ba20341e70
Source: https://github.com/cringeops/bes2600 Source: https://github.com/cringeops/bes2600/pull/14 Source: https://github.com/cringeops/bes2600/pull/17 Source: https://github.com/cringeops/bes2600/pull/20
652 lines
20 KiB
C
652 lines
20 KiB
C
/*
|
|
* Mac80211 driver for BES2600 device
|
|
*
|
|
* Copyright (c) 2022, Bestechnic
|
|
* Author:
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/list.h>
|
|
|
|
#include "epta_coex.h"
|
|
#include "epta_request.h"
|
|
#include "bes_log.h"
|
|
|
|
#define EPTA_PERIOD_TIME 102400
|
|
|
|
#define BT_TIME_MAX 80000
|
|
|
|
#define BT_SHUTDOWN_TIME 0
|
|
#define BT_SHUTDOWN_MIN_TIME 0
|
|
#define BT_DISCONNECTED_TIME 0
|
|
#define BT_DISCONNECTED_MIN_TIME 0
|
|
#define BT_CONNECTING_TIME 60000
|
|
#define BT_CONNECTING_MIN_TIME 0
|
|
#define BT_CONNECTED_TIME 0
|
|
#define BT_CONNECTED_MIN_TIME 25000
|
|
#define BT_CONNECTED_SNIFF_TIME 0
|
|
#define BT_CONNECTED_SNIFF_MIN_TIME 20000
|
|
|
|
#define BT_BOTHSCAN_DISABLE_TIME 0
|
|
#define BT_BOTHSCAN_DISABLE_MIN_TIME 0
|
|
#define BT_BOTHSCAN_ENABLE_TIME 0
|
|
#define BT_BOTHSCAN_ENABLE_MIN_TIME 20000
|
|
#define BT_PSCAN_ENABLE_TIME 0
|
|
#define BT_PSCAN_ENABLE_MIN_TIME 20000
|
|
#define BT_ISCAN_ENABLE_TIME 0
|
|
#define BT_ISCAN_ENABLE_MIN_TIME 20000
|
|
|
|
#define BT_AUDIO_NONE_TIME 0
|
|
#define BT_AUDIO_NONE_MIN_TIME 0
|
|
#define BT_AUDIO_A2DP_TIME 60000
|
|
#define BT_AUDIO_A2DP_MIN_TIME 0
|
|
#define BT_AUDIO_SCO_TIME 80000
|
|
#define BT_AUDIO_SCO_MIN_TIME 0
|
|
|
|
#define BT_INQ_START_TIME 20000
|
|
#define BT_INQ_START_MIN_TIME 30000
|
|
#define BT_INQ_STOP_TIME 0
|
|
#define BT_INQ_STOP_MIN_TIME 0
|
|
|
|
#define BT_LE_SCAN_START_TIME 20000
|
|
#define BT_LE_SCAN_START_MIN_TIME 30000
|
|
#define BT_LE_SCAN_STOP_TIME 0
|
|
#define BT_LE_SCAN_STOP_MIN_TIME 0
|
|
|
|
#define BT_LE_ADV_START_TIME 20000
|
|
#define BT_LE_ADV_START_MIN_TIME 40000
|
|
#define BT_LE_ADV_STOP_TIME 0
|
|
#define BT_LE_ADV_STOP_MIN_TIME 0
|
|
|
|
#define BT_LE_CONNECTED_TIME 0
|
|
#define BT_LE_CONNECTED_MIN_TIME 50000
|
|
#define BT_LE_DISCONNECTED_TIME 0
|
|
#define BT_LE_DISCONNECTED_MIN_TIME 0
|
|
|
|
// BIT[2:0]
|
|
#define BT_REQUEST_STATUS_SHIFT 0
|
|
#define BT_REQUEST_STATUS_MASK (0x7 << BT_REQUEST_STATUS_SHIFT)
|
|
#define BT_REQUEST_STATUS_VALUE(n) (((n) & BT_REQUEST_STATUS_MASK) >> BT_REQUEST_STATUS_SHIFT)
|
|
|
|
// BIT[5:3]
|
|
#define BT_REQUEST_SCAN_SHIFT 3
|
|
#define BT_REQUEST_SCAN_MASK (0x7 << BT_REQUEST_SCAN_SHIFT)
|
|
#define BT_REQUEST_SCAN_VALUE(n) (((n) & BT_REQUEST_SCAN_MASK) >> BT_REQUEST_SCAN_SHIFT)
|
|
|
|
// BIT[8:6]
|
|
#define BT_REQUEST_AUDIO_SHIFT 6
|
|
#define BT_REQUEST_AUDIO_MASK (0x7 << BT_REQUEST_AUDIO_SHIFT)
|
|
#define BT_REQUEST_AUDIO_VALUE(n) (((n) & BT_REQUEST_AUDIO_MASK) >> BT_REQUEST_AUDIO_SHIFT)
|
|
|
|
// BIT[10:9]
|
|
#define BT_REQUEST_INQ_SHIFT 9
|
|
#define BT_REQUEST_INQ_MASK (0x3 << BT_REQUEST_INQ_SHIFT)
|
|
#define BT_REQUEST_INQ_VALUE(n) (((n) & BT_REQUEST_INQ_MASK) >> BT_REQUEST_INQ_SHIFT)
|
|
|
|
// BIT[12:11]
|
|
#define BT_REQUEST_LE_SCAN_SHIFT 11
|
|
#define BT_REQUEST_LE_SCAN_MASK (0x3 << BT_REQUEST_LE_SCAN_SHIFT)
|
|
#define BT_REQUEST_LE_SCAN_VALUE(n) (((n) & BT_REQUEST_LE_SCAN_MASK) >> BT_REQUEST_LE_SCAN_SHIFT)
|
|
|
|
// BIT[15:13]
|
|
#define BT_REQUEST_LE_ADV_SHIFT 13
|
|
#define BT_REQUEST_LE_ADV_MASK (0x7 << BT_REQUEST_LE_ADV_SHIFT)
|
|
#define BT_REQUEST_LE_ADV_VALUE(n) (((n) & BT_REQUEST_LE_ADV_MASK) >> BT_REQUEST_LE_ADV_SHIFT)
|
|
|
|
// BIT[17:16]
|
|
#define BT_REQUEST_LE_STATUS_SHIFT 16
|
|
#define BT_REQUEST_LE_STATUS_MASK (0x3 << BT_REQUEST_LE_STATUS_SHIFT)
|
|
#define BT_REQUEST_LE_STATUS_VALUE(n) (((n) & BT_REQUEST_LE_STATUS_MASK) >> BT_REQUEST_LE_STATUS_SHIFT)
|
|
|
|
typedef enum {
|
|
BWIFI_BT_STATUS_SHUTDOWN = 0,
|
|
BWIFI_BT_STATUS_DISCONNECTED = 1,
|
|
BWIFI_BT_STATUS_CONNECTING = 2,
|
|
BWIFI_BT_STATUS_CONNECTED_SNIFF = 3,
|
|
BWIFI_BT_STATUS_CONNECTED = 4,
|
|
} BWIFI_BT_STATUS_T;
|
|
|
|
typedef enum {
|
|
BWIFI_BT_BOTHSCAN_DISABLE = 0,
|
|
BWIFI_BT_BOTHSCAN_ENABLE = 1,
|
|
BWIFI_BT_PSCAN_ENABLE = 2,
|
|
BWIFI_BT_ISCAN_ENABLE = 3,
|
|
} BWIFI_BT_SCAN_T;
|
|
|
|
typedef enum {
|
|
BWIFI_BT_AUDIO_NONE = 0,
|
|
BWIFI_BT_AUDIO_A2DP = 1,
|
|
BWIFI_BT_AUDIO_SCO = 2,
|
|
} BWIFI_BT_AUDIO_T;
|
|
|
|
typedef enum {
|
|
BWIFI_BT_INQ_STOP = 0,
|
|
BWIFI_BT_INQ_START = 1,
|
|
} BWIFI_BT_INQ_T;
|
|
|
|
typedef enum {
|
|
BWIFI_LE_SCAN_STOP = 0,
|
|
BWIFI_LE_SCAN_START = 1,
|
|
} BWIFI_BT_LE_SCAN_T;
|
|
|
|
typedef enum {
|
|
BWIFI_LE_ADV_STOP = 0,
|
|
BWIFI_LE_ADV_START = 1,
|
|
} BWIFI_BT_LE_ADV_T;
|
|
|
|
typedef enum {
|
|
BWIFI_LE_DISCONNECTED = 0,
|
|
BWIFI_LE_CONNECTED = 1,
|
|
} BWIFI_BT_LE_STATUS_T;
|
|
|
|
enum COEX_BT_OPER_T {
|
|
COEX_BT_OPER_STATUS,
|
|
COEX_BT_OPER_SCAN,
|
|
COEX_BT_OPER_AUDIO,
|
|
COEX_BT_OPER_INQ,
|
|
COEX_BT_OPER_LE_SCAN,
|
|
COEX_BT_OPER_LE_ADV,
|
|
COEX_BT_OPER_LE_STATUS,
|
|
|
|
COEX_BT_OPER_NUM,
|
|
};
|
|
|
|
union COEX_BT_OPER_TYPE_T {
|
|
BWIFI_BT_STATUS_T status;
|
|
BWIFI_BT_SCAN_T scan;
|
|
BWIFI_BT_AUDIO_T audio;
|
|
BWIFI_BT_INQ_T inq;
|
|
BWIFI_BT_LE_SCAN_T le_scan;
|
|
BWIFI_BT_LE_ADV_T le_adv;
|
|
BWIFI_BT_LE_STATUS_T le_status;
|
|
};
|
|
|
|
struct COEX_BT_OPER_TIME_T {
|
|
enum COEX_BT_OPER_T oper;
|
|
union COEX_BT_OPER_TYPE_T type;
|
|
uint32_t time;
|
|
uint32_t min_time;
|
|
};
|
|
|
|
struct COEX_BT_OPER_TIME_T g_coex_bt_oper[COEX_BT_OPER_NUM];
|
|
|
|
static void coex_bt_time_init(void)
|
|
{
|
|
memset(g_coex_bt_oper, 0, sizeof(g_coex_bt_oper));
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].type.status = BWIFI_BT_STATUS_SHUTDOWN;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].type.scan = BWIFI_BT_BOTHSCAN_DISABLE;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].type.audio = BWIFI_BT_AUDIO_NONE;
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].type.inq = BWIFI_BT_INQ_STOP;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].type.le_scan = BWIFI_LE_SCAN_STOP;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].type.le_adv = BWIFI_LE_ADV_STOP;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].type.le_status = BWIFI_LE_DISCONNECTED;
|
|
}
|
|
|
|
static uint32_t coex_calc_bt_time(void)
|
|
{
|
|
uint32_t i;
|
|
uint32_t time = 0, min_time = 0;
|
|
|
|
for (i = 0; i < COEX_BT_OPER_NUM; ++i) {
|
|
time += g_coex_bt_oper[i].time;
|
|
if (min_time < g_coex_bt_oper[i].min_time)
|
|
min_time = g_coex_bt_oper[i].min_time;
|
|
}
|
|
|
|
bes_devel("%s time:%u, min_time:%u", __func__, time, min_time);
|
|
time = time < min_time ? min_time : time;
|
|
return time < BT_TIME_MAX ? time : BT_TIME_MAX;
|
|
}
|
|
|
|
void coex_calc_wifi_scan_time(uint32_t *min_chan, uint32_t *max_chan)
|
|
{
|
|
uint32_t time = coex_calc_bt_time();
|
|
|
|
if (time == 0) {
|
|
*min_chan = 100;
|
|
*max_chan = 100;
|
|
} else if (time < 40000) {
|
|
*min_chan = 50;
|
|
*max_chan = 110;
|
|
} else if (time < 60000) {
|
|
*min_chan = 40;
|
|
*max_chan = 110;
|
|
} else if (time < 80000) {
|
|
*min_chan = 30;
|
|
*max_chan = 120;
|
|
} else {
|
|
*min_chan = 30;
|
|
*max_chan = 130;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_state_notify(struct bes2600_common *hw_priv)
|
|
{
|
|
int32_t wifi_dur, bt_dur, mode;
|
|
|
|
bt_dur = coex_calc_bt_time();
|
|
wifi_dur = EPTA_PERIOD_TIME - bt_dur;
|
|
mode = 0;
|
|
coex_set_epta_params(hw_priv, wifi_dur, bt_dur, mode);
|
|
}
|
|
|
|
static void coex_bt_oper_status(struct bes2600_common *hw_priv, BWIFI_BT_STATUS_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_BT_STATUS_SHUTDOWN:
|
|
coex_bt_time_init();
|
|
break;
|
|
case BWIFI_BT_STATUS_DISCONNECTED:
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].type.status = BWIFI_BT_STATUS_DISCONNECTED;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].time = BT_DISCONNECTED_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].min_time = BT_DISCONNECTED_MIN_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].type.audio = BWIFI_BT_AUDIO_NONE;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].time = BT_AUDIO_NONE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].min_time = BT_AUDIO_NONE_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_STATUS_CONNECTING:
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].type.status = BWIFI_BT_STATUS_CONNECTING;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].time = BT_CONNECTING_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].min_time = BT_CONNECTING_MIN_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].type.audio = BWIFI_BT_AUDIO_NONE;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].time = BT_AUDIO_NONE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].min_time = BT_AUDIO_NONE_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_STATUS_CONNECTED:
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].type.status = BWIFI_BT_STATUS_CONNECTED;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].time = BT_CONNECTED_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].min_time = BT_CONNECTED_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_STATUS_CONNECTED_SNIFF:
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].type.status = BWIFI_BT_STATUS_CONNECTED_SNIFF;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].time = BT_CONNECTED_SNIFF_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_STATUS].min_time = BT_CONNECTED_SNIFF_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_oper_scan(struct bes2600_common *hw_priv, BWIFI_BT_SCAN_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_BT_BOTHSCAN_DISABLE:
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].type.scan = BWIFI_BT_BOTHSCAN_DISABLE;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].time = BT_BOTHSCAN_DISABLE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].min_time = BT_BOTHSCAN_DISABLE_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_BOTHSCAN_ENABLE:
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].type.scan = BWIFI_BT_BOTHSCAN_ENABLE;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].time = BT_BOTHSCAN_ENABLE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].min_time = BT_BOTHSCAN_ENABLE_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_PSCAN_ENABLE:
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].type.scan = BWIFI_BT_PSCAN_ENABLE;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].time = BT_PSCAN_ENABLE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].min_time = BT_PSCAN_ENABLE_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_ISCAN_ENABLE:
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].type.scan = BWIFI_BT_ISCAN_ENABLE;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].time = BT_ISCAN_ENABLE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_SCAN].min_time = BT_ISCAN_ENABLE_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_oper_audio(struct bes2600_common *hw_priv, BWIFI_BT_AUDIO_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_BT_AUDIO_NONE:
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].type.audio = BWIFI_BT_AUDIO_NONE;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].time = BT_AUDIO_NONE_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].min_time = BT_AUDIO_NONE_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_AUDIO_A2DP:
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].type.audio = BWIFI_BT_AUDIO_A2DP;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].time = BT_AUDIO_A2DP_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].min_time = BT_AUDIO_A2DP_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_AUDIO_SCO:
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].type.audio = BWIFI_BT_AUDIO_SCO;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].time = BT_AUDIO_SCO_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_AUDIO].min_time = BT_AUDIO_SCO_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_oper_inq(struct bes2600_common *hw_priv, BWIFI_BT_INQ_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_BT_INQ_START:
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].type.inq = BWIFI_BT_INQ_START;
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].time = BT_INQ_START_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].min_time = BT_INQ_START_MIN_TIME;
|
|
break;
|
|
case BWIFI_BT_INQ_STOP:
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].type.inq = BWIFI_BT_INQ_STOP;
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].time = BT_INQ_STOP_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_INQ].min_time = BT_INQ_STOP_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_oper_le_scan(struct bes2600_common *hw_priv, BWIFI_BT_LE_SCAN_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_LE_SCAN_START:
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].type.le_scan = BWIFI_LE_SCAN_START;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].time = BT_LE_SCAN_START_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].min_time = BT_LE_SCAN_START_MIN_TIME;
|
|
break;
|
|
case BWIFI_LE_SCAN_STOP:
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].type.le_scan = BWIFI_LE_SCAN_STOP;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].time = BT_LE_SCAN_STOP_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_SCAN].min_time = BT_LE_SCAN_STOP_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_oper_le_adv(struct bes2600_common *hw_priv, BWIFI_BT_LE_ADV_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_LE_ADV_START:
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].type.le_adv = BWIFI_LE_ADV_START;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].time = BT_LE_ADV_START_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].min_time = BT_LE_ADV_START_MIN_TIME;
|
|
break;
|
|
case BWIFI_LE_ADV_STOP:
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].type.le_adv = BWIFI_LE_ADV_STOP;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].time = BT_LE_ADV_STOP_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_ADV].min_time = BT_LE_ADV_STOP_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void coex_bt_oper_le_status(struct bes2600_common *hw_priv, BWIFI_BT_LE_STATUS_T type)
|
|
{
|
|
bes_devel("%s type:%d", __func__, type);
|
|
|
|
switch (type) {
|
|
case BWIFI_LE_CONNECTED:
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].type.le_status = BWIFI_LE_CONNECTED;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].time = BT_LE_CONNECTED_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].min_time = BT_LE_CONNECTED_MIN_TIME;
|
|
break;
|
|
case BWIFI_LE_DISCONNECTED:
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].type.le_status = BWIFI_LE_DISCONNECTED;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].time = BT_LE_DISCONNECTED_TIME;
|
|
g_coex_bt_oper[COEX_BT_OPER_LE_STATUS].min_time = BT_LE_DISCONNECTED_MIN_TIME;
|
|
break;
|
|
default:
|
|
bes_err("%s type error:%d", __func__, type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int coex_wifi_state_notify(struct bes2600_common *hw_priv, enum bwifi_epta_state state)
|
|
{
|
|
bes_devel("%s state:%d", __func__, state);
|
|
switch (state) {
|
|
case EPTA_STATE_WIFI_DISCONNECTED:
|
|
coex_set_wifi_conn(hw_priv, state);
|
|
break;
|
|
case EPTA_STATE_WIFI_SCANNING:
|
|
coex_set_wifi_conn(hw_priv, state);
|
|
break;
|
|
case EPTA_STATE_WIFI_SCAN_COMP:
|
|
coex_set_wifi_conn(hw_priv, state);
|
|
break;
|
|
case EPTA_STATE_WIFI_CONNECTING:
|
|
coex_set_wifi_conn(hw_priv, state);
|
|
break;
|
|
case EPTA_STATE_WIFI_CONNECTED:
|
|
coex_set_wifi_conn(hw_priv, state);
|
|
break;
|
|
case EPTA_STATE_WIFI_GOT_IP:
|
|
coex_set_wifi_conn(hw_priv, state);
|
|
break;
|
|
case EPTA_STATE_WIFI_TTS_START:
|
|
coex_set_epta_tts(hw_priv, 0);
|
|
break;
|
|
case EPTA_STATE_WIFI_TTS_END:
|
|
coex_set_epta_tts(hw_priv, 1);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void coex_wifi_idle(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(false);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_DISCONNECTED);
|
|
}
|
|
|
|
static void coex_wifi_scanning(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(false); //scan use tdd
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_SCANNING);
|
|
}
|
|
|
|
static void coex_wifi_scan_comp(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_SCAN_COMP);
|
|
}
|
|
|
|
static void coex_wifi_connecting(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(false);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_CONNECTING);
|
|
}
|
|
|
|
static void coex_wifi_connecting_5g(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(true);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_CONNECTING);
|
|
}
|
|
|
|
static void coex_wifi_connected(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_CONNECTED);
|
|
}
|
|
|
|
static void coex_wifi_connected_5g(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(true);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_CONNECTED);
|
|
}
|
|
|
|
static void coex_wifi_got_ip(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_GOT_IP);
|
|
}
|
|
|
|
static void coex_wifi_got_ip_5g(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(true); // used for scan -> got ip 5g
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_GOT_IP);
|
|
}
|
|
|
|
static void coex_wifi_disconnecting(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
}
|
|
|
|
static void coex_wifi_disconnected(struct bes2600_common *hw_priv, BWIFI_STATUS_T value)
|
|
{
|
|
bes_devel("%s", __func__);
|
|
coex_set_fdd_mode(false);
|
|
coex_wifi_state_notify(hw_priv, EPTA_STATE_WIFI_DISCONNECTED);
|
|
}
|
|
|
|
static int coex_wifi_bt_ts_request(struct bes2600_common *hw_priv, COEX_TS_TYPE_T type, uint32_t value)
|
|
{
|
|
COEX_WIFI_BT_TS_T *wifi_bt_ts_event;
|
|
|
|
bes_devel("%s type:%u, value:0x%x", __func__, type, value);
|
|
|
|
if (atomic_read(&hw_priv->netdevice_start) == 0) {
|
|
bes_devel("net down. skip");
|
|
return 0;
|
|
}
|
|
|
|
/* called from spin lock vif_lock context */
|
|
wifi_bt_ts_event = kmalloc(sizeof(COEX_WIFI_BT_TS_T), GFP_ATOMIC);
|
|
if (wifi_bt_ts_event == NULL) {
|
|
bes_err("ts_event: malloc fail");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
INIT_LIST_HEAD(&wifi_bt_ts_event->node);
|
|
wifi_bt_ts_event->type = type;
|
|
wifi_bt_ts_event->value = value;
|
|
|
|
spin_lock(&hw_priv->coex_event_lock);
|
|
list_add_tail(&wifi_bt_ts_event->node, &hw_priv->coex_event_list);
|
|
spin_unlock(&hw_priv->coex_event_lock);
|
|
|
|
schedule_work(&hw_priv->coex_work);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void bbt_change_current_status(struct bes2600_common *hw_priv, uint32_t new_status)
|
|
{
|
|
coex_wifi_bt_ts_request(hw_priv, COEX_TS_TYPE_BT, new_status);
|
|
}
|
|
|
|
void bwifi_change_current_status(struct bes2600_common *hw_priv, BWIFI_STATUS_T new_status)
|
|
{
|
|
coex_wifi_bt_ts_request(hw_priv, COEX_TS_TYPE_WIFI, new_status);
|
|
}
|
|
|
|
static void coex_wifi_bt_ts_cb(struct bes2600_common *hw_priv, COEX_WIFI_BT_TS_T *evt)
|
|
{
|
|
if (evt->type == COEX_TS_TYPE_BT) {
|
|
coex_bt_oper_scan(hw_priv, (BWIFI_BT_SCAN_T)BT_REQUEST_SCAN_VALUE(evt->value));
|
|
coex_bt_oper_audio(hw_priv, (BWIFI_BT_AUDIO_T)BT_REQUEST_AUDIO_VALUE(evt->value));
|
|
coex_bt_oper_inq(hw_priv, (BWIFI_BT_INQ_T)BT_REQUEST_INQ_VALUE(evt->value));
|
|
coex_bt_oper_le_scan(hw_priv, (BWIFI_BT_LE_SCAN_T)BT_REQUEST_LE_SCAN_VALUE(evt->value));
|
|
coex_bt_oper_le_adv(hw_priv, (BWIFI_BT_LE_ADV_T)BT_REQUEST_LE_ADV_VALUE(evt->value));
|
|
coex_bt_oper_le_status(hw_priv, (BWIFI_BT_LE_STATUS_T)BT_REQUEST_LE_STATUS_VALUE(evt->value));
|
|
// process BT STATUS in the end
|
|
coex_bt_oper_status(hw_priv, (BWIFI_BT_STATUS_T)BT_REQUEST_STATUS_VALUE(evt->value));
|
|
coex_bt_state_notify(hw_priv);
|
|
} else if (evt->type == COEX_TS_TYPE_WIFI) {
|
|
switch (evt->value) {
|
|
case BWIFI_STATUS_IDLE:
|
|
coex_wifi_idle(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_SCANNING:
|
|
coex_wifi_scanning(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_SCANNING_COMP:
|
|
coex_wifi_scan_comp(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_CONNECTING:
|
|
coex_wifi_connecting(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_CONNECTING_5G:
|
|
coex_wifi_connecting_5g(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_CONNECTED:
|
|
coex_wifi_connected(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_CONNECTED_5G:
|
|
coex_wifi_connected_5g(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_GOT_IP:
|
|
coex_wifi_got_ip(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_GOT_IP_5G:
|
|
coex_wifi_got_ip_5g(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_DISCONNECTING:
|
|
coex_wifi_disconnecting(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
case BWIFI_STATUS_DISCONNECTED:
|
|
coex_wifi_disconnected(hw_priv, (BWIFI_STATUS_T)evt->value);
|
|
break;
|
|
default:
|
|
bes_err("UNKNOWN WIFI type %d", evt->value);
|
|
break;
|
|
}
|
|
} else {
|
|
bes_err("UNKNOWN EPTA type %d, %d", evt->type, evt->value);
|
|
}
|
|
}
|
|
|
|
static void coex_wifi_bt_ts_thread(struct work_struct *work)
|
|
{
|
|
COEX_WIFI_BT_TS_T *coex_event;
|
|
struct bes2600_common *hw_priv = container_of(work, struct bes2600_common, coex_work);
|
|
|
|
spin_lock(&hw_priv->coex_event_lock);
|
|
while (!list_empty(&hw_priv->coex_event_list)) {
|
|
coex_event = list_first_entry(&hw_priv->coex_event_list, COEX_WIFI_BT_TS_T, node);
|
|
list_del(&coex_event->node);
|
|
spin_unlock(&hw_priv->coex_event_lock);
|
|
coex_wifi_bt_ts_cb(hw_priv, coex_event);
|
|
kfree(coex_event);
|
|
|
|
spin_lock(&hw_priv->coex_event_lock);
|
|
}
|
|
spin_unlock(&hw_priv->coex_event_lock);
|
|
}
|
|
|
|
void coex_wifi_bt_ts_thread_init(struct bes2600_common *hw_priv)
|
|
{
|
|
coex_bt_time_init();
|
|
|
|
INIT_WORK(&hw_priv->coex_work, coex_wifi_bt_ts_thread);
|
|
INIT_LIST_HEAD(&hw_priv->coex_event_list);
|
|
spin_lock_init(&hw_priv->coex_event_lock);
|
|
}
|
|
|
|
void coex_wifi_bt_ts_thread_deinit(struct bes2600_common *hw_priv)
|
|
{
|
|
cancel_work_sync(&hw_priv->coex_work);
|
|
}
|