0
0
Fork 0
hgicf/hgic_fmac/event.c

196 lines
7 KiB
C

#ifdef __RTOS__
#include <linux/types.h>
#include <linux/unaligned.h>
#include <linux/bitops.h>
#include <linux/jiffies.h>
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#else
#include <linux/version.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/net.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
#endif
#include "hgicf.h"
#include "../utils/fwctrl.h"
#include "cfg.h"
#include "event.h"
char *hgicf_hw_state(int state)
{
switch (state) {
case HGICF_HW_DISCONNECTED:
return "Disconnect";
case HGICF_HW_DISABLED:
return "DISABLED";
case HGICF_HW_INACTIVE:
return "INACTIVE";
case HGICF_HW_SCANNING:
return "SCANNING";
case HGICF_HW_AUTHENTICATING:
return "AUTHENTICATING";
case HGICF_HW_ASSOCIATING:
return "ASSOCIATING";
case HGICF_HW_ASSOCIATED:
return "ASSOCIATED";
case HGICF_HW_4WAY_HANDSHAKE:
return "4WAY_HANDSHAKE";
case HGICF_HW_GROUP_HANDSHAKE:
return "GROUP_HANDSHAKE";
case HGICF_HW_CONNECTED:
return "CONNECTED";
default:
return "Unknown";
}
}
int hgicf_rx_fw_event(struct hgicf_wdev *hg, struct sk_buff *skb)
{
char drop = 1;
char *data = NULL;
u32 evt_id = 0;
struct hgic_ctrl_hdr *evt = NULL;
struct hgicf_vif *vif = NULL;
if (skb == NULL || skb->dev == NULL || skb->len < sizeof(struct hgic_ctrl_hdr)) {
dev_kfree_skb(skb);
return -1;
}
vif = (struct hgicf_vif *)netdev_priv(skb->dev);
evt = (struct hgic_ctrl_hdr *)skb->data;
skb_pull(skb, sizeof(struct hgic_ctrl_hdr));
data = skb->data;
evt_id = HDR_EVTID(evt);
//hgic_dbg("event id:%d\r\n", evt->event.event_id);
switch (evt_id) {
case HGIC_EVENT_STATE_CHG:
vif->hw_state = data[0];
switch (vif->hw_state) {
case HGICF_HW_CONNECTED:
memcpy(vif->hw_bssid, data + 1, ETH_ALEN);
break;
default:
break;
}
break;
case HGIC_EVENT_DISCONNECT_REASON:
memcpy(&vif->disconnect_reason, data, sizeof(int));
break;
case HGIC_EVENT_ASSOC_STATUS:
memcpy(&vif->assoc_status_code, data, sizeof(int));
break;
case HGIC_EVENT_SCANNING:
hgicf_event(hg, skb->dev->name, HGIC_EVENT_SCANNING, 0, 0);
break;
case HGIC_EVENT_SCAN_DONE:
hgicf_event(hg, skb->dev->name, HGIC_EVENT_SCAN_DONE, 0, 0);
break;
case HGIC_EVENT_TX_BITRATE:
hg->status.tx_bitrate = get_unaligned_le32((u8 *)(evt + 1));
hgicf_event(hg, skb->dev->name, HGIC_EVENT_TX_BITRATE, hg->status.tx_bitrate, 0);
break;
case HGIC_EVENT_PAIR_START:
hg->status.pair_state = 0;
memset(hg->pairing_sta, 0, 6);
hgicf_event(hg, skb->dev->name, HGIC_EVENT_PAIR_START, 0, 0);
break;
case HGIC_EVENT_PAIR_SUCCESS:
hg->status.pair_state = 1;
if(skb->len >= 6) memcpy(hg->pairing_sta, data, 6);
hgicf_event(hg, skb->dev->name, HGIC_EVENT_PAIR_SUCCESS, (long)hg->pairing_sta, 0);
break;
case HGIC_EVENT_PAIR_DONE:
hg->paired_stas_cnt = (evt->hdr.length - sizeof(struct hgic_ctrl_hdr)) / 6;
if (hg->paired_stas) {
kfree(hg->paired_stas);
}
hg->paired_stas = kzalloc(evt->hdr.length, GFP_KERNEL);
if (hg->paired_stas) {
memcpy(hg->paired_stas, data, hg->paired_stas_cnt * 6);
}
hgicf_event(hg, skb->dev->name, HGIC_EVENT_PAIR_DONE, (long)hg->paired_stas, (long)hg->paired_stas_cnt);
break;
case HGIC_EVENT_CONECT_START:
vif->hw_state = HGICF_HW_ASSOCIATING;
hgicf_event(hg, skb->dev->name, HGIC_EVENT_CONECT_START, 0, 0);
break;
case HGIC_EVENT_CONECTED:
vif->hw_state = HGICF_HW_CONNECTED;
hgicf_event(hg, skb->dev->name, HGIC_EVENT_CONECTED, (long)skb->data, skb->len);
break;
case HGIC_EVENT_DISCONECTED:
vif->hw_state = HGICF_HW_DISCONNECTED;
hgicf_event(hg, skb->dev->name, HGIC_EVENT_DISCONECTED, (long)skb->data, skb->len);
break;
case HGIC_EVENT_SIGNAL:
hg->status.signal = (s8)data[0];
hg->status.evm = (s8)data[1];
hgicf_event(hg, skb->dev->name, HGIC_EVENT_SIGNAL, hg->status.signal, hg->status.evm);
break;
case HGIC_EVENT_FWDBG_INFO:
hgicf_event(hg, skb->dev->name, HGIC_EVENT_FWDBG_INFO, (long)skb->data, skb->len);
#ifndef __RTOS__
printk("%s", skb->data);
if (skb_queue_len(&hg->dbginfo_q) > 4) {
kfree_skb(skb_dequeue(&hg->dbginfo_q));
}
skb_queue_tail(&hg->dbginfo_q, skb);
drop = 0;
#endif
break;
case HGIC_EVENT_REQUEST_PARAM:
schedule_work(&hg->ctrl.flush_work);
break;
case HGIC_EVENT_CUSTOMER_MGMT:
hgic_dbg("rx mgmt from %pM, %d bytes\r\n", data, skb->len - 6);
hgicf_event(hg, skb->dev->name, HGIC_EVENT_CUSTOMER_MGMT, (long)skb->data, skb->len);
#ifndef __RTOS__
if (skb_queue_len(&hg->custmgmt_q) > 16) {
kfree_skb(skb_dequeue(&hg->custmgmt_q));
}
skb_queue_tail(&hg->custmgmt_q, skb);
drop = 0;
#endif
break;
case HGIC_EVENT_CUST_DRIVER_DATA:
hgicf_event(hg, skb->dev->name, HGIC_EVENT_CUST_DRIVER_DATA, (long)skb->data, skb->len);
#ifndef __RTOS__
if (skb_queue_len(&hg->cust_driverdata_q) > 16) {
kfree_skb(skb_dequeue(&hg->cust_driverdata_q));
}
skb_queue_tail(&hg->cust_driverdata_q, skb);
drop = 0;
#endif
break;
case HGIC_EVENT_DHCPC_DONE:
#ifndef __RTOS__
memcpy(&hg->dhcpc, skb->data, sizeof(hg->dhcpc));
#endif
hgicf_event(hg, skb->dev->name, HGIC_EVENT_DHCPC_DONE, (long)skb->data, skb->len);
break;
case HGIC_EVENT_CONNECT_FAIL:
hg->status.conntect_fail = data[0];
hgicf_event(hg, skb->dev->name, HGIC_EVENT_CONNECT_FAIL, data[0], 0);
break;
case HGIC_EVENT_UNPAIR_STA:
hgic_dbg("unpair sta: %pM\r\n", data);
hgicf_event(hg, skb->dev->name, HGIC_EVENT_UNPAIR_STA, data, 0);
break;
default:
break;
}
if (drop) { dev_kfree_skb(skb); }
return 0;
}