SSB-8693 wifi_hal changes for google scan
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / wifi_hal.cpp
CommitLineData
b2737ea7 1#include <errno.h>\r
2#include <stdint.h>\r
3#include <fcntl.h>\r
4#include <sys/socket.h>\r
5#include <netlink/genl/genl.h>\r
6#include <netlink/genl/family.h>\r
7#include <netlink/genl/ctrl.h>\r
8#include <linux/rtnetlink.h>\r
9#include <netpacket/packet.h>\r
10#include <linux/filter.h>\r
11#include <linux/errqueue.h>\r
12\r
13#include <linux/pkt_sched.h>\r
14#include <netlink/object-api.h>\r
15#include <netlink/netlink.h>\r
16#include <netlink/socket.h>\r
17#include <netlink/attr.h>\r
18#include <netlink/handlers.h>\r
19#include <netlink/msg.h>\r
20\r
21#include <dirent.h>\r
22#include <net/if.h>\r
23\r
24#include "sync.h"\r
25\r
26#define LOG_TAG "WifiHAL"\r
27\r
28#include <utils/Log.h>\r
29\r
30#include "wifi_hal.h"\r
31#include "common.h"\r
32#include "cpp_bindings.h"\r
33\r
34\r
35#define WIFI_HAL_CMD_SOCK_PORT 644\r
36#define WIFI_HAL_EVENT_SOCK_PORT 645\r
37\r
38#define FEATURE_SET 0\r
39#define FEATURE_SET_MATRIX 1\r
40#define ATTR_NODFS_VALUE 3\r
41\r
42static void internal_event_handler(wifi_handle handle, int events);\r
43static int internal_no_seq_check(nl_msg *msg, void *arg);\r
44static int internal_valid_message_handler(nl_msg *msg, void *arg);\r
45static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);\r
46static int wifi_add_membership(wifi_handle handle, const char *group);\r
47static wifi_error wifi_init_interfaces(wifi_handle handle);\r
48\r
49typedef enum wifi_attr {\r
50 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,\r
51 ANDR_WIFI_ATTRIBUTE_FEATURE_SET,\r
52 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI\r
53} wifi_attr_t;\r
54\r
55/* Initialize/Cleanup */\r
56\r
57void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)\r
58{\r
59 uint32_t pid = getpid() & 0x3FFFFF;\r
60 nl_socket_set_local_port(sock, pid + (port << 22));\r
61}\r
62\r
63static nl_sock * wifi_create_nl_socket(int port)\r
64{\r
65 ALOGI("Creating socket");\r
66 struct nl_sock *sock = nl_socket_alloc();\r
67 if (sock == NULL) {\r
68 ALOGE("Could not create handle");\r
69 return NULL;\r
70 }\r
71\r
72 wifi_socket_set_local_port(sock, port);\r
73\r
74 struct sockaddr *addr = NULL;\r
75 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));\r
76\r
77 ALOGI("Connecting socket");\r
78 if (nl_connect(sock, NETLINK_GENERIC)) {\r
79 ALOGE("Could not connect handle");\r
80 nl_socket_free(sock);\r
81 return NULL;\r
82 }\r
83\r
84 ALOGI("Making socket nonblocking");\r
85 /*\r
86 if (nl_socket_set_nonblocking(sock)) {\r
87 ALOGE("Could make socket non-blocking");\r
88 nl_socket_free(sock);\r
89 return NULL;\r
90 }\r
91 */\r
92\r
93 return sock;\r
94}\r
95\r
96wifi_error wifi_initialize(wifi_handle *handle)\r
97{\r
98 srand(getpid());\r
99\r
100 ALOGI("Initializing wifi");\r
101 hal_info *info = (hal_info *)malloc(sizeof(hal_info));\r
102 if (info == NULL) {\r
103 ALOGE("Could not allocate hal_info");\r
104 return WIFI_ERROR_UNKNOWN;\r
105 }\r
106\r
107 memset(info, 0, sizeof(*info));\r
108\r
109 ALOGI("Creating socket");\r
110 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);\r
111 if (cmd_sock == NULL) {\r
112 ALOGE("Could not create handle");\r
113 return WIFI_ERROR_UNKNOWN;\r
114 }\r
115\r
116 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);\r
117 if (event_sock == NULL) {\r
118 ALOGE("Could not create handle");\r
119 nl_socket_free(cmd_sock);\r
120 return WIFI_ERROR_UNKNOWN;\r
121 }\r
122\r
123 struct nl_cb *cb = nl_socket_get_cb(event_sock);\r
124 if (cb == NULL) {\r
125 ALOGE("Could not create handle");\r
126 return WIFI_ERROR_UNKNOWN;\r
127 }\r
128\r
129// ALOGI("cb->refcnt = %d", cb->cb_refcnt);\r
130 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);\r
131 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);\r
132 nl_cb_put(cb);\r
133\r
134 info->cmd_sock = cmd_sock;\r
135 info->event_sock = event_sock;\r
136 info->clean_up = false;\r
137 info->in_event_loop = false;\r
138\r
139 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);\r
140 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;\r
141 info->num_event_cb = 0;\r
142\r
143 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);\r
144 info->alloc_cmd = DEFAULT_CMD_SIZE;\r
145 info->num_cmd = 0;\r
146\r
147 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");\r
148 if (info->nl80211_family_id < 0) {\r
149 ALOGE("Could not resolve nl80211 familty id");\r
150 nl_socket_free(cmd_sock);\r
151 nl_socket_free(event_sock);\r
152 free(info);\r
153 return WIFI_ERROR_UNKNOWN;\r
154 }\r
155\r
156 pthread_mutex_init(&info->cb_lock, NULL);\r
157\r
158 *handle = (wifi_handle) info;\r
159 ALOGD("wifi_initialize, handle = %p\n", handle);\r
160 ALOGD("wifi_initialize, *handle = %p\n", *handle);\r
161 ALOGD("wifi_initialize, info = %p\n", info);\r
162 ALOGD("wifi_initialize, *info = %pn", *info);\r
163 wifi_add_membership(*handle, "scan");\r
164 wifi_add_membership(*handle, "mlme");\r
165 wifi_add_membership(*handle, "regulatory");\r
166 wifi_add_membership(*handle, "vendor");\r
167\r
168 wifi_init_interfaces(*handle);\r
169 ALOGD("Found %d interfaces", info->num_interfaces);\r
170\r
171\r
172 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);\r
173 return WIFI_SUCCESS;\r
174}\r
175\r
176static int wifi_add_membership(wifi_handle handle, const char *group)\r
177{\r
178 hal_info *info = getHalInfo(handle);\r
179\r
180 int id = wifi_get_multicast_id(handle, "nl80211", group);\r
181 if (id < 0) {\r
182 ALOGE("Could not find group %s", group);\r
183 return id;\r
184 }\r
185\r
186 int ret = nl_socket_add_membership(info->event_sock, id);\r
187 if (ret < 0) {\r
188 ALOGE("Could not add membership to group %s", group);\r
189 }\r
190\r
191 ALOGI("Successfully added membership for group %s", group);\r
192 return ret;\r
193}\r
194\r
195static void internal_cleaned_up_handler(wifi_handle handle)\r
196{\r
197 hal_info *info = getHalInfo(handle);\r
198 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;\r
199\r
200 if (info->cmd_sock != 0) {\r
201 nl_socket_free(info->cmd_sock);\r
202 nl_socket_free(info->event_sock);\r
203 info->cmd_sock = NULL;\r
204 info->event_sock = NULL;\r
205 }\r
206\r
207 (*cleaned_up_handler)(handle);\r
208 pthread_mutex_destroy(&info->cb_lock);\r
209 free(info);\r
210\r
211 ALOGI("Internal cleanup completed");\r
212}\r
213\r
214void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)\r
215{\r
216 hal_info *info = getHalInfo(handle);\r
217 info->cleaned_up_handler = handler;\r
218 info->clean_up = true;\r
219\r
220 ALOGI("Wifi cleanup completed");\r
221}\r
222\r
223static int internal_pollin_handler(wifi_handle handle)\r
224{\r
225 hal_info *info = getHalInfo(handle);\r
226 ALOGI("even_loop info = %p", info);\r
227 struct nl_cb *cb = nl_socket_get_cb(info->event_sock);\r
228 int res = nl_recvmsgs(info->event_sock, cb);\r
229 ALOGD("nl_recvmsgs returned %d", res);\r
230 nl_cb_put(cb);\r
231 return res;\r
232}\r
233\r
234/* Run event handler */\r
235void wifi_event_loop(wifi_handle handle)\r
236{\r
237 hal_info *info = getHalInfo(handle);\r
238 ALOGI("even_loop info = %p", info);\r
239 ALOGI("even_loop info = %p", handle);\r
240 if (info->in_event_loop) {\r
241 return;\r
242 } else {\r
243 info->in_event_loop = true;\r
244 }\r
245\r
246 pollfd pfd;\r
247 memset(&pfd, 0, sizeof(pfd));\r
248\r
249 pfd.fd = nl_socket_get_fd(info->event_sock);\r
250 pfd.events = POLLIN;\r
251\r
252 /* TODO: Add support for timeouts */\r
253\r
254 do {\r
255 int timeout = -1; /* Infinite timeout */\r
256 pfd.revents = 0;\r
257 ALOGI("Polling socket");\r
258 int result = poll(&pfd, 1, -1);\r
259 if (result < 0) {\r
260 ALOGE("Error polling socket");\r
261 } else if (pfd.revents & POLLERR) {\r
262 ALOGE("POLL Error; error no = %d", errno);\r
263 char buf[2048];\r
264 int result2 = read(pfd.fd, buf, sizeof(buf));\r
265 ALOGE("Read after POLL returned %d, error no = %d", result2, errno);\r
266 } else if (pfd.revents & POLLHUP) {\r
267 ALOGE("Remote side hung up");\r
268 break;\r
269 } else if (pfd.revents & POLLIN) {\r
270 ALOGI("Found some events!!!");\r
271 internal_pollin_handler(handle);\r
272 } else {\r
273 ALOGE("Unknown event - %0x", pfd.revents);\r
274 }\r
275 } while (!info->clean_up);\r
276\r
277\r
278 ALOGI("Cleaning up");\r
279 internal_cleaned_up_handler(handle);\r
280}\r
281\r
282///////////////////////////////////////////////////////////////////////////////////////\r
283\r
284static int internal_no_seq_check(struct nl_msg *msg, void *arg)\r
285{\r
286 return NL_OK;\r
287}\r
288\r
289static int internal_valid_message_handler(nl_msg *msg, void *arg)\r
290{\r
291 wifi_handle handle = (wifi_handle)arg;\r
292 hal_info *info = getHalInfo(handle);\r
293 ALOGI("even_loop info = %p", handle);\r
294 ALOGD("internal_valid_message_handler, info = %p", info);\r
295\r
296 WifiEvent event(msg);\r
297 int res = event.parse();\r
298 if (res < 0) {\r
299 ALOGE("Failed to parse event: %d", res);\r
300 return NL_SKIP;\r
301 }\r
302\r
303 int cmd = event.get_cmd();\r
304 uint32_t vendor_id = 0;\r
305 int subcmd = 0;\r
306\r
307 if (cmd == NL80211_CMD_VENDOR) {\r
308 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);\r
309 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);\r
310 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",\r
311 event.get_cmdString(), vendor_id, subcmd);\r
312 } else {\r
313 ALOGI("event received %s", event.get_cmdString());\r
314 }\r
315\r
316 //ALOGI("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);\r
317 //event.log();\r
318\r
319 bool dispatched = false;\r
320\r
321 pthread_mutex_lock(&info->cb_lock);\r
322 \r
323 ALOGI("Number of events %d", info->num_event_cb);\r
324\r
325 for (int i = 0; i < info->num_event_cb; i++) {\r
326 if (cmd == info->event_cb[i].nl_cmd) {\r
327 if (cmd == NL80211_CMD_VENDOR\r
328 && ((vendor_id != info->event_cb[i].vendor_id)\r
329 || (subcmd != info->event_cb[i].vendor_subcmd)))\r
330 {\r
331 /* event for a different vendor, ignore it */\r
332 continue;\r
333 }\r
334\r
335 cb_info *cbi = &(info->event_cb[i]);\r
336 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;\r
337 void *cb_arg = cbi->cb_arg;\r
338 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;\r
339 if (cmd != NULL) {\r
340 cmd->addRef();\r
341 }\r
342\r
343 pthread_mutex_unlock(&info->cb_lock);\r
344\r
345 (*cb_func)(msg, cb_arg);\r
346 if (cmd != NULL) {\r
347 cmd->releaseRef();\r
348 }\r
349\r
350 return NL_OK;\r
351 }\r
352 }\r
353\r
354 pthread_mutex_unlock(&info->cb_lock);\r
355 return NL_OK;\r
356}\r
357\r
358///////////////////////////////////////////////////////////////////////////////////////\r
359\r
360class GetMulticastIdCommand : public WifiCommand\r
361{\r
362private:\r
363 const char *mName;\r
364 const char *mGroup;\r
365 int mId;\r
366public:\r
367 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)\r
368 : WifiCommand(handle, 0)\r
369 {\r
370 mName = name;\r
371 mGroup = group;\r
372 mId = -1;\r
373 }\r
374\r
375 int getId() {\r
376 return mId;\r
377 }\r
378\r
379 virtual int create() {\r
380 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");\r
381 ALOGI("ctrl family = %d", nlctrlFamily);\r
382 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);\r
383 if (ret < 0) {\r
384 return ret;\r
385 }\r
386 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);\r
387 return ret;\r
388 }\r
389\r
390 virtual int handleResponse(WifiEvent& reply) {\r
391\r
392 ALOGE("handling reponse in %s", __func__);\r
393\r
394 struct nlattr **tb = reply.attributes();\r
395 struct genlmsghdr *gnlh = reply.header();\r
396 struct nlattr *mcgrp = NULL;\r
397 int i;\r
398\r
399 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {\r
400 ALOGE("No multicast groups found");\r
401 return NL_SKIP;\r
402 } else {\r
403 ALOGE("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));\r
404 }\r
405\r
406 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {\r
407\r
408 ALOGE("Processing group");\r
409 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];\r
410 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),\r
411 nla_len(mcgrp), NULL);\r
412 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {\r
413 continue;\r
414 }\r
415\r
416 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);\r
417 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);\r
418\r
419 ALOGE("Found group name %s", grpName);\r
420\r
421 if (strncmp(grpName, mGroup, grpNameLen) != 0)\r
422 continue;\r
423\r
424 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);\r
425 break;\r
426 }\r
427\r
428 return NL_SKIP;\r
429 }\r
430\r
431};\r
432\r
433class SetPnoMacAddrOuiCommand : public WifiCommand {\r
434\r
435private:\r
436 byte *mOui;\r
437 feature_set *fset;\r
438 feature_set *feature_matrix;\r
439 int *fm_size;\r
440 int set_size_max;\r
441public:\r
442 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)\r
443 : WifiCommand(handle, 0)\r
444 {\r
445 mOui = scan_oui;\r
446 }\r
447\r
448 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {\r
449 int result = request.create(GOOGLE_OUI, subcmd);\r
450 if (result < 0) {\r
451 return result;\r
452 }\r
453\r
454 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);\r
455 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);\r
456 if (result < 0) {\r
457 return result;\r
458 }\r
459\r
460 request.attr_end(data);\r
461 return WIFI_SUCCESS;\r
462\r
463 }\r
464\r
465 int start() {\r
466 ALOGD("Sending mac address OUI");\r
467 WifiRequest request(familyId(), ifaceId());\r
468 int result = createRequest(request, SLSI_NL80211_VENDOR_SUBCMD_SET_GSCAN_OUI, mOui);\r
469 if (result != WIFI_SUCCESS) {\r
470 ALOGE("failed to create request; result = %d", result);\r
471 return result;\r
472 }\r
473\r
474 result = requestResponse(request);\r
475 if (result != WIFI_SUCCESS) {\r
476 ALOGE("failed to set scanning mac OUI; result = %d", result);\r
477 }\r
478\r
479 return result;\r
480 }\r
481protected:\r
482 virtual int handleResponse(WifiEvent& reply) {\r
483 ALOGD("Request complete!");\r
484 /* Nothing to do on response! */\r
485 return NL_SKIP;\r
486 }\r
487};\r
488\r
489class SetNodfsCommand : public WifiCommand {\r
490\r
491private:\r
492 u32 mNoDfs;\r
493public:\r
494 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)\r
495 : WifiCommand(handle, 0) {\r
496 mNoDfs = nodfs;\r
497 }\r
498 virtual int create() {\r
499 int ret;\r
500\r
501 ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_NODFS);\r
502 if (ret < 0) {\r
503 ALOGE("Can't create message to send to driver - %d", ret);\r
504 return ret;\r
505 }\r
506\r
507 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);\r
508 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);\r
509 if (ret < 0) {\r
510 return ret;\r
511 }\r
512\r
513 mMsg.attr_end(data);\r
514 return WIFI_SUCCESS;\r
515 }\r
516};\r
517\r
518static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)\r
519{\r
520 GetMulticastIdCommand cmd(handle, name, group);\r
521 int res = cmd.requestResponse();\r
522 if (res < 0)\r
523 return res;\r
524 else\r
525 return cmd.getId();\r
526}\r
527\r
528/////////////////////////////////////////////////////////////////////////\r
529\r
530static bool is_wifi_interface(const char *name)\r
531{\r
532 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {\r
533 /* not a wifi interface; ignore it */\r
534 return false;\r
535 } else {\r
536 return true;\r
537 }\r
538}\r
539\r
540static int get_interface(const char *name, interface_info *info)\r
541{\r
542 strcpy(info->name, name);\r
543 info->id = if_nametoindex(name);\r
544 ALOGI("found an interface : %s, id = %d", name, info->id);\r
545 return WIFI_SUCCESS;\r
546}\r
547\r
548wifi_error wifi_init_interfaces(wifi_handle handle)\r
549{\r
550 hal_info *info = (hal_info *)handle;\r
551 ALOGD("wifi_init_interfaces, info = %p", info);\r
552\r
553 struct dirent *de;\r
554\r
555 DIR *d = opendir("/sys/class/net");\r
556 if (d == 0)\r
557 return WIFI_ERROR_UNKNOWN;\r
558\r
559 int n = 0;\r
560 while ((de = readdir(d))) {\r
561 if (de->d_name[0] == '.')\r
562 continue;\r
563 if (is_wifi_interface(de->d_name) ) {\r
564 n++;\r
565 }\r
566 }\r
567\r
568 closedir(d);\r
569\r
570 d = opendir("/sys/class/net");\r
571 if (d == 0)\r
572 return WIFI_ERROR_UNKNOWN;\r
573\r
574 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);\r
575\r
576 int i = 0;\r
577 while ((de = readdir(d))) {\r
578 if (de->d_name[0] == '.')\r
579 continue;\r
580 if (is_wifi_interface(de->d_name)) {\r
581 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));\r
582 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {\r
583 free(ifinfo);\r
584 continue;\r
585 }\r
586 ifinfo->handle = handle;\r
587 info->interfaces[i] = ifinfo;\r
588 i++;\r
589 }\r
590 }\r
591\r
592 closedir(d);\r
593\r
594 info->num_interfaces = n;\r
595 return WIFI_SUCCESS;\r
596}\r
597\r
598wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)\r
599{\r
600 hal_info *info = (hal_info *)handle;\r
601\r
602 *interfaces = (wifi_interface_handle *)info->interfaces;\r
603 *num = info->num_interfaces;\r
604\r
605 return WIFI_SUCCESS;\r
606}\r
607\r
608wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)\r
609{\r
610 interface_info *info = (interface_info *)handle;\r
611 strcpy(name, info->name);\r
612 return WIFI_SUCCESS;\r
613}\r
614\r
615wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)\r
616{\r
617 return WIFI_ERROR_NOT_SUPPORTED;\r
618}\r
619\r
620wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,\r
621 feature_set set[], int *set_size)\r
622{\r
623 return WIFI_ERROR_NOT_SUPPORTED;\r
624}\r
625\r
626wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)\r
627{\r
628 SetPnoMacAddrOuiCommand command(handle, scan_oui);\r
629 return (wifi_error)command.start();\r
630\r
631}\r
632\r
633wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)\r
634{\r
635 SetNodfsCommand command(handle, nodfs);\r
636 return (wifi_error) command.requestResponse();\r
637}\r
638\r
639/////////////////////////////////////////////////////////////////////////////\r