197 lines
7 KiB
C
197 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;
|
||
|
}
|
||
|
|