#include <ctype.h>
|
#include <pthread.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <unistd.h>
|
#include <sys/ioctl.h>
|
#include <sys/socket.h>
|
#include <net/if.h>
|
#include <errno.h>
|
#include <sys/prctl.h>
|
#include <sys/time.h>
|
|
#include "DeviceIo/Rk_wifi.h"
|
#include "slog.h"
|
#include "utility.h"
|
|
static bool save_last_ap = false;
|
static int connecting_id = -1;
|
|
static RK_WIFI_RUNNING_State_e gstate = RK_WIFI_State_OFF;
|
|
static char retry_connect_cmd[128];
|
|
typedef struct {
|
char ssid[SSID_BUF_LEN];
|
char bssid[BSSID_BUF_LEN];
|
} RK_WIFI_CONNECT_INFO;
|
|
static RK_WIFI_CONNECT_INFO connect_info =
|
{
|
"",
|
"",
|
};
|
|
static int is_non_psk(const char* str)
|
{
|
RK_WIFI_encode_gbk_t *nonpsk = m_nonpsk_head;
|
while (nonpsk) {
|
if (strcmp(nonpsk->utf8, str) == 0) {
|
return 1;
|
}
|
nonpsk = nonpsk->next;
|
}
|
|
return 0;
|
}
|
|
static RK_wifi_state_callback m_cb;
|
static int priority = 0;
|
static volatile bool wifi_wrong_key = false;
|
static volatile bool wifi_cancel = false;
|
static volatile bool wifi_connect_lock = false;
|
static volatile bool wifi_is_exist = false;
|
|
static void format_wifiinfo(int flag, char *info);
|
static int get_pid(const char Name[]);
|
static void RK_wifi_start_monitor(void *arg);
|
|
static char* wifi_state[] = {
|
"RK_WIFI_State_IDLE",
|
"RK_WIFI_State_CONNECTING",
|
"RK_WIFI_State_CONNECTFAILED",
|
"RK_WIFI_State_CONNECTFAILED_WRONG_KEY",
|
"RK_WIFI_State_CONNECTED",
|
"RK_WIFI_State_DISCONNECTED",
|
"RK_WIFI_State_OPEN",
|
"RK_WIFI_State_OFF",
|
"RK_WIFI_State_SCAN_RESULTS",
|
"RK_WIFI_State_DHCP_OK",
|
};
|
|
static char* exec1(const char* cmd)
|
{
|
if (NULL == cmd || 0 == strlen(cmd)) {
|
pr_err("exec1 cmd is NULL!\n");
|
return NULL;
|
}
|
|
pr_info("[RKWIFI] exec1: %s\n", cmd);
|
|
FILE* fp = NULL;
|
char buf[128];
|
char* ret;
|
static int SIZE_UNITE = 512;
|
size_t size = SIZE_UNITE;
|
|
fp = popen((const char *) cmd, "r");
|
if (NULL == fp) {
|
pr_err("exec1 popen fp NULL!\n");
|
return NULL;
|
}
|
|
memset(buf, 0, sizeof(buf));
|
ret = (char*) malloc(sizeof(char) * size);
|
memset(ret, 0, sizeof(char) * size);
|
while (NULL != fgets(buf, sizeof(buf)-1, fp)) {
|
if (size <= (strlen(ret) + strlen(buf))) {
|
size += SIZE_UNITE;
|
ret = (char*) realloc(ret, sizeof(char) * size);
|
}
|
strcat(ret, buf);
|
}
|
|
pclose(fp);
|
ret = (char*) realloc(ret, sizeof(char) * (strlen(ret) + 1));
|
|
return ret;
|
}
|
|
static int exec(const char* cmd, const char* ret)
|
{
|
char* tmp;
|
tmp = exec1(cmd);
|
|
if (NULL == tmp) {
|
pr_err("exec tmp is NULL!\n");
|
return -1;
|
}
|
|
char convers[strlen(tmp) + 1];
|
|
memset(ret, 0, strlen(ret));
|
strncpy(ret, tmp, strlen(tmp) + 1);
|
free(tmp);
|
|
return 0;
|
}
|
|
static int RK_wifi_search_with_ssid(const char *ssid)
|
{
|
RK_WIFI_SAVED_INFO wsi;
|
int id, len;
|
|
RK_wifi_getSavedInfo(&wsi);
|
for (int i = 0; i < wsi.count; i++) {
|
if ((strlen(wsi.save_info[i].ssid) > 64) || (strlen(ssid) > 64))
|
pr_err("RK_wifi_search_with_ssid ssid error!!!\n");
|
pr_err("RK_wifi_search_with_ssid save_info[%d].ssid: %s, ssid: %s \n",
|
i, wsi.save_info[i].ssid, ssid);
|
if (strlen(wsi.save_info[i].ssid) > strlen(ssid))
|
len = strlen(wsi.save_info[i].ssid);
|
else
|
len = strlen(ssid);
|
if (strncmp(wsi.save_info[i].ssid, ssid, len) == 0) {
|
return wsi.save_info[i].id;
|
}
|
}
|
|
return -1;
|
}
|
|
int RK_wifi_running_getConnectionInfo(RK_WIFI_INFO_Connection_s* pInfo)
|
{
|
FILE *fp = NULL;
|
char line[512];
|
char *value;
|
|
if (pInfo == NULL)
|
return -1;
|
|
if (remove("/tmp/status.tmp"))
|
pr_err("remove /tmp/status.tmp failed!\n");
|
exec_command_system("wpa_cli -iwlan0 status > /tmp/status.tmp");
|
|
// check wpa is running first
|
memset(line, 0, sizeof(line));
|
exec("cat /tmp/status.tmp", line);
|
pr_info("status.tmp: %s\n", line);
|
|
memset(line, 0, sizeof(line));
|
exec("wpa_cli -iwlan0 status", line);
|
pr_info("wpa_cli status: %s\n", line);
|
|
fp = fopen("/tmp/status.tmp", "r");
|
if (!fp) {
|
pr_err("fopen /tmp/status.tmp failed!\n");
|
return -1;
|
}
|
|
return 0;
|
}
|
|
static int is_wifi_enable()
|
{
|
int ret = 0;
|
|
return ret;
|
}
|
|
int RK_wifi_scan(void)
|
{
|
int ret;
|
char str[32];
|
|
memset(str, 0, sizeof(str));
|
ret = exec("wpa_cli -iwlan0 scan", str);
|
|
if (0 != ret)
|
return -1;
|
|
if (0 != strncmp(str, "OK", 2) && 0 != strncmp(str, "ok", 2)) {
|
pr_info("scan error: %s\n", str);
|
return -2;
|
}
|
|
return 0;
|
}
|
|
char* RK_wifi_scan_r_sec(const unsigned int cols)
|
{
|
char line[256], utf[256];
|
char item[384];
|
char col[128];
|
char *scan_r, *p_strtok;
|
size_t size = 0, index = 0;
|
static size_t UNIT_SIZE = 512;
|
FILE *fp = NULL;
|
int is_utf8;
|
int is_nonpsk;
|
|
if (!(cols & 0x1F)) {
|
scan_r = (char*) malloc(3 * sizeof(char));
|
memset(scan_r, 0, 3);
|
strcpy(scan_r, "[]");
|
pr_err("_scan_r: %s\n");
|
return scan_r;
|
}
|
|
remove("/tmp/scan_r.tmp");
|
exec_command_system("wpa_cli -iwlan0 scan_r > /tmp/scan_r.tmp");
|
|
fp = fopen("/tmp/scan_r.tmp", "r");
|
if (!fp) {
|
pr_err("open /tmp/scan_r.tmp fail!!!\n");
|
return NULL;
|
}
|
|
memset(line, 0, sizeof(line));
|
fgets(line, sizeof(line), fp);
|
|
size += UNIT_SIZE;
|
scan_r = (char*) malloc(size * sizeof(char));
|
memset(scan_r, 0, size);
|
strcat(scan_r, "[");
|
|
m_gbk_head = encode_gbk_reset(m_gbk_head);
|
m_nonpsk_head = encode_gbk_reset(m_nonpsk_head);
|
while (fgets(line, sizeof(line) - 1, fp)) {
|
index = 0;
|
is_nonpsk = 0;
|
p_strtok = strtok(line, "\t");
|
memset(item, 0, sizeof(item));
|
strcat(item, "{");
|
while (p_strtok) {
|
if (p_strtok[strlen(p_strtok) - 1] == '\n')
|
p_strtok[strlen(p_strtok) - 1] = '\0';
|
if ((cols & (1 << index)) || 3 == index) {
|
memset(col, 0, sizeof(col));
|
if (0 == index) {
|
snprintf(col, sizeof(col), "\"bssid\":\"%s\",", p_strtok);
|
} else if (1 == index) {
|
snprintf(col, sizeof(col), "\"frequency\":%d,", atoi(p_strtok));
|
} else if (2 == index) {
|
snprintf(col, sizeof(col), "\"rssi\":%d,", atoi(p_strtok));
|
} else if (3 == index) {
|
if (cols & (1 << index)) {
|
snprintf(col, sizeof(col), "\"flags\":\"%s\",", p_strtok);
|
}
|
if (!strstr(p_strtok, "WPA") && !strstr(p_strtok, "WEP")) {
|
is_nonpsk = 1;
|
}
|
} else if (4 == index) {
|
char utf8[strlen(p_strtok) + 1];
|
memset(utf8, 0, sizeof(utf8));
|
|
if (strlen(p_strtok) > 0) {
|
char dst[strlen(p_strtok) + 1];
|
memset(dst, 0, sizeof(dst));
|
spec_char_convers(p_strtok, dst);
|
|
// Strings that will send should retain escape characters
|
// Strings whether GBK or UTF8 that need save local should remove escape characters
|
// The ssid can't contains escape character while do connect
|
is_utf8 = RK_encode_is_utf8(dst, strlen(dst));
|
char utf8_noescape[sizeof(utf8)];
|
char dst_noescape[sizeof(utf8)];
|
memset(utf8_noescape, 0, sizeof(utf8_noescape));
|
memset(dst_noescape, 0, sizeof(dst_noescape));
|
if (!is_utf8) {
|
RK_encode_gbk_to_utf8(dst, strlen(dst), utf8);
|
remove_escape_character(dst, dst_noescape);
|
remove_escape_character(utf8, utf8_noescape);
|
m_gbk_head = encode_gbk_insert(m_gbk_head, dst_noescape, utf8_noescape);
|
|
// if convert gbk to utf8 failed, ignore it
|
if (!RK_encode_is_utf8(utf8, strlen(utf8))) {
|
continue;
|
}
|
} else {
|
strncpy(utf8, dst, strlen(dst));
|
remove_escape_character(dst, dst_noescape);
|
remove_escape_character(utf8, utf8_noescape);
|
}
|
|
// Decide whether encrypted or not
|
if (is_nonpsk) {
|
m_nonpsk_head = encode_gbk_insert(m_nonpsk_head, dst_noescape, utf8_noescape);
|
}
|
}
|
snprintf(col, sizeof(col), "\"ssid\":\"%s\",", utf8);
|
}
|
strcat(item, col);
|
}
|
p_strtok = strtok(NULL, "\t");
|
index++;
|
}
|
if (item[strlen(item) - 1] == ',') {
|
item[strlen(item) - 1] = '\0';
|
}
|
strcat(item, "},");
|
|
if (size <= (strlen(scan_r) + strlen(item)) + 3) {
|
size += UNIT_SIZE;
|
scan_r = (char*) realloc(scan_r, sizeof(char) * size);
|
}
|
strcat(scan_r, item);
|
}
|
if (scan_r[strlen(scan_r) - 1] == ',') {
|
scan_r[strlen(scan_r) - 1] = '\0';
|
}
|
strcat(scan_r, "]");
|
fclose(fp);
|
pr_err("__scan_r: %s\n");
|
return scan_r;
|
}
|
|
static int set_hide_network(const int id)
|
{
|
int ret;
|
char str[8];
|
char cmd[128];
|
|
memset(str, 0, sizeof(str));
|
memset(cmd, 0, sizeof(cmd));
|
snprintf(cmd, sizeof(cmd), "wpa_cli -iwlan0 set_network %d scan_ssid %d", id, 1);
|
ret = exec(cmd, str);
|
|
if (0 != ret || 0 == strlen(str) || 0 != strncmp(str, "OK", 2))
|
return -1;
|
|
return 0;
|
}
|
|
|
#define WIFI_CONNECT_RETRY 50
|
static bool check_wifi_isconnected(void)
|
{
|
|
return isWifiConnected;
|
}
|
|
static void check_ping_test()
|
{
|
char line[1024];
|
int ping_retry = 10;
|
int dns_retry;
|
|
while (ping_retry--) {
|
dns_retry = 5;
|
memset(line, 0, sizeof(line));
|
pr_info("check dns\n");
|
while (dns_retry--) {
|
exec("cat /etc/resolv.conf", line);
|
if (strstr(line, "nameserver"))
|
break;
|
sleep(1);
|
}
|
pr_info("dns ok: %s\n", line);
|
pr_info("to ping\n");
|
sync();
|
sleep(1);
|
memset(line, 0, sizeof(line));
|
exec("ping www.baidu.com -c 1", line);
|
//RK_shell_exec("ping 8.8.8.8 -c 1", line, sizeof(line));
|
//usleep(100000);
|
pr_info("line: %s\n", line);
|
//if (strstr(line, "PING www.baidu.com") && strstr(line, "bytes from")) {
|
//if (strstr(line, "PING 8.8.8.8") && strstr(line, "bytes from")) {
|
if (strstr(line, "bytes from")) {
|
pr_info("ping ok\n");
|
break;
|
}
|
usleep(200000);
|
}
|
}
|
|
static void* wifi_connect_state_check(void *arg)
|
{
|
return NULL;
|
}
|
|
int RK_wifi_connect(const char* ssid, const char* psk)
|
{
|
int ret = 0;
|
|
return ret;
|
}
|
|
int RK_wifi_forget_with_bssid(const char *bssid)
|
{
|
|
return 0;
|
}
|
|
int RK_wifi_cancel(void)
|
{
|
|
}
|
|
int RK_wifi_connect_with_ssid(const char *ssid)
|
{
|
return -1;
|
}
|
|
int RK_wifi_disconnect_network(void)
|
{
|
exec_command_system("wpa_cli -iwlan0 disconnect");
|
return 0;
|
}
|
|
int RK_wifi_reset(void)
|
{
|
|
}
|
|
int RK_wifi_recovery(void)
|
{
|
|
}
|
|
int RK_wifi_get_mac(char *wifi_mac)
|
{
|
int sock_mac;
|
struct ifreq ifr_mac;
|
char mac_addr[18] = {0};
|
|
if(!wifi_mac) {
|
pr_err("%s: wifi_mac is null\n", __func__);
|
return -1;
|
}
|
|
sock_mac = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (sock_mac == -1) {
|
pr_info("create mac socket failed.");
|
return -1;
|
}
|
|
memset(&ifr_mac, 0, sizeof(ifr_mac));
|
strncpy(ifr_mac.ifr_name, "wlan0", sizeof(ifr_mac.ifr_name) - 1);
|
|
if ((ioctl(sock_mac, SIOCGIFHWADDR, &ifr_mac)) < 0) {
|
pr_info("Mac socket ioctl failed.");
|
return -1;
|
}
|
|
sprintf(mac_addr, "%02X:%02X:%02X:%02X:%02X:%02X",
|
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[0],
|
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[1],
|
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[2],
|
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[3],
|
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[4],
|
(unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]);
|
|
close(sock_mac);
|
strncpy(wifi_mac, mac_addr, 18);
|
pr_info("the wifi mac : %s\r\n", wifi_mac);
|
|
return 0;
|
}
|
|
int RK_wifi_has_config()
|
{
|
|
}
|
|
int RK_wifi_ping(char *address)
|
{
|
|
}
|
|
#define EVENT_BUF_SIZE 1024
|
#define PROPERTY_VALUE_MAX 32
|
#define PROPERTY_KEY_MAX 32
|
#include <poll.h>
|
#include <wpa_ctrl.h>
|
static void wifi_close_sockets();
|
static const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE ";
|
static const char IFNAME[] = "IFNAME=";
|
static const char IFACE_DIR[] = "/var/run/wpa_supplicant";
|
#define WIFI_CHIP_TYPE_PATH "/sys/class/rkwifi/chip"
|
#define WIFI_DRIVER_INF "/sys/class/rkwifi/driver"
|
#define IFNAMELEN (sizeof(IFNAME) - 1)
|
static struct wpa_ctrl *ctrl_conn;
|
static struct wpa_ctrl *monitor_conn;
|
#define DBG_NETWORK 1
|
|
static int exit_sockets[2];
|
static char primary_iface[PROPERTY_VALUE_MAX] = "wlan0";
|
|
#define HOSTAPD "hostapd"
|
#define WPA_SUPPLICANT "wpa_supplicant"
|
#define DNSMASQ "dnsmasq"
|
#define UDHCPC "udhcpc"
|
|
static int get_pid(const char Name[]) {
|
int len;
|
char name[32] = {0};
|
len = strlen(Name);
|
strncpy(name,Name,len);
|
name[31] ='\0';
|
char cmdresult[256] = {0};
|
char cmd[64] = {0};
|
FILE *pFile = NULL;
|
int pid = 0;
|
|
sprintf(cmd, "pidof %s", name);
|
pFile = popen(cmd, "r");
|
if (pFile != NULL) {
|
while (fgets(cmdresult, sizeof(cmdresult), pFile)) {
|
pid = atoi(cmdresult);
|
break;
|
}
|
pclose(pFile);
|
}
|
return pid;
|
}
|
|
static void wifi_close_sockets() {
|
if (ctrl_conn != NULL) {
|
wpa_ctrl_close(ctrl_conn);
|
ctrl_conn = NULL;
|
}
|
|
if (monitor_conn != NULL) {
|
wpa_ctrl_close(monitor_conn);
|
monitor_conn = NULL;
|
}
|
|
if (exit_sockets[0] >= 0) {
|
close(exit_sockets[0]);
|
exit_sockets[0] = -1;
|
}
|
|
if (exit_sockets[1] >= 0) {
|
close(exit_sockets[1]);
|
exit_sockets[1] = -1;
|
}
|
}
|
|
static int str_starts_with(char * str, char * search_str)
|
{
|
if ((str == NULL) || (search_str == NULL))
|
return 0;
|
return (strstr(str, search_str) == str);
|
}
|
|
static void get_wifi_info_by_event(char *event, RK_WIFI_RUNNING_State_e state, RK_WIFI_INFO_Connection_s *info)
|
{
|
int len = 0;
|
char buf[10];
|
char *start_tag = NULL, *end_tag = NULL, *id_tag = NULL, *reason_tag = NULL;
|
|
if(event == NULL)
|
return;
|
|
memset(info, 0, sizeof(RK_WIFI_INFO_Connection_s));
|
RK_wifi_running_getConnectionInfo(info);
|
|
switch(state) {
|
case RK_WIFI_State_DISCONNECTED:
|
start_tag = strstr(event, "bssid=");
|
if(start_tag)
|
strncpy(info->bssid, start_tag + strlen("bssid="), 17);
|
|
//strncpy(info->ssid, connect_info.ssid, SSID_BUF_LEN);
|
reason_tag = strstr(event, "reason=");
|
if(reason_tag) {
|
memset(buf, 0, sizeof(buf));
|
strncpy(buf, reason_tag + strlen("reason="), 2);
|
info->reason = atoi(buf);
|
}
|
|
break;
|
|
case RK_WIFI_State_CONNECTFAILED_WRONG_KEY:
|
start_tag = strstr(event, "ssid=\"");
|
if(start_tag) {
|
end_tag = strstr(event, "\" auth_failures");
|
if(!end_tag) {
|
pr_err("%s: don't find end tag\n", __func__);
|
break;
|
}
|
len = strlen(start_tag) - strlen(end_tag) - strlen("ssid=\"");
|
char value[128] = {0};
|
char sname[128];
|
char sname1[128];
|
char utf8[128];
|
memset(sname, 0, sizeof(sname));
|
memset(sname1, 0, sizeof(sname));
|
memset(utf8, 0, sizeof(utf8));
|
strncpy(value, start_tag + strlen("ssid=\""), len);
|
spec_char_convers(value, sname);
|
remove_escape_character(sname, sname1);
|
get_encode_gbk_utf8(m_gbk_head, sname1, utf8);
|
pr_info("convers str: %s, sname: %s, ori: %s\n", value, sname1, utf8);
|
strncpy(info->ssid, utf8, strlen(utf8));
|
}
|
|
id_tag = strstr(event, "id=");
|
if(id_tag) {
|
len = strlen(id_tag) - strlen("id=") - strlen(start_tag) - 1;
|
memset(buf, 0, sizeof(buf));
|
strncpy(buf, id_tag + strlen("id="), len);
|
info->id = atoi(buf);
|
}
|
|
strncpy(info->bssid, connect_info.bssid, BSSID_BUF_LEN);
|
break;
|
}
|
}
|
|
static void get_valid_connect_info(RK_WIFI_INFO_Connection_s *info)
|
{
|
int count = 10;
|
|
while(count--) {
|
RK_wifi_running_getConnectionInfo(info);
|
if(!info->id && !strlen(info->ssid)
|
&& !strlen(info->bssid) && !info->freq
|
&& !strlen(info->mode) && !strlen(info->ip_address)
|
&& !strlen(info->mac_address) && !strlen(info->wpa_state)) {
|
pr_info("wait to get valid connect info\n");
|
usleep(100000);
|
} else {
|
break;
|
}
|
}
|
}
|
|
static int dispatch_event(char* event)
|
{
|
RK_WIFI_INFO_Connection_s info;
|
|
if (strstr(event, "CTRL-EVENT-BSS") || strstr(event, "CTRL-EVENT-TERMINATING"))
|
return 0;
|
|
pr_info("%s: %s\n", __func__, event);
|
|
if (str_starts_with(event, (char *)WPA_EVENT_DISCONNECTED)) {
|
pr_info("%s: wifi is disconnect\n", __FUNCTION__);
|
exec_command_system("ip addr flush dev wlan0");
|
get_wifi_info_by_event(event, RK_WIFI_State_DISCONNECTED, &info);
|
wifi_state_send(RK_WIFI_State_DISCONNECTED, &info);
|
exec_command_system("wpa_cli -i wlan0 reconnect");
|
} else if (str_starts_with(event, (char *)WPA_EVENT_CONNECTED)) {
|
pr_info("%s: wifi is connected\n", __func__);
|
get_valid_connect_info(&info);
|
wifi_state_send(RK_WIFI_State_CONNECTED, &info);
|
} else if (str_starts_with(event, (char *)WPA_EVENT_SCAN_RESULTS)) {
|
pr_info("%s: wifi event results\n", __func__);
|
exec_command_system("echo 1 > /tmp/scan_r");
|
wifi_state_send(RK_WIFI_State_SCAN_RESULTS, NULL);
|
} else if (strstr(event, "reason=WRONG_KEY")) {
|
wifi_wrong_key = true;
|
pr_info("%s: wifi reason=WRONG_KEY \n", __func__);
|
get_wifi_info_by_event(event, RK_WIFI_State_CONNECTFAILED_WRONG_KEY, &info);
|
wifi_state_send(RK_WIFI_State_CONNECTFAILED_WRONG_KEY, &info);
|
} else if (str_starts_with(event, (char *)WPA_EVENT_TERMINATING)) {
|
pr_info("%s: wifi is WPA_EVENT_TERMINATING!\n", __func__);
|
wifi_close_sockets();
|
return -1;
|
}
|
|
return 0;
|
}
|
|
static int check_wpa_supplicant_state() {
|
int count = 5;
|
int wpa_supplicant_pid = 0;
|
wpa_supplicant_pid = get_pid(WPA_SUPPLICANT);
|
//pr_info("%s: wpa_supplicant_pid = %d\n",__FUNCTION__,wpa_supplicant_pid);
|
if(wpa_supplicant_pid > 0) {
|
return 1;
|
}
|
return 0;
|
}
|
|
static int wifi_ctrl_recv(char *reply, size_t *reply_len)
|
{
|
int res;
|
int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
|
struct pollfd rfds[2];
|
|
memset(rfds, 0, 2 * sizeof(struct pollfd));
|
rfds[0].fd = ctrlfd;
|
rfds[0].events |= POLLIN;
|
rfds[1].fd = exit_sockets[1];
|
rfds[1].events |= POLLIN;
|
do {
|
res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000));
|
if (res < 0) {
|
pr_info("Error poll = %d\n", res);
|
return res;
|
} else if (res == 0) {
|
/* timed out, check if supplicant is activeor not .. */
|
res = check_wpa_supplicant_state();
|
if (res < 0)
|
return -2;
|
}
|
} while (res == 0);
|
|
if (rfds[0].revents & POLLIN) {
|
return wpa_ctrl_recv(monitor_conn, reply, reply_len);
|
}
|
return -2;
|
}
|
|
static int wifi_wait_on_socket(char *buf, size_t buflen)
|
{
|
size_t nread = buflen - 1;
|
int result;
|
char *match, *match2;
|
|
if (monitor_conn == NULL) {
|
return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
|
primary_iface, WPA_EVENT_TERMINATING);
|
}
|
|
result = wifi_ctrl_recv(buf, &nread);
|
|
/* Terminate reception on exit socket */
|
if (result == -2) {
|
return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
|
primary_iface, WPA_EVENT_TERMINATING);
|
}
|
|
if (result < 0) {
|
//pr_info("wifi_ctrl_recv failed: %s\n", strerror(errno));
|
//return snprintf(buf, buflen, "IFNAME=%s %s - recv error",
|
// primary_iface, WPA_EVENT_TERMINATING);
|
}
|
|
buf[nread] = '\0';
|
|
/* Check for EOF on the socket */
|
if (result == 0 && nread == 0) {
|
/* Fabricate an event to pass up */
|
pr_info("Received EOF on supplicant socket\n");
|
return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received",
|
primary_iface, WPA_EVENT_TERMINATING);
|
}
|
|
if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
|
match = strchr(buf, ' ');
|
if (match != NULL) {
|
if (match[1] == '<') {
|
match2 = strchr(match + 2, '>');
|
if (match2 != NULL) {
|
nread -= (match2 - match);
|
memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
|
}
|
}
|
} else {
|
return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
|
}
|
} else if (buf[0] == '<') {
|
match = strchr(buf, '>');
|
if (match != NULL) {
|
nread -= (match + 1 - buf);
|
memmove(buf, match + 1, nread + 1);
|
if (0)
|
pr_info("supplicant generated event without interface - %s\n", buf);
|
}
|
} else {
|
if (0)
|
pr_info("supplicant generated event without interface and without message level - %s\n", buf);
|
}
|
|
return nread;
|
}
|
|
static int wifi_connect_on_socket_path(const char *path)
|
{
|
char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
|
|
if(!check_wpa_supplicant_state()) {
|
pr_info("%s: wpa_supplicant is not ready\n",__FUNCTION__);
|
return -1;
|
}
|
|
ctrl_conn = wpa_ctrl_open(path);
|
if (ctrl_conn == NULL) {
|
pr_info("Unable to open connection to supplicant on \"%s\": %s\n",
|
path, strerror(errno));
|
return -1;
|
}
|
monitor_conn = wpa_ctrl_open(path);
|
if (monitor_conn == NULL) {
|
wpa_ctrl_close(ctrl_conn);
|
ctrl_conn = NULL;
|
return -1;
|
}
|
if (wpa_ctrl_attach(monitor_conn) != 0) {
|
wpa_ctrl_close(monitor_conn);
|
wpa_ctrl_close(ctrl_conn);
|
ctrl_conn = monitor_conn = NULL;
|
return -1;
|
}
|
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
|
wpa_ctrl_close(monitor_conn);
|
wpa_ctrl_close(ctrl_conn);
|
ctrl_conn = monitor_conn = NULL;
|
return -1;
|
}
|
return 0;
|
}
|
|
/* Establishes the control and monitor socket connections on the interface */
|
static int wifi_connect_to_supplicant()
|
{
|
static char path[1024];
|
int count = 10;
|
|
pr_info("%s \n", __FUNCTION__);
|
while(count-- > 0) {
|
if (access(IFACE_DIR, F_OK) == 0)
|
break;
|
sleep(1);
|
}
|
|
snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
|
|
return wifi_connect_on_socket_path(path);
|
}
|
|
static void RK_wifi_start_monitor(void *arg)
|
{
|
char eventStr[EVENT_BUF_SIZE];
|
int ret;
|
|
prctl(PR_SET_NAME,"RK_wifi_start_monitor");
|
|
if ((ret = wifi_connect_to_supplicant()) != 0) {
|
pr_info("%s, connect to supplicant fail.\n", __FUNCTION__);
|
return;
|
}
|
|
for (;;) {
|
memset(eventStr, 0, EVENT_BUF_SIZE);
|
if (!wifi_wait_on_socket(eventStr, EVENT_BUF_SIZE))
|
continue;
|
|
if (dispatch_event(eventStr)) {
|
pr_info("disconnecting from the supplicant, no more events\n");
|
break;
|
}
|
}
|
}
|
|
static void execute(const char cmdline[], char recv_buff[], int len)
|
{
|
//pr_info("[AIRKISS] execute: %s\n", cmdline);
|
|
FILE *stream = NULL;
|
char *tmp_buff = recv_buff;
|
|
if ((stream = popen(cmdline, "r")) == NULL) {
|
pr_info("[AIRKISS] execute: %s failed\n", cmdline);
|
return;
|
}
|
|
if (recv_buff == NULL) {
|
pclose(stream);
|
return;
|
}
|
|
memset(recv_buff, 0, len);
|
while (fgets(tmp_buff, len, stream)) {
|
tmp_buff += strlen(tmp_buff);
|
len -= strlen(tmp_buff);
|
if (len <= 1) {
|
pr_info("[AIRKISS] overflow, please enlarge recv_buff\n");
|
break;
|
}
|
}
|
pclose(stream);
|
}
|
|
static int start_airkiss()
|
{
|
int ret = -1, cnt = 3;
|
|
while(cnt--) {
|
exec_command_system("rm /tmp/airkiss.conf");
|
exec_command_system("killall rk_airkiss");
|
usleep(500000);
|
exec_command_system("rk_airkiss &");
|
usleep(500000);
|
|
if(get_pid("rk_airkiss") > 0) {
|
pr_info("[AIRKISS] start rk_airkiss success, cnt: %d\n", cnt);
|
ret = 0;
|
break;
|
}
|
}
|
|
return ret;
|
}
|
|
static bool check_airkiss_conf()
|
{
|
int wait_cnt = 60;
|
bool file_exist = false;
|
|
while (wait_cnt--) {
|
pr_info("[AIRKISS] check airkiss conf, wait_cnt: %d\n", wait_cnt);
|
if (access("/tmp/airkiss.conf", F_OK) == 0) {
|
pr_info("[AIRKISS] geted airkiss data\n");
|
file_exist = true;
|
break;
|
}
|
sleep(1);
|
}
|
|
return file_exist;
|
}
|
|
static void get_airkiss_ssid_password(char *ssid, char *password)
|
{
|
char *cp;
|
char ret_buf[1024];
|
|
/*
|
* cat /tmp/airkiss.conf
|
* rk_ssid=<unknown ssid>
|
* rk_password=cccccc
|
*/
|
execute("cat /tmp/airkiss.conf | grep rk_ssid", ret_buf, 1024);
|
pr_info("[AIRKISS] ssid ret_buf: %s\n", ret_buf);
|
if (cp = strstr(ret_buf, "=")) {
|
strcpy(ssid, cp + 1);
|
ssid[strlen(ssid) - 1] = '\0';
|
}
|
|
execute("cat /tmp/airkiss.conf | grep rk_password", ret_buf, 1024);
|
pr_info("[AIRKISS] password ret_buf: %s\n", ret_buf);
|
if (cp = strstr(ret_buf, "=")) {
|
strcpy(password, cp + 1);
|
password[strlen(password) - 1] = '\0';
|
}
|
|
pr_info("[AIRKISS] SSID: %s[%d], PSK: %s[%d]\n", ssid, strlen(ssid), password, strlen(password));
|
}
|
|
static int RK_wifi_rtl_airkiss_start(char *ssid, char *password)
|
{
|
int reset_cnt = 1;
|
bool file_exist = false;
|
|
pr_info("=== %s ===\n", __func__);
|
|
retry:
|
if(start_airkiss() < 0) {
|
pr_info("[AIRKISS] start rk_airkiss failed\n");
|
return -1;
|
}
|
|
file_exist = check_airkiss_conf();
|
|
if ((!file_exist) && (--reset_cnt)) {
|
pr_info("[AIRKISS] geted airkiss data failed, reset_cnt: %d\n", reset_cnt);
|
goto retry;
|
}
|
|
if (!file_exist) {
|
pr_info("[AIRKISS] don't get airkiss data\n");
|
exec_command_system("killall rk_airkiss");
|
return -1;
|
}
|
|
get_airkiss_ssid_password(ssid, password);
|
return 0;
|
}
|
|
static void RK_wifi_rtl_airkiss_stop()
|
{
|
exec_command_system("rm /tmp/airkiss.conf");
|
exec_command_system("killall rk_airkiss");
|
}
|
|
int RK_wifi_airkiss_start(char *ssid, char *password)
|
{
|
#ifdef REALTEK
|
return RK_wifi_rtl_airkiss_start(ssid, password);
|
#else
|
pr_info("Currently only supports realtek airkiss config\n");
|
return -1;
|
#endif
|
}
|
|
void RK_wifi_airkiss_stop()
|
{
|
#ifdef REALTEK
|
return RK_wifi_rtl_airkiss_stop();
|
#else
|
pr_info("Currently only supports realtek airkiss config\n");
|
#endif
|
}
|