修复 Linux RTLWifi 驱动的 AP 模式支持

买了个 TL-WN725N v1 的无线网卡,据它自己说是支持 AP 模式的,Linux 3.7.x 驱动正常,使用的 rtlwifi:rtl8192cu。使用 iw list 命令查看网卡的确是支持 AP 模式的,由于配置 hostapd 测试了一下,客户端也可以看到 AP 了,但连接上后就自动断开,iPad 直接就连接不上。。。

通过查找、分析,最后定位问题在驱动程序上,下面是修复补丁,将rtlwifi编译成独立的模块替换系统中原有的模块即可。

From 59fb30735cbe7eb4f69b13a056947efcc4bfeab0 Mon Sep 17 00:00:00 2001
From: Heiher <admin@heiher.info>
Date: Tue, 19 Feb 2013 22:51:22 +0800
Subject: [PATCH] rtlwifi: Fix AP mode.
 
---
 Makefile | 25 ++++++++++++++-----------
 core.c   | 26 ++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 11 deletions(-)
 
diff --git a/Makefile b/Makefile
index 97935c5..544d22b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_RTLWIFI) 		+= rtlwifi.o
+obj-m 		+= rtlwifi.o
 rtlwifi-objs	:=		\
 		base.o		\
 		cam.o		\
@@ -11,18 +11,21 @@ rtlwifi-objs	:=		\
 
 rtl8192c_common-objs +=		\
 
-ifneq ($(CONFIG_PCI),)
 rtlwifi-objs	+= pci.o
-endif
-
-ifneq ($(CONFIG_USB),)
 rtlwifi-objs	+= usb.o
-endif
 
-obj-$(CONFIG_RTL8192C_COMMON)	+= rtl8192c/
-obj-$(CONFIG_RTL8192CE)		+= rtl8192ce/
-obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
-obj-$(CONFIG_RTL8192SE)		+= rtl8192se/
-obj-$(CONFIG_RTL8192DE)		+= rtl8192de/
+#obj-m	+= rtl8192c/
+#obj-m	+= rtl8192ce/
+#obj-m	+= rtl8192cu/
+#obj-m	+= rtl8192se/
+#obj-m	+= rtl8192de/
 
 ccflags-y += -D__CHECK_ENDIAN__
+
+KVERSION = $(shell uname -r)
+
+all:
+	make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
+clean:
+	make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
+
diff --git a/core.c b/core.c
index a7c0e52..6e40070 100644
--- a/core.c
+++ b/core.c
@@ -574,6 +574,27 @@ static int rtl_op_conf_tx(struct ieee80211_hw *hw,
 	return 0;
 }
 
+static void _rtl_update_beacon(struct ieee80211_hw *hw,
+            struct ieee80211_sta *sta, struct ieee80211_vif *vif)
+{
+    struct sk_buff *skb;
+    struct ieee80211_tx_control control;
+
+    control.sta = sta;
+    skb = ieee80211_beacon_get(hw, vif);
+    rtl_op_tx(hw, &control, skb);
+}
+
+static int rtl_op_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+             bool set)
+{
+    struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+    _rtl_update_beacon(hw, sta, rtlpriv->mac80211.vif);
+
+    return 0;
+}
+
 static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_bss_conf *bss_conf, u32 changed)
@@ -591,6 +612,10 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 		if ((changed & BSS_CHANGED_BEACON) ||
 		    (changed & BSS_CHANGED_BEACON_ENABLED &&
 		     bss_conf->enable_beacon)) {
+			rcu_read_lock();
+			sta = get_sta(hw, vif, bss_conf->bssid);
+			_rtl_update_beacon(hw, sta, vif);
+			rcu_read_unlock();
 			if (mac->beacon_enabled == 0) {
 				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
 					 "BSS_CHANGED_BEACON_ENABLED\n");
@@ -1183,6 +1208,7 @@ const struct ieee80211_ops rtl_ops = {
 	.configure_filter = rtl_op_configure_filter,
 	.sta_add = rtl_op_sta_add,
 	.sta_remove = rtl_op_sta_remove,
+	.set_tim = rtl_op_set_tim,
 	.set_key = rtl_op_set_key,
 	.conf_tx = rtl_op_conf_tx,
 	.bss_info_changed = rtl_op_bss_info_changed,
-- 
1.8.1.3
cd linux-3.7
cd drivers/net/wirless/rtlwifi/
patch -Np1 -i ~/rtlwifi-Fix-AP-mode.patch
make
 
# Test
sudo rmmod rtl8129cu
sudo rmmod rtlwifi
sudo insmod ./rtlwifi.ko
sudo insmod rtl8192cu.ko

Over!

开始玩 Gjs 啦

以前玩了一段时间的 Vala,用于开发 GLib 及 GObject 对象系统的应用程序相对 C 语言就挺方便了。但感觉这种语言翻译还是有点复杂了,尤其是在遇到一个内存管理问题后,感觉更明显,而这个问题至今还没有被解决了。。。=> https://bugzilla.gnome.org/show_bug.cgi?id=684182

最近看到相关的资讯,GNOME 建议使用 Gjs 开发新的应用程序,因为目前的 GNOME Shell 已经在使用 gjs 了,并且之前也简单的修改过系统菜单方面的代码,觉得还是挺有意思的。现在就开始玩玩啦。

动态语言就是方便呀,有了 GObject-Introspection 后,一下子就多了那么多玩有的功能出来。语言绑定这个东西有的时候真的很烦人,但有的时候也挺可爱的。

说了半天都忘了说 Gjs 是啥了。。。Gjs 是 GNOME 的 Javascript 语言绑定,它主要基于 Spidermonkey javascript 引擎与 GObject-Introspection 框架。

在看了一些例子后,发现 Gjs 自身还是很简单的,对于使用它开发应用程序的人来说,只要学习了 javascript 的基本语法和项目给出的语法风格建议及了解 GObject-Introspection 并能够使用它就行了。下面就是具体用来的 Gir 库的使用问题了。

如果想了解的更多,如它是如何自我扩展的,可以先看看项目代码中的 modules。这让我想起了 JNI,其它就是一些接口的定义与实现,重要的就是数据的传递,类型的转换等等啦。

我还是先去学习一下 Javascript 的基本语法吧。。。

Over!