ioctl.cpp
来自「这个是串口驱动程序开发包」· C++ 代码 · 共 1,202 行 · 第 1/3 页
CPP
1,202 行
IoReleaseCancelSpinLock(OldIrql);
}
else
{
// We can queue the char. We need to set
// a cancel routine because flow control could
// keep the char from transmitting. Make sure
// that the irp hasn't already been canceled.
if (Irp->Cancel)
{
IoReleaseCancelSpinLock(OldIrql);
Status = STATUS_CANCELLED;
}
else
{
m_CurrentImmediateIrp = Irp;
m_TotalCharsQueued++;
IoReleaseCancelSpinLock(OldIrql);
StartImmediate();
return STATUS_PENDING;
}
}
break;
case IOCTL_SERIAL_PURGE:
ULONG Mask;
if (Irp.IoctlInputBufferLength() < sizeof(ULONG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
// Check to make sure that the mask only has
// 0 or the other appropriate values.
Mask = *((PULONG)(Irp.SystemBuffer()));
if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT |
SERIAL_PURGE_RXABORT |
SERIAL_PURGE_TXCLEAR |
SERIAL_PURGE_RXCLEAR
)
)
))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
// Either start this irp or put it on the
// queue.
return StartOrQueue(
Irp,
&m_PurgeQueue,
&m_CurrentPurgeIrp,
StartPurge
);
case IOCTL_SERIAL_GET_HANDFLOW:
if (Irp.IoctlOutputBufferLength() < sizeof(SERIAL_HANDFLOW))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp.Information() = sizeof(SERIAL_HANDFLOW);
m_ControlLock.Lock();
*((PSERIAL_HANDFLOW)Irp.SystemBuffer()) = m_HandFlow;
m_ControlLock.Release();
break;
case IOCTL_SERIAL_SET_HANDFLOW:
{
PSERIAL_HANDFLOW HandFlow = (PSERIAL_HANDFLOW) Irp.SystemBuffer();
// Make sure that the hand shake and control is the
// right size.
if (Irp.IoctlInputBufferLength() < sizeof(SERIAL_HANDFLOW))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
// Make sure that there are no invalid bits set in
// the control and handshake.
if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
// Make sure that the app hasn't set an invlid DTR mode.
if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
SERIAL_DTR_MASK)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
// Make sure that haven't set totally invalid xon/xoff
// limits.
if ((HandFlow->XonLimit < 0) ||
((ULONG)HandFlow->XonLimit > m_BufferSize))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
if ((HandFlow->XoffLimit < 0) ||
((ULONG)HandFlow->XoffLimit > m_BufferSize))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
m_ControlLock.Lock();
// Under the protection of the lock, make sure that
// we aren't turning on error replacement when we
// are doing line status/modem status insertion.
if (m_EscapeChar)
{
if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR)
{
Status = STATUS_INVALID_PARAMETER;
m_ControlLock.Release();
break;
}
}
m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK_PARM) SetHandFlow, HandFlow);
m_ControlLock.Release();
break;
}
case IOCTL_SERIAL_GET_MODEMSTATUS:
if (Irp.IoctlOutputBufferLength() < sizeof(ULONG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp.Information() = sizeof(ULONG);
m_ControlLock.Lock();
m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK_PARM) GetModemUpdate,
Irp.SystemBuffer());
m_ControlLock.Release();
break;
case IOCTL_SERIAL_GET_DTRRTS:
{
ULONG ModemControl;
if (Irp.IoctlOutputBufferLength() < sizeof(ULONG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp.Information() = sizeof(ULONG);
Irp.Status() = STATUS_SUCCESS;
// Reading this hardware has no effect on the device.
ModemControl = m_pController->ReadByte(MODEM_CONTROL_REGISTER);
ModemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE;
*(PULONG)Irp.SystemBuffer() = ModemControl;
break;
}
case IOCTL_SERIAL_GET_COMMSTATUS:
{
KIRQL OldIrql;
if (Irp.IoctlOutputBufferLength() < sizeof(SERIAL_STATUS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp.Information() = sizeof(SERIAL_STATUS);
// Acquire the cancel spin lock so nothing much
// changes while were getting the state.
IoAcquireCancelSpinLock(&OldIrql);
m_KdInterrupt.SynchronizeExecution(
(KDIRQ_SYNC_CALLBACK_PARM) GetCommStatus,
Irp.SystemBuffer()
);
IoReleaseCancelSpinLock(OldIrql);
break;
}
case IOCTL_SERIAL_GET_PROPERTIES:
if (Irp.IoctlOutputBufferLength() < sizeof(SERIAL_COMMPROP))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
// No synchronization is required since this information
// is "static".
GetProperties(
(PSERIAL_COMMPROP)Irp.SystemBuffer()
);
Irp.Information() = sizeof(SERIAL_COMMPROP);
Irp.Status() = STATUS_SUCCESS;
break;
case IOCTL_SERIAL_XOFF_COUNTER:
{
PSERIAL_XOFF_COUNTER Xc = (PSERIAL_XOFF_COUNTER) Irp.SystemBuffer();
if (Irp.IoctlInputBufferLength() < sizeof(SERIAL_XOFF_COUNTER))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
if (Xc->Counter <= 0)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
// So far so good. Put the irp onto the write queue.
return StartOrQueue(
Irp,
&m_WriteQueue,
&m_CurrentWriteIrp,
StartWrite
);
}
case IOCTL_SERIAL_LSRMST_INSERT:
{
PUCHAR escapeChar = (PUCHAR) Irp.SystemBuffer();
// Make sure we get a byte.
if (Irp.IoctlInputBufferLength() < sizeof(UCHAR))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
m_ControlLock.Lock();
if (*escapeChar)
{
// We've got some escape work to do. We will make sure that
// the character is not the same as the Xon or Xoff character,
// or that we are already doing error replacement.
if ((*escapeChar == m_SpecialChars.XoffChar) ||
(*escapeChar == m_SpecialChars.XonChar) ||
(m_HandFlow.FlowReplace & SERIAL_ERROR_CHAR))
{
Status = STATUS_INVALID_PARAMETER;
m_ControlLock.Release();
break;
}
}
m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK_PARM) SetEscapeChar, Irp);
m_ControlLock.Release();
break;
}
case IOCTL_SERIAL_CONFIG_SIZE:
if (Irp.IoctlOutputBufferLength() < sizeof(ULONG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp.Information() = sizeof(ULONG);
Irp.Status() = STATUS_SUCCESS;
*(PULONG)Irp.SystemBuffer() = 0;
break;
case IOCTL_SERIAL_GET_STATS:
if (Irp.IoctlOutputBufferLength() < sizeof(SERIALPERF_STATS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp.Information() = sizeof(SERIALPERF_STATS);
Irp.Status() = STATUS_SUCCESS;
m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK_PARM) GetStats, Irp);
break;
case IOCTL_SERIAL_CLEAR_STATS:
m_KdInterrupt.SynchronizeExecution((KDIRQ_SYNC_CALLBACK) ClearStats);
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
DoneWithIoctl:;
Irp.Status() = Status;
DebugDump(DBG_DIAG6, ("Complete Irp: %x\n",Irp) );
Irp.Complete();
return Status;
}
VOID KdSerialDevice::GetProperties(IN PSERIAL_COMMPROP Properties)
/*++
Routine Description:
This function returns the capabilities of this particular
serial device.
Arguments:
Properties - The structure used to return the properties
--*/
{
RtlZeroMemory(
Properties,
sizeof(SERIAL_COMMPROP)
);
Properties->PacketLength = sizeof(SERIAL_COMMPROP);
Properties->PacketVersion = 2;
Properties->ServiceMask = SERIAL_SP_SERIALCOMM;
Properties->MaxTxQueue = 0;
Properties->MaxRxQueue = 0;
Properties->MaxBaud = SERIAL_BAUD_USER;
Properties->SettableBaud = m_SupportedBauds;
Properties->ProvSubType = SERIAL_SP_RS232;
Properties->ProvCapabilities = SERIAL_PCF_DTRDSR |
SERIAL_PCF_RTSCTS |
SERIAL_PCF_CD |
SERIAL_PCF_PARITY_CHECK |
SERIAL_PCF_XONXOFF |
SERIAL_PCF_SETXCHAR |
SERIAL_PCF_TOTALTIMEOUTS |
SERIAL_PCF_INTTIMEOUTS;
Properties->SettableParams = SERIAL_SP_PARITY |
SERIAL_SP_BAUD |
SERIAL_SP_DATABITS |
SERIAL_SP_STOPBITS |
SERIAL_SP_HANDSHAKING |
SERIAL_SP_PARITY_CHECK |
SERIAL_SP_CARRIER_DETECT;
Properties->SettableData = SERIAL_DATABITS_5 |
SERIAL_DATABITS_6 |
SERIAL_DATABITS_7 |
SERIAL_DATABITS_8;
Properties->SettableStopParity = SERIAL_STOPBITS_10 |
SERIAL_STOPBITS_15 |
SERIAL_STOPBITS_20 |
SERIAL_PARITY_NONE |
SERIAL_PARITY_ODD |
SERIAL_PARITY_EVEN |
SERIAL_PARITY_MARK |
SERIAL_PARITY_SPACE;
Properties->CurrentTxQueue = 0;
Properties->CurrentRxQueue = m_BufferSize;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?