summaryrefslogtreecommitdiff
path: root/audio/sysvad/common.cpp
diff options
context:
space:
mode:
authorDaniel Rugerio <[email protected]>2021-08-13 15:05:12 -0700
committerGitHub <[email protected]>2021-08-13 15:05:12 -0700
commit7895dd22785ddba5e973662ed942be3b3452b89d (patch)
tree5c4572d5bfd076d3776a88c5757e37f3ed50c0e7 /audio/sysvad/common.cpp
parentdf47b2d284558fa9aacd19257153037e4ebba60e (diff)
audio: Updates for Windows 10 22000 (#655)
* Updates for Windows 10 22000. * Change how WIL is consumed.
Diffstat (limited to 'audio/sysvad/common.cpp')
-rw-r--r--audio/sysvad/common.cpp737
1 files changed, 714 insertions, 23 deletions
diff --git a/audio/sysvad/common.cpp b/audio/sysvad/common.cpp
index 9292c96d..9bc3e644 100644
--- a/audio/sysvad/common.cpp
+++ b/audio/sysvad/common.cpp
@@ -39,6 +39,12 @@ Abstract:
#include "UsbHsDevice.h"
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+#include <SidebandAudio.h>
+#include <A2DPSidebandAudio.h>
+#include "A2dpHpMinipairs.h"
+#include "A2dpHpDevice.h"
+#endif // SYSVAD_A2DP_SIDEBAND
//-----------------------------------------------------------------------------
// CSaveData statics
@@ -57,6 +63,9 @@ class BthHfpDevice; // Forward declaration.
class UsbHsDevice; // Forward declaration.
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+class A2dpHpDevice; // Forward declaration.
+#endif // SYSVAD_A2DP_SIDEBAND
///////////////////////////////////////////////////////////////////////////////
// CAdapterCommon
@@ -299,6 +308,11 @@ class CAdapterCommon :
);
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+ STDMETHODIMP_(NTSTATUS) InitA2dpSideband();
+
+ STDMETHODIMP_(VOID) CleanupA2dpSideband();
+#endif // SYSVAD_A2DP_SIDEBAND
STDMETHODIMP_(VOID) Cleanup();
@@ -313,10 +327,7 @@ class CAdapterCommon :
_Out_ PUNKNOWN * Unknown,
_In_ REFCLSID,
_In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType
+ _In_ POOL_FLAGS PoolFlags
);
#ifdef SYSVAD_BTH_BYPASS
@@ -396,6 +407,43 @@ class CAdapterCommon :
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+ //=====================================================================
+ // A2DP Sideband Audio support.
+
+ private:
+ PVOID m_A2dpSidebandNotificationHandle;
+ FAST_MUTEX m_A2dpSidebandFastMutex; // To serialize access.
+ WDFWORKITEM m_A2dpSidebandWorkItem; // Async work-item.
+ LIST_ENTRY m_A2dpSidebandWorkTasks; // Work-item's tasks.
+ LIST_ENTRY m_A2dpSidebandDevices; // A2DP Sideband devices.
+ NPAGED_LOOKASIDE_LIST m_A2dpSidebandWorkTaskPool; // LookasideList
+ size_t m_A2dpSidebandWorkTaskPoolElementSize;
+ BOOL m_A2dpSidebandEnableCleanup; // Do cleanup if true.
+
+ private:
+ static
+ DRIVER_NOTIFICATION_CALLBACK_ROUTINE EvtA2dpSidebandInterfaceChange;
+
+ static
+ EVT_WDF_WORKITEM EvtA2dpSidebandInterfaceWorkItem;
+
+ protected:
+ A2dpHpDevice * A2dpSidebandDeviceFind
+ (
+ _In_ PUNICODE_STRING SymbolicLinkName
+ );
+
+ NTSTATUS A2dpSidebandInterfaceArrival
+ (
+ _In_ PUNICODE_STRING SymbolicLinkName
+ );
+
+ NTSTATUS A2dpSidebandInterfaceRemoval
+ (
+ _In_ PUNICODE_STRING SymbolicLinkName
+ );
+#endif // SYSVAD_A2DP_SIDEBAND
private:
@@ -505,10 +553,7 @@ NewAdapterCommon
_Out_ PUNKNOWN * Unknown,
_In_ REFCLSID,
_In_opt_ PUNKNOWN UnknownOuter,
- _When_((PoolType & NonPagedPoolMustSucceed) != 0,
- __drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
- _In_ POOL_TYPE PoolType
+ _In_ POOL_FLAGS PoolFlags
)
/*++
@@ -550,7 +595,7 @@ Return Value:
//
// Allocate an adapter object.
//
- CAdapterCommon *p = new(PoolType, MINADAPTER_POOLTAG) CAdapterCommon(UnknownOuter);
+ CAdapterCommon *p = new(PoolFlags, MINADAPTER_POOLTAG) CAdapterCommon(UnknownOuter);
if (p == NULL)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
@@ -733,6 +778,11 @@ Return Value:
m_UsbSidebandEnableCleanup = FALSE;
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+ m_A2dpSidebandEnableCleanup = FALSE;
+#endif // SYSVAD_A2DP_SIDEBAND
+
+
m_pServiceGroupWave = NULL;
m_pDeviceObject = DeviceObject;
@@ -777,7 +827,7 @@ Return Value:
// Initialize HW.
//
- m_pHW = new (NonPagedPoolNx, SYSVAD_POOLTAG) CSYSVADHW;
+ m_pHW = new (POOL_FLAG_NON_PAGED, SYSVAD_POOLTAG) CSYSVADHW;
if (!m_pHW)
{
DPF(D_TERSE, ("Insufficient memory for SYSVAD HW"));
@@ -1772,7 +1822,7 @@ Return Value:
&miniport,
MiniportClassId,
NULL,
- NonPagedPoolNx,
+ POOL_FLAG_NON_PAGED,
adapterCommon,
DeviceContext,
MiniportPair
@@ -2175,7 +2225,7 @@ CAdapterCommon::CacheSubdevice
NTSTATUS ntStatus = STATUS_SUCCESS;
MINIPAIR_UNKNOWN *pNewSubdevice = NULL;
- pNewSubdevice = new(NonPagedPoolNx, MINADAPTER_POOLTAG) MINIPAIR_UNKNOWN;
+ pNewSubdevice = new(POOL_FLAG_NON_PAGED, MINADAPTER_POOLTAG) MINIPAIR_UNKNOWN;
if (!pNewSubdevice)
{
@@ -2300,6 +2350,13 @@ CAdapterCommon::Cleanup()
CleanupUsbSideband();
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+ //
+ // This ensures A2DP Sideband notifications are turned off when port class
+ // cleanups and unregisters the static subdevices.
+ //
+ CleanupA2dpSideband();
+#endif // SYSVAD_A2DP_SIDEBAND
EmptySubdeviceCache();
}
@@ -2310,6 +2367,8 @@ CAdapterCommon::Cleanup()
NTSTATUS
CAdapterCommon::UpdatePowerRelations(_In_ PIRP Irp)
{
+ PAGED_CODE();
+
PDEVICE_RELATIONS priorRelations = NULL;
PDEVICE_RELATIONS newRelations = NULL;
ULONG qprPdosCount = 0;
@@ -2354,7 +2413,7 @@ CAdapterCommon::UpdatePowerRelations(_In_ PIRP Irp)
// space for the extra PDEVICE_OBJECTs we need.
//
size = sizeof(DEVICE_RELATIONS) + (count - 1) * sizeof(PDEVICE_OBJECT);
- newRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(PagedPool, size, USBSIDEBANDTEST_POOLTAG015);
+ newRelations = (PDEVICE_RELATIONS)ExAllocatePool2(POOL_FLAG_PAGED, size, USBSIDEBANDTEST_POOLTAG015);
ASSERT(newRelations);
if (NULL == newRelations)
{
@@ -2367,7 +2426,6 @@ CAdapterCommon::UpdatePowerRelations(_In_ PIRP Irp)
// If there was an existing device relations structure, copy
// the entries to the new structure.
//
- RtlZeroMemory(newRelations, size);
if (priorRelations != NULL && priorRelations->Count > 0)
{
size = sizeof(DEVICE_RELATIONS) + (priorRelations->Count - 1) * sizeof(PDEVICE_OBJECT);
@@ -2974,7 +3032,7 @@ Return Value:
//
// Alloc a new structure for this Bluetooth hands-free device.
//
- bthDevice = new (NonPagedPoolNx, MINADAPTER_POOLTAG) BthHfpDevice(NULL); // NULL -> OuterUnknown
+ bthDevice = new (POOL_FLAG_NON_PAGED, MINADAPTER_POOLTAG) BthHfpDevice(NULL); // NULL -> OuterUnknown
if (NULL == bthDevice)
{
DPF(D_ERROR, ("BthHfpScoInterfaceArrival: unable to allocate BthHfpDevice, out of memory"));
@@ -3582,7 +3640,7 @@ NT status code.
//
// Alloc a new structure for this USB device.
//
- usbHsDevice = new (NonPagedPoolNx, MINADAPTER_POOLTAG) UsbHsDevice(NULL); // NULL -> OuterUnknown
+ usbHsDevice = new (POOL_FLAG_NON_PAGED, MINADAPTER_POOLTAG) UsbHsDevice(NULL); // NULL -> OuterUnknown
if (NULL == usbHsDevice)
{
DPF(D_ERROR, ("UsbSidebandInterfaceArrival: unable to allocate UsbSidebandDevice, out of memory"));
@@ -3931,7 +3989,7 @@ CAdapterCommon::AddDeviceAsPowerDependency
NTSTATUS status = STATUS_SUCCESS;
// allocate SysVadPowerRelationsDo
- PSysVadPowerRelationsDo powerDepDo = (PSysVadPowerRelationsDo)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(SysVadPowerRelationsDo), USBSIDEBANDTEST_POOLTAG014);
+ PSysVadPowerRelationsDo powerDepDo = (PSysVadPowerRelationsDo)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(SysVadPowerRelationsDo), USBSIDEBANDTEST_POOLTAG014);
if (NULL == powerDepDo)
{
status = STATUS_INSUFFICIENT_RESOURCES;
@@ -4064,6 +4122,637 @@ Cleanup the USB Sideband environment.
}
#endif // SYSVAD_USB_SIDEBAND
+#ifdef SYSVAD_A2DP_SIDEBAND
+//
+// CAdapterCommon A2DP Sideband function implementation.
+//
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID
+CAdapterCommon::EvtA2dpSidebandInterfaceWorkItem
+(
+ _In_ WDFWORKITEM WorkItem
+)
+/*++
+
+Routine Description:
+
+The function handles the arrival or removal of a A2DP Sideband interface.
+
+Arguments:
+
+WorkItem - WDF work-item object.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[EvtA2dpSidebandInterfaceWorkItem]"));
+
+ CAdapterCommon * This;
+
+ if (WorkItem == NULL)
+ {
+ return;
+ }
+
+ This = GetA2dpHpWorkItemContext(WorkItem)->Adapter;
+ ASSERT(This != NULL);
+
+ for (;;)
+ {
+ PLIST_ENTRY le = NULL;
+ A2dpHpWorkTask * task = NULL;
+
+ //
+ // Retrieve a taask.
+ //
+ ExAcquireFastMutex(&This->m_A2dpSidebandFastMutex);
+ if (!IsListEmpty(&This->m_A2dpSidebandWorkTasks))
+ {
+ le = RemoveHeadList(&This->m_A2dpSidebandWorkTasks);
+ task = CONTAINING_RECORD(le, A2dpHpWorkTask, ListEntry);
+ InitializeListHead(le);
+ }
+ ExReleaseFastMutex(&This->m_A2dpSidebandFastMutex);
+
+ if (task == NULL)
+ {
+ break;
+ }
+
+ ASSERT(task->Device != NULL);
+ _Analysis_assume_(task->Device != NULL);
+
+ //
+ // Process the task.
+ //
+ switch (task->Action)
+ {
+ case eA2dpHpTaskStart:
+ task->Device->Start();
+ break;
+
+ case eA2dpHpTaskStop:
+ task->Device->Stop();
+ break;
+
+ default:
+ DPF(D_ERROR, ("EvtA2dpSidebandInterfaceWorkItem: invalid action %d", task->Action));
+ break;
+ }
+
+ //
+ // Release the ref we took on the device when we inserted the task in the queue.
+ // For a stop operation this may be the last reference.
+ //
+ SAFE_RELEASE(task->Device);
+
+ //
+ // Free the task.
+ //
+ ExFreeToNPagedLookasideList(&This->m_A2dpSidebandWorkTaskPool, task);
+ }
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+A2dpHpDevice *
+CAdapterCommon::A2dpSidebandDeviceFind
+(
+ _In_ PUNICODE_STRING SymbolicLinkName
+)
+/*++
+
+Routine Description:
+
+The function looks for the specified device in the adapter's list.
+
+Arguments:
+
+SymbolicLinkName - interface's symbolic link.
+
+Return Value:
+
+A2dpSidebandDevice pointer or NULL.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::A2dpSidebandDeviceFind]"));
+
+ PLIST_ENTRY le = NULL;
+ A2dpHpDevice * a2dpDevice = NULL;
+
+ ExAcquireFastMutex(&m_A2dpSidebandFastMutex);
+
+ for (le = m_A2dpSidebandDevices.Flink; le != &m_A2dpSidebandDevices; le = le->Flink)
+ {
+ A2dpHpDevice * tmpA2dpHpDevice = A2dpHpDevice::GetA2dpHpDevice(le);
+ ASSERT(tmpA2dpHpDevice != NULL);
+
+ PUNICODE_STRING unicodeStr = tmpA2dpHpDevice->GetSymbolicLinkName();
+ ASSERT(unicodeStr != NULL);
+
+ if (unicodeStr->Length == SymbolicLinkName->Length &&
+ 0 == wcsncmp(unicodeStr->Buffer, SymbolicLinkName->Buffer, unicodeStr->Length / sizeof(WCHAR)))
+ {
+ // Found it!
+ a2dpDevice = tmpA2dpHpDevice;
+ a2dpDevice->AddRef();
+ break;
+ }
+ }
+
+ ExReleaseFastMutex(&m_A2dpSidebandFastMutex);
+
+ return a2dpDevice;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::A2dpSidebandInterfaceArrival
+(
+ _In_ PUNICODE_STRING SymbolicLinkName
+)
+/*++
+
+Routine Description:
+
+The function handles the arrival of a new A2DP Sideband interface.
+
+Arguments:
+
+SymbolicLinkName - new interface's symbolic link.
+
+Return Value:
+
+NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::A2dpSidebandInterfaceArrival]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ A2dpHpDevice *a2dpHpDevice = NULL;
+ A2dpHpWorkTask *a2dpHpWorkTask = NULL;
+
+ DPF(D_VERBOSE, ("A2dpSidebandInterfaceArrival: SymbolicLinkName %wZ", SymbolicLinkName));
+
+ //
+ // Check if the A2DP device is already present.
+ // According to the docs it is possible to receive two notifications for the same
+ // interface.
+ //
+ a2dpHpDevice = A2dpSidebandDeviceFind(SymbolicLinkName);
+ if (a2dpHpDevice != NULL)
+ {
+ DPF(D_VERBOSE, ("A2dpSidebandInterfaceArrival: A2DP device already present"));
+ SAFE_RELEASE(a2dpHpDevice);
+ ntStatus = STATUS_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Alloc a new structure for this A2DP device.
+ //
+ a2dpHpDevice = new (POOL_FLAG_NON_PAGED, MINADAPTER_POOLTAG) A2dpHpDevice(NULL); // NULL -> OuterUnknown
+ if (NULL == a2dpHpDevice)
+ {
+ DPF(D_ERROR, ("A2dpSidebandInterfaceArrival: unable to allocate A2dpSidebandDevice, out of memory"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+
+ DPF(D_VERBOSE, ("A2dpSidebandInterfaceArrival: created A2dpSidebandDevice 0x%p ", a2dpHpDevice));
+
+ //
+ // Basic initialization of the A2DP Sideband interface.
+ // The audio miniport creation is done later by the A2dpSidebandDevice.Start()
+ // which is invoked asynchronously by a worker thread.
+ // A2dpSidebandDevice->Init() must be invoked just after the creation of the object.
+ //
+ ntStatus = a2dpHpDevice->Init(this, SymbolicLinkName);
+ IF_FAILED_JUMP(ntStatus, Done);
+
+ //
+ // Get and init a work task.
+ //
+ a2dpHpWorkTask = (A2dpHpWorkTask*)ExAllocateFromNPagedLookasideList(&m_A2dpSidebandWorkTaskPool);
+ if (NULL == a2dpHpWorkTask)
+ {
+ DPF(D_ERROR, ("A2dpSidebandInterfaceArrival: unable to allocate A2dpSidebandWorkTask, out of memory"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+
+ // a2dpWorkTask->L.Size is set to sizeof(A2dpSidebandWorkTask) in the Look Aside List configuration
+#pragma warning(suppress: 6386)
+ RtlZeroMemory(a2dpHpWorkTask, sizeof(*a2dpHpWorkTask));
+ a2dpHpWorkTask->Action = eA2dpHpTaskStart;
+ InitializeListHead(&a2dpHpWorkTask->ListEntry);
+ // Note that a2dpDevice has one reference at this point.
+ a2dpHpWorkTask->Device = a2dpHpDevice;
+
+ ExAcquireFastMutex(&m_A2dpSidebandFastMutex);
+
+ //
+ // Insert this new A2DP Sideband device in our list.
+ //
+ InsertTailList(&m_A2dpSidebandDevices, a2dpHpDevice->GetListEntry());
+
+ //
+ // Add a new task for the worker thread.
+ //
+ InsertTailList(&m_A2dpSidebandWorkTasks, &a2dpHpWorkTask->ListEntry);
+ a2dpHpDevice->AddRef(); // released when task runs.
+
+ //
+ // Schedule a work-item if not already running.
+ //
+ WdfWorkItemEnqueue(m_A2dpSidebandWorkItem);
+
+ ExReleaseFastMutex(&m_A2dpSidebandFastMutex);
+
+Done:
+ if (!NT_SUCCESS(ntStatus))
+ {
+ // Release the last ref, this will delete the A2dpSidebandDevice
+ SAFE_RELEASE(a2dpHpDevice);
+
+ if (a2dpHpWorkTask != NULL)
+ {
+ ExFreeToNPagedLookasideList(&m_A2dpSidebandWorkTaskPool, a2dpHpWorkTask);
+ a2dpHpWorkTask = NULL;
+ }
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::A2dpSidebandInterfaceRemoval
+(
+ _In_ PUNICODE_STRING SymbolicLinkName
+)
+/*++
+
+Routine Description:
+
+The function handles the removal of a A2DP Sideband interface.
+
+Arguments:
+
+SymbolicLinkName - interface's symbolic link to remove.
+
+Return Value:
+
+NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::A2dpSidebandInterfaceRemoval]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ A2dpHpDevice *a2dpHpDevice = NULL;
+ A2dpHpWorkTask *a2dpHpWorkTask = NULL;
+
+ DPF(D_VERBOSE, ("A2dpSidebandInterfaceRemoval: SymbolicLinkName %wZ", SymbolicLinkName));
+
+ //
+ // Check if the A2DP device is present.
+ //
+ a2dpHpDevice = A2dpSidebandDeviceFind(SymbolicLinkName);
+ if (a2dpHpDevice == NULL)
+ {
+ // This can happen if the init/start of the A2dpSidebandDevice failed.
+ DPF(D_VERBOSE, ("A2dpSidebandInterfaceRemoval: A2DP device not found"));
+ ntStatus = STATUS_SUCCESS;
+ goto Done;
+ }
+
+ //
+ // Init a work task.
+ //
+ a2dpHpWorkTask = (A2dpHpWorkTask*)ExAllocateFromNPagedLookasideList(&m_A2dpSidebandWorkTaskPool);
+ if (NULL == a2dpHpWorkTask)
+ {
+ DPF(D_ERROR, ("A2dpSidebandInterfaceRemoval: unable to allocate A2dpSidebandWorkTask, out of memory"));
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto Done;
+ }
+
+ // a2dpWorkTask->L.Size is set to sizeof(A2dpSidebandWorkTask) in the Look Aside List configuration
+#pragma warning(suppress: 6386)
+ RtlZeroMemory(a2dpHpWorkTask, sizeof(*a2dpHpWorkTask));
+ a2dpHpWorkTask->Action = eA2dpHpTaskStop;
+ InitializeListHead(&a2dpHpWorkTask->ListEntry);
+ // Work-item callback will release the reference we got above from A2dpSidebandDeviceFind.
+ a2dpHpWorkTask->Device = a2dpHpDevice;
+
+ ExAcquireFastMutex(&m_A2dpSidebandFastMutex);
+
+ //
+ // Remove this A2DP device from our list and release the associated reference.
+ //
+ RemoveEntryList(a2dpHpDevice->GetListEntry());
+ InitializeListHead(a2dpHpDevice->GetListEntry());
+ a2dpHpDevice->Release(); // This is not the last ref.
+
+ //
+ // Add a new task for the worker thread.
+ //
+ InsertTailList(&m_A2dpSidebandWorkTasks, &a2dpHpWorkTask->ListEntry);
+
+ //
+ // Schedule a work-item if not already running.
+ //
+ WdfWorkItemEnqueue(m_A2dpSidebandWorkItem);
+
+ ExReleaseFastMutex(&m_A2dpSidebandFastMutex);
+
+ //
+ // All done.
+ //
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ // Release the ref we got in find.
+ SAFE_RELEASE(a2dpHpDevice);
+ }
+
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::EvtA2dpSidebandInterfaceChange(
+ _In_ PVOID NotificationPointer,
+ _Inout_opt_ PVOID Context
+)
+/*++
+
+Routine Description:
+
+This callback is invoked when a new A2DP Sideband interface is added or removed.
+
+Arguments:
+NotificationPointer - Interface change notification
+Context - CAdapterCommon ptr.
+
+Return Value:
+
+NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[EvtA2dpSidebandInterfaceChange]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ CAdapterCommon * This = NULL;
+ PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationPointer;
+
+ //
+ // Make sure this is the interface class we extect. Any other class guid
+ // is an error, but let it go since it is not fatal to the machine.
+ //
+ if (!IsEqualGUID(Notification->InterfaceClassGuid, GUID_DEVINTERFACE_A2DP_SIDEBAND_AUDIO))
+ {
+ DPF(D_VERBOSE, ("EvtA2dpSidebandInterfaceChange: bad interface ClassGuid"));
+ ASSERTMSG("EvtA2dpSidebandInterfaceChange: bad interface ClassGuid ", FALSE);
+
+ goto Done;
+ }
+
+ This = (CAdapterCommon *)Context;
+ ASSERT(This != NULL);
+ _Analysis_assume_(This != NULL);
+
+ //
+ // Take action based on the event. Any other event type is an error,
+ // but let it go since it is not fatal to the machine.
+ //
+ if (IsEqualGUID(Notification->Event, GUID_DEVICE_INTERFACE_ARRIVAL))
+ {
+ ntStatus = This->A2dpSidebandInterfaceArrival(Notification->SymbolicLinkName);
+ }
+ else if (IsEqualGUID(Notification->Event, GUID_DEVICE_INTERFACE_REMOVAL))
+ {
+ ntStatus = This->A2dpSidebandInterfaceRemoval(Notification->SymbolicLinkName);
+ }
+ else
+ {
+ DPF(D_VERBOSE, ("EvtA2dpSidebandInterfaceChange: bad "
+ "GUID_DEVINTERFACE_A2DP_SIDEBAND_AUDIO event"));
+ ASSERTMSG("EvtA2dpSidebandInterfaceChange: bad "
+ "GUID_DEVINTERFACE_A2DP_SIDEBAND_AUDIO event ", FALSE);
+
+ goto Done;
+ }
+
+Done:
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CAdapterCommon::InitA2dpSideband()
+/*++
+
+Routine Description:
+
+Initialize the A2DP Sideband environment.
+
+Return Value:
+
+NT status code.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::InitA2dpSideband]"));
+
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ WDF_WORKITEM_CONFIG wiConfig;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ A2dpHpWorkItemContext * wiContext;
+ DECLARE_CONST_UNICODE_STRING(a2dpSidebandSupportInterface, L"A2dpSidebandSupport");
+ UNICODE_STRING sidebandSupportRefString;
+ RtlInitUnicodeString(&sidebandSupportRefString, NULL);
+
+ //
+ // Init spin-lock, linked lists, work-item, event, etc.
+ // Init all members to default values. This basic init should not fail.
+ //
+ m_A2dpSidebandWorkItem = NULL;
+ m_A2dpSidebandNotificationHandle = NULL;
+ ExInitializeFastMutex(&m_A2dpSidebandFastMutex);
+ InitializeListHead(&m_A2dpSidebandWorkTasks);
+ InitializeListHead(&m_A2dpSidebandDevices);
+ m_A2dpSidebandWorkTaskPoolElementSize = sizeof(A2dpHpWorkTask);
+ ExInitializeNPagedLookasideList(&m_A2dpSidebandWorkTaskPool,
+ NULL,
+ NULL,
+ POOL_NX_ALLOCATION,
+ m_A2dpSidebandWorkTaskPoolElementSize,
+ MINADAPTER_POOLTAG,
+ 0);
+ //
+ // Enable A2DP Sideband Cleanup.
+ // Do any allocation/initialization that can fail after this point.
+ //
+ m_A2dpSidebandEnableCleanup = TRUE;
+
+ //
+ // Allocate a WDF work-item.
+ //
+ WDF_WORKITEM_CONFIG_INIT(&wiConfig, EvtA2dpSidebandInterfaceWorkItem);
+ wiConfig.AutomaticSerialization = FALSE;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, A2dpHpWorkItemContext);
+ attributes.ParentObject = GetWdfDevice();
+ ntStatus = WdfWorkItemCreate(&wiConfig,
+ &attributes,
+ &m_A2dpSidebandWorkItem);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("InitA2dpSideband: WdfWorkItemCreate failed: 0x%x", ntStatus)),
+ Done);
+
+ wiContext = GetA2dpHpWorkItemContext(m_A2dpSidebandWorkItem);
+ wiContext->Adapter = this; // weak ref.
+
+ //
+ // Publish A2DP Sideband support interface.
+ //
+ ntStatus = IoRegisterDeviceInterface(
+ GetPhysicalDeviceObject(),
+ &GUID_SIDEBANDAUDIO_A2DP_SUPPORT_INTERFACE,
+ (PUNICODE_STRING)&a2dpSidebandSupportInterface,
+ &sidebandSupportRefString);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("InitA2dpSideband: IoRegisterDeviceInterface(GUID_SIDEBANDAUDIO_A2DP_SUPPORT_INTERFACE) failed: 0x%x", ntStatus)),
+ Done);
+
+ ntStatus = IoSetDeviceInterfaceState(&sidebandSupportRefString, TRUE);
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("InitA2dpSideband: IoSetDeviceInterfaceState failed: 0x%x", ntStatus)),
+ Done);
+
+ //
+ // Register for A2DP Sideband interface changes.
+ //
+ ntStatus = IoRegisterPlugPlayNotification(
+ EventCategoryDeviceInterfaceChange,
+ PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
+ (PVOID)&GUID_DEVINTERFACE_A2DP_SIDEBAND_AUDIO,
+ m_pDeviceObject->DriverObject,
+ EvtA2dpSidebandInterfaceChange,
+ (PVOID)this,
+ &m_A2dpSidebandNotificationHandle);
+
+ IF_FAILED_ACTION_JUMP(
+ ntStatus,
+ DPF(D_ERROR, ("InitA2dpSideband: IoRegisterPlugPlayNotification(GUID_DEVINTERFACE_A2DP_SIDEBAND_AUDIO) failed: 0x%x", ntStatus)),
+ Done);
+
+ //
+ // Initialization completed.
+ //
+ ntStatus = STATUS_SUCCESS;
+
+Done:
+ RtlFreeUnicodeString(&sidebandSupportRefString);
+ return ntStatus;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID
+CAdapterCommon::CleanupA2dpSideband()
+/*++
+
+Routine Description:
+
+Cleanup the A2DP Sideband environment.
+
+--*/
+{
+ PAGED_CODE();
+ DPF_ENTER(("[CAdapterCommon::CleanupA2dpSideband]"));
+
+ //
+ // Do nothing if A2DP Sideband environment was not correctly initialized.
+ //
+ if (m_A2dpSidebandEnableCleanup == FALSE)
+ {
+ return;
+ }
+
+ //
+ // Unregister for A2DP Sideband interface changes.
+ //
+ if (m_A2dpSidebandNotificationHandle != NULL)
+ {
+ (void)IoUnregisterPlugPlayNotificationEx(m_A2dpSidebandNotificationHandle);
+ m_A2dpSidebandNotificationHandle = NULL;
+ }
+
+ //
+ // Wait for the A2DP Sideband worker thread to be done.
+ //
+ if (m_A2dpSidebandWorkItem != NULL)
+ {
+ WdfWorkItemFlush(m_A2dpSidebandWorkItem);
+ WdfObjectDelete(m_A2dpSidebandWorkItem);
+ m_A2dpSidebandWorkItem = NULL;
+ }
+
+ ASSERT(IsListEmpty(&m_A2dpSidebandWorkTasks));
+
+ //
+ // Stop and delete all A2dpSidebandDevices. We are the only thread accessing this list,
+ // so there is no need to acquire the mutex.
+ //
+ while (!IsListEmpty(&m_A2dpSidebandDevices))
+ {
+ A2dpHpDevice * a2dpHpDevice = NULL;
+ PLIST_ENTRY le = NULL;
+
+ le = RemoveHeadList(&m_A2dpSidebandDevices);
+
+ a2dpHpDevice = A2dpHpDevice::GetA2dpHpDevice(le);
+ InitializeListHead(le);
+
+ // a2dpDevice is invalid after this call.
+ a2dpHpDevice->Stop();
+
+ // This should be the last reference.
+ a2dpHpDevice->Release();
+ }
+
+ ASSERT(IsListEmpty(&m_A2dpSidebandDevices));
+
+ //
+ // General cleanup.
+ //
+ ExDeleteNPagedLookasideList(&m_A2dpSidebandWorkTaskPool);
+}
+#endif // SYSVAD_A2DP_SIDEBAND
+
#pragma code_seg("PAGE")
NTSTATUS
@@ -4089,7 +4778,7 @@ Return Value:
PAGED_CODE();
// Allocate the KEY_VALUE_FULL_INFORMATION structure
ulFullInfoLength = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_DEVICE_REG_KEY_LENGTH;
- kvFullInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePoolWithTag(NonPagedPoolNx, ulFullInfoLength, MINADAPTER_POOLTAG);
+ kvFullInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulFullInfoLength, MINADAPTER_POOLTAG);
IF_TRUE_ACTION_JUMP(kvFullInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, Exit);
// Iterate over each value and copy it to the destination
@@ -4109,7 +4798,7 @@ Return Value:
ulFullInfoLength = ulFullInfoResultLength;
- kvFullInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePoolWithTag(NonPagedPoolNx, ulFullInfoLength, MINADAPTER_POOLTAG);
+ kvFullInfo = (PKEY_VALUE_FULL_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulFullInfoLength, MINADAPTER_POOLTAG);
IF_TRUE_ACTION_JUMP(kvFullInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
// Try to enumerate the current value again
@@ -4125,7 +4814,7 @@ Return Value:
}
// Allocate the key value name string
- pwstrKeyValueName = (PWSTR)ExAllocatePoolWithTag(NonPagedPoolNx, kvFullInfo->NameLength + sizeof(WCHAR)*2, MINADAPTER_POOLTAG);
+ pwstrKeyValueName = (PWSTR)ExAllocatePool2(POOL_FLAG_NON_PAGED, kvFullInfo->NameLength + sizeof(WCHAR)*2, MINADAPTER_POOLTAG);
IF_TRUE_ACTION_JUMP(kvFullInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
// Copy the key value name from the full information struct
@@ -4196,7 +4885,7 @@ Return Value:
// Allocate the KEY_BASIC_INFORMATION structure
ulBasicInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_DEVICE_REG_KEY_LENGTH;
- kBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePoolWithTag(NonPagedPoolNx, ulBasicInfoLength, MINADAPTER_POOLTAG);
+ kBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulBasicInfoLength, MINADAPTER_POOLTAG);
IF_TRUE_ACTION_JUMP(kBasicInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, Exit);
ntStatus = STATUS_SUCCESS;
@@ -4215,7 +4904,7 @@ Return Value:
// Free and re-allocate the KEY_BASIC_INFORMATION structure with the correct size.
ExFreePoolWithTag(kBasicInfo, MINADAPTER_POOLTAG);
ulBasicInfoLength = ulBasicInfoResultLength;
- kBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePoolWithTag(NonPagedPoolNx, ulBasicInfoLength, MINADAPTER_POOLTAG);
+ kBasicInfo = (PKEY_BASIC_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, ulBasicInfoLength, MINADAPTER_POOLTAG);
IF_TRUE_ACTION_JUMP(kBasicInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
// Try to enumerate the current key again.
@@ -4231,7 +4920,7 @@ Return Value:
}
// Allocate the key name string
- pwstrKeyName = (PWSTR)ExAllocatePoolWithTag(NonPagedPoolNx, kBasicInfo->NameLength + sizeof(WCHAR), MINADAPTER_POOLTAG);
+ pwstrKeyName = (PWSTR)ExAllocatePool2(POOL_FLAG_NON_PAGED, kBasicInfo->NameLength + sizeof(WCHAR), MINADAPTER_POOLTAG);
IF_TRUE_ACTION_JUMP(kBasicInfo == NULL, ntStatus = STATUS_INSUFFICIENT_RESOURCES, loop_exit);
// Copy the key name from the basic information struct
@@ -4338,6 +5027,8 @@ Return Value:
--*/
{
+ PAGED_CODE();
+
NTSTATUS ntStatus = STATUS_SUCCESS;
HANDLE hDeviceInterfaceParametersKey(NULL);
HANDLE hTemplateDeviceInterfaceParametersKey(NULL);