static int wl_cfgvendor_gscan_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0; struct wl_priv *cfg = wiphy_priv(wiphy); dhd_pno_gscan_capabilities_t *reply = NULL; uint32 reply_len = 0; reply = dhd_dev_pno_get_gscan(wl_to_prmry_ndev(cfg), DHD_PNO_GET_CAPABILITIES, NULL, &reply_len); if (!reply) { WL_ERR(("Could not get capabilities\n")); err = -EINVAL; return err; } err = wl_cfgvendor_send_cmd_reply(wiphy, wl_to_prmry_ndev(cfg), reply, reply_len); if (unlikely(err)) WL_ERR(("Vendor Command reply failed ret:%d \n", err)); kfree(reply); return err; }
s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) { #ifndef DHD_SDALIGN #define DHD_SDALIGN 32 #endif struct net_device *ndev; s32 err = 0; WL_TRACE(("In\n")); if (dhd_dongle_up) { WL_ERR(("Dongle is already up\n")); return err; } ndev = wl_to_prmry_ndev(wl); if (need_lock) rtnl_lock(); err = wl_dongle_up(ndev, 0); if (unlikely(err)) { WL_ERR(("wl_dongle_up failed\n")); goto default_conf_out; } dhd_dongle_up = true; default_conf_out: if (need_lock) rtnl_unlock(); return err; }
static int wl_cfgvendor_get_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0; struct wl_priv *cfg = wiphy_priv(wiphy); int reply; reply = dhd_dev_get_feature_set(wl_to_prmry_ndev(cfg)); err = wl_cfgvendor_send_cmd_reply(wiphy, wl_to_prmry_ndev(cfg), &reply, sizeof(int)); if (unlikely(err)) WL_ERR(("Vendor Command reply failed ret:%d \n", err)); return err; }
/* set mode to allow pattern */ bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf)); err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); if (err) { if (err == -EOPNOTSUPP) { WL_INFO(("filter_mode not supported\n")); } else { WL_ERR(("filter_mode (%d)\n", err)); } goto dongle_filter_out; } dongle_filter_out: return err; } #endif /* OEM_ANDROID */ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) { #ifndef DHD_SDALIGN #define DHD_SDALIGN 32 #endif struct net_device *ndev; s32 err = 0; WL_TRACE(("In\n")); if (dhd_dongle_up) { WL_ERR(("Dongle is already up\n")); return err; } ndev = wl_to_prmry_ndev(wl); if (need_lock) rtnl_lock(); err = wl_dongle_up(ndev, 0); if (unlikely(err)) { WL_ERR(("wl_dongle_up failed\n")); goto default_conf_out; } #ifndef OEM_ANDROID err = wl_dongle_power(ndev, PM_FAST); if (unlikely(err)) { WL_ERR(("wl_dongle_power failed\n")); goto default_conf_out; } err = wl_dongle_glom(ndev, 0, DHD_SDALIGN); if (unlikely(err)) { WL_ERR(("wl_dongle_glom failed\n")); goto default_conf_out; } err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3); if (unlikely(err)) { WL_ERR(("wl_dongle_roam failed\n")); goto default_conf_out; } wl_dongle_scantime(ndev, 40, 80); wl_dongle_offload(ndev, 1, 0xf); wl_dongle_filter(ndev, 1); #endif /* OEM_ANDROID */ dhd_dongle_up = true; default_conf_out: if (need_lock) rtnl_unlock(); return err; }
static int wl_cfgvendor_gscan_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0, type, band; struct wl_priv *cfg = wiphy_priv(wiphy); uint16 *reply = NULL; uint32 reply_len = 0, num_channels, mem_needed; struct sk_buff *skb; type = nla_type(data); if (type == GSCAN_ATTRIBUTE_BAND) { band = nla_get_u32(data); } else { return -1; } reply = dhd_dev_pno_get_gscan(wl_to_prmry_ndev(cfg), DHD_PNO_GET_CHANNEL_LIST, &band, &reply_len); if (!reply) { WL_ERR(("Could not get channel list\n")); err = -EINVAL; return err; } num_channels = reply_len/ sizeof(uint32); mem_needed = reply_len + VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * 2); /* Alloc the SKB for vendor_event */ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed); if (unlikely(!skb)) { WL_ERR(("skb alloc failed")); err = -ENOMEM; goto exit; } nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels); nla_put(skb, GSCAN_ATTRIBUTE_CHANNEL_LIST, reply_len, reply); err = cfg80211_vendor_cmd_reply(skb); if (unlikely(err)) WL_ERR(("Vendor Command reply failed ret:%d \n", err)); exit: kfree(reply); return err; }
static int wl_cfgvendor_get_feature_set_matrix(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0; struct wl_priv *cfg = wiphy_priv(wiphy); struct sk_buff *skb; int *reply; int num, mem_needed, i; reply = dhd_dev_get_feature_set_matrix(wl_to_prmry_ndev(cfg), &num); if (!reply) { WL_ERR(("Could not get feature list matrix\n")); err = -EINVAL; return err; } mem_needed = VENDOR_REPLY_OVERHEAD + (ATTRIBUTE_U32_LEN * num) + ATTRIBUTE_U32_LEN; /* Alloc the SKB for vendor_event */ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed); if (unlikely(!skb)) { WL_ERR(("skb alloc failed")); err = -ENOMEM; goto exit; } nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, num); for (i = 0; i < num; i++) { nla_put_u32(skb, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, reply[i]); } err = cfg80211_vendor_cmd_reply(skb); if (unlikely(err)) WL_ERR(("Vendor Command reply failed ret:%d \n", err)); exit: kfree(reply); return err; }
static int wl_cfgvendor_set_pno_mac_oui(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0; struct wl_priv *cfg = wiphy_priv(wiphy); int type; uint8 pno_random_mac_oui[DOT11_OUI_LEN]; type = nla_type(data); if (type == ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI) { memcpy(pno_random_mac_oui, nla_data(data), DOT11_OUI_LEN); err = dhd_dev_pno_set_mac_oui(wl_to_prmry_ndev(cfg), pno_random_mac_oui); if (unlikely(err)) WL_ERR(("Bad OUI, could not set:%d \n", err)); } else { err = -1; } return err; }
static int wl_cfgvendor_gscan_get_batch_results(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int len) { int err = 0; struct wl_priv *cfg = wiphy_priv(wiphy); gscan_results_cache_t *results, *iter; uint32 reply_len, complete = 1; int32 mem_needed, num_results_iter; wifi_gscan_result_t *ptr; uint16 num_scan_ids, num_results; struct sk_buff *skb; struct nlattr *scan_hdr, *complete_flag; err = dhd_dev_wait_batch_results_complete(wl_to_prmry_ndev(cfg)); if (err != BCME_OK) return -EBUSY; err = dhd_dev_pno_lock_access_batch_results(wl_to_prmry_ndev(cfg)); if (err != BCME_OK) { WL_ERR(("Can't obtain lock to access batch results %d\n", err)); return -EBUSY; } results = dhd_dev_pno_get_gscan(wl_to_prmry_ndev(cfg), DHD_PNO_GET_BATCH_RESULTS, NULL, &reply_len); if (!results) { WL_ERR(("No results to send %d\n", err)); err = wl_cfgvendor_send_cmd_reply(wiphy, wl_to_prmry_ndev(cfg), results, 0); if (unlikely(err)) WL_ERR(("Vendor Command reply failed ret:%d \n", err)); dhd_dev_pno_unlock_access_batch_results(wl_to_prmry_ndev(cfg)); return err; } num_scan_ids = reply_len & 0xFFFF; num_results = (reply_len & 0xFFFF0000) >> 16; mem_needed = (num_results * sizeof(wifi_gscan_result_t)) + (num_scan_ids * GSCAN_BATCH_RESULT_HDR_LEN) + VENDOR_REPLY_OVERHEAD + SCAN_RESULTS_COMPLETE_FLAG_LEN; if (mem_needed > (int32)NLMSG_DEFAULT_SIZE) { mem_needed = (int32)NLMSG_DEFAULT_SIZE; complete = 0; } WL_TRACE(("complete %d mem_needed %d max_mem %d\n", complete, mem_needed, (int)NLMSG_DEFAULT_SIZE)); /* Alloc the SKB for vendor_event */ skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, mem_needed); if (unlikely(!skb)) { WL_ERR(("skb alloc failed")); dhd_dev_pno_unlock_access_batch_results(wl_to_prmry_ndev(cfg)); return -ENOMEM; } iter = results; complete_flag = nla_reserve(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, sizeof(complete)); mem_needed = mem_needed - (SCAN_RESULTS_COMPLETE_FLAG_LEN + VENDOR_REPLY_OVERHEAD); while (iter) { num_results_iter = (mem_needed - GSCAN_BATCH_RESULT_HDR_LEN)/sizeof(wifi_gscan_result_t); if (num_results_iter <= 0 || ((iter->tot_count - iter->tot_consumed) > num_results_iter)) break; scan_hdr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); /* no more room? we are done then (for now) */ if (scan_hdr == NULL) { complete = 0; break; } nla_put_u32(skb, GSCAN_ATTRIBUTE_SCAN_ID, iter->scan_id); nla_put_u8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, iter->flag); num_results_iter = iter->tot_count - iter->tot_consumed; nla_put_u32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num_results_iter); if (num_results_iter) { ptr = &iter->results[iter->tot_consumed]; iter->tot_consumed += num_results_iter; nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, num_results_iter * sizeof(wifi_gscan_result_t), ptr); } nla_nest_end(skb, scan_hdr); mem_needed -= GSCAN_BATCH_RESULT_HDR_LEN + (num_results_iter * sizeof(wifi_gscan_result_t)); iter = iter->next; } memcpy(nla_data(complete_flag), &complete, sizeof(complete)); dhd_dev_gscan_batch_cache_cleanup(wl_to_prmry_ndev(cfg)); dhd_dev_pno_unlock_access_batch_results(wl_to_prmry_ndev(cfg)); return cfg80211_vendor_cmd_reply(skb); }