提交 13a9930d 编写于 作者: W Wolfram Sang 提交者: Greg Kroah-Hartman

staging: ks7010: add driver from Nanonote extra-repository

See the TODO for details where this driver came from. Only a few minor
changes were made to make the driver suitable for staging:

* updated Kconfig help text and dependencies
* added TODO
* removed two __DATE__ and __TIME__ printouts to allow reproducible builds
* added to staging main Kconfig + Makefile

Tested on a Renesas Salvator-X board with a Spectec SDW-823 card. I
could connect to a WPA-protected network.
Signed-off-by: NWolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 e3c9078a
......@@ -102,4 +102,6 @@ source "drivers/staging/most/Kconfig"
source "drivers/staging/i4l/Kconfig"
source "drivers/staging/ks7010/Kconfig"
endif # STAGING
......@@ -40,3 +40,4 @@ obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_WILC1000) += wilc1000/
obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_ISDN_I4L) += i4l/
obj-$(CONFIG_KS7010) += ks7010/
config KS7010
tristate "KeyStream KS7010 SDIO support"
depends on MMC && WIRELESS
select WIRELESS_EXT
select WEXT_PRIV
help
This is a driver for KeyStream KS7010 based SDIO WIFI cards. It is
found on at least later Spectec SDW-821 (FCC-ID "S2Y-WLAN-11G-K" only,
sadly not FCC-ID "S2Y-WLAN-11B-G") and Spectec SDW-823 microSD cards.
obj-$(CONFIG_KS7010) += ks7010.o
ccflags-y += -D_SDIO_ -DKS_WLAN_DEBUG=0
ks7010-y := michael_mic.o ks_hostif.o ks_wlan_net.o ks_debug.o \
ks7010_sdio.o ks7010_config.o
KS7010 Linux driver
===================
This driver is based on source code from the Ben Nanonote extra repository [1]
which is based on the original v007 release from Renesas [2]. Some more
background info about the chipset can be found here [3] and here [4]. Thank
you to all which already participated in cleaning up the driver so far!
[1] http://projects.qi-hardware.com/index.php/p/openwrt-packages/source/tree/master/ks7010/src
[2] http://downloads.qi-hardware.com/software/ks7010_sdio_v007.tar.bz2
[3] http://en.qi-hardware.com/wiki/Ben_NanoNote_Wi-Fi
[4] https://wikidevi.com/wiki/Renesas
TODO
----
First a few words what not to do (at least not blindly):
- don't be overly strict with the 80 char limit. Only if it REALLY makes the
code more readable
- No '#if 0/1' removal unless the surrounding code is understood and removal is
really OK. There might be some hints hidden there.
Now the TODOs:
- fix codechecker warnings (checkpatch, sparse, smatch). But PLEASE make sure
that you are not only silencing the warning but really fixing code. You
should understand the change you submit.
- drop using a config file and use an upstream technique for configuration
- fix the 'card removal' event when card is inserted when booting
- driver crashes when removing the card
- check what other upstream wireless mechanisms can be used instead of the
custom ones here
Please send any patches to:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Wolfram Sang <wsa@the-dreams.de>
Linux Driver Project Developer List <driverdev-devel@linuxdriverproject.org>
/*
*
* eap_packet.h
* $Id: eap_packet.h 991 2009-09-14 01:38:58Z sekine $
*
*/
#ifndef EAP_PACKET_H
#define EAP_PACKET_H
#define WBIT(n) (1 << (n))
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
struct ether_hdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned char h_dest_snap;
unsigned char h_source_snap;
unsigned char h_command;
unsigned char h_vendor_id[3];
unsigned short h_proto; /* packet type ID field */
#define ETHER_PROTOCOL_TYPE_EAP 0x888e
#define ETHER_PROTOCOL_TYPE_IP 0x0800
#define ETHER_PROTOCOL_TYPE_ARP 0x0806
/* followed by length octets of data */
} __attribute__ ((packed));
struct ieee802_1x_hdr {
unsigned char version;
unsigned char type;
unsigned short length;
/* followed by length octets of data */
} __attribute__ ((packed));
#define EAPOL_VERSION 2
enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
IEEE802_1X_TYPE_EAPOL_START = 1,
IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
IEEE802_1X_TYPE_EAPOL_KEY = 3,
IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
};
enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
EAPOL_KEY_TYPE_WPA = 254 };
#define IEEE8021X_REPLAY_COUNTER_LEN 8
#define IEEE8021X_KEY_SIGN_LEN 16
#define IEEE8021X_KEY_IV_LEN 16
#define IEEE8021X_KEY_INDEX_FLAG 0x80
#define IEEE8021X_KEY_INDEX_MASK 0x03
struct ieee802_1x_eapol_key {
unsigned char type;
unsigned short key_length;
/* does not repeat within the life of the keying material used to
* encrypt the Key field; 64-bit NTP timestamp MAY be used here */
unsigned char replay_counter[IEEE8021X_REPLAY_COUNTER_LEN];
unsigned char key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */
unsigned char key_index; /* key flag in the most significant bit:
* 0 = broadcast (default key),
* 1 = unicast (key mapping key); key index is in the
* 7 least significant bits */
/* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as
* the key */
unsigned char key_signature[IEEE8021X_KEY_SIGN_LEN];
/* followed by key: if packet body length = 44 + key length, then the
* key field (of key_length bytes) contains the key in encrypted form;
* if packet body length = 44, key field is absent and key_length
* represents the number of least significant octets from
* MS-MPPE-Send-Key attribute to be used as the keying material;
* RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */
} __attribute__ ((packed));
#define WPA_NONCE_LEN 32
#define WPA_REPLAY_COUNTER_LEN 8
struct wpa_eapol_key {
unsigned char type;
unsigned short key_info;
unsigned short key_length;
unsigned char replay_counter[WPA_REPLAY_COUNTER_LEN];
unsigned char key_nonce[WPA_NONCE_LEN];
unsigned char key_iv[16];
unsigned char key_rsc[8];
unsigned char key_id[8]; /* Reserved in IEEE 802.11i/RSN */
unsigned char key_mic[16];
unsigned short key_data_length;
/* followed by key_data_length bytes of key_data */
} __attribute__ ((packed));
#define WPA_KEY_INFO_TYPE_MASK (WBIT(0) | WBIT(1) | WBIT(2))
#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 WBIT(0)
#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES WBIT(1)
#define WPA_KEY_INFO_KEY_TYPE WBIT(3) /* 1 = Pairwise, 0 = Group key */
/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */
#define WPA_KEY_INFO_KEY_INDEX_MASK (WBIT(4) | WBIT(5))
#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
#define WPA_KEY_INFO_INSTALL WBIT(6) /* pairwise */
#define WPA_KEY_INFO_TXRX WBIT(6) /* group */
#define WPA_KEY_INFO_ACK WBIT(7)
#define WPA_KEY_INFO_MIC WBIT(8)
#define WPA_KEY_INFO_SECURE WBIT(9)
#define WPA_KEY_INFO_ERROR WBIT(10)
#define WPA_KEY_INFO_REQUEST WBIT(11)
#define WPA_KEY_INFO_ENCR_KEY_DATA WBIT(12) /* IEEE 802.11i/RSN only */
#define WPA_CAPABILITY_PREAUTH WBIT(0)
#define GENERIC_INFO_ELEM 0xdd
#define RSN_INFO_ELEM 0x30
enum {
REASON_UNSPECIFIED = 1,
REASON_DEAUTH_LEAVING = 3,
REASON_INVALID_IE = 13,
REASON_MICHAEL_MIC_FAILURE = 14,
REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
REASON_GROUP_KEY_UPDATE_TIMEOUT = 16,
REASON_IE_IN_4WAY_DIFFERS = 17,
REASON_GROUP_CIPHER_NOT_VALID = 18,
REASON_PAIRWISE_CIPHER_NOT_VALID = 19,
REASON_AKMP_NOT_VALID = 20,
REASON_UNSUPPORTED_RSN_IE_VERSION = 21,
REASON_INVALID_RSN_IE_CAPAB = 22,
REASON_IEEE_802_1X_AUTH_FAILED = 23,
REASON_CIPHER_SUITE_REJECTED = 24
};
#endif /* EAP_PACKET_H */
#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);
}
此差异已折叠。
/*
*
* Driver for KeyStream, KS7010 based SDIO cards.
*
* ks7010_sdio.h
* $Id: ks7010_sdio.h 1019 2009-09-28 05:41:07Z sekine $
*
* Copyright (C) 2006-2008 KeyStream Corp.
* Copyright (C) 2009 Renesas Technology Corp.
*
* This program is free software; you can redistribute it and/or modify
* it undr the terms of the GNU General Public License version 2 as
* published by the Free Sotware Foundation.
*/
#ifndef _KS7010_SDIO_H
#define _KS7010_SDIO_H
#ifdef DEVICE_ALIGNMENT
#undef DEVICE_ALIGNMENT
#endif
#define DEVICE_ALIGNMENT 32
/* SDIO KeyStream vendor and device */
#define SDIO_VENDOR_ID_KS_CODE_A 0x005b
#define SDIO_VENDOR_ID_KS_CODE_B 0x0023
#define SDIO_DEVICE_ID_KS_7010 0x7910
/* Read Status Register */
#define READ_STATUS 0x000000
#define READ_STATUS_BUSY 0
#define READ_STATUS_IDLE 1
/* Read Index Register */
#define READ_INDEX 0x000004
/* Read Data Size Register */
#define READ_DATA_SIZE 0x000008
/* Write Status Register */
#define WRITE_STATUS 0x00000C
#define WRITE_STATUS_BUSY 0
#define WRITE_STATUS_IDLE 1
/* Write Index Register */
#define WRITE_INDEX 0x000010
/* Write Status/Read Data Size Register
* for network packet (less than 2048 bytes data)
*/
#define WSTATUS_RSIZE 0x000014
#define WSTATUS_MASK 0x80 /* Write Status Register value */
#define RSIZE_MASK 0x7F /* Read Data Size Register value [10:4] */
/* ARM to SD interrupt Enable */
#define INT_ENABLE 0x000020
/* ARM to SD interrupt Pending */
#define INT_PENDING 0x000024
#define INT_GCR_B (1<<7)
#define INT_GCR_A (1<<6)
#define INT_WRITE_STATUS (1<<5)
#define INT_WRITE_INDEX (1<<4)
#define INT_WRITE_SIZE (1<<3)
#define INT_READ_STATUS (1<<2)
#define INT_READ_INDEX (1<<1)
#define INT_READ_SIZE (1<<0)
/* General Communication Register A */
#define GCR_A 0x000028
#define GCR_A_INIT 0
#define GCR_A_REMAP 1
#define GCR_A_RUN 2
/* General Communication Register B */
#define GCR_B 0x00002C
#define GCR_B_ACTIVE 0
#define GCR_B_DOZE 1
/* Wakeup Register */
/* #define WAKEUP 0x008104 */
/* #define WAKEUP_REQ 0x00 */
#define WAKEUP 0x008018
#define WAKEUP_REQ 0x5a
/* AHB Data Window 0x010000-0x01FFFF */
#define DATA_WINDOW 0x010000
#define WINDOW_SIZE 64*1024
#define KS7010_IRAM_ADDRESS 0x06000000
/*
* struct define
*/
struct hw_info_t {
struct ks_sdio_card *sdio_card;
struct completion ks7010_sdio_wait;
struct workqueue_struct *ks7010sdio_wq;
struct workqueue_struct *ks7010sdio_init;
struct work_struct init_task;
struct delayed_work rw_wq;
unsigned char *read_buf;
struct tasklet_struct rx_bh_task;
};
struct ks_sdio_packet {
struct ks_sdio_packet *next;
u16 nb;
u8 buffer[0] __attribute__((aligned(4)));
};
struct ks_sdio_card {
struct sdio_func *func;
struct ks_wlan_private *priv;
int model;
const char *firmware;
spinlock_t lock;
};
/* Tx Device struct */
#define TX_DEVICE_BUFF_SIZE 1024
struct tx_device_buffer {
unsigned char *sendp; /* pointer of send req data */
unsigned int size;
void (*complete_handler)(void *arg1, void *arg2);
void *arg1;
void *arg2;
};
struct tx_device{
struct tx_device_buffer tx_dev_buff[TX_DEVICE_BUFF_SIZE];
unsigned int qhead; /* tx buffer queue first pointer */
unsigned int qtail; /* tx buffer queue last pointer */
spinlock_t tx_dev_lock;
};
/* Rx Device struct */
#define RX_DATA_SIZE (2 + 2 + 2347 + 1)
#define RX_DEVICE_BUFF_SIZE 32
struct rx_device_buffer {
unsigned char data[RX_DATA_SIZE];
unsigned int size;
};
struct rx_device{
struct rx_device_buffer rx_dev_buff[RX_DEVICE_BUFF_SIZE];
unsigned int qhead; /* rx buffer queue first pointer */
unsigned int qtail; /* rx buffer queue last pointer */
spinlock_t rx_dev_lock;
};
#ifndef NO_FIRMWARE_CLASS
#define ROM_FILE "ks7010sd.rom"
#define CFG_FILE "ks79xx.cfg"
#else
#define ROM_FILE "/lib/firmware/ks7010sd.rom"
#define CFG_FILE "/lib/firmware/ks79xx.cfg"
#endif
#define KS_WLAN_DRIVER_VERSION_INFO "ks7010 sdio linux 007"
#endif /* _KS7010_SDIO_H */
/*
* Driver for KeyStream 11b/g wireless LAN cards.
*
* ks_debug.c
* $Id: ks_debug.c 991 2009-09-14 01:38:58Z sekine $
*
* Copyright (C) 2005-2008 KeyStream Corp.
* Copyright (C) 2009 Renesas Technology Corp.
*
* This program is free software; you can redistribute it and/or modify
* it undr the terms of the GNU General Public License version 2 as
* published by the Free Sotware Foundation.
*/
#include "ks_wlan.h"
#include "ks_debug.h"
void print_buffer(unsigned char *p, int length)
{
#ifdef KS_WLAN_DEBUG
int i;
#define HEX_OFFSET "\
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F"
printk(HEX_OFFSET);
for (i=0; i<length; i++) {
if (i % 16 == 0) printk("\n%04X-%04X:", i, i+15);
printk(" %02X", *(p+i));
}
printk("\n");
#endif
}
/*
* Driver for KeyStream 11b/g wireless LAN cards.
*
* ks_debug.h
* $Id: ks_debug.h 991 2009-09-14 01:38:58Z sekine $
*
* Copyright (C) 2005-2008 KeyStream Corp.
* Copyright (C) 2009 Renesas Technology Corp.
*
* This program is free software; you can redistribute it and/or modify
* it undr the terms of the GNU General Public License version 2 as
* published by the Free Sotware Foundation.
*/
#ifndef _KS_DEBUG_H
#define _KS_DEBUG_H
#include <linux/kernel.h>
#ifdef KS_WLAN_DEBUG
#define DPRINTK(n, fmt, args...) \
if (KS_WLAN_DEBUG>(n)) printk(KERN_NOTICE "%s: "fmt, __FUNCTION__, ## args)
#else
#define DPRINTK(n, fmt, args...)
#endif
extern void print_buffer(unsigned char *p, int size);
#endif /* _KS_DEBUG_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* Driver for KeyStream 11b/g wireless LAN
*
* ks_wlan_ioctl.h
* $Id: ks_wlan_ioctl.h 996 2009-09-14 02:54:21Z sekine $
*
* Copyright (c) 2005-2008 KeyStream Corp.
* Copyright (C) 2009 Renesas Technology Corp.
*
* This program is free software; you can redistribute it and/or modify
* it undr the terms of the GNU General Public License version 2 as
* published by the Free Sotware Foundation.
*/
#ifndef _KS_WLAN_IOCTL_H
#define _KS_WLAN_IOCTL_H
#include <linux/wireless.h>
/* The low order bit identify a SET (0) or a GET (1) ioctl. */
/* SIOCIWFIRSTPRIV+0 */
#define KS_WLAN_GET_DRIVER_VERSION SIOCIWFIRSTPRIV+1
/* SIOCIWFIRSTPRIV+2 */
#define KS_WLAN_GET_FIRM_VERSION SIOCIWFIRSTPRIV+3
#ifdef WPS
#define KS_WLAN_SET_WPS_ENABLE SIOCIWFIRSTPRIV+4
#define KS_WLAN_GET_WPS_ENABLE SIOCIWFIRSTPRIV+5
#define KS_WLAN_SET_WPS_PROBE_REQ SIOCIWFIRSTPRIV+6
#endif
#define KS_WLAN_GET_EEPROM_CKSUM SIOCIWFIRSTPRIV+7
#define KS_WLAN_SET_PREAMBLE SIOCIWFIRSTPRIV+8
#define KS_WLAN_GET_PREAMBLE SIOCIWFIRSTPRIV+9
#define KS_WLAN_SET_POWER_SAVE SIOCIWFIRSTPRIV+10
#define KS_WLAN_GET_POWER_SAVE SIOCIWFIRSTPRIV+11
#define KS_WLAN_SET_SCAN_TYPE SIOCIWFIRSTPRIV+12
#define KS_WLAN_GET_SCAN_TYPE SIOCIWFIRSTPRIV+13
#define KS_WLAN_SET_RX_GAIN SIOCIWFIRSTPRIV+14
#define KS_WLAN_GET_RX_GAIN SIOCIWFIRSTPRIV+15
#define KS_WLAN_HOSTT SIOCIWFIRSTPRIV+16 /* unused */
//#define KS_WLAN_SET_REGION SIOCIWFIRSTPRIV+17
#define KS_WLAN_SET_BEACON_LOST SIOCIWFIRSTPRIV+18
#define KS_WLAN_GET_BEACON_LOST SIOCIWFIRSTPRIV+19
#define KS_WLAN_SET_TX_GAIN SIOCIWFIRSTPRIV+20
#define KS_WLAN_GET_TX_GAIN SIOCIWFIRSTPRIV+21
/* for KS7010 */
#define KS_WLAN_SET_PHY_TYPE SIOCIWFIRSTPRIV+22
#define KS_WLAN_GET_PHY_TYPE SIOCIWFIRSTPRIV+23
#define KS_WLAN_SET_CTS_MODE SIOCIWFIRSTPRIV+24
#define KS_WLAN_GET_CTS_MODE SIOCIWFIRSTPRIV+25
/* SIOCIWFIRSTPRIV+26 */
/* SIOCIWFIRSTPRIV+27 */
#define KS_WLAN_SET_SLEEP_MODE SIOCIWFIRSTPRIV+28 /* sleep mode */
#define KS_WLAN_GET_SLEEP_MODE SIOCIWFIRSTPRIV+29 /* sleep mode */
/* SIOCIWFIRSTPRIV+30 */
/* SIOCIWFIRSTPRIV+31 */
#ifdef __KERNEL__
#include "ks_wlan.h"
#include <linux/netdevice.h>
extern int ks_wlan_read_config_file(ks_wlan_private *priv);
extern int ks_wlan_setup_parameter(ks_wlan_private *priv, unsigned int commit_flag);
#endif /* __KERNEL__ */
#endif /* _KS_WLAN_IOCTL_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册