#include "list.h"

#define MODNAME "baycomusb"
#define MODSTR MODNAME" "__FILE__": "
#define VERSTR "0.09"

#undef CONNECTEVENT
#define EVENTNAME L"\\BaseNamedObjects\\baycomusbconnevent"

enum { _removed, _remove_pending, _stopped, _stop_pending, _started } dabusb_device_state;

typedef struct 
{
	// physical device object
	PDEVICE_OBJECT pdo;        
	// Device object we call when submitting Urbs/Irps to the USB stack
	PDEVICE_OBJECT sdo;
	// set when PendingIoCount goes to 0; flags device can be removed
	KEVENT RemoveEvent;
	// set when PendingIoCount goes to 1 ( 1st increment was on add device )
	// this indicates no IO requests outstanding, either user, system, or otherwise
	KEVENT NoPendingIoEvent;
	KEVENT release_ok;
	// incremented when device is added and any IO request is received;
	// decremented when any io request is completed or passed on, and when device is removed
	LONG pending_io_count;
	// 0 = removed, 1 = removing, 2 = loaded/stopped, 3 = started
	ULONG device_state;
        // DosDevice Name
	UNICODE_STRING deviceLinkUnicodeString;
	// open counter
	KSEMAPHORE open_sem;

	/*
	 * power stuff
	 */

        // power management
        DEVICE_POWER_STATE CurrentDevicePowerState;
 
        //Bus drivers set the appropriate values in this structure in response
        //to an IRP_MN_QUERY_CAPABILITIES IRP. Function and filter drivers might
        //alter the capabilities set by the bus driver.
	DEVICE_CAPABILITIES DeviceCapabilities;
 
        // used to save the currently-being-handled system-requested power irp request
	PIRP PowerIrp;
 
        // set to signal driver-generated power request is finished
	KEVENT SelfRequestedPowerIrpEvent;

	// flag set when IRP_MN_WAIT_WAKE is received and we're in a power state
	// where we can signal a wait
	BOOLEAN EnabledForWakeup;
	
        // used to flag that we're currently handling a self-generated power request
	BOOLEAN SelfPowerIrp;
 
        // default power state to power down to on self-suspend
        ULONG PowerDownLevel;

        LONG opened;

        /* last USB error */
        ULONG lastusberror;
        
        /* Pointer to pipe handles for ep->pipeh mapping */
        void *eptopipeh[32];
        unsigned int epmaxpkt[16]; /* we only need output maxpkt sizes */
        
        /* configuration number */
        unsigned int cfgindex;

	/* List of pending completion structs to cancel */
	struct list_head cancel_list;
	KSPIN_LOCK cancel_list_lock;

} dabusb_t, *pdabusb_t;


#define KERN_EMERG      "<0>"   /* system is unusable                   */
#define KERN_ALERT      "<1>"   /* action must be taken immediately     */
#define KERN_CRIT       "<2>"   /* critical conditions                  */
#define KERN_ERR        "<3>"   /* error conditions                     */
#define KERN_WARNING    "<4>"   /* warning conditions                   */
#define KERN_NOTICE     "<5>"   /* normal but significant condition     */
#define KERN_INFO       "<6>"   /* informational                        */
#define KERN_DEBUG      "<7>"   /* debug-level messages                 */

#define printk DbgPrint
#define kmalloc(size) ExAllocatePool(NonPagedPool,size)
#define kfree ExFreePool
#define mdelay(x) udelay(1000*(x))

#define b(x) printk(MODSTR "breakpoint: %d",x); DbgBreakPoint()

// --------------- power.c ---------------
NTSTATUS dabusb_dispatch_power( IN PDEVICE_OBJECT fdo, IN PIRP Irp);

// --------------- bcioctl.c -------------
NTSTATUS baycomusb_ioctl(IN PDEVICE_OBJECT fdo, IN PIRP irp);
NTSTATUS baycomusb_internal_ioctl(IN PDEVICE_OBJECT fdo, IN PIRP irp);

VOID dabusb_increment_io_count( IN PDEVICE_OBJECT fdo);
LONG dabusb_decrement_io_count( IN PDEVICE_OBJECT fdo);

NTSTATUS OnRequestComplete(IN PDEVICE_OBJECT fdo, IN PIRP irp, IN PKEVENT pev );

NTSTATUS async_cancel_all(PDEVICE_OBJECT fdo);
NTSTATUS abort_pipes(PDEVICE_OBJECT fdo);

int usb_control_msg(PDEVICE_OBJECT fdo, unsigned char requesttype, unsigned char request,
                    unsigned short value, unsigned short index, unsigned short length, void *data, unsigned int timeout);
int usb_bulk_msg(PDEVICE_OBJECT fdo, unsigned int ep, unsigned int dlen, void *data, unsigned int timeout);
int usb_resetep(PDEVICE_OBJECT fdo, unsigned int ep);
int usb_setconfiguration(PDEVICE_OBJECT fdo, unsigned int configuration);
int usb_setinterface(PDEVICE_OBJECT fdo, unsigned int intf, unsigned int altsetting);

NTSTATUS dabusb_SelfSuspendOrActivate(IN PDEVICE_OBJECT fdo, IN BOOLEAN fSuspend);
NTSTATUS dabusb_QueryCapabilities(IN PDEVICE_OBJECT Lowerfdo, IN PDEVICE_CAPABILITIES DeviceCapabilities);
