diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 8030feb..4fb8328 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2895,6 +2895,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->require_vht = atoi(pos); } else if (os_strcmp(buf, "vht_oper_chwidth") == 0) { conf->vht_oper_chwidth = atoi(pos); + } else if (os_strcmp(buf, "ht_oper_chwidth") == 0) { + conf->ht_oper_chwidth = atoi(pos); } else if (os_strcmp(buf, "vht_oper_centr_freq_seg0_idx") == 0) { conf->vht_oper_centr_freq_seg0_idx = atoi(pos); } else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") == 0) { diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 33819ab..26338e5 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -751,7 +751,8 @@ static int hostapd_ctrl_iface_send_qos_map_conf(struct hostapd_data *hapd, wpabuf_put_data(buf, qos_map_set, qos_map_set_len); ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, - wpabuf_head(buf), wpabuf_len(buf)); + wpabuf_head(buf), wpabuf_len(buf), + hapd->iconf->ht_oper_chwidth); wpabuf_free(buf); return ret; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 2d07c67..552f740 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -665,6 +665,8 @@ struct hostapd_config { u8 vht_oper_centr_freq_seg0_idx; u8 vht_oper_centr_freq_seg1_idx; + u8 ht_oper_chwidth; + /* Use driver-generated interface addresses when adding multiple BSSs */ u8 use_driver_iface_addr; diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index b89f60e..395a02b 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -485,7 +485,7 @@ int hostapd_flush(struct hostapd_data *hapd) int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, - int center_segment0, int center_segment1) + int center_segment0, int center_segment1, int ht_oper_chwidth) { struct hostapd_freq_params data; @@ -494,7 +494,8 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, vht_oper_chwidth, center_segment0, center_segment1, hapd->iface->current_mode ? - hapd->iface->current_mode->vht_capab : 0)) + hapd->iface->current_mode->vht_capab : 0, + ht_oper_chwidth)) return -1; if (hapd->driver == NULL) @@ -670,13 +671,13 @@ int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *data, - size_t len) + size_t len, int chwidth) { if (hapd->driver == NULL || hapd->driver->send_action == NULL) return 0; return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, hapd->own_addr, hapd->own_addr, data, - len, 0); + len, 0, chwidth); } @@ -684,7 +685,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, enum hostapd_hw_mode mode, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, - int center_segment0, int center_segment1) + int center_segment0, int center_segment1, + int ht_oper_chwidth) { struct hostapd_data *hapd = iface->bss[0]; struct hostapd_freq_params data; @@ -703,7 +705,8 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, vht_enabled, sec_channel_offset, vht_oper_chwidth, center_segment0, center_segment1, - iface->current_mode->vht_capab)) { + iface->current_mode->vht_capab, + ht_oper_chwidth)) { wpa_printf(MSG_ERROR, "Can't set freq params"); return -1; } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 757a706..d7f0c27 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -61,7 +61,7 @@ int hostapd_flush(struct hostapd_data *hapd); int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, - int center_segment0, int center_segment1); + int center_segment0, int center_segment1, int ht_oper_chwidth); int hostapd_set_rts(struct hostapd_data *hapd, int rts); int hostapd_set_frag(struct hostapd_data *hapd, int frag); int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, @@ -97,7 +97,7 @@ int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, int reason); int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *data, - size_t len); + size_t len, int chwidth); int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, u16 auth_alg); int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, @@ -110,7 +110,7 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, enum hostapd_hw_mode mode, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, - int center_segment0, int center_segment1); + int center_segment0, int center_segment1, int ht_oper_chwidth); int hostapd_drv_do_acs(struct hostapd_data *hapd); diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 0720e14..3ab6060 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1279,7 +1279,8 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) iconf->vht_oper_chwidth, iconf->vht_oper_centr_freq_seg0_idx, iconf->vht_oper_centr_freq_seg1_idx, - iface->current_mode->vht_capab) == 0) + iface->current_mode->vht_capab, + iconf->ht_oper_chwidth) == 0) params.freq = &freq; res = hostapd_drv_set_ap(hapd, ¶ms); diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index 9f249d7..a478b3f 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -443,6 +443,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, "num_sta_ht_20_mhz=%d\n" "num_sta_ht40_intolerant=%d\n" "olbc_ht=%d\n" + "ht_oper_chwidth=%d\n" "ht_op_mode=0x%x\n", hostapd_state_text(iface->state), iface->phy, @@ -456,6 +457,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, iface->num_sta_ht_20mhz, iface->num_sta_ht40_intolerant, iface->olbc_ht, + iface->conf->ht_oper_chwidth, iface->ht_op_mode); if (os_snprintf_error(buflen - len, ret)) return len; diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 47adba7..6bf0825 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -515,6 +515,8 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, /* Seems cf1 and chan_width is enough here */ switch (chan_width) { + case CHAN_WIDTH_5: + case CHAN_WIDTH_10: case CHAN_WIDTH_20_NOHT: case CHAN_WIDTH_20: n_chans = 1; @@ -571,6 +573,8 @@ static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq, /* Reported via radar event */ switch (chan_width) { + case CHAN_WIDTH_5: + case CHAN_WIDTH_10: case CHAN_WIDTH_20_NOHT: case CHAN_WIDTH_20: radar_n_chans = 1; @@ -736,7 +740,8 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) iface->conf->secondary_channel, iface->conf->vht_oper_chwidth, iface->conf->vht_oper_centr_freq_seg0_idx, - iface->conf->vht_oper_centr_freq_seg1_idx); + iface->conf->vht_oper_centr_freq_seg1_idx, + iface->conf->ht_oper_chwidth); if (res) { wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); @@ -897,7 +902,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) iface->conf->vht_oper_chwidth, vht_oper_centr_freq_seg0_idx, vht_oper_centr_freq_seg1_idx, - iface->current_mode->vht_capab); + iface->current_mode->vht_capab, + iface->conf->ht_oper_chwidth); if (err) { wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index f54d1ad..cd6420a 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -502,6 +502,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, case CHAN_WIDTH_160: chwidth = VHT_CHANWIDTH_160MHZ; break; + case CHAN_WIDTH_5: + case CHAN_WIDTH_10: case CHAN_WIDTH_20_NOHT: case CHAN_WIDTH_20: case CHAN_WIDTH_40: @@ -532,6 +534,11 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx; hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx; + if (width == CHAN_WIDTH_5) + hapd->iconf->ht_oper_chwidth = 5; + else if (width == CHAN_WIDTH_10) + hapd->iconf->ht_oper_chwidth = 10; + is_dfs = ieee80211_is_dfs(freq); if (hapd->csa_in_progress && diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c index 179dc7a..9c9512e 100644 --- a/src/ap/gas_serv.c +++ b/src/ap/gas_serv.c @@ -1228,7 +1228,8 @@ static void gas_serv_req_local_processing(struct hostapd_data *hapd, if (prot) convert_to_protected_dual(tx_buf); hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, - wpabuf_head(tx_buf), wpabuf_len(tx_buf)); + wpabuf_head(tx_buf), wpabuf_len(tx_buf), + hapd->iconf->ht_oper_chwidth); wpabuf_free(tx_buf); } @@ -1288,7 +1289,8 @@ static void gas_serv_rx_gas_initial_req(struct hostapd_data *hapd, if (prot) convert_to_protected_dual(buf); hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, - wpabuf_head(buf), wpabuf_len(buf)); + wpabuf_head(buf), wpabuf_len(buf), + hapd->iconf->ht_oper_chwidth); wpabuf_free(buf); return; } @@ -1421,7 +1423,8 @@ send_resp: if (prot) convert_to_protected_dual(tx_buf); hostapd_drv_send_action(hapd, hapd->iface->freq, 0, sa, - wpabuf_head(tx_buf), wpabuf_len(tx_buf)); + wpabuf_head(tx_buf), wpabuf_len(tx_buf), + hapd->iconf->ht_oper_chwidth); wpabuf_free(tx_buf); } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 55ca9e8..cb656f8 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -188,6 +188,7 @@ int hostapd_reload_config(struct hostapd_iface *iface) hapd->iconf->ht_capab = oldconf->ht_capab; hapd->iconf->vht_capab = oldconf->vht_capab; hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth; + hapd->iconf->ht_oper_chwidth = oldconf->ht_oper_chwidth; hapd->iconf->vht_oper_centr_freq_seg0_idx = oldconf->vht_oper_centr_freq_seg0_idx; hapd->iconf->vht_oper_centr_freq_seg1_idx = @@ -1436,7 +1437,8 @@ static int fst_hostapd_send_action_cb(void *ctx, const u8 *da, struct hostapd_data *hapd = ctx; return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, da, - wpabuf_head(buf), wpabuf_len(buf)); + wpabuf_head(buf), wpabuf_len(buf), + hapd->iconf->ht_oper_chwidth); } @@ -1595,7 +1597,8 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, hapd->iconf->secondary_channel, hapd->iconf->vht_oper_chwidth, hapd->iconf->vht_oper_centr_freq_seg0_idx, - hapd->iconf->vht_oper_centr_freq_seg1_idx)) { + hapd->iconf->vht_oper_centr_freq_seg1_idx, + hapd->iconf->ht_oper_chwidth)) { wpa_printf(MSG_ERROR, "Could not set channel for " "kernel driver"); goto fail; @@ -2879,11 +2882,14 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd, conf->vht_oper_chwidth, conf->vht_oper_centr_freq_seg0_idx, conf->vht_oper_centr_freq_seg1_idx, - conf->vht_capab)) + conf->vht_capab, + conf->ht_oper_chwidth)) return -1; switch (params->bandwidth) { case 0: + case 5: + case 10: case 20: case 40: conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; @@ -3051,6 +3057,8 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, switch (freq_params->bandwidth) { case 0: + case 5: + case 10: case 20: case 40: vht_bw = VHT_CHANWIDTH_USE_HT; diff --git a/src/ap/hs20.c b/src/ap/hs20.c index d7909fa..05871f2 100644 --- a/src/ap/hs20.c +++ b/src/ap/hs20.c @@ -134,7 +134,8 @@ int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr, } ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, - wpabuf_head(buf), wpabuf_len(buf)); + wpabuf_head(buf), wpabuf_len(buf), + hapd->iconf->ht_oper_chwidth); wpabuf_free(buf); @@ -169,7 +170,8 @@ int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd, wpabuf_put_buf(buf, payload); ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, - wpabuf_head(buf), wpabuf_len(buf)); + wpabuf_head(buf), wpabuf_len(buf), + hapd->iconf->ht_oper_chwidth); wpabuf_free(buf); diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 41d50ce..cd684ed 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -145,7 +145,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, /* In driver, response frame should be forced to sent when STA is in * PS mode */ res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, - mgmt->da, &mgmt->u.action.category, len); + mgmt->da, &mgmt->u.action.category, len, + hapd->iconf->ht_oper_chwidth); if (!res) { wpa_printf(MSG_DEBUG, "Successfully send WNM-Sleep Response " @@ -295,7 +296,8 @@ static int ieee802_11_send_bss_trans_mgmt_request(struct hostapd_data *hapd, len = pos - &mgmt->u.action.category; res = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, - mgmt->da, &mgmt->u.action.category, len); + mgmt->da, &mgmt->u.action.category, len, + hapd->iconf->ht_oper_chwidth); os_free(mgmt); return res; } diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index 9c37ea6..49eaf87 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -354,7 +354,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, int center_segment0, - int center_segment1, u32 vht_caps) + int center_segment1, u32 vht_caps, + int ht_oper_chwidth) { os_memset(data, 0, sizeof(*data)); data->mode = mode; @@ -367,6 +368,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, data->center_freq2 = 0; data->bandwidth = sec_channel_offset ? 40 : 20; + if (ht_oper_chwidth) { + if (!sec_channel_offset) + data->bandwidth = ht_oper_chwidth; /* user-override */ + } + if (data->vht_enabled) switch (vht_oper_chwidth) { case VHT_CHANWIDTH_USE_HT: if (center_segment1 || diff --git a/src/common/hw_features_common.h b/src/common/hw_features_common.h index 7360b4e..ae2e9a1 100644 --- a/src/common/hw_features_common.h +++ b/src/common/hw_features_common.h @@ -34,6 +34,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, int center_segment0, - int center_segment1, u32 vht_caps); + int center_segment1, u32 vht_caps, + int ht_oper_chwidth); #endif /* HW_FEATURES_COMMON_H */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index adfcdb4..2443a66 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1587,6 +1587,8 @@ enum chan_width { CHAN_WIDTH_80, CHAN_WIDTH_80P80, CHAN_WIDTH_160, + CHAN_WIDTH_5, + CHAN_WIDTH_10, CHAN_WIDTH_UNKNOWN }; @@ -2652,7 +2654,8 @@ struct wpa_driver_ops { * @bssid: BSSID (Address 3) * @data: Frame body * @data_len: data length in octets - @ @no_cck: Whether CCK rates must not be used to transmit this frame + * @no_cck: Whether CCK rates must not be used to transmit this frame + * @chwidth: Specify channel width, or use 0 for default. * Returns: 0 on success, -1 on failure * * This command can be used to request the driver to transmit an action @@ -2670,7 +2673,8 @@ struct wpa_driver_ops { */ int (*send_action)(void *priv, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *src, const u8 *bssid, - const u8 *data, size_t data_len, int no_cck); + const u8 *data, size_t data_len, int no_cck, + int chwidth); /** * send_action_cancel_wait - Cancel action frame TX wait diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index b32d35f..443f56d 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -90,6 +90,10 @@ const char * event_to_string(enum wpa_event_type event) const char * channel_width_to_string(enum chan_width width) { switch (width) { + case CHAN_WIDTH_5: + return "5 MHz"; + case CHAN_WIDTH_10: + return "10 MHz"; case CHAN_WIDTH_20_NOHT: return "20 MHz (no HT)"; case CHAN_WIDTH_20: diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 014bde3..0c2c080 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -177,7 +177,8 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, unsigned int freq, unsigned int wait, const u8 *buf, size_t buf_len, u64 *cookie, int no_cck, int no_ack, int offchanok, - const u16 *csa_offs, size_t csa_offs_len); + const u16 *csa_offs, size_t csa_offs_len, + int chwidth); static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report); @@ -210,6 +211,10 @@ static int nl80211_set_param(void *priv, const char *param); enum chan_width convert2width(int width) { switch (width) { + case NL80211_CHAN_WIDTH_5: + return CHAN_WIDTH_5; + case NL80211_CHAN_WIDTH_10: + return CHAN_WIDTH_10; case NL80211_CHAN_WIDTH_20_NOHT: return CHAN_WIDTH_20_NOHT; case NL80211_CHAN_WIDTH_20: @@ -3186,7 +3191,7 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss, unsigned int freq, int no_cck, int offchanok, unsigned int wait_time, const u16 *csa_offs, - size_t csa_offs_len) + size_t csa_offs_len, int chwidth) { struct wpa_driver_nl80211_data *drv = bss->drv; u64 cookie; @@ -3213,7 +3218,7 @@ static int wpa_driver_nl80211_send_frame(struct i802_bss *bss, wpa_printf(MSG_DEBUG, "nl80211: send_frame -> send_frame_cmd"); res = nl80211_send_frame_cmd(bss, freq, wait_time, data, len, &cookie, no_cck, noack, offchanok, - csa_offs, csa_offs_len); + csa_offs, csa_offs_len, chwidth); if (res == 0 && !noack) { const struct ieee80211_mgmt *mgmt; u16 fc; @@ -3241,7 +3246,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, int offchanok, unsigned int wait_time, const u16 *csa_offs, - size_t csa_offs_len) + size_t csa_offs_len, int chwidth) { struct wpa_driver_nl80211_data *drv = bss->drv; struct ieee80211_mgmt *mgmt; @@ -3271,7 +3276,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, } return nl80211_send_frame_cmd(bss, freq, 0, data, data_len, NULL, 1, noack, - 1, csa_offs, csa_offs_len); + 1, csa_offs, csa_offs_len, chwidth); } if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) { @@ -3286,7 +3291,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, data, data_len, &drv->send_action_cookie, no_cck, noack, offchanok, - csa_offs, csa_offs_len); + csa_offs, csa_offs_len, chwidth); } if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && @@ -3660,17 +3665,17 @@ fail: static int nl80211_put_freq_params(struct nl_msg *msg, const struct hostapd_freq_params *freq) { + enum nl80211_chan_width cw; + wpa_printf(MSG_DEBUG, " * freq=%d", freq->freq); if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq->freq)) return -ENOBUFS; wpa_printf(MSG_DEBUG, " * vht_enabled=%d", freq->vht_enabled); wpa_printf(MSG_DEBUG, " * ht_enabled=%d", freq->ht_enabled); + wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth); if (freq->vht_enabled) { - enum nl80211_chan_width cw; - - wpa_printf(MSG_DEBUG, " * bandwidth=%d", freq->bandwidth); switch (freq->bandwidth) { case 20: cw = NL80211_CHAN_WIDTH_20; @@ -3720,8 +3725,26 @@ static int nl80211_put_freq_params(struct nl_msg *msg, break; } + switch (freq->bandwidth) { + case 5: + cw = NL80211_CHAN_WIDTH_5; + break; + case 10: + cw = NL80211_CHAN_WIDTH_10; + break; + case 40: + cw = NL80211_CHAN_WIDTH_40; + break; + case 20: + default: + cw = NL80211_CHAN_WIDTH_20; + break; + } + + wpa_printf(MSG_DEBUG, " * channel_width=%d", cw); wpa_printf(MSG_DEBUG, " * channel_type=%d", ct); - if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct)) + if (nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cw) || + nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct)) return -ENOBUFS; } return 0; @@ -6366,7 +6389,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, const u8 *buf, size_t buf_len, u64 *cookie_out, int no_cck, int no_ack, int offchanok, const u16 *csa_offs, - size_t csa_offs_len) + size_t csa_offs_len, int cwidth) { struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; @@ -6380,6 +6403,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_FRAME)) || (freq && nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq)) || + (chwidth && nla_put_u32(msg, NL80211_ATTR_CHANNEL_WIDTH, cwidth)) || (wait && nla_put_u32(msg, NL80211_ATTR_DURATION, wait)) || (offchanok && ((drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || drv->test_use_roc_tx) && @@ -6433,7 +6457,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *data, size_t data_len, - int no_cck) + int no_cck, int chwidth) { struct wpa_driver_nl80211_data *drv = bss->drv; int ret = -1; @@ -6466,7 +6490,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, ret = nl80211_send_frame_cmd(bss, freq, wait_time, buf, 24 + data_len, &drv->send_action_cookie, - no_cck, 0, 1, NULL, 0); + no_cck, 0, 1, NULL, 0, chwidth); os_free(buf); return ret; @@ -7890,11 +7914,12 @@ static int driver_nl80211_send_action(void *priv, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *data, size_t data_len, - int no_cck) + int no_cck, int chwidth) { struct i802_bss *bss = priv; return wpa_driver_nl80211_send_action(bss, freq, wait_time, dst, src, - bssid, data, data_len, no_cck); + bssid, data, data_len, no_cck, + chwidth); } diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index dae203a..74aaab2 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -427,6 +427,8 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2) int freq1 = 0; switch (convert2width(width)) { + case CHAN_WIDTH_5: + case CHAN_WIDTH_10: case CHAN_WIDTH_20_NOHT: case CHAN_WIDTH_20: return 0; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index d6cc099..805a28b 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2118,7 +2118,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, freq->channel, freq->ht_enabled, vht_freq.vht_enabled, freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps) != 0) + chwidth, seg0, seg1, vht_caps, 0) != 0) return; *freq = vht_freq;