2007-10-24

アクセスポイントの一覧を取得してみる

OID_802_11_BSSID_LISTを使って無線アクセスポイントの一覧を取得してみました。
 
ポイントは、先に OID_802_11_BSSID_LIST_SCANを呼ぶ必要があることと、OID_802_11_BSSID_LIST_SCANの呼び出しが終わってもアクセスポイントの一覧は更新されていないことがあるという事でしょうか。
別の解説では 6秒とか書かれてますが、そんなに待てませんよね...
 
あと、2つめ以降の BSSIDを取得しようとして pNdisBssidList->Bssid[i]と書いてしばらく悩んでいました。 (Cは不慣れなので...)
 
DWORD                           dwBytesReturned = 0,
                                dwError;
UCHAR                           ucQueryBuffer[1024]; // サイズは適当...
PNDISUIO_QUERY_OID              pNdisQueryOid;
PNDISUIO_SET_OID                pNdisSetOid;
PNDIS_802_11_BSSID_LIST_EX      pNdisBssidList;
PNDIS_WLAN_BSSID_EX             pNdisBssid;


// BSSIDの一覧を更新
ZeroMemory(ucQueryBuffer, 1024);
pNdisSetOid                     = (PNDISUIO_SET_OID)&ucQueryBuffer[0];
pNdisSetOid->Oid                = OID_802_11_BSSID_LIST_SCAN;
pNdisSetOid->ptcDeviceName      = WLAN_DEVICE_NAME;

if (!DeviceIoControl(
        g_hNdis                         ,
        IOCTL_NDISUIO_SET_OID_VALUE     ,
        (LPVOID)&ucQueryBuffer[0]       ,
        sizeof(ucQueryBuffer)           ,
        (LPVOID)&ucQueryBuffer[0]       ,
        sizeof(ucQueryBuffer)           ,
        &dwBytesReturned                ,
        NULL
)) {
    dwError = GetLastError();
}

// 一応 待ってみる
Sleep(6000);

// BSSIDの一覧を取得
ZeroMemory(ucQueryBuffer, 1024);
pNdisQueryOid                   = (PNDISUIO_QUERY_OID)&ucQueryBuffer[0];
pNdisQueryOid->Oid              = OID_802_11_BSSID_LIST;
pNdisQueryOid->ptcDeviceName    = WLAN_DEVICE_NAME;


if (DeviceIoControl(
        g_hNdis                         ,
        IOCTL_NDISUIO_QUERY_OID_VALUE   ,
        (LPVOID)&ucQueryBuffer[0]       ,
        sizeof(ucQueryBuffer)           ,
        (LPVOID)&ucQueryBuffer[0]       ,
        sizeof(ucQueryBuffer)           ,
        &dwBytesReturned                ,
        NULL
)) {
    pNdisBssidList = (PNDIS_802_11_BSSID_LIST_EX)pNdisQueryOid->Data;
    pNdisBssid = &(pNdisBssidList->Bssid[0]);
    for (int i = 0; i < pNdisBssidList->NumberOfItems; i++) {
        if (pNdisBssid->Length) {
            // 有効なデータ
        }
        // 次のBSSID
        pNdisBssid = (PNDIS_WLAN_BSSID_EX)(((PBYTE)pNdisBssid) + pNdisBssid->Length );
    }
} else {
    dwError = GetLastError();
}
 
これでインフラストラクチャモード、アドホックモード問わずにアクセスポイントの一覧を取得できるようになりました。
 
ついでに NDIS_WLAN_BSSID_EXの NetworkTypeInUseメンバを見ると Ndis802_11OFDM24(802.11g)が返ってきていました。
すぐにでも WifiInfoに組み込もうと思ったのですが、試してみると 11bのアクセスポイントに対しても Ndis802_11OFDM24が返ってきています。
 
こんなところでオチをつけなくてもいいのに...。
 
ちょっと残念ですが、少なくともアクセスポイントの一覧は取得できたので良しとしましょう。
 

4 件のコメント:

匿名 さんのコメント...

WifiInfoの更新wktk

kazuaki さんのコメント...

こんにちは。
コメントありがとうございます。

残念ながら 11b, 11gの種別はうまく取れないようです。

インフラストラクチャ-アドホックの切り替えも今のところうまく動いていません。
ちょっと別の方法を探してみますので気長にお待ち下さい(笑

yamame さんのコメント...

プログラミング的な事は全く分かりませんけど、なんか面倒な事になってますね。
>11bのアクセスポイントに対してもNdis802_11OFDM24が返ってきています。
これはアドエス以外でも同じなんでしょうか?アドエスだけならSHARPの手抜きという事にry
そういえば、WifiInfoのカーソルキー左右で表示が切り替えられますが、押してからワンテンポ遅れるのは数値取得とかに時間が掛かっているからでしょうか?

あと、関係ない話ですけど。
ttp://d.hatena.ne.jp/solipt/20071026/1193327658
「Standard SDIOで、3.5~6.5Mbpsなのが、このHS-SDIOで9~16Mbps」
Wifiの転送速度の限界はWM自体の限界ではなく、SDIOの限界と言うことですかね。

kazuaki さんのコメント...

yamameさん こんにちは。

Windows Mobileのプログラムはアドエスからなので他の状況はわかりませんが、いろいろ検索していると他のデバイスでも色々と動作しない機能があるみたいです。

WifiInfoの表示切り替えが遅いのは 情報の取得で時間がかかっているのではなく、画面を書き換えるかどうかを一定時間ごとに判定しているためだと思います。
よく考えたら即時反映の方がいいですよね。

HS SDIOの記事については不勉強なのでよくわかりません。アドエスの無線LANも SDIOで接続されているという事なのでしょうか。
アドエスも通信速度自体はそれほど悪くないと思っています。むしろ多少通信速度があがっても処理速度が追いつかないでしょうね。