/*++

Copyright (c) 1996 - 1998  Microsoft Corporation

Module Name:

    hidmini.c

Abstract: Human Input Device (HID) minidriver that creates an example
        device.

--*/
#include <WDM.H>
#include <USBDI.H>

#include <HIDPORT.H>
#include <HIDMINI.H>


NTSTATUS
DriverEntry(
           IN PDRIVER_OBJECT  DriverObject,
           IN PUNICODE_STRING registryPath
           )
/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    registryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    HID_MINIDRIVER_REGISTRATION HidMinidriverRegistration;

    DBGBREAK;

    DBGPrint(("HIDMINI.SYS: DriverEntry Enter\n"));

    DBGPrint(("HIDMINI.SYS: DriverObject (%lx)\n", DriverObject));

    //
    // Create dispatch points
    //
    // All of the other dispatch routines are handled by HIDCLASS, except for 
    // IRP_MJ_POWER, which isn't implemented yet.
    //

    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HidMiniIoctl;
    DriverObject->MajorFunction[IRP_MJ_PNP]                     = HidMiniPnP;
    DriverObject->MajorFunction[IRP_MJ_POWER]                   = HidMiniPower;
    DriverObject->DriverExtension->AddDevice                    = HidMiniAddDevice;
    DriverObject->DriverUnload                                  = HidMiniUnload;

    //
    // Register Sample layer with HIDCLASS.SYS module
    //

    HidMinidriverRegistration.Revision              = HID_REVISION;
    HidMinidriverRegistration.DriverObject          = DriverObject;
    HidMinidriverRegistration.RegistryPath          = registryPath;
    HidMinidriverRegistration.DeviceExtensionSize   = sizeof(DEVICE_EXTENSION);

    //  HIDMINI does not need to be polled.
    HidMinidriverRegistration.DevicesArePolled      = FALSE;

    DBGPrint(("HIDMINI.SYS: DeviceExtensionSize = %x\n", HidMinidriverRegistration.DeviceExtensionSize));

    DBGPrint(("HIDMINI.SYS: Registering with HIDCLASS.SYS\n"));

    //
    // After registering with HIDCLASS, it takes over control of the device, and sends
    // things our way if they need device specific processing.
    //
    ntStatus = HidRegisterMinidriver(&HidMinidriverRegistration);

    DBGPrint(("HIDMINI.SYS: DriverEntry Exit = %x\n", ntStatus));

    return ntStatus;
}


NTSTATUS
HidMiniAddDevice(
                IN PDRIVER_OBJECT DriverObject,
                IN PDEVICE_OBJECT DeviceObject
                )
/*++

Routine Description:

    Process AddDevice.  Provides the opportunity to initialize the DeviceObject or the
    DriverObject.

Arguments:

    DriverObject - pointer to the driver object.
    
    DeviceObject - pointer to a device object.

Return Value:

    NT status code.

--*/
{
    NTSTATUS                ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION       deviceExtension;

    DBGPrint(("\n\n"));
    DBGPrint(("HIDMINI.SYS: HidMiniAddDevice Entry\n"));

    deviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION( DeviceObject );

    KeInitializeEvent( &deviceExtension->AllRequestsCompleteEvent,
                       NotificationEvent,
                       FALSE );

    KeInitializeSpinLock( &deviceExtension->OutputRawQueue.SpinLock );
    KeInitializeSpinLock( &deviceExtension->OutputReportQueue.SpinLock );
    InitializeListHead( &deviceExtension->OutputRawQueue.List );
    InitializeListHead( &deviceExtension->OutputReportQueue.List );

    ExInitializeNPagedLookasideList ( &deviceExtension->OutputRawQueue.MemListPool,
                                      NULL,
                                      NULL,
                                      0,
                                      sizeof(HIDMINI_RAW_OUTPUT),
                                      'QwaR',   // HidMini RAW QUEUE
                                      0 );

    ExInitializeNPagedLookasideList    (    &deviceExtension->OutputReportQueue.MemListPool,
                                            NULL,
                                            NULL,
                                            0,
                                            sizeof(HIDMINI_REPORT_OUTPUT),
                                            'QpeR',   // HidMini Report QUEUE
                                            0 );

    deviceExtension->OutputRawQueue.nElements = 0;
    deviceExtension->OutputReportQueue.nElements = 0;

    KeInitializeDpc ( &deviceExtension->HidMiniWriteDPCObject,
                      HidMiniWriteDPC,
                      (PVOID)deviceExtension );

    KeInitializeTimer( &deviceExtension->HidMiniWriteTimer );

    //
    // Put the timer in the signaled state so that HidMiniWriteReport will
    // start it.
    //
    KeSetEvent( &deviceExtension->HidMiniWriteTimer, 0, FALSE );


    DBGPrint(("HIDMINI.SYS: HidMiniAddDevice Exit = %x\n", ntStatus));

    return ntStatus;
}



VOID
HidMiniUnload(
             IN PDRIVER_OBJECT DriverObject
             )
/*++

Routine Description:

    Free all the allocated resources, etc. in anticipation of this driver being unloaded.

Arguments:

    DriverObject - pointer to the driver object.

Return Value:

    VOID.

--*/
{
    DBGPrint(("HIDMINI.SYS: HidMiniUnload Enter\n"));

    DBGPrint(("HIDMINI.SYS: Unloading DriverObject = %x\n", DriverObject));

    DBGPrint(("HIDMINI.SYS: Unloading Exit = VOID\n"));
}


