//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// Copyright (c) Samsung Electronics. Co. LTD. All rights reserved.

/*++

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:

   LED.c   LED Driver

Abstract:

Functions:



Notes:

--*/

#include <windows.h>
#include <ledtest.h>
//#include <types.h>
#include <bsp.h>
#include <drvmsg.h>
#include <drvlib_mem.h>



#define LED_MASK        (0xf)
#define LED1_ON			(1<<0)													// LED1 ON
#define LED1_OFF		(0<<0)														// LED1 OFF
#define LED2_ON			(1<<1)	
#define LED2_OFF		(0<<1)
#define LED3_ON			(1<<2)
#define LED3_OFF		(0<<2)
#define LED4_ON			(1<<3)
#define LED4_OFF		(0<<3)

static volatile GPIO_REG *g_pGPIOreg = NULL;


/**
*    @fn    AllocResource(void)
*    @note  This function maps System Controller Register Block to virtual address space.
*/
static BOOL
AllocResources(void)
{
    PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};
    DBGMSG(LED_FUNC, (TEXT("[LED] ++%s\n"), _T(__FUNCTION__)));

    // GPIO Virtual alloc
    g_pGPIOreg = (GPIO_REG *)DrvLib_MapIoSpace(BASE_REG_PA_GPIO, sizeof(GPIO_REG), FALSE);
    if (g_pGPIOreg == NULL)
    {
        DBGMSG(LED_INFO,(TEXT("[LED:ERR] %s->g_pCMUCLKRegs MmMapIoSpace() Failed \n"), _T(__FUNCTION__)));
        return FALSE;
    }

#if 0           // gpio x210
	//init GPIO
	Set_PinFunction(g_pGPIOreg, GPH13_Output);  // led 1
	Set_PinFunction(g_pGPIOreg, GPH14_Output);	// led 2
	Set_PinFunction(g_pGPIOreg, GPH16_Output);  // led 3
	Set_PinFunction(g_pGPIOreg, GPH17_Output);  // led 4

	// OFF
	Set_PinData(g_pGPIOreg, GPH13_Output, 1);
	Set_PinData(g_pGPIOreg, GPH14_Output, 1);
	Set_PinData(g_pGPIOreg, GPH16_Output, 1);
	Set_PinData(g_pGPIOreg, GPH17_Output, 1);

	Sleep(3000);
	// ON
	Set_PinData(g_pGPIOreg, GPH13_Output, 0);
	Set_PinData(g_pGPIOreg, GPH14_Output, 0);
	Set_PinData(g_pGPIOreg, GPH16_Output, 0);
	Set_PinData(g_pGPIOreg, GPH17_Output, 0);


#else   // x210-ii

	//init GPIO
	Set_PinFunction(g_pGPIOreg, GPJ03_Output);
	Set_PinFunction(g_pGPIOreg, GPJ04_Output);
	Set_PinFunction(g_pGPIOreg, GPJ05_Output);
	Set_PinFunction(g_pGPIOreg, GPD01_Output);

	// ON
	Set_PinData(g_pGPIOreg, GPJ03_Output, 0);
	Set_PinData(g_pGPIOreg, GPJ04_Output, 0);
	Set_PinData(g_pGPIOreg, GPJ05_Output, 0);
	Set_PinData(g_pGPIOreg, GPD01_Output, 0);

	Sleep(500);
	// OFF
	Set_PinData(g_pGPIOreg, GPJ03_Output, 1);
	Set_PinData(g_pGPIOreg, GPJ04_Output, 1);
	Set_PinData(g_pGPIOreg, GPJ05_Output, 1);
	Set_PinData(g_pGPIOreg, GPD01_Output, 1);



#endif

    DBGMSG(LED_FUNC, (TEXT("[LED] --%s\n"), _T(__FUNCTION__)));

    return TRUE;
}

/**
*    @fn    ReleaseResource(void)
*    @note  This function unmaps System Controller Register Block' virtual address space.
*/
static void
ReleaseResources(void)
{
    DBGMSG(LED_FUNC, (TEXT("[LED] ++%s\n"), _T(__FUNCTION__)));

    if (g_pGPIOreg != NULL)
    {
        DrvLib_UnmapIoSpace((PVOID)g_pGPIOreg);
        g_pGPIOreg = NULL;
    }

    DBGMSG(LED_FUNC, (TEXT("[LED] --%s\n"), _T(__FUNCTION__)));
}


BOOL
DllEntry(
    HINSTANCE   hinstDll,             /*@parm Instance pointer. */
    DWORD   	dwReason,                 /*@parm Reason routine is called. */
    LPVOID  	lpReserved                /*@parm system parameter. */
    )
{

    if (dwReason == DLL_PROCESS_ATTACH)
    {
      ///  DEBUGREGISTER(hinstDll);
      //  DisableThreadLibraryCalls ((HMODULE)hinstDll);
        DBGMSG(LED_FUNC,(TEXT("[LED] %s : Process Attach\n"), _T(__FUNCTION__)));
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        DBGMSG(LED_FUNC,(TEXT("[LED] %s : Process Detach\n"), _T(__FUNCTION__)));
    }

    return TRUE;
}

BOOL LED_Deinit(PDWORD pContext)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] ++%s(0x%08x)\n"), _T(__FUNCTION__), pContext));


    ReleaseResources();

    LocalFree(pContext);

    DBGMSG(LED_FUNC,(TEXT("[LED] --%s\n"), _T(__FUNCTION__) ));

    return TRUE;
}

DWORD
LED_Init(DWORD dwContext)
{
    DBGMSG(LED_FUNC,(TEXT("[LED:INF] ++%s(0x%08x)\n"), _T(__FUNCTION__), dwContext));

    if (AllocResources() == FALSE)
    {
        DBGMSG(LED_INFO,(TEXT("[LED:ERR] %s->AllocResources() Failed \n"), _T(__FUNCTION__)));
        goto CleanUp;
    }

    DBGMSG(LED_FUNC,(TEXT("[LED:INF] --%s()\n"), _T(__FUNCTION__)));

    return TRUE;

CleanUp:

    DBGMSG(LED_INFO,(TEXT("[LED:ERR] --%s : Failed\n"), _T(__FUNCTION__)));

    LED_Deinit(0);

    return FALSE;
}

DWORD
LED_Open(DWORD pContext, DWORD dwAccess, DWORD dwShareMode)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x, 0x%08x, 0x%08x)\n"), _T(__FUNCTION__), pContext, dwAccess, dwShareMode));
    return TRUE;
}

BOOL
LED_Close(DWORD pContext)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x)\n"), _T(__FUNCTION__), pContext));
    return TRUE;
}

DWORD
LED_Read (DWORD pContext,  LPVOID pBuf, DWORD Len)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x, 0x%08x, 0x%08x)\n"), _T(__FUNCTION__), pContext, pBuf, Len));
    return (0);    // End of File
}

DWORD
LED_Write(DWORD pContext, LPCVOID pBuf, DWORD Len)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x, 0x%08x, 0x%08x)\n"), _T(__FUNCTION__), pContext, pBuf, Len));
    return (0);    // Number of Byte
}

DWORD
LED_Seek (DWORD pContext, long pos, DWORD type)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x, 0x%08x, 0x%08x)\n"), _T(__FUNCTION__), pContext, pos, type));
    return (DWORD)-1;    // Failure
}

BOOL
LED_PowerUp(DWORD pContext)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x)\n"), _T(__FUNCTION__), pContext));
    return TRUE;
}

BOOL
LED_PowerDown(DWORD pContext)
{
    DBGMSG(LED_FUNC,(TEXT("[LED] %s(0x%08x)\n"), _T(__FUNCTION__), pContext));
    return TRUE;
}

BOOL
LED_IOControl(DWORD pContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{

	BOOL bRet = TRUE;

    DWORD dwIndex;

    if ( !( (dwCode == IOCTL_LED_SET_ON)))

    {
        DBGMSG(LED_INFO,(TEXT("[LED:ERR] %s : Unknown IOCTL [0x%08x]\n"), _T(__FUNCTION__), dwCode));
        SetLastError (ERROR_INVALID_ACCESS);
        return FALSE;
    }

    switch(dwCode)
    {
    case IOCTL_LED_SET_ON:
        if ((dwLenIn < sizeof(DWORD)) || (NULL == pBufIn))
        {
            DBGMSG(LED_INFO,(TEXT("[LED:ERR] %s(IOCTL_LED_SET_POWER_ON) : Invalid Parameter\n"),_T(__FUNCTION__)));
            SetLastError (ERROR_INVALID_PARAMETER);
            bRet = FALSE;
            break;
        }

        dwIndex = (DWORD)(*pBufIn);

		dwIndex = dwIndex & LED_MASK; 

		if(LED1_ON&dwIndex)
		{
			Set_PinData(g_pGPIOreg, GPJ03_Output, 0);  //LED 1
		}
		else
		{
			Set_PinData(g_pGPIOreg, GPJ03_Output, 1);  //LED 1
		}

		if(LED2_ON&dwIndex)
		{	Set_PinData(g_pGPIOreg, GPJ04_Output, 0);  //LED 2
		}
		else
		{
			Set_PinData(g_pGPIOreg, GPJ04_Output, 1);  //LED 2
		}

		if(LED3_ON&dwIndex)
		{	Set_PinData(g_pGPIOreg, GPJ05_Output, 0);  //LED 3
		}
		else
		{	Set_PinData(g_pGPIOreg, GPJ05_Output, 1);  //LED 3
		}


		if(LED4_ON&dwIndex)
		{	Set_PinData(g_pGPIOreg, GPD01_Output, 0);  // LED 4
		}
		else
		{	Set_PinData(g_pGPIOreg, GPD01_Output, 1);  //LED 4
		}


#if 0

        switch(dwIndex)
        {
	
        case 1:    // LED ON

			// ON
			Set_PinData(g_pGPIOreg, GPJ03_Output, 0);  //LED 1
			Set_PinData(g_pGPIOreg, GPJ04_Output, 0);  //LED 2
			Set_PinData(g_pGPIOreg, GPJ05_Output, 0);  //LED 3
			Set_PinData(g_pGPIOreg, GPD01_Output, 0);  // LED 4
			break;
 	    case 2:    // LED Off
        case 3:		//

			// X210-II
			// OFF
			Set_PinData(g_pGPIOreg, GPJ03_Output, 1);
			Set_PinData(g_pGPIOreg, GPJ04_Output, 1);
			Set_PinData(g_pGPIOreg, GPJ05_Output, 1);
			Set_PinData(g_pGPIOreg, GPD01_Output, 1);
            break;
		
        default:
            DBGMSG(LED_INFO,(TEXT("[LED:ERR] %s(IOCTL_LED_SET_POWER_ON, %d) : Invalid Parameter\n"), _T(__FUNCTION__), dwIndex));
            SetLastError (ERROR_INVALID_PARAMETER);
            bRet = FALSE;
        }

#endif	


        break;
	default:
		DBGMSG(LED_INFO,(TEXT("[LED:ERR] %s(IOCTL_LED_SET_POWER_ON, %d) : Invalid Parameter\n"), _T(__FUNCTION__), dwIndex));
		SetLastError (ERROR_INVALID_PARAMETER);
		bRet = FALSE;



    }

    return bRet;
}

// EOF
