Revert "Use Android Go configurations"
[GitHub/mt8127/android_device_alcatel_ttab.git] / wpa_supplicant_8_lib / mediatek_driver_cmd_nl80211.c
CommitLineData
f3fa1980
S
1/*
2 * Driver interaction with extended Linux CFG8021
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * Alternatively, this software may be distributed under the terms of BSD
9 * license.
10 *
11 */
12#include "includes.h"
13#include <linux/wireless.h>
14#include "netlink/genl/genl.h"
15
16#include "common.h"
17#include "driver_nl80211.h"
18#include "linux_ioctl.h"
19#include "wpa_supplicant_i.h"
20#include "config.h"
21#ifdef ANDROID
22#include "android_drv.h"
23#endif
24
c481cf08 25#include "mediatek_driver_nl80211.h"
f3fa1980
S
26#include "driver_i.h"
27
c481cf08
JA
28#include "p2p/p2p_i.h"
29
f3fa1980 30#include "eloop.h"
c481cf08
JA
31#define PRIV_CMD_SIZE 512
32
33typedef struct android_wifi_priv_cmd {
34 char buf[PRIV_CMD_SIZE];
35 int used_len;
36 int total_len;
37} android_wifi_priv_cmd;
38
39static int drv_errors = 0;
40
41static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
42{
43 drv_errors++;
44 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
45 drv_errors = 0;
46 /* avoid the framework to handle HANGED */
47 /*
48 * wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
49 */
50 }
51}
52
53static int testmode_sta_statistics_handler(struct nl_msg *msg, void *arg)
54{
55 struct nlattr *tb[NL80211_ATTR_MAX + 1] = {};
56 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
57 struct nlattr *sinfo[NL80211_TESTMODE_STA_STATISTICS_NUM] = {};
58 struct wpa_driver_sta_statistics_s *sta_statistics = (struct wpa_driver_sta_statistics_s *)arg;
59 unsigned char i = 0;
60 static struct nla_policy policy[NL80211_TESTMODE_STA_STATISTICS_NUM] = {
61 [NL80211_TESTMODE_STA_STATISTICS_VERSION] = { .type = NLA_U8 },
62 [NL80211_TESTMODE_STA_STATISTICS_MAC] = { .type = NLA_UNSPEC },
63 [NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE] = { .type = NLA_U32 },
64 [NL80211_TESTMODE_STA_STATISTICS_FLAG] = { .type = NLA_U32 },
65 [NL80211_TESTMODE_STA_STATISTICS_PER] = { .type = NLA_U8 },
66 [NL80211_TESTMODE_STA_STATISTICS_RSSI] = { .type = NLA_U8 },
67 [NL80211_TESTMODE_STA_STATISTICS_PHY_MODE] = { .type = NLA_U32 },
68 [NL80211_TESTMODE_STA_STATISTICS_TX_RATE] = { .type = NLA_U16 },
69 [NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT] = { .type = NLA_U32 },
70 [NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT] = { .type = NLA_U32 },
71 [NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME] = { .type = NLA_U32 },
72 [NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT] = { .type = NLA_U32 },
73 [NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT] = { .type = NLA_U32 },
74
75 [NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME] = { .type = NLA_U32 },
76 [NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME] = { .type = NLA_U32 },
77 [NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME] = { .type = NLA_U32 },
78 [NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME] = { .type = NLA_U32 },
79
80 [NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY] = { .type = NLA_UNSPEC },
81 [NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC },
82 [NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC },
83 [NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC },
84 /*
85 * how many packages TX during statistics interval
86 */
87 [NL80211_TESTMODE_STA_STATISTICS_ENQUEUE] = { .type = NLA_U32 },
88 /*
89 * how many packages this sta TX during statistics interval
90 */
91 [NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE] = { .type = NLA_U32 },
92
93 /*
94 * how many packages dequeue during statistics interval
95 */
96 [NL80211_TESTMODE_STA_STATISTICS_DEQUEUE] = { .type = NLA_U32 },
97
98 /*
99 * how many packages this sta dequeue during statistics interval
100 */
101 [NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE] = { .type = NLA_U32 },
102
103 /*
104 * how many TC[0-3] resource back from firmware during
105 * statistics interval
106 */
107 [NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY] = { .type = NLA_UNSPEC },
108 [NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY] = { .type = NLA_UNSPEC },
109 [NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY] = { .type = NLA_UNSPEC },
110 [NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY] = { .type = NLA_UNSPEC },
111
112 [NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT] = { .type = NLA_U32 },
113 [NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT] = { .type = NLA_U32 },
114 [NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT] = { .type = NLA_U32 },
115 [NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT] = { .type = NLA_U32 },
116 [NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT] = { .type = NLA_U32 },
117 [NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT] = { .type = NLA_U32 },
118 [NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT] = { .type = NLA_U32 },
119 [NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY] = { .type = NLA_UNSPEC }
120 };
121
122 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
123 genlmsg_attrlen(gnlh, 0), NULL);
124
125 if (!tb[NL80211_ATTR_TESTDATA] ||
126 nla_parse_nested(sinfo, NL80211_TESTMODE_STA_STATISTICS_MAX, tb[NL80211_ATTR_TESTDATA], policy))
127 return NL_SKIP;
128
129 for (i=1; i < NL80211_TESTMODE_STA_STATISTICS_NUM; i++) {
130
131 if (!sinfo[i])
132 continue;
133
134 switch(i) {
135 case NL80211_TESTMODE_STA_STATISTICS_VERSION:
136 sta_statistics->version = nla_get_u8(sinfo[i]);
137 break;
138 case NL80211_TESTMODE_STA_STATISTICS_MAC:
139 nla_memcpy(sta_statistics->addr, sinfo[i], ETH_ALEN);
140 break;
141 case NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE:
142 sta_statistics->link_score = nla_get_u32(sinfo[i]);
143 break;
144 case NL80211_TESTMODE_STA_STATISTICS_FLAG:
145 sta_statistics->flag = nla_get_u32(sinfo[i]);
146 break;
147 case NL80211_TESTMODE_STA_STATISTICS_PER:
148 sta_statistics->per = nla_get_u8(sinfo[i]);
149 break;
150 case NL80211_TESTMODE_STA_STATISTICS_RSSI:
151 sta_statistics->rssi = (((int)nla_get_u8(sinfo[i]) - 220) / 2);
152 break;
153 case NL80211_TESTMODE_STA_STATISTICS_PHY_MODE:
154 sta_statistics->phy_mode = nla_get_u32(sinfo[i]);
155 break;
156 case NL80211_TESTMODE_STA_STATISTICS_TX_RATE:
157 sta_statistics->tx_rate = (((double)nla_get_u16(sinfo[i])) / 2);
158 break;
159 case NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT:
160 sta_statistics->tx_fail_cnt = nla_get_u32(sinfo[i]);
161 break;
162 case NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT:
163 sta_statistics->tx_timeout_cnt = nla_get_u32(sinfo[i]);
164 break;
165 case NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME:
166 sta_statistics->tx_avg_air_time = nla_get_u32(sinfo[i]);
167 break;
168 case NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT:
169 sta_statistics->tx_total_cnt = nla_get_u32(sinfo[i]);
170 break;
171 case NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT:
172 sta_statistics->tx_exc_threshold_cnt = nla_get_u32(sinfo[i]);
173 break;
174 case NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME:
175 sta_statistics->tx_avg_process_time = nla_get_u32(sinfo[i]);
176 break;
177 case NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME:
178 sta_statistics->tx_max_process_time = nla_get_u32(sinfo[i]);
179 break;
180 case NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME:
181 sta_statistics->tx_avg_hif_process_time = nla_get_u32(sinfo[i]);
182 break;
183 case NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME:
184 sta_statistics->tx_max_hif_process_time = nla_get_u32(sinfo[i]);
185 break;
186 case NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY:
187 nla_memcpy(sta_statistics->tc_buf_full_cnt, sinfo[i], sizeof(sta_statistics->tc_buf_full_cnt));
188 break;
189 case NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY:
190 nla_memcpy(sta_statistics->tc_que_len, sinfo[i], sizeof(sta_statistics->tc_que_len));
191 break;
192 case NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY:
193 nla_memcpy(sta_statistics->tc_avg_que_len, sinfo[i], sizeof(sta_statistics->tc_avg_que_len));
194 break;
195 case NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY:
196 nla_memcpy(sta_statistics->tc_cur_que_len, sinfo[i], sizeof(sta_statistics->tc_cur_que_len));
197 break;
198
199 case NL80211_TESTMODE_STA_STATISTICS_ENQUEUE:
200 sta_statistics->enqueue_total_cnt = nla_get_u32(sinfo[i]);
201 break;
202
203 case NL80211_TESTMODE_STA_STATISTICS_DEQUEUE:
204 sta_statistics->dequeue_total_cnt = nla_get_u32(sinfo[i]);
205 break;
206
207 case NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE:
208 sta_statistics->enqueue_sta_total_cnt = nla_get_u32(sinfo[i]);
209 break;
210
211 case NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE:
212 sta_statistics->dequeue_sta_total_cnt = nla_get_u32(sinfo[i]);
213 break;
214
215 case NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT:
216 sta_statistics->isr_cnt = nla_get_u32(sinfo[i]);
217 break;
218
219 case NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT:
220 sta_statistics->isr_pass_cnt = nla_get_u32(sinfo[i]);
221 break;
222 case NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT:
223 sta_statistics->isr_task_cnt = nla_get_u32(sinfo[i]);
224 break;
225
226 case NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT:
227 sta_statistics->isr_ab_cnt = nla_get_u32(sinfo[i]);
228 break;
229
230 case NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT:
231 sta_statistics->isr_sw_cnt = nla_get_u32(sinfo[i]);
232 break;
233
234 case NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT:
235 sta_statistics->isr_tx_cnt = nla_get_u32(sinfo[i]);
236 break;
237
238 case NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT:
239 sta_statistics->isr_rx_cnt = nla_get_u32(sinfo[i]);
240 break;
241
242 case NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY:
243 nla_memcpy(sta_statistics->dequeue_no_tc_res, sinfo[i],
244 sizeof(sta_statistics->dequeue_no_tc_res));
245 break;
246
247 case NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY:
248 nla_memcpy(sta_statistics->tc_used_res, sinfo[i],
249 sizeof(sta_statistics->tc_used_res));
250 break;
251 case NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY:
252 nla_memcpy(sta_statistics->tc_wanted_res, sinfo[i],
253 sizeof(sta_statistics->tc_wanted_res));
254 break;
255
256 case NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY:
257 nla_memcpy(sta_statistics->tc_back_count, sinfo[i],
258 sizeof(sta_statistics->tc_back_count));
259 break;
260
261 case NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY:
262 nla_memcpy(sta_statistics->reserved, sinfo[i], sizeof(sta_statistics->reserved));
263 break;
264 default:
265 break;
266 }
267 }
268
269 return NL_SKIP;
270}
271
272#ifdef CONFIG_MTK_LTE_COEX
273static int testmode_available_channel_handler(struct nl_msg *msg, void *arg)
274{
275 struct nlattr *tb[NL80211_ATTR_MAX + 1] = {};
276 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
277 struct nlattr *tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + 1] = {};
278 struct wpa_driver_available_chan_s *available_chans = (struct wpa_driver_available_chan_s *)arg;
279 static struct nla_policy chan_policy[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + 1] = {
280 [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1] = { .type = NLA_U32 },
281 [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36] = { .type = NLA_U32 },
282 [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52] = { .type = NLA_U32 },
283 [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100] = { .type = NLA_U32 },
284 [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149] = { .type = NLA_U32 },
285 };
286
287 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
288 genlmsg_attrlen(gnlh, 0), NULL);
289
290 if (!tb[NL80211_ATTR_TESTDATA] ||
291 nla_parse_nested(tb_chan, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX, tb[NL80211_ATTR_TESTDATA], chan_policy))
292 return NL_SKIP;
293
294 if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1])
295 available_chans->ch_2g_base1 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1]);
296
297 if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36])
298 available_chans->ch_5g_base36 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36]);
299
300 if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52])
301 available_chans->ch_5g_base52 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52]);
302
303 if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100])
304 available_chans->ch_5g_base100 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100]);
305
306 if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149])
307 available_chans->ch_5g_base149 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149]);
308
309 return NL_SKIP;
310}
311#endif
312
313static int wpa_driver_nl80211_testmode(void *priv, const u8 *data, size_t data_len)
314{
315 struct i802_bss *bss = priv;
316 struct wpa_driver_nl80211_data *drv = bss->drv;
317 struct nl_msg *msg, *cqm = NULL;
318 struct wpa_driver_testmode_params *params;
319 int index;
320
321 msg = nlmsg_alloc();
322 if (!msg)
323 return -1;
324
325 wpa_printf(MSG_DEBUG, "nl80211 test mode: ifindex=%d", drv->ifindex);
326
327 nl80211_cmd(drv, msg, 0, NL80211_CMD_TESTMODE);
328
329 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
330 NLA_PUT(msg, NL80211_ATTR_TESTDATA, data_len, data);
331
332 params = (struct wpa_driver_testmode_params *)data;
333
334 /* Mask version field */
335 index = params->hdr.index & BITS(0, 23);
336
337 switch(index) {
338 case 0x10:
339 {
340 struct wpa_driver_get_sta_statistics_params *sta_params =
341 (struct wpa_driver_get_sta_statistics_params *)data;
342 return send_and_recv_msgs(drv, msg, testmode_sta_statistics_handler, sta_params->buf);
343 }
344#ifdef CONFIG_MTK_LTE_COEX
345 case 0x30:
346 {
347 struct wpa_driver_get_available_channel_params *chan_params =
348 (struct wpa_driver_get_available_channel_params *)data;
349 return send_and_recv_msgs(drv, msg, testmode_available_channel_handler, chan_params->buf);
350 }
351#endif
352 default:
353 {
354 int ret = send_and_recv_msgs(drv, msg, NULL, NULL);
355 wpa_printf(MSG_EXCESSIVE, "ret=%d, nl=%p", ret, drv->global->nl);
356 return ret;
357 }
358 }
359
360nla_put_failure:
361 nlmsg_free(msg);
362 return -ENOBUFS;
363}
364
365static int wpa_driver_nl80211_driver_sw_cmd(void *priv, int set, u32 *adr, u32 *dat)
366{
367 struct i802_bss *bss = priv;
368 struct wpa_driver_nl80211_data *drv = bss->drv;
369 struct wpa_driver_sw_cmd_params params;
370 struct nl_msg *msg, *cqm = NULL;
371 int ret = 0;
372
373 os_memset(&params, 0, sizeof(params));
374
375 params.hdr.index = NL80211_TESTMODE_SW_CMD;
376 params.hdr.index = params.hdr.index | (0x01 << 24);
377 params.hdr.buflen = sizeof(struct wpa_driver_sw_cmd_params);
378
379 params.adr = *adr;
380 params.data = *dat;
381
382 if (set)
383 params.set = 1;
384 else
385 params.set = 0;
386
387 wpa_driver_nl80211_testmode(priv, (u8 *)&params, sizeof(struct wpa_driver_sw_cmd_params));
388 return 0;
389}
390
391#ifdef CONFIG_HOTSPOT_MGR_SUPPORT
392static int wpa_driver_hotspot_block_list_update(void *priv, const u8 *bssid, int blocked)
393{
394 struct wpa_driver_hotspot_params params;
395
396 os_memset(&params, 0, sizeof(params));
397
398 if (bssid)
399 os_memcpy(params.bssid, bssid, ETH_ALEN);
400
401 params.blocked = (u8)blocked;
402
403 params.hdr.index = NL80211_TESTMODE_HS20;
404 params.hdr.index = params.hdr.index | (0x01 << 24);
405 params.hdr.buflen = sizeof(struct wpa_driver_hotspot_params);
406
407 return wpa_driver_nl80211_testmode(priv, (u8 *)&params,
408 sizeof(struct wpa_driver_hotspot_params));
409}
410
411static int wpa_driver_sta_block(void *priv, char *cmd)
412{
413 u8 bssid[ETH_ALEN] = {};
414 int blocked = 1;
415
416 /* Block client device */
417 if (hwaddr_aton(cmd, bssid)) {
418 wpa_printf(MSG_DEBUG, "STA block: invalid DEVICE ADDRESS '%s'", cmd);
419 return -1;
420 }
421
422 wpa_printf(MSG_DEBUG, "Block STA " MACSTR, MAC2STR(bssid));
423 return wpa_driver_hotspot_block_list_update(priv, bssid, blocked);
424}
425
426static int wpa_driver_sta_unblock(void *priv, char *cmd)
427{
428 u8 bssid[ETH_ALEN] = {};
429 int blocked = 0;
430
431 /* Unblock client device */
432 if (hwaddr_aton(cmd, bssid)) {
433 wpa_printf(MSG_DEBUG, "STA unblock : invalid DEVICE ADDRESS '%s'", cmd);
434 return -1;
435 }
436
437 wpa_printf(MSG_DEBUG, "Unblock STA " MACSTR, MAC2STR(bssid));
438 return wpa_driver_hotspot_block_list_update(priv, bssid, blocked);
439}
440
441static int wpa_driver_set_max_client(void *priv, char *cmd, char *buf, size_t buflen)
442{
443 char *str = NULL;
444 int len = 0;
445 int value = 0;
446 struct wpa_driver_hotspot_set_config_params params;
447
448 os_memset(&params, 0, sizeof(params));
449
450 value = atoi(cmd);
451
452 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_max_connect value=%d\n", value);
453
454 params.hdr.index = NL80211_TESTMODE_HS_SET_CONFIG;
455 params.hdr.index = params.hdr.index | (0x01 << 24);
456 params.hdr.buflen = sizeof(struct wpa_driver_hotspot_set_config_params);
457
458 params.index = 1;
459 params.value = (u32)value;
460
461 return wpa_driver_nl80211_testmode(priv, (u8 *)&params,
462 sizeof(struct wpa_driver_hotspot_set_config_params));
463}
464#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */
465
466#ifdef CONFIG_MTK_LTE_COEX
467int wpa_driver_get_lte_available_channels(void *priv, struct wpa_driver_available_chan_s *buf)
468{
469 struct wpa_driver_get_available_channel_params params;
470
471 os_memset(&params, 0, sizeof(params));
472
473 params.hdr.index = 0x30;
474 params.hdr.index = params.hdr.index | (0x01 << 24);
475 params.hdr.buflen = sizeof(struct wpa_driver_get_available_channel_params);
476 /* buffer for return structure */
477 params.buf = (u8 *)buf;
478 return wpa_driver_nl80211_testmode(priv, (u8 *)&params,
479 sizeof(struct wpa_driver_get_available_channel_params));
480}
481
482static u8 wpa_driver_do_mtk_acs(void *priv)
483{
484 struct wpa_driver_available_chan_s available_chans;
485 u8 ch[14];
486 int ch_num, i;
487 int wait_cnt = 0;
488
489 do {
490 os_memset(&available_chans, 0, sizeof(struct wpa_driver_available_chan_s));
491 wpa_driver_get_lte_available_channels(priv, &available_chans);
492
493 if (BIT(31) & available_chans.ch_2g_base1) {
494 wpa_printf(MSG_DEBUG, "2G Channel: 0x%08x", available_chans.ch_2g_base1);
495 break;
496 } else {
497 wpa_printf(MSG_DEBUG, "2G Channel: 0x%08x, waiting for scan complete",
498 available_chans.ch_2g_base1);
499 wait_cnt++;
500 if (wait_cnt > 5)
501 return 0;
502 os_sleep(0, 1000*350);
503 }
504 } while(1);
505
506 os_memset(ch, 0, sizeof(ch));
507 ch_num = 0;
508
509 for (i = 0; i < 14; i++) {
510 if (BIT(i) & available_chans.ch_2g_base1) {
511 ch[ch_num] = i + 1;
512 ch_num++;
513 } else
514 continue;
515 }
516
517 wpa_printf(MSG_DEBUG, "Driver report 2G available %d channel", ch_num);
518 for (i = 0; i < ch_num; i++)
519 wpa_printf(MSG_DEBUG,"Channel %d is fine", ch[i]);
520
521 return ch[0];
522}
523#endif /* CONFIG_MTK_LTE_COEX */
524
525#ifdef CONFIG_WAPI_SUPPORT
526int wpa_driver_nl80211_set_wapi_key(void *priv,
527 const u8 *addr, int key_idx,
528 int set_tx, const u8 *seq,
529 size_t seq_len,
530 const u8 *key, size_t key_len)
531{
532 struct i802_bss *bss = priv;
533 struct wpa_driver_nl80211_data *drv = bss->drv;
534 struct nl_msg *msg, *cqm = NULL;
535 struct wpa_driver_wapi_key_params params;
536 int ret = 0;
537
538 os_memset(&params, 0, sizeof(params));
539
540 params.hdr.index = NL80211_TESTMODE_WAPI;
541 params.hdr.index = params.hdr.index | (0x01 << 24);
542 params.hdr.buflen = sizeof(struct wpa_driver_wapi_key_params);
543
544 wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]1 %s: ", __FUNCTION__);
545
546 if (seq_len > IW_ENCODE_SEQ_MAX_SIZE * 2) {
547 wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]%s: Invalid seq_len %lu",
548 __FUNCTION__, (unsigned long)seq_len);
549 return -1;
550 }
551
552 params.key_index = key_idx + 1;
553 params.key_len = key_len;
554
555 if (addr == NULL ||
556 os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
557 params.extparams.ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
558 if (set_tx)
559 params.extparams.ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
560
561 if (addr)
562 os_memcpy(params.extparams.addr, addr, ETH_ALEN);
563 else
564 os_memset(params.extparams.addr, 0xff, ETH_ALEN);
565
566 if (key && key_len) {
567 os_memcpy(params.extparams.key, key, key_len);
568 params.extparams.key_len = key_len;
569 }
570
571 wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]2 %s:", __FUNCTION__);
572
573 wpa_printf(MSG_DEBUG, "%s: Set IW_ENCODE_ALG_SMS4 to ext->alg",
574 __FUNCTION__);
575
576 params.extparams.alg = IW_ENCODE_ALG_SMS4;
577
578 wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]3 %s: ", __FUNCTION__);
579
580 if (seq && seq_len)
581 os_memcpy(params.extparams.tx_seq, seq, seq_len);
582
583 wpa_hexdump(MSG_DEBUG, "seq", seq, seq_len);
584
585 wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]4 Copy buffer %s: ", __FUNCTION__);
586
587 wpa_driver_nl80211_testmode(priv, (u8 *)&params, sizeof(struct wpa_driver_wapi_key_params));
588
589 return 0;
590}
591
592/**
593* wpa_driver_nl80211_send_msg - send some information to driver
594* @priv: private driver interface data from init()
595* @msg_in: the message sent to driver
596* @msg_in_len: the length of sent message
597* @msg_out: the message given back from driver
598* @msg_out_len: the length of message given back from driver
599*
600* Returns: 0 on success, -1 on failure
601*
602*/
603static int wpa_driver_nl80211_send_msg(void *priv, const u8 *msg_in, int msg_in_len,
604 u8 *msg_out, int *msg_out_len)
605{
606 struct i802_bss *bss = priv;
607 struct wpa_driver_nl80211_data *drv = bss->drv;
608 int ret = 0;
609
610 if (msg_in_len > 1024) {
611 wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_send_msg: msg too long");
612 return -1;
613 }
614
615 return ret;
616}
617#endif /* CONFIG_WAPI_SUPPORT */
618
619static inline int wpa_drv_set_test_mode(struct wpa_supplicant *wpa_s,
620 const u8 *buf, size_t buf_len)
621{
622 return wpa_driver_nl80211_testmode(wpa_s->drv_priv, buf, buf_len);
623}
624
625
626/**********************************************************************
627* OVERLAPPED functins, previous defination is in driver_nl80211.c,
628* it will be modified
629***********************************************************************/
630
631/**********************************************************************/
632extern int wpa_config_write(const char *name, struct wpa_config *config);
633
634static int wpa_driver_mediatek_set_country(void *priv, const char *alpha2_arg)
635{
636 struct i802_bss *bss = priv;
637 struct wpa_driver_nl80211_data *drv = bss->drv;
638 int ioctl_sock = -1;
639 struct iwreq iwr;
640 int ret = -1;
641 char buf[11];
642#ifdef MTK_TC1_FEATURE
643 char replace_ifname[IFNAMSIZ+1];
644
645 memset(replace_ifname, 0, IFNAMSIZ+1);
646 os_strlcpy(replace_ifname, "wlan0", os_strlen("wlan0")+1);
647#endif
648
649 ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
650 if (ioctl_sock < 0) {
651 wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__);
652 return -1;
653 }
654 os_memset(&iwr, 0, sizeof(iwr));
655#ifdef MTK_TC1_FEATURE
656 // convert 'p2p0' -> 'wlan0' :
657 // when iface name is p2p0, COUNTRY driver command doesn't support in MTK solution.
658 if (os_strncmp(drv->first_bss->ifname, "p2p0", os_strlen("p2p0")) == 0) {
659 wpa_printf(MSG_DEBUG, "Change interface name : p2p0->wlan0");
660 os_strlcpy(iwr.ifr_name, replace_ifname, IFNAMSIZ );
661 } else {
662 os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ);
663 }
664#else
665 os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ);
666#endif
667 snprintf(buf, sizeof(buf), "COUNTRY %s", alpha2_arg);
668 iwr.u.data.pointer = buf;
669 iwr.u.data.length = strlen(buf);
670 if ((ret = ioctl(ioctl_sock, 0x8B0C, &iwr)) < 0) { // SIOCSIWPRIV
671 wpa_printf(MSG_DEBUG, "ioctl[SIOCSIWPRIV]: %s", buf);
672 close(ioctl_sock);
673 return ret;
674 }
675 else {
676 close(ioctl_sock);
677 return 0;
678 }
679
680}
681
682/*
683* update channel list in wpa_supplicant
684* if coutry code chanaged
685*/
686static void wpa_driver_notify_country_change(struct wpa_global *global, char *cmd)
687{
688 struct wpa_supplicant *wpa_s;
689
690 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
691 union wpa_event_data event;
692
693 os_memset(&event, 0, sizeof(event));
694 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
695 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
696 event.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
697 if (os_strlen(cmd) > 9) {
698 event.channel_list_changed.alpha2[0] = cmd[8];
699 event.channel_list_changed.alpha2[1] = cmd[9];
700 }
701 } else {
702 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
703 }
704 // Notify all interfaces
705 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
706 wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
707 }
708 }
709}
710
711/**
712 * mtk_p2p_get_device - Fetch a peer entry
713 * @p2p: P2P module context from p2p_init()
714 * @addr: P2P Device Address of the peer
715 * Returns: Pointer to the device entry or %NULL if not found
716 */
717struct p2p_device *mtk_p2p_get_device(struct p2p_data *p2p, const u8 *addr)
718{
719 struct p2p_device *dev;
720
721 dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
722 if (memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
723 return dev;
724 }
725 return NULL;
726}
727/*
728 * we should use interface MAC address
729 * instead of device MAC when query
730 * STA statistics, as driver uses interface addr
731 * to do TX/RX
732 * In most cases, the interface addr and device addr
733 * should be the same
734 */
735u8 *wpas_p2p_get_sta_mac(struct wpa_supplicant *wpa_s, u8 *org_addr)
736{
737 struct p2p_data *p2p = wpa_s->global->p2p;
738 struct wpa_ssid *ssid = wpa_s->current_ssid;
739 struct p2p_device *dev = NULL;
740 int is_p2p_client = 0;
741
742 if (!p2p) {
743 wpa_printf(MSG_DEBUG, "interface %s not support p2p", wpa_s->ifname);
744 return NULL;
745 }
746
747 if (!ssid) {
748 wpa_printf(MSG_DEBUG, "P2P: ssid not connected");
749 return NULL;
750 }
751
752 dev = mtk_p2p_get_device(p2p, org_addr);
753
754 if (!dev) {
755 wpa_printf(MSG_DEBUG, "P2P: device " MACSTR "not found",
756 MAC2STR(org_addr));
757 return NULL;
758 }
759
760 is_p2p_client = ssid->mode == WPAS_MODE_INFRA ? 1 : 0;
761
762 if (is_p2p_client) {
763 if (memcmp(dev->info.p2p_device_addr, wpa_s->bssid, ETH_ALEN) &&
764 !is_zero_ether_addr(wpa_s->bssid)) {
765 wpa_printf(MSG_DEBUG, "P2P: we are GC, Use interface_addr "
766 MACSTR "instead of " MACSTR,
767 MAC2STR(wpa_s->bssid),
768 MAC2STR(org_addr));
769 return wpa_s->bssid;
770 }
771 }
772
773 /*
774 * we are GO, interface_addr should be filled
775 * when RX NL80211_CMD_NEW_STA event
776 * if it is defferent between device addr and interface addr
777 */
778 if (memcmp(dev->info.p2p_device_addr, dev->interface_addr, ETH_ALEN) &&
779 !is_zero_ether_addr(dev->interface_addr)) {
780 wpa_printf(MSG_DEBUG, "P2P: we are GO, Use interface_addr " MACSTR
781 "instead of " MACSTR,
782 MAC2STR(dev->interface_addr),
783 MAC2STR(org_addr));
784 return dev->interface_addr;
785 }
786 return NULL;
787}
788
789/* Move GET_STA_STATISTICS to "DRIVER GET_STA_STATISTICS", implement in 3rd part lib */
790/* [ALPS00618361] [WFD Quality Enhancement] */
791int wpas_get_sta_statistics(struct wpa_supplicant *wpa_s, u8 *sta_addr, u8 *buf)
792{
793 struct wpa_driver_get_sta_statistics_params params;
794
795 os_memset(&params, 0, sizeof(params));
796
797 if(sta_addr)
798 os_memcpy(params.addr, sta_addr, ETH_ALEN);
799
800 wpa_printf(MSG_DEBUG, "get_sta_statistics ["MACSTR"]", MAC2STR(params.addr));
801
802 params.hdr.index = NL80211_TESTMODE_STATISTICS;
803 params.hdr.index = params.hdr.index | (0x01 << 24);
804 params.hdr.buflen = sizeof(struct wpa_driver_get_sta_statistics_params);
805
806 /* buffer for return structure */
807 params.buf = buf;
808
809 return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&params,
810 sizeof(struct wpa_driver_get_sta_statistics_params));
811}
812
813/* [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */
814static int print_sta_statistics(struct wpa_supplicant *wpa_s, struct wpa_driver_sta_statistics_s *sta_stats,
815 unsigned long mask, char *buf, size_t buflen)
816{
817 size_t i;
818 int ret;
819 char *pos, *end;
820
821 pos = buf;
822 end = buf + buflen;
823
824 ret = os_snprintf(pos, end - pos, "sta_addr="MACSTR"\n", MAC2STR(sta_stats->addr));
825 if (ret < 0 || ret >= end - pos)
826 return 0;
827 pos += ret;
828
829 ret = os_snprintf(pos, end - pos, "link_score=%d\n", sta_stats->link_score);
830 if (ret < 0 || ret >= end - pos)
831 return 0;
832 pos += ret;
833
834 ret = os_snprintf(pos, end - pos, "per=%d\n", sta_stats->per);
835 if (ret < 0 || ret >= end - pos)
836 return 0;
837 pos += ret;
838
839 ret = os_snprintf(pos, end - pos, "rssi=%d\n", sta_stats->rssi);
840 if (ret < 0 || ret >= end - pos)
841 return 0;
842 pos += ret;
843
844 ret = os_snprintf(pos, end - pos, "phy=0x%08X\n", sta_stats->phy_mode);
845 if (ret < 0 || ret >= end - pos)
846 return 0;
847 pos += ret;
848
849 ret = os_snprintf(pos, end - pos, "rate=%.1f\n", sta_stats->tx_rate);
850 if (ret < 0 || ret >= end - pos)
851 return 0;
852 pos += ret;
853
854 ret = os_snprintf(pos, end - pos, "total_cnt=%d\n", sta_stats->tx_total_cnt);
855 if (ret < 0 || ret >= end - pos)
856 return 0;
857 pos += ret;
858
859 ret = os_snprintf(pos, end - pos, "threshold_cnt=%d\n", sta_stats->tx_exc_threshold_cnt);
860 if (ret < 0 || ret >= end - pos)
861 return 0;
862 pos += ret;
863
864 ret = os_snprintf(pos, end - pos, "fail_cnt=%d\n", sta_stats->tx_fail_cnt);
865 if (ret < 0 || ret >= end - pos)
866 return 0;
867 pos += ret;
868
869 ret = os_snprintf(pos, end - pos, "timeout_cnt=%d\n", sta_stats->tx_timeout_cnt);
870 if (ret < 0 || ret >= end - pos)
871 return 0;
872 pos += ret;
873
874 ret = os_snprintf(pos, end - pos, "apt=%d\n", sta_stats->tx_avg_process_time);
875 if (ret < 0 || ret >= end - pos)
876 return 0;
877 pos += ret;
878
879 ret = os_snprintf(pos, end - pos, "aat=%d\n", sta_stats->tx_avg_air_time);
880 if (ret < 0 || ret >= end - pos)
881 return 0;
882 pos += ret;
883
884 ret = os_snprintf(pos, end - pos, "TC_buf_full_cnt=%d:%d:%d:%d\n",
885 sta_stats->tc_buf_full_cnt[TC0_INDEX],
886 sta_stats->tc_buf_full_cnt[TC1_INDEX],
887 sta_stats->tc_buf_full_cnt[TC2_INDEX],
888 sta_stats->tc_buf_full_cnt[TC3_INDEX]);
889 if (ret < 0 || ret >= end - pos)
890 return 0;
891 pos += ret;
892
893 ret = os_snprintf(pos, end - pos, "TC_sta_que_len=%d:%d:%d:%d\n",
894 sta_stats->tc_que_len[TC0_INDEX],
895 sta_stats->tc_que_len[TC1_INDEX],
896 sta_stats->tc_que_len[TC2_INDEX],
897 sta_stats->tc_que_len[TC3_INDEX]);
898 if (ret < 0 || ret >= end - pos)
899 return 0;
900 pos += ret;
901
902 ret = os_snprintf(pos, end - pos, "TC_avg_que_len=%d:%d:%d:%d\n",
903 sta_stats->tc_avg_que_len[TC0_INDEX],
904 sta_stats->tc_avg_que_len[TC1_INDEX],
905 sta_stats->tc_avg_que_len[TC2_INDEX],
906 sta_stats->tc_avg_que_len[TC3_INDEX]);
907 if (ret < 0 || ret >= end - pos)
908 return 0;
909 pos += ret;
910
911 ret = os_snprintf(pos, end - pos, "TC_cur_que_len=%d:%d:%d:%d\n",
912 sta_stats->tc_cur_que_len[TC0_INDEX],
913 sta_stats->tc_cur_que_len[TC1_INDEX],
914 sta_stats->tc_cur_que_len[TC2_INDEX],
915 sta_stats->tc_cur_que_len[TC3_INDEX]);
916 if (ret < 0 || ret >= end - pos)
917 return 0;
918 pos += ret;
919
920 ret = os_snprintf(pos, end - pos, "flag=0x%08X\n", sta_stats->flag);
921 if (ret < 0 || ret >= end - pos)
922 return 0;
923 pos += ret;
924
925 ret = os_snprintf(pos, end - pos, "reserved0=");
926 if (ret < 0 || ret >= end - pos)
927 return 0;
928 pos += ret;
929 for (i = 0; i < 16; i++) {
930 ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]);
931 if (ret < 0 || ret >= end - pos)
932 return 0;
933 pos += ret;
934
935 if (((i + 1) % 4) == 0) {
936 ret = os_snprintf(pos, end - pos, " ");
937 if (ret < 0 || ret >= end - pos)
938 return 0;
939 pos += ret;
940 }
941 }
942 ret = os_snprintf(pos, end - pos, "\n");
943 if (ret < 0 || ret >= end - pos)
944 return 0;
945 pos += ret;
946
947 ret = os_snprintf(pos, end - pos, "reserved1=");
948 if (ret < 0 || ret >= end - pos)
949 return 0;
950 pos += ret;
951 for (i = 16; i < 32; i++) {
952 ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]);
953 if (ret < 0 || ret >= end - pos)
954 return 0;
955 pos += ret;
956
957 if (((i + 1) % 4) == 0) {
958 ret = os_snprintf(pos, end - pos, " ");
959 if (ret < 0 || ret >= end - pos)
960 return 0;
961 pos += ret;
962 }
963 }
964 ret = os_snprintf(pos, end - pos, "\n");
965 if (ret < 0 || ret >= end - pos)
966 return 0;
967 pos += ret;
968
969 ret = os_snprintf(pos, end - pos, "====\n");
970 if (ret < 0 || ret >= end - pos)
971 return 0;
972 pos += ret;
973
974 return pos - buf;
975}
976
977/* [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */
978static void format_sta_statistics(struct wpa_driver_sta_statistics_s *s)
979{
980 wpa_printf(MSG_DEBUG, "NWFD: Basic info* AVG:%4d:EN:%4d:DE:%4d:SEN:%4d:SDE:%4d:HIF:%4d",
981 s->tx_avg_process_time,
982 s->enqueue_total_cnt,
983 s->dequeue_total_cnt,
984 s->enqueue_sta_total_cnt,
985 s->dequeue_sta_total_cnt,
986 s->tx_total_cnt);
987
988 wpa_printf(MSG_DEBUG, "NWFD: Time info* TTL:%4d:AVG:%4d:MAX:%4d:HIFAVG:%4d:HIFMAX:%4d",
989 s->tx_total_cnt,
990 s->tx_avg_process_time,
991 s->tx_max_process_time,
992 s->tx_avg_hif_process_time,
993 s->tx_max_hif_process_time);
994
995 wpa_printf(MSG_DEBUG, "NWFD: No TC RES* Score:%4d:EN:%4d#%4d#%4d#%4d:DE:%4d#%4d#%4d#%4d",
996 s->link_score,
997 s->tc_buf_full_cnt[TC0_INDEX],
998 s->tc_buf_full_cnt[TC1_INDEX],
999 s->tc_buf_full_cnt[TC2_INDEX],
1000 s->tc_buf_full_cnt[TC3_INDEX],
1001 s->dequeue_no_tc_res[TC0_INDEX],
1002 s->dequeue_no_tc_res[TC1_INDEX],
1003 s->dequeue_no_tc_res[TC2_INDEX],
1004 s->dequeue_no_tc_res[TC3_INDEX]);
1005
1006 wpa_printf(MSG_DEBUG, "NWFD: Irq info* T:%4d:P:%4d:TT:%4d:A:%4d:S:%4d:R:%4d:T:%4d",
1007 s->isr_cnt,
1008 s->isr_pass_cnt,
1009 s->isr_task_cnt,
1010 s->isr_ab_cnt,
1011 s->isr_sw_cnt,
1012 s->isr_rx_cnt,
1013 s->isr_tx_cnt);
1014
1015 /*
1016 * TC resouce information: format:
1017 * 1. how many TC resource wanted during statistics intervals
1018 * 2. how many TC resource acquire successfully
1019 * 3. how many TC resource back during statistics intervals
1020 */
1021 wpa_printf(MSG_DEBUG, "NWFD: TC Res info[W:U:B]* Score:%4d:"
1022 "#%5d:%5d:%5d#"
1023 "#%5d:%5d:%5d#"
1024 "#%5d:%5d:%5d#"
1025 "#%5d:%5d:%5d#",
1026 s->link_score,
1027 s->tc_wanted_res[TC0_INDEX],
1028 s->tc_used_res[TC0_INDEX],
1029 s->tc_back_count[TC0_INDEX],
1030
1031 s->tc_wanted_res[TC1_INDEX],
1032 s->tc_used_res[TC1_INDEX],
1033 s->tc_back_count[TC1_INDEX],
1034
1035 s->tc_wanted_res[TC2_INDEX],
1036 s->tc_used_res[TC2_INDEX],
1037 s->tc_back_count[TC2_INDEX],
1038
1039 s->tc_wanted_res[TC3_INDEX],
1040 s->tc_used_res[TC3_INDEX],
1041 s->tc_back_count[TC3_INDEX]);
1042}
1043
1044int wpa_driver_get_sta_statistics(struct wpa_supplicant *wpa_s, char *addr,
1045 char *buf, size_t buflen)
1046{
1047 char *str = NULL;
1048 int len = 0;
1049 u8 sta_addr[ETH_ALEN];
1050 u8 *mac = NULL;
1051 struct wpa_driver_sta_statistics_s sta_statistics;
1052
1053 memset(&sta_statistics, 0 ,sizeof(sta_statistics));
1054
1055 if (hwaddr_aton(addr, sta_addr)) {
1056 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: invalid "
1057 "address '%s'", addr);
1058 return -1;
1059 }
1060
1061 mac = wpas_p2p_get_sta_mac(wpa_s, sta_addr);
1062
1063 if (wpas_get_sta_statistics(wpa_s, mac ? mac : sta_addr,
1064 (u8 *)&sta_statistics) < 0) {
1065 wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: command failed");
1066 return -1;
1067 }
1068 len = print_sta_statistics(wpa_s, &sta_statistics, 0x00, buf, buflen);
1069
1070 format_sta_statistics(&sta_statistics);
1071 return len;
1072}
1073
1074#ifdef CONFIG_MTK_P2P_SIGMA
1075static int wpas_p2p_sigma_test_mode(struct wpa_supplicant *wpa_s, int index, int value)
1076{
1077 struct wpa_driver_p2p_sigma_params params;
1078
1079 os_memset(&params, 0, sizeof(params));
1080
1081 params.hdr.index = 1;
1082 params.hdr.index = params.hdr.index | (0x01 << 24);
1083 params.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params);
1084
1085 params.idx = (u32)index;
1086 params.value = (u32)value;
1087
1088 return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&params,
1089 sizeof(struct wpa_driver_p2p_sigma_params));
1090}
1091
1092static int p2p_ctrl_iface_set_opps(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1093{
1094 char *str = NULL;
1095 u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1096 int len = 0;
1097 size_t ssid_len = 0;
1098 char *ssid;
1099 int CTWin;
1100
1101 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps cmd=%s\n", cmd);
1102
1103 CTWin = atoi(cmd);
1104
1105 str = os_strchr(cmd, ' ');
1106 if (str) {
1107 *str ++ = '\0';
1108
1109 if (hwaddr_aton(str, addr))
1110 return -1;
1111 }
f3fa1980 1112
c481cf08
JA
1113 str = os_strchr(str, ' ');
1114 if (str) {
1115 *str ++ = '\0';
f3fa1980 1116
c481cf08
JA
1117 ssid = wpa_config_parse_string(str, &ssid_len);
1118 if (ssid) {
1119 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%zu)%s\n",
1120 CTWin, MAC2STR(addr), ssid_len, ssid);
1121 os_free(ssid);
1122 }
1123 else {
1124 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%zu)\n",
1125 CTWin, MAC2STR(addr), ssid_len);
1126 }
1127 }
1128
1129 wpas_p2p_sigma_test_mode(wpa_s, 107, (int)CTWin);
1130
1131 //len = os_snprintf(buf, buflen, "return OK");
1132
1133 return len;
1134}
1135
1136static int p2p_ctrl_iface_set_power_save(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
f3fa1980 1137{
c481cf08
JA
1138 char *str = NULL;
1139 int len = 0;
1140 int value = 0;
f3fa1980 1141
c481cf08 1142 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save cmd=%s\n", cmd);
f3fa1980 1143
c481cf08
JA
1144 value = atoi(cmd);
1145
1146 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save value=%d\n", value);
1147
1148 wpas_p2p_sigma_test_mode(wpa_s, 108, (int)value);
1149
1150 //len = os_snprintf(buf, buflen, "return OK");
1151
1152 return len;
1153
1154}
1155
1156static int p2p_ctrl_iface_set_sleep(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1157{
1158 char *str = NULL;
1159 u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1160 int len = 0;
1161 size_t ssid_len = 0;
1162 char *ssid;
1163
1164 if (hwaddr_aton(cmd, addr))
f3fa1980 1165 return -1;
c481cf08
JA
1166
1167 str = os_strchr(cmd, ' ');
1168 if (str) {
1169 *str ++ = '\0';
1170
1171 ssid = wpa_config_parse_string(str, &ssid_len);
1172 if (ssid) {
1173 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%zu)%s\n",
1174 MAC2STR(addr), ssid_len, ssid);
1175 os_free(ssid);
1176 }
1177 else {
1178 wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%zu)\n",
1179 MAC2STR(addr), ssid_len);
1180 }
f3fa1980 1181 }
c481cf08
JA
1182
1183 wpas_p2p_sigma_test_mode(wpa_s, 106, 0);
1184
1185 //len = os_snprintf(buf, buflen, "return OK");
1186
1187 return len;
1188
1189}
1190#endif /* CONFIG_MTK_P2P_SIGMA */
1191
1192/* utils for parse cmdline:
1193 * cmd: paramters in cmd line
1194 * argv: paramter vector
1195 * len: cmd lenght
1196 * example:
1197 * cmd = "driver P2P_SET_NOA 1 2 3"
1198 * argv[0] = "driver"
1199 * argv[1] = "P2P_SET_NOA"
1200 * argv[2] = "1"
1201 * argv[3] = "2"
1202 * argv[4] = "3"
1203 */
1204
1205int tokenize_space(char *cmd, char *argv[], int len)
1206{
1207 char *pos;
1208 char *start;
1209 int argc = 0;
1210
1211 start = pos = cmd;
1212 for (;;) {
1213 argv[argc] = pos;
1214 argc++;
1215 while (*pos != '\n' && *pos != ' ' && *pos != '\0') {
1216 pos++;
1217 if (pos - start >= len)
1218 break;
1219 }
1220
1221 if (*pos == '\0')
1222 break;
1223
1224 if (*pos == '\n' || *pos == ' ') {
1225 *pos++ = '\0';
1226 if (pos - start >= len)
1227 break;
1228 }
f3fa1980 1229 }
c481cf08
JA
1230
1231 return argc;
1232}
1233
1234static int p2p_ctrl_iface_set_noa(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1235{
1236 struct wpa_driver_p2p_noa_params {
1237 struct wpa_driver_test_mode_info hdr;
1238 u32 idx;
1239 u32 value; /* should not be used in this case */
1240 u32 count;
1241 u32 interval;
1242 u32 duration;
1243 };
1244 char *argv[64];
1245 int argc;
1246 struct wpa_driver_p2p_noa_params noa_param;
1247
1248 os_memset(&noa_param, 0, sizeof(noa_param));
1249
1250 /* P2P_SET_NOA 255 100 3 */
1251 /*
1252 * argv format:
1253 * argv[0] = "P2P_SET_NOA"
1254 * argv[1] = "255"
1255 * argv[2] = "100"
1256 * argv[3] = "3"
1257 */
1258 argc = tokenize_space(cmd, argv, os_strlen(cmd));
1259
1260 if (argc != 4) {
1261 wpa_printf(MSG_DEBUG, "P2P: NOA: invalid cmd format");
1262 return -1;
f3fa1980 1263 }
c481cf08
JA
1264
1265 /* fill in the params structure */
1266 noa_param.hdr.index = 1;
1267 noa_param.hdr.index = noa_param.hdr.index | (0x01 << 24);
1268 noa_param.hdr.buflen = sizeof(struct wpa_driver_p2p_noa_params);
1269
1270 noa_param.idx = 4;
1271 noa_param.count = (u32)atoi(argv[1]);
1272 noa_param.interval= (u32)atoi(argv[2]);
1273 noa_param.duration= (u32)atoi(argv[3]);
1274
1275 wpa_printf(MSG_DEBUG, "P2P: set noa: %d %d %d",
1276 noa_param.count,
1277 noa_param.interval,
1278 noa_param.duration);
1279
1280 return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&noa_param,
1281 sizeof(struct wpa_driver_p2p_noa_params));
1282}
1283
1284static int p2p_ctrl_iface_set_ps(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1285{
1286 char *argv[64];
1287 int argc;
1288 int enable;
1289 s32 ctw;
1290 struct wpa_driver_p2p_sigma_params opps_param;
1291
1292 os_memset(&opps_param, 0, sizeof(opps_param));
1293
1294 /* P2P_SET_PS 2 1 3
1295 * argv format:
1296 * argv[0] = "P2P_SET_PS"
1297 * argv[1] = "2"
1298 * argv[2] = "1"
1299 * argv[3] = "3"
1300 */
1301 argc = tokenize_space(cmd, argv, os_strlen(cmd));
1302
1303 if (argc != 4) {
1304 wpa_printf(MSG_DEBUG, "P2P: Opps: invalid cmd format");
1305 return -1;
1306 }
1307
1308 /* fill in the params structure */
1309 opps_param.hdr.index = 1;
1310 opps_param.hdr.index = opps_param.hdr.index | (0x01 << 24);
1311 opps_param.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params);
1312
1313 opps_param.idx = 107;
1314
1315 enable = atoi(argv[2]);
1316 ctw = atoi(argv[3]);
1317
1318 /* BIT 7 control OPPS on / off */
1319 if (enable)
1320 ctw |= BIT(7);
1321
1322 opps_param.value = ctw;
1323
1324 wpa_printf(MSG_DEBUG, "P2P: set opps: 0x%x",
1325 opps_param.value);
1326
1327 return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&opps_param,
1328 sizeof(struct wpa_driver_p2p_sigma_params));
1329}
1330
1331#ifdef CONFIG_MTK_WFD_SINK
1332static int wpas_wfd_data_update(struct wpa_supplicant *wpa_s, struct wfd_data_s *p_wfd_data)
1333{
1334 struct wpa_driver_wfd_data_s params;
1335 os_memset(&params, 0, sizeof(params));
1336
1337 wpa_printf(MSG_DEBUG, "WFD: wpas_wfd_data_update wfd_en %u wfd_dev_info 0x%x wfd_ctrl_port %u wfd_state 0x%x",
1338 p_wfd_data->WfdEnable, p_wfd_data->WfdDevInfo, p_wfd_data->WfdControlPort, p_wfd_data->WfdState);
1339
1340
1341 params.hdr.index = 2;
1342 params.hdr.index = params.hdr.index | (0x01 << 24);
1343 params.hdr.buflen = sizeof(struct wfd_data_s);
1344
1345 params.WfdCmdType = p_wfd_data->WfdCmdType;
1346 params.WfdEnable = p_wfd_data->WfdEnable;
1347 params.WfdCoupleSinkStatus = p_wfd_data->WfdCoupleSinkStatus;
1348 params.WfdDevInfo = p_wfd_data->WfdDevInfo;
1349 params.WfdControlPort = p_wfd_data->WfdControlPort;
1350 params.WfdMaximumTp = p_wfd_data->WfdMaximumTp;
1351 params.WfdExtendCap = p_wfd_data->WfdExtendCap;
1352 os_memcpy(params.WfdCoupleSinkAddress, p_wfd_data->WfdCoupleSinkAddress, ETH_ALEN);
1353 os_memcpy(params.WfdAssociatedBssid, p_wfd_data->WfdAssociatedBssid, ETH_ALEN);
1354 os_memcpy(params.WfdVideoIp, p_wfd_data->WfdVideoIp, sizeof(p_wfd_data->WfdVideoIp));
1355 os_memcpy(params.WfdAudioIp, p_wfd_data->WfdAudioIp, sizeof(p_wfd_data->WfdAudioIp));
1356 params.WfdVideoPort = p_wfd_data->WfdVideoPort;
1357 params.WfdAudioPort = p_wfd_data->WfdAudioPort;
1358 params.WfdFlag = p_wfd_data->WfdFlag;
1359 params.WfdPolicy = p_wfd_data->WfdPolicy;
1360 params.WfdState = p_wfd_data->WfdState;
1361 params.WfdSessionInformationIELen = p_wfd_data->WfdSessionInformationIELen;
1362 os_memcpy(params.WfdSessionInformationIE, p_wfd_data->WfdSessionInformationIE,
1363 p_wfd_data->WfdSessionInformationIELen);
1364 os_memcpy(params.WfdPrimarySinkMac, p_wfd_data->WfdPrimarySinkMac, ETH_ALEN);
1365 os_memcpy(params.WfdSecondarySinkMac, p_wfd_data->WfdSecondarySinkMac, ETH_ALEN);
1366 params.WfdAdvancedFlag = p_wfd_data->WfdAdvancedFlag;
1367
1368 params.WfdSessionAvailable = p_wfd_data->WfdSessionAvailable;
1369 params.WfdSigmaMode = p_wfd_data->WfdSigmaMode;
1370 os_memcpy(params.WfdLocalIp, p_wfd_data->WfdLocalIp, sizeof(p_wfd_data->WfdLocalIp));
1371
1372 return wpa_drv_set_test_mode(wpa_s, (u8 *)&params, sizeof(struct wpa_driver_wfd_data_s));
1373}
1374
1375static int p2p_get_capability(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1376{
1377 int ret = 0;
1378 struct p2p_data *p2p = wpa_s->global->p2p;
1379 wpa_printf(MSG_DEBUG, "%s %d, %d", __func__, __LINE__, p2p->dev_capab);
1380 if (os_strncmp(cmd, "p2p_dev_capa", os_strlen("p2p_dev_capa")) == 0) {
1381 ret = snprintf(buf, buflen, "p2p_dev_capa=%d\n", p2p->dev_capab);
1382 wpa_printf(MSG_DEBUG, "%s %d %d, %s", __func__, __LINE__, p2p->dev_capab, buf);
1383 } else if (os_strncmp(cmd, "p2p_group_capa", os_strlen("p2p_group_capa")) == 0) {
1384 wpa_printf(MSG_DEBUG, "%s not implement", __func__);
1385 ret = -1;
1386 }
1387 return ret;
1388}
1389
1390static int p2p_set_capability(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
1391{
1392 int ret = 0;
1393 wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__);
1394 struct p2p_data *p2p = wpa_s->global->p2p;
1395 if (os_strncmp(cmd, "p2p_dev_capa ", os_strlen("p2p_dev_capa ")) == 0) {
1396 int old_cap = p2p->dev_capab;
1397 int dev_cap = atoi(cmd + os_strlen("p2p_dev_capa "));
1398 p2p->dev_capab = dev_cap & 0xff;
1399 wpa_printf(MSG_DEBUG, "%s %d %d, %d", __func__, __LINE__, p2p->dev_capab,
1400 old_cap);
1401 } else if (os_strncmp(cmd, "p2p_group_capa ", os_strlen("p2p_group_capa ")) == 0) {
1402 wpa_printf(MSG_DEBUG, "%s group not implement", __func__);
1403 ret = -1;
1404 }
1405 return ret;
1406}
1407
1408/**
1409 * priv_p2p_freq_to_channel - Convert frequency into channel info
1410 * @op_class: Buffer for returning operating class
1411 * @channel: Buffer for returning channel number
1412 * Returns: 0 on success, -1 if the specified frequency is unknown
1413 */
1414static int priv_p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel)
1415{
1416 /* TODO: more operating classes */
1417 if (freq >= 2412 && freq <= 2472) {
1418 if ((freq - 2407) % 5)
1419 return -1;
1420
1421 *op_class = 81; /* 2.407 GHz, channels 1..13 */
1422 *channel = (freq - 2407) / 5;
1423 return 0;
1424 }
1425
1426 if (freq == 2484) {
1427 *op_class = 82; /* channel 14 */
1428 *channel = 14;
1429 return 0;
1430 }
1431
1432 if (freq >= 5180 && freq <= 5240) {
1433 if ((freq - 5000) % 5)
1434 return -1;
1435
1436 *op_class = 115; /* 5 GHz, channels 36..48 */
1437 *channel = (freq - 5000) / 5;
1438 return 0;
1439 }
1440
1441 if (freq >= 5260 && freq <= 5320) {
1442 *op_class = 118; /* 5 GHz, channels 52..64 */
1443 *channel = (freq - 5000) / 5;
1444 return 0;
1445 }
1446
1447 if (freq >= 5500 && freq <= 5700) {
1448 *op_class = 121; /* 5 GHz, channels 100..140 */
1449 *channel = (freq - 5000) / 5;
1450 return 0;
1451 }
1452
1453 if (freq >= 5745 && freq <= 5805) {
1454 if ((freq - 5000) % 5)
1455 return -1;
1456
1457 *op_class = 124; /* 5 GHz, channels 149..161 */
1458 *channel = (freq - 5000) / 5;
f3fa1980
S
1459 return 0;
1460 }
1461
c481cf08
JA
1462 if (freq >= 5825 && freq <= 5845) {
1463 *op_class = 125; /* 5 GHz, channels 149,153,157,161,165,169 */
1464 *channel = (freq - 5000) / 5;
1465 return 0;
1466 }
1467
1468 return -1;
f3fa1980
S
1469}
1470
c481cf08 1471static int p2p_wfd_sink_config_scc(struct wpa_supplicant *wpa_s, int scc, unsigned int oper_freq)
f3fa1980 1472{
c481cf08
JA
1473 int ret = 0;
1474 u8 op_reg_class = 0, op_channel = 0;
1475 unsigned int r;
1476 struct wpa_supplicant *iface;
1477 struct p2p_data *p2p = wpa_s->global->p2p;
1478 wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__);
1479 if (!p2p) {
1480 wpa_printf(MSG_DEBUG, "Not support p2p.");
1481 return ret;
1482 }
1483 if (scc && oper_freq) {
1484 priv_p2p_freq_to_channel(oper_freq, &op_reg_class, &op_channel);
1485 p2p->op_channel = op_channel;
1486 p2p->op_reg_class = op_reg_class;
1487 p2p->channels.reg_classes = 1;
1488 p2p->channels.reg_class[0].channels = 1;
1489 p2p->channels.reg_class[0].reg_class = op_reg_class;
1490 p2p->channels.reg_class[0].channel[0] = op_channel;
1491 wpa_printf(MSG_DEBUG, "Enable SCC in WFD sink mode class %d, channel %d",
1492 op_reg_class, op_channel);
1493 return ret;
1494 }
1495 /* Get back to MCC */
1496 wpa_printf(MSG_DEBUG, "Config MCC");
1497 if (wpa_s->conf->p2p_oper_reg_class &&
1498 wpa_s->conf->p2p_oper_channel) {
1499 p2p->op_reg_class = wpa_s->conf->p2p_oper_reg_class;
1500 p2p->op_channel = wpa_s->conf->p2p_oper_channel;
1501 p2p->cfg->cfg_op_channel = 1;
1502 } else {
1503 p2p->op_reg_class = 81;
1504 os_get_random((u8 *)&r, sizeof(r));
1505 p2p->op_channel = 1 + (r % 3) * 5;
1506 p2p->cfg->cfg_op_channel = 0;
1507 }
f3fa1980 1508
c481cf08
JA
1509 os_memcpy(&p2p->channels, &p2p->cfg->channels, sizeof(struct p2p_channels));
1510 return ret;
1511}
1512
1513
1514static int mtk_get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
1515 struct wpa_used_freq_data *freqs_data,
1516 unsigned int len)
1517{
1518 struct wpa_supplicant *ifs;
1519 u8 bssid[ETH_ALEN];
1520 int freq;
1521 unsigned int idx = 0, i;
1522
1523 wpa_dbg(wpa_s, MSG_DEBUG,
1524 "Determining shared radio frequencies (max len %u)", len);
1525 os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
1526
1527 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
1528 radio_list) {
1529 wpa_printf(MSG_DEBUG, "Get shared freqs ifname %s", ifs->ifname);
1530 if (idx == len)
1531 break;
1532
1533 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
1534 continue;
1535
1536 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
1537 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
1538 freq = ifs->current_ssid->frequency;
1539 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
1540 freq = ifs->assoc_freq;
1541 else
1542 continue;
1543
1544 /* Hold only distinct freqs */
1545 for (i = 0; i < idx; i++)
1546 if (freqs_data[i].freq == freq)
1547 break;
1548
1549 if (i == idx)
1550 freqs_data[idx++].freq = freq;
1551
1552 if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
1553 freqs_data[i].flags = ifs->current_ssid->p2p_group ?
1554 WPA_FREQ_USED_BY_P2P_CLIENT :
1555 WPA_FREQ_USED_BY_INFRA_STATION;
1556 }
f3fa1980 1557 }
c481cf08
JA
1558
1559 return idx;
1560}
1561
1562
1563static int mtk_get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
1564 int *freq_array, unsigned int len)
1565{
1566 struct wpa_used_freq_data *freqs_data;
1567 int num, i;
1568
1569 os_memset(freq_array, 0, sizeof(int) * len);
1570
1571 freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
1572 if (!freqs_data)
1573 return -1;
1574
1575 num = mtk_get_shared_radio_freqs_data(wpa_s, freqs_data, len);
1576 for (i = 0; i < num; i++)
1577 freq_array[i] = freqs_data[i].freq;
1578
1579 os_free(freqs_data);
1580
1581 return num;
f3fa1980 1582}
c481cf08 1583#endif
f3fa1980
S
1584
1585int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
1586 size_t buf_len )
1587{
1588 struct i802_bss *bss = priv;
1589 struct wpa_driver_nl80211_data *drv = bss->drv;
1590 struct ifreq ifr;
c481cf08 1591 android_wifi_priv_cmd priv_cmd;
f3fa1980
S
1592 struct wpa_supplicant *wpa_s;
1593 struct hostapd_data *hapd;
1594 int handled = 0;
1595 int cmd_len = 0;
1596 union wpa_event_data event;
1597 static int user_force_band = 0;
1598 int ret = -1;
1599
1600 if (drv == NULL) {
c481cf08 1601 wpa_printf(MSG_ERROR, "%s: drv is NULL, exit", __func__);
f3fa1980
S
1602 return -1;
1603 }
1604 if (drv->ctx == NULL) {
c481cf08 1605 wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL, exit", __func__);
f3fa1980
S
1606 return -1;
1607 }
1608
c481cf08 1609 if (bss->drv->nlmode == NL80211_IFTYPE_AP) {
f3fa1980
S
1610 hapd = (struct hostapd_data *)(drv->ctx);
1611 }
1612 else {
1613 wpa_s = (struct wpa_supplicant *)(drv->ctx);
1614 if (wpa_s->conf == NULL) {
c481cf08 1615 wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL, exit", __func__);
f3fa1980
S
1616 return -1;
1617 }
1618 }
1619
c481cf08 1620 wpa_printf(MSG_INFO, "%s: %s recv cmd %s", __func__, bss->ifname, cmd);
f3fa1980
S
1621 handled = 1;
1622
1623 if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) {
1624 int state;
1625 state = atoi(cmd + 10);
1626 wpa_printf(MSG_DEBUG, "POWERMODE=%d", state);
c481cf08
JA
1627 } else if (os_strncasecmp(cmd, "GET_STA_STATISTICS ", 19) == 0) {
1628 ret = wpa_driver_get_sta_statistics(wpa_s, cmd + 19, buf, buf_len);
f3fa1980
S
1629 } else if (os_strncmp(cmd, "MACADDR", os_strlen("MACADDR")) == 0) {
1630 u8 macaddr[ETH_ALEN] = {};
1631 os_memcpy(&macaddr, wpa_s->own_addr, ETH_ALEN);
1632 ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
1633 wpa_printf(MSG_DEBUG, "%s", buf);
c481cf08 1634 } else if(os_strncasecmp(cmd, "COUNTRY", os_strlen("COUNTRY")) == 0) {
f3fa1980
S
1635 if (os_strlen(cmd) != os_strlen("COUNTRY") + 3) {
1636 wpa_printf(MSG_DEBUG, "Ignore COUNTRY cmd %s", cmd);
1637 ret = 0;
1638 } else {
c481cf08
JA
1639 wpa_printf(MSG_INFO, "Set country: %s", cmd + 8);
1640 // ret = wpa_drv_set_country(wpa_s, cmd + 8);
1641 ret = wpa_driver_mediatek_set_country(priv, cmd + 8);
f3fa1980
S
1642 if (ret == 0) {
1643 wpa_printf(MSG_DEBUG, "Update channel list after country code changed");
c481cf08 1644 wpa_driver_notify_country_change(wpa_s->global, cmd);
f3fa1980
S
1645 }
1646 }
1647 } else if (os_strcasecmp(cmd, "start") == 0) {
c481cf08
JA
1648 if ((ret = linux_set_iface_flags(drv->global->ioctl_sock,
1649 drv->first_bss->ifname, 1))) {
f3fa1980
S
1650 wpa_printf(MSG_INFO, "nl80211: Could not set interface UP, ret=%d \n", ret);
1651 } else {
1652 wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STARTED");
1653 }
1654 } else if (os_strcasecmp(cmd, "stop") == 0) {
1655 if (drv->associated) {
1656 ret = wpa_drv_deauthenticate(wpa_s, drv->bssid, WLAN_REASON_DEAUTH_LEAVING);
1657 if (ret != 0)
1658 wpa_printf(MSG_DEBUG, "DRIVER-STOP error, ret=%d", ret);
1659 } else {
1660 wpa_printf(MSG_INFO, "nl80211: not associated, no need to deauthenticate \n");
1661 }
1662
c481cf08
JA
1663 if ((ret = linux_set_iface_flags(drv->global->ioctl_sock,
1664 drv->first_bss->ifname, 0))) {
f3fa1980
S
1665 wpa_printf(MSG_INFO, "nl80211: Could not set interface Down, ret=%d \n", ret);
1666 } else {
1667 wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STOPPED");
1668 }
1669 } else if (os_strncasecmp(cmd, "getpower", 8) == 0) {
c481cf08 1670 u32 mode = 0;
f3fa1980
S
1671 // ret = wpa_driver_wext_driver_get_power(drv, &mode);
1672 if (ret == 0) {
1673 ret = snprintf(buf, buf_len, "powermode = %u\n", mode);
1674 wpa_printf(MSG_DEBUG, "%s", buf);
1675 if (ret < (int)buf_len)
1676 return ret;
1677 }
c481cf08
JA
1678 } else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0) {
1679 u32 sw_cmd = 0x9F000000;
1680 u32 idx = 0;
1681 char *cp = cmd + 12;
1682 char *endp;
1683
1684 if (*cp != '\0') {
1685 idx = (u32)strtol(cp, &endp, 0);
1686 if (endp != cp) {
1687 idx += 0x00900200;
1688 wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
1689 ret = 0;
1690 }
f3fa1980 1691 }
c481cf08
JA
1692 } else if (os_strncasecmp(cmd, "rxfilter-remove", 15) == 0) {
1693 u32 sw_cmd = 0x9F000000;
1694 u32 idx = 0;
1695 char *cp = cmd + 15;
f3fa1980 1696 char *endp;
c481cf08 1697
f3fa1980 1698 if (*cp != '\0') {
c481cf08
JA
1699 idx = (u32)strtol(cp, &endp, 0);
1700 if (endp != cp) {
1701 idx += 0x00900300;
1702 wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
1703 ret = 0;
1704 }
f3fa1980 1705 }
c481cf08
JA
1706 } else if (os_strncasecmp(cmd, "rxfilter-stop", 13) == 0) {
1707 u32 sw_cmd = 0x9F000000;
1708 u32 idx = 0x00900000;
1709 wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
1710 ret = 0;
1711 } else if (os_strncasecmp(cmd, "rxfilter-start", 14) == 0) {
1712 u32 sw_cmd = 0x9F000000;
1713 u32 idx = 0x00900100;
1714 wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
1715 ret = 0;
f3fa1980
S
1716 } else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) {
1717 ret = 0; /* mt5921 linux driver not implement yet */
1718 } else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) {
1719 ret = 0; /* mt5921 linux driver not implement yet */
1720 } else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) {
1721 ret = 0; /* mt5921 linux driver not implement yet */
c481cf08
JA
1722#ifdef CONFIG_HOTSPOT_MGR_SUPPORT
1723 } else if (os_strncmp(cmd, "STA-BLOCK ", 10) == 0) {
1724 if (wpa_driver_sta_block(priv, cmd + 10)) {
1725 ret = -1;
1726 } else {
1727 ret = 0;
1728 }
1729 } else if (os_strncmp(cmd, "STA-UNBLOCK ", 12) == 0) {
1730 if (wpa_driver_sta_unblock(priv, cmd + 12)) {
1731 ret = -1;
1732 } else {
1733 ret = 0;
1734 }
1735 } else if (os_strncasecmp(cmd, "set_max_client ", 15) == 0) {
1736 wpa_driver_set_max_client(priv, cmd + 15, buf, buf_len);
1737#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */
1738#ifdef CONFIG_MTK_LTE_COEX
1739 } else if (os_strncmp(cmd, "MTK-ACS", 7) == 0) {
1740 u8 ch = wpa_driver_do_mtk_acs(priv);
1741 os_memcpy(buf, &ch, sizeof(u8));
1742 ret = sizeof(u8);
1743#endif /* CONFIG_MTK_LTE_COEX */
1744#ifdef CONFIG_WAPI_SUPPORT
1745 } else if (os_strncasecmp(cmd, "set-wapi-key", 12) == 0) {
1746 struct wapi_key_param_type {
1747 u8 *addr;
1748 int key_idx;
1749 int set_tx;
1750 u8 *seq;
1751 size_t seq_len;
1752 u8 *key;
1753 size_t key_len;
1754 } *wapi_key_param;
1755 wapi_key_param = (struct wapi_key_param_type*)buf;
1756
1757 ret = wpa_driver_nl80211_set_wapi_key(priv, (const u8*)wapi_key_param->addr,
1758 wapi_key_param->key_idx, wapi_key_param->set_tx,
1759 (const u8*)wapi_key_param->seq, wapi_key_param->seq_len,
1760 (const u8*)wapi_key_param->key, wapi_key_param->key_len);
1761 } else if (os_strncasecmp(cmd, "wapi-msg-send", 13) == 0) {
1762 struct wapi_msg_send_param_type {
1763 u8 *msg_in;
1764 int msg_in_len;
1765 u8 *msg_out;
1766 int *msg_out_len;
1767 } *wapi_msg_send_param;
1768 wapi_msg_send_param = (struct wapi_msg_send_param_type*)buf;
1769 ret = wpa_driver_nl80211_send_msg(priv, (const u8*)wapi_msg_send_param->msg_in,
1770 wapi_msg_send_param->msg_in_len, wapi_msg_send_param->msg_out,
1771 wapi_msg_send_param->msg_out_len);
1772#endif /* CONFIG_WAPI_SUPPORT */
1773#ifdef CONFIG_MTK_WFD_SINK
1774 } else if (os_strncmp(cmd, "p2p_get_cap ", os_strlen("p2p_get_cap ")) == 0) {
1775 struct p2p_data *p2p = wpa_s->global->p2p;
1776 if (p2p) {
1777 wpa_printf(MSG_DEBUG, "%s %d, %d ",
1778 __func__, __LINE__, p2p->dev_capab);
1779 ret = p2p_get_capability(wpa_s, cmd + os_strlen("p2p_get_cap "),
1780 buf, buf_len);
1781 }
1782 } else if (os_strncmp(cmd, "p2p_set_cap ", os_strlen("p2p_set_cap ")) == 0) {
1783 struct p2p_data *p2p = wpa_s->global->p2p;
1784 if (p2p) {
1785 wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__);
1786 ret = p2p_set_capability(wpa_s, cmd + os_strlen("p2p_set_cap "),
1787 buf, buf_len);
1788 }
1789 } else if (os_strncmp(cmd, "MIRACAST ", os_strlen("MIRACAST ")) == 0) {
1790 unsigned char miracast = atoi(cmd + os_strlen("MIRACAST "));
1791 char *pos = os_strstr(cmd, " freq=");
1792 unsigned int freq = 0;
1793 int num;
1794 wpa_printf(MSG_DEBUG, "MIRACAST %d", miracast);
1795 switch (miracast) {
1796 case 0:
1797 case 1:
1798 num = mtk_get_shared_radio_freqs(wpa_s, &freq, 1);
1799 if (num > 0 && freq > 0) {
1800 wpa_printf(MSG_DEBUG, "AIS connected %d", freq);
1801 p2p_wfd_sink_config_scc(wpa_s, 1, freq);
1802 } else
1803 p2p_wfd_sink_config_scc(wpa_s, 0, 0);
1804 handled = 0; /* DRIVER MIRACAST used as private cmd*/
1805 break;
1806 case 2:
1807 if (pos) {
1808 pos += 6;
1809 freq = atoi(pos);
1810 wpa_printf(MSG_DEBUG, "MIRACAST freq %d", freq);
1811 p2p_wfd_sink_config_scc(wpa_s, 1, freq);
1812 /* rebuild DRIVER MIRACAST 2 cmd */
1813 os_memset(cmd, 0, os_strlen(cmd));
1814 os_memcpy(cmd, "MIRACAST 2", os_strlen("MIRACAST 2"));
1815 } else {
1816 num = mtk_get_shared_radio_freqs(wpa_s, &freq, 1);
1817 if (num > 0 && freq > 0) {
1818 wpa_printf(MSG_DEBUG, "AIS connected %d", freq);
1819 p2p_wfd_sink_config_scc(wpa_s, 1, freq);
1820 } else
1821 p2p_wfd_sink_config_scc(wpa_s, 0, 0);
1822 }
1823
1824 handled = 0; /* DRIVER MIRACAST used as private cmd*/
1825
1826 break;
1827 default:
1828 wpa_printf(MSG_DEBUG, "Unknown MIRACAST value %d", miracast);
1829 handled = 0; /* DRIVER MIRACAST used as private cmd*/
1830 break;
1831 }
1832 } else if (os_strncasecmp(cmd, "p2p_use_mcc=", os_strlen("p2p_use_mcc=")) == 0) {
1833 unsigned char use_mcc = atoi(cmd + os_strlen("p2p_use_mcc="));
1834 wpa_printf(MSG_DEBUG, "p2p_use_mcc %d", use_mcc);
1835 // MCC/SCC should be determined by GO negotation
1836 // wpa_s->global->p2p->p2p_use_mcc = use_mcc;
1837 if (use_mcc) {
1838 wpa_printf(MSG_DEBUG, "SCC_MCC, config MCC");
1839 p2p_wfd_sink_config_scc(wpa_s, 0, 0);
1840 } else {
1841 int shared_freq;
1842 int num = 0;
1843 wpa_printf(MSG_DEBUG, "use_mcc=0");
1844 num = mtk_get_shared_radio_freqs(wpa_s, &shared_freq, 1);
1845 if (num > 0 && shared_freq > 0) {
1846 wpa_printf(MSG_DEBUG, "p2p disconnected, AIS connected %d", shared_freq);
1847 p2p_wfd_sink_config_scc(wpa_s, 1, shared_freq);
1848 } else
1849 p2p_wfd_sink_config_scc(wpa_s, 0, 0);
1850 }
1851 } else if (os_strncmp(cmd, "wfd_data_update", os_strlen("wfd_data_update")) == 0) {
1852 wpa_printf(MSG_DEBUG, "CONFIG_MTK_P2P: Update wfd_data");
1853 ret = wpas_wfd_data_update(wpa_s, (struct wfd_data_s *)buf);
1854#endif
1855#ifdef CONFIG_MTK_P2P_SIGMA
1856 } else if (os_strncasecmp(cmd, "mcc", 3) == 0) {
1857 if (wpa_s->drv_priv) {
1858 int mcc = 0;
1859 char *value = NULL;
1860 value = os_strchr(cmd, ' ');
1861 if (value == NULL)
1862 return -1;
1863 *value++ = '\0';
1864 struct wpa_supplicant *_wpa_s;
1865 mcc = atoi(value);
1866 if (mcc) {
1867 for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) {
1868
1869 /*
1870 * 2 is appropriate?
1871 * just legacy wifi vs p2p wifi?
1872 */
1873 _wpa_s->num_multichan_concurrent = 2;
1874 _wpa_s->drv_flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
1875 if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg)
1876 _wpa_s->global->p2p->cfg->concurrent_operations = 1;
1877 }
1878 } else {
1879 for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) {
1880
1881 /*
1882 * assign as 0 beacause our driver will
1883 * not report iface_combination to supplicant
1884 */
1885 _wpa_s->num_multichan_concurrent = 0;
1886 _wpa_s->drv_flags &= ~WPA_DRIVER_FLAGS_P2P_CONCURRENT;
1887 if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg)
1888 _wpa_s->global->p2p->cfg->concurrent_operations = 0;
1889 }
1890 }
1891
1892 wpa_printf(MSG_DEBUG, "mcc = %d", mcc);
1893 ret = 0;
1894 }
1895 } else if (os_strncmp(cmd, "p2p_set_opps ", 13) == 0) {
1896 ret = p2p_ctrl_iface_set_opps(wpa_s, cmd + 13, buf, buf_len);
1897 } else if (os_strncmp(cmd, "p2p_set_power_save ", 19) == 0) {
1898 ret = p2p_ctrl_iface_set_power_save(wpa_s, cmd + 19, buf, buf_len);
1899 } else if (os_strncmp(cmd, "p2p_set_sleep ", 14) == 0) {
1900 ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd + 14, buf, buf_len);
1901 } else if (os_strncmp(cmd, "p2p_set_sleep", 13) == 0) {
1902 char cmd2[] = {"ff:ff:ff:ff:ff:ff \"\""};
1903 ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd2, buf, buf_len);
1904 } else if (os_strncasecmp(cmd, "sigma_mode", 10) == 0) {
1905 int sigma = 0;
1906 char *value = NULL;
1907 value = os_strchr(cmd, ' ');
1908 if (value == NULL)
1909 return -1;
1910 *value++ = '\0';
1911 sigma = atoi(value);
1912 wpa_printf(MSG_DEBUG, "p2p: sigma: set mode %d", sigma);
1913 // we should not have workaround for sigma programs
1914 // wpa_s->global->p2p->sigma_mode = sigma;
1915 ret = 0;
1916#endif /* CONFIG_MTK_P2P_SIGMA */
1917 } else if (os_strncmp(cmd, "P2P_SET_NOA", os_strlen("P2P_SET_NOA")) == 0) {
1918 ret = p2p_ctrl_iface_set_noa(wpa_s, cmd, buf, buf_len);
1919 } else if (os_strncmp(cmd, "P2P_SET_PS", os_strlen("P2P_SET_PS")) == 0) {
1920 ret = p2p_ctrl_iface_set_ps(wpa_s, cmd, buf, buf_len);
1921 } else if (os_strncasecmp(cmd, "SETSUSPENDMODE ", 15) == 0) {
1922 struct wpa_driver_suspendmode_params params;
1923 params.hdr.index = NL80211_TESTMODE_SUSPEND;
1924 params.hdr.index = params.hdr.index | (0x01 << 24);
1925 params.hdr.buflen = sizeof(params);
1926 params.suspend = *(cmd+15)-'0';
1927 wpa_driver_nl80211_testmode(priv, (u8* )&params, sizeof(params));
1928 handled = 0; /* 6630 driver handled this command in driver, so give a chance to 6630 driver */
1929 }else if(os_strncasecmp(cmd, "mtk_rx_packet_filter ", 21) == 0) {
1930 char buf[9] = {0}, *errChar = NULL;
1931 char *pos = NULL;
1932 /* mtk_rx_packet_filter 00000000000000FE 0000000000000000 0000000000000000 */
1933 struct wpa_driver_rx_filter_params params;
1934 params.hdr.index = NL80211_TESTMODE_RXFILTER;
1935 params.hdr.index = params.hdr.index | (0x01 << 24);
1936 params.hdr.buflen = sizeof(params);
1937
1938 pos = cmd;
1939 pos = pos + 21;
1940 if (pos == NULL || strlen(cmd) != 71 ) {
1941 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter] Error! \n");
1942 return -1;
1943 }
1944
1945 os_memcpy(buf,pos,8);
1946 buf[8] = '\0';
1947 params.Ipv4FilterHigh = strtol(buf,&errChar,16);
1948 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv4FilterHigh (0x%08x),errChar [%p]\n", params.Ipv4FilterHigh,errChar);
1949
1950 pos = pos + 8;
1951 os_memcpy(buf,pos,8);
1952 buf[8] = '\0';
1953 params.Ipv4FilterLow = strtol(buf,&errChar,16);
1954 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv4FilterLow (0x%08x),errChar [%p]\n", params.Ipv4FilterLow,errChar);
1955
1956 pos = pos + 9;
1957 os_memcpy(buf,pos,8);
1958 buf[8] = '\0';
1959 params.Ipv6FilterHigh = strtol(buf,&errChar,16);
1960 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv6FilterHigh (0x%08x),errChar [%p]\n", params.Ipv6FilterHigh,errChar);
1961
1962 pos = pos + 8;
1963 os_memcpy(buf,pos,8);
1964 buf[8] = '\0';
1965 params.Ipv6FilterLow = strtol(buf,&errChar,16);
1966 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv6FilterLow (0x%08x),errChar [%p]\n", params.Ipv6FilterLow,errChar);
1967
1968 pos = pos + 9;
1969 os_memcpy(buf,pos,8);
1970 buf[8] = '\0';
1971 params.SnapFilterHigh = strtol(buf,&errChar,16);
1972 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.SnapFilterHigh (0x%08x),errChar [%p]\n", params.SnapFilterHigh,errChar);
1973
1974 pos = pos + 8;
1975 os_memcpy(buf,pos,8);
1976 buf[8] = '\0';
1977 params.SnapFilterLow = strtol(buf,&errChar,16);
1978 wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.SnapFilterLow (0x%08x),errChar [%p]\n", params.SnapFilterLow,errChar);
1979
1980 ret = wpa_driver_nl80211_testmode(priv, (u8 *)&params, sizeof(params));
f3fa1980 1981 } else {
c481cf08
JA
1982 u8 buffer[100];
1983 struct wpa_driver_test_mode_info *params = (struct wpa_driver_test_mode_info *)buffer;
1984 params->index = NL80211_TESTMODE_STR_CMD | (0x01 << 24);
1985 params->buflen = sizeof(*params) + strlen(cmd);
1986 strncpy((char*)(params+1), cmd, sizeof(buffer)-sizeof(*params));
1987 ret = wpa_driver_nl80211_testmode(priv, buffer, params->buflen);
f3fa1980 1988 handled = 0;
c481cf08 1989 wpa_printf(MSG_INFO, "Transparent command for driver nl80211, ret=%d", ret);
f3fa1980
S
1990 }
1991
c481cf08
JA
1992 if (handled == 0) {
1993 cmd_len = strlen(cmd);
1994
1995 memset(&ifr, 0, sizeof(ifr));
1996 memset(&priv_cmd, 0, sizeof(priv_cmd));
1997 memset(buf, 0, buf_len);
1998 strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
1999 ifr.ifr_name[IFNAMSIZ - 1] = '\0';
2000
2001 if (cmd_len >= PRIV_CMD_SIZE) {
2002 wpa_printf(MSG_INFO, "%s: cmd: %s overflow",
2003 __func__, cmd);
2004 cmd_len = PRIV_CMD_SIZE - 1;
2005 }
2006
2007 memcpy(priv_cmd.buf, cmd, cmd_len + 1);
2008 priv_cmd.used_len = cmd_len + 1;
2009 priv_cmd.total_len = PRIV_CMD_SIZE;
2010 ifr.ifr_data = &priv_cmd;
2011
2012 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
2013 if (ret < 0) {
2014 wpa_printf(MSG_ERROR, "%s: failed to issue private commands,"
2015 " error msg: %s\n", __func__, strerror(errno));
2016 wpa_driver_send_hang_msg(drv);
2017 ret = snprintf(buf, buf_len, "%s\n", "FAIL");
2018 } else {
2019
2020 wpa_printf(MSG_INFO, "%s: ret = %d used = %u total = %u",
2021 __func__, ret , priv_cmd.used_len, priv_cmd.total_len);
2022
2023 drv_errors = 0;
2024 ret = 0;
2025 if ((os_strncasecmp(cmd, "WLS_BATCHING", 12) == 0))
2026 ret = strlen(buf);
2027 /*
2028 * There no need to call wpa_supplicant_event func
2029 * on which the cmd is SETBAND
2030 */
2031 if (os_strncasecmp(cmd, "SETBAND", 7) == 0) {
2032 /*
2033 * wpa_supplicant_event(drv->ctx,
2034 * EVENT_CHANNEL_LIST_CHANGED, NULL);
2035 */
2036 wpa_printf(MSG_INFO, "%s: Unsupported command SETBAND\n", __func__);
2037 }
2038 }
2039 } /* handled == 0 */
2040
f3fa1980
S
2041 return ret;
2042}
2043
2044int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
2045{
c481cf08 2046 char buf[MAX_DRV_CMD_SIZE];
f3fa1980
S
2047 struct i802_bss *bss = priv;
2048 struct wpa_driver_nl80211_data *drv = bss->drv;
2049
c481cf08
JA
2050 wpa_printf(MSG_DEBUG, "iface %s P2P_SET_NOA %d %d %d", bss->ifname, count, start, duration);
2051 snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration);
2052 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1);
f3fa1980
S
2053}
2054
2055int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
2056{
2057 struct i802_bss *bss = priv;
2058 struct wpa_driver_nl80211_data *drv = bss->drv;
2059
2060 wpa_printf(MSG_DEBUG, "iface %s P2P_GET_NOA, ignored", bss->ifname);
2061 return -1;
2062}
2063
2064int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
2065{
c481cf08 2066 char buf[MAX_DRV_CMD_SIZE];
f3fa1980
S
2067 struct i802_bss *bss = priv;
2068 struct wpa_driver_nl80211_data *drv = bss->drv;
2069
c481cf08
JA
2070 wpa_printf(MSG_DEBUG, "iface %s P2P_SET_PS %d %d %d", bss->ifname, legacy_ps, opp_ps, ctwindow);
2071 snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow);
2072 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1);
f3fa1980
S
2073}
2074
2075int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
2076 const struct wpabuf *proberesp,
2077 const struct wpabuf *assocresp)
2078{
2079 struct i802_bss *bss = priv;
2080 struct wpa_driver_nl80211_data *drv = bss->drv;
2081
2082 wpa_printf(MSG_DEBUG, "iface %s set_ap_wps_p2p_ie, ignored", bss->ifname);
2083 return 0;
2084}
2085