| //------------------------------------------------------------------------------ |
| // Copyright (c) 2004-2010 Atheros Corporation. All rights reserved. |
| // |
| // |
| // Permission to use, copy, modify, and/or distribute this software for any |
| // purpose with or without fee is hereby granted, provided that the above |
| // copyright notice and this permission notice appear in all copies. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| // |
| // |
| //------------------------------------------------------------------------------ |
| //============================================================================== |
| // This module implements the hardware independent layer of the |
| // Wireless Module Interface (WMI) protocol. |
| // |
| // Author(s): ="Atheros" |
| //============================================================================== |
| |
| #include <a_config.h> |
| #include <athdefs.h> |
| #include <a_types.h> |
| #include <a_osapi.h> |
| #include "htc.h" |
| #include "htc_api.h" |
| #include "wmi.h" |
| #include <wlan_api.h> |
| #include <wmi_api.h> |
| #include <ieee80211.h> |
| #include <ieee80211_node.h> |
| #include "dset_api.h" |
| #include "gpio_api.h" |
| #include "wmi_host.h" |
| #include "a_drv.h" |
| #include "a_drv_api.h" |
| #define ATH_MODULE_NAME wmi |
| #include "a_debug.h" |
| #include "dbglog_api.h" |
| #include "roaming.h" |
| |
| #define ATH_DEBUG_WMI ATH_DEBUG_MAKE_MODULE_MASK(0) |
| |
| #ifdef ATH_DEBUG_MODULE |
| |
| static ATH_DEBUG_MASK_DESCRIPTION wmi_debug_desc[] = { |
| { ATH_DEBUG_WMI , "General WMI Tracing"}, |
| }; |
| |
| ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi, |
| "wmi", |
| "Wireless Module Interface", |
| ATH_DEBUG_MASK_DEFAULTS, |
| ATH_DEBUG_DESCRIPTION_COUNT(wmi_debug_desc), |
| wmi_debug_desc); |
| |
| #endif |
| |
| #ifndef REXOS |
| #define DBGARG _A_FUNCNAME_ |
| #define DBGFMT "%s() : " |
| #define DBG_WMI ATH_DEBUG_WMI |
| #define DBG_ERROR ATH_DEBUG_ERR |
| #define DBG_WMI2 ATH_DEBUG_WMI |
| #define A_DPRINTF AR_DEBUG_PRINTF |
| #endif |
| |
| 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_channel_change_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); |
| |
| static A_STATUS |
| wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len); |
| |
| static A_STATUS |
| wmi_acm_reject_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_INT32 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); |
| |
| A_STATUS wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, |
| WMI_SYNC_FLAG syncflag); |
| |
| A_UINT8 ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, A_UINT32 size); |
| A_UINT8 ar6000_get_lower_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, A_UINT32 size); |
| |
| void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); |
| void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); |
| static A_STATUS wmi_send_rssi_threshold_params(struct wmi_t *wmip, |
| WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); |
| static A_STATUS wmi_send_snr_threshold_params(struct wmi_t *wmip, |
| WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); |
| #if defined(CONFIG_TARGET_PROFILE_SUPPORT) |
| static A_STATUS |
| wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); |
| #endif /* CONFIG_TARGET_PROFILE_SUPPORT */ |
| |
| static A_STATUS wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap, |
| int len); |
| static A_STATUS wmi_dtimexpiry_event_rx(struct wmi_t *wmip, A_UINT8 *datap, |
| int len); |
| |
| static A_STATUS wmi_peer_node_event_rx (struct wmi_t *wmip, A_UINT8 *datap, |
| int len); |
| #ifdef ATH_AR6K_11N_SUPPORT |
| static A_STATUS wmi_addba_req_event_rx(struct wmi_t *, A_UINT8 *, int); |
| static A_STATUS wmi_addba_resp_event_rx(struct wmi_t *, A_UINT8 *, int); |
| static A_STATUS wmi_delba_req_event_rx(struct wmi_t *, A_UINT8 *, int); |
| static A_STATUS wmi_btcoex_config_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); |
| static A_STATUS wmi_btcoex_stats_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); |
| #endif |
| static A_STATUS wmi_hci_event_rx(struct wmi_t *, A_UINT8 *, int); |
| |
| #ifdef WAPI_ENABLE |
| static A_STATUS wmi_wapi_rekey_event_rx(struct wmi_t *wmip, A_UINT8 *datap, |
| int len); |
| #endif |
| |
| #if defined(UNDER_CE) |
| #if defined(NDIS51_MINIPORT) |
| unsigned int processDot11Hdr = 0; |
| #else |
| unsigned int processDot11Hdr = 1; |
| #endif |
| #else |
| extern unsigned int processDot11Hdr; |
| #endif |
| |
| int wps_enable; |
| static const A_INT32 wmi_rateTable[][2] = { |
| //{W/O SGI, with SGI} |
| {1000, 1000}, |
| {2000, 2000}, |
| {5500, 5500}, |
| {11000, 11000}, |
| {6000, 6000}, |
| {9000, 9000}, |
| {12000, 12000}, |
| {18000, 18000}, |
| {24000, 24000}, |
| {36000, 36000}, |
| {48000, 48000}, |
| {54000, 54000}, |
| {6500, 7200}, |
| {13000, 14400}, |
| {19500, 21700}, |
| {26000, 28900}, |
| {39000, 43300}, |
| {52000, 57800}, |
| {58500, 65000}, |
| {65000, 72200}, |
| {13500, 15000}, |
| {27000, 30000}, |
| {40500, 45000}, |
| {54000, 60000}, |
| {81000, 90000}, |
| {108000, 120000}, |
| {121500, 135000}, |
| {135000, 150000}, |
| {0, 0}}; |
| |
| #define MODE_A_SUPPORT_RATE_START ((A_INT32) 4) |
| #define MODE_A_SUPPORT_RATE_STOP ((A_INT32) 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 ((A_INT32) 0) |
| #define MODE_B_SUPPORT_RATE_STOP ((A_INT32) 3) |
| |
| #define MODE_G_SUPPORT_RATE_START ((A_INT32) 0) |
| #define MODE_G_SUPPORT_RATE_STOP ((A_INT32) 11) |
| |
| #define MODE_GHT20_SUPPORT_RATE_START ((A_INT32) 0) |
| #define MODE_GHT20_SUPPORT_RATE_STOP ((A_INT32) 19) |
| |
| #define MAX_NUMBER_OF_SUPPORT_RATES (MODE_GHT20_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, |
| }; |
| |
| #include "athstartpack.h" |
| |
| /* This stuff is used when we want a simple layer-3 visibility */ |
| typedef PREPACK struct _iphdr { |
| A_UINT8 ip_ver_hdrlen; /* version and hdr length */ |
| A_UINT8 ip_tos; /* type of service */ |
| A_UINT16 ip_len; /* total length */ |
| A_UINT16 ip_id; /* identification */ |
| A_INT16 ip_off; /* fragment offset field */ |
| #define IP_DF 0x4000 /* dont fragment flag */ |
| #define IP_MF 0x2000 /* more fragments flag */ |
| #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ |
| A_UINT8 ip_ttl; /* time to live */ |
| A_UINT8 ip_p; /* protocol */ |
| A_UINT16 ip_sum; /* checksum */ |
| A_UINT8 ip_src[4]; /* source and dest address */ |
| A_UINT8 ip_dst[4]; |
| } POSTPACK iphdr; |
| |
| #include "athendpack.h" |
| |
| static A_INT16 rssi_event_value = 0; |
| static A_INT16 snr_event_value = 0; |
| |
| A_BOOL is_probe_ssid = FALSE; |
| |
| void * |
| wmi_init(void *devt) |
| { |
| struct wmi_t *wmip; |
| |
| A_REGISTER_MODULE_DEBUG_INFO(wmi); |
| |
| wmip = A_MALLOC (sizeof(struct wmi_t)); |
| if (wmip == NULL) { |
| return (NULL); |
| } |
| A_MEMZERO(wmip, sizeof(struct wmi_t )); |
| #ifdef THREAD_X |
| INIT_WMI_LOCK(wmip); |
| #else |
| A_MUTEX_INIT(&wmip->wmi_lock); |
| #endif |
| 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; |
| |
| wmip->wmi_pair_crypto_type = NONE_CRYPT; |
| wmip->wmi_grp_crypto_type = NONE_CRYPT; |
| |
| wmip->wmi_ht_allowed[A_BAND_24GHZ] = 1; |
| wmip->wmi_ht_allowed[A_BAND_5GHZ] = 1; |
| |
| 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; |
| } |
| |
| UNLOCK_WMI(wmip); |
| |
| A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1); |
| } |
| |
| void |
| wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid) |
| { |
| A_ASSERT( eid != ENDPOINT_UNUSED); |
| wmip->wmi_endpoint_id = eid; |
| } |
| |
| HTC_ENDPOINT_ID |
| wmi_get_control_ep(struct wmi_t * wmip) |
| { |
| return(wmip->wmi_endpoint_id); |
| } |
| |
| 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)) { |
| #ifdef THREAD_X |
| DELETE_WMI_LOCK(&wmip); |
| #else |
| A_MUTEX_DELETE(&wmip->wmi_lock); |
| #endif |
| } |
| 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); |
| } |
| |
| A_STATUS wmi_meta_add(struct wmi_t *wmip, void *osbuf, A_UINT8 *pVersion,void *pTxMetaS) |
| { |
| switch(*pVersion){ |
| case 0: |
| return (A_OK); |
| case WMI_META_VERSION_1: |
| { |
| WMI_TX_META_V1 *pV1= NULL; |
| A_ASSERT(osbuf != NULL); |
| if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != A_OK) { |
| return A_NO_MEMORY; |
| } |
| |
| pV1 = (WMI_TX_META_V1 *)A_NETBUF_DATA(osbuf); |
| /* the pktID is used in conjunction with txComplete messages |
| * allowing the target to notify which tx requests have been |
| * completed and how. */ |
| pV1->pktID = 0; |
| /* the ratePolicyID allows the host to specify which rate policy |
| * to use for transmitting this packet. 0 means use default behavior. */ |
| pV1->ratePolicyID = 0; |
| A_ASSERT(pVersion != NULL); |
| /* the version must be used to populate the meta field of the WMI_DATA_HDR */ |
| *pVersion = WMI_META_VERSION_1; |
| return (A_OK); |
| } |
| #ifdef CONFIG_CHECKSUM_OFFLOAD |
| case WMI_META_VERSION_2: |
| { |
| WMI_TX_META_V2 *pV2 ; |
| A_ASSERT(osbuf != NULL); |
| if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != A_OK) { |
| return A_NO_MEMORY; |
| } |
| pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf); |
| A_MEMCPY(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2)); |
| return (A_OK); |
| } |
| #endif |
| default: |
| return (A_OK); |
| } |
| } |
| |
| /* Adds a WMI data header */ |
| A_STATUS |
| wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_BOOL bMoreData, |
| WMI_DATA_HDR_DATA_TYPE data_type,A_UINT8 metaVersion, void *pTxMetaS) |
| { |
| WMI_DATA_HDR *dtHdr; |
| // A_UINT8 metaVersion = 0; |
| A_STATUS status; |
| |
| A_ASSERT(osbuf != NULL); |
| |
| /* adds the meta data field after the wmi data hdr. If metaVersion |
| * is returns 0 then no meta field was added. */ |
| if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != A_OK) { |
| return status; |
| } |
| |
| if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) { |
| return A_NO_MEMORY; |
| } |
| |
| dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); |
| A_MEMZERO(dtHdr, sizeof(WMI_DATA_HDR)); |
| |
| WMI_DATA_HDR_SET_MSG_TYPE(dtHdr, msgType); |
| WMI_DATA_HDR_SET_DATA_TYPE(dtHdr, data_type); |
| |
| if (bMoreData) { |
| WMI_DATA_HDR_SET_MORE_BIT(dtHdr); |
| } |
| |
| WMI_DATA_HDR_SET_META(dtHdr, metaVersion); |
| //dtHdr->rssi = 0; |
| |
| return (A_OK); |
| } |
| |
| |
| A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 layer2Priority, A_BOOL wmmEnabled) |
| { |
| A_UINT8 *datap; |
| A_UINT8 trafficClass = WMM_AC_BE; |
| A_UINT16 ipType = IP_ETHERTYPE; |
| WMI_DATA_HDR *dtHdr; |
| A_BOOL streamExists = FALSE; |
| A_UINT8 userPriority; |
| A_UINT32 hdrsize, metasize; |
| ATH_LLC_SNAP_HDR *llcHdr; |
| |
| WMI_CREATE_PSTREAM_CMD cmd; |
| |
| A_ASSERT(osbuf != NULL); |
| |
| // |
| // Initialize header size |
| // |
| hdrsize = 0; |
| |
| datap = A_NETBUF_DATA(osbuf); |
| dtHdr = (WMI_DATA_HDR *)datap; |
| metasize = (WMI_DATA_HDR_GET_META(dtHdr))? WMI_MAX_TX_META_SZ : 0; |
| |
| if (!wmmEnabled) |
| { |
| /* If WMM is disabled all traffic goes as BE traffic */ |
| userPriority = 0; |
| } |
| else |
| { |
| if (processDot11Hdr) |
| { |
| hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32)); |
| llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + |
| hdrsize); |
| |
| |
| } |
| else |
| { |
| llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize + |
| sizeof(ATH_MAC_HDR)); |
| } |
| |
| if (llcHdr->etherType == A_CPU2BE16(ipType)) |
| { |
| /* Extract the endpoint info from the TOS field in the IP header */ |
| |
| userPriority = wmi_determine_userPriority (((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority); |
| } |
| else |
| { |
| userPriority = layer2Priority & 0x7; |
| } |
| } |
| |
| |
| /* workaround for WMM S5 */ |
| if ((WMM_AC_VI == wmip->wmi_traffic_class) && ((5 == userPriority) || (4 == userPriority))) |
| { |
| userPriority = 1; |
| } |
| |
| trafficClass = convert_userPriority_to_trafficClass(userPriority); |
| |
| WMI_DATA_HDR_SET_UP(dtHdr, userPriority); |
| /* lower 3-bits are 802.1d priority */ |
| //dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; |
| |
| 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; |
| } |
| |
| A_STATUS |
| wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode) |
| { |
| A_UINT8 *datap; |
| A_UINT16 typeorlen; |
| ATH_MAC_HDR macHdr; |
| ATH_LLC_SNAP_HDR *llcHdr; |
| struct ieee80211_frame *wh; |
| A_UINT32 hdrsize; |
| |
| A_ASSERT(osbuf != NULL); |
| |
| if (A_NETBUF_HEADROOM(osbuf) < |
| (sizeof(struct ieee80211_qosframe) + 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)); |
| goto AddDot11Hdr; |
| } |
| |
| /* |
| * 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)); |
| |
| // Remove the Ethernet hdr |
| A_NETBUF_PULL(osbuf, sizeof(ATH_MAC_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); |
| |
| llcHdr = (ATH_LLC_SNAP_HDR *)(datap); |
| llcHdr->dsap = 0xAA; |
| llcHdr->ssap = 0xAA; |
| llcHdr->cntl = 0x03; |
| llcHdr->orgCode[0] = 0x0; |
| llcHdr->orgCode[1] = 0x0; |
| llcHdr->orgCode[2] = 0x0; |
| llcHdr->etherType = typeorlen; |
| |
| AddDot11Hdr: |
| /* Make room for 802.11 hdr */ |
| if (wmip->wmi_is_wmm_enabled) |
| { |
| hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32)); |
| if (A_NETBUF_PUSH(osbuf, hdrsize) != A_OK) |
| { |
| return A_NO_MEMORY; |
| } |
| wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); |
| wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_QOS; |
| } |
| else |
| { |
| hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(A_UINT32)); |
| if (A_NETBUF_PUSH(osbuf, hdrsize) != A_OK) |
| { |
| return A_NO_MEMORY; |
| } |
| wh = (struct ieee80211_frame *) A_NETBUF_DATA(osbuf); |
| wh->i_fc[0] = IEEE80211_FC0_SUBTYPE_DATA; |
| } |
| /* Setup the SA & DA */ |
| IEEE80211_ADDR_COPY(wh->i_addr2, macHdr.srcMac); |
| |
| if (mode == INFRA_NETWORK) { |
| IEEE80211_ADDR_COPY(wh->i_addr3, macHdr.dstMac); |
| } |
| else if (mode == ADHOC_NETWORK) { |
| IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac); |
| } |
| |
| return (A_OK); |
| } |
| |
| A_STATUS |
| wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf) |
| { |
| A_UINT8 *datap; |
| struct ieee80211_frame *pwh,wh; |
| A_UINT8 type,subtype; |
| ATH_LLC_SNAP_HDR *llcHdr; |
| ATH_MAC_HDR macHdr; |
| A_UINT32 hdrsize; |
| |
| A_ASSERT(osbuf != NULL); |
| datap = A_NETBUF_DATA(osbuf); |
| |
| pwh = (struct ieee80211_frame *)datap; |
| type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; |
| subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; |
| |
| A_MEMCPY((A_UINT8 *)&wh, datap, sizeof(struct ieee80211_frame)); |
| |
| /* strip off the 802.11 hdr*/ |
| if (subtype == IEEE80211_FC0_SUBTYPE_QOS) { |
| hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32)); |
| A_NETBUF_PULL(osbuf, hdrsize); |
| } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) { |
| A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame)); |
| } |
| |
| datap = A_NETBUF_DATA(osbuf); |
| llcHdr = (ATH_LLC_SNAP_HDR *)(datap); |
| |
| macHdr.typeOrLen = llcHdr->etherType; |
| A_MEMZERO(macHdr.dstMac, sizeof(macHdr.dstMac)); |
| A_MEMZERO(macHdr.srcMac, sizeof(macHdr.srcMac)); |
| |
| switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { |
| case IEEE80211_FC1_DIR_NODS: |
| IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); |
| IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); |
| break; |
| case IEEE80211_FC1_DIR_TODS: |
| IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr3); |
| IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr2); |
| break; |
| case IEEE80211_FC1_DIR_FROMDS: |
| IEEE80211_ADDR_COPY(macHdr.dstMac, wh.i_addr1); |
| IEEE80211_ADDR_COPY(macHdr.srcMac, wh.i_addr3); |
| break; |
| case IEEE80211_FC1_DIR_DSTODS: |
| break; |
| } |
| |
| // Remove the LLC Hdr. |
| A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)); |
| |
| // Insert the ATH MAC hdr. |
| |
| A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR)); |
| datap = A_NETBUF_DATA(osbuf); |
| |
| A_MEMCPY (datap, &macHdr, sizeof(ATH_MAC_HDR)); |
| |
| return A_OK; |
| } |
| |
| /* |
| * performs 802.3 to DIX encapsulation for received packets. |
| * Assumes the entire 802.3 header is contigous. |
| */ |
| A_STATUS |
| wmi_dot3_2_dix(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++; |
| 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++; |
| 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; |
| #if defined(CONFIG_TARGET_PROFILE_SUPPORT) |
| case (WMIX_PROF_COUNT_EVENTID): |
| wmi_prof_count_rx(wmip, datap, len); |
| break; |
| #endif /* CONFIG_TARGET_PROFILE_SUPPORT */ |
| 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_NETBUF_FREE(osbuf); |
| A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); |
| wmip->wmi_stats.cmd_len_err++; |
| 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_NETBUF_FREE(osbuf); |
| A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); |
| wmip->wmi_stats.cmd_len_err++; |
| return A_ERROR; |
| } |
| |
| datap = A_NETBUF_DATA(osbuf); |
| len = A_NETBUF_LEN(osbuf); |
| |
| loggingReq = 0; |
| |
| 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_GENERIC_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_PEER_NODE_EVENTID): |
| A_DPRINTF (DBG_WMI, (DBGFMT "WMI_PEER_NODE_EVENTID\n", DBGARG)); |
| status = wmi_peer_node_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)); |
| { |
| /* |
| * convert WMI_BSS_INFO_HDR2 to WMI_BSS_INFO_HDR |
| * Take a local copy of the WMI_BSS_INFO_HDR2 from the wmi buffer |
| * and reconstruct the WMI_BSS_INFO_HDR in its place |
| */ |
| WMI_BSS_INFO_HDR2 bih2; |
| WMI_BSS_INFO_HDR *bih; |
| A_MEMCPY(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2)); |
| |
| A_NETBUF_PUSH(osbuf, 4); |
| datap = A_NETBUF_DATA(osbuf); |
| len = A_NETBUF_LEN(osbuf); |
| bih = (WMI_BSS_INFO_HDR *)datap; |
| |
| bih->channel = bih2.channel; |
| bih->frameType = bih2.frameType; |
| bih->snr = bih2.snr; |
| bih->rssi = bih2.snr - 95; |
| bih->ieMask = bih2.ieMask; |
| A_MEMCPY(bih->bssid, bih2.bssid, ATH_MAC_LEN); |
| |
| status = wmi_bssInfo_event_rx(wmip, datap, len); |
| A_WMI_SEND_GENERIC_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_CHANNEL_CHANGE_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CHANNEL_CHANGE_EVENTID\n", DBGARG)); |
| status = wmi_channel_change_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); |
| 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; |
| case (WMI_PSPOLL_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSPOLL_EVENT\n", DBGARG)); |
| status = wmi_pspoll_event_rx(wmip, datap, len); |
| break; |
| case (WMI_DTIMEXPIRY_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DTIMEXPIRY_EVENT\n", DBGARG)); |
| status = wmi_dtimexpiry_event_rx(wmip, datap, len); |
| break; |
| case (WMI_SET_PARAMS_REPLY_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG)); |
| status = wmi_set_params_event_rx(wmip, datap, len); |
| break; |
| case (WMI_ACM_REJECT_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SET_PARAMS_REPLY Event\n", DBGARG)); |
| status = wmi_acm_reject_event_rx(wmip, datap, len); |
| break; |
| #ifdef ATH_AR6K_11N_SUPPORT |
| case (WMI_ADDBA_REQ_EVENTID): |
| status = wmi_addba_req_event_rx(wmip, datap, len); |
| break; |
| case (WMI_ADDBA_RESP_EVENTID): |
| status = wmi_addba_resp_event_rx(wmip, datap, len); |
| break; |
| case (WMI_DELBA_REQ_EVENTID): |
| status = wmi_delba_req_event_rx(wmip, datap, len); |
| break; |
| case (WMI_REPORT_BTCOEX_CONFIG_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_CONFIG_EVENTID", DBGARG)); |
| status = wmi_btcoex_config_event_rx(wmip, datap, len); |
| break; |
| case (WMI_REPORT_BTCOEX_STATS_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BTCOEX_STATS_EVENTID", DBGARG)); |
| status = wmi_btcoex_stats_event_rx(wmip, datap, len); |
| break; |
| #endif |
| case (WMI_TX_COMPLETE_EVENTID): |
| { |
| int index; |
| TX_COMPLETE_MSG_V1 *pV1; |
| WMI_TX_COMPLETE_EVENT *pEv = (WMI_TX_COMPLETE_EVENT *)datap; |
| A_PRINTF("comp: %d %d %d\n", pEv->numMessages, pEv->msgLen, pEv->msgType); |
| |
| for(index = 0 ; index < pEv->numMessages ; index++) { |
| pV1 = (TX_COMPLETE_MSG_V1 *)(datap + sizeof(WMI_TX_COMPLETE_EVENT) + index*sizeof(TX_COMPLETE_MSG_V1)); |
| A_PRINTF("msg: %d %d %d %d\n", pV1->status, pV1->pktID, pV1->rateIdx, pV1->ackFailures); |
| } |
| } |
| break; |
| case (WMI_HCI_EVENT_EVENTID): |
| status = wmi_hci_event_rx(wmip, datap, len); |
| break; |
| #ifdef WAPI_ENABLE |
| case (WMI_WAPI_REKEY_EVENTID): |
| A_DPRINTF(DBG_WMI, (DBGFMT "WMI_WAPI_REKEY_EVENTID", DBGARG)); |
| status = wmi_wapi_rekey_event_rx(wmip, datap, len); |
| break; |
| #endif |
| 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; |
| } |
| |
| /* Send a "simple" wmi command -- one with no arguments */ |
| static A_STATUS |
| wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid) |
| { |
| void *osbuf; |
| |
| osbuf = A_NETBUF_ALLOC(0); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| return (wmi_cmd_send(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* Send a "simple" extended wmi command -- one with no arguments. |
| Enabling this command only if GPIO or profiling support is enabled. |
| This is to suppress warnings on some platforms */ |
| #if defined(CONFIG_HOST_GPIO_SUPPORT) || defined(CONFIG_TARGET_PROFILE_SUPPORT) |
| static A_STATUS |
| wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid) |
| { |
| void *osbuf; |
| |
| osbuf = A_NETBUF_ALLOC(0); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| return (wmi_cmd_send_xtnd(wmip, osbuf, cmdid, NO_SYNC_WMIFLAG)); |
| } |
| #endif |
| |
| 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, |
| ev->sw_version, ev->abi_version); |
| |
| return A_OK; |
| } |
| |
| #define LE_READ_4(p) \ |
| ((A_UINT32) \ |
| ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \ |
| (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24))) |
| |
| static int __inline |
| iswmmoui(const A_UINT8 *frm) |
| { |
| return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); |
| } |
| |
| static int __inline |
| iswmmparam(const A_UINT8 *frm) |
| { |
| return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; |
| } |
| |
| |
| static A_STATUS |
| wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_CONNECT_EVENT *ev; |
| A_UINT8 *pie,*peie; |
| |
| 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); |
| |
| /* initialize pointer to start of assoc rsp IEs */ |
| pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + |
| sizeof(A_UINT16) + /* capinfo*/ |
| sizeof(A_UINT16) + /* status Code */ |
| sizeof(A_UINT16) ; /* associd */ |
| |
| /* initialize pointer to end of assoc rsp IEs */ |
| peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen; |
| |
| while (pie < peie) |
| { |
| switch (*pie) |
| { |
| case IEEE80211_ELEMID_VENDOR: |
| if (iswmmoui(pie)) |
| { |
| if(iswmmparam (pie)) |
| { |
| wmip->wmi_is_wmm_enabled = TRUE; |
| } |
| } |
| break; |
| } |
| |
| if (wmip->wmi_is_wmm_enabled) |
| { |
| break; |
| } |
| pie += pie[1] + 2; |
| } |
| |
| A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid, |
| ev->listenInterval, ev->beaconInterval, |
| (NETWORK_TYPE) 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; |
| wmip->wmi_traffic_class = 100; |
| |
| 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)); |
| |
| wmip->wmi_is_wmm_enabled = FALSE; |
| wmip->wmi_pair_crypto_type = NONE_CRYPT; |
| wmip->wmi_grp_crypto_type = NONE_CRYPT; |
| |
| A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid, |
| ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus); |
| |
| return A_OK; |
| } |
| |
| static A_STATUS |
| wmi_peer_node_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_PEER_NODE_EVENT *ev; |
| |
| if (len < sizeof(WMI_PEER_NODE_EVENT)) { |
| return A_EINVAL; |
| } |
| ev = (WMI_PEER_NODE_EVENT *)datap; |
| if (ev->eventCode == PEER_NODE_JOIN_EVENT) { |
| A_DPRINTF (DBG_WMI, (DBGFMT "Joined node with Macaddr: ", DBGARG)); |
| } else if(ev->eventCode == PEER_NODE_LEAVE_EVENT) { |
| A_DPRINTF (DBG_WMI, (DBGFMT "left node with Macaddr: ", DBGARG)); |
| } |
| |
| A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr); |
| |
| 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 = NULL; |
| WMI_BSS_INFO_HDR *bih; |
| A_UINT8 *buf; |
| A_UINT32 nodeCachingAllowed = 1; |
| A_UCHAR cached_ssid_len = 0; |
| A_UCHAR cached_ssid_buf[IEEE80211_NWID_LEN] = {0}; |
| A_UINT8 beacon_ssid_len = 0; |
| |
| if (len <= sizeof(WMI_BSS_INFO_HDR)) { |
| return A_EINVAL; |
| } |
| |
| bih = (WMI_BSS_INFO_HDR *)datap; |
| bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); |
| |
| if (bih->rssi > 0) { |
| if (NULL == bss) |
| return A_OK; //no node found in the table, just drop the node with incorrect RSSI |
| else |
| bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX |
| } |
| |
| 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) { |
| wmi_node_return(wmip, bss); |
| return A_EINVAL; |
| } |
| |
| if(!nodeCachingAllowed) { |
| wmi_node_return(wmip, bss); |
| return A_OK; |
| } |
| |
| 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) ) { |
| wmi_node_return(wmip, bss); |
| return A_OK; |
| } |
| |
| 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. |
| */ |
| |
| /* In case of hidden AP, beacon will not have ssid, |
| * but a directed probe response will have it, |
| * so cache the probe-resp-ssid if already present. */ |
| if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType)) |
| { |
| A_UCHAR *ie_ssid; |
| |
| ie_ssid = bss->ni_cie.ie_ssid; |
| if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0)) |
| { |
| cached_ssid_len = ie_ssid[1]; |
| memcpy(cached_ssid_buf, ie_ssid + 2, cached_ssid_len); |
| } |
| } |
| |
| /* |
| * Use the current average rssi of associated AP base on assumpiton |
| * 1. Most os with GUI will update RSSI by wmi_get_stats_cmd() periodically |
| * 2. wmi_get_stats_cmd(..) will be called when calling wmi_startscan_cmd(...) |
| * The average value of RSSI give end-user better feeling for instance value of scan result |
| * It also sync up RSSI info in GUI between scan result and RSSI signal icon |
| */ |
| if (bss && IEEE80211_ADDR_EQ(wmip->wmi_bssid, bih->bssid)) { |
| bih->rssi = bss->ni_rssi; |
| bih->snr = bss->ni_snr; |
| } |
| |
| wlan_node_reclaim(&wmip->wmi_scan_table, bss); |
| } |
| |
| /* beacon/probe response frame format |
| * [8] time stamp |
| * [2] beacon interval |
| * [2] capability information |
| * [tlv] ssid */ |
| beacon_ssid_len = buf[SSID_IE_LEN_INDEX]; |
| |
| /* If ssid is cached for this hidden AP, then change buffer len accordingly. */ |
| if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && |
| (0 != cached_ssid_len) && |
| (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) |
| { |
| len += (cached_ssid_len - beacon_ssid_len); |
| } |
| |
| 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); |
| |
| /* In case of hidden AP, beacon will not have ssid, |
| * but a directed probe response will have it, |
| * so place the cached-ssid(probe-resp) in the bssinfo. */ |
| if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) && |
| (0 != cached_ssid_len) && |
| (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1]))) |
| { |
| A_UINT8 *ni_buf = bss->ni_buf; |
| int buf_len = len; |
| |
| /* copy the first 14 bytes such as |
| * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */ |
| A_MEMCPY(ni_buf, buf, SSID_IE_LEN_INDEX + 1); |
| |
| ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len; |
| ni_buf += (SSID_IE_LEN_INDEX + 1); |
| |
| buf += (SSID_IE_LEN_INDEX + 1); |
| buf_len -= (SSID_IE_LEN_INDEX + 1); |
| |
| /* copy the cached ssid */ |
| A_MEMCPY(ni_buf, cached_ssid_buf, cached_ssid_len); |
| ni_buf += cached_ssid_len; |
| |
| buf += beacon_ssid_len; |
| buf_len -= beacon_ssid_len; |
| |
| if (cached_ssid_len > beacon_ssid_len) |
| buf_len -= (cached_ssid_len - beacon_ssid_len); |
| |
| /* now copy the rest of bytes */ |
| A_MEMCPY(ni_buf, buf, buf_len); |
| } |
| else |
| A_MEMCPY(bss->ni_buf, buf, len); |
| |
| bss->ni_framelen = 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_REPLY *reply; |
| A_INT32 rate; |
| A_UINT32 sgi,index; |
| /* 54149: |
| * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY. |
| * since there is difference in the length and to avoid returning |
| * error value. |
| */ |
| if (len < sizeof(WMI_BIT_RATE_REPLY)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_BIT_RATE_REPLY *)datap; |
| A_DPRINTF(DBG_WMI, |
| (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex)); |
| |
| if (reply->rateIndex == (A_INT8) RATE_AUTO) { |
| rate = RATE_AUTO; |
| } else { |
| // the SGI state is stored as the MSb of the rateIndex |
| index = reply->rateIndex & 0x7f; |
| sgi = (reply->rateIndex & 0x80)? 1:0; |
| rate = wmi_rateTable[index][sgi]; |
| } |
| |
| 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_REPLY *reply; |
| |
| if (len < sizeof(WMI_FIX_RATES_REPLY)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_FIX_RATES_REPLY *)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; |
| if ((A_STATUS)ev->status == A_OK) { |
| wlan_refresh_inactive_nodes(&wmip->wmi_scan_table); |
| } |
| A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (A_STATUS) ev->status); |
| is_probe_ssid = FALSE; |
| |
| 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) |
| { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len); |
| |
| return A_OK; |
| } |
| |
| static A_STATUS |
| wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_RSSI_THRESHOLD_EVENT *reply; |
| WMI_RSSI_THRESHOLD_VAL newThreshold; |
| WMI_RSSI_THRESHOLD_PARAMS_CMD cmd; |
| SQ_THRESHOLD_PARAMS *sq_thresh = |
| &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; |
| A_UINT8 upper_rssi_threshold, lower_rssi_threshold; |
| A_INT16 rssi; |
| |
| if (len < sizeof(*reply)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_RSSI_THRESHOLD_EVENT *)datap; |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| newThreshold = (WMI_RSSI_THRESHOLD_VAL) reply->range; |
| rssi = reply->rssi; |
| |
| /* |
| * Identify the threshold breached and communicate that to the app. After |
| * that install a new set of thresholds based on the signal quality |
| * reported by the target |
| */ |
| if (newThreshold) { |
| /* Upper threshold breached */ |
| if (rssi < sq_thresh->upper_threshold[0]) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper RSSI threshold event: " |
| " %d\n", DBGARG, rssi)); |
| } else if ((rssi < sq_thresh->upper_threshold[1]) && |
| (rssi >= sq_thresh->upper_threshold[0])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD1_ABOVE; |
| } else if ((rssi < sq_thresh->upper_threshold[2]) && |
| (rssi >= sq_thresh->upper_threshold[1])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD2_ABOVE; |
| } else if ((rssi < sq_thresh->upper_threshold[3]) && |
| (rssi >= sq_thresh->upper_threshold[2])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD3_ABOVE; |
| } else if ((rssi < sq_thresh->upper_threshold[4]) && |
| (rssi >= sq_thresh->upper_threshold[3])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD4_ABOVE; |
| } else if ((rssi < sq_thresh->upper_threshold[5]) && |
| (rssi >= sq_thresh->upper_threshold[4])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD5_ABOVE; |
| } else if (rssi >= sq_thresh->upper_threshold[5]) { |
| newThreshold = WMI_RSSI_THRESHOLD6_ABOVE; |
| } |
| } else { |
| /* Lower threshold breached */ |
| if (rssi > sq_thresh->lower_threshold[0]) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower RSSI threshold event: " |
| "%d %d\n", DBGARG, rssi, sq_thresh->lower_threshold[0])); |
| } else if ((rssi > sq_thresh->lower_threshold[1]) && |
| (rssi <= sq_thresh->lower_threshold[0])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD6_BELOW; |
| } else if ((rssi > sq_thresh->lower_threshold[2]) && |
| (rssi <= sq_thresh->lower_threshold[1])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD5_BELOW; |
| } else if ((rssi > sq_thresh->lower_threshold[3]) && |
| (rssi <= sq_thresh->lower_threshold[2])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD4_BELOW; |
| } else if ((rssi > sq_thresh->lower_threshold[4]) && |
| (rssi <= sq_thresh->lower_threshold[3])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD3_BELOW; |
| } else if ((rssi > sq_thresh->lower_threshold[5]) && |
| (rssi <= sq_thresh->lower_threshold[4])) |
| { |
| newThreshold = WMI_RSSI_THRESHOLD2_BELOW; |
| } else if (rssi <= sq_thresh->lower_threshold[5]) { |
| newThreshold = WMI_RSSI_THRESHOLD1_BELOW; |
| } |
| } |
| /* Calculate and install the next set of thresholds */ |
| lower_rssi_threshold = ar6000_get_lower_threshold(rssi, sq_thresh, |
| sq_thresh->lower_threshold_valid_count); |
| upper_rssi_threshold = ar6000_get_upper_threshold(rssi, sq_thresh, |
| sq_thresh->upper_threshold_valid_count); |
| /* Issue a wmi command to install the thresholds */ |
| cmd.thresholdAbove1_Val = upper_rssi_threshold; |
| cmd.thresholdBelow1_Val = lower_rssi_threshold; |
| cmd.weight = sq_thresh->weight; |
| cmd.pollTime = sq_thresh->polling_interval; |
| |
| rssi_event_value = rssi; |
| |
| if (wmi_send_rssi_threshold_params(wmip, &cmd) != A_OK) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n", |
| DBGARG)); |
| } |
| |
| A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, 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, (WMI_TARGET_ERROR_VAL) 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; |
| WMM_TSPEC_IE *tspec_ie; |
| A_UINT16 activeTsids; |
| |
| if (len < sizeof(*reply)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_CAC_EVENT *)datap; |
| |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) && |
| (reply->statusCode != TSPEC_STATUS_CODE_ADMISSION_ACCEPTED)) { |
| tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); |
| |
| wmi_delete_pstream_cmd(wmip, reply->ac, |
| (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); |
| } |
| else if (reply->cac_indication == CAC_INDICATION_NO_RESP) { |
| A_UINT8 i; |
| |
| /* following assumes that there is only one outstanding ADDTS request |
| when this event is received */ |
| LOCK_WMI(wmip); |
| activeTsids = wmip->wmi_streamExistsForAC[reply->ac]; |
| UNLOCK_WMI(wmip); |
| |
| for (i = 0; i < sizeof(activeTsids) * 8; i++) { |
| if ((activeTsids >> i) & 1) { |
| break; |
| } |
| } |
| if (i < (sizeof(activeTsids) * 8)) { |
| wmi_delete_pstream_cmd(wmip, reply->ac, i); |
| } |
| } |
| /* |
| * Ev#72990: Clear active tsids and Add missing handling |
| * for delete qos stream from AP |
| */ |
| else if (reply->cac_indication == CAC_INDICATION_DELETE) { |
| A_UINT8 tsid = 0; |
| |
| tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion); |
| tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK); |
| LOCK_WMI(wmip); |
| wmip->wmi_streamExistsForAC[reply->ac] &= ~(1<<tsid); |
| activeTsids = wmip->wmi_streamExistsForAC[reply->ac]; |
| 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, reply->ac); |
| wmip->wmi_fatPipeExists &= ~(1 << reply->ac); |
| } |
| } |
| |
| A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac, |
| reply->cac_indication, reply->statusCode, |
| reply->tspecSuggestion); |
| |
| return A_OK; |
| } |
| |
| static A_STATUS |
| wmi_channel_change_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_CHANNEL_CHANGE_EVENT *reply; |
| |
| if (len < sizeof(*reply)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_CHANNEL_CHANGE_EVENT *)datap; |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel, |
| reply->newChannel); |
| |
| 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) |
| { |
| if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) { |
| return A_EINVAL; |
| } |
| 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; |
| SQ_THRESHOLD_PARAMS *sq_thresh = |
| &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; |
| WMI_SNR_THRESHOLD_VAL newThreshold; |
| WMI_SNR_THRESHOLD_PARAMS_CMD cmd; |
| A_UINT8 upper_snr_threshold, lower_snr_threshold; |
| A_INT16 snr; |
| |
| if (len < sizeof(*reply)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_SNR_THRESHOLD_EVENT *)datap; |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| newThreshold = (WMI_SNR_THRESHOLD_VAL) reply->range; |
| snr = reply->snr; |
| /* |
| * Identify the threshold breached and communicate that to the app. After |
| * that install a new set of thresholds based on the signal quality |
| * reported by the target |
| */ |
| if (newThreshold) { |
| /* Upper threshold breached */ |
| if (snr < sq_thresh->upper_threshold[0]) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Spurious upper SNR threshold event: " |
| "%d\n", DBGARG, snr)); |
| } else if ((snr < sq_thresh->upper_threshold[1]) && |
| (snr >= sq_thresh->upper_threshold[0])) |
| { |
| newThreshold = WMI_SNR_THRESHOLD1_ABOVE; |
| } else if ((snr < sq_thresh->upper_threshold[2]) && |
| (snr >= sq_thresh->upper_threshold[1])) |
| { |
| newThreshold = WMI_SNR_THRESHOLD2_ABOVE; |
| } else if ((snr < sq_thresh->upper_threshold[3]) && |
| (snr >= sq_thresh->upper_threshold[2])) |
| { |
| newThreshold = WMI_SNR_THRESHOLD3_ABOVE; |
| } else if (snr >= sq_thresh->upper_threshold[3]) { |
| newThreshold = WMI_SNR_THRESHOLD4_ABOVE; |
| } |
| } else { |
| /* Lower threshold breached */ |
| if (snr > sq_thresh->lower_threshold[0]) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Spurious lower SNR threshold event: " |
| "%d %d\n", DBGARG, snr, sq_thresh->lower_threshold[0])); |
| } else if ((snr > sq_thresh->lower_threshold[1]) && |
| (snr <= sq_thresh->lower_threshold[0])) |
| { |
| newThreshold = WMI_SNR_THRESHOLD4_BELOW; |
| } else if ((snr > sq_thresh->lower_threshold[2]) && |
| (snr <= sq_thresh->lower_threshold[1])) |
| { |
| newThreshold = WMI_SNR_THRESHOLD3_BELOW; |
| } else if ((snr > sq_thresh->lower_threshold[3]) && |
| (snr <= sq_thresh->lower_threshold[2])) |
| { |
| newThreshold = WMI_SNR_THRESHOLD2_BELOW; |
| } else if (snr <= sq_thresh->lower_threshold[3]) { |
| newThreshold = WMI_SNR_THRESHOLD1_BELOW; |
| } |
| } |
| |
| /* Calculate and install the next set of thresholds */ |
| lower_snr_threshold = ar6000_get_lower_threshold(snr, sq_thresh, |
| sq_thresh->lower_threshold_valid_count); |
| upper_snr_threshold = ar6000_get_upper_threshold(snr, sq_thresh, |
| sq_thresh->upper_threshold_valid_count); |
| |
| /* Issue a wmi command to install the thresholds */ |
| cmd.thresholdAbove1_Val = upper_snr_threshold; |
| cmd.thresholdBelow1_Val = lower_snr_threshold; |
| cmd.weight = sq_thresh->weight; |
| cmd.pollTime = sq_thresh->polling_interval; |
| |
| A_DPRINTF(DBG_WMI, (DBGFMT "snr: %d, threshold: %d, lower: %d, upper: %d\n" |
| ,DBGARG, snr, newThreshold, lower_snr_threshold, |
| upper_snr_threshold)); |
| |
| snr_event_value = snr; |
| |
| if (wmi_send_snr_threshold_params(wmip, &cmd) != A_OK) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n", |
| DBGARG)); |
| } |
| A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, 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, |
| (WMI_LQ_THRESHOLD_VAL) 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, (A_INT8*)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) |
| { |
| A_STATUS status; |
| #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID)) |
| WMI_CMD_HDR *cHdr; |
| HTC_ENDPOINT_ID eid = wmip->wmi_endpoint_id; |
| |
| A_ASSERT(osbuf != NULL); |
| |
| if (syncflag >= END_WMIFLAG) { |
| A_NETBUF_FREE(osbuf); |
| 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) { |
| A_NETBUF_FREE(osbuf); |
| return A_NO_MEMORY; |
| } |
| |
| cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); |
| cHdr->commandId = (A_UINT16) cmdId; |
| cHdr->info1 = 0; // added for virtual interface |
| |
| /* |
| * Only for OPT_TX_CMD, use BE endpoint. |
| */ |
| if (IS_OPT_TX_CMD(cmdId)) { |
| if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, FALSE, FALSE,0,NULL)) != A_OK) { |
| A_NETBUF_FREE(osbuf); |
| return status; |
| } |
| eid = A_WMI_Ac2EndpointID(wmip->wmi_devt, WMM_AC_BE); |
| } |
| A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid); |
| |
| 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_OPT_TX_CMD |
| } |
| |
| A_STATUS |
| wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId, |
| WMI_SYNC_FLAG syncflag) |
| { |
| WMIX_CMD_HDR *cHdr; |
| |
| if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) { |
| A_NETBUF_FREE(osbuf); |
| return A_NO_MEMORY; |
| } |
| |
| cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); |
| cHdr->commandId = (A_UINT32) 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; |
| wmip->wmi_traffic_class = 100; |
| |
| 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)); |
| |
| if (ssidLength) |
| { |
| 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); |
| } |
| |
| wmip->wmi_pair_crypto_type = pairwiseCrypto; |
| wmip->wmi_grp_crypto_type = groupCrypto; |
| |
| 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; |
| wmip->wmi_traffic_class = 100; |
| |
| 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) |
| { |
| A_STATUS status; |
| wmip->wmi_traffic_class = 100; |
| |
| /* Bug fix for 24817(elevator bug) - the disconnect command does not |
| need to do a SYNC before.*/ |
| status = wmi_simple_cmd(wmip, WMI_DISCONNECT_CMDID); |
| |
| 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, |
| A_INT8 numChan, A_UINT16 *channelList) |
| { |
| void *osbuf; |
| WMI_START_SCAN_CMD *sc; |
| A_INT8 size; |
| |
| size = sizeof (*sc); |
| |
| if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) { |
| return A_EINVAL; |
| } |
| |
| 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); |
| |
| sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf)); |
| sc->scanType = scanType; |
| sc->forceFgScan = forceFgScan; |
| sc->isLegacy = isLegacy; |
| sc->homeDwellTime = homeDwellTime; |
| sc->forceScanInterval = forceScanInterval; |
| sc->numChannels = numChan; |
| if (numChan) { |
| A_MEMCPY(sc->channelList, channelList, numChan * sizeof(A_UINT16)); |
| } |
| |
| 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, A_UINT16 maxact_scan_per_ssid) |
| { |
| 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; |
| sc->maxact_scan_per_ssid = maxact_scan_per_ssid; |
| |
| 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; |
| } |
| |
| if (flag & SPECIFIC_SSID_FLAG) { |
| is_probe_ssid = TRUE; |
| } |
| |
| 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_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time, |
| A_UINT32 ps_period, A_UINT8 sleep_period) |
| { |
| void *osbuf; |
| WMI_AP_PS_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_AP_PS_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->psType = psType; |
| cmd->idle_time = idle_time; |
| cmd->ps_period = ps_period; |
| cmd->sleep_period = sleep_period; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_AP_PS_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod, |
| A_UINT16 psPollNum, A_UINT16 dtimPolicy, |
| A_UINT16 tx_wakeup_policy, A_UINT16 num_tx_to_wakeup, |
| A_UINT16 ps_fail_event_policy) |
| { |
| 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; |
| pm->tx_wakeup_policy = tx_wakeup_policy; |
| pm->num_tx_to_wakeup = num_tx_to_wakeup; |
| pm->ps_fail_event_policy = ps_fail_event_policy; |
| |
| 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, A_UINT8 *macAddr, |
| 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); |
| #ifdef WAPI_ENABLE |
| if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) { |
| #else |
| if (NULL != keyRSC) { |
| #endif // WAPI_ENABLE |
| A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC)); |
| } |
| cmd->key_op_ctrl = key_op_ctrl; |
| |
| if(macAddr) { |
| A_MEMCPY(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN); |
| } |
| |
| 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) |
| { |
| return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID); |
| } |
| |
| 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) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID); |
| } |
| |
| A_STATUS |
| wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid) |
| { |
| WMI_DATA_HDR *dtHdr; |
| |
| A_ASSERT( eid != wmip->wmi_endpoint_id); |
| 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 - eid %d\n", DBGARG, eid)); |
| |
| return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, eid)); |
| } |
| |
| 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_SYNC_CMD *cmd; |
| WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC]; |
| A_UINT8 i,numPriStreams=0; |
| A_STATUS status = A_OK; |
| |
| 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(sizeof(*cmd)); |
| if (cmd_osbuf == NULL) { |
| status = A_NO_MEMORY; |
| break; |
| } |
| |
| A_NETBUF_PUT(cmd_osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_SYNC_CMD *)(A_NETBUF_DATA(cmd_osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| /* In the SYNC cmd sent on the control Ep, send a bitmap of the data |
| * eps on which the Data Sync will be sent |
| */ |
| cmd->dataSyncMap = wmip->wmi_fatPipeExists; |
| |
| 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 |
| |
| /* if Buffer allocation for any of the dataSync fails, then do not |
| * send the Synchronize cmd on the control ep |
| */ |
| if (A_FAILED(status)) { |
| break; |
| } |
| |
| /* |
| * 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, |
| A_WMI_Ac2EndpointID(wmip->wmi_devt, |
| 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_UINT8 fatPipeExistsForAC=0; |
| A_INT32 minimalPHY = 0; |
| A_INT32 nominalPHY = 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; |
| } |
| |
| // |
| // check nominal PHY rate is >= minimalPHY, so that DUT |
| // can allow TSRS IE |
| // |
| |
| // get the physical rate |
| minimalPHY = ((params->minPhyRate / 1000)/1000); // unit of bps |
| |
| // check minimal phy < nominal phy rate |
| // |
| if (params->nominalPHY >= minimalPHY) |
| { |
| nominalPHY = (params->nominalPHY * 1000)/500; // unit of 500 kbps |
| A_DPRINTF(DBG_WMI, |
| (DBGFMT "TSRS IE Enabled::MinPhy %x->NominalPhy ===> %x\n", DBGARG, |
| minimalPHY, nominalPHY)); |
| |
| params->nominalPHY = nominalPHY; |
| } |
| else |
| { |
| params->nominalPHY = 0; |
| } |
| |
| 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 ((A_UINT32)params->tsid == (A_UINT32)WMI_IMPLICIT_PSTREAM) { |
| LOCK_WMI(wmip); |
| fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); |
| wmip->wmi_fatPipeExists |= (1<<params->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)); |
| wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid); |
| /* if a thinstream becomes active, the fat pipe automatically |
| * becomes active |
| */ |
| wmip->wmi_fatPipeExists |= (1<<params->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; |
| |
| /* validate the parameters */ |
| if (trafficClass > 3) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Invalid trafficClass: %d\n", DBGARG, trafficClass)); |
| 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_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<<tsid))) { |
| |
| A_NETBUF_FREE(osbuf); |
| A_DPRINTF(DBG_WMI, |
| (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass)); |
| /* TODO: return a more appropriate err code */ |
| return A_ERROR; |
| } |
| |
| A_DPRINTF(DBG_WMI, |
| (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid)); |
| |
| status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID, |
| SYNC_BEFORE_WMIFLAG)); |
| |
| LOCK_WMI(wmip); |
| wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid); |
| activeTsids = wmip->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<<trafficClass); |
| } |
| |
| return status; |
| } |
| |
| A_STATUS |
| wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8 subType, A_UINT16 rateMask) |
| { |
| void *osbuf; |
| WMI_FRAME_RATES_CMD *cmd; |
| A_UINT8 frameType; |
| |
| A_DPRINTF(DBG_WMI, |
| (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask)); |
| |
| if((type != IEEE80211_FRAME_TYPE_MGT && type != IEEE80211_FRAME_TYPE_CTL) || |
| (subType > 15)){ |
| |
| return A_EINVAL; |
| } |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| frameType = (A_UINT8)((subType << 4) | type); |
| |
| cmd->bEnableMask = bEnable; |
| cmd->frameType = frameType; |
| cmd->frameRateMask = rateMask; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_FRAMERATES_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* |
| * used to set the bit rate. rate is in Kbps. If rate == -1 |
| * then auto selection is used. |
| */ |
| A_STATUS |
| wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_INT32 ctlRate) |
| { |
| void *osbuf; |
| WMI_BIT_RATE_CMD *cmd; |
| A_INT8 drix, mrix, crix, ret_val; |
| |
| if (dataRate != -1) { |
| ret_val = wmi_validate_bitrate(wmip, dataRate, &drix); |
| if(ret_val == A_EINVAL){ |
| return A_EINVAL; |
| } |
| } else { |
| drix = -1; |
| } |
| |
| if (mgmtRate != -1) { |
| ret_val = wmi_validate_bitrate(wmip, mgmtRate, &mrix); |
| if(ret_val == A_EINVAL){ |
| return A_EINVAL; |
| } |
| } else { |
| mrix = -1; |
| } |
| if (ctlRate != -1) { |
| ret_val = wmi_validate_bitrate(wmip, ctlRate, &crix); |
| if(ret_val == A_EINVAL){ |
| return A_EINVAL; |
| } |
| } else { |
| crix = -1; |
| } |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| cmd->rateIndex = drix; |
| cmd->mgmtRateIndex = mrix; |
| cmd->ctlRateIndex = crix; |
| |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_get_bitrate_cmd(struct wmi_t *wmip) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID); |
| } |
| |
| /* |
| * 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_INT32 rateIndex) |
| { |
| WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode; |
| A_BOOL isValid = TRUE; |
| switch(phyMode) { |
| case WMI_11A_MODE: |
| if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){ |
| if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { |
| isValid = FALSE; |
| } |
| } else { |
| 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 (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ |
| if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { |
| isValid = FALSE; |
| } |
| } else { |
| 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 (wmip->wmi_ht_allowed[A_BAND_24GHZ]){ |
| if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) { |
| isValid = FALSE; |
| } |
| } else { |
| 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 *rate_idx) |
| { |
| A_INT8 i; |
| |
| for (i=0;;i++) |
| { |
| if (wmi_rateTable[(A_UINT32) i][0] == 0) { |
| return A_EINVAL; |
| } |
| if (wmi_rateTable[(A_UINT32) i][0] == rate) { |
| break; |
| } |
| } |
| |
| if(wmi_is_bitrate_index_valid(wmip, (A_INT32) i) != TRUE) { |
| return A_EINVAL; |
| } |
| |
| *rate_idx = i; |
| return A_OK; |
| } |
| |
| A_STATUS |
| wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask) |
| { |
| void *osbuf; |
| WMI_FIX_RATES_CMD *cmd; |
| #if 0 |
| A_INT32 rateIndex; |
| /* This check does not work for AR6003 as the HT modes are enabled only when |
| * the STA is connected to a HT_BSS and is not based only on channel. It is |
| * safe to skip this check however because rate control will only use rates |
| * that are permitted by the valid rate mask and the fix rate mask. Meaning |
| * the fix rate mask is not sufficient by itself to cause an invalid rate |
| * to be used. */ |
| /* 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; |
| } |
| } |
| } |
| #endif |
| |
| |
| 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) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID); |
| } |
| |
| A_STATUS |
| wmi_get_channelList_cmd(struct wmi_t *wmip) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID); |
| } |
| |
| /* |
| * 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)); |
| } |
| |
| void |
| wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) |
| { |
| SQ_THRESHOLD_PARAMS *sq_thresh = |
| &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI]; |
| /* |
| * Parse the command and store the threshold values here. The checks |
| * for valid values can be put here |
| */ |
| sq_thresh->weight = rssiCmd->weight; |
| sq_thresh->polling_interval = rssiCmd->pollTime; |
| |
| sq_thresh->upper_threshold[0] = rssiCmd->thresholdAbove1_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->upper_threshold[1] = rssiCmd->thresholdAbove2_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->upper_threshold[2] = rssiCmd->thresholdAbove3_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->upper_threshold[3] = rssiCmd->thresholdAbove4_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->upper_threshold[4] = rssiCmd->thresholdAbove5_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->upper_threshold[5] = rssiCmd->thresholdAbove6_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->upper_threshold_valid_count = 6; |
| |
| /* List sorted in descending order */ |
| sq_thresh->lower_threshold[0] = rssiCmd->thresholdBelow6_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->lower_threshold[1] = rssiCmd->thresholdBelow5_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->lower_threshold[2] = rssiCmd->thresholdBelow4_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->lower_threshold[3] = rssiCmd->thresholdBelow3_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->lower_threshold[4] = rssiCmd->thresholdBelow2_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->lower_threshold[5] = rssiCmd->thresholdBelow1_Val - SIGNAL_QUALITY_NOISE_FLOOR; |
| sq_thresh->lower_threshold_valid_count = 6; |
| |
| if (!rssi_event_value) { |
| /* |
| * Configuring the thresholds to their extremes allows the host to get an |
| * event from the target which is used for the configuring the correct |
| * thresholds |
| */ |
| rssiCmd->thresholdAbove1_Val = sq_thresh->upper_threshold[0]; |
| rssiCmd->thresholdBelow1_Val = sq_thresh->lower_threshold[0]; |
| } else { |
| /* |
| * In case the user issues multiple times of rssi_threshold_setting, |
| * we should not use the extreames anymore, the target does not expect that. |
| */ |
| rssiCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(rssi_event_value, sq_thresh, |
| sq_thresh->upper_threshold_valid_count); |
| rssiCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(rssi_event_value, sq_thresh, |
| sq_thresh->lower_threshold_valid_count); |
| } |
| } |
| |
| A_STATUS |
| wmi_set_rssi_threshold_params(struct wmi_t *wmip, |
| WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) |
| { |
| |
| /* Check 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; |
| } |
| |
| wmi_cache_configure_rssithreshold(wmip, rssiCmd); |
| |
| return (wmi_send_rssi_threshold_params(wmip, rssiCmd)); |
| } |
| |
| A_STATUS |
| wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd) |
| { |
| void *osbuf; |
| WMI_SET_IP_CMD *cmd; |
| |
| /* Multicast address are not valid */ |
| if((*((A_UINT8*)&ipCmd->ips[0]) >= 0xE0) || |
| (*((A_UINT8*)&ipCmd->ips[1]) >= 0xE0)) { |
| return A_EINVAL; |
| } |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_IP_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD)); |
| cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMCPY(cmd, ipCmd, sizeof(WMI_SET_IP_CMD)); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_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; |
| A_UINT16 activeTsids=0; |
| A_UINT8 streamExists=0; |
| A_UINT8 i; |
| |
| 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)); |
| |
| if(hostModeCmd->asleep) { |
| /* |
| * Relinquish credits from all implicitly created pstreams since when we |
| * go to sleep. If user created explicit thinstreams exists with in a |
| * fatpipe leave them intact for the user to delete |
| */ |
| LOCK_WMI(wmip); |
| streamExists = wmip->wmi_fatPipeExists; |
| UNLOCK_WMI(wmip); |
| |
| for(i=0;i< WMM_NUM_AC;i++) { |
| if (streamExists & (1<<i)) { |
| LOCK_WMI(wmip); |
| activeTsids = wmip->wmi_streamExistsForAC[i]; |
| UNLOCK_WMI(wmip); |
| /* If there are no user created thin streams delete the fatpipe */ |
| if(!activeTsids) { |
| streamExists &= ~(1<<i); |
| /*Indicate inactivity to drv layer for this fatpipe(pstream)*/ |
| A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt,i); |
| } |
| } |
| } |
| |
| /* Update the fatpipes that exists*/ |
| LOCK_WMI(wmip); |
| wmip->wmi_fatPipeExists = streamExists; |
| UNLOCK_WMI(wmip); |
| } |
| |
| 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)); |
| |
| } |
| |
| void |
| wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) |
| { |
| SQ_THRESHOLD_PARAMS *sq_thresh = |
| &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR]; |
| /* |
| * Parse the command and store the threshold values here. The checks |
| * for valid values can be put here |
| */ |
| sq_thresh->weight = snrCmd->weight; |
| sq_thresh->polling_interval = snrCmd->pollTime; |
| |
| sq_thresh->upper_threshold[0] = snrCmd->thresholdAbove1_Val; |
| sq_thresh->upper_threshold[1] = snrCmd->thresholdAbove2_Val; |
| sq_thresh->upper_threshold[2] = snrCmd->thresholdAbove3_Val; |
| sq_thresh->upper_threshold[3] = snrCmd->thresholdAbove4_Val; |
| sq_thresh->upper_threshold_valid_count = 4; |
| |
| /* List sorted in descending order */ |
| sq_thresh->lower_threshold[0] = snrCmd->thresholdBelow4_Val; |
| sq_thresh->lower_threshold[1] = snrCmd->thresholdBelow3_Val; |
| sq_thresh->lower_threshold[2] = snrCmd->thresholdBelow2_Val; |
| sq_thresh->lower_threshold[3] = snrCmd->thresholdBelow1_Val; |
| sq_thresh->lower_threshold_valid_count = 4; |
| |
| if (!snr_event_value) { |
| /* |
| * Configuring the thresholds to their extremes allows the host to get an |
| * event from the target which is used for the configuring the correct |
| * thresholds |
| */ |
| snrCmd->thresholdAbove1_Val = (A_UINT8)sq_thresh->upper_threshold[0]; |
| snrCmd->thresholdBelow1_Val = (A_UINT8)sq_thresh->lower_threshold[0]; |
| } else { |
| /* |
| * In case the user issues multiple times of snr_threshold_setting, |
| * we should not use the extreames anymore, the target does not expect that. |
| */ |
| snrCmd->thresholdAbove1_Val = ar6000_get_upper_threshold(snr_event_value, sq_thresh, |
| sq_thresh->upper_threshold_valid_count); |
| snrCmd->thresholdBelow1_Val = ar6000_get_lower_threshold(snr_event_value, sq_thresh, |
| sq_thresh->lower_threshold_valid_count); |
| } |
| |
| } |
| A_STATUS |
| wmi_set_snr_threshold_params(struct wmi_t *wmip, |
| WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) |
| { |
| 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; |
| } |
| wmi_cache_configure_snrthreshold(wmip, snrCmd); |
| return (wmi_send_snr_threshold_params(wmip, snrCmd)); |
| } |
| |
| 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) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID); |
| } |
| |
| 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, SYNC_BEFORE_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_abort_scan_cmd(struct wmi_t *wmip) |
| { |
| return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID); |
| } |
| |
| 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) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID); |
| } |
| |
| 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) |
| { |
| return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID); |
| } |
| |
| 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) |
| { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| return wmi_simple_cmd_xtnd(wmip, WMIX_GPIO_INPUT_GET_CMDID); |
| } |
| |
| /* 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_UINT8 ac, 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) || (ac >= WMM_NUM_AC)) |
| { |
| 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; |
| cmd->ac = ac; |
| |
| 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 |
| wmi_determine_userPriority( |
| A_UINT8 *pkt, |
| A_UINT32 layer2Pri) |
| { |
| A_UINT8 ipPri; |
| iphdr *ipHdr = (iphdr *)pkt; |
| |
| /* Determine IPTOS priority */ |
| /* |
| * IP Tos format : |
| * (Refer Pg 57 WMM-test-plan-v1.2) |
| * IP-TOS - 8bits |
| * : DSCP(6-bits) ECN(2-bits) |
| * : DSCP - P2 P1 P0 X X X |
| * where (P2 P1 P0) form 802.1D |
| */ |
| ipPri = ipHdr->ip_tos >> 5; |
| ipPri &= 0x7; |
| |
| if ((layer2Pri & 0x7) > ipPri) |
| return ((A_UINT8)layer2Pri & 0x7); |
| else |
| return ipPri; |
| } |
| |
| 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) |
| { |
| A_STATUS ret = A_OK; |
| |
| #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0) |
| #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF 0 |
| #define TSPEC_MAX_BURST_SIZE_ATHEROS_DEF 0 |
| #define TSPEC_DELAY_BOUND_ATHEROS_DEF 0 |
| #define TSPEC_MEDIUM_TIME_ATHEROS_DEF 0 |
| #define TSPEC_SBA_ATHEROS_DEF 0x2000 /* factor is 1 */ |
| |
| /* Verify TSPEC params for ATHEROS compliance */ |
| if(tspecCompliance == ATHEROS_COMPLIANCE) { |
| if ((pCmd->suspensionInt != TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF) || |
| (pCmd->serviceStartTime != TSPEC_SERVICE_START_TIME_ATHEROS_DEF) || |
| (pCmd->minDataRate != pCmd->meanDataRate) || |
| (pCmd->minDataRate != pCmd->peakDataRate) || |
| (pCmd->maxBurstSize != TSPEC_MAX_BURST_SIZE_ATHEROS_DEF) || |
| (pCmd->delayBound != TSPEC_DELAY_BOUND_ATHEROS_DEF) || |
| (pCmd->sba != TSPEC_SBA_ATHEROS_DEF) || |
| (pCmd->mediumTime != TSPEC_MEDIUM_TIME_ATHEROS_DEF)) { |
| |
| A_DPRINTF(DBG_WMI, (DBGFMT "Invalid TSPEC params\n", DBGARG)); |
| //A_PRINTF("%s: Invalid TSPEC params\n", __func__); |
| ret = A_EINVAL; |
| } |
| } |
| |
| return ret; |
| } |
| |
| #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, A_UINT8 preamblePolicy) |
| { |
| 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; |
| cmd->preamblePolicy = preamblePolicy; |
| |
| 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_qos_supp_cmd(struct wmi_t *wmip, A_UINT8 status) |
| { |
| void *osbuf; |
| WMI_SET_QOS_SUPP_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_SET_QOS_SUPP_CMD*)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->status = status; |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_QOS_SUPP_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)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode) |
| { |
| void *osbuf; |
| WMI_AP_SET_COUNTRY_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| A_MEMCPY(cmd->countryCode,countryCode,3); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_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; |
| |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Enter - streamType=%d, status=%d\n", streamType, status)); |
| |
| 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; |
| |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("cmd params is %d\n", cmd->paramType)); |
| |
| if (cmd->paramType == BT_PARAM_SCO) { |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("sco params %d %d %d %d %d %d %d %d %d %d %d %d\n", cmd->info.scoParams.numScoCyclesForceTrigger, |
| cmd->info.scoParams.dataResponseTimeout, |
| cmd->info.scoParams.stompScoRules, |
| cmd->info.scoParams.scoOptFlags, |
| cmd->info.scoParams.stompDutyCyleVal, |
| cmd->info.scoParams.stompDutyCyleMaxVal, |
| cmd->info.scoParams.psPollLatencyFraction, |
| cmd->info.scoParams.noSCOSlots, |
| cmd->info.scoParams.noIdleSlots, |
| cmd->info.scoParams.scoOptOffRssi, |
| cmd->info.scoParams.scoOptOnRssi, |
| cmd->info.scoParams.scoOptRtsCount)); |
| } |
| else if (cmd->paramType == BT_PARAM_A2DP) { |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("A2DP params %d %d %d %d %d %d %d %d\n", cmd->info.a2dpParams.a2dpWlanUsageLimit, |
| cmd->info.a2dpParams.a2dpBurstCntMin, |
| cmd->info.a2dpParams.a2dpDataRespTimeout, |
| cmd->info.a2dpParams.a2dpOptFlags, |
| cmd->info.a2dpParams.isCoLocatedBtRoleMaster, |
| cmd->info.a2dpParams.a2dpOptOffRssi, |
| cmd->info.a2dpParams.a2dpOptOnRssi, |
| cmd->info.a2dpParams.a2dpOptRtsCount)); |
| } |
| else if (cmd->paramType == BT_PARAM_ANTENNA_CONFIG) { |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("Ant config %d\n", cmd->info.antType)); |
| } |
| else if (cmd->paramType == BT_PARAM_COLOCATED_BT_DEVICE) { |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("co-located BT %d\n", cmd->info.coLocatedBtDev)); |
| } |
| else if (cmd->paramType == BT_PARAM_ACLCOEX) { |
| AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("ACL params %d %d %d\n", cmd->info.aclCoexParams.aclWlanMediumUsageTime, |
| cmd->info.aclCoexParams.aclBtMediumUsageTime, |
| cmd->info.aclCoexParams.aclDataRespTimeout)); |
| } |
| else if (cmd->paramType == BT_PARAM_11A_SEPARATE_ANT) { |
| A_DPRINTF(DBG_WMI, (DBGFMT "11A ant\n", DBGARG)); |
| } |
| |
| 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_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_FE_ANT_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_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID, |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| |
| A_STATUS |
| wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip, |
| WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_COLOCATED_BT_DEV_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_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD)); |
| A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID, |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip, |
| WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_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_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID, |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip, |
| WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_SCO_CONFIG_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_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID , |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip, |
| WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_A2DP_CONFIG_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_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID , |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, |
| WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_ACLCOEX_CONFIG_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_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID , |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_DEBUG_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_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID , |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip, |
| WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_SET_BTCOEX_BT_OPERATING_STATUS_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_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID , |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd) |
| { |
| void *osbuf; |
| WMI_GET_BTCOEX_CONFIG_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_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(alloc_cmd, sizeof(*cmd)); |
| A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID , |
| NO_SYNC_WMIFLAG)); |
| |
| } |
| |
| A_STATUS |
| wmi_get_btcoex_stats_cmd(struct wmi_t *wmip) |
| { |
| |
| return wmi_simple_cmd(wmip, WMI_GET_BTCOEX_STATS_CMDID); |
| |
| } |
| |
| 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_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR* buffer) |
| { |
| void *osbuf; |
| WMI_SET_PARAMS_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + length); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd) + length); |
| |
| cmd = (WMI_SET_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->opcode = opcode; |
| cmd->length = length; |
| A_MEMCPY(cmd->buffer, buffer, length); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| |
| A_STATUS |
| wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4) |
| { |
| void *osbuf; |
| WMI_SET_MCAST_FILTER_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->multicast_mac[0] = 0x01; |
| cmd->multicast_mac[1] = 0x00; |
| cmd->multicast_mac[2] = 0x5e; |
| cmd->multicast_mac[3] = dot2&0x7F; |
| cmd->multicast_mac[4] = dot3; |
| cmd->multicast_mac[5] = dot4; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_MCAST_FILTER_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| |
| A_STATUS |
| wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4) |
| { |
| void *osbuf; |
| WMI_SET_MCAST_FILTER_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_SET_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->multicast_mac[0] = 0x01; |
| cmd->multicast_mac[1] = 0x00; |
| cmd->multicast_mac[2] = 0x5e; |
| cmd->multicast_mac[3] = dot2&0x7F; |
| cmd->multicast_mac[4] = dot3; |
| cmd->multicast_mac[5] = dot4; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_DEL_MCAST_FILTER_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable) |
| { |
| void *osbuf; |
| WMI_MCAST_FILTER_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_MCAST_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->enable = enable; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_MCAST_FILTER_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; |
| |
| 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][0]); |
| } |
| } |
| |
| void |
| wmi_node_return (struct wmi_t *wmip, bss_t *bss) |
| { |
| if (NULL != bss) |
| { |
| wlan_node_return (&wmip->wmi_scan_table, bss); |
| } |
| } |
| |
| void |
| wmi_set_nodeage(struct wmi_t *wmip, A_UINT32 nodeAge) |
| { |
| wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge); |
| } |
| |
| bss_t * |
| wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid, |
| A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID) |
| { |
| bss_t *node = NULL; |
| node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid, |
| ssidLength, bIsWPA2, bMatchSSID); |
| return node; |
| } |
| |
| |
| #ifdef THREAD_X |
| void |
| wmi_refresh_scan_table (struct wmi_t *wmip) |
| { |
| wlan_refresh_inactive_nodes (&wmip->wmi_scan_table); |
| } |
| #endif |
| |
| 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; |
| } |
| |
| void |
| wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr) |
| { |
| bss_t *ni=NULL; |
| |
| ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); |
| if (ni != NULL) { |
| wlan_node_reclaim(&wmip->wmi_scan_table, ni); |
| } |
| |
| return; |
| } |
| |
| 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%lx\n", DBGARG, (unsigned long)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, reply->bssidList[0]); |
| |
| return A_OK; |
| } |
| |
| |
| static A_STATUS |
| wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len) |
| { |
| WMI_SET_PARAMS_REPLY *reply; |
| |
| if (len < sizeof(WMI_SET_PARAMS_REPLY)) { |
| return A_EINVAL; |
| } |
| reply = (WMI_SET_PARAMS_REPLY *)datap; |
| |
| if (A_OK == reply->status) |
| { |
| |
| } |
| else |
| { |
| |
| } |
| |
| return A_OK; |
| } |
| |
| |
| |
| static A_STATUS |
| wmi_acm_reject_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len) |
| { |
| WMI_ACM_REJECT_EVENT *ev; |
| |
| ev = (WMI_ACM_REJECT_EVENT *)datap; |
| wmip->wmi_traffic_class = ev->trafficClass; |
| printk("ACM REJECT %d\n",wmip->wmi_traffic_class); |
| 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; |
| A_UINT32 size; |
| |
| size = sizeof(*data_reply) + length; |
| |
| if (size <= length) { |
| return A_ERROR; |
| } |
| |
| 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)) { |
| A_NETBUF_FREE(osbuf); |
| 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)); |
| } |
| |
| #if defined(CONFIG_TARGET_PROFILE_SUPPORT) |
| A_STATUS |
| wmi_prof_cfg_cmd(struct wmi_t *wmip, |
| A_UINT32 period, |
| A_UINT32 nbins) |
| { |
| void *osbuf; |
| WMIX_PROF_CFG_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMIX_PROF_CFG_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->period = period; |
| cmd->nbins = nbins; |
| |
| return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr) |
| { |
| void *osbuf; |
| WMIX_PROF_ADDR_SET_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMIX_PROF_ADDR_SET_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->addr = addr; |
| |
| return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_prof_start_cmd(struct wmi_t *wmip) |
| { |
| return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID); |
| } |
| |
| A_STATUS |
| wmi_prof_stop_cmd(struct wmi_t *wmip) |
| { |
| return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID); |
| } |
| |
| A_STATUS |
| wmi_prof_count_get_cmd(struct wmi_t *wmip) |
| { |
| return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID); |
| } |
| |
| /* Called to handle WMIX_PROF_CONT_EVENTID */ |
| static A_STATUS |
| wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap; |
| |
| A_DPRINTF(DBG_WMI, |
| (DBGFMT "Enter - addr=0x%x count=%d\n", DBGARG, |
| prof_data->addr, prof_data->count)); |
| |
| A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count); |
| |
| return A_OK; |
| } |
| #endif /* CONFIG_TARGET_PROFILE_SUPPORT */ |
| |
| #ifdef OS_ROAM_MANAGEMENT |
| |
| #define ETHERNET_MAC_ADDRESS_LENGTH 6 |
| |
| void |
| wmi_scan_indication (struct wmi_t *wmip) |
| { |
| struct ieee80211_node_table *nt; |
| A_UINT32 gen; |
| A_UINT32 size; |
| A_UINT32 bsssize; |
| bss_t *bss; |
| A_UINT32 numbss; |
| PNDIS_802_11_BSSID_SCAN_INFO psi; |
| PBYTE pie; |
| NDIS_802_11_FIXED_IEs *pFixed; |
| NDIS_802_11_VARIABLE_IEs *pVar; |
| A_UINT32 RateSize; |
| |
| struct ar6kScanIndication |
| { |
| NDIS_802_11_STATUS_INDICATION ind; |
| NDIS_802_11_BSSID_SCAN_INFO_LIST slist; |
| } *pAr6kScanIndEvent; |
| |
| nt = &wmip->wmi_scan_table; |
| |
| ++nt->nt_si_gen; |
| |
| |
| gen = nt->nt_si_gen; |
| |
| size = offsetof(struct ar6kScanIndication, slist) + |
| offsetof(NDIS_802_11_BSSID_SCAN_INFO_LIST, BssidScanInfo); |
| |
| numbss = 0; |
| |
| IEEE80211_NODE_LOCK(nt); |
| |
| //calc size |
| for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { |
| if (bss->ni_si_gen != gen) { |
| bsssize = offsetof(NDIS_802_11_BSSID_SCAN_INFO, Bssid) + offsetof(NDIS_WLAN_BSSID_EX, IEs); |
| bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); |
| |
| #ifdef SUPPORT_WPA2 |
| if (bss->ni_cie.ie_rsn) { |
| bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; |
| } |
| #endif |
| if (bss->ni_cie.ie_wpa) { |
| bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; |
| } |
| |
| // bsssize must be a multiple of 4 to maintain alignment. |
| bsssize = (bsssize + 3) & ~3; |
| |
| size += bsssize; |
| |
| numbss++; |
| } |
| } |
| |
| if (0 == numbss) |
| { |
| // RETAILMSG(1, (L"AR6K: scan indication: 0 bss\n")); |
| ar6000_scan_indication (wmip->wmi_devt, NULL, 0); |
| IEEE80211_NODE_UNLOCK (nt); |
| return; |
| } |
| |
| pAr6kScanIndEvent = A_MALLOC(size); |
| |
| if (NULL == pAr6kScanIndEvent) |
| { |
| IEEE80211_NODE_UNLOCK(nt); |
| return; |
| } |
| |
| A_MEMZERO(pAr6kScanIndEvent, size); |
| |
| //copy data |
| pAr6kScanIndEvent->ind.StatusType = Ndis802_11StatusType_BssidScanInfoList; |
| pAr6kScanIndEvent->slist.Version = 1; |
| pAr6kScanIndEvent->slist.NumItems = numbss; |
| |
| psi = &pAr6kScanIndEvent->slist.BssidScanInfo[0]; |
| |
| for (bss = nt->nt_node_first; bss; bss = bss->ni_list_next) { |
| if (bss->ni_si_gen != gen) { |
| |
| bss->ni_si_gen = gen; |
| |
| //Set scan time |
| psi->ScanTime = bss->ni_tstamp - WLAN_NODE_INACT_TIMEOUT_MSEC; |
| |
| // Copy data to bssid_ex |
| bsssize = offsetof(NDIS_WLAN_BSSID_EX, IEs); |
| bsssize = bsssize + sizeof(NDIS_802_11_FIXED_IEs); |
| |
| #ifdef SUPPORT_WPA2 |
| if (bss->ni_cie.ie_rsn) { |
| bsssize = bsssize + bss->ni_cie.ie_rsn[1] + 2; |
| } |
| #endif |
| if (bss->ni_cie.ie_wpa) { |
| bsssize = bsssize + bss->ni_cie.ie_wpa[1] + 2; |
| } |
| |
| // bsssize must be a multiple of 4 to maintain alignment. |
| bsssize = (bsssize + 3) & ~3; |
| |
| psi->Bssid.Length = bsssize; |
| |
| memcpy (psi->Bssid.MacAddress, bss->ni_macaddr, ETHERNET_MAC_ADDRESS_LENGTH); |
| |
| |
| //if (((bss->ni_macaddr[3] == 0xCE) && (bss->ni_macaddr[4] == 0xF0) && (bss->ni_macaddr[5] == 0xE7)) || |
| // ((bss->ni_macaddr[3] == 0x03) && (bss->ni_macaddr[4] == 0xE2) && (bss->ni_macaddr[5] == 0x70))) |
| // RETAILMSG (1, (L"%x\n",bss->ni_macaddr[5])); |
| |
| psi->Bssid.Ssid.SsidLength = 0; |
| pie = bss->ni_cie.ie_ssid; |
| |
| if (pie) { |
| // Format of SSID IE is: |
| // Type (1 octet) |
| // Length (1 octet) |
| // SSID (Length octets) |
| // |
| // Validation of the IE should have occurred within WMI. |
| // |
| if (pie[1] <= 32) { |
| psi->Bssid.Ssid.SsidLength = pie[1]; |
| memcpy(psi->Bssid.Ssid.Ssid, &pie[2], psi->Bssid.Ssid.SsidLength); |
| } |
| } |
| psi->Bssid.Privacy = (bss->ni_cie.ie_capInfo & 0x10) ? 1 : 0; |
| |
| //Post the RSSI value relative to the Standard Noise floor value. |
| psi->Bssid.Rssi = bss->ni_rssi; |
| |
| if (bss->ni_cie.ie_chan >= 2412 && bss->ni_cie.ie_chan <= 2484) { |
| |
| if (bss->ni_cie.ie_rates && bss->ni_cie.ie_xrates) { |
| psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM24; |
| } |
| else { |
| psi->Bssid.NetworkTypeInUse = Ndis802_11DS; |
| } |
| } |
| else { |
| psi->Bssid.NetworkTypeInUse = Ndis802_11OFDM5; |
| } |
| |
| psi->Bssid.Configuration.Length = sizeof(psi->Bssid.Configuration); |
| psi->Bssid.Configuration.BeaconPeriod = bss->ni_cie.ie_beaconInt; // Units are Kmicroseconds (1024 us) |
| psi->Bssid.Configuration.ATIMWindow = 0; |
| psi->Bssid.Configuration.DSConfig = bss->ni_cie.ie_chan * 1000; |
| psi->Bssid.InfrastructureMode = ((bss->ni_cie.ie_capInfo & 0x03) == 0x01 ) ? Ndis802_11Infrastructure : Ndis802_11IBSS; |
| |
| RateSize = 0; |
| pie = bss->ni_cie.ie_rates; |
| if (pie) { |
| RateSize = (pie[1] < NDIS_802_11_LENGTH_RATES_EX) ? pie[1] : NDIS_802_11_LENGTH_RATES_EX; |
| memcpy(psi->Bssid.SupportedRates, &pie[2], RateSize); |
| } |
| pie = bss->ni_cie.ie_xrates; |
| if (pie && RateSize < NDIS_802_11_LENGTH_RATES_EX) { |
| memcpy(psi->Bssid.SupportedRates + RateSize, &pie[2], |
| (pie[1] < (NDIS_802_11_LENGTH_RATES_EX - RateSize)) ? pie[1] : (NDIS_802_11_LENGTH_RATES_EX - RateSize)); |
| } |
| |
| // Copy the fixed IEs |
| psi->Bssid.IELength = sizeof(NDIS_802_11_FIXED_IEs); |
| |
| pFixed = (NDIS_802_11_FIXED_IEs *)psi->Bssid.IEs; |
| memcpy(pFixed->Timestamp, bss->ni_cie.ie_tstamp, sizeof(pFixed->Timestamp)); |
| pFixed->BeaconInterval = bss->ni_cie.ie_beaconInt; |
| pFixed->Capabilities = bss->ni_cie.ie_capInfo; |
| |
| // Copy selected variable IEs |
| |
| pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pFixed + sizeof(NDIS_802_11_FIXED_IEs)); |
| |
| #ifdef SUPPORT_WPA2 |
| // Copy the WPAv2 IE |
| if (bss->ni_cie.ie_rsn) { |
| pie = bss->ni_cie.ie_rsn; |
| psi->Bssid.IELength += pie[1] + 2; |
| memcpy(pVar, pie, pie[1] + 2); |
| pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); |
| } |
| #endif |
| // Copy the WPAv1 IE |
| if (bss->ni_cie.ie_wpa) { |
| pie = bss->ni_cie.ie_wpa; |
| psi->Bssid.IELength += pie[1] + 2; |
| memcpy(pVar, pie, pie[1] + 2); |
| pVar = (NDIS_802_11_VARIABLE_IEs *)((PBYTE)pVar + pie[1] + 2); |
| } |
| |
| // Advance buffer pointer |
| psi = (PNDIS_802_11_BSSID_SCAN_INFO)((BYTE*)psi + bsssize + FIELD_OFFSET(NDIS_802_11_BSSID_SCAN_INFO, Bssid)); |
| } |
| } |
| |
| IEEE80211_NODE_UNLOCK(nt); |
| |
| // wmi_free_allnodes(wmip); |
| |
| // RETAILMSG(1, (L"AR6K: scan indication: %u bss\n", numbss)); |
| |
| ar6000_scan_indication (wmip->wmi_devt, pAr6kScanIndEvent, size); |
| |
| A_FREE(pAr6kScanIndEvent); |
| } |
| #endif |
| |
| A_UINT8 |
| ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, |
| A_UINT32 size) |
| { |
| A_UINT32 index; |
| A_UINT8 threshold = (A_UINT8)sq_thresh->upper_threshold[size - 1]; |
| |
| /* The list is already in sorted order. Get the next lower value */ |
| for (index = 0; index < size; index ++) { |
| if (rssi < sq_thresh->upper_threshold[index]) { |
| threshold = (A_UINT8)sq_thresh->upper_threshold[index]; |
| break; |
| } |
| } |
| |
| return threshold; |
| } |
| |
| A_UINT8 |
| ar6000_get_lower_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, |
| A_UINT32 size) |
| { |
| A_UINT32 index; |
| A_UINT8 threshold = (A_UINT8)sq_thresh->lower_threshold[size - 1]; |
| |
| /* The list is already in sorted order. Get the next lower value */ |
| for (index = 0; index < size; index ++) { |
| if (rssi > sq_thresh->lower_threshold[index]) { |
| threshold = (A_UINT8)sq_thresh->lower_threshold[index]; |
| break; |
| } |
| } |
| |
| return threshold; |
| } |
| static A_STATUS |
| wmi_send_rssi_threshold_params(struct wmi_t *wmip, |
| WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) |
| { |
| void *osbuf; |
| A_INT8 size; |
| WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd; |
| |
| 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)); |
| } |
| static A_STATUS |
| wmi_send_snr_threshold_params(struct wmi_t *wmip, |
| WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) |
| { |
| void *osbuf; |
| A_INT8 size; |
| WMI_SNR_THRESHOLD_PARAMS_CMD *cmd; |
| |
| 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_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd) |
| { |
| void *osbuf; |
| WMI_SET_TARGET_EVENT_REPORT_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_TARGET_EVENT_REPORT_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_TARGET_EVENT_REPORT_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| bss_t *wmi_rm_current_bss (struct wmi_t *wmip, A_UINT8 *id) |
| { |
| wmi_get_current_bssid (wmip, id); |
| return wlan_node_remove (&wmip->wmi_scan_table, id); |
| } |
| |
| A_STATUS wmi_add_current_bss (struct wmi_t *wmip, A_UINT8 *id, bss_t *bss) |
| { |
| wlan_setup_node (&wmip->wmi_scan_table, bss, id); |
| return A_OK; |
| } |
| |
| #ifdef ATH_AR6K_11N_SUPPORT |
| static A_STATUS |
| wmi_addba_req_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap; |
| |
| A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd); |
| |
| return A_OK; |
| } |
| |
| |
| static A_STATUS |
| wmi_addba_resp_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap; |
| |
| A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd); |
| |
| return A_OK; |
| } |
| |
| static A_STATUS |
| wmi_delba_req_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap; |
| |
| A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd); |
| |
| return A_OK; |
| } |
| |
| A_STATUS |
| wmi_btcoex_config_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len); |
| |
| return A_OK; |
| } |
| |
| |
| A_STATUS |
| wmi_btcoex_stats_event_rx(struct wmi_t * wmip,A_UINT8 * datap,int len) |
| { |
| A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); |
| |
| A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len); |
| |
| return A_OK; |
| |
| } |
| #endif |
| |
| static A_STATUS |
| wmi_hci_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap; |
| A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd); |
| |
| return A_OK; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| //// //// |
| //// AP mode functions //// |
| //// //// |
| //////////////////////////////////////////////////////////////////////////////// |
| /* |
| * IOCTL: AR6000_XIOCTL_AP_COMMIT_CONFIG |
| * |
| * When AR6K in AP mode, This command will be called after |
| * changing ssid, channel etc. It will pass the profile to |
| * target with a flag which will indicate which parameter changed, |
| * also if this flag is 0, there was no change in parametes, so |
| * commit cmd will not be sent to target. Without calling this IOCTL |
| * the changes will not take effect. |
| */ |
| A_STATUS |
| wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p) |
| { |
| void *osbuf; |
| WMI_CONNECT_CMD *cm; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cm)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cm)); |
| cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cm, sizeof(*cm)); |
| |
| A_MEMCPY(cm,p,sizeof(*cm)); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* |
| * IOCTL: AR6000_XIOCTL_AP_HIDDEN_SSID |
| * |
| * This command will be used to enable/disable hidden ssid functioanlity of |
| * beacon. If it is enabled, ssid will be NULL in beacon. |
| */ |
| A_STATUS |
| wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid) |
| { |
| void *osbuf; |
| WMI_AP_HIDDEN_SSID_CMD *hs; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_HIDDEN_SSID_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_HIDDEN_SSID_CMD)); |
| hs = (WMI_AP_HIDDEN_SSID_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(hs, sizeof(*hs)); |
| |
| hs->hidden_ssid = hidden_ssid; |
| |
| A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_HIDDEN_SSID %d\n", DBGARG , hidden_ssid)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_HIDDEN_SSID_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* |
| * IOCTL: AR6000_XIOCTL_AP_SET_MAX_NUM_STA |
| * |
| * This command is used to limit max num of STA that can connect |
| * with this AP. This value should not exceed AP_MAX_NUM_STA (this |
| * is max num of STA supported by AP). Value was already validated |
| * in ioctl.c |
| */ |
| A_STATUS |
| wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta) |
| { |
| void *osbuf; |
| WMI_AP_SET_NUM_STA_CMD *ns; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_NUM_STA_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_NUM_STA_CMD)); |
| ns = (WMI_AP_SET_NUM_STA_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(ns, sizeof(*ns)); |
| |
| ns->num_sta = num_sta; |
| |
| A_DPRINTF(DBG_WMI, (DBGFMT "AR6000_XIOCTL_AP_SET_MAX_NUM_STA %d\n", DBGARG , num_sta)); |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_NUM_STA_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* |
| * IOCTL: AR6000_XIOCTL_AP_SET_ACL_MAC |
| * |
| * This command is used to send list of mac of STAs which will |
| * be allowed to connect with this AP. When this list is empty |
| * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. |
| */ |
| A_STATUS |
| wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl) |
| { |
| void *osbuf; |
| WMI_AP_ACL_MAC_CMD *a; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_MAC_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD)); |
| a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(a, sizeof(*a)); |
| A_MEMCPY(a,acl,sizeof(*acl)); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* |
| * IOCTL: AR6000_XIOCTL_AP_SET_MLME |
| * |
| * This command is used to send list of mac of STAs which will |
| * be allowed to connect with this AP. When this list is empty |
| * firware will allow all STAs till the count reaches AP_MAX_NUM_STA. |
| */ |
| A_STATUS |
| wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason) |
| { |
| void *osbuf; |
| WMI_AP_SET_MLME_CMD *mlme; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_MLME_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_MLME_CMD)); |
| mlme = (WMI_AP_SET_MLME_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(mlme, sizeof(*mlme)); |
| |
| mlme->cmd = cmd; |
| A_MEMCPY(mlme->mac, mac, ATH_MAC_LEN); |
| mlme->reason = reason; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| static A_STATUS |
| wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) |
| { |
| WMI_PSPOLL_EVENT *ev; |
| |
| if (len < sizeof(WMI_PSPOLL_EVENT)) { |
| return A_EINVAL; |
| } |
| ev = (WMI_PSPOLL_EVENT *)datap; |
| |
| A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid); |
| return A_OK; |
| } |
| |
| static A_STATUS |
| wmi_dtimexpiry_event_rx(struct wmi_t *wmip, A_UINT8 *datap,int len) |
| { |
| A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt); |
| return A_OK; |
| } |
| |
| #ifdef WAPI_ENABLE |
| static A_STATUS |
| wmi_wapi_rekey_event_rx(struct wmi_t *wmip, A_UINT8 *datap,int len) |
| { |
| A_UINT8 *ev; |
| |
| if (len < 7) { |
| return A_EINVAL; |
| } |
| ev = (A_UINT8 *)datap; |
| |
| A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]); |
| return A_OK; |
| } |
| #endif |
| |
| A_STATUS |
| wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag) |
| { |
| WMI_AP_SET_PVB_CMD *cmd; |
| void *osbuf = NULL; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_PVB_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_PVB_CMD)); |
| cmd = (WMI_AP_SET_PVB_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| cmd->aid = aid; |
| cmd->flag = flag; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period) |
| { |
| WMI_AP_CONN_INACT_CMD *cmd; |
| void *osbuf = NULL; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_CONN_INACT_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_CONN_INACT_CMD)); |
| cmd = (WMI_AP_CONN_INACT_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| cmd->period = period; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell) |
| { |
| WMI_AP_PROT_SCAN_TIME_CMD *cmd; |
| void *osbuf = NULL; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_PROT_SCAN_TIME_CMD)); |
| cmd = (WMI_AP_PROT_SCAN_TIME_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| cmd->period_min = period; |
| cmd->dwell_ms = dwell; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim) |
| { |
| WMI_AP_SET_DTIM_CMD *cmd; |
| void *osbuf = NULL; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_DTIM_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_DTIM_CMD)); |
| cmd = (WMI_AP_SET_DTIM_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| |
| cmd->dtim = dtim; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| /* |
| * IOCTL: AR6000_XIOCTL_AP_SET_ACL_POLICY |
| * |
| * This command is used to set ACL policay. While changing policy, if you |
| * want to retain the existing MAC addresses in the ACL list, policy should be |
| * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared. |
| * If there is no chage in policy, the list will be intact. |
| */ |
| A_STATUS |
| wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy) |
| { |
| void *osbuf; |
| WMI_AP_ACL_POLICY_CMD *po; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_ACL_POLICY_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_POLICY_CMD)); |
| po = (WMI_AP_ACL_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(po, sizeof(*po)); |
| |
| po->policy = policy; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset) |
| { |
| void *osbuf; |
| WMI_AP_SET_11BG_RATESET_CMD *rs; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_AP_SET_11BG_RATESET_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_AP_SET_11BG_RATESET_CMD)); |
| rs = (WMI_AP_SET_11BG_RATESET_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(rs, sizeof(*rs)); |
| |
| rs->rateset = rateset; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_11BG_RATESET_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| #ifdef ATH_AR6K_11N_SUPPORT |
| A_STATUS |
| wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd) |
| { |
| void *osbuf; |
| WMI_SET_HT_CAP_CMD *htCap; |
| A_UINT8 band; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*htCap)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*htCap)); |
| |
| band = (cmd->band)? A_BAND_5GHZ : A_BAND_24GHZ; |
| wmip->wmi_ht_allowed[band] = (cmd->enable)? 1:0; |
| |
| htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(htCap, sizeof(*htCap)); |
| A_MEMCPY(htCap, cmd, sizeof(*htCap)); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width) |
| { |
| void *osbuf; |
| WMI_SET_HT_OP_CMD *htInfo; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*htInfo)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*htInfo)); |
| |
| htInfo = (WMI_SET_HT_OP_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(htInfo, sizeof(*htInfo)); |
| htInfo->sta_chan_width = sta_chan_width; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_OP_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| #endif |
| |
| A_STATUS |
| wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray) |
| { |
| void *osbuf; |
| WMI_SET_TX_SELECT_RATES_CMD *pData; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*pData)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*pData)); |
| |
| pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMCPY(pData, pMaskArray, sizeof(*pData)); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| |
| A_STATUS |
| wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz) |
| { |
| void *osbuf; |
| WMI_HCI_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd) + sz); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd) + sz); |
| cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf)); |
| |
| cmd->cmd_buf_sz = sz; |
| A_MEMCPY(cmd->buf, buf, sz); |
| return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| #ifdef ATH_AR6K_11N_SUPPORT |
| A_STATUS |
| wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask) |
| { |
| void *osbuf; |
| WMI_ALLOW_AGGR_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_ALLOW_AGGR_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->tx_allow_aggr = tx_tidmask; |
| cmd->rx_allow_aggr = rx_tidmask; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid) |
| { |
| void *osbuf; |
| WMI_ADDBA_REQ_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_ADDBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->tid = tid; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink) |
| { |
| void *osbuf; |
| WMI_DELBA_REQ_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_DELBA_REQ_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->tid = tid; |
| cmd->is_sender_initiator = uplink; /* uplink =1 - uplink direction, 0=downlink direction */ |
| |
| /* Delete the local aggr state, on host */ |
| return (wmi_cmd_send(wmip, osbuf, WMI_DELBA_REQ_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| #endif |
| |
| A_STATUS |
| wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion, |
| A_BOOL rxDot11Hdr, A_BOOL defragOnHost) |
| { |
| void *osbuf; |
| WMI_RX_FRAME_FORMAT_CMD *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->dot11Hdr = (rxDot11Hdr==TRUE)? 1:0; |
| cmd->defragOnHost = (defragOnHost==TRUE)? 1:0; |
| cmd->metaVersion = rxMetaVersion; /* */ |
| |
| /* Delete the local aggr state, on host */ |
| return (wmi_cmd_send(wmip, osbuf, WMI_RX_FRAME_FORMAT_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| |
| A_STATUS |
| wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode) |
| { |
| void *osbuf; |
| WMI_SET_THIN_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_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf)); |
| cmd->enable = (bThinMode==TRUE)? 1:0; |
| |
| /* Delete the local aggr state, on host */ |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| |
| A_STATUS |
| wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence) |
| { |
| void *osbuf; |
| WMI_SET_BT_WLAN_CONN_PRECEDENCE *cmd; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(*cmd)); |
| |
| cmd = (WMI_SET_BT_WLAN_CONN_PRECEDENCE *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->precedence = precedence; |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk) |
| { |
| void *osbuf; |
| WMI_SET_PMK_CMD *p; |
| |
| osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_PMK_CMD)); |
| if (osbuf == NULL) { |
| return A_NO_MEMORY; |
| } |
| |
| A_NETBUF_PUT(osbuf, sizeof(WMI_SET_PMK_CMD)); |
| |
| p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(p, sizeof(*p)); |
| |
| A_MEMCPY(p->pmk, pmk, WMI_PMK_LEN); |
| |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG)); |
| } |
| |
| A_STATUS |
| wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 sgiMask, A_UINT8 sgiPERThreshold) |
| { |
| void *osbuf; |
| WMI_SET_TX_SGI_PARAM_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_SGI_PARAM_CMD *)(A_NETBUF_DATA(osbuf)); |
| A_MEMZERO(cmd, sizeof(*cmd)); |
| cmd->sgiMask = sgiMask; |
| cmd->sgiPERThreshold = sgiPERThreshold; |
| return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SGI_PARAM_CMDID, |
| NO_SYNC_WMIFLAG)); |
| } |
| |
| bss_t * |
| wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid, |
| A_UINT32 ssidLength, |
| A_UINT32 dot11AuthMode, A_UINT32 authMode, |
| A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp) |
| { |
| bss_t *node = NULL; |
| node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid, |
| ssidLength, dot11AuthMode, authMode, pairwiseCryptoType, grpwiseCryptoTyp); |
| |
| return node; |
| } |
| |
| A_UINT16 |
| wmi_ieee2freq (int chan) |
| { |
| A_UINT16 freq = 0; |
| freq = wlan_ieee2freq (chan); |
| return freq; |
| |
| } |
| |
| A_UINT32 |
| wmi_freq2ieee (A_UINT16 freq) |
| { |
| A_UINT16 chan = 0; |
| chan = wlan_freq2ieee (freq); |
| return chan; |
| } |