Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpin.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/wdm/audio/sysaudio/deviface.c 00005 * PURPOSE: System Audio graph builder 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 #include "sysaudio.h" 00010 00011 NTSTATUS 00012 NTAPI 00013 Pin_fnDeviceIoControl( 00014 PDEVICE_OBJECT DeviceObject, 00015 PIRP Irp) 00016 { 00017 PDISPATCH_CONTEXT Context; 00018 NTSTATUS Status; 00019 ULONG BytesReturned; 00020 PFILE_OBJECT FileObject = NULL; 00021 PIO_STACK_LOCATION IoStack; 00022 00023 DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); 00024 00025 /* Get current stack location */ 00026 IoStack = IoGetCurrentIrpStackLocation(Irp); 00027 00028 /* The dispatch context is stored in the FsContext member */ 00029 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; 00030 00031 /* Sanity check */ 00032 ASSERT(Context); 00033 00034 /* acquire real pin file object */ 00035 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 00036 if (!NT_SUCCESS(Status)) 00037 { 00038 Irp->IoStatus.Information = 0; 00039 Irp->IoStatus.Status = Status; 00040 /* Complete the irp */ 00041 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00042 return Status; 00043 } 00044 00045 /* Re-dispatch the request to the real target pin */ 00046 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode, 00047 IoStack->Parameters.DeviceIoControl.Type3InputBuffer, 00048 IoStack->Parameters.DeviceIoControl.InputBufferLength, 00049 Irp->UserBuffer, 00050 IoStack->Parameters.DeviceIoControl.OutputBufferLength, 00051 &BytesReturned); 00052 /* release file object */ 00053 ObDereferenceObject(FileObject); 00054 00055 /* Save status and information */ 00056 Irp->IoStatus.Information = BytesReturned; 00057 Irp->IoStatus.Status = Status; 00058 /* Complete the irp */ 00059 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00060 /* Done */ 00061 return Status; 00062 } 00063 00064 00065 00066 NTSTATUS 00067 NTAPI 00068 Pin_fnWrite( 00069 PDEVICE_OBJECT DeviceObject, 00070 PIRP Irp) 00071 { 00072 PDISPATCH_CONTEXT Context; 00073 PIO_STACK_LOCATION IoStack; 00074 PFILE_OBJECT FileObject; 00075 NTSTATUS Status; 00076 00077 /* Get current stack location */ 00078 IoStack = IoGetCurrentIrpStackLocation(Irp); 00079 00080 /* The dispatch context is stored in the FsContext member */ 00081 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; 00082 00083 /* Sanity check */ 00084 ASSERT(Context); 00085 00086 if (Context->hMixerPin) 00087 { 00088 // FIXME 00089 // call kmixer to convert stream 00090 UNIMPLEMENTED 00091 } 00092 00093 /* acquire real pin file object */ 00094 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 00095 if (!NT_SUCCESS(Status)) 00096 { 00097 DPRINT1("failed\n"); 00098 Irp->IoStatus.Information = 0; 00099 Irp->IoStatus.Status = Status; 00100 /* Complete the irp */ 00101 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00102 return Status; 00103 } 00104 00105 /* skip current irp location */ 00106 IoSkipCurrentIrpStackLocation(Irp); 00107 00108 /* get next stack location */ 00109 IoStack = IoGetNextIrpStackLocation(Irp); 00110 /* store file object of next device object */ 00111 IoStack->FileObject = FileObject; 00112 IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; 00113 //ASSERT(Irp->AssociatedIrp.SystemBuffer); 00114 00115 /* now call the driver */ 00116 Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); 00117 00118 /* dereference file object */ 00119 ObDereferenceObject(FileObject); 00120 00121 return Status; 00122 00123 } 00124 00125 NTSTATUS 00126 NTAPI 00127 Pin_fnClose( 00128 PDEVICE_OBJECT DeviceObject, 00129 PIRP Irp) 00130 { 00131 PDISPATCH_CONTEXT Context; 00132 PIO_STACK_LOCATION IoStack; 00133 00134 //DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject, Irp); 00135 00136 /* Get current stack location */ 00137 IoStack = IoGetCurrentIrpStackLocation(Irp); 00138 00139 /* The dispatch context is stored in the FsContext member */ 00140 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; 00141 00142 if (Context->Handle) 00143 { 00144 ZwClose(Context->Handle); 00145 } 00146 00147 if (Context->hMixerPin) 00148 { 00149 ZwClose(Context->hMixerPin); 00150 } 00151 00152 FreeItem(Context); 00153 00154 Irp->IoStatus.Status = STATUS_SUCCESS; 00155 Irp->IoStatus.Information = 0; 00156 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00157 return STATUS_SUCCESS; 00158 } 00159 00160 static KSDISPATCH_TABLE PinTable = 00161 { 00162 Pin_fnDeviceIoControl, 00163 KsDispatchInvalidDeviceRequest, 00164 Pin_fnWrite, 00165 KsDispatchInvalidDeviceRequest, 00166 Pin_fnClose, 00167 KsDispatchInvalidDeviceRequest, 00168 KsDispatchInvalidDeviceRequest, 00169 KsDispatchFastIoDeviceControlFailure, 00170 KsDispatchFastReadFailure, 00171 KsDispatchFastWriteFailure, 00172 }; 00173 00174 NTSTATUS 00175 SetMixerInputOutputFormat( 00176 IN PFILE_OBJECT FileObject, 00177 IN PKSDATAFORMAT InputFormat, 00178 IN PKSDATAFORMAT OutputFormat) 00179 { 00180 KSP_PIN PinRequest; 00181 ULONG BytesReturned; 00182 NTSTATUS Status; 00183 00184 /* re-using pin */ 00185 PinRequest.Property.Set = KSPROPSETID_Connection; 00186 PinRequest.Property.Flags = KSPROPERTY_TYPE_SET; 00187 PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT; 00188 00189 /* set the input format */ 00190 PinRequest.PinId = 0; 00191 DPRINT("InputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", InputFormat, InputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX)); 00192 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, 00193 (PVOID)&PinRequest, 00194 sizeof(KSP_PIN), 00195 (PVOID)InputFormat, 00196 InputFormat->FormatSize, 00197 &BytesReturned); 00198 if (!NT_SUCCESS(Status)) 00199 return Status; 00200 00201 /* set the the output format */ 00202 PinRequest.PinId = 1; 00203 DPRINT("OutputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", OutputFormat, OutputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX)); 00204 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, 00205 (PVOID)&PinRequest, 00206 sizeof(KSP_PIN), 00207 (PVOID)OutputFormat, 00208 OutputFormat->FormatSize, 00209 &BytesReturned); 00210 return Status; 00211 } 00212 00213 00214 NTSTATUS 00215 CreateMixerPinAndSetFormat( 00216 IN HANDLE KMixerHandle, 00217 IN KSPIN_CONNECT *PinConnect, 00218 IN PKSDATAFORMAT InputFormat, 00219 IN PKSDATAFORMAT OutputFormat, 00220 OUT PHANDLE MixerPinHandle) 00221 { 00222 NTSTATUS Status; 00223 HANDLE PinHandle; 00224 PFILE_OBJECT FileObject = NULL; 00225 00226 Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle); 00227 00228 if (!NT_SUCCESS(Status)) 00229 { 00230 DPRINT1("Failed to create Mixer Pin with %x\n", Status); 00231 return STATUS_UNSUCCESSFUL; 00232 } 00233 00234 Status = ObReferenceObjectByHandle(PinHandle, 00235 GENERIC_READ | GENERIC_WRITE, 00236 IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 00237 00238 if (!NT_SUCCESS(Status)) 00239 { 00240 DPRINT1("Failed to get file object with %x\n", Status); 00241 return STATUS_UNSUCCESSFUL; 00242 } 00243 00244 Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat); 00245 if (!NT_SUCCESS(Status)) 00246 { 00247 ObDereferenceObject(FileObject); 00248 ZwClose(PinHandle); 00249 return Status; 00250 } 00251 00252 ObDereferenceObject(FileObject); 00253 00254 *MixerPinHandle = PinHandle; 00255 return Status; 00256 } 00257 00258 00259 NTSTATUS 00260 NTAPI 00261 InstantiatePins( 00262 IN PKSAUDIO_DEVICE_ENTRY DeviceEntry, 00263 IN PKSPIN_CONNECT Connect, 00264 IN PDISPATCH_CONTEXT DispatchContext, 00265 IN PSYSAUDIODEVEXT DeviceExtension) 00266 { 00267 NTSTATUS Status; 00268 HANDLE RealPinHandle; 00269 PKSDATAFORMAT_WAVEFORMATEX InputFormat; 00270 PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL; 00271 PKSPIN_CONNECT MixerPinConnect = NULL; 00272 KSPIN_CINSTANCES PinInstances; 00273 00274 DPRINT("InstantiatePins entered\n"); 00275 00276 /* query instance count */ 00277 Status = GetPinInstanceCount(DeviceEntry, &PinInstances, Connect); 00278 if (!NT_SUCCESS(Status)) 00279 { 00280 /* failed to query instance count */ 00281 return Status; 00282 } 00283 00284 /* can be the pin be instantiated */ 00285 if (PinInstances.PossibleCount == 0) 00286 { 00287 /* caller wanted to open an instance-less pin */ 00288 return STATUS_UNSUCCESSFUL; 00289 } 00290 00291 /* has the maximum instance count been exceeded */ 00292 if (PinInstances.CurrentCount == PinInstances.PossibleCount) 00293 { 00294 /* FIXME pin already exists 00295 * and kmixer infrastructure is not implemented 00296 */ 00297 return STATUS_UNSUCCESSFUL; 00298 } 00299 00300 /* Fetch input format */ 00301 InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1); 00302 00303 /* Let's try to create the audio irp pin */ 00304 Status = KsCreatePin(DeviceEntry->Handle, Connect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); 00305 00306 if (!NT_SUCCESS(Status)) 00307 { 00308 /* FIXME disable kmixer 00309 */ 00310 return STATUS_UNSUCCESSFUL; 00311 } 00312 #if 0 00313 if (!NT_SUCCESS(Status)) 00314 { 00315 /* the audio irp pin didnt accept the input format 00316 * let's compute a compatible format 00317 */ 00318 MixerPinConnect = AllocateItem(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); 00319 if (!MixerPinConnect) 00320 { 00321 /* not enough memory */ 00322 return STATUS_INSUFFICIENT_RESOURCES; 00323 } 00324 00325 /* Zero pin connect */ 00326 RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); 00327 00328 /* Copy initial connect details */ 00329 RtlMoveMemory(MixerPinConnect, Connect, sizeof(KSPIN_CONNECT)); 00330 00331 00332 OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1); 00333 00334 Status = ComputeCompatibleFormat(DeviceEntry, Connect->PinId, InputFormat, OutputFormat); 00335 if (!NT_SUCCESS(Status)) 00336 { 00337 DPRINT1("ComputeCompatibleFormat failed with %x\n", Status); 00338 FreeItem(MixerPinConnect); 00339 return Status; 00340 } 00341 00342 /* Retry with Mixer format */ 00343 Status = KsCreatePin(DeviceEntry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); 00344 if (!NT_SUCCESS(Status)) 00345 { 00346 /* This should not fail */ 00347 DPRINT1("KsCreatePin failed with %x\n", Status); 00348 DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels); 00349 DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels); 00350 00351 FreeItem(MixerPinConnect); 00352 return Status; 00353 } 00354 } 00355 #endif 00356 00357 //DeviceEntry->Pins[Connect->PinId].References = 0; 00358 00359 /* initialize dispatch context */ 00360 DispatchContext->Handle = RealPinHandle; 00361 DispatchContext->PinId = Connect->PinId; 00362 DispatchContext->AudioEntry = DeviceEntry; 00363 00364 00365 DPRINT("RealPinHandle %p\n", RealPinHandle); 00366 00367 /* Do we need to transform the audio stream */ 00368 if (OutputFormat != NULL) 00369 { 00370 /* Now create the mixer pin */ 00371 Status = CreateMixerPinAndSetFormat(DeviceExtension->KMixerHandle, 00372 MixerPinConnect, 00373 (PKSDATAFORMAT)InputFormat, 00374 (PKSDATAFORMAT)OutputFormat, 00375 &DispatchContext->hMixerPin); 00376 00377 /* check for success */ 00378 if (!NT_SUCCESS(Status)) 00379 { 00380 DPRINT1("Failed to create Mixer Pin with %x\n", Status); 00381 FreeItem(MixerPinConnect); 00382 } 00383 } 00384 /* done */ 00385 return Status; 00386 } 00387 00388 NTSTATUS 00389 GetConnectRequest( 00390 IN PIRP Irp, 00391 OUT PKSPIN_CONNECT * Result) 00392 { 00393 PIO_STACK_LOCATION IoStack; 00394 ULONG ObjectLength, ParametersLength; 00395 PVOID Buffer; 00396 00397 /* get current irp stack */ 00398 IoStack = IoGetCurrentIrpStackLocation(Irp); 00399 00400 /* get object class length */ 00401 ObjectLength = (wcslen(KSSTRING_Pin) + 1) * sizeof(WCHAR); 00402 00403 /* check for minium length requirement */ 00404 if (ObjectLength + sizeof(KSPIN_CONNECT) > IoStack->FileObject->FileName.MaximumLength) 00405 return STATUS_UNSUCCESSFUL; 00406 00407 /* extract parameters length */ 00408 ParametersLength = IoStack->FileObject->FileName.MaximumLength - ObjectLength; 00409 00410 /* allocate buffer */ 00411 Buffer = AllocateItem(NonPagedPool, ParametersLength); 00412 if (!Buffer) 00413 return STATUS_INSUFFICIENT_RESOURCES; 00414 00415 /* copy parameters */ 00416 RtlMoveMemory(Buffer, &IoStack->FileObject->FileName.Buffer[ObjectLength / sizeof(WCHAR)], ParametersLength); 00417 00418 /* store result */ 00419 *Result = (PKSPIN_CONNECT)Buffer; 00420 00421 return STATUS_SUCCESS; 00422 } 00423 00424 00425 00426 NTSTATUS 00427 NTAPI 00428 DispatchCreateSysAudioPin( 00429 IN PDEVICE_OBJECT DeviceObject, 00430 IN PIRP Irp) 00431 { 00432 NTSTATUS Status = STATUS_SUCCESS; 00433 PIO_STACK_LOCATION IoStack; 00434 PKSAUDIO_DEVICE_ENTRY DeviceEntry; 00435 PKSPIN_CONNECT Connect; 00436 PDISPATCH_CONTEXT DispatchContext; 00437 00438 DPRINT("DispatchCreateSysAudioPin entered\n"); 00439 00440 /* get current stack location */ 00441 IoStack = IoGetCurrentIrpStackLocation(Irp); 00442 00443 /* sanity checks */ 00444 ASSERT(IoStack->FileObject); 00445 ASSERT(IoStack->FileObject->RelatedFileObject); 00446 ASSERT(IoStack->FileObject->RelatedFileObject->FsContext); 00447 00448 /* get current attached virtual device */ 00449 DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)IoStack->FileObject->RelatedFileObject->FsContext; 00450 00451 /* check for success */ 00452 if (!NT_SUCCESS(Status)) 00453 { 00454 /* failed */ 00455 Irp->IoStatus.Status = Status; 00456 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00457 return Status; 00458 } 00459 00460 /* get connect details */ 00461 Status = GetConnectRequest(Irp, &Connect); 00462 00463 /* check for success */ 00464 if (!NT_SUCCESS(Status)) 00465 { 00466 /* failed to obtain connect details */ 00467 Irp->IoStatus.Status = Status; 00468 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00469 return Status; 00470 } 00471 00472 00473 /* allocate dispatch context */ 00474 DispatchContext = AllocateItem(NonPagedPool, sizeof(DISPATCH_CONTEXT)); 00475 if (!DispatchContext) 00476 { 00477 /* failed */ 00478 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 00479 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00480 return STATUS_INSUFFICIENT_RESOURCES; 00481 } 00482 00483 /* zero dispatch context */ 00484 RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT)); 00485 00486 /* allocate object header */ 00487 Status = KsAllocateObjectHeader(&DispatchContext->ObjectHeader, 0, NULL, Irp, &PinTable); 00488 if (!NT_SUCCESS(Status)) 00489 { 00490 /* failed */ 00491 FreeItem(DispatchContext); 00492 Irp->IoStatus.Status = Status; 00493 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00494 return Status; 00495 } 00496 00497 /* now instantiate the pins */ 00498 Status = InstantiatePins(DeviceEntry, Connect, DispatchContext, (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension); 00499 if (!NT_SUCCESS(Status)) 00500 { 00501 /* failed */ 00502 KsFreeObjectHeader(DispatchContext->ObjectHeader); 00503 FreeItem(DispatchContext); 00504 } 00505 else 00506 { 00507 /* store dispatch context */ 00508 IoStack->FileObject->FsContext = (PVOID)DispatchContext; 00509 } 00510 00511 00512 /* FIXME create items for clocks / allocators */ 00513 Irp->IoStatus.Status = Status; 00514 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00515 return Status; 00516 } Generated on Fri May 25 2012 04:19:51 for ReactOS by
1.7.6.1
|