/**
* This file contains the handling of command
* responses as well as events generated by firmware.
*/
#include <linux/delay.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
#include <net/iw_handler.h>
#include "host.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "join.h"
#include "wext.h"
/**
* @brief This function handles disconnect event. it
* reports disconnect to upper layer, clean tx/rx packets,
* reset link state etc.
*
* @param priv A pointer to wlan_private structure
* @return n/a
*/
void libertas_mac_event_disconnected(wlan_private * priv)
{
wlan_adapter *adapter = priv->adapter;
union iwreq_data wrqu;
if (adapter->connect_status != LIBERTAS_CONNECTED)
return;
lbs_deb_enter(LBS_DEB_CMD);
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
/*
* Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
* It causes problem in the Supplicant
*/
msleep_interruptible(1000);
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
/* Free Tx and Rx packets */
kfree_skb(priv->adapter->currenttxskb);
priv->adapter->currenttxskb = NULL;
/* report disconnect to upper layer */
netif_stop_queue(priv->dev);
netif_carrier_off(priv->dev);
/* reset SNR/NF/RSSI values */
memset(adapter->SNR, 0x00, sizeof(adapter->SNR));
memset(adapter->NF, 0x00, sizeof(adapter->NF));
memset(adapter->RSSI, 0x00, sizeof(adapter->RSSI));
memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
adapter->nextSNRNF = 0;
adapter->numSNRNF = 0;
lbs_deb_cmd("current SSID '%s', length %u\n",
escape_essid(adapter->curbssparams.ssid,
adapter->curbssparams.ssid_len),
adapter->curbssparams.ssid_len);
adapter->connect_status = LIBERTAS_DISCONNECTED;
/* Clear out associated SSID and BSSID since connection is
* no longer valid.
*/
memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
adapter->curbssparams.ssid_len = 0;
if (adapter->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
lbs_deb_cmd("disconnected, so exit PS mode\n");
libertas_ps_wakeup(priv, 0);
}
lbs_deb_leave(LBS_DEB_CMD);
}
/**
* @brief This function handles MIC failure event.
*
* @param priv A pointer to wlan_private structure
* @para event the event id
* @return n/a
*/
static void handle_mic_failureevent(wlan_private * priv, u32 event)
{
char buf[50];
lbs_deb_enter(LBS_DEB_CMD);
memset(buf, 0, sizeof(buf));
sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
strcat(buf, "unicast ");
} else {
strcat(buf, "multicast ");
}
libertas_send_iwevcustom_event(priv, buf);
lbs_deb_leave(LBS_DEB_CMD);
}
static int wlan_ret_reg_access(wlan_private * priv,
u16 type, struct cmd_ds_command *resp)
{
int ret = 0;
wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
switch (type) {
case CMD_RET(CMD_MAC_REG_ACCESS):
{
struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
adapter->offsetvalue.value = le32_to_cpu(reg->value);
break;
}
case CMD_RET(CMD_BBP_REG_ACCESS):
{
struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
adapter->offsetvalue.value = reg->value;
break;
}
case CMD_RET(CMD_RF_REG_ACCESS):
{
struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
adapter->offsetvalue.value = reg->value;
break;
}
default:
ret = -1;
}
lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}