Files
luban-lite/bsp/peripheral/wireless/atbm603x/net/wpa/p2p/p2p_main.c
刘可亮 8bca5e8332 v1.0.4
2024-04-03 16:40:57 +08:00

1828 lines
48 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "p2p.h"
#include "p2p_i.h"
#include "p2p_debug.h"
#include "p2p_common.h"
#include "p2p_defs.h"
#include "p2p_list.h"
#include "atbm_hal.h"
#include "p2p_main.h"
#include "wps_main.h"
#if CONFIG_P2P
extern struct wifi_configure *hmac_cfg;
struct p2p_bss{
struct dl_list list;
atbm_uint8 bssid[6];
int rssi;
atbm_uint16 freq;
atbm_uint8 *res;
atbm_uint16 res_len;
};
//hal_queue_t p2p_task_queue ;
struct dl_list p2p_bss_list;
struct p2p_data *p2p_global;
static void wpas_p2p_join_scan_req(struct atbmwifi_vif *priv, int freq,
const atbm_uint8 *ssid, atbm_size_t ssid_len);
static int wpas_send_action(void *ctx, unsigned int freq, const atbm_uint8 *dst,
const atbm_uint8 *src, const atbm_uint8 *bssid, const atbm_uint8 *buf,
atbm_size_t len, unsigned int wait_time, int *scheduled);
int atbm_p2p_connect(struct atbmwifi_vif *priv, const atbm_uint8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method,
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq,
const atbm_uint8 *group_ssid, atbm_size_t group_ssid_len);
static void wpas_p2p_debug_print(void *ctx, int level, const char *msg)
{
p2p_printf(level, "P2P: %s", msg);
}
extern atbm_uint8 test_p2p_mac[6];
static int wpas_p2p_connect_check(struct p2p_data *p2p, const atbm_uint8 *peer_addr)
{
struct p2p_device *dev;
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)p2p->ctx;
atbm_uint8 channel;
int ret;
dev = p2p_get_device(p2p, peer_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
p2p_dbg(p2p, "Cannot connect to unknown P2P Device " MACSTR,
MAC2STR(peer_addr));
return -1;
}
ret = ieee80211_freq_to_chan(dev->listen_freq, &channel);
if(ret != ATBM_HOSTAPD_MODE_IEEE80211G){
return -1;
}
//p2p->cfg->channel = channel; //change listen channel
atbm_enable_listening(priv, (atbm_uint16)channel);
return 0;
}
void p2p_scan_result(void)
{
struct p2p_bss *bss;
struct p2p_bss *bss_next;
struct p2p_data *p2pdata = p2p_global;
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)p2p_global->ctx;
struct p2p_task_msg msg;
if(priv->p2p_scan == 0){
return;
}
dl_list_for_each_safe(bss, bss_next, &p2p_bss_list, struct p2p_bss, list){
p2p_scan_res_handler(p2pdata, bss->bssid,
(int)bss->freq, 0, bss->rssi, bss->res, bss->res_len);
dl_list_del(&bss->list);
atbm_kfree(bss->res);
atbm_kfree(bss);
}
if(priv->p2p_join){
if(wpas_p2p_connect_check(p2pdata, priv->join_iface_addr)){
if(priv->p2p_join_scan_count++ < 20){
p2p_printf(MSG_INFO, "p2p join scan no found, continue scan");
priv->scan_no_connect = 0;
return;
}else{
p2p_printf(MSG_INFO, "p2p join scan max count, stop");
}
}
priv->p2p_join_scan_count = 0;
priv->p2p_scan = 0;
priv->p2p_join = 0;
priv->scan_expire = 0;
priv->scan_no_connect = 1;
msg.event = JOIN_SCAN_END;
msg.param = NULL;
atbm_os_MsgQ_Send(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
return;
}
end:
/* Start join operation immediately */
priv->p2p_scan = 0;
priv->p2p_join = 0;
priv->scan_expire = 0;
priv->scan_no_connect = 1;
p2p_scan_res_handled(p2pdata);
return;
//ɨ<><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ
}
extern atbm_void sta_scan_start_timer_func(atbm_void *data1,atbm_void *data2);
static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
unsigned int num_req_dev_types,
const atbm_uint8 *req_dev_types, const atbm_uint8 *dev_id, atbm_uint16 pw_id)
{
struct atbmwifi_vif *priv = ctx;
int ret;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
struct wsm_template_frame frame = {
.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
};
if(p2pdata == NULL){
return -1;
}
priv->p2p_scan = 1;
priv->p2p_join = 0;
priv->scan_expire = 0;
priv->scan_no_connect = 1;
priv->scan_expire = 2;
priv->ssid_length = P2P_WILDCARD_SSID_LEN;
atbm_memcpy(priv->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
priv->ssid[P2P_WILDCARD_SSID_LEN] = '\0';
frame.skb = atbmwifi_ieee80211_send_probe_req(priv,NULL,priv->extra_ie,priv->extra_ie_len,1);
if (!frame.skb){
ret = -1;
goto END;
}
ret = wsm_set_template_frame(hw_priv, &frame,
priv->if_id);
dl_list_init(&p2p_bss_list);
atbmwifi_eloop_register_timeout(0,priv->scan_expire*1000,sta_scan_start_timer_func,(atbm_void *)priv,ATBM_NULL);
p2p_notify_scan_trigger_status(p2pdata, 0);
atbm_dev_kfree_skb(frame.skb);
atbmwifi_sta_scan(priv);
END:
return ret;
}
static void wpas_p2p_join_scan_req(struct atbmwifi_vif *priv, int freq,
const atbm_uint8 *ssid, atbm_size_t ssid_len)
{
int ret;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct atbmwifi_common *hw_priv = _atbmwifi_vifpriv_to_hwpriv(priv);
struct wsm_template_frame frame = {
.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
};
if(p2pdata == NULL){
return;
}
if (ssid && ssid_len) {
priv->ssid_length = ssid_len;
atbm_memcpy(priv->ssid, ssid, ssid_len);
priv->ssid[ssid_len] = '\0';
} else {
priv->ssid_length = P2P_WILDCARD_SSID_LEN;
atbm_memcpy(priv->ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
priv->ssid[P2P_WILDCARD_SSID_LEN] = '\0';
}
//////////WPS_IE(<28><>wps<70><73><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>)
priv->p2p_scan = 1;
priv->p2p_join = 1;
priv->scan_expire = 0;
priv->scan_no_connect = 1;
frame.skb = atbmwifi_ieee80211_send_probe_req(priv,NULL,priv->extra_ie,priv->extra_ie_len,1);
if (!frame.skb){
ret = -1;
return;
//goto END;
}
ret = wsm_set_template_frame(hw_priv, &frame,
priv->if_id);
// atbmwifi_RegisterEventHandler(WIFI_SCAN_COMPLETE_EVENT, p2p_scan_result);
dl_list_init(&p2p_bss_list);
atbmwifi_eloop_register_timeout(0, priv->scan_expire * 1000, sta_scan_start_timer_func,(atbm_void *)priv,ATBM_NULL);
atbm_dev_kfree_skb(frame.skb);
}
static int wpas_send_action(void *ctx, unsigned int freq, const atbm_uint8 *dst,
const atbm_uint8 *src, const atbm_uint8 *bssid, const atbm_uint8 *buf,
atbm_size_t len, unsigned int wait_time, int *scheduled)
{
struct atbmwifi_vif *priv = ctx;
struct atbmwifi_common * hw_priv = priv->hw_priv;
struct atbm_buff *skb;
struct atbmwifi_ieee80211_mgmt *mgmt;
if(len > 512){
p2p_printf(MSG_ERROR, "<ERROR> wpas_send_action too long");
return -1;
}
skb = atbm_dev_alloc_skb(sizeof(*mgmt) + len + 100);
if (!skb)
{
p2p_printf(MSG_ERROR, "<ERROR> wpas_send_action alloc skb");
return -1;
}
mgmt = (struct atbmwifi_ieee80211_mgmt *)atbm_skb_put(skb, 24);
atbm_memset(mgmt, 0, 24);
mgmt->frame_control = atbm_cpu_to_le16(ATBM_IEEE80211_FTYPE_MGMT | ATBM_IEEE80211_STYPE_ACTION);
atbm_memcpy(mgmt->da, dst, ATBM_ETH_ALEN);
atbm_memcpy(mgmt->sa, src, ATBM_ETH_ALEN);
atbm_memcpy(mgmt->bssid, bssid, ATBM_ETH_ALEN);
atbm_memcpy(atbm_skb_put(skb, len), buf, len);
ATBM_IEEE80211_SKB_TXCB(skb)->flags |= ATBM_IEEE80211_TX_INTFL_DONT_ENCRYPT | ATBM_IEEE80211_TX_CTL_NO_CCK_RATE;
ATBM_IEEE80211_SKB_TXCB(skb)->b_net = 0;
//printf("send_action, wait time:%d\n", wait_time);
atbmwifi_tx(hw_priv, skb, priv);
if(wait_time > 10){
wait_time = 10;
}
atbm_SleepMs(wait_time);
// atbmwifi_eloop_cancel_timeout(wpas_send_action_timeout, ctx, NULL);
// atbmwifi_eloop_register_timeout(0, wait_time, wpas_send_action_timeout, priv, NULL);
return 0;
}
static void wpas_send_action_done(void *ctx)
{
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
p2p_printf(MSG_DEBUG, "wpas_send_action_done");
// atbmwifi_eloop_cancel_timeout(wpas_send_action_timeout, ctx, NULL);
}
static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
{
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
void *param_res;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_task_msg msg;
priv->p2p_go_neg_process = 0;
if(res->status){ //P2P״̬<D7B4><CCAC><EFBFBD><EFBFBD> Э<><D0AD>ʧ<EFBFBD><CAA7>
p2p_printf(MSG_ERROR,"P2P GO COMPLET ERR:%d", res->status);
p2p_set_state(p2pdata, P2P_IDLE);
return;
}
printf("wpas_go_neg_completed\n");
param_res = (void *)atbm_kmalloc(sizeof(struct p2p_go_neg_results), GFP_KERNEL);
if(param_res == NULL){
p2p_printf(MSG_ERROR,"param_res malloc err");
return;
}
atbm_memset(param_res, 0, sizeof(struct p2p_go_neg_results));
atbm_memcpy(param_res, res, sizeof(struct p2p_go_neg_results));
msg.event = GO_NEG_COMPLETED;
msg.param = param_res;
atbm_os_MsgQ_Send(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
}
//<2F>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˻ص<CBBB><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>˻ص<CBBB>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӶԷ<D3B6>
static void wpas_go_neg_req_rx(void *ctx, const atbm_uint8 *src, atbm_uint16 dev_passwd_id,
atbm_uint8 go_intent)
{
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if(!priv->p2p_auto_go_req){
return;
}
if(priv->p2p_ap){ //<2F>Ѿ<EFBFBD><D1BE><EFBFBD>GO<47><4F>ʱ<EFBFBD>򲻴<EFBFBD><F2B2BBB4><EFBFBD>GO<47><4F><EFBFBD><EFBFBD>
p2p_printf(MSG_INFO,"P2P GO is active, ignore go req\n");
return;
}
p2p_clear_timeout(p2pdata);
}
static int wpas_peer_waiting_cb(void *ctx, const atbm_uint8 *src)
{
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_task_msg msg;
printf("wpas_peer_waiting_cb\n");
if(!priv->p2p_auto_go_req){
return -1;
}
if(priv->p2p_ap){ //<2F>Ѿ<EFBFBD><D1BE><EFBFBD>GO<47><4F>ʱ<EFBFBD>򲻴<EFBFBD><F2B2BBB4><EFBFBD>GO<47><4F><EFBFBD><EFBFBD>
p2p_printf(MSG_INFO,"P2P GO is active, ignore go req\n");
return -1;
}
p2p_stop_find(p2pdata);
if(wpas_p2p_connect_check(p2pdata, src)){
printf("p2p channel set err\n");
return -1;
}
atbm_memcpy(priv->join_iface_addr, src, ATBM_ETH_ALEN);
msg.event = GO_NEG_PEER_WAIT;
msg.param = NULL;
atbm_os_MsgQ_Send(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
return 0;
}
static void wpas_dev_found(void *ctx, const atbm_uint8 *addr,
const struct p2p_peer_info *info,
int new_device)
{
#ifndef CONFIG_NO_STDOUT_DEBUG
struct atbmwifi_vif *priv = ctx;
char devtype[WPS_DEV_TYPE_BUFSIZE];
char *wfd_dev_info_hex = NULL;
if (info->p2ps_instance) {
char str[256];
const atbm_uint8 *buf = wpabuf_head(info->p2ps_instance);
atbm_size_t len = wpabuf_len(info->p2ps_instance);
while (len) {
atbm_uint32 id;
atbm_uint16 methods;
atbm_uint8 str_len;
if (len < 4 + 2 + 1)
break;
id = ATBM_WPA_GET_LE32(buf);
buf += sizeof(atbm_uint32);
methods = ATBM_WPA_GET_BE16(buf);
buf += sizeof(atbm_uint16);
str_len = *buf++;
if (str_len > len - 4 - 2 - 1)
break;
atbm_memcpy(str, buf, str_len);
str[str_len] = '\0';
buf += str_len;
len -= str_len + sizeof(atbm_uint32) + sizeof(atbm_uint16) + sizeof(atbm_uint8);
p2p_printf(MSG_INFO,
P2P_EVENT_DEVICE_FOUND MACSTR
" p2p_dev_addr=" MACSTR
" pri_dev_type=%s name='%s'"
" config_methods=0x%x"
" dev_capab=0x%x"
" group_capab=0x%x"
" adv_id=%x asp_svc=%s%s",
MAC2STR(addr),
MAC2STR(info->p2p_device_addr),
wps_dev_type_bin2str(
info->pri_dev_type,
devtype, sizeof(devtype)),
info->device_name, methods,
info->dev_capab, info->group_capab,
id, str,
info->vendor_elems ?
" vendor_elems=1" : "");
}
goto done;
}
p2p_printf(MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
" p2p_dev_addr=" MACSTR
" pri_dev_type=%s name='%s' config_methods=0x%x "
"dev_capab=0x%x group_capab=0x%x%s%s%s new=%d",
MAC2STR(addr), MAC2STR(info->p2p_device_addr),
wps_dev_type_bin2str(info->pri_dev_type, devtype,
sizeof(devtype)),
info->device_name, info->config_methods,
info->dev_capab, info->group_capab,
wfd_dev_info_hex ? " wfd_dev_info=0x" : "",
wfd_dev_info_hex ? wfd_dev_info_hex : "",
info->vendor_elems ? " vendor_elems=1" : "",
new_device);
done:
atbm_kfree(wfd_dev_info_hex);
#endif
}
static void wpas_dev_lost(void *ctx, const atbm_uint8 *dev_addr)
{
p2p_printf(MSG_INFO, P2P_EVENT_DEVICE_LOST
"p2p_dev_addr=" MACSTR, MAC2STR(dev_addr));
}
static void wpas_find_stopped(void *ctx)
{
p2p_printf(MSG_INFO, P2P_EVENT_FIND_STOPPED);
}
static int wpas_start_listen(void *ctx, unsigned int freq,
unsigned int duration,
const struct wpabuf *probe_resp_ie)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>PB REQ(P2P IE)
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
atbm_uint8 channel;
int ret;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
ret = ieee80211_freq_to_chan(freq, &channel);
if(ret != ATBM_HOSTAPD_MODE_IEEE80211G){
p2p_printf(MSG_ERROR, "unspported freq");
return -1;
}
// wdt_pit_feed(1);
atbm_enable_listening(priv, (atbm_uint16)channel);
p2p_listen_cb(p2pdata, freq, duration);
priv->p2p_listen = 1;
return 0;
}
static void wpas_stop_listen(void *ctx)
{
//ֹͣ<CDA3><D6B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if(priv->p2p_listen){
priv->p2p_listen = 0;
if(priv->p2p_go_neg_process == 0){
atbm_disable_listening(priv);
}
p2p_listen_end(p2pdata, 0);
}
}
static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf,
unsigned int freq)
{
//GO ģʽ <20><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>PB REQ
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
struct atbmwifi_common * hw_priv = priv->hw_priv;
struct atbm_buff *skb;
int len = wpabuf_len(buf);
skb = atbm_dev_alloc_skb(len + 100);
if (!skb)
{
p2p_printf(MSG_ERROR, "<ERROR> wpas_send_probe_resp alloc skb");
return -1;
}
atbm_memcpy(atbm_skb_put(skb, len), wpabuf_head(buf), len);
ATBM_IEEE80211_SKB_TXCB(skb)->flags |= ATBM_IEEE80211_TX_INTFL_DONT_ENCRYPT | ATBM_IEEE80211_TX_CTL_NO_CCK_RATE;
ATBM_IEEE80211_SKB_TXCB(skb)->b_net = 0;
atbmwifi_tx(hw_priv, skb, priv);
return 0;
}
void wpas_sd_request(void *ctx, int freq, const atbm_uint8 *sa, atbm_uint8 dialog_token,
atbm_uint16 update_indic, const atbm_uint8 *tlvs, atbm_size_t tlvs_len)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>񣬲<EFBFBD>֧<EFBFBD><D6A7>
}
void wpas_sd_response(void *ctx, const atbm_uint8 *sa, atbm_uint16 update_indic,
const atbm_uint8 *tlvs, atbm_size_t tlvs_len)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>񣬲<EFBFBD>֧<EFBFBD><D6A7>
}
static void wpas_prov_disc_req(void *ctx, const atbm_uint8 *peer, atbm_uint16 config_methods,
const atbm_uint8 *dev_addr, const atbm_uint8 *pri_dev_type,
const char *dev_name, atbm_uint16 supp_config_methods,
atbm_uint8 dev_capab, atbm_uint8 group_capab, const atbm_uint8 *group_id,
atbm_size_t group_id_len)
{
//<2F>ص<EFBFBD>
}
static void wpas_prov_disc_resp(void *ctx, const atbm_uint8 *peer, atbm_uint16 config_methods)
{
//<2F>ص<EFBFBD> <20><><EFBFBD><EFBFBD>p2p<32><70><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>WPS<50><53><EFBFBD><EFBFBD>
}
static void wpas_prov_disc_fail(void *ctx, const atbm_uint8 *peer,
enum p2p_prov_disc_status status,
atbm_uint32 adv_id, const atbm_uint8 *adv_mac,
const char *deferred_session_resp)
{
//<2F>ص<EFBFBD>
}
static atbm_uint8 wpas_invitation_process(void *ctx, const atbm_uint8 *sa, const atbm_uint8 *bssid,
const atbm_uint8 *go_dev_addr, const atbm_uint8 *ssid,
atbm_size_t ssid_len, int *go, atbm_uint8 *group_bssid,
int *force_freq, int persistent_group,
const struct p2p_channels *channels,
int dev_pw_id)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD>֧<EFBFBD><D6A7>
return 0;
}
static void wpas_invitation_received(void *ctx, const atbm_uint8 *sa, const atbm_uint8 *bssid,
const atbm_uint8 *ssid, atbm_size_t ssid_len,
const atbm_uint8 *go_dev_addr, atbm_uint8 status,
int op_freq)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD>֧<EFBFBD><D6A7>
}
static void wpas_invitation_result(void *ctx, int status, const atbm_uint8 *bssid,
const struct p2p_channels *channels,
const atbm_uint8 *peer, int neg_freq,
int peer_oper_freq)
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD>֧<EFBFBD><D6A7>
}
static int wpas_get_noa(void *ctx, const atbm_uint8 *interface_addr, atbm_uint8 *buf,
atbm_size_t buf_len)
{
return 0;
}
static int wpas_go_connected(void *ctx, const atbm_uint8 *dev_addr)
{
//go <20><><EFBFBD><EFBFBD>״̬
return 0;
}
static void wpas_presence_resp(void *ctx, const atbm_uint8 *src, atbm_uint8 status,
const atbm_uint8 *noa, atbm_size_t noa_len)
{
}
static int wpas_is_concurrent_session_active(void *ctx)
{
//<2F><><EFBFBD><EFBFBD>״̬
return 0;
}
static int wpas_p2p_in_progress(void *ctx)
{
return 0;//<2F><><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>״̬
}
static int wpas_get_persistent_group(void *ctx, const atbm_uint8 *addr, const atbm_uint8 *ssid,
atbm_size_t ssid_len, atbm_uint8 *go_dev_addr,
atbm_uint8 *ret_ssid, atbm_size_t *ret_ssid_len,
atbm_uint8 *intended_iface_addr)
{
return 0;
}
static int wpas_get_go_info(void *ctx, atbm_uint8 *intended_addr,
atbm_uint8 *ssid, atbm_size_t *ssid_len, int *group_iface,
unsigned int *freq)
{
//<2F><>ȡGO<47><4F>Ϣ
return 0;
}
static int wpas_remove_stale_groups(void *ctx, const atbm_uint8 *peer, const atbm_uint8 *go,
const atbm_uint8 *ssid, atbm_size_t ssid_len)
{
//
return 0;
}
static void wpas_p2ps_prov_complete(void *ctx, atbm_uint8 status, const atbm_uint8 *dev,
const atbm_uint8 *adv_mac, const atbm_uint8 *ses_mac,
const atbm_uint8 *grp_mac, atbm_uint32 adv_id, atbm_uint32 ses_id,
atbm_uint8 conncap, int passwd_id,
const atbm_uint8 *persist_ssid,
atbm_size_t persist_ssid_size, int response_done,
int prov_start, const char *session_info,
const atbm_uint8 *feat_cap, atbm_size_t feat_cap_len,
unsigned int freq,
const atbm_uint8 *group_ssid, atbm_size_t group_ssid_len)
{
}
// P2P GO DISC resp cb
static int wpas_prov_disc_resp_cb(void *ctx)
{
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
struct p2p_task_msg msg;
printf("wpas_prov_disc_resp_cb\n");
if(priv->p2p_ap){
msg.event = GO_DISC_RESP;
msg.param = NULL;
atbm_os_MsgQ_Send(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
}
return 0;
}
static atbm_uint8 p2ps_group_capability(void *ctx, atbm_uint8 incoming, atbm_uint8 role,
unsigned int *force_freq,
unsigned int *pref_freq)
{
return 0;
}
static int wpas_p2p_get_pref_freq_list(void *ctx, int go,
unsigned int *len,
unsigned int *freq_list)
{
return 0;
}
static void wpas_p2p_add_chan(struct p2p_reg_class *reg, atbm_uint8 chan)
{
reg->channel[reg->channels] = chan;
reg->channels++;
}
static int wpas_p2p_setup_channels(struct p2p_channels *chan,
struct p2p_channels *cli_chan)
{
int cla = 0;
atbm_memset(cli_chan, 0, sizeof(*cli_chan));
/* Operating class 81 - 2.4 GHz band channels 1..13 */
chan->reg_class[cla].reg_class = 81;
chan->reg_class[cla].channels = 0;
wpas_p2p_add_chan(&chan->reg_class[cla], 1);
wpas_p2p_add_chan(&chan->reg_class[cla], 6);
wpas_p2p_add_chan(&chan->reg_class[cla], 11);
if (chan->reg_class[cla].channels)
cla++;
chan->reg_classes = cla;
return 0;
}
static int wpas_p2p_join(struct atbmwifi_vif *priv, const atbm_uint8 *iface_addr,
const atbm_uint8 *dev_addr, enum p2p_wps_method wps_method,
int auto_join, int op_freq,
const atbm_uint8 *ssid, atbm_size_t ssid_len)
{
p2p_printf(MSG_DEBUG, "P2P: Request to join existing group (iface "
MACSTR " dev " MACSTR " op_freq=%d)%s",
MAC2STR(iface_addr), MAC2STR(dev_addr), op_freq,
auto_join ? " (auto_join)" : "");
if (ssid && ssid_len) {
p2p_printf(MSG_DEBUG, "P2P: Group SSID specified: %s",
wpa_ssid_txt(ssid, ssid_len));
}
priv->p2p_auto_join = !!auto_join;
atbm_memcpy(priv->join_iface_addr, iface_addr, ATBM_ETH_ALEN);
atbm_memcpy(priv->join_dev_addr, dev_addr, ATBM_ETH_ALEN);
priv->p2p_wps_method = wps_method;
priv->p2p_join_scan_count = 0;
wpas_p2p_join_scan_req(priv, op_freq, ssid, ssid_len);
return 0;
}
static int wpas_p2p_start_go_neg(struct atbmwifi_vif *priv,
const atbm_uint8 *peer_addr,
enum p2p_wps_method wps_method,
int go_intent, const atbm_uint8 *own_interface_addr,
unsigned int force_freq, int persistent_group,
struct atbm_wpa_ssid *ssid, unsigned int pref_freq)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if (persistent_group)
persistent_group = 2;
/*
* Increase GO config timeout if HT40 is used since it takes some time
* to scan channels for coex purposes before the BSS can be started.
*/
p2p_set_config_timeout(p2pdata, 255, 20);
return p2p_connect(p2pdata, peer_addr, wps_method,
go_intent, own_interface_addr, force_freq,
persistent_group, ssid ? ssid->ssid : ATBM_NULL,
ssid ? ssid->ssid_len : 0, 0, pref_freq, 0);
}
static void wpas_p2p_assoc_req_ie(struct atbmwifi_vif *priv, const atbm_uint8 *bssid, int p2p_group)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
int ret;
if(priv->p2p_assoc_req_ie){
atbm_kfree(priv->p2p_assoc_req_ie);
priv->p2p_assoc_req_ie = NULL;
}
priv->p2p_assoc_req_ie = (atbm_uint8 *)atbm_kmalloc(100, GFP_KERNEL);
ret = p2p_assoc_req_ie(p2pdata, bssid, priv->p2p_assoc_req_ie
, 100, p2p_group, NULL);
if(ret < 0){
printf("P2P assoc req ie creat err\n");
priv->p2p_assoc_req_ie_len = 0;
return;
}
priv->p2p_assoc_req_ie_len = ret;
}
static void wpas_p2p_ie_update(void *ctx, struct wpabuf *beacon_ies,
struct wpabuf *proberesp_ies)
{
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)ctx;
if(priv->p2p_ap){
if(beacon_ies){
wpabuf_free(priv->p2p_go_beacon_ie);
priv->p2p_go_beacon_ie = beacon_ies;
}
wpabuf_free(priv->p2p_go_probe_resp_ie);
priv->p2p_go_probe_resp_ie = proberesp_ies;
}else{
wpabuf_free(beacon_ies);
wpabuf_free(proberesp_ies);
}
wpa_comm_init_extra_ie(priv);
atbmwifi_ap_start_beacon(priv);
atbm_kfree(priv->extra_ie);
priv->extra_ie = NULL;
priv->extra_ie_len = 0;
}
static void wpas_p2p_idle_update(void *ctx, int idle)
{
}
struct p2p_group *wpas_p2p_group_init(struct atbmwifi_vif *priv, struct p2p_go_neg_results *res)
{
struct p2p_group *group;
struct p2p_group_config *cfg;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if(p2pdata == NULL){
return NULL;
}
cfg = (struct p2p_group_config *)atbm_kzalloc(sizeof(*cfg), GFP_KERNEL);
if (cfg == NULL){
return NULL;
}
cfg->persistent_group = 2;
atbm_memcpy(cfg->interface_addr, priv->mac_addr, ATBM_ETH_ALEN);
cfg->max_clients = 4;
atbm_memcpy(cfg->ssid, res->ssid, res->ssid_len);
cfg->ssid_len = res->ssid_len;
cfg->freq = res->freq;
cfg->cb_ctx = priv;
cfg->ie_update = wpas_p2p_ie_update;
cfg->idle_update = wpas_p2p_idle_update;
cfg->ip_addr_alloc = 0; //<2F><>֧<EFBFBD><D6A7>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>ȡIP<49><50>ַ
group = p2p_group_init(p2pdata, cfg);
if (group == NULL){
atbm_kfree(cfg);
}
priv->p2pgroup = group;
return group;
}
void wpas_p2p_group_deinit(struct atbmwifi_vif *priv){
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if(priv->p2p_ap){
p2p_group_deinit(priv->p2pgroup);
priv->p2pgroup = ATBM_NULL;
priv->p2p_ap = 0;
}
}
static void p2p_join_scan_process(struct atbmwifi_vif *priv)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
int freq;
struct p2p_device *dev;
if(priv->p2p_auto_join){
dev = p2p_get_device(p2pdata, priv->join_iface_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
p2p_dbg(p2pdata, "Cannot connect to unknown P2P Device " MACSTR,
MAC2STR(priv->join_iface_addr));
return;
}
atbm_p2p_connect(priv, priv->join_iface_addr, NULL, WPS_PBC,
0, 0, 0, 0, priv->p2p_go_intent, dev->listen_freq,
NULL, 0);
return;
}
if(priv->p2p_join){
freq = p2p_get_oper_freq(p2pdata, priv->join_iface_addr);
if(freq > 0){
atbm_uint16 method;
switch (priv->p2p_wps_method) {
case WPS_PIN_DISPLAY:
method = WPS_CONFIG_KEYPAD;
break;
case WPS_PIN_KEYPAD:
method = WPS_CONFIG_DISPLAY;
break;
case WPS_PBC:
method = WPS_CONFIG_PUSHBUTTON;
break;
case WPS_P2PS:
method = WPS_CONFIG_P2PS;
break;
default:
method = 0;
break;
}
if (p2p_prov_disc_req(p2pdata,priv->join_dev_addr,NULL, method, 1,
freq, priv->user_initiated_pd) < 0) {
p2p_printf(MSG_DEBUG, "P2P: Failed to send Provision "
"Discovery Request before joining an "
"existing group");
return;
}
return;
}else{
printf("p2p join scan no found, continue scan\n");
priv->scan_no_connect = 0;
return;
}
}
}
static void p2p_go_peer_wait_process(struct atbmwifi_vif *priv)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_device *dev;
int ret;
atbm_uint8 channel;
dev = p2p_get_device(p2pdata, priv->join_iface_addr);
if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) {
p2p_dbg(p2pdata, "Cannot connect to unknown P2P Device " MACSTR,
MAC2STR(priv->join_iface_addr));
return;
}
if(0 == (dev->flags & P2P_DEV_PEER_WAITING_RESPONSE)){
return;
}
atbm_p2p_connect(priv, priv->join_iface_addr, NULL, WPS_PBC,
0, 0, 0, 0, priv->p2p_go_intent, dev->listen_freq, NULL, 0);
}
static void p2p_go_complete_process(struct atbmwifi_vif *priv, void *param)
{
struct p2p_go_neg_results *res = (struct p2p_go_neg_results *)param;
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
atbm_uint8 op_class, op_channel;
int len;
if(res == NULL){
return;
}
p2p_freq_to_channel(res->freq, &op_class, &op_channel);
if (res->role_go) {
atbm_disable_listening(priv);
atbmwifi_stop_iftype(priv, priv->iftype);
len = strlen(res->passphrase);
// atbm_wifi_set_config(res->ssid, res->ssid_len,
// res->passphrase, len, ATBM_KEY_WPA2 , 0);
// hmac_cfg->channel_no = p2pdata->cfg->channel;
priv->p2p_ap = 1;
printf("wps ap ssid:%s,pwd:%s, channel:%d\n",
res->ssid, res->passphrase, op_channel);
atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_P2P_GO);
// atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_AP);
// wifi_StartAP(res->ssid, res->ssid_len, (atbm_uint8 *)res->passphrase, len, p2pdata->cfg->channel,ATBM_KEY_WPA2, 0);
wifi_SetAPConfig(priv,(unsigned char *)res->ssid, res->ssid_len, (atbm_uint8 *)res->passphrase, len, op_channel, ATBM_KEY_WPA2, 0);
atbmwifi_wpa_event_start_ap(priv);
wpas_p2p_group_init(priv, res);
if(priv->appdata == NULL){
printf("hostapd wps NULL\n");
return;
}
// hmac_cfg->dev_password_len = 0;
priv->pbc = 1;
priv->pin = 0;
hostapd_wps_button_pushed(priv->appdata, res->peer_interface_addr);
} else {
wpa_printf(MSG_INFO, "res->wps_method:%d channel:%d\n", res->wps_method, op_channel);
if(res->wps_method == WPS_PBC){
priv->ssid_length = priv->config.ssid_len = res->ssid_len;
atbm_memset(priv->ssid, 0, ATBM_IEEE80211_MAX_SSID_LEN);
atbm_memset(priv->config.ssid, 0, ATBM_IEEE80211_MAX_SSID_LEN);
atbm_memcpy(priv->ssid, res->ssid, res->ssid_len);
atbm_memcpy(priv->config.ssid, res->ssid, res->ssid_len);
priv->p2p_scan = 0;
priv->p2p_join = 1;
priv->iftype = ATBM_NL80211_IFTYPE_P2P_CLIENT;
atbm_disable_listening(priv);
atbm_SleepMs(10);
wpas_p2p_assoc_req_ie(priv, res->peer_interface_addr, 1);
#if FAST_CONNECT_MODE
atbm_wifi_set_fast_connect_mode(1, op_channel, ATBM_NULL);
#endif
wpas_wps_p2p_start_pbc(priv->appdata, res->peer_interface_addr, 1);
}
}
}
static void p2p_go_disc_resp_process(struct atbmwifi_vif *priv)
{
// hmac_cfg->dev_password_len = 0;
priv->pbc = 1;
priv->pin = 0;
hostapd_wps_button_pushed(priv->appdata, NULL);
}
static void p2p_rx_action_process(struct atbmwifi_vif *priv, void *param)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_action *action = (struct p2p_action *)param;
if((action == NULL) || (p2pdata == NULL)){
return;
}
p2p_rx_action(p2pdata, action->da, action->sa, action->bssid,
action->category, action->data, action->len, action->freq);
atbm_kfree(action->data);
}
static void p2p_action_ack_process(struct atbmwifi_vif *priv, void *param)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_action_ack *action_ack = (struct p2p_action_ack *)param;
if((action_ack == NULL) || (p2pdata == NULL)){
return;
}
//printf("action_ack->res:%d\n", action_ack->res);
p2p_send_action_cb(p2pdata, 0, action_ack->da, action_ack->sa,
action_ack->bssid, action_ack->res);
}
static void p2p_main_thread(void *arg)
{
int ret;
struct atbmwifi_vif *priv = (struct atbmwifi_vif *)arg;
struct p2p_task_msg msg;
int size = sizeof(struct p2p_task_msg);
atbm_p2p_init(priv);
while(1){
atbm_memset(&msg, 0, sizeof(struct p2p_task_msg));
ret = atbm_os_MsgQ_Recv(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
if(ret){
continue;
}
switch(msg.event){
case JOIN_SCAN_END:
p2p_join_scan_process(priv);
break;
case GO_NEG_PEER_WAIT:
p2p_go_peer_wait_process(priv);
break;
case GO_NEG_COMPLETED:
p2p_go_complete_process(priv, msg.param);
break;
case GO_DISC_RESP:
p2p_go_disc_resp_process(priv);
break;
case P2P_RX_ACTION:
p2p_rx_action_process(priv, msg.param);
break;
case P2P_ACTION_ACK:
p2p_action_ack_process(priv, msg.param);
break;
default:
break;
}
if(msg.param){
atbm_kfree(msg.param);
msg.param = NULL;
}
}
}
static int p2p_main_task_creat(struct atbmwifi_vif *priv)
{
pAtbm_thread_t p2p_thread;
priv->p2p_task_msg_stack = (atbm_void *)atbm_kmalloc(P2P_QUEUE_NUM * sizeof(struct p2p_task_msg), GFP_KERNEL);
if(!priv->p2p_task_msg_stack){
return -1;
}
atbm_os_MsgQ_Create(&priv->p2p_task_msg, priv->p2p_task_msg_stack, sizeof(struct p2p_task_msg), P2P_QUEUE_NUM);
p2p_thread = atbm_createThread(p2p_main_thread, (atbm_void*)priv, P2P_TASK_PRIORITY);
priv->p2p_task = p2p_thread;
return 0;
}
static int p2p_main_task_release(struct atbmwifi_vif *priv)
{
if(priv->p2p_task){
atbm_stopThread(priv->p2p_task);
priv->p2p_task = NULL;
}
atbm_os_MsgQ_Delete(&priv->p2p_task_msg);
if(priv->p2p_task_msg_stack){
atbm_kfree(priv->p2p_task_msg_stack);
priv->p2p_task_msg_stack = ATBM_NULL;
}
return 0;
}
atbm_uint8 * atbm_p2p_add_scan_ie(struct atbmwifi_vif *priv, atbm_uint8 * pos)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct wpabuf *wpabuf = (struct wpabuf *)priv->p2p_scan_ie;
if(p2pdata == NULL || wpabuf == NULL){
return pos;
}
atbm_memcpy(pos, wpabuf->buf, wpabuf->used);
pos += wpabuf->used;
return pos;
}
atbm_uint8 *atbm_p2p_add_ap_beacon_ie(struct atbmwifi_vif *priv, atbm_uint8 * pos)
{
struct wpabuf *wpabuf = (struct wpabuf *)priv->p2p_go_beacon_ie;
if(priv->p2p_go_beacon_ie == NULL){
return pos;
}
atbm_memcpy(pos, wpabuf->buf, wpabuf->used);
pos += wpabuf->used;
return pos;
}
atbm_uint8 *atbm_p2p_add_ap_pbresp_ie(struct atbmwifi_vif *priv, atbm_uint8 * pos)
{
struct wpabuf *wpabuf = (struct wpabuf *)priv->p2p_go_probe_resp_ie;
if(priv->p2p_go_probe_resp_ie == NULL){
return pos;
}
atbm_memcpy(pos, wpabuf->buf, wpabuf->used);
pos += wpabuf->used;
return pos;
}
atbm_uint8 *atbm_p2p_add_ap_assoc_resp_ie(struct atbmwifi_vif *priv, atbm_uint8 * pos)
{
struct wpabuf *wpabuf;
wpabuf = p2p_group_assoc_resp_ie(priv->p2pgroup, 0);
if(wpabuf == NULL){
return pos;
}
atbm_memcpy(pos, wpabuf->buf, wpabuf->used);
pos += wpabuf->used;
wpabuf_free(wpabuf);
return pos;
}
void atbm_p2p_wps_sucess(struct atbmwifi_vif *priv, int registrar)
{
#if 0
if(registrar){
p2p_group_notif_formation_done(priv->p2pgroup);
}else{
}
#endif
}
int atbm_p2p_prash_ie(struct atbmwifi_vif *priv, atbm_uint8 *bssid,
atbm_uint16 freq, atbm_int8 rssi, atbm_uint8 *data, atbm_uint16 len){
struct p2p_bss *bss;
struct atbmwifi_ieee802_11_elems elems;
int i;
atbm_ieee802_11_parse_elems(data,len,&elems);
#if 0
printf("prash ssid:");
for(i=0; i<elems.ssid_len; i++){
printf("%c", elems.ssid[i]);
}
printf("\n");
#endif
#if 0 //<2F><><EFBFBD><EFBFBD>P2P<32><EFBFBD><E8B1B8>SSID<49><44> "DIRECT-"
if((elems.ssid_len != priv->ssid_length)
|| atbm_memcmp(elems.ssid, priv->ssid, priv->ssid_length)){
return -1;
}
#endif
if((elems.p2p_ie == NULL) || (elems.wps_ie == NULL)){
return -1;
}
bss = (struct p2p_bss *)atbm_kmalloc(sizeof(struct p2p_bss), GFP_KERNEL);
if(bss == NULL){
return -1;
}
bss->res = (atbm_uint8 *)atbm_kmalloc(len, GFP_KERNEL);
if(bss->res == NULL){
atbm_kfree(bss);
return -1;
}
atbm_memcpy(bss->bssid, bssid, 6);
bss->rssi = (int)rssi;
bss->freq = freq;
atbm_memcpy(bss->res, data, len);
bss->res_len = len;
dl_list_add(&p2p_bss_list, &bss->list);
return 0;
}
int atbm_p2p_probe_req_rx(struct atbmwifi_vif *priv, const atbm_uint8 *addr,
const atbm_uint8 *dst, const atbm_uint8 *bssid,
const atbm_uint8 *ie, atbm_size_t ie_len,
unsigned int rx_freq, int ssi_signal)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if (p2pdata == NULL){
return -1;
}
//printf("rx pb_req from:"MACSTR"\n", MAC2STR(addr));
return p2p_probe_req_rx(p2pdata, addr, dst, bssid,
ie, ie_len, rx_freq, priv->p2p_join);
}
void atbm_p2p_rx_action(struct atbmwifi_vif *priv, const atbm_uint8 *da,
const atbm_uint8 *sa, const atbm_uint8 *bssid,
atbm_uint8 category, const atbm_uint8 *data, atbm_size_t len, atbm_uint16 freq)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_action *action = NULL;
struct p2p_task_msg msg;
if (p2pdata == NULL){
return;
}
if(category != WLAN_ACTION_PUBLIC){
return;
}
action = (struct p2p_action *)atbm_kmalloc(sizeof(struct p2p_action), GFP_KERNEL);
if(action == NULL){
return;
}
action->data = (atbm_uint8 *)atbm_kmalloc(len, GFP_KERNEL);
if(action->data == NULL){
atbm_kfree(action);
return;
}
atbm_memcpy(action->bssid, bssid, 6);
atbm_memcpy(action->sa, sa, 6);
atbm_memcpy(action->da, da, 6);
atbm_memcpy(action->data, data, len);
action->category = category;
action->freq = freq;
action->len = len;
msg.event = P2P_RX_ACTION;
msg.param = action;
atbm_os_MsgQ_Send(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
// p2p_rx_action(p2pdata, da, sa, bssid, category, data, len, freq);
}
void atbm_p2p_tx_action_ack(struct atbmwifi_vif *priv, struct atbmwifi_ieee80211_mgmt *mgmt, int status)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct p2p_action_ack *action_ack = NULL;
struct p2p_task_msg msg;
if(p2pdata == NULL){
return;
}
if(mgmt->u.action.category != WLAN_ACTION_PUBLIC){
return;
}
action_ack = (struct p2p_action_ack *)atbm_kmalloc(sizeof(struct p2p_action_ack), GFP_KERNEL);
if(action_ack == NULL){
return;
}
atbm_memcpy(action_ack->bssid, mgmt->bssid, 6);
atbm_memcpy(action_ack->da, mgmt->da, 6);
atbm_memcpy(action_ack->sa, mgmt->sa, 6);
//printf("action ack status:%X\n", status);
if(status){
action_ack->res = P2P_SEND_ACTION_NO_ACK;
}else{
action_ack->res = P2P_SEND_ACTION_SUCCESS;
}
msg.event = P2P_ACTION_ACK;
msg.param = action_ack;
atbm_os_MsgQ_Send(&priv->p2p_task_msg, &msg, sizeof(struct p2p_task_msg), ATBM_TX_WAIT_FOREVER);
}
void atbm_p2p_dev_info_set(struct atbmwifi_vif *priv, struct wps_context *wps_ctx)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if(p2pdata == NULL){
return;
}
atbm_memcpy(wps_ctx->dev.mac_addr, p2pdata->cfg->dev_addr, ATBM_ETH_ALEN);
wps_ctx->dev.device_name = p2pdata->cfg->dev_name;
wps_ctx->dev.manufacturer = p2pdata->cfg->manufacturer;
wps_ctx->dev.model_name = p2pdata->cfg->model_name;
wps_ctx->dev.model_number = p2pdata->cfg->model_number;
wps_ctx->dev.serial_number = p2pdata->cfg->serial_number;
wps_ctx->config_methods = p2pdata->cfg->config_methods;
}
int atbm_p2p_init(struct atbmwifi_vif *priv)
{
struct p2p_config p2p;
atbm_size_t ielen;
struct wpabuf *ies;
struct p2p_data *p2pdata;
struct wps_context *wps_ctx;
struct wpa_supplicant *wpa_s;
if(priv->iftype != ATBM_NUM_NL80211_IFTYPES){
atbmwifi_stop_iftype(priv, priv->iftype);
}
atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_P2P_CLIENT);
// atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_STATION);
wpa_s = (struct wpa_supplicant *)priv->appdata;
priv->iftype = ATBM_NL80211_IFTYPE_P2P_CLIENT;
priv->p2p_ap = 0;
priv->p2p_join = 0;
priv->p2p_scan = 0;
if(priv->p2p_wps_privkey == ATBM_NULL){
if(dh5_init((struct wpabuf **)&priv->p2p_wps_privkey, (struct wpabuf **)&priv->p2p_wps_pubkey) == NULL)
return -1;
}
if(wpas_wps_p2p_init(wpa_s)){
return -1;
}
atbm_memset(&p2p, 0, sizeof(p2p));
p2p.cb_ctx = priv;
p2p.debug_print = wpas_p2p_debug_print;
p2p.p2p_scan = wpas_p2p_scan;
p2p.send_action = wpas_send_action;
p2p.send_action_done = wpas_send_action_done;
p2p.go_neg_completed = wpas_go_neg_completed;
p2p.go_neg_req_rx = wpas_go_neg_req_rx;
p2p.peer_waiting_cb = wpas_peer_waiting_cb;
p2p.dev_found = wpas_dev_found;
p2p.dev_lost = wpas_dev_lost;
p2p.find_stopped = wpas_find_stopped;
p2p.start_listen = wpas_start_listen;
p2p.stop_listen = wpas_stop_listen;
p2p.send_probe_resp = wpas_send_probe_resp;
// p2p.sd_request = wpas_sd_request;
// p2p.sd_response = wpas_sd_response;
p2p.prov_disc_req = wpas_prov_disc_req;
p2p.prov_disc_resp = wpas_prov_disc_resp;
p2p.prov_disc_fail = wpas_prov_disc_fail;
// p2p.invitation_process = wpas_invitation_process;
// p2p.invitation_received = wpas_invitation_received;
// p2p.invitation_result = wpas_invitation_result;
// p2p.get_noa = wpas_get_noa;
p2p.go_connected = wpas_go_connected;
// p2p.presence_resp = wpas_presence_resp;
p2p.is_concurrent_session_active = wpas_is_concurrent_session_active;
p2p.is_p2p_in_progress = wpas_p2p_in_progress;
// p2p.get_persistent_group = wpas_get_persistent_group;
p2p.get_go_info = wpas_get_go_info;
// p2p.remove_stale_groups = wpas_remove_stale_groups;
// p2p.p2ps_prov_complete = wpas_p2ps_prov_complete;
p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb;
p2p.p2ps_group_capability = p2ps_group_capability;
// p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list;
wps_ctx = wpa_s->wsc_data->wps_ctx;
atbm_memcpy(p2p.dev_addr, priv->mac_addr, ATBM_ETH_ALEN);
p2p.dev_name = wps_ctx->dev.device_name;
p2p.manufacturer = wps_ctx->dev.manufacturer;
p2p.model_name = wps_ctx->dev.model_name;
p2p.model_number = wps_ctx->dev.model_number;
p2p.serial_number = wps_ctx->dev.serial_number;
atbm_memcpy(p2p.uuid, wps_ctx->uuid, 16);
p2p.config_methods = wps_ctx->config_methods;
atbm_memcpy(p2p.pri_dev_type, wps_ctx->dev.pri_dev_type,
WPS_DEV_TYPE_LEN);
p2p.num_sec_dev_types = 0;
//atbm_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type,
// p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN);
if (wpas_p2p_setup_channels(&p2p.channels, &p2p.cli_channels)) {
p2p_printf(MSG_ERROR,
"P2P: Failed to configure supported channel list");
return -1;
}
p2p.reg_class = P2P_LISTEN_REG_CLASS;
p2p.channel = P2P_LISTEN_CHANNEL;
p2p.channel_forced = 1;
p2p_printf(MSG_DEBUG, "P2P: Own listen channel: %d:%d",
p2p.reg_class, p2p.channel);
p2p.op_reg_class = P2P_LISTEN_REG_CLASS;
p2p.op_channel = P2P_LISTEN_CHANNEL;
p2p.cfg_op_channel = 1;
p2p_printf(MSG_DEBUG, "P2P: Configured operating channel: "
"%d:%d", p2p.op_reg_class, p2p.op_channel);
atbm_memcpy(p2p.country, "XX\x04", 3);
p2p.concurrent_operations = 0;
p2p.max_peers = P2P_MAX_PEERS;
p2p.p2p_intra_bss = 0;
p2p.max_listen = 1000;
p2p.passphrase_len = 8;
p2pdata = p2p_init(&p2p);
priv->p2pdata = p2pdata;
if(priv->p2pdata == NULL){
p2p_printf(MSG_ERROR, "P2P: init error");
return -1;
}
p2p_global = priv->p2pdata;
p2p_global->ctx = priv;
ielen = p2p_scan_ie_buf_len(p2pdata);
ies = wpabuf_alloc(ielen);
if (ies == NULL) {
p2p_printf(MSG_ERROR, "P2P: P2P_IE malloc error");
return -1;
}
p2p_scan_ie(p2pdata, ies, NULL, BAND_2_4_GHZ);
priv->p2p_scan_ie = ies; //PB<50><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>P2P_IER
// MIB_Flags |= MIB_F_P2P_STARTED;
#ifdef CONFIG_WIFI_DISPLAY
wifi_display_subelem_set(priv, 0, "000600111c440032");
wifi_display_enable(priv, 1);
#endif
return 0;
}
int atbm_p2p_find(struct atbmwifi_vif *priv, unsigned int timeout,
enum p2p_discovery_type type,
unsigned int num_req_dev_types, const atbm_uint8 *req_dev_types,
const atbm_uint8 *dev_id, unsigned int search_delay,
atbm_uint8 seek_cnt, const char **seek_string, int freq, int autoconn)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct wpa_supplicant *wpa_s;
if (p2pdata == NULL){
return -1;
}
if(priv->p2p_ap){
priv->p2p_ap = 0;
}
if(priv->iftype != ATBM_NUM_NL80211_IFTYPES){
atbmwifi_stop_iftype(priv, priv->iftype);
}
atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_P2P_CLIENT);
wpa_s = (struct wpa_supplicant *)priv->appdata;
if(!wpa_s->wsc_data && wpas_wps_p2p_init(wpa_s)){
return -1;
}
p2p_flush(p2pdata);
priv->p2p_auto_go_req = autoconn;
return p2p_find(p2pdata, timeout, type,
num_req_dev_types, req_dev_types, dev_id,
search_delay, seek_cnt, seek_string, freq);
}
void atbm_p2p_stop_find(struct atbmwifi_vif *priv)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
if (p2pdata == NULL){
return;
}
p2p_stop_find(p2pdata);
}
int atbm_p2p_connect(struct atbmwifi_vif *priv, const atbm_uint8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method,
int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, const atbm_uint8 *group_ssid,
atbm_size_t group_ssid_len)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata;
if(p2pdata == NULL){
return -1;
}
if(priv->p2p_go_neg_process){
return -1;
}
priv->p2p_ap = 0;
if (go_intent < 0 || go_intent > 15){
go_intent = P2P_DEFULT_GO_INTENT;
}
priv->p2p_go_intent = go_intent;
priv->p2p_wps_method = wps_method;
if (pin){
os_strlcpy(priv->p2p_pin, pin, sizeof(priv->p2p_pin));
}else if(wps_method == WPS_PIN_DISPLAY){
}else if(wps_method == WPS_P2PS){
os_strlcpy(priv->p2p_pin, "12345670", sizeof(priv->p2p_pin));
}else{
priv->p2p_pin[0]='\0';
}
if(join || auto_join){
atbm_uint8 iface_addr[ATBM_ETH_ALEN], dev_addr[ATBM_ETH_ALEN];
atbm_memcpy(dev_addr, peer_addr, ATBM_ETH_ALEN);
if (p2p_get_interface_addr(p2pdata, peer_addr,iface_addr) < 0) {
atbm_memcpy(iface_addr, peer_addr, ATBM_ETH_ALEN);
p2p_get_dev_addr(p2pdata, peer_addr,dev_addr);
}
if (auto_join){
}
priv->user_initiated_pd = 1;
if(priv->iftype != ATBM_NL80211_IFTYPE_P2P_CLIENT && priv->iftype != ATBM_NUM_NL80211_IFTYPES){
atbmwifi_stop_iftype(priv, priv->iftype);
}
atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_P2P_CLIENT);
wpa_s = (struct wpa_supplicant *)priv->appdata;
if(!wpa_s->wsc_data && wpas_wps_p2p_init(wpa_s)){
return -1;
}
if (wpas_p2p_join(priv, iface_addr, dev_addr, wps_method,
auto_join, freq, group_ssid, group_ssid_len) < 0){
return -1;
}
return 0;
}
if (wpas_p2p_start_go_neg(priv, peer_addr, wps_method,
go_intent, priv->mac_addr, freq,
persistent_group, NULL, 0) < 0) {
return -1;
}
priv->p2p_go_neg_process = 1;
return 0;
}
int atbm_p2p_listen(struct atbmwifi_vif *priv, unsigned int timeout,
int autoconn, int channel)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct wpa_supplicant *wpa_s;
if (p2pdata == NULL){
return -1;
}
if(priv->p2p_ap){
priv->p2p_ap = 0;
}
if(priv->iftype != ATBM_NUM_NL80211_IFTYPES){
atbmwifi_stop_iftype(priv, priv->iftype);
}
atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_P2P_CLIENT);
wpa_s = (struct wpa_supplicant *)priv->appdata;
if(!wpa_s->wsc_data && wpas_wps_p2p_init(wpa_s)){
return -1;
}
p2p_flush(p2pdata);
priv->p2p_auto_go_req = autoconn;
p2pdata->cfg->channel = channel;
p2pdata->cfg->op_channel = channel;
return p2p_listen(p2pdata, timeout);
}
int atbm_p2p_go_start(struct atbmwifi_vif *priv)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;
struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)priv->appdata;
struct p2p_go_neg_results *res = NULL;
int len;
if(p2pdata == NULL){
return -1;
}
atbm_disable_listening(priv);
atbmwps_cancel(priv);
if(priv->iftype != ATBM_NUM_NL80211_IFTYPES)
atbmwifi_stop_iftype(priv, priv->iftype);
priv->p2p_ap = 1;
res = (struct p2p_go_neg_results *)atbm_kmalloc(sizeof(struct p2p_go_neg_results), GFP_KERNEL);
if(res == NULL){
return -1;
}
atbm_memset(res, 0, sizeof(struct p2p_go_neg_results));
p2p_build_ssid(p2pdata, res->ssid, &res->ssid_len);
p2p_random(res->passphrase, p2pdata->cfg->passphrase_len);
len = strlen(res->passphrase);
wpa_printf(MSG_INFO, "wps ap ssid:%s,pwd:%s, channel:%d\n",
res->ssid, res->passphrase, p2pdata->cfg->channel);
atbmwifi_start_iftype(priv, ATBM_NL80211_IFTYPE_P2P_GO);
wpas_p2p_group_init(priv, res);
wifi_SetAPConfig(priv,(unsigned char *)res->ssid, res->ssid_len, (atbm_uint8 *)res->passphrase, len, p2pdata->cfg->channel, ATBM_KEY_WPA2, 0);
atbmwifi_wpa_event_start_ap(priv);
atbm_kfree(res);
return 0;
}
void atbm_p2p_go_stop(struct atbmwifi_vif *priv){
atbm_disable_listening(priv);
atbmwps_deinit(priv);
atbmwifi_stop_iftype(priv, priv->iftype);
wpas_p2p_group_deinit(priv);
priv->p2p_scan = 0;
priv->p2p_join = 0;
priv->p2p_auto_join = 0;
if(priv->p2p_go_beacon_ie){
wpabuf_free(priv->p2p_go_beacon_ie);
priv->p2p_go_beacon_ie = ATBM_NULL;
}
if(priv->p2p_go_probe_resp_ie){
wpabuf_free(priv->p2p_go_probe_resp_ie);
priv->p2p_go_probe_resp_ie = ATBM_NULL;
}
}
int atbm_p2p_auto_connect(struct atbmwifi_vif *priv, atbm_uint8 *mac, int go_intent)
{
return atbm_p2p_connect(priv, mac, NULL, WPS_PBC,
0, 1, 1, 0, go_intent, 0, NULL, 0);
}
int atbm_p2p_find_wait_connect(struct atbmwifi_vif *priv, int go_intent)
{
priv->p2p_go_intent = go_intent;
return atbm_p2p_find(priv, 0, 0, 0, NULL, NULL, 0, 0, NULL, 0, 1);
}
int atbm_p2p_find_only(struct atbmwifi_vif *priv, int timeout)
{
return atbm_p2p_find(priv, timeout, 0, 0, NULL, NULL, 0, 0, NULL, 0, 0);
}
int atbm_p2p_listen_wait_connect(struct atbmwifi_vif *priv, int go_intent, int channel){
wifi_printk(WIFI_ALWAYS, "priv:%x go_intent:%d channel:%d\n", priv, go_intent, channel);
priv->p2p_go_intent = go_intent;
return atbm_p2p_listen(priv, 0, 1, channel);
}
int atbm_p2p_start(struct atbmwifi_vif *priv)
{
if(priv->p2pdata != NULL){
iot_printf("p2p is started\n");
return -1;
}
p2p_main_task_creat(priv);
return 0;
}
int atbm_p2p_get_peers(struct atbmwifi_vif *priv)
{
struct p2p_data *p2pdata = (struct p2p_data *)priv->p2pdata;;
struct p2p_device *dev = NULL;
char buf[100];
if (p2pdata == NULL){
return -1;
}
dl_list_for_each(dev, &p2pdata->devices, struct p2p_device, list) {
atbm_memset(buf, 0, 100);
sprintf(buf,"dev mac:%02X%02X%02X%02X%02X%02X,name:",
dev->info.p2p_device_addr[0],dev->info.p2p_device_addr[1],
dev->info.p2p_device_addr[2],dev->info.p2p_device_addr[3],
dev->info.p2p_device_addr[4],dev->info.p2p_device_addr[5]);
iot_printf(buf);
iot_printf(dev->info.device_name);
iot_printf("\n");
}
return 0;
}
int atbm_p2p_deinit(struct atbmwifi_vif *priv)
{
if(priv->p2pdata == NULL){
iot_printf("p2p is stopped\n");
return -1;
}
if(priv->iftype != ATBM_NUM_NL80211_IFTYPES){
atbmwifi_stop_iftype(priv, priv->iftype);
}
atbm_disable_listening(priv);
atbmwps_cancel(priv);
atbmwifi_stop();
if(priv->p2p_ap){
p2p_group_deinit(priv->p2pgroup);
priv->p2pgroup = NULL;
priv->p2p_ap = 0;
}
priv->p2p_scan = 0;
priv->p2p_join = 0;
priv->p2p_auto_join = 0;
priv->p2p_go_neg_process = 0;
priv->p2p_auto_go_req = 0;
p2p_main_task_release(priv);
p2p_deinit(priv->p2pdata);
priv->p2pdata = NULL;
if(priv->p2p_scan_ie){
wpabuf_free(priv->p2p_scan_ie);
priv->p2p_scan_ie = NULL;
}
if(priv->p2p_go_beacon_ie){
wpabuf_free(priv->p2p_go_beacon_ie);
priv->p2p_go_beacon_ie = NULL;
}
if(priv->p2p_go_probe_resp_ie){
wpabuf_free(priv->p2p_go_probe_resp_ie);
priv->p2p_go_probe_resp_ie = NULL;
}
if(priv->p2p_assoc_req_ie){
atbm_kfree(priv->p2p_assoc_req_ie);
priv->p2p_assoc_req_ie = NULL;
}
if(priv->p2p_wps_privkey){
wpabuf_free(priv->p2p_wps_privkey);
priv->p2p_wps_privkey = NULL;
}
if(priv->p2p_wps_pubkey){
wpabuf_free(priv->p2p_wps_pubkey);
priv->p2p_wps_pubkey = NULL;
}
// MIB_Flags &= ~MIB_F_P2P_STARTED;
// atbmwifi_sta_start(priv);
return 0;
}
int atbm_p2p_restart(struct atbmwifi_vif *priv){
void *p2p_wps_pubkey = priv->p2p_wps_pubkey;
void *p2p_wps_privkey = priv->p2p_wps_privkey;
priv->p2p_wps_pubkey = ATBM_NULL;
priv->p2p_wps_privkey = ATBM_NULL;
atbm_p2p_deinit(priv);
atbm_SleepMs(10);
priv->p2p_wps_pubkey = p2p_wps_pubkey;
priv->p2p_wps_privkey = p2p_wps_privkey;
atbm_p2p_start(priv);
return 0;
}
#endif