/* * File : drv_wlan.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2017, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2018-7-10 tyx the first version */ #include "wifi_structures.h" #include "wifi_constants.h" #include #include #include "board.h" #include "drv_wlan.h" // #define SCAN_WAIT_TIME (10000) struct scan_user_data { struct rt_completion done; scan_callback_fn fun; void *data; }; extern rthw_mode_t wifi_mode; rthw_mode_t rthw_wifi_mode_get(void) { return wifi_mode; } int rthw_wifi_stop(void) { return wifi_off(); } int rthw_wifi_start(rthw_mode_t mode) { if(wifi_on(mode) < 0) { rt_kprintf("ERROR: wifi_on failed\n"); return -1; } return 0; } int rthw_wifi_connect(char *ssid, int ssid_len, char *password, int pass_len, rthw_security_t security_type) { int mode; rtw_wifi_setting_t setting; mode = rthw_wifi_mode_get(); if ((mode != RTHW_MODE_STA) && (mode != RTHW_MODE_STA_AP)) { return -1; } if(wext_get_mode(WLAN0_NAME, &mode) < 0) { rt_kprintf("L:%d wifi get mode err\n", __LINE__); return -1; } if(wifi_connect(ssid, security_type, password, ssid_len, pass_len, -1, NULL) != RTW_SUCCESS) { rt_kprintf("wifi connect fail\n"); return -1; } rt_kprintf("wifi connect success\n"); rt_kprintf("Show Wi-Fi information\n"); wifi_get_setting(WLAN0_NAME,&setting); wifi_show_setting(WLAN0_NAME,&setting); return 0; } int rthw_wifi_connect_bssid(char *bssid, char *ssid, int ssid_len, char *password, int pass_len, rthw_security_t security_type) { int mode; rtw_wifi_setting_t setting; mode = rthw_wifi_mode_get(); if ((mode != RTHW_MODE_STA) && (mode != RTHW_MODE_STA_AP)) { return -1; } if(wext_get_mode(WLAN0_NAME, &mode) < 0) { rt_kprintf("L:%d wifi get mode err\n", __LINE__); return -1; } if(wifi_connect_bssid(bssid, ssid, security_type, password, 6, ssid_len, pass_len, -1, NULL) != RTW_SUCCESS) { rt_kprintf("wifi connect fail\n"); return -1; } rt_kprintf("wifi connect success\n"); rt_kprintf("Show Wi-Fi information\n"); wifi_get_setting(WLAN0_NAME,&setting); wifi_show_setting(WLAN0_NAME,&setting); return 0; } int rthw_wifi_ap_start(char *ssid, char *password, int channel) { int mode = 0, timeout = 20; rtw_security_t security_type = RTW_SECURITY_WPA2_AES_PSK; char *name = RT_NULL; mode = rthw_wifi_mode_get(); if (mode == RTHW_MODE_AP) { name = WLAN0_NAME; } else if (mode == RTHW_MODE_STA_AP) { name = WLAN1_NAME; } else { return -1; } if(wext_get_mode(name, &mode) < 0) { rt_kprintf("L:%d wifi get mode err\n", __LINE__); return -1; } if (password == RT_NULL) { security_type = RTW_SECURITY_OPEN; } if(wifi_start_ap(ssid, security_type, password, rt_strlen(ssid), rt_strlen(password), 6) != 0) { rt_kprintf("ERROR: wifi_start_ap failed\n"); return -1; } while(1) { char essid[33]; if(wext_get_ssid(name, (unsigned char *) essid) > 0) { if(strcmp((const char *) essid, (const char *)ssid) == 0) { rt_kprintf("%s started\n", ssid); break; } } if(timeout == 0) { rt_kprintf("Start AP timeout\n"); return -1; } rt_thread_delay(1 * RT_TICK_PER_SECOND); timeout --; } return 0; } static int rthw_wifi_disconnect(char *name) { char essid[33]; int timeout = 20; const rt_uint8_t null_bssid[ETH_ALEN + 2] = {0, 0, 0, 0, 0, 1, 0, 0}; if (name == RT_NULL) return -1; if (wext_get_ssid(name, (unsigned char *) essid) < 0) { rt_kprintf("\nWIFI disconnected!\n"); return -1; } if (wext_set_bssid(name, null_bssid) < 0) { rt_kprintf("Failed to set bogus BSSID to disconnect"); return -1; } while (1) { if(wext_get_ssid(name, (unsigned char *) essid) < 0) { rt_kprintf("WIFI disconnected!\n"); break; } if(timeout == 0) { rt_kprintf("ERROR: Deassoc timeout!\n"); return -1; } rt_thread_delay(10); timeout --; } return 0; } int rthw_wifi_sta_disconnect(void) { int mode = 0; char *name = RT_NULL; mode = rthw_wifi_mode_get(); if (mode == RTHW_MODE_STA) { name = WLAN0_NAME; } else if (mode == RTHW_MODE_STA_AP) { name = WLAN0_NAME; } else { return -1; } return rthw_wifi_disconnect(name); } int rthw_wifi_ap_disconnect(void) { int mode = 0; char *name = RT_NULL; mode = rthw_wifi_mode_get(); if (mode == RTHW_MODE_AP) { name = WLAN0_NAME; } else if (mode == RTHW_MODE_STA_AP) { name = WLAN1_NAME; } else { return -1; } return rthw_wifi_disconnect(name); } int rthw_wifi_rssi_get(void) { int rssi = 0; wifi_get_rssi(&rssi); return rssi; } void rthw_wifi_channel_set(int channel) { wifi_set_channel(channel); } int rthw_wifi_channel_get(void) { int channel; wifi_get_channel(&channel); return channel; } static rtw_result_t rthw_wifi_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result) { struct scan_user_data* user_data = malloced_scan_result->user_data; struct rthw_wlan_info info = { 0 }; if (malloced_scan_result->scan_complete != RTW_TRUE) { rtw_scan_result_t* record = &malloced_scan_result->ap_details; if (user_data->fun != RT_NULL) { record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */ info.ssid = record->SSID.val; info.bssid = record->BSSID.octet; info.band = record->band; info.datarate = 0; info.channel = record->channel; info.rssi = record->signal_strength; info.security = record->security; user_data->fun(&info, user_data->data); } } else { user_data->fun(RT_NULL, user_data->data); rt_free(user_data); rt_kprintf("scan ap down\n"); } return RTW_SUCCESS; } int rthw_wifi_scan(scan_callback_fn fun, void *data) { struct scan_user_data *user_data; if (fun == RT_NULL) { rt_kprintf("scan callback fun is null\n"); return -1; } user_data = rt_malloc(sizeof(struct scan_user_data)); if (user_data == RT_NULL) { rt_kprintf("wifi scan malloc fail\n"); return -1; } user_data->fun = fun; user_data->data = data; if (wifi_scan_networks(rthw_wifi_scan_result_handler, user_data) != RTW_SUCCESS) { rt_kprintf("ERROR: wifi scan failed\n\r"); return -1; } return 0; } static rthw_wlan_monitor_callback_t monitor_callback; static void rthw_wifi_promisc_callback(unsigned char *buf, unsigned int len, void* userdata) { if (monitor_callback) { monitor_callback(userdata, len, RT_NULL); } } void rthw_wifi_monitor_callback_set(rthw_wlan_monitor_callback_t callback) { monitor_callback = callback; } void rthw_wifi_monitor_enable(int enable) { if (enable) { wifi_enter_promisc_mode(); wifi_set_promisc(RTW_PROMISC_ENABLE, rthw_wifi_promisc_callback, 1); rt_kprintf("%s run \n", __FUNCTION__); } else { wifi_set_promisc(RTW_PROMISC_DISABLE, RT_NULL, 0); rthw_wifi_stop(); } }