S5PC100-board android 2.1 RT3070 usb wifi 移植
硬件环境:s5pc100开发板,rt3070usbwifi模块
软件环境:
unbuntu8.10;
linux-2.6.29内核
utc100_android_2.1源码;
rt3070模块驱动;
1.首先我们将需要的上述四个工作文件拷贝到工作目录下
2.接着我们查看一下linux-2.6.29-sansung
打开这个内核源码工作目录
查看一下里面的参数有没有设置正确
make menuconfig
(1)Networking support
->wireless
->[*]Common routines for IEEE802.11 drivers
这个是关系到 wifi 相应服务的一些参数
打开后发现没有什么需要修改的
Device Drivers->
->Network device support
->[*]Wireless LAN
[*] Wireless LAN (pre-802.11)
< > STRIP (Metricom starmode radio IP)
[*] Wireless LAN (IEEE 802.11)
<M> Marvell 8xxx Libertas WLAN driver support
< > Marvell Libertas 8388 USB 802.11b/g cards
[*] Enable full debugging output in the Libertas module.
< > USB ZD1201 based Wireless device support
< > Wireless RNDIS USB support
< > IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)
这里也没有什么需要修改 的
3.由于我们默认的是像素是800x768,而我们的触屏像素默认的是480x272
所以要进行修改
Device Driversà
Graphics support à
Support for frame buffer devices à
Select LCD Type (Innolux 4.3 inch(480x272))
(X) Innolux 4.3 inch (480x272)
修改 后我们回到linux-2.6.29-sansung下
make
会生成 zImage 这个就是真正的内核镜像文件 ,我们将其拷贝到tftpboot目录下
4. 接着我们对wifi模块相关的目录进行修改
将rt3070解压后在其目录下会找到三个工作目录
MODULE
NETIF
UTIL
这三个目录分别是我们包含了我们需要使用的三个wifi加载模块
由于我们所使用的内核是linux-2.6.29,
所以我们需要查看顶层目录下的Makefile
2 all:
3 make -C UTIL/
4 $(SHELL) cp_util.sh
5 make -C MODULE/
6 $(SHELL) cp_module.sh
7 make -C NETIF/
8
9 clean:
10 make -C UTIL/ clean
11 make -C MODULE/ clean
12 make -C NETIF/ clean
5.再到RT3070原目录下的各个目录下进行修改
~/rt3070/MODULE/
~/rt3070/ NETIF/
~/rt3070/ UTIL/
在这个三个目录下会找到相应的Makefile
我们要修改其编译的源码工作路径
将其修改为内核所在的绝对路径:
107 ifeq ($(PLATFORM),PC)
108 # Linux 2.6
109 LINUX_SRC = /home/linux-2.6.29-sansung
由于我们选择的 平台选项为PC 即 PLATFORM = PC
所以我们只需修改PC这个选项的工作路径。
6.进行修改后我们到回到~/rt3070/目录下
make
z在三个目录下会生成三个相应的.ko
注!:~/rt3070/MODULE$ 这个目录下的
RT2870STA.dat 这个文件
这个文件非常重要,是RT3070的固件(firmware)内含它的一些配置属性。
接着我们到android_2.1目录下
7. 安装交叉工具链
下载cross-4.2.2-eabi.tar.bz2 和arm-none-linux-gnueabi-arm-2008q3-72-for-linux.tar.bz2
(网上查找)
arm-none-linux-gnueabi-arm-2008q3-72-for-linux.tar.bz2
cross-4.2.2-eabi.tar.bz2
将这两个解压缩文件安装到/usr/local/arm/下
然后使用tar 命令解压这两个文件
这两个工具链要安装到/usr/local/arm/下 。
执行命令:
$ tar xvf arm-none-linux-gnueabi-arm-2008q3-72-for-linux.tar.bz2
接下来将cross-4.2.2-eabi.tar.bz2解压
$ tar xvf cross-4.2.2-eabi.tar.bz2
8.之后回到android2.1_v1.
先编译android 源码 make TARGET_PRODUCT=s5p100
编译需要很长时间,编译完之后我们制作filesystem(文件系统),
在根目录下编写一个制作文件系统的shell脚本;
vim make_utc100_yaffs2_image.sh
#!/bin/sh
rm ./filesystem -rf
mkdir ./filesystem
cp ./out/target/product/utc100/root/* ./filesystem/ -a
cp ./out/target/product/utc100/system ./filesystem/ -a
cp ./vendor/sec/utc100/app/* ./filesystem/system/app/ -a
tar zxvf ./vendor/sec/utc100/busybox.tgz -C ./filesystem/system/
#./mkyaffs2image ./utc100_root/ utc100_root.img
做完这步之后修改这个脚本的执行权限 chmod 755 make_utc100_yaffs2_image.sh
这样我们就能够执行 ./ make_utc100_yaffs2_image.sh
接着我们就能够在当前目录下找到 filesystem 这个目录下 了
当然你也可以通过拷贝来制作文件系统:
在主目录下mkdir filesystem
cd utc100_android_2.1
cp ./out/target/product/utc100/root/* ./filesystem/ -a
cp ./out/target/product/utc100/system ./filesystem/ -a
cp ./vendor/sec/utc100/app/* ./filesystem/system/app/ -a
使用这几步后,一个文件系统就这样制作成功了
文件系统制作以后
需要改变其用户所有组
sudo chown filesystem/* root.root
sudo chmod 777 filesystem/*
然后我们将 filesystem拷贝至 /opt/目录下
到根目录下修改 sudo vim /etc/exports
最后一行进行添加:/opt/filesystem *(rw,sync,no_subtree_check,no_root_squash)
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/opt/filesystem *(rw,sync,no_subtree_check,no_root_squash)
9.接下来我们通过网络挂载启动开发板,做好相应的开发板环境配置
setenv gatewayip 192.168.1.1
setenv ipaddr 192.168.1.175 //开发板IP
setenv serverip 192.168.1.155 //VMWARE IP
setenv bootcmd tftp 20008000 zImage\;bootm 20008000
setenv bootargs root=nfs nfsroot=192.168.1.155:/opt/filesystem init=/linuxrc console=ttySAC0,115200 ip=192.168.1.175
如果我们使用了minicom,
我们在开启开发板的时候要将VM虚拟机的窗口Removeabled Deivces-à serial port设置 成 disconnect,
10.启动开发板后发现,s5pc100 板子启动时提示没办法mount上nfs?
解决办法:
(1) 修改init.rc中注释掉69 行 72行 102行(这几行主要意思就是mount yaffs的文件系统)而我们已经自己制作了文件系统。
修改保存之后
重新启动
问题又出现了,提示:s5pc100 板子启动时没办法进入bin /sh ?
解决办法:
(1)修改init.rc中注释掉console /system/busybox/bin/ash
将 console /system/bin/sh前面的#号去掉
接着我们的开发板就能够正常启动到开发板了
11.但是我们按触摸屏时发现X方向是反的,
解决办法:触摸屏驱动ts是一个典型的input子系统的设备,上报的x值有问题,导致屏幕的位置不正确,所以要修改上报input子系统的x方向的值。
1.首先打开~/linux-2.6.29-sansung/drivers/input/touchscreen/s3c-ts.c 打开相关调试信息
2.点击屏幕最左和最右两个点,在串口中发现根据adc转换后的这两个点的x值和大约为800,说明整个屏的在x方向总共分了800个位置
3.因为屏幕x方向是触摸方向是反的,对故在191行增加一句ts->xp = 800 -ts->xp;在上报input子系统前修改x值。
修改这个以后重新在~/linux-2.6.29-sansung/目录下make
重新编译加载内核,然后将其拷贝替换之前的zImage
12.重新启动开发板,将USBWIFI模块插在开发板上,在触摸屏上打开menu,点击settings中的Wireless & networks按下Wi-Fi按钮
它就会自动调用WifiEnabler.java
在串口终端输入:logcat & 打印后台信息
提示:unable to start wi-fi
修改HAL层的hardware/libhardware_legacy/wifi/wifi.c
wifi.c 是 wifi 的hardware 抽像层,必须修改 wifi_load() . wifi_unload()这两个加载和卸载的结构体
修改
int wifi_load_driver()
181 {
182 char driver_status[PROPERTY_VALUE_MAX];
183 int count = 100; /* wait at most 20 seconds for completion */
184 LOGE("starting load wifi driver!");
185 if (check_driver_loaded()) {
186 return 0;
187 }
188
189 /*
190 if (insmod(DRIVER_MODULE_PATH_1, DRIVER_MODULE_ARG) < 0)
191 {
192 LOGE("%s , wifi insmod module1 failed!",__FUNCTION__);
193 return -1;
194 }
195
196 if (insmod(DRIVER_MODULE_PATH_2, DRIVER_MODULE_ARG) < 0)
197 {
198 LOGE("%s , wifi insmod module2 failed!",__FUNCTION__);
199 return -1;
200 }
202
203 if (insmod(DRIVER_MODULE_PATH_3, DRIVER_MODULE_ARG) < 0)
204 {
205 LOGE("%s , wifi insmod module3 failed!",__FUNCTION__);
206 return -1;
207 }
208
209 LOGE("starting wait 10s");
210 usleep(10000000);
211 LOGE("end waiting 10s");
212 */
int wifi_unload_driver()
238 {
239 int count = 20; /* wait at most 20 seconds for completion */
240 /*
241 if (rmmod(DRIVER_MODULE_NAME_1) == 0)
242 {
243 LOGE("unload drvier1 successfull!\n");
244 usleep(500000);
245 if(rmmod(DRIVER_MODULE_NAME_2) == 0)
246 {
247 usleep(500000);//wait for a second
248 LOGE("unload drvier2 successfull!\n");
249 if(rmmod(DRIVER_MODULE_NAME_3) == 0)
250 {
251 LOGE("unload drvier3 successfull!\n");
252 return 0;
253 }
254 else
255 {
256 LOGE("unload drvier3 failed!\n");
257 return -1;
258 }
}
260 else
261 {
262 LOGE("unload drvier2 failed!\n");
263 return -1;
264 }
265 }
266 else
267 {
268 LOGE("unload drvier1 failed!\n");
269 return -1;
270
271 }*/
272
273 return 0;
274
275 /*
276 while (count-- > 0)
277 {
if (!check_driver_loaded())
279 break;
280 usleep(500000);
281 }
282
283 if (count)
284 {
285 return 0;
286 }
287
288 return -1;
289 }
290 else
291 return -1;*/
292 }
对这些行进行修改
还要修改
WIFI_DRIVER_MODULE_PATH等相关宏指定的名称和路径,保证顺利加载驱动和firmware
把所需要的wifi模块加进来
54 #ifndef WIFI_DRIVER_MODULE_PATH
55 #define WIFI_DRIVER_MODULE_PATH_1 "/system/lib/modules/rtutil3070sta.ko"
56 #define WIFI_DRIVER_MODULE_PATH_2 "/system/lib/modules/rt3070sta.ko"
57 #define WIFI_DRIVER_MODULE_PATH_3 "/system/lib/modules/rtnet3070sta.ko"
61 #define WIFI_DRIVER_MODULE_NAME_1 "rtnet3070sta"
62 #define WIFI_DRIVER_MODULE_NAME_2 "rt3070sta"
63 #define WIFI_DRIVER_MODULE_NAME_3 "rtutil3070sta"
69 #define WIFI_FIRMWARE_LOADER ""
70 #endif
71 #define WIFI_TEST_INTERFACE "ra0"
72
73 static const char IFACE_DIR[] = "/data/misc/wifi/wpa_supplicant";
74 //static const char IFACE_DIR[] = "/data/system/wpa_supplicant";
75 static const char DRIVER_MODULE_NAME_1[] = WIFI_DRIVER_MODULE_NAME_1;
76 static const char DRIVER_MODULE_NAME_2[] = WIFI_DRIVER_MODULE_NAME_2;
77 static const char DRIVER_MODULE_NAME_3[] = WIFI_DRIVER_MODULE_NAME_3;
78 static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME_1 " ";
79 static const char DRIVER_MODULE_PATH_1[] = WIFI_DRIVER_MODULE_PATH_1;
80 static const char DRIVER_MODULE_PATH_2[] = WIFI_DRIVER_MODULE_PATH_2;
81 static const char DRIVER_MODULE_PATH_3[] = WIFI_DRIVER_MODULE_PATH_3;
82 static const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG;
83 static const char FIRMWARE_LOADER[] = WIFI_FIRMWARE_LOADER;
84 static const char DRIVER_PROP_NAME[] = "wlan.driver.status";
85 static const char SUPPLICANT_NAME[] = "wpa_supplicant";
86 static const char SUPP_PROP_NAME[] = "init.svc.wpa_supplicant";
87 static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
88 static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf";
89 static const char MODULE_FILE[] = "/proc/modules";
修改完wifi.c之后
我们打开开发板接着调试
又出现了问题
提示
E/WifiHW ( 1893): Cannot open "/system/etc/wifi/wpa_supplicant.conf
usbcore: deregistering interface driver rt2870
<--- rtusb exit onf": No such file or directory
这主要是相关的wpa_supplicant的配置没做
修改init.rc
#for wifi
mkdir /system/etc/wifi 0777 wifi wifi
chmod 0777 /system/etc/wifi/wpa_supplicant.conf
chown wifi wifi /system/etc/wifi/wpa_supplicant.conf
#wpa_supplicant control socket for android wifi.c
mkdir /data/misc/wifi 0777 wifi wifi
mkdir /data/misc/wifi/sockets 0777 system wifi
mkdir /data/misc/wifi/wpa_supplicant 0777 wifi wifi
mkdir /data/system/wpa_supplicant
chown system wifi /data/system/wpa_supplicant
chmod 0777 /data/system/wpa_supplicant
//添加DHCP功能
mkdir /data/misc/dhcp
chmod 0777 /data/misc/dhcp
chown dhcp dhcp /data/misc/dhcp
setprop wifi.interface ra0
在init.rc的service启动部分添加如下:
#这里wpa_supplicant 使用wireless extension 作为 driver, wlan0 为intercace, /data/misc/wifi/wpa_supplicant.conf
#作为配置文件
service wpa_supplicant /system/bin/wpa_supplicant -d -Dwext -ira0 -c/data/misc/wifi/wpa_supplicant.conf
#user system
group system wifi inet
disabled
oneshot
service dhcpcd /system/bin/dhcpcd -f /system/etc/dhcpcd/dhcpcd.conf -d ra0
group system dhcp wifi
disabled
oneshot
13.启动时出现以下提示,原因是init.rc中启动service那几行的位置不正确
init: /init.rc: 108: invalid option 'chown'
init: /init.rc: 108: invalid option 'chmod'
init: /init.rc: 108: invalid option 'chown'
init: /init.rc: 108: invalid option 'chmod'
将关于启动service的命令放到init.rc的末尾。
14.再次测试遇到以下问题:E/logwrapper( 2069): executing /system/bin/wpa_supplicant failed: No such file or directory
粗略看了一下external/wpa_supplicant下的Android.mk发现里面
WPA_BUILD_SUPPLICANT := false 修改成true(它本来要满足一些条件才能变成true的,这里直接改了先。)
改了之后在上级目录执行mm指令
就产生了相关的system/bin/wpa_supplicant
将产生的bin文件和.so文件拷贝到文件系统中去。
15.再次测试遇到以下问题: Open file "/etc/Wireless/RT2870STA/RT2870STA.dat" failed!
将rt3070 源码Module文件夹下的固件RT2870STA.dat放置到Android文件系统下
system/etc/Wireless/RT2870STA目录下,没有的目录要自己建立。
16.再次测试遇到以下问题:Error changing group ownership of /data/misc/wifi/wpa_supplicant.conf
在wifi.c中找到
static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf";
destfd = open(SUPP_CONFIG_FILE, O_CREAT|O_WRONLY, 0660);
说明文件wpa_supplicant.conf是wifi.c中创建的,权限为system system。
但是wifi.c中又有这样的语句
if (chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0) {
LOGE("Error changing group ownership of %s to %d: %s",
SUPP_CONFIG_FILE, AID_WIFI, strerror(errno));
unlink(SUPP_CONFIG_FILE);
return -1;
}
意思要转变/data/misc/wifi/wpa_supplicant.conf这个文件组权限为wifi,明显在这是行不通的。
因为wifi.c本身的权限只有system system,除非wifi.c拥有root权限。
解决办法:
注释掉(chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0这段句话,不要在代码中改它的权限。
在这段代码前面加上
chmod(SUPP_CONFIG_FILE, 0777); 这样的话不管是谁都可以读取这个config文件。
17.提示Unable to open connection to supplicant on "/data/system/wpa_supplicant/sta": No suchfile or directory
原因打开的路径的不对,在wpa_supplicant.conf中设定的路径为
ctrl_interface=DIR=/data/misc/wifi/wpa_supplicant
但是在wifi.c中设定的static const char IFACE_DIR[]不正确,所以在建立socket时失败。
修改wifi.c中的两个宏
#define WIFI_TEST_INTERFACE "ra0"
static const char IFACE_DIR[] = "/data/misc/wifi/wpa_supplicant";
18.wifi_connect_to_supplicant函数无法执行成功,返回值为-1,打印相关信息发现函数体内
wpa_ctrl_attach(monitor_conn)无法正确执行。
分析wpa_ctrl_attach函数:
->wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, buf, &len, NULL);//socket的建立和地址绑定是在wpa_ctrl_open(ifname)中完成
->(send(ctrl->s, _cmd, _cmd_len, 0) < 0)//发送命令,这个命令发送后将由wpa_supplicant的守护进程
->res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);//select 等带回应(10s 后超时)
............................
wpa_supplicant 接收消息是在以下函数中完成的:
wpa_supplicant_ctrl_iface_receive 函数( ctrl_iface_unix.c )
->recvfrom(sock, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &from, &fromlen);//接收消息
->if (os_strcmp(buf, "ATTACH") == 0) //收到消息并判断
->wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)//执行对应的处理函数
->if (reply_len == 2)
->sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen);//返回OK给HAL层(wpa_ctrl_request)
问题出现了,明明这里发送OK,但是select函数并没有接收到,后打印sendto的异常代码,发现是
permission Deny,又是权限的问题。打印from,发现路径为data/misc/wifi/sockets
解决办法:
修改wpa_ctrl.c中的wpa_ctrl_open函数
chmod(ctrl->local.sun_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);//这里的local.sun_path就是路径data/misc/wifi/sockets
修改为
chmod(ctrl->local.sun_path, 0777);
19. D/wpa_supplicant( 2096): No suitable AP found.
没有搜索到的网络列表
修改config_file.c中:
wpa_config_read(const char *name)函数
chmod(name, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
修改为
chmod(name, 0777);
20.能够进行AP scan但是搜索到之后wifi睡眠,当你再次触摸屏幕的时候系统崩溃
原因:代码中没有实现相关的唤醒的函数,所以当你再次触摸屏幕的时候系统崩溃。
关闭wifi的睡眠功能:
在wifisettings里面按下menu键,然后点击advance选项,然后在弹出的对话框中选择
wifi_sleep_options,最后选择never(这样wifi的部分就不会睡眠了)
21. /s5pc100/android2.1/frameworks/base/wifi/java/android/net/wifi 路径
WifiStateTracker.java:353: mInterfaceName = SystemProperties.get("wifi.interface", "eth0");
修改为
WifiStateTracker.java:353: mInterfaceName = SystemProperties.get("wifi.interface", "ra0");
22.如何自动获得IP?使用dhcp
修改源码目录下external/dhcpcd下的android.mk文件
取消注释
26 include $(CLEAR_VARS)
27 LOCAL_MODULE := dhcpcd.conf
28 LOCAL_MODULE_TAGS := user
29 LOCAL_MODULE_CLASS := ETC
30 LOCAL_MODULE_PATH := $(etc_dir)
31 LOCAL_SRC_FILES := android.conf
32 include $(BUILD_PREBUILT)
然后重新编译mm
将编译产生的dhcpcd.conf放置到文件系统的目录system/etc/dhcpcd/dhcpcd.conf
确保init.rc中有如下的语句启动dhcp
mkdir /data/misc/dhcp 0770 dhcp dhcp
chown dhcp dhcp /data/misc/dhcp
service dhcpcd /system/bin/dhcpcd -f /system/etc/dhcpcd/dhcpcd.conf -d eth0
group system dhcp
disabled
oneshot
23.经过这些步骤,终于能够在开发板上利用WIFI模块上网了,android的logcat果然是个神器啊!