1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/legacy/stream/driver.c 5 * PURPOSE: WDM Codec Class Driver 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "stream.h" 10 11 NTSTATUS 12 NTAPI 13 StreamClassAddDevice( 14 IN PDRIVER_OBJECT DriverObject, 15 IN PDEVICE_OBJECT PhysicalDeviceObject) 16 { 17 PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension; 18 PDEVICE_OBJECT DeviceObject, LowerDeviceObject; 19 PSTREAM_DEVICE_EXTENSION DeviceExtension; 20 PKSOBJECT_CREATE_ITEM ItemList; 21 NTSTATUS Status; 22 23 /* Fetch driver object extension */ 24 DriverObjectExtension = IoGetDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice); 25 if (!DriverObjectExtension) 26 { 27 /* Failed to get driver extension */ 28 return STATUS_DEVICE_DOES_NOT_EXIST; 29 } 30 /* Allocate Create Item */ 31 ItemList = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM)); 32 if (!ItemList) 33 { 34 /* Failed to allocated Create Item */ 35 return STATUS_INSUFFICIENT_RESOURCES; 36 } 37 38 /* Create the FDO */ 39 Status = IoCreateDevice(DriverObject, DriverObjectExtension->Data.DeviceExtensionSize + sizeof(STREAM_DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, 0, &DeviceObject); 40 if (!NT_SUCCESS(Status)) 41 { 42 /* Failed to create the FDO */ 43 ExFreePool(ItemList); 44 return Status; 45 } 46 47 /* Attach to device stack */ 48 LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); 49 if (!LowerDeviceObject) 50 { 51 /* Failed to attach */ 52 IoDeleteDevice(DeviceObject); 53 ExFreePool(ItemList); 54 return STATUS_UNSUCCESSFUL; 55 } 56 57 /* Zero Create item */ 58 RtlZeroMemory(ItemList, sizeof(KSOBJECT_CREATE_ITEM)); 59 /* Setup object class */ 60 RtlInitUnicodeString(&ItemList->ObjectClass, L"GLOBAL"); 61 /* Setup CreateDispatch routine */ 62 ItemList->Create = StreamClassCreateFilter; 63 64 /* Get device extension */ 65 DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 66 /* Zero device extension */ 67 RtlZeroMemory(DeviceExtension, sizeof(STREAM_DEVICE_EXTENSION)); 68 /* Initialize Ks streaming */ 69 Status = KsAllocateDeviceHeader(&DeviceExtension->Header, 1, ItemList); 70 if (!NT_SUCCESS(Status)) 71 { 72 /* Cleanup resources */ 73 IoDetachDevice(LowerDeviceObject); 74 IoDeleteDevice(DeviceObject); 75 ExFreePool(ItemList); 76 return Status; 77 } 78 79 /* Store lower device object */ 80 DeviceExtension->LowerDeviceObject = LowerDeviceObject; 81 82 /* Store physical device object */ 83 DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; 84 /* Store driver object extension */ 85 DeviceExtension->DriverExtension = DriverObjectExtension; 86 /* Initialize memory list */ 87 InitializeListHead(&DeviceExtension->MemoryResourceList); 88 /* Setup device extension */ 89 DeviceExtension->DeviceExtension = (PVOID) (DeviceExtension + 1); 90 /* Init interrupt dpc */ 91 KeInitializeDpc(&DeviceExtension->InterruptDpc, StreamClassInterruptDpc, (PVOID)DeviceExtension); 92 93 /* Set device transfer method */ 94 DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; 95 /* Clear init flag */ 96 DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; 97 98 return Status; 99 } 100 101 /* 102 *@implemented 103 */ 104 NTSTATUS 105 STREAMAPI 106 StreamClassRegisterAdapter( 107 IN PVOID Argument1, 108 IN PVOID Argument2, 109 IN PHW_INITIALIZATION_DATA HwInitializationData) 110 { 111 NTSTATUS Status; 112 PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension; 113 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1; 114 115 /* Allocate driver extension */ 116 Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice, sizeof(STREAM_CLASS_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension); 117 if (!NT_SUCCESS(Status)) 118 { 119 /* Failed to allocate */ 120 return STATUS_INSUFFICIENT_RESOURCES; 121 } 122 123 /* Zero driver object extension */ 124 RtlZeroMemory(DriverObjectExtension, sizeof(STREAM_CLASS_DRIVER_EXTENSION)); 125 126 /* copy HwInitializationData */ 127 RtlCopyMemory(&DriverObjectExtension->Data, HwInitializationData, sizeof(HW_INITIALIZATION_DATA)); 128 129 /* Setup device init methods */ 130 DriverObject->DriverExtension->AddDevice = StreamClassAddDevice; 131 DriverObject->DriverUnload = KsNullDriverUnload; 132 133 /* Setup irp handlers */ 134 DriverObject->MajorFunction[IRP_MJ_PNP] = StreamClassPnp; 135 DriverObject->MajorFunction[IRP_MJ_POWER] = StreamClassPower; 136 DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = StreamClassSystemControl; 137 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = StreamClassCleanup; 138 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = StreamClassFlushBuffers; 139 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StreamClassDeviceControl; 140 141 /* Let Ks handle these */ 142 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE); 143 KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE); 144 145 return STATUS_SUCCESS; 146 } 147 148 /* 149 *@implemented 150 */ 151 152 VOID 153 NTAPI 154 StreamClassReenumerateStreams( 155 IN PVOID HwDeviceExtension, 156 IN ULONG StreamDescriptorSize) 157 { 158 HW_STREAM_REQUEST_BLOCK_EXT RequestBlock; 159 PSTREAM_DEVICE_EXTENSION DeviceExtension; 160 PHW_STREAM_DESCRIPTOR StreamDescriptor; 161 162 if (!HwDeviceExtension || !StreamDescriptorSize) 163 return; 164 165 StreamDescriptor = ExAllocatePool(NonPagedPool, StreamDescriptorSize); 166 if (!StreamDescriptor) 167 return; 168 169 /* Zero stream descriptor */ 170 RtlZeroMemory(StreamDescriptor, StreamDescriptorSize); 171 172 /* Get our DeviceExtension */ 173 DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION)); 174 ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension); 175 176 177 /* Zero RequestBlock */ 178 RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT)); 179 180 /* Setup get stream info struct */ 181 RequestBlock.Block.SizeOfThisPacket = sizeof(HW_STREAM_REQUEST_BLOCK); 182 RequestBlock.Block.Command = SRB_GET_STREAM_INFO; 183 RequestBlock.Block.CommandData.StreamBuffer = StreamDescriptor; 184 KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE); 185 186 /* FIXME SYNCHRONIZATION */ 187 188 /* Send the request */ 189 DeviceExtension->DriverExtension->Data.HwReceivePacket ((PHW_STREAM_REQUEST_BLOCK)&RequestBlock); 190 191 /* Is the device already completed? */ 192 if (RequestBlock.Block.Status == STATUS_PENDING) 193 { 194 /* Request is pending, wait for result */ 195 KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL); 196 } 197 198 if (!NT_SUCCESS(RequestBlock.Block.Status)) 199 { 200 /* Release Stream descriptor */ 201 ExFreePool(StreamDescriptor); 202 } 203 else 204 { 205 if (DeviceExtension->StreamDescriptor) 206 { 207 /* Release old stream descriptor */ 208 ExFreePool(DeviceExtension->StreamDescriptor); 209 } 210 211 /* Store stream descriptor */ 212 DeviceExtension->StreamDescriptor = StreamDescriptor; 213 DeviceExtension->StreamDescriptorSize = StreamDescriptorSize; 214 } 215 216 } 217 218 /* 219 *@implemented 220 */ 221 222 VOID 223 NTAPI 224 StreamClassDebugAssert( 225 IN PCHAR File, 226 IN ULONG Line, 227 IN PCHAR AssertText, 228 IN ULONG AssertValue) 229 { 230 #if DBG 231 DbgBreakPoint(); 232 #endif 233 } 234 235 /* 236 *@implemented 237 */ 238 VOID 239 __cdecl 240 StreamClassDebugPrint( 241 IN STREAM_DEBUG_LEVEL DebugPrintLevel, 242 IN PCCHAR DebugMessage, 243 ...) 244 { 245 #if DBG 246 va_list ap; 247 248 if (DebugPrintLevel <=STREAMDEBUG_LEVEL) 249 { 250 va_start(ap, DebugMessage); 251 252 DbgPrint(DebugMessage, ap); 253 254 va_end(ap); 255 } 256 #endif 257 258 } 259 260 /* 261 *@unimplemented 262 */ 263 VOID 264 __cdecl 265 StreamClassDeviceNotification( 266 IN STREAM_MINIDRIVER_DEVICE_NOTIFICATION_TYPE NotificationType, 267 IN PVOID HwDeviceExtension, 268 IN PHW_STREAM_REQUEST_BLOCK pSrb, 269 IN PKSEVENT_ENTRY EventEntry, 270 IN GUID *EventSet, 271 IN ULONG EventId) 272 { 273 PHW_STREAM_REQUEST_BLOCK_EXT RequestBlock; 274 if (NotificationType == DeviceRequestComplete) 275 { 276 RequestBlock = (PHW_STREAM_REQUEST_BLOCK_EXT)pSrb; 277 278 KeSetEvent(&RequestBlock->Event, 0, FALSE); 279 return; 280 } 281 282 UNIMPLEMENTED; 283 } 284 285 /* 286 *@implemented 287 */ 288 PVOID 289 STREAMAPI 290 StreamClassGetDmaBuffer( 291 IN PVOID HwDeviceExtension) 292 { 293 PSTREAM_DEVICE_EXTENSION DeviceExtension; 294 295 /* Get our DeviceExtension */ 296 DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION)); 297 ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension); 298 299 return DeviceExtension->DmaCommonBuffer; 300 } 301 302 NTSTATUS 303 NTAPI 304 StreamClassRWCompletion( 305 IN PDEVICE_OBJECT DeviceObject, 306 IN PIRP Irp, 307 IN PVOID Context) 308 { 309 PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context; 310 311 IoStatusBlock->Information = Irp->IoStatus.Information; 312 IoStatusBlock->Status = Irp->IoStatus.Status; 313 314 return STATUS_SUCCESS; 315 } 316 317 /* 318 *@implemented 319 */ 320 BOOLEAN 321 STREAMAPI 322 StreamClassReadWriteConfig( 323 IN PVOID HwDeviceExtension, 324 IN BOOLEAN Read, 325 IN PVOID Buffer, 326 IN ULONG OffSet, 327 IN ULONG Length) 328 { 329 PIRP Irp; 330 ULONG MajorFunction; 331 KEVENT Event; 332 PSTREAM_DEVICE_EXTENSION DeviceExtension; 333 LARGE_INTEGER Offset; 334 IO_STATUS_BLOCK StatusBlock; 335 NTSTATUS Status; 336 337 /* Get our DeviceExtension */ 338 DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION)); 339 ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension); 340 341 if (Read) 342 { 343 /* Zero input buffer */ 344 RtlZeroMemory(Buffer, Length); 345 } 346 347 /* Set request type */ 348 MajorFunction = (Read ? IRP_MJ_READ : IRP_MJ_WRITE); 349 350 /* Initialize event */ 351 KeInitializeEvent(&Event, NotificationEvent, FALSE); 352 353 /* Set offset */ 354 Offset.QuadPart = OffSet; 355 356 /* Pre-init status block */ 357 StatusBlock.Status = STATUS_NOT_SUPPORTED; 358 359 /* Create Irp */ 360 Irp = IoBuildSynchronousFsdRequest(MajorFunction, 361 DeviceExtension->LowerDeviceObject, /* Verify */ 362 Buffer, 363 Length, 364 &Offset, 365 &Event, 366 &StatusBlock); 367 368 if (!Irp) 369 { 370 /* Failed to allocate memory */ 371 return FALSE; 372 } 373 374 /* Setup a completion routine */ 375 IoSetCompletionRoutine(Irp, StreamClassRWCompletion, (PVOID)&Event, TRUE, TRUE, TRUE); 376 377 /* Call driver */ 378 Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp); 379 380 if (Status == STATUS_PENDING) 381 { 382 /* Request is pending, wait for result */ 383 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 384 /* Fetch result */ 385 Status = StatusBlock.Status; 386 } 387 388 if (!NT_SUCCESS(Status)) 389 { 390 return FALSE; 391 } 392 393 /* FIXME Handle Length != InputLength */ 394 return TRUE; 395 } 396