1 /* 2 * 3 * COPYRIGHT: See COPYING in the top level directory 4 * PROJECT: ReactOS Sound System 5 * FILE: drivers/multimedia/audio/sndblst/sndblst.c 6 * PURPOSE: Sound Blaster / Pro / 16 driver 7 * PROGRAMMER: Andrew Greenwood (silverblade@reactos.org) 8 * 9 * UPDATE HISTORY: Feb 25, 2009: New rewrite started 10 * 11 */ 12 13 /* DEFINES AND INCLUDES ******************************************************/ 14 15 #include <ntddk.h> 16 #include <windef.h> 17 #include <mmsystem.h> 18 #include <debug.h> 19 20 #define CompleteIrpAndReturn(irp, status) \ 21 irp->IoStatus.Status = status; \ 22 irp->IoStatus.Information = 0; \ 23 IoCompleteRequest(Irp, IO_NO_INCREMENT); \ 24 return status; 25 26 27 /* FORWARD DECLARATIONS *****************************************************/ 28 29 static VOID NTAPI 30 UnloadSoundBlaster(PDRIVER_OBJECT DriverObject); 31 32 33 /* DEVICE "DISCOVERY" *******************************************************/ 34 /* Nb: These need to go in the helper lib */ 35 36 typedef NTSTATUS (*SOUNDDEVICEENUMERATIONCALLBACK)( 37 IN PUNICODE_STRING DeviceRegistryPath); 38 39 NTSTATUS 40 EnumerateSoundDevices( 41 IN PUNICODE_STRING RegistryPath, 42 IN PWSTR RegistrySubKey, 43 IN SOUNDDEVICEENUMERATIONCALLBACK Callback) 44 { 45 NTSTATUS Status; 46 OBJECT_ATTRIBUTES RegAttributes; 47 HKEY MainKeyHandle, ChildKeyHandle; 48 UNICODE_STRING UnicodeSubkeyName, DeviceKeyName; 49 KEY_BASIC_INFORMATION KeyInfo, *FinalKeyInfo; 50 ULONG i = 0, NeededDataLength = 0, FinalDataLength = 0, NameLength = 0; 51 52 /* Turn the subkey name into a Unicode string */ 53 RtlInitUnicodeString(&UnicodeSubkeyName, RegistrySubKey); 54 55 /* Open the registry key for the service */ 56 InitializeObjectAttributes(&RegAttributes, 57 RegistryPath, 58 OBJ_CASE_INSENSITIVE, 59 NULL, 60 (PSECURITY_DESCRIPTOR) NULL); 61 62 Status = ZwOpenKey(&MainKeyHandle, KEY_READ, &RegAttributes); 63 64 if ( ! NT_SUCCESS(Status) ) 65 { 66 DPRINT("Failed to open registry key\n"); 67 return Status; 68 } 69 70 /* Open the subkey usually named "Parameters" */ 71 InitializeObjectAttributes(&RegAttributes, 72 &UnicodeSubkeyName, 73 OBJ_CASE_INSENSITIVE, 74 MainKeyHandle, 75 (PSECURITY_DESCRIPTOR) NULL); 76 77 Status = ZwOpenKey(&ChildKeyHandle, KEY_ENUMERATE_SUB_KEYS, &RegAttributes); 78 79 /* We're done with the main key now */ 80 ZwClose(MainKeyHandle); 81 82 if ( ! NT_SUCCESS(Status) ) 83 { 84 DPRINT("Failed to open registry subkeys for enumeration\n"); 85 return Status; 86 } 87 88 /* Enumerate through the device keys */ 89 while ( ( Status = ZwEnumerateKey(ChildKeyHandle, 90 i, 91 KeyBasicInformation, 92 &KeyInfo, 93 sizeof(KEY_BASIC_INFORMATION), 94 &NeededDataLength) ) != STATUS_NO_MORE_ENTRIES ) 95 { 96 PWSTR EnumeratedKeyName, StartOfEnumeratedKeyName; 97 98 DPRINT("Found subkey %d\n", i); 99 100 FinalDataLength = NeededDataLength + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]); 101 DPRINT("Allocating %d bytes\n", FinalDataLength); 102 103 FinalKeyInfo = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool, FinalDataLength); 104 105 if ( ! FinalKeyInfo ) 106 { 107 Status = STATUS_INSUFFICIENT_RESOURCES; 108 break; 109 } 110 111 /* This time we get the real info */ 112 Status = ZwEnumerateKey(ChildKeyHandle, 113 i, 114 KeyBasicInformation, 115 FinalKeyInfo, 116 FinalDataLength, 117 &NeededDataLength); 118 119 if ( ! NT_SUCCESS(Status) ) 120 { 121 DPRINT("FAILED to enumerate key!\n"); 122 } 123 else 124 { 125 NameLength = RegistryPath->Length + sizeof(WCHAR) + 126 UnicodeSubkeyName.Length + sizeof(WCHAR) + 127 FinalKeyInfo->NameLength + sizeof(UNICODE_NULL); 128 129 DPRINT("Allocating memory for name (%d bytes)\n", NameLength); 130 131 EnumeratedKeyName = (PWSTR) ExAllocatePool(PagedPool, NameLength); 132 133 if ( ! EnumeratedKeyName ) 134 { 135 ExFreePool((PVOID)FinalKeyInfo); 136 Status = STATUS_INSUFFICIENT_RESOURCES; 137 break; 138 } 139 140 StartOfEnumeratedKeyName = EnumeratedKeyName; 141 142 /* Start building the registry path using the service key */ 143 RtlCopyMemory(EnumeratedKeyName, 144 RegistryPath->Buffer, 145 RegistryPath->Length); 146 147 EnumeratedKeyName += RegistryPath->Length / sizeof(WCHAR); 148 EnumeratedKeyName[0] = '\\'; 149 ++ EnumeratedKeyName; 150 151 /* Append the parameters subkey */ 152 RtlCopyMemory(EnumeratedKeyName, 153 RegistrySubKey, 154 UnicodeSubkeyName.Length); 155 156 EnumeratedKeyName += UnicodeSubkeyName.Length / sizeof(WCHAR); 157 EnumeratedKeyName[0] = '\\'; 158 ++ EnumeratedKeyName; 159 160 /* And finally append the enumerated key name */ 161 RtlCopyMemory(EnumeratedKeyName, 162 FinalKeyInfo->Name, 163 FinalKeyInfo->NameLength); 164 165 EnumeratedKeyName += FinalKeyInfo->NameLength / sizeof(WCHAR); 166 EnumeratedKeyName[0] = UNICODE_NULL; 167 168 /* Reset pointer */ 169 EnumeratedKeyName = StartOfEnumeratedKeyName; 170 171 /* Convert into a Unicode string for the callback */ 172 RtlInitUnicodeString(&DeviceKeyName, EnumeratedKeyName); 173 174 Callback(&DeviceKeyName); 175 176 /* No longer need the key name */ 177 ExFreePool((PVOID)EnumeratedKeyName); 178 EnumeratedKeyName = NULL; 179 } 180 181 /* No longer need the key info */ 182 ExFreePool((PVOID)FinalKeyInfo); 183 FinalKeyInfo = NULL; 184 185 ++ i; 186 } 187 188 /* We're done with enumeration so close this */ 189 ZwClose(ChildKeyHandle); 190 191 /* This isn't an error */ 192 if ( Status == STATUS_NO_MORE_ENTRIES ) 193 { 194 Status = STATUS_SUCCESS; 195 } 196 197 /* No devices configured? */ 198 if ( i == 0 && Status == STATUS_NO_MORE_ENTRIES ) 199 { 200 Status = STATUS_DEVICE_CONFIGURATION_ERROR; 201 } 202 203 return Status; 204 } 205 206 NTSTATUS 207 PublishWaveOutDevice( 208 IN DWORD HardwareDeviceIndex, 209 IN PWSTR BaseDeviceName, 210 IN DWORD DeviceIndex, 211 IN LPWAVEOUTCAPS Capabilities) 212 { 213 return STATUS_SUCCESS; 214 } 215 216 217 typedef struct _SOUND_BLASTER_DEVICE 218 { 219 DWORD BasePort; 220 DWORD MidiUartBasePort; 221 222 DWORD Irq; 223 224 DWORD DmaChannel_8; 225 DWORD DmaChannel_16; 226 227 DWORD DspVersion; 228 229 DWORD ActualDmaBufferSize; 230 DWORD DmaBufferSize; 231 } SOUND_BLASTER_DEVICE; 232 233 234 NTSTATUS 235 AllocateSoundBlasterStructure(OUT SOUND_BLASTER_DEVICE* SoundBlasterDevice) 236 { 237 return STATUS_NOT_IMPLEMENTED; 238 } 239 240 /* callback */ 241 /* 242 Configuration options within the registry: 243 REG_DWORD Actual Dma Buffer Size 0x00004000 244 REG_DWORD Configuration Error 0xffffffff 245 REG_DWORD Dma Buffer Size 0x00004000 246 REG_DWORD DmaChannel 0x00000001 247 REG_DWORD DmaChannel16 0x00000005 248 REG_DWORD DSP Version 0x00000405 249 REG_DWORD Interrupt 0x00000005 250 REG_DWORD Load Type 0x00000000 251 REG_BINARY Mixer Settings ?? 252 REG_DWORD MPU401 Port 0xffffffff 253 REG_DWORD Port 0x00000220 254 */ 255 256 NTSTATUS 257 ConfigureSoundBlasterDevice(IN PUNICODE_STRING DeviceRegistryPath) 258 { 259 OBJECT_ATTRIBUTES RegAttributes; 260 NTSTATUS Status = STATUS_SUCCESS; 261 HKEY ConfigKeyHandle; 262 263 DPRINT("Configuring Sound Blaster (config at %S)\n", DeviceRegistryPath->Buffer); 264 265 if ( ! DeviceRegistryPath ) 266 { 267 return STATUS_INVALID_PARAMETER; 268 } 269 270 /* Open the registry key */ 271 InitializeObjectAttributes(&RegAttributes, 272 DeviceRegistryPath, 273 OBJ_CASE_INSENSITIVE, 274 NULL, 275 (PSECURITY_DESCRIPTOR) NULL); 276 277 Status = ZwOpenKey(&ConfigKeyHandle, KEY_READ, &RegAttributes); 278 279 if ( ! NT_SUCCESS(Status) ) 280 { 281 DPRINT("Failed to open config registry key\n"); 282 return Status; 283 } 284 285 /* Read configuration */ 286 DPRINT("Reading configuration\n"); 287 288 //Status = ZwQueryValueKey(ConfigKeyHandle, 289 290 return Status; 291 } 292 293 294 /* IRP DISPATCHERS **********************************************************/ 295 296 static NTSTATUS NTAPI 297 CreateSoundBlaster( 298 IN PDEVICE_OBJECT DeviceObject, 299 IN PIRP Irp) 300 { 301 DPRINT("Sound Blaster driver received IRP_MJ_CREATE\n"); 302 303 CompleteIrpAndReturn(Irp, STATUS_SUCCESS); 304 } 305 306 static NTSTATUS NTAPI 307 CloseSoundBlaster( 308 IN PDEVICE_OBJECT DeviceObject, 309 IN PIRP Irp) 310 { 311 DPRINT("Sound Blaster driver received IRP_MJ_CLOSE\n"); 312 313 CompleteIrpAndReturn(Irp, STATUS_SUCCESS); 314 } 315 316 static NTSTATUS NTAPI 317 CleanupSoundBlaster( 318 IN PDEVICE_OBJECT DeviceObject, 319 IN PIRP Irp) 320 { 321 DPRINT("Sound Blaster driver received IRP_MJ_CLEANUP\n"); 322 323 CompleteIrpAndReturn(Irp, STATUS_SUCCESS); 324 } 325 326 static NTSTATUS NTAPI 327 ControlSoundBlaster( 328 IN PDEVICE_OBJECT DeviceObject, 329 IN PIRP Irp) 330 { 331 DPRINT("Sound Blaster driver received IRP_MJ_CONTROL\n"); 332 333 CompleteIrpAndReturn(Irp, STATUS_SUCCESS); 334 } 335 336 static NTSTATUS NTAPI 337 WriteToSoundBlaster( 338 IN PDEVICE_OBJECT DeviceObject, 339 IN PIRP Irp) 340 { 341 DPRINT("Sound Blaster driver received IRP_MJ_WRITE\n"); 342 343 CompleteIrpAndReturn(Irp, STATUS_SUCCESS); 344 } 345 346 347 /* DRIVER ENTRYPOINT ********************************************************/ 348 349 NTSTATUS NTAPI 350 DriverEntry( 351 IN PDRIVER_OBJECT DriverObject, 352 IN PUNICODE_STRING RegistryPath) 353 { 354 NTSTATUS Status = STATUS_SUCCESS; 355 356 DPRINT("Sound Blaster driver by silverblade\n"); 357 358 DriverObject->Flags = 0; 359 DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateSoundBlaster; 360 DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseSoundBlaster; 361 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CleanupSoundBlaster; 362 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlSoundBlaster; 363 DriverObject->MajorFunction[IRP_MJ_WRITE] = WriteToSoundBlaster; 364 DriverObject->DriverUnload = UnloadSoundBlaster; 365 366 EnumerateSoundDevices(RegistryPath, L"Parameters", ConfigureSoundBlasterDevice); 367 368 return Status; 369 } 370 371 static VOID NTAPI 372 UnloadSoundBlaster(IN PDRIVER_OBJECT DriverObject) 373 { 374 DPRINT("Sound Blaster driver is being unloaded\n"); 375 } 376