<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                首先來看WPAS中P2P相關模塊的初始化。該初始化工作我們在第4章4.3.4中“wpa_supplicant_init_iface分析之五”曾提到過,其對應的函數wpas_p2p_init,馬上來看它 **p2p_supplicant.c::wpas_p2p_init** ~~~ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) { struct p2p_config p2p; //p2p變量指向一個p2p_config對象,代表P2P模塊的配置信息 unsigned int r; int i; //①WPA_DRIVER_FLAGS_P2P_CAPABLE:代表Wifi驅動對P2P支持的能力,詳情見下文解釋 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)) return 0; if (global->p2p) return 0; //如果wifi driver能完成P2P功能,就不用勞駕WPAS了 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) {......} //②初始化并設置p2p_config對象 os_memset(&p2p, 0, sizeof(p2p)); p2p.msg_ctx = wpa_s; p2p.cb_ctx = wpa_s; p2p.p2p_scan = wpas_p2p_scan; //P2P對應的掃描函數 .......//設置一些回調函數 p2p.get_noa = wpas_get_noa; p2p.go_connected = wpas_go_connected; //設置P2P Device address。 os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); //設置P2P模塊配置信息,包括device name,model name,uuid等 p2p.dev_name = wpa_s->conf->device_name; p2p.manufacturer = wpa_s->conf->manufacturer; p2p.model_name = wpa_s->conf->model_name; p2p.model_number = wpa_s->conf->model_number; p2p.serial_number = wpa_s->conf->serial_number; if (wpa_s->wps) { os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16); p2p.config_methods = wpa_s->wps->config_methods; } //設置Operation Channel信息和listen channel信息 if (wpa_s->conf->p2p_listen_reg_class && wpa_s->conf->p2p_listen_channel) { p2p.reg_class = wpa_s->conf->p2p_listen_reg_class; p2p.channel = wpa_s->conf->p2p_listen_channel; } else { ......//設置默認值 } ...... //設置國家碼 if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) { os_memcpy(p2p.country, wpa_s->conf->country, 2); p2p.country[2] = 0x04; } else//配置文件中沒有設置國家,所以取值為"XX\x04" os_memcpy(p2p.country, "XX\x04", 3);//讀者可回顧圖7-7 //判斷wifi 驅動是否支持配置文件中設置的operationg channel和listen channel if (wpas_p2p_setup_channels(wpa_s, &p2p.channels)) {......} os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type,WPS_DEV_TYPE_LEN); p2p.num_sec_dev_types = wpa_s->conf->num_sec_device_types; os_memcpy(p2p.sec_dev_type, wpa_s->conf->sec_device_type, p2p.num_sec_dev_types * WPS_DEV_TYPE_LEN); //是否支持concurrent operation p2p.concurrent_operations = !!(wpa_s->drv_flags&WPA_DRIVER_FLAGS_P2P_CONCURRENT); p2p.max_peers = 100;//最多能保存100個對端P2P Device信息 //配置文件中沒有設置p2p_ssid_postfix,但P2pStateMachine在initializeP2pSettings函數中 //將設置P2P SSID后綴。以筆者的Galaxy Note2為例,其P2P SSID后綴為“Android_4aa9” if (wpa_s->conf->p2p_ssid_postfix) {......} p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss; //③global->p2p指向一個p2p_data結構體,它是WPAS中P2P模塊的代表 global->p2p = p2p_init(&p2p); ...... for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {//拷貝vendor廠商特定的WSC屬性信息 if (wpa_s->conf->wps_vendor_ext[i] == NULL) continue; p2p_add_wps_vendor_extension(global->p2p, wpa_s->conf->wps_vendor_ext[i]); } return 0; } ~~~ 由上述代碼可知,wpas_p2p_init的工作非常簡單,主要內容包括: 初始化一個p2p_config對象,然后根據p2p_supplicant.conf文件的信息來設置其中的內容,同時還需要為P2P模塊設置一些回調函數。 調用p2p_init函數以初始化P2P模塊。 下面來介紹上述代碼中涉及到的一些知識。 **1、Driver Flags和重要數據結構介紹** 先來看上述代碼中提到的drv_flags變量。WPAS中,Wifi驅動對P2P功能的支持情況就是由它來表達的。筆者的Galaxy Note2中該變量取值為0x2EAC0,其表達的含義如下: **driver.h** ~~~ #define WPA_DRIVER_FLAGS_AP 0x00000040 //Wifi driver支持AP。它使得P2P設備能扮演GO /* 標志標明association成功后,kernel driver需要設置WEP key 這個標志出現的原因是由于kernel API發生了變動,使得只能在關聯成功后才能設置key */ #define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 0x00000080 #define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200 //Wifi驅動支持STA和P2P的并發運行 #define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800 //Wifi驅動支持P2P /* 7.2.2.1.2“Probe Request幀設置”一節曾提到過說P2P包含Device Address和Interface Address 兩種類型的地址。在實際實現過程中,這兩個地址分別代表兩個virtual interface。顯然,P2P中第一個和一直 存在的是擁有Device Address的vitural interface。下面這個標志表示該virtual interface可以參與 P2P管理(除P2P Group Operation之外的工作)工作以及非P2P相關的工作(例如利用這個virtual interface 加入到一個BSS) */ #define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P 0x00002000 /* 該標志主要針對associate操作。當關聯操作失敗后,如果driver支持該選項,則表明driver能處理失敗之 后的各種收尾工作(Key、timeout等工作)。否則,WPAS需要自己處理這些事情 */ #define WPA_DRIVER_FLAGS_SANE_ERROR_CODES 0x00004000 //下面這個標志和off channel機制有關。讀者可參考第4章4.3.4中“capability介紹”一節。當802.11 //MAC幀通過off channel發送的話,下面這個標志表示driver會反饋一個發送情況(TX Report)消息給WPAS #define WPA_DRIVER_FLAGS_OFFCHANNEL_TX 0x00008000 //下面這兩個標志表示kernel中的driver是否能反饋Deauthentication/Disassociation幀 //發送情況(TX Report) #define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS 0x00020000 ~~~ 下面來看wpas_p2p_init中出現的幾個重要數據結構,首先是p2p_config和p2p_data,它們的成員如圖7-29所示: :-: ![](http://img.blog.csdn.net/20140319211222281?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSW5ub3N0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 圖7-29 p2p_config和p2p_data結構示意圖 圖7-29展示了p2p_config和p2p_data兩個數據結構中一些重要的成員。其中: * p2p_config定義了20個回調函數。這些回調函數定義了P2P模塊和外界交互的接口。在wpas_p2p_init中,這些回調函數均指向p2p_supplicant.c中對應的函數,例如p2p_scan指向wpas_p2p_scan,dev_lost指向wpas_dev_lost。另外,由于回調函數的參數比較復雜,所以圖中均省略了參數信息。 * p2p_data指向一個p2p_config對象。 下面來看另外幾個重要數據結構的內容圖7-30展示了五種數據結構,其中: * p2p_device代表一個P2P設備。其中一些諸如設備名,Device CapabilityBitmap等信息保存在一個類型為p2p_peer_info的對象中。 * p2p_group代表一個P2P Group的信息,其內部包含一個p2p_group_config對象和一個p2p_group_member鏈表。p2p_group_config表示該Group的配置信息,p2p_group_member代表Group Member即P2P Client的信息。 下面來看另外幾個重要數據結構的內容,如圖7-30所示: :-: ![](http://img.blog.csdn.net/20140319211239296?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSW5ub3N0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 圖7-30 p2p_device及其他數據結構示意圖 >[info] 提示: WPAS中定義了非常多的數據結構類型,這極大增加了初學者的學習難度。根據筆者自己的經驗,建議讀者在學習過程中先簡單了解這些數據結構的名字及作用,然后在具體代碼分析時再結合代碼邏輯來了解這些數據結構及其內部各個成員變量的具體作用。 下面來看p2p_init函數。 **2、p2p_init函數** p2p_init函數將初始化WPAS中的P2P模塊,其代碼如下所示。 **p2p.c::p2p_init** ~~~ struct p2p_data * p2p_init(const struct p2p_config *cfg) { struct p2p_data *p2p; ...... /* 從下面這行代碼可看出,一個p2p_data對象的內存分布,該內存將包含一個p2p_data的所有信息以及一個 p2p_config對象的所有信息。 */ p2p = os_zalloc(sizeof(*p2p) + sizeof(*cfg)); // 將p2p_data的cfg成員變量指向保存p2p_config信息的那塊內存地址 p2p->cfg = (struct p2p_config *) (p2p + 1); os_memcpy(p2p->cfg, cfg, sizeof(*cfg)); // 拷貝傳入的p2p_config信息 if (cfg->dev_name) p2p->cfg->dev_name = os_strdup(cfg->dev_name); ......// 其他信息拷貝 #ifdef ANDROID_P2P p2p->min_disc_int = 2; // listen state的最小時間為200毫秒 p2p->sd_dev_list = NULL; #else p2p->min_disc_int = 1; #endif p2p->max_disc_int = 3; // 隨機獲取next_tie_breaker的初值 // 第二個參數1表示next_tie_breaker的字節長度,其類型是u8 os_get_random(&p2p->next_tie_breaker, 1); p2p->next_tie_breaker &= 0x01; // 設置本機P2P Device的device capability信息 if (cfg->sd_request) p2p->dev_capab |= P2P_DEV_CAPAB_SERVICE_DISCOVERY; p2p->dev_capab |= P2P_DEV_CAPAB_INVITATION_PROCEDURE; if (cfg->concurrent_operations)// 支持concurrent功能 p2p->dev_capab |= P2P_DEV_CAPAB_CONCURRENT_OPER; p2p->dev_capab |= P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY; dl_list_init(&p2p->devices); // 注冊一個超時時間(如果定義了ANDROID_P2P宏,該時間為30ms) // 用來檢測是否有不活躍的p2p_device eloop_register_timeout(P2P_PEER_EXPIRATION_INTERVAL, 0,p2p_expiration_timeout, p2p, NULL); return p2p; } ~~~ p2p模塊初始化還算比較簡單。 **3、注冊Action幀監聽事件** 4.3.4節分析wpa_driver_nl80211_finish_drv_init時曾介紹過,wpa_driver_nl80211_set_mode函數和P2P關系較大。為什么這么說呢?相信代碼能給出最直接的解釋。 **driver_nl80211.c::wpa_driver_nl80211_set_mode** ~~~ static int wpa_driver_nl80211_set_mode(struct i802_bss *bss, enum nl80211_iftype nlmode) { // 注意,在wpa_driver_nl80211_finish_drv_init函數中,nlmode被設置為NL80211_IFTYPE_STATION struct wpa_driver_nl80211_data *drv = bss->drv; int ret = -1; int i; /* drv->nlmode的類型為enum nl80211_iftype,4.3.4節關于wpa_driver_nl80211_finish_drv_init 的分析中有對該變量的解釋。drv->nlmode只有為NL80211_IFTYPE_AP或NL80211_IFTYPE_P2P_GO時, is_ap_interface函數才返回非0值。很顯然此時virtual interface的類型不可能是GO。 */ int was_ap = is_ap_interface(drv->nlmode); int res; // 設置虛擬interface的類型為NL80211_IFTYPE_STATION res = nl80211_set_mode(drv, drv->ifindex, nlmode); if (res == 0) { drv->nlmode = nlmode; ret = 0; goto done;// 設置成功,直接跳轉到done處 } ...... done: ...... if (is_ap_interface(nlmode)) { nl80211_mgmt_unsubscribe(bss, "start AP"); if (nl80211_setup_ap(bss)) return -1; } else if (was_ap) { nl80211_teardown_ap(bss); } else { // 本例將執行下面這個函數以取消監聽Action幀事件 // 由于之前并未注冊,所以此時執行這個函數將沒有實際作用 nl80211_mgmt_unsubscribe(bss, "mode change"); } if (!is_ap_interface(nlmode) && nl80211_mgmt_subscribe_non_ap(bss) < 0)// 注冊對Action幀的監聽事件 wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action " "frame processing - ignore for now"); return 0; } ~~~ nl80211_mgmt_subscribte_non_ap將注冊對Action幀的監聽事件,其作用就是當設備收到Action幀后,Wi-Fi驅動將發送對應的netlink消息給WPAS。來看nl80211_mgmt_subscribte_non_ap函數,代碼如下所示。 **driver_nl80211.c::nl80211_mgmt_subscribte_non_ap** ~~~ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) { struct wpa_driver_nl80211_data *drv = bss->drv; /* 下面這個函數將注冊libnl回調事件到event loop。在4.3.4節關于 wpa_driver_nl80211_init_nl與nl80211_init_bss分析中曾詳細介紹過該函數。 總之,當WPAS收到對應的netlink消息后,process_bss_event函數將被調用。 */ if (nl80211_alloc_mgmt_handle(bss)) return -1; #if defined(CONFIG_P2P) || defined(CONFIG_INTERWORKING) ......// 注冊對GAS Public Action幀的監聽,Service Discovery和它有關 #endif /* CONFIG_P2P || CONFIG_INTERWORKING */ #ifdef CONFIG_P2P /* 注冊對P2P Public Action幀的監聽,第二個參數中的04-09-50-6F-9A-09指明了P2P Public Action 幀Frame Body的Category、Action Field、OUI、OUI-Type(參考表7-3)的取值。即只有收到的 Frame Body對應字段分別等于上述指定值的Action幀,Wi-Fi驅動才會發送netlink消息給WPAS。 */ if (nl80211_register_action_frame(bss, (u8 *) "\x04\x09\x50\x6f\x9a\x09",6) < 0) return -1; /* 注冊對P2P Action幀的監聽,第二個參數中7F-50-6F-9A-09指明了Action幀Frame Body的 Category和OUI。根據802.11規范,7F代表Vendor Specific,50-6F-9A是WFA的OUI,最后一個 09代表P2P。 */ if (nl80211_register_action_frame(bss,(u8 *)"\x7f\x50\x6f\x9a\x09",5) < 0) return -1; #endif /* CONFIG_P2P */ #ifdef CONFIG_IEEE80211W ...... #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_TDLS ...... #endif /* CONFIG_TDLS */ ......// 其他感興趣幀的注冊 return 0; } ~~~ 由上述代碼可知nl80211_mgmt_subscribe_non_ap在P2P方面注冊了兩種類型的幀監聽事件。 * P2P Public Action幀監聽事件:根據P2P規范,目前使用的均是802.11 Public Action幀,即Category的值為0x04。目前GON、P2P Invitation、Provision Discovery以及Device Discoverability使用P2P Public Action幀。 * P2P Action幀監聽事件:這種類型的幀屬于802.11 Action幀的一種,其Category取值為0x7F,OUI指定為WFA的OUI(即50-6F-9A),而OUI-Type指定為P2P(取值為0x09)。目前Noticeof Absence、P2P Presence、GO Discoverability使用P2P Action幀。 >[info] 注意 上述注冊的Action幀監聽事件對應的處理函數是process_bss_event。 至此,P2P模塊以及Action幀監聽事件注冊等工作都已完成,WPAS馬上可為WifiP2pService提供P2P相關的服務了。下面將結合7.2節中介紹的如下幾個重要的P2P工作流程來分析代碼。 * 搜索周圍的P2P設備。 * 向某個P2P設備發起Provision Discovery流程。 * 對端設備開展Group Formation流程,重點關注其中的Group Negotiation。 >[info] 提示 GON結束后,如果本機設備扮演Client,則后續工作包括Provisioning(即WSC安全配置協商,本機充當Enrollee,參考第6章)和加入Group(類似STA加入AP,參考第4章)。如果本機扮演GO,則后續工作也分為Provisioning(充當Registrar)和處理Client加入Group(扮演AP的角色)。本書不討論和GO相關的知識,請讀者在閱讀完相關章節基礎上自行研究它們。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看