You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
642 lines
16 KiB
642 lines
16 KiB
#include "common.h"
|
|
|
|
#include "bdadebug.h"
|
|
|
|
#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
|
|
|
|
/**************************************************************/
|
|
/* Driver Name - Change the driver name to reflect your executable name! */
|
|
/**************************************************************/
|
|
|
|
#define MODULENAME "BDA Generic Tuner Sample"
|
|
#define MODULENAMEUNICODE L"BDA Generic Tuner Sample"
|
|
|
|
#define STR_MODULENAME MODULENAME
|
|
|
|
// This defines the name of the WMI device that manages service IOCTLS
|
|
#define DEVICENAME (L"\\\\.\\" MODULENAMEUNICODE)
|
|
#define SYMBOLICNAME (L"\\DosDevices\\" MODULENAMEUNICODE)
|
|
|
|
#define ATSC_RECEIVER 1
|
|
//#define DVBS_RECEIVER 1
|
|
// #define DVBT_RECEIVER 1
|
|
// #define CABLE_RECEIVER 1
|
|
|
|
// Must define exactly one of the 4 above
|
|
# if !(defined(ATSC_RECEIVER) || defined(DVBT_RECEIVER) || defined(DVBS_RECEIVER) || defined (CABLE_RECEIVER))
|
|
#error "Must define exactly one of ATSC, DVBT, DVBS or CABLE"
|
|
#endif
|
|
# if defined(ATSC_RECEIVER) && (defined(DVBT_RECEIVER) || defined(DVBS_RECEIVER) || defined (CABLE_RECEIVER))
|
|
#error “Multiple tranport definitions"
|
|
# elif defined(DVBT_RECEIVER) && (defined(ATSC_RECEIVER) || defined(DVBS_RECEIVER) || defined (CABLE_RECEIVER))
|
|
#error “Multiple tranport definitions"
|
|
# elif defined(DVBS_RECEIVER) && (defined(ATSC_RECEIVER) || defined(DVBT_RECEIVER) || defined (CABLE_RECEIVER))
|
|
#error “Multiple tranport definitions"
|
|
# elif defined(CABLE_RECEIVER) && (defined(ATSC_RECEIVER) || defined(DVBS_RECEIVER) || defined (DVBT_RECEIVER))
|
|
#error “Multiple tranport definitions"
|
|
#endif
|
|
|
|
#define MS_SAMPLE_TUNER_POOL_TAG 'TadB'
|
|
|
|
|
|
// Define a structure that represents what the underlying device can do.
|
|
//
|
|
// Note - It is possible to set conflicting settings. In this case, the
|
|
// CFilter::CheckChanges method should return an error. Only a
|
|
// self-consistent resource should be submitted to the underlying device.
|
|
//
|
|
typedef struct _BDATUNER_DEVICE_RESOURCE
|
|
{
|
|
// Tuner Resources
|
|
//
|
|
ULONG ulCarrierFrequency;
|
|
ULONG ulFrequencyMultiplier;
|
|
GUID guidDemodulator;
|
|
|
|
// Demodulator Resources
|
|
//
|
|
ULONG ulDemodProperty1;
|
|
ULONG ulDemodProperty2;
|
|
ULONG ulDemodProperty3;
|
|
} BDATUNER_DEVICE_RESOURCE, * PBDATUNER_DEVICE_RESOURCE;
|
|
|
|
|
|
// Define a structure that represents the underlying device status.
|
|
//
|
|
typedef struct _BDATUNER_DEVICE_STATUS
|
|
{
|
|
// Tuner Status
|
|
//
|
|
BOOLEAN fCarrierPresent;
|
|
|
|
// Demodulator Status
|
|
//
|
|
BOOLEAN fSignalLocked;
|
|
} BDATUNER_DEVICE_STATUS, * PBDATUNER_DEVICE_STATUS;
|
|
|
|
|
|
extern const KSDEVICE_DESCRIPTOR DeviceDescriptor;
|
|
|
|
//
|
|
// Define the filter class.
|
|
//
|
|
class CFilter {
|
|
public:
|
|
|
|
//
|
|
// Define the AVStream Filter Dispatch Functions
|
|
// Network provider and AVStream use these functions
|
|
// to create or remove a filter instance
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
Create(
|
|
IN OUT PKSFILTER Filter,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
FilterClose(
|
|
IN OUT PKSFILTER Filter,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
/**************************************************************/
|
|
/* Only used to process frames.
|
|
* Filters that transport data do not implement this dispatch function.
|
|
static
|
|
STDMETHODIMP
|
|
Process(
|
|
IN PKSFILTER Filter,
|
|
IN PKSPROCESSPIN_INDEXENTRY ProcessPinsIndex
|
|
);*/
|
|
/**************************************************************/
|
|
|
|
//
|
|
// KSMETHODSETID_BdaChangeSync
|
|
// Filter change sync methods
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
StartChanges(
|
|
IN PIRP pIrp,
|
|
IN PKSMETHOD pKSMethod,
|
|
OPTIONAL PVOID pvIgnored
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CheckChanges(
|
|
IN PIRP pIrp,
|
|
IN PKSMETHOD pKSMethod,
|
|
OPTIONAL PVOID pvIgnored
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CommitChanges(
|
|
IN PIRP pIrp,
|
|
IN PKSMETHOD pKSMethod,
|
|
OPTIONAL PVOID pvIgnored
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetChangeState(
|
|
IN PIRP pIrp,
|
|
IN PKSMETHOD pKSMethod,
|
|
OUT PULONG pulChangeState
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetMedium(
|
|
IN PIRP pIrp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN KSPIN_MEDIUM * pulProperty
|
|
);
|
|
|
|
//
|
|
// KSMETHODSETID_BdaDeviceConfiguration
|
|
// Methods to modify filter topology.
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
CreateTopology(
|
|
IN PIRP pIrp,
|
|
IN PKSMETHOD pKSMethod,
|
|
OPTIONAL PVOID pvIgnored
|
|
);
|
|
|
|
//
|
|
// Filter Implementation Methods
|
|
//
|
|
STDMETHODIMP_(class CDevice *)
|
|
GetDevice() { return m_pDevice;};
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PutFrequency(
|
|
IN ULONG ulBdaParameter
|
|
)
|
|
{
|
|
m_NewResource.ulCarrierFrequency = ulBdaParameter;
|
|
m_BdaChangeState = BDA_CHANGES_PENDING;
|
|
|
|
return STATUS_SUCCESS;
|
|
};
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetFrequency(
|
|
IN PULONG pulBdaParameter
|
|
)
|
|
{
|
|
*pulBdaParameter = m_CurResource.ulCarrierFrequency;
|
|
|
|
return STATUS_SUCCESS;
|
|
};
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
SetDemodulator(
|
|
IN const GUID * pguidDemodulator
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
SetDemodProperty1(
|
|
IN ULONG ulDemodProperty1
|
|
)
|
|
{
|
|
m_NewResource.ulDemodProperty1 = ulDemodProperty1;
|
|
m_BdaChangeState = BDA_CHANGES_PENDING;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetDemodProperty1(
|
|
IN PULONG pulDemodProperty1
|
|
)
|
|
{
|
|
if (pulDemodProperty1)
|
|
{
|
|
*pulDemodProperty1 = m_CurResource.ulDemodProperty1;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
SetDemodProperty2(
|
|
IN ULONG ulDemodProperty2
|
|
)
|
|
{
|
|
m_NewResource.ulDemodProperty2 = ulDemodProperty2;
|
|
m_BdaChangeState = BDA_CHANGES_PENDING;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetDemodProperty3(
|
|
IN PULONG pulDemodProperty3
|
|
)
|
|
{
|
|
if (pulDemodProperty3)
|
|
{
|
|
*pulDemodProperty3 = m_CurResource.ulDemodProperty3;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetStatus(
|
|
PBDATUNER_DEVICE_STATUS pDeviceStatus
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
SetDeviceState(
|
|
KSSTATE newKsState
|
|
)
|
|
{
|
|
m_KsState = newKsState;
|
|
return STATUS_SUCCESS;
|
|
};
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
AcquireResources();
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
ReleaseResources();
|
|
|
|
private:
|
|
class CDevice * m_pDevice;
|
|
|
|
// Filter Properties
|
|
//
|
|
|
|
// Filter Resources
|
|
//
|
|
KSSTATE m_KsState;
|
|
BDA_CHANGE_STATE m_BdaChangeState;
|
|
BDATUNER_DEVICE_RESOURCE m_CurResource;
|
|
BDATUNER_DEVICE_RESOURCE m_NewResource;
|
|
ULONG m_ulResourceID;
|
|
BOOLEAN m_fResourceAcquired;
|
|
};
|
|
|
|
//
|
|
// Define the device class.
|
|
//
|
|
class CDevice {
|
|
public:
|
|
|
|
//
|
|
// Define the AVStream Device Dispatch Functions
|
|
// AVStream uses these functions to create and start the device
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
Create(
|
|
IN PKSDEVICE pKSDevice
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
Start(
|
|
IN PKSDEVICE pKSDevice,
|
|
IN PIRP pIrp,
|
|
IN PCM_RESOURCE_LIST pTranslatedResourceList OPTIONAL,
|
|
IN PCM_RESOURCE_LIST pUntranslatedResourceList OPTIONAL
|
|
);
|
|
|
|
//
|
|
// Utility functions for the device
|
|
// An instance of the filter uses these functions
|
|
// to manage resources on the device.
|
|
//
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
InitializeHW(
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetStatus(
|
|
PBDATUNER_DEVICE_STATUS pDeviceStatus
|
|
);
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetImplementationGUID(
|
|
GUID * pguidImplementation
|
|
)
|
|
{
|
|
if (pguidImplementation)
|
|
{
|
|
*pguidImplementation = m_guidImplemenation;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetDeviceInstance(
|
|
ULONG * pulDeviceInstance
|
|
)
|
|
{
|
|
if (pulDeviceInstance)
|
|
{
|
|
*pulDeviceInstance = m_ulDeviceInstance;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
AcquireResources(
|
|
PBDATUNER_DEVICE_RESOURCE pNewResource,
|
|
PULONG pulAcquiredResourceID
|
|
);
|
|
|
|
NTSTATUS
|
|
UpdateResources(
|
|
PBDATUNER_DEVICE_RESOURCE pNewResource,
|
|
ULONG ulResourceID
|
|
);
|
|
|
|
NTSTATUS
|
|
ReleaseResources(
|
|
ULONG ulResourceID
|
|
);
|
|
|
|
|
|
private:
|
|
|
|
PKSDEVICE m_pKSDevice;
|
|
|
|
GUID m_guidImplemenation;
|
|
ULONG m_ulDeviceInstance;
|
|
BDATUNER_DEVICE_RESOURCE m_CurResource;
|
|
ULONG m_ulCurResourceID;
|
|
ULONG m_ulcResourceUsers;
|
|
};
|
|
|
|
|
|
//
|
|
// Define the Input-pin class.
|
|
//
|
|
class CAntennaPin {
|
|
public:
|
|
//
|
|
// Define the AVStream Pin Dispatch Functions
|
|
// Network provider and AVStream use these functions
|
|
// to create or remove a pin instance or to change the pin's
|
|
// state after the minidriver receives a connection state
|
|
// property 'set' IOCTL.
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PinCreate(
|
|
IN OUT PKSPIN Pin,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PinClose(
|
|
IN OUT PKSPIN Pin,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PinSetDeviceState(
|
|
IN PKSPIN Pin,
|
|
IN KSSTATE ToState,
|
|
IN KSSTATE FromState
|
|
);
|
|
|
|
//
|
|
// Define a data intersection handler function for the
|
|
// pin (KSPIN_DESCRIPTOR_EX structure).
|
|
// Network provider and AVStream use this function
|
|
// to connect the input pin with an upstream filter.
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
IntersectDataFormat(
|
|
IN PVOID pContext,
|
|
IN PIRP pIrp,
|
|
IN PKSP_PIN Pin,
|
|
IN PKSDATARANGE DataRange,
|
|
IN PKSDATARANGE MatchingDataRange,
|
|
IN ULONG DataBufferSize,
|
|
OUT PVOID Data OPTIONAL,
|
|
OUT PULONG DataSize
|
|
);
|
|
|
|
//
|
|
// Network provider and AVStream use these functions
|
|
// to set and get properties of nodes that are controlled
|
|
// by the input pin.
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetCenterFrequency(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PutCenterFrequency(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetSignalStatus(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
|
|
//
|
|
// Utility functions for the pin
|
|
//
|
|
STDMETHODIMP_(class CFilter *)
|
|
GetFilter() { return m_pFilter;};
|
|
|
|
STDMETHODIMP_(void)
|
|
SetFilter(class CFilter * pFilter) { m_pFilter = pFilter;};
|
|
|
|
private:
|
|
class CFilter* m_pFilter;
|
|
ULONG ulReserved;
|
|
KSSTATE m_KsState;
|
|
|
|
// Node Properties
|
|
//
|
|
BOOLEAN m_fResourceChanged;
|
|
ULONG m_ulCurrentFrequency;
|
|
ULONG m_ulPendingFrequency;
|
|
};
|
|
|
|
|
|
//
|
|
// Define the Output-pin class.
|
|
//
|
|
class CTransportPin{
|
|
public:
|
|
//
|
|
// Define the AVStream Pin Dispatch Functions
|
|
// Network provider and AVStream use these functions
|
|
// to create or remove a pin instance or to change the pin's
|
|
// state after the minidriver receives a connection state
|
|
// property 'set' IOCTL.
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PinCreate(
|
|
IN OUT PKSPIN Pin,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PinClose(
|
|
IN OUT PKSPIN Pin,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
//
|
|
// Define a data intersection handler function for the
|
|
// pin (KSPIN_DESCRIPTOR_EX structure).
|
|
// Network provider and AVStream use this function
|
|
// to connect the output pin with a downstream filter.
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
IntersectDataFormat(
|
|
IN PVOID pContext,
|
|
IN PIRP pIrp,
|
|
IN PKSP_PIN Pin,
|
|
IN PKSDATARANGE DataRange,
|
|
IN PKSDATARANGE MatchingDataRange,
|
|
IN ULONG DataBufferSize,
|
|
OUT PVOID Data OPTIONAL,
|
|
OUT PULONG DataSize
|
|
);
|
|
|
|
//
|
|
// BDA Signal Properties
|
|
//
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetSignalStatus(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PutAutoDemodProperty(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
#if !ATSC_RECEIVER
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetDigitalDemodProperty(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PutDigitalDemodProperty(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
#endif // !ATSC_RECEIVER
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
GetExtensionProperties(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
static
|
|
STDMETHODIMP_(NTSTATUS)
|
|
PutExtensionProperties(
|
|
IN PIRP Irp,
|
|
IN PKSPROPERTY pKSProperty,
|
|
IN PULONG pulProperty
|
|
);
|
|
|
|
STDMETHODIMP_(class CFilter *)
|
|
GetFilter() { return m_pFilter;};
|
|
|
|
STDMETHODIMP_(void)
|
|
SetFilter(class CFilter * pFilter) { m_pFilter = pFilter;};
|
|
|
|
private:
|
|
class CFilter* m_pFilter;
|
|
ULONG ulReserved;
|
|
KSSTATE m_KsState;
|
|
|
|
// Node Properties
|
|
//
|
|
BOOLEAN m_fResourceChanged;
|
|
ULONG m_ulCurrentProperty1;
|
|
ULONG m_ulPendingProperty1;
|
|
|
|
ULONG m_ulCurrentProperty2;
|
|
|
|
ULONG m_ulCurrentProperty3;
|
|
ULONG m_ulPendingProperty3;
|
|
};
|
|
|
|
//
|
|
// Topology Constants
|
|
//
|
|
typedef enum {
|
|
PIN_TYPE_ANTENNA = 0,
|
|
PIN_TYPE_TRANSPORT
|
|
} FilterPinTypes;
|
|
|
|
typedef enum {
|
|
INITIAL_ANNTENNA_PIN_ID = 0
|
|
} InitialPinIDs;
|
|
|
|
//
|
|
// Data declarations
|
|
//
|
|
|
|
extern const BDA_FILTER_TEMPLATE BdaFilterTemplate;
|
|
extern const KSFILTER_DESCRIPTOR InitialFilterDescriptor;
|
|
extern const KSFILTER_DESCRIPTOR TemplateFilterDescriptor;
|
|
|
|
|