586 lines
15 KiB
C
Raw Normal View History

2025-10-10 16:07:00 +08:00
#include <common/bk_include.h>
#include "bk_arm_arch.h"
#include "bk_misc.h"
#include <os/mem.h>
#include "bk_uart.h"
#include "sys_rtos.h"
#include <os/os.h>
#include <common/bk_kernel_err.h>
#include "bk_fake_clock.h"
#include "lwip/sockets.h"
#include "airkiss.h"
#include "airkiss_pingpong.h"
#include "airkiss_main.h"
//#include "flash.h"
#include "bk_wifi.h"
#include "bk_wifi_types.h"
#include "common/bk_err.h"
#include "components/event.h"
#include "components/netif_types.h"
#include <modules/wifi.h>
static airkiss_context_t *ak_contex = NULL;
const airkiss_config_t ak_conf = {
(airkiss_memset_fn) &os_memset,
(airkiss_memcpy_fn) &os_memcpy,
(airkiss_memcmp_fn) &os_memcmp,
(airkiss_printf_fn) &AIRKISS_PRT
};
beken_timer_t ak_chan_timer;
beken_timer_t ak_doing_timer;
beken_thread_t ak_thread_handle = NULL;
beken_semaphore_t ak_semaphore = NULL;
beken_semaphore_t ak_connect_semaphore = NULL;
airkiss_channel_t g_chans;
airkiss_mac_t g_macs;
volatile u8 airkiss_exit = 0;
u8 *read_buf = NULL;
extern void net_set_sta_ipup_callback(void *fn);
static unsigned char calcrc_1byte(unsigned char abyte)
{
unsigned char i, crc_1byte;
crc_1byte = 0;
for (i = 0; i < 8; i++) {
if (((crc_1byte ^ abyte) & 0x01)) {
crc_1byte ^= 0x18;
crc_1byte >>= 1;
crc_1byte |= 0x80;
} else
crc_1byte >>= 1;
abyte >>= 1;
}
return crc_1byte;
}
static unsigned char calcrc_bytes(unsigned char *p, unsigned int num_of_bytes)
{
unsigned char crc = 0;
while (num_of_bytes--)
crc = calcrc_1byte(crc ^ *p++);
return crc;
}
void airkiss_count_usefull_packet(const unsigned char *frame, int size)
{
u8 mac_crc = 0;
u8 *mac_ptr = 0;
u16 channel = 0;
uint32_t elmt_addr, var_part_addr, var_part_len;
int i;
struct wifi_mac_hdr *fwifi_mac_hdr = (struct wifi_mac_hdr *)frame;
struct wifi_bcn_frame const *frm = (struct wifi_bcn_frame const *)frame;
chan_param_t *cur_chan = &g_chans.chan[g_chans.cur_chan_idx];
mac_ptr = (u8 *)&fwifi_mac_hdr->addr2;
mac_crc = calcrc_bytes(mac_ptr, 6);
if (!frame || !size)
return;
if ((MAC_FCTRL_BEACON == (fwifi_mac_hdr->fctl & MAC_FCTRL_TYPESUBTYPE_MASK))
|| (MAC_FCTRL_PROBERSP == (fwifi_mac_hdr->fctl & MAC_FCTRL_TYPESUBTYPE_MASK))) {
cur_chan->bcn_cnt++;
var_part_addr = (uint32_t)frm->variable;
var_part_len = size - MAC_BEACON_VARIABLE_PART_OFT;
elmt_addr = bk_wifi_find_ie(var_part_addr, var_part_len, MAC_ELTID_DS);
if (elmt_addr != 0)
channel = *(uint8_t*)(elmt_addr + MAC_DS_CHANNEL_OFT);
for (i = 0; i < g_macs.mac_cnt; i++) {
if ((mac_crc == g_macs.mac[i].mac_crc)) {
if (channel != 0)
g_macs.mac[i].channel = channel;
break;
}
}
if (i == g_macs.mac_cnt) {
g_macs.mac[i].mac_crc = mac_crc;
if (channel != 0)
g_macs.mac[i].channel = channel;
g_macs.mac_cnt++;
}
} else if (MAC_FCTRL_DATA_T == (fwifi_mac_hdr->fctl & MAC_FCTRL_TYPE_MASK))
cur_chan->data_cnt++;
}
void airkiss_set_scan_all_channel(void)
{
int i;
os_memset(&g_chans, 0, sizeof(airkiss_channel_t));
os_memset(&g_macs, 0, sizeof(airkiss_mac_t));
g_chans.all_chan_nums = MAX_CHANNELS - 1;
for (i = 0; i < g_chans.all_chan_nums; i++)
g_chans.chan[i].channel = i + 1;
g_chans.mode = AIRKISS_SCAN_ALL_CHAN;
g_chans.cur_chan_idx = 0;
AIRKISS_WARN("change to all scan mode\r\n");
}
u32 airkiss_calc_time_for_selected_channel(u8 valid_cnt)
{
u32 timer_cnt;
timer_cnt = (valid_cnt / MIN_VALID_DATACNT_INCHAN) * MIN_SEL_CHAN_TIMER;
if (timer_cnt < MIN_SEL_CHAN_TIMER)
return MIN_SEL_CHAN_TIMER;
else if (timer_cnt > MAX_SEL_CHAN_TIMER)
return MAX_SEL_CHAN_TIMER;
return timer_cnt;
}
void airkiss_add_channel(u8 channel, u8 bcn_cnt, u8 data_cnt)
{
int i;
if (data_cnt < MIN_VALID_DATACNT_INCHAN)
return;
if (bcn_cnt < MIN_VALID_BCNCNT_INCHAN)
return;
for (i = 0; i < g_chans.selected_chan_nums; i++) {
u8 cur_cnt = g_chans.chan[i].data_cnt;
u8 cur_chan = g_chans.chan[i].channel;
if (cur_cnt < data_cnt) {
if (cur_chan != channel) {
u8 move_cnt = g_chans.selected_chan_nums - i;
os_memmove(&g_chans.chan[i + 1], &g_chans.chan[i], move_cnt * sizeof(chan_param_t));
g_chans.selected_chan_nums += 1;
}
g_chans.chan[i].channel = channel;
g_chans.chan[i].data_cnt = data_cnt;
return;
}
}
if (i == g_chans.selected_chan_nums) {
g_chans.selected_chan_nums ++;
g_chans.chan[i].channel = channel;
g_chans.chan[i].data_cnt = data_cnt;
}
}
void airkiss_switch_channel_callback(void *data)
{
int ret;
u8 bcn_cnt = 0, data_cnt = 0;
u32 timer_cnt = 0;
u8 channel = 0;
chan_param_t *cur_chan = &g_chans.chan[g_chans.cur_chan_idx];
wifi_channel_t chan = {0};
bcn_cnt = cur_chan->bcn_cnt;
data_cnt = cur_chan->data_cnt;
channel = cur_chan->channel;
AIRKISS_PRT("finish scan ch:%02d, bcn:%03d, data:%03d\r\n",
channel, bcn_cnt, data_cnt);
AIRKISS_PRT("\r\n");
switch (g_chans.mode) {
case AIRKISS_SCAN_ALL_CHAN:
airkiss_add_channel(channel, bcn_cnt, data_cnt);
g_chans.cur_chan_idx++;
timer_cnt = AIRKISS_SWITCH_TIMER;
if (g_chans.cur_chan_idx >= g_chans.all_chan_nums) {
g_chans.cur_chan_idx = 0;
if (g_chans.selected_chan_nums) {
g_chans.mode = AIRKISS_SCAN_SELECTED_CHAN;
data_cnt = g_chans.chan[g_chans.cur_chan_idx].data_cnt;
timer_cnt = airkiss_calc_time_for_selected_channel(data_cnt);
AIRKISS_WARN("change to selected scan mode\r\n");
} else
airkiss_set_scan_all_channel();
}
break;
case AIRKISS_SCAN_SELECTED_CHAN:
g_chans.cur_chan_idx++;
data_cnt = g_chans.chan[g_chans.cur_chan_idx].data_cnt;
timer_cnt = airkiss_calc_time_for_selected_channel(data_cnt);
if (g_chans.cur_chan_idx >= g_chans.selected_chan_nums) {
g_chans.cur_chan_idx = 0;
airkiss_set_scan_all_channel();
g_chans.mode = AIRKISS_SCAN_ALL_CHAN;
timer_cnt = AIRKISS_SWITCH_TIMER;
}
break;
default:
AIRKISS_WARN("unknow state:%d\r\n", g_chans.mode);
g_chans.mode = AIRKISS_SCAN_ALL_CHAN;
return;
break;
}
channel = g_chans.chan[g_chans.cur_chan_idx].channel;
AIRKISS_PRT("start scan ch:%02d/%02d, time_intval:%d\r\n", g_chans.cur_chan_idx, channel, timer_cnt);
chan.primary = channel;
BK_LOG_ON_ERR(bk_wifi_monitor_set_channel(&chan));
airkiss_change_channel(ak_contex);
if (!airkiss_exit) {
ret = rtos_change_period(&ak_chan_timer, timer_cnt);
BK_ASSERT(kNoErr == ret);
}
}
void airkiss_doing_timeout_callback(void *data)
{
wifi_channel_t chan = {0};
int ret;
AIRKISS_WARN("airkiss_doing_timeout, restart channel switch timer\r\n");
// stop doing timer
ret = rtos_stop_timer(&ak_doing_timer);
BK_ASSERT(kNoErr == ret);
airkiss_change_channel(ak_contex);
// restart scan process
ret = airkiss_init(ak_contex, &ak_conf);
if (0 != ret)
AIRKISS_FATAL("re-airkiss init failed!!\r\n");
airkiss_set_scan_all_channel();
g_chans.cur_chan_idx = 0; // set channel 1
chan.primary = g_chans.chan[g_chans.cur_chan_idx].channel;
BK_LOG_ON_ERR(bk_wifi_monitor_set_channel(&chan));
if (!airkiss_exit) {
ret = rtos_change_period(&ak_chan_timer, AIRKISS_SWITCH_TIMER);
BK_ASSERT(kNoErr == ret);
}
}
bk_err_t airkiss_monitor_callback(const uint8_t *data, uint32_t len, const wifi_frame_info_t *info)
{
GLOBAL_INT_DECLARATION();
if (len < AIRKISS_MIN_RX_BUF_SIZE)
return BK_ERR_PARAM;
airkiss_count_usefull_packet(data, len);
GLOBAL_INT_DISABLE();
write_to_pingpong_buf((uint8_t *)data, AIRKISS_MIN_RX_BUF_SIZE, len);
GLOBAL_INT_RESTORE();
if (ak_semaphore)
rtos_set_semaphore(&ak_semaphore);
return BK_OK;
}
int process_airkiss(const unsigned char *packet, int size)
{
int ret, result, i;
u8 mac_crc = 0;
u8 *mac_ptr = 0;
struct wifi_mac_hdr *fwifi_mac_hdr = (struct wifi_mac_hdr *)packet;
wifi_channel_t chan = {0};
mac_ptr = (u8 *)&fwifi_mac_hdr->addr2;
mac_crc = calcrc_bytes(mac_ptr, 6);
ret = airkiss_recv(ak_contex, (void *)packet, size);
if (ret == AIRKISS_STATUS_CONTINUE) {
} else if (ret == AIRKISS_STATUS_CHANNEL_LOCKED) {
result = rtos_stop_timer(&ak_chan_timer);
BK_ASSERT(kNoErr == result);
for (i = 0; i < g_macs.mac_cnt; i++) {
if ((mac_crc == g_macs.mac[i].mac_crc)) {
if (g_chans.chan[g_chans.cur_chan_idx].channel != g_macs.mac[i].channel) {
g_chans.chan[g_chans.cur_chan_idx].channel = g_macs.mac[i].channel;
chan.primary = g_chans.chan[g_chans.cur_chan_idx].channel;
BK_LOG_ON_ERR(bk_wifi_monitor_set_channel(&chan));
}
}
}
AIRKISS_WARN("Lock channel in %d\r\n", g_chans.chan[g_chans.cur_chan_idx].channel);
AIRKISS_WARN("start airkiss doing timer\r\n");
result = rtos_start_timer(&ak_doing_timer);
BK_ASSERT(kNoErr == result);
} else if (ret == AIRKISS_STATUS_COMPLETE) {
result = rtos_stop_timer(&ak_doing_timer);
BK_ASSERT(kNoErr == result);
}
return ret;
}
int airkiss_connected_to_bssid(void *arg, event_module_t event_module,
int event_id, void *event_data)
{
if (ak_connect_semaphore)
rtos_set_semaphore(&ak_connect_semaphore);
return BK_OK;
}
void airkiss_start_udp_boardcast(u8 random_data)
{
int err, i;
int udp_broadcast_fd = -1;
struct sockaddr_in remote_skt;
udp_broadcast_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udp_broadcast_fd == -1) {
AIRKISS_WARN("Socket failed\r\n");
return;
}
os_memset(&remote_skt, 0, sizeof(struct sockaddr_in));
remote_skt.sin_family = AF_INET;
remote_skt.sin_addr.s_addr = INADDR_BROADCAST;//INADDR_ANY;
remote_skt.sin_port = htons(10000);
i = MIN_UDP_RANDOM_SEND;
while (i--) {
err = sendto(udp_broadcast_fd, &random_data, 1, 0, (struct sockaddr *)&remote_skt, sizeof(remote_skt));
rtos_delay_milliseconds(2);
if (err == -1)
AIRKISS_WARN("send udp boardcast failed\r\n");
}
close(udp_broadcast_fd);
}
void airkiss_main(void *arg)
{
int result;
u32 con_time;
airkiss_result_t ak_result;
u8 *airkiss_read_buf = NULL;
wifi_channel_t chan = {0};
result = pingpong_init();
if (0 != result) {
AIRKISS_FATAL("Airkiss pingpong_init failed!!\r\n");
goto kiss_exit;
}
result = rtos_init_timer(&ak_chan_timer,
AIRKISS_SWITCH_TIMER,
airkiss_switch_channel_callback,
(void *)0);
BK_ASSERT(kNoErr == result);
result = rtos_init_timer(&ak_doing_timer,
AIRKISS_DOING_TIMER,
airkiss_doing_timeout_callback,
(void *)0);
BK_ASSERT(kNoErr == result);
ak_contex = (airkiss_context_t *)os_malloc(sizeof(airkiss_context_t));
airkiss_read_buf = (u8 *)os_malloc(sizeof(u8) * AIRKISS_MIN_RX_BUF_SIZE);
if ((!ak_contex) || (!airkiss_read_buf)) {
AIRKISS_FATAL("Airkiss no buffer\r\n");
goto kiss_exit;
}
read_buf = airkiss_read_buf;
result = airkiss_init(ak_contex, &ak_conf);
if (result != 0) {
AIRKISS_FATAL("Airkiss init failed!!\r\n");
goto kiss_exit;
}
AIRKISS_WARN("Airkiss version: %s\r\n", airkiss_version());
BK_LOG_ON_ERR(bk_wifi_monitor_stop());
BK_LOG_ON_ERR(bk_wifi_monitor_register_cb(airkiss_monitor_callback));
BK_LOG_ON_ERR(bk_wifi_monitor_start());
// start from first channel
airkiss_set_scan_all_channel();
g_chans.cur_chan_idx = 0; // set channel 1
chan.primary = g_chans.chan[g_chans.cur_chan_idx].channel;
chan.second = WIFI_SECOND_CHANNEL_NONE;
BK_LOG_ON_ERR(bk_wifi_monitor_set_channel(&chan));
result = rtos_start_timer(&ak_chan_timer);
BK_ASSERT(kNoErr == result);
airkiss_exit = 0;
ak_result.ssid = NULL;
while (0 == airkiss_exit) {
uint32_t actual;
result = rtos_get_semaphore(&ak_semaphore, BEKEN_WAIT_FOREVER);
// count received packet
actual = 0;
read_from_pingpong_buf(read_buf, AIRKISS_MIN_RX_BUF_SIZE, &actual);
if (g_chans.mode == AIRKISS_SCAN_SELECTED_CHAN) {
if (AIRKISS_STATUS_COMPLETE == process_airkiss(airkiss_read_buf, actual)) {
AIRKISS_WARN("Airkiss completed.\r\n");
airkiss_get_result(ak_contex, &ak_result);
AIRKISS_WARN("Result:\r\n");
AIRKISS_WARN("ssid:[%s]\r\n", ak_result.ssid);
AIRKISS_WARN("ssid_len:[%d]\r\n", ak_result.ssid_length);
AIRKISS_WARN("ssid_crc:[%x]\r\n", ak_result.reserved);
AIRKISS_WARN("key:[%s]\r\n", ak_result.pwd);
AIRKISS_WARN("key_len:[%d]\r\n", ak_result.pwd_length);
AIRKISS_WARN("random:[0x%02x]\r\n", ak_result.random);
break;
}
}
}
// stop monitor mode
BK_LOG_ON_ERR(bk_wifi_monitor_stop());
BK_LOG_ON_ERR(bk_wifi_monitor_register_cb(NULL));
if (ak_result.ssid) {
if (ak_connect_semaphore == NULL) {
result = rtos_init_semaphore(&ak_connect_semaphore, 1);
BK_ASSERT(kNoErr == result);
}
// register GOT_IP4 event
bk_event_register_cb(EVENT_MOD_NETIF, EVENT_NETIF_GOT_IP4,
airkiss_connected_to_bssid, NULL);
// connect to this bssid
demo_sta_app_init(ak_result.ssid, ak_result.pwd);
// wait for connect to bssid
con_time = AIRKISS_CONNECT_TIMER;
result = rtos_get_semaphore(&ak_connect_semaphore, con_time);
if (result == kNoErr) {
// start udp boardcast
if (airkiss_exit)
BK_LOG_ON_ERR(bk_wifi_sta_stop());
else
airkiss_start_udp_boardcast(ak_result.random);
} else {
BK_LOG_ON_ERR(bk_wifi_sta_stop());
AIRKISS_FATAL("airkiss connect to bssid timeout\r\n");
}
// unregister GO_IP4 event
bk_event_unregister_cb(EVENT_MOD_NETIF, EVENT_NETIF_GOT_IP4,
airkiss_connected_to_bssid);
rtos_deinit_semaphore(&ak_connect_semaphore);
ak_connect_semaphore = NULL;
}
kiss_exit:
AIRKISS_WARN("Airkiss exit.\r\n");
result = rtos_stop_timer(&ak_chan_timer);
BK_ASSERT(kNoErr == result);
result = rtos_stop_timer(&ak_doing_timer);
BK_ASSERT(kNoErr == result);
do {
rtos_delay_milliseconds(10);
} while (rtos_is_timer_running(&ak_chan_timer) || (rtos_is_timer_running(&ak_doing_timer)));
result = rtos_deinit_timer(&ak_chan_timer);
BK_ASSERT(kNoErr == result);
result = rtos_deinit_timer(&ak_doing_timer);
BK_ASSERT(kNoErr == result);
rtos_deinit_semaphore(&ak_semaphore);
ak_semaphore = NULL;
if (ak_contex) {
os_free(ak_contex);
ak_contex = NULL;
}
if (airkiss_read_buf) {
os_free(airkiss_read_buf);
airkiss_read_buf = NULL;
}
ak_thread_handle = NULL;
pingpong_free();
rtos_delete_thread(NULL);
}
uint32_t airkiss_is_at_its_context(void)
{
return (NULL != ak_thread_handle);
}
uint32_t airkiss_start(void)
{
uint32_t ret = kNoErr;
if (NULL == ak_semaphore) {
ret = rtos_init_semaphore(&ak_semaphore, 1);
BK_ASSERT(kNoErr == ret);
}
if (NULL == ak_thread_handle) {
ret = rtos_create_thread(&ak_thread_handle,
BEKEN_DEFAULT_WORKER_PRIORITY,
"airkiss",
(beken_thread_function_t)airkiss_main,
4096,
(beken_thread_arg_t)0);
if (ret != kNoErr) {
AIRKISS_FATAL("Error: airkiss_start_process: %d\r\n", ret);
ret = kGeneralErr;
}
}
return ret;
}
uint32_t airkiss_stop(void)
{
GLOBAL_INT_DECLARATION();
if (ak_thread_handle && ak_semaphore) {
GLOBAL_INT_DISABLE();
airkiss_exit = 1;
GLOBAL_INT_RESTORE();
if (ak_connect_semaphore)
rtos_set_semaphore(&ak_connect_semaphore);
}
return kNoErr;
}
u32 airkiss_process(u8 start)
{
int ret;
AIRKISS_FATAL("airkiss_process:%d\r\n", start);
if (start)
ret = airkiss_start();
else
ret = airkiss_stop();
return ret;
}
// eof