#ifdef __RTOS__ #include #include #include #include #include #include #include #include #include #include #else #include #include #include #include #include #include #include #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; }