/**
 * @file ntdd8042.h
 * Copyright 2012, 2013 MinGW.org project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
/* Created by Casper S. Hornstrup <chorns@users.sourceforge.net> */
#ifndef __NTDD8042_H
#define __NTDD8042_H
#pragma GCC system_header
#include <_mingw.h>

/*
 * i8042 IOCTL interface.
 */

#ifdef __cplusplus
extern "C" {
#endif

#include "ntddk.h"
#include "ntddkbd.h"
#include "ntddmou.h"

#define IOCTL_INTERNAL_I8042_CONTROLLER_WRITE_BUFFER \
  CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF2, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_INTERNAL_I8042_HOOK_KEYBOARD \
  CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF0, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_INTERNAL_I8042_KEYBOARD_START_INFORMATION \
  CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF3, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_INTERNAL_I8042_KEYBOARD_WRITE_BUFFER \
  CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0FF1, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_INTERNAL_I8042_HOOK_MOUSE \
  CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF0, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_INTERNAL_I8042_MOUSE_START_INFORMATION \
  CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF3, METHOD_NEITHER, FILE_ANY_ACCESS)

#define IOCTL_INTERNAL_I8042_MOUSE_WRITE_BUFFER \
  CTL_CODE(FILE_DEVICE_MOUSE, 0x0FF1, METHOD_NEITHER, FILE_ANY_ACCESS)

#define I8042_POWER_SYS_BUTTON            0x0001
#define I8042_SLEEP_SYS_BUTTON            0x0002
#define I8042_WAKE_SYS_BUTTON             0x0004
#define I8042_SYS_BUTTONS                 (I8042_POWER_SYS_BUTTON | \
                                           I8042_SLEEP_SYS_BUTTON | \
                                           I8042_WAKE_SYS_BUTTON)

typedef enum _TRANSMIT_STATE {
  Idle = 0,
  SendingBytes
} TRANSMIT_STATE;

typedef struct _OUTPUT_PACKET {
  PUCHAR  Bytes;
  ULONG  CurrentByte;
  ULONG  ByteCount;
  TRANSMIT_STATE  State;
} OUTPUT_PACKET, *POUTPUT_PACKET;

typedef enum _KEYBOARD_SCAN_STATE {
  Normal,
  GotE0,
  GotE1
} KEYBOARD_SCAN_STATE, *PKEYBOARD_SCAN_STATE;

typedef enum _MOUSE_STATE {
  MouseIdle,
  XMovement,
  YMovement,
  ZMovement,
  MouseExpectingACK,
  MouseResetting
} MOUSE_STATE, *PMOUSE_STATE;

typedef enum _MOUSE_RESET_SUBSTATE {
	ExpectingReset,
	ExpectingResetId,
	ExpectingGetDeviceIdACK,
	ExpectingGetDeviceIdValue,
	ExpectingSetResolutionDefaultACK,
	ExpectingSetResolutionDefaultValueACK,
	ExpectingSetResolutionACK,
	ExpectingSetResolutionValueACK,
	ExpectingSetScaling1to1ACK,
	ExpectingSetScaling1to1ACK2,
	ExpectingSetScaling1to1ACK3,
	ExpectingReadMouseStatusACK,
	ExpectingReadMouseStatusByte1,
	ExpectingReadMouseStatusByte2,
	ExpectingReadMouseStatusByte3,
	StartPnPIdDetection,
	ExpectingLoopSetSamplingRateACK,
	ExpectingLoopSetSamplingRateValueACK,
	ExpectingPnpIdByte1,
	ExpectingPnpIdByte2,
	ExpectingPnpIdByte3,
	ExpectingPnpIdByte4,
	ExpectingPnpIdByte5,
	ExpectingPnpIdByte6,
	ExpectingPnpIdByte7,
	EnableWheel,
	Enable5Buttons,
	ExpectingGetDeviceId2ACK,
	ExpectingGetDeviceId2Value,
	ExpectingSetSamplingRateACK,
	ExpectingSetSamplingRateValueACK,
	ExpectingEnableACK,
	ExpectingFinalResolutionACK,
	ExpectingFinalResolutionValueACK,
	ExpectingGetDeviceIdDetectACK,
	ExpectingGetDeviceIdDetectValue,
	CustomHookStateMinimum = 100,
	CustomHookStateMaximum = 999,
	I8042ReservedMinimum = 1000
} MOUSE_RESET_SUBSTATE, *PMOUSE_RESET_SUBSTATE;

typedef struct _INTERNAL_I8042_START_INFORMATION {
  ULONG  Size;
  PKINTERRUPT  InterruptObject;
  ULONG  Reserved[8];
} INTERNAL_I8042_START_INFORMATION, *PINTERNAL_I8042_START_INFORMATION;

typedef VOID DDKAPI
(*PI8042_ISR_WRITE_PORT)(
  /*IN*/ PVOID  Context,
  /*IN*/ UCHAR  Value);

typedef VOID DDKAPI
(*PI8042_QUEUE_PACKET)(
  /*IN*/ PVOID  Context);

typedef NTSTATUS DDKAPI
(*PI8042_SYNCH_READ_PORT) (
  /*IN*/ PVOID  Context,
  /*OUT*/ PUCHAR  Value,
  /*IN*/ BOOLEAN  WaitForACK);

typedef NTSTATUS DDKAPI
(*PI8042_SYNCH_WRITE_PORT)(
  /*IN*/ PVOID  Context,
  /*IN*/ UCHAR  Value,
  /*IN*/ BOOLEAN  WaitForACK);


typedef NTSTATUS DDKAPI
(*PI8042_KEYBOARD_INITIALIZATION_ROUTINE)(
  /*IN*/ PVOID  InitializationContext,
  /*IN*/ PVOID  SynchFuncContext,
  /*IN*/ PI8042_SYNCH_READ_PORT  ReadPort,
  /*IN*/ PI8042_SYNCH_WRITE_PORT  WritePort,
  /*OUT*/ PBOOLEAN  TurnTranslationOn);

typedef BOOLEAN DDKAPI
(*PI8042_KEYBOARD_ISR)(
  PVOID  IsrContext,
  PKEYBOARD_INPUT_DATA  CurrentInput,
  POUTPUT_PACKET  CurrentOutput,
  UCHAR  StatusByte,
  PUCHAR  Byte,
  PBOOLEAN  ContinueProcessing,
  PKEYBOARD_SCAN_STATE  ScanState);

typedef struct _INTERNAL_I8042_HOOK_KEYBOARD {
  /*OUT*/ PVOID  Context;
  /*OUT*/ PI8042_KEYBOARD_INITIALIZATION_ROUTINE  InitializationRoutine;
  /*OUT*/ PI8042_KEYBOARD_ISR  IsrRoutine;
  /*IN*/ PI8042_ISR_WRITE_PORT  IsrWritePort;
  /*IN*/ PI8042_QUEUE_PACKET  QueueKeyboardPacket;
  /*IN*/ PVOID  CallContext;
} INTERNAL_I8042_HOOK_KEYBOARD, *PINTERNAL_I8042_HOOK_KEYBOARD;

typedef BOOLEAN DDKAPI
(*PI8042_MOUSE_ISR)(
  PVOID  IsrContext,
  PMOUSE_INPUT_DATA  CurrentInput,
  POUTPUT_PACKET  CurrentOutput,
  UCHAR  StatusByte,
  PUCHAR  Byte,
  PBOOLEAN  ContinueProcessing,
  PMOUSE_STATE  MouseState,
  PMOUSE_RESET_SUBSTATE  ResetSubState);

typedef struct _INTERNAL_I8042_HOOK_MOUSE {
  /*OUT*/ PVOID  Context;
  /*OUT*/ PI8042_MOUSE_ISR  IsrRoutine;
  /*IN*/ PI8042_ISR_WRITE_PORT  IsrWritePort;
  /*IN*/ PI8042_QUEUE_PACKET  QueueMousePacket;
  /*IN*/ PVOID  CallContext;
} INTERNAL_I8042_HOOK_MOUSE, *PINTERNAL_I8042_HOOK_MOUSE;

#ifdef __cplusplus
}
#endif

#endif /* __NTDD8042_H */
