netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mohamed Abbas <mabbas@linux.intel.com>
To: netdev@vger.kernel.org
Cc: "John W. Linville" <linville@tuxdriver.com>
Subject: [PATCH 01/3] d80211:  add support for SIOCSIWRATE, SIOCSIWTXPOW and SIOCSIWPOWER
Date: Mon, 21 Aug 2006 17:30:22 -0700	[thread overview]
Message-ID: <44EA501E.4010605@linux.intel.com> (raw)
In-Reply-To: <20060821075158.728615077@sipsolutions.net>

[-- Attachment #1: Type: text/plain, Size: 457 bytes --]

the attached patch will add support to handle these iw_handle 
SIOC[S/G]IWRATE, SIOC[S/G]IWTXPOW and SIOC[S/G]IWPOWER.  It also  added 
some changes in ieee80211_ioctl_giwrange function to report supported 
channels and rates.  a call to ieee80211_hw_config is needed to infor 
the low level driver about these changes, I guess we might need to add 
flag to indicate which parameters was changed so the low level driver 
does not need to make extra calls.


[-- Attachment #2: d80211-add-more-wireless-tool-cmd.patch --]
[-- Type: text/plain, Size: 10386 bytes --]

diff --git a/include/net/d80211.h b/include/net/d80211.h
index ba5cb4c..0cde91f 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -256,6 +256,7 @@ struct ieee80211_conf {
         u8 antenna_max;			/* maximum antenna gain */
 	short tx_power_reduction; /* in 0.1 dBm */
 
+	u8 power_management_enable;     /* flag to enable/disable power management*/
 	int antenna_sel;		/* default antenna conf:
 					 *	0 = default/diversity,
 			  		 *	1 = Ant0,
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 11804d5..86a5373 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1250,6 +1250,10 @@ static int ieee80211_tx(struct net_devic
 			break;
 	}
 
+	/* only data unicast frame */
+	if ((tx.u.tx.rate) && !mgmt && !control->no_ack)
+		local->last_rate = tx.u.tx.rate->rate * 100000;
+
 	skb = tx.skb; /* handlers are allowed to change skb */
 
 	if (sta)
@@ -4358,6 +4362,8 @@ struct net_device *ieee80211_alloc_hw(si
 	local->long_retry_limit = 4;
 	local->conf.calib_int = 60;
 	local->conf.radio_enabled = 1;
+	local->last_rate = -1;
+	local->conf.power_management_enable = 0;
 	local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
 	local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
 
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index bdaaf5e..29c40c5 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -396,6 +396,9 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 	int *supp_rates[NUM_IEEE80211_MODES];
 	int *basic_rates[NUM_IEEE80211_MODES];
 
+	u32 last_rate; /* last tx data rate value. management and multi cast frame
+			* wont be used. */
+
 	int rts_threshold;
 	int cts_protect_erp_frames;
 	int fragmentation_threshold;
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index b983716..5e01659 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -1537,6 +1537,19 @@ static int ieee80211_ioctl_giwname(struc
 				   char *name, char *extra)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+        if (!local->conf.radio_enabled) {
+        	strcpy(name, "radio off");
+                return 0;
+	} else if (sdata->type == IEEE80211_IF_TYPE_STA) {
+        	if (!(sdata->u.sta.associated) ||
+                     (sdata->u.sta.probereq_poll)) {
+			strcpy(name, "unassociated");
+			return 0;
+		}
+        }
 
 	switch (local->conf.phymode) {
 	case MODE_IEEE80211A:
@@ -1565,6 +1578,9 @@ static int ieee80211_ioctl_giwrange(stru
 				 struct iw_point *data, char *extra)
 {
 	struct iw_range *range = (struct iw_range *) extra;
+	int i,j,c;
+	int skip_bg = 0;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	data->length = sizeof(struct iw_range);
 	memset(range, 0, sizeof(struct iw_range));
@@ -1580,6 +1596,42 @@ static int ieee80211_ioctl_giwrange(stru
 	range->min_frag = 256;
 	range->max_frag = 2346;
 
+	j = 0;
+        for (i = 0; i < local->num_curr_rates ; i++) {
+                struct ieee80211_rate *rate = &local->curr_rates[i];
+
+                if (rate->flags & IEEE80211_RATE_SUPPORTED) {
+			range->bitrate[j] = rate->rate * 100000;
+			j++;
+		}
+	}
+	range->num_bitrates = j;
+
+	c = 0;
+        for (i = 0; i < local->hw->num_modes; i++) {
+                struct ieee80211_hw_modes *mode = &local->hw->modes[i];
+		if (skip_bg &&
+                    ((mode->mode == MODE_IEEE80211G) ||
+                    (mode->mode == MODE_IEEE80211B)))
+			continue;
+
+		for (j = 0; 
+		     j < mode->num_channels && c < IW_MAX_FREQUENCIES; j++) {
+			struct ieee80211_channel *chan = &mode->channels[j];
+
+                        range->freq[c].i = chan->chan;
+                        range->freq[c].m = chan->freq * 100000;
+                        range->freq[c].e = 1;
+			c++;
+		}
+		if ((mode->mode == MODE_IEEE80211G) || 
+		    (mode->mode == MODE_IEEE80211B))
+			skip_bg = 1;
+
+	}
+        range->num_channels = c;
+        range->num_frequency = c;
+
 	return 0;
 }
 
@@ -2138,6 +2190,169 @@ static int ieee80211_ioctl_giwretry(stru
 }
 
 
+static int ieee80211_ioctl_siwrate(struct net_device *dev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu, char *extra)
+{
+        struct ieee80211_local *local = dev->ieee80211_ptr;
+        int i, j;
+        u32 target_rate = wrqu->bitrate.value /100000;
+        u32 fixed;
+	int *old_supp = local->supp_rates[local->conf.phymode];
+	int *supp = NULL;
+
+        /* value = -1, fixed = 0 means auto only, so we should use
+         * all rates offered by AP
+         * value = X, fixed = 1 means only rate X
+         * value = X, fixed = 0 means all rates lower equal X */
+        if (target_rate == -1) {
+                fixed = 0;
+                goto apply;
+        }
+
+        fixed = wrqu->bitrate.fixed;
+	supp = (int *) kmalloc((local->num_curr_rates + 1) * 
+					sizeof(int), GFP_KERNEL);
+	if (!supp)
+		return 0;
+
+	j = 0;
+	for (i=0; i< local->num_curr_rates; i++) {
+		struct ieee80211_rate *rate = &local->curr_rates[i];
+
+		if (target_rate == rate->rate) {
+			supp[j++] = rate->rate;
+			break;
+		} else if (!fixed)
+			supp[j++] = rate->rate;
+	}
+
+	supp[j] = -1;
+
+        if ((j >= local->num_curr_rates) || (j == 0)) {
+                kfree(supp);
+                supp = NULL;
+        }
+
+     apply:
+	if (!old_supp && !supp)
+		return 0;
+
+        local->supp_rates[local->conf.phymode] = supp;
+	if (old_supp)
+        	kfree(old_supp);
+
+	
+	ieee80211_prepare_rates(dev);
+	ieee80211_hw_config(dev);
+        return 0;
+}
+
+static int ieee80211_ioctl_giwrate(struct net_device *dev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu, char *extra)
+{
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+        u32 max_rate = 0;
+	int i;
+
+        for (i = local->num_curr_rates - 1; i >= 0 ; i--) {
+                struct ieee80211_rate *rate = &local->curr_rates[i];
+
+		if (rate->flags & IEEE80211_RATE_SUPPORTED) {	
+			max_rate = rate->rate * 100000;
+			break;
+		}
+	}
+
+        if (max_rate >= local->last_rate)
+                wrqu->bitrate.value = local->last_rate;
+        else
+                wrqu->bitrate.value = max_rate;
+        return 0;
+}
+
+static int ieee80211_ioctl_giwtxpow(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu, char *extra)
+{
+	struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev);
+
+	wrqu->txpower.flags = IW_TXPOW_DBM;
+        wrqu->txpower.fixed = 1;
+        wrqu->txpower.disabled = (conf->radio_enabled) ? 0 : 1;
+	wrqu->txpower.value = conf->power_level;
+        return 0;
+}
+
+
+static int ieee80211_ioctl_siwtxpow(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu, char *extra)
+{
+	int rc = 0;
+	struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev);
+
+	/* we need to add flag in ieee80211_conf to mark the changed fields.
+	*/
+        if (wrqu->txpower.flags != IW_TXPOW_DBM) 
+                rc = -EINVAL;
+	else
+		conf->power_level = wrqu->txpower.value;
+        
+
+	ieee80211_ioctl_set_radio_enabled(dev, !wrqu->txpower.disabled);
+        return rc;
+}
+
+static int ieee80211_ioctl_siwpower(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu, char *extra)
+{
+	struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev);
+
+        /* We might need to add new callback function instead of
+           calling ieee80211_hw_config
+	*/
+	if (wrqu->power.disabled) {
+		conf->power_management_enable = 0;
+		ieee80211_hw_config(dev);
+		return 0;
+        }
+
+        if (wrqu->power.flags & IW_POWER_TYPE) 
+                return -EOPNOTSUPP;
+
+        switch (wrqu->power.flags & IW_POWER_MODE) {
+        case IW_POWER_ON:       /* If not specified */
+        case IW_POWER_MODE:     /* If set all mask */
+        case IW_POWER_ALL_R:    /* If explicitely state all */
+                break;
+        default:                /* Otherwise we don't support it */
+                return -EOPNOTSUPP;
+        }
+
+	conf->power_management_enable = 1;
+	ieee80211_hw_config(dev);
+
+        return 0;
+}
+
+static int ieee80211_ioctl_giwpower(struct net_device *dev,
+                            struct iw_request_info *info,
+                            union iwreq_data *wrqu, char *extra)
+{
+	struct ieee80211_conf *conf = ieee80211_get_hw_conf(dev);
+
+        if (!conf->power_management_enable)
+                wrqu->power.disabled = 1;
+        else {
+                wrqu->power.disabled = 0;
+        }
+        return 0;
+}
+
+
 static void ieee80211_ioctl_unmask_channels(struct ieee80211_local *local)
 {
 	int m, c;
@@ -3141,20 +3356,20 @@ static const iw_handler ieee80211_handle
 	(iw_handler) NULL,				/* SIOCGIWNICKN */
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) NULL,				/* -- hole -- */
-	(iw_handler) NULL,				/* SIOCSIWRATE */
-	(iw_handler) NULL,				/* SIOCGIWRATE */
+	(iw_handler) ieee80211_ioctl_siwrate,		/* SIOCSIWRATE */
+	(iw_handler) ieee80211_ioctl_giwrate,		/* SIOCGIWRATE */
 	(iw_handler) ieee80211_ioctl_siwrts,		/* SIOCSIWRTS */
 	(iw_handler) ieee80211_ioctl_giwrts,		/* SIOCGIWRTS */
 	(iw_handler) ieee80211_ioctl_siwfrag,		/* SIOCSIWFRAG */
 	(iw_handler) ieee80211_ioctl_giwfrag,		/* SIOCGIWFRAG */
-	(iw_handler) NULL,				/* SIOCSIWTXPOW */
-	(iw_handler) NULL,				/* SIOCGIWTXPOW */
+	(iw_handler) ieee80211_ioctl_siwtxpow,		/* SIOCSIWTXPOW */
+	(iw_handler) ieee80211_ioctl_giwtxpow,		/* SIOCGIWTXPOW */
 	(iw_handler) ieee80211_ioctl_siwretry,		/* SIOCSIWRETRY */
 	(iw_handler) ieee80211_ioctl_giwretry,		/* SIOCGIWRETRY */
 	(iw_handler) ieee80211_ioctl_siwencode,		/* SIOCSIWENCODE */
 	(iw_handler) ieee80211_ioctl_giwencode,		/* SIOCGIWENCODE */
-	(iw_handler) NULL,				/* SIOCSIWPOWER */
-	(iw_handler) NULL,				/* SIOCGIWPOWER */
+	(iw_handler) ieee80211_ioctl_siwpower,		/* SIOCSIWPOWER */
+	(iw_handler) ieee80211_ioctl_giwpower,		/* SIOCGIWPOWER */
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) NULL,				/* -- hole -- */
 	(iw_handler) ieee80211_ioctl_siwgenie,		/* SIOCSIWGENIE */

  reply	other threads:[~2006-08-22  0:30 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-21  7:41 [PATCH 00/18] d80211: various cleanups/fixes/changes Johannes Berg
2006-08-21  7:41 ` [PATCH 01/18] d80211: LED triggers Johannes Berg
2006-08-22  0:30   ` Mohamed Abbas [this message]
2006-08-22  0:36     ` [PATCH 02/3] d80211: iwlist scan Mohamed Abbas
2006-08-23 15:46       ` Jiri Benc
2006-08-28 20:37         ` [PATCH 0/7] d80211: support more wireless command mabbas
2006-08-22  0:38     ` [PATCH 03/3] d80211: adhoc Mohamed Abbas
2006-08-23 15:51       ` Jiri Benc
2006-08-23 15:19     ` [PATCH 01/3] d80211: add support for SIOCSIWRATE, SIOCSIWTXPOW and SIOCSIWPOWER Jiri Benc
2006-08-25 18:37     ` Jouni Malinen
2006-08-25 18:46       ` Mohamed Abbas
2006-08-22 16:54   ` [PATCH 01/18] d80211: LED triggers Jouni Malinen
2006-08-22 18:38     ` Jiri Benc
2006-08-23  7:02     ` Johannes Berg
2006-08-23 18:16   ` Jiri Benc
2006-08-24  7:03     ` Johannes Berg
2006-09-22 11:59   ` Jiri Benc
2006-08-21  7:41 ` [PATCH 02/18] d80211: master link Johannes Berg
2006-08-21  8:13   ` Johannes Berg
2006-08-21 19:08   ` Jiri Benc
2006-08-22  7:49     ` Johannes Berg
2006-08-21  7:41 ` [PATCH 03/18] d80211: pointers as extended booleans Johannes Berg
2006-08-22  6:43   ` Bill Fink
2006-08-22  8:39     ` Johannes Berg
2006-08-21  7:41 ` [PATCH 04/18] d80211: use kzalloc() Johannes Berg
2006-08-21  7:41 ` [PATCH 05/18] d80211: get rid of WME bitfield Johannes Berg
2006-08-21  7:41 ` [PATCH 06/18] d80211: rework rate control registration Johannes Berg
2006-08-21 19:19   ` Jiri Benc
2006-08-22  8:33     ` Johannes Berg
2006-08-21  7:41 ` [PATCH 07/18] d80211: get rid of sta_aid in favour of keeping track of TIM Johannes Berg
2006-08-22 18:36   ` Jiri Benc
2006-08-23  7:04     ` Johannes Berg
2006-08-23 10:04     ` [PATCH] " Johannes Berg
2006-08-23 10:05       ` Johannes Berg
2006-08-23 10:16     ` [PATCH ] " Johannes Berg
2006-08-21  7:41 ` [PATCH 08/18] d80211: clean up exports Johannes Berg
2006-08-22 16:44   ` Jouni Malinen
2006-08-23  7:01     ` Johannes Berg
2006-08-23 10:03     ` [PATCH] " Johannes Berg
2006-08-21  7:41 ` [PATCH 09/18] d80211: move out rate control registration code Johannes Berg
2006-08-21  7:41 ` [PATCH 10/18] d80211: clean up includes Johannes Berg
2006-08-21  7:41 ` [PATCH 11/18] d80211: clean up qdisc requeue Johannes Berg
2006-08-21 19:31   ` Jiri Benc
2006-08-22  7:48     ` Johannes Berg
2006-08-21  7:41 ` [PATCH 12/18] d80211: fix some sparse warnings Johannes Berg
2006-08-22 18:55   ` Jiri Benc
2006-08-21  7:41 ` [PATCH 13/18] d80211: clean up some coding style issues Johannes Berg
2006-08-21 19:35   ` Jiri Benc
2006-08-22  8:27     ` Johannes Berg
2006-08-21  7:41 ` [PATCH 14/18] d80211: make lowlevel TX framedump option visible Johannes Berg
2006-08-21  7:41 ` [PATCH 15/18] d80211: surface IBSS debug Johannes Berg
2006-08-21  7:41 ` [PATCH 16/18] d80211: get rid of MICHAEL_MIC_HWACCEL define Johannes Berg
2006-08-22 19:00   ` Jiri Benc
2006-08-23  7:05     ` Johannes Berg
2006-08-23  9:46       ` Jiri Benc
2006-08-21  7:41 ` [PATCH 17/18] d80211: surface powersave debug switch Johannes Berg
2006-08-21  7:41 ` [PATCH 18/18] d80211: fix some documentation Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=44EA501E.4010605@linux.intel.com \
    --to=mabbas@linux.intel.com \
    --cc=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).