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

📄 ioctl.c

📁 usb to rs232 虚拟RS232串口驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

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