📄 usbios.c
字号:
stack = IoGetNextIrpStackLocation(Irp);
stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
stack->Parameters.Others.Argument1 = urb;
// This IRP might have been cancelled the last time it was used, in which case
// the cancel flag will still be on. Clear it to prevent USBD from thinking that it's
// been cancelled again! A better way to do this would be to call IoReuseIrp,
// but that function is not declared in WDM.H.
Irp->Cancel = FALSE;
// UsbCom_IncrementIoCount(Extension->DeviceObject); //henry
// DbgPrint("Exit StartWriteUrb()\n");
return IoCallDriver(Extension->TopOfStackDeviceObject, Irp);
} // StartInterruptUrb
NTSTATUS
OnWriteInterrupt(
PDEVICE_OBJECT junk,
PIRP Irp,
PDEVICE_EXTENSION Extension
)
{ // OnInterrupt
PURB Urb;
KIRQL oldirql;
// KeAcquireSpinLock(&Extension->polllock, &oldirql);
Extension->writepending = FALSE; // allow another write to be started
// PVOID powercontext = Extension->powercontext;
// Extension->powercontext = NULL;
// KeReleaseSpinLock(&Extension->polllock, oldirql);
// If the poll completed successfully, do whatever it is we do when we
// get an interrupt (in this sample, that's answering an IOCTL) and
// reissue the read. We're trying to have a read outstanding on the
// interrupt pipe all the time except when power is off.
Urb = Extension->WritingUrb;
DbgPrint("WriteInterrupt_Routine: DO=%08x Irp=%08x TransferLength=%d, Urb Status=%x, Irp Status = %x\n",
Extension->DeviceObject,
Irp,
Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
Urb->UrbHeader.Status,
Irp->IoStatus.Status);
if (NT_SUCCESS(Irp->IoStatus.Status)) { // device signalled an interrupt
// if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
// TransferData(Extension, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
TransmitData(Extension);
// DbgPrint("Submitting the next read URB\n");
// Unless we're in the middle of a power-off sequence, reissue the
// polling IRP. Normally, SaveContext would have tried to cancel the
// IRP, and we won't get to this statement because STATUS_CANCELLED
// will fail the NT_SUCCESS test. We don't have any guarantee that the
// IRP will actually complete with STATUS_CANCELLED, though. Hence this test.
// if (!powercontext)
// StartReadUrb(Extension); // issue next polling request
} // device signalled an interrupt
#if DBG
else {
DbgPrint(" - Write polling IRP %X failed - %X (USBD status %X)\n",
Irp, Irp->IoStatus.Status, URB_STATUS(Extension->WritingUrb));
}
#endif
// UsbCom_DecrementIoCount(Extension->DeviceObject); //henry
// If we cancelled the poll during a power-down sequence, notify our
// power management code that it can continue.
/*
if (powercontext)
GenericSaveRestoreComplete(powercontext);
IoReleaseRemoveLock(&Extension->RemoveLock, Irp); // balances acquisition in StartInterruptUrb
*/
return STATUS_MORE_PROCESSING_REQUIRED;
} // OnInterrupt
VOID
TransmitData(
IN PDEVICE_EXTENSION Extension
)
{
Extension->HoldingEmpty = TRUE;
if (Extension->WriteLength ||
Extension->TransmitImmediate ||
Extension->SendXoffChar ||
Extension->SendXonChar) {
//
// Even though all of the characters being
// sent haven't all been sent, this variable
// will be checked when the transmit queue is
// empty. If it is still true and there is a
// wait on the transmit queue being empty then
// we know we finished transmitting all characters
// following the initiation of the wait since
// the code that initiates the wait will set
// this variable to false.
//
// One reason it could be false is that
// the writes were cancelled before they
// actually started, or that the writes
// failed due to timeouts. This variable
// basically says a character was written
// by the isr at some point following the
// initiation of the wait.
//
Extension->EmptiedTransmit = TRUE;
//
// If we have output flow control based on
// the modem status lines, then we have to do
// all the modem work before we output each
// character. (Otherwise we might miss a
// status line change.)
//
if (Extension->HandFlow.ControlHandShake &
SERIAL_OUT_HANDSHAKEMASK) {
SerialHandleModemUpdate(
Extension,
TRUE
);
}
//
// We can only send the xon character if
// the only reason we are holding is because
// of the xoff. (Hardware flow control or
// sending break preclude putting a new character
// on the wire.)
//
if (Extension->SendXonChar &&
!(Extension->TXHolding & ~SERIAL_TX_XOFF)) {
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/* WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XonChar
);
*/
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/* WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XonChar
);
*/
}
Extension->SendXonChar = FALSE;
Extension->HoldingEmpty = FALSE;
//
// If we send an xon, by definition we
// can't be holding by Xoff.
//
Extension->TXHolding &= ~SERIAL_TX_XOFF;
//
// If we are sending an xon char then
// by definition we can't be "holding"
// up reception by Xoff.
//
Extension->RXHolding &= ~SERIAL_RX_XOFF;
} else if (Extension->SendXoffChar &&
!Extension->TXHolding) {
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/* WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XoffChar
);
*/
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/* WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->SpecialChars.XoffChar
);
*/
}
//
// We can't be sending an Xoff character
// if the transmission is already held
// up because of Xoff. Therefore, if we
// are holding then we can't send the char.
//
//
// If the application has set xoff continue
// mode then we don't actually stop sending
// characters if we send an xoff to the other
// side.
//
if (!(Extension->HandFlow.FlowReplace &
SERIAL_XOFF_CONTINUE)) {
Extension->TXHolding |= SERIAL_TX_XOFF;
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
}
}
Extension->SendXoffChar = FALSE;
Extension->HoldingEmpty = FALSE;
//
// Even if transmission is being held
// up, we should still transmit an immediate
// character if all that is holding us
// up is xon/xoff (OS/2 rules).
//
} else if (Extension->TransmitImmediate &&
(!Extension->TXHolding ||
(Extension->TXHolding == SERIAL_TX_XOFF)
)) {
Extension->TransmitImmediate = FALSE;
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/* WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->ImmediateChar
);
*/
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/* WRITE_TRANSMIT_HOLDING(
Extension->Controller,
Extension->ImmediateChar
);
*/
}
Extension->HoldingEmpty = FALSE;
SerialInsertQueueDpc(
&Extension->CompleteImmediateDpc,
NULL,
NULL,
Extension
);
} else if (!Extension->TXHolding) {
ULONG amountToWrite;
/*
if (Extension->FifoPresent) {
amountToWrite = (Extension->TxFifoAmount <
Extension->WriteLength)?
Extension->TxFifoAmount:
Extension->WriteLength;
} else {
amountToWrite = 1;
}
*/
amountToWrite = (OutPipeMaxSize <
Extension->WriteLength)?
OutPipeMaxSize:
Extension->WriteLength;
Extension->WriteSize = amountToWrite; // Pass this information to StartWriteUrb.
if ((Extension->HandFlow.FlowReplace &
SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
//
// We have to raise if we're sending
// this character.
//
SerialSetRTS(Extension);
if (amountToWrite == 1) {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/*
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
*(Extension->WriteCurrentChar)
);
*/
StartWriteUrb(Extension);
} else {
Extension->PerfStats.TransmittedCount +=
amountToWrite;
Extension->WmiPerfData.TransmittedCount +=
amountToWrite;
/*
WRITE_TRANSMIT_FIFO_HOLDING(
Extension->Controller,
Extension->WriteCurrentChar,
amountToWrite
);
*/
StartWriteUrb(Extension);
}
SerialInsertQueueDpc(
&Extension->StartTimerLowerRTSDpc,
NULL,
NULL,
Extension
)?Extension->CountOfTryingToLowerRTS++:0;
} else {
if (amountToWrite == 1) {
Extension->PerfStats.TransmittedCount++;
Extension->WmiPerfData.TransmittedCount++;
/*
WRITE_TRANSMIT_HOLDING(
Extension->Controller,
*(Extension->WriteCurrentChar)
);
*/
StartWriteUrb(Extension);
} else {
Extension->PerfStats.TransmittedCount +=
amountToWrite;
Extension->WmiPerfData.TransmittedCount +=
amountToWrite;
/*
WRITE_TRANSMIT_FIFO_HOLDING(
Extension->Controller,
Extension->WriteCurrentChar,
amountToWrite
);
*/
StartWriteUrb(Extension);
}
}
Extension->HoldingEmpty = FALSE;
Extension->WriteCurrentChar += amountToWrite;
Extension->WriteLength -= amountToWrite;
/*
if (!Extension->WriteLength) {
PIO_STACK_LOCATION IrpSp;
//
// No More characters left. This
// write is complete. Take care
// when updating the information field,
// we could have an xoff counter masquerading
// as a write irp.
//
IrpSp = IoGetCurrentIrpStackLocation(
Extension->CurrentWriteIrp
);
Extension->CurrentWriteIrp->
IoStatus.Information =
(IrpSp->MajorFunction == IRP_MJ_WRITE)?
(IrpSp->Parameters.Write.Length):
(1);
SerialInsertQueueDpc(
&Extension->CompleteWriteDpc,
NULL,
NULL,
Extension
);
}
*/
}
} else if (!Extension->WriteLength) {
PIO_STACK_LOCATION IrpSp;
//
// No More characters left. This
// write is complete. Take care
// when updating the information field,
// we could have an xoff counter masquerading
// as a write irp.
//
IrpSp = IoGetCurrentIrpStackLocation(
Extension->CurrentWriteIrp
);
Extension->CurrentWriteIrp->
IoStatus.Information =
(IrpSp->MajorFunction == IRP_MJ_WRITE)?
(IrpSp->Parameters.Write.Length):
(1);
SerialInsertQueueDpc(
&Extension->CompleteWriteDpc,
NULL,
NULL,
Extension
);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -