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

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**  * This file contains the major functions in WLAN  * driver. It includes init, exit, open, close and main  * thread etc..  */#include <linux/moduleparam.h>#include <linux/delay.h>#include <linux/freezer.h>#include <linux/etherdevice.h>#include <linux/netdevice.h>#include <linux/if_arp.h>#include <linux/kthread.h>#include <net/iw_handler.h>#include <net/ieee80211.h>#include "host.h"#include "decl.h"#include "dev.h"#include "wext.h"#include "debugfs.h"#include "assoc.h"#include "join.h"#define DRIVER_RELEASE_VERSION "323.p0"const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION#ifdef  DEBUG    "-dbg"#endif    "";/* Module parameters */unsigned int libertas_debug = 0;module_param(libertas_debug, int, 0644);EXPORT_SYMBOL_GPL(libertas_debug);#define WLAN_TX_PWR_DEFAULT		20	/*100mW */#define WLAN_TX_PWR_US_DEFAULT		20	/*100mW */#define WLAN_TX_PWR_JP_DEFAULT		16	/*50mW */#define WLAN_TX_PWR_FR_DEFAULT		20	/*100mW */#define WLAN_TX_PWR_EMEA_DEFAULT	20	/*100mW *//* Format { channel, frequency (MHz), maxtxpower } *//* band: 'B/G', region: USA FCC/Canada IC */static struct chan_freq_power channel_freq_power_US_BG[] = {	{1, 2412, WLAN_TX_PWR_US_DEFAULT},	{2, 2417, WLAN_TX_PWR_US_DEFAULT},	{3, 2422, WLAN_TX_PWR_US_DEFAULT},	{4, 2427, WLAN_TX_PWR_US_DEFAULT},	{5, 2432, WLAN_TX_PWR_US_DEFAULT},	{6, 2437, WLAN_TX_PWR_US_DEFAULT},	{7, 2442, WLAN_TX_PWR_US_DEFAULT},	{8, 2447, WLAN_TX_PWR_US_DEFAULT},	{9, 2452, WLAN_TX_PWR_US_DEFAULT},	{10, 2457, WLAN_TX_PWR_US_DEFAULT},	{11, 2462, WLAN_TX_PWR_US_DEFAULT}};/* band: 'B/G', region: Europe ETSI */static struct chan_freq_power channel_freq_power_EU_BG[] = {	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT},	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT},	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT},	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT},	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT},	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT},	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT},	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT},	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT},	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT},	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT},	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT},	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT}};/* band: 'B/G', region: Spain */static struct chan_freq_power channel_freq_power_SPN_BG[] = {	{10, 2457, WLAN_TX_PWR_DEFAULT},	{11, 2462, WLAN_TX_PWR_DEFAULT}};/* band: 'B/G', region: France */static struct chan_freq_power channel_freq_power_FR_BG[] = {	{10, 2457, WLAN_TX_PWR_FR_DEFAULT},	{11, 2462, WLAN_TX_PWR_FR_DEFAULT},	{12, 2467, WLAN_TX_PWR_FR_DEFAULT},	{13, 2472, WLAN_TX_PWR_FR_DEFAULT}};/* band: 'B/G', region: Japan */static struct chan_freq_power channel_freq_power_JPN_BG[] = {	{1, 2412, WLAN_TX_PWR_JP_DEFAULT},	{2, 2417, WLAN_TX_PWR_JP_DEFAULT},	{3, 2422, WLAN_TX_PWR_JP_DEFAULT},	{4, 2427, WLAN_TX_PWR_JP_DEFAULT},	{5, 2432, WLAN_TX_PWR_JP_DEFAULT},	{6, 2437, WLAN_TX_PWR_JP_DEFAULT},	{7, 2442, WLAN_TX_PWR_JP_DEFAULT},	{8, 2447, WLAN_TX_PWR_JP_DEFAULT},	{9, 2452, WLAN_TX_PWR_JP_DEFAULT},	{10, 2457, WLAN_TX_PWR_JP_DEFAULT},	{11, 2462, WLAN_TX_PWR_JP_DEFAULT},	{12, 2467, WLAN_TX_PWR_JP_DEFAULT},	{13, 2472, WLAN_TX_PWR_JP_DEFAULT},	{14, 2484, WLAN_TX_PWR_JP_DEFAULT}};/** * the structure for channel, frequency and power */struct region_cfp_table {	u8 region;	struct chan_freq_power *cfp_BG;	int cfp_no_BG;};/** * the structure for the mapping between region and CFP */static struct region_cfp_table region_cfp_table[] = {	{0x10,			/*US FCC */	 channel_freq_power_US_BG,	 ARRAY_SIZE(channel_freq_power_US_BG),	 }	,	{0x20,			/*CANADA IC */	 channel_freq_power_US_BG,	 ARRAY_SIZE(channel_freq_power_US_BG),	 }	,	{0x30, /*EU*/ channel_freq_power_EU_BG,	 ARRAY_SIZE(channel_freq_power_EU_BG),	 }	,	{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,	 ARRAY_SIZE(channel_freq_power_SPN_BG),	 }	,	{0x32, /*FRANCE*/ channel_freq_power_FR_BG,	 ARRAY_SIZE(channel_freq_power_FR_BG),	 }	,	{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,	 ARRAY_SIZE(channel_freq_power_JPN_BG),	 }	,/*Add new region here */};/** * the table to keep region code */u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =    { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };/** * 802.11b/g supported bitrates (in 500Kb/s units) */u8 libertas_bg_rates[MAX_RATES] =    { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,0x00, 0x00 };/** * FW rate table.  FW refers to rates by their index in this table, not by the * rate value itself.  Values of 0x00 are * reserved positions. */static u8 fw_data_rates[MAX_RATES] =    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,      0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00};/** *  @brief use index to get the data rate * *  @param idx                The index of data rate *  @return 	   		data rate or 0 */u32 libertas_fw_index_to_data_rate(u8 idx){	if (idx >= sizeof(fw_data_rates))		idx = 0;	return fw_data_rates[idx];}/** *  @brief use rate to get the index * *  @param rate                 data rate *  @return 	   		index or 0 */u8 libertas_data_rate_to_fw_index(u32 rate){	u8 i;	if (!rate)		return 0;	for (i = 0; i < sizeof(fw_data_rates); i++) {		if (rate == fw_data_rates[i])			return i;	}	return 0;}/** * Attributes exported through sysfs *//** * @brief Get function for sysfs attribute anycast_mask */static ssize_t libertas_anycast_get(struct device * dev,		struct device_attribute *attr, char * buf){	struct cmd_ds_mesh_access mesh_access;	memset(&mesh_access, 0, sizeof(mesh_access));	libertas_prepare_and_send_command(to_net_dev(dev)->priv,			CMD_MESH_ACCESS,			CMD_ACT_MESH_GET_ANYCAST,			CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));}/** * @brief Set function for sysfs attribute anycast_mask */static ssize_t libertas_anycast_set(struct device * dev,		struct device_attribute *attr, const char * buf, size_t count){	struct cmd_ds_mesh_access mesh_access;	uint32_t datum;	memset(&mesh_access, 0, sizeof(mesh_access));	sscanf(buf, "%x", &datum);	mesh_access.data[0] = cpu_to_le32(datum);	libertas_prepare_and_send_command((to_net_dev(dev))->priv,			CMD_MESH_ACCESS,			CMD_ACT_MESH_SET_ANYCAST,			CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);	return strlen(buf);}int libertas_add_rtap(wlan_private *priv);void libertas_remove_rtap(wlan_private *priv);/** * Get function for sysfs attribute rtap */static ssize_t libertas_rtap_get(struct device * dev,		struct device_attribute *attr, char * buf){	wlan_private *priv = (wlan_private *) (to_net_dev(dev))->priv;	wlan_adapter *adapter = priv->adapter;	return snprintf(buf, 5, "0x%X\n", adapter->monitormode);}/** *  Set function for sysfs attribute rtap */static ssize_t libertas_rtap_set(struct device * dev,		struct device_attribute *attr, const char * buf, size_t count){	int monitor_mode;	wlan_private *priv = (wlan_private *) (to_net_dev(dev))->priv;	wlan_adapter *adapter = priv->adapter;	sscanf(buf, "%x", &monitor_mode);	if (monitor_mode != WLAN_MONITOR_OFF) {		if(adapter->monitormode == monitor_mode)			return strlen(buf);		if (adapter->monitormode == WLAN_MONITOR_OFF) {			if (adapter->mode == IW_MODE_INFRA)				libertas_send_deauthentication(priv);			else if (adapter->mode == IW_MODE_ADHOC)				libertas_stop_adhoc_network(priv);			libertas_add_rtap(priv);		}		adapter->monitormode = monitor_mode;	}	else {		if(adapter->monitormode == WLAN_MONITOR_OFF)			return strlen(buf);		adapter->monitormode = WLAN_MONITOR_OFF;		libertas_remove_rtap(priv);		netif_wake_queue(priv->dev);		netif_wake_queue(priv->mesh_dev);	}	libertas_prepare_and_send_command(priv,			CMD_802_11_MONITOR_MODE, CMD_ACT_SET,			CMD_OPTION_WAITFORRSP, 0, &adapter->monitormode);	return strlen(buf);}/** * libertas_rtap attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/libertas-rtap) */static DEVICE_ATTR(libertas_rtap, 0644, libertas_rtap_get,		libertas_rtap_set );/** * anycast_mask attribute to be exported per mshX interface * through sysfs (/sys/class/net/mshX/anycast_mask) */static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set);static ssize_t libertas_autostart_enabled_get(struct device * dev,		struct device_attribute *attr, char * buf){	struct cmd_ds_mesh_access mesh_access;	memset(&mesh_access, 0, sizeof(mesh_access));	libertas_prepare_and_send_command(to_net_dev(dev)->priv,			CMD_MESH_ACCESS,			CMD_ACT_MESH_GET_AUTOSTART_ENABLED,			CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);	return sprintf(buf, "%d\n", le32_to_cpu(mesh_access.data[0]));}static ssize_t libertas_autostart_enabled_set(struct device * dev,		struct device_attribute *attr, const char * buf, size_t count){	struct cmd_ds_mesh_access mesh_access;	uint32_t datum;	wlan_private * priv = (to_net_dev(dev))->priv;	int ret;	memset(&mesh_access, 0, sizeof(mesh_access));	sscanf(buf, "%d", &datum);	mesh_access.data[0] = cpu_to_le32(datum);	ret = libertas_prepare_and_send_command(priv,			CMD_MESH_ACCESS,			CMD_ACT_MESH_SET_AUTOSTART_ENABLED,			CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);	if (ret == 0)		priv->mesh_autostart_enabled = datum ? 1 : 0;	return strlen(buf);}static DEVICE_ATTR(autostart_enabled, 0644,		libertas_autostart_enabled_get, libertas_autostart_enabled_set);static struct attribute *libertas_mesh_sysfs_entries[] = {	&dev_attr_anycast_mask.attr,	&dev_attr_autostart_enabled.attr,	NULL,};static struct attribute_group libertas_mesh_attr_group = {	.attrs = libertas_mesh_sysfs_entries,};/** *  @brief Check if the device can be open and wait if necessary. * *  @param dev     A pointer to net_device structure *  @return 	   0 * * For USB adapter, on some systems the device open handler will be * called before FW ready. Use the following flag check and wait * function to work around the issue. * */static int pre_open_check(struct net_device *dev){	wlan_private *priv = (wlan_private *) dev->priv;	wlan_adapter *adapter = priv->adapter;	int i = 0;	while (!adapter->fw_ready && i < 20) {		i++;		msleep_interruptible(100);	}	if (!adapter->fw_ready) {		lbs_pr_err("firmware not ready\n");		return -1;	}	return 0;}/** *  @brief This function opens the device * *  @param dev     A pointer to net_device structure *  @return 	   0 */static int libertas_dev_open(struct net_device *dev){	wlan_private *priv = (wlan_private *) dev->priv;	wlan_adapter *adapter = priv->adapter;	lbs_deb_enter(LBS_DEB_NET);	priv->open = 1;	if (adapter->connect_status == LIBERTAS_CONNECTED) {		netif_carrier_on(priv->dev);		if (priv->mesh_dev)			netif_carrier_on(priv->mesh_dev);	} else {		netif_carrier_off(priv->dev);		if (priv->mesh_dev)			netif_carrier_off(priv->mesh_dev);	}	lbs_deb_leave(LBS_DEB_NET);	return 0;}/** *  @brief This function opens the mshX interface * *  @param dev     A pointer to net_device structure *  @return 	   0 */static int libertas_mesh_open(struct net_device *dev){	wlan_private *priv = (wlan_private *) dev->priv ;	if (pre_open_check(dev) == -1)		return -1;	priv->mesh_open = 1 ;	netif_wake_queue(priv->mesh_dev);	if (priv->infra_open == 0)		return libertas_dev_open(priv->dev) ;	return 0;}/** *  @brief This function opens the ethX interface * *  @param dev     A pointer to net_device structure *  @return 	   0 */static int libertas_open(struct net_device *dev){	wlan_private *priv = (wlan_private *) dev->priv ;	if(pre_open_check(dev) == -1)		return -1;	priv->infra_open = 1 ;	netif_wake_queue(priv->dev);	if (priv->open == 0)		return libertas_dev_open(priv->dev) ;	return 0;}static int libertas_dev_close(struct net_device *dev){	wlan_private *priv = dev->priv;	lbs_deb_enter(LBS_DEB_NET);	netif_carrier_off(priv->dev);	priv->open = 0;	lbs_deb_leave(LBS_DEB_NET);	return 0;}/** *  @brief This function closes the mshX interface * *  @param dev     A pointer to net_device structure *  @return 	   0 */static int libertas_mesh_close(struct net_device *dev){	wlan_private *priv = (wlan_private *) (dev->priv);	priv->mesh_open = 0;	netif_stop_queue(priv->mesh_dev);	if (priv->infra_open == 0)		return libertas_dev_close(dev);	else		return 0;}/** *  @brief This function closes the ethX interface * *  @param dev     A pointer to net_device structure *  @return 	   0 */static int libertas_close(struct net_device *dev){	wlan_private *priv = (wlan_private *) dev->priv;	netif_stop_queue(dev);	priv->infra_open = 0;	if (priv->mesh_open == 0)		return libertas_dev_close(dev);	else		return 0;}static int libertas_hard_start_xmit(struct sk_buff *skb, struct net_device *dev){	int ret = 0;	wlan_private *priv = dev->priv;	lbs_deb_enter(LBS_DEB_NET);	if (priv->dnld_sent || priv->adapter->TxLockFlag) {		priv->stats.tx_dropped++;		goto done;	}	netif_stop_queue(priv->dev);	if (priv->mesh_dev)		netif_stop_queue(priv->mesh_dev);	if (libertas_process_tx(priv, skb) == 0)		dev->trans_start = jiffies;done:	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);	return ret;}/** * @brief Mark mesh packets and handover them to libertas_hard_start_xmit * */static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,

⌨️ 快捷键说明

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