--- /dev/null
+/**
+ @file wlan.c
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Janne Ylalehto <janne.ylalehto@nokia.com>
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include <wlancond.h>
+#include <wlancond-dbus.h>
+#include <wlancond-supp.h>
+
+#include "common.h"
+#include "dbus.h"
+#include "dbus-helper.h"
+#include "wlan.h"
+#include "log.h"
+
+/* -- SCANNING -- */
+
+static wlan_found_ap found_ap_cb = NULL;
+
+int wlan_scan(const char * ssid, wlan_found_ap new_found_ap_cb)
+{
+ DBusMessage *msg, *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s: %s (active)", __func__, ssid);
+
+ dbus_error_init(&error);
+
+ found_ap_cb = new_found_ap_cb;
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_SCAN_REQ);
+
+ gint32 power_level = WLANCOND_TX_POWER100;
+ guint32 flags = 0;
+
+ append_dbus_args(
+ msg,
+ DBUS_TYPE_INT32, &power_level,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, strlen(ssid) + 1,
+ DBUS_TYPE_UINT32, &flags,
+
+ DBUS_TYPE_INVALID);
+
+ reply = dbus_connection_send_with_reply_and_block(get_dbus_connection(),
+ msg, -1, &error);
+
+ dbus_message_unref(msg);
+
+ if (reply) {
+ DLOG_DEBUG("Scan reply OK");
+ dbus_message_unref(reply);
+
+ return 0;
+ } else if (dbus_error_is_set(&error)) {
+ DLOG_INFO("Scan pending call result:%s", error.name);
+ dbus_error_free(&error);
+ found_ap_cb = NULL;
+ return -1;
+ } else {
+ DLOG_WARN("Scan without reply");
+ found_ap_cb = NULL;
+ return -1;
+ }
+}
+
+gboolean wlan_is_scanning()
+{
+ return found_ap_cb ? TRUE : FALSE;
+}
+
+void wlan_notify_ap(const char *ssid, const char *bssid,
+ int rssi, unsigned int channel, unsigned int cap_bits)
+{
+ if (found_ap_cb)
+ found_ap_cb(SEARCH_CONTINUE, ssid, bssid, rssi / 2 - 110);
+}
+
+void wlan_notify_end_of_search()
+{
+ wlan_found_ap prev_found_ap_cb = found_ap_cb;
+ found_ap_cb = NULL;
+
+ // A new search may be started right after calling this callback
+
+ if (prev_found_ap_cb)
+ prev_found_ap_cb(SEARCH_FINISHED, NULL, NULL, 0);
+}
+
+/* - CONNECTING - */
+
+static wlan_connected connected_cb;
+
+static void connect_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("Connect reply callback");
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+
+ DLOG_DEBUG("Connect pending call result:%s", error.name);
+
+ connected_cb(-1, error.name);
+ dbus_error_free(&error);
+ } else if (reply) {
+ connected_cb(0, NULL);
+ }
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void wlan_connect(const char * ssid, wlan_connected _connected_cb)
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s: %s", __func__, ssid);
+
+ connected_cb = _connected_cb;
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_SETTINGS_AND_CONNECT_REQ);
+
+ guint32 dummy = 0;
+ guint32 *dummyP = &dummy;
+
+ gint32 power_level, mode, encryption, default_key;
+ guint32 adhoc_channel, flags;
+
+ power_level = WLANCOND_TX_POWER100;
+ mode = WLANCOND_INFRA;
+ encryption = 0;
+ default_key = 0;
+ adhoc_channel = 0;
+ flags = WLANCOND_USE_SUPPLICANT;
+
+ append_dbus_args(
+ msg,
+ DBUS_TYPE_INT32, &power_level,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, strlen(ssid),
+ DBUS_TYPE_INT32, &mode,
+ DBUS_TYPE_INT32, &encryption,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_INT32, &default_key,
+ DBUS_TYPE_UINT32, &adhoc_channel,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending, connect_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
+static void disconnect_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("Disconnect reply callback");
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+
+ DLOG_DEBUG("Disconnect pending call result:%s", error.name);
+
+ dbus_error_free(&error);
+ }
+
+ // No need to notify, wpa_supplicant will signal that for us
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void wlan_disconnect()
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s", __func__);
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_DISCONNECT_REQ);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending, disconnect_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
+/* -- STATUS -- */
+
+static wlan_status_reply status_cb;
+
+static void status_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s", __func__);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+
+ DLOG_DEBUG("%s error: %s", __func__, error.name);
+ goto dbus_error;
+ } else if (reply) {
+ char *essid, *bssid, *ifname;
+ int essid_len, bssid_len;
+ unsigned long sens, channel, capability, security;
+
+ if (!dbus_message_get_args(
+ reply, &error,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &essid, &essid_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, &bssid_len,
+ DBUS_TYPE_UINT32, &sens,
+ DBUS_TYPE_UINT32, &channel,
+ DBUS_TYPE_UINT32, &capability,
+ DBUS_TYPE_UINT32, &security,
+ DBUS_TYPE_STRING, &ifname,
+ DBUS_TYPE_INVALID))
+ {
+ DLOG_DEBUG("%s parse reply error: %s", __func__,
+ error.name);
+ goto dbus_error;
+ }
+
+ status_cb(0, essid, essid_len, bssid, bssid_len,
+ sens, channel, capability, security,
+ ifname);
+ }
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+
+ return;
+dbus_error:
+ status_cb(-1, NULL, 0, NULL, 0,
+ 0, 0, 0, 0,
+ error.name);
+ dbus_error_free(&error);
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void wlan_get_status(wlan_status_reply reply_cb)
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s", __func__);
+
+ status_cb = reply_cb;
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_STATUS_REQ);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending, status_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+