📄 usblptpd11.c
字号:
/* Win NT/2000/XP Driver for DeVaSys USBLPT-PD11(D) USB Development Board */
/* Copyright 2001 Craig Peacock, Craig.Peacock@beyondlogic.org */
/* 27th October 2001 */
#include <ntddk.h>
#include <ddk/parallel.h>
#include "USBLPT_IOCTL.h"
#define NT_DEVICE_NAME L"\\Device\\USBLPTPD11_"
#define WIN32_DEVICE_NAME L"\\DosDevices\\USBLPTPD11_"
#define PAR_PORT_NAME L"\\Device\\ParallelPort"
#define I2C_CTL_READ 0x01
#define I2C_CTL_WRITE 0xFE
#define I2C_TRUE 1
#define I2C_FALSE 0
#define XD0 0x01
#define XD1 0x02
#define XD6 0x40
#define XD7 0x80
#define XERROR 0x08
#define XBUSY 0x80
#define XACK 0x40
#define XPAPEREND 0x20
#define XSELECT 0x10
#define outportb(ADDR,BYTE) outp(ADDR,BYTE)
#define inportb(ADDR) inp(ADDR)
#define SetSCL(PortAddress) outportb(PortAddress, inportb(PortAddress) & ~XD0)
#define ClearSCL(PortAddress) outportb(PortAddress, inportb(PortAddress) | XD0)
#define ClearStatus(PortAddress) outportb(PortAddress, inportb(PortAddress) & ~XD6)
#define SetStatus(PortAddress) outportb(PortAddress, inportb(PortAddress) | XD6)
#define SetSDA(PortAddress) outportb(PortAddress, inportb(PortAddress) & ~XD7)
#define ClearSDA(PortAddres) outportb(PortAddress, inportb(PortAddress) | XD7)
#define GetSCL(PortAddress) ((~inportb(PortAddress+1)) & XBUSY) >> 7
#define GetSDA(PortAddress) ((inportb(PortAddress+1) & XPAPEREND) >> 5)
#define GetSuspend(PortAddress) ((inportb(PortAddress+1) & XSELECT) >> 4)
#define GetInt(PortAddress) ((inportb(PortAddress+1) & XACK) >> 6)
#define Stop(PortAddress) {ClearSCL(PortAddress);ClearSDA(PortAddress);SetSCL(PortAddress);SetSDA(PortAddress);}
#define SetAck(PortAddress) {ClearSCL(PortAddress);ClearSDA(PortAddress);SetSCL(PortAddress);ClearSCL(PortAddress);SetSDA(PortAddress);}
#define SetNak(PortAddress) {ClearSCL(PortAddress);SetSDA(PortAddress);SetSCL(PortAddress);ClearSCL(PortAddress);}
#define Idle(PortAddress) {SetSCL(PortAddress);SetSDA(PortAddress);Stop(PortAddress);}
NTSTATUS USBLPTPD11DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS USBLPTPD11CreateDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
NTSTATUS USBLPTPD11CloseDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
NTSTATUS USBLPTPD11CreateDevice(IN PDRIVER_OBJECT pDriverObject, IN ULONG DeviceNumber);
BOOLEAN USBLPTPD11Isr(IN PKINTERRUPT Interrupt, IN OUT PVOID Context);
VOID USBLPTPD11Unload(IN PDRIVER_OBJECT DriverObject);
VOID USBLPTPD11StartIo(PDEVICE_OBJECT DeviceObject, PIRP pIrp);
VOID USBLPTPD11DpcRoutine(IN PKDPC Dpc, PDEVICE_OBJECT deviceObject, IN PIRP Irp, IN PVOID Context);
VOID USBLPTPD11TimeOutDPC(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
NTSTATUS DetectDevice(LONG wLptBaseAddr);
NTSTATUS I2C_Read(unsigned char * pbyData, unsigned char byDevId, unsigned char byCount, unsigned long PortAddress);
NTSTATUS I2C_Write(unsigned char byDevId, unsigned char * pbyData, unsigned char byCount, unsigned long PortAddress);
NTSTATUS I2C_Init(unsigned long PortAddress);
unsigned char Start(unsigned long PortAddress);
unsigned char ByteOut(unsigned char byData, unsigned long PortAddress);
void ByteIn(unsigned char * pbyData, unsigned long PortAddress);
typedef struct _LOCAL_DEVICE_INFO {
PDEVICE_OBJECT deviceObject;
PDRIVER_OBJECT DriverObject;
ULONG DeviceNumber;
PKINTERRUPT InterruptObject;
ULONG PortAddress;
INTERFACE_TYPE InterfaceType;
ULONG BusNumber;
KIRQL Irql;
ULONG Level;
ULONG Vector;
KINTERRUPT_MODE InterruptMode;
KAFFINITY Affinity;
KTIMER IntTimer;
KDPC IntTimerDPC;
LARGE_INTEGER IntTimer_uS;
PFILE_OBJECT ParPortFileObject;
PDEVICE_OBJECT ParPortDeviceObject;
} LOCAL_DEVICE_INFO, *PLOCAL_DEVICE_INFO;
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
ULONG DeviceNumber;
ULONG NumOfParallelPorts;
NTSTATUS status;
DriverObject->MajorFunction[IRP_MJ_CREATE] = USBLPTPD11CreateDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBLPTPD11CloseDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBLPTPD11DeviceControl;
DriverObject->DriverUnload = USBLPTPD11Unload;
DriverObject->DriverStartIo = USBLPTPD11StartIo;
NumOfParallelPorts = IoGetConfigurationInformation()->ParallelCount;
KdPrint( ("USBLPTPD11: USBLPT-PD11 DriverEntry Loading. System has %d Parallel Ports",NumOfParallelPorts) );
for( DeviceNumber=0; DeviceNumber<NumOfParallelPorts; DeviceNumber++)
{
status = USBLPTPD11CreateDevice( DriverObject, DeviceNumber);
if( !NT_SUCCESS(status))
return status;
}
return STATUS_SUCCESS;
}
NTSTATUS USBLPTPD11CreateDevice (
IN PDRIVER_OBJECT DriverObject,
IN ULONG DeviceNumber
)
{
PDEVICE_OBJECT deviceObject;
NTSTATUS status;
PLOCAL_DEVICE_INFO deviceExtension;
WCHAR NTDeviceBuffer[44];
WCHAR Win32DeviceBuffer[52];
WCHAR ParPortDeviceBuffer[46];
WCHAR NumberBuffer[6];
UNICODE_STRING uniWin32Device = {0, sizeof(Win32DeviceBuffer)/sizeof(WCHAR), Win32DeviceBuffer};
UNICODE_STRING uniParPortDevice = {0, sizeof(ParPortDeviceBuffer)/sizeof(WCHAR), ParPortDeviceBuffer};
UNICODE_STRING uniNumber = {0, sizeof(NumberBuffer)/sizeof(WCHAR), NumberBuffer};
UNICODE_STRING uniNTDevice = {0, sizeof(NTDeviceBuffer)/sizeof(WCHAR), NTDeviceBuffer};
KEVENT event;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
PARALLEL_PORT_INFORMATION ParPortInfo;
MORE_PARALLEL_PORT_INFORMATION MoreParPortInfo;
RtlIntegerToUnicodeString(DeviceNumber, 10, &uniNumber);
RtlAppendUnicodeToString(&uniNTDevice, NT_DEVICE_NAME);
RtlAppendUnicodeStringToString(&uniNTDevice, &uniNumber);
RtlAppendUnicodeToString(&uniParPortDevice, PAR_PORT_NAME);
RtlAppendUnicodeStringToString(&uniParPortDevice, &uniNumber);
RtlAppendUnicodeToString(&uniWin32Device, WIN32_DEVICE_NAME);
RtlAppendUnicodeStringToString(&uniWin32Device, &uniNumber);
status = IoCreateDevice(DriverObject, // DriverObject
sizeof(LOCAL_DEVICE_INFO), // DeviceExtensionSize
&uniNTDevice, // DeviceName
FILE_DEVICE_PARALLEL_PORT, // DeviceType
0, // DeviceCharacteristics
TRUE, // Exclusive
&deviceObject); // *DeviceObject
KdPrint( ("USBLPTPD11: USBLPT-PD11 Create Device %d, DriverObject %X, DeviceObject %X",DeviceNumber,DriverObject,deviceObject) );
if(!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: Cannot Create Device - IoCreateDevice Failed NTSTATUS %x\n",status) );
return status;
}
deviceExtension = deviceObject->DeviceExtension;
RtlZeroMemory(deviceExtension, sizeof(PLOCAL_DEVICE_INFO));
deviceExtension->deviceObject = deviceObject;
deviceExtension->DeviceNumber = DeviceNumber;
status = IoGetDeviceObjectPointer(&uniParPortDevice,
FILE_READ_ATTRIBUTES,
&deviceExtension->ParPortFileObject,
&deviceExtension->ParPortDeviceObject);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: DriverEntry Cannot Open ParPort, ParallelPort%d\n",DeviceNumber) );
IoDeleteDevice(DriverObject->DeviceObject);
return STATUS_SUCCESS;
}
ObReferenceObjectByPointer( deviceExtension->ParPortDeviceObject,FILE_READ_ATTRIBUTES,
NULL,KernelMode);
ObDereferenceObject(deviceExtension->ParPortFileObject);
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_GET_PARALLEL_PORT_INFO,
deviceExtension->ParPortDeviceObject,
NULL,
0,
&ParPortInfo,
sizeof(PARALLEL_PORT_INFORMATION),
TRUE,
&event,
&ioStatus);
if (!irp) {
KdPrint( ("USBLPTPD11: GET_PARALLEL_PORT_INFO Insufficent Resources for IoBuildDeviceIoControlRequest\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(deviceExtension->ParPortDeviceObject, irp);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: GET_PARALLEL_PORT_INFO Unexpected Failure in IoCallDriver\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return status;
}
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(status))
{
KdPrint( ("USBLPTPD11: GET_PARALLEL_PORT_INFO Unexpected Failure in KeWaitForSingleObject\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return status;
}
KdPrint( ("USBLPTPD11: Parallel Port at Address 0x%x and spans %d bytes",(ULONG)ParPortInfo.Controller,ParPortInfo.SpanOfController) );
deviceExtension->PortAddress = (ULONG)ParPortInfo.Controller;
/* Get Interrupt Information */
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_GET_MORE_PARALLEL_PORT_INFO,
deviceExtension->ParPortDeviceObject,
NULL,
0,
&MoreParPortInfo,
sizeof(MORE_PARALLEL_PORT_INFORMATION),
TRUE,
&event,
&ioStatus);
if (!irp) {
KdPrint( ("USBLPTPD11: GET_MORE_PARALLEL_PORT_INFO Insufficent Resources for IoBuildDeviceIoControlRequest\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(deviceExtension->ParPortDeviceObject, irp);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: GET_MORE_PARALLEL_PORT_INFO Unexpected Failure in IoCallDriver\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return status;
}
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: GET_MORE_PARALLEL_PORT_INFO Unexpected Failure in KeWaitForSingleObject\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return status;
}
KdPrint( ("USBLPTPD11: InterfaceType 0x%08x",MoreParPortInfo.InterfaceType) );
KdPrint( ("USBLPTPD11: BusNumber 0x%08x",MoreParPortInfo.BusNumber) );
KdPrint( ("USBLPTPD11: Interrupt Vector 0x%08x",MoreParPortInfo.InterruptVector) );
KdPrint( ("USBLPTPD11: Interrupt Affinity 0x%08x",MoreParPortInfo.InterruptAffinity ) );
KdPrint( ("USBLPTPD11: Interrupt Mode 0x%08x",MoreParPortInfo.InterruptMode) );
deviceExtension->InterfaceType = MoreParPortInfo.InterfaceType;
deviceExtension->BusNumber = MoreParPortInfo.BusNumber;
deviceExtension->Irql = 0x14;
deviceExtension->Vector = MoreParPortInfo.InterruptVector;
deviceExtension->InterruptMode = MoreParPortInfo.InterruptMode;
deviceExtension->Affinity = MoreParPortInfo.InterruptAffinity;
status = IoCreateSymbolicLink (&uniWin32Device, &uniNTDevice);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: Unexpected error while Creating Symbolic Link\n") );
IoDeleteDevice(DriverObject->DeviceObject);
return status;
}
return STATUS_SUCCESS;
}
NTSTATUS USBLPTPD11CreateDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PLOCAL_DEVICE_INFO DeviceExtension = DeviceObject->DeviceExtension;
ULONG MappedVector;
KEVENT event;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
KdPrint( ("USBLPTPD11: CreateFile() Call - Acquiring Port%d from ParPort",DeviceExtension->DeviceNumber) );
/* Now that someone has opened a handle to us, Acquire the LPT Port from ParPort.SYS */
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE,
DeviceExtension->ParPortDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
&event,
&ioStatus);
if (!irp) {
KdPrint( ("USBLPTPD11: PARALLEL_PORT_ALLOCATE Insufficent Resources for IoBuildDeviceIoControlRequest\n") );
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(DeviceExtension->ParPortDeviceObject, irp);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: PARALLEL_PORT_ALLOCATE Unexpected Failure in IoCallDriver\n") );
return status;
}
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: PARALLEL_PORT_ALLOCATE Unexpected Failure in KeWaitForSingleObject\n") );
return status;
}
/* and Setup Interrupts */
if (DeviceExtension->Vector) {
IoInitializeDpcRequest(DeviceObject,USBLPTPD11DpcRoutine);
status = IoConnectInterrupt(&DeviceExtension->InterruptObject, // InterruptObject
USBLPTPD11Isr, // ServiceRoutine
DeviceObject, // ServiceContext
NULL, // SpinLock
DeviceExtension->Vector, // Vector
DeviceExtension->Irql, // Irql
DeviceExtension->Irql, // SynchronizeIrql
DeviceExtension->InterruptMode, // InterruptMode
FALSE, // ShareVector
DeviceExtension->Affinity, // ProcessorEnableMask
FALSE); // FloatingSave
if (!NT_SUCCESS (status)) {
DbgPrint("USBLPTPD11: IoConnectInterrupt Failed\n");
return STATUS_INSUFFICIENT_RESOURCES; /* Can't obtain IRQ */
}
/* and Setup Timeout Timer */
KeInitializeTimer(&DeviceExtension->IntTimer);
}
else KdPrint( ("USBLPTPD11: No Interrupts enabled on LPT%d. You may want to enable the use of interrupts in control panel",DeviceExtension->DeviceNumber) );
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS USBLPTPD11CloseDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PLOCAL_DEVICE_INFO DeviceExtension = DeviceObject->DeviceExtension;
KEVENT event;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
KdPrint( ("USBLPTPD11: CloseHandle() Call - Releasing Port from ParPort") );
/* Now that someone has closed the handle free the LPT Port from ParPort.SYS */
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_PARALLEL_PORT_FREE,
DeviceExtension->ParPortDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
&event,
&ioStatus);
if (!irp) {
KdPrint( ("USBLPTPD11: PARALLEL_PORT_FREE Insufficent Resources for IoBuildDeviceIoControlRequest\n") );
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(DeviceExtension->ParPortDeviceObject, irp);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: PARALLEL_PORT_FREE Unexpected Failure in IoCallDriver\n") );
return status;
}
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(status)) {
KdPrint( ("USBLPTPD11: PARALLEL_PORT_FREE Unexpected Failure in KeWaitForSingleObject\n") );
return status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -