2015年8月4日 星期二

在 Fedora 22 安裝「EDIMAX EW-7811Un」驅動程式

將舊筆電由 Fedora 20 升級到 Fedora 22,在編譯 EDIMAX EW-7811Un 的「驅動程式核心模組」時,果不其然地又遇到問題了。原因又是 Linux 中的 C 函式庫有些調整,花了些時間把問題全部解決了。既然,Fedora 改版了,乾脆前文也重新改寫一次,用一個有完整的安裝步驟的發文,開啟另一個階段的序幕。
  以下的操作步驟是基於這些條件,如果讀者有情況不同,要斟酌修改:
  • 下載的「驅動程式」原始檔案,先存在一般使用者目錄下。
  • 解壓縮、修改、編譯等步驟,也都在一般使用者的權限下進行。
  • 進行安裝前,切換成 root 身份

一、下載「驅動程式」、解壓縮

從 Realtek 的官網下載 RTL8192CU 最新版的驅動程式 (目前是 4.0.2_9000.20130911),因為要修改「核心模組原始碼」的一個 C 程式檔,所以原有驅動程式的安裝不可以讓它自動作業,要分段執行。
    第一步先解壓縮,
[SiB@M2400 ~]$ unzip RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip
解開後,產生一個名為 RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911 的目錄,之後的文章中將這個目錄稱為『原始碼目錄』。
  接著把工作目錄切換到『原始碼目錄』中一個『driver』目錄,還要再做解壓縮,
[SiB@M2400 ~]$ cd RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/driver/
[SiB@M2400 driver]$ tar zxvf rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911.tar.gz
解開後,產生一個名為 rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911 的目錄,之後的文章中將這個目錄稱為『驅動原始碼目錄』(RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/driver/),主要修改的檔案就在這個目錄之下。

二、修改驅動程式原始碼

筆者未修改程式前,出現編譯錯誤的檔案是『 os_intfs.c 』這個檔,就從這個檔案的修改先做。運氣好的話,就只要修改這個檔案就好了。將修改處整理在後,因為檔案前面的修改都會加入文字,影響之後的列數,故由程式後端開始修改。

檔案『驅動原始碼目錄 /os_dep/linux/os_intfs.c』的修改

第 948 列(註:本次增加的修改),原文
static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb)
{
修改為
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 12, 0))
static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb) // Original
#else
   #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
   // Added for compiling in F20 (after 3.14.9)
   static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback)
   #else
   // Added for compiling in F20 (before 3.14.9)
   static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv)
   #endif
#endif
{
第 750 列,原文
            rtw_proc = NULL;
        }
    }
}
#endif
修改為
            rtw_proc = NULL;
        }
    }
}
#endif  /* create_proc_entry not defined */
#endif
第 278 列,原文
#define RTW_PROC_NAME DRV_NAME

void rtw_proc_init_one(struct net_device *dev)
修改為
#define RTW_PROC_NAME DRV_NAME
  
#ifndef create_proc_entry
/* dummy routines */
void rtw_proc_remove_one(struct net_device *dev) { }
void rtw_proc_init_one(struct net_device *dev) { }
#else  /* create_proc_entry not defined */

void rtw_proc_init_one(struct net_device *dev)

檔案『驅動原始碼目錄 /os_dep/linux/usb_intf.c』的修改

第 1580 列(註:本次增加的修改),原文
    DBG_871X(DRV_NAME " driver version=%s\n", DRIVERVERSION);
    DBG_871X("build time: %s %s\n", __DATE__, __TIME__);
修改為
    DBG_871X(DRV_NAME " driver version=%s\n", DRIVERVERSION);
    //DBG_871X("build time: %s %s\n", __DATE__, __TIME__);
即將第 1580 列註解掉,使其不執行。

檔案『驅動原始碼目錄 /os_dep/linux/rtw_android.c』的修改

第 233 列(註:本次增加的修改),原文
    for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
        if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
            break;
修改為
    for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
        if(0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
            break;
即將函式『strnicmp()』改為『strncasecmp()』。

檔案『驅動原始碼目錄 /hal/rtl8192c/rtl8192c_rf6052.c』的修改

第 1018 列(註:本次增加的修改),原文
    for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
    {
        for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++)
        {
            RF_Shadow[eRFPath][Offset].Value = 0;
修改為
    for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++)
    {
        for (Offset = 0; Offset < RF6052_MAX_REG; Offset++)
        {
            RF_Shadow[eRFPath][Offset].Value = 0;
即將『 <= 』改為『 < 』。

完成以上修改後,存檔備用。

三、編譯「核心模組」

接下來準備下編譯命令了,先不急著切換為 root 權限。並將工作目錄切換到『驅動原始碼目錄』,再下命令
[SiB@M2400 rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911]$ make

四、安裝「核心模組」

最後執行安裝操作,這時再切換成 root 身份,這些命令是從『原始碼目錄』下的 install.sh 這個腳本檔取出。這是 Realtek RTL8192cu 驅動程式原來的安裝步驟(解壓縮、編譯、安裝)的最後一個步驟,
[root@M2400 rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911]# rmmod rtl8192cu
[root@M2400 rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911]# insmod 8192cu.ko
[root@M2400 rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911]# make install
單純命令如下,方便複製、貼上
rmmod rtl8192cu
insmod 8192cu.ko
make install
這時候,讀者應該可以開始測試無線網路了。
  幾個相關的發文列在下面,有需要的讀者請自行參考:

五、抑制 Fedora 原裝的驅動程式

安裝完成後,當然希望下次開機可以作業系統可以載入正確的核心模組,在重開機前還有個步驟要做,待會重開機才會正確。
  就是抑制 Fedora 原裝驅動程式,筆者發現的幾個做法,把它們都列出來,讓讀者自己選用:
  • 在檔案『 /etc/modprobe.d/blacklist.conf 』末,加上『 blacklist rtl8192cu 』這行敘述。
  • 或是在檔案『 /boot/grub2/grub.conf 』中,linux 開始那列命令最後,加上『 modprobe.blacklist=rtl8192cu 』。
注意:『  』只是為標示文字範圍,不要加進去。

六、更新核心後,立即編譯新版的驅動程式

在舊版核心(網路可正常使用時)執行系統的 kernel 更新後,可以立即編譯、安裝適用新版的驅動程式。這樣重開機時,以新核心啟用 Fedora 時,就不會沒網路用了。
  假設讀者已經參考前面的發文,修改好 EDIMAX EW-7811un 的驅動程式原始碼(請參考前段發文」。以下步驟說明是以 Fedora 22 核心版本 4.1.3-200,而電腦是 i686 等級的 CPU 為例,執行之五個命令如下:
cd ~/RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/driver/rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911/
make ARCH=i386 -C /lib/modules/4.1.3-200.fc22.i686/build M=`pwd` modules
su
install -p -m 644 8192cu.ko /lib/modules/4.1.3-200.fc22.i686/kernel/drivers/net/wireless/
/sbin/depmod -a 4.1.3-200.fc22.i686
第一個命令是切換到解壓縮後的驅動程式原始碼目錄,第二個命令是編譯『驅動程式的核心模組』。第三個命令是將權限切換到 root 身份,但不改變目前的工作目錄。接下來的兩個命令是將編譯好的『核心模組』安裝到新版的 Linux 核心。
  若讀者的電腦是 64-bit 的 CPU, 那麼參考的五個命令為:
cd ~/RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911/driver/rtl8188C_8192C_usb_linux_v4.0.2_9000.20130911/
make ARCH=x86_64 -C /lib/modules/4.1.3-200.fc22.x86_64/build M=`pwd` modules
su
install -p -m 644 8192cu.ko  /lib/modules/4.1.3-200.fc22.x86_64/kernel/drivers/net/wireless/
/sbin/depmod -a 4.1.3-200.fc22.x86_64

注意一:如果這階段使用前文的方法,一開始就切換到 root 身份,就不用『su』這個命令了。
注意二:上例兩組命令中的『4.1.3-200.fc22.i686』和『4.1.3-200.fc22.x86_64』是對應更新後新版的 Linux 核心模組,可以用『uname -r』這個命令查詢,
[SiB@M2400 ~]$ uname -r
4.1.3-200.fc22.i686
在用『 yum 』更新的過程中,也會出現新更新的核心之版本訊息,讀者稍加留意也可得知。

七、相關資訊

找尋這些編譯步驟的奮戰過程,請參考之前的發文:

已測試版本:

  ⚫ Fedora 22 : 4.1.10-200, 4.1.8-200, 4.1.7-200, 4.1.6-200, 4.1.4-200, 4.1.3-200
4.0.7-300, 4.0.4-300

參考資料:

沒有留言:

張貼留言

感謝你耐心看完本文,歡迎留下任何指正、建議,筆者會儘快回應。(English is also welcome.)