Functions | |
| static void | net80211_add_channels (struct net80211_device *dev, int start, int len, int txpower) |
| Add channels to 802.11 device. | |
| static void | net80211_filter_hw_channels (struct net80211_device *dev) |
| Filter 802.11 device channels for hardware capabilities. | |
| static void | net80211_set_rtscts_rate (struct net80211_device *dev) |
| Pick TX rate for RTS/CTS packets based on data rate. | |
| static int | net80211_process_capab (struct net80211_device *dev, u16 capab) |
| Update 802.11 device state to reflect received capabilities field. | |
| static int | net80211_process_ie (struct net80211_device *dev, union ieee80211_ie *ie, void *ie_end) |
| Update 802.11 device state to reflect received information elements. | |
| static union ieee80211_ie * | net80211_marshal_request_info (struct net80211_device *dev, union ieee80211_ie *ie) |
| Create information elements for outgoing probe or association packet. | |
| static void net80211_add_channels | ( | struct net80211_device * | dev, | |
| int | start, | |||
| int | len, | |||
| int | txpower | |||
| ) | [static] |
Add channels to 802.11 device.
| dev | 802.11 device | |
| start | First channel number to add | |
| len | Number of channels to add | |
| txpower | TX power (dBm) to allow on added channels |
Definition at line 925 of file net80211.c.
References net80211_channel::band, net80211_channel::center_freq, net80211_channel::channel_nr, net80211_device::channels, net80211_channel::hw_value, net80211_channel::maxpower, NET80211_BAND_2GHZ, NET80211_BAND_5GHZ, NET80211_MAX_CHANNELS, and net80211_device::nr_channels.
Referenced by net80211_prepare_probe(), and net80211_process_ie().
00927 { 00928 int i, chan = start; 00929 00930 for ( i = dev->nr_channels; len-- && i < NET80211_MAX_CHANNELS; i++ ) { 00931 dev->channels[i].channel_nr = chan; 00932 dev->channels[i].maxpower = txpower; 00933 dev->channels[i].hw_value = 0; 00934 00935 if ( chan >= 1 && chan <= 14 ) { 00936 dev->channels[i].band = NET80211_BAND_2GHZ; 00937 if ( chan == 14 ) 00938 dev->channels[i].center_freq = 2484; 00939 else 00940 dev->channels[i].center_freq = 2407 + 5 * chan; 00941 chan++; 00942 } else { 00943 dev->channels[i].band = NET80211_BAND_5GHZ; 00944 dev->channels[i].center_freq = 5000 + 5 * chan; 00945 chan += 4; 00946 } 00947 } 00948 00949 dev->nr_channels = i; 00950 }
| static void net80211_filter_hw_channels | ( | struct net80211_device * | dev | ) | [static] |
Filter 802.11 device channels for hardware capabilities.
| dev | 802.11 device |
Channels are matched based on center frequency, ignoring band and channel number.
If the driver specifies no supported channels, the effect will be as though all were supported.
Definition at line 969 of file net80211.c.
References net80211_channel::center_freq, net80211_device::channel, net80211_hw_info::channels, net80211_device::channels, net80211_device_operations::config, net80211_device::hw, net80211_channel::hw_value, net80211_channel::maxpower, NET80211_CFG_CHANNEL, net80211_device::nr_channels, net80211_hw_info::nr_channels, and net80211_device::op.
Referenced by net80211_prepare_probe(), and net80211_process_ie().
00970 { 00971 int delta = 0, i = 0; 00972 int old_freq = dev->channels[dev->channel].center_freq; 00973 struct net80211_channel *chan, *hwchan; 00974 00975 if ( ! dev->hw->nr_channels ) 00976 return; 00977 00978 dev->channel = 0; 00979 for ( chan = dev->channels; chan < dev->channels + dev->nr_channels; 00980 chan++, i++ ) { 00981 int ok = 0; 00982 for ( hwchan = dev->hw->channels; 00983 hwchan < dev->hw->channels + dev->hw->nr_channels; 00984 hwchan++ ) { 00985 if ( hwchan->center_freq == chan->center_freq ) { 00986 ok = 1; 00987 break; 00988 } 00989 } 00990 00991 if ( ! ok ) 00992 delta++; 00993 else { 00994 chan->hw_value = hwchan->hw_value; 00995 if ( hwchan->maxpower != 0 && 00996 chan->maxpower > hwchan->maxpower ) 00997 chan->maxpower = hwchan->maxpower; 00998 if ( old_freq == chan->center_freq ) 00999 dev->channel = i - delta; 01000 if ( delta ) 01001 chan[-delta] = *chan; 01002 } 01003 } 01004 01005 dev->nr_channels -= delta; 01006 01007 if ( dev->channels[dev->channel].center_freq != old_freq ) 01008 dev->op->config ( dev, NET80211_CFG_CHANNEL ); 01009 }
| static void net80211_set_rtscts_rate | ( | struct net80211_device * | dev | ) | [static] |
Pick TX rate for RTS/CTS packets based on data rate.
| dev | 802.11 device |
Definition at line 1980 of file net80211.c.
References net80211_device::basic_rates, net80211_device::nr_rates, net80211_device::rate, net80211_device::rates, net80211_device::rtscts_rate, and u16.
Referenced by net80211_process_ie(), and net80211_set_rate_idx().
01981 { 01982 u16 datarate = dev->rates[dev->rate]; 01983 u16 rtsrate = 0; 01984 int rts_idx = -1; 01985 int i; 01986 01987 for ( i = 0; i < dev->nr_rates; i++ ) { 01988 u16 rate = dev->rates[i]; 01989 01990 if ( ! ( dev->basic_rates & ( 1 << i ) ) || rate > datarate ) 01991 continue; 01992 01993 if ( rate > rtsrate ) { 01994 rtsrate = rate; 01995 rts_idx = i; 01996 } 01997 } 01998 01999 /* If this is in initialization, we might not have any basic 02000 rates; just use the first data rate in that case. */ 02001 if ( rts_idx < 0 ) 02002 rts_idx = 0; 02003 02004 dev->rtscts_rate = rts_idx; 02005 }
| static int net80211_process_capab | ( | struct net80211_device * | dev, | |
| u16 | capab | |||
| ) | [static] |
Update 802.11 device state to reflect received capabilities field.
| dev | 802.11 device | |
| capab | Capabilities field in beacon, probe, or association frame |
| rc | Return status code |
Definition at line 1018 of file net80211.c.
References net80211_device_operations::config, DBGC, ENOSYS, IEEE80211_CAPAB_ADHOC, IEEE80211_CAPAB_MANAGED, IEEE80211_CAPAB_SHORT_PMBL, IEEE80211_CAPAB_SHORT_SLOT, NET80211_CFG_PHY_PARAMS, NET80211_PHY_USE_SHORT_PREAMBLE, NET80211_PHY_USE_SHORT_SLOT, net80211_device::op, net80211_device::phy_flags, and u16.
Referenced by net80211_handle_assoc_reply(), and net80211_prepare_assoc().
01020 { 01021 u16 old_phy = dev->phy_flags; 01022 01023 if ( ( capab & ( IEEE80211_CAPAB_MANAGED | IEEE80211_CAPAB_ADHOC ) ) != 01024 IEEE80211_CAPAB_MANAGED ) { 01025 DBGC ( dev, "802.11 %p cannot handle IBSS network\n", dev ); 01026 return -ENOSYS; 01027 } 01028 01029 dev->phy_flags &= ~( NET80211_PHY_USE_SHORT_PREAMBLE | 01030 NET80211_PHY_USE_SHORT_SLOT ); 01031 01032 if ( capab & IEEE80211_CAPAB_SHORT_PMBL ) 01033 dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE; 01034 01035 if ( capab & IEEE80211_CAPAB_SHORT_SLOT ) 01036 dev->phy_flags |= NET80211_PHY_USE_SHORT_SLOT; 01037 01038 if ( old_phy != dev->phy_flags ) 01039 dev->op->config ( dev, NET80211_CFG_PHY_PARAMS ); 01040 01041 return 0; 01042 }
| static int net80211_process_ie | ( | struct net80211_device * | dev, | |
| union ieee80211_ie * | ie, | |||
| void * | ie_end | |||
| ) | [static] |
Update 802.11 device state to reflect received information elements.
| dev | 802.11 device | |
| ie | Pointer to first information element | |
| ie_end | Pointer to tail of packet I/O buffer |
| rc | Return status code |
Definition at line 1052 of file net80211.c.
References ieee80211_ie_country_triplet::band, net80211_channel::band, net80211_device::basic_rates, net80211_device::channel, net80211_channel::channel_nr, net80211_device::channels, net80211_device_operations::config, ieee80211_ie::country, ieee80211_ie_ds_param::current_channel, DBGC, ieee80211_ie::ds_param, ieee80211_ie::erp_info, net80211_device::essid, ieee80211_ie_country_triplet::first, ieee80211_ie_country_band_triplet::first_channel, net80211_hw_info::flags, net80211_device::hw, ieee80211_ie::id, IEEE80211_ERP_BARKER_LONG, IEEE80211_ERP_USE_PROTECTION, ieee80211_ie_bound(), IEEE80211_IE_COUNTRY, IEEE80211_IE_DS_PARAM, IEEE80211_IE_ERP_INFO, IEEE80211_IE_EXT_RATES, IEEE80211_IE_RATES, IEEE80211_IE_SSID, ieee80211_next_ie(), ieee80211_ie::len, ieee80211_ie_country_band_triplet::max_txpower, memcpy, ieee80211_ie_country::name, net80211_add_channels(), NET80211_CFG_PHY_PARAMS, NET80211_CFG_RATE, net80211_change_channel(), net80211_filter_hw_channels(), NET80211_MAX_RATES, NET80211_PHY_USE_PROTECTION, NET80211_PHY_USE_SHORT_PREAMBLE, NET80211_PHY_USE_SHORT_SLOT, net80211_set_rtscts_rate(), ieee80211_ie_country_band_triplet::nr_channels, net80211_device::nr_channels, net80211_hw_info::nr_rates, net80211_device::nr_rates, net80211_device::op, net80211_device::phy_flags, net80211_device::rate, net80211_hw_info::rates, ieee80211_ie::rates, net80211_device::rates, ieee80211_ie::ssid, ieee80211_ie_country::triplet, u16, u32, and u8.
Referenced by net80211_handle_assoc_reply(), and net80211_prepare_assoc().
01054 { 01055 u16 old_rate = dev->rates[dev->rate]; 01056 u16 old_phy = dev->phy_flags; 01057 int have_rates = 0, i; 01058 int ds_channel = 0; 01059 int changed = 0; 01060 int band = dev->channels[dev->channel].band; 01061 01062 if ( ! ieee80211_ie_bound ( ie, ie_end ) ) 01063 return 0; 01064 01065 for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) { 01066 switch ( ie->id ) { 01067 case IEEE80211_IE_SSID: 01068 if ( ie->len <= 32 ) { 01069 memcpy ( dev->essid, ie->ssid, ie->len ); 01070 dev->essid[ie->len] = 0; 01071 } 01072 break; 01073 01074 case IEEE80211_IE_RATES: 01075 case IEEE80211_IE_EXT_RATES: 01076 if ( ! have_rates ) { 01077 dev->nr_rates = 0; 01078 dev->basic_rates = 0; 01079 have_rates = 1; 01080 } 01081 for ( i = 0; i < ie->len && 01082 dev->nr_rates < NET80211_MAX_RATES; i++ ) { 01083 u8 rid = ie->rates[i]; 01084 u16 rate = ( rid & 0x7f ) * 5; 01085 01086 if ( rid & 0x80 ) 01087 dev->basic_rates |= 01088 ( 1 << dev->nr_rates ); 01089 01090 dev->rates[dev->nr_rates++] = rate; 01091 } 01092 01093 break; 01094 01095 case IEEE80211_IE_DS_PARAM: 01096 if ( dev->channel < dev->nr_channels && ds_channel == 01097 dev->channels[dev->channel].channel_nr ) 01098 break; 01099 ds_channel = ie->ds_param.current_channel; 01100 net80211_change_channel ( dev, ds_channel ); 01101 break; 01102 01103 case IEEE80211_IE_COUNTRY: 01104 dev->nr_channels = 0; 01105 01106 DBGC ( dev, "802.11 %p setting country regulations " 01107 "for %c%c\n", dev, ie->country.name[0], 01108 ie->country.name[1] ); 01109 for ( i = 0; i < ( ie->len - 3 ) / 3; i++ ) { 01110 union ieee80211_ie_country_triplet *t = 01111 &ie->country.triplet[i]; 01112 if ( t->first > 200 ) { 01113 DBGC ( dev, "802.11 %p ignoring regulatory " 01114 "extension information\n", dev ); 01115 } else { 01116 net80211_add_channels ( dev, 01117 t->band.first_channel, 01118 t->band.nr_channels, 01119 t->band.max_txpower ); 01120 } 01121 } 01122 net80211_filter_hw_channels ( dev ); 01123 break; 01124 01125 case IEEE80211_IE_ERP_INFO: 01126 dev->phy_flags &= ~( NET80211_PHY_USE_PROTECTION | 01127 NET80211_PHY_USE_SHORT_PREAMBLE ); 01128 if ( ie->erp_info & IEEE80211_ERP_USE_PROTECTION ) 01129 dev->phy_flags |= NET80211_PHY_USE_PROTECTION; 01130 if ( ! ( ie->erp_info & IEEE80211_ERP_BARKER_LONG ) ) 01131 dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE; 01132 break; 01133 } 01134 } 01135 01136 if ( have_rates ) { 01137 /* Allow only those rates that are also supported by 01138 the hardware. */ 01139 int delta = 0, j; 01140 01141 dev->rate = 0; 01142 for ( i = 0; i < dev->nr_rates; i++ ) { 01143 int ok = 0; 01144 for ( j = 0; j < dev->hw->nr_rates[band]; j++ ) { 01145 if ( dev->hw->rates[band][j] == dev->rates[i] ){ 01146 ok = 1; 01147 break; 01148 } 01149 } 01150 01151 if ( ! ok ) 01152 delta++; 01153 else { 01154 dev->rates[i - delta] = dev->rates[i]; 01155 if ( old_rate == dev->rates[i] ) 01156 dev->rate = i - delta; 01157 } 01158 } 01159 01160 dev->nr_rates -= delta; 01161 01162 /* Sort available rates - sorted subclumps tend to already 01163 exist, so insertion sort works well. */ 01164 for ( i = 1; i < dev->nr_rates; i++ ) { 01165 u16 rate = dev->rates[i]; 01166 u32 tmp, br, mask; 01167 01168 for ( j = i - 1; j >= 0 && dev->rates[j] >= rate; j-- ) 01169 dev->rates[j + 1] = dev->rates[j]; 01170 dev->rates[j + 1] = rate; 01171 01172 /* Adjust basic_rates to match by rotating the 01173 bits from bit j+1 to bit i left one position. */ 01174 mask = ( ( 1 << i ) - 1 ) & ~( ( 1 << ( j + 1 ) ) - 1 ); 01175 br = dev->basic_rates; 01176 tmp = br & ( 1 << i ); 01177 br = ( br & ~( mask | tmp ) ) | ( ( br & mask ) << 1 ); 01178 br |= ( tmp >> ( i - j - 1 ) ); 01179 dev->basic_rates = br; 01180 } 01181 01182 net80211_set_rtscts_rate ( dev ); 01183 01184 if ( dev->rates[dev->rate] != old_rate ) 01185 changed |= NET80211_CFG_RATE; 01186 } 01187 01188 if ( dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE ) 01189 dev->phy_flags &= ~NET80211_PHY_USE_SHORT_PREAMBLE; 01190 if ( dev->hw->flags & NET80211_HW_NO_SHORT_SLOT ) 01191 dev->phy_flags &= ~NET80211_PHY_USE_SHORT_SLOT; 01192 01193 if ( old_phy != dev->phy_flags ) 01194 changed |= NET80211_CFG_PHY_PARAMS; 01195 01196 if ( changed ) 01197 dev->op->config ( dev, changed ); 01198 01199 return 0; 01200 }
| static union ieee80211_ie * net80211_marshal_request_info | ( | struct net80211_device * | dev, | |
| union ieee80211_ie * | ie | |||
| ) | [static, write] |
Create information elements for outgoing probe or association packet.
| dev | 802.11 device | |
| ie | Pointer to start of information element area |
| next_ie | Pointer to first byte after added information elements |
Definition at line 1210 of file net80211.c.
References net80211_device::basic_rates, net80211_device::essid, ieee80211_ie::id, IEEE80211_IE_EXT_RATES, IEEE80211_IE_RATES, IEEE80211_IE_RSN, IEEE80211_IE_SSID, IEEE80211_IE_VENDOR, ieee80211_next_ie(), ieee80211_ie::len, memcpy, net80211_device::nr_rates, NULL, net80211_device::rates, ieee80211_ie::rates, net80211_device::rsn_ie, ieee80211_ie::ssid, and strlen().
Referenced by net80211_probe_start(), and net80211_send_assoc().
01212 { 01213 int i; 01214 01215 ie->id = IEEE80211_IE_SSID; 01216 ie->len = strlen ( dev->essid ); 01217 memcpy ( ie->ssid, dev->essid, ie->len ); 01218 01219 ie = ieee80211_next_ie ( ie, NULL ); 01220 01221 ie->id = IEEE80211_IE_RATES; 01222 ie->len = dev->nr_rates; 01223 if ( ie->len > 8 ) 01224 ie->len = 8; 01225 01226 for ( i = 0; i < ie->len; i++ ) { 01227 ie->rates[i] = dev->rates[i] / 5; 01228 if ( dev->basic_rates & ( 1 << i ) ) 01229 ie->rates[i] |= 0x80; 01230 } 01231 01232 ie = ieee80211_next_ie ( ie, NULL ); 01233 01234 if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_RSN ) { 01235 memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 ); 01236 ie = ieee80211_next_ie ( ie, NULL ); 01237 } 01238 01239 if ( dev->nr_rates > 8 ) { 01240 /* 802.11 requires we use an Extended Basic Rates IE 01241 for the rates beyond the eighth. */ 01242 01243 ie->id = IEEE80211_IE_EXT_RATES; 01244 ie->len = dev->nr_rates - 8; 01245 01246 for ( ; i < dev->nr_rates; i++ ) { 01247 ie->rates[i - 8] = dev->rates[i] / 5; 01248 if ( dev->basic_rates & ( 1 << i ) ) 01249 ie->rates[i - 8] |= 0x80; 01250 } 01251 01252 ie = ieee80211_next_ie ( ie, NULL ); 01253 } 01254 01255 if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_VENDOR ) { 01256 memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 ); 01257 ie = ieee80211_next_ie ( ie, NULL ); 01258 } 01259 01260 return ie; 01261 }
1.5.7.1