diff --git a/firmwares/bcm43439a0/structs.common.h b/firmwares/bcm43439a0/structs.common.h
index 6597d1cd1..9a5874743 100644
--- a/firmwares/bcm43439a0/structs.common.h
+++ b/firmwares/bcm43439a0/structs.common.h
@@ -9,6 +9,25 @@
#define PAD _XSTR(__LINE__)
#endif
+struct wl_rxsts {
+ uint pkterror;
+ uint phytype;
+ uint16 chanspec;
+ uint16 datarate;
+ uint8 mcs;
+ uint8 htflags;
+ uint antenna;
+ uint pktlength;
+ uint32 mactime;
+ uint sq;
+ int32 signal;
+ int32 noise;
+ uint preamble;
+ uint encoding;
+ uint nfrmtype;
+ struct wl_if *wlif;
+} __attribute__((packed));
+
struct sk_buff {
union { /* 0x000 */
uint32 u32;
@@ -953,6 +972,47 @@ struct wlc_hw_info {
uint32 PAD; /* 0x168 */
} __attribute__((packed));
+struct wlc_if_stats {
+ /* transmit stat counters */
+ uint32 txframe; /* tx data frames */
+ uint32 txbyte; /* tx data bytes */
+ uint32 txerror; /* tx data errors (derived: sum of others) */
+ uint32 txnobuf; /* tx out of buffer errors */
+ uint32 txrunt; /* tx runt frames */
+ uint32 txfail; /* tx failed frames */
+ uint32 rxframe; /* rx data frames */
+ uint32 rxbyte; /* rx data bytes */
+ uint32 rxerror; /* rx data errors (derived: sum of others) */
+ uint32 rxnobuf; /* rx out of buffer errors */
+ uint32 rxrunt; /* rx runt frames */
+ uint32 rxfragerr; /* rx fragment errors */
+ uint32 txretry; /* tx retry frames */
+ uint32 txretrie; /* tx multiple retry frames */
+ uint32 txfrmsnt; /* tx sent frames */
+ uint32 txmulti; /* tx mulitcast sent frames */
+ uint32 txfrag; /* tx fragments sent */
+ uint32 rxmulti; /* rx multicast frames */
+};
+
+struct wl_if {
+ struct wlc_if *wlcif;
+ struct hndrte_dev *dev;
+};
+
+struct wlc_if {
+ struct wlc_if *next;
+ uint8 type;
+ uint8 index;
+ uint8 flags;
+ struct wl_if *wlif;
+ void *qi;
+ union {
+ struct scb *scb;
+ struct wlc_bsscfg *bsscfg;
+ } u;
+ struct wlc_if_stats _cnt;
+};
+
struct wlc_info {
void *pub; /* 0x000 */
void *osh; /* 0x004 */
@@ -1083,7 +1143,7 @@ struct wlc_info {
uint32 PAD; /* 0x1f8 */
uint32 PAD; /* 0x1fc */
uint32 PAD; /* 0x200 */
- uint32 PAD; /* 0x204 */
+ uint32 monitor; /* 0x204 */
uint32 PAD; /* 0x208 */
uint32 PAD; /* 0x20c */
uint32 PAD; /* 0x210 */
@@ -1320,7 +1380,7 @@ struct wlc_info {
uint32 PAD; /* 0x5ac */
uint32 PAD; /* 0x5b0 */
uint32 PAD; /* 0x5b4 */
- uint32 PAD; /* 0x5b8 */
+ struct wlc_if *wlcif_list; /* 0x5b8 */
uint32 PAD; /* 0x5bc */
uint32 PAD; /* 0x5c0 */
uint32 PAD; /* 0x5c4 */
diff --git a/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/brcm.h b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/brcm.h
new file mode 100644
index 000000000..d86e49f52
--- /dev/null
+++ b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/brcm.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * *
+ * ########### ########### ########## ########## *
+ * ############ ############ ############ ############ *
+ * ## ## ## ## ## ## ## *
+ * ## ## ## ## ## ## ## *
+ * ########### #### ###### ## ## ## ## ###### *
+ * ########### #### # ## ## ## ## # # *
+ * ## ## ###### ## ## ## ## # # *
+ * ## ## # ## ## ## ## # # *
+ * ############ ##### ###### ## ## ## ##### ###### *
+ * ########### ########### ## ## ## ########## *
+ * *
+ * S E C U R E M O B I L E N E T W O R K I N G *
+ * *
+ * This file is part of NexMon. *
+ * *
+ * Copyright (c) 2016 NexMon Team *
+ * *
+ * NexMon is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * NexMon is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with NexMon. If not, see . *
+ * *
+ **************************************************************************/
+
+#pragma once
+
+#include "../include/types.h"
+#define WL_CHANSPEC_CHAN_MASK 0x00ff
+#define CHSPEC_CHANNEL(chspec) ((uint8_t)((chspec) & WL_CHANSPEC_CHAN_MASK))
diff --git a/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/d11.h b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/d11.h
new file mode 100644
index 000000000..98905fbbc
--- /dev/null
+++ b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/d11.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * *
+ * ########### ########### ########## ########## *
+ * ############ ############ ############ ############ *
+ * ## ## ## ## ## ## ## *
+ * ## ## ## ## ## ## ## *
+ * ########### #### ###### ## ## ## ## ###### *
+ * ########### #### # ## ## ## ## # # *
+ * ## ## ###### ## ## ## ## # # *
+ * ## ## # ## ## ## ## # # *
+ * ############ ##### ###### ## ## ## ##### ###### *
+ * ########### ########### ## ## ## ########## *
+ * *
+ * S E C U R E M O B I L E N E T W O R K I N G *
+ * *
+ * This file is part of NexMon. *
+ * *
+ * Copyright (c) 2016 NexMon Team *
+ * *
+ * NexMon is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * NexMon is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with NexMon. If not, see . *
+ * *
+ **************************************************************************/
+
+#pragma once
+
+struct d11rxhdr {
+ unsigned short RxFrameSize; /* Actual byte length of the frame data received */
+ unsigned short PAD;
+ unsigned short PhyRxStatus_0; /* PhyRxStatus 15:0 */
+ unsigned short PhyRxStatus_1; /* PhyRxStatus 31:16 */
+ unsigned short PhyRxStatus_2; /* PhyRxStatus 47:32 */
+ unsigned short PhyRxStatus_3; /* PhyRxStatus 63:48 */
+ unsigned short PhyRxStatus_4; /* PhyRxStatus 79:64 */
+ unsigned short PhyRxStatus_5; /* PhyRxStatus 95:80 */
+ unsigned short RxStatus1; /* MAC Rx status */
+ unsigned short RxStatus2; /* extended MAC Rx status */
+ unsigned short RxTSFTime; /* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
+ unsigned short RxChan; /* gain code, channel radio code, and phy type -> looks like chanspec */
+} __attribute__((packed));
+
+ /* ucode RxStatus1: */
+#define RXS_BCNSENT 0x8000
+#define RXS_SECKINDX_MASK 0x07e0
+#define RXS_SECKINDX_SHIFT 5
+#define RXS_DECERR (1 << 4)
+#define RXS_DECATMPT (1 << 3)
+/* PAD bytes to make IP data 4 bytes aligned */
+#define RXS_PBPRES (1 << 2)
+#define RXS_RESPFRAMETX (1 << 1)
+#define RXS_FCSERR (1 << 0)
+
+/* ucode RxStatus2: */
+#define RXS_AMSDU_MASK 1
+#define RXS_AGGTYPE_MASK 0x6
+#define RXS_AGGTYPE_SHIFT 1
+#define RXS_PHYRXST_VALID (1 << 8)
+#define RXS_RXANT_MASK 0x3
+#define RXS_RXANT_SHIFT 12
+
+/* RxChan */
+#define RXS_CHAN_40 0x1000
+#define RXS_CHAN_5G 0x0800
+#define RXS_CHAN_ID_MASK 0x07f8
+#define RXS_CHAN_ID_SHIFT 3
+#define RXS_CHAN_PHYTYPE_MASK 0x0007
+#define RXS_CHAN_PHYTYPE_SHIFT 0
+
+struct wlc_d11rxhdr {
+ struct d11rxhdr rxhdr;
+ unsigned int tsf_l;
+ char rssi; /* computed instanteneous RSSI in BMAC */
+ char rxpwr0;
+ char rxpwr1;
+ char do_rssi_ma; /* do per-pkt sampling for per-antenna ma in HIGH */
+ char rxpwr[4]; /* rssi for supported antennas */
+} __attribute__((packed));
+
diff --git a/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/local_wrapper.h b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/local_wrapper.h
new file mode 100644
index 000000000..f903f57e1
--- /dev/null
+++ b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/include/local_wrapper.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * *
+ * ########### ########### ########## ########## *
+ * ############ ############ ############ ############ *
+ * ## ## ## ## ## ## ## *
+ * ## ## ## ## ## ## ## *
+ * ########### #### ###### ## ## ## ## ###### *
+ * ########### #### # ## ## ## ## # # *
+ * ## ## ###### ## ## ## ## # # *
+ * ## ## # ## ## ## ## # # *
+ * ############ ##### ###### ## ## ## ##### ###### *
+ * ########### ########### ## ## ## ########## *
+ * *
+ * S E C U R E M O B I L E N E T W O R K I N G *
+ * *
+ * This file is part of NexMon. *
+ * *
+ * Copyright (c) 2016 NexMon Team *
+ * *
+ * NexMon is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * NexMon is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with NexMon. If not, see . *
+ * *
+ **************************************************************************/
+
+#ifndef LOCAL_WRAPPER_H
+#define LOCAL_WRAPPER_H
+
+#include "../src/local_wrapper.c" // wrapper definitions for functions that already exist in the firmware
+
+#endif /*LOCAL_WRAPPER_H*/
diff --git a/patches/bcm43439a0/7_95_49_2271bb6/nexmon/src/monitormode.c b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/src/monitormode.c
new file mode 100644
index 000000000..7bf82c4d1
--- /dev/null
+++ b/patches/bcm43439a0/7_95_49_2271bb6/nexmon/src/monitormode.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * *
+ * ########### ########### ########## ########## *
+ * ############ ############ ############ ############ *
+ * ## ## ## ## ## ## ## *
+ * ## ## ## ## ## ## ## *
+ * ########### #### ###### ## ## ## ## ###### *
+ * ########### #### # ## ## ## ## # # *
+ * ## ## ###### ## ## ## ## # # *
+ * ## ## # ## ## ## ## # # *
+ * ############ ##### ###### ## ## ## ##### ###### *
+ * ########### ########### ## ## ## ########## *
+ * *
+ * S E C U R E M O B I L E N E T W O R K I N G *
+ * *
+ * This file is part of NexMon. *
+ * *
+ * Copyright (c) 2016 NexMon Team *
+ * *
+ * NexMon is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * NexMon is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with NexMon. If not, see . *
+ * *
+ **************************************************************************/
+
+#pragma NEXMON targetregion "patch"
+
+#include
+#include // wrapper definitions for functions that already exist in the firmware
+#include // structures that are used by the code in the firmware
+#include
+#include
+#include "d11.h"
+#include "brcm.h"
+
+//#define RADIOTAP_MCS
+#include
+
+#define MONITOR_DISABLED 0
+#define MONITOR_IEEE80211 1
+#define MONITOR_RADIOTAP 2
+#define MONITOR_LOG_ONLY 3
+#define MONITOR_DROP_FRM 4
+#define MONITOR_IPV4_UDP 5
+
+void
+wl_monitor_radiotap(struct wl_info *wl, struct wl_rxsts *sts, struct sk_buff *p) {
+ struct sk_buff *p_new = pkt_buf_get_skb(wl->wlc->osh, p->len + sizeof(struct nexmon_radiotap_header));
+ struct nexmon_radiotap_header *frame = (struct nexmon_radiotap_header *) p_new->data;
+ struct tsf tsf;
+ wlc_bmac_read_tsf(wl->wlc_hw, &tsf.tsf_l, &tsf.tsf_h);
+
+ frame->header.it_version = 0;
+ frame->header.it_pad = 0;
+ frame->header.it_len = sizeof(struct nexmon_radiotap_header);
+ frame->header.it_present =
+ (1<tsf.tsf_l = tsf.tsf_l;
+ frame->tsf.tsf_h = tsf.tsf_h;
+ frame->flags = IEEE80211_RADIOTAP_F_FCS;
+ frame->chan_freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(sts->chanspec));
+ frame->chan_flags = 0;
+ frame->dbm_antsignal = sts->signal;
+
+ memcpy(p_new->data + sizeof(struct nexmon_radiotap_header), p->data + 6, p->len - 6);
+
+ p_new->len -= 6;
+
+ if (wl->wlc->wlcif_list->next)
+ wl->wlc->wlcif_list->wlif->dev->chained->funcs->xmit(wl->wlc->wlcif_list->wlif->dev, wl->wlc->wlcif_list->wlif->dev->chained, p_new);
+ else
+ wl->dev->chained->funcs->xmit(wl->dev, wl->dev->chained, p_new);
+}
+
+void
+wl_monitor_hook(struct wl_info *wl, struct wl_rxsts *sts, struct sk_buff *p) {
+ switch(wl->wlc->monitor & 0xFF) {
+ case MONITOR_RADIOTAP:
+ wl_monitor_radiotap(wl, sts, p);
+ break;
+
+ case MONITOR_IEEE80211:
+ wl_monitor(wl, sts, p);
+ break;
+
+ case MONITOR_LOG_ONLY:
+ printf("frame received\n");
+ break;
+
+ case MONITOR_DROP_FRM:
+ break;
+
+ case MONITOR_IPV4_UDP:
+ printf("%s: udp tunneling not implemented\n");
+ // not implemented yet
+ break;
+ }
+}
+
+__attribute__((at(0x81F6D6, "flashpatch", CHIP_VER_BCM43439a0, FW_VER_ALL)))
+BLPatch(flash_patch_76, wl_monitor_hook);
diff --git a/patches/common/wrapper.c b/patches/common/wrapper.c
index 112ac397f..3909fe201 100644
--- a/patches/common/wrapper.c
+++ b/patches/common/wrapper.c
@@ -374,6 +374,7 @@ AT(CHIP_VER_BCM43909b0, FW_VER_ALL, 0x646B8)
AT(CHIP_VER_BCM4361b0, FW_VER_13_38_55_1_sta, 0x177954)
AT(CHIP_VER_BCM4366c0, FW_VER_10_10_122_20, 0x205B50)
AT(CHIP_VER_BCM43436b0, FW_VER_ALL, 0x807C48)
+AT(CHIP_VER_BCM43439a0, FW_VER_ALL, 0x8928FC)
void *
pkt_buf_get_skb(void *osh, unsigned int len)
RETURN_DUMMY
@@ -690,6 +691,7 @@ AT(CHIP_VER_BCM43438, FW_VER_7_45_41_26_r640327, 0x1BEAC)
AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_26_r640327, 0x1BEAC)
AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x1C0F8)
AT(CHIP_VER_BCM43436b0, FW_VER_9_88_4_65, 0x1B242)
+AT(CHIP_VER_BCM43439a0, FW_VER_ALL, 0x84F3E0)
void
wlc_bmac_read_tsf(void *wlc_hw, unsigned int *tsf_l_ptr, unsigned int *tsf_h_ptr)
VOID_DUMMY
@@ -902,6 +904,7 @@ AT(CHIP_VER_BCM43455, FW_VER_ALL, 0x1ED5C)
AT(CHIP_VER_BCM43455c0, FW_VER_7_45_154, 0x1A270C)
AT(CHIP_VER_BCM43455c0, FW_VER_7_45_189, 0x1A7490)
AT(CHIP_VER_BCM43436b0, FW_VER_9_88_4_65, 0xae0a)
+AT(CHIP_VER_BCM43439a0, FW_VER_ALL, 0x818838)
void
wl_monitor(void *wl, void *sts, void *p)
VOID_DUMMY
@@ -921,6 +924,7 @@ AT(CHIP_VER_BCM4361b0, FW_VER_13_38_55_1_sta, 0x1D96B8)
AT(CHIP_VER_BCM43455c0, FW_VER_ALL, 0x9C59C)
AT(CHIP_VER_BCM4358, FW_VER_7_112_300_14, 0x1A6C84)
AT(CHIP_VER_BCM4366c0, FW_VER_10_10_122_20, 0x26CC08)
+AT(CHIP_VER_BCM43439a0, FW_VER_ALL, 0x82ED70)
void *
wlc_recv(void *wlc, void *p)
RETURN_DUMMY
@@ -1435,6 +1439,7 @@ AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_26_r640327, 0x23278)
AT(CHIP_VER_BCM43430a1, FW_VER_7_45_41_46, 0x236a4)
AT(CHIP_VER_BCM4330, FW_VER_ALL, 0x826F3C)
AT(CHIP_VER_BCM43436b0, FW_VER_9_88_4_65, 0x8644)
+AT(CHIP_VER_BCM43439a0, FW_VER_ALL, 0x86C37C)
int
wlc_phy_channel2freq(unsigned int channel)
RETURN_DUMMY