#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_TAG "RK_BCM_LOG" #define SYSLOG_DEBUG #define DEBUG 1 #ifdef SYSLOG_DEBUG #define pr_debug(fmt, ...) syslog(LOG_DEBUG, fmt, ##__VA_ARGS__) #define pr_info(fmt, ...) syslog(LOG_INFO, fmt, ##__VA_ARGS__) #define pr_warning(fmt, ...) syslog(LOG_WARNING, fmt, ##__VA_ARGS__) #define pr_err(fmt, ...) syslog(LOG_ERR, fmt, ##__VA_ARGS__) #else #define pr_debug printf #define pr_info printf #define pr_warning printf #define pr_err printf #endif static int system_fd_closexec(const char* command) { int wait_val = 0; pid_t pid = -1; if (!command) return 1; if ((pid = vfork()) < 0) return -1; if (pid == 0) { int i = 0; int stdin_fd = fileno(stdin); int stdout_fd = fileno(stdout); int stderr_fd = fileno(stderr); long sc_open_max = sysconf(_SC_OPEN_MAX); if (sc_open_max < 0) { sc_open_max = 20000; /* enough? */ } /* close all descriptors in child sysconf(_SC_OPEN_MAX) */ for (i = 0; i < sc_open_max; i++) { if (i == stdin_fd || i == stdout_fd || i == stderr_fd) continue; close(i); } execl(_PATH_BSHELL, "sh", "-c", command, (char*)0); _exit(127); } while (waitpid(pid, &wait_val, 0) < 0) { if (errno != EINTR) { wait_val = -1; break; } } return wait_val; } static int rk_command_system(const char *cmd) { pid_t status; status = system_fd_closexec(cmd); if (-1 == status) { pr_err("[system_exec_err] -1\n"); return -1; } else { if (WIFEXITED(status)) { if (0 == WEXITSTATUS(status)) { return 0; } else { pr_err("[system_exec_err] -2\n"); return -2; } } else { pr_err("[system_exec_err] -3\n"); return -3; } } return 0; } void rk_command(const char cmdline[], char recv_buff[], int len) { if (DEBUG) pr_info("[BT_DEBUG] execute: %s\n", cmdline); FILE *stream = NULL; char *tmp_buff = recv_buff; memset(recv_buff, 0, len); if ((stream = popen(cmdline, "r")) != NULL) { while (fgets(tmp_buff, len, stream)) { //pr_info("tmp_buf[%d]: %s\n", strlen(tmp_buff), tmp_buff); tmp_buff += strlen(tmp_buff); len -= strlen(tmp_buff); if (len <= 1) break; } if (DEBUG) pr_info("[BT_DEBUG] execute_r: %s \n", recv_buff); pclose(stream); } else pr_err("[popen] error: %s\n", cmdline); } static int rk_get_pid(const char Name[]) { int len; char name[32] = {0}; char cmdresult[256] = {0}; char cmd[64] = {0}; FILE *pFile = NULL; int pid = 0; len = strlen(Name); strncpy(name,Name,len); name[31] ='\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; } int rk_kill_task(char *name) { char cmd[128] = {0}; int exec_cnt = 3, retry_cnt = 10; if (!rk_get_pid(name)) return 0; memset(cmd, 0, 128); sprintf(cmd, "killall %s", name); while(exec_cnt) { if(!rk_command_system(cmd)) break; exec_cnt--; } if(exec_cnt <= 0) { pr_info("%s: kill %s failed\n", __func__, name); return -1; } msleep(100); retry: if (rk_get_pid(name) && (retry_cnt--)) { msleep(100); goto retry; } pr_info("%s: kill %s, retry_cnt = %d\n", __func__, name, retry_cnt); if (rk_get_pid(name)) return -1; else return 0; } int rk_run_task(char *name, char *cmd) { int exec_cnt = 3, retry_cnt = 6; while(exec_cnt) { if(!rk_command_system(cmd)) break; exec_cnt--; } if(exec_cnt <= 0) { pr_info("%s: run %s failed\n", __func__, name); return -1; } msleep(100); retry: if (!rk_get_pid(name) && (retry_cnt--)) { msleep(100); goto retry; } if (!rk_get_pid(name)) return -1; else return 0; } /****** wpa_supplicant ******/ #include #include #define EVENT_BUF_SIZE 1024 #define PROPERTY_VALUE_MAX 32 #define PROPERTY_KEY_MAX 32 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 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[32] = "wlan0"; static int dispatch_event(char* event) { 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__); rk_command_system("ip addr flush dev wlan0"); rk_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__); } else if (str_starts_with(event, (char *)WPA_EVENT_SCAN_RESULTS)) { pr_info("%s: wifi event results\n", __func__); } else if (strstr(event, "reason=WRONG_KEY")) { pr_info("%s: wifi reason=WRONG_KEY \n", __func__); } 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_suppplicant"); 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_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; } } } /****** wpa_supplicant end ******/ void rk_wifi_module_init() { rk_command_system("insmod /vendor/lib/modules/bcmdhd_indep_power.ko"); } void rk_wifi_module_exit() { rk_command_system("rmmod bcmdhd_indep_power"); } void rk_wifi_disconnect_ap() { rk_command_system("killall wpa_supplicant"); } int rk_get_dhcp() { char cmd[128], cmd_results[128]; int cnt = 60; rk_command_system("udhcpc -i wlan0 -t 15 -q"); retry: rk_command("ifconfig wlan0 | grep inet | awk '{print $2}' | awk -F: '{print $2}' | awk -F. '{print $1}'", cmd_results, 128); if ((cmd_results[0] == 0) && (cmd_results[0] == 127) && (cmd_results[0] == 169)) { sleep(1); if (cnt--) goto retry; if (cnt == 0) { pr_err("dhcp fail!!!\n"); return -1; } } return 1; } int rk_wifi_get_status(void) { char cmd_results[128]; int cnt = 60; retry: rk_command("wl status | grep BSSID: | awk '{print $2}'", cmd_results, 128); if ((cmd_results[0] == 0) || (strncmp(cmd_results, "00:00:00:00:00:00", 17))) { sleep(1); if (cnt--) goto retry; if (cnt == 0) { pr_err("status: unknow\n"); return -1; } } pr_err("status: connected!\n"); return 1; } int rk_wifi_get_channel(void) { char cmd_results[128]; rk_command("wl status | grep Channel | awk '{print $17}'", cmd_results, 128); return cmd_results[0]; } char *rk_wifi_get_wakeup_reason(void) { char cmd_results[128]; rk_command("dhd_priv wl wowl_wakeind | grep wakeind | awk '{print $4}' | sed -n '2p' | awk -F= '{print $2}'", cmd_results, 128); pr_err("wakeup_reason: %s\n", cmd_results); return cmd_results; } int rk_wifi_get_signal(void) { char cmd_results[128]; int signal = 0; rk_command("wl status | grep noise | awk '{print $10}'", cmd_results, 128); signal = atoi(cmd_results[0]); pr_err("signal: %d\n", signal); return signal; } int rk_wifi_set_net_info(char *ip, char *mask, char *gw, char *dns) { char cmd[128]; memset(cmd, 0, 128); sprintf(cmd, "ifconfig wlan0 %s netmask %s", ip, mask); rk_command_system(cmd); memset(cmd, 0, 128); sprintf(cmd, "route add default gw %s", gw); rk_command_system(cmd); memset(cmd, 0, 128); sprintf(cmd, "echo \"nameserver %s\" > /etc/resolv.conf", dns); rk_command_system(cmd); return 1; } int rk_wifi_set_ssid_for_wakeup(void) { return 1; } int rk_wifi_clr_ssid_for_wakeup(void) { return 1; } int rk_wifi_start(void) { } int rk_wifi_restart(void) { } void rk_wifi_scan(void) { } int rk_wifi_scan_results(struct wpa_ap_info *pslt, int num) { } void rk_wifi_connect_ap(char *ssid, char *psk) { char cmd[128], cmd_results[128]; int cnt = 60; rk_command_system("ifconfig wlan0 down"); usleep(500*100); rk_command_system("ifconfig wlan0 up"); usleep(500*100); rk_command_system("cp /etc/wpa_supplicant.conf /tmp/ -rf"); memset(cmd, 0, 128); sprintf(cmd, "sed -i \"s/SSID/%s/g\" /tmp/wpa_supplicant.conf", ssid); rk_command_system(cmd); memset(cmd, 0, 128); sprintf(cmd, "sed -i \"s/PASSWORD/%s/g\" /tmp/wpa_supplicant.conf", psk); rk_command_system(cmd); if (rk_get_pid("wpa_supplicant") > 0) rk_kill_task("wpa_supplicant"); if (rk_run_task("wpa_supplicant", "wpa_supplicant -B -i wlan0 -c /tmp/wpa_supplicant.conf")) { pr_err("wpa_supplicant start fail!!!\n"); return; } sleep(1); rk_wifi_get_status(); rk_get_dhcp(); } void rk_wifi_set_tcp_port(int port) { } static char wowl_pattern[256]; void rk_wifi_set_tcp_wakeup_data(int offset, int num, char *data) { int mask; for (int i = 0; i < num; i++) mask |= (0x1 < i); memset(wowl_pattern, 0, 256); sprintf(wowl_pattern, "wl_cy wowl_pattern add %d 0x%x %s", offset, mask, data); } void rk_wifi_suspend(void) { int fd, size; char buf[200]; fd = open("/proc/tcp_params", O_RDONLY); memset(buf, 0, 200); lseek(fd, 0, SEEK_SET); size = read(fd, buf, 200); rk_command_system("wl_cy tcpka_conn_mode 1"); usleep(200*200); pr_info("buf: %s\n", buf); rk_command_system(buf); usleep(200*200); rk_command_system("wl_cy tcpka_conn_enable 1 1 30 1 8"); usleep(200*200); rk_command_system("wl_cy wowl 131094"); usleep(200*200); //printf("wl_cy wowl_pattern add 54 0x07 0x313233\n"); //rk_command_system("wl_cy wowl_pattern add 54 0x07 0x313233"); //usleep(200*200); //printf("wl_cy wowl_pattern add 66 0x07 0x313233\n"); //rk_command_system("wl_cy wowl_pattern add 66 0x07 0x313233"); pr_info("wowl_pattern: %s\n"); rk_command_system(wowl_pattern); usleep(200*200); rk_command_system("wl_cy wowl_activate 1"); usleep(200*200); rk_command_system("wl_cy PM 2"); usleep(200*200); rk_command_system("wl_cy hostsleep 1"); usleep(200*200); rk_command_system("killall wpa_supplicant"); }