#include <ntifs.h>
#include <ntddk.h>

#include <wdm.h>
#include <usbdrivr.h>
#include <HIDPORT.H>

#include "buildnumber.h"
#include "RBC9-Report.h"
#include "RBC9-Profil.h"
#include "RBC9-Device.h"
#include "RBC9-Registre.h"

#define PAGEDCODE code_seg("PAGE")
#define LOCKEDCODE code_seg()

#define RBC9_COMPLETE_REQUEST(irp, info, status, pri) \
  (irp)->IoStatus.Information = (info); \
  (irp)->IoStatus.Status = (status); \
  IoCompleteRequest((irp), (pri));

#define DBG_OUT(_x_)						\
    KdPrint(_x_);								\
  KdPrint(("\n"));

#define DBG_INFO(_x_)						\
    KdPrint(_x_);							

#define DBG_ENTER(_x_)						\
  KdPrint(("> Enter: %s: ", __FUNCTION__));   \
   KdPrint(_x_);								\
  KdPrint(("\n"));

#define DBG_LEAVE(_x_)						\
  KdPrint(("> Leave: %s: ", __FUNCTION__));   \
  KdPrint(_x_);								\
  KdPrint(("\n"));



NTSTATUS RBC9_DispatchCreateClose(
	IN PDEVICE_OBJECT		DeviceObject,
	IN PIRP					Irp
	);

VOID RBC9_DriverUnload(
	IN PDRIVER_OBJECT		DriverObject 
	);

NTSTATUS RBC9_AddDevice(
	IN PDRIVER_OBJECT DriverObject,
	IN PDEVICE_OBJECT func_dev_obj
	);

NTSTATUS RBC9_DispatchPnp(
	IN PDEVICE_OBJECT		dev_obj,
	IN PIRP irp
	);

NTSTATUS RBC9_DispatchPower(
	IN PDEVICE_OBJECT pDev_obj, 
	IN PIRP pIrp
	);

NTSTATUS RBC9_DispatchIntDevice(
	IN PDEVICE_OBJECT pDev_obj,
	IN PIRP pIrp
	);

NTSTATUS RBC9_DispatchDevice(
	IN PDEVICE_OBJECT pFdo, 
	IN PIRP pIrp
	);

NTSTATUS RBC9_DispatchSystem(
	IN PDEVICE_OBJECT pFdo, 
	IN PIRP pIrp
	);

NTSTATUS RBC9_IncRequestCount(
	IN PDEVICE_EXTENSION pDevExt
	);

VOID RBC9_DecRequestCount(
	IN PDEVICE_EXTENSION pDevExt
	);


// RBC9-Pnp.c

NTSTATUS RBC9_pnp_complete(
	IN PDEVICE_OBJECT pDev_obj, 
	IN PIRP pIrp,
	IN PVOID ctxt);

NTSTATUS RBC9_pnp_start(
	IN PDEVICE_OBJECT pDev_obj,
	IN PIRP pIrp
	);

NTSTATUS RBC9_device_start(
	IN PDEVICE_OBJECT pDev_obj
	);

NTSTATUS RBC9_pnp_stop(
	IN PDEVICE_OBJECT pDev_obj,
	IN PIRP pIrp
	);

NTSTATUS RBC9_pnp_surprise_remove(
	IN PDEVICE_OBJECT pDev_obj,
	IN PIRP pIrp
	);

NTSTATUS RBC9_pnp_remove(
	IN PDEVICE_OBJECT pDev_obj,
	IN PIRP pIrp
	);

NTSTATUS RBC9_device_remove(
	IN PDEVICE_OBJECT pDev_obj
	);

NTSTATUS RBC9_pnp_capabilities(
	IN PDEVICE_OBJECT pDev_obj,
	IN PIRP pIrp
	);

// RBC9-IOCTL.c

NTSTATUS RBC9_ioctl_get_dev_desc(
	IN PDEVICE_OBJECT pDev_obj,	
	IN PIRP pIrp
	);

NTSTATUS RBC9_ioctl_get_dev_attr(
	IN PDEVICE_OBJECT pDev_obj,	
	IN PIRP pIrp
	);

NTSTATUS RBC9_ioctl_get_rep_desc(
	IN PDEVICE_OBJECT pDev_obj,	
	IN PIRP pIrp
	);

NTSTATUS RBC9_ioctl_read_rep(
	IN PDEVICE_OBJECT pDev_obj,	
	IN PIRP pIrp
	);

NTSTATUS RBC9_ioctl_write_rep(
	IN PDEVICE_OBJECT pDev_obj,	
	IN PIRP pIrp
	);

VOID RBC9_notify_input_report_change(
	IN PDEVICE_OBJECT pDev_obj
	);

VOID RBC9_notify_input_report_stop(
	IN PDEVICE_OBJECT pDev_obj
	);

// RBC9-USB.c

NTSTATUS RBC9_usb_start(
	IN PDEVICE_OBJECT pDev_obj
	);

NTSTATUS RBC9_usb_remove(
	IN PDEVICE_OBJECT pDev_obj
	);

static NTSTATUS RBC9_usb_reset(
	IN PDEVICE_OBJECT Dev_obj);

static NTSTATUS RBC9_usb_get_port_status(
	IN PDEVICE_OBJECT pDev_obj,
	OUT ULONG *port_status
	);

static NTSTATUS RBC9_usb_call(
	IN PDEVICE_OBJECT pDev_obj, 
	IN ULONG ioctl_code,
    IN PVOID arg1,
	IN PVOID arg2
	);

static NTSTATUS RBC9_usb_reset_port(
	IN PDEVICE_OBJECT pDev_obj
	);

static NTSTATUS RBC9_usb_get_dev_desc(
	IN PDEVICE_OBJECT pDev_obj
	);

static NTSTATUS RBC9_usb_select_conf(
	IN PDEVICE_OBJECT pDev_obj
	);

static NTSTATUS RBC9_usb_get_conf_desc(
	IN PDEVICE_OBJECT pDev_obj,
    OUT PUSB_CONFIGURATION_DESCRIPTOR *conf_desc,
    OUT ULONG *size,
    IN UCHAR conf_idx);


static NTSTATUS RBC9_usb_get_hid_desc(
	IN PDEVICE_OBJECT pDev_obj
	);


static VOID RBC9_usb_worker(
	IN PVOID ctxt);

NTSTATUS RBC9_usb_get_interrupt_transfer(
	IN PDEVICE_OBJECT pDev_obj, 
	IN PVOID buf, 
	ULONG *buf_size);

NTSTATUS RBC9_usb_put_interrupt_transfer(
	IN PDEVICE_OBJECT pDev_obj, 
	IN PVOID buf, 
	ULONG *buf_size);

NTSTATUS RBC9_usb_put_control_transfer(
	IN PDEVICE_OBJECT pDev_obj, 
	IN PVOID buf, 
	ULONG *buf_size,
	IN PVOID packet
	);
NTSTATUS RBC9_usb_get_control_transfer(
	IN PDEVICE_OBJECT pDev_obj, 
	IN PVOID buf, 
	ULONG *buf_size,
	IN PVOID packet
	);

static NTSTATUS RBC9_usb_interrupt_transfer(
	IN PDEVICE_OBJECT pDev_obj,
    IN PVOID buf, 
	ULONG *buf_size,
    USBD_PIPE_HANDLE pipe, 
	ULONG flags);

static NTSTATUS RBC9_usb_control_transfer(
	IN PDEVICE_OBJECT pDev_obj,
    IN PVOID buf, 
	ULONG *buf_size,
    USBD_PIPE_HANDLE pipe, 
	ULONG flags,
	IN PVOID packet);

// RBC9-Hid.c

NTSTATUS RBC9_hid_start(
	IN PDEVICE_OBJECT pDev_obj);

NTSTATUS RBC9_hid_remove(
	IN PDEVICE_OBJECT pDev_obj
	);

NTSTATUS RBC9_hid_get_rep_desc(
	IN PDEVICE_OBJECT pDev_obj, 
	OUT UCHAR *buf, 
	OUT ULONG *size);

NTSTATUS RBC9_hid_read_rep(
	IN PDEVICE_OBJECT pDev_obj, 
	OUT UCHAR *buf, 
	OUT ULONG *size);

NTSTATUS RBC9_hid_write_rep(
	IN PDEVICE_OBJECT pDev_obj,
	IN UCHAR *buf, 
	IN ULONG *size, 
	IN UCHAR id);

static VOID RBC9_hid_worker(
	IN PVOID ctxt
	);

static VOID RBC9_hid_generate_raw_output(
	PCONTROLLER_OUTPUT_REPORT out_state,
	PRAW_OUTPUT raw_out
	);

NTSTATUS RBC9_nav_led(
	IN PDEVICE_OBJECT pDev_obj,
	BOOLEAN Led
	);

NTSTATUS RBC9_nav_calibrate(
	IN PDEVICE_OBJECT pDev_obj
	);


NTSTATUS RBC9_nav_init(
	IN PDEVICE_OBJECT pDev_obj
	);



// RBC9-Profil.c

void RBC9_Wait(
	short MilliSec);

VOID RBC9_InitState(
	IN PDEVICE_OBJECT pDev_obj);

VOID RBC9_process_raw_input(
	IN PDEVICE_OBJECT pDev_obj
	);


VOID RBC9_Delete_Profil(
	IN PDEVICE_OBJECT pDev_obj
	);

PPROFIL RBC9_Select_Profil(
	IN PDEVICE_OBJECT pDev_obj,
	short Profil_Id
	);

BOOLEAN RBC9_Profil_Exist(
	IN PDEVICE_OBJECT pDev_obj,
	short Profil_Id
	);

VOID RBC9_Clear_KeyB_Buffer(
	IN PDEVICE_OBJECT pDev_obj,
	BOOLEAN ClearKeep
	);

// RBC9-Led.c

VOID RBC9_Led_Queue_Add(IN PDEVICE_OBJECT pDev_obj,int HowLong,int TimeOn,int TimeOff);
VOID RBC9_Led_Queue_Delete(IN PDEVICE_OBJECT pDev_obj);
VOID RBC9_Led_Clignote(IN PDEVICE_OBJECT pDev_obj);

VOID RBC9_SEQ_Change_Profil(IN PDEVICE_OBJECT pDev_obj);
VOID RBC9_SEQ_Init_HID(IN PDEVICE_OBJECT pDev_obj);
VOID RBC9_SEQ_Special_Action(IN PDEVICE_OBJECT pDev_obj);
VOID RBC9_SEQ_Special_Action_Fin(IN PDEVICE_OBJECT pDev_obj);

