[rdkb][common][bsp][Add hostapd ucode support]

[Description]
Add hostapd ucode support for wifi7

[Release-log]

Change-Id: Ic4c3cca4a36a11fc3f9f9fdc94842b66a00721bf
diff --git a/recipes-wifi/hostapd/files/common.uc b/recipes-wifi/hostapd/files/common.uc
index 9ece3b1..ccffe3e 100644
--- a/recipes-wifi/hostapd/files/common.uc
+++ b/recipes-wifi/hostapd/files/common.uc
@@ -1,6 +1,6 @@
 import * as nl80211 from "nl80211";
 import * as rtnl from "rtnl";
-import { readfile } from "fs";
+import { readfile, glob, basename, readlink } from "fs";
 
 const iftypes = {
 	ap: nl80211.const.NL80211_IFTYPE_AP,
@@ -94,6 +94,156 @@
 	return null;
 }
 
+function phy_sysfs_file(phy, name)
+{
+	return trim(readfile(`/sys/class/ieee80211/${phy}/${name}`));
+}
+
+function macaddr_split(str)
+{
+	return map(split(str, ":"), (val) => hex(val));
+}
+
+function macaddr_join(addr)
+{
+	return join(":", map(addr, (val) => sprintf("%02x", val)));
+}
+
+function wdev_macaddr(wdev)
+{
+	return trim(readfile(`/sys/class/net/${wdev}/address`));
+}
+
+const phy_proto = {
+	macaddr_init: function(used, options) {
+		this.macaddr_options = options ?? {};
+		this.macaddr_list = {};
+
+		if (type(used) == "object")
+			for (let addr in used)
+				this.macaddr_list[addr] = used[addr];
+		else
+			for (let addr in used)
+				this.macaddr_list[addr] = -1;
+
+		this.for_each_wdev((wdev) => {
+			let macaddr = wdev_macaddr(wdev);
+			this.macaddr_list[macaddr] ??= -1;
+		});
+
+		return this.macaddr_list;
+	},
+
+	macaddr_generate: function(data) {
+		let phy = this.name;
+		let idx = int(data.id ?? 0);
+		let mbssid = int(data.mbssid ?? 0) > 0;
+		let num_global = int(data.num_global ?? 1);
+		let use_global = !mbssid && idx < num_global;
+
+		let base_addr = phy_sysfs_file(phy, "macaddress");
+		if (!base_addr)
+			return null;
+
+		if (!idx && !mbssid)
+			return base_addr;
+
+		let base_mask = phy_sysfs_file(phy, "address_mask");
+		if (!base_mask)
+			return null;
+
+		if (base_mask == "00:00:00:00:00:00" && idx >= num_global) {
+			let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
+
+			if (idx < length(addrs))
+				return addrs[idx];
+
+			base_mask = "ff:ff:ff:ff:ff:ff";
+		}
+
+		let addr = macaddr_split(base_addr);
+		let mask = macaddr_split(base_mask);
+		let type;
+
+		if (mbssid)
+			type = "b5";
+		else if (use_global)
+			type = "add";
+		else if (mask[0] > 0)
+			type = "b1";
+		else if (mask[5] < 0xff)
+			type = "b5";
+		else
+			type = "add";
+
+		switch (type) {
+		case "b1":
+			if (!(addr[0] & 2))
+				idx--;
+			addr[0] |= 2;
+			addr[0] ^= idx << 2;
+			break;
+		case "b5":
+			if (mbssid)
+				addr[0] |= 2;
+			addr[5] ^= idx;
+			break;
+		default:
+			for (let i = 5; i > 0; i--) {
+				addr[i] += idx;
+				if (addr[i] < 256)
+					break;
+				addr[i] %= 256;
+			}
+			break;
+		}
+
+		return macaddr_join(addr);
+	},
+
+	macaddr_next: function(val) {
+		let data = this.macaddr_options ?? {};
+		let list = this.macaddr_list;
+
+		for (let i = 0; i < 32; i++) {
+			data.id = i;
+
+			let mac = this.macaddr_generate(data);
+			if (!mac)
+				return null;
+
+			if (list[mac] != null)
+				continue;
+
+			list[mac] = val != null ? val : -1;
+			return mac;
+		}
+	},
+
+	for_each_wdev: function(cb) {
+		let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`);
+		wdevs = map(wdevs, (arg) => basename(arg));
+		for (let wdev in wdevs) {
+			if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name)
+				continue;
+
+			cb(wdev);
+		}
+	}
+};
+
+function phy_open(phy)
+{
+	let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
+	if (!phyidx)
+		return null;
+
+	return proto({
+		name: phy,
+		idx: int(phyidx)
+	}, phy_proto);
+}
+
 const vlist_proto = {
 	update: function(values, arg) {
 		let data = this.data;
@@ -150,7 +300,7 @@
 			if (!is_equal(val1[key], val2[key]))
 				return false;
 		for (let key in val2)
-			if (!val1[key])
+			if (val1[key] == null)
 				return false;
 		return true;
 	} else {
@@ -165,4 +315,4 @@
 		}, vlist_proto);
 }
 
-export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac };
+export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac, phy_open };