/* * This function informs the CFG802.11 subsystem of a new IBSS. * * The following information are sent to the CFG802.11 subsystem * to register the new IBSS. If we do not register the new IBSS, * a kernel panic will result. * - SSID * - SSID length * - BSSID * - Channel */ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) { struct ieee80211_channel *chan; struct mwifiex_bss_info bss_info; struct cfg80211_bss *bss; int ie_len; u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; enum ieee80211_band band; if (mwifiex_get_bss_info(priv, &bss_info)) return -1; ie_buf[0] = WLAN_EID_SSID; ie_buf[1] = bss_info.ssid.ssid_len; memcpy(&ie_buf[sizeof(struct ieee_types_header)], &bss_info.ssid.ssid, bss_info.ssid.ssid_len); ie_len = ie_buf[1] + sizeof(struct ieee_types_header); band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); chan = __ieee80211_get_channel(priv->wdev->wiphy, ieee80211_channel_to_frequency(bss_info.bss_chan, band)); bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, 0, ie_buf, ie_len, 0, GFP_KERNEL); cfg80211_put_bss(bss); memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); return 0; }
/* * IOCTL request handler to change Ad-Hoc channel. * * This function allocates the IOCTL request buffer, fills it * with requisite parameters and calls the IOCTL handler. * * The function follows the following steps to perform the change - * - Get current IBSS information * - Get current channel * - If no change is required, return * - If not connected, change channel and return * - If connected, * - Disconnect * - Change channel * - Perform specific SSID scan with same SSID * - Start/Join the IBSS */ int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) { int ret; struct mwifiex_bss_info bss_info; struct mwifiex_ssid_bssid ssid_bssid; u16 curr_chan = 0; memset(&bss_info, 0, sizeof(bss_info)); /* Get BSS information */ if (mwifiex_get_bss_info(priv, &bss_info)) return -1; /* Get current channel */ ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, &curr_chan); if (curr_chan == channel) { ret = 0; goto done; } dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n", curr_chan, channel); if (!bss_info.media_connected) { ret = 0; goto done; } /* Do disonnect */ memset(&ssid_bssid, 0, ETH_ALEN); ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, (u16 *) &channel); /* Do specific SSID scanning */ if (mwifiex_request_scan(priv, &bss_info.ssid)) { ret = -1; goto done; } /* Start/Join Adhoc network */ memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); memcpy(&ssid_bssid.ssid, &bss_info.ssid, sizeof(struct mwifiex_802_11_ssid)); ret = mwifiex_bss_start(priv, &ssid_bssid); done: return ret; }
/* * Proc info file read handler. * * This function is called when the 'info' file is opened for reading. * It prints the following driver related information - * - Driver name * - Driver version * - Driver extended version * - Interface name * - BSS mode * - Media state (connected or disconnected) * - MAC address * - Total number of Tx bytes * - Total number of Rx bytes * - Total number of Tx packets * - Total number of Rx packets * - Total number of dropped Tx packets * - Total number of dropped Rx packets * - Total number of corrupted Tx packets * - Total number of corrupted Rx packets * - Carrier status (on or off) * - Tx queue status (started or stopped) * * For STA mode drivers, it also prints the following extra - * - ESSID * - BSSID * - Channel * - Region code * - Multicast count * - Multicast addresses */ static ssize_t mwifiex_info_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct mwifiex_private *priv = (struct mwifiex_private *) file->private_data; struct net_device *netdev = priv->netdev; struct netdev_hw_addr *ha; struct netdev_queue *txq; unsigned long page = get_zeroed_page(GFP_KERNEL); char *p = (char *) page, fmt[64]; struct mwifiex_bss_info info; ssize_t ret; int i = 0; if (!p) return -ENOMEM; memset(&info, 0, sizeof(info)); ret = mwifiex_get_bss_info(priv, &info); if (ret) goto free_and_exit; mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); if (!priv->version_str[0]) mwifiex_get_ver_ext(priv); p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); p += sprintf(p, "driver_version = %s", fmt); p += sprintf(p, "\nverext = %s", priv->version_str); p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); if (info.bss_mode >= ARRAY_SIZE(bss_modes)) p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode); else p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); p += sprintf(p, "media_state=\"%s\"\n", (!priv->media_connected ? "Disconnected" : "Connected")); p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr); if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { p += sprintf(p, "multicast_count=\"%d\"\n", netdev_mc_count(netdev)); p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); p += sprintf(p, "country_code = \"%s\"\n", info.country_code); netdev_for_each_mc_addr(ha, netdev) p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", i++, ha->addr); } p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); p += sprintf(p, "tx queue"); for (i = 0; i < netdev->num_tx_queues; i++) { txq = netdev_get_tx_queue(netdev, i); p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ? "stopped" : "started"); } p += sprintf(p, "\n"); ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, (unsigned long) p - page); free_and_exit: free_page(page); return ret; }
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel) { int ret; struct mwifiex_bss_info bss_info; struct mwifiex_ssid_bssid ssid_bssid; u16 curr_chan = 0; struct cfg80211_bss *bss = NULL; struct ieee80211_channel *chan; enum ieee80211_band band; memset(&bss_info, 0, sizeof(bss_info)); if (mwifiex_get_bss_info(priv, &bss_info)) return -1; ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, &curr_chan); if (curr_chan == channel) { ret = 0; goto done; } dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n", curr_chan, channel); if (!bss_info.media_connected) { ret = 0; goto done; } memset(&ssid_bssid, 0, ETH_ALEN); ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, &channel); if (mwifiex_request_scan(priv, &bss_info.ssid)) { ret = -1; goto done; } band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); chan = __ieee80211_get_channel(priv->wdev->wiphy, ieee80211_channel_to_frequency(channel, band)); bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid, bss_info.ssid.ssid, bss_info.ssid.ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n", bss_info.bssid); ret = mwifiex_bss_start(priv, bss, &bss_info.ssid); done: return ret; }