/*
 * example.c - example plugin demonstrating cmdu extension handling.
 *
 * Copyright (C) 2023 IOPSYS Software Solutions AB. All rights reserved.
 *
 * Author: anjan.chanda@iopsys.eu
 *
 * See LICENSE file for license related information.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include <libubox/list.h>

#include <1905_tlvs.h>
#include <easymesh.h>

#include <extension.h>

struct example_private {
	void *module;
	void *cookie;
	int paused;
	uint16_t types[16];
	int num_types;
};

static int example_init(void **priv, void *cookie);
static void example_exit(void *priv);

int example_process_cmdu(struct example_private *p, void *cmdu, size_t cmdulen)
{
	fprintf(stderr, "%s: called\n", __func__);
	return CMDU_OK;
}

int example_process(void *priv, uint8_t *src, void *cmdu, size_t cmdulen)
{
	struct example_private *p = (struct example_private *)priv;

	if (!cmdu || cmdulen == 0)
		return -1;

	if (!p->paused)
		example_process_cmdu(p, cmdu, cmdulen);

	return 0;
}

int example_start(void *priv)
{
	struct example_private *p = (struct example_private *)priv;

	p->paused = 0;

	return 0;
}

int example_stop(void *priv)
{
	struct example_private *p = (struct example_private *)priv;

	p->paused = 1;

	return 0;
}


extern struct plugin example;
struct plugin example = {
	.name = "example",
	.oui = "\x11\x22\x33",
	.init = example_init,
	.exit = example_exit,
	.start = example_start,
	.stop = example_stop,
	.process_cmdu = example_process,
};

int example_init(void **priv, void *cookie)
{
	struct example_private *p;

	p = calloc(1, sizeof(struct example_private));
	if (!p)
		return -1;

	*priv = p;
	p->module = &example;
	p->cookie = cookie;

	fprintf(stderr, "%s: *priv = %p\n", __func__, *priv);
	fprintf(stderr, "%s: plugin: %p\n", __func__, p->module);

	cmdu_set_extension_mask(p->module,
			CMDU_TYPE_TOPOLOGY_DISCOVERY,		CMDU_RX,
			CMDU_TYPE_TOPOLOGY_NOTIFICATION,	CMDU_RX,
			CMDU_TYPE_TOPOLOGY_QUERY,		CMDU_PRE_TX,
			CMDU_TYPE_TOPOLOGY_RESPONSE,		CMDU_PRE_TX | CMDU_RX,
			CMDU_TYPE_VENDOR_SPECIFIC,		CMDU_PRE_TX | CMDU_RX,
			CMDU_TYPE_AP_AUTOCONFIGURATION_SEARCH,	CMDU_RX,
			CMDU_TYPE_AP_AUTOCONFIGURATION_RESPONSE,CMDU_RX | CMDU_PRE_TX,
			CMDU_TYPE_AP_AUTOCONFIGURATION_WSC,	CMDU_RX,
			CMDU_TYPE_AP_AUTOCONFIGURATION_RENEW,	CMDU_RX,
			CMDU_1905_ACK,				CMDU_RX | CMDU_PRE_TX,
			CMDU_BEACON_METRICS_QUERY,		CMDU_RX,
			CMDU_BACKHAUL_STEER_REQUEST,		CMDU_RX | CMDU_PRE_TX,
			CMDU_AP_METRICS_QUERY,			CMDU_RX,
			CMDU_ASSOC_STA_LINK_METRICS_QUERY,	CMDU_RX,
			CMDU_UNASSOC_STA_LINK_METRIC_QUERY,	CMDU_RX,
#if (EASYMESH_VERSION > 1)
			CMDU_CHANNEL_SCAN_REQUEST,		CMDU_PRE_TX,
			CMDU_CHANNEL_SCAN_REPORT,		CMDU_PRE_TX,
			CMDU_BACKHAUL_STA_CAPABILITY_QUERY,	CMDU_PRE_TX,
			CMDU_BACKHAUL_STA_CAPABILITY_REPORT,	CMDU_PRE_TX,
#endif
			CMDU_POLICY_CONFIG_REQ,			CMDU_RX,
			CMDU_CHANNEL_PREFERENCE_QUERY,		CMDU_PRE_TX,
			CMDU_CHANNEL_SELECTION_REQ,		CMDU_PRE_TX,
			CMDU_CLIENT_STEERING_REQUEST,		CMDU_PRE_TX,
			CMDU_CLIENT_ASSOC_CONTROL_REQUEST,	CMDU_PRE_TX,
			CMDU_AP_CAPABILITY_QUERY,		CMDU_RX,
			CMDU_AP_CAPABILITY_REPORT,		CMDU_PRE_TX,
			CMDU_HIGHER_LAYER_DATA,			CMDU_PRE_TX,
			CMDU_CLIENT_CAPABILITY_QUERY,		CMDU_RX,
#if (EASYMESH_VERSION > 2)
			CMDU_BSS_CONFIG_RESPONSE,		CMDU_RX,
			CMDU_DPP_CCE_INDICATION,		CMDU_RX,
			CMDU_AGENT_LIST,			CMDU_RX,
#endif
			-1, -1);


	return 0;
}

static void example_exit(void *priv)
{
	struct example_private *p = (struct example_private *)priv;

	if (p)
		free(p);
}
