]>
Commit | Line | Data |
---|---|---|
30295c89 VM |
1 | //------------------------------------------------------------------------------ |
2 | // Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. | |
3 | // | |
4 | // | |
5 | // Permission to use, copy, modify, and/or distribute this software for any | |
6 | // purpose with or without fee is hereby granted, provided that the above | |
7 | // copyright notice and this permission notice appear in all copies. | |
8 | // | |
9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
10 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
11 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
12 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
13 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
14 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
15 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
16 | // | |
17 | // | |
18 | //------------------------------------------------------------------------------ | |
19 | //============================================================================== | |
20 | // This module implements the hardware independent layer of the | |
21 | // Wireless Module Interface (WMI) protocol. | |
22 | // | |
23 | // Author(s): ="Atheros" | |
24 | //============================================================================== | |
25 | ||
26 | #include <a_config.h> | |
27 | #include <athdefs.h> | |
28 | #include <a_types.h> | |
29 | #include <a_osapi.h> | |
30 | #include "htc.h" | |
31 | #include "htc_api.h" | |
32 | #include "wmi.h" | |
33 | #include <wlan_api.h> | |
34 | #include <wmi_api.h> | |
35 | #include <ieee80211.h> | |
36 | #include <ieee80211_node.h> | |
37 | #include "dset_api.h" | |
38 | #include "gpio_api.h" | |
39 | #include "wmi_host.h" | |
40 | #include "a_drv.h" | |
41 | #include "a_drv_api.h" | |
42 | #define ATH_MODULE_NAME wmi | |
43 | #include "a_debug.h" | |
44 | #include "dbglog_api.h" | |
45 | #include "roaming.h" | |
46 | ||
47 | #define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0) | |
48 | ||
49 | #ifdef ATH_DEBUG_MODULE | |
50 | ||
090f807a | 51 | static struct ath_debug_mask_description wmi_debug_desc[] = { |
30295c89 VM |
52 | { ATH_DEBUG_WMI , "General WMI Tracing"}, |
53 | }; | |
54 | ||
55 | ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi, | |
56 | "wmi", | |
57 | "Wireless Module Interface", | |
58 | ATH_DEBUG_MASK_DEFAULTS, | |
59 | ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc), | |
60 | wmi_debug_desc); | |
61 | ||
62 | #endif | |
63 | ||
64 | #ifndef REXOS | |
65 | #define DBGARG _A_FUNCNAME_ | |
66 | #define DBGFMT "%s() : " | |
67 | #define DBG_WMI ATH_DEBUG_WMI | |
68 | #define DBG_ERROR ATH_DEBUG_ERR | |
69 | #define DBG_WMI2 ATH_DEBUG_WMI | |
70 | #define A_DPRINTF AR_DEBUG_PRINTF | |
71 | #endif | |
72 | ||
ab3655da | 73 | static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 74 | |
ab3655da | 75 | static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 76 | int len); |
ab3655da | 77 | static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 VM |
78 | int len); |
79 | ||
ab3655da | 80 | static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 81 | int len); |
ab3655da | 82 | static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 83 | int len); |
ab3655da | 84 | static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 85 | int len); |
ab3655da | 86 | static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 87 | int len); |
1f4c34bd | 88 | static int wmi_sync_point(struct wmi_t *wmip); |
30295c89 | 89 | |
ab3655da | 90 | static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 91 | int len); |
ab3655da | 92 | static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 93 | int len); |
ab3655da | 94 | static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 95 | int len); |
ab3655da | 96 | static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 97 | int len); |
ab3655da JP |
98 | static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len); |
99 | static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, | |
30295c89 VM |
100 | int len); |
101 | ||
ab3655da | 102 | static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 VM |
103 | int len); |
104 | #ifdef CONFIG_HOST_DSET_SUPPORT | |
ab3655da JP |
105 | static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len); |
106 | static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, | |
30295c89 VM |
107 | int len); |
108 | #endif /* CONFIG_HOST_DSET_SUPPORT */ | |
109 | ||
110 | ||
ab3655da | 111 | static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 112 | int len); |
ab3655da JP |
113 | static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len); |
114 | static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len); | |
115 | static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); | |
116 | static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len); | |
117 | static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len); | |
118 | static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len); | |
119 | static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len); | |
120 | static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, | |
30295c89 | 121 | int len); |
ab3655da | 122 | static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 123 | int len); |
ab3655da | 124 | static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 125 | int len); |
1f4c34bd | 126 | static int |
e1ce2a3a | 127 | wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); |
30295c89 | 128 | |
1f4c34bd | 129 | static int |
e1ce2a3a | 130 | wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); |
30295c89 | 131 | |
1f4c34bd | 132 | static int |
e1ce2a3a | 133 | wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len); |
30295c89 VM |
134 | |
135 | #ifdef CONFIG_HOST_GPIO_SUPPORT | |
ab3655da JP |
136 | static int wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len); |
137 | static int wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len); | |
138 | static int wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len); | |
30295c89 VM |
139 | #endif /* CONFIG_HOST_GPIO_SUPPORT */ |
140 | ||
141 | #ifdef CONFIG_HOST_TCMD_SUPPORT | |
1f4c34bd | 142 | static int |
ab3655da | 143 | wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 VM |
144 | #endif |
145 | ||
1f4c34bd | 146 | static int |
ab3655da | 147 | wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 148 | |
1f4c34bd | 149 | static int |
ab3655da | 150 | wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 151 | |
1f4c34bd | 152 | static int |
ab3655da | 153 | wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 154 | |
1071a134 | 155 | static bool |
f68057e6 | 156 | wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex); |
30295c89 | 157 | |
1f4c34bd | 158 | static int |
ab3655da | 159 | wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 160 | |
1f4c34bd | 161 | static int |
ab3655da | 162 | wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 163 | |
ab3655da | 164 | static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 | 165 | |
1f4c34bd | 166 | int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, |
30295c89 VM |
167 | WMI_SYNC_FLAG syncflag); |
168 | ||
cb1e3709 JP |
169 | u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size); |
170 | u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size); | |
30295c89 VM |
171 | |
172 | void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); | |
173 | void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); | |
1f4c34bd | 174 | static int wmi_send_rssi_threshold_params(struct wmi_t *wmip, |
30295c89 | 175 | WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); |
1f4c34bd | 176 | static int wmi_send_snr_threshold_params(struct wmi_t *wmip, |
30295c89 VM |
177 | WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); |
178 | #if defined(CONFIG_TARGET_PROFILE_SUPPORT) | |
1f4c34bd | 179 | static int |
ab3655da | 180 | wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len); |
30295c89 VM |
181 | #endif /* CONFIG_TARGET_PROFILE_SUPPORT */ |
182 | ||
ab3655da | 183 | static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 | 184 | int len); |
ab3655da | 185 | static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 VM |
186 | int len); |
187 | ||
ab3655da | 188 | static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap, |
30295c89 VM |
189 | int len); |
190 | #ifdef ATH_AR6K_11N_SUPPORT | |
ab3655da JP |
191 | static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int); |
192 | static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int); | |
193 | static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int); | |
194 | static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len); | |
195 | static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len); | |
30295c89 | 196 | #endif |
ab3655da | 197 | static int wmi_hci_event_rx(struct wmi_t *, u8 *, int); |
30295c89 VM |
198 | |
199 | #ifdef WAPI_ENABLE | |
ab3655da | 200 | static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap, |
30295c89 VM |
201 | int len); |
202 | #endif | |
203 | ||
204 | #if defined(UNDER_CE) | |
205 | #if defined(NDIS51_MINIPORT) | |
206 | unsigned int processDot11Hdr = 0; | |
207 | #else | |
208 | unsigned int processDot11Hdr = 1; | |
209 | #endif | |
210 | #else | |
211 | extern unsigned int processDot11Hdr; | |
212 | #endif | |
213 | ||
214 | int wps_enable; | |
f68057e6 | 215 | static const s32 wmi_rateTable[][2] = { |
30295c89 VM |
216 | //{W/O SGI, with SGI} |
217 | {1000, 1000}, | |
218 | {2000, 2000}, | |
219 | {5500, 5500}, | |
220 | {11000, 11000}, | |
221 | {6000, 6000}, | |
222 | {9000, 9000}, | |
223 | {12000, 12000}, | |
224 | {18000, 18000}, | |
225 | {24000, 24000}, | |
226 | {36000, 36000}, | |
227 | {48000, 48000}, | |
228 | {54000, 54000}, | |
229 | {6500, 7200}, | |
230 | {13000, 14400}, | |
231 | {19500, 21700}, | |
232 | {26000, 28900}, | |
233 | {39000, 43300}, | |
234 | {52000, 57800}, | |
235 | {58500, 65000}, | |
236 | {65000, 72200}, | |
237 | {13500, 15000}, | |
238 | {27000, 30000}, | |
239 | {40500, 45000}, | |
240 | {54000, 60000}, | |
241 | {81000, 90000}, | |
242 | {108000, 120000}, | |
243 | {121500, 135000}, | |
244 | {135000, 150000}, | |
245 | {0, 0}}; | |
246 | ||
f68057e6 JP |
247 | #define MODE_A_SUPPORT_RATE_START ((s32) 4) |
248 | #define MODE_A_SUPPORT_RATE_STOP ((s32) 11) | |
30295c89 VM |
249 | |
250 | #define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START | |
251 | #define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP | |
252 | ||
f68057e6 JP |
253 | #define MODE_B_SUPPORT_RATE_START ((s32) 0) |
254 | #define MODE_B_SUPPORT_RATE_STOP ((s32) 3) | |
30295c89 | 255 | |
f68057e6 JP |
256 | #define MODE_G_SUPPORT_RATE_START ((s32) 0) |
257 | #define MODE_G_SUPPORT_RATE_STOP ((s32) 11) | |
30295c89 | 258 | |
f68057e6 JP |
259 | #define MODE_GHT20_SUPPORT_RATE_START ((s32) 0) |
260 | #define MODE_GHT20_SUPPORT_RATE_STOP ((s32) 19) | |
30295c89 VM |
261 | |
262 | #define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_SUPPORT_RATE_STOP + 1) | |
263 | ||
264 | /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ | |
ab3655da | 265 | const u8 up_to_ac[]= { |
30295c89 VM |
266 | WMM_AC_BE, |
267 | WMM_AC_BK, | |
268 | WMM_AC_BK, | |
269 | WMM_AC_BE, | |
270 | WMM_AC_VI, | |
271 | WMM_AC_VI, | |
272 | WMM_AC_VO, | |
273 | WMM_AC_VO, | |
274 | }; | |
275 | ||
276 | #include "athstartpack.h" | |
277 | ||
278 | /* This stuff is used when we want a simple layer-3 visibility */ | |
279 | typedef PREPACK struct _iphdr { | |
ab3655da JP |
280 | u8 ip_ver_hdrlen; /* version and hdr length */ |
281 | u8 ip_tos; /* type of service */ | |
4853ac05 JP |
282 | u16 ip_len; /* total length */ |
283 | u16 ip_id; /* identification */ | |
cb1e3709 | 284 | s16 ip_off; /* fragment offset field */ |
30295c89 VM |
285 | #define IP_DF 0x4000 /* dont fragment flag */ |
286 | #define IP_MF 0x2000 /* more fragments flag */ | |
287 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ | |
ab3655da JP |
288 | u8 ip_ttl; /* time to live */ |
289 | u8 ip_p; /* protocol */ | |
4853ac05 | 290 | u16 ip_sum; /* checksum */ |
ab3655da JP |
291 | u8 ip_src[4]; /* source and dest address */ |
292 | u8 ip_dst[4]; | |
30295c89 VM |
293 | } POSTPACK iphdr; |
294 | ||
295 | #include "athendpack.h" | |
296 | ||
cb1e3709 JP |
297 | static s16 rssi_event_value = 0; |
298 | static s16 snr_event_value = 0; | |
30295c89 | 299 | |
1071a134 | 300 | bool is_probe_ssid = false; |
30295c89 VM |
301 | |
302 | void * | |
303 | wmi_init(void *devt) | |
304 | { | |
305 | struct wmi_t *wmip; | |
306 | ||
307 | A_REGISTER_MODULE_DEBUG_INFO(wmi); | |
308 | ||
309 | wmip = A_MALLOC (sizeof(struct wmi_t)); | |
310 | if (wmip == NULL) { | |
311 | return (NULL); | |
312 | } | |
313 | A_MEMZERO(wmip, sizeof(struct wmi_t )); | |
314 | #ifdef THREAD_X | |
315 | INIT_WMI_LOCK(wmip); | |
316 | #else | |
317 | A_MUTEX_INIT(&wmip->wmi_lock); | |
318 | #endif | |
319 | wmip->wmi_devt = devt; | |
320 | wlan_node_table_init(wmip, &wmip->wmi_scan_table); | |
321 | wmi_qos_state_init(wmip); | |
322 | ||
323 | wmip->wmi_powerMode = REC_POWER; | |
324 | wmip->wmi_phyMode = WMI_11G_MODE; | |
325 | ||
326 | wmip->wmi_pair_crypto_type = NONE_CRYPT; | |
327 | wmip->wmi_grp_crypto_type = NONE_CRYPT; | |
328 | ||
329 | wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1; | |
330 | wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1; | |
331 | ||
332 | return (wmip); | |
333 | } | |
334 | ||
335 | void | |
336 | wmi_qos_state_init(struct wmi_t *wmip) | |
337 | { | |
ab3655da | 338 | u8 i; |
30295c89 VM |
339 | |
340 | if (wmip == NULL) { | |
341 | return; | |
342 | } | |
343 | LOCK_WMI(wmip); | |
344 | ||
345 | /* Initialize QoS States */ | |
346 | wmip->wmi_numQoSStream = 0; | |
347 | ||
348 | wmip->wmi_fatPipeExists = 0; | |
349 | ||
350 | for (i=0; i < WMM_NUM_AC; i++) { | |
351 | wmip->wmi_streamExistsForAC[i]=0; | |
352 | } | |
353 | ||
354 | UNLOCK_WMI(wmip); | |
355 | ||
356 | A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1); | |
357 | } | |
358 | ||
359 | void | |
360 | wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid) | |
361 | { | |
362 | A_ASSERT( eid != ENDPOINT_UNUSED); | |
363 | wmip->wmi_endpoint_id = eid; | |
364 | } | |
365 | ||
366 | HTC_ENDPOINT_ID | |
367 | wmi_get_control_ep(struct wmi_t * wmip) | |
368 | { | |
369 | return(wmip->wmi_endpoint_id); | |
370 | } | |
371 | ||
372 | void | |
373 | wmi_shutdown(struct wmi_t *wmip) | |
374 | { | |
375 | if (wmip != NULL) { | |
376 | wlan_node_table_cleanup(&wmip->wmi_scan_table); | |
377 | if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) { | |
378 | #ifdef THREAD_X | |
379 | DELETE_WMI_LOCK(&wmip); | |
380 | #else | |
381 | A_MUTEX_DELETE(&wmip->wmi_lock); | |
382 | #endif | |
383 | } | |
384 | A_FREE(wmip); | |
385 | } | |
386 | } | |
387 | ||
388 | /* | |
389 | * performs DIX to 802.3 encapsulation for transmit packets. | |
390 | * uses passed in buffer. Returns buffer or NULL if failed. | |
391 | * Assumes the entire DIX header is contigous and that there is | |
392 | * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. | |
393 | */ | |
1f4c34bd | 394 | int |
30295c89 VM |
395 | wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf) |
396 | { | |
ab3655da | 397 | u8 *datap; |
4853ac05 | 398 | u16 typeorlen; |
30295c89 VM |
399 | ATH_MAC_HDR macHdr; |
400 | ATH_LLC_SNAP_HDR *llcHdr; | |
401 | ||
402 | A_ASSERT(osbuf != NULL); | |
403 | ||
404 | if (A_NETBUF_HEADROOM(osbuf) < | |
405 | (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) | |
406 | { | |
407 | return A_NO_MEMORY; | |
408 | } | |
409 | ||
410 | datap = A_NETBUF_DATA(osbuf); | |
411 | ||
4853ac05 | 412 | typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); |
30295c89 VM |
413 | |
414 | if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { | |
415 | /* | |
416 | * packet is already in 802.3 format - return success | |
417 | */ | |
418 | A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); | |
4f69cef0 | 419 | return (0); |
30295c89 VM |
420 | } |
421 | ||
422 | /* | |
423 | * Save mac fields and length to be inserted later | |
424 | */ | |
05209262 LR |
425 | memcpy(macHdr.dstMac, datap, ATH_MAC_LEN); |
426 | memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); | |
30295c89 VM |
427 | macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + |
428 | sizeof(ATH_LLC_SNAP_HDR)); | |
429 | ||
430 | /* | |
431 | * Make room for LLC+SNAP headers | |
432 | */ | |
4f69cef0 | 433 | if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { |
30295c89 VM |
434 | return A_NO_MEMORY; |
435 | } | |
436 | datap = A_NETBUF_DATA(osbuf); | |
437 | ||
05209262 | 438 | memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR)); |
30295c89 VM |
439 | |
440 | llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); | |
441 | llcHdr->dsap = 0xAA; | |
442 | llcHdr->ssap = 0xAA; | |
443 | llcHdr->cntl = 0x03; | |
444 | llcHdr->orgCode[0] = 0x0; | |
445 | llcHdr->orgCode[1] = 0x0; | |
446 | llcHdr->orgCode[2] = 0x0; | |
447 | llcHdr->etherType = typeorlen; | |
448 | ||
4f69cef0 | 449 | return (0); |
30295c89 VM |
450 | } |
451 | ||
ab3655da | 452 | int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS) |
30295c89 VM |
453 | { |
454 | switch(*pVersion){ | |
455 | case 0: | |
4f69cef0 | 456 | return (0); |
30295c89 VM |
457 | case WMI_META_VERSION_1: |
458 | { | |
459 | WMI_TX_META_V1 *pV1= NULL; | |
460 | A_ASSERT(osbuf != NULL); | |
4f69cef0 | 461 | if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) { |
30295c89 VM |
462 | return A_NO_MEMORY; |
463 | } | |
464 | ||
465 | pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf); | |
466 | /* the pktID is used in conjunction with txComplete messages | |
467 | * allowing the target to notify which tx requests have been | |
468 | * completed and how. */ | |
469 | pV1->pktID = 0; | |
470 | /* the ratePolicyID allows the host to specify which rate policy | |
471 | * to use for transmitting this packet. 0 means use default behavior. */ | |
472 | pV1->ratePolicyID = 0; | |
473 | A_ASSERT(pVersion != NULL); | |
474 | /* the version must be used to populate the meta field of the WMI_DATA_HDR */ | |
475 | *pVersion = WMI_META_VERSION_1; | |
4f69cef0 | 476 | return (0); |
30295c89 VM |
477 | } |
478 | #ifdef CONFIG_CHECKSUM_OFFLOAD | |
479 | case WMI_META_VERSION_2: | |
480 | { | |
481 | WMI_TX_META_V2 *pV2 ; | |
482 | A_ASSERT(osbuf != NULL); | |
4f69cef0 | 483 | if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) { |
30295c89 VM |
484 | return A_NO_MEMORY; |
485 | } | |
486 | pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf); | |
05209262 | 487 | memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2)); |
4f69cef0 | 488 | return (0); |
30295c89 VM |
489 | } |
490 | #endif | |
491 | default: | |
4f69cef0 | 492 | return (0); |
30295c89 VM |
493 | } |
494 | } | |
495 | ||
496 | /* Adds a WMI data header */ | |
1f4c34bd | 497 | int |
ab3655da JP |
498 | wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, |
499 | WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS) | |
30295c89 VM |
500 | { |
501 | WMI_DATA_HDR *dtHdr; | |
ab3655da | 502 | // u8 metaVersion = 0; |
1f4c34bd | 503 | int status; |
30295c89 VM |
504 | |
505 | A_ASSERT(osbuf != NULL); | |
506 | ||
507 | /* adds the meta data field after the wmi data hdr. If metaVersion | |
508 | * is returns 0 then no meta field was added. */ | |
4f69cef0 | 509 | if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) { |
30295c89 VM |
510 | return status; |
511 | } | |
512 | ||
4f69cef0 | 513 | if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) { |
30295c89 VM |
514 | return A_NO_MEMORY; |
515 | } | |
516 | ||
517 | dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); | |
518 | A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR)); | |
519 | ||
520 | WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType); | |
521 | WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type); | |
522 | ||
523 | if (bMoreData) { | |
524 | WMI_DATA_HDR_SET_MORE_BIT(dtHdr); | |
525 | } | |
526 | ||
527 | WMI_DATA_HDR_SET_META(dtHdr, metaVersion); | |
528 | //dtHdr->rssi = 0; | |
529 | ||
4f69cef0 | 530 | return (0); |
30295c89 VM |
531 | } |
532 | ||
533 | ||
e1ce2a3a | 534 | u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled) |
30295c89 | 535 | { |
ab3655da JP |
536 | u8 *datap; |
537 | u8 trafficClass = WMM_AC_BE; | |
4853ac05 | 538 | u16 ipType = IP_ETHERTYPE; |
30295c89 | 539 | WMI_DATA_HDR *dtHdr; |
ab3655da JP |
540 | u8 streamExists = 0; |
541 | u8 userPriority; | |
e1ce2a3a | 542 | u32 hdrsize, metasize; |
30295c89 VM |
543 | ATH_LLC_SNAP_HDR *llcHdr; |
544 | ||
545 | WMI_CREATE_PSTREAM_CMD cmd; | |
546 | ||
547 | A_ASSERT(osbuf != NULL); | |
548 | ||
549 | // | |
550 | // Initialize header size | |
551 | // | |
552 | hdrsize = 0; | |
553 | ||
554 | datap = A_NETBUF_DATA(osbuf); | |
555 | dtHdr = (WMI_DATA_HDR *)datap; | |
556 | metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0; | |
557 | ||
558 | if (!wmmEnabled) | |
559 | { | |
560 | /* If WMM is disabled all traffic goes as BE traffic */ | |
561 | userPriority = 0; | |
562 | } | |
563 | else | |
564 | { | |
565 | if (processDot11Hdr) | |
566 | { | |
e1ce2a3a | 567 | hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); |
30295c89 VM |
568 | llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + |
569 | hdrsize); | |
570 | ||
571 | ||
572 | } | |
573 | else | |
574 | { | |
575 | llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + | |
576 | sizeof(ATH_MAC_HDR)); | |
577 | } | |
578 | ||
579 | if (llcHdr->etherType == A_CPU2BE16(ipType)) | |
580 | { | |
581 | /* Extract the endpoint info from the TOS field in the IP header */ | |
582 | ||
ab3655da | 583 | userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority); |
30295c89 VM |
584 | } |
585 | else | |
586 | { | |
587 | userPriority = layer2Priority & 0x7; | |
588 | } | |
589 | } | |
590 | ||
591 | ||
592 | /* workaround for WMM S5 */ | |
593 | if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority))) | |
594 | { | |
595 | userPriority = 1; | |
596 | } | |
597 | ||
598 | trafficClass = convert_userPriority_to_trafficClass(userPriority); | |
599 | ||
600 | WMI_DATA_HDR_SET_UP(dtHdr, userPriority); | |
601 | /* lower 3-bits are 802.1d priority */ | |
602 | //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; | |
603 | ||
604 | LOCK_WMI(wmip); | |
605 | streamExists = wmip->wmi_fatPipeExists; | |
606 | UNLOCK_WMI(wmip); | |
607 | ||
608 | if (!(streamExists & (1 << trafficClass))) | |
609 | { | |
610 | ||
611 | A_MEMZERO(&cmd, sizeof(cmd)); | |
612 | cmd.trafficClass = trafficClass; | |
613 | cmd.userPriority = userPriority; | |
614 | cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT; | |
615 | /* Implicit streams are created with TSID 0xFF */ | |
616 | ||
617 | cmd.tsid = WMI_IMPLICIT_PSTREAM; | |
618 | wmi_create_pstream_cmd(wmip, &cmd); | |
619 | } | |
620 | ||
621 | return trafficClass; | |
622 | } | |
623 | ||
1f4c34bd | 624 | int |
30295c89 VM |
625 | wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode) |
626 | { | |
ab3655da | 627 | u8 *datap; |
4853ac05 | 628 | u16 typeorlen; |
30295c89 VM |
629 | ATH_MAC_HDR macHdr; |
630 | ATH_LLC_SNAP_HDR *llcHdr; | |
631 | struct ieee80211_frame *wh; | |
e1ce2a3a | 632 | u32 hdrsize; |
30295c89 VM |
633 | |
634 | A_ASSERT(osbuf != NULL); | |
635 | ||
636 | if (A_NETBUF_HEADROOM(osbuf) < | |
637 | (sizeof(struct ieee80211_qosframe) + sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) | |
638 | { | |
639 | return A_NO_MEMORY; | |
640 | } | |
641 | ||
642 | datap = A_NETBUF_DATA(osbuf); | |
643 | ||
4853ac05 | 644 | typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); |
30295c89 VM |
645 | |
646 | if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { | |
647 | /* | |
648 | * packet is already in 802.3 format - return success | |
649 | */ | |
650 | A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); | |
651 | goto AddDot11Hdr; | |
652 | } | |
653 | ||
654 | /* | |
655 | * Save mac fields and length to be inserted later | |
656 | */ | |
05209262 LR |
657 | memcpy(macHdr.dstMac, datap, ATH_MAC_LEN); |
658 | memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); | |
30295c89 VM |
659 | macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + |
660 | sizeof(ATH_LLC_SNAP_HDR)); | |
661 | ||
662 | // Remove the Ethernet hdr | |
663 | A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_HDR)); | |
664 | /* | |
665 | * Make room for LLC+SNAP headers | |
666 | */ | |
4f69cef0 | 667 | if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { |
30295c89 VM |
668 | return A_NO_MEMORY; |
669 | } | |
670 | datap = A_NETBUF_DATA(osbuf); | |
671 | ||
672 | llcHdr = (ATH_LLC_SNAP_HDR *)(datap); | |
673 | llcHdr->dsap = 0xAA; | |
674 | llcHdr->ssap = 0xAA; | |
675 | llcHdr->cntl = 0x03; | |
676 | llcHdr->orgCode[0] = 0x0; | |
677 | llcHdr->orgCode[1] = 0x0; | |
678 | llcHdr->orgCode[2] = 0x0; | |
679 | llcHdr->etherType = typeorlen; | |
680 | ||
681 | AddDot11Hdr: | |
682 | /* Make room for 802.11 hdr */ | |
683 | if (wmip->wmi_is_wmm_enabled) | |
684 | { | |
e1ce2a3a | 685 | hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); |
4f69cef0 | 686 | if (A_NETBUF_PUSH(osbuf, hdrsize) != 0) |
30295c89 VM |
687 | { |
688 | return A_NO_MEMORY; | |
689 | } | |
690 | wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); | |
691 | wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS; | |
692 | } | |
693 | else | |
694 | { | |
e1ce2a3a | 695 | hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32)); |
4f69cef0 | 696 | if (A_NETBUF_PUSH(osbuf, hdrsize) != 0) |
30295c89 VM |
697 | { |
698 | return A_NO_MEMORY; | |
699 | } | |
700 | wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); | |
701 | wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA; | |
702 | } | |
703 | /* Setup the SA & DA */ | |
704 | IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac); | |
705 | ||
706 | if (mode == INFRA_NETWORK) { | |
707 | IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac); | |
708 | } | |
709 | else if (mode == ADHOC_NETWORK) { | |
710 | IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac); | |
711 | } | |
712 | ||
4f69cef0 | 713 | return (0); |
30295c89 VM |
714 | } |
715 | ||
1f4c34bd | 716 | int |
30295c89 VM |
717 | wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf) |
718 | { | |
ab3655da | 719 | u8 *datap; |
30295c89 | 720 | struct ieee80211_frame *pwh,wh; |
ab3655da | 721 | u8 type,subtype; |
30295c89 VM |
722 | ATH_LLC_SNAP_HDR *llcHdr; |
723 | ATH_MAC_HDR macHdr; | |
e1ce2a3a | 724 | u32 hdrsize; |
30295c89 VM |
725 | |
726 | A_ASSERT(osbuf != NULL); | |
727 | datap = A_NETBUF_DATA(osbuf); | |
728 | ||
729 | pwh = (struct ieee80211_frame *)datap; | |
730 | type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | |
731 | subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; | |
732 | ||
05209262 | 733 | memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame)); |
30295c89 VM |
734 | |
735 | /* strip off the 802.11 hdr*/ | |
736 | if (subtype == IEEE80211_FC0_SUBTYPE_QOS) { | |
e1ce2a3a | 737 | hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32)); |
30295c89 VM |
738 | A_NETBUF_PULL(osbuf, hdrsize); |
739 | } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) { | |
740 | A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame)); | |
741 | } | |
742 | ||
743 | datap = A_NETBUF_DATA(osbuf); | |
744 | llcHdr = (ATH_LLC_SNAP_HDR *)(datap); | |
745 | ||
746 | macHdr.typeOrLen = llcHdr->etherType; | |
747 | A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac)); | |
748 | A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac)); | |
749 | ||
750 | switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { | |
751 | case IEEE80211_FC1_DIR_NODS: | |
752 | IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); | |
753 | IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); | |
754 | break; | |
755 | case IEEE80211_FC1_DIR_TODS: | |
756 | IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3); | |
757 | IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); | |
758 | break; | |
759 | case IEEE80211_FC1_DIR_FROMDS: | |
760 | IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); | |
761 | IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3); | |
762 | break; | |
763 | case IEEE80211_FC1_DIR_DSTODS: | |
764 | break; | |
765 | } | |
766 | ||
767 | // Remove the LLC Hdr. | |
768 | A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)); | |
769 | ||
770 | // Insert the ATH MAC hdr. | |
771 | ||
772 | A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR)); | |
773 | datap = A_NETBUF_DATA(osbuf); | |
774 | ||
05209262 | 775 | memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR)); |
30295c89 | 776 | |
4f69cef0 | 777 | return 0; |
30295c89 VM |
778 | } |
779 | ||
780 | /* | |
781 | * performs 802.3 to DIX encapsulation for received packets. | |
782 | * Assumes the entire 802.3 header is contigous. | |
783 | */ | |
1f4c34bd | 784 | int |
30295c89 VM |
785 | wmi_dot3_2_dix(void *osbuf) |
786 | { | |
ab3655da | 787 | u8 *datap; |
30295c89 VM |
788 | ATH_MAC_HDR macHdr; |
789 | ATH_LLC_SNAP_HDR *llcHdr; | |
790 | ||
791 | A_ASSERT(osbuf != NULL); | |
792 | datap = A_NETBUF_DATA(osbuf); | |
793 | ||
05209262 | 794 | memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR)); |
30295c89 VM |
795 | llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); |
796 | macHdr.typeOrLen = llcHdr->etherType; | |
797 | ||
4f69cef0 | 798 | if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) { |
30295c89 VM |
799 | return A_NO_MEMORY; |
800 | } | |
801 | ||
802 | datap = A_NETBUF_DATA(osbuf); | |
803 | ||
05209262 | 804 | memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR)); |
30295c89 | 805 | |
4f69cef0 | 806 | return (0); |
30295c89 VM |
807 | } |
808 | ||
809 | /* | |
810 | * Removes a WMI data header | |
811 | */ | |
1f4c34bd | 812 | int |
30295c89 VM |
813 | wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf) |
814 | { | |
815 | A_ASSERT(osbuf != NULL); | |
816 | ||
817 | return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR))); | |
818 | } | |
819 | ||
820 | void | |
821 | wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg) | |
822 | { | |
823 | wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg); | |
824 | } | |
825 | ||
826 | /* | |
827 | * WMI Extended Event received from Target. | |
828 | */ | |
1f4c34bd | 829 | int |
30295c89 VM |
830 | wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf) |
831 | { | |
832 | WMIX_CMD_HDR *cmd; | |
4853ac05 | 833 | u16 id; |
ab3655da | 834 | u8 *datap; |
e1ce2a3a | 835 | u32 len; |
4f69cef0 | 836 | int status = 0; |
30295c89 VM |
837 | |
838 | if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) { | |
839 | A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); | |
840 | wmip->wmi_stats.cmd_len_err++; | |
841 | return A_ERROR; | |
842 | } | |
843 | ||
844 | cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); | |
845 | id = cmd->commandId; | |
846 | ||
4f69cef0 | 847 | if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) { |
30295c89 VM |
848 | A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); |
849 | wmip->wmi_stats.cmd_len_err++; | |
850 | return A_ERROR; | |
851 | } | |
852 | ||
853 | datap = A_NETBUF_DATA(osbuf); | |
854 | len = A_NETBUF_LEN(osbuf); | |
855 | ||
856 | switch (id) { | |
857 | case (WMIX_DSETOPENREQ_EVENTID): | |
858 | status = wmi_dset_open_req_rx(wmip, datap, len); | |
859 | break; | |
860 | #ifdef CONFIG_HOST_DSET_SUPPORT | |
861 | case (WMIX_DSETCLOSE_EVENTID): | |
862 | status = wmi_dset_close_rx(wmip, datap, len); | |
863 | break; | |
864 | case (WMIX_DSETDATAREQ_EVENTID): | |
865 | status = wmi_dset_data_req_rx(wmip, datap, len); | |
866 | break; | |
867 | #endif /* CONFIG_HOST_DSET_SUPPORT */ | |
868 | #ifdef CONFIG_HOST_GPIO_SUPPORT | |
869 | case (WMIX_GPIO_INTR_EVENTID): | |
870 | wmi_gpio_intr_rx(wmip, datap, len); | |
871 | break; | |
872 | case (WMIX_GPIO_DATA_EVENTID): | |
873 | wmi_gpio_data_rx(wmip, datap, len); | |
874 | break; | |
875 | case (WMIX_GPIO_ACK_EVENTID): | |
876 | wmi_gpio_ack_rx(wmip, datap, len); | |
877 | break; | |
878 | #endif /* CONFIG_HOST_GPIO_SUPPORT */ | |
879 | case (WMIX_HB_CHALLENGE_RESP_EVENTID): | |
880 | wmi_hbChallengeResp_rx(wmip, datap, len); | |
881 | break; | |
882 | case (WMIX_DBGLOG_EVENTID): | |
883 | wmi_dbglog_event_rx(wmip, datap, len); | |
884 | break; | |
885 | #if defined(CONFIG_TARGET_PROFILE_SUPPORT) | |
886 | case (WMIX_PROF_COUNT_EVENTID): | |
887 | wmi_prof_count_rx(wmip, datap, len); | |
888 | break; | |
889 | #endif /* CONFIG_TARGET_PROFILE_SUPPORT */ | |
890 | default: | |
891 | A_DPRINTF(DBG_WMI|DBG_ERROR, | |
892 | (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); | |
893 | wmip->wmi_stats.cmd_id_err++; | |
894 | status = A_ERROR; | |
895 | break; | |
896 | } | |
897 | ||
898 | return status; | |
899 | } | |
900 | ||
901 | /* | |
902 | * Control Path | |
903 | */ | |
e1ce2a3a | 904 | u32 cmdRecvNum; |
30295c89 | 905 | |
1f4c34bd | 906 | int |
30295c89 VM |
907 | wmi_control_rx(struct wmi_t *wmip, void *osbuf) |
908 | { | |
909 | WMI_CMD_HDR *cmd; | |
4853ac05 | 910 | u16 id; |
ab3655da | 911 | u8 *datap; |
e1ce2a3a | 912 | u32 len, i, loggingReq; |
4f69cef0 | 913 | int status = 0; |
30295c89 VM |
914 | |
915 | A_ASSERT(osbuf != NULL); | |
916 | if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) { | |
917 | A_NETBUF_FREE(osbuf); | |
918 | A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); | |
919 | wmip->wmi_stats.cmd_len_err++; | |
920 | return A_ERROR; | |
921 | } | |
922 | ||
923 | cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); | |
924 | id = cmd->commandId; | |
925 | ||
4f69cef0 | 926 | if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) { |
30295c89 VM |
927 | A_NETBUF_FREE(osbuf); |
928 | A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); | |
929 | wmip->wmi_stats.cmd_len_err++; | |
930 | return A_ERROR; | |
931 | } | |
932 | ||
933 | datap = A_NETBUF_DATA(osbuf); | |
934 | len = A_NETBUF_LEN(osbuf); | |
935 | ||
936 | loggingReq = 0; | |
937 | ||
938 | ar6000_get_driver_cfg(wmip->wmi_devt, | |
939 | AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS, | |
940 | &loggingReq); | |
941 | ||
942 | if(loggingReq) { | |
943 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id)); | |
944 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum)); | |
945 | for(i = 0; i < len; i++) | |
946 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i])); | |
947 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n")); | |
948 | } | |
949 | ||
950 | LOCK_WMI(wmip); | |
951 | cmdRecvNum++; | |
952 | UNLOCK_WMI(wmip); | |
953 | ||
954 | switch (id) { | |
955 | case (WMI_GET_BITRATE_CMDID): | |
956 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG)); | |
957 | status = wmi_bitrate_reply_rx(wmip, datap, len); | |
958 | break; | |
959 | case (WMI_GET_CHANNEL_LIST_CMDID): | |
960 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG)); | |
961 | status = wmi_channelList_reply_rx(wmip, datap, len); | |
962 | break; | |
963 | case (WMI_GET_TX_PWR_CMDID): | |
964 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG)); | |
965 | status = wmi_txPwr_reply_rx(wmip, datap, len); | |
966 | break; | |
967 | case (WMI_READY_EVENTID): | |
968 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG)); | |
969 | status = wmi_ready_event_rx(wmip, datap, len); | |
970 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
971 | A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt); | |
972 | break; | |
973 | case (WMI_CONNECT_EVENTID): | |
974 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG)); | |
975 | status = wmi_connect_event_rx(wmip, datap, len); | |
976 | A_WMI_SEND_GENERIC_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
977 | break; | |
978 | case (WMI_DISCONNECT_EVENTID): | |
979 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG)); | |
980 | status = wmi_disconnect_event_rx(wmip, datap, len); | |
981 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
982 | break; | |
983 | case (WMI_PEER_NODE_EVENTID): | |
984 | A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG)); | |
985 | status = wmi_peer_node_event_rx(wmip, datap, len); | |
986 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
987 | break; | |
988 | case (WMI_TKIP_MICERR_EVENTID): | |
989 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG)); | |
990 | status = wmi_tkip_micerr_event_rx(wmip, datap, len); | |
991 | break; | |
992 | case (WMI_BSSINFO_EVENTID): | |
993 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG)); | |
994 | { | |
995 | /* | |
996 | * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR | |
997 | * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer | |
998 | * and reconstruct the WMI_BSS_INFO_HDR in its place | |
999 | */ | |
1000 | WMI_BSS_INFO_HDR2 bih2; | |
1001 | WMI_BSS_INFO_HDR *bih; | |
05209262 | 1002 | memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2)); |
30295c89 VM |
1003 | |
1004 | A_NETBUF_PUSH(osbuf, 4); | |
1005 | datap = A_NETBUF_DATA(osbuf); | |
1006 | len = A_NETBUF_LEN(osbuf); | |
1007 | bih = (WMI_BSS_INFO_HDR *)datap; | |
1008 | ||
1009 | bih->channel = bih2.channel; | |
1010 | bih->frameType = bih2.frameType; | |
1011 | bih->snr = bih2.snr; | |
1012 | bih->rssi = bih2.snr - 95; | |
1013 | bih->ieMask = bih2.ieMask; | |
05209262 | 1014 | memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN); |
30295c89 VM |
1015 | |
1016 | status = wmi_bssInfo_event_rx(wmip, datap, len); | |
1017 | A_WMI_SEND_GENERIC_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
1018 | } | |
1019 | break; | |
1020 | case (WMI_REGDOMAIN_EVENTID): | |
1021 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG)); | |
1022 | status = wmi_regDomain_event_rx(wmip, datap, len); | |
1023 | break; | |
1024 | case (WMI_PSTREAM_TIMEOUT_EVENTID): | |
1025 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG)); | |
1026 | status = wmi_pstream_timeout_event_rx(wmip, datap, len); | |
1027 | /* pstreams are fatpipe abstractions that get implicitly created. | |
1028 | * User apps only deal with thinstreams. creation of a thinstream | |
1029 | * by the user or data traffic flow in an AC triggers implicit | |
1030 | * pstream creation. Do we need to send this event to App..? | |
1031 | * no harm in sending it. | |
1032 | */ | |
1033 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
1034 | break; | |
1035 | case (WMI_NEIGHBOR_REPORT_EVENTID): | |
1036 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG)); | |
1037 | status = wmi_neighborReport_event_rx(wmip, datap, len); | |
1038 | break; | |
1039 | case (WMI_SCAN_COMPLETE_EVENTID): | |
1040 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG)); | |
1041 | status = wmi_scanComplete_rx(wmip, datap, len); | |
1042 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
1043 | break; | |
1044 | case (WMI_CMDERROR_EVENTID): | |
1045 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG)); | |
1046 | status = wmi_errorEvent_rx(wmip, datap, len); | |
1047 | break; | |
1048 | case (WMI_REPORT_STATISTICS_EVENTID): | |
1049 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG)); | |
1050 | status = wmi_statsEvent_rx(wmip, datap, len); | |
1051 | break; | |
1052 | case (WMI_RSSI_THRESHOLD_EVENTID): | |
1053 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG)); | |
1054 | status = wmi_rssiThresholdEvent_rx(wmip, datap, len); | |
1055 | break; | |
1056 | case (WMI_ERROR_REPORT_EVENTID): | |
1057 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG)); | |
1058 | status = wmi_reportErrorEvent_rx(wmip, datap, len); | |
1059 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
1060 | break; | |
1061 | case (WMI_OPT_RX_FRAME_EVENTID): | |
1062 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG)); | |
1063 | status = wmi_opt_frame_event_rx(wmip, datap, len); | |
1064 | break; | |
1065 | case (WMI_REPORT_ROAM_TBL_EVENTID): | |
1066 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG)); | |
1067 | status = wmi_roam_tbl_event_rx(wmip, datap, len); | |
1068 | break; | |
1069 | case (WMI_EXTENSION_EVENTID): | |
1070 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG)); | |
1071 | status = wmi_control_rx_xtnd(wmip, osbuf); | |
1072 | break; | |
1073 | case (WMI_CAC_EVENTID): | |
1074 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG)); | |
1075 | status = wmi_cac_event_rx(wmip, datap, len); | |
1076 | break; | |
1077 | case (WMI_CHANNEL_CHANGE_EVENTID): | |
1078 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG)); | |
1079 | status = wmi_channel_change_event_rx(wmip, datap, len); | |
1080 | break; | |
1081 | case (WMI_REPORT_ROAM_DATA_EVENTID): | |
1082 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG)); | |
1083 | status = wmi_roam_data_event_rx(wmip, datap, len); | |
1084 | break; | |
1085 | #ifdef CONFIG_HOST_TCMD_SUPPORT | |
1086 | case (WMI_TEST_EVENTID): | |
1087 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG)); | |
1088 | status = wmi_tcmd_test_report_rx(wmip, datap, len); | |
1089 | break; | |
1090 | #endif | |
1091 | case (WMI_GET_FIXRATES_CMDID): | |
1092 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG)); | |
1093 | status = wmi_ratemask_reply_rx(wmip, datap, len); | |
1094 | break; | |
1095 | case (WMI_TX_RETRY_ERR_EVENTID): | |
1096 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG)); | |
1097 | status = wmi_txRetryErrEvent_rx(wmip, datap, len); | |
1098 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
1099 | break; | |
1100 | case (WMI_SNR_THRESHOLD_EVENTID): | |
1101 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG)); | |
1102 | status = wmi_snrThresholdEvent_rx(wmip, datap, len); | |
1103 | break; | |
1104 | case (WMI_LQ_THRESHOLD_EVENTID): | |
1105 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG)); | |
1106 | status = wmi_lqThresholdEvent_rx(wmip, datap, len); | |
1107 | A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); | |
1108 | break; | |
1109 | case (WMI_APLIST_EVENTID): | |
1110 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n")); | |
1111 | status = wmi_aplistEvent_rx(wmip, datap, len); | |
1112 | break; | |
1113 | case (WMI_GET_KEEPALIVE_CMDID): | |
1114 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG)); | |
1115 | status = wmi_keepalive_reply_rx(wmip, datap, len); | |
1116 | break; | |
1117 | case (WMI_GET_WOW_LIST_EVENTID): | |
1118 | status = wmi_get_wow_list_event_rx(wmip, datap, len); | |
1119 | break; | |
1120 | case (WMI_GET_PMKID_LIST_EVENTID): | |
1121 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG)); | |
1122 | status = wmi_get_pmkid_list_event_rx(wmip, datap, len); | |
1123 | break; | |
1124 | case (WMI_PSPOLL_EVENTID): | |
1125 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG)); | |
1126 | status = wmi_pspoll_event_rx(wmip, datap, len); | |
1127 | break; | |
1128 | case (WMI_DTIMEXPIRY_EVENTID): | |
1129 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG)); | |
1130 | status = wmi_dtimexpiry_event_rx(wmip, datap, len); | |
1131 | break; | |
1132 | case (WMI_SET_PARAMS_REPLY_EVENTID): | |
1133 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG)); | |
1134 | status = wmi_set_params_event_rx(wmip, datap, len); | |
1135 | break; | |
1136 | case (WMI_ACM_REJECT_EVENTID): | |
1137 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG)); | |
1138 | status = wmi_acm_reject_event_rx(wmip, datap, len); | |
1139 | break; | |
1140 | #ifdef ATH_AR6K_11N_SUPPORT | |
1141 | case (WMI_ADDBA_REQ_EVENTID): | |
1142 | status = wmi_addba_req_event_rx(wmip, datap, len); | |
1143 | break; | |
1144 | case (WMI_ADDBA_RESP_EVENTID): | |
1145 | status = wmi_addba_resp_event_rx(wmip, datap, len); | |
1146 | break; | |
1147 | case (WMI_DELBA_REQ_EVENTID): | |
1148 | status = wmi_delba_req_event_rx(wmip, datap, len); | |
1149 | break; | |
1150 | case (WMI_REPORT_BTCOEX_CONFIG_EVENTID): | |
1151 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG)); | |
1152 | status = wmi_btcoex_config_event_rx(wmip, datap, len); | |
1153 | break; | |
1154 | case (WMI_REPORT_BTCOEX_STATS_EVENTID): | |
1155 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG)); | |
1156 | status = wmi_btcoex_stats_event_rx(wmip, datap, len); | |
1157 | break; | |
1158 | #endif | |
1159 | case (WMI_TX_COMPLETE_EVENTID): | |
1160 | { | |
1161 | int index; | |
1162 | TX_COMPLETE_MSG_V1 *pV1; | |
1163 | WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap; | |
1164 | A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType); | |
1165 | ||
1166 | for(index = 0 ; index < pEv->numMessages ; index++) { | |
1167 | pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1)); | |
1168 | A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures); | |
1169 | } | |
1170 | } | |
1171 | break; | |
1172 | case (WMI_HCI_EVENT_EVENTID): | |
1173 | status = wmi_hci_event_rx(wmip, datap, len); | |
1174 | break; | |
1175 | #ifdef WAPI_ENABLE | |
1176 | case (WMI_WAPI_REKEY_EVENTID): | |
1177 | A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG)); | |
1178 | status = wmi_wapi_rekey_event_rx(wmip, datap, len); | |
1179 | break; | |
1180 | #endif | |
1181 | default: | |
1182 | A_DPRINTF(DBG_WMI|DBG_ERROR, | |
1183 | (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); | |
1184 | wmip->wmi_stats.cmd_id_err++; | |
1185 | status = A_ERROR; | |
1186 | break; | |
1187 | } | |
1188 | ||
1189 | A_NETBUF_FREE(osbuf); | |
1190 | ||
1191 | return status; | |
1192 | } | |
1193 | ||
1194 | /* Send a "simple" wmi command -- one with no arguments */ | |
1f4c34bd | 1195 | static int |
30295c89 VM |
1196 | wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid) |
1197 | { | |
1198 | void *osbuf; | |
1199 | ||
1200 | osbuf = A_NETBUF_ALLOC(0); | |
1201 | if (osbuf == NULL) { | |
1202 | return A_NO_MEMORY; | |
1203 | } | |
1204 | ||
1205 | return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); | |
1206 | } | |
1207 | ||
1208 | /* Send a "simple" extended wmi command -- one with no arguments. | |
1209 | Enabling this command only if GPIO or profiling support is enabled. | |
1210 | This is to suppress warnings on some platforms */ | |
1211 | #if defined(CONFIG_HOST_GPIO_SUPPORT) || defined(CONFIG_TARGET_PROFILE_SUPPORT) | |
1f4c34bd | 1212 | static int |
30295c89 VM |
1213 | wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid) |
1214 | { | |
1215 | void *osbuf; | |
1216 | ||
1217 | osbuf = A_NETBUF_ALLOC(0); | |
1218 | if (osbuf == NULL) { | |
1219 | return A_NO_MEMORY; | |
1220 | } | |
1221 | ||
1222 | return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); | |
1223 | } | |
1224 | #endif | |
1225 | ||
1f4c34bd | 1226 | static int |
ab3655da | 1227 | wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1228 | { |
1229 | WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap; | |
1230 | ||
1231 | if (len < sizeof(WMI_READY_EVENT)) { | |
1232 | return A_EINVAL; | |
1233 | } | |
1234 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1071a134 | 1235 | wmip->wmi_ready = true; |
30295c89 VM |
1236 | A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability, |
1237 | ev->sw_version, ev->abi_version); | |
1238 | ||
4f69cef0 | 1239 | return 0; |
30295c89 VM |
1240 | } |
1241 | ||
1242 | #define LE_READ_4(p) \ | |
e1ce2a3a | 1243 | ((u32) \ |
ab3655da JP |
1244 | ((((u8 *)(p))[0] ) | (((u8 *)(p))[1] << 8) | \ |
1245 | (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24))) | |
30295c89 VM |
1246 | |
1247 | static int __inline | |
ab3655da | 1248 | iswmmoui(const u8 *frm) |
30295c89 VM |
1249 | { |
1250 | return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); | |
1251 | } | |
1252 | ||
1253 | static int __inline | |
ab3655da | 1254 | iswmmparam(const u8 *frm) |
30295c89 VM |
1255 | { |
1256 | return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; | |
1257 | } | |
1258 | ||
1259 | ||
1f4c34bd | 1260 | static int |
ab3655da | 1261 | wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1262 | { |
1263 | WMI_CONNECT_EVENT *ev; | |
ab3655da | 1264 | u8 *pie,*peie; |
30295c89 VM |
1265 | |
1266 | if (len < sizeof(WMI_CONNECT_EVENT)) | |
1267 | { | |
1268 | return A_EINVAL; | |
1269 | } | |
1270 | ev = (WMI_CONNECT_EVENT *)datap; | |
1271 | ||
1272 | A_DPRINTF(DBG_WMI, | |
1273 | (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", | |
1274 | DBGARG, ev->channel, | |
1275 | ev->bssid[0], ev->bssid[1], ev->bssid[2], | |
1276 | ev->bssid[3], ev->bssid[4], ev->bssid[5])); | |
1277 | ||
05209262 | 1278 | memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN); |
30295c89 VM |
1279 | |
1280 | /* initialize pointer to start of assoc rsp IEs */ | |
1281 | pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + | |
4853ac05 JP |
1282 | sizeof(u16) + /* capinfo*/ |
1283 | sizeof(u16) + /* status Code */ | |
1284 | sizeof(u16) ; /* associd */ | |
30295c89 VM |
1285 | |
1286 | /* initialize pointer to end of assoc rsp IEs */ | |
1287 | peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen; | |
1288 | ||
1289 | while (pie < peie) | |
1290 | { | |
1291 | switch (*pie) | |
1292 | { | |
1293 | case IEEE80211_ELEMID_VENDOR: | |
1294 | if (iswmmoui(pie)) | |
1295 | { | |
1296 | if(iswmmparam (pie)) | |
1297 | { | |
1071a134 | 1298 | wmip->wmi_is_wmm_enabled = true; |
30295c89 VM |
1299 | } |
1300 | } | |
1301 | break; | |
1302 | } | |
1303 | ||
1304 | if (wmip->wmi_is_wmm_enabled) | |
1305 | { | |
1306 | break; | |
1307 | } | |
1308 | pie += pie[1] + 2; | |
1309 | } | |
1310 | ||
1311 | A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid, | |
1312 | ev->listenInterval, ev->beaconInterval, | |
1313 | (NETWORK_TYPE) ev->networkType, ev->beaconIeLen, | |
1314 | ev->assocReqLen, ev->assocRespLen, | |
1315 | ev->assocInfo); | |
1316 | ||
4f69cef0 | 1317 | return 0; |
30295c89 VM |
1318 | } |
1319 | ||
1f4c34bd | 1320 | static int |
ab3655da | 1321 | wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1322 | { |
1323 | WMI_REG_DOMAIN_EVENT *ev; | |
1324 | ||
1325 | if (len < sizeof(*ev)) { | |
1326 | return A_EINVAL; | |
1327 | } | |
1328 | ev = (WMI_REG_DOMAIN_EVENT *)datap; | |
1329 | ||
1330 | A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain); | |
1331 | ||
4f69cef0 | 1332 | return 0; |
30295c89 VM |
1333 | } |
1334 | ||
1f4c34bd | 1335 | static int |
ab3655da | 1336 | wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1337 | { |
1338 | WMI_NEIGHBOR_REPORT_EVENT *ev; | |
1339 | int numAps; | |
1340 | ||
1341 | if (len < sizeof(*ev)) { | |
1342 | return A_EINVAL; | |
1343 | } | |
1344 | ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap; | |
1345 | numAps = ev->numberOfAps; | |
1346 | ||
1347 | if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) { | |
1348 | return A_EINVAL; | |
1349 | } | |
1350 | ||
1351 | A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor); | |
1352 | ||
4f69cef0 | 1353 | return 0; |
30295c89 VM |
1354 | } |
1355 | ||
1f4c34bd | 1356 | static int |
ab3655da | 1357 | wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1358 | { |
1359 | WMI_DISCONNECT_EVENT *ev; | |
1360 | wmip->wmi_traffic_class = 100; | |
1361 | ||
1362 | if (len < sizeof(WMI_DISCONNECT_EVENT)) { | |
1363 | return A_EINVAL; | |
1364 | } | |
1365 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1366 | ||
1367 | ev = (WMI_DISCONNECT_EVENT *)datap; | |
1368 | ||
1369 | A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid)); | |
1370 | ||
1071a134 | 1371 | wmip->wmi_is_wmm_enabled = false; |
30295c89 VM |
1372 | wmip->wmi_pair_crypto_type = NONE_CRYPT; |
1373 | wmip->wmi_grp_crypto_type = NONE_CRYPT; | |
1374 | ||
1375 | A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid, | |
1376 | ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus); | |
1377 | ||
4f69cef0 | 1378 | return 0; |
30295c89 VM |
1379 | } |
1380 | ||
1f4c34bd | 1381 | static int |
ab3655da | 1382 | wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1383 | { |
1384 | WMI_PEER_NODE_EVENT *ev; | |
1385 | ||
1386 | if (len < sizeof(WMI_PEER_NODE_EVENT)) { | |
1387 | return A_EINVAL; | |
1388 | } | |
1389 | ev = (WMI_PEER_NODE_EVENT *)datap; | |
1390 | if (ev->eventCode == PEER_NODE_JOIN_EVENT) { | |
1391 | A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG)); | |
1392 | } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) { | |
1393 | A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG)); | |
1394 | } | |
1395 | ||
1396 | A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr); | |
1397 | ||
4f69cef0 | 1398 | return 0; |
30295c89 VM |
1399 | } |
1400 | ||
1f4c34bd | 1401 | static int |
ab3655da | 1402 | wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1403 | { |
1404 | WMI_TKIP_MICERR_EVENT *ev; | |
1405 | ||
1406 | if (len < sizeof(*ev)) { | |
1407 | return A_EINVAL; | |
1408 | } | |
1409 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1410 | ||
1411 | ev = (WMI_TKIP_MICERR_EVENT *)datap; | |
1412 | A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast); | |
1413 | ||
4f69cef0 | 1414 | return 0; |
30295c89 VM |
1415 | } |
1416 | ||
1f4c34bd | 1417 | static int |
ab3655da | 1418 | wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1419 | { |
1420 | bss_t *bss = NULL; | |
1421 | WMI_BSS_INFO_HDR *bih; | |
ab3655da | 1422 | u8 *buf; |
e1ce2a3a | 1423 | u32 nodeCachingAllowed = 1; |
d8cb316f LR |
1424 | u8 cached_ssid_len = 0; |
1425 | u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0}; | |
ab3655da | 1426 | u8 beacon_ssid_len = 0; |
30295c89 VM |
1427 | |
1428 | if (len <= sizeof(WMI_BSS_INFO_HDR)) { | |
1429 | return A_EINVAL; | |
1430 | } | |
1431 | ||
1432 | bih = (WMI_BSS_INFO_HDR *)datap; | |
1433 | bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); | |
1434 | ||
1435 | if (bih->rssi > 0) { | |
1436 | if (NULL == bss) | |
4f69cef0 | 1437 | return 0; //no node found in the table, just drop the node with incorrect RSSI |
30295c89 VM |
1438 | else |
1439 | bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX | |
1440 | } | |
1441 | ||
1442 | A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len); | |
1443 | /* What is driver config for wlan node caching? */ | |
1444 | if(ar6000_get_driver_cfg(wmip->wmi_devt, | |
1445 | AR6000_DRIVER_CFG_GET_WLANNODECACHING, | |
4f69cef0 | 1446 | &nodeCachingAllowed) != 0) { |
30295c89 VM |
1447 | wmi_node_return(wmip, bss); |
1448 | return A_EINVAL; | |
1449 | } | |
1450 | ||
1451 | if(!nodeCachingAllowed) { | |
1452 | wmi_node_return(wmip, bss); | |
4f69cef0 | 1453 | return 0; |
30295c89 VM |
1454 | } |
1455 | ||
1456 | buf = datap + sizeof(WMI_BSS_INFO_HDR); | |
1457 | len -= sizeof(WMI_BSS_INFO_HDR); | |
1458 | ||
fa1ae16c AS |
1459 | A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, " |
1460 | "bssid \"%pM\"\n", DBGARG, bih->channel, | |
97d23545 | 1461 | (unsigned char) bih->rssi, bih->bssid)); |
30295c89 VM |
1462 | |
1463 | if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) { | |
1464 | wmi_node_return(wmip, bss); | |
4f69cef0 | 1465 | return 0; |
30295c89 VM |
1466 | } |
1467 | ||
1468 | if (bss != NULL) { | |
1469 | /* | |
1470 | * Free up the node. Not the most efficient process given | |
1471 | * we are about to allocate a new node but it is simple and should be | |
1472 | * adequate. | |
1473 | */ | |
1474 | ||
1475 | /* In case of hidden AP, beacon will not have ssid, | |
1476 | * but a directed probe response will have it, | |
1477 | * so cache the probe-resp-ssid if already present. */ | |
1071a134 | 1478 | if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType)) |
30295c89 | 1479 | { |
d8cb316f | 1480 | u8 *ie_ssid; |
30295c89 VM |
1481 | |
1482 | ie_ssid = bss->ni_cie.ie_ssid; | |
1483 | if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0)) | |
1484 | { | |
1485 | cached_ssid_len = ie_ssid[1]; | |
1486 | memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len); | |
1487 | } | |
1488 | } | |
1489 | ||
1490 | /* | |
1491 | * Use the current average rssi of associated AP base on assumpiton | |
1492 | * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically | |
1493 | * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...) | |
1494 | * The average value of RSSI give end-user better feeling for instance value of scan result | |
1495 | * It also sync up RSSI info in GUI between scan result and RSSI signal icon | |
1496 | */ | |
2a4724a7 | 1497 | if (IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) { |
30295c89 VM |
1498 | bih->rssi = bss->ni_rssi; |
1499 | bih->snr = bss->ni_snr; | |
1500 | } | |
1501 | ||
1502 | wlan_node_reclaim(&wmip->wmi_scan_table, bss); | |
1503 | } | |
1504 | ||
1505 | /* beacon/probe response frame format | |
1506 | * [8] time stamp | |
1507 | * [2] beacon interval | |
1508 | * [2] capability information | |
1509 | * [tlv] ssid */ | |
1510 | beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; | |
1511 | ||
1512 | /* If ssid is cached for this hidden AP, then change buffer len accordingly. */ | |
1071a134 | 1513 | if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && |
30295c89 VM |
1514 | (0 != cached_ssid_len) && |
1515 | (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) | |
1516 | { | |
1517 | len += (cached_ssid_len - beacon_ssid_len); | |
1518 | } | |
1519 | ||
1520 | bss = wlan_node_alloc(&wmip->wmi_scan_table, len); | |
1521 | if (bss == NULL) { | |
1522 | return A_NO_MEMORY; | |
1523 | } | |
1524 | ||
1525 | bss->ni_snr = bih->snr; | |
1526 | bss->ni_rssi = bih->rssi; | |
1527 | A_ASSERT(bss->ni_buf != NULL); | |
1528 | ||
1529 | /* In case of hidden AP, beacon will not have ssid, | |
1530 | * but a directed probe response will have it, | |
1531 | * so place the cached-ssid(probe-resp) in the bssinfo. */ | |
1071a134 | 1532 | if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && |
30295c89 VM |
1533 | (0 != cached_ssid_len) && |
1534 | (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) | |
1535 | { | |
ab3655da | 1536 | u8 *ni_buf = bss->ni_buf; |
30295c89 VM |
1537 | int buf_len = len; |
1538 | ||
1539 | /* copy the first 14 bytes such as | |
1540 | * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */ | |
05209262 | 1541 | memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1); |
30295c89 VM |
1542 | |
1543 | ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; | |
1544 | ni_buf += (SSID_IE_LEN_INDEX + 1); | |
1545 | ||
1546 | buf += (SSID_IE_LEN_INDEX + 1); | |
1547 | buf_len -= (SSID_IE_LEN_INDEX + 1); | |
1548 | ||
1549 | /* copy the cached ssid */ | |
05209262 | 1550 | memcpy(ni_buf, cached_ssid_buf, cached_ssid_len); |
30295c89 VM |
1551 | ni_buf += cached_ssid_len; |
1552 | ||
1553 | buf += beacon_ssid_len; | |
1554 | buf_len -= beacon_ssid_len; | |
1555 | ||
1556 | if (cached_ssid_len > beacon_ssid_len) | |
1557 | buf_len -= (cached_ssid_len - beacon_ssid_len); | |
1558 | ||
1559 | /* now copy the rest of bytes */ | |
05209262 | 1560 | memcpy(ni_buf, buf, buf_len); |
30295c89 VM |
1561 | } |
1562 | else | |
05209262 | 1563 | memcpy(bss->ni_buf, buf, len); |
30295c89 VM |
1564 | |
1565 | bss->ni_framelen = len; | |
4f69cef0 | 1566 | if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) { |
30295c89 VM |
1567 | wlan_node_free(bss); |
1568 | return A_EINVAL; | |
1569 | } | |
1570 | ||
1571 | /* | |
1572 | * Update the frequency in ie_chan, overwriting of channel number | |
1573 | * which is done in wlan_parse_beacon | |
1574 | */ | |
1575 | bss->ni_cie.ie_chan = bih->channel; | |
1576 | wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); | |
1577 | ||
4f69cef0 | 1578 | return 0; |
30295c89 VM |
1579 | } |
1580 | ||
1f4c34bd | 1581 | static int |
ab3655da | 1582 | wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1583 | { |
1584 | bss_t *bss; | |
1585 | WMI_OPT_RX_INFO_HDR *bih; | |
ab3655da | 1586 | u8 *buf; |
30295c89 VM |
1587 | |
1588 | if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) { | |
1589 | return A_EINVAL; | |
1590 | } | |
1591 | ||
1592 | bih = (WMI_OPT_RX_INFO_HDR *)datap; | |
1593 | buf = datap + sizeof(WMI_OPT_RX_INFO_HDR); | |
1594 | len -= sizeof(WMI_OPT_RX_INFO_HDR); | |
1595 | ||
1596 | A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG, | |
1597 | bih->bssid[4], bih->bssid[5])); | |
1598 | ||
1599 | bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); | |
1600 | if (bss != NULL) { | |
1601 | /* | |
1602 | * Free up the node. Not the most efficient process given | |
1603 | * we are about to allocate a new node but it is simple and should be | |
1604 | * adequate. | |
1605 | */ | |
1606 | wlan_node_reclaim(&wmip->wmi_scan_table, bss); | |
1607 | } | |
1608 | ||
1609 | bss = wlan_node_alloc(&wmip->wmi_scan_table, len); | |
1610 | if (bss == NULL) { | |
1611 | return A_NO_MEMORY; | |
1612 | } | |
1613 | ||
1614 | bss->ni_snr = bih->snr; | |
1615 | bss->ni_cie.ie_chan = bih->channel; | |
1616 | A_ASSERT(bss->ni_buf != NULL); | |
05209262 | 1617 | memcpy(bss->ni_buf, buf, len); |
30295c89 VM |
1618 | wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); |
1619 | ||
4f69cef0 | 1620 | return 0; |
30295c89 VM |
1621 | } |
1622 | ||
1623 | /* This event indicates inactivity timeout of a fatpipe(pstream) | |
1624 | * at the target | |
1625 | */ | |
1f4c34bd | 1626 | static int |
ab3655da | 1627 | wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1628 | { |
1629 | WMI_PSTREAM_TIMEOUT_EVENT *ev; | |
1630 | ||
1631 | if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) { | |
1632 | return A_EINVAL; | |
1633 | } | |
1634 | ||
1635 | A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG)); | |
1636 | ||
1637 | ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap; | |
1638 | ||
1639 | /* When the pstream (fat pipe == AC) timesout, it means there were no | |
1640 | * thinStreams within this pstream & it got implicitly created due to | |
1641 | * data flow on this AC. We start the inactivity timer only for | |
1642 | * implicitly created pstream. Just reset the host state. | |
1643 | */ | |
1644 | /* Set the activeTsids for this AC to 0 */ | |
1645 | LOCK_WMI(wmip); | |
1646 | wmip->wmi_streamExistsForAC[ev->trafficClass]=0; | |
1647 | wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass); | |
1648 | UNLOCK_WMI(wmip); | |
1649 | ||
1650 | /*Indicate inactivity to driver layer for this fatpipe (pstream)*/ | |
1651 | A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass); | |
1652 | ||
4f69cef0 | 1653 | return 0; |
30295c89 VM |
1654 | } |
1655 | ||
1f4c34bd | 1656 | static int |
ab3655da | 1657 | wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1658 | { |
1659 | WMI_BIT_RATE_REPLY *reply; | |
f68057e6 | 1660 | s32 rate; |
e1ce2a3a | 1661 | u32 sgi,index; |
30295c89 VM |
1662 | /* 54149: |
1663 | * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY. | |
1664 | * since there is difference in the length and to avoid returning | |
1665 | * error value. | |
1666 | */ | |
1667 | if (len < sizeof(WMI_BIT_RATE_REPLY)) { | |
1668 | return A_EINVAL; | |
1669 | } | |
1670 | reply = (WMI_BIT_RATE_REPLY *)datap; | |
1671 | A_DPRINTF(DBG_WMI, | |
1672 | (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex)); | |
1673 | ||
f2ab1275 | 1674 | if (reply->rateIndex == (s8) RATE_AUTO) { |
30295c89 VM |
1675 | rate = RATE_AUTO; |
1676 | } else { | |
1677 | // the SGI state is stored as the MSb of the rateIndex | |
1678 | index = reply->rateIndex & 0x7f; | |
1679 | sgi = (reply->rateIndex & 0x80)? 1:0; | |
1680 | rate = wmi_rateTable[index][sgi]; | |
1681 | } | |
1682 | ||
1683 | A_WMI_BITRATE_RX(wmip->wmi_devt, rate); | |
4f69cef0 | 1684 | return 0; |
30295c89 VM |
1685 | } |
1686 | ||
1f4c34bd | 1687 | static int |
ab3655da | 1688 | wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1689 | { |
1690 | WMI_FIX_RATES_REPLY *reply; | |
1691 | ||
1692 | if (len < sizeof(WMI_FIX_RATES_REPLY)) { | |
1693 | return A_EINVAL; | |
1694 | } | |
1695 | reply = (WMI_FIX_RATES_REPLY *)datap; | |
1696 | A_DPRINTF(DBG_WMI, | |
1697 | (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask)); | |
1698 | ||
1699 | A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask); | |
1700 | ||
4f69cef0 | 1701 | return 0; |
30295c89 VM |
1702 | } |
1703 | ||
1f4c34bd | 1704 | static int |
ab3655da | 1705 | wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1706 | { |
1707 | WMI_CHANNEL_LIST_REPLY *reply; | |
1708 | ||
1709 | if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) { | |
1710 | return A_EINVAL; | |
1711 | } | |
1712 | reply = (WMI_CHANNEL_LIST_REPLY *)datap; | |
1713 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1714 | ||
1715 | A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels, | |
1716 | reply->channelList); | |
1717 | ||
4f69cef0 | 1718 | return 0; |
30295c89 VM |
1719 | } |
1720 | ||
1f4c34bd | 1721 | static int |
ab3655da | 1722 | wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1723 | { |
1724 | WMI_TX_PWR_REPLY *reply; | |
1725 | ||
1726 | if (len < sizeof(*reply)) { | |
1727 | return A_EINVAL; | |
1728 | } | |
1729 | reply = (WMI_TX_PWR_REPLY *)datap; | |
1730 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1731 | ||
1732 | A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM); | |
1733 | ||
4f69cef0 | 1734 | return 0; |
30295c89 | 1735 | } |
1f4c34bd | 1736 | static int |
ab3655da | 1737 | wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1738 | { |
1739 | WMI_GET_KEEPALIVE_CMD *reply; | |
1740 | ||
1741 | if (len < sizeof(*reply)) { | |
1742 | return A_EINVAL; | |
1743 | } | |
1744 | reply = (WMI_GET_KEEPALIVE_CMD *)datap; | |
1745 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1746 | ||
1747 | A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured); | |
1748 | ||
4f69cef0 | 1749 | return 0; |
30295c89 VM |
1750 | } |
1751 | ||
1752 | ||
1f4c34bd | 1753 | static int |
ab3655da | 1754 | wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1755 | { |
1756 | WMIX_DSETOPENREQ_EVENT *dsetopenreq; | |
1757 | ||
1758 | if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) { | |
1759 | return A_EINVAL; | |
1760 | } | |
1761 | dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap; | |
1762 | A_DPRINTF(DBG_WMI, | |
1763 | (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id)); | |
1764 | A_WMI_DSET_OPEN_REQ(wmip->wmi_devt, | |
1765 | dsetopenreq->dset_id, | |
1766 | dsetopenreq->targ_dset_handle, | |
1767 | dsetopenreq->targ_reply_fn, | |
1768 | dsetopenreq->targ_reply_arg); | |
1769 | ||
4f69cef0 | 1770 | return 0; |
30295c89 VM |
1771 | } |
1772 | ||
1773 | #ifdef CONFIG_HOST_DSET_SUPPORT | |
1f4c34bd | 1774 | static int |
ab3655da | 1775 | wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1776 | { |
1777 | WMIX_DSETCLOSE_EVENT *dsetclose; | |
1778 | ||
1779 | if (len < sizeof(WMIX_DSETCLOSE_EVENT)) { | |
1780 | return A_EINVAL; | |
1781 | } | |
1782 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1783 | ||
1784 | dsetclose = (WMIX_DSETCLOSE_EVENT *)datap; | |
1785 | A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie); | |
1786 | ||
4f69cef0 | 1787 | return 0; |
30295c89 VM |
1788 | } |
1789 | ||
1f4c34bd | 1790 | static int |
ab3655da | 1791 | wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1792 | { |
1793 | WMIX_DSETDATAREQ_EVENT *dsetdatareq; | |
1794 | ||
1795 | if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) { | |
1796 | return A_EINVAL; | |
1797 | } | |
1798 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1799 | ||
1800 | dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap; | |
1801 | A_WMI_DSET_DATA_REQ(wmip->wmi_devt, | |
1802 | dsetdatareq->access_cookie, | |
1803 | dsetdatareq->offset, | |
1804 | dsetdatareq->length, | |
1805 | dsetdatareq->targ_buf, | |
1806 | dsetdatareq->targ_reply_fn, | |
1807 | dsetdatareq->targ_reply_arg); | |
1808 | ||
4f69cef0 | 1809 | return 0; |
30295c89 VM |
1810 | } |
1811 | #endif /* CONFIG_HOST_DSET_SUPPORT */ | |
1812 | ||
1f4c34bd | 1813 | static int |
ab3655da | 1814 | wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1815 | { |
1816 | WMI_SCAN_COMPLETE_EVENT *ev; | |
1817 | ||
1818 | ev = (WMI_SCAN_COMPLETE_EVENT *)datap; | |
4f69cef0 | 1819 | if ((int)ev->status == 0) { |
30295c89 VM |
1820 | wlan_refresh_inactive_nodes(&wmip->wmi_scan_table); |
1821 | } | |
1f4c34bd | 1822 | A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status); |
1071a134 | 1823 | is_probe_ssid = false; |
30295c89 | 1824 | |
4f69cef0 | 1825 | return 0; |
30295c89 VM |
1826 | } |
1827 | ||
1828 | /* | |
1829 | * Target is reporting a programming error. This is for | |
1830 | * developer aid only. Target only checks a few common violations | |
1831 | * and it is responsibility of host to do all error checking. | |
1832 | * Behavior of target after wmi error event is undefined. | |
1833 | * A reset is recommended. | |
1834 | */ | |
1f4c34bd | 1835 | static int |
ab3655da | 1836 | wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1837 | { |
1838 | WMI_CMD_ERROR_EVENT *ev; | |
1839 | ||
1840 | ev = (WMI_CMD_ERROR_EVENT *)datap; | |
1841 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId)); | |
1842 | switch (ev->errorCode) { | |
1843 | case (INVALID_PARAM): | |
1844 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n")); | |
1845 | break; | |
1846 | case (ILLEGAL_STATE): | |
1847 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n")); | |
1848 | break; | |
1849 | case (INTERNAL_ERROR): | |
1850 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n")); | |
1851 | break; | |
1852 | } | |
1853 | ||
4f69cef0 | 1854 | return 0; |
30295c89 VM |
1855 | } |
1856 | ||
1857 | ||
1f4c34bd | 1858 | static int |
ab3655da | 1859 | wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1860 | { |
1861 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1862 | ||
1863 | A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len); | |
1864 | ||
4f69cef0 | 1865 | return 0; |
30295c89 VM |
1866 | } |
1867 | ||
1f4c34bd | 1868 | static int |
ab3655da | 1869 | wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1870 | { |
1871 | WMI_RSSI_THRESHOLD_EVENT *reply; | |
1872 | WMI_RSSI_THRESHOLD_VAL newThreshold; | |
1873 | WMI_RSSI_THRESHOLD_PARAMS_CMD cmd; | |
1874 | SQ_THRESHOLD_PARAMS *sq_thresh = | |
1875 | &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; | |
ab3655da | 1876 | u8 upper_rssi_threshold, lower_rssi_threshold; |
cb1e3709 | 1877 | s16 rssi; |
30295c89 VM |
1878 | |
1879 | if (len < sizeof(*reply)) { | |
1880 | return A_EINVAL; | |
1881 | } | |
1882 | reply = (WMI_RSSI_THRESHOLD_EVENT *)datap; | |
1883 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1884 | newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range; | |
1885 | rssi = reply->rssi; | |
1886 | ||
1887 | /* | |
1888 | * Identify the threshold breached and communicate that to the app. After | |
1889 | * that install a new set of thresholds based on the signal quality | |
1890 | * reported by the target | |
1891 | */ | |
1892 | if (newThreshold) { | |
1893 | /* Upper threshold breached */ | |
1894 | if (rssi < sq_thresh->upper_threshold[0]) { | |
1895 | A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: " | |
1896 | " %d\n", DBGARG, rssi)); | |
1897 | } else if ((rssi < sq_thresh->upper_threshold[1]) && | |
1898 | (rssi >= sq_thresh->upper_threshold[0])) | |
1899 | { | |
1900 | newThreshold = WMI_RSSI_THRESHOLD1_ABOVE; | |
1901 | } else if ((rssi < sq_thresh->upper_threshold[2]) && | |
1902 | (rssi >= sq_thresh->upper_threshold[1])) | |
1903 | { | |
1904 | newThreshold = WMI_RSSI_THRESHOLD2_ABOVE; | |
1905 | } else if ((rssi < sq_thresh->upper_threshold[3]) && | |
1906 | (rssi >= sq_thresh->upper_threshold[2])) | |
1907 | { | |
1908 | newThreshold = WMI_RSSI_THRESHOLD3_ABOVE; | |
1909 | } else if ((rssi < sq_thresh->upper_threshold[4]) && | |
1910 | (rssi >= sq_thresh->upper_threshold[3])) | |
1911 | { | |
1912 | newThreshold = WMI_RSSI_THRESHOLD4_ABOVE; | |
1913 | } else if ((rssi < sq_thresh->upper_threshold[5]) && | |
1914 | (rssi >= sq_thresh->upper_threshold[4])) | |
1915 | { | |
1916 | newThreshold = WMI_RSSI_THRESHOLD5_ABOVE; | |
1917 | } else if (rssi >= sq_thresh->upper_threshold[5]) { | |
1918 | newThreshold = WMI_RSSI_THRESHOLD6_ABOVE; | |
1919 | } | |
1920 | } else { | |
1921 | /* Lower threshold breached */ | |
1922 | if (rssi > sq_thresh->lower_threshold[0]) { | |
1923 | A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: " | |
1924 | "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0])); | |
1925 | } else if ((rssi > sq_thresh->lower_threshold[1]) && | |
1926 | (rssi <= sq_thresh->lower_threshold[0])) | |
1927 | { | |
1928 | newThreshold = WMI_RSSI_THRESHOLD6_BELOW; | |
1929 | } else if ((rssi > sq_thresh->lower_threshold[2]) && | |
1930 | (rssi <= sq_thresh->lower_threshold[1])) | |
1931 | { | |
1932 | newThreshold = WMI_RSSI_THRESHOLD5_BELOW; | |
1933 | } else if ((rssi > sq_thresh->lower_threshold[3]) && | |
1934 | (rssi <= sq_thresh->lower_threshold[2])) | |
1935 | { | |
1936 | newThreshold = WMI_RSSI_THRESHOLD4_BELOW; | |
1937 | } else if ((rssi > sq_thresh->lower_threshold[4]) && | |
1938 | (rssi <= sq_thresh->lower_threshold[3])) | |
1939 | { | |
1940 | newThreshold = WMI_RSSI_THRESHOLD3_BELOW; | |
1941 | } else if ((rssi > sq_thresh->lower_threshold[5]) && | |
1942 | (rssi <= sq_thresh->lower_threshold[4])) | |
1943 | { | |
1944 | newThreshold = WMI_RSSI_THRESHOLD2_BELOW; | |
1945 | } else if (rssi <= sq_thresh->lower_threshold[5]) { | |
1946 | newThreshold = WMI_RSSI_THRESHOLD1_BELOW; | |
1947 | } | |
1948 | } | |
1949 | /* Calculate and install the next set of thresholds */ | |
1950 | lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh, | |
1951 | sq_thresh->lower_threshold_valid_count); | |
1952 | upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh, | |
1953 | sq_thresh->upper_threshold_valid_count); | |
1954 | /* Issue a wmi command to install the thresholds */ | |
1955 | cmd.thresholdAbove1_Val = upper_rssi_threshold; | |
1956 | cmd.thresholdBelow1_Val = lower_rssi_threshold; | |
1957 | cmd.weight = sq_thresh->weight; | |
1958 | cmd.pollTime = sq_thresh->polling_interval; | |
1959 | ||
1960 | rssi_event_value = rssi; | |
1961 | ||
4f69cef0 | 1962 | if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) { |
30295c89 VM |
1963 | A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n", |
1964 | DBGARG)); | |
1965 | } | |
1966 | ||
1967 | A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi); | |
1968 | ||
4f69cef0 | 1969 | return 0; |
30295c89 VM |
1970 | } |
1971 | ||
1972 | ||
1f4c34bd | 1973 | static int |
ab3655da | 1974 | wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1975 | { |
1976 | WMI_TARGET_ERROR_REPORT_EVENT *reply; | |
1977 | ||
1978 | if (len < sizeof(*reply)) { | |
1979 | return A_EINVAL; | |
1980 | } | |
1981 | reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap; | |
1982 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
1983 | ||
1984 | A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal); | |
1985 | ||
4f69cef0 | 1986 | return 0; |
30295c89 VM |
1987 | } |
1988 | ||
1f4c34bd | 1989 | static int |
ab3655da | 1990 | wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
1991 | { |
1992 | WMI_CAC_EVENT *reply; | |
1993 | WMM_TSPEC_IE *tspec_ie; | |
4853ac05 | 1994 | u16 activeTsids; |
30295c89 VM |
1995 | |
1996 | if (len < sizeof(*reply)) { | |
1997 | return A_EINVAL; | |
1998 | } | |
1999 | reply = (WMI_CAC_EVENT *)datap; | |
2000 | ||
2001 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2002 | ||
2003 | if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && | |
2004 | (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) { | |
2005 | tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); | |
2006 | ||
2007 | wmi_delete_pstream_cmd(wmip, reply->ac, | |
2008 | (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); | |
2009 | } | |
2010 | else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { | |
ab3655da | 2011 | u8 i; |
30295c89 VM |
2012 | |
2013 | /* following assumes that there is only one outstanding ADDTS request | |
2014 | when this event is received */ | |
2015 | LOCK_WMI(wmip); | |
2016 | activeTsids = wmip->wmi_streamExistsForAC[reply->ac]; | |
2017 | UNLOCK_WMI(wmip); | |
2018 | ||
2019 | for (i = 0; i < sizeof(activeTsids) * 8; i++) { | |
2020 | if ((activeTsids >> i) & 1) { | |
2021 | break; | |
2022 | } | |
2023 | } | |
2024 | if (i < (sizeof(activeTsids) * 8)) { | |
2025 | wmi_delete_pstream_cmd(wmip, reply->ac, i); | |
2026 | } | |
2027 | } | |
2028 | /* | |
2029 | * Ev#72990: Clear active tsids and Add missing handling | |
2030 | * for delete qos stream from AP | |
2031 | */ | |
2032 | else if (reply->cac_indication == CAC_INDICATION_DELETE) { | |
ab3655da | 2033 | u8 tsid = 0; |
30295c89 VM |
2034 | |
2035 | tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); | |
2036 | tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); | |
2037 | LOCK_WMI(wmip); | |
2038 | wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid); | |
2039 | activeTsids = wmip->wmi_streamExistsForAC[reply->ac]; | |
2040 | UNLOCK_WMI(wmip); | |
2041 | ||
2042 | ||
2043 | /* Indicate stream inactivity to driver layer only if all tsids | |
2044 | * within this AC are deleted. | |
2045 | */ | |
2046 | if (!activeTsids) { | |
2047 | A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, reply->ac); | |
2048 | wmip->wmi_fatPipeExists &= ~(1 << reply->ac); | |
2049 | } | |
2050 | } | |
2051 | ||
2052 | A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac, | |
2053 | reply->cac_indication, reply->statusCode, | |
2054 | reply->tspecSuggestion); | |
2055 | ||
4f69cef0 | 2056 | return 0; |
30295c89 VM |
2057 | } |
2058 | ||
1f4c34bd | 2059 | static int |
ab3655da | 2060 | wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2061 | { |
2062 | WMI_CHANNEL_CHANGE_EVENT *reply; | |
2063 | ||
2064 | if (len < sizeof(*reply)) { | |
2065 | return A_EINVAL; | |
2066 | } | |
2067 | reply = (WMI_CHANNEL_CHANGE_EVENT *)datap; | |
2068 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2069 | ||
2070 | A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel, | |
2071 | reply->newChannel); | |
2072 | ||
4f69cef0 | 2073 | return 0; |
30295c89 VM |
2074 | } |
2075 | ||
1f4c34bd | 2076 | static int |
ab3655da | 2077 | wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2078 | { |
2079 | WMIX_HB_CHALLENGE_RESP_EVENT *reply; | |
2080 | ||
2081 | if (len < sizeof(*reply)) { | |
2082 | return A_EINVAL; | |
2083 | } | |
2084 | reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap; | |
2085 | A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG)); | |
2086 | ||
2087 | A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source); | |
2088 | ||
4f69cef0 | 2089 | return 0; |
30295c89 VM |
2090 | } |
2091 | ||
1f4c34bd | 2092 | static int |
ab3655da | 2093 | wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2094 | { |
2095 | WMI_TARGET_ROAM_TBL *reply; | |
2096 | ||
2097 | if (len < sizeof(*reply)) { | |
2098 | return A_EINVAL; | |
2099 | } | |
2100 | reply = (WMI_TARGET_ROAM_TBL *)datap; | |
2101 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2102 | ||
2103 | A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply); | |
2104 | ||
4f69cef0 | 2105 | return 0; |
30295c89 VM |
2106 | } |
2107 | ||
1f4c34bd | 2108 | static int |
ab3655da | 2109 | wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2110 | { |
2111 | WMI_TARGET_ROAM_DATA *reply; | |
2112 | ||
2113 | if (len < sizeof(*reply)) { | |
2114 | return A_EINVAL; | |
2115 | } | |
2116 | reply = (WMI_TARGET_ROAM_DATA *)datap; | |
2117 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2118 | ||
2119 | A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply); | |
2120 | ||
4f69cef0 | 2121 | return 0; |
30295c89 VM |
2122 | } |
2123 | ||
1f4c34bd | 2124 | static int |
ab3655da | 2125 | wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2126 | { |
2127 | if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) { | |
2128 | return A_EINVAL; | |
2129 | } | |
2130 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2131 | ||
2132 | A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt); | |
2133 | ||
4f69cef0 | 2134 | return 0; |
30295c89 VM |
2135 | } |
2136 | ||
1f4c34bd | 2137 | static int |
ab3655da | 2138 | wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2139 | { |
2140 | WMI_SNR_THRESHOLD_EVENT *reply; | |
2141 | SQ_THRESHOLD_PARAMS *sq_thresh = | |
2142 | &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; | |
2143 | WMI_SNR_THRESHOLD_VAL newThreshold; | |
2144 | WMI_SNR_THRESHOLD_PARAMS_CMD cmd; | |
ab3655da | 2145 | u8 upper_snr_threshold, lower_snr_threshold; |
cb1e3709 | 2146 | s16 snr; |
30295c89 VM |
2147 | |
2148 | if (len < sizeof(*reply)) { | |
2149 | return A_EINVAL; | |
2150 | } | |
2151 | reply = (WMI_SNR_THRESHOLD_EVENT *)datap; | |
2152 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2153 | ||
2154 | newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range; | |
2155 | snr = reply->snr; | |
2156 | /* | |
2157 | * Identify the threshold breached and communicate that to the app. After | |
2158 | * that install a new set of thresholds based on the signal quality | |
2159 | * reported by the target | |
2160 | */ | |
2161 | if (newThreshold) { | |
2162 | /* Upper threshold breached */ | |
2163 | if (snr < sq_thresh->upper_threshold[0]) { | |
2164 | A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: " | |
2165 | "%d\n", DBGARG, snr)); | |
2166 | } else if ((snr < sq_thresh->upper_threshold[1]) && | |
2167 | (snr >= sq_thresh->upper_threshold[0])) | |
2168 | { | |
2169 | newThreshold = WMI_SNR_THRESHOLD1_ABOVE; | |
2170 | } else if ((snr < sq_thresh->upper_threshold[2]) && | |
2171 | (snr >= sq_thresh->upper_threshold[1])) | |
2172 | { | |
2173 | newThreshold = WMI_SNR_THRESHOLD2_ABOVE; | |
2174 | } else if ((snr < sq_thresh->upper_threshold[3]) && | |
2175 | (snr >= sq_thresh->upper_threshold[2])) | |
2176 | { | |
2177 | newThreshold = WMI_SNR_THRESHOLD3_ABOVE; | |
2178 | } else if (snr >= sq_thresh->upper_threshold[3]) { | |
2179 | newThreshold = WMI_SNR_THRESHOLD4_ABOVE; | |
2180 | } | |
2181 | } else { | |
2182 | /* Lower threshold breached */ | |
2183 | if (snr > sq_thresh->lower_threshold[0]) { | |
2184 | A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: " | |
2185 | "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0])); | |
2186 | } else if ((snr > sq_thresh->lower_threshold[1]) && | |
2187 | (snr <= sq_thresh->lower_threshold[0])) | |
2188 | { | |
2189 | newThreshold = WMI_SNR_THRESHOLD4_BELOW; | |
2190 | } else if ((snr > sq_thresh->lower_threshold[2]) && | |
2191 | (snr <= sq_thresh->lower_threshold[1])) | |
2192 | { | |
2193 | newThreshold = WMI_SNR_THRESHOLD3_BELOW; | |
2194 | } else if ((snr > sq_thresh->lower_threshold[3]) && | |
2195 | (snr <= sq_thresh->lower_threshold[2])) | |
2196 | { | |
2197 | newThreshold = WMI_SNR_THRESHOLD2_BELOW; | |
2198 | } else if (snr <= sq_thresh->lower_threshold[3]) { | |
2199 | newThreshold = WMI_SNR_THRESHOLD1_BELOW; | |
2200 | } | |
2201 | } | |
2202 | ||
2203 | /* Calculate and install the next set of thresholds */ | |
2204 | lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh, | |
2205 | sq_thresh->lower_threshold_valid_count); | |
2206 | upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh, | |
2207 | sq_thresh->upper_threshold_valid_count); | |
2208 | ||
2209 | /* Issue a wmi command to install the thresholds */ | |
2210 | cmd.thresholdAbove1_Val = upper_snr_threshold; | |
2211 | cmd.thresholdBelow1_Val = lower_snr_threshold; | |
2212 | cmd.weight = sq_thresh->weight; | |
2213 | cmd.pollTime = sq_thresh->polling_interval; | |
2214 | ||
2215 | A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n" | |
2216 | ,DBGARG, snr, newThreshold, lower_snr_threshold, | |
2217 | upper_snr_threshold)); | |
2218 | ||
2219 | snr_event_value = snr; | |
2220 | ||
4f69cef0 | 2221 | if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) { |
30295c89 VM |
2222 | A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n", |
2223 | DBGARG)); | |
2224 | } | |
2225 | A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr); | |
2226 | ||
4f69cef0 | 2227 | return 0; |
30295c89 VM |
2228 | } |
2229 | ||
1f4c34bd | 2230 | static int |
ab3655da | 2231 | wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2232 | { |
2233 | WMI_LQ_THRESHOLD_EVENT *reply; | |
2234 | ||
2235 | if (len < sizeof(*reply)) { | |
2236 | return A_EINVAL; | |
2237 | } | |
2238 | reply = (WMI_LQ_THRESHOLD_EVENT *)datap; | |
2239 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2240 | ||
2241 | A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, | |
2242 | (WMI_LQ_THRESHOLD_VAL) reply->range, | |
2243 | reply->lq); | |
2244 | ||
4f69cef0 | 2245 | return 0; |
30295c89 VM |
2246 | } |
2247 | ||
1f4c34bd | 2248 | static int |
ab3655da | 2249 | wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 | 2250 | { |
4853ac05 | 2251 | u16 ap_info_entry_size; |
30295c89 VM |
2252 | WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap; |
2253 | WMI_AP_INFO_V1 *ap_info_v1; | |
ab3655da | 2254 | u8 i; |
30295c89 VM |
2255 | |
2256 | if (len < sizeof(WMI_APLIST_EVENT)) { | |
2257 | return A_EINVAL; | |
2258 | } | |
2259 | ||
2260 | if (ev->apListVer == APLIST_VER1) { | |
2261 | ap_info_entry_size = sizeof(WMI_AP_INFO_V1); | |
2262 | ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList; | |
2263 | } else { | |
2264 | return A_EINVAL; | |
2265 | } | |
2266 | ||
2267 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP)); | |
2268 | if (len < (int)(sizeof(WMI_APLIST_EVENT) + | |
2269 | (ev->numAP - 1) * ap_info_entry_size)) | |
2270 | { | |
2271 | return A_EINVAL; | |
2272 | } | |
2273 | ||
2274 | /* | |
2275 | * AP List Ver1 Contents | |
2276 | */ | |
2277 | for (i = 0; i < ev->numAP; i++) { | |
2278 | AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\ | |
2279 | "Channel %d\n", i, | |
2280 | ap_info_v1->bssid[0], ap_info_v1->bssid[1], | |
2281 | ap_info_v1->bssid[2], ap_info_v1->bssid[3], | |
2282 | ap_info_v1->bssid[4], ap_info_v1->bssid[5], | |
2283 | ap_info_v1->channel)); | |
2284 | ap_info_v1++; | |
2285 | } | |
4f69cef0 | 2286 | return 0; |
30295c89 VM |
2287 | } |
2288 | ||
1f4c34bd | 2289 | static int |
ab3655da | 2290 | wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 | 2291 | { |
e1ce2a3a | 2292 | u32 dropped; |
30295c89 | 2293 | |
e1ce2a3a | 2294 | dropped = *((u32 *)datap); |
30295c89 VM |
2295 | datap += sizeof(dropped); |
2296 | len -= sizeof(dropped); | |
f2ab1275 | 2297 | A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len); |
4f69cef0 | 2298 | return 0; |
30295c89 VM |
2299 | } |
2300 | ||
2301 | #ifdef CONFIG_HOST_GPIO_SUPPORT | |
1f4c34bd | 2302 | static int |
ab3655da | 2303 | wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2304 | { |
2305 | WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap; | |
2306 | ||
2307 | A_DPRINTF(DBG_WMI, | |
2308 | (DBGFMT "Enter - intrmask=0x%x input=0x%x.\n", DBGARG, | |
2309 | gpio_intr->intr_mask, gpio_intr->input_values)); | |
2310 | ||
2311 | A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values); | |
2312 | ||
4f69cef0 | 2313 | return 0; |
30295c89 VM |
2314 | } |
2315 | ||
1f4c34bd | 2316 | static int |
ab3655da | 2317 | wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2318 | { |
2319 | WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap; | |
2320 | ||
2321 | A_DPRINTF(DBG_WMI, | |
2322 | (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, | |
2323 | gpio_data->reg_id, gpio_data->value)); | |
2324 | ||
2325 | A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value); | |
2326 | ||
4f69cef0 | 2327 | return 0; |
30295c89 VM |
2328 | } |
2329 | ||
1f4c34bd | 2330 | static int |
ab3655da | 2331 | wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
2332 | { |
2333 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
2334 | ||
2335 | A_WMI_GPIO_ACK_RX(); | |
2336 | ||
4f69cef0 | 2337 | return 0; |
30295c89 VM |
2338 | } |
2339 | #endif /* CONFIG_HOST_GPIO_SUPPORT */ | |
2340 | ||
2341 | /* | |
2342 | * Called to send a wmi command. Command specific data is already built | |
2343 | * on osbuf and current osbuf->data points to it. | |
2344 | */ | |
1f4c34bd | 2345 | int |
30295c89 VM |
2346 | wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, |
2347 | WMI_SYNC_FLAG syncflag) | |
2348 | { | |
1f4c34bd | 2349 | int status; |
30295c89 VM |
2350 | #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID)) |
2351 | WMI_CMD_HDR *cHdr; | |
2352 | HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id; | |
2353 | ||
2354 | A_ASSERT(osbuf != NULL); | |
2355 | ||
2356 | if (syncflag >= END_WMIFLAG) { | |
2357 | A_NETBUF_FREE(osbuf); | |
2358 | return A_EINVAL; | |
2359 | } | |
2360 | ||
2361 | if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { | |
2362 | /* | |
2363 | * We want to make sure all data currently queued is transmitted before | |
2364 | * the cmd execution. Establish a new sync point. | |
2365 | */ | |
2366 | wmi_sync_point(wmip); | |
2367 | } | |
2368 | ||
4f69cef0 | 2369 | if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) { |
30295c89 VM |
2370 | A_NETBUF_FREE(osbuf); |
2371 | return A_NO_MEMORY; | |
2372 | } | |
2373 | ||
2374 | cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); | |
4853ac05 | 2375 | cHdr->commandId = (u16) cmdId; |
30295c89 VM |
2376 | cHdr->info1 = 0; // added for virtual interface |
2377 | ||
2378 | /* | |
2379 | * Only for OPT_TX_CMD, use BE endpoint. | |
2380 | */ | |
2381 | if (IS_OPT_TX_CMD(cmdId)) { | |
4f69cef0 | 2382 | if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) { |
30295c89 VM |
2383 | A_NETBUF_FREE(osbuf); |
2384 | return status; | |
2385 | } | |
2386 | eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE); | |
2387 | } | |
2388 | A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid); | |
2389 | ||
2390 | if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { | |
2391 | /* | |
2392 | * We want to make sure all new data queued waits for the command to | |
2393 | * execute. Establish a new sync point. | |
2394 | */ | |
2395 | wmi_sync_point(wmip); | |
2396 | } | |
4f69cef0 | 2397 | return (0); |
30295c89 VM |
2398 | #undef IS_OPT_TX_CMD |
2399 | } | |
2400 | ||
1f4c34bd | 2401 | int |
30295c89 VM |
2402 | wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, |
2403 | WMI_SYNC_FLAG syncflag) | |
2404 | { | |
2405 | WMIX_CMD_HDR *cHdr; | |
2406 | ||
4f69cef0 | 2407 | if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) { |
30295c89 VM |
2408 | A_NETBUF_FREE(osbuf); |
2409 | return A_NO_MEMORY; | |
2410 | } | |
2411 | ||
2412 | cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); | |
e1ce2a3a | 2413 | cHdr->commandId = (u32) cmdId; |
30295c89 VM |
2414 | |
2415 | return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag); | |
2416 | } | |
2417 | ||
1f4c34bd | 2418 | int |
30295c89 VM |
2419 | wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType, |
2420 | DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode, | |
ab3655da JP |
2421 | CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen, |
2422 | CRYPTO_TYPE groupCrypto, u8 groupCryptoLen, | |
d8cb316f | 2423 | int ssidLength, u8 *ssid, |
e1ce2a3a | 2424 | u8 *bssid, u16 channel, u32 ctrl_flags) |
30295c89 VM |
2425 | { |
2426 | void *osbuf; | |
2427 | WMI_CONNECT_CMD *cc; | |
2428 | wmip->wmi_traffic_class = 100; | |
2429 | ||
2430 | if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) { | |
2431 | return A_EINVAL; | |
2432 | } | |
2433 | if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) { | |
2434 | return A_EINVAL; | |
2435 | } | |
2436 | ||
2437 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD)); | |
2438 | if (osbuf == NULL) { | |
2439 | return A_NO_MEMORY; | |
2440 | } | |
2441 | ||
2442 | A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD)); | |
2443 | ||
2444 | cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); | |
2445 | A_MEMZERO(cc, sizeof(*cc)); | |
2446 | ||
2447 | if (ssidLength) | |
2448 | { | |
05209262 | 2449 | memcpy(cc->ssid, ssid, ssidLength); |
30295c89 VM |
2450 | } |
2451 | ||
2452 | cc->ssidLength = ssidLength; | |
2453 | cc->networkType = netType; | |
2454 | cc->dot11AuthMode = dot11AuthMode; | |
2455 | cc->authMode = authMode; | |
2456 | cc->pairwiseCryptoType = pairwiseCrypto; | |
2457 | cc->pairwiseCryptoLen = pairwiseCryptoLen; | |
2458 | cc->groupCryptoType = groupCrypto; | |
2459 | cc->groupCryptoLen = groupCryptoLen; | |
2460 | cc->channel = channel; | |
2461 | cc->ctrl_flags = ctrl_flags; | |
2462 | ||
2463 | if (bssid != NULL) { | |
05209262 | 2464 | memcpy(cc->bssid, bssid, ATH_MAC_LEN); |
30295c89 VM |
2465 | } |
2466 | ||
2467 | wmip->wmi_pair_crypto_type = pairwiseCrypto; | |
2468 | wmip->wmi_grp_crypto_type = groupCrypto; | |
2469 | ||
2470 | return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG)); | |
2471 | } | |
2472 | ||
1f4c34bd | 2473 | int |
4853ac05 | 2474 | wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel) |
30295c89 VM |
2475 | { |
2476 | void *osbuf; | |
2477 | WMI_RECONNECT_CMD *cc; | |
2478 | wmip->wmi_traffic_class = 100; | |
2479 | ||
2480 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD)); | |
2481 | if (osbuf == NULL) { | |
2482 | return A_NO_MEMORY; | |
2483 | } | |
2484 | ||
2485 | A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD)); | |
2486 | ||
2487 | cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf)); | |
2488 | A_MEMZERO(cc, sizeof(*cc)); | |
2489 | ||
2490 | cc->channel = channel; | |
2491 | ||
2492 | if (bssid != NULL) { | |
05209262 | 2493 | memcpy(cc->bssid, bssid, ATH_MAC_LEN); |
30295c89 VM |
2494 | } |
2495 | ||
2496 | return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG)); | |
2497 | } | |
2498 | ||
1f4c34bd | 2499 | int |
30295c89 VM |
2500 | wmi_disconnect_cmd(struct wmi_t *wmip) |
2501 | { | |
1f4c34bd | 2502 | int status; |
30295c89 VM |
2503 | wmip->wmi_traffic_class = 100; |
2504 | ||
2505 | /* Bug fix for 24817(elevator bug) - the disconnect command does not | |
2506 | need to do a SYNC before.*/ | |
2507 | status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID); | |
2508 | ||
2509 | return status; | |
2510 | } | |
2511 | ||
1f4c34bd | 2512 | int |
30295c89 | 2513 | wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, |
1071a134 | 2514 | u32 forceFgScan, u32 isLegacy, |
e1ce2a3a | 2515 | u32 homeDwellTime, u32 forceScanInterval, |
f2ab1275 | 2516 | s8 numChan, u16 *channelList) |
30295c89 VM |
2517 | { |
2518 | void *osbuf; | |
2519 | WMI_START_SCAN_CMD *sc; | |
f2ab1275 | 2520 | s8 size; |
30295c89 VM |
2521 | |
2522 | size = sizeof (*sc); | |
2523 | ||
2524 | if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) { | |
2525 | return A_EINVAL; | |
2526 | } | |
2527 | ||
2528 | if (numChan) { | |
2529 | if (numChan > WMI_MAX_CHANNELS) { | |
2530 | return A_EINVAL; | |
2531 | } | |
4853ac05 | 2532 | size += sizeof(u16) * (numChan - 1); |
30295c89 VM |
2533 | } |
2534 | ||
2535 | osbuf = A_NETBUF_ALLOC(size); | |
2536 | if (osbuf == NULL) { | |
2537 | return A_NO_MEMORY; | |
2538 | } | |
2539 | ||
2540 | A_NETBUF_PUT(osbuf, size); | |
2541 | ||
2542 | sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf)); | |
2543 | sc->scanType = scanType; | |
2544 | sc->forceFgScan = forceFgScan; | |
2545 | sc->isLegacy = isLegacy; | |
2546 | sc->homeDwellTime = homeDwellTime; | |
2547 | sc->forceScanInterval = forceScanInterval; | |
2548 | sc->numChannels = numChan; | |
2549 | if (numChan) { | |
05209262 | 2550 | memcpy(sc->channelList, channelList, numChan * sizeof(u16)); |
30295c89 VM |
2551 | } |
2552 | ||
2553 | return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG)); | |
2554 | } | |
2555 | ||
1f4c34bd | 2556 | int |
4853ac05 JP |
2557 | wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec, |
2558 | u16 fg_end_sec, u16 bg_sec, | |
2559 | u16 minact_chdw_msec, u16 maxact_chdw_msec, | |
2560 | u16 pas_chdw_msec, | |
ab3655da | 2561 | u8 shScanRatio, u8 scanCtrlFlags, |
e1ce2a3a | 2562 | u32 max_dfsch_act_time, u16 maxact_scan_per_ssid) |
30295c89 VM |
2563 | { |
2564 | void *osbuf; | |
2565 | WMI_SCAN_PARAMS_CMD *sc; | |
2566 | ||
2567 | osbuf = A_NETBUF_ALLOC(sizeof(*sc)); | |
2568 | if (osbuf == NULL) { | |
2569 | return A_NO_MEMORY; | |
2570 | } | |
2571 | ||
2572 | A_NETBUF_PUT(osbuf, sizeof(*sc)); | |
2573 | ||
2574 | sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
2575 | A_MEMZERO(sc, sizeof(*sc)); | |
2576 | sc->fg_start_period = fg_start_sec; | |
2577 | sc->fg_end_period = fg_end_sec; | |
2578 | sc->bg_period = bg_sec; | |
2579 | sc->minact_chdwell_time = minact_chdw_msec; | |
2580 | sc->maxact_chdwell_time = maxact_chdw_msec; | |
2581 | sc->pas_chdwell_time = pas_chdw_msec; | |
2582 | sc->shortScanRatio = shScanRatio; | |
2583 | sc->scanCtrlFlags = scanCtrlFlags; | |
2584 | sc->max_dfsch_act_time = max_dfsch_act_time; | |
2585 | sc->maxact_scan_per_ssid = maxact_scan_per_ssid; | |
2586 | ||
2587 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID, | |
2588 | NO_SYNC_WMIFLAG)); | |
2589 | } | |
2590 | ||
1f4c34bd | 2591 | int |
e1ce2a3a | 2592 | wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask) |
30295c89 VM |
2593 | { |
2594 | void *osbuf; | |
2595 | WMI_BSS_FILTER_CMD *cmd; | |
2596 | ||
2597 | if (filter >= LAST_BSS_FILTER) { | |
2598 | return A_EINVAL; | |
2599 | } | |
2600 | ||
2601 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2602 | if (osbuf == NULL) { | |
2603 | return A_NO_MEMORY; | |
2604 | } | |
2605 | ||
2606 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2607 | ||
2608 | cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); | |
2609 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2610 | cmd->bssFilter = filter; | |
2611 | cmd->ieMask = ieMask; | |
2612 | ||
2613 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID, | |
2614 | NO_SYNC_WMIFLAG)); | |
2615 | } | |
2616 | ||
1f4c34bd | 2617 | int |
ab3655da | 2618 | wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag, |
d8cb316f | 2619 | u8 ssidLength, u8 *ssid) |
30295c89 VM |
2620 | { |
2621 | void *osbuf; | |
2622 | WMI_PROBED_SSID_CMD *cmd; | |
2623 | ||
2624 | if (index > MAX_PROBED_SSID_INDEX) { | |
2625 | return A_EINVAL; | |
2626 | } | |
2627 | if (ssidLength > sizeof(cmd->ssid)) { | |
2628 | return A_EINVAL; | |
2629 | } | |
2630 | if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) { | |
2631 | return A_EINVAL; | |
2632 | } | |
2633 | if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) { | |
2634 | return A_EINVAL; | |
2635 | } | |
2636 | ||
2637 | if (flag & SPECIFIC_SSID_FLAG) { | |
1071a134 | 2638 | is_probe_ssid = true; |
30295c89 VM |
2639 | } |
2640 | ||
2641 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2642 | if (osbuf == NULL) { | |
2643 | return A_NO_MEMORY; | |
2644 | } | |
2645 | ||
2646 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2647 | ||
2648 | cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf)); | |
2649 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2650 | cmd->entryIndex = index; | |
2651 | cmd->flag = flag; | |
2652 | cmd->ssidLength = ssidLength; | |
05209262 | 2653 | memcpy(cmd->ssid, ssid, ssidLength); |
30295c89 VM |
2654 | |
2655 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID, | |
2656 | NO_SYNC_WMIFLAG)); | |
2657 | } | |
2658 | ||
1f4c34bd | 2659 | int |
4853ac05 | 2660 | wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons) |
30295c89 VM |
2661 | { |
2662 | void *osbuf; | |
2663 | WMI_LISTEN_INT_CMD *cmd; | |
2664 | ||
2665 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2666 | if (osbuf == NULL) { | |
2667 | return A_NO_MEMORY; | |
2668 | } | |
2669 | ||
2670 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2671 | ||
2672 | cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf)); | |
2673 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2674 | cmd->listenInterval = listenInterval; | |
2675 | cmd->numBeacons = listenBeacons; | |
2676 | ||
2677 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID, | |
2678 | NO_SYNC_WMIFLAG)); | |
2679 | } | |
2680 | ||
1f4c34bd | 2681 | int |
4853ac05 | 2682 | wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons) |
30295c89 VM |
2683 | { |
2684 | void *osbuf; | |
2685 | WMI_BMISS_TIME_CMD *cmd; | |
2686 | ||
2687 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2688 | if (osbuf == NULL) { | |
2689 | return A_NO_MEMORY; | |
2690 | } | |
2691 | ||
2692 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2693 | ||
2694 | cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf)); | |
2695 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2696 | cmd->bmissTime = bmissTime; | |
2697 | cmd->numBeacons = bmissBeacons; | |
2698 | ||
2699 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID, | |
2700 | NO_SYNC_WMIFLAG)); | |
2701 | } | |
2702 | ||
1f4c34bd | 2703 | int |
ab3655da JP |
2704 | wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType, |
2705 | u8 ieLen, u8 *ieInfo) | |
30295c89 VM |
2706 | { |
2707 | void *osbuf; | |
2708 | WMI_SET_ASSOC_INFO_CMD *cmd; | |
4853ac05 | 2709 | u16 cmdLen; |
30295c89 VM |
2710 | |
2711 | cmdLen = sizeof(*cmd) + ieLen - 1; | |
2712 | osbuf = A_NETBUF_ALLOC(cmdLen); | |
2713 | if (osbuf == NULL) { | |
2714 | return A_NO_MEMORY; | |
2715 | } | |
2716 | ||
2717 | A_NETBUF_PUT(osbuf, cmdLen); | |
2718 | ||
2719 | cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf)); | |
2720 | A_MEMZERO(cmd, cmdLen); | |
2721 | cmd->ieType = ieType; | |
2722 | cmd->bufferSize = ieLen; | |
05209262 | 2723 | memcpy(cmd->assocInfo, ieInfo, ieLen); |
30295c89 VM |
2724 | |
2725 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID, | |
2726 | NO_SYNC_WMIFLAG)); | |
2727 | } | |
2728 | ||
1f4c34bd | 2729 | int |
ab3655da | 2730 | wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode) |
30295c89 VM |
2731 | { |
2732 | void *osbuf; | |
2733 | WMI_POWER_MODE_CMD *cmd; | |
2734 | ||
2735 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2736 | if (osbuf == NULL) { | |
2737 | return A_NO_MEMORY; | |
2738 | } | |
2739 | ||
2740 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2741 | ||
2742 | cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
2743 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2744 | cmd->powerMode = powerMode; | |
2745 | wmip->wmi_powerMode = powerMode; | |
2746 | ||
2747 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID, | |
2748 | NO_SYNC_WMIFLAG)); | |
2749 | } | |
2750 | ||
1f4c34bd | 2751 | int |
ab3655da | 2752 | wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl, |
4853ac05 | 2753 | u16 atim_windows, u16 timeout_value) |
30295c89 VM |
2754 | { |
2755 | void *osbuf; | |
2756 | WMI_IBSS_PM_CAPS_CMD *cmd; | |
2757 | ||
2758 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2759 | if (osbuf == NULL) { | |
2760 | return A_NO_MEMORY; | |
2761 | } | |
2762 | ||
2763 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2764 | ||
2765 | cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf)); | |
2766 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2767 | cmd->power_saving = pmEnable; | |
2768 | cmd->ttl = ttl; | |
2769 | cmd->atim_windows = atim_windows; | |
2770 | cmd->timeout_value = timeout_value; | |
2771 | ||
2772 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID, | |
2773 | NO_SYNC_WMIFLAG)); | |
2774 | } | |
2775 | ||
1f4c34bd | 2776 | int |
e1ce2a3a JP |
2777 | wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time, |
2778 | u32 ps_period, u8 sleep_period) | |
30295c89 VM |
2779 | { |
2780 | void *osbuf; | |
2781 | WMI_AP_PS_CMD *cmd; | |
2782 | ||
2783 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2784 | if (osbuf == NULL) { | |
2785 | return A_NO_MEMORY; | |
2786 | } | |
2787 | ||
2788 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2789 | ||
2790 | cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf)); | |
2791 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2792 | cmd->psType = psType; | |
2793 | cmd->idle_time = idle_time; | |
2794 | cmd->ps_period = ps_period; | |
2795 | cmd->sleep_period = sleep_period; | |
2796 | ||
2797 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID, | |
2798 | NO_SYNC_WMIFLAG)); | |
2799 | } | |
2800 | ||
1f4c34bd | 2801 | int |
4853ac05 JP |
2802 | wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod, |
2803 | u16 psPollNum, u16 dtimPolicy, | |
2804 | u16 tx_wakeup_policy, u16 num_tx_to_wakeup, | |
2805 | u16 ps_fail_event_policy) | |
30295c89 VM |
2806 | { |
2807 | void *osbuf; | |
2808 | WMI_POWER_PARAMS_CMD *pm; | |
2809 | ||
2810 | osbuf = A_NETBUF_ALLOC(sizeof(*pm)); | |
2811 | if (osbuf == NULL) { | |
2812 | return A_NO_MEMORY; | |
2813 | } | |
2814 | ||
2815 | A_NETBUF_PUT(osbuf, sizeof(*pm)); | |
2816 | ||
2817 | pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
2818 | A_MEMZERO(pm, sizeof(*pm)); | |
2819 | pm->idle_period = idlePeriod; | |
2820 | pm->pspoll_number = psPollNum; | |
2821 | pm->dtim_policy = dtimPolicy; | |
2822 | pm->tx_wakeup_policy = tx_wakeup_policy; | |
2823 | pm->num_tx_to_wakeup = num_tx_to_wakeup; | |
2824 | pm->ps_fail_event_policy = ps_fail_event_policy; | |
2825 | ||
2826 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID, | |
2827 | NO_SYNC_WMIFLAG)); | |
2828 | } | |
2829 | ||
1f4c34bd | 2830 | int |
ab3655da | 2831 | wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout) |
30295c89 VM |
2832 | { |
2833 | void *osbuf; | |
2834 | WMI_DISC_TIMEOUT_CMD *cmd; | |
2835 | ||
2836 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2837 | if (osbuf == NULL) { | |
2838 | return A_NO_MEMORY; | |
2839 | } | |
2840 | ||
2841 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2842 | ||
2843 | cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf)); | |
2844 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2845 | cmd->disconnectTimeout = timeout; | |
2846 | ||
2847 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID, | |
2848 | NO_SYNC_WMIFLAG)); | |
2849 | } | |
2850 | ||
1f4c34bd | 2851 | int |
ab3655da JP |
2852 | wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType, |
2853 | u8 keyUsage, u8 keyLength, u8 *keyRSC, | |
2854 | u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr, | |
30295c89 VM |
2855 | WMI_SYNC_FLAG sync_flag) |
2856 | { | |
2857 | void *osbuf; | |
2858 | WMI_ADD_CIPHER_KEY_CMD *cmd; | |
2859 | ||
2860 | if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) || | |
2861 | (keyMaterial == NULL)) | |
2862 | { | |
2863 | return A_EINVAL; | |
2864 | } | |
2865 | ||
2866 | if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) { | |
2867 | return A_EINVAL; | |
2868 | } | |
2869 | ||
2870 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2871 | if (osbuf == NULL) { | |
2872 | return A_NO_MEMORY; | |
2873 | } | |
2874 | ||
2875 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2876 | ||
2877 | cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); | |
2878 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2879 | cmd->keyIndex = keyIndex; | |
2880 | cmd->keyType = keyType; | |
2881 | cmd->keyUsage = keyUsage; | |
2882 | cmd->keyLength = keyLength; | |
05209262 | 2883 | memcpy(cmd->key, keyMaterial, keyLength); |
30295c89 VM |
2884 | #ifdef WAPI_ENABLE |
2885 | if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) { | |
2886 | #else | |
2887 | if (NULL != keyRSC) { | |
2888 | #endif // WAPI_ENABLE | |
05209262 | 2889 | memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC)); |
30295c89 VM |
2890 | } |
2891 | cmd->key_op_ctrl = key_op_ctrl; | |
2892 | ||
2893 | if(macAddr) { | |
05209262 | 2894 | memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN); |
30295c89 VM |
2895 | } |
2896 | ||
2897 | return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag)); | |
2898 | } | |
2899 | ||
1f4c34bd | 2900 | int |
ab3655da | 2901 | wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk) |
30295c89 VM |
2902 | { |
2903 | void *osbuf; | |
2904 | WMI_ADD_KRK_CMD *cmd; | |
2905 | ||
2906 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2907 | if (osbuf == NULL) { | |
2908 | return A_NO_MEMORY; | |
2909 | } | |
2910 | ||
2911 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2912 | ||
2913 | cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf)); | |
2914 | A_MEMZERO(cmd, sizeof(*cmd)); | |
05209262 | 2915 | memcpy(cmd->krk, krk, WMI_KRK_LEN); |
30295c89 VM |
2916 | |
2917 | return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG)); | |
2918 | } | |
2919 | ||
1f4c34bd | 2920 | int |
30295c89 VM |
2921 | wmi_delete_krk_cmd(struct wmi_t *wmip) |
2922 | { | |
2923 | return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID); | |
2924 | } | |
2925 | ||
1f4c34bd | 2926 | int |
ab3655da | 2927 | wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex) |
30295c89 VM |
2928 | { |
2929 | void *osbuf; | |
2930 | WMI_DELETE_CIPHER_KEY_CMD *cmd; | |
2931 | ||
2932 | if (keyIndex > WMI_MAX_KEY_INDEX) { | |
2933 | return A_EINVAL; | |
2934 | } | |
2935 | ||
2936 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2937 | if (osbuf == NULL) { | |
2938 | return A_NO_MEMORY; | |
2939 | } | |
2940 | ||
2941 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2942 | ||
2943 | cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); | |
2944 | A_MEMZERO(cmd, sizeof(*cmd)); | |
2945 | cmd->keyIndex = keyIndex; | |
2946 | ||
2947 | return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID, | |
2948 | NO_SYNC_WMIFLAG)); | |
2949 | } | |
2950 | ||
1f4c34bd | 2951 | int |
ab3655da | 2952 | wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId, |
1071a134 | 2953 | bool set) |
30295c89 VM |
2954 | { |
2955 | void *osbuf; | |
2956 | WMI_SET_PMKID_CMD *cmd; | |
2957 | ||
2958 | if (bssid == NULL) { | |
2959 | return A_EINVAL; | |
2960 | } | |
2961 | ||
1071a134 | 2962 | if ((set == true) && (pmkId == NULL)) { |
30295c89 VM |
2963 | return A_EINVAL; |
2964 | } | |
2965 | ||
2966 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2967 | if (osbuf == NULL) { | |
2968 | return A_NO_MEMORY; | |
2969 | } | |
2970 | ||
2971 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2972 | ||
2973 | cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf)); | |
05209262 | 2974 | memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); |
1071a134 | 2975 | if (set == true) { |
05209262 | 2976 | memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid)); |
30295c89 VM |
2977 | cmd->enable = PMKID_ENABLE; |
2978 | } else { | |
2979 | A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid)); | |
2980 | cmd->enable = PMKID_DISABLE; | |
2981 | } | |
2982 | ||
2983 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG)); | |
2984 | } | |
2985 | ||
1f4c34bd | 2986 | int |
1071a134 | 2987 | wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en) |
30295c89 VM |
2988 | { |
2989 | void *osbuf; | |
2990 | WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd; | |
2991 | ||
2992 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
2993 | if (osbuf == NULL) { | |
2994 | return A_NO_MEMORY; | |
2995 | } | |
2996 | ||
2997 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
2998 | ||
2999 | cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf)); | |
1071a134 | 3000 | cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE; |
30295c89 VM |
3001 | |
3002 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID, | |
3003 | NO_SYNC_WMIFLAG)); | |
3004 | } | |
3005 | ||
1f4c34bd | 3006 | int |
30295c89 VM |
3007 | wmi_set_akmp_params_cmd(struct wmi_t *wmip, |
3008 | WMI_SET_AKMP_PARAMS_CMD *akmpParams) | |
3009 | { | |
3010 | void *osbuf; | |
3011 | WMI_SET_AKMP_PARAMS_CMD *cmd; | |
3012 | ||
3013 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3014 | if (osbuf == NULL) { | |
3015 | return A_NO_MEMORY; | |
3016 | } | |
3017 | ||
3018 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
3019 | cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
3020 | cmd->akmpInfo = akmpParams->akmpInfo; | |
3021 | ||
3022 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID, | |
3023 | NO_SYNC_WMIFLAG)); | |
3024 | } | |
3025 | ||
1f4c34bd | 3026 | int |
30295c89 VM |
3027 | wmi_set_pmkid_list_cmd(struct wmi_t *wmip, |
3028 | WMI_SET_PMKID_LIST_CMD *pmkInfo) | |
3029 | { | |
3030 | void *osbuf; | |
3031 | WMI_SET_PMKID_LIST_CMD *cmd; | |
4853ac05 | 3032 | u16 cmdLen; |
ab3655da | 3033 | u8 i; |
30295c89 VM |
3034 | |
3035 | cmdLen = sizeof(pmkInfo->numPMKID) + | |
3036 | pmkInfo->numPMKID * sizeof(WMI_PMKID); | |
3037 | ||
3038 | osbuf = A_NETBUF_ALLOC(cmdLen); | |
3039 | if (osbuf == NULL) { | |
3040 | return A_NO_MEMORY; | |
3041 | } | |
3042 | ||
3043 | A_NETBUF_PUT(osbuf, cmdLen); | |
3044 | cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf)); | |
3045 | cmd->numPMKID = pmkInfo->numPMKID; | |
3046 | ||
3047 | for (i = 0; i < cmd->numPMKID; i++) { | |
05209262 | 3048 | memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i], |
30295c89 VM |
3049 | WMI_PMKID_LEN); |
3050 | } | |
3051 | ||
3052 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID, | |
3053 | NO_SYNC_WMIFLAG)); | |
3054 | } | |
3055 | ||
1f4c34bd | 3056 | int |
30295c89 VM |
3057 | wmi_get_pmkid_list_cmd(struct wmi_t *wmip) |
3058 | { | |
3059 | return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID); | |
3060 | } | |
3061 | ||
1f4c34bd | 3062 | int |
30295c89 VM |
3063 | wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid) |
3064 | { | |
3065 | WMI_DATA_HDR *dtHdr; | |
3066 | ||
3067 | A_ASSERT( eid != wmip->wmi_endpoint_id); | |
3068 | A_ASSERT(osbuf != NULL); | |
3069 | ||
4f69cef0 | 3070 | if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) { |
30295c89 VM |
3071 | return A_NO_MEMORY; |
3072 | } | |
3073 | ||
3074 | dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); | |
3075 | dtHdr->info = | |
3076 | (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT; | |
3077 | ||
3078 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter - eid %d\n", DBGARG, eid)); | |
3079 | ||
3080 | return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid)); | |
3081 | } | |
3082 | ||
3083 | typedef struct _WMI_DATA_SYNC_BUFS { | |
ab3655da | 3084 | u8 trafficClass; |
30295c89 VM |
3085 | void *osbuf; |
3086 | }WMI_DATA_SYNC_BUFS; | |
3087 | ||
1f4c34bd | 3088 | static int |
30295c89 VM |
3089 | wmi_sync_point(struct wmi_t *wmip) |
3090 | { | |
3091 | void *cmd_osbuf; | |
3092 | WMI_SYNC_CMD *cmd; | |
3093 | WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC]; | |
ab3655da | 3094 | u8 i,numPriStreams=0; |
4f69cef0 | 3095 | int status = 0; |
30295c89 VM |
3096 | |
3097 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
3098 | ||
3099 | memset(dataSyncBufs,0,sizeof(dataSyncBufs)); | |
3100 | ||
3101 | /* lock out while we walk through the priority list and assemble our local array */ | |
3102 | LOCK_WMI(wmip); | |
3103 | ||
3104 | for (i=0; i < WMM_NUM_AC ; i++) { | |
3105 | if (wmip->wmi_fatPipeExists & (1 << i)) { | |
3106 | numPriStreams++; | |
3107 | dataSyncBufs[numPriStreams-1].trafficClass = i; | |
3108 | } | |
3109 | } | |
3110 | ||
3111 | UNLOCK_WMI(wmip); | |
3112 | ||
3113 | /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */ | |
3114 | ||
3115 | do { | |
3116 | /* | |
3117 | * We allocate all network buffers needed so we will be able to | |
3118 | * send all required frames. | |
3119 | */ | |
3120 | cmd_osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3121 | if (cmd_osbuf == NULL) { | |
3122 | status = A_NO_MEMORY; | |
3123 | break; | |
3124 | } | |
3125 | ||
3126 | A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd)); | |
3127 | ||
3128 | cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf)); | |
3129 | A_MEMZERO(cmd, sizeof(*cmd)); | |
3130 | ||
3131 | /* In the SYNC cmd sent on the control Ep, send a bitmap of the data | |
3132 | * eps on which the Data Sync will be sent | |
3133 | */ | |
3134 | cmd->dataSyncMap = wmip->wmi_fatPipeExists; | |
3135 | ||
3136 | for (i=0; i < numPriStreams ; i++) { | |
3137 | dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0); | |
3138 | if (dataSyncBufs[i].osbuf == NULL) { | |
3139 | status = A_NO_MEMORY; | |
3140 | break; | |
3141 | } | |
3142 | } //end for | |
3143 | ||
3144 | /* if Buffer allocation for any of the dataSync fails, then do not | |
3145 | * send the Synchronize cmd on the control ep | |
3146 | */ | |
391bb211 | 3147 | if (status) { |
30295c89 VM |
3148 | break; |
3149 | } | |
3150 | ||
3151 | /* | |
3152 | * Send sync cmd followed by sync data messages on all endpoints being | |
3153 | * used | |
3154 | */ | |
3155 | status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID, | |
3156 | NO_SYNC_WMIFLAG); | |
3157 | ||
391bb211 | 3158 | if (status) { |
30295c89 VM |
3159 | break; |
3160 | } | |
3161 | /* cmd buffer sent, we no longer own it */ | |
3162 | cmd_osbuf = NULL; | |
3163 | ||
3164 | for(i=0; i < numPriStreams; i++) { | |
3165 | A_ASSERT(dataSyncBufs[i].osbuf != NULL); | |
3166 | status = wmi_dataSync_send(wmip, | |
3167 | dataSyncBufs[i].osbuf, | |
3168 | A_WMI_Ac2EndpointID(wmip->wmi_devt, | |
3169 | dataSyncBufs[i]. | |
3170 | trafficClass) | |
3171 | ); | |
3172 | ||
391bb211 | 3173 | if (status) { |
30295c89 VM |
3174 | break; |
3175 | } | |
3176 | /* we don't own this buffer anymore, NULL it out of the array so it | |
3177 | * won't get cleaned up */ | |
3178 | dataSyncBufs[i].osbuf = NULL; | |
3179 | } //end for | |
3180 | ||
1071a134 | 3181 | } while(false); |
30295c89 VM |
3182 | |
3183 | /* free up any resources left over (possibly due to an error) */ | |
3184 | ||
3185 | if (cmd_osbuf != NULL) { | |
3186 | A_NETBUF_FREE(cmd_osbuf); | |
3187 | } | |
3188 | ||
3189 | for (i = 0; i < numPriStreams; i++) { | |
3190 | if (dataSyncBufs[i].osbuf != NULL) { | |
3191 | A_NETBUF_FREE(dataSyncBufs[i].osbuf); | |
3192 | } | |
3193 | } | |
3194 | ||
3195 | return (status); | |
3196 | } | |
3197 | ||
1f4c34bd | 3198 | int |
30295c89 VM |
3199 | wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params) |
3200 | { | |
3201 | void *osbuf; | |
3202 | WMI_CREATE_PSTREAM_CMD *cmd; | |
ab3655da | 3203 | u8 fatPipeExistsForAC=0; |
f68057e6 JP |
3204 | s32 minimalPHY = 0; |
3205 | s32 nominalPHY = 0; | |
30295c89 VM |
3206 | |
3207 | /* Validate all the parameters. */ | |
3208 | if( !((params->userPriority < 8) && | |
3209 | (params->userPriority <= 0x7) && | |
3210 | (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) && | |
3211 | (params->trafficDirection == UPLINK_TRAFFIC || | |
3212 | params->trafficDirection == DNLINK_TRAFFIC || | |
3213 | params->trafficDirection == BIDIR_TRAFFIC) && | |
3214 | (params->trafficType == TRAFFIC_TYPE_APERIODIC || | |
3215 | params->trafficType == TRAFFIC_TYPE_PERIODIC ) && | |
3216 | (params->voicePSCapability == DISABLE_FOR_THIS_AC || | |
3217 | params->voicePSCapability == ENABLE_FOR_THIS_AC || | |
3218 | params->voicePSCapability == ENABLE_FOR_ALL_AC) && | |
3219 | (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) ) | |
3220 | { | |
3221 | return A_EINVAL; | |
3222 | } | |
3223 | ||
3224 | // | |
3225 | // check nominal PHY rate is >= minimalPHY, so that DUT | |
3226 | // can allow TSRS IE | |
3227 | // | |
3228 | ||
3229 | // get the physical rate | |
3230 | minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps | |
3231 | ||
3232 | // check minimal phy < nominal phy rate | |
3233 | // | |
3234 | if (params->nominalPHY >= minimalPHY) | |
3235 | { | |
3236 | nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps | |
3237 | A_DPRINTF(DBG_WMI, | |
3238 | (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG, | |
3239 | minimalPHY, nominalPHY)); | |
3240 | ||
3241 | params->nominalPHY = nominalPHY; | |
3242 | } | |
3243 | else | |
3244 | { | |
3245 | params->nominalPHY = 0; | |
3246 | } | |
3247 | ||
3248 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3249 | if (osbuf == NULL) { | |
3250 | return A_NO_MEMORY; | |
3251 | } | |
3252 | ||
3253 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
3254 | ||
3255 | A_DPRINTF(DBG_WMI, | |
3256 | (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG, | |
3257 | params->trafficClass, params->tsid)); | |
3258 | ||
3259 | cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); | |
3260 | A_MEMZERO(cmd, sizeof(*cmd)); | |
05209262 | 3261 | memcpy(cmd, params, sizeof(*cmd)); |
30295c89 VM |
3262 | |
3263 | /* this is an implicitly created Fat pipe */ | |
e1ce2a3a | 3264 | if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) { |
30295c89 VM |
3265 | LOCK_WMI(wmip); |
3266 | fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); | |
3267 | wmip->wmi_fatPipeExists |= (1<<params->trafficClass); | |
3268 | UNLOCK_WMI(wmip); | |
3269 | } else { | |
3270 | /* this is an explicitly created thin stream within a fat pipe */ | |
3271 | LOCK_WMI(wmip); | |
3272 | fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); | |
3273 | wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid); | |
3274 | /* if a thinstream becomes active, the fat pipe automatically | |
3275 | * becomes active | |
3276 | */ | |
3277 | wmip->wmi_fatPipeExists |= (1<<params->trafficClass); | |
3278 | UNLOCK_WMI(wmip); | |
3279 | } | |
3280 | ||
3281 | /* Indicate activty change to driver layer only if this is the | |
3282 | * first TSID to get created in this AC explicitly or an implicit | |
3283 | * fat pipe is getting created. | |
3284 | */ | |
3285 | if (!fatPipeExistsForAC) { | |
3286 | A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass); | |
3287 | } | |
3288 | ||
3289 | /* mike: should be SYNC_BEFORE_WMIFLAG */ | |
3290 | return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID, | |
3291 | NO_SYNC_WMIFLAG)); | |
3292 | } | |
3293 | ||
1f4c34bd | 3294 | int |
ab3655da | 3295 | wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid) |
30295c89 VM |
3296 | { |
3297 | void *osbuf; | |
3298 | WMI_DELETE_PSTREAM_CMD *cmd; | |
1f4c34bd | 3299 | int status; |
4853ac05 | 3300 | u16 activeTsids=0; |
30295c89 VM |
3301 | |
3302 | /* validate the parameters */ | |
3303 | if (trafficClass > 3) { | |
3304 | A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass)); | |
3305 | return A_EINVAL; | |
3306 | } | |
3307 | ||
3308 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3309 | if (osbuf == NULL) { | |
3310 | return A_NO_MEMORY; | |
3311 | } | |
3312 | ||
3313 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
3314 | ||
3315 | cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); | |
3316 | A_MEMZERO(cmd, sizeof(*cmd)); | |
3317 | ||
3318 | cmd->trafficClass = trafficClass; | |
3319 | cmd->tsid = tsid; | |
3320 | ||
3321 | LOCK_WMI(wmip); | |
3322 | activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; | |
3323 | UNLOCK_WMI(wmip); | |
3324 | ||
3325 | /* Check if the tsid was created & exists */ | |
3326 | if (!(activeTsids & (1<<tsid))) { | |
3327 | ||
3328 | A_NETBUF_FREE(osbuf); | |
3329 | A_DPRINTF(DBG_WMI, | |
3330 | (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass)); | |
3331 | /* TODO: return a more appropriate err code */ | |
3332 | return A_ERROR; | |
3333 | } | |
3334 | ||
3335 | A_DPRINTF(DBG_WMI, | |
3336 | (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid)); | |
3337 | ||
3338 | status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID, | |
3339 | SYNC_BEFORE_WMIFLAG)); | |
3340 | ||
3341 | LOCK_WMI(wmip); | |
3342 | wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid); | |
3343 | activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; | |
3344 | UNLOCK_WMI(wmip); | |
3345 | ||
3346 | ||
3347 | /* Indicate stream inactivity to driver layer only if all tsids | |
3348 | * within this AC are deleted. | |
3349 | */ | |
3350 | if(!activeTsids) { | |
3351 | A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass); | |
3352 | wmip->wmi_fatPipeExists &= ~(1<<trafficClass); | |
3353 | } | |
3354 | ||
3355 | return status; | |
3356 | } | |
3357 | ||
1f4c34bd | 3358 | int |
4853ac05 | 3359 | wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask) |
30295c89 VM |
3360 | { |
3361 | void *osbuf; | |
3362 | WMI_FRAME_RATES_CMD *cmd; | |
ab3655da | 3363 | u8 frameType; |
30295c89 VM |
3364 | |
3365 | A_DPRINTF(DBG_WMI, | |
3366 | (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask)); | |
3367 | ||
3368 | if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) || | |
3369 | (subType > 15)){ | |
3370 | ||
3371 | return A_EINVAL; | |
3372 | } | |
3373 | ||
3374 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3375 | if (osbuf == NULL) { | |
3376 | return A_NO_MEMORY; | |
3377 | } | |
3378 | ||
3379 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
3380 | ||
3381 | cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf)); | |
3382 | A_MEMZERO(cmd, sizeof(*cmd)); | |
3383 | ||
ab3655da | 3384 | frameType = (u8)((subType << 4) | type); |
30295c89 VM |
3385 | |
3386 | cmd->bEnableMask = bEnable; | |
3387 | cmd->frameType = frameType; | |
3388 | cmd->frameRateMask = rateMask; | |
3389 | ||
3390 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG)); | |
3391 | } | |
3392 | ||
3393 | /* | |
3394 | * used to set the bit rate. rate is in Kbps. If rate == -1 | |
3395 | * then auto selection is used. | |
3396 | */ | |
1f4c34bd | 3397 | int |
f68057e6 | 3398 | wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate) |
30295c89 VM |
3399 | { |
3400 | void *osbuf; | |
3401 | WMI_BIT_RATE_CMD *cmd; | |
f2ab1275 | 3402 | s8 drix, mrix, crix, ret_val; |
30295c89 VM |
3403 | |
3404 | if (dataRate != -1) { | |
3405 | ret_val = wmi_validate_bitrate(wmip, dataRate, &drix); | |
3406 | if(ret_val == A_EINVAL){ | |
3407 | return A_EINVAL; | |
3408 | } | |
3409 | } else { | |
3410 | drix = -1; | |
3411 | } | |
3412 | ||
3413 | if (mgmtRate != -1) { | |
3414 | ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix); | |
3415 | if(ret_val == A_EINVAL){ | |
3416 | return A_EINVAL; | |
3417 | } | |
3418 | } else { | |
3419 | mrix = -1; | |
3420 | } | |
3421 | if (ctlRate != -1) { | |
3422 | ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix); | |
3423 | if(ret_val == A_EINVAL){ | |
3424 | return A_EINVAL; | |
3425 | } | |
3426 | } else { | |
3427 | crix = -1; | |
3428 | } | |
3429 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3430 | if (osbuf == NULL) { | |
3431 | return A_NO_MEMORY; | |
3432 | } | |
3433 | ||
3434 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
3435 | ||
3436 | cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf)); | |
3437 | A_MEMZERO(cmd, sizeof(*cmd)); | |
3438 | ||
3439 | cmd->rateIndex = drix; | |
3440 | cmd->mgmtRateIndex = mrix; | |
3441 | cmd->ctlRateIndex = crix; | |
3442 | ||
3443 | ||
3444 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); | |
3445 | } | |
3446 | ||
1f4c34bd | 3447 | int |
30295c89 VM |
3448 | wmi_get_bitrate_cmd(struct wmi_t *wmip) |
3449 | { | |
3450 | return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID); | |
3451 | } | |
3452 | ||
3453 | /* | |
1071a134 | 3454 | * Returns true iff the given rate index is legal in the current PHY mode. |
30295c89 | 3455 | */ |
1071a134 | 3456 | bool |
f68057e6 | 3457 | wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex) |
30295c89 VM |
3458 | { |
3459 | WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode; | |
1071a134 | 3460 | bool isValid = true; |
30295c89 VM |
3461 | switch(phyMode) { |
3462 | case WMI_11A_MODE: | |
3463 | if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){ | |
3464 | if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { | |
1071a134 | 3465 | isValid = false; |
30295c89 VM |
3466 | } |
3467 | } else { | |
3468 | if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) { | |
1071a134 | 3469 | isValid = false; |
30295c89 VM |
3470 | } |
3471 | } | |
3472 | break; | |
3473 | ||
3474 | case WMI_11B_MODE: | |
3475 | if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) { | |
1071a134 | 3476 | isValid = false; |
30295c89 VM |
3477 | } |
3478 | break; | |
3479 | ||
3480 | case WMI_11GONLY_MODE: | |
3481 | if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ | |
3482 | if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { | |
1071a134 | 3483 | isValid = false; |
30295c89 VM |
3484 | } |
3485 | } else { | |
3486 | if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) { | |
1071a134 | 3487 | isValid = false; |
30295c89 VM |
3488 | } |
3489 | } | |
3490 | break; | |
3491 | ||
3492 | case WMI_11G_MODE: | |
3493 | case WMI_11AG_MODE: | |
3494 | if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ | |
3495 | if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { | |
1071a134 | 3496 | isValid = false; |
30295c89 VM |
3497 | } |
3498 | } else { | |
3499 | if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) { | |
1071a134 | 3500 | isValid = false; |
30295c89 VM |
3501 | } |
3502 | } | |
3503 | break; | |
3504 | default: | |
1071a134 | 3505 | A_ASSERT(false); |
30295c89 VM |
3506 | break; |
3507 | } | |
3508 | ||
3509 | return isValid; | |
3510 | } | |
3511 | ||
f68057e6 | 3512 | s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx) |
30295c89 | 3513 | { |
f2ab1275 | 3514 | s8 i; |
30295c89 VM |
3515 | |
3516 | for (i=0;;i++) | |
3517 | { | |
e1ce2a3a | 3518 | if (wmi_rateTable[(u32) i][0] == 0) { |
30295c89 VM |
3519 | return A_EINVAL; |
3520 | } | |
e1ce2a3a | 3521 | if (wmi_rateTable[(u32) i][0] == rate) { |
30295c89 VM |
3522 | break; |
3523 | } | |
3524 | } | |
3525 | ||
f68057e6 | 3526 | if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) { |
30295c89 VM |
3527 | return A_EINVAL; |
3528 | } | |
3529 | ||
3530 | *rate_idx = i; | |
4f69cef0 | 3531 | return 0; |
30295c89 VM |
3532 | } |
3533 | ||
1f4c34bd | 3534 | int |
e1ce2a3a | 3535 | wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask) |
30295c89 VM |
3536 | { |
3537 | void *osbuf; | |
3538 | WMI_FIX_RATES_CMD *cmd; | |
3539 | #if 0 | |
f68057e6 | 3540 | s32 rateIndex; |
30295c89 VM |
3541 | /* This check does not work for AR6003 as the HT modes are enabled only when |
3542 | * the STA is connected to a HT_BSS and is not based only on channel. It is | |
3543 | * safe to skip this check however because rate control will only use rates | |
3544 | * that are permitted by the valid rate mask and the fix rate mask. Meaning | |
3545 | * the fix rate mask is not sufficient by itself to cause an invalid rate | |
3546 | * to be used. */ | |
3547 | /* Make sure all rates in the mask are valid in the current PHY mode */ | |
3548 | for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) { | |
e1ce2a3a | 3549 | if((1 << rateIndex) & (u32)fixRatesMask) { |
1071a134 | 3550 | if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) { |
30295c89 VM |
3551 | A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG)); |
3552 | return A_EINVAL; | |
3553 | } | |
3554 | } | |
3555 | } | |
3556 | #endif | |
3557 | ||
3558 | ||
3559 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
3560 | if (osbuf == NULL) { | |
3561 | return A_NO_MEMORY; | |
3562 | } | |
3563 | ||
3564 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
3565 | ||
3566 | cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf)); | |
3567 | A_MEMZERO(cmd, sizeof(*cmd)); | |
3568 | ||
3569 | cmd->fixRateMask = fixRatesMask; | |
3570 | ||
3571 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); | |
3572 | } | |
3573 | ||
1f4c34bd | 3574 | int |
30295c89 VM |
3575 | wmi_get_ratemask_cmd(struct wmi_t *wmip) |
3576 | { | |
3577 | return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID); | |
3578 | } | |
3579 | ||
1f4c34bd | 3580 | int |
30295c89 VM |
3581 | wmi_get_channelList_cmd(struct wmi_t *wmip) |
3582 | { | |
3583 | return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID); | |
3584 | } | |
3585 | ||
3586 | /* | |
3587 | * used to generate a wmi sey channel Parameters cmd. | |
3588 | * mode should always be specified and corresponds to the phy mode of the | |
3589 | * wlan. | |
3590 | * numChan should alway sbe specified. If zero indicates that all available | |
3591 | * channels should be used. | |
3592 | * channelList is an array of channel frequencies (in Mhz) which the radio | |
3593 | * should limit its operation to. It should be NULL if numChan == 0. Size of | |
3594 | * array should correspond to numChan entries. | |
3595 | */ | |
1f4c34bd | 3596 | int |
ab3655da | 3597 | wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam, |
f2ab1275 | 3598 | WMI_PHY_MODE mode, s8 numChan, |
4853ac05 | 3599 | u16 *channelList) |
30295c89 VM |
3600 | { |
3601 | void *osbuf; | |
3602 | WMI_CHANNEL_PARAMS_CMD *cmd; | |
f2ab1275 | 3603 | s8 size; |
30295c89 VM |
3604 | |
3605 | size = sizeof (*cmd); | |
3606 | ||
3607 | if (numChan) { | |
3608 | if (numChan > WMI_MAX_CHANNELS) { | |
3609 | return A_EINVAL; | |
3610 | } | |
4853ac05 | 3611 | size += sizeof(u16) * (numChan - 1); |
30295c89 VM |
3612 | } |
3613 | ||
3614 | osbuf = A_NETBUF_ALLOC(size); | |
3615 | if (osbuf == NULL) { | |
3616 | return A_NO_MEMORY; | |
3617 | } | |
3618 | ||
3619 | A_NETBUF_PUT(osbuf, size); | |
3620 | ||
3621 | cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
3622 | A_MEMZERO(cmd, size); | |
3623 | ||
3624 | wmip->wmi_phyMode = mode; | |
3625 | cmd->scanParam = scanParam; | |
3626 | cmd->phyMode = mode; | |
3627 | cmd->numChannels = numChan; | |
05209262 | 3628 | memcpy(cmd->channelList, channelList, numChan * sizeof(u16)); |
30295c89 VM |
3629 | |
3630 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID, | |
3631 | NO_SYNC_WMIFLAG)); | |
3632 | } | |
3633 | ||
3634 | void | |
3635 | wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) | |
3636 | { | |
3637 | SQ_THRESHOLD_PARAMS *sq_thresh = | |
3638 | &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; | |
3639 | /* | |
3640 | * Parse the command and store the threshold values here. The checks | |
3641 | * for valid values can be put here | |
3642 | */ | |
3643 | sq_thresh->weight = rssiCmd->weight; | |
3644 | sq_thresh->polling_interval = rssiCmd->pollTime; | |
3645 | ||
3646 | sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3647 | sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3648 | sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3649 | sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3650 | sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3651 | sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3652 | sq_thresh->upper_threshold_valid_count = 6; | |
3653 | ||
3654 | /* List sorted in descending order */ | |
3655 | sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3656 | sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3657 | sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3658 | sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3659 | sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3660 | sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR; | |
3661 | sq_thresh->lower_threshold_valid_count = 6; | |
3662 | ||
3663 | if (!rssi_event_value) { | |
3664 | /* | |
3665 | * Configuring the thresholds to their extremes allows the host to get an | |
3666 | * event from the target which is used for the configuring the correct | |
3667 | * thresholds | |
3668 | */ | |
3669 | rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0]; | |
3670 | rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0]; | |
3671 | } else { | |
3672 | /* | |
3673 | * In case the user issues multiple times of rssi_threshold_setting, | |
3674 | * we should not use the extreames anymore, the target does not expect that. | |
3675 | */ | |
3676 | rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh, | |
3677 | sq_thresh->upper_threshold_valid_count); | |
3678 | rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh, | |
3679 | sq_thresh->lower_threshold_valid_count); | |
3680 | } | |
3681 | } | |
3682 | ||
1f4c34bd | 3683 | int |
30295c89 VM |
3684 | wmi_set_rssi_threshold_params(struct wmi_t *wmip, |
3685 | WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) | |
3686 | { | |
3687 | ||
3688 | /* Check these values are in ascending order */ | |
3689 | if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val || | |
3690 | rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val || | |
3691 | rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val || | |
3692 | rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val || | |
3693 | rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val || | |
3694 | rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val || | |
3695 | rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val || | |
3696 | rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val || | |
3697 | rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val || | |
3698 | rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) | |
3699 | { | |
3700 | return A_EINVAL; | |
3701 | } | |
3702 | ||
3703 | wmi_cache_configure_rssithreshold(wmip, rssiCmd); | |
3704 | ||
3705 | return (wmi_send_rssi_threshold_params(wmip, rssiCmd)); | |
3706 | } | |
3707 | ||
1f4c34bd | 3708 | int |
30295c89 VM |
3709 | wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd) |
3710 | { | |
3711 | void *osbuf; | |
3712 | WMI_SET_IP_CMD *cmd; | |
3713 | ||
3714 | /* Multicast address are not valid */ | |
ab3655da JP |
3715 | if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) || |
3716 | (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) { | |
30295c89 VM |
3717 | return A_EINVAL; |
3718 | } | |
3719 | ||
3720 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD)); | |
3721 | if (osbuf == NULL) { | |
3722 | return A_NO_MEMORY; | |
3723 | } | |
3724 | ||
3725 | A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD)); | |
3726 | cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf)); | |
05209262 | 3727 | memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD)); |
30295c89 VM |
3728 | |
3729 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID, | |
3730 | NO_SYNC_WMIFLAG)); | |
3731 | } | |
3732 | ||
1f4c34bd | 3733 | int |
30295c89 VM |
3734 | wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, |
3735 | WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd) | |
3736 | { | |
3737 | void *osbuf; | |
f2ab1275 | 3738 | s8 size; |
30295c89 | 3739 | WMI_SET_HOST_SLEEP_MODE_CMD *cmd; |
4853ac05 | 3740 | u16 activeTsids=0; |
ab3655da JP |
3741 | u8 streamExists=0; |
3742 | u8 i; | |
30295c89 VM |
3743 | |
3744 | if( hostModeCmd->awake == hostModeCmd->asleep) { | |
3745 | return A_EINVAL; | |
3746 | } | |
3747 | ||
3748 | size = sizeof (*cmd); | |
3749 | ||
3750 | osbuf = A_NETBUF_ALLOC(size); | |
3751 | if (osbuf == NULL) { | |
3752 | return A_NO_MEMORY; | |
3753 | } | |
3754 | ||
3755 | A_NETBUF_PUT(osbuf, size); | |
3756 | ||
3757 | cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
3758 | A_MEMZERO(cmd, size); | |
05209262 | 3759 | memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD)); |
30295c89 VM |
3760 | |
3761 | if(hostModeCmd->asleep) { | |
3762 | /* | |
3763 | * Relinquish credits from all implicitly created pstreams since when we | |
3764 | * go to sleep. If user created explicit thinstreams exists with in a | |
3765 | * fatpipe leave them intact for the user to delete | |
3766 | */ | |
3767 | LOCK_WMI(wmip); | |
3768 | streamExists = wmip->wmi_fatPipeExists; | |
3769 | UNLOCK_WMI(wmip); | |
3770 | ||
3771 | for(i=0;i< WMM_NUM_AC;i++) { | |
3772 | if (streamExists & (1<<i)) { | |
3773 | LOCK_WMI(wmip); | |
3774 | activeTsids = wmip->wmi_streamExistsForAC[i]; | |
3775 | UNLOCK_WMI(wmip); | |
3776 | /* If there are no user created thin streams delete the fatpipe */ | |
3777 | if(!activeTsids) { | |
3778 | streamExists &= ~(1<<i); | |
3779 | /*Indicate inactivity to drv layer for this fatpipe(pstream)*/ | |
3780 | A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i); | |
3781 | } | |
3782 | } | |
3783 | } | |
3784 | ||
3785 | /* Update the fatpipes that exists*/ | |
3786 | LOCK_WMI(wmip); | |
3787 | wmip->wmi_fatPipeExists = streamExists; | |
3788 | UNLOCK_WMI(wmip); | |
3789 | } | |
3790 | ||
3791 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID, | |
3792 | NO_SYNC_WMIFLAG)); | |
3793 | } | |
3794 | ||
1f4c34bd | 3795 | int |
30295c89 VM |
3796 | wmi_set_wow_mode_cmd(struct wmi_t *wmip, |
3797 | WMI_SET_WOW_MODE_CMD *wowModeCmd) | |
3798 | { | |
3799 | void *osbuf; | |
f2ab1275 | 3800 | s8 size; |
30295c89 VM |
3801 | WMI_SET_WOW_MODE_CMD *cmd; |
3802 | ||
3803 | size = sizeof (*cmd); | |
3804 | ||
3805 | osbuf = A_NETBUF_ALLOC(size); | |
3806 | if (osbuf == NULL) { | |
3807 | return A_NO_MEMORY; | |
3808 | } | |
3809 | ||
3810 | A_NETBUF_PUT(osbuf, size); | |
3811 | ||
3812 | cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
3813 | A_MEMZERO(cmd, size); | |
05209262 | 3814 | memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD)); |
30295c89 VM |
3815 | |
3816 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID, | |
3817 | NO_SYNC_WMIFLAG)); | |
3818 | ||
3819 | } | |
3820 | ||
1f4c34bd | 3821 | int |
30295c89 VM |
3822 | wmi_get_wow_list_cmd(struct wmi_t *wmip, |
3823 | WMI_GET_WOW_LIST_CMD *wowListCmd) | |
3824 | { | |
3825 | void *osbuf; | |
f2ab1275 | 3826 | s8 size; |
30295c89 VM |
3827 | WMI_GET_WOW_LIST_CMD *cmd; |
3828 | ||
3829 | size = sizeof (*cmd); | |
3830 | ||
3831 | osbuf = A_NETBUF_ALLOC(size); | |
3832 | if (osbuf == NULL) { | |
3833 | return A_NO_MEMORY; | |
3834 | } | |
3835 | ||
3836 | A_NETBUF_PUT(osbuf, size); | |
3837 | ||
3838 | cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf)); | |
3839 | A_MEMZERO(cmd, size); | |
05209262 | 3840 | memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD)); |
30295c89 VM |
3841 | |
3842 | return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID, | |
3843 | NO_SYNC_WMIFLAG)); | |
3844 | ||
3845 | } | |
3846 | ||
1f4c34bd | 3847 | static int |
ab3655da | 3848 | wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
3849 | { |
3850 | WMI_GET_WOW_LIST_REPLY *reply; | |
3851 | ||
3852 | if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) { | |
3853 | return A_EINVAL; | |
3854 | } | |
3855 | reply = (WMI_GET_WOW_LIST_REPLY *)datap; | |
3856 | ||
3857 | A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters, | |
3858 | reply); | |
3859 | ||
4f69cef0 | 3860 | return 0; |
30295c89 VM |
3861 | } |
3862 | ||
1f4c34bd | 3863 | int wmi_add_wow_pattern_cmd(struct wmi_t *wmip, |
30295c89 | 3864 | WMI_ADD_WOW_PATTERN_CMD *addWowCmd, |
ab3655da JP |
3865 | u8 *pattern, u8 *mask, |
3866 | u8 pattern_size) | |
30295c89 VM |
3867 | { |
3868 | void *osbuf; | |
f2ab1275 | 3869 | s8 size; |
30295c89 | 3870 | WMI_ADD_WOW_PATTERN_CMD *cmd; |
ab3655da | 3871 | u8 *filter_mask = NULL; |
30295c89 VM |
3872 | |
3873 | size = sizeof (*cmd); | |
3874 | ||
ab3655da | 3875 | size += ((2 * addWowCmd->filter_size)* sizeof(u8)); |
30295c89 VM |
3876 | osbuf = A_NETBUF_ALLOC(size); |
3877 | if (osbuf == NULL) { | |
3878 | return A_NO_MEMORY; | |
3879 | } | |
3880 | ||
3881 | A_NETBUF_PUT(osbuf, size); | |
3882 | ||
3883 | cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); | |
3884 | cmd->filter_list_id = addWowCmd->filter_list_id; | |
3885 | cmd->filter_offset = addWowCmd->filter_offset; | |
3886 | cmd->filter_size = addWowCmd->filter_size; | |
3887 | ||
05209262 | 3888 | memcpy(cmd->filter, pattern, addWowCmd->filter_size); |
30295c89 | 3889 | |
ab3655da | 3890 | filter_mask = (u8 *)(cmd->filter + cmd->filter_size); |
05209262 | 3891 | memcpy(filter_mask, mask, addWowCmd->filter_size); |
30295c89 VM |
3892 | |
3893 | ||
3894 | return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID, | |
3895 | NO_SYNC_WMIFLAG)); | |
3896 | } | |
3897 | ||
1f4c34bd | 3898 | int |
30295c89 VM |
3899 | wmi_del_wow_pattern_cmd(struct wmi_t *wmip, |
3900 | WMI_DEL_WOW_PATTERN_CMD *delWowCmd) | |
3901 | { | |
3902 | void *osbuf; | |
f2ab1275 | 3903 | s8 size; |
30295c89 VM |
3904 | WMI_DEL_WOW_PATTERN_CMD *cmd; |
3905 | ||
3906 | size = sizeof (*cmd); | |
3907 | ||
3908 | osbuf = A_NETBUF_ALLOC(size); | |
3909 | if (osbuf == NULL) { | |
3910 | return A_NO_MEMORY; | |
3911 | } | |
3912 | ||
3913 | A_NETBUF_PUT(osbuf, size); | |
3914 | ||
3915 | cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); | |
3916 | A_MEMZERO(cmd, size); | |
05209262 | 3917 | memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD)); |
30295c89 VM |
3918 | |
3919 | return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID, | |
3920 | NO_SYNC_WMIFLAG)); | |
3921 | ||
3922 | } | |
3923 | ||
3924 | void | |
3925 | wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) | |
3926 | { | |
3927 | SQ_THRESHOLD_PARAMS *sq_thresh = | |
3928 | &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; | |
3929 | /* | |
3930 | * Parse the command and store the threshold values here. The checks | |
3931 | * for valid values can be put here | |
3932 | */ | |
3933 | sq_thresh->weight = snrCmd->weight; | |
3934 | sq_thresh->polling_interval = snrCmd->pollTime; | |
3935 | ||
3936 | sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val; | |
3937 | sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val; | |
3938 | sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val; | |
3939 | sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val; | |
3940 | sq_thresh->upper_threshold_valid_count = 4; | |
3941 | ||
3942 | /* List sorted in descending order */ | |
3943 | sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val; | |
3944 | sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val; | |
3945 | sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val; | |
3946 | sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val; | |
3947 | sq_thresh->lower_threshold_valid_count = 4; | |
3948 | ||
3949 | if (!snr_event_value) { | |
3950 | /* | |
3951 | * Configuring the thresholds to their extremes allows the host to get an | |
3952 | * event from the target which is used for the configuring the correct | |
3953 | * thresholds | |
3954 | */ | |
ab3655da JP |
3955 | snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0]; |
3956 | snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0]; | |
30295c89 VM |
3957 | } else { |
3958 | /* | |
3959 | * In case the user issues multiple times of snr_threshold_setting, | |
3960 | * we should not use the extreames anymore, the target does not expect that. | |
3961 | */ | |
3962 | snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh, | |
3963 | sq_thresh->upper_threshold_valid_count); | |
3964 | snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh, | |
3965 | sq_thresh->lower_threshold_valid_count); | |
3966 | } | |
3967 | ||
3968 | } | |
1f4c34bd | 3969 | int |
30295c89 VM |
3970 | wmi_set_snr_threshold_params(struct wmi_t *wmip, |
3971 | WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) | |
3972 | { | |
3973 | if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val || | |
3974 | snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val || | |
3975 | snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val || | |
3976 | snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val || | |
3977 | snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val || | |
3978 | snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) | |
3979 | { | |
3980 | return A_EINVAL; | |
3981 | } | |
3982 | wmi_cache_configure_snrthreshold(wmip, snrCmd); | |
3983 | return (wmi_send_snr_threshold_params(wmip, snrCmd)); | |
3984 | } | |
3985 | ||
1f4c34bd | 3986 | int |
30295c89 VM |
3987 | wmi_clr_rssi_snr(struct wmi_t *wmip) |
3988 | { | |
3989 | void *osbuf; | |
3990 | ||
3991 | osbuf = A_NETBUF_ALLOC(sizeof(int)); | |
3992 | if (osbuf == NULL) { | |
3993 | return A_NO_MEMORY; | |
3994 | } | |
3995 | ||
3996 | return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID, | |
3997 | NO_SYNC_WMIFLAG)); | |
3998 | } | |
3999 | ||
1f4c34bd | 4000 | int |
30295c89 VM |
4001 | wmi_set_lq_threshold_params(struct wmi_t *wmip, |
4002 | WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd) | |
4003 | { | |
4004 | void *osbuf; | |
f2ab1275 | 4005 | s8 size; |
30295c89 VM |
4006 | WMI_LQ_THRESHOLD_PARAMS_CMD *cmd; |
4007 | /* These values are in ascending order */ | |
4008 | if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val || | |
4009 | lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val || | |
4010 | lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val || | |
4011 | lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val || | |
4012 | lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val || | |
4013 | lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) { | |
4014 | ||
4015 | return A_EINVAL; | |
4016 | } | |
4017 | ||
4018 | size = sizeof (*cmd); | |
4019 | ||
4020 | osbuf = A_NETBUF_ALLOC(size); | |
4021 | if (osbuf == NULL) { | |
4022 | return A_NO_MEMORY; | |
4023 | } | |
4024 | ||
4025 | A_NETBUF_PUT(osbuf, size); | |
4026 | ||
4027 | cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
4028 | A_MEMZERO(cmd, size); | |
05209262 | 4029 | memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD)); |
30295c89 VM |
4030 | |
4031 | return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID, | |
4032 | NO_SYNC_WMIFLAG)); | |
4033 | } | |
4034 | ||
1f4c34bd | 4035 | int |
e1ce2a3a | 4036 | wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask) |
30295c89 VM |
4037 | { |
4038 | void *osbuf; | |
f2ab1275 | 4039 | s8 size; |
30295c89 VM |
4040 | WMI_TARGET_ERROR_REPORT_BITMASK *cmd; |
4041 | ||
4042 | size = sizeof (*cmd); | |
4043 | ||
4044 | osbuf = A_NETBUF_ALLOC(size); | |
4045 | if (osbuf == NULL) { | |
4046 | return A_NO_MEMORY; | |
4047 | } | |
4048 | ||
4049 | A_NETBUF_PUT(osbuf, size); | |
4050 | ||
4051 | cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf)); | |
4052 | A_MEMZERO(cmd, size); | |
4053 | ||
4054 | cmd->bitmask = mask; | |
4055 | ||
4056 | return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, | |
4057 | NO_SYNC_WMIFLAG)); | |
4058 | } | |
4059 | ||
1f4c34bd | 4060 | int |
e1ce2a3a | 4061 | wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source) |
30295c89 VM |
4062 | { |
4063 | void *osbuf; | |
4064 | WMIX_HB_CHALLENGE_RESP_CMD *cmd; | |
4065 | ||
4066 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4067 | if (osbuf == NULL) { | |
4068 | return A_NO_MEMORY; | |
4069 | } | |
4070 | ||
4071 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4072 | ||
4073 | cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf)); | |
4074 | cmd->cookie = cookie; | |
4075 | cmd->source = source; | |
4076 | ||
4077 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID, | |
4078 | NO_SYNC_WMIFLAG)); | |
4079 | } | |
4080 | ||
1f4c34bd | 4081 | int |
4853ac05 JP |
4082 | wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask, |
4083 | u16 tsr, bool rep, u16 size, | |
e1ce2a3a | 4084 | u32 valid) |
30295c89 VM |
4085 | { |
4086 | void *osbuf; | |
4087 | WMIX_DBGLOG_CFG_MODULE_CMD *cmd; | |
4088 | ||
4089 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4090 | if (osbuf == NULL) { | |
4091 | return A_NO_MEMORY; | |
4092 | } | |
4093 | ||
4094 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4095 | ||
4096 | cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf)); | |
4097 | cmd->config.cfgmmask = mmask; | |
4098 | cmd->config.cfgtsr = tsr; | |
4099 | cmd->config.cfgrep = rep; | |
4100 | cmd->config.cfgsize = size; | |
4101 | cmd->config.cfgvalid = valid; | |
4102 | ||
4103 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID, | |
4104 | NO_SYNC_WMIFLAG)); | |
4105 | } | |
4106 | ||
1f4c34bd | 4107 | int |
30295c89 VM |
4108 | wmi_get_stats_cmd(struct wmi_t *wmip) |
4109 | { | |
4110 | return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID); | |
4111 | } | |
4112 | ||
1f4c34bd | 4113 | int |
ab3655da | 4114 | wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid) |
30295c89 VM |
4115 | { |
4116 | void *osbuf; | |
4117 | WMI_ADD_BAD_AP_CMD *cmd; | |
4118 | ||
4119 | if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) { | |
4120 | return A_EINVAL; | |
4121 | } | |
4122 | ||
4123 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4124 | if (osbuf == NULL) { | |
4125 | return A_NO_MEMORY; | |
4126 | } | |
4127 | ||
4128 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4129 | ||
4130 | cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); | |
4131 | cmd->badApIndex = apIndex; | |
05209262 | 4132 | memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); |
30295c89 VM |
4133 | |
4134 | return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG)); | |
4135 | } | |
4136 | ||
1f4c34bd | 4137 | int |
ab3655da | 4138 | wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex) |
30295c89 VM |
4139 | { |
4140 | void *osbuf; | |
4141 | WMI_DELETE_BAD_AP_CMD *cmd; | |
4142 | ||
4143 | if (apIndex > WMI_MAX_BAD_AP_INDEX) { | |
4144 | return A_EINVAL; | |
4145 | } | |
4146 | ||
4147 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4148 | if (osbuf == NULL) { | |
4149 | return A_NO_MEMORY; | |
4150 | } | |
4151 | ||
4152 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4153 | ||
4154 | cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); | |
4155 | cmd->badApIndex = apIndex; | |
4156 | ||
4157 | return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID, | |
4158 | NO_SYNC_WMIFLAG)); | |
4159 | } | |
4160 | ||
1f4c34bd | 4161 | int |
30295c89 VM |
4162 | wmi_abort_scan_cmd(struct wmi_t *wmip) |
4163 | { | |
4164 | return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID); | |
4165 | } | |
4166 | ||
1f4c34bd | 4167 | int |
ab3655da | 4168 | wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM) |
30295c89 VM |
4169 | { |
4170 | void *osbuf; | |
4171 | WMI_SET_TX_PWR_CMD *cmd; | |
4172 | ||
4173 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4174 | if (osbuf == NULL) { | |
4175 | return A_NO_MEMORY; | |
4176 | } | |
4177 | ||
4178 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4179 | ||
4180 | cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf)); | |
4181 | cmd->dbM = dbM; | |
4182 | ||
4183 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); | |
4184 | } | |
4185 | ||
1f4c34bd | 4186 | int |
30295c89 VM |
4187 | wmi_get_txPwr_cmd(struct wmi_t *wmip) |
4188 | { | |
4189 | return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID); | |
4190 | } | |
4191 | ||
4853ac05 | 4192 | u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass) |
30295c89 | 4193 | { |
4853ac05 | 4194 | u16 activeTsids=0; |
30295c89 VM |
4195 | |
4196 | LOCK_WMI(wmip); | |
4197 | activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; | |
4198 | UNLOCK_WMI(wmip); | |
4199 | ||
4200 | return activeTsids; | |
4201 | } | |
4202 | ||
1f4c34bd | 4203 | int |
30295c89 VM |
4204 | wmi_get_roam_tbl_cmd(struct wmi_t *wmip) |
4205 | { | |
4206 | return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID); | |
4207 | } | |
4208 | ||
1f4c34bd | 4209 | int |
ab3655da | 4210 | wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType) |
30295c89 VM |
4211 | { |
4212 | void *osbuf; | |
e1ce2a3a | 4213 | u32 size = sizeof(u8); |
30295c89 VM |
4214 | WMI_TARGET_ROAM_DATA *cmd; |
4215 | ||
4216 | osbuf = A_NETBUF_ALLOC(size); /* no payload */ | |
4217 | if (osbuf == NULL) { | |
4218 | return A_NO_MEMORY; | |
4219 | } | |
4220 | ||
4221 | A_NETBUF_PUT(osbuf, size); | |
4222 | ||
4223 | cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf)); | |
4224 | cmd->roamDataType = roamDataType; | |
4225 | ||
4226 | return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID, | |
4227 | NO_SYNC_WMIFLAG)); | |
4228 | } | |
4229 | ||
1f4c34bd | 4230 | int |
30295c89 | 4231 | wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, |
ab3655da | 4232 | u8 size) |
30295c89 VM |
4233 | { |
4234 | void *osbuf; | |
4235 | WMI_SET_ROAM_CTRL_CMD *cmd; | |
4236 | ||
4237 | osbuf = A_NETBUF_ALLOC(size); | |
4238 | if (osbuf == NULL) { | |
4239 | return A_NO_MEMORY; | |
4240 | } | |
4241 | ||
4242 | A_NETBUF_PUT(osbuf, size); | |
4243 | ||
4244 | cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf)); | |
4245 | A_MEMZERO(cmd, size); | |
4246 | ||
05209262 | 4247 | memcpy(cmd, p, size); |
30295c89 VM |
4248 | |
4249 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID, | |
4250 | NO_SYNC_WMIFLAG)); | |
4251 | } | |
4252 | ||
1f4c34bd | 4253 | int |
30295c89 VM |
4254 | wmi_set_powersave_timers_cmd(struct wmi_t *wmip, |
4255 | WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, | |
ab3655da | 4256 | u8 size) |
30295c89 VM |
4257 | { |
4258 | void *osbuf; | |
4259 | WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd; | |
4260 | ||
4261 | /* These timers can't be zero */ | |
4262 | if(!pCmd->psPollTimeout || !pCmd->triggerTimeout || | |
4263 | !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD || | |
4264 | pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) || | |
4265 | !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD || | |
4266 | pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD)) | |
4267 | return A_EINVAL; | |
4268 | ||
4269 | osbuf = A_NETBUF_ALLOC(size); | |
4270 | if (osbuf == NULL) { | |
4271 | return A_NO_MEMORY; | |
4272 | } | |
4273 | ||
4274 | A_NETBUF_PUT(osbuf, size); | |
4275 | ||
4276 | cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); | |
4277 | A_MEMZERO(cmd, size); | |
4278 | ||
05209262 | 4279 | memcpy(cmd, pCmd, size); |
30295c89 VM |
4280 | |
4281 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, | |
4282 | NO_SYNC_WMIFLAG)); | |
4283 | } | |
4284 | ||
4285 | #ifdef CONFIG_HOST_GPIO_SUPPORT | |
4286 | /* Send a command to Target to change GPIO output pins. */ | |
1f4c34bd | 4287 | int |
30295c89 | 4288 | wmi_gpio_output_set(struct wmi_t *wmip, |
e1ce2a3a JP |
4289 | u32 set_mask, |
4290 | u32 clear_mask, | |
4291 | u32 enable_mask, | |
4292 | u32 disable_mask) | |
30295c89 VM |
4293 | { |
4294 | void *osbuf; | |
4295 | WMIX_GPIO_OUTPUT_SET_CMD *output_set; | |
4296 | int size; | |
4297 | ||
4298 | size = sizeof(*output_set); | |
4299 | ||
4300 | A_DPRINTF(DBG_WMI, | |
4301 | (DBGFMT "Enter - set=0x%x clear=0x%x enb=0x%x dis=0x%x\n", DBGARG, | |
4302 | set_mask, clear_mask, enable_mask, disable_mask)); | |
4303 | ||
4304 | osbuf = A_NETBUF_ALLOC(size); | |
4305 | if (osbuf == NULL) { | |
4306 | return A_NO_MEMORY; | |
4307 | } | |
4308 | A_NETBUF_PUT(osbuf, size); | |
4309 | output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf)); | |
4310 | ||
4311 | output_set->set_mask = set_mask; | |
4312 | output_set->clear_mask = clear_mask; | |
4313 | output_set->enable_mask = enable_mask; | |
4314 | output_set->disable_mask = disable_mask; | |
4315 | ||
4316 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID, | |
4317 | NO_SYNC_WMIFLAG)); | |
4318 | } | |
4319 | ||
4320 | /* Send a command to the Target requesting state of the GPIO input pins */ | |
1f4c34bd | 4321 | int |
30295c89 VM |
4322 | wmi_gpio_input_get(struct wmi_t *wmip) |
4323 | { | |
4324 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
4325 | ||
4326 | return wmi_simple_cmd_xtnd(wmip, WMIX_GPIO_INPUT_GET_CMDID); | |
4327 | } | |
4328 | ||
4329 | /* Send a command to the Target that changes the value of a GPIO register. */ | |
1f4c34bd | 4330 | int |
30295c89 | 4331 | wmi_gpio_register_set(struct wmi_t *wmip, |
e1ce2a3a JP |
4332 | u32 gpioreg_id, |
4333 | u32 value) | |
30295c89 VM |
4334 | { |
4335 | void *osbuf; | |
4336 | WMIX_GPIO_REGISTER_SET_CMD *register_set; | |
4337 | int size; | |
4338 | ||
4339 | size = sizeof(*register_set); | |
4340 | ||
4341 | A_DPRINTF(DBG_WMI, | |
4342 | (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value)); | |
4343 | ||
4344 | osbuf = A_NETBUF_ALLOC(size); | |
4345 | if (osbuf == NULL) { | |
4346 | return A_NO_MEMORY; | |
4347 | } | |
4348 | A_NETBUF_PUT(osbuf, size); | |
4349 | register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf)); | |
4350 | ||
4351 | register_set->gpioreg_id = gpioreg_id; | |
4352 | register_set->value = value; | |
4353 | ||
4354 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID, | |
4355 | NO_SYNC_WMIFLAG)); | |
4356 | } | |
4357 | ||
4358 | /* Send a command to the Target to fetch the value of a GPIO register. */ | |
1f4c34bd | 4359 | int |
30295c89 | 4360 | wmi_gpio_register_get(struct wmi_t *wmip, |
e1ce2a3a | 4361 | u32 gpioreg_id) |
30295c89 VM |
4362 | { |
4363 | void *osbuf; | |
4364 | WMIX_GPIO_REGISTER_GET_CMD *register_get; | |
4365 | int size; | |
4366 | ||
4367 | size = sizeof(*register_get); | |
4368 | ||
4369 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id)); | |
4370 | ||
4371 | osbuf = A_NETBUF_ALLOC(size); | |
4372 | if (osbuf == NULL) { | |
4373 | return A_NO_MEMORY; | |
4374 | } | |
4375 | A_NETBUF_PUT(osbuf, size); | |
4376 | register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf)); | |
4377 | ||
4378 | register_get->gpioreg_id = gpioreg_id; | |
4379 | ||
4380 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID, | |
4381 | NO_SYNC_WMIFLAG)); | |
4382 | } | |
4383 | ||
4384 | /* Send a command to the Target acknowledging some GPIO interrupts. */ | |
1f4c34bd | 4385 | int |
30295c89 | 4386 | wmi_gpio_intr_ack(struct wmi_t *wmip, |
e1ce2a3a | 4387 | u32 ack_mask) |
30295c89 VM |
4388 | { |
4389 | void *osbuf; | |
4390 | WMIX_GPIO_INTR_ACK_CMD *intr_ack; | |
4391 | int size; | |
4392 | ||
4393 | size = sizeof(*intr_ack); | |
4394 | ||
4395 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask)); | |
4396 | ||
4397 | osbuf = A_NETBUF_ALLOC(size); | |
4398 | if (osbuf == NULL) { | |
4399 | return A_NO_MEMORY; | |
4400 | } | |
4401 | A_NETBUF_PUT(osbuf, size); | |
4402 | intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf)); | |
4403 | ||
4404 | intr_ack->ack_mask = ack_mask; | |
4405 | ||
4406 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID, | |
4407 | NO_SYNC_WMIFLAG)); | |
4408 | } | |
4409 | #endif /* CONFIG_HOST_GPIO_SUPPORT */ | |
4410 | ||
1f4c34bd | 4411 | int |
4853ac05 | 4412 | wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop, u8 eCWmin, |
ab3655da | 4413 | u8 eCWmax, u8 aifsn) |
30295c89 VM |
4414 | { |
4415 | void *osbuf; | |
4416 | WMI_SET_ACCESS_PARAMS_CMD *cmd; | |
4417 | ||
4418 | if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) || | |
4419 | (aifsn > WMI_MAX_AIFSN_ACPARAM) || (ac >= WMM_NUM_AC)) | |
4420 | { | |
4421 | return A_EINVAL; | |
4422 | } | |
4423 | ||
4424 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4425 | if (osbuf == NULL) { | |
4426 | return A_NO_MEMORY; | |
4427 | } | |
4428 | ||
4429 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4430 | ||
4431 | cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
4432 | cmd->txop = txop; | |
4433 | cmd->eCWmin = eCWmin; | |
4434 | cmd->eCWmax = eCWmax; | |
4435 | cmd->aifsn = aifsn; | |
4436 | cmd->ac = ac; | |
4437 | ||
4438 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID, | |
4439 | NO_SYNC_WMIFLAG)); | |
4440 | } | |
4441 | ||
1f4c34bd | 4442 | int |
ab3655da JP |
4443 | wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType, |
4444 | u8 trafficClass, u8 maxRetries, | |
4445 | u8 enableNotify) | |
30295c89 VM |
4446 | { |
4447 | void *osbuf; | |
4448 | WMI_SET_RETRY_LIMITS_CMD *cmd; | |
4449 | ||
4450 | if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) && | |
4451 | (frameType != DATA_FRAMETYPE)) | |
4452 | { | |
4453 | return A_EINVAL; | |
4454 | } | |
4455 | ||
4456 | if (maxRetries > WMI_MAX_RETRIES) { | |
4457 | return A_EINVAL; | |
4458 | } | |
4459 | ||
4460 | if (frameType != DATA_FRAMETYPE) { | |
4461 | trafficClass = 0; | |
4462 | } | |
4463 | ||
4464 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4465 | if (osbuf == NULL) { | |
4466 | return A_NO_MEMORY; | |
4467 | } | |
4468 | ||
4469 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4470 | ||
4471 | cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf)); | |
4472 | cmd->frameType = frameType; | |
4473 | cmd->trafficClass = trafficClass; | |
4474 | cmd->maxRetries = maxRetries; | |
4475 | cmd->enableNotify = enableNotify; | |
4476 | ||
4477 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID, | |
4478 | NO_SYNC_WMIFLAG)); | |
4479 | } | |
4480 | ||
4481 | void | |
ab3655da | 4482 | wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid) |
30295c89 VM |
4483 | { |
4484 | if (bssid != NULL) { | |
05209262 | 4485 | memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN); |
30295c89 VM |
4486 | } |
4487 | } | |
4488 | ||
1f4c34bd | 4489 | int |
ab3655da | 4490 | wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode) |
30295c89 VM |
4491 | { |
4492 | void *osbuf; | |
4493 | WMI_SET_OPT_MODE_CMD *cmd; | |
4494 | ||
4495 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4496 | if (osbuf == NULL) { | |
4497 | return A_NO_MEMORY; | |
4498 | } | |
4499 | ||
4500 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4501 | ||
4502 | cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
4503 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4504 | cmd->optMode = optMode; | |
4505 | ||
4506 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID, | |
4507 | SYNC_BOTH_WMIFLAG)); | |
4508 | } | |
4509 | ||
1f4c34bd | 4510 | int |
30295c89 | 4511 | wmi_opt_tx_frame_cmd(struct wmi_t *wmip, |
ab3655da JP |
4512 | u8 frmType, |
4513 | u8 *dstMacAddr, | |
4514 | u8 *bssid, | |
4853ac05 | 4515 | u16 optIEDataLen, |
ab3655da | 4516 | u8 *optIEData) |
30295c89 VM |
4517 | { |
4518 | void *osbuf; | |
4519 | WMI_OPT_TX_FRAME_CMD *cmd; | |
4520 | osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd)); | |
4521 | if (osbuf == NULL) { | |
4522 | return A_NO_MEMORY; | |
4523 | } | |
4524 | ||
4525 | A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd))); | |
4526 | ||
4527 | cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf)); | |
4528 | A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1)); | |
4529 | ||
4530 | cmd->frmType = frmType; | |
4531 | cmd->optIEDataLen = optIEDataLen; | |
ab3655da | 4532 | //cmd->optIEData = (u8 *)((int)cmd + sizeof(*cmd)); |
05209262 LR |
4533 | memcpy(cmd->bssid, bssid, sizeof(cmd->bssid)); |
4534 | memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr)); | |
4535 | memcpy(&cmd->optIEData[0], optIEData, optIEDataLen); | |
30295c89 VM |
4536 | |
4537 | return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID, | |
4538 | NO_SYNC_WMIFLAG)); | |
4539 | } | |
4540 | ||
1f4c34bd | 4541 | int |
4853ac05 | 4542 | wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl) |
30295c89 VM |
4543 | { |
4544 | void *osbuf; | |
4545 | WMI_BEACON_INT_CMD *cmd; | |
4546 | ||
4547 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4548 | if (osbuf == NULL) { | |
4549 | return A_NO_MEMORY; | |
4550 | } | |
4551 | ||
4552 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4553 | ||
4554 | cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf)); | |
4555 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4556 | cmd->beaconInterval = intvl; | |
4557 | ||
4558 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID, | |
4559 | NO_SYNC_WMIFLAG)); | |
4560 | } | |
4561 | ||
4562 | ||
1f4c34bd | 4563 | int |
4853ac05 | 4564 | wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize) |
30295c89 VM |
4565 | { |
4566 | void *osbuf; | |
4567 | WMI_SET_VOICE_PKT_SIZE_CMD *cmd; | |
4568 | ||
4569 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4570 | if (osbuf == NULL) { | |
4571 | return A_NO_MEMORY; | |
4572 | } | |
4573 | ||
4574 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4575 | ||
4576 | cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf)); | |
4577 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4578 | cmd->voicePktSize = voicePktSize; | |
4579 | ||
4580 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID, | |
4581 | NO_SYNC_WMIFLAG)); | |
4582 | } | |
4583 | ||
4584 | ||
1f4c34bd | 4585 | int |
ab3655da | 4586 | wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen) |
30295c89 VM |
4587 | { |
4588 | void *osbuf; | |
4589 | WMI_SET_MAX_SP_LEN_CMD *cmd; | |
4590 | ||
4591 | /* maxSPLen is a two-bit value. If user trys to set anything | |
4592 | * other than this, then its invalid | |
4593 | */ | |
4594 | if(maxSPLen & ~0x03) | |
4595 | return A_EINVAL; | |
4596 | ||
4597 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4598 | if (osbuf == NULL) { | |
4599 | return A_NO_MEMORY; | |
4600 | } | |
4601 | ||
4602 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4603 | ||
4604 | cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf)); | |
4605 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4606 | cmd->maxSPLen = maxSPLen; | |
4607 | ||
4608 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID, | |
4609 | NO_SYNC_WMIFLAG)); | |
4610 | } | |
4611 | ||
ab3655da JP |
4612 | u8 wmi_determine_userPriority( |
4613 | u8 *pkt, | |
e1ce2a3a | 4614 | u32 layer2Pri) |
30295c89 | 4615 | { |
ab3655da | 4616 | u8 ipPri; |
30295c89 VM |
4617 | iphdr *ipHdr = (iphdr *)pkt; |
4618 | ||
4619 | /* Determine IPTOS priority */ | |
4620 | /* | |
4621 | * IP Tos format : | |
4622 | * (Refer Pg 57 WMM-test-plan-v1.2) | |
4623 | * IP-TOS - 8bits | |
4624 | * : DSCP(6-bits) ECN(2-bits) | |
4625 | * : DSCP - P2 P1 P0 X X X | |
4626 | * where (P2 P1 P0) form 802.1D | |
4627 | */ | |
4628 | ipPri = ipHdr->ip_tos >> 5; | |
4629 | ipPri &= 0x7; | |
4630 | ||
4631 | if ((layer2Pri & 0x7) > ipPri) | |
ab3655da | 4632 | return ((u8)layer2Pri & 0x7); |
30295c89 VM |
4633 | else |
4634 | return ipPri; | |
4635 | } | |
4636 | ||
ab3655da | 4637 | u8 convert_userPriority_to_trafficClass(u8 userPriority) |
30295c89 VM |
4638 | { |
4639 | return (up_to_ac[userPriority & 0x7]); | |
4640 | } | |
4641 | ||
ab3655da | 4642 | u8 wmi_get_power_mode_cmd(struct wmi_t *wmip) |
30295c89 VM |
4643 | { |
4644 | return wmip->wmi_powerMode; | |
4645 | } | |
4646 | ||
1f4c34bd | 4647 | int |
8205669a | 4648 | wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance) |
30295c89 | 4649 | { |
4f69cef0 | 4650 | int ret = 0; |
30295c89 VM |
4651 | |
4652 | #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0) | |
4653 | #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0 | |
4654 | #define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0 | |
4655 | #define TSPEC_DELAY_BOUND_ATHEROS_DEF 0 | |
4656 | #define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0 | |
4657 | #define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */ | |
4658 | ||
4659 | /* Verify TSPEC params for ATHEROS compliance */ | |
4660 | if(tspecCompliance == ATHEROS_COMPLIANCE) { | |
4661 | if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) || | |
4662 | (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) || | |
4663 | (pCmd->minDataRate != pCmd->meanDataRate) || | |
4664 | (pCmd->minDataRate != pCmd->peakDataRate) || | |
4665 | (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) || | |
4666 | (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) || | |
4667 | (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) || | |
4668 | (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) { | |
4669 | ||
4670 | A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG)); | |
4671 | //A_PRINTF("%s: Invalid TSPEC params\n", __func__); | |
4672 | ret = A_EINVAL; | |
4673 | } | |
4674 | } | |
4675 | ||
4676 | return ret; | |
4677 | } | |
4678 | ||
4679 | #ifdef CONFIG_HOST_TCMD_SUPPORT | |
1f4c34bd | 4680 | static int |
ab3655da | 4681 | wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
4682 | { |
4683 | ||
4684 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
4685 | ||
4686 | A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len); | |
4687 | ||
4f69cef0 | 4688 | return 0; |
30295c89 VM |
4689 | } |
4690 | ||
4691 | #endif /* CONFIG_HOST_TCMD_SUPPORT*/ | |
4692 | ||
1f4c34bd | 4693 | int |
ab3655da | 4694 | wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode) |
30295c89 VM |
4695 | { |
4696 | void *osbuf; | |
4697 | WMI_SET_AUTH_MODE_CMD *cmd; | |
4698 | ||
4699 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4700 | if (osbuf == NULL) { | |
4701 | return A_NO_MEMORY; | |
4702 | } | |
4703 | ||
4704 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4705 | ||
4706 | cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
4707 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4708 | cmd->mode = mode; | |
4709 | ||
4710 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID, | |
4711 | NO_SYNC_WMIFLAG)); | |
4712 | } | |
4713 | ||
1f4c34bd | 4714 | int |
ab3655da | 4715 | wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode) |
30295c89 VM |
4716 | { |
4717 | void *osbuf; | |
4718 | WMI_SET_REASSOC_MODE_CMD *cmd; | |
4719 | ||
4720 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4721 | if (osbuf == NULL) { | |
4722 | return A_NO_MEMORY; | |
4723 | } | |
4724 | ||
4725 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4726 | ||
4727 | cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
4728 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4729 | cmd->mode = mode; | |
4730 | ||
4731 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID, | |
4732 | NO_SYNC_WMIFLAG)); | |
4733 | } | |
4734 | ||
1f4c34bd | 4735 | int |
ab3655da | 4736 | wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy) |
30295c89 VM |
4737 | { |
4738 | void *osbuf; | |
4739 | WMI_SET_LPREAMBLE_CMD *cmd; | |
4740 | ||
4741 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4742 | if (osbuf == NULL) { | |
4743 | return A_NO_MEMORY; | |
4744 | } | |
4745 | ||
4746 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4747 | ||
4748 | cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf)); | |
4749 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4750 | cmd->status = status; | |
4751 | cmd->preamblePolicy = preamblePolicy; | |
4752 | ||
4753 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID, | |
4754 | NO_SYNC_WMIFLAG)); | |
4755 | } | |
4756 | ||
1f4c34bd | 4757 | int |
4853ac05 | 4758 | wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold) |
30295c89 VM |
4759 | { |
4760 | void *osbuf; | |
4761 | WMI_SET_RTS_CMD *cmd; | |
4762 | ||
4763 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4764 | if (osbuf == NULL) { | |
4765 | return A_NO_MEMORY; | |
4766 | } | |
4767 | ||
4768 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4769 | ||
4770 | cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf)); | |
4771 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4772 | cmd->threshold = threshold; | |
4773 | ||
4774 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID, | |
4775 | NO_SYNC_WMIFLAG)); | |
4776 | } | |
4777 | ||
1f4c34bd | 4778 | int |
30295c89 VM |
4779 | wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status) |
4780 | { | |
4781 | void *osbuf; | |
4782 | WMI_SET_WMM_CMD *cmd; | |
4783 | ||
4784 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4785 | if (osbuf == NULL) { | |
4786 | return A_NO_MEMORY; | |
4787 | } | |
4788 | ||
4789 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4790 | ||
4791 | cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf)); | |
4792 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4793 | cmd->status = status; | |
4794 | ||
4795 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID, | |
4796 | NO_SYNC_WMIFLAG)); | |
4797 | ||
4798 | } | |
4799 | ||
1f4c34bd | 4800 | int |
ab3655da | 4801 | wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status) |
30295c89 VM |
4802 | { |
4803 | void *osbuf; | |
4804 | WMI_SET_QOS_SUPP_CMD *cmd; | |
4805 | ||
4806 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4807 | if (osbuf == NULL) { | |
4808 | return A_NO_MEMORY; | |
4809 | } | |
4810 | ||
4811 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4812 | ||
4813 | cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf)); | |
4814 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4815 | cmd->status = status; | |
4816 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_CMDID, | |
4817 | NO_SYNC_WMIFLAG)); | |
4818 | } | |
4819 | ||
4820 | ||
1f4c34bd | 4821 | int |
30295c89 VM |
4822 | wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg) |
4823 | { | |
4824 | void *osbuf; | |
4825 | WMI_SET_WMM_TXOP_CMD *cmd; | |
4826 | ||
4827 | if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) ) | |
4828 | return A_EINVAL; | |
4829 | ||
4830 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4831 | if (osbuf == NULL) { | |
4832 | return A_NO_MEMORY; | |
4833 | } | |
4834 | ||
4835 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4836 | ||
4837 | cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf)); | |
4838 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4839 | cmd->txopEnable = cfg; | |
4840 | ||
4841 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID, | |
4842 | NO_SYNC_WMIFLAG)); | |
4843 | ||
4844 | } | |
4845 | ||
1f4c34bd | 4846 | int |
d8cb316f | 4847 | wmi_set_country(struct wmi_t *wmip, u8 *countryCode) |
30295c89 VM |
4848 | { |
4849 | void *osbuf; | |
4850 | WMI_AP_SET_COUNTRY_CMD *cmd; | |
4851 | ||
4852 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4853 | if (osbuf == NULL) { | |
4854 | return A_NO_MEMORY; | |
4855 | } | |
4856 | ||
4857 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4858 | ||
4859 | cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf)); | |
4860 | A_MEMZERO(cmd, sizeof(*cmd)); | |
05209262 | 4861 | memcpy(cmd->countryCode,countryCode,3); |
30295c89 VM |
4862 | |
4863 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID, | |
4864 | NO_SYNC_WMIFLAG)); | |
4865 | } | |
4866 | ||
4867 | #ifdef CONFIG_HOST_TCMD_SUPPORT | |
4868 | /* WMI layer doesn't need to know the data type of the test cmd. | |
4869 | This would be beneficial for customers like Qualcomm, who might | |
25985edc | 4870 | have different test command requirements from different manufacturers |
30295c89 | 4871 | */ |
1f4c34bd | 4872 | int |
e1ce2a3a | 4873 | wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len) |
30295c89 VM |
4874 | { |
4875 | void *osbuf; | |
4876 | char *data; | |
4877 | ||
4878 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
4879 | ||
4880 | osbuf= A_NETBUF_ALLOC(len); | |
4881 | if(osbuf == NULL) | |
4882 | { | |
4883 | return A_NO_MEMORY; | |
4884 | } | |
4885 | A_NETBUF_PUT(osbuf, len); | |
4886 | data = A_NETBUF_DATA(osbuf); | |
05209262 | 4887 | memcpy(data, buf, len); |
30295c89 VM |
4888 | |
4889 | return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID, | |
4890 | NO_SYNC_WMIFLAG)); | |
4891 | } | |
4892 | ||
4893 | #endif | |
4894 | ||
1f4c34bd | 4895 | int |
ab3655da | 4896 | wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status) |
30295c89 VM |
4897 | { |
4898 | void *osbuf; | |
4899 | WMI_SET_BT_STATUS_CMD *cmd; | |
4900 | ||
4901 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status)); | |
4902 | ||
4903 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4904 | if (osbuf == NULL) { | |
4905 | return A_NO_MEMORY; | |
4906 | } | |
4907 | ||
4908 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4909 | ||
4910 | cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); | |
4911 | A_MEMZERO(cmd, sizeof(*cmd)); | |
4912 | cmd->streamType = streamType; | |
4913 | cmd->status = status; | |
4914 | ||
4915 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID, | |
4916 | NO_SYNC_WMIFLAG)); | |
4917 | } | |
4918 | ||
1f4c34bd | 4919 | int |
30295c89 VM |
4920 | wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd) |
4921 | { | |
4922 | void *osbuf; | |
4923 | WMI_SET_BT_PARAMS_CMD* alloc_cmd; | |
4924 | ||
4925 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType)); | |
4926 | ||
4927 | if (cmd->paramType == BT_PARAM_SCO) { | |
4928 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger, | |
4929 | cmd->info.scoParams.dataResponseTimeout, | |
4930 | cmd->info.scoParams.stompScoRules, | |
4931 | cmd->info.scoParams.scoOptFlags, | |
4932 | cmd->info.scoParams.stompDutyCyleVal, | |
4933 | cmd->info.scoParams.stompDutyCyleMaxVal, | |
4934 | cmd->info.scoParams.psPollLatencyFraction, | |
4935 | cmd->info.scoParams.noSCOSlots, | |
4936 | cmd->info.scoParams.noIdleSlots, | |
4937 | cmd->info.scoParams.scoOptOffRssi, | |
4938 | cmd->info.scoParams.scoOptOnRssi, | |
4939 | cmd->info.scoParams.scoOptRtsCount)); | |
4940 | } | |
4941 | else if (cmd->paramType == BT_PARAM_A2DP) { | |
4942 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit, | |
4943 | cmd->info.a2dpParams.a2dpBurstCntMin, | |
4944 | cmd->info.a2dpParams.a2dpDataRespTimeout, | |
4945 | cmd->info.a2dpParams.a2dpOptFlags, | |
4946 | cmd->info.a2dpParams.isCoLocatedBtRoleMaster, | |
4947 | cmd->info.a2dpParams.a2dpOptOffRssi, | |
4948 | cmd->info.a2dpParams.a2dpOptOnRssi, | |
4949 | cmd->info.a2dpParams.a2dpOptRtsCount)); | |
4950 | } | |
4951 | else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) { | |
4952 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType)); | |
4953 | } | |
4954 | else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) { | |
4955 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev)); | |
4956 | } | |
4957 | else if (cmd->paramType == BT_PARAM_ACLCOEX) { | |
4958 | AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime, | |
4959 | cmd->info.aclCoexParams.aclBtMediumUsageTime, | |
4960 | cmd->info.aclCoexParams.aclDataRespTimeout)); | |
4961 | } | |
4962 | else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) { | |
4963 | A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG)); | |
4964 | } | |
4965 | ||
4966 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4967 | if (osbuf == NULL) { | |
4968 | return A_NO_MEMORY; | |
4969 | } | |
4970 | ||
4971 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4972 | ||
4973 | alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
4974 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 4975 | memcpy(alloc_cmd, cmd, sizeof(*cmd)); |
30295c89 VM |
4976 | |
4977 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID, | |
4978 | NO_SYNC_WMIFLAG)); | |
4979 | } | |
4980 | ||
1f4c34bd | 4981 | int |
30295c89 VM |
4982 | wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd) |
4983 | { | |
4984 | void *osbuf; | |
4985 | WMI_SET_BTCOEX_FE_ANT_CMD *alloc_cmd; | |
4986 | ||
4987 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
4988 | if (osbuf == NULL) { | |
4989 | return A_NO_MEMORY; | |
4990 | } | |
4991 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
4992 | alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf)); | |
4993 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 4994 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); |
30295c89 VM |
4995 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID, |
4996 | NO_SYNC_WMIFLAG)); | |
4997 | ||
4998 | } | |
4999 | ||
5000 | ||
1f4c34bd | 5001 | int |
30295c89 VM |
5002 | wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip, |
5003 | WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd) | |
5004 | { | |
5005 | void *osbuf; | |
5006 | WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *alloc_cmd; | |
5007 | ||
5008 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5009 | if (osbuf == NULL) { | |
5010 | return A_NO_MEMORY; | |
5011 | } | |
5012 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5013 | alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf)); | |
5014 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5015 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); |
30295c89 VM |
5016 | A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev); |
5017 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, | |
5018 | NO_SYNC_WMIFLAG)); | |
5019 | ||
5020 | } | |
5021 | ||
1f4c34bd | 5022 | int |
30295c89 VM |
5023 | wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip, |
5024 | WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd) | |
5025 | { | |
5026 | void *osbuf; | |
5027 | WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *alloc_cmd; | |
5028 | ||
5029 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5030 | if (osbuf == NULL) { | |
5031 | return A_NO_MEMORY; | |
5032 | } | |
5033 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5034 | alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5035 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5036 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD)); |
30295c89 VM |
5037 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, |
5038 | NO_SYNC_WMIFLAG)); | |
5039 | ||
5040 | } | |
5041 | ||
1f4c34bd | 5042 | int |
30295c89 VM |
5043 | wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip, |
5044 | WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd) | |
5045 | { | |
5046 | void *osbuf; | |
5047 | WMI_SET_BTCOEX_SCO_CONFIG_CMD *alloc_cmd; | |
5048 | ||
5049 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5050 | if (osbuf == NULL) { | |
5051 | return A_NO_MEMORY; | |
5052 | } | |
5053 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5054 | alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5055 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5056 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); |
30295c89 VM |
5057 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID , |
5058 | NO_SYNC_WMIFLAG)); | |
5059 | ||
5060 | } | |
5061 | ||
1f4c34bd | 5062 | int |
30295c89 VM |
5063 | wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip, |
5064 | WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd) | |
5065 | { | |
5066 | void *osbuf; | |
5067 | WMI_SET_BTCOEX_A2DP_CONFIG_CMD *alloc_cmd; | |
5068 | ||
5069 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5070 | if (osbuf == NULL) { | |
5071 | return A_NO_MEMORY; | |
5072 | } | |
5073 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5074 | alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5075 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5076 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); |
30295c89 VM |
5077 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID , |
5078 | NO_SYNC_WMIFLAG)); | |
5079 | ||
5080 | } | |
5081 | ||
1f4c34bd | 5082 | int |
30295c89 VM |
5083 | wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, |
5084 | WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd) | |
5085 | { | |
5086 | void *osbuf; | |
5087 | WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *alloc_cmd; | |
5088 | ||
5089 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5090 | if (osbuf == NULL) { | |
5091 | return A_NO_MEMORY; | |
5092 | } | |
5093 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5094 | alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5095 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5096 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); |
30295c89 VM |
5097 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID , |
5098 | NO_SYNC_WMIFLAG)); | |
5099 | ||
5100 | } | |
5101 | ||
1f4c34bd | 5102 | int |
30295c89 VM |
5103 | wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd) |
5104 | { | |
5105 | void *osbuf; | |
5106 | WMI_SET_BTCOEX_DEBUG_CMD *alloc_cmd; | |
5107 | ||
5108 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5109 | if (osbuf == NULL) { | |
5110 | return A_NO_MEMORY; | |
5111 | } | |
5112 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5113 | alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5114 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5115 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD)); |
30295c89 VM |
5116 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID , |
5117 | NO_SYNC_WMIFLAG)); | |
5118 | ||
5119 | } | |
5120 | ||
1f4c34bd | 5121 | int |
30295c89 VM |
5122 | wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip, |
5123 | WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd) | |
5124 | { | |
5125 | void *osbuf; | |
5126 | WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *alloc_cmd; | |
5127 | ||
5128 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5129 | if (osbuf == NULL) { | |
5130 | return A_NO_MEMORY; | |
5131 | } | |
5132 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5133 | alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); | |
5134 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5135 | memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD)); |
30295c89 VM |
5136 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID , |
5137 | NO_SYNC_WMIFLAG)); | |
5138 | ||
5139 | } | |
5140 | ||
1f4c34bd | 5141 | int |
30295c89 VM |
5142 | wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd) |
5143 | { | |
5144 | void *osbuf; | |
5145 | WMI_GET_BTCOEX_CONFIG_CMD *alloc_cmd; | |
5146 | ||
5147 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5148 | if (osbuf == NULL) { | |
5149 | return A_NO_MEMORY; | |
5150 | } | |
5151 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5152 | alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5153 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5154 | memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD)); |
30295c89 VM |
5155 | return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID , |
5156 | NO_SYNC_WMIFLAG)); | |
5157 | ||
5158 | } | |
5159 | ||
1f4c34bd | 5160 | int |
30295c89 VM |
5161 | wmi_get_btcoex_stats_cmd(struct wmi_t *wmip) |
5162 | { | |
5163 | ||
5164 | return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID); | |
5165 | ||
5166 | } | |
5167 | ||
1f4c34bd | 5168 | int |
30295c89 VM |
5169 | wmi_get_keepalive_configured(struct wmi_t *wmip) |
5170 | { | |
5171 | void *osbuf; | |
5172 | WMI_GET_KEEPALIVE_CMD *cmd; | |
5173 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5174 | if (osbuf == NULL) { | |
5175 | return A_NO_MEMORY; | |
5176 | } | |
5177 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5178 | cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); | |
5179 | A_MEMZERO(cmd, sizeof(*cmd)); | |
5180 | return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID, | |
5181 | NO_SYNC_WMIFLAG)); | |
5182 | } | |
5183 | ||
ab3655da | 5184 | u8 wmi_get_keepalive_cmd(struct wmi_t *wmip) |
30295c89 VM |
5185 | { |
5186 | return wmip->wmi_keepaliveInterval; | |
5187 | } | |
5188 | ||
1f4c34bd | 5189 | int |
ab3655da | 5190 | wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval) |
30295c89 VM |
5191 | { |
5192 | void *osbuf; | |
5193 | WMI_SET_KEEPALIVE_CMD *cmd; | |
5194 | ||
5195 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5196 | if (osbuf == NULL) { | |
5197 | return A_NO_MEMORY; | |
5198 | } | |
5199 | ||
5200 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5201 | ||
5202 | cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); | |
5203 | A_MEMZERO(cmd, sizeof(*cmd)); | |
5204 | cmd->keepaliveInterval = keepaliveInterval; | |
5205 | wmip->wmi_keepaliveInterval = keepaliveInterval; | |
5206 | ||
5207 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID, | |
5208 | NO_SYNC_WMIFLAG)); | |
5209 | } | |
5210 | ||
1f4c34bd | 5211 | int |
e1ce2a3a | 5212 | wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer) |
30295c89 VM |
5213 | { |
5214 | void *osbuf; | |
5215 | WMI_SET_PARAMS_CMD *cmd; | |
5216 | ||
5217 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length); | |
5218 | if (osbuf == NULL) { | |
5219 | return A_NO_MEMORY; | |
5220 | } | |
5221 | ||
5222 | A_NETBUF_PUT(osbuf, sizeof(*cmd) + length); | |
5223 | ||
5224 | cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
5225 | A_MEMZERO(cmd, sizeof(*cmd)); | |
5226 | cmd->opcode = opcode; | |
5227 | cmd->length = length; | |
05209262 | 5228 | memcpy(cmd->buffer, buffer, length); |
30295c89 VM |
5229 | |
5230 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID, | |
5231 | NO_SYNC_WMIFLAG)); | |
5232 | } | |
5233 | ||
5234 | ||
1f4c34bd | 5235 | int |
ab3655da | 5236 | wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4) |
30295c89 VM |
5237 | { |
5238 | void *osbuf; | |
5239 | WMI_SET_MCAST_FILTER_CMD *cmd; | |
5240 | ||
5241 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5242 | if (osbuf == NULL) { | |
5243 | return A_NO_MEMORY; | |
5244 | } | |
5245 | ||
5246 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5247 | ||
5248 | cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); | |
5249 | cmd->multicast_mac[0] = 0x01; | |
5250 | cmd->multicast_mac[1] = 0x00; | |
5251 | cmd->multicast_mac[2] = 0x5e; | |
5252 | cmd->multicast_mac[3] = dot2&0x7F; | |
5253 | cmd->multicast_mac[4] = dot3; | |
5254 | cmd->multicast_mac[5] = dot4; | |
5255 | ||
5256 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID, | |
5257 | NO_SYNC_WMIFLAG)); | |
5258 | } | |
5259 | ||
5260 | ||
1f4c34bd | 5261 | int |
ab3655da | 5262 | wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4) |
30295c89 VM |
5263 | { |
5264 | void *osbuf; | |
5265 | WMI_SET_MCAST_FILTER_CMD *cmd; | |
5266 | ||
5267 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5268 | if (osbuf == NULL) { | |
5269 | return A_NO_MEMORY; | |
5270 | } | |
5271 | ||
5272 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5273 | ||
5274 | cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); | |
5275 | cmd->multicast_mac[0] = 0x01; | |
5276 | cmd->multicast_mac[1] = 0x00; | |
5277 | cmd->multicast_mac[2] = 0x5e; | |
5278 | cmd->multicast_mac[3] = dot2&0x7F; | |
5279 | cmd->multicast_mac[4] = dot3; | |
5280 | cmd->multicast_mac[5] = dot4; | |
5281 | ||
5282 | return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID, | |
5283 | NO_SYNC_WMIFLAG)); | |
5284 | } | |
5285 | ||
1f4c34bd | 5286 | int |
ab3655da | 5287 | wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable) |
30295c89 VM |
5288 | { |
5289 | void *osbuf; | |
5290 | WMI_MCAST_FILTER_CMD *cmd; | |
5291 | ||
5292 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5293 | if (osbuf == NULL) { | |
5294 | return A_NO_MEMORY; | |
5295 | } | |
5296 | ||
5297 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5298 | ||
5299 | cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); | |
5300 | cmd->enable = enable; | |
5301 | ||
5302 | return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_CMDID, | |
5303 | NO_SYNC_WMIFLAG)); | |
5304 | } | |
5305 | ||
1f4c34bd | 5306 | int |
ab3655da JP |
5307 | wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen, |
5308 | u8 *ieInfo) | |
30295c89 VM |
5309 | { |
5310 | void *osbuf; | |
5311 | WMI_SET_APPIE_CMD *cmd; | |
4853ac05 | 5312 | u16 cmdLen; |
30295c89 VM |
5313 | |
5314 | cmdLen = sizeof(*cmd) + ieLen - 1; | |
5315 | osbuf = A_NETBUF_ALLOC(cmdLen); | |
5316 | if (osbuf == NULL) { | |
5317 | return A_NO_MEMORY; | |
5318 | } | |
5319 | ||
5320 | A_NETBUF_PUT(osbuf, cmdLen); | |
5321 | ||
5322 | cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf)); | |
5323 | A_MEMZERO(cmd, cmdLen); | |
5324 | ||
5325 | cmd->mgmtFrmType = mgmtFrmType; | |
5326 | cmd->ieLen = ieLen; | |
05209262 | 5327 | memcpy(cmd->ieInfo, ieInfo, ieLen); |
30295c89 VM |
5328 | |
5329 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG)); | |
5330 | } | |
5331 | ||
1f4c34bd | 5332 | int |
4853ac05 | 5333 | wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen) |
30295c89 VM |
5334 | { |
5335 | void *osbuf; | |
ab3655da | 5336 | u8 *data; |
30295c89 VM |
5337 | |
5338 | osbuf = A_NETBUF_ALLOC(dataLen); | |
5339 | if (osbuf == NULL) { | |
5340 | return A_NO_MEMORY; | |
5341 | } | |
5342 | ||
5343 | A_NETBUF_PUT(osbuf, dataLen); | |
5344 | ||
5345 | data = A_NETBUF_DATA(osbuf); | |
5346 | ||
05209262 | 5347 | memcpy(data, cmd, dataLen); |
30295c89 VM |
5348 | |
5349 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG)); | |
5350 | } | |
5351 | ||
f68057e6 | 5352 | s32 wmi_get_rate(s8 rateindex) |
30295c89 VM |
5353 | { |
5354 | if (rateindex == RATE_AUTO) { | |
5355 | return 0; | |
5356 | } else { | |
e1ce2a3a | 5357 | return(wmi_rateTable[(u32) rateindex][0]); |
30295c89 VM |
5358 | } |
5359 | } | |
5360 | ||
5361 | void | |
5362 | wmi_node_return (struct wmi_t *wmip, bss_t *bss) | |
5363 | { | |
5364 | if (NULL != bss) | |
5365 | { | |
5366 | wlan_node_return (&wmip->wmi_scan_table, bss); | |
5367 | } | |
5368 | } | |
5369 | ||
5370 | void | |
e1ce2a3a | 5371 | wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge) |
30295c89 VM |
5372 | { |
5373 | wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge); | |
5374 | } | |
5375 | ||
5376 | bss_t * | |
d8cb316f | 5377 | wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid, |
e1ce2a3a | 5378 | u32 ssidLength, bool bIsWPA2, bool bMatchSSID) |
30295c89 VM |
5379 | { |
5380 | bss_t *node = NULL; | |
5381 | node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid, | |
5382 | ssidLength, bIsWPA2, bMatchSSID); | |
5383 | return node; | |
5384 | } | |
5385 | ||
5386 | ||
5387 | #ifdef THREAD_X | |
5388 | void | |
5389 | wmi_refresh_scan_table (struct wmi_t *wmip) | |
5390 | { | |
5391 | wlan_refresh_inactive_nodes (&wmip->wmi_scan_table); | |
5392 | } | |
5393 | #endif | |
5394 | ||
5395 | void | |
5396 | wmi_free_allnodes(struct wmi_t *wmip) | |
5397 | { | |
5398 | wlan_free_allnodes(&wmip->wmi_scan_table); | |
5399 | } | |
5400 | ||
5401 | bss_t * | |
ab3655da | 5402 | wmi_find_node(struct wmi_t *wmip, const u8 *macaddr) |
30295c89 VM |
5403 | { |
5404 | bss_t *ni=NULL; | |
5405 | ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); | |
5406 | return ni; | |
5407 | } | |
5408 | ||
5409 | void | |
ab3655da | 5410 | wmi_free_node(struct wmi_t *wmip, const u8 *macaddr) |
30295c89 VM |
5411 | { |
5412 | bss_t *ni=NULL; | |
5413 | ||
5414 | ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); | |
5415 | if (ni != NULL) { | |
5416 | wlan_node_reclaim(&wmip->wmi_scan_table, ni); | |
5417 | } | |
5418 | ||
5419 | return; | |
5420 | } | |
5421 | ||
1f4c34bd | 5422 | int |
30295c89 | 5423 | wmi_dset_open_reply(struct wmi_t *wmip, |
e1ce2a3a JP |
5424 | u32 status, |
5425 | u32 access_cookie, | |
5426 | u32 dset_size, | |
5427 | u32 dset_version, | |
5428 | u32 targ_handle, | |
5429 | u32 targ_reply_fn, | |
5430 | u32 targ_reply_arg) | |
30295c89 VM |
5431 | { |
5432 | void *osbuf; | |
5433 | WMIX_DSETOPEN_REPLY_CMD *open_reply; | |
5434 | ||
5435 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%lx\n", DBGARG, (unsigned long)wmip)); | |
5436 | ||
5437 | osbuf = A_NETBUF_ALLOC(sizeof(*open_reply)); | |
5438 | if (osbuf == NULL) { | |
5439 | return A_NO_MEMORY; | |
5440 | } | |
5441 | ||
5442 | A_NETBUF_PUT(osbuf, sizeof(*open_reply)); | |
5443 | open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); | |
5444 | ||
5445 | open_reply->status = status; | |
5446 | open_reply->targ_dset_handle = targ_handle; | |
5447 | open_reply->targ_reply_fn = targ_reply_fn; | |
5448 | open_reply->targ_reply_arg = targ_reply_arg; | |
5449 | open_reply->access_cookie = access_cookie; | |
5450 | open_reply->size = dset_size; | |
5451 | open_reply->version = dset_version; | |
5452 | ||
5453 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID, | |
5454 | NO_SYNC_WMIFLAG)); | |
5455 | } | |
5456 | ||
1f4c34bd | 5457 | static int |
e1ce2a3a | 5458 | wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) |
30295c89 VM |
5459 | { |
5460 | WMI_PMKID_LIST_REPLY *reply; | |
e1ce2a3a | 5461 | u32 expected_len; |
30295c89 VM |
5462 | |
5463 | if (len < sizeof(WMI_PMKID_LIST_REPLY)) { | |
5464 | return A_EINVAL; | |
5465 | } | |
5466 | reply = (WMI_PMKID_LIST_REPLY *)datap; | |
5467 | expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN; | |
5468 | ||
5469 | if (len < expected_len) { | |
5470 | return A_EINVAL; | |
5471 | } | |
5472 | ||
5473 | A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID, | |
5474 | reply->pmkidList, reply->bssidList[0]); | |
5475 | ||
4f69cef0 | 5476 | return 0; |
30295c89 VM |
5477 | } |
5478 | ||
5479 | ||
1f4c34bd | 5480 | static int |
e1ce2a3a | 5481 | wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) |
30295c89 VM |
5482 | { |
5483 | WMI_SET_PARAMS_REPLY *reply; | |
5484 | ||
5485 | if (len < sizeof(WMI_SET_PARAMS_REPLY)) { | |
5486 | return A_EINVAL; | |
5487 | } | |
5488 | reply = (WMI_SET_PARAMS_REPLY *)datap; | |
5489 | ||
4f69cef0 | 5490 | if (0 == reply->status) |
30295c89 VM |
5491 | { |
5492 | ||
5493 | } | |
5494 | else | |
5495 | { | |
5496 | ||
5497 | } | |
5498 | ||
4f69cef0 | 5499 | return 0; |
30295c89 VM |
5500 | } |
5501 | ||
5502 | ||
5503 | ||
1f4c34bd | 5504 | static int |
e1ce2a3a | 5505 | wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len) |
30295c89 VM |
5506 | { |
5507 | WMI_ACM_REJECT_EVENT *ev; | |
5508 | ||
5509 | ev = (WMI_ACM_REJECT_EVENT *)datap; | |
5510 | wmip->wmi_traffic_class = ev->trafficClass; | |
5511 | printk("ACM REJECT %d\n",wmip->wmi_traffic_class); | |
4f69cef0 | 5512 | return 0; |
30295c89 VM |
5513 | } |
5514 | ||
5515 | ||
5516 | #ifdef CONFIG_HOST_DSET_SUPPORT | |
1f4c34bd | 5517 | int |
30295c89 | 5518 | wmi_dset_data_reply(struct wmi_t *wmip, |
e1ce2a3a | 5519 | u32 status, |
ab3655da | 5520 | u8 *user_buf, |
e1ce2a3a JP |
5521 | u32 length, |
5522 | u32 targ_buf, | |
5523 | u32 targ_reply_fn, | |
5524 | u32 targ_reply_arg) | |
30295c89 VM |
5525 | { |
5526 | void *osbuf; | |
5527 | WMIX_DSETDATA_REPLY_CMD *data_reply; | |
e1ce2a3a | 5528 | u32 size; |
30295c89 VM |
5529 | |
5530 | size = sizeof(*data_reply) + length; | |
5531 | ||
5532 | if (size <= length) { | |
5533 | return A_ERROR; | |
5534 | } | |
5535 | ||
5536 | A_DPRINTF(DBG_WMI, | |
5537 | (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status)); | |
5538 | ||
5539 | osbuf = A_NETBUF_ALLOC(size); | |
5540 | if (osbuf == NULL) { | |
5541 | return A_NO_MEMORY; | |
5542 | } | |
5543 | A_NETBUF_PUT(osbuf, size); | |
5544 | data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); | |
5545 | ||
5546 | data_reply->status = status; | |
5547 | data_reply->targ_buf = targ_buf; | |
5548 | data_reply->targ_reply_fn = targ_reply_fn; | |
5549 | data_reply->targ_reply_arg = targ_reply_arg; | |
5550 | data_reply->length = length; | |
5551 | ||
4f69cef0 | 5552 | if (status == 0) { |
30295c89 VM |
5553 | if (a_copy_from_user(data_reply->buf, user_buf, length)) { |
5554 | A_NETBUF_FREE(osbuf); | |
5555 | return A_ERROR; | |
5556 | } | |
5557 | } | |
5558 | ||
5559 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID, | |
5560 | NO_SYNC_WMIFLAG)); | |
5561 | } | |
5562 | #endif /* CONFIG_HOST_DSET_SUPPORT */ | |
5563 | ||
1f4c34bd | 5564 | int |
e1ce2a3a | 5565 | wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status) |
30295c89 VM |
5566 | { |
5567 | void *osbuf; | |
5568 | char *cmd; | |
5569 | ||
5570 | wps_enable = status; | |
5571 | ||
5572 | osbuf = a_netbuf_alloc(sizeof(1)); | |
5573 | if (osbuf == NULL) { | |
5574 | return A_NO_MEMORY; | |
5575 | } | |
5576 | ||
5577 | a_netbuf_put(osbuf, sizeof(1)); | |
5578 | ||
5579 | cmd = (char *)(a_netbuf_to_data(osbuf)); | |
5580 | ||
5581 | A_MEMZERO(cmd, sizeof(*cmd)); | |
5582 | cmd[0] = (status?1:0); | |
5583 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID, | |
5584 | NO_SYNC_WMIFLAG)); | |
5585 | } | |
5586 | ||
5587 | #if defined(CONFIG_TARGET_PROFILE_SUPPORT) | |
1f4c34bd | 5588 | int |
30295c89 | 5589 | wmi_prof_cfg_cmd(struct wmi_t *wmip, |
e1ce2a3a JP |
5590 | u32 period, |
5591 | u32 nbins) | |
30295c89 VM |
5592 | { |
5593 | void *osbuf; | |
5594 | WMIX_PROF_CFG_CMD *cmd; | |
5595 | ||
5596 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5597 | if (osbuf == NULL) { | |
5598 | return A_NO_MEMORY; | |
5599 | } | |
5600 | ||
5601 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5602 | ||
5603 | cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf)); | |
5604 | A_MEMZERO(cmd, sizeof(*cmd)); | |
5605 | cmd->period = period; | |
5606 | cmd->nbins = nbins; | |
5607 | ||
5608 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG)); | |
5609 | } | |
5610 | ||
1f4c34bd | 5611 | int |
e1ce2a3a | 5612 | wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr) |
30295c89 VM |
5613 | { |
5614 | void *osbuf; | |
5615 | WMIX_PROF_ADDR_SET_CMD *cmd; | |
5616 | ||
5617 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5618 | if (osbuf == NULL) { | |
5619 | return A_NO_MEMORY; | |
5620 | } | |
5621 | ||
5622 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5623 | ||
5624 | cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf)); | |
5625 | A_MEMZERO(cmd, sizeof(*cmd)); | |
5626 | cmd->addr = addr; | |
5627 | ||
5628 | return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG)); | |
5629 | } | |
5630 | ||
1f4c34bd | 5631 | int |
30295c89 VM |
5632 | wmi_prof_start_cmd(struct wmi_t *wmip) |
5633 | { | |
5634 | return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID); | |
5635 | } | |
5636 | ||
1f4c34bd | 5637 | int |
30295c89 VM |
5638 | wmi_prof_stop_cmd(struct wmi_t *wmip) |
5639 | { | |
5640 | return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID); | |
5641 | } | |
5642 | ||
1f4c34bd | 5643 | int |
30295c89 VM |
5644 | wmi_prof_count_get_cmd(struct wmi_t *wmip) |
5645 | { | |
5646 | return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID); | |
5647 | } | |
5648 | ||
5649 | /* Called to handle WMIX_PROF_CONT_EVENTID */ | |
1f4c34bd | 5650 | static int |
ab3655da | 5651 | wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
5652 | { |
5653 | WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap; | |
5654 | ||
5655 | A_DPRINTF(DBG_WMI, | |
5656 | (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG, | |
5657 | prof_data->addr, prof_data->count)); | |
5658 | ||
5659 | A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count); | |
5660 | ||
4f69cef0 | 5661 | return 0; |
30295c89 VM |
5662 | } |
5663 | #endif /* CONFIG_TARGET_PROFILE_SUPPORT */ | |
5664 | ||
5665 | #ifdef OS_ROAM_MANAGEMENT | |
5666 | ||
5667 | #define ETHERNET_MAC_ADDRESS_LENGTH 6 | |
5668 | ||
5669 | void | |
5670 | wmi_scan_indication (struct wmi_t *wmip) | |
5671 | { | |
5672 | struct ieee80211_node_table *nt; | |
e1ce2a3a JP |
5673 | u32 gen; |
5674 | u32 size; | |
5675 | u32 bsssize; | |
30295c89 | 5676 | bss_t *bss; |
e1ce2a3a | 5677 | u32 numbss; |
30295c89 VM |
5678 | PNDIS_802_11_BSSID_SCAN_INFO psi; |
5679 | PBYTE pie; | |
5680 | NDIS_802_11_FIXED_IEs *pFixed; | |
5681 | NDIS_802_11_VARIABLE_IEs *pVar; | |
e1ce2a3a | 5682 | u32 RateSize; |
30295c89 VM |
5683 | |
5684 | struct ar6kScanIndication | |
5685 | { | |
5686 | NDIS_802_11_STATUS_INDICATION ind; | |
5687 | NDIS_802_11_BSSID_SCAN_INFO_LIST slist; | |
5688 | } *pAr6kScanIndEvent; | |
5689 | ||
5690 | nt = &wmip->wmi_scan_table; | |
5691 | ||
5692 | ++nt->nt_si_gen; | |
5693 | ||
5694 | ||
5695 | gen = nt->nt_si_gen; | |
5696 | ||
5697 | size = offsetof(struct ar6kScanIndication, slist) + | |
5698 | offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo); | |
5699 | ||
5700 | numbss = 0; | |
5701 | ||
5702 | IEEE80211_NODE_LOCK(nt); | |
5703 | ||
5704 | //calc size | |
5705 | for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { | |
5706 | if (bss->ni_si_gen != gen) { | |
5707 | bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs); | |
5708 | bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); | |
5709 | ||
5710 | #ifdef SUPPORT_WPA2 | |
5711 | if (bss->ni_cie.ie_rsn) { | |
5712 | bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; | |
5713 | } | |
5714 | #endif | |
5715 | if (bss->ni_cie.ie_wpa) { | |
5716 | bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; | |
5717 | } | |
5718 | ||
5719 | // bsssize must be a multiple of 4 to maintain alignment. | |
5720 | bsssize = (bsssize + 3) & ~3; | |
5721 | ||
5722 | size += bsssize; | |
5723 | ||
5724 | numbss++; | |
5725 | } | |
5726 | } | |
5727 | ||
5728 | if (0 == numbss) | |
5729 | { | |
5730 | // RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n")); | |
5731 | ar6000_scan_indication (wmip->wmi_devt, NULL, 0); | |
5732 | IEEE80211_NODE_UNLOCK (nt); | |
5733 | return; | |
5734 | } | |
5735 | ||
5736 | pAr6kScanIndEvent = A_MALLOC(size); | |
5737 | ||
5738 | if (NULL == pAr6kScanIndEvent) | |
5739 | { | |
5740 | IEEE80211_NODE_UNLOCK(nt); | |
5741 | return; | |
5742 | } | |
5743 | ||
5744 | A_MEMZERO(pAr6kScanIndEvent, size); | |
5745 | ||
5746 | //copy data | |
5747 | pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList; | |
5748 | pAr6kScanIndEvent->slist.Version = 1; | |
5749 | pAr6kScanIndEvent->slist.NumItems = numbss; | |
5750 | ||
5751 | psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0]; | |
5752 | ||
5753 | for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { | |
5754 | if (bss->ni_si_gen != gen) { | |
5755 | ||
5756 | bss->ni_si_gen = gen; | |
5757 | ||
5758 | //Set scan time | |
5759 | psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC; | |
5760 | ||
5761 | // Copy data to bssid_ex | |
5762 | bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs); | |
5763 | bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); | |
5764 | ||
5765 | #ifdef SUPPORT_WPA2 | |
5766 | if (bss->ni_cie.ie_rsn) { | |
5767 | bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; | |
5768 | } | |
5769 | #endif | |
5770 | if (bss->ni_cie.ie_wpa) { | |
5771 | bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; | |
5772 | } | |
5773 | ||
5774 | // bsssize must be a multiple of 4 to maintain alignment. | |
5775 | bsssize = (bsssize + 3) & ~3; | |
5776 | ||
5777 | psi->Bssid.Length = bsssize; | |
5778 | ||
5779 | memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH); | |
5780 | ||
5781 | ||
5782 | //if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) || | |
5783 | // ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70))) | |
5784 | // RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5])); | |
5785 | ||
5786 | psi->Bssid.Ssid.SsidLength = 0; | |
5787 | pie = bss->ni_cie.ie_ssid; | |
5788 | ||
5789 | if (pie) { | |
5790 | // Format of SSID IE is: | |
5791 | // Type (1 octet) | |
5792 | // Length (1 octet) | |
5793 | // SSID (Length octets) | |
5794 | // | |
5795 | // Validation of the IE should have occurred within WMI. | |
5796 | // | |
5797 | if (pie[1] <= 32) { | |
5798 | psi->Bssid.Ssid.SsidLength = pie[1]; | |
5799 | memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength); | |
5800 | } | |
5801 | } | |
5802 | psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0; | |
5803 | ||
5804 | //Post the RSSI value relative to the Standard Noise floor value. | |
5805 | psi->Bssid.Rssi = bss->ni_rssi; | |
5806 | ||
5807 | if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) { | |
5808 | ||
5809 | if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) { | |
5810 | psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24; | |
5811 | } | |
5812 | else { | |
5813 | psi->Bssid.NetworkTypeInUse = Ndis802_11DS; | |
5814 | } | |
5815 | } | |
5816 | else { | |
5817 | psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5; | |
5818 | } | |
5819 | ||
5820 | psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration); | |
5821 | psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us) | |
5822 | psi->Bssid.Configuration.ATIMWindow = 0; | |
5823 | psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000; | |
5824 | psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS; | |
5825 | ||
5826 | RateSize = 0; | |
5827 | pie = bss->ni_cie.ie_rates; | |
5828 | if (pie) { | |
5829 | RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX; | |
5830 | memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize); | |
5831 | } | |
5832 | pie = bss->ni_cie.ie_xrates; | |
5833 | if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) { | |
5834 | memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2], | |
5835 | (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize)); | |
5836 | } | |
5837 | ||
5838 | // Copy the fixed IEs | |
5839 | psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs); | |
5840 | ||
5841 | pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs; | |
5842 | memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp)); | |
5843 | pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt; | |
5844 | pFixed->Capabilities = bss->ni_cie.ie_capInfo; | |
5845 | ||
5846 | // Copy selected variable IEs | |
5847 | ||
5848 | pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs)); | |
5849 | ||
5850 | #ifdef SUPPORT_WPA2 | |
5851 | // Copy the WPAv2 IE | |
5852 | if (bss->ni_cie.ie_rsn) { | |
5853 | pie = bss->ni_cie.ie_rsn; | |
5854 | psi->Bssid.IELength += pie[1] + 2; | |
5855 | memcpy(pVar, pie, pie[1] + 2); | |
5856 | pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); | |
5857 | } | |
5858 | #endif | |
5859 | // Copy the WPAv1 IE | |
5860 | if (bss->ni_cie.ie_wpa) { | |
5861 | pie = bss->ni_cie.ie_wpa; | |
5862 | psi->Bssid.IELength += pie[1] + 2; | |
5863 | memcpy(pVar, pie, pie[1] + 2); | |
5864 | pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); | |
5865 | } | |
5866 | ||
5867 | // Advance buffer pointer | |
5868 | psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid)); | |
5869 | } | |
5870 | } | |
5871 | ||
5872 | IEEE80211_NODE_UNLOCK(nt); | |
5873 | ||
5874 | // wmi_free_allnodes(wmip); | |
5875 | ||
5876 | // RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss)); | |
5877 | ||
5878 | ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size); | |
5879 | ||
5880 | A_FREE(pAr6kScanIndEvent); | |
5881 | } | |
5882 | #endif | |
5883 | ||
cb1e3709 | 5884 | u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, |
e1ce2a3a | 5885 | u32 size) |
30295c89 | 5886 | { |
e1ce2a3a | 5887 | u32 index; |
ab3655da | 5888 | u8 threshold = (u8)sq_thresh->upper_threshold[size - 1]; |
30295c89 VM |
5889 | |
5890 | /* The list is already in sorted order. Get the next lower value */ | |
5891 | for (index = 0; index < size; index ++) { | |
5892 | if (rssi < sq_thresh->upper_threshold[index]) { | |
ab3655da | 5893 | threshold = (u8)sq_thresh->upper_threshold[index]; |
30295c89 VM |
5894 | break; |
5895 | } | |
5896 | } | |
5897 | ||
5898 | return threshold; | |
5899 | } | |
5900 | ||
cb1e3709 | 5901 | u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, |
e1ce2a3a | 5902 | u32 size) |
30295c89 | 5903 | { |
e1ce2a3a | 5904 | u32 index; |
ab3655da | 5905 | u8 threshold = (u8)sq_thresh->lower_threshold[size - 1]; |
30295c89 VM |
5906 | |
5907 | /* The list is already in sorted order. Get the next lower value */ | |
5908 | for (index = 0; index < size; index ++) { | |
5909 | if (rssi > sq_thresh->lower_threshold[index]) { | |
ab3655da | 5910 | threshold = (u8)sq_thresh->lower_threshold[index]; |
30295c89 VM |
5911 | break; |
5912 | } | |
5913 | } | |
5914 | ||
5915 | return threshold; | |
5916 | } | |
1f4c34bd | 5917 | static int |
30295c89 VM |
5918 | wmi_send_rssi_threshold_params(struct wmi_t *wmip, |
5919 | WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) | |
5920 | { | |
5921 | void *osbuf; | |
f2ab1275 | 5922 | s8 size; |
30295c89 VM |
5923 | WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd; |
5924 | ||
5925 | size = sizeof (*cmd); | |
5926 | ||
5927 | osbuf = A_NETBUF_ALLOC(size); | |
5928 | if (osbuf == NULL) { | |
5929 | return A_NO_MEMORY; | |
5930 | } | |
5931 | ||
5932 | A_NETBUF_PUT(osbuf, size); | |
5933 | ||
5934 | cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
5935 | A_MEMZERO(cmd, size); | |
05209262 | 5936 | memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD)); |
30295c89 VM |
5937 | |
5938 | return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID, | |
5939 | NO_SYNC_WMIFLAG)); | |
5940 | } | |
1f4c34bd | 5941 | static int |
30295c89 VM |
5942 | wmi_send_snr_threshold_params(struct wmi_t *wmip, |
5943 | WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) | |
5944 | { | |
5945 | void *osbuf; | |
f2ab1275 | 5946 | s8 size; |
30295c89 VM |
5947 | WMI_SNR_THRESHOLD_PARAMS_CMD *cmd; |
5948 | ||
5949 | size = sizeof (*cmd); | |
5950 | ||
5951 | osbuf = A_NETBUF_ALLOC(size); | |
5952 | if (osbuf == NULL) { | |
5953 | return A_NO_MEMORY; | |
5954 | } | |
5955 | ||
5956 | A_NETBUF_PUT(osbuf, size); | |
5957 | cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); | |
5958 | A_MEMZERO(cmd, size); | |
05209262 | 5959 | memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD)); |
30295c89 VM |
5960 | |
5961 | return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID, | |
5962 | NO_SYNC_WMIFLAG)); | |
5963 | } | |
5964 | ||
1f4c34bd | 5965 | int |
30295c89 VM |
5966 | wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd) |
5967 | { | |
5968 | void *osbuf; | |
5969 | WMI_SET_TARGET_EVENT_REPORT_CMD* alloc_cmd; | |
5970 | ||
5971 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
5972 | if (osbuf == NULL) { | |
5973 | return A_NO_MEMORY; | |
5974 | } | |
5975 | ||
5976 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
5977 | ||
5978 | alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf)); | |
5979 | A_MEMZERO(alloc_cmd, sizeof(*cmd)); | |
05209262 | 5980 | memcpy(alloc_cmd, cmd, sizeof(*cmd)); |
30295c89 VM |
5981 | |
5982 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID, | |
5983 | NO_SYNC_WMIFLAG)); | |
5984 | } | |
5985 | ||
ab3655da | 5986 | bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id) |
30295c89 VM |
5987 | { |
5988 | wmi_get_current_bssid (wmip, id); | |
5989 | return wlan_node_remove (&wmip->wmi_scan_table, id); | |
5990 | } | |
5991 | ||
ab3655da | 5992 | int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss) |
30295c89 VM |
5993 | { |
5994 | wlan_setup_node (&wmip->wmi_scan_table, bss, id); | |
4f69cef0 | 5995 | return 0; |
30295c89 VM |
5996 | } |
5997 | ||
5998 | #ifdef ATH_AR6K_11N_SUPPORT | |
1f4c34bd | 5999 | static int |
ab3655da | 6000 | wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
6001 | { |
6002 | WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap; | |
6003 | ||
6004 | A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd); | |
6005 | ||
4f69cef0 | 6006 | return 0; |
30295c89 VM |
6007 | } |
6008 | ||
6009 | ||
1f4c34bd | 6010 | static int |
ab3655da | 6011 | wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
6012 | { |
6013 | WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap; | |
6014 | ||
6015 | A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd); | |
6016 | ||
4f69cef0 | 6017 | return 0; |
30295c89 VM |
6018 | } |
6019 | ||
1f4c34bd | 6020 | static int |
ab3655da | 6021 | wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
6022 | { |
6023 | WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap; | |
6024 | ||
6025 | A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd); | |
6026 | ||
4f69cef0 | 6027 | return 0; |
30295c89 VM |
6028 | } |
6029 | ||
1f4c34bd | 6030 | int |
ab3655da | 6031 | wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
6032 | { |
6033 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
6034 | ||
6035 | A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len); | |
6036 | ||
4f69cef0 | 6037 | return 0; |
30295c89 VM |
6038 | } |
6039 | ||
6040 | ||
1f4c34bd | 6041 | int |
ab3655da | 6042 | wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len) |
30295c89 VM |
6043 | { |
6044 | A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); | |
6045 | ||
6046 | A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len); | |
6047 | ||
4f69cef0 | 6048 | return 0; |
30295c89 VM |
6049 | |
6050 | } | |
6051 | #endif | |
6052 | ||
1f4c34bd | 6053 | static int |
ab3655da | 6054 | wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
6055 | { |
6056 | WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap; | |
6057 | A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd); | |
6058 | ||
4f69cef0 | 6059 | return 0; |
30295c89 VM |
6060 | } |
6061 | ||
6062 | //////////////////////////////////////////////////////////////////////////////// | |
6063 | //// //// | |
6064 | //// AP mode functions //// | |
6065 | //// //// | |
6066 | //////////////////////////////////////////////////////////////////////////////// | |
6067 | /* | |
6068 | * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG | |
6069 | * | |
6070 | * When AR6K in AP mode, This command will be called after | |
6071 | * changing ssid, channel etc. It will pass the profile to | |
6072 | * target with a flag which will indicate which parameter changed, | |
6073 | * also if this flag is 0, there was no change in parametes, so | |
6074 | * commit cmd will not be sent to target. Without calling this IOCTL | |
6075 | * the changes will not take effect. | |
6076 | */ | |
1f4c34bd | 6077 | int |
30295c89 VM |
6078 | wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p) |
6079 | { | |
6080 | void *osbuf; | |
6081 | WMI_CONNECT_CMD *cm; | |
6082 | ||
6083 | osbuf = A_NETBUF_ALLOC(sizeof(*cm)); | |
6084 | if (osbuf == NULL) { | |
6085 | return A_NO_MEMORY; | |
6086 | } | |
6087 | ||
6088 | A_NETBUF_PUT(osbuf, sizeof(*cm)); | |
6089 | cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); | |
6090 | A_MEMZERO(cm, sizeof(*cm)); | |
6091 | ||
05209262 | 6092 | memcpy(cm,p,sizeof(*cm)); |
30295c89 VM |
6093 | |
6094 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG)); | |
6095 | } | |
6096 | ||
6097 | /* | |
6098 | * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID | |
6099 | * | |
6100 | * This command will be used to enable/disable hidden ssid functioanlity of | |
6101 | * beacon. If it is enabled, ssid will be NULL in beacon. | |
6102 | */ | |
1f4c34bd | 6103 | int |
ab3655da | 6104 | wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid) |
30295c89 VM |
6105 | { |
6106 | void *osbuf; | |
6107 | WMI_AP_HIDDEN_SSID_CMD *hs; | |
6108 | ||
6109 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD)); | |
6110 | if (osbuf == NULL) { | |
6111 | return A_NO_MEMORY; | |
6112 | } | |
6113 | ||
6114 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD)); | |
6115 | hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf)); | |
6116 | A_MEMZERO(hs, sizeof(*hs)); | |
6117 | ||
6118 | hs->hidden_ssid = hidden_ssid; | |
6119 | ||
6120 | A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid)); | |
6121 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG)); | |
6122 | } | |
6123 | ||
6124 | /* | |
6125 | * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA | |
6126 | * | |
6127 | * This command is used to limit max num of STA that can connect | |
6128 | * with this AP. This value should not exceed AP_MAX_NUM_STA (this | |
6129 | * is max num of STA supported by AP). Value was already validated | |
6130 | * in ioctl.c | |
6131 | */ | |
1f4c34bd | 6132 | int |
ab3655da | 6133 | wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta) |
30295c89 VM |
6134 | { |
6135 | void *osbuf; | |
6136 | WMI_AP_SET_NUM_STA_CMD *ns; | |
6137 | ||
6138 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD)); | |
6139 | if (osbuf == NULL) { | |
6140 | return A_NO_MEMORY; | |
6141 | } | |
6142 | ||
6143 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD)); | |
6144 | ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf)); | |
6145 | A_MEMZERO(ns, sizeof(*ns)); | |
6146 | ||
6147 | ns->num_sta = num_sta; | |
6148 | ||
6149 | A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta)); | |
6150 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG)); | |
6151 | } | |
6152 | ||
6153 | /* | |
6154 | * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC | |
6155 | * | |
6156 | * This command is used to send list of mac of STAs which will | |
6157 | * be allowed to connect with this AP. When this list is empty | |
6158 | * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. | |
6159 | */ | |
1f4c34bd | 6160 | int |
30295c89 VM |
6161 | wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl) |
6162 | { | |
6163 | void *osbuf; | |
6164 | WMI_AP_ACL_MAC_CMD *a; | |
6165 | ||
6166 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD)); | |
6167 | if (osbuf == NULL) { | |
6168 | return A_NO_MEMORY; | |
6169 | } | |
6170 | ||
6171 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD)); | |
6172 | a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf)); | |
6173 | A_MEMZERO(a, sizeof(*a)); | |
05209262 | 6174 | memcpy(a,acl,sizeof(*acl)); |
30295c89 VM |
6175 | |
6176 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG)); | |
6177 | } | |
6178 | ||
6179 | /* | |
6180 | * IOCTL: AR6000_XIOCTL_AP_SET_MLME | |
6181 | * | |
6182 | * This command is used to send list of mac of STAs which will | |
6183 | * be allowed to connect with this AP. When this list is empty | |
6184 | * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. | |
6185 | */ | |
1f4c34bd | 6186 | int |
4853ac05 | 6187 | wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason) |
30295c89 VM |
6188 | { |
6189 | void *osbuf; | |
6190 | WMI_AP_SET_MLME_CMD *mlme; | |
6191 | ||
6192 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD)); | |
6193 | if (osbuf == NULL) { | |
6194 | return A_NO_MEMORY; | |
6195 | } | |
6196 | ||
6197 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD)); | |
6198 | mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf)); | |
6199 | A_MEMZERO(mlme, sizeof(*mlme)); | |
6200 | ||
6201 | mlme->cmd = cmd; | |
05209262 | 6202 | memcpy(mlme->mac, mac, ATH_MAC_LEN); |
30295c89 VM |
6203 | mlme->reason = reason; |
6204 | ||
6205 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG)); | |
6206 | } | |
6207 | ||
1f4c34bd | 6208 | static int |
ab3655da | 6209 | wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len) |
30295c89 VM |
6210 | { |
6211 | WMI_PSPOLL_EVENT *ev; | |
6212 | ||
6213 | if (len < sizeof(WMI_PSPOLL_EVENT)) { | |
6214 | return A_EINVAL; | |
6215 | } | |
6216 | ev = (WMI_PSPOLL_EVENT *)datap; | |
6217 | ||
6218 | A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid); | |
4f69cef0 | 6219 | return 0; |
30295c89 VM |
6220 | } |
6221 | ||
1f4c34bd | 6222 | static int |
ab3655da | 6223 | wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len) |
30295c89 VM |
6224 | { |
6225 | A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt); | |
4f69cef0 | 6226 | return 0; |
30295c89 VM |
6227 | } |
6228 | ||
6229 | #ifdef WAPI_ENABLE | |
1f4c34bd | 6230 | static int |
ab3655da | 6231 | wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len) |
30295c89 | 6232 | { |
ab3655da | 6233 | u8 *ev; |
30295c89 VM |
6234 | |
6235 | if (len < 7) { | |
6236 | return A_EINVAL; | |
6237 | } | |
ab3655da | 6238 | ev = (u8 *)datap; |
30295c89 VM |
6239 | |
6240 | A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]); | |
4f69cef0 | 6241 | return 0; |
30295c89 VM |
6242 | } |
6243 | #endif | |
6244 | ||
1f4c34bd | 6245 | int |
4853ac05 | 6246 | wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag) |
30295c89 VM |
6247 | { |
6248 | WMI_AP_SET_PVB_CMD *cmd; | |
6249 | void *osbuf = NULL; | |
6250 | ||
6251 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD)); | |
6252 | if (osbuf == NULL) { | |
6253 | return A_NO_MEMORY; | |
6254 | } | |
6255 | ||
6256 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD)); | |
6257 | cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf)); | |
6258 | A_MEMZERO(cmd, sizeof(*cmd)); | |
6259 | ||
6260 | cmd->aid = aid; | |
6261 | cmd->flag = flag; | |
6262 | ||
6263 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG)); | |
6264 | } | |
6265 | ||
1f4c34bd | 6266 | int |
e1ce2a3a | 6267 | wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period) |
30295c89 VM |
6268 | { |
6269 | WMI_AP_CONN_INACT_CMD *cmd; | |
6270 | void *osbuf = NULL; | |
6271 | ||
6272 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD)); | |
6273 | if (osbuf == NULL) { | |
6274 | return A_NO_MEMORY; | |
6275 | } | |
6276 | ||
6277 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD)); | |
6278 | cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf)); | |
6279 | A_MEMZERO(cmd, sizeof(*cmd)); | |
6280 | ||
6281 | cmd->period = period; | |
6282 | ||
6283 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG)); | |
6284 | } | |
6285 | ||
1f4c34bd | 6286 | int |
e1ce2a3a | 6287 | wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell) |
30295c89 VM |
6288 | { |
6289 | WMI_AP_PROT_SCAN_TIME_CMD *cmd; | |
6290 | void *osbuf = NULL; | |
6291 | ||
6292 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); | |
6293 | if (osbuf == NULL) { | |
6294 | return A_NO_MEMORY; | |
6295 | } | |
6296 | ||
6297 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); | |
6298 | cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf)); | |
6299 | A_MEMZERO(cmd, sizeof(*cmd)); | |
6300 | ||
6301 | cmd->period_min = period; | |
6302 | cmd->dwell_ms = dwell; | |
6303 | ||
6304 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG)); | |
6305 | } | |
6306 | ||
1f4c34bd | 6307 | int |
ab3655da | 6308 | wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim) |
30295c89 VM |
6309 | { |
6310 | WMI_AP_SET_DTIM_CMD *cmd; | |
6311 | void *osbuf = NULL; | |
6312 | ||
6313 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD)); | |
6314 | if (osbuf == NULL) { | |
6315 | return A_NO_MEMORY; | |
6316 | } | |
6317 | ||
6318 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD)); | |
6319 | cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf)); | |
6320 | A_MEMZERO(cmd, sizeof(*cmd)); | |
6321 | ||
6322 | cmd->dtim = dtim; | |
6323 | ||
6324 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG)); | |
6325 | } | |
6326 | ||
6327 | /* | |
6328 | * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY | |
6329 | * | |
6330 | * This command is used to set ACL policay. While changing policy, if you | |
6331 | * want to retain the existing MAC addresses in the ACL list, policy should be | |
6332 | * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared. | |
6333 | * If there is no chage in policy, the list will be intact. | |
6334 | */ | |
1f4c34bd | 6335 | int |
ab3655da | 6336 | wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy) |
30295c89 VM |
6337 | { |
6338 | void *osbuf; | |
6339 | WMI_AP_ACL_POLICY_CMD *po; | |
6340 | ||
6341 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD)); | |
6342 | if (osbuf == NULL) { | |
6343 | return A_NO_MEMORY; | |
6344 | } | |
6345 | ||
6346 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD)); | |
6347 | po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); | |
6348 | A_MEMZERO(po, sizeof(*po)); | |
6349 | ||
6350 | po->policy = policy; | |
6351 | ||
6352 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG)); | |
6353 | } | |
6354 | ||
1f4c34bd | 6355 | int |
ab3655da | 6356 | wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset) |
30295c89 VM |
6357 | { |
6358 | void *osbuf; | |
6359 | WMI_AP_SET_11BG_RATESET_CMD *rs; | |
6360 | ||
6361 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD)); | |
6362 | if (osbuf == NULL) { | |
6363 | return A_NO_MEMORY; | |
6364 | } | |
6365 | ||
6366 | A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD)); | |
6367 | rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf)); | |
6368 | A_MEMZERO(rs, sizeof(*rs)); | |
6369 | ||
6370 | rs->rateset = rateset; | |
6371 | ||
6372 | return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG)); | |
6373 | } | |
6374 | ||
6375 | #ifdef ATH_AR6K_11N_SUPPORT | |
1f4c34bd | 6376 | int |
30295c89 VM |
6377 | wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd) |
6378 | { | |
6379 | void *osbuf; | |
6380 | WMI_SET_HT_CAP_CMD *htCap; | |
ab3655da | 6381 | u8 band; |
30295c89 VM |
6382 | |
6383 | osbuf = A_NETBUF_ALLOC(sizeof(*htCap)); | |
6384 | if (osbuf == NULL) { | |
6385 | return A_NO_MEMORY; | |
6386 | } | |
6387 | ||
6388 | A_NETBUF_PUT(osbuf, sizeof(*htCap)); | |
6389 | ||
6390 | band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ; | |
6391 | wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0; | |
6392 | ||
6393 | htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf)); | |
6394 | A_MEMZERO(htCap, sizeof(*htCap)); | |
05209262 | 6395 | memcpy(htCap, cmd, sizeof(*htCap)); |
30295c89 VM |
6396 | |
6397 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID, | |
6398 | NO_SYNC_WMIFLAG)); | |
6399 | } | |
6400 | ||
1f4c34bd | 6401 | int |
ab3655da | 6402 | wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width) |
30295c89 VM |
6403 | { |
6404 | void *osbuf; | |
6405 | WMI_SET_HT_OP_CMD *htInfo; | |
6406 | ||
6407 | osbuf = A_NETBUF_ALLOC(sizeof(*htInfo)); | |
6408 | if (osbuf == NULL) { | |
6409 | return A_NO_MEMORY; | |
6410 | } | |
6411 | ||
6412 | A_NETBUF_PUT(osbuf, sizeof(*htInfo)); | |
6413 | ||
6414 | htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf)); | |
6415 | A_MEMZERO(htInfo, sizeof(*htInfo)); | |
6416 | htInfo->sta_chan_width = sta_chan_width; | |
6417 | ||
6418 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID, | |
6419 | NO_SYNC_WMIFLAG)); | |
6420 | } | |
6421 | #endif | |
6422 | ||
1f4c34bd | 6423 | int |
e1ce2a3a | 6424 | wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray) |
30295c89 VM |
6425 | { |
6426 | void *osbuf; | |
6427 | WMI_SET_TX_SELECT_RATES_CMD *pData; | |
6428 | ||
6429 | osbuf = A_NETBUF_ALLOC(sizeof(*pData)); | |
6430 | if (osbuf == NULL) { | |
6431 | return A_NO_MEMORY; | |
6432 | } | |
6433 | ||
6434 | A_NETBUF_PUT(osbuf, sizeof(*pData)); | |
6435 | ||
6436 | pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf)); | |
05209262 | 6437 | memcpy(pData, pMaskArray, sizeof(*pData)); |
30295c89 VM |
6438 | |
6439 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID, | |
6440 | NO_SYNC_WMIFLAG)); | |
6441 | } | |
6442 | ||
6443 | ||
1f4c34bd | 6444 | int |
4853ac05 | 6445 | wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz) |
30295c89 VM |
6446 | { |
6447 | void *osbuf; | |
6448 | WMI_HCI_CMD *cmd; | |
6449 | ||
6450 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz); | |
6451 | if (osbuf == NULL) { | |
6452 | return A_NO_MEMORY; | |
6453 | } | |
6454 | ||
6455 | A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz); | |
6456 | cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf)); | |
6457 | ||
6458 | cmd->cmd_buf_sz = sz; | |
05209262 | 6459 | memcpy(cmd->buf, buf, sz); |
30295c89 VM |
6460 | return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG)); |
6461 | } | |
6462 | ||
6463 | #ifdef ATH_AR6K_11N_SUPPORT | |
1f4c34bd | 6464 | int |
4853ac05 | 6465 | wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask) |
30295c89 VM |
6466 | { |
6467 | void *osbuf; | |
6468 | WMI_ALLOW_AGGR_CMD *cmd; | |
6469 | ||
6470 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6471 | if (osbuf == NULL) { | |
6472 | return A_NO_MEMORY; | |
6473 | } | |
6474 | ||
6475 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6476 | ||
6477 | cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf)); | |
6478 | cmd->tx_allow_aggr = tx_tidmask; | |
6479 | cmd->rx_allow_aggr = rx_tidmask; | |
6480 | ||
6481 | return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG)); | |
6482 | } | |
6483 | ||
1f4c34bd | 6484 | int |
ab3655da | 6485 | wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid) |
30295c89 VM |
6486 | { |
6487 | void *osbuf; | |
6488 | WMI_ADDBA_REQ_CMD *cmd; | |
6489 | ||
6490 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6491 | if (osbuf == NULL) { | |
6492 | return A_NO_MEMORY; | |
6493 | } | |
6494 | ||
6495 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6496 | ||
6497 | cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); | |
6498 | cmd->tid = tid; | |
6499 | ||
6500 | return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG)); | |
6501 | } | |
6502 | ||
1f4c34bd | 6503 | int |
ab3655da | 6504 | wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink) |
30295c89 VM |
6505 | { |
6506 | void *osbuf; | |
6507 | WMI_DELBA_REQ_CMD *cmd; | |
6508 | ||
6509 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6510 | if (osbuf == NULL) { | |
6511 | return A_NO_MEMORY; | |
6512 | } | |
6513 | ||
6514 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6515 | ||
6516 | cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); | |
6517 | cmd->tid = tid; | |
6518 | cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */ | |
6519 | ||
6520 | /* Delete the local aggr state, on host */ | |
6521 | return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG)); | |
6522 | } | |
6523 | #endif | |
6524 | ||
1f4c34bd | 6525 | int |
ab3655da | 6526 | wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, |
1071a134 | 6527 | bool rxDot11Hdr, bool defragOnHost) |
30295c89 VM |
6528 | { |
6529 | void *osbuf; | |
6530 | WMI_RX_FRAME_FORMAT_CMD *cmd; | |
6531 | ||
6532 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6533 | if (osbuf == NULL) { | |
6534 | return A_NO_MEMORY; | |
6535 | } | |
6536 | ||
6537 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6538 | ||
6539 | cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf)); | |
1071a134 JP |
6540 | cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0; |
6541 | cmd->defragOnHost = (defragOnHost==true)? 1:0; | |
30295c89 VM |
6542 | cmd->metaVersion = rxMetaVersion; /* */ |
6543 | ||
6544 | /* Delete the local aggr state, on host */ | |
6545 | return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG)); | |
6546 | } | |
6547 | ||
6548 | ||
1f4c34bd | 6549 | int |
1071a134 | 6550 | wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode) |
30295c89 VM |
6551 | { |
6552 | void *osbuf; | |
6553 | WMI_SET_THIN_MODE_CMD *cmd; | |
6554 | ||
6555 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6556 | if (osbuf == NULL) { | |
6557 | return A_NO_MEMORY; | |
6558 | } | |
6559 | ||
6560 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6561 | ||
6562 | cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf)); | |
1071a134 | 6563 | cmd->enable = (bThinMode==true)? 1:0; |
30295c89 VM |
6564 | |
6565 | /* Delete the local aggr state, on host */ | |
6566 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG)); | |
6567 | } | |
6568 | ||
6569 | ||
1f4c34bd | 6570 | int |
30295c89 VM |
6571 | wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence) |
6572 | { | |
6573 | void *osbuf; | |
6574 | WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd; | |
6575 | ||
6576 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6577 | if (osbuf == NULL) { | |
6578 | return A_NO_MEMORY; | |
6579 | } | |
6580 | ||
6581 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6582 | ||
6583 | cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf)); | |
6584 | A_MEMZERO(cmd, sizeof(*cmd)); | |
6585 | cmd->precedence = precedence; | |
6586 | ||
6587 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, | |
6588 | NO_SYNC_WMIFLAG)); | |
6589 | } | |
6590 | ||
1f4c34bd | 6591 | int |
ab3655da | 6592 | wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk) |
30295c89 VM |
6593 | { |
6594 | void *osbuf; | |
6595 | WMI_SET_PMK_CMD *p; | |
6596 | ||
6597 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD)); | |
6598 | if (osbuf == NULL) { | |
6599 | return A_NO_MEMORY; | |
6600 | } | |
6601 | ||
6602 | A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD)); | |
6603 | ||
6604 | p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf)); | |
6605 | A_MEMZERO(p, sizeof(*p)); | |
6606 | ||
05209262 | 6607 | memcpy(p->pmk, pmk, WMI_PMK_LEN); |
30295c89 VM |
6608 | |
6609 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG)); | |
6610 | } | |
6611 | ||
711a1bcc VM |
6612 | int |
6613 | wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd) | |
6614 | { | |
6615 | void *osbuf; | |
6616 | WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p; | |
6617 | ||
6618 | osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD)); | |
6619 | if (osbuf == NULL) { | |
6620 | return A_NO_MEMORY; | |
6621 | } | |
6622 | ||
6623 | A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD)); | |
6624 | ||
6625 | p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf)); | |
6626 | memset(p, 0, sizeof(*p)); | |
6627 | ||
6628 | p->threshold = cmd->threshold; | |
6629 | ||
6630 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG)); | |
6631 | } | |
6632 | ||
1f4c34bd | 6633 | int |
e1ce2a3a | 6634 | wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold) |
30295c89 VM |
6635 | { |
6636 | void *osbuf; | |
6637 | WMI_SET_TX_SGI_PARAM_CMD *cmd; | |
6638 | ||
6639 | osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); | |
6640 | if (osbuf == NULL) { | |
6641 | return A_NO_MEMORY ; | |
6642 | } | |
6643 | ||
6644 | A_NETBUF_PUT(osbuf, sizeof(*cmd)); | |
6645 | ||
6646 | cmd = (WMI_SET_TX_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf)); | |
6647 | A_MEMZERO(cmd, sizeof(*cmd)); | |
6648 | cmd->sgiMask = sgiMask; | |
6649 | cmd->sgiPERThreshold = sgiPERThreshold; | |
6650 | return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID, | |
6651 | NO_SYNC_WMIFLAG)); | |
6652 | } | |
6653 | ||
6654 | bss_t * | |
d8cb316f | 6655 | wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid, |
e1ce2a3a JP |
6656 | u32 ssidLength, |
6657 | u32 dot11AuthMode, u32 authMode, | |
6658 | u32 pairwiseCryptoType, u32 grpwiseCryptoTyp) | |
30295c89 VM |
6659 | { |
6660 | bss_t *node = NULL; | |
6661 | node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid, | |
6662 | ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp); | |
6663 | ||
6664 | return node; | |
6665 | } | |
6666 | ||
4853ac05 | 6667 | u16 wmi_ieee2freq (int chan) |
30295c89 | 6668 | { |
4853ac05 | 6669 | u16 freq = 0; |
30295c89 VM |
6670 | freq = wlan_ieee2freq (chan); |
6671 | return freq; | |
6672 | ||
6673 | } | |
6674 | ||
e1ce2a3a | 6675 | u32 wmi_freq2ieee (u16 freq) |
30295c89 | 6676 | { |
4853ac05 | 6677 | u16 chan = 0; |
30295c89 VM |
6678 | chan = wlan_freq2ieee (freq); |
6679 | return chan; | |
6680 | } |