blob: 1a87d3a0967c054d5d4b851e194daa9b3bbcdcf7 [file] [log] [blame]
David Kilroyea60a6a2009-06-18 23:21:26 +01001/* cfg80211 support
2 *
3 * See copyright notice in main.c
4 */
5#include <linux/ieee80211.h>
6#include <net/cfg80211.h>
7#include "hw.h"
8#include "main.h"
9#include "orinoco.h"
10
11#include "cfg.h"
12
13/* Supported bitrates. Must agree with hw.c */
14static struct ieee80211_rate orinoco_rates[] = {
15 { .bitrate = 10 },
16 { .bitrate = 20 },
17 { .bitrate = 55 },
18 { .bitrate = 110 },
19};
20
21static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid;
22
23/* Called after orinoco_private is allocated. */
24void orinoco_wiphy_init(struct wiphy *wiphy)
25{
26 struct orinoco_private *priv = wiphy_priv(wiphy);
27
28 wiphy->privid = orinoco_wiphy_privid;
29
30 set_wiphy_dev(wiphy, priv->dev);
31}
32
33/* Called after firmware is initialised */
34int orinoco_wiphy_register(struct wiphy *wiphy)
35{
36 struct orinoco_private *priv = wiphy_priv(wiphy);
37 int i, channels = 0;
38
39 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
40 wiphy->max_scan_ssids = 1;
41 else
42 wiphy->max_scan_ssids = 0;
43
44 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
45
46 /* TODO: should we set if we only have demo ad-hoc?
47 * (priv->has_port3)
48 */
49 if (priv->has_ibss)
50 wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
51
52 if (!priv->broken_monitor || force_monitor)
53 wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
54
55 priv->band.bitrates = orinoco_rates;
56 priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates);
57
58 /* Only support channels allowed by the card EEPROM */
59 for (i = 0; i < NUM_CHANNELS; i++) {
60 if (priv->channel_mask & (1 << i)) {
61 priv->channels[i].center_freq =
62 ieee80211_dsss_chan_to_freq(i+1);
63 channels++;
64 }
65 }
66 priv->band.channels = priv->channels;
67 priv->band.n_channels = channels;
68
69 wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
70 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
71
72 i = 0;
73 if (priv->has_wep) {
74 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40;
75 i++;
76
77 if (priv->has_big_wep) {
78 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104;
79 i++;
80 }
81 }
82 if (priv->has_wpa) {
83 priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP;
84 i++;
85 }
86 wiphy->cipher_suites = priv->cipher_suites;
87 wiphy->n_cipher_suites = i;
88
89 wiphy->rts_threshold = priv->rts_thresh;
90 if (!priv->has_mwo)
91 wiphy->frag_threshold = priv->frag_thresh;
92
93 return wiphy_register(wiphy);
94}
95
David Kilroy5217c572009-06-18 23:21:32 +010096static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
97 enum nl80211_iftype type, u32 *flags,
98 struct vif_params *params)
99{
100 struct orinoco_private *priv = wiphy_priv(wiphy);
101 int err = 0;
102 unsigned long lock;
David Kilroyea60a6a2009-06-18 23:21:26 +0100103
David Kilroy5217c572009-06-18 23:21:32 +0100104 if (orinoco_lock(priv, &lock) != 0)
105 return -EBUSY;
106
107 switch (type) {
108 case NL80211_IFTYPE_ADHOC:
109 if (!priv->has_ibss && !priv->has_port3)
110 err = -EINVAL;
111 break;
112
113 case NL80211_IFTYPE_STATION:
114 break;
115
116 case NL80211_IFTYPE_MONITOR:
117 if (priv->broken_monitor && !force_monitor) {
118 printk(KERN_WARNING "%s: Monitor mode support is "
119 "buggy in this firmware, not enabling\n",
120 wiphy_name(wiphy));
121 err = -EINVAL;
122 }
123 break;
124
125 default:
126 err = -EINVAL;
127 }
128
129 if (!err) {
130 priv->iw_mode = type;
131 set_port_type(priv);
132 err = orinoco_commit(priv);
133 }
134
135 orinoco_unlock(priv, &lock);
136
137 return err;
138}
139
David Kilroyc63cdbe2009-06-18 23:21:33 +0100140static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
141 struct cfg80211_scan_request *request)
142{
143 struct orinoco_private *priv = wiphy_priv(wiphy);
144 int err;
145
146 if (!request)
147 return -EINVAL;
148
149 if (priv->scan_request && priv->scan_request != request)
150 return -EBUSY;
151
152 priv->scan_request = request;
153
154 err = orinoco_hw_trigger_scan(priv, request->ssids);
155
156 return err;
157}
158
David Kilroy5217c572009-06-18 23:21:32 +0100159const struct cfg80211_ops orinoco_cfg_ops = {
160 .change_virtual_intf = orinoco_change_vif,
David Kilroyc63cdbe2009-06-18 23:21:33 +0100161 .scan = orinoco_scan,
David Kilroyea60a6a2009-06-18 23:21:26 +0100162};