IOCTL90 Physical Device Driver sample source code: Difference between revisions
Appearance
Created page with "By Joseph Nord This page shows example PDD source code for implementing Ioctl90 API in a device driver. Example code follows for Ioctl90 initialization, message dispatch and..." |
mNo edit summary |
||
| Line 1: | Line 1: | ||
By [[Joseph Nord]] | ''By [[Joseph Nord]]'' | ||
This page shows example PDD source code for implementing Ioctl90 API in a device driver. | This page shows example PDD source code for implementing Ioctl90 API in a device driver. Example code follows for Ioctl90 initialization, message dispatch and callback processing. | ||
Example code follows for Ioctl90 initialization, message dispatch and callback processing. | |||
* Last API update 16-Dec-1999. | * Last API update 16-Dec-1999. | ||
* Last document update 09-Aug-2003. | * Last document update 09-Aug-2003. | ||
For feeback, contact "joe" at this domain | For feeback, contact "joe" at this domain | ||
Example Callback initiated by PDD: | Example Callback initiated by PDD: | ||
Latest revision as of 15:11, 25 March 2018
By Joseph Nord
This page shows example PDD source code for implementing Ioctl90 API in a device driver. Example code follows for Ioctl90 initialization, message dispatch and callback processing.
- Last API update 16-Dec-1999.
- Last document update 09-Aug-2003.
For feeback, contact "joe" at this domain
Example Callback initiated by PDD:
// When a mixer application changes a mixer setting, the
// device driver informs all other mixer application of
// the change by posting event semaphores for each application.
void ioctlmixCallback (PSTREAM pStreamThis)
{
PSTREAM pStream;
USHORT usRC;
ULONG ulNumPosts;
ULONG ulNumPostsLin;
ULONG ulHev;
// To post an event semaphore, we need a linear address
// of where the kernel should place the post count.
usRC = DevHelp_VirtToLin (_SS(),
(USHORT)(&ulNumPosts),
&ulNumPostsLin);
if (usRC != 0)
{
#ifdef CSDEBUG
ddprintf (ERROR_MONITOR, "ioctlmixCallback VirtToLin failed\n");
DebugBreakpoint();
#endif
return;
}
// Each client mixer application creates its own semaphore.
// The semaphore must be "shared", but it is only shared between
// the application and this device driver.
pStream = streamGetListHead();
while (pStream != NULL)
{
// Only signal callback to mixer applications other than
// the one that commanded the change to the mixer.
// It already knows about the state change.
if (pStream != pStreamThis &&
pStream->ulCallbackSem != 0)
{
ulHev = pStream->ulCallbackSem;
// To post the sem, must open it from device driver.
// When post a sem, must also reset it or it will post forever
DevHelp_OpenEventSem (ulHev);
usRC = DevHelp_PostEventSem (ulHev);
#ifdef CSDEBUG
if (usRC != 0)
{
ddprintf (ERROR_MONITOR, "ioctlmixCallback PostEvent failed\n");
DebugBreakpoint();
}
#endif
DevHelp_ResetEventSem (ulHev, ulNumPostsLin);
DevHelp_CloseEventSem (ulHev);
}
pStream = pStream->pNext;
}
}
Example Device driver Ioctl90 message dispatch:
//
// Array of pointers to functions - dispatch table
//
USHORT (*ioctlmixFuncs[]) (PSTREAM pStream,
PMIXSTRUCT pMix,
USHORT usDLength) =
{
ioctlmix_MonoInSet, // 40 Set functions in 0x40 range
ioctlmix_Unused, // 41 ioctlmix_PhoneSet
ioctlmix_MicSet, // 42
ioctlmix_LineSet, // 43
ioctlmix_CDSet, // 44
ioctlmix_Unused, // 45 ioctlmix_VideoSet
ioctlmix_AuxSet, // 46
ioctlmix_Unused, // 47
ioctlmix_Unused, // 48
ioctlmix_Unused, // 49
ioctlmix_Unused, // 4A
ioctlmix_Unused, // 4B ioctlmix_BassTrebleSet
ioctlmix_ThreeDSet, // 4C
ioctlmix_StreamVolSet, // 4D
ioctlmix_RecordSrcSet, // 4E
ioctlmix_RecordGainSet, // 4F
ioctlmix_Unused, // 50
ioctlmix_Unused, // 51
ioctlmix_Unused, // 52
ioctlmix_Unused, // 53
ioctlmix_Unused, // 54
ioctlmix_Unused, // 55
ioctlmix_Unused, // 56
ioctlmix_Unused, // 57
ioctlmix_Unused, // 58
ioctlmix_Unused, // 59
ioctlmix_Unused, // 5A
ioctlmix_Unused, // 5B
ioctlmix_Unused, // 5C
ioctlmix_Unused, // 5D
ioctlmix_Unused, // 5E
ioctlmix_Unused, // 5F
ioctlmix_MonoInQuery, // 60 Query functions in 0x40 range
ioctlmix_Unused, // 61 ioctlmix_PhoneQuery
ioctlmix_MicQuery, // 62
ioctlmix_LineQuery, // 63
ioctlmix_CDQuery, // 64
ioctlmix_Unused, // 65 ioctlmix_VideoQuery
ioctlmix_AuxQuery, // 66
ioctlmix_Unused, // 67
ioctlmix_Unused, // 68
ioctlmix_Unused, // 69
ioctlmix_Unused, // 6A
ioctlmix_Unused, // 6B ioctlmix_BassTrebleQuery
ioctlmix_ThreeDQuery, // 6C
ioctlmix_StreamVolQuery, // 6D
ioctlmix_RecordSrcQuery, // 6E
ioctlmix_RecordGainQuery, // 6F
ioctlmix_Unused, // 70
ioctlmix_Unused, // 71
ioctlmix_Unused, // 72
ioctlmix_Unused, // 73
ioctlmix_Unused, // 74
ioctlmix_Unused, // 75
ioctlmix_Unused, // 76
ioctlmix_Unused, // 77
ioctlmix_Unused, // 78
ioctlmix_Unused, // 79
ioctlmix_Unused, // 7A
ioctlmix_Unused, // 7B
ioctlmix_Unused, // 7C
ioctlmix_Unused, // 7D
ioctlmix_Unused, // 7E
ioctlmix_Unused, // 7F
ioctlmix_APILevelQuery, // 80
ioctlmix_GetAPIMap, // 81
ioctlmix_CallbackReg, // 82
ioctlmix_MsgBuf // 83
};
BYTE MaxIoctlmixFuncs = sizeof(ioctlmixFuncs)/sizeof(ioctlmixFuncs[0])-1;
// This function services all audio control requests from the ioctl
// interface.
// The parameter 'function' is number of the request. The parameter 'bufP'
// is a pointer to a buffer containing information specific to the request.
// The parameter 'sys_file_num' contains the system file number unique to
// the session issuing the ioctl.
// The function returns information specific to the request in the buffer
// pointed to by 'bufP'. Also, the function returns the value 0 if successful.
USHORT ioctlmixMain (USHORT Function,
USHORT SysFileNum,
PVOID pvData,
USHORT usDLength)
{
PSTREAM pStream;
USHORT usRC;
Function -= 0x40; // Function numbers start at 0x40.
if (Function > MaxIoctlmixFuncs)
{
usRC = RPBADCMD;
}
else
{
// get the stream pointer from the system file number
pStream = streamGetFromSysFileNum (SysFileNum);
if (pStream == NULL)
{
// If open/close logic is working, this error
// case should never happen.
#ifdef CSDEBUG
ddprintf (ERROR_MONITOR,
"IOCTL: Main - Stream lookup failed, sysfile %x\n",
SysFileNum);
#endif
usRC = RPGENFAIL;
}
else if (pvData == NULL)
{
#ifdef CSDEBUG
ddprintf (ERROR_MONITOR,
"ERR: ioctlmixMain pvData is NULL.\n");
#endif
usRC = RPINVPARM;
}
else
{
usRC = ioctlmixFuncs [Function] (pStream,
(PMIXSTRUCT)pvData,
usDLength);
}
}
return (usRC);
}
Example device driver Ioctl90 initialization:
void ioctlmixInit (void)
{
unsigned I;
// Verify that ioctlmixCheckTable has correct number of entries.
// That is, runtime verify that positions in dispatch table are
// consistent with header file defines for use by applications.
if (MaxIoctlmixFuncs != MSGBUF - 0x40)
{
#ifdef CSDEBUG
ddprintf (ERROR_MONITOR,
"ioctlmixInit Dispatch table size is wrong!!!\n");
#endif
ProductionBreakpoint();
}
// Ability to support 3D sound effect is not supported
// on all the hardware configurations.
if (!mix3DSupported())
{
ioctlmixFuncs[THREEDSET-0x40] = ioctlmix_Unused;
ioctlmixFuncs[THREEDQUERY-0x40] = ioctlmix_Unused;
}
// Fill in bSupport table. Indicate which of the
// possible 256 IOCTL functions this driver supports.
for (I = 0; I <= 0xFF; I++)
{
if (I >= 0x40 && I - 0x40 <= MaxIoctlmixFuncs)
{
// A function is "supported" if it has an entry in dispatch table.
ioctl90SupportTable[I] = (ioctlmixFuncs[I-0x40] != ioctlmix_Unused);
}
else
{
// All entries outside our table bounds are not supported.
ioctl90SupportTable[I] = FALSE;
}
}
}