All audio device drivers are installable drivers and must provide a DriverProc entry point. Installable drivers and the DriverProc entry point are described in the manuals included with the Microsoft Windows Software Development Kit.
Installable drivers can supply a configuration dialog box for users to access through the Drivers option in the Control Panel. If your device driver supports different interrupt-level and port assignments, it should allow user configuration through the Drivers option in the Control Panel.
Interrupt-level and port assignments, and any other hardware-related settings, should be stored in a section with the same name as the driver in the user's SYSTEM.INI file. To conform to other Windows drivers, use the key names “int” and “port” to specify interrupt-level and port assignments. For example, the following SYSTEM.INI section specifies interrupt level 3 and port 0x220 for the Sound Blaster driver:
[sndblst.drv]
int=3
port=220
Regardless of how many types of audio devices a driver supports, the driver will always have a single DriverProc function. The following example is the DriverProc function from the Sound Blaster driver, which supports four types of audio devices.
LRESULT FAR PASCAL _loadds DriverProc(DWORD dwDriverID, HDRVR hDriver, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
{
switch (uMsg)
{
case DRV_LOAD:
return (LRESULT)1L;
case DRV_FREE:
return (LRESULT)1L;
case DRV_OPEN:
return (LRESULT)1L;
case DRV_FREE:
return 1L;
case DRV_OPEN:
return 1L;
case DRV_CLOSE:
return (LRESULT)1L;
case DRV_ENABLE:
/* Enable the driver: set up hardware, hook interrupts,
* allocate DMA buffer, etc. Note that you cannot fail
* the DRV_ENABLE message; the return value is ignored.
*/
Enable();
return (LRESULT)1L;
case DRV_DISABLE:
/* Disable the driver: free DMA buffer, unhook interrupts
* reset hardware, etc.
*/
Disable();
return (LRESULT)1L;
case DRV_QUERYCONFIGURE:
/* This driver supports configuration
*/
return (LRESULT)1L;
case DRV_CONFIGURE:
/* Configure the driver: display a dialog box that allows
* the user to configure the driver. For example, setting
* the port base and interrupt. Return DRVCNF_RESTART if
* Windows needs to be restarted before the changes take
* affect.
*/
return (LRESULT)Config(LOWORD(lParam1), ghModule);
case DRV_INSTALL:
return (LRESULT)DRVCNF_RESTART;
case DRV_REMOVE:
/* Remove the driver: the drivers applet will send this
* message when the driver is being removed from the
* installed drivers list. The driver should remove its
* .INI section, etc.
*/
ConfigRemove();
return (LRESULT)DRVCNF_RESTART;
default:
return DefDriverProc(dwDriverID, hDriver, uMsg, lParam1, lParam2);
}
}
This DriverProc function calls two functions, Enable and Disable to do the work of enabling and disabling the driver. These functions are part of the driver. Their implementation is dependent upon the target hardware and the structure of the driver.
Generally, when a driver is enabled, you initialize the hardware, hook interrupts, allocate any memory that you need, and set a flag to indicate the driver is enabled. If your driver has not been enabled by MMSYSTEM, or if it failed the enable process, the driver should return MMSYSERR_NOTENABLED from any messages it receives from client applications. When a driver is disabled, you free any memory that you allocated, unhook interrupts, reset the hardware, and set a flag to indicate the driver is not enabled.
It's possible for a driver to receive a DRV_DISABLE message while it is in the process
of sending or receiving audio data. For example, this can happen when the user switches
to a MS-DOS application when Windows is running in standard mode. Audio device drivers should follow the behavior specified in the following table when they receive a DRV_DISABLE/DRV_ENABLE message pair:
Driver Type | Disable/Enable Behavior |
waveform output | As if the driver were paused with a WODM_PAUSE message and then restarted with a WODM_RESTART message. |
waveform input | As if the driver were stopped with a WIDM_STOP message and then restarted with a WIDM_START message. |
MIDI output | If the driver is asynchronous, stop output when disabled and continue when reenabled. |
MIDI input | As if the driver were stopped with a MIDM_STOP message and then restarted with a MIDM_START message. |