|
@@ -272,6 +272,7 @@ static void rtl8187_rx_cb(struct urb *urb)
|
|
struct ieee80211_rx_status rx_status = { 0 };
|
|
struct ieee80211_rx_status rx_status = { 0 };
|
|
int rate, signal;
|
|
int rate, signal;
|
|
u32 flags;
|
|
u32 flags;
|
|
|
|
+ u32 quality;
|
|
|
|
|
|
spin_lock(&priv->rx_queue.lock);
|
|
spin_lock(&priv->rx_queue.lock);
|
|
if (skb->next)
|
|
if (skb->next)
|
|
@@ -295,44 +296,57 @@ static void rtl8187_rx_cb(struct urb *urb)
|
|
flags = le32_to_cpu(hdr->flags);
|
|
flags = le32_to_cpu(hdr->flags);
|
|
signal = hdr->signal & 0x7f;
|
|
signal = hdr->signal & 0x7f;
|
|
rx_status.antenna = (hdr->signal >> 7) & 1;
|
|
rx_status.antenna = (hdr->signal >> 7) & 1;
|
|
- rx_status.signal = signal;
|
|
|
|
rx_status.noise = hdr->noise;
|
|
rx_status.noise = hdr->noise;
|
|
rx_status.mactime = le64_to_cpu(hdr->mac_time);
|
|
rx_status.mactime = le64_to_cpu(hdr->mac_time);
|
|
- priv->signal = signal;
|
|
|
|
priv->quality = signal;
|
|
priv->quality = signal;
|
|
|
|
+ rx_status.qual = priv->quality;
|
|
priv->noise = hdr->noise;
|
|
priv->noise = hdr->noise;
|
|
|
|
+ rate = (flags >> 20) & 0xF;
|
|
|
|
+ if (rate > 3) { /* OFDM rate */
|
|
|
|
+ if (signal > 90)
|
|
|
|
+ signal = 90;
|
|
|
|
+ else if (signal < 25)
|
|
|
|
+ signal = 25;
|
|
|
|
+ signal = 90 - signal;
|
|
|
|
+ } else { /* CCK rate */
|
|
|
|
+ if (signal > 95)
|
|
|
|
+ signal = 95;
|
|
|
|
+ else if (signal < 30)
|
|
|
|
+ signal = 30;
|
|
|
|
+ signal = 95 - signal;
|
|
|
|
+ }
|
|
|
|
+ rx_status.signal = signal;
|
|
|
|
+ priv->signal = signal;
|
|
} else {
|
|
} else {
|
|
struct rtl8187b_rx_hdr *hdr =
|
|
struct rtl8187b_rx_hdr *hdr =
|
|
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
|
|
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
|
|
|
|
+ /* The Realtek datasheet for the RTL8187B shows that the RX
|
|
|
|
+ * header contains the following quantities: signal quality,
|
|
|
|
+ * RSSI, AGC, the received power in dB, and the measured SNR.
|
|
|
|
+ * In testing, none of these quantities show qualitative
|
|
|
|
+ * agreement with AP signal strength, except for the AGC,
|
|
|
|
+ * which is inversely proportional to the strength of the
|
|
|
|
+ * signal. In the following, the quality and signal strength
|
|
|
|
+ * are derived from the AGC. The arbitrary scaling constants
|
|
|
|
+ * are chosen to make the results close to the values obtained
|
|
|
|
+ * for a BCM4312 using b43 as the driver. The noise is ignored
|
|
|
|
+ * for now.
|
|
|
|
+ */
|
|
flags = le32_to_cpu(hdr->flags);
|
|
flags = le32_to_cpu(hdr->flags);
|
|
- signal = hdr->agc >> 1;
|
|
|
|
- rx_status.antenna = (hdr->signal >> 7) & 1;
|
|
|
|
- rx_status.signal = 64 - min(hdr->noise, (u8)64);
|
|
|
|
- rx_status.noise = hdr->noise;
|
|
|
|
|
|
+ quality = 170 - hdr->agc;
|
|
|
|
+ if (quality > 100)
|
|
|
|
+ quality = 100;
|
|
|
|
+ signal = 14 - hdr->agc / 2;
|
|
|
|
+ rx_status.qual = quality;
|
|
|
|
+ priv->quality = quality;
|
|
|
|
+ rx_status.signal = signal;
|
|
|
|
+ priv->signal = signal;
|
|
|
|
+ rx_status.antenna = (hdr->rssi >> 7) & 1;
|
|
rx_status.mactime = le64_to_cpu(hdr->mac_time);
|
|
rx_status.mactime = le64_to_cpu(hdr->mac_time);
|
|
- priv->signal = hdr->signal;
|
|
|
|
- priv->quality = hdr->agc >> 1;
|
|
|
|
- priv->noise = hdr->noise;
|
|
|
|
|
|
+ rate = (flags >> 20) & 0xF;
|
|
}
|
|
}
|
|
|
|
|
|
skb_trim(skb, flags & 0x0FFF);
|
|
skb_trim(skb, flags & 0x0FFF);
|
|
- rate = (flags >> 20) & 0xF;
|
|
|
|
- if (rate > 3) { /* OFDM rate */
|
|
|
|
- if (signal > 90)
|
|
|
|
- signal = 90;
|
|
|
|
- else if (signal < 25)
|
|
|
|
- signal = 25;
|
|
|
|
- signal = 90 - signal;
|
|
|
|
- } else { /* CCK rate */
|
|
|
|
- if (signal > 95)
|
|
|
|
- signal = 95;
|
|
|
|
- else if (signal < 30)
|
|
|
|
- signal = 30;
|
|
|
|
- signal = 95 - signal;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- rx_status.qual = priv->quality;
|
|
|
|
- rx_status.signal = signal;
|
|
|
|
rx_status.rate_idx = rate;
|
|
rx_status.rate_idx = rate;
|
|
rx_status.freq = dev->conf.channel->center_freq;
|
|
rx_status.freq = dev->conf.channel->center_freq;
|
|
rx_status.band = dev->conf.channel->band;
|
|
rx_status.band = dev->conf.channel->band;
|
|
@@ -1030,9 +1044,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
|
|
|
|
|
priv->mode = IEEE80211_IF_TYPE_MNTR;
|
|
priv->mode = IEEE80211_IF_TYPE_MNTR;
|
|
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
|
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
|
- IEEE80211_HW_RX_INCLUDES_FCS |
|
|
|
|
- IEEE80211_HW_SIGNAL_UNSPEC;
|
|
|
|
- dev->max_signal = 65;
|
|
|
|
|
|
+ IEEE80211_HW_RX_INCLUDES_FCS;
|
|
|
|
|
|
eeprom.data = dev;
|
|
eeprom.data = dev;
|
|
eeprom.register_read = rtl8187_eeprom_register_read;
|
|
eeprom.register_read = rtl8187_eeprom_register_read;
|
|
@@ -1147,10 +1159,16 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
|
(*channel++).hw_value = txpwr >> 8;
|
|
(*channel++).hw_value = txpwr >> 8;
|
|
}
|
|
}
|
|
|
|
|
|
- if (priv->is_rtl8187b)
|
|
|
|
|
|
+ if (priv->is_rtl8187b) {
|
|
printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
|
|
printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
|
|
"is EXPERIMENTAL, and could damage your\n"
|
|
"is EXPERIMENTAL, and could damage your\n"
|
|
" hardware, use at your own risk\n");
|
|
" hardware, use at your own risk\n");
|
|
|
|
+ dev->flags |= IEEE80211_HW_SIGNAL_DBM;
|
|
|
|
+ } else {
|
|
|
|
+ dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
|
|
|
|
+ dev->max_signal = 65;
|
|
|
|
+ }
|
|
|
|
+
|
|
if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
|
|
if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
|
|
printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
|
|
printk(KERN_INFO "rtl8187: inconsistency between id with OEM"
|
|
" info!\n");
|
|
" info!\n");
|