ReactOS 0.4.16-dev-329-g9223134
mpu401.c
Go to the documentation of this file.
1/*
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/dd/mpu401/mpu401.c
6 * PURPOSE: MPU-401 MIDI device driver
7 * PROGRAMMER: Andrew Greenwood
8 * UPDATE HISTORY:
9 * Sept 26, 2003: Copied from beep.c as template
10 * Sept 27, 2003: Implemented MPU-401 init & playback
11 */
12
13/* INCLUDES ****************************************************************/
14
15#include <ntddk.h>
16//#include <ntddbeep.h>
17
18//#define NDEBUG
19#include <debug.h>
20
21#include "mpu401.h"
22
23
24/* INTERNAL VARIABLES ******************************************************/
25
27
28
29/* FUNCTIONS ***************************************************************/
30
34{
35// PDEVICE_INSTANCE Instance = Context;
36 PDEVICE_OBJECT DeviceObject; // = Context;
37 PDEVICE_EXTENSION Parameters; // = DeviceObject->DeviceExtension;
38 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MidiOut0");
39 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\MidiOut0");
40// CONFIG Config;
42 NTSTATUS s;
43
44 // This is TEMPORARY, to ensure that we don't process more than 1 device.
45 // I'll remove this limitation in the future.
46 if (DeviceCount > 0)
47 {
48 DPRINT("Sorry - only 1 device supported by MPU401 driver at present :(\n");
50 }
51
52 DPRINT("Creating IO device\n");
53
54 s = IoCreateDevice(Context, // driverobject
55 sizeof(DEVICE_EXTENSION),
57 FILE_DEVICE_SOUND, // Correct?
58 0,
59 FALSE,
61
62 if (!NT_SUCCESS(s))
63 return s;
64
65 DPRINT("Device Extension at 0x%x\n", DeviceObject->DeviceExtension);
66 Parameters = DeviceObject->DeviceExtension;
67
68 DPRINT("Creating DOS link\n");
69
70 /* Create the dos device link */
71 IoCreateSymbolicLink(&SymlinkName,
72 &DeviceName);
73
74 DPRINT("Initializing device\n");
75
76// DPRINT("Allocating memory for parameters structure\n");
77 // Bodged:
78// Parameters = (PDEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(DEVICE_EXTENSION));
79// DeviceObject->DeviceExtension = Parameters;
80// Parameters = Instance->DriverObject->DriverExtension;
81
82 DPRINT("DeviceObject at 0x%x, DeviceExtension at 0x%x\n", DeviceObject, Parameters);
83
84 if (! Parameters)
85 {
86 DPRINT("NULL POINTER!\n");
88 }
89
90// Instance->DriverObject->DriverExtension = Parameters;
91
92 DPRINT("Setting reg path\n");
93 Parameters->RegistryPath = RegistryPath;
94// Parameters->DriverObject = Instance->DriverObject;
95
96 DPRINT("Zeroing table memory and setting query routine\n");
97 RtlZeroMemory(Table, sizeof(Table));
98 Table[0].QueryRoutine = LoadSettings;
99
100 DPRINT("Setting port and IRQ defaults\n");
101 Parameters->Port = DEFAULT_PORT;
102 Parameters->IRQ = DEFAULT_IRQ;
103
104// Only to be enabled once we can get support for multiple cards working :)
105/*
106 DPRINT("Loading settings from: %S\n", RegistryPath);
107
108 s = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, RegistryPath, Table,
109 &Parameters, NULL);
110*/
111
112 if (! NT_SUCCESS(s))
113 return s;
114
115 DPRINT("Port 0x%x IRQ %d\n", Parameters->Port, Parameters->IRQ);
116
117// Instance->P
118
119 // Enter UART mode (should be done in init phase
120 if (! InitUARTMode(Parameters->Port))
121 {
122 DPRINT("UART mode initialization FAILED!\n");
123 // Set state indication somehow
124 // Failure - what error code do we give?!
125 // return STATUS_????
126 }
127
128 DeviceCount ++;
129
130 return STATUS_SUCCESS;
131}
132
133
134static NTSTATUS NTAPI
136 PIRP Irp)
137/*
138 * FUNCTION: Handles user mode requests
139 * ARGUMENTS:
140 * DeviceObject = Device for request
141 * Irp = I/O request packet describing request
142 * RETURNS: Success or failure
143 */
144{
145 DPRINT("MPU401Create() called!\n");
146
147 // Initialize the MPU-401?
148 // ... do stuff ...
149
150
151 // Play a note to say we're alive:
158
159 Irp->IoStatus.Status = STATUS_SUCCESS;
160 Irp->IoStatus.Information = 0;
163
164 return(STATUS_SUCCESS);
165}
166
167
168static NTSTATUS NTAPI
170 PIRP Irp)
171/*
172 * FUNCTION: Handles user mode requests
173 * ARGUMENTS:
174 * DeviceObject = Device for request
175 * Irp = I/O request packet describing request
176 * RETURNS: Success or failure
177 */
178{
179 PDEVICE_EXTENSION DeviceExtension;
181
182 DPRINT("MPU401Close() called!\n");
183
184 DeviceExtension = DeviceObject->DeviceExtension;
185
187
188 Irp->IoStatus.Status = Status;
189 Irp->IoStatus.Information = 0;
192
193 return(Status);
194}
195
196
197static NTSTATUS NTAPI
199 PIRP Irp)
200/*
201 * FUNCTION: Handles user mode requests
202 * ARGUMENTS:
203 * DeviceObject = Device for request
204 * Irp = I/O request packet describing request
205 * RETURNS: Success or failure
206 */
207{
208 ULONG Channel;
209 DPRINT("MPU401Cleanup() called!\n");
210
211 // Reset the device (should we do this?)
212 for (Channel = 0; Channel <= 15; Channel ++)
213 {
214 // All notes off
215// MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 123, 0);
216 // All controllers off
217// MPU401_WRITE_MESSAGE(MPU401_PORT, 0xb0 + Channel, 121, 0);
218 }
219
220
221 Irp->IoStatus.Status = STATUS_SUCCESS;
222 Irp->IoStatus.Information = 0;
225
226 return(STATUS_SUCCESS);
227}
228
229
230static NTSTATUS NTAPI
232 PIRP Irp)
233/*
234 * FUNCTION: Handles user mode requests
235 * ARGUMENTS:
236 * DeviceObject = Device for request
237 * Irp = I/O request packet describing request
238 * RETURNS: Success or failure
239 */
240{
242 PDEVICE_EXTENSION DeviceExtension;
244 PUCHAR Data;
245
246 DPRINT("MPU401DeviceControl() called!\n");
247
248 DeviceExtension = DeviceObject->DeviceExtension;
250
251 DPRINT("Control code %d [0x%x]\n", Stack->Parameters.DeviceIoControl.IoControlCode,
252 Stack->Parameters.DeviceIoControl.IoControlCode);
253
254 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
255 {
256 case IOCTL_MIDI_PLAY :
257 {
258 DPRINT("Received IOCTL_MIDI_PLAY\n");
259 Data = (PUCHAR) Irp->AssociatedIrp.SystemBuffer;
260
261 DPRINT("Sending %d bytes of MIDI data to 0x%x:\n", Stack->Parameters.DeviceIoControl.InputBufferLength, DeviceExtension->Port);
262
263 for (ByteCount = 0; ByteCount < Stack->Parameters.DeviceIoControl.InputBufferLength; ByteCount ++)
264 {
265 DPRINT("0x%x ", Data[ByteCount]);
266
267 MPU401_WRITE_BYTE(DeviceExtension->Port, Data[ByteCount]);
268// if (WaitToSend(MPU401_PORT))
269// MPU401_WRITE_DATA(MPU401_PORT, Data[ByteCount]);
270 }
271
272 Irp->IoStatus.Status = STATUS_SUCCESS;
274
275 return(STATUS_SUCCESS);
276 }
277 }
278
279 return(STATUS_SUCCESS);
280
281/*
282 DeviceExtension = DeviceObject->DeviceExtension;
283 Stack = IoGetCurrentIrpStackLocation(Irp);
284 BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
285
286 Irp->IoStatus.Information = 0;
287
288 if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
289 {
290 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
291 IoCompleteRequest(Irp,
292 IO_NO_INCREMENT);
293 return(STATUS_NOT_IMPLEMENTED);
294 }
295
296 if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
297 || (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
298 || (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
299 {
300 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
301 IoCompleteRequest(Irp,
302 IO_NO_INCREMENT);
303 return(STATUS_INVALID_PARAMETER);
304 }
305
306 DueTime.QuadPart = 0;
307*/
308 /* do the beep!! */
309/* DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
310 pbsp->Frequency,
311 pbsp->Duration);
312
313 if (BeepParam->Duration >= 0)
314 {
315 DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
316
317 KeSetTimer(&DeviceExtension->Timer,
318 DueTime,
319 &DeviceExtension->Dpc);
320
321 HalMakeBeep(BeepParam->Frequency);
322 DeviceExtension->BeepOn = TRUE;
323 KeWaitForSingleObject(&DeviceExtension->Event,
324 Executive,
325 KernelMode,
326 FALSE,
327 NULL);
328 }
329 else if (BeepParam->Duration == (DWORD)-1)
330 {
331 if (DeviceExtension->BeepOn != FALSE)
332 {
333 HalMakeBeep(0);
334 DeviceExtension->BeepOn = FALSE;
335 }
336 else
337 {
338 HalMakeBeep(BeepParam->Frequency);
339 DeviceExtension->BeepOn = TRUE;
340 }
341 }
342
343 DPRINT("Did the beep!\n");
344
345 Irp->IoStatus.Status = STATUS_SUCCESS;
346 IoCompleteRequest(Irp,
347 IO_NO_INCREMENT);
348 return(STATUS_SUCCESS);
349*/
350}
351
352
353static VOID NTAPI
355{
356 DPRINT("MPU401Unload() called!\n");
357}
358
359
363/*
364 * FUNCTION: Called by the system to initialize the driver
365 * ARGUMENTS:
366 * DriverObject = object describing this driver
367 * RegistryPath = path to our configuration entries
368 * RETURNS: Success or failure
369 */
370{
371// PDEVICE_EXTENSION DeviceExtension;
372// PDEVICE_OBJECT DeviceObject;
373// DEVICE_INSTANCE Instance;
374 // Doesn't support multiple instances (yet ...)
376
377 DPRINT("MPU401 Device Driver 0.0.1\n");
378
379 // Is this really necessary? Yes! (Talking to myself again...)
380// Instance.DriverObject = DriverObject;
381 // previous instance = NULL...
382
383// DeviceExtension->RegistryPath = RegistryPath;
384
385 DriverObject->Flags = 0;
386 DriverObject->MajorFunction[IRP_MJ_CREATE] = MPU401Create;
387 DriverObject->MajorFunction[IRP_MJ_CLOSE] = MPU401Close;
388 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MPU401Cleanup;
390 DriverObject->DriverUnload = MPU401Unload;
391
392 // Major hack to just get this damn thing working:
394
395// DPRINT("Enumerating devices at %wZ\n", RegistryPath);
396
397// Status = EnumDeviceKeys(RegistryPath, PARMS_SUBKEY, InitDevice, (PVOID)&DeviceObject); // &Instance;
398
399 // check error
400
401 /* set up device extension */
402// DeviceExtension = DeviceObject->DeviceExtension;
403// DeviceExtension->BeepOn = FALSE;
404
405 return(STATUS_SUCCESS);
406}
407
408/* EOF */
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
void LoadSettings(void)
Definition: settings.c:53
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
Status
Definition: gdiplustypes.h:25
ASMGENDATA Table[]
Definition: genincdata.c:61
GLdouble s
Definition: gl.h:2039
#define IOCTL_MIDI_PLAY
Definition: mmdef.h:74
static NTSTATUS NTAPI MPU401Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mpu401.c:135
static NTSTATUS NTAPI MPU401Cleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mpu401.c:198
static NTSTATUS NTAPI MPU401Close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mpu401.c:169
ULONG DeviceCount
Definition: mpu401.c:26
static VOID NTAPI MPU401Unload(PDRIVER_OBJECT DriverObject)
Definition: mpu401.c:354
static NTSTATUS InitDevice(IN PUNICODE_STRING RegistryPath, IN PVOID Context)
Definition: mpu401.c:31
static NTSTATUS NTAPI MPU401DeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: mpu401.c:231
#define MPU401_WRITE_DATA(bp, x)
Definition: mpu401.h:53
#define MPU401_PORT
Definition: mpu401.h:28
#define DEFAULT_PORT
Definition: mpu401.h:19
#define MPU401_WRITE_BYTE(bp, x)
Definition: mpu401.h:68
BOOLEAN WaitToSend(ULONG BasePort)
Definition: portio.c:16
BOOLEAN InitUARTMode(ULONG BasePort)
Definition: portio.c:64
#define DEFAULT_IRQ
Definition: mpu401.h:20
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
#define IoCompleteRequest
Definition: irp.c:1240
#define L(x)
Definition: ntvdm.h:50
#define FILE_DEVICE_SOUND
Definition: winioctl.h:74
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define IRP_MJ_CLEANUP