xref: /reactos/sdk/lib/drivers/sound/mment4/control.c (revision c948ea85)
1 /*
2  * PROJECT:     ReactOS Sound System "MME Buddy" NT4 Library
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        lib/drivers/sound/mment4/control.c
5  *
6  * PURPOSE:     Device control for NT4 audio devices
7  *
8  * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
9 */
10 
11 #include "precomp.h"
12 
13 #include <winioctl.h>
14 #include <ntddsnd.h>
15 
16 #include <mmebuddy_debug.h>
17 
18 /*
19     Convenience routine for getting the path of a device and opening it.
20 */
21 MMRESULT
22 OpenNt4KernelSoundDevice(
23     IN  PSOUND_DEVICE SoundDevice,
24     IN  BOOLEAN ReadOnly,
25     OUT PHANDLE Handle)
26 {
27     PWSTR Path;
28     MMRESULT Result;
29 
30     VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
31     VALIDATE_MMSYS_PARAMETER( Handle );
32 
33     Result = GetSoundDeviceIdentifier(SoundDevice, (PVOID*) &Path);
34     if ( ! MMSUCCESS(Result) )
35     {
36         SND_ERR(L"Unable to get sound device path\n");
37         return TranslateInternalMmResult(Result);
38     }
39 
40     SND_ASSERT( Path );
41 
42     return OpenKernelSoundDeviceByName(Path, ReadOnly, Handle);
43 }
44 
45 /*
46     Device open/close. These are basically wrappers for the MME-Buddy
47     open and close routines, which provide a Windows device handle.
48     These may seem simple but as you can return pretty much anything
49     as the handle, we could just as easily return a structure etc.
50 */
51 MMRESULT
52 OpenNt4SoundDevice(
53     IN  PSOUND_DEVICE SoundDevice,
54     OUT PVOID* Handle)
55 {
56     SND_TRACE(L"Opening NT4 style sound device\n");
57 
58     VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
59     VALIDATE_MMSYS_PARAMETER( Handle );
60 
61     return OpenNt4KernelSoundDevice(SoundDevice, FALSE, Handle);
62 }
63 
64 MMRESULT
65 CloseNt4SoundDevice(
66     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
67     IN  PVOID Handle)
68 {
69     SND_TRACE(L"Closing NT4 style sound device\n");
70 
71     VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
72     return CloseKernelSoundDevice((HANDLE) Handle);
73 }
74 
75 /*
76     Provides an implementation for the "get capabilities" request,
77     using the standard IOCTLs used by NT4 sound drivers.
78 */
79 MMRESULT
80 GetNt4SoundDeviceCapabilities(
81     IN  PSOUND_DEVICE SoundDevice,
82     OUT PVOID Capabilities,
83     IN  DWORD CapabilitiesSize)
84 {
85     MMRESULT Result;
86     MMDEVICE_TYPE DeviceType;
87     DWORD IoCtl;
88     HANDLE DeviceHandle;
89 
90     /* If these are bad there's an internal error with MME-Buddy! */
91     SND_ASSERT( SoundDevice );
92     SND_ASSERT( Capabilities );
93     SND_ASSERT( CapabilitiesSize > 0 );
94 
95     SND_TRACE(L"NT4 get-capabilities routine called\n");
96 
97     /* Get the device type */
98     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
99     SND_ASSERT( Result == MMSYSERR_NOERROR );
100 
101     if ( ! MMSUCCESS(Result) )
102         return TranslateInternalMmResult(Result);
103 
104     /* Choose the appropriate IOCTL */
105     if ( IS_WAVE_DEVICE_TYPE(DeviceType) )
106     {
107         IoCtl = IOCTL_WAVE_GET_CAPABILITIES;
108     }
109     else if ( IS_MIDI_DEVICE_TYPE(DeviceType) )
110     {
111         IoCtl = IOCTL_MIDI_GET_CAPABILITIES;
112     }
113     else
114     {
115         /* FIXME - need to support AUX and mixer devices */
116         SND_ASSERT( FALSE );
117         IoCtl = 0;
118     }
119 
120     /* Get the capabilities information from the driver */
121     Result = OpenNt4KernelSoundDevice(SoundDevice, TRUE, &DeviceHandle);
122 
123     if ( ! MMSUCCESS(Result) )
124     {
125         SND_ERR(L"Failed to open device\n");
126         return TranslateInternalMmResult(Result);
127     }
128 
129     Result = SyncOverlappedDeviceIoControl(DeviceHandle,
130                                            IoCtl,
131                                            Capabilities,
132                                            CapabilitiesSize,
133                                            NULL,
134                                            0,
135                                            NULL);
136 
137     CloseKernelSoundDevice(DeviceHandle);
138 
139     if ( ! MMSUCCESS(Result) )
140     {
141         SND_ERR(L"Retrieval of capabilities information failed\n");
142         Result = TranslateInternalMmResult(Result);
143     }
144 
145     return Result;
146 }
147 
148 /*
149     Querying/setting the format of a wave device. Querying format support
150     requires us to first open the device, whereas setting format is done
151     on an already opened device.
152 */
153 MMRESULT
154 QueryNt4WaveDeviceFormatSupport(
155     IN  PSOUND_DEVICE SoundDevice,
156     IN  LPWAVEFORMATEX Format,
157     IN  DWORD FormatSize)
158 {
159     MMRESULT Result;
160     HANDLE Handle;
161 
162     SND_TRACE(L"NT4 wave format support querying routine called\n");
163 
164     VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) );
165     VALIDATE_MMSYS_PARAMETER( Format );
166     VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
167 
168     /* Get the device path */
169     Result = OpenNt4KernelSoundDevice(SoundDevice,
170                                       FALSE,
171                                       &Handle);
172 
173     if ( ! MMSUCCESS(Result) )
174     {
175         SND_ERR(L"Unable to open kernel sound device\n");
176         return TranslateInternalMmResult(Result);
177     }
178 
179     Result = SyncOverlappedDeviceIoControl(Handle,
180                                            IOCTL_WAVE_QUERY_FORMAT,
181                                            (LPVOID) Format,
182                                            FormatSize,
183                                            NULL,
184                                            0,
185                                            NULL);
186 
187     if ( ! MMSUCCESS(Result) )
188     {
189         SND_ERR(L"Sync overlapped I/O failed - MMSYS_ERROR %d\n", Result);
190         Result = TranslateInternalMmResult(Result);
191     }
192 
193     CloseKernelSoundDevice(Handle);
194 
195     return MMSYSERR_NOERROR;
196 }
197 
198 MMRESULT
199 SetNt4WaveDeviceFormat(
200     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
201     IN  DWORD DeviceId,
202     IN  LPWAVEFORMATEX Format,
203     IN  DWORD FormatSize)
204 {
205     MMRESULT Result;
206     HANDLE Handle;
207 
208     VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
209     VALIDATE_MMSYS_PARAMETER( Format );
210     VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
211 
212     Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
213 
214     if ( ! MMSUCCESS(Result) )
215         return TranslateInternalMmResult(Result);
216 
217     SND_TRACE(L"Setting wave device format on handle %x\n", Handle);
218 
219     Result = SyncOverlappedDeviceIoControl(Handle,
220                                            IOCTL_WAVE_SET_FORMAT,
221                                            (LPVOID) Format,
222                                            FormatSize,
223                                            NULL,
224                                            0,
225                                            NULL);
226 
227     if ( ! MMSUCCESS(Result) )
228         return TranslateInternalMmResult(Result);
229 
230     return MMSYSERR_NOERROR;
231 }
232 
233 #if 0
234 MMRESULT
235 SubmitNt4WaveHeader(
236     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
237     IN  PWAVEHDR WaveHeader)
238 {
239     VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
240     VALIDATE_MMSYS_PARAMETER( WaveHeader );
241 
242     SND_TRACE(L"Submitting wave header %p (in sound thread)\n", WaveHeader);
243 
244     /* TODO: This should only submit the header to the device, nothing more! */
245 }
246 #endif
247