//---------------------------------------------------------------------------

#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <Dialogs.hpp>                        
#include "ezusbsys.h"
#include <Menus.hpp>
#include <Buttons.hpp>
#include <ComCtrls.hpp>

//Global defs
#define MAX_IOCTL_BUFF 512
#define MAX_FILE_SIZE (1024*8)
#define MAX_EP0_XFER_SIZE (1024*4)  // 4K Control EP0 transfer limit imposed by OS
#define MAX_ISO_SIZE (256*256*16)   // 1 Meg Iso buffer

#define MAX_DRIVER_NAME 64
#define DEVICE_DESCRIPTOR_SIZE 32 /* bigger than we need */
#define MAX_ITEMS_IN_LB 1024
#define MAX_BUFFER_SIZE 512
#define MAX_PIPES 30
#define MAX_USB_DEV_NUMBER 32
#define GET_CONFIG_DESCRIPTOR_LENGTH(pv) \
    ((pUsb_Configuration_Descriptor)pv)->wTotalLength

#define GET_STRING_DESCRIPTOR_LENGTH(pv) \
    ((pUsb_String_Descriptor)pv)->bLength

#define IDS_USB_OPS_UNARY "Get Dev Desc\nGet Config Desc\nGet Pipe Info\n"
#define IDS_USB_OPS_VEN "Vendor Request\n"
#define IDS_USB_OPS_BULK "Bulk Byte Transfer\nBulk File Transfer\n"
#define IDS_USB_OPS_ANCHOR "Anchor Download\n"
#define IDS_USB_OPS_RES "Reset Pipe\nAbort Pipe\n"
#define IDS_USB_OPS_ISO "ISO Transfer\n"
//#define IDS_USB_OPS_SET "Set Interface\nSet Dev Desc\nSet Config Desc\nSet Config\nClear Feature\nSync Frame\n"
#define IDS_USB_OPS_SET "Set Interface\n"
//#define IDS_USB_PIPE_TYPE "Reset Pipe\nAbort Pipe\n"
//#define IDS_USB_IOCTL_TYPE "Get Dev Desc\nGet Config Desc\nGet Pipe Info\nReset Port\nVendor Request\nRead Bulk\nWrite Bulk\nWrite File\nRead File\nAnchor Download\nReset, Abort Pipe\nISO Transfer\nSet Interface\nReset Hold\nReset Release\n"
#define IDS_USB_EE_RAW     "FF FF FF FF FF FF FF"
#define IDS_USB_EE_DEV     "B0 47 05 80 00 01 00"
#define IDS_USB_EE_EZLINK  "B0 47 05 10 27 01 00"
#define IDS_USB_EE_EXAMPLE "B0 47 05 02 10 01 00"
                                                                         

#define MAX_INTEL_HEX_RECORD_LENGTH 4096
typedef struct _INTEL_HEX_RECORD
{
   //BYTE  Length;
   WORD  Length;
   WORD  Address;
   BYTE  Type;
   BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;

#define TGT_IMG_SIZE 0x10000 //64KB (65,536 Byte) target image
#define TGT_SEG_SIZE 16		//16 byte segments

struct MemSeg
{
	DWORD TAddr; //Target Address
	DWORD HAddr; //Host Address
	DWORD Size;  //block size
	DWORD Stat;  //status
	PCHAR pData; //data bytes
};

struct TMemImg
{
	CHAR data[TGT_IMG_SIZE]; //target image store
};

struct TMemCache
{
	TMemImg* pImg;	//pointer to image
	int nSeg;		//segment count
	MemSeg pSeg[TGT_IMG_SIZE/TGT_SEG_SIZE]; //info about segments
};

void ParseDeviceDescriptor(PVOID pvBuffer);
void ParseConfigurationDescriptor(PVOID pvBuffer);
void DumpBuffer(PVOID pvBuffer, ULONG length);
void ParseStringDescriptor(PVOID pvBuffer);
void DumpBuffer(PVOID pvBuffer, ULONG length);

typedef struct __usb_Dev_Descriptor__ {
    UCHAR bLength;
    UCHAR bDescriptorType;
    USHORT bcdUSB;
    UCHAR bDeviceClass;
    UCHAR bDeviceSubClass;
    UCHAR bDeviceProtocol;
    UCHAR bMaxPacketSize0;
    USHORT idVendor;
    USHORT idProduct;
    USHORT bcdDevice;
    UCHAR iManufacturer;
    UCHAR iProduct;
    UCHAR iSerialNumber;
    UCHAR bNumConfigurations;
} Usb_Device_Descriptor, *pUsb_Device_Descriptor;

typedef struct __usb_Config_Descriptor__ {
    UCHAR bLength;
    UCHAR bDescriptorType;
    USHORT wTotalLength;
    UCHAR bNumInterfaces;
    UCHAR bConfigurationValue;
    UCHAR iConfiguration;
    UCHAR bmAttributes;
    UCHAR MaxPower;
} Usb_Configuration_Descriptor, *pUsb_Configuration_Descriptor;

typedef struct _USB_INTERFACE_DESCRIPTOR {
    UCHAR bLength;
    UCHAR bDescriptorType;
    UCHAR bInterfaceNumber;
    UCHAR bAlternateSetting;
    UCHAR bNumEndpoints;
    UCHAR bInterfaceClass;
    UCHAR bInterfaceSubClass;
    UCHAR bInterfaceProtocol;
    UCHAR iInterface;
} Usb_Interface_Descriptor, *pUsb_Interface_Descriptor;

typedef struct _USB_ENDPOINT_DESCRIPTOR {
    UCHAR bLength;
    UCHAR bDescriptorType;
    UCHAR bEndpointAddress;
    UCHAR bmAttributes;
    USHORT wMaxPacketSize;
    UCHAR bInterval;
} Usb_Endpoint_Descriptor, *pUsb_Endpoint_Descriptor;

typedef struct __usb_String_Descriptor__ { //TPM added the usb_String_Descriptor
    UCHAR bLength;
    UCHAR bDescriptorType;
    WCHAR bString[1];
} Usb_String_Descriptor, *pUsb_String_Descriptor;

BOOLEAN
bOpenDriver (HANDLE * phDeviceHandle, PCHAR devname);

typedef PVOID USBD_PIPE_HANDLE;
typedef PVOID USBD_CONFIGURATION_HANDLE;
typedef PVOID USBD_INTERFACE_HANDLE;

typedef enum _USBD_PIPE_TYPE {
    UsbdPipeTypeControl,
    UsbdPipeTypeIsochronous,
    UsbdPipeTypeBulk,
    UsbdPipeTypeInterrupt
} USBD_PIPE_TYPE;


typedef struct _USBD_PIPE_INFORMATION {
    //
    // OUTPUT
    // These fields are filled in by USBD
    //
    USHORT MaximumPacketSize;  // Maximum packet size for this pipe
    UCHAR EndpointAddress;     // 8 bit USB endpoint address (includes direction)
                               // taken from endpoint descriptor
    UCHAR Interval;            // Polling interval in ms if interrupt pipe

    USBD_PIPE_TYPE PipeType;   // PipeType identifies type of transfer valid for this pipe
    USBD_PIPE_HANDLE PipeHandle;

    //
    // INPUT
    // These fields are filled in by the client driver
    //
    ULONG MaximumTransferSize; // Maximum size for a single request
                               // in bytes.
    ULONG PipeFlags;
} USBD_PIPE_INFORMATION, *PUSBD_PIPE_INFORMATION;


typedef struct _USBD_INTERFACE_INFORMATION {
    USHORT Length;       // Length of this structure, including
                         // all pipe information structures that
                         // follow.
    //
    // INPUT
    //
    // Interface number and Alternate setting this
    // structure is associated with
    //
    UCHAR InterfaceNumber;
    UCHAR AlternateSetting;

    //
    // OUTPUT
    // These fields are filled in by USBD
    //
    UCHAR Class;
    UCHAR SubClass;
    UCHAR Protocol;
    UCHAR Reserved;

    USBD_INTERFACE_HANDLE InterfaceHandle;
    ULONG NumberOfPipes;

    //
    // INPUT/OUPUT
    // see PIPE_INFORMATION
    USBD_PIPE_INFORMATION Pipes[0];

} USBD_INTERFACE_INFORMATION, *PUSBD_INTERFACE_INFORMATION;

typedef LONG USBD_STATUS;

typedef struct _USBD_ISO_PACKET_DESCRIPTOR {
    ULONG Offset;       // INPUT Offset of the packet from the begining of the
                        // buffer.

    ULONG Length;       // OUTPUT length of data received (for in).
                        // OUTPUT 0 for OUT.
    USBD_STATUS Status; // status code for this packet.
} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR;

//HANDLE  hDevice;

//---------------------------------------------------------------------------
class TMainForm : public TForm
{
__published:	// IDE-managed Components
   TMemo *Memo;
   TLabel         *Driver_Name;
   TEdit          *DriverName;
   TGroupBox      *Controls;
   TButton        *QuitBtn;
   TBevel         *Bevel1;
   TButton        *HoldBtn;
   TButton        *Get_Device_DescriptorBtn;
   TButton        *Get_Configuration_DescriptorBtn;
   TButton        *Get_Pipe_InfoBtn;
   TButton        *GetStringBtn;
   TShape *RunInd;
   TButton *RunBtn;
   TButton *Load_MonitorBtn;
   TCheckBox *Verbose_Check_Box;
   TButton *Set_Interface_Btn;
   TLabel *IFace;
   TEdit *Interface_Num_Box;
   TLabel *Label5;
   TEdit *Alternate_Setting_Box;
   TButton *FPGA_OUTBtn;
   TButton *Get_FrameBtn;
   TOpenDialog *OpenFileDlg;
   TButton *Code_LoadBtn;
   TButton *FPGATESTBtn;
   TBevel *Bevel2;
   TGroupBox *Vend_Req_Group;
   TLabel *Label1;
   TLabel *Label2;
   TLabel *Label3;
   TLabel *Label4;
   TButton *Vend_ReqBtn;
   TEdit *Vend_Req;
   TEdit *Vend_Req_Value;
   TEdit *Vend_Req_Index;
   TEdit *Vend_Req_Len;
   TMainMenu *MainMenu1;
   TMenuItem *File1;
   TMenuItem *Read_DataDlg;
   TMenuItem *Read_Results_Dlg;
   TMenuItem *GetProtocol1;
   TMenuItem *N1;
   TMenuItem *EXIT1;
   TLabel *Label6;
   TLabel *Label7;
   TButton *GetASCIIBtn;
   TButton *GetBinaryBtn;
   TButton *GetProtocolBtn;
  TButton *SEQ_OUTBtn;
   TBevel *Bevel3;
   TBitBtn *Exe_StartBtn;
   TButton *CLEARBtn;
   TLabel *Label8;
   TUpDown *DAC_SelUpDown;
   TLabel *DACSelect;
   TEdit *DACEd;
   TButton *DAC_SetBtn;
   TLabel *Label9;
   TLabel *FDACSelect;
   TUpDown *FDAC_SelUpDown;
   TEdit *FDACEd;
   TButton *FDAC_SetBtn;
  TButton *FIFO_Read_Btn;
   TButton *DownloadBtn;
   //void __fastcall FormActivate(TObject *Sender);
   void __fastcall QuitBtnClick(TObject *Sender);
   void __fastcall CLEARBtnClick(TObject *Sender);
   void __fastcall HoldBtnClick(TObject *Sender);
   void __fastcall Get_Device_DescriptorBtnClick(TObject *Sender);
   void __fastcall Get_Configuration_DescriptorBtnClick(TObject *Sender);
   void __fastcall Get_Pipe_InfoBtnClick(TObject *Sender);
   void __fastcall GetStringBtnClick(TObject *Sender);
   void __fastcall DownloadBtnClick(TObject *Sender);
   void __fastcall RunBtnClick(TObject *Sender);
   void __fastcall Vend_ReqBtnClick(TObject *Sender);
   void __fastcall Load_MonitorBtnClick(TObject *Sender);
   void __fastcall Verbose_Check_BoxClick(TObject *Sender);
   void __fastcall Set_Interface_BtnClick(TObject *Sender);
   void __fastcall Get_FrameBtnClick(TObject *Sender);
   void __fastcall FPGA_OUTBtnClick(TObject *Sender);
   void __fastcall Code_LoadBtnClick(TObject *Sender);
   void __fastcall StopBtnClick(TObject *Sender);
   void __fastcall FPGATESTBtnClick(TObject *Sender);
   void __fastcall EXIT1Click(TObject *Sender);
   void __fastcall FormActivate(TObject *Sender);
   void __fastcall Read_DataDlg_Click(TObject *Sender);
   void __fastcall Read_Results_DlgClick(TObject *Sender);
   void __fastcall GetProtocol1Click(TObject *Sender);
  void __fastcall SEQ_OUTBtnClick(TObject *Sender);
   void __fastcall Exe_StartBtnClick(TObject *Sender);
   void __fastcall DAC_SelUpDownClick(TObject *Sender, TUDBtnType Button);
   void __fastcall DACEdChange(TObject *Sender);
   void __fastcall DAC_SetBtnClick(TObject *Sender);
   void __fastcall FDAC_SelUpDownClick(TObject *Sender, TUDBtnType Button);
   void __fastcall FDACEdChange(TObject *Sender);
  void __fastcall FIFO_Read_BtnClick(TObject *Sender);
   void __fastcall FDAC_SetBtnClick(TObject *Sender);

private:	// User declarations
   unsigned long    nBytes;
   char     *build_time;
   char     *build_date;
   char     tempbuff[256];
   char     Command[64];
   int      Command_Length, fifo_bytes;
   char     *pcDriverName;
   char*    pVenbuf;
   PVOID    pvBuffer;
   BOOLEAN  bResult, bAutoHoldRun,m_Verbose;
   int      m_DldLen, m_DldOffset;
   unsigned char interfaceNum, alternateSetting;
   void Anchor_Download();
   void Ezusb_DownloadIntelHex(PINTEL_HEX_RECORD pHexRecord);
   BOOLEAN Loading_Monitor, Loading_Code;
   BOOLEAN FirstRead;
   AnsiString m_strPathUSBRoot, m_strMonFileName, m_strCodeFileName, m_strFPGAFileName;
   AnsiString SeqFileName;
   void __fastcall Toggle();
   void __fastcall Send_Dummy();
   void __fastcall SEQ_Load();
   void __fastcall FIFO_Read_First();

public:		// User declarations
   void __fastcall SetFGain(int d1, int d2);
   TMemCache   m_MemCache;	   //target mem cache info
	TMemImg     m_MemImg;		//target memory image
   int         m_nTarg;
  __fastcall TMainForm(TComponent* Owner);
   char  BlkBuf[MAX_FILE_SIZE];
	char  VenBuf[MAX_FILE_SIZE];
	char  TstBuf[MAX_FILE_SIZE];
	char  IsoBuf[MAX_ISO_SIZE];
   //char  Command[16];
   void Send_Command(void);
   char *Target_Response();
   BOOLEAN  EXE_ON;
   void __fastcall EXE_Start();
   int   DAC[8];
   int   FDAC[4];
   unsigned short DACselect, FDACselect;
   HANDLE  hDevice;
   char* PIPE_TYPE_STRINGS[4];
   char* PIPE_DIRECTION[2];

   TMemoryManager* mmOld;
   Cardinal bytes;





};
//---------------------------------------------------------------------------
extern PACKAGE TMainForm *MainForm;
//---------------------------------------------------------------------------
#endif
