summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/eagle/esp_ctrl.c
diff options
context:
space:
mode:
authorSrikant Patnaik2015-01-11 12:28:04 +0530
committerSrikant Patnaik2015-01-11 12:28:04 +0530
commit871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch)
tree8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/net/wireless/eagle/esp_ctrl.c
parent9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff)
downloadFOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2
FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/net/wireless/eagle/esp_ctrl.c')
-rwxr-xr-xdrivers/net/wireless/eagle/esp_ctrl.c784
1 files changed, 784 insertions, 0 deletions
diff --git a/drivers/net/wireless/eagle/esp_ctrl.c b/drivers/net/wireless/eagle/esp_ctrl.c
new file mode 100755
index 00000000..2e3eb831
--- /dev/null
+++ b/drivers/net/wireless/eagle/esp_ctrl.c
@@ -0,0 +1,784 @@
+/*
+ * 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 */
+#include "esp_version.h"
+
+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, 28))
+ ieee80211_stop_tx_ba_session(sip->epub->hw, node->addr, (u16)tid, WLAN_BACK_INITIATOR);
+#elif (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, 28))
+ ieee80211_start_tx_ba_session(sip->epub->hw, node->addr, tid);
+#elif (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) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+ sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->addr, tid, node->ifidx, 0);
+#else
+ sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->sta->addr, tid, node->ifidx, 0);
+#endif
+ } 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));
+ char test_res_str[560];
+ sprintf(test_res_str, "esp_host:%llx\nesp_target: %.*s", DRIVER_VER, *len, p);
+
+ esp_dbg(ESP_SHOW, "%s\n", test_res_str);
+#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, test_res_str, strlen(test_res_str));
+ }
+#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;
+ }
+ case SIP_EVT_NOISEFLOOR:{
+ struct sip_evt_noisefloor *ep = (struct sip_evt_noisefloor *)(buf + SIP_CTRL_HDR_LEN);
+ atomic_set(&sip->noise_floor, ep->noise_floor);
+ 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 */
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+int is_file_exist(const char * filename)
+{
+ int exist = 0;
+ struct file *filp = (struct file *)-ENOENT;
+ filp = filp_open(filename, O_RDONLY, S_IRUSR);
+ if (!IS_ERR(filp))
+ {
+ exist = 1;
+ filp_close(filp, NULL);
+ }
+
+ return exist;
+}
+void get_esp_init_name(char * raw_filename)
+{
+ int ret = 0;
+ unsigned char buf[80];
+ int varlen = 80;
+ char esp_init_perfix[256] = "esp_init_data";
+ char esp_init_suffix[256] = ".bin";
+ char filename[256];
+ ret = wmt_getsyspara("wmt.model.no", buf, &varlen);
+ if (ret == 0)
+ {
+ sprintf(filename, "%s/%s_%s%s", "/system/etc/firmware", esp_init_perfix, buf, esp_init_suffix);
+ if (is_file_exist(filename))
+ {
+ sprintf(raw_filename, "%s_%s%s", esp_init_perfix, buf, esp_init_suffix);
+ return ;
+ }
+ }
+ sprintf(raw_filename, "%s", ESP_INIT_NAME);
+ return ;
+}
+
+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;
+ char esp_init_name[256];
+ get_esp_init_name(esp_init_name);
+ printk("esp_init_name = %s\n", esp_init_name);
+ #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 -EINVAL;
+ 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 -EINVAL;
+
+ 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 -EINVAL;
+
+ 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);
+}
+
+int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size)
+{
+ int index = 0;
+ struct sk_buff *skb = NULL;
+ struct sip_cmd_ampdu_action * action;
+ if(action_num == SIP_AMPDU_RX_START){
+ index = esp_get_empty_rxampdu(epub, addr, tid);
+ } else if(action_num == SIP_AMPDU_RX_STOP){
+ index = esp_get_exist_rxampdu(epub, addr, tid);
+ }
+ if(index < 0)
+ return -EACCES;
+ skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ampdu_action) + sizeof(struct sip_hdr), SIP_CMD_AMPDU_ACTION);
+ if(!skb)
+ return -EINVAL;
+
+ 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 = index;
+ 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);
+}
+
+#ifdef HW_SCAN
+/*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 -EINVAL;
+
+ 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);
+}
+#endif
+
+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 -EINVAL;
+
+ 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 -EINVAL;
+
+
+ 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 -EINVAL;
+
+ 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 -EINVAL;
+
+ 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);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index)
+#else
+int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node, struct ieee80211_vif *vif, u8 index)
+#endif
+{
+ struct sk_buff *skb = NULL;
+ struct sip_cmd_setsta *setstacmd;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
+ struct ieee80211_ht_info ht_info = node->ht_info;
+#endif
+ skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setsta) + sizeof(struct sip_hdr), SIP_CMD_SETSTA);
+ if (!skb)
+ return -EINVAL;
+
+ setstacmd = (struct sip_cmd_setsta *)(skb->data + sizeof(struct sip_hdr));
+ setstacmd->ifidx = ifidx;
+ setstacmd->index = index;
+ setstacmd->set = set;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+ 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;
+ }
+ }
+ }
+#else
+ setstacmd->aid = node->aid;
+ memcpy(setstacmd->mac, node->addr, ETH_ALEN);
+ if(set){
+ if(ht_info.ht_supported){
+ if(ht_info.cap & IEEE80211_HT_CAP_SGI_20)
+ setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
+ else
+ setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
+ setstacmd->ampdu_factor = ht_info.ampdu_factor;
+ setstacmd->ampdu_density = ht_info.ampdu_density;
+ } else {
+ //note supp_rates is u64[] in 2.6.27
+ if(node->supp_rates[IEEE80211_BAND_2GHZ] & (~(u64)CONF_HW_BIT_RATE_11B_MASK)){
+ setstacmd->phymode = ESP_IEEE80211_T_OFDM;
+ } else {
+ setstacmd->phymode = ESP_IEEE80211_T_CCK;
+ }
+ }
+ }
+#endif
+ 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 -ENOMEM;
+
+ memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len);
+
+ return sip_cmd_enqueue(epub->sip, skb);
+}