// 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.
//#include "bsp.h"// lqm test.
//#include "ioctl_cfg.h"

#include <windows.h>
#include <nled.h>
#include <led_drvr.h>
#include <types.h>
#include <bsp.h>
#include <drvmsg.h>
#include <drvlib_mem.h>
#include <ceddk.h>


volatile static GPIO_REG* v_pGPIOregs = NULL;

#define NUM_OF_LEDS 4
#define IOCTL_LED_ADJUST	CTL_CODE(FILE_DEVICE_UNKNOWN, 2057, METHOD_BUFFERED, FILE_ANY_ACCESS)	// lqm added for LED adjust.10-07-27

#define LED_OFF			0
#define LED_ON			1
#define LED_BLINK		2

#define LED1                GPH13_Output            // LED1
#define LED2                GPH14_Output            // LED2
#define LED3                GPH16_Output            // LED3
#define LED4                GPH17_Output            // LED4

//added by terry 20111018
#define WIFI_PWR_EN 	GPH26_Output
#define WIFI_PD		 	GPH27_Output

DWORD g_LEDPort[NUM_OF_LEDS] = {LED1, LED2,LED3, LED4};

#define TEST_LED 1

void HW_WIFI_Init(void)
{
	Set_PinFunction(v_pGPIOregs, WIFI_PWR_EN);
	Set_PinFunction(v_pGPIOregs, WIFI_PD);
}

void HW_WIFI_PWR_EN(BOOL on)
{
	if(TRUE==on)
	{			
		RETAILMSG(1, (_T("[LED]  HW_WIFI_PWR_EN.........................\r\n")));
		Set_PinData(v_pGPIOregs, WIFI_PWR_EN, 1);
	}
	else
	{
		Set_PinData(v_pGPIOregs, WIFI_PWR_EN, 0);
	}

}

void HW_WIFI_PD(BOOL on)
{
	if(TRUE==on)
	{			
		RETAILMSG(1, (_T("[LED]  HW_WIFI_PD 1.........................\r\n")));	
		Set_PinData(v_pGPIOregs, WIFI_PD, 1);
	}
	else
	{
		Set_PinData(v_pGPIOregs, WIFI_PD, 0);
	}

}



// 配置GPM[0:3]为output.
void LED_ConfigGPIO()
{
	//g_pGPIOReg->GPMCON = g_pGPIOReg->GPMCON & (~0xffff<<0) | (0x1111<<0);
	//g_pGPIOReg->GPMPUD &=(~0xff<<0);
}



BOOL HW_LED_INIT(DWORD dwID)
{
	BOOL bReturn = TRUE;
	
//	LEDMSG(LED_FUNC, (TEXT("+%s\r\n"), _T(__FUNCTION__)));

	if(dwID >= NUM_OF_LEDS)
	{
//		LEDERR(TRUE, (TEXT("LED%d is not available.\r\n"), dwID));
		bReturn = FALSE;
	}
	else
	{
		switch(dwID)
		{
			case 0:
			case 1:
			case 2:
			case 3:
				Set_PinFunction(v_pGPIOregs, g_LEDPort[dwID]);
			//	Set_PinPullUD(v_pGPIOregs, g_LEDPort[dwID], sgip_PULL_DISABLE);
				break;

			default:
				break;
		}
	}
	
//	LEDMSG(LED_FUNC, (TEXT("-%s\r\n"), _T(__FUNCTION__)));

	return bReturn;
}




BOOL HW_LED_ON(DWORD dwID)
{
	BOOL bReturn = TRUE;
	
//	LEDMSG(LED_FUNC, (TEXT("+%s\r\n"), _T(__FUNCTION__)));

	if(dwID >= NUM_OF_LEDS)
	{
//		LEDERR(TRUE, (TEXT("LED%d is not available.\r\n"), dwID));
		bReturn = FALSE;
	}
	else
	{
		switch(dwID)
		{
			case 0:
			case 1:
			case 2:
			case 3:				
				Set_PinData(v_pGPIOregs, g_LEDPort[dwID], 1);
				break;

			default:
				break;
		}

//		g_LEDStatus[dwID] = LED_ON;
	}
	
//	LEDMSG(LED_FUNC, (TEXT("-%s\r\n"), _T(__FUNCTION__)));

	return bReturn;
}




BOOL HW_LED_OFF(DWORD dwID)
{
	BOOL bReturn = TRUE;
	
	//LEDMSG(LED_FUNC, (TEXT("+%s\r\n"), _T(__FUNCTION__)));

	if(dwID >= NUM_OF_LEDS)
	{
//		LEDERR(TRUE, (TEXT("LED%d is not available.\r\n"), dwID));
		bReturn = FALSE;
	}
	else
	{
		switch(dwID)
		{
			case 0:
			case 1:
			case 2:
			case 3:				
				Set_PinData(v_pGPIOregs, g_LEDPort[dwID], 0);
				break;

			default:
				break;
		}

//		g_LEDStatus[dwID] = LED_OFF;
	}
	
//	LEDMSG(LED_FUNC, (TEXT("-%s\r\n"), _T(__FUNCTION__)));

	return bReturn;
}

// ARMEasy6410 LED硬件接口:
// GPM0,GPM1,GPM2,GPM3.
void SetLED(DWORD code)
{
	switch(code)
	{
		case 0x0:
			
			HW_LED_OFF(0);
			HW_LED_OFF(1);
			HW_LED_OFF(2);
			HW_LED_OFF(3);
			break;//全灭
		case 0x1:
		case 0x2:
		case 0x4:
		case 0x5:
		case 0x8:
		case 0xa:
		case 0xf:
			HW_LED_ON(0);
			HW_LED_ON(1);
			HW_LED_ON(2);
			HW_LED_ON(3);
			break;//全亮
			
		default:
			break;
	}

	
}

static BOOL LED_AllocResources(void)
{

	BOOL bReturn = TRUE;

	// GPIO initialization
	v_pGPIOregs = (GPIO_REG*)DrvLib_MapIoSpace(BASE_REG_PA_GPIO, sizeof(GPIO_REG), FALSE);
	if (v_pGPIOregs == NULL)
	{
//		LEDERR(TRUE, (_T("Failed to allocate the v_pGPIOregs.\r\n")));
		bReturn = FALSE;
	}
	
	return bReturn;
	
	
}

static void
LED_ReleaseResources(void)
{
	RETAILMSG(0, (_T("[LED] ++%s()\r\n"), _T(__FUNCTION__)));
	if (v_pGPIOregs != NULL)
	{
		DrvLib_UnmapIoSpace((PVOID)v_pGPIOregs);
		v_pGPIOregs = NULL;
	}
}

BOOL DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
{
	if (dwReason == DLL_PROCESS_ATTACH)
	{
		DEBUGREGISTER(hinstDll);
		DEBUGMSG(1, (_T("[LED] %s() : Process Attach\r\n"), _T(__FUNCTION__)));
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		DEBUGMSG(1, (_T("[LED] %s() : Process Detach\r\n"), _T(__FUNCTION__)));
	}

	return TRUE;
}

DWORD LED_Init(DWORD dwContext)
{
	int i;
HANDLE SDIOInsertedEvent=NULL;

	RETAILMSG(1, (_T("[LED] ++%s(0x%08x)\r\n"), _T(__FUNCTION__), dwContext));
	if (LED_AllocResources() == FALSE)
	{
		RETAILMSG(1,(_T("[LED:ERR] %s() : LED_AllocResources() Failed \n\r"), _T(__FUNCTION__)));
		LED_ReleaseResources();
		return FALSE;
	}
	
	//LED_ConfigGPIO();
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_INIT(i);
		HW_LED_OFF(i);
	}
	


#if  TEST_LED	
	RETAILMSG(1, (_T("[LED]  test LED ...............................\r\n")));
	Sleep(1000);
	
	//LED_ConfigGPIO();
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_ON(i);	
	}
	
	Sleep(1000);
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_OFF(i);
	}
	Sleep(1000);
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_ON(i);	
	}
	Sleep(1000);
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_OFF(i);
	}
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_ON(i);	
	}
	Sleep(1000);
	for(i=0; i<NUM_OF_LEDS;i++)
	{
		HW_LED_OFF(i);
	}
	
#endif	

//added by terry for test SDIO_WIFI 20111017

#if 0
	//added by terry for SDIO wifi 20111022
	SDIOInsertedEvent = CreateEvent (NULL, FALSE, FALSE, (LPCTSTR)(L"SDIOInsertedEvent"));
	if(NULL ==SDIOInsertedEvent)
	{
	      RETAILMSG(1, (_T("[LED]  CreateEvent SDIOInsertedEvent  failied! ...............................\r\n")));
	}
	
	RETAILMSG(1, (_T("[LED]  WIFI Power on...............................\r\n")));
	HW_WIFI_Init();
	HW_WIFI_PWR_EN(1);
	HW_WIFI_PD(0);
	Sleep(10);
	HW_WIFI_PD(1);
	SetEvent(SDIOInsertedEvent) ;
	//added by terry for SDIO wifi 20111022 END
#endif
	
	return TRUE;
}

BOOL LED_Deinit(DWORD pContext)
{
    RETAILMSG(0, (_T("[LED] ++%s(0x%08x)\r\n"), _T(__FUNCTION__), pContext));
    LED_ReleaseResources();
    return TRUE;
}


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

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

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

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

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

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


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

BOOL
LED_IOControl(DWORD pContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
	DWORD temp;
    RETAILMSG(0, (_T("[LED] %s(0x%08x, 0x%08x)\r\n"), _T(__FUNCTION__), pContext, dwCode));
	switch(dwCode)
	{
		case IOCTL_LED_ADJUST:
			temp = *(DWORD *)pBufIn;
			RETAILMSG(0,(TEXT("[LED] code:0x%x\n"),temp));
			SetLED(temp);
			break;

		default:
			break;
	}
    return TRUE;
}

