#include <stdlib.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <types.h>
#include "umf_miracast.h"
#include "gl_task.h"
#include "mid_dtv_display.h"
#include "wfd_core.h"
#include "drv_audio_interface.h"

static MIRACAST_ModCbk_pf g_pfMIRACASTCallback = NULL;
pthread_t nMiracastThread;
static MIRACAST_InitExitStatus_e bMiracastInitFinish = MIRACAST_FINISH;
static MIRACAST_InitExitStatus_e bMiracastExitFinish = MIRACAST_FINISH;

#ifdef CONFIG_SUPPORT_MULTI_DONGLE
static Dongle_e Dongle_Select = Dongle_None;
#endif
//==================================================================
static void MiracastDriverThread()
{
	Miracast_Info_t g_MiracastInfo;
#ifdef CONFIG_SUPPORT_MULTI_DONGLE
	g_MiracastInfo.eDongle = Dongle_Select;
	g_MiracastInfo.P2PName = g_DongleMap[Dongle_Select].P2PName;
#else
	g_MiracastInfo.eDongle = WIFI_DONGLE;
	g_MiracastInfo.P2PName = g_DongleMap[WIFI_DONGLE].P2PName;
#endif
	g_MiracastInfo.Dev_Name = MIRACASE_DEV_NAME;
	g_MiracastInfo.bHDCP = MIRACASE_SUPPORT_HDCP;
	
	prctl(PR_SET_NAME , "MiracastDriverThread", NULL, NULL, NULL);
	Miracast_Startup(g_pfMIRACASTCallback,&g_MiracastInfo);
}

INT32 MiracastInit(void)
{
	printf("[Miracast]  MiracastInit ------->\n");
	UINT32 u32PanelWidth = 0;
	UINT32 u32PanelHeight = 0;
	bMiracastInitFinish = MIRACAST_InProcessing;
	if(nMiracastThread == 0)
	{
		MID_DISP_DTVGetPanelResolution(&u32PanelWidth,&u32PanelHeight);
		if(u32PanelHeight > 500)
			WFD_Set_Video_Format(0x0001DEFF, 0x07FFFFFF, 0x00000FFF);
		else
			WFD_Set_Video_Format(0x00008C7F, 0x003c3FFF, 0x00000FFF);
		if (CONFIG_AUDIO_FEATURE & AUDIO_FEATURE_AAC)
			WFD_Set_Audio_Format(3);//1:AAC 2:PCM 3:AAC&PCM
		else
			WFD_Set_Audio_Format(2);//1:AAC 2:PCM 3:AAC&PCM

#ifdef CONFIG_SUPPORT_MULTI_DONGLE
		Dongle_Select = MID_NWSI_WLAN_GetWifiDongle();
		if(Dongle_Select != Dongle_None)
#endif
		{
			pthread_create(&nMiracastThread, NULL, (void *)MiracastDriverThread, NULL);
		}
	}
	else
		printf("[Miracast] waring: re-init without pthread_join!!\n");
	
	bMiracastInitFinish = MIRACAST_FINISH;
	printf("[Miracast]  <--------MiracastInit \n");
	return 0;
}

INT32 MiracastExit(void)
{
	printf("[Miracast] MiracastExit ---------->\n");
	bMiracastExitFinish = MIRACAST_InProcessing;
	if(nMiracastThread)
	{
		printf("[CC DBG]  do thread_join!!!! \n");
		Miracast_Exit();
		pthread_join(nMiracastThread, NULL);
		nMiracastThread = 0;
	}
	bMiracastExitFinish = MIRACAST_FINISH;
	printf("[Miracast] <---------- MiracastExit \n");
	return 0;
}

void miracast_Init(MIRACAST_ModualCfg_t *pMIRACAST_ModualCfg)
{
	char cmd[100] = {0};
#ifdef CONFIG_SUPPORT_MULTI_DONGLE
	Dongle_Select = MID_NWSI_WLAN_CheckWifiDongle();
#endif

	if ((pMIRACAST_ModualCfg != NULL) && (pMIRACAST_ModualCfg->pfCallBack != NULL))
	{
		g_pfMIRACASTCallback = pMIRACAST_ModualCfg->pfCallBack;
	}
#if 0
	system("echo 1000000 > /proc/sys/net/core/rmem_default");
	system("echo 1000000 > /proc/sys/net/core/rmem_max");
	system("echo 100000  > /proc/sys/net/core/netdev_max_backlog");
	system("echo 20480 > /proc/sys/net/core/optmem_max");		
	
	system("echo 8388608 > /proc/sys/net/core/rmem_default");
	system("echo 8388608 > /proc/sys/net/core/rmem_max");
	system("echo 5000  > /proc/sys/net/core/netdev_max_backlog");
	system("echo 1  > /proc/sys/net/ipv4/tcp_tw_reuse");
	system("echo 16384   > /proc/sys/net/ipv4/udp_rmem_min");

#else
	system("echo 2097152 > /proc/sys/net/core/rmem_default");
	system("echo 2097152 > /proc/sys/net/core/rmem_max");
	system("echo 163840 > /proc/sys/net/core/wmem_default");
	system("echo 1048576 > /proc/sys/net/core/wmem_max");
	system("echo 10240 > /proc/sys/net/core/optmem_max");
	system("echo 1000 > /proc/sys/net/core/netdev_max_backlog");
	system("echo 524288 1048576 2097152 > /proc/sys/net/ipv4/tcp_rmem");
	system("echo 4096 16384 1950592 > /proc/sys/net/ipv4/tcp_wmem");
	//system("echo 524288 1048576 2097152 > /proc/sys/net/ipv4/tcp_wmem");
	
	system("echo 300 > /proc/sys/net/core/netdev_budget");
	system("echo 128 > /proc/sys/net/ipv4/tcp_max_syn_backlog");
	system("echo 512 > /proc/sys/net/ipv4/tcp_max_tw_buckets");
	system("echo 0 > /proc/sys/net/ipv4/tcp_tw_reuse");
	system("echo 10 > /proc/sys/net/ipv4/tcp_fin_timeout");
	system("echo 1 > /proc/sys/net/ipv4/tcp_slow_start_after_idle");
	system("echo 4096 > /proc/sys/net/ipv4/udp_rmem_min");
	system("echo 4096 > /proc/sys/net/ipv4/udp_wmem_min");
	system("echo 0 > /proc/sys/net/ipv4/tcp_low_latency");
	system("echo 300 > /proc/sys/net/unix/max_dgram_qlen");
	system("echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle");
	system("echo 3145728 > /proc/sys/net/ipv4/ipfrag_low_thresh");
	system("echo 4194304 > /proc/sys/net/ipv4/ipfrag_high_thresh");
	//system("echo 512 > /proc/sys/net/ipv4/tcp_max_orphans");


	system("echo 10 > /proc/sys/net/ipv4/tcp_fin_timeout");
	system("echo 10 > /proc/sys/net/ipv4/tcp_retries1");
	system("echo 15 > /proc/sys/net/ipv4/tcp_syn_retries");
	system("echo 25 > /proc/sys/net/ipv4/tcp_retries2");
	system("echo 8192 > /proc/sys/net/ipv4/tcp_max_orphans");

#endif
	//system("echo 32 > /proc/sys/net/core/dev_weight");	
	//system("echo 542720 > /proc/sys/net/core/wmem_default");
	//system("echo 1000000 > /proc/sys/net/core/wmem_max");
	//system("echo 2000  > /proc/sys/net/core/netdev_budget");
	//system("echo 262144   > /proc/sys/net/ipv4/udp_rmem_min");
	//system("echo 0  >/proc/sys/net/ipv4/tcp_timestamps");
#ifdef CONFIG_SUPPORT_MULTI_DONGLE
	if(Dongle_Select != Dongle_None)
	{
		if(Dongle_Select == Dongle_AIC_8800)
		{
			memset(cmd, 0, 100);
			sprintf(cmd, "insmod /tmp/aic_load_fw.ko");
			system(cmd);
		}
		memset(cmd, 0, 100);
		sprintf(cmd, "insmod /tmp/%s.ko", g_DongleMap[Dongle_Select].pKoName);
		system(cmd);
	}
	else
		printf("%s Not support dongle \n", __FUNCTION__);
#else
	#ifdef CONFIG_SUPPORT_AIC8800
	memset(cmd, 0, 100);
	sprintf(cmd, "insmod /tmp/aic_load_fw.ko");
	system(cmd);
	#endif
	memset(cmd, 0, 100);
	sprintf(cmd, "insmod /tmp/%s.ko", g_DongleMap[WIFI_DONGLE].pKoName);
	system(cmd);
#endif
}

MIRACAST_InitExitStatus_e miracast_getMiracastInitStatus(void)
{
	return bMiracastInitFinish;
}

MIRACAST_InitExitStatus_e miracast_getMiracastExitStatus(void)
{
	return bMiracastExitFinish;
}

