* released under the GPL
*/
-
#include "ieee80211.h"
#include <linux/random.h>
u8 *tag = *tag_p;
if (ieee->modulation & IEEE80211_OFDM_MODULATION){
-
*tag++ = MFIE_TYPE_RATES_EX;
*tag++ = 8;
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
}
-
/* We may add an option for custom rates that specific HW might support */
*tag_p = tag;
}
-
static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
{
u8 *tag = *tag_p;
ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
}
-
void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
inline void softmac_mgmt_xmit(struct sk_buff *skb,
struct ieee80211_hdr_3addr *header=
(struct ieee80211_hdr_3addr *) skb->data;
-
spin_lock_irqsave(&ieee->lock, flags);
/* called with 2nd param 0, no mgmt lock required */
if(single){
if(ieee->queue_stop){
-
enqueue_mgmt(ieee,skb);
}else{
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
}
}
-
inline void softmac_ps_mgmt_xmit(struct sk_buff *skb,
struct ieee80211_device *ieee)
{
-
short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
struct ieee80211_hdr_3addr *header =
(struct ieee80211_hdr_3addr *) skb->data;
-
if(single){
-
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
/* avoid watchdog triggers */
ieee->dev->trans_start = jiffies;
ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
-
}else{
-
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
if (ieee->seq_ctrl[0] == 0xFFF)
/* avoid watchdog triggers */
ieee->dev->trans_start = jiffies;
ieee->softmac_hard_start_xmit(skb,ieee->dev);
-
}
}
+
inline struct sk_buff *
ieee80211_disassociate_skb(struct ieee80211_network *beacon,
struct ieee80211_device *ieee, u8 asRsn)
disass->reasoncode = asRsn;
return skb;
}
+
void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn)
{
struct ieee80211_network *beacon = &ieee->current_network;
while(1)
{
-
do{
ch++;
if (ch > MAX_CHANNEL_NUMBER)
if (ieee->sync_scan_hurryup)
goto out;
-
msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME);
-
}
out:
ieee->sync_scan_hurryup = 0;
(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
if (watchdog++ > MAX_CHANNEL_NUMBER)
goto out; /* no good chans */
-
}while(!channel_map[ieee->current_network.channel]);
if (ieee->scanning == 0 )
del_timer_sync(&ieee->beacon_timer);
spin_unlock_irqrestore(&ieee->beacon_lock,flags);
-
}
-
void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
{
if(ieee->stop_send_beacons)
ieee80211_beacons_stop(ieee);
}
-
void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
{
if(ieee->start_send_beacons)
ieee80211_beacons_start(ieee);
}
-
static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
{
down(&ieee->scan_sem);
}
}else
ieee->start_scan(ieee->dev);
-
}
/* called with wx_sem held */
ieee80211_softmac_scan_syncro(ieee);
else
ieee->scan_syncro(ieee->dev);
-
}
inline struct sk_buff *
auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
return skb;
-
}
static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee,
memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
}
-
skb->dev = ieee->dev;
return skb;
}
assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
-
if(ieee->short_slot)
assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
memcpy(auth->header.addr1, dest, ETH_ALEN);
auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
return skb;
-
-
}
static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee, short pwr)
(pwr ? IEEE80211_FCTL_PM:0));
return skb;
-
-
}
-
static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
{
struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
}
}
-
static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8 *dest)
{
struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
}
}
-
static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
{
-
struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
if (buf) {
}
}
-
inline struct sk_buff *
ieee80211_association_req(struct ieee80211_network *beacon,
struct ieee80211_device *ieee)
hdr = (struct ieee80211_assoc_request_frame *)
skb_put(skb, sizeof(struct ieee80211_assoc_request_frame));
-
hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
hdr->header.duration_id= 37; //FIXME
memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
if(turbo_info_len) {
ieee80211_TURBO_Info(ieee, &tag);
}
-
return skb;
}
void ieee80211_associate_abort(struct ieee80211_device *ieee)
{
-
unsigned long flags;
spin_lock_irqsave(&ieee->lock, flags);
ieee80211_associate_abort((struct ieee80211_device *) dev);
}
-
static void ieee80211_associate_step1(struct ieee80211_device *ieee)
{
struct ieee80211_network *beacon = &ieee->current_network;
ieee->softmac_stats.tx_auth_rq++;
skb=ieee80211_authentication_req(beacon, ieee, 0);
if (!skb){
-
ieee80211_associate_abort(ieee);
}
else{
printk(KERN_INFO "Associated successfully\n");
if(ieee80211_is_54g(&ieee->current_network) &&
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
-
ieee->rate = 540;
printk(KERN_INFO"Using G rates\n");
}else{
if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
return;
-
if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
/* if the user specified the AP MAC, we need also the essid
* This could be obtained by beacons or, if the network does not
*/
(!apset && ssidset && ssidbroad && ssidmatch)
){
-
-
/* if the essid is hidden replace it with the
* essid provided by the user.
*/
ieee->state = IEEE80211_LINKED;
ieee->beinretry = false;
}
-
}
}
-
}
void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
spin_lock_irqsave(&ieee->lock, flags);
list_for_each_entry(target, &ieee->network_list, list) {
-
/* if the state become different that NOLINK means
* we had found what we are searching for
*/
-
if (ieee->state != IEEE80211_NOLINK)
break;
if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
ieee80211_softmac_new_net(ieee, target);
}
-
spin_unlock_irqrestore(&ieee->lock, flags);
-
}
-
static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
{
struct ieee80211_authentication *a;
return -ENOMEM;
}
}
-
return cpu_to_le16(a->status);
-
}
-
static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
{
struct ieee80211_authentication *a;
if (status != -1) {
ieee80211_resp_to_auth(ieee, status, dest);
}
-
}
inline void
printk(KERN_INFO"New client associated: %pM\n", dest);
}
-
-
void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
{
-
struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
if (buf)
softmac_ps_mgmt_xmit(buf, ieee);
-
}
-
static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
u32 *time_l)
{
}
return 1;
-
-
}
static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
spin_lock_irqsave(&ieee->lock, flags);
if((ieee->ps == IEEE80211_PS_DISABLED ||
-
ieee->iw_mode != IW_MODE_INFRA ||
ieee->state != IEEE80211_LINKED)){
goto out;
if(sleep == 1){
-
if(ieee->sta_sleep == 1)
ieee->enter_sleep_state(ieee->dev,th,tl);
else if(ieee->sta_sleep == 0){
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
-
if(ieee->ps_is_queue_empty(ieee->dev)){
-
-
ieee->sta_sleep = 2;
ieee->ps_request_tx_ack(ieee->dev);
ieee->ps_tl = tl;
}
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
-
}
-
-
}else if(sleep == 2){
//#warning CHECK_LOCK_HERE
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
}
-
out:
spin_unlock_irqrestore(&ieee->lock, flags);
-
}
void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
ieee80211_sta_ps_send_null_frame(ieee, 0);
}
return;
-
}
if(ieee->sta_sleep == 1)
*/
}
else {
-
if((ieee->sta_sleep == 0) && !success){
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
ieee80211_sta_ps_send_null_frame(ieee, 0);
ieee->last_rx_ps_time = jiffies;
switch (WLAN_FC_GET_STYPE(header->frame_control)) {
-
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
-
IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
WLAN_FC_GET_STYPE(header->frame_ctl));
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
}
}
break;
-
case IEEE80211_STYPE_ASSOC_REQ:
case IEEE80211_STYPE_REASSOC_REQ:
-
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
ieee->iw_mode == IW_MODE_MASTER)
ieee80211_rx_assoc_rq(ieee, skb);
break;
-
case IEEE80211_STYPE_AUTH:
-
if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
ieee->iw_mode == IW_MODE_INFRA){
-
IEEE80211_DEBUG_MGMT("Received authentication response");
errcode = auth_parse(skb, &challenge, &chlen);
}
}
break;
-
case IEEE80211_STYPE_PROBE_REQ:
-
if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
((ieee->iw_mode == IW_MODE_ADHOC ||
ieee->iw_mode == IW_MODE_MASTER) &&
ieee80211_rx_probe_rq(ieee, skb);
break;
-
case IEEE80211_STYPE_DISASSOC:
case IEEE80211_STYPE_DEAUTH:
/* FIXME for now repeat all the association procedure
queue_work(ieee->wq, &ieee->associate_procedure_wq);
}
-
break;
-
default:
return -1;
break;
}
-
return 0;
}
-
-
/* following are for a simpler TX queue management.
* Instead of using netif_[stop/wake]_queue the driver
* will uses these two function (plus a reset one), that
void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
struct ieee80211_device *ieee)
{
-
-
unsigned long flags;
int i;
ieee80211_sta_wakeup(ieee,0);
for(i = 0; i < txb->nr_frags; i++) {
-
if (ieee->queue_stop){
ieee->tx_pending.txb = txb;
ieee->tx_pending.frag = i;
exit:
spin_unlock_irqrestore(&ieee->lock,flags);
-
}
/* called with ieee->lock acquired */
ieee->tx_pending.frag = i;
return;
}else{
-
ieee->softmac_data_hard_start_xmit(
ieee->tx_pending.txb->fragments[i],
ieee->dev,ieee->rate);
}
}
-
ieee80211_txb_free(ieee->tx_pending.txb);
ieee->tx_pending.txb = NULL;
}
-
void ieee80211_reset_queue(struct ieee80211_device *ieee)
{
unsigned long flags;
}
ieee->queue_stop = 0;
spin_unlock_irqrestore(&ieee->lock,flags);
-
}
void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
{
-
unsigned long flags;
struct sk_buff *skb;
struct ieee80211_hdr_3addr *header;
if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
-
header = (struct ieee80211_hdr_3addr *) skb->data;
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
ieee->softmac_stats.swtxawake++;
netif_wake_queue(ieee->dev);
}
-
exit :
spin_unlock_irqrestore(&ieee->lock,flags);
}
-
void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
{
-
if (! netif_queue_stopped(ieee->dev)){
netif_stop_queue(ieee->dev);
ieee->softmac_stats.swtxstop++;
}
ieee->queue_stop = 1;
-
}
-
inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
{
-
random_ether_addr(ieee->current_network.bssid);
}
down(&ieee->wx_sem);
-
if (ieee->current_network.ssid_len == 0){
strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
ieee80211_randomize_cell(ieee);
if(ieee->modulation & IEEE80211_CCK_MODULATION){
-
ieee->current_network.rates_len = 4;
ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
if(ieee->short_slot)
ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
-
}
ieee->state = IEEE80211_LINKED;
up(&ieee->wx_sem);
}
+
inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
{
queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 100);
b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
return skb;
-
}
struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
up(&ieee->wx_sem);
}
-
void ieee80211_stop_protocol(struct ieee80211_device *ieee)
{
if (!ieee->proto_started)
ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
-
/* if the user set the MAC of the ad-hoc cell and then
* switch to managed mode, shall we make sure that association
* attempts does not fail just because the user provide the essid
}
}
-
#define DRV_NAME "Ieee80211"
void ieee80211_softmac_init(struct ieee80211_device *ieee)
{
del_timer_sync(&ieee->associate_timer);
cancel_delayed_work(&ieee->associate_retry_wq);
-
//add for RF power on power of
cancel_delayed_work(&ieee->GPIOChangeRFWorkItem);
* Start of WPA code. *
* this is stolen from the ipw2200 driver *
********************************************************/
-
-
static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
{
/* This is called when wpa_supplicant loads and closes the driver
return 0;
}
-
static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie,
int wpa_ie_len)
{
ieee80211_disassociate(ieee);
}
-
static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command,
int reason)
{
-
int ret = 0;
switch (command) {
return ret;
}
-
static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
struct ieee_param *param, int plen)
{
static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
{
-
struct ieee80211_security sec = {
.flags = SEC_AUTH_MODE,
};
case IEEE_PARAM_PRIVACY_INVOKED:
ieee->privacy_invoked=value;
break;
-
case IEEE_PARAM_AUTH_ALGS:
ret = ieee80211_wpa_set_auth_algs(ieee, value);
break;
-
case IEEE_PARAM_IEEE_802_1X:
ieee->ieee802_1x=value;
break;
ieee->wpax_type_notify = value;
spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
break;
-
default:
printk("Unknown WPA param: %d\n",name);
ret = -EOPNOTSUPP;
}
switch (param->cmd) {
-
case IEEE_CMD_SET_WPA_PARAM:
ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
param->u.wpa_param.value);
break;
-
case IEEE_CMD_SET_WPA_IE:
ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
break;
-
case IEEE_CMD_SET_ENCRYPTION:
ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
break;
-
case IEEE_CMD_MLME:
ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
param->u.mlme.reason_code);
break;
-
default:
printk("Unknown WPA supplicant request: %d\n",param->cmd);
ret = -EOPNOTSUPP;