Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
chan.c
Go to the documentation of this file.
1 /*
2  * This file contains helper code to handle channel
3  * settings and keeping track of what is possible at
4  * any point in time.
5  *
6  * Copyright 2009 Johannes Berg <[email protected]>
7  */
8 
9 #include <linux/export.h>
10 #include <net/cfg80211.h>
11 #include "core.h"
12 
13 struct ieee80211_channel *
16 {
17  struct ieee80211_channel *chan;
18  struct ieee80211_sta_ht_cap *ht_cap;
19 
20  chan = ieee80211_get_channel(&rdev->wiphy, freq);
21 
22  /* Primary channel not allowed */
23  if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
24  return NULL;
25 
26  if (channel_type == NL80211_CHAN_HT40MINUS &&
28  return NULL;
29  else if (channel_type == NL80211_CHAN_HT40PLUS &&
31  return NULL;
32 
33  ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
34 
35  if (channel_type != NL80211_CHAN_NO_HT) {
36  if (!ht_cap->ht_supported)
37  return NULL;
38 
39  if (channel_type != NL80211_CHAN_HT20 &&
40  (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
42  return NULL;
43  }
44 
45  return chan;
46 }
47 
49  struct ieee80211_channel *chan,
51 {
52  struct ieee80211_channel *sec_chan;
53  int diff;
54 
55  switch (channel_type) {
57  diff = 20;
58  break;
60  diff = -20;
61  break;
62  default:
63  return true;
64  }
65 
66  sec_chan = ieee80211_get_channel(wiphy, chan->center_freq + diff);
67  if (!sec_chan)
68  return false;
69 
70  /* we'll need a DFS capability later */
71  if (sec_chan->flags & (IEEE80211_CHAN_DISABLED |
75  return false;
76 
77  return true;
78 }
80 
82  int freq, enum nl80211_channel_type chantype)
83 {
84  struct ieee80211_channel *chan;
85 
86  if (!rdev->ops->set_monitor_channel)
87  return -EOPNOTSUPP;
88  if (!cfg80211_has_monitors_only(rdev))
89  return -EBUSY;
90 
91  chan = rdev_freq_to_chan(rdev, freq, chantype);
92  if (!chan)
93  return -EINVAL;
94 
95  return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
96 }
97 
98 void
100  struct ieee80211_channel **chan,
101  enum cfg80211_chan_mode *chanmode)
102 {
103  *chan = NULL;
104  *chanmode = CHAN_MODE_UNDEFINED;
105 
106  ASSERT_WDEV_LOCK(wdev);
107 
108  if (wdev->netdev && !netif_running(wdev->netdev))
109  return;
110 
111  switch (wdev->iftype) {
113  if (wdev->current_bss) {
114  *chan = wdev->current_bss->pub.channel;
115  *chanmode = wdev->ibss_fixed
118  return;
119  }
122  if (wdev->current_bss) {
123  *chan = wdev->current_bss->pub.channel;
124  *chanmode = CHAN_MODE_SHARED;
125  return;
126  }
127  break;
128  case NL80211_IFTYPE_AP:
130  if (wdev->beacon_interval) {
131  *chan = wdev->channel;
132  *chanmode = CHAN_MODE_SHARED;
133  }
134  return;
136  if (wdev->mesh_id_len) {
137  *chan = wdev->channel;
138  *chanmode = CHAN_MODE_SHARED;
139  }
140  return;
143  case NL80211_IFTYPE_WDS:
144  /* these interface types don't really have a channel */
145  return;
147  if (wdev->wiphy->features &
149  *chanmode = CHAN_MODE_EXCLUSIVE;
150  return;
152  case NUM_NL80211_IFTYPES:
153  WARN_ON(1);
154  }
155 
156  return;
157 }