📄 ioctl.c
字号:
Extension->Interrupt,
SerialGetStats,
Irp
);
*/
SerialGetStats(Irp);
break;
}
case IOCTL_SERIAL_CLEAR_STATS: {
/*
KeSynchronizeExecution(
Extension->Interrupt,
SerialClearStats,
Extension
);
*/
SerialClearStats(deviceExtension);
break;
}
default: {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
}
DoneWithIoctl:;
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
UsbCom_DecrementIoCount(DeviceObject);
return ntStatus;
}
VOID
SerialGetProperties(
IN PDEVICE_EXTENSION Extension,
IN PSERIAL_COMMPROP Properties
)
/*++
Routine Description:
This function returns the capabilities of this particular
serial device.
Arguments:
Extension - The serial device extension.
Properties - The structure used to return the properties
Return Value:
None.
--*/
{
ULONG SupportedBauds = 0;
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 = Extension->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 = Extension->BufferSize;
}
NTSTATUS
SerialInternalIoControl(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
/*++
Routine Description:
This routine provides the initial processing for all of the
internal Ioctrls for the serial device.
Arguments:
PDevObj - Pointer to the device object for this device
PIrp - Pointer to the IRP for the current request
Return Value:
The function value is the final status of the call
--*/
{
//
// The status that gets returned to the caller and
// set in the Irp.
//
NTSTATUS status;
//
// The current stack location. This contains all of the
// information we need to process this particular request.
//
PIO_STACK_LOCATION pIrpStack;
//
// Just what it says. This is the serial specific device
// extension of the device object create for the serial driver.
//
PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
//
// A temporary to hold the old IRQL so that it can be
// restored once we complete/validate this request.
//
KIRQL OldIrql;
NTSTATUS prologueStatus;
SYSTEM_POWER_STATE cap;
// SERIAL_LOCKED_PAGED_CODE();
SerialDump(SERIRPPATH, ("SERIAL: Dispatch InternalIoControl entry for: %x\n", PIrp));
/*
if ((prologueStatus = SerialIRPPrologue(PIrp, pDevExt))
!= STATUS_SUCCESS) {
SerialCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
return prologueStatus;
}
SerialDump(SERIRPPATH, ("SERIAL: Dispatch InternalIoControl entry for: %x\n", PIrp));
if (SerialCompleteIfError(PDevObj, PIrp) != STATUS_SUCCESS) {
return STATUS_CANCELLED;
}
*/
UsbCom_IncrementIoCount(PDevObj);
// Can't accept a new io request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending
if ( !UsbCom_CanAcceptIoRequests( PDevObj ) ) {
status = STATUS_DELETE_PENDING;
PIrp->IoStatus.Status = status;
PIrp->IoStatus.Information = 0;
IoCompleteRequest( PIrp, IO_NO_INCREMENT );
DbgPrint("Removed: %d, Started: %d, Stop: %d\n",
pDevExt->DeviceRemoved,
pDevExt->DeviceStarted,
pDevExt->StopDeviceRequested);
UsbCom_DecrementIoCount(PDevObj);
return status;
}
pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
PIrp->IoStatus.Information = 0L;
status = STATUS_SUCCESS;
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
//
// Send a wait-wake IRP
//
case IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE:
//
// Make sure we can do wait-wake based on what the device reported
//
for (cap = PowerSystemSleeping1; cap < PowerSystemMaximum; cap++) {
if ((pDevExt->DeviceStateMap[cap] >= PowerDeviceD0)
&& (pDevExt->DeviceStateMap[cap] <= pDevExt->DeviceWake)) {
break;
}
}
if (cap < PowerSystemMaximum) {
pDevExt->SendWaitWake = TRUE;
status = STATUS_SUCCESS;
} else {
status = STATUS_NOT_SUPPORTED;
}
break;
case IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE:
pDevExt->SendWaitWake = FALSE;
if (pDevExt->PendingWakeIrp != NULL) {
IoCancelIrp(pDevExt->PendingWakeIrp);
}
status = STATUS_SUCCESS;
break;
//
// Put the serial port in a "filter-driver" appropriate state
//
// WARNING: This code assumes it is being called by a trusted kernel
// entity and no checking is done on the validity of the settings
// passed to IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS
//
// If validity checking is desired, the regular ioctl's should be used
//
case IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS:
case IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS: {
SERIAL_BASIC_SETTINGS basic;
PSERIAL_BASIC_SETTINGS pBasic;
SHORT AppropriateDivisor;
SERIAL_IOCTL_SYNC S;
if (pIrpStack->Parameters.DeviceIoControl.IoControlCode
== IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS) {
//
// Check the buffer size
//
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_BASIC_SETTINGS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Everything is 0 -- timeouts and flow control and fifos. If
// We add additional features, this zero memory method
// may not work.
//
RtlZeroMemory(&basic, sizeof(SERIAL_BASIC_SETTINGS));
basic.TxFifo = 1;
basic.RxFifo = SERIAL_1_BYTE_HIGH_WATER;
PIrp->IoStatus.Information = sizeof(SERIAL_BASIC_SETTINGS);
pBasic = (PSERIAL_BASIC_SETTINGS)PIrp->AssociatedIrp.SystemBuffer;
//
// Save off the old settings
//
RtlCopyMemory(&pBasic->Timeouts, &pDevExt->Timeouts,
sizeof(SERIAL_TIMEOUTS));
RtlCopyMemory(&pBasic->HandFlow, &pDevExt->HandFlow,
sizeof(SERIAL_HANDFLOW));
pBasic->RxFifo = pDevExt->RxFifoTrigger;
pBasic->TxFifo = pDevExt->TxFifoAmount;
//
// Point to our new settings
//
pBasic = &basic;
} else { // restoring settings
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength
< sizeof(SERIAL_BASIC_SETTINGS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
pBasic = (PSERIAL_BASIC_SETTINGS)PIrp->AssociatedIrp.SystemBuffer;
}
KeAcquireSpinLock(&pDevExt->ControlLock, &OldIrql);
//
// Set the timeouts
//
RtlCopyMemory(&pDevExt->Timeouts, &pBasic->Timeouts,
sizeof(SERIAL_TIMEOUTS));
//
// Set flowcontrol
//
S.Extension = pDevExt;
S.Data = &pBasic->HandFlow;
// KeSynchronizeExecution(pDevExt->Interrupt, SerialSetHandFlow, &S);
// SerialSetHandFlow(&S); henry
/*
if (pDevExt->FifoPresent) {
pDevExt->TxFifoAmount = pBasic->TxFifo;
pDevExt->RxFifoTrigger = (UCHAR)pBasic->RxFifo;
WRITE_FIFO_CONTROL(pDevExt->Controller, (UCHAR)0);
READ_RECEIVE_BUFFER(pDevExt->Controller);
WRITE_FIFO_CONTROL(pDevExt->Controller,
(UCHAR)(SERIAL_FCR_ENABLE | pDevExt->RxFifoTrigger
| SERIAL_FCR_RCVR_RESET
| SERIAL_FCR_TXMT_RESET));
} else {
pDevExt->TxFifoAmount = pDevExt->RxFifoTrigger = 0;
WRITE_FIFO_CONTROL(pDevExt->Controller, (UCHAR)0);
}
*/
KeReleaseSpinLock(&pDevExt->ControlLock, OldIrql);
break;
}
default:
status = STATUS_INVALID_PARAMETER;
break;
}
PIrp->IoStatus.Status = status;
//SerialDump(SERIRPPATH, ("SERIAL: Complete Irp: %x\n", PIrp));
SerialCompleteRequest(pDevExt, PIrp, 0);
return status;
}
NTSTATUS
UsbCom_SetBaud(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG baudrate
)
{
NTSTATUS Status;
USHORT valueBaud;
UCHAR i,index_matched;
ULONG baudArray[14] = { 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400,
110, 300, 1200, 460800, 921600 };
//#ifdef SS_USE_SINGLE_TI
// USHORT valueBaudArray[14] = { 0xA0, 0xD0, 0x68, 0x34, 0x1A, 0x11, 0x09, 0x04,
// 0x68, 0x68, 0x42, 0x68, 0x68 };
//#endif
USHORT valueBaudArray[14] = { 0x30, 0x18, 0x0C, 0x06, 0x03, 0x02, 0x01, 0x68,
0x68, 0x1A, 0x60, 0x68, 0x68 };
DbgPrint("enter UsbCom_SetBaud() DO=%08x Irp=%08x BaudRate=%u\n", DeviceObject, Irp, baudrate);
index_matched = 255;
for (i=0; i<14; i++)
{
if (baudArray[i] == baudrate)
index_matched = i;
}
if (index_matched == 255) {
/*
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp,
IO_NO_INCREMENT);
UsbCom_DecrementIoCount(DeviceObject);
*/
return STATUS_INVALID_PARAMETER;
}
valueBaud = valueBaudArray[index_matched];
Status = UsbCom_SendVendor(DeviceObject, VendorBaudRate, valueBaud);
DbgPrint("exit UsbCom_SetBaud() Status=%08x\n", Status );
return Status;
}
NTSTATUS
UsbCom_SendVendor(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Request,
IN USHORT Value
)
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
UCHAR ChannelNumber;
deviceExtension = DeviceObject->DeviceExtension;
ChannelNumber = (UCHAR)deviceExtension->ChannelNumber;
Request = ( ((ChannelNumber << 5) & 0xe0) | ( Request & 0x1f ) );
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));
if (! urb) {
DbgPrint("UsbCom_SendVendor() DO=%08x ExAllocatePool() URB_CONTROL_VENDOR_OR_CLASS_REQUEST : FAIL\n", DeviceObject );
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto UsbCom_SendVendorDone;
}
UsbBuildVendorRequest(urb,
URB_FUNCTION_VENDOR_DEVICE,
(USHORT) sizeof (struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
0, // out direction
0, // reserved bits in request type
Request, // request
Value, // value
0, // index
NULL,
NULL,
0,
NULL);
DbgPrint("UsbCom_SendVendor() DO=%08x Urb=%08x [Channel=%u Request=%02x Value=%04x]\n",
DeviceObject, urb, ChannelNumber, Request, Value);
ntStatus = UsbCom_CallUSBD(DeviceObject, urb);
ExF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -