⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scan.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		numprobes = puserscanin->numprobes ? puserscanin->numprobes : 0;		/*		 * Set the BSSID filter to the incoming configuration,		 *   if non-zero.  If not set, it will remain disabled (all zeros).		 */		memcpy(pscancfgout->bssid, puserscanin->bssid,		       sizeof(pscancfgout->bssid));		if (puserscanin->ssid_len) {			pssidtlv =			    (struct mrvlietypes_ssidparamset *) pscancfgout->			    tlvbuffer;			pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID);			pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len);			memcpy(pssidtlv->ssid, puserscanin->ssid,			       puserscanin->ssid_len);			ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len;		}		/*		 *  The default number of channels sent in the command is low to		 *    ensure the response buffer from the firmware does not truncate		 *    scan results.  That is not an issue with an SSID or BSSID		 *    filter applied to the scan results in the firmware.		 */		if (   puserscanin->ssid_len		    || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) {			*pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN;			*pfilteredscan = 1;		}	} else {		pscancfgout->bsstype = CMD_BSS_TYPE_ANY;		numprobes = 0;	}	/* If the input config or adapter has the number of Probes set, add tlv */	if (numprobes) {		pnumprobestlv = (struct mrvlietypes_numprobes *) ptlvpos;		pnumprobestlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);		pnumprobestlv->header.len = cpu_to_le16(2);		pnumprobestlv->numprobes = cpu_to_le16(numprobes);		ptlvpos += sizeof(*pnumprobestlv);	}	/*	 * Set the output for the channel TLV to the address in the tlv buffer	 *   past any TLVs that were added in this fuction (SSID, numprobes).	 *   channel TLVs will be added past this for each scan command, preserving	 *   the TLVs that were previously added.	 */	*ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos;	if (!puserscanin || !puserscanin->chanlist[0].channumber) {		/* Create a default channel scan list */		lbs_deb_scan("creating full region channel list\n");		wlan_scan_create_channel_list(priv, pscanchanlist,					      *pfilteredscan);		goto out;	}	for (chanidx = 0;	     chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX	     && puserscanin->chanlist[chanidx].channumber; chanidx++) {		channel = puserscanin->chanlist[chanidx].channumber;		(pscanchanlist + chanidx)->channumber = channel;		radiotype = puserscanin->chanlist[chanidx].radiotype;		(pscanchanlist + chanidx)->radiotype = radiotype;		scantype = puserscanin->chanlist[chanidx].scantype;		if (scantype == CMD_SCAN_TYPE_PASSIVE) {			(pscanchanlist +			 chanidx)->chanscanmode.passivescan = 1;		} else {			(pscanchanlist +			 chanidx)->chanscanmode.passivescan = 0;		}		if (puserscanin->chanlist[chanidx].scantime) {			scandur = puserscanin->chanlist[chanidx].scantime;		} else {			if (scantype == CMD_SCAN_TYPE_PASSIVE) {				scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME;			} else {				scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME;			}		}		(pscanchanlist + chanidx)->minscantime =		    cpu_to_le16(scandur);		(pscanchanlist + chanidx)->maxscantime =		    cpu_to_le16(scandur);	}	/* Check if we are only scanning the current channel */	if ((chanidx == 1) &&	    (puserscanin->chanlist[0].channumber ==			       priv->adapter->curbssparams.channel)) {		*pscancurrentonly = 1;		lbs_deb_scan("scanning current channel only");	}out:	return pscancfgout;}/** *  @brief Construct and send multiple scan config commands to the firmware * *  Only used from wlan_scan_networks() * *  Previous routines have created a wlan_scan_cmd_config with any requested *   TLVs.  This function splits the channel TLV into maxchanperscan lists *   and sends the portion of the channel TLV along with the other TLVs *   to the wlan_cmd routines for execution in the firmware. * *  @param priv            A pointer to wlan_private structure *  @param maxchanperscan  Maximum number channels to be included in each *                         scan command sent to firmware *  @param filteredscan    Flag indicating whether or not a BSSID or SSID *                         filter is being used for the firmware command *                         scan command sent to firmware *  @param pscancfgout     Scan configuration used for this scan. *  @param pchantlvout     Pointer in the pscancfgout where the channel TLV *                         should start.  This is past any other TLVs that *                         must be sent down in each firmware command. *  @param pscanchanlist   List of channels to scan in maxchanperscan segments * *  @return                0 or error return otherwise */static int wlan_scan_channel_list(wlan_private * priv,				  int maxchanperscan,				  u8 filteredscan,				  struct wlan_scan_cmd_config * pscancfgout,				  struct mrvlietypes_chanlistparamset * pchantlvout,				  struct chanscanparamset * pscanchanlist,				  const struct wlan_ioctl_user_scan_cfg * puserscanin,				  int full_scan){	struct chanscanparamset *ptmpchan;	struct chanscanparamset *pstartchan;	u8 scanband;	int doneearly;	int tlvidx;	int ret = 0;	int scanned = 0;	union iwreq_data wrqu;	lbs_deb_enter_args(LBS_DEB_SCAN, "maxchanperscan %d, filteredscan %d, "		"full_scan %d", maxchanperscan, filteredscan, full_scan);	if (!pscancfgout || !pchantlvout || !pscanchanlist) {		lbs_deb_scan("pscancfgout, pchantlvout or "			"pscanchanlist is NULL\n");		ret = -1;		goto out;	}	pchantlvout->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);	/* Set the temp channel struct pointer to the start of the desired list */	ptmpchan = pscanchanlist;	if (priv->adapter->last_scanned_channel && !puserscanin)		ptmpchan += priv->adapter->last_scanned_channel;	/* Loop through the desired channel list, sending a new firmware scan	 *   commands for each maxchanperscan channels (or for 1,6,11 individually	 *   if configured accordingly)	 */	while (ptmpchan->channumber) {		tlvidx = 0;		pchantlvout->header.len = 0;		scanband = ptmpchan->radiotype;		pstartchan = ptmpchan;		doneearly = 0;		/* Construct the channel TLV for the scan command.  Continue to		 *  insert channel TLVs until:		 *    - the tlvidx hits the maximum configured per scan command		 *    - the next channel to insert is 0 (end of desired channel list)		 *    - doneearly is set (controlling individual scanning of 1,6,11)		 */		while (tlvidx < maxchanperscan && ptmpchan->channumber		       && !doneearly && scanned < 2) {			lbs_deb_scan("channel %d, radio %d, passive %d, "				"dischanflt %d, maxscantime %d\n",				ptmpchan->channumber,				ptmpchan->radiotype,			             ptmpchan->chanscanmode.passivescan,			             ptmpchan->chanscanmode.disablechanfilt,			             ptmpchan->maxscantime);			/* Copy the current channel TLV to the command being prepared */			memcpy(pchantlvout->chanscanparam + tlvidx,			       ptmpchan, sizeof(pchantlvout->chanscanparam));			/* Increment the TLV header length by the size appended */			/* Ew, it would be _so_ nice if we could just declare the			   variable little-endian and let GCC handle it for us */			pchantlvout->header.len =				cpu_to_le16(le16_to_cpu(pchantlvout->header.len) +					    sizeof(pchantlvout->chanscanparam));			/*			 *  The tlv buffer length is set to the number of bytes of the			 *    between the channel tlv pointer and the start of the			 *    tlv buffer.  This compensates for any TLVs that were appended			 *    before the channel list.			 */			pscancfgout->tlvbufferlen = ((u8 *) pchantlvout						     - pscancfgout->tlvbuffer);			/*  Add the size of the channel tlv header and the data length */			pscancfgout->tlvbufferlen +=			    (sizeof(pchantlvout->header)			     + le16_to_cpu(pchantlvout->header.len));			/* Increment the index to the channel tlv we are constructing */			tlvidx++;			doneearly = 0;			/* Stop the loop if the *current* channel is in the 1,6,11 set			 *   and we are not filtering on a BSSID or SSID.			 */			if (!filteredscan && (ptmpchan->channumber == 1					      || ptmpchan->channumber == 6					      || ptmpchan->channumber == 11)) {				doneearly = 1;			}			/* Increment the tmp pointer to the next channel to be scanned */			ptmpchan++;			scanned++;			/* Stop the loop if the *next* channel is in the 1,6,11 set.			 *  This will cause it to be the only channel scanned on the next			 *  interation			 */			if (!filteredscan && (ptmpchan->channumber == 1					      || ptmpchan->channumber == 6					      || ptmpchan->channumber == 11)) {				doneearly = 1;			}		}		/* Send the scan command to the firmware with the specified cfg */		ret = libertas_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,					    0, 0, pscancfgout);		if (scanned >= 2 && !full_scan) {			ret = 0;			goto done;		}		scanned = 0;	}done:	priv->adapter->last_scanned_channel = ptmpchan->channumber;	if (priv->adapter->last_scanned_channel) {		/* Schedule the next part of the partial scan */		if (!full_scan && !priv->adapter->surpriseremoved) {			cancel_delayed_work(&priv->scan_work);			queue_delayed_work(priv->work_thread, &priv->scan_work,			                   msecs_to_jiffies(300));		}	} else {		/* All done, tell userspace the scan table has been updated */		memset(&wrqu, 0, sizeof(union iwreq_data));		wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);	}out:	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);	return ret;}/* * Only used from wlan_scan_networks()*/static void clear_selected_scan_list_entries(wlan_adapter *adapter,	const struct wlan_ioctl_user_scan_cfg *scan_cfg){	struct bss_descriptor *bss;	struct bss_descriptor *safe;	u32 clear_ssid_flag = 0, clear_bssid_flag = 0;	lbs_deb_enter(LBS_DEB_SCAN);	if (!scan_cfg)		goto out;	if (scan_cfg->clear_ssid && scan_cfg->ssid_len)		clear_ssid_flag = 1;	if (scan_cfg->clear_bssid	    && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0)	    && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) {		clear_bssid_flag = 1;	}	if (!clear_ssid_flag && !clear_bssid_flag)		goto out;	mutex_lock(&adapter->lock);	list_for_each_entry_safe (bss, safe, &adapter->network_list, list) {		u32 clear = 0;		/* Check for an SSID match */		if (   clear_ssid_flag		    && (bss->ssid_len == scan_cfg->ssid_len)		    && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len))			clear = 1;		/* Check for a BSSID match */		if (   clear_bssid_flag		    && !compare_ether_addr(bss->bssid, scan_cfg->bssid))			clear = 1;		if (clear) {			list_move_tail (&bss->list, &adapter->network_free_list);			clear_bss_descriptor(bss);		}	}	mutex_unlock(&adapter->lock);out:	lbs_deb_leave(LBS_DEB_SCAN);}/** *  @brief Internal function used to start a scan based on an input config * *  Also used from debugfs * *  Use the input user scan configuration information when provided in *    order to send the appropriate scan commands to firmware to populate or *    update the internal driver scan table * *  @param priv          A pointer to wlan_private structure *  @param puserscanin   Pointer to the input configuration for the requested *                       scan. *  @param full_scan     ??? * *  @return              0 or < 0 if error */int wlan_scan_networks(wlan_private * priv,                       const struct wlan_ioctl_user_scan_cfg * puserscanin,                       int full_scan){	wlan_adapter * adapter = priv->adapter;	struct mrvlietypes_chanlistparamset *pchantlvout;	struct chanscanparamset * scan_chan_list = NULL;	struct wlan_scan_cmd_config * scan_cfg = NULL;	u8 filteredscan;	u8 scancurrentchanonly;	int maxchanperscan;	int ret;#ifdef CONFIG_LIBERTAS_DEBUG	struct bss_descriptor * iter_bss;	int i = 0;	DECLARE_MAC_BUF(mac);#endif	lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);	/* Cancel any partial outstanding partial scans if this scan	 * is a full scan.	 */	if (full_scan && delayed_work_pending(&priv->scan_work))		cancel_delayed_work(&priv->scan_work);	scan_chan_list = kzalloc(sizeof(struct chanscanparamset) *				WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);	if (scan_chan_list == NULL) {		ret = -ENOMEM;		goto out;	}	scan_cfg = wlan_scan_setup_scan_config(priv,					       puserscanin,					       &pchantlvout,					       scan_chan_list,					       &maxchanperscan,					       &filteredscan,					       &scancurrentchanonly);	if (scan_cfg == NULL) {		ret = -ENOMEM;		goto out;	}	clear_selected_scan_list_entries(adapter, puserscanin);	/* Keep the data path active if we are only scanning our current channel */	if (!scancurrentchanonly) {		netif_stop_queue(priv->dev);		netif_carrier_off(priv->dev);		if (priv->mesh_dev) {			netif_stop_queue(priv->mesh_dev);			netif_carrier_off(priv->mesh_dev);		}	}	ret = wlan_scan_channel_list(priv,				     maxchanperscan,				     filteredscan,				     scan_cfg,				     pchantlvout,				     scan_chan_list,				     puserscanin,				     full_scan);#ifdef CONFIG_LIBERTAS_DEBUG	/* Dump the scan table */	mutex_lock(&adapter->lock);	lbs_deb_scan("The scan table contains:\n");	list_for_each_entry (iter_bss, &adapter->network_list, list) {		lbs_deb_scan("scan %02d, %s, RSSI, %d, SSID '%s'\n",		       i++, print_mac(mac, iter_bss->bssid), (s32) iter_bss->rssi,		       escape_essid(iter_bss->ssid, iter_bss->ssid_len));	}	mutex_unlock(&adapter->lock);#endif	if (priv->adapter->connect_status == LIBERTAS_CONNECTED) {		netif_carrier_on(priv->dev);		netif_wake_queue(priv->dev);		if (priv->mesh_dev) {			netif_carrier_on(priv->mesh_dev);			netif_wake_queue(priv->mesh_dev);		}	}out:	if (scan_cfg)		kfree(scan_cfg);	if (scan_chan_list)		kfree(scan_chan_list);	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);	return ret;}/** *  @brief Interpret a BSS scan response returned from the firmware * *  Parse the various fixed fields and IEs passed back for a a BSS probe *   response or beacon from the scan command.  Record information as needed *   in the scan table struct bss_descriptor for that entry. * *  @param bss  Output parameter: Pointer to the BSS Entry * *  @return             0 or -1 */static int libertas_process_bss(struct bss_descriptor * bss,				u8 ** pbeaconinfo, int *bytesleft){	struct ieeetypes_fhparamset *pFH;	struct ieeetypes_dsparamset *pDS;	struct ieeetypes_cfparamset *pCF;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -