/*	
 *	app.h
 *
 *	PceCom - P/ECE USBシリアルポートデバイスドライバ
 *	Copyright (C) 2005 Naoyuki Sawa
 *
 *	* Sat Jul 23 17:10:00 JST 2005 Naoyuki Sawa
 *	- 1st リリース。
 */
#ifndef __APP_H__
#define __APP_H__

#include "clipwdm.h"

/****************************************************************************
 *
 ****************************************************************************/

///* {C338FFCC-63F5-4445-92C6-5DCE96065258} */
//DEFINE_GUID(PCECOM_GUID,0xC338FFCC,0x63F5,0x4445,0x92,0xC6,0x5D,0xCE,0x96,0x06,0x52,0x58);
//→デバイスインターフェイスでなく、明示的なデバイス名とシンボリックリンクを使っているので、
//  デバイスインターフェイスのためのGUIDは、現在のところ必要ありません。

typedef struct _IOCTL {
	SERIAL_QUEUE_SIZE queue_size;
	SERIAL_STATUS comm_status;
	int modem_status;
	int dtr_rts;
	SERIAL_LINE_CONTROL line_control;
	SERIAL_BAUD_RATE baud_rate;
	SERIAL_HANDFLOW handflow;
	SERIAL_TIMEOUTS timeouts;
	SERIAL_CHARS chars;
	int wait_mask;
	//
	IRP* wait_on_mask_irp;
} IOCTL;

typedef struct _RDWR {
	KEVENT terminate_event;
	PKTHREAD polling_thread;
	//
	int read_length;
	int read_capacity;
	unsigned char* read_buffer/*[read_capacity]*/;
	LIST_ENTRY read_irp_list;
	KEVENT read_start_event;
	KEVENT read_pulse_event;
	PKTHREAD read_thread;
	IRP* read_current_irp;
	//
	int write_length;
	int write_capacity;
	unsigned char* write_buffer/*[write_capacity]*/;
	LIST_ENTRY write_irp_list;
	KEVENT write_start_event;
	KEVENT write_pulse_event;
	PKTHREAD write_thread;
	IRP* write_current_irp;
} RDWR;

typedef struct _DEVICE_EXTENSION {
	DEVICE_OBJECT* device_object;
	DEVICE_OBJECT* next_device_object;
	DEVICE_OBJECT* physical_device_object;
	//
	IO_REMOVE_LOCK remove_lock;
	//
	UNICODE_STRING device_name;		/* デバイス名 ("\Device\PceCom#") */
	WCHAR _device_name[64];
	UNICODE_STRING port_name;		/* ポート名 ("COM#") */
	WCHAR _port_name[64];
	UNICODE_STRING symbolic_link_name;	/* シンボリックリンク名 ("\??\COM#") */
	WCHAR _symbolic_link_name[64];
	//
	USBD_PIPE_INFORMATION read_pipe;
	USBD_PIPE_INFORMATION write_pipe;
	//
	IOCTL ioctl;
	RDWR rdwr;
} DEVICE_EXTENSION;

/****************************************************************************
 *
 ****************************************************************************/

/* * キャンセルスピンロックを、本来のキャンセルスピンロックとしてだけでなく、
 *   デバイスドライバ全体の共通スピンロックとして利用することにします。
 * - 複数のスピンロックを使うことによるデッドロックを避け、実装を簡単にするための暫定措置です。
 *   本当は、無用な性能低下を防ぐために、複数のスピンロックを用意するべきです。
 */
#define ENTER_CS	{ KIRQL __irql__; IoAcquireCancelSpinLock(&__irql__);
#define LEAVE_CS	                  IoReleaseCancelSpinLock( __irql__); }

/* main.c */
void driver_unload(DRIVER_OBJECT* driver_object);
NTSTATUS add_device(DRIVER_OBJECT* driver_object, DEVICE_OBJECT* physical_device_object);
NTSTATUS dispatch_pnp(DEVICE_OBJECT* device_object, IRP* irp);
NTSTATUS dispatch_create(DEVICE_OBJECT* device_object, IRP* irp);
NTSTATUS dispatch_close(DEVICE_OBJECT* device_object, IRP* irp);
NTSTATUS dispatch_power(DEVICE_OBJECT* device_object, IRP* irp);
void delete_device(DEVICE_OBJECT* device_object);
NTSTATUS register_serialcomm(DEVICE_OBJECT* device_object);
void unregister_serialcomm(DEVICE_OBJECT* device_object);
NTSTATUS select_configuration(DEVICE_OBJECT* device_object);
void deselect_configuration(DEVICE_OBJECT* device_object);
void cancel_all_irps(DEVICE_OBJECT* device_object);

/* rdwr.c */
NTSTATUS init_rdwr(DEVICE_OBJECT* device_object);
void exit_rdwr(DEVICE_OBJECT* device_object);
NTSTATUS dispatch_read(DEVICE_OBJECT* device_object, IRP* irp);
NTSTATUS dispatch_write(DEVICE_OBJECT* device_object, IRP* irp);
void abort_read(DEVICE_OBJECT* device_object);
void abort_write(DEVICE_OBJECT* device_object);

/* ioctl.c */
NTSTATUS init_ioctl(DEVICE_OBJECT* device_object);
void exit_ioctl(DEVICE_OBJECT* device_object);
NTSTATUS dispatch_ioctl(DEVICE_OBJECT* device_object, IRP* irp);
void complete_wait_on_mask(IRP* irp, int wait_mask);

#endif /*__APP_H__*/

