diff --git a/apps/system/utils/netcmd_dhcpd.c b/apps/system/utils/netcmd_dhcpd.c index 6cab7042b2..44eb7f5aa5 100644 --- a/apps/system/utils/netcmd_dhcpd.c +++ b/apps/system/utils/netcmd_dhcpd.c @@ -148,7 +148,7 @@ int cmd_dhcpd(int argc, char *argv[]) } } - if (dhcpd_start(argv[2]) != 0) { + if (dhcpd_start(argv[2], NULL) != 0) { printf("%s : failed to start dhcpd\n", __FUNCTION__); goto done; } diff --git a/external/dhcpd/dhcpd.c b/external/dhcpd/dhcpd.c index e6ee3c9fa3..e7c462d82f 100644 --- a/external/dhcpd/dhcpd.c +++ b/external/dhcpd/dhcpd.c @@ -75,8 +75,15 @@ #include /* For CONFIG_CPP_HAVE_WARNING */ #include /* For irqstore() and friends -- REVISIT */ #include /* For net_lock() and friends */ +#ifndef CONFIG_NET_LWIP +#include /* For low-level ARP interfaces -- REVISIT */ +#endif #include /* Advertised DHCPD APIs */ -#endif /* CONFIG_NETUTILS_DHCPD_HOST */ +#undef nvdbg +#undef ndbg +#define ndbg(...) printf(__VA_ARGS__) +#define nvdbg(...) printf(__VA_ARGS__) +#endif /* CONFIG_NETUTILS_DHCPD_HOST */ #include #include @@ -92,10 +99,12 @@ #include #include #include +#include /**************************************************************************** * Global Data ****************************************************************************/ +sem_t g_dhcpd_sem; /**************************************************************************** * Private Data @@ -300,15 +309,18 @@ static struct dhcpd_state_s g_state; static int g_dhcpd_running = 0; static int g_dhcpd_quit = 0; +static int g_dhcpd_sockfd = -1; static pthread_t g_tid = 0; -static char DHCPD_IFNAME[IFNAMSIZ] = {0,}; +static char DHCPD_IFNAME[IFNAMSIZ] = { 0, }; #if DHCPD_SELECT -static struct timeval g_select_timeout = {10, 0}; +static struct timeval g_select_timeout = { 1, 0 }; #endif +static dhcp_sta_joined g_dhcp_sta_joined; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -333,7 +345,7 @@ static inline void dhcpd_arpupdate(uint16_t *pipaddr, uint8_t *phwaddr) } #else #define dhcpd_arpupdate(pipaddr, phwaddr) -#endif /* CONFIG_NET_LWIP */ +#endif /* CONFIG_NET_LWIP */ #else #define dhcpd_arpupdate(pipaddr, phwaddr) #endif @@ -484,10 +496,10 @@ static in_addr_t dhcpd_allocipaddr(void) if ((lease == NULL || dhcpd_leaseexpired(lease))) { ndbg("lease pass!!\n"); #ifdef CONFIG_CPP_HAVE_WARNING -/** -#warning "FIXME: Should check if anything responds to an ARP request or ping" -#warning " to verify that there is no other user of this IP address" -**/ + /** + #warning "FIXME: Should check if anything responds to an ARP request or ping" + #warning " to verify that there is no other user of this IP address" + **/ #endif ndbg("leases talbe = %d %d \n", ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP, g_state.ds_leases[ipaddr - CONFIG_NETUTILS_DHCPD_STARTIP].allocated); @@ -558,7 +570,7 @@ static inline bool dhcpd_parseoptions(void) */ switch (ptr[DHCPD_OPTION_CODE]) { - /* Skip over any padding bytes */ + /* Skip over any padding bytes */ case DHCP_OPTION_PAD: optlen = 1; @@ -832,42 +844,6 @@ static inline int dhcpd_socket(void) } -/**************************************************************************** - * Name: dhcpd_openresponder - ****************************************************************************/ - -static inline int dhcpd_openresponder(void) -{ - struct sockaddr_in addr; - int sockfd; - int ret; - - nvdbg("Responder: %08lx\n", ntohl(g_state.ds_serverip)); - - /* Create a socket to listen for requests from DHCP clients */ - - sockfd = dhcpd_socket(); - if (sockfd < 0) { - ndbg("socket failed: %d\n", errno); - return ERROR; - } - - /* Bind the socket to a local port. */ - - addr.sin_family = AF_INET; - addr.sin_port = HTONS(DHCP_SERVER_PORT); - addr.sin_addr.s_addr = g_state.ds_serverip; - - ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - if (ret < 0) { - ndbg("bind failed, port=%d addr=%08lx: %d\n", addr.sin_port, (long)addr.sin_addr.s_addr, errno); - close(sockfd); - return ERROR; - } - - return sockfd; -} - /**************************************************************************** * Name: dhcpd_initpacket ****************************************************************************/ @@ -911,7 +887,6 @@ static int dhcpd_sendpacket(int bbroadcast) { struct sockaddr_in addr; in_addr_t ipaddr; - int sockfd; int len; int ret = ERROR; @@ -955,25 +930,22 @@ static int dhcpd_sendpacket(int bbroadcast) /* Create a socket to respond with a packet to the client. We * cannot re-use the listener socket because it is not bound correctly */ + if (g_dhcpd_sockfd == -1) { + ndbg("socket is not valid\n"); + } - sockfd = dhcpd_openresponder(); - if (sockfd >= 0) { - /* Then send the reponse to the DHCP client port at that address */ + /* Then send the reponse to the DHCP client port at that address */ - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = HTONS(DHCP_CLIENT_PORT); - addr.sin_addr.s_addr = ipaddr; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = HTONS(DHCP_CLIENT_PORT); + addr.sin_addr.s_addr = ipaddr; - /* Send the minimum sized packet that includes the END option */ + /* Send the minimum sized packet that includes the END option */ - len = (g_state.ds_optend - (uint8_t *)&g_state.ds_outpacket) + 1; - nvdbg("sendto %08lx:%04x len=%d\n", (long)ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port), len); - ret = sendto(sockfd, &g_state.ds_outpacket, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - close(sockfd); - } else { - ndbg("create socket failed : %d\n", sockfd); - } + len = (g_state.ds_optend - (uint8_t *)&g_state.ds_outpacket) + 1; + nvdbg("sendto %08lx:%04x len=%d\n", (long)ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port), len); + ret = sendto(g_dhcpd_sockfd, &g_state.ds_outpacket, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); return ret; } @@ -986,7 +958,6 @@ static int dhcpd_send_offerpacket(void) { struct sockaddr_in addr; in_addr_t ipaddr; - int sockfd; int len; int ret = ERROR; @@ -1001,29 +972,25 @@ static int dhcpd_send_offerpacket(void) ipaddr = htonl(IPADDR_BROADCAST); #endif - sockfd = dhcpd_openresponder(); - if (sockfd >= 0) { - /* Then send the reponse to the DHCP client port at that address */ + if (g_dhcpd_sockfd == -1) { + ndbg("dhcpd socket is not valid\n"); + } + /* Then send the reponse to the DHCP client port at that address */ - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_port = HTONS(DHCP_CLIENT_PORT); - addr.sin_addr.s_addr = ipaddr; + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = HTONS(DHCP_CLIENT_PORT); + addr.sin_addr.s_addr = ipaddr; - /* Send the minimum sized packet that includes the END option */ + /* Send the minimum sized packet that includes the END option */ - len = (g_state.ds_optend - (uint8_t *)&g_state.ds_outpacket) + 1; - nvdbg("dhcp offer sendto %08lx:%04x len=%d\n", (long)ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port), len); - ret = sendto(sockfd, &g_state.ds_outpacket, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); - close(sockfd); - } else { - ndbg("create socket failed : %d\n", sockfd); - } + len = (g_state.ds_optend - (uint8_t *)&g_state.ds_outpacket) + 1; + nvdbg("dhcp offer sendto %08lx:%04x len=%d\n", (long)ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port), len); + ret = sendto(g_dhcpd_sockfd, &g_state.ds_outpacket, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); return ret; } - /**************************************************************************** * Name: dhcpd_sendoffer ****************************************************************************/ @@ -1123,6 +1090,10 @@ int dhcpd_sendack(in_addr_t ipaddr) } dhcpd_setlease(g_state.ds_inpacket.chaddr, ipaddr, leasetime); + /* TODO: new callback way up to application to inform a new STA has called + * dhcp client + */ + g_dhcp_sta_joined(); return OK; } @@ -1414,7 +1385,6 @@ static inline int dhcpd_openlistener(void) return sockfd; } - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -1446,29 +1416,16 @@ static int dhcpd_netif_init(char *intf) ndbg("\n"); - ndbg("Server IP address set : %u.%u.%u.%u\n", - (unsigned char)((htonl(server_ipaddr.s_addr) >> 24) & 0xff), - (unsigned char)((htonl(server_ipaddr.s_addr) >> 16) & 0xff), - (unsigned char)((htonl(server_ipaddr.s_addr) >> 8) & 0xff), - (unsigned char)((htonl(server_ipaddr.s_addr) >> 0) & 0xff)); + ndbg("Server IP address set : %u.%u.%u.%u\n", (unsigned char)((htonl(server_ipaddr.s_addr) >> 24) & 0xff), (unsigned char)((htonl(server_ipaddr.s_addr) >> 16) & 0xff), (unsigned char)((htonl(server_ipaddr.s_addr) >> 8) & 0xff), (unsigned char)((htonl(server_ipaddr.s_addr) >> 0) & 0xff)); - ndbg("Server netmask address set : %u.%u.%u.%u\n", - (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 24) & 0xff), - (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 16) & 0xff), - (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 8) & 0xff), - (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 0) & 0xff)); + ndbg("Server netmask address set : %u.%u.%u.%u\n", (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 24) & 0xff), (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 16) & 0xff), (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 8) & 0xff), (unsigned char)((htonl(netmask_ipaddr.s_addr) >> 0) & 0xff)); - ndbg("Server default gateway address set : %u.%u.%u.%u\n", - (unsigned char)((htonl(server_ipaddr.s_addr) >> 24) & 0xff), - (unsigned char)((htonl(server_ipaddr.s_addr) >> 16) & 0xff), - (unsigned char)((htonl(server_ipaddr.s_addr) >> 8) & 0xff), - (unsigned char)((htonl(server_ipaddr.s_addr) >> 0) & 0xff)); + ndbg("Server default gateway address set : %u.%u.%u.%u\n", (unsigned char)((htonl(server_ipaddr.s_addr) >> 24) & 0xff), (unsigned char)((htonl(server_ipaddr.s_addr) >> 16) & 0xff), (unsigned char)((htonl(server_ipaddr.s_addr) >> 8) & 0xff), (unsigned char)((htonl(server_ipaddr.s_addr) >> 0) & 0xff)); ndbg("\n"); return 0; } - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -1501,7 +1458,6 @@ static int dhcpd_netif_deinit(char *intf) return 0; } - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1521,13 +1477,33 @@ int dhcpd_status(void) ****************************************************************************/ void dhcpd_stop(void) { + int ret = -1; + if (g_dhcpd_running == 0) { + return; + } + g_dhcpd_quit = 1; + while (ret != OK) { + ret = sem_wait(&g_dhcpd_sem); + if (ret != OK) { + ndbg("ERR: sem_wait for dhcpd failed\n"); + if (errno == EINTR) { + ndbg("ERR: EINTR for sem_wait in dhcpd\n"); + continue; + } + return; + } + } + ret = sem_destroy(&g_dhcpd_sem); + if (ret != OK) { + ndbg("ERR: sem_destroy for dhcpd failed\n"); + return; + } #if DHCPD_SELECT ndbg("WARN : dhcpd will be stopped after %d seconds\n", g_select_timeout.tv_sec); #endif } - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1537,7 +1513,6 @@ void dhcpd_stop(void) int dhcpd_run(void *arg) { - int sockfd; int nbytes; #if DHCPD_SELECT int ret = OK; @@ -1546,7 +1521,6 @@ int dhcpd_run(void *arg) ndbg("Started on %s\n", DHCPD_IFNAME); /* Initialize everything to zero */ - memset(&g_state, 0, sizeof(struct dhcpd_state_s)); /* Initialize netif address (ip address, netmask, default gateway) */ @@ -1559,55 +1533,52 @@ int dhcpd_run(void *arg) /* Now loop indefinitely, reading packets from the DHCP server socket */ - sockfd = -1; + g_dhcpd_sockfd = -1; g_dhcpd_quit = 0; g_dhcpd_running = 1; - while (!g_dhcpd_quit) { - /* Create a socket to listen for requests from DHCP clients */ - - /* TODO : Need to add cancellation point */ + /* Create a socket to listen for requests from DHCP clients */ + /* TODO : Need to add cancellation point */ + g_dhcpd_sockfd = dhcpd_openlistener(); + if (g_dhcpd_sockfd < 0) { + ndbg("Failed to create socket\n"); + ret = ERROR; + goto exit_with_error; + } - if (sockfd < 0) { - sockfd = dhcpd_openlistener(); - if (sockfd < 0) { - ndbg("Failed to create socket\n"); - ret = ERROR; - break; - } - } + while (!g_dhcpd_quit) { #if DHCPD_SELECT nbytes = -1; FD_ZERO(&sockfd_set); - FD_SET(sockfd, &sockfd_set); + FD_SET(g_dhcpd_sockfd, &sockfd_set); - ret = select(sockfd+1, &sockfd_set, NULL, NULL, &g_select_timeout); - if ((ret > 0) && FD_ISSET(sockfd, &sockfd_set)) { + ret = select(g_dhcpd_sockfd + 1, &sockfd_set, NULL, NULL, &g_select_timeout); + if ((ret > 0) && FD_ISSET(g_dhcpd_sockfd, &sockfd_set)) { /* Read the next g_state.ds_outpacket */ - nbytes = recv(sockfd, &g_state.ds_inpacket, sizeof(struct dhcpmsg_s), 0); + nbytes = recv(g_dhcpd_sockfd, &g_state.ds_inpacket, sizeof(struct dhcpmsg_s), 0); } else if (ret == 0) { - if (!g_dhcpd_quit) + if (!g_dhcpd_quit) { continue; - else { + } else { ndbg("select timeout exit\n"); break; } } else { - /* Debugging purpose : Error case*/ + /* Debugging purpose : Error case */ ndbg("ERROR, select ret %d [errno %d]\n", ret, errno); break; } #else - nbytes = recv(sockfd, &g_state.ds_inpacket, sizeof(struct dhcpmsg_s), 0); + nbytes = recv(g_dhcpd_sockfd, &g_state.ds_inpacket, sizeof(struct dhcpmsg_s), 0); #endif if (nbytes < 0) { /* On errors (other EINTR), close the socket and try again */ ndbg("recv failed: %d\n", errno); if (errno != EINTR) { - close(sockfd); - sockfd = -1; + close(g_dhcpd_sockfd); + g_dhcpd_sockfd = -1; } continue; } @@ -1632,9 +1603,7 @@ int dhcpd_run(void *arg) switch (g_state.ds_optmsgtype) { case DHCPDISCOVER: ndbg("DHCPDISCOVER\n"); - if (dhcpd_discover() == ERROR) { - ndbg("DHCPDISCOVER : Failed to send DHCP Discover, errno %d\n", errno); - } + dhcpd_discover(); break; case DHCPREQUEST: @@ -1659,9 +1628,12 @@ int dhcpd_run(void *arg) } } - if (sockfd != -1) { - close(sockfd); + if (g_dhcpd_sockfd != -1) { + close(g_dhcpd_sockfd); } + sem_post(&g_dhcpd_sem); + +exit_with_error: g_dhcpd_running = 0; /* de-initialize netif address (ip address, netmask, default gateway) */ @@ -1673,7 +1645,6 @@ int dhcpd_run(void *arg) return ret; } - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1685,12 +1656,17 @@ int dhcpd_run(void *arg) #define DHCPD_SCHED_PRI 100 #define DHCPD_SCHED_POLICY SCHED_RR -int dhcpd_start(char *intf) +int dhcpd_start(char *intf, dhcp_sta_joined dhcp_join_cb) { pthread_attr_t attr; int status; + int ret; struct sched_param sparam; - + ret = sem_init(&g_dhcpd_sem, 0, 0); + if (ret != OK) { + ndbg("failed to initialize semaphore\n"); + goto err_exit; + } /* Set network interface name for DHCPD */ if (intf) { strncpy(DHCPD_IFNAME, intf, strlen(intf)); @@ -1707,25 +1683,26 @@ int dhcpd_start(char *intf) sparam.sched_priority = DHCPD_SCHED_PRI; status = pthread_attr_setschedparam(&attr, &sparam); if (status != 0) { - ndbg("failed to pthread_attr_setschedparam, ret %d, errno %d\n", - status, errno); + ndbg("failed to pthread_attr_setschedparam, ret %d, errno %d\n", status, errno); goto err_exit; } status = pthread_attr_setschedpolicy(&attr, DHCPD_SCHED_POLICY); if (status != 0) { - ndbg("failed to pthread_attr_setchedpolicy, ret %d, errno %d\n", - status, errno); + ndbg("failed to pthread_attr_setchedpolicy, ret %d, errno %d\n", status, errno); goto err_exit; } status = pthread_attr_setstacksize(&attr, DHCPD_STACK_SIZE); if (status != 0) { - ndbg("failed to pthread_attr_setstacksize, ret %d, errno %d\n", - status, errno); + ndbg("failed to pthread_attr_setstacksize, ret %d, errno %d\n", status, errno); goto err_exit; } + if (dhcp_join_cb) { + g_dhcp_sta_joined = dhcp_join_cb; + } + status = pthread_create(&g_tid, &attr, (pthread_startroutine_t)dhcpd_run, NULL); if (status != 0) { ndbg("failed to start dhcpd\n"); diff --git a/external/include/protocols/dhcpd.h b/external/include/protocols/dhcpd.h index fb2531ff50..2a1f5bfc79 100644 --- a/external/include/protocols/dhcpd.h +++ b/external/include/protocols/dhcpd.h @@ -88,6 +88,8 @@ extern "C" { #define EXTERN extern #endif +typedef void (*dhcp_sta_joined)(void); + /** * @brief Starts DHCP server which is attached given network interface. * @@ -102,7 +104,7 @@ int dhcpd_run(void *arg); * @param[in] intf the name of network interface to run DHCP server * @return On success, 0. On failure, returns -1 */ -int dhcpd_start(char *intf); +int dhcpd_start(char *intf, dhcp_sta_joined dhcp_join_cb); #undef EXTERN #ifdef __cplusplus diff --git a/framework/Makefile b/framework/Makefile index 47f11cc241..f56df3bc7e 100644 --- a/framework/Makefile +++ b/framework/Makefile @@ -42,6 +42,10 @@ ifeq ($(CONFIG_NETUTILS_MQTT), y) include src$(DELIM)mqtt$(DELIM)Make.defs endif +ifeq ($(CONFIG_WIFI_MANAGER), y) +include src$(DELIM)wifi_manager$(DELIM)Make.defs +endif + AOBJS = $(ASRCS:.S=$(OBJEXT)) COBJS = $(CSRCS:.c=$(OBJEXT)) diff --git a/framework/include/wifi_manager/wifi_manager.h b/framework/include/wifi_manager/wifi_manager.h new file mode 100644 index 0000000000..9f3a8ef739 --- /dev/null +++ b/framework/include/wifi_manager/wifi_manager.h @@ -0,0 +1,167 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +/** + * @defgroup Wi-Fi_Manager Wi-Fi_Manager + * @ingroup Wi-Fi_Manager + * @brief Provides APIs for Wi-Fi Manager + * @{ + */ + +#ifndef WIFI_MANAGER_H +#define WIFI_MANAGER_H + +typedef enum { + // STA mode status + AP_DISCONNECTED, + AP_CONNECTED, + + // SOFT AP mode status + CLIENT_CONNECTED, + CLIENT_DISCONNECTED +} connect_status_e; + +/** + * @brief wifi result type FAIL, SUCCESS, INVALID ARGS + */ +typedef enum { + WIFI_MANAGER_FAIL = -1, + WIFI_MANAGER_SUCCESS, + WIFI_MANAGER_INVALID_ARGS, + WIFI_MANAGER_TIMEOUT, + WIFI_MANAGER_BUSY, +} wifi_manager_result_e; + +typedef enum { + STA_MODE, + SOFT_AP_MODE +} wifi_manager_mode_e; + +typedef struct { + void (*sta_connected)(void); + void (*sta_disconnected)(void); + void (*softap_sta_join)(void); + void (*softap_sta_leave)(void); +} wifi_manager_cb_s; + +typedef struct { + char ip4_address[18]; + char ssid[32]; + int rssi; + connect_status_e status; + wifi_manager_mode_e mode; + wifi_manager_cb_s *wmcb; +} wifi_manager_info_s; + +typedef struct { + char ssid[32]; + uint16_t channel; + char passphrase[32]; +} wifi_manager_softap_config_s; + +/** + * @brief wifi authentication type WPA, WPA2, WPS + */ +typedef enum { + WIFI_MANAGER_AUTH_OPEN, /**< open mode */ + WIFI_MANAGER_AUTH_WEP_SHARED, /**< use shared key (wep key) */ + WIFI_MANAGER_AUTH_WPA_PSK, /**< WPA_PSK mode */ + WIFI_MANAGER_AUTH_WPA2_PSK, /**< WPA2_PSK mode */ + WIFI_MANAGER_AUTH_WPA_AND_WPA2_PSK, /**< WPA_PSK and WPA_PSK mixed mode */ + WIFI_MANAGER_AUTH_UNKNOWN, /**< unknown type */ +} wifi_manager_ap_auth_type_e; + +/** + * @brief wifi encryption type WEP, AES, TKIP + */ +typedef enum { + WIFI_MANAGER_CRYPTO_NONE, /**< none encryption */ + WIFI_MANAGER_CRYPTO_WEP_64, /**< WEP encryption wep-40 */ + WIFI_MANAGER_CRYPTO_WEP_128, /**< WEP encryption wep-104 */ + WIFI_MANAGER_CRYPTO_AES, /**< AES encryption */ + WIFI_MANAGER_CRYPTO_TKIP, /**< TKIP encryption */ + WIFI_MANAGER_CRYPTO_TKIP_AND_AES, /**< TKIP and AES mixed encryption */ + WIFI_MANAGER_CRYPTO_UNKNOWN, /**< unknown encryption */ +} wifi_manager_ap_crypto_type_e; + +/** + * @brief wifi ap connect config + */ +typedef struct { + char ssid[32]; /**< Service Set Identification */ + unsigned int ssid_length; /**< Service Set Identification Length */ + char passphrase[64]; /**< ap passphrase(password) */ + unsigned int passphrase_length; /**< ap passphrase length */ + wifi_manager_ap_auth_type_e ap_auth_type; /**< @ref wifi_utils_ap_auth_type */ + wifi_manager_ap_crypto_type_e ap_crypto_type; /**< @ref wifi_utils_ap_crypto_type */ +} wifi_manager_ap_config_s; + +/** + * @brief Initialize Wi-Fi Manager including starting Wi-Fi interface. + * @param[in] callback functions called when wi-fi events happen + * @return On success, WIFI_MANAGER_SUCCESS (i.e., 0) is returned. On failure, non-zero value is returned. + * @since Tizen RT v1.1 + */ +wifi_manager_result_e wifi_manager_init(wifi_manager_cb_s *wmcb); + +/** + * @brief Deinitialize Wi-Fi Manager including stoping Wi-Fi interface. + * @param[in] none + * @return On success, WIFI_MANAGER_SUCCESS (i.e., 0) is returned. On failure, non-zero value is returned. + * @since Tizen RT v1.1 + */ +wifi_manager_result_e wifi_manager_deinit(void); + +/** + * @brief Change the Wi-Fi mode to station or AP. + * @param[in] Wi-Fi mode (station or AP) + * @param[in] In case of AP mode, AP configuration infomation should be given including ssid, channel, and passphrase. + * @return On success, WIFI_MANAGER_SUCCESS (i.e., 0) is returned. On failure, non-zero value is returned. + * @since Tizen RT v1.1 + */ +wifi_manager_result_e wifi_manager_set_mode(wifi_manager_mode_e mode, wifi_manager_softap_config_s *config); + +/** + * @brief Retrieve current status of Wi-Fi interface including mode, connection status, ssid, received signal strengh indication, and ip address. + * @param[out] retrieved information including mode, connection s tatus, ssid, received signal strengh indication, and ip address. + * @return On success, WIFI_MANAGER_SUCCESS (i.e., 0) is returned. On failure, non-zero value is returned. + * @since Tizen RT v1.1 + */ +wifi_manager_result_e wifi_manager_get_info(wifi_manager_info_s *info); + +/** + * @brief Connect to an access point. + * @param[in] ssid, passphrase, authentication type, and cryto type of the access point which the wi-fi interface connect to. + * @return On success, WIFI_MANAGER_SUCCESS (i.e., 0) is returned. On failure, non-zero value is returned. + * @since Tizen RT v1.1 + */ +wifi_manager_result_e wifi_manager_connect_ap(wifi_manager_ap_config_s *config); + +/** + * @brief Disconnect from the connected access point + * @param[in] none + * @return On success, WIFI_MANAGER_SUCCESS (i.e., 0) is returned. On failure, non-zero value is returned. + * @since Tizen RT v1.1 + */ +wifi_manager_result_e wifi_manager_disconnect_ap(void); + +#endif + +/** + *@} + */ diff --git a/framework/src/wifi_manager/Kconfig b/framework/src/wifi_manager/Kconfig new file mode 100644 index 0000000000..aec8102413 --- /dev/null +++ b/framework/src/wifi_manager/Kconfig @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt +# + +config WIFI_MANAGER + bool "Enable Wi-Fi Manager" + default n + ---help--- + Easy APIs for applications to use and control Wi-Fi features + +if WIFI_MANAGER +source "$EXTERNALDIR/slsi_wifi/Kconfig" +endif #WIFI_MANAGER diff --git a/framework/src/wifi_manager/Make.defs b/framework/src/wifi_manager/Make.defs new file mode 100644 index 0000000000..417972f1c1 --- /dev/null +++ b/framework/src/wifi_manager/Make.defs @@ -0,0 +1,23 @@ +########################################################################### +# +# Copyright 2017 Samsung Electronics All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +# +########################################################################### + +CSRCS += wifi_manager.c wifi_utils.c wifi_net.c wifi_mutex.c wifi_semaphore.c + +DEPPATH += --dep-path src/wifi_manager +VPATH += :src/wifi_manager + diff --git a/framework/src/wifi_manager/wifi_common.h b/framework/src/wifi_manager/wifi_common.h new file mode 100644 index 0000000000..c9395f1417 --- /dev/null +++ b/framework/src/wifi_manager/wifi_common.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef WIFI_COMMON_H +#define WIFI_COMMON_H + + +/** + * @brief time out option (used by message queue, uart, semaphore, mutex) + * + */ +typedef enum { + WIFI_UTILS_NO_WAIT = 0, /**< no wait contant */ + WIFI_UTILS_FOREVER = -1, /**< wait until job finished */ +} wifi_utils_timeout_option; + +/** + * @brief wifi result type FAIL, SUCCESS, INVALID ARGS + */ +typedef enum { + WIFI_UTILS_FAIL = -1, + WIFI_UTILS_SUCCESS, + WIFI_UTILS_INVALID_ARGS, + WIFI_UTILS_TIMEOUT, + WIFI_UTILS_BUSY, +} wifi_utils_result_e; + + +#endif //WIFI_COMMON_H diff --git a/framework/src/wifi_manager/wifi_manager.c b/framework/src/wifi_manager/wifi_manager.c new file mode 100644 index 0000000000..82b29c9716 --- /dev/null +++ b/framework/src/wifi_manager/wifi_manager.c @@ -0,0 +1,422 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wifi_utils.h" +#include "wifi_mutex.h" +#include "wifi_net.h" + +static void *g_dhcp_handle = NULL; +static dhcp_sta_joined g_new_sta_join = NULL; +#ifdef CONFIG_ENABLE_IOTIVITY +mqd_t g_dw_nwevent_mqfd; +#endif + +/* + * Iotivity stack receives network events from wifi manager module + * this will be changed later + */ +#ifdef CONFIG_ENABLE_IOTIVITY +void __tizenrt_manual_linkset(const char *msg) +{ + int ret = mq_send(g_dw_nwevent_mqfd, msg, 3, 42); + if (ret < 0) { + ndbg("send message fail\n"); + return; + } +} +#endif + +static wifi_manager_info_s g_manager_info; + +static wifi_mutex w_mutex; + +static wifi_utils_result_e start_dhcp_client(void) +{ + struct dhcpc_state state; + int ret; + + g_dhcp_handle = dhcpc_open(CTRL_IFNAME); + if (g_dhcp_handle == NULL) { + ndbg("Invalid dhcp handle\n"); + return WIFI_UTILS_FAIL; + } + ret = dhcpc_request(g_dhcp_handle, &state); + if (ret != OK) { + dhcpc_close(g_dhcp_handle); + return WIFI_UTILS_FAIL; + } + + netlib_set_ipv4addr(CTRL_IFNAME, &state.ipaddr); + netlib_set_ipv4netmask(CTRL_IFNAME, &state.netmask); + netlib_set_dripv4addr(CTRL_IFNAME, &state.default_router); + + nvdbg("IP address : %s ----\n", inet_ntoa(state.ipaddr)); + + return WIFI_UTILS_SUCCESS; +} + +static wifi_utils_result_e stop_dhcp_client(void) +{ + if (g_dhcp_handle == NULL) { + return WIFI_UTILS_FAIL; + } else { + dhcpc_close(g_dhcp_handle); + g_dhcp_handle = NULL; + } + + return WIFI_UTILS_SUCCESS; +} + +static wifi_utils_result_e start_dhcp_server(void) +{ + struct in_addr in = {.s_addr = 0x012fa8c0 }; + netlib_set_ipv4addr(CTRL_IFNAME, &in); + in.s_addr = 0x00ffffff; + netlib_set_ipv4netmask(CTRL_IFNAME, &in); + in.s_addr = 0x012fa8c0; + netlib_set_dripv4addr(CTRL_IFNAME, &in); + + if (dhcpd_start(CTRL_IFNAME, g_new_sta_join) < 0) { + ndbg("DHCP Server - started fail\n"); + return WIFI_UTILS_FAIL; + } + + nvdbg("DHCP Server - started success\n"); + return WIFI_UTILS_SUCCESS; +} + +static wifi_utils_result_e stop_dhcp_server(void) +{ + struct in_addr in = { .s_addr = INADDR_NONE }; + netlib_set_ipv4addr(CTRL_IFNAME, &in); + netlib_set_ipv4netmask(CTRL_IFNAME, &in); + netlib_set_dripv4addr(CTRL_IFNAME, &in); + + dhcpd_stop(); + + return WIFI_UTILS_SUCCESS; +} + +static void wifi_status_set(connect_status_e status) +{ +#ifdef CONFIG_DEBUG_NET_INFO + static char connect_status_str[5][25] = { + // STA mode + "AP_DISCONNECTED", + "AP_CONNECTED", + + // SOFTAP mode + "CLIENT_CONNECTED", + "CLIENT_DISCONNECTED" + }; +#endif + + if (g_manager_info.status != status) { + nvdbg("Wifi Network Status Changes from [%s] to [%s]", connect_status_str[g_manager_info.status], connect_status_str[status]); + g_manager_info.status = status; + } +} + +static void ap_connect_event_func(void) +{ + wifi_manager_cb_s *wifi_cb = g_manager_info.wmcb; + if (g_manager_info.mode == STA_MODE) { + nvdbg("WIFI CONNECTED AP - STA MODE"); + wifi_status_set(AP_CONNECTED); + + /* Perform DHCP client */ + if (start_dhcp_client() != WIFI_UTILS_SUCCESS) { + ndbg("DHCP client start failed\n"); + return; + } + if (stop_dhcp_client() != WIFI_UTILS_SUCCESS) { + ndbg("DHCP client stop failed\n"); + } + + if (wifi_cb != NULL && wifi_cb->sta_connected) { + wifi_cb->sta_connected(); + } else { + ndbg("Callback wifimanager ap_connect failed\n"); + } + } else if (g_manager_info.mode == SOFT_AP_MODE) { + nvdbg("CONNECTED FROM CLIENT - SOFT AP MODE"); + wifi_status_set(CLIENT_CONNECTED); + + /* No callbacks here, in case new client joins, we invoke callback + * from DHCP server instead + */ + } +#ifdef CONFIG_ENABLE_IOTIVITY + __tizenrt_manual_linkset("gen"); +#endif + /* TODO: Import files from source + * sendStatusTrigger (TRIGGER_NETWORK_CHANGED, DAWIT_NW_CHANGED_UP); + */ +} + +static void ap_disconnect_event_func(void) +{ + wifi_manager_cb_s *wifi_cb = g_manager_info.wmcb; + if (g_manager_info.mode == STA_MODE) { + nvdbg("WIFI DISCONNECTED AP - STA MODE"); + strncpy(g_manager_info.ssid, "", 32); + strcpy(g_manager_info.ip4_address, ""); + g_manager_info.rssi = 0; + wifi_status_set(AP_DISCONNECTED); + + if (wifi_cb != NULL && wifi_cb->sta_disconnected) { + wifi_cb->sta_disconnected(); + } else { + ndbg("Callback wifimanager ap_disconnected failed\n"); + } + } else if (g_manager_info.mode == SOFT_AP_MODE) { + nvdbg("DISCONNECTED FROM CLIENT - SOFT AP MODE"); + wifi_status_set(CLIENT_DISCONNECTED); + if (wifi_cb != NULL && wifi_cb->softap_sta_leave) { + wifi_cb->softap_sta_leave(); + } else { + ndbg("Callback wifimanager ap_disconnected failed\n"); + } + } +#ifdef CONFIG_ENABLE_IOTIVITY + __tizenrt_manual_linkset("del"); +#endif + + /* TODO: Import files from source + * sendStatusTrigger(TRIGGER_NETWORK_CHANGED, DAWIT_NW_CHANGED_DOWN); + */ +} + +/** + * Public API + */ + +wifi_manager_result_e wifi_manager_connect_ap(wifi_manager_ap_config_s *config) +{ + if (config == NULL) { + return WIFI_MANAGER_INVALID_ARGS; + } + + wifi_utils_info info; + wifi_utils_ap_config_s util_config; + + wifi_utils_get_info(&info); + + if (info.wifi_status == WIFI_UTILS_SOFT_AP_MODE) { + ndbg("Current mode soft ap mode, can not connect ap"); + return WIFI_MANAGER_FAIL; + } + + wifi_mutex_acquire(&w_mutex, WIFI_UTILS_FOREVER); + + strncpy(util_config.ssid, config->ssid, config->ssid_length); + util_config.ssid_length = config->ssid_length; + strncpy(util_config.passphrase, config->passphrase, config->passphrase_length); + util_config.passphrase_length = config->passphrase_length; + util_config.ap_auth_type = config->ap_auth_type; + util_config.ap_crypto_type = config->ap_crypto_type; + + wifi_utils_result_e result = wifi_utils_connect_ap(&util_config); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("Wifi AP connect fail"); + wifi_mutex_release(&w_mutex); + return WIFI_MANAGER_FAIL; + } + + /* g_manager_info.wmcb->sta_connected(); */ + wifi_utils_get_info(&info); + + char ip4_add_str[18] = { 0, }; + wifi_net_ip4_addr_to_ip4_str(info.ip4_address, ip4_add_str); + strncpy(g_manager_info.ssid, config->ssid, 32); + strcpy(g_manager_info.ip4_address, ip4_add_str); + g_manager_info.rssi = info.rssi; + + wifi_mutex_release(&w_mutex); + + return WIFI_MANAGER_SUCCESS; +} + +wifi_manager_result_e wifi_manager_disconnect_ap(void) +{ + wifi_utils_result_e result = WIFI_UTILS_SUCCESS; + + wifi_mutex_acquire(&w_mutex, WIFI_UTILS_FOREVER); + result = wifi_utils_disconnect_ap(); + wifi_mutex_release(&w_mutex); + + return result; +} + +wifi_manager_result_e wifi_manager_init(wifi_manager_cb_s *wmcb) +{ + wifi_utils_result_e result = WIFI_UTILS_SUCCESS; + + result = wifi_mutex_create(&w_mutex); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("wifi_mutex_create fail"); + return WIFI_MANAGER_FAIL; + } + + result = wifi_utils_init(); + + if (result != WIFI_UTILS_SUCCESS) { + ndbg("wifi_utils_init fail"); + return WIFI_MANAGER_FAIL; + } + + wifi_utils_register_connection_callback(ap_connect_event_func, ap_disconnect_event_func); + strncpy(g_manager_info.ip4_address, "", 18); + strcpy(g_manager_info.ssid, ""); + g_manager_info.rssi = 0; + g_manager_info.mode = STA_MODE; + g_manager_info.mode = AP_DISCONNECTED; + g_manager_info.wmcb = wmcb; + +#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"); + return WIFI_MANAGER_FAIL; + } +#endif + + return WIFI_MANAGER_SUCCESS; +} + +wifi_manager_result_e wifi_manager_deinit() +{ + wifi_utils_result_e result = WIFI_UTILS_SUCCESS; + + if ((g_manager_info.mode == SOFT_AP_MODE) && (stop_dhcp_server() != WIFI_UTILS_SUCCESS)) { + ndbg("dhcp server stop fail\n"); + return WIFI_MANAGER_FAIL; + } + + result = wifi_mutex_destroy(&w_mutex); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("wifi_mutex_destroy fail"); + return WIFI_MANAGER_FAIL; + } + + result = wifi_utils_deinit(); + + if (result != WIFI_UTILS_SUCCESS) { + ndbg("wifi_utils_deinit fail"); + return WIFI_MANAGER_FAIL; + } + + return WIFI_MANAGER_SUCCESS; +} + +wifi_manager_result_e wifi_manager_set_mode(wifi_manager_mode_e mode, wifi_manager_softap_config_s *config) +{ + wifi_utils_result_e result = WIFI_UTILS_SUCCESS; + + if (mode != STA_MODE && mode != SOFT_AP_MODE) { + return WIFI_MANAGER_INVALID_ARGS; + } + // STA mode -> SOFT AP mode + if (g_manager_info.mode == STA_MODE && mode == SOFT_AP_MODE) { + wifi_utils_softap_config_s soft_ap_config; + + soft_ap_config.channel = config->channel; + soft_ap_config.ap_crypto_type = WIFI_UTILS_CRYPTO_AES; + soft_ap_config.ap_auth_type = WIFI_UTILS_AUTH_WPA2_PSK; + strncpy(soft_ap_config.ssid, config->ssid, sizeof(config->ssid)); + soft_ap_config.ssid_length = strlen(config->ssid); + strncpy(soft_ap_config.passphrase, config->passphrase, sizeof(config->passphrase)); + soft_ap_config.passphrase_length = strlen(config->passphrase); + soft_ap_config.inform_new_sta_join = g_manager_info.wmcb->softap_sta_join; + + wifi_mutex_acquire(&w_mutex, WIFI_UTILS_FOREVER); + + g_new_sta_join = soft_ap_config.inform_new_sta_join; + result = wifi_utils_start_soft_ap(&soft_ap_config); + + if (result != WIFI_UTILS_SUCCESS) { + ndbg("Start soft ap mode fail"); + wifi_mutex_release(&w_mutex); + return WIFI_MANAGER_FAIL; + } + + if (start_dhcp_server() != WIFI_UTILS_SUCCESS) { + ndbg("start DHCP server Failed\n"); + return WIFI_MANAGER_FAIL; + } + + g_manager_info.mode = SOFT_AP_MODE; + g_manager_info.status = CLIENT_DISCONNECTED; + wifi_mutex_release(&w_mutex); + + nvdbg("Wifi Change STA MODE -> SOFT AP MODE"); + } + // SOFT AP mode -> STA mode + else if (g_manager_info.mode == SOFT_AP_MODE && mode == STA_MODE) { + wifi_mutex_acquire(&w_mutex, WIFI_UTILS_FOREVER); + + result = wifi_utils_stop(); + if (result != WIFI_UTILS_SUCCESS) { + ndbg("Wifi stop fail"); + wifi_mutex_release(&w_mutex); + return WIFI_MANAGER_FAIL; + } + + 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; + } + + g_manager_info.mode = STA_MODE; + g_manager_info.status = AP_DISCONNECTED; + wifi_mutex_release(&w_mutex); + + nvdbg("Wifi Chnage SOFT AP MODE -> STA MODE"); + } + + return WIFI_MANAGER_SUCCESS; +} + +wifi_manager_result_e wifi_manager_get_info(wifi_manager_info_s *info) +{ + wifi_mutex_acquire(&w_mutex, WIFI_UTILS_FOREVER); + *info = g_manager_info; + wifi_mutex_release(&w_mutex); + + return WIFI_MANAGER_SUCCESS; +} diff --git a/framework/src/wifi_manager/wifi_mutex.c b/framework/src/wifi_manager/wifi_mutex.c new file mode 100644 index 0000000000..d621ce1f90 --- /dev/null +++ b/framework/src/wifi_manager/wifi_mutex.c @@ -0,0 +1,40 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include "wifi_mutex.h" +#include "wifi_semaphore.h" + +wifi_utils_result_e wifi_mutex_create(wifi_mutex *mutex) +{ + return wifi_semaphore_create((wifi_semaphore *)mutex, 1); +} + +wifi_utils_result_e wifi_mutex_acquire(wifi_mutex *mutex, int time_out) +{ + return wifi_semaphore_acquire((wifi_semaphore *)mutex, time_out); +} + +wifi_utils_result_e wifi_mutex_release(wifi_mutex *mutex) +{ + return wifi_semaphore_release((wifi_semaphore *)mutex); +} + +wifi_utils_result_e wifi_mutex_destroy(wifi_mutex *mutex) +{ + return wifi_semaphore_destroy((wifi_semaphore *)mutex); +} diff --git a/framework/src/wifi_manager/wifi_mutex.h b/framework/src/wifi_manager/wifi_mutex.h new file mode 100644 index 0000000000..9bd7a29d34 --- /dev/null +++ b/framework/src/wifi_manager/wifi_mutex.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef WIFI_MUTEX_H +#define WIFI_MUTEX_H +#include +#include "wifi_common.h" +typedef sem_t wifi_mutex; + +/** + * @brief create mutex + * + * @param[in] mutex : wifi_mutex + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_mutex_create(wifi_mutex *mutex); + +/** + * @brief acquire the lock a mutex + * + * @param[in] mutex : wifi_mutex + * @param[in] time_out : set time out, WIFI_UTILS_NO_WAIT, WIFI_UTILS_FOREVER, or wait milliseconds + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + * @return WIFI_UTILS_TIMEOUT : occur timeout + */ +wifi_utils_result_e wifi_mutex_acquire(wifi_mutex *mutex, int time_out); + +/** + * @brief release the lock on a mutex + * + * @param[in] mutex : wifi_mutex + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_mutex_release(wifi_mutex *mutex); + +/** + * @brief destroy a mutex + * + * @param[in] mutex : wifi_mutex + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_mutex_destroy(wifi_mutex *mutex); + +#endif //WIFI_MUTEX_H diff --git a/framework/src/wifi_manager/wifi_net.c b/framework/src/wifi_manager/wifi_net.c new file mode 100644 index 0000000000..a79ffa3b97 --- /dev/null +++ b/framework/src/wifi_manager/wifi_net.c @@ -0,0 +1,220 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wifi_utils.h" +#include "wifi_net.h" + +#define ptr2uint32(ptr) (uint32_t)ptr[3] | \ + ((uint32_t)ptr[2] << 8) | \ + ((uint32_t)ptr[1] << 16) | \ + ((uint32_t)ptr[0] << 24) + +#define NTP2UNIX_TRANLSLATION 2208988800u +#define NTP_VERSION 3 +static void convert_ntp_time(FAR uint8_t *timestamp, unsigned int *sec, unsigned int *usec) +{ + time_t seconds; + uint32_t frac; + uint32_t nsec; +#ifdef CONFIG_HAVE_LONG_LONG + uint64_t tmp; +#else + uint32_t a16; + uint32_t b0; + uint32_t t32; + uint32_t t16; + uint32_t t0; +#endif + + /* NTP timestamps are represented as a 64-bit fixed-point number, in + * seconds relative to 0000 UT on 1 January 1900. The integer part is + * in the first 32 bits and the fraction part in the last 32 bits, as + * shown in the following diagram. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Integer Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fraction Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + seconds = ptr2uint32(timestamp); + + /* Translate seconds to account for the difference in the origin time */ + + if (seconds > NTP2UNIX_TRANLSLATION) { + seconds -= NTP2UNIX_TRANLSLATION; + } + + /* Conversion of the fractional part to nanoseconds: + * + * NSec = (f * 1,000,000,000) / 4,294,967,296 + * = (f * (5**9 * 2**9) / (2**32) + * = (f * 5**9) / (2**23) + * = (f * 1,953,125) / 8,388,608 + */ + + frac = ptr2uint32((timestamp + 4)); +#ifdef CONFIG_HAVE_LONG_LONG + /* if we have 64-bit long long values, then the computation is easy */ + + tmp = ((uint64_t)frac * 1953125) >> 23; + nsec = (uint32_t)tmp; + +#else + /* If we don't have 64 bit integer types, then the calculation is a little + * more complex: + * + * Let f = a << 16 + b + * 1,953,125 = 0x1d << 16 + 0xcd65 + * NSec << 23 = ((a << 16) + b) * ((0x1d << 16) + 0xcd65) + * = (a << 16) * 0x1d << 16) + + * (a << 16) * 0xcd65 + + * b * 0x1d << 16) + + * b * 0xcd65; + */ + + /* Break the fractional part up into two values */ + + a16 = frac >> 16; + b0 = frac & 0xffff; + + /* Get the b32 and b0 terms + * + * t32 = (a << 16) * 0x1d << 16) + * t0 = b * 0xcd65 + */ + + t32 = 0x001d * a16; + t0 = 0xcd65 * b0; + + /* Get the first b16 term + * + * (a << 16) * 0xcd65 + */ + + t16 = 0xcd65 * a16; + + /* Add the upper 16-bits to the b32 accumulator */ + + t32 += (t16 >> 16); + + /* Add the lower 16-bits to the b0 accumulator, handling carry to the b32 + * accumulator + */ + + t16 <<= 16; + if (t0 > (0xffffffff - t16)) { + t32++; + } + + t0 += t16; + + /* Get the second b16 term + * + * b * (0x1d << 16) + */ + + t16 = 0x001d * b0; + + /* Add the upper 16-bits to the b32 accumulator */ + + t32 += (t16 >> 16); + + /* Add the lower 16-bits to the b0 accumulator, handling carry to the b32 + * accumulator + */ + + t16 <<= 16; + if (t0 > (0xffffffff - t16)) { + t32++; + } + + t0 += t16; + + /* t32 and t0 represent the 64 bit product. Now shift right by 23 bits to + * accomplish the divide by by 2**23. + */ + + nsec = (t32 << (32 - 23)) + (t0 >> 23); +#endif + *sec = seconds; + *usec = nsec / 1000; + ndbg(" %lu seconds, %lu usec\n", (uint32_t)seconds, (uint32_t)nsec / 1000); + +} + +wifi_utils_result_e wifi_net_hostname_to_ip4(char *hostname, unsigned int *ip4_address) +{ + if (hostname == NULL || ip4_address == NULL) { + return WIFI_UTILS_INVALID_ARGS; + } + + struct hostent *shost; + + shost = gethostbyname((const char *)hostname); + if (shost == NULL) { + ndbg("gethostbyname fail %d\n", shost); + return WIFI_UTILS_FAIL; + } + + memcpy(ip4_address, shost->h_addr, sizeof(in_addr_t)); + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_net_ip4_addr_to_ip4_str(unsigned int ip4_addr, char ip4_str[18]) +{ + if (ip4_addr <= 0 || ip4_str == NULL) { + return WIFI_UTILS_INVALID_ARGS; + } + + unsigned char bytes[4]; + bytes[0] = ip4_addr & 0xFF; + bytes[1] = (ip4_addr >> 8) & 0xFF; + bytes[2] = (ip4_addr >> 16) & 0xFF; + bytes[3] = (ip4_addr >> 24) & 0xFF; + + sprintf(ip4_str, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_net_mac_addr_to_mac_str(unsigned char mac_addr[6], char mac_str[20]) +{ + if (!mac_addr || !mac_str) { + return WIFI_UTILS_INVALID_ARGS; + } + + snprintf(mac_str, 18, "%02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + return WIFI_UTILS_SUCCESS; +} diff --git a/framework/src/wifi_manager/wifi_net.h b/framework/src/wifi_manager/wifi_net.h new file mode 100644 index 0000000000..dcae6d296e --- /dev/null +++ b/framework/src/wifi_manager/wifi_net.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef WIFI_NET_H +#define WIFI_NET_H +#include "wifi_common.h" + +/** + * @file wifi_net.h + * @brief network utility (dns, ntp) API + */ + +/** + * @brief host name to IP4 address + * + * @param[in] hostname : host name string (ex - www.google.co.kr) + * @param[out] ip4_address : host ip4 address (32bit) + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_hostname_to_ip4(char *hostname, unsigned int *ip4_address); + +/** + * @brief convert ip4 address (32bit) to ip4 address string (123.123.123.123) + * + * @param[in] ip4_addr : ip4 address 32bit + * @param[out] ip4_str : ip4 address string + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_ip4_addr_to_ip4_str(unsigned int ip4_addr, char ip4_str[18]); + +/** + * @brief convert mac address (48bit) to mac address string (FF:FF:FF:FF:FF:FF) + * + * @param[in] mac_addr : mac address 48bit + * @param[out] mac_str : mac address string + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_mac_addr_to_mac_str(unsigned char mac_addr[6], char mac_str[20]); + +#endif //WIFI_NET_H diff --git a/framework/src/wifi_manager/wifi_semaphore.c b/framework/src/wifi_manager/wifi_semaphore.c new file mode 100644 index 0000000000..47658d62e1 --- /dev/null +++ b/framework/src/wifi_manager/wifi_semaphore.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include +#include +#include +#include "wifi_semaphore.h" + +wifi_utils_result_e wifi_semaphore_create(wifi_semaphore *semaphore, unsigned int init_value) +{ + if (!semaphore) { + return WIFI_UTILS_INVALID_ARGS; + } + + if (sem_init((sem_t *)semaphore, 0, init_value)) { + return WIFI_UTILS_FAIL; + } + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_semaphore_acquire(wifi_semaphore *semaphore, int time_out) +{ + int result; + + if (!semaphore || time_out < -1) { + return WIFI_UTILS_INVALID_ARGS; + } + + if (time_out == WIFI_UTILS_FOREVER) { + result = sem_wait((sem_t *)semaphore); + } else if (time_out == WIFI_UTILS_NO_WAIT) { + result = sem_trywait((sem_t *)semaphore); + } else { + time_t sec; + uint32_t nsec; + struct timespec abstime; + + sec = time_out / 1000; + nsec = (time_out - 1000 * sec) * 1000000; + + clock_gettime(CLOCK_REALTIME, &abstime); + + abstime.tv_sec += sec; + abstime.tv_nsec += nsec; + if (abstime.tv_nsec >= 1000000000) { + abstime.tv_sec++; + abstime.tv_nsec -= 1000000000; + } + + result = sem_timedwait((sem_t *)semaphore, &abstime); + } + + if (result == 0) { + return WIFI_UTILS_SUCCESS; + } + + if (get_errno() == ETIMEDOUT) { + return WIFI_UTILS_TIMEOUT; + } + + return WIFI_UTILS_FAIL; +} + +wifi_utils_result_e wifi_semaphore_release(wifi_semaphore *semaphore) +{ + if (!semaphore) { + return WIFI_UTILS_INVALID_ARGS; + } + + if (sem_post((sem_t *)semaphore)) { + return WIFI_UTILS_FAIL; + } + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_semaphore_destroy(wifi_semaphore *semaphore) +{ + if (!semaphore) { + return WIFI_UTILS_INVALID_ARGS; + } + + if (sem_destroy((sem_t *)semaphore)) { + return WIFI_UTILS_FAIL; + } + + return WIFI_UTILS_SUCCESS; +} diff --git a/framework/src/wifi_manager/wifi_semaphore.h b/framework/src/wifi_manager/wifi_semaphore.h new file mode 100644 index 0000000000..dbc8e4a600 --- /dev/null +++ b/framework/src/wifi_manager/wifi_semaphore.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef WIFI_SEMAPHORE_H +#define WIFI_SEMAPHORE_H + +#include +#include "wifi_common.h" + +/** + * @file wifi_semaphore.h + * @brief semaphore API + */ + +#ifdef DOXYGEN +/** + * @brief wifi_semaphore struct + */ +typedef vendor_semapore wifi_semaphore; +#else +typedef sem_t wifi_semaphore; +#endif + +/** + * @brief create semaphore + * + * @param[in] semaphore : wifi semaphore + * @param[in] init_value : initial value of the semaphore (resource size) + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_semaphore_create(wifi_semaphore *semaphore, unsigned int init_value); + +/** + * @brief acquire semaphore + * + * @param[in] semaphore : wifi semaphore + * @param[in] time_out : set time out, WIFI_UTILS_NO_WAIT, WIFI_UTILS_FOREVER, or wait milliseconds + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + * @return WIFI_UTILS_TIMEOUT : occur timeout + */ +wifi_utils_result_e wifi_semaphore_acquire(wifi_semaphore *semaphore, int time_out); + +/** + * @brief releases semaphore + * + * @param[in] semaphore : wifi semaphore + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_semaphore_release(wifi_semaphore *semaphore); + +/** + * @brief destroy semaphore + * + * @param[in] semaphore : wifi semaphore + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_semaphore_destroy(wifi_semaphore *semaphore); + +#endif //WIFI_SEMAPHORE_H diff --git a/framework/src/wifi_manager/wifi_utils.c b/framework/src/wifi_manager/wifi_utils.c new file mode 100644 index 0000000000..0b7a2b9a6d --- /dev/null +++ b/framework/src/wifi_manager/wifi_utils.c @@ -0,0 +1,466 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include "wifi_utils.h" + +#include // to be fixed + +#define MACADDR_LENGTH 6 +#define SSID_LENGTH_MAX 32 +#define PASSPHRASE_LENGTH_MAX 64 +#define DHCP_RETRY_COUNT 1 + +typedef void (*link_up_handler)(void *params); +typedef void (*link_down_handler)(void *params); + +static sem_t g_sem_scan_result; +static WiFi_InterFace_ID_t g_mode; +static uint8_t g_join_result; +static link_up_handler g_linkup = NULL; +static link_down_handler g_linkdown = NULL; + +void LinkUpHandlerCb(slsi_reason_t *reason) +{ + g_join_result = reason->reason_code; + if ((reason->reason_code == SLSI_STATUS_SUCCESS) && g_linkup) { + g_linkup(NULL); + } +} + +void LinkDownHandlerCb(slsi_reason_t *reason) +{ + if (g_linkdown) { + g_linkdown(NULL); + } +} + +wifi_utils_result_e wifi_utils_init(void) +{ + if (g_mode != SLSI_WIFI_NONE) { + return WIFI_UTILS_FAIL; + } + + int ret; + + ret = WiFiStart(SLSI_WIFI_STATION_IF, NULL); + if (ret != SLSI_STATUS_SUCCESS) { + ndbg("Failed to start STA mode\n"); + return WIFI_UTILS_FAIL; + } + g_mode = SLSI_WIFI_STATION_IF; + + ret = WiFiRegisterLinkCallback(&LinkUpHandlerCb, &LinkDownHandlerCb); + if (ret != SLSI_STATUS_SUCCESS) { + ndbg("Link callback handles: register failed !\n"); + return WIFI_UTILS_FAIL; + } else { + nvdbg("Link callback handles: registered\n"); + } + sem_init(&g_sem_scan_result, 0, 0); + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_utils_deinit(void) +{ + int ret; + + ret = WiFiStop(); + if (ret != SLSI_STATUS_SUCCESS) { + ndbg("Failed to stop STA mode\n"); + return WIFI_UTILS_FAIL; + } + g_mode = SLSI_WIFI_NONE; + + g_linkup = NULL; + g_linkdown = NULL; + g_join_result = 0; + sem_destroy(&g_sem_scan_result); + + return WIFI_UTILS_SUCCESS; +} + +int8_t ScanResultHandlerCb(slsi_reason_t *reason) +{ + if (reason->reason_code == 0) { + /* Scan succeeded */ + } else { + ndbg("Scan failed reason: %d, locally_generated: %d\n", reason->reason_code, reason->locally_generated); + } + + sem_post(&g_sem_scan_result); + return 0; +} + +wifi_utils_result_e wifi_utils_scan_ap(wifi_utils_ap_scan_info_s *ap_list, unsigned int list_size, unsigned int *found_ap_count) +{ + if (!ap_list || (list_size == 0) || !found_ap_count) { + return WIFI_UTILS_INVALID_ARGS; + } + + int ret; + unsigned int bss_count = 0; + slsi_scan_info_t *results = NULL; + slsi_scan_info_t *head = NULL; + + // issue a scan request command and wait for the message return + WiFiRegisterScanCallback(ScanResultHandlerCb); + ret = WiFiScanNetwork(); + if (ret != SLSI_STATUS_SUCCESS) { + return WIFI_UTILS_FAIL; + } + + sem_wait(&g_sem_scan_result); + + // get scan results when message arrives + ret = WiFiGetScanResults(&results); + if (ret != SLSI_STATUS_SUCCESS || !results) { + return WIFI_UTILS_FAIL; + } + head = results; + + do { + ap_list[bss_count].channel = results->channel; + snprintf(ap_list[bss_count].ssid, SLSI_SSID_LEN + 1, "%s", results->ssid); + ap_list[bss_count].ssid_length = (unsigned int)(results->ssid_len); + hwaddr_aton(results->bssid, ap_list[bss_count].bssid); + ap_list[bss_count].rssi = results->rssi; + + if (!results->sec_modes) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_OPEN; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_NONE; + } else { + if (results->sec_modes->secmode == SLSI_SEC_MODE_WEP || results->sec_modes->secmode == SLSI_SEC_MODE_WEP_SHARED || results->sec_modes->secmode == (SLSI_SEC_MODE_WEP | SLSI_SEC_MODE_WEP_SHARED)) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WEP_SHARED; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_WEP_64; + } else if (results->num_sec_modes == 2 && results->sec_modes[0].secmode == SLSI_SEC_MODE_WPA_MIXED && results->sec_modes[1].secmode == SLSI_SEC_MODE_WPA2_MIXED) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA_AND_WPA2_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_TKIP_AND_AES; + } else if (results->sec_modes->secmode == SLSI_SEC_MODE_WPA2_MIXED) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA2_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_TKIP_AND_AES; + } else if (results->sec_modes->secmode == SLSI_SEC_MODE_WPA2_CCMP) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA2_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_AES; + } else if (results->sec_modes->secmode == SLSI_SEC_MODE_WPA2_TKIP) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA2_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_TKIP; + } else if (results->sec_modes->secmode == SLSI_SEC_MODE_WPA_MIXED) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_TKIP_AND_AES; + } else if (results->sec_modes->secmode == SLSI_SEC_MODE_WPA_CCMP) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_AES; + } else if (results->sec_modes->secmode == SLSI_SEC_MODE_WPA_TKIP) { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_WPA_PSK; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_TKIP; + } else { + ap_list[bss_count].ap_auth_type = WIFI_UTILS_AUTH_UNKNOWN; + ap_list[bss_count].ap_crypto_type = WIFI_UTILS_CRYPTO_UNKNOWN; + } + } + + results = results->next; + if (ap_list[bss_count].ap_auth_type != WIFI_UTILS_AUTH_UNKNOWN && ap_list[bss_count].ap_crypto_type != WIFI_UTILS_CRYPTO_UNKNOWN) { + bss_count++; + } + } while (results->next && bss_count < list_size); + + *found_ap_count = bss_count; + results = head; + WiFiFreeScanResults(&results); + + int i; + for (i = 0; i < *found_ap_count && i < list_size; i++) { + int j; + int max = i; + for (j = i + 1; j < *found_ap_count && i < list_size; j++) { + if (ap_list[max].rssi < ap_list[j].rssi) { + max = j; + } + } + + wifi_utils_ap_scan_info_s tmp; + tmp = ap_list[i]; + ap_list[i] = ap_list[max]; + ap_list[max] = tmp; + } + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_utils_register_connection_callback(void *connect_event_func, void *disconnect_event_func) +{ + g_linkup = connect_event_func; + g_linkdown = disconnect_event_func; + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_utils_connect_ap(wifi_utils_ap_config_s *ap_connect_config) +{ + if (!ap_connect_config) { + return WIFI_UTILS_INVALID_ARGS; + } + + int ret; + wifi_utils_result_e result = WIFI_UTILS_FAIL; + slsi_security_config_t *config = NULL; + + if (ap_connect_config->passphrase && ap_connect_config->passphrase_length) { + config = (slsi_security_config_t *)zalloc(sizeof(slsi_security_config_t)); + if (!config) { + ndbg("Memory allocation failed!\n"); + goto connect_ap_fail; + } + + if ((ap_connect_config->ap_auth_type == WIFI_UTILS_AUTH_WEP_SHARED) && (ap_connect_config->passphrase_length == 5 || ap_connect_config->passphrase_length == 13)) { + config->passphrase[0] = '"'; + memcpy(&config->passphrase[1], ap_connect_config->passphrase, ap_connect_config->passphrase_length); + config->passphrase[ap_connect_config->passphrase_length + 1] = '"'; + config->passphrase[ap_connect_config->passphrase_length + 2] = '\0'; + } else { + memcpy(config->passphrase, ap_connect_config->passphrase, ap_connect_config->passphrase_length); + } + + if (ap_connect_config->ap_auth_type == WIFI_UTILS_AUTH_WEP_SHARED) { + config->secmode = SLSI_SEC_MODE_WEP_SHARED; + } else if (ap_connect_config->ap_auth_type == WIFI_UTILS_AUTH_WPA_PSK) { + if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_AES) { + config->secmode = SLSI_SEC_MODE_WPA_CCMP; + } else if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP) { + config->secmode = SLSI_SEC_MODE_WPA_TKIP; + } else if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP_AND_AES) { + config->secmode = SLSI_SEC_MODE_WPA_MIXED; + } + } else if (ap_connect_config->ap_auth_type == WIFI_UTILS_AUTH_WPA2_PSK) { + if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_AES) { + config->secmode = SLSI_SEC_MODE_WPA2_CCMP; + } else if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP) { + config->secmode = SLSI_SEC_MODE_WPA2_TKIP; + } else if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP_AND_AES) { + config->secmode = SLSI_SEC_MODE_WPA2_MIXED; + } + } else if (ap_connect_config->ap_auth_type == WIFI_UTILS_AUTH_WPA_AND_WPA2_PSK) { + if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_AES) { + config->secmode = (SLSI_SEC_MODE_WPA_CCMP | SLSI_SEC_MODE_WPA2_CCMP); + } else if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP) { + config->secmode = (SLSI_SEC_MODE_WPA_TKIP | SLSI_SEC_MODE_WPA2_TKIP); + } else if (ap_connect_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP_AND_AES) { + config->secmode = (SLSI_SEC_MODE_WPA_MIXED | SLSI_SEC_MODE_WPA2_MIXED); + } + } else { + /* wrong security type */ + ndbg("Wrong security type\n"); + goto connect_ap_fail; + } + } + + ret = WiFiNetworkJoin((uint8_t *)ap_connect_config->ssid, ap_connect_config->ssid_length, NULL, config); + if (ret != SLSI_STATUS_SUCCESS) { + if (ret == SLSI_STATUS_ALREADY_CONNECTED) { + nvdbg("WiFiNetworkJoin already connected\n"); + result = WIFI_UTILS_SUCCESS; + } else { + ndbg("WiFiNetworkJoin failed: %d, %s\n", ret, ap_connect_config->ssid); + goto connect_ap_fail; + } + } else { + result = WIFI_UTILS_SUCCESS; + nvdbg("Successfully joined the network: %s\n", ap_connect_config->ssid); + } + +connect_ap_fail: + if (config) { + free(config); + config = NULL; + } + + return result; +} + +wifi_utils_result_e wifi_utils_disconnect_ap(void) +{ + int ret; + + ret = WiFiNetworkLeave(); + if (ret != SLSI_STATUS_SUCCESS) { + return WIFI_UTILS_FAIL; + } + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_utils_get_info(wifi_utils_info *wifi_info) +{ + if (!wifi_info) { + return WIFI_UTILS_INVALID_ARGS; + } + if (g_mode == SLSI_WIFI_NONE) { + return WIFI_UTILS_FAIL; + } + + struct netif *netif; + + netif = netif_find(CTRL_IFNAME); /* to be changed pkes */ + wifi_info->ip4_address = netif->ip_addr.addr; + + int ret; + + ret = WiFiGetMac(wifi_info->mac_address); + if (ret != SLSI_STATUS_SUCCESS) { + return WIFI_UTILS_FAIL; + } + + wifi_info->rssi = (int)0; + + if (g_mode == SLSI_WIFI_SOFT_AP_IF) { + wifi_info->wifi_status = WIFI_UTILS_SOFT_AP_MODE; + } else if (g_mode == SLSI_WIFI_STATION_IF) { + uint8_t isConnected; + if (WiFiIsConnected(&isConnected, NULL) == SLSI_STATUS_SUCCESS) { + int8_t rssi; + wifi_info->wifi_status = WIFI_UTILS_CONNECTED; + if (WiFiGetRssi(&rssi) == SLSI_STATUS_SUCCESS) { + wifi_info->rssi = (int)rssi; + } + } else { + wifi_info->wifi_status = WIFI_UTILS_DISCONNECTED; + } + } + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_utils_start_soft_ap(wifi_utils_softap_config_s *soft_ap_config) +{ + if (!soft_ap_config) { + return WIFI_UTILS_INVALID_ARGS; + } + + if (g_mode != SLSI_WIFI_STATION_IF) { + ndbg("start softap failed: g_mode = %d\n", g_mode); + return WIFI_UTILS_FAIL; + } + + wifi_utils_result_e ret = WIFI_UTILS_FAIL; + slsi_ap_config_t *ap_config = NULL; + slsi_security_config_t *security_config = NULL; + + ap_config = (slsi_ap_config_t *)zalloc(sizeof(slsi_ap_config_t)); + if (!ap_config) { + ndbg("Memory allocation failed!\n"); + return WIFI_UTILS_FAIL; + } + + /* add initialization code as slsi_app */ + ap_config->beacon_period = 100; + ap_config->DTIM = 1; + ap_config->phy_mode = 1; + + if (soft_ap_config->channel > 14 || soft_ap_config->channel < 1) { + ndbg("Channel needs to be between 1 and 14" " (highest channel depends on regulatory of countries)\n"); + goto start_soft_ap_fail; + } else { + ap_config->channel = soft_ap_config->channel; + } + + if (soft_ap_config->ssid == NULL) { + goto start_soft_ap_fail; + } else { + memcpy(&ap_config->ssid, soft_ap_config->ssid, soft_ap_config->ssid_length); + ap_config->ssid_len = soft_ap_config->ssid_length; + } + + if (!soft_ap_config->passphrase || !soft_ap_config->passphrase_length) { + goto start_soft_ap_fail; + } else { + security_config = (slsi_security_config_t *)zalloc(sizeof(slsi_security_config_t)); + if (!security_config) { + ndbg("Memory allocation failed!\n"); + goto start_soft_ap_fail; + } + memcpy(security_config->passphrase, soft_ap_config->passphrase, soft_ap_config->passphrase_length); + } + + if ((soft_ap_config->ap_auth_type == WIFI_UTILS_AUTH_WPA_PSK) && (soft_ap_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP)) { + security_config->secmode = SLSI_SEC_MODE_WPA_TKIP; + } else if ((soft_ap_config->ap_auth_type == WIFI_UTILS_AUTH_WPA2_PSK) && (soft_ap_config->ap_crypto_type == WIFI_UTILS_CRYPTO_AES)) { + security_config->secmode = SLSI_SEC_MODE_WPA2_CCMP; + } else if ((soft_ap_config->ap_auth_type == WIFI_UTILS_AUTH_WPA_AND_WPA2_PSK) && (soft_ap_config->ap_crypto_type == WIFI_UTILS_CRYPTO_TKIP_AND_AES)) { + security_config->secmode = (SLSI_SEC_MODE_WPA_MIXED | SLSI_SEC_MODE_WPA2_MIXED); + } else { + // if not WPA-TKIP, WPA2-AES, WPA/WPA2 TKIP/AES/MIXED, return fail. + ndbg("Wrong security config. Match proper auth and crypto.\n"); + goto start_soft_ap_fail; + } + ap_config->security = security_config; + + if (WiFiStart(SLSI_WIFI_SOFT_AP_IF, ap_config) != SLSI_STATUS_SUCCESS) { + ndbg("Failed to start AP mode\n"); + goto start_soft_ap_fail; + } + g_mode = SLSI_WIFI_SOFT_AP_IF; + nvdbg("SoftAP with SSID: %s has successfully started!\n", soft_ap_config->ssid); + + ret = WIFI_UTILS_SUCCESS; +start_soft_ap_fail: + if (ap_config) { + free(ap_config); + ap_config = NULL; + } + if (security_config) { + free(security_config); + security_config = NULL; + } + return ret; +} + +wifi_utils_result_e wifi_utils_start_sta(void) +{ + g_mode = SLSI_WIFI_NONE; + + g_join_result = 0; + + if (wifi_utils_init() != WIFI_UTILS_SUCCESS) { + return WIFI_UTILS_FAIL; + } + + return WIFI_UTILS_SUCCESS; +} + +wifi_utils_result_e wifi_utils_stop(void) +{ + int ret; + + if (g_mode != SLSI_WIFI_SOFT_AP_IF) { + return WIFI_UTILS_FAIL; + } + + ret = WiFiStop(); + if (ret != SLSI_STATUS_SUCCESS) { + ndbg("Failed to stop AP mode\n"); + return WIFI_UTILS_FAIL; + } + + return WIFI_UTILS_SUCCESS; +} diff --git a/framework/src/wifi_manager/wifi_utils.h b/framework/src/wifi_manager/wifi_utils.h new file mode 100644 index 0000000000..528268b523 --- /dev/null +++ b/framework/src/wifi_manager/wifi_utils.h @@ -0,0 +1,206 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ + +#ifndef WIFI_UTILS_H +#define WIFI_UTILS_H + +#include "wifi_common.h" + +/** + * @brief wifi authentication type WPA, WPA2, WPS + */ +typedef enum { + WIFI_UTILS_AUTH_OPEN, /**< open mode */ + WIFI_UTILS_AUTH_WEP_SHARED, /**< use shared key (wep key) */ + WIFI_UTILS_AUTH_WPA_PSK, /**< WPA_PSK mode */ + WIFI_UTILS_AUTH_WPA2_PSK, /**< WPA2_PSK mode */ + WIFI_UTILS_AUTH_WPA_AND_WPA2_PSK, /**< WPA_PSK and WPA_PSK mixed mode */ + WIFI_UTILS_AUTH_UNKNOWN, /**< unknown type */ +} wifi_utils_ap_auth_type_e; + +/** + * @brief wifi encryption type WEP, AES, TKIP + */ +typedef enum { + WIFI_UTILS_CRYPTO_NONE, /**< none encryption */ + WIFI_UTILS_CRYPTO_WEP_64, /**< WEP encryption wep-40 */ + WIFI_UTILS_CRYPTO_WEP_128, /**< WEP encryption wep-104 */ + WIFI_UTILS_CRYPTO_AES, /**< AES encryption */ + WIFI_UTILS_CRYPTO_TKIP, /**< TKIP encryption */ + WIFI_UTILS_CRYPTO_TKIP_AND_AES, /**< TKIP and AES mixed encryption */ + WIFI_UTILS_CRYPTO_UNKNOWN, /**< unknown encryption */ +} wifi_utils_ap_crypto_type_e; + +/** + * @brief wifi status (connected, dis_connected, soft_ap) + */ +typedef enum { + WIFI_UTILS_DISCONNECTED, /**< wifi is disconnected */ + WIFI_UTILS_CONNECTED, /**< connected */ + WIFI_UTILS_SOFT_AP_MODE, /**< soft ap mode */ +} wifi_utils_status_e; + +/** + * @brief wifi access point information + */ +typedef struct { + unsigned int channel; /**< Radio channel that the AP beacon was received on */ + char ssid[32]; /**< Service Set Identification (i.e. Name of Access Point) */ + unsigned int ssid_length; /**< The length of Service Set Identification */ + unsigned char bssid[6]; /**< MAC address of Access Point */ + unsigned int max_rate; /**< Maximum data rate in kilobits/s */ + int rssi; /**< Receive Signal Strength Indication in dBm */ + wifi_utils_ap_auth_type_e ap_auth_type; /**< @ref wifi_utils_ap_auth_type */ + wifi_utils_ap_crypto_type_e ap_crypto_type; /**< @ref wifi_utils_ap_crypto_type */ +} wifi_utils_ap_scan_info_s; + +/** + * @brief wifi ap connect config + */ +typedef struct { + char ssid[32]; /**< Service Set Identification */ + unsigned int ssid_length; /**< Service Set Identification Length */ + char passphrase[64]; /**< ap passphrase(password) */ + unsigned int passphrase_length; /**< ap passphrase length */ + wifi_utils_ap_auth_type_e ap_auth_type; /**< @ref wifi_utils_ap_auth_type */ + wifi_utils_ap_crypto_type_e ap_crypto_type; /**< @ref wifi_utils_ap_crypto_type */ +} wifi_utils_ap_config_s; + +/** + * @brief soft ap mode config + */ +typedef struct { + unsigned int channel; /**< soft ap wifi channel */ + char ssid[32]; /**< Service Set Identification */ + unsigned int ssid_length; /**< Service Set Identification Length */ + char passphrase[64]; /**< ap passphrase(password) */ + unsigned int passphrase_length; /**< ap passphrase length */ + wifi_utils_ap_auth_type_e ap_auth_type; /**< @ref wifi_utils_ap_auth_type */ + wifi_utils_ap_crypto_type_e ap_crypto_type; /**< @ref wifi_utils_ap_crypto_type */ + void (*inform_new_sta_join)(void); /**< @ref inform application about new station joining softAP */ +} wifi_utils_softap_config_s; + +/** + * @brief wifi information (ip address, mac address) + */ +typedef struct { + uint32_t ip4_address; /**< ip4 address */ + unsigned char mac_address[6]; /**< MAC address of wifi interface */ + int rssi; /**< Receive Signal Strength Indication in dBm */ + wifi_utils_status_e wifi_status; /**< @ref wifi_utils_status */ +} wifi_utils_info; + +/** + * @brief wifi interface init + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + */ +wifi_utils_result_e wifi_utils_init(void); + +/** + * @brief wifi interface deinit + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + */ +wifi_utils_result_e wifi_utils_deinit(void); + +/** + * @brief scans access point list + * + * @param[in] ap_list : pre declared wifi_utils_ap_scan_info_s array pointer + * @param[in] list_size : ap_list size (wifi_utils_ap_info array) + * @param[out] found_ap_count : found ap count + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_scan_ap(wifi_utils_ap_scan_info_s *ap_list, unsigned int list_size, unsigned int *found_ap_count); + +/** + * @brief wifi connect access point + * + * @param[in] ap_connect_config : target ap connect config + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_connect_ap(wifi_utils_ap_config_s *ap_connect_config); + +/** + * @brief wifi disconnect access point + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + */ +wifi_utils_result_e wifi_utils_disconnect_ap(void); + +/** + * @brief get wifi information (IP address, MAC address) + * + * @param[out] wifi_info : @ref wifi_utils_info + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_get_info(wifi_utils_info *wifi_info); + +/** + * @brief register wifi connection event callback (connect/disconnect event) + * + * @param[in] connect_event_func : when wifi connect event received, function start + * @param[in] disconnect_event_func : when wifi disconnect event received, function start + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_register_connection_callback(void *connect_event_func, void *disconnect_event_func); + +/** + * @brief wifi start soft ap mode + * + * @param[in] soft_ap_config : @ref wifi_utils_softap_config_s + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + * @return WIFI_UTILS_INVALID_ARGS : input parameter invalid + */ +wifi_utils_result_e wifi_utils_start_soft_ap(wifi_utils_softap_config_s *soft_ap_config); + +/** + * @brief start wifi sta mode + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + */ +wifi_utils_result_e wifi_utils_start_sta(void); + +/** + * @brief stop wifi + * + * @return WIFI_UTILS_SUCCESS : success + * @return WIFI_UTILS_FAIL : fail + */ +wifi_utils_result_e wifi_utils_stop(void); + +#endif //WIFI_UTILS_H diff --git a/os/net/Kconfig b/os/net/Kconfig index 2c27ae5006..bdcd0ee4aa 100644 --- a/os/net/Kconfig +++ b/os/net/Kconfig @@ -132,6 +132,12 @@ endif #NET_SECURITY_TLS endmenu #Protocols +menu "Wireless" + +source ../framework/src/wifi_manager/Kconfig + +endmenu #Wireless + menu "Network utilities" source "$EXTERNALDIR/netutils/Kconfig.netutil"