#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <linux/wireless.h>
+
#include <wifi-manager.h>
#ifdef TIZEN_FEATURE_ENABLE_WIFI_DIRECT
#include <wifi-direct.h>
#include "mobileap_handler.h"
#include "mobileap_notification.h"
+#ifndef IFNAMSIZ
+#define IFNAMEIZ 16
+#endif
+
#define WIFI_RECOVERY_GUARD_TIME 1000 /* ms */
#define MOBILE_AP_WIFI_KEY_MIN_LEN 8 /**< Minimum length of wifi key */
#define MOBILE_AP_WIFI_KEY_MAX_LEN 64 /**< Maximum length of wifi key */
static wifi_manager_h wifi_manager = NULL;
+typedef void (*wifi_interface_cb)(const char *ifname, void *user_data);
+
+typedef enum {
+ WIFI_BAND_NONE = 0,
+ WIFI_BAND_2G = 1 << 0,
+ WIFI_BAND_5G = 1 << 1
+} wifi_bands_e;
+
void _init_wifi_manager(void)
{
int ret = wifi_manager_initialize(&wifi_manager);
return (strlen(key) && (strlen(key) <= MOBILE_AP_WIFI_KEY_MAX_LEN));
}
+static char *_extract_ifname(char *ifname, int size, char *line)
+{
+ char *end;
+
+ while (*line == ' ')
+ line++;
+
+ end = strstr(line, ": ");
+
+ if ((end == NULL) || (((end - line) + 1) > size))
+ return NULL;
+
+ memcpy(ifname, line, (end - line));
+ ifname[end - line] = '\0';
+
+ return end;
+}
+
+static void _foreach_wifi_interface(wifi_interface_cb cb, void *user_data)
+{
+ char line[1024];
+ FILE *file;
+
+ if (cb == NULL)
+ return;
+
+ file = fopen("/proc/net/wireless", "r");
+ if (file == NULL) {
+ ERR("Error opening wireless interface details"); //LCOV_EXCL_LINE
+ return;
+ }
+
+ /* Skip first two lines of header */
+ if (fgets(line, sizeof(line), file) == NULL) {
+ ERR("Error skipping line 1"); //LCOV_EXCL_LINE
+ fclose(file);
+ return;
+ }
+
+ if (fgets(line, sizeof(line), file) == NULL) {
+ ERR("Error skipping line 2"); //LCOV_EXCL_LINE
+ fclose(file);
+ return;
+ }
+
+ while (fgets(line, sizeof(line), file)) {
+ char ifname[IFNAMSIZ + 1];
+
+ if((line[0] == '\0') || (line[1] == '\0'))
+ continue;
+
+ if (_extract_ifname(ifname, sizeof(ifname), line) == NULL) {
+ ERR("Failed to fetch ifname, continue for next interface");
+ continue;
+ }
+
+ cb(ifname, user_data);
+ }
+
+ fclose(file);
+}
+
+static int _get_supported_wifi_bands(const char *ifname)
+{
+ struct iwreq req;
+ char buff[sizeof(struct iw_range) * 2];
+ struct iw_range *range;
+ int fd;
+ int i;
+ int ret = WIFI_BAND_NONE;
+
+ fd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return ret;
+
+ memset(&req, 0, sizeof(req));
+
+ req.u.data.pointer = (caddr_t) buff;
+ req.u.data.length = sizeof(buff);
+ req.u.data.flags = 0;
+ strncpy(req.ifr_name, ifname, IFNAMSIZ);
+
+ if (ioctl(fd, SIOCGIWRANGE, &req) < 0) {
+ close(fd);
+ return ret;
+ }
+
+ range = (struct iw_range *) buff;
+
+ if (range->we_version_compiled <= 15) {
+ close(fd);
+ return ret;
+ }
+
+ if (range->num_frequency <= 0) {
+ close(fd);
+ return ret;
+ }
+
+ for (i = 0; i < range->num_frequency; i++) {
+ if (range->freq[i].i == 1)
+ ret |= WIFI_BAND_2G;
+
+ if (range->freq[i].i == 36) {
+ ret |= WIFI_BAND_5G;
+ break;
+ }
+ }
+
+ close(fd);
+ return ret;
+}
+
mobile_ap_error_code_e _reload_softap_settings(Tethering *obj, softap_settings_t *settings)
{
gboolean backup_prev_wifi_on = prev_wifi_on;
return TRUE;
}
+static void _get_wifi_interface_details(const char *ifname, void *user_data)
+{
+ GVariantBuilder *builder = (GVariantBuilder *)user_data;
+ GVariantBuilder *sub_builder;
+ int supported_bands;
+
+ DBG("Available interface [%s]", ifname);
+ supported_bands = _get_supported_wifi_bands(ifname);
+
+ sub_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+ g_variant_builder_add(sub_builder, "{sv}", "IfName",
+ g_variant_new_string(ifname));
+
+ g_variant_builder_add(sub_builder, "{sv}", "Is2GBandSupported",
+ g_variant_new_boolean(supported_bands & WIFI_BAND_2G));
+
+ g_variant_builder_add(sub_builder, "{sv}", "Is5GBandSupported",
+ g_variant_new_boolean(supported_bands & WIFI_BAND_5G));
+
+ g_variant_builder_add(builder, "(@a{sv})",
+ g_variant_builder_end(sub_builder));
+
+ g_variant_builder_unref(sub_builder);
+}
+
+gboolean tethering_get_wifi_interfaces(Tethering *obj,
+ GDBusMethodInvocation *context)
+{
+ DBG("+");
+
+ GVariant *var = NULL;
+ GVariantBuilder *builder;
+
+ g_assert(obj != NULL);
+#ifndef TIZEN_FEATURE_UNITTEST
+ g_assert(context != NULL);
+#endif
+
+ builder = g_variant_builder_new(G_VARIANT_TYPE("a(a{sv})"));
+ _foreach_wifi_interface(_get_wifi_interface_details, builder);
+ var = g_variant_new("(@a(a{sv}))", g_variant_builder_end(builder));
+ g_variant_builder_unref(builder);
+
+#ifndef TIZEN_FEATURE_UNITTEST
+ g_dbus_method_invocation_return_value(context, var);
+#endif
+ g_variant_unref(var);
+
+ DBG("-");
+ return TRUE;
+}
+
gboolean tethering_set_hostapd_tx_power(Tethering *obj,
GDBusMethodInvocation *context, gint txpower)
{