/** * @brief Request the driver to add a virtual interface * * @param wiphy A pointer to wiphy structure * @param name Virtual interface name * @param type Virtual interface type * @param flags Flags for the virtual interface * @param params A pointer to vif_params structure * @param new_dev new net_device to return * * @return 0 -- success, otherwise fail */ int woal_cfg80211_add_virt_if(struct wiphy *wiphy, #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) const #endif char *name, enum nl80211_iftype type, u32 *flags, struct vif_params *params, struct net_device **new_dev) { int ret = 0; struct net_device *ndev = NULL; moal_private *priv = NULL, *new_priv = NULL; moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy); struct wireless_dev *wdev = NULL; moal_private *vir_priv; int i = 0; ENTER(); ASSERT_RTNL(); priv = (moal_private *)woal_get_priv_bss_type(handle, MLAN_BSS_TYPE_WIFIDIRECT); if (!priv || !priv->phandle) { PRINTM(MERROR, "priv or handle is NULL\n"); LEAVE(); return -EFAULT; } if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) { PRINTM(MERROR, "max virtual interface limit reached\n"); for (i = 0; i < priv->phandle->priv_num; i++) { vir_priv = priv->phandle->priv[i]; if (vir_priv->bss_virtual) { woal_cfg80211_del_virt_if(wiphy, vir_priv->netdev); break; } } if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) { LEAVE(); return -ENOMEM; } } PRINTM(MMSG, "Add virtual interface %s\n", name); if ((type != NL80211_IFTYPE_P2P_CLIENT) && (type != NL80211_IFTYPE_P2P_GO)) { PRINTM(MERROR, "Invalid iftype: %d\n", type); LEAVE(); return -EINVAL; } handle = priv->phandle; /* Cancel previous scan req */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); new_priv = woal_alloc_virt_interface(handle, handle->priv_num, MLAN_BSS_TYPE_WIFIDIRECT, name); if (!new_priv) { PRINTM(MERROR, "Add virtual interface fail."); LEAVE(); return -EFAULT; } handle->priv_num++; wdev = (struct wireless_dev *)&new_priv->w_dev; memset(wdev, 0, sizeof(struct wireless_dev)); ndev = new_priv->netdev; SET_NETDEV_DEV(ndev, wiphy_dev(wiphy)); ndev->ieee80211_ptr = wdev; wdev->iftype = type; wdev->wiphy = wiphy; new_priv->wdev = wdev; new_priv->bss_virtual = MTRUE; new_priv->pa_netdev = priv->netdev; woal_init_sta_dev(ndev, new_priv); /* Initialize priv structure */ woal_init_priv(new_priv, MOAL_CMD_WAIT); /** Init to GO/CLIENT mode */ if (type == NL80211_IFTYPE_P2P_CLIENT) woal_cfg80211_init_p2p_client(new_priv); else if (type == NL80211_IFTYPE_P2P_GO) woal_cfg80211_init_p2p_go(new_priv); ret = register_netdevice(ndev); if (ret) { handle->priv[new_priv->bss_index] = NULL; handle->priv_num--; if (ndev->reg_state == NETREG_REGISTERED) { unregister_netdevice(ndev); free_netdev(ndev); ndev = NULL; } PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret); goto done; } netif_carrier_off(ndev); woal_stop_queue(ndev); if (new_dev) *new_dev = ndev; #ifdef CONFIG_PROC_FS woal_create_proc_entry(new_priv); #ifdef PROC_DEBUG woal_debug_entry(new_priv); #endif /* PROC_DEBUG */ #endif /* CONFIG_PROC_FS */ done: LEAVE(); return ret; }
/** * @brief initialize AP or GO parameters * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * @param params A pointer to beacon_parameters structure * @return 0 -- success, otherwise fail */ int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) #endif { moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); PRINTM(MIOCTL, "add beacon\n"); #ifdef STA_CFG80211 /*** cancel pending scan */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); #endif if (params != NULL) { /* bss config */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) { ret = -EFAULT; goto done; } /* set mgmt frame ies */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_mgmt_frame_ie(priv, #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) params->tail, params->tail_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) params->beacon. tail, params->beacon. tail_len, params->beacon. proberesp_ies, params->beacon. proberesp_ies_len, params->beacon. assocresp_ies, params->beacon. assocresp_ies_len, #else params->tail, params->tail_len, params-> proberesp_ies, params-> proberesp_ies_len, params-> assocresp_ies, params-> assocresp_ies_len, #endif NULL, 0, MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | MGMT_MASK_ASSOC_RESP #endif )) { ret = -EFAULT; goto done; } } /* if the bss is stopped, then start it */ if (priv->bss_started == MFALSE) { if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START)) { ret = -EFAULT; goto done; } } done: LEAVE(); return ret; }
/** * @brief initialize AP or GO parameters * * @param wiphy A pointer to wiphy structure * @param dev A pointer to net_device structure * @param params A pointer to beacon_parameters structure * @return 0 -- success, otherwise fail */ int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) #endif { moal_private *priv = (moal_private *)woal_get_netdev_priv(dev); int ret = 0; ENTER(); PRINTM(MMSG, "wlan: Starting AP\n"); #ifdef STA_CFG80211 /*** cancel pending scan */ woal_cancel_scan(priv, MOAL_IOCTL_WAIT); #endif if (params != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) priv->channel = ieee80211_frequency_to_channel(params->chandef.chan-> center_freq); #else priv->channel = ieee80211_frequency_to_channel(params->channel-> center_freq); #endif #endif /* bss config */ if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) { ret = -EFAULT; goto done; } /* set mgmt frame ies */ ret = woal_cfg80211_mgmt_frame_ie(priv, #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !defined(COMPAT_WIRELESS) params->tail, params->tail_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) params->beacon.tail, params->beacon.tail_len, params->beacon.proberesp_ies, params->beacon. proberesp_ies_len, params->beacon.assocresp_ies, params->beacon. assocresp_ies_len, #else params->tail, params->tail_len, params->proberesp_ies, params->proberesp_ies_len, params->assocresp_ies, params->assocresp_ies_len, #endif NULL, 0, MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | MGMT_MASK_ASSOC_RESP #endif , MOAL_IOCTL_WAIT); if (ret) goto done; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || defined(COMPAT_WIRELESS) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { ret = woal_cfg80211_mgmt_frame_ie(priv, params->beacon.beacon_ies, params->beacon.beacon_ies_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON_WPS_P2P, MOAL_IOCTL_WAIT); if (ret) { PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); goto done; } } #else if (params->beacon_ies && params->beacon_ies_len) { ret = woal_cfg80211_mgmt_frame_ie(priv, params->beacon_ies, params->beacon_ies_len, NULL, 0, NULL, 0, NULL, 0, MGMT_MASK_BEACON_WPS_P2P, MOAL_IOCTL_WAIT); if (ret) { PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n"); goto done; } } #endif #endif /* if the bss is stopped, then start it */ if (priv->bss_started == MFALSE) { if (MLAN_STATUS_SUCCESS != woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START)) { ret = -EFAULT; goto done; } } PRINTM(MMSG, "wlan: AP started\n"); done: LEAVE(); return ret; }