// ConsolePIC.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//

#include "stdafx.h"
#include "windows.h"
#include "mpusbapi.h"

#define MPUSBAPI_VERSION            0x00010000L
#define	MPUSB_DEV_NO_INFO           2
#define	MPUSB_DEV_INVALID_INST      3
#define	MPUSB_DEV_VIDPID_NOT_FOUND  4
#define MPUSB_DEV_NOT_ATTACHED      5
//---------------------------------------------------------------------------

// Global Vars
char vid_pid[]= "vid_04d8&pid_000b";    // Default Demo Application Firmware
char out_pipe[]= "\\MCHP_EP1";
char in_pipe[]= "\\MCHP_EP1";

DWORD temp;

HINSTANCE libHandle;
HANDLE myOutPipe;
HANDLE myInPipe;

//---------------------------------------------------------------------------
// Prototypes
void GetSummary(void);
void LoadDLL(void);
void GetUSBDemoFWVersion(void);
DWORD SendReceivePacket(BYTE *SendData, DWORD SendLength, BYTE *ReceiveData,
                    DWORD *ReceiveLength, UINT SendDelay, UINT ReceiveDelay);
void CheckInvalidHandle(void);

//---------------------------------------------------------------------------


int _tmain(int argc, _TCHAR* argv[])
{
	//***********************************************************************************************
	BOOLEAN bQuit;
    DWORD selection;
    bQuit = false;

    // Load DLL when it is necessary, i.e. on start-up!
    LoadDLL();

    // Always a good idea to initialize the handles
    myOutPipe = myInPipe = INVALID_HANDLE_VALUE;
	

    printf("Microchip Technology Inc., 2004\r\n");
    printf("===============================\r\n");
    while(!bQuit)
    {
        printf("Select an option\r\n");
        printf("[1] Get MPUSBAPI Version\r\n");
        printf("[2] Summarize Instances\r\n");
        printf("[3] Get USB Demo Firmware Version\r\n");
        printf("[4] Quit\r\n>>");
        scanf_s("%d",&selection);

        switch(selection)
        {
            case 1:
                temp = MPUSBGetDLLVersion();
                printf("MPUSBAPI Version: %d.%d\r\n",HIWORD(temp),LOWORD(temp));
                break;
            case 2:
                GetSummary();
                break;
            case 3:
                GetUSBDemoFWVersion();
                break;
            case 4:
                bQuit = true;
                break;
            default:
                break;
        }// end switch

        fflush(stdin);printf("\r\n");
    }//end while

    // Always check to close all handles before exiting!
    if (myOutPipe != INVALID_HANDLE_VALUE) MPUSBClose(myOutPipe);
    if (myInPipe != INVALID_HANDLE_VALUE) MPUSBClose(myInPipe);
    myOutPipe = myInPipe = INVALID_HANDLE_VALUE;

    // Always check to close the library too.
    if (libHandle != NULL) FreeLibrary(libHandle);
//*****************************************************************************************************************


	return 0;
}


//---------------------------------------------------------------------------

void GetSummary(void)
{
    HANDLE tempPipe = INVALID_HANDLE_VALUE;
    DWORD count = 0;
    DWORD max_count;

    max_count = MPUSBGetDeviceCount(vid_pid);

    printf("\r\n%d device(s) with %s currently attached\r\n",max_count,vid_pid);

    // Note:
    // The total number of devices using the generic driver could be
    // bigger than max_count. They could have different vid & pid numbers.
    // This means if max_count is 2, the valid instance index do not
    // necessary have to be '0' and '1'.
    //
    // Below is a sample code for searching for all valid instance indexes.
    // MAX_NUM_MPUSB_DEV is defined in _mpusbapi.h
    count = 0;
    for(int i = 0; i < MAX_NUM_MPUSB_DEV; i++)
    {
        tempPipe = MPUSBOpen(i,vid_pid,NULL,MP_READ,0);
        if(tempPipe != INVALID_HANDLE_VALUE)
        {
			printf("Instance Index # %d	 MPUSBOpen Handel:%d\r\n",i,tempPipe);
            MPUSBClose(tempPipe);
            count++;
        }
        if(count == max_count) break;
    }//end for
    printf("SUB	GetSummary Ende: \r\n");
}//end GetSummary

//---------------------------------------------------------------------------

void LoadDLL(void)
{
    libHandle = NULL;
    libHandle = LoadLibrary(TEXT("mpusbapi"));
    if(libHandle == NULL)
    {
        printf("Error loading mpusbapi.dll\r\n");
    }
    else
    {
        MPUSBGetDLLVersion=(DWORD(*)(void))GetProcAddress(libHandle,"_MPUSBGetDLLVersion");
        MPUSBGetDeviceCount=(DWORD(*)(PCHAR))GetProcAddress(libHandle,"_MPUSBGetDeviceCount");
        MPUSBOpen=(HANDLE(*)(DWORD,PCHAR,PCHAR,DWORD,DWORD))GetProcAddress(libHandle,"_MPUSBOpen");
        MPUSBWrite=(DWORD(*)(HANDLE,PVOID,DWORD,PDWORD,DWORD))GetProcAddress(libHandle,"_MPUSBWrite");
        MPUSBRead=(DWORD(*)(HANDLE,PVOID,DWORD,PDWORD,DWORD))GetProcAddress(libHandle,"_MPUSBRead");
        MPUSBReadInt=(DWORD(*)(HANDLE,PVOID,DWORD,PDWORD,DWORD))GetProcAddress(libHandle,"_MPUSBReadInt");
        MPUSBClose=(BOOL(*)(HANDLE))GetProcAddress(libHandle,"_MPUSBClose");

        if((MPUSBGetDeviceCount == NULL) || (MPUSBOpen == NULL) ||
            (MPUSBWrite == NULL) || (MPUSBRead == NULL) ||
            (MPUSBClose == NULL) || (MPUSBGetDLLVersion == NULL) ||
            (MPUSBReadInt == NULL))
            printf("GetProcAddress Error\r\n");
    }//end if else
}//end LoadDLL

//---------------------------------------------------------------------------

void GetUSBDemoFWVersion(void)
{
    // First we need to open data pipes...
    DWORD selection;
    fflush(stdin);
    printf("Enter a valid instance index to open a USB connection: ");
    scanf_s("%d",&selection);

    //myOutPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0);
	myOutPipe = MPUSBOpen(selection,vid_pid,"\\MCHP_EP1",MP_WRITE,0);
	printf("mmpusbOpen WRITE handel:%d\r\n",myOutPipe);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    myInPipe = MPUSBOpen(selection,vid_pid,out_pipe,MP_READ,0);

	printf("mmpusbOpen READ  handel:%d\r\n",myInPipe);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    if(myOutPipe == INVALID_HANDLE_VALUE || myInPipe == INVALID_HANDLE_VALUE)
    {
        printf("Failed to open data pipes.\r\n");
        return;
    }//end if


    // The default demo firmware application has a defined application
    // level protocol.
    // To read the firmware version, the host must send the READ_VERSION
    // command which is defined as 0x00, follows by the length of the
    // expected result, in this case is 2 bytes, major version, and minor
    // version.
    // i.e. <READ_VERSION><0x02>
    //
    // The response packet from the board has the following format:
    // <READ_VERSION><0x02><MINOR_VER><MAJOR_VER>

    // The receive buffer size must be equal to or larger than the maximum
    // endpoint size it is communicating with. In this case, 64 bytes.

    BYTE send_buf[64],receive_buf[64];
    DWORD RecvLength=8;					// füt test habe ich gemacht<<<<<<<<<<<<<<<<<<<<<<<<<<<
    #define READ_VERSION    0x12		// füt test habe ich gemacht<<<<<<<<<<<<<<<<<<<<<<<<<<<
    //send_buf[0] = READ_VERSION;      // Command
	send_buf[0] = 0x02;      // Command
    send_buf[1] = 0x12;      // Expected length of the result
	send_buf[2] = 0x22;
	send_buf[3] = 0x32;
	send_buf[4] = 0x42;
	send_buf[5] = 0x52;
	send_buf[6] = 0x62;
	send_buf[7] = 0x72;
    if(SendReceivePacket(send_buf,8,receive_buf,&RecvLength,1000,1000) == 1)
    {
       // if(RecvLength == 4 && receive_buf[0] == READ_VERSION && receive_buf[1] == 0x02)
       // {
			printf("\nUSB gesendet  %x-%x-%x-%x-%x-%x-%x-%x\r\n",send_buf[0], send_buf[1],send_buf[2], send_buf[3],send_buf[4]\
				, send_buf[5],send_buf[6], send_buf[7]);// füt test habe ich gemacht<<<<<<<<<<<<<<<<<<<<<<<<<<<
            printf("\nUSB Empfangen  %x-%x-%x-%x-%x-%x-%x-%x\r\n",receive_buf[0], receive_buf[1],receive_buf[2], receive_buf[3]\
				,receive_buf[4], receive_buf[5],receive_buf[6], receive_buf[7]);// füt test habe ich gemacht<<<<<<<<<<<<<<<<<<<<<<<<<<<
       // }
    }
    else
	{
        printf("USB Operation Failed\r\n");
	}

    // Let's close the data pipes since we have nothing left to do..
    MPUSBClose(myOutPipe);
    MPUSBClose(myInPipe);
    myOutPipe = myInPipe = INVALID_HANDLE_VALUE;
    printf("Verlasse GetUSBDemoFWVersion) mit Close() all \r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}//end GetUSBDemoFWVersion
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A typical application would send a command to the target device and expect
// a response.
// SendReceivePacket is a wrapper function that facilitates the
// send command / read response paradigm
//
// SendData - pointer to data to be sent
// SendLength - length of data to be sent
// ReceiveData - Points to the buffer that receives the data read from the call
// ReceiveLength - Points to the number of bytes read
// SendDelay - time-out value for MPUSBWrite operation in milliseconds
// ReceiveDelay - time-out value for MPUSBRead operation in milliseconds
//
DWORD SendReceivePacket(BYTE *SendData, DWORD SendLength, BYTE *ReceiveData,DWORD *ReceiveLength, UINT SendDelay, UINT ReceiveDelay)
{
	printf("## Eintritt in SendReceivePacket()  ##\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    DWORD SentDataLength;
    DWORD ExpectedReceiveLength = *ReceiveLength;

    if(myOutPipe != INVALID_HANDLE_VALUE && myInPipe != INVALID_HANDLE_VALUE)
    {
		printf("## myOutPipe & myInPipe haben Gültige Handel ##\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        if(MPUSBWrite(myOutPipe,SendData,SendLength,&SentDataLength,SendDelay))
        {
			printf("## MPUSBWrite( myOutPipe,SendData,SendLength,&SentDataLength,SendDelay)  war OK ##\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
			
            if(MPUSBRead(myInPipe,ReceiveData, ExpectedReceiveLength, ReceiveLength,ReceiveDelay))
            {
				printf("## MPUSBRead(myInPipe,ReceiveData, ExpectedReceiveLength, ReceiveLength,ReceiveDelay)  war OK ##\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                if(*ReceiveLength == ExpectedReceiveLength)
                {
					printf("Verlasse if(MPUSBRead() mit return 1 Success! \r\n");	//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                    return 1;   // Success!
                }
                else if(*ReceiveLength < ExpectedReceiveLength)
                {
					printf("Verlasse if(MPUSBRead() mit return 2 Partially failed, incorrect receive length! \r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                    return 2;   // Partially failed, incorrect receive length
                }//end if else 
            }
            else
			{
				printf("ELSE :USB Operation MPUSBRead Failed\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                CheckInvalidHandle();
			}		
        }
        else
		{
			printf("ELSE:USB Operation MPUSBWrite Failed\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            CheckInvalidHandle();
		}
    }//end if
	else	
	{ 
		printf("myOutPipe:%d und myInPipe:%d handel error:\r\n",myOutPipe,myInPipe); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	}
	printf("Verlasse SendReceivePacket() mit return 0 \r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	return 0;  // Operation Failed
}//end SendReceivePacket

//---------------------------------------------------------------------------

void CheckInvalidHandle(void)
{
	printf("## Eintritt in CheckInvalidHandle() ##\r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    if(GetLastError() == ERROR_INVALID_HANDLE)
    {
        // Most likely cause of the error is the board was disconnected.
        MPUSBClose(myOutPipe);
        MPUSBClose(myInPipe);
        myOutPipe = myInPipe = INVALID_HANDLE_VALUE;
		printf("if(GetLastError()=ERROR_INVALID_HANDLE) Close(all) \r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    }//end if
    else
	{
        printf("Error Code :\r\n",GetLastError());//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	}
	printf("Verlasse CheckInvalidHandle() \r\n");//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}//end CheckInvalidHandle

//---------------------------------------------------------------------------
/*
///////////////////////////////////////////////////////////////////////////////
//	MPUSBRead :
//
//  handle  - Identifies the endpoint pipe to be read. The pipe handle must
//            have been created with MP_READ access attribute.
//
//  pData   - Points to the buffer that receives the data read from the pipe.
//
//  dwLen   - Specifies the number of bytes to be read from the pipe.
//
//  pLength - Points to the number of bytes read. MPUSBRead sets this value to
//            zero before doing any work or error checking.
//
//  dwMilliseconds
//          - Specifies the time-out interval, in milliseconds. The function
//            returns if the interval elapses, even if the operation is
//            incomplete. If dwMilliseconds is zero, the function tests the
//            data pipe and returns immediately. If dwMilliseconds is INFINITE,
//            the function's time-out interval never elapses.
//
//	Note that "input" and "output" refer to the parameter designations in calls
//	to this function, which are the opposite of common sense from the
//	perspective of an application making the calls.
//
DWORD MPUSBRead(HANDLE handle,          // Input
                PVOID pData,            // Output
                DWORD dwLen,            // Input
                PDWORD pLength,         // Output
                DWORD dwMilliseconds)   // Input
///////////////////////////////////////////////////////////////////////////////
//	MPUSBWrite :
//
//  handle  - Identifies the endpoint pipe to be written to. The pipe handle
//            must have been created with MP_WRITE access attribute.
//
//  pData   - Points to the buffer containing the data to be written to the pipe.
//
//  dwLen   - Specifies the number of bytes to write to the pipe.
//
//  pLength - Points to the number of bytes written by this function call.
//            MPUSBWrite sets this value to zero before doing any work or
//            error checking.
//
//  dwMilliseconds
//          - Specifies the time-out interval, in milliseconds. The function
//            returns if the interval elapses, even if the operation is
//            incomplete. If dwMilliseconds is zero, the function tests the
//            data pipe and returns immediately. If dwMilliseconds is INFINITE,
//            the function's time-out interval never elapses.
//
//	Note that "input" and "output" refer to the parameter designations in calls
//	to this function, which are the opposite of common sense from the
//	perspective of an application making the calls.
//
DWORD MPUSBWrite(HANDLE handle,         // Input
                 PVOID pData,           // Input
                 DWORD dwLen,           // Input
                 PDWORD pLength,        // Output
                 DWORD dwMilliseconds)  // Input
 ///////////////////////////////////////////////////////////////////////////////
//	MPUSBReadInt :
//
//  handle  - Identifies the endpoint pipe to be read. The pipe handle must
//            have been created with MP_READ access attribute.
//
//  pData   - Points to the buffer that receives the data read from the pipe.
//
//  dwLen   - Specifies the number of bytes to be read from the pipe.
//
//  pLength - Points to the number of bytes read. MPUSBRead sets this value to
//            zero before doing any work or error checking.
//
//  dwMilliseconds
//          - Specifies the time-out interval, in milliseconds. The function
//            returns if the interval elapses, even if the operation is
//            incomplete. If dwMilliseconds is zero, the function tests the
//            data pipe and returns immediately. If dwMilliseconds is INFINITE,
//            the function's time-out interval never elapses.
//
//	Note that "input" and "output" refer to the parameter designations in calls
//	to this function, which are the opposite of common sense from the
//	perspective of an application making the calls.
//
DWORD MPUSBReadInt(HANDLE handle,       // Input
                   PVOID pData,         // Output
                   DWORD dwLen,         // Input
                   PDWORD pLength,      // Output
                   DWORD dwMilliseconds)// Input
///////////////////////////////////////////////////////////////////////////////
//	MPUSBOpen : Returns the handle to the endpoint pipe with matching VID & PID
//
//  All pipes are opened with the FILE_FLAG_OVERLAPPED attribute.
//  This allows MPUSBRead,MPUSBWrite, and MPUSBReadInt to have a time-out value.
//
//  Note: Time-out value has no meaning for Isochronous pipes.
//
//  instance - An instance number of the device to open.
//             Typical usage is to call MPUSBGetDeviceCount first to find out
//             how many instances there are.
//             It is important to understand that the driver is shared among
//             different devices. The number of devices returned by
//             MPUSBGetDeviceCount could be equal to or less than the number
//             of all the devices that are currently connected & using the
//             generic driver.
//
//             Example:
//             if there are 3 device with the following PID&VID connected:
//             Device Instance 0, VID 0x04d8, PID 0x0001
//             Device Instance 1, VID 0x04d8, PID 0x0002
//             Device Instance 2, VID 0x04d8, PID 0x0001
//
//             If the device of interest has VID = 0x04d8 and PID = 0x0002
//             Then MPUSBGetDeviceCount will only return '1'.
//             The calling function should have a mechanism that attempts
//             to call MPUSBOpen up to the absolute maximum of MAX_NUM_MPUSB_DEV
//             (MAX_NUM_MPUSB_DEV is defined in _mpusbapi.h).
//             It should also keep track of the number of successful calls
//             to MPUSBOpen(). Once the number of successes equals the
//             number returned by MPUSBGetDeviceCount, the attempts should
//             be aborted because there will no more devices with
//             a matching vid&pid left.
//
//  pVID_PID - A string containing the PID&VID value of the target device.
//             The format is "vid_xxxx&pid_yyyy". Where xxxx is the VID value
//             in hex and yyyy is the PID value in hex.
//             Example: If a device has the VID value of 0x04d8 and PID value
//                      of 0x000b, then the input string should be:
//                      "vid_04d8&pid_000b"
//
//  pEP      - A string of the endpoint number on the target endpoint to open.
//             The format is "\\MCHP_EPz". Where z is the endpoint number in
//             decimal.
//             Example: "\\MCHP_EP1"
//
//             This arguement can be NULL. A NULL value should be used to
//             create a handles for non-specific endpoint functions.
//             MPUSBRead, MPUSBWrite, MPUSBReadInt are endpoint specific
//             functions.
//             All others are not.
//             Non-specific endpoint functions will become available in the
//             next release of the DLL.
//
//             Note: To use MPUSBReadInt(), the format of pEP has to be
//                   "\\MCHP_EPz_ASYNC". This option is only available for
//                   an IN interrupt endpoint. A data pipe opened with the
//                   "_ASYNC" keyword would buffer the data at the interval
//                   specified in the endpoint descriptor upto the maximum of
//                   100 data sets. Any data received after the driver buffer
//                   is full will be ignored.
//                   The user application should call MPUSBReadInt() often
//                   enough so that the maximum limit of 100 is never reached.
//
//  dwDir    - Specifies the direction of the endpoint.
//             Use MP_READ for MPUSBRead, MPSUBReadInt
//             Use MP_WRITE for MPUSBWrite
//
//  dwReserved Future Use
//
//  Summary of transfer type usage:
//  ============================================================================
//  Transfer Type       Functions                       Time-Out Applicable?
//  ============================================================================
//  Interrupt - IN      MPUSBRead, MPUSBReadInt         Yes
//  Interrupt - OUT     MPUSBWrite                      Yes
//  Bulk - IN           MPUSBRead                       Yes
//  Bulk - OUT          MPUSBWrite                      Yes
//  Isochronous - IN    MPUSBRead                       No
//  Isochronous - OUT   MPUSBWrite                      No
//  ============================================================================
//
//	Note that "input" and "output" refer to the parameter designations in calls
//	to this function, which are the opposite of common sense from the
//	perspective of an application making the calls.
//
HANDLE MPUSBOpen(DWORD instance,    // Input
                 PCHAR pVID_PID,    // Input
                 PCHAR pEP,         // Input
                 DWORD dwDir,       // Input
                 DWORD dwReserved)  // Input <Future Use>

///////////////////////////////////////////////////////////////////////////////
//	MPUSBGetDLLVersion : get mpusbapi.dll revision level
//
//	Input:
//		None
//	Output:
//		32-bit revision level MMMMmmmm
//

///////////////////////////////////////////////////////////////////////////////
//	MPUSBGetDeviceCount : Returns the number of devices with matching VID & PID
//
//	Note that "input" and "output" refer to the parameter designations in calls
//	to this function, which are the opposite of common sense from the
//	perspective of an application making the calls.
//
DWORD MPUSBGetDeviceCount(PCHAR pVID_PID)

///////////////////////////////////////////////////////////////////////////////
//	MPUSBClose : closes a given handle.
//
//	Note that "input" and "output" refer to the parameter designations in calls
//	to this function, which are the opposite of common sense from the
//	perspective of an application making the calls.
//
BOOL MPUSBClose(HANDLE handle)
*/