/*
 * FST module implementation
 * Copyright (c) 2014, Qualcomm Atheros, Inc.
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "utils/includes.h"

#include "utils/common.h"
#include "utils/eloop.h"
#include "fst/fst.h"
#include "fst/fst_internal.h"
#include "fst/fst_defs.h"
#include "fst/fst_ctrl_iface.h"

static int fst_global_initialized = 0;
struct dl_list fst_global_ctrls_list;


static void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface,
						    bool connected,
						    const u8 *peer_addr)
{
	union fst_event_extra extra;

	extra.peer_state.connected = connected;
	os_strlcpy(extra.peer_state.ifname, fst_iface_get_name(iface),
		   sizeof(extra.peer_state.ifname));
	os_memcpy(extra.peer_state.addr, peer_addr, ETH_ALEN);

	foreach_fst_ctrl_call(on_event, EVENT_PEER_STATE_CHANGED,
			      iface, NULL, &extra);
}


struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr,
			      const struct fst_wpa_obj *iface_obj,
			      const struct fst_iface_cfg *cfg)
{
	struct fst_group *g;
	struct fst_group *group = NULL;
	struct fst_iface *iface = NULL;
	bool new_group = false;

	WPA_ASSERT(ifname != NULL);
	WPA_ASSERT(iface_obj != NULL);
	WPA_ASSERT(cfg != NULL);

	foreach_fst_group(g) {
		if (os_strcmp(cfg->group_id, fst_group_get_id(g)) == 0) {
			group = g;
			break;
		}
	}

	if (!group) {
		group = fst_group_create(cfg->group_id);
		if (!group) {
			fst_printf(MSG_ERROR, "%s: FST group cannot be created",
				   cfg->group_id);
			return NULL;
		}
		new_group = true;
	}

	iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg);
	if (!iface) {
		fst_printf_group(group, MSG_ERROR, "cannot create iface for %s",
				 ifname);
		if (new_group)
			fst_group_delete(group);
		return NULL;
	}

	fst_group_attach_iface(group, iface);
	fst_group_update_ie(group);

	foreach_fst_ctrl_call(on_iface_added, iface);

	fst_printf_iface(iface, MSG_DEBUG,
			 "iface attached to group %s (prio=%d, llt=%d)",
			 cfg->group_id, cfg->priority, cfg->llt);

	return iface;
}


void fst_detach(struct fst_iface *iface)
{
	struct fst_group *group = fst_iface_get_group(iface);

	fst_printf_iface(iface, MSG_DEBUG, "iface detached from group %s",
			 fst_group_get_id(group));
	fst_session_global_on_iface_detached(iface);
	foreach_fst_ctrl_call(on_iface_removed, iface);
	fst_group_detach_iface(group, iface);
	fst_iface_delete(iface);
	fst_group_update_ie(group);
	fst_group_delete_if_empty(group);
}


int fst_global_init(void)
{
	dl_list_init(&fst_global_groups_list);
	dl_list_init(&fst_global_ctrls_list);
	fst_session_global_init();
	fst_global_initialized = 1;
	return 0;
}


void fst_global_deinit(void)
{
	struct fst_group *group;
	struct fst_ctrl_handle *h;

	if (!fst_global_initialized)
		return;

	fst_session_global_deinit();
	while ((group = fst_first_group()) != NULL)
		fst_group_delete(group);
	while ((h = dl_list_first(&fst_global_ctrls_list,
				  struct fst_ctrl_handle,
				  global_ctrls_lentry)))
		fst_global_del_ctrl(h);
	fst_global_initialized = 0;
}


struct fst_ctrl_handle * fst_global_add_ctrl(const struct fst_ctrl *ctrl)
{
	struct fst_ctrl_handle *h;

	if (!ctrl)
		return NULL;

	h = os_zalloc(sizeof(*h));
	if (!h)
		return NULL;

	if (ctrl->init && ctrl->init()) {
		os_free(h);
		return NULL;
	}

	h->ctrl = *ctrl;
	dl_list_add_tail(&fst_global_ctrls_list, &h->global_ctrls_lentry);

	return h;
}


void fst_global_del_ctrl(struct fst_ctrl_handle *h)
{
	dl_list_del(&h->global_ctrls_lentry);
	if (h->ctrl.deinit)
		h->ctrl.deinit();
	os_free(h);
}


void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt,
		   size_t len)
{
	if (fst_iface_is_connected(iface, mgmt->sa, false))
		fst_session_on_action_rx(iface, mgmt, len);
	else
		wpa_printf(MSG_DEBUG,
			   "FST: Ignore FST Action frame - no FST connection with "
			   MACSTR, MAC2STR(mgmt->sa));
}


void fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr)
{
	if (is_zero_ether_addr(addr))
		return;

#ifndef HOSTAPD
	fst_group_update_ie(fst_iface_get_group(iface));
#endif /* HOSTAPD */

	fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected",
			 MAC2STR(addr));

	fst_ctrl_iface_notify_peer_state_change(iface, true, addr);
}


void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr)
{
	if (is_zero_ether_addr(addr))
		return;

#ifndef HOSTAPD
	fst_group_update_ie(fst_iface_get_group(iface));
#endif /* HOSTAPD */

	fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected",
			 MAC2STR(addr));

	fst_ctrl_iface_notify_peer_state_change(iface, false, addr);
}


bool fst_are_ifaces_aggregated(struct fst_iface *iface1,
			       struct fst_iface *iface2)
{
	return fst_iface_get_group(iface1) == fst_iface_get_group(iface2);
}


void fst_update_mac_addr(struct fst_iface *iface, const u8 *addr)
{
	fst_printf_iface(iface, MSG_DEBUG, "new MAC address " MACSTR,
			 MAC2STR(addr));
	os_memcpy(iface->own_addr, addr, sizeof(iface->own_addr));
	fst_group_update_ie(fst_iface_get_group(iface));
}


enum mb_band_id fst_hw_mode_to_band(enum hostapd_hw_mode mode)
{
	switch (mode) {
	case HOSTAPD_MODE_IEEE80211B:
	case HOSTAPD_MODE_IEEE80211G:
		return MB_BAND_ID_WIFI_2_4GHZ;
	case HOSTAPD_MODE_IEEE80211A:
		return MB_BAND_ID_WIFI_5GHZ;
	case HOSTAPD_MODE_IEEE80211AD:
		return MB_BAND_ID_WIFI_60GHZ;
	default:
		WPA_ASSERT(0);
		return MB_BAND_ID_WIFI_2_4GHZ;
	}
}
