Added support for the sniff indication interface.

This commit is contained in:
mark 2000-01-12 19:54:18 +00:00
parent 681dea73b2
commit 9c3206d536
2 changed files with 200 additions and 47 deletions

View file

@ -1112,10 +1112,10 @@ typedef struct hfa384x_rx_frame
/*-- MAC rx descriptor (hfa384x byte order) --*/
UINT16 status __WLAN_ATTRIB_PACK__;
UINT32 time __WLAN_ATTRIB_PACK__;
UINT8 signal __WLAN_ATTRIB_PACK__;
UINT8 silence __WLAN_ATTRIB_PACK__;
UINT8 rx_flow __WLAN_ATTRIB_PACK__;
UINT8 signal __WLAN_ATTRIB_PACK__;
UINT8 rate __WLAN_ATTRIB_PACK__;
UINT8 rx_flow __WLAN_ATTRIB_PACK__;
UINT16 reserved1 __WLAN_ATTRIB_PACK__;
UINT16 reserved2 __WLAN_ATTRIB_PACK__;

View file

@ -68,6 +68,7 @@
#include <wlan/p80211conv.h>
#include <wlan/p80211msg.h>
#include <wlan/p80211netdev.h>
#include <wlan/p80211req.h>
#include <wlan/p80211metadef.h>
#include <wlan/p80211metastruct.h>
#include <prism2/hfa384x.h>
@ -134,6 +135,7 @@ static void prism2sta_int_info(wlandevice_t *wlandev);
static void prism2sta_int_txexc(wlandevice_t *wlandev);
static void prism2sta_int_tx(wlandevice_t *wlandev);
static void prism2sta_int_rx(wlandevice_t *wlandev);
static void prism2sta_int_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid, hfa384x_rx_frame_t *rxdesc);
static void prism2sta_int_alloc(wlandevice_t *wlandev);
static void prism2sta_inf_handover(wlandevice_t *wlandev, void *buf);
@ -1162,46 +1164,6 @@ void prism2sta_int_rx(wlandevice_t *wlandev)
rxdesc.time = hfa384x2host32(rxdesc.time);
rxdesc.data_len = hfa384x2host16(rxdesc.data_len);
/* Allocate the buffer, note CRC (aka FCS). This function assumes */
/* there needs to be space for one */
pb = p80211pb_alloc_p80211(NULL,
rxdesc.data_len + WLAN_HDR_A3_LEN + WLAN_CRC_LEN);
if ( pb == NULL ) {
WLAN_LOG_DEBUG0(1, "pballoc failed.\n");
goto failed;
}
/* Copy the 802.11 hdr to the buffer */
result = hfa384x_copy_from_bap(hw, hw->bap, rxfid,
HFA384x_RX_80211HDR_OFF, pb->p80211_hdr, WLAN_HDR_A3_LEN);
if ( result ) {
WLAN_LOG_DEBUG4(1,
"copy_from_bap(0x%04x, %d, %d) failed, result=%d\n",
rxfid,
HFA384x_RX_80211HDR_OFF,
WLAN_HDR_A3_LEN,
result);
p80211pb_free(pb);
goto failed;
}
/* Copy the payload data to the buffer */
result = hfa384x_copy_from_bap(hw, hw->bap, rxfid,
HFA384x_RX_DATA_OFF, pb->p80211_payload, rxdesc.data_len);
if ( result ) {
WLAN_LOG_DEBUG4(1,
"copy_from_bap(0x%04x, %d, %d) failed, result=%d\n",
rxfid,
HFA384x_RX_DATA_OFF,
rxdesc.data_len,
result);
p80211pb_free(pb);
goto failed;
}
/* Set the length */
pb->p80211frmlen = WLAN_HDR_A3_LEN + rxdesc.data_len + WLAN_CRC_LEN;
#if 0
printk(KERN_DEBUG"rxf(%d): ",rxlen);
for (i=0; i<pb->p80211frmlen; i++) {
@ -1214,23 +1176,60 @@ printk("\n");
switch( HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) )
{
case 0:
/* Allocate the buffer, note CRC (aka FCS). pballoc */
/* assumes there needs to be space for one */
pb = p80211pb_alloc_p80211(NULL,
rxdesc.data_len + WLAN_HDR_A3_LEN + WLAN_CRC_LEN);
if ( pb == NULL ) {
WLAN_LOG_DEBUG0(1, "pballoc failed.\n");
goto failed;
}
/* Copy the 802.11 hdr to the buffer */
result = hfa384x_copy_from_bap(hw, hw->bap, rxfid,
HFA384x_RX_80211HDR_OFF, pb->p80211_hdr, WLAN_HDR_A3_LEN);
if ( result ) {
WLAN_LOG_DEBUG4(1,
"copy_from_bap(0x%04x, %d, %d) failed, result=%d\n",
rxfid,
HFA384x_RX_80211HDR_OFF,
WLAN_HDR_A3_LEN,
result);
p80211pb_free(pb);
goto failed;
}
/* Copy the payload data to the buffer */
if ( rxdesc.data_len > 0 ) {
result = hfa384x_copy_from_bap(hw,
hw->bap, rxfid, HFA384x_RX_DATA_OFF,
pb->p80211_payload, rxdesc.data_len);
if ( result ) {
WLAN_LOG_DEBUG4(1,
"copy_from_bap(0x%04x, %d, %d) failed, result=%d\n",
rxfid,
HFA384x_RX_DATA_OFF,
rxdesc.data_len,
result);
p80211pb_free(pb);
goto failed;
}
}
/* Set the length */
pb->p80211frmlen = WLAN_HDR_A3_LEN + rxdesc.data_len + WLAN_CRC_LEN;
/* Call p80211netdev_rx */
p80211netdev_rx(wlandev, pb);
break;
case 7:
WLAN_LOG_DEBUG0(1,"Received monitor frame\n");
prism2sta_int_rxmonitor( wlandev, rxfid, &rxdesc);
/* Copy to wlansnif skb */
/* Call p80211 sniff response function */
/* free the locally allocated space */
WLAN_HEX_DUMP(1, "monrxdesc", &rxdesc, sizeof(rxdesc));
WLAN_HEX_DUMP(1, "monrxfrm", pb->p80211_hdr, pb->p80211frmlen);
p80211pb_free(pb);
break;
default:
WLAN_LOG_WARNING1("Received frame on unsupported port=%d\n",
HFA384x_RXSTATUS_MACPORT_GET(rxdesc.status) );
p80211pb_free(pb);
break;
}
@ -1240,6 +1239,160 @@ failed:
}
/*----------------------------------------------------------------
* prism2sta_int_rxmonitor
*
* Helper function for int_rx. Handles monitor frames.
* Note that this function allocates space for the FCS and sets it
* to 0xffffffff. The hfa384x doesn't give us the FCS value but the
* higher layers expect it. 0xffffffff is used as a flag to indicate
* the FCS is bogus.
*
* Arguments:
* wlandev wlan device structure
* rxfid received FID
* rxdesc rx descriptor read from card in int_rx
*
* Returns:
* nothing
*
* Side effects:
* Allocates an skb and passes it up via p80211ind_sniff()
* Call context:
* interrupt
----------------------------------------------------------------*/
void prism2sta_int_rxmonitor( wlandevice_t *wlandev, UINT16 rxfid, hfa384x_rx_frame_t *rxdesc)
{
prism2sta_priv_t *priv = wlandev->priv;
hfa384x_t *hw = priv->hw;
UINT hdrlen = 0;
UINT datalen = 0;
UINT skblen = 0;
p80211msg_lnxind_wlansniffrm_t *msg;
UINT8 *datap;
UINT16 fc;
struct sk_buff *skb;
DBFENTER;
/* Don't forget the status, time, and data_len fields are in host order */
/* Figure out how big the frame is */
fc = ieee2host16(rxdesc->frame_control);
switch ( WLAN_GET_FC_FTYPE(fc) )
{
case WLAN_FTYPE_DATA:
if ( WLAN_GET_FC_TODS(fc) && WLAN_GET_FC_FROMDS(fc) ) {
hdrlen = WLAN_HDR_A4_LEN;
} else {
hdrlen = WLAN_HDR_A3_LEN;
}
datalen = rxdesc->data_len;
break;
case WLAN_FTYPE_MGMT:
hdrlen = WLAN_HDR_A3_LEN;
datalen = rxdesc->data_len;
break;
case WLAN_FTYPE_CTL:
switch ( WLAN_GET_FC_FSTYPE(fc) )
{
case WLAN_FSTYPE_PSPOLL:
case WLAN_FSTYPE_RTS:
case WLAN_FSTYPE_CFEND:
case WLAN_FSTYPE_CFENDCFACK:
hdrlen = 16;
break;
case WLAN_FSTYPE_CTS:
case WLAN_FSTYPE_ACK:
hdrlen = 10;
break;
}
datalen = 0;
break;
}
/* Allocate an ind message+framesize skb */
skblen = sizeof(p80211msg_lnxind_wlansniffrm_t) +
hdrlen + datalen + WLAN_CRC_LEN;
skb = alloc_skb(skblen, GFP_ATOMIC);
skb_put(skb, skblen);
datap = skb->data + sizeof(p80211msg_lnxind_wlansniffrm_t);
msg = (p80211msg_lnxind_wlansniffrm_t*)skb->data;
/* Initialize the message members */
msg->msgcode = DIDmsg_lnxind_wlansniffrm;
msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
strcpy(msg->devname, wlandev->name);
msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
msg->hosttime.status = 0;
msg->hosttime.len = 4;
msg->hosttime.data = jiffies;
msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
msg->mactime.status = 0;
msg->mactime.len = 4;
msg->mactime.data = rxdesc->time;
msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
msg->channel.status = P80211ENUM_msgitem_status_no_value;
msg->channel.len = 4;
msg->channel.data = 0;
msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
msg->rssi.status = P80211ENUM_msgitem_status_no_value;
msg->rssi.len = 4;
msg->rssi.data = 0;
msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
msg->sq.status = P80211ENUM_msgitem_status_no_value;
msg->sq.len = 4;
msg->sq.data = 0;
msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
msg->signal.status = 0;
msg->signal.len = 4;
msg->signal.data = rxdesc->signal;
msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
msg->noise.status = 0;
msg->noise.len = 4;
msg->noise.data = rxdesc->silence;
msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
msg->rate.status = 0;
msg->rate.len = 4;
msg->rate.data = rxdesc->rate / 5; /* set to 802.11 units */
msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
msg->istx.status = 0;
msg->istx.len = 4;
msg->istx.data = P80211ENUM_truth_false;
msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
msg->frmlen.status = 0;
msg->frmlen.len = 4;
msg->frmlen.data = hdrlen + datalen + WLAN_CRC_LEN;
/* Copy the 802.11 header to the skb (ctl frames may be less than a full header) */
memcpy( datap, &(rxdesc->frame_control), hdrlen);
/* If any, copy the data from the card to the skb */
if ( datalen > 0 )
{
hfa384x_copy_from_bap(hw,
hw->bap, rxfid, HFA384x_RX_DATA_OFF,
datap + hdrlen, datalen);
}
/* Set the CRC */
memset( datap + skb->len - WLAN_CRC_LEN, 0xff, WLAN_CRC_LEN);
/* Pass it up */
p80211ind_sniff(wlandev, skb);
DBFEXIT;
return;
}
/*----------------------------------------------------------------
* prism2sta_int_alloc
*