#include "bsp_netdev_hzluat.h"

#include "sr_config.h"

#include "sr_log.h"


//合宙头文件
#include "luat_mobile.h"


static SR_NETDEV_T gs_luatNetdev;



#ifdef BSP_HZLUAT_USE_DEVOM_OPS

static SR_NETDEV_OM_OPS_T  servOps =
{
	.get_imei = _LuatGetImei,
	.get_imsi = _LuatGetImsi,
	.get_iccid = _LuatGetIccid,
	.get_cfun = _LuatGetCfun,
	.set_cfun = _LuatSetCfun,
	.get_cell_info = _LuatGetCellInfo, 
	.get_signal_streng = _LuatGetSignalStreng,
	.get_net_reg_sta = _LuatGetNetRegSta,
	.check_sim_ready    = _LuatCheckSimReady,
	.get_netlink_sta = _LuatGetNetlinkSta,
	.get_pdp_sta     = _LuatGetPdpSta,
};

#endif









#ifdef BSP_HZLUAT_USE_WIFI_OPS

static SR_WIFI_OPS_T wifiOps =
{
   .get_scan_info = _LuatWifiScan,
   .get_scan_info_async = _LuatWifiScanAsync,
};

#endif





//注册网络设备
static int _BspNetdevRegHzLuat(void)
{
  int result=0;
		
  gs_luatNetdev.name = BSP_HZLUAT_NETDEV_NAME;  

  gs_luatNetdev.devomOps = &servOps;
  gs_luatNetdev.wifiOps = &wifiOps;
  
  result = SR_NetdevRegister(&gs_luatNetdev);
		
  return result;
}
SR_INIT_BSP_EXPORT(_BspNetdevRegHzLuat,SR_PRIORITY_1);




//合宙的网络事件通知回调
static void luat_mobile_event_cb(LUAT_MOBILE_EVENT_E event, uint8_t index, uint8_t status)
{
    NetdevEvtCb eventCb = (NetdevEvtCb)gs_luatNetdev.netEvtCb;
    uint8_t srEvent = 0xFF;   //朝阳的事件
    uint8_t srStatus = 0xFF;  //朝阳的状态值
	
	luat_mobile_cell_info_t cell_info;
	luat_mobile_signal_strength_info_t signal_info;
	uint16_t mcc;
	uint8_t csq, i, mnc;
	char imsi[20];
	char iccid[24] = {0};
	char apn[32] = {0};
	ip_addr_t ipv4;
	ip_addr_t ipv6;
	int result;


	srStatus = status;
	
	switch(event)
	{
	case LUAT_MOBILE_EVENT_CFUN:
		srEvent = SR_NET_EVT_CFUN;
		BSP_LOG(DEBUG,"[BSP]EVENT_CFUN: index=%d status=%d", index,status);

		switch(status)
	    {
          	case LUAT_MOBILE_CFUN_OFF:
			case LUAT_MOBILE_CFUN_NO_RF:
				srStatus = SR_CFUN_MODE_FLY;    //飞行
			break;
			
			case LUAT_MOBILE_CFUN_ON:           //全功能
				srStatus = SR_CFUN_MODE_FULL;    
		    break;
			default:
                srStatus = 0xFF;                //无效值
			break;        
		}
		
	
		break;
	case LUAT_MOBILE_EVENT_SIM:
		srEvent = SR_NET_EVT_SIM;

	    BSP_LOG(DEBUG,"[BSP]EVENT_SIM: index(simId=%d)，status=%d", index,status);

		if(status >= LUAT_MOBILE_SIM_ENTER_PIN_RESULT) srStatus = 0xFF;   //无效值
				
		switch(status)
		{
			case LUAT_MOBILE_SIM_READY:
				BSP_LOG(DEBUG,"SIM卡正常工作");
				luat_mobile_get_iccid(index, iccid, sizeof(iccid));
				BSP_LOG(DEBUG,"ICCID %s", iccid);
				luat_mobile_get_imsi(index, imsi, sizeof(imsi));
				BSP_LOG(DEBUG,"IMSI %s", imsi);
				luat_mobile_get_plmn_from_imsi(imsi, &mcc, &mnc);
				result = luat_mobile_get_isp_from_plmn(mcc, mnc);
				switch(result)
				{

					case LUAT_MOBILE_ISP_CMCC:
						BSP_LOG(DEBUG,"中国移动卡");
						break;
					case LUAT_MOBILE_ISP_CTCC:
						BSP_LOG(DEBUG,"中国电信卡");
						break;
					case LUAT_MOBILE_ISP_CUCC:
						BSP_LOG(DEBUG,"中国联通卡");
						break;
					case LUAT_MOBILE_ISP_CRCC:
						BSP_LOG(DEBUG,"中国广电卡");
						break;
					case LUAT_MOBILE_ISP_UNKNOW:
						BSP_LOG(DEBUG,"未知运营商");
						break;
					default:
						BSP_LOG(DEBUG,"非中国卡");
						break;
				}
				break;
			case LUAT_MOBILE_NO_SIM:
				BSP_LOG(DEBUG,"SIM卡不存在");
				break;
			case LUAT_MOBILE_SIM_NEED_PIN:
				BSP_LOG(DEBUG,"SIM卡需要输入PIN码");
				break;
		}

		
		break;
	case LUAT_MOBILE_EVENT_REGISTER_STATUS:
		srEvent = SR_NET_EVT_REGSTA;
		BSP_LOG(DEBUG,"[BSP]EVENT_REGISTER:移动网络注册状态变更，status=%d", status);

		if(status >= LUAT_MOBILE_STATUS_SMS_ONLY_REGISTERED) srStatus = 0xFF;   //无效值
			
		break;
	case LUAT_MOBILE_EVENT_CELL_INFO:
		//srEvent = SR_NET_EVT_CELL_INFO;
		BSP_LOG(DEBUG,"[BSP]CELL INFO，status=%d", status);

	
		switch(status)
		{
			case LUAT_MOBILE_CELL_INFO_UPDATE:  /**< 小区基站信息变更，只有设置了周期性搜索小区基站时才会有*/
				 #if  0
					BSP_LOG(DEBUG,"周期性搜索小区信息完成一次");
					luat_mobile_get_last_notify_cell_info(&cell_info);
					if (cell_info.lte_service_info.cid)
					{
						BSP_LOG(DEBUG,"服务小区信息 mcc %x mnc %x cellid %u band %d tac %u pci %u earfcn %u is_tdd %d rsrp %d rsrq %d snr %d rssi %d",
								cell_info.lte_service_info.mcc, cell_info.lte_service_info.mnc, cell_info.lte_service_info.cid,
								cell_info.lte_service_info.band, cell_info.lte_service_info.tac, cell_info.lte_service_info.pci, cell_info.lte_service_info.earfcn,
								cell_info.lte_service_info.is_tdd, cell_info.lte_service_info.rsrp, cell_info.lte_service_info.rsrq,
								cell_info.lte_service_info.snr, cell_info.lte_service_info.rssi);
					}
					for (i = 0; i < cell_info.lte_neighbor_info_num; i++)
					{
						if (cell_info.lte_info[i].cid)
						{
							BSP_LOG(DEBUG,"邻小区 %d mcc %x mnc %x cellid %u tac %u pci %u", i + 1, cell_info.lte_info[i].mcc,
									cell_info.lte_info[i].mnc, cell_info.lte_info[i].cid, cell_info.lte_info[i].tac, cell_info.lte_info[i].pci);
							BSP_LOG(DEBUG,"邻小区 %d earfcn %u rsrp %d rsrq %d snr %d", i + 1, cell_info.lte_info[i].earfcn, cell_info.lte_info[i].rsrp,
									cell_info.lte_info[i].rsrq, cell_info.lte_info[i].snr);
						}
					}
				#endif
				
			break;
				
			case LUAT_MOBILE_SIGNAL_UPDATE:  /**< 网络信号状态变更，但是不一定是有变化*/
				#if  0
					BSP_LOG(DEBUG,"服务小区信号状态变更");
					luat_mobile_get_last_notify_signal_strength_info(&signal_info);
					luat_mobile_get_last_notify_signal_strength(&csq);
					if (signal_info.luat_mobile_lte_signal_strength_vaild)
					{
						BSP_LOG(DEBUG,"rsrp %d, rsrq %d, snr %d, rssi %d, csq %d (rssi->)%d", signal_info.lte_signal_strength.rsrp,
								signal_info.lte_signal_strength.rsrq, signal_info.lte_signal_strength.snr,
								signal_info.lte_signal_strength.rssi, csq, luat_mobile_rssi_to_csq(signal_info.lte_signal_strength.rssi));
					}
				#endif

			break;
		}
		
	break;
		
	case LUAT_MOBILE_EVENT_PDP:
		srEvent = SR_NET_EVT_PDP;
		BSP_LOG(DEBUG,"[BSP]EVENT_PDP: PDP激活状态变更index(cid=%d) status=%d", index, status);

		switch(status)
	    {
          	case LUAT_MOBILE_PDP_ACTIVED:
				srStatus = SR_PDP_ACTIVED;      //激活
			break;
			
			case LUAT_MOBILE_PDP_DEACTIVING:
	        case LUAT_MOBILE_PDP_DEACTIVED:
				srStatus = SR_PDP_UNACTIVED;    //未激活
		    break;
			default:
                srStatus = 0xFF;    //无效值
			break;        
		}

		gs_luatNetdev.pdpSta = srStatus;  //保存，供其他接口查询
	
		break;
	case LUAT_MOBILE_EVENT_NETIF:
		srEvent = SR_NET_EVT_LINK;
		BSP_LOG(DEBUG,"[BSP]EVENT_NETIF: internet工作状态变更为 status=%d index(cause=%d)", status,index);
		
	
		switch (status)
		{
			case LUAT_MOBILE_NETIF_LINK_ON:
				srStatus = SR_NET_LINK_ON;
				BSP_LOG(DEBUG,"可以上网,NETIF_LINK_ON");
			    #if  0  //调试用
					if (luat_mobile_get_apn(0, 0, apn, sizeof(apn)))
					{
						BSP_LOG(DEBUG,"默认apn %s", apn);
					}
					luat_mobile_get_local_ip(0, 1, &ipv4, &ipv6);
					if (ipv4.type != 0xff)
					{
						BSP_LOG(DEBUG,"IPV4 %s", ip4addr_ntoa(&ipv4.u_addr.ip4));
					}
					if (ipv6.type != 0xff)
					{
						BSP_LOG(DEBUG,"IPV6 %s", ip6addr_ntoa(&ipv4.u_addr.ip6));
					}
				#endif
			break;
				
			default:
				srStatus = SR_NET_LINK_OFF;
				BSP_LOG(DEBUG,"不能上网");
			break;
		}

		gs_luatNetdev.linkSta = srStatus;  //保存，供其他接口查询
		break;
		
	case LUAT_MOBILE_EVENT_TIME_SYNC:
		//srEvent = SR_NET_EVT_TIME_SYNC;
		BSP_LOG(DEBUG,"[BSP]EVENT_TIME_SYNC:通过网络同步了UTC时间");
	
		break;
	case LUAT_MOBILE_EVENT_CSCON:
		srEvent = SR_NET_EVT_CSCON;
		BSP_LOG(DEBUG,"[BSP]EVENT_CSCON: RRC status=%d", status);
	
		break;
	case LUAT_MOBILE_EVENT_FATAL_ERROR:
		BSP_LOG(DEBUG,"[BSP]EVENT_FATAL_ERROR:网络需要严重故障，建议在5秒后重启协议栈");
		
		break;
	default:
		break;
	}


	if(srEvent != 0xFF) 
	{
       if(eventCb) eventCb(gs_luatNetdev.netEvtArgs,srEvent,index,srStatus);

	}
}


//网络设备软件初始化
static int _BspNetdevInitHzLuat(void)
{

    luat_mobile_event_register_handler(luat_mobile_event_cb);
	//luat_mobile_sms_event_register_handler(sms_event_cb); //预留
	//luat_mobile_set_period_work(90000, 5000, 4);
	luat_mobile_set_period_work(0, 5000, 4);
	luat_mobile_set_check_network_period(120000);
	luat_mobile_set_sim_id(2);  //自动选择
	luat_mobile_set_sim_detect_sim0_first(); //在自动选择模式时，开机后优先用sim0 

}
SR_INIT_BSP_EXPORT(_BspNetdevInitHzLuat,SR_PRIORITY_0);


#if 0
备注：
@设置周期性辅助工作，包括周期性搜索小区基站，SIM卡短时间脱离卡槽后周期性尝试恢复，这个功能和luat_mobile_reset_stack是有可能冲突的。所有功能默认都是关闭的 
参数
@get_cell_period 周期性搜索小区基站的时间间隔，单位ms，这个会增加低功耗，尽量的长，或者写0关闭这个功能，用上面的手段搜索  
@check_sim_period SIM卡短时间脱离卡槽后尝试恢复的时间间隔，单位ms，建议在5000~10000，或者写0，当SIM卡移除的消息上来后手动重启协议栈  
search_cell_time 启动周期性搜索小区基站后，每次搜索的最大时间，单位s，1~8  
@返回int 
int luat_mobile_set_period_work( uint32_t  get_cell_period, uint32_t  check_sim_period,uint8_t  search_cell_time)  



@设置定时检测网络是否正常并且在检测到长时间无网时通过重启协议栈来恢复，但是不能保证一定成功，这个功能和luat_mobile_reset_stack是有可能冲突的。所有功能默认都是关闭的 
参数
@period 无网时长，单位ms，不可以太短，建议60000以上，为网络搜索网络保留足够的时间  
@返回void 
void luat_mobile_set_check_network_period( uint32_t  period ) 

#endif
