/*******************************************************************
Copyright (C):    
File name    :    HXCP_STM32.C
DESCRIPTION  :
AUTHOR       :
Version      :    1.0
Date         :    2014/02/26
Others       :
History      :
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1) Date: 2014/02/26         Author: ChenDajie
   content:

*******************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include<time.h>
#include<sys/time.h>
#include<signal.h>


#include <sys/ioctl.h>

#include <stdarg.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <linux/rtc.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>



#include "Iec10x.h"
#include "sys.h"
#include "Iec104.h"
#include "huayun_common.h"
#include "PRIO_QUEUE_Iec10x.h"

#define DEFAULT_HW_RTC "/dev/rtc0"

/*******************************************************************************
* Function Name  : stm32f103_init
* Description    : stm32f103_init program
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
static int Linux_init(void) {


    return 0;
}

static void *Linux_Malloc(unsigned char NumByte){

    return malloc(NumByte);
}


static void Linux_Free(void *pblock){

    free(pblock);
}

int SetHardwareRtc(struct tm *t_tm)
{
    int fd, retval = 0;
    struct rtc_time rtc_tm;
    rtc_tm.tm_sec = t_tm->tm_sec;
    rtc_tm.tm_min = t_tm->tm_min;
    rtc_tm.tm_hour = t_tm->tm_hour;
    rtc_tm.tm_mday = t_tm->tm_mday;
    rtc_tm.tm_mon = t_tm->tm_mon;
    rtc_tm.tm_year = t_tm->tm_year;
    rtc_tm.tm_wday = t_tm->tm_wday;
    rtc_tm.tm_yday = t_tm->tm_yday;
    rtc_tm.tm_isdst = t_tm->tm_isdst;
    fd = open (DEFAULT_HW_RTC, O_RDONLY);
    if (fd == -1) {
        perror(DEFAULT_HW_RTC);
        return -1;
    }
    /* Write the RTC time/date */
    retval = ioctl(fd, RTC_SET_TIME, &rtc_tm);
    if (retval == -1) {
        perror("write rtc");
        close(fd);
        return -1;
    }
    close(fd);

    fd = open (DEFAULT_HW_RTC, O_RDONLY);
    if (fd == -1) {
        perror(DEFAULT_HW_RTC);
        return -1;
    }
    /* Read the RTC time/date */
    retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
    if (retval == -1) {
        perror("read rtc");
        close(fd);
        return -1;
    }
    dy_syslog(LOG_DEBUG,"Current RTC date/time is %d-%d-%d,%02d:%02d:%02d ",
            rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
            rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
    close(fd);
    struct tm rtc;
    rtc.tm_sec = rtc_tm.tm_sec;
    rtc.tm_min = rtc_tm.tm_min;
    rtc.tm_hour = rtc_tm.tm_hour;
    rtc.tm_mday = rtc_tm.tm_mday;
    rtc.tm_mon = rtc_tm.tm_mon;
    rtc.tm_year = rtc_tm.tm_year;
    rtc.tm_wday = rtc_tm.tm_wday;
    rtc.tm_yday = rtc_tm.tm_yday;
    rtc.tm_isdst = rtc_tm.tm_isdst;
    if( abs(mktime(&rtc) - mktime(t_tm)) > 10)//大于10S意味着有问�?
        return -1;
    return 0;
}

static uint32_t Linux_SetTime(PCP56Time2a_T time){

	struct tm t_tm;
	time_t stime;

	t_tm.tm_sec = time->_milliseconds / 1000;
	t_tm.tm_min = time->_min._minutes;
	t_tm.tm_hour = time->_hour._hours;
	t_tm.tm_mday = time->_day._dayofmonth;
	t_tm.tm_wday = time->_day._dayofweek;
	t_tm.tm_mon = time->_month._month-1;
	t_tm.tm_year = time->_year._year+100;

	stime = mktime(&t_tm);
	stime -= 60*60*8;
	localtime_r(&stime, &t_tm);
	
	SetHardwareRtc(&t_tm);

    return RET_SUCESS;
}
#if 1
static uint32_t Linux_GetTime(PCP56Time2a_T time, time_t time_stamp){

	struct tm* ptm;	

	if(time_stamp)
	{
		time_t stamp = time_stamp + 60*60*8;
		stamp = time_stamp + 60*60*8;	
		ptm = localtime (&stamp);
		time->_milliseconds = (stamp%60)*1000;
	}
	else
	{
		struct timeval tv;
		gettimeofday (&tv, NULL);
		tv.tv_sec += 60*60*8;
		ptm = localtime (&tv.tv_sec);
		time->_milliseconds = tv.tv_usec / 1000;
	}
	
	time->_min._minutes = ptm->tm_min;
	time->_hour._hours = ptm->tm_hour;
	time->_day._dayofmonth = ptm->tm_mday;
	time->_day._dayofweek = ptm->tm_wday;
	time->_month._month = ptm->tm_mon+1;
	time->_year._year =ptm->tm_year-100;

	//dy_syslog(LOG_DEBUG,"-%s- tm_year %d Clock(20%d-%d-%d %d %d:%d:%d) ----------", __FUNCTION__,ptm->tm_year,time->_year._year,time->_month._month,time->_day._dayofmonth,
                    //time->_day._dayofweek,time->_hour._hours,time->_min._minutes,time->_milliseconds/1000);
	
    return RET_SUCESS;
}
#else
static uint32_t Linux_GetTime(PCP56Time2a_T time){

	struct timeval tv;
	struct tm* ptm;
	
	gettimeofday (&tv, NULL);
	tv.tv_sec += 60*60*8;
	ptm = localtime (&tv.tv_sec);
	
	time->_milliseconds = tv.tv_usec / 1000;
	time->_min._minutes = ptm->tm_min;
	time->_hour._hours = ptm->tm_hour;
	time->_day._dayofmonth = ptm->tm_mday;
	time->_day._dayofweek = ptm->tm_wday;
	time->_month._month = ptm->tm_mon+1;
	time->_year._year =ptm->tm_year-100;

	//dy_syslog(LOG_DEBUG,"-%s- tm_year %d Clock(20%d-%d-%d %d %d:%d:%d) ----------", __FUNCTION__,ptm->tm_year,time->_year._year,time->_month._month,time->_day._dayofmonth,
                    //time->_day._dayofweek,time->_hour._hours,time->_min._minutes,time->_milliseconds);
	
    return RET_SUCESS;
}
#endif
int8_t test_val = 1;
static int8_t Linux_GetStationInfo(uint16_t Addr,uint8_t n){

    //*MaxNum = WTP_SUPPORT_END_NUMBER;
    //*Addr = n;
    return test_val++;
}

static float Linux_GetStaTemp(uint16_t Addr){

    return 30;
}

static uint16_t Linux_GetLinkAddr(void){

    return 0x0001;
}

static void Linux_CloseLink(void){

    //GPRSFlag = SYSTEM_FLAG_GPRS_CLOSE;
    IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED;
}

void delay_ms(uint16_t ms){

    usleep(ms*1000);
}

uint8_t Linuxsend(int socketfd,char *buf, int len){
	int ret = write(socketfd,buf,len);
    if(ret < 0){
        dy_syslog(LOG_ERR,"-%s-,Send error ret %d",__FUNCTION__,ret);
        return RET_ERROR;
    }
	dy_syslog_hex(LOG_DEBUG, buf,len,"ret %d len %d                   网关->HUAYUN",ret,len);
    
    return RET_SUCESS;
}
void LinuxLock(void){

    pthread_mutex_lock(&mutex);
}
void LinuxUnlock(){

    pthread_mutex_unlock(&mutex);
}
int8_t GetInfoNum(uint8_t *InfoNum, uint8_t DevType)
{
	*InfoNum = 2;
	return 0;
}
/*******************************************************************************
* Function Name  : stm32f103
* Description    : stm32f103
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
static IEC10X_T Linux = {
    "Linux",
    Linux_init,
    delay_ms,
    Linux_CloseLink,
    Linux_Malloc,
    Linux_Free,
    IEC10X_PrioEnQueue,
    IEC10X_PrioDeQueue,
    IEC10X_PrioFindQueueHead,
    IEC10X_HighestPrio,            /* Get the highest Prio Queue*/
    IEC10X_PrioInitQueue,
    IEC10X_Prio_ClearQueue,
    Linuxsend,
    Linux_SetTime,
    Linux_GetTime,
    Linux_GetStationInfo,
    Linux_GetStaTemp,
    Linux_GetLinkAddr,
    GetInfoNum,

#ifdef IEC10XLOCK
    LinuxLock,
    LinuxUnlock
#endif
};
/*******************************************************************************
* Function Name  : mstm32f103RegisterShtxxain
* Description    : Main program
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
uint32_t Stm32f103RegisterIec10x(void){
    return RegisterIEC10XMoudle(&Linux);
}
