From b0d0ca15fb749d70db3bb2af392078c4926b4d88 Mon Sep 17 00:00:00 2001 From: Andrew Greenwood Date: Thu, 24 Nov 2005 13:30:51 +0000 Subject: [PATCH] Some preliminary stubbing of the Kernel Streaming components (portcls being moved from other directory) svn path=/trunk/; revision=19525 --- reactos/drivers/multimedia/README | 17 + reactos/drivers/multimedia/avtest/avtest.xml | 8 + reactos/drivers/multimedia/avtest/entry.c | 83 +++++ reactos/drivers/multimedia/directory.xml | 24 ++ reactos/drivers/multimedia/ks.h | 352 +++++++++++++++++++ reactos/drivers/multimedia/ks/avstream.c | 16 + reactos/drivers/multimedia/ks/connect.c | 57 +++ reactos/drivers/multimedia/ks/ks.def | 7 + reactos/drivers/multimedia/ks/ks.xml | 9 + reactos/drivers/multimedia/ks/stubs.c | 112 ++++++ reactos/drivers/multimedia/wdmaud/entry.c | 59 ++++ reactos/drivers/multimedia/wdmaud/wdmaud.xml | 7 + 12 files changed, 751 insertions(+) create mode 100755 reactos/drivers/multimedia/README create mode 100755 reactos/drivers/multimedia/avtest/avtest.xml create mode 100755 reactos/drivers/multimedia/avtest/entry.c create mode 100755 reactos/drivers/multimedia/directory.xml create mode 100755 reactos/drivers/multimedia/ks.h create mode 100755 reactos/drivers/multimedia/ks/avstream.c create mode 100755 reactos/drivers/multimedia/ks/connect.c create mode 100755 reactos/drivers/multimedia/ks/ks.def create mode 100755 reactos/drivers/multimedia/ks/ks.xml create mode 100755 reactos/drivers/multimedia/ks/stubs.c create mode 100755 reactos/drivers/multimedia/wdmaud/entry.c create mode 100755 reactos/drivers/multimedia/wdmaud/wdmaud.xml diff --git a/reactos/drivers/multimedia/README b/reactos/drivers/multimedia/README new file mode 100755 index 00000000000..33e5266d9a7 --- /dev/null +++ b/reactos/drivers/multimedia/README @@ -0,0 +1,17 @@ +This is a directory for the kernel streaming components, along with multimedia +kernel-mode drivers. + +Platform components: +- ks.sys Kernel Streaming (and AvStream) +- sysaudio Filter graph builder (topology?) +- portcls Port Class +- wdmaud Kernel-mode portion of the MME (Win 3.1-style) driver + +Optional drivers: +- sndblst Sound Blaster (+ Pro / 16) compatible driver +- mpu401 MPU-401 MIDI compatible driver + +Much of this code exists only as stubs for future implementation. + +-Andrew Greenwood + diff --git a/reactos/drivers/multimedia/avtest/avtest.xml b/reactos/drivers/multimedia/avtest/avtest.xml new file mode 100755 index 00000000000..5088f33c374 --- /dev/null +++ b/reactos/drivers/multimedia/avtest/avtest.xml @@ -0,0 +1,8 @@ + + . + .. + + ks + ntoskrnl + entry.c + diff --git a/reactos/drivers/multimedia/avtest/entry.c b/reactos/drivers/multimedia/avtest/entry.c new file mode 100755 index 00000000000..2c66a5e85ba --- /dev/null +++ b/reactos/drivers/multimedia/avtest/entry.c @@ -0,0 +1,83 @@ +#include +#include + +/* Where do we go? */ +#ifndef SIZEOF_ARRAY + #define SIZEOF_ARRAY(array) \ + (sizeof(array) / sizeof(array[0])) +#endif + +/* Not in the DDK but hey! */ +#define DEFINE_KSFILTER_DISPATCH(name) \ + const KSFILTER_DISPATCH name = + +/* To be put in KS.H */ +#define DEFINE_KSFILTER_DESCRIPTOR(name) \ + const KSFILTER_DESCRIPTOR name = + +#define DEFINE_KSFILTER_DESCRIPTOR_TABLE(name) \ + const KSFILTER_DESCRIPTOR* const name[] = + + + +NTSTATUS FilterCreate( + IN OUT PKSFILTER Filter, + IN PIRP Irp) +{ + return STATUS_SUCCESS; +} + +NTSTATUS FilterClose( + IN OUT PKSFILTER Filter, + IN PIRP Irp) +{ + return STATUS_SUCCESS; +} + +NTSTATUS Process( + IN PKSFILTER Filter, + IN PKSPROCESSPIN_INDEXENTRY ProcessPinsIndex) +{ + return STATUS_SUCCESS; +} + + +DEFINE_KSFILTER_DISPATCH(FilterDispatch) +{ + FilterCreate, + FilterClose, + Process, + NULL // Reset +}; + +DEFINE_KSFILTER_DESCRIPTOR(FilterDesc) +{ +}; + +DEFINE_KSFILTER_DESCRIPTOR_TABLE(FilterDescs) +{ + &FilterDesc +}; + + + +const KSDEVICE_DESCRIPTOR DeviceDescriptor = +{ + NULL, + SIZEOF_ARRAY(FilterDescs), + FilterDescs +}; + + +/* Funcs */ + +NTSTATUS STDCALL +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPathName) +{ + DPRINT1("AVStream test component loaded!\n"); + + return KsInitializeDriver(DriverObject, RegistryPathName, + &DeviceDescriptor); +} diff --git a/reactos/drivers/multimedia/directory.xml b/reactos/drivers/multimedia/directory.xml new file mode 100755 index 00000000000..513f4ba8557 --- /dev/null +++ b/reactos/drivers/multimedia/directory.xml @@ -0,0 +1,24 @@ + + + + + + + + + + diff --git a/reactos/drivers/multimedia/ks.h b/reactos/drivers/multimedia/ks.h new file mode 100755 index 00000000000..c9dd477ac7c --- /dev/null +++ b/reactos/drivers/multimedia/ks.h @@ -0,0 +1,352 @@ +/* + Kernel Streaming + + Part of the ReactOS project + (See ReactOS licence for usage restrictions/permissions) + + This file created by Andrew Greenwood. + + Started September 12th, 2005. + + You may notice some structs are empty. These are just placeholders and + should be fleshed-out when functions are implemented that require the + use of such structs. +*/ + +#ifndef __INCLUDES_REACTOS_KS_H__ +#define __INCLUDES_REACTOS_KS_H__ + +#include + +/* What's this meant to be?! */ +#define KSDDKAPI + + +/* Some unimplemented structs :) */ + +typedef struct _BUS_INTERFACE_REFERENCE +{ +} BUS_INTERFACE_REFERENCE, *PBUS_INTERFACE_REFERENCE; + +typedef struct _KSPIN_DESCRIPTOR +{ +} KSPIN_DESCRIPTOR, *PKSPIN_DESCRIPTOR; + +typedef struct _KSPIN_DESCRIPTOR_EX +{ +} KSPIN_DESCRIPTOR_EX, *PKSPIN_DESCRIPTOR_EX; + + +/* This is just to shut the compiler up so DON'T USE IT! */ +typedef void (*PFNKSINTERSECTHANDLER)(void); + + + +typedef struct _KS_COMPRESSION +{ + ULONG RatioNumerator; + ULONG RatioDenominator; + ULONG RatioConstantMargin; +} KS_COMPRESSION, *PKS_COMPRESSION; + +typedef struct _KS_FRAMING_RANGE +{ + ULONG MinFrameSize; + ULONG MaxFrameSize; + ULONG Stepping; +} KS_FRAMING_RANGE, *PKS_FRAMING_RANGE; + +typedef struct _KS_FRAMING_RANGE_WEIGHTED +{ + /* Obsolete */ +} KS_FRAMING_RANGE_WEIGHTED, *PKS_FRAMING_RANGE_WEIGHTED; + +typedef struct _KS_FRAMING_ITEM +{ + GUID MemoryType; + GUID BusType; + ULONG MemoryFlags; + ULONG BusFlags; + ULONG Flags; + ULONG Frames; + ULONG FileAlignment; + ULONG MemoryTypeWeight; + KS_FRAMING_RANGE PhysicalRange; + KS_FRAMING_RANGE_WEIGHTED FramingRange; +} KS_FRAMING_ITEM, *PKS_FRAMING_ITEM; + + + +typedef struct _KSALLOCATOR_FRAMING +{ + union + { + ULONG OptionFlags; + ULONG RequirementsFlags; + }; + POOL_TYPE PoolType; + ULONG Frames; + ULONG FrameSize; + ULONG FileAlignment; + ULONG Reserved; +} KSALLOCATOR_FRAMING, *PKSALLOCATOR_FRAMING; + +typedef struct _KSALLOCATOR_FRAMING_EX +{ + ULONG CountItems; + ULONG PinFlags; + KS_COMPRESSION OutputCompression; + ULONG PinWeight; + KS_FRAMING_ITEM FramingItem[1]; +} KSALLOCATOR_FRAMING_EX, *PKSALLOCATOR_FRAMING_EX; + + + +typedef struct _KSATTRIBUTE +{ + ULONG Size; + ULONG Flags; + GUID Attribute; +} KSATTRIBUTE, *PKSATTRIBUTE; + + +/* +typedef struct _KSBUFFER_ITEM +{ + KSDPC_ITEM DpcItem; + LIST_ENTRY BufferList; +} KSBUFFER_ITEM, *PKSBUFFER_ITEM; +*/ + + +typedef struct _KSIDENTIFIER +{ + GUID Set; + ULONG Id; + ULONG Flags; +} KSIDENTIFIER; + +typedef KSIDENTIFIER KSPIN_MEDIUM, *PKSPIN_MEDIUM; +typedef KSIDENTIFIER KSPIN_INTERFACE, *PKSPIN_INTERFACE; +typedef KSIDENTIFIER KSPROPERTY, *PKSPROPERTY; + +typedef struct _KSPRIORITY +{ + ULONG PriorityClass; + ULONG PrioritySubClass; +} KSPRIORITY, *PKSPRIORITY; + +typedef struct _KSPIN_CONNECT +{ + KSPIN_INTERFACE Interface; + KSPIN_MEDIUM Medium; + ULONG PinId; + HANDLE PinToHandle; + KSPRIORITY Priority; +} KSPIN_CONNECT, *PKSPIN_CONNECT; + +typedef struct _KSP_PIN +{ + KSPROPERTY Property; + ULONG PinId; + ULONG Reserved; +} KSP_PIN, *PKSP_PIN; + + +typedef struct _KSDEVICE +{ + /* TODO */ +} KSDEVICE, *PKSDEVICE; + + +/* Device dispatch routines */ + +typedef NTSTATUS + (*PFNKSDEVICECREATE) + ( + IN PKSDEVICE Device + ); + +typedef NTSTATUS + (*PFNKSDEVICEPNPSTART) + ( + IN PKSDEVICE Device, + IN PIRP Irp, + IN PCM_RESOURCE_LIST TranslatedResourceList OPTIONAL, + IN PCM_RESOURCE_LIST UntranslatedResourceList OPTIONAL + ); + +typedef NTSTATUS + (*PFNKSDEVICE) + ( + IN PKSDEVICE Device + ); + +typedef NTSTATUS + (*PFNKSDEVICEIRP) + ( + IN PKSDEVICE Device, + IN PIRP Irp + ); + +typedef VOID + (*PFNKSDEVICEIRPVOID) + ( + IN PKSDEVICE Device, + IN PIRP Irp + ); + +typedef NTSTATUS + (*PFNKSDEVICEQUERYCAPABILITIES) + ( + IN PKSDEVICE Device, + IN PIRP Irp, + IN OUT PDEVICE_CAPABILITIES Capabilities + ); + +typedef NTSTATUS + (*PFNKSDEVICEQUERYPOWER) + ( + IN PKSDEVICE Device, + IN PIRP Irp, + IN DEVICE_POWER_STATE DeviceTo, + IN DEVICE_POWER_STATE DeviceFrom, + IN SYSTEM_POWER_STATE SystemTo, + IN SYSTEM_POWER_STATE SystemFrom, + IN POWER_ACTION Action + ); + +typedef VOID + (*PFNKSDEVICESETPOWER) + ( + IN PKSDEVICE Device, + IN PIRP Irp, + IN DEVICE_POWER_STATE To, + IN DEVICE_POWER_STATE From + ); + +typedef struct _KSDEVICE_DISPATCH +{ + PFNKSDEVICECREATE Add; + PFNKSDEVICEPNPSTART Start; + PFNKSDEVICE PostStart; + PFNKSDEVICEIRP QueryStop; + PFNKSDEVICEIRPVOID CancelStop; + PFNKSDEVICEIRPVOID Stop; + PFNKSDEVICEIRP QueryRemove; + PFNKSDEVICEIRPVOID CancelRemove; + PFNKSDEVICEIRPVOID Remove; + PFNKSDEVICEQUERYCAPABILITIES QueryCapabilities; + PFNKSDEVICEIRPVOID SurpriseRemoval; + PFNKSDEVICEQUERYPOWER Querypower; + PFNKSDEVICESETPOWER SetPower; +} KSDEVICE_DISPATCH, *PKSDEVICE_DISPATCH; + + + +/* Some more unimplemented stuff */ + +typedef struct _KSFILTER +{ +} KSFILTER, *PKSFILTER; + +typedef struct _KSPROCESSPIN_INDEXENTRY +{ +} KSPROCESSPIN_INDEXENTRY, *PKSPROCESSPIN_INDEXENTRY; + + +/* Filter dispatch routines */ + +typedef NTSTATUS + (*PFNKSFILTERIRP) + ( + IN PKSFILTER Filter, + IN PIRP Irp + ); + +typedef NTSTATUS + (*PFNKSFILTERPROCESS) + ( + IN PKSFILTER FIlter, + IN PKSPROCESSPIN_INDEXENTRY ProcessPinsIndex + ); + +typedef NTSTATUS + (*PFNKSFILTERVOID) + ( + IN PKSFILTER Filter + ); + +typedef struct _KSFILTER_DISPATCH +{ + PFNKSFILTERIRP Create; + PFNKSFILTERIRP Close; + PFNKSFILTERPROCESS Process; + PFNKSFILTERVOID Reset; +} KSFILTER_DISPATCH, *PKSFILTER_DISPATCH; + + + +/* TODO! */ + +typedef struct _KSAUTOMATION_TABLE +{ +} KSAUTOMATION_TABLE, *PKSAUTOMATION_TABLE; + +typedef struct _KSNODE_DESCRIPTOR +{ +} KSNODE_DESCRIPTOR, *PKSNODE_DESCRIPTOR; + +typedef struct _KSTOPOLOGY_CONNECTION +{ +} KSTOPOLOGY_CONNECTION, *PKSTOPOLOGY_CONNECTION; + +typedef struct _KSCOMPONENTID +{ +} KSCOMPONENTID, *PKSCOMPONENTID; + + +/* Descriptors (filter, device, ...) */ + +typedef struct _KSFILTER_DESCRIPTOR +{ + const KSFILTER_DISPATCH* Dispatch; + const KSAUTOMATION_TABLE* AutomationTable; + ULONG Version; + ULONG Flags; + const GUID* ReferenceGuid; + ULONG PinDescriptorsCount; + ULONG PinDescriptorSize; + const KSPIN_DESCRIPTOR_EX* PinDescriptors; + ULONG CategoriesCount; + const GUID* Categories; + ULONG NodeDescriptorsCount; + ULONG NodeDescriptorSize; + const KSNODE_DESCRIPTOR* NodeDescriptors; + ULONG ConnectionsCount; + const KSTOPOLOGY_CONNECTION* Connections; + const KSCOMPONENTID* ComponentId; +} KSFILTER_DESCRIPTOR, *PKSFILTER_DESCRIPTOR; + +typedef struct _KSDEVICE_DESCRIPTOR +{ + const KSDEVICE_DISPATCH* Dispatch; + ULONG FilterDescriptorsCount; + const KSFILTER_DESCRIPTOR* const* FilterDescriptors; + ULONG Version; /* Doesn't appear to be in the documentation */ +} KSDEVICE_DESCRIPTOR, *PKSDEVICE_DESCRIPTOR; + + + + +/* + API functions +*/ + +NTSTATUS NTAPI +KsInitializeDriver( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL); + +#endif diff --git a/reactos/drivers/multimedia/ks/avstream.c b/reactos/drivers/multimedia/ks/avstream.c new file mode 100755 index 00000000000..ed358b3ca82 --- /dev/null +++ b/reactos/drivers/multimedia/ks/avstream.c @@ -0,0 +1,16 @@ +#include +#include + + +NTSTATUS NTAPI +KsInitializeDriver( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL) +{ + DPRINT("KsInitializeDriver\n"); + + /* This should set up IRPs etc. */ + + return STATUS_NOT_IMPLEMENTED; +} diff --git a/reactos/drivers/multimedia/ks/connect.c b/reactos/drivers/multimedia/ks/connect.c new file mode 100755 index 00000000000..103de91b334 --- /dev/null +++ b/reactos/drivers/multimedia/ks/connect.c @@ -0,0 +1,57 @@ +/* + ReactOS Kernel Streaming component + + Written (or rather, stubbed!) by Andrew Greenwood + September 2005 +*/ + +#include + +KSDDKAPI NTSTATUS NTAPI +KsCreatePin( + IN HANDLE FilterHandle, + IN PKSPIN_CONNECT Connect, + IN ACCESS_MASK DesiredAccess, + OUT PHANDLE ConnectionHandle) +{ +} + +KSDDKAPI NTSTATUS NTAPI +KsHandleSizedListQuery( + IN PIRP Irp, + IN ULONG DataItemsCount, + IN ULONG DataItemSize, + IN const VOID* DataItems) +{ +} + +KSDDKAPI NTSTATUS NTAPI +KsPinDataIntersection( + IN PIRP Irp, + IN PKSP_PIN Pin, + OUT PVOID Data, + IN ULONG DescriptorsCount, + IN const KSPIN_DESCRIPTOR* Descriptor, + IN PFNKSINTERSECTHANDLER IntersectHandler) +{ +} + +KSDDKAPI NTSTATUS NTAPI +KsPinPropertyHandler( + IN PIRP Irp, + IN PKSPROPERTY Property, + IN OUT PVOID Data, + IN ULONG DescriptorsCount, + IN const KSPIN_DESCRIPTOR* Descriptor) +{ +} + +KSDDKAPI NTSTATUS NTAPI +KsValidateConnectRequest( + IN PIRP Irp, + IN ULONG DescriptorsCount, + IN KSPIN_DESCRIPTOR* Descriptor, + OUT PKSPIN_CONNECT* Connect) +{ +} + diff --git a/reactos/drivers/multimedia/ks/ks.def b/reactos/drivers/multimedia/ks/ks.def new file mode 100755 index 00000000000..f1cf706a2e8 --- /dev/null +++ b/reactos/drivers/multimedia/ks/ks.def @@ -0,0 +1,7 @@ +; ks.sys - Kernel Streaming + +LIBRARY ks.sys + +EXPORTS +KsInitializeDriver@12 + diff --git a/reactos/drivers/multimedia/ks/ks.xml b/reactos/drivers/multimedia/ks/ks.xml new file mode 100755 index 00000000000..785dc0afd29 --- /dev/null +++ b/reactos/drivers/multimedia/ks/ks.xml @@ -0,0 +1,9 @@ + + . + .. + + ntoskrnl + + + avstream.c + diff --git a/reactos/drivers/multimedia/ks/stubs.c b/reactos/drivers/multimedia/ks/stubs.c new file mode 100755 index 00000000000..39c8bd0f318 --- /dev/null +++ b/reactos/drivers/multimedia/ks/stubs.c @@ -0,0 +1,112 @@ +#include "ks.h" + + +typedef struct _KSDEVICE_DESCRIPTOR +{ +} KSDEVICE_DESCRIPTOR, *PKSDEVICE_DESCRIPTOR; + +typedef struct _KSDEVICE +{ +} KSDEVICE, *PKSDEVICE; + + +NTSTATUS +KsAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + /* KsCreateDevice(DriverObject, PhysicalDeviceObject, ...); */ + + return STATUS_NOT_IMPLEMENTED; +} + + + +NTSTATUS +KsInitializeDriver( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath, + IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +KsInitializeDevice( + IN PDEVICE_OBJECT FunctionalDeviceObject, + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN PDEVICE_OBJECT NextDeviceObject, + IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +KsCreateDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PhysicalDeviceObject, + IN const KSDEVICE_DESCRIPTOR* Descriptor OPTIONAL, + IN ULONG ExtensionSize OPTIONAL, + OUT PKSDEVICE* Device OPTIONAL) +{ + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +KsTerminateDevice( + IN PDEVICE_OBJECT DeviceObject) +{ + return STATUS_NOT_IMPLEMENTED; +} + + + +VOID +KsAcquireDevice( + IN PKSDEVICE Device) +{ + /* Acquire device mutex */ +} + +VOID +KsReleaseDevice( + IN PKSDEVICE Device) +{ + /* Releases device mutex and exits critical region */ +} + +VOID +KsAcquireControl( + IN PVOID Object) +{ + /* Acquire filter control mutex for Object */ + /* Object should be pointed to a KSFILTER or KSPIN */ +} + + +PKSDEVICE +KsGetDevice( + IN PVOID Object) +{ + /* ? */ + return 0; +} + +// inline +/* +PKSDEVICE __inline +KsFilterGetDevice( + IN PKSFILTER Filter) +{ + return KsGetDevice((PVOID) Filter); +} + +PKSDEVICE __inline +KsPinGetDevice( + IN PKSPIN Pin) +{ + return KsGetDevice((PVOID) Pin); +} +*/ diff --git a/reactos/drivers/multimedia/wdmaud/entry.c b/reactos/drivers/multimedia/wdmaud/entry.c new file mode 100755 index 00000000000..c1956e86ad4 --- /dev/null +++ b/reactos/drivers/multimedia/wdmaud/entry.c @@ -0,0 +1,59 @@ +/* + This doesn't do much yet... +*/ + +#include + +#define InPassiveIrql() \ + (KeGetCurrentIrql() == IRQL_PASSIVE_LEVEL) + + +NTSTATUS AudioDeviceControl( + IN PDEVICE_OBJECT device, + IN PIRP irp +) +{ + return STATUS_SUCCESS; +} + + +NTSTATUS AudioAddDevice( + IN PDRIVER_OBJECT driver, + IN PDEVICE_OBJECT device +) +{ + DPRINT("AudioAddDevice called\n"); + + if ( ! IsPassiveIrql() ) + { + /* What do we do?! */ + /* RtlAssert("FAIL", __FILE__, __LINE__, "?" */ + } + + return STATUS_SUCCESS; +} + +VOID AudioUnload( + IN PDRIVER_OBJECT driver +) +{ + DPRINT("AudioUnload called\n"); +} + + + +NTSTATUS STDCALL +DriverEntry( + IN PDRIVER_OBJECT driver, + IN PUNICODE_STRING registry_path +) +{ + DPRINT("Wdmaud.sys loaded\n"); + + driver->DriverExtension->AddDevice = AudioAddDevice; + driver->DriverUnload = AudioUnload; + + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AudioDeviceControl; + + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/multimedia/wdmaud/wdmaud.xml b/reactos/drivers/multimedia/wdmaud/wdmaud.xml new file mode 100755 index 00000000000..a421f9a5832 --- /dev/null +++ b/reactos/drivers/multimedia/wdmaud/wdmaud.xml @@ -0,0 +1,7 @@ + + . + .. + + ntoskrnl + entry.c +