From 5a3e16857d5da8a5db2e2c803129ccb43982cfc1 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Wed, 19 Nov 2008 17:11:20 +0000 Subject: prepare-ar6001-driver-linux-sdio.patch Signed-off-by: Andy Green --- drivers/ar6000/wmi/wmi.c | 3954 ++++++++++++++++++++++++++++++++++++ drivers/ar6000/wmi/wmi_doc.h | 4421 +++++++++++++++++++++++++++++++++++++++++ drivers/ar6000/wmi/wmi_host.h | 71 + 3 files changed, 8446 insertions(+) create mode 100644 drivers/ar6000/wmi/wmi.c create mode 100644 drivers/ar6000/wmi/wmi_doc.h create mode 100644 drivers/ar6000/wmi/wmi_host.h (limited to 'drivers/ar6000/wmi') diff --git a/drivers/ar6000/wmi/wmi.c b/drivers/ar6000/wmi/wmi.c new file mode 100644 index 00000000000..d322cf3f522 --- /dev/null +++ b/drivers/ar6000/wmi/wmi.c @@ -0,0 +1,3954 @@ +/* + * Copyright (c) 2004-2007 Atheros Communications Inc. + * All rights reserved. + * + * This module implements the hardware independent layer of the + * Wireless Module Interface (WMI) protocol. + * + * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi.c#3 $ + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * + */ + +#include +#include +#include +#include +#include "htc.h" +#include "htc_api.h" +#include "wmi.h" +#include +#include +#include +#include +#include "dset_api.h" +#include "gpio_api.h" +#include "wmi_host.h" +#include "a_drv.h" +#include "a_drv_api.h" +#include "a_debug.h" +#include "dbglog_api.h" + +static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_sync_point(struct wmi_t *wmip); + +static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); + +static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +#ifdef CONFIG_HOST_DSET_SUPPORT +static A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +#endif /* CONFIG_HOST_DSET_SUPPORT */ + + +static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, + int len); +static A_STATUS +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len); + +#ifdef CONFIG_HOST_GPIO_SUPPORT +static A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +#endif /* CONFIG_HOST_GPIO_SUPPORT */ + +#ifdef CONFIG_HOST_TCMD_SUPPORT +static A_STATUS +wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); +#endif + +static A_STATUS +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +static A_STATUS +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +static A_STATUS +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +static A_BOOL +wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex); + +static A_STATUS +wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +static A_STATUS +wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); + +int wps_enable; +static const A_INT32 wmi_rateTable[] = { + 1000, + 2000, + 5500, + 11000, + 6000, + 9000, + 12000, + 18000, + 24000, + 36000, + 48000, + 54000, + 0}; + +#define MODE_A_SUPPORT_RATE_START 4 +#define MODE_A_SUPPORT_RATE_STOP 11 + +#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START +#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP + +#define MODE_B_SUPPORT_RATE_START 0 +#define MODE_B_SUPPORT_RATE_STOP 3 + +#define MODE_G_SUPPORT_RATE_START 0 +#define MODE_G_SUPPORT_RATE_STOP 11 + +#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_G_SUPPORT_RATE_STOP + 1) + +/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ +const A_UINT8 up_to_ac[]= { + WMM_AC_BE, + WMM_AC_BK, + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO, + }; + +void * +wmi_init(void *devt) +{ + struct wmi_t *wmip; + + wmip = A_MALLOC(sizeof(struct wmi_t)); + if (wmip == NULL) { + return (NULL); + } + A_MEMZERO(wmip, sizeof(*wmip)); + A_MUTEX_INIT(&wmip->wmi_lock); + wmip->wmi_devt = devt; + wlan_node_table_init(wmip, &wmip->wmi_scan_table); + wmi_qos_state_init(wmip); + wmip->wmi_powerMode = REC_POWER; + wmip->wmi_phyMode = WMI_11G_MODE; + + return (wmip); +} + +void +wmi_qos_state_init(struct wmi_t *wmip) +{ + A_UINT8 i; + + if (wmip == NULL) { + return; + } + LOCK_WMI(wmip); + + /* Initialize QoS States */ + wmip->wmi_numQoSStream = 0; + + wmip->wmi_fatPipeExists = 0; + + for (i=0; i < WMM_NUM_AC; i++) { + wmip->wmi_streamExistsForAC[i]=0; + } + + /* Initialize the static Wmi stream Pri to WMM AC mappings Arrays */ + WMI_INIT_WMISTREAM_AC_MAP(wmip); + + UNLOCK_WMI(wmip); + + A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1); +} + +void +wmi_shutdown(struct wmi_t *wmip) +{ + if (wmip != NULL) { + wlan_node_table_cleanup(&wmip->wmi_scan_table); + if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) { + A_MUTEX_DELETE(&wmip->wmi_lock); + } + A_FREE(wmip); + } +} + +/* + * performs DIX to 802.3 encapsulation for transmit packets. + * uses passed in buffer. Returns buffer or NULL if failed. + * Assumes the entire DIX header is contigous and that there is + * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. + */ +A_STATUS +wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf) +{ + A_UINT8 *datap; + A_UINT16 typeorlen; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_HEADROOM(osbuf) < + (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) + { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); + + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { + /* + * packet is already in 802.3 format - return success + */ + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); + return (A_OK); + } + + /* + * Save mac fields and length to be inserted later + */ + A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN); + A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); + macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + + sizeof(ATH_LLC_SNAP_HDR)); + + /* + * Make room for LLC+SNAP headers + */ + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR)); + + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); + llcHdr->dsap = 0xAA; + llcHdr->ssap = 0xAA; + llcHdr->cntl = 0x03; + llcHdr->orgCode[0] = 0x0; + llcHdr->orgCode[1] = 0x0; + llcHdr->orgCode[2] = 0x0; + llcHdr->etherType = typeorlen; + + return (A_OK); +} + +/* + * Adds a WMI data header + * Assumes there is enough room in the buffer to add header. + */ +A_STATUS +wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType) +{ + WMI_DATA_HDR *dtHdr; + + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) { + return A_NO_MEMORY; + } + + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); + dtHdr->info = msgType; + dtHdr->rssi = 0; + + return (A_OK); +} + +A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up) +{ + A_UINT8 *datap; + A_UINT8 trafficClass = WMM_AC_BE, userPriority = up; + ATH_LLC_SNAP_HDR *llcHdr; + A_UINT16 ipType = IP_ETHERTYPE; + WMI_DATA_HDR *dtHdr; + WMI_CREATE_PSTREAM_CMD cmd; + A_BOOL streamExists = FALSE; + + A_ASSERT(osbuf != NULL); + + datap = A_NETBUF_DATA(osbuf); + + if (up == UNDEFINED_PRI) { + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + + sizeof(ATH_MAC_HDR)); + + if (llcHdr->etherType == A_CPU2BE16(ipType)) { + /* Extract the endpoint info from the TOS field in the IP header */ + userPriority = A_WMI_IPTOS_TO_USERPRIORITY(((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR)); + } + } + + if (userPriority < MAX_NUM_PRI) { + trafficClass = convert_userPriority_to_trafficClass(userPriority); + } + + dtHdr = (WMI_DATA_HDR *)datap; + if(dir==UPLINK_TRAFFIC) + dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; /* lower 3-bits are 802.1d priority */ + + LOCK_WMI(wmip); + streamExists = wmip->wmi_fatPipeExists; + UNLOCK_WMI(wmip); + + if (!(streamExists & (1 << trafficClass))) { + + A_MEMZERO(&cmd, sizeof(cmd)); + cmd.trafficClass = trafficClass; + cmd.userPriority = userPriority; + cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT; + /* Implicit streams are created with TSID 0xFF */ + cmd.tsid = WMI_IMPLICIT_PSTREAM; + wmi_create_pstream_cmd(wmip, &cmd); + } + + return trafficClass; +} + +WMI_PRI_STREAM_ID +wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass) +{ + return WMI_ACCESSCATEGORY_WMISTREAM(wmip, trafficClass); +} + +/* + * performs 802.3 to DIX encapsulation for received packets. + * Assumes the entire 802.3 header is contigous. + */ +A_STATUS +wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf) +{ + A_UINT8 *datap; + ATH_MAC_HDR macHdr; + ATH_LLC_SNAP_HDR *llcHdr; + + A_ASSERT(osbuf != NULL); + datap = A_NETBUF_DATA(osbuf); + + A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR)); + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); + macHdr.typeOrLen = llcHdr->etherType; + + if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) { + return A_NO_MEMORY; + } + + datap = A_NETBUF_DATA(osbuf); + + A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR)); + + return (A_OK); +} + +/* + * Removes a WMI data header + */ +A_STATUS +wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf) +{ + A_ASSERT(osbuf != NULL); + + return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR))); +} + +void +wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg) +{ + wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg); +} + +/* + * WMI Extended Event received from Target. + */ +A_STATUS +wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf) +{ + WMIX_CMD_HDR *cmd; + A_UINT16 id; + A_UINT8 *datap; + A_UINT32 len; + A_STATUS status = A_OK; + + if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + A_NETBUF_FREE(osbuf); + return A_ERROR; + } + + cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); + id = cmd->commandId; + + if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + A_NETBUF_FREE(osbuf); + return A_ERROR; + } + + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + + switch (id) { + case (WMIX_DSETOPENREQ_EVENTID): + status = wmi_dset_open_req_rx(wmip, datap, len); + break; +#ifdef CONFIG_HOST_DSET_SUPPORT + case (WMIX_DSETCLOSE_EVENTID): + status = wmi_dset_close_rx(wmip, datap, len); + break; + case (WMIX_DSETDATAREQ_EVENTID): + status = wmi_dset_data_req_rx(wmip, datap, len); + break; +#endif /* CONFIG_HOST_DSET_SUPPORT */ +#ifdef CONFIG_HOST_GPIO_SUPPORT + case (WMIX_GPIO_INTR_EVENTID): + wmi_gpio_intr_rx(wmip, datap, len); + break; + case (WMIX_GPIO_DATA_EVENTID): + wmi_gpio_data_rx(wmip, datap, len); + break; + case (WMIX_GPIO_ACK_EVENTID): + wmi_gpio_ack_rx(wmip, datap, len); + break; +#endif /* CONFIG_HOST_GPIO_SUPPORT */ + case (WMIX_HB_CHALLENGE_RESP_EVENTID): + wmi_hbChallengeResp_rx(wmip, datap, len); + break; + case (WMIX_DBGLOG_EVENTID): + wmi_dbglog_event_rx(wmip, datap, len); + break; + default: + A_DPRINTF(DBG_WMI|DBG_ERROR, + (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); + wmip->wmi_stats.cmd_id_err++; + status = A_ERROR; + break; + } + + return status; +} + +/* + * Control Path + */ +A_UINT32 cmdRecvNum; + +A_STATUS +wmi_control_rx(struct wmi_t *wmip, void *osbuf) +{ + WMI_CMD_HDR *cmd; + A_UINT16 id; + A_UINT8 *datap; + A_UINT32 len, i, loggingReq; + A_STATUS status = A_OK; + + A_ASSERT(osbuf != NULL); + if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + A_NETBUF_FREE(osbuf); + return A_ERROR; + } + + cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); + id = cmd->commandId; + + if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) { + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); + wmip->wmi_stats.cmd_len_err++; + A_NETBUF_FREE(osbuf); + return A_ERROR; + } + + datap = A_NETBUF_DATA(osbuf); + len = A_NETBUF_LEN(osbuf); + + ar6000_get_driver_cfg(wmip->wmi_devt, + AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS, + &loggingReq); + + if(loggingReq) { + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id)); + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum)); + for(i = 0; i < len; i++) + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i])); + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n")); + } + + LOCK_WMI(wmip); + cmdRecvNum++; + UNLOCK_WMI(wmip); + + switch (id) { + case (WMI_GET_BITRATE_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG)); + status = wmi_bitrate_reply_rx(wmip, datap, len); + break; + case (WMI_GET_CHANNEL_LIST_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG)); + status = wmi_channelList_reply_rx(wmip, datap, len); + break; + case (WMI_GET_TX_PWR_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG)); + status = wmi_txPwr_reply_rx(wmip, datap, len); + break; + case (WMI_READY_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG)); + status = wmi_ready_event_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt); + break; + case (WMI_CONNECT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG)); + status = wmi_connect_event_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_DISCONNECT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG)); + status = wmi_disconnect_event_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_TKIP_MICERR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG)); + status = wmi_tkip_micerr_event_rx(wmip, datap, len); + break; + case (WMI_BSSINFO_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG)); + status = wmi_bssInfo_event_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_REGDOMAIN_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG)); + status = wmi_regDomain_event_rx(wmip, datap, len); + break; + case (WMI_PSTREAM_TIMEOUT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG)); + status = wmi_pstream_timeout_event_rx(wmip, datap, len); + /* pstreams are fatpipe abstractions that get implicitly created. + * User apps only deal with thinstreams. creation of a thinstream + * by the user or data traffic flow in an AC triggers implicit + * pstream creation. Do we need to send this event to App..? + * no harm in sending it. + */ + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_NEIGHBOR_REPORT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG)); + status = wmi_neighborReport_event_rx(wmip, datap, len); + break; + case (WMI_SCAN_COMPLETE_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG)); + status = wmi_scanComplete_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_CMDERROR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG)); + status = wmi_errorEvent_rx(wmip, datap, len); + break; + case (WMI_REPORT_STATISTICS_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG)); + status = wmi_statsEvent_rx(wmip, datap, len); + break; + case (WMI_RSSI_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_rssiThresholdEvent_rx(wmip, datap, len); + break; + case (WMI_ERROR_REPORT_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG)); + status = wmi_reportErrorEvent_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_OPT_RX_FRAME_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG)); + status = wmi_opt_frame_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_ROAM_TBL_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG)); + status = wmi_roam_tbl_event_rx(wmip, datap, len); + break; + case (WMI_EXTENSION_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG)); + status = wmi_control_rx_xtnd(wmip, osbuf); + break; + case (WMI_CAC_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG)); + status = wmi_cac_event_rx(wmip, datap, len); + break; + case (WMI_REPORT_ROAM_DATA_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG)); + status = wmi_roam_data_event_rx(wmip, datap, len); + break; +#ifdef CONFIG_HOST_TCMD_SUPPORT + case (WMI_TEST_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG)); + status = wmi_tcmd_test_report_rx(wmip, datap, len); + break; +#endif + case (WMI_GET_FIXRATES_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG)); + status = wmi_ratemask_reply_rx(wmip, datap, len); + break; + case (WMI_TX_RETRY_ERR_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG)); + status = wmi_txRetryErrEvent_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_SNR_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_snrThresholdEvent_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_LQ_THRESHOLD_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG)); + status = wmi_lqThresholdEvent_rx(wmip, datap, len); + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); + break; + case (WMI_APLIST_EVENTID): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n")); + status = wmi_aplistEvent_rx(wmip, datap, len); + break; + case (WMI_GET_KEEPALIVE_CMDID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG)); + status = wmi_keepalive_reply_rx(wmip, datap, len); + break; + case (WMI_GET_WOW_LIST_EVENTID): + status = wmi_get_wow_list_event_rx(wmip, datap, len); + break; + case (WMI_GET_PMKID_LIST_EVENTID): + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG)); + status = wmi_get_pmkid_list_event_rx(wmip, datap, len); + break; + default: + A_DPRINTF(DBG_WMI|DBG_ERROR, + (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); + wmip->wmi_stats.cmd_id_err++; + status = A_ERROR; + break; + } + + A_NETBUF_FREE(osbuf); + + return status; +} + +static A_STATUS +wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap; + + if (len < sizeof(WMI_READY_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + wmip->wmi_ready = TRUE; + A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability); + + return A_OK; +} + +static A_STATUS +wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_CONNECT_EVENT *ev; + + if (len < sizeof(WMI_CONNECT_EVENT)) { + return A_EINVAL; + } + ev = (WMI_CONNECT_EVENT *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + DBGARG, ev->channel, + ev->bssid[0], ev->bssid[1], ev->bssid[2], + ev->bssid[3], ev->bssid[4], ev->bssid[5])); + + A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN); + + A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid, + ev->listenInterval, ev->beaconInterval, + ev->networkType, ev->beaconIeLen, + ev->assocReqLen, ev->assocRespLen, + ev->assocInfo); + + return A_OK; +} + +static A_STATUS +wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_REG_DOMAIN_EVENT *ev; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + ev = (WMI_REG_DOMAIN_EVENT *)datap; + + A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain); + + return A_OK; +} + +static A_STATUS +wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_NEIGHBOR_REPORT_EVENT *ev; + int numAps; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap; + numAps = ev->numberOfAps; + + if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) { + return A_EINVAL; + } + + A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor); + + return A_OK; +} + +static A_STATUS +wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_DISCONNECT_EVENT *ev; + + if (len < sizeof(WMI_DISCONNECT_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + ev = (WMI_DISCONNECT_EVENT *)datap; + + A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid)); + + A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid, + ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus); + + return A_OK; +} + +static A_STATUS +wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TKIP_MICERR_EVENT *ev; + + if (len < sizeof(*ev)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + ev = (WMI_TKIP_MICERR_EVENT *)datap; + A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast); + + return A_OK; +} + +static A_STATUS +wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + bss_t *bss; + WMI_BSS_INFO_HDR *bih; + A_UINT8 *buf; + A_UINT32 nodeCachingAllowed; + + if (len <= sizeof(WMI_BSS_INFO_HDR)) { + return A_EINVAL; + } + + A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len); + /* What is driver config for wlan node caching? */ + if(ar6000_get_driver_cfg(wmip->wmi_devt, + AR6000_DRIVER_CFG_GET_WLANNODECACHING, + &nodeCachingAllowed) != A_OK) { + return A_EINVAL; + } + + if(!nodeCachingAllowed) { + return A_OK; + } + + + bih = (WMI_BSS_INFO_HDR *)datap; + buf = datap + sizeof(WMI_BSS_INFO_HDR); + len -= sizeof(WMI_BSS_INFO_HDR); + + A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, " + "bssid \"%02x:%02x:%02x:%02x:%02x:%02x\"\n", DBGARG, + bih->channel, (unsigned char) bih->rssi, bih->bssid[0], + bih->bssid[1], bih->bssid[2], bih->bssid[3], bih->bssid[4], + bih->bssid[5])); + + if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) { + printk("%s() A_OK 2\n", __FUNCTION__); + return A_OK; + } + + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); + if (bss != NULL) { + /* + * Free up the node. Not the most efficient process given + * we are about to allocate a new node but it is simple and should be + * adequate. + */ + wlan_node_reclaim(&wmip->wmi_scan_table, bss); + } + + bss = wlan_node_alloc(&wmip->wmi_scan_table, len); + if (bss == NULL) { + return A_NO_MEMORY; + } + + bss->ni_snr = bih->snr; + bss->ni_rssi = bih->rssi; + A_ASSERT(bss->ni_buf != NULL); + A_MEMCPY(bss->ni_buf, buf, len); + + if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) { + wlan_node_free(bss); + return A_EINVAL; + } + + /* + * Update the frequency in ie_chan, overwriting of channel number + * which is done in wlan_parse_beacon + */ + bss->ni_cie.ie_chan = bih->channel; + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); + + return A_OK; +} + +static A_STATUS +wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + bss_t *bss; + WMI_OPT_RX_INFO_HDR *bih; + A_UINT8 *buf; + + if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) { + return A_EINVAL; + } + + bih = (WMI_OPT_RX_INFO_HDR *)datap; + buf = datap + sizeof(WMI_OPT_RX_INFO_HDR); + len -= sizeof(WMI_OPT_RX_INFO_HDR); + + A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG, + bih->bssid[4], bih->bssid[5])); + + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); + if (bss != NULL) { + /* + * Free up the node. Not the most efficient process given + * we are about to allocate a new node but it is simple and should be + * adequate. + */ + wlan_node_reclaim(&wmip->wmi_scan_table, bss); + } + + bss = wlan_node_alloc(&wmip->wmi_scan_table, len); + if (bss == NULL) { + return A_NO_MEMORY; + } + + bss->ni_snr = bih->snr; + bss->ni_cie.ie_chan = bih->channel; + A_ASSERT(bss->ni_buf != NULL); + A_MEMCPY(bss->ni_buf, buf, len); + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); + + return A_OK; +} + + /* This event indicates inactivity timeout of a fatpipe(pstream) + * at the target + */ +static A_STATUS +wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_PSTREAM_TIMEOUT_EVENT *ev; + + if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) { + return A_EINVAL; + } + + A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG)); + + ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap; + + /* When the pstream (fat pipe == AC) timesout, it means there were no + * thinStreams within this pstream & it got implicitly created due to + * data flow on this AC. We start the inactivity timer only for + * implicitly created pstream. Just reset the host state. + */ + /* Set the activeTsids for this AC to 0 */ + LOCK_WMI(wmip); + wmip->wmi_streamExistsForAC[ev->trafficClass]=0; + wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass); + UNLOCK_WMI(wmip); + + /*Indicate inactivity to driver layer for this fatpipe (pstream)*/ + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass); + + return A_OK; +} + +static A_STATUS +wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_BIT_RATE_CMD *reply; + A_INT32 rate; + + if (len < sizeof(WMI_BIT_RATE_CMD)) { + return A_EINVAL; + } + reply = (WMI_BIT_RATE_CMD *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex)); + + if (reply->rateIndex == RATE_AUTO) { + rate = RATE_AUTO; + } else { + rate = wmi_rateTable[(A_UINT32) reply->rateIndex]; + } + + A_WMI_BITRATE_RX(wmip->wmi_devt, rate); + + return A_OK; +} + +static A_STATUS +wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_FIX_RATES_CMD *reply; + + if (len < sizeof(WMI_BIT_RATE_CMD)) { + return A_EINVAL; + } + reply = (WMI_FIX_RATES_CMD *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask)); + + A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask); + + return A_OK; +} + +static A_STATUS +wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_CHANNEL_LIST_REPLY *reply; + + if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_CHANNEL_LIST_REPLY *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels, + reply->channelList); + + return A_OK; +} + +static A_STATUS +wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TX_PWR_REPLY *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TX_PWR_REPLY *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM); + + return A_OK; +} +static A_STATUS +wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_GET_KEEPALIVE_CMD *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_GET_KEEPALIVE_CMD *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured); + + return A_OK; +} + + +static A_STATUS +wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMIX_DSETOPENREQ_EVENT *dsetopenreq; + + if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) { + return A_EINVAL; + } + dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap; + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id)); + A_WMI_DSET_OPEN_REQ(wmip->wmi_devt, + dsetopenreq->dset_id, + dsetopenreq->targ_dset_handle, + dsetopenreq->targ_reply_fn, + dsetopenreq->targ_reply_arg); + + return A_OK; +} + +#ifdef CONFIG_HOST_DSET_SUPPORT +static A_STATUS +wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMIX_DSETCLOSE_EVENT *dsetclose; + + if (len < sizeof(WMIX_DSETCLOSE_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + dsetclose = (WMIX_DSETCLOSE_EVENT *)datap; + A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie); + + return A_OK; +} + +static A_STATUS +wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMIX_DSETDATAREQ_EVENT *dsetdatareq; + + if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) { + return A_EINVAL; + } + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap; + A_WMI_DSET_DATA_REQ(wmip->wmi_devt, + dsetdatareq->access_cookie, + dsetdatareq->offset, + dsetdatareq->length, + dsetdatareq->targ_buf, + dsetdatareq->targ_reply_fn, + dsetdatareq->targ_reply_arg); + + return A_OK; +} +#endif /* CONFIG_HOST_DSET_SUPPORT */ + +static A_STATUS +wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_SCAN_COMPLETE_EVENT *ev; + + ev = (WMI_SCAN_COMPLETE_EVENT *)datap; + A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, ev->status); + + return A_OK; +} + +/* + * Target is reporting a programming error. This is for + * developer aid only. Target only checks a few common violations + * and it is responsibility of host to do all error checking. + * Behavior of target after wmi error event is undefined. + * A reset is recommended. + */ +static A_STATUS +wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_CMD_ERROR_EVENT *ev; + + ev = (WMI_CMD_ERROR_EVENT *)datap; + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId)); + switch (ev->errorCode) { + case (INVALID_PARAM): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n")); + break; + case (ILLEGAL_STATE): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n")); + break; + case (INTERNAL_ERROR): + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n")); + break; + } + + return A_OK; +} + + +static A_STATUS +wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TARGET_STATS *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_STATS *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, reply); + + return A_OK; +} + +static A_STATUS +wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_RSSI_THRESHOLD_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_RSSI_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, reply->range, reply->rssi); + + return A_OK; +} + + +static A_STATUS +wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TARGET_ERROR_REPORT_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, reply->errorVal); + + return A_OK; +} + +static A_STATUS +wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_CAC_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_CAC_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac, + reply->cac_indication, reply->statusCode, + reply->tspecSuggestion); + + return A_OK; +} + +static A_STATUS +wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMIX_HB_CHALLENGE_RESP_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG)); + + A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source); + + return A_OK; +} + +static A_STATUS +wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TARGET_ROAM_TBL *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ROAM_TBL *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply); + + return A_OK; +} + +static A_STATUS +wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TARGET_ROAM_DATA *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TARGET_ROAM_DATA *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply); + + return A_OK; +} + +static A_STATUS +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_TX_RETRY_ERR_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_TX_RETRY_ERR_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt); + + return A_OK; +} + +static A_STATUS +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_SNR_THRESHOLD_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_SNR_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->snr); + + return A_OK; +} + +static A_STATUS +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_LQ_THRESHOLD_EVENT *reply; + + if (len < sizeof(*reply)) { + return A_EINVAL; + } + reply = (WMI_LQ_THRESHOLD_EVENT *)datap; + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->lq); + + return A_OK; +} + +static A_STATUS +wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + A_UINT16 ap_info_entry_size; + WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap; + WMI_AP_INFO_V1 *ap_info_v1; + A_UINT8 i; + + if (len < sizeof(WMI_APLIST_EVENT)) { + return A_EINVAL; + } + + if (ev->apListVer == APLIST_VER1) { + ap_info_entry_size = sizeof(WMI_AP_INFO_V1); + ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList; + } else { + return A_EINVAL; + } + + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP)); + if (len < (int)(sizeof(WMI_APLIST_EVENT) + + (ev->numAP - 1) * ap_info_entry_size)) + { + return A_EINVAL; + } + + /* + * AP List Ver1 Contents + */ + for (i = 0; i < ev->numAP; i++) { + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\ + "Channel %d\n", i, + ap_info_v1->bssid[0], ap_info_v1->bssid[1], + ap_info_v1->bssid[2], ap_info_v1->bssid[3], + ap_info_v1->bssid[4], ap_info_v1->bssid[5], + ap_info_v1->channel)); + ap_info_v1++; + } + return A_OK; +} + +static A_STATUS +wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + A_UINT32 dropped; + + dropped = *((A_UINT32 *)datap); + datap += sizeof(dropped); + len -= sizeof(dropped); + A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, datap, len); + return A_OK; +} + +#ifdef CONFIG_HOST_GPIO_SUPPORT +static A_STATUS +wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap; + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - intrmask=0x%x input=0x%x.\n", DBGARG, + gpio_intr->intr_mask, gpio_intr->input_values)); + + A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values); + + return A_OK; +} + +static A_STATUS +wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap; + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, + gpio_data->reg_id, gpio_data->value)); + + A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value); + + return A_OK; +} + +static A_STATUS +wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_GPIO_ACK_RX(); + + return A_OK; +} +#endif /* CONFIG_HOST_GPIO_SUPPORT */ + +/* + * Called to send a wmi command. Command specific data is already built + * on osbuf and current osbuf->data points to it. + */ +A_STATUS +wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag) +{ +#define IS_LONG_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID) || (cmdId == WMI_ADD_WOW_PATTERN_CMDID)) + WMI_CMD_HDR *cHdr; + WMI_PRI_STREAM_ID streamID = WMI_CONTROL_PRI; + + A_ASSERT(osbuf != NULL); + + if (syncflag >= END_WMIFLAG) { + return A_EINVAL; + } + + if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { + /* + * We want to make sure all data currently queued is transmitted before + * the cmd execution. Establish a new sync point. + */ + wmi_sync_point(wmip); + } + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) { + return A_NO_MEMORY; + } + + cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); + cHdr->commandId = cmdId; + + /* + * Send cmd, some via control pipe, others via data pipe + */ + if (IS_LONG_CMD(cmdId)) { + wmi_data_hdr_add(wmip, osbuf, CNTL_MSGTYPE); + // TODO ... these can now go through the control endpoint via HTC 2.0 + streamID = WMI_BEST_EFFORT_PRI; + } + A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID); + + if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { + /* + * We want to make sure all new data queued waits for the command to + * execute. Establish a new sync point. + */ + wmi_sync_point(wmip); + } + return (A_OK); +#undef IS_LONG_CMD +} + +A_STATUS +wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, + WMI_SYNC_FLAG syncflag) +{ + WMIX_CMD_HDR *cHdr; + + if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) { + return A_NO_MEMORY; + } + + cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); + cHdr->commandId = cmdId; + + return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag); +} + +A_STATUS +wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType, + DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode, + CRYPTO_TYPE pairwiseCrypto, A_UINT8 pairwiseCryptoLen, + CRYPTO_TYPE groupCrypto,A_UINT8 groupCryptoLen, + int ssidLength, A_UCHAR *ssid, + A_UINT8 *bssid, A_UINT16 channel, A_UINT32 ctrl_flags) +{ + void *osbuf; + WMI_CONNECT_CMD *cc; + + if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) { + return A_EINVAL; + } + if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD)); + + cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cc, sizeof(*cc)); + + A_MEMCPY(cc->ssid, ssid, ssidLength); + cc->ssidLength = ssidLength; + cc->networkType = netType; + cc->dot11AuthMode = dot11AuthMode; + cc->authMode = authMode; + cc->pairwiseCryptoType = pairwiseCrypto; + cc->pairwiseCryptoLen = pairwiseCryptoLen; + cc->groupCryptoType = groupCrypto; + cc->groupCryptoLen = groupCryptoLen; + cc->channel = channel; + cc->ctrl_flags = ctrl_flags; + + if (bssid != NULL) { + A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN); + } + if (wmi_set_keepalive_cmd(wmip, wmip->wmi_keepaliveInterval) != A_OK) { + return(A_ERROR); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel) +{ + void *osbuf; + WMI_RECONNECT_CMD *cc; + + osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD)); + + cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cc, sizeof(*cc)); + + cc->channel = channel; + + if (bssid != NULL) { + A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_disconnect_cmd(struct wmi_t *wmip) +{ + void *osbuf; + A_STATUS status; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + /* Bug fix for 24817(elevator bug) - the disconnect command does not + need to do a SYNC before.*/ + status = (wmi_cmd_send(wmip, osbuf, WMI_DISCONNECT_CMDID, + NO_SYNC_WMIFLAG)); + + return status; +} + +A_STATUS +wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, + A_BOOL forceFgScan, A_BOOL isLegacy, + A_UINT32 homeDwellTime, A_UINT32 forceScanInterval) +{ + void *osbuf; + WMI_START_SCAN_CMD *sc; + + if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*sc)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*sc)); + + sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf)); + sc->scanType = scanType; + sc->forceFgScan = forceFgScan; + sc->isLegacy = isLegacy; + sc->homeDwellTime = homeDwellTime; + sc->forceScanInterval = forceScanInterval; + + return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec, + A_UINT16 fg_end_sec, A_UINT16 bg_sec, + A_UINT16 minact_chdw_msec, A_UINT16 maxact_chdw_msec, + A_UINT16 pas_chdw_msec, + A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags, + A_UINT32 max_dfsch_act_time) +{ + void *osbuf; + WMI_SCAN_PARAMS_CMD *sc; + + osbuf = A_NETBUF_ALLOC(sizeof(*sc)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*sc)); + + sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(sc, sizeof(*sc)); + sc->fg_start_period = fg_start_sec; + sc->fg_end_period = fg_end_sec; + sc->bg_period = bg_sec; + sc->minact_chdwell_time = minact_chdw_msec; + sc->maxact_chdwell_time = maxact_chdw_msec; + sc->pas_chdwell_time = pas_chdw_msec; + sc->shortScanRatio = shScanRatio; + sc->scanCtrlFlags = scanCtrlFlags; + sc->max_dfsch_act_time = max_dfsch_act_time; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask) +{ + void *osbuf; + WMI_BSS_FILTER_CMD *cmd; + + if (filter >= LAST_BSS_FILTER) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->bssFilter = filter; + cmd->ieMask = ieMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag, + A_UINT8 ssidLength, A_UCHAR *ssid) +{ + void *osbuf; + WMI_PROBED_SSID_CMD *cmd; + + if (index > MAX_PROBED_SSID_INDEX) { + return A_EINVAL; + } + if (ssidLength > sizeof(cmd->ssid)) { + return A_EINVAL; + } + if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) { + return A_EINVAL; + } + if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->entryIndex = index; + cmd->flag = flag; + cmd->ssidLength = ssidLength; + A_MEMCPY(cmd->ssid, ssid, ssidLength); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons) +{ + void *osbuf; + WMI_LISTEN_INT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->listenInterval = listenInterval; + cmd->numBeacons = listenBeacons; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons) +{ + void *osbuf; + WMI_BMISS_TIME_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->bmissTime = bmissTime; + cmd->numBeacons = bmissBeacons; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType, + A_UINT8 ieLen, A_UINT8 *ieInfo) +{ + void *osbuf; + WMI_SET_ASSOC_INFO_CMD *cmd; + A_UINT16 cmdLen; + + cmdLen = sizeof(*cmd) + ieLen - 1; + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + + cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, cmdLen); + cmd->ieType = ieType; + cmd->bufferSize = ieLen; + A_MEMCPY(cmd->assocInfo, ieInfo, ieLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode) +{ + void *osbuf; + WMI_POWER_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->powerMode = powerMode; + wmip->wmi_powerMode = powerMode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl, + A_UINT16 atim_windows, A_UINT16 timeout_value) +{ + void *osbuf; + WMI_IBSS_PM_CAPS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->power_saving = pmEnable; + cmd->ttl = ttl; + cmd->atim_windows = atim_windows; + cmd->timeout_value = timeout_value; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod, + A_UINT16 psPollNum, A_UINT16 dtimPolicy) +{ + void *osbuf; + WMI_POWER_PARAMS_CMD *pm; + + osbuf = A_NETBUF_ALLOC(sizeof(*pm)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*pm)); + + pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(pm, sizeof(*pm)); + pm->idle_period = idlePeriod; + pm->pspoll_number = psPollNum; + pm->dtim_policy = dtimPolicy; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout) +{ + void *osbuf; + WMI_DISC_TIMEOUT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->disconnectTimeout = timeout; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType, + A_UINT8 keyUsage, A_UINT8 keyLength, A_UINT8 *keyRSC, + A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, + WMI_SYNC_FLAG sync_flag) +{ + void *osbuf; + WMI_ADD_CIPHER_KEY_CMD *cmd; + + if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) || + (keyMaterial == NULL)) + { + return A_EINVAL; + } + + if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keyIndex = keyIndex; + cmd->keyType = keyType; + cmd->keyUsage = keyUsage; + cmd->keyLength = keyLength; + A_MEMCPY(cmd->key, keyMaterial, keyLength); + if (NULL != keyRSC) { + A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC)); + } + cmd->key_op_ctrl = key_op_ctrl; + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag)); +} + +A_STATUS +wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk) +{ + void *osbuf; + WMI_ADD_KRK_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + A_MEMCPY(cmd->krk, krk, WMI_KRK_LEN); + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_delete_krk_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); + + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_KRK_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex) +{ + void *osbuf; + WMI_DELETE_CIPHER_KEY_CMD *cmd; + + if (keyIndex > WMI_MAX_KEY_INDEX) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keyIndex = keyIndex; + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId, + A_BOOL set) +{ + void *osbuf; + WMI_SET_PMKID_CMD *cmd; + + if (bssid == NULL) { + return A_EINVAL; + } + + if ((set == TRUE) && (pmkId == NULL)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid)); + if (set == TRUE) { + A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid)); + cmd->enable = PMKID_ENABLE; + } else { + A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid)); + cmd->enable = PMKID_DISABLE; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en) +{ + void *osbuf; + WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_akmp_params_cmd(struct wmi_t *wmip, + WMI_SET_AKMP_PARAMS_CMD *akmpParams) +{ + void *osbuf; + WMI_SET_AKMP_PARAMS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->akmpInfo = akmpParams->akmpInfo; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_pmkid_list_cmd(struct wmi_t *wmip, + WMI_SET_PMKID_LIST_CMD *pmkInfo) +{ + void *osbuf; + WMI_SET_PMKID_LIST_CMD *cmd; + A_UINT16 cmdLen; + A_UINT8 i; + + cmdLen = sizeof(pmkInfo->numPMKID) + + pmkInfo->numPMKID * sizeof(WMI_PMKID); + + osbuf = A_NETBUF_ALLOC(cmdLen); + + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->numPMKID = pmkInfo->numPMKID; + + for (i = 0; i < cmd->numPMKID; i++) { + A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i], + WMI_PMKID_LEN); + } + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_pmkid_list_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_PMKID_LIST_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, WMI_PRI_STREAM_ID streamID) +{ + WMI_DATA_HDR *dtHdr; + + A_ASSERT(streamID != WMI_CONTROL_PRI); + A_ASSERT(osbuf != NULL); + + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) { + return A_NO_MEMORY; + } + + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); + dtHdr->info = + (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - streamID %d\n", DBGARG, streamID)); + + return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID)); +} + +typedef struct _WMI_DATA_SYNC_BUFS { + A_UINT8 trafficClass; + void *osbuf; +}WMI_DATA_SYNC_BUFS; + +static A_STATUS +wmi_sync_point(struct wmi_t *wmip) +{ + void *cmd_osbuf; + WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC]; + A_UINT8 i,numPriStreams=0; + A_STATUS status; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + memset(dataSyncBufs,0,sizeof(dataSyncBufs)); + + /* lock out while we walk through the priority list and assemble our local array */ + LOCK_WMI(wmip); + + for (i=0; i < WMM_NUM_AC ; i++) { + if (wmip->wmi_fatPipeExists & (1 << i)) { + numPriStreams++; + dataSyncBufs[numPriStreams-1].trafficClass = i; + } + } + + UNLOCK_WMI(wmip); + + /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */ + + do { + /* + * We allocate all network buffers needed so we will be able to + * send all required frames. + */ + cmd_osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (cmd_osbuf == NULL) { + status = A_NO_MEMORY; + break; + } + + for (i=0; i < numPriStreams ; i++) { + dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0); + if (dataSyncBufs[i].osbuf == NULL) { + status = A_NO_MEMORY; + break; + } + } //end for + + /* + * Send sync cmd followed by sync data messages on all endpoints being + * used + */ + status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID, + NO_SYNC_WMIFLAG); + + if (A_FAILED(status)) { + break; + } + /* cmd buffer sent, we no longer own it */ + cmd_osbuf = NULL; + + for(i=0; i < numPriStreams; i++) { + A_ASSERT(dataSyncBufs[i].osbuf != NULL); + + status = wmi_dataSync_send(wmip, dataSyncBufs[i].osbuf, + WMI_ACCESSCATEGORY_WMISTREAM(wmip,dataSyncBufs[i].trafficClass)); + + if (A_FAILED(status)) { + break; + } + /* we don't own this buffer anymore, NULL it out of the array so it + * won't get cleaned up */ + dataSyncBufs[i].osbuf = NULL; + } //end for + + } while(FALSE); + + /* free up any resources left over (possibly due to an error) */ + + if (cmd_osbuf != NULL) { + A_NETBUF_FREE(cmd_osbuf); + } + + for (i = 0; i < numPriStreams; i++) { + if (dataSyncBufs[i].osbuf != NULL) { + A_NETBUF_FREE(dataSyncBufs[i].osbuf); + } + } + + return (status); +} + +A_STATUS +wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params) +{ + void *osbuf; + WMI_CREATE_PSTREAM_CMD *cmd; + A_UINT16 activeTsids=0; + A_UINT8 fatPipeExistsForAC=0; + + /* Validate all the parameters. */ + if( !((params->userPriority < 8) && + (params->userPriority <= 0x7) && + (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) && + (params->trafficDirection == UPLINK_TRAFFIC || + params->trafficDirection == DNLINK_TRAFFIC || + params->trafficDirection == BIDIR_TRAFFIC) && + (params->trafficType == TRAFFIC_TYPE_APERIODIC || + params->trafficType == TRAFFIC_TYPE_PERIODIC ) && + (params->voicePSCapability == DISABLE_FOR_THIS_AC || + params->voicePSCapability == ENABLE_FOR_THIS_AC || + params->voicePSCapability == ENABLE_FOR_ALL_AC) && + (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) ) + { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + A_DPRINTF(DBG_WMI, + (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG, + params->trafficClass, params->tsid)); + + cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + A_MEMCPY(cmd, params, sizeof(*cmd)); + + /* this is an implicitly created Fat pipe */ + if (params->tsid == WMI_IMPLICIT_PSTREAM) { + LOCK_WMI(wmip); + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); + wmip->wmi_fatPipeExists |= (1<trafficClass); + UNLOCK_WMI(wmip); + } else { + /* this is an explicitly created thin stream within a fat pipe */ + LOCK_WMI(wmip); + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); + activeTsids = wmip->wmi_streamExistsForAC[params->trafficClass]; + wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<tsid); + /* if a thinstream becomes active, the fat pipe automatically + * becomes active + */ + wmip->wmi_fatPipeExists |= (1<trafficClass); + UNLOCK_WMI(wmip); + } + + /* Indicate activty change to driver layer only if this is the + * first TSID to get created in this AC explicitly or an implicit + * fat pipe is getting created. + */ + if (!fatPipeExistsForAC) { + A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass); + } + + /* mike: should be SYNC_BEFORE_WMIFLAG */ + return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid) +{ + void *osbuf; + WMI_DELETE_PSTREAM_CMD *cmd; + A_STATUS status; + A_UINT16 activeTsids=0; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->trafficClass = trafficClass; + cmd->tsid = tsid; + + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + /* Check if the tsid was created & exists */ + if (!(activeTsids & (1<wmi_streamExistsForAC[trafficClass] &= ~(1<wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + + /* Indicate stream inactivity to driver layer only if all tsids + * within this AC are deleted. + */ + if(!activeTsids) { + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass); + wmip->wmi_fatPipeExists &= ~(1<rateIndex = index; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_bitrate_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); +} + +/* + * Returns TRUE iff the given rate index is legal in the current PHY mode. + */ +A_BOOL +wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex) +{ + WMI_PHY_MODE phyMode = wmip->wmi_phyMode; + A_BOOL isValid = TRUE; + switch(phyMode) { + case WMI_11A_MODE: + if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) { + isValid = FALSE; + } + break; + + case WMI_11B_MODE: + if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) { + isValid = FALSE; + } + break; + + case WMI_11GONLY_MODE: + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) { + isValid = FALSE; + } + break; + + case WMI_11G_MODE: + case WMI_11AG_MODE: + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) { + isValid = FALSE; + } + break; + + default: + A_ASSERT(FALSE); + break; + } + + return isValid; +} + +A_INT8 +wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate) +{ + A_INT8 i; + if (rate != -1) + { + for (i=0;;i++) + { + if (wmi_rateTable[(A_UINT32) i] == 0) { + return A_EINVAL; + } + if (wmi_rateTable[(A_UINT32) i] == rate) { + break; + } + } + } + else{ + i = -1; + } + + if(wmi_is_bitrate_index_valid(wmip, i) != TRUE) { + return A_EINVAL; + } + + return i; +} + +A_STATUS +wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask) +{ + void *osbuf; + WMI_FIX_RATES_CMD *cmd; + A_UINT32 rateIndex; + + /* Make sure all rates in the mask are valid in the current PHY mode */ + for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) { + if((1 << rateIndex) & (A_UINT32)fixRatesMask) { + if(wmi_is_bitrate_index_valid(wmip, rateIndex) != TRUE) { + A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG)); + return A_EINVAL; + } + } + } + + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + + cmd->fixRateMask = fixRatesMask; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_ratemask_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_channelList_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_CHANNEL_LIST_CMDID, + NO_SYNC_WMIFLAG)); +} + +/* + * used to generate a wmi sey channel Parameters cmd. + * mode should always be specified and corresponds to the phy mode of the + * wlan. + * numChan should alway sbe specified. If zero indicates that all available + * channels should be used. + * channelList is an array of channel frequencies (in Mhz) which the radio + * should limit its operation to. It should be NULL if numChan == 0. Size of + * array should correspond to numChan entries. + */ +A_STATUS +wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam, + WMI_PHY_MODE mode, A_INT8 numChan, + A_UINT16 *channelList) +{ + void *osbuf; + WMI_CHANNEL_PARAMS_CMD *cmd; + A_INT8 size; + + size = sizeof (*cmd); + + if (numChan) { + if (numChan > WMI_MAX_CHANNELS) { + return A_EINVAL; + } + size += sizeof(A_UINT16) * (numChan - 1); + } + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + wmip->wmi_phyMode = mode; + cmd->scanParam = scanParam; + cmd->phyMode = mode; + cmd->numChannels = numChan; + A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_rssi_threshold_params(struct wmi_t *wmip, + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) +{ + void *osbuf; + A_INT8 size; + WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd; + /* These values are in ascending order */ + if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val || + rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val || + rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val || + rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val || + rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val || + rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val || + rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val || + rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val || + rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val || + rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) { + + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, + WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd) +{ + void *osbuf; + A_INT8 size; + WMI_SET_HOST_SLEEP_MODE_CMD *cmd; + + if( hostModeCmd->awake == hostModeCmd->asleep) { + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_wow_mode_cmd(struct wmi_t *wmip, + WMI_SET_WOW_MODE_CMD *wowModeCmd) +{ + void *osbuf; + A_INT8 size; + WMI_SET_WOW_MODE_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID, + NO_SYNC_WMIFLAG)); + +} + +A_STATUS +wmi_get_wow_list_cmd(struct wmi_t *wmip, + WMI_GET_WOW_LIST_CMD *wowListCmd) +{ + void *osbuf; + A_INT8 size; + WMI_GET_WOW_LIST_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID, + NO_SYNC_WMIFLAG)); + +} + +static A_STATUS +wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + WMI_GET_WOW_LIST_REPLY *reply; + + if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_GET_WOW_LIST_REPLY *)datap; + + A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters, + reply); + + return A_OK; +} + +A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip, + WMI_ADD_WOW_PATTERN_CMD *addWowCmd, + A_UINT8* pattern, A_UINT8* mask, + A_UINT8 pattern_size) +{ + void *osbuf; + A_INT8 size; + WMI_ADD_WOW_PATTERN_CMD *cmd; + A_UINT8 *filter_mask = NULL; + + size = sizeof (*cmd); + + size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8)); + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->filter_list_id = addWowCmd->filter_list_id; + cmd->filter_offset = addWowCmd->filter_offset; + cmd->filter_size = addWowCmd->filter_size; + + A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size); + + filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size); + A_MEMCPY(filter_mask, mask, addWowCmd->filter_size); + + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_del_wow_pattern_cmd(struct wmi_t *wmip, + WMI_DEL_WOW_PATTERN_CMD *delWowCmd) +{ + void *osbuf; + A_INT8 size; + WMI_DEL_WOW_PATTERN_CMD *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID, + NO_SYNC_WMIFLAG)); + +} + +A_STATUS +wmi_set_snr_threshold_params(struct wmi_t *wmip, + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) +{ + void *osbuf; + A_INT8 size; + WMI_SNR_THRESHOLD_PARAMS_CMD *cmd; + /* These values are in ascending order */ + if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val || + snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val || + snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val || + snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val || + snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val || + snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) { + + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_clr_rssi_snr(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(sizeof(int)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_lq_threshold_params(struct wmi_t *wmip, + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd) +{ + void *osbuf; + A_INT8 size; + WMI_LQ_THRESHOLD_PARAMS_CMD *cmd; + /* These values are in ascending order */ + if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val || + lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val || + lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val || + lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val || + lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val || + lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) { + + return A_EINVAL; + } + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + A_MEMCPY(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD)); + + return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask) +{ + void *osbuf; + A_INT8 size; + WMI_TARGET_ERROR_REPORT_BITMASK *cmd; + + size = sizeof (*cmd); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + cmd->bitmask = mask; + + return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source) +{ + void *osbuf; + WMIX_HB_CHALLENGE_RESP_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->cookie = cookie; + cmd->source = source; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask, + A_UINT16 tsr, A_BOOL rep, A_UINT16 size, + A_UINT32 valid) +{ + void *osbuf; + WMIX_DBGLOG_CFG_MODULE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->config.cfgmmask = mmask; + cmd->config.cfgtsr = tsr; + cmd->config.cfgrep = rep; + cmd->config.cfgsize = size; + cmd->config.cfgvalid = valid; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_stats_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_STATISTICS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid) +{ + void *osbuf; + WMI_ADD_BAD_AP_CMD *cmd; + + if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->badApIndex = apIndex; + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid)); + + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex) +{ + void *osbuf; + WMI_DELETE_BAD_AP_CMD *cmd; + + if (apIndex > WMI_MAX_BAD_AP_INDEX) { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->badApIndex = apIndex; + + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM) +{ + void *osbuf; + WMI_SET_TX_PWR_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->dbM = dbM; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_txPwr_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on) +{ + WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0, + WMI_SHORTSCANRATIO_DEFAULT, + DEFAULT_SCAN_CTRL_FLAGS, + 0}; + + if (on) { + /* Enable foreground scanning */ + if (wmi_scanparams_cmd(wmip, scParams.fg_start_period, + scParams.fg_end_period, + scParams.bg_period, + scParams.minact_chdwell_time, + scParams.maxact_chdwell_time, + scParams.pas_chdwell_time, + scParams.shortScanRatio, + scParams.scanCtrlFlags, + scParams.max_dfsch_act_time) != A_OK) { + return -EIO; + } + } else { + wmi_disconnect_cmd(wmip); + if (wmi_scanparams_cmd(wmip, 0xFFFF, 0, 0, 0, + 0, 0, 0, 0xFF, 0) != A_OK) { + return -EIO; + } + } + + return A_OK; +} + + +A_UINT16 +wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass) +{ + A_UINT16 activeTsids=0; + + LOCK_WMI(wmip); + activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; + UNLOCK_WMI(wmip); + + return activeTsids; +} + +A_STATUS +wmi_get_roam_tbl_cmd(struct wmi_t *wmip) +{ + void *osbuf; + + osbuf = A_NETBUF_ALLOC(0); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_TBL_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType) +{ + void *osbuf; + A_UINT32 size = sizeof(A_UINT8); + WMI_TARGET_ROAM_DATA *cmd; + + osbuf = A_NETBUF_ALLOC(size); /* no payload */ + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf)); + cmd->roamDataType = roamDataType; + + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, + A_UINT8 size) +{ + void *osbuf; + WMI_SET_ROAM_CTRL_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + A_MEMCPY(cmd, p, size); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_powersave_timers_cmd(struct wmi_t *wmip, + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, + A_UINT8 size) +{ + void *osbuf; + WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd; + + /* These timers can't be zero */ + if(!pCmd->psPollTimeout || !pCmd->triggerTimeout || + !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD || + pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) || + !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD || + pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD)) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, size); + + cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, size); + + A_MEMCPY(cmd, pCmd, size); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, + NO_SYNC_WMIFLAG)); +} + +#ifdef CONFIG_HOST_GPIO_SUPPORT +/* Send a command to Target to change GPIO output pins. */ +A_STATUS +wmi_gpio_output_set(struct wmi_t *wmip, + A_UINT32 set_mask, + A_UINT32 clear_mask, + A_UINT32 enable_mask, + A_UINT32 disable_mask) +{ + void *osbuf; + WMIX_GPIO_OUTPUT_SET_CMD *output_set; + int size; + + size = sizeof(*output_set); + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - set=0x%x clear=0x%x enb=0x%x dis=0x%x\n", DBGARG, + set_mask, clear_mask, enable_mask, disable_mask)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf)); + + output_set->set_mask = set_mask; + output_set->clear_mask = clear_mask; + output_set->enable_mask = enable_mask; + output_set->disable_mask = disable_mask; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID, + NO_SYNC_WMIFLAG)); +} + +/* Send a command to the Target requesting state of the GPIO input pins */ +A_STATUS +wmi_gpio_input_get(struct wmi_t *wmip) +{ + void *osbuf; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + osbuf = A_NETBUF_ALLOC(0); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INPUT_GET_CMDID, + NO_SYNC_WMIFLAG)); +} + +/* Send a command to the Target that changes the value of a GPIO register. */ +A_STATUS +wmi_gpio_register_set(struct wmi_t *wmip, + A_UINT32 gpioreg_id, + A_UINT32 value) +{ + void *osbuf; + WMIX_GPIO_REGISTER_SET_CMD *register_set; + int size; + + size = sizeof(*register_set); + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf)); + + register_set->gpioreg_id = gpioreg_id; + register_set->value = value; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID, + NO_SYNC_WMIFLAG)); +} + +/* Send a command to the Target to fetch the value of a GPIO register. */ +A_STATUS +wmi_gpio_register_get(struct wmi_t *wmip, + A_UINT32 gpioreg_id) +{ + void *osbuf; + WMIX_GPIO_REGISTER_GET_CMD *register_get; + int size; + + size = sizeof(*register_get); + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf)); + + register_get->gpioreg_id = gpioreg_id; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID, + NO_SYNC_WMIFLAG)); +} + +/* Send a command to the Target acknowledging some GPIO interrupts. */ +A_STATUS +wmi_gpio_intr_ack(struct wmi_t *wmip, + A_UINT32 ack_mask) +{ + void *osbuf; + WMIX_GPIO_INTR_ACK_CMD *intr_ack; + int size; + + size = sizeof(*intr_ack); + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf)); + + intr_ack->ack_mask = ack_mask; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID, + NO_SYNC_WMIFLAG)); +} +#endif /* CONFIG_HOST_GPIO_SUPPORT */ + +A_STATUS +wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop, A_UINT8 eCWmin, + A_UINT8 eCWmax, A_UINT8 aifsn) +{ + void *osbuf; + WMI_SET_ACCESS_PARAMS_CMD *cmd; + + if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) || + (aifsn > WMI_MAX_AIFSN_ACPARAM)) + { + return A_EINVAL; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->txop = txop; + cmd->eCWmin = eCWmin; + cmd->eCWmax = eCWmax; + cmd->aifsn = aifsn; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType, + A_UINT8 trafficClass, A_UINT8 maxRetries, + A_UINT8 enableNotify) +{ + void *osbuf; + WMI_SET_RETRY_LIMITS_CMD *cmd; + + if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) && + (frameType != DATA_FRAMETYPE)) + { + return A_EINVAL; + } + + if (maxRetries > WMI_MAX_RETRIES) { + return A_EINVAL; + } + + if (frameType != DATA_FRAMETYPE) { + trafficClass = 0; + } + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf)); + cmd->frameType = frameType; + cmd->trafficClass = trafficClass; + cmd->maxRetries = maxRetries; + cmd->enableNotify = enableNotify; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID, + NO_SYNC_WMIFLAG)); +} + +void +wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid) +{ + if (bssid != NULL) { + A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN); + } +} + +A_STATUS +wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode) +{ + void *osbuf; + WMI_SET_OPT_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->optMode = optMode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID, + SYNC_BOTH_WMIFLAG)); +} + +A_STATUS +wmi_opt_tx_frame_cmd(struct wmi_t *wmip, + A_UINT8 frmType, + A_UINT8 *dstMacAddr, + A_UINT8 *bssid, + A_UINT16 optIEDataLen, + A_UINT8 *optIEData) +{ + void *osbuf; + WMI_OPT_TX_FRAME_CMD *cmd; + osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd))); + + cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1)); + + cmd->frmType = frmType; + cmd->optIEDataLen = optIEDataLen; + //cmd->optIEData = (A_UINT8 *)((int)cmd + sizeof(*cmd)); + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid)); + A_MEMCPY(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr)); + A_MEMCPY(&cmd->optIEData[0], optIEData, optIEDataLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl) +{ + void *osbuf; + WMI_BEACON_INT_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->beaconInterval = intvl; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID, + NO_SYNC_WMIFLAG)); +} + + +A_STATUS +wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize) +{ + void *osbuf; + WMI_SET_VOICE_PKT_SIZE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->voicePktSize = voicePktSize; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID, + NO_SYNC_WMIFLAG)); +} + + +A_STATUS +wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen) +{ + void *osbuf; + WMI_SET_MAX_SP_LEN_CMD *cmd; + + /* maxSPLen is a two-bit value. If user trys to set anything + * other than this, then its invalid + */ + if(maxSPLen & ~0x03) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->maxSPLen = maxSPLen; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_UINT8 +convert_userPriority_to_trafficClass(A_UINT8 userPriority) +{ + return (up_to_ac[userPriority & 0x7]); +} + +A_UINT8 +wmi_get_power_mode_cmd(struct wmi_t *wmip) +{ + return wmip->wmi_powerMode; +} + +A_STATUS +wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance) +{ + return A_OK; +} + +#ifdef CONFIG_HOST_TCMD_SUPPORT +static A_STATUS +wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) +{ + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len); + + return A_OK; +} + +#endif /* CONFIG_HOST_TCMD_SUPPORT*/ + +A_STATUS +wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode) +{ + void *osbuf; + WMI_SET_AUTH_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->mode = mode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode) +{ + void *osbuf; + WMI_SET_REASSOC_MODE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->mode = mode; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status) +{ + void *osbuf; + WMI_SET_LPREAMBLE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold) +{ + void *osbuf; + WMI_SET_RTS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->threshold = threshold; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status) +{ + void *osbuf; + WMI_SET_WMM_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID, + NO_SYNC_WMIFLAG)); + +} + +A_STATUS +wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg) +{ + void *osbuf; + WMI_SET_WMM_TXOP_CMD *cmd; + + if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) ) + return A_EINVAL; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->txopEnable = cfg; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID, + NO_SYNC_WMIFLAG)); + +} + +#ifdef CONFIG_HOST_TCMD_SUPPORT +/* WMI layer doesn't need to know the data type of the test cmd. + This would be beneficial for customers like Qualcomm, who might + have different test command requirements from differnt manufacturers + */ +A_STATUS +wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len) +{ + void *osbuf; + char *data; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); + + osbuf= A_NETBUF_ALLOC(len); + if(osbuf == NULL) + { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, len); + data = A_NETBUF_DATA(osbuf); + A_MEMCPY(data, buf, len); + + return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID, + NO_SYNC_WMIFLAG)); +} + +#endif + +A_STATUS +wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status) +{ + void *osbuf; + WMI_SET_BT_STATUS_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->streamType = streamType; + cmd->status = status; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd) +{ + void *osbuf; + WMI_SET_BT_PARAMS_CMD* alloc_cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(alloc_cmd, sizeof(*cmd)); + A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd)); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_get_keepalive_configured(struct wmi_t *wmip) +{ + void *osbuf; + WMI_GET_KEEPALIVE_CMD *cmd; + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_UINT8 +wmi_get_keepalive_cmd(struct wmi_t *wmip) +{ + return wmip->wmi_keepaliveInterval; +} + +A_STATUS +wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval) +{ + void *osbuf; + WMI_SET_KEEPALIVE_CMD *cmd; + + osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*cmd)); + + cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, sizeof(*cmd)); + cmd->keepaliveInterval = keepaliveInterval; + wmip->wmi_keepaliveInterval = keepaliveInterval; + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID, + NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen, + A_UINT8 *ieInfo) +{ + void *osbuf; + WMI_SET_APPIE_CMD *cmd; + A_UINT16 cmdLen; + + if (ieLen > WMI_MAX_IE_LEN) { + return A_ERROR; + } + cmdLen = sizeof(*cmd) + ieLen - 1; + osbuf = A_NETBUF_ALLOC(cmdLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, cmdLen); + + cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf)); + A_MEMZERO(cmd, cmdLen); + + cmd->mgmtFrmType = mgmtFrmType; + cmd->ieLen = ieLen; + A_MEMCPY(cmd->ieInfo, ieInfo, ieLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG)); +} + +A_STATUS +wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen) +{ + void *osbuf; + A_UINT8 *data; + + osbuf = A_NETBUF_ALLOC(dataLen); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, dataLen); + + data = A_NETBUF_DATA(osbuf); + + A_MEMCPY(data, cmd, dataLen); + + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG)); +} + +A_INT32 +wmi_get_rate(A_INT8 rateindex) +{ + if (rateindex == RATE_AUTO) { + return 0; + } else { + return(wmi_rateTable[(A_UINT32) rateindex]); + } +} + +void +wmi_node_return (struct wmi_t *wmip, bss_t *bss) +{ + if (NULL != bss) + { + wlan_node_return (&wmip->wmi_scan_table, bss); + } +} + +bss_t * +wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid, + A_UINT32 ssidLength, A_BOOL bIsWPA2) +{ + bss_t *node = NULL; + node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid, + ssidLength, bIsWPA2); + return node; +} + +void +wmi_free_allnodes(struct wmi_t *wmip) +{ + wlan_free_allnodes(&wmip->wmi_scan_table); +} + +bss_t * +wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr) +{ + bss_t *ni=NULL; + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); + return ni; +} + +A_STATUS +wmi_dset_open_reply(struct wmi_t *wmip, + A_UINT32 status, + A_UINT32 access_cookie, + A_UINT32 dset_size, + A_UINT32 dset_version, + A_UINT32 targ_handle, + A_UINT32 targ_reply_fn, + A_UINT32 targ_reply_arg) +{ + void *osbuf; + WMIX_DSETOPEN_REPLY_CMD *open_reply; + + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%x\n", DBGARG, (int)wmip)); + + osbuf = A_NETBUF_ALLOC(sizeof(*open_reply)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + A_NETBUF_PUT(osbuf, sizeof(*open_reply)); + open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); + + open_reply->status = status; + open_reply->targ_dset_handle = targ_handle; + open_reply->targ_reply_fn = targ_reply_fn; + open_reply->targ_reply_arg = targ_reply_arg; + open_reply->access_cookie = access_cookie; + open_reply->size = dset_size; + open_reply->version = dset_version; + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID, + NO_SYNC_WMIFLAG)); +} + +static A_STATUS +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len) +{ + WMI_PMKID_LIST_REPLY *reply; + A_UINT32 expected_len; + + if (len < sizeof(WMI_PMKID_LIST_REPLY)) { + return A_EINVAL; + } + reply = (WMI_PMKID_LIST_REPLY *)datap; + expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN; + + if (len < expected_len) { + return A_EINVAL; + } + + A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID, + reply->pmkidList); + + return A_OK; +} + +#ifdef CONFIG_HOST_DSET_SUPPORT +A_STATUS +wmi_dset_data_reply(struct wmi_t *wmip, + A_UINT32 status, + A_UINT8 *user_buf, + A_UINT32 length, + A_UINT32 targ_buf, + A_UINT32 targ_reply_fn, + A_UINT32 targ_reply_arg) +{ + void *osbuf; + WMIX_DSETDATA_REPLY_CMD *data_reply; + int size; + + size = sizeof(*data_reply) + length; + + A_DPRINTF(DBG_WMI, + (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status)); + + osbuf = A_NETBUF_ALLOC(size); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + A_NETBUF_PUT(osbuf, size); + data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); + + data_reply->status = status; + data_reply->targ_buf = targ_buf; + data_reply->targ_reply_fn = targ_reply_fn; + data_reply->targ_reply_arg = targ_reply_arg; + data_reply->length = length; + + if (status == A_OK) { + if (a_copy_from_user(data_reply->buf, user_buf, length)) { + return A_ERROR; + } + } + + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID, + NO_SYNC_WMIFLAG)); +} +#endif /* CONFIG_HOST_DSET_SUPPORT */ + +A_STATUS +wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status) +{ + void *osbuf; + char *cmd; + + wps_enable = status; + + osbuf = a_netbuf_alloc(sizeof(1)); + if (osbuf == NULL) { + return A_NO_MEMORY; + } + + a_netbuf_put(osbuf, sizeof(1)); + + cmd = (char *)(a_netbuf_to_data(osbuf)); + + A_MEMZERO(cmd, sizeof(*cmd)); + cmd[0] = (status?1:0); + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID, + NO_SYNC_WMIFLAG)); +} + diff --git a/drivers/ar6000/wmi/wmi_doc.h b/drivers/ar6000/wmi/wmi_doc.h new file mode 100644 index 00000000000..19cd9386cab --- /dev/null +++ b/drivers/ar6000/wmi/wmi_doc.h @@ -0,0 +1,4421 @@ +/* + * + * Copyright (c) 2004-2007 Atheros Communications Inc. + * All rights reserved. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * + * + */ + + +#if 0 +Wireless Module Interface (WMI) Documentaion + + This section describes the format and the usage model for WMI control and + data messages between the host and the AR6000-based targets. The header + file include/wmi.h contains all command and event manifest constants as + well as structure typedefs for each set of command and reply parameters. + +Data Frames + + The data payload transmitted and received by the target follows RFC-1042 + encapsulation and thus starts with an 802.2-style LLC-SNAP header. The + WLAN module completes 802.11 encapsulation of the payload, including the + MAC header, FCS, and WLAN security related fields. At the interface to the + message transport (HTC), a data frame is encapsulated in a WMI message. + +WMI Message Structure + + The WMI protocol leverages an 802.3-style Ethernet header in communicating + the source and destination information between the host and the AR6000 + modules using a 14-byte 802.3 header ahead of the 802.2-style payload. In + addition, the WMI protocol adds a header to all data messages: + + { + INT8 rssi + The RSSI of the received packet and its units are shown in db above the + noise floor, and the noise floor is shown in dbm. + UINT8 info + Contains information on message type and user priority. Message type + differentiates between a data packet and a synchronization message. + } WMI_DATA_HDR + + User priority contains the 802.1d user priority info from host to target. Host + software translates the host Ethernet format to 802.3 format prior to Tx and + 802.3 format to host format in the Rx direction. The host does not transmit the + FCS that follows the data. MsgType differentiates between a regular data + packet (msgType=0) and a synchronization message (msgType=1). + +Data Endpoints + + The AR6000 chipset provides several data endpoints to support quality of + service (QoS) and maintains separate queues and separate DMA engines for + each data endpoint. A data endpoint can be bi-directional. + + Best effort (BE) class traffic uses the default data endpoint (2). The host can + establish up to two additional data endpoints for other traffic classes. Once + such a data endpoint is established, it sends and receives corresponding QoS + traffic in a manner similar to the default data endpoint. + + If QoS is desired over the interconnect, host software must classify each data + packet and place it on the appropriate data endpoint. The information + required to classify data is generally available in-band as an 802.1p/q style + tag or as the ToS field in the IP header. The information may also be available + out-of-band depending on the host DDI. + +Connection States + + Table B-1 describes the AR6000 WLAN connection states: + + Table B-1. AR6000 Connection States + +Connection State + Description + + DISCONNECTED + In this state, the AR6000 device is not connected to a wireless + network. The device is in this state after reset when it sends the + WIRELESS MODULE “READY” EVENT, after it processes a + DISCONNECT command, and when it loses its link with the + access point (AP) that it was connected to. The device signals a + transition to the DISCONNECTED state with a “DISCONNECT” + event. + +CONNECTED + In this state, the AR6000 device is connected to wireless networks. + The device enters this state after successfully processing a + CONNECT, which establishes a connection with a wireless + network. The device signals a transition to the CONNECTED state + with a “CONNECT” event. + + +Message Types + + WMI uses commands, replies, and events for the control and configuration of + the AR6000 device. The control protocol is asynchronous. Table B-2 describes + AR6000 message types: + +Table B-2. AR6000 Message Types + +Message Type + Description + +Commands + Control messages that flow from the host to the device + +Replies/Events + Control messages that flow from the device to the host. + + The device issues a reply to some WMI commands, but not to others. + The payload in a reply is command-specific, and some commands do + not trigger a reply message at all. Events are control messages issued + by the device to signal the occurrence of an asynchronous event. + + +WMI Message Format + + All WMI control commands, replies and events use the header format: + + WMI_CMD_HDR Header Format + { + UINT16 id + This 16-bit constant identifies which WMI command the host is issuing, + which command the target is replying to, or which event has occurred. + WMI_CMD_HDR + } + + + A variable-size command-, reply-, or event-specific payload follows the + header. Over the interconnect, all fields in control messages (including + WMI_CMD_HDR and the command specific payload) use 32-bit little Endian + byte ordering and fields are packed. The AR6000 device always executes + commands in order, and the host may send multiple commands without + waiting for previous commands to complete. A majority of commands are + processed to completion once received. Other commands trigger a longer + duration activity whose completion is signaled to the host through an event. + +Command Restrictions + + Some commands may only be issued when the AR6000 device is in a certain + state. The host is required to wait for an event signaling a state transition + before such a command can be issued. For example, if a command requires + the device to be in the CONNECTED state, then the host is required to wait + for a “CONNECT” event before it issues that command. + + The device ignores any commands inappropriate for its current state. If the + command triggers a reply, the device generates an error reply. Otherwise, the + device silently ignores the inappropriate command. + +Command and Data Synchronization + + WMI provides a mechanism for a host to advise the device of necessary + synchronization between commands and data. The device implements + synchronization; no implicit synchronization exists between endpoints. + + The host controls synchronization using the “SYNCHRONIZE” command + over the control channel and synchronization messages over data channels. + The device stops each data channel upon receiving a synchronization message + on that channel, processing all data packets received prior to that message. + After the device receives synchronization messages for each data endpoint + and the “SYNCHRONIZE” command, it resumes all channels. + + When the host must guarantee a command executes before processing new + data packets, it first issues the command, then issues the “SYNCHRONIZE” + command and sends synchronization messages on data channels. When the + host must guarantee the device has processed all old data packets before a + processing a new command, it issues a “SYNCHRONIZE” command and + synchronization messages on all data channels, then issues the desired + command. + + + +WMI Commands + + ADD_BAD_AP + Cause the AR6000 device to avoid a particular AP + ADD_CIPHER_KEY + Add or replace any of the four AR6000 encryption keys + ADD_WOW_PATTERN + Used to add a pattern to the WoW pattern list + CLR_RSSI_SNR + Clear the current calculated RSSI and SNR value + CONNECT_CMD + Request that the AR6000 device establish a wireless connection + with the specified SSID + CREATE_PSTREAM + Create prioritized data endpoint between the host and device + DELETE_BAD_AP + Clear an entry in the bad AP table + DELETE_CIPHER_KEY + Delete a previously added cipher key + DELETE_PSTREAM + Delete a prioritized data endpoint + DELETE_WOW_PATTERN + Remove a pre-specified pattern from the WoW pattern list + EXTENSION + WMI message interface command + GET_BIT_RATE + Retrieve rate most recently used by the AR6000 + GET_CHANNEL_LIST + Retrieve list of channels used by the AR6000 + GET_FIXRATES + Retrieves the rate-mask set via the SET_FIXRATES command. + GET_PMKID_LIST_CMD + Retrieve the firmware list of PMKIDs + GET_ROAM_DATA + Internal use for data collection; available in special build only + GET_ROAM_TBL + Retrieve the roaming table maintained on the target + GET_TARGET_STATS + Request that the target send the statistics it maintains + GET_TX_PWR + Retrieve the current AR6000 device Tx power levels + GET_WOW_LIST + Retrieve the current list of WoW patterns + LQ_THRESHOLD_PARAMS + Set the link quality thresholds + OPT_TX_FRAME + Send a special frame (special feature) + RECONNECT + Request a reconnection to a BSS + RSSI_THRESHOLD_PARAMS + Configure how the AR6000 device monitors and reports signal + strength (RSSI) of the connected BSS + SCAN_PARAMS + Determine dwell time and changes scanned channels + SET_ACCESS_PARAMS + Set access parameters for the wireless network + SET_ADHOC_BSSID + Set the BSSID for an ad hoc network + SET_AKMP_PARAMS + Set multiPMKID mode + SET_APPIE + Add application-specified IE to a management frame + SET_ASSOC_INFO + Specify the IEs the device should add to association or + reassociation requests + SET_AUTH_MODE + Set 802.11 authentication mode of reconnection + SET_BEACON_INT + Set the beacon interval for an ad hoc network + SET_BIT_RATE + Set the AR6000 to a specific fixed bit rate + SET_BMISS_TIME + Set the beacon miss time + SET_BSS_FILTER + Inform the AR6000 of network types about which it wants to + receive information using a “BSSINFO” event + SET_BT_PARAMS + Set the status of a Bluetooth stream (SCO or A2DP) or set + Bluetooth coexistence register parameters + SET_BT_STATUS + Set the status of a Bluetooth stream (SCO or A2DP) + SET_CHANNEL_PARAMETERS + Configure WLAN channel parameters + SET_DISC_TIMEOUT + Set the amount of time the AR6000 spends attempting to + reestablish a connection + SET_FIXRATES + Set the device to a specific fixed PHY rate (supported subset) + SET_HALPARAM + Internal AR6000 command to set certain hardware parameters + SET_HOST_SLEEP_MODE + Set the host mode to asleep or awake + SET_IBSS_PM_CAPS + Support a non-standard power management scheme for an + ad hoc network + SET_LISTEN_INT + Request a listen interval + SET_LPREAMBLE + Override the short preamble capability of the AR6000 device + SET_MAX_SP_LEN + Set the maximum service period + SET_OPT_MODE + Set the special mode on/off (special feature) + SET_PMKID + Set the pairwise master key ID (PMKID) + SET_PMKID_LIST_CMD + Configure the firmware list of PMKIDs + SET_POWER_MODE + Set guidelines on trade-off between power utilization + SET_POWER_PARAMS + Configure power parameters + SET_POWERSAVE_PARAMS + Set the two AR6000 power save timers + SET_PROBED_SSID + Provide list of SSIDs the device should seek + SET_REASSOC_MODE + Specify whether the disassociated frame should be sent upon + reassociation + SET_RETRY_LIMITS + Limit how many times the device tries to send a frame + SET_ROAM_CTRL + Control roaming behavior + SET_RTS + Determine when RTS should be sent + SET_SCAN_PARAMS + Set the AR6000 scan parameters + SET_TKIP_COUNTERMEASURES + Enable/disable reports of TKIP MIC errors + SET_TX_PWR + Specify the AR6000 device Tx power levels + SET_VOICE_PKT_SIZE + Set voice packet size + SET_WMM + Override the AR6000 WMM capability + SET_WMM_TXOP + Configure TxOP bursting when sending traffic to a WMM- + capable AP + SET_WOW_MODE + Enable/disable WoW mode + SET_WSC_STATUS + Enable/disable profile check in cserv when the WPS protocol + is in progress + SNR_THRESHOLD_PARAMS + Configure how the device monitors and reports SNR of BSS + START_SCAN + Start a long or short channel scan + SYNCHRONIZE + Force a synchronization point between command and data + paths + TARGET_REPORT_ERROR_BITMASK + Control “ERROR_REPORT” events from the AR6000 + + + + +Name + ADD_BAD_AP + +Synopsis + The host uses this command to cause the AR6000 to avoid a particular AP. The + AR6000 maintain a table with up to two APs to avoid. An ADD_BAD_AP command + adds or replaces the specified entry in this bad AP table. + + If the AR6000 are currently connected to the AP specified in this command, they + disassociate. + +Command + wmiconfig eth1 --badap + +Command Parameters + UINT8 badApIndex Index [0...1] that identifies which entry in the + bad AP table to use + + + UINT8 bssid[6] MAC address of the AP to avoid + +Command Values + badApIndex = 0, 1 Entry in the bad AP table to use + +Reset Value + The bad AP table is cleared + +Restrictions + None + +See Also + “DELETE_BAD_AP” on page B-13 + +===================================================================== +Name + ADD_CIPHER_KEY + +Synopsis + The host uses this command to add/replace any of four encryption keys on the + AR6000. The ADD_CIPHER_KEY command is issued after the CONNECT event + has been received by the host for all dot11Auth modes except for SHARED_AUTH. + When the dot11AuthMode is SHARED_AUTH, then the ADD_CIPHER_KEY + command should be issued before the “CONNECT” command. + +Command + wmiconfig eth1 --cipherkey + + +Command Parameters + UINT8 keyIndex Index (0...3) of the key to add/replace; + uniquely identifies the key + UINT8 keyType CRYPTO_TYPE + UINT8 keyUsage Specifies usage parameters of the key when + keyType = WEP_CRYPT + UINT8 keyLength Length of the key in bytes + UINT8 keyOpCtrl bit[0] = Initialize TSC (default), + bit[1] = Initialize RSC + UINT8 keyRSC[8] Key replay sequence counter (RSC) initial + value the device should use + UINT8 key[32] Key material used for this connection + Command Values + { + NONE_CRYPT = 1 + WEP_CRYPT = 2 + TKIP_CRYPT = 3 + AES_CRYPT = 4 + KEY_OP_INIT_TSC 0x01 + KEY_OP_INIT_RSC 0x02 + KEY_OP_INIT_VAL 0x03 + Default is to Initialize the TSC + KEY_OP_VALID_MASK 0x04 + Two operations defined + } CRYPTO_TYPE + + { + PAIRWISE_USAGE = 0 Set if the key is used for unicast traffic only + GROUP_USAGE = 1 Set if the key is used to receive multicast + traffic (also set for static WEP keys) + TX_USAGE = 2 Set for the GROUP key used to transmit frames + All others are reserved + } KEY_USAGE + +Reset Value + The four available keys are disabled. + +Restrictions + The cipher should correspond to the encryption mode specified in the “CONNECT” + command. + +See Also + “DELETE_CIPHER_KEY” + +===================================================================== + + +Name + ADD_WOW_PATTERN + +Synopsis + The host uses this command to add a pattern to the WoW pattern list; used for + pattern-matching for host wakeups by the WoW module. If the host mode is asleep + and WoW is enabled, all packets are matched against the existing WoW patterns. If a + packet matches any of the patterns specified, the target will wake up the host. All + non-matching packets are discarded by the target without being sent up to the host. + +Command + wmiconfig –addwowpattern + + +Command Parameters + A_UINT8 filter_list_id ID of the list that is to include the new pattern + A_UINT8 filter_size Size of the new pattern + A_UINT8 filter_offset Offset at which the pattern matching for this + new pattern should begin at + A_UINT8 filter[1] Byte stream that contains both the pattern and + the mask of the new WoW wake-up pattern + +Reply Parameters + None + +Reset Value + None defined (default host mode is awake) + +Restrictions + None + +See Also + “DELETE_WOW_PATTERN” + +===================================================================== + + +Name + CLR_RSSI_SNR + +Synopsis + Clears the current calculated RSSI and SNR value. RSSI and SNR are reported by + running-average value. This command will clear the history and have a fresh start + for the running-average mechanism. + +Command + wmiconfig eth1 --cleanRssiSnr + +Command Parameters + None + +Reply Parameters + None + +Reset Value + None defined + +Restrictions + None + +===================================================================== + +Name + CONNECT_CMD + +Synopsis + New connect control information (connectCtrl) is added, with 32 possible modifiers. + + CONNECT_SEND_REASSOC + Valid only for a host-controlled connection to a + particular AP. If this bit is set, a reassociation frame is + sent. If this bit is clear, an association request frame is + sent to the AP. + + CONNECT_IGNORE_WPAx_GROUP_CIPHER + No group key is issued in the CONNECT command, + so use the group key advertised by the AP. In a target- + initiated roaming situation this allows a STA to roam + between APs that support different multicast ciphers. + + CONNECT_PROFILE_MATCH_DONE + In a host-controlled connection case, it is possible that + during connect, firmware may not have the + information for a profile match (e.g, when the AP + supports hidden SSIDs and the device may not + transmit probe requests during connect). By setting + this bit in the connection control information, the + firmware waits for a beacon from the AP with the + BSSID supplied in the CONNECT command. No + additional profile checks are done. + + CONNECT_IGNORE_AAC_BEACON + Ignore the Admission Capacity information in the + beacon of the AP + + CONNECT_ASSOC_POLICY_USER + When set, the CONNECT_SEND_REASSOC setting + determines if an Assoc or Reassoc is sent to an AP + +Command + wmiconfig --setconnectctrl + +Command Parameters + typedef struct{ + A_UINT8 networktype; + A_UINT8 dot11authmode; + A_UINT8 authmode; + A_UINT8 pairwiseCryptoType; /*CRYPTO_TYPE*/ + A_UINT8 pairwiseCryptoLen; + A_UINT8 groupCryptoType; /*CRYPTO_TYPE*/ + A_UINT8 groupCryptoLen; + A_UINT8 ssidLength; + A_UCHAR ssid[WMI_MAX_SSID_LEN]; + A_UINT16 channel; + A_UINT8 bssid[AUTH_MAC_LEN]; + A_UINT8 ctrl_flags; /*WMI_CONNECT_CTRL_FLAGS_BITS*/ + } WMI_CONNECT_CMD; + + ctrl flags bitmask + = 0x0001 CONNECT_ASSOC_POLICY_USER + Assoc frames are sent using the policy specified by + the flag + = 0x0002 CONNECT_SEND_REASSOC + Send Reassoc frame while connecting, otherwise send + assoc frames + = 0x0004 CONNECT_IGNORE_WPAx_GROUP_CIPHER + Ignore WPAx group cipher for WPA/WPA2 + = 0x0008 CONNECT_PROFILE_MATCH_DONE + Ignore any profile check + = 0x0010 CONNECT_IGNORE_AAC_BEACON + Ignore the admission control information in the + beacon + ... CONNECT_CMD, continued + Command Values + typedef enum { + INFRA_NETWORK = 0x01, + ADHOC_NETWORK = 0x02, + ADHOC_CREATOR = 0x04, + } NETWORK_TYPE; + + typedef enum { + OPEN_AUTH = 0x01, + SHARED_AUTH = 0x02, + LEAP_AUTH = 0x04, + } DOT11_AUTH_MODE; + typedef enum { + NONE_AUTH = 0x01, + WPA_AUTH = 0x02, + WPA_PSK_AUTH = 0x03, + WPA2_AUTH = 0x04, + WPA2_PSK_AUTH = 0x05, + WPA_AUTH_CCKM = 0x06, + WPA2_AUTH_CCKM = 0x07, + } AUTH_MODE; + typedef enum { + NONE_CRYPT = 0x01, + WEP_CRYPT = 0x02, + TKIP_CRYPT = 0x03, + AES_CRYPT = 0x04, + } CRYPTO_TYPE; + typedef enum { + CONNECT_ASSOC_POLICY_USER = 0x0001, + CONNECT_SEND_REASSOC = 0x0002, + CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, + CONNECT_PROFILE_MATCH_DONE = 0x0008, + CONNECT_IGNORE_AAC_BEACON = 0x0010, + } WMI_CONNECT_CTRL_FLAGS_BITS; + + pairwiseCryptoLen and groupCryptoLen are valid when the respective + CryptoTypesis WEP_CRYPT, otherwise this value should be 0. This is the length in + bytes. + +Reset Value + None defined + +Restrictions + None + +===================================================================== + + +Name + CREATE_PSTREAM + +Synopsis + The host uses this command to create a new prioritized data endpoint between the + host and the AR6000 device that carries a prioritized stream of data. If the AP that the + device connects to requires TSPEC stream establishment, the device requests the + corresponding TSPEC with the AP. The maximum and minimum service interval + ranges from 0 – 0x7FFFFFFF (ms), where 0 = disabled. The device does not send a + reply event for this command, as it is always assumed the command has succeeded. + An AP admission control response comes to the host via a WMI_CAC_INDICATION + event, once the response for the ADDTS frame comes. + + Examples of cases where reassociation is generated (when WMM) and cases where + ADDTS is generated (when WMM and enabling ACM) are when: + Changing UAPSD flags in WMM mode, reassociation is generated + Changing the interval of sending auto QoS Null frame in WMM mode; + reassociation is not generated + Issuing a command with same previous parameters in WMM mode and enabling + ACM, an ADDTS request is generated + Changing the interval of a QoS null frame sending in WMM mode and enabling + ACM, an ADDTS request is generated + Issuing the command in disconnected state, reassociation or ADDTS is not + generated but the parameters are available after (re)association + +Command + --createqos + + where: + + + 802.1D user priority range (0–7) + + = 0 Tx (uplink) traffic + = 1 Rx (downlink) traffic + = 2 Bi-directional traffic + + = 1 BK + = 2 VI + = 3 VO + + = 0 Aperiodic + = 1 Periodic + + Specifies whether the voice power save mechanism + (APSD if AP supports it or legacy/simulated APSD + [using PS-Poll]) should be used + = 0 Disable voice power save for traffic class + = 1 Enable APSD voice power save for traffic class + = 2 Enable voice power save for all traffic classes + + (In ms) + + Inactivity interval (in ms) (0 = Infinite) + + (In ms) + + Service start time + + TSID range (0–15) + + Nominal MAC SDU size + + Maximum MAC SDU size + + Minimum data rate (in bps) + + Mean data rate (in bps) + + Peak data rate (in bps) + + Maximum burst size (in bps) + + Delay bound + + Minimum PHY rate (in bps) + + Surplus bandwidth allowance + + Medium time in TU of 32-ms periods per sec + ... CREATE_PSTREAM (continued) + +Command Parameters + UINT8 trafficClass TRAFFIC_CLASS value + UINT8 traffic + Direction + DIR_TYPE value + UINT8 rxQueueNum + AR6000 device mailbox index (2 or 3) + corresponding to the endpoint the host + wishes to use to receive packets for the + prioritized stream + UINT8 trafficType TRAFFIC_TYPE value + UINT8 voicePS +Capability + VOICEPS_CAP_TYPE value + UINT8 tsid Traffic stream ID + UINT8 userPriority 802.1D user priority + UINT16 nominalMSDU Nominal MSDU in octets + UINT16 maxMSDU Maximum MSDU in octets + UINT32 minServiceInt Minimum service interval: the min. + period of traffic specified (in ms) + UINT32 maxServiceInt Maximum service interval: the max. + period of traffic specified (in ms) + UINT32 inactivityInt Indicates how many ms an established + stream is inactive before the prioritized + data endpoint is taken down and the + corresponding T-SPEC deleted + UINT32 suspensionInt Suspension interval (in ms) + UINT32 service StartTime Service start time + UINT32 minDataRate Minimum data rate (in bps) + UINT32 meanDataRate Mean data rate (in bps) + UINT32 peakDataRate Peak data rate (in bps) + UINT32 maxBurstSize + UINT32 delayBound + UINT32 minPhyRate Minimum PHY rate for TSPEC (in bps) + UINT32 sba Surplus bandwidth allowance + UINT32 mediumTime Medium TSPEC time (in units of 32 ms) +Command Values + { + WMM_AC_BE = 0 Best Effort + WMM_AC_BK = 1 Background + WMM_AC_VI = 2 Video + WMM_AC_VO = 3 Voice + All other values reserved + } TRAFFIC_CLASS + { + UPLINK_TRAFFIC = 0 From the AR6000 device to the AP + DOWNLINK_TRAFFIC = 1 From the AP to the AR6000 device + BIDIR_TRAFFIC = 2 Bi-directional traffic + All other values reserved + } DIR_TYPE + { + DISABLE_FOR_THIS_AC = 0 + ENABLE_FOR_THIS_AC = 1 + ENABLE_FOR_ALL_AC = 2 + All other values reserved + } VOICEPS_CAP_TYPE + + ... CREATE_PSTREAM (continued) + + + VI BE BK Supported, Y/N? + 0 0 0 0 Y + 0 0 0 1 Y + 0 0 1 0 N + 0 0 1 1 N + 0 1 0 0 Y + 0 1 0 1 Y + 0 1 1 0 N + 0 1 1 1 N + 1 0 0 0 Y + 1 0 0 1 Y + 1 0 1 0 N + 1 1 0 0 N + 1 1 0 1 Y + 1 1 0 0 N + 1 1 1 0 N + 1 1 1 1 Y + +Reset Value + No pstream is present after reset; each of the BE, BK, VI,VO pstreams must be created + (either implicitly by data flow or explicitly by user) + +Restrictions + This command can only be issued when the device is in the CONNECTED state. If + the device receives the command while in DISCONNECTED state, it replies with a + failure indication. At most four prioritized data endpoints can be created, one for + each AC. + +See Also + “DELETE_PSTREAM” +===================================================================== + +Name + DELETE_BAD_AP + +Synopsis + The host uses this command to clear a particular entry in the bad AP table + +Command + wmiconfig eth1 --rmAP [--num=] // used to clear a badAP + entry. num is index from 0-3 + +Command Parameters + UINT8 badApIndex Index [0...n] that identifies the entry in the bad + AP table to delete + +Command Values + badApIndex = 0, 1, 2, 3 + Entry in the bad AP table + +Reset Value + None defined + +Restrictions + None + +See Also + “ADD_BAD_AP” + +===================================================================== + + +Name + DELETE_CIPHER_KEY + +Synopsis + The host uses this command to delete a key that was previously added with the + “ADD_CIPHER_KEY” command. + +Command + TBD + +Command Parameters + UINT8 keyIndex Index (0...3) of the key to be deleted + +Command Values + keyIndex = 0, 1,2, 3 Key to delete + +Reset Value + None + +Restrictions + The host should not delete a key that is currently in use by the AR6000. + +See Also + “ADD_CIPHER_KEY” + +===================================================================== + +Name + DELETE_PSTREAM + +Synopsis + The host uses this command to delete a prioritized data endpoint created by a + previous “CREATE_PSTREAM” command + +Command + --deleteqos , where: + + + = 0 BE + = 1 BK + = 2 VI + = 3 VO + + The TSpec ID; use the -qosqueue option + to get the active TSpec IDs for each traffic class + +Command Parameters + A_UINT8 trafficClass Indicate the traffic class of the stream + being deleted + +Command Values + { + WMM_AC_BE = 0 Best effort + WMM_AC_BK = 1 Background + WMM_AC_VI = 2 Video + WMM_AC_VO = 3 Voice + } TRAFFIC CLASS + + 0-15 for TSID + +Reply Values + N/A + +Restrictions + This command should only be issued after a “CREATE_PSTREAM” command has + successfully created a prioritized stream + +See Also + “CREATE_PSTREAM” + +===================================================================== + + +Name + DELETE_WOW_PATTERN + +Synopsis + The host uses this command to remove a pre-specified pattern from the + WoW pattern list. + +Command + wmiconfig –delwowpattern + +Command Parameters + A_UINT8 filter_list_id ID of the list that contains the WoW filter + pattern to delete + A_UINT8 filter_id ID of the WoW filter pattern to delete + +Reply Parameters + None + + + +Reset Value + None defined + +Restrictions + None + +See Also + “ADD_WOW_PATTERN” + +===================================================================== + + +Name + EXTENSION + +Synopsis + The WMI message interface is used mostly for wireless control messages to a wireless + module applicable to wireless module management regardless of the target platform + implementation. However, some commands only peripherally related to wireless + management are desired during operation. These wireless extension commands may + be platform-specific or implementation-dependent. + +Command + N/A + +Command Parameters + Command-specific + +Command Values + Command-specific + +Reply Parameters + Command-specific + +Reset Values + None defined + +Restrictions + None defined + +===================================================================== + + +Name + GET_BIT_RATE + +Synopsis + Used by the host to obtain the rate most recently used by the AR6000 device + +Command + wmiconfig eth1 --getfixrates + +Command Parameters + None + + + +Reply Parameters + INT8 + rateIndex + See the “SET_BIT_RATE” command + +Reset Values + None + +Restrictions + This command should only be used during development/debug; it is not intended +for use in production. It is only valid when the device is in the CONNECTED state + +See Also + “SET_BIT_RATE” + +===================================================================== + + +Name + GET_CHANNEL_LIST + +Synopsis + Used by the host uses to retrieve the list of channels that can be used by the device + while in the current wireless mode and in the current regulatory domain. + +Command + TBD + +Command Parameters + None + +Reply Parameters + UINT8 reserved Reserved + UINT8 numberOfChannels Number of channels the reply contains + UINT16 channelList[numberOfChannels] Array of channel frequencies (in MHz) + +Reset Values + None defined + +Restrictions + The maximum number of channels that can be reported are 32 + +===================================================================== + + +Name + GET_FIXRATES + +Synopsis + Clears the current calculated RSSI and SNR value. RSSI and SNR are reported by + running-average value. This command will clear the history and have a fresh start for + the running-average mechanism. + +Synopsis + This returns rate-mask set via WMI_SET_FIXRATES to retrieve the current fixed rate + that the AR6001 or AR6001 is using. See “SET_FIXRATES”. + +Command + wmiconfig eth1 --getfixrates + +Command Parameters + A_UINT16 fixRateMask; Note: if this command is used prior to + using WMI_SET_FIXRATES, AR6000 + returns 0xffff as fixRateMask, indicating + all the rates are enabled + +Reply Parameters + None + +Reset Value + None defined + +Restrictions + None + +See Also + “SET_FIXRATES” + +===================================================================== + + + +Name + GET_PMKID_LIST_CMD + +Synopsis + Retrieves the list of PMKIDs on the firmware. The + WMI_GET_PMKID_LIST_EVENT is generated by the firmware. + +Command + TBD + +Command Parameters + +Reset Values + None + +Restrictions + None + +See Also + SET_PMKID_LIST_CMD GET_PMKID_LIST_EVENT + +===================================================================== + + +Name + GET_ROAM_TBL + +Synopsis + Retrieve the roaming table maintained on the target. The response is reported + asynchronously through the ROAM_TBL_EVENT. + +Command + wmiconfig --getroamtable + +Command Parameters + A_UINT8 roamCtrlType; + A_UINT16 roamMode + A_UINT16 numEntries + WMI_BSS_ROAM_INFO bssRoamInfo[1] + +Reply Value + Reported asynchronously through the ROAM_TBL_EVENT + +Reset Value + None defined + +Restrictions + None + +See Also + SET_KEEPALIVE + +===================================================================== + + +Name + GET_TARGET_STATS + +Synopsis + The host uses this command to request that the target send the statistics that it + maintains. The statistics obtained from the target are accrued in the host every time + the GET_TARGET_STATS command is issued. The --clearStats option is added to + clear the target statistics maintained in the host. + +Command + wmiconfig --getTargetStats --clearStats + +Command Parameters + TARGET_STATS targetStats + WMI_TARGET_STATS + UINT8 clearStats + + +Reply Value + RSSI return value (0–100) + +Reset Values + All statistics are cleared (zeroed) + +Restrictions + The --getTargetStats option must be used; the --clearStats option is also available also + + +===================================================================== + +Name + GET_TX_PWR + +Synopsis + The host uses this command to retrieve the current Tx power level + +Command + wmiconfig -i eth1 --getpower + +Command Parameters + None + +Reply Parameters + UINT16 dbM The current Tx power level specified in dbM + +Reset Values + The maximum permitted by the regulatory domain + +Restrictions + None + +See Also + “SET_TX_PWR” + +===================================================================== + + +Name + GET_WOW_LIST + +Synopsis + The host uses this command to retrieve the current list of WoW patterns. + +Command + wmiconfig –getwowlist + +Command Parameters + A_UINT8 filter_list_id ID of the list of WoW patterns to retrieve + +Reply Value(s) + A_UINT16 num_filters Number of WoW patterns contained in the list + A_UINT8 wow_mode Current mode of WoW (enabled or disabled) + A_UINT8 host_mode Current host mode (asleep or awake) + WOW_FILTER wow_filters[1] + Contents of the WoW filter pattern list + (contains mask, pattern, offset and size + information for each of the patterns) + +Reset Value + None defined + +Restrictions + None + +See Also + “SET_WSC_STATUS” + +===================================================================== + + +Name + LQ_THRESHOLD_PARAMS + +Synopsis + Sets Link Quality thresholds, the sampling will happen at every unicast data frame + Tx if a certain threshold is met, and the corresponding event will be sent to the host. + +Command + --lqThreshold ... + ... + +Command Parameters + = 0 Disable link quality sampling + = 1 Enable link quality sampling + Above thresholds (value in [0,100]), in + ascending order + Below thresholds (value in [0,100]), in + ascending order + +Command Values + See command parameters + +Reset Value + None defined + +Restrictions + None + +===================================================================== + + +Name + OPT_TX_FRAME + +Synopsis + Special feature, sends a special frame. + +Command + wmiconfig --sendframe + + +Command Parameters + { + A_UINT16 optIEDataLen; + A_UINT8 frmType; + A_UINT8 dstAddr[ATH_MAC_LEN]; + A_UINT8 bssid[ATH_MAC_LEN]; + A_UINT8 optIEData[1]; + } WMI_OPT_TX_FRAME_CMD; + +Command Values + = 1 Probe request frame + = 2 Probe response frame + = 3 CPPP start + = 4 CPPP stop + +Reset Value + None defined + +Restrictions + Send a special frame only when special mode is on. + +===================================================================== + + +Name + RECONNECT + +Synopsis + This command requests a reconnection to a BSS to which the AR6000 device was + formerly connected + +Command + TBD + +Command Parameters + UINT16 channel Provides a hint as to which channel was + used for a previous connection + UINT8 bssid[6] If set, indicates which BSSID to connect to + +Command Values + None + +Reset Values + None + +Restrictions + None + +See Also + “CONNECT_CMD” + +===================================================================== + + +Name + RSSI_THRESHOLD_PARAMS + +Synopsis + Configures how the AR6000 device monitors and reports signal strength (RSSI) of the + connected BSS, which is used as a link quality metric. The four RSSI threshold sets (in + dbM) of the host specification divide the signal strength range into six segments. + When signal strength increases or decreases across one of the boundaries, an + RSSI_THRESHOLD event is signaled to the host. The host may then choose to take + action (such as influencing roaming). + +Command + wmiconfig eth1 --rssiThreshold + ... + + ... + + +Command Parameters + UINT8 weight Range in [1, 16] used to calculate average RSSI + UINT32 pollTime RSSI (signal strength) sampling frequency in + seconds (if pollTime = 0, single strength + sampling is disabled) + USER_RSS__THOLD tholds[12] Thresholds (6 x 2) + +Command Values + None defined + +Reset Values + pollTime is 0, and sampling is disabled + +Restrictions + Can only be issued if the AR6000 device is connected + + +===================================================================== + +Name + SCAN_PARAMS + +Synopsis + The minact parameter determines the minimum active channel dwell time, within + which if the STA receives any beacon, it remains on that channel until the maxact + channel dwell time. If the STA does not receive a beacon within the minact dwell + time, it switches to scan the next channel. + +Command + wmiconfig -scan -minact= --maxact= + +Command Parameters + UINT16 maxact Channel dwell time (in ms), default = 0 + UINT16 minact Channel dwell time (in ms), default = 105 + +Command Values + See channel parameters + +Reset Values + None defined + +Restrictions + The minact value should be greater than 0; maxact should be between 5–65535 ms + and greater than minact + +===================================================================== + + +Name + SET_ACCESS_PARAMS + +Synopsis + Allows the host to set access parameters for the wireless network. A thorough + understanding of IEEE 802.11 is required to properly manipulate these parameters. + +Command + wmiconfig eth1 --acparams --txop --cwmin <0-15> + --cwmax <0-15> --aifsn<0-15> + +Command Parameters + UINT16 txop The maximum time (expressed in units of + 32 ms) the device can spend transmitting + after acquiring the right to transmit + UINT8 eCWmin Minimum contention window + UINT8 eCWmax Maximum contention window + UINT8 aifsn The arbitration inter-frame space number + +Command Values + None + +Reset Values + Reasonable defaults that vary, between endpoints (prioritized streams) + +Restrictions + None + +===================================================================== + + +Name + SET_ADHOC_BSSID + +Synopsis + Allows the host to set the BSSID for an ad hoc network. If a network with this BSSID + is not found, the target creates an ad hoc network with this BSSID after the connect + WMI command is triggered (e.g., by the SIOCSIWESSID IOCTL). + +Command + wmiconfig eth1 --adhocbssid + +Command Parameters + A_UINT8 bssid[ATH_MAC_LEN] BSSID is specified in xx:xx:xx:xx:xx:xx format + +Command Values + None + +Reset Values + None + +Restrictions + None + +===================================================================== + + +Name + SET_AKMP_PARAMS + +Synopsis + Enables or disables multi PMKID mode. + +Command + wmiconfig eth1 --setakmp --multipmkid= + +Command Parameters + typedef struct { + A_UINT32 akmpInfo; + } WMI_SET_AKMP_PARAMS_CMD; + +Command Values + akmpInfo; + bit[0] = 0 + MultiPMKID mode is disabled and PMKIDs that + were set using the WMI_SET_PMKID_CMD are + used in the [Re]AssocRequest frame. + bit[0] = 1 + MultiPMKID mode is enabled and PMKIDs issued + by the WMI_SET_PMKID_LIST_CMD are used in + the next [Re]AssocRequest sent to the AP. + +Reset Values + MultiPMKID mode is disabled + +Restrictions + None + +===================================================================== + + +Name + SET_APPIE + +Synopsis + Add an application-specified IE to a management frame. The maximum length is + 76 bytes. Including the length and the element ID, this translates to 78 bytes. + +Command + wmiconfig --setappie , where: + + frame + One of beacon, probe, respon, assoc + + IE + A hex string beginning with DD (if = 0, no + IE is sent in the management frame) + +Command Parameters + mgmtFrmType; + A WMI_MGMT_FRAME_TYPE + + ieLen; + Length of the IE to add to the GMT frame + +Command Values + None + +Reset Value + None defined + +Restrictions + Supported only for the probe request and association request management frame +types. Also, only one IE can be added per management frame type. + +===================================================================== + + +Name + SET_ASSOC_INFO + +Synopsis + The host uses this command to specify any information elements (IEs) it wishes the + AR6000 device to add to all future association and reassociation requests. IEs must be + correct and are used as is by the device. IEs specified through this command are + cleared with a DISCONNECT. + +Command + wmiconfig eth1 --setAssocIe + +Command Parameters + UINT8 ieType Used directly in 802.11 frames + UINT8 bufferSize Size of assocInfo (in bytes) ranging from + 0–240. If = 0, previously set IEs are cleared. + UINT8 assocInfo[bufferSize] Used directly in 802.11 frames + +Command Values + None + +Reset Values + IEs are cleared + +Restrictions + This command can only be issued in the DISCONNECTED state + +===================================================================== + + +Name + SET_AUTHMODE + +Synopsis + Sets the 802.11 authentication mode of reconnection + +Command + wmiconfig eth1 --setauthmode + +Command Parameters + UINT8 mode + +Command Values + mode = 0x00 Proceed with authentication during reconnect + = 0x01 Do not proceed with authentication during reconnect + +Reset Values + Authentication + +Restrictions + None + +===================================================================== + + +Name + SET_BEACON_INT + +Synopsis + Sets the beacon interval for an ad hoc network. Beacon interval selection may have an + impact on power savings. To some degree, a longer interval reduces power + consumption but also decreases throughput. A thorough understanding of IEEE + 802.11 ad hoc networks is required to use this command effectively. + +Command + wmiconfig eth1 --ibssconintv + +Command Parameters + UINT16 beaconInterval Specifies the beacon interval in TU units (1024 ms) + +Command Values + None + +Reset Values + The default beacon interval is 100 TUs (102.4 ms) + +Restrictions + This command can only be issued before the AR6000 device starts an ad hoc network + +See Also + “SET_IBSS_PM_CAPS” + +===================================================================== + + +Name + SET_BIT_RATE + +Synopsis + The host uses this command to set the AR6000 device to a specific fixed rate. + +Command + wmiconfig eth1 --setfixrates ... + +Command Parameters + INT8 rateIndex + A WMI_BIT_RATE value + { + RATE_AUTO = -1 + RATE_1Mb = 0 + RATE_2Mb = 1 + RATE_5_5M = 2 + RATE_11Mb = 3 + RATE_6Mb = 4 + RATE_9Mb = 5 + RATE_12Mb = 6 + RATE_18Mb = 7 + RATE_24Mb = 8 + RATE_36Mb = 9 + RATE_48Mb = 10 + RATE_54Mb = 11 + } WMI_BIT_RATE + + +Command Values + See command parameters + +Reset Values + The dynamic rate is determined by the AR6000 device + +Restrictions + This command is intended for use only during development/debug; it is not +intended for use in production + +See Also + “GET_BIT_RATE” + +===================================================================== + + +Name + SET_BMISS_TIME + +Synopsis + This command sets the beacon miss (BMISS) time, which the AR6000 hardware use + to recognize missed beacons. When an excessive number (15) of consecutive beacons + are missed, the AR6000 consider switching to a different BSS. The time can be + specified in number of beacons or in TUs. + +Command(s) + wmiconfig eth1 --setbmissbeacons= + wmiconfig eth1 --setbmisstime= + +Command Parameters + UINT16 bmissTime Specifies the beacon miss time + [1000...5000] in TUs (1024 ms) + UINT16 bmissbeacons Specifies the number of beacons [5...50] + +Command Values + None + +Reset Values + bmissTime is 1500 TUs (1536 ms) + +Restrictions + None + +===================================================================== + + +Name + SET_BSS_FILTER + +Synopsis + The host uses this to inform the AR6000 device of the types of networks about which + it wants to receive information from the “BSSINFO” event. As the device performs + either foreground or background scans, it applies the filter and sends “BSSINFO” + events only for the networks that pass the filter. If any of the bssFilter or the ieMask + filter matches, a BSS Info is sent to the host. The ieMask currently is used as a match + for the IEs in the beacons, probe reponses and channel switch action management + frame. See also “Scan and Roam” on page C-1. + + The BSS filter command has been enhanced to support IE based filtering. The IEs can + be specified as a bitmask through this command using this enum. + +Command + wmiconfig eth1 –filter = --ieMask 0x + +Command Parameters + UINT8 BssFilter + + Command Values + typedef struct { + A_UINT8 bssFilter; See WMI_BSS_FILTER + A_UINT32 ieMask; + } __ATTRIB_PACK WMI_BSS_FILTER_CMD; + + The ieMask can take this combination of values: + + enum { + BSS_ELEMID_CHANSWITCH = 0x01 + BSS_ELEMID_ATHEROS = 0x02, + } + +Reply Value + None + +Reset Value + BssFilter = NONE_BSS_FILTER (0) + +Restrictions + None + +See Also + “CONNECT_CMD” + +===================================================================== + + +Name + SET_BT_PARAMS + +Synopsis + This command is used to set the status of a Bluetooth stream or set Bluetooth + coexistence register parameters. The stream may be an SCO or an A2DP stream and + its status can be started/stopped/suspended/resumed. + +Command + wmiconfig –setBTparams + +Command Parameters + struct { + union { + BT_PARAMS_SCO scoParams; + BT_PARAMS_A2DP a2dpParams; + BT_PARAMS_MISC miscParams; + BT_COEX_REGS regs; + } info; + A_UINT8 paramType; + struct { + A_UINT8 noSCOPkts; Number of SCO packets between consecutive PS-POLLs + A_UINT8 pspollTimeout; + A_UINT8 stompbt; + } BT_PARAMS_SCO; + struct { + A2DP BT stream parameters + A_UINT32 period; + A_UINT32 dutycycle; + A_UINT8 stompbt; + } BT_PARAMS_A2DP; + struct { + union { + WLAN_PROTECT_POLICY_TYPE protectParams; + A_UINT16 wlanCtrlFlags; + }info; + A_UINT8 paramType; + } BT_PARAMS_MISC; + struct { + BT coexistence registers values + A_UINT32 mode; Coexistence mode + A_UINT32 scoWghts; WLAN and BT weights + A_UINT32 a2dpWghts; + A_UINT32 genWghts; + A_UINT32 mode2; Coexistence mode2 + A_UINT8 setVal; + } BT_COEX_REGS; + +Command Values + None defined + +Reset Value + None + +Restrictions + None + +===================================================================== + + +Name + SET_BT_STATUS + +Synopsis + Sets the status of a Bluetooth stream. The stream may be a SCO or an A2DP stream + and its status can be started/stopped/suspended/resumed. + +Command + wmiconfig –setBTstatus + +Command Parameters + { + A_UINT8 streamType; Stream type + A_UINT8 status; Stream status + }WMI_SET_BT_STATUS_CMD; + +Command Values + { + BT_STREAM_UNDEF = 0 + BT_STREAM_SCO + SCO stream + BT_STREAM_A2DP + A2DP stream + BT_STREAM_MAX + } BT_STREAM_TYPE; + + { + BT_STATUS_UNDEF = 0 + BT_STATUS_START + BT_STATUS_STOP + BT_STATUS_RESUME + BT_STATUS_SUSPEND + BT_STATUS_MAX + } BT_STREAM_STATUS; + +Reset Value + None defined + +Restrictions + None + +===================================================================== + + +Name + SET_CHANNEL_PARAMETERS + +Synopsis + Configures various WLAN parameters related to channels, sets the wireless mode, + and can restrict the AR6000 device to a subset of available channels. The list of + available channels varies depending on the wireless mode and the regulatory + domain. The device never operates on a channel outside of its regulatory domain. The + device starts to scan the list of channels right after this command. + +Command + wmiconfig eth1 --wmode + +Command Parameters + UINT8 phyMode See Values below. + UINT8 numberOfChannels + Number of channels in the channel array that + follows. If = 0, then the device uses all of the + channels permitted by the regulatory domain + and by the specified phyMode. + UINT16 channel[numberOfChannels] + Array listing the subset of channels (expressed + as frequencies in MHz) the host wants the + device to use. Any channel not permitted by + the specified phyMode or by the specified + regulatory domain is ignored by the device. + +Command Values + phyMode = { + Wireless mode + 11a = 0x01 + 11g = 0x02 + 11ag = 0x03 + 11b = 0x04 + 11g only = 0x05 + } + +Reset Values + phyMode + 11ag + 802.11a/g modules + 11g + 802.11g module + channels + Defaults to all channels permitted by the + current regulatory domain. + +Restrictions + This command, if issued, should be issued soon after reset and prior to the first + connection. This command should only be issued in the DISCONNECTED state. + +===================================================================== + + +Name + SET_DISC_TIMEOUT + +Synopsis + The host uses this command to configure the amount of time that the AR6000 should + spend when it attempts to reestablish a connection after losing link with its current + BSS. If this time limit is exceeded, the AR6000 send a “DISCONNECT” event. After + sending the “DISCONNECT” event the AR6000 continues to attempt to reestablish a + connection, but they do so at the interval corresponding to a foreground scan as + established by the “SET_SCAN_PARAMS” command. + + A timeout value of 0 indicates that the AR6000 will disable all autonomous roaming, + so that the AR6000 will not perform any scans after sending a “DISCONNECT” + event to the host. The state is maintained until a shutdown or host sets different + timeout value from 0. + +Command + wmiconfig eth1 --disc= + +Command Parameters + UINT8 disconnectTimeout + Specifies the time limit (in seconds) after + which a failure to reestablish a connection + results in a “DISCONNECT” event + +Command Values + None + +Reset Values + disconnectTimeout is 10 seconds + +Restrictions + This command can only be issued while in a DISCONNECTED state + +===================================================================== + + +Name + SET_FIXRATES + +Synopsis + By default, the AR6000 device uses all PHY rates based on mode of operation. If the + host application requires the device to use subset of supported rates, it can set those + rates with this command. In 802.11g mode, the AR6000 device takes the entire + 802.11g basic rate set and the rates specified with this command and uses it as the + supported rate set. + + This rate set is advertised in the probe request and the assoc/re-assoc request as + supported rates. Upon successful association, the device modifies the rate set pool + using the: intersection of AP-supported rates with the union of the 802.11g basic rate + set and rates set using this command. The device picks transmission rates from this + pool based on a rate control algorithm. + +Command + TBD + +Command Parameters + A_UINT16 fixRateMask; + The individual bit is an index for rate table, + and setting the that index to 1 would set that + corresponding rate. E.g., fixRateMask = 9 + (1001) sets 1 Mbps and 11 Mbps. + +Command Values + None + +Reset Value + None defined + +Restrictions + None + +See Also + “GET_FIXRATES” + +===================================================================== + + +Name + SET_WHAL_PARAM + +Synopsis + An internal AR6000 command that is used to set certain hardware parameters. The + description of this command is in $WORKAREA/include/halapi.h. + +Command + TBD + +Command Parameters + ATH_HAL_SETCABTO_CMDID + Sets the timeout waiting for the multicast + traffic after a DTIM beacon (in TUs). + +Command Values + None + +Reset Value + Default = 10 TUs + +Restrictions + This command should be executed before issuing a connect command. + +===================================================================== + + +Name + SET_HOST_SLEEP_MODE + +Synopsis + The host uses this command to set the host mode to asleep or awake. All packets are + delivered to the host when the host mode is awake. When host mode is asleep, only if + WoW is enabled and the incoming packet matches one of the specified WoW + patterns, will the packet be delivered to the host. The host will also be woken up by + the target for pattern-matching packets and important events. + +Command + wmiconfig –sethostmode= + +Command Parameters + A_BOOL awake Set the host mode to awake + A_BOOL asleep Set the host mode to asleep + +Command Values + 1 = awake, 0 = asleep + +Reset Value + None defined (default host mode is awake) + +Restrictions + None + + +===================================================================== + +Name + SET_IBSS_PM_CAPS + +Synopsis + Used to support a non-standard power management scheme for an ad hoc wireless + network consisting of up to eight stations (STAs) that support this form of power + saving (e.g., Atheros-based STAs). A thorough understanding of IEEE 802.11 ad hoc + networks is required to use this command effectively. + +Command + wmiconfig eth1 --ibsspmcaps --ps= + --aw= + --ttl=