OS/2 IOCTL90 Mixer Programming Specification
Joe Nord

The category 0x90 mixer IOCTLs define an interface between application level mixer programs and audio device drivers (PDDs) on OS/2 platforms.  

Last API update 14-May-2002.
Last document update 09-Aug-2003

The IOCTLs were invented to expand on the operating system base APIs (The 0x80 APIs) to make it possible for a user to control the listening level of a CD-ROM or other source which is not controllable via the standard MMPM/2 API.  The original driving application was a tuner application for a FM radio card connected to the sound cards line-in jack.  With the base operating system defined interfaces, there was no means to control the relative sound level of the line input to the sound card.

Note: In this document, "the operating system APIs" refer to the original OS/2 mixer definition.  There does exist an exhanced mixer interface which can do many of the things that Ioctl90 provides, but the operating system defined enhanced mixer interface has some issues in implementation which prevented wide spread acceptance.  

CD-DA Listening level
The other driving force in the development of Ioctl90 was a means to adjust the relative volume of CD-DA playback.

Users will note that the OS/2 shipped CD-Player application includes a volume slider. This slider adjust the CD-ROM playback volume at the CD-ROM unit. The analog signal from the CD-ROM player is provided to the system audio device via an analog cable. Under MMPM/2, there is no means to adjust the volume of this signal at the audio device.
Master volume can be adjusted and wave volume can be adjusted, but the relative volume of the CD input cannot be adjusted with just the MMPM/2 API.

The category 90 mixer IOCTLs fill this gap and the text below is the API specification.  Example code is provided for both physical device driver implementation as well as mixer application implementation.

The IOCTLs also support volume control for various other inputs to the audio device mixer and the ability to override record gain and stream volume for execution of WinOS2 and other applications that do not implement their own sliders for these controls.

For feedback, send email - "joe" at this domain.

Example code

STATUS (Drivers known to implement this API)

If your device driver supports the Ioctl90 API and you would like to be listed above, send me a note.

Limitations and differences from Windows mixer definitions

A programmer will note that this API does not address some of the common features of a mixer application.  The most notable missing function is Master Volume.

The IOCTL90 definition attempts to not redefine things that are already defined in MMPM/2 API. Exceptions are made for record gain, record source and stream volume, but these exceptions are kept to a minimum to avoid complicating the progamming of an audio device driver.

A developed mixer application is expected to use a combination of the standard MMPM/2 APIs (via MCI commands) along with the the Category 0x90 IOCTLs defined in this file.

Master Volume
MMPM/2 defines master volume and the operating system ships a master volume application. The standard application works.  Since master volume is already handled by the MMPM/2 API, it is not re-invented in the category 90 IOCTLs.  Mixer application developers COULD issue appropriate MCI commands to adjust master volume outside IOCTL90.    They are encouraged to not implement master volume in the mixer application.

The OS/2 shipped "Volume Control" application is not very robust. It provides no means for message callbacks.  That is, there can be at-most ONE controller of master volume in the system as any change of master volume by a secondary application cannot be reflected on the GUI of the OS/2 standard volume control application.

Per-Stream Volume and Per-Stream Gain
On OS/2, wave audio volume, record gain and record source are defined as per-stream concepts. This is very different than Windows where application volume and gain are defined as system global.

On OS/2, any external set of wave playback or capture volume are system defined to be un-done
when a stream is started.  Volume and gain are supposed to be different for each application and
each application is expected to implement sliders to support adjustment of its stream volume and gain (and most do).

Unfortunately, a sufficiently large number of applications do not.  Usually, this is due to the application being ported from Windows environment where the support of a global external mixer was assumed.

IOCTL90 allows the mixer application to override MMPM/2 per-stream volume and record gain.  These are not required elements for implementation of a supporting device driver, but they may be implemented to support these applications.

This ability to override stream playback and capture volumes is most useful for execution of Windows multimedia
applications inside WinOS2.   By allowing the OS/2 native mixer to control these settings globally, the OS/2 mixer
can effect record gain, record source and playback volumes for WinOS2 applications.

This eliminates the need for a WinOS2 mixer application.


Hardware mixer model

The Category 0x90 mixer IOCTLs are modeled on the Intel AC97 Audio CODEC definition.

The same hardware architecture is used by numerous audio system venders, thus promoting the portability of the IOCTL90 mixer API.  The AC97 is also a "fairly simple" mixer device and can therefore be emulated on many other more full-function devices, again promoting portability of the API.

For details on the AC97 mixer architecture, consult this data sheet, Crystal Clear(tm) SoundFusion(tm) Audio Codec '97 (CS4297A)

All Set/Get functions accept a single parameter (data block pointer) which has this definition:

typedef struct
{
   ULONG Mute;                  // UnMute==0, Mute==1
   ULONG VolumeL;               // 0..100 percent
   ULONG VolumeR;               // 0..100 percent
} MIXSTRUCT, *PMIXSTRUCT;
The IOCTLs in the 0x40 and 0x60 range are nearly self explanatory.  (Get/Set volume).

The 0x80 and 0x81 APIs were added after external review to improve evolution of the API.

The query APIs return the value most recently written, not a calculated value based on
the setting read from the hardware.  This avoids granularity issues of the physical device
hardware (often only 32 possible settings) versus 101 possible volume settings in the API (0..100 percent).


40 - MonoInSet

Set volume of system Mono input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Volume range 0..100
Right Not used.  Set = Left.

Connection:
In most add-in card systems, this input is not used.
In many motherboard installations, this input is used for PC Speaker (beeps and clicks).
It is also used on motherboard systems for the audible signal from internal modems.

The device driver takes the MONO volume from the "left" field of the passed structure.
Application should fill in "right" field of structure with same value set for left.
 
41 - PhoneSet

Set volume of system Phone input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
In most add-in card systems, this input is not used.
In many PCI audio motherboard installations, this input is used connection from internal modem.

42 - MicSet

Set volume of system microphone.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
This IOCTL sets the listening level of the system microphone.  System microphone is normally muted.
It can be un-muted to enable karoke mode.

Note: This IOCTL does not effect the record level for microphone.

43 - LineSet

Set volume of system Line-In connection

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
Line-In is normally an input on the system sound card - accessible on the back of the computer system.

44 - CDSet

Sets the listening level of the CD-ROM analog signal input to the audio device.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
CD-ROM input to sound card volume is controlled with this API.

This input is normally connected to the sound card via connector inside the PC system unit.  The signal controlled with this API is that which arrives on the analog cable from the CD-ROM drive.

Note:
If CD-DA digital streaming is being used, the sound card views the CD data as normal wave-audio.   That is, this API will not effect CD-ROM lisenting level if CD-DA digital streaming is being used (CD player application choice).

45 - VideoSet

Sets the listening level of the sound card "video" input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
On equiped systems, effects the lisenting level of movie playback.
Most systems do not used this mixer input.

46 - AuxSet

Sets the listening level of the sound card "aux" input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
On equiped systems, effects the lisenting level of aux input.
AC97 systems include an Aux connection that may or may not actually be populated on system.
Most ISA devices do not include an Aux connector.

48 - SPDIFSet

Sets the listening level of the sound card "S/PDIF" input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
On equiped systems, effects the lisenting level of S/PDIF input.

4B - BassTrebleSet

Change Bass and Treble settings

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute (flags) not used, set to 0
Left (Bass) 0..100
Right (Treble) 0..100

Connection:
Bass and Treble are not part of the AC97 mixer definition.

They are implemented on some audio devices as a post processing algorithm
applied to the output of audio device.  Bass and Treble effect the sound level
of low frequency and high frequency sounds independent of volume.

A device driver can indicate support for Bass only, Treble only or both via
the BassTrebleQuery API.

Device drivers  default both bass and treble to 50%.
A setting of 50% means no effect to the audio signal.

4C - ThreeDSet

Enables or disables 3D sound effect.  Popular algorithms include SRS and QSOUND.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute (enable) 0x01=No 3D (Muted)
0x00=Enabled 
Left (Space) 0..100
Right (Center) 0..100

Connection:
3D is a post processing algorithm applied to the output of audio device to
artificially make the speakers sound like they are further apart.

A device driver can indicate support for Space and Center via the ThreeDQuery API.

Enable flags:
Application should set only bit D0.  Other bits should be zero.
Device driver should reference only bit D0.  Other bits are don't care.

4D - StreamVolSet

Sets the stream playback volume globally - disabling MMPM/2 per-stream volume.
Notice that this API is redundent to and overrides the MMPM/2 defined concept of per-stream volume.

This API is implemented as counterpart to function 4F RecordGainSet.

Introduced: API Level 2

All device drivers implementing this IOCTL are expected to return API level 2 or
beyond on API level query IOCTL.

Parameters (PMIXSTRUCT).
 
Mute (Flags) 0x0001=>Mute 0x0002=>Release
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
Overrides MMPM/2 per-stream volume.
Note, this API does not effect system master volume.

4E - RecordSrcSet

Overrides MMPM/2 defined per-stream record source.

Provided record source will be used as global record source.
Call with "release" bit set in flags to return control to MMPM/2.

Introduced: API Level 2

Parameters (PMIXSTRUCT).
 
Mute (Flags) 0x0002=>Release
Left Record Source
Right Not used, set to 0

Record Source Definition
0x00000000..0x0000000F Reserved
0x00000010 Mic
0x00000020 CD-ROM
0x00000040 Video
0x00000080 Aux
0x00000100 Line
0x00000200 Loopback
0x00000400 SPDIF
0x00000800 Phone

On query, device driver indicates whether or not it supports input mixer.

If input mux, mixer application can set only one source as input.
If input mixer, mixer application can OR on appropriate bits.

Application should use results of function 81 (function support map) to know
which inputs the device supports.

For many AC97 based implementations, the bit value from this API can be shifted and placed in the hardware MUX
register with no modification.    There are execptions:

The AC97 hardware definition includes two "Loopback" entries (one for stereo, one for mono). 
The audio driver already knows how many channels are involved based on the stream initialization and
accordingly only needs to define a single "Looback" record source.  These are position 5 and 6.  One is redundent.
By definition, the "5" position (Stereo loop) is defined in Ioctl90 as "Loopback" and covers both stereo and mono loopback.

The S/PDIF capture record source is defined to occupy the position of the mono record source.

Device Specific Notes:
On the Crystal Semiconductor ISA Mode 3 device driver, (CS4236B/7B/8B, CS4235, CS4239):
MONO-IN is a playback source and its volume can be adjusted via function 0x40.
MONO-IN however is not a possible record source.    The device driver treats a request to
record from MONO-IN as a request to record from NULL device (no sound).

4F - RecordGainSet

Sets the record gain globally - disabling MMPM/2 per-stream record gain.
Notice that this API is redundent to and overrides the MMPM/2 defined concept of per-stream record gain.

It can be argued that this API should only effect record gain for WinOS2.
MMPM/2 already defines record gain as a concept for OS/2 applications.

The API exists for two primary reasons

This API changes definition of record gain from a MMPM/2 per-stream concept to a
mixer application global concept.  Once this IOCTL is sent, record gain is global.
The gain sent from the mixer application overrules the per-stream gain sent from MMPM/2.

API Level 2 includes the ability for the mixer application to return control of
gain to traditional MMPM/2 per-stream definition.

Introduced: API Level 1, Current implementation requires API level 2 (for release)

Parameters (PMIXSTRUCT).
 
Mute (Flags) 0x0001=>Mute 0x0002=>Release
Left Left volume range 0..100
Right Not used, set to 0

Connection:
Sets the record gain setting just before the Analog/Digital converter inside the AC97 mixer.
This API effects what you "record", not what you "hear".

Notes:
Crystal Semiconductor drivers 2.08 (ISA) and 3.03 (PCI) implement this API, but implement
it only with global effect (API level 1).

Crystal Semiconductor driver 2.09 (ISA) implements this API at API level 2.
That is, the "release" bit is defined and recognized by the device driver.

In API level 2, the mixer definition was enhanced to allow the mixer to return record gain to be a per-stream concept.
That is, to cancel the override and again place record gain into the control of MMPM/2.


60 - MonoInQuery

Query volume of system Mono input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Volume range 0..100
Right Not used, PDD will set to 0 

Connection:
In most add-in card systems, this input is not used.
In many motherboard installations, this input is used for PC Speaker (beeps and clicks).
It is also used on motherboard systems for the audible signal from internal modems.

The device driver sets the left field to value for mono volume.

61 - PhoneQuery

Query volume of system Phone input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
In most add-in card systems, this input is not used.
In many motherboard installations, this input is used connection from internal modem.

62 - MicQuery

Query volume of system microphone.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
This IOCTL sets the listening level of the system microphone.  System microphone is normally muted.
It can be un-muted to enable karoke mode.

Note: This IOCTL does not effect the record level for microphone.

63 - LineQuery

Query volume of system Line-In connection

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
Line-In is normally an input on the system sound card - on the back of the PC system unit.

64 - CDQuery

Query the listening level of the CD-ROM analog signal input to the audio device.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
CD-ROM input to sound card volume is controlled with this API.

If CD-DA digital streaming is being used, the sound card views the CD data as wave-out.   That is, this API will not effect CD-ROM lisenting level if CD-DA digital streaming is being used (CD player application choice).

65 - VideoQuery

Query the listening level of the sound card "video" input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
On equiped systems, effects the lisenting level of movie playback.
Most systems do not used this mixer input.

66 - AuxQuery

Queries the listening level of the sound card "aux" input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
On equiped systems, effects the lisenting level of aux input.
AC97 systems include an Aux connection that may or may not actually be populated on system.
Most ISA devices do not include an Aux connector.

68 - SPDIFQuery

Queries the listening level of the sound card "S/PDIF" input.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute 0=>Audible, 1=>Mute
Left Left volume range 0..100
Right Right volume range 0..100

Connection:
On equiped systems, effects the lisenting level of S/PDIF input.

6C - ThreeDQuery

Queries 3D sound effect.  Popular algorithms include SRS and QSOUND.

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute (flags) D0 = 1 3D Is off (muted)
D0 = 0 3D Enabled 
D1 = Space is supported
D2 = Center is supported
Left (Space) 0..100
Right (Center) 0..100

A device driver implementing support for 3D sound effect may or may not
support Space and Center.  Both are independently programmable items.
The device driver will turn on the 0x02 and 0x04 bits to indicate which
of the slider options can be implemented in mixer application.

The 0x01 bit indicates the current state of 3D effect.  If bit is on, 3D is enabled.

6B - BassTrebleQuery

Query Bass and Treble settings

Introduced: API Level 1

Parameters (PMIXSTRUCT).
 
Mute (flags) 0x0001 - Bass is supported
0x0002 - Treble supported
Left (Bass) 0..100
Right (Treble) 0..100

Connection:
See the BassTrebleSet API for description for details on Bass and Treble.

Device driver returns current setting for Bass and Treble and bit flags
indicating which Bass/Treble adjustements are supported by the device.

If either Bass or Treble is not supported, the matching bit in the flags
will be off and the Left/Right field of the returned parm will be 0.

A device driver implementing this Ioctl must support at least
one of the adjustable settings (Bass/Treble).

6D - StreamVolQuery

Query the global stream volume.

See function 4D (StreamVolSet) for a detailed description of this APIs behavior.

Introduced: API Level 2

Parameters (PMIXSTRUCT).
 
Mute (flags) 0x0001=>Mute  0x0002=>Release
Left Left volume range 0..100
Right Right volume range 0..100

API Level 2:
The Mute field is a bit mask (flags).
Bit 0x00000001 -  If true, then stream volume is muted.
Bit 0x00000002 -  If true, then stream volume is "released" to MMPM/2 control.

Notes:
The values returned are dependent on who controls the record gain.
If under MMPM/2 control (mixer has released), then the mute and volume
levels returned reflect the most recent value programmed from MMPM/2.

If mixer application is controlling the setting, then the values returned
for mute and volume are the most recent values sent via function 4F.
Note, the values returned may reflect the values sent from a different
mixer application (multiple mixer clients).

6E - RecordSrcQuery

Query global record source.

Introduced: API Level 2

Parameters (PMIXSTRUCT).
 
Mute (Flags) 0x0001=>Reserved
0x0002=>Release
0x0004=>Input mixer
Left Record Source
Right Not used, set to 0

See function 4E for definition of record sources.

The record source value returned is dependent on who controls the record source.

Bit D1 will be set in the flags field to let the mixer application know
if record source definition is global (0) or MMPM/2 per-stream (1).

Bit D2 will be set in the flags field to indicate that the device supports an
input mixer rather than the AC97 standard input mux.

If under MMPM/2 control (mixer has released), then
1) The record source is a per-stream concept.
2) The record source returned represents the record source most recently
    set by MMPM/2.  This allows the mixer application to initialize its record
    source to the record source most recently programmed by MMPM/2.

If mixer application controls record source, then
1) Record source is a global concept
2) Record source may actually be multiple sources (if input mixer)
3) Record source returned represents the record source most recently
    sent via function 4F.

Note, the value returned may reflect the value sent from a different
mixer application (multiple mixer clients).

6F - RecordGainQuery

Query the global record gain level.

See function 4F (RecordGainSet) for a detailed description of this APIs behavior.

Introduced: API Level 1.  Enhanced in API Level 2.

In API Level 1
If the device driver has never received API call 4F, this IOCTL will return
the gain level most recently sent by MMPM/2 for per-stream volume.
This technique can be useful to initialize the value of the record gain slider to
the volume that is presently in effect per definition from MMPM/2.

Once function 4F has been sent, this API returns the record gain level most recently set via function 4F.

In API Level 2
The values returned are dependent on who controls the record gain.
If under MMPM/2 control (mixer has released), then the mute and volume
levels returned reflect the most recent value programmed from MMPM/2.

If mixer application is controlling the setting, then the values returned
for mute and volume are the most recent values sent via function 4F.
Note, the values returned may reflect the values sent from a different
mixer application (multiple mixer clients).

Parameters (PMIXSTRUCT).
 
Mute (flags) 0x0001=>Mute  0x0002=>Release
Left Left volume range 0..100
Right Not used, PDD will set to 0

Connection:
Reads the record gain setting just before the Analog/Digital converter inside the AC97 mixer.
This API effects what you "record", not what you "hear".

In API Level 1:
The Mute field is a boolean.  If true, then record gain is muted.

In API Level 2:
The Mute field is a bit mask (flags).
Bit 0x00000001 -  If true, then record gain is muted.
Bit 0x00000002 -  If true, then record gain is "released" to MMPM/2 control.

80 - ApiLevelQuery

In first release, this function returns a ULONG, 0x00000001.
As significant changes are made to the Category 90 mixer API, the return value
of this function will be incremented.

In current specification, audio device drivers should return 2.

Introduced: API Level 1

Parameters (PULONG).
 
ulAPILevel Driver returns level supported

API Level Functions Map - Where label omitted, API level is 1.  The API level indicates the minimum version of the specification that will support execution of the Ioctl.  Notice that many elements are added after "level 2", but are level 1 in definition as their implementation is compatiable with a mixer application that understands only level 1 communication.

40 - MonoInSet 60 - MonoInQuery
41 - PhoneSet 61 - PhoneQuery
42 - MicSet 62 - MicQuery
43 - LineSet 63 - LineQuery
44 - CDSet 64 - CDQuery
45 - VideoSet 65 - VideoQuery
46 - AuxSet 66 - AuxQuery
48 - SPDIFSet
68 - SPDIFQuery
4B - BassTrebleSet 6B - BassTrebleQuery
4C - ThreeDSet 6C - ThreeDQuery
4D - StreamVolSet (2) 6D - StreamVolQuery (2)
4E - RecordSrcSet (2) 6E - RecordSrcQuery (2)
4F - RecordGainSet (1,2) 4F - RecordGainQuery (1,2)
80 - ApiLevelQuery
81 - GetApiMap
82 - CallbackReg
83 - MsgBuf

Differences from original API definition result in increment of the API level.

The table above uses this convention.
With no notation, API level 1 is assumed.  API level 1 means that if the API is
listed in the API support map, it is implemented by the device driver.

New API level 1 IOCTLs can be added even after later API levels are defined.

The API level is used to describe differences in definition of an IOCTL.
These differences are noted in the table and are documented below and
in the documentation for each IOCTL.

(1,2)
The RecordGainSet API differs in behavior on API levels 1 and 2.
In API level 1, once the mixer application forces an override of record
gain, control of record gain is forever in the domain of the mixer application.
This is enhanced in API level 2 where the mixer application can return
record gain to be a per-stream concept as defined by MMPM/2.

(2)
A device driver implementing StreamVolSet API is expected to return
API level 2 or greater.  This API follows programming convention of
the level 2 implementation of RecordGainSet.

81 - GetApiMap

Device driver fills in an application memory buffer (256 bytes) with BYTE size booleans representing which of the possible 256 IOCTL functions that the device driver implements.

Introduced: API Level 1

This API can be used to identify mixer components that do not apply for the particular hardware.

For example, the Crystal Semiconductor PCI driver set implements the full AC97 defined mixer interface.
The Crystal Semiconductor ISA driver however does not implement "Video" or "Phone" volume as
these are concepts which are alien to the ISA hardware.

Notice that the buffer returned is 256 bytes while it is only possible for an application to send 192 IOCTL functions (IOCTL API requires that function be >= 0x40).    Wasting these 64 bytes of memory allows the application to index the array using the IOCTL number rather than IOCTL function number less 0x40.

82 - CallbackReg

Application provides handle to shared event semaphore.

Introduced: API Level 1

Parameters (HEV).

Application provides event semaphore handle to audio device driver.

This API is designed to let multiple mixer applications execute concurrently with sliders that "track".
The application is responsible for creating the event semahore.

When a mixer component state changes, the device driver posts the event semaphore which
wakes up an application thread that is blocked on the semaphore.  The application should
then issue query APIs to read the current state of the mixer.

This API is implemented in Crystal Semiconductor PCI driver set 3.04 and ISA 2.09.

Example code
  HEV hevCallback;
  ulRC = DosCreateEventSem (NULL, &hevCallback, DC_SEM_SHARED, FALSE);
  if (ulRC != 0)
  {
     printf ("mixerapiInit - CreateSem failed\n");
     hevCallback = NULL;
  }
  else
  {
     fCallbackThreadAlive = TRUE;
     if (_beginthread (CallbackThreadFunc, NULL, 32*1024, NULL) == -1)
     {
        printf ("mixerapiInit - callback thread create failed\n");
        CallbackFunc = NULL;
        fCallbackThreadAlive = FALSE;
        ulRC = 1;
     }
  }
  ulRC = mixerapiIOCTL90 (CALLBACKREG, &hevCallback, sizeof(hevCallback));

When the mixer application terminates or otherwise closes the semaphore, it should
contact the audio PDD to de-register.  De-register is done by registering a NULL semaphore.

Example code
  ulZero = 0;
  ulRC = mixerapiIOCTL90 (CALLBACKREG, &ulZero, sizeof(ulZero));
  ulRC = DosCloseEventSem (hsemCallback);
  hsemCallback = NULL;

83 - MsgBuf

Device driver fills in an application memory buffer with characters displayed during boot
and any strings displayed by device driver for debug or problem diagnosis in the field.

Introduced: API Level 1

Parameters (PMSGBUF).

typedef struct
{
   ULONG pBuffer;     // Application linear address to message buffer (in)
   ULONG ulSize;      // Size of buffer (in).  Count of chars (out).
   ULONG fClear;      // PDD should clear buffer after copy (in)
   ULONG fError;      // Message buffer includes error message (out)
   ULONG fNewInfo;    // Message buffer has new text since last read (out)
   ULONG ulCharsLost; // Messages lost - circular queue wrap around (out)
} MIXMSGBUF, *PMIXMSGBUF;

Application should pass NULL buffer on first call.
Device driver will set ulSize field to the maximum possible size of returned buffer
and will set the boolean return values to indicate what information is in the buffer.

Application should then malloc that much memory and call device driver to retrieve
message text.

If pBuffer points to invalid memory, the application will fail with access violation.

fError and ulCharsLost are clearned when buffer is cleared.
fNewInfo is cleared on each buffer read where pBuffer is not NULL.

When new message text is added to the buffer, the device driver posts
the callback semaphore.


Useful prototypes (header file)

// This structure is passed to the device driver using DosDevIOCTL.
typedef struct
{
   ULONG Mute;                  // UnMute==0, Mute==1
   ULONG VolumeL;               // 0..100 percent
   ULONG VolumeR;               // 0..100 percent
} MIXSTRUCT, *PMIXSTRUCT;

#define MONOINSET       0x40    // SET functions in the 0x40 range
#define PHONESET        0x41
#define MICSET          0x42
#define LINESET         0x43
#define CDSET           0x44
#define VIDEOSET        0x45
#define AUXSET          0x46
#define SPDIFSET        0x48
#define BASSTREBLESET   0x4B
#define THREEDSET       0x4C
#define STREAMVOLSET    0x4D
#define RECORDSRCSET    0x4E
#define RECORDGAINSET   0x4F

#define MONOINQUERY     0x60    // QUERY functions in the 0x60 range
#define PHONEQUERY      0x61
#define MICQUERY        0x62
#define LINEQUERY       0x63
#define CDQUERY         0x64
#define VIDEOQUERY      0x65
#define AUXQUERY        0x66
#define SPDIFQUERY      0x68
#define BASSTREBLEQUERY 0x6B

#define THREEDQUERY     0x6C
#define STREAMVOLQUERY  0x4D
#define RECORDSRCQUERY  0x4E
#define RECORDGAINQUERY 0x4F
#define APILEVELQUERY   0x80
#define GETAPIMAP       0x81    // Get 256 byte BOOL list of supported IOCTLs
#define CALLBACKREG     0x82    // Provide HSEM for mixer change callbacks
#define MSGBUF          0x83    // Get PDD error log message buffer


Example Query PDD Name:

The application will query the 8 character device driver name by calling MMPM/2 MCI APIs to get the PDD name for the "WaveAudio" MCI device.   Application should then issue DosOpen on the device name and finally DosDevIOCTL to perform mixer operations.

NOTE: The device driver names used by audio device drivers DO change and are not guaranteed to remain the same for any given release.  USE the available MMPM/2 APIs!

//
// OS/2 32-bit program to query the Physical Device Driver name
// for the default MMPM/2 WaveAudio device.  Joe Nord 10-Mar-1999
//

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <os2.h>

#define INCL_OS2MM
#include <os2me.h>

ULONG GetAudioPDDName (char *pszPDDName)
{
   ULONG                   ulRC;
   char                    szAmpMix[9] = "AMPMIX01";

   MCI_SYSINFO_PARMS       SysInfo;
   MCI_SYSINFO_LOGDEVICE   SysInfoParm;
   MCI_SYSINFO_QUERY_NAME  QueryNameParm;

   memset (&SysInfo, '\0', sizeof(SysInfo));
   memset (&SysInfoParm, '\0', sizeof(SysInfoParm));
   memset (&QueryNameParm, '\0', sizeof(QueryNameParm));

   SysInfo.ulItem       = MCI_SYSINFO_QUERY_NAMES;
   SysInfo.usDeviceType  = MCI_DEVTYPE_WAVEFORM_AUDIO;
   SysInfo.pSysInfoParm = &QueryNameParm;

   strcpy (QueryNameParm.szLogicalName, szAmpMix);

   ulRC = mciSendCommand (0,
                          MCI_SYSINFO,
                          MCI_SYSINFO_ITEM | MCI_WAIT,
                          (PVOID) &SysInfo,
                          0);
   if (ulRC != 0)
   {
      printf ("mciSendCommand ulRC=%u\n", ulRC);
      return (ulRC);
   }

   // Get PDD associated with our AmpMixer
   // Device name is in pSysInfoParm->szPDDName

   SysInfo.ulItem       = MCI_SYSINFO_QUERY_DRIVER;
   SysInfo.usDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
   SysInfo.pSysInfoParm = &SysInfoParm;

   strcpy (SysInfoParm.szInstallName, QueryNameParm.szInstallName);

   ulRC = mciSendCommand (0,
                          MCI_SYSINFO,
                          MCI_SYSINFO_ITEM | MCI_WAIT,
                          (PVOID) &SysInfo,
                          0);
   if (ulRC != 0)
   {
      printf ("mciSendCommand ulRC=%u\n", ulRC);
      return (ulRC);
   }

   strcpy (pszPDDName, SysInfoParm.szPDDName);

   return (ulRC);
}
 

int main (void)
{
   ULONG ulRC;
   char  szPddName [256];

   ulRC = GetAudioPDDName (&szPddName);
   printf ("GetAudioPDDName ulRC=%u\n", ulRC);
   printf ("   PddName=%s\n", szPddName);

   return (0);
}
 


Example DosOpen:

Driver name in call to the open function should include "\\DEV\\ "
      Example: hPdd = DevOpen ("\\DEV\\BSAUD1$"); or
      Example: hPdd = DevOpen ("\\DEV\\CWCAUD1$");

HFILE DevOpen (char *ddName)
{
   ULONG ulRC;
   ULONG OpenFlags;
   ULONG OpenMode;
   ULONG ulFileSize      = 0;
   ULONG ulFileAttribute = 0;
   ULONG ulActionTaken   = 0;
   HFILE hPdd            = NULL;

   OpenFlags = OPEN_ACTION_OPEN_IF_EXISTS;   // Do not create file

   OpenMode  = OPEN_ACCESS_READWRITE +       // Read/Write file
               OPEN_SHARE_DENYNONE +         // Non-exclusive access
               OPEN_FLAGS_FAIL_ON_ERROR;     // No system popups on errors

   ulRC = DosOpen (ddName,          // in
                   &hPdd,           //    out (handle)
                   &ulActionTaken,  //    out
                   ulFileSize,      // in
                   ulFileAttribute, // in
                   OpenFlags,       // in
                   OpenMode,        // in
                   NULL);           // in

   printf ("DosOpen RC = %x\n", ulRC);

   if (ulRC != 0)
      hPdd = NULL;

   return (hPdd);
}


Example DosDevIOCTL:

ULONG SendIOCTL (HFILE hPdd, ULONG ulFunc, PMIXSTRUCT pMix)
{
   ULONG     ulRC;
   ULONG     ulSizeOfStruct =  = sizeof (MixStruct);

   ulRC = DosDevIOCtl
      (hPdd,               // Device Handle
       0x90,               // Category (user defined >= 0x80)
       ulFunc,             // Function Use defines in .H file
       NULL,               // in      Address of parm data (not used)
       0,                  // in      Max size of parm data structure
       NULL,               // in out  Actual size of parm data structure
       pMix,               // in      Address of command data
       ulSizeOfStruct,     // in      Maximum size of command data
       &ulSizeOfStruct);   // in out  Size of command data

   printf ("DosDevIOCtl ulRC = %d\n", ulRC);

   return (ulRC);
}


Device Specific Information:

The Ioctl90 API is based on AC97 mixer architecture (common hardware for PCI bus audio).  It does not necessarily exactly map to other mixer architectures.  Where known, differences are documented below.

AC97 Definition   CS4236B/7B/8B   CS4235/9
PCI Bus designs   ISA Mode 3      ISA Mode 3
---------------   -------------   --------
MonoIn            MonoIn          MonoIn
Phone             none            none
Microphone        Mic             Mic
Line-In           Aux1            Aux1    Aux1 = Line-In connector on card
CD-ROM            Aux2            Aux2    Aux2 = CD-ROM Analog cable
Video             none            none
Aux               Line            DAC2    CS4236B=FM Volume, CS4235=Digital vol

Record sources:
On the Crystal Semiconductor ISA Mode 3 device driver, (CS4236B/7B/8B, CS4235, CS4239):
MONO-IN is not a possible record source.