⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioctl.c

📁 串口Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:

            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 + -