顯示具有 wifi 標籤的文章。 顯示所有文章
顯示具有 wifi 標籤的文章。 顯示所有文章

2013年1月30日 星期三

iwlist [interface] scanning 回傳訊息的順序修改

常常發現在不同的wifi dongle在使用iwlist [interface] scanning後所得到訊息往往裡面的順序都會有所不同,可是上層APP parse function已經寫好了(例如:目前的parse是以"Quality"的訊息來判對AP資訊的結束),又不想改寫的話,就只好修改wifi dongle driver 在iwlist [interface] scanning 回傳訊的順序,所以就去瞭解一下iwlist [interface] scanning的動作流程。

由iwlist.c中可以發現,scanning的動作是呼叫"print_scanning_info"函式,在此function中可以看到
      /* Initiate Scanning */
      if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0)
這裡就是對interface發出scanning的ioctl,而後就等待底層的回應
      /* Wait until something happens */
      ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
當底層有回應後,在呼叫
 if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0)
來讀取底層回傳的訊息。

所以修改底層可以先以"SIOCGIWSCAN"來搜尋,以RTL8192CU的驅動來看,
rtw_wx_set_scan, /* SIOCSIWSCAN */
rtw_wx_get_scan, /* SIOCGIWSCAN */
rtw_wx_set_essid, /* SIOCSIWESSID */
可以看到"SIOCGIWSCAN" 對應函式為"rtw_wx_get_scan",在其中可以看到"translate_scan"的函式,這個函式就是要修改的地方。在此函式中可以看到最後的訊息是Quality相關,也可以看到關鍵的cmd。
/* Add quality statistics */
iwe.cmd = IWEVQUAL;
接著再以"IWEVQUAL" 來搜尋RT5370 dirver,就可以看到"rt_ioctl_siwscan" int sta_ioctl.c,而其中Quality相關的動作是在中間
/*Channel and Frequency */
......
/*Add quality statistics */
....
/*Encyption key */
接下來就只要把Quality相關的程式碼移到函式的尾端,如此就可讓兩個WIFI dongle在iwlist [interface] scanning的回傳訊息中,每個AP都會以Quality作為結尾。

WIFI signal percentage與dbm互轉

因RTL8192CU與RT5370在iwlist [interface] scanning 回傳的訊息中,signal level的回傳值RTL8192CU使用percentage,而RT5370卻是以DB表示,所以為了統一UI上顯示的訊息,所以將signal level轉為percentage表示。

percentage to dbm:
在RTL8192CU的driver中有段程式碼將percentage to dbm(rtw_recv.h),程式碼如下:

__inline static s32 translate_percentage_to_dbm(u32 SignalStrengthIndex)
{
s32 SignalPower; // in dBm.

// Translate to dBm (x=0.5y-95).
SignalPower = (s32)((SignalStrengthIndex + 1) >> 1);
SignalPower -= 95;

return SignalPower;
}

dbm to percentage:
在RT5370的driver中有段程式碼將dbm to percentage(cmm_info.c),程式碼如下:
/* Rssi*/
Rssi = (INT)pBss->Rssi;
if (Rssi >= -50)
Rssi_Quality = 100;
else if (Rssi >= -80)    /* between -50 ~ -80dbm*/
Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10);
else if (Rssi >= -90)   /* between -80 ~ -90dbm*/
Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10);
else    /* < -84 dbm*/
Rssi_Quality = 0;
sprintf(msg+strlen(msg),"%-9d", Rssi_Quality);

也許有人會問怎麼不把percent to dbm的函式反轉就可以做dbm to percentage,為什麼要這麼麻煩?原本也是打算這麼做,可是實做後發現,也許是廠商不同,RT5370回傳的dbm值若是直接使用反轉的函式所得到的percentage值有時會出現超過100%的數值,所以後來還是乖乖的使用判斷的方式來將dbm to percentage。