📄 readwrit.c
字号:
/*
* UNIMODEM "Fakemodem" controllerless driver illustrative example
*
* (C) 2000 Microsoft Corporation
* All Rights Reserved
*
* The code in this module simply supports the very basic AT command parser.
* This code should be completely replaced with the actual code to support
* your controllerless modem.
*/
#include "fakemodem.h"
NTSTATUS
FakeModemRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
NTSTATUS status=STATUS_UNSUCCESSFUL;
KIRQL OldIrql;
KIRQL CancelIrql;
Irp->IoStatus.Information = 0;
//
// make sure the device is ready for irp's
//
status=CheckStateAndAddReference( DeviceObject, Irp);
if (STATUS_SUCCESS != status) {
//
// not accepting irp's. The irp has already been completed
//
return status;
}
Irp->IoStatus.Status=STATUS_PENDING;
IoMarkIrpPending(Irp);
KeAcquireSpinLock(&deviceExtension->SpinLock, &OldIrql);
//
// make irp cancelable
//
IoAcquireCancelSpinLock(&CancelIrql);
IoSetCancelRoutine(Irp, ReadCancelRoutine);
IoReleaseCancelSpinLock(CancelIrql);
//
// put it on queue
//
InsertTailList(&deviceExtension->ReadQueue, &Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&deviceExtension->SpinLock, OldIrql);
//
// call the real work function to process the irps
//
ReadIrpWorker( DeviceObject);
RemoveReferenceForDispatch(DeviceObject);
return STATUS_PENDING;
}
NTSTATUS
FakeModemWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
NTSTATUS status=STATUS_UNSUCCESSFUL;
KIRQL OldIrql;
KIRQL CancelIrql;
Irp->IoStatus.Information = 0;
// make sure the device is ready for irp's
status=CheckStateAndAddReference( DeviceObject, Irp);
if (STATUS_SUCCESS != status) {
// not accepting irp's. The irp has already been complted
return status;
}
Irp->IoStatus.Status=STATUS_PENDING;
IoMarkIrpPending(Irp);
KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);
// make irp cancelable
IoAcquireCancelSpinLock(&CancelIrql);
IoSetCancelRoutine(Irp, WriteCancelRoutine);
IoReleaseCancelSpinLock(CancelIrql);
// put it on queue
InsertTailList( &deviceExtension->WriteQueue, &Irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&deviceExtension->SpinLock, OldIrql);
// call the real work function to process the irps
if (deviceExtension->Started)
{
WriteIrpWorker(DeviceObject);
}
RemoveReferenceForDispatch(DeviceObject);
return STATUS_PENDING;
}
VOID
WriteIrpWorker(
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
NTSTATUS status=STATUS_UNSUCCESSFUL;
KIRQL OldIrql;
KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);
if (deviceExtension->CurrentWriteIrp != NULL) {
// already in use
goto Exit;
}
while (!IsListEmpty(&deviceExtension->WriteQueue)) {
PLIST_ENTRY ListElement;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
KIRQL CancelIrql;
ListElement=RemoveHeadList( &deviceExtension->WriteQueue);
Irp=CONTAINING_RECORD(ListElement,IRP,Tail.Overlay.ListEntry);
IoAcquireCancelSpinLock(&CancelIrql);
if (Irp->Cancel) {
// this one has been canceled
Irp->IoStatus.Information=STATUS_CANCELLED;
IoReleaseCancelSpinLock(CancelIrql);
continue;
}
IoSetCancelRoutine(
Irp,
NULL
);
IoReleaseCancelSpinLock(CancelIrql);
deviceExtension->CurrentWriteIrp=Irp;
IrpSp=IoGetCurrentIrpStackLocation(Irp);
ProcessWriteBytes( deviceExtension, Irp->AssociatedIrp.SystemBuffer,
IrpSp->Parameters.Write.Length);
KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);
Irp->IoStatus.Information = IrpSp->Parameters.Write.Length;
RemoveReferenceAndCompleteRequest( DeviceObject, Irp, STATUS_SUCCESS);
KeAcquireSpinLock( &deviceExtension->SpinLock, &OldIrql);
deviceExtension->CurrentWriteIrp=NULL;
}
Exit:
KeReleaseSpinLock( &deviceExtension->SpinLock, OldIrql);
TryToSatisfyRead( deviceExtension);
ReadIrpWorker( DeviceObject);
ProcessConnectionStateChange( DeviceObject);
return;
}
VOID
ProcessWriteBytes(
PDEVICE_EXTENSION DeviceExtension,
PUCHAR Characters,
ULONG Length
)
{
UCHAR CurrentCharacter;
while (Length != 0) {
CurrentCharacter=*Characters++;
Length--;
PutCharInReadBuffer( DeviceExtension, CurrentCharacter);
switch (DeviceExtension->CommandMatchState) {
case COMMAND_MATCH_STATE_IDLE:
if ((CurrentCharacter == 'a') || (CurrentCharacter == 'A')) {
// got an A
DeviceExtension->CommandMatchState=COMMAND_MATCH_STATE_GOT_A;
DeviceExtension->ConnectCommand=FALSE;
DeviceExtension->IgnoreNextChar=FALSE;
}
break;
case COMMAND_MATCH_STATE_GOT_A:
if ((CurrentCharacter == 't') || (CurrentCharacter == 'T')) {
// got an T
DeviceExtension->CommandMatchState=COMMAND_MATCH_STATE_GOT_T;
} else {
if (CurrentCharacter == '\r') {
DeviceExtension->CommandMatchState=COMMAND_MATCH_STATE_IDLE;
}
}
break;
case COMMAND_MATCH_STATE_GOT_T:
if (!DeviceExtension->IgnoreNextChar) {
// the last char was not a special char
// check for CONNECT command
if ((CurrentCharacter == 'A') || (CurrentCharacter == 'a')) {
DeviceExtension->ConnectCommand=TRUE;
}
if ((CurrentCharacter == 'D') || (CurrentCharacter == 'd')) {
DeviceExtension->ConnectCommand=TRUE;
}
}
DeviceExtension->IgnoreNextChar=FALSE;
if ((CurrentCharacter == '&')
||
(CurrentCharacter == '/')
||
(CurrentCharacter == '\\')
||
(CurrentCharacter == '+')
||
(CurrentCharacter == '%')) {
// these characters are part of are used in init
// strings and may be proceeding an A or D
// which we don't want to misinterpret as a dial or answer
DeviceExtension->IgnoreNextChar=TRUE;
}
if (CurrentCharacter == '\r') {
//
// got a CR, send a response to the command
//
DeviceExtension->CommandMatchState=COMMAND_MATCH_STATE_IDLE;
if (DeviceExtension->ConnectCommand) {
//
// place <cr><lf>CONNECT<cr><lf> in the buffer
//
PutCharInReadBuffer(DeviceExtension,'\r');
PutCharInReadBuffer(DeviceExtension,'\n');
PutCharInReadBuffer(DeviceExtension,'C');
PutCharInReadBuffer(DeviceExtension,'O');
PutCharInReadBuffer(DeviceExtension,'N');
PutCharInReadBuffer(DeviceExtension,'N');
PutCharInReadBuffer(DeviceExtension,'E');
PutCharInReadBuffer(DeviceExtension,'C');
PutCharInReadBuffer(DeviceExtension,'T');
PutCharInReadBuffer(DeviceExtension,'\r');
PutCharInReadBuffer(DeviceExtension,'\n');
//
// connected now raise CD
//
DeviceExtension->CurrentlyConnected=TRUE;
DeviceExtension->ConnectionStateChanged=TRUE;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -