7620a无线中继模块(wisp)

该模块为7620a无线中继模块,支持自动扫描,自动拨号,支持中文ssid配置(需要编解码模块支持)

无线驱动需要增加wifi断开和连接信号发送,用于应用层处理事件。

该模块仅供参考,如有问题,可以联系我。

/*
 * wisp.c
 * 7620a无线中继模块,支持自动重拨,支持中文ssid
 * Author:dxt1107
 * Mail:destan19@126.com
 * 2014.12.04
 */
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <bcmnvram.h>
#include <shutils.h>
#include <ralink.h>
#include <bcmutils.h>
#include <etioctl.h>
#include <bcmparams.h>
#include <linux/autoconf.h>
#include <signal.h>
#include "encode.h"
#define WISP_IFNAME "apcli0"

#define STAT_LINK_DOWN 0
#define STAT_LINK_UP 1
#define SIG_APCLI_LINKDOWN SIGUSR2 + 20  // 37
#define SIG_APCLI_LINKUP   SIGUSR2 + 21  // 38
#define SIG_WISP_DEBUG     SIGUSR2 + 22  // 39
#define SCAN_INTERVAL 3
#define CHECK_NETWORK_INTERVAL 180
#define DIAGNOSE_INTERVAL 16
static int wisp_debug = 0;

#define WDBG(fmt,args...) if (wisp_debug)\
	printf("dxt1107\033[0;32;32m%s,%d "fmt"\033[m",__func__,__LINE__,##args);

struct wifi_node_t{
	struct wifi_node_t * next;
	char ssid[64];
	char bssid[32];
	char auth_mode[32];
	char encrypt_type[32];	
	char w_mode[16];
	int signal;
	int channel;
};
typedef enum wifi_status
{
	STATUS_INIT = 0,
	STATUS_AUTH_OK,
	STATUS_CONNECTED_OK,
	STATUS_INTERNET_OK,
}E_WIFI_STATUS;
struct wifi_node_t * wifi_head = NULL;
struct wifi_node_t g_cur_connect_wifi;
static int g_wifi_node_count = 0;
E_WIFI_STATUS  g_wifi_status = STATUS_INIT;

static void update_wifi_status(E_WIFI_STATUS status)
{
	char buf[16] = {0};
	if ( status < STATUS_INIT || status > STATUS_INTERNET_OK ) {
		printf("error,invalid status,%d\n",status);
		return;
	}
	g_wifi_status = status;
	sprintf(buf, "%d", status);
	nvram_set("wisp_status",buf);
}

void show_all_wifi_node(void)
{
	if (!wisp_debug)
		return;
	printf("dxt1107###########begin show wifi list###############\n");
	int i = 0;
	struct wifi_node_t * p = wifi_head;
	while ( p ) {
		i++;
		printf("%d ssid:%s,bssid:%s,channel:%d,mode:%s,signal:%d\n",
				i, p->ssid,p->bssid,p->channel,p->auth_mode,p->signal);
		p = p->next;
	}
	printf("dxt1107###########end show wifi list###############\n");

}

void show_one_wifi_node(struct wifi_node_t * p )
{
	if ( !p )
		return;
	printf("dxt1107###ssid:%s,bssid:%s,channel:%d,mode:%s,signal:%d###\n",
			p->ssid,p->bssid,p->channel,p->auth_mode,p->signal);
}
int  add_wifi_node(struct wifi_node_t * item)
{
	if ( NULL == item )
		return 0;
	item ->next = NULL;
	if ( wifi_head == NULL ){
		wifi_head = item;
	}
	else{
		item->next = wifi_head->next;
		wifi_head->next = item;
	}
	g_wifi_node_count ++;
	return 1;
}


void  del_wifi_node(struct wifi_node_t * item)
{
	struct wifi_node_t * p = wifi_head;
	struct wifi_node_t * prev = wifi_head;
	if ( NULL == item )
		return ;
	if ( wifi_head == NULL ){
		return ;
	}
	else{
		while ( p ) {
			if ( !strcmp ( p->bssid , item->bssid) && 
				p->channel == item->channel) {
				if ( NULL == prev->next )
					wifi_head = NULL;
				else {
					prev->next = p->next;
				}
				g_wifi_node_count--;
				WDBG("dxt1107bssid:%s,ssid:%s,channel:%d,cur_count:%d\n",\
					p->bssid,p->ssid,p->channel,g_wifi_node_count);
				free(p);
				return;
			}
			prev = p;
			p = p->next;
		}
	}
}

void clear_wifi_list(void)
{
	struct wifi_node_t * p = wifi_head, * tmp = NULL;
	while ( p ) {
		tmp = p->next;
		free (p);
		p = tmp;		
	}
	wifi_head = NULL;
	g_wifi_node_count = 0;
}


static void
wisp_signal(int sig)
{
	char   signal[] = "XXXX";
	int pid;
	if (sig == SIG_APCLI_LINKDOWN) {
		WDBG("dxt1107###########wisp link down#############\n");
	    if (pids("udhcpc"))
	    {
	        snprintf(signal, sizeof(signal), "-%d", SIGUSR2);
	        eval("killall", signal, "udhcpc");
	        usleep(9000);
	    }
		sleep(1);
	    if (pids("udhcpc"))
	    {
	        eval("killall", "-SIGTERM", "udhcpc");
	         usleep(9000);
	    }
	    unlink("/tmp/udhcpc");
		printf("[%d] ssid:%s,channel:%d,change status %d==>%d\n",\
						__LINE__,g_cur_connect_wifi.ssid,\
						g_cur_connect_wifi.channel,g_wifi_status,STATUS_INIT);
		update_wifi_status(STATUS_INIT);

	}
	else if (sig == SIG_APCLI_LINKUP) {
		WDBG("dxt1107###########wisp link up#############\n");

		if (g_wifi_status >= STATUS_CONNECTED_OK)
			return;
		symlink( "/sbin/rc", "/tmp/udhcpc" );
		char *wan_hostname = nvram_safe_get("wan_hostname");
		char *dhcp_argv[] = {
		    "udhcpc",
		    "-i", WISP_IFNAME,
		    "-p", "/var/run/udhcpc_wan.pid",
		    "-s", "/tmp/udhcpc",
		    wan_hostname && *wan_hostname ? "-H" : NULL,
		    wan_hostname && *wan_hostname ? wan_hostname : NULL,
		    NULL };

	    int dhcpret = 0, trycount = 3;
		
		while (trycount != 0)
		{
			dhcpret = _eval_udhcpc(dhcp_argv, NULL, 0, &pid);
	        	if ((-3) == dhcpret) {
	        		trycount -= 1;
					dprintf( "## Pull dhcp process fails, retry three times pulled.\n" );
					usleep(2000);
	        	} else {
					break;
	        	}
		}
		WDBG("[%d] ssid:%s,channel:%d,change status %d==>%d\n",\
							__LINE__,g_cur_connect_wifi.ssid,
							g_cur_connect_wifi.channel,g_wifi_status,STATUS_AUTH_OK);
		update_wifi_status(STATUS_AUTH_OK);

	
	}
	else if ( sig == SIG_WISP_DEBUG )
	{
		
		wisp_debug = (wisp_debug == 1)?0:1;
		show_all_wifi_node();
		printf("ssid:%s,bssid:%s,channel:%d,status:%d,count:%d\n",
			g_cur_connect_wifi.ssid,g_cur_connect_wifi.bssid,
			g_cur_connect_wifi.channel,g_wifi_status,
			g_wifi_node_count);
	}
}


void hex_to_str(unsigned char * str,unsigned char *hex){
    unsigned char *p = hex;
    unsigned char *p_dst = str;
    unsigned char tmp[8]={0};
    strcpy(p_dst,"0x");
    p_dst+=2;
    while(*p)
    {
        memset(tmp,0x0,sizeof(tmp));
        sprintf(tmp,"%X",*p);
        memcpy(p_dst,tmp,2);
        p_dst+=2;
        p++;
    }
}

void my_trim(char *s)
{
	size_t len = strlen(s);
	size_t lws;

	/* trim trailing whitespace */
	while (len && isspace(s[len-1]))
		--len;

	/* trim leading whitespace */
	if (len) {
		lws = strspn(s, " \n\r\t\v");
		if (lws) {
			len -= lws;
			memmove(s, s + lws, len);
		}
	}
	s[len] = '\0';
}

/*
 * Function: parse_auth_encrypt
 * Description:
 * Input: auth_encrypt
 * Output: auth_mode, encrypt_type
 * Return: none
 * Author: dxt1107
 */

void parse_auth_encrypt(char *auth_encrypt, 
				char * auth_mode, 
				char *encrypt_type)
{
	char *p = NULL;
	char auth_encrypt_buf[64] = {0};
	strcpy(auth_encrypt_buf,auth_encrypt);
	
	if ( 0 == memcmp(auth_encrypt_buf,"NONE",4)) {
		strcpy(auth_mode, "OPEN");
		strcpy(encrypt_type, "NONE" );
	}
	else if ( 0 == memcmp(auth_encrypt_buf,"WEP",3)) {
		strcpy (auth_mode, "WEPAUTO");
		strcpy(encrypt_type, "WEP" );
	}
	else {
		p = strtok (auth_encrypt_buf, "/");
		if ( !p ) {
			printf("invalid type:%s\n",auth_encrypt);
			return;
		}
		strcpy ( auth_mode, p);
		p = strtok (NULL, "/");
		if ( !p ) {
			return;
		}
		strcpy ( encrypt_type, p);
		if ( 0 == memcmp ( auth_mode, "WPA1PSKWPA2PSK",14)) {
			strcpy(auth_mode,"WPA2PSK");
		}
	}
}



void update_wifi_list()
{
	char  channel[8];
	char  ssid[64];
	char  bssid[32];
	char  auth_mode[32];
	char  encrypt_type[32];
	char  auth_encrypt[64];
	char  cmd_buf[256] = {0};
	char  signal[16] = {0};
	char  w_mode[16] = {0};
	char  * conf_ssid = NULL;
	char  * conf_ae = NULL;
	char ssid_buf[128] = {0};
	struct wifi_node_t * new_node = NULL;
	FILE *fp = NULL;
	conf_ssid = nvram_safe_get( "wisp_ssid" );
	WDBG("conf_ssid:%s\n",conf_ssid);
	conf_ae = nvram_safe_get( "wisp_auth_encrypt" );
	if ( !conf_ssid || !strlen (conf_ssid)) {
		printf("error,wisp_ssid not set.");
		return;
	}

	if ( !conf_ae || !strlen (conf_ae)) {
		printf("error,auth_encrypt not set.");
		return;
	}
	if ( is_cn_encode(conf_ssid)) {
		hex_to_str(ssid_buf,conf_ssid);
	}
	else {
		strcpy(ssid_buf,conf_ssid);
	}

	do_system( "iwpriv "WISP_IFNAME" set SiteSurvey=1",wisp_debug);
	sleep(4);
	sprintf(cmd_buf,"iwpriv ra0 get_site_survey");
	fp = popen(cmd_buf,"r");
	if (!fp) {
		return;
	}
	if ( NULL != wifi_head ) {
		clear_wifi_list();
	}
	fgets(cmd_buf,sizeof(cmd_buf),fp);
	fgets(cmd_buf,sizeof(cmd_buf),fp);

	while (fgets(cmd_buf,sizeof(cmd_buf),fp) ) {
		memset (encrypt_type,0x0,sizeof(encrypt_type));
		memset (auth_mode,0x0,sizeof(auth_mode));
		memset(channel,0x0,sizeof(channel));
		memset(bssid,0x0,sizeof(bssid));
		memset(ssid,0x0,sizeof(ssid));
		memset(w_mode,0x0,sizeof(w_mode));
		memset(signal,0x0,sizeof(signal));
		memset(auth_encrypt,0x0,sizeof(auth_encrypt));

		memcpy(channel,cmd_buf,4);
		my_trim(channel);

		memcpy(ssid,cmd_buf+4,64);
		my_trim(ssid);
		WDBG("ssid=%s,%s--\n",ssid_buf,ssid);
	
		memcpy(bssid,cmd_buf+69,20);
		my_trim(bssid);
		memcpy(auth_encrypt,cmd_buf+89,23);
		my_trim(auth_encrypt);
		memcpy(signal,cmd_buf+112,9);
		my_trim(signal);
		memcpy(w_mode,cmd_buf+121,8);
		my_trim(w_mode);
		
		if ( strcmp(ssid_buf,ssid) 
			|| atoi(channel) <= 0 ) {
			continue;
		}
		parse_auth_encrypt(auth_encrypt,auth_mode,encrypt_type);
		
		new_node = (struct wifi_node_t *) malloc (sizeof(struct wifi_node_t));
		if ( NULL == new_node ) {
			printf("malloc wifi_node error!\n");
			continue;
		}
		new_node->next = NULL;
		new_node->channel = atoi(channel);
		new_node->signal = atoi(signal);
		strcpy(new_node->bssid,bssid);
		strcpy(new_node->ssid,ssid);
		strcpy(new_node->auth_mode,auth_mode);
		strcpy(new_node->encrypt_type,encrypt_type);
		add_wifi_node(new_node);
	}
	pclose(fp);
}

void wisp_init_config(void)
{
	char   cmd_buf[128] = {0};
	do_system("ifconfig "WISP_IFNAME" up", wisp_debug );
		
	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWispPid=%d",0 );
	do_system(cmd_buf , wisp_debug );
	do_system( "iwpriv  "WISP_IFNAME" set ApCliAuthMode=" , wisp_debug );
	do_system("iwpriv  "WISP_IFNAME" set ApCliEncrypType=" , wisp_debug );
	do_system("iwpriv  "WISP_IFNAME" set Channel=" , wisp_debug );
	do_system("iwpriv  "WISP_IFNAME" set ApCliEnable=1", wisp_debug);
	nvram_set("wan_ifname", WISP_IFNAME);
}

void connect_wifi(struct wifi_node_t * wifi_node)
{
	char * password;
	char * ssid;

	char   cmd_buf[128] = {0};
	do_system("iwpriv  "WISP_IFNAME" set ApCliEnable=0", 0);

	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWispPid=%d",0 );
	do_system(cmd_buf , wisp_debug );
	
	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set Channel=%d", wifi_node->channel);
	do_system(cmd_buf , wisp_debug );
	sleep(5);
	
	ssid = nvram_safe_get( "wisp_ssid" );
	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliSsid='%s'",ssid);
	do_system(cmd_buf ,wisp_debug );

	password =  nvram_safe_get( "wisp_password");

	if ( 0 == memcmp( wifi_node->encrypt_type, "WEP",3)) {
		sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliDefaultKeyID=%d",1 );
		do_system(cmd_buf , wisp_debug );	
		sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliKey1=%s",password );
		do_system(cmd_buf , wisp_debug );	
	}
	else {
		sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWPAPSK=%s",password );
		do_system(cmd_buf , wisp_debug );	
	}
	
	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliWispPid=%d",getpid() );
	do_system(cmd_buf , wisp_debug );


	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliAuthMode=%s",wifi_node->auth_mode);
	do_system(cmd_buf , wisp_debug );
	sprintf(cmd_buf, "iwpriv  "WISP_IFNAME" set ApCliEncrypType=%s",\
							wifi_node->encrypt_type);
	do_system(cmd_buf , wisp_debug );
	do_system("iwpriv  "WISP_IFNAME" set ApCliEnable=1", 0);
}

static char ping_domain[][32] ={
		{"www.baidu.com"},
		{"www.126.com"},
		{""},
};

int check_internet(void)
{
	int i;
	char read_buf[256] = {0};
	int len = 0;
	FILE * fp  = NULL;
	char cmd_buf[128] = {0};
	struct hostent *p = NULL;
	for (i = 0;strlen(ping_domain[i])> 0;i++){
		p = gethostbyname(ping_domain[i]);
		if (!p)
		{	
			WDBG("get host name failed.%s\n",ping_domain[i]);
			continue;
		}
		sprintf(cmd_buf,"ping %s -c 4",ping_domain[i]);
		fp = popen(cmd_buf,"r");
		if ( !fp ) {
			continue;
		}
		len = fread(read_buf,1, sizeof(read_buf), fp);
		if ( strstr(read_buf, "64 bytes from") && !strstr(read_buf,nvram_safe_get("wan_gateway"))) {
			WDBG("ping success.%s\n",ping_domain[i]);
			pclose(fp);
			return 1;
		}
		pclose(fp);
	}
	return 0;
}


/*
 * function:update_wifi_info
 * desc:用于页面获取连接信息
 * author:dxt1107
 * date:2014.12.08
*/
void update_wifi_info(const struct wifi_node_t * p)
{
	char buf[32] = {0};
	sprintf(buf, "%d", p->signal);
	nvram_set("wisp_signal",buf);
	nvram_set("wisp_bssid",p->bssid);	
	sprintf(buf, "%d", p->channel);
	nvram_set("wisp_channel",buf);
	WDBG("wisp_signal:%d,bssid:%s,channel:%d\n",p->signal,p->bssid,p->channel);
}


void check_wisp_status(void)
{
	int sleep_ct = 0;
	int wifi_count = 0;
	struct wifi_node_t * p_wifi = wifi_head;
	
	while ( p_wifi ) {
		wifi_count ++;
		update_wifi_status(STATUS_INIT);
		WDBG("connecting {%s,%s,%d}..........%d\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel,wifi_count);
		memcpy(&g_cur_connect_wifi,p_wifi,sizeof(struct wifi_node_t));

		update_wifi_info(&g_cur_connect_wifi);
		connect_wifi(p_wifi);
		sleep_ct = 0;
		while (sleep_ct < 20 && g_wifi_status < STATUS_AUTH_OK ) {
			sleep(1);
			sleep_ct ++;
		}
		if ( STATUS_AUTH_OK == g_wifi_status ) {
			WDBG("{%s,%s,%d} auth ..............ok\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);

			sleep_ct = 0;
			while (sleep_ct < 20 && !nvram_match("wan_status", "Connected") ) {
				sleep(1);
				sleep_ct ++;
			}

			if (nvram_match("wan_status", "Connected")){ 
				printf("[%d] ssid:%s,channel:%d,change status %d==>%d\n",__LINE__,g_cur_connect_wifi.ssid,
					g_cur_connect_wifi.channel,STATUS_AUTH_OK,STATUS_CONNECTED_OK);
				update_wifi_status(STATUS_CONNECTED_OK);
				WDBG("{%s,%s,%d} connect ..............ok\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
				sleep_ct = 0;
				while (sleep_ct < 2 ) {
					if (check_internet()) {
						WDBG("{%s,%s,%d} connect internet ..............ok\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
						
						update_wifi_status(STATUS_INTERNET_OK);

						return;
					}
					sleep(15);
					sleep_ct ++;
				}
				WDBG("{%s,%s,%d} connect internet ..............failed\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
			}
			else 
				WDBG("{%s,%s,%d} lease ip ..............failed\n",p_wifi->ssid,p_wifi->bssid,p_wifi->channel);
		}
		p_wifi = p_wifi->next;
	}
}

void check_wifi_list_change(void)
{
	if ( strlen(g_cur_connect_wifi.ssid) > 0) {
		WDBG("##### current scan result #########\n");
		show_all_wifi_node();
		WDBG("last time connect wifi:\n");
		show_one_wifi_node(&g_cur_connect_wifi);
		del_wifi_node(&g_cur_connect_wifi);
	}
}

void diagnose_network(void)
{
	char *wan_ip = NULL;
	switch ( g_wifi_status ) {
		case STATUS_CONNECTED_OK:
			wan_ip = nvram_safe_get("wan_ipaddr");
			if ( (NULL == wan_ip || strlen(wan_ip) < 7 ) 
					&& nvram_match("wan_status", "Connected")) {
				nvram_set("wan_status","Disconnected");
				update_wifi_status(STATUS_INIT);
				printf("diagnose network .........success.\n");
			}
		default:
			break;
	}
}
int main(int argc,char *argv[])
{
	int loop_time = 0;
	memset(&g_cur_connect_wifi,0x0,sizeof(g_cur_connect_wifi));
	update_wifi_status(STATUS_INIT);
	nvram_set("wan_status","Disconnected");
	wisp_init_config();
	signal(SIG_APCLI_LINKDOWN, wisp_signal);
	signal(SIG_APCLI_LINKUP, wisp_signal);
	signal(SIG_WISP_DEBUG, wisp_signal);
	signal(SIGCHLD, SIG_IGN); 
	
	while(1){
		WDBG("loop time:%d,status:%d,count:%d\n",loop_time, g_wifi_status,g_wifi_node_count);

		if ( STATUS_AUTH_OK <= g_wifi_status ) {
			if (!nvram_match("wan_status", "Connected")){ 
				update_wifi_status(STATUS_AUTH_OK);
			}
			else {
				update_wifi_status(STATUS_CONNECTED_OK);
			}
		}
		
		if ( STATUS_CONNECTED_OK <= g_wifi_status ) {
			if (!check_internet()) {
				update_wifi_status(STATUS_CONNECTED_OK);
			}
			else {
				update_wifi_status(STATUS_INTERNET_OK);
				sleep(CHECK_NETWORK_INTERVAL);
				continue;
			}
		}

		if ( loop_time > 3) {
			sleep(10);
		}
		if ( 0 ==  loop_time % DIAGNOSE_INTERVAL )
			diagnose_network();

		if ( loop_time < 3 || 0 == (loop_time % SCAN_INTERVAL) ) {
			WDBG("dxt1107 begin scan ssid........\n");
			update_wifi_list();
			if ( g_wifi_node_count > 1) {
				check_wifi_list_change();
			}
			if ( (g_wifi_status < STATUS_CONNECTED_OK 
							&& 1 == g_wifi_node_count ) 
							|| g_wifi_node_count > 1) {
				update_wifi_status(STATUS_INIT);
				check_wisp_status();
			}
		}
		loop_time++;
		if ( loop_time > 0xffff )
			loop_time = 1;

	}

	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: EC600N-CN是一款高性能的无线路由器。它采用了先进的AC600技术,支持双频并行无线传输,提供了更稳定和更快的无线网络连接。它具有卓越的传输速度和稳定性,适用于各种应用场景。 EC600N-CN具备多种工作模式,包括无线路由器模式、无线AP模式、无线中继器模式、无线客户端模式和WISP模式。用户可以根据自己的需求选择不同的工作模式,以实现最佳的网络覆盖。 同时,EC600N-CN还配备了多个以太网口,用户可以通过有线方式连接多个设备,提供更稳定和更快速的网络连接。支持多种安全加密方式,如WEP、WPA/WPA2等,以保护网络的安全性。 EC600N-CN还提供了易于设置和管理的用户界面,用户可以通过Web界面进行快速设置,灵活控制和管理路由器的各项功能。另外,它还支持远程管理功能,用户可以通过互联网远程管理和控制路由器,提高操作的便捷性。 总之,EC600N-CN是一款功能强大、性能卓越的无线路由器,适用于各种场景下的无线网络覆盖需求。无论是家庭用户还是商业用户,都可以通过EC600N-CN实现高速稳定的无线网络连接,提升用户体验。 ### 回答2: EC600N-CN是一款由某个制造商生产的电子产品。它是一款具有创新设计和先进功能的设备。EC600N-CN的主要特点如下: 首先,EC600N-CN具有出色的性能。它配备了高速处理器和大容量内存,可以快速运行各种应用程序和多媒体内容。无论是处理办公任务、浏览网页还是享受高清视频,EC600N-CN都能提供流畅的体验。 其次,EC600N-CN拥有丰富的连接选项。它支持Wi-Fi和蓝牙等无线连接技术,可以轻松与其他设备进行数据传输和共享。此外,它还具备USB和HDMI接口,方便用户连接外部设备如鼠标、键盘和显示器。 第三,EC600N-CN拥有出色的显示效果。它配备了高分辨率和宽屏设计的显示屏,能够呈现更加清晰、生动的图像和视频。此外,EC600N-CN还采用了先进的显示技术,如IPS或AMOLED,提供更宽广的可视角度和更高的色彩饱和度。 最后,EC600N-CN还具备优秀的电池续航能力。它配备了高容量的电池,能够支持长时间的续航使用。这使得用户无需频繁充电,可以更加便利地使用EC600N-CN。 总之,EC600N-CN是一款功能强大、性能出色的电子产品。无论是在工作、学习还是娱乐时使用,它都能提供高效、舒适的体验。通过丰富的连接选项和清晰的显示效果,EC600N-CN可以满足用户的多种需求。而且,它的长久续航能力也能够确保用户持续的使用体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值