📄 ioctl.c
字号:
switch (Lc->StopBits) {
case STOP_BIT_1: {
Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1;
LStop = SERIAL_1_STOP;
break;
}
case STOP_BITS_1_5: {
if (LData != SERIAL_5_DATA) {
Status = STATUS_INVALID_PARAMETER;
goto DoneWithIoctl;
}
Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1_5;
LStop = SERIAL_1_5_STOP;
break;
}
case STOP_BITS_2: {
if (LData == SERIAL_5_DATA) {
Status = STATUS_INVALID_PARAMETER;
goto DoneWithIoctl;
}
Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_2;
LStop = SERIAL_2_STOP;
break;
}
default: {
Status = STATUS_INVALID_PARAMETER;
goto DoneWithIoctl;
}
}
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
Extension->LineControl =
(UCHAR)((Extension->LineControl & SERIAL_LCR_BREAK) |
(LData | LParity | LStop));
Extension->ValidDataMask = Mask;
KeSynchronizeExecution(
Extension->Interrupt,
SerialSetLineControl,
Extension
);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_GET_LINE_CONTROL: {
PSERIAL_LINE_CONTROL Lc = (PSERIAL_LINE_CONTROL)Irp->AssociatedIrp.SystemBuffer;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_LINE_CONTROL)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) {
Lc->WordLength = 5;
} else if ((Extension->LineControl & SERIAL_DATA_MASK)
== SERIAL_6_DATA) {
Lc->WordLength = 6;
} else if ((Extension->LineControl & SERIAL_DATA_MASK)
== SERIAL_7_DATA) {
Lc->WordLength = 7;
} else if ((Extension->LineControl & SERIAL_DATA_MASK)
== SERIAL_8_DATA) {
Lc->WordLength = 8;
}
if ((Extension->LineControl & SERIAL_PARITY_MASK)
== SERIAL_NONE_PARITY) {
Lc->Parity = NO_PARITY;
} else if ((Extension->LineControl & SERIAL_PARITY_MASK)
== SERIAL_ODD_PARITY) {
Lc->Parity = ODD_PARITY;
} else if ((Extension->LineControl & SERIAL_PARITY_MASK)
== SERIAL_EVEN_PARITY) {
Lc->Parity = EVEN_PARITY;
} else if ((Extension->LineControl & SERIAL_PARITY_MASK)
== SERIAL_MARK_PARITY) {
Lc->Parity = MARK_PARITY;
} else if ((Extension->LineControl & SERIAL_PARITY_MASK)
== SERIAL_SPACE_PARITY) {
Lc->Parity = SPACE_PARITY;
}
if (Extension->LineControl & SERIAL_2_STOP) {
if (Lc->WordLength == 5) {
Lc->StopBits = STOP_BITS_1_5;
} else {
Lc->StopBits = STOP_BITS_2;
}
} else {
Lc->StopBits = STOP_BIT_1;
}
Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_TIMEOUTS: {
PSERIAL_TIMEOUTS NewTimeouts =
((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_TIMEOUTS)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) &&
(NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
(NewTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
Status = STATUS_INVALID_PARAMETER;
break;
}
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
Extension->Timeouts.ReadIntervalTimeout =
NewTimeouts->ReadIntervalTimeout;
Extension->Timeouts.ReadTotalTimeoutMultiplier =
NewTimeouts->ReadTotalTimeoutMultiplier;
Extension->Timeouts.ReadTotalTimeoutConstant =
NewTimeouts->ReadTotalTimeoutConstant;
Extension->Timeouts.WriteTotalTimeoutMultiplier =
NewTimeouts->WriteTotalTimeoutMultiplier;
Extension->Timeouts.WriteTotalTimeoutConstant =
NewTimeouts->WriteTotalTimeoutConstant;
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_GET_TIMEOUTS: {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_TIMEOUTS)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
*((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = Extension->Timeouts;
Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_CHARS: {
SERIAL_IOCTL_SYNC S;
PSERIAL_CHARS NewChars =
((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_CHARS)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// The only thing that can be wrong with the chars
// is that the xon and xoff characters are the
// same.
//
#if 0
if (NewChars->XonChar == NewChars->XoffChar) {
Status = STATUS_INVALID_PARAMETER;
break;
}
#endif
//
// We acquire the control lock so that only
// one request can GET or SET the characters
// at a time. The sets could be synchronized
// by the interrupt spinlock, but that wouldn't
// prevent multiple gets at the same time.
//
S.Extension = Extension;
S.Data = NewChars;
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
//
// Under the protection of the lock, make sure that
// the xon and xoff characters aren't the same as
// the escape character.
//
if (Extension->EscapeChar) {
if ((Extension->EscapeChar == NewChars->XonChar) ||
(Extension->EscapeChar == NewChars->XoffChar)) {
Status = STATUS_INVALID_PARAMETER;
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
}
Extension->WmiCommData.XonCharacter = NewChars->XonChar;
Extension->WmiCommData.XoffCharacter = NewChars->XoffChar;
KeSynchronizeExecution(
Extension->Interrupt,
SerialSetChars,
&S
);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_GET_CHARS: {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_CHARS)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
*((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer) = Extension->SpecialChars;
Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_DTR:
case IOCTL_SERIAL_CLR_DTR: {
//
// Make sure we are at power D0
//
if (Extension->PowerState != PowerDeviceD0) {
Status = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(Status)) {
break;
}
}
//
// We acquire the lock so that we can check whether
// automatic dtr flow control is enabled. If it is
// then we return an error since the app is not allowed
// to touch this if it is automatic.
//
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK)
== SERIAL_DTR_HANDSHAKE) {
Status = STATUS_INVALID_PARAMETER;
} else {
KeSynchronizeExecution(
Extension->Interrupt,
((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_DTR)?
(SerialSetDTR):(SerialClrDTR)),
Extension
);
}
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_RESET_DEVICE: {
break;
}
case IOCTL_SERIAL_SET_RTS:
case IOCTL_SERIAL_CLR_RTS: {
//
// Make sure we are at power D0
//
if (Extension->PowerState != PowerDeviceD0) {
Status = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(Status)) {
break;
}
}
//
// We acquire the lock so that we can check whether
// automatic rts flow control or transmit toggleing
// is enabled. If it is then we return an error since
// the app is not allowed to touch this if it is automatic
// or toggling.
//
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
if (((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
== SERIAL_RTS_HANDSHAKE) ||
((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
== SERIAL_TRANSMIT_TOGGLE)) {
Status = STATUS_INVALID_PARAMETER;
} else {
KeSynchronizeExecution(
Extension->Interrupt,
((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_RTS)?
(SerialSetRTS):(SerialClrRTS)),
Extension
);
}
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_XOFF: {
KeSynchronizeExecution(
Extension->Interrupt,
SerialPretendXoff,
Extension
);
break;
}
case IOCTL_SERIAL_SET_XON: {
KeSynchronizeExecution(
Extension->Interrupt,
SerialPretendXon,
Extension
);
break;
}
case IOCTL_SERIAL_SET_BREAK_ON: {
//
// Make sure we are at power D0
//
if (Extension->PowerState != PowerDeviceD0) {
Status = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(Status)) {
break;
}
}
KeSynchronizeExecution(
Extension->Interrupt,
SerialTurnOnBreak,
Extension
);
break;
}
case IOCTL_SERIAL_SET_BREAK_OFF: {
//
// Make sure we are at power D0
//
if (Extension->PowerState != PowerDeviceD0) {
Status = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(Status)) {
break;
}
}
KeSynchronizeExecution(
Extension->Interrupt,
SerialTurnOffBreak,
Extension
);
break;
}
case IOCTL_SERIAL_SET_QUEUE_SIZE: {
//
// Type ahead buffer is fixed, so we just validate
// the the users request is not bigger that our
// own internal buffer size.
//
PSERIAL_QUEUE_SIZE Rs =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -