USB驅動程式是通過DriverStudio3.2生成的。
USB硬體設備是公司開發的。
在正常情況下,上下位機通信都很正常。但如果此時PC上有U盤進行插拔操作,偶爾會出現通信失敗的情況。
當通信失敗時上位機的情況表現為:
1.ReadFile讀失敗,但不會導致函式被阻塞。
2.WriteFile寫失敗,但會導致函式阻塞,直到拔掉USB設備此函式才會回傳。
出現這種例外不知道是USB驅動沒有寫好,還是下位機設備抗干擾性不強。
望高手指點。
謝謝,專案急!!!!!!!
uj5u.com熱心網友回復:
網上有人懷疑是設備號寫錯了,但我的程式是通過工具自己生成的。所以。。。。。。uj5u.com熱心網友回復:
我把驅動代碼貼上來:總共六個檔案,是WDM開發的。工具是DriverStudio3.2//-------------------------------------------------------------------------
Communication_dataDriver.h
//-------------------------------------------------------------------------
// Communication_dataDriver.h
//
// Generated by DriverWizard 3.2.0 (Build 2485)
// Requires DDK and DriverWorks
// File created on 11/2/2011
//
// This include file contains the definition of a subclass of KDriver.
// WDM drivers declare a subclass of KDriver and override member
// function DriverEntry and AddDevice.
//
#ifndef __COMMUNICATION_DATADRIVER_H__
#define __COMMUNICATION_DATADRIVER_H__
class Communication_dataDriver : public KDriver
{
SAFE_DESTRUCTORS
public:
// Member functions
virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath);
virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo);
virtual VOID Unload(VOID);
protected:
// Member data
int m_Unit;
};
#endif // __COMMUNICATION_DATADRIVER_H__
//-------------------------------------------------------------------
Communication_dataDriver.cpp
//-------------------------------------------------------------------
// Communication_dataDriver.cpp
//
// Generated by DriverWizard 3.2.0 (Build 2485)
// Requires DDK and DriverWorks
// File created on 11/2/2011
//
// This source file contains the implementation of a subclass of KDriver.
// WDM drivers implement a subclass of KDriver and override member
// function DriverEntry and AddDevice.
//
#define VDW_MAIN
#include <vdw.h>
#include <kusb.h>
#include <kusbbusintf.h>
#include "function.h"
#include "Communication_dataDriver.h"
#include "Communication_dataDevice.h"
#pragma hdrstop("Communication_data.pch")
// Memory allocation pool tag
// Override this value using the global function SetPoolTag().
POOLTAG DefaultPoolTag('mmoC');
// Global driver trace object
// TODO: Use KDebugOnlyTrace if you want trace messages
// to appear only in checked builds. Use KTrace if
// you want trace messages to always appear. Call
// method SetOutputLevel to set the output threshold.
KDebugOnlyTrace T("Communication_data");
///////////////////////////////////////////////////////////////////////////////////////////////////
// Begin INIT section
#pragma code_seg("INIT")
DECLARE_DRIVER_CLASS(Communication_dataDriver, NULL)
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDriver::DriverEntry
// This routine is called when the driver is loaded. Drivers often
// read the registry for configurable parameters.
//
// Arguments:
// IN RegistryPath
// pointer to a unicode string representing the path to
// driver-specific key in the registry. Look for:
// HKLM\SYSTEM\CurrentControlSet\Services\Communication_data
//
// Return Value:
// NTSTATUS code
//
NTSTATUS Communication_dataDriver::DriverEntry(PUNICODE_STRING RegistryPath)
{
T.Trace(TraceInfo, __FUNCTION__"++. Compiled at " __TIME__ " on " __DATE__ "\n");
#ifdef DBG
//DbgBreakPoint();
#endif
NTSTATUS status = STATUS_SUCCESS;
m_Unit = 0;
// This macro suppresses compiler warning for unreferenced variable.
// If you reference this parameter, simply remove the macro.
UNREFERENCED_PARAMETER(RegistryPath);
T.Trace(TraceInfo, __FUNCTION__"--. STATUS %x\n", status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma code_seg() // end INIT code
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDriver::AddDevice
// This routine is called when the system detects a device for which this
// driver is responsible. This function creates the Functional Device
// Object, or FDO. The FDO enables this driver to handle requests for
// the physical device.
//
// Arguments:
// IN Pdo
// Physical Device Object. This is a pointer to a system device
// object that represents the physical device.
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDriver::AddDevice(PDEVICE_OBJECT Pdo)
{
T.Trace(TraceInfo, __FUNCTION__"++.\n");
NTSTATUS status = STATUS_SUCCESS;
// Create Communication_dataDevice using a form of "placement" new
// that is a member operator of KDevice. This will use storage
// in the system device object extension to store the class instance.
Communication_dataDevice* pDevice = new (
NULL, // no name
FILE_DEVICE_UNKNOWN,
NULL, // no name
0,
DO_DIRECT_IO
| DO_EXCLUSIVE
| DO_POWER_PAGABLE
)
Communication_dataDevice(Pdo, m_Unit);
if (pDevice == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
status = pDevice->ConstructorStatus();
if (!NT_SUCCESS(status))
{
delete pDevice;
}
else
{
m_Unit++;
pDevice->ReportNewDevicePowerState(PowerDeviceD0);
}
}
T.Trace(TraceInfo, __FUNCTION__"--. STATUS %x\n", status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDriver::Unload
// This routine is called when the driver is unloaded. Delete any
// device objects created in DriverEntry by calling base class method
// Unload(). Cleanup any allocations made for registry values in
// DriverEntry.
//
// Arguments:
// none
//
// Return Value:
// none
//
VOID Communication_dataDriver::Unload(VOID)
{
T.Trace(TraceInfo, __FUNCTION__"++.\n");
// If you don't need to perform any functions
// except to call the base class KDriver::Unload(),
// then this entire routine may be safely deleted.
// Call base class to delete all devices.
KDriver::Unload();
T.Trace(TraceInfo, __FUNCTION__"--.\n");
}
//---------------------------------------------------------------------
function.h
//---------------------------------------------------------------------
// function.h
//
// Generated by DriverWizard 3.2.0 (Build 2485)
// Requires DDK and DriverWorks
// File created on 11/2/2011
//
// This include file specifies the set of request handlers that the
// driver implements. This controls which driver functions are enabled.
//
#ifndef __FUNCTION_H__
#define __FUNCTION_H__
#define DRIVER_FUNCTION_CREATE
#define DRIVER_FUNCTION_CLOSE
#define DRIVER_FUNCTION_READ
#define DRIVER_FUNCTION_WRITE
#define DRIVER_FUNCTION_DEVICE_CONTROL
#define DRIVER_FUNCTION_CLEANUP
#define DRIVER_FUNCTION_ADD_DEVICE
#define DRIVER_FUNCTION_PNP
#define DRIVER_FUNCTION_POWER
#define DRIVER_FUNCTION_SYSTEM_CONTROL
#define DRIVER_FUNCTION_UNLOAD
#endif // __FUNCTION_H__
//-------------------------------------------------------------
intrface.h
//-------------------------------------------------------------
// intrface.h
//
// Generated by C DriverWizard 3.2.0 (Build 2485)
// Requires DDK Only
// File created on 11/2/2011
//
// Define an Interface Guid for Communication_data device class.
// This GUID is used to register (IoRegisterDeviceInterface)
// an instance of an interface so that user application
// can control the Communication_data device.
//
// {8D96C3F0-627C-490D-BAA2-3F7D1D789F3D}
DEFINE_GUID(GUID_DEVINTERFACE_COMMUNICATION_DATA,
0x8D96C3F0, 0x627C, 0x490D, 0xBA, 0xA2, 0x3F, 0x7D, 0x1D, 0x78, 0x9F, 0x3D);
// Define a Setup Class GUID for Communication_data Class. This is same
// as the COMMUNICATION_DATA CLASS guid in the INF files.
//
// {C14F5235-5790-436F-B6BA-AEF87EE15AF2}
DEFINE_GUID(GUID_DEVCLASS_COMMUNICATION_DATA,
0xC14F5235, 0x5790, 0x436F, 0xB6, 0xBA, 0xAE, 0xF8, 0x7E, 0xE1, 0x5A, 0xF2);
// GUID definition are required to be outside of header inclusion pragma to avoid
// error during precompiled headers.
//
#ifndef __INTRFACE_H__
#define __INTRFACE_H__
#define FILE_DEVICE_COMMUNICATION_DATA 0x8000
// Define Interface reference/dereference routines for
// Interfaces exported by IRP_MN_QUERY_INTERFACE
#define COMMUNICATION_DATA_IOCTL(index) \
CTL_CODE(FILE_DEVICE_COMMUNICATION_DATA, index, METHOD_BUFFERED, FILE_READ_DATA)
#endif // __INTRFACE_H__
uj5u.com熱心網友回復:
// Communication_dataDevice.h//
// Generated by DriverWizard 3.2.0 (Build 2485)
// Requires DDK and DriverWorks
// File created on 11/2/2011
//
// This include file contains the definition of a subclass of KPnpDevice.
// WDM drivers declare a subclass of KPnpDevice and override member
// functions to handle requests (IRPs) from the system.
//
#ifndef __COMMUNICATION_DATADEVICE_H__
#define __COMMUNICATION_DATADEVICE_H__
class Communication_dataDevice : public KPnpDevice
{
public:
SAFE_DESTRUCTORS;
Communication_dataDevice(PDEVICE_OBJECT Pdo, ULONG Unit);
~Communication_dataDevice();
VOID Invalidate(void);
// Member functions
DEVMEMBER_DISPATCHERS
virtual NTSTATUS OnStartDevice(KIrp I);
virtual NTSTATUS OnStopDevice(KIrp I);
virtual NTSTATUS OnRemoveDevice(KIrp I);
virtual NTSTATUS OnQueryCapabilities(KIrp I);
MEMBER_COMPLETEIRP(Communication_dataDevice, OnQueryCapabilitiesComplete)
virtual NTSTATUS OnDevicePowerUp(KIrp I);
virtual NTSTATUS OnDeviceSleep(KIrp I);
virtual NTSTATUS DefaultPnp(KIrp I);
virtual NTSTATUS DefaultPower(KIrp I);
typedef struct _USB_COMPLETION_INFO
{
PURB m_pUrb;
Communication_dataDevice* m_pClass;
} USB_COMPLETION_INFO, *PUSB_COMPLETION_INFO;
MEMBER_COMPLETEIRPWITHCONTEXT(USB_COMPLETION_INFO, IoComplete)
void TestBusInterface();
protected:
// Member data
KUsbLowerDevice m_Lower;
KUsbInterface m_Interface;
KUsbPipe Pipe2; // Pipe for USB endpoint address 82, type BULK
KUsbPipe Pipe3; // Pipe for USB endpoint address 3, type BULK
#if (_WDM_ && (WDM_MAJORVERSION > 1 || ((WDM_MAJORVERSION == 1) && (WDM_MINORVERSION >= 0x20))))
KUsbBusInterface m_BusIntf; // Direct client access to USB bus on Windows XP and above
BOOLEAN m_fBusIntfAvailable;
#endif
#ifdef __COMMENT_ONLY
// The following member functions are actually defined by
// a DEVMEMBER_XXX or MEMBER_XXX macro (such as DEVMEMBER_DISPATCHERS).
// The macro __COMMENT_ONLY never gets defined. These comment-only
// definitions simply allow easy navigation to the functions within
// the Visual Studio IDE using the class browser.
virtual NTSTATUS Create(KIrp I); // COMMENT_ONLY
virtual NTSTATUS Close(KIrp I); // COMMENT_ONLY
virtual NTSTATUS Read(KIrp I); // COMMENT_ONLY
virtual NTSTATUS Write(KIrp I); // COMMENT_ONLY
virtual NTSTATUS DeviceControl(KIrp I); // COMMENT_ONLY
virtual NTSTATUS CleanUp(KIrp I); // COMMENT_ONLY
virtual NTSTATUS SystemControl(KIrp I); // COMMENT_ONLY
#endif // __COMMENT_ONLY
};
#endif // __COMMUNICATION_DATADEVICE_H__
uj5u.com熱心網友回復:
我給你頂頂,接著貼uj5u.com熱心網友回復:
//---------------------------------------------------Communication_dataDevice.cpp
//--------------------------------------------------
// Communication_dataDevice.cpp
//
// Generated by DriverWizard 3.2.0 (Build 2485)
// Requires DDK and DriverWorks
// File created on 11/2/2011
//
// This source file contains the implementation of a subclass of KDevice.
// WDM drivers implement a subclass of KPnpDevice and override member
// functions to handle requests (IRPs) from the system.
//
#include <vdw.h>
#include <kusb.h>
#include <kusbbusintf.h>
#include "Communication_dataDriver.h"
#include "Communication_dataDevice.h"
#include "..\\intrface.h"
#pragma hdrstop("Communication_data.pch")
// Global driver trace object
// TODO: Use KDebugOnlyTrace if you want trace messages
// to appear only in checked builds. Use KTrace if
// you want trace messages to always appear. Call
// method SetOutputLevel to set the output threshold.
extern KDebugOnlyTrace T;
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::Communication_dataDevice
// This is the constructor for the class representing 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.
// The object being constructed contains a data member (m_Lower) 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 class driver.
//
// Arguments:
// IN Pdo
// Physical Device Object. This is a pointer to a system
// device object that represents the physical device.
//
// IN Unit
// Unit number to append to the device's base device name
// to distinguish multiple units of this device type.
//
// Return Value:
// none
//
Communication_dataDevice::Communication_dataDevice(PDEVICE_OBJECT Pdo, ULONG Unit) :
KPnpDevice(Pdo, &GUID_DEVINTERFACE_COMMUNICATION_DATA)
{
if (!NT_SUCCESS(m_ConstructorStatus))
{
T.Trace(TraceError, __FUNCTION__": Failed to create device Communication_dataDevice"
" unit number %d status %x\n", Unit, m_ConstructorStatus);
ASSERT(FALSE);
return;
}
// Initialize the lower device
m_Lower.Initialize(this, Pdo);
// Initialize the interface object. The wizard generates code
// to support a single interface. You may create and add additional
// interfaces. By default, the wizard uses InterfaceNumber 0 (the
// first interface descriptor), ConfigurationValue 1 (the first
// configuration descriptor), and initial interface alternate
// setting of 0. If your device has multiple interfaces or alternate
// settings for an interface, you can add additional KUsbInterface
// objects or adjust the parameters passed to this function.
m_Interface.Initialize(
m_Lower, //KUsbLowerDevice
0, //InterfaceNumber
1, //ConfigurationValue
0 //Initial Interface Alternate Setting
);
// Initialize each Pipe object
Pipe2.Initialize(m_Lower, 0x82, 512);
Pipe3.Initialize(m_Lower, 0x3, 512);
#if (_WDM_ && (WDM_MAJORVERSION > 1 ||((WDM_MAJORVERSION == 1) && (WDM_MINORVERSION >= 0x20))))
// Initialize USB direct client access interface
if (STATUS_SUCCESS == m_BusIntf.Initialize(m_Lower.TopOfStack()))
m_fBusIntfAvailable = TRUE;
else
m_fBusIntfAvailable = FALSE;
#endif
// Inform the base class of the lower edge device object
SetLowerDevice(&m_Lower);
// Initialize the PnP Policy settings to the "standard" policy
SetPnpPolicy();
// TODO: Customize the PnP Policy for this device by setting
// flags in m_Policies.
// Initialize the Power Policy settings to the "standard" policy
SetPowerPolicy();
// TODO: Customize the Power Policy for this device by setting
// flags in m_PowerPolicies.
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::~Communication_dataDevice
// This is the destructor for the class.
//
// Arguments:
// none
//
// Return Value:
// none
//
Communication_dataDevice::~Communication_dataDevice()
{
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::DefaultPnp
// Default handler for IRP_MJ_PNP.
// This routine just passes the IRP through to the lower device. 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.
//
// Arguments:
// IN I
// the plug and play IRP
//
// Return Value:
// NTSTATUS
// Result returned from lower device
//
NTSTATUS Communication_dataDevice::DefaultPnp(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
T << I;
I.ForceReuseOfCurrentStackLocationInCalldown();
NTSTATUS status = m_Lower.PnpCall(this, I);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::DefaultPower
// Default handler for IRP_MJ_POWER.
// This routine just passes the IRP through to the lower device. IRPs
// that correspond to any virtual members of KpnpDevice that handle
// minor functions of IRP_MJ_POWER and that are not overridden get
// passed to this routine.
//
// Arguments:
// IN I
// the power IRP
//
// Return Value:
// NTSTATUS
// Result returned from lower device
//
NTSTATUS Communication_dataDevice::DefaultPower(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
T << I;
I.IndicatePowerIrpProcessed();
I.CopyParametersDown();
NTSTATUS status = m_Lower.PnpPowerCall(this, I);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::SystemControl
// Default 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.
//
// Arguments:
// IN I
// the system control (WMI) IRP
//
// Return Value:
// NTSTATUS
// Result returned from lower device
//
NTSTATUS Communication_dataDevice::SystemControl(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
T << I;
NTSTATUS status = STATUS_SUCCESS;
I.ForceReuseOfCurrentStackLocationInCalldown();
status = m_Lower.PnpCall(this, I);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::OnStartDevice
// Handler for IRP_MJ_PNP subfcn IRP_MN_START_DEVICE.
// Initialize the hardware device. Typically, the driver initializes
// physical resources here. Call I.AllocatedResources() for a list
// of the raw resources that the system has assigned to the device,
// or I.TranslatedResources() for the translated resource list.
//
// Arguments:
// IN I
// the start device IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnStartDevice(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
I.Information() = 0;
status = STATUS_UNSUCCESSFUL;
AC_STATUS acStatus = AC_SUCCESS;
// By default, the wizard passes a ConfigurationValue of 1 to
// ActivateConfiguration(). This corresponds to the first configuration
// that the device reports in its configuration descriptor. If the device
// supports multiple configurations, pass the appropriate
// ConfigurationValue of the configuration to activate here.
acStatus = m_Lower.ActivateConfiguration(
1 // ConfigurationValue 1 (the first configuration)
);
switch (acStatus)
{
case AC_SUCCESS:
T << "USB ActivateConfiguration OK\n";
status = STATUS_SUCCESS;
// TODO: Use the USB direct client access
TestBusInterface();
break;
case AC_COULD_NOT_LOCATE_INTERFACE:
T << "ActivateConfiguration Error: Could not locate interface\n";
break;
case AC_COULD_NOT_PRECONFIGURE_INTERFACE:
T << "ActivateConfiguration Error: Could not get configuration descriptor\n";
break;
case AC_CONFIGURATION_REQUEST_FAILED:
T << "ActivateConfiguration Error: H/W did not accept configuration URB\n";
break;
case AC_FAILED_TO_INITIALIZE_INTERFACE_OBJECT:
T << "ActivateConfiguration Error: Failed to initialize interface object\n";
break;
case AC_FAILED_TO_GET_DESCRIPTOR:
T << "ActivateConfiguration Error: Failed to get device descriptor\n";
break;
case AC_FAILED_TO_OPEN_PIPE_OBJECT:
// NOTE: this may not be an error. 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 endpoint,
// then it's likely not a problem.
status = STATUS_SUCCESS;
T << "ActivateConfiguration Warning: Failed to open pipe object\n";
break;
default:
T << "ActivateConfiguration Error: Unexpected error activating USB configuration\n";
break;
}
// TODO: Add USB device-specific code to start the hardware.
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
uj5u.com熱心網友回復:
///////////////////////////////////////////////////////////////////////////////////////////////////// Communication_dataDevice::OnStopDevice
// Handler for IRP_MJ_PNP subfcn IRP_MN_STOP_DEVICE.
// The system calls this when the device is stopped. Release any
// hardware resources in this routine.
//
// Arguments:
// IN I
// the stop device IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnStopDevice(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Add device-specific code to stop your hardware device.
// The base class will handle completion of the IRP
// Release the system resources
Invalidate();
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, STATUS_SUCCESS);
// Can't fail this IRP
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::OnRemoveDevice
// Handler for IRP_MJ_PNP subfcn IRP_MN_REMOVE_DEVICE.
// The system calls this when the device is removed.
// Our PnP policy will take care of
// (1) giving the IRP to the lower device
// (2) detaching the PDO
// (3) deleting the device object
//
// Arguments:
// IN I
// the remove device IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnRemoveDevice(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Add device-specific code to remove your hardware device.
// The base class will handle completion of the IRP
// Release the system resources
Invalidate();
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, STATUS_SUCCESS);
// Can't fail this IRP
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::OnQueryCapabilities
// Handler for IRP_MJ_PNP subfcn IRP_MN_QUERY_CAPABILITIES.
// The system calls this to query the device capabilities.
// The Bus driver fills in the device capabilities structure.
// This method is usually only overridden to alter the
// device capabilities reported by the bus driver.
//
// Arguments:
// IN I
// the query capabilities IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnQueryCapabilities(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
I.CopyParametersDown();
I.SetCompletionRoutine(LinkTo(OnQueryCapabilitiesComplete), this, TRUE, TRUE, TRUE);
status = m_Lower.PnpCall(this, I);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::OnQueryCapabilitiesComplete
// Completion routine for IRP_MJ_PNP subfcn IRP_MN_QUERY_CAPABILITIES.
// The system calls OnQueryCapabilities to query the device capabilities.
// The Bus driver fills in the device capabilities structure.
// This method is called when the IRP is completed to alter the
// device capabilities reported by the bus driver.
//
// Arguments:
// IN I
// the query capabilities IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnQueryCapabilitiesComplete(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++.");
NTSTATUS status = I.Status();
if (I->PendingReturned)
I.MarkPending();
if (NT_SUCCESS(status))
{
// TODO: Adjust device capabilities structure as required.
I.DeviceCapabilities()->SurpriseRemovalOK = TRUE;
}
T.Trace(TraceInfo, __FUNCTION__"--.");
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::TestBusInterface
// This routine uses the USB direct client interface to
// query information.
//
// Arguments:
// none
//
// Return Value:
// none
//
void Communication_dataDevice::TestBusInterface()
{
#if (_WDM_ && (WDM_MAJORVERSION > 1 ||((WDM_MAJORVERSION == 1) && (WDM_MINORVERSION >= 0x20))))
if (m_fBusIntfAvailable)
{
T.Trace(TraceInfo, "USB Bus Interface Version: %u\n", m_BusIntf.Version());
T.Trace(TraceInfo, "High Speed Device: %S\n", (m_BusIntf.IsDeviceHighSpeed()?"TRUE":"FALSE"));
USBD_VERSION_INFORMATION UsbVerInfo;
RtlZeroMemory(&UsbVerInfo, sizeof(USBD_VERSION_INFORMATION));
ULONG HcdCapabilities = 0;
m_BusIntf.GetUSBDIVersion(&UsbVerInfo, &HcdCapabilities);
T.Trace(TraceInfo, "USBDI_Version: %u\n", UsbVerInfo.USBDI_Version);
T.Trace(TraceInfo, "Supported_USB_Version: %u\n", UsbVerInfo.Supported_USB_Version);
ULONG TotalBW, ConsumedBW;
NTSTATUS Status = m_BusIntf.GetBandwidth(&TotalBW,&ConsumedBW);
if (STATUS_SUCCESS == Status)
{
T.Trace(TraceInfo, "Total Bandwidth: %u\n", TotalBW);
T.Trace(TraceInfo, "Consumed Bandwidth: %u\n", ConsumedBW);
}
PWSTR HcName = NULL;
Status = m_BusIntf.GetControllerName(HcName);
if (STATUS_SUCCESS == Status && HcName)
{
T.Trace(TraceInfo, "HC Name: %s\n", HcName);
delete HcName;
}
ULONG CurrentFrame;
m_BusIntf.QueryBusTime(&CurrentFrame);
T.Trace(TraceInfo, "Current Frame: %u\n", CurrentFrame);
}
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::OnDevicePowerUp
// Handler for IRP_MJ_POWER subfcn IRP_MN_SET_POWER
// for a request to go to power on state from low power state
// This function was called by the framework from the completion
// routine of the IRP_MJ_POWER dispatch handler in KPnpDevice.
// The bus driver has completed the IRP and this driver can now
// access the hardware device.
// This routine runs at DISPATCH_LEVEL.
//
// Arguments:
// IN I
// the power IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnDevicePowerUp(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Add device-specific code to:
// Restore any context to the hardware device that
// was saved during the handling of a power down request.
// See the OnDeviceSleep function.
// Do NOT complete this IRP.
// The base class will handle completion of the IRP
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::OnDeviceSleep
// Handler for IRP_MJ_POWER subfcn IRP_MN_SET_POWER
// for a request to go to a low power state from a high power state
// This function was called by the framework from the IRP_MJ_POWER
// dispatch handler in KPnpDevice prior to forwarding to the PDO.
// The hardware has yet to be powered down and this driver can now
// access the hardware device.
// This routine runs at PASSIVE_LEVEL.
//
// Arguments:
// IN I
// the power IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::OnDeviceSleep(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Add device-specific code to:
// Save any context to the hardware device that will be required
// during a power up request. See the OnDevicePowerUp function.
// Do NOT complete this IRP. The base class handles forwarding
// this IRP to the PDO.
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::Create
// Dispatch routine for IRP_MJ_CREATE requests.
//
// Arguments:
// IN I
// the create IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::Create(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
// TODO: For any IRP, to display the contents of the IRP
// in a formatted way, use the KTrace << operator:
// T << I;
NTSTATUS status = STATUS_SUCCESS;
// For devices that expose an interface instead of symbolic
// link, DO_EXCLUSIVE flag is not used by the I/O manager.
// So, exclusivity must be enforced here.
if (m_OpenCounter.Test() > 0)
{
status = STATUS_SHARING_VIOLATION;
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
// TODO: At this point, perform custom processing for IRP_MJ_CREATE
// Generally a create IRP is targeted at our FDO, so its not needed
// to pass it down to the PDO.
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
uj5u.com熱心網友回復:
///////////////////////////////////////////////////////////////////////////////////////////////////// Communication_dataDevice::Close
// Dispatch routine for IRP_MJ_CLOSE requests.
//
// Arguments:
// IN I
// the close IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::Close(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: At this point, perform custom processing for IRP_MJ_CLOSE
// Generally a close IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO.
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::Read
// Dispatch routine for IRP_MJ_READ requests.
//
// Arguments:
// IN I
// the read IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::Read(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Validate the parameters of the IRP. Replace "FALSE"
// in the following line with error checking code that
// evaulates to TRUE if the request is not valid.
if (FALSE)
{
status = STATUS_INVALID_PARAMETER;
I.Information() = 0;
I.PnpComplete(status);
T.Trace(TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
// Always ok to read 0 elements
if (I.ReadSize() == 0)
{
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
KMemory Mem(I.Mdl()); // Declare a memory object
// Get a pointer to the caller's buffer. Note that this
// routine is safe on all platforms.
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG readSize = I.ReadSize();
ULONG bytesRead = 0;
PURB pUrb = Pipe2.BuildBulkTransfer(
pBuffer,
readSize,
TRUE,
NULL,
TRUE,
NULL);
if (pUrb == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
status = Pipe2.SubmitUrb(pUrb,NULL,NULL,NULL);//100MS
bytesRead = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;//pUrb->UrbInterruptTransfer.TransferBufferLength;
delete pUrb;
}
I.Information() = bytesRead;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::Write
// Dispatch routine for IRP_MJ_WRITE requests.
//
// Arguments:
// IN I
// the write IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::Write(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: Validate the parameters of the IRP. Replace "FALSE"
// in the following line with error checking code that
// evaulates to TRUE if the request is not valid.
if (FALSE)
{
status = STATUS_INVALID_PARAMETER;
I.Information() = 0;
I.PnpComplete(status);
T.Trace(TraceWarning, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
// Always ok to write 0 elements
if (I.WriteSize() == 0)
{
I.Information() = 0;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
KMemory Mem(I.Mdl()); // Declare a memory object
// Get a pointer to the caller's buffer. Note that this
// routine is safe on all platforms.
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG writeSize = I.WriteSize();
ULONG bytesSent = 0;
PURB pUrb = Pipe3.BuildBulkTransfer(
pBuffer,
writeSize,
FALSE,
NULL,
TRUE,
NULL);
if (pUrb == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
status = Pipe3.SubmitUrb(pUrb,NULL,NULL,NULL);
bytesSent = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;//pUrb->UrbInterruptTransfer.TransferBufferLength;
delete pUrb;
}
I.Information() = bytesSent;
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::DeviceControl
// Dispatch routine for IRP_MJ_DEVICE_CONTROL requests.
//
// Arguments:
// IN I
// the ioctl IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::DeviceControl(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
switch (I.IoctlCode())
{
case 0:
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
// If the IRP's IOCTL handler deferred processing using some driver
// specific scheme, the status variable is set to STATUS_PENDING.
// In this case we simply return that status, and the IRP will be
// completed later. Otherwise, complete the IRP using the status
// returned by the IOCTL handler.
if (status != STATUS_PENDING)
{
I.PnpComplete(this, status);
}
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::CleanUp
// Dispatch routine for IRP_MJ_CLEANUP requests.
//
// Arguments:
// IN I
// the cleanup IRP
//
// Return Value:
// NTSTATUS
//
NTSTATUS Communication_dataDevice::CleanUp(KIrp I)
{
T.Trace(TraceInfo, __FUNCTION__"++. IRP %p\n", I);
NTSTATUS status = STATUS_SUCCESS;
// TODO: At this point, perform custom processing for IRP_MJ_CLEANUP
I.PnpComplete(this, status);
T.Trace(TraceInfo, __FUNCTION__"--. IRP %p, STATUS %x\n", I, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Communication_dataDevice::Invalidate
// This method performs resource cleanup.
// This function is called from OnStopDevice, OnRemoveDevice and
// OnStartDevice (in error conditions). It calls the Invalidate
// member funcitons for each resource to free the underlying system
// resource if allocated. It is safe to call Invalidate more than
// once for a resource, or for an uninitialized resource.
//
// Arguments:
// none
//
// Return Value:
// none
//
VOID Communication_dataDevice::Invalidate()
{
NTSTATUS status = STATUS_SUCCESS;
status = m_Lower.DeActivateConfiguration();
if (!NT_SUCCESS(status))
{
T.Trace(TraceWarning, __FUNCTION__" DeActivateConfiguration failed, STATUS %x\n", status);
}
m_Lower.ReleaseResources();
}
--------------結束----------
uj5u.com熱心網友回復:
木有回帖的,幫你頂一下uj5u.com熱心網友回復:
把你的USB設備和U盤一個插在電腦后面,一個插在前面,如果還有影響, 是你驅動問題的可能性大. 如果都插在相鄰介面才有影響, 是硬體問題.看你的驅動,是用的BULK傳輸模式. 高速模式還是低速模式?是否占滿了USB帶寬? 這些都有關系.
另外也要試試如果同時插拔U口的攝像頭等USB設備,是否有影響.
uj5u.com熱心網友回復:
另外把殺毒查木馬之類的監控軟體關了.uj5u.com熱心網友回復:
我們用的是用的BULK傳輸模式,全速。前面后面都插過都有這樣的問題。上位機用執行緒不間斷呼叫ReadFile函式,如果設備沒有資料上來次函式不會回傳。不知道這種情況是不是占滿帶寬?
殺毒查木馬之類的監控軟體 關掉還沒有試過,明天回公司去試試。
uj5u.com熱心網友回復:
試過了,殺毒、防火墻和監控軟體都關閉了,還是會出現插拔U盤,USB設備通信通信失敗的問題uj5u.com熱心網友回復:
那就是USB帶寬影響的. USB全速帶寬你是不能全部占用的. 每秒500-600K位元組就很不錯了. U盤插入時候, 系統要去讀取USB的Device資訊, 讀取U盤的檔案分配表等, 如果支持自動運行, 還會讀取U盤程式運行. 對U盤檔案的操作都是用BULK傳輸。或者你降低帶寬的占用,這需要設備開發人員配合, 或者你允許失敗,軟體里面重試幾次。 寫失敗停止程式就停止回應,是你跟下位機配合不好,驅動發的IRP沒有回傳。
uj5u.com熱心網友回復:
謝謝你給的建議。我先去查查看uj5u.com熱心網友回復:
上位機和USB設備建立(邏輯上的)通信后,上位機會用執行緒讀USB設備資料,但資料不是每次都能讀到,在讀不到資料的時候,USB設備也沒有傳空資料給上位機,導致USB協議層會不間斷的發送N ACK狀態,通過USB總線監控工具看了,每產生一個N ACK時間大約7-12ms之間,是不是因為N ACK發送太頻繁導致USB總線帶寬被搶占,此時插拔U盤就會出現問題?下位機開發人員不在,今天沒有辦法測驗了。
我看了U盤也是BULK傳輸模式,它們發送是out -> IN 的回圈發送,每此IN都有資料被讀取。估計固定時間會向USB控制器放入空資料。所以,有個問題,一般多長時間向USB控制器放入空資料比較優呢?
uj5u.com熱心網友回復:
重點看PC跟設備傳輸資料的時候, 帶寬占用多少. 其它時間進行的協議性的通訊不用理會.uj5u.com熱心網友回復:
如果不用管USB協議的傳輸方式,那么我們的總線帶寬占有率并不高,1秒中發送一個12位元組的報文uj5u.com熱心網友回復:
不懂 windows 的驅動,但是 Linux 下的驅動都是不會引起 read、write 阻塞的都是驅動中使用緩沖區保存資料,應用軟體呼叫時檢查驅動緩沖資料或者設定緩沖資料、打開中斷函式的
uj5u.com熱心網友回復:
每秒12位元組, 控制傳輸就夠用了.USB協議為控制傳輸留了綠色通道.uj5u.com熱心網友回復:
沒做過驅動,學習。uj5u.com熱心網友回復:
我也遇到了此種情況,但我用的是高速模式啊,此問題最后確認問題原因了沒?uj5u.com熱心網友回復:
這個driver studio生成的驅動程式難道不用修改的嗎?uj5u.com熱心網友回復:
用Libusb吧
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/154353.html
標籤:網絡及通訊開發
下一篇:c語言
