ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pin.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.