2007-07-08 17:31:55 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS Kernel Streaming
|
|
|
|
* FILE: drivers/wdm/audio/sysaudio/main.c
|
|
|
|
* PURPOSE: System Audio graph builder
|
|
|
|
* PROGRAMMER: Andrew Greenwood
|
|
|
|
*
|
|
|
|
* HISTORY:
|
|
|
|
* 8 Jul 07 Started basic implementation
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ntddk.h>
|
2009-01-26 10:08:17 +00:00
|
|
|
#include <ks.h>
|
2009-01-27 20:02:50 +00:00
|
|
|
#define YDEBUG
|
2007-07-08 17:31:55 +00:00
|
|
|
#include <debug.h>
|
2009-01-26 10:08:17 +00:00
|
|
|
//#include <dxsdk/mediaobj.h>
|
|
|
|
#include "sysaudio.h"
|
|
|
|
|
2009-02-10 16:28:24 +00:00
|
|
|
const GUID KSCATEGORY_AUDIO_DEVICE = {0xFBF6F530L, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
|
|
|
|
const GUID KSCATEGORY_PREFERRED_WAVEOUT_DEVICE = {0xD6C5066EL, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
|
|
|
|
const GUID KSCATEGORY_PREFERRED_WAVEIN_DEVICE = {0xD6C50671L, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
|
|
|
|
const GUID KSCATEGORY_PREFERRED_MIDIOUT_DEVICE = {0xD6C50674L, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
|
|
|
|
const GUID KS_CATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
|
|
|
|
const GUID GUID_DEVICE_INTERFACE_ARRIVAL = {0xCB3A4004L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}};
|
|
|
|
const GUID GUID_DEVICE_INTERFACE_REMOVAL = {0xCB3A4005L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}};
|
2009-01-26 10:08:17 +00:00
|
|
|
|
2009-01-27 20:02:50 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
SysAudio_Unload(IN PDRIVER_OBJECT DriverObject)
|
|
|
|
{
|
2009-01-27 20:02:50 +00:00
|
|
|
DPRINT1("SysAudio_Unload called\n");
|
2009-01-26 10:08:17 +00:00
|
|
|
}
|
2007-07-08 17:31:55 +00:00
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2009-01-26 10:08:17 +00:00
|
|
|
SysAudio_Pnp(
|
2007-07-08 17:31:55 +00:00
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
2009-01-26 10:08:17 +00:00
|
|
|
PIO_STACK_LOCATION IrpStack;
|
|
|
|
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
|
|
|
|
SYSAUDIODEVEXT *DeviceExtension;
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
DPRINT1("SysAudio_Pnp called\n");
|
2007-07-08 17:31:55 +00:00
|
|
|
|
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
|
|
|
|
|
|
|
|
if (IrpStack->MinorFunction == IRP_MN_REMOVE_DEVICE)
|
|
|
|
{
|
|
|
|
if (DeviceExtension->EchoCancelNotificationEntry)
|
|
|
|
IoUnregisterPlugPlayNotification(DeviceExtension->EchoCancelNotificationEntry);
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
if (DeviceExtension->KsAudioNotificationEntry)
|
|
|
|
IoUnregisterPlugPlayNotification(DeviceExtension->KsAudioNotificationEntry);
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
IoDeleteSymbolicLink(&SymlinkName);
|
|
|
|
}
|
2009-02-10 16:28:24 +00:00
|
|
|
else if (IrpStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
|
|
|
|
{
|
|
|
|
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
|
|
|
}
|
2009-01-26 10:08:17 +00:00
|
|
|
|
|
|
|
return KsDefaultDispatchPnp(DeviceObject, Irp);
|
2007-07-08 17:31:55 +00:00
|
|
|
}
|
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
NTSTATUS
|
2007-07-08 17:31:55 +00:00
|
|
|
NTAPI
|
2009-01-26 10:08:17 +00:00
|
|
|
DeviceInterfaceChangeCallback(
|
|
|
|
IN PVOID NotificationStructure,
|
|
|
|
IN PVOID Context)
|
2007-07-08 17:31:55 +00:00
|
|
|
{
|
2009-02-10 16:28:24 +00:00
|
|
|
DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event;
|
|
|
|
SYSAUDIODEVEXT *DeviceExtension = (SYSAUDIODEVEXT*)Context;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
|
|
|
|
|
|
|
|
if (IsEqualGUIDAligned(&Event->Event,
|
|
|
|
&GUID_DEVICE_INTERFACE_ARRIVAL))
|
|
|
|
{
|
|
|
|
/* a new device has arrived */
|
|
|
|
|
|
|
|
PFILE_OBJECT FileObject = NULL;
|
|
|
|
PDEVICE_OBJECT DeviceObject = NULL;
|
|
|
|
UNICODE_STRING DeviceName;
|
|
|
|
PKSAUDIO_DEVICE_ENTRY DeviceEntry;
|
|
|
|
|
|
|
|
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY));
|
|
|
|
if (!DeviceEntry)
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
|
|
|
if (!RtlCreateUnicodeString(&DeviceEntry->DeviceName, Event->SymbolicLinkName->Buffer))
|
|
|
|
{
|
|
|
|
ExFreePool(DeviceEntry);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 1 //HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
|
|
|
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\00000017");
|
|
|
|
#else
|
|
|
|
RtlInitUnicodeString(&DeviceName, Event->SymbolicLinkName->Buffer);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Status = IoGetDeviceObjectPointer(&DeviceName,
|
|
|
|
FILE_READ_DATA | FILE_WRITE_DATA,
|
|
|
|
&FileObject,
|
|
|
|
&DeviceObject);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ExFreePool(DeviceEntry);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
DeviceEntry->DeviceObject = DeviceObject;
|
|
|
|
DeviceEntry->FileObject = FileObject;
|
|
|
|
|
|
|
|
InsertTailList(&DeviceExtension->KsAudioDeviceList, &DeviceEntry->Entry);
|
|
|
|
DeviceExtension->NumberOfKsAudioDevices++;
|
|
|
|
|
|
|
|
DPRINT1("Successfully opened audio device\n");
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
else if (IsEqualGUIDAligned(&Event->Event,
|
|
|
|
&GUID_DEVICE_INTERFACE_REMOVAL))
|
|
|
|
{
|
|
|
|
DPRINT1("Remove interface to audio device!\n");
|
|
|
|
///FIXME
|
|
|
|
///
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UNICODE_STRING EventName, InterfaceGuid;
|
|
|
|
|
|
|
|
RtlStringFromGUID(&Event->Event, &EventName);
|
|
|
|
RtlStringFromGUID(&Event->InterfaceClassGuid, &InterfaceGuid);
|
|
|
|
DPRINT1("Unknown event: Event %wZ GUID %wZ\n", &EventName, &InterfaceGuid);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2007-07-08 17:31:55 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
DispatchCreate(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
DPRINT1("DispatchCreate\n");
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2009-01-27 20:02:50 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2007-07-08 17:31:55 +00:00
|
|
|
SysAudio_AddDevice(
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
|
|
|
{
|
2009-01-26 10:08:17 +00:00
|
|
|
NTSTATUS Status;
|
2007-07-08 17:31:55 +00:00
|
|
|
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio");
|
|
|
|
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\sysaudio");
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
2009-01-26 10:08:17 +00:00
|
|
|
PDEVICE_OBJECT NextDeviceObject;
|
|
|
|
KSOBJECT_CREATE_ITEM CreateItem;
|
|
|
|
SYSAUDIODEVEXT *DeviceExtension;
|
2009-01-27 20:02:50 +00:00
|
|
|
UNICODE_STRING SymbolicLink;
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-27 20:02:50 +00:00
|
|
|
DPRINT1("SysAudio_AddDevice called\n");
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
/* create the device */
|
|
|
|
Status = IoCreateDevice(DriverObject,
|
|
|
|
sizeof(SYSAUDIODEVEXT),
|
2007-07-08 17:31:55 +00:00
|
|
|
&DeviceName,
|
2009-01-26 10:08:17 +00:00
|
|
|
FILE_DEVICE_KS,
|
|
|
|
0,
|
2007-07-08 17:31:55 +00:00
|
|
|
FALSE,
|
|
|
|
&DeviceObject);
|
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
/* check for success */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2007-07-08 17:31:55 +00:00
|
|
|
{
|
|
|
|
DPRINT("Failed to create \\Device\\sysaudio !\n");
|
2009-01-26 10:08:17 +00:00
|
|
|
return Status;
|
2007-07-08 17:31:55 +00:00
|
|
|
}
|
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
/* create the symbolic link */
|
|
|
|
Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2007-07-08 17:31:55 +00:00
|
|
|
{
|
|
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
DPRINT("Failed to create \\DosDevices\\sysaudio symlink!\n");
|
2009-01-26 10:08:17 +00:00
|
|
|
return Status;
|
2007-07-08 17:31:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
DeviceExtension = (SYSAUDIODEVEXT*)DeviceObject->DeviceExtension;
|
|
|
|
/* initialize device extension */
|
|
|
|
RtlZeroMemory(DeviceExtension, sizeof(SYSAUDIODEVEXT));
|
|
|
|
|
|
|
|
KeInitializeMutex(&DeviceExtension->Mutex, 0);
|
|
|
|
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
2009-02-10 16:28:24 +00:00
|
|
|
InitializeListHead(&DeviceExtension->KsAudioDeviceList);
|
2009-01-26 10:08:17 +00:00
|
|
|
|
|
|
|
/* initialize create item struct */
|
|
|
|
RtlZeroMemory(&CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
|
|
|
|
CreateItem.Create = DispatchCreate;
|
|
|
|
|
|
|
|
Status = KsAllocateDeviceHeader(&DeviceExtension->KsDeviceHeader,
|
|
|
|
1,
|
|
|
|
&CreateItem);
|
|
|
|
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
NextDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
|
|
|
|
if (NextDeviceObject)
|
|
|
|
{
|
|
|
|
/// FIXME
|
|
|
|
/// KsSetDevicePnpAndBaseObject(DeviceExtension->KsDeviceHeader, NextDeviceObject, DeviceObject);
|
|
|
|
///
|
|
|
|
|
|
|
|
DeviceExtension->NextDeviceObject = NextDeviceObject;
|
|
|
|
|
|
|
|
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
|
|
|
|
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
|
|
|
|
(PVOID)&KS_CATEGORY_AUDIO,
|
|
|
|
DriverObject,
|
|
|
|
DeviceInterfaceChangeCallback,
|
|
|
|
(PVOID)DeviceExtension,
|
|
|
|
(PVOID*)&DeviceExtension->KsAudioNotificationEntry);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("IoRegisterPlugPlayNotification failed with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
|
|
|
|
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
|
|
|
|
&DMOCATEGORY_ACOUSTIC_ECHO_CANCEL,
|
|
|
|
DriverObject,
|
|
|
|
DeviceInterfaceChangeCallback,
|
|
|
|
(PVOID)DeviceExtension,
|
|
|
|
&DeviceExtension->EchoCancelNotificationEntry);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("IoRegisterPlugPlayNotification failed with %x\n", Status);
|
|
|
|
return Status;
|
|
|
|
}
|
2009-01-27 20:02:50 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_PREFERRED_MIDIOUT_DEVICE, NULL, &SymbolicLink);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to register KSCATEGORY_PREFERRED_MIDIOUT_DEVICE interface\n");
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
RtlFreeUnicodeString(&SymbolicLink);
|
|
|
|
|
|
|
|
Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_PREFERRED_WAVEIN_DEVICE, NULL, &SymbolicLink);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to register KSCATEGORY_PREFERRED_WAVEIN_DEVICE interface\n");
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
RtlFreeUnicodeString(&SymbolicLink);
|
|
|
|
|
|
|
|
Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_PREFERRED_WAVEOUT_DEVICE, NULL, &SymbolicLink);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("Failed to register KSCATEGORY_PREFERRED_WAVEOUT_DEVICE interface\n");
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
RtlFreeUnicodeString(&SymbolicLink);
|
2009-01-26 10:08:17 +00:00
|
|
|
|
|
|
|
/* set io flags */
|
|
|
|
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
|
|
|
|
/* clear initializing flag */
|
|
|
|
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DPRINT("Device SysAudio_AddDevice result %x\n", Status);
|
|
|
|
|
|
|
|
return Status;
|
2007-07-08 17:31:55 +00:00
|
|
|
}
|
|
|
|
|
2009-02-10 16:28:24 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
SysAudio_Stub(
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
DPRINT1("SysAudio_Stub called\n");
|
|
|
|
|
|
|
|
/* TODO */
|
|
|
|
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-08 17:31:55 +00:00
|
|
|
NTSTATUS NTAPI
|
|
|
|
DriverEntry(
|
|
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PUNICODE_STRING RegistryPath)
|
|
|
|
{
|
2009-01-27 20:02:50 +00:00
|
|
|
DPRINT1("System audio graph builder (sysaudio) started\n");
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
DPRINT1("Setting KS function handlers\n");
|
2009-02-10 16:28:24 +00:00
|
|
|
|
|
|
|
#if KS_IMPLEMENTED
|
2009-01-26 10:08:17 +00:00
|
|
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
|
|
|
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
|
|
|
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
|
|
|
|
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
|
2009-02-10 16:28:24 +00:00
|
|
|
#else
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = SysAudio_Stub;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SysAudio_Stub;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = SysAudio_Stub;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SysAudio_Stub;
|
|
|
|
#endif
|
|
|
|
|
2007-07-08 17:31:55 +00:00
|
|
|
|
2009-01-26 10:08:17 +00:00
|
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = SysAudio_Pnp;
|
2007-07-08 17:31:55 +00:00
|
|
|
DriverObject->DriverUnload = SysAudio_Unload;
|
2009-01-26 10:08:17 +00:00
|
|
|
DriverObject->DriverExtension->AddDevice = SysAudio_AddDevice;
|
2007-07-08 17:31:55 +00:00
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|