first commit

This commit is contained in:
pvvx 2023-12-25 21:53:30 +03:00
parent 9b8b484b76
commit 306d16ebe3
42 changed files with 16809 additions and 0 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,22 @@
config ESP8089
depends on WLAN_80211 && MMC
select WIRELESS_EXT
select WEXT_PRIV
select CFG80211
select MAC80211
select NL80211_TESTMODE
bool "Espressif 8089 sdio Wi-Fi"
---help---
Espressif 8089 sdio Wi-Fi support
config BK3515A_COMBO
depends on ESP8089
select WIRELESS_EXT
select WEXT_PRIV
select CFG80211
select MAC80211
select NL80211_TESTMODE
bool "Espressif 8089 sdio Wi-Fi combo with BK3515A bluetooth"
---help---
RK Wi-Fi+BT+[GPS optional] Combo module support

View File

@ -0,0 +1,18 @@
include drivers/net/wireless/esp8089/esp_config.mk
#EXTRA_CFLAGS += -DDEBUG -DSIP_DEBUG -DFAST_TX_STATUS -DANDROID -DKERNEL_IV_WAR -DRX_SENDUP_SYNC -DDEBUGFS -DHAS_FW -DTEST_MODE -DINIT_DATA_CONF -DHAS_INIT_DATA
EXTRA_CFLAGS += -DDEBUG -DSIP_DEBUG -DFAST_TX_STATUS -DANDROID -DKERNEL_IV_WAR -DRX_SENDUP_SYNC -DDEBUGFS -DHAS_FW -DTEST_MODE -DHAS_INIT_DATA
obj-$(CONFIG_ESP8089) := wlan.o
wlan-y += esp_debug.o
wlan-y += sdio_sif_esp.o
wlan-y += esp_android.o
wlan-y += esp_main.o
wlan-y += esp_sip.o
wlan-y += esp_ctrl.o
wlan-y += esp_mac80211.o
wlan-y += esp_debug.o
wlan-y += esp_utils.o
wlan-y += esp_pm.o
wlan-y += testmode.o

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,399 @@
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/aio.h>
#include "esp_android.h"
#include "esp_debug.h"
#include "esp_sif.h"
#ifdef ANDROID
#include "esp_path.h"
#include "esp_conf.h"
int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length)
{
int ret = 0;
struct file *filp = (struct file *)-ENOENT;
mm_segment_t oldfs;
oldfs = get_fs();
set_fs(KERNEL_DS);
do {
int mode = (wbuf) ? O_RDWR | O_CREAT : O_RDONLY;
filp = filp_open(filename, mode, S_IRUSR);
if (IS_ERR(filp) || !filp->f_op) {
esp_dbg(ESP_DBG_ERROR, "%s: file %s filp_open error\n", __FUNCTION__, filename);
ret = -ENOENT;
break;
}
if (length==0) {
/* Read the length of the file only */
struct inode *inode;
inode = GET_INODE_FROM_FILEP(filp);
if (!inode) {
esp_dbg(ESP_DBG_ERROR, "%s: Get inode from %s failed\n", __FUNCTION__, filename);
ret = -ENOENT;
break;
}
ret = i_size_read(inode->i_mapping->host);
break;
}
if (wbuf) {
if ( (ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) {
esp_dbg(ESP_DBG_ERROR, "%s: Write %u bytes to file %s error %d\n", __FUNCTION__,
length, filename, ret);
break;
}
} else {
if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) {
esp_dbg(ESP_DBG_ERROR, "%s: Read %u bytes from file %s error %d\n", __FUNCTION__,
length, filename, ret);
break;
}
}
} while (0);
if (!IS_ERR(filp)) {
filp_close(filp, NULL);
}
set_fs(oldfs);
return ret;
}
int android_request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device)
{
int ret = 0;
struct firmware *firmware;
char filename[256];
const char *raw_filename = name;
*firmware_p = firmware = kmalloc((sizeof(*firmware)), GFP_KERNEL);
if (!firmware)
return -ENOMEM;
memset(firmware, 0, sizeof(*firmware));
if (mod_eagle_path_get() == NULL)
sprintf(filename, "%s/%s", FWPATH, raw_filename);
else
sprintf(filename, "%s/%s", mod_eagle_path_get(), raw_filename);
do {
size_t length, bufsize, bmisize;
if ( (ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0) {
break;
} else {
length = ret;
}
bufsize = ALIGN(length, PAGE_SIZE);
bmisize = E_ROUND_UP(length, 4);
bufsize = max(bmisize, bufsize);
firmware->data = vmalloc(bufsize);
firmware->size = length;
if (!firmware->data) {
esp_dbg(ESP_DBG_ERROR, "%s: Cannot allocate buffer for firmware\n", __FUNCTION__);
ret = -ENOMEM;
break;
}
if ( (ret=android_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) {
esp_dbg(ESP_DBG_ERROR, "%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length);
ret = -1;
break;
}
} while (0);
if (ret<0) {
if (firmware) {
if (firmware->data)
vfree(firmware->data);
kfree(firmware);
}
*firmware_p = NULL;
} else {
ret = 0;
}
return ret;
}
void android_release_firmware(const struct firmware *firmware)
{
if (firmware) {
if (firmware->data)
vfree(firmware->data);
kfree((struct firmware *)firmware);
}
}
int logger_write( const unsigned char prio,
const char __kernel * const tag,
const char __kernel * const fmt,
...)
{
int ret = 0;
va_list vargs;
struct file *filp = (struct file *)-ENOENT;
mm_segment_t oldfs;
struct iovec vec[3];
int tag_bytes = strlen(tag) + 1, msg_bytes;
char *msg;
va_start(vargs, fmt);
msg = kvasprintf(GFP_ATOMIC, fmt, vargs);
va_end(vargs);
if (!msg)
return -ENOMEM;
if (in_interrupt()) {
/* we have no choice since aio_write may be blocked */
printk(KERN_ALERT "%s", msg);
goto out_free_message;
}
msg_bytes = strlen(msg) + 1;
if (msg_bytes <= 1) /* empty message? */
goto out_free_message; /* don't bother, then */
if ((msg_bytes + tag_bytes + 1) > 2048) {
ret = -E2BIG;
goto out_free_message;
}
vec[0].iov_base = (unsigned char *) &prio;
vec[0].iov_len = 1;
vec[1].iov_base = (void *) tag;
vec[1].iov_len = strlen(tag) + 1;
vec[2].iov_base = (void *) msg;
vec[2].iov_len = strlen(msg) + 1;
oldfs = get_fs();
set_fs(KERNEL_DS);
do {
filp = filp_open("/dev/log/main", O_WRONLY, S_IRUSR);
if (IS_ERR(filp) || !filp->f_op) {
esp_dbg(ESP_DBG_ERROR, "%s: filp open /dev/log/main error\n", __FUNCTION__);
ret = -ENOENT;
break;
}
if (filp->f_op->aio_write) {
int nr_segs = sizeof(vec) / sizeof(vec[0]);
int len = vec[0].iov_len + vec[1].iov_len + vec[2].iov_len;
struct kiocb kiocb;
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = 0;
kiocb.ki_left = len;
kiocb.ki_nbytes = len;
ret = filp->f_op->aio_write(&kiocb, vec, nr_segs, kiocb.ki_pos);
}
} while (0);
if (!IS_ERR(filp)) {
filp_close(filp, NULL);
}
set_fs(oldfs);
out_free_message:
if (msg) {
kfree(msg);
}
return ret;
}
struct esp_init_table_elem esp_init_table[MAX_ATTR_NUM] = {
{"crystal_26M_en", 48, -1},
{"test_xtal", 49, -1},
{"sdio_configure", 50, -1},
{"bt_configure", 51, -1},
{"bt_protocol", 52, -1},
{"dual_ant_configure", 53, -1},
{"test_uart_configure", 54, -1},
{"share_xtal", 55, -1},
{"gpio_wake", 56, -1},
{"no_auto_sleep", 57, -1},
{"attr10", -1, -1},
{"attr11", -1, -1},
{"attr12", -1, -1},
{"attr13", -1, -1},
{"attr14", -1, -1},
{"attr15", -1, -1},
//attr that is not send to target
{"ext_rst", -1, -1},
{"attr17", -1, -1},
{"attr18", -1, -1},
{"attr19", -1, -1},
{"attr20", -1, -1},
{"attr21", -1, -1},
{"attr22", -1, -1},
{"attr23", -1, -1},
};
int esp_atoi(char *str)
{
int num = 0;
int ng_flag = 0;
if (*str == '-') {
str++;
ng_flag = 1;
}
while(*str != '\0') {
num = num * 10 + *str++ - '0';
}
return ng_flag ? 0-num : num;
}
void show_esp_init_table(struct esp_init_table_elem *econf)
{
int i;
for (i = 0; i < MAX_ATTR_NUM; i++)
if (esp_init_table[i].offset > -1)
esp_dbg(ESP_DBG_ERROR, "%s: esp_init_table[%d] attr[%s] offset[%d] value[%d]\n",
__FUNCTION__, i,
esp_init_table[i].attr,
esp_init_table[i].offset,
esp_init_table[i].value);
}
int android_request_init_conf(void)
{
u8 *conf_buf;
u8 *pbuf;
int flag;
int str_len;
int length;
int ret;
int i;
char attr_name[CONF_ATTR_LEN];
char num_buf[CONF_VAL_LEN];
#ifdef INIT_DATA_CONF
char filename[256];
if (mod_eagle_path_get() == NULL)
sprintf(filename, "%s/%s", FWPATH, INIT_CONF_FILE);
else
sprintf(filename, "%s/%s", mod_eagle_path_get(), INIT_CONF_FILE);
if ((ret=android_readwrite_file(filename, NULL, NULL, 0)) < 0 || ret > MAX_BUF_LEN) {
esp_dbg(ESP_DBG_ERROR, "%s: file read length error, ret %d\n", __FUNCTION__, ret);
return -1;
} else {
length = ret;
}
#endif /* INIT_DATA_CONF */
conf_buf = (u8 *)kmalloc(MAX_BUF_LEN, GFP_KERNEL);
#ifdef INIT_DATA_CONF
if ((ret=android_readwrite_file(filename, conf_buf, NULL, length)) != length) {
esp_dbg(ESP_DBG_ERROR, "%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length);
goto failed;
}
#else
length = strlen(INIT_DATA_CONF_BUF);
strncpy(conf_buf, INIT_DATA_CONF_BUF, length);
#endif
conf_buf[length] = '\0';
flag = 0;
str_len = 0;
for (pbuf = conf_buf; *pbuf != '$' && *pbuf != '\n'; pbuf++) {
if (*pbuf == '=') {
flag = 1;
*(attr_name+str_len) = '\0';
str_len = 0;
continue;
}
if (*pbuf == ';') {
int value;
flag = 0;
*(num_buf+str_len) = '\0';
if((value = esp_atoi(num_buf)) > 255 || value < 0){
esp_dbg(ESP_DBG_ERROR, "%s: value is too big", __FUNCTION__);
goto failed;
}
for (i = 0; i < MAX_ATTR_NUM; i++) {
if (esp_init_table[i].value > -1)
continue;
if (strcmp(esp_init_table[i].attr, attr_name) == 0) {
esp_dbg(ESP_DBG_TRACE, "%s: attr_name[%s]", __FUNCTION__, attr_name); /* add by th */
esp_init_table[i].value = value;
}
if(strcmp(esp_init_table[i].attr, "share_xtal") == 0){
sif_record_bt_config(esp_init_table[i].value);
}
if(strcmp(esp_init_table[i].attr, "ext_rst") == 0){
sif_record_rst_config(esp_init_table[i].value);
}
}
str_len = 0;
continue;
}
if (flag == 0) {
*(attr_name+str_len) = *pbuf;
if (++str_len > CONF_ATTR_LEN) {
esp_dbg(ESP_DBG_ERROR, "%s: attr len is too long", __FUNCTION__);
goto failed;
}
} else {
*(num_buf+str_len) = *pbuf;
if (++str_len > CONF_VAL_LEN) {
esp_dbg(ESP_DBG_ERROR, "%s: value len is too long", __FUNCTION__);
goto failed;
}
}
}
//show_esp_init_table(esp_init_table);
return 0;
failed:
kfree(conf_buf);
return ret;
}
void fix_init_data(u8 *init_data_buf, int buf_size)
{
int i;
for (i = 0; i < MAX_FIX_ATTR_NUM; i++) {
if (esp_init_table[i].offset > -1 && esp_init_table[i].offset < buf_size && esp_init_table[i].value > -1) {
*(u8 *)(init_data_buf + esp_init_table[i].offset) = esp_init_table[i].value;
} else if (esp_init_table[i].offset > buf_size) {
esp_dbg(ESP_DBG_ERROR, "%s: offset[%d] longer than init_data_buf len[%d] Ignore\n", __FUNCTION__, esp_init_table[i].offset, buf_size);
}
}
}
void show_init_buf(u8 *buf, int size)
{
int i = 0;
for (i = 0; i < size; i++)
printk(KERN_ERR "offset[%d] [0x%02x]", i, buf[i]);
printk(KERN_ERR "\n");
}
#endif //ANDROID

View File

@ -0,0 +1,56 @@
#ifndef _ESP_ANDROID_H
#define _ESP_ANDROID_H
#include <linux/version.h>
#include <linux/firmware.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
#define GET_INODE_FROM_FILEP(filp) \
(filp)->f_path.dentry->d_inode
#else
#define GET_INODE_FROM_FILEP(filp) \
(filp)->f_dentry->d_inode
#endif
#define E_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#ifdef ANDROID
int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length);
int android_request_firmware(const struct firmware **firmware_p, const char *name, struct device *device);
void android_release_firmware(const struct firmware *firmware);
#ifdef INIT_DATA_CONF
#define INIT_CONF_FILE "init_data.conf"
#endif /* def INIT_DATA_CONF */
#define CONF_ATTR_LEN 24
#define CONF_VAL_LEN 3
#define MAX_ATTR_NUM 24
#define MAX_FIX_ATTR_NUM 16
#define MAX_BUF_LEN ((CONF_ATTR_LEN + CONF_VAL_LEN + 2) * MAX_ATTR_NUM + 2)
struct esp_init_table_elem {
char attr[CONF_ATTR_LEN];
int offset;
short value;
};
int android_request_init_conf(void);
void fix_init_data(u8 *init_data_buf, int buf_size);
void show_init_buf(u8 *buf, int size);
#endif
#if defined(ANDROID) && defined(ESP_ANDROID_LOGGER)
extern int logger_write( const unsigned char prio,
const char __kernel * const tag,
const char __kernel * const fmt,
...);
#endif // ANDROID
#endif

View File

@ -0,0 +1,301 @@
/*
* Copyright (c) 2010 - 2012 Espressif System.
*/
#if 0
#define RATETAB_ENT(_rate, _rateid, _flags) { \
.bitrate = (_rate), \
.flags = (_flags), \
.hw_value = (_rateid), \
}
#define CHAN2G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
.hw_value = (_channel), \
.center_freq = (_freq), \
.flags = (_flags), \
.max_antenna_gain = 0, \
.max_power = 30, \
}
static struct ieee80211_channel esp_2ghz_channels[] = {
CHAN2G(1, 2412, 0),
CHAN2G(2, 2417, 0),
CHAN2G(3, 2422, 0),
CHAN2G(4, 2427, 0),
CHAN2G(5, 2432, 0),
CHAN2G(6, 2437, 0),
CHAN2G(7, 2442, 0),
CHAN2G(8, 2447, 0),
CHAN2G(9, 2452, 0),
CHAN2G(10, 2457, 0),
CHAN2G(11, 2462, 0),
CHAN2G(12, 2467, 0),
CHAN2G(13, 2472, 0),
CHAN2G(14, 2484, 0),
};
static int esp_cfg80211_change_iface(struct wiphy *wiphy,
struct net_device *ndev,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params)
{
struct esp_pub *epub = wdev_priv(dev->ieee80211_ptr);
struct wireless_dev *wdev = epub->wdev;
/* only support STA mode for now */
if (type != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
}
wdev->iftype = type;
return 0;
}
static int esp_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_scan_request *request)
{
struct esp_pub *epub = wdev_priv(dev->ieee80211_ptr);
int ret = 0;
if (!esp_ready(ar))
return -EIO;
if (request->n_ssids && request->ssids[0].ssid_len) {
u8 i;
if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
for (i = 0; i < request->n_ssids; i++)
esp_wl_probedssid_cmd(epub->wl, i + 1,
SPECIFIC_SSID_FLAG,
request->ssids[i].ssid_len,
request->ssids[i].ssid);
}
if (esp_wl_startscan_cmd(epub->wl, WL_LONG_SCAN, 0,
false, 0, 0, 0, NULL) != 0) {
esp_dbg(ESP_DBG_ERROR, "wl_startscan_cmd failed\n");
ret = -EIO;
}
epub->wl->scan_req = request;
return ret;
}
static struct cfg80211_ops esp_cfg80211_ops = {
.change_virtual_intf = esp_cfg80211_change_iface,
.scan = esp_cfg80211_scan,
.connect = esp_cfg80211_connect,
.disconnect = esp_cfg80211_disconnect,
.add_key = esp_cfg80211_add_key,
.get_key = esp_cfg80211_get_key,
.del_key = esp_cfg80211_del_key,
.set_default_key = esp_cfg80211_set_default_key,
.set_wiphy_params = esp_cfg80211_set_wiphy_params,
.set_tx_power = esp_cfg80211_set_txpower,
.get_tx_power = esp_cfg80211_get_txpower,
.set_power_mgmt = esp_cfg80211_set_power_mgmt,
.join_ibss = esp_cfg80211_join_ibss,
.leave_ibss = esp_cfg80211_leave_ibss,
.get_station = esp_get_station,
.set_pmksa = esp_set_pmksa,
.del_pmksa = esp_del_pmksa,
.flush_pmksa = esp_flush_pmksa,
};
static struct ieee80211_ops esp_ieee80211_ops = {
}
static struct cfg80211_ops esp_cfg80211_ops = {0};
static struct ieee80211_rate esp_g_rates[] = {
RATETAB_ENT(10, 0x1, 0),
RATETAB_ENT(20, 0x2, 0),
RATETAB_ENT(55, 0x4, 0),
RATETAB_ENT(110, 0x8, 0),
RATETAB_ENT(60, 0x10, 0),
RATETAB_ENT(90, 0x20, 0),
RATETAB_ENT(120, 0x40, 0),
RATETAB_ENT(180, 0x80, 0),
RATETAB_ENT(240, 0x100, 0),
RATETAB_ENT(360, 0x200, 0),
RATETAB_ENT(480, 0x400, 0),
RATETAB_ENT(540, 0x800, 0),
};
#define esp_g_rates_size 12
static struct ieee80211_supported_band esp_band_2ghz = {
.n_channels = ARRAY_SIZE(esp_2ghz_channels),
.channels = esp_2ghz_channels,
.n_bitrates = esp_g_rates_size,
.bitrates = esp_g_rates,
};
static const u32 cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP40,
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
};
static struct wireless_dev *
esp_cfg80211_init(struct device *dev) {
int ret = 0;
struct wireless_dev *wdev;
wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
if (!wdev) {
esp_dbg(ESP_DBG_ERROR, "couldn't allocate wireless device\n");
return NULL;
}
wdev->wiphy = wiphy_new(&esp_cfg80211_ops, sizeof(struct esp_pub));
if (!wdev->wiphy) {
esp_dbg(ESP_DBG_ERROR, "couldn't allocate wiphy device\n");
kfree(wdev);
return NULL;
}
set_wiphy_dev(wdev->wiphy, dev);
wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &esp_band_2ghz;
//wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &esp_band_5ghz;
wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wdev->wiphy->cipher_suites = cipher_suites;
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
ret = wiphy_register(wdev->wiphy);
if (ret < 0) {
esp_dbg(ESP_DBG_ERROR, "couldn't register wiphy device\n");
wiphy_free(wdev->wiphy);
kfree(wdev);
return NULL;
}
return wdev;
}
static void
esp_cfg80211_descory(struct esp_pub *pub)
{
return;
}
static int esp_open(struct net_device *dev)
{
return 0;
}
static struct net_device_stats *
esp_get_stats(struct net_device *dev) {
struct net_device_stats *stats = NULL;
return stats;
}
static int esp_close(struct net_device *dev)
{
return 0;
}
static int esp_data_tx(struct sk_buff *skb, struct net_device *dev)
{
return 0;
}
static struct net_device_ops esp_netdev_ops = {
.ndo_open = esp_open,
.ndo_stop = esp_close,
.ndo_start_xmit = esp_data_tx,
.ndo_get_stats = esp_get_stats,
};
static inline void
esp_init_netdev(struct net_device *dev)
{
dev->netdev_ops = &esp_netdev_ops;
dev->watchdog_timeo = 10;
dev->needed_headroom = ETH_HLEN + sizeof(struct llc_snap_hdr) + SIP_HDR_LEN;
return;
}
static void
esp_disconnect(struct esp_pub *epub)
{
return;
}
static void
esp_disconnect_timeout_handler(unsigned long ptr)
{
struct net_device *netdev = (struct net_device *)ptr;
struct esp_pub *epub = wdev_priv(netdev->ieee80211_ptr);
//esp_init_profile(epub);
esp_disconnect(epub);
}
struct esp_pub *
esp_pub_alloc_cfg80211(struct device *dev) {
struct net_device *netdev;
struct wireless_dev *wdev;
struct esp_pub *epub;
struct esp_wl *wl;
wdev = esp_cfg80211_init(dev);
if (wdev == NULL) {
esp_dbg(ESP_DBG_ERROR, "%s: cfg80211_init failed \n", __func__);
return NULL;
}
epub = wdev_priv(wdev);
epub->dev = dev;
epub->wdev = wdev;
wdev->iftype = NL80211_IFTYPE_STATION;
/* Still register ethernet device */
netdev = alloc_netdev(0, "wlan%d", ether_setup);
if (!netdev) {
esp_dbg(ESP_DBG_ERROR, "%s: alloc_netdev failed \n", __func__);
esp_cfg80211_descory(epub);
return NULL;
}
netdev->ieee80211_ptr = wdev;
SET_NETDEV_DEV(netdev, wiphy_dev(wdev->wiphy));
wdev->netdev = netdev;
esp_init_netdev(netdev);
epub->net_dev = netdev;
//spin_lock_init(&epub->lock);
wl = &epub->wl;
//esp_init_wl(wl);
init_waitqueue_head(&epub->ev_waitq);
//sema_init(epub->sem, 1);
INIT_LIST_HEAD(&wl->amsdu_rx_buffer_queue);
setup_timer(&wl->disconnect_timer, esp_disconnect_timeout_handler,
(unsigned long) netdev);
return epub;
}
#endif

View File

@ -0,0 +1,6 @@
#ifndef _ESP_CONF_H_
#define _ESP_CONF_H_
#define INIT_DATA_CONF_BUF "crystal_26M_en=1;test_xtal=0;sdio_configure=2;bt_configure=0;bt_protocol=0;dual_ant_configure=0;test_uart_configure=2;share_xtal=0;gpio_wake=0;no_auto_sleep=0;ext_rst=0;$"
#endif /*_ESP_CONF_H_ */

View File

@ -0,0 +1 @@
EXTRA_CFLAGS += -DP2P_CONCURRENT -DESP_ACK_INTERRUPT

View File

@ -0,0 +1,700 @@
/*
* Copyright (c) 2009 - 2012 Espressif System.
*/
#include <net/mac80211.h>
#include <net/cfg80211.h>
#include <linux/skbuff.h>
#include <linux/bitops.h>
#include <linux/firmware.h>
#include "esp_pub.h"
#include "esp_sip.h"
#include "esp_ctrl.h"
#include "esp_sif.h"
#include "esp_debug.h"
#include "slc_host_register.h"
#include "esp_wmac.h"
#include "esp_utils.h"
#include "esp_wl.h"
#ifdef ANDROID
#include "esp_android.h"
#include "esp_path.h"
#endif /* ANDROID */
#ifdef TEST_MODE
#include "testmode.h"
#endif /* TEST_MODE */
extern struct completion *gl_bootup_cplx;
#ifdef ESP_RX_COPYBACK_TEST
static void sip_show_copyback_buf(void)
{
//show_buf(copyback_buf, copyback_offset);
}
#endif /* ESP_RX_COPYBACK_TEST */
static void esp_tx_ba_session_op(struct esp_sip *sip, struct esp_node *node, trc_ampdu_state_t state, u8 tid )
{
struct esp_tx_tid *txtid;
txtid = &node->tid[tid];
if (state == TRC_TX_AMPDU_STOPPED) {
if (txtid->state == ESP_TID_STATE_OPERATIONAL) {
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT\n", __func__, tid);
spin_lock_bh(&sip->epub->tx_ampdu_lock);
txtid->state = ESP_TID_STATE_WAIT_STOP;
spin_unlock_bh(&sip->epub->tx_ampdu_lock);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
ieee80211_stop_tx_ba_session(sip->epub->hw, node->sta->addr, (u16)tid, WLAN_BACK_INITIATOR);
#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
ieee80211_stop_tx_ba_session(node->sta, (u16)tid, WLAN_BACK_INITIATOR);
#else
ieee80211_stop_tx_ba_session(node->sta, (u16)tid);
#endif /* KERNEL_VERSION 2.6.39 */
} else {
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
}
} else if (state == TRC_TX_AMPDU_OPERATIONAL) {
if (txtid->state == ESP_TID_STATE_STOP) {
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL\n", __func__, tid);
spin_lock_bh(&sip->epub->tx_ampdu_lock);
txtid->state = ESP_TID_STATE_TRIGGER;
spin_unlock_bh(&sip->epub->tx_ampdu_lock);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
ieee80211_start_tx_ba_session(sip->epub->hw, node->sta->addr, tid);
#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 37))
ieee80211_start_tx_ba_session(node->sta, (u16)tid);
#else
ieee80211_start_tx_ba_session(node->sta, (u16)tid, 0);
#endif /* KERNEL_VERSION 2.6.39 */
} else if(txtid->state == ESP_TID_STATE_OPERATIONAL) {
sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->sta->addr, tid, node->ifidx, 0);
} else {
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
}
}
}
int sip_parse_events(struct esp_sip *sip, u8 *buf)
{
struct sip_hdr *hdr = (struct sip_hdr *)buf;
switch (hdr->c_evtid) {
case SIP_EVT_TARGET_ON: {
/* use rx work queue to send... */
if (atomic_read(&sip->state) == SIP_PREPARE_BOOT || atomic_read(&sip->state) == SIP_BOOT) {
atomic_set(&sip->state, SIP_SEND_INIT);
queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
} else {
esp_dbg(ESP_DBG_ERROR, "%s boot during wrong state %d\n", __func__, atomic_read(&sip->state));
}
break;
}
case SIP_EVT_BOOTUP: {
struct sip_evt_bootup2 *bootup_evt = (struct sip_evt_bootup2 *)(buf + SIP_CTRL_HDR_LEN);
if (sip->rawbuf)
kfree(sip->rawbuf);
sip_post_init(sip, bootup_evt);
if (gl_bootup_cplx)
complete(gl_bootup_cplx);
break;
}
case SIP_EVT_RESETTING:{
if (gl_bootup_cplx)
complete(gl_bootup_cplx);
break;
}
case SIP_EVT_SLEEP:{
//atomic_set(&sip->epub->ps.state, ESP_PM_ON);
break;
}
case SIP_EVT_TXIDLE:{
//struct sip_evt_txidle *txidle = (struct sip_evt_txidle *)(buf + SIP_CTRL_HDR_LEN);
//sip_txdone_clear(sip, txidle->last_seq);
break;
}
#ifndef FAST_TX_STATUS
case SIP_EVT_TX_STATUS: {
struct sip_evt_tx_report *report = (struct sip_evt_tx_report *)(buf + SIP_CTRL_HDR_LEN);
sip_txdoneq_process(sip, report);
break;
}
#endif /* FAST_TX_STATUS */
case SIP_EVT_SCAN_RESULT: {
struct sip_evt_scan_report *report = (struct sip_evt_scan_report *)(buf + SIP_CTRL_HDR_LEN);
if (atomic_read(&sip->epub->wl.off)) {
esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
return 0;
}
sip_scandone_process(sip, report);
break;
}
case SIP_EVT_ROC: {
struct sip_evt_roc* report = (struct sip_evt_roc *)(buf + SIP_CTRL_HDR_LEN);
esp_rocdone_process(sip->epub->hw, report);
break;
}
#ifdef ESP_RX_COPYBACK_TEST
case SIP_EVT_COPYBACK: {
u32 len = hdr->len - SIP_CTRL_HDR_LEN;
esp_dbg(ESP_DBG_TRACE, "%s copyback len %d seq %u\n", __func__, len, hdr->seq);
memcpy(copyback_buf + copyback_offset, pkt->buf + SIP_CTRL_HDR_LEN, len);
copyback_offset += len;
//show_buf(pkt->buf, 256);
//how about totlen % 256 == 0??
if (hdr->hdr.len < 256) {
//sip_show_copyback_buf();
kfree(copyback_buf);
}
}
break;
#endif /* ESP_RX_COPYBACK_TEST */
case SIP_EVT_CREDIT_RPT:
break;
#ifdef TEST_MODE
case SIP_EVT_WAKEUP: {
u8 check_str[12];
struct sip_evt_wakeup* wakeup_evt= (struct sip_evt_wakeup *)(buf + SIP_CTRL_HDR_LEN);
sprintf((char *)&check_str, "%d", wakeup_evt->check_data);
esp_test_cmd_event(TEST_CMD_WAKEUP, (char *)&check_str);
break;
}
case SIP_EVT_DEBUG: {
u8 check_str[100];
int i;
char * ptr_str = (char *)& check_str;
struct sip_evt_debug* debug_evt = (struct sip_evt_debug *)(buf + SIP_CTRL_HDR_LEN);
for(i = 0; i < debug_evt->len; i++)
ptr_str += sprintf(ptr_str, "0x%x%s", debug_evt->results[i], i == debug_evt->len -1 ? "":" " );
esp_test_cmd_event(TEST_CMD_DEBUG, (char *)&check_str);
break;
}
case SIP_EVT_LOOPBACK: {
u8 check_str[12];
struct sip_evt_loopback *loopback_evt = (struct sip_evt_loopback *)(buf + SIP_CTRL_HDR_LEN);
esp_dbg(ESP_DBG_LOG, "%s loopback len %d seq %u\n", __func__,hdr->len, hdr->seq);
if(loopback_evt->pack_id!=get_loopback_id()) {
sprintf((char *)&check_str, "seq id error %d, expect %d", loopback_evt->pack_id, get_loopback_id());
esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
}
if((loopback_evt->pack_id+1) <get_loopback_num()) {
inc_loopback_id();
sip_send_loopback_mblk(sip, loopback_evt->txlen, loopback_evt->rxlen, get_loopback_id());
} else {
sprintf((char *)&check_str, "test over!");
esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
}
break;
}
#endif /*TEST_MODE*/
case SIP_EVT_SNPRINTF_TO_HOST: {
u8 *p = (buf + sizeof(struct sip_hdr) + sizeof(u16));
u16 *len = (u16 *)(buf + sizeof(struct sip_hdr));
esp_dbg(ESP_SHOW, "esp_target: %.*s \n", *len, p);
#ifdef ANDROID
if(*len && sip->epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
char filename[256];
if (mod_eagle_path_get() == NULL)
sprintf(filename, "%s/%s", FWPATH, "test_results");
else
sprintf(filename, "%s/%s", mod_eagle_path_get(), "test_results");
android_readwrite_file(filename, NULL, p, *len);
}
#endif
break;
}
case SIP_EVT_TRC_AMPDU: {
struct sip_evt_trc_ampdu *ep = (struct sip_evt_trc_ampdu*)(buf + SIP_CTRL_HDR_LEN);
struct esp_node *node = NULL;
int i = 0;
if (atomic_read(&sip->epub->wl.off)) {
esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
return 0;
}
node = esp_get_node_by_addr(sip->epub, ep->addr);
if(node == NULL)
break;
#if 0
esp_tx_ba_session_op(sip, node, ep->state, ep->tid);
#else
for (i = 0; i < 8; i++) {
if (ep->tid & (1<<i)) {
esp_tx_ba_session_op(sip, node, ep->state, i);
}
}
#endif
break;
}
default:
break;
}
return 0;
}
#ifdef HAS_INIT_DATA
#include "esp_init_data.h"
#else
#define ESP_INIT_NAME "esp_init_data.bin"
#endif /* HAS_INIT_DATA */
void sip_send_chip_init(struct esp_sip *sip)
{
size_t size = 0;
#ifndef HAS_INIT_DATA
const struct firmware *fw_entry;
u8 * esp_init_data = NULL;
int ret = 0;
#ifdef ANDROID
ret = android_request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
#else
ret = request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
#endif /* ANDROID */
if (ret) {
esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO INIT DATA!!=================\n", __func__);
return;
}
esp_init_data = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
size = fw_entry->size;
#ifdef ANDROID
android_release_firmware(fw_entry);
#else
release_firmware(fw_entry);
#endif /* ANDROID */
if (esp_init_data == NULL) {
esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO MEMORY!!=================\n", __func__);
return;
}
#else
size = sizeof(esp_init_data);
#endif /* !HAS_INIT_DATA */
#ifdef ANDROID
//show_init_buf(esp_init_data,size);
fix_init_data(esp_init_data, size);
//show_init_buf(esp_init_data,size);
#endif
atomic_sub(1, &sip->tx_credits);
sip_send_cmd(sip, SIP_CMD_INIT, size, (void *)esp_init_data);
#ifndef HAS_INIT_DATA
kfree(esp_init_data);
#endif /* !HAS_INIT_DATA */
}
int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf)
{
struct sk_buff *skb = NULL;
struct sip_cmd_config *configcmd;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
if (!skb)
return -1;
esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->channel->center_freq);
configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
configcmd->center_freq= conf->channel->center_freq;
configcmd->duration= 0;
return sip_cmd_enqueue(epub->sip, skb);
}
int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc)
{
struct sk_buff *skb = NULL;
struct sip_cmd_bss_info_update*bsscmd;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_bss_info_update) + sizeof(struct sip_hdr), SIP_CMD_BSS_INFO_UPDATE);
if (!skb)
return -1;
bsscmd = (struct sip_cmd_bss_info_update *)(skb->data + sizeof(struct sip_hdr));
if (assoc == 2) { //hack for softAP mode
bsscmd->beacon_int = evif->beacon_interval;
} else if (assoc == 1) {
set_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
} else {
clear_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
}
bsscmd->bssid_no = evif->index;
bsscmd->isassoc= assoc;
memcpy(bsscmd->bssid, bssid, ETH_ALEN);
return sip_cmd_enqueue(epub->sip, skb);
}
int sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params)
{
struct sk_buff *skb = NULL;
struct sip_cmd_set_wmm_params* bsscmd;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_set_wmm_params) + sizeof(struct sip_hdr), SIP_CMD_SET_WMM_PARAM);
if (!skb)
return -1;
bsscmd = (struct sip_cmd_set_wmm_params *)(skb->data + sizeof(struct sip_hdr));
bsscmd->aci= aci;
bsscmd->aifs=params->aifs;
bsscmd->txop_us=params->txop*32;
bsscmd->ecw_min = 32 - __builtin_clz(params->cw_min);
bsscmd->ecw_max= 32 -__builtin_clz(params->cw_max);
return sip_cmd_enqueue(epub->sip, skb);
}
//since we only support ba for only one ta for each tid, so index = tid
static u8 find_empty_index(struct esp_pub *epub)
{
return 0;
}
int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, u8 * addr, u16 tid, u16 ssn, u8 buf_size)
{
u8 index = find_empty_index(epub);
struct sk_buff *skb = NULL;
struct sip_cmd_ampdu_action * action;
if(index < 0)
return -1;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ampdu_action) + sizeof(struct sip_hdr), SIP_CMD_AMPDU_ACTION);
if(!skb)
return -1;
action = (struct sip_cmd_ampdu_action *)(skb->data + sizeof(struct sip_hdr));
action->action = action_num;
//for TX, it means interface index
action->index = ssn;
switch(action_num) {
case SIP_AMPDU_RX_START:
action->ssn = ssn;
case SIP_AMPDU_RX_STOP:
action->index = tid;
case SIP_AMPDU_TX_OPERATIONAL:
case SIP_AMPDU_TX_STOP:
action->win_size = buf_size;
action->tid = tid;
memcpy(action->addr, addr, ETH_ALEN);
break;
}
return sip_cmd_enqueue(epub->sip, skb);
}
/*send cmd to target, if aborted is true, inform target stop scan, report scan complete imediately
return 1: complete over, 0: success, still have next scan, -1: hardware failure
*/
int sip_send_scan(struct esp_pub *epub)
{
struct cfg80211_scan_request *scan_req = epub->wl.scan_req;
struct sk_buff *skb = NULL;
struct sip_cmd_scan *scancmd;
u8 *ptr = NULL;
int i;
u8 append_len, ssid_len;
ASSERT(scan_req != NULL);
ssid_len = scan_req->n_ssids == 0 ? 0:
(scan_req->n_ssids == 1 ? scan_req->ssids->ssid_len: scan_req->ssids->ssid_len + (scan_req->ssids + 1)->ssid_len);
append_len = ssid_len + scan_req->n_channels + scan_req->ie_len;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_scan) + sizeof(struct sip_hdr) + append_len, SIP_CMD_SCAN);
if (!skb)
return -1;
ptr = skb->data;
scancmd = (struct sip_cmd_scan *)(ptr + sizeof(struct sip_hdr));
ptr += sizeof(struct sip_hdr);
scancmd->aborted= false;
if (scancmd->aborted==false) {
ptr += sizeof(struct sip_cmd_scan);
if (scan_req->n_ssids <=0 || (scan_req->n_ssids == 1&& ssid_len == 0)) {
scancmd->ssid_len = 0;
} else {
scancmd->ssid_len = ssid_len;
if(scan_req->ssids->ssid_len == ssid_len)
memcpy(ptr, scan_req->ssids->ssid, scancmd->ssid_len);
else
memcpy(ptr, (scan_req->ssids + 1)->ssid, scancmd->ssid_len);
}
ptr += scancmd->ssid_len;
scancmd->n_channels=scan_req->n_channels;
for (i=0; i<scan_req->n_channels; i++)
ptr[i] = scan_req->channels[i]->hw_value;
ptr += scancmd->n_channels;
if (scan_req->ie_len && scan_req->ie != NULL) {
scancmd->ie_len=scan_req->ie_len;
memcpy(ptr, scan_req->ie, scan_req->ie_len);
} else {
scancmd->ie_len = 0;
}
//add a flag that support two ssids,
if(scan_req->n_ssids > 1)
scancmd->ssid_len |= 0x80;
}
return sip_cmd_enqueue(epub->sip, skb);
}
int sip_send_suspend_config(struct esp_pub *epub, u8 suspend)
{
struct sip_cmd_suspend *cmd = NULL;
struct sk_buff *skb = NULL;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_suspend) + sizeof(struct sip_hdr), SIP_CMD_SUSPEND);
if (!skb)
return -1;
cmd = (struct sip_cmd_suspend *)(skb->data + sizeof(struct sip_hdr));
cmd->suspend = suspend;
return sip_cmd_enqueue(epub->sip, skb);
}
int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps)
{
struct sip_cmd_ps *pscmd = NULL;
struct sk_buff *skb = NULL;
struct sip_hdr *shdr = NULL;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ps) + sizeof(struct sip_hdr), SIP_CMD_PS);
if (!skb)
return -1;
shdr = (struct sip_hdr *)skb->data;
pscmd = (struct sip_cmd_ps *)(skb->data + sizeof(struct sip_hdr));
pscmd->dtim_period = ps->dtim_period;
pscmd->max_sleep_period = ps->max_sleep_period;
#if 0
if (atomic_read(&ps->state) == ESP_PM_TURNING_ON) {
pscmd->on = 1;
SIP_HDR_SET_PM_TURNING_ON(shdr);
} else if (atomic_read(&ps->state) == ESP_PM_TURNING_OFF) {
pscmd->on = 0;
SIP_HDR_SET_PM_TURNING_OFF(shdr);
} else {
esp_dbg(ESP_DBG_ERROR, "%s PM WRONG STATE %d\n", __func__, atomic_read(&ps->state));
ASSERT(0);
}
#endif
return sip_cmd_enqueue(epub->sip, skb);
}
void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report)
{
struct esp_pub *epub = sip->epub;
esp_dbg(ESP_DBG_TRACE, "eagle hw scan report\n");
if (epub->wl.scan_req) {
hw_scan_done(epub, scan_report->aborted);
epub->wl.scan_req = NULL;
}
}
int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid)
{
struct sip_cmd_setkey *setkeycmd;
struct sk_buff *skb = NULL;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setkey) + sizeof(struct sip_hdr), SIP_CMD_SETKEY);
if (!skb)
return -1;
setkeycmd = (struct sip_cmd_setkey *)(skb->data + sizeof(struct sip_hdr));
if (peer_addr) {
memcpy(setkeycmd->addr, peer_addr, ETH_ALEN);
} else {
memset(setkeycmd->addr, 0, ETH_ALEN);
}
setkeycmd->bssid_no = bssid_no;
setkeycmd->hw_key_idx= key->hw_key_idx;
if (isvalid) {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
setkeycmd->alg= key->alg;
#else
setkeycmd->alg= esp_cipher2alg(key->cipher);
#endif /* NEW_KERNEL */
setkeycmd->keyidx = key->keyidx;
setkeycmd->keylen = key->keylen;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
if (key->alg == ALG_TKIP) {
#else
if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
#endif /* NEW_KERNEL */
memcpy(setkeycmd->key, key->key, 16);
memcpy(setkeycmd->key+16,key->key+24,8);
memcpy(setkeycmd->key+24,key->key+16,8);
} else {
memcpy(setkeycmd->key, key->key, key->keylen);
}
setkeycmd->flags=1;
} else {
setkeycmd->flags=0;
}
return sip_cmd_enqueue(epub->sip, skb);
}
#ifdef FPGA_LOOPBACK
#define LOOPBACK_PKT_LEN 200
int sip_send_loopback_cmd_mblk(struct esp_sip *sip)
{
int cnt, ret;
for (cnt = 0; cnt < 4; cnt++) {
if (0!=(ret=sip_send_loopback_mblk(sip, LOOPBACK_PKT_LEN, LOOPBACK_PKT_LEN, 0)))
return ret;
}
return 0;
}
#endif /* FPGA_LOOPBACK */
int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id)
{
struct sk_buff *skb = NULL;
struct sip_cmd_loopback *cmd;
u8 *ptr = NULL;
int i, ret;
//send 100 loopback pkt
if(txpacket_len)
skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr) + txpacket_len, SIP_CMD_LOOPBACK);
else
skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr), SIP_CMD_LOOPBACK);
if (!skb)
return -ENOMEM;
ptr = skb->data;
cmd = (struct sip_cmd_loopback *)(ptr + sizeof(struct sip_hdr));
ptr += sizeof(struct sip_hdr);
cmd->txlen = txpacket_len;
cmd->rxlen = rxpacket_len;
cmd->pack_id = packet_id;
if (txpacket_len) {
ptr += sizeof(struct sip_cmd_loopback);
/* fill up pkt payload */
for (i = 0; i < txpacket_len; i++) {
ptr[i] = i;
}
}
ret = sip_cmd_enqueue(sip, skb);
if (ret <0)
return ret;
return 0;
}
//remain_on_channel
int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration)
{
struct sk_buff *skb = NULL;
struct sip_cmd_config *configcmd;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
if (!skb)
return -1;
configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
configcmd->center_freq= center_freq;
configcmd->duration= duration;
return sip_cmd_enqueue(epub->sip, skb);
}
int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index)
{
struct sk_buff *skb = NULL;
struct sip_cmd_setsta *setstacmd;
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setsta) + sizeof(struct sip_hdr), SIP_CMD_SETSTA);
if (!skb)
return -1;
setstacmd = (struct sip_cmd_setsta *)(skb->data + sizeof(struct sip_hdr));
setstacmd->ifidx = ifidx;
setstacmd->index = index;
setstacmd->set = set;
if(sta->aid == 0)
setstacmd->aid = vif->bss_conf.aid;
else
setstacmd->aid = sta->aid;
memcpy(setstacmd->mac, sta->addr, ETH_ALEN);
if(set){
if(sta->ht_cap.ht_supported){
if(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
else
setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
setstacmd->ampdu_factor = sta->ht_cap.ampdu_factor;
setstacmd->ampdu_density = sta->ht_cap.ampdu_density;
} else {
if(sta->supp_rates[IEEE80211_BAND_2GHZ] & (~(u32)CONF_HW_BIT_RATE_11B_MASK)){
setstacmd->phymode = ESP_IEEE80211_T_OFDM;
} else {
setstacmd->phymode = ESP_IEEE80211_T_CCK;
}
}
}
return sip_cmd_enqueue(epub->sip, skb);
}
int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len)
{
struct sk_buff *skb = NULL;
skb = sip_alloc_ctrl_skbuf(epub->sip, cmd_len + sizeof(struct sip_hdr), cmd_id);
if (!skb)
return -1;
memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len);
return sip_cmd_enqueue(epub->sip, skb);
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2009- 2012 Espressif System.
*
*/
#ifndef _ESP_CTRL_H_
#define _ESP_CTRL_H_
int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id);
int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf);
int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid);
int sip_send_scan(struct esp_pub *epub);
void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report);
int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc);
int sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params);
int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, u8 * addr, u16 tid, u16 ssn, u8 buf_size);
int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration);
int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index);
int sip_send_suspend_config(struct esp_pub *epub, u8 suspend);
int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps);
int sip_parse_events(struct esp_sip *sip, u8 *buf);
int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len);
#ifdef ESP_RX_COPYBACK_TEST
int sip_show_copyback_buf(void);
#endif /* ESP_RX_COPYBACK_TEST */
#endif /* _ESP_CTRL_H_ */

View File

@ -0,0 +1,285 @@
/*
* Copyright (c) 2011 Espressif System.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <net/mac80211.h>
#include "sip2_common.h"
#include "esp_debug.h"
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG_FS)
static struct dentry *esp_debugfs_root = NULL;
static int esp_debugfs_open(struct inode *inode, struct file *filp)
{
filp->private_data = inode->i_private;
return 0;
}
static ssize_t esp_debugfs_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
if (*ppos >= 32)
return 0;
if (*ppos + count > 32)
count = 32 - *ppos;
if (copy_to_user(buffer, filp->private_data + *ppos, count))
return -EFAULT;
*ppos += count;
return count;
}
static ssize_t esp_debugfs_write(struct file *filp, const char __user *buffer,
size_t count, loff_t *ppos)
{
if (*ppos >= 32)
return 0;
if (*ppos + count > 32)
count = 32 - *ppos;
if (copy_from_user(filp->private_data + *ppos, buffer, count))
return -EFAULT;
*ppos += count;
return count;
}
struct file_operations esp_debugfs_fops = {
.owner = THIS_MODULE,
.open = esp_debugfs_open,
.read = esp_debugfs_read,
.write = esp_debugfs_write,
};
struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type) {
struct dentry *rc = NULL;
umode_t mode = 0644;
if(!esp_debugfs_root)
return NULL;
if(!parent)
parent = esp_debugfs_root;
switch(type) {
case ESP_U8:
rc = debugfs_create_u8(name, mode, parent, (u8*)value);
break;
case ESP_U16:
rc = debugfs_create_u16(name, mode, parent, (u16*)value);
break;
case ESP_U32:
rc = debugfs_create_u32(name, mode, parent, (u32*)value);
break;
case ESP_U64:
rc = debugfs_create_u64(name, mode, parent, (u64*)value);
break;
case ESP_BOOL:
rc = debugfs_create_bool(name, mode, parent, (u32*)value);
break;
default: //32
rc = debugfs_create_u32(name, mode, parent, (u32*)value);
}
if (!rc)
goto Fail;
else
return rc;
Fail:
debugfs_remove_recursive(esp_debugfs_root);
esp_debugfs_root = NULL;
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
return NULL;
}
struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob) {
struct dentry * rc = NULL;
umode_t mode = 0644;
if(!esp_debugfs_root)
return NULL;
if(!parent)
parent = esp_debugfs_root;
rc = debugfs_create_blob(name, mode, parent, blob);
if (!rc)
goto Fail;
else
return rc;
Fail:
debugfs_remove_recursive(esp_debugfs_root);
esp_debugfs_root = NULL;
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
return NULL;
}
struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size) {
struct dentry *rc;
umode_t mode = 0644;
if(!esp_debugfs_root)
return NULL;
if(!parent)
parent = esp_debugfs_root;
rc = debugfs_create_file(name, mode, parent, data, &esp_debugfs_fops);
if (!rc)
goto Fail;
else
return rc;
Fail:
debugfs_remove_recursive(esp_debugfs_root);
esp_debugfs_root = NULL;
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
return NULL;
}
struct dentry *esp_debugfs_add_sub_dir(const char *name) {
struct dentry *sub_dir = NULL;
sub_dir = debugfs_create_dir(name, esp_debugfs_root);
if (!sub_dir)
goto Fail;
return sub_dir;
Fail:
debugfs_remove_recursive(esp_debugfs_root);
esp_debugfs_root = NULL;
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; dir name: %s\n", __FUNCTION__, name);
return NULL;
}
int esp_debugfs_init(void)
{
esp_dbg(ESP_DBG, "esp debugfs init\n");
esp_debugfs_root = debugfs_create_dir("esp_debug", NULL);
if (!esp_debugfs_root || IS_ERR_OR_NULL(esp_debugfs_root)) {
return -ENOENT;
}
return 0;
}
void esp_debugfs_exit(void)
{
esp_dbg(ESP_DBG, "esp debugfs exit");
debugfs_remove_recursive(esp_debugfs_root);
return;
}
#else
inline struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type) {
return NULL;
}
inline struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob) {
return NULL;
}
inline struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size) {
return NULL;
}
struct dentry *esp_debugfs_add_sub_dir(const char *name) {
return NULL;
}
inline int esp_debugfs_init(void)
{
return -1;
}
inline void esp_debugfs_exit(void)
{
}
#endif
void show_buf(u8 *buf, u32 len)
{
// print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
#if 1
int i = 0, j;
printk(KERN_INFO "\n++++++++++++++++show rbuf+++++++++++++++\n");
for (i = 0; i < (len / 16); i++) {
j = i * 16;
printk(KERN_INFO "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x \n", buf[j], buf[j+1],buf[j+2],buf[j+3],buf[j+4],buf[j+5],buf[j+6],buf[j+7],buf[j+8],buf[j+9],buf[j+10],buf[j+11],buf[j+12],buf[j+13],buf[j+14],buf[j+15]);
}
printk(KERN_INFO "\n++++++++++++++++++++++++++++++++++++++++\n");
#endif//0000
}
#ifdef HOST_RC
static u8 get_cnt(u32 cnt_store, int idx)
{
int shift = idx << 2;
return (u8)((cnt_store>>shift) & 0xf);
}
void esp_show_rcstatus(struct sip_rc_status *rcstatus)
{
int i;
char msg[82];
char rcstr[16];
u32 cnt_store = rcstatus->rc_cnt_store;
memset(msg, 0 ,sizeof(msg));
memset(rcstr, 0 ,sizeof(rcstr));
printk(KERN_INFO "rcstatus map 0x%08x cntStore 0x%08x\n", rcstatus->rc_map, rcstatus->rc_cnt_store);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (rcstatus->rc_map & BIT(i)) {
sprintf(rcstr, "rcIdx %d, cnt %d ", i, get_cnt(cnt_store, i));
strcat(msg, rcstr);
}
}
printk(KERN_INFO "%s \n", msg);
}
void esp_show_tx_rates(struct ieee80211_tx_rate* rates)
{
int i;
char msg[128];
char rcstr[32];
memset(msg, 0 ,sizeof(msg));
memset(rcstr, 0 ,sizeof(rcstr));
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (rates->idx != -1 ) {
sprintf(rcstr, "Idx %d, cnt %d, flag %02x ", rates->idx, rates->count, rates->flags);
strcat(msg, rcstr);
}
rates++;
}
strcat(msg, "\n");
printk(KERN_INFO "%s \n", msg);
}
#endif /* HOST_RC */

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2011 Espressif System.
*
*/
#ifndef _DEBUG_H_
#define assert(v) BUG_ON(!(v))
#define ASSERT(v) BUG_ON(!(v))
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <asm/uaccess.h>
typedef enum esp_type {
ESP_BOOL,
ESP_U8,
ESP_U16,
ESP_U32,
ESP_U64
} esp_type;
struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type);
struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob);
struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size);
struct dentry *esp_debugfs_add_sub_dir(const char *name);
int esp_debugfs_init(void);
void esp_debugfs_exit(void);
enum {
ESP_DBG_ERROR = BIT(0),
ESP_DBG_TRACE = BIT(1),
ESP_DBG_LOG = BIT(2),
ESP_DBG = BIT(3),
ESP_SHOW = BIT(4),
ESP_DBG_TXAMPDU = BIT(5),
ESP_DBG_OP = BIT(6),
ESP_DBG_PS = BIT(7),
ESP_DBG_ALL = 0xffffffff
};
extern unsigned int esp_msg_level;
#ifdef ESP_ANDROID_LOGGER
extern bool log_off;
#endif /* ESP_ANDROID_LOGGER */
#if defined(ANDROID) && defined(ESP_ANDROID_LOGGER)
#include "esp_android.h"
#define esp_dbg(mask, fmt, args...) do { \
if (esp_msg_level & mask) \
{ \
if (log_off) \
printk(fmt, ##args); \
else \
logger_write(4, "esp_wifi", fmt, ##args); \
} \
} while (0)
#else
#define esp_dbg(mask, fmt, args...) do { \
if (esp_msg_level & mask) \
printk(fmt, ##args); \
} while (0)
#endif /* ANDROID && ESP_ANDROID_LOGGER */
void show_buf(u8 *buf, u32 len);
#ifdef HOST_RC
struct sip_rc_status;
struct ieee80211_tx_rate;
void esp_show_rcstatus(struct sip_rc_status *rcstatus);
void esp_show_tx_rates(struct ieee80211_tx_rate *rates);
#endif /* HOST_RC */
#endif /* _DEBUG_H_ */

View File

@ -0,0 +1 @@
static char esp_init_data[] = {0x5,0x0,4,2,5,5,5,2,5,0,4,5,5,4,5,5,4,-2,-3,-1,-16,-16,-16,-32,-32,-32,204,1,0xff,0xff,0,0,0,0,82,78,74,68,64,56,0,0,1,1,2,3,4,5,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,240,10,0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,266 @@
/*
* Copyright (c) 2010 - 2012 Espressif System.
*/
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <linux/firmware.h>
#include <linux/sched.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <linux/time.h>
#include <linux/moduleparam.h>
#include "esp_pub.h"
#include "esp_sip.h"
#include "esp_sif.h"
#include "esp_debug.h"
#ifdef ANDROID
#include "esp_android.h"
#endif /* ANDROID */
#include "esp_wl.h"
#include "slc_host_register.h"
#include "esp_android.h"
struct completion *gl_bootup_cplx = NULL;
#ifndef FPGA_DEBUG
static int esp_download_fw(struct esp_pub * epub);
#endif /* !FGPA_DEBUG */
static bool modparam_no_txampdu = false;
static bool modparam_no_rxampdu = false;
module_param_named(no_txampdu, modparam_no_txampdu, bool, 0444);
MODULE_PARM_DESC(no_txampdu, "Disable tx ampdu.");
module_param_named(no_rxampdu, modparam_no_rxampdu, bool, 0444);
MODULE_PARM_DESC(no_rxampdu, "Disable rx ampdu.");
static char *modparam_eagle_path = "";
module_param_named(eagle_path, modparam_eagle_path, charp, 0444);
MODULE_PARM_DESC(eagle_path, "eagle path");
bool mod_support_no_txampdu()
{
return modparam_no_txampdu;
}
bool mod_support_no_rxampdu()
{
return modparam_no_rxampdu;
}
void mod_support_no_txampdu_set(bool value)
{
modparam_no_txampdu = value;
}
char *mod_eagle_path_get(void)
{
if (modparam_eagle_path[0] == '\0')
return NULL;
return modparam_eagle_path;
}
int esp_pub_init_all(struct esp_pub *epub)
{
int ret = 0;
/* completion for bootup event poll*/
DECLARE_COMPLETION_ONSTACK(complete);
atomic_set(&epub->ps.state, ESP_PM_OFF);
if(epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
epub->sip = sip_attach(epub);
esp_dump_var("esp_msg_level", NULL, &esp_msg_level, ESP_U32);
#if defined(ANDROID) && defined (ESP_ANDROID_LOGGER)
esp_dump_var("log_off", NULL, &log_off, ESP_U32);
#endif /* ESP_ANDROID_LOGGER */
ret = sip_prepare_boot(epub->sip);
if (ret)
return ret;
} else {
atomic_set(&epub->sip->state, SIP_PREPARE_BOOT);
atomic_set(&epub->sip->tx_credits, 0);
}
#ifndef FPGA_DEBUG
ret = esp_download_fw(epub);
if (ret) {
esp_dbg(ESP_DBG_ERROR, "download firmware failed\n");
return ret;
}
esp_dbg(ESP_DBG_TRACE, "download firmware OK \n");
#else
#ifndef SDIO_TEST
sip_send_bootup(epub->sip);
#endif /* !SDIO_TEST */
#endif /* FPGA_DEBUG */
gl_bootup_cplx = &complete;
sif_enable_irq(epub);
if(epub->sdio_state == ESP_SDIO_STATE_SECOND_INIT){
sip_poll_bootup_event(epub->sip);
} else {
sip_poll_resetting_event(epub->sip);
}
gl_bootup_cplx = NULL;
return ret;
}
#if 0
void esp_ps_config(struct esp_pub *epub, struct esp_ps *ps, bool on)
{
unsigned long time = jiffies - ps->last_config_time;
u32 time_msec = jiffies_to_msecs(time);
ps->last_config_time = jiffies;
if (on && (atomic_read(&ps->state) == ESP_PM_TURNING_ON || atomic_read(&ps->state) == ESP_PM_ON)) {
esp_dbg(ESP_DBG_PS, "%s same state\n", __func__);
return;
}
ps->nulldata_pm_on = false;
esp_dbg(ESP_DBG_PS, "%s PS %s, dtim %u maxslp %u period %u\n", __func__, on?"ON":"OFF", ps->dtim_period, ps->max_sleep_period, time_msec);
//NB: turn on ps may need additional check, make sure don't hurt iperf downlink since pkt may be sparse during rx
if (on) {
esp_dbg(ESP_DBG_PS, "%s ps state %d => turning ON\n", __func__, atomic_read(&ps->state));
atomic_set(&ps->state, ESP_PM_TURNING_ON);
} else {
esp_dbg(ESP_DBG_PS, "%s ps state %d => turning OFF\n", __func__, atomic_read(&ps->state));
atomic_set(&ps->state, ESP_PM_TURNING_OFF);
}
sip_send_ps_config(epub, ps);
}
#endif
void
esp_dsr(struct esp_pub *epub)
{
sip_rx(epub);
}
struct esp_fw_hdr {
u8 magic;
u8 blocks;
u8 pad[2];
u32 entry_addr;
} __packed;
struct esp_fw_blk_hdr {
u32 load_addr;
u32 data_len;
} __packed;
#define ESP_FW_NAME1 "eagle_fw1.bin"
#define ESP_FW_NAME2 "eagle_fw2.bin"
#ifndef FPGA_DEBUG
static int esp_download_fw(struct esp_pub * epub)
{
#ifndef HAS_FW
const struct firmware *fw_entry;
#endif /* !HAS_FW */
u8 * fw_buf = NULL;
u32 offset = 0;
int ret = 0;
u8 blocks;
struct esp_fw_hdr *fhdr;
struct esp_fw_blk_hdr *bhdr=NULL;
struct sip_cmd_bootup bootcmd;
#ifndef HAS_FW
char * esp_fw_name = epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT ? ESP_FW_NAME1 : ESP_FW_NAME2;
#ifdef ANDROID
ret = android_request_firmware(&fw_entry, esp_fw_name, epub->dev);
#else
ret = request_firmware(&fw_entry, esp_fw_name, epub->dev);
#endif //ANDROID
if (ret)
return ret;
fw_buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
#ifdef ANDROID
android_release_firmware(fw_entry);
#else
release_firmware(fw_entry);
#endif //ANDROID
if (fw_buf == NULL) {
return -ENOMEM;
}
#else
#include "eagle_fw1.h"
#include "eagle_fw2.h"
fw_buf = epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT ? &eagle_fw1[0] : &eagle_fw2[0];
#endif /* HAS_FW */
fhdr = (struct esp_fw_hdr *)fw_buf;
if (fhdr->magic != 0xE9) {
esp_dbg(ESP_DBG_ERROR, "%s wrong magic! \n", __func__);
goto _err;
}
blocks = fhdr->blocks;
offset += sizeof(struct esp_fw_hdr);
while (blocks) {
bhdr = (struct esp_fw_blk_hdr *)(&fw_buf[offset]);
offset += sizeof(struct esp_fw_blk_hdr);
ret = sip_write_memory(epub->sip, bhdr->load_addr, &fw_buf[offset], bhdr->data_len);
if (ret) {
esp_dbg(ESP_DBG_ERROR, "%s Failed to write fw, err: %d\n", __func__, ret);
goto _err;
}
blocks--;
offset += bhdr->data_len;
}
/* TODO: last byte should be the checksum and skip checksum for now */
bootcmd.boot_addr = fhdr->entry_addr;
ret = sip_send_cmd(epub->sip, SIP_CMD_BOOTUP, sizeof(struct sip_cmd_bootup), &bootcmd);
if (ret)
goto _err;
_err:
#ifndef HAS_FW
kfree(fw_buf);
#endif /* !HAS_FW */
return ret;
}
#endif /* !FPGA_DEBUG */

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) 2012 Espressif System
*/
#ifndef _ESP_OS_H_
#define _ESP_OS_H_
#ifndef __packed
#define __packed __attribute__ ((packed))
#endif /* __packed */
#include "net/mac80211.h"
#endif /*__ESP_OS_H_*/

View File

@ -0,0 +1,6 @@
#ifndef _ESP_PATH_H_
#define _ESP_PATH_H_
#define FWPATH "/system/lib/modules"
//module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
#endif /* _ESP_PATH_H_ */

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2010 -2013 Espressif System.
*
*/
#ifdef CONFIG_HAS_WAKELOCK
#include <linux/wakelock.h>
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include "esp_pub.h"
#ifdef CONFIG_HAS_EARLYSUSPEND
static void esp_early_suspend(struct early_suspend *h)
{
printk("%s\n", __func__);
}
static void esp_late_resume(struct early_suspend*h)
{
printk("%s\n", __func__);
}
static struct early_suspend esp_early_suspend_ctrl = {
.suspend = esp_early_suspend,
.resume = esp_late_resume,
.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20,
};
#endif /* EARLYSUSPEND */
void esp_register_early_suspend(void)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
register_early_suspend(&esp_early_suspend_ctrl);
#endif
}
void esp_unregister_early_suspend(void)
{
#ifdef CONFIG_HAS_EARLYSUSPEND
unregister_early_suspend(&esp_early_suspend_ctrl);
#endif
}
#ifdef CONFIG_HAS_WAKELOCK
static struct wake_lock esp_wake_lock_;
#endif /* WAKELOCK */
void esp_wakelock_init(void)
{
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_init(&esp_wake_lock_, WAKE_LOCK_SUSPEND, "eagle");
#endif
}
void esp_wakelock_destroy(void)
{
#ifdef CONFIG_HAS_WAKELOCK
wake_lock_destroy(&esp_wake_lock_);
#endif
}
void esp_wake_lock(void)
{
#ifdef CONFIG_HAS_WAKELOCK
wake_lock(&esp_wake_lock_);
#endif
}
void esp_wake_unlock(void)
{
#ifdef CONFIG_HAS_WAKELOCK
wake_unlock(&esp_wake_lock_);
#endif
}

View File

@ -0,0 +1,223 @@
/*
* Copyright (c) 2011-2012 Espressif System.
*
* wlan device header file
*/
#ifndef _ESP_PUB_H_
#define _ESP_PUB_H_
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <linux/firmware.h>
#include <linux/sched.h>
#include <net/mac80211.h>
#include <net/cfg80211.h>
#include <linux/version.h>
#include "sip2_common.h"
enum esp_sdio_state{
ESP_SDIO_STATE_FIRST_INIT,
ESP_SDIO_STATE_FIRST_NORMAL_EXIT,
ESP_SDIO_STATE_FIRST_ERROR_EXIT,
ESP_SDIO_STATE_SECOND_INIT,
ESP_SDIO_STATE_SECOND_ERROR_EXIT,
};
enum esp_tid_state {
ESP_TID_STATE_INIT,
ESP_TID_STATE_TRIGGER,
ESP_TID_STATE_PROGRESS,
ESP_TID_STATE_OPERATIONAL,
ESP_TID_STATE_WAIT_STOP,
ESP_TID_STATE_STOP,
};
struct esp_tx_tid {
u8 state;
u8 cnt;
u16 ssn;
};
#define WME_NUM_TID 16
struct esp_node {
struct esp_tx_tid tid[WME_NUM_TID];
struct ieee80211_sta *sta;
u8 ifidx;
u8 index;
};
#define WME_AC_BE 2
#define WME_AC_BK 3
#define WME_AC_VI 1
#define WME_AC_VO 0
struct llc_snap_hdr {
u8 dsap;
u8 ssap;
u8 cntl;
u8 org_code[3];
__be16 eth_type;
} __packed;
struct esp_vif {
struct esp_pub *epub;
u8 index;
u32 beacon_interval;
bool ap_up;
struct timer_list beacon_timer;
};
/* WLAN related, mostly... */
/*struct hw_scan_timeout {
struct delayed_work w;
struct ieee80211_hw *hw;
};*/
typedef struct esp_wl {
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 dot11_auth_mode;
u8 auth_mode;
u8 prwise_crypto;
u8 prwise_crypto_len;
u8 grp_crypto;
u8 grp_crpto_len;
u8 def_txkey_index;
u32 used_key_entries; //each bit represent an entry, 0: avail 1: used
u8 bssid[ETH_ALEN];
u8 req_bssid[ETH_ALEN];
u16 ch_hint;
u16 bss_ch;
u16 listen_intvl_b;
u16 listen_intvl_t;
//struct hw_scan_timeout *hsd;
struct cfg80211_scan_request *scan_req;
atomic_t ptk_cnt;
atomic_t gtk_cnt;
atomic_t tkip_key_set;
//struct ieee80211_key_conf *ptk;
//struct ieee80211_key_conf *gtk[4];
struct list_head amsdu_rx_buffer_queue;
struct timer_list disconnect_timer;
/* so far only 2G band */
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
unsigned long flags;
atomic_t off;
} esp_wl_t;
typedef struct esp_hw_idx_map {
u8 mac[ETH_ALEN];
u8 flag;
} esp_hw_idx_map_t;
#define ESP_TXQ_MAX_LEN 64 /* TBD: better #? */
#define ESP_PUB_F_TXPAUSE 0x1
#define ESP_WL_FLAG_RFKILL BIT(0)
#define ESP_WL_FLAG_HW_REGISTERED BIT(1)
#define ESP_WL_FLAG_CONNECT BIT(2)
#define ESP_WL_FLAG_STOP_TXQ BIT(3)
#define ESP_PUB_MAX_VIF 2
#define ESP_PUB_MAX_STA 4 //for one interface
enum {
ESP_PM_OFF = 0,
ESP_PM_TURNING_ON,
ESP_PM_ON,
ESP_PM_TURNING_OFF, /* Do NOT change the order */
};
struct esp_ps {
u32 dtim_period;
u32 max_sleep_period;
unsigned long last_config_time;
atomic_t state;
bool nulldata_pm_on;
};
struct esp_pub {
struct device *dev;
#ifdef ESP_NO_MAC80211
struct net_device *net_dev;
struct wireless_dev *wdev;
struct net_device_stats *net_stats;
#else
struct ieee80211_hw *hw;
struct ieee80211_vif *vif;
u8 vif_slot;
#endif /* ESP_MAC80211 */
void *sif; /* serial interface control block, e.g. sdio */
enum esp_sdio_state sdio_state;
struct esp_sip *sip;
struct esp_wl wl;
struct esp_hw_idx_map hi_map[19];
struct esp_hw_idx_map low_map[ESP_PUB_MAX_VIF][2];
u32 flags; //flags to represent rfkill switch,start
u8 roc_flags; //0: not in remain on channel state, 1: in roc state
struct work_struct tx_work; /* attach to ieee80211 workqueue */
/* latest mac80211 has multiple tx queue, but we stick with single queue now */
spinlock_t rx_lock;
spinlock_t tx_ampdu_lock;
spinlock_t tx_lock;
struct mutex tx_mtx;
struct sk_buff_head txq;
atomic_t txq_stopped;
struct work_struct sendup_work; /* attach to ieee80211 workqueue */
struct sk_buff_head txdoneq;
struct sk_buff_head rxq;
struct workqueue_struct *esp_wkq;
u8 bssid[ETH_ALEN];
u8 mac_addr[ETH_ALEN];
u32 rx_filter;
unsigned long scan_permit;
bool scan_permit_valid;
struct delayed_work scan_timeout_work;
u8 enodes_map;
u8 enodes_maps[ESP_PUB_MAX_VIF];
struct esp_node * enodes[ESP_PUB_MAX_STA + 1];
struct esp_ps ps;
};
typedef struct esp_pub esp_pub_t;
struct esp_pub *esp_pub_alloc_mac80211(struct device *dev);
int esp_pub_dealloc_mac80211(struct esp_pub *epub);
int esp_register_mac80211(struct esp_pub *epub);
int esp_pub_init_all(struct esp_pub *epub);
char *mod_eagle_path_get(void);
void esp_dsr(struct esp_pub *epub);
void hw_scan_done(struct esp_pub *epub, bool aborted);
void esp_rocdone_process(struct ieee80211_hw *hw, struct sip_evt_roc *report);
void esp_ps_config(struct esp_pub *epub, struct esp_ps *ps, bool on);
void esp_register_early_suspend(void);
void esp_unregister_early_suspend(void);
void esp_wakelock_init(void);
void esp_wakelock_destroy(void);
void esp_wake_lock(void);
void esp_wake_unlock(void);
struct esp_node * esp_get_node_by_addr(struct esp_pub * epub, u8 *addr);
#ifdef TEST_MODE
int test_init_netlink(struct esp_sip *sip);
void test_exit_netlink(void);
void esp_test_cmd_event(u32 cmd_type, char *reply_info);
#endif
#endif /* _ESP_PUB_H_ */

View File

@ -0,0 +1,142 @@
/*
* Copyright (c) 2011 - 2013 Espressif System.
*
* Serial I/F wrapper layer for eagle WLAN device,
* abstraction of buses like SDIO/SIP, and provides
* flow control for tx/rx layer
*
*/
#ifndef _ESP_SIF_H_
#define _ESP_SIF_H_
#include "esp_pub.h"
#include <linux/mmc/host.h>
/*
* H/W SLC module definitions
*/
#define SIF_SLC_BLOCK_SIZE 512
#define SIF_DMA_BUFFER_SIZE (64 * 1024)
/* to make the last byte located at :xffff, increase 1 byte here */
//#define SIF_SLC_WINDOW_END_ADDR (0xffff + 1)
//#define SIF_SLC_WINDOW_END_ADDR (0x1ffff + 1 - 0x800)
#define SIF_MAX_SCATTER_REQUESTS 4
#define SIF_MAX_SCATTER_ENTRIES_PER_REQ 16
#define SIF_MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024)
/* SIF bus request */
#define SIF_REQ_MAX_NUM 64
/* S/W struct mapping to slc registers */
typedef struct slc_host_regs {
/* do NOT read token_rdata
*
u32 pf_data;
u32 token_rdata;
*/
u32 intr_raw;
u32 state_w0;
u32 state_w1;
u32 config_w0;
u32 config_w1;
u32 intr_status;
u32 config_w2;
u32 config_w3;
u32 config_w4;
u32 token_wdata;
u32 intr_clear;
u32 intr_enable;
} sif_slc_reg_t;
struct sif_req {
struct list_head list;
u32 address;
u8 *buffer;
u32 length;
u32 flag;
int status;
void * context;
};
#define SIF_TO_DEVICE 0x1
#define SIF_FROM_DEVICE 0x2
#define SIF_SYNC 0x00000010
#define SIF_ASYNC 0x00000020
#define SIF_BYTE_BASIS 0x00000040
#define SIF_BLOCK_BASIS 0x00000080
#define SIF_FIXED_ADDR 0x00000100
#define SIF_INC_ADDR 0x00000200
static void inline sif_setup_req(struct sif_req *req, u32 addr, u32 flag, u32 len,
u8 * buf, void *context)
{
req->address = addr;
req->flag = flag;
req->length = len;
req->buffer = buf;
req->context = context;
}
void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res);
u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res);
void sif_enable_irq(struct esp_pub *epub);
void sif_disable_irq(struct esp_pub *epub);
void sif_disable_target_interrupt(struct esp_pub *epub);
int sif_io_raw(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag);
int sif_io_sync(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag);
int sif_io_async(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag, void * context);
u32 sif_get_blksz(struct esp_pub *epub);
u32 sif_get_target_id(struct esp_pub *epub);
int sif_lldesc_read_sync(struct esp_pub *epub, u8 *buf, u32 len);
int sif_lldesc_write_sync(struct esp_pub *epub, u8 *buf, u32 len);
int sif_lldesc_read_raw(struct esp_pub *epub, u8 *buf, u32 len, bool noround);
int sif_lldesc_write_raw(struct esp_pub *epub, u8 *buf, u32 len);
struct slc_host_regs * sif_get_regs(struct esp_pub *epub);
void sif_lock_bus(struct esp_pub *epub);
void sif_unlock_bus(struct esp_pub *epub);
void sif_platform_target_poweroff(void);
void sif_platform_target_poweron(void);
void sif_platform_target_speed(int high_speed);
void sif_platform_reset_target(void);
void sif_platform_rescan_card(unsigned insert);
void sif_raw_dummy_read(struct esp_pub *epub);
void sif_record_bt_config(int value);
int sif_get_bt_config(void);
void sif_record_rst_config(int value);
int sif_get_rst_config(void);
void sif_record_retry_config(void);
int sif_get_retry_config(void);
#ifdef ESP_ACK_INTERRUPT
//extern void sif_platform_ack_interrupt(struct mmc_host *mmc);
extern void sif_platform_ack_interrupt(struct esp_pub *epub);
#endif //ESP_ACK_INTERRUPT
#define sif_reg_read_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR)
#define sif_reg_write_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR)
#endif /* _ESP_SIF_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
/*
* Copyright (c) 2009- 2012 Espressif System.
*
* Serial Interconnctor Protocol
*/
#ifndef _ESP_SIP_H
#define _ESP_SIP_H
#include "sip2_common.h"
#define SIP_PKT_MAX_LEN (1024*16)
/* 16KB on normal X86 system, should check before porting to orhters */
#define SIP_TX_AGGR_BUF_SIZE (4 * PAGE_SIZE)
#define SIP_RX_AGGR_BUF_SIZE (4 * PAGE_SIZE)
struct sk_buff;
struct sip_pkt {
struct list_head list;
u8 * buf_begin;
u32 buf_len;
u8 * buf;
u32 payload_len;
#if 0
union {
struct sip_tx_pkt_info tx;
struct sip_rx_pkt_info rx;
} info;
#endif
void *context;
int status;
//void (* completion)(struct esp_sip *sip, struct sip_pkt *pkt);
};
typedef enum SIP_STATE {
SIP_INIT = 0,
SIP_PREPARE_BOOT,
SIP_BOOT,
SIP_SEND_INIT,
SIP_WAIT_BOOTUP,
SIP_RUN,
SIP_SUSPEND,
SIP_STOP
} SIP_STATE;
enum sip_notifier {
SIP_TX_DONE = 1,
SIP_RX_DONE = 2,
};
#define SIP_CREDITS_LOW_THRESHOLD 64 //i.e. 4k
struct esp_sip {
struct list_head free_ctrl_txbuf;
struct list_head free_ctrl_rxbuf;
u32 rxseq; /* sip pkt seq, should match target side */
u32 txseq;
u32 txdataseq;
atomic_t state;
spinlock_t lock;
int boot_credits;
atomic_t tx_credits;
atomic_t tx_ask_credit_update;
u8 * rawbuf; /* used in boot stage, free once chip is fully up */
u8 * tx_aggr_buf;
u8 * tx_aggr_write_ptr; /* update after insertion of each pkt */
u8 * tx_aggr_lastpkt_ptr;
u8 * rx_aggr_buf;
u8 * rx_aggr_write_ptr;
u8 * rx_aggr_lastpkt_ptr;
spinlock_t rx_lock;
struct sk_buff_head rxq;
#ifndef RX_SYNC
struct work_struct rx_process_work;
#endif/* RX_SYNC */
u16 tx_blksz;
u16 rx_blksz;
bool dump_rpbm_err;
bool sendup_rpbm_pkt;
bool rxabort_fixed;
bool support_bgscan;
u8 credit_to_reserve;
s16 noise_floor;
u32 tx_tot_len; /* total len for one transaction */
u32 rx_tot_len;
atomic_t rx_handling;
atomic_t tx_data_pkt_queued;
#ifndef FAST_TX_STATUS
atomic_t pending_tx_status;
#endif /* !FAST_TX_STATUS */
atomic_t data_tx_stopped;
atomic_t tx_stopped;
struct esp_pub *epub;
};
int sip_rx(struct esp_pub * epub);
//int sip_download_fw(struct esp_sip *sip, u32 load_addr, u32 boot_addr);
/* tx must pad as 4-byte aligned */
int sip_tx(struct esp_pub * epub, struct sip_pkt *pkt);
int sip_get_raw_credits(struct esp_sip *);
int sip_write_memory(struct esp_sip *, u32 addr, u8* buf, u16 len);
void sip_credit_process(struct esp_pub *, u8 credits);
int sip_prepare_boot(struct esp_sip *sip);
int sip_send_cmd(struct esp_sip *sip, int cid, u32 cmdlen, void * cmd);
struct esp_sip * sip_attach(struct esp_pub *);
int sip_post_init(struct esp_sip *sip, struct sip_evt_bootup2 *bevt);
void sip_detach(struct esp_sip *sip);
void sip_txq_process(struct esp_pub *epub);
struct sk_buff * sip_alloc_ctrl_skbuf(struct esp_sip *sip, u16 len, u32 cid);
void sip_free_ctrl_skbuff(struct esp_sip *sip, struct sk_buff* skb);
bool sip_queue_need_stop(struct esp_sip *sip);
bool sip_queue_may_resume(struct esp_sip *sip);
bool sip_tx_data_need_stop(struct esp_sip *sip);
bool sip_tx_data_may_resume(struct esp_sip *sip);
void sip_tx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb);
void sip_rx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb);
int sip_cmd_enqueue(struct esp_sip *sip, struct sk_buff *skb);
void sip_dump_pending_data(struct esp_pub *epub);
int sip_poll_bootup_event(struct esp_sip *sip);
int sip_poll_resetting_event(struct esp_sip *sip);
void sip_trigger_txq_process(struct esp_sip *sip);
void sip_send_chip_init(struct esp_sip *sip);
bool mod_support_no_txampdu(void);
bool mod_support_no_rxampdu(void);
void mod_support_no_txampdu_set(bool value);
#ifdef FPGA_DEBUG
int sip_send_bootup(struct esp_sip *sip);
#endif /* FPGA_DEBUG */
void sip_debug_show(struct esp_sip *sip);
#endif

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) 2012 Espressif System.
*/
#include "linux/types.h"
#include "linux/kernel.h"
#include <linux/ieee80211.h>
#include <net/mac80211.h>
#include <linux/skbuff.h>
#include <net/tcp.h>
#include <linux/ip.h>
#include <asm/checksum.h>
#include "esp_pub.h"
#include "esp_utils.h"
#include "esp_wmac.h"
#include "esp_debug.h"
/*
* Convert IEEE channel number to MHz frequency.
*/
u32
esp_ieee2mhz(u8 chan)
{
if (chan == 14)
return 2484;
if (chan < 14)
return 2407 + chan*5;
else
return 2512 + ((chan-15)*20);
}
enum {
ESP_RATE_1_LONG = 0x0,
ESP_RATE_2_LONG = 0x1,
ESP_RATE_2_SHORT = 0x5,
ESP_RATE_5_SHORT = 0x6,
ESP_RATE_5_LONG = 0x2,
ESP_RATE_11_SHORT = 0x7,
ESP_RATE_11_LONG = 0x3,
ESP_RATE_6 = 0xb,
ESP_RATE_9 = 0xf,
ESP_RATE_12 = 0xa,
ESP_RATE_18 = 0xe,
ESP_RATE_24 = 0x9,
ESP_RATE_36 = 0xd,
ESP_RATE_48 = 0x8,
ESP_RATE_54 = 0xc,
/* ESP_RATE_MCS0 =0x10,
ESP_RATE_MCS1 =0x11,
ESP_RATE_MCS2 =0x12,
ESP_RATE_MCS3 =0x13,
ESP_RATE_MCS4 =0x14,
ESP_RATE_MCS5 =0x15,
ESP_RATE_MCS6 =0x16,
ESP_RATE_MCS7 =0x17,
*/
};
static u8 esp_rate_table[20] = {
ESP_RATE_1_LONG,
ESP_RATE_2_SHORT,
ESP_RATE_5_SHORT,
ESP_RATE_11_SHORT,
ESP_RATE_6,
ESP_RATE_9,
ESP_RATE_12,
ESP_RATE_18,
ESP_RATE_24,
ESP_RATE_36,
ESP_RATE_48,
ESP_RATE_54,
/* ESP_RATE_MCS0,
ESP_RATE_MCS1,
ESP_RATE_MCS2,
ESP_RATE_MCS3,
ESP_RATE_MCS4,
ESP_RATE_MCS5,
ESP_RATE_MCS6,
ESP_RATE_MCS7,
*/
};
s8 esp_wmac_rate2idx(u8 rate)
{
int i;
for (i = 0; i < 20; i++) {
if (rate == esp_rate_table[i])
return i;
}
if (rate == ESP_RATE_2_LONG)
return 1;
if (rate == ESP_RATE_5_LONG)
return 2;
if (rate == ESP_RATE_11_LONG)
return 3;
esp_dbg(ESP_DBG_ERROR,"%s unknown rate 0x%02x \n", __func__, rate);
return 0;
}
bool esp_wmac_rxsec_error(u8 error)
{
return (error >= RX_SECOV_ERR && error <= RX_SECFIFO_TIMEOUT) || (error >= RX_WEPICV_ERR && error <= RX_WAPIMIC_ERR);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
int esp_cipher2alg(int cipher)
{
if (cipher == WLAN_CIPHER_SUITE_TKIP)
return ALG_TKIP;
if (cipher == WLAN_CIPHER_SUITE_CCMP)
return ALG_CCMP;
if (cipher == WLAN_CIPHER_SUITE_WEP40 || cipher == WLAN_CIPHER_SUITE_WEP104)
return ALG_WEP;
if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
return ALG_AES_CMAC;
//printk("%s wrong cipher 0x%x!\n",__func__,cipher);
return -1;
}
#endif /* NEW_KERNEL */
#ifdef RX_CHECKSUM_TEST
atomic_t g_iv_len;
void esp_rx_checksum_test(struct sk_buff *skb)
{
static u32 ip_err = 0;
static u32 tcp_err = 0;
struct ieee80211_hdr *pwh = (struct ieee80211_hdr *)skb->data;
int hdrlen = ieee80211_hdrlen(pwh->frame_control);
if(ieee80211_has_protected(pwh->frame_control))
hdrlen += atomic_read(&g_iv_len);
if (ieee80211_is_data(pwh->frame_control)) {
struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
if (ntohs(llc->eth_type) == ETH_P_IP) {
int llclen = sizeof(struct llc_snap_hdr);
struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
__sum16 csum_bak = iph->check;
iph->check = 0;
iph->check = ip_fast_csum(iph, iph->ihl);
if (iph->check != csum_bak) {
esp_dbg(ESP_DBG_ERROR, "total ip checksum error %d\n", ++ip_err);
}
iph->check = csum_bak;
if (iph->protocol == 0x06) {
struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
int datalen = skb->len - (hdrlen + llclen + iph->ihl * 4);
csum_bak = tcph->check;
tcph->check = 0;
tcph->check = tcp_v4_check(datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0));
if (tcph->check != csum_bak)
{
esp_dbg(ESP_DBG_ERROR, "total tcp checksum error %d\n", ++tcp_err);
}
tcph->check = csum_bak;
}
}
}
}
#endif
#ifdef GEN_ERR_CHECKSUM
void esp_gen_err_checksum(struct sk_buff *skb)
{
static u32 tx_seq = 0;
if ((tx_seq++ % 16) == 0)
{
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
if(ieee80211_has_protected(pwh->frame_control))
hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
if (ntohs(llc->eth_type) == ETH_P_IP) {
int llclen = sizeof(struct llc_snap_hdr);
struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
iph->check = ~iph->check;
if (iph->protocol == 0x06) {
struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
tcph->check = ~tcph->check;
}
}
}
}
#endif
bool esp_is_ip_pkt(struct sk_buff *skb)
{
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
int hdrlen;
struct llc_snap_hdr * llc;
if (!ieee80211_is_data(hdr->frame_control))
return false;
hdrlen = ieee80211_hdrlen(hdr->frame_control);
if(ieee80211_has_protected(hdr->frame_control))
hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
#ifdef RX_CHECKSUM_TEST
atomic_set(&g_iv_len, IEEE80211_SKB_CB(skb)->control.hw_key->iv_len);
#endif
if(skb->len < hdrlen + sizeof(struct llc_snap_hdr))
return false;
llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
if (ntohs(llc->eth_type) != ETH_P_IP)
return false;
else
return true;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2011-2012 Espressif System.
*/
#ifndef _ESP_UTILS_H_
#define _ESP_UTILS_H_
#include "linux/types.h"
#include <linux/version.h>
#ifndef BIT
#define BIT(x) (0x1 << (x))
#endif
u32 esp_ieee2mhz(u8 chan);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
enum ieee80211_key_alg {
ALG_WEP,
ALG_TKIP,
ALG_CCMP,
ALG_AES_CMAC
};
int esp_cipher2alg(int cipher);
void esp_rx_checksum_test(struct sk_buff *skb);
void esp_gen_err_checksum(struct sk_buff *skb);
#endif /* NEW_KERNEL */
bool esp_is_ip_pkt(struct sk_buff *skb);
#endif

View File

@ -0,0 +1 @@
#define DRIVER_VER 0xc51cbcad39ff

View File

@ -0,0 +1,61 @@
#ifndef _ESP_WL_H_
#define _ESP_WL_H_
//#define MAX_PROBED_SSID_INDEX 9
enum {
CONF_HW_BIT_RATE_1MBPS = BIT(0),
CONF_HW_BIT_RATE_2MBPS = BIT(1),
CONF_HW_BIT_RATE_5_5MBPS = BIT(2),
CONF_HW_BIT_RATE_11MBPS = BIT(3),
CONF_HW_BIT_RATE_6MBPS = BIT(4),
CONF_HW_BIT_RATE_9MBPS = BIT(5),
CONF_HW_BIT_RATE_12MBPS = BIT(6),
CONF_HW_BIT_RATE_18MBPS = BIT(7),
CONF_HW_BIT_RATE_22MBPS = BIT(8),
CONF_HW_BIT_RATE_24MBPS = BIT(9),
CONF_HW_BIT_RATE_36MBPS = BIT(10),
CONF_HW_BIT_RATE_48MBPS = BIT(11),
CONF_HW_BIT_RATE_54MBPS = BIT(12),
CONF_HW_BIT_RATE_11B_MASK = (CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS),
};
#if 0
enum {
CONF_HW_RATE_INDEX_1MBPS = 0,
CONF_HW_RATE_INDEX_2MBPS = 1,
CONF_HW_RATE_INDEX_5_5MBPS = 2,
CONF_HW_RATE_INDEX_6MBPS = 3,
CONF_HW_RATE_INDEX_9MBPS = 4,
CONF_HW_RATE_INDEX_11MBPS = 5,
CONF_HW_RATE_INDEX_12MBPS = 6,
CONF_HW_RATE_INDEX_18MBPS = 7,
CONF_HW_RATE_INDEX_22MBPS = 8,
CONF_HW_RATE_INDEX_24MBPS = 9,
CONF_HW_RATE_INDEX_36MBPS = 10,
CONF_HW_RATE_INDEX_48MBPS = 11,
CONF_HW_RATE_INDEX_54MBPS = 12,
CONF_HW_RATE_INDEX_MAX,
};
enum {
CONF_HW_RXTX_RATE_54 = 0,
CONF_HW_RXTX_RATE_48,
CONF_HW_RXTX_RATE_36,
CONF_HW_RXTX_RATE_24,
CONF_HW_RXTX_RATE_22,
CONF_HW_RXTX_RATE_18,
CONF_HW_RXTX_RATE_12,
CONF_HW_RXTX_RATE_11,
CONF_HW_RXTX_RATE_9,
CONF_HW_RXTX_RATE_6,
CONF_HW_RXTX_RATE_5_5,
CONF_HW_RXTX_RATE_2,
CONF_HW_RXTX_RATE_1,
CONF_HW_RXTX_RATE_MAX,
CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff
};
#endif
#endif /* _ESP_WL_H_ */

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2011-2012 Espressif System.
*
* MAC header
*/
#ifndef _ESP_WMAC_H_
#define _ESP_WMAC_H_
struct esp_mac_rx_ctrl {
signed rssi:8;
unsigned rate:4;
unsigned is_group:1;
unsigned:1;
unsigned sig_mode:2;
unsigned legacy_length:12;
unsigned damatch0:1;
unsigned damatch1:1;
unsigned bssidmatch0:1;
unsigned bssidmatch1:1;
unsigned MCS:7;
unsigned CWB:1;
unsigned HT_length:16;
unsigned Smoothing:1;
unsigned Not_Sounding:1;
unsigned:1;
unsigned Aggregation:1;
unsigned STBC:2;
unsigned FEC_CODING:1;
unsigned SGI:1;
unsigned rxend_state:8;
unsigned ampdu_cnt:8;
unsigned channel:4;
unsigned:12;
};
struct esp_rx_ampdu_len {
unsigned substate:8;
unsigned sublen:12;
unsigned :12;
};
struct esp_tx_ampdu_entry {
u32 sub_len:12,
dili_num:7,
:1,
null_byte:2,
data:1,
enc:1,
seq:8;
};
//rxend_state flags
#define RX_PYH_ERR_MIN 0x42
#define RX_AGC_ERR_MIN 0x42
#define RX_AGC_ERR_MAX 0x47
#define RX_OFDM_ERR_MIN 0x50
#define RX_OFDM_ERR_MAX 0x58
#define RX_CCK_ERR_MIN 0x59
#define RX_CCK_ERR_MAX 0x5F
#define RX_ABORT 0x80
#define RX_SF_ERR 0x40
#define RX_FCS_ERR 0x41
#define RX_AHBOV_ERR 0xC0
#define RX_BUFOV_ERR 0xC1
#define RX_BUFINV_ERR 0xC2
#define RX_AMPDUSF_ERR 0xC3
#define RX_AMPDUBUFOV_ERR 0xC4
#define RX_MACBBFIFOOV_ERR 0xC5
#define RX_RPBM_ERR 0xC6
#define RX_BTFORCE_ERR 0xC7
#define RX_SECOV_ERR 0xE1
#define RX_SECPROT_ERR0 0xE2
#define RX_SECPROT_ERR1 0xE3
#define RX_SECKEY_ERR 0xE4
#define RX_SECCRLEN_ERR 0xE5
#define RX_SECFIFO_TIMEOUT 0xE6
#define RX_WEPICV_ERR 0xF0
#define RX_TKIPICV_ERR 0xF4
#define RX_TKIPMIC_ERR 0xF5
#define RX_CCMPMIC_ERR 0xF8
#define RX_WAPIMIC_ERR 0xFC
s8 esp_wmac_rate2idx(u8 rate);
bool esp_wmac_rxsec_error(u8 error);
#endif /* _ESP_WMAC_H_ */

View File

@ -0,0 +1 @@
crystal_26M_en=0;test_xtal=0;sdio_configure=2;bt_configure=0;bt_protocol=0;dual_ant_configure=0;test_uart_configure=2;share_xtal=0;gpio_wake=0;no_auto_sleep=0;ext_rst=0;$

View File

@ -0,0 +1,3 @@
#export TOOLCHAIN_PREFIX=/cold/RK2/4.2/sdk4_2/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
export KERNEL_DIR=/cold/rk4.4/new_sdk/sdk4_4_for_push/kernel
export EAGLE_BASE_DIR=$(pwd)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2013 Espressif System.
*
* sdio stub code for RK
*/
#include <mach/gpio.h>
#include <mach/iomux.h>
#define ESP8089_DRV_VERSION "1.03"
extern int rk29sdk_wifi_power(int on);
extern int rk29sdk_wifi_set_carddetect(int val);
void sif_platform_rescan_card(unsigned insert)
{
rk29sdk_wifi_set_carddetect(insert);
}
void sif_platform_reset_target(void)
{
if(sif_get_bt_config() == 1 && sif_get_retry_config() == 0){
if(sif_get_rst_config() == 1){
//TODO, use gpio to reset target
} else {
iomux_set(GPIO3_D2);
gpio_request(RK30_PIN3_PD2, "esp8089-sdio-wifi");
mdelay(100);
gpio_direction_output(RK30_PIN3_PD2, 0);
mdelay(50);
gpio_direction_output(RK30_PIN3_PD2, 1);
}
} else {
//rk29sdk_wifi_set_carddetect(0);
rk29sdk_wifi_power(0);
rk29sdk_wifi_power(1);
//rk29sdk_wifi_set_carddetect(1);
}
}
void sif_platform_target_poweroff(void)
{
printk("=======================================================\n");
printk("==== Dislaunching Wi-Fi driver! (Powered by Rockchip) ====\n");
printk("=======================================================\n");
printk("Espressif ESP8089 SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", ESP8089_DRV_VERSION);
//rk29sdk_wifi_set_carddetect(0);
if(sif_get_bt_config() != 1)
rk29sdk_wifi_power(0);
}
void sif_platform_target_poweron(void)
{
printk("=======================================================\n");
printk("==== Launching Wi-Fi driver! (Powered by Rockchip) ====\n");
printk("=======================================================\n");
printk("Espressif ESP8089 SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", ESP8089_DRV_VERSION);
if(sif_get_bt_config() == 1){
sif_platform_reset_target();
}
rk29sdk_wifi_power(1);
//rk29sdk_wifi_set_carddetect(1);
}
void sif_platform_target_speed(int high_speed)
{
}
#ifdef ESP_ACK_INTERRUPT
extern void sdmmc_ack_interrupt(struct mmc_host *mmc);
void sif_platform_ack_interrupt(struct esp_pub *epub)
{
struct esp_sdio_ctrl *sctrl = NULL;
struct sdio_func *func = NULL;
ASSERT(epub != NULL);
sctrl = (struct esp_sdio_ctrl *)epub->sif;
func = sctrl->func;
ASSERT(func != NULL);
sdmmc_ack_interrupt(func->card->host);
}
#endif //ESP_ACK_INTERRUPT
late_initcall(esp_sdio_init);
//module_init(esp_sdio_init);
module_exit(esp_sdio_exit);

View File

@ -0,0 +1,453 @@
/*
* Copyright (c) 2010 - 2012 Espressif System.
*
* Common definitions of Serial Interconnctor Protocol
*
* little endian
*/
#ifndef _SIP2_COMMON_H
#define _SIP2_COMMON_H
#ifdef __ets__
#include "utils.h"
#endif /*__ets__*/
/* max 16 types */
typedef enum {
SIP_CTRL = 0,
SIP_DATA,
SIP_DATA_AMPDU,
} SIP_TYPE;
typedef enum {
SIP_TX_CTRL_BUF = 0, /* from host */
SIP_RX_CTRL_BUF, /* to host */
SIP_TX_DATA_BUF, /* from host */
SIP_RX_DATA_BUF /* to host */
} SIP_BUF_TYPE;
enum sip_cmd_id {
SIP_CMD_GET_VER = 0,
SIP_CMD_WRITE_MEMORY,//1 ROM code
SIP_CMD_READ_MEMORY,//2
SIP_CMD_WRITE_REG,//3 ROM code
SIP_CMD_READ_REG, //4
SIP_CMD_BOOTUP,//5 ROM code
SIP_CMD_COPYBACK,//6
SIP_CMD_INIT, //7
SIP_CMD_SCAN,//8
SIP_CMD_SETKEY,//9
SIP_CMD_CONFIG,//10
SIP_CMD_BSS_INFO_UPDATE,//11
SIP_CMD_LOOPBACK,//12 ROM code
//do not add cmd before this line
SIP_CMD_SET_WMM_PARAM,
SIP_CMD_AMPDU_ACTION,
SIP_CMD_HB_REQ, //15
SIP_CMD_RESET_MAC, //16
SIP_CMD_PRE_DOWN, //17
SIP_CMD_SLEEP, /* for sleep testing */
SIP_CMD_WAKEUP, /* for sleep testing */
SIP_CMD_DEBUG, /* for general testing */
SIP_CMD_GET_FW_VER, /* get fw rev. */
SIP_CMD_SETVIF,
SIP_CMD_SETSTA,
SIP_CMD_PS,
SIP_CMD_SUSPEND,
SIP_CMD_MAX
};
enum {
SIP_EVT_TARGET_ON = 0, //
SIP_EVT_BOOTUP,//1 in ROM code
SIP_EVT_COPYBACK,//2
SIP_EVT_SCAN_RESULT, //3
SIP_EVT_TX_STATUS,//4
SIP_EVT_CREDIT_RPT, //5, in ROM code
SIP_EVT_ERROR,//6
SIP_EVT_LOOPBACK,//7, in ROM code
SIP_EVT_SNPRINTF_TO_HOST, //8 in ROM code
//do not add evt before this line
SIP_EVT_HB_ACK, //9
SIP_EVT_RESET_MAC_ACK, //10
SIP_EVT_WAKEUP,//11 /* for sleep testing */
SIP_EVT_DEBUG,//12 /* for general testing */
SIP_EVT_PRINT_TO_HOST, //13
SIP_EVT_TRC_AMPDU, //14
SIP_EVT_ROC, //15
SIP_EVT_RESETTING,
SIP_EVT_SLEEP,
SIP_EVT_TXIDLE,
SIP_EVT_MAX
};
#define SIP_IFIDX_MASK 0xf0
#define SIP_IFIDX_S 4
#define SIP_TYPE_MASK 0x0f
#define SIP_TYPE_S 0
#define SIP_HDR_GET_IFIDX(fc0) (((fc0) & SIP_IFIDX_MASK) >> SIP_IFIDX_S)
#define SIP_HDR_SET_IFIDX(fc0, ifidx) ( (fc0) = ((fc0) & ~SIP_IFIDX_MASK) | ((ifidx) << SIP_IFIDX_S & SIP_IFIDX_MASK) )
#define SIP_HDR_GET_TYPE(fc0) ((fc0) & SIP_TYPE_MASK )
/* assume type field is cleared */
#define SIP_HDR_SET_TYPE(fc0, type) ((fc0) = ((fc0) & ~ SIP_TYPE_MASK) | ((type) & SIP_TYPE_MASK))
/* sip 2.0, not hybrid header so far */
#define SIP_HDR_IS_CTRL(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_CTRL)
#define SIP_HDR_IS_DATA(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA)
#define SIP_HDR_IS_AMPDU(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA_AMPDU)
/* fc[1] flags, only for data pkt. Ctrl pkts use fc[1] as eventID */
#define SIP_HDR_SET_FLAGS(hdr, flags) ((hdr)->fc[1] |= (flags))
#define SIP_HDR_F_MORE_PKT 0x1
#define SIP_HDR_F_NEED_CRDT_RPT 0x2
#define SIP_HDR_F_SYNC 0x4
#define SIP_HDR_F_SYNC_RESET 0x8
#define SIP_HDR_F_PM_TURNING_ON 0x10
#define SIP_HDR_F_PM_TURNING_OFF 0x20
#define SIP_HDR_NEED_CREDIT_UPDATE(hdr) ((hdr)->fc[1] & SIP_HDR_F_NEED_CRDT_RPT)
#define SIP_HDR_IS_MORE_PKT(hdr) ((hdr)->fc[1] & SIP_HDR_F_MORE_PKT)
#define SIP_HDR_IS_CRDT_RPT(hdr) ((hdr)->fc[1] & SIP_HDR_F_CRDT_RPT)
#define SIP_HDR_IS_SYNC(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC)
#define SIP_HDR_IS_SYNC_RESET(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC_RESET)
#define SIP_HDR_IS_SYNC_PKT(hdr) (SIP_HDR_IS_SYNC(hdr) | SIP_HDR_IS_SYNC_RESET(hdr))
#define SIP_HDR_SET_SYNC(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC)
#define SIP_HDR_SET_SYNC_RESET(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC_RESET)
#define SIP_HDR_SET_MORE_PKT(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_MORE_PKT)
#define SIP_HDR_SET_PM_TURNING_ON(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_ON)
#define SIP_HDR_IS_PM_TURNING_ON(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_ON)
#define SIP_HDR_SET_PM_TURNING_OFF(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_OFF)
#define SIP_HDR_IS_PM_TURNING_OFF(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_OFF)
/*
* fc[0]: first 4bit: ifidx; last 4bit: type
* fc[1]: flags
*
* Don't touch the header definitons
*/
struct sip_hdr_min {
u8 fc[2];
__le16 len;
} __packed;
/* not more than 4byte long */
struct sip_tx_data_info {
u8 tid;
u8 ac;
u8 p2p:1,
enc_flag:7;
u8 hw_kid;
} __packed;
/* NB: this structure should be not more than 4byte !! */
struct sip_tx_info {
union {
u32 cmdid;
struct sip_tx_data_info dinfo;
} u;
} __packed;
struct sip_hdr {
u8 fc[2]; //fc[0]: type and ifidx ; fc[1] is eventID if the first ctrl pkt in the chain. data pkt still can use fc[1] to set flag
__le16 len;
union {
volatile u32 recycled_credits; /* last 12bits is credits, first 20 bits is actual length of the first pkt in the chain */
struct sip_tx_info tx_info;
} u;
u32 seq;
} __packed;
#define h_credits u.recycled_credits
#define c_evtid fc[1]
#define c_cmdid u.tx_info.u.cmdid
#define d_ac u.tx_info.u.dinfo.ac
#define d_tid u.tx_info.u.dinfo.tid
#define d_p2p u.tx_info.u.dinfo.p2p
#define d_enc_flag u.tx_info.u.dinfo.enc_flag
#define d_hw_kid u.tx_info.u.dinfo.hw_kid
#define SIP_CREDITS_MASK 0xfff /* last 12 bits */
#ifdef HOST_RC
#define RC_CNT_MASK 0xf
struct sip_rc_status {
u32 rc_map;
union {
u32 rc_cnt1:4,
rc_cnt2:4,
rc_cnt3:4,
rc_cnt4:4,
rc_cnt5:4;
u32 rc_cnt_store;
};
};
/* copy from mac80211.h */
struct sip_tx_rc {
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
s8 rts_cts_rate_idx;
};
#endif /* HOST_RC */
#define SIP_HDR_MIN_LEN 4
#define SIP_HDR_LEN sizeof(struct sip_hdr)
#define SIP_CTRL_HDR_LEN SIP_HDR_LEN /* same as sip_hdr in sip2 design */
#define SIP_BOOT_BUF_SIZE 256
#define SIP_CTRL_BUF_SZ 256 /* too much?? */
#define SIP_CTRL_BUF_N 6
#define SIP_CTRL_TXBUF_N 2
#define SIP_CTRL_RXBUF_N 4
/* WAR for mblk */
#define SIP_RX_ADDR_PREFIX_MASK 0xfc000000
#define SIP_RX_ADDR_SHIFT 6 /* [31:5], shift 6 bits*/
struct sip_cmd_write_memory {
u32 addr;
u32 len;
} __packed;
struct sip_cmd_read_memory {
u32 addr;
u32 len;
} __packed;
struct sip_cmd_write_reg {
u32 addr;
u32 val;
} __packed;
struct sip_cmd_bootup {
u32 boot_addr;
} __packed;
struct sip_cmd_loopback {
u32 txlen; //host to target packet len, 0 means no txpacket
u32 rxlen; //target to host packet len, 0 means no rxpacket
u32 pack_id; //sequence of packet
} __packed;
struct sip_evt_loopback {
u32 txlen; //host to target packet len, 0 means no txpacket
u32 rxlen; //target to host packet len, 0 means no rxpacket
u32 pack_id; //sequence of packet
} __packed;
struct sip_cmd_copyback {
u32 addr;
u32 len;
} __packed;
struct sip_cmd_scan {
// u8 ssid[32];
u8 ssid_len;
// u8 hw_channel[14];
u8 n_channels;
u8 ie_len;
u8 aborted;
} __packed; // ie[] append at the end
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif /* ETH_ALEN */
struct sip_cmd_setkey {
u8 bssid_no;
u8 addr[ETH_ALEN];
u8 alg;
u8 keyidx;
u8 hw_key_idx;
u8 flags;
u8 keylen;
u8 key[32];
} __packed;
struct sip_cmd_config {
u16 center_freq;
u16 duration;
} __packed;
struct sip_cmd_bss_info_update {
u8 bssid[ETH_ALEN];
u16 isassoc;
u32 beacon_int;
u8 bssid_no;
} __packed;
struct sip_evt_bootup {
u16 tx_blksz;
u8 mac_addr[ETH_ALEN];
/* anything else ? */
} __packed;
struct sip_cmd_setvif {
u8 index;
u8 mac[ETH_ALEN];
u8 set;
u8 op_mode;
u8 is_p2p;
} __packed;
enum esp_ieee80211_phytype{
ESP_IEEE80211_T_CCK = 0,
ESP_IEEE80211_T_OFDM = 1,
ESP_IEEE80211_T_HT20_L = 2,
ESP_IEEE80211_T_HT20_S = 3,
};
struct sip_cmd_setsta {
u8 ifidx;
u8 index;
u8 set;
u8 phymode;
u8 mac[ETH_ALEN];
u16 aid;
u8 ampdu_factor;
u8 ampdu_density;
u16 resv;
} __packed;
struct sip_cmd_ps {
u8 dtim_period;
u8 max_sleep_period;
u8 on;
u8 resv;
} __packed;
struct sip_cmd_suspend {
u8 suspend;
u8 resv[3];
} __packed;
#define SIP_DUMP_RPBM_ERR BIT(0)
#define SIP_RXABORT_FIXED BIT(1)
#define SIP_SUPPORT_BGSCAN BIT(2)
struct sip_evt_bootup2 {
u16 tx_blksz;
u8 mac_addr[ETH_ALEN];
u16 rx_blksz;
u8 credit_to_reserve;
u8 options;
s16 noise_floor;
u8 resv[2];
/* anything else ? */
} __packed;
typedef enum {
TRC_TX_AMPDU_STOPPED = 1,
TRC_TX_AMPDU_OPERATIONAL,
TRC_TX_AMPDU_WAIT_STOP,
TRC_TX_AMPDU_WAIT_OPERATIONAL,
TRC_TX_AMPDU_START,
} trc_ampdu_state_t;
struct sip_evt_trc_ampdu {
u8 state;
u8 tid;
u8 addr[ETH_ALEN];
} __packed;
struct sip_cmd_set_wmm_params {
u8 aci;
u8 aifs;
u8 ecw_min;
u8 ecw_max;
u16 txop_us;
} __packed;
#define SIP_AMPDU_RX_START 0
#define SIP_AMPDU_RX_STOP 1
#define SIP_AMPDU_TX_OPERATIONAL 2
#define SIP_AMPDU_TX_STOP 3
struct sip_cmd_ampdu_action {
u8 action;
u8 index;
u8 tid;
u8 win_size;
u16 ssn;
u8 addr[ETH_ALEN];
} __packed;
#define SIP_TX_ST_OK 0
#define SIP_TX_ST_NOEB 1
#define SIP_TX_ST_ACKTO 2
#define SIP_TX_ST_ENCERR 3
//NB: sip_tx_status must be 4 bytes aligned
struct sip_tx_status {
u32 sip_seq;
#ifdef HOST_RC
struct sip_rc_status rcstatus;
#endif /* HOST_RC */
u8 errno; /* success or failure code */
u8 rate_index;
char ack_signal;
u8 pad;
} __packed;
struct sip_evt_tx_report {
u32 pkts;
struct sip_tx_status status[0];
} __packed;
struct sip_evt_tx_mblk {
u32 mblk_map;
} __packed;
struct sip_evt_scan_report {
u16 scan_id;
u16 aborted;
} __packed;
struct sip_evt_roc {
u16 state; //start:1, end :0
u16 is_ok;
} __packed;
struct sip_evt_txidle {
u32 last_seq;
} __packed;
/*
* for mblk direct memory access, no need for sip_hdr. tx: first 2k for contrl msg,
* rest of 14k for data. rx, same.
*/
#ifdef TEST_MODE
struct sip_cmd_sleep {
u32 sleep_mode;
u32 sleep_tm_ms;
u32 wakeup_tm_ms; //zero: after receive bcn, then sleep, nozero: delay nozero ms to sleep
u32 sleep_times; //zero: always sleep, nozero: after nozero number sleep/wakeup, then end up sleep
} __packed;
struct sip_cmd_wakeup {
u32 check_data; //0:copy to event
} __packed;
struct sip_evt_wakeup {
u32 check_data;
} __packed;
//general debug command
struct sip_cmd_debug {
u32 cmd_type;
u32 para_num;
u32 para[10];
} __packed;
struct sip_evt_debug {
u16 len;
u32 results[8];
u16 pad;
} __packed;
#endif //ifdef TEST_MODE
#endif /* _SIP_COMMON_H_ */

View File

@ -0,0 +1,242 @@
//Generated at 2012-10-23 20:11:08
/*
* Copyright (c) 2011 Espressif System
*
*/
#ifndef SLC_HOST_REGISTER_H_INCLUDED
#define SLC_HOST_REGISTER_H_INCLUDED
/* #define REG_SLC_HOST_BASE 0x00000000 */
/* skip the token1, since reading it will clean the credit */
#define REG_SLC_HOST_BASE 0x00000000
#define SLC_HOST_PF (REG_SLC_HOST_BASE + 0x0)
#define SLC_HOST_TOKEN_RDATA (REG_SLC_HOST_BASE + 0x4)
#define SLC_HOST_RX_PF_EOF 0x0000000F
#define SLC_HOST_RX_PF_EOF_S 28
#define SLC_HOST_TOKEN1 0x00000FFF
#define SLC_HOST_TOKEN1_S 16
#define SLC_HOST_RX_PF_VALID (BIT(15))
#define SLC_HOST_TOKEN0 0x00000FFF
#define SLC_HOST_TOKEN0_S 0
#define SLC_HOST_TOKEN0_MASK SLC_HOST_TOKEN0
#define SLC_HOST_INT_RAW (REG_SLC_HOST_BASE + 0x8)
#define SLC_HOST_EXT_BIT3_INT_RAW (BIT(22))
#define SLC_HOST_EXT_BIT2_INT_RAW (BIT(21))
#define SLC_HOST_EXT_BIT1_INT_RAW (BIT(20))
#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_RAW (BIT(19))
#define SLC_HOST_RX_PF_VALID_INT_RAW (BIT(18))
#define SLC_HOST_TX_OVF_INT_RAW (BIT(17))
#define SLC_HOST_RX_UDF_INT_RAW (BIT(16))
#define SLC_HOST_TX_START_INT_RAW (BIT(15))
#define SLC_HOST_RX_START_INT_RAW (BIT(14))
#define SLC_HOST_RX_EOF_INT_RAW (BIT(13))
#define SLC_HOST_RX_SOF_INT_RAW (BIT(12))
#define SLC_HOST_TOKEN1_0TO1_INT_RAW (BIT(11))
#define SLC_HOST_TOKEN0_0TO1_INT_RAW (BIT(10))
#define SLC_HOST_TOKEN1_1TO0_INT_RAW (BIT(9))
#define SLC_HOST_TOKEN0_1TO0_INT_RAW (BIT(8))
#define SLC_HOST_TOHOST_BIT7_INT_RAW (BIT(7))
#define SLC_HOST_TOHOST_BIT6_INT_RAW (BIT(6))
#define SLC_HOST_TOHOST_BIT5_INT_RAW (BIT(5))
#define SLC_HOST_TOHOST_BIT4_INT_RAW (BIT(4))
#define SLC_HOST_TOHOST_BIT3_INT_RAW (BIT(3))
#define SLC_HOST_TOHOST_BIT2_INT_RAW (BIT(2))
#define SLC_HOST_TOHOST_BIT1_INT_RAW (BIT(1))
#define SLC_HOST_TOHOST_BIT0_INT_RAW (BIT(0))
#define SLC_HOST_STATE_W0 (REG_SLC_HOST_BASE + 0xC)
#define SLC_HOST_STATE3 0x000000FF
#define SLC_HOST_STATE3_S 24
#define SLC_HOST_STATE2 0x000000FF
#define SLC_HOST_STATE2_S 16
#define SLC_HOST_STATE1 0x000000FF
#define SLC_HOST_STATE1_S 8
#define SLC_HOST_STATE0 0x000000FF
#define SLC_HOST_STATE0_S 0
#define SLC_HOST_STATE_W1 (REG_SLC_HOST_BASE + 0x10)
#define SLC_HOST_STATE7 0x000000FF
#define SLC_HOST_STATE7_S 24
#define SLC_HOST_STATE6 0x000000FF
#define SLC_HOST_STATE6_S 16
#define SLC_HOST_STATE5 0x000000FF
#define SLC_HOST_STATE5_S 8
#define SLC_HOST_STATE4 0x000000FF
#define SLC_HOST_STATE4_S 0
#define SLC_HOST_CONF_W0 (REG_SLC_HOST_BASE + 0x14)
#define SLC_HOST_CONF3 0x000000FF
#define SLC_HOST_CONF3_S 24
#define SLC_HOST_CONF2 0x000000FF
#define SLC_HOST_CONF2_S 16
#define SLC_HOST_CONF1 0x000000FF
#define SLC_HOST_CONF1_S 8
#define SLC_HOST_CONF0 0x000000FF
#define SLC_HOST_CONF0_S 0
#define SLC_HOST_CONF_W1 (REG_SLC_HOST_BASE + 0x18)
#define SLC_HOST_CONF7 0x000000FF
#define SLC_HOST_CONF7_S 24
#define SLC_HOST_CONF6 0x000000FF
#define SLC_HOST_CONF6_S 16
#define SLC_HOST_CONF5 0x000000FF
#define SLC_HOST_CONF5_S 8
#define SLC_HOST_CONF4 0x000000FF
#define SLC_HOST_CONF4_S 0
#define SLC_HOST_INT_ST (REG_SLC_HOST_BASE + 0x1C)
#define SLC_HOST_RX_ST (BIT(23))
#define SLC_HOST_EXT_BIT3_INT_ST (BIT(22))
#define SLC_HOST_EXT_BIT2_INT_ST (BIT(21))
#define SLC_HOST_EXT_BIT1_INT_ST (BIT(20))
#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_ST (BIT(19))
#define SLC_HOST_RX_PF_VALID_INT_ST (BIT(18))
#define SLC_HOST_TX_OVF_INT_ST (BIT(17))
#define SLC_HOST_RX_UDF_INT_ST (BIT(16))
#define SLC_HOST_TX_START_INT_ST (BIT(15))
#define SLC_HOST_RX_START_INT_ST (BIT(14))
#define SLC_HOST_RX_EOF_INT_ST (BIT(13))
#define SLC_HOST_RX_SOF_INT_ST (BIT(12))
#define SLC_HOST_TOKEN1_0TO1_INT_ST (BIT(11))
#define SLC_HOST_TOKEN0_0TO1_INT_ST (BIT(10))
#define SLC_HOST_TOKEN1_1TO0_INT_ST (BIT(9))
#define SLC_HOST_TOKEN0_1TO0_INT_ST (BIT(8))
#define SLC_HOST_TOHOST_BIT7_INT_ST (BIT(7))
#define SLC_HOST_TOHOST_BIT6_INT_ST (BIT(6))
#define SLC_HOST_TOHOST_BIT5_INT_ST (BIT(5))
#define SLC_HOST_TOHOST_BIT4_INT_ST (BIT(4))
#define SLC_HOST_TOHOST_BIT3_INT_ST (BIT(3))
#define SLC_HOST_TOHOST_BIT2_INT_ST (BIT(2))
#define SLC_HOST_TOHOST_BIT1_INT_ST (BIT(1))
#define SLC_HOST_TOHOST_BIT0_INT_ST (BIT(0))
#define SLC_HOST_CONF_W2 (REG_SLC_HOST_BASE + 0x20)
#define SLC_HOST_CONF11 0x000000FF
#define SLC_HOST_CONF11_S 24
#define SLC_HOST_CONF10 0x000000FF
#define SLC_HOST_CONF10_S 16
#define SLC_HOST_CONF9 0x000000FF
#define SLC_HOST_CONF9_S 8
#define SLC_HOST_CONF8 0x000000FF
#define SLC_HOST_CONF8_S 0
#define SLC_HOST_CONF_W3 (REG_SLC_HOST_BASE + 0x24)
#define SLC_HOST_CONF15 0x000000FF
#define SLC_HOST_CONF15_S 24
#define SLC_HOST_CONF14 0x000000FF
#define SLC_HOST_CONF14_S 16
#define SLC_HOST_CONF13 0x000000FF
#define SLC_HOST_CONF13_S 8
#define SLC_HOST_CONF12 0x000000FF
#define SLC_HOST_CONF12_S 0
#define SLC_HOST_GEN_TXDONE_INT BIT(16)
#define SLC_HOST_GEN_RXDONE_INT BIT(17)
#define SLC_HOST_CONF_W4 (REG_SLC_HOST_BASE + 0x28)
#define SLC_HOST_CONF19 0x000000FF
#define SLC_HOST_CONF19_S 24
#define SLC_HOST_CONF18 0x000000FF
#define SLC_HOST_CONF18_S 16
#define SLC_HOST_CONF17 0x000000FF
#define SLC_HOST_CONF17_S 8
#define SLC_HOST_CONF16 0x000000FF
#define SLC_HOST_CONF16_S 0
#define SLC_HOST_TOKEN_WDATA (REG_SLC_HOST_BASE + 0x2C)
#define SLC_HOST_TOKEN1_WD 0x00000FFF
#define SLC_HOST_TOKEN1_WD_S 16
#define SLC_HOST_TOKEN0_WD 0x00000FFF
#define SLC_HOST_TOKEN0_WD_S 0
#define SLC_HOST_INT_CLR (REG_SLC_HOST_BASE + 0x30)
#define SLC_HOST_TOKEN1_WR (BIT(31))
#define SLC_HOST_TOKEN0_WR (BIT(30))
#define SLC_HOST_TOKEN1_DEC (BIT(29))
#define SLC_HOST_TOKEN0_DEC (BIT(28))
#define SLC_HOST_EXT_BIT3_INT_CLR (BIT(22))
#define SLC_HOST_EXT_BIT2_INT_CLR (BIT(21))
#define SLC_HOST_EXT_BIT1_INT_CLR (BIT(20))
#define SLC_HOST_EXT_BIT0_INT_CLR (BIT(19))
#define SLC_HOST_RX_PF_VALID_INT_CLR (BIT(18))
#define SLC_HOST_TX_OVF_INT_CLR (BIT(17))
#define SLC_HOST_RX_UDF_INT_CLR (BIT(16))
#define SLC_HOST_TX_START_INT_CLR (BIT(15))
#define SLC_HOST_RX_START_INT_CLR (BIT(14))
#define SLC_HOST_RX_EOF_INT_CLR (BIT(13))
#define SLC_HOST_RX_SOF_INT_CLR (BIT(12))
#define SLC_HOST_TOKEN1_0TO1_INT_CLR (BIT(11))
#define SLC_HOST_TOKEN0_0TO1_INT_CLR (BIT(10))
#define SLC_HOST_TOKEN1_1TO0_INT_CLR (BIT(9))
#define SLC_HOST_TOKEN0_1TO0_INT_CLR (BIT(8))
#define SLC_HOST_TOHOST_BIT7_INT_CLR (BIT(7))
#define SLC_HOST_TOHOST_BIT6_INT_CLR (BIT(6))
#define SLC_HOST_TOHOST_BIT5_INT_CLR (BIT(5))
#define SLC_HOST_TOHOST_BIT4_INT_CLR (BIT(4))
#define SLC_HOST_TOHOST_BIT3_INT_CLR (BIT(3))
#define SLC_HOST_TOHOST_BIT2_INT_CLR (BIT(2))
#define SLC_HOST_TOHOST_BIT1_INT_CLR (BIT(1))
#define SLC_HOST_TOHOST_BIT0_INT_CLR (BIT(0))
#define SLC_HOST_INT_ENA (REG_SLC_HOST_BASE + 0x34)
#define SLC_HOST_EXT_BIT3_INT_ENA (BIT(22))
#define SLC_HOST_EXT_BIT2_INT_ENA (BIT(21))
#define SLC_HOST_EXT_BIT1_INT_ENA (BIT(20))
#define SLC_HOST_EXT_BIT0_INT_ENA (BIT(19))
#define SLC_HOST_RX_PF_VALID_INT_ENA (BIT(18))
#define SLC_HOST_TX_OVF_INT_ENA (BIT(17))
#define SLC_HOST_RX_UDF_INT_ENA (BIT(16))
#define SLC_HOST_TX_START_INT_ENA (BIT(15))
#define SLC_HOST_RX_START_INT_ENA (BIT(14))
#define SLC_HOST_RX_EOF_INT_ENA (BIT(13))
#define SLC_HOST_RX_SOF_INT_ENA (BIT(12))
#define SLC_HOST_TOKEN1_0TO1_INT_ENA (BIT(11))
#define SLC_HOST_TOKEN0_0TO1_INT_ENA (BIT(10))
#define SLC_HOST_TOKEN1_1TO0_INT_ENA (BIT(9))
#define SLC_HOST_TOKEN0_1TO0_INT_ENA (BIT(8))
#define SLC_HOST_TOHOST_BIT7_INT_ENA (BIT(7))
#define SLC_HOST_TOHOST_BIT6_INT_ENA (BIT(6))
#define SLC_HOST_TOHOST_BIT5_INT_ENA (BIT(5))
#define SLC_HOST_TOHOST_BIT4_INT_ENA (BIT(4))
#define SLC_HOST_TOHOST_BIT3_INT_ENA (BIT(3))
#define SLC_HOST_TOHOST_BIT2_INT_ENA (BIT(2))
#define SLC_HOST_TOHOST_BIT1_INT_ENA (BIT(1))
#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT(0))
#define SLC_HOST_CONF_W5 (REG_SLC_HOST_BASE + 0x3C)
#define SLC_HOST_CONF23 0x000000FF
#define SLC_HOST_CONF23_S 24
#define SLC_HOST_CONF22 0x000000FF
#define SLC_HOST_CONF22_S 16
#define SLC_HOST_CONF21 0x000000FF
#define SLC_HOST_CONF21_S 8
#define SLC_HOST_CONF20 0x000000FF
#define SLC_HOST_CONF20_S 0
#define SLC_HOST_DATE (REG_SLC_HOST_BASE + 0x78)
#define SLC_HOST_ID (REG_SLC_HOST_BASE + 0x7C)
#define SLC_ADDR_WINDOW_CLEAR_MASK (~(0xf<<12))
#define SLC_FROM_HOST_ADDR_WINDOW (0x1<<12)
#define SLC_TO_HOST_ADDR_WINDOW (0x3<<12)
#define SLC_SET_FROM_HOST_ADDR_WINDOW(v) do { \
(v) &= 0xffff; \
(v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \
(v) |= SLC_FROM_HOST_ADDR_WINDOW; \
} while (0);
#define SLC_SET_TO_HOST_ADDR_WINDOW(v) do { \
(v) &= 0xffff; \
(v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \
(v) |= SLC_TO_HOST_ADDR_WINDOW; \
} while (0);
#endif // SLC_HOST_REGISTER_H_INCLUDED

View File

@ -0,0 +1,561 @@
/*
* Copyright (c) 2011 Espressif System.
*
* MAC80211 support module
*/
#ifdef TEST_MODE
#include <linux/etherdevice.h>
#include <linux/workqueue.h>
#include <linux/nl80211.h>
#include <linux/ieee80211.h>
#include <linux/slab.h>
#include <net/regulatory.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <net/genetlink.h>
#include "esp_pub.h"
#include "esp_sip.h"
#include "esp_ctrl.h"
#include "esp_sif.h"
#include "esp_debug.h"
#include "esp_wl.h"
#include "testmode.h"
static u32 connected_nl;
static struct genl_info info_copy;
static struct esp_sip *sip_copy;
static u8 *sdio_buff;
#define SIP sip_copy
#define OUT_DONE() \
do { \
printk(KERN_DEBUG "esp_sdio: error occured in %s\n", __func__); \
} while(0)
/* ESP TEST netlinf family */
static struct genl_family test_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = "esp_sdio",
.version = 1,
.maxattr = TEST_ATTR_MAX,
};
struct loopback_param_s {
u32 packet_num;
u32 packet_id;
};
static struct loopback_param_s loopback_param;
u32 get_loopback_num()
{
return loopback_param.packet_num;
}
u32 get_loopback_id()
{
return loopback_param.packet_id;
}
void inc_loopback_id()
{
loopback_param.packet_id++;
}
#define REGISTER_REPLY(info) \
memcpy((char *)&info_copy, (char *)(info), sizeof(struct genl_info))
static void sip_send_test_cmd(struct esp_sip *sip, struct sk_buff *skb)
{
skb_queue_tail(&sip->epub->txq, skb);
#ifdef FPGA_LOOPBACK
queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
#else
ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work);
#endif /* FPGA_LOOPBACK */
}
static int esp_test_cmd_reply(struct genl_info *info, u32 cmd_type, char *reply_info)
{
struct sk_buff *skb;
void *hdr;
/*directly send ask_info to target, and waiting for report*/
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (skb == NULL)
goto out;
hdr = genlmsg_put(skb, info->snd_pid, info->snd_seq, &test_genl_family, 0, cmd_type);
if (hdr == NULL)
goto nla_put_failure;
NLA_PUT_STRING(skb, TEST_ATTR_STR, reply_info);
genlmsg_end(skb, hdr);
genlmsg_reply(skb, info);
return 0;
nla_put_failure:
nlmsg_free(skb);
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_echo(struct sk_buff *skb_2,
struct genl_info *info)
{
char *echo_info;
int res;
if (info == NULL)
goto out;
connected_nl = info->snd_pid;
printk(KERN_DEBUG "esp_sdio: received a echo, "
"from pid %d\n", info->snd_pid);
sip_debug_show(SIP);
/*get echo info*/
echo_info = nla_data(info->attrs[TEST_ATTR_STR]);
res=esp_test_cmd_reply(info, TEST_CMD_ECHO, echo_info);
return res;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_sdiospeed(struct sk_buff *skb_2,
struct genl_info *info)
{
char *speed_info;
int res;
if (info == NULL)
goto out;
connected_nl = info->snd_pid;
/*get echo info*/
speed_info = nla_data(info->attrs[TEST_ATTR_STR]);
printk(KERN_DEBUG "esp_sdio: received a sdio speed %s, "
"from pid %d\n", speed_info, info->snd_pid);
if (!strcmp(speed_info, "high")) {
sif_platform_target_speed(1);
} else if (!strcmp(speed_info, "low")) {
sif_platform_target_speed(0);
} else {
printk(KERN_DEBUG "%s: %s unsupported\n", __func__, speed_info);
}
res=esp_test_cmd_reply(info, TEST_CMD_SDIOSPEED, speed_info);
return res;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_ask(struct sk_buff *skb_2,
struct genl_info *info)
{
char *ask_info;
int res;
if (info == NULL)
goto out;
/*get echo info*/
ask_info = nla_data(info->attrs[TEST_ATTR_STR]);
/*directly send ask_info to target, and waiting for report*/
res=esp_test_cmd_reply(info, TEST_CMD_ASK, "ok");
return res;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_sleep(struct sk_buff *skb_2,
struct genl_info *info)
{
struct sip_cmd_sleep *sleepcmd;
struct sk_buff *skb = NULL;
int res;
if (info == NULL)
goto out;
skb = sip_alloc_ctrl_skbuf(SIP, sizeof(struct sip_cmd_sleep), SIP_CMD_SLEEP);
if (!skb)
goto out;
sleepcmd = (struct sip_cmd_sleep *)(skb->data + sizeof(struct sip_tx_info));
sleepcmd->sleep_mode = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
sleepcmd->sleep_tm_ms = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
sleepcmd->wakeup_tm_ms = nla_get_u32(info->attrs[TEST_ATTR_PARA2]);
sleepcmd->sleep_times = nla_get_u32(info->attrs[TEST_ATTR_PARA3]);
sip_send_test_cmd(SIP, skb);
/*directly send ask_info to target, and waiting for report*/
res=esp_test_cmd_reply(info, TEST_CMD_SLEEP, "ok");
return res;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_wakeup(struct sk_buff *skb_2,
struct genl_info *info)
{
struct sip_cmd_wakeup *wakeupcmd;
struct sk_buff *skb = NULL;
//int res;
if (info == NULL)
goto out;
skb = sip_alloc_ctrl_skbuf(SIP, sizeof(struct sip_cmd_wakeup), SIP_CMD_WAKEUP);
if (!skb)
goto out;
wakeupcmd = (struct sip_cmd_wakeup *)(skb->data + sizeof(struct sip_tx_info));
wakeupcmd->check_data = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
/*directly send reply_info to target, and waiting for report*/
REGISTER_REPLY(info);
//res=esp_test_cmd_reply(info, TEST_CMD_WAKEUP, "ok");
sip_send_test_cmd(SIP, skb);
return 0;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_loopback(struct sk_buff *skb_2,
struct genl_info *info)
{
u32 txpacket_len;
u32 rxpacket_len;
if (info == NULL)
goto out;
txpacket_len = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
rxpacket_len = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
loopback_param.packet_num = nla_get_u32(info->attrs[TEST_ATTR_PARA2]);
loopback_param.packet_id=0;
REGISTER_REPLY(info);
return sip_send_loopback_mblk(SIP, txpacket_len, rxpacket_len, 0);
out:
OUT_DONE();
return -EINVAL;
}
/*
u8 probe_req_frm[] = {0x40,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0x8F,0x11,0x22,0x88,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x01,0x08,0x82,0x84,0x8B,0x96,
0x0C,0x12,0x18,0x24,0x32,0x04,0x30,0x48,0x60,0x6C
};
*/
static int sip_send_tx_frame(struct esp_sip *sip, u32 packet_len)
{
struct sk_buff *skb = NULL;
u8 *ptr = NULL;
int i;
skb = alloc_skb(packet_len, GFP_KERNEL);
skb->len = packet_len;
ptr = skb->data;
/* fill up pkt payload */
for (i = 0; i < skb->len; i++) {
ptr[i] = i;
}
#ifdef FPGA_LOOPBACK
skb_queue_tail(&sip->epub->txq, skb);
queue_work(sip->epub->esp_wkq, &sip->epub->tx_work);
#else
sip_tx_data_pkt_enqueue(sip->epub, skb);
ieee80211_queue_work(sip->epub->hw, &sip->epub->tx_work);
#endif
return 0;
}
static int esp_test_tx(struct sk_buff *skb_2,
struct genl_info *info)
{
u32 txpacket_len;
u32 res;
if (info == NULL)
goto out;
txpacket_len = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
REGISTER_REPLY(info);
sip_send_tx_frame(SIP, txpacket_len);
res=esp_test_cmd_reply(info, TEST_CMD_TX, "tx out");
return res;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_genl(struct sk_buff *skb_2,
struct genl_info *info)
{
struct sip_cmd_debug *dbgcmd;
struct sk_buff *skb = NULL;
int i;
if (info == NULL)
goto out;
skb = sip_alloc_ctrl_skbuf(SIP, sizeof(struct sip_cmd_debug), SIP_CMD_DEBUG);
if (!skb)
goto out;
dbgcmd = (struct sip_cmd_debug *)(skb->data + sizeof(struct sip_hdr));
dbgcmd->cmd_type = nla_get_u32(info->attrs[TEST_ATTR_CMD_TYPE]);
dbgcmd->para_num = nla_get_u32(info->attrs[TEST_ATTR_PARA_NUM]);
printk(KERN_DEBUG "%s dbgcmdType %d paraNum %d\n", __func__, dbgcmd->cmd_type, dbgcmd->para_num);
for (i=0; i<dbgcmd->para_num; i++)
dbgcmd->para[i] = nla_get_u32(info->attrs[TEST_ATTR_PARA(i)]);
/*directly send reply_info to target, and waiting for report*/
REGISTER_REPLY(info);
sip_send_test_cmd(SIP, skb);
return 0;
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_sdio_wr(struct sk_buff *skb_2,
struct genl_info *info)
{
int res;
u32 func_no, addr, value;
if (info == NULL)
goto out;
func_no = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
addr = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
value = nla_get_u32(info->attrs[TEST_ATTR_PARA2]);
if(!func_no) {
sdio_io_writeb( SIP->epub, (u8) value&0xff, addr, &res);
} else {
memcpy(sdio_buff, (u8 *)&value, 4);
res=sif_io_sync(SIP->epub, addr, sdio_buff, 4, SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
}
/*directly send reply_info to target, and waiting for report*/
REGISTER_REPLY(info);
if (!res)
esp_test_cmd_reply(info, TEST_CMD_SDIO_WR, "write ok!");
else
esp_test_cmd_reply(info, TEST_CMD_SDIO_WR, "write fail!");
out:
OUT_DONE();
return -EINVAL;
}
static int esp_test_sdio_rd(struct sk_buff *skb_2,
struct genl_info *info)
{
int res;
u32 func_no, addr, value;
char value_str[12];
if (info == NULL)
goto out;
func_no = nla_get_u32(info->attrs[TEST_ATTR_PARA0]);
addr = nla_get_u32(info->attrs[TEST_ATTR_PARA1]);
if(!func_no) {
memset(sdio_buff, 0, 4);
sdio_buff[0]= sdio_io_readb(SIP->epub, addr, &res);
} else {
res=sif_io_sync(SIP->epub, addr, sdio_buff, 4, SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
}
memcpy((u8 *)&value, sdio_buff, 4);
/*directly send reply_info to target, and waiting for report*/
REGISTER_REPLY(info);
if (!res) {
sprintf((char *)&value_str, "0x%x", value);
esp_test_cmd_reply(info, TEST_CMD_SDIO_RD, value_str);
} else
esp_test_cmd_reply(info, TEST_CMD_SDIO_RD, "read fail!");
out:
OUT_DONE();
return -EINVAL;
}
/* TEST_CMD netlink policy */
static struct nla_policy test_genl_policy[TEST_ATTR_MAX + 1] = {
[TEST_ATTR_CMD_NAME]= { .type = NLA_NUL_STRING, .len = GENL_NAMSIZ - 1 },
[TEST_ATTR_CMD_TYPE] = { .type = NLA_U32 },
[TEST_ATTR_PARA_NUM] = { .type = NLA_U32 },
[TEST_ATTR_PARA0] = { .type = NLA_U32 },
[TEST_ATTR_PARA1] = { .type = NLA_U32 },
[TEST_ATTR_PARA2] = { .type = NLA_U32 },
[TEST_ATTR_PARA3] = { .type = NLA_U32 },
[TEST_ATTR_PARA4] = { .type = NLA_U32 },
[TEST_ATTR_PARA5] = { .type = NLA_U32 },
[TEST_ATTR_PARA6] = { .type = NLA_U32 },
[TEST_ATTR_PARA7] = { .type = NLA_U32 },
[TEST_ATTR_STR] = { .type = NLA_NUL_STRING, .len = 256-1 },
};
/* Generic Netlink operations array */
static struct genl_ops esp_test_ops[] = {
{
.cmd = TEST_CMD_ECHO,
.policy = test_genl_policy,
.doit = esp_test_echo,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_ASK,
.policy = test_genl_policy,
.doit = esp_test_ask,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_SLEEP,
.policy = test_genl_policy,
.doit = esp_test_sleep,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_WAKEUP,
.policy = test_genl_policy,
.doit = esp_test_wakeup,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_LOOPBACK,
.policy = test_genl_policy,
.doit = esp_test_loopback,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_TX,
.policy = test_genl_policy,
.doit = esp_test_tx,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_DEBUG,
.policy = test_genl_policy,
.doit = esp_test_genl,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_SDIO_WR,
.policy = test_genl_policy,
.doit = esp_test_sdio_wr,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_SDIO_RD,
.policy = test_genl_policy,
.doit = esp_test_sdio_rd,
.flags = GENL_ADMIN_PERM,
},
{
.cmd = TEST_CMD_SDIOSPEED,
.policy = test_genl_policy,
.doit = esp_test_sdiospeed,
.flags = GENL_ADMIN_PERM,
},
};
static int esp_test_netlink_notify(struct notifier_block *nb,
unsigned long state,
void *_notify)
{
struct netlink_notify *notify = _notify;
if (state != NETLINK_URELEASE)
return NOTIFY_DONE;
if (notify->pid == connected_nl) {
printk(KERN_INFO "esp_sdio: user released netlink"
" socket \n");
connected_nl = 0;
}
return NOTIFY_DONE;
}
static struct notifier_block test_netlink_notifier = {
.notifier_call = esp_test_netlink_notify,
};
int test_init_netlink(struct esp_sip *sip)
{
int rc;
printk(KERN_INFO "esp_sdio: initializing netlink\n");
sip_copy=sip;
/* temp buffer for sdio test */
sdio_buff = kzalloc(8, GFP_KERNEL);
rc = genl_register_family_with_ops(&test_genl_family,
esp_test_ops, ARRAY_SIZE(esp_test_ops));
if (rc)
goto failure;
rc = netlink_register_notifier(&test_netlink_notifier);
if (rc)
goto failure;
return 0;
failure:
printk(KERN_DEBUG "esp_sdio: error occured in %s\n", __func__);
kfree(sdio_buff);
return -EINVAL;
}
void test_exit_netlink(void)
{
int ret;
if (sdio_buff == NULL)
return;
kfree(sdio_buff);
printk(KERN_INFO "esp_sdio: closing netlink\n");
/* unregister the notifier */
netlink_unregister_notifier(&test_netlink_notifier);
/* unregister the family */
ret = genl_unregister_family(&test_genl_family);
if (ret)
printk(KERN_DEBUG "esp_sdio: "
"unregister family %i\n", ret);
}
void esp_test_cmd_event(u32 cmd_type, char *reply_info)
{
esp_test_cmd_reply(&info_copy, cmd_type, reply_info);
}
#endif //ifdef TEST_MODE

View File

@ -0,0 +1,46 @@
#ifndef __TEST_MODE
#define __TEST_MODE
enum {
TEST_CMD_UNSPEC,
TEST_CMD_ECHO,
TEST_CMD_ASK,
TEST_CMD_SLEEP,
TEST_CMD_WAKEUP,
TEST_CMD_LOOPBACK,
TEST_CMD_TX,
TEST_CMD_RX,
TEST_CMD_DEBUG,
TEST_CMD_SDIO_WR,
TEST_CMD_SDIO_RD,
TEST_CMD_SDIOSPEED,
__TEST_CMD_MAX,
};
#define TEST_CMD_MAX (__TEST_CMD_MAX - 1)
enum {
TEST_ATTR_UNSPEC,
TEST_ATTR_CMD_NAME,
TEST_ATTR_CMD_TYPE,
TEST_ATTR_PARA_NUM,
TEST_ATTR_PARA0,
TEST_ATTR_PARA1,
TEST_ATTR_PARA2,
TEST_ATTR_PARA3,
TEST_ATTR_PARA4,
TEST_ATTR_PARA5,
TEST_ATTR_PARA6,
TEST_ATTR_PARA7,
TEST_ATTR_STR,
__TEST_ATTR_MAX,
};
#define TEST_ATTR_MAX (__TEST_ATTR_MAX - 1)
#define TEST_ATTR_PARA(i) (TEST_ATTR_PARA0+(i))
u32 get_loopback_num(void);
u32 get_loopback_id(void);
void inc_loopback_id(void);
#endif