RTL88x2B Driver from Realtek. Version: 5.3.1

This commit is contained in:
Rin Cat
2018-11-23 15:19:44 -05:00
commit 95374e485a
599 changed files with 660947 additions and 0 deletions

3226
core/efuse/rtw_efuse.c Normal file

File diff suppressed because it is too large Load Diff

3630
core/mesh/rtw_mesh.c Normal file

File diff suppressed because it is too large Load Diff

506
core/mesh/rtw_mesh.h Normal file
View File

@@ -0,0 +1,506 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifndef __RTW_MESH_H_
#define __RTW_MESH_H_
#ifndef CONFIG_AP_MODE
#error "CONFIG_RTW_MESH can't be enabled when CONFIG_AP_MODE is not defined\n"
#endif
#ifndef RTW_MESH_SCAN_RESULT_EXP_MS
#define RTW_MESH_SCAN_RESULT_EXP_MS (10 * 1000)
#endif
#ifndef RTW_MESH_OFFCH_CAND_FIND_INT_MS
#define RTW_MESH_OFFCH_CAND_FIND_INT_MS (10 * 1000)
#endif
#define RTW_MESH_TTL 31
#define RTW_MESH_PERR_MIN_INT 100
#define RTW_MESH_DEFAULT_ELEMENT_TTL 31
#define RTW_MESH_RANN_INTERVAL 5000
#define RTW_MESH_PATH_TO_ROOT_TIMEOUT 6000
#define RTW_MESH_DIAM_TRAVERSAL_TIME 50
#define RTW_MESH_PATH_TIMEOUT 5000
#define RTW_MESH_PREQ_MIN_INT 10
#define RTW_MESH_MAX_PREQ_RETRIES 4
#define RTW_MESH_MIN_DISCOVERY_TIMEOUT (2 * RTW_MESH_DIAM_TRAVERSAL_TIME)
#define RTW_MESH_ROOT_CONFIRMATION_INTERVAL 2000
#define RTW_MESH_PATH_REFRESH_TIME 1000
#define RTW_MESH_ROOT_INTERVAL 5000
#define RTW_MESH_PLINK_UNKNOWN 0
#define RTW_MESH_PLINK_LISTEN 1
#define RTW_MESH_PLINK_OPN_SNT 2
#define RTW_MESH_PLINK_OPN_RCVD 3
#define RTW_MESH_PLINK_CNF_RCVD 4
#define RTW_MESH_PLINK_ESTAB 5
#define RTW_MESH_PLINK_HOLDING 6
#define RTW_MESH_PLINK_BLOCKED 7
extern const char *_rtw_mesh_plink_str[];
#define rtw_mesh_plink_str(s) ((s <= RTW_MESH_PLINK_BLOCKED) ? _rtw_mesh_plink_str[s] : _rtw_mesh_plink_str[RTW_MESH_PLINK_UNKNOWN])
#define RTW_MESH_PS_UNKNOWN 0
#define RTW_MESH_PS_ACTIVE 1
#define RTW_MESH_PS_LSLEEP 2
#define RTW_MESH_PS_DSLEEP 3
extern const char *_rtw_mesh_ps_str[];
#define rtw_mesh_ps_str(mps) ((mps <= RTW_MESH_PS_DSLEEP) ? _rtw_mesh_ps_str[mps] : _rtw_mesh_ps_str[RTW_MESH_PS_UNKNOWN])
#define GET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 0, 0, 8)
#define GET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 1, 0, 8)
#define GET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 2, 0, 8)
#define GET_MESH_CONF_ELE_SYNC_METHOD_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 3, 0, 8)
#define GET_MESH_CONF_ELE_AUTH_PROTO_ID(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 4, 0, 8)
#define GET_MESH_CONF_ELE_MESH_FORMATION(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 0, 8)
#define GET_MESH_CONF_ELE_CTO_MGATE(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 0, 1)
#define GET_MESH_CONF_ELE_NUM_OF_PEERINGS(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 1, 6)
#define GET_MESH_CONF_ELE_CTO_AS(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 5, 7, 1)
#define GET_MESH_CONF_ELE_MESH_CAP(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 0, 8)
#define GET_MESH_CONF_ELE_ACCEPT_PEERINGS(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 0, 1)
#define GET_MESH_CONF_ELE_MCCA_SUP(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 1, 1)
#define GET_MESH_CONF_ELE_MCCA_EN(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 2, 1)
#define GET_MESH_CONF_ELE_FORWARDING(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 3, 1)
#define GET_MESH_CONF_ELE_MBCA_EN(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 4, 1)
#define GET_MESH_CONF_ELE_TBTT_ADJ(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 5, 1)
#define GET_MESH_CONF_ELE_PS_LEVEL(_iec) LE_BITS_TO_1BYTE(((u8 *)(_iec)) + 6, 6, 1)
#define SET_MESH_CONF_ELE_PATH_SEL_PROTO_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 0, 0, 8, _val)
#define SET_MESH_CONF_ELE_PATH_SEL_METRIC_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 1, 0, 8, _val)
#define SET_MESH_CONF_ELE_CONGEST_CTRL_MODE_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 2, 0, 8, _val)
#define SET_MESH_CONF_ELE_SYNC_METHOD_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 3, 0, 8, _val)
#define SET_MESH_CONF_ELE_AUTH_PROTO_ID(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 4, 0, 8, _val)
#define SET_MESH_CONF_ELE_CTO_MGATE(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 5, 0, 1, _val)
#define SET_MESH_CONF_ELE_NUM_OF_PEERINGS(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 5, 1, 6, _val)
#define SET_MESH_CONF_ELE_CTO_AS(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 5, 7, 1, _val)
#define SET_MESH_CONF_ELE_ACCEPT_PEERINGS(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 0, 1, _val)
#define SET_MESH_CONF_ELE_MCCA_SUP(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 1, 1, _val)
#define SET_MESH_CONF_ELE_MCCA_EN(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 2, 1, _val)
#define SET_MESH_CONF_ELE_FORWARDING(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 3, 1, _val)
#define SET_MESH_CONF_ELE_MBCA_EN(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 4, 1, _val)
#define SET_MESH_CONF_ELE_TBTT_ADJ(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 5, 1, _val)
#define SET_MESH_CONF_ELE_PS_LEVEL(_iec, _val) SET_BITS_TO_LE_1BYTE(((u8 *)(_iec)) + 6, 6, 1, _val)
/* Mesh flags */
#define MESH_FLAGS_AE 0x3 /* mask */
#define MESH_FLAGS_AE_A4 0x1
#define MESH_FLAGS_AE_A5_A6 0x2
/* Max number of paths */
#define RTW_MESH_MAX_PATHS 1024
#define RTW_PREQ_Q_F_START 0x1
#define RTW_PREQ_Q_F_REFRESH 0x2
struct rtw_mesh_preq_queue {
_list list;
u8 dst[ETH_ALEN];
u8 flags;
};
extern const u8 ae_to_mesh_ctrl_len[];
enum mesh_frame_type {
MESH_UCAST_DATA = 0x0,
MESH_BMCAST_DATA = 0x1,
MESH_UCAST_PX_DATA = 0x2,
MESH_BMCAST_PX_DATA = 0x3,
MESH_MHOP_UCAST_ACT = 0x4,
MESH_MHOP_BMCAST_ACT = 0x5,
};
enum mpath_sel_frame_type {
MPATH_PREQ = 0,
MPATH_PREP,
MPATH_PERR,
MPATH_RANN
};
/**
* enum rtw_mesh_deferred_task_flags - mesh deferred tasks
*
*
*
* @RTW_MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks
* @RTW_MESH_WORK_ROOT: the mesh root station needs to send a frame
* @RTW_MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other
* mesh nodes
* @RTW_MESH_WORK_MBSS_CHANGED: rebuild beacon and notify driver of BSS changes
*/
enum rtw_mesh_deferred_task_flags {
RTW_MESH_WORK_HOUSEKEEPING,
RTW_MESH_WORK_ROOT,
RTW_MESH_WORK_DRIFT_ADJUST,
RTW_MESH_WORK_MBSS_CHANGED,
};
#define RTW_MESH_MAX_PEER_CANDIDATES 15 /* aid consideration */
#define RTW_MESH_MAX_PEER_LINKS 8
#define RTW_MESH_PEER_LINK_TIMEOUT 20
#define RTW_MESH_PEER_CONF_DISABLED 0 /* special time value means no confirmation ongoing */
#if CONFIG_RTW_MESH_PEER_BLACKLIST
#define IS_PEER_CONF_DISABLED(plink) ((plink)->peer_conf_end_time == RTW_MESH_PEER_CONF_DISABLED)
#define IS_PEER_CONF_TIMEOUT(plink)(!IS_PEER_CONF_DISABLED(plink) && rtw_time_after(rtw_get_current_time(), (plink)->peer_conf_end_time))
#define SET_PEER_CONF_DISABLED(plink) (plink)->peer_conf_end_time = RTW_MESH_PEER_CONF_DISABLED
#define SET_PEER_CONF_END_TIME(plink, timeout_ms) \
do { \
(plink)->peer_conf_end_time = rtw_get_current_time() + rtw_ms_to_systime(timeout_ms); \
if ((plink)->peer_conf_end_time == RTW_MESH_PEER_CONF_DISABLED) \
(plink)->peer_conf_end_time++; \
} while (0)
#else
#define IS_PEER_CONF_DISABLED(plink) 1
#define IS_PEER_CONF_TIMEOUT(plink) 0
#define SET_PEER_CONF_DISABLED(plink) do {} while (0)
#define SET_PEER_CONF_END_TIME(plink, timeout_ms) do {} while (0)
#endif /* CONFIG_RTW_MESH_PEER_BLACKLIST */
#define RTW_MESH_CTO_MGATE_CONF_DISABLED 0 /* special time value means no confirmation ongoing */
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
#define IS_CTO_MGATE_CONF_DISABLED(plink) ((plink)->cto_mgate_conf_end_time == RTW_MESH_CTO_MGATE_CONF_DISABLED)
#define IS_CTO_MGATE_CONF_TIMEOUT(plink)(!IS_CTO_MGATE_CONF_DISABLED(plink) && rtw_time_after(rtw_get_current_time(), (plink)->cto_mgate_conf_end_time))
#define SET_CTO_MGATE_CONF_DISABLED(plink) (plink)->cto_mgate_conf_end_time = RTW_MESH_CTO_MGATE_CONF_DISABLED
#define SET_CTO_MGATE_CONF_END_TIME(plink, timeout_ms) \
do { \
(plink)->cto_mgate_conf_end_time = rtw_get_current_time() + rtw_ms_to_systime(timeout_ms); \
if ((plink)->cto_mgate_conf_end_time == RTW_MESH_CTO_MGATE_CONF_DISABLED) \
(plink)->cto_mgate_conf_end_time++; \
} while (0)
#else
#define IS_CTO_MGATE_CONF_DISABLED(plink) 1
#define IS_CTO_MGATE_CONF_TIMEOUT(plink) 0
#define SET_CTO_MGATE_CONF_DISABLED(plink) do {} while (0)
#define SET_CTO_MGATE_CONF_END_TIME(plink, timeout_ms) do {} while (0)
#endif /* CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST */
struct mesh_plink_ent {
u8 valid;
u8 addr[ETH_ALEN];
u8 plink_state;
#ifdef CONFIG_RTW_MESH_AEK
u8 aek_valid;
u8 aek[32];
#endif
u16 llid;
u16 plid;
#ifndef CONFIG_RTW_MESH_DRIVER_AID
u16 aid; /* aid assigned from upper layer */
#endif
u16 peer_aid; /* aid assigned from peer */
u8 chosen_pmk[16];
#ifdef CONFIG_RTW_MESH_AEK
u8 sel_pcs[4];
u8 l_nonce[32];
u8 p_nonce[32];
#endif
#ifdef CONFIG_RTW_MESH_DRIVER_AID
u8 *tx_conf_ies;
u16 tx_conf_ies_len;
#endif
u8 *rx_conf_ies;
u16 rx_conf_ies_len;
struct wlan_network *scanned;
#if CONFIG_RTW_MESH_PEER_BLACKLIST
systime peer_conf_end_time;
#endif
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
systime cto_mgate_conf_end_time;
#endif
};
#ifdef CONFIG_RTW_MESH_AEK
#define MESH_PLINK_AEK_VALID(ent) ent->aek_valid
#else
#define MESH_PLINK_AEK_VALID(ent) 0
#endif
struct mesh_plink_pool {
_lock lock;
u8 num; /* current ent being used */
struct mesh_plink_ent ent[RTW_MESH_MAX_PEER_CANDIDATES];
#if CONFIG_RTW_MESH_PEER_BLACKLIST
_queue peer_blacklist;
#endif
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
_queue cto_mgate_blacklist;
#endif
};
#define RTW_MESH_PEER_CONF_TIMEOUT_MS (20 * 1000)
#define RTW_MESH_PEER_BLACKLIST_TIMEOUT_MS (20 * 1000)
#define RTW_MESH_CTO_MGATE_CONF_TIMEOUT_MS (20 * 1000)
#define RTW_MESH_CTO_MGATE_BLACKLIST_TIMEOUT_MS (20 * 1000)
struct mesh_peer_sel_policy {
u32 scanr_exp_ms;
#if CONFIG_RTW_MESH_OFFCH_CAND
u32 offch_find_int_ms; /* 0 means no offch find by driver */
#endif
#if CONFIG_RTW_MESH_PEER_BLACKLIST
u32 peer_conf_timeout_ms;
u32 peer_blacklist_timeout_ms;
#endif
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
u8 cto_mgate_require;
u32 cto_mgate_conf_timeout_ms;
u32 cto_mgate_blacklist_timeout_ms;
#endif
};
/* b2u flags */
#define RTW_MESH_B2U_ALL BIT0
#define RTW_MESH_B2U_GA_UCAST BIT1 /* Group addressed unicast frame, forward only */
#define RTW_MESH_B2U_BCAST BIT2
#define RTW_MESH_B2U_IP_MCAST BIT3
#define rtw_msrc_b2u_policy_chk(flags, mda) ( \
(flags & RTW_MESH_B2U_ALL) \
|| ((flags & RTW_MESH_B2U_BCAST) && is_broadcast_mac_addr(mda)) \
|| ((flags & RTW_MESH_B2U_IP_MCAST) && (IP_MCAST_MAC(mda) || ICMPV6_MCAST_MAC(mda))) \
)
#define rtw_mfwd_b2u_policy_chk(flags, mda, ucst) ( \
(flags & RTW_MESH_B2U_ALL) \
|| ((flags & RTW_MESH_B2U_GA_UCAST) && ucst) \
|| ((flags & RTW_MESH_B2U_BCAST) && is_broadcast_mac_addr(mda)) \
|| ((flags & RTW_MESH_B2U_IP_MCAST) && (IP_MCAST_MAC(mda) || ICMPV6_MCAST_MAC(mda))) \
)
struct rtw_mesh_cfg {
u8 max_peer_links; /* peering limit */
u32 plink_timeout; /* seconds */
u8 dot11MeshTTL;
u8 element_ttl;
u32 path_refresh_time;
u16 dot11MeshHWMPpreqMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
u32 dot11MeshHWMPactivePathTimeout;
u8 dot11MeshHWMPmaxPREQretries;
u16 min_discovery_timeout;
u16 dot11MeshHWMPconfirmationInterval;
u16 dot11MeshHWMPperrMinInterval;
u8 dot11MeshHWMPRootMode;
BOOLEAN dot11MeshForwarding;
s32 rssi_threshold; /* in dBm, 0: no specified */
u16 dot11MeshHWMPRannInterval;
BOOLEAN dot11MeshGateAnnouncementProtocol;
u32 dot11MeshHWMPactivePathToRootTimeout;
u16 dot11MeshHWMProotInterval;
u8 path_gate_timeout_factor;
struct mesh_peer_sel_policy peer_sel_policy;
#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
u8 b2u_flags_msrc;
u8 b2u_flags_mfwd;
#endif
};
struct rtw_mesh_stats {
u32 fwded_mcast; /* Mesh forwarded multicast frames */
u32 fwded_unicast; /* Mesh forwarded unicast frames */
u32 fwded_frames; /* Mesh total forwarded frames */
u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/
u32 dropped_frames_no_route; /* Not transmitted, no route found */
u32 dropped_frames_congestion;/* Not forwarded due to congestion */
u32 dropped_frames_duplicate;
u32 mrc_del_qlen; /* MRC entry deleted cause by queue length limit */
};
struct rtw_mrc;
struct rtw_mesh_info {
u8 mesh_id[NDIS_802_11_LENGTH_SSID];
size_t mesh_id_len;
/* Active Path Selection Protocol Identifier */
u8 mesh_pp_id;
/* Active Path Selection Metric Identifier */
u8 mesh_pm_id;
/* Congestion Control Mode Identifier */
u8 mesh_cc_id;
/* Synchronization Protocol Identifier */
u8 mesh_sp_id;
/* Authentication Protocol Identifier */
u8 mesh_auth_id;
struct mesh_plink_pool plink_ctl;
u32 mesh_seqnum;
/* MSTA's own hwmp sequence number */
u32 sn;
systime last_preq;
systime last_sn_update;
systime next_perr;
/* Last used Path Discovery ID */
u32 preq_id;
ATOMIC_T mpaths;
struct rtw_mesh_table *mesh_paths;
struct rtw_mesh_table *mpp_paths;
int mesh_paths_generation;
int mpp_paths_generation;
int num_gates;
struct rtw_mesh_stats mshstats;
_queue mpath_tx_queue;
u32 mpath_tx_queue_len;
struct tasklet_struct mpath_tx_tasklet;
struct rtw_mrc *mrc;
_lock mesh_preq_queue_lock;
struct rtw_mesh_preq_queue preq_queue;
int preq_queue_len;
};
extern const char *_action_self_protected_str[];
#define action_self_protected_str(action) ((action < RTW_ACT_SELF_PROTECTED_NUM) ? _action_self_protected_str[action] : _action_self_protected_str[0])
u8 *rtw_set_ie_mesh_id(u8 *buf, u32 *buf_len, const char *mesh_id, u8 id_len);
u8 *rtw_set_ie_mesh_config(u8 *buf, u32 *buf_len
, u8 path_sel_proto, u8 path_sel_metric, u8 congest_ctl_mode, u8 sync_method, u8 auth_proto
, u8 num_of_peerings, bool cto_mgate, bool cto_as
, bool accept_peerings, bool mcca_sup, bool mcca_en, bool forwarding
, bool mbca_en, bool tbtt_adj, bool ps_level);
int rtw_bss_is_same_mbss(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b);
int rtw_bss_is_candidate_mesh_peer(WLAN_BSSID_EX *self, WLAN_BSSID_EX *target, u8 ch, u8 add_peer);
void rtw_chk_candidate_peer_notify(_adapter *adapter, struct wlan_network *scanned);
void rtw_mesh_peer_status_chk(_adapter *adapter);
#if CONFIG_RTW_MESH_OFFCH_CAND
u8 rtw_mesh_offch_candidate_accepted(_adapter *adapter);
u8 rtw_mesh_select_operating_ch(_adapter *adapter);
#endif
#if CONFIG_RTW_MESH_PEER_BLACKLIST
int rtw_mesh_peer_blacklist_add(_adapter *adapter, const u8 *addr);
int rtw_mesh_peer_blacklist_del(_adapter *adapter, const u8 *addr);
int rtw_mesh_peer_blacklist_search(_adapter *adapter, const u8 *addr);
void rtw_mesh_peer_blacklist_flush(_adapter *adapter);
void dump_mesh_peer_blacklist(void *sel, _adapter *adapter);
void dump_mesh_peer_blacklist_settings(void *sel, _adapter *adapter);
#endif
#if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
u8 rtw_mesh_cto_mgate_required(_adapter *adapter);
u8 rtw_mesh_cto_mgate_network_filter(_adapter *adapter, struct wlan_network *scanned);
int rtw_mesh_cto_mgate_blacklist_add(_adapter *adapter, const u8 *addr);
int rtw_mesh_cto_mgate_blacklist_del(_adapter *adapter, const u8 *addr);
int rtw_mesh_cto_mgate_blacklist_search(_adapter *adapter, const u8 *addr);
void rtw_mesh_cto_mgate_blacklist_flush(_adapter *adapter);
void dump_mesh_cto_mgate_blacklist(void *sel, _adapter *adapter);
void dump_mesh_cto_mgate_blacklist_settings(void *sel, _adapter *adapter);
#endif
void dump_mesh_peer_sel_policy(void *sel, _adapter *adapter);
void dump_mesh_networks(void *sel, _adapter *adapter);
int rtw_sae_check_frames(_adapter *adapter, const u8 *buf, u32 len, u8 tx);
int rtw_mesh_check_frames_tx(_adapter *adapter, const u8 **buf, size_t *len);
int rtw_mesh_check_frames_rx(_adapter *adapter, const u8 *buf, size_t len);
unsigned int on_action_self_protected(_adapter *adapter, union recv_frame *rframe);
bool rtw_mesh_update_bss_peering_status(_adapter *adapter, WLAN_BSSID_EX *bss);
bool rtw_mesh_update_bss_formation_info(_adapter *adapter, WLAN_BSSID_EX *bss);
bool rtw_mesh_update_bss_forwarding_state(_adapter *adapter, WLAN_BSSID_EX *bss);
struct mesh_plink_ent *_rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr);
struct mesh_plink_ent *rtw_mesh_plink_get(_adapter *adapter, const u8 *hwaddr);
struct mesh_plink_ent *rtw_mesh_plink_get_no_estab_by_idx(_adapter *adapter, u8 idx);
int _rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr);
int rtw_mesh_plink_add(_adapter *adapter, const u8 *hwaddr);
int rtw_mesh_plink_set_state(_adapter *adapter, const u8 *hwaddr, u8 state);
#ifdef CONFIG_RTW_MESH_AEK
int rtw_mesh_plink_set_aek(_adapter *adapter, const u8 *hwaddr, const u8 *aek);
#endif
#if CONFIG_RTW_MESH_PEER_BLACKLIST
int rtw_mesh_plink_set_peer_conf_timeout(_adapter *adapter, const u8 *hwaddr);
#endif
void _rtw_mesh_plink_del_ent(_adapter *adapter, struct mesh_plink_ent *ent);
int rtw_mesh_plink_del(_adapter *adapter, const u8 *hwaddr);
void rtw_mesh_plink_ctl_init(_adapter *adapter);
void rtw_mesh_plink_ctl_deinit(_adapter *adapter);
void dump_mesh_plink_ctl(void *sel, _adapter *adapter);
int rtw_mesh_peer_establish(_adapter *adapter, struct mesh_plink_ent *plink, struct sta_info *sta);
void _rtw_mesh_expire_peer_ent(_adapter *adapter, struct mesh_plink_ent *plink);
void rtw_mesh_expire_peer(_adapter *adapter, const u8 *peer_addr);
u8 rtw_mesh_ps_annc(_adapter *adapter, u8 ps);
unsigned int on_action_mesh(_adapter *adapter, union recv_frame *rframe);
void rtw_mesh_cfg_init(_adapter *adapter);
void rtw_mesh_cfg_init_max_peer_links(_adapter *adapter, u8 stack_conf);
void rtw_mesh_cfg_init_plink_timeout(_adapter *adapter, u32 stack_conf);
void rtw_mesh_init_mesh_info(_adapter *adapter);
void rtw_mesh_deinit_mesh_info(_adapter *adapter);
#if CONFIG_RTW_MESH_DATA_BMC_TO_UC
void dump_mesh_b2u_flags(void *sel, _adapter *adapter);
#endif
int rtw_mesh_addr_resolve(_adapter *adapter, struct xmit_frame *xframe, _pkt *pkt, _list *b2u_list);
s8 rtw_mesh_tx_set_whdr_mctrl_len(u8 mesh_frame_mode, struct pkt_attrib *attrib);
void rtw_mesh_tx_build_mctrl(_adapter *adapter, struct pkt_attrib *attrib, u8 *buf);
u8 rtw_mesh_tx_build_whdr(_adapter *adapter, struct pkt_attrib *attrib
, u16 *fctrl, struct rtw_ieee80211_hdr *whdr);
int rtw_mesh_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta);
int rtw_mesh_rx_data_validate_mctrl(_adapter *adapter, union recv_frame *rframe
, const struct rtw_ieee80211s_hdr *mctrl, const u8 *mda, const u8 *msa
, u8 *mctrl_len, const u8 **da, const u8 **sa);
int rtw_mesh_rx_validate_mctrl_non_amsdu(_adapter *adapter, union recv_frame *rframe);
int rtw_mesh_rx_msdu_act_check(union recv_frame *rframe
, const u8 *mda, const u8 *msa
, const u8 *da, const u8 *sa
, struct rtw_ieee80211s_hdr *mctrl
, struct xmit_frame **fwd_frame, _list *b2u_list);
void dump_mesh_stats(void *sel, _adapter *adapter);
#if defined(PLATFORM_LINUX) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
#define rtw_lockdep_assert_held(l) lockdep_assert_held(l)
#define rtw_lockdep_is_held(l) lockdep_is_held(l)
#else
#error "TBD\n"
#endif
#include "rtw_mesh_pathtbl.h"
#include "rtw_mesh_hwmp.h"
#endif /* __RTW_MESH_H_ */

1570
core/mesh/rtw_mesh_hwmp.c Normal file

File diff suppressed because it is too large Load Diff

60
core/mesh/rtw_mesh_hwmp.h Normal file
View File

@@ -0,0 +1,60 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifndef __RTW_MESH_HWMP_H_
#define __RTW_MESH_HWMP_H_
#ifndef DBG_RTW_HWMP
#define DBG_RTW_HWMP 0
#endif
#if DBG_RTW_HWMP
#define RTW_HWMP_DBG(fmt, arg...) RTW_PRINT(fmt, ##arg)
#else
#define RTW_HWMP_DBG(fmt, arg...) RTW_DBG(fmt, ##arg)
#endif
#ifndef INFO_RTW_HWMP
#define INFO_RTW_HWMP 0
#endif
#if INFO_RTW_HWMP
#define RTW_HWMP_INFO(fmt, arg...) RTW_PRINT(fmt, ##arg)
#else
#define RTW_HWMP_INFO(fmt, arg...) RTW_INFO(fmt, ##arg)
#endif
void rtw_ewma_err_rate_init(struct rtw_ewma_err_rate *e);
unsigned long rtw_ewma_err_rate_read(struct rtw_ewma_err_rate *e);
void rtw_ewma_err_rate_add(struct rtw_ewma_err_rate *e, unsigned long val);
int rtw_mesh_path_error_tx(_adapter *adapter,
u8 ttl, const u8 *target, u32 target_sn,
u16 target_rcode, const u8 *ra);
void rtw_ieee80211s_update_metric(_adapter *adapter, u8 mac_id,
u8 per, u8 rate,
u8 bw, u8 total_pkt);
void rtw_mesh_rx_path_sel_frame(_adapter *adapter, union recv_frame *rframe);
void rtw_mesh_queue_preq(struct rtw_mesh_path *mpath, u8 flags);
void rtw_mesh_path_start_discovery(_adapter *adapter);
void rtw_mesh_path_timer(void *ctx);
void rtw_mesh_path_tx_root_frame(_adapter *adapter);
void rtw_mesh_work_hdl(_workitem *work);
void rtw_ieee80211_mesh_path_timer(void *ctx);
void rtw_ieee80211_mesh_path_root_timer(void *ctx);
BOOLEAN rtw_ieee80211_mesh_root_setup(_adapter *adapter);
void rtw_mesh_work(_workitem *work);
void rtw_mesh_atlm_param_req_timer(void *ctx);
#endif /* __RTW_MESH_HWMP_H_ */

1082
core/mesh/rtw_mesh_pathtbl.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,193 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifndef __RTW_MESH_PATHTBL_H_
#define __RTW_MESH_PATHTBL_H_
#ifndef DBG_RTW_MPATH
#define DBG_RTW_MPATH 1
#endif
#if DBG_RTW_MPATH
#define RTW_MPATH_DBG(fmt, arg...) RTW_PRINT(fmt, ##arg)
#else
#define RTW_MPATH_DBG(fmt, arg...) do {} while (0)
#endif
/**
* enum rtw_mesh_path_flags - mesh path flags
*
* @RTW_MESH_PATH_ACTIVE: the mesh path can be used for forwarding
* @RTW_MESH_PATH_RESOLVING: the discovery process is running for this mesh path
* @RTW_MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence
* number
* @RTW_MESH_PATH_FIXED: the mesh path has been manually set and should not be
* modified
* @RTW_MESH_PATH_RESOLVED: the mesh path can has been resolved
* @RTW_MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination
* already queued up, waiting for the discovery process to start.
* @RTW_MESH_PATH_DELETED: the mesh path has been deleted and should no longer
* be used
*
* RTW_MESH_PATH_RESOLVED is used by the mesh path timer to
* decide when to stop or cancel the mesh path discovery.
*/
enum rtw_mesh_path_flags {
RTW_MESH_PATH_ACTIVE = BIT(0),
RTW_MESH_PATH_RESOLVING = BIT(1),
RTW_MESH_PATH_SN_VALID = BIT(2),
RTW_MESH_PATH_FIXED = BIT(3),
RTW_MESH_PATH_RESOLVED = BIT(4),
RTW_MESH_PATH_REQ_QUEUED = BIT(5),
RTW_MESH_PATH_DELETED = BIT(6),
};
/**
* struct rtw_mesh_path - mesh path structure
*
* @dst: mesh path destination mac address
* @mpp: mesh proxy mac address
* @rhash: rhashtable list pointer
* @gate_list: list pointer for known gates list
* @sdata: mesh subif
* @next_hop: mesh neighbor to which frames for this destination will be
* forwarded
* @timer: mesh path discovery timer
* @frame_queue: pending queue for frames sent to this destination while the
* path is unresolved
* @rcu: rcu head for freeing mesh path
* @sn: target sequence number
* @metric: current metric to this destination
* @hop_count: hops to destination
* @exp_time: in jiffies, when the path will expire or when it expired
* @discovery_timeout: timeout (lapse in jiffies) used for the last discovery
* retry
* @discovery_retries: number of discovery retries
* @flags: mesh path flags, as specified on &enum rtw_mesh_path_flags
* @state_lock: mesh path state lock used to protect changes to the
* mpath itself. No need to take this lock when adding or removing
* an mpath to a hash bucket on a path table.
* @rann_snd_addr: the RANN sender address
* @rann_metric: the aggregated path metric towards the root node
* @last_preq_to_root: Timestamp of last PREQ sent to root
* @is_root: the destination station of this path is a root node
* @is_gate: the destination station of this path is a mesh gate
*
*
* The dst address is unique in the mesh path table. Since the mesh_path is
* protected by RCU, deleting the next_hop STA must remove / substitute the
* mesh_path structure and wait until that is no longer reachable before
* destroying the STA completely.
*/
struct rtw_mesh_path {
u8 dst[ETH_ALEN];
u8 mpp[ETH_ALEN]; /* used for MPP or MAP */
rtw_rhash_head rhash;
rtw_hlist_node gate_list;
_adapter *adapter;
struct sta_info __rcu *next_hop;
_timer timer;
_queue frame_queue;
u32 frame_queue_len;
rtw_rcu_head rcu;
u32 sn;
u32 metric;
u8 hop_count;
systime exp_time;
systime discovery_timeout;
systime gate_timeout;
u32 gate_ann_int; /* gate announce interval */
u8 discovery_retries;
enum rtw_mesh_path_flags flags;
_lock state_lock;
u8 rann_snd_addr[ETH_ALEN];
u32 rann_metric;
unsigned long last_preq_to_root;
bool is_root;
bool is_gate;
bool gate_asked;
};
/**
* struct rtw_mesh_table
*
* @known_gates: list of known mesh gates and their mpaths by the station. The
* gate's mpath may or may not be resolved and active.
* @gates_lock: protects updates to known_gates
* @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr
* @entries: number of entries in the table
*/
struct rtw_mesh_table {
rtw_hlist_head known_gates;
_lock gates_lock;
rtw_rhashtable rhead;
ATOMIC_T entries;
};
#define RTW_MESH_PATH_EXPIRE (600 * HZ)
/* Maximum number of paths per interface */
#define RTW_MESH_MAX_MPATHS 1024
/* Number of frames buffered per destination for unresolved destinations */
#define RTW_MESH_FRAME_QUEUE_LEN 10
int rtw_mesh_nexthop_lookup(_adapter *adapter,
const u8 *mda, const u8 *msa, u8 *ra);
int rtw_mesh_nexthop_resolve(_adapter *adapter,
struct xmit_frame *xframe);
struct rtw_mesh_path *rtw_mesh_path_lookup(_adapter *adapter,
const u8 *dst);
struct rtw_mesh_path *rtw_mpp_path_lookup(_adapter *adapter,
const u8 *dst);
int rtw_mpp_path_add(_adapter *adapter,
const u8 *dst, const u8 *mpp);
struct rtw_mesh_path *
rtw_mesh_path_lookup_by_idx(_adapter *adapter, int idx);
struct rtw_mesh_path *
rtw_mpp_path_lookup_by_idx(_adapter *adapter, int idx);
void rtw_mesh_path_fix_nexthop(struct rtw_mesh_path *mpath, struct sta_info *next_hop);
void rtw_mesh_path_expire(_adapter *adapter);
struct rtw_mesh_path *
rtw_mesh_path_add(_adapter *adapter, const u8 *dst);
int rtw_mesh_path_add_gate(struct rtw_mesh_path *mpath);
void rtw_mesh_gate_del(struct rtw_mesh_table *tbl, struct rtw_mesh_path *mpath);
bool rtw_mesh_gate_search(struct rtw_mesh_table *tbl, const u8 *addr);
int rtw_mesh_path_send_to_gates(struct rtw_mesh_path *mpath);
int rtw_mesh_gate_num(_adapter *adapter);
void rtw_mesh_plink_broken(struct sta_info *sta);
void rtw_mesh_path_assign_nexthop(struct rtw_mesh_path *mpath, struct sta_info *sta);
void rtw_mesh_path_flush_pending(struct rtw_mesh_path *mpath);
void rtw_mesh_path_tx_pending(struct rtw_mesh_path *mpath);
int rtw_mesh_pathtbl_init(_adapter *adapter);
void rtw_mesh_pathtbl_unregister(_adapter *adapter);
int rtw_mesh_path_del(_adapter *adapter, const u8 *addr);
void rtw_mesh_path_flush_by_nexthop(struct sta_info *sta);
void rtw_mesh_path_discard_frame(_adapter *adapter,
struct xmit_frame *xframe);
static inline void rtw_mesh_path_activate(struct rtw_mesh_path *mpath)
{
mpath->flags |= RTW_MESH_PATH_ACTIVE | RTW_MESH_PATH_RESOLVED;
}
void rtw_mesh_path_flush_by_iface(_adapter *adapter);
#endif /* __RTW_MESH_PATHTBL_H_ */

4983
core/rtw_ap.c Normal file

File diff suppressed because it is too large Load Diff

3155
core/rtw_beamforming.c Normal file

File diff suppressed because it is too large Load Diff

1580
core/rtw_br_ext.c Normal file

File diff suppressed because it is too large Load Diff

1575
core/rtw_bt_mp.c Normal file

File diff suppressed because it is too large Load Diff

1763
core/rtw_btcoex.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
/******************************************************************************
*
* Copyright(c) 2013 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <hal_btcoex_wifionly.h>
#include <hal_data.h>
void rtw_btcoex_wifionly_switchband_notify(PADAPTER padapter)
{
hal_btcoex_wifionly_switchband_notify(padapter);
}
void rtw_btcoex_wifionly_scan_notify(PADAPTER padapter)
{
hal_btcoex_wifionly_scan_notify(padapter);
}
void rtw_btcoex_wifionly_hw_config(PADAPTER padapter)
{
hal_btcoex_wifionly_hw_config(padapter);
}
void rtw_btcoex_wifionly_initialize(PADAPTER padapter)
{
hal_btcoex_wifionly_initlizevariables(padapter);
}
void rtw_btcoex_wifionly_AntInfoSetting(PADAPTER padapter)
{
hal_btcoex_wifionly_AntInfoSetting(padapter);
}

5046
core/rtw_cmd.c Normal file

File diff suppressed because it is too large Load Diff

6189
core/rtw_debug.c Normal file

File diff suppressed because it is too large Load Diff

369
core/rtw_eeprom.c Normal file
View File

@@ -0,0 +1,369 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_EEPROM_C_
#include <drv_conf.h>
#include <osdep_service.h>
#include <drv_types.h>
void up_clk(_adapter *padapter, u16 *x)
{
*x = *x | _EESK;
rtw_write8(padapter, EE_9346CR, (u8)*x);
rtw_udelay_os(CLOCK_RATE);
}
void down_clk(_adapter *padapter, u16 *x)
{
*x = *x & ~_EESK;
rtw_write8(padapter, EE_9346CR, (u8)*x);
rtw_udelay_os(CLOCK_RATE);
}
void shift_out_bits(_adapter *padapter, u16 data, u16 count)
{
u16 x, mask;
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
mask = 0x01 << (count - 1);
x = rtw_read8(padapter, EE_9346CR);
x &= ~(_EEDO | _EEDI);
do {
x &= ~_EEDI;
if (data & mask)
x |= _EEDI;
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
rtw_write8(padapter, EE_9346CR, (u8)x);
rtw_udelay_os(CLOCK_RATE);
up_clk(padapter, &x);
down_clk(padapter, &x);
mask = mask >> 1;
} while (mask);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x &= ~_EEDI;
rtw_write8(padapter, EE_9346CR, (u8)x);
out:
return;
}
u16 shift_in_bits(_adapter *padapter)
{
u16 x, d = 0, i;
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x = rtw_read8(padapter, EE_9346CR);
x &= ~(_EEDO | _EEDI);
d = 0;
for (i = 0; i < 16; i++) {
d = d << 1;
up_clk(padapter, &x);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x = rtw_read8(padapter, EE_9346CR);
x &= ~(_EEDI);
if (x & _EEDO)
d |= 1;
down_clk(padapter, &x);
}
out:
return d;
}
void standby(_adapter *padapter)
{
u8 x;
x = rtw_read8(padapter, EE_9346CR);
x &= ~(_EECS | _EESK);
rtw_write8(padapter, EE_9346CR, x);
rtw_udelay_os(CLOCK_RATE);
x |= _EECS;
rtw_write8(padapter, EE_9346CR, x);
rtw_udelay_os(CLOCK_RATE);
}
u16 wait_eeprom_cmd_done(_adapter *padapter)
{
u8 x;
u16 i, res = _FALSE;
standby(padapter);
for (i = 0; i < 200; i++) {
x = rtw_read8(padapter, EE_9346CR);
if (x & _EEDO) {
res = _TRUE;
goto exit;
}
rtw_udelay_os(CLOCK_RATE);
}
exit:
return res;
}
void eeprom_clean(_adapter *padapter)
{
u16 x;
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x = rtw_read8(padapter, EE_9346CR);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x &= ~(_EECS | _EEDI);
rtw_write8(padapter, EE_9346CR, (u8)x);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
up_clk(padapter, &x);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
down_clk(padapter, &x);
out:
return;
}
void eeprom_write16(_adapter *padapter, u16 reg, u16 data)
{
u8 x;
#ifdef CONFIG_RTL8712
u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
tmp8_ori = rtw_read8(padapter, 0x102502f1);
tmp8_new = tmp8_ori & 0xf7;
if (tmp8_ori != tmp8_new) {
rtw_write8(padapter, 0x102502f1, tmp8_new);
}
tmp8_clk_ori = rtw_read8(padapter, 0x10250003);
tmp8_clk_new = tmp8_clk_ori | 0x20;
if (tmp8_clk_new != tmp8_clk_ori) {
rtw_write8(padapter, 0x10250003, tmp8_clk_new);
}
#endif
x = rtw_read8(padapter, EE_9346CR);
x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
x |= _EEM1 | _EECS;
rtw_write8(padapter, EE_9346CR, x);
shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
if (padapter->EepromAddressSize == 8) /* CF+ and SDIO */
shift_out_bits(padapter, 0, 6);
else /* USB */
shift_out_bits(padapter, 0, 4);
standby(padapter);
/* Commented out by rcnjko, 2004.0
* Erase this particular word. Write the erase opcode and register
* number in that order. The opcode is 3bits in length; reg is 6 bits long. */
/* shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
* shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
*
* if (wait_eeprom_cmd_done(Adapter ) == FALSE)
* {
* return;
* } */
standby(padapter);
/* write the new word to the EEPROM */
/* send the write opcode the EEPORM */
shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
/* select which word in the EEPROM that we are writing to. */
shift_out_bits(padapter, reg, padapter->EepromAddressSize);
/* write the data to the selected EEPROM word. */
shift_out_bits(padapter, data, 16);
if (wait_eeprom_cmd_done(padapter) == _FALSE)
goto exit;
standby(padapter);
shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
shift_out_bits(padapter, reg, 4);
eeprom_clean(padapter);
exit:
#ifdef CONFIG_RTL8712
if (tmp8_clk_new != tmp8_clk_ori)
rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
if (tmp8_new != tmp8_ori)
rtw_write8(padapter, 0x102502f1, tmp8_ori);
#endif
return;
}
u16 eeprom_read16(_adapter *padapter, u16 reg) /* ReadEEprom */
{
u16 x;
u16 data = 0;
#ifdef CONFIG_RTL8712
u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
tmp8_ori = rtw_read8(padapter, 0x102502f1);
tmp8_new = tmp8_ori & 0xf7;
if (tmp8_ori != tmp8_new) {
rtw_write8(padapter, 0x102502f1, tmp8_new);
}
tmp8_clk_ori = rtw_read8(padapter, 0x10250003);
tmp8_clk_new = tmp8_clk_ori | 0x20;
if (tmp8_clk_new != tmp8_clk_ori) {
rtw_write8(padapter, 0x10250003, tmp8_clk_new);
}
#endif
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
/* select EEPROM, reset bits, set _EECS */
x = rtw_read8(padapter, EE_9346CR);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
x |= _EEM1 | _EECS;
rtw_write8(padapter, EE_9346CR, (unsigned char)x);
/* write the read opcode and register number in that order */
/* The opcode is 3bits in length, reg is 6 bits long */
shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
shift_out_bits(padapter, reg, padapter->EepromAddressSize);
/* Now read the data (16 bits) in from the selected EEPROM word */
data = shift_in_bits(padapter);
eeprom_clean(padapter);
out:
#ifdef CONFIG_RTL8712
if (tmp8_clk_new != tmp8_clk_ori)
rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
if (tmp8_new != tmp8_ori)
rtw_write8(padapter, 0x102502f1, tmp8_ori);
#endif
return data;
}
/* From even offset */
void eeprom_read_sz(_adapter *padapter, u16 reg, u8 *data, u32 sz)
{
u16 x, data16;
u32 i;
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
/* select EEPROM, reset bits, set _EECS */
x = rtw_read8(padapter, EE_9346CR);
if (rtw_is_surprise_removed(padapter)) {
goto out;
}
x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
x |= _EEM1 | _EECS;
rtw_write8(padapter, EE_9346CR, (unsigned char)x);
/* write the read opcode and register number in that order */
/* The opcode is 3bits in length, reg is 6 bits long */
shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
shift_out_bits(padapter, reg, padapter->EepromAddressSize);
for (i = 0; i < sz; i += 2) {
data16 = shift_in_bits(padapter);
data[i] = data16 & 0xff;
data[i + 1] = data16 >> 8;
}
eeprom_clean(padapter);
out:
return;
}
/* addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg) */
u8 eeprom_read(_adapter *padapter, u32 addr_off, u8 sz, u8 *rbuf)
{
u8 quotient, remainder, addr_2align_odd;
u16 reg, stmp , i = 0, idx = 0;
reg = (u16)(addr_off >> 1);
addr_2align_odd = (u8)(addr_off & 0x1);
if (addr_2align_odd) { /* read that start at high part: e.g 1,3,5,7,9,... */
stmp = eeprom_read16(padapter, reg);
rbuf[idx++] = (u8)((stmp >> 8) & 0xff); /* return hogh-part of the short */
reg++;
sz--;
}
quotient = sz >> 1;
remainder = sz & 0x1;
for (i = 0 ; i < quotient; i++) {
stmp = eeprom_read16(padapter, reg + i);
rbuf[idx++] = (u8)(stmp & 0xff);
rbuf[idx++] = (u8)((stmp >> 8) & 0xff);
}
reg = reg + i;
if (remainder) { /* end of read at lower part of short : 0,2,4,6,... */
stmp = eeprom_read16(padapter, reg);
rbuf[idx] = (u8)(stmp & 0xff);
}
return _TRUE;
}
VOID read_eeprom_content(_adapter *padapter)
{
}

2859
core/rtw_ieee80211.c Normal file

File diff suppressed because it is too large Load Diff

696
core/rtw_io.c Normal file
View File

@@ -0,0 +1,696 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
/*
The purpose of rtw_io.c
a. provides the API
b. provides the protocol engine
c. provides the software interface between caller and the hardware interface
Compiler Flag Option:
1. CONFIG_SDIO_HCI:
a. USE_SYNC_IRP: Only sync operations are provided.
b. USE_ASYNC_IRP:Both sync/async operations are provided.
2. CONFIG_USB_HCI:
a. USE_ASYNC_IRP: Both sync/async operations are provided.
3. CONFIG_CFIO_HCI:
b. USE_SYNC_IRP: Only sync operations are provided.
Only sync read/rtw_write_mem operations are provided.
jackson@realtek.com.tw
*/
#define _RTW_IO_C_
#include <drv_types.h>
#include <hal_data.h>
#if defined(PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
#error "Shall be Linux or Windows, but not both!\n"
#endif
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_PLATFORM_RTL8197D)
#define rtw_le16_to_cpu(val) val
#define rtw_le32_to_cpu(val) val
#define rtw_cpu_to_le16(val) val
#define rtw_cpu_to_le32(val) val
#else
#define rtw_le16_to_cpu(val) le16_to_cpu(val)
#define rtw_le32_to_cpu(val) le32_to_cpu(val)
#define rtw_cpu_to_le16(val) cpu_to_le16(val)
#define rtw_cpu_to_le32(val) cpu_to_le32(val)
#endif
u8 _rtw_read8(_adapter *adapter, u32 addr)
{
u8 r_val;
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u8(*_read8)(struct intf_hdl *pintfhdl, u32 addr);
_read8 = pintfhdl->io_ops._read8;
r_val = _read8(pintfhdl, addr);
return r_val;
}
u16 _rtw_read16(_adapter *adapter, u32 addr)
{
u16 r_val;
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u16(*_read16)(struct intf_hdl *pintfhdl, u32 addr);
_read16 = pintfhdl->io_ops._read16;
r_val = _read16(pintfhdl, addr);
return rtw_le16_to_cpu(r_val);
}
u32 _rtw_read32(_adapter *adapter, u32 addr)
{
u32 r_val;
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u32(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
_read32 = pintfhdl->io_ops._read32;
r_val = _read32(pintfhdl, addr);
return rtw_le32_to_cpu(r_val);
}
int _rtw_write8(_adapter *adapter, u32 addr, u8 val)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
int ret;
_write8 = pintfhdl->io_ops._write8;
ret = _write8(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write16(_adapter *adapter, u32 addr, u16 val)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
int ret;
_write16 = pintfhdl->io_ops._write16;
val = rtw_cpu_to_le16(val);
ret = _write16(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write32(_adapter *adapter, u32 addr, u32 val)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
int ret;
_write32 = pintfhdl->io_ops._write32;
val = rtw_cpu_to_le32(val);
ret = _write32(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_writeN(_adapter *adapter, u32 addr , u32 length , u8 *pdata)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = (struct intf_hdl *)(&(pio_priv->intf));
int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata);
int ret;
_writeN = pintfhdl->io_ops._writeN;
ret = _writeN(pintfhdl, addr, length, pdata);
return RTW_STATUS_CODE(ret);
}
#ifdef CONFIG_SDIO_HCI
u8 _rtw_sd_f0_read8(_adapter *adapter, u32 addr)
{
u8 r_val = 0x00;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u8(*_sd_f0_read8)(struct intf_hdl *pintfhdl, u32 addr);
_sd_f0_read8 = pintfhdl->io_ops._sd_f0_read8;
if (_sd_f0_read8)
r_val = _sd_f0_read8(pintfhdl, addr);
else
RTW_WARN(FUNC_ADPT_FMT" _sd_f0_read8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return r_val;
}
#ifdef CONFIG_SDIO_INDIRECT_ACCESS
u8 _rtw_sd_iread8(_adapter *adapter, u32 addr)
{
u8 r_val = 0x00;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u8(*_sd_iread8)(struct intf_hdl *pintfhdl, u32 addr);
_sd_iread8 = pintfhdl->io_ops._sd_iread8;
if (_sd_iread8)
r_val = _sd_iread8(pintfhdl, addr);
else
RTW_ERR(FUNC_ADPT_FMT" _sd_iread8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return r_val;
}
u16 _rtw_sd_iread16(_adapter *adapter, u32 addr)
{
u16 r_val = 0x00;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u16(*_sd_iread16)(struct intf_hdl *pintfhdl, u32 addr);
_sd_iread16 = pintfhdl->io_ops._sd_iread16;
if (_sd_iread16)
r_val = _sd_iread16(pintfhdl, addr);
else
RTW_ERR(FUNC_ADPT_FMT" _sd_iread16 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return r_val;
}
u32 _rtw_sd_iread32(_adapter *adapter, u32 addr)
{
u32 r_val = 0x00;
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u32(*_sd_iread32)(struct intf_hdl *pintfhdl, u32 addr);
_sd_iread32 = pintfhdl->io_ops._sd_iread32;
if (_sd_iread32)
r_val = _sd_iread32(pintfhdl, addr);
else
RTW_ERR(FUNC_ADPT_FMT" _sd_iread32 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return r_val;
}
int _rtw_sd_iwrite8(_adapter *adapter, u32 addr, u8 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_sd_iwrite8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
int ret = -1;
_sd_iwrite8 = pintfhdl->io_ops._sd_iwrite8;
if (_sd_iwrite8)
ret = _sd_iwrite8(pintfhdl, addr, val);
else
RTW_ERR(FUNC_ADPT_FMT" _sd_iwrite8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return RTW_STATUS_CODE(ret);
}
int _rtw_sd_iwrite16(_adapter *adapter, u32 addr, u16 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_sd_iwrite16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
int ret = -1;
_sd_iwrite16 = pintfhdl->io_ops._sd_iwrite16;
if (_sd_iwrite16)
ret = _sd_iwrite16(pintfhdl, addr, val);
else
RTW_ERR(FUNC_ADPT_FMT" _sd_iwrite16 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return RTW_STATUS_CODE(ret);
}
int _rtw_sd_iwrite32(_adapter *adapter, u32 addr, u32 val)
{
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_sd_iwrite32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
int ret = -1;
_sd_iwrite32 = pintfhdl->io_ops._sd_iwrite32;
if (_sd_iwrite32)
ret = _sd_iwrite32(pintfhdl, addr, val);
else
RTW_ERR(FUNC_ADPT_FMT" _sd_iwrite32 callback is NULL\n", FUNC_ADPT_ARG(adapter));
return RTW_STATUS_CODE(ret);
}
#endif /* CONFIG_SDIO_INDIRECT_ACCESS */
#endif /* CONFIG_SDIO_HCI */
int _rtw_write8_async(_adapter *adapter, u32 addr, u8 val)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
int ret;
_write8_async = pintfhdl->io_ops._write8_async;
ret = _write8_async(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write16_async(_adapter *adapter, u32 addr, u16 val)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
int ret;
_write16_async = pintfhdl->io_ops._write16_async;
val = rtw_cpu_to_le16(val);
ret = _write16_async(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
int _rtw_write32_async(_adapter *adapter, u32 addr, u32 val)
{
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
int ret;
_write32_async = pintfhdl->io_ops._write32_async;
val = rtw_cpu_to_le32(val);
ret = _write32_async(pintfhdl, addr, val);
return RTW_STATUS_CODE(ret);
}
void _rtw_read_mem(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
if (RTW_CANNOT_RUN(adapter)) {
return;
}
_read_mem = pintfhdl->io_ops._read_mem;
_read_mem(pintfhdl, addr, cnt, pmem);
}
void _rtw_write_mem(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
_write_mem = pintfhdl->io_ops._write_mem;
_write_mem(pintfhdl, addr, cnt, pmem);
}
void _rtw_read_port(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
u32(*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
if (RTW_CANNOT_RUN(adapter)) {
return;
}
_read_port = pintfhdl->io_ops._read_port;
_read_port(pintfhdl, addr, cnt, pmem);
}
void _rtw_read_port_cancel(_adapter *adapter)
{
void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
_read_port_cancel = pintfhdl->io_ops._read_port_cancel;
RTW_DISABLE_FUNC(adapter, DF_RX_BIT);
if (_read_port_cancel)
_read_port_cancel(pintfhdl);
}
u32 _rtw_write_port(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
{
u32(*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
/* struct io_queue *pio_queue = (struct io_queue *)adapter->pio_queue; */
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
u32 ret = _SUCCESS;
_write_port = pintfhdl->io_ops._write_port;
ret = _write_port(pintfhdl, addr, cnt, pmem);
return ret;
}
u32 _rtw_write_port_and_wait(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem, int timeout_ms)
{
int ret = _SUCCESS;
struct xmit_buf *pxmitbuf = (struct xmit_buf *)pmem;
struct submit_ctx sctx;
rtw_sctx_init(&sctx, timeout_ms);
pxmitbuf->sctx = &sctx;
ret = _rtw_write_port(adapter, addr, cnt, pmem);
if (ret == _SUCCESS)
ret = rtw_sctx_wait(&sctx, __func__);
return ret;
}
void _rtw_write_port_cancel(_adapter *adapter)
{
void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
struct io_priv *pio_priv = &adapter->iopriv;
struct intf_hdl *pintfhdl = &(pio_priv->intf);
_write_port_cancel = pintfhdl->io_ops._write_port_cancel;
RTW_DISABLE_FUNC(adapter, DF_TX_BIT);
if (_write_port_cancel)
_write_port_cancel(pintfhdl);
}
int rtw_init_io_priv(_adapter *padapter, void (*set_intf_ops)(_adapter *padapter, struct _io_ops *pops))
{
struct io_priv *piopriv = &padapter->iopriv;
struct intf_hdl *pintf = &piopriv->intf;
if (set_intf_ops == NULL)
return _FAIL;
piopriv->padapter = padapter;
pintf->padapter = padapter;
pintf->pintf_dev = adapter_to_dvobj(padapter);
set_intf_ops(padapter, &pintf->io_ops);
return _SUCCESS;
}
/*
* Increase and check if the continual_io_error of this @param dvobjprive is larger than MAX_CONTINUAL_IO_ERR
* @return _TRUE:
* @return _FALSE:
*/
int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj)
{
int ret = _FALSE;
int value;
value = ATOMIC_INC_RETURN(&dvobj->continual_io_error);
if (value > MAX_CONTINUAL_IO_ERR) {
RTW_INFO("[dvobj:%p][ERROR] continual_io_error:%d > %d\n", dvobj, value, MAX_CONTINUAL_IO_ERR);
ret = _TRUE;
} else {
/* RTW_INFO("[dvobj:%p] continual_io_error:%d\n", dvobj, value); */
}
return ret;
}
/*
* Set the continual_io_error of this @param dvobjprive to 0
*/
void rtw_reset_continual_io_error(struct dvobj_priv *dvobj)
{
ATOMIC_SET(&dvobj->continual_io_error, 0);
}
#ifdef DBG_IO
u32 read_sniff_ranges[][2] = {
/* {0x520, 0x523}, */
};
u32 write_sniff_ranges[][2] = {
/* {0x520, 0x523}, */
/* {0x4c, 0x4c}, */
};
int read_sniff_num = sizeof(read_sniff_ranges) / sizeof(u32) / 2;
int write_sniff_num = sizeof(write_sniff_ranges) / sizeof(u32) / 2;
bool match_read_sniff_ranges(u32 addr, u16 len)
{
int i;
for (i = 0; i < read_sniff_num; i++) {
if (addr + len > read_sniff_ranges[i][0] && addr <= read_sniff_ranges[i][1])
return _TRUE;
}
return _FALSE;
}
bool match_write_sniff_ranges(u32 addr, u16 len)
{
int i;
for (i = 0; i < write_sniff_num; i++) {
if (addr + len > write_sniff_ranges[i][0] && addr <= write_sniff_ranges[i][1])
return _TRUE;
}
return _FALSE;
}
struct rf_sniff_ent {
u8 path;
u16 reg;
u32 mask;
};
struct rf_sniff_ent rf_read_sniff_ranges[] = {
/* example for all path addr 0x55 with all RF Reg mask */
/* {MAX_RF_PATH, 0x55, bRFRegOffsetMask}, */
};
struct rf_sniff_ent rf_write_sniff_ranges[] = {
/* example for all path addr 0x55 with all RF Reg mask */
/* {MAX_RF_PATH, 0x55, bRFRegOffsetMask}, */
};
int rf_read_sniff_num = sizeof(rf_read_sniff_ranges) / sizeof(struct rf_sniff_ent);
int rf_write_sniff_num = sizeof(rf_write_sniff_ranges) / sizeof(struct rf_sniff_ent);
bool match_rf_read_sniff_ranges(u8 path, u32 addr, u32 mask)
{
int i;
for (i = 0; i < rf_read_sniff_num; i++) {
if (rf_read_sniff_ranges[i].path == MAX_RF_PATH || rf_read_sniff_ranges[i].path == path)
if (addr == rf_read_sniff_ranges[i].reg && (mask & rf_read_sniff_ranges[i].mask))
return _TRUE;
}
return _FALSE;
}
bool match_rf_write_sniff_ranges(u8 path, u32 addr, u32 mask)
{
int i;
for (i = 0; i < rf_write_sniff_num; i++) {
if (rf_write_sniff_ranges[i].path == MAX_RF_PATH || rf_write_sniff_ranges[i].path == path)
if (addr == rf_write_sniff_ranges[i].reg && (mask & rf_write_sniff_ranges[i].mask))
return _TRUE;
}
return _FALSE;
}
u8 dbg_rtw_read8(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u8 val = _rtw_read8(adapter, addr);
if (match_read_sniff_ranges(addr, 1))
RTW_INFO("DBG_IO %s:%d rtw_read8(0x%04x) return 0x%02x\n", caller, line, addr, val);
return val;
}
u16 dbg_rtw_read16(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u16 val = _rtw_read16(adapter, addr);
if (match_read_sniff_ranges(addr, 2))
RTW_INFO("DBG_IO %s:%d rtw_read16(0x%04x) return 0x%04x\n", caller, line, addr, val);
return val;
}
u32 dbg_rtw_read32(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u32 val = _rtw_read32(adapter, addr);
if (match_read_sniff_ranges(addr, 4))
RTW_INFO("DBG_IO %s:%d rtw_read32(0x%04x) return 0x%08x\n", caller, line, addr, val);
return val;
}
int dbg_rtw_write8(_adapter *adapter, u32 addr, u8 val, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 1))
RTW_INFO("DBG_IO %s:%d rtw_write8(0x%04x, 0x%02x)\n", caller, line, addr, val);
return _rtw_write8(adapter, addr, val);
}
int dbg_rtw_write16(_adapter *adapter, u32 addr, u16 val, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 2))
RTW_INFO("DBG_IO %s:%d rtw_write16(0x%04x, 0x%04x)\n", caller, line, addr, val);
return _rtw_write16(adapter, addr, val);
}
int dbg_rtw_write32(_adapter *adapter, u32 addr, u32 val, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 4))
RTW_INFO("DBG_IO %s:%d rtw_write32(0x%04x, 0x%08x)\n", caller, line, addr, val);
return _rtw_write32(adapter, addr, val);
}
int dbg_rtw_writeN(_adapter *adapter, u32 addr , u32 length , u8 *data, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, length))
RTW_INFO("DBG_IO %s:%d rtw_writeN(0x%04x, %u)\n", caller, line, addr, length);
return _rtw_writeN(adapter, addr, length, data);
}
#ifdef CONFIG_SDIO_HCI
u8 dbg_rtw_sd_f0_read8(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u8 val = _rtw_sd_f0_read8(adapter, addr);
#if 0
if (match_read_sniff_ranges(addr, 1))
RTW_INFO("DBG_IO %s:%d rtw_sd_f0_read8(0x%04x) return 0x%02x\n", caller, line, addr, val);
#endif
return val;
}
#ifdef CONFIG_SDIO_INDIRECT_ACCESS
u8 dbg_rtw_sd_iread8(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u8 val = rtw_sd_iread8(adapter, addr);
if (match_read_sniff_ranges(addr, 1))
RTW_INFO("DBG_IO %s:%d rtw_sd_iread8(0x%04x) return 0x%02x\n", caller, line, addr, val);
return val;
}
u16 dbg_rtw_sd_iread16(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u16 val = _rtw_sd_iread16(adapter, addr);
if (match_read_sniff_ranges(addr, 2))
RTW_INFO("DBG_IO %s:%d rtw_sd_iread16(0x%04x) return 0x%04x\n", caller, line, addr, val);
return val;
}
u32 dbg_rtw_sd_iread32(_adapter *adapter, u32 addr, const char *caller, const int line)
{
u32 val = _rtw_sd_iread32(adapter, addr);
if (match_read_sniff_ranges(addr, 4))
RTW_INFO("DBG_IO %s:%d rtw_sd_iread32(0x%04x) return 0x%08x\n", caller, line, addr, val);
return val;
}
int dbg_rtw_sd_iwrite8(_adapter *adapter, u32 addr, u8 val, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 1))
RTW_INFO("DBG_IO %s:%d rtw_sd_iwrite8(0x%04x, 0x%02x)\n", caller, line, addr, val);
return _rtw_sd_iwrite8(adapter, addr, val);
}
int dbg_rtw_sd_iwrite16(_adapter *adapter, u32 addr, u16 val, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 2))
RTW_INFO("DBG_IO %s:%d rtw_sd_iwrite16(0x%04x, 0x%04x)\n", caller, line, addr, val);
return _rtw_sd_iwrite16(adapter, addr, val);
}
int dbg_rtw_sd_iwrite32(_adapter *adapter, u32 addr, u32 val, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 4))
RTW_INFO("DBG_IO %s:%d rtw_sd_iwrite32(0x%04x, 0x%08x)\n", caller, line, addr, val);
return _rtw_sd_iwrite32(adapter, addr, val);
}
#endif /* CONFIG_SDIO_INDIRECT_ACCESS */
#endif /* CONFIG_SDIO_HCI */
#endif

166
core/rtw_ioctl_query.c Normal file
View File

@@ -0,0 +1,166 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_IOCTL_QUERY_C_
#include <drv_types.h>
#ifdef PLATFORM_WINDOWS
/*
* Added for WPA2-PSK, by Annie, 2005-09-20.
* */
u8
query_802_11_capability(
_adapter *Adapter,
u8 *pucBuf,
u32 *pulOutLen
)
{
static NDIS_802_11_AUTHENTICATION_ENCRYPTION szAuthEnc[] = {
{Ndis802_11AuthModeOpen, Ndis802_11EncryptionDisabled},
{Ndis802_11AuthModeOpen, Ndis802_11Encryption1Enabled},
{Ndis802_11AuthModeShared, Ndis802_11EncryptionDisabled},
{Ndis802_11AuthModeShared, Ndis802_11Encryption1Enabled},
{Ndis802_11AuthModeWPA, Ndis802_11Encryption2Enabled},
{Ndis802_11AuthModeWPA, Ndis802_11Encryption3Enabled},
{Ndis802_11AuthModeWPAPSK, Ndis802_11Encryption2Enabled},
{Ndis802_11AuthModeWPAPSK, Ndis802_11Encryption3Enabled},
{Ndis802_11AuthModeWPANone, Ndis802_11Encryption2Enabled},
{Ndis802_11AuthModeWPANone, Ndis802_11Encryption3Enabled},
{Ndis802_11AuthModeWPA2, Ndis802_11Encryption2Enabled},
{Ndis802_11AuthModeWPA2, Ndis802_11Encryption3Enabled},
{Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption2Enabled},
{Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption3Enabled}
};
static ULONG ulNumOfPairSupported = sizeof(szAuthEnc) / sizeof(NDIS_802_11_AUTHENTICATION_ENCRYPTION);
NDIS_802_11_CAPABILITY *pCap = (NDIS_802_11_CAPABILITY *)pucBuf;
u8 *pucAuthEncryptionSupported = (u8 *) pCap->AuthenticationEncryptionSupported;
pCap->Length = sizeof(NDIS_802_11_CAPABILITY);
if (ulNumOfPairSupported > 1)
pCap->Length += (ulNumOfPairSupported - 1) * sizeof(NDIS_802_11_AUTHENTICATION_ENCRYPTION);
pCap->Version = 2;
pCap->NoOfPMKIDs = NUM_PMKID_CACHE;
pCap->NoOfAuthEncryptPairsSupported = ulNumOfPairSupported;
if (sizeof(szAuthEnc) <= 240) /* 240 = 256 - 4*4 */ { /* SecurityInfo.szCapability: only 256 bytes in size. */
_rtw_memcpy(pucAuthEncryptionSupported, (u8 *)szAuthEnc, sizeof(szAuthEnc));
*pulOutLen = pCap->Length;
return _TRUE;
} else {
*pulOutLen = 0;
return _FALSE;
}
}
u8 query_802_11_association_information(_adapter *padapter, PNDIS_802_11_ASSOCIATION_INFORMATION pAssocInfo)
{
struct wlan_network *tgt_network;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct security_priv *psecuritypriv = &(padapter->securitypriv);
WLAN_BSSID_EX *psecnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
u8 *pDest = (u8 *)pAssocInfo + sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
unsigned char i, *auth_ie, *supp_ie;
/* NdisZeroMemory(pAssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION)); */
_rtw_memset(pAssocInfo, 0, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION));
/* pAssocInfo->Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION); */
/* ------------------------------------------------------ */
/* Association Request related information */
/* ------------------------------------------------------ */
/* Req_1. AvailableRequestFixedIEs */
if (psecnetwork != NULL) {
pAssocInfo->AvailableRequestFixedIEs |= NDIS_802_11_AI_REQFI_CAPABILITIES | NDIS_802_11_AI_REQFI_CURRENTAPADDRESS;
pAssocInfo->RequestFixedIEs.Capabilities = (unsigned short) *&psecnetwork->IEs[10];
_rtw_memcpy(pAssocInfo->RequestFixedIEs.CurrentAPAddress,
&psecnetwork->MacAddress, 6);
pAssocInfo->OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING | _FW_LINKED) == _TRUE) {
if (psecuritypriv->ndisauthtype >= Ndis802_11AuthModeWPA2)
pDest[0] = 48; /* RSN Information Element */
else
pDest[0] = 221; /* WPA(SSN) Information Element */
supp_ie = &psecuritypriv->supplicant_ie[0];
i = 13; /* 0~11 is fixed information element */
while ((i < supp_ie[0]) && (i < 256)) {
if ((unsigned char)supp_ie[i] == pDest[0]) {
_rtw_memcpy((u8 *)(pDest),
&supp_ie[i],
supp_ie[1 + i] + 2);
break;
}
i = i + supp_ie[i + 1] + 2;
if (supp_ie[1 + i] == 0)
i = i + 1;
}
pAssocInfo->RequestIELength += (2 + supp_ie[1 + i]); /* (2 + psecnetwork->IEs[1+i]+4); */
}
}
/* ------------------------------------------------------ */
/* Association Response related information */
/* ------------------------------------------------------ */
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
tgt_network = &(pmlmepriv->cur_network);
if (tgt_network != NULL) {
pAssocInfo->AvailableResponseFixedIEs =
NDIS_802_11_AI_RESFI_CAPABILITIES
| NDIS_802_11_AI_RESFI_ASSOCIATIONID
;
pAssocInfo->ResponseFixedIEs.Capabilities = (unsigned short) *&tgt_network->network.IEs[10];
pAssocInfo->ResponseFixedIEs.StatusCode = 0;
pAssocInfo->ResponseFixedIEs.AssociationId = (unsigned short) tgt_network->aid;
pDest = (u8 *)pAssocInfo + sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAssocInfo->RequestIELength;
auth_ie = &psecuritypriv->authenticator_ie[0];
i = auth_ie[0] - 12;
if (i > 0) {
_rtw_memcpy((u8 *)&pDest[0], &auth_ie[1], i);
pAssocInfo->ResponseIELength = i;
}
pAssocInfo->OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAssocInfo->RequestIELength;
}
}
return _TRUE;
}
#endif

901
core/rtw_ioctl_rtl.c Normal file
View File

@@ -0,0 +1,901 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_IOCTL_RTL_C_
#include <drv_types.h>
#ifdef CONFIG_MP_INCLUDED
#include <rtw_mp_ioctl.h>
#endif
struct oid_obj_priv oid_rtl_seg_01_01[] = {
{1, &oid_null_function}, /* 0x80 */
{1, &oid_null_function}, /* 0x81 */
{1, &oid_null_function}, /* 0x82 */
{1, &oid_null_function}, /* 0x83 */ /* OID_RT_SET_SNIFFER_MODE */
{1, &oid_rt_get_signal_quality_hdl}, /* 0x84 */
{1, &oid_rt_get_small_packet_crc_hdl}, /* 0x85 */
{1, &oid_rt_get_middle_packet_crc_hdl}, /* 0x86 */
{1, &oid_rt_get_large_packet_crc_hdl}, /* 0x87 */
{1, &oid_rt_get_tx_retry_hdl}, /* 0x88 */
{1, &oid_rt_get_rx_retry_hdl}, /* 0x89 */
{1, &oid_rt_pro_set_fw_dig_state_hdl}, /* 0x8A */
{1, &oid_rt_pro_set_fw_ra_state_hdl} , /* 0x8B */
{1, &oid_null_function}, /* 0x8C */
{1, &oid_null_function}, /* 0x8D */
{1, &oid_null_function}, /* 0x8E */
{1, &oid_null_function}, /* 0x8F */
{1, &oid_rt_get_rx_total_packet_hdl}, /* 0x90 */
{1, &oid_rt_get_tx_beacon_ok_hdl}, /* 0x91 */
{1, &oid_rt_get_tx_beacon_err_hdl}, /* 0x92 */
{1, &oid_rt_get_rx_icv_err_hdl}, /* 0x93 */
{1, &oid_rt_set_encryption_algorithm_hdl}, /* 0x94 */
{1, &oid_null_function}, /* 0x95 */
{1, &oid_rt_get_preamble_mode_hdl}, /* 0x96 */
{1, &oid_null_function}, /* 0x97 */
{1, &oid_rt_get_ap_ip_hdl}, /* 0x98 */
{1, &oid_rt_get_channelplan_hdl}, /* 0x99 */
{1, &oid_rt_set_preamble_mode_hdl}, /* 0x9A */
{1, &oid_rt_set_bcn_intvl_hdl}, /* 0x9B */
{1, &oid_null_function}, /* 0x9C */
{1, &oid_rt_dedicate_probe_hdl}, /* 0x9D */
{1, &oid_null_function}, /* 0x9E */
{1, &oid_null_function}, /* 0x9F */
{1, &oid_null_function}, /* 0xA0 */
{1, &oid_null_function}, /* 0xA1 */
{1, &oid_null_function}, /* 0xA2 */
{1, &oid_null_function}, /* 0xA3 */
{1, &oid_null_function}, /* 0xA4 */
{1, &oid_null_function}, /* 0xA5 */
{1, &oid_null_function}, /* 0xA6 */
{1, &oid_rt_get_total_tx_bytes_hdl}, /* 0xA7 */
{1, &oid_rt_get_total_rx_bytes_hdl}, /* 0xA8 */
{1, &oid_rt_current_tx_power_level_hdl}, /* 0xA9 */
{1, &oid_rt_get_enc_key_mismatch_count_hdl}, /* 0xAA */
{1, &oid_rt_get_enc_key_match_count_hdl}, /* 0xAB */
{1, &oid_rt_get_channel_hdl}, /* 0xAC */
{1, &oid_rt_set_channelplan_hdl}, /* 0xAD */
{1, &oid_rt_get_hardware_radio_off_hdl}, /* 0xAE */
{1, &oid_null_function}, /* 0xAF */
{1, &oid_null_function}, /* 0xB0 */
{1, &oid_null_function}, /* 0xB1 */
{1, &oid_null_function}, /* 0xB2 */
{1, &oid_null_function}, /* 0xB3 */
{1, &oid_rt_get_key_mismatch_hdl}, /* 0xB4 */
{1, &oid_null_function}, /* 0xB5 */
{1, &oid_null_function}, /* 0xB6 */
{1, &oid_null_function}, /* 0xB7 */
{1, &oid_null_function}, /* 0xB8 */
{1, &oid_null_function}, /* 0xB9 */
{1, &oid_null_function}, /* 0xBA */
{1, &oid_rt_supported_wireless_mode_hdl}, /* 0xBB */
{1, &oid_rt_get_channel_list_hdl}, /* 0xBC */
{1, &oid_rt_get_scan_in_progress_hdl}, /* 0xBD */
{1, &oid_null_function}, /* 0xBE */
{1, &oid_null_function}, /* 0xBF */
{1, &oid_null_function}, /* 0xC0 */
{1, &oid_rt_forced_data_rate_hdl}, /* 0xC1 */
{1, &oid_rt_wireless_mode_for_scan_list_hdl}, /* 0xC2 */
{1, &oid_rt_get_bss_wireless_mode_hdl}, /* 0xC3 */
{1, &oid_rt_scan_with_magic_packet_hdl}, /* 0xC4 */
{1, &oid_null_function}, /* 0xC5 */
{1, &oid_null_function}, /* 0xC6 */
{1, &oid_null_function}, /* 0xC7 */
{1, &oid_null_function}, /* 0xC8 */
{1, &oid_null_function}, /* 0xC9 */
{1, &oid_null_function}, /* 0xCA */
{1, &oid_null_function}, /* 0xCB */
{1, &oid_null_function}, /* 0xCC */
{1, &oid_null_function}, /* 0xCD */
{1, &oid_null_function}, /* 0xCE */
{1, &oid_null_function}, /* 0xCF */
};
struct oid_obj_priv oid_rtl_seg_01_03[] = {
{1, &oid_rt_ap_get_associated_station_list_hdl}, /* 0x00 */
{1, &oid_null_function}, /* 0x01 */
{1, &oid_rt_ap_switch_into_ap_mode_hdl}, /* 0x02 */
{1, &oid_null_function}, /* 0x03 */
{1, &oid_rt_ap_supported_hdl}, /* 0x04 */
{1, &oid_rt_ap_set_passphrase_hdl}, /* 0x05 */
};
struct oid_obj_priv oid_rtl_seg_01_11[] = {
{1, &oid_null_function}, /* 0xC0 OID_RT_PRO_RX_FILTER */
{1, &oid_null_function}, /* 0xC1 OID_CE_USB_WRITE_REGISTRY */
{1, &oid_null_function}, /* 0xC2 OID_CE_USB_READ_REGISTRY */
{1, &oid_null_function}, /* 0xC3 OID_RT_PRO_SET_INITIAL_GAIN */
{1, &oid_null_function}, /* 0xC4 OID_RT_PRO_SET_BB_RF_STANDBY_MODE */
{1, &oid_null_function}, /* 0xC5 OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE */
{1, &oid_null_function}, /* 0xC6 OID_RT_PRO_SET_TX_CHARGE_PUMP */
{1, &oid_null_function}, /* 0xC7 OID_RT_PRO_SET_RX_CHARGE_PUMP */
{1, &oid_rt_pro_rf_write_registry_hdl}, /* 0xC8 */
{1, &oid_rt_pro_rf_read_registry_hdl}, /* 0xC9 */
{1, &oid_null_function} /* 0xCA OID_RT_PRO_QUERY_RF_TYPE */
};
struct oid_obj_priv oid_rtl_seg_03_00[] = {
{1, &oid_null_function}, /* 0x00 */
{1, &oid_rt_get_connect_state_hdl}, /* 0x01 */
{1, &oid_null_function}, /* 0x02 */
{1, &oid_null_function}, /* 0x03 */
{1, &oid_rt_set_default_key_id_hdl}, /* 0x04 */
};
/* ************** oid_rtl_seg_01_01 section start ************** */
NDIS_STATUS oid_rt_pro_set_fw_dig_state_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
#if 0
PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
_irqL oldirql;
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
_irqlevel_changed_(&oldirql, LOWER);
if (poid_par_priv->information_buf_len >= sizeof(struct setdig_parm)) {
/* DEBUG_ERR(("===> oid_rt_pro_set_fw_dig_state_hdl. type:0x%02x.\n",*((unsigned char*)poid_par_priv->information_buf ))); */
if (!rtw_setfwdig_cmd(Adapter, *((unsigned char *)poid_par_priv->information_buf)))
status = NDIS_STATUS_NOT_ACCEPTED;
} else
status = NDIS_STATUS_NOT_ACCEPTED;
_irqlevel_changed_(&oldirql, RAISE);
#endif
return status;
}
/* ----------------------------------------------------------------------------- */
NDIS_STATUS oid_rt_pro_set_fw_ra_state_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
#if 0
PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
_irqL oldirql;
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
_irqlevel_changed_(&oldirql, LOWER);
if (poid_par_priv->information_buf_len >= sizeof(struct setra_parm)) {
/* DEBUG_ERR(("===> oid_rt_pro_set_fw_ra_state_hdl. type:0x%02x.\n",*((unsigned char*)poid_par_priv->information_buf ))); */
if (!rtw_setfwra_cmd(Adapter, *((unsigned char *)poid_par_priv->information_buf)))
status = NDIS_STATUS_NOT_ACCEPTED;
} else
status = NDIS_STATUS_NOT_ACCEPTED;
_irqlevel_changed_(&oldirql, RAISE);
#endif
return status;
}
/* ----------------------------------------------------------------------------- */
NDIS_STATUS oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
/* DEBUG_ERR(("<**********************oid_rt_get_signal_quality_hdl\n")); */
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
#if 0
if (pMgntInfo->mAssoc || pMgntInfo->mIbss) {
ulInfo = pAdapter->RxStats.SignalQuality;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else {
ulInfo = 0xffffffff; /* It stands for -1 in 4-byte integer. */
}
break;
#endif
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
*(ULONG *)poid_par_priv->information_buf = padapter->recvpriv.rx_smallpacket_crcerr;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
*(ULONG *)poid_par_priv->information_buf = padapter->recvpriv.rx_middlepacket_crcerr;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
*(ULONG *)poid_par_priv->information_buf = padapter->recvpriv.rx_largepacket_crcerr;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
*(u64 *)poid_par_priv->information_buf = padapter->recvpriv.rx_pkts + padapter->recvpriv.rx_drop;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(u32)) {
/* _rtw_memcpy(*(uint *)poid_par_priv->information_buf,padapter->recvpriv.rx_icv_err,sizeof(u32)); */
*(uint *)poid_par_priv->information_buf = padapter->recvpriv.rx_icv_err;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH ;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
ULONG preamblemode = 0 ;
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
if (padapter->registrypriv.preamble == PREAMBLE_LONG)
preamblemode = 0;
else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
preamblemode = 1;
else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
preamblemode = 2;
*(ULONG *)poid_par_priv->information_buf = preamblemode ;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH ;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
*(u16 *)poid_par_priv->information_buf = rfctl->ChannelPlan;
return status;
}
NDIS_STATUS oid_rt_set_channelplan_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
rfctl->ChannelPlan = *(u16 *)poid_par_priv->information_buf;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_set_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
ULONG preamblemode = 0;
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
preamblemode = *(ULONG *)poid_par_priv->information_buf ;
if (preamblemode == 0)
padapter->registrypriv.preamble = PREAMBLE_LONG;
else if (preamblemode == 1)
padapter->registrypriv.preamble = PREAMBLE_AUTO;
else if (preamblemode == 2)
padapter->registrypriv.preamble = PREAMBLE_SHORT;
*(ULONG *)poid_par_priv->information_buf = preamblemode ;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH ;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_dedicate_probe_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
*(u64 *)poid_par_priv->information_buf = padapter->xmitpriv.tx_bytes;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH ;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
/* _rtw_memcpy(*(uint *)poid_par_priv->information_buf,padapter->recvpriv.rx_icv_err,sizeof(u32)); */
*(u64 *)poid_par_priv->information_buf = padapter->recvpriv.rx_bytes;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH ;
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_current_tx_power_level_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
NDIS_STATUS oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
NDIS_802_11_CONFIGURATION *pnic_Config;
ULONG channelnum;
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
pnic_Config = &pmlmepriv->cur_network.network.Configuration;
else
pnic_Config = &padapter->registrypriv.dev_network.Configuration;
channelnum = pnic_Config->DSConfig;
*(ULONG *)poid_par_priv->information_buf = channelnum;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
return status;
}
NDIS_STATUS oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_supported_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
ULONG ulInfo = 0 ;
/* DEBUG_ERR(("<**********************oid_rt_supported_wireless_mode_hdl\n")); */
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
if (poid_par_priv->information_buf_len >= sizeof(ULONG)) {
ulInfo |= 0x0100; /* WIRELESS_MODE_B */
ulInfo |= 0x0200; /* WIRELESS_MODE_G */
ulInfo |= 0x0400; /* WIRELESS_MODE_A */
*(ULONG *) poid_par_priv->information_buf = ulInfo;
/* DEBUG_ERR(("<===oid_rt_supported_wireless_mode %x\n",ulInfo)); */
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
} else
status = NDIS_STATUS_INVALID_LENGTH;
return status;
}
NDIS_STATUS oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
NDIS_STATUS oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
NDIS_STATUS oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
/* ************** oid_rtl_seg_01_01 section end ************** */
/* ************** oid_rtl_seg_01_03 section start ************** */
NDIS_STATUS oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
NDIS_STATUS oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
NDIS_STATUS oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
return status;
}
NDIS_STATUS oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
/* ************** oid_rtl_seg_01_03 section end ************** */
/* **************** oid_rtl_seg_01_11 section start **************** */
NDIS_STATUS oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
_irqL oldirql;
/* DEBUG_ERR(("<**********************oid_rt_pro_rf_write_registry_hdl\n")); */
if (poid_par_priv->type_of_oid != SET_OID) { /* QUERY_OID */
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
_irqlevel_changed_(&oldirql, LOWER);
if (poid_par_priv->information_buf_len == (sizeof(unsigned long) * 3)) {
/* RegOffsetValue - The offset of RF register to write. */
/* RegDataWidth - The data width of RF register to write. */
/* RegDataValue - The value to write. */
/* RegOffsetValue = *((unsigned long*)InformationBuffer); */
/* RegDataWidth = *((unsigned long*)InformationBuffer+1); */
/* RegDataValue = *((unsigned long*)InformationBuffer+2); */
if (!rtw_setrfreg_cmd(Adapter,
*(unsigned char *)poid_par_priv->information_buf,
(unsigned long)(*((unsigned long *)poid_par_priv->information_buf + 2))))
status = NDIS_STATUS_NOT_ACCEPTED;
} else
status = NDIS_STATUS_INVALID_LENGTH;
_irqlevel_changed_(&oldirql, RAISE);
return status;
}
/* ------------------------------------------------------------------------------ */
NDIS_STATUS oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
#if 0
PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
_irqL oldirql;
/* DEBUG_ERR(("<**********************oid_rt_pro_rf_read_registry_hdl\n")); */
if (poid_par_priv->type_of_oid != SET_OID) { /* QUERY_OID */
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
_irqlevel_changed_(&oldirql, LOWER);
if (poid_par_priv->information_buf_len == (sizeof(unsigned long) * 3)) {
if (Adapter->mppriv.act_in_progress == _TRUE)
status = NDIS_STATUS_NOT_ACCEPTED;
else {
/* init workparam */
Adapter->mppriv.act_in_progress = _TRUE;
Adapter->mppriv.workparam.bcompleted = _FALSE;
Adapter->mppriv.workparam.act_type = MPT_READ_RF;
Adapter->mppriv.workparam.io_offset = *(unsigned long *)poid_par_priv->information_buf;
Adapter->mppriv.workparam.io_value = 0xcccccccc;
/* RegOffsetValue - The offset of RF register to read. */
/* RegDataWidth - The data width of RF register to read. */
/* RegDataValue - The value to read. */
/* RegOffsetValue = *((unsigned long*)InformationBuffer); */
/* RegDataWidth = *((unsigned long*)InformationBuffer+1); */
/* RegDataValue = *((unsigned long*)InformationBuffer+2); */
if (!rtw_getrfreg_cmd(Adapter,
*(unsigned char *)poid_par_priv->information_buf,
(unsigned char *)&Adapter->mppriv.workparam.io_value))
status = NDIS_STATUS_NOT_ACCEPTED;
}
} else
status = NDIS_STATUS_INVALID_LENGTH;
_irqlevel_changed_(&oldirql, RAISE);
#endif
return status;
}
/* **************** oid_rtl_seg_01_11 section end**************** */
/* ************** oid_rtl_seg_03_00 section start ************** */
enum _CONNECT_STATE_ {
CHECKINGSTATUS,
ASSOCIATED,
ADHOCMODE,
NOTASSOCIATED
};
NDIS_STATUS oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
ULONG ulInfo;
if (poid_par_priv->type_of_oid != QUERY_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
/* nStatus==0 CheckingStatus */
/* nStatus==1 Associated */
/* nStatus==2 AdHocMode */
/* nStatus==3 NotAssociated */
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
ulInfo = CHECKINGSTATUS;
else if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
ulInfo = ASSOCIATED;
else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
ulInfo = ADHOCMODE;
else
ulInfo = NOTASSOCIATED ;
*(ULONG *)poid_par_priv->information_buf = ulInfo;
*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
#if 0
/* Rearrange the order to let the UI still shows connection when scan is in progress */
if (pMgntInfo->mAssoc)
ulInfo = 1;
else if (pMgntInfo->mIbss)
ulInfo = 2;
else if (pMgntInfo->bScanInProgress)
ulInfo = 0;
else
ulInfo = 3;
ulInfoLen = sizeof(ULONG);
#endif
return status;
}
NDIS_STATUS oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
{
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
PADAPTER padapter = (PADAPTER)(poid_par_priv->adapter_context);
if (poid_par_priv->type_of_oid != SET_OID) {
status = NDIS_STATUS_NOT_ACCEPTED;
return status;
}
return status;
}
/* ************** oid_rtl_seg_03_00 section end ************** */

894
core/rtw_ioctl_set.c Normal file
View File

@@ -0,0 +1,894 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_IOCTL_SET_C_
#include <drv_types.h>
#include <hal_data.h>
extern void indicate_wx_scan_complete_event(_adapter *padapter);
#define IS_MAC_ADDRESS_BROADCAST(addr) \
(\
((addr[0] == 0xff) && (addr[1] == 0xff) && \
(addr[2] == 0xff) && (addr[3] == 0xff) && \
(addr[4] == 0xff) && (addr[5] == 0xff)) ? _TRUE : _FALSE \
)
u8 rtw_validate_bssid(u8 *bssid)
{
u8 ret = _TRUE;
if (is_zero_mac_addr(bssid)
|| is_broadcast_mac_addr(bssid)
|| is_multicast_mac_addr(bssid)
)
ret = _FALSE;
return ret;
}
u8 rtw_validate_ssid(NDIS_802_11_SSID *ssid)
{
u8 i;
u8 ret = _TRUE;
if (ssid->SsidLength > 32) {
ret = _FALSE;
goto exit;
}
#ifdef CONFIG_VALIDATE_SSID
for (i = 0; i < ssid->SsidLength; i++) {
/* wifi, printable ascii code must be supported */
if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e))) {
ret = _FALSE;
break;
}
}
#endif /* CONFIG_VALIDATE_SSID */
exit:
return ret;
}
u8 rtw_do_join(_adapter *padapter);
u8 rtw_do_join(_adapter *padapter)
{
_irqL irqL;
_list *plist, *phead;
u8 *pibss = NULL;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct sitesurvey_parm parm;
_queue *queue = &(pmlmepriv->scanned_queue);
u8 ret = _SUCCESS;
_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
phead = get_list_head(queue);
plist = get_next(phead);
pmlmepriv->cur_network.join_res = -2;
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
pmlmepriv->pscanned = plist;
pmlmepriv->to_join = _TRUE;
rtw_init_sitesurvey_parm(padapter, &parm);
_rtw_memcpy(&parm.ssid[0], &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
parm.ssid_num = 1;
if (_rtw_queue_empty(queue) == _TRUE) {
_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
/* when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty */
/* we try to issue sitesurvey firstly */
if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _FALSE
|| rtw_to_roam(padapter) > 0
) {
/* submit site_survey_cmd */
ret = rtw_sitesurvey_cmd(padapter, &parm);
if (_SUCCESS != ret) {
pmlmepriv->to_join = _FALSE;
}
} else {
pmlmepriv->to_join = _FALSE;
ret = _FAIL;
}
goto exit;
} else {
int select_ret;
_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
select_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
if (select_ret == _SUCCESS) {
pmlmepriv->to_join = _FALSE;
_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
} else {
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) {
/* submit createbss_cmd to change to a ADHOC_MASTER */
/* pmlmepriv->lock has been acquired by caller... */
WLAN_BSSID_EX *pdev_network = &(padapter->registrypriv.dev_network);
/*pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;*/
init_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
pibss = padapter->registrypriv.dev_network.MacAddress;
_rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
_rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
rtw_update_registrypriv_dev_network(padapter);
rtw_generate_random_ibss(pibss);
if (rtw_create_ibss_cmd(padapter, 0) != _SUCCESS) {
ret = _FALSE;
goto exit;
}
pmlmepriv->to_join = _FALSE;
} else {
/* can't associate ; reset under-linking */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
#if 0
if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)) {
if (_rtw_memcmp(pmlmepriv->cur_network.network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength)) {
/* for funk to do roaming */
/* funk will reconnect, but funk will not sitesurvey before reconnect */
if (pmlmepriv->sitesurveyctrl.traffic_busy == _FALSE)
rtw_sitesurvey_cmd(padapter, &parm);
}
}
#endif
/* when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue */
/* we try to issue sitesurvey firstly */
if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _FALSE
|| rtw_to_roam(padapter) > 0
) {
/* RTW_INFO("rtw_do_join() when no desired bss in scanning queue\n"); */
ret = rtw_sitesurvey_cmd(padapter, &parm);
if (_SUCCESS != ret) {
pmlmepriv->to_join = _FALSE;
}
} else {
ret = _FAIL;
pmlmepriv->to_join = _FALSE;
}
}
}
}
exit:
return ret;
}
#ifdef PLATFORM_WINDOWS
u8 rtw_pnp_set_power_wakeup(_adapter *padapter)
{
u8 res = _SUCCESS;
res = rtw_setstandby_cmd(padapter, 0);
return res;
}
u8 rtw_pnp_set_power_sleep(_adapter *padapter)
{
u8 res = _SUCCESS;
/* DbgPrint("+rtw_pnp_set_power_sleep\n"); */
res = rtw_setstandby_cmd(padapter, 1);
return res;
}
u8 rtw_set_802_11_reload_defaults(_adapter *padapter, NDIS_802_11_RELOAD_DEFAULTS reloadDefaults)
{
/* SecClearAllKeys(Adapter); */
/* 8711 CAM was not for En/Decrypt only */
/* so, we can't clear all keys. */
/* should we disable WPAcfg (ox0088) bit 1-2, instead of clear all CAM */
/* TO DO... */
return _TRUE;
}
u8 set_802_11_test(_adapter *padapter, NDIS_802_11_TEST *test)
{
u8 ret = _TRUE;
switch (test->Type) {
case 1:
NdisMIndicateStatus(padapter->hndis_adapter, NDIS_STATUS_MEDIA_SPECIFIC_INDICATION, (PVOID)&test->AuthenticationEvent, test->Length - 8);
NdisMIndicateStatusComplete(padapter->hndis_adapter);
break;
case 2:
NdisMIndicateStatus(padapter->hndis_adapter, NDIS_STATUS_MEDIA_SPECIFIC_INDICATION, (PVOID)&test->RssiTrigger, sizeof(NDIS_802_11_RSSI));
NdisMIndicateStatusComplete(padapter->hndis_adapter);
break;
default:
ret = _FALSE;
break;
}
return ret;
}
u8 rtw_set_802_11_pmkid(_adapter *padapter, NDIS_802_11_PMKID *pmkid)
{
u8 ret = _SUCCESS;
return ret;
}
#endif
u8 rtw_set_802_11_bssid(_adapter *padapter, u8 *bssid)
{
_irqL irqL;
u8 status = _SUCCESS;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
RTW_PRINT("set bssid:%pM\n", bssid);
if ((bssid[0] == 0x00 && bssid[1] == 0x00 && bssid[2] == 0x00 && bssid[3] == 0x00 && bssid[4] == 0x00 && bssid[5] == 0x00) ||
(bssid[0] == 0xFF && bssid[1] == 0xFF && bssid[2] == 0xFF && bssid[3] == 0xFF && bssid[4] == 0xFF && bssid[5] == 0xFF)) {
status = _FAIL;
goto exit;
}
_enter_critical_bh(&pmlmepriv->lock, &irqL);
RTW_INFO("Set BSSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
goto handle_tkip_countermeasure;
else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
goto release_mlme_lock;
if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
if (_rtw_memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN) == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE)
goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
} else {
rtw_disassoc_cmd(padapter, 0, 0);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources(padapter, 1);
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
}
}
}
handle_tkip_countermeasure:
if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
status = _FAIL;
goto release_mlme_lock;
}
_rtw_memset(&pmlmepriv->assoc_ssid, 0, sizeof(NDIS_802_11_SSID));
_rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
pmlmepriv->assoc_by_bssid = _TRUE;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
pmlmepriv->to_join = _TRUE;
else
status = rtw_do_join(padapter);
release_mlme_lock:
_exit_critical_bh(&pmlmepriv->lock, &irqL);
exit:
return status;
}
u8 rtw_set_802_11_ssid(_adapter *padapter, NDIS_802_11_SSID *ssid)
{
_irqL irqL;
u8 status = _SUCCESS;
u32 cur_time = 0;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *pnetwork = &pmlmepriv->cur_network;
RTW_PRINT("set ssid [%s] fw_state=0x%08x\n",
ssid->Ssid, get_fwstate(pmlmepriv));
if (!rtw_is_hw_init_completed(padapter)) {
status = _FAIL;
goto exit;
}
_enter_critical_bh(&pmlmepriv->lock, &irqL);
RTW_INFO("Set SSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
goto handle_tkip_countermeasure;
else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
goto release_mlme_lock;
if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == _TRUE) {
if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
(_rtw_memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength) == _TRUE)) {
if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE)) {
if (rtw_is_same_ibss(padapter, pnetwork) == _FALSE) {
/* if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again */
rtw_disassoc_cmd(padapter, 0, 0);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources(padapter, 1);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
}
} else {
goto release_mlme_lock;/* it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again. */
}
}
#ifdef CONFIG_LPS
else
rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
#endif
} else {
rtw_disassoc_cmd(padapter, 0, 0);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
rtw_indicate_disconnect(padapter, 0, _FALSE);
rtw_free_assoc_resources(padapter, 1);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
}
}
}
handle_tkip_countermeasure:
if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
status = _FAIL;
goto release_mlme_lock;
}
if (rtw_validate_ssid(ssid) == _FALSE) {
status = _FAIL;
goto release_mlme_lock;
}
_rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID));
pmlmepriv->assoc_by_bssid = _FALSE;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
pmlmepriv->to_join = _TRUE;
else
status = rtw_do_join(padapter);
release_mlme_lock:
_exit_critical_bh(&pmlmepriv->lock, &irqL);
exit:
return status;
}
u8 rtw_set_802_11_connect(_adapter *padapter, u8 *bssid, NDIS_802_11_SSID *ssid)
{
_irqL irqL;
u8 status = _SUCCESS;
u32 cur_time = 0;
bool bssid_valid = _TRUE;
bool ssid_valid = _TRUE;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
if (!ssid || rtw_validate_ssid(ssid) == _FALSE)
ssid_valid = _FALSE;
if (!bssid || rtw_validate_bssid(bssid) == _FALSE)
bssid_valid = _FALSE;
if (ssid_valid == _FALSE && bssid_valid == _FALSE) {
RTW_INFO(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n",
FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid);
status = _FAIL;
goto exit;
}
if (!rtw_is_hw_init_completed(padapter)) {
status = _FAIL;
goto exit;
}
_enter_critical_bh(&pmlmepriv->lock, &irqL);
RTW_PRINT(FUNC_ADPT_FMT" fw_state=0x%08x\n",
FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
goto handle_tkip_countermeasure;
else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
goto release_mlme_lock;
handle_tkip_countermeasure:
if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
status = _FAIL;
goto release_mlme_lock;
}
if (ssid && ssid_valid)
_rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID));
else
_rtw_memset(&pmlmepriv->assoc_ssid, 0, sizeof(NDIS_802_11_SSID));
if (bssid && bssid_valid) {
_rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
pmlmepriv->assoc_by_bssid = _TRUE;
} else
pmlmepriv->assoc_by_bssid = _FALSE;
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE)
pmlmepriv->to_join = _TRUE;
else
status = rtw_do_join(padapter);
release_mlme_lock:
_exit_critical_bh(&pmlmepriv->lock, &irqL);
exit:
return status;
}
u8 rtw_set_802_11_infrastructure_mode(_adapter *padapter,
NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
{
_irqL irqL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *cur_network = &pmlmepriv->cur_network;
NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state = &(cur_network->network.InfrastructureMode);
u8 ap2sta_mode = _FALSE;
u8 ret = _TRUE;
if (*pold_state != networktype) {
/* RTW_INFO("change mode, old_mode=%d, new_mode=%d, fw_state=0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv)); */
if (*pold_state == Ndis802_11APMode
|| *pold_state == Ndis802_11_mesh
) {
/* change to other mode from Ndis802_11APMode/Ndis802_11_mesh */
cur_network->join_res = -1;
ap2sta_mode = _TRUE;
#ifdef CONFIG_NATIVEAP_MLME
stop_ap_mode(padapter);
#endif
}
_enter_critical_bh(&pmlmepriv->lock, &irqL);
if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) || (*pold_state == Ndis802_11IBSS))
rtw_disassoc_cmd(padapter, 0, 0);
if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
rtw_free_assoc_resources(padapter, 1);
if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
rtw_indicate_disconnect(padapter, 0, _FALSE); /*will clr Linked_state; before this function, we must have checked whether issue dis-assoc_cmd or not*/
}
}
*pold_state = networktype;
_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
switch (networktype) {
case Ndis802_11IBSS:
set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
break;
case Ndis802_11Infrastructure:
set_fwstate(pmlmepriv, WIFI_STATION_STATE);
if (ap2sta_mode)
rtw_init_bcmc_stainfo(padapter);
break;
case Ndis802_11APMode:
set_fwstate(pmlmepriv, WIFI_AP_STATE);
#ifdef CONFIG_NATIVEAP_MLME
start_ap_mode(padapter);
/* rtw_indicate_connect(padapter); */
#endif
break;
#ifdef CONFIG_RTW_MESH
case Ndis802_11_mesh:
set_fwstate(pmlmepriv, WIFI_MESH_STATE);
start_ap_mode(padapter);
break;
#endif
case Ndis802_11AutoUnknown:
case Ndis802_11InfrastructureMax:
break;
case Ndis802_11Monitor:
set_fwstate(pmlmepriv, WIFI_MONITOR_STATE);
break;
default:
ret = _FALSE;
rtw_warn_on(1);
}
/* SecClearAllKeys(adapter); */
_exit_critical_bh(&pmlmepriv->lock, &irqL);
}
return ret;
}
u8 rtw_set_802_11_disassociate(_adapter *padapter)
{
_irqL irqL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
_enter_critical_bh(&pmlmepriv->lock, &irqL);
if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
rtw_disassoc_cmd(padapter, 0, 0);
rtw_indicate_disconnect(padapter, 0, _FALSE);
/* modify for CONFIG_IEEE80211W, none 11w can use it */
rtw_free_assoc_resources_cmd(padapter);
if (_FAIL == rtw_pwr_wakeup(padapter))
RTW_INFO("%s(): rtw_pwr_wakeup fail !!!\n", __FUNCTION__);
}
_exit_critical_bh(&pmlmepriv->lock, &irqL);
return _TRUE;
}
#if 1
u8 rtw_set_802_11_bssid_list_scan(_adapter *padapter, struct sitesurvey_parm *pparm)
{
_irqL irqL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 res = _TRUE;
_enter_critical_bh(&pmlmepriv->lock, &irqL);
res = rtw_sitesurvey_cmd(padapter, pparm);
_exit_critical_bh(&pmlmepriv->lock, &irqL);
return res;
}
#else
u8 rtw_set_802_11_bssid_list_scan(_adapter *padapter, struct sitesurvey_parm *pparm)
{
_irqL irqL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 res = _TRUE;
if (padapter == NULL) {
res = _FALSE;
goto exit;
}
if (!rtw_is_hw_init_completed(padapter)) {
res = _FALSE;
goto exit;
}
if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) == _TRUE) ||
(pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)) {
/* Scan or linking is in progress, do nothing. */
res = _TRUE;
} else {
if (rtw_is_scan_deny(padapter)) {
RTW_INFO(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
indicate_wx_scan_complete_event(padapter);
return _SUCCESS;
}
_enter_critical_bh(&pmlmepriv->lock, &irqL);
res = rtw_sitesurvey_cmd(padapter, pparm);
_exit_critical_bh(&pmlmepriv->lock, &irqL);
}
exit:
return res;
}
#endif
u8 rtw_set_802_11_authentication_mode(_adapter *padapter, NDIS_802_11_AUTHENTICATION_MODE authmode)
{
struct security_priv *psecuritypriv = &padapter->securitypriv;
int res;
u8 ret;
psecuritypriv->ndisauthtype = authmode;
if (psecuritypriv->ndisauthtype > 3)
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
#ifdef CONFIG_WAPI_SUPPORT
if (psecuritypriv->ndisauthtype == 6)
psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
#endif
res = rtw_set_auth(padapter, psecuritypriv);
if (res == _SUCCESS)
ret = _TRUE;
else
ret = _FALSE;
return ret;
}
u8 rtw_set_802_11_add_wep(_adapter *padapter, NDIS_802_11_WEP *wep)
{
u8 bdefaultkey;
u8 btransmitkey;
sint keyid, res;
struct security_priv *psecuritypriv = &(padapter->securitypriv);
u8 ret = _SUCCESS;
bdefaultkey = (wep->KeyIndex & 0x40000000) > 0 ? _FALSE : _TRUE; /* for ??? */
btransmitkey = (wep->KeyIndex & 0x80000000) > 0 ? _TRUE : _FALSE; /* for ??? */
keyid = wep->KeyIndex & 0x3fffffff;
if (keyid >= 4) {
ret = _FALSE;
goto exit;
}
switch (wep->KeyLength) {
case 5:
psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
break;
case 13:
psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
break;
default:
psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
break;
}
_rtw_memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]), &(wep->KeyMaterial), wep->KeyLength);
psecuritypriv->dot11DefKeylen[keyid] = wep->KeyLength;
psecuritypriv->dot11PrivacyKeyIndex = keyid;
res = rtw_set_key(padapter, psecuritypriv, keyid, 1, _TRUE);
if (res == _FAIL)
ret = _FALSE;
exit:
return ret;
}
/*
* rtw_get_cur_max_rate -
* @adapter: pointer to _adapter structure
*
* Return 0 or 100Kbps
*/
u16 rtw_get_cur_max_rate(_adapter *adapter)
{
int i = 0;
u16 rate = 0, max_rate = 0;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
WLAN_BSSID_EX *pcur_bss = &pmlmepriv->cur_network.network;
struct sta_info *psta = NULL;
u8 short_GI = 0;
#ifdef CONFIG_80211N_HT
u8 rf_type = 0;
#endif
#ifdef CONFIG_MP_INCLUDED
if (adapter->registrypriv.mp_mode == 1) {
if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
return 0;
}
#endif
if ((check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE)
&& (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE))
return 0;
psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
if (psta == NULL)
return 0;
short_GI = query_ra_short_GI(psta, rtw_get_tx_bw_mode(adapter, psta));
#ifdef CONFIG_80211N_HT
if (is_supported_ht(psta->wireless_mode)) {
rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
max_rate = rtw_mcs_rate(rf_type
, (psta->cmn.bw_mode == CHANNEL_WIDTH_40) ? 1 : 0
, short_GI
, psta->htpriv.ht_cap.supp_mcs_set
);
}
#ifdef CONFIG_80211AC_VHT
else if (is_supported_vht(psta->wireless_mode))
max_rate = ((rtw_vht_mcs_to_data_rate(psta->cmn.bw_mode, short_GI, pmlmepriv->vhtpriv.vht_highest_rate) + 1) >> 1) * 10;
#endif /* CONFIG_80211AC_VHT */
else
#endif /* CONFIG_80211N_HT */
{
while ((pcur_bss->SupportedRates[i] != 0) && (pcur_bss->SupportedRates[i] != 0xFF)) {
rate = pcur_bss->SupportedRates[i] & 0x7F;
if (rate > max_rate)
max_rate = rate;
i++;
}
max_rate = max_rate * 10 / 2;
}
return max_rate;
}
/*
* rtw_set_scan_mode -
* @adapter: pointer to _adapter structure
* @scan_mode:
*
* Return _SUCCESS or _FAIL
*/
int rtw_set_scan_mode(_adapter *adapter, RT_SCAN_TYPE scan_mode)
{
if (scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
return _FAIL;
adapter->mlmepriv.scan_mode = scan_mode;
return _SUCCESS;
}
/*
* rtw_set_channel_plan -
* @adapter: pointer to _adapter structure
* @channel_plan:
*
* Return _SUCCESS or _FAIL
*/
int rtw_set_channel_plan(_adapter *adapter, u8 channel_plan)
{
struct registry_priv *pregistrypriv = &adapter->registrypriv;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
/* handle by cmd_thread to sync with scan operation */
return rtw_set_chplan_cmd(adapter, RTW_CMDF_WAIT_ACK, channel_plan, 1);
}
/*
* rtw_set_country -
* @adapter: pointer to _adapter structure
* @country_code: string of country code
*
* Return _SUCCESS or _FAIL
*/
int rtw_set_country(_adapter *adapter, const char *country_code)
{
#ifdef CONFIG_RTW_IOCTL_SET_COUNTRY
return rtw_set_country_cmd(adapter, RTW_CMDF_WAIT_ACK, country_code, 1);
#else
RTW_INFO("%s(): not applied\n", __func__);
return _SUCCESS;
#endif
}
/*
* rtw_set_band -
* @adapter: pointer to _adapter structure
* @band: band to set
*
* Return _SUCCESS or _FAIL
*/
int rtw_set_band(_adapter *adapter, u8 band)
{
if (rtw_band_valid(band)) {
RTW_INFO(FUNC_ADPT_FMT" band:%d\n", FUNC_ADPT_ARG(adapter), band);
adapter->setband = band;
return _SUCCESS;
}
RTW_PRINT(FUNC_ADPT_FMT" band:%d fail\n", FUNC_ADPT_ARG(adapter), band);
return _FAIL;
}

382
core/rtw_iol.c Normal file
View File

@@ -0,0 +1,382 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#ifdef CONFIG_IOL
struct xmit_frame *rtw_IOL_accquire_xmit_frame(ADAPTER *adapter)
{
struct xmit_frame *xmit_frame;
struct xmit_buf *xmitbuf;
struct pkt_attrib *pattrib;
struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
#if 1
xmit_frame = rtw_alloc_xmitframe(pxmitpriv);
if (xmit_frame == NULL) {
RTW_INFO("%s rtw_alloc_xmitframe return null\n", __FUNCTION__);
goto exit;
}
xmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
if (xmitbuf == NULL) {
RTW_INFO("%s rtw_alloc_xmitbuf return null\n", __FUNCTION__);
rtw_free_xmitframe(pxmitpriv, xmit_frame);
xmit_frame = NULL;
goto exit;
}
xmit_frame->frame_tag = MGNT_FRAMETAG;
xmit_frame->pxmitbuf = xmitbuf;
xmit_frame->buf_addr = xmitbuf->pbuf;
xmitbuf->priv_data = xmit_frame;
pattrib = &xmit_frame->attrib;
update_mgntframe_attrib(adapter, pattrib);
pattrib->qsel = QSLT_BEACON;/* Beacon */
pattrib->subtype = WIFI_BEACON;
pattrib->pktlen = pattrib->last_txcmdsz = 0;
#else
xmit_frame = alloc_mgtxmitframe(pxmitpriv);
if (xmit_frame == NULL)
RTW_INFO("%s alloc_mgtxmitframe return null\n", __FUNCTION__);
else {
pattrib = &xmit_frame->attrib;
update_mgntframe_attrib(adapter, pattrib);
pattrib->qsel = QSLT_BEACON;
pattrib->pktlen = pattrib->last_txcmdsz = 0;
}
#endif
exit:
return xmit_frame;
}
int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
{
struct pkt_attrib *pattrib = &xmit_frame->attrib;
u16 buf_offset;
u32 ori_len;
buf_offset = TXDESC_OFFSET;
ori_len = buf_offset + pattrib->pktlen;
/* check if the io_buf can accommodate new cmds */
if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
RTW_INFO("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n", __FUNCTION__
, ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
return _FAIL;
}
_rtw_memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
pattrib->pktlen += cmd_len;
pattrib->last_txcmdsz += cmd_len;
/* RTW_INFO("%s ori:%u + cmd_len:%u = %u\n", __FUNCTION__, ori_len, cmd_len, buf_offset+pattrib->pktlen); */
return _SUCCESS;
}
bool rtw_IOL_applied(ADAPTER *adapter)
{
if (1 == adapter->registrypriv.fw_iol)
return _TRUE;
#ifdef CONFIG_USB_HCI
if ((2 == adapter->registrypriv.fw_iol) && (IS_FULL_SPEED_USB(adapter)))
return _TRUE;
#endif
return _FALSE;
}
int rtw_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
{
return rtw_hal_iol_cmd(adapter, xmit_frame, max_wating_ms, bndy_cnt);
}
#ifdef CONFIG_IOL_NEW_GENERATION
int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
{
return _SUCCESS;
}
int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0};
/* RTW_PUT_LE16((u8*)&cmd.address, addr); */
/* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
cmd.address = cpu_to_le16(addr);
cmd.data = cpu_to_le32(value);
if (mask != 0xFF) {
cmd.length = 12;
/* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
cmd.mask = cpu_to_le32(mask);
}
/* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
/* RTW_PUT_LE16((u8*)&cmd.address, addr); */
/* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
cmd.address = cpu_to_le16(addr);
cmd.data = cpu_to_le32(value);
if (mask != 0xFFFF) {
cmd.length = 12;
/* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
cmd.mask = cpu_to_le32(mask);
}
/* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
/* RTW_PUT_LE16((u8*)&cmd.address, addr); */
/* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
cmd.address = cpu_to_le16(addr);
cmd.data = cpu_to_le32(value);
if (mask != 0xFFFFFFFF) {
cmd.length = 12;
/* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
cmd.mask = cpu_to_le32(mask);
}
/* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__, addr,value,mask); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
{
struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0};
/* RTW_PUT_LE16((u8*)&cmd.address, addr); */
/* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
cmd.address = (rf_path << 8) | ((addr) & 0xFF);
cmd.data = cpu_to_le32(value);
if (mask != 0x000FFFFF) {
cmd.length = 12;
/* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
cmd.mask = cpu_to_le32(mask);
}
/* RTW_INFO("%s rf_path:0x%02x addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__,rf_path, addr,value,mask); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
}
int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
{
struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
/* RTW_PUT_LE16((u8*)&cmd.address, us); */
cmd.address = cpu_to_le16(us);
/* RTW_INFO("%s %u\n", __FUNCTION__, us); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
}
int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
{
struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
/* RTW_PUT_LE16((u8*)&cmd.address, ms); */
cmd.address = cpu_to_le16(ms);
/* RTW_INFO("%s %u\n", __FUNCTION__, ms); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
}
int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
{
struct ioreg_cfg cmd = {4, IOREG_CMD_END, 0xFFFF, 0xFF, 0x0};
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
}
u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
{
u8 is_cmd_bndy = _FALSE;
if (((pxmit_frame->attrib.pktlen + 32) % 256) + 8 >= 256) {
rtw_IOL_append_END_cmd(pxmit_frame);
pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen + 32) / 256) + 1) * 256);
/* printk("==> %s, pktlen(%d)\n",__FUNCTION__,pxmit_frame->attrib.pktlen); */
pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
is_cmd_bndy = _TRUE;
}
return is_cmd_bndy;
}
void rtw_IOL_cmd_buf_dump(ADAPTER *Adapter, int buf_len, u8 *pbuf)
{
int i;
int j = 1;
printk("###### %s ######\n", __FUNCTION__);
for (i = 0; i < buf_len; i++) {
printk("%02x-", *(pbuf + i));
if (j % 32 == 0)
printk("\n");
j++;
}
printk("\n");
printk("============= ioreg_cmd len = %d ===============\n", buf_len);
}
#else /* CONFIG_IOL_NEW_GENERATION */
int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
{
IOL_CMD cmd = {0x0, IOL_CMD_LLT, 0x0, 0x0};
RTW_PUT_BE32((u8 *)&cmd.value, (u32)page_boundary);
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
}
int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value)
{
IOL_CMD cmd = {0x0, IOL_CMD_WB_REG, 0x0, 0x0};
RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
}
int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value)
{
IOL_CMD cmd = {0x0, IOL_CMD_WW_REG, 0x0, 0x0};
RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
}
int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value)
{
IOL_CMD cmd = {0x0, IOL_CMD_WD_REG, 0x0, 0x0};
u8 *pos = (u8 *)&cmd;
RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
}
#ifdef DBG_IO
int dbg_rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 1))
RTW_INFO("DBG_IO %s:%d IOL_WB(0x%04x, 0x%02x)\n", caller, line, addr, value);
return _rtw_IOL_append_WB_cmd(xmit_frame, addr, value);
}
int dbg_rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 2))
RTW_INFO("DBG_IO %s:%d IOL_WW(0x%04x, 0x%04x)\n", caller, line, addr, value);
return _rtw_IOL_append_WW_cmd(xmit_frame, addr, value);
}
int dbg_rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, const char *caller, const int line)
{
if (match_write_sniff_ranges(addr, 4))
RTW_INFO("DBG_IO %s:%d IOL_WD(0x%04x, 0x%08x)\n", caller, line, addr, value);
return _rtw_IOL_append_WD_cmd(xmit_frame, addr, value);
}
#endif
int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
{
IOL_CMD cmd = {0x0, IOL_CMD_DELAY_US, 0x0, 0x0};
RTW_PUT_BE32((u8 *)&cmd.value, (u32)us);
/* RTW_INFO("%s %u\n", __FUNCTION__, us); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
}
int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
{
IOL_CMD cmd = {0x0, IOL_CMD_DELAY_MS, 0x0, 0x0};
RTW_PUT_BE32((u8 *)&cmd.value, (u32)ms);
/* RTW_INFO("%s %u\n", __FUNCTION__, ms); */
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
}
int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
{
IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
return rtw_IOL_append_cmds(xmit_frame, (u8 *)&end_cmd, 8);
}
int rtw_IOL_exec_cmd_array_sync(PADAPTER adapter, u8 *IOL_cmds, u32 cmd_num, u32 max_wating_ms)
{
struct xmit_frame *xmit_frame;
xmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
if (xmit_frame == NULL)
return _FAIL;
if (rtw_IOL_append_cmds(xmit_frame, IOL_cmds, cmd_num << 3) == _FAIL)
return _FAIL;
return rtw_IOL_exec_cmds_sync(adapter, xmit_frame, max_wating_ms, 0);
}
int rtw_IOL_exec_empty_cmds_sync(ADAPTER *adapter, u32 max_wating_ms)
{
IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
return rtw_IOL_exec_cmd_array_sync(adapter, (u8 *)&end_cmd, 1, max_wating_ms);
}
#endif /* CONFIG_IOL_NEW_GENERATION */
#endif /* CONFIG_IOL */

128
core/rtw_mem.c Normal file
View File

@@ -0,0 +1,128 @@
/******************************************************************************
*
* Copyright(c) 2016 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <rtw_mem.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
MODULE_AUTHOR("Realtek Semiconductor Corp.");
MODULE_VERSION("DRIVERVERSION");
struct sk_buff_head rtk_skb_mem_q;
struct u8 *rtk_buf_mem[NR_RECVBUFF];
struct u8 *rtw_get_buf_premem(int index)
{
printk("%s, rtk_buf_mem index : %d\n", __func__, index);
return rtk_buf_mem[index];
}
u16 rtw_rtkm_get_buff_size(void)
{
return MAX_RTKM_RECVBUF_SZ;
}
EXPORT_SYMBOL(rtw_rtkm_get_buff_size);
u8 rtw_rtkm_get_nr_recv_skb(void)
{
return MAX_RTKM_NR_PREALLOC_RECV_SKB;
}
EXPORT_SYMBOL(rtw_rtkm_get_nr_recv_skb);
struct sk_buff *rtw_alloc_skb_premem(u16 in_size)
{
struct sk_buff *skb = NULL;
if (in_size > MAX_RTKM_RECVBUF_SZ) {
pr_info("warning %s: driver buffer size(%d) > rtkm buffer size(%d)\n", __func__, in_size, MAX_RTKM_RECVBUF_SZ);
WARN_ON(1);
return skb;
}
skb = skb_dequeue(&rtk_skb_mem_q);
printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
return skb;
}
EXPORT_SYMBOL(rtw_alloc_skb_premem);
int rtw_free_skb_premem(struct sk_buff *pskb)
{
if (!pskb)
return -1;
if (skb_queue_len(&rtk_skb_mem_q) >= MAX_RTKM_NR_PREALLOC_RECV_SKB)
return -1;
skb_queue_tail(&rtk_skb_mem_q, pskb);
printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
return 0;
}
EXPORT_SYMBOL(rtw_free_skb_premem);
static int __init rtw_mem_init(void)
{
int i;
SIZE_PTR tmpaddr = 0;
SIZE_PTR alignment = 0;
struct sk_buff *pskb = NULL;
printk("%s\n", __func__);
pr_info("MAX_RTKM_NR_PREALLOC_RECV_SKB: %d\n", MAX_RTKM_NR_PREALLOC_RECV_SKB);
pr_info("MAX_RTKM_RECVBUF_SZ: %d\n", MAX_RTKM_RECVBUF_SZ);
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
for (i = 0; i < NR_RECVBUFF; i++)
rtk_buf_mem[i] = usb_buffer_alloc(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma);
#endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */
skb_queue_head_init(&rtk_skb_mem_q);
for (i = 0; i < MAX_RTKM_NR_PREALLOC_RECV_SKB; i++) {
pskb = __dev_alloc_skb(MAX_RTKM_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (pskb) {
tmpaddr = (SIZE_PTR)pskb->data;
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
skb_queue_tail(&rtk_skb_mem_q, pskb);
} else
printk("%s, alloc skb memory fail!\n", __func__);
pskb = NULL;
}
printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
return 0;
}
static void __exit rtw_mem_exit(void)
{
if (skb_queue_len(&rtk_skb_mem_q))
printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
skb_queue_purge(&rtk_skb_mem_q);
printk("%s\n", __func__);
}
module_init(rtw_mem_init);
module_exit(rtw_mem_exit);

1478
core/rtw_mi.c Normal file

File diff suppressed because it is too large Load Diff

5123
core/rtw_mlme.c Normal file

File diff suppressed because it is too large Load Diff

16886
core/rtw_mlme_ext.c Executable file

File diff suppressed because it is too large Load Diff

3584
core/rtw_mp.c Normal file

File diff suppressed because it is too large Load Diff

2529
core/rtw_mp_ioctl.c Normal file

File diff suppressed because it is too large Load Diff

454
core/rtw_odm.c Normal file
View File

@@ -0,0 +1,454 @@
/******************************************************************************
*
* Copyright(c) 2013 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <rtw_odm.h>
#include <hal_data.h>
u32 rtw_phydm_ability_ops(_adapter *adapter, HAL_PHYDM_OPS ops, u32 ability)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
struct dm_struct *podmpriv = &pHalData->odmpriv;
u32 result = 0;
switch (ops) {
case HAL_PHYDM_DIS_ALL_FUNC:
podmpriv->support_ability = DYNAMIC_FUNC_DISABLE;
halrf_cmn_info_set(podmpriv, HALRF_CMNINFO_ABILITY, DYNAMIC_FUNC_DISABLE);
break;
case HAL_PHYDM_FUNC_SET:
podmpriv->support_ability |= ability;
break;
case HAL_PHYDM_FUNC_CLR:
podmpriv->support_ability &= ~(ability);
break;
case HAL_PHYDM_ABILITY_BK:
/* dm flag backup*/
podmpriv->bk_support_ability = podmpriv->support_ability;
pHalData->bk_rf_ability = halrf_cmn_info_get(podmpriv, HALRF_CMNINFO_ABILITY);
break;
case HAL_PHYDM_ABILITY_RESTORE:
/* restore dm flag */
podmpriv->support_ability = podmpriv->bk_support_ability;
halrf_cmn_info_set(podmpriv, HALRF_CMNINFO_ABILITY, pHalData->bk_rf_ability);
break;
case HAL_PHYDM_ABILITY_SET:
podmpriv->support_ability = ability;
break;
case HAL_PHYDM_ABILITY_GET:
result = podmpriv->support_ability;
break;
}
return result;
}
/* set ODM_CMNINFO_IC_TYPE based on chip_type */
void rtw_odm_init_ic_type(_adapter *adapter)
{
struct dm_struct *odm = adapter_to_phydm(adapter);
u4Byte ic_type = chip_type_to_odm_ic_type(rtw_get_chip_type(adapter));
rtw_warn_on(!ic_type);
odm_cmn_info_init(odm, ODM_CMNINFO_IC_TYPE, ic_type);
}
void rtw_odm_adaptivity_ver_msg(void *sel, _adapter *adapter)
{
RTW_PRINT_SEL(sel, "ADAPTIVITY_VERSION "ADAPTIVITY_VERSION"\n");
}
#define RTW_ADAPTIVITY_EN_DISABLE 0
#define RTW_ADAPTIVITY_EN_ENABLE 1
void rtw_odm_adaptivity_en_msg(void *sel, _adapter *adapter)
{
struct registry_priv *regsty = &adapter->registrypriv;
RTW_PRINT_SEL(sel, "RTW_ADAPTIVITY_EN_");
if (regsty->adaptivity_en == RTW_ADAPTIVITY_EN_DISABLE)
_RTW_PRINT_SEL(sel, "DISABLE\n");
else if (regsty->adaptivity_en == RTW_ADAPTIVITY_EN_ENABLE)
_RTW_PRINT_SEL(sel, "ENABLE\n");
else
_RTW_PRINT_SEL(sel, "INVALID\n");
}
#define RTW_ADAPTIVITY_MODE_NORMAL 0
#define RTW_ADAPTIVITY_MODE_CARRIER_SENSE 1
void rtw_odm_adaptivity_mode_msg(void *sel, _adapter *adapter)
{
struct registry_priv *regsty = &adapter->registrypriv;
RTW_PRINT_SEL(sel, "RTW_ADAPTIVITY_MODE_");
if (regsty->adaptivity_mode == RTW_ADAPTIVITY_MODE_NORMAL)
_RTW_PRINT_SEL(sel, "NORMAL\n");
else if (regsty->adaptivity_mode == RTW_ADAPTIVITY_MODE_CARRIER_SENSE)
_RTW_PRINT_SEL(sel, "CARRIER_SENSE\n");
else
_RTW_PRINT_SEL(sel, "INVALID\n");
}
#define RTW_ADAPTIVITY_DML_DISABLE 0
#define RTW_ADAPTIVITY_DML_ENABLE 1
void rtw_odm_adaptivity_dml_msg(void *sel, _adapter *adapter)
{
struct registry_priv *regsty = &adapter->registrypriv;
RTW_PRINT_SEL(sel, "RTW_ADAPTIVITY_DML_");
if (regsty->adaptivity_dml == RTW_ADAPTIVITY_DML_DISABLE)
_RTW_PRINT_SEL(sel, "DISABLE\n");
else if (regsty->adaptivity_dml == RTW_ADAPTIVITY_DML_ENABLE)
_RTW_PRINT_SEL(sel, "ENABLE\n");
else
_RTW_PRINT_SEL(sel, "INVALID\n");
}
void rtw_odm_adaptivity_dc_backoff_msg(void *sel, _adapter *adapter)
{
struct registry_priv *regsty = &adapter->registrypriv;
RTW_PRINT_SEL(sel, "RTW_ADAPTIVITY_DC_BACKOFF:%u\n", regsty->adaptivity_dc_backoff);
}
void rtw_odm_adaptivity_config_msg(void *sel, _adapter *adapter)
{
rtw_odm_adaptivity_ver_msg(sel, adapter);
rtw_odm_adaptivity_en_msg(sel, adapter);
rtw_odm_adaptivity_mode_msg(sel, adapter);
rtw_odm_adaptivity_dml_msg(sel, adapter);
rtw_odm_adaptivity_dc_backoff_msg(sel, adapter);
}
bool rtw_odm_adaptivity_needed(_adapter *adapter)
{
struct registry_priv *regsty = &adapter->registrypriv;
struct mlme_priv *mlme = &adapter->mlmepriv;
bool ret = _FALSE;
if (regsty->adaptivity_en == RTW_ADAPTIVITY_EN_ENABLE)
ret = _TRUE;
return ret;
}
void rtw_odm_adaptivity_parm_msg(void *sel, _adapter *adapter)
{
struct dm_struct *odm = adapter_to_phydm(adapter);
rtw_odm_adaptivity_config_msg(sel, adapter);
RTW_PRINT_SEL(sel, "%10s %16s %16s %22s %12s\n"
, "th_l2h_ini", "th_edcca_hl_diff", "th_l2h_ini_mode2", "th_edcca_hl_diff_mode2", "edcca_enable");
RTW_PRINT_SEL(sel, "0x%-8x %-16d 0x%-14x %-22d %-12d\n"
, (u8)odm->th_l2h_ini
, odm->th_edcca_hl_diff
, (u8)odm->th_l2h_ini_mode2
, odm->th_edcca_hl_diff_mode2
, odm->edcca_enable
);
RTW_PRINT_SEL(sel, "%15s %9s\n", "AdapEnableState", "Adap_Flag");
RTW_PRINT_SEL(sel, "%-15x %-9x\n"
, odm->adaptivity_enable
, odm->adaptivity_flag
);
}
void rtw_odm_adaptivity_parm_set(_adapter *adapter, s8 th_l2h_ini, s8 th_edcca_hl_diff, s8 th_l2h_ini_mode2, s8 th_edcca_hl_diff_mode2, u8 edcca_enable)
{
struct dm_struct *odm = adapter_to_phydm(adapter);
odm->th_l2h_ini = th_l2h_ini;
odm->th_edcca_hl_diff = th_edcca_hl_diff;
odm->th_l2h_ini_mode2 = th_l2h_ini_mode2;
odm->th_edcca_hl_diff_mode2 = th_edcca_hl_diff_mode2;
odm->edcca_enable = edcca_enable;
}
void rtw_odm_get_perpkt_rssi(void *sel, _adapter *adapter)
{
struct dm_struct *odm = adapter_to_phydm(adapter);
RTW_PRINT_SEL(sel, "rx_rate = %s, rssi_a = %d(%%), rssi_b = %d(%%)\n",
HDATA_RATE(odm->rx_rate), odm->rssi_a, odm->rssi_b);
}
void rtw_odm_acquirespinlock(_adapter *adapter, enum rt_spinlock_type type)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
_irqL irqL;
switch (type) {
case RT_IQK_SPINLOCK:
_enter_critical_bh(&pHalData->IQKSpinLock, &irqL);
default:
break;
}
}
void rtw_odm_releasespinlock(_adapter *adapter, enum rt_spinlock_type type)
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
_irqL irqL;
switch (type) {
case RT_IQK_SPINLOCK:
_exit_critical_bh(&pHalData->IQKSpinLock, &irqL);
default:
break;
}
}
inline u8 rtw_odm_get_dfs_domain(_adapter *adapter)
{
#ifdef CONFIG_DFS_MASTER
struct dm_struct *pDM_Odm = adapter_to_phydm(adapter);
return pDM_Odm->dfs_region_domain;
#else
return PHYDM_DFS_DOMAIN_UNKNOWN;
#endif
}
inline u8 rtw_odm_dfs_domain_unknown(_adapter *adapter)
{
#ifdef CONFIG_DFS_MASTER
return rtw_odm_get_dfs_domain(adapter) == PHYDM_DFS_DOMAIN_UNKNOWN;
#else
return 1;
#endif
}
#ifdef CONFIG_DFS_MASTER
inline VOID rtw_odm_radar_detect_reset(_adapter *adapter)
{
phydm_radar_detect_reset(adapter_to_phydm(adapter));
}
inline VOID rtw_odm_radar_detect_disable(_adapter *adapter)
{
phydm_radar_detect_disable(adapter_to_phydm(adapter));
}
/* called after ch, bw is set */
inline VOID rtw_odm_radar_detect_enable(_adapter *adapter)
{
phydm_radar_detect_enable(adapter_to_phydm(adapter));
}
inline BOOLEAN rtw_odm_radar_detect(_adapter *adapter)
{
return phydm_radar_detect(adapter_to_phydm(adapter));
}
#endif /* CONFIG_DFS_MASTER */
void rtw_odm_parse_rx_phy_status_chinfo(union recv_frame *rframe, u8 *phys)
{
#ifndef DBG_RX_PHYSTATUS_CHINFO
#define DBG_RX_PHYSTATUS_CHINFO 0
#endif
#if (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1)
_adapter *adapter = rframe->u.hdr.adapter;
struct dm_struct *phydm = adapter_to_phydm(adapter);
struct rx_pkt_attrib *attrib = &rframe->u.hdr.attrib;
u8 *wlanhdr = get_recvframe_data(rframe);
if (phydm->support_ic_type & PHYSTS_2ND_TYPE_IC) {
/*
* 8723D:
* type_0(CCK)
* l_rxsc
* is filled with primary channel SC, not real rxsc.
* 0:LSC, 1:USC
* type_1(OFDM)
* rf_mode
* RF bandwidth when RX
* l_rxsc(legacy), ht_rxsc
* see below RXSC N-series
* type_2(Not used)
*/
/*
* 8821C, 8822B:
* type_0(CCK)
* l_rxsc
* is filled with primary channel SC, not real rxsc.
* 0:LSC, 1:USC
* type_1(OFDM)
* rf_mode
* RF bandwidth when RX
* l_rxsc(legacy), ht_rxsc
* see below RXSC AC-series
* type_2(Not used)
*/
if ((*phys & 0xf) == 0) {
struct phy_status_rpt_jaguar2_type0 *phys_t0 = (struct phy_status_rpt_jaguar2_type0 *)phys;
if (DBG_RX_PHYSTATUS_CHINFO) {
RTW_PRINT("phys_t%u ta="MAC_FMT" %s, %s(band:%u, ch:%u, l_rxsc:%u)\n"
, *phys & 0xf
, MAC_ARG(get_ta(wlanhdr))
, is_broadcast_mac_addr(get_ra(wlanhdr)) ? "BC" : is_multicast_mac_addr(get_ra(wlanhdr)) ? "MC" : "UC"
, HDATA_RATE(attrib->data_rate)
, phys_t0->band, phys_t0->channel, phys_t0->rxsc
);
}
} else if ((*phys & 0xf) == 1) {
struct phy_status_rpt_jaguar2_type1 *phys_t1 = (struct phy_status_rpt_jaguar2_type1 *)phys;
u8 rxsc = (attrib->data_rate > DESC_RATE11M && attrib->data_rate < DESC_RATEMCS0) ? phys_t1->l_rxsc : phys_t1->ht_rxsc;
u8 pkt_cch = 0;
u8 pkt_bw = CHANNEL_WIDTH_20;
#if ODM_IC_11N_SERIES_SUPPORT
if (phydm->support_ic_type & ODM_IC_11N_SERIES) {
/* RXSC N-series */
#define RXSC_DUP 0
#define RXSC_LSC 1
#define RXSC_USC 2
#define RXSC_40M 3
static const s8 cch_offset_by_rxsc[4] = {0, -2, 2, 0};
if (phys_t1->rf_mode == 0) {
pkt_cch = phys_t1->channel;
pkt_bw = CHANNEL_WIDTH_20;
} else if (phys_t1->rf_mode == 1) {
if (rxsc == RXSC_LSC || rxsc == RXSC_USC) {
pkt_cch = phys_t1->channel + cch_offset_by_rxsc[rxsc];
pkt_bw = CHANNEL_WIDTH_20;
} else if (rxsc == RXSC_40M) {
pkt_cch = phys_t1->channel;
pkt_bw = CHANNEL_WIDTH_40;
}
} else
rtw_warn_on(1);
goto type1_end;
}
#endif /* ODM_IC_11N_SERIES_SUPPORT */
#if ODM_IC_11AC_SERIES_SUPPORT
if (phydm->support_ic_type & ODM_IC_11AC_SERIES) {
/* RXSC AC-series */
#define RXSC_DUP 0 /* 0: RX from all SC of current rf_mode */
#define RXSC_LL20M_OF_160M 8 /* 1~8: RX from 20MHz SC */
#define RXSC_L20M_OF_160M 6
#define RXSC_L20M_OF_80M 4
#define RXSC_L20M_OF_40M 2
#define RXSC_U20M_OF_40M 1
#define RXSC_U20M_OF_80M 3
#define RXSC_U20M_OF_160M 5
#define RXSC_UU20M_OF_160M 7
#define RXSC_L40M_OF_160M 12 /* 9~12: RX from 40MHz SC */
#define RXSC_L40M_OF_80M 10
#define RXSC_U40M_OF_80M 9
#define RXSC_U40M_OF_160M 11
#define RXSC_L80M_OF_160M 14 /* 13~14: RX from 80MHz SC */
#define RXSC_U80M_OF_160M 13
static const s8 cch_offset_by_rxsc[15] = {0, 2, -2, 6, -6, 10, -10, 14, -14, 4, -4, 12, -12, 8, -8};
if (phys_t1->rf_mode > 3) {
/* invalid rf_mode */
rtw_warn_on(1);
goto type1_end;
}
if (phys_t1->rf_mode == 0) {
/* RF 20MHz */
pkt_cch = phys_t1->channel;
pkt_bw = CHANNEL_WIDTH_20;
goto type1_end;
}
if (rxsc == 0) {
/* RF and RX with same BW */
if (attrib->data_rate >= DESC_RATEMCS0) {
pkt_cch = phys_t1->channel;
pkt_bw = phys_t1->rf_mode;
}
goto type1_end;
}
if ((phys_t1->rf_mode == 1 && rxsc >= 1 && rxsc <= 2) /* RF 40MHz, RX 20MHz */
|| (phys_t1->rf_mode == 2 && rxsc >= 1 && rxsc <= 4) /* RF 80MHz, RX 20MHz */
|| (phys_t1->rf_mode == 3 && rxsc >= 1 && rxsc <= 8) /* RF 160MHz, RX 20MHz */
) {
pkt_cch = phys_t1->channel + cch_offset_by_rxsc[rxsc];
pkt_bw = CHANNEL_WIDTH_20;
} else if ((phys_t1->rf_mode == 2 && rxsc >= 9 && rxsc <= 10) /* RF 80MHz, RX 40MHz */
|| (phys_t1->rf_mode == 3 && rxsc >= 9 && rxsc <= 12) /* RF 160MHz, RX 40MHz */
) {
if (attrib->data_rate >= DESC_RATEMCS0) {
pkt_cch = phys_t1->channel + cch_offset_by_rxsc[rxsc];
pkt_bw = CHANNEL_WIDTH_40;
}
} else if ((phys_t1->rf_mode == 3 && rxsc >= 13 && rxsc <= 14) /* RF 160MHz, RX 80MHz */
) {
if (attrib->data_rate >= DESC_RATEMCS0) {
pkt_cch = phys_t1->channel + cch_offset_by_rxsc[rxsc];
pkt_bw = CHANNEL_WIDTH_80;
}
} else
rtw_warn_on(1);
}
#endif /* ODM_IC_11AC_SERIES_SUPPORT */
type1_end:
if (DBG_RX_PHYSTATUS_CHINFO) {
RTW_PRINT("phys_t%u ta="MAC_FMT" %s, %s(band:%u, ch:%u, rf_mode:%u, l_rxsc:%u, ht_rxsc:%u) => %u,%u\n"
, *phys & 0xf
, MAC_ARG(get_ta(wlanhdr))
, is_broadcast_mac_addr(get_ra(wlanhdr)) ? "BC" : is_multicast_mac_addr(get_ra(wlanhdr)) ? "MC" : "UC"
, HDATA_RATE(attrib->data_rate)
, phys_t1->band, phys_t1->channel, phys_t1->rf_mode, phys_t1->l_rxsc, phys_t1->ht_rxsc
, pkt_cch, pkt_bw
);
}
/* for now, only return cneter channel of 20MHz packet */
if (pkt_cch && pkt_bw == CHANNEL_WIDTH_20)
attrib->ch = pkt_cch;
} else {
struct phy_status_rpt_jaguar2_type2 *phys_t2 = (struct phy_status_rpt_jaguar2_type2 *)phys;
if (DBG_RX_PHYSTATUS_CHINFO) {
RTW_PRINT("phys_t%u ta="MAC_FMT" %s, %s(band:%u, ch:%u, l_rxsc:%u, ht_rxsc:%u)\n"
, *phys & 0xf
, MAC_ARG(get_ta(wlanhdr))
, is_broadcast_mac_addr(get_ra(wlanhdr)) ? "BC" : is_multicast_mac_addr(get_ra(wlanhdr)) ? "MC" : "UC"
, HDATA_RATE(attrib->data_rate)
, phys_t2->band, phys_t2->channel, phys_t2->l_rxsc, phys_t2->ht_rxsc
);
}
}
}
#endif /* (ODM_PHY_STATUS_NEW_TYPE_SUPPORT == 1) */
}

5454
core/rtw_p2p.c Normal file

File diff suppressed because it is too large Load Diff

2674
core/rtw_pwrctrl.c Normal file

File diff suppressed because it is too large Load Diff

4996
core/rtw_recv.c Executable file

File diff suppressed because it is too large Load Diff

1847
core/rtw_rf.c Normal file

File diff suppressed because it is too large Load Diff

2493
core/rtw_rm.c Normal file

File diff suppressed because it is too large Load Diff

998
core/rtw_rm_fsm.c Normal file
View File

@@ -0,0 +1,998 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <hal_data.h>
#include "rtw_rm_fsm.h"
#ifdef CONFIG_RTW_80211K
struct fsm_state {
u8 *name;
int(*fsm_func)(struct rm_obj *prm, enum RM_EV_ID evid);
};
static void rm_state_initial(struct rm_obj *prm);
static void rm_state_goto(struct rm_obj *prm, enum RM_STATE rm_state);
static void rm_state_run(struct rm_obj *prm, enum RM_EV_ID evid);
static struct rm_event *rm_dequeue_ev(_queue *queue);
static struct rm_obj *rm_dequeue_rm(_queue *queue);
void rm_timer_callback(void *data)
{
int i;
_adapter *padapter = (_adapter *)data;
struct rm_priv *prmpriv = &padapter->rmpriv;
struct rm_clock *pclock;
/* deal with clock */
for (i=0;i<RM_TIMER_NUM;i++) {
pclock = &prmpriv->clock[i];
if (pclock->prm == NULL
||(ATOMIC_READ(&(pclock->counter)) == 0))
continue;
ATOMIC_DEC(&(pclock->counter));
if (ATOMIC_READ(&(pclock->counter)) == 0)
rm_post_event(pclock->prm->psta->padapter,
pclock->prm->rmid, prmpriv->clock[i].evid);
}
_set_timer(&prmpriv->rm_timer, CLOCK_UNIT);
}
int rtw_init_rm(_adapter *padapter)
{
struct rm_priv *prmpriv = &padapter->rmpriv;
RTW_INFO("RM: %s\n",__func__);
_rtw_init_queue(&(prmpriv->rm_queue));
_rtw_init_queue(&(prmpriv->ev_queue));
/* bit 0-7 */
prmpriv->rm_en_cap_def[0] = 0
/*| BIT(RM_LINK_MEAS_CAP_EN)*/
| BIT(RM_NB_REP_CAP_EN)
/*| BIT(RM_PARAL_MEAS_CAP_EN)*/
| BIT(RM_REPEAT_MEAS_CAP_EN)
| BIT(RM_BCN_PASSIVE_MEAS_CAP_EN)
| BIT(RM_BCN_ACTIVE_MEAS_CAP_EN)
| BIT(RM_BCN_TABLE_MEAS_CAP_EN)
/*| BIT(RM_BCN_MEAS_REP_COND_CAP_EN)*/;
/* bit 8-15 */
prmpriv->rm_en_cap_def[1] = 0
/*| BIT(RM_FRAME_MEAS_CAP_EN - 8)*/
#ifdef CONFIG_RTW_ACS
| BIT(RM_CH_LOAD_CAP_EN - 8)
| BIT(RM_NOISE_HISTO_CAP_EN - 8)
#endif
/*| BIT(RM_STATIS_MEAS_CAP_EN - 8)*/
/*| BIT(RM_LCI_MEAS_CAP_EN - 8)*/
/*| BIT(RM_LCI_AMIMUTH_CAP_EN - 8)*/
/*| BIT(RM_TRANS_STREAM_CAT_MEAS_CAP_EN - 8)*/
/*| BIT(RM_TRIG_TRANS_STREAM_CAT_MEAS_CAP_EN - 8)*/;
/* bit 16-23 */
prmpriv->rm_en_cap_def[2] = 0
/*| BIT(RM_AP_CH_REP_CAP_EN - 16)*/
/*| BIT(RM_RM_MIB_CAP_EN - 16)*/
/*| BIT(RM_OP_CH_MAX_MEAS_DUR0 - 16)*/
/*| BIT(RM_OP_CH_MAX_MEAS_DUR1 - 16)*/
/*| BIT(RM_OP_CH_MAX_MEAS_DUR2 - 16)*/
/*| BIT(RM_NONOP_CH_MAX_MEAS_DUR0 - 16)*/
/*| BIT(RM_NONOP_CH_MAX_MEAS_DUR1 - 16)*/
/*| BIT(RM_NONOP_CH_MAX_MEAS_DUR2 - 16)*/;
/* bit 24-31 */
prmpriv->rm_en_cap_def[3] = 0
/*| BIT(RM_MEAS_PILOT_CAP0 - 24)*/
/*| BIT(RM_MEAS_PILOT_CAP1 - 24)*/
/*| BIT(RM_MEAS_PILOT_CAP2 - 24)*/
/*| BIT(RM_MEAS_PILOT_TRANS_INFO_CAP_EN - 24)*/
/*| BIT(RM_NB_REP_TSF_OFFSET_CAP_EN - 24)*/
| BIT(RM_RCPI_MEAS_CAP_EN - 24)
| BIT(RM_RSNI_MEAS_CAP_EN - 24)
/*| BIT(RM_BSS_AVG_ACCESS_DELAY_CAP_EN - 24)*/;
/* bit 32-39 */
prmpriv->rm_en_cap_def[4] = 0
/*| BIT(RM_BSS_AVG_ACCESS_DELAY_CAP_EN - 32)*/
/*| BIT(RM_AVALB_ADMIS_CAPACITY_CAP_EN - 32)*/
/*| BIT(RM_ANT_CAP_EN - 32)*/;
prmpriv->enable = _TRUE;
/* clock timer */
rtw_init_timer(&prmpriv->rm_timer,
padapter, rm_timer_callback, padapter);
_set_timer(&prmpriv->rm_timer, CLOCK_UNIT);
return _SUCCESS;
}
int rtw_deinit_rm(_adapter *padapter)
{
struct rm_priv *prmpriv = &padapter->rmpriv;
struct rm_obj *prm;
struct rm_event *pev;
RTW_INFO("RM: %s\n",__func__);
prmpriv->enable = _FALSE;
_cancel_timer_ex(&prmpriv->rm_timer);
/* free all events and measurements */
while((pev = rm_dequeue_ev(&prmpriv->ev_queue)) != NULL)
rtw_mfree((void *)pev, sizeof(struct rm_event));
while((prm = rm_dequeue_rm(&prmpriv->rm_queue)) != NULL)
rm_state_run(prm, RM_EV_cancel);
_rtw_deinit_queue(&(prmpriv->rm_queue));
_rtw_deinit_queue(&(prmpriv->ev_queue));
return _SUCCESS;
}
int rtw_free_rm_priv(_adapter *padapter)
{
return rtw_deinit_rm(padapter);
}
static int rm_enqueue_ev(_queue *queue, struct rm_event *obj, bool to_head)
{
_irqL irqL;
if (obj == NULL)
return _FAIL;
_enter_critical(&queue->lock, &irqL);
if (to_head)
rtw_list_insert_head(&obj->list, &queue->queue);
else
rtw_list_insert_tail(&obj->list, &queue->queue);
_exit_critical(&queue->lock, &irqL);
return _SUCCESS;
}
static void rm_set_clock(struct rm_obj *prm, u32 ms, enum RM_EV_ID evid)
{
ATOMIC_SET(&(prm->pclock->counter), (ms/CLOCK_UNIT));
prm->pclock->evid = evid;
}
static struct rm_clock *rm_alloc_clock(_adapter *padapter, struct rm_obj *prm)
{
int i;
struct rm_priv *prmpriv = &padapter->rmpriv;
struct rm_clock *pclock = NULL;
for (i=0;i<RM_TIMER_NUM;i++) {
pclock = &prmpriv->clock[i];
if (pclock->prm == NULL) {
pclock->prm = prm;
ATOMIC_SET(&(pclock->counter), 0);
pclock->evid = RM_EV_max;
break;
}
}
return pclock;
}
static void rm_cancel_clock(struct rm_obj *prm)
{
ATOMIC_SET(&(prm->pclock->counter), 0);
prm->pclock->evid = RM_EV_max;
}
static void rm_free_clock(struct rm_clock *pclock)
{
pclock->prm = NULL;
ATOMIC_SET(&(pclock->counter), 0);
pclock->evid = RM_EV_max;
}
static int is_list_linked(const struct list_head *head)
{
return head->prev != NULL;
}
void rm_free_rmobj(struct rm_obj *prm)
{
if (is_list_linked(&prm->list))
rtw_list_delete(&prm->list);
if (prm->q.pssid)
rtw_mfree(prm->q.pssid, strlen(prm->q.pssid)+1);
if (prm->q.opt.bcn.req_start)
rtw_mfree(prm->q.opt.bcn.req_start,
prm->q.opt.bcn.req_len);
if (prm->pclock)
rm_free_clock(prm->pclock);
rtw_mfree((void *)prm, sizeof(struct rm_obj));
}
struct rm_obj *rm_alloc_rmobj(_adapter *padapter)
{
struct rm_obj *prm;
prm = (struct rm_obj *)rtw_malloc(sizeof(struct rm_obj));
if (prm == NULL)
return NULL;
_rtw_memset(prm, 0, sizeof(struct rm_obj));
/* alloc timer */
if ((prm->pclock = rm_alloc_clock(padapter, prm)) == NULL) {
rm_free_rmobj(prm);
return NULL;
}
return prm;
}
int rm_enqueue_rmobj(_adapter *padapter, struct rm_obj *prm, bool to_head)
{
_irqL irqL;
struct rm_priv *prmpriv = &padapter->rmpriv;
_queue *queue = &prmpriv->rm_queue;
if (prm == NULL)
return _FAIL;
_enter_critical(&queue->lock, &irqL);
if (to_head)
rtw_list_insert_head(&prm->list, &queue->queue);
else
rtw_list_insert_tail(&prm->list, &queue->queue);
_exit_critical(&queue->lock, &irqL);
rm_state_initial(prm);
return _SUCCESS;
}
static struct rm_obj *rm_dequeue_rm(_queue *queue)
{
_irqL irqL;
struct rm_obj *prm;
_enter_critical(&queue->lock, &irqL);
if (rtw_is_list_empty(&(queue->queue)))
prm = NULL;
else {
prm = LIST_CONTAINOR(get_next(&(queue->queue)),
struct rm_obj, list);
/* rtw_list_delete(&prm->list); */
}
_exit_critical(&queue->lock, &irqL);
return prm;
}
static struct rm_event *rm_dequeue_ev(_queue *queue)
{
_irqL irqL;
struct rm_event *ev;
_enter_critical(&queue->lock, &irqL);
if (rtw_is_list_empty(&(queue->queue)))
ev = NULL;
else {
ev = LIST_CONTAINOR(get_next(&(queue->queue)),
struct rm_event, list);
rtw_list_delete(&ev->list);
}
_exit_critical(&queue->lock, &irqL);
return ev;
}
static struct rm_obj *_rm_get_rmobj(_queue *queue, u32 rmid)
{
_irqL irqL;
_list *phead, *plist;
struct rm_obj *prm = NULL;
if (rmid == 0)
return NULL;
_enter_critical(&queue->lock, &irqL);
phead = get_list_head(queue);
plist = get_next(phead);
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
prm = LIST_CONTAINOR(plist, struct rm_obj, list);
if (rmid == (prm->rmid)) {
_exit_critical(&queue->lock, &irqL);
return prm;
}
plist = get_next(plist);
}
_exit_critical(&queue->lock, &irqL);
return NULL;
}
struct sta_info *rm_get_psta(_adapter *padapter, u32 rmid)
{
struct rm_priv *prmpriv = &padapter->rmpriv;
struct rm_obj *prm;
prm = _rm_get_rmobj(&prmpriv->rm_queue, rmid);
if (prm)
return prm->psta;
return NULL;
}
struct rm_obj *rm_get_rmobj(_adapter *padapter, u32 rmid)
{
struct rm_priv *prmpriv = &padapter->rmpriv;
return _rm_get_rmobj(&prmpriv->rm_queue, rmid);
}
u8 rtw_rm_post_envent_cmd(_adapter *padapter, u32 rmid, u8 evid)
{
struct cmd_obj *pcmd;
struct rm_event *pev;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
u8 res = _SUCCESS;
pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
if (pcmd == NULL) {
res = _FAIL;
goto exit;
}
pev = (struct rm_event*)rtw_zmalloc(sizeof(struct rm_event));
if (pev == NULL) {
rtw_mfree((u8 *) pcmd, sizeof(struct cmd_obj));
res = _FAIL;
goto exit;
}
pev->rmid = rmid;
pev->evid = evid;
init_h2fwcmd_w_parm_no_rsp(pcmd, pev, GEN_CMD_CODE(_RM_POST_EVENT));
res = rtw_enqueue_cmd(pcmdpriv, pcmd);
exit:
return res;
}
int rm_post_event(_adapter *padapter, u32 rmid, enum RM_EV_ID evid)
{
if (padapter->rmpriv.enable == _FALSE)
return _FALSE;
RTW_INFO("RM: post asyn %s to rmid=%x\n", rm_event_name(evid), rmid);
rtw_rm_post_envent_cmd(padapter, rmid, evid);
return _SUCCESS;
}
int _rm_post_event(_adapter *padapter, u32 rmid, enum RM_EV_ID evid)
{
struct rm_priv *prmpriv = &padapter->rmpriv;
struct rm_event *pev;
if (evid >= RM_EV_max || rmid == 0)
return _FALSE;
pev = (struct rm_event *)rtw_malloc(sizeof(struct rm_event));
if (pev == NULL)
return _FALSE;
pev->rmid = rmid;
pev->evid = evid;
RTW_INFO("RM: post sync %s to rmid=%x\n", rm_event_name(evid), rmid);
rm_enqueue_ev(&prmpriv->ev_queue, pev, FALSE);
return _SUCCESS;
}
static void rm_bcast_aid_handler(_adapter *padapter, struct rm_event *pev)
{
_irqL irqL;
_list *phead, *plist;
_queue *queue = &padapter->rmpriv.rm_queue;
struct rm_obj *prm;
_enter_critical(&queue->lock, &irqL);
phead = get_list_head(queue);
plist = get_next(phead);
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
prm = LIST_CONTAINOR(plist, struct rm_obj, list);
plist = get_next(plist);
if (RM_GET_AID(pev->rmid) == RM_GET_AID(prm->rmid)) {
_exit_critical(&queue->lock, &irqL);
rm_state_run(prm, pev->evid);
_enter_critical(&queue->lock, &irqL);
}
}
_exit_critical(&queue->lock, &irqL);
return;
}
/* main handler of RM (Resource Management) */
void rm_handler(_adapter *padapter, struct rm_event *pe)
{
int i;
struct rm_priv *prmpriv = &padapter->rmpriv;
struct rm_obj *prm;
struct rm_event *pev;
/* dequeue event */
while((pev = rm_dequeue_ev(&prmpriv->ev_queue)) != NULL)
{
if (RM_IS_ID_FOR_ALL(pev->rmid)) {
/* apply to all aid mateched measurement */
rm_bcast_aid_handler(padapter, pev);
rtw_mfree((void *)pev, sizeof(struct rm_event));
continue;
}
/* retrieve rmobj */
prm = _rm_get_rmobj(&prmpriv->rm_queue, pev->rmid);
if (prm == NULL) {
RTW_ERR("RM: rmid=%x event=%s doesn't find rm obj\n",
pev->rmid, rm_event_name(pev->evid));
rtw_mfree((void *)pev, sizeof(struct rm_event));
return;
}
/* run state machine */
rm_state_run(prm, pev->evid);
rtw_mfree((void *)pev, sizeof(struct rm_event));
}
}
static int rm_issue_meas_req(struct rm_obj *prm)
{
switch (prm->q.action_code) {
case RM_ACT_RADIO_MEAS_REQ:
switch (prm->q.m_type) {
case bcn_req:
case ch_load_req:
case noise_histo_req:
issue_radio_meas_req(prm);
break;
default:
break;
} /* meas_type */
break;
case RM_ACT_NB_REP_REQ:
/* issue neighbor request */
issue_nb_req(prm);
break;
case RM_ACT_LINK_MEAS_REQ:
default:
return _FALSE;
} /* action_code */
return _SUCCESS;
}
/*
* RM state machine
*/
static int rm_state_idle(struct rm_obj *prm, enum RM_EV_ID evid)
{
_adapter *padapter = prm->psta->padapter;
u8 val8;
u32 val32;
prm->p.category = RTW_WLAN_CATEGORY_RADIO_MEAS;
switch (evid) {
case RM_EV_state_in:
switch (prm->q.action_code) {
case RM_ACT_RADIO_MEAS_REQ:
/* copy attrib from meas_req to meas_rep */
prm->p.action_code = RM_ACT_RADIO_MEAS_REP;
prm->p.diag_token = prm->q.diag_token;
prm->p.e_id = _MEAS_RSP_IE_;
prm->p.m_token = prm->q.m_token;
prm->p.m_type = prm->q.m_type;
prm->p.rpt = prm->q.rpt;
prm->p.ch_num = prm->q.ch_num;
prm->p.op_class = prm->q.op_class;
if (prm->q.m_type == ch_load_req
|| prm->q.m_type == noise_histo_req) {
/*
* phydm measure current ch periodically
* scan current ch is not necessary
*/
val8 = padapter->mlmeextpriv.cur_channel;
if (prm->q.ch_num == val8)
prm->poll_mode = 1;
}
RTW_INFO("RM: rmid=%x %s switch in repeat=%u\n",
prm->rmid, rm_type_req_name(prm->q.m_type),
prm->q.rpt);
break;
case RM_ACT_NB_REP_REQ:
prm->p.action_code = RM_ACT_NB_REP_RESP;
RTW_INFO("RM: rmid=%x Neighbor request switch in\n",
prm->rmid);
break;
case RM_ACT_LINK_MEAS_REQ:
prm->p.action_code = RM_ACT_LINK_MEAS_REP;
rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);
RTW_INFO("RM: rmid=%x Link meas switch in\n",
prm->rmid);
break;
default:
prm->p.action_code = prm->q.action_code;
rm_set_rep_mode(prm, MEAS_REP_MOD_INCAP);
RTW_INFO("RM: rmid=%x recv unknown action %d\n",
prm->rmid,prm->p.action_code);
break;
} /* switch() */
if (prm->rmid & RM_MASTER) {
if (rm_issue_meas_req(prm) == _SUCCESS)
rm_state_goto(prm, RM_ST_WAIT_MEAS);
else
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
} else {
rm_state_goto(prm, RM_ST_DO_MEAS);
return _SUCCESS;
}
if (prm->p.m_mode) {
issue_null_reply(prm);
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
if (prm->q.rand_intvl) {
/* get low tsf to generate random interval */
val32 = rtw_read32(padapter, REG_TSFTR);
val32 = val32 % prm->q.rand_intvl;
RTW_INFO("RM: rmid=%x rand_intval=%d, rand=%d\n",
prm->rmid, (int)prm->q.rand_intvl,val32);
rm_set_clock(prm, prm->q.rand_intvl,
RM_EV_delay_timer_expire);
return _SUCCESS;
}
break;
case RM_EV_delay_timer_expire:
rm_state_goto(prm, RM_ST_DO_MEAS);
break;
case RM_EV_cancel:
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_state_out:
rm_cancel_clock(prm);
break;
default:
break;
}
return _SUCCESS;
}
/* we do the measuring */
static int rm_state_do_meas(struct rm_obj *prm, enum RM_EV_ID evid)
{
_adapter *padapter = prm->psta->padapter;
u8 val8;
u64 val64;
switch (evid) {
case RM_EV_state_in:
if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
switch (prm->q.m_type) {
case bcn_req:
if (prm->q.m_mode == bcn_req_bcn_table) {
RTW_INFO("RM: rmid=%x Beacon table\n",
prm->rmid);
_rm_post_event(padapter, prm->rmid,
RM_EV_survey_done);
return _SUCCESS;
}
break;
case ch_load_req:
case noise_histo_req:
if (prm->poll_mode)
_rm_post_event(padapter, prm->rmid,
RM_EV_survey_done);
return _SUCCESS;
default:
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
if (!ready_for_scan(prm)) {
prm->wait_busy = RM_BUSY_TRAFFIC_TIMES;
RTW_INFO("RM: wait busy traffic - %d\n",
prm->wait_busy);
rm_set_clock(prm, RM_WAIT_BUSY_TIMEOUT,
RM_EV_busy_timer_expire);
return _SUCCESS;
}
}
_rm_post_event(padapter, prm->rmid, RM_EV_start_meas);
break;
case RM_EV_start_meas:
if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
/* resotre measurement start time */
rtw_hal_get_hwreg(padapter, HW_VAR_TSF, (u8 *)&val64);
prm->meas_start_time = val64;
switch (prm->q.m_type) {
case bcn_req:
val8 = 1; /* Enable free run counter */
rtw_hal_set_hwreg(padapter,
HW_VAR_FREECNT, &val8);
rm_sitesurvey(prm);
break;
case ch_load_req:
case noise_histo_req:
rm_sitesurvey(prm);
break;
default:
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
break;
}
}
/* handle measurement timeout */
rm_set_clock(prm, RM_MEAS_TIMEOUT, RM_EV_meas_timer_expire);
break;
case RM_EV_survey_done:
if (prm->q.action_code == RM_ACT_RADIO_MEAS_REQ) {
switch (prm->q.m_type) {
case bcn_req:
rm_cancel_clock(prm);
rm_state_goto(prm, RM_ST_SEND_REPORT);
return _SUCCESS;
case ch_load_req:
case noise_histo_req:
retrieve_radio_meas_result(prm);
if (rm_radio_meas_report_cond(prm) == _SUCCESS)
rm_state_goto(prm, RM_ST_SEND_REPORT);
else
rm_set_clock(prm, RM_COND_INTVL,
RM_EV_retry_timer_expire);
break;
default:
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
}
break;
case RM_EV_meas_timer_expire:
RTW_INFO("RM: rmid=%x measurement timeount\n",prm->rmid);
rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
issue_null_reply(prm);
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_busy_timer_expire:
if (!ready_for_scan(prm) && prm->wait_busy--) {
RTW_INFO("RM: wait busy - %d\n",prm->wait_busy);
rm_set_clock(prm, RM_WAIT_BUSY_TIMEOUT,
RM_EV_busy_timer_expire);
break;
}
else if (prm->wait_busy <= 0) {
RTW_INFO("RM: wait busy timeout\n");
rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
issue_null_reply(prm);
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
_rm_post_event(padapter, prm->rmid, RM_EV_start_meas);
break;
case RM_EV_request_timer_expire:
rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
issue_null_reply(prm);
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_retry_timer_expire:
/* expired due to meas condition mismatch, meas again */
_rm_post_event(padapter, prm->rmid, RM_EV_start_meas);
break;
case RM_EV_cancel:
rm_set_rep_mode(prm, MEAS_REP_MOD_REFUSE);
issue_null_reply(prm);
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_state_out:
rm_cancel_clock(prm);
/* resotre measurement end time */
rtw_hal_get_hwreg(padapter, HW_VAR_TSF, (u8 *)&val64);
_rtw_memcpy(&prm->meas_end_time, (char *)&val64, sizeof(u64));
val8 = 0; /* Disable free run counter */
rtw_hal_set_hwreg(padapter, HW_VAR_FREECNT, &val8);
break;
default:
break;
}
return _SUCCESS;
}
static int rm_state_wait_meas(struct rm_obj *prm, enum RM_EV_ID evid)
{
u8 val8;
u64 val64;
switch (evid) {
case RM_EV_state_in:
/* we create meas_req, waiting for peer report */
rm_set_clock(prm, RM_REQ_TIMEOUT,
RM_EV_request_timer_expire);
break;
case RM_EV_recv_rep:
rm_state_goto(prm, RM_ST_RECV_REPORT);
break;
case RM_EV_request_timer_expire:
case RM_EV_cancel:
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_state_out:
rm_cancel_clock(prm);
break;
default:
break;
}
return _SUCCESS;
}
static int rm_state_send_report(struct rm_obj *prm, enum RM_EV_ID evid)
{
u8 val8;
switch (evid) {
case RM_EV_state_in:
/* we have to issue report */
switch (prm->q.m_type) {
case bcn_req:
issue_beacon_rep(prm);
break;
case ch_load_req:
case noise_histo_req:
issue_radio_meas_rep(prm);
break;
default:
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
/* check repeat */
if (prm->p.rpt) {
RTW_INFO("RM: rmid=%x repeat=%u/%u\n",
prm->rmid, prm->p.rpt,
prm->q.rpt);
prm->p.rpt--;
/*
* we recv meas_req,
* delay for a wihile and than meas again
*/
if (prm->poll_mode)
rm_set_clock(prm, RM_REPT_POLL_INTVL,
RM_EV_repeat_delay_expire);
else
rm_set_clock(prm, RM_REPT_SCAN_INTVL,
RM_EV_repeat_delay_expire);
return _SUCCESS;
}
/* we are done */
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_repeat_delay_expire:
rm_state_goto(prm, RM_ST_DO_MEAS);
break;
case RM_EV_cancel:
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_state_out:
rm_cancel_clock(prm);
break;
default:
break;
}
return _SUCCESS;
}
static int rm_state_recv_report(struct rm_obj *prm, enum RM_EV_ID evid)
{
u8 val8;
switch (evid) {
case RM_EV_state_in:
/* we issue meas_req, got peer's meas report */
switch (prm->p.action_code) {
case RM_ACT_RADIO_MEAS_REP:
/* check refuse, incapable and repeat */
val8 = prm->p.m_mode;
if (val8) {
RTW_INFO("RM: rmid=%x peer reject (%s repeat=%d)\n",
prm->rmid,
val8|MEAS_REP_MOD_INCAP?"INCAP":
val8|MEAS_REP_MOD_REFUSE?"REFUSE":
val8|MEAS_REP_MOD_LATE?"LATE":"",
prm->p.rpt);
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
break;
case RM_ACT_NB_REP_RESP:
/* report to upper layer if needing */
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
default:
rm_state_goto(prm, RM_ST_END);
return _SUCCESS;
}
/* check repeat */
if (prm->p.rpt) {
RTW_INFO("RM: rmid=%x repeat=%u/%u\n",
prm->rmid, prm->p.rpt,
prm->q.rpt);
prm->p.rpt--;
/* waitting more report */
rm_state_goto(prm, RM_ST_WAIT_MEAS);
break;
}
/* we are done */
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_cancel:
rm_state_goto(prm, RM_ST_END);
break;
case RM_EV_state_out:
rm_cancel_clock(prm);
break;
default:
break;
}
return _SUCCESS;
}
static int rm_state_end(struct rm_obj *prm, enum RM_EV_ID evid)
{
switch (evid) {
case RM_EV_state_in:
_rm_post_event(prm->psta->padapter, prm->rmid, RM_EV_state_out);
break;
case RM_EV_cancel:
case RM_EV_state_out:
default:
rm_free_rmobj(prm);
break;
}
return _SUCCESS;
}
struct fsm_state rm_fsm[] = {
{"RM_ST_IDLE", rm_state_idle},
{"RM_ST_DO_MEAS", rm_state_do_meas},
{"RM_ST_WAIT_MEAS", rm_state_wait_meas},
{"RM_ST_SEND_REPORT", rm_state_send_report},
{"RM_ST_RECV_REPORT", rm_state_recv_report},
{"RM_ST_END", rm_state_end}
};
char *rm_state_name(enum RM_STATE state)
{
return rm_fsm[state].name;
}
char *rm_event_name(enum RM_EV_ID evid)
{
switch(evid) {
case RM_EV_state_in:
return "RM_EV_state_in";
case RM_EV_busy_timer_expire:
return "RM_EV_busy_timer_expire";
case RM_EV_delay_timer_expire:
return "RM_EV_delay_timer_expire";
case RM_EV_meas_timer_expire:
return "RM_EV_meas_timer_expire";
case RM_EV_repeat_delay_expire:
return "RM_EV_repeat_delay_expire";
case RM_EV_retry_timer_expire:
return "RM_EV_retry_timer_expire";
case RM_EV_request_timer_expire:
return "RM_EV_request_timer_expire";
case RM_EV_wait_report:
return "RM_EV_wait_report";
case RM_EV_start_meas:
return "RM_EV_start_meas";
case RM_EV_survey_done:
return "RM_EV_survey_done";
case RM_EV_recv_rep:
return "RM_EV_recv_report";
case RM_EV_cancel:
return "RM_EV_cancel";
case RM_EV_state_out:
return "RM_EV_state_out";
case RM_EV_max:
return "RM_EV_max";
default:
return "RM_EV_unknown";
}
return "UNKNOWN";
}
static void rm_state_initial(struct rm_obj *prm)
{
prm->state = RM_ST_IDLE;
RTW_INFO("\n");
RTW_INFO("RM: rmid=%x %-18s -> %s\n",prm->rmid,
"new measurement", rm_fsm[prm->state].name);
rm_post_event(prm->psta->padapter, prm->rmid, RM_EV_state_in);
}
static void rm_state_run(struct rm_obj *prm, enum RM_EV_ID evid)
{
RTW_INFO("RM: rmid=%x %-18s %s\n",prm->rmid,
rm_fsm[prm->state].name,rm_event_name(evid));
rm_fsm[prm->state].fsm_func(prm, evid);
}
static void rm_state_goto(struct rm_obj *prm, enum RM_STATE rm_state)
{
if (prm->state == rm_state)
return;
rm_state_run(prm, RM_EV_state_out);
RTW_INFO("\n");
RTW_INFO("RM: rmid=%x %-18s -> %s\n",prm->rmid,
rm_fsm[prm->state].name, rm_fsm[rm_state].name);
prm->state = rm_state;
rm_state_run(prm, RM_EV_state_in);
}
#endif /* CONFIG_RTW_80211K */

595
core/rtw_rson.c Normal file
View File

@@ -0,0 +1,595 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RTW_RSON_C_
#include <drv_types.h>
#ifdef CONFIG_RTW_REPEATER_SON
/******** Custommize Part ***********************/
unsigned char RTW_RSON_OUI[] = {0xFA, 0xFA, 0xFA};
#define RSON_SCORE_DIFF_TH 8
/*
Calculate the corresponding score.
*/
inline u8 rtw_cal_rson_score(struct rtw_rson_struct *cand_rson_data, NDIS_802_11_RSSI Rssi)
{
if ((cand_rson_data->hopcnt == RTW_RSON_HC_NOTREADY)
|| (cand_rson_data->connectible == RTW_RSON_DENYCONNECT))
return RTW_RSON_SCORE_NOTCNNT;
return RTW_RSON_SCORE_MAX - (cand_rson_data->hopcnt * 10) + (Rssi/10);
}
/*************************************************/
static u8 rtw_rson_block_bssid_idx = 0;
u8 rtw_rson_block_bssid[10][6] = {
/*{0x02, 0xE0, 0x4C, 0x07, 0xC3, 0xF6}*/
};
/* fake root, regard a real AP as a SO root */
static u8 rtw_rson_root_bssid_idx = 0;
u8 rtw_rson_root_bssid[10][6] = {
/*{0x1c, 0x5f, 0x2b, 0x5a, 0x60, 0x24}*/
};
int is_match_bssid(u8 *mac, u8 bssid_array[][6], int num)
{
int i;
for (i = 0; i < num; i++)
if (_rtw_memcmp(mac, bssid_array[i], 6) == _TRUE)
return _TRUE;
return _FALSE;
}
void init_rtw_rson_data(struct dvobj_priv *dvobj)
{
/*Aries todo. if pdvobj->rson_data.ver == 1 */
dvobj->rson_data.ver = RTW_RSON_VER;
dvobj->rson_data.id = CONFIG_RTW_REPEATER_SON_ID;
#ifdef CONFIG_RTW_REPEATER_SON_ROOT
dvobj->rson_data.hopcnt = RTW_RSON_HC_ROOT;
dvobj->rson_data.connectible = RTW_RSON_ALLOWCONNECT;
#else
dvobj->rson_data.hopcnt = RTW_RSON_HC_NOTREADY;
dvobj->rson_data.connectible = RTW_RSON_DENYCONNECT;
#endif
dvobj->rson_data.loading = 0;
_rtw_memset(dvobj->rson_data.res, 0xAA, sizeof(dvobj->rson_data.res));
}
void rtw_rson_get_property_str(_adapter *padapter, char *rson_data_str)
{
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
sprintf(rson_data_str, "version : \t%d\nid : \t\t%08x\nhop count : \t%d\nconnectible : \t%s\nloading : \t%d\nreserve : \t%16ph\n",
pdvobj->rson_data.ver,
pdvobj->rson_data.id,
pdvobj->rson_data.hopcnt,
pdvobj->rson_data.connectible ? "connectable":"unconnectable",
pdvobj->rson_data.loading,
pdvobj->rson_data.res);
}
int str2hexbuf(char *str, u8 *hexbuf, int len)
{
u8 *p;
int i, slen, idx = 0;
p = (unsigned char *)str;
if ((*p != '0') || (*(p+1) != 'x'))
return _FALSE;
slen = strlen(str);
if (slen > (len*2) + 2)
return _FALSE;
p += 2;
for (i = 0 ; i < len; i++, idx = idx+2) {
hexbuf[i] = key_2char2num(p[idx], p[idx + 1]);
if (slen <= idx+2)
break;
}
return _TRUE;
}
int rtw_rson_set_property(_adapter *padapter, char *field, char *value)
{
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
int num = 0;
if (_rtw_memcmp(field, (u8 *)"ver", 3) == _TRUE)
pdvobj->rson_data.ver = rtw_atoi(value);
else if (_rtw_memcmp(field, (u8 *)"id", 2) == _TRUE)
num = sscanf(value, "%08x", &(pdvobj->rson_data.id));
else if (_rtw_memcmp(field, (u8 *)"hc", 2) == _TRUE)
num = sscanf(value, "%hhu", &(pdvobj->rson_data.hopcnt));
else if (_rtw_memcmp(field, (u8 *)"cnt", 3) == _TRUE)
num = sscanf(value, "%hhu", &(pdvobj->rson_data.connectible));
else if (_rtw_memcmp(field, (u8 *)"loading", 2) == _TRUE)
num = sscanf(value, "%hhu", &(pdvobj->rson_data.loading));
else if (_rtw_memcmp(field, (u8 *)"res", 2) == _TRUE) {
str2hexbuf(value, pdvobj->rson_data.res, 16);
return 1;
} else
return _FALSE;
return num;
}
/*
return : TRUE -- competitor is taking advantage than condidate
FALSE -- we should continue keeping candidate
*/
int rtw_rson_choose(struct wlan_network **candidate, struct wlan_network *competitor)
{
s16 comp_score = 0, cand_score = 0;
struct rtw_rson_struct rson_cand, rson_comp;
if (is_match_bssid(competitor->network.MacAddress, rtw_rson_block_bssid, rtw_rson_block_bssid_idx) == _TRUE)
return _FALSE;
if ((competitor == NULL)
|| (rtw_get_rson_struct(&(competitor->network), &rson_comp) != _TRUE)
|| (rson_comp.id != CONFIG_RTW_REPEATER_SON_ID))
return _FALSE;
comp_score = rtw_cal_rson_score(&rson_comp, competitor->network.Rssi);
if (comp_score == RTW_RSON_SCORE_NOTCNNT)
return _FALSE;
if (*candidate == NULL)
return _TRUE;
if (rtw_get_rson_struct(&((*candidate)->network), &rson_cand) != _TRUE)
return _FALSE;
cand_score = rtw_cal_rson_score(&rson_cand, (*candidate)->network.Rssi);
RTW_INFO("%s: competitor_score=%d, candidate_score=%d\n", __func__, comp_score, cand_score);
if (comp_score - cand_score > RSON_SCORE_DIFF_TH)
return _TRUE;
return _FALSE;
}
inline u8 rtw_rson_varify_ie(u8 *p)
{
u8 *ptr = NULL;
u8 ver;
u32 id;
u8 hopcnt;
u8 allcnnt;
ptr = p + 2 + sizeof(RTW_RSON_OUI);
ver = *ptr;
/* for (ver == 1) */
if (ver != 1)
return _FALSE;
return _TRUE;
}
/*
Parsing RTK self-organization vendor IE
*/
int rtw_get_rson_struct(WLAN_BSSID_EX *bssid, struct rtw_rson_struct *rson_data)
{
sint limit = 0;
u32 len;
u8 *p;
if ((rson_data == NULL) || (bssid == NULL))
return -EINVAL;
/* Default */
rson_data->id = 0;
rson_data->ver = 0;
rson_data->hopcnt = 0;
rson_data->connectible = 0;
rson_data->loading = 0;
/* fake root */
if (is_match_bssid(bssid->MacAddress, rtw_rson_root_bssid, rtw_rson_root_bssid_idx) == _TRUE) {
rson_data->id = CONFIG_RTW_REPEATER_SON_ID;
rson_data->ver = RTW_RSON_VER;
rson_data->hopcnt = RTW_RSON_HC_ROOT;
rson_data->connectible = RTW_RSON_ALLOWCONNECT;
rson_data->loading = 0;
return _TRUE;
}
limit = bssid->IELength - _BEACON_IE_OFFSET_;
for (p = bssid->IEs + _BEACON_IE_OFFSET_; ; p += (len + 2)) {
p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &len, limit);
limit -= len;
if ((p == NULL) || (len == 0))
break;
if (p && (_rtw_memcmp(p + 2, RTW_RSON_OUI, sizeof(RTW_RSON_OUI)) == _TRUE)
&& rtw_rson_varify_ie(p)) {
p = p + 2 + sizeof(RTW_RSON_OUI);
rson_data->ver = *p;
/* for (ver == 1) */
p = p + 1;
rson_data->id = le32_to_cpup((__le32 *)p);
p = p + 4;
rson_data->hopcnt = *p;
p = p + 1;
rson_data->connectible = *p;
p = p + 1;
rson_data->loading = *p;
return _TRUE;
}
}
return -EBADMSG;
}
u32 rtw_rson_append_ie(_adapter *padapter, unsigned char *pframe, u32 *len)
{
u8 *ptr, *ori, ie_len = 0;
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
/* static int iii = 0;*/
if ((!pdvobj) || (!pframe))
return 0;
ptr = ori = pframe;
*ptr++ = _VENDOR_SPECIFIC_IE_;
*ptr++ = ie_len = sizeof(RTW_RSON_OUI)+sizeof(pdvobj->rson_data);
_rtw_memcpy(ptr, RTW_RSON_OUI, sizeof(RTW_RSON_OUI));
ptr = ptr + sizeof(RTW_RSON_OUI);
*ptr++ = pdvobj->rson_data.ver;
*(s32 *)ptr = cpu_to_le32(pdvobj->rson_data.id);
ptr = ptr + sizeof(pdvobj->rson_data.id);
*ptr++ = pdvobj->rson_data.hopcnt;
*ptr++ = pdvobj->rson_data.connectible;
*ptr++ = pdvobj->rson_data.loading;
_rtw_memcpy(ptr, pdvobj->rson_data.res, sizeof(pdvobj->rson_data.res));
pframe = ptr;
/*
iii = iii % 20;
if (iii++ == 0)
RTW_INFO("%s : RTW RSON IE : %20ph\n", __func__, ori);
*/
*len += (ie_len+2);
return ie_len;
}
void rtw_rson_do_disconnect(_adapter *padapter)
{
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
#ifndef CONFIG_RTW_REPEATER_SON_ROOT
pdvobj->rson_data.ver = RTW_RSON_VER;
pdvobj->rson_data.id = CONFIG_RTW_REPEATER_SON_ID;
pdvobj->rson_data.hopcnt = RTW_RSON_HC_NOTREADY;
pdvobj->rson_data.connectible = RTW_RSON_DENYCONNECT;
pdvobj->rson_data.loading = 0;
rtw_mi_tx_beacon_hdl(padapter);
#endif
}
void rtw_rson_join_done(_adapter *padapter)
{
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
WLAN_BSSID_EX *cur_network = NULL;
struct rtw_rson_struct rson_data;
RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
if (!padapter->mlmepriv.cur_network_scanned)
return;
cur_network = &(padapter->mlmepriv.cur_network_scanned->network);
if (rtw_get_rson_struct(cur_network, &rson_data) != _TRUE) {
RTW_ERR("%s: try to join a improper network(%s)\n", __func__, cur_network->Ssid.Ssid);
return;
}
#ifndef CONFIG_RTW_REPEATER_SON_ROOT
/* update rson_data */
pdvobj->rson_data.ver = RTW_RSON_VER;
pdvobj->rson_data.id = rson_data.id;
pdvobj->rson_data.hopcnt = rson_data.hopcnt + 1;
pdvobj->rson_data.connectible = RTW_RSON_ALLOWCONNECT;
pdvobj->rson_data.loading = 0;
rtw_mi_tx_beacon_hdl(padapter);
#endif
}
int rtw_rson_isupdate_roamcan(struct mlme_priv *mlme
, struct wlan_network **candidate, struct wlan_network *competitor)
{
struct rtw_rson_struct rson_cand, rson_comp, rson_curr;
s16 comp_score, cand_score, curr_score;
if ((competitor == NULL)
|| (rtw_get_rson_struct(&(competitor->network), &rson_comp) != _TRUE)
|| (rson_comp.id != CONFIG_RTW_REPEATER_SON_ID))
return _FALSE;
if (is_match_bssid(competitor->network.MacAddress, rtw_rson_block_bssid, rtw_rson_block_bssid_idx) == _TRUE)
return _FALSE;
if ((!mlme->cur_network_scanned)
|| (mlme->cur_network_scanned == competitor)
|| (rtw_get_rson_struct(&(mlme->cur_network_scanned->network), &rson_curr)) != _TRUE)
return _FALSE;
if (rtw_get_passing_time_ms((u32)competitor->last_scanned) >= mlme->roam_scanr_exp_ms)
return _FALSE;
comp_score = rtw_cal_rson_score(&rson_comp, competitor->network.Rssi);
curr_score = rtw_cal_rson_score(&rson_curr, mlme->cur_network_scanned->network.Rssi);
if (comp_score - curr_score < RSON_SCORE_DIFF_TH)
return _FALSE;
if (*candidate == NULL)
return _TRUE;
if (rtw_get_rson_struct(&((*candidate)->network), &rson_cand) != _TRUE) {
RTW_ERR("%s : Unable to get rson_struct from candidate(%s -- " MAC_FMT")\n",
__func__, (*candidate)->network.Ssid.Ssid, MAC_ARG((*candidate)->network.MacAddress));
return _FALSE;
}
cand_score = rtw_cal_rson_score(&rson_cand, (*candidate)->network.Rssi);
RTW_DBG("comp_score=%d , cand_score=%d , curr_score=%d\n", comp_score, cand_score, curr_score);
if (cand_score < comp_score)
return _TRUE;
#if 0 /* Handle 11R protocol */
#ifdef CONFIG_RTW_80211R
if (rtw_chk_ft_flags(adapter, RTW_FT_SUPPORTED)) {
ptmp = rtw_get_ie(&competitor->network.IEs[12], _MDIE_, &mdie_len, competitor->network.IELength-12);
if (ptmp) {
if (!_rtw_memcmp(&pftpriv->mdid, ptmp+2, 2))
goto exit;
/*The candidate don't support over-the-DS*/
if (rtw_chk_ft_flags(adapter, RTW_FT_STA_OVER_DS_SUPPORTED)) {
if ((rtw_chk_ft_flags(adapter, RTW_FT_OVER_DS_SUPPORTED) && !(*(ptmp+4) & 0x01)) ||
(!rtw_chk_ft_flags(adapter, RTW_FT_OVER_DS_SUPPORTED) && (*(ptmp+4) & 0x01))) {
RTW_INFO("FT: ignore the candidate(" MAC_FMT ") for over-the-DS\n", MAC_ARG(competitor->network.MacAddress));
rtw_clr_ft_flags(adapter, RTW_FT_OVER_DS_SUPPORTED);
goto exit;
}
}
} else
goto exit;
}
#endif
#endif
return _FALSE;
}
void rtw_rson_show_survey_info(struct seq_file *m, _list *plist, _list *phead)
{
struct wlan_network *pnetwork = NULL;
struct rtw_rson_struct rson_data;
s16 rson_score;
u16 index = 0;
RTW_PRINT_SEL(m, "%5s %-17s %3s %5s %14s %10s %-3s %5s %32s\n", "index", "bssid", "ch", "id", "hop_cnt", "loading", "RSSI", "score", "ssid");
while (1) {
if (rtw_end_of_queue_search(phead, plist) == _TRUE)
break;
pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
if (!pnetwork)
break;
_rtw_memset(&rson_data, 0, sizeof(rson_data));
rson_score = 0;
if (rtw_get_rson_struct(&(pnetwork->network), &rson_data) == _TRUE)
rson_score = rtw_cal_rson_score(&rson_data, pnetwork->network.Rssi);
RTW_PRINT_SEL(m, "%5d "MAC_FMT" %3d 0x%08x %6d %10d %6d %6d %32s\n",
++index,
MAC_ARG(pnetwork->network.MacAddress),
pnetwork->network.Configuration.DSConfig,
rson_data.id,
rson_data.hopcnt,
rson_data.loading,
(int)pnetwork->network.Rssi,
rson_score,
pnetwork->network.Ssid.Ssid);
plist = get_next(plist);
}
}
/*
Description : As a AP role, We need to check the qualify of associating STA.
We also need to check if we are ready to be associated.
return : TRUE -- AP REJECT this STA
FALSE -- AP ACCEPT this STA
*/
u8 rtw_rson_ap_check_sta(_adapter *padapter, u8 *pframe, uint pkt_len, unsigned short ie_offset)
{
struct wlan_network *pnetwork = NULL;
struct rtw_rson_struct rson_target;
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
int len = 0;
u8 ret = _FALSE;
u8 *p;
#ifndef CONFIG_RTW_REPEATER_SON_ROOT
_rtw_memset(&rson_target, 0, sizeof(rson_target));
for (p = pframe + WLAN_HDR_A3_LEN + ie_offset; ; p += (len + 2)) {
p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
if ((p == NULL) || (len == 0))
break;
if (p && (_rtw_memcmp(p + 2, RTW_RSON_OUI, sizeof(RTW_RSON_OUI)) == _TRUE)
&& rtw_rson_varify_ie(p)) {
p = p + 2 + sizeof(RTW_RSON_OUI);
rson_target.ver = *p;
/* for (ver == 1) */
p = p + 1;
rson_target.id = le32_to_cpup((__le32 *)p);
p = p + 4;
rson_target.hopcnt = *p;
p = p + 1;
rson_target.connectible = *p;
p = p + 1;
rson_target.loading = *p;
break;
}
}
if (rson_target.id == 0) /* Normal STA, not a RSON STA */
ret = _FALSE;
else if (rson_target.id != pdvobj->rson_data.id) {
ret = _TRUE;
RTW_INFO("%s : Reject AssoReq because RSON ID not match, STA=%08x, our=%08x\n",
__func__, rson_target.id, pdvobj->rson_data.id);
} else if ((pdvobj->rson_data.hopcnt == RTW_RSON_HC_NOTREADY)
|| (pdvobj->rson_data.connectible == RTW_RSON_DENYCONNECT)) {
ret = _TRUE;
RTW_INFO("%s : Reject AssoReq becuase our hopcnt=%d or connectbile=%d\n",
__func__, pdvobj->rson_data.hopcnt, pdvobj->rson_data.connectible);
}
#endif
return ret;
}
u8 rtw_rson_scan_wk_cmd(_adapter *padapter, int op)
{
struct cmd_obj *ph2c;
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
u8 *extra_cmd_buf;
u8 res = _SUCCESS;
ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
if (ph2c == NULL) {
res = _FAIL;
goto exit;
}
pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
if (pdrvextra_cmd_parm == NULL) {
rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
res = _FAIL;
goto exit;
}
pdrvextra_cmd_parm->ec_id = RSON_SCAN_WK_CID;
pdrvextra_cmd_parm->type = op;
pdrvextra_cmd_parm->size = 0;
pdrvextra_cmd_parm->pbuf = NULL;
init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
res = rtw_enqueue_cmd(pcmdpriv, ph2c);
exit:
return res;
}
void rtw_rson_scan_cmd_hdl(_adapter *padapter, int op)
{
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
u8 val8;
if (mlmeext_chk_scan_state(pmlmeext, SCAN_DISABLE) != _TRUE)
return;
if (op == RSON_SCAN_PROCESS) {
padapter->rtw_rson_scanstage = RSON_SCAN_PROCESS;
val8 = 0x1e;
rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &val8, _FALSE);
val8 = 1;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
issue_probereq(padapter, NULL, NULL);
/* stop rson_scan after 100ms */
_set_timer(&(pmlmeext->rson_scan_timer), 100);
} else if (op == RSON_SCAN_DISABLE) {
padapter->rtw_rson_scanstage = RSON_SCAN_DISABLE;
val8 = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
val8 = 0xff;
rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &val8, _FALSE);
/* report_surveydone_event(padapter);*/
if (pmlmepriv->to_join == _TRUE) {
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) != _TRUE) {
int s_ret;
set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
pmlmepriv->to_join = _FALSE;
s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
if (s_ret == _SUCCESS)
_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
else if (s_ret == 2) {
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
rtw_indicate_connect(padapter);
} else {
RTW_INFO("try_to_join, but select scanning queue fail, to_roam:%d\n", rtw_to_roam(padapter));
if (rtw_to_roam(padapter) != 0) {
if (rtw_dec_to_roam(padapter) == 0) {
rtw_set_to_roam(padapter, 0);
#ifdef CONFIG_INTEL_WIDI
if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING) {
_rtw_memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
RTW_INFO("change to widi listen\n");
}
#endif /* CONFIG_INTEL_WIDI */
rtw_free_assoc_resources(padapter, 1);
rtw_indicate_disconnect(padapter, 0, _FALSE);
} else
pmlmepriv->to_join = _TRUE;
} else
rtw_indicate_disconnect(padapter, 0, _FALSE);
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
}
}
} else {
if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) {
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
&& check_fwstate(pmlmepriv, _FW_LINKED)) {
if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
#ifdef CONFIG_RTW_80211R
if (rtw_chk_ft_flags(padapter, RTW_FT_OVER_DS_SUPPORTED)) {
start_clnt_ft_action(adapter, (u8 *)pmlmepriv->roam_network->network.MacAddress);
} else {
/*wait a little time to retrieve packets buffered in the current ap while scan*/
_set_timer(&pmlmeext->ft_roam_timer, 30);
}
#else
receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress
, WLAN_REASON_ACTIVE_ROAM, _FALSE);
#endif
}
}
}
issue_action_BSSCoexistPacket(padapter);
issue_action_BSSCoexistPacket(padapter);
issue_action_BSSCoexistPacket(padapter);
}
} else {
RTW_ERR("%s : improper parameter -- op = %d\n", __func__, op);
}
}
#endif /* CONFIG_RTW_REPEATER_SON */

130
core/rtw_sdio.c Normal file
View File

@@ -0,0 +1,130 @@
/******************************************************************************
*
* Copyright(c) 2015 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#define _RTW_SDIO_C_
#include <drv_types.h> /* struct dvobj_priv and etc. */
#include <drv_types_sdio.h> /* RTW_SDIO_ADDR_CMD52_GEN */
/*
* Description:
* Use SDIO cmd52 or cmd53 to read/write data
*
* Parameters:
* d pointer of device object(struct dvobj_priv)
* addr SDIO address, 17 bits
* buf buffer for I/O
* len length
* write 0:read, 1:write
* cmd52 0:cmd52, 1:cmd53
*
* Return:
* _SUCCESS I/O ok.
* _FAIL I/O fail.
*/
static u8 sdio_io(struct dvobj_priv *d, u32 addr, void *buf, size_t len, u8 write, u8 cmd52)
{
u32 addr_drv; /* address with driver defined bit */
int err;
u8 retry = 0;
u8 stop_retry = _FALSE; /* flag for stopping retry or not */
if (rtw_is_surprise_removed(dvobj_get_primary_adapter(d))) {
RTW_ERR("%s: bSurpriseRemoved, skip %s 0x%05x, %zu bytes\n",
__FUNCTION__, write?"write":"read", addr, len);
return _FAIL;
}
addr_drv = addr;
if (cmd52)
addr_drv = RTW_SDIO_ADDR_CMD52_GEN(addr_drv);
do {
if (write)
err = d->intf_ops->write(d, addr_drv, buf, len, 0);
else
err = d->intf_ops->read(d, addr_drv, buf, len, 0);
if (!err) {
if (retry) {
RTW_INFO("%s: Retry %s OK! addr=0x%05x %zu bytes, retry=%u,%u\n",
__FUNCTION__, write?"write":"read",
addr, len, retry, ATOMIC_READ(&d->continual_io_error));
RTW_INFO_DUMP("Data: ", buf, len);
}
rtw_reset_continual_io_error(d);
break;
}
RTW_ERR("%s: %s FAIL! error(%d) addr=0x%05x %zu bytes, retry=%u,%u\n",
__FUNCTION__, write?"write":"read", err, addr, len,
retry, ATOMIC_READ(&d->continual_io_error));
retry++;
stop_retry = rtw_inc_and_chk_continual_io_error(d);
if ((err == -1) || (stop_retry == _TRUE) || (retry > SD_IO_TRY_CNT)) {
/* critical error, unrecoverable */
RTW_ERR("%s: Fatal error! Set surprise remove flag ON! (retry=%u,%u)\n",
__FUNCTION__, retry, ATOMIC_READ(&d->continual_io_error));
rtw_set_surprise_removed(dvobj_get_primary_adapter(d));
return _FAIL;
}
/* WLAN IOREG or SDIO Local */
if ((addr & 0x10000) || !(addr & 0xE000)) {
RTW_WARN("%s: Retry %s addr=0x%05x %zu bytes, retry=%u,%u\n",
__FUNCTION__, write?"write":"read", addr, len,
retry, ATOMIC_READ(&d->continual_io_error));
continue;
}
return _FAIL;
} while (1);
return _SUCCESS;
}
u8 rtw_sdio_read_cmd52(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
{
return sdio_io(d, addr, buf, len, 0, 1);
}
u8 rtw_sdio_read_cmd53(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
{
return sdio_io(d, addr, buf, len, 0, 0);
}
u8 rtw_sdio_write_cmd52(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
{
return sdio_io(d, addr, buf, len, 1, 1);
}
u8 rtw_sdio_write_cmd53(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
{
return sdio_io(d, addr, buf, len, 1, 0);
}
u8 rtw_sdio_f0_read(struct dvobj_priv *d, u32 addr, void *buf, size_t len)
{
int err;
u8 ret;
ret = _SUCCESS;
addr = RTW_SDIO_ADDR_F0_GEN(addr);
err = d->intf_ops->read(d, addr, buf, len, 0);
if (err)
ret = _FAIL;
return ret;
}

3408
core/rtw_security.c Normal file

File diff suppressed because it is too large Load Diff

332
core/rtw_sreset.c Normal file
View File

@@ -0,0 +1,332 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#include <drv_types.h>
#include <hal_data.h>
#include <rtw_sreset.h>
void sreset_init_value(_adapter *padapter)
{
#if defined(DBG_CONFIG_ERROR_DETECT)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
_rtw_mutex_init(&psrtpriv->silentreset_mutex);
psrtpriv->silent_reset_inprogress = _FALSE;
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
psrtpriv->last_tx_time = 0;
psrtpriv->last_tx_complete_time = 0;
#endif
}
void sreset_reset_value(_adapter *padapter)
{
#if defined(DBG_CONFIG_ERROR_DETECT)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
psrtpriv->last_tx_time = 0;
psrtpriv->last_tx_complete_time = 0;
#endif
}
u8 sreset_get_wifi_status(_adapter *padapter)
{
#if defined(DBG_CONFIG_ERROR_DETECT)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
u8 status = WIFI_STATUS_SUCCESS;
u32 val32 = 0;
_irqL irqL;
if (psrtpriv->silent_reset_inprogress == _TRUE)
return status;
val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
if (val32 == 0xeaeaeaea)
psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
else if (val32 != 0) {
RTW_INFO("txdmastatu(%x)\n", val32);
psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
}
if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
RTW_INFO("==>%s error_status(0x%x)\n", __FUNCTION__, psrtpriv->Wifi_Error_Status);
status = (psrtpriv->Wifi_Error_Status & (~(USB_READ_PORT_FAIL | USB_WRITE_PORT_FAIL)));
}
RTW_INFO("==> %s wifi_status(0x%x)\n", __FUNCTION__, status);
/* status restore */
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
return status;
#else
return WIFI_STATUS_SUCCESS;
#endif
}
void sreset_set_wifi_error_status(_adapter *padapter, u32 status)
{
#if defined(DBG_CONFIG_ERROR_DETECT)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.Wifi_Error_Status = status;
#endif
}
void sreset_set_trigger_point(_adapter *padapter, s32 tgp)
{
#if defined(DBG_CONFIG_ERROR_DETECT)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.dbg_trigger_point = tgp;
#endif
}
bool sreset_inprogress(_adapter *padapter)
{
#if defined(DBG_CONFIG_ERROR_RESET)
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
return pHalData->srestpriv.silent_reset_inprogress;
#else
return _FALSE;
#endif
}
void sreset_restore_security_station(_adapter *padapter)
{
u8 EntryId = 0;
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
struct sta_priv *pstapriv = &padapter->stapriv;
struct sta_info *psta;
struct security_priv *psecuritypriv = &(padapter->securitypriv);
struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
{
u8 val8;
if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) {
val8 = 0xcc;
#ifdef CONFIG_WAPI_SUPPORT
} else if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) {
/* Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey. */
val8 = 0x4c;
#endif
} else
val8 = 0xcf;
rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
}
if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
psta = rtw_get_stainfo(pstapriv, get_bssid(mlmepriv));
if (psta == NULL) {
/* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
} else {
/* pairwise key */
rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _FALSE);
/* group key */
rtw_set_key(padapter, &padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0, _FALSE);
}
}
}
void sreset_restore_network_station(_adapter *padapter)
{
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
u8 doiqk = _FALSE;
#if 0
{
/* ======================================================= */
/* reset related register of Beacon control */
/* set MSR to nolink */
Set_MSR(padapter, _HW_STATE_NOLINK_);
/* reject all data frame */
rtw_write16(padapter, REG_RXFLTMAP2, 0x00);
/* reset TSF */
rtw_write8(padapter, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
/* disable update TSF */
SetBcnCtrlReg(padapter, BIT(4), 0);
/* ======================================================= */
}
#endif
rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure, RTW_CMDF_DIRECTLY);
{
u8 threshold;
#ifdef CONFIG_USB_HCI
/* TH=1 => means that invalidate usb rx aggregation */
/* TH=0 => means that validate usb rx aggregation, use init value. */
if (mlmepriv->htpriv.ht_option) {
if (padapter->registrypriv.wifi_spec == 1)
threshold = 1;
else
threshold = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
} else {
threshold = 1;
rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
}
#endif
}
doiqk = _TRUE;
rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK , &doiqk);
set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
doiqk = _FALSE;
rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
/* disable dynamic functions, such as high power, DIG */
/*rtw_phydm_func_disable_all(padapter);*/
rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
{
u8 join_type = 0;
rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTING);
}
Set_MSR(padapter, (pmlmeinfo->state & 0x3));
mlmeext_joinbss_event_callback(padapter, 1);
/* restore Sequence No. */
rtw_hal_set_hwreg(padapter, HW_VAR_RESTORE_HW_SEQ, 0);
sreset_restore_security_station(padapter);
}
void sreset_restore_network_status(_adapter *padapter)
{
struct mlme_priv *mlmepriv = &padapter->mlmepriv;
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
sreset_restore_network_station(padapter);
} else if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
RTW_INFO(FUNC_ADPT_FMT" %s\n", FUNC_ADPT_ARG(padapter), MLME_IS_AP(padapter) ? "AP" : "MESH");
rtw_ap_restore_network(padapter);
} else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE))
RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
else
RTW_INFO(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
}
void sreset_stop_adapter(_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if (padapter == NULL)
return;
RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
rtw_netif_stop_queue(padapter->pnetdev);
rtw_cancel_all_timer(padapter);
/* TODO: OS and HCI independent */
#if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI)
tasklet_kill(&pxmitpriv->xmit_tasklet);
#endif
if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
rtw_scan_abort(padapter);
if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
rtw_set_to_roam(padapter, 0);
rtw_join_timeout_handler(padapter);
}
}
void sreset_start_adapter(_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
if (padapter == NULL)
return;
RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
if (check_fwstate(pmlmepriv, _FW_LINKED))
sreset_restore_network_status(padapter);
/* TODO: OS and HCI independent */
#if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI)
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
#endif
if (is_primary_adapter(padapter))
_set_timer(&adapter_to_dvobj(padapter)->dynamic_chk_timer, 2000);
rtw_netif_wake_queue(padapter->pnetdev);
}
void sreset_reset(_adapter *padapter)
{
#ifdef DBG_CONFIG_ERROR_RESET
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
struct sreset_priv *psrtpriv = &pHalData->srestpriv;
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
_irqL irqL;
systime start = rtw_get_current_time();
struct dvobj_priv *psdpriv = padapter->dvobj;
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
RTW_INFO("%s\n", __FUNCTION__);
psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
#ifdef CONFIG_LPS
rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "SRESET");
#endif/* #ifdef CONFIG_LPS */
_enter_pwrlock(&pwrpriv->lock);
psrtpriv->silent_reset_inprogress = _TRUE;
pwrpriv->change_rfpwrstate = rf_off;
rtw_mi_sreset_adapter_hdl(padapter, _FALSE);/*sreset_stop_adapter*/
#ifdef CONFIG_IPS
_ips_enter(padapter);
_ips_leave(padapter);
#endif
rtw_mi_sreset_adapter_hdl(padapter, _TRUE);/*sreset_start_adapter*/
psrtpriv->silent_reset_inprogress = _FALSE;
_exit_pwrlock(&pwrpriv->lock);
RTW_INFO("%s done in %d ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
pdbgpriv->dbg_sreset_cnt++;
psrtpriv->self_dect_fw = _FALSE;
psrtpriv->rx_cnt = 0;
#endif
}

1329
core/rtw_sta_mgt.c Normal file

File diff suppressed because it is too large Load Diff

3505
core/rtw_tdls.c Normal file

File diff suppressed because it is too large Load Diff

1053
core/rtw_vht.c Normal file

File diff suppressed because it is too large Load Diff

1312
core/rtw_wapi.c Normal file

File diff suppressed because it is too large Load Diff

922
core/rtw_wapi_sms4.c Normal file
View File

@@ -0,0 +1,922 @@
/******************************************************************************
*
* Copyright(c) 2016 - 2017 Realtek Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*****************************************************************************/
#ifdef CONFIG_WAPI_SUPPORT
#include <linux/unistd.h>
#include <linux/etherdevice.h>
#include <drv_types.h>
#include <rtw_wapi.h>
#ifdef CONFIG_WAPI_SW_SMS4
#define WAPI_LITTLE_ENDIAN
/* #define BIG_ENDIAN */
#define ENCRYPT 0
#define DECRYPT 1
/**********************************************************
**********************************************************/
const u8 Sbox[256] = {
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
};
const u32 CK[32] = {
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
};
#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y))))
#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \
Sbox[(_A) >> 16 & 0xFF] << 16 | \
Sbox[(_A) >> 8 & 0xFF] << 8 | \
Sbox[(_A) & 0xFF])
#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24))
#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23))
static void
xor_block(void *dst, void *src1, void *src2)
/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned */
{
((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0];
((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1];
((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2];
((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3];
}
void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk)
{
u32 r, mid, x0, x1, x2, x3, *p;
p = (u32 *)Input;
x0 = p[0];
x1 = p[1];
x2 = p[2];
x3 = p[3];
#ifdef WAPI_LITTLE_ENDIAN
x0 = Rotl(x0, 16);
x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
x1 = Rotl(x1, 16);
x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
x2 = Rotl(x2, 16);
x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
x3 = Rotl(x3, 16);
x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
#endif
for (r = 0; r < 32; r += 4) {
mid = x1 ^ x2 ^ x3 ^ rk[r + 0];
mid = ByteSub(mid);
x0 ^= L1(mid);
mid = x2 ^ x3 ^ x0 ^ rk[r + 1];
mid = ByteSub(mid);
x1 ^= L1(mid);
mid = x3 ^ x0 ^ x1 ^ rk[r + 2];
mid = ByteSub(mid);
x2 ^= L1(mid);
mid = x0 ^ x1 ^ x2 ^ rk[r + 3];
mid = ByteSub(mid);
x3 ^= L1(mid);
}
#ifdef WAPI_LITTLE_ENDIAN
x0 = Rotl(x0, 16);
x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
x1 = Rotl(x1, 16);
x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
x2 = Rotl(x2, 16);
x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
x3 = Rotl(x3, 16);
x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
#endif
p = (u32 *)Output;
p[0] = x3;
p[1] = x2;
p[2] = x1;
p[3] = x0;
}
void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag)
{
u32 r, mid, x0, x1, x2, x3, *p;
p = (u32 *)Key;
x0 = p[0];
x1 = p[1];
x2 = p[2];
x3 = p[3];
#ifdef WAPI_LITTLE_ENDIAN
x0 = Rotl(x0, 16);
x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
x1 = Rotl(x1, 16);
x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
x2 = Rotl(x2, 16);
x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
x3 = Rotl(x3, 16);
x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
#endif
x0 ^= 0xa3b1bac6;
x1 ^= 0x56aa3350;
x2 ^= 0x677d9197;
x3 ^= 0xb27022dc;
for (r = 0; r < 32; r += 4) {
mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
mid = ByteSub(mid);
rk[r + 0] = x0 ^= L2(mid);
mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
mid = ByteSub(mid);
rk[r + 1] = x1 ^= L2(mid);
mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
mid = ByteSub(mid);
rk[r + 2] = x2 ^= L2(mid);
mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
mid = ByteSub(mid);
rk[r + 3] = x3 ^= L2(mid);
}
if (CryptFlag == DECRYPT) {
for (r = 0; r < 16; r++)
mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid;
}
}
void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
u8 *Output, u16 *OutputLength, u32 CryptFlag)
{
u32 blockNum, i, j, rk[32];
u16 remainder;
u8 blockIn[16], blockOut[16], tempIV[16], k;
*OutputLength = 0;
remainder = InputLength & 0x0F;
blockNum = InputLength >> 4;
if (remainder != 0)
blockNum++;
else
remainder = 16;
for (k = 0; k < 16; k++)
tempIV[k] = IV[15 - k];
memcpy(blockIn, tempIV, 16);
SMS4KeyExt((u8 *)Key, rk, CryptFlag);
for (i = 0; i < blockNum - 1; i++) {
SMS4Crypt((u8 *)blockIn, blockOut, rk);
xor_block(&Output[i * 16], &Input[i * 16], blockOut);
memcpy(blockIn, blockOut, 16);
}
*OutputLength = i * 16;
SMS4Crypt((u8 *)blockIn, blockOut, rk);
for (j = 0; j < remainder; j++)
Output[i * 16 + j] = Input[i * 16 + j] ^ blockOut[j];
*OutputLength += remainder;
}
void WapiSMS4Encryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
u8 *Output, u16 *OutputLength)
{
WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
}
void WapiSMS4Decryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
u8 *Output, u16 *OutputLength)
{
/* OFB mode: is also ENCRYPT flag */
WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
}
void WapiSMS4CalculateMic(u8 *Key, u8 *IV, u8 *Input1, u8 Input1Length,
u8 *Input2, u16 Input2Length, u8 *Output, u8 *OutputLength)
{
u32 blockNum, i, remainder, rk[32];
u8 BlockIn[16], BlockOut[16], TempBlock[16], tempIV[16], k;
*OutputLength = 0;
remainder = Input1Length & 0x0F;
blockNum = Input1Length >> 4;
for (k = 0; k < 16; k++)
tempIV[k] = IV[15 - k];
memcpy(BlockIn, tempIV, 16);
SMS4KeyExt((u8 *)Key, rk, ENCRYPT);
SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
for (i = 0; i < blockNum; i++) {
xor_block(BlockIn, (Input1 + i * 16), BlockOut);
SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
}
if (remainder != 0) {
memset(TempBlock, 0, 16);
memcpy(TempBlock, (Input1 + blockNum * 16), remainder);
xor_block(BlockIn, TempBlock, BlockOut);
SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
}
remainder = Input2Length & 0x0F;
blockNum = Input2Length >> 4;
for (i = 0; i < blockNum; i++) {
xor_block(BlockIn, (Input2 + i * 16), BlockOut);
SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
}
if (remainder != 0) {
memset(TempBlock, 0, 16);
memcpy(TempBlock, (Input2 + blockNum * 16), remainder);
xor_block(BlockIn, TempBlock, BlockOut);
SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
}
memcpy(Output, BlockOut, 16);
*OutputLength = 16;
}
void SecCalculateMicSMS4(
u8 KeyIdx,
u8 *MicKey,
u8 *pHeader,
u8 *pData,
u16 DataLen,
u8 *MicBuffer
)
{
#if 0
struct ieee80211_hdr_3addr_qos *header;
u8 TempBuf[34], TempLen = 32, MicLen, QosOffset, *IV;
u16 *pTemp, fc;
WAPI_TRACE(WAPI_TX | WAPI_RX, "=========>%s\n", __FUNCTION__);
header = (struct ieee80211_hdr_3addr_qos *)pHeader;
memset(TempBuf, 0, 34);
memcpy(TempBuf, pHeader, 2); /* FrameCtrl */
pTemp = (u16 *)TempBuf;
*pTemp &= 0xc78f; /* bit4,5,6,11,12,13 */
memcpy((TempBuf + 2), (pHeader + 4), 12); /* Addr1, Addr2 */
memcpy((TempBuf + 14), (pHeader + 22), 2); /* SeqCtrl */
pTemp = (u16 *)(TempBuf + 14);
*pTemp &= 0x000f;
memcpy((TempBuf + 16), (pHeader + 16), 6); /* Addr3 */
fc = le16_to_cpu(header->frame_ctl);
if (GetFrDs((u16 *)&fc) && GetToDs((u16 *)&fc)) {
memcpy((TempBuf + 22), (pHeader + 24), 6);
QosOffset = 30;
} else {
memset((TempBuf + 22), 0, 6);
QosOffset = 24;
}
if ((fc & 0x0088) == 0x0088) {
memcpy((TempBuf + 28), (pHeader + QosOffset), 2);
TempLen += 2;
/* IV = pHeader + QosOffset + 2 + SNAP_SIZE + sizeof(u16) + 2; */
IV = pHeader + QosOffset + 2 + 2;
} else {
IV = pHeader + QosOffset + 2;
/* IV = pHeader + QosOffset + SNAP_SIZE + sizeof(u16) + 2; */
}
TempBuf[TempLen - 1] = (u8)(DataLen & 0xff);
TempBuf[TempLen - 2] = (u8)((DataLen & 0xff00) >> 8);
TempBuf[TempLen - 4] = KeyIdx;
WAPI_DATA(WAPI_TX, "CalculateMic - KEY", MicKey, 16);
WAPI_DATA(WAPI_TX, "CalculateMic - IV", IV, 16);
WAPI_DATA(WAPI_TX, "CalculateMic - TempBuf", TempBuf, TempLen);
WAPI_DATA(WAPI_TX, "CalculateMic - pData", pData, DataLen);
WapiSMS4CalculateMic(MicKey, IV, TempBuf, TempLen,
pData, DataLen, MicBuffer, &MicLen);
if (MicLen != 16)
WAPI_TRACE(WAPI_ERR, "%s: MIC Length Error!!\n", __FUNCTION__);
WAPI_TRACE(WAPI_TX | WAPI_RX, "<=========%s\n", __FUNCTION__);
#endif
}
/* AddCount: 1 or 2.
* If overflow, return 1,
* else return 0.
*/
u8 WapiIncreasePN(u8 *PN, u8 AddCount)
{
u8 i;
if (NULL == PN)
return 1;
/* YJ,test,091102 */
/*
if(AddCount == 2){
RTW_INFO("############################%s(): PN[0]=0x%x\n", __FUNCTION__, PN[0]);
if(PN[0] == 0x48){
PN[0] += AddCount;
return 1;
}else{
PN[0] += AddCount;
return 0;
}
}
*/
/* YJ,test,091102,end */
for (i = 0; i < 16; i++) {
if (PN[i] + AddCount <= 0xff) {
PN[i] += AddCount;
return 0;
} else {
PN[i] += AddCount;
AddCount = 1;
}
}
return 1;
}
void WapiGetLastRxUnicastPNForQoSData(
u8 UserPriority,
PRT_WAPI_STA_INFO pWapiStaInfo,
u8 *PNOut
)
{
WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
switch (UserPriority) {
case 0:
case 3:
memcpy(PNOut, pWapiStaInfo->lastRxUnicastPNBEQueue, 16);
break;
case 1:
case 2:
memcpy(PNOut, pWapiStaInfo->lastRxUnicastPNBKQueue, 16);
break;
case 4:
case 5:
memcpy(PNOut, pWapiStaInfo->lastRxUnicastPNVIQueue, 16);
break;
case 6:
case 7:
memcpy(PNOut, pWapiStaInfo->lastRxUnicastPNVOQueue, 16);
break;
default:
WAPI_TRACE(WAPI_ERR, "%s: Unknown TID\n", __FUNCTION__);
break;
}
WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
}
void WapiSetLastRxUnicastPNForQoSData(
u8 UserPriority,
u8 *PNIn,
PRT_WAPI_STA_INFO pWapiStaInfo
)
{
WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
switch (UserPriority) {
case 0:
case 3:
memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue, PNIn, 16);
break;
case 1:
case 2:
memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue, PNIn, 16);
break;
case 4:
case 5:
memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue, PNIn, 16);
break;
case 6:
case 7:
memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue, PNIn, 16);
break;
default:
WAPI_TRACE(WAPI_ERR, "%s: Unknown TID\n", __FUNCTION__);
break;
}
WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
}
/****************************************************************************
FALSE not RX-Reorder
TRUE do RX Reorder
add to support WAPI to N-mode
*****************************************************************************/
u8 WapiCheckPnInSwDecrypt(
_adapter *padapter,
struct sk_buff *pskb
)
{
u8 ret = false;
#if 0
struct ieee80211_hdr_3addr_qos *header;
u16 fc;
u8 *pDaddr, *pTaddr, *pRaddr;
header = (struct ieee80211_hdr_3addr_qos *)pskb->data;
pTaddr = header->addr2;
pRaddr = header->addr1;
fc = le16_to_cpu(header->frame_ctl);
if (GetToDs(&fc))
pDaddr = header->addr3;
else
pDaddr = header->addr1;
if ((_rtw_memcmp(pRaddr, padapter->pnetdev->dev_addr, ETH_ALEN) == 0)
&& !(pDaddr)
&& (GetFrameType(&fc) == WIFI_QOS_DATA_TYPE))
/* && ieee->pHTInfo->bCurrentHTSupport && */
/* ieee->pHTInfo->bCurRxReorderEnable) */
ret = false;
else
ret = true;
#endif
WAPI_TRACE(WAPI_RX, "%s: return %d\n", __FUNCTION__, ret);
return ret;
}
int SecSMS4HeaderFillIV(_adapter *padapter, u8 *pxmitframe)
{
struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
u8 *frame = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
u8 *pSecHeader = NULL, *pos = NULL, *pRA = NULL;
u8 bPNOverflow = false, bFindMatchPeer = false, hdr_len = 0;
PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
PRT_WAPI_STA_INFO pWapiSta = NULL;
int ret = 0;
WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
return ret;
#if 0
hdr_len = sMacHdrLng;
if (GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE)
hdr_len += 2;
/* hdr_len += SNAP_SIZE + sizeof(u16); */
pos = skb_push(pskb, padapter->wapiInfo.extra_prefix_len);
memmove(pos, pos + padapter->wapiInfo.extra_prefix_len, hdr_len);
pSecHeader = pskb->data + hdr_len;
pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)pSecHeader;
pRA = pskb->data + 4;
WAPI_DATA(WAPI_TX, "FillIV - Before Fill IV", pskb->data, pskb->len);
/* Address 1 is always receiver's address */
if (IS_MCAST(pRA)) {
if (!pWapiInfo->wapiTxMsk.bTxEnable) {
WAPI_TRACE(WAPI_ERR, "%s: bTxEnable = 0!!\n", __FUNCTION__);
return -2;
}
if (pWapiInfo->wapiTxMsk.keyId <= 1) {
pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
pWapiExt->Reserved = 0;
bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
if (bPNOverflow) {
/* Update MSK Notification. */
WAPI_TRACE(WAPI_ERR, "===============>%s():multicast PN overflow\n", __FUNCTION__);
rtw_wapi_app_event_handler(padapter, NULL, 0, pRA, false, false, true, 0, false);
}
} else {
WAPI_TRACE(WAPI_ERR, "%s: Invalid Wapi Multicast KeyIdx!!\n", __FUNCTION__);
ret = -3;
}
} else {
list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
if (!memcmp(pWapiSta->PeerMacAddr, pRA, 6)) {
bFindMatchPeer = true;
break;
}
}
if (bFindMatchPeer) {
if ((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)) {
WAPI_TRACE(WAPI_ERR, "%s: bTxEnable = 0!!\n", __FUNCTION__);
return -4;
}
if (pWapiSta->wapiUsk.keyId <= 1) {
if (pWapiSta->wapiUskUpdate.bTxEnable)
pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
else
pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
pWapiExt->Reserved = 0;
bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
if (bPNOverflow) {
/* Update USK Notification. */
WAPI_TRACE(WAPI_ERR, "===============>%s():unicast PN overflow\n", __FUNCTION__);
rtw_wapi_app_event_handler(padapter, NULL, 0, pWapiSta->PeerMacAddr, false, true, false, 0, false);
}
} else {
WAPI_TRACE(WAPI_ERR, "%s: Invalid Wapi Unicast KeyIdx!!\n", __FUNCTION__);
ret = -5;
}
} else {
WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT"!!\n", __FUNCTION__, MAC_ARG(pRA));
ret = -6;
}
}
WAPI_DATA(WAPI_TX, "FillIV - After Fill IV", pskb->data, pskb->len);
WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
return ret;
#endif
}
/* WAPI SW Enc: must have done Coalesce! */
void SecSWSMS4Encryption(
_adapter *padapter,
u8 *pxmitframe
)
{
PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
PRT_WAPI_STA_INFO pWapiSta = NULL;
u8 *pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_SIZE;
struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL;
u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16];
u16 OutputLength;
WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
WAPI_TRACE(WAPI_TX, "hdrlen: %d\n", pattrib->hdrlen);
return;
DataOffset = pattrib->hdrlen + pattrib->iv_len;
pRA = pframe + 4;
if (IS_MCAST(pRA)) {
KeyIdx = pWapiInfo->wapiTxMsk.keyId;
pIV = pWapiInfo->lastTxMulticastPN;
pMicKey = pWapiInfo->wapiTxMsk.micKey;
pDataKey = pWapiInfo->wapiTxMsk.dataKey;
} else {
if (!list_empty(&(pWapiInfo->wapiSTAUsedList))) {
list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
if (0 == memcmp(pWapiSta->PeerMacAddr, pRA, 6)) {
bFindMatchPeer = true;
break;
}
}
if (bFindMatchPeer) {
if (pWapiSta->wapiUskUpdate.bTxEnable) {
KeyIdx = pWapiSta->wapiUskUpdate.keyId;
WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
pIV = pWapiSta->lastTxUnicastPN;
pMicKey = pWapiSta->wapiUskUpdate.micKey;
pDataKey = pWapiSta->wapiUskUpdate.dataKey;
} else {
KeyIdx = pWapiSta->wapiUsk.keyId;
WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
pIV = pWapiSta->lastTxUnicastPN;
pMicKey = pWapiSta->wapiUsk.micKey;
pDataKey = pWapiSta->wapiUsk.dataKey;
}
} else {
WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta!!\n", __FUNCTION__);
return;
}
} else {
WAPI_TRACE(WAPI_ERR, "%s: wapiSTAUsedList is empty!!\n", __FUNCTION__);
return;
}
}
SecPtr = pframe;
SecCalculateMicSMS4(KeyIdx, pMicKey, SecPtr, (SecPtr + DataOffset), pattrib->pktlen, MicBuffer);
WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, padapter->wapiInfo.extra_postfix_len);
memcpy(pframe + pattrib->hdrlen + pattrib->iv_len + pattrib->pktlen - pattrib->icv_len,
(u8 *)MicBuffer,
padapter->wapiInfo.extra_postfix_len
);
WapiSMS4Encryption(pDataKey, pIV, (SecPtr + DataOffset), pattrib->pktlen + pattrib->icv_len, (SecPtr + DataOffset), &OutputLength);
WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption", pframe, pattrib->hdrlen + pattrib->iv_len + pattrib->pktlen);
WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
}
u8 SecSWSMS4Decryption(
_adapter *padapter,
u8 *precv_frame,
struct recv_priv *precv_priv
)
{
PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
struct recv_frame_hdr *precv_hdr;
PRT_WAPI_STA_INFO pWapiSta = NULL;
u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false;
u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16];
u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos;
u8 TID = 0;
u16 OutputLength, DataLen;
u8 bQosData;
struct sk_buff *pskb;
WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
return 0;
precv_hdr = &((union recv_frame *)precv_frame)->u.hdr;
pskb = (struct sk_buff *)(precv_hdr->rx_data);
precv_hdr->bWapiCheckPNInDecrypt = WapiCheckPnInSwDecrypt(padapter, pskb);
WAPI_TRACE(WAPI_RX, "=========>%s: check PN %d\n", __FUNCTION__, precv_hdr->bWapiCheckPNInDecrypt);
WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len);
IVOffset = sMacHdrLng;
bQosData = GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE;
if (bQosData)
IVOffset += 2;
/* if(GetHTC()) */
/* IVOffset += 4; */
/* IVOffset += SNAP_SIZE + sizeof(u16); */
DataOffset = IVOffset + padapter->wapiInfo.extra_prefix_len;
pRA = pskb->data + 4;
pTA = pskb->data + 10;
KeyIdx = *(pskb->data + IVOffset);
pRecvPN = pskb->data + IVOffset + 2;
pSecData = pskb->data + DataOffset;
DataLen = pskb->len - DataOffset;
pRecvMic = pskb->data + pskb->len - padapter->wapiInfo.extra_postfix_len;
TID = GetTid(pskb->data);
if (!list_empty(&(pWapiInfo->wapiSTAUsedList))) {
list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
if (0 == memcmp(pWapiSta->PeerMacAddr, pTA, 6)) {
bFindMatchPeer = true;
break;
}
}
}
if (!bFindMatchPeer) {
WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA));
return false;
}
if (IS_MCAST(pRA)) {
WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__);
if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet) {
pLastRxPN = pWapiSta->lastRxMulticastPN;
if (!WapiComparePN(pRecvPN, pLastRxPN)) {
WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__);
WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16);
WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16);
return false;
}
memcpy(pLastRxPN, pRecvPN, 16);
pMicKey = pWapiSta->wapiMsk.micKey;
pDataKey = pWapiSta->wapiMsk.dataKey;
} else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet) {
WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__);
bUseUpdatedKey = true;
memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16);
pMicKey = pWapiSta->wapiMskUpdate.micKey;
pDataKey = pWapiSta->wapiMskUpdate.dataKey;
} else {
WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__, KeyIdx);
return false;
}
} else {
WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__);
if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet) {
WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__);
if (precv_hdr->bWapiCheckPNInDecrypt) {
if (GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE) {
WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS);
pLastRxPN = lastRxPNforQoS;
} else
pLastRxPN = pWapiSta->lastRxUnicastPN;
if (!WapiComparePN(pRecvPN, pLastRxPN))
return false;
if (bQosData)
WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
else
memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
} else
memcpy(precv_hdr->WapiTempPN, pRecvPN, 16);
if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE)) {
if ((pRecvPN[0] & 0x1) == 0) {
WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__);
return false;
}
}
pMicKey = pWapiSta->wapiUsk.micKey;
pDataKey = pWapiSta->wapiUsk.dataKey;
} else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet) {
WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__);
if (pWapiSta->bAuthenticatorInUpdata)
bUseUpdatedKey = true;
else
bUseUpdatedKey = false;
if (bQosData)
WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
else
memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
pMicKey = pWapiSta->wapiUskUpdate.micKey;
pDataKey = pWapiSta->wapiUskUpdate.dataKey;
} else {
WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId,
pWapiSta->wapiUskUpdate.keyId);
/* dump_buf(pskb->data,pskb->len); */
return false;
}
}
WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16);
WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16);
WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength);
if (OutputLength != DataLen)
WAPI_TRACE(WAPI_ERR, "%s: Output Length Error!!!!\n", __FUNCTION__);
WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len);
DataLen -= padapter->wapiInfo.extra_postfix_len;
SecCalculateMicSMS4(KeyIdx, pMicKey, pskb->data, pSecData, DataLen, MicBuffer);
WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN);
WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN);
if (0 == memcmp(MicBuffer, pRecvMic, padapter->wapiInfo.extra_postfix_len)) {
WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__);
if (bUseUpdatedKey) {
/* delete the old key */
if (IS_MCAST(pRA)) {
WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__);
pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId;
memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16);
memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16);
pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false;
} else {
WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__);
pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId;
memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16);
memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16);
pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false;
}
}
} else {
WAPI_TRACE(WAPI_ERR, "%s: Check MIC Error, Dropped !!!!\n", __FUNCTION__);
return false;
}
pos = pskb->data;
memmove(pos + padapter->wapiInfo.extra_prefix_len, pos, IVOffset);
skb_pull(pskb, padapter->wapiInfo.extra_prefix_len);
WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
return true;
}
u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
{
u8 *pframe;
u32 res = _SUCCESS;
WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) {
WAPI_TRACE(WAPI_TX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
return _FAIL;
}
if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
return _FAIL;
pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
SecSWSMS4Encryption(padapter, pxmitframe);
WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
return res;
}
u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
{
u8 *pframe;
u32 res = _SUCCESS;
WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable)) {
WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
return _FAIL;
}
/* drop packet when hw decrypt fail
* return tempraily */
return _FAIL;
/* pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data; */
if (false == SecSWSMS4Decryption(padapter, precvframe, &padapter->recvpriv)) {
WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n", __FUNCTION__);
return _FAIL;
}
WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
return res;
}
#else
u32 rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
{
WAPI_TRACE(WAPI_TX, "=========>Dummy %s\n", __FUNCTION__);
WAPI_TRACE(WAPI_TX, "<=========Dummy %s\n", __FUNCTION__);
return _SUCCESS;
}
u32 rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
{
WAPI_TRACE(WAPI_RX, "=========>Dummy %s\n", __FUNCTION__);
WAPI_TRACE(WAPI_RX, "<=========Dummy %s\n", __FUNCTION__);
return _SUCCESS;
}
#endif
#endif

4725
core/rtw_wlan_util.c Normal file

File diff suppressed because it is too large Load Diff

5834
core/rtw_xmit.c Normal file

File diff suppressed because it is too large Load Diff