1 /*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 *
4 * This software may be distributed under the terms of the BSD license.
5 * See README for more details.
6 */
7 #include "includes.h"
8 #include "driver_nl80211_hisi.h"
9 #include "driver_nl80211.h"
10 #include "wpa_supplicant_i.h"
11 #include "config.h"
12 #include "android_drv.h"
13 #include "securec.h"
14
15 #if defined(HISI_CONNECTIVITY_PATCH) && defined(HISI_MIRACAST_SINK_OPT)
16 #include "hisi_miracast_sink.h"
17 #endif
18
19 #define WPA_PS_ENABLED 0
20 #define WPA_PS_DISABLED 1
21
22 int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg,
23 int (*valid_handler)(struct nl_msg *, void *),
24 void *valid_data);
25
26 static int drv_errors = 0;
27
wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data * drv)28 static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
29 {
30 drv_errors++;
31 if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
32 drv_errors = 0;
33 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
34 }
35 }
36
wpa_driver_set_power_save(void * priv,int state)37 static int wpa_driver_set_power_save(void *priv, int state)
38 {
39 struct i802_bss *bss = priv;
40 struct wpa_driver_nl80211_data *drv = bss->drv;
41 struct nl_msg *msg;
42 int ret = -1;
43 enum nl80211_ps_state ps_state;
44
45 msg = nlmsg_alloc();
46 if (!msg)
47 return -1;
48
49 genlmsg_put(msg, 0, 0, drv->global->nl80211_id, 0, 0,
50 NL80211_CMD_SET_POWER_SAVE, 0);
51
52 if (state == WPA_PS_ENABLED)
53 ps_state = NL80211_PS_ENABLED;
54 else
55 ps_state = NL80211_PS_DISABLED;
56
57 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
58 NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state);
59
60 ret = send_and_recv_msgs(drv, msg, NULL, NULL);
61 msg = NULL;
62 if (ret < 0)
63 wpa_printf(MSG_ERROR, "nl80211: Set power mode fail: %d", ret);
64 nla_put_failure:
65 nlmsg_free(msg);
66 return ret;
67 }
68
get_power_mode_handler(struct nl_msg * msg,void * arg)69 static int get_power_mode_handler(struct nl_msg *msg, void *arg)
70 {
71 struct nlattr *tb[NL80211_ATTR_MAX + 1];
72 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
73 int *state = (int *)arg;
74
75 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
76 genlmsg_attrlen(gnlh, 0), NULL);
77
78 if (!tb[NL80211_ATTR_PS_STATE])
79 return NL_SKIP;
80
81 if (state) {
82 *state = (int)nla_get_u32(tb[NL80211_ATTR_PS_STATE]);
83 wpa_printf(MSG_DEBUG, "nl80211: Get power mode = %d", *state);
84 *state = (*state == NL80211_PS_ENABLED) ?
85 WPA_PS_ENABLED : WPA_PS_DISABLED;
86 }
87
88 return NL_SKIP;
89 }
90
wpa_driver_get_power_save(void * priv,int * state)91 static int wpa_driver_get_power_save(void *priv, int *state)
92 {
93 struct i802_bss *bss = priv;
94 struct wpa_driver_nl80211_data *drv = bss->drv;
95 struct nl_msg *msg;
96 int ret = -1;
97
98 msg = nlmsg_alloc();
99 if (!msg)
100 return -1;
101
102 genlmsg_put(msg, 0, 0, drv->global->nl80211_id, 0, 0,
103 NL80211_CMD_GET_POWER_SAVE, 0);
104
105 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
106
107 ret = send_and_recv_msgs(drv, msg, get_power_mode_handler, state);
108 msg = NULL;
109 if (ret < 0)
110 wpa_printf(MSG_ERROR, "nl80211: Get power mode fail: %d", ret);
111 nla_put_failure:
112 nlmsg_free(msg);
113 return ret;
114 }
115
116 int g_is_jp = 0;
wpa_driver_nl80211_driver_cmd(void * priv,char * cmd,char * buf,size_t buf_len)117 int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, size_t buf_len )
118 {
119 struct i802_bss *bss = priv;
120 struct wpa_driver_nl80211_data *drv = bss->drv;
121 struct ifreq ifr;
122 int ret = 0;
123 int ret_s;
124
125 wpa_printf(MSG_ERROR, "wpa_driver_nl80211_driver_cmd:cmd = %s", cmd);
126 if (os_strcasecmp(cmd, "STOP") == 0)
127 {
128 linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 0);
129 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED");
130 }
131 else if (os_strcasecmp(cmd, "START") == 0)
132 {
133 linux_set_iface_flags(drv->global->ioctl_sock, bss->ifname, 1);
134 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED");
135 }
136 else if (os_strcasecmp(cmd, "MACADDR") == 0)
137 {
138 u8 macaddr[ETH_ALEN] = {};
139
140 ret = linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, macaddr);
141 if (!ret)
142 {
143 ret_s = snprintf_s(buf, buf_len, buf_len - 1,
144 "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
145 if (ret_s == -1) {
146 wpa_printf(MSG_ERROR, "%s:%d, snprintf failed, ret=%d", __func__, __LINE__, ret_s);
147 }
148 }
149 }
150 else if (os_strcasecmp(cmd, "RELOAD") == 0)
151 {
152 wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
153 }
154 else if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0)
155 {
156 int state;
157
158 state = atoi(cmd + 10);
159 ret = wpa_driver_set_power_save(priv, state);
160 if (ret < 0)
161 {
162 wpa_driver_send_hang_msg(drv);
163 }
164 else
165 {
166 drv_errors = 0;
167 }
168 }
169 else if (os_strncasecmp(cmd, "GETPOWER", 8) == 0)
170 {
171 int state = -1;
172
173 ret = wpa_driver_get_power_save(priv, &state);
174 if (!ret && (state != -1))
175 {
176 ret_s = snprintf_s(buf, buf_len, buf_len - 1, "POWERMODE = %d\n", state);
177 if (ret_s == -1) {
178 wpa_printf(MSG_ERROR, "%s:%d, snprintf failed, ret=%d", __func__, __LINE__, ret_s);
179 }
180 drv_errors = 0;
181 }
182 else
183 {
184 wpa_driver_send_hang_msg(drv);
185 }
186 }
187 else
188 {
189 /* Use private command */
190 wifi_priv_cmd priv_cmd = {0};
191 uint32 ret_len = 0;
192 size_t buf_len_tmp;
193
194 if (buf_len > MAX_PRIV_CMD_SIZE || strlen(cmd) >= MAX_PRIV_CMD_SIZE)
195 {
196 wpa_printf(MSG_ERROR, "%s: too long priavte command, strlen(cmd)=%zu buf_len=%zu", __func__, strlen(cmd), buf_len);
197 return -1;
198 }
199 buf_len_tmp = buf_len;
200 if (MAX_PRIV_CMD_SIZE == buf_len)
201 {
202 buf_len = strlen(cmd); /* default driver xxx cmd */
203 }
204
205 /* Hisi private data structure cmd should use buf_len, rather than strlen(cmd) */
206 ret_s = memcpy_s(buf, buf_len_tmp, cmd, buf_len);
207 if (ret_s != EOK) {
208 wpa_printf(MSG_ERROR, "%s:%d, memcpy failed, ret=%d", __func__, __LINE__, ret_s);
209 }
210
211 ret_s = memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr));
212 if (ret_s != EOK) {
213 wpa_printf(MSG_ERROR, "%s:%d, memset failed, ret=%d", __func__, __LINE__, ret_s);
214 }
215
216 ret_s = memcpy_s(priv_cmd.buf, MAX_PRIV_CMD_SIZE, buf, buf_len);
217 if (ret_s != EOK) {
218 wpa_printf(MSG_ERROR, "%s:%d, memcpy failed, ret=%d", __func__, __LINE__, ret_s);
219 }
220
221 priv_cmd.total_len = buf_len; /* MAX_PRIV_CMD_SIZE */
222 priv_cmd.used_len = buf_len; /* strlen(cmd) */
223
224 ifr.ifr_data = (void *)&priv_cmd;
225 os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
226
227 wpa_printf(MSG_EXCESSIVE, "%s: 1:ifr_name=%s, len=%zu, buf_len=%zu", __func__, ifr.ifr_name, strlen(buf), buf_len);
228
229 ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
230 if (ret < 0)
231 {
232 wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__);
233 wpa_driver_send_hang_msg(drv);
234 }
235 else
236 {
237 drv_errors = 0;
238 ret_len = os_strlen(priv_cmd.buf);
239 ret_len = (ret_len < MAX_PRIV_CMD_SIZE) ? ret_len : (MAX_PRIV_CMD_SIZE - 1);
240 /* SET Command return 0 which means OK, GET Command return string length */
241 if (os_strncasecmp(buf, priv_cmd.buf, ret_len) != 0)
242 {
243 ret = ret_len;
244 }
245 ret_s = memset_s(buf, buf_len, 0, buf_len);
246 if (ret_s != EOK) {
247 wpa_printf(MSG_ERROR, "%s:%d, memset failed, ret=%d", __func__, __LINE__, ret_s);
248 }
249
250 ret_s = memcpy_s(buf, buf_len, priv_cmd.buf, ret_len); /* copy kernel space return string to user space */
251 if (ret_s != EOK) {
252 wpa_printf(MSG_ERROR, "%s:%d, memcpy failed, ret=%d", __func__, __LINE__, ret_s);
253 }
254 buf[ret_len] = '\0';
255
256 if (os_strncasecmp(cmd, "COUNTRY", 7) == 0)
257 {
258 union wpa_event_data event = {0};
259 g_is_jp = (os_strncasecmp(cmd + 8, "JP", 2) == 0) ? 1 : 0 ;
260
261 event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
262 event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
263 wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &event);
264
265 wpa_printf(MSG_DEBUG, "%s:set country code end. len=%zu, ret_len=%d ret=%d", __func__, strlen(buf), ret_len, ret);
266 return ret;
267 }
268 #ifdef HISI_MIRACAST_SINK_OPT
269 hisi_miracast_sink_log("%s:%.15s len=%zu, ret_len=%d ret=%d", __func__, buf, strlen(buf), ret_len, ret);
270 #else
271 #ifdef HW_WPA_REDUCE_LOG
272 wpa_printf(MSG_EXCESSIVE, "%s:%.15s len=%zu, ret_len=%d ret=%d", __func__, buf, strlen(buf), ret_len, ret);
273 #else
274 wpa_printf(MSG_DEBUG, "%s:%.15s len=%zu, ret_len=%d ret=%d", __func__, buf, strlen(buf), ret_len, ret);
275 #endif
276 #endif
277 }
278 }
279 return ret;
280 }
281
wpa_driver_set_p2p_noa(void * priv,u8 count,int start,int duration)282 int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
283 {
284 char buf[MAX_DRV_CMD_SIZE] = {0};
285 char *pbuf;
286 oal_p2p_noa_param_stru *pst_p2p_noa = NULL;
287 char *_cmd = "P2P_SET_NOA";
288 int ret_s;
289
290 wpa_printf(MSG_ERROR, "%s: Entry", __func__);
291 pbuf = buf;
292 ret_s = sprintf_s(pbuf, MAX_DRV_CMD_SIZE, "%s", _cmd);
293 if (ret_s == -1) {
294 wpa_printf(MSG_ERROR, "%s:%d, sprintf failed, ret=%d", __func__, __LINE__, ret_s);
295 }
296 pbuf += ret_s;
297 *pbuf++ = '\0';
298 pst_p2p_noa = (oal_p2p_noa_param_stru *)pbuf;
299 pst_p2p_noa->uc_count = count;
300 pst_p2p_noa->ul_duration= duration;
301 pst_p2p_noa->ul_start_time= start;
302
303 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(_cmd) + 1 + sizeof(oal_p2p_noa_param_stru));
304
305 }
306
wpa_driver_get_p2p_noa(void * priv,u8 * buf,size_t len)307 int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
308 {
309 /* Return 0 till we handle p2p_presence request completely in the device side */
310 return 0;
311 }
312
wpa_driver_set_p2p_ps(void * priv,int legacy_ps,int opp_ps,int ctwindow)313 int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
314 {
315 char buf[MAX_DRV_CMD_SIZE] = {0};
316 char *pbuf;
317 oal_p2p_ops_param_stru *pst_p2p_ops = NULL;
318 char *_cmd = "P2P_SET_PS";
319 int ret_s;
320
321 wpa_printf(MSG_ERROR, "%s: Entry", __func__);
322 pbuf = buf;
323 ret_s = sprintf_s(pbuf, MAX_DRV_CMD_SIZE, "%s", _cmd);
324 if (ret_s == -1) {
325 wpa_printf(MSG_ERROR, "%s:%d, sprintf failed, ret=%d", __func__, __LINE__, ret_s);
326 }
327 pbuf += ret_s;
328 *pbuf++ = '\0';
329 pst_p2p_ops = (oal_p2p_ops_param_stru *)pbuf;
330 pst_p2p_ops->en_ops_ctrl = opp_ps;
331 pst_p2p_ops->uc_ct_window = ctwindow;
332
333 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(_cmd) + 1 + sizeof(oal_p2p_ops_param_stru));
334 }
335
wpa_driver_set_ap_wps_p2p_ie(void * priv,const struct wpabuf * beacon,const struct wpabuf * proberesp,const struct wpabuf * assocresp)336 int wpa_driver_set_ap_wps_p2p_ie(void *priv,
337 const struct wpabuf *beacon,
338 const struct wpabuf *proberesp,
339 const struct wpabuf *assocresp)
340 {
341 char buf[MAX_WPSP2PIE_CMD_SIZE] = {0};
342 struct wpabuf *ap_wps_p2p_ie = NULL;
343 char *_cmd = "SET_AP_WPS_P2P_IE";
344 char *pbuf;
345 int ret = 0;
346 int i;
347 int ret_s;
348 oal_app_ie_stru *pst_app_ie = NULL;
349 struct cmd_desc {
350 int cmd;
351 const struct wpabuf *src;
352 } cmd_arr[] = {
353 {0x0, beacon},
354 {0x2, proberesp},
355 {0x4, assocresp},
356 {-1, NULL}
357 };
358
359 wpa_printf(MSG_ERROR, "%s: Entry", __func__);
360 for (i = 0; cmd_arr[i].cmd != -1; i++) {
361 ret_s = memset_s(buf, sizeof(buf), 0, sizeof(buf));
362 if (ret_s != EOK) {
363 wpa_printf(MSG_ERROR, "%s:%d, memset failed, ret=%d", __func__, __LINE__, ret_s);
364 }
365 pbuf = buf;
366 ret_s = sprintf_s(pbuf, MAX_WPSP2PIE_CMD_SIZE, "%s", _cmd);
367 if (ret_s == -1) {
368 wpa_printf(MSG_ERROR, "%s:%d, memset failed, ret=%d", __func__, __LINE__, ret_s);
369 }
370 pbuf += ret_s;
371 *pbuf++ = '\0';
372 ap_wps_p2p_ie = cmd_arr[i].src ?
373 wpabuf_dup(cmd_arr[i].src) : NULL;
374 if (ap_wps_p2p_ie) {
375 if (wpabuf_len(ap_wps_p2p_ie) > WLAN_WPS_IE_MAX_SIZE)
376 {
377 wpa_printf(MSG_ERROR, "%s: app ie too large to wifi driver buffer.app_ie_len %d, auc_ie len %ul",
378 __func__, (int)wpabuf_len(ap_wps_p2p_ie), WLAN_WPS_IE_MAX_SIZE);
379 wpabuf_free(ap_wps_p2p_ie);
380 return -1;
381 }
382
383 pst_app_ie = (oal_app_ie_stru *)pbuf;
384 pst_app_ie->en_app_ie_type = cmd_arr[i].cmd;
385 pst_app_ie->ul_ie_len = wpabuf_len(ap_wps_p2p_ie);
386
387 ret_s = memcpy_s(pst_app_ie->auc_ie, sizeof(pst_app_ie->auc_ie), wpabuf_head(ap_wps_p2p_ie), wpabuf_len(ap_wps_p2p_ie));
388 if (ret_s != EOK) {
389 wpa_printf(MSG_ERROR, "%s:%d, memcpy failed, ret=%d", __func__, __LINE__, ret_s);
390 }
391 #if defined(HISI_CONNECTIVITY_PATCH) && defined(HISI_MIRACAST_SINK_OPT)
392 hisi_miracast_sink_log("cmd:%s, type %d, ie_len %d\r\n",
393 _cmd,
394 pst_app_ie->en_app_ie_type,
395 pst_app_ie->ul_ie_len);
396 #else
397 #ifdef HW_WPA_REDUCE_LOG
398 wpa_printf(MSG_EXCESSIVE, "cmd:%s, type %d, ie_len %d\r\n",
399 _cmd,
400 pst_app_ie->en_app_ie_type,
401 pst_app_ie->ul_ie_len);
402 #else
403 wpa_printf(MSG_DEBUG, "cmd:%s, type %d, ie_len %d\r\n",
404 _cmd,
405 pst_app_ie->en_app_ie_type,
406 pst_app_ie->ul_ie_len);
407 #endif /* HW_WPA_REDUCE_LOG */
408 #endif
409 wpa_printf(MSG_EXCESSIVE, "ie %p\r\n",
410 pst_app_ie->auc_ie);
411
412 wpa_hexdump(MSG_EXCESSIVE, "P2P: set p2p wps ie", (const char *)pbuf, pst_app_ie->ul_ie_len + 8);
413
414 if (strlen(_cmd) + sizeof(oal_app_ie_stru) + 1 < sizeof(buf))
415 {
416 ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf,
417 strlen(_cmd) + sizeof(oal_app_ie_stru) + 1);
418 }
419 else
420 {
421 wpa_printf(MSG_ERROR, "%s:error.app total length to large!, cmd_len = %zu, buffer = %d", __func__, strlen(_cmd) + sizeof(oal_app_ie_stru) + 1, (int)sizeof(buf));
422 ret = -1;
423 }
424 wpabuf_free(ap_wps_p2p_ie);
425 if (ret < 0)
426 break;
427 }
428 }
429 return ret;
430 }
431
wpa_driver_set_power_on(void * priv,int on)432 int wpa_driver_set_power_on(void *priv, int on)
433 {
434 char buf[MAX_PRIV_CMD_SIZE] = {0};
435 char *pbuf;
436 char *_cmd = "SET_POWER_ON";
437 int ret_s;
438
439 wpa_printf(MSG_DEBUG, "%s: Entry,power flag:%d", __func__, on);
440 pbuf = buf;
441 ret_s = sprintf_s(pbuf, MAX_PRIV_CMD_SIZE, "%s %d", _cmd, on);
442 if (ret_s == -1) {
443 wpa_printf(MSG_ERROR, "%s:%d, sprintf failed, ret=%d", __func__, __LINE__, ret_s);
444 }
445 wpa_printf(MSG_DEBUG, "%s:buf is %s", __func__, buf);
446
447 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf));
448 }
449
wpa_driver_set_powermgmt_on(void * priv,int powermgmt_on)450 int wpa_driver_set_powermgmt_on(void *priv, int powermgmt_on)
451 {
452 char buf[MAX_PRIV_CMD_SIZE] = {0};
453 char *pbuf;
454 char *_cmd = "SET_POWER_MGMT_ON";
455 int ret_s;
456
457 wpa_printf(MSG_DEBUG, "%s: Entry,power mgmt flag:%d", __func__, powermgmt_on);
458 pbuf = buf;
459 ret_s = sprintf_s(pbuf, MAX_PRIV_CMD_SIZE, "%s %d", _cmd, powermgmt_on);
460 if (ret_s == -1) {
461 wpa_printf(MSG_ERROR, "%s:%d, sprintf failed, ret=%d", __func__, __LINE__, ret_s);
462 }
463 wpa_printf(MSG_DEBUG, "%s:buf is %s", __func__, buf);
464
465 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf));
466 }
467
wpa_driver_set_qos_map(void * priv,const u8 * qos_map_set,u8 qos_map_set_len)468 int wpa_driver_set_qos_map(void *priv, const u8 *qos_map_set,
469 u8 qos_map_set_len)
470 {
471 char buf[MAX_DRV_CMD_SIZE] = {0};
472 char *pbuf;
473 int i, up_start;
474 int ret = 0;
475 int ret_s;
476 oal_qos_map_param_stru *pst_qos_map = NULL;
477 char *_cmd = "SET_QOS_MAP";
478
479 if (qos_map_set_len < 16 || qos_map_set_len > 58 || qos_map_set_len & 1)
480 {
481 wpa_printf(MSG_ERROR, "Invalid QoS Map");
482 return -1;
483 }
484
485 wpa_printf(MSG_ERROR, "%s: Entry,set_qos_map", __func__);
486 pbuf = buf;
487 ret_s = sprintf_s(pbuf, MAX_DRV_CMD_SIZE, "%s", _cmd);
488 if (ret_s == -1) {
489 wpa_printf(MSG_ERROR, "%s:%d, sprintf failed, ret=%d", __func__, __LINE__, ret_s);
490 }
491 pbuf += ret_s;
492 *pbuf++ = '\0';
493
494 pst_qos_map= (oal_qos_map_param_stru *)pbuf;
495 pst_qos_map->valid = 1;
496 pst_qos_map->num_dscp_except = (qos_map_set_len - 16) / 2;
497 if (pst_qos_map->num_dscp_except)
498 {
499 for (i = 0; i < pst_qos_map->num_dscp_except; i++)
500 {
501 pst_qos_map->dscp_exception[i] = qos_map_set[i * 2];
502 pst_qos_map->dscp_exception_up[i] = qos_map_set[i * 2 + 1];
503 }
504 }
505 up_start = qos_map_set_len - 16;
506 for (i = 0; i < MAX_QOS_UP_RANGE; i++)
507 {
508 pst_qos_map->up_low[i] = qos_map_set[up_start + (i * 2)];
509 pst_qos_map->up_high[i] = qos_map_set[up_start + (i * 2) + 1];
510 }
511
512 ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(_cmd) + 1 + sizeof(oal_qos_map_param_stru));
513 return ret;
514 }
515
wpa_driver_set_tx_power(void * priv,int power)516 int wpa_driver_set_tx_power(void *priv, int power)
517 {
518 char buf[MAX_PRIV_CMD_SIZE] = {0};
519 int len = 0;
520
521 wpa_printf(MSG_ERROR, "%s: Entry,power limit:%d", __func__, power);
522 if (power <= 0 || power > 100)
523 {
524 wpa_printf(MSG_ERROR, "%s: Entry,invalid power, valid power should in range(0,100]!", __func__);
525 return -1;
526 }
527 len = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "TX_POWER %d", power);
528 if (len == -1) {
529 wpa_printf(MSG_ERROR, "%s:%d, snprintf failed, ret=%d", __func__, __LINE__, len);
530 }
531 buf[len] = '\0';
532 wpa_printf(MSG_DEBUG, "%s:buf is %s", __func__, buf);
533
534 return wpa_driver_nl80211_driver_cmd(priv, buf, buf, len);
535 }
536
537 #ifdef CONFIG_OWE
wpa_driver_nl80211_sta_assoc(void * priv,const u8 * own_addr,const u8 * addr,int reassoc,u16 status,const u8 * pst_assoc_rsp_ie,size_t len)538 int wpa_driver_nl80211_sta_assoc(void *priv, const u8 *own_addr, const u8 *addr,
539 int reassoc, u16 status, const u8 *pst_assoc_rsp_ie, size_t len)
540 {
541 char buf[MAX_WPSP2PIE_CMD_SIZE] = {0};
542 char *pbuf;
543 char *_cmd = "SET_MLME_IE";
544 int ret = 0;
545 int ret_s;
546 set_mlme_stru *pst_mlme_ie = NULL;
547
548 if (NULL == pst_assoc_rsp_ie)
549 {
550 wpa_printf(MSG_WARNING, "%s[%d]: buf is null.\n", __FUNCTION__, __LINE__);
551 return -1;
552 }
553
554 if (len > WLAN_WPS_IE_MAX_SIZE)
555 {
556 /* ����·�ie ���ȴ����¼��ڴ��С����ʾ���� */
557 wpa_printf(MSG_ERROR, "%s[%d]: assoc rsp ie too large to wifi driver buffer. ie_len %zu, MAX len %d",
558 __FUNCTION__, __LINE__, len, WLAN_WPS_IE_MAX_SIZE);
559 return -1;
560 }
561
562 pbuf = buf;
563 ret_s = sprintf_s(pbuf, MAX_WPSP2PIE_CMD_SIZE, "%s", _cmd);
564 if (ret_s == -1) {
565 wpa_printf(MSG_ERROR, "%s:%d, sprintf failed, ret=%d", __func__, __LINE__, ret_s);
566 }
567 pbuf += ret_s;
568 *pbuf++ = '\0';
569
570 pst_mlme_ie = (set_mlme_stru *)pbuf;
571 if (reassoc)
572 {
573 pst_mlme_ie->en_mlme_type = OAL_IEEE80211_MLME_REASSOC_RSP;
574 }
575 else
576 {
577 pst_mlme_ie->en_mlme_type = OAL_IEEE80211_MLME_ASSOC_RSP;
578 }
579 pst_mlme_ie->us_status = status;
580 ret_s = memcpy_s(pst_mlme_ie->uc_macaddr, sizeof(pst_mlme_ie->uc_macaddr), addr, ETH_ALEN);
581 if (ret_s != EOK) {
582 wpa_printf(MSG_ERROR, "%s:%d, memcpy failed, ret=%d", __func__, __LINE__, ret_s);
583 }
584
585 pst_mlme_ie->us_ie_len = len;
586 ret_s = memcpy_s(pst_mlme_ie->auc_ie, sizeof(pst_mlme_ie->auc_ie), pst_assoc_rsp_ie, len);
587 if (ret_s != EOK) {
588 wpa_printf(MSG_ERROR, "%s:%d, memcpy failed, ret=%d", __func__, __LINE__, ret_s);
589 }
590
591 wpa_printf(MSG_ERROR, "%s[%d]: sta_assoc begin send assoc rsp ie len[%zu] to driver", __FUNCTION__, __LINE__, len);
592
593 wpa_printf(MSG_ERROR, "cmd:%s, type %d, status %d, ie_len %d",
594 _cmd,
595 pst_mlme_ie->en_mlme_type,
596 pst_mlme_ie->us_status,
597 pst_mlme_ie->us_ie_len);
598
599 wpa_hexdump(MSG_ERROR, "MLME: set sta_assoc ie", (const char *)pbuf, pst_mlme_ie->us_ie_len + 8);
600
601 if (os_strlen(_cmd) + sizeof(set_mlme_stru) + 1 < sizeof(buf))
602 {
603 ret = wpa_driver_nl80211_driver_cmd(priv, buf, buf,
604 os_strlen(_cmd) + sizeof(set_mlme_stru) + 1);
605 }
606 else
607 {
608 wpa_printf(MSG_ERROR, "%s:error. app total length to large! cmd_len = %zu, buffer = %d",
609 __func__, os_strlen(_cmd) + sizeof(set_mlme_stru) + 1, (int)sizeof(buf));
610 ret = -1;
611 }
612
613 return ret;
614 }
615 #endif
616
617 #ifdef CONFIG_HW_GET_P2P_SIGNAL_POLL
wpa_drv_get_p2p_link_noise(void * priv,struct wpa_signal_info * si)618 int wpa_drv_get_p2p_link_noise(void *priv, struct wpa_signal_info *si)
619 {
620 if (priv == NULL || si == NULL) {
621 return -1;
622 }
623 struct i802_bss *bss = priv;
624 struct wpa_driver_nl80211_data *drv = bss->drv;
625 os_memset(si, 0, sizeof(struct wpa_signal_info));
626 return nl80211_get_link_noise(drv, si);
627 }
628 #endif /* CONFIG_HW_GET_P2P_SIGNAL_POLL */
629
wpa_sockets_open(void)630 static int wpa_sockets_open(void)
631 {
632 int skfd;
633
634 skfd = socket(PF_INET, SOCK_DGRAM, 0);
635 if (skfd < 0)
636 {
637 wpa_printf(MSG_ERROR,
638 "nl80211: socket open failed.");
639 return -1;
640 }
641 return skfd;
642 }
wpa_sockets_close(int32 skfd)643 static void wpa_sockets_close(int32 skfd)
644 {
645 close(skfd);
646 }
wpa_send_cmd_to_driver(int skfd,s8 * ifname,wifi_priv_cmd * ioctl_data)647 static int wpa_send_cmd_to_driver(int skfd, s8* ifname, wifi_priv_cmd* ioctl_data)
648 {
649 struct ifreq ifr;
650 int ret;
651 int ret_s;
652
653 ret_s = memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr));
654 if (ret_s != EOK) {
655 wpa_printf(MSG_ERROR, "%s:%d, memset failed, ret=%d", __func__, __LINE__, ret_s);
656 }
657
658 ret_s = strncpy_s(ifr.ifr_name, IFNAMSIZ, "wlan0", strlen("wlan0"));
659 if (ret_s != EOK) {
660 wpa_printf(MSG_ERROR, "%s:%d, strncpy failed, ret=%d", __func__, __LINE__, ret_s);
661 }
662 ifr.ifr_name[IFNAMSIZ-1] = '\0';
663 ifr.ifr_data = (void*)ioctl_data;
664
665 ret = ioctl(skfd, SIOCDEVPRIVATE+1, &ifr);
666
667 if (ret < 0)
668 {
669 wpa_printf(MSG_ERROR,
670 "%s: failed to issue ioctl cmd.\n", __func__);
671 }
672
673 return ret;
674 }
675
676 static cust_data_stru global_cust_data = {0,0};
677
get_cust_config_params(void)678 static void get_cust_config_params(void)
679 {
680 int skfd;
681 wifi_priv_cmd ioctl_data = {0};
682 int ret;
683 int len;
684
685 if (-1 == (skfd = wpa_sockets_open()))
686 {
687 wpa_printf(MSG_ERROR,
688 "%s: failed create socket.\n", __func__);
689 return;
690 }
691
692 len = snprintf_s(ioctl_data.buf, MAX_PRIV_CMD_SIZE, MAX_PRIV_CMD_SIZE - 1, "WPAS_GET_CUST");
693 if (len == -1) {
694 wpa_printf(MSG_ERROR, "%s:%d, snprintf failed, ret=%d", __func__, __LINE__, len);
695 }
696 ioctl_data.total_len = MAX_PRIV_CMD_SIZE;
697 ioctl_data.used_len = len;
698 #ifdef HW_WPA_REDUCE_LOG
699 wpa_printf(MSG_ERROR, "%s:ioctl_data cmd is %s", __func__, ioctl_data.buf);
700 #else
701 wpa_printf(MSG_ERROR, "%s:ioctl_data cmd is %s", __func__, ioctl_data.buf);
702 #endif
703
704 ret = wpa_send_cmd_to_driver(skfd, (s8 *)"wlan0", &ioctl_data);
705
706 if (ret < 0)
707 {
708 wpa_printf(MSG_ERROR,
709 "%s: send cmd to driver failed.\n", __func__);
710 wpa_sockets_close(skfd);
711 return;
712 }
713
714 drv_errors = 0;
715
716 global_cust_data.read = 1;
717 global_cust_data.disable_capab_2ght40 = (u32)(*ioctl_data.buf);
718 wpa_printf(MSG_ERROR,
719 "%s: update wps global cust data: [disable_capab_2ght40:%d]\n", __func__, global_cust_data.disable_capab_2ght40);
720
721 wpa_sockets_close(skfd);
722 }
723
get_cust_disable_capab_2ght40(void)724 u32 get_cust_disable_capab_2ght40(void)
725 {
726 if (!global_cust_data.read)
727 {
728 get_cust_config_params();
729 }
730
731 return global_cust_data.disable_capab_2ght40;
732 }