sdk-hwV1.3/external/eyesee-mpp/system/public/smartlink/smartlink.c

1135 lines
35 KiB
C
Executable File

/************************************************************************************************/
/* Copyright (C), 2001-2017, Allwinner Tech. Co., Ltd. */
/************************************************************************************************/
/**
* @file smartlink.c
* @brief
* @author id: guixing
* @version v0.1
* @date 2017-02-14
*/
/************************************************************************************************/
/* Include Files */
/************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <linux/socket.h>
#include <linux/if_ether.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <netinet/in.h>
#include "smartlink.h"
/************************************************************************************************/
/* Macros & Typedefs */
/************************************************************************************************/
#define WIFI_NAME "wlan0"
#define MAX_WIFI_CHN 196
#define ENABLE_ENCRYPT
#define CAL_CHECK_NUM 3
#define CRC8_INIT 0x0
#define CRC8_POLY 0x31
#define BROADCAST_ADDR "255.255.255.255"
#define BROADCAST_PORT 10001
#ifdef SMARTLINK_DEBUG
#define SL_DB_PRT(fmt, args...) \
do { \
printf("[FUN]%s [LINE]%d " fmt, __FUNCTION__, __LINE__, ##args); \
} while (0)
#else
#define SL_DB_PRT(fmt, args...) \
do {} while (0)
#endif
#ifdef SMARTLINK_ERROR
#define SL_ERR_PRT(fmt, args...) \
do { \
printf("\033[0;32;31m ERROR! [FUN]%s [LINE]%d " fmt "\033[0m", __FUNCTION__, __LINE__, ##args); \
} while (0)
#else
#define SL_ERR_PRT(fmt, args...) \
do {} while (0)
#endif
/************************************************************************************************/
/* Structure Declarations */
/************************************************************************************************/
typedef struct tag_DHD_PRIV_CMD_S {
char *buf;
int used_len;
int total_len;
} DHD_PRIV_CMD_S;
typedef struct tag_SSID_PWD_CALC_S {
char calc_cnt[64+256];
char ssid_pwd_val[CAL_CHECK_NUM][64+256];
char ssid[64];
char pwd[256];
char ssid_crc_cnt;
char ssid_crc_val[CAL_CHECK_NUM];
char ssid_crc;
char pwd_crc_cnt;
char pwd_crc_val[CAL_CHECK_NUM];
char pwd_crc;
} SSID_PWD_CALC_S;
/************************************************************************************************/
/* Global Variables */
/************************************************************************************************/
static unsigned short g_protocol = 0x0003;
static int g_smartlink_chn = 0;
static int g_ssid_pwd_size = 0;
static int g_ssid_size = 0;
static int g_pwd_size = 0;
static int g_pwd_recv_flag = 0;
static unsigned char g_ssid_pwd_val[192] = {0};
static unsigned char g_ssid_crc = 0;
static unsigned char g_pwd_crc = 0;
static unsigned char g_random_num = 0;
static unsigned char g_max_packet_num = 0;
SSID_PWD_CALC_S g_ssid_pwd_calc;
static short int g_wifi_support_chn[64] = {0};
/************************************************************************************************/
/* Function Declarations */
/************************************************************************************************/
/* None */
/************************************************************************************************/
/* Function Definitions */
/************************************************************************************************/
static unsigned char cal_crc8(const unsigned char* in, int num)
{
unsigned char crc = CRC8_INIT;
int i = 0, j = 0;
for(i = 0; i < num; i++ ) {
crc ^= in[i];
for(j = 0; j < 8; j++) {
if(crc & 0x1)
crc = (crc >> 1) ^ CRC8_POLY;
else
crc = crc >> 1;
}
}
return crc;
}
static int dhd_priv_ioctrl(const char *wifi_name, char *cmd, char *data)
{
struct ifreq ifr;
DHD_PRIV_CMD_S priv_cmd;
int ret = 0;
int ioctl_sock; /* socket for ioctl() use */
char buf[512]={0};
int len = 0, i = 0;
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
if (NULL == cmd) {
SL_ERR_PRT("Input cmd is NULL!\n");
return -1;
}
if (NULL == data) {
SL_ERR_PRT("Input data is NULL!\n");
return -1;
}
/* Setup 1. fill private cmd and data for ioctrl */
memset(buf, '\0', sizeof(buf));
len = 0;
for (i = 0; len < sizeof(buf) && cmd[i] != '\0'; i++, len++) {
buf[len] = cmd[i];
}
if (len == (sizeof(buf) - 1)) {
SL_ERR_PRT("Input cmd:%s too long > %d !\n", cmd, (int)sizeof(buf));
return -1;
} else {
buf[len] = ' ';
len++;
}
for (i = 0; len < sizeof(buf) && data[i] != '\0'; i++, len++) {
buf[len] = data[i];
}
buf[len] = ' ';
SL_DB_PRT("Do cmd:%s\n", buf);
/* Setup 2. Create private socket */
ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (ioctl_sock < 0) {
SL_ERR_PRT("Create socket(PF_INET,SOCK_DGRAM) fail! error[%d]:%s \n", errno, strerror(errno));
return -1;
}
memset(&ifr, 0, sizeof(ifr));
memset(&priv_cmd, 0, sizeof(priv_cmd));
strncpy(ifr.ifr_name, wifi_name, sizeof(ifr.ifr_name));
priv_cmd.buf = buf;
priv_cmd.used_len = sizeof(buf);
priv_cmd.total_len = sizeof(buf);
ifr.ifr_data = (char*)&priv_cmd;
/* Setup 3. Do dhd wifi private cmd. */
ret = 0;
if ((ret = ioctl(ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) {
SL_ERR_PRT("Do ioctl cmd:SIOCDEVPRIVATE fail! error[%d]:%s \n", errno, strerror(errno));
} else {
SL_DB_PRT("Do %s ret_len:%d, %d\n", buf, ret, strlen(buf));
strncpy(data, buf, strlen(buf));
}
close(ioctl_sock);
return ret;
}
static int set_wifi_channel(const char *wifi_name, int chn)
{
int ret = 0;
char data_buf[16];
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
if (chn < 1 || chn > MAX_WIFI_CHN) {
SL_ERR_PRT("Input chn:%d is error! 1<=chn<=%d is ok!\n", chn, MAX_WIFI_CHN);
return -1;
}
memset(data_buf, '\0', sizeof(data_buf));
if (chn < 10) {
data_buf[0] = '0' + chn;
} else if (chn >= 10 && chn < 100) {
data_buf[0] = '0' + chn/10;
data_buf[1] = '0' + chn%10;
} else if (chn >= 100 && chn < 1000) {
data_buf[0] = '0' + chn/100;
data_buf[1] = '0' + (chn%100)/10;
data_buf[2] = '0' + (chn%100)%10;
}
/*command:"channel" is differential in Linux 4.4 and Linux 3.10.[Linux4.4:"channel"][Linux3.10:"set_channel"] */
ret = dhd_priv_ioctrl(wifi_name, "channel", data_buf);
if (ret) {
SL_ERR_PRT("Do dhd_priv_ioctrl %s set_channel %s fail! ret:%d\n", wifi_name, data_buf, ret);
return -1;
}
return 0;
}
static int get_wifi_channel(const char *wifi_name, int *chn)
{
int ret = 0;
char data_buf[128];
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
memset(data_buf, '\0', sizeof(data_buf));
ret = dhd_priv_ioctrl(wifi_name, "get_channel", data_buf);
if (ret) {
SL_ERR_PRT("Do dhd_priv_ioctrl %s get_channel %s fail! ret:%d\n", wifi_name, data_buf, ret);
return -1;
}
sscanf(data_buf, "channel %d", chn);
SL_DB_PRT("data_buf:%s The current wifi channel:%d\n", data_buf, *chn);
return 0;
}
int set_wifi_monitor(const char *wifi_name, int monitor_enable)
{
int ret = 0;
char data_buf[16] = {0};
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
memset(data_buf, '\0', sizeof(data_buf));
if (monitor_enable) {
data_buf[0] = '1';
} else {
data_buf[0] = '0';
}
ret = dhd_priv_ioctrl(wifi_name, "monitor", data_buf);
if (ret) {
SL_ERR_PRT("Do dhd_priv_ioctrl %s monitor %s fail! ret:%d\n", wifi_name, data_buf, ret);
return -1;
}
return 0;
}
static int create_monitor_socket(const char *wifi_name)
{
struct ifreq ifr;
struct sockaddr_ll ll;
int fd = -1;
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
/* Setup 1. Create Raw socket */
fd = socket(PF_PACKET, SOCK_RAW, htons(g_protocol));
if (fd < 0) {
SL_ERR_PRT("Create PF_PACKET, SOCK_RAW, htons(0x%x)=0x%x fd:%d fail! error[%d]:%s\n",
g_protocol, htons(g_protocol), fd, errno, strerror(errno));
return -1;
} else {
SL_DB_PRT("Create socket PF_PACKET, SOCK_RAW, htons(0x%x)=0x%x fd:%d ok!\n",
g_protocol, htons(g_protocol), fd);
}
/* Setup 2. Setting net device, for socket. this is wifi wlan0. */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, wifi_name, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
SL_ERR_PRT("Do ioctl:SIOCGIFINDEX fail! fd:%d error[%d]:%s\n", fd, errno, strerror(errno));
close(fd);
return -1;
}
/* Setup 3. Bind wifi dev for monitor wriless packet. */
memset(&ll, 0, sizeof(ll));
ll.sll_family = PF_PACKET;
ll.sll_ifindex = ifr.ifr_ifindex;
ll.sll_protocol = htons(g_protocol);
if (bind(fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
SL_ERR_PRT("Do bind fd:%d fail! error[%d]:%s\n", fd, errno, strerror(errno));
close(fd);
return -1;
}
return fd;
}
static int delete_monitor_socket(int fd)
{
if (fd > 0) {
close(fd);
return 0;
} else {
SL_ERR_PRT("Input monitor socket fd:%d error!\n", fd);
return -1;
}
}
static void init_smartlink_data(void)
{
g_smartlink_chn = 0;
g_ssid_pwd_size = 0;
g_ssid_size = 0;
g_pwd_size = 0;
g_pwd_recv_flag = 0;
memset(g_ssid_pwd_val, 0, sizeof(g_ssid_pwd_val));
g_ssid_crc = 0;
g_pwd_crc = 0;
g_random_num = 0;
g_max_packet_num = 0;
memset(&g_ssid_pwd_calc, 0, sizeof(g_ssid_pwd_calc));
memset(&g_wifi_support_chn, 0, sizeof(g_wifi_support_chn));
/* In most country, 12,13,14 2.4G wifi channel is forbidden to using. */
g_wifi_support_chn[0] = 1;
g_wifi_support_chn[1] = 2;
g_wifi_support_chn[2] = 3;
g_wifi_support_chn[3] = 4;
g_wifi_support_chn[4] = 5;
g_wifi_support_chn[5] = 6;
g_wifi_support_chn[6] = 7;
g_wifi_support_chn[7] = 8;
g_wifi_support_chn[8] = 9;
g_wifi_support_chn[9] = 10;
g_wifi_support_chn[10] = 11;
/* In china, same 5G wifi channel is used. */
g_wifi_support_chn[11] = 36;
g_wifi_support_chn[12] = 40;
g_wifi_support_chn[13] = 44;
g_wifi_support_chn[14] = 48;
g_wifi_support_chn[15] = 149;
g_wifi_support_chn[16] = 153;
g_wifi_support_chn[17] = 157;
g_wifi_support_chn[18] = 161;
g_wifi_support_chn[19] = 165;
g_wifi_support_chn[20] = 0;
g_wifi_support_chn[21] = 0;
}
static int parser_smartlink_data(const unsigned char *data, int len, unsigned char *da_mac)
{
int ret = 0;
int cnt = 0, tmp = 0;
unsigned char pack_num = 0;
unsigned char crc = 0;
if (NULL == data) {
SL_ERR_PRT("Input data is NULL!\n");
return -1;
}
/*if not a Data-packet discare it*/
if(data[0] != 0x88){
return -1;
}
if (len >= 188 || len <= 36) {
return -1;
}
memset(da_mac, 0, 6);
/*multicase_head could in address1[4~9] or adress3[16~21] */
if(0x01 == data[16] && 0x00 == data[17] && 0x5e == data[18]){
for (cnt = 0; cnt < 6; cnt++) {
da_mac[cnt] = data[16+cnt];
}
}
else if (0x01 == data[4] && 0x00 == data[5] && 0x5e == data[6]) {
for (cnt = 0; cnt < 6; cnt++) {
da_mac[cnt] = data[4+cnt];
}
}
else {
return -1;
}
/* Check data_num : (1<= num <=127) */
pack_num = da_mac[3] & 0x7f;
if (pack_num > 128) {
//printf(" pack_num error! num:%d \n\n", pack_num);
return -1;
}
if (g_max_packet_num > 6 && pack_num > g_max_packet_num) {
//printf(" pack_num:%d > max_pack_num:%d error! \n\n", pack_num, g_max_packet_num);
return -1;
}
/* calculate the packt crc, and check */
if (pack_num < 5) {
crc = cal_crc8(&da_mac[4], 1);
if (crc != da_mac[5])
return -1;
}
/* parser smartlink data */
switch (pack_num) {
case 1:
if (da_mac[4] > MAX_WIFI_CHN) {
return -1;
}
break;
case 2:
if (da_mac[4] > 192) {
return -1;
}
g_ssid_pwd_size = da_mac[4];
if (g_pwd_recv_flag) {
g_ssid_size = g_ssid_pwd_size - g_pwd_size;
}
g_max_packet_num = 4 + g_ssid_pwd_size/2 + g_ssid_pwd_size%2 + 1;
break;
case 3:
g_pwd_size = da_mac[4];
g_pwd_recv_flag = 1;
if (g_ssid_pwd_size > 0) {
g_ssid_size = g_ssid_pwd_size - g_pwd_size;
}
break;
case 4:
g_random_num = da_mac[4];
break;
default:
if (g_max_packet_num > 6 && pack_num == g_max_packet_num) {
g_pwd_crc = da_mac[4];
g_ssid_crc = da_mac[5];
} else {
tmp = (pack_num-5)*2;
if (tmp >= sizeof(g_ssid_pwd_val)) {
return -1;
}
g_ssid_pwd_val[tmp] = da_mac[4];
g_ssid_pwd_val[tmp+1] = da_mac[5];
}
break;
}
return 0;
}
static int parser_smartlink_data_debug(unsigned char *data, int len, char *da_mac)
{
int ret = 0;
unsigned char crc = 0;
if (NULL == data) {
SL_ERR_PRT("Input data is NULL!\n");
return -1;
}
memset(da_mac, 0, 6);
if (len >= 128 || len <= 32) {
return -1;
}
// TODO: Get MAC:DA from 802.2 SNAP packt head.
int i = 0;
unsigned char pack_num = 0;
for (i = 0; i < (len - 24); i++) {
if (0x01 == data[i] && 0x00 == data[i+1] && 0x5e == data[i+2]) {
printf(" [%X:%X:%X] ", data[i], data[i+1], data[i+2]);
/* Check data_num is ok ? (1<= num <=127) */
pack_num = data[i+3] & 0x7f;
if (pack_num > 128) {
printf(" pack_num error! num:%d \n\n", pack_num);
return -1;
}
if (g_max_packet_num > 6 && pack_num > g_max_packet_num) {
printf(" pack_num:%d > max_pack_num:%d error! \n\n", pack_num, g_max_packet_num);
return -1;
}
/* calculate the packt crc. */
crc = cal_crc8(&data[i+4], 1);
switch (pack_num) {
case 1:
printf(" Cnt:%d channel :%d CRC:%d-%d ", pack_num, data[i+4], data[i+5], crc);
break;
case 2:
printf(" Cnt:%d pwd+ssid:%d CRC:%d-%d ", pack_num, data[i+4], data[i+5], crc);
break;
case 3:
printf(" Cnt:%d pwd size:%d CRC:%d-%d ", pack_num, data[i+4], data[i+5], crc);
break;
case 4:
printf(" Cnt:%d randome :%d CRC:%d-%d ", pack_num, data[i+4], data[i+5], crc);
break;
default:
if (g_max_packet_num > 6 && pack_num == g_max_packet_num) {
printf(" Cnt:%d pwd_crc:%d ssid_crc:%d ", pack_num, data[i+4], data[i+5]);
} else {
printf(" Cnt:%d data:\'%c\' date:\'%c\' ", pack_num, data[i+4], data[i+5]);
}
break;
}
i += 5;
len = i + 24 + 12; /////////for testing!!!!!!!
} else {
printf("%02x ", data[i]);
}
}
return 0;
}
static int check_receive_result(SMARTLINK_AP_S *ap_info)
{
int i = 0;
unsigned char crc = 0;
if (NULL == ap_info) {
SL_ERR_PRT("Input ap_info is NULL!\n");
return -1;
}
if (g_smartlink_chn < 1 || g_smartlink_chn > MAX_WIFI_CHN) {
return -1;
}
if (0 == g_random_num || 0xff == g_random_num) {
return -1;
}
if (0 == g_max_packet_num) {
return -1;
}
if (g_pwd_recv_flag) {
if (g_ssid_pwd_size != (g_ssid_size + g_pwd_size))
return -1;
} else {
return -1;
}
for (i = 0; i < g_ssid_pwd_size; i++) {
if (0 == g_ssid_pwd_val[i] || 0xff == g_ssid_pwd_val[i]) {
return -1;
}
}
if (g_pwd_size > 0) {
crc = cal_crc8(g_ssid_pwd_val, g_pwd_size);
if (crc != g_pwd_crc) {
return -1;
}
}
crc = cal_crc8(&g_ssid_pwd_val[g_pwd_size], g_ssid_size);
if (crc != g_ssid_crc) {
return -1;
}
for (i = 0; i < g_pwd_size; i++) {
ap_info->psswd[i] = g_ssid_pwd_val[i];
}
for (i = 0; i < g_ssid_size; i++) {
ap_info->ssid[i] = g_ssid_pwd_val[g_pwd_size+i];
}
ap_info->random_num = g_random_num;
printf("[FUN]:%s [LINE]:%d wifi_chn:%d pwd_ssid_size:%d pwd_size:%d random:%d ssid:%s pwd:%s ssid_crc:%d pwd_crc:%d max_pack:%d\n", __func__, __LINE__,
g_smartlink_chn, g_ssid_pwd_size, g_pwd_size, g_random_num, ap_info->ssid, ap_info->psswd, g_ssid_crc, g_pwd_crc, g_max_packet_num);
return 0;
}
int lock_smartlink_wifi_chn(const char *wifi_name, int lock_time_out, int chn_parser_time)
{
int ret = 0, chn_cnt = 0, tmp_chn = 0;
int wifi_chn = 0, fd = 0;
int recv_chn_cnt[64] = {0};
int lock_flag = 0, use_time_ms = 0, lock_loop = 0;
char crc = 0;
struct timeval parser_start_tv, chn_start_tv, tmp_tv;
fd_set inputfs, rfds;
int res = 0, res2 = 0, chn_loop = 0;
unsigned char buf[2300] = {0};
unsigned char da_mac[6] = {0};
char multicase_head[3] = {0x01,0x00,0x5e};
struct sockaddr_ll ll;
socklen_t fromlen;
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
if (lock_time_out < (chn_parser_time * 32) || chn_parser_time < 10) {
SL_ERR_PRT("Input lock_time_out chn_parser_time error!\n");
return -1;
}
init_smartlink_data();
memset(recv_chn_cnt, 0, sizeof(recv_chn_cnt));
gettimeofday(&parser_start_tv, NULL);
lock_flag = 0;
lock_loop = 8888888;
while (lock_loop--) {
for (chn_cnt = 0; 0 != g_wifi_support_chn[chn_cnt]; chn_cnt++) {
/* Setting wifi channel, for loop all wifi channel. */
ret = set_wifi_channel(wifi_name, g_wifi_support_chn[chn_cnt]);
if (ret) {
SL_ERR_PRT("Do set_wifi_channel fail! ret:%d\n", ret);
continue;
}
//usleep(1000);
/* Read current wifi channel data, for make sure send wifi channel. */
fd = create_monitor_socket(wifi_name);
if (fd <= 0) {
SL_ERR_PRT("Do create_monitor_socket fail! ret:%d\n", fd);
return -1;
}
chn_loop = 0;
gettimeofday(&chn_start_tv, NULL);
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/*start receive and analyze data*/
memset(&ll, 0, sizeof(ll));
while (1) {
inputfs = rfds;
tmp_tv.tv_sec = 0;
tmp_tv.tv_usec = chn_parser_time * 1000;
ret = select(fd+1, &inputfs, (fd_set *)0, (fd_set *)0, &tmp_tv);
if (0 == ret) {
printf ("[FUN]:%s [LINE]:%d ==>> wifi_chn:%d recv time out!\n",
__func__,__LINE__, g_wifi_support_chn[chn_cnt]);
//continue;
} else if (ret < 0) {
printf ("[FUN]:%s [LINE]:%d ==>> wifi_chn:%d recv error!\n",
__func__,__LINE__, g_wifi_support_chn[chn_cnt]);
//continue;
} else {
fromlen = sizeof(ll);
res = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&ll, &fromlen);
if (res < 0) {
SL_ERR_PRT("Do recvfrom fail! fd:%d res:%d error[%d]:%s\n", fd, res, errno, strerror(errno));
} else {
ret = parser_smartlink_data(buf, res, da_mac);
if (0 == ret) {
/* Calculate every recver chn data num. */
recv_chn_cnt[chn_cnt] += 1;
/* if is NO. 1 packet, and wifi_chn is make sure, so find wifi_chn */
if (1 == (da_mac[3] & 0x7f) && da_mac[4] > 0 && recv_chn_cnt[chn_cnt] > 3) {
g_smartlink_chn = da_mac[4];
printf("[FUN]:%s [LINE]:%d I finded smartlink channel:%d !\n",
__func__, __LINE__, g_smartlink_chn);
delete_monitor_socket(fd);
return 0;
}
/* If receive right data, just loop twice channel lock test. */
if (0 == lock_flag && recv_chn_cnt[chn_cnt] > 3) {
printf("[FUN]:%s [LINE]:%d Recver right data, just loop Twice again!!! chn_cnt:%d recv_chn_cnt:%d\n",
__func__, __LINE__, chn_cnt, recv_chn_cnt[chn_cnt]);
lock_flag = 1;
lock_loop = 1;
chn_cnt = 31;
break;
}
}
}
}
/*check timeout*/
chn_loop++;
if (0 == chn_loop%3) {
gettimeofday(&tmp_tv, NULL);
use_time_ms = (tmp_tv.tv_sec - chn_start_tv.tv_sec) * 1000 +
(tmp_tv.tv_usec - chn_start_tv.tv_usec) / 1000;
if (use_time_ms > chn_parser_time) {
SL_DB_PRT("Currcut will change chn:%d, chn_parser_time:%d use_time %dms loop:%d\n",
g_wifi_support_chn[chn_cnt], chn_parser_time, use_time_ms, chn_loop);
break;
}
}
}//end of while(1) : parser every channle
ret = delete_monitor_socket(fd);
if (ret) {
SL_ERR_PRT("Do delete_monitor_socket fail! ret:%d\n", ret);
return -1;
}
}
/* Lock smartlink channel operation time out! So don't finded smartlink channel return error! */
if (0 == lock_flag) {
gettimeofday(&tmp_tv, NULL);
use_time_ms = (tmp_tv.tv_sec - parser_start_tv.tv_sec) * 1000 +
(tmp_tv.tv_usec - parser_start_tv.tv_usec) / 1000;
if (use_time_ms > lock_time_out && 0 == lock_flag) {
printf("Lock smartlink channel time out! lock_time:%dms use_time %dms lock_loop:%d\n",
lock_time_out, use_time_ms, lock_loop);
return -1;
}
}
}//end of while(lock_loop)
/* If ios and same andriod system don't get wifi channel, so we will check witch smartlink channel is. */
if (g_smartlink_chn <= 0) {
/* find max packet in wifi channel */
res = 0;
for (chn_cnt = 0; 0 != g_wifi_support_chn[chn_cnt]; chn_cnt++) {
if (recv_chn_cnt[chn_cnt] > res) {
res = recv_chn_cnt[chn_cnt];
tmp_chn = g_wifi_support_chn[chn_cnt];
}
}
/* check again in most pack_num wifi channel */
if(res > 1 && res <30){
printf("[FUN]:%s [LINE]:%d Try to monitor channel:%d, please wait 3 second!\n",
__func__, __LINE__,tmp_chn);
/* Setting wifi channel, for loop all wifi channel. */
ret = set_wifi_channel(wifi_name, tmp_chn);
if (ret) {
SL_ERR_PRT("Do set_wifi_channel fail! ret:%d\n", ret);
}
/* Read current wifi channel data, for make sure send wifi channel. */
fd = create_monitor_socket(wifi_name);
if (fd <= 0) {
SL_ERR_PRT("Do create_monitor_socket fail! ret:%d\n", fd);
return -1;
}
memset(&ll, 0, sizeof(ll));
chn_loop = 0;
chn_parser_time = 3000;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
gettimeofday(&chn_start_tv, NULL);
while(1){
inputfs = rfds;
tmp_tv.tv_sec = 0;
tmp_tv.tv_usec = 500 * 1000;
ret = select(fd+1, &inputfs, (fd_set *)0, (fd_set *)0, &tmp_tv);
if (0 == ret) {
printf ("[FUN]:%s [LINE]:%d ==>> wifi_chn:%d recv time out!\n",
__func__,__LINE__,tmp_chn);
//continue;
} else if (ret < 0) {
printf ("[FUN]:%s [LINE]:%d ==>> wifi_chn:%d recv error!\n",
__func__,__LINE__,tmp_chn);
//continue;
} else{
fromlen = sizeof(ll);
res2 = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&ll, &fromlen);
if (res2 < 0) {
SL_ERR_PRT("Do recvfrom fail! fd:%d res2:%d error[%d]:%s\n", fd, res2, errno, strerror(errno));
}
ret = parser_smartlink_data(buf, res2, da_mac);
if (0 == ret) {
/* Calculate every recver chn data num. */
res += 1;
if(res >=30){
break;
}
}
}
/*check timeout*/
chn_loop++;
if (0 == chn_loop%5) {
gettimeofday(&tmp_tv, NULL);
use_time_ms = (tmp_tv.tv_sec - chn_start_tv.tv_sec) * 1000 +
(tmp_tv.tv_usec - chn_start_tv.tv_usec) / 1000;
if (use_time_ms > chn_parser_time) {
SL_DB_PRT("Currcut will change chn:%d, chn_parser_time:%d use_time %dms loop:%d\n",
g_wifi_support_chn[chn_cnt], chn_parser_time, use_time_ms, chn_loop);
break;
}
}
}//end of while(1)
delete_monitor_socket(fd);
}
if (res >= 30) {
g_smartlink_chn = tmp_chn;
printf("[FUN]:%s [LINE]:%d I finded g_smartlink_chn:%d tmp_chn:%d res:%d\n",
__func__, __LINE__, g_smartlink_chn, tmp_chn, res);
} else {
printf("[FUN]:%s [LINE]:%d Don't finded smartlink chn! res:%d\n",
__func__, __LINE__, res);
return -1;
}
}
return 0;
}
static int decrypt_smartlink_data(SMARTLINK_AP_S *ap_info)
{
int i = 0, tmp = 0;
if (NULL == ap_info) {
SL_ERR_PRT("Input ap_info is NULL!\n");
return -1;
}
if (0 == g_random_num || 0xff == g_random_num) {
SL_ERR_PRT("g_random_num:%d is no recieve!\n", g_random_num);
return -1;
}
tmp = g_random_num + g_ssid_pwd_size;
for (i = 0; i < g_ssid_size; i++) {
ap_info->ssid[i] = ap_info->ssid[i] ^ tmp;
}
for (i = 0; i < g_pwd_size; i++) {
ap_info->psswd[i] = ap_info->psswd[i] ^ tmp;
}
return 0;
}
int parser_smartlink_config(const char *wifi_name, int time_out, SMARTLINK_AP_S *ap_info)
{
int ret = 0, fd = 0;
int chn_cnt = 0, use_time_ms = 0;
struct timeval parser_start_tv, tmp_tv;
int res = 0;
unsigned char buf[2300] = {0};
unsigned char da_mac[6] = {0};
struct sockaddr_ll ll;
socklen_t fromlen;
fd_set inputfs, rfds;
if (NULL == wifi_name) {
SL_ERR_PRT("Input wifi_name is NULL!\n");
return -1;
}
if (NULL == ap_info) {
SL_ERR_PRT("Input ap_info is NULL!\n");
return -1;
}
if (time_out < 100) {
SL_ERR_PRT("Input time_out:%d too little!\n", time_out);
return -1;
}
/* Step 1. Check wifi channel is locked? */
if (g_smartlink_chn <= 0 || g_smartlink_chn > MAX_WIFI_CHN) {
SL_ERR_PRT("Current smartlink wifi channle:%d error!\n", g_smartlink_chn);
return -1;
}
/* Step 2. Set right lock wifi channel. */
ret = set_wifi_channel(wifi_name, g_smartlink_chn);
if (ret) {
SL_ERR_PRT("Do set_wifi_channel fail! ret:%d\n", ret);
return -1;
}
usleep(1000);
/* Step 3. Parser smartlink config data packet. */
gettimeofday(&parser_start_tv, NULL);
/* Read current wifi channel data, for make sure send wifi channel. */
fd = create_monitor_socket(wifi_name);
if (fd <= 0) {
SL_ERR_PRT("Do create_monitor_socket fail! ret:%d\n", fd);
return -1;
}
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
while (1) {
inputfs = rfds;
tmp_tv.tv_sec = 0;
tmp_tv.tv_usec = 400 * 1000;
ret = select(fd+1, &inputfs, (fd_set *)0, (fd_set *)0, &tmp_tv);
if (0 == ret) {
printf ("[FUN]:%s [LINE]:%d ==>> wifi_chn:%d recv time out!\n",
__func__,__LINE__, g_wifi_support_chn[chn_cnt]);
//continue;
} else if (ret < 0) {
printf ("[FUN]:%s [LINE]:%d ==>> wifi_chn:%d recv error!\n",
__func__,__LINE__, g_wifi_support_chn[chn_cnt]);
//continue;
} else {
memset(&ll, 0, sizeof(ll));
fromlen = sizeof(ll);
res = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&ll, &fromlen);
if (res < 0) {
SL_ERR_PRT("Do recvfrom fail! fd:%d res:%d error[%d]:%s\n", fd, res, errno, strerror(errno));
} else {
ret = parser_smartlink_data(buf, res, da_mac);
if (0 == ret) {
/* Calculate every recver chn data num. */
ret = check_receive_result(ap_info);
if (0 == ret) {
#ifdef ENABLE_ENCRYPT
ret = decrypt_smartlink_data(ap_info);
if (ret) {
SL_ERR_PRT("Do decrypt_smartlink_data fail! ret:%d\n", ret);
break;
}
#endif
printf("[FUN]:%s [LINE]:%d Receive smarlink complete! ssid:%s psswd:%s random:%d\n",
__func__, __LINE__, ap_info->ssid, ap_info->psswd, ap_info->random_num);
break;
}
}
}
}
/* Calculate parser smartlink data time out for return this function. */
gettimeofday(&tmp_tv, NULL);
use_time_ms = (tmp_tv.tv_sec - parser_start_tv.tv_sec) * 1000 +
(tmp_tv.tv_usec - parser_start_tv.tv_usec) / 1000;
if (use_time_ms > time_out) {
printf("Parser smartlink config data packet time out! time_out:%dms use_time %dms\n",
time_out, use_time_ms);
delete_monitor_socket(fd);
return -1;
}
}
ret = delete_monitor_socket(fd);
if (ret) {
SL_ERR_PRT("Do delete_monitor_socket fail! ret:%d\n", ret);
return -1;
}
return 0;
}
int send_broadcast_val(unsigned char random_num)
{
int ret = 0, num = 0;
int fd = -1, opt = 1;
struct sockaddr_in server; /* server's address information */
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
SL_ERR_PRT("Create socket SOCK_DGRAM fd:%d fail! error[%d]:%s\n", fd, errno, strerror(errno));
return -1;
}
opt = 1;
ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (ret < 0) {
SL_ERR_PRT("setsockopt SO_REUSEADDR fd:%d fail! ret:%d error[%d]:%s\n", fd, ret, errno, strerror(errno));
goto cleanup;
}
opt = 1;
ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
if (ret < 0) {
SL_ERR_PRT("setsockopt SO_BROADCAST fd:%d fail! ret:%d error[%d]:%s\n", fd, ret, errno, strerror(errno));
goto cleanup;
}
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(BROADCAST_PORT);
server.sin_addr.s_addr = INADDR_BROADCAST;
socklen_t len;
len = sizeof(struct sockaddr_in);
num = 10;
while (num--) {
ret = sendto(fd, &random_num, sizeof(random_num), 0, (struct sockaddr *)&server, len);
if (ret < 0) {
SL_ERR_PRT("sendto random_num fd:%d fail! ret:%d error[%d]:%s\n", fd, ret, errno, strerror(errno));
}
usleep(100 * 1000);
}
ret = 0;
cleanup:
if (fd > 0) {
close(fd);
}
return ret;
}
#if 0
int main_test()
{
int ret = 0, cnt = 0;
SMARTLINK_AP_S ap_info;
ret = set_wifi_monitor(WIFI_NAME, 1);
if (ret) {
SL_ERR_PRT("Do set_wifi_monitor fail! ret:%d\n", ret);
return -1;
}
ret = lock_smartlink_wifi_chn(WIFI_NAME, 60*1000, 100);
if (ret) {
SL_ERR_PRT("Do lock_smartlink_wifi_chn fail! ret:%d\n", ret);
goto main_exit;
}
printf("\n\n");
memset(&ap_info, 0, sizeof(ap_info));
ret = parser_smartlink_config(WIFI_NAME, 20*1000, &ap_info);
if (ret) {
SL_ERR_PRT("Do parser_smartlink_config fail! ret:%d\n", ret);
goto main_exit;
}
main_exit:
ret = set_wifi_monitor(WIFI_NAME, 0);
if (ret) {
SL_ERR_PRT("Do set_wifi_monitor fail! ret:%d\n", ret);
return -1;
}
return 0;
}
#endif