[x86] add rootwait option to the kernel command line (#6209)
[openwrt.git] / target / linux / s3c24xx / files-2.6.31 / drivers / ar6000 / wmi / wmi.c
1 /*
2 * Copyright (c) 2004-2007 Atheros Communications Inc.
3 * All rights reserved.
4 *
5 * This module implements the hardware independent layer of the
6 * Wireless Module Interface (WMI) protocol.
7 *
8 * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi.c#3 $
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation;
14 *
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing
18 * rights and limitations under the License.
19 *
20 *
21 *
22 */
23
24 #include <a_config.h>
25 #include <athdefs.h>
26 #include <a_types.h>
27 #include <a_osapi.h>
28 #include "htc.h"
29 #include "htc_api.h"
30 #include "wmi.h"
31 #include <ieee80211.h>
32 #include <ieee80211_node.h>
33 #include <wlan_api.h>
34 #include <wmi_api.h>
35 #include "dset_api.h"
36 #include "gpio_api.h"
37 #include "wmi_host.h"
38 #include "a_drv.h"
39 #include "a_drv_api.h"
40 #include "a_debug.h"
41 #include "dbglog_api.h"
42
43 static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44
45 static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
46 int len);
47 static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
48 int len);
49 static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
50 int len);
51 static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
52 int len);
53 static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
54 int len);
55 static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
56 int len);
57 static A_STATUS wmi_sync_point(struct wmi_t *wmip);
58
59 static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
60 int len);
61 static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
62 int len);
63 static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
64 int len);
65 static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
66 int len);
67 static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
68 static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
69 int len);
70
71 static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
72 int len);
73 #ifdef CONFIG_HOST_DSET_SUPPORT
74 static A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
75 static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
76 int len);
77 #endif /* CONFIG_HOST_DSET_SUPPORT */
78
79
80 static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap,
81 int len);
82 static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
83 static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
84 static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
85 static A_STATUS wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
86 static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
87 static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
88 static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
89 int len);
90 static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
91 int len);
92 static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
93 int len);
94 static A_STATUS
95 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
96
97 #ifdef CONFIG_HOST_GPIO_SUPPORT
98 static A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
99 static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
100 static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
101 #endif /* CONFIG_HOST_GPIO_SUPPORT */
102
103 #ifdef CONFIG_HOST_TCMD_SUPPORT
104 static A_STATUS
105 wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
106 #endif
107
108 static A_STATUS
109 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
110
111 static A_STATUS
112 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
113
114 static A_STATUS
115 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
116
117 static A_BOOL
118 wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex);
119
120 static A_STATUS
121 wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
122
123 static A_STATUS
124 wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
125
126 static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
127
128 int wps_enable;
129 static const A_INT32 wmi_rateTable[] = {
130 1000,
131 2000,
132 5500,
133 11000,
134 6000,
135 9000,
136 12000,
137 18000,
138 24000,
139 36000,
140 48000,
141 54000,
142 0};
143
144 #define MODE_A_SUPPORT_RATE_START 4
145 #define MODE_A_SUPPORT_RATE_STOP 11
146
147 #define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
148 #define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
149
150 #define MODE_B_SUPPORT_RATE_START 0
151 #define MODE_B_SUPPORT_RATE_STOP 3
152
153 #define MODE_G_SUPPORT_RATE_START 0
154 #define MODE_G_SUPPORT_RATE_STOP 11
155
156 #define MAX_NUMBER_OF_SUPPORT_RATES (MODE_G_SUPPORT_RATE_STOP + 1)
157
158 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
159 const A_UINT8 up_to_ac[]= {
160 WMM_AC_BE,
161 WMM_AC_BK,
162 WMM_AC_BK,
163 WMM_AC_BE,
164 WMM_AC_VI,
165 WMM_AC_VI,
166 WMM_AC_VO,
167 WMM_AC_VO,
168 };
169
170 void *
171 wmi_init(void *devt)
172 {
173 struct wmi_t *wmip;
174
175 wmip = A_MALLOC(sizeof(struct wmi_t));
176 if (wmip == NULL) {
177 return (NULL);
178 }
179 A_MEMZERO(wmip, sizeof(*wmip));
180 A_MUTEX_INIT(&wmip->wmi_lock);
181 wmip->wmi_devt = devt;
182 wlan_node_table_init(wmip, &wmip->wmi_scan_table);
183 wmi_qos_state_init(wmip);
184 wmip->wmi_powerMode = REC_POWER;
185 wmip->wmi_phyMode = WMI_11G_MODE;
186
187 return (wmip);
188 }
189
190 void
191 wmi_qos_state_init(struct wmi_t *wmip)
192 {
193 A_UINT8 i;
194
195 if (wmip == NULL) {
196 return;
197 }
198 LOCK_WMI(wmip);
199
200 /* Initialize QoS States */
201 wmip->wmi_numQoSStream = 0;
202
203 wmip->wmi_fatPipeExists = 0;
204
205 for (i=0; i < WMM_NUM_AC; i++) {
206 wmip->wmi_streamExistsForAC[i]=0;
207 }
208
209 /* Initialize the static Wmi stream Pri to WMM AC mappings Arrays */
210 WMI_INIT_WMISTREAM_AC_MAP(wmip);
211
212 UNLOCK_WMI(wmip);
213
214 A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
215 }
216
217 void
218 wmi_shutdown(struct wmi_t *wmip)
219 {
220 if (wmip != NULL) {
221 wlan_node_table_cleanup(&wmip->wmi_scan_table);
222 if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
223 A_MUTEX_DELETE(&wmip->wmi_lock);
224 }
225 A_FREE(wmip);
226 }
227 }
228
229 /*
230 * performs DIX to 802.3 encapsulation for transmit packets.
231 * uses passed in buffer. Returns buffer or NULL if failed.
232 * Assumes the entire DIX header is contigous and that there is
233 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
234 */
235 A_STATUS
236 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
237 {
238 A_UINT8 *datap;
239 A_UINT16 typeorlen;
240 ATH_MAC_HDR macHdr;
241 ATH_LLC_SNAP_HDR *llcHdr;
242
243 A_ASSERT(osbuf != NULL);
244
245 if (A_NETBUF_HEADROOM(osbuf) <
246 (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
247 {
248 return A_NO_MEMORY;
249 }
250
251 datap = A_NETBUF_DATA(osbuf);
252
253 typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
254
255 if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
256 /*
257 * packet is already in 802.3 format - return success
258 */
259 A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
260 return (A_OK);
261 }
262
263 /*
264 * Save mac fields and length to be inserted later
265 */
266 A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);
267 A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
268 macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
269 sizeof(ATH_LLC_SNAP_HDR));
270
271 /*
272 * Make room for LLC+SNAP headers
273 */
274 if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
275 return A_NO_MEMORY;
276 }
277
278 datap = A_NETBUF_DATA(osbuf);
279
280 A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
281
282 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
283 llcHdr->dsap = 0xAA;
284 llcHdr->ssap = 0xAA;
285 llcHdr->cntl = 0x03;
286 llcHdr->orgCode[0] = 0x0;
287 llcHdr->orgCode[1] = 0x0;
288 llcHdr->orgCode[2] = 0x0;
289 llcHdr->etherType = typeorlen;
290
291 return (A_OK);
292 }
293
294 /*
295 * Adds a WMI data header
296 * Assumes there is enough room in the buffer to add header.
297 */
298 A_STATUS
299 wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType)
300 {
301 WMI_DATA_HDR *dtHdr;
302
303 A_ASSERT(osbuf != NULL);
304
305 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
306 return A_NO_MEMORY;
307 }
308
309 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
310 dtHdr->info = msgType;
311 dtHdr->rssi = 0;
312
313 return (A_OK);
314 }
315
316 A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up)
317 {
318 A_UINT8 *datap;
319 A_UINT8 trafficClass = WMM_AC_BE, userPriority = up;
320 ATH_LLC_SNAP_HDR *llcHdr;
321 A_UINT16 ipType = IP_ETHERTYPE;
322 WMI_DATA_HDR *dtHdr;
323 WMI_CREATE_PSTREAM_CMD cmd;
324 A_BOOL streamExists = FALSE;
325
326 A_ASSERT(osbuf != NULL);
327
328 datap = A_NETBUF_DATA(osbuf);
329
330 if (up == UNDEFINED_PRI) {
331 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) +
332 sizeof(ATH_MAC_HDR));
333
334 if (llcHdr->etherType == A_CPU2BE16(ipType)) {
335 /* Extract the endpoint info from the TOS field in the IP header */
336 userPriority = A_WMI_IPTOS_TO_USERPRIORITY(((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR));
337 }
338 }
339
340 if (userPriority < MAX_NUM_PRI) {
341 trafficClass = convert_userPriority_to_trafficClass(userPriority);
342 }
343
344 dtHdr = (WMI_DATA_HDR *)datap;
345 if(dir==UPLINK_TRAFFIC)
346 dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; /* lower 3-bits are 802.1d priority */
347
348 LOCK_WMI(wmip);
349 streamExists = wmip->wmi_fatPipeExists;
350 UNLOCK_WMI(wmip);
351
352 if (!(streamExists & (1 << trafficClass))) {
353
354 A_MEMZERO(&cmd, sizeof(cmd));
355 cmd.trafficClass = trafficClass;
356 cmd.userPriority = userPriority;
357 cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
358 /* Implicit streams are created with TSID 0xFF */
359 cmd.tsid = WMI_IMPLICIT_PSTREAM;
360 wmi_create_pstream_cmd(wmip, &cmd);
361 }
362
363 return trafficClass;
364 }
365
366 WMI_PRI_STREAM_ID
367 wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass)
368 {
369 return WMI_ACCESSCATEGORY_WMISTREAM(wmip, trafficClass);
370 }
371
372 /*
373 * performs 802.3 to DIX encapsulation for received packets.
374 * Assumes the entire 802.3 header is contigous.
375 */
376 A_STATUS
377 wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf)
378 {
379 A_UINT8 *datap;
380 ATH_MAC_HDR macHdr;
381 ATH_LLC_SNAP_HDR *llcHdr;
382
383 A_ASSERT(osbuf != NULL);
384 datap = A_NETBUF_DATA(osbuf);
385
386 A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR));
387 llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
388 macHdr.typeOrLen = llcHdr->etherType;
389
390 if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
391 return A_NO_MEMORY;
392 }
393
394 datap = A_NETBUF_DATA(osbuf);
395
396 A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
397
398 return (A_OK);
399 }
400
401 /*
402 * Removes a WMI data header
403 */
404 A_STATUS
405 wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
406 {
407 A_ASSERT(osbuf != NULL);
408
409 return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
410 }
411
412 void
413 wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
414 {
415 wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
416 }
417
418 /*
419 * WMI Extended Event received from Target.
420 */
421 A_STATUS
422 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
423 {
424 WMIX_CMD_HDR *cmd;
425 A_UINT16 id;
426 A_UINT8 *datap;
427 A_UINT32 len;
428 A_STATUS status = A_OK;
429
430 if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
431 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
432 wmip->wmi_stats.cmd_len_err++;
433 A_NETBUF_FREE(osbuf);
434 return A_ERROR;
435 }
436
437 cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
438 id = cmd->commandId;
439
440 if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
441 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
442 wmip->wmi_stats.cmd_len_err++;
443 A_NETBUF_FREE(osbuf);
444 return A_ERROR;
445 }
446
447 datap = A_NETBUF_DATA(osbuf);
448 len = A_NETBUF_LEN(osbuf);
449
450 switch (id) {
451 case (WMIX_DSETOPENREQ_EVENTID):
452 status = wmi_dset_open_req_rx(wmip, datap, len);
453 break;
454 #ifdef CONFIG_HOST_DSET_SUPPORT
455 case (WMIX_DSETCLOSE_EVENTID):
456 status = wmi_dset_close_rx(wmip, datap, len);
457 break;
458 case (WMIX_DSETDATAREQ_EVENTID):
459 status = wmi_dset_data_req_rx(wmip, datap, len);
460 break;
461 #endif /* CONFIG_HOST_DSET_SUPPORT */
462 #ifdef CONFIG_HOST_GPIO_SUPPORT
463 case (WMIX_GPIO_INTR_EVENTID):
464 wmi_gpio_intr_rx(wmip, datap, len);
465 break;
466 case (WMIX_GPIO_DATA_EVENTID):
467 wmi_gpio_data_rx(wmip, datap, len);
468 break;
469 case (WMIX_GPIO_ACK_EVENTID):
470 wmi_gpio_ack_rx(wmip, datap, len);
471 break;
472 #endif /* CONFIG_HOST_GPIO_SUPPORT */
473 case (WMIX_HB_CHALLENGE_RESP_EVENTID):
474 wmi_hbChallengeResp_rx(wmip, datap, len);
475 break;
476 case (WMIX_DBGLOG_EVENTID):
477 wmi_dbglog_event_rx(wmip, datap, len);
478 break;
479 default:
480 A_DPRINTF(DBG_WMI|DBG_ERROR,
481 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
482 wmip->wmi_stats.cmd_id_err++;
483 status = A_ERROR;
484 break;
485 }
486
487 return status;
488 }
489
490 /*
491 * Control Path
492 */
493 A_UINT32 cmdRecvNum;
494
495 A_STATUS
496 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
497 {
498 WMI_CMD_HDR *cmd;
499 A_UINT16 id;
500 A_UINT8 *datap;
501 A_UINT32 len, i, loggingReq;
502 A_STATUS status = A_OK;
503
504 A_ASSERT(osbuf != NULL);
505 if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
506 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
507 wmip->wmi_stats.cmd_len_err++;
508 A_NETBUF_FREE(osbuf);
509 return A_ERROR;
510 }
511
512 cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
513 id = cmd->commandId;
514
515 if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
516 A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
517 wmip->wmi_stats.cmd_len_err++;
518 A_NETBUF_FREE(osbuf);
519 return A_ERROR;
520 }
521
522 datap = A_NETBUF_DATA(osbuf);
523 len = A_NETBUF_LEN(osbuf);
524
525 ar6000_get_driver_cfg(wmip->wmi_devt,
526 AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
527 &loggingReq);
528
529 if(loggingReq) {
530 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
531 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
532 for(i = 0; i < len; i++)
533 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
534 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
535 }
536
537 LOCK_WMI(wmip);
538 cmdRecvNum++;
539 UNLOCK_WMI(wmip);
540
541 switch (id) {
542 case (WMI_GET_BITRATE_CMDID):
543 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
544 status = wmi_bitrate_reply_rx(wmip, datap, len);
545 break;
546 case (WMI_GET_CHANNEL_LIST_CMDID):
547 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
548 status = wmi_channelList_reply_rx(wmip, datap, len);
549 break;
550 case (WMI_GET_TX_PWR_CMDID):
551 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
552 status = wmi_txPwr_reply_rx(wmip, datap, len);
553 break;
554 case (WMI_READY_EVENTID):
555 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
556 status = wmi_ready_event_rx(wmip, datap, len);
557 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
558 A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
559 break;
560 case (WMI_CONNECT_EVENTID):
561 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
562 status = wmi_connect_event_rx(wmip, datap, len);
563 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
564 break;
565 case (WMI_DISCONNECT_EVENTID):
566 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
567 status = wmi_disconnect_event_rx(wmip, datap, len);
568 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
569 break;
570 case (WMI_TKIP_MICERR_EVENTID):
571 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
572 status = wmi_tkip_micerr_event_rx(wmip, datap, len);
573 break;
574 case (WMI_BSSINFO_EVENTID):
575 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
576 status = wmi_bssInfo_event_rx(wmip, datap, len);
577 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
578 break;
579 case (WMI_REGDOMAIN_EVENTID):
580 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
581 status = wmi_regDomain_event_rx(wmip, datap, len);
582 break;
583 case (WMI_PSTREAM_TIMEOUT_EVENTID):
584 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
585 status = wmi_pstream_timeout_event_rx(wmip, datap, len);
586 /* pstreams are fatpipe abstractions that get implicitly created.
587 * User apps only deal with thinstreams. creation of a thinstream
588 * by the user or data traffic flow in an AC triggers implicit
589 * pstream creation. Do we need to send this event to App..?
590 * no harm in sending it.
591 */
592 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
593 break;
594 case (WMI_NEIGHBOR_REPORT_EVENTID):
595 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
596 status = wmi_neighborReport_event_rx(wmip, datap, len);
597 break;
598 case (WMI_SCAN_COMPLETE_EVENTID):
599 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
600 status = wmi_scanComplete_rx(wmip, datap, len);
601 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
602 break;
603 case (WMI_CMDERROR_EVENTID):
604 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
605 status = wmi_errorEvent_rx(wmip, datap, len);
606 break;
607 case (WMI_REPORT_STATISTICS_EVENTID):
608 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
609 status = wmi_statsEvent_rx(wmip, datap, len);
610 break;
611 case (WMI_RSSI_THRESHOLD_EVENTID):
612 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
613 status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
614 break;
615 case (WMI_ERROR_REPORT_EVENTID):
616 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
617 status = wmi_reportErrorEvent_rx(wmip, datap, len);
618 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
619 break;
620 case (WMI_OPT_RX_FRAME_EVENTID):
621 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
622 status = wmi_opt_frame_event_rx(wmip, datap, len);
623 break;
624 case (WMI_REPORT_ROAM_TBL_EVENTID):
625 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
626 status = wmi_roam_tbl_event_rx(wmip, datap, len);
627 break;
628 case (WMI_EXTENSION_EVENTID):
629 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
630 status = wmi_control_rx_xtnd(wmip, osbuf);
631 break;
632 case (WMI_CAC_EVENTID):
633 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
634 status = wmi_cac_event_rx(wmip, datap, len);
635 break;
636 case (WMI_REPORT_ROAM_DATA_EVENTID):
637 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
638 status = wmi_roam_data_event_rx(wmip, datap, len);
639 break;
640 #ifdef CONFIG_HOST_TCMD_SUPPORT
641 case (WMI_TEST_EVENTID):
642 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
643 status = wmi_tcmd_test_report_rx(wmip, datap, len);
644 break;
645 #endif
646 case (WMI_GET_FIXRATES_CMDID):
647 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
648 status = wmi_ratemask_reply_rx(wmip, datap, len);
649 break;
650 case (WMI_TX_RETRY_ERR_EVENTID):
651 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
652 status = wmi_txRetryErrEvent_rx(wmip, datap, len);
653 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
654 break;
655 case (WMI_SNR_THRESHOLD_EVENTID):
656 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
657 status = wmi_snrThresholdEvent_rx(wmip, datap, len);
658 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
659 break;
660 case (WMI_LQ_THRESHOLD_EVENTID):
661 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
662 status = wmi_lqThresholdEvent_rx(wmip, datap, len);
663 A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
664 break;
665 case (WMI_APLIST_EVENTID):
666 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
667 status = wmi_aplistEvent_rx(wmip, datap, len);
668 break;
669 case (WMI_GET_KEEPALIVE_CMDID):
670 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
671 status = wmi_keepalive_reply_rx(wmip, datap, len);
672 break;
673 case (WMI_GET_WOW_LIST_EVENTID):
674 status = wmi_get_wow_list_event_rx(wmip, datap, len);
675 break;
676 case (WMI_GET_PMKID_LIST_EVENTID):
677 A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
678 status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
679 break;
680 default:
681 A_DPRINTF(DBG_WMI|DBG_ERROR,
682 (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
683 wmip->wmi_stats.cmd_id_err++;
684 status = A_ERROR;
685 break;
686 }
687
688 A_NETBUF_FREE(osbuf);
689
690 return status;
691 }
692
693 static A_STATUS
694 wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
695 {
696 WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
697
698 if (len < sizeof(WMI_READY_EVENT)) {
699 return A_EINVAL;
700 }
701 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
702 wmip->wmi_ready = TRUE;
703 A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability);
704
705 return A_OK;
706 }
707
708 static A_STATUS
709 wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
710 {
711 WMI_CONNECT_EVENT *ev;
712
713 if (len < sizeof(WMI_CONNECT_EVENT)) {
714 return A_EINVAL;
715 }
716 ev = (WMI_CONNECT_EVENT *)datap;
717 A_DPRINTF(DBG_WMI,
718 (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
719 DBGARG, ev->channel,
720 ev->bssid[0], ev->bssid[1], ev->bssid[2],
721 ev->bssid[3], ev->bssid[4], ev->bssid[5]));
722
723 A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
724
725 A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
726 ev->listenInterval, ev->beaconInterval,
727 ev->networkType, ev->beaconIeLen,
728 ev->assocReqLen, ev->assocRespLen,
729 ev->assocInfo);
730
731 return A_OK;
732 }
733
734 static A_STATUS
735 wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
736 {
737 WMI_REG_DOMAIN_EVENT *ev;
738
739 if (len < sizeof(*ev)) {
740 return A_EINVAL;
741 }
742 ev = (WMI_REG_DOMAIN_EVENT *)datap;
743
744 A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
745
746 return A_OK;
747 }
748
749 static A_STATUS
750 wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
751 {
752 WMI_NEIGHBOR_REPORT_EVENT *ev;
753 int numAps;
754
755 if (len < sizeof(*ev)) {
756 return A_EINVAL;
757 }
758 ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
759 numAps = ev->numberOfAps;
760
761 if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
762 return A_EINVAL;
763 }
764
765 A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
766
767 return A_OK;
768 }
769
770 static A_STATUS
771 wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
772 {
773 WMI_DISCONNECT_EVENT *ev;
774
775 if (len < sizeof(WMI_DISCONNECT_EVENT)) {
776 return A_EINVAL;
777 }
778 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
779
780 ev = (WMI_DISCONNECT_EVENT *)datap;
781
782 A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
783
784 A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
785 ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
786
787 return A_OK;
788 }
789
790 static A_STATUS
791 wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
792 {
793 WMI_TKIP_MICERR_EVENT *ev;
794
795 if (len < sizeof(*ev)) {
796 return A_EINVAL;
797 }
798 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
799
800 ev = (WMI_TKIP_MICERR_EVENT *)datap;
801 A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
802
803 return A_OK;
804 }
805
806 static A_STATUS
807 wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
808 {
809 bss_t *bss;
810 WMI_BSS_INFO_HDR *bih;
811 A_UINT8 *buf;
812 A_UINT32 nodeCachingAllowed;
813
814 if (len <= sizeof(WMI_BSS_INFO_HDR)) {
815 return A_EINVAL;
816 }
817
818 A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
819 /* What is driver config for wlan node caching? */
820 if(ar6000_get_driver_cfg(wmip->wmi_devt,
821 AR6000_DRIVER_CFG_GET_WLANNODECACHING,
822 &nodeCachingAllowed) != A_OK) {
823 return A_EINVAL;
824 }
825
826 if(!nodeCachingAllowed) {
827 return A_OK;
828 }
829
830
831 bih = (WMI_BSS_INFO_HDR *)datap;
832 buf = datap + sizeof(WMI_BSS_INFO_HDR);
833 len -= sizeof(WMI_BSS_INFO_HDR);
834
835 A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
836 "bssid \"%02x:%02x:%02x:%02x:%02x:%02x\"\n", DBGARG,
837 bih->channel, (unsigned char) bih->rssi, bih->bssid[0],
838 bih->bssid[1], bih->bssid[2], bih->bssid[3], bih->bssid[4],
839 bih->bssid[5]));
840
841 if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
842 printk("%s() A_OK 2\n", __FUNCTION__);
843 return A_OK;
844 }
845
846 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
847 if (bss != NULL) {
848 /*
849 * Free up the node. Not the most efficient process given
850 * we are about to allocate a new node but it is simple and should be
851 * adequate.
852 */
853 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
854 }
855
856 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
857 if (bss == NULL) {
858 return A_NO_MEMORY;
859 }
860
861 bss->ni_snr = bih->snr;
862 bss->ni_rssi = bih->rssi;
863 A_ASSERT(bss->ni_buf != NULL);
864 A_MEMCPY(bss->ni_buf, buf, len);
865
866 if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
867 wlan_node_free(bss);
868 return A_EINVAL;
869 }
870
871 /*
872 * Update the frequency in ie_chan, overwriting of channel number
873 * which is done in wlan_parse_beacon
874 */
875 bss->ni_cie.ie_chan = bih->channel;
876 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
877
878 return A_OK;
879 }
880
881 static A_STATUS
882 wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
883 {
884 bss_t *bss;
885 WMI_OPT_RX_INFO_HDR *bih;
886 A_UINT8 *buf;
887
888 if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
889 return A_EINVAL;
890 }
891
892 bih = (WMI_OPT_RX_INFO_HDR *)datap;
893 buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
894 len -= sizeof(WMI_OPT_RX_INFO_HDR);
895
896 A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
897 bih->bssid[4], bih->bssid[5]));
898
899 bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
900 if (bss != NULL) {
901 /*
902 * Free up the node. Not the most efficient process given
903 * we are about to allocate a new node but it is simple and should be
904 * adequate.
905 */
906 wlan_node_reclaim(&wmip->wmi_scan_table, bss);
907 }
908
909 bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
910 if (bss == NULL) {
911 return A_NO_MEMORY;
912 }
913
914 bss->ni_snr = bih->snr;
915 bss->ni_cie.ie_chan = bih->channel;
916 A_ASSERT(bss->ni_buf != NULL);
917 A_MEMCPY(bss->ni_buf, buf, len);
918 wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
919
920 return A_OK;
921 }
922
923 /* This event indicates inactivity timeout of a fatpipe(pstream)
924 * at the target
925 */
926 static A_STATUS
927 wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
928 {
929 WMI_PSTREAM_TIMEOUT_EVENT *ev;
930
931 if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
932 return A_EINVAL;
933 }
934
935 A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
936
937 ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
938
939 /* When the pstream (fat pipe == AC) timesout, it means there were no
940 * thinStreams within this pstream & it got implicitly created due to
941 * data flow on this AC. We start the inactivity timer only for
942 * implicitly created pstream. Just reset the host state.
943 */
944 /* Set the activeTsids for this AC to 0 */
945 LOCK_WMI(wmip);
946 wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
947 wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
948 UNLOCK_WMI(wmip);
949
950 /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
951 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
952
953 return A_OK;
954 }
955
956 static A_STATUS
957 wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
958 {
959 WMI_BIT_RATE_CMD *reply;
960 A_INT32 rate;
961
962 if (len < sizeof(WMI_BIT_RATE_CMD)) {
963 return A_EINVAL;
964 }
965 reply = (WMI_BIT_RATE_CMD *)datap;
966 A_DPRINTF(DBG_WMI,
967 (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
968
969 if (reply->rateIndex == RATE_AUTO) {
970 rate = RATE_AUTO;
971 } else {
972 rate = wmi_rateTable[(A_UINT32) reply->rateIndex];
973 }
974
975 A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
976
977 return A_OK;
978 }
979
980 static A_STATUS
981 wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
982 {
983 WMI_FIX_RATES_CMD *reply;
984
985 if (len < sizeof(WMI_BIT_RATE_CMD)) {
986 return A_EINVAL;
987 }
988 reply = (WMI_FIX_RATES_CMD *)datap;
989 A_DPRINTF(DBG_WMI,
990 (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
991
992 A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
993
994 return A_OK;
995 }
996
997 static A_STATUS
998 wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
999 {
1000 WMI_CHANNEL_LIST_REPLY *reply;
1001
1002 if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
1003 return A_EINVAL;
1004 }
1005 reply = (WMI_CHANNEL_LIST_REPLY *)datap;
1006 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1007
1008 A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
1009 reply->channelList);
1010
1011 return A_OK;
1012 }
1013
1014 static A_STATUS
1015 wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1016 {
1017 WMI_TX_PWR_REPLY *reply;
1018
1019 if (len < sizeof(*reply)) {
1020 return A_EINVAL;
1021 }
1022 reply = (WMI_TX_PWR_REPLY *)datap;
1023 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1024
1025 A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
1026
1027 return A_OK;
1028 }
1029 static A_STATUS
1030 wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1031 {
1032 WMI_GET_KEEPALIVE_CMD *reply;
1033
1034 if (len < sizeof(*reply)) {
1035 return A_EINVAL;
1036 }
1037 reply = (WMI_GET_KEEPALIVE_CMD *)datap;
1038 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1039
1040 A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
1041
1042 return A_OK;
1043 }
1044
1045
1046 static A_STATUS
1047 wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1048 {
1049 WMIX_DSETOPENREQ_EVENT *dsetopenreq;
1050
1051 if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
1052 return A_EINVAL;
1053 }
1054 dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
1055 A_DPRINTF(DBG_WMI,
1056 (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
1057 A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
1058 dsetopenreq->dset_id,
1059 dsetopenreq->targ_dset_handle,
1060 dsetopenreq->targ_reply_fn,
1061 dsetopenreq->targ_reply_arg);
1062
1063 return A_OK;
1064 }
1065
1066 #ifdef CONFIG_HOST_DSET_SUPPORT
1067 static A_STATUS
1068 wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1069 {
1070 WMIX_DSETCLOSE_EVENT *dsetclose;
1071
1072 if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
1073 return A_EINVAL;
1074 }
1075 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1076
1077 dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
1078 A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
1079
1080 return A_OK;
1081 }
1082
1083 static A_STATUS
1084 wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1085 {
1086 WMIX_DSETDATAREQ_EVENT *dsetdatareq;
1087
1088 if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
1089 return A_EINVAL;
1090 }
1091 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1092
1093 dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
1094 A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
1095 dsetdatareq->access_cookie,
1096 dsetdatareq->offset,
1097 dsetdatareq->length,
1098 dsetdatareq->targ_buf,
1099 dsetdatareq->targ_reply_fn,
1100 dsetdatareq->targ_reply_arg);
1101
1102 return A_OK;
1103 }
1104 #endif /* CONFIG_HOST_DSET_SUPPORT */
1105
1106 static A_STATUS
1107 wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1108 {
1109 WMI_SCAN_COMPLETE_EVENT *ev;
1110
1111 ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
1112 A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, ev->status);
1113
1114 return A_OK;
1115 }
1116
1117 /*
1118 * Target is reporting a programming error. This is for
1119 * developer aid only. Target only checks a few common violations
1120 * and it is responsibility of host to do all error checking.
1121 * Behavior of target after wmi error event is undefined.
1122 * A reset is recommended.
1123 */
1124 static A_STATUS
1125 wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1126 {
1127 WMI_CMD_ERROR_EVENT *ev;
1128
1129 ev = (WMI_CMD_ERROR_EVENT *)datap;
1130 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
1131 switch (ev->errorCode) {
1132 case (INVALID_PARAM):
1133 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
1134 break;
1135 case (ILLEGAL_STATE):
1136 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
1137 break;
1138 case (INTERNAL_ERROR):
1139 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
1140 break;
1141 }
1142
1143 return A_OK;
1144 }
1145
1146
1147 static A_STATUS
1148 wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1149 {
1150 WMI_TARGET_STATS *reply;
1151
1152 if (len < sizeof(*reply)) {
1153 return A_EINVAL;
1154 }
1155 reply = (WMI_TARGET_STATS *)datap;
1156 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1157
1158 A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, reply);
1159
1160 return A_OK;
1161 }
1162
1163 static A_STATUS
1164 wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1165 {
1166 WMI_RSSI_THRESHOLD_EVENT *reply;
1167
1168 if (len < sizeof(*reply)) {
1169 return A_EINVAL;
1170 }
1171 reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
1172 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1173
1174 A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, reply->range, reply->rssi);
1175
1176 return A_OK;
1177 }
1178
1179
1180 static A_STATUS
1181 wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1182 {
1183 WMI_TARGET_ERROR_REPORT_EVENT *reply;
1184
1185 if (len < sizeof(*reply)) {
1186 return A_EINVAL;
1187 }
1188 reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
1189 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1190
1191 A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, reply->errorVal);
1192
1193 return A_OK;
1194 }
1195
1196 static A_STATUS
1197 wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1198 {
1199 WMI_CAC_EVENT *reply;
1200
1201 if (len < sizeof(*reply)) {
1202 return A_EINVAL;
1203 }
1204 reply = (WMI_CAC_EVENT *)datap;
1205 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1206
1207 A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
1208 reply->cac_indication, reply->statusCode,
1209 reply->tspecSuggestion);
1210
1211 return A_OK;
1212 }
1213
1214 static A_STATUS
1215 wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1216 {
1217 WMIX_HB_CHALLENGE_RESP_EVENT *reply;
1218
1219 if (len < sizeof(*reply)) {
1220 return A_EINVAL;
1221 }
1222 reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
1223 A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
1224
1225 A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
1226
1227 return A_OK;
1228 }
1229
1230 static A_STATUS
1231 wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1232 {
1233 WMI_TARGET_ROAM_TBL *reply;
1234
1235 if (len < sizeof(*reply)) {
1236 return A_EINVAL;
1237 }
1238 reply = (WMI_TARGET_ROAM_TBL *)datap;
1239 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1240
1241 A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
1242
1243 return A_OK;
1244 }
1245
1246 static A_STATUS
1247 wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1248 {
1249 WMI_TARGET_ROAM_DATA *reply;
1250
1251 if (len < sizeof(*reply)) {
1252 return A_EINVAL;
1253 }
1254 reply = (WMI_TARGET_ROAM_DATA *)datap;
1255 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1256
1257 A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
1258
1259 return A_OK;
1260 }
1261
1262 static A_STATUS
1263 wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1264 {
1265 WMI_TX_RETRY_ERR_EVENT *reply;
1266
1267 if (len < sizeof(*reply)) {
1268 return A_EINVAL;
1269 }
1270 reply = (WMI_TX_RETRY_ERR_EVENT *)datap;
1271 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1272
1273 A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
1274
1275 return A_OK;
1276 }
1277
1278 static A_STATUS
1279 wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1280 {
1281 WMI_SNR_THRESHOLD_EVENT *reply;
1282
1283 if (len < sizeof(*reply)) {
1284 return A_EINVAL;
1285 }
1286 reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
1287 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1288
1289 A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->snr);
1290
1291 return A_OK;
1292 }
1293
1294 static A_STATUS
1295 wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1296 {
1297 WMI_LQ_THRESHOLD_EVENT *reply;
1298
1299 if (len < sizeof(*reply)) {
1300 return A_EINVAL;
1301 }
1302 reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
1303 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1304
1305 A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->lq);
1306
1307 return A_OK;
1308 }
1309
1310 static A_STATUS
1311 wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1312 {
1313 A_UINT16 ap_info_entry_size;
1314 WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
1315 WMI_AP_INFO_V1 *ap_info_v1;
1316 A_UINT8 i;
1317
1318 if (len < sizeof(WMI_APLIST_EVENT)) {
1319 return A_EINVAL;
1320 }
1321
1322 if (ev->apListVer == APLIST_VER1) {
1323 ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
1324 ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
1325 } else {
1326 return A_EINVAL;
1327 }
1328
1329 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
1330 if (len < (int)(sizeof(WMI_APLIST_EVENT) +
1331 (ev->numAP - 1) * ap_info_entry_size))
1332 {
1333 return A_EINVAL;
1334 }
1335
1336 /*
1337 * AP List Ver1 Contents
1338 */
1339 for (i = 0; i < ev->numAP; i++) {
1340 AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
1341 "Channel %d\n", i,
1342 ap_info_v1->bssid[0], ap_info_v1->bssid[1],
1343 ap_info_v1->bssid[2], ap_info_v1->bssid[3],
1344 ap_info_v1->bssid[4], ap_info_v1->bssid[5],
1345 ap_info_v1->channel));
1346 ap_info_v1++;
1347 }
1348 return A_OK;
1349 }
1350
1351 static A_STATUS
1352 wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1353 {
1354 A_UINT32 dropped;
1355
1356 dropped = *((A_UINT32 *)datap);
1357 datap += sizeof(dropped);
1358 len -= sizeof(dropped);
1359 A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, datap, len);
1360 return A_OK;
1361 }
1362
1363 #ifdef CONFIG_HOST_GPIO_SUPPORT
1364 static A_STATUS
1365 wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1366 {
1367 WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap;
1368
1369 A_DPRINTF(DBG_WMI,
1370 (DBGFMT "Enter - intrmask=0x%x input=0x%x.\n", DBGARG,
1371 gpio_intr->intr_mask, gpio_intr->input_values));
1372
1373 A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values);
1374
1375 return A_OK;
1376 }
1377
1378 static A_STATUS
1379 wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1380 {
1381 WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap;
1382
1383 A_DPRINTF(DBG_WMI,
1384 (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG,
1385 gpio_data->reg_id, gpio_data->value));
1386
1387 A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value);
1388
1389 return A_OK;
1390 }
1391
1392 static A_STATUS
1393 wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
1394 {
1395 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
1396
1397 A_WMI_GPIO_ACK_RX();
1398
1399 return A_OK;
1400 }
1401 #endif /* CONFIG_HOST_GPIO_SUPPORT */
1402
1403 /*
1404 * Called to send a wmi command. Command specific data is already built
1405 * on osbuf and current osbuf->data points to it.
1406 */
1407 A_STATUS
1408 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
1409 WMI_SYNC_FLAG syncflag)
1410 {
1411 #define IS_LONG_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID) || (cmdId == WMI_ADD_WOW_PATTERN_CMDID))
1412 WMI_CMD_HDR *cHdr;
1413 WMI_PRI_STREAM_ID streamID = WMI_CONTROL_PRI;
1414
1415 A_ASSERT(osbuf != NULL);
1416
1417 if (syncflag >= END_WMIFLAG) {
1418 return A_EINVAL;
1419 }
1420
1421 if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
1422 /*
1423 * We want to make sure all data currently queued is transmitted before
1424 * the cmd execution. Establish a new sync point.
1425 */
1426 wmi_sync_point(wmip);
1427 }
1428
1429 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
1430 return A_NO_MEMORY;
1431 }
1432
1433 cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
1434 cHdr->commandId = cmdId;
1435
1436 /*
1437 * Send cmd, some via control pipe, others via data pipe
1438 */
1439 if (IS_LONG_CMD(cmdId)) {
1440 wmi_data_hdr_add(wmip, osbuf, CNTL_MSGTYPE);
1441 // TODO ... these can now go through the control endpoint via HTC 2.0
1442 streamID = WMI_BEST_EFFORT_PRI;
1443 }
1444 A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID);
1445
1446 if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
1447 /*
1448 * We want to make sure all new data queued waits for the command to
1449 * execute. Establish a new sync point.
1450 */
1451 wmi_sync_point(wmip);
1452 }
1453 return (A_OK);
1454 #undef IS_LONG_CMD
1455 }
1456
1457 A_STATUS
1458 wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
1459 WMI_SYNC_FLAG syncflag)
1460 {
1461 WMIX_CMD_HDR *cHdr;
1462
1463 if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
1464 return A_NO_MEMORY;
1465 }
1466
1467 cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
1468 cHdr->commandId = cmdId;
1469
1470 return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
1471 }
1472
1473 A_STATUS
1474 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
1475 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
1476 CRYPTO_TYPE pairwiseCrypto, A_UINT8 pairwiseCryptoLen,
1477 CRYPTO_TYPE groupCrypto,A_UINT8 groupCryptoLen,
1478 int ssidLength, A_UCHAR *ssid,
1479 A_UINT8 *bssid, A_UINT16 channel, A_UINT32 ctrl_flags)
1480 {
1481 void *osbuf;
1482 WMI_CONNECT_CMD *cc;
1483
1484 if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
1485 return A_EINVAL;
1486 }
1487 if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
1488 return A_EINVAL;
1489 }
1490
1491 osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
1492 if (osbuf == NULL) {
1493 return A_NO_MEMORY;
1494 }
1495
1496 A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
1497
1498 cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
1499 A_MEMZERO(cc, sizeof(*cc));
1500
1501 A_MEMCPY(cc->ssid, ssid, ssidLength);
1502 cc->ssidLength = ssidLength;
1503 cc->networkType = netType;
1504 cc->dot11AuthMode = dot11AuthMode;
1505 cc->authMode = authMode;
1506 cc->pairwiseCryptoType = pairwiseCrypto;
1507 cc->pairwiseCryptoLen = pairwiseCryptoLen;
1508 cc->groupCryptoType = groupCrypto;
1509 cc->groupCryptoLen = groupCryptoLen;
1510 cc->channel = channel;
1511 cc->ctrl_flags = ctrl_flags;
1512
1513 if (bssid != NULL) {
1514 A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
1515 }
1516 if (wmi_set_keepalive_cmd(wmip, wmip->wmi_keepaliveInterval) != A_OK) {
1517 return(A_ERROR);
1518 }
1519
1520 return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
1521 }
1522
1523 A_STATUS
1524 wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel)
1525 {
1526 void *osbuf;
1527 WMI_RECONNECT_CMD *cc;
1528
1529 osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
1530 if (osbuf == NULL) {
1531 return A_NO_MEMORY;
1532 }
1533
1534 A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
1535
1536 cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
1537 A_MEMZERO(cc, sizeof(*cc));
1538
1539 cc->channel = channel;
1540
1541 if (bssid != NULL) {
1542 A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
1543 }
1544
1545 return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
1546 }
1547
1548 A_STATUS
1549 wmi_disconnect_cmd(struct wmi_t *wmip)
1550 {
1551 void *osbuf;
1552 A_STATUS status;
1553
1554 osbuf = A_NETBUF_ALLOC(0); /* no payload */
1555 if (osbuf == NULL) {
1556 return A_NO_MEMORY;
1557 }
1558
1559 /* Bug fix for 24817(elevator bug) - the disconnect command does not
1560 need to do a SYNC before.*/
1561 status = (wmi_cmd_send(wmip, osbuf, WMI_DISCONNECT_CMDID,
1562 NO_SYNC_WMIFLAG));
1563
1564 return status;
1565 }
1566
1567 A_STATUS
1568 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
1569 A_BOOL forceFgScan, A_BOOL isLegacy,
1570 A_UINT32 homeDwellTime, A_UINT32 forceScanInterval)
1571 {
1572 void *osbuf;
1573 WMI_START_SCAN_CMD *sc;
1574
1575 if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
1576 return A_EINVAL;
1577 }
1578
1579 osbuf = A_NETBUF_ALLOC(sizeof(*sc));
1580 if (osbuf == NULL) {
1581 return A_NO_MEMORY;
1582 }
1583
1584 A_NETBUF_PUT(osbuf, sizeof(*sc));
1585
1586 sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
1587 sc->scanType = scanType;
1588 sc->forceFgScan = forceFgScan;
1589 sc->isLegacy = isLegacy;
1590 sc->homeDwellTime = homeDwellTime;
1591 sc->forceScanInterval = forceScanInterval;
1592
1593 return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
1594 }
1595
1596 A_STATUS
1597 wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
1598 A_UINT16 fg_end_sec, A_UINT16 bg_sec,
1599 A_UINT16 minact_chdw_msec, A_UINT16 maxact_chdw_msec,
1600 A_UINT16 pas_chdw_msec,
1601 A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
1602 A_UINT32 max_dfsch_act_time)
1603 {
1604 void *osbuf;
1605 WMI_SCAN_PARAMS_CMD *sc;
1606
1607 osbuf = A_NETBUF_ALLOC(sizeof(*sc));
1608 if (osbuf == NULL) {
1609 return A_NO_MEMORY;
1610 }
1611
1612 A_NETBUF_PUT(osbuf, sizeof(*sc));
1613
1614 sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
1615 A_MEMZERO(sc, sizeof(*sc));
1616 sc->fg_start_period = fg_start_sec;
1617 sc->fg_end_period = fg_end_sec;
1618 sc->bg_period = bg_sec;
1619 sc->minact_chdwell_time = minact_chdw_msec;
1620 sc->maxact_chdwell_time = maxact_chdw_msec;
1621 sc->pas_chdwell_time = pas_chdw_msec;
1622 sc->shortScanRatio = shScanRatio;
1623 sc->scanCtrlFlags = scanCtrlFlags;
1624 sc->max_dfsch_act_time = max_dfsch_act_time;
1625
1626 return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
1627 NO_SYNC_WMIFLAG));
1628 }
1629
1630 A_STATUS
1631 wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask)
1632 {
1633 void *osbuf;
1634 WMI_BSS_FILTER_CMD *cmd;
1635
1636 if (filter >= LAST_BSS_FILTER) {
1637 return A_EINVAL;
1638 }
1639
1640 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1641 if (osbuf == NULL) {
1642 return A_NO_MEMORY;
1643 }
1644
1645 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1646
1647 cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
1648 A_MEMZERO(cmd, sizeof(*cmd));
1649 cmd->bssFilter = filter;
1650 cmd->ieMask = ieMask;
1651
1652 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
1653 NO_SYNC_WMIFLAG));
1654 }
1655
1656 A_STATUS
1657 wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
1658 A_UINT8 ssidLength, A_UCHAR *ssid)
1659 {
1660 void *osbuf;
1661 WMI_PROBED_SSID_CMD *cmd;
1662
1663 if (index > MAX_PROBED_SSID_INDEX) {
1664 return A_EINVAL;
1665 }
1666 if (ssidLength > sizeof(cmd->ssid)) {
1667 return A_EINVAL;
1668 }
1669 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
1670 return A_EINVAL;
1671 }
1672 if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
1673 return A_EINVAL;
1674 }
1675
1676 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1677 if (osbuf == NULL) {
1678 return A_NO_MEMORY;
1679 }
1680
1681 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1682
1683 cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
1684 A_MEMZERO(cmd, sizeof(*cmd));
1685 cmd->entryIndex = index;
1686 cmd->flag = flag;
1687 cmd->ssidLength = ssidLength;
1688 A_MEMCPY(cmd->ssid, ssid, ssidLength);
1689
1690 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
1691 NO_SYNC_WMIFLAG));
1692 }
1693
1694 A_STATUS
1695 wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons)
1696 {
1697 void *osbuf;
1698 WMI_LISTEN_INT_CMD *cmd;
1699
1700 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1701 if (osbuf == NULL) {
1702 return A_NO_MEMORY;
1703 }
1704
1705 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1706
1707 cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
1708 A_MEMZERO(cmd, sizeof(*cmd));
1709 cmd->listenInterval = listenInterval;
1710 cmd->numBeacons = listenBeacons;
1711
1712 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
1713 NO_SYNC_WMIFLAG));
1714 }
1715
1716 A_STATUS
1717 wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons)
1718 {
1719 void *osbuf;
1720 WMI_BMISS_TIME_CMD *cmd;
1721
1722 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1723 if (osbuf == NULL) {
1724 return A_NO_MEMORY;
1725 }
1726
1727 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1728
1729 cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
1730 A_MEMZERO(cmd, sizeof(*cmd));
1731 cmd->bmissTime = bmissTime;
1732 cmd->numBeacons = bmissBeacons;
1733
1734 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
1735 NO_SYNC_WMIFLAG));
1736 }
1737
1738 A_STATUS
1739 wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
1740 A_UINT8 ieLen, A_UINT8 *ieInfo)
1741 {
1742 void *osbuf;
1743 WMI_SET_ASSOC_INFO_CMD *cmd;
1744 A_UINT16 cmdLen;
1745
1746 cmdLen = sizeof(*cmd) + ieLen - 1;
1747 osbuf = A_NETBUF_ALLOC(cmdLen);
1748 if (osbuf == NULL) {
1749 return A_NO_MEMORY;
1750 }
1751
1752 A_NETBUF_PUT(osbuf, cmdLen);
1753
1754 cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
1755 A_MEMZERO(cmd, cmdLen);
1756 cmd->ieType = ieType;
1757 cmd->bufferSize = ieLen;
1758 A_MEMCPY(cmd->assocInfo, ieInfo, ieLen);
1759
1760 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
1761 NO_SYNC_WMIFLAG));
1762 }
1763
1764 A_STATUS
1765 wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode)
1766 {
1767 void *osbuf;
1768 WMI_POWER_MODE_CMD *cmd;
1769
1770 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1771 if (osbuf == NULL) {
1772 return A_NO_MEMORY;
1773 }
1774
1775 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1776
1777 cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
1778 A_MEMZERO(cmd, sizeof(*cmd));
1779 cmd->powerMode = powerMode;
1780 wmip->wmi_powerMode = powerMode;
1781
1782 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
1783 NO_SYNC_WMIFLAG));
1784 }
1785
1786 A_STATUS
1787 wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
1788 A_UINT16 atim_windows, A_UINT16 timeout_value)
1789 {
1790 void *osbuf;
1791 WMI_IBSS_PM_CAPS_CMD *cmd;
1792
1793 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1794 if (osbuf == NULL) {
1795 return A_NO_MEMORY;
1796 }
1797
1798 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1799
1800 cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
1801 A_MEMZERO(cmd, sizeof(*cmd));
1802 cmd->power_saving = pmEnable;
1803 cmd->ttl = ttl;
1804 cmd->atim_windows = atim_windows;
1805 cmd->timeout_value = timeout_value;
1806
1807 return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
1808 NO_SYNC_WMIFLAG));
1809 }
1810
1811 A_STATUS
1812 wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
1813 A_UINT16 psPollNum, A_UINT16 dtimPolicy)
1814 {
1815 void *osbuf;
1816 WMI_POWER_PARAMS_CMD *pm;
1817
1818 osbuf = A_NETBUF_ALLOC(sizeof(*pm));
1819 if (osbuf == NULL) {
1820 return A_NO_MEMORY;
1821 }
1822
1823 A_NETBUF_PUT(osbuf, sizeof(*pm));
1824
1825 pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
1826 A_MEMZERO(pm, sizeof(*pm));
1827 pm->idle_period = idlePeriod;
1828 pm->pspoll_number = psPollNum;
1829 pm->dtim_policy = dtimPolicy;
1830
1831 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
1832 NO_SYNC_WMIFLAG));
1833 }
1834
1835 A_STATUS
1836 wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout)
1837 {
1838 void *osbuf;
1839 WMI_DISC_TIMEOUT_CMD *cmd;
1840
1841 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1842 if (osbuf == NULL) {
1843 return A_NO_MEMORY;
1844 }
1845
1846 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1847
1848 cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
1849 A_MEMZERO(cmd, sizeof(*cmd));
1850 cmd->disconnectTimeout = timeout;
1851
1852 return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
1853 NO_SYNC_WMIFLAG));
1854 }
1855
1856 A_STATUS
1857 wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType,
1858 A_UINT8 keyUsage, A_UINT8 keyLength, A_UINT8 *keyRSC,
1859 A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl,
1860 WMI_SYNC_FLAG sync_flag)
1861 {
1862 void *osbuf;
1863 WMI_ADD_CIPHER_KEY_CMD *cmd;
1864
1865 if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
1866 (keyMaterial == NULL))
1867 {
1868 return A_EINVAL;
1869 }
1870
1871 if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
1872 return A_EINVAL;
1873 }
1874
1875 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1876 if (osbuf == NULL) {
1877 return A_NO_MEMORY;
1878 }
1879
1880 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1881
1882 cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
1883 A_MEMZERO(cmd, sizeof(*cmd));
1884 cmd->keyIndex = keyIndex;
1885 cmd->keyType = keyType;
1886 cmd->keyUsage = keyUsage;
1887 cmd->keyLength = keyLength;
1888 A_MEMCPY(cmd->key, keyMaterial, keyLength);
1889 if (NULL != keyRSC) {
1890 A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
1891 }
1892 cmd->key_op_ctrl = key_op_ctrl;
1893
1894 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
1895 }
1896
1897 A_STATUS
1898 wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk)
1899 {
1900 void *osbuf;
1901 WMI_ADD_KRK_CMD *cmd;
1902
1903 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1904
1905 if (osbuf == NULL) {
1906 return A_NO_MEMORY;
1907 }
1908
1909 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1910
1911 cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
1912 A_MEMZERO(cmd, sizeof(*cmd));
1913 A_MEMCPY(cmd->krk, krk, WMI_KRK_LEN);
1914
1915 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
1916 }
1917
1918 A_STATUS
1919 wmi_delete_krk_cmd(struct wmi_t *wmip)
1920 {
1921 void *osbuf;
1922
1923 osbuf = A_NETBUF_ALLOC(0);
1924
1925 if (osbuf == NULL) {
1926 return A_NO_MEMORY;
1927 }
1928
1929 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_KRK_CMDID, NO_SYNC_WMIFLAG));
1930 }
1931
1932 A_STATUS
1933 wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex)
1934 {
1935 void *osbuf;
1936 WMI_DELETE_CIPHER_KEY_CMD *cmd;
1937
1938 if (keyIndex > WMI_MAX_KEY_INDEX) {
1939 return A_EINVAL;
1940 }
1941
1942 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1943 if (osbuf == NULL) {
1944 return A_NO_MEMORY;
1945 }
1946
1947 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1948
1949 cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
1950 A_MEMZERO(cmd, sizeof(*cmd));
1951 cmd->keyIndex = keyIndex;
1952
1953 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
1954 NO_SYNC_WMIFLAG));
1955 }
1956
1957 A_STATUS
1958 wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
1959 A_BOOL set)
1960 {
1961 void *osbuf;
1962 WMI_SET_PMKID_CMD *cmd;
1963
1964 if (bssid == NULL) {
1965 return A_EINVAL;
1966 }
1967
1968 if ((set == TRUE) && (pmkId == NULL)) {
1969 return A_EINVAL;
1970 }
1971
1972 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1973 if (osbuf == NULL) {
1974 return A_NO_MEMORY;
1975 }
1976
1977 A_NETBUF_PUT(osbuf, sizeof(*cmd));
1978
1979 cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
1980 A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
1981 if (set == TRUE) {
1982 A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
1983 cmd->enable = PMKID_ENABLE;
1984 } else {
1985 A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
1986 cmd->enable = PMKID_DISABLE;
1987 }
1988
1989 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
1990 }
1991
1992 A_STATUS
1993 wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
1994 {
1995 void *osbuf;
1996 WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
1997
1998 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
1999 if (osbuf == NULL) {
2000 return A_NO_MEMORY;
2001 }
2002
2003 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2004
2005 cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
2006 cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
2007
2008 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
2009 NO_SYNC_WMIFLAG));
2010 }
2011
2012 A_STATUS
2013 wmi_set_akmp_params_cmd(struct wmi_t *wmip,
2014 WMI_SET_AKMP_PARAMS_CMD *akmpParams)
2015 {
2016 void *osbuf;
2017 WMI_SET_AKMP_PARAMS_CMD *cmd;
2018
2019 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2020 if (osbuf == NULL) {
2021 return A_NO_MEMORY;
2022 }
2023
2024 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2025 cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2026 cmd->akmpInfo = akmpParams->akmpInfo;
2027
2028 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
2029 NO_SYNC_WMIFLAG));
2030 }
2031
2032 A_STATUS
2033 wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
2034 WMI_SET_PMKID_LIST_CMD *pmkInfo)
2035 {
2036 void *osbuf;
2037 WMI_SET_PMKID_LIST_CMD *cmd;
2038 A_UINT16 cmdLen;
2039 A_UINT8 i;
2040
2041 cmdLen = sizeof(pmkInfo->numPMKID) +
2042 pmkInfo->numPMKID * sizeof(WMI_PMKID);
2043
2044 osbuf = A_NETBUF_ALLOC(cmdLen);
2045
2046 if (osbuf == NULL) {
2047 return A_NO_MEMORY;
2048 }
2049
2050 A_NETBUF_PUT(osbuf, cmdLen);
2051 cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
2052 cmd->numPMKID = pmkInfo->numPMKID;
2053
2054 for (i = 0; i < cmd->numPMKID; i++) {
2055 A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
2056 WMI_PMKID_LEN);
2057 }
2058
2059 return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
2060 NO_SYNC_WMIFLAG));
2061 }
2062
2063 A_STATUS
2064 wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
2065 {
2066 void *osbuf;
2067
2068 osbuf = A_NETBUF_ALLOC(0); /* no payload */
2069 if (osbuf == NULL) {
2070 return A_NO_MEMORY;
2071 }
2072
2073 return (wmi_cmd_send(wmip, osbuf, WMI_GET_PMKID_LIST_CMDID,
2074 NO_SYNC_WMIFLAG));
2075 }
2076
2077 A_STATUS
2078 wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, WMI_PRI_STREAM_ID streamID)
2079 {
2080 WMI_DATA_HDR *dtHdr;
2081
2082 A_ASSERT(streamID != WMI_CONTROL_PRI);
2083 A_ASSERT(osbuf != NULL);
2084
2085 if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
2086 return A_NO_MEMORY;
2087 }
2088
2089 dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
2090 dtHdr->info =
2091 (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
2092
2093 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - streamID %d\n", DBGARG, streamID));
2094
2095 return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID));
2096 }
2097
2098 typedef struct _WMI_DATA_SYNC_BUFS {
2099 A_UINT8 trafficClass;
2100 void *osbuf;
2101 }WMI_DATA_SYNC_BUFS;
2102
2103 static A_STATUS
2104 wmi_sync_point(struct wmi_t *wmip)
2105 {
2106 void *cmd_osbuf;
2107 WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
2108 A_UINT8 i,numPriStreams=0;
2109 A_STATUS status;
2110
2111 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
2112
2113 memset(dataSyncBufs,0,sizeof(dataSyncBufs));
2114
2115 /* lock out while we walk through the priority list and assemble our local array */
2116 LOCK_WMI(wmip);
2117
2118 for (i=0; i < WMM_NUM_AC ; i++) {
2119 if (wmip->wmi_fatPipeExists & (1 << i)) {
2120 numPriStreams++;
2121 dataSyncBufs[numPriStreams-1].trafficClass = i;
2122 }
2123 }
2124
2125 UNLOCK_WMI(wmip);
2126
2127 /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
2128
2129 do {
2130 /*
2131 * We allocate all network buffers needed so we will be able to
2132 * send all required frames.
2133 */
2134 cmd_osbuf = A_NETBUF_ALLOC(0); /* no payload */
2135 if (cmd_osbuf == NULL) {
2136 status = A_NO_MEMORY;
2137 break;
2138 }
2139
2140 for (i=0; i < numPriStreams ; i++) {
2141 dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
2142 if (dataSyncBufs[i].osbuf == NULL) {
2143 status = A_NO_MEMORY;
2144 break;
2145 }
2146 } //end for
2147
2148 /*
2149 * Send sync cmd followed by sync data messages on all endpoints being
2150 * used
2151 */
2152 status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
2153 NO_SYNC_WMIFLAG);
2154
2155 if (A_FAILED(status)) {
2156 break;
2157 }
2158 /* cmd buffer sent, we no longer own it */
2159 cmd_osbuf = NULL;
2160
2161 for(i=0; i < numPriStreams; i++) {
2162 A_ASSERT(dataSyncBufs[i].osbuf != NULL);
2163
2164 status = wmi_dataSync_send(wmip, dataSyncBufs[i].osbuf,
2165 WMI_ACCESSCATEGORY_WMISTREAM(wmip,dataSyncBufs[i].trafficClass));
2166
2167 if (A_FAILED(status)) {
2168 break;
2169 }
2170 /* we don't own this buffer anymore, NULL it out of the array so it
2171 * won't get cleaned up */
2172 dataSyncBufs[i].osbuf = NULL;
2173 } //end for
2174
2175 } while(FALSE);
2176
2177 /* free up any resources left over (possibly due to an error) */
2178
2179 if (cmd_osbuf != NULL) {
2180 A_NETBUF_FREE(cmd_osbuf);
2181 }
2182
2183 for (i = 0; i < numPriStreams; i++) {
2184 if (dataSyncBufs[i].osbuf != NULL) {
2185 A_NETBUF_FREE(dataSyncBufs[i].osbuf);
2186 }
2187 }
2188
2189 return (status);
2190 }
2191
2192 A_STATUS
2193 wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
2194 {
2195 void *osbuf;
2196 WMI_CREATE_PSTREAM_CMD *cmd;
2197 A_UINT16 activeTsids=0;
2198 A_UINT8 fatPipeExistsForAC=0;
2199
2200 /* Validate all the parameters. */
2201 if( !((params->userPriority < 8) &&
2202 (params->userPriority <= 0x7) &&
2203 (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) &&
2204 (params->trafficDirection == UPLINK_TRAFFIC ||
2205 params->trafficDirection == DNLINK_TRAFFIC ||
2206 params->trafficDirection == BIDIR_TRAFFIC) &&
2207 (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
2208 params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
2209 (params->voicePSCapability == DISABLE_FOR_THIS_AC ||
2210 params->voicePSCapability == ENABLE_FOR_THIS_AC ||
2211 params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
2212 (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
2213 {
2214 return A_EINVAL;
2215 }
2216
2217 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2218 if (osbuf == NULL) {
2219 return A_NO_MEMORY;
2220 }
2221
2222 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2223
2224 A_DPRINTF(DBG_WMI,
2225 (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
2226 params->trafficClass, params->tsid));
2227
2228 cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
2229 A_MEMZERO(cmd, sizeof(*cmd));
2230 A_MEMCPY(cmd, params, sizeof(*cmd));
2231
2232 /* this is an implicitly created Fat pipe */
2233 if (params->tsid == WMI_IMPLICIT_PSTREAM) {
2234 LOCK_WMI(wmip);
2235 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
2236 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
2237 UNLOCK_WMI(wmip);
2238 } else {
2239 /* this is an explicitly created thin stream within a fat pipe */
2240 LOCK_WMI(wmip);
2241 fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
2242 activeTsids = wmip->wmi_streamExistsForAC[params->trafficClass];
2243 wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
2244 /* if a thinstream becomes active, the fat pipe automatically
2245 * becomes active
2246 */
2247 wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
2248 UNLOCK_WMI(wmip);
2249 }
2250
2251 /* Indicate activty change to driver layer only if this is the
2252 * first TSID to get created in this AC explicitly or an implicit
2253 * fat pipe is getting created.
2254 */
2255 if (!fatPipeExistsForAC) {
2256 A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
2257 }
2258
2259 /* mike: should be SYNC_BEFORE_WMIFLAG */
2260 return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
2261 NO_SYNC_WMIFLAG));
2262 }
2263
2264 A_STATUS
2265 wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid)
2266 {
2267 void *osbuf;
2268 WMI_DELETE_PSTREAM_CMD *cmd;
2269 A_STATUS status;
2270 A_UINT16 activeTsids=0;
2271
2272 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2273 if (osbuf == NULL) {
2274 return A_NO_MEMORY;
2275 }
2276
2277 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2278
2279 cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
2280 A_MEMZERO(cmd, sizeof(*cmd));
2281
2282 cmd->trafficClass = trafficClass;
2283 cmd->tsid = tsid;
2284
2285 LOCK_WMI(wmip);
2286 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
2287 UNLOCK_WMI(wmip);
2288
2289 /* Check if the tsid was created & exists */
2290 if (!(activeTsids & (1<<tsid))) {
2291
2292 A_DPRINTF(DBG_WMI,
2293 (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
2294 /* TODO: return a more appropriate err code */
2295 return A_ERROR;
2296 }
2297
2298 A_DPRINTF(DBG_WMI,
2299 (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
2300
2301 status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
2302 SYNC_BEFORE_WMIFLAG));
2303
2304 LOCK_WMI(wmip);
2305 wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
2306 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
2307 UNLOCK_WMI(wmip);
2308
2309
2310 /* Indicate stream inactivity to driver layer only if all tsids
2311 * within this AC are deleted.
2312 */
2313 if(!activeTsids) {
2314 A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
2315 wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
2316 }
2317
2318 return status;
2319 }
2320
2321 /*
2322 * used to set the bit rate. rate is in Kbps. If rate == -1
2323 * then auto selection is used.
2324 */
2325 A_STATUS
2326 wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 rate)
2327 {
2328 void *osbuf;
2329 WMI_BIT_RATE_CMD *cmd;
2330 A_INT8 index;
2331
2332 if (rate != -1) {
2333 index = wmi_validate_bitrate(wmip, rate);
2334 if(index == A_EINVAL){
2335 return A_EINVAL;
2336 }
2337 } else {
2338 index = -1;
2339 }
2340
2341 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2342 if (osbuf == NULL) {
2343 return A_NO_MEMORY;
2344 }
2345
2346 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2347
2348 cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
2349 A_MEMZERO(cmd, sizeof(*cmd));
2350
2351 cmd->rateIndex = index;
2352
2353 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
2354 }
2355
2356 A_STATUS
2357 wmi_get_bitrate_cmd(struct wmi_t *wmip)
2358 {
2359 void *osbuf;
2360
2361 osbuf = A_NETBUF_ALLOC(0); /* no payload */
2362 if (osbuf == NULL) {
2363 return A_NO_MEMORY;
2364 }
2365
2366 return (wmi_cmd_send(wmip, osbuf, WMI_GET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
2367 }
2368
2369 /*
2370 * Returns TRUE iff the given rate index is legal in the current PHY mode.
2371 */
2372 A_BOOL
2373 wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex)
2374 {
2375 WMI_PHY_MODE phyMode = wmip->wmi_phyMode;
2376 A_BOOL isValid = TRUE;
2377 switch(phyMode) {
2378 case WMI_11A_MODE:
2379 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
2380 isValid = FALSE;
2381 }
2382 break;
2383
2384 case WMI_11B_MODE:
2385 if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
2386 isValid = FALSE;
2387 }
2388 break;
2389
2390 case WMI_11GONLY_MODE:
2391 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
2392 isValid = FALSE;
2393 }
2394 break;
2395
2396 case WMI_11G_MODE:
2397 case WMI_11AG_MODE:
2398 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
2399 isValid = FALSE;
2400 }
2401 break;
2402
2403 default:
2404 A_ASSERT(FALSE);
2405 break;
2406 }
2407
2408 return isValid;
2409 }
2410
2411 A_INT8
2412 wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate)
2413 {
2414 A_INT8 i;
2415 if (rate != -1)
2416 {
2417 for (i=0;;i++)
2418 {
2419 if (wmi_rateTable[(A_UINT32) i] == 0) {
2420 return A_EINVAL;
2421 }
2422 if (wmi_rateTable[(A_UINT32) i] == rate) {
2423 break;
2424 }
2425 }
2426 }
2427 else{
2428 i = -1;
2429 }
2430
2431 if(wmi_is_bitrate_index_valid(wmip, i) != TRUE) {
2432 return A_EINVAL;
2433 }
2434
2435 return i;
2436 }
2437
2438 A_STATUS
2439 wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask)
2440 {
2441 void *osbuf;
2442 WMI_FIX_RATES_CMD *cmd;
2443 A_UINT32 rateIndex;
2444
2445 /* Make sure all rates in the mask are valid in the current PHY mode */
2446 for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
2447 if((1 << rateIndex) & (A_UINT32)fixRatesMask) {
2448 if(wmi_is_bitrate_index_valid(wmip, rateIndex) != TRUE) {
2449 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
2450 return A_EINVAL;
2451 }
2452 }
2453 }
2454
2455
2456 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2457 if (osbuf == NULL) {
2458 return A_NO_MEMORY;
2459 }
2460
2461 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2462
2463 cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
2464 A_MEMZERO(cmd, sizeof(*cmd));
2465
2466 cmd->fixRateMask = fixRatesMask;
2467
2468 return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
2469 }
2470
2471 A_STATUS
2472 wmi_get_ratemask_cmd(struct wmi_t *wmip)
2473 {
2474 void *osbuf;
2475
2476 osbuf = A_NETBUF_ALLOC(0); /* no payload */
2477 if (osbuf == NULL) {
2478 return A_NO_MEMORY;
2479 }
2480
2481 return (wmi_cmd_send(wmip, osbuf, WMI_GET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
2482 }
2483
2484 A_STATUS
2485 wmi_get_channelList_cmd(struct wmi_t *wmip)
2486 {
2487 void *osbuf;
2488
2489 osbuf = A_NETBUF_ALLOC(0); /* no payload */
2490 if (osbuf == NULL) {
2491 return A_NO_MEMORY;
2492 }
2493
2494 return (wmi_cmd_send(wmip, osbuf, WMI_GET_CHANNEL_LIST_CMDID,
2495 NO_SYNC_WMIFLAG));
2496 }
2497
2498 /*
2499 * used to generate a wmi sey channel Parameters cmd.
2500 * mode should always be specified and corresponds to the phy mode of the
2501 * wlan.
2502 * numChan should alway sbe specified. If zero indicates that all available
2503 * channels should be used.
2504 * channelList is an array of channel frequencies (in Mhz) which the radio
2505 * should limit its operation to. It should be NULL if numChan == 0. Size of
2506 * array should correspond to numChan entries.
2507 */
2508 A_STATUS
2509 wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
2510 WMI_PHY_MODE mode, A_INT8 numChan,
2511 A_UINT16 *channelList)
2512 {
2513 void *osbuf;
2514 WMI_CHANNEL_PARAMS_CMD *cmd;
2515 A_INT8 size;
2516
2517 size = sizeof (*cmd);
2518
2519 if (numChan) {
2520 if (numChan > WMI_MAX_CHANNELS) {
2521 return A_EINVAL;
2522 }
2523 size += sizeof(A_UINT16) * (numChan - 1);
2524 }
2525
2526 osbuf = A_NETBUF_ALLOC(size);
2527 if (osbuf == NULL) {
2528 return A_NO_MEMORY;
2529 }
2530
2531 A_NETBUF_PUT(osbuf, size);
2532
2533 cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2534 A_MEMZERO(cmd, size);
2535
2536 wmip->wmi_phyMode = mode;
2537 cmd->scanParam = scanParam;
2538 cmd->phyMode = mode;
2539 cmd->numChannels = numChan;
2540 A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16));
2541
2542 return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
2543 NO_SYNC_WMIFLAG));
2544 }
2545
2546 A_STATUS
2547 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
2548 WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
2549 {
2550 void *osbuf;
2551 A_INT8 size;
2552 WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
2553 /* These values are in ascending order */
2554 if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
2555 rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
2556 rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
2557 rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
2558 rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
2559 rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
2560 rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
2561 rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
2562 rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
2563 rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) {
2564
2565 return A_EINVAL;
2566 }
2567
2568 size = sizeof (*cmd);
2569
2570 osbuf = A_NETBUF_ALLOC(size);
2571 if (osbuf == NULL) {
2572 return A_NO_MEMORY;
2573 }
2574
2575 A_NETBUF_PUT(osbuf, size);
2576
2577 cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2578 A_MEMZERO(cmd, size);
2579 A_MEMCPY(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
2580
2581 return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
2582 NO_SYNC_WMIFLAG));
2583 }
2584
2585 A_STATUS
2586 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
2587 WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
2588 {
2589 void *osbuf;
2590 A_INT8 size;
2591 WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
2592
2593 if( hostModeCmd->awake == hostModeCmd->asleep) {
2594 return A_EINVAL;
2595 }
2596
2597 size = sizeof (*cmd);
2598
2599 osbuf = A_NETBUF_ALLOC(size);
2600 if (osbuf == NULL) {
2601 return A_NO_MEMORY;
2602 }
2603
2604 A_NETBUF_PUT(osbuf, size);
2605
2606 cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
2607 A_MEMZERO(cmd, size);
2608 A_MEMCPY(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
2609
2610 return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
2611 NO_SYNC_WMIFLAG));
2612 }
2613
2614 A_STATUS
2615 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
2616 WMI_SET_WOW_MODE_CMD *wowModeCmd)
2617 {
2618 void *osbuf;
2619 A_INT8 size;
2620 WMI_SET_WOW_MODE_CMD *cmd;
2621
2622 size = sizeof (*cmd);
2623
2624 osbuf = A_NETBUF_ALLOC(size);
2625 if (osbuf == NULL) {
2626 return A_NO_MEMORY;
2627 }
2628
2629 A_NETBUF_PUT(osbuf, size);
2630
2631 cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
2632 A_MEMZERO(cmd, size);
2633 A_MEMCPY(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
2634
2635 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
2636 NO_SYNC_WMIFLAG));
2637
2638 }
2639
2640 A_STATUS
2641 wmi_get_wow_list_cmd(struct wmi_t *wmip,
2642 WMI_GET_WOW_LIST_CMD *wowListCmd)
2643 {
2644 void *osbuf;
2645 A_INT8 size;
2646 WMI_GET_WOW_LIST_CMD *cmd;
2647
2648 size = sizeof (*cmd);
2649
2650 osbuf = A_NETBUF_ALLOC(size);
2651 if (osbuf == NULL) {
2652 return A_NO_MEMORY;
2653 }
2654
2655 A_NETBUF_PUT(osbuf, size);
2656
2657 cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
2658 A_MEMZERO(cmd, size);
2659 A_MEMCPY(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
2660
2661 return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
2662 NO_SYNC_WMIFLAG));
2663
2664 }
2665
2666 static A_STATUS
2667 wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
2668 {
2669 WMI_GET_WOW_LIST_REPLY *reply;
2670
2671 if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
2672 return A_EINVAL;
2673 }
2674 reply = (WMI_GET_WOW_LIST_REPLY *)datap;
2675
2676 A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
2677 reply);
2678
2679 return A_OK;
2680 }
2681
2682 A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
2683 WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
2684 A_UINT8* pattern, A_UINT8* mask,
2685 A_UINT8 pattern_size)
2686 {
2687 void *osbuf;
2688 A_INT8 size;
2689 WMI_ADD_WOW_PATTERN_CMD *cmd;
2690 A_UINT8 *filter_mask = NULL;
2691
2692 size = sizeof (*cmd);
2693
2694 size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8));
2695 osbuf = A_NETBUF_ALLOC(size);
2696 if (osbuf == NULL) {
2697 return A_NO_MEMORY;
2698 }
2699
2700 A_NETBUF_PUT(osbuf, size);
2701
2702 cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
2703 cmd->filter_list_id = addWowCmd->filter_list_id;
2704 cmd->filter_offset = addWowCmd->filter_offset;
2705 cmd->filter_size = addWowCmd->filter_size;
2706
2707 A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size);
2708
2709 filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size);
2710 A_MEMCPY(filter_mask, mask, addWowCmd->filter_size);
2711
2712
2713 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
2714 NO_SYNC_WMIFLAG));
2715 }
2716
2717 A_STATUS
2718 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
2719 WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
2720 {
2721 void *osbuf;
2722 A_INT8 size;
2723 WMI_DEL_WOW_PATTERN_CMD *cmd;
2724
2725 size = sizeof (*cmd);
2726
2727 osbuf = A_NETBUF_ALLOC(size);
2728 if (osbuf == NULL) {
2729 return A_NO_MEMORY;
2730 }
2731
2732 A_NETBUF_PUT(osbuf, size);
2733
2734 cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
2735 A_MEMZERO(cmd, size);
2736 A_MEMCPY(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
2737
2738 return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
2739 NO_SYNC_WMIFLAG));
2740
2741 }
2742
2743 A_STATUS
2744 wmi_set_snr_threshold_params(struct wmi_t *wmip,
2745 WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
2746 {
2747 void *osbuf;
2748 A_INT8 size;
2749 WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
2750 /* These values are in ascending order */
2751 if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
2752 snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
2753 snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
2754 snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
2755 snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
2756 snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) {
2757
2758 return A_EINVAL;
2759 }
2760
2761 size = sizeof (*cmd);
2762
2763 osbuf = A_NETBUF_ALLOC(size);
2764 if (osbuf == NULL) {
2765 return A_NO_MEMORY;
2766 }
2767
2768 A_NETBUF_PUT(osbuf, size);
2769
2770 cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2771 A_MEMZERO(cmd, size);
2772 A_MEMCPY(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
2773
2774 return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
2775 NO_SYNC_WMIFLAG));
2776 }
2777
2778 A_STATUS
2779 wmi_clr_rssi_snr(struct wmi_t *wmip)
2780 {
2781 void *osbuf;
2782
2783 osbuf = A_NETBUF_ALLOC(sizeof(int));
2784 if (osbuf == NULL) {
2785 return A_NO_MEMORY;
2786 }
2787
2788 return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
2789 NO_SYNC_WMIFLAG));
2790 }
2791
2792 A_STATUS
2793 wmi_set_lq_threshold_params(struct wmi_t *wmip,
2794 WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
2795 {
2796 void *osbuf;
2797 A_INT8 size;
2798 WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
2799 /* These values are in ascending order */
2800 if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
2801 lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
2802 lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
2803 lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
2804 lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
2805 lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
2806
2807 return A_EINVAL;
2808 }
2809
2810 size = sizeof (*cmd);
2811
2812 osbuf = A_NETBUF_ALLOC(size);
2813 if (osbuf == NULL) {
2814 return A_NO_MEMORY;
2815 }
2816
2817 A_NETBUF_PUT(osbuf, size);
2818
2819 cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
2820 A_MEMZERO(cmd, size);
2821 A_MEMCPY(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
2822
2823 return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
2824 NO_SYNC_WMIFLAG));
2825 }
2826
2827 A_STATUS
2828 wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask)
2829 {
2830 void *osbuf;
2831 A_INT8 size;
2832 WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
2833
2834 size = sizeof (*cmd);
2835
2836 osbuf = A_NETBUF_ALLOC(size);
2837 if (osbuf == NULL) {
2838 return A_NO_MEMORY;
2839 }
2840
2841 A_NETBUF_PUT(osbuf, size);
2842
2843 cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
2844 A_MEMZERO(cmd, size);
2845
2846 cmd->bitmask = mask;
2847
2848 return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
2849 NO_SYNC_WMIFLAG));
2850 }
2851
2852 A_STATUS
2853 wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source)
2854 {
2855 void *osbuf;
2856 WMIX_HB_CHALLENGE_RESP_CMD *cmd;
2857
2858 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2859 if (osbuf == NULL) {
2860 return A_NO_MEMORY;
2861 }
2862
2863 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2864
2865 cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
2866 cmd->cookie = cookie;
2867 cmd->source = source;
2868
2869 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
2870 NO_SYNC_WMIFLAG));
2871 }
2872
2873 A_STATUS
2874 wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
2875 A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
2876 A_UINT32 valid)
2877 {
2878 void *osbuf;
2879 WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
2880
2881 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2882 if (osbuf == NULL) {
2883 return A_NO_MEMORY;
2884 }
2885
2886 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2887
2888 cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
2889 cmd->config.cfgmmask = mmask;
2890 cmd->config.cfgtsr = tsr;
2891 cmd->config.cfgrep = rep;
2892 cmd->config.cfgsize = size;
2893 cmd->config.cfgvalid = valid;
2894
2895 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
2896 NO_SYNC_WMIFLAG));
2897 }
2898
2899 A_STATUS
2900 wmi_get_stats_cmd(struct wmi_t *wmip)
2901 {
2902 void *osbuf;
2903
2904 osbuf = A_NETBUF_ALLOC(0); /* no payload */
2905 if (osbuf == NULL) {
2906 return A_NO_MEMORY;
2907 }
2908
2909 return (wmi_cmd_send(wmip, osbuf, WMI_GET_STATISTICS_CMDID,
2910 NO_SYNC_WMIFLAG));
2911 }
2912
2913 A_STATUS
2914 wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid)
2915 {
2916 void *osbuf;
2917 WMI_ADD_BAD_AP_CMD *cmd;
2918
2919 if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
2920 return A_EINVAL;
2921 }
2922
2923 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2924 if (osbuf == NULL) {
2925 return A_NO_MEMORY;
2926 }
2927
2928 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2929
2930 cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
2931 cmd->badApIndex = apIndex;
2932 A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
2933
2934 return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, NO_SYNC_WMIFLAG));
2935 }
2936
2937 A_STATUS
2938 wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex)
2939 {
2940 void *osbuf;
2941 WMI_DELETE_BAD_AP_CMD *cmd;
2942
2943 if (apIndex > WMI_MAX_BAD_AP_INDEX) {
2944 return A_EINVAL;
2945 }
2946
2947 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2948 if (osbuf == NULL) {
2949 return A_NO_MEMORY;
2950 }
2951
2952 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2953
2954 cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
2955 cmd->badApIndex = apIndex;
2956
2957 return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
2958 NO_SYNC_WMIFLAG));
2959 }
2960
2961 A_STATUS
2962 wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM)
2963 {
2964 void *osbuf;
2965 WMI_SET_TX_PWR_CMD *cmd;
2966
2967 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
2968 if (osbuf == NULL) {
2969 return A_NO_MEMORY;
2970 }
2971
2972 A_NETBUF_PUT(osbuf, sizeof(*cmd));
2973
2974 cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
2975 cmd->dbM = dbM;
2976
2977 return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
2978 }
2979
2980 A_STATUS
2981 wmi_get_txPwr_cmd(struct wmi_t *wmip)
2982 {
2983 void *osbuf;
2984
2985 osbuf = A_NETBUF_ALLOC(0); /* no payload */
2986 if (osbuf == NULL) {
2987 return A_NO_MEMORY;
2988 }
2989
2990 return (wmi_cmd_send(wmip, osbuf, WMI_GET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
2991 }
2992
2993 A_STATUS
2994 wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on)
2995 {
2996 WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0,
2997 WMI_SHORTSCANRATIO_DEFAULT,
2998 DEFAULT_SCAN_CTRL_FLAGS,
2999 0};
3000
3001 if (on) {
3002 /* Enable foreground scanning */
3003 if (wmi_scanparams_cmd(wmip, scParams.fg_start_period,
3004 scParams.fg_end_period,
3005 scParams.bg_period,
3006 scParams.minact_chdwell_time,
3007 scParams.maxact_chdwell_time,
3008 scParams.pas_chdwell_time,
3009 scParams.shortScanRatio,
3010 scParams.scanCtrlFlags,
3011 scParams.max_dfsch_act_time) != A_OK) {
3012 return -EIO;
3013 }
3014 } else {
3015 wmi_disconnect_cmd(wmip);
3016 if (wmi_scanparams_cmd(wmip, 0xFFFF, 0, 0, 0,
3017 0, 0, 0, 0xFF, 0) != A_OK) {
3018 return -EIO;
3019 }
3020 }
3021
3022 return A_OK;
3023 }
3024
3025
3026 A_UINT16
3027 wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass)
3028 {
3029 A_UINT16 activeTsids=0;
3030
3031 LOCK_WMI(wmip);
3032 activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
3033 UNLOCK_WMI(wmip);
3034
3035 return activeTsids;
3036 }
3037
3038 A_STATUS
3039 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
3040 {
3041 void *osbuf;
3042
3043 osbuf = A_NETBUF_ALLOC(0); /* no payload */
3044 if (osbuf == NULL) {
3045 return A_NO_MEMORY;
3046 }
3047
3048 return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_TBL_CMDID,
3049 NO_SYNC_WMIFLAG));
3050 }
3051
3052 A_STATUS
3053 wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType)
3054 {
3055 void *osbuf;
3056 A_UINT32 size = sizeof(A_UINT8);
3057 WMI_TARGET_ROAM_DATA *cmd;
3058
3059 osbuf = A_NETBUF_ALLOC(size); /* no payload */
3060 if (osbuf == NULL) {
3061 return A_NO_MEMORY;
3062 }
3063
3064 A_NETBUF_PUT(osbuf, size);
3065
3066 cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
3067 cmd->roamDataType = roamDataType;
3068
3069 return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
3070 NO_SYNC_WMIFLAG));
3071 }
3072
3073 A_STATUS
3074 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
3075 A_UINT8 size)
3076 {
3077 void *osbuf;
3078 WMI_SET_ROAM_CTRL_CMD *cmd;
3079
3080 osbuf = A_NETBUF_ALLOC(size);
3081 if (osbuf == NULL) {
3082 return A_NO_MEMORY;
3083 }
3084
3085 A_NETBUF_PUT(osbuf, size);
3086
3087 cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
3088 A_MEMZERO(cmd, size);
3089
3090 A_MEMCPY(cmd, p, size);
3091
3092 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
3093 NO_SYNC_WMIFLAG));
3094 }
3095
3096 A_STATUS
3097 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
3098 WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
3099 A_UINT8 size)
3100 {
3101 void *osbuf;
3102 WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
3103
3104 /* These timers can't be zero */
3105 if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
3106 !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
3107 pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
3108 !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
3109 pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
3110 return A_EINVAL;
3111
3112 osbuf = A_NETBUF_ALLOC(size);
3113 if (osbuf == NULL) {
3114 return A_NO_MEMORY;
3115 }
3116
3117 A_NETBUF_PUT(osbuf, size);
3118
3119 cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
3120 A_MEMZERO(cmd, size);
3121
3122 A_MEMCPY(cmd, pCmd, size);
3123
3124 return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
3125 NO_SYNC_WMIFLAG));
3126 }
3127
3128 #ifdef CONFIG_HOST_GPIO_SUPPORT
3129 /* Send a command to Target to change GPIO output pins. */
3130 A_STATUS
3131 wmi_gpio_output_set(struct wmi_t *wmip,
3132 A_UINT32 set_mask,
3133 A_UINT32 clear_mask,
3134 A_UINT32 enable_mask,
3135 A_UINT32 disable_mask)
3136 {
3137 void *osbuf;
3138 WMIX_GPIO_OUTPUT_SET_CMD *output_set;
3139 int size;
3140
3141 size = sizeof(*output_set);
3142
3143 A_DPRINTF(DBG_WMI,
3144 (DBGFMT "Enter - set=0x%x clear=0x%x enb=0x%x dis=0x%x\n", DBGARG,
3145 set_mask, clear_mask, enable_mask, disable_mask));
3146
3147 osbuf = A_NETBUF_ALLOC(size);
3148 if (osbuf == NULL) {
3149 return A_NO_MEMORY;
3150 }
3151 A_NETBUF_PUT(osbuf, size);
3152 output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf));
3153
3154 output_set->set_mask = set_mask;
3155 output_set->clear_mask = clear_mask;
3156 output_set->enable_mask = enable_mask;
3157 output_set->disable_mask = disable_mask;
3158
3159 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID,
3160 NO_SYNC_WMIFLAG));
3161 }
3162
3163 /* Send a command to the Target requesting state of the GPIO input pins */
3164 A_STATUS
3165 wmi_gpio_input_get(struct wmi_t *wmip)
3166 {
3167 void *osbuf;
3168
3169 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3170
3171 osbuf = A_NETBUF_ALLOC(0);
3172 if (osbuf == NULL) {
3173 return A_NO_MEMORY;
3174 }
3175
3176 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INPUT_GET_CMDID,
3177 NO_SYNC_WMIFLAG));
3178 }
3179
3180 /* Send a command to the Target that changes the value of a GPIO register. */
3181 A_STATUS
3182 wmi_gpio_register_set(struct wmi_t *wmip,
3183 A_UINT32 gpioreg_id,
3184 A_UINT32 value)
3185 {
3186 void *osbuf;
3187 WMIX_GPIO_REGISTER_SET_CMD *register_set;
3188 int size;
3189
3190 size = sizeof(*register_set);
3191
3192 A_DPRINTF(DBG_WMI,
3193 (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value));
3194
3195 osbuf = A_NETBUF_ALLOC(size);
3196 if (osbuf == NULL) {
3197 return A_NO_MEMORY;
3198 }
3199 A_NETBUF_PUT(osbuf, size);
3200 register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf));
3201
3202 register_set->gpioreg_id = gpioreg_id;
3203 register_set->value = value;
3204
3205 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID,
3206 NO_SYNC_WMIFLAG));
3207 }
3208
3209 /* Send a command to the Target to fetch the value of a GPIO register. */
3210 A_STATUS
3211 wmi_gpio_register_get(struct wmi_t *wmip,
3212 A_UINT32 gpioreg_id)
3213 {
3214 void *osbuf;
3215 WMIX_GPIO_REGISTER_GET_CMD *register_get;
3216 int size;
3217
3218 size = sizeof(*register_get);
3219
3220 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id));
3221
3222 osbuf = A_NETBUF_ALLOC(size);
3223 if (osbuf == NULL) {
3224 return A_NO_MEMORY;
3225 }
3226 A_NETBUF_PUT(osbuf, size);
3227 register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf));
3228
3229 register_get->gpioreg_id = gpioreg_id;
3230
3231 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID,
3232 NO_SYNC_WMIFLAG));
3233 }
3234
3235 /* Send a command to the Target acknowledging some GPIO interrupts. */
3236 A_STATUS
3237 wmi_gpio_intr_ack(struct wmi_t *wmip,
3238 A_UINT32 ack_mask)
3239 {
3240 void *osbuf;
3241 WMIX_GPIO_INTR_ACK_CMD *intr_ack;
3242 int size;
3243
3244 size = sizeof(*intr_ack);
3245
3246 A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask));
3247
3248 osbuf = A_NETBUF_ALLOC(size);
3249 if (osbuf == NULL) {
3250 return A_NO_MEMORY;
3251 }
3252 A_NETBUF_PUT(osbuf, size);
3253 intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf));
3254
3255 intr_ack->ack_mask = ack_mask;
3256
3257 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID,
3258 NO_SYNC_WMIFLAG));
3259 }
3260 #endif /* CONFIG_HOST_GPIO_SUPPORT */
3261
3262 A_STATUS
3263 wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop, A_UINT8 eCWmin,
3264 A_UINT8 eCWmax, A_UINT8 aifsn)
3265 {
3266 void *osbuf;
3267 WMI_SET_ACCESS_PARAMS_CMD *cmd;
3268
3269 if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
3270 (aifsn > WMI_MAX_AIFSN_ACPARAM))
3271 {
3272 return A_EINVAL;
3273 }
3274
3275 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3276 if (osbuf == NULL) {
3277 return A_NO_MEMORY;
3278 }
3279
3280 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3281
3282 cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3283 cmd->txop = txop;
3284 cmd->eCWmin = eCWmin;
3285 cmd->eCWmax = eCWmax;
3286 cmd->aifsn = aifsn;
3287
3288 return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
3289 NO_SYNC_WMIFLAG));
3290 }
3291
3292 A_STATUS
3293 wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
3294 A_UINT8 trafficClass, A_UINT8 maxRetries,
3295 A_UINT8 enableNotify)
3296 {
3297 void *osbuf;
3298 WMI_SET_RETRY_LIMITS_CMD *cmd;
3299
3300 if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
3301 (frameType != DATA_FRAMETYPE))
3302 {
3303 return A_EINVAL;
3304 }
3305
3306 if (maxRetries > WMI_MAX_RETRIES) {
3307 return A_EINVAL;
3308 }
3309
3310 if (frameType != DATA_FRAMETYPE) {
3311 trafficClass = 0;
3312 }
3313
3314 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3315 if (osbuf == NULL) {
3316 return A_NO_MEMORY;
3317 }
3318
3319 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3320
3321 cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
3322 cmd->frameType = frameType;
3323 cmd->trafficClass = trafficClass;
3324 cmd->maxRetries = maxRetries;
3325 cmd->enableNotify = enableNotify;
3326
3327 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
3328 NO_SYNC_WMIFLAG));
3329 }
3330
3331 void
3332 wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid)
3333 {
3334 if (bssid != NULL) {
3335 A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
3336 }
3337 }
3338
3339 A_STATUS
3340 wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode)
3341 {
3342 void *osbuf;
3343 WMI_SET_OPT_MODE_CMD *cmd;
3344
3345 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3346 if (osbuf == NULL) {
3347 return A_NO_MEMORY;
3348 }
3349
3350 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3351
3352 cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3353 A_MEMZERO(cmd, sizeof(*cmd));
3354 cmd->optMode = optMode;
3355
3356 return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
3357 SYNC_BOTH_WMIFLAG));
3358 }
3359
3360 A_STATUS
3361 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
3362 A_UINT8 frmType,
3363 A_UINT8 *dstMacAddr,
3364 A_UINT8 *bssid,
3365 A_UINT16 optIEDataLen,
3366 A_UINT8 *optIEData)
3367 {
3368 void *osbuf;
3369 WMI_OPT_TX_FRAME_CMD *cmd;
3370 osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
3371 if (osbuf == NULL) {
3372 return A_NO_MEMORY;
3373 }
3374
3375 A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
3376
3377 cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
3378 A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
3379
3380 cmd->frmType = frmType;
3381 cmd->optIEDataLen = optIEDataLen;
3382 //cmd->optIEData = (A_UINT8 *)((int)cmd + sizeof(*cmd));
3383 A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
3384 A_MEMCPY(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
3385 A_MEMCPY(&cmd->optIEData[0], optIEData, optIEDataLen);
3386
3387 return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
3388 NO_SYNC_WMIFLAG));
3389 }
3390
3391 A_STATUS
3392 wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl)
3393 {
3394 void *osbuf;
3395 WMI_BEACON_INT_CMD *cmd;
3396
3397 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3398 if (osbuf == NULL) {
3399 return A_NO_MEMORY;
3400 }
3401
3402 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3403
3404 cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
3405 A_MEMZERO(cmd, sizeof(*cmd));
3406 cmd->beaconInterval = intvl;
3407
3408 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
3409 NO_SYNC_WMIFLAG));
3410 }
3411
3412
3413 A_STATUS
3414 wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize)
3415 {
3416 void *osbuf;
3417 WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
3418
3419 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3420 if (osbuf == NULL) {
3421 return A_NO_MEMORY;
3422 }
3423
3424 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3425
3426 cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
3427 A_MEMZERO(cmd, sizeof(*cmd));
3428 cmd->voicePktSize = voicePktSize;
3429
3430 return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
3431 NO_SYNC_WMIFLAG));
3432 }
3433
3434
3435 A_STATUS
3436 wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen)
3437 {
3438 void *osbuf;
3439 WMI_SET_MAX_SP_LEN_CMD *cmd;
3440
3441 /* maxSPLen is a two-bit value. If user trys to set anything
3442 * other than this, then its invalid
3443 */
3444 if(maxSPLen & ~0x03)
3445 return A_EINVAL;
3446
3447 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3448 if (osbuf == NULL) {
3449 return A_NO_MEMORY;
3450 }
3451
3452 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3453
3454 cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
3455 A_MEMZERO(cmd, sizeof(*cmd));
3456 cmd->maxSPLen = maxSPLen;
3457
3458 return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
3459 NO_SYNC_WMIFLAG));
3460 }
3461
3462 A_UINT8
3463 convert_userPriority_to_trafficClass(A_UINT8 userPriority)
3464 {
3465 return (up_to_ac[userPriority & 0x7]);
3466 }
3467
3468 A_UINT8
3469 wmi_get_power_mode_cmd(struct wmi_t *wmip)
3470 {
3471 return wmip->wmi_powerMode;
3472 }
3473
3474 A_STATUS
3475 wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance)
3476 {
3477 return A_OK;
3478 }
3479
3480 #ifdef CONFIG_HOST_TCMD_SUPPORT
3481 static A_STATUS
3482 wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
3483 {
3484
3485 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3486
3487 A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len);
3488
3489 return A_OK;
3490 }
3491
3492 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
3493
3494 A_STATUS
3495 wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
3496 {
3497 void *osbuf;
3498 WMI_SET_AUTH_MODE_CMD *cmd;
3499
3500 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3501 if (osbuf == NULL) {
3502 return A_NO_MEMORY;
3503 }
3504
3505 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3506
3507 cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3508 A_MEMZERO(cmd, sizeof(*cmd));
3509 cmd->mode = mode;
3510
3511 return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
3512 NO_SYNC_WMIFLAG));
3513 }
3514
3515 A_STATUS
3516 wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
3517 {
3518 void *osbuf;
3519 WMI_SET_REASSOC_MODE_CMD *cmd;
3520
3521 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3522 if (osbuf == NULL) {
3523 return A_NO_MEMORY;
3524 }
3525
3526 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3527
3528 cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
3529 A_MEMZERO(cmd, sizeof(*cmd));
3530 cmd->mode = mode;
3531
3532 return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
3533 NO_SYNC_WMIFLAG));
3534 }
3535
3536 A_STATUS
3537 wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status)
3538 {
3539 void *osbuf;
3540 WMI_SET_LPREAMBLE_CMD *cmd;
3541
3542 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3543 if (osbuf == NULL) {
3544 return A_NO_MEMORY;
3545 }
3546
3547 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3548
3549 cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
3550 A_MEMZERO(cmd, sizeof(*cmd));
3551 cmd->status = status;
3552
3553 return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
3554 NO_SYNC_WMIFLAG));
3555 }
3556
3557 A_STATUS
3558 wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold)
3559 {
3560 void *osbuf;
3561 WMI_SET_RTS_CMD *cmd;
3562
3563 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3564 if (osbuf == NULL) {
3565 return A_NO_MEMORY;
3566 }
3567
3568 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3569
3570 cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
3571 A_MEMZERO(cmd, sizeof(*cmd));
3572 cmd->threshold = threshold;
3573
3574 return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
3575 NO_SYNC_WMIFLAG));
3576 }
3577
3578 A_STATUS
3579 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
3580 {
3581 void *osbuf;
3582 WMI_SET_WMM_CMD *cmd;
3583
3584 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3585 if (osbuf == NULL) {
3586 return A_NO_MEMORY;
3587 }
3588
3589 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3590
3591 cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
3592 A_MEMZERO(cmd, sizeof(*cmd));
3593 cmd->status = status;
3594
3595 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
3596 NO_SYNC_WMIFLAG));
3597
3598 }
3599
3600 A_STATUS
3601 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
3602 {
3603 void *osbuf;
3604 WMI_SET_WMM_TXOP_CMD *cmd;
3605
3606 if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
3607 return A_EINVAL;
3608
3609 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3610 if (osbuf == NULL) {
3611 return A_NO_MEMORY;
3612 }
3613
3614 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3615
3616 cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
3617 A_MEMZERO(cmd, sizeof(*cmd));
3618 cmd->txopEnable = cfg;
3619
3620 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
3621 NO_SYNC_WMIFLAG));
3622
3623 }
3624
3625 #ifdef CONFIG_HOST_TCMD_SUPPORT
3626 /* WMI layer doesn't need to know the data type of the test cmd.
3627 This would be beneficial for customers like Qualcomm, who might
3628 have different test command requirements from differnt manufacturers
3629 */
3630 A_STATUS
3631 wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len)
3632 {
3633 void *osbuf;
3634 char *data;
3635
3636 A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
3637
3638 osbuf= A_NETBUF_ALLOC(len);
3639 if(osbuf == NULL)
3640 {
3641 return A_NO_MEMORY;
3642 }
3643 A_NETBUF_PUT(osbuf, len);
3644 data = A_NETBUF_DATA(osbuf);
3645 A_MEMCPY(data, buf, len);
3646
3647 return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
3648 NO_SYNC_WMIFLAG));
3649 }
3650
3651 #endif
3652
3653 A_STATUS
3654 wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status)
3655 {
3656 void *osbuf;
3657 WMI_SET_BT_STATUS_CMD *cmd;
3658
3659 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3660 if (osbuf == NULL) {
3661 return A_NO_MEMORY;
3662 }
3663
3664 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3665
3666 cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
3667 A_MEMZERO(cmd, sizeof(*cmd));
3668 cmd->streamType = streamType;
3669 cmd->status = status;
3670
3671 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
3672 NO_SYNC_WMIFLAG));
3673 }
3674
3675 A_STATUS
3676 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
3677 {
3678 void *osbuf;
3679 WMI_SET_BT_PARAMS_CMD* alloc_cmd;
3680
3681 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3682 if (osbuf == NULL) {
3683 return A_NO_MEMORY;
3684 }
3685
3686 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3687
3688 alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
3689 A_MEMZERO(alloc_cmd, sizeof(*cmd));
3690 A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd));
3691
3692 return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
3693 NO_SYNC_WMIFLAG));
3694 }
3695
3696 A_STATUS
3697 wmi_get_keepalive_configured(struct wmi_t *wmip)
3698 {
3699 void *osbuf;
3700 WMI_GET_KEEPALIVE_CMD *cmd;
3701 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3702 if (osbuf == NULL) {
3703 return A_NO_MEMORY;
3704 }
3705 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3706 cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
3707 A_MEMZERO(cmd, sizeof(*cmd));
3708 return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
3709 NO_SYNC_WMIFLAG));
3710 }
3711
3712 A_UINT8
3713 wmi_get_keepalive_cmd(struct wmi_t *wmip)
3714 {
3715 return wmip->wmi_keepaliveInterval;
3716 }
3717
3718 A_STATUS
3719 wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval)
3720 {
3721 void *osbuf;
3722 WMI_SET_KEEPALIVE_CMD *cmd;
3723
3724 osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
3725 if (osbuf == NULL) {
3726 return A_NO_MEMORY;
3727 }
3728
3729 A_NETBUF_PUT(osbuf, sizeof(*cmd));
3730
3731 cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
3732 A_MEMZERO(cmd, sizeof(*cmd));
3733 cmd->keepaliveInterval = keepaliveInterval;
3734 wmip->wmi_keepaliveInterval = keepaliveInterval;
3735
3736 return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
3737 NO_SYNC_WMIFLAG));
3738 }
3739
3740 A_STATUS
3741 wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen,
3742 A_UINT8 *ieInfo)
3743 {
3744 void *osbuf;
3745 WMI_SET_APPIE_CMD *cmd;
3746 A_UINT16 cmdLen;
3747
3748 if (ieLen > WMI_MAX_IE_LEN) {
3749 return A_ERROR;
3750 }
3751 cmdLen = sizeof(*cmd) + ieLen - 1;
3752 osbuf = A_NETBUF_ALLOC(cmdLen);
3753 if (osbuf == NULL) {
3754 return A_NO_MEMORY;
3755 }
3756
3757 A_NETBUF_PUT(osbuf, cmdLen);
3758
3759 cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
3760 A_MEMZERO(cmd, cmdLen);
3761
3762 cmd->mgmtFrmType = mgmtFrmType;
3763 cmd->ieLen = ieLen;
3764 A_MEMCPY(cmd->ieInfo, ieInfo, ieLen);
3765
3766 return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
3767 }
3768
3769 A_STATUS
3770 wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen)
3771 {
3772 void *osbuf;
3773 A_UINT8 *data;
3774
3775 osbuf = A_NETBUF_ALLOC(dataLen);
3776 if (osbuf == NULL) {
3777 return A_NO_MEMORY;
3778 }
3779
3780 A_NETBUF_PUT(osbuf, dataLen);
3781
3782 data = A_NETBUF_DATA(osbuf);
3783
3784 A_MEMCPY(data, cmd, dataLen);
3785
3786 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
3787 }
3788
3789 A_INT32
3790 wmi_get_rate(A_INT8 rateindex)
3791 {
3792 if (rateindex == RATE_AUTO) {
3793 return 0;
3794 } else {
3795 return(wmi_rateTable[(A_UINT32) rateindex]);
3796 }
3797 }
3798
3799 void
3800 wmi_node_return (struct wmi_t *wmip, bss_t *bss)
3801 {
3802 if (NULL != bss)
3803 {
3804 wlan_node_return (&wmip->wmi_scan_table, bss);
3805 }
3806 }
3807
3808 bss_t *
3809 wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
3810 A_UINT32 ssidLength, A_BOOL bIsWPA2)
3811 {
3812 bss_t *node = NULL;
3813 node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
3814 ssidLength, bIsWPA2);
3815 return node;
3816 }
3817
3818 void
3819 wmi_free_allnodes(struct wmi_t *wmip)
3820 {
3821 wlan_free_allnodes(&wmip->wmi_scan_table);
3822 }
3823
3824 bss_t *
3825 wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
3826 {
3827 bss_t *ni=NULL;
3828 ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
3829 return ni;
3830 }
3831
3832 A_STATUS
3833 wmi_dset_open_reply(struct wmi_t *wmip,
3834 A_UINT32 status,
3835 A_UINT32 access_cookie,
3836 A_UINT32 dset_size,
3837 A_UINT32 dset_version,
3838 A_UINT32 targ_handle,
3839 A_UINT32 targ_reply_fn,
3840 A_UINT32 targ_reply_arg)
3841 {
3842 void *osbuf;
3843 WMIX_DSETOPEN_REPLY_CMD *open_reply;
3844
3845 A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%x\n", DBGARG, (int)wmip));
3846
3847 osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
3848 if (osbuf == NULL) {
3849 return A_NO_MEMORY;
3850 }
3851
3852 A_NETBUF_PUT(osbuf, sizeof(*open_reply));
3853 open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
3854
3855 open_reply->status = status;
3856 open_reply->targ_dset_handle = targ_handle;
3857 open_reply->targ_reply_fn = targ_reply_fn;
3858 open_reply->targ_reply_arg = targ_reply_arg;
3859 open_reply->access_cookie = access_cookie;
3860 open_reply->size = dset_size;
3861 open_reply->version = dset_version;
3862
3863 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
3864 NO_SYNC_WMIFLAG));
3865 }
3866
3867 static A_STATUS
3868 wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
3869 {
3870 WMI_PMKID_LIST_REPLY *reply;
3871 A_UINT32 expected_len;
3872
3873 if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
3874 return A_EINVAL;
3875 }
3876 reply = (WMI_PMKID_LIST_REPLY *)datap;
3877 expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
3878
3879 if (len < expected_len) {
3880 return A_EINVAL;
3881 }
3882
3883 A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
3884 reply->pmkidList);
3885
3886 return A_OK;
3887 }
3888
3889 #ifdef CONFIG_HOST_DSET_SUPPORT
3890 A_STATUS
3891 wmi_dset_data_reply(struct wmi_t *wmip,
3892 A_UINT32 status,
3893 A_UINT8 *user_buf,
3894 A_UINT32 length,
3895 A_UINT32 targ_buf,
3896 A_UINT32 targ_reply_fn,
3897 A_UINT32 targ_reply_arg)
3898 {
3899 void *osbuf;
3900 WMIX_DSETDATA_REPLY_CMD *data_reply;
3901 int size;
3902
3903 size = sizeof(*data_reply) + length;
3904
3905 A_DPRINTF(DBG_WMI,
3906 (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
3907
3908 osbuf = A_NETBUF_ALLOC(size);
3909 if (osbuf == NULL) {
3910 return A_NO_MEMORY;
3911 }
3912 A_NETBUF_PUT(osbuf, size);
3913 data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
3914
3915 data_reply->status = status;
3916 data_reply->targ_buf = targ_buf;
3917 data_reply->targ_reply_fn = targ_reply_fn;
3918 data_reply->targ_reply_arg = targ_reply_arg;
3919 data_reply->length = length;
3920
3921 if (status == A_OK) {
3922 if (a_copy_from_user(data_reply->buf, user_buf, length)) {
3923 return A_ERROR;
3924 }
3925 }
3926
3927 return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
3928 NO_SYNC_WMIFLAG));
3929 }
3930 #endif /* CONFIG_HOST_DSET_SUPPORT */
3931
3932 A_STATUS
3933 wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status)
3934 {
3935 void *osbuf;
3936 char *cmd;
3937
3938 wps_enable = status;
3939
3940 osbuf = a_netbuf_alloc(sizeof(1));
3941 if (osbuf == NULL) {
3942 return A_NO_MEMORY;
3943 }
3944
3945 a_netbuf_put(osbuf, sizeof(1));
3946
3947 cmd = (char *)(a_netbuf_to_data(osbuf));
3948
3949 A_MEMZERO(cmd, sizeof(*cmd));
3950 cmd[0] = (status?1:0);
3951 return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
3952 NO_SYNC_WMIFLAG));
3953 }
3954
This page took 0.262659 seconds and 5 git commands to generate.