First part of dot11req_scan/scan_results.

Incomplete:

0)  Testing.  :)
1)  ScanResults needs to have the *rates fields filled.
2)  Scan needs to enable the port if necessary.

And of course, (3), the startup script rewrite to make everything more
intelligent.   That'll be the fun part.
This commit is contained in:
solomon 2002-09-29 19:44:19 +00:00
parent f563fb744b
commit bd8c2ed235
7 changed files with 344 additions and 88 deletions

View file

@ -41,6 +41,9 @@
* Intersil Corporation as part of PRISM(R) chipset product development.
*
* --------------------------------------------------------------------
- Implemented the dot11req_scan/dot11req_scan_results functions.
This, combined with more intelligent startup scripts, will allow
you to have multiple profiles per network. Not finished yet.
- hfa384x.h updates.
- additions to the MIB.
- Cleaned up wireless extension stuff a little bit.

View file

@ -401,26 +401,50 @@ typedef struct wait_queue *wait_queue_head_t;
#endif
#endif
/*
#ifndef le16_to_cpu
#define le16_to_cpu(x) (x)
#define le16_to_cpup(x) (*(x))
#define le32_to_cpu(x) (x)
#define le32_to_cpup(x) (*(x))
#define cpu_to_le16(x) (x)
#define cpu_to_le32(x) (x)
#define be16_to_cpu(x) ntohs(x)
#define be16_to_cpup(x) ntohs(*(x))
#define be32_to_cpu(x) ntohl(x)
#define be32_to_cpup(x) ntohl(*(x))
#define cpu_to_be16(x) htons(x)
#define cpu_to_be32(x) htonl(x)
#define cpu_to_le16s(x) do { } while (0)
#define cpu_to_le32s(x) do { } while (0)
#define le16_to_cpus(x) do { } while (0)
#define le32_to_cpus(x) do { } while (0)
#ifndef wait_event_interruptible_timeout
// retval == 0; signal met; we're good.
// retval < 0; interrupted by signal.
// retval > 0; timed out.
#define __wait_event_interruptible_timeout(wq, condition, timeout, ret) \
do { \
int __ret = 0; \
if (!(condition)) { \
wait_queue_t __wait; \
unsigned long expire; \
init_waitqueue_entry(&__wait, current); \
\
expire = timeout + jiffies; \
add_wait_queue(&wq, &__wait); \
for (;;) { \
set_current_state(TASK_INTERRUPTIBLE); \
if (condition) \
break; \
if (jiffies > expire) { \
ret = jiffies - expire; \
break; \
} \
if (!signal_pending(current)) { \
schedule_timeout(timeout); \
continue; \
} \
ret = -ERESTARTSYS; \
break; \
} \
current->state = TASK_RUNNING; \
remove_wait_queue(&wq, &__wait); \
} \
} while (0)
#define wait_event_interruptible_timeout(wq, condition, timeout) \
({ \
int __ret = 0; \
if (!(condition)) \
__wait_event_interruptible_timeout(wq, condition, \
timeout, __ret); \
__ret; \
})
#endif
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,90))
#define spin_lock(l) do { } while (0)

View file

@ -221,72 +221,124 @@ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
int result = 0;
prism2sta_priv_t *priv = (prism2sta_priv_t*)wlandev->priv;
p80211msg_dot11req_scan_t *msg = msgp;
// hfa384x_t *hw = priv->hw;
// hfa384x_ScanRequest_data_t scanreq;
// UINT16 word;
hfa384x_t *hw = priv->hw;
UINT16 roamingmode, word;
int i, timeout;
hfa384x_HostScanRequest_data_t scanreq;
DBFENTER;
if (!priv->ap) {
if (priv->ap) {
WLAN_LOG_ERROR0("Prism2 in AP mode cannot perform scans.\n");
result = 1;
msg->resultcode.data = P80211ENUM_resultcode_not_supported;
goto exit;
}
/*** STATION ***/
memset(&scanreq, 0, sizeof(scanreq));
#if 0
/* Check the roaming mode to make sure we can scan, change if necessary */
/* Check the port status, if disabled, then enable */
/* Construct the channel list */
/* Set the rate based on...what? */
if ( !joined )
rate=min(HFA384x_RID_TXRATECNTL) (aka dot11OperationalRates)
else
if ( dot11req_scan.ssid == currssid )
rate=max(HFA384x_RID_CNF_BASICRATES)
(if supported on STA..we might need to save
this from prior scans)
else
rate=min(HFA384x_RID_TXRATECNTL) (aka dot11OperationalRates)
endif
endif
/* Set the scan command */
/* Issue the Inquire */
/* Sleep until scanresults are in */
/* Build the persistent (filtered) results */
/* save current roaming mode */
result = hfa384x_drvr_getconfig16(hw,
HFA384x_RID_CNFROAMINGMODE, &roamingmode);
if ( result ) {
WLAN_LOG_ERROR1("getconfig(ROAMMODE) failed. result=%d\n",
result);
msg->resultcode.data =
P80211ENUM_resultcode_implementation_failure;
goto exit;
}
/* drop into mode 3 for the scan */
word = HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM;
result = hfa384x_drvr_setconfig16(hw,
HFA384x_RID_CNFROAMINGMODE, &word);
if ( result ) {
WLAN_LOG_ERROR1("setconfig(ROAMINGMODE) failed. result=%d\n",
result);
msg->resultcode.data =
P80211ENUM_resultcode_implementation_failure;
goto exit;
}
word = 2;
hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, &word);
/* active or passive? */
if (HFA384x_FIRMWARE_VERSION(priv->ident_sta_fw.major,
priv->ident_sta_fw.minor,
priv->ident_sta_fw.variant) <
HFA384x_FIRMWARE_VERSION(1,5,1)) {
if (msg->scantype.data != P80211ENUM_scantype_active) {
word = host2hfa384x_16(msg->maxchanneltime.data);
} else {
word = 0;
}
result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, &word);
if ( result ) {
WLAN_LOG_ERROR0("Passive scan not supported with "
"current firmware.\n");
}
}
/* Issue the scan request */
scanreq.channelList = host2hfa384x_16(0x07ff); /* scan channels 1-11 */
scanreq.txRate = host2hfa384x_16(BIT1); /* probes @ 2Mb/s */
result = hfa384x_drvr_setconfig( hw, HFA384x_RID_SCANREQUEST,
&scanreq, HFA384x_RID_SCANREQUEST_LEN);
if ( result ) {
WLAN_LOG_ERROR1("setconfig(SCANREQUEST) failed. result=%d\n",
result);
result = 0;
}
/* set up the txrate to be 1MBPS. Should be fastest basicrate... */
word = HFA384x_RATEBIT_1;
/* Issue an async inquire */
hfa384x_drvr_scanresults(hw, HFA384x_IT_SCANRESULTS);
/* set up the channel list */
word = 0;
for (i = 0; i < msg->channellist.data.len; i++) {
UINT8 channel = msg->channellist.data.data[i];
if (channel > 14) continue;
/* channel 1 is BIT0 ... channel 14 is BIT13 */
word |= (1 << (channel-1));
}
scanreq.channelList = host2hfa384x_16(word);
/* sleep until info frame arrives */
#endif
result = 0;
msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
msg->resultcode.data = P80211ENUM_resultcode_not_supported;
} else {
/* set up the ssid, if present. */
scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
/*** ACCESS POINT ***/
// XXX MAC port status, enable if necessary.
/* Scan is currently unsupported for AP */
/* TODO: Find out if host managed scan is supported in ap f/w */
/* we might want to use it to allow some "auto config" */
/* mode where the AP scans for others and then selects */
/* its channel and settings based on what it finds. */
msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
msg->resultcode.data = P80211ENUM_resultcode_not_supported;
}
/* Figure out our timeout first Kus, then HZ */
timeout = msg->channellist.data.len * msg->maxchanneltime.data;
timeout = timeout * 1000 / HZ;
/* Issue the scan request */
hw->scanflag = 0;
WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq));
result = hfa384x_drvr_setconfig( hw,
HFA384x_RID_HOSTSCAN, &scanreq,
sizeof(hfa384x_HostScanRequest_data_t));
if ( result ) {
WLAN_LOG_ERROR1("setconfig(SCANREQUEST) failed. result=%d\n",
result);
msg->resultcode.data =
P80211ENUM_resultcode_implementation_failure;
goto exit;
}
/* sleep until info frame arrives */
wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
// XXX hw->scanflag contains the number of results, or -1 if none.
hw->scanflag = 0;
// XXX restore port status.
if ( result ) {
WLAN_LOG_ERROR1("setconfig(ROAMMODE) failed. result=%d\n",
result);
msg->resultcode.data =
P80211ENUM_resultcode_implementation_failure;
goto exit;
}
result = 0;
msg->resultcode.data = P80211ENUM_resultcode_success;
exit:
msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
DBFEXIT;
return result;
@ -316,26 +368,124 @@ int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
{
int result = 0;
p80211msg_dot11req_scan_results_t *req;
prism2sta_priv_t *priv = (prism2sta_priv_t*)wlandev->priv;
p80211msg_dot11req_scan_results_t *msg = msgp;
hfa384x_t *hw = priv->hw;
hfa384x_HScanResultSub_t *item = NULL;
int count;
DBFENTER;
if (!priv->ap) {
req = (p80211msg_dot11req_scan_results_t *) msgp;
/*** STATION ***/
req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
/* Same situation as scan */
msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
msg->resultcode.data = P80211ENUM_resultcode_not_supported;
} else {
/*** ACCESS POINT ***/
/* Same situation as scan */
msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
msg->resultcode.data = P80211ENUM_resultcode_not_supported;
if (priv->ap) {
result = 1;
req->resultcode.data = P80211ENUM_resultcode_not_supported;
goto exit;
}
if (! priv->scanresults) {
WLAN_LOG_ERROR0("dot11req_scan_results can only be used adter a successful dot11req_scan.\n");
result = 2;
req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
goto exit;
}
count = (hfa384x2host_16(priv->scanresults->framelen) - 3) / 32;
if (req->bssindex.data > count) {
WLAN_LOG_ERROR2("reqeusted index (%ld) out of range (%d)\n",
req->bssindex.data, hw->scanflag);
result = 2;
req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
goto exit;
}
item = &(priv->scanresults->info.hscanresult.result[req->bssindex.data]);
/* signal and noise */
req->signal.status = P80211ENUM_msgitem_status_data_ok;
req->noise.status = P80211ENUM_msgitem_status_data_ok;
req->signal.data = hfa384x2host_16(item->sl);
req->noise.data = hfa384x2host_16(item->anl);
/* BSSID */
req->bssid.status = P80211ENUM_msgitem_status_data_ok;
req->bssid.data.len = WLAN_BSSID_LEN;
memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
/* SSID */
req->ssid.status = P80211ENUM_msgitem_status_data_ok;
req->ssid.data.len = item->ssid.len;
memcpy(req->ssid.data.data, item->ssid.data, item->ssid.len);
#if 0
/* supported rates */
for (count = 0; count < 10 ; count++)
if (item->supprates[count] == 0)
break;
req->rates.status = P80211ENUM_msgitem_status_data_ok;
req->rates.data.len = count;
memcpy(req->rates.data.data, item->supprates, count);
// XXX re-write to use "basicrate1-n, operationarate1-n"
#endif
/* beacon period */
req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
req->beaconperiod.data = hfa384x2host_16(item->bcnint);
/* timestamps */
req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
req->timestamp.data = jiffies;
req->localtime.status = P80211ENUM_msgitem_status_data_ok;
req->localtime.data = jiffies;
/* atim window */
req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
req->ibssatimwindow.data = hfa384x2host_16(item->atim);
/* Channel */
req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
req->dschannel.data = hfa384x2host_16(item->chid);
/* capinfo bits */
count = hfa384x2host_16(item->capinfo);
/* privacy flag */
req->privacy.status = P80211ENUM_msgitem_status_data_ok;
req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
/* cfpollable */
req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
/* cfpollreq */
req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
/* bsstype */
req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
P80211ENUM_bsstype_infrastructure :
P80211ENUM_bsstype_independent;
// item->proberesp_rate
/*
req->fhdwelltime
req->fhhopset
req->fhhoppattern
req->fhhopindex
req->cfpdurremaining
*/
result = 0;
req->resultcode.data = P80211ENUM_resultcode_success;
exit:
DBFEXIT;
return result;
}

View file

@ -550,6 +550,8 @@ static void prism2sta_inf_handover(
wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
static void prism2sta_inf_tallies(
wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
static void prism2sta_inf_hostscanresults(
wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
static void prism2sta_inf_scanresults(
wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
static void prism2sta_inf_chinforesults(
@ -1786,6 +1788,49 @@ void prism2sta_inf_scanresults(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
return;
}
/*----------------------------------------------------------------
* prism2sta_inf_hostscanresults
*
* Handles the receipt of a Scan Results info frame.
*
* Arguments:
* wlandev wlan device structure
* inf ptr to info frame (contents in hfa384x order)
*
* Returns:
* nothing
*
* Side effects:
*
* Call context:
* interrupt
----------------------------------------------------------------*/
void prism2sta_inf_hostscanresults(wlandevice_t *wlandev,
hfa384x_InfFrame_t *inf)
{
prism2sta_priv_t *priv = wlandev->priv;
hfa384x_t *hw = priv->hw;
int nbss;
DBFENTER;
nbss = (hfa384x2host_16(inf->framelen) - 3) / 32;
WLAN_LOG_DEBUG1(2, "Received %d hostscan results\n", count);
if (priv->scanresults)
kfree(priv->scanresults);
priv->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC);
memcpy(priv->scanresults, inf, sizeof(hfa384x_InfFrame_t));
if (nbss == 0)
nbss = -1;
/* Notify/wake the sleeping caller. */
hw->scanflag = nbss;
wake_up_interruptible(&hw->cmdq);
DBFEXIT;
};
/*----------------------------------------------------------------
* prism2sta_inf_chinforesults
@ -2542,6 +2587,9 @@ void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
case HFA384x_IT_COMMTALLIES:
prism2sta_inf_tallies(wlandev, inf);
break;
case HFA384x_IT_HOSTSCANRESULTS:
prism2sta_inf_hostscanresults(wlandev, inf);
break;
case HFA384x_IT_SCANRESULTS:
prism2sta_inf_scanresults(wlandev, inf);
break;

View file

@ -2432,6 +2432,8 @@ typedef struct hfa384x
UINT16 infofid;
struct semaphore infofid_sem;
#endif /* !USB */
int scanflag; /* to signal scan comlete */
int join_ap; /* are we joined to a specific ap */
int join_retries; /* number of join retries till we fail */
hfa384x_JoinRequest_data_t joinreq; /* join request saved data */

View file

@ -185,8 +185,9 @@ typedef struct prism2sta_priv
prism2sta_accesslist_t deny; /* Denied station list. */
UINT32 psusercount; /* Power save user count. */
hfa384x_CommTallies32_t tallies; /* Communication tallies. */
UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment. */
UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment */
hfa384x_InfFrame_t *scanresults;
} prism2sta_priv_t;

View file

@ -485,6 +485,34 @@ p80211meta_t MKREQMETANAME(dot11req_scan_results)[] = {
/* fromtextptr */ p80211_fromtext_enumint,
/* validfunptr */ p80211_isvalid_enumint
},
{
/* name */ MKITEMNAME("signal"),
/* did */ 0,
/* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, 0UL, ISCONFIRM),
/* min */ 0,
/* max */ 0,
/* maxlen */ 0,
/* minlen */ 0,
/* enumptr */ NULL,
/* collptr */ NULL,
/* totextptr */ p80211_totext_int,
/* fromtextptr */ p80211_fromtext_int,
/* validfunptr */ p80211_isvalid_int
},
{
/* name */ MKITEMNAME("noise"),
/* did */ 0,
/* flags */ P80211ITEM_SETFLAGS(ISREQUIRED, 0UL, ISCONFIRM),
/* min */ 0,
/* max */ 0,
/* maxlen */ 0,
/* minlen */ 0,
/* enumptr */ NULL,
/* collptr */ NULL,
/* totextptr */ p80211_totext_int,
/* fromtextptr */ p80211_fromtext_int,
/* validfunptr */ p80211_isvalid_int
},
{
/* name */ MKITEMNAME("bssid"),
/* did */ 0,