Sysdriver: How to capture Input data and play user audio application data

Dear Tim,

i tried with below code

NTSTATUS MiniportTopology::PropertyHandlerJackDescription
(
In PPCPROPERTY_REQUEST PropertyRequest
)
/*++

Routine Description:

Handles ( KSPROPSETID_Jack, KSPROPERTY_JACK_DESCRIPTION )

Arguments:

PropertyRequest -
cJackDescriptions - # of elements in the jack descriptions array.
JackDescriptions - Array of jack descriptions pointers.

Return Value:

NT status code.

–*/
{
PAGED_CODE();

ASSERT(PropertyRequest);

DPF_ENTER(("[PropertyHandler_MicInJackDescription]"));

NTSTATUS                ntStatus = STATUS_INVALID_DEVICE_REQUEST;
ULONG                   nPinId = (ULONG)-1;

ULONG                   cJackDescriptions = ARRAYSIZE(MicInJackDescriptions);
PKSJACK_DESCRIPTION* JackDescriptions = MicInJackDescriptions;

if (PropertyRequest->InstanceSize >= sizeof(ULONG))
{
    nPinId = *(PULONG(PropertyRequest->Instance));

    if ((nPinId < cJackDescriptions) && (JackDescriptions[nPinId] != NULL))
    {
        if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
        {
            ntStatus =
                KsHelper::PropertyHandler_BasicSupport
                (
                    PropertyRequest,
                    KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_GET,
                    VT_ILLEGAL
                );
        }
        else
        {
            ULONG cbNeeded = sizeof(KSMULTIPLE_ITEM) + sizeof(KSJACK_DESCRIPTION);

            if (PropertyRequest->ValueSize == 0)
            {
                PropertyRequest->ValueSize = cbNeeded;
                ntStatus = STATUS_BUFFER_OVERFLOW;
            }
            else if (PropertyRequest->ValueSize < cbNeeded)
            {
                ntStatus = STATUS_BUFFER_TOO_SMALL;
            }
            else
            {
                if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
                {
                    PKSMULTIPLE_ITEM pMI = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
                    PKSJACK_DESCRIPTION pDesc = (PKSJACK_DESCRIPTION)(pMI + 1);

                    pMI->Size = cbNeeded;
                    pMI->Count = 1;
                    pDesc->IsConnected = FALSE;/////////////////////////setting it to false
                    RtlCopyMemory(pDesc, JackDescriptions[nPinId], sizeof(KSJACK_DESCRIPTION));
                    ntStatus = STATUS_SUCCESS;
                }
            }
        }
    }
}

return ntStatus;

}

where I set pDesc->IsConnected to FALSE even after that I can see virtual mic in sound control panel…am I doing something wrong

this API is getting called.

got it fixed

i was setting at wrong place

static
KSJACK_DESCRIPTION MicInJackDesc =
{
KSAUDIO_SPEAKER_MONO,
JACKDESC_RGB(179, 201, 140),
eConnTypeCombination,
eGeoLocRear,
eGenLocPrimaryBox,
ePortConnJack,
FALSE//TRUE///////////////////////////it works
};

Dear Tim ,

I have done some code change as per your suggestion.

inside IOCTL:
MicInJackDesc.IsConnected = FALSE

inside topology properties class:

static PCEVENT_ITEM JackInfoChangeEvent =
{
{
&KSEVENTSETID_PinCapsChange, // Something changed
KSEVENT_PINCAPS_JACKINFOCHANGE, // Jack Info Changes
KSEVENT_TYPE_ENABLE | KSEVENT_TYPE_BASICSUPPORT,
CMiniportTopology_EventHandler_JackState
}
};

DEFINE_PCAUTOMATION_TABLE_PROP_EVENT(AutomationMicInTopoFilter, PropertiesTopoFilter, JackInfoChangeEvent);

inside topology class:

NTSTATUS CMiniportTopology_EventHandler_JackState
(
In PPCEVENT_REQUEST EventRequest
)
{
DPF_ENTER((“[CMiniportTopologySYSVAD::CMiniportTopology_EventHandler_JackState]”));
PCMiniportTopology miniport = reinterpret_cast(EventRequest->MajorTarget);
if (EventRequest->Verb == PCEVENT_VERB_ADD)
{
miniport->AddEventToEventList(EventRequest->EventEntry);
}
return STATUS_SUCCESS;
}

even after that its not working, do I need to call GenerateEventList also??
is there any thing else required???will this CMiniportTopology_EventHandler_JackState get called automatically and remove the mic from sound control panel after I set MicInJackDesc.IsConnected = FALSE in my IOCTL……plz advice

That’s 99% of it. The only thing remaining is that you need to TRIGGER the event by calling m_PortEvents->GenerateEventList when you change the jack state.

Dear Tim,

inside below api i am calling GenerateEventList

NTSTATUS CMiniportTopology_EventHandler_JackState
(
In PPCEVENT_REQUEST EventRequest
)
{
DPF_ENTER((“[CMiniportTopologySYSVAD::CMiniportTopology_EventHandler_JackState]”));
PCMiniportTopology miniport = reinterpret_cast(EventRequest->MajorTarget);
if (EventRequest->Verb == PCEVENT_VERB_ADD)
{
miniport->AddEventToEventList(EventRequest->EventEntry);
}
miniport->GenerateEventList(
(GUID*)&KSEVENTSETID_PinCapsChange, // event set. NULL is a wild card for all events.
KSEVENT_PINCAPS_JACKINFOCHANGE, // event ID.
TRUE, // use pid ID.
(int)TopologyPin::Microphone, // pin ID.
FALSE, // do not use node ID.
ULONG(-1)); // node ID, not used.
return STATUS_SUCCESS;
}

am I doing correct??

Hi Tim,

refering to above post,looks like calling GenerateEventList inside CMiniportTopology_EventHandler_JackState api is not correct, may I know from where and how to call GenerateEventList .

need your help to understand this.

Thanks

No, you didn’t read what I wrote. Whenever YOU change the jack state, YOU need to call GenerateEventList. That EventHandler_JackState function is called by port class to get the event registered. Leave that the way it was.

Hi Tim,

I am facing buffer overflow issue.

I am using ring buffer to store audio data in driver, from that ringbuffer i am fetching and assigning to mdl buffer.
but after 5 min ringbuffer overflows and after that i start getting some noise instead of actual audio.

how to avoid this buffer overflow .
need your help.

It probably means that the clock on your data source does not exactly match the clock in your receiving system. Common problem. You need to be able to handle that, usually by dropping the oldest samples. You will get one click, then it should resume until it fills again.

If you’re serious about quality, so one glitch in 5 minutes isn’t acceptable, then you need to monitor the circular buffer level, and use that to make fractional adjustments in your sample rate.

Hi Tim,

What could be the reason of audio delay in virtual mic.
I am getting approx 2 sec delay in audio.

Two seconds delay based on what? How are you measuring that? That usually means your circular buffer is too large. If you have a 200k byte circular buffer, that would hold 2 seconds of 48kHz mono 16-bit PCM audio. If your data is coming in from a network source, you could also be seeing network delays.

Hi Tim,

I am using Ioctl to hide the virtual audio mic from sound control panel recording section, but when i restart the system it automatically comes again

may i know the reason??
is it happening because by default i am showing the driver under recording section??

plz advice.

thanks …

How (and why) are you hiding your microphone? The audio system tries to be uniformly fair. If you look like a microphone, then you’ll be listed as a microphone device.

actually requirement is like that,based on some condition it should show and hide from sound control panel but always present in device manager. this i achieved but when i hide after system restart it comes again

actually KSJACK_DESCRIPTION, has a member IsConnected that says whether something is plugged in. If that member is false, you’ll be in Device Manager, but will not be an audio device. this is what i am doing just setting the bit using ioctl

Is it possible that when i install the virtual driver that time it should only be inside device manager untill i send ioctl to show it inside sound panel recording section???

Right, that’s what I do, too. Just hake sure your initial KSJACK_DESCRIPTION structure shows unplugged. It should stay invisible until an ioctl turns it back on. That works for me. If your global KSJACK_DESCRIPTION starts out plugged, that would explain what you see.

got it resolved, actually by default IsConnected was set to true now made it false , and setting it to true using Ioctl as per my requirement.

thanks.

Hello chauhan, I am also developing a Windows virtual Mic driver. I need to send the PCM data received by the upper-layer application to the virtual Mic driver through IOCTL. Other applications can receive the corresponding sound data when this virtual Mic is selected. See Everyone’s discussion, I hope you can give me some help, is it convenient to contact me: feddi1998@sohu.com

What help do you need? How much code do you already have? This is not a free consulting service. It’s a place to get advice.