mirror of
https://github.com/drasko/open-ameba.git
synced 2024-12-28 00:55:19 +00:00
1076 lines
27 KiB
C
1076 lines
27 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "main.h"
|
|
#include "udp.h"
|
|
#include <sockets.h>
|
|
#if LWIP_SOCKET
|
|
#include <lwip_netconf.h>
|
|
#include <osdep_service.h>
|
|
#include "platform_stdlib.h"
|
|
#include "wifi_simple_config_parser.h"
|
|
#include "wifi_simple_config.h"
|
|
|
|
#if CONFIG_EXAMPLE_UART_ATCMD
|
|
#include "at_cmd/atcmd_wifi.h"
|
|
#endif
|
|
|
|
#define STACKSIZE 512
|
|
#define LEAVE_ACK_EARLY 0
|
|
|
|
#if (CONFIG_LWIP_LAYER == 0)
|
|
extern u32 _ntohl(u32 n);
|
|
#endif
|
|
|
|
#if CONFIG_WLAN
|
|
#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
|
|
#include "wifi/wifi_conf.h"
|
|
int is_promisc_callback_unlock = 0;
|
|
static int is_fixed_channel;
|
|
int fixed_channel_num;
|
|
unsigned char g_ssid[32];
|
|
int g_ssid_len;
|
|
|
|
extern int promisc_get_fixed_channel( void *, u8 *, int* );
|
|
struct rtk_test_sc;
|
|
|
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
#include "arch/bpstruct.h"
|
|
#endif
|
|
|
|
// support scan list function from APP, comment by default
|
|
//#define SC_SCAN_SUPPORT
|
|
|
|
PACK_STRUCT_BEGIN
|
|
struct ack_msg {
|
|
PACK_STRUCT_FIELD(u8_t flag);
|
|
PACK_STRUCT_FIELD(u16_t length);
|
|
PACK_STRUCT_FIELD(u8_t smac[6]);
|
|
PACK_STRUCT_FIELD(u8_t status);
|
|
PACK_STRUCT_FIELD(u16_t device_type);
|
|
PACK_STRUCT_FIELD(u32_t device_ip);
|
|
PACK_STRUCT_FIELD(u8_t device_name[64]);
|
|
}__attribute__((packed)); // PACK_STRUCT_STRUCT;
|
|
PACK_STRUCT_END
|
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
|
#include "arch/epstruct.h"
|
|
#endif
|
|
|
|
|
|
|
|
#define MULCAST_PORT (8864)
|
|
|
|
#define SCAN_BUFFER_LENGTH (1024)
|
|
|
|
#ifndef WLAN0_NAME
|
|
#define WLAN0_NAME "wlan0"
|
|
#endif
|
|
#define JOIN_SIMPLE_CONFIG (uint32_t)(1 << 8)
|
|
extern uint32_t rtw_join_status;
|
|
char simple_config_terminate = 0;
|
|
|
|
int simple_config_result;
|
|
static struct ack_msg *ack_content;
|
|
struct rtk_test_sc *backup_sc_ctx;
|
|
extern struct netif xnetif[NET_IF_NUM];
|
|
|
|
// listen scan command and ACK
|
|
#ifdef SC_SCAN_SUPPORT
|
|
|
|
static int pin_enable = 0;
|
|
static int scan_start = 0;
|
|
|
|
#ifdef RTW_PACK_STRUCT_USE_INCLUDES
|
|
#include "pack_begin.h"
|
|
#endif
|
|
RTW_PACK_STRUCT_BEGIN
|
|
struct ack_msg_scan {
|
|
u8_t flag;
|
|
u16_t length;
|
|
u8_t smac[6];
|
|
u8_t status;
|
|
u16_t device_type;
|
|
u32_t device_ip;
|
|
u8_t device_name[64];
|
|
u8_t pin_enabled;
|
|
}
|
|
RTW_PACK_STRUCT_STRUCT;
|
|
RTW_PACK_STRUCT_END
|
|
#ifdef RTW_PACK_STRUCT_USE_INCLUDES
|
|
#include "pack_end.h"
|
|
#endif
|
|
|
|
static void set_device_name(char *device_name)
|
|
{
|
|
int pos = 0;
|
|
memcpy(device_name, "ameba_", 6);
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
sprintf(device_name + 6 + pos, "%02x", xnetif[0].hwaddr[i + 3]);
|
|
pos += 2;
|
|
if(i != 2)
|
|
device_name[6 + pos++] = ':';
|
|
}
|
|
return;
|
|
}
|
|
void SC_scan_thread(void *para)
|
|
{
|
|
int sockfd_scan;
|
|
struct sockaddr_in device_addr;
|
|
unsigned char packet[256];
|
|
struct sockaddr from;
|
|
struct sockaddr_in *from_sin = (struct sockaddr_in*) &from;
|
|
socklen_t fromLen = sizeof(from);
|
|
struct ack_msg_scan ack_msg;
|
|
|
|
#ifdef RTW_PACK_STRUCT_USE_INCLUDES
|
|
#include "pack_begin.h"
|
|
#endif
|
|
RTW_PACK_STRUCT_BEGIN
|
|
struct scan_msg{
|
|
unsigned char flag;
|
|
unsigned short length;
|
|
unsigned char sec_level;
|
|
unsigned char nonce[64];
|
|
unsigned char digest[16];
|
|
unsigned char smac[6];
|
|
unsigned short device_type;
|
|
};
|
|
RTW_PACK_STRUCT_STRUCT;
|
|
RTW_PACK_STRUCT_END
|
|
#ifdef RTW_PACK_STRUCT_USE_INCLUDES
|
|
#include "pack_end.h"
|
|
#endif
|
|
|
|
struct scan_msg *pMsg;
|
|
|
|
if ((sockfd_scan = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
|
printf("SC scan socket error\n");
|
|
return;
|
|
}
|
|
memset(&device_addr, 0, sizeof(struct sockaddr_in));
|
|
device_addr.sin_family = AF_INET;
|
|
device_addr.sin_port = htons(18864);
|
|
device_addr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if (bind(sockfd_scan, (struct sockaddr *)&device_addr, sizeof(struct sockaddr)) == -1)
|
|
{
|
|
printf("SC scan bind error\n");
|
|
close(sockfd_scan);
|
|
return;
|
|
}
|
|
memset(packet, 0, sizeof(packet));
|
|
|
|
// for now, no checking for the validity of received data, wf, 0225
|
|
while(1)
|
|
{
|
|
if((recvfrom(sockfd_scan, &packet, sizeof(packet), MSG_DONTWAIT, &from, &fromLen)) >= 0) {
|
|
uint16_t from_port = ntohs(from_sin->sin_port);
|
|
//printf("SC_scan: recv %d bytes from %d.%d.%d.%d:%d\n",packetLen, ip[0], ip[1], ip[2], ip[3], from_port);
|
|
|
|
from_sin->sin_port = htons(8864);
|
|
// send ACK for scan
|
|
pMsg = (struct scan_msg *)packet;
|
|
if(pMsg->flag == 0x00) // scan flag
|
|
{
|
|
ack_msg.flag = 0x21;
|
|
ack_msg.length = sizeof(struct ack_msg_scan);
|
|
ack_msg.status = 1;
|
|
memcpy(ack_msg.smac, xnetif[0].hwaddr, 6);
|
|
|
|
ack_msg.device_type = 0;
|
|
ack_msg.device_ip = xnetif[0].ip_addr.addr;
|
|
memset(ack_msg.device_name, 0, 64);
|
|
set_device_name((char*)ack_msg.device_name);
|
|
// set the device_name to: ameba_xxxxxx(last 3 bytes of MAC)
|
|
ack_msg.pin_enabled = pin_enable;
|
|
for(int i = 0; i < 3;i++)
|
|
{
|
|
int ret = sendto(sockfd_scan,(unsigned char *)&ack_msg,sizeof(struct ack_msg_scan),0,(struct sockaddr *)&from, fromLen);
|
|
if(ret < 0)
|
|
printf("send ACK for scan fail\n");
|
|
//else
|
|
//printf("send %d bytes of ACK to scan\n", ret);
|
|
}
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
vTaskDelay(500);
|
|
}
|
|
}
|
|
|
|
void SC_listen_ACK_scan()
|
|
{
|
|
if(xTaskCreate(SC_scan_thread, ((const char*)"SC_scan_thread"), 512, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
|
|
printf("%s xTaskCreate(SC_scan_thread) failed\n", __FUNCTION__);
|
|
}
|
|
|
|
#endif
|
|
|
|
void SC_set_ack_content()
|
|
{
|
|
memset(ack_content, 0, sizeof(struct ack_msg));
|
|
ack_content->flag = 0x20;
|
|
ack_content->length = htons(sizeof(struct ack_msg)-3);
|
|
memcpy(ack_content->smac, xnetif[0].hwaddr, 6);
|
|
ack_content->status = 0;
|
|
ack_content->device_type = 0;
|
|
ack_content->device_ip = xnetif[0].ip_addr.addr;
|
|
memset(ack_content->device_name, 0, 64);
|
|
}
|
|
|
|
int SC_send_simple_config_ack(u8 round)
|
|
{
|
|
#if CONFIG_LWIP_LAYER
|
|
int ack_transmit_round, ack_num_each_sec;
|
|
int ack_socket;
|
|
//int sended_data = 0;
|
|
struct sockaddr_in to_addr;
|
|
#if LEAVE_ACK_EARLY
|
|
u8 check_phone_ack = 0;
|
|
#endif
|
|
SC_set_ack_content();
|
|
|
|
ack_socket = socket(PF_INET, SOCK_DGRAM, IP_PROTO_UDP);
|
|
if (ack_socket == -1) {
|
|
return -1;
|
|
}
|
|
#if LEAVE_ACK_EARLY
|
|
else {
|
|
struct sockaddr_in bindAddr;
|
|
bindAddr.sin_family = AF_INET;
|
|
bindAddr.sin_port = htons(8864);
|
|
bindAddr.sin_addr.s_addr = INADDR_ANY;
|
|
if(bind(ack_socket, (struct sockaddr *) &bindAddr, sizeof(bindAddr)) == 0)
|
|
check_phone_ack = 1;
|
|
}
|
|
#endif
|
|
printf("Sending simple config ack\n");
|
|
FD_ZERO(&to_addr);
|
|
to_addr.sin_family = AF_INET;
|
|
to_addr.sin_port = htons(8864);
|
|
to_addr.sin_addr.s_addr = (backup_sc_ctx->ip_addr);
|
|
for (ack_transmit_round = 0;ack_transmit_round < round; ack_transmit_round++) {
|
|
for (ack_num_each_sec = 0;ack_num_each_sec < 20; ack_num_each_sec++) {
|
|
//sended_data =
|
|
sendto(ack_socket, (unsigned char *)ack_content, sizeof(struct ack_msg), 0, (struct sockaddr *) &to_addr, sizeof(struct sockaddr));
|
|
//printf("\r\nAlready send %d bytes data\n", sended_data);
|
|
vTaskDelay(50); /* delay 50 ms */
|
|
|
|
#if LEAVE_ACK_EARLY
|
|
if(check_phone_ack) {
|
|
unsigned char packet[100];
|
|
int packetLen;
|
|
struct sockaddr from;
|
|
struct sockaddr_in *from_sin = (struct sockaddr_in*) &from;
|
|
socklen_t fromLen = sizeof(from);
|
|
|
|
if((packetLen = recvfrom(ack_socket, &packet, sizeof(packet), MSG_DONTWAIT, &from, &fromLen)) >= 0) {
|
|
uint8_t *ip = (uint8_t *) &from_sin->sin_addr.s_addr;
|
|
uint16_t from_port = ntohs(from_sin->sin_port);
|
|
printf("recv %d bytes from %d.%d.%d.%d:%d at round=%d, num=%d\n",
|
|
packetLen, ip[0], ip[1], ip[2], ip[3], from_port,
|
|
ack_transmit_round, ack_num_each_sec);
|
|
goto leave_ack;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
leave_ack:
|
|
close(ack_socket);
|
|
#endif
|
|
|
|
#if CONFIG_INIC_CMD_RSP
|
|
extern unsigned int inic_sc_ip_addr;
|
|
inic_sc_ip_addr = backup_sc_ctx->ip_addr;
|
|
inic_c2h_wifi_info("ATWQ", RTW_SUCCESS);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int SC_check_and_show_connection_info(void)
|
|
{
|
|
rtw_wifi_setting_t setting;
|
|
int ret = -1;
|
|
|
|
#if CONFIG_LWIP_LAYER
|
|
/* If not rise priority, LwIP DHCP may timeout */
|
|
vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 3);
|
|
/* Start DHCP Client */
|
|
ret = LwIP_DHCP(0, DHCP_START);
|
|
vTaskPrioritySet(NULL, tskIDLE_PRIORITY + 1);
|
|
#endif
|
|
|
|
#if CONFIG_EXAMPLE_UART_ATCMD == 0
|
|
wifi_get_setting(WLAN0_NAME, &setting);
|
|
wifi_show_setting(WLAN0_NAME, &setting);
|
|
#endif
|
|
|
|
#if CONFIG_LWIP_LAYER
|
|
if (ret != DHCP_ADDRESS_ASSIGNED)
|
|
return SC_DHCP_FAIL;
|
|
else
|
|
#endif
|
|
return SC_SUCCESS;
|
|
}
|
|
|
|
static void check_and_set_security_in_connection(rtw_security_t security_mode, rtw_network_info_t *wifi)
|
|
{
|
|
|
|
if (security_mode == RTW_SECURITY_WPA2_AES_PSK) {
|
|
printf("wifi->security_type = RTW_SECURITY_WPA2_AES_PSK\n");
|
|
wifi->security_type = RTW_SECURITY_WPA2_AES_PSK;
|
|
} else if (security_mode == RTW_SECURITY_WEP_PSK) {
|
|
printf("wifi->security_type = RTW_SECURITY_WEP_PSK\n");
|
|
wifi->security_type = RTW_SECURITY_WEP_PSK;
|
|
wifi->key_id = 0;
|
|
} else if (security_mode == RTW_SECURITY_WPA_AES_PSK) {
|
|
printf("wifi->security_type = RTW_SECURITY_WPA_AES_PSK\n");
|
|
wifi->security_type = RTW_SECURITY_WPA_AES_PSK;
|
|
} else {
|
|
printf("wifi->security_type = RTW_SECURITY_OPEN\n");
|
|
wifi->security_type = RTW_SECURITY_OPEN;
|
|
}
|
|
}
|
|
|
|
int get_connection_info_from_profile(rtw_security_t security_mode, rtw_network_info_t *wifi)
|
|
{
|
|
|
|
printf("======= Connection Information =======\n");
|
|
check_and_set_security_in_connection(security_mode, wifi);
|
|
|
|
wifi->password = backup_sc_ctx->password;
|
|
wifi->password_len = (int)strlen((char const *)backup_sc_ctx->password);
|
|
|
|
/* 1.both scanned g_ssid and ssid from profile are null, return fail */
|
|
if ((0 == g_ssid_len) && (0 == strlen(backup_sc_ctx->ssid))) {
|
|
printf("no ssid info found, connect will fail\n");
|
|
return -1;
|
|
}
|
|
|
|
/* g_ssid and ssid from profile are same, enter connect and retry */
|
|
if (0 == strcmp(backup_sc_ctx->ssid, g_ssid)) {
|
|
wifi->ssid.len = strlen(backup_sc_ctx->ssid);
|
|
rtw_memcpy(wifi->ssid.val, backup_sc_ctx->ssid, wifi->ssid.len);
|
|
printf("using ssid from profile and scan result\n");
|
|
goto ssid_set_done;
|
|
}
|
|
|
|
/* if there is profile, but g_ssid and profile are different, using profile to connect and retry */
|
|
if (strlen(backup_sc_ctx->ssid) > 0) {
|
|
wifi->ssid.len = strlen(backup_sc_ctx->ssid);
|
|
rtw_memcpy(wifi->ssid.val, backup_sc_ctx->ssid, wifi->ssid.len);
|
|
printf("using ssid only from profile\n");
|
|
goto ssid_set_done;
|
|
|
|
}
|
|
|
|
/* if there is no profile but have scanned ssid, using g_ssid to connect and retry
|
|
(maybe ssid is right and password is wrong) */
|
|
if (g_ssid_len > 0) {
|
|
wifi->ssid.len = g_ssid_len;
|
|
rtw_memcpy(wifi->ssid.val, g_ssid, wifi->ssid.len);
|
|
printf("using ssid only from scan result\n");
|
|
goto ssid_set_done;
|
|
}
|
|
|
|
|
|
ssid_set_done:
|
|
|
|
|
|
if(wifi->security_type == RTW_SECURITY_WEP_PSK)
|
|
{
|
|
if(wifi->password_len == 10)
|
|
{
|
|
u32 p[5] = {0};
|
|
u8 pwd[6], i = 0;
|
|
sscanf((const char*)backup_sc_ctx->password, "%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4]);
|
|
for(i=0; i< 5; i++)
|
|
pwd[i] = (u8)p[i];
|
|
pwd[5] = '\0';
|
|
memset(backup_sc_ctx->password, 0, 65);
|
|
strcpy((char*)backup_sc_ctx->password, (char*)pwd);
|
|
wifi->password_len = 5;
|
|
}else if(wifi->password_len == 26){
|
|
u32 p[13] = {0};
|
|
u8 pwd[14], i = 0;
|
|
sscanf((const char*)backup_sc_ctx->password, "%02x%02x%02x%02x%02x%02x%02x"\
|
|
"%02x%02x%02x%02x%02x%02x", &p[0], &p[1], &p[2], &p[3], &p[4],\
|
|
&p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12]);
|
|
for(i=0; i< 13; i++)
|
|
pwd[i] = (u8)p[i];
|
|
pwd[13] = '\0';
|
|
memset(backup_sc_ctx->password, 0, 64);
|
|
strcpy((char*)backup_sc_ctx->password, (char*)pwd);
|
|
wifi->password_len = 13;
|
|
}
|
|
}
|
|
printf("wifi.password = %s\n", wifi->password);
|
|
printf("wifi.password_len = %d\n", wifi->password_len);
|
|
printf("wifi.ssid = %s\n", wifi->ssid.val);
|
|
printf("wifi.ssid_len = %d\n", wifi->ssid.len);
|
|
printf("wifi.channel = %d\n", fixed_channel_num);
|
|
printf("===== start to connect target AP =====\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma pack(1)
|
|
struct scan_with_ssid_result {
|
|
u8 len; /* len of a memory area store ap info */
|
|
u8 mac[ETH_ALEN];
|
|
int rssi;
|
|
u8 sec_mode;
|
|
u8 password_id;
|
|
u8 channel;
|
|
//char ssid[65];
|
|
};
|
|
|
|
|
|
struct sc_ap_info {
|
|
|
|
char *ssid;
|
|
int ssid_len;
|
|
|
|
};
|
|
|
|
|
|
|
|
rtw_security_t SC_translate_iw_security_mode(u8 security_type) {
|
|
|
|
rtw_security_t security_mode = RTW_SECURITY_UNKNOWN;
|
|
|
|
|
|
switch (security_type) {
|
|
case IW_ENCODE_ALG_NONE:
|
|
security_mode = RTW_SECURITY_OPEN;
|
|
break;
|
|
case IW_ENCODE_ALG_WEP:
|
|
security_mode = RTW_SECURITY_WEP_PSK;
|
|
break;
|
|
case IW_ENCODE_ALG_CCMP:
|
|
security_mode = RTW_SECURITY_WPA2_AES_PSK;
|
|
break;
|
|
default:
|
|
printf("error: security type not supported\n");
|
|
break;
|
|
};
|
|
|
|
return security_mode;
|
|
}
|
|
|
|
/*
|
|
|
|
scan buf format:
|
|
|
|
len mac rssi sec wps channel ssid
|
|
1B 6B 4B 1B 1B 1B (len - 14)B
|
|
|
|
*/
|
|
enum sc_result SC_parse_scan_result_and_connect(scan_buf_arg* scan_buf, rtw_network_info_t *wifi)
|
|
{
|
|
|
|
struct scan_with_ssid_result scan_result;
|
|
|
|
char *buf = scan_buf->buf;
|
|
int buf_len = scan_buf->buf_len;
|
|
char ssid[65];
|
|
int ssid_len = 0 ;
|
|
int parsed_len = 0;
|
|
u8 scan_channel = 0;
|
|
int i = 0;
|
|
int ret = 0;
|
|
u8 pscan_config = PSCAN_ENABLE | PSCAN_SIMPLE_CONFIG;
|
|
|
|
memset((void*)&scan_result, 0, sizeof(struct scan_with_ssid_result));
|
|
|
|
/* if wifi_is_connected_to_ap and we run here, ther will be hardfault(caused by auto reconnect) */
|
|
printf("Scan result got, start to connect AP with scanned bssid\n");
|
|
|
|
while (1) {
|
|
|
|
memcpy(&scan_result, buf, sizeof(struct scan_with_ssid_result));
|
|
/* len maybe 3*/
|
|
if (scan_result.len < sizeof(struct scan_with_ssid_result)) {
|
|
printf("length = %d, too small!\n",scan_result.len);
|
|
goto sc_connect_wifi_fail;
|
|
}
|
|
|
|
/* set ssid */
|
|
memset(ssid, 0, 65);
|
|
|
|
ssid_len = scan_result.len - sizeof(struct scan_with_ssid_result);
|
|
|
|
memcpy(ssid, buf + sizeof(struct scan_with_ssid_result), ssid_len);
|
|
|
|
/* run here means there is a match */
|
|
if (ssid_len == wifi->ssid.len) {
|
|
if (memcmp(ssid, wifi->ssid.val, ssid_len) == 0) {
|
|
|
|
printf("Connecting to MAC=%02x:%02x:%02x:%02x:%02x:%02x, ssid = %s, SEC=%d\n",
|
|
scan_result.mac[0], scan_result.mac[1], scan_result.mac[2],
|
|
scan_result.mac[3], scan_result.mac[4], scan_result.mac[5],
|
|
ssid, scan_result.sec_mode);
|
|
|
|
scan_channel = scan_result.channel;
|
|
|
|
|
|
/* try 3 times to connect */
|
|
for (i = 0; i < 3; i++) {
|
|
if(wifi_set_pscan_chan(&scan_channel, &pscan_config, 1) < 0){
|
|
printf("\n\rERROR: wifi set partial scan channel fail");
|
|
ret = SC_TARGET_CHANNEL_SCAN_FAIL;
|
|
goto sc_connect_wifi_fail;
|
|
}
|
|
ret = wifi_connect_bssid(scan_result.mac, (char*)wifi->ssid.val, SC_translate_iw_security_mode(scan_result.sec_mode),
|
|
(char*)wifi->password, ETH_ALEN, wifi->ssid.len, wifi->password_len, 0, NULL);
|
|
if (ret == RTW_SUCCESS)
|
|
goto sc_connect_wifi_success;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
buf = buf + scan_result.len;
|
|
parsed_len += scan_result.len;
|
|
if (parsed_len >= buf_len) {
|
|
printf("parsed=%d, total = %d\n", parsed_len, buf_len);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
sc_connect_wifi_success:
|
|
printf("%s success\n", __FUNCTION__);
|
|
return ret;
|
|
|
|
sc_connect_wifi_fail:
|
|
printf("%s fail\n", __FUNCTION__);
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
When BSSID_CHECK_SUPPORT is not set, there will be problems:
|
|
|
|
1.AP1 and AP2 (different SSID) both forward simple config packets,
|
|
profile is from AP2, but Ameba connect with AP1
|
|
2.AP1 and AP2 (same SSID, but different crypto or password), both forward simple config packets,
|
|
profile is from AP2, but Ameba connect with AP1
|
|
3. ...
|
|
|
|
fix: using SSID to query matched BSSID(s) in scan result, traverse and connect.
|
|
|
|
|
|
Consideration:
|
|
1.Only take ssid and password
|
|
2.Assume they have different channel.
|
|
3.Assume they have different encrypt methods
|
|
|
|
*/
|
|
int SC_connect_to_candidate_AP (rtw_network_info_t *wifi){
|
|
|
|
int ret;
|
|
|
|
scan_buf_arg scan_buf;
|
|
int scan_cnt = 0;
|
|
char *ssid = (char*)wifi->ssid.val;
|
|
int ssid_len = wifi->ssid.len;
|
|
|
|
|
|
printf("Connect with SSID=%s password=%s\n", wifi->ssid.val, wifi->password);
|
|
|
|
/* scan buf init */
|
|
scan_buf.buf_len = 1000;
|
|
scan_buf.buf = (char*)pvPortMalloc(scan_buf.buf_len);
|
|
if(!scan_buf.buf){
|
|
printf("ERROR: Can't malloc memory\n");
|
|
return RTW_NOMEM;
|
|
}
|
|
|
|
/* set ssid_len, ssid to scan buf */
|
|
memset(scan_buf.buf, 0, scan_buf.buf_len);
|
|
if(ssid && ssid_len > 0 && ssid_len <= 32){
|
|
memcpy(scan_buf.buf, &ssid_len, sizeof(int));
|
|
memcpy(scan_buf.buf+sizeof(int), ssid, ssid_len);
|
|
}
|
|
|
|
/* call wifi scan to scan */
|
|
if(scan_cnt = (wifi_scan(RTW_SCAN_TYPE_ACTIVE, RTW_BSS_TYPE_ANY, &scan_buf)) < 0){
|
|
printf("ERROR: wifi scan failed\n");
|
|
ret = RTW_ERROR;
|
|
}else{
|
|
ret = SC_parse_scan_result_and_connect(&scan_buf, wifi);
|
|
}
|
|
|
|
if(scan_buf.buf)
|
|
vPortFree(scan_buf.buf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
|
|
rtw_security_t SC_translate_security(u8 security_type)
|
|
{
|
|
|
|
rtw_security_t security_mode = RTW_SECURITY_UNKNOWN;
|
|
|
|
switch (security_type) {
|
|
case RTW_ENCRYPTION_OPEN:
|
|
security_mode = RTW_SECURITY_OPEN;
|
|
break;
|
|
case RTW_ENCRYPTION_WEP40:
|
|
case RTW_ENCRYPTION_WEP104:
|
|
security_mode = RTW_SECURITY_WEP_PSK;
|
|
break;
|
|
case RTW_ENCRYPTION_WPA_TKIP:
|
|
case RTW_ENCRYPTION_WPA_AES:
|
|
case RTW_ENCRYPTION_WPA2_TKIP:
|
|
case RTW_ENCRYPTION_WPA2_AES:
|
|
case RTW_ENCRYPTION_WPA2_MIXED:
|
|
security_mode = RTW_SECURITY_WPA2_AES_PSK;
|
|
break;
|
|
case RTW_ENCRYPTION_UNKNOWN:
|
|
case RTW_ENCRYPTION_UNDEF:
|
|
default:
|
|
printf( "unknow security mode,connect fail\n");
|
|
}
|
|
|
|
return security_mode;
|
|
|
|
}
|
|
|
|
|
|
enum sc_result SC_connect_to_AP(void)
|
|
{
|
|
enum sc_result ret = SC_ERROR;
|
|
u8 scan_channel;
|
|
u8 pscan_config;
|
|
int max_retry = 5, retry = 0;
|
|
rtw_security_t security_mode;
|
|
rtw_network_info_t wifi = {0};
|
|
if(!(fixed_channel_num == 0)){
|
|
scan_channel = fixed_channel_num;
|
|
}
|
|
pscan_config = PSCAN_ENABLE | PSCAN_SIMPLE_CONFIG;
|
|
|
|
security_mode = SC_translate_security(g_security_mode);
|
|
g_security_mode = 0xff;//clear it
|
|
|
|
if (-1 == get_connection_info_from_profile(security_mode, &wifi)) {
|
|
ret = SC_CONTROLLER_INFO_PARSE_FAIL;
|
|
goto wifi_connect_fail;
|
|
}
|
|
|
|
#if CONFIG_AUTO_RECONNECT
|
|
/* disable auto reconnect */
|
|
wifi_set_autoreconnect(0);
|
|
#endif
|
|
|
|
#if 1
|
|
/* optimization: get g_bssid to connect with only pscan */
|
|
while (1) {
|
|
if(wifi_set_pscan_chan(&scan_channel, &pscan_config, 1) < 0){
|
|
printf("ERROR: wifi set partial scan channel fail\n");
|
|
ret = SC_TARGET_CHANNEL_SCAN_FAIL;
|
|
goto wifi_connect_fail;
|
|
}
|
|
rtw_join_status = 0;//clear simple config status
|
|
ret = wifi_connect_bssid(g_bssid, (char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password,
|
|
ETH_ALEN, wifi.ssid.len, wifi.password_len, wifi.key_id, NULL);
|
|
|
|
if (ret == RTW_SUCCESS)
|
|
goto wifi_connect_success;
|
|
|
|
if (retry == max_retry) {
|
|
printf("connect fail with bssid, try ssid instead\n");
|
|
break;
|
|
}
|
|
retry ++;
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
/* when optimization fail: if connect with bssid fail because of we have connect to the wrong AP */
|
|
ret = SC_connect_to_candidate_AP(&wifi);
|
|
if (RTW_SUCCESS == ret) {
|
|
goto wifi_connect_success;
|
|
} else {
|
|
ret = SC_JOIN_BSS_FAIL;
|
|
goto wifi_connect_fail;
|
|
}
|
|
#endif
|
|
|
|
|
|
wifi_connect_success:
|
|
ret = SC_check_and_show_connection_info();
|
|
goto wifi_connect_end;
|
|
|
|
|
|
wifi_connect_fail:
|
|
printf("SC_connect_to_AP failed\n");
|
|
goto wifi_connect_end;
|
|
|
|
wifi_connect_end:
|
|
#if CONFIG_AUTO_RECONNECT
|
|
wifi_config_autoreconnect(1, 10, 5);
|
|
#endif
|
|
return ret;
|
|
|
|
|
|
}
|
|
/* Make callback one by one to wlan rx when promiscuous mode */
|
|
|
|
void simple_config_callback(unsigned char *buf, unsigned int len, void* userdata)
|
|
{
|
|
unsigned char * da = buf;
|
|
unsigned char * sa = buf + ETH_ALEN;
|
|
taskENTER_CRITICAL();
|
|
if (is_promisc_callback_unlock == 1) {
|
|
simple_config_result = rtk_start_parse_packet(da, sa, len, userdata, (void *)backup_sc_ctx);
|
|
//printf("\r\nresult in callback function = %d\n",simple_config_result);
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
|
|
}
|
|
|
|
static unsigned int simple_config_cmd_start_time;
|
|
static unsigned int simple_config_cmd_current_time;
|
|
extern int simple_config_status;
|
|
extern void rtk_restart_simple_config(void);
|
|
|
|
|
|
extern void rtk_sc_deinit(void);
|
|
|
|
void init_simple_config_lib_config(struct simple_config_lib_config* config)
|
|
{
|
|
config->free = rtw_mfree;
|
|
config->malloc = rtw_malloc;
|
|
config->memcmp = memcmp;
|
|
config->memcpy = memcpy;
|
|
config->memset = memset;
|
|
config->printf = printf;
|
|
config->strcpy = strcpy;
|
|
config->strlen = strlen;
|
|
config->zmalloc = rtw_zmalloc;
|
|
#if CONFIG_LWIP_LAYER
|
|
config->_ntohl = lwip_ntohl;
|
|
#else
|
|
config->_ntohl = _ntohl;
|
|
#endif
|
|
config->is_promisc_callback_unlock = &is_promisc_callback_unlock;
|
|
}
|
|
|
|
|
|
int init_test_data(char *custom_pin_code)
|
|
{
|
|
#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
|
|
is_promisc_callback_unlock = 1;
|
|
is_fixed_channel = 0;
|
|
fixed_channel_num = 0;
|
|
simple_config_result = 0;
|
|
rtw_memset(g_ssid, 0, 32);
|
|
g_ssid_len = 0;
|
|
simple_config_cmd_start_time = xTaskGetTickCount();
|
|
|
|
if (ack_content != NULL) {
|
|
vPortFree(ack_content);
|
|
ack_content = NULL;
|
|
}
|
|
ack_content = pvPortMalloc(sizeof(struct ack_msg));
|
|
if (!ack_content) {
|
|
printf("rtk_sc_init fail by allocate ack\n");
|
|
}
|
|
memset(ack_content, 0, sizeof(struct ack_msg));
|
|
|
|
#ifdef SC_SCAN_SUPPORT
|
|
if(custom_pin_code)
|
|
pin_enable = 1;
|
|
else
|
|
pin_enable = 0;
|
|
#endif
|
|
|
|
backup_sc_ctx = pvPortMalloc(sizeof(struct rtk_test_sc));
|
|
if (!backup_sc_ctx) {
|
|
printf("[Mem]malloc SC context fail\n");
|
|
} else {
|
|
memset(backup_sc_ctx, 0, sizeof(struct rtk_test_sc));
|
|
struct simple_config_lib_config lib_config;
|
|
init_simple_config_lib_config(&lib_config);
|
|
//custom_pin_code can be null
|
|
if (rtk_sc_init(custom_pin_code, &lib_config) < 0) {
|
|
printf("Rtk_sc_init fail\n");
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#else
|
|
printf("Platform no include simple config now\n");
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
void deinit_test_data(){
|
|
#if (CONFIG_INCLUDE_SIMPLE_CONFIG)
|
|
rtk_sc_deinit();
|
|
if (backup_sc_ctx != NULL) {
|
|
vPortFree(backup_sc_ctx);
|
|
backup_sc_ctx = NULL;
|
|
}
|
|
if (ack_content != NULL) {
|
|
vPortFree(ack_content);
|
|
ack_content = NULL;
|
|
}
|
|
rtw_join_status = 0;//clear simple config status
|
|
#endif
|
|
}
|
|
|
|
void stop_simple_config()
|
|
{
|
|
simple_config_terminate = 1;
|
|
}
|
|
|
|
enum sc_result simple_config_test(rtw_network_info_t *wifi)
|
|
{
|
|
int channel = 1;
|
|
enum sc_result ret = SC_SUCCESS;
|
|
unsigned int start_time;
|
|
int is_need_connect_to_AP = 0;
|
|
int fix_channel = 0;
|
|
int delta_time = 0;
|
|
wifi_set_promisc(RTW_PROMISC_ENABLE, simple_config_callback, 1);
|
|
start_time = xTaskGetTickCount();
|
|
printf("\n");
|
|
wifi_set_channel(channel);
|
|
while (simple_config_terminate != 1) {
|
|
vTaskDelay(50); //delay 0.5s to release CPU usage
|
|
simple_config_cmd_current_time = xTaskGetTickCount();
|
|
#if CONFIG_GAGENT
|
|
if (simple_config_cmd_current_time - simple_config_cmd_start_time < ((50 + delta_time)*configTICK_RATE_HZ)) {
|
|
#else
|
|
if (simple_config_cmd_current_time - simple_config_cmd_start_time < ((120 + delta_time)*configTICK_RATE_HZ)) {
|
|
#endif
|
|
unsigned int current_time = xTaskGetTickCount();
|
|
if (((current_time - start_time)*1000 /configTICK_RATE_HZ < 100)
|
|
|| (is_fixed_channel == 1)) {
|
|
if(is_fixed_channel == 0 && get_channel_flag == 1){
|
|
fix_channel = promisc_get_fixed_channel(g_bssid,g_ssid,&g_ssid_len);
|
|
if(fix_channel != 0)
|
|
{
|
|
printf("in simple_config_test fix channel = %d ssid: %s\n",fix_channel, g_ssid);
|
|
is_fixed_channel = 1;
|
|
fixed_channel_num = fix_channel;
|
|
wifi_set_channel(fix_channel);
|
|
}
|
|
else
|
|
printf("get channel fail\n");
|
|
}
|
|
|
|
if (simple_config_result == 1) {
|
|
is_need_connect_to_AP = 1;
|
|
is_fixed_channel = 0;
|
|
break;
|
|
}
|
|
if (simple_config_result == -1) {
|
|
printf("simple_config_test restart for result = -1\n");
|
|
delta_time = 60;
|
|
wifi_set_channel(1);
|
|
is_need_connect_to_AP = 0;
|
|
is_fixed_channel = 0;
|
|
fixed_channel_num = 0;
|
|
memset(g_ssid, 0, 32);
|
|
g_ssid_len = 0;
|
|
simple_config_result = 0;
|
|
g_security_mode = 0xff;
|
|
rtk_restart_simple_config();
|
|
}
|
|
if (simple_config_result == -2) {
|
|
printf("The APP or client must have pin!\n");
|
|
break;
|
|
}
|
|
} else {
|
|
channel++;
|
|
if ((1 <= channel) && (channel <= 13)) {
|
|
if (wifi_set_channel(channel) == 0) {
|
|
start_time = xTaskGetTickCount();
|
|
printf("Switch to channel(%d)\n", channel);
|
|
}
|
|
} else {
|
|
channel = 1;
|
|
if (wifi_set_channel(channel) == 0) {
|
|
start_time = xTaskGetTickCount();
|
|
printf("Switch to channel(%d)\n", channel);
|
|
}
|
|
}
|
|
|
|
}
|
|
} else {
|
|
ret = SC_NO_CONTROLLER_FOUND;
|
|
break;
|
|
}
|
|
}
|
|
wifi_set_promisc(RTW_PROMISC_DISABLE, NULL, 0);
|
|
if (is_need_connect_to_AP == 1) {
|
|
if(NULL == wifi){
|
|
int tmp_res = SC_connect_to_AP();
|
|
if (SC_SUCCESS == tmp_res) {
|
|
if(-1 == SC_send_simple_config_ack(10))
|
|
ret = SC_UDP_SOCKET_CREATE_FAIL;
|
|
#ifdef SC_SCAN_SUPPORT
|
|
// check whether the thread of listen scan command is already created
|
|
if(scan_start == 0)
|
|
{
|
|
scan_start = 1;
|
|
SC_listen_ACK_scan();
|
|
}
|
|
#endif
|
|
} else {
|
|
ret = tmp_res;
|
|
}
|
|
}else{
|
|
if (-1 == get_connection_info_from_profile(wifi->security_type,wifi)) {
|
|
ret = SC_CONTROLLER_INFO_PARSE_FAIL;
|
|
}else
|
|
ret = SC_SUCCESS;
|
|
}
|
|
}else{
|
|
ret = SC_NO_CONTROLLER_FOUND;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//Filter packet da[] = {0x01, 0x00, 0x5e}
|
|
//add another filter for bcast, {0xff, 0xff, 0xff, 0xff}
|
|
#define MASK_SIZE 3
|
|
void filter_add_enable(){
|
|
u8 mask[MASK_SIZE]={0xFF,0xFF,0xFF};
|
|
u8 pattern[MASK_SIZE]={0x01,0x00,0x5e};
|
|
u8 pattern_bcast[MASK_SIZE]={0xff,0xff,0xff};
|
|
|
|
rtw_packet_filter_pattern_t packet_filter;
|
|
rtw_packet_filter_pattern_t packet_filter_bcast;
|
|
rtw_packet_filter_rule_e rule;
|
|
|
|
packet_filter.offset = 0;
|
|
packet_filter.mask_size = 3;
|
|
packet_filter.mask = mask;
|
|
packet_filter.pattern = pattern;
|
|
|
|
packet_filter_bcast.offset = 0;
|
|
packet_filter_bcast.mask_size = 3;
|
|
packet_filter_bcast.mask = mask;
|
|
packet_filter_bcast.pattern = pattern_bcast;
|
|
|
|
rule = RTW_POSITIVE_MATCHING;
|
|
|
|
wifi_init_packet_filter();
|
|
wifi_add_packet_filter(1, &packet_filter,rule);
|
|
wifi_add_packet_filter(2, &packet_filter_bcast,rule);
|
|
|
|
wifi_enable_packet_filter(1);
|
|
wifi_enable_packet_filter(2);
|
|
}
|
|
|
|
void remove_filter(){
|
|
wifi_disable_packet_filter(1);
|
|
wifi_disable_packet_filter(2);
|
|
wifi_remove_packet_filter(1);
|
|
wifi_remove_packet_filter(2);
|
|
}
|
|
|
|
void print_simple_config_result(enum sc_result sc_code)
|
|
{
|
|
printf("\n");
|
|
switch (sc_code) {
|
|
case SC_NO_CONTROLLER_FOUND:
|
|
printf("Simple Config timeout!! Can't get Ap profile. Please try again\n");
|
|
break;
|
|
case SC_CONTROLLER_INFO_PARSE_FAIL:
|
|
printf("Simple Config fail, cannot parse target ap info from controller\n");
|
|
break;
|
|
case SC_TARGET_CHANNEL_SCAN_FAIL:
|
|
printf("Simple Config cannot scan the target channel\n");
|
|
break;
|
|
case SC_JOIN_BSS_FAIL:
|
|
printf("Simple Config Join bss failed\n");
|
|
break;
|
|
case SC_DHCP_FAIL:
|
|
printf("Simple Config fail, cannot get dhcp ip address\n");
|
|
break;
|
|
case SC_UDP_SOCKET_CREATE_FAIL:
|
|
printf("Simple Config Ack socket create fail!!!\n");
|
|
break;
|
|
case SC_TERMINATE:
|
|
printf("Simple Config terminate\n");
|
|
break;
|
|
case SC_SUCCESS:
|
|
printf("Simple Config success\n");
|
|
break;
|
|
|
|
case SC_ERROR:
|
|
default:
|
|
printf("unknown error when simple config!\n");
|
|
|
|
}
|
|
}
|
|
|
|
#endif //CONFIG_INCLUDE_SIMPLE_CONFIG
|
|
|
|
void cmd_simple_config(int argc, char **argv){
|
|
#if CONFIG_INCLUDE_SIMPLE_CONFIG
|
|
char *custom_pin_code = NULL;
|
|
enum sc_result ret = SC_ERROR;
|
|
|
|
if(argc > 2){
|
|
printf("Input Error!\n");
|
|
}
|
|
|
|
if(argc == 2)
|
|
custom_pin_code = (argv[1]);
|
|
|
|
simple_config_terminate = 0;
|
|
rtw_join_status |= JOIN_SIMPLE_CONFIG;
|
|
|
|
wifi_enter_promisc_mode();
|
|
if(init_test_data(custom_pin_code) == 0){
|
|
filter_add_enable();
|
|
ret = simple_config_test(NULL);
|
|
deinit_test_data();
|
|
print_simple_config_result(ret);
|
|
remove_filter();
|
|
}
|
|
#if CONFIG_INIC_CMD_RSP
|
|
if(ret != SC_SUCCESS)
|
|
inic_c2h_wifi_info("ATWQ", RTW_ERROR);
|
|
#endif
|
|
|
|
#if CONFIG_EXAMPLE_UART_ATCMD
|
|
if(ret == SC_SUCCESS){
|
|
at_printf("\n\r[ATWQ] OK");
|
|
}else{
|
|
at_printf("\n\r[ATWQ] ERROR:%d",ret);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
#endif //#if CONFIG_WLAN
|
|
|
|
#endif // LWIP_SOCKET
|
|
|