#include "lwip_dm9k.h"
#include "dm9k.h"
#include "ethernetif_dm9k.h"
#include "lwip/tcpip.h"
#include "lwip_init.h"
#include "malloc.h"
#include "memory_manager.h"

struct netif dm9k_netif; // 定义一个网络接口

#define DM9K_TASK_PRIO     10
#define DM9K_TASK_STK_SIZE 512
CPU_STK     dm9k_task_stk[DM9K_TASK_STK_SIZE];
static void ethernet_link_status_updated(struct netif *netif);
// lwip 默认IP设置
void lwip_dm9k_default_ip_set(__lwip_dev *lwipx)
{

    // 默认远端IP为:192.168.1.100
    lwipx->remoteip[0] = 192;
    lwipx->remoteip[1] = 168;
    lwipx->remoteip[2] = 1;
    lwipx->remoteip[3] = 10;

    // MAC地址设置(高三字节固定为:2.0.0,低三字节用STM32唯一ID)
    lwipx->mac[0] = 2; // 高三字节(IEEE称之为组织唯一ID,OUI)地址固定为:2.0.0
    lwipx->mac[1] = 0;
    lwipx->mac[2] = 0;
    lwipx->mac[3] = 0x90; // 低三字节用STM32的唯一ID
    lwipx->mac[4] = 0x00;
    lwipx->mac[5] = 0xae;

    // 默认本地IP为:192.168.1.30
    lwipx->ip[0] = 192;
    lwipx->ip[1] = 168;
    lwipx->ip[2] = 1;
    lwipx->ip[3] = 40;

    // 默认子网掩码:255.255.255.0
    lwipx->netmask[0] = 255;
    lwipx->netmask[1] = 255;
    lwipx->netmask[2] = 255;
    lwipx->netmask[3] = 0;

    // 默认网关:192.168.1.1
    lwipx->gateway[0] = 192;
    lwipx->gateway[1] = 168;
    lwipx->gateway[2] = 1;
    lwipx->gateway[3] = 1;

    lwipx->dhcpstatus = 0; // 没有DHCP
}

void ethernet_dm9k_link_thread(void const *argument)
{
    struct netif *netif = (struct netif *)(argument);

    for (;;)
    {
        ethernet_link_check_state(netif);
        OSTimeDly(2000);
    }
}

// LWIP初始化(LWIP启动的时候使用)
void lwip_dm9k_init(void)
{
    ip4_addr_t ipaddr;
    ip4_addr_t netmask;
    ip4_addr_t gw;
    uint8_t    linkchanged = 0;

    lwip_dm9k_default_ip_set(&dm9kdev); // 设置默认IP等信息
    dm9k_init();

#ifdef USE_DHCP // 使用动态IP
    ip_addr_set_zero_ip4(&ipaddr);
    ip_addr_set_zero_ip4(&netmask);
    ip_addr_set_zero_ip4(&gw);
#else // 使用静态IP
    IP4_ADDR(&ipaddr, dm9kdev.ip[0], dm9kdev.ip[1], dm9kdev.ip[2], dm9kdev.ip[3]);
    IP4_ADDR(&netmask, dm9kdev.netmask[0], dm9kdev.netmask[1], dm9kdev.netmask[2], dm9kdev.netmask[3]);
    IP4_ADDR(&gw, dm9kdev.gateway[0], dm9kdev.gateway[1], dm9kdev.gateway[2], dm9kdev.gateway[3]);
#endif

    netif_add(&dm9k_netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_dm9k_init, &tcpip_input); // 向网卡列表中添加一个网口
    netif_set_default(&dm9k_netif);                                                            // 设置netif为默认网口
    printf("LwIP Registers dm9k_netif default network interface....\r\n");
    /* Set the link callback function, this function is called on change of link status*/
#if LWIP_NETIF_LINK_CALLBACK
    netif_set_link_callback(&dm9k_netif, ethernet_link_status_updated);
#endif

    // OSTaskCreateExt((void (*)(void *))ethernet_dm9k_link_thread,
    //                 (void const *)&dm9k_netif,
    //                 (OS_STK *)&dm9k_task_stk[DM9K_TASK_STK_SIZE - 1],
    //                 (INT8U)DM9K_TASK_PRIO,
    //                 (INT16U)DM9K_TASK_PRIO,
    //                 (OS_STK *)&dm9k_task_stk[0],
    //                 (INT32U)DM9K_TASK_STK_SIZE,
    //                 (void *)0,
    //                 (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP);

    linkchanged = dm9k_linkstat();

    if (netif_is_link_up(&dm9k_netif) && (linkchanged == 0))
    {
        printf("dm9k LwIP Error interface....\r\n");
        netif_set_down(&dm9k_netif);
        netif_set_link_down(&dm9k_netif);
    }
    else if (!netif_is_link_up(&dm9k_netif) && (linkchanged == 1))
    {
        printf("dm9k LwIP Finish interface....\r\n");
        netif_set_up(&dm9k_netif);
        netif_set_link_up(&dm9k_netif);
    }

    // ethernet_link_check_state(&dm9k_netif);
    //  if (ethernet_link_check_state() == 1)
    // {
    //     dm9k_netif.flags |= NETIF_FLAG_LINK_UP;
    //     netif_set_up(&dm9k_netif);
    // }
}

/**
 * @brief  This function notify user about link status changement.
 * @param  netif: the network interface
 * @retval None
 */
static void ethernet_link_status_updated(struct netif *netif)
{
#if LWIP_DHCP
    if (DHCPSemaphore == NULL)
    {
        osSemaphoreDef(ETH_SEM);
        DHCPSemaphore = osSemaphoreCreate(osSemaphore(ETH_SEM), 1);
    }
#else
    ip_addr_t ipaddr;
    ip_addr_t netmask;
    ip_addr_t gw;
#endif /* USE_DHCP */

    if (netif_is_link_up(netif))
    {
#if LWIP_DHCP
        /* Update DHCP state machine */
        dm9kdev.dhcpstatus = DHCP_START;
        osSemaphoreRelease(DHCPSemaphore);
#else
        IP4_ADDR(&ipaddr, dm9kdev.ip[0], dm9kdev.ip[1], dm9kdev.ip[2], dm9kdev.ip[3]);
        IP4_ADDR(&netmask, dm9kdev.netmask[0], dm9kdev.netmask[1], dm9kdev.netmask[2], dm9kdev.netmask[3]);
        IP4_ADDR(&gw, dm9kdev.gateway[0], dm9kdev.gateway[1], dm9kdev.gateway[2], dm9kdev.gateway[3]);

        dm9kdev.dhcpstatus = DHCP_ADDRESS_ASSIGNED; // 标记网络开启成功。
#endif /* USE_DHCP */
    }
    else
    {
#if LWIP_DHCP
        /* Update DHCP state machine */
        osSemaphoreRelease(DHCPSemaphore);
#endif /* USE_DHCP */
        dm9kdev.dhcpstatus = DHCP_LINK_DOWN;
    }
}
