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