linux内核3.8以后加入了在内核态加载firmware的支持,因此systemd在v217以后去除了用户太加载firmware的支持
而orangepi到现在(2016年1月6日)仍然使用的是3.4.39内核,该内核不支持内核态加载firmware。而wily(ubuntu 15.10)使用的systemd是v225,不支持用户态加载firmware,因此在orangepi+wily的情况下,firmware是无法加载的。
要解决这个问题,我们需要使用udev的rule文件调用外部程序加载firmware
我写了这样一个程序来加载firmware,代码地址为:https://github.com/freason/orangepi_wily_firmware_loader.git
使用方法如下:
1. 修改: “/lib/udev/rules.d/50-firmware.rules”这个文件,把
SUBSYSTEM=="firmware", ACTION=="add", ATTR{loading}="-1"
这一行换成:
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware $env{FIRMWARE} /sys/$env{DEVPATH}"
2. 用arm-gcc编译firmware.c生成名为firmware的可执行文件,并把这个文件拷贝到orangepi的/lib/udev目录下
这里有两种方式,一种是直接在orangepi下编译,另外一种是使用arm-linux-gnueabi-gcc进行交叉编译。我使用的第二种方式,github上提供了我编译的版本
3. 拷贝firmware到orangepi的/lib/firmware下,orangepi wily没有提供firmware所以我们必须手动从其他地方拷贝firmware过来,我是从pc的UBUNTU上拷贝过来的
firmware.c工作的原理:
插入usb wifi后,rtl8192cu的驱动会请求firmware,这时内核会创建两个文件loading和data。其中loading为加载的状态,1为正在加载,0为加载完成,-1为错误,我们向loading文件里写入这三个字符串即可通知内核相应的消息。data为数据缓冲,我们将firmware数据写入该文件,内核会从这个文件中读取firmware数据。
注意:写loading这个文件不能使用bash中的echo+重定向,我试过,没成功。我没有仔细研读fopen的代码,但firmware.c中打开文件时使用的模式为"we",其中e表示O_CLOEXEC,参见http://linux.die.net/man/3/fopen,不知bash下有什么命令能起到这个模式的作用。