Partial implementation of WDMAUD.DRV - device capability querying fails
[reactos.git] / reactos / lib / wdmaud / wdmaud.h
1 /*
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Multimedia
5 * FILE: lib/wdmaud/wdmaud.h
6 * PURPOSE: WDM Audio Support - Common header
7 * PROGRAMMER: Andrew Greenwood
8 * UPDATE HISTORY:
9 * Nov 12, 2005: Declarations for debugging + interface
10 */
11
12 #ifndef __WDMAUD_PRIVATE_H__
13 #define __WDMAUD_PRIVATE_H__
14
15 /* Debugging */
16
17
18 /*
19 Some of this stuff belongs in ksmedia.h or other such global includes.
20 */
21
22 #include <stdio.h>
23
24 #include <debug.h>
25 #include <ddk/ntddk.h>
26
27 #include <windows.h>
28 #include <mmsystem.h>
29 #include <mmddk.h>
30
31 /* HACK! */
32 #define DbgPrint printf
33
34 /* TODO: Put elsewhere */
35 #if 0
36 typedef struct tagWAVEOUTCAPS2A {
37 WORD wMid; /* manufacturer ID */
38 WORD wPid; /* product ID */
39 MMVERSION vDriverVersion; /* version of the driver */
40 CHAR szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
41 DWORD dwFormats; /* formats supported */
42 WORD wChannels; /* number of sources supported */
43 WORD wReserved1; /* packing */
44 DWORD dwSupport; /* functionality supported by driver */
45 GUID ManufacturerGuid; /* for extensible MID mapping */
46 GUID ProductGuid; /* for extensible PID mapping */
47 GUID NameGuid; /* for name lookup in registry */
48 } WAVEOUTCAPS2A, *PWAVEOUTCAPS2A, *NPWAVEOUTCAPS2A, *LPWAVEOUTCAPS2A;
49 typedef struct tagWAVEOUTCAPS2W {
50 WORD wMid; /* manufacturer ID */
51 WORD wPid; /* product ID */
52 MMVERSION vDriverVersion; /* version of the driver */
53 WCHAR szPname[MAXPNAMELEN]; /* product name (NULL terminated string) */
54 DWORD dwFormats; /* formats supported */
55 WORD wChannels; /* number of sources supported */
56 WORD wReserved1; /* packing */
57 DWORD dwSupport; /* functionality supported by driver */
58 GUID ManufacturerGuid; /* for extensible MID mapping */
59 GUID ProductGuid; /* for extensible PID mapping */
60 GUID NameGuid; /* for name lookup in registry */
61 } WAVEOUTCAPS2W, *PWAVEOUTCAPS2W, *NPWAVEOUTCAPS2W, *LPWAVEOUTCAPS2W;
62 #ifdef UNICODE
63 typedef WAVEOUTCAPS2W WAVEOUTCAPS2;
64 typedef PWAVEOUTCAPS2W PWAVEOUTCAPS2;
65 typedef NPWAVEOUTCAPS2W NPWAVEOUTCAPS2;
66 typedef LPWAVEOUTCAPS2W LPWAVEOUTCAPS2;
67 #else
68 typedef WAVEOUTCAPS2A WAVEOUTCAPS2;
69 typedef PWAVEOUTCAPS2A PWAVEOUTCAPS2;
70 typedef NPWAVEOUTCAPS2A NPWAVEOUTCAPS2;
71 typedef LPWAVEOUTCAPS2A LPWAVEOUTCAPS2;
72 #endif // UNICODE
73 #endif
74
75
76
77 /*
78 Handy macros
79 */
80
81 #define REPORT_MM_RESULT(message, success) \
82 DPRINT("%s %s\n", message, success == MMSYSERR_NOERROR ? "succeeded" : "failed")
83
84
85 /*
86 Private IOCTLs shared between wdmaud.sys and wdmaud.drv
87
88 TO ADD/MODIFY:
89 IOCTL_WDMAUD_OPEN_PIN
90 IOCTL_WDMAUD_WAVE_OUT_WRITE_PIN
91 IOCTL_WDMAUD_WAVE_IN_READ_PIN
92 IOCTL_WDMAUD_MIXER_CLOSE
93 IOCTL_WDMAUD_MIXER_OPEN
94 IOCTL_WDMAUD_MIDI_IN_READ_PIN
95 IOCTL_WDMAUD_MIXER_GETLINEINFO
96 IOCTL_WDMAUD_MIXER_GETHARDWAREEVENTDATA
97 IOCTL_WDMAUD_MIXER_SETCONTROLDETAILS
98 IOCTL_WDMAUD_MIXER_GETCONTROLDETAILS
99 IOCTL_WDMAUD_MIXER_GETLINECONTROLS
100 */
101
102 /* 0x1d8000 */
103 #define IOCTL_WDMAUD_HELLO \
104 CTL_CODE(FILE_DEVICE_SOUND, 0x0000, METHOD_BUFFERED, FILE_WRITE_ACCESS)
105
106 #define IOCTL_WDMAUD_ADD_DEVICE 0x1d8004
107 #define IOCTL_WDMAUD_REMOVE_DEVICE 0x1d8008
108 #define IOCTL_WDMAUD_GET_CAPABILITIES 0x1d800c
109 #define IOCTL_WDMAUD_GET_DEVICE_COUNT 0x1d8010
110 #define IOCTL_WDMAUD_OPEN_DEVICE 0x1d8014
111 #define IOCTL_WDMAUD_CLOSE_DEVICE 0x1d8018
112 #define IOCTL_WDMAUD_AUX_GET_VOLUME 0x1d801c
113 #define IOCTL_WDMAUD_AUX_SET_VOLUME 0x1d8020
114
115 /* 0x1d8024 */
116 #define IOCTL_WDMAUD_GOODBYE \
117 CTL_CODE(FILE_DEVICE_SOUND, 0x0009, METHOD_BUFFERED, FILE_WRITE_ACCESS)
118
119 #define IOCTL_WDMAUD_SET_PREFERRED 0x1d8028
120
121 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN1 0x1d8100
122 #define IOCTL_WDMAUD_WAVE_OUT_START 0x1d8104 /* Reset wave in? */
123 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN3 0x1d8108 /* Start wave in? */
124 #define IOCTL_WDMAUD_BREAK_LOOP 0x1d810c
125
126 #define IOCTL_WDMAUD_GET_WAVE_OUT_POS 0x1d8110 /* Does something funky */
127 #define IOCTL_WDMAUD_SET_VOLUME 0x1d8114 /* Hasn't this already been covered? */
128 #define IOCTL_WDMAUD_UNKNOWN1 0x1d8018 /* Not used by wdmaud.drv */
129 #define IOCTL_WDMAUD_SUBMIT_WAVE_HDR 0x1d811c
130
131 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN4 0x1d8140
132 #define IOCTL_WDMAUD_WAVE_IN_START 0x1d8144 /* Reset wave out? */
133 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN6 0x1d8148 /* Start wave out? */
134
135 #define IOCTL_WDMAUD_MIDI_OUT_SHORT_MESSAGE \
136 0x1d8204 /* Wrong description? */
137
138 #define IOCTL_WDMAUD_UNKNOWN2 0x1d8208
139
140 #define IOCTL_WDMAUD_MIDI_OUT_LONG_MESSAGE \
141 0x1d820c
142
143 #define IOCTL_WDMAUD_SUBMIT_MIDI_HDR 0x1d8210
144
145 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN7 0x1d8240
146 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN8 0x1d8244
147 #define IOCTL_WDMAUD_SET_STATE_UNKNOWN9 0x1d8248
148
149 #define IOCTL_WDMAUD_READ_MIDI_DATA 0x1d824c
150 #define IOCTL_WDMAUD_MIDI_MESSAGE 0x1d8300 /* Wrong description? */
151
152 #define IOCTL_WDMAUD_MIXER_UNKNOWN1 0x1d8310
153 #define IOCTL_WDMAUD_MIXER_UNKNOWN2 0x1d8314
154 #define IOCTL_WDMAUD_MIXER_UNKNOWN3 0x1d8318
155
156
157 /*
158 Device Types
159 */
160
161 enum
162 {
163 WDMAUD_WAVE_IN = 0,
164 WDMAUD_WAVE_OUT,
165
166 WDMAUD_MIDI_IN,
167 WDMAUD_MIDI_OUT,
168
169 WDMAUD_MIXER,
170
171 WDMAUD_AUX,
172
173 /* For range checking */
174 WDMAUD_MIN_DEVICE_TYPE = WDMAUD_WAVE_IN,
175 WDMAUD_MAX_DEVICE_TYPE = WDMAUD_AUX
176 };
177
178 /*
179 Some macros for device type matching and checking
180 */
181
182 #define IsWaveInDeviceType(device_type) (device_type == WDMAUD_WAVE_IN)
183 #define IsWaveOutDeviceType(device_type) (device_type == WDMAUD_WAVE_OUT)
184 #define IsMidiInDeviceType(device_type) (device_type == WDMAUD_MIDI_IN)
185 #define IsMidiOutDeviceType(device_type) (device_type == WDMAUD_MIDI_OUT)
186 #define IsMixerDeviceType(device_type) (device_type == WDMAUD_MIXER)
187 #define IsAuxDeviceType(device_type) (device_type == WDMAUD_AUX)
188
189 #define IsWaveDeviceType(device_type) \
190 (IsWaveInDeviceType(device_type) || IsWaveOutDeviceType(device_type))
191 #define IsMidiDeviceType(device_type) \
192 (IsMidiInDeviceType(device_type) || IsMidiOutDeviceType(device_type))
193
194 #define IsValidDeviceType(device_type) \
195 (device_type >= WDMAUD_MIN_DEVICE_TYPE && \
196 device_type <= WDMAUD_MAX_DEVICE_TYPE)
197
198 /*
199 The various "caps" (capabilities) structures begin with the same members,
200 so a generic structure is defined here which can be accessed independently
201 of a device type.
202 */
203
204 typedef struct
205 {
206 WORD wMid;
207 WORD wPid;
208 MMVERSION vDriverVersion;
209 WCHAR szPname[MAXPNAMELEN];
210 } COMMONCAPSW, *LPCOMMONCAPSW;
211
212 /* Unicode, anyone? */
213 typedef COMMONCAPSW COMMONCAPS;
214 typedef LPCOMMONCAPSW LPCOMMONCAPS;
215
216 /* More abstraction */
217 typedef LPVOID PWDMAUD_HEADER;
218
219 /*
220 There are also various "opendesc" structures, but these don't have any
221 common members. Regardless, this typedef simply serves as a placeholder
222 to indicate that to access the members, it should be cast accordingly.
223 */
224 typedef struct OPENDESC *LPOPENDESC;
225
226 typedef struct
227 {
228 DWORD sample_size;
229 HANDLE thread;
230 DWORD thread_id;
231 union
232 {
233 LPWAVEOPENDESC open_descriptor;
234 LPWAVEHDR wave_header;
235 };
236 DWORD unknown_10; /* pointer to something */
237 DWORD unknown_14;
238 LPCRITICAL_SECTION queue_critical_section;
239 HANDLE queue_event;
240 HANDLE exit_thread_event;
241 DWORD unknown_24;
242 DWORD is_paused;
243 DWORD is_running;
244 DWORD unknown_30;
245 DWORD unknown_34;
246 DWORD unknown_38;
247 char signature[4];
248 } WDMAUD_DEVICE_STATE, *PWDMAUD_DEVICE_STATE;
249
250 typedef struct
251 {
252 DWORD unknown_00;
253 DWORD id;
254 DWORD type;
255 HWAVE wave_handle;
256 DWORD client_instance;
257 DWORD client_callback;
258 DWORD unknown_18;
259 DWORD flags;
260 DWORD ioctl_param2;
261 DWORD ioctl_param1;
262 DWORD with_critical_section;
263 DWORD string_2c;
264 DWORD unknown_30;
265 DWORD playing_notes;
266 DWORD unknown_38;
267 DWORD unknown_3c;
268 DWORD unknown_40;
269 DWORD unknown_44;
270 DWORD unknown_48;
271 DWORD unknown_4C;
272 DWORD unknown_50;
273 DWORD beef;
274 PWDMAUD_DEVICE_STATE state;
275 char signature[4];
276 WCHAR path[1];
277 } WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO;
278
279 typedef struct
280 {
281 PWDMAUD_DEVICE_INFO offspring; /* not sure about this */
282 LPOVERLAPPED overlapped;
283 char signature[4];
284 } WDMAUD_WAVE_PREPARATION_DATA, *PWDMAUD_WAVE_PREPARATION_DATA;
285
286 /* Ugh... */
287
288 typedef struct
289 {
290 DWORD cbSize; /* Maybe? */
291
292 } WDMAUD_CAPS, *PWDMAUD_CAPS;
293
294 /*
295 Not quite sure what these are/do yet
296 */
297
298 #define MAGIC_42 0x42424242 /* Queue critical section */
299 #define MAGIC_43 0x43434343 /* Queue critical section */
300 #define MAGIC_48 0x48484848 /* Exit-thread event */
301
302 #define IsQueueMagic(test_value) \
303 ( ( (DWORD)test_value == MAGIC_42 ) || ( (DWORD)test_value == MAGIC_43) )
304
305
306 /*
307 This should eventually be removed, but is used so we can be nosey and see
308 what the kernel-mode wdmaud.sys is doing with our structures!
309 */
310
311 #ifdef DUMP_WDMAUD_STRUCTURES
312
313 #define DUMP_MEMBER(struct, member) \
314 DPRINT("%s : %d [0x%x]\n", #member, (int) struct->member, (int) struct->member);
315
316 #define DUMP_WDMAUD_DEVICE_INFO(info) \
317 { \
318 DPRINT("-- %s --\n", #info); \
319 DUMP_MEMBER(info, unknown_00); \
320 DUMP_MEMBER(info, id); \
321 DUMP_MEMBER(info, type); \
322 DUMP_MEMBER(info, wave_handle); \
323 DUMP_MEMBER(info, client_instance); \
324 DUMP_MEMBER(info, client_callback); \
325 DUMP_MEMBER(info, unknown_18); \
326 DUMP_MEMBER(info, flags); \
327 DUMP_MEMBER(info, ioctl_param2); \
328 DUMP_MEMBER(info, ioctl_param1); \
329 DUMP_MEMBER(info, with_critical_section); \
330 DUMP_MEMBER(info, string_2c); \
331 DUMP_MEMBER(info, unknown_30); \
332 DUMP_MEMBER(info, playing_notes); \
333 DUMP_MEMBER(info, unknown_38); \
334 DUMP_MEMBER(info, unknown_3c); \
335 DUMP_MEMBER(info, unknown_40); \
336 DUMP_MEMBER(info, unknown_44); \
337 DUMP_MEMBER(info, unknown_48); \
338 DUMP_MEMBER(info, unknown_4C); \
339 DUMP_MEMBER(info, unknown_50); \
340 DUMP_MEMBER(info, beef); \
341 DUMP_MEMBER(info, state); \
342 DUMP_MEMBER(info, signature); \
343 }
344
345 #else
346
347 #define DUMP_MEMBER(struct, member)
348 #define DUMP_WDMAUD_DEVICE_INFO(info)
349
350 #endif
351
352
353 /* Helper (helper.c) funcs */
354
355 MMRESULT TranslateWinError(DWORD error);
356 #define GetLastMmError() TranslateWinError(GetLastError());
357
358
359 /* user.c */
360 void NotifyClient(
361 PWDMAUD_DEVICE_INFO device,
362 DWORD message,
363 DWORD p1,
364 DWORD p2);
365
366 /* #define NotifyClient(device, message, p1, p2) ? */
367
368
369 /* kernel.c */
370
371 BOOL EnableKernelInterface();
372 BOOL DisableKernelInterface();
373 HANDLE GetKernelInterface();
374
375 MMRESULT CallKernelDevice(
376 PWDMAUD_DEVICE_INFO device,
377 DWORD ioctl_code,
378 DWORD param1,
379 DWORD param2);
380
381 /* devices.c */
382 BOOL IsValidDevicePath(WCHAR* path);
383 MMRESULT ValidateDeviceInfo(PWDMAUD_DEVICE_INFO info);
384 MMRESULT ValidateDeviceState(PWDMAUD_DEVICE_STATE state);
385 MMRESULT ValidateDeviceStateEvents(PWDMAUD_DEVICE_STATE state);
386 MMRESULT ValidateDeviceInfoAndState(PWDMAUD_DEVICE_INFO device_info);
387
388 PWDMAUD_DEVICE_INFO CreateDeviceData(CHAR device_type, WCHAR* device_path);
389 PWDMAUD_DEVICE_INFO CloneDeviceData(PWDMAUD_DEVICE_INFO original);
390 void DeleteDeviceData(PWDMAUD_DEVICE_INFO device_data);
391 /* mixer ... */
392
393 MMRESULT ModifyDevicePresence(
394 CHAR device_type,
395 WCHAR* device_path,
396 BOOL adding);
397
398 #define AddDevice(device_type, device_path) \
399 ModifyDevicePresence(device_type, device_path, TRUE)
400
401 #define AddWaveInDevice(device_path) \
402 AddDevice(WDMAUD_WAVE_IN, device_path)
403 #define AddWaveOutDevice(device_path) \
404 AddDevice(WDMAUD_WAVE_OUT, device_path)
405 #define AddMidiInDevice(device_path) \
406 AddDevice(WDMAUD_MIDI_IN, device_path)
407 #define AddMidiOutDevice(device_path) \
408 AddDevice(WDMAUD_MIDI_OUT, device_path)
409 #define AddMixerDevice(device_path) \
410 AddDevice(WDMAUD_MIXER, device_path)
411 #define AddAuxDevice(device_path) \
412 AddDevice(WDMAUD_AUX, device_path)
413
414 #define RemoveDevice(device_type, device_path) \
415 ModifyDevicePresence(device_type, device_path, FALSE)
416
417 #define RemoveWaveInDevice(device_path) \
418 RemoveDevice(WDMAUD_WAVE_IN, device_path)
419 #define RemoveWaveOutDevice(device_path) \
420 RemoveDevice(WDMAUD_WAVE_OUT, device_path)
421 #define RemoveMidiInDevice(device_path) \
422 RemoveDevice(WDMAUD_MIDI_IN, device_path)
423 #define RemoveMidiOutDevice(device_path) \
424 RemoveDevice(WDMAUD_MIDI_OUT, device_path)
425 #define RemoveMixerDevice(device_path) \
426 RemoveDevice(WDMAUD_MIXER, device_path)
427 #define RemoveAuxDevice(device_path) \
428 RemoveDevice(WDMAUD_AUX, device_path)
429
430
431 DWORD GetDeviceCount(CHAR device_type, WCHAR* device_path);
432 #define GetWaveInCount(device_path) GetDeviceCount(WDMAUD_WAVE_IN, device_path)
433 #define GetWaveOutCount(device_path) GetDeviceCount(WDMAUD_WAVE_OUT, device_path)
434 #define GetMidiInCount(device_path) GetDeviceCount(WDMAUD_MIDI_IN, device_path)
435 #define GetMidiOutCount(device_path) GetDeviceCount(WDMAUD_MIDI_OUT, device_path)
436 #define GetMixerCount(device_path) GetDeviceCount(WDMAUD_MIXER, device_path)
437 #define GetAuxCount(device_path) GetDeviceCount(WDMAUD_AUX, device_path)
438
439 MMRESULT GetDeviceCapabilities(
440 CHAR device_type,
441 DWORD device_id,
442 WCHAR* device_path,
443 LPCOMMONCAPS caps);
444
445 #define GetWaveInCapabilities(id, device_path, caps) \
446 GetDeviceCapabilities(id, WDMAUD_WAVE_IN, device_path, caps);
447 #define GetWaveOutCapabilities(id, device_path, caps) \
448 GetDeviceCapabilities(id, WDMAUD_WAVE_OUT, device_path, caps);
449 #define GetMidiInCapabilities(id, device_path, caps) \
450 GetDeviceCapabilities(id, WDMAUD_MIDI_IN, device_path, caps);
451 #define GetMidiOutCapabilities(id, device_path, caps) \
452 GetDeviceCapabilities(id, WDMAUD_MIDI_OUT, device_path, caps);
453 #define GetMixerCapabilities(id, device_path, caps) \
454 GetDeviceCapabilities(id, WDMAUD_MIXER, device_path, caps);
455 #define GetAuxCapabilities(id, device_path, caps) \
456 GetDeviceCapabilities(id, WDMAUD_AUX, device_path, caps);
457
458 MMRESULT OpenWaveDevice(
459 CHAR device_type,
460 DWORD device_id,
461 LPWAVEOPENDESC open_details,
462 DWORD flags,
463 DWORD user_data);
464
465 #define OpenWaveOut(id, open_details, flags, user_data) \
466 OpenWaveDevice(WDMAUD_WAVE_OUT, id, open_details, flags, user_data);
467
468 MMRESULT CloseDevice(
469 PWDMAUD_DEVICE_INFO device
470 );
471
472
473 /* wavehdr.h */
474
475 #define SET_WAVEHDR_FLAG(header, flag) \
476 header->dwFlags |= flag
477
478 #define CLEAR_WAVEHDR_FLAG(header, flag) \
479 header->dwFlags &= ~flag
480
481 MMRESULT ValidateWavePreparationData(PWDMAUD_WAVE_PREPARATION_DATA prep_data);
482
483 MMRESULT ValidateWaveHeader(PWAVEHDR header);
484
485 MMRESULT PrepareWaveHeader(
486 PWDMAUD_DEVICE_INFO device,
487 PWAVEHDR header
488 );
489
490 MMRESULT UnprepareWaveHeader(PWAVEHDR header);
491
492 #define IsHeaderPrepared(header) \
493 ( header->reserved != 0 )
494
495 MMRESULT CompleteWaveHeader(PWAVEHDR header);
496
497 MMRESULT WriteWaveData(PWDMAUD_DEVICE_INFO device, PWAVEHDR header);
498
499
500 /* threads.c */
501
502 BOOL CreateCompletionThread(PWDMAUD_DEVICE_INFO device);
503
504
505 /* MORE... */
506
507 #endif