1 /* 2 * PROJECT: ReactOS Serial mouse driver 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/input/sermouse/fdo.c 5 * PURPOSE: IRP_MJ_PNP operations for FDOs 6 * PROGRAMMERS: Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org) 7 */ 8 9 #include "sermouse.h" 10 11 #include <debug.h> 12 13 NTSTATUS NTAPI 14 SermouseAddDevice( 15 IN PDRIVER_OBJECT DriverObject, 16 IN PDEVICE_OBJECT Pdo) 17 { 18 PSERMOUSE_DRIVER_EXTENSION DriverExtension; 19 PDEVICE_OBJECT Fdo; 20 PSERMOUSE_DEVICE_EXTENSION DeviceExtension = NULL; 21 NTSTATUS Status; 22 23 TRACE_(SERMOUSE, "SermouseAddDevice called. Pdo = 0x%p\n", Pdo); 24 25 if (Pdo == NULL) 26 return STATUS_SUCCESS; 27 28 /* Create new device object */ 29 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); 30 Status = IoCreateDevice( 31 DriverObject, 32 sizeof(SERMOUSE_DEVICE_EXTENSION), 33 NULL, 34 FILE_DEVICE_SERIAL_MOUSE_PORT, 35 FILE_DEVICE_SECURE_OPEN, 36 TRUE, 37 &Fdo); 38 if (!NT_SUCCESS(Status)) 39 { 40 WARN_(SERMOUSE, "IoCreateDevice() failed with status 0x%08lx\n", Status); 41 goto cleanup; 42 } 43 44 DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)Fdo->DeviceExtension; 45 RtlZeroMemory(DeviceExtension, sizeof(SERMOUSE_DEVICE_EXTENSION)); 46 DeviceExtension->MouseType = mtNone; 47 DeviceExtension->PnpState = dsStopped; 48 DeviceExtension->DriverExtension = DriverExtension; 49 KeInitializeEvent(&DeviceExtension->StopWorkerThreadEvent, NotificationEvent, FALSE); 50 Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice); 51 if (!NT_SUCCESS(Status)) 52 { 53 WARN_(SERMOUSE, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); 54 goto cleanup; 55 } 56 if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE) 57 Fdo->Flags |= DO_POWER_PAGABLE; 58 if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO) 59 Fdo->Flags |= DO_BUFFERED_IO; 60 if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO) 61 Fdo->Flags |= DO_DIRECT_IO; 62 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 63 64 return STATUS_SUCCESS; 65 66 cleanup: 67 if (DeviceExtension) 68 { 69 if (DeviceExtension->LowerDevice) 70 IoDetachDevice(DeviceExtension->LowerDevice); 71 } 72 if (Fdo) 73 { 74 IoDeleteDevice(Fdo); 75 } 76 return Status; 77 } 78 79 NTSTATUS NTAPI 80 SermouseStartDevice( 81 IN PDEVICE_OBJECT DeviceObject, 82 IN PIRP Irp) 83 { 84 PSERMOUSE_DEVICE_EXTENSION DeviceExtension; 85 SERMOUSE_MOUSE_TYPE MouseType; 86 NTSTATUS Status; 87 88 DeviceExtension = (PSERMOUSE_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 89 90 ASSERT(DeviceExtension->PnpState == dsStopped); 91 ASSERT(DeviceExtension->LowerDevice); 92 MouseType = SermouseDetectLegacyDevice(DeviceExtension->LowerDevice); 93 if (MouseType == mtNone) 94 { 95 WARN_(SERMOUSE, "No mouse connected to Fdo %p\n", 96 DeviceExtension->LowerDevice); 97 return STATUS_DEVICE_NOT_CONNECTED; 98 } 99 100 switch (MouseType) 101 { 102 case mtMicrosoft: 103 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE; 104 DeviceExtension->AttributesInformation.NumberOfButtons = 2; 105 break; 106 case mtLogitech: 107 DeviceExtension->AttributesInformation.MouseIdentifier = MOUSE_SERIAL_HARDWARE; 108 DeviceExtension->AttributesInformation.NumberOfButtons = 3; 109 break; 110 case mtWheelZ: 111 DeviceExtension->AttributesInformation.MouseIdentifier = WHEELMOUSE_SERIAL_HARDWARE; 112 DeviceExtension->AttributesInformation.NumberOfButtons = 3; 113 break; 114 default: 115 WARN_(SERMOUSE, "Unknown mouse type 0x%lx\n", MouseType); 116 ASSERT(FALSE); 117 return STATUS_UNSUCCESSFUL; 118 } 119 120 if (DeviceExtension->DriverExtension->NumberOfButtons != 0) 121 /* Override the number of buttons */ 122 DeviceExtension->AttributesInformation.NumberOfButtons = DeviceExtension->DriverExtension->NumberOfButtons; 123 124 DeviceExtension->AttributesInformation.SampleRate = 1200 / 8; 125 DeviceExtension->AttributesInformation.InputDataQueueLength = 1; 126 DeviceExtension->MouseType = MouseType; 127 DeviceExtension->PnpState = dsStarted; 128 129 /* Start read loop */ 130 Status = PsCreateSystemThread( 131 &DeviceExtension->WorkerThreadHandle, 132 (ACCESS_MASK)0L, 133 NULL, 134 NULL, 135 NULL, 136 SermouseDeviceWorker, 137 DeviceObject); 138 139 return Status; 140 } 141 142 NTSTATUS NTAPI 143 SermousePnp( 144 IN PDEVICE_OBJECT DeviceObject, 145 IN PIRP Irp) 146 { 147 ULONG MinorFunction; 148 PIO_STACK_LOCATION Stack; 149 ULONG_PTR Information = 0; 150 NTSTATUS Status; 151 152 Stack = IoGetCurrentIrpStackLocation(Irp); 153 MinorFunction = Stack->MinorFunction; 154 Information = Irp->IoStatus.Information; 155 156 switch (MinorFunction) 157 { 158 /* FIXME: do all these minor functions 159 IRP_MN_QUERY_REMOVE_DEVICE 0x1 160 IRP_MN_REMOVE_DEVICE 0x2 161 IRP_MN_CANCEL_REMOVE_DEVICE 0x3 162 IRP_MN_STOP_DEVICE 0x4 163 IRP_MN_QUERY_STOP_DEVICE 0x5 164 IRP_MN_CANCEL_STOP_DEVICE 0x6 165 IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7 166 IRP_MN_QUERY_INTERFACE (optional) 0x8 167 IRP_MN_QUERY_CAPABILITIES (optional) 0x9 168 IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xd 169 IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14 170 IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16 171 IRP_MN_SURPRISE_REMOVAL 0x17 172 */ 173 case IRP_MN_START_DEVICE: /* 0x0 */ 174 { 175 TRACE_(SERMOUSE, "IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); 176 /* Call lower driver */ 177 Status = ForwardIrpAndWait(DeviceObject, Irp); 178 if (NT_SUCCESS(Status)) 179 Status = SermouseStartDevice(DeviceObject, Irp); 180 break; 181 } 182 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */ 183 { 184 switch (Stack->Parameters.QueryDeviceRelations.Type) 185 { 186 case BusRelations: 187 { 188 PDEVICE_RELATIONS DeviceRelations = NULL; 189 TRACE_(SERMOUSE, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n"); 190 191 DeviceRelations = ExAllocatePoolWithTag(PagedPool, FIELD_OFFSET(DEVICE_RELATIONS, Objects), SERMOUSE_TAG); 192 if (!DeviceRelations) 193 { 194 WARN_(SERMOUSE, "ExAllocatePoolWithTag() failed\n"); 195 Status = STATUS_NO_MEMORY; 196 } 197 else 198 { 199 DeviceRelations->Count = 0; 200 Status = STATUS_SUCCESS; 201 Information = (ULONG_PTR)DeviceRelations; 202 } 203 break; 204 } 205 default: 206 { 207 TRACE_(SERMOUSE, "IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n", 208 Stack->Parameters.QueryDeviceRelations.Type); 209 return ForwardIrpAndForget(DeviceObject, Irp); 210 } 211 } 212 break; 213 } 214 default: 215 { 216 TRACE_(SERMOUSE, "IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction); 217 return ForwardIrpAndForget(DeviceObject, Irp); 218 } 219 } 220 221 Irp->IoStatus.Information = Information; 222 Irp->IoStatus.Status = Status; 223 IoCompleteRequest(Irp, IO_NO_INCREMENT); 224 return Status; 225 } 226