Ejemplo n.º 1
0
static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
			     union iwreq_data *wrqu, char *b)
{
	struct r8192_priv *priv = rtllib_priv(dev);
	struct rtllib_device *ieee = priv->rtllib;
	enum rt_rf_power_state rtState;
	int ret;

	if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
		if ((ieee->state >= RTLLIB_ASSOCIATING) &&
		    (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED))
			return 0;
		if ((priv->rtllib->state == RTLLIB_LINKED) &&
		    (priv->rtllib->CntAfterLink < 2))
			return 0;
	}

	if (priv->bHwRadioOff == true) {
		printk(KERN_INFO "================>%s(): hwradio off\n",
		       __func__);
		return 0;
	}
	rtState = priv->rtllib->eRFPowerState;
	if (!priv->up)
		return -ENETDOWN;
	if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true)
		return -EAGAIN;

	if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
		struct iw_scan_req *req = (struct iw_scan_req *)b;
		if (req->essid_len) {
			ieee->current_network.ssid_len = req->essid_len;
			memcpy(ieee->current_network.ssid, req->essid,
			       req->essid_len);
		}
	}

	down(&priv->wx_sem);

	priv->rtllib->FirstIe_InScan = true;

	if (priv->rtllib->state != RTLLIB_LINKED) {
		if (priv->rtllib->PowerSaveControl.bInactivePs) {
			if (rtState == eRfOff) {
				if (priv->rtllib->RfOffReason >
				    RF_CHANGE_BY_IPS) {
					RT_TRACE(COMP_ERR, "%s(): RF is "
						 "OFF.\n", __func__);
					up(&priv->wx_sem);
					return -1;
				} else {
					RT_TRACE(COMP_PS, "=========>%s(): "
						 "IPSLeave\n", __func__);
					down(&priv->rtllib->ips_sem);
					IPSLeave(dev);
					up(&priv->rtllib->ips_sem);
				}
			}
		}
		rtllib_stop_scan(priv->rtllib);
		if (priv->rtllib->LedControlHandler)
			priv->rtllib->LedControlHandler(dev,
							 LED_CTL_SITE_SURVEY);

		if (priv->rtllib->eRFPowerState != eRfOff) {
			priv->rtllib->actscanning = true;

			if (ieee->ScanOperationBackupHandler)
				ieee->ScanOperationBackupHandler(ieee->dev,
							 SCAN_OPT_BACKUP);

			rtllib_start_scan_syncro(priv->rtllib, 0);

			if (ieee->ScanOperationBackupHandler)
				ieee->ScanOperationBackupHandler(ieee->dev,
							 SCAN_OPT_RESTORE);
		}
		ret = 0;
	} else {
		priv->rtllib->actscanning = true;
		ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b);
	}

	up(&priv->wx_sem);
	return ret;
}
Ejemplo n.º 2
0
void rtllib_wx_sync_scan_wq(void *data)
{
	struct rtllib_device *ieee = container_of_work_rsl(data,
				     struct rtllib_device, wx_sync_scan_wq);
	short chan;
	enum ht_extchnl_offset chan_offset = 0;
	enum ht_channel_width bandwidth = 0;
	int b40M = 0;

	if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
		rtllib_start_scan_syncro(ieee, 0);
		goto out;
	}

	chan = ieee->current_network.channel;

	if (ieee->LeisurePSLeave)
		ieee->LeisurePSLeave(ieee->dev);
	/* notify AP to be in PS mode */
	rtllib_sta_ps_send_null_frame(ieee, 1);
	rtllib_sta_ps_send_null_frame(ieee, 1);

	rtllib_stop_all_queues(ieee);

	if (ieee->data_hard_stop)
		ieee->data_hard_stop(ieee->dev);
	rtllib_stop_send_beacons(ieee);
	ieee->state = RTLLIB_LINKED_SCANNING;
	ieee->link_change(ieee->dev);
	/* wait for ps packet to be kicked out successfully */
	msleep(50);

	if (ieee->ScanOperationBackupHandler)
		ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP);

	if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT &&
	    ieee->pHTInfo->bCurBW40MHz) {
		b40M = 1;
		chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
		bandwidth = (enum ht_channel_width)ieee->pHTInfo->bCurBW40MHz;
		RT_TRACE(COMP_DBG, "Scan in 40M, force to 20M first:%d, %d\n",
			 chan_offset, bandwidth);
		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20,
				       HT_EXTCHNL_OFFSET_NO_EXT);
	}

	rtllib_start_scan_syncro(ieee, 0);

	if (b40M) {
		RT_TRACE(COMP_DBG, "Scan in 20M, back to 40M\n");
		if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
			ieee->set_chan(ieee->dev, chan + 2);
		else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
			ieee->set_chan(ieee->dev, chan - 2);
		else
			ieee->set_chan(ieee->dev, chan);
		ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
	} else {
		ieee->set_chan(ieee->dev, chan);
	}

	if (ieee->ScanOperationBackupHandler)
		ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE);

	ieee->state = RTLLIB_LINKED;
	ieee->link_change(ieee->dev);

	/* Notify AP that I wake up again */
	rtllib_sta_ps_send_null_frame(ieee, 0);

	if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 ||
	    ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
		ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
	}

	if (ieee->data_hard_resume)
		ieee->data_hard_resume(ieee->dev);

	if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
		rtllib_start_send_beacons(ieee);

	rtllib_wake_all_queues(ieee);

out:
	mutex_unlock(&ieee->wx_mutex);

}