2 * Linux cfg80211 driver - Android related functions
4 * $Copyright Open Broadcom Corporation$
6 * $Id: wl_android.c 505064 2014-09-26 09:40:28Z $
9 #include <linux/module.h>
10 #include <linux/netdevice.h>
11 #include <net/netlink.h>
13 #include <linux/compat.h>
16 #include <wl_android.h>
17 #include <wldev_common.h>
20 #include <linux_osl.h>
22 #include <dngl_stats.h>
24 #include <dhd_config.h>
25 #include <proto/bcmip.h>
33 #include <wl_cfg80211.h>
36 #include <wl_cfgnan.h>
44 #define htodchanspec(i) i
45 #define dtohchanspec(i) i
49 #define ANDROID_ERROR_LEVEL 0x0001
50 #define ANDROID_TRACE_LEVEL 0x0002
51 #define ANDROID_INFO_LEVEL 0x0004
53 uint android_msg_level = ANDROID_ERROR_LEVEL;
55 #define ANDROID_ERROR(x) \
57 if (android_msg_level & ANDROID_ERROR_LEVEL) { \
58 printk(KERN_ERR "ANDROID-ERROR) "); \
62 #define ANDROID_TRACE(x) \
64 if (android_msg_level & ANDROID_TRACE_LEVEL) { \
65 printk(KERN_ERR "ANDROID-TRACE) "); \
69 #define ANDROID_INFO(x) \
71 if (android_msg_level & ANDROID_INFO_LEVEL) { \
72 printk(KERN_ERR "ANDROID-INFO) "); \
78 * Android private command strings, PLEASE define new private commands here
79 * so they can be updated easily in the future (if needed)
82 #define CMD_START "START"
83 #define CMD_STOP "STOP"
84 #define CMD_SCAN_ACTIVE "SCAN-ACTIVE"
85 #define CMD_SCAN_PASSIVE "SCAN-PASSIVE"
86 #define CMD_RSSI "RSSI"
87 #define CMD_LINKSPEED "LINKSPEED"
88 #ifdef PKT_FILTER_SUPPORT
89 #define CMD_RXFILTER_START "RXFILTER-START"
90 #define CMD_RXFILTER_STOP "RXFILTER-STOP"
91 #define CMD_RXFILTER_ADD "RXFILTER-ADD"
92 #define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE"
93 #if defined(CUSTOM_PLATFORM_NV_TEGRA)
94 #define CMD_PKT_FILTER_MODE "PKT_FILTER_MODE"
95 #define CMD_PKT_FILTER_PORTS "PKT_FILTER_PORTS"
96 #endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
97 #endif /* PKT_FILTER_SUPPORT */
98 #define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START"
99 #define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
100 #define CMD_BTCOEXMODE "BTCOEXMODE"
101 #define CMD_SETSUSPENDOPT "SETSUSPENDOPT"
102 #define CMD_SETSUSPENDMODE "SETSUSPENDMODE"
103 #define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR"
104 #define CMD_SETFWPATH "SETFWPATH"
105 #define CMD_SETBAND "SETBAND"
106 #define CMD_GETBAND "GETBAND"
107 #define CMD_COUNTRY "COUNTRY"
108 #define CMD_P2P_SET_NOA "P2P_SET_NOA"
109 #if !defined WL_ENABLE_P2P_IF
110 #define CMD_P2P_GET_NOA "P2P_GET_NOA"
111 #endif /* WL_ENABLE_P2P_IF */
112 #define CMD_P2P_SD_OFFLOAD "P2P_SD_"
113 #define CMD_P2P_SET_PS "P2P_SET_PS"
114 #define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE"
115 #define CMD_SETROAMMODE "SETROAMMODE"
116 #define CMD_SETIBSSBEACONOUIDATA "SETIBSSBEACONOUIDATA"
117 #define CMD_MIRACAST "MIRACAST"
118 #define CMD_NAN "NAN_"
119 #define CMD_GET_CHANNEL "GET_CHANNEL"
120 #define CMD_SET_ROAM "SET_ROAM_TRIGGER"
121 #define CMD_GET_ROAM "GET_ROAM_TRIGGER"
122 #define CMD_GET_KEEP_ALIVE "GET_KEEP_ALIVE"
123 #define CMD_GET_PM "GET_PM"
124 #define CMD_SET_PM "SET_PM"
125 #define CMD_MONITOR "MONITOR"
127 #if defined(WL_SUPPORT_AUTO_CHANNEL)
128 #define CMD_GET_BEST_CHANNELS "GET_BEST_CHANNELS"
129 #endif /* WL_SUPPORT_AUTO_CHANNEL */
131 #if defined(CUSTOM_PLATFORM_NV_TEGRA)
132 #define CMD_SETMIRACAST "SETMIRACAST"
133 #define CMD_ASSOCRESPIE "ASSOCRESPIE"
134 #define CMD_RXRATESTATS "RXRATESTATS"
135 #endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
137 #define CMD_KEEP_ALIVE "KEEPALIVE"
139 /* CCX Private Commands */
141 #define CMD_GETCCKM_RN "get cckm_rn"
142 #define CMD_SETCCKM_KRK "set cckm_krk"
143 #define CMD_GET_ASSOC_RES_IES "get assoc_res_ies"
147 #define CMD_PNOSSIDCLR_SET "PNOSSIDCLR"
148 #define CMD_PNOSETUP_SET "PNOSETUP "
149 #define CMD_PNOENABLE_SET "PNOFORCE"
150 #define CMD_PNODEBUG_SET "PNODEBUG"
151 #define CMD_WLS_BATCHING "WLS_BATCHING"
152 #endif /* PNO_SUPPORT */
154 #define CMD_OKC_SET_PMK "SET_PMK"
155 #define CMD_OKC_ENABLE "OKC_ENABLE"
157 #define CMD_HAPD_MAC_FILTER "HAPD_MAC_FILTER"
160 #define CMD_GET_FTKEY "GET_FTKEY"
164 #define CMD_SETIBSSTXFAILEVENT "SETIBSSTXFAILEVENT"
165 #define CMD_GET_IBSS_PEER_INFO "GETIBSSPEERINFO"
166 #define CMD_GET_IBSS_PEER_INFO_ALL "GETIBSSPEERINFOALL"
167 #define CMD_SETIBSSROUTETABLE "SETIBSSROUTETABLE"
168 #define CMD_SETIBSSAMPDU "SETIBSSAMPDU"
169 #define CMD_SETIBSSANTENNAMODE "SETIBSSANTENNAMODE"
172 #define CMD_ROAM_OFFLOAD "SETROAMOFFLOAD"
173 #define CMD_ROAM_OFFLOAD_APLIST "SETROAMOFFLAPLIST"
174 #define CMD_GET_LINK_STATUS "GETLINKSTATUS"
176 #ifdef P2PRESP_WFDIE_SRC
177 #define CMD_P2P_SET_WFDIE_RESP "P2P_SET_WFDIE_RESP"
178 #define CMD_P2P_GET_WFDIE_RESP "P2P_GET_WFDIE_RESP"
179 #endif /* P2PRESP_WFDIE_SRC */
181 /* related with CMD_GET_LINK_STATUS */
182 #define WL_ANDROID_LINK_VHT 0x01
183 #define WL_ANDROID_LINK_MIMO 0x02
184 #define WL_ANDROID_LINK_AP_VHT_SUPPORT 0x04
185 #define WL_ANDROID_LINK_AP_MIMO_SUPPORT 0x08
187 /* miracast related definition */
188 #define MIRACAST_MODE_OFF 0
189 #define MIRACAST_MODE_SOURCE 1
190 #define MIRACAST_MODE_SINK 2
192 #ifndef MIRACAST_AMPDU_SIZE
193 #define MIRACAST_AMPDU_SIZE 8
196 #ifndef MIRACAST_MCHAN_ALGO
197 #define MIRACAST_MCHAN_ALGO 1
200 #ifndef MIRACAST_MCHAN_BW
201 #define MIRACAST_MCHAN_BW 25
204 #ifdef CONNECTION_STATISTICS
205 #define CMD_GET_CONNECTION_STATS "GET_CONNECTION_STATS"
207 struct connection_stats {
222 #endif /* CONNECTION_STATISTICS */
224 static LIST_HEAD(miracast_resume_list);
226 static u8 miracast_cur_mode;
235 struct list_head list;
238 typedef struct _android_wifi_priv_cmd {
242 } android_wifi_priv_cmd;
245 typedef struct _compat_android_wifi_priv_cmd {
249 } compat_android_wifi_priv_cmd;
250 #endif /* CONFIG_COMPAT */
252 #if defined(BCMFW_ROAM_ENABLE)
253 #define CMD_SET_ROAMPREF "SET_ROAMPREF"
255 #define MAX_NUM_SUITES 10
256 #define WIDTH_AKM_SUITE 8
257 #define JOIN_PREF_RSSI_LEN 0x02
258 #define JOIN_PREF_RSSI_SIZE 4 /* RSSI pref header size in bytes */
259 #define JOIN_PREF_WPA_HDR_SIZE 4 /* WPA pref header size in bytes */
260 #define JOIN_PREF_WPA_TUPLE_SIZE 12 /* Tuple size in bytes */
261 #define JOIN_PREF_MAX_WPA_TUPLES 16
262 #define MAX_BUF_SIZE (JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE + \
263 (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES))
264 #endif /* BCMFW_ROAM_ENABLE */
267 static s32 wl_genl_handle_msg(struct sk_buff *skb, struct genl_info *info);
268 static int wl_genl_init(void);
269 static int wl_genl_deinit(void);
271 extern struct net init_net;
272 /* attribute policy: defines which attribute has which type (e.g int, char * etc)
273 * possible values defined in net/netlink.h
275 static struct nla_policy wl_genl_policy[BCM_GENL_ATTR_MAX + 1] = {
276 [BCM_GENL_ATTR_STRING] = { .type = NLA_NUL_STRING },
277 [BCM_GENL_ATTR_MSG] = { .type = NLA_BINARY },
280 #define WL_GENL_VER 1
281 /* family definition */
282 static struct genl_family wl_genl_family = {
283 .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */
285 .name = "bcm-genl", /* Netlink I/F for Android */
286 .version = WL_GENL_VER, /* Version Number */
287 .maxattr = BCM_GENL_ATTR_MAX,
290 /* commands: mapping between the command enumeration and the actual function */
291 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
292 struct genl_ops wl_genl_ops[] = {
294 .cmd = BCM_GENL_CMD_MSG,
296 .policy = wl_genl_policy,
297 .doit = wl_genl_handle_msg,
302 struct genl_ops wl_genl_ops = {
303 .cmd = BCM_GENL_CMD_MSG,
305 .policy = wl_genl_policy,
306 .doit = wl_genl_handle_msg,
310 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */
312 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
313 static struct genl_multicast_group wl_genl_mcast[] = {
314 { .name = "bcm-genl-mcast", },
317 static struct genl_multicast_group wl_genl_mcast = {
318 .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */
319 .name = "bcm-genl-mcast",
321 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */
325 * Extern function declarations (TODO: move them to dhd_linux.h)
327 int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
328 int dhd_dev_init_ioctl(struct net_device *dev);
330 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
331 int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, dhd_pub_t *dhd, char *command);
333 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
335 int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
337 int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
339 int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
341 #endif /* WL_CFG80211 */
344 #ifdef ENABLE_4335BT_WAR
345 extern int bcm_bt_lock(int cookie);
346 extern void bcm_bt_unlock(int cookie);
347 static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24; /* cookie is "WiFi" */
348 #endif /* ENABLE_4335BT_WAR */
350 extern bool ap_fw_loaded;
351 extern char iface_name[IFNAMSIZ];
354 * Local (static) functions and variables
357 /* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
358 * time (only) in dhd_open, subsequential wifi on will be handled by
361 int g_wifi_on = TRUE;
364 * Local (static) function definitions
366 static int wl_android_get_link_speed(struct net_device *net, char *command, int total_len)
372 error = wldev_get_link_speed(net, &link_speed);
376 /* Convert Kbps to Android Mbps */
377 link_speed = link_speed / 1000;
378 bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
379 ANDROID_INFO(("%s: command result is %s\n", __FUNCTION__, command));
380 return bytes_written;
383 static int wl_android_get_rssi(struct net_device *net, char *command, int total_len)
385 wlc_ssid_t ssid = {0};
387 int bytes_written = 0;
390 error = wldev_get_rssi(net, &rssi);
393 #if defined(RSSIOFFSET)
394 rssi = wl_update_rssi_offset(net, rssi);
397 error = wldev_get_ssid(net, &ssid);
400 if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) {
401 ANDROID_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__));
403 memcpy(command, ssid.SSID, ssid.SSID_len);
404 bytes_written = ssid.SSID_len;
406 bytes_written += snprintf(&command[bytes_written], total_len, " rssi %d", rssi);
407 ANDROID_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written));
408 return bytes_written;
411 static int wl_android_set_suspendopt(struct net_device *dev, char *command, int total_len)
417 suspend_flag = *(command + strlen(CMD_SETSUSPENDOPT) + 1) - '0';
419 if (suspend_flag != 0)
421 ret_now = net_os_set_suspend_disable(dev, suspend_flag);
423 if (ret_now != suspend_flag) {
424 if (!(ret = net_os_set_suspend(dev, ret_now, 1)))
425 ANDROID_INFO(("%s: Suspend Flag %d -> %d\n",
426 __FUNCTION__, ret_now, suspend_flag));
428 ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
433 static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len)
437 #if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND)
440 suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0';
441 if (suspend_flag != 0)
444 if (!(ret = net_os_set_suspend(dev, suspend_flag, 0)))
445 ANDROID_INFO(("%s: Suspend Mode %d\n", __FUNCTION__, suspend_flag));
447 ANDROID_ERROR(("%s: failed %d\n", __FUNCTION__, ret));
453 static int wl_android_get_band(struct net_device *dev, char *command, int total_len)
459 error = wldev_get_band(dev, &band);
462 bytes_written = snprintf(command, total_len, "Band %d", band);
463 return bytes_written;
468 #define PNO_PARAM_SIZE 50
469 #define VALUE_SIZE 50
470 #define LIMIT_STR_FMT ("%50s %50s")
472 wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len)
476 char *pos, *pos2, *token, *token2, *delim;
477 char param[PNO_PARAM_SIZE], value[VALUE_SIZE];
478 struct dhd_pno_batch_params batch_params;
479 ANDROID_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
480 if (total_len < strlen(CMD_WLS_BATCHING)) {
481 ANDROID_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
485 pos = command + strlen(CMD_WLS_BATCHING) + 1;
486 memset(&batch_params, 0, sizeof(struct dhd_pno_batch_params));
488 if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) {
489 pos += strlen(PNO_BATCHING_SET) + 1;
490 while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) {
491 memset(param, 0, sizeof(param));
492 memset(value, 0, sizeof(value));
493 if (token == NULL || !*token)
497 delim = strchr(token, PNO_PARAM_VALUE_DELLIMETER);
501 tokens = sscanf(token, LIMIT_STR_FMT, param, value);
502 if (!strncmp(param, PNO_PARAM_SCANFREQ, strlen(PNO_PARAM_SCANFREQ))) {
503 batch_params.scan_fr = simple_strtol(value, NULL, 0);
504 ANDROID_INFO(("scan_freq : %d\n", batch_params.scan_fr));
505 } else if (!strncmp(param, PNO_PARAM_BESTN, strlen(PNO_PARAM_BESTN))) {
506 batch_params.bestn = simple_strtol(value, NULL, 0);
507 ANDROID_INFO(("bestn : %d\n", batch_params.bestn));
508 } else if (!strncmp(param, PNO_PARAM_MSCAN, strlen(PNO_PARAM_MSCAN))) {
509 batch_params.mscan = simple_strtol(value, NULL, 0);
510 ANDROID_INFO(("mscan : %d\n", batch_params.mscan));
511 } else if (!strncmp(param, PNO_PARAM_CHANNEL, strlen(PNO_PARAM_CHANNEL))) {
514 tokens = sscanf(value, "<%s>", value);
517 ANDROID_ERROR(("%s : invalid format for channel"
518 " <> params\n", __FUNCTION__));
521 while ((token2 = strsep(&pos2,
522 PNO_PARAM_CHANNEL_DELIMETER)) != NULL) {
523 if (token2 == NULL || !*token2)
527 if (*token2 == 'A' || *token2 == 'B') {
528 batch_params.band = (*token2 == 'A')?
529 WLC_BAND_5G : WLC_BAND_2G;
530 ANDROID_INFO(("band : %s\n",
531 (*token2 == 'A')? "A" : "B"));
533 batch_params.chan_list[i++] =
534 simple_strtol(token2, NULL, 0);
535 batch_params.nchan++;
536 ANDROID_INFO(("channel :%d\n",
537 batch_params.chan_list[i-1]));
540 } else if (!strncmp(param, PNO_PARAM_RTT, strlen(PNO_PARAM_RTT))) {
541 batch_params.rtt = simple_strtol(value, NULL, 0);
542 ANDROID_INFO(("rtt : %d\n", batch_params.rtt));
544 ANDROID_ERROR(("%s : unknown param: %s\n", __FUNCTION__, param));
549 err = dhd_dev_pno_set_for_batch(dev, &batch_params);
551 ANDROID_ERROR(("failed to configure batch scan\n"));
553 memset(command, 0, total_len);
554 err = sprintf(command, "%d", err);
556 } else if (!strncmp(pos, PNO_BATCHING_GET, strlen(PNO_BATCHING_GET))) {
557 err = dhd_dev_pno_get_for_batch(dev, command, total_len);
559 ANDROID_ERROR(("failed to getting batching results\n"));
561 err = strlen(command);
563 } else if (!strncmp(pos, PNO_BATCHING_STOP, strlen(PNO_BATCHING_STOP))) {
564 err = dhd_dev_pno_stop_for_batch(dev);
566 ANDROID_ERROR(("failed to stop batching scan\n"));
568 memset(command, 0, total_len);
569 err = sprintf(command, "OK");
572 ANDROID_ERROR(("%s : unknown command\n", __FUNCTION__));
579 #ifndef WL_SCHED_SCAN
580 static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
582 wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
585 cmd_tlv_t *cmd_tlv_temp;
590 int pno_freq_expo_max = 0;
594 char pno_in_example[] = {
595 'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
599 'd', 'l', 'i', 'n', 'k',
611 #endif /* PNO_SET_DEBUG */
612 ANDROID_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
614 if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
615 ANDROID_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len));
619 memcpy(command, pno_in_example, sizeof(pno_in_example));
620 total_len = sizeof(pno_in_example);
622 str_ptr = command + strlen(CMD_PNOSETUP_SET);
623 tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
625 cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
626 memset(ssids_local, 0, sizeof(ssids_local));
628 if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
629 (cmd_tlv_temp->version == PNO_TLV_VERSION) &&
630 (cmd_tlv_temp->subtype == PNO_TLV_SUBTYPE_LEGACY_PNO)) {
632 str_ptr += sizeof(cmd_tlv_t);
633 tlv_size_left -= sizeof(cmd_tlv_t);
635 if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
636 MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
637 ANDROID_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid));
640 if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
641 ANDROID_ERROR(("%s scan duration corrupted field size %d\n",
642 __FUNCTION__, tlv_size_left));
646 pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
647 ANDROID_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
649 if (str_ptr[0] != 0) {
650 if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
651 ANDROID_ERROR(("%s pno repeat : corrupted field\n",
656 pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
657 ANDROID_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
658 if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
659 ANDROID_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n",
664 pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
665 ANDROID_INFO(("%s: pno_freq_expo_max=%d\n",
666 __FUNCTION__, pno_freq_expo_max));
670 ANDROID_ERROR(("%s get wrong TLV command\n", __FUNCTION__));
674 res = dhd_dev_pno_set_for_ssid(dev, ssids_local, nssid, pno_time, pno_repeat,
675 pno_freq_expo_max, NULL, 0);
679 #endif /* !WL_SCHED_SCAN */
680 #endif /* PNO_SUPPORT */
682 static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
685 int bytes_written = 0;
687 ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command);
690 bytes_written = sizeof(struct ether_addr);
691 return bytes_written;
695 static int wl_android_get_cckm_rn(struct net_device *dev, char *command)
699 ANDROID_TRACE(("%s:wl_android_get_cckm_rn\n", dev->name));
701 error = wldev_iovar_getint(dev, "cckm_rn", &rn);
702 if (unlikely(error)) {
703 ANDROID_ERROR(("wl_android_get_cckm_rn error (%d)\n", error));
706 memcpy(command, &rn, sizeof(int));
711 static int wl_android_set_cckm_krk(struct net_device *dev, char *command)
714 unsigned char key[16];
715 static char iovar_buf[WLC_IOCTL_MEDLEN];
717 ANDROID_TRACE(("%s: wl_iw_set_cckm_krk\n", dev->name));
719 memset(iovar_buf, 0, sizeof(iovar_buf));
720 memcpy(key, command+strlen("set cckm_krk")+1, 16);
722 error = wldev_iovar_setbuf(dev, "cckm_krk", key, sizeof(key),
723 iovar_buf, WLC_IOCTL_MEDLEN, NULL);
726 ANDROID_ERROR((" cckm_krk set error (%d)\n", error));
732 static int wl_android_get_assoc_res_ies(struct net_device *dev, char *command)
735 u8 buf[WL_ASSOC_INFO_MAX];
736 wl_assoc_info_t assoc_info;
737 u32 resp_ies_len = 0;
738 int bytes_written = 0;
740 ANDROID_TRACE(("%s: wl_iw_get_assoc_res_ies\n", dev->name));
742 error = wldev_iovar_getbuf(dev, "assoc_info", NULL, 0, buf, WL_ASSOC_INFO_MAX, NULL);
743 if (unlikely(error)) {
744 ANDROID_ERROR(("could not get assoc info (%d)\n", error));
748 memcpy(&assoc_info, buf, sizeof(wl_assoc_info_t));
749 assoc_info.req_len = htod32(assoc_info.req_len);
750 assoc_info.resp_len = htod32(assoc_info.resp_len);
751 assoc_info.flags = htod32(assoc_info.flags);
753 if (assoc_info.resp_len) {
754 resp_ies_len = assoc_info.resp_len - sizeof(struct dot11_assoc_resp);
757 /* first 4 bytes are ie len */
758 memcpy(command, &resp_ies_len, sizeof(u32));
759 bytes_written = sizeof(u32);
761 /* get the association resp IE's if there are any */
763 error = wldev_iovar_getbuf(dev, "assoc_resp_ies", NULL, 0,
764 buf, WL_ASSOC_INFO_MAX, NULL);
765 if (unlikely(error)) {
766 ANDROID_ERROR(("could not get assoc resp_ies (%d)\n", error));
770 memcpy(command+sizeof(u32), buf, resp_ies_len);
771 bytes_written += resp_ies_len;
773 return bytes_written;
779 wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct maclist *maclist)
783 char mac_buf[MAX_NUM_OF_ASSOCLIST *
784 sizeof(struct ether_addr) + sizeof(uint)] = {0};
785 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
787 /* set filtering mode */
788 if ((ret = wldev_ioctl(dev, WLC_SET_MACMODE, &macmode, sizeof(macmode), true)) != 0) {
789 ANDROID_ERROR(("%s : WLC_SET_MACMODE error=%d\n", __FUNCTION__, ret));
792 if (macmode != MACLIST_MODE_DISABLED) {
793 /* set the MAC filter list */
794 if ((ret = wldev_ioctl(dev, WLC_SET_MACLIST, maclist,
795 sizeof(int) + sizeof(struct ether_addr) * maclist->count, true)) != 0) {
796 ANDROID_ERROR(("%s : WLC_SET_MACLIST error=%d\n", __FUNCTION__, ret));
799 /* get the current list of associated STAs */
800 assoc_maclist->count = MAX_NUM_OF_ASSOCLIST;
801 if ((ret = wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist,
802 sizeof(mac_buf), false)) != 0) {
803 ANDROID_ERROR(("%s : WLC_GET_ASSOCLIST error=%d\n", __FUNCTION__, ret));
806 /* do we have any STA associated? */
807 if (assoc_maclist->count) {
808 /* iterate each associated STA */
809 for (i = 0; i < assoc_maclist->count; i++) {
811 /* compare with each entry */
812 for (j = 0; j < maclist->count; j++) {
813 ANDROID_INFO(("%s : associated="MACDBG " list="MACDBG "\n",
814 __FUNCTION__, MAC2STRDBG(assoc_maclist->ea[i].octet),
815 MAC2STRDBG(maclist->ea[j].octet)));
816 if (memcmp(assoc_maclist->ea[i].octet,
817 maclist->ea[j].octet, ETHER_ADDR_LEN) == 0) {
822 /* do conditional deauth */
823 /* "if not in the allow list" or "if in the deny list" */
824 if ((macmode == MACLIST_MODE_ALLOW && !match) ||
825 (macmode == MACLIST_MODE_DENY && match)) {
828 scbval.val = htod32(1);
829 memcpy(&scbval.ea, &assoc_maclist->ea[i],
831 if ((ret = wldev_ioctl(dev,
832 WLC_SCB_DEAUTHENTICATE_FOR_REASON,
833 &scbval, sizeof(scb_val_t), true)) != 0)
834 ANDROID_ERROR(("%s WLC_SCB_DEAUTHENTICATE error=%d\n",
844 * HAPD_MAC_FILTER mac_mode mac_cnt mac_addr1 mac_addr2
848 wl_android_set_mac_address_filter(struct net_device *dev, const char* str)
853 int macmode = MACLIST_MODE_DISABLED;
854 struct maclist *list;
855 char eabuf[ETHER_ADDR_STR_LEN];
857 /* string should look like below (macmode/macnum/maclist) */
858 /* 1 2 00:11:22:33:44:55 00:11:22:33:44:ff */
860 /* get the MAC filter mode */
861 macmode = bcm_atoi(strsep((char**)&str, " "));
863 if (macmode < MACLIST_MODE_DISABLED || macmode > MACLIST_MODE_ALLOW) {
864 ANDROID_ERROR(("%s : invalid macmode %d\n", __FUNCTION__, macmode));
868 macnum = bcm_atoi(strsep((char**)&str, " "));
869 if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
870 ANDROID_ERROR(("%s : invalid number of MAC address entries %d\n",
871 __FUNCTION__, macnum));
874 /* allocate memory for the MAC list */
875 list = (struct maclist*)kmalloc(sizeof(int) +
876 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
878 ANDROID_ERROR(("%s : failed to allocate memory\n", __FUNCTION__));
881 /* prepare the MAC list */
882 list->count = htod32(macnum);
883 bzero((char *)eabuf, ETHER_ADDR_STR_LEN);
884 for (i = 0; i < list->count; i++) {
885 strncpy(eabuf, strsep((char**)&str, " "), ETHER_ADDR_STR_LEN - 1);
886 if (!(ret = bcm_ether_atoe(eabuf, &list->ea[i]))) {
887 ANDROID_ERROR(("%s : mac parsing err index=%d, addr=%s\n",
888 __FUNCTION__, i, eabuf));
892 ANDROID_INFO(("%s : %d/%d MACADDR=%s", __FUNCTION__, i, list->count, eabuf));
895 if ((ret = wl_android_set_ap_mac_list(dev, macmode, list)) != 0)
896 ANDROID_ERROR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
904 * Global function definitions (declared in wl_android.h)
907 int wl_android_wifi_on(struct net_device *dev)
910 #ifdef CONFIG_MACH_UNIVERSAL5433
912 /* Do not retry old revision Helsinki Prime */
916 retry = POWERUP_MAX_RETRY;
919 int retry = POWERUP_MAX_RETRY;
920 #endif /* CONFIG_MACH_UNIVERSAL5433 */
923 ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
927 printf("%s in 1\n", __FUNCTION__);
928 dhd_net_if_lock(dev);
929 printf("%s in 2: g_wifi_on=%d\n", __FUNCTION__, g_wifi_on);
932 dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY);
934 ret = dhd_net_bus_resume(dev, 0);
937 ret = dhd_net_bus_devreset(dev, FALSE);
941 ANDROID_ERROR(("\nfailed to power up wifi chip, retry again (%d left) **\n\n",
944 dhd_net_bus_devreset(dev, TRUE);
946 dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
947 } while (retry-- > 0);
949 ANDROID_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n"));
953 ret = dhd_net_bus_devreset(dev, FALSE);
956 dhd_net_bus_resume(dev, 1);
961 if (dhd_dev_init_ioctl(dev) < 0) {
966 #endif /* !BCMPCIE */
971 printf("%s: Success\n", __FUNCTION__);
972 dhd_net_if_unlock(dev);
977 dhd_net_bus_devreset(dev, TRUE);
978 dhd_net_bus_suspend(dev);
979 dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
980 printf("%s: Failed\n", __FUNCTION__);
981 dhd_net_if_unlock(dev);
986 int wl_android_wifi_off(struct net_device *dev)
991 ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
995 printf("%s in 1\n", __FUNCTION__);
996 dhd_net_if_lock(dev);
997 printf("%s in 2: g_wifi_on=%d\n", __FUNCTION__, g_wifi_on);
999 #if defined(BCMSDIO) || defined(BCMPCIE)
1000 ret = dhd_net_bus_devreset(dev, TRUE);
1002 dhd_net_bus_suspend(dev);
1003 #endif /* BCMSDIO */
1004 #endif /* BCMSDIO || BCMPCIE */
1005 dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
1008 printf("%s out\n", __FUNCTION__);
1009 dhd_net_if_unlock(dev);
1014 static int wl_android_set_fwpath(struct net_device *net, char *command, int total_len)
1016 if ((strlen(command) - strlen(CMD_SETFWPATH)) > MOD_PARAM_PATHLEN)
1018 return dhd_net_set_fw_path(net, command + strlen(CMD_SETFWPATH) + 1);
1021 #ifdef CONNECTION_STATISTICS
1023 wl_chanim_stats(struct net_device *dev, u8 *chan_idle)
1026 wl_chanim_stats_t *list;
1027 /* Parameter _and_ returned buffer of chanim_stats. */
1028 wl_chanim_stats_t param;
1029 u8 result[WLC_IOCTL_SMLEN];
1030 chanim_stats_t *stats;
1032 memset(¶m, 0, sizeof(param));
1033 memset(result, 0, sizeof(result));
1035 param.buflen = htod32(sizeof(wl_chanim_stats_t));
1036 param.count = htod32(WL_CHANIM_COUNT_ONE);
1038 if ((err = wldev_iovar_getbuf(dev, "chanim_stats", (char*)¶m, sizeof(wl_chanim_stats_t),
1039 (char*)result, sizeof(result), 0)) < 0) {
1040 ANDROID_ERROR(("Failed to get chanim results %d \n", err));
1044 list = (wl_chanim_stats_t*)result;
1046 list->buflen = dtoh32(list->buflen);
1047 list->version = dtoh32(list->version);
1048 list->count = dtoh32(list->count);
1050 if (list->buflen == 0) {
1053 } else if (list->version != WL_CHANIM_STATS_VERSION) {
1054 ANDROID_ERROR(("Sorry, firmware has wl_chanim_stats version %d "
1055 "but driver supports only version %d.\n",
1056 list->version, WL_CHANIM_STATS_VERSION));
1061 stats = list->stats;
1062 stats->glitchcnt = dtoh32(stats->glitchcnt);
1063 stats->badplcp = dtoh32(stats->badplcp);
1064 stats->chanspec = dtoh16(stats->chanspec);
1065 stats->timestamp = dtoh32(stats->timestamp);
1066 stats->chan_idle = dtoh32(stats->chan_idle);
1068 ANDROID_INFO(("chanspec: 0x%4x glitch: %d badplcp: %d idle: %d timestamp: %d\n",
1069 stats->chanspec, stats->glitchcnt, stats->badplcp, stats->chan_idle,
1072 *chan_idle = stats->chan_idle;
1078 wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len)
1080 wl_cnt_t* cnt = NULL;
1082 struct connection_stats *output;
1083 unsigned int bufsize = 0;
1084 int bytes_written = 0;
1087 ANDROID_INFO(("%s: enter Get Connection Stats\n", __FUNCTION__));
1089 if (total_len <= 0) {
1090 ANDROID_ERROR(("%s: invalid buffer size %d\n", __FUNCTION__, total_len));
1094 bufsize = total_len;
1095 if (bufsize < sizeof(struct connection_stats)) {
1096 ANDROID_ERROR(("%s: not enough buffer size, provided=%u, requires=%u\n",
1097 __FUNCTION__, bufsize,
1098 sizeof(struct connection_stats)));
1102 if ((cnt = kmalloc(sizeof(*cnt), GFP_KERNEL)) == NULL) {
1103 ANDROID_ERROR(("kmalloc failed\n"));
1106 memset(cnt, 0, sizeof(*cnt));
1108 ret = wldev_iovar_getbuf(dev, "counters", NULL, 0, (char *)cnt, sizeof(wl_cnt_t), NULL);
1110 ANDROID_ERROR(("%s: wldev_iovar_getbuf() failed, ret=%d\n",
1111 __FUNCTION__, ret));
1115 if (dtoh16(cnt->version) > WL_CNT_T_VERSION) {
1116 ANDROID_ERROR(("%s: incorrect version of wl_cnt_t, expected=%u got=%u\n",
1117 __FUNCTION__, WL_CNT_T_VERSION, cnt->version));
1121 /* link_speed is in kbps */
1122 ret = wldev_get_link_speed(dev, &link_speed);
1123 if (ret || link_speed < 0) {
1124 ANDROID_ERROR(("%s: wldev_get_link_speed() failed, ret=%d, speed=%d\n",
1125 __FUNCTION__, ret, link_speed));
1129 output = (struct connection_stats *)command;
1130 output->txframe = dtoh32(cnt->txframe);
1131 output->txbyte = dtoh32(cnt->txbyte);
1132 output->txerror = dtoh32(cnt->txerror);
1133 output->rxframe = dtoh32(cnt->rxframe);
1134 output->rxbyte = dtoh32(cnt->rxbyte);
1135 output->txfail = dtoh32(cnt->txfail);
1136 output->txretry = dtoh32(cnt->txretry);
1137 output->txretrie = dtoh32(cnt->txretrie);
1138 output->txrts = dtoh32(cnt->txrts);
1139 output->txnocts = dtoh32(cnt->txnocts);
1140 output->txexptime = dtoh32(cnt->txexptime);
1141 output->txrate = link_speed;
1143 /* Channel idle ratio. */
1144 if (wl_chanim_stats(dev, &(output->chan_idle)) < 0) {
1145 output->chan_idle = 0;
1150 bytes_written = sizeof(struct connection_stats);
1151 return bytes_written;
1159 #endif /* CONNECTION_STATISTICS */
1162 wl_android_set_pmk(struct net_device *dev, char *command, int total_len)
1166 char smbuf[WLC_IOCTL_SMLEN];
1171 bzero(pmk, sizeof(pmk));
1172 memcpy((char *)pmk, command + strlen("SET_PMK "), 32);
1173 error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL);
1175 ANDROID_ERROR(("Failed to set PMK for OKC, error = %d\n", error));
1178 ANDROID_ERROR(("PMK is "));
1179 for (i = 0; i < 32; i++)
1180 ANDROID_ERROR(("%02X ", pmk[i]));
1182 ANDROID_ERROR(("\n"));
1188 wl_android_okc_enable(struct net_device *dev, char *command, int total_len)
1191 char okc_enable = 0;
1193 okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0';
1194 error = wldev_iovar_setint(dev, "okc_enable", okc_enable);
1196 ANDROID_ERROR(("Failed to %s OKC, error = %d\n",
1197 okc_enable ? "enable" : "disable", error));
1200 wldev_iovar_setint(dev, "ccx_enable", 0);
1207 int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len)
1212 if (sscanf(command, "%*s %d", &mode) != 1) {
1213 ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
1217 error = wldev_iovar_setint(dev, "roam_off", mode);
1219 ANDROID_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n",
1220 __FUNCTION__, mode, error));
1224 ANDROID_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n",
1225 __FUNCTION__, mode, error));
1230 int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, int total_len)
1232 char ie_buf[VNDR_IE_MAX_LEN];
1233 char *ioctl_buf = NULL;
1236 int ielen = 0, datalen = 0, idx = 0, tot_len = 0;
1237 vndr_ie_setbuf_t *vndr_ie = NULL;
1240 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1243 /* Check the VSIE (Vendor Specific IE) which was added.
1244 * If exist then send IOVAR to delete it
1246 if (wl_cfg80211_ibss_vsie_delete(dev) != BCME_OK) {
1250 pcmd = command + strlen(CMD_SETIBSSBEACONOUIDATA) + 1;
1251 for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
1254 ie_buf[idx] = (uint8)simple_strtoul(hex, NULL, 16);
1257 while ((*pcmd != '\0') && (idx < VNDR_IE_MAX_LEN)) {
1260 ie_buf[idx++] = (uint8)simple_strtoul(hex, NULL, 16);
1263 tot_len = sizeof(vndr_ie_setbuf_t) + (datalen - 1);
1264 vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
1266 ANDROID_ERROR(("IE memory alloc failed\n"));
1269 /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
1270 strncpy(vndr_ie->cmd, "add", VNDR_IE_CMD_LEN - 1);
1271 vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
1273 /* Set the IE count - the buffer contains only 1 IE */
1274 iecount = htod32(1);
1275 memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
1277 /* Set packet flag to indicate that BEACON's will contain this IE */
1278 pktflag = htod32(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG);
1279 memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
1282 vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar) DOT11_MNG_PROPR_ID;
1284 memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, &ie_buf,
1286 memcpy(&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data,
1287 &ie_buf[DOT11_OUI_LEN], datalen);
1289 ielen = DOT11_OUI_LEN + datalen;
1290 vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
1292 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
1294 ANDROID_ERROR(("ioctl memory alloc failed\n"));
1300 memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN); /* init the buffer */
1301 err = wldev_iovar_setbuf(dev, "ie", vndr_ie, tot_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1304 if (err != BCME_OK) {
1311 /* do NOT free 'vndr_ie' for the next process */
1312 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie, tot_len);
1323 #if defined(BCMFW_ROAM_ENABLE)
1325 wl_android_set_roampref(struct net_device *dev, char *command, int total_len)
1328 char smbuf[WLC_IOCTL_SMLEN];
1329 uint8 buf[MAX_BUF_SIZE];
1332 int num_ucipher_suites = 0;
1333 int num_akm_suites = 0;
1334 wpa_suite_t ucipher_suites[MAX_NUM_SUITES];
1335 wpa_suite_t akm_suites[MAX_NUM_SUITES];
1337 int total_bytes = 0;
1342 pcmd = command + strlen(CMD_SET_ROAMPREF) + 1;
1343 total_len_left = total_len - strlen(CMD_SET_ROAMPREF) + 1;
1345 num_akm_suites = simple_strtoul(pcmd, NULL, 16);
1346 /* Increment for number of AKM suites field + space */
1348 total_len_left -= 3;
1350 /* check to make sure pcmd does not overrun */
1351 if (total_len_left < (num_akm_suites * WIDTH_AKM_SUITE))
1354 memset(buf, 0, sizeof(buf));
1355 memset(akm_suites, 0, sizeof(akm_suites));
1356 memset(ucipher_suites, 0, sizeof(ucipher_suites));
1358 /* Save the AKM suites passed in the command */
1359 for (i = 0; i < num_akm_suites; i++) {
1360 /* Store the MSB first, as required by join_pref */
1361 for (j = 0; j < 4; j++) {
1364 buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
1366 memcpy((uint8 *)&akm_suites[i], buf, sizeof(uint32));
1369 total_len_left -= (num_akm_suites * WIDTH_AKM_SUITE);
1370 num_ucipher_suites = simple_strtoul(pcmd, NULL, 16);
1371 /* Increment for number of cipher suites field + space */
1373 total_len_left -= 3;
1375 if (total_len_left < (num_ucipher_suites * WIDTH_AKM_SUITE))
1378 /* Save the cipher suites passed in the command */
1379 for (i = 0; i < num_ucipher_suites; i++) {
1380 /* Store the MSB first, as required by join_pref */
1381 for (j = 0; j < 4; j++) {
1384 buf[j] = (uint8)simple_strtoul(hex, NULL, 16);
1386 memcpy((uint8 *)&ucipher_suites[i], buf, sizeof(uint32));
1389 /* Join preference for RSSI
1390 * Type : 1 byte (0x01)
1391 * Length : 1 byte (0x02)
1392 * Value : 2 bytes (reserved)
1394 *pref++ = WL_JOIN_PREF_RSSI;
1395 *pref++ = JOIN_PREF_RSSI_LEN;
1399 /* Join preference for WPA
1400 * Type : 1 byte (0x02)
1401 * Length : 1 byte (not used)
1402 * Value : (variable length)
1404 * count : 1 byte (no of tuples)
1412 num_tuples = num_akm_suites * num_ucipher_suites;
1413 if (num_tuples != 0) {
1414 if (num_tuples <= JOIN_PREF_MAX_WPA_TUPLES) {
1415 *pref++ = WL_JOIN_PREF_WPA;
1418 *pref++ = (uint8)num_tuples;
1419 total_bytes = JOIN_PREF_RSSI_SIZE + JOIN_PREF_WPA_HDR_SIZE +
1420 (JOIN_PREF_WPA_TUPLE_SIZE * num_tuples);
1422 ANDROID_ERROR(("%s: Too many wpa configs for join_pref \n", __FUNCTION__));
1426 /* No WPA config, configure only RSSI preference */
1427 total_bytes = JOIN_PREF_RSSI_SIZE;
1430 /* akm-ucipher-mcipher tuples in the format required for join_pref */
1431 for (i = 0; i < num_ucipher_suites; i++) {
1432 for (j = 0; j < num_akm_suites; j++) {
1433 memcpy(pref, (uint8 *)&akm_suites[j], WPA_SUITE_LEN);
1434 pref += WPA_SUITE_LEN;
1435 memcpy(pref, (uint8 *)&ucipher_suites[i], WPA_SUITE_LEN);
1436 pref += WPA_SUITE_LEN;
1437 /* Set to 0 to match any available multicast cipher */
1438 memset(pref, 0, WPA_SUITE_LEN);
1439 pref += WPA_SUITE_LEN;
1443 prhex("join pref", (uint8 *)buf, total_bytes);
1444 error = wldev_iovar_setbuf(dev, "join_pref", buf, total_bytes, smbuf, sizeof(smbuf), NULL);
1446 ANDROID_ERROR(("Failed to set join_pref, error = %d\n", error));
1450 #endif /* defined(BCMFW_ROAM_ENABLE */
1454 wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_cfg *config)
1456 struct io_cfg *resume_cfg;
1459 resume_cfg = kzalloc(sizeof(struct io_cfg), GFP_KERNEL);
1463 if (config->iovar) {
1464 ret = wldev_iovar_getint(dev, config->iovar, &resume_cfg->param);
1466 ANDROID_ERROR(("%s: Failed to get current %s value\n",
1467 __FUNCTION__, config->iovar));
1471 ret = wldev_iovar_setint(dev, config->iovar, config->param);
1473 ANDROID_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
1474 config->iovar, config->param));
1478 resume_cfg->iovar = config->iovar;
1480 resume_cfg->arg = kzalloc(config->len, GFP_KERNEL);
1481 if (!resume_cfg->arg) {
1485 ret = wldev_ioctl(dev, config->ioctl, resume_cfg->arg, config->len, false);
1487 ANDROID_ERROR(("%s: Failed to get ioctl %d\n", __FUNCTION__,
1491 ret = wldev_ioctl(dev, config->ioctl + 1, config->arg, config->len, true);
1493 ANDROID_ERROR(("%s: Failed to set %s to %d\n", __FUNCTION__,
1494 config->iovar, config->param));
1497 if (config->ioctl + 1 == WLC_SET_PM)
1498 wl_cfg80211_update_power_mode(dev);
1499 resume_cfg->ioctl = config->ioctl;
1500 resume_cfg->len = config->len;
1503 list_add(&resume_cfg->list, head);
1507 kfree(resume_cfg->arg);
1513 wl_android_iolist_resume(struct net_device *dev, struct list_head *head)
1515 struct io_cfg *config;
1516 struct list_head *cur, *q;
1519 list_for_each_safe(cur, q, head) {
1520 config = list_entry(cur, struct io_cfg, list);
1521 if (config->iovar) {
1523 ret = wldev_iovar_setint(dev, config->iovar,
1527 ret = wldev_ioctl(dev, config->ioctl + 1,
1528 config->arg, config->len, true);
1529 if (config->ioctl + 1 == WLC_SET_PM)
1530 wl_cfg80211_update_power_mode(dev);
1539 wl_android_set_miracast(struct net_device *dev, char *command, int total_len)
1543 struct io_cfg config;
1545 if (sscanf(command, "%*s %d", &mode) != 1) {
1546 ANDROID_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__));
1550 ANDROID_INFO(("%s: enter miracast mode %d\n", __FUNCTION__, mode));
1552 if (miracast_cur_mode == mode)
1555 wl_android_iolist_resume(dev, &miracast_resume_list);
1556 miracast_cur_mode = MIRACAST_MODE_OFF;
1559 case MIRACAST_MODE_SOURCE:
1560 /* setting mchan_algo to platform specific value */
1561 config.iovar = "mchan_algo";
1563 ret = wldev_ioctl(dev, WLC_GET_BCNPRD, &val, sizeof(int), false);
1564 if (!ret && val > 100) {
1566 ANDROID_ERROR(("%s: Connected station's beacon interval: "
1567 "%d and set mchan_algo to %d \n",
1568 __FUNCTION__, val, config.param));
1571 config.param = MIRACAST_MCHAN_ALGO;
1573 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
1577 /* setting mchan_bw to platform specific value */
1578 config.iovar = "mchan_bw";
1579 config.param = MIRACAST_MCHAN_BW;
1580 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
1584 /* setting apmdu to platform specific value */
1585 config.iovar = "ampdu_mpdu";
1586 config.param = MIRACAST_AMPDU_SIZE;
1587 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
1591 /* Source mode shares most configurations with sink mode.
1592 * Fall through here to avoid code duplication
1594 case MIRACAST_MODE_SINK:
1595 /* disable internal roaming */
1596 config.iovar = "roam_off";
1598 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
1603 config.iovar = NULL;
1604 config.ioctl = WLC_GET_PM;
1606 config.len = sizeof(int);
1607 ret = wl_android_iolist_add(dev, &miracast_resume_list, &config);
1612 case MIRACAST_MODE_OFF:
1616 miracast_cur_mode = mode;
1621 ANDROID_ERROR(("%s: turnoff miracast mode because of err%d\n", __FUNCTION__, ret));
1622 wl_android_iolist_resume(dev, &miracast_resume_list);
1627 #define NETLINK_OXYGEN 30
1628 #define AIBSS_BEACON_TIMEOUT 10
1630 static struct sock *nl_sk = NULL;
1632 static void wl_netlink_recv(struct sk_buff *skb)
1634 ANDROID_ERROR(("netlink_recv called\n"));
1637 static int wl_netlink_init(void)
1639 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
1640 struct netlink_kernel_cfg cfg = {
1641 .input = wl_netlink_recv,
1645 if (nl_sk != NULL) {
1646 ANDROID_ERROR(("nl_sk already exist\n"));
1650 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
1651 nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN,
1652 0, wl_netlink_recv, NULL, THIS_MODULE);
1653 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0))
1654 nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, THIS_MODULE, &cfg);
1656 nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, &cfg);
1659 if (nl_sk == NULL) {
1660 ANDROID_ERROR(("nl_sk is not ready\n"));
1667 static void wl_netlink_deinit(void)
1670 netlink_kernel_release(nl_sk);
1676 wl_netlink_send_msg(int pid, int type, int seq, void *data, size_t size)
1678 struct sk_buff *skb = NULL;
1679 struct nlmsghdr *nlh = NULL;
1682 if (nl_sk == NULL) {
1683 ANDROID_ERROR(("nl_sk was not initialized\n"));
1687 skb = alloc_skb(NLMSG_SPACE(size), GFP_ATOMIC);
1689 ANDROID_ERROR(("failed to allocate memory\n"));
1693 nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
1695 ANDROID_ERROR(("failed to build nlmsg, skb_tailroom:%d, nlmsg_total_size:%d\n",
1696 skb_tailroom(skb), nlmsg_total_size(size)));
1701 memcpy(nlmsg_data(nlh), data, size);
1702 nlh->nlmsg_seq = seq;
1703 nlh->nlmsg_type = type;
1705 /* netlink_unicast() takes ownership of the skb and frees it itself. */
1706 ret = netlink_unicast(nl_sk, skb, pid, 0);
1707 ANDROID_TRACE(("netlink_unicast() pid=%d, ret=%d\n", pid, ret));
1714 static int wl_android_set_ibss_txfail_event(struct net_device *dev, char *command, int total_len)
1719 aibss_txfail_config_t txfail_config = {0, 0, 0, 0};
1720 char smbuf[WLC_IOCTL_SMLEN];
1722 if (sscanf(command, CMD_SETIBSSTXFAILEVENT " %d %d", &retry, &pid) <= 0) {
1723 ANDROID_ERROR(("Failed to get Parameter from : %s\n", command));
1727 /* set pid, and if the event was happened, let's send a notification through netlink */
1728 wl_cfg80211_set_txfail_pid(pid);
1730 /* If retry value is 0, it disables the functionality for TX Fail. */
1732 txfail_config.max_tx_retry = retry;
1733 txfail_config.bcn_timeout = 0; /* 0 : disable tx fail from beacon */
1735 txfail_config.version = AIBSS_TXFAIL_CONFIG_VER_0;
1736 txfail_config.len = sizeof(txfail_config);
1738 err = wldev_iovar_setbuf(dev, "aibss_txfail_config", (void *) &txfail_config,
1739 sizeof(aibss_txfail_config_t), smbuf, WLC_IOCTL_SMLEN, NULL);
1740 ANDROID_TRACE(("retry=%d, pid=%d, err=%d\n", retry, pid, err));
1742 return ((err == 0)?total_len:err);
1745 static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command,
1746 int total_len, bool bAll)
1749 int bytes_written = 0;
1751 bss_peer_list_info_t peer_list_info;
1752 bss_peer_info_t *peer_info;
1755 struct ether_addr mac_ea;
1757 ANDROID_TRACE(("get ibss peer info(%s)\n", bAll?"true":"false"));
1760 if (sscanf (command, "GETIBSSPEERINFO %02x:%02x:%02x:%02x:%02x:%02x",
1761 (unsigned int *)&mac_ea.octet[0], (unsigned int *)&mac_ea.octet[1],
1762 (unsigned int *)&mac_ea.octet[2], (unsigned int *)&mac_ea.octet[3],
1763 (unsigned int *)&mac_ea.octet[4], (unsigned int *)&mac_ea.octet[5]) != 6) {
1764 ANDROID_TRACE(("invalid MAC address\n"));
1769 if ((buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL)) == NULL) {
1770 ANDROID_ERROR(("kmalloc failed\n"));
1774 error = wldev_iovar_getbuf(dev, "bss_peer_info", NULL, 0, buf, WLC_IOCTL_MAXLEN, NULL);
1775 if (unlikely(error)) {
1776 ANDROID_ERROR(("could not get ibss peer info (%d)\n", error));
1781 memcpy(&peer_list_info, buf, sizeof(peer_list_info));
1782 peer_list_info.version = htod16(peer_list_info.version);
1783 peer_list_info.bss_peer_info_len = htod16(peer_list_info.bss_peer_info_len);
1784 peer_list_info.count = htod32(peer_list_info.count);
1786 ANDROID_TRACE(("ver:%d, len:%d, count:%d\n", peer_list_info.version,
1787 peer_list_info.bss_peer_info_len, peer_list_info.count));
1789 if (peer_list_info.count > 0) {
1791 bytes_written += sprintf(&command[bytes_written], "%u ",
1792 peer_list_info.count);
1794 peer_info = (bss_peer_info_t *) ((void *)buf + BSS_PEER_LIST_INFO_FIXED_LEN);
1797 for (i = 0; i < peer_list_info.count; i++) {
1799 ANDROID_TRACE(("index:%d rssi:%d, tx:%u, rx:%u\n", i, peer_info->rssi,
1800 peer_info->tx_rate, peer_info->rx_rate));
1803 memcmp(&mac_ea, &peer_info->ea, sizeof(struct ether_addr)) == 0) {
1807 if (bAll || found) {
1808 bytes_written += sprintf(&command[bytes_written], MACF,
1809 ETHER_TO_MACF(peer_info->ea));
1810 bytes_written += sprintf(&command[bytes_written], " %u %d ",
1811 peer_info->tx_rate/1000, peer_info->rssi);
1817 peer_info = (bss_peer_info_t *)((void *)peer_info+sizeof(bss_peer_info_t));
1821 ANDROID_ERROR(("could not get ibss peer info : no item\n"));
1823 bytes_written += sprintf(&command[bytes_written], "%s", "\0");
1825 ANDROID_TRACE(("command(%u):%s\n", total_len, command));
1826 ANDROID_TRACE(("bytes_written:%d\n", bytes_written));
1829 return bytes_written;
1832 int wl_android_set_ibss_routetable(struct net_device *dev, char *command, int total_len)
1835 char *pcmd = command;
1838 ibss_route_tbl_t *route_tbl = NULL;
1839 char *ioctl_buf = NULL;
1840 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
1842 uint32 route_tbl_len;
1846 struct ipv4_addr dipaddr;
1847 struct ether_addr ea;
1849 route_tbl_len = sizeof(ibss_route_tbl_t) +
1850 (MAX_IBSS_ROUTE_TBL_ENTRY - 1) * sizeof(ibss_route_entry_t);
1851 route_tbl = (ibss_route_tbl_t *)kzalloc(route_tbl_len, kflags);
1853 ANDROID_ERROR(("Route TBL alloc failed\n"));
1856 ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
1858 ANDROID_ERROR(("ioctl memory alloc failed\n"));
1864 memset(ioctl_buf, 0, WLC_IOCTL_MEDLEN);
1867 str = bcmstrtok(&pcmd, " ", NULL);
1870 str = bcmstrtok(&pcmd, " ", NULL);
1872 ANDROID_ERROR(("Invalid number parameter %s\n", str));
1876 entries = bcm_strtoul(str, &endptr, 0);
1877 if (*endptr != '\0') {
1878 ANDROID_ERROR(("Invalid number parameter %s\n", str));
1882 ANDROID_INFO(("Routing table count:%d\n", entries));
1883 route_tbl->num_entry = entries;
1885 for (i = 0; i < entries; i++) {
1886 str = bcmstrtok(&pcmd, " ", NULL);
1887 if (!str || !bcm_atoipv4(str, &dipaddr)) {
1888 ANDROID_ERROR(("Invalid ip string %s\n", str));
1894 str = bcmstrtok(&pcmd, " ", NULL);
1895 if (!str || !bcm_ether_atoe(str, &ea)) {
1896 ANDROID_ERROR(("Invalid ethernet string %s\n", str));
1900 bcopy(&dipaddr, &route_tbl->route_entry[i].ipv4_addr, IPV4_ADDR_LEN);
1901 bcopy(&ea, &route_tbl->route_entry[i].nexthop, ETHER_ADDR_LEN);
1904 route_tbl_len = sizeof(ibss_route_tbl_t) +
1905 ((!entries?0:(entries - 1)) * sizeof(ibss_route_entry_t));
1906 err = wldev_iovar_setbuf(dev, "ibss_route_tbl",
1907 route_tbl, route_tbl_len, ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1908 if (err != BCME_OK) {
1909 ANDROID_ERROR(("Fail to set iovar %d\n", err));
1923 wl_android_set_ibss_ampdu(struct net_device *dev, char *command, int total_len)
1925 char *pcmd = command;
1926 char *str = NULL, *endptr = NULL;
1927 struct ampdu_aggr aggr;
1928 char smbuf[WLC_IOCTL_SMLEN];
1931 int wme_AC2PRIO[AC_COUNT][2] = {
1932 {PRIO_8021D_VO, PRIO_8021D_NC}, /* AC_VO - 3 */
1933 {PRIO_8021D_CL, PRIO_8021D_VI}, /* AC_VI - 2 */
1934 {PRIO_8021D_BK, PRIO_8021D_NONE}, /* AC_BK - 1 */
1935 {PRIO_8021D_BE, PRIO_8021D_EE}}; /* AC_BE - 0 */
1937 ANDROID_TRACE(("set ibss ampdu:%s\n", command));
1939 memset(&aggr, 0, sizeof(aggr));
1940 /* Cofigure all priorities */
1941 aggr.conf_TID_bmap = NBITMASK(NUMPRIO);
1943 /* acquire parameters */
1945 str = bcmstrtok(&pcmd, " ", NULL);
1947 for (idx = 0; idx < AC_COUNT; idx++) {
1949 str = bcmstrtok(&pcmd, " ", NULL);
1951 ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
1954 on = bcm_strtoul(str, &endptr, 0) ? TRUE : FALSE;
1955 if (*endptr != '\0') {
1956 ANDROID_ERROR(("Invalid number format %s\n", str));
1960 setbit(&aggr.enab_TID_bmap, wme_AC2PRIO[idx][0]);
1961 setbit(&aggr.enab_TID_bmap, wme_AC2PRIO[idx][1]);
1965 err = wldev_iovar_setbuf(dev, "ampdu_txaggr", (void *)&aggr,
1966 sizeof(aggr), smbuf, WLC_IOCTL_SMLEN, NULL);
1968 return ((err == 0) ? total_len : err);
1971 int wl_android_set_ibss_antenna(struct net_device *dev, char *command, int total_len)
1973 char *pcmd = command;
1975 int txchain, rxchain;
1978 ANDROID_TRACE(("set ibss antenna:%s\n", command));
1980 /* acquire parameters */
1982 str = bcmstrtok(&pcmd, " ", NULL);
1985 str = bcmstrtok(&pcmd, " ", NULL);
1987 ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
1990 txchain = bcm_atoi(str);
1993 str = bcmstrtok(&pcmd, " ", NULL);
1995 ANDROID_ERROR(("Invalid parameter : %s\n", pcmd));
1998 rxchain = bcm_atoi(str);
2000 err = wldev_iovar_setint(dev, "txchain", txchain);
2003 err = wldev_iovar_setint(dev, "rxchain", rxchain);
2004 return ((err == 0)?total_len:err);
2006 #endif /* WLAIBSS */
2008 int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
2012 wl_mkeep_alive_pkt_t mkeep_alive_pkt;
2013 wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
2017 uint period_msec = 0;
2021 ANDROID_ERROR(("%s: extra is NULL\n", __FUNCTION__));
2024 if (sscanf(extra, "%d", &period_msec) != 1)
2026 ANDROID_ERROR(("%s: sscanf error. check period_msec value\n", __FUNCTION__));
2029 ANDROID_ERROR(("%s: period_msec is %d\n", __FUNCTION__, period_msec));
2031 memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t));
2033 str = "mkeep_alive";
2034 str_len = strlen(str);
2035 strncpy(buf, str, str_len);
2036 buf[ str_len ] = '\0';
2037 mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
2038 mkeep_alive_pkt.period_msec = period_msec;
2039 buf_len = str_len + 1;
2040 mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
2041 mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
2043 /* Setup keep alive zero for null packet generation */
2044 mkeep_alive_pkt.keep_alive_id = 0;
2045 mkeep_alive_pkt.len_bytes = 0;
2046 buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
2047 /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and
2048 * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
2049 * guarantee that the buffer is properly aligned.
2051 memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
2053 if ((res = wldev_ioctl(dev, WLC_SET_VAR, buf, buf_len, TRUE)) < 0)
2055 ANDROID_ERROR(("%s:keep_alive set failed. res[%d]\n", __FUNCTION__, res));
2059 ANDROID_ERROR(("%s:keep_alive set ok. res[%d]\n", __FUNCTION__, res));
2067 get_string_by_separator(char *result, int result_len, const char *src, char separator)
2069 char *end = result + result_len - 1;
2070 while ((result != end) && (*src != separator) && (*src)) {
2074 if (*src == separator)
2080 wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd)
2083 int i, cnt, size, err, ioctl_buf_len;
2084 roamoffl_bssid_list_t *bssid_list;
2085 const char *str = cmd;
2088 str = get_string_by_separator(sbuf, 32, str, ',');
2089 cnt = bcm_atoi(sbuf);
2090 cnt = MIN(cnt, MAX_ROAMOFFL_BSSID_NUM);
2091 size = sizeof(int) + sizeof(struct ether_addr) * cnt;
2092 ANDROID_ERROR(("ROAM OFFLOAD BSSID LIST %d BSSIDs, size %d\n", cnt, size));
2093 bssid_list = kmalloc(size, GFP_KERNEL);
2094 if (bssid_list == NULL) {
2095 ANDROID_ERROR(("%s: memory alloc for bssid list(%d) failed\n",
2096 __FUNCTION__, size));
2099 ioctl_buf_len = size + 64;
2100 ioctl_buf = kmalloc(ioctl_buf_len, GFP_KERNEL);
2101 if (ioctl_buf == NULL) {
2102 ANDROID_ERROR(("%s: memory alloc for ioctl_buf(%d) failed\n",
2103 __FUNCTION__, ioctl_buf_len));
2108 for (i = 0; i < cnt; i++) {
2109 str = get_string_by_separator(sbuf, 32, str, ',');
2110 if (bcm_ether_atoe(sbuf, &bssid_list->bssid[i]) == 0) {
2111 ANDROID_ERROR(("%s: Invalid station MAC Address!!!\n", __FUNCTION__));
2118 bssid_list->cnt = cnt;
2119 err = wldev_iovar_setbuf(dev, "roamoffl_bssid_list",
2120 bssid_list, size, ioctl_buf, ioctl_buf_len, NULL);
2127 #ifdef P2PRESP_WFDIE_SRC
2128 static int wl_android_get_wfdie_resp(struct net_device *dev, char *command, int total_len)
2131 int bytes_written = 0;
2132 int only_resp_wfdsrc = 0;
2134 error = wldev_iovar_getint(dev, "p2p_only_resp_wfdsrc", &only_resp_wfdsrc);
2136 ANDROID_ERROR(("%s: Failed to get the mode for only_resp_wfdsrc, error = %d\n",
2137 __FUNCTION__, error));
2141 bytes_written = snprintf(command, total_len, "%s %d",
2142 CMD_P2P_GET_WFDIE_RESP, only_resp_wfdsrc);
2144 return bytes_written;
2147 static int wl_android_set_wfdie_resp(struct net_device *dev, int only_resp_wfdsrc)
2151 error = wldev_iovar_setint(dev, "p2p_only_resp_wfdsrc", only_resp_wfdsrc);
2153 ANDROID_ERROR(("%s: Failed to set only_resp_wfdsrc %d, error = %d\n",
2154 __FUNCTION__, only_resp_wfdsrc, error));
2160 #endif /* P2PRESP_WFDIE_SRC */
2162 static int wl_android_get_link_status(struct net_device *dev, char *command,
2165 int bytes_written, error, result = 0, single_stream, stf = -1, i, nss = 0, mcs_map;
2167 uint encode, rate, txexp;
2168 struct wl_bss_info *bi;
2169 int datalen = sizeof(uint32) + sizeof(wl_bss_info_t);
2172 /* get BSS information */
2173 *(u32 *) buf = htod32(datalen);
2174 error = wldev_ioctl(dev, WLC_GET_BSS_INFO, (void *)buf, datalen, false);
2175 if (unlikely(error)) {
2176 ANDROID_ERROR(("Could not get bss info %d\n", error));
2180 bi = (struct wl_bss_info *) (buf + sizeof(uint32));
2182 for (i = 0; i < ETHER_ADDR_LEN; i++) {
2183 if (bi->BSSID.octet[i] > 0) {
2188 if (i == ETHER_ADDR_LEN) {
2189 ANDROID_TRACE(("No BSSID\n"));
2193 /* check VHT capability at beacon */
2195 if (CHSPEC_IS5G(bi->chanspec)) {
2196 result |= WL_ANDROID_LINK_AP_VHT_SUPPORT;
2200 /* get a rspec (radio spectrum) rate */
2201 error = wldev_iovar_getint(dev, "nrate", &rspec);
2202 if (unlikely(error) || rspec == 0) {
2203 ANDROID_ERROR(("get link status error (%d)\n", error));
2207 encode = (rspec & WL_RSPEC_ENCODING_MASK);
2208 rate = (rspec & WL_RSPEC_RATE_MASK);
2209 txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
2212 case WL_RSPEC_ENCODE_HT:
2213 /* check Rx MCS Map for HT */
2214 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
2216 if (i == MAX_STREAMS_SUPPORTED-1) {
2219 if (bi->basic_mcs[i] & bitmap) {
2224 case WL_RSPEC_ENCODE_VHT:
2225 /* check Rx MCS Map for VHT */
2226 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
2227 mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
2228 if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
2235 /* check MIMO capability with nss in beacon */
2237 result |= WL_ANDROID_LINK_AP_MIMO_SUPPORT;
2240 single_stream = (encode == WL_RSPEC_ENCODE_RATE) ||
2241 ((encode == WL_RSPEC_ENCODE_HT) && rate < 8) ||
2242 ((encode == WL_RSPEC_ENCODE_VHT) &&
2243 ((rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT) == 1);
2246 if ((rspec & WL_RSPEC_STBC) && single_stream) {
2247 stf = OLD_NRATE_STF_STBC;
2249 stf = (single_stream) ? OLD_NRATE_STF_SISO : OLD_NRATE_STF_SDM;
2251 } else if (txexp == 1 && single_stream) {
2252 stf = OLD_NRATE_STF_CDD;
2255 /* check 11ac (VHT) */
2256 if (encode == WL_RSPEC_ENCODE_VHT) {
2257 if (CHSPEC_IS5G(bi->chanspec)) {
2258 result |= WL_ANDROID_LINK_VHT;
2263 if (result & WL_ANDROID_LINK_AP_MIMO_SUPPORT) {
2265 case OLD_NRATE_STF_SISO:
2267 case OLD_NRATE_STF_CDD:
2268 case OLD_NRATE_STF_STBC:
2269 result |= WL_ANDROID_LINK_MIMO;
2271 case OLD_NRATE_STF_SDM:
2272 if (!single_stream) {
2273 result |= WL_ANDROID_LINK_MIMO;
2279 ANDROID_TRACE(("%s:result=%d, stf=%d, single_stream=%d, mcs map=%d\n",
2280 __FUNCTION__, result, stf, single_stream, nss));
2282 bytes_written = sprintf(command, "%s %d", CMD_GET_LINK_STATUS, result);
2284 return bytes_written;
2288 wl_android_get_channel(
2289 struct net_device *dev, char* command, int total_len)
2293 int bytes_written = 0;
2295 if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) {
2296 ANDROID_TRACE(("hw_channel %d\n", ci.hw_channel));
2297 ANDROID_TRACE(("target_channel %d\n", ci.target_channel));
2298 ANDROID_TRACE(("scan_channel %d\n", ci.scan_channel));
2299 bytes_written = snprintf(command, sizeof(channel_info_t)+2, "channel %d", ci.hw_channel);
2300 ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
2303 return bytes_written;
2307 wl_android_set_roam_trigger(
2308 struct net_device *dev, char* command, int total_len)
2311 int roam_trigger[2];
2313 sscanf(command, "%*s %10d", &roam_trigger[0]);
2314 roam_trigger[1] = WLC_BAND_ALL;
2316 ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 1);
2318 ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
2324 wl_android_get_roam_trigger(
2325 struct net_device *dev, char *command, int total_len)
2329 int roam_trigger[2] = {0, 0};
2330 int trigger[2]= {0, 0};
2332 roam_trigger[1] = WLC_BAND_2G;
2333 ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
2335 trigger[0] = roam_trigger[0];
2337 ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
2339 roam_trigger[1] = WLC_BAND_5G;
2340 ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
2342 trigger[1] = roam_trigger[0];
2344 ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
2346 ANDROID_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1]));
2347 bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]);
2349 return bytes_written;
2353 wl_android_get_keep_alive(struct net_device *dev, char *command, int total_len) {
2355 wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
2356 int bytes_written = -1;
2357 int res = -1, len, i = 0;
2358 char* str = "mkeep_alive";
2360 ANDROID_TRACE(("%s: command = %s\n", __FUNCTION__, command));
2362 len = WLC_IOCTL_MEDLEN;
2363 mkeep_alive_pktp = kmalloc(len, GFP_KERNEL);
2364 memset(mkeep_alive_pktp, 0, len);
2365 strcpy((char*)mkeep_alive_pktp, str);
2367 if ((res = wldev_ioctl(dev, WLC_GET_VAR, mkeep_alive_pktp, len, FALSE))<0) {
2368 ANDROID_ERROR(("%s: GET mkeep_alive ERROR %d\n", __FUNCTION__, res));
2372 "Period (msec) :%d\n"
2375 mkeep_alive_pktp->keep_alive_id,
2376 dtoh32(mkeep_alive_pktp->period_msec),
2377 dtoh16(mkeep_alive_pktp->len_bytes));
2378 for (i=0; i<mkeep_alive_pktp->len_bytes; i++) {
2379 printf("%02x", mkeep_alive_pktp->data[i]);
2383 bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", dtoh32(mkeep_alive_pktp->period_msec));
2384 bytes_written += snprintf(command+bytes_written, total_len, "0x");
2385 for (i=0; i<mkeep_alive_pktp->len_bytes; i++) {
2386 bytes_written += snprintf(command+bytes_written, total_len, "%x", mkeep_alive_pktp->data[i]);
2388 ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
2391 kfree(mkeep_alive_pktp);
2392 return bytes_written;
2396 wl_android_set_pm(struct net_device *dev,char *command, int total_len)
2400 ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command));
2402 sscanf(command, "%*s %d", &pm);
2404 ret = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE);
2406 ANDROID_ERROR(("WLC_SET_PM ERROR %d ret=%d\n", pm, ret));
2412 wl_android_get_pm(struct net_device *dev,char *command, int total_len)
2418 int bytes_written=-1;
2420 ret = wldev_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local),FALSE);
2422 ANDROID_TRACE(("%s: PM = %d\n", __func__, pm_local));
2423 if (pm_local == PM_OFF)
2425 else if(pm_local == PM_MAX)
2427 else if(pm_local == PM_FAST)
2433 bytes_written = snprintf(command, total_len, "PM %s", pm);
2434 ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
2436 return bytes_written;
2440 wl_android_set_monitor(struct net_device *dev, char *command, int total_len)
2446 sscanf(command, "%*s %d", &val);
2447 bytes_written = wldev_ioctl(dev, WLC_SET_MONITOR, &val, sizeof(int), 1);
2449 ANDROID_ERROR(("WLC_SET_MONITOR ERROR %d ret=%d\n", val, ret));
2450 return bytes_written;
2453 int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
2455 #define PRIVATE_COMMAND_MAX_LEN 8192
2457 char *command = NULL;
2458 int bytes_written = 0;
2459 android_wifi_priv_cmd priv_cmd;
2461 net_os_wake_lock(net);
2463 if (!ifr->ifr_data) {
2468 #ifdef CONFIG_COMPAT
2469 if (is_compat_task()) {
2470 compat_android_wifi_priv_cmd compat_priv_cmd;
2471 if (copy_from_user(&compat_priv_cmd, ifr->ifr_data,
2472 sizeof(compat_android_wifi_priv_cmd))) {
2477 priv_cmd.buf = compat_ptr(compat_priv_cmd.buf);
2478 priv_cmd.used_len = compat_priv_cmd.used_len;
2479 priv_cmd.total_len = compat_priv_cmd.total_len;
2481 #endif /* CONFIG_COMPAT */
2483 if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
2488 if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) {
2489 ANDROID_ERROR(("%s: too long priavte command\n", __FUNCTION__));
2493 command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL);
2496 ANDROID_ERROR(("%s: failed to allocate memory\n", __FUNCTION__));
2500 if (copy_from_user(command, priv_cmd.buf, priv_cmd.total_len)) {
2504 command[priv_cmd.total_len] = '\0';
2506 ANDROID_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name));
2508 if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) {
2509 ANDROID_INFO(("%s, Received regular START command\n", __FUNCTION__));
2510 bytes_written = wl_android_wifi_on(net);
2512 else if (strnicmp(command, CMD_SETFWPATH, strlen(CMD_SETFWPATH)) == 0) {
2513 bytes_written = wl_android_set_fwpath(net, command, priv_cmd.total_len);
2517 ANDROID_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n",
2518 __FUNCTION__, command, ifr->ifr_name));
2523 if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) {
2524 bytes_written = wl_android_wifi_off(net);
2526 else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) {
2527 /* TBD: SCAN-ACTIVE */
2529 else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) {
2530 /* TBD: SCAN-PASSIVE */
2532 else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) {
2533 bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len);
2535 else if (strnicmp(command, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) {
2536 bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len);
2538 #ifdef PKT_FILTER_SUPPORT
2539 else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) {
2540 bytes_written = net_os_enable_packet_filter(net, 1);
2542 else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) {
2543 bytes_written = net_os_enable_packet_filter(net, 0);
2545 else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) {
2546 int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
2547 bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
2549 else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) {
2550 int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
2551 bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
2553 #if defined(CUSTOM_PLATFORM_NV_TEGRA)
2554 else if (strnicmp(command, CMD_PKT_FILTER_MODE, strlen(CMD_PKT_FILTER_MODE)) == 0) {
2555 dhd_set_packet_filter_mode(net, &command[strlen(CMD_PKT_FILTER_MODE) + 1]);
2556 } else if (strnicmp(command, CMD_PKT_FILTER_PORTS, strlen(CMD_PKT_FILTER_PORTS)) == 0) {
2557 bytes_written = dhd_set_packet_filter_ports(net,
2558 &command[strlen(CMD_PKT_FILTER_PORTS) + 1]);
2559 ret = bytes_written;
2561 #endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
2562 #endif /* PKT_FILTER_SUPPORT */
2563 else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) {
2564 /* TBD: BTCOEXSCAN-START */
2566 else if (strnicmp(command, CMD_BTCOEXSCAN_STOP, strlen(CMD_BTCOEXSCAN_STOP)) == 0) {
2567 /* TBD: BTCOEXSCAN-STOP */
2569 else if (strnicmp(command, CMD_BTCOEXMODE, strlen(CMD_BTCOEXMODE)) == 0) {
2571 void *dhdp = wl_cfg80211_get_dhdp();
2572 bytes_written = wl_cfg80211_set_btcoex_dhcp(net, dhdp, command);
2574 #ifdef PKT_FILTER_SUPPORT
2575 uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
2578 net_os_enable_packet_filter(net, 0); /* DHCP starts */
2580 net_os_enable_packet_filter(net, 1); /* DHCP ends */
2581 #endif /* PKT_FILTER_SUPPORT */
2582 #endif /* WL_CFG80211 */
2584 else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) {
2585 bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
2587 else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) {
2588 bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len);
2590 else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) {
2591 uint band = *(command + strlen(CMD_SETBAND) + 1) - '0';
2592 #ifdef WL_HOST_BAND_MGMT
2594 if ((ret = wl_cfg80211_set_band(net, band)) < 0) {
2595 if (ret == BCME_UNSUPPORTED) {
2596 /* If roam_var is unsupported, fallback to the original method */
2597 ANDROID_ERROR(("WL_HOST_BAND_MGMT defined, "
2598 "but roam_band iovar unsupported in the firmware\n"));
2604 if ((band == WLC_BAND_AUTO) || (ret == BCME_UNSUPPORTED))
2605 bytes_written = wldev_set_band(net, band);
2607 bytes_written = wldev_set_band(net, band);
2608 #endif /* WL_HOST_BAND_MGMT */
2610 else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) {
2611 bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
2614 /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
2615 else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
2616 char *country_code = command + strlen(CMD_COUNTRY) + 1;
2618 /* Customer_hw5 want to keep connections */
2619 bytes_written = wldev_set_country(net, country_code, true, false);
2621 bytes_written = wldev_set_country(net, country_code, true, true);
2624 #endif /* WL_CFG80211 */
2628 else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
2629 bytes_written = dhd_dev_pno_stop_for_ssid(net);
2631 #ifndef WL_SCHED_SCAN
2632 else if (strnicmp(command, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) {
2633 bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
2635 #endif /* !WL_SCHED_SCAN */
2636 else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
2637 int enable = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
2638 bytes_written = (enable)? 0 : dhd_dev_pno_stop_for_ssid(net);
2640 else if (strnicmp(command, CMD_WLS_BATCHING, strlen(CMD_WLS_BATCHING)) == 0) {
2641 bytes_written = wls_parse_batching_cmd(net, command, priv_cmd.total_len);
2643 #endif /* PNO_SUPPORT */
2644 else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
2645 bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
2647 else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
2648 int skip = strlen(CMD_P2P_SET_NOA) + 1;
2649 bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
2650 priv_cmd.total_len - skip);
2653 else if (strnicmp(command, CMD_P2P_SD_OFFLOAD, strlen(CMD_P2P_SD_OFFLOAD)) == 0) {
2658 cmd_id = strsep((char **)&buf, " ");
2659 /* if buf == NULL, means no arg */
2665 bytes_written = wl_cfg80211_sd_offload(net, cmd_id, buf, len);
2669 else if (strnicmp(command, CMD_NAN, strlen(CMD_NAN)) == 0) {
2670 bytes_written = wl_cfg80211_nan_cmd_handler(net, command,
2671 priv_cmd.total_len);
2674 #if !defined WL_ENABLE_P2P_IF
2675 else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
2676 bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
2678 #endif /* WL_ENABLE_P2P_IF */
2679 else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
2680 int skip = strlen(CMD_P2P_SET_PS) + 1;
2681 bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
2682 priv_cmd.total_len - skip);
2685 else if (strnicmp(command, CMD_SET_AP_WPS_P2P_IE,
2686 strlen(CMD_SET_AP_WPS_P2P_IE)) == 0) {
2687 int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3;
2688 bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
2689 priv_cmd.total_len - skip, *(command + skip - 2) - '0');
2692 else if (strnicmp(command, CMD_GET_FTKEY, strlen(CMD_GET_FTKEY)) == 0) {
2693 wl_cfg80211_get_fbt_key(command);
2694 bytes_written = FBT_KEYLEN;
2697 #endif /* WL_CFG80211 */
2698 else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0)
2699 bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len);
2700 else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0)
2701 bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len);
2703 else if (strnicmp(command, CMD_GETCCKM_RN, strlen(CMD_GETCCKM_RN)) == 0) {
2704 bytes_written = wl_android_get_cckm_rn(net, command);
2706 else if (strnicmp(command, CMD_SETCCKM_KRK, strlen(CMD_SETCCKM_KRK)) == 0) {
2707 bytes_written = wl_android_set_cckm_krk(net, command);
2709 else if (strnicmp(command, CMD_GET_ASSOC_RES_IES, strlen(CMD_GET_ASSOC_RES_IES)) == 0) {
2710 bytes_written = wl_android_get_assoc_res_ies(net, command);
2713 #if defined(WL_SUPPORT_AUTO_CHANNEL)
2714 else if (strnicmp(command, CMD_GET_BEST_CHANNELS,
2715 strlen(CMD_GET_BEST_CHANNELS)) == 0) {
2716 bytes_written = wl_cfg80211_get_best_channels(net, command,
2717 priv_cmd.total_len);
2719 #endif /* WL_SUPPORT_AUTO_CHANNEL */
2720 else if (strnicmp(command, CMD_HAPD_MAC_FILTER, strlen(CMD_HAPD_MAC_FILTER)) == 0) {
2721 int skip = strlen(CMD_HAPD_MAC_FILTER) + 1;
2722 wl_android_set_mac_address_filter(net, (const char*)command+skip);
2724 else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0)
2725 bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len);
2726 #if defined(BCMFW_ROAM_ENABLE)
2727 else if (strnicmp(command, CMD_SET_ROAMPREF, strlen(CMD_SET_ROAMPREF)) == 0) {
2728 bytes_written = wl_android_set_roampref(net, command, priv_cmd.total_len);
2730 #endif /* BCMFW_ROAM_ENABLE */
2732 else if (strnicmp(command, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0)
2733 bytes_written = wl_android_set_miracast(net, command, priv_cmd.total_len);
2734 #if defined(CUSTOM_PLATFORM_NV_TEGRA)
2735 else if (strnicmp(command, CMD_SETMIRACAST, strlen(CMD_SETMIRACAST)) == 0)
2736 bytes_written = wldev_miracast_tuning(net, command, priv_cmd.total_len);
2737 else if (strnicmp(command, CMD_ASSOCRESPIE, strlen(CMD_ASSOCRESPIE)) == 0)
2738 bytes_written = wldev_get_assoc_resp_ie(net, command, priv_cmd.total_len);
2739 else if (strnicmp(command, CMD_RXRATESTATS, strlen(CMD_RXRATESTATS)) == 0)
2740 bytes_written = wldev_get_rx_rate_stats(net, command, priv_cmd.total_len);
2741 #endif /* defined(CUSTOM_PLATFORM_NV_TEGRA) */
2742 else if (strnicmp(command, CMD_SETIBSSBEACONOUIDATA, strlen(CMD_SETIBSSBEACONOUIDATA)) == 0)
2743 bytes_written = wl_android_set_ibss_beacon_ouidata(net,
2744 command, priv_cmd.total_len);
2747 else if (strnicmp(command, CMD_SETIBSSTXFAILEVENT,
2748 strlen(CMD_SETIBSSTXFAILEVENT)) == 0)
2749 bytes_written = wl_android_set_ibss_txfail_event(net, command, priv_cmd.total_len);
2750 else if (strnicmp(command, CMD_GET_IBSS_PEER_INFO_ALL,
2751 strlen(CMD_GET_IBSS_PEER_INFO_ALL)) == 0)
2752 bytes_written = wl_android_get_ibss_peer_info(net, command, priv_cmd.total_len,
2754 else if (strnicmp(command, CMD_GET_IBSS_PEER_INFO,
2755 strlen(CMD_GET_IBSS_PEER_INFO)) == 0)
2756 bytes_written = wl_android_get_ibss_peer_info(net, command, priv_cmd.total_len,
2758 else if (strnicmp(command, CMD_SETIBSSROUTETABLE,
2759 strlen(CMD_SETIBSSROUTETABLE)) == 0)
2760 bytes_written = wl_android_set_ibss_routetable(net, command,
2761 priv_cmd.total_len);
2762 else if (strnicmp(command, CMD_SETIBSSAMPDU, strlen(CMD_SETIBSSAMPDU)) == 0)
2763 bytes_written = wl_android_set_ibss_ampdu(net, command, priv_cmd.total_len);
2764 else if (strnicmp(command, CMD_SETIBSSANTENNAMODE, strlen(CMD_SETIBSSANTENNAMODE)) == 0)
2765 bytes_written = wl_android_set_ibss_antenna(net, command, priv_cmd.total_len);
2766 #endif /* WLAIBSS */
2767 else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) {
2768 int skip = strlen(CMD_KEEP_ALIVE) + 1;
2769 bytes_written = wl_keep_alive_set(net, command + skip, priv_cmd.total_len - skip);
2772 else if (strnicmp(command, CMD_ROAM_OFFLOAD, strlen(CMD_ROAM_OFFLOAD)) == 0) {
2773 int enable = *(command + strlen(CMD_ROAM_OFFLOAD) + 1) - '0';
2774 bytes_written = wl_cfg80211_enable_roam_offload(net, enable);
2776 else if (strnicmp(command, CMD_ROAM_OFFLOAD_APLIST, strlen(CMD_ROAM_OFFLOAD_APLIST)) == 0) {
2777 bytes_written = wl_android_set_roam_offload_bssid_list(net,
2778 command + strlen(CMD_ROAM_OFFLOAD_APLIST) + 1);
2781 #ifdef P2PRESP_WFDIE_SRC
2782 else if (strnicmp(command, CMD_P2P_SET_WFDIE_RESP,
2783 strlen(CMD_P2P_SET_WFDIE_RESP)) == 0) {
2784 int mode = *(command + strlen(CMD_P2P_SET_WFDIE_RESP) + 1) - '0';
2785 bytes_written = wl_android_set_wfdie_resp(net, mode);
2786 } else if (strnicmp(command, CMD_P2P_GET_WFDIE_RESP,
2787 strlen(CMD_P2P_GET_WFDIE_RESP)) == 0) {
2788 bytes_written = wl_android_get_wfdie_resp(net, command, priv_cmd.total_len);
2790 #endif /* P2PRESP_WFDIE_SRC */
2791 else if (strnicmp(command, CMD_GET_LINK_STATUS, strlen(CMD_GET_LINK_STATUS)) == 0) {
2792 bytes_written = wl_android_get_link_status(net, command, priv_cmd.total_len);
2794 #ifdef CONNECTION_STATISTICS
2795 else if (strnicmp(command, CMD_GET_CONNECTION_STATS,
2796 strlen(CMD_GET_CONNECTION_STATS)) == 0) {
2797 bytes_written = wl_android_get_connection_stats(net, command,
2798 priv_cmd.total_len);
2801 else if(strnicmp(command, CMD_GET_CHANNEL, strlen(CMD_GET_CHANNEL)) == 0) {
2802 bytes_written = wl_android_get_channel(net, command, priv_cmd.total_len);
2804 else if (strnicmp(command, CMD_SET_ROAM, strlen(CMD_SET_ROAM)) == 0) {
2805 bytes_written = wl_android_set_roam_trigger(net, command, priv_cmd.total_len);
2807 else if (strnicmp(command, CMD_GET_ROAM, strlen(CMD_GET_ROAM)) == 0) {
2808 bytes_written = wl_android_get_roam_trigger(net, command, priv_cmd.total_len);
2810 else if (strnicmp(command, CMD_GET_KEEP_ALIVE, strlen(CMD_GET_KEEP_ALIVE)) == 0) {
2811 int skip = strlen(CMD_GET_KEEP_ALIVE) + 1;
2812 bytes_written = wl_android_get_keep_alive(net, command+skip, priv_cmd.total_len-skip);
2814 else if (strnicmp(command, CMD_GET_PM, strlen(CMD_GET_PM)) == 0) {
2815 bytes_written = wl_android_get_pm(net, command, priv_cmd.total_len);
2817 else if (strnicmp(command, CMD_SET_PM, strlen(CMD_SET_PM)) == 0) {
2818 bytes_written = wl_android_set_pm(net, command, priv_cmd.total_len);
2820 else if (strnicmp(command, CMD_MONITOR, strlen(CMD_MONITOR)) == 0) {
2821 bytes_written = wl_android_set_monitor(net, command, priv_cmd.total_len);
2823 ANDROID_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
2824 snprintf(command, 3, "OK");
2825 bytes_written = strlen("OK");
2828 if (bytes_written >= 0) {
2829 if ((bytes_written == 0) && (priv_cmd.total_len > 0))
2831 if (bytes_written >= priv_cmd.total_len) {
2832 ANDROID_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written));
2833 bytes_written = priv_cmd.total_len;
2837 priv_cmd.used_len = bytes_written;
2838 if (copy_to_user(priv_cmd.buf, command, bytes_written)) {
2839 ANDROID_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__));
2844 ret = bytes_written;
2848 net_os_wake_unlock(net);
2856 int wl_android_init(void)
2860 #ifdef ENABLE_INSMOD_NO_FW_LOAD
2861 dhd_download_fw_on_driverload = FALSE;
2862 #endif /* ENABLE_INSMOD_NO_FW_LOAD */
2863 if (!iface_name[0]) {
2864 memset(iface_name, 0, IFNAMSIZ);
2865 bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ);
2876 int wl_android_exit(void)
2879 struct io_cfg *cur, *q;
2883 #endif /* WL_GENL */
2884 wl_netlink_deinit();
2886 list_for_each_entry_safe(cur, q, &miracast_resume_list, list) {
2887 list_del(&cur->list);
2894 void wl_android_post_init(void)
2897 #ifdef ENABLE_4335BT_WAR
2898 bcm_bt_unlock(lock_cookie_wifi);
2899 printk("%s: btlock released\n", __FUNCTION__);
2900 #endif /* ENABLE_4335BT_WAR */
2902 if (!dhd_download_fw_on_driverload)
2907 /* Generic Netlink Initializaiton */
2908 static int wl_genl_init(void)
2912 ANDROID_TRACE(("GEN Netlink Init\n\n"));
2914 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2915 /* register new family */
2916 ret = genl_register_family(&wl_genl_family);
2920 /* register functions (commands) of the new family */
2921 ret = genl_register_ops(&wl_genl_family, &wl_genl_ops);
2923 ANDROID_ERROR(("register ops failed: %i\n", ret));
2924 genl_unregister_family(&wl_genl_family);
2928 ret = genl_register_mc_group(&wl_genl_family, &wl_genl_mcast);
2930 ret = genl_register_family_with_ops_groups(&wl_genl_family, wl_genl_ops, wl_genl_mcast);
2931 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
2933 ANDROID_ERROR(("register mc_group failed: %i\n", ret));
2934 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2935 genl_unregister_ops(&wl_genl_family, &wl_genl_ops);
2937 genl_unregister_family(&wl_genl_family);
2944 ANDROID_ERROR(("Registering Netlink failed!!\n"));
2948 /* Generic netlink deinit */
2949 static int wl_genl_deinit(void)
2952 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2953 if (genl_unregister_ops(&wl_genl_family, &wl_genl_ops) < 0)
2954 ANDROID_ERROR(("Unregister wl_genl_ops failed\n"));
2956 if (genl_unregister_family(&wl_genl_family) < 0)
2957 ANDROID_ERROR(("Unregister wl_genl_ops failed\n"));
2962 s32 wl_event_to_bcm_event(u16 event_type)
2966 switch (event_type) {
2967 case WLC_E_SERVICE_FOUND:
2968 event = BCM_E_SVC_FOUND;
2970 case WLC_E_P2PO_ADD_DEVICE:
2971 event = BCM_E_DEV_FOUND;
2973 case WLC_E_P2PO_DEL_DEVICE:
2974 event = BCM_E_DEV_LOST;
2976 /* Above events are supported from BCM Supp ver 47 Onwards */
2977 #ifdef BT_WIFI_HANDOVER
2978 case WLC_E_BT_WIFI_HANDOVER_REQ:
2979 event = BCM_E_DEV_BT_WIFI_HO_REQ;
2981 #endif /* BT_WIFI_HANDOVER */
2984 ANDROID_ERROR(("Event not supported\n"));
2992 struct net_device *ndev,
3000 struct sk_buff *skb = NULL;
3003 bcm_event_hdr_t *hdr = NULL;
3004 int mcast = 1; /* By default sent as mutlicast type */
3006 u8 *ptr = NULL, *p = NULL;
3007 u32 tot_len = sizeof(bcm_event_hdr_t) + subhdr_len + len;
3008 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
3011 ANDROID_TRACE(("Enter \n"));
3013 /* Decide between STRING event and Data event */
3014 if (event_type == 0)
3015 attr_type = BCM_GENL_ATTR_STRING;
3017 attr_type = BCM_GENL_ATTR_MSG;
3019 skb = genlmsg_new(NLMSG_GOODSIZE, kflags);
3025 msg = genlmsg_put(skb, 0, 0, &wl_genl_family, 0, BCM_GENL_CMD_MSG);
3032 if (attr_type == BCM_GENL_ATTR_STRING) {
3033 /* Add a BCM_GENL_MSG attribute. Since it is specified as a string.
3034 * make sure it is null terminated
3036 if (subhdr || subhdr_len) {
3037 ANDROID_ERROR(("No sub hdr support for the ATTR STRING type \n"));
3042 ret = nla_put_string(skb, BCM_GENL_ATTR_STRING, buf);
3044 ANDROID_ERROR(("nla_put_string failed\n"));
3050 /* Create a single buffer for all */
3051 p = ptr = kzalloc(tot_len, kflags);
3054 ANDROID_ERROR(("ENOMEM!!\n"));
3058 /* Include the bcm event header */
3059 hdr = (bcm_event_hdr_t *)ptr;
3060 hdr->event_type = wl_event_to_bcm_event(event_type);
3061 hdr->len = len + subhdr_len;
3062 ptr += sizeof(bcm_event_hdr_t);
3064 /* Copy subhdr (if any) */
3065 if (subhdr && subhdr_len) {
3066 memcpy(ptr, subhdr, subhdr_len);
3072 memcpy(ptr, buf, len);
3075 ret = nla_put(skb, BCM_GENL_ATTR_MSG, tot_len, p);
3077 ANDROID_ERROR(("nla_put_string failed\n"));
3084 /* finalize the message */
3085 genlmsg_end(skb, msg);
3086 /* NETLINK_CB(skb).dst_group = 1; */
3088 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
3089 if ((err = genlmsg_multicast(skb, 0, wl_genl_mcast.id, GFP_ATOMIC)) < 0)
3091 if ((err = genlmsg_multicast(&wl_genl_family, skb, 0, 0, GFP_ATOMIC)) < 0)
3093 ANDROID_ERROR(("genlmsg_multicast for attr(%d) failed. Error:%d \n",
3096 ANDROID_TRACE(("Multicast msg sent successfully. attr_type:%d len:%d \n",
3097 attr_type, tot_len));
3099 NETLINK_CB(skb).dst_group = 0; /* Not in multicast group */
3101 /* finalize the message */
3102 genlmsg_end(skb, msg);
3104 /* send the message back */
3105 if (genlmsg_unicast(&init_net, skb, pid) < 0)
3106 ANDROID_ERROR(("genlmsg_unicast failed\n"));
3120 struct sk_buff *skb,
3121 struct genl_info *info)
3126 ANDROID_TRACE(("Enter \n"));
3132 na = info->attrs[BCM_GENL_ATTR_MSG];
3134 ANDROID_ERROR(("nlattribute NULL\n"));
3138 data = (char *)nla_data(na);
3140 ANDROID_ERROR(("Invalid data\n"));
3143 /* Handle the data */
3144 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)) || defined(WL_COMPAT_WIRELESS)
3145 ANDROID_TRACE(("%s: Data received from pid (%d) \n", __func__,
3148 ANDROID_TRACE(("%s: Data received from pid (%d) \n", __func__,
3150 #endif /* (LINUX_VERSION < VERSION(3, 7, 0) || WL_COMPAT_WIRELESS */
3155 #endif /* WL_GENL */
3158 #if defined(RSSIAVG)
3160 wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
3162 wl_rssi_cache_t *node, *cur, **rssi_head;
3165 rssi_head = &rssi_cache_ctrl->m_cache_head;
3169 ANDROID_INFO(("%s: Free %d with BSSID %pM\n",
3170 __FUNCTION__, i, &node->BSSID));
3180 wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
3182 wl_rssi_cache_t *node, *prev, **rssi_head;
3183 int i = -1, tmp = 0;
3186 do_gettimeofday(&now);
3188 rssi_head = &rssi_cache_ctrl->m_cache_head;
3193 if (now.tv_sec > node->tv.tv_sec) {
3194 if (node == *rssi_head) {
3196 *rssi_head = node->next;
3199 prev->next = node->next;
3201 ANDROID_INFO(("%s: Del %d with BSSID %pM\n",
3202 __FUNCTION__, i, &node->BSSID));
3218 wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, u8 *bssid)
3220 wl_rssi_cache_t *node, *prev, **rssi_head;
3221 int i = -1, tmp = 0;
3223 rssi_head = &rssi_cache_ctrl->m_cache_head;
3228 if (!memcmp(&node->BSSID, bssid, ETHER_ADDR_LEN)) {
3229 if (node == *rssi_head) {
3231 *rssi_head = node->next;
3234 prev->next = node->next;
3236 ANDROID_INFO(("%s: Del %d with BSSID %pM\n",
3237 __FUNCTION__, i, &node->BSSID));
3253 wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
3255 wl_rssi_cache_t *node, **rssi_head;
3257 rssi_head = &rssi_cache_ctrl->m_cache_head;
3268 wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
3270 wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
3273 struct ether_addr bssid;
3274 struct timeval now, timeout;
3279 error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), false);
3280 if (error == BCME_NOTASSOCIATED) {
3281 ANDROID_INFO(("%s: Not Associated! res:%d\n", __FUNCTION__, error));
3285 ANDROID_ERROR(("Could not get bssid (%d)\n", error));
3287 error = wldev_get_rssi(net, &rssi);
3289 ANDROID_ERROR(("Could not get rssi (%d)\n", error));
3293 do_gettimeofday(&now);
3294 timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
3295 if (timeout.tv_sec < now.tv_sec) {
3297 * Integer overflow - assume long enough timeout to be assumed
3298 * to be infinite, i.e., the timeout would never happen.
3300 ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu",
3301 __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec));
3305 rssi_head = &rssi_cache_ctrl->m_cache_head;
3309 if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) {
3310 ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d\n",
3311 __FUNCTION__, k, &bssid, rssi));
3312 for (j=0; j<RSSIAVG_LEN-1; j++)
3313 node->RSSI[j] = node->RSSI[j+1];
3314 node->RSSI[j] = rssi;
3324 leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL);
3326 ANDROID_ERROR(("%s: Memory alloc failure %d\n",
3327 __FUNCTION__, sizeof(wl_rssi_cache_t)));
3330 ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%d in the leaf\n",
3331 __FUNCTION__, k, &bssid, rssi));
3336 memcpy(&leaf->BSSID, &bssid, ETHER_ADDR_LEN);
3337 for (j=0; j<RSSIAVG_LEN; j++)
3338 leaf->RSSI[j] = rssi;
3346 *rssi_avg = (int)wl_get_avg_rssi(rssi_cache_ctrl, &bssid);
3352 wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list)
3354 wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
3355 wl_bss_info_t *bi = NULL;
3357 struct timeval now, timeout;
3359 if (!ss_list->count)
3362 do_gettimeofday(&now);
3363 timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
3364 if (timeout.tv_sec < now.tv_sec) {
3366 * Integer overflow - assume long enough timeout to be assumed
3367 * to be infinite, i.e., the timeout would never happen.
3369 ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu",
3370 __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec));
3373 rssi_head = &rssi_cache_ctrl->m_cache_head;
3376 for (i = 0; i < ss_list->count; i++) {
3380 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
3382 if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
3383 ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n",
3384 __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
3385 for (j=0; j<RSSIAVG_LEN-1; j++)
3386 node->RSSI[j] = node->RSSI[j+1];
3387 node->RSSI[j] = dtoh16(bi->RSSI);
3400 leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL);
3402 ANDROID_ERROR(("%s: Memory alloc failure %d\n",
3403 __FUNCTION__, sizeof(wl_rssi_cache_t)));
3406 ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n",
3407 __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
3412 memcpy(&leaf->BSSID, &bi->BSSID, ETHER_ADDR_LEN);
3413 for (j=0; j<RSSIAVG_LEN; j++)
3414 leaf->RSSI[j] = dtoh16(bi->RSSI);
3424 wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr)
3426 wl_rssi_cache_t *node, **rssi_head;
3427 int j, rssi_sum, rssi=RSSI_MINVAL;
3429 rssi_head = &rssi_cache_ctrl->m_cache_head;
3433 if (!memcmp(&node->BSSID, addr, ETHER_ADDR_LEN)) {
3436 for (j=0; j<RSSIAVG_LEN; j++)
3437 rssi_sum += node->RSSI[RSSIAVG_LEN-j-1];
3438 rssi = rssi_sum / j;
3443 rssi = MIN(rssi, RSSI_MAXVAL);
3444 if (rssi == RSSI_MINVAL) {
3445 ANDROID_ERROR(("%s: BSSID %pM does not in RSSI cache\n",
3446 __FUNCTION__, addr));
3452 #if defined(RSSIOFFSET)
3454 wl_update_rssi_offset(struct net_device *net, int rssi)
3461 chip = dhd_conf_get_chip(dhd_get_pub(net));
3462 chiprev = dhd_conf_get_chiprev(dhd_get_pub(net));
3463 if (chip == BCM4330_CHIP_ID && chiprev == BCM4330B2_CHIP_REV) {
3464 #if defined(RSSIOFFSET_NEW)
3466 for (j=0; j<RSSI_OFFSET; j++) {
3467 if (rssi - (RSSI_OFFSET_MINVAL+RSSI_OFFSET_INTVAL*(j+1)) < 0)
3472 rssi += RSSI_OFFSET;
3475 return MIN(rssi, RSSI_MAXVAL);
3479 #if defined(BSSCACHE)
3480 #define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN 32
3483 wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
3485 wl_bss_cache_t *node, *cur, **bss_head;
3488 ANDROID_TRACE(("%s called\n", __FUNCTION__));
3490 bss_head = &bss_cache_ctrl->m_cache_head;
3494 ANDROID_TRACE(("%s: Free %d with BSSID %pM\n",
3495 __FUNCTION__, i, &node->results.bss_info->BSSID));
3505 wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
3507 wl_bss_cache_t *node, *prev, **bss_head;
3508 int i = -1, tmp = 0;
3511 do_gettimeofday(&now);
3513 bss_head = &bss_cache_ctrl->m_cache_head;
3518 if (now.tv_sec > node->tv.tv_sec) {
3519 if (node == *bss_head) {
3521 *bss_head = node->next;
3524 prev->next = node->next;
3526 ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n",
3527 __FUNCTION__, i, &node->results.bss_info->BSSID,
3528 dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID));
3544 wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, u8 *bssid)
3546 wl_bss_cache_t *node, *prev, **bss_head;
3547 int i = -1, tmp = 0;
3549 bss_head = &bss_cache_ctrl->m_cache_head;
3554 if (!memcmp(&node->results.bss_info->BSSID, bssid, ETHER_ADDR_LEN)) {
3555 if (node == *bss_head) {
3557 *bss_head = node->next;
3560 prev->next = node->next;
3562 ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%d, SSID \"%s\"\n",
3563 __FUNCTION__, i, &node->results.bss_info->BSSID,
3564 dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID));
3580 wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
3582 wl_bss_cache_t *node, **bss_head;
3584 bss_head = &bss_cache_ctrl->m_cache_head;
3595 wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, wl_scan_results_t *ss_list)
3597 wl_bss_cache_t *node, *prev, *leaf, *tmp, **bss_head;
3598 wl_bss_info_t *bi = NULL;
3600 struct timeval now, timeout;
3602 if (!ss_list->count)
3605 do_gettimeofday(&now);
3606 timeout.tv_sec = now.tv_sec + BSSCACHE_TIMEOUT;
3607 if (timeout.tv_sec < now.tv_sec) {
3609 * Integer overflow - assume long enough timeout to be assumed
3610 * to be infinite, i.e., the timeout would never happen.
3612 ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu",
3613 __FUNCTION__, BSSCACHE_TIMEOUT, now.tv_sec, timeout.tv_sec));
3616 bss_head = &bss_cache_ctrl->m_cache_head;
3618 for (i=0; i < ss_list->count; i++) {
3621 bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
3624 if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
3626 leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
3628 ANDROID_ERROR(("%s: Memory alloc failure %d and keep old BSS info\n",
3629 __FUNCTION__, dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
3633 memcpy(leaf->results.bss_info, bi, dtoh32(bi->length));
3634 leaf->next = node->next;
3637 leaf->results.count = 1;
3638 leaf->results.version = ss_list->version;
3639 ANDROID_TRACE(("%s: Update %d with BSSID %pM, RSSI=%d, SSID \"%s\", length=%d\n",
3640 __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID, dtoh32(bi->length)));
3659 leaf = kmalloc(dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL);
3661 ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__,
3662 dtoh32(bi->length) + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN));
3665 ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%d, SSID \"%s\" in the leaf\n",
3666 __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
3668 memcpy(leaf->results.bss_info, bi, dtoh32(bi->length));
3672 leaf->results.count = 1;
3673 leaf->results.version = ss_list->version;
3684 wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl)
3686 ANDROID_TRACE(("%s:\n", __FUNCTION__));
3687 wl_free_bss_cache(bss_cache_ctrl);