當然,Google 的結果也是找到一些不確定是直接或間接的解答,只好彙整、研究、分析,再加上許多嘗試,終於,還是找到成功安裝的步驟。
一、下載「驅動程式」、解壓縮
和前文一樣,從 Realtek 的官網下載驅動程式才安全,因為要修改「核心模組原始碼」的一個標頭檔及三個 C 程式檔,所以原有驅動程式的安裝不可以讓它自動作業,要分段執行。第一步先解壓縮,
[SiB@M2400 ~]$ unzip RTL8192xC_USB_linux_v3.4.4_4749.20121105.zip解開後,產生一個名為 RTL8188C_8192C_USB_linux_v3.4.4_4749.20121105 的目錄,之後的文章中將這個目錄稱為『原始碼目錄』。
接著把工作目錄切換到『原始碼目錄』中一個『driver』目錄,還要再做解壓縮,
[SiB@M2400 ~]$ cd RTL8188C_8192C_USB_linux_v3.4.4_4749.20121105/driver/解開後,產生一個名為 rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105 的目錄,之後的文章中將這個目錄稱為『驅動原始碼目錄』,主要修改的檔案就在這個目錄之下。
[SiB@M2400 driver]$ tar zxvf rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105.tar.gz
二、下載「修補檔」參考、修改編譯腳本及程式
從這裏下載「修補檔」。筆者測試結果,可以正確修改驅動程式檔,所以可直接用『修補』命令的方式偷懶。先將工作目錄切換到『驅動原始碼目錄』,再用 patch 命令修補檔案,[SiB@M2400 driver]$ cd rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105上兩個命令是接續前面的命令,第二個命令是假設所下載的『修補檔(patch file)』在用戶 SiB 的『家目錄』。所修改的檔案整理如下:
[SiB@M2400 rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105]$ patch -p1 -i ~/use_kthread_run.patch
目錄 | 檔案名 | 修改處的列號 |
---|---|---|
驅動原始碼目錄/core/ | rtw_mp.c | 1143 |
驅動原始碼目錄/include/ | osdep_service.h | 102, 137, 572, 829 |
驅動原始碼目錄/os_dep/ | osdep_service.c | 1555 |
驅動原始碼目錄/os_dep/linux/ | os_intfs.c | 799 |
檔案『驅動原始碼目錄/core/rtw_mp.c』的修改
第 1143 列,原文//3 6. start thread pmp_priv->tx.PktTxThread = kernel_thread(mp_xmit_packet_thread, pmp_priv, CLONE_FS|CLONE_FILES); if(pmp_priv->tx.PktTxThread < 0) DBG_871X("Create PktTx Thread Fail !!!!!\n");修改為
//3 6. start thread if(!start_kthread(&pmp_priv->tx.PktTxThread, mp_xmit_packet_thread, pmp_priv, "8192cu-mp-xmit")) DBG_871X("Create PktTx Thread Fail !!!!!\n");完成以上修改後,存檔備用。
檔案『驅動原始碼目錄/include/osdep_service.h』的修改(由後而前)
第 829 或 830 列,原文為空白(檔案最後),加入三列文字成為#ifdef PLATFORM_LINUX extern int start_kthread(_thread_hdl_ *t_hdl, int (*threadfn)(void *data), void *data, const char *name); #endif第 572 列,原文(2013-3-4 增補)
#ifdef PLATFORM_LINUX //struct net_device *pnetdev = (struct net_device *)context; //daemonize("%s", pnetdev->name); daemonize("%s", "RTKTHREAD"); allow_signal(SIGTERM); #endif修改為
#ifdef PLATFORM_LINUX //struct net_device *pnetdev = (struct net_device *)context; //daemonize("%s", pnetdev->name); //daemonize("%s", "RTKTHREAD"); allow_signal(SIGTERM); #endif第 137 列,原文
typedef pid_t _thread_hdl_;修改為
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) typedef pid_t _thread_hdl_; #else typedef struct task_struct * _thread_hdl_; #endif第 102 或 103 列,原文為空白,加入三列文字成為
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) #include <linux/kthread.h> #endif完成以上修改後,存檔備用。
檔案『驅動原始碼目錄/os_dep/osdep_service.c』的修改
第 1555 列,原文為空白(檔案最後),加入 14 列文字#ifdef PLATFORM_LINUX int start_kthread(_thread_hdl_ *t_hdl, int (*threadfn)(void *data), void *data, const char *name) { #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) *t_hdl = kernel_thread(threadfn, data, CLONE_FS|CLONE_FILES); if(*t_hdl < 0) #else *t_hdl = kthread_run(threadfn, data, name); if(IS_ERR(*t_hdl)) #endif return 0; return -1; } #endif完成以上修改後,存檔備用。
檔案『驅動原始碼目錄/os_dep/linux/os_intfs.c』的修改
第 799 列,原文#ifdef CONFIG_SDIO_HCI padapter->xmitThread = kernel_thread(rtw_xmit_thread, padapter, CLONE_FS|CLONE_FILES); if(padapter->xmitThread < 0) _status = _FAIL; #endif #ifdef CONFIG_RECV_THREAD_MODE padapter->recvThread = kernel_thread(recv_thread, padapter, CLONE_FS|CLONE_FILES); if(padapter->recvThread < 0) _status = _FAIL; #endif padapter->cmdThread = kernel_thread(rtw_cmd_thread, padapter, CLONE_FS|CLONE_FILES); if(padapter->cmdThread < 0) _status = _FAIL; else _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); //wait for cmd_thread to run #ifdef CONFIG_EVENT_THREAD_MODE padapter->evtThread = kernel_thread(event_thread, padapter, CLONE_FS|CLONE_FILES); if(padapter->evtThread < 0) _status = _FAIL; #endif
修改為
幾個相關的發文列在下面,有需要的讀者請自行參考:
就是抑制 Fedora 原裝驅動程式,筆者發現的幾個做法,把它們都列出來,讓讀者自己選用:
#ifdef CONFIG_SDIO_HCI if(!start_kthread(&padapter->xmitThread, rtw_xmit_thread, padapter, "8192cu-xmit")) _status = _FAIL; #endif #ifdef CONFIG_RECV_THREAD_MODE if(!start_kthread(&padapter->recvThread, recv_thread, padapter, "8192cu-recv")) _status = _FAIL; #endif if(!start_kthread(&padapter->cmdThread, rtw_cmd_thread, padapter, "8192cu-cmd")) _status = _FAIL; else _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); //wait for cmd_thread to run #ifdef CONFIG_EVENT_THREAD_MODE if(!start_kthread(&padapter->evtThread, event_thread, padapter, "8192cu-evt")) _status = _FAIL; #endif完成以上修改後,存檔備用。
三、編譯「核心模組」
接下來準備下編譯命令了,先切換成 root 身份,並將工作目錄切換到『驅動原始碼目錄』,再下命令[root@M2400 rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105]# make
四、安裝「核心模組」
最後執行安裝操作,這些命令是從『原始碼目錄』下的 install.sh 這個腳本檔取出。這是 Realtek RTL8192cu 驅動程式原來的安裝步驟(解壓縮、編譯、安裝)的最後一個步驟,這時候,讀者應該可以開始測試無線網路了。[root@M2400 rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105]# rmmod rtl8192cu
[root@M2400 rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105]# insmod 8192cu.ko
[root@M2400 rtl8188C_8192C_usb_linux_v3.4.4_4749.20121105]# make install
幾個相關的發文列在下面,有需要的讀者請自行參考:
- 安裝 Fedora 的某特定版本之套件
- 安裝 Fedora 「編譯『核心模組』」所需套件
- 在 Fedora 安裝「EDIMAX EW-7811Un」的驅動程式
- 在 Fedora 18 用「EDIMAX EW-7811Un」的變通辦法
五、抑制 Fedora 原裝驅動程式
安裝完成後,當然希望下次開機可以作業系統可以載入正確的核心模組,在重開機前還有個步驟要做,待會重開機才會正確。就是抑制 Fedora 原裝驅動程式,筆者發現的幾個做法,把它們都列出來,讓讀者自己選用:
- 在檔案『/etc/modprobe.d/blacklist.conf』末,加上『blacklist rtl8192cu』這行敘述。
- 或是在檔案『/boot/grub2/grub.conf』中,linux 開始那列命令最後,加上『modprobe.blacklist=rtl8192cu』。
後記:
- 2013-2-22:發現 Fedora 的核心又更新到 3.7.9-201,按照本文再試一下。修改了一個忙中有錯的地方。同時簡化本文步驟,移除 version.h 的鏈結設定;這個設定在編譯 EDIMAX EW-7811Un 的核心模組時是不需要的,但編譯其它核心模組時,可能需要。因此,若是已加入 version.h 鏈結,不必移除也不會出錯。
- 2013-3-4:Fedora 的核心又更新到 3.8.1-201。在檔案『驅動原始碼目錄/include/osdep_service.h』的第 575 列要再修改一下,編譯才不會出錯。
- 2013-3-25:若是安裝 Fedora 17 系統,在最近的更新之後 kernel 為 3.8.3-103,同樣會出現這個問題。本文解決辦法也可適用。
已測試版本:
- Fedora 18: kernel 3.7.6-201, 3.7.7-201, 3.7.8-202, 3.7.9-201
參考資料:
- Ask Fedora, "Realtek 8192cu Fedora 18," [Fed. 18, 2013].
- Canonical Ltd., "Comment 65 for bug 1030858," [Fed. 18, 2013].
- Canonical Ltd., "0bda:8176 RTL8188CUS does not connect to wireless networks," Jul. 30, 2012 [Fed. 18, 2013].
- Jan-Marek Glogowski, "[Bug 1030858] Re: 0bda:8176 RTL8188CUS does not connect to wireless networks," Dec. 20, 2012 [Fed. 18, 2013].
沒有留言:
張貼留言
感謝你耐心看完本文,歡迎留下任何指正、建議,筆者會儘快回應。(English is also welcome.)