// SPDX-License-Identifier: GPL-2.0-only
/*
 * wifimngr.h - header file for wifimngr.
 *
 * Copyright (C) 2019-2024 IOPSYS Software Solutions AB. All rights reserved.
 * Copyright (C) 2025 Genexis AB.
 *
 * Author: Anjan Chanda <anjan.chanda@genexis.eu>
 */

#ifndef WIFIMNGR_H
#define WIFIMNGR_H

#include <linux/limits.h>

#include "wifimngr_opts.h"

#define WIFI_DEV_MAX_NUM        8
#define WIFI_IF_MAX_NUM         32
#define WIFI_MLD_MAX_NUM        4

#define WIFI_OBJECT                     "wifi"
#define WIFI_WPS_OBJECT                 "wifi.wps"

#define WIFI_RADIO_OBJECT               "wifi.radio"
#define WIFI_AP_OBJECT                  "wifi.ap"
#define WIFI_BSTA_OBJECT                "wifi.bsta"
#define WIFI_APMLD_OBJECT               "wifi.apmld"
#define WIFI_BSTAMLD_OBJECT             "wifi.bstamld"

#define WIFI_AP_OBJECT_PREFIX           WIFI_AP_OBJECT"."
#define WIFI_RADIO_OBJECT_PREFIX        WIFI_RADIO_OBJECT"."
#define WIFI_BSTA_OBJECT_PREFIX         WIFI_BSTA_OBJECT"."
#define WIFI_APMLD_OBJECT_PREFIX        WIFI_APMLD_OBJECT"."
#define WIFI_BSTAMLD_OBJECT_PREFIX      WIFI_BSTAMLD_OBJECT"."


/* wifi ubus objects */
struct wifi_ubus_object {
	void *priv;
	struct ubus_object obj;
	struct ubus_object_type obj_type;
	struct list_head list;
};

/* initial estimate for number of APs in scanresults */
#define NUM_SCANRES			128
#define MAX_NUM_SUPP_CHANNELS		64
#define MAX_NUM_PER_CHANNEL_SCANRES	64

struct wifimngr_channel {
	uint32_t channel;		/* 20MHz ctrl-channel */
	uint32_t freq;			/* frequency in MHz */

#ifdef WIFI_CACHE_SCANRESULTS 
	/* cached scanresults from latest scan */
	time_t scanres_ts;
	int num_scanres;
	struct wifi_bss *scanres;
#endif
};

struct wifimngr_device {
	char device[16];
	char phy[16];
	union {
		uint8_t macaddr[6];
		char phypath[256];
	};
	char country[3];
	enum wifi_band band;
	bool disabled;
	bool mlo_capable;
	bool mlo;
	bool acs_enabled;
	uint32_t object_id;

	int num_ch;
	struct wifimngr_channel ch[MAX_NUM_SUPP_CHANNELS];
};

struct wifimngr_iface {
	char iface[16];
	char device[16];
	char phy[16];
	char mld[16];
	char mld_netdev[16];
	enum wifi_band band;
	bool mlo;
	enum wifi_mode mode;
	int disabled;
	uint32_t object_id;
};

struct wifimngr_mld {
	char ifname[16];
	enum wifi_mode mode;
	uint32_t object_id;
};

struct wifimngr {
	struct wifimngr_device wdev[WIFI_DEV_MAX_NUM];
	int num_wifi_device;

	struct wifimngr_iface ifs[WIFI_IF_MAX_NUM];
	int num_wifi_iface;

	struct wifimngr_mld mld[WIFI_MLD_MAX_NUM];
	int num_wifi_mld;

	const char *evmap_file;
	const char *conffile;
	struct uloop_timeout hbtimer;
	uint64_t ticks;

#ifdef HAS_UBUS
	struct ubus_context *ubus_ctx;
	struct ubus_object wifi_obj;
	struct ubus_object wifi_wps_obj;
#endif

	struct list_head event_list;
	struct list_head radiolist;  /* list of wifi_ubus_objects */
	struct list_head iflist;     /* list of wifi_ubus_objects */
};

int wifimngr_get_wifi_devices(struct wifimngr *w, const char *conffile);
int wifimngr_get_wifi_interfaces(struct wifimngr *w, const char *conffile);
int wifimngr_get_wifi_mlds(struct wifimngr *w, const char *conffile);

struct wifimngr_device *wifimngr_ifname_to_device(struct wifimngr *w, const char *ifname);

const char *ubus_objname_to_ifname(struct ubus_object *obj);

#define UBUS_METHOD_ADD(_tab, iter, __m)				\
do {									\
	struct ubus_method ___m = __m;					\
	memcpy(&_tab[iter++], &___m, sizeof(struct ubus_method));	\
} while(0)


int add_wifi_methods(struct wifimngr *w, struct ubus_object *wifi_obj);
int add_wps_methods(struct wifimngr *w, struct ubus_object *wifi_wps_obj);

int wifimngr_add_objects(struct wifimngr *w);

int wifimngr_add_object(struct wifimngr *w, const char *objname,
			int (*add_methods)(struct wifimngr *w, struct ubus_object *o),
			struct ubus_object *object);

int wifimngr_add_radio_object(struct wifimngr *w, struct wifimngr_device *wdev);
int wifimngr_add_interface_object(struct wifimngr *w, struct wifimngr_iface *iface);
int wifimngr_add_mld_interface_object(struct wifimngr *w, struct wifimngr_mld *mldif);

int wifimngr_main(struct wifimngr_cmdline_opts *opts);
int wifimngr_init(struct wifimngr **w, struct wifimngr_cmdline_opts *opts);
int wifimngr_exit(struct wifimngr *w);

int wifimngr_reconfig(struct wifimngr *w);

void wifimngr_version(void);

/* uci functions */
int uci_add_wifi_iface(char **argv);
int uci_del_wifi_iface(char *ifname);
int uci_get_wifi_devices(struct wifimngr *w, const char *conffile);
int uci_get_wifi_interfaces(struct wifimngr *w, const char *conffile);
int uci_get_wifi_mlds(struct wifimngr *w, const char *conffile);


extern int wifimngr_nl_msgs_handler(struct ubus_context *ctx);

//void wifimngr_event_init(void);
void wifimngr_event_exit(struct wifimngr *w);

int wifimngr_events_register(struct wifimngr *w, const char *ifname,
			     const char *family, const char *group);

int wifimngr_event_register(struct wifimngr *w, const char *ifname,
			    const char *family, const char *group);

void wifimngr_event_unregister(struct wifimngr *w, const char *ifname);

void wifimngr_del_object(struct wifimngr *w, struct ubus_object *obj, bool remove_from_ubus);

struct wifimngr_device *wifimngr_lookup_wifi_device(struct wifimngr *w,
						    const char *device);

struct wifimngr_iface *wifimngr_lookup_wifi_iface(struct wifimngr *w,
						    const char *iface);

#ifdef WIFI_CACHE_SCANRESULTS
int wifimngr_get_initial_scanresults(struct wifimngr *w);
int wifimngr_update_scanresults_cache(struct wifimngr_device *wdev, int sz, char *evbuf);
void wifimngr_flush_scanresults(struct wifimngr *w);
#endif

//TODO: deprecate
int find_phy_from_device_path(char *path, char *phy, size_t size);
bool phy_dir_exist(char *phy);


int wl_radio_help(struct ubus_context *ctx, struct ubus_object *obj,
		  struct ubus_request_data *req, const char *method,
		  struct blob_attr *msg);

int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_radio_stats(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_scan(struct ubus_context *ctx, struct ubus_object *obj,
		  struct ubus_request_data *req, const char *method,
		  struct blob_attr *msg);

int wl_scan_ex(struct ubus_context *ctx, struct ubus_object *obj,
		  struct ubus_request_data *req, const char *method,
		  struct blob_attr *msg);

int wl_scanresults(struct ubus_context *ctx, struct ubus_object *obj,
		  struct ubus_request_data *req, const char *method,
		  struct blob_attr *msg);

int wl_autochannel(struct ubus_context *ctx, struct ubus_object *obj,
		   struct ubus_request_data *req, const char *method,
		   struct blob_attr *msg);

int wl_start_cac(struct ubus_context *ctx, struct ubus_object *obj,
		 struct ubus_request_data *req, const char *method,
		 struct blob_attr *msg);

int wl_stop_cac(struct ubus_context *ctx, struct ubus_object *obj,
		 struct ubus_request_data *req, const char *method,
		 struct blob_attr *msg);

int wl_simulate_radar(struct ubus_context *ctx, struct ubus_object *obj,
		     struct ubus_request_data *req, const char *method,
		     struct blob_attr *msg);

int wl_add_iface(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_del_iface(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_channels_info(struct ubus_context *ctx, struct ubus_object *obj,
		     struct ubus_request_data *req, const char *method,
		     struct blob_attr *msg);

int wl_channels(struct ubus_context *ctx, struct ubus_object *obj,
		 struct ubus_request_data *req, const char *method,
		 struct blob_attr *msg);

int wl_opclass_preferences(struct ubus_context *ctx, struct ubus_object *obj,
			   struct ubus_request_data *req, const char *method,
			   struct blob_attr *msg);

int wl_radio_get_param(struct ubus_context *ctx, struct ubus_object *obj,
		  struct ubus_request_data *req, const char *method,
		  struct blob_attr *msg);




int wl_ap_dump_beacon(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int wl_apmld_dump_beacon(struct ubus_context *ctx, struct ubus_object *obj,
			 struct ubus_request_data *req, const char *method,
			 struct blob_attr *msg);

int wl_ap_help(struct ubus_context *ctx, struct ubus_object *obj,
	       struct ubus_request_data *req, const char *method,
	       struct blob_attr *msg);

int wl_ap_status(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_ap_stats(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_assoclist(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_wifi_assoclist(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int wl_block_sta(struct ubus_context *ctx, struct ubus_object *obj,
		 struct ubus_request_data *req, const char *method,
		 struct blob_attr *msg);

int wl_apmld_block_sta(struct ubus_context *ctx, struct ubus_object *obj,
		       struct ubus_request_data *req, const char *method,
		       struct blob_attr *msg);

int wl_blocked_stas(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int wl_apmld_blocked_stas(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int ap_chan_switch(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int wl_stations(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_sta_ratings(struct ubus_context *ctx, struct ubus_object *obj,
		   struct ubus_request_data *req, const char *method,
		   struct blob_attr *msg);

int wl_apmld_sta_ratings(struct ubus_context *ctx, struct ubus_object *obj,
			 struct ubus_request_data *req, const char *method,
			 struct blob_attr *msg);

int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int sta_probe(struct ubus_context *ctx, struct ubus_object *obj,
	      struct ubus_request_data *req, const char *method,
	      struct blob_attr *msg);

int sta_monitor_add(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int sta_monitor_del(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int sta_monitor_get(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int subscribe_frame(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int unsubscribe_frame(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int ap_measure_link(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int ap_mbo_disallow_assoc(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int ap_bss_up(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int ap_bss_down(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int ap_send_action(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);


int wl_sta_dpp_listen(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int wl_sta_dpp_stop_listen(struct ubus_context *ctx, struct ubus_object *obj,
			  struct ubus_request_data *req, const char *method,
			  struct blob_attr *msg);

int set_qos_map(struct ubus_context *ctx, struct ubus_object *obj,
                struct ubus_request_data *req, const char *method,
                struct blob_attr *msg);

int send_qos_map_conf(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);


int nbr_add(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int nbr_del(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int nbr_list(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int nbr_request(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int btm_request(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int assoc_control(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int vsie_add(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *ureq, const char *method,
		      struct blob_attr *msg);

int vsie_del(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *ureq, const char *method,
		      struct blob_attr *msg);

int wl_sta_status(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_sta_stats(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_sta_disconnect_ap(struct ubus_context *ctx, struct ubus_object *obj,
			 struct ubus_request_data *req, const char *method,
			 struct blob_attr *msg);

int wl_sta_4addr(struct ubus_context *ctx, struct ubus_object *obj,
		 struct ubus_request_data *req, const char *method,
		 struct blob_attr *msg);

int wl_status(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_help_command(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg, const char *command);

int wl_help(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wl_wps_help(struct ubus_context *ctx, struct ubus_object *obj,
		struct ubus_request_data *req, const char *method,
		struct blob_attr *msg);

int wifi_set_debug(struct ubus_context *ctx, struct ubus_object *obj,
			struct ubus_request_data *req, const char *method,
			struct blob_attr *msg);

int wl_apmld_help(struct ubus_context *ctx, struct ubus_object *obj,
		  struct ubus_request_data *req, const char *method,
		  struct blob_attr *msg);

int wl_apmld_status(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int wl_apmld_stats(struct ubus_context *ctx, struct ubus_object *obj,
		   struct ubus_request_data *req, const char *method,
		   struct blob_attr *msg);

int wl_apmld_assoclist(struct ubus_context *ctx, struct ubus_object *obj,
		       struct ubus_request_data *req, const char *method,
		       struct blob_attr *msg);

int wl_apmld_stations(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg);

int wl_apmld_disconnect_sta(struct ubus_context *ctx, struct ubus_object *obj,
			    struct ubus_request_data *req, const char *method,
			    struct blob_attr *msg);

int wl_mldsta_status(struct ubus_context *ctx, struct ubus_object *obj,
		     struct ubus_request_data *req, const char *method,
		     struct blob_attr *msg);

int wl_mldsta_stats(struct ubus_context *ctx, struct ubus_object *obj,
		    struct ubus_request_data *req, const char *method,
		    struct blob_attr *msg);

int wl_mldsta_disconnect_ap(struct ubus_context *ctx, struct ubus_object *obj,
			    struct ubus_request_data *req, const char *method,
			    struct blob_attr *msg);


#ifndef blobmsg_add_macaddr
#define blobmsg_add_macaddr(b, f, v)	\
do {					\
	char _vstr[18] = {0};		\
	hwaddr_ntoa((v), _vstr);	\
	blobmsg_add_string(b, f, _vstr);\
} while (0)
#endif

#endif /* WIFIMNGR_H */
