Saveliy Tretiakov <saveliyt@mail.ru>
- Only one file may be open on a port at any given time
- Implemented IOCTL_SERIAL_GET_STATS and IOCTL_SERIAL_CLEAR_STATS
Modified: trunk/reactos/drivers/dd/serial/close.c
Modified: trunk/reactos/drivers/dd/serial/create.c
Modified: trunk/reactos/drivers/dd/serial/devctrl.c
Modified: trunk/reactos/drivers/dd/serial/misc.c
Modified: trunk/reactos/drivers/dd/serial/pnp.c
Modified: trunk/reactos/drivers/dd/serial/rw.c
Modified: trunk/reactos/drivers/dd/serial/serial.h

Modified: trunk/reactos/drivers/dd/serial/close.c
--- trunk/reactos/drivers/dd/serial/close.c	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/close.c	2005-03-16 19:24:41 UTC (rev 14139)
@@ -16,7 +16,14 @@
 	IN PDEVICE_OBJECT DeviceObject,
 	IN PIRP Irp)
 {
+	PSERIAL_DEVICE_EXTENSION pDeviceExtension;
+	
 	DPRINT("Serial: IRP_MJ_CLOSE\n");
-	IoCompleteRequest(Irp, IO_NO_INCREMENT);
+	pDeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+	pDeviceExtension->IsOpened = FALSE;
+	
+	Irp->IoStatus.Information = 0;
+	Irp->IoStatus.Status = STATUS_SUCCESS;
+ 	IoCompleteRequest(Irp, IO_NO_INCREMENT);
 	return STATUS_SUCCESS;
 }

Modified: trunk/reactos/drivers/dd/serial/create.c
--- trunk/reactos/drivers/dd/serial/create.c	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/create.c	2005-03-16 19:24:41 UTC (rev 14139)
@@ -41,7 +41,15 @@
 		goto ByeBye;
 	}
 	
+	if(DeviceExtension->IsOpened)
+	{
+		DPRINT("Serial: COM%lu is already opened", DeviceExtension->ComPort);
+		Status = STATUS_ACCESS_DENIED;
+		goto ByeBye;
+	}
+	
 	DPRINT("Serial: open COM%lu: successfull\n", DeviceExtension->ComPort);
+	DeviceExtension->IsOpened = TRUE;
 	Status = STATUS_SUCCESS;
 	
 ByeBye:

Modified: trunk/reactos/drivers/dd/serial/devctrl.c
--- trunk/reactos/drivers/dd/serial/devctrl.c	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/devctrl.c	2005-03-16 19:24:41 UTC (rev 14139)
@@ -145,6 +145,32 @@
 	return Status;
 }
 
+BOOL
+SerialClearPerfStats(
+	IN PSERIALPERF_STATS pSerialPerfStats)
+{
+	RtlZeroMemory(pSerialPerfStats, sizeof(SERIALPERF_STATS));
+	return TRUE;
+}
+
+BOOL
+SerialGetPerfStats(IN PIRP pIrp)
+{
+	PSERIAL_DEVICE_EXTENSION pDeviceExtension;
+	pDeviceExtension = (PSERIAL_DEVICE_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;
+}
+
 NTSTATUS STDCALL
 SerialDeviceControl(
 	IN PDEVICE_OBJECT DeviceObject,
@@ -175,9 +201,12 @@
 	{
 		case IOCTL_SERIAL_CLEAR_STATS:
 		{
-			/* FIXME */
-			DPRINT1("Serial: IOCTL_SERIAL_CLEAR_STATS not implemented.\n");
-			Status = STATUS_NOT_IMPLEMENTED;
+			DPRINT("Serial: IOCTL_SERIAL_CLEAR_STATS\n");
+			KeSynchronizeExecution(
+				DeviceExtension->Interrupt,
+				(PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats,
+				&DeviceExtension->SerialPerfStats);
+			Status = STATUS_SUCCESS;
 			break;
 		}
 		case IOCTL_SERIAL_CLR_DTR:
@@ -320,9 +349,24 @@
 		}
 		case IOCTL_SERIAL_GET_STATS:
 		{
-			/* FIXME */
-			DPRINT1("Serial: IOCTL_SERIAL_GET_STATS not implemented.\n");
-			Status = STATUS_NOT_IMPLEMENTED;
+			DPRINT1("Serial: IOCTL_SERIAL_GET_STATS\n");
+			if (LengthOut < sizeof(SERIALPERF_STATS))
+			{
+				DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n");
+				Status = STATUS_BUFFER_TOO_SMALL;
+			}
+			else if (Buffer == NULL)
+			{
+				DPRINT("Serial: return STATUS_INVALID_PARAMETER\n");
+				Status = STATUS_INVALID_PARAMETER;
+			}
+			else
+			{
+				KeSynchronizeExecution(DeviceExtension->Interrupt,
+					(PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp);
+					Status = STATUS_SUCCESS;
+					Information = sizeof(SERIALPERF_STATS);
+			}
 			break;
 		}
 		case IOCTL_SERIAL_GET_TIMEOUTS:

Modified: trunk/reactos/drivers/dd/serial/misc.c
--- trunk/reactos/drivers/dd/serial/misc.c	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/misc.c	2005-03-16 19:24:41 UTC (rev 14139)
@@ -105,6 +105,7 @@
 			if (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DR)
 			{
 				DPRINT1("Serial: Byte received: 0x%x\n", READ_PORT_UCHAR(SER_RBR(ComPortBase)));
+				DeviceExtension->SerialPerfStats.ReceivedCount++;
 				return TRUE;
 			}
 			break;

Modified: trunk/reactos/drivers/dd/serial/pnp.c
--- trunk/reactos/drivers/dd/serial/pnp.c	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/pnp.c	2005-03-16 19:24:41 UTC (rev 14139)
@@ -219,6 +219,7 @@
 {
 	ULONG MinorFunction;
 	PIO_STACK_LOCATION Stack;
+	ULONG Information = 0;
 	PDEVICE_OBJECT LowerDevice;
 	NTSTATUS Status;
 	
@@ -236,8 +237,6 @@
 			Status = ForwardIrpAndWait(DeviceObject, Irp);
 			if (NT_SUCCESS(Status))
 				Status = SerialPnpStartDevice(DeviceObject, Irp);
-			Irp->IoStatus.Status = Status;
-			IoCompleteRequest(Irp, IO_NO_INCREMENT);
 			break;
 		}
 		/* IRP_MN_QUERY_STOP_DEVICE (FIXME: required) */
@@ -270,6 +269,9 @@
 			break;
 		}
 	}
-
+	
+	Irp->IoStatus.Information = Information;
+	Irp->IoStatus.Status = Status;
+	IoCompleteRequest(Irp, IO_NO_INCREMENT);
 	return Status;
 }

Modified: trunk/reactos/drivers/dd/serial/rw.c
--- trunk/reactos/drivers/dd/serial/rw.c	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/rw.c	2005-03-16 19:24:41 UTC (rev 14139)
@@ -80,6 +80,7 @@
 		while ((READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_TBE) == 0)
 			;
 		WRITE_PORT_UCHAR(SER_THR(ComPortBase), Buffer[i]);
+		DeviceExtension->SerialPerfStats.TransmittedCount++;
 	}
 	IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
 	

Modified: trunk/reactos/drivers/dd/serial/serial.h
--- trunk/reactos/drivers/dd/serial/serial.h	2005-03-16 17:30:11 UTC (rev 14138)
+++ trunk/reactos/drivers/dd/serial/serial.h	2005-03-16 19:24:41 UTC (rev 14139)
@@ -67,6 +67,9 @@
 	SERIAL_LINE_CONTROL SerialLineControl;
 	ULONG WaitMask;
 	
+	SERIALPERF_STATS SerialPerfStats;
+	BOOL IsOpened;
+	
 	/* Current values */
 	UCHAR IER; /* Base+1, Interrupt Enable Register */
 	UCHAR MCR; /* Base+4, Modem Control Register */