Wi-Fi Manager is introduced to provide easy APIs for applications to easily manipulate Wi-Fi features
}
}
- if (dhcpd_start(argv[2]) != 0) {
+ if (dhcpd_start(argv[2], NULL) != 0) {
printf("%s : failed to start dhcpd\n", __FUNCTION__);
goto done;
}
#include <tinyara/compiler.h> /* For CONFIG_CPP_HAVE_WARNING */
#include <arch/irq.h> /* For irqstore() and friends -- REVISIT */
#include <tinyara/net/net.h> /* For net_lock() and friends */
+#ifndef CONFIG_NET_LWIP
+#include <tinyara/net/arp.h> /* For low-level ARP interfaces -- REVISIT */
+#endif
#include <protocols/dhcpd.h> /* 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 <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <semaphore.h>
/****************************************************************************
* Global Data
****************************************************************************/
+sem_t g_dhcpd_sem;
/****************************************************************************
* Private Data
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
****************************************************************************/
}
#else
#define dhcpd_arpupdate(pipaddr, phwaddr)
-#endif /* CONFIG_NET_LWIP */
+#endif /* CONFIG_NET_LWIP */
#else
#define dhcpd_arpupdate(pipaddr, phwaddr)
#endif
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);
*/
switch (ptr[DHCPD_OPTION_CODE]) {
- /* Skip over any padding bytes */
+ /* Skip over any padding bytes */
case DHCP_OPTION_PAD:
optlen = 1;
}
/****************************************************************************
- * 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
****************************************************************************/
{
struct sockaddr_in addr;
in_addr_t ipaddr;
- int sockfd;
int len;
int ret = ERROR;
/* 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;
}
{
struct sockaddr_in addr;
in_addr_t ipaddr;
- int sockfd;
int len;
int ret = ERROR;
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
****************************************************************************/
}
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;
}
return sockfd;
}
-
/****************************************************************************
* Private Functions
****************************************************************************/
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
****************************************************************************/
return 0;
}
-
/****************************************************************************
* Public Functions
****************************************************************************/
****************************************************************************/
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
****************************************************************************/
int dhcpd_run(void *arg)
{
- int sockfd;
int nbytes;
#if DHCPD_SELECT
int ret = OK;
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) */
/* 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;
}
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:
}
}
- 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) */
return ret;
}
-
/****************************************************************************
* Public Functions
****************************************************************************/
#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));
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");
#define EXTERN extern
#endif
+typedef void (*dhcp_sta_joined)(void);
+
/**
* @brief Starts DHCP server which is attached given network interface.
*
* @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
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))
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <b> wifi result type FAIL, SUCCESS, INVALID ARGS</b>
+ */
+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 <b> wifi authentication type WPA, WPA2, WPS</b>
+ */
+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
+
+/**
+ *@}
+ */
--- /dev/null
+#
+# 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
--- /dev/null
+###########################################################################
+#
+# 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
+
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <b> wifi result type FAIL, SUCCESS, INVALID ARGS</b>
+ */
+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
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <tinyara/config.h>
+#include <debug.h>
+#include <fcntl.h>
+#include <mqueue.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+#include <wifi_manager/wifi_manager.h>
+#include <protocols/dhcpc.h>
+#include <protocols/dhcpd.h>
+#include <slsi_wifi/slsi_wifi_api.h>
+#include <semaphore.h>
+#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;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * 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);
+}
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <semaphore.h>
+#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
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <tinyara/config.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sched.h>
+#include <errno.h>
+#include <debug.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#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;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * 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
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <semaphore.h>
+#include <errno.h>
+#include <time.h>
+#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;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <semaphore.h>
+#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
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <tinyara/config.h>
+#include <debug.h>
+#include <stdio.h>
+#include <slsi_wifi/slsi_wifi_api.h>
+#include "wifi_utils.h"
+
+#include <net/lwip/netif.h> // 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;
+}
--- /dev/null
+/****************************************************************************
+ *
+ * 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 <b> wifi authentication type WPA, WPA2, WPS</b>
+ */
+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
endmenu #Protocols
+menu "Wireless"
+
+source ../framework/src/wifi_manager/Kconfig
+
+endmenu #Wireless
+
menu "Network utilities"
source "$EXTERNALDIR/netutils/Kconfig.netutil"