mirror of
https://github.com/shenmintao/aic8800d80.git
synced 2026-09-27 01:54:16 +00:00
602 lines
15 KiB
C
602 lines
15 KiB
C
/**
|
|
******************************************************************************
|
|
*
|
|
* Copyright (C) 2020 AIC semiconductor.
|
|
*
|
|
* @file aicwf_manager.c
|
|
*
|
|
* @brief netlink msg definitions
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/netlink.h>
|
|
#include <net/sock.h>
|
|
#include "aicwf_manager.h"
|
|
#include "lmac_mac.h"
|
|
#include "aicwf_debug.h"
|
|
|
|
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
|
|
#define MAC_ARG(x) ((u8_l *)(x))[0], ((u8_l *)(x))[1], ((u8_l *)(x))[2], ((u8_l *)(x))[3], ((u8_l *)(x))[4], ((u8_l *)(x))[5]
|
|
#define MANAGER_STR "[MANAGER] USB "
|
|
|
|
|
|
static struct sock *nl_sock = NULL;
|
|
|
|
static struct rwnx_vif *nl_rwnx_vif[PHY_BAND_MAX][CONFIG_IFACE_NUMBER] = {{NULL}};
|
|
static u8_l nl_hook[PHY_BAND_MAX][CONFIG_IFACE_NUMBER] = {{0}};
|
|
|
|
static u8_l nl_daemon_on = 0;
|
|
|
|
#define FREQ_2G_MIN 2412
|
|
#define FREQ_2G_MAX 2484
|
|
#define FREQ_5G_MIN 5170
|
|
#define FREQ_5G_MAX 5825
|
|
#define FREQ_6G_MIN 5925
|
|
#define FREQ_6G_MAX 7125
|
|
|
|
static int freq_to_channel(int freq)
|
|
{
|
|
if (freq >= FREQ_2G_MIN && freq <= FREQ_2G_MAX) {
|
|
if (freq == 2484) {
|
|
return 14;
|
|
} else {
|
|
return (freq - 2412) / 5 + 1;
|
|
}
|
|
} else if (freq >= FREQ_5G_MIN && freq <= FREQ_5G_MAX) {
|
|
return (freq - 5000) / 5;
|
|
} else if (freq >= FREQ_6G_MIN && freq <= FREQ_6G_MAX) {
|
|
return (freq - 5950) / 5;
|
|
} else {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"aic Unsupported frequency: %d MHz\n", freq);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
void aicwf_nl_recv_msg(struct sk_buff *skb)
|
|
{
|
|
struct rwnx_vif *rwnx_vif;
|
|
struct rwnx_sta *sta = NULL;
|
|
u8_l rwnx_hook = 0;
|
|
u8_l band;
|
|
u8_l ssid;
|
|
struct nlmsghdr *nlh = NULL;
|
|
struct b_nl_message *msg = NULL;
|
|
struct b_elm_header *hdr = NULL;
|
|
struct b_elm_intf *intf = NULL;
|
|
struct b_elm_sta_info *sta_info = NULL;
|
|
struct b_elm_roam_info *roam_info = NULL;
|
|
u32 offset = 0;
|
|
|
|
if (skb == NULL) {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"skb is null.\n");
|
|
return;
|
|
}
|
|
|
|
nlh = (struct nlmsghdr *)skb->data;
|
|
msg = (struct b_nl_message *)NLMSG_DATA(nlh);
|
|
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s, %d\n", __func__, msg->type);
|
|
|
|
/* message type */
|
|
switch(msg->type) {
|
|
case AIC_NL_DAEMON_ON_TYPE:
|
|
nl_daemon_on = 1;
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"AIC_NL_DAEMON_ON_TYPE\n");
|
|
for (band = 0; band < PHY_BAND_MAX; band++) {
|
|
for (ssid = 0; ssid < CONFIG_IFACE_NUMBER; ssid++) {
|
|
rwnx_vif = nl_rwnx_vif[band][ssid];
|
|
rwnx_hook = nl_hook[band][ssid];
|
|
|
|
if (!rwnx_hook) {
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s, !rwnx_hook, %d,%d\n", __func__, band, ssid);
|
|
continue;
|
|
}
|
|
if (rwnx_vif == NULL || rwnx_vif->up == false) {
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s, !rwnx_vif, %d,%d\n", __func__, band, ssid);
|
|
continue;
|
|
}
|
|
|
|
#ifdef CONFIG_BAND_STEERING
|
|
aicwf_band_steering_init(rwnx_vif);
|
|
#endif
|
|
|
|
spin_lock_bh(&rwnx_vif->rwnx_hw->cb_lock);
|
|
list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list){
|
|
if (sta->valid)
|
|
aicwf_nl_send_new_sta_msg(rwnx_vif, sta->mac_addr);
|
|
}
|
|
spin_unlock_bh(&rwnx_vif->rwnx_hw->cb_lock);
|
|
}
|
|
}
|
|
break;
|
|
case AIC_NL_DAEMON_OFF_TYPE:
|
|
nl_daemon_on = 0;
|
|
break;
|
|
#ifdef CONFIG_BAND_STEERING
|
|
case AIC_NL_B_STEER_BLOCK_ADD_TYPE:
|
|
case AIC_NL_B_STEER_BLOCK_DEL_TYPE:
|
|
while (offset < msg->len) {
|
|
hdr = (struct b_elm_header *)(msg->content + offset);
|
|
offset += ELM_HEADER_LEN;
|
|
|
|
switch(hdr->id) {
|
|
case AIC_ELM_INTF_ID:
|
|
intf = (struct b_elm_intf *)(msg->content + offset);
|
|
break;
|
|
case AIC_ELM_STA_INFO_ID:
|
|
sta_info = (struct b_elm_sta_info *)(msg->content + offset);
|
|
break;
|
|
default:
|
|
AICWFDBG(LOGERROR, MANAGER_STR"unknown element id.\n");
|
|
break;
|
|
}
|
|
offset += hdr->len;
|
|
}
|
|
|
|
if (intf && sta_info) {
|
|
band = intf->band;
|
|
ssid = intf->ssid;
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"STEER_BLOCK band: %d, ssid: %d\n", band, ssid);
|
|
rwnx_vif = nl_rwnx_vif[band][ssid];
|
|
rwnx_hook = nl_hook[band][ssid];
|
|
|
|
if (!rwnx_hook) {
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"rwnx_hook is null p1.\n");
|
|
break;
|
|
}
|
|
if (rwnx_vif == NULL || rwnx_vif->up == false) {
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"rwnx_vif is null/down p1.\n");
|
|
break;
|
|
}
|
|
|
|
if (msg->type == AIC_NL_B_STEER_BLOCK_ADD_TYPE)
|
|
aicwf_band_steering_block_entry_add(rwnx_vif, sta_info->mac);
|
|
else if (msg->type == AIC_NL_B_STEER_BLOCK_DEL_TYPE)
|
|
aicwf_band_steering_block_entry_del(rwnx_vif, sta_info->mac);
|
|
}
|
|
break;
|
|
case AIC_NL_B_STEER_ROAM_TYPE:
|
|
while (offset < msg->len) {
|
|
hdr = (struct b_elm_header *)(msg->content + offset);
|
|
offset += ELM_HEADER_LEN;
|
|
|
|
/* element type: should handle wrong length */
|
|
switch(hdr->id) {
|
|
case AIC_ELM_INTF_ID:
|
|
intf = (struct b_elm_intf *)(msg->content + offset);
|
|
break;
|
|
case AIC_ELM_ROAM_INFO_ID:
|
|
roam_info = (struct b_elm_roam_info *)(msg->content + offset);
|
|
break;
|
|
default:
|
|
AICWFDBG(LOGERROR, MANAGER_STR"unknown element id.\n");
|
|
break;
|
|
}
|
|
offset += hdr->len;
|
|
}
|
|
|
|
if (intf && roam_info) {
|
|
band = intf->band;
|
|
ssid = intf->ssid;
|
|
rwnx_vif = nl_rwnx_vif[band][ssid];
|
|
rwnx_hook = nl_hook[band][ssid];
|
|
|
|
if (!rwnx_hook) {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"rwnx_hook is null p2.\n");
|
|
break;
|
|
}
|
|
if (rwnx_vif == NULL || rwnx_vif->up == false) {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"rwnx_vif is null/down p2.\n");
|
|
break;
|
|
}
|
|
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"AIC_NL_B_STEER_ROAM_TYPE (hostapd_cli)!\n");
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"sta_mac="MAC_FMT"\n", MAC_ARG(roam_info->sta_mac));
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"bss_mac="MAC_FMT" bss_ch=%u method=%s\n",
|
|
MAC_ARG(roam_info->bss_mac),
|
|
roam_info->bss_ch,
|
|
roam_info->method == 0 ? "11V" : "Deauth");
|
|
|
|
if (roam_info->method == 1)
|
|
aicwf_band_steering_roam_block_entry_add(rwnx_vif, roam_info->sta_mac);
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
AICWFDBG(LOGERROR, MANAGER_STR"unknown message type.\n");
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_msg(void *msg, u32 msg_len)
|
|
{
|
|
struct nlmsghdr *nlh = NULL;
|
|
struct sk_buff *skb = NULL;
|
|
u32 skb_len;
|
|
s32 err;
|
|
|
|
skb_len = NLMSG_SPACE(NL_MAX_MSG_SIZE);
|
|
skb = __dev_alloc_skb(skb_len, GFP_ATOMIC);
|
|
if (!skb) {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"allocate skb failed.\n");
|
|
goto func_return;
|
|
}
|
|
|
|
nlh = nlmsg_put(skb, 0, 0, 0, NL_MAX_MSG_SIZE, 0);
|
|
if (!nlh) {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"put netlink header failed.\n");
|
|
kfree_skb(skb);
|
|
goto func_return;
|
|
}
|
|
|
|
NETLINK_CB(skb).portid = 0;
|
|
NETLINK_CB(skb).dst_group = 0;
|
|
memset(NLMSG_DATA(nlh), 0, msg_len);
|
|
memcpy(NLMSG_DATA(nlh), (u8_l *)msg, msg_len);
|
|
|
|
if (!nl_sock) {
|
|
AICWFDBG(LOGERROR, MANAGER_STR"[%s %u] nl_sock is NULL\n", __FUNCTION__, __LINE__);
|
|
goto msg_fail_skb;
|
|
}
|
|
|
|
err = netlink_unicast(nl_sock, skb, NL_AIC_MANAGER_PID, MSG_DONTWAIT);
|
|
|
|
if (err < 0) {
|
|
/* netlink_unicast() already kfree_skb */
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"send netlink unicast failed.\n");
|
|
goto func_return;
|
|
}
|
|
|
|
func_return:
|
|
return;
|
|
|
|
msg_fail_skb:
|
|
kfree_skb(skb);
|
|
}
|
|
|
|
static void aicwf_netlink_set_msg(
|
|
struct b_nl_message *msg, u32 *msg_len, void *elm, u32 elm_len)
|
|
{
|
|
memcpy(msg->content + (*msg_len), elm, elm_len);
|
|
(*msg_len) += elm_len;
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_del_sta_msg(struct rwnx_vif *rwnx_vif, u8_l *mac)
|
|
{
|
|
u32 msg_len = 0;
|
|
struct b_nl_message msg = {0};
|
|
struct b_elm_header hdr = {0};
|
|
struct b_elm_intf intf = {{0}};
|
|
struct b_elm_sta_info sta_info = {{0}};
|
|
|
|
if (!nl_daemon_on)
|
|
return;
|
|
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s, "MAC_FMT"\n", __func__, MAC_ARG(mac));
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_ID;
|
|
hdr.len = ELM_INTF_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_ID */
|
|
intf.root = 0; /* TBD */
|
|
intf.band = rwnx_vif->ap.band;
|
|
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_STA_INFO_ID;
|
|
hdr.len = ELM_STA_INFO_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_STA_INFO_ID */
|
|
memcpy(sta_info.mac, mac, 6);
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info, ELM_STA_INFO_LEN);
|
|
|
|
/* finish message */
|
|
msg.type = AIC_NL_DEL_STA_TYPE;
|
|
msg.len = msg_len;
|
|
|
|
/* length += (type + len) */
|
|
msg_len += 8;
|
|
aicwf_nl_send_msg((void *)&msg, msg_len);
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_new_sta_msg(struct rwnx_vif *rwnx_vif, u8_l *mac)
|
|
{
|
|
u32 msg_len = 0;
|
|
struct b_nl_message msg = {0};
|
|
struct b_elm_header hdr = {0};
|
|
struct b_elm_intf intf = {{0}};
|
|
struct b_elm_sta_info sta_info = {{0}};
|
|
|
|
if (!nl_daemon_on)
|
|
return;
|
|
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s, "MAC_FMT"\n", __func__, MAC_ARG(mac));
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_ID;
|
|
hdr.len = ELM_INTF_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_ID */
|
|
intf.root = 0; /* TBD */
|
|
intf.band = rwnx_vif->ap.band;
|
|
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_STA_INFO_ID;
|
|
hdr.len = ELM_STA_INFO_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_STA_INFO_ID */
|
|
memcpy(sta_info.mac, mac, 6);
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info, ELM_STA_INFO_LEN);
|
|
|
|
/* finish message */
|
|
msg.type = AIC_NL_NEW_STA_TYPE;
|
|
msg.len = msg_len;
|
|
|
|
/* length += (type + len) */
|
|
msg_len += 8;
|
|
aicwf_nl_send_msg((void *)&msg, msg_len);
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_intf_rpt_msg(struct rwnx_vif *rwnx_vif)
|
|
{
|
|
u32 msg_len = 0;
|
|
struct b_nl_message msg = {0};
|
|
struct b_elm_header hdr = {0};
|
|
struct b_elm_intf intf = {{0}};
|
|
struct b_elm_intf_info intf_info = {0};
|
|
|
|
if (!nl_daemon_on)
|
|
return;
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_ID;
|
|
hdr.len = ELM_INTF_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_ID */
|
|
memcpy(intf.mac, rwnx_vif->ndev->dev_addr, 6);
|
|
intf.root = 0; /* TBD */
|
|
intf.band = rwnx_vif->ap.band;
|
|
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
|
|
memcpy(intf.name, rwnx_vif->ndev->name, 16);
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_INFO_ID;
|
|
hdr.len = ELM_INTF_INFO_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_INFO_ID */
|
|
intf_info.ch = freq_to_channel(rwnx_vif->ap.freq);
|
|
intf_info.tx_tp = 0; /* TBD */
|
|
intf_info.rx_tp = 0; /* TBD */
|
|
|
|
intf_info.bss_info = 0;
|
|
intf_info.reg_class = (rwnx_vif->ap.band == 0) ? 81 : 128;
|
|
intf_info.phy_type = 7;
|
|
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf_info, ELM_INTF_INFO_LEN);
|
|
|
|
/* finish message */
|
|
msg.type = AIC_NL_INTF_RPT_TYPE;
|
|
msg.len = msg_len;
|
|
|
|
/* length += (type + len) */
|
|
msg_len += 8;
|
|
aicwf_nl_send_msg((void *)&msg, msg_len);
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_sta_rpt_msg(struct rwnx_vif *rwnx_vif, struct rwnx_sta *sta)
|
|
{
|
|
u32 msg_len = 0;
|
|
struct b_nl_message msg = {0};
|
|
struct b_elm_header hdr = {0};
|
|
struct b_elm_intf intf = {{0}};
|
|
struct b_elm_sta_info sta_info = {{0}};
|
|
struct b_elm_sta_info_ext sta_info_ext = {{0}};
|
|
|
|
if (!nl_daemon_on)
|
|
return;
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_ID;
|
|
hdr.len = ELM_INTF_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_ID */
|
|
memcpy(intf.mac, rwnx_vif->ndev->dev_addr, 6);
|
|
intf.root = 0; /* TBD */
|
|
intf.band = rwnx_vif->ap.band;
|
|
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
|
|
memcpy(intf.name, rwnx_vif->ndev->name, 16);
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_STA_INFO_ID;
|
|
hdr.len = ELM_STA_INFO_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_STA_INFO_ID */
|
|
memcpy(sta_info.mac, sta->mac_addr, 6);
|
|
sta_info.rssi = sta->rssi;
|
|
sta_info.link_time = sta->link_time;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info, ELM_STA_INFO_LEN);
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_STA_INFO_EXT_ID;
|
|
hdr.len = ELM_STA_INFO_EXT_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_STA_INFO_EXT_ID */
|
|
memcpy(sta_info_ext.mac, sta->mac_addr, 6);
|
|
sta_info_ext.supported_band = sta->support_band;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&sta_info_ext, ELM_STA_INFO_EXT_LEN);
|
|
|
|
/* finish message */
|
|
msg.type = AIC_NL_STA_RPT_TYPE;
|
|
msg.len = msg_len;
|
|
|
|
/* length += (type + len) */
|
|
msg_len += 8;
|
|
aicwf_nl_send_msg((void *)&msg, msg_len);
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_frame_rpt_msg(struct rwnx_vif *rwnx_vif, u16_l frame_type, u8_l *sa, s8_l rssi)
|
|
{
|
|
u32 msg_len = 0;
|
|
struct b_nl_message msg = {0};
|
|
struct b_elm_header hdr = {0};
|
|
struct b_elm_frame_info frame_info = {0};
|
|
struct b_elm_intf intf = {{0}};
|
|
|
|
if (!nl_daemon_on)
|
|
return;
|
|
|
|
//AICWFDBG(LOGSTEER, "[NETLINK] %s, sta: "MAC_FMT"\n", __func__, MAC_ARG(sa));
|
|
|
|
/* TBD */
|
|
if (frame_type == WIFI_PROBEREQ && rssi <= LOW_RSSI_IGNORE) {
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"WIFI_PROBEREQ <= %d, ignore\n", LOW_RSSI_IGNORE);
|
|
return;
|
|
}
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_ID;
|
|
hdr.len = ELM_INTF_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_ID */
|
|
intf.root = 0; /* TBD */
|
|
intf.band = rwnx_vif->ap.band;
|
|
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_FRAME_INFO_ID;
|
|
hdr.len = ELM_FRAME_INFO_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_FRAME_INFO_ID */
|
|
frame_info.frame_type = frame_type;
|
|
memcpy(frame_info.sa, sa, 6);
|
|
frame_info.rssi = rssi;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&frame_info, ELM_FRAME_INFO_LEN);
|
|
|
|
/* finish message */
|
|
msg.type = AIC_NL_FRAME_RPT_TYPE;
|
|
msg.len = msg_len;
|
|
|
|
/* length += (type + len) */
|
|
msg_len += 8;
|
|
aicwf_nl_send_msg((void *)&msg, msg_len);
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_send_time_tick_msg(struct rwnx_vif *rwnx_vif)
|
|
{
|
|
u32 msg_len = 0;
|
|
struct b_nl_message msg = {0};
|
|
struct b_elm_header hdr = {0};
|
|
struct b_elm_intf intf = {{0}};
|
|
|
|
if (!nl_daemon_on)
|
|
return;
|
|
|
|
/* element header */
|
|
hdr.id = AIC_ELM_INTF_ID;
|
|
hdr.len = ELM_INTF_LEN;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&hdr, ELM_HEADER_LEN);
|
|
|
|
/* element: AIC_ELM_INTF_ID */
|
|
intf.root = 0; /* TBD */
|
|
intf.band = rwnx_vif->ap.band;
|
|
intf.ssid = rwnx_vif->rwnx_hw->iface_idx;
|
|
aicwf_netlink_set_msg(&msg, &msg_len, (void *)&intf, ELM_INTF_LEN);
|
|
|
|
/* finish message */
|
|
msg.type = AIC_NL_TIME_TICK_TYPE;
|
|
msg.len = msg_len;
|
|
|
|
/* length += (type + len) */
|
|
msg_len += 8;
|
|
aicwf_nl_send_msg((void *)&msg, msg_len);
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_hook(struct rwnx_vif *rwnx_vif, u8_l band, u8_l ssid)
|
|
{
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s band:%d, ssid:%d\n", __func__, band, ssid);
|
|
|
|
nl_hook[band][ssid] = 1;
|
|
nl_rwnx_vif[band][ssid] = rwnx_vif;
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_hook_deinit(u8_l band, u8_l ssid)
|
|
{
|
|
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"%s band:%d, ssid:%d\n", __func__, band, ssid);
|
|
|
|
nl_hook[band][ssid] = 0;
|
|
nl_rwnx_vif[band][ssid] = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void aicwf_nl_init(void)
|
|
{
|
|
if (nl_sock) {
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"netlink already init.\n");
|
|
return;
|
|
}
|
|
struct netlink_kernel_cfg cfg = {
|
|
.input = aicwf_nl_recv_msg,
|
|
};
|
|
|
|
nl_sock = netlink_kernel_create(&init_net, NL_AIC_PROTOCOL, &cfg);
|
|
if (!nl_sock)
|
|
AICWFDBG(LOGERROR, MANAGER_STR"create netlink falied.\n");
|
|
|
|
return;
|
|
}
|
|
|
|
void aicwf_nl_deinit(void)
|
|
{
|
|
if(nl_sock)
|
|
{
|
|
netlink_kernel_release(nl_sock);
|
|
nl_sock = NULL;
|
|
}
|
|
AICWFDBG(LOGSTEER, MANAGER_STR"[aicwf_nl_deinit] delete nl_sock netlink succeed.\n");
|
|
|
|
return;
|
|
}
|
|
|