📄 usblptpd11.c
字号:
}
/* And restore Interrupts */
if (DeviceExtension->Vector) IoDisconnectInterrupt(DeviceExtension->InterruptObject);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
USBLPTPD11DeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG inBufLength; /* Input buffer length */
ULONG outBufLength; /* Output buffer length */
PUCHAR CharBuffer; /* Pointer to Char Formatted Buffer */
PULONG LongBuffer; /* Pointer to Long Formatted Buffer */
PVOID ioBuffer; /* pointer to Input and output buffer */
UCHAR Count;
UCHAR Buffer[40];
PLOCAL_DEVICE_INFO DeviceExtension = DeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation( pIrp );
inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
ioBuffer = pIrp->AssociatedIrp.SystemBuffer;
CharBuffer = (PUCHAR) ioBuffer;
LongBuffer = (PULONG) ioBuffer;
switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
{
case IOCTL_DETECT_DEVICE:
KdPrint( ("USBLPTPD11: IOCTL_DETECT_DEVICE") );
/* Clear ECP's Extended Control Register Setting Port to Standard Mode */
outportb(DeviceExtension->PortAddress + 0x402, 0x00);
ntStatus = DetectDevice(DeviceExtension->PortAddress);
pIrp->IoStatus.Information = 0; /* Output Buffer Size */
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_INIT_I2C:
KdPrint( ("USBLPTPD11: IOCTL_I2C_INIT\n") );
ntStatus = I2C_Init(DeviceExtension->PortAddress);
pIrp->IoStatus.Information = 0; /* Output Buffer Size */
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_READ_I2C:
ntStatus = STATUS_BUFFER_TOO_SMALL;
pIrp->IoStatus.Information = 0;
if (inBufLength >= 2) { /* Safe to retreive byCount Value */
KdPrint( ("USBLPTPD11: READ_I2C, byDevID = 0x%02X, byCount = 0x%02X\n",CharBuffer[0],CharBuffer[1]) );
Count = CharBuffer[1];
if (outBufLength >= Count) { /* Safe to call I2C_Read Operation */
ntStatus = I2C_Read( ioBuffer, CharBuffer[0], CharBuffer[1], DeviceExtension->PortAddress);
pIrp->IoStatus.Information = Count; /* Output Buffer Size */
}
}
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_WRITE_I2C:
ntStatus = STATUS_BUFFER_TOO_SMALL;
if (inBufLength >= 2) { /* Safe to retreive byCount Value */
KdPrint( ("USBLPTPD11: Write_I2C, byDevID = 0x%02X, byCount = 0x%02X\n",CharBuffer[0],CharBuffer[1]) );
Count = CharBuffer[1] + 2;
if (inBufLength >= Count) /* Safe to call I2C_Write Operation */
ntStatus = I2C_Write(CharBuffer[0], &CharBuffer[2], CharBuffer[1], DeviceExtension->PortAddress);
}
pIrp->IoStatus.Information = 0; /* Output Buffer Size */
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_STATUS_LED:
KdPrint( ("USBLPTPD11: IOCTL_STATUS_LED") );
if (inBufLength >= 1) {
if (CharBuffer[0]) SetStatus(DeviceExtension->PortAddress);
else ClearStatus(DeviceExtension->PortAddress);
ntStatus = STATUS_SUCCESS;
} else ntStatus = STATUS_BUFFER_TOO_SMALL;
pIrp->IoStatus.Information = 0; /* Output Buffer Size */
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_GET_SUSPEND:
KdPrint( ("USBLPTPD11: IOCTL_GET_SUSPEND") );
if (outBufLength >= 1) {
*(PUCHAR)ioBuffer = GetSuspend(DeviceExtension->PortAddress);
pIrp->IoStatus.Information = 1; /* Output Buffer Size */
ntStatus = STATUS_SUCCESS;
} else {
pIrp->IoStatus.Information = 0;
ntStatus = STATUS_BUFFER_TOO_SMALL;
}
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_GET_INT:
KdPrint( ("USBLPTPD11: IOCTL_GET_INT") );
if (outBufLength >= 1) {
*(PUCHAR)ioBuffer = GetInt(DeviceExtension->PortAddress);
pIrp->IoStatus.Information = 1; /* Output Buffer Size */
ntStatus = STATUS_SUCCESS;
} else {
pIrp->IoStatus.Information = 0;
ntStatus = STATUS_BUFFER_TOO_SMALL;
}
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
break;
case IOCTL_WAIT_INTERRUPT:
if (inBufLength >= 4) {
KdPrint( ("USBLPTPD11: Wait for Interrupt, Timeout = %duS\n",LongBuffer[0]) );
DeviceExtension->IntTimer_uS = RtlConvertLongToLargeInteger(0 - LongBuffer[0]);
/* Check if IRQ line (nAck) already High. If this is the case, return immediately */
if ((inportb(DeviceExtension->PortAddress + 1) & 0x40) | (DeviceExtension->Vector == 0)){
pIrp->IoStatus.Information = 0; /* Output Buffer Size */
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
ntStatus = STATUS_SUCCESS;
}
else {
/* Mark IRP as pending and place in queue */
IoMarkIrpPending(pIrp);
IoStartPacket(DeviceObject, pIrp, NULL, NULL);
ntStatus = STATUS_PENDING;
}
} else {
ntStatus = STATUS_BUFFER_TOO_SMALL;
pIrp->IoStatus.Information = 0; /* Output Buffer Size */
pIrp->IoStatus.Status = ntStatus;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
}
break;
default:
KdPrint( ("USBLPTPD11: Unsupported IOCTL Call\n") );
ntStatus = STATUS_UNSUCCESSFUL;
pIrp->IoStatus.Status = ntStatus;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
break;
}
return ntStatus;
}
VOID USBLPTPD11Unload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT CurrentDevice;
PLOCAL_DEVICE_INFO DeviceExtension;
KEVENT event;
PIRP irp;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
WCHAR Win32DeviceBuffer[52];
WCHAR NumberBuffer[6];
UNICODE_STRING uniWin32Device = {0, sizeof(Win32DeviceBuffer)/sizeof(WCHAR), Win32DeviceBuffer};
UNICODE_STRING uniNumber = {0, sizeof(NumberBuffer)/sizeof(WCHAR), NumberBuffer};
CurrentDevice = DriverObject->DeviceObject;
while( CurrentDevice ) {
DeviceExtension = CurrentDevice->DeviceExtension;
KdPrint( ("USBLPTPD11: USBLPT-PD11 is Unloading Device %d, DeviceObject %x",DeviceExtension->DeviceNumber, CurrentDevice ) );
/* Disable Parallel Port IRQ's */
outportb(DeviceExtension->PortAddress+2, inportb(DeviceExtension->PortAddress+2) & 0xEF);
// Convert Device Number to Unicode String
uniNumber.Length = 0;
uniWin32Device.Length = 0;
RtlIntegerToUnicodeString(DeviceExtension->DeviceNumber, 10, &uniNumber);
RtlAppendUnicodeToString(&uniWin32Device, WIN32_DEVICE_NAME);
RtlAppendUnicodeStringToString(&uniWin32Device, &uniNumber);
IoDeleteSymbolicLink (&uniWin32Device);
IoDeleteDevice(CurrentDevice);
CurrentDevice = DriverObject->DeviceObject;
}
}
VOID USBLPTPD11StartIo(PDEVICE_OBJECT DeviceObject, PIRP pIrp)
{
PLOCAL_DEVICE_INFO DeviceExtension = DeviceObject->DeviceExtension;
/* Enable Parallel Port IRQ's */
outportb(DeviceExtension->PortAddress+2, inportb(DeviceExtension->PortAddress+2) | 0x10);
/* Set up timers for Interrupt Time Out */
KeInitializeDpc(&DeviceExtension->IntTimerDPC,
USBLPTPD11TimeOutDPC,
DeviceObject);
KeSetTimer(&DeviceExtension->IntTimer,
DeviceExtension->IntTimer_uS,
&DeviceExtension->IntTimerDPC);
}
VOID USBLPTPD11TimeOutDPC(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
PDEVICE_OBJECT deviceObject;
PLOCAL_DEVICE_INFO deviceExtension;
PIRP pIrp;
deviceObject = DeferredContext;
pIrp = deviceObject->CurrentIrp;
deviceExtension = deviceObject->DeviceExtension;
KdPrint( ("USBLPTPD11: ISRTimeOutDPC, pIrp = 0x%08X\n",pIrp) );
if (pIrp != NULL)
{
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_IO_TIMEOUT;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
IoStartNextPacket(deviceObject, FALSE);
}
}
BOOLEAN USBLPTPD11Isr(IN PKINTERRUPT Interrupt, IN OUT PVOID Context)
{
PDEVICE_OBJECT deviceObject = Context;
KdPrint( ("USBLPTPD11: Interrupt Service Routine\n") );
/* We should check if the interrupt comes from us and return */
if (!(deviceObject->CurrentIrp == NULL)) {
IoRequestDpc(deviceObject,
deviceObject->CurrentIrp,
NULL);
}
return TRUE;
}
VOID USBLPTPD11DpcRoutine(IN PKDPC Dpc, PDEVICE_OBJECT deviceObject, IN PIRP Irp, IN PVOID Context)
{
PLOCAL_DEVICE_INFO deviceExtension;
PIRP pIrp;
pIrp = deviceObject->CurrentIrp;
deviceExtension = deviceObject->DeviceExtension;
if (pIrp != NULL)
{
KdPrint( ("USBLPTPD11: DPC Routine Valid IRP - Completing Request\n") );
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KeCancelTimer(&deviceExtension->IntTimer);
IoStartNextPacket(deviceObject, FALSE);
}
return;
}
NTSTATUS I2C_Read(unsigned char * pbyData, unsigned char byDevId, unsigned char byCount, unsigned long PortAddress) {
unsigned char byRetVal = 0;
while(1) {
if(!Start(PortAddress)) return STATUS_DATA_ERROR;
if( !ByteOut( byDevId |= I2C_CTL_READ, PortAddress ) ) return STATUS_DATA_ERROR;
while(byCount) {
ByteIn( pbyData+byRetVal, PortAddress );
byCount--;
byRetVal++;
if(byCount) {
SetAck(PortAddress);
}
else {
SetNak(PortAddress);
}
}
Stop(PortAddress);
break;
}
return STATUS_SUCCESS;
}
NTSTATUS I2C_Write(unsigned char byDevId, unsigned char * pbyData, unsigned char byCount, unsigned long PortAddress) {
unsigned char byRetVal = 0;
if( !Start(PortAddress) ) return STATUS_DATA_ERROR;
if( !ByteOut( byDevId &= I2C_CTL_WRITE, PortAddress) ) return STATUS_DATA_ERROR;
while(byCount) {
if( !ByteOut( *(pbyData+byRetVal), PortAddress ) ) return STATUS_DATA_ERROR;
byCount--;
byRetVal++;
}
Stop(PortAddress);
return STATUS_SUCCESS;
}
NTSTATUS I2C_Init(unsigned long PortAddress) {
Idle(PortAddress);
if (GetSDA(PortAddress) && GetSCL(PortAddress)) return STATUS_SUCCESS;
else return STATUS_DATA_ERROR;
}
unsigned char Start(unsigned long PortAddress) {
if( !(GetSCL(PortAddress) && GetSDA(PortAddress)) )
{
Stop(PortAddress);
if( !(GetSCL(PortAddress) && GetSDA(PortAddress)) )
return I2C_FALSE;
}
ClearSDA(PortAddress);
return I2C_TRUE;
}
unsigned char ByteOut(unsigned char byData, unsigned long PortAddress) {
unsigned char i;
unsigned char AckWait=0;
for (i=0x80; i>0; i>>=1) {
ClearSCL(PortAddress);
if (byData & i) SetSDA(PortAddress);
else ClearSDA(PortAddress);
SetSCL(PortAddress);
}
// Check for ACK
ClearSCL(PortAddress);
SetSDA(PortAddress);
SetSCL(PortAddress);
if (GetSDA(PortAddress)) {
ClearSCL(PortAddress);
return I2C_FALSE;
}
ClearSCL(PortAddress);
return I2C_TRUE; // ACK was detected if here
}
void ByteIn(unsigned char * pbyData, unsigned long PortAddress) {
unsigned char i;
unsigned char byTemp=0;
for (i=0; i<8; i++) {
ClearSCL(PortAddress);
byTemp |= GetSDA(PortAddress);
SetSCL(PortAddress);
if (i != 7) byTemp <<= 1;
}
*pbyData = byTemp;
}
NTSTATUS DetectDevice(LONG PortAddress)
{
/* Set XD1 and check */
outportb(PortAddress, inportb(PortAddress) | XD1);
if (!(inportb(PortAddress+1) & XERROR)) return STATUS_UNSUCCESSFUL;
/* Clear XD1 and Check */
outportb(PortAddress, inportb(PortAddress) & ~XD1);
if (inportb(PortAddress+1) & XERROR) return STATUS_UNSUCCESSFUL;
/* Set SDA and Check Loopback */
SetSDA(PortAddress);
if (!GetSDA(PortAddress)) return STATUS_UNSUCCESSFUL;
/* Clear SDA and Check Loopback */
ClearSDA(PortAddress);
if (GetSDA(PortAddress)) return STATUS_UNSUCCESSFUL;
/* Set SCL and Check Loopback */
SetSCL(PortAddress);
if (!GetSCL(PortAddress)) return STATUS_UNSUCCESSFUL;
/* Clear SCL and Check Loopback */
ClearSCL(PortAddress);
if (GetSCL(PortAddress)) return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -