From: Seongil Hahm Date: Mon, 25 Sep 2017 10:14:00 +0000 (-0700) Subject: Introduce w_info_mutex to protect g_manager_info of wifi_manager while limiting the... X-Git-Tag: 1.1_Public_Release~137^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f37cb00113cb053c5ba3759f6c8ace74eee2d50a;p=rtos%2Ftinyara.git Introduce w_info_mutex to protect g_manager_info of wifi_manager while limiting the role of w_mutex to serializing wifi_manager APIs 1. By using this w_info_mutex, deadlock between wifi_manager and slsi_wifi callback is resolved. 2. Introduce additional wifi_manager status: WIFI_MODE_CHAING, WIFI_INITIALIZING, WIFI_DEINITIALIZING, and WIFI_FAILURE. In case of WIFI_FAILURE, app developers are requested to deinit and init wifi_manager. 3. wifi_manager_set_mode() returns WIFI_MANAGER_INVALID_ARGS when mode is softap without config. --- diff --git a/apps/examples/testcase/ta_tc/wifi_manager/utc/utc_wifi_manager_main.c b/apps/examples/testcase/ta_tc/wifi_manager/utc/utc_wifi_manager_main.c index e82cfc8..3e5550c 100644 --- a/apps/examples/testcase/ta_tc/wifi_manager/utc/utc_wifi_manager_main.c +++ b/apps/examples/testcase/ta_tc/wifi_manager/utc/utc_wifi_manager_main.c @@ -143,7 +143,7 @@ static void utc_wifi_manager_set_mode_n(void) ret = wifi_manager_set_mode(SOFTAP_MODE, NULL); - TC_ASSERT_EQ("wifi_manager_set_mode_n", ret, WIFI_MANAGER_FAIL); + TC_ASSERT_EQ("wifi_manager_set_mode_n", ret, WIFI_MANAGER_INVALID_ARGS); wifi_manager_softap_config_s ap_config; strncpy(ap_config.ssid, CONFIG_EXAMPLES_TESTCASE_WIFI_MANAGER_UTC_SOFTAP_SSID, \ @@ -388,7 +388,7 @@ int wifi_manager_utc(int argc, FAR char *argv[]) utc_wifi_utils_disconnect_ap_p(); WIFITEST_WAIT; - + utc_wifi_utils_disconnect_ap_n(); // Should be run after positive tc, that is, the second disconnect gets failed. utc_wifi_manager_deinit_p(); diff --git a/framework/include/wifi_manager/wifi_manager.h b/framework/include/wifi_manager/wifi_manager.h index 5edea22..f18fc71 100644 --- a/framework/include/wifi_manager/wifi_manager.h +++ b/framework/include/wifi_manager/wifi_manager.h @@ -60,7 +60,11 @@ typedef enum { typedef enum { WIFI_NONE = -1, STA_MODE, - SOFTAP_MODE + SOFTAP_MODE, + WIFI_MODE_CHANGING, + WIFI_INITIALIZING, + WIFI_DEINITIALIZING, + WIFI_FAILURE } wifi_manager_mode_e; typedef enum { diff --git a/framework/src/wifi_manager/wifi_manager.c b/framework/src/wifi_manager/wifi_manager.c index 89ec492..935489a 100644 --- a/framework/src/wifi_manager/wifi_manager.c +++ b/framework/src/wifi_manager/wifi_manager.c @@ -55,6 +55,7 @@ void __tizenrt_manual_linkset(const char *msg) static wifi_manager_info_s g_manager_info; static wifi_manager_cb_s *g_manager_callback = NULL; static wifi_mutex *w_mutex = NULL; +static wifi_mutex *w_info_mutex = NULL; static wifi_utils_result_e start_dhcp_client(void) { @@ -69,6 +70,7 @@ static wifi_utils_result_e start_dhcp_client(void) ret = dhcpc_request(g_dhcp_handle, &state); if (ret != OK) { dhcpc_close(g_dhcp_handle); + g_dhcp_handle = NULL; return WIFI_UTILS_FAIL; } @@ -148,8 +150,7 @@ static void wifi_linkup_event_func(void) wifi_manager_cb_s *wifi_cb = g_manager_callback; wifi_utils_info info; - wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); - + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); if (g_manager_info.mode == STA_MODE) { nvdbg("WIFI CONNECTED AP - STA MODE"); wifi_status_set(AP_CONNECTED); @@ -157,7 +158,8 @@ static void wifi_linkup_event_func(void) /* Perform DHCP client */ if (start_dhcp_client() != WIFI_UTILS_SUCCESS) { ndbg("DHCP client start failed\n"); - wifi_mutex_release(w_mutex); + g_manager_info.mode = WIFI_FAILURE; + wifi_mutex_release(w_info_mutex); return; } if (stop_dhcp_client() != WIFI_UTILS_SUCCESS) { @@ -174,8 +176,7 @@ static void wifi_linkup_event_func(void) g_manager_info.status = STATUS_UNKNOWN; } strncpy(g_manager_info.ip4_address, ip4_add_str, 18); - - wifi_mutex_release(w_mutex); + wifi_mutex_release(w_info_mutex); if (wifi_cb != NULL && wifi_cb->sta_connected != NULL) { wifi_cb->sta_connected(); @@ -185,8 +186,7 @@ static void wifi_linkup_event_func(void) } else if (g_manager_info.mode == SOFTAP_MODE) { nvdbg("CONNECTED FROM CLIENT - SOFT AP MODE"); wifi_status_set(CLIENT_CONNECTED); - - wifi_mutex_release(w_mutex); + wifi_mutex_release(w_info_mutex); /* No callbacks here, in case new client joins, we invoke callback * from DHCP server instead @@ -207,7 +207,7 @@ static void wifi_linkdown_event_func(void) // wifi_manager_init() creates the callback handler and deinit() joins the callback handler. wifi_manager_cb_s *wifi_cb = g_manager_callback; - wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); if (g_manager_info.mode == STA_MODE) { nvdbg("WIFI DISCONNECTED AP - STA MODE"); @@ -215,6 +215,7 @@ static void wifi_linkdown_event_func(void) g_manager_info.ip4_address[0] = '\0'; g_manager_info.rssi = 0; wifi_status_set(AP_DISCONNECTED); + wifi_mutex_release(w_info_mutex); if (wifi_cb != NULL && wifi_cb->sta_disconnected != NULL) { wifi_cb->sta_disconnected(); @@ -224,6 +225,8 @@ static void wifi_linkdown_event_func(void) } else if (g_manager_info.mode == SOFTAP_MODE) { nvdbg("DISCONNECTED FROM CLIENT - SOFT AP MODE"); wifi_status_set(CLIENT_DISCONNECTED); + wifi_mutex_release(w_info_mutex); + if (wifi_cb != NULL && wifi_cb->softap_sta_left != NULL) { wifi_cb->softap_sta_left(); } else { @@ -231,8 +234,6 @@ static void wifi_linkdown_event_func(void) } } - wifi_mutex_release(w_mutex); - #ifdef CONFIG_ENABLE_IOTIVITY __tizenrt_manual_linkset("del"); #endif @@ -339,18 +340,19 @@ wifi_manager_result_e wifi_manager_connect_ap(wifi_manager_ap_config_s *config) wifi_utils_info info; wifi_utils_ap_config_s util_config; + wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); if (wifi_utils_get_info(&info) != WIFI_UTILS_SUCCESS) { ndbg("Wi-Fi info retrival fails.\n"); + wifi_mutex_release(w_mutex); return WIFI_MANAGER_FAIL; } if (info.wifi_status == WIFI_UTILS_SOFTAP_MODE) { ndbg("Current mode soft ap mode, can not connect ap"); + wifi_mutex_release(w_mutex); return WIFI_MANAGER_FAIL; } - wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); - strncpy(util_config.ssid, config->ssid, config->ssid_length + 1); util_config.ssid_length = config->ssid_length; strncpy(util_config.passphrase, config->passphrase, config->passphrase_length + 1); @@ -364,10 +366,11 @@ wifi_manager_result_e wifi_manager_connect_ap(wifi_manager_ap_config_s *config) wifi_mutex_release(w_mutex); return WIFI_MANAGER_FAIL; } + wifi_mutex_release(w_mutex); + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); strncpy(g_manager_info.ssid, config->ssid, config->ssid_length + 1); - - wifi_mutex_release(w_mutex); + wifi_mutex_release(w_info_mutex); return WIFI_MANAGER_SUCCESS; } @@ -393,119 +396,184 @@ wifi_manager_result_e wifi_manager_init(wifi_manager_cb_s *wmcb) return WIFI_MANAGER_FAIL; } + if (w_info_mutex == NULL) { + w_info_mutex = (wifi_mutex *)malloc(sizeof(wifi_mutex)); + if (w_info_mutex == NULL) { + ndbg("w_info_mutex malloc fails.\n"); + return WIFI_MANAGER_FAIL; + } + result = wifi_mutex_create(w_info_mutex); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("w_info_mutex_create fail"); + goto error_without_mutex_release; + } + } + + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); if (w_mutex != NULL) { ndbg("WI-FI is already initialized.\n"); + wifi_mutex_release(w_info_mutex); return WIFI_MANAGER_INITIALIZED; } w_mutex = (wifi_mutex *)malloc(sizeof(wifi_mutex)); if (w_mutex == NULL) { ndbg("w_mutex malloc fails.\n"); - return WIFI_MANAGER_FAIL; + wifi_mutex_release(w_info_mutex); + goto error_with_mutex_destory; } result = wifi_mutex_create(w_mutex); if (result != WIFI_UTILS_SUCCESS) { ndbg("wifi_mutex_create fail"); - goto error_without_mutex_release; + wifi_mutex_release(w_info_mutex); + goto error_with_mutex_destory; } - wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); + /* wifi_manager mode is switched to wifi_initializing */ + g_manager_info.mode = WIFI_INITIALIZING; + wifi_mutex_release(w_info_mutex); - result = wifi_utils_init(); +#ifdef CONFIG_ENABLE_IOTIVITY + struct mq_attr lq_attr; + lq_attr.mq_maxmsg = 10; + lq_attr.mq_msgsize = 4; + lq_attr.mq_flags = 0; + g_dw_nwevent_mqfd = mq_open("netlink_evtq", O_WRONLY | O_CREAT, 0666, &lq_attr); + if (g_dw_nwevent_mqfd == (mqd_t)ERROR) { + ndbg("iotivity connect event message queue init fail"); + goto error_with_mutex_destory_all; + } +#endif + + wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); + result = wifi_utils_init(); if (result != WIFI_UTILS_SUCCESS) { ndbg("wifi_utils_init fail"); goto error_with_mutex_release; } wifi_utils_register_callback(wifi_linkup_event_func, wifi_linkdown_event_func); + + if (wifi_utils_get_info(&info) != WIFI_UTILS_SUCCESS) { + ndbg("wifi_utils_get_info fail"); + goto error_with_mutex_release; + } + wifi_mutex_release(w_mutex); + + /* update wifi_manager info by being protected by w_info_mutex */ + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); g_manager_info.ssid[0] = '\0'; g_manager_info.ip4_address[0] = '\0'; g_manager_info.rssi = 0; g_manager_info.mode = STA_MODE; g_manager_callback = wmcb; wifi_status_set(AP_DISCONNECTED); - - if (wifi_utils_get_info(&info) != WIFI_UTILS_SUCCESS) { - ndbg("wifi_utils_get_info fail"); - goto error_with_mutex_release; - } strncpy(g_manager_info.mac_address, info.mac_address, 6); + wifi_mutex_release(w_info_mutex); + + return WIFI_MANAGER_SUCCESS; +error_with_mutex_release: wifi_mutex_release(w_mutex); #ifdef CONFIG_ENABLE_IOTIVITY - struct mq_attr lq_attr; - lq_attr.mq_maxmsg = 10; - lq_attr.mq_msgsize = 4; - lq_attr.mq_flags = 0; - g_dw_nwevent_mqfd = mq_open("netlink_evtq", O_WRONLY | O_CREAT, 0666, &lq_attr); - - if (g_dw_nwevent_mqfd == (mqd_t)ERROR) { - ndbg("iotivity connect event message queue init fail"); - goto error_with_mutex_destory; - } +error_with_mutex_destory_all: #endif + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); + g_manager_info.mode = WIFI_NONE; - return WIFI_MANAGER_SUCCESS; + result = wifi_mutex_destroy(w_mutex); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("wifi_mutex_destroy fail %d", result); + } + wifi_mutex_release(w_info_mutex); -error_with_mutex_release: - wifi_mutex_release(w_mutex); -#ifdef CONFIG_ENABLE_IOTIVITY error_with_mutex_destory: -#endif - result = wifi_mutex_destroy(w_mutex); - if (result != WIFI_UTILS_SUCCESS) { - ndbg("wifi_mutex_destroy fail %d", result); - return WIFI_MANAGER_FAIL; - } + result = wifi_mutex_destroy(w_info_mutex); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("w_info_mutex_destroy fail %d", result); + } + error_without_mutex_release: + if (w_mutex != NULL) { free(w_mutex); w_mutex = NULL; - return WIFI_MANAGER_FAIL; + } + if (w_info_mutex != NULL) { + free(w_info_mutex); + w_info_mutex = NULL; + } + + return WIFI_MANAGER_FAIL; } wifi_manager_result_e wifi_manager_deinit() { wifi_utils_result_e result = WIFI_UTILS_SUCCESS; + wifi_manager_result_e ret = WIFI_MANAGER_SUCCESS; if ((g_manager_info.mode == WIFI_NONE) || (w_mutex == NULL)) { ndbg("WI-FI is already deinitialized.\n"); return WIFI_MANAGER_DEINITIALIZED; } - wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); - - if ((g_manager_info.mode == SOFTAP_MODE) && (stop_dhcp_server() != WIFI_UTILS_SUCCESS)) { - ndbg("dhcp server stop fail\n"); - wifi_mutex_release(w_mutex); + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); + /* wifi_manager mode is switched to wifi_deinitializing */ + if ((g_manager_info.mode != WIFI_INITIALIZING) && (g_manager_info.mode != WIFI_MODE_CHANGING) && \ + (g_manager_info.mode != WIFI_DEINITIALIZING)) { + g_manager_info.mode = WIFI_DEINITIALIZING; + } else { + ndbg("Can't deinitilize wifi_manager from the current wifi mode %d\n", g_manager_info.mode); + wifi_mutex_release(w_info_mutex); return WIFI_MANAGER_FAIL; } - result = wifi_utils_deinit(); + if ((g_manager_info.mode == SOFTAP_MODE) || (g_manager_info.mode == WIFI_FAILURE)) { + stop_dhcp_server(); + } + wifi_mutex_release(w_info_mutex); + wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); + result = wifi_utils_deinit(); if (result != WIFI_UTILS_SUCCESS) { ndbg("wifi_utils_deinit fail"); - wifi_mutex_release(w_mutex); - return WIFI_MANAGER_FAIL; + ret = WIFI_MANAGER_FAIL; } + wifi_mutex_release(w_mutex); - g_manager_info.mode = WIFI_NONE; - + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); ndbg("w_mutex->semcount: %d, w_mutex->flags: %d\n", w_mutex->semcount, w_mutex->flags); - wifi_mutex_release(w_mutex); - result = wifi_mutex_destroy(w_mutex); if (result != WIFI_UTILS_SUCCESS) { ndbg("wifi_mutex_destroy fail %d", result); - return WIFI_MANAGER_FAIL; + ret = WIFI_MANAGER_FAIL; } - free(w_mutex); - w_mutex = NULL; - return WIFI_MANAGER_SUCCESS; + if (ret != WIFI_MANAGER_FAIL) { + g_manager_info.mode = WIFI_NONE; + } else { + g_manager_info.mode = WIFI_FAILURE; + } + + if (w_mutex != NULL) { + free(w_mutex); + w_mutex = NULL; + } + wifi_mutex_release(w_info_mutex); + + result = wifi_mutex_destroy(w_info_mutex); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("w_info_mutex_destroy fail %d", result); + } + if (w_info_mutex != NULL) { + free(w_info_mutex); + w_info_mutex = NULL; + } + + return ret; } wifi_manager_result_e wifi_manager_set_mode(wifi_manager_mode_e mode, wifi_manager_softap_config_s *config) @@ -517,19 +585,31 @@ wifi_manager_result_e wifi_manager_set_mode(wifi_manager_mode_e mode, wifi_manag return WIFI_MANAGER_INVALID_ARGS; } - if ((mode == SOFTAP_MODE) && ((strlen(config->ssid) > 31) || (strlen(config->passphrase) > 63))) { - ndbg("SoftAP configuration fails: too long ssid or passphrase\n"); + if ((mode == SOFTAP_MODE) && ((config == NULL) || (strlen(config->ssid) > 31) || (strlen(config->passphrase) > 63))) { + ndbg("SoftAP configuration fails: no config or too long ssid or passphrase\n"); ndbg("Make sure that length of SSID < 32 and length of passphrase < 64\n"); return WIFI_MANAGER_INVALID_ARGS; } + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); if (g_manager_info.mode == mode) { ndbg("wifi manager set mode failed: current mode is the same as requested.\n"); + wifi_mutex_release(w_info_mutex); return WIFI_MANAGER_SUCCESS; } + /* wifi mode is switched to WIFI_MODE_CHANGING */ + if ((g_manager_info.mode != STA_MODE) && (g_manager_info.mode != SOFTAP_MODE)) { + ndbg("Can't change wifi mode from current mode %d.\n", g_manager_info.mode); + wifi_mutex_release(w_info_mutex); + return WIFI_MANAGER_FAIL; + } + + g_manager_info.mode = WIFI_MODE_CHANGING; + wifi_mutex_release(w_info_mutex); + // Wifi mode is changed to SOFT AP - if ((mode == SOFTAP_MODE) && (config != NULL)) { + if (mode == SOFTAP_MODE) { wifi_utils_softap_config_s softap_config; softap_config.channel = config->channel; @@ -542,60 +622,64 @@ wifi_manager_result_e wifi_manager_set_mode(wifi_manager_mode_e mode, wifi_manag softap_config.inform_new_sta_join = g_manager_callback->softap_sta_joined; wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); - g_new_sta_join = softap_config.inform_new_sta_join; result = wifi_utils_start_softap(&softap_config); - if (result != WIFI_UTILS_SUCCESS) { - ndbg("Start softap mode fail"); - wifi_mutex_release(w_mutex); - return WIFI_MANAGER_FAIL; + ndbg("Starting softap mode failed."); + goto error_with_failure; } if (start_dhcp_server() != WIFI_UTILS_SUCCESS) { - ndbg("start DHCP server Failed\n"); - wifi_mutex_release(w_mutex); - return WIFI_MANAGER_FAIL; + ndbg("Starting DHCP server failed.\n"); + goto error_with_failure; } + wifi_mutex_release(w_mutex); + /* update wifi_manager_info */ + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); g_manager_info.mode = SOFTAP_MODE; strncpy(g_manager_info.ssid, config->ssid, softap_config.ssid_length + 1); wifi_status_set(CLIENT_DISCONNECTED); - wifi_mutex_release(w_mutex); + wifi_mutex_release(w_info_mutex); nvdbg("Wifi mode is changed to SOFT AP"); } // Wifi mode is changed to station - else if (mode == STA_MODE) { + else { wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); - result = wifi_utils_stop_softap(); if (result != WIFI_UTILS_SUCCESS) { - ndbg("Wifi stop fail"); - wifi_mutex_release(w_mutex); - return WIFI_MANAGER_FAIL; + ndbg("Stoping softap failed."); + goto error_with_failure; } stop_dhcp_server(); result = wifi_utils_start_sta(); if (result != WIFI_UTILS_SUCCESS) { - ndbg("start STA fail (change STA mode fail)"); - wifi_mutex_release(w_mutex); - return WIFI_MANAGER_FAIL; + ndbg("Starting STA failed."); + goto error_with_failure; } + wifi_mutex_release(w_mutex); + /* update wifi_manager_info */ + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); g_manager_info.mode = STA_MODE; wifi_status_set(AP_DISCONNECTED); - wifi_mutex_release(w_mutex); + wifi_mutex_release(w_info_mutex); nvdbg("Wifi mode is changed to station"); - } else { - ndbg("Invalid config!\n"); - return WIFI_MANAGER_FAIL; } return WIFI_MANAGER_SUCCESS; + +error_with_failure: + wifi_mutex_release(w_mutex); + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); + g_manager_info.mode = WIFI_FAILURE; + wifi_mutex_release(w_info_mutex); + + return WIFI_MANAGER_FAIL; } wifi_manager_result_e wifi_manager_get_info(wifi_manager_info_s *info) @@ -605,9 +689,9 @@ wifi_manager_result_e wifi_manager_get_info(wifi_manager_info_s *info) return WIFI_MANAGER_FAIL; } - wifi_mutex_acquire(w_mutex, WIFI_UTILS_FOREVER); + wifi_mutex_acquire(w_info_mutex, WIFI_UTILS_FOREVER); *info = g_manager_info; - wifi_mutex_release(w_mutex); + wifi_mutex_release(w_info_mutex); return WIFI_MANAGER_SUCCESS; } @@ -630,6 +714,6 @@ wifi_manager_result_e wifi_manager_scan_ap(void) } wifi_mutex_release(w_mutex); - + return ret; }