蟹さんのWiFiコード

蟹さんのWiFiチップには以下のようなものがある。

|製品|Version|
|:--|:--|
|8188C|0x1000|
|8192C|0x1001|
|8192D|0x1002|
|8188E|0x1003|
|8812E|0x1004|
|8192E|0x1005|
|8881A|0x1006|
|8814A|0x1007|
|8723B|0x1008|

auの蟹さんは8196C+8192DRでdocomoの蟹さんは8196E+8196CEです。

これらのチップは8051が入ったチップでfirmwareのダウンロードが必要となる。

Host Controle Interface(HCI)はUSB,PCIe,SDIOがある。RL8196CなどのSOCとはPCIeで接続されている。

|SOC|ARCHITECTURE|
|:--|:--|
|RTL8196C|RLX4181|
|RTL8196D|RLX5281|
|RTL8196E|RLX4181|
|RTL8197D|RLX5281|
|RTL8197F|MIPS 24K|
|RTL8198|RLX5281|
|RTL8881AM|RLX5281|

GPLで公開されているコードはLinux専用のものとそれをECOSなどにポートしたものがある。ECOSにポートしたもののソースファイルは以下のようになっている。

path: ecos-3.0/packages/devs/eth/rltk/819x/wlan/v3_3/src/rtl8192cd

|ファイル名|ECOS|内容|
|:--|:--|:--|
|1x_kmsm_aes.c|○|AES|
|1x_kmsm_hmac.c|○|HMAC|
|1x_md5c.c||MD5|
|1x_rc4.c||RC4|
|8188e_hw.c|○|RTL8188E|
|8192cd_11h.c|○|~~Software TKIP encryption/descryption routines~~|
|8192cd_a4_sta.c||a4 sta functions|
|8192cd_aes.c|○|Software AES encryption/descryption routines|
|8192cd_br_ext.c|○|bridge extention functions|
|8192cd_cfg80211.c|||
|8192cd_comapi.c||API-compatible handling routines|
|8192cd_dfs.c|○|Handling routines for DFS (Dynamic Frequency Selection) functions|
|8192cd_dfs_det.c||Handling routines for DFS DET functions|
|8192cd_dmem.c|○|D-MEM supporting module for RTL8190 802.11N wireless NIC on RTL865x platform|
|8192cd_eeprom.c||Routines to read and write eeprom|
|8192cd_host.c|○|Routines to handle host CPU related functions|
|8192cd_hw.c|○|Routines to access hardware|
|8192cd_ioctl.c|○|io-control handling routines|
|8192cd_led.c|○|Handling routines for LED lightening functions|
|8192cd_mib.c|○|SNMP MIB module|
|8192cd_mp.c|○|MP routines|
|8192cd_net80211.c||API-compatible handling routines|
|8192cd_osdep.c|○|Routines to handle OS dependent jobs and interfaces|
|8192cd_p2p.c|○|P2P  support ; WIFI-DRIECT|
|8192cd_proc.c|○|Handle routines for proc file system|
|8192cd_psk.c|○|WPA PSK handling routines|
|8192cd_psk_hapd.c||WPA PSK handling routines|
|8192cd_rx.c|○|RX handle routines|
|8192cd_security.c|○|Handle routines to communicate with AUTH daemon (802.1x authenticator)|
|8192cd_sme.c|○|Handling routines for 802.11 SME (Station Management Entity)|
|8192cd_sta_control.c||a4 sta functions|
|8192cd_tkip.c|○|Software TKIP encryption/descryption routines|
|8192cd_tx.c|○|TX handle routines|
|8192cd_util.c|○|Utility routines|
|8192d_hw.c||RTL8192D|
|8812_hw.c||RTL8812|
|8812_vht_gen.c|||
|Beamforming.c|||
|EdcaTurboCheck.c|||
|Hal8188EPwrSeq.c|○|This file includes all kinds of Power Action event for RTL8188E and corresponding hardware configurtions which are released from HW SD.|
|Hal8192CDMOutSrc.c|○|This file is for 92CE/92CU outsource dynamic mechanism for partner.|
|Hal8723BPwrSeq.c||This file includes all kinds of Power Action event for RTL8723B and corresponding hardware configurtions which are released from HW SD.|
|Hal8812PwrSeq.c||This file includes all kinds of Power Action event for RTL8812 and corresponding hardware configurtions which are released from HW SD.|
|Hal8821APwrSeq.c||This file includes all kinds of Power Action event for RTL8188E and corresponding hardware configurtions which are released from HW SD.|
|HalDMOutSrc.c|○|This file is for common outsource dynamic mechanism for partner.|
|HalPwrSeqCmd.c|○|Implement HW Power sequence configuration CMD handling routine for Realtek devices.|
|RateAdaptive.c|○|Implement Rate Adaptive functions for common operations.|
|romeperf.c||Performance Profiling routines|
|rtl8672_port.c|||
|rtw_android.c|||
|sha256.c||SHA-256 hash implementation and interface functions|

firmwareは./data_92d/rtl8192dfw_n.binなどになり、このファイルをbin2c.plというスクリプトでテキストにしてコード中に取り込むようです。

ドライバーでのWPAのサポート(INCLUDE_WPA_PSK)があるので、8192cd_tx.cと8192cd_rx.cでカーネルのEthernetレイヤーとつながっている。

AESの暗号化の処理は8192cd_aes.cにあるaesccmp_encrypt,aesccmp_decryptで行っている模様。

3つのバージョンがディレクトリを分けて入っていた。どれが使われているかはecos.dbで指定されている。

Linuxの高速パケット処理(FASTPATH)の対応コードもある。

通常のWIFIチップはAP,STATIONの両方のモードで使える。ドライバーは別々になっているか同一のケースがある。

WiFiのドライバーはそれ単体では完結しておらずユーザランドのプログラムとnl80211やhostapdのプロトコルで接続され、処理を行っている。

クライアント接続(STATION)での処理はプリシェアードキーの確認処理(PSK)、送信データの暗号化、受信データの復号化になる。また送受信の電波の設定も必要になる。

SSIDの一覧はビーコンパケットを集めるとできるので、ドライバーレイヤーより高い処理になるのかもしれない。

ECOSのIPスタックはFreeBSDのコードを使ってるようだ。

蟹さんはRTL8196などのLexra(MIPS 1)のプロダクトと後期にMIPS 24Kのプロダクトも出していたのでソースツリーにはMIPS用(msdk)とLexra用(rsdk)が含まれていた。

LinuxやECOS以外にも\_\_DRAYTEK\_OS\_\_や\_\_OSK\_\_でもビルドされているように見えるが、何を意味しているかや実際動くのかは不明。

これ以外もWlanHALなどのディレクトリにファイルがある。

RTL8195Aの定義もある。RTL8195AはWiFi内蔵のSOCでmbedのサポートもあるARMアーキテクチャのamebaと言われるチップです。mbed環境はおそらくFreeRTOSなのではないかと思われる。

ECOS対応はドライバーコードを修正してLINUXとの差を以下のコードで調整しているようです。

ecos-3.0/packages/devs/eth/rltk/819x/wlan/v3_3/src/if_819x_wlan.c
ecos-3.0/packages/devs/eth/rltk/819x/wlan/v3_3/src/8192cd_ecos.c
ecos-3.0/packages/devs/eth/rltk/819x/wrapper/v3_0/src/*

とりあえずgithubにあったソースをビルド試してみました。ccなどはLinux用のtoolchainをFreeBSDのLinuxエミュレーションで使い、make,tclshはpkgでインストールした/usr/local/bin/にディレクトリを掘って、シンボリックリンクしてPATHを通してbashやperlのスクリプトはパスを書き換えて、あとこまごまと修正してビルド通りました。yuicompresserを使っていたのでopenjdk8をインストールしました。

https://github.com/yamori813/ecos_http

```
msdk-elf-gcc -Wall -Wpointer-arith -Wstrict-prototypes -Wundef  -Wno-write-strings -EL -mips32 -mips32r2 -msoft-float -g -Os -ffunction-sections -fdata-sections  -fno-exceptions -G0 -minterlink-mips16 -D__ECOS -fno-pic -mno-abicalls -DEMBEDDED -I./ -I/usr/home/hiroki/kani/ecos_http/rtk/ecos-work/97f-8812br-16M-gw_install/include -DCOMPRESSED_KERNEL -G 0 -D__LITTLE_ENDIAN__ -DCONFIG_RTL_8197F -include /usr/home/hiroki/kani/ecos_http/rtk/ecos-work/97f-8812br-16M-gw_install/include/pkgconf/system.h -include /usr/home/hiroki/kani/ecos_http/rtk/ecos-work/97f-8812br-16M-gw_install/include/cyg/hal/bspcpu.h -DLZMA_COMPRESS   -c -o LzmaDecode.o LzmaDecode.c
msdk-elf-gcc -EL -msoft-float -fno-pic -mno-abicalls -Os -fomit-frame-pointer -c vmlinux_img.c -o vmlinux_img.o
msdk-elf-objcopy --add-section .vmlinux=vmlinux_img.gz vmlinux_img.o
msdk-elf-ld -static -nostdlib -EL -G 0 -T ld.script -o memload-partial start.o hfload.o read_memory.o vsprintf.o prom_printf.o string.o ctype.o misc.o cache-mips32.o LzmaDecode.o   vmlinux_img.o
msdk-elf-nm memload-partial | grep -v '\(compiled\)\|\(\.o$\)\|\( [aU] \)\|\(\.\.ng$\)\|\(LASH[RL]DI\)' | sort > system.map
cp memload-partial memload-full
msdk-elf-objcopy -Obinary memload-full nfjrom
./cvimg signature nfjrom ecos.bin 0x80500000 20000 cs6c

Generate image successfully, length=1760258, checksum=0xaac4

==============================================
Summary ==>
Image loading  addr          :0x80500000
Image decompress end addr    :0x80469d84
Available size               :0x0009627c
make[4]: Leaving directory '/usr/home/hiroki/kani/ecos_http/rtk/ecos-work/AP/rtkload'
make[3]: Leaving directory '/usr/home/hiroki/kani/ecos_http/rtk/ecos-work/AP'
./AP/tools/mgbin -c -o fw-97f-8812br-16M-gw.bin  ./AP/rtkload/ecos.bin

Merge KERNEL => fw-97f-8812br-16M-gw.bin ok, size=1760274.
chmod +x trx
./trx -f 0x0002 -o bcmhead_upgrade_file.bin fw-97f-8812br-16M-gw.bin
sed 's/HDR0/RTK0/' bcmhead_upgrade_file.bin > RTK0_MAGIC_upgradefile.bin
make[2]: Leaving directory '/usr/home/hiroki/kani/ecos_http/rtk/ecos-work'
make[1]: Leaving directory '/usr/home/hiroki/kani/ecos_http/rtk/ecos-work'
```

上記のツリーは設定してある、8197f(mips 24k) + 8812でしかコンパイル通ららないようです。

ECOS用のソースの関数は以下の通りです。

```c:if_819x_wlan.c
static cyg_uint32 rltk819x_wlan_isr(cyg_vector_t vector, cyg_addrword_t data)
static void rltk819x_wlan_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
static bool rltk819x_wlan_init(struct cyg_netdevtab_entry *tab)
static bool rltk819x_wlan_wds_init(struct cyg_netdevtab_entry *tab)
static bool rltk819x_wlan_mesh_init(struct cyg_netdevtab_entry *tab)
static bool rltk819x_wlan_vap_init(struct cyg_netdevtab_entry *tab)
static bool rltk819x_wlan_pwlan_init(struct cyg_netdevtab_entry *tab)
static bool rltk819x_wlan_vxd_init(struct cyg_netdevtab_entry *tab)
static void rltk819x_wlan_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
static void rltk819x_wlan_stop(struct eth_drv_sc *sc)
void assign_diff_AC(unsigned char* pMib, unsigned char* pVal)
static int rltk819x_wlan_control(struct eth_drv_sc *sc, unsigned long key, void *data,
static int rltk819x_wlan_can_send(struct eth_drv_sc *sc)
static void rltk819x_wlan_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
static void rltk819x_wlan_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,
static void rltk819x_wlan_deliver(struct eth_drv_sc *sc)
static void rltk819x_wlan_poll(struct eth_drv_sc *sc)
static int rltk819x_wlan_int_vector(struct eth_drv_sc *sc)
int rltk819x_send_wlan(struct eth_drv_sc *sc, unsigned char *data, int size)
int rltk819x_send_wlan_mesh(struct eth_drv_sc *sc, unsigned char *data, int size)
```

```c:8192cd_ecos.c
void set_ecos_pr_fun(pr_fun *pr)
void *rltk_wlan_init(int wlan_idx)
void *rltk_wlan_vxd_init(int wlan_idx)
void *rltk_wlan_vap_init(int wlan_idx, int vap_idx)
void interrupt_dsr(struct net_device *dev)
int can_xmit(struct net_device *dev)
struct sk_buff *copy_skb(struct sk_buff *skb)
struct net_device *rltk_get_wds_net_device(int wlan_idx, int wds_num)
struct net_device *rltk_get_mesh_net_device(int wlan_idx, int mesh_num)
void passthru_wlan_show()
void passthru_wlan_write()
struct net_device *rltk_get_pwlan_net_device(int dev_num, int device_num)
void rtl8192cd_wlan_cmd_dispatch(char *name, int argc, char *argv[])
int encode_ssid_str(const char *source,char *dest )
void silence_stainfo(void)
```

```c:wrapper.c
static void init_local_pool(void)
void *alloc_local(int size)
int mac_hash(unsigned char *da)
struct net_device * getDevByMac(unsigned char * mac)
void dump_fst_fdb()
void addfdbentry(unsigned char *mac,struct net_device *dev)
int rtl_CheckPassthruFrame(unsigned char* data)
static inline struct ethhdr *eth_hdr(const struct mbuf *m)
void enable_dnstrap(int en)
int get_interface_ip(char *interface_name)
inline int br_dns_packet_recap(struct mbuf *m)
inline int br_dns_filter_enter(struct mbuf *m)
int is_dns_packet(struct sk_buff *skb)
int is_dns_packet(struct sk_buff *skb)
void	wrapper_up(struct sk_buff *skb)
void	wrapper_que_up(struct sk_buff *skb, struct net_device *root_dev)
void wrapper_que_retrieve(struct net_device *dev)
int wrapper_que_len(struct net_device *dev)
void wrapper_free_tx_queue(struct net_device *dev)
void wrapper_deliver(Rltk819x_t *info, struct eth_drv_sg *sg_list, int sg_len)
struct net_device *alloc_etherdev(int sizeof_priv)
void wrapper_init(void)
void wrapper_binding(Rltk819x_t *info, void *dev)
int wrapper_isr(Rltk819x_t *info)
void wrapper_dsr(Rltk819x_t *info)
void wrapper_free_tx(struct net_device *dev, unsigned long key)
void wrapper_que_free_tx_pkt(struct net_device *root_dev, struct sk_buff *skb)
void wrapper_start(Rltk819x_t *info)
void wrapper_stop(Rltk819x_t *info)
int wrapper_can_send(Rltk819x_t *info)
void wrapper_tx(Rltk819x_t *info, struct eth_drv_sg *sg_list, int sg_len,
static struct net_device *wrapper_find_netdev(char *name)
struct net_device_stats *wrapper_get_stats(char *ifname)
void shutdown_netdev(void) 
int rtk_atoi(char *s)
void suspend_check_cmd_dispatch(int argc, char *argv[])
static void suspend_check_timer_fn(void *arg)
void suspend_check_init(void)
int rtl_isWanDevDecideByIfp(struct ifnet *ifp)
struct net_device * rtl_getDevByIfp(struct ifnet *ifp)
struct net_device * rtl_getDevByName(char *name)
```

rltk819x_wlan_init() - if_819x_wlan.c ->
rltk_wlan_init() - 8192cd_ecos.c ->
rtl8192cd_init_one() - 8192cd_osdep.c


rltk819x_wlan_start() - if_819x_wlan.c ->
wrapper_start() - wrapper.c ->
(((struct net_device *)info->dev)->open)((struct net_device *)info->dev);
rtl8192cd_open() - 8192cd_osdep.c ->
rtl8192cd_init_hw_PCI() - 8192cd_hw.c ->
Load_92D_Firmware() - 8192d_hw.c


設定はrltk819x_wlan_control()の中では構造体などに値を設定しているだけのように見えます。

rltk819x_wlan_control() - if_819x_wlan.c

送信はwrapper_tx()でskbに変換しているようです。

rltk819x_wlan_send() - if_819x_wlan.c ->
wrapper_tx() - wrapper.c ->
(dev->hard_start_xmit)(skb, dev);
rtl8192cd_start_xmit() - 8192cd_tx.c ->
\_\_rtl8192cd_start_xmit() - 8192cd_tx.c



受信は割り込みで処理されて一旦eCosに渡ってから、rltk819x_wlan_recv()が呼ばれるようです。wrapper_deliver()でskbからmbufに変換しているようです。RTLPKG_DEVS_ETH_RLTK_819X_RX_ZERO_COPYが定義されているとsbkをそのままmbufにしますが、定義されてない場合はmemcpy()するようです。

rltk819x_wlan_recv() - if_819x_wlan.c ->
wrapper_deliver() - wrapper.c ->


割り込み処理は以下のようになっています。

rltk819x_wlan_isr() - if_819x_wlan.c ->
wrapper_isr() - wrapper.c ->
(((struct net_device *)info->dev)->isr)((struct net_device *)info->dev)
rtl8192cd_interrupt() - rtl8192cd/8192cd_osdep.c ->
\_\_rtl8192cd_interrupt() - rtl8192cd/8192cd_osdep.c ->
rtl8192cd_rx_isr() - rtl8192cd/8192cd_rx.c

割り込み処理は二つに分かれていてisrルーチンがCYG_ISR_CALL_DSRを返すと、dsrルーチンが後で呼ばれ、CYG_ISR_HANDLEDだと呼ばれないようです。

毎度突っ込みどころ満載なので、気がついたところを書いておきたいと思います。

こんなコードがあります。

```c:8192cd_rx.c
#ifdef __ECOS
        if (SUCCESS==rtl_isWlanPassthruFrame(pskb->data))
#else
        if (SUCCESS==rtl_isPassthruFrame(pskb->data))
#endif
```

実態はここにあります。

```c:8192cd_util.c
#ifdef __ECOS
INT32 rtl_isWlanPassthruFrame(UINT8 *data)
#else
INT32 rtl_isPassthruFrame(UINT8 *data)
#endif
{
```

ECOSへの移植なのになぜ関数名を変える必要があるのでしょうか？

```c:8192cd_psk.c
#ifdef __ECOS
int ecos_send_wlan(struct net_device *dev, unsigned char *data, int size)
{
省略
}
#ifdef __ECOS
int ecos_send_wlan_mesh(struct net_device *dev, unsigned char *data, int size)
{
省略
}
#endif
#endif
```

二つ目のifdefは意味ありません。

```c:8192cd_11h.c
/*
 *  Software TKIP encryption/descryption routines
 *
 *  $Id: 8192cd_tkip.c,v 1.4.4.2 2010/09/30 05:27:28 button Exp $
 ```

ファイルをコピーして作ってコメントがそのままになっています。

```c:8192cd_hw.c
#ifdef CONFIG_PHY_WLAN_EAT_40MHZ
                ClkSel = XTAL_CLK_SEL_40M;
#else
#ifdef CONFIG_WLAN_HAL_8881A
                if(GET_CHIP_VER(priv) == VERSION_8881A)
                        ClkSel = XTAL_CLK_SEL_40M;
                else
#endif
                ClkSel = XTAL_CLK_SEL_25M;
#endif //CONFIG_PHY_EAT_40MHZ
```

コメントのマクロが間違っています。どっちもあるのでどっちが正しいかも分かりません。

```
#ifdef INCLUDE_WPA_PSK
```

INCLUDEはなんか違うような気がします。マクロは良く分からない略称がいろいろあります。

```
#if 0
```

487行もあります。

8192cd_psk_hapd.cは8192cd_psk.cがあまりにぐちゃぐちゃになったので、もともとのファイルを別に作ったのではないかと思われます。

結構ぐちゃぐちゃです。DKM

FreeBSDのこれらのデバイスのサポートコードはdev/rtwnになります。

参考

いろいろよいWIFIの技術説明がありました。

https://www.infraexpert.com/study/wireless.html

https://www.silex.jp/blog/wireless/lan/

https://licensecounter.jp/engineer-voice/blog/articles/20190319__1.html