diff options
Diffstat (limited to 'drivers/staging/ks7010/ks7010_config.c')
-rw-r--r-- | drivers/staging/ks7010/ks7010_config.c | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/drivers/staging/ks7010/ks7010_config.c b/drivers/staging/ks7010/ks7010_config.c new file mode 100644 index 0000000..4a80984 --- /dev/null +++ b/drivers/staging/ks7010/ks7010_config.c @@ -0,0 +1,556 @@ +#include <linux/kernel.h> +#include <linux/mmc/sdio_func.h> + +#include "ks_wlan.h" +#include "ks_hostif.h" +#include "ks_wlan_ioctl.h" +#include "ks_debug.h" + +static int wep_on_off; +#define WEP_OFF 0 +#define WEP_ON_64BIT 1 +#define WEP_ON_128BIT 2 + +static int wep_type; +#define WEP_KEY_CHARACTER 0 +#define WEP_KEY_HEX 1 + +static +void analyze_character_wep_key(struct ks_wlan_parameter *param, int wep_key_index, char *value) +{ + int i; + unsigned char wep_key[26], key_length; + + key_length = (wep_on_off == WEP_ON_64BIT) ? 5 : 13; + /* 64bit key_length = 5; 128bit key_length = 13; */ + + for (i=0; i<key_length; i++) { + wep_key[i] = value[i]; + } + + if(wep_key_index < 0 || wep_key_index > 3) + return; + + param->wep_key[wep_key_index].size = key_length; + for (i=0; i<(param->wep_key[wep_key_index].size); i++) { + param->wep_key[wep_key_index].val[i] = wep_key[i]; + } +} + +static +void analyze_hex_wep_key(struct ks_wlan_parameter *param, int wep_key_index, char *value) +{ + unsigned char wep_end[26], i, j, key_length; + + key_length = (wep_on_off == WEP_ON_64BIT) ? 10 : 26; + /* 64bit key_length = 10; 128bit key_length = 26; */ + + for (i=0; i<key_length; i++) { + wep_end[i] = value[i]; + if (i % 2) { + /* Odd */ + for (j=0x00; j<0x10; j++) { + if (j<0x0a) { + if (wep_end[i] == j+0x30) + wep_end[i] = j; + } else { + if ((wep_end[i] == j+0x37) | (wep_end[i] == j+0x57)) + wep_end[i] = j; + } + } + } else { + /* Even */ + for (j=0x00; j<0x10; j++) { + if (j<0x0a) { + if (wep_end[i] == j+0x30) { + wep_end[i] = j*16; + } + } else { + if ((wep_end[i] == j+0x37) | (wep_end[i] == j+0x57)) + wep_end[i] = j*16; + } + } + } + } + + for (i=0; i<key_length/2; i++) { + wep_end[i] = wep_end[i*2] + wep_end[(i*2)+1]; + } + + if(wep_key_index < 0 || wep_key_index > 3) + return ; + + param->wep_key[wep_key_index].size = key_length/2; + for (i=0; i<(param->wep_key[wep_key_index].size); i++) { + param->wep_key[wep_key_index].val[i] = wep_end[i]; + } + +} + +static +int rate_set_configuration(ks_wlan_private *priv, char *value) +{ + int rc=0; + + priv->reg.tx_rate = TX_RATE_FIXED; + priv->reg.rate_set.size = 1; + + switch(*value){ + case '1': /* 1M 11M 12M 18M */ + if(*(value+1) == '8'){ + priv->reg.rate_set.body[0] = TX_RATE_18M; + } + else if(*(value+1) == '2'){ + priv->reg.rate_set.body[0] = TX_RATE_12M|BASIC_RATE; + } + else if(*(value+1) == '1'){ + priv->reg.rate_set.body[0] = TX_RATE_11M|BASIC_RATE; + } + else{ + priv->reg.rate_set.body[0] = TX_RATE_1M|BASIC_RATE; + } + break; + case '2': /* 2M 24M */ + if(*(value+1) == '4'){ + priv->reg.rate_set.body[0] = TX_RATE_24M|BASIC_RATE; + } + else{ + priv->reg.rate_set.body[0] = TX_RATE_2M|BASIC_RATE; + } + break; + case '3': /* 36M */ + priv->reg.rate_set.body[0] = TX_RATE_36M; + break; + case '4': /* 48M */ + priv->reg.rate_set.body[0] = TX_RATE_48M; + break; + case '5': /* 5.5M 54M */ + if(*(value+1) == '4'){ + priv->reg.rate_set.body[0] = TX_RATE_54M; + } + else{ + priv->reg.rate_set.body[0] = TX_RATE_5M|BASIC_RATE; + } + break; + case '6': /* 6M */ + priv->reg.rate_set.body[0] = TX_RATE_6M|BASIC_RATE; + break; + case '9': /* 9M */ + priv->reg.rate_set.body[0] = TX_RATE_9M; + break; + case 'K': + priv->reg.rate_set.body[6] = TX_RATE_36M; + priv->reg.rate_set.body[5] = TX_RATE_18M; + priv->reg.rate_set.body[4] = TX_RATE_24M|BASIC_RATE; + priv->reg.rate_set.body[3] = TX_RATE_12M|BASIC_RATE; + priv->reg.rate_set.body[2] = TX_RATE_6M|BASIC_RATE; + priv->reg.rate_set.body[1] = TX_RATE_11M|BASIC_RATE; + priv->reg.rate_set.body[0] = TX_RATE_2M|BASIC_RATE; + priv->reg.tx_rate = TX_RATE_FULL_AUTO; + priv->reg.rate_set.size = 7; + break; + default: + priv->reg.rate_set.body[11] = TX_RATE_54M; + priv->reg.rate_set.body[10] = TX_RATE_48M; + priv->reg.rate_set.body[9] = TX_RATE_36M; + priv->reg.rate_set.body[8] = TX_RATE_18M; + priv->reg.rate_set.body[7] = TX_RATE_9M; + priv->reg.rate_set.body[6] = TX_RATE_24M|BASIC_RATE; + priv->reg.rate_set.body[5] = TX_RATE_12M|BASIC_RATE; + priv->reg.rate_set.body[4] = TX_RATE_6M|BASIC_RATE; + priv->reg.rate_set.body[3] = TX_RATE_11M|BASIC_RATE; + priv->reg.rate_set.body[2] = TX_RATE_5M|BASIC_RATE; + priv->reg.rate_set.body[1] = TX_RATE_2M|BASIC_RATE; + priv->reg.rate_set.body[0] = TX_RATE_1M|BASIC_RATE; + priv->reg.tx_rate = TX_RATE_FULL_AUTO; + priv->reg.rate_set.size = 12; + break; + } + return rc; +} + +#ifndef NO_FIRMWARE_CLASS +#include <linux/firmware.h> +#else +#define MAX_CONFIG_FILE_SIZE (1024*10) +#endif +int ks_wlan_read_config_file(ks_wlan_private *priv) +{ + struct { + const int key_len; + const char *key; + const char *val; + } cfg_tbl[] = { + {15,"BeaconLostCount", "20"}, /* 0 */ + {7,"Channel", "1"}, /* 1 */ + {17,"FragmentThreshold","2346"}, /* 2 */ + {13,"OperationMode","Infrastructure"}, /* 3 */ + {19,"PowerManagementMode","ACTIVE"}, /* 4 */ + {12,"RTSThreshold","2347"}, /* 5 */ + {4,"SSID","default"}, /* 6 */ + {6,"TxRate","Auto"}, /* 7 */ + {23,"AuthenticationAlgorithm",""}, /* 8 */ + {12,"WepKeyValue1",""}, /* 9 */ + {12,"WepKeyValue2",""}, /* 10 */ + {12,"WepKeyValue3",""}, /* 11 */ + {12,"WepKeyValue4",""}, /* 12 */ + {8,"WepIndex","1"}, /* 13 */ + {7,"WepType","STRING"}, /* 14 */ + {3,"Wep","OFF"}, /* 15 */ + {13,"PREAMBLE_TYPE","SHORT"}, /* 16 */ + {8,"ScanType","ACTIVE_SCAN"}, /* 17 */ + {8,"ROM_FILE", ROM_FILE}, /* 18 */ + {7,"PhyType", "BG_MODE"}, /* 19 */ + {7,"CtsMode", "FALSE"}, /* 20 */ + {19,"PhyInformationTimer", "0"}, /* 21 */ + {0,"",""}, + }; + +#ifndef NO_FIRMWARE_CLASS + const struct firmware *fw_entry; + struct device *dev = NULL; + int retval; +#else + struct file *srcf; + int nr_read ; + int retval; + char *cfg_buf=NULL; + int orgfsuid, orgfsgid; + mm_segment_t orgfs; +#endif + char cfg_file[]=CFG_FILE; + char *cur_p, *end_p; + char wk_buff[256], *wk_p; + + /* Initialize Variable */ + priv->reg.operation_mode = MODE_INFRASTRUCTURE; /* Infrastructure */ + priv->reg.channel = 10; /* 10 */ + memset(priv->reg.bssid, 0x0, ETH_ALEN); /* BSSID */ + priv->reg.ssid.body[0] = '\0'; /* SSID */ + priv->reg.ssid.size = 0; /* SSID size */ + priv->reg.tx_rate = TX_RATE_AUTO; /* TxRate Fully Auto */ + priv->reg.preamble = SHORT_PREAMBLE; /* Preamble = SHORT */ + priv->reg.powermgt = POWMGT_ACTIVE_MODE; /* POWMGT_ACTIVE_MODE */ + priv->reg.scan_type = ACTIVE_SCAN; /* Active */ + priv->reg.beacon_lost_count = 20; /* Beacon Lost Count */ + priv->reg.rts = 2347UL; /* RTS Threashold */ + priv->reg.fragment = 2346UL; /* Fragmentation Threashold */ + + strcpy(&priv->reg.rom_file[0], ROM_FILE); + + priv->skb = NULL; + + priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; /* AuthenticationAlgorithm */ + + priv->reg.privacy_invoked = 0x00; /* WEP */ + priv->reg.wep_index=0; + memset(&priv->reg.wep_key[0],0,sizeof(priv->reg.wep_key[0])); + memset(&priv->reg.wep_key[1],0,sizeof(priv->reg.wep_key[0])); + memset(&priv->reg.wep_key[2],0,sizeof(priv->reg.wep_key[0])); + memset(&priv->reg.wep_key[3],0,sizeof(priv->reg.wep_key[0])); + + priv->reg.phy_type = D_11BG_COMPATIBLE_MODE; + priv->reg.cts_mode = CTS_MODE_FALSE; + priv->reg.phy_info_timer = 0; + priv->reg.rate_set.body[11] = TX_RATE_54M; + priv->reg.rate_set.body[10] = TX_RATE_48M; + priv->reg.rate_set.body[9] = TX_RATE_36M; + priv->reg.rate_set.body[8] = TX_RATE_18M; + priv->reg.rate_set.body[7] = TX_RATE_9M; + priv->reg.rate_set.body[6] = TX_RATE_24M|BASIC_RATE; + priv->reg.rate_set.body[5] = TX_RATE_12M|BASIC_RATE; + priv->reg.rate_set.body[4] = TX_RATE_6M|BASIC_RATE; + priv->reg.rate_set.body[3] = TX_RATE_11M|BASIC_RATE; + priv->reg.rate_set.body[2] = TX_RATE_5M|BASIC_RATE; + priv->reg.rate_set.body[1] = TX_RATE_2M|BASIC_RATE; + priv->reg.rate_set.body[0] = TX_RATE_1M|BASIC_RATE; + priv->reg.tx_rate = TX_RATE_FULL_AUTO; + priv->reg.rate_set.size = 12; + +#ifndef NO_FIRMWARE_CLASS +#if (defined _PCMCIA_) + dev = &priv->ks_wlan_hw.pcmcia_dev->dev; +#elif (defined _PCI_) + dev = &priv->ks_wlan_hw.pci_dev->dev; +#elif (defined _SDIO_) + dev = &priv->ks_wlan_hw.sdio_card->func->dev; +#endif + if((retval = request_firmware(&fw_entry, cfg_file, dev)) !=0 ){ + DPRINTK(1, "error request_firmware() file=%s ret=%d\n", cfg_file, retval); + return 1; + } + + DPRINTK(4, "success request_firmware() file=%s size=%d\n", cfg_file, fw_entry->size); + cur_p = fw_entry->data; + end_p = cur_p + fw_entry->size; +#else + orgfsuid=current->fsuid; + orgfsgid=current->fsgid; + orgfs=get_fs(); + set_fs(KERNEL_DS); + + srcf = filp_open(cfg_file, O_RDONLY, 0); + if (IS_ERR(srcf)) { + printk(KERN_ERR "error %ld opening %s\n", -PTR_ERR(srcf),cfg_file); + goto no_config_file; + } + + if (!(srcf->f_op && srcf->f_op->read)) { + printk(KERN_ERR "%s does not have a read method\n", cfg_file); + goto no_config_file; + } + + cfg_buf = (char *)kzalloc(MAX_CONFIG_FILE_SIZE, GFP_ATOMIC); + if (!cfg_buf) { + printk(KERN_ERR "%s does not read : out of memory \n", cfg_file); + goto no_config_file; + } + + nr_read = srcf->f_op->read(srcf, (unsigned char *)cfg_buf, MAX_CONFIG_FILE_SIZE, &srcf->f_pos); + + DPRINTK(1, "read retval=%d file=%s\n", nr_read, priv->reg.cfg_file); + retval=filp_close(srcf ,NULL); + if (retval) + DPRINTK(1, "error %d closing %s\n", -retval,priv->reg.cfg_file); + + if (nr_read < 1) { + printk(KERN_ERR "%s does not read : file is empty num=%d\n", cfg_file, nr_read); + goto no_config_file; + }else if(nr_read > MAX_CONFIG_FILE_SIZE){ + printk(KERN_ERR "%s does not read : file is too big \n", cfg_file); + goto no_config_file; + } + cur_p = cfg_buf; + end_p = cur_p + nr_read; +#endif + *end_p = '\0'; + + while (cur_p < end_p) { + int i, j, len; + + len = end_p - cur_p; + for (i=0; cfg_tbl[i].key_len != 0; i++) { + if (*cur_p == '#') { + break; + } + if (len < cfg_tbl[i].key_len) { + continue; + } + if (!strncmp(cfg_tbl[i].key, cur_p, cfg_tbl[i].key_len)) { + break; + } + } + if ((*cur_p == '#') || (cfg_tbl[i].key_len == 0)) { + while (*cur_p != '\n') { + if (cur_p >= end_p) { + break; + } + cur_p++; + } + cur_p++; + } else { + cur_p += cfg_tbl[i].key_len; + if (*cur_p != '=') { + while (*cur_p != '\n') { + if (cur_p >= end_p) { + break; + } + cur_p++; + } + continue; + } + cur_p++; + + for (j=0,wk_p=cur_p; *wk_p != '\n' && wk_p < end_p; j++,wk_p++) { + wk_buff[j] = *wk_p; + } + wk_buff[j] = '\0'; + cur_p = wk_p; + DPRINTK(4,"%s=%s\n",cfg_tbl[i].key, wk_buff); + wk_p = wk_buff; + + switch (i) { + case 0: /* "BeaconLostCount", "10" */ + priv->reg.beacon_lost_count = simple_strtol(wk_buff, NULL, 10); + break; + case 1: /* "Channel", "1" */ + priv->reg.channel = simple_strtol(wk_buff, NULL, 10); + break; + case 2: /* "FragmentThreshold","2346" */ + j = simple_strtol(wk_buff, NULL, 10); + priv->reg.fragment = (unsigned long)j; + break; + case 3: /* "OperationMode","Infrastructure" */ + switch (*wk_buff) { + case 'P': + priv->reg.operation_mode = MODE_PSEUDO_ADHOC; + break; + case 'I': + priv->reg.operation_mode = MODE_INFRASTRUCTURE; + break; + case '8': + priv->reg.operation_mode = MODE_ADHOC; + break; + default: + priv->reg.operation_mode = MODE_INFRASTRUCTURE; + } + break; + case 4: /* "PowerManagementMode","POWER_ACTIVE" */ + if (!strncmp(wk_buff, "SAVE1", 5)) { + priv->reg.powermgt = POWMGT_SAVE1_MODE; + } else if (!strncmp(wk_buff, "SAVE2", 5)){ + priv->reg.powermgt = POWMGT_SAVE2_MODE; + } else { + priv->reg.powermgt = POWMGT_ACTIVE_MODE; + } + break; + case 5: /* "RTSThreshold","2347" */ + j = simple_strtol(wk_buff, NULL, 10); + priv->reg.rts = (unsigned long)j; + break; + case 6: /* "SSID","" */ + if (*wk_p != '"') + break; + wk_p++; + for (j=0; *wk_p != '"'; j++) { + if (wk_p == '\0') { + break; + } + priv->reg.ssid.body[j] = *wk_p++; + } + priv->reg.ssid.body[j] = '\0'; + priv->reg.ssid.size = j; + wk_p++; + break; + case 7: /* "TxRate","Auto" */ + rate_set_configuration(priv, wk_p); + break; + case 8: /* "AuthenticationAlgorithm","OPEN_SYSTEM" */ + switch (*wk_p) { + case 'O': /* Authenticate System : Open System */ + priv->reg.authenticate_type = AUTH_TYPE_OPEN_SYSTEM; + break; + case 'S': /* Authenticate System : Shared Key */ + priv->reg.authenticate_type = AUTH_TYPE_SHARED_KEY; + break; + } + break; + case 9: /* "WepKeyValue1","" */ + case 10: /* "WepKeyValue2","" */ + case 11: /* "WepKeyValue3","" */ + case 12: /* "WepKeyValue4","" */ + if (wep_on_off != WEP_OFF) { + switch (wep_type) { + case WEP_KEY_CHARACTER: + analyze_character_wep_key(&priv->reg, (i-9), wk_p); + break; + case WEP_KEY_HEX: + analyze_hex_wep_key(&priv->reg, (i-9), wk_p); + break; + } + } + break; + case 13: /* "WepIndex","1"->0 (So, Zero Origin) */ + priv->reg.wep_index = simple_strtol(wk_buff, NULL, 10) - 1; + break; + case 14: /* "WepType","STRING" */ + if (!strncmp(wk_buff, "STRING", 6)) { + wep_type = WEP_KEY_CHARACTER; + } else { + wep_type = WEP_KEY_HEX; + } + break; + case 15: /* "Wep","OFF" */ + if (!strncmp(wk_buff, "OFF", 3)) { + priv->reg.privacy_invoked = 0x00; + wep_on_off = WEP_OFF; + } else { /* 64bit or 128bit */ + priv->reg.privacy_invoked = 0x01; + if (*wk_buff == '6') { /* 64bit */ + wep_on_off = WEP_ON_64BIT; + } else { /* 128bit */ + wep_on_off = WEP_ON_128BIT; + } + } + break; + case 16: /* "PREAMBLE_TYPE","LONG" */ + if (!strncmp(wk_buff, "SHORT", 5)) { + priv->reg.preamble = SHORT_PREAMBLE; + } else { /* "LONG" */ + priv->reg.preamble = LONG_PREAMBLE; + } + break; + case 17: /* "ScanType","ACTIVE_SCAN" */ + if (!strncmp(wk_buff, "PASSIVE_SCAN", 12)) { + priv->reg.scan_type = PASSIVE_SCAN; + } else { /* "ACTIVE_SCAN" */ + priv->reg.scan_type = ACTIVE_SCAN; + } + break; + case 18: // "ROM_FILE",ROMFILE + if (*wk_p != '"') + break; + wk_p++; + for (j=0; *wk_p != '"'; j++) { + if (wk_p == '\0') { + break; + } + priv->reg.rom_file[j] = *wk_p++; + } + priv->reg.rom_file[j] = '\0'; + wk_p++; + break; + case 19: /*"PhyType", "BG_MODE" */ + if (!strncmp(wk_buff, "B_MODE", 6)) { + priv->reg.phy_type = D_11B_ONLY_MODE; + } else if (!strncmp(wk_buff, "G_MODE", 6)) { + priv->reg.phy_type = D_11G_ONLY_MODE; + } else { + priv->reg.phy_type = D_11BG_COMPATIBLE_MODE; + } + break; + case 20: /* "CtsMode", "FALSE" */ + if (!strncmp(wk_buff, "TRUE", 4)) { + priv->reg.cts_mode = CTS_MODE_TRUE; + } else { + priv->reg.cts_mode = CTS_MODE_FALSE; + } + break; + case 21: /* "PhyInformationTimer", "0" */ + j = simple_strtol(wk_buff, NULL, 10); + priv->reg.phy_info_timer = (uint16_t)j; + break; + default: + break; + } + if (cur_p >= end_p) { + break; + } + cur_p++; + } + + } +#ifndef NO_FIRMWARE_CLASS + release_firmware(fw_entry); +#else +no_config_file: + kfree(cfg_buf); + set_fs(orgfs); + current->fsuid=orgfsuid; + current->fsgid=orgfsgid; +#endif + + DPRINTK(3,"\n operation_mode = %d\n channel = %d\n ssid = %s\n tx_rate = %d\n \ + preamble = %d\n powermgt = %d\n scan_type = %d\n beacon_lost_count = %d\n rts = %d\n \ + fragment = %d\n privacy_invoked = %d\n wep_type = %d\n wep_on_off = %d\n wep_index = %d\n romfile = %s\n", + priv->reg.operation_mode,priv->reg.channel,&priv->reg.ssid.body[0],priv->reg.tx_rate, + priv->reg.preamble,priv->reg.powermgt,priv->reg.scan_type,priv->reg.beacon_lost_count, + priv->reg.rts,priv->reg.fragment,priv->reg.privacy_invoked,wep_type,wep_on_off,priv->reg.wep_index, + &priv->reg.rom_file[0] + ); + DPRINTK(3,"\n phy_type = %d\n cts_mode = %d\n tx_rate = %d\n phy_info_timer = %d\n", + priv->reg.phy_type,priv->reg.cts_mode,priv->reg.tx_rate,priv->reg.phy_info_timer ); + + return(0); +} + |