hostapd: update to 2011-04-21
[librecmc/librecmc.git] / package / hostapd / patches / 800-dynamic_20_40_mhz.patch
1 --- a/hostapd/config_file.c
2 +++ b/hostapd/config_file.c
3 @@ -1901,6 +1901,10 @@ struct hostapd_config * hostapd_config_r
4                                            "ht_capab", line);
5                                 errors++;
6                         }
7 +               } else if (os_strcmp(buf, "dynamic_ht40") == 0) {
8 +                       conf->dynamic_ht40 = atoi(pos);
9 +                       if (conf->dynamic_ht40 == 1)
10 +                               conf->dynamic_ht40 = 1500;
11                 } else if (os_strcmp(buf, "require_ht") == 0) {
12                         conf->require_ht = atoi(pos);
13  #endif /* CONFIG_IEEE80211N */
14 --- a/src/ap/ap_config.h
15 +++ b/src/ap/ap_config.h
16 @@ -393,6 +393,7 @@ struct hostapd_config {
17         int ieee80211n;
18         int secondary_channel;
19         int require_ht;
20 +       int dynamic_ht40;
21  };
22  
23  
24 --- a/src/ap/hostapd.c
25 +++ b/src/ap/hostapd.c
26 @@ -285,6 +285,7 @@ static void hostapd_cleanup_iface_pre(st
27   */
28  static void hostapd_cleanup_iface(struct hostapd_iface *iface)
29  {
30 +       hostapd_deinit_ht(iface);
31         hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
32         iface->hw_features = NULL;
33         os_free(iface->current_rates);
34 --- a/src/ap/hostapd.h
35 +++ b/src/ap/hostapd.h
36 @@ -220,6 +220,9 @@ struct hostapd_iface {
37         /* Overlapping BSS information */
38         int olbc_ht;
39  
40 +       int force_20mhz;
41 +       struct os_time last_20mhz_trigger;
42 +
43         u16 ht_op_mode;
44         void (*scan_cb)(struct hostapd_iface *iface);
45  
46 --- a/src/ap/ieee802_11.c
47 +++ b/src/ap/ieee802_11.c
48 @@ -1242,6 +1242,9 @@ static void handle_beacon(struct hostapd
49                                              sizeof(mgmt->u.beacon)), &elems,
50                                       0);
51  
52 +       if (!elems.ht_capabilities)
53 +               hostapd_trigger_20mhz(hapd->iface);
54 +
55         ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
56  }
57  
58 --- a/src/ap/ieee802_11.h
59 +++ b/src/ap/ieee802_11.h
60 @@ -65,4 +65,17 @@ void hostapd_tx_status(struct hostapd_da
61  void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
62                                 int wds);
63  
64 +#ifdef CONFIG_IEEE80211N
65 +void hostapd_trigger_20mhz(struct hostapd_iface *iface);
66 +void hostapd_deinit_ht(struct hostapd_iface *iface);
67 +
68 +#else
69 +static inline void hostapd_deinit_ht(struct hostapd_iface *iface)
70 +{
71 +}
72 +static inline void hostapd_trigger_20mhz(struct hostapd_iface *iface)
73 +{
74 +}
75 +#endif /* CONFIG_IEEE80211N */
76 +
77  #endif /* IEEE802_11_H */
78 --- a/src/ap/ieee802_11_ht.c
79 +++ b/src/ap/ieee802_11_ht.c
80 @@ -70,12 +70,15 @@ u8 * hostapd_eid_ht_operation(struct hos
81  
82         oper->control_chan = hapd->iconf->channel;
83         oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode);
84 -       if (hapd->iconf->secondary_channel == 1)
85 -               oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
86 -                       HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
87 -       if (hapd->iconf->secondary_channel == -1)
88 -               oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
89 -                       HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
90 +
91 +       if (!hapd->iface->force_20mhz) {
92 +               if (hapd->iconf->secondary_channel == 1)
93 +                       oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE |
94 +                               HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
95 +               if (hapd->iconf->secondary_channel == -1)
96 +                       oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
97 +                               HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH;
98 +       }
99  
100         pos += sizeof(*oper);
101  
102 @@ -265,3 +268,80 @@ void hostapd_get_ht_capab(struct hostapd
103  
104         neg_ht_cap->ht_capabilities_info = host_to_le16(cap);
105  }
106 +
107 +static int hostapd_set_force_20mhz(struct hostapd_iface *iface);
108 +
109 +static int hostapd_restore_40mhz(void *eloop_data, void *user_ctx)
110 +{
111 +       struct hostapd_iface *iface = eloop_data;
112 +       struct os_time time;
113 +       int timeout;
114 +
115 +       if (!iface->last_20mhz_trigger.sec)
116 +           return;
117 +
118 +       os_get_time(&time);
119 +       timeout = iface->last_20mhz_trigger.sec + iface->conf->dynamic_ht40 -
120 +                 time.sec;
121 +
122 +       if (timeout > 0) {
123 +               eloop_register_timeout(timeout, 0, hostapd_restore_40mhz,
124 +                                      iface, NULL);
125 +               return;
126 +       }
127 +
128 +       iface->last_20mhz_trigger.sec = 0;
129 +       iface->last_20mhz_trigger.usec = 0;
130 +
131 +       iface->force_20mhz = 0;
132 +       hostapd_set_force_20mhz(iface);
133 +}
134 +
135 +static int hostapd_set_force_20mhz(struct hostapd_iface *iface)
136 +{
137 +       int secondary_channel;
138 +       int i;
139 +
140 +       ieee802_11_set_beacons(iface);
141 +
142 +       for (i = 0; i < iface->num_bss; i++) {
143 +               struct hostapd_data *hapd = iface->bss[i];
144 +
145 +               if (iface->force_20mhz)
146 +                       secondary_channel = 0;
147 +               else
148 +                       secondary_channel = hapd->iconf->secondary_channel;
149 +
150 +               if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
151 +                                        hapd->iconf->channel,
152 +                                        hapd->iconf->ieee80211n,
153 +                                        secondary_channel)) {
154 +                       wpa_printf(MSG_ERROR, "Could not set channel for "
155 +                                  "kernel driver");
156 +               }
157 +       }
158 +}
159 +
160 +void hostapd_deinit_ht(struct hostapd_iface *iface)
161 +{
162 +       eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);
163 +}
164 +
165 +void hostapd_trigger_20mhz(struct hostapd_iface *iface)
166 +{
167 +       if (!iface->conf->dynamic_ht40)
168 +               return;
169 +
170 +       if (!iface->force_20mhz) {
171 +               iface->force_20mhz = 1;
172 +               hostapd_set_force_20mhz(iface);
173 +       }
174 +
175 +       if (!iface->last_20mhz_trigger.sec) {
176 +               eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL);
177 +               eloop_register_timeout(iface->conf->dynamic_ht40, 0,
178 +                                      hostapd_restore_40mhz, iface, NULL);
179 +       }
180 +
181 +       os_get_time(&iface->last_20mhz_trigger);
182 +}