虽然Brillo m10-dev系统已经可以在RPi 2B/3B上正常运行了,同时RPi 3B的无线网卡也可以正常工用在AP/STA模式,但是在kernel log还是会有如下的警告信息:
[ 10.336324] cfg80211: Calling CRDA to update world regulatory domain [ 13.496321] cfg80211: Calling CRDA to update world regulatory domain [ 16.656316] cfg80211: Calling CRDA to update world regulatory domain [ 19.816311] cfg80211: Calling CRDA to update world regulatory domain [ 22.976321] cfg80211: Calling CRDA to update world regulatory domain [ 26.136317] cfg80211: Calling CRDA to update world regulatory domain [ 29.296426] cfg80211: Calling CRDA to update world regulatory domain [ 32.456312] cfg80211: Calling CRDA to update world regulatory domain [ 35.616304] cfg80211: Exceeded CRDA call max attempts. Not calling CRDA
看到了有80211字段, 很显然跟无线网卡有关,同时我们如果去查找代码的话,可以发现log出自于rpi-4.1.y/net/wireless/reg.c文件:
/*
* This lets us keep regulatory code which is updated on a regulatory
* basis in userspace.
*/
static int call_crda(const char *alpha2)
{
char country[12];
char *env[] = { country, NULL };
snprintf(country, sizeof(country), "COUNTRY=%c%c",
alpha2[0], alpha2[1]);
/* query internal regulatory database (if it exists) */
reg_regdb_query(alpha2);
if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n");
return -EINVAL;
}
if (!is_world_regdom((char *) alpha2))
pr_info("Calling CRDA for country: %c%c\n",
alpha2[0], alpha2[1]);
else
pr_info("Calling CRDA to update world regulatory domain\n");
return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env);
}
从这里的comments我们可以知道,我们需要在userspace中更新regulatory domain,也就意味着我们需要一个应用程序去更新regulator domain。
而CRDA又是什么东西呢?从https://wireless.wiki.kernel.org/en/developers/regulatory/crda我们知道它的全称为Central Regulator Domain Agent, 就是用来更新regulatory domain的,在kernel启动或者是系统运行时,kernel会发送相应的uevent通知userspace去更新regulator domain,相关的UEVENT如下:
change@/devices/platform/regulatory.0 ACTION=change DEVPATH=/devices/platform/regulatory.0 SUBSYSTEM=platform COUNTRY=00 MODALIAS=platform:regulatory SEQNUM=1095
NOTE:在执行iw reg set命令的时候,也会收到相关的UEVENT信息:
$ iw reg set US
对于userspace应用来说,在Raspbian或者Ubuntu等其他linux系统来说,udev就会接收到相关的UEVENT信息,然后执行相应的命令去更新,也让你会发现有这相样的udev rules:
KERNEL=="regulatory*", ACTION=="change", SUBSYSTEM=="platform", RUN+="/sbin/crda"
通过/sbin/crda去更新regulatory domain。在Ubuntu 14.04系统下,可以通过如下命令下载crda的代码:
$ apt-get source crda
Reading package lists... Done
Building dependency tree
Reading state information... Done
NOTICE: 'crda' packaging is maintained in the 'Git' version control system at:
git://git.debian.org/kernel/crda.git
Need to get 29.5 kB of source archives.
Get:1 http://ubuntu.cn99.com/ubuntu/ trusty/main crda 1.1.2-1ubuntu2 (dsc) [2,068 B]
Get:2 http://ubuntu.cn99.com/ubuntu/ trusty/main crda 1.1.2-1ubuntu2 (tar) [21.8 kB]
Get:3 http://ubuntu.cn99.com/ubuntu/ trusty/main crda 1.1.2-1ubuntu2 (diff) [5,703 B]
Fetched 29.5 kB in 1s (17.0 kB/s)
gpgv: Signature made Mon 01 Oct 2012 03:57:22 PM EDT using RSA key ID 7D86500B
gpgv: Can't check signature: public key not found
dpkg-source: warning: failed to verify signature on ./crda_1.1.2-1ubuntu2.dsc
dpkg-source: info: extracting crda in crda-1.1.2
dpkg-source: info: unpacking crda_1.1.2.orig.tar.bz2
dpkg-source: info: unpacking crda_1.1.2-1ubuntu2.debian.tar.gz
dpkg-source: info: applying do_not_embed_pubkeys.patch
dpkg-source: info: applying crda_add-nested-support-for-libnl-3.2.patch
通过查看crda的代码,我们知道除了需要/sbin/crda文件之外,我们还需要如下这几个文件:
- /lib/crda/regulatory.bin
- /lib/crda/pubkeys/benh@debian.org.key.pub.pem
- /lib/crda/pubkeys/linville.key.pub.pem
NOTE: pubkeys只是用来检查regulatory.bin是否合法。
当然crda还会去读取环境变量:COUNTRY,并根据当前的环境变量更新regulatory domain。
在Brillo系统中,没有crda,也没有regulatory.bin,为什么DragonBoard 410c的kernel log却没有这样的log呢?原因在于regulatory domain的信息除了可以由userspace提供外,还可以采用kernel built-in的形式,只要你在配置kernel的时候,enable CONFIG_CFG80211_INTERNAL_REGDB,同时你还需要更新一下kernel代码中的net/wireless/db.txt文件:
# # This file is a placeholder to prevent accidental build breakage if someone # enables CONFIG_CFG80211_INTERNAL_REGDB. Almost no one actually needs to # enable that build option. # # You should be using CRDA instead. It is even better if you use the CRDA # package provided by your distribution, since they will probably keep it # up-to-date on your behalf. # # If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will # need to replace this file with one containing appropriately formatted # regulatory rules that cover the regulatory domains you will be using. Your # best option is to extract the db.txt file from the wireless-regdb git # repository: # # git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git #
如果你去查看DragonBoard 410c kernel相关的代码的话,你可以发现这个文件已经包含了regulatory domain的相关信息,如果去再去查看提记录的话,你会发出这个文件已经被修改多次,这也说明,regulatory domain还是通过userspace来更新比较好。
在brillo-m10-dev-rpi3b中也实现类似这样的更新机制:
存在一个crdad service, 用于monitor UEVENT, 当收到regulatory domain更新的UEVENT, 设置COUNTERY环境变量后,执行/system/bin/crda读取/vendor/lib/crda/regulatory.bin去更新regulatory domain。
1. 相关文件结构
/local/brillo-m10-dev-rpi3b +-- device `-- hzak `-- rpi3b +-- base_product | `-- rpi3b.mk +-- bsp | +-- crdad | `-- sepolicy | +-- crdad.te | `-- file_contexts `-- fs_config `-- android_filesystem_config.h
NOTE:
a. crda的代码来自于git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/crda.git
b. regulatory.bin及相应的pubkeys来自于NOOBS_v1.9.0.zip文件
c. 需要定义crdad domain, 不然在start crdad service时,会有如下log:
# start crdad [ 109.723461] init: Service crdad does not have a SELinux domain defined.
d. 最终生成的文件system/bin/crda可能需要有NET_CAP_ADMIN与NET_CAP_RAW权限,不然在写入regulatory时会失败。需要修改device/hzak/rpi3b/fs_config/android_filesystem_config.h文件。
2. 最终生成的文件结构
/system +-- bin | +-- crda | `-- crdad +-- etc | `-- init | `-- crdad.rc `-- vendor `-- lib `-- crda +-- pubkeys | +-- benh@debian.org.key.pub.pem | `-- linville.key.pub.pem `-- regulatory.bin
3. 由于在kernel中开启了CONFIG_CFG80211_REG_DEBUG, 所以在kernel中会出现如下log:
[ 7.145061] cfg80211: Calling CRDA to update world regulatory domain [ 7.215262] cfg80211: World regulatory domain updated: [ 7.220425] cfg80211: DFS Master region: unset [ 7.224779] cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time) [ 7.234573] cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz), (N/A, 2000 mBm), (N/A) [ 7.242615] cfg80211: (2457000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm), (N/A) [ 7.250672] cfg80211: (2474000 KHz - 2494000 KHz @ 20000 KHz), (N/A, 2000 mBm), (N/A) [ 7.258745] cfg80211: (5170000 KHz - 5250000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2000 mBm), (N/A) [ 7.268289] cfg80211: (5250000 KHz - 5330000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2000 mBm), (0 s) [ 7.277838] cfg80211: (5490000 KHz - 5730000 KHz @ 160000 KHz), (N/A, 2000 mBm), (0 s) [ 7.285977] cfg80211: (5735000 KHz - 5835000 KHz @ 80000 KHz), (N/A, 2000 mBm), (N/A) [ 7.293983] cfg80211: (57240000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 0 mBm), (N/A)
而如果通过iw命令手动更新regulatory domain, 也会有相应的log:
# iw reg set CN
[ 1201.998057] cfg80211: Calling CRDA for country: CN
# [ 1202.044542] cfg80211: Regulatory domain changed to country: CN
[ 1202.050432] cfg80211: DFS Master region: FCC
[ 1202.054612] cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)
[ 1202.064375] cfg80211: (2402000 KHz - 2482000 KHz @ 40000 KHz), (N/A, 2000 mBm), (N/A)
[ 1202.072401] cfg80211: (5170000 KHz - 5250000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2300 mBm), (N/A)
[ 1202.081898] cfg80211: (5250000 KHz - 5330000 KHz @ 80000 KHz, 160000 KHz AUTO), (N/A, 2300 mBm), (0 s)
[ 1202.091390] cfg80211: (5735000 KHz - 5835000 KHz @ 80000 KHz), (N/A, 3000 mBm), (N/A)
[ 1202.099407] cfg80211: (57240000 KHz - 59400000 KHz @ 2160000 KHz), (N/A, 2800 mBm), (N/A)
[ 1202.107772] cfg80211: (59400000 KHz - 63720000 KHz @ 2160000 KHz), (N/A, 4400 mBm), (N/A)
[ 1202.116136] cfg80211: (63720000 KHz - 65880000 KHz @ 2160000 KHz), (N/A, 2800 mBm), (N/A)
相关的代码可以从这里下载:2016_04_15_brillo-m10-dev-rpi3b-v1.1.tar.gz
- 相关的参考文档
- https://wireless.wiki.kernel.org/en/developers/regulatory/crda
你好,请问怎么开启CONFIG_CFG80211_INTERNAL_REGDB,它是内核的一个模块么?如果是,那么在make menuconfig里面的位置是什么,谢谢
你可以参考这两篇文档:
1. http://linuxwireless.org/en/developers/Regulatory/
2. http://linuxwireless.org/en/developers/Regulatory/CRDA/#CONFIG_CFG80211_INTERNAL_REGDB
在这个文件中:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/net/wireless/Kconfig#n142
1
1
1