nexmon – Rev 1
?pathlinks?
diff -Naur linux-2.6.23_orig/drivers/net/wireless/zd1211rw/zd_mac.c linux-2.6.23_rawtx/drivers/net/wireless/zd1211rw/zd_mac.c
--- linux-2.6.23_orig/drivers/net/wireless/zd1211rw/zd_mac.c 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23_rawtx/drivers/net/wireless/zd1211rw/zd_mac.c 2007-12-04 00:07:04.000000000 +0100
@@ -164,8 +164,17 @@
static int reset_mode(struct zd_mac *mac)
{
struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- u32 filter = (ieee->iw_mode == IW_MODE_MONITOR) ? ~0 : STA_RX_FILTER;
- return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
+ struct zd_ioreq32 ioreqs[] = {
+ { CR_RX_FILTER, STA_RX_FILTER },
+ { CR_SNIFFER_ON, 0U },
+ };
+
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ ioreqs[0].value = 0xffffffff;
+ ioreqs[1].value = 0x1;
+ }
+
+ return zd_iowrite32a(&mac->chip, ioreqs, ARRAY_SIZE(ioreqs));
}
int zd_mac_open(struct net_device *netdev)
@@ -211,7 +220,13 @@
goto disable_rx;
housekeeping_enable(mac);
- ieee80211softmac_start(netdev);
+ netif_carrier_on(netdev);
+ ieee80211softmac_start(netdev);
+ if(!netif_queue_stopped(netdev))
+ netif_start_queue(netdev);
+ else
+ netif_wake_queue(netdev);
+
return 0;
disable_rx:
zd_chip_disable_rx(chip);
@@ -778,6 +793,8 @@
struct ieee80211_hdr_4addr *hdr)
{
struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+ struct ieee80211softmac_txrates *txrates = &softmac->txrates;
u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl));
u8 rate, zd_rate;
int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0;
@@ -787,10 +804,16 @@
int flags = 0;
/* FIXME: 802.11a? */
- rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt);
-
- if (short_preamble)
- flags |= R2M_SHORT_PREAMBLE;
+ if(ieee->iw_mode == IW_MODE_MONITOR)
+ {
+ rate = txrates->default_rate;
+ }
+ else
+ {
+ rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt);
+ if (short_preamble)
+ flags |= R2M_SHORT_PREAMBLE;
+ }
zd_rate = rate_to_zd_rate(rate);
cs->modulation = zd_rate_to_modulation(zd_rate, flags);
@@ -800,6 +823,7 @@
struct ieee80211_hdr_4addr *header)
{
struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
unsigned int tx_length = le16_to_cpu(cs->tx_length);
u16 fctl = le16_to_cpu(header->frame_ctl);
u16 ftype = WLAN_FC_GET_TYPE(fctl);
@@ -813,13 +837,21 @@
cs->control = 0;
- /* First fragment */
- if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0)
+ if(ieee->iw_mode == IW_MODE_MONITOR)
+ {
cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
-
- /* Multicast */
- if (is_multicast_ether_addr(header->addr1))
cs->control |= ZD_CS_MULTICAST;
+ }
+ else
+ {
+ /* First fragment */
+ if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0)
+ cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
+
+ /* Multicast */
+ if (is_multicast_ether_addr(header->addr1))
+ cs->control |= ZD_CS_MULTICAST;
+ }
/* PS-POLL */
if (ftype == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL)
@@ -846,6 +878,7 @@
struct ieee80211_txb *txb,
int frag_num)
{
+ struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
int r;
struct sk_buff *skb = txb->fragments[frag_num];
struct ieee80211_hdr_4addr *hdr =
@@ -869,7 +902,10 @@
cs->tx_length = cpu_to_le16(frag_len);
- cs_set_control(mac, cs, hdr);
+/* if(ieee->iw_mode == IW_MODE_MONITOR)
+ cs->control = ZD_CS_MULTICAST;
+ else*/
+ cs_set_control(mac, cs, hdr);
packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
ZD_ASSERT(packet_length <= 0xffff);
@@ -925,7 +961,11 @@
ieee->stats.tx_dropped++;
return r;
}
- r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
+
+ if(ieee->iw_mode == IW_MODE_MONITOR)
+ r = zd_usb_tx_inject(&mac->chip.usb, skb->data, skb->len);
+ else
+ r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
if (r) {
ieee->stats.tx_dropped++;
return r;
@@ -945,6 +985,8 @@
u8 rt_rate;
u16 rt_channel;
u16 rt_chbitmask;
+ u8 rt_antsignal;
+ u8 rt_antnoise;
} __attribute__((packed));
static void fill_rt_header(void *buffer, struct zd_mac *mac,
@@ -958,7 +1000,9 @@
hdr->rt_hdr.it_len = cpu_to_le16(sizeof(struct zd_rt_hdr));
hdr->rt_hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_RATE));
+ (1 << IEEE80211_RADIOTAP_RATE) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE));
hdr->rt_flags = 0;
if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256))
@@ -972,6 +1016,9 @@
hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ |
((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) ==
ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK));
+
+ hdr->rt_antsignal = status->signal_strength;
+ hdr->rt_antnoise = stats->noise;
}
/* Returns 1 if the data packet is for us and 0 otherwise. */
@@ -1078,7 +1125,8 @@
const struct rx_status *status;
*pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status));
- if (status->frame_status & ZD_RX_ERROR) {
+ if ((status->frame_status & ZD_RX_ERROR) ||
+ (status->frame_status & ~0x21)){
struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
ieee->stats.rx_errors++;
if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
diff -Naur linux-2.6.23_orig/drivers/net/wireless/zd1211rw/zd_usb.c linux-2.6.23_rawtx/drivers/net/wireless/zd1211rw/zd_usb.c
--- linux-2.6.23_orig/drivers/net/wireless/zd1211rw/zd_usb.c 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23_rawtx/drivers/net/wireless/zd1211rw/zd_usb.c 2007-12-04 00:07:33.000000000 +0100
@@ -811,6 +811,46 @@
return r;
}
+/* Puts the frame on the USB endpoint. It doesn't wait for
+ * completion. The frame must contain the control set.
+ */
+int zd_usb_tx_inject(struct zd_usb *usb, const u8 *frame, unsigned int length)
+{
+ int r;
+ struct usb_device *udev = zd_usb_to_usbdev(usb);
+ struct urb *urb;
+ void *buffer;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC,
+ &urb->transfer_dma);
+ if (!buffer) {
+ r = -ENOMEM;
+ goto error_free_urb;
+ }
+ memcpy(buffer, frame, length);
+
+ usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
+ buffer, length, tx_urb_complete, NULL);
+
+ r = usb_submit_urb(urb, GFP_ATOMIC);
+ if (r)
+ goto error;
+ return 0;
+error:
+ usb_buffer_free(zd_usb_to_usbdev(usb), length, buffer,
+ urb->transfer_dma);
+error_free_urb:
+ usb_free_urb(urb);
+out:
+ return r;
+}
+
static inline void init_usb_interrupt(struct zd_usb *usb)
{
struct zd_usb_interrupt *intr = &usb->intr;
diff -Naur linux-2.6.23_orig/drivers/net/wireless/zd1211rw/zd_usb.h linux-2.6.23_rawtx/drivers/net/wireless/zd1211rw/zd_usb.h
--- linux-2.6.23_orig/drivers/net/wireless/zd1211rw/zd_usb.h 2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23_rawtx/drivers/net/wireless/zd1211rw/zd_usb.h 2007-12-04 00:07:22.000000000 +0100
@@ -222,6 +222,7 @@
void zd_usb_disable_rx(struct zd_usb *usb);
int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length);
+int zd_usb_tx_inject(struct zd_usb *usb, const u8 *frame, unsigned int length);
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
const zd_addr_t *addresses, unsigned int count);