?? ioctl.c
字號:
/*++
Copyright (c) 2005-2006 E0 Technology,Inc.
Module Name:
ioctl.c
Abstract:
Virtual Com Port Driver for USB to RS232 Converter of E0 Technology,Inc.
Environment:
Kernel mode
Notes:
Revision History:
2006/3/1 : Adapted from the serial DDK sample.
--*/
#include "usb2com.h"
PCHAR
SerialGetIoctlName(
IN ULONG IoControlCode
)
/*++
Routine Description:
SerialGetIoctlName returns the name of the ioctl
--*/
{
switch (IoControlCode)
{
case IOCTL_SERIAL_SET_BAUD_RATE : return "IOCTL_SERIAL_SET_BAUD_RATE";
case IOCTL_SERIAL_GET_BAUD_RATE: return "IOCTL_SERIAL_GET_BAUD_RATE";
case IOCTL_SERIAL_GET_MODEM_CONTROL: return "IOCTL_SERIAL_GET_MODEM_CONTROL";
case IOCTL_SERIAL_SET_MODEM_CONTROL: return "IOCTL_SERIAL_SET_MODEM_CONTROL";
case IOCTL_SERIAL_SET_FIFO_CONTROL: return "IOCTL_SERIAL_SET_FIFO_CONTROL";
case IOCTL_SERIAL_SET_LINE_CONTROL: return "IOCTL_SERIAL_SET_LINE_CONTROL";
case IOCTL_SERIAL_GET_LINE_CONTROL: return "IOCTL_SERIAL_GET_LINE_CONTROL";
case IOCTL_SERIAL_SET_TIMEOUTS: return "IOCTL_SERIAL_SET_TIMEOUTS";
case IOCTL_SERIAL_GET_TIMEOUTS: return "IOCTL_SERIAL_GET_TIMEOUTS";
case IOCTL_SERIAL_SET_CHARS: return "IOCTL_SERIAL_SET_CHARS";
case IOCTL_SERIAL_GET_CHARS: return "IOCTL_SERIAL_GET_CHARS";
case IOCTL_SERIAL_SET_DTR: return "IOCTL_SERIAL_SET_DTR";
case IOCTL_SERIAL_CLR_DTR: return "IOCTL_SERIAL_SET_DTR";
case IOCTL_SERIAL_RESET_DEVICE: return "IOCTL_SERIAL_RESET_DEVICE";
case IOCTL_SERIAL_SET_RTS: return "IOCTL_SERIAL_SET_RTS";
case IOCTL_SERIAL_CLR_RTS: return "IOCTL_SERIAL_CLR_RTS";
case IOCTL_SERIAL_SET_XOFF: return "IOCTL_SERIAL_SET_XOFF";
case IOCTL_SERIAL_SET_XON: return "IOCTL_SERIAL_SET_XON";
case IOCTL_SERIAL_SET_BREAK_ON: return "IOCTL_SERIAL_SET_BREAK_ON";
case IOCTL_SERIAL_SET_BREAK_OFF: return "IOCTL_SERIAL_SET_BREAK_OFF";
case IOCTL_SERIAL_SET_QUEUE_SIZE: return "IOCTL_SERIAL_SET_QUEUE_SIZE";
case IOCTL_SERIAL_GET_WAIT_MASK: return "IOCTL_SERIAL_GET_WAIT_MASK";
case IOCTL_SERIAL_SET_WAIT_MASK: return "IOCTL_SERIAL_SET_WAIT_MASK";
case IOCTL_SERIAL_WAIT_ON_MASK: return "IOCTL_SERIAL_WAIT_ON_MASK";
case IOCTL_SERIAL_IMMEDIATE_CHAR: return "IOCTL_SERIAL_IMMEDIATE_CHAR";
case IOCTL_SERIAL_PURGE: return "IOCTL_SERIAL_PURGE";
case IOCTL_SERIAL_GET_HANDFLOW: return "IOCTL_SERIAL_GET_HANDFLOW";
case IOCTL_SERIAL_SET_HANDFLOW: return "IOCTL_SERIAL_SET_HANDFLOW";
case IOCTL_SERIAL_GET_MODEMSTATUS: return "IOCTL_SERIAL_GET_MODEMSTATUS";
case IOCTL_SERIAL_GET_DTRRTS: return "IOCTL_SERIAL_GET_DTRRTS";
case IOCTL_SERIAL_GET_COMMSTATUS: return "IOCTL_SERIAL_GET_COMMSTATUS";
case IOCTL_SERIAL_GET_PROPERTIES: return "IOCTL_SERIAL_GET_PROPERTIES";
case IOCTL_SERIAL_XOFF_COUNTER: return "IOCTL_SERIAL_XOFF_COUNTER";
case IOCTL_SERIAL_LSRMST_INSERT: return "IOCTL_SERIAL_LSRMST_INSERT";
case IOCTL_SERIAL_CONFIG_SIZE: return "IOCTL_SERIAL_CONFIG_SIZE";
case IOCTL_SERIAL_GET_STATS: return "IOCTL_SERIAL_GET_STATS";
case IOCTL_SERIAL_CLEAR_STATS: return "IOCTL_SERIAL_CLEAR_STATS";
default: return "UnKnown ioctl";
}
}
#define HID_REQ_GET_REPORT 0x01
#define HID_REQ_GET_IDLE 0x02
#define HID_REQ_GET_PROTOCOL 0x03
#define HID_REQ_SET_REPORT 0x09
#define HID_REQ_SET_IDLE 0x0A
#define HID_REQ_SET_PROTOCOL 0x0B
/*
#define STOP_BIT_1 0
#define STOP_BITS_1_5 1
#define STOP_BITS_2 2
#define NO_PARITY 0
#define ODD_PARITY 1
#define EVEN_PARITY 2
#define MARK_PARITY 3
#define SPACE_PARITY 4
*/
NTSTATUS
SerialSetBaudRateAndLineControl(
IN PDEVICE_EXTENSION deviceExtension,
IN ULONG NewBaudRate,
IN PSERIAL_LINE_CONTROL NewSettings
)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG WrittenLen;
UCHAR FeatureBuf[5];
UCHAR config;
//do somthing
DbgPrint("BaudRate: %d\n",NewBaudRate);
if(NewBaudRate == 0)
NewBaudRate = deviceExtension->BaudRate;
if(NewSettings == NULL)
NewSettings = &deviceExtension->SerialLineControl;
DbgPrint("Serial: SerialSetLineControl(%wZ, Settings { %lu %lu %lu })\n",
&deviceExtension->DosName, NewSettings->StopBits, NewSettings->Parity, NewSettings->WordLength);
*((ULONG *)FeatureBuf) = NewBaudRate;
//cypress_m8.c
config = 0; // reset config byte
config |= NewSettings->WordLength-5; // assign data bits in 2 bit space ( max 3 )
/* 1 bit gap */
config |= ((NewSettings->StopBits ? 1 : 0) << 3); // assign stop bits in 1 bit space
config |= ((NewSettings->Parity > 0) << 4); // assign parity flag in 1 bit space
config |= ((NewSettings->Parity&1) << 5); // assign parity type in 1 bit space
/* 1 bit gap */
//config |= (reset << 7);
FeatureBuf[4] = config;
Status = UsbDoControlTransfer(
deviceExtension->DeviceObject,
URB_FUNCTION_CLASS_INTERFACE,
USBD_SHORT_TRANSFER_OK,
HID_REQ_SET_REPORT,
0x0300,//Report Type(01 Input 02 Output 03 Feature) and Report ID
0,
5,
FeatureBuf,
&WrittenLen);
DbgPrint("FeatureBuf: %02x %02x %02x %02x %02x\n",
FeatureBuf[0],
FeatureBuf[1],
FeatureBuf[2],
FeatureBuf[3],
FeatureBuf[4]);
FeatureBuf[0] = FeatureBuf[1] = FeatureBuf[2] = FeatureBuf[3] = FeatureBuf[4] = 0;
Status = UsbDoControlTransfer(
deviceExtension->DeviceObject,
URB_FUNCTION_CLASS_INTERFACE,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
HID_REQ_GET_REPORT,
0x0300,//Report Type(01 Input 02 Output 03 Feature) and Report ID
0,
5,
FeatureBuf,
&WrittenLen);
DbgPrint("FeatureBuf: %02x %02x %02x %02x %02x\n",
FeatureBuf[0],
FeatureBuf[1],
FeatureBuf[2],
FeatureBuf[3],
FeatureBuf[4]);
if (NT_SUCCESS(Status))
{
deviceExtension->BaudRate = NewBaudRate;
deviceExtension->SerialLineControl = *NewSettings;
}
return Status;
}
NTSTATUS
SerialSetLineControl(
IN PDEVICE_EXTENSION DeviceExtension,
IN PSERIAL_LINE_CONTROL NewSettings)
{
NTSTATUS Status = STATUS_SUCCESS;
ASSERT(DeviceExtension);
ASSERT(NewSettings);
//do somthing
if (NT_SUCCESS(Status))
DeviceExtension->SerialLineControl = *NewSettings;
return Status;
}
static BOOLEAN
SerialClearPerfStats(
IN PDEVICE_EXTENSION DeviceExtension)
{
ASSERT(DeviceExtension);
RtlZeroMemory(&DeviceExtension->SerialPerfStats, sizeof(SERIALPERF_STATS));
DeviceExtension->BreakInterruptErrorCount = 0;
return TRUE;
}
static BOOLEAN
SerialGetPerfStats(IN PIRP pIrp)
{
PDEVICE_EXTENSION pDeviceExtension;
ASSERT(pIrp);
pDeviceExtension = (PDEVICE_EXTENSION)
IoGetCurrentIrpStackLocation(pIrp)->DeviceObject->DeviceExtension;
/*
* we assume buffer is big enough to hold SerialPerfStats structure
* caller must verify this
*/
RtlCopyMemory(
pIrp->AssociatedIrp.SystemBuffer,
&pDeviceExtension->SerialPerfStats,
sizeof(SERIALPERF_STATS)
);
return TRUE;
}
static NTSTATUS
SerialGetCommProp(
OUT PSERIAL_COMMPROP pCommProp,
IN PDEVICE_EXTENSION DeviceExtension)
{
ASSERT(pCommProp);
RtlZeroMemory(pCommProp, sizeof(SERIAL_COMMPROP));
pCommProp->PacketLength = sizeof(SERIAL_COMMPROP);
pCommProp->PacketVersion = 2;
pCommProp->ServiceMask = SERIAL_SP_SERIALCOMM;
pCommProp->MaxTxQueue = pCommProp->CurrentTxQueue = DeviceExtension->OutputBuffer.Length - 1;
pCommProp->MaxRxQueue = pCommProp->CurrentRxQueue = DeviceExtension->InputBuffer.Length - 1;
pCommProp->ProvSubType = SERIAL_SP_RS232;
pCommProp->ProvCapabilities = SERIAL_PCF_DTRDSR | SERIAL_PCF_INTTIMEOUTS | SERIAL_PCF_PARITY_CHECK
| SERIAL_PCF_RTSCTS | SERIAL_PCF_SETXCHAR | SERIAL_PCF_SPECIALCHARS | SERIAL_PCF_TOTALTIMEOUTS
| SERIAL_PCF_XONXOFF;
pCommProp->SettableParams = SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_HANDSHAKING
| SERIAL_SP_PARITY | SERIAL_SP_PARITY_CHECK | SERIAL_SP_STOPBITS;
/* SettableBaud is related to Uart type */
pCommProp->SettableBaud = SERIAL_BAUD_075 | SERIAL_BAUD_110 | SERIAL_BAUD_134_5
| SERIAL_BAUD_150 | SERIAL_BAUD_300 | SERIAL_BAUD_600 | SERIAL_BAUD_1200
| SERIAL_BAUD_1800 | SERIAL_BAUD_2400 | SERIAL_BAUD_4800 | SERIAL_BAUD_7200
| SERIAL_BAUD_9600 | SERIAL_BAUD_USER;
pCommProp->MaxBaud = SERIAL_BAUD_USER;
pCommProp->SettableData = SERIAL_DATABITS_5 | SERIAL_DATABITS_6 | SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
pCommProp->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;
pCommProp->ProvSpec2 = 0; /* Size of provider-specific data */
return STATUS_SUCCESS;
}
static NTSTATUS
SerialGetCommStatus(
OUT PSERIAL_STATUS pSerialStatus,
IN PDEVICE_EXTENSION DeviceExtension)
{
KIRQL Irql;
ASSERT(pSerialStatus);
RtlZeroMemory(pSerialStatus, sizeof(SERIAL_STATUS));
pSerialStatus->Errors = 0;
if (DeviceExtension->BreakInterruptErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_BREAK;
if (DeviceExtension->SerialPerfStats.FrameErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_FRAMING;
if (DeviceExtension->SerialPerfStats.SerialOverrunErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_OVERRUN;
if (DeviceExtension->SerialPerfStats.BufferOverrunErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_QUEUEOVERRUN;
if (DeviceExtension->SerialPerfStats.ParityErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_PARITY;
pSerialStatus->HoldReasons = 0; /* FIXME */
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
pSerialStatus->AmountInInQueue = (DeviceExtension->InputBuffer.WritePosition + DeviceExtension->InputBuffer.Length
- DeviceExtension->InputBuffer.ReadPosition) % DeviceExtension->InputBuffer.Length;
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
//KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
//pSerialStatus->AmountInOutQueue = (DeviceExtension->OutputBuffer.WritePosition + DeviceExtension->OutputBuffer.Length
// - DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length;
//KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
pSerialStatus->AmountInOutQueue = DeviceExtension->TotalCharsQueued;
pSerialStatus->EofReceived = FALSE; /* always FALSE */
pSerialStatus->WaitForImmediate = FALSE; /* always FALSE */
return STATUS_SUCCESS;
}
NTSTATUS
USB2COM_ProcessIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch table handler for IRP_MJ_DEVICE_CONTROL;
Handle DeviceIoControl() calls from User mode
Arguments:
DeviceObject - pointer to the FDO for this instance of the 82930 device.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus;
ULONG length=0;
PUCHAR pch;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
USB2COM_KdPrint( DBGLVL_DEFAULT,("IRP_MJ_DEVICE_CONTROL\n"));
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
deviceExtension = DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// get pointers and lengths of the caller's (user's) IO buffer
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
USB2COM_KdPrint( DBGLVL_DEFAULT,("IoControl: %s\n",SerialGetIoctlName(ioControlCode)));
if(ioControlCode == IOCTL_USB2COM_RESET_PIPE
|| ioControlCode == IOCTL_USB2COM_GET_CONFIG_DESCRIPTOR
|| ioControlCode == IOCTL_USB2COM_RESET_DEVICE
)
{
// 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,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -