1 /** @file mlan_mbo.c
2  *
3  *  @brief  This file provides functions for process MBO feature
4  *
5  *  Copyright 2022-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 /********************************************************
12 Change log:
13     8/SEP/2022: initial version
14 ********************************************************/
15 
16 #include <mlan_api.h>
17 #include "mlan_mbo.h"
18 
19 #if CONFIG_DRIVER_MBO
20 #define WNM_NOTIFICATION_SIZE 200U
21 /********************************************************
22                 Local Variables
23 ********************************************************/
24 
25 /********************************************************
26                 Global Variables
27 ********************************************************/
28 const t_u8 mbo_oui[3]             = {0x50, 0x6f, 0x9a};
29 static const t_u8 mbo_oui_type[1] = {0x16};
30 /* MBO ATTR ID NON PREF CHAN REPORT */
31 static const t_u8 mbo_attr_id[1] = {0x2};
32 /********************************************************
33                 Local Functions
34 ********************************************************/
35 /** Dialog Token */
36 static t_u8 mbo_dialog_token = 0;
37 /********************************************************
38                 Global functions
39 ********************************************************/
40 
41 /**
42  * @brief This function add MBO OUI.
43  *
44  * @param oui A pointer to MBO OCE element structure
45  *
46  * @return pointer incremented to the end of the element
47  */
wlan_add_mbo_oui(t_u8 * oui)48 t_u8 *wlan_add_mbo_oui(t_u8 *oui)
49 {
50     (void)memcpy(oui, mbo_oui, sizeof(mbo_oui));
51     return (oui + sizeof(mbo_oui));
52 }
53 
54 /**
55  * @brief This function add MBO OUI TYPE.
56  *
57  * @param oui A pointer to MBO OCE element structure
58  *
59  * @return void
60  */
wlan_add_mbo_oui_type(t_u8 * oui_type)61 t_u8 *wlan_add_mbo_oui_type(t_u8 *oui_type)
62 {
63     (void)memcpy(oui_type, mbo_oui_type, sizeof(mbo_oui_type));
64     return (oui_type + sizeof(mbo_oui_type));
65 }
66 
67 /**
68  * @brief This function add MBO Attributes id.
69  *
70  * @param oui A pointer to MBO OCE element structure
71  *
72  * @return void
73  */
wlan_add_mbo_attr_id(t_u8 * attr_id)74 t_u8 *wlan_add_mbo_attr_id(t_u8 *attr_id)
75 {
76     (void)memcpy(attr_id, mbo_attr_id, sizeof(mbo_attr_id));
77     return (attr_id + sizeof(mbo_attr_id));
78 }
79 
80 /**
81  * @brief This function add cellular data CAP attribute into MBO OCE IE.
82  *
83  * @param oui A pointer to MBO OCE element structure
84  *
85  * @return void
86  */
wlan_add_mbo_cellular_cap(t_u8 * attrib)87 t_u8 *wlan_add_mbo_cellular_cap(t_u8 *attrib)
88 {
89     attrib[0] = (t_u8)MBO_CELLULAR_DATA_CAP;
90     attrib[1] = 0x01;
91     attrib[2] = 0x03;
92     return (attrib + 3);
93 }
94 
95 /**
96  * @brief This function add prefer or non-prefer channels into MBO OCE IE.
97  *
98  * @param oui A pointer to MBO OCE element structure
99  *
100  * @return void
101  */
wlan_add_mbo_prefer_ch(t_u8 * attrib,t_u8 ch0,t_u8 pefer0,t_u8 ch1,t_u8 pefer1)102 t_u8 *wlan_add_mbo_prefer_ch(t_u8 *attrib, t_u8 ch0, t_u8 pefer0, t_u8 ch1, t_u8 pefer1)
103 {
104     t_u8 oper_class      = 0;
105     mlan_private *pmpriv = (mlan_private *)mlan_adap->priv[0];
106 
107     attrib[0] = (t_u8)MBO_NON_PERFER_CH_REPORT;
108     attrib[1] = 0x04;
109     (void)wlan_get_curr_global_oper_class(pmpriv, ch0, BW_20MHZ, &oper_class);
110     attrib[2] = oper_class; /*Wi-Fi CERTIFIED Agile Multiband. Test Plan v1.4 section 5.2.8. Set Global operating class
111                                to this field. */
112     attrib[3] = ch0;
113     attrib[4] = pefer0;
114     attrib[5] = 0;
115 
116     attrib[6] = (t_u8)MBO_NON_PERFER_CH_REPORT;
117     attrib[7] = 0x04;
118     (void)wlan_get_curr_global_oper_class(pmpriv, ch1, BW_20MHZ, &oper_class);
119     attrib[8]  = oper_class;
120     attrib[9]  = ch1;
121     attrib[10] = pefer1;
122     attrib[11] = 0;
123     return (attrib + 12);
124 }
125 
wlan_send_mgmt_wnm_notification(t_u8 * src_addr,t_u8 * dst_addr,t_u8 * target_bssid,t_u8 * tag_nr,t_u8 tag_len,bool protect)126 void wlan_send_mgmt_wnm_notification(
127     t_u8 *src_addr, t_u8 *dst_addr, t_u8 *target_bssid, t_u8 *tag_nr, t_u8 tag_len, bool protect)
128 {
129     wlan_mgmt_pkt *pmgmt_pkt_hdr    = MNULL;
130     IEEEtypes_FrameCtl_t *mgmt_fc_p = MNULL;
131     t_u8 *pos                       = MNULL;
132     t_u16 pkt_len                   = 0;
133     t_u32 meas_pkt_len              = 0;
134 
135     pmgmt_pkt_hdr = wifi_PrepDefaultMgtMsg(
136         SUBTYPE_ACTION, (mlan_802_11_mac_addr *)(void *)dst_addr, (mlan_802_11_mac_addr *)(void *)src_addr,
137         (mlan_802_11_mac_addr *)(void *)dst_addr, sizeof(wlan_mgmt_pkt) + WNM_NOTIFICATION_SIZE);
138     if (pmgmt_pkt_hdr == MNULL)
139     {
140         PRINTM(MERROR, "No memory available for BTM resp");
141         return;
142     }
143 
144     mgmt_fc_p = (IEEEtypes_FrameCtl_t *)(void *)&pmgmt_pkt_hdr->wlan_header.frm_ctl;
145     if (protect)
146     {
147         mgmt_fc_p->wep = 1;
148     }
149 
150     /* 802.11 management body */
151     pos    = (t_u8 *)pmgmt_pkt_hdr + sizeof(wlan_mgmt_pkt);
152     pos[0] = (t_u8)IEEE_MGMT_ACTION_CATEGORY_WNM;
153     pos[1] = (t_u8)IEEE_MGMT_WNM_NOTIFICATION_REQUEST;
154     pos[2] = mbo_dialog_token++;
155     pos[3] = 221; /* type */
156     pos += 4;
157     (void)memcpy(pos, tag_nr, tag_len);
158     pos += tag_len;
159 
160     meas_pkt_len           = sizeof(wlan_mgmt_pkt) + 4U + (t_u32)tag_len;
161     pkt_len                = (t_u16)meas_pkt_len;
162     pmgmt_pkt_hdr->frm_len = (t_u16)pkt_len - (t_u16)sizeof(t_u16);
163     (void)wifi_inject_frame(WLAN_BSS_TYPE_STA, (t_u8 *)pmgmt_pkt_hdr, pkt_len);
164 #if !CONFIG_MEM_POOLS
165     OSA_MemoryFree(pmgmt_pkt_hdr);
166 #else
167     OSA_MemoryPoolFree(buf_1536_MemoryPool, pmgmt_pkt_hdr);
168 #endif
169 }
170 
171 #endif /* CONFIG_DRIVER_MBO */
172