瀏覽代碼

first commit

flyingcys 2 年之前
當前提交
6e479190cc
共有 100 個文件被更改,包括 15429 次插入0 次删除
  1. 201 0
      LICENSE
  2. 24 0
      README.md
  3. 207 0
      SConscript
  4. 10 0
      drv_wifi/SConscript
  5. 778 0
      drv_wifi/bl808_sec_eng.h
  6. 98 0
      drv_wifi/bl808_wifi.c
  7. 23 0
      drv_wifi/bl808_wifi.h
  8. 487 0
      drv_wifi/bl_pm.c
  9. 111 0
      drv_wifi/bl_pm.h
  10. 799 0
      drv_wifi/bl_sec.c
  11. 83 0
      drv_wifi/bl_sec.h
  12. 273 0
      drv_wifi/bl_wifi.c
  13. 52 0
      drv_wifi/bl_wifi.h
  14. 238 0
      drv_wifi/hosal_adc.h
  15. 152 0
      drv_wifi/hosal_dma.h
  16. 558 0
      drv_wifi/sec_eng_reg.h
  17. 21 0
      fs/vfs/include/device/vfs_adc.h
  18. 26 0
      fs/vfs/include/device/vfs_device.h
  19. 75 0
      fs/vfs/include/device/vfs_gpio.h
  20. 64 0
      fs/vfs/include/device/vfs_i2c.h
  21. 57 0
      fs/vfs/include/device/vfs_pwm.h
  22. 64 0
      fs/vfs/include/device/vfs_rtc.h
  23. 108 0
      fs/vfs/include/device/vfs_spi.h
  24. 106 0
      fs/vfs/include/device/vfs_uart.h
  25. 54 0
      fs/vfs/include/device/vfs_wdg.h
  26. 20 0
      fs/vfs/include/fs/vfs_romfs.h
  27. 115 0
      fs/vfs/include/hal/soc/adc.h
  28. 73 0
      fs/vfs/include/hal/soc/dac.h
  29. 157 0
      fs/vfs/include/hal/soc/flash.h
  30. 158 0
      fs/vfs/include/hal/soc/gpio.h
  31. 140 0
      fs/vfs/include/hal/soc/i2c.h
  32. 54 0
      fs/vfs/include/hal/soc/interpt.h
  33. 105 0
      fs/vfs/include/hal/soc/nand.h
  34. 83 0
      fs/vfs/include/hal/soc/nor.h
  35. 68 0
      fs/vfs/include/hal/soc/pwm.h
  36. 93 0
      fs/vfs/include/hal/soc/qspi.h
  37. 26 0
      fs/vfs/include/hal/soc/rng.h
  38. 74 0
      fs/vfs/include/hal/soc/rtc.h
  39. 118 0
      fs/vfs/include/hal/soc/sd.h
  40. 32 0
      fs/vfs/include/hal/soc/soc.h
  41. 87 0
      fs/vfs/include/hal/soc/spi.h
  42. 63 0
      fs/vfs/include/hal/soc/timer.h
  43. 229 0
      fs/vfs/include/hal/soc/uart.h
  44. 108 0
      fs/vfs/include/hal/soc/usb_hcd.h
  45. 44 0
      fs/vfs/include/hal/soc/wdg.h
  46. 270 0
      fs/vfs/include/vfs.h
  47. 34 0
      fs/vfs/include/vfs_conf.h
  48. 27 0
      fs/vfs/include/vfs_dir.h
  49. 30 0
      fs/vfs/include/vfs_err.h
  50. 28 0
      fs/vfs/include/vfs_file.h
  51. 124 0
      fs/vfs/include/vfs_inode.h
  52. 25 0
      fs/vfs/include/vfs_register.h
  53. 86 0
      fs/vfs/posix/dirent.c
  54. 86 0
      fs/vfs/posix/include/dirent.h
  55. 30 0
      fs/vfs/posix/include/sys/prctl.h
  56. 47 0
      fs/vfs/posix/prctl.c
  57. 869 0
      fs/vfs/src/vfs.c
  58. 157 0
      fs/vfs/src/vfs_file.c
  59. 242 0
      fs/vfs/src/vfs_inode.c
  60. 126 0
      fs/vfs/src/vfs_register.c
  61. 579 0
      network/wifi/include/bl60x_fw_api.h
  62. 70 0
      network/wifi/include/bl_phy_api.h
  63. 0 0
      network/wifi/include/rd.h
  64. 257 0
      network/wifi/include/supplicant_api.h
  65. 二進制
      network/wifi/lib/libwifi.a
  66. 10 0
      network/wifi/modules/bugkiller/inc/bugkiller_fw.h
  67. 37 0
      network/wifi_bt_coex/include/wifi_bt_coex.h
  68. 45 0
      network/wifi_bt_coex/src/wifi_bt_coex.c
  69. 78 0
      network/wifi_bt_coex/src/wifi_bt_coex_cli.c
  70. 24 0
      network/wifi_bt_coex/src/wifi_bt_coex_ctx.c
  71. 7 0
      network/wifi_bt_coex/src/wifi_bt_coex_ctx.h
  72. 12 0
      network/wifi_bt_coex/src/wifi_bt_coex_impl.h
  73. 166 0
      network/wifi_bt_coex/src/wifi_bt_coex_impl_bl602.c
  74. 184 0
      network/wifi_bt_coex/src/wifi_bt_coex_impl_bl606p.c
  75. 184 0
      network/wifi_bt_coex/src/wifi_bt_coex_impl_bl808.c
  76. 250 0
      network/wifi_hosal/include/wifi_hosal.h
  77. 70 0
      network/wifi_hosal/port/wifi_hosal_bl602.c
  78. 63 0
      network/wifi_hosal/port/wifi_hosal_bl606p.c
  79. 63 0
      network/wifi_hosal/port/wifi_hosal_bl808.c
  80. 247 0
      network/wifi_hosal/wifi_hosal.c
  81. 272 0
      network/wifi_manager/bl60x_wifi_driver/bl_cmds.c
  82. 75 0
      network/wifi_manager/bl60x_wifi_driver/bl_cmds.h
  83. 294 0
      network/wifi_manager/bl60x_wifi_driver/bl_defs.h
  84. 89 0
      network/wifi_manager/bl60x_wifi_driver/bl_irqs.c
  85. 23 0
      network/wifi_manager/bl60x_wifi_driver/bl_irqs.h
  86. 618 0
      network/wifi_manager/bl60x_wifi_driver/bl_main.c
  87. 197 0
      network/wifi_manager/bl60x_wifi_driver/bl_main.h
  88. 62 0
      network/wifi_manager/bl60x_wifi_driver/bl_mod_params.c
  89. 43 0
      network/wifi_manager/bl60x_wifi_driver/bl_mod_params.h
  90. 1 0
      network/wifi_manager/bl60x_wifi_driver/bl_msg_rx.c
  91. 0 0
      network/wifi_manager/bl60x_wifi_driver/bl_msg_rx.h
  92. 1144 0
      network/wifi_manager/bl60x_wifi_driver/bl_msg_tx.c
  93. 52 0
      network/wifi_manager/bl60x_wifi_driver/bl_msg_tx.h
  94. 56 0
      network/wifi_manager/bl60x_wifi_driver/bl_platform.c
  95. 23 0
      network/wifi_manager/bl60x_wifi_driver/bl_platform.h
  96. 854 0
      network/wifi_manager/bl60x_wifi_driver/bl_rx.c
  97. 199 0
      network/wifi_manager/bl60x_wifi_driver/bl_rx.h
  98. 25 0
      network/wifi_manager/bl60x_wifi_driver/bl_strs.h
  99. 303 0
      network/wifi_manager/bl60x_wifi_driver/bl_tx.c
  100. 56 0
      network/wifi_manager/bl60x_wifi_driver/bl_tx.h

+ 201 - 0
LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 24 - 0
README.md

@@ -0,0 +1,24 @@
+# bl808 wlan driver for RT-Thread
+
+## 1. 简介
+
+**bl808 wlan driver for RT-Thread**是 BL808 在 rt-thread 上的 wlan 驱动。该驱动包从 [https://github.com/sipeed/M1s_BL808_SDK](https://github.com/sipeed/M1s_BL808_SDK) 仓库中的 Wi-Fi 部分移植而来。
+
+### 1.1 许可证
+
+遵循 Apache 2.0 许可,详见 `LICENSE` 文件。
+
+### 1.2 依赖
+
+- RT-Thread 4.0+
+- RT-Thread LWIP 组件
+- RT-Thread WIFI 组件
+- mbedtls v2.28.1 pakcage
+
+## 2. 注意事项
+
+目前该驱动只支持 Wi-Fi 功能。
+
+## 3. 联系方式
+
+维护人:[flyingcys](https://github.com/flyingcys)

+ 207 - 0
SConscript

@@ -0,0 +1,207 @@
+import os
+from building import *
+
+cwd = GetCurrentDir()
+LOCAL_CPPPATH=[]
+
+src = []
+path = [cwd]
+# add general drivers
+
+src += Split("""stage/blog/blog.c""")
+path += [cwd + r'/stage/blog']
+
+
+src += Split("""
+    stage/blfdt/src/fdt.c
+    stage/blfdt/src/fdt_ro.c
+    stage/blfdt/src/fdt_wip.c
+    stage/blfdt/src/fdt_sw.c
+    stage/blfdt/src/fdt_rw.c
+    stage/blfdt/src/fdt_strerror.c
+    stage/blfdt/src/fdt_empty_tree.c
+    stage/blfdt/src/fdt_addresses.c
+    stage/blfdt/src/fdt_overlay.c
+""")
+
+path += [
+    cwd + r'/stage/blfdt/inc',
+]
+
+src += Split("""
+    stage/blog/blog.c
+    utils/src/utils_log.c
+    utils/src/utils_hex.c
+    utils/src/utils_dns.c
+    utils/src/utils_getopt.c
+    utils/src/utils_string.c
+    utils/src/utils_crc.c
+    utils/src/utils_list.c
+    utils/src/utils_rbtree.c
+    utils/src/utils_tlv_bl.c
+""")
+path += [
+    cwd + r'/utils/include'
+]
+
+src += Split("""
+    os/bl_os_adapter/bl_os_adapter/bl_os_hal.c
+""")
+
+src += Split("""
+    security/blcrypto_suite/src/blcrypto_suite_bignum.c
+    security/blcrypto_suite/src/blcrypto_suite_ecp.c
+    security/blcrypto_suite/src/blcrypto_suite_ecp_curves.c
+    security/blcrypto_suite/src/blcrypto_suite_platform_util.c
+    security/blcrypto_suite/src/blcrypto_suite_porting.c
+    security/blcrypto_suite/src/blcrypto_suite_hacc.c
+    security/blcrypto_suite/src/blcrypto_suite_aes.c
+    security/blcrypto_suite/src/blcrypto_suite_hacc_glue.c
+    security/blcrypto_suite/src/blcrypto_suite_hacc_secp256r1_mul.c
+    security/blcrypto_suite/src/blcrypto_suite_supplicant_api.c
+    security/blcrypto_suite/src/blcrypto_suite_export_fw.c
+""")
+
+src += Split("""
+    security/mbedtls_lts/port/mbedtls_port_mem.c
+    security/mbedtls_lts/port/bignum_ext.c
+    security/mbedtls_lts/port/test_case.c
+""")
+             
+LOCAL_CPPPATH += [cwd + r'/security/mbedtls_lts',
+         cwd + r'/security/mbedtls_lts/port']
+
+src += Split("""
+    network/wifi_bt_coex/src/wifi_bt_coex.c
+    network/wifi_bt_coex/src/wifi_bt_coex_ctx.c
+    network/wifi_bt_coex/src/wifi_bt_coex_impl_bl808.c
+    network/wifi_hosal/wifi_hosal.c
+    network/wifi_hosal/port/wifi_hosal_bl808.c
+    network/wifi_manager/bl60x_wifi_driver/ipc_host.c
+    network/wifi_manager/bl60x_wifi_driver/bl_cmds.c
+    network/wifi_manager/bl60x_wifi_driver/bl_irqs.c
+    network/wifi_manager/bl60x_wifi_driver/bl_main.c
+    network/wifi_manager/bl60x_wifi_driver/bl_mod_params.c
+    network/wifi_manager/bl60x_wifi_driver/bl_msg_rx.c
+    network/wifi_manager/bl60x_wifi_driver/bl_msg_tx.c
+    network/wifi_manager/bl60x_wifi_driver/bl_platform.c
+    network/wifi_manager/bl60x_wifi_driver/bl_rx.c
+    network/wifi_manager/bl60x_wifi_driver/bl_tx.c
+    network/wifi_manager/bl60x_wifi_driver/bl_utils.c
+    network/wifi_manager/bl60x_wifi_driver/stateMachine.c
+    network/wifi_manager/bl60x_wifi_driver/wifi.c
+    network/wifi_manager/bl60x_wifi_driver/wifi_mgmr.c
+    network/wifi_manager/bl60x_wifi_driver/wifi_mgmr_api.c
+    network/wifi_manager/bl60x_wifi_driver/wifi_mgmr_ext.c
+    network/wifi_manager/bl60x_wifi_driver/wifi_mgmr_profile.c
+    network/wifi_manager/bl60x_wifi_driver/wifi_mgmr_event.c
+    network/wifi_manager/bl60x_wifi_driver/wifi_pkt_hooks.c
+""")
+
+src += Split("""
+    security/wpa_supplicant/port/os_bl.c
+    security/wpa_supplicant/src/ap/ap_config.c
+    security/wpa_supplicant/src/ap/wpa_auth_ie.c
+    security/wpa_supplicant/src/ap/wpa_auth_rsn_ccmp_only.c
+    security/wpa_supplicant/src/bl_supplicant/bl_hostap.c
+    security/wpa_supplicant/src/bl_supplicant/bl_wpa3.c
+    security/wpa_supplicant/src/bl_supplicant/bl_wpa_main.c
+    security/wpa_supplicant/src/bl_supplicant/bl_wpas_glue.c
+    security/wpa_supplicant/src/bl_supplicant/bl_wps.c
+    security/wpa_supplicant/src/common/sae.c
+    security/wpa_supplicant/src/common/wpa_common.c
+    security/wpa_supplicant/src/crypto/aes-cbc.c
+    security/wpa_supplicant/src/crypto/aes-internal-bl.c
+    security/wpa_supplicant/src/crypto/aes-omac1.c
+    security/wpa_supplicant/src/crypto/aes-unwrap.c
+    security/wpa_supplicant/src/crypto/aes-wrap.c
+    security/wpa_supplicant/src/crypto/crypto_internal-modexp.c
+    security/wpa_supplicant/src/crypto/dh_group5.c
+    security/wpa_supplicant/src/crypto/dh_groups.c
+    security/wpa_supplicant/src/crypto/md5-internal.c
+    security/wpa_supplicant/src/crypto/md5.c
+    security/wpa_supplicant/src/crypto/rc4.c
+    security/wpa_supplicant/src/crypto/sha1-internal.c
+    security/wpa_supplicant/src/crypto/sha1-pbkdf2.c
+    security/wpa_supplicant/src/crypto/sha1.c
+    security/wpa_supplicant/src/crypto/sha256-internal.c
+    security/wpa_supplicant/src/crypto/sha256-prf.c
+    security/wpa_supplicant/src/crypto/sha256.c
+    security/wpa_supplicant/src/eap_peer/eap_common.c
+    security/wpa_supplicant/src/rsn_supp/pmksa_cache.c
+    security/wpa_supplicant/src/rsn_supp/wpa.c
+    security/wpa_supplicant/src/rsn_supp/wpa_ie.c
+    security/wpa_supplicant/src/utils/common.c
+    security/wpa_supplicant/src/utils/wpa_debug.c
+    security/wpa_supplicant/src/utils/wpabuf.c
+    security/wpa_supplicant/src/wps/wps.c
+    security/wpa_supplicant/src/wps/wps_attr_build.c
+    security/wpa_supplicant/src/wps/wps_attr_parse.c
+    security/wpa_supplicant/src/wps/wps_attr_process.c
+    security/wpa_supplicant/src/wps/wps_common.c
+    security/wpa_supplicant/src/wps/wps_dev_attr.c
+    security/wpa_supplicant/src/wps/wps_enrollee.c
+    security/wpa_supplicant/src/wps/wps_registrar.c
+    security/wpa_supplicant/src/wps/wps_validate.c
+    security/wpa_supplicant/test/test_crypto-bl.c
+""")
+
+path += [cwd + r'/stage/yloop/include']
+
+path += [cwd + r'/os/bl_os_adapter/bl_os_adapter',
+         cwd + r'/os/bl_os_adapter/bl_os_adapter/include',
+         cwd + r'/os/bl_os_adapter/bl_os_adapter/include/bl_os_adapter']
+
+path += [cwd + r'/network/wifi_manager/bl60x_wifi_driver']
+
+path += [cwd + r'/network/wifi_bt_coex/include',
+         cwd + r'/network/wifi_manager/bl60x_wifi_driver/include']
+
+path += [cwd + r'/network/wifi_hosal/include']
+path += [cwd + r'/network/wifi/include']
+
+
+path += [cwd + r'/security/wpa_supplicant/port/include',
+         cwd + r'/security/wpa_supplicant/src',
+         cwd + r'/security/wpa_supplicant/include',
+         cwd + r'/security/wpa_supplicant/include/bl_supplicant',
+         cwd + r'/security/blcrypto_suite/inc',
+         cwd + r'/security/blcrypto_suite/priv_inc',
+
+         cwd + r'/fs/vfs/include']
+   
+src += Split("""
+    fs/vfs/src/vfs.c
+    fs/vfs/src/vfs_file.c
+    fs/vfs/src/vfs_inode.c
+    fs/vfs/src/vfs_register.c
+    stage/yloop/src/aos_rtthread_port.c
+    stage/yloop/src/yloop.c
+    stage/yloop/src/select.c
+    stage/yloop/src/device.c
+    stage/yloop/src/local_event.c
+""")
+path += [cwd + r'/stage/yloop/include']
+           
+src += Split("""
+    drv_wifi/bl_pm.c
+    drv_wifi/bl_sec.c
+    drv_wifi/bl_wifi.c
+    drv_wifi/bl_pm.c
+    drv_wifi/bl808_wifi.c
+""")
+path += [cwd + r'/drv_wifi']
+
+libpath = [cwd + '/platform/soc/bl606p/bl606p_phyrf/lib']
+libs = ['bl606p_phyrf.a']
+libpath += [cwd + '/network/wifi/lib']
+libs += ['libwifi.a']
+
+LOCAL_CFLAGS = ' -DMBEDTLS_CONFIG_FILE="<mbedtls_sample_config.h>"'
+CPPDEFINES = ['CFG_TXDESC="4"', 'CFG_STA_MAX="5"', 'CFG_CHIP_BL808', 'BL_CHIP_NAME="BL808"']
+LOCAL_CFLAGS += ' -DARCH_RISCV'
+
+group = DefineGroup('Libraries', src, depend = ['PKG_USING_WLAN_BL808'], CPPPATH = path, LIBS = libs, LIBPATH = libpath, CPPDEFINES = CPPDEFINES, LOCAL_CPPPATH = LOCAL_CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS)
+
+
+Return('group')

+ 10 - 0
drv_wifi/SConscript

@@ -0,0 +1,10 @@
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c') + Glob('*.cpp')
+CPPPATH = [cwd]
+LOCAL_CFLAGS = ' -DARCH_RISCV'
+
+group = DefineGroup('drv_wifi', src, depend = [''], CPPPATH = CPPPATH, LOCAL_CFLAGS = LOCAL_CFLAGS)
+
+Return('group')

+ 778 - 0
drv_wifi/bl808_sec_eng.h

@@ -0,0 +1,778 @@
+/**
+  ******************************************************************************
+  * @file    bl808_sec_eng.h
+  * @version V1.0
+  * @date
+  * @brief   This file is the standard driver header file
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+#ifndef __BL808_SEC_ENG_H__
+#define __BL808_SEC_ENG_H__
+
+#include "sec_eng_reg.h"
+#include "bl808_common.h"
+
+/** @addtogroup  BL808_Peripheral_Driver
+ *  @{
+ */
+
+/** @addtogroup  SEC_ENG
+ *  @{
+ */
+
+/** @defgroup  SEC_ENG_Public_Types
+ *  @{
+ */
+
+/**
+ *  @brief AES port type definition
+ */
+typedef enum {
+    SEC_ENG_AES_ID0, /*!< AES0 port define */
+} SEC_ENG_AES_ID_Type;
+
+/**
+ *  @brief SHA port type definition
+ */
+typedef enum {
+    SEC_ENG_SHA_ID0, /*!< SHA0 port define */
+} SEC_ENG_SHA_ID_Type;
+
+/**
+ *  @brief SHA type definition
+ */
+typedef enum {
+    SEC_ENG_SHA256,     /*!< SHA type:SHA256 */
+    SEC_ENG_SHA224,     /*!< SHA type:SHA224 */
+    SEC_ENG_SHA1,       /*!< SHA type:SHA1 */
+    SEC_ENG_SHA1_RSVD,  /*!< SHA type:SHA1 */
+    SEC_ENG_SHA512,     /*!< SHA type:SHA512 */
+    SEC_ENG_SHA384,     /*!< SHA type:SHA384 */
+    SEC_ENG_SHA512T224, /*!< SHA type:SHA512T224 */
+    SEC_ENG_SHA512T256, /*!< SHA type:SHA512T156 */
+    SEC_ENG_MD5,        /*!< MD5 */
+    SEC_ENG_CRC16,      /*!< CRC-16 */
+    SEC_ENG_CRC32,      /*!< CRC-32 */
+} SEC_ENG_SHA_Type;
+
+/**
+ *  @brief AES type definition
+ */
+typedef enum {
+    SEC_ENG_AES_ECB, /*!< AES mode type:ECB */
+    SEC_ENG_AES_CTR, /*!< AES mode type:CTR */
+    SEC_ENG_AES_CBC, /*!< AES mode type:CBC */
+    SEC_ENG_AES_XTS, /*!< AES mode type:XTS */
+} SEC_ENG_AES_Type;
+
+/**
+ *  @brief AES XTS mode type definition
+ */
+typedef enum {
+    SEC_ENG_AES_XTS_MODE1, /*!< AES xts mode type:mode1 */
+    SEC_ENG_AES_XTS_MODE2, /*!< AES xts mode type:mode2 */
+} SEC_ENG_AES_XTS_MODE_Type;
+
+/**
+ *  @brief AES KEY type definition
+ */
+typedef enum {
+    SEC_ENG_AES_KEY_128BITS,        /*!< AES KEY type:128 bits */
+    SEC_ENG_AES_KEY_256BITS,        /*!< AES KEY type:256 bits */
+    SEC_ENG_AES_KEY_192BITS,        /*!< AES KEY type:192 bits */
+    SEC_ENG_AES_DOUBLE_KEY_128BITS, /*!< AES double KEY type:128 bits */
+} SEC_ENG_AES_Key_Type;
+
+/**
+ *  @brief AES CTR mode counter type definition
+ */
+typedef enum {
+    SEC_ENG_AES_COUNTER_BYTE_4, /*!< AES CTR mode counter type:4 bytes */
+    SEC_ENG_AES_COUNTER_BYTE_1, /*!< AES CTR mode counter type:1 byte */
+    SEC_ENG_AES_COUNTER_BYTE_2, /*!< AES CTR mode counter type:2 bytes */
+    SEC_ENG_AES_COUNTER_BYTE_3, /*!< AES CTR mode counter type:3 bytes */
+} SEC_ENG_AES_Counter_Type;
+
+/**
+ *  @brief AES use new or old value type definition
+ */
+typedef enum {
+    SEC_ENG_AES_USE_NEW, /*!< Use new value */
+    SEC_ENG_AES_USE_OLD, /*!< Use old value same as last one */
+} SEC_ENG_AES_ValueUsed_Type;
+
+/**
+ *  @brief AES KEY source type definition
+ */
+typedef enum {
+    SEC_ENG_AES_KEY_SW, /*!< AES KEY from software */
+    SEC_ENG_AES_KEY_HW, /*!< AES KEY from hardware */
+} SEC_ENG_AES_Key_Src_Type;
+
+/**
+ *  @brief AES KEY source type definition
+ */
+typedef enum {
+    SEC_ENG_AES_ENCRYPTION, /*!< AES encryption */
+    SEC_ENG_AES_DECRYPTION, /*!< AES decryption */
+} SEC_ENG_AES_EnDec_Type;
+
+/**
+ *  @brief AES PKA register size type definition
+ */
+typedef enum {
+    SEC_ENG_PKA_REG_SIZE_8 = 1, /*!< Register size is  8 Bytes */
+    SEC_ENG_PKA_REG_SIZE_16,    /*!< Register size is  16 Bytes */
+    SEC_ENG_PKA_REG_SIZE_32,    /*!< Register size is  32 Bytes */
+    SEC_ENG_PKA_REG_SIZE_64,    /*!< Register size is  64 Bytes */
+    SEC_ENG_PKA_REG_SIZE_96,    /*!< Register size is  96 Bytes */
+    SEC_ENG_PKA_REG_SIZE_128,   /*!< Register size is  128 Bytes */
+    SEC_ENG_PKA_REG_SIZE_192,   /*!< Register size is  192 Bytes */
+    SEC_ENG_PKA_REG_SIZE_256,   /*!< Register size is  256 Bytes */
+    SEC_ENG_PKA_REG_SIZE_384,   /*!< Register size is  384 Bytes */
+    SEC_ENG_PKA_REG_SIZE_512,   /*!< Register size is  512 Bytes */
+} SEC_ENG_PKA_REG_SIZE_Type;
+
+/**
+ *  @brief AES PKA register size type definition
+ */
+typedef enum {
+    SEC_ENG_PKA_OP_PPSEL,                /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MOD2N = 0x11,         /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LDIV2N = 0x12,        /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LMUL2N = 0x13,        /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LDIV = 0x14,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LSQR = 0x15,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LMUL = 0x16,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LSUB = 0x17,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LADD = 0x18,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_LCMP = 0x19,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MDIV2 = 0x21,         /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MINV = 0x22,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MEXP = 0x23,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MSQR = 0x24,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MMUL = 0x25,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MREM = 0x26,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MSUB = 0x27,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MADD = 0x28,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_RESIZE = 0x31,        /*!< PKA operation type */
+    SEC_ENG_PKA_OP_MOVDAT = 0x32,        /*!< PKA operation type */
+    SEC_ENG_PKA_OP_NLIR = 0x33,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_SLIR = 0x34,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_CLIR = 0x35,          /*!< PKA operation type */
+    SEC_ENG_PKA_OP_CFLIRI_BUFFER = 0x36, /*!< PKA operation type */
+    SEC_ENG_PKA_OP_CTLIRI_PLD = 0x37,    /*!< PKA operation type */
+    SEC_ENG_PKA_OP_CFLIR_BUFFER = 0x38,  /*!< PKA operation type */
+    SEC_ENG_PKA_OP_CTLIR_PLD = 0x39,     /*!< PKA operation type */
+} SEC_ENG_PKA_OP_Type;
+
+/**
+ *  @brief Sec Eng Interrupt Type Def
+ */
+typedef enum {
+    SEC_ENG_INT_TRNG, /*!< Sec Eng Trng Interrupt Type */
+    SEC_ENG_INT_AES,  /*!< Sec Eng Aes Interrupt Type */
+    SEC_ENG_INT_SHA,  /*!< Sec Eng Sha Interrupt Type */
+    SEC_ENG_INT_PKA,  /*!< Sec Eng Pka Interrupt Type */
+    SEC_ENG_INT_CDET, /*!< Sec Eng Cdet Interrupt Type */
+    SEC_ENG_INT_GMAC, /*!< Sec Eng Gmac Interrupt Type */
+    SEC_ENG_INT_ALL,  /*!< Sec Eng All Interrupt Types */
+} SEC_ENG_INT_Type;
+
+/**
+ *  @brief SEC_ENG SHA256 context
+ */
+typedef struct
+{
+    uint32_t total[2];    /*!< Number of bytes processed */
+    uint32_t *shaBuf;     /*!< Data not processed but in this temp buffer */
+    uint32_t *shaPadding; /*!< Padding data */
+    uint8_t shaFeed;      /*!< Sha has feed data */
+} SEC_Eng_SHA256_Ctx;
+
+/**
+ *  @brief SEC_ENG SHA512 context
+ */
+typedef struct
+{
+    uint64_t total[2];    /*!< Number of bytes processed */
+    uint64_t *shaBuf;     /*!< Data not processed but in this temp buffer */
+    uint64_t *shaPadding; /*!< Padding data */
+    uint8_t shaFeed;      /*!< Sha has feed data */
+} SEC_Eng_SHA512_Ctx;
+
+/**
+ *  @brief SEC_ENG MD5 context
+ */
+typedef struct
+{
+    uint32_t total[2];    /*!< Number of bytes processed */
+    uint32_t *md5Buf;     /*!< Data not processed but in this temp buffer */
+    uint32_t *md5Padding; /*!< Padding data */
+    uint8_t md5Feed;      /*!< md5 has feed data */
+} SEC_Eng_MD5_Ctx;
+
+/**
+ *  @brief SEC_ENG SHA256 link mode context
+ */
+typedef struct
+{
+    uint32_t total[2];    /*!< Number of bytes processed */
+    uint32_t *shaBuf;     /*!< Data not processed but in this temp buffer */
+    uint32_t *shaPadding; /*!< Padding data */
+    uint32_t linkAddr;    /*!< Link configure address */
+} SEC_Eng_SHA256_Link_Ctx;
+
+/**
+ *  @brief SEC_ENG MD5 link mode context
+ */
+typedef struct
+{
+    uint64_t total[2];    /*!< Number of bytes processed */
+    uint64_t *shaBuf;     /*!< Data not processed but in this temp buffer */
+    uint64_t *shaPadding; /*!< Padding data */
+    uint32_t linkAddr;    /*!< Link configure address */
+} SEC_Eng_SHA512_Link_Ctx;
+
+/**
+ *  @brief SEC_ENG SHA256 link mode context
+ */
+typedef struct
+{
+    uint32_t total[2];    /*!< Number of bytes processed */
+    uint32_t *md5Buf;     /*!< Data not processed but in this temp buffer */
+    uint32_t *md5Padding; /*!< Padding data */
+    uint32_t linkAddr;    /*!< Link configure address */
+} SEC_Eng_MD5_Link_Ctx;
+
+/**
+ *  @brief SEC_ENG AES context
+ */
+typedef struct
+{
+    uint8_t aesFeed;       /*!< AES has feed data */
+    SEC_ENG_AES_Type mode; /*!< AES mode */
+} SEC_Eng_AES_Ctx;
+
+/**
+ *  @brief SEC_ENG SHA link config structure type definition
+ */
+typedef struct
+{
+    uint32_t            : 2;  /*!< [1:0]Reserved */
+    uint32_t shaMode    : 3;  /*!< [4:2]Sha-256/sha-224/sha-1/sha-1/sha-512/sha-384/sha-512T224/sha-512T256 */
+    uint32_t            : 1;  /*!< [5]Reserved */
+    uint32_t shaHashSel : 1;  /*!< [6]New hash or accumulate last hash */
+    uint32_t            : 2;  /*!< [8:7]Reserved */
+    uint32_t shaIntClr  : 1;  /*!< [9]Clear interrupt */
+    uint32_t shaIntSet  : 1;  /*!< [10]Set interrupt */
+    uint32_t            : 1;  /*!< [11]Reserved */
+    uint32_t shaModeExt : 2;  /*!< [13:12]Extention,0:sha 1:md5 2:crc16 3:crc32 */
+    uint32_t            : 2;  /*!< [15:14]Reserved */
+    uint32_t shaMsgLen  : 16; /*!< [31:16]Number of 512-bit block */
+    uint32_t shaSrcAddr;      /*!< Message source address */
+    uint32_t result[16];      /*!< Result of SHA */
+} __attribute__((aligned(4))) SEC_Eng_SHA_Link_Config_Type;
+
+/**
+ *  @brief SEC_ENG SHA link config structure type definition
+ */
+typedef struct
+{
+    uint32_t            : 2;  /*!< [1:0]Reserved */
+    uint32_t shaMode    : 3;  /*!< [4:2]Sha-256/sha-224/sha-1/sha-1/sha-512/sha-384/sha-512T224/sha-512T256 */
+    uint32_t            : 1;  /*!< [5]Reserved */
+    uint32_t shaHashSel : 1;  /*!< [6]New hash or accumulate last hash */
+    uint32_t            : 2;  /*!< [8:7]Reserved */
+    uint32_t shaIntClr  : 1;  /*!< [9]Clear interrupt */
+    uint32_t shaIntSet  : 1;  /*!< [10]Set interrupt */
+    uint32_t            : 1;  /*!< [11]Reserved */
+    uint32_t shaModeExt : 2;  /*!< [13:12]Extention,0:sha 1:md5 2:crc16 3:crc32 */
+    uint32_t            : 2;  /*!< [15:14]Reserved */
+    uint32_t shaMsgLen  : 16; /*!< [31:16]Number of 512-bit block */
+    uint32_t shaSrcAddr;      /*!< Message source address */
+    uint32_t poly;            /*!< poly of CRC */
+    uint32_t dout_inv : 1;    /*!< [0]dout inv of CRC */
+    uint32_t dout_ref : 1;    /*!< [1]dout ref of CRC */
+    uint32_t din_ref  : 1;    /*!< [2]din ref of CRC */
+    uint32_t          : 29;   /*!< [31:3]Reserved */
+    uint32_t ivAndHash;       /*!< CRC hash and also used as iv in 1st block */
+} __attribute__((aligned(4))) SEC_Eng_CRC_Link_Config_Type;
+
+/**
+ *  @brief SEC_ENG AES link config structure type definition
+ */
+typedef struct
+{
+    uint32_t              : 3;  /*!< [2:0]Reserved */
+    uint32_t aesMode      : 2;  /*!< [4:3]128-bit/256-bit/192-bit/128-bit-double key mode select */
+    uint32_t aesDecEn     : 1;  /*!< [5]Encode or decode */
+    uint32_t aesDecKeySel : 1;  /*!< [6]Use new key or use same key as last one */
+    uint32_t aesHwKeyEn   : 1;  /*!< [7]Enable or disable using hardware hey */
+    uint32_t              : 1;  /*!< [8]Reserved */
+    uint32_t aesIntClr    : 1;  /*!< [9]Clear interrupt */
+    uint32_t aesIntSet    : 1;  /*!< [10]Set interrupt */
+    uint32_t              : 1;  /*!< [11]Reserved */
+    uint32_t aesBlockMode : 2;  /*!< [13:12]ECB/CTR/CBC mode select */
+    uint32_t aesIVSel     : 1;  /*!< [14]Use new iv or use same iv as last one */
+    uint32_t aesXTS       : 1;  /*!< [15]XTS mode select */
+    uint32_t aesMsgLen    : 16; /*!< [31:16]Number of 128-bit block */
+    uint32_t aesSrcAddr;        /*!< Message source address */
+    uint32_t aesDstAddr;        /*!< Message destination address */
+    uint32_t aesIV0;            /*!< Big endian initial vector(MSB) */
+    uint32_t aesIV1;            /*!< Big endian initial vector */
+    uint32_t aesIV2;            /*!< Big endian initial vector */
+    uint32_t aesIV3;            /*!< Big endian initial vector(LSB)(CTR mode:counter initial value) */
+    uint32_t aesKey0;           /*!< Big endian aes key(aes-128/256 key MSB) */
+    uint32_t aesKey1;           /*!< Big endian aes key */
+    uint32_t aesKey2;           /*!< Big endian aes key */
+    uint32_t aesKey3;           /*!< Big endian aes key(aes-128 key LSB) */
+    uint32_t aesKey4;           /*!< Big endian aes key */
+    uint32_t aesKey5;           /*!< Big endian aes key */
+    uint32_t aesKey6;           /*!< Big endian aes key */
+    uint32_t aesKey7;           /*!< Big endian aes key(aes-256 key LSB) */
+} __attribute__((aligned(4))) SEC_Eng_AES_Link_Config_Type;
+
+/**
+ *  @brief SEC_ENG AES XTS mode1 link config structure type definition
+ */
+typedef struct
+{
+    uint32_t              : 3;  /*!< [2:0]Reserved */
+    uint32_t aesMode      : 2;  /*!< [4:3]128-bit/256-bit/192-bit/128-bit-double key mode select */
+    uint32_t aesDecEn     : 1;  /*!< [5]Encode or decode */
+    uint32_t aesDecKeySel : 1;  /*!< [6]Use new key or use same key as last one */
+    uint32_t aesHwKeyEn   : 1;  /*!< [7]Enable or disable using hardware hey */
+    uint32_t              : 1;  /*!< [8]Reserved */
+    uint32_t aesIntClr    : 1;  /*!< [9]Clear interrupt */
+    uint32_t aesIntSet    : 1;  /*!< [10]Set interrupt */
+    uint32_t              : 1;  /*!< [11]Reserved */
+    uint32_t aesBlockMode : 2;  /*!< [13:12]ECB/CTR/CBC mode select */
+    uint32_t aesIVSel     : 1;  /*!< [14]Use new iv or use same iv as last one */
+    uint32_t aesXTS       : 1;  /*!< [15]XTS mode select */
+    uint32_t aesMsgLen    : 16; /*!< [31:16]Number of 128-bit block */
+    uint32_t aesSrcAddr;        /*!< Message source address */
+    uint32_t aesDstAddr;        /*!< Message destination address */
+    uint32_t aesIV0;            /*!< Big endian initial vector(MSB) */
+    uint32_t aesIV1;            /*!< Big endian initial vector */
+    uint32_t aesIV2;            /*!< Big endian initial vector */
+    uint32_t aesIV3;            /*!< Big endian initial vector(LSB)(CTR mode:counter initial value) */
+    uint32_t aesKey10;          /*!< Big endian aes key1(aes-128/256 key MSB) */
+    uint32_t aesKey11;          /*!< Big endian aes key1 */
+    uint32_t aesKey12;          /*!< Big endian aes key1 */
+    uint32_t aesKey13;          /*!< Big endian aes key1(aes-128 key LSB) */
+    uint32_t aesKey14;          /*!< Big endian aes key1 */
+    uint32_t aesKey15;          /*!< Big endian aes key1 */
+    uint32_t aesKey16;          /*!< Big endian aes key1 */
+    uint32_t aesKey17;          /*!< Big endian aes key1(aes-256 key LSB) */
+    uint32_t            : 16;   /*!< [15:0]Reserved */
+    uint32_t aesUnitLen : 16;   /*!< [31:16]Big endian aes unit len */
+    uint32_t aesKey20;          /*!< Big endian aes key2(aes-128/256 key MSB) */
+    uint32_t aesKey21;          /*!< Big endian aes key2 */
+    uint32_t aesKey22;          /*!< Big endian aes key2 */
+    uint32_t aesKey23;          /*!< Big endian aes key2(aes-128 key LSB) */
+    uint32_t aesKey24;          /*!< Big endian aes key2 */
+    uint32_t aesKey25;          /*!< Big endian aes key2 */
+    uint32_t aesKey26;          /*!< Big endian aes key2 */
+    uint32_t aesKey27;          /*!< Big endian aes key2(aes-256 key LSB) */
+} __attribute__((aligned(4))) SEC_Eng_AES_XTS_Mode1_Link_Config_Type;
+
+/**
+ *  @brief SEC_ENG GMAC link config structure type definition
+ */
+typedef struct
+{
+    uint32_t            : 9;  /*!< [8:0]reserved */
+    uint32_t gmacIntClr : 1;  /*!< [9]Clear interrupt */
+    uint32_t gmacIntSet : 1;  /*!< [10]Set interrupt */
+    uint32_t            : 5;  /*!< [15:11]reserved */
+    uint32_t gmacMsgLen : 16; /*!< [31:16]Number of 128-bit block */
+    uint32_t gmacSrcAddr;     /*!< Message source address */
+    uint32_t gmacKey0;        /*!< GMAC key */
+    uint32_t gmacKey1;        /*!< GMAC key */
+    uint32_t gmacKey2;        /*!< GMAC key */
+    uint32_t gmacKey3;        /*!< GMAC key */
+    uint32_t result[4];       /*!< Result of GMAC */
+} __attribute__((aligned(4))) SEC_Eng_GMAC_Link_Config_Type;
+
+/**
+ *  @brief SEC_ENG PKA status type definition
+ */
+typedef struct
+{
+    uint16_t primeFail   : 1; /*!< [0]Prime fail */
+    uint16_t errUnknown  : 1; /*!< [1]Err unknown opc */
+    uint16_t errOverflow : 1; /*!< [2]Err opq overflow */
+    uint16_t errSrc2     : 1; /*!< [3]Err invalid src2 */
+    uint16_t errSrc1     : 1; /*!< [4]Err invalid src1 */
+    uint16_t errSrc0     : 1; /*!< [5]Err invalid src0 */
+    uint16_t errDiv0     : 1; /*!< [6]Err div by 0 */
+    uint16_t errFull     : 1; /*!< [7]Err cam full */
+    uint16_t lastOpc     : 1; /*!< [8]Last opc */
+    uint16_t opqFull     : 1; /*!< [9]Opq full */
+    uint16_t cmdIndex    : 5; /*!< [14:10]Cmd err index */
+    uint16_t errCmd      : 1; /*!< [15]Err cmd */
+} SEC_Eng_PKA_Status_Type;
+
+/*@} end of group SEC_ENG_Public_Types */
+
+/** @defgroup  SEC_ENG_Public_Constants
+ *  @{
+ */
+
+/** @defgroup  SEC_ENG_AES_ID_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_ID_TYPE(type) (((type) == SEC_ENG_AES_ID0))
+
+/** @defgroup  SEC_ENG_SHA_ID_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_SHA_ID_TYPE(type) (((type) == SEC_ENG_SHA_ID0))
+
+/** @defgroup  SEC_ENG_SHA_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_SHA_TYPE(type) (((type) == SEC_ENG_SHA256) ||     \
+                                   ((type) == SEC_ENG_SHA224) ||     \
+                                   ((type) == SEC_ENG_SHA1) ||       \
+                                   ((type) == SEC_ENG_SHA1_RSVD) ||  \
+                                   ((type) == SEC_ENG_SHA512) ||     \
+                                   ((type) == SEC_ENG_SHA384) ||     \
+                                   ((type) == SEC_ENG_SHA512T224) || \
+                                   ((type) == SEC_ENG_SHA512T256) || \
+                                   ((type) == SEC_ENG_MD5) ||        \
+                                   ((type) == SEC_ENG_CRC16) ||      \
+                                   ((type) == SEC_ENG_CRC32))
+
+/** @defgroup  SEC_ENG_AES_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_TYPE(type) (((type) == SEC_ENG_AES_ECB) || \
+                                   ((type) == SEC_ENG_AES_CTR) || \
+                                   ((type) == SEC_ENG_AES_CBC) || \
+                                   ((type) == SEC_ENG_AES_XTS))
+
+/** @defgroup  SEC_ENG_AES_XTS_MODE_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_XTS_MODE_TYPE(type) (((type) == SEC_ENG_AES_XTS_MODE1) || \
+                                            ((type) == SEC_ENG_AES_XTS_MODE2))
+
+/** @defgroup  SEC_ENG_AES_KEY_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_KEY_TYPE(type) (((type) == SEC_ENG_AES_KEY_128BITS) || \
+                                       ((type) == SEC_ENG_AES_KEY_256BITS) || \
+                                       ((type) == SEC_ENG_AES_KEY_192BITS) || \
+                                       ((type) == SEC_ENG_AES_DOUBLE_KEY_128BITS))
+
+/** @defgroup  SEC_ENG_AES_COUNTER_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_COUNTER_TYPE(type) (((type) == SEC_ENG_AES_COUNTER_BYTE_4) || \
+                                           ((type) == SEC_ENG_AES_COUNTER_BYTE_1) || \
+                                           ((type) == SEC_ENG_AES_COUNTER_BYTE_2) || \
+                                           ((type) == SEC_ENG_AES_COUNTER_BYTE_3))
+
+/** @defgroup  SEC_ENG_AES_VALUEUSED_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_VALUEUSED_TYPE(type) (((type) == SEC_ENG_AES_USE_NEW) || \
+                                             ((type) == SEC_ENG_AES_USE_OLD))
+
+/** @defgroup  SEC_ENG_AES_KEY_SRC_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_KEY_SRC_TYPE(type) (((type) == SEC_ENG_AES_KEY_SW) || \
+                                           ((type) == SEC_ENG_AES_KEY_HW))
+
+/** @defgroup  SEC_ENG_AES_ENDEC_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_AES_ENDEC_TYPE(type) (((type) == SEC_ENG_AES_ENCRYPTION) || \
+                                         ((type) == SEC_ENG_AES_DECRYPTION))
+
+/** @defgroup  SEC_ENG_PKA_REG_SIZE_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_PKA_REG_SIZE_TYPE(type) (((type) == SEC_ENG_PKA_REG_SIZE_8) ||   \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_16) ||  \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_32) ||  \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_64) ||  \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_96) ||  \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_128) || \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_192) || \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_256) || \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_384) || \
+                                            ((type) == SEC_ENG_PKA_REG_SIZE_512))
+
+/** @defgroup  SEC_ENG_PKA_OP_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_PKA_OP_TYPE(type) (((type) == SEC_ENG_PKA_OP_PPSEL) ||         \
+                                      ((type) == SEC_ENG_PKA_OP_MOD2N) ||         \
+                                      ((type) == SEC_ENG_PKA_OP_LDIV2N) ||        \
+                                      ((type) == SEC_ENG_PKA_OP_LMUL2N) ||        \
+                                      ((type) == SEC_ENG_PKA_OP_LDIV) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_LSQR) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_LMUL) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_LSUB) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_LADD) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_LCMP) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MDIV2) ||         \
+                                      ((type) == SEC_ENG_PKA_OP_MINV) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MEXP) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MSQR) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MMUL) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MREM) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MSUB) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_MADD) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_RESIZE) ||        \
+                                      ((type) == SEC_ENG_PKA_OP_MOVDAT) ||        \
+                                      ((type) == SEC_ENG_PKA_OP_NLIR) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_SLIR) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_CLIR) ||          \
+                                      ((type) == SEC_ENG_PKA_OP_CFLIRI_BUFFER) || \
+                                      ((type) == SEC_ENG_PKA_OP_CTLIRI_PLD) ||    \
+                                      ((type) == SEC_ENG_PKA_OP_CFLIR_BUFFER) ||  \
+                                      ((type) == SEC_ENG_PKA_OP_CTLIR_PLD))
+
+/** @defgroup  SEC_ENG_INT_TYPE
+ *  @{
+ */
+#define IS_SEC_ENG_INT_TYPE(type) (((type) == SEC_ENG_INT_TRNG) || \
+                                   ((type) == SEC_ENG_INT_AES) ||  \
+                                   ((type) == SEC_ENG_INT_SHA) ||  \
+                                   ((type) == SEC_ENG_INT_PKA) ||  \
+                                   ((type) == SEC_ENG_INT_CDET) || \
+                                   ((type) == SEC_ENG_INT_GMAC) || \
+                                   ((type) == SEC_ENG_INT_ALL))
+
+/*@} end of group SEC_ENG_Public_Constants */
+
+/** @defgroup  SEC_ENG_Public_Macros
+ *  @{
+ */
+#define SEC_ENG_PKA_STATUS_LAST_OPC_OFFSET 24
+#define SEC_ENG_PKA_STATUS_LAST_OPC_MASK   0x01000000
+
+/*@} end of group SEC_ENG_Public_Macros */
+
+/** @defgroup  SEC_ENG_Public_Functions
+ *  @{
+ */
+#ifndef BFLB_USE_HAL_DRIVER
+void SEC_GMAC_IRQHandler(void);
+void SEC_CDET_IRQHandler(void);
+void SEC_TRNG_IRQHandler(void);
+void SEC_PKA_IRQHandler(void);
+void SEC_AES_IRQHandler(void);
+void SEC_SHA_IRQHandler(void);
+#endif
+void Sec_Eng_SHA256_Init(SEC_Eng_SHA256_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, SEC_ENG_SHA_Type shaType,
+                         uint32_t shaTmpBuf[16], uint32_t padding[16]);
+void Sec_Eng_SHA512_Init(SEC_Eng_SHA512_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, SEC_ENG_SHA_Type shaType,
+                         uint64_t shaTmpBuf[16], uint64_t padding[16]);
+void Sec_Eng_MD5_Init(SEC_Eng_MD5_Ctx *md5Ctx, SEC_ENG_SHA_ID_Type shaNo, SEC_ENG_SHA_Type shaType,
+                      uint32_t md5TmpBuf[16], uint32_t padding[16]);
+void Sec_Eng_SHA_Start(SEC_ENG_SHA_ID_Type shaNo);
+BL_Err_Type Sec_Eng_SHA256_Update(SEC_Eng_SHA256_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, const uint8_t *input,
+                                  uint32_t len);
+BL_Err_Type Sec_Eng_SHA512_Update(SEC_Eng_SHA512_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, const uint8_t *input,
+                                  uint64_t len);
+BL_Err_Type Sec_Eng_MD5_Update(SEC_Eng_MD5_Ctx *md5Ctx, SEC_ENG_SHA_ID_Type shaNo, const uint8_t *input,
+                               uint32_t len);
+BL_Err_Type Sec_Eng_SHA256_Finish(SEC_Eng_SHA256_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, uint8_t *hash);
+BL_Err_Type Sec_Eng_SHA512_Finish(SEC_Eng_SHA512_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, uint8_t *hash);
+BL_Err_Type Sec_Eng_MD5_Finish(SEC_Eng_MD5_Ctx *md5Ctx, SEC_ENG_SHA_ID_Type shaNo, uint8_t *hash);
+void Sec_Eng_SHA_Enable_Link(SEC_ENG_SHA_ID_Type shaNo);
+void Sec_Eng_SHA_Disable_Link(SEC_ENG_SHA_ID_Type shaNo);
+void Sec_Eng_SHA256_Link_Init(SEC_Eng_SHA256_Link_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, uint32_t linkAddr,
+                              uint32_t shaTmpBuf[16], uint32_t padding[16]);
+void Sec_Eng_SHA512_Link_Init(SEC_Eng_SHA512_Link_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo, uint32_t linkAddr,
+                              uint64_t shaTmpBuf[16], uint64_t padding[16]);
+void Sec_Eng_MD5_Link_Init(SEC_Eng_MD5_Link_Ctx *md5Ctx, SEC_ENG_SHA_ID_Type shaNo, uint32_t linkAddr,
+                           uint32_t md5TmpBuf[16], uint32_t padding[16]);
+void Sec_Eng_Set_MD5_Din(SEC_ENG_AES_ID_Type aesNo);
+void Sec_Eng_Set_MD5_Din_Be(SEC_ENG_AES_ID_Type aesNo);
+void Sec_Eng_Set_MD5_Dout(SEC_ENG_AES_ID_Type aesNo);
+void Sec_Eng_Set_MD5_Dout_BE(SEC_ENG_AES_ID_Type aesNo);
+BL_Err_Type Sec_Eng_SHA256_Link_Update(SEC_Eng_SHA256_Link_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo,
+                                       const uint8_t *input, uint32_t len);
+BL_Err_Type Sec_Eng_SHA512_Link_Update(SEC_Eng_SHA512_Link_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo,
+                                       const uint8_t *input, uint64_t len);
+BL_Err_Type Sec_Eng_MD5_Link_Update(SEC_Eng_MD5_Link_Ctx *md5Ctx, SEC_ENG_SHA_ID_Type shaNo,
+                                    const uint8_t *input, uint32_t len);
+BL_Err_Type Sec_Eng_SHA256_Link_Finish(SEC_Eng_SHA256_Link_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo,
+                                       uint8_t *hash);
+BL_Err_Type Sec_Eng_SHA512_Link_Finish(SEC_Eng_SHA512_Link_Ctx *shaCtx, SEC_ENG_SHA_ID_Type shaNo,
+                                       uint8_t *hash);
+BL_Err_Type Sec_Eng_MD5_Link_Finish(SEC_Eng_MD5_Link_Ctx *md5Ctx, SEC_ENG_SHA_ID_Type shaNo,
+                                    uint8_t *hash);
+BL_Err_Type Sec_Eng_Group0_Request_SHA_Access(void);
+BL_Err_Type Sec_Eng_Group0_Release_SHA_Access(void);
+BL_Err_Type Sec_Eng_Group1_Request_SHA_Access(void);
+BL_Err_Type Sec_Eng_Group1_Release_SHA_Access(void);
+BL_Err_Type Sec_Eng_AES_Init(SEC_Eng_AES_Ctx *aesCtx, SEC_ENG_AES_ID_Type aesNo, SEC_ENG_AES_Type aesType,
+                             SEC_ENG_AES_Key_Type keyType, SEC_ENG_AES_EnDec_Type enDecType);
+void Sec_Eng_AES_Enable_LE(SEC_ENG_AES_ID_Type aesNo);
+void Sec_Eng_AES_Enable_BE(SEC_ENG_AES_ID_Type aesNo);
+void Sec_Eng_AES_Enable_Link(SEC_ENG_AES_ID_Type aesNo);
+void Sec_Eng_AES_Disable_Link(SEC_ENG_AES_ID_Type aesNo);
+BL_Err_Type Sec_Eng_CRC16_Link_Work(SEC_ENG_SHA_ID_Type shaNo, uint32_t linkAddr, const uint8_t *in, uint32_t len,
+                                    uint8_t *out);
+BL_Err_Type Sec_Eng_CRC32_Link_Work(SEC_ENG_SHA_ID_Type shaNo, uint32_t linkAddr, const uint8_t *in, uint32_t len,
+                                    uint8_t *out);
+BL_Err_Type Sec_Eng_AES_Link_Work(SEC_ENG_AES_ID_Type aesNo, uint32_t linkAddr, const uint8_t *in, uint32_t len,
+                                  uint8_t *out);
+void Sec_Eng_AES_Set_Hw_Key_Src(SEC_ENG_AES_ID_Type aesNo, uint8_t src);
+void Sec_Eng_AES_Set_Key_IV(SEC_ENG_AES_ID_Type aesNo, SEC_ENG_AES_Key_Src_Type keySrc, const uint8_t *key,
+                            const uint8_t *iv);
+void Sec_Eng_AES_Set_Key_IV_BE(SEC_ENG_AES_ID_Type aesNo, SEC_ENG_AES_Key_Src_Type keySrc, const uint8_t *key,
+                               const uint8_t *iv);
+void Sec_Eng_AES_Set_Counter_Byte(SEC_ENG_AES_ID_Type aesNo, SEC_ENG_AES_Counter_Type counterType);
+BL_Err_Type Sec_Eng_AES_Crypt(SEC_Eng_AES_Ctx *aesCtx, SEC_ENG_AES_ID_Type aesNo, const uint8_t *in, uint32_t len,
+                              uint8_t *out);
+BL_Err_Type Sec_Eng_AES_Finish(SEC_ENG_AES_ID_Type aesNo);
+BL_Err_Type Sec_Eng_Group0_Request_AES_Access(void);
+BL_Err_Type Sec_Eng_Group0_Release_AES_Access(void);
+BL_Err_Type Sec_Eng_Group1_Request_AES_Access(void);
+BL_Err_Type Sec_Eng_Group1_Release_AES_Access(void);
+BL_Err_Type Sec_Eng_Trng_Enable(void);
+void Sec_Eng_Trng_Int_Enable(void);
+void Sec_Eng_Trng_Int_Disable(void);
+BL_Err_Type Sec_Eng_Trng_Read(uint8_t data[32]);
+BL_Err_Type Sec_Eng_Trng_Get_Random(uint8_t *data, uint32_t len);
+void Sec_Eng_Trng_Int_Read_Trigger(void);
+void Sec_Eng_Trng_Int_Read(uint8_t data[32]);
+void Sec_Eng_Trng_Disable(void);
+BL_Err_Type Sec_Eng_Group0_Request_Trng_Access(void);
+BL_Err_Type Sec_Eng_Group0_Release_Trng_Access(void);
+BL_Err_Type Sec_Eng_Group1_Request_Trng_Access(void);
+BL_Err_Type Sec_Eng_Group1_Release_Trng_Access(void);
+void Sec_Eng_PKA_Reset(void);
+void Sec_Eng_PKA_BigEndian_Enable(void);
+void Sec_Eng_PKA_LittleEndian_Enable(void);
+void Sec_Eng_PKA_GetStatus(SEC_Eng_PKA_Status_Type *status);
+void Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_Type regType, uint8_t regIndex, const uint32_t *data, uint16_t size,
+                            uint8_t lastOp);
+void Sec_Eng_PKA_Read_Data(SEC_ENG_PKA_REG_SIZE_Type regType, uint8_t regIdx, uint32_t *result, uint8_t retSize);
+void Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_Type dRegType, uint8_t dRegIdx, uint8_t size, uint8_t lastOp);
+void Sec_Eng_PKA_Write_Immediate(SEC_ENG_PKA_REG_SIZE_Type regType, uint8_t regIndex, uint32_t data, uint8_t lastOp);
+void Sec_Eng_PKA_NREG(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_Move_Data(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_RESIZE(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MADD(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t s2RegType, uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MSUB(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t s2RegType, uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MREM(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s2RegType,
+                      uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MMUL(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t s2RegType, uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MSQR(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s2RegType,
+                      uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MEXP(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t s2RegType, uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MINV(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s2RegType,
+                      uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_MINV(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s2RegType,
+                      uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_LCMP(uint8_t *cout, uint8_t s0RegType, uint8_t s0RegIdx, uint8_t s1RegType, uint8_t s1RegIdx);
+void Sec_Eng_PKA_LADD(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_LSUB(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_LMUL(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s1RegType,
+                      uint8_t s1RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_LSQR(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_LDIV(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                      uint8_t s2RegType,
+                      uint8_t s2RegIdx, uint8_t lastOp);
+void Sec_Eng_PKA_LMUL2N(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                        uint16_t bit_shift,
+                        uint8_t lastOp);
+void Sec_Eng_PKA_LDIV2N(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                        uint16_t bit_shift,
+                        uint8_t lastOp);
+void Sec_Eng_PKA_LMOD2N(uint8_t dRegType, uint8_t dRegIdx, uint8_t s0RegType, uint8_t s0RegIdx,
+                        uint16_t bit_shift,
+                        uint8_t lastOp);
+void Sec_Eng_PKA_GF2Mont(uint8_t dRegType, uint8_t dRegIdx, uint8_t sRegType, uint8_t sRegIdx, uint32_t size,
+                         uint8_t tRegType, uint8_t tRegIdx, uint8_t pRegType, uint8_t pRegIdx);
+void Sec_Eng_PKA_Mont2GF(uint8_t dRegType, uint8_t dRegIdx, uint8_t aRegType, uint8_t aRegIdx, uint8_t invrRegType,
+                         uint8_t invrRegIdx,
+                         uint8_t tRegType, uint8_t tRegIdx, uint8_t pRegType, uint8_t pRegIdx);
+BL_Err_Type Sec_Eng_Group0_Request_PKA_Access(void);
+BL_Err_Type Sec_Eng_Group0_Release_PKA_Access(void);
+BL_Err_Type Sec_Eng_Group1_Request_PKA_Access(void);
+BL_Err_Type Sec_Eng_Group1_Release_PKA_Access(void);
+void Sec_Eng_GMAC_Enable_LE(void);
+void Sec_Eng_GMAC_Enable_BE(void);
+void Sec_Eng_GMAC_Enable_Link(void);
+void Sec_Eng_GMAC_Disable_Link(void);
+BL_Err_Type Sec_Eng_GMAC_Link_Work(uint32_t linkAddr, const uint8_t *in, uint32_t len, uint8_t *out);
+BL_Err_Type Sec_Eng_Group0_Request_GMAC_Access(void);
+BL_Err_Type Sec_Eng_Group0_Release_GMAC_Access(void);
+BL_Err_Type Sec_Eng_Group1_Request_GMAC_Access(void);
+BL_Err_Type Sec_Eng_Group1_Release_GMAC_Access(void);
+void SEC_Eng_IntMask(SEC_ENG_INT_Type intType, BL_Mask_Type intMask);
+void SEC_Eng_ClrIntStatus(SEC_ENG_INT_Type intType);
+void SEC_Eng_Int_Callback_Install(SEC_ENG_INT_Type intType, intCallback_Type *cbFun);
+BL_Sts_Type SEC_Eng_GetIntStatus(SEC_ENG_INT_Type intType);
+/*----------*/
+void SEC_Eng_Turn_On_Sec_Ring(void);
+void SEC_Eng_Turn_Off_Sec_Ring(void);
+void Sec_Eng_PKA_Clear_Int(void);
+void Sec_Eng_PKA_Read_Block(uint32_t *dest, const uint32_t *src, uint32_t len);
+void Sec_Eng_PKA_Read_Block(uint32_t *dest, const uint32_t *src, uint32_t len);
+void Sec_Eng_PKA_Write_Block(uint32_t *dest, const uint32_t *src, uint32_t len);
+void Sec_Eng_PKA_Write_Block(uint32_t *dest, const uint32_t *src, uint32_t len);
+/*----------*/;
+
+/*@} end of group SEC_ENG_Public_Functions */
+
+/*@} end of group SEC_ENG */
+
+/*@} end of group BL808_Peripheral_Driver */
+
+#endif /* __BL808_SEC_ENG_H__ */

+ 98 - 0
drv_wifi/bl808_wifi.c

@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022/12/25     flyingcys    first version
+ */
+
+#undef ARCH_RISCV
+#include <rtthread.h>
+#include <stdio.h>
+
+#include "bl808_wifi.h"
+
+// static wifi_interface_t wifi_interface;
+
+#define WIFI_AP_PSM_INFO_SSID "conf_ap_ssid"
+#define WIFI_AP_PSM_INFO_PASSWORD "conf_ap_psk"
+#define WIFI_AP_PSM_INFO_PMK "conf_ap_pmk"
+#define WIFI_AP_PSM_INFO_BSSID "conf_ap_bssid"
+#define WIFI_AP_PSM_INFO_CHANNEL "conf_ap_channel"
+#define WIFI_AP_PSM_INFO_IP "conf_ap_ip"
+#define WIFI_AP_PSM_INFO_MASK "conf_ap_mask"
+#define WIFI_AP_PSM_INFO_GW "conf_ap_gw"
+#define WIFI_AP_PSM_INFO_DNS1 "conf_ap_dns1"
+#define WIFI_AP_PSM_INFO_DNS2 "conf_ap_dns2"
+#define WIFI_AP_PSM_INFO_IP_LEASE_TIME "conf_ap_ip_lease_time"
+#define WIFI_AP_PSM_INFO_GW_MAC "conf_ap_gw_mac"
+
+void start_aos_loop(void);
+
+#define TASK_AOS_TASKNAME ((char *)"aos_loop")
+#define TASK_AOS_STACKSIZE (2048)
+#define TASK_AOS_PRIORITY (20)
+
+#define TASK_WIFIMAIN_TASKNAME ((char *)"wifi_main")
+#define TASK_WIFIMAIN_STACKSIZE (4096)
+#define TASK_WIFIMAIN_PRIORITY (15)
+
+void bl808_wifi_init(void *event_callback)
+{
+    static uint8_t stack_wifi_init = 0;
+
+    if (1 == stack_wifi_init) {
+        return;
+    }
+    stack_wifi_init = 1;
+
+    start_aos_loop();
+
+    bl_sec_init();
+    phy_powroffset_set((int8_t[4]){0x0, 0x0, 0x0, 0x0});
+    bl_tpc_update_power_rate_11b((int8_t[4]){0x14, 0x14, 0x14, 0x12});
+    bl_tpc_update_power_rate_11g((int8_t[8]){0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xe, 0xe});
+    bl_tpc_update_power_rate_11n((int8_t[8]){0x12, 0x12, 0x12, 0x12, 0x12, 0x10, 0xe, 0xe});
+
+    bl_pm_init();
+
+    bl_os_task_create(TASK_WIFIMAIN_TASKNAME, wifi_main, TASK_WIFIMAIN_STACKSIZE, NULL, TASK_WIFIMAIN_PRIORITY, NULL);
+    bl_os_event_register(EV_WIFI, event_callback, NULL);
+
+    rt_thread_delay(1000);
+
+    // bl_os_event_notify(CODE_WIFI_ON_INIT_DONE, 0);
+    static wifi_conf_t conf = {
+        .country_code = "CN",
+    };
+    wifi_mgmr_start_background(&conf);
+}
+
+static void aos_loop_proc(void *pvParameters)
+{
+    // int fd_console;
+
+    vfs_init();
+    vfs_device_init();
+
+    aos_loop_init();
+
+    rt_kprintf("start aos loop... \r\n");
+
+    aos_loop_run();
+
+    bl_os_puts("------------------------------------------\r\n");
+    bl_os_puts("+++++++++Critical Exit From Loop++++++++++\r\n");
+    bl_os_puts("******************************************\r\n");
+}
+
+void start_aos_loop(void)
+{
+    rt_thread_t tid = rt_thread_create(TASK_AOS_TASKNAME, aos_loop_proc, RT_NULL,
+                           TASK_AOS_STACKSIZE, TASK_AOS_PRIORITY, 20);
+    if(RT_NULL != tid)  
+        rt_thread_startup(tid);
+    rt_kprintf("aos_loop_tid:%p\r\n", tid);
+}

+ 23 - 0
drv_wifi/bl808_wifi.h

@@ -0,0 +1,23 @@
+
+#ifndef __BL808_WIFI_H__
+#define __BL808_WIFI_H__
+
+#include <wifi_mgmr.h>
+#include <wifi_mgmr_api.h>
+#include <wifi_mgmr_ext.h>
+#include <bl_defs.h>
+#include "bl_main.h"
+
+#include <bl_wifi.h>
+#include <bl60x_fw_api.h>
+#include <bl_os_private.h>
+
+// yloop
+#include <aos/kernel.h>
+#include <aos/yloop.h>
+
+#include <event_device.h>
+
+void bl808_wifi_init(void *event_callback);
+
+#endif /* __BL808_WIFI_H__ */

+ 487 - 0
drv_wifi/bl_pm.c

@@ -0,0 +1,487 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <utils_list.h>
+#include <blog.h>
+#include "bl_pm.h"
+#include "bl_os_hal.h"
+#include <assert.h>
+
+enum PM_STATE {
+    PM_STATE_INITED = 0,
+    PM_STATE_STOP,
+    PM_STATE_START,
+    PM_STATE_STOPPED,
+    PM_STATE_RUNNING,
+};
+
+union ps_cap {
+    uint32_t cap;
+    struct {
+        unsigned int uapsd_mode     :   1;
+        unsigned int mac_idle       :   1;
+        unsigned int ma_doze        :   1;
+        unsigned int rf_onoff       :   1;
+        unsigned int pti_pta_config :   1;
+        unsigned int force_sleep    :   1;
+    } bits;
+};
+
+struct pm_env
+{
+    uint32_t level;
+    union ps_cap wlan_capacity;
+    union ps_cap bt_capacity;
+    enum PM_STATE state;
+    BL_Mutex_t pm_mux;
+    utils_dlist_t *pm_list;
+};
+
+struct pm_node
+{
+    utils_dlist_t dlist_item;
+    enum PM_EVEMT event;
+    uint32_t code;
+    uint16_t priority;
+    uint32_t cap_bit;
+    bl_pm_cb_t ops;
+    enum PM_EVENT_ABLE enable;
+    void *ctx;
+};
+
+static struct pm_env *gp_pm_env = NULL;
+
+static int pm_env_init(void)
+{
+    int i = 0;
+
+    assert(!gp_pm_env);
+
+    gp_pm_env = bl_os_malloc(sizeof(struct pm_env));
+    assert(gp_pm_env);
+
+    memset(gp_pm_env, 0, sizeof(struct pm_env));
+    gp_pm_env->pm_list = bl_os_malloc(sizeof(utils_dlist_t) * PM_EVENT_MAX);
+    assert(gp_pm_env->pm_list);
+
+    memset(gp_pm_env->pm_list, 0, sizeof(bl_pm_cb_t) * PM_EVENT_MAX);
+
+    gp_pm_env->pm_mux = bl_os_mutex_create();
+    assert(gp_pm_env->pm_mux);
+
+    for (i = 0; i < PM_EVENT_MAX; i++) {
+        INIT_UTILS_DLIST_HEAD(&(gp_pm_env->pm_list)[i]);
+    }
+
+    gp_pm_env->state = PM_STATE_INITED;
+
+    ///for debug
+    gp_pm_env->bt_capacity.cap = 0xffff;
+
+    return 0;
+}
+
+static void pm_node_delete(utils_dlist_t *queue)
+{
+    struct pm_node *node = NULL;
+    utils_dlist_t *tmp;
+
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        bl_os_mutex_lock(gp_pm_env->pm_mux);
+        utils_dlist_del(&(node->dlist_item));
+        bl_os_free(node);
+        bl_os_mutex_unlock(gp_pm_env->pm_mux);
+    }
+}
+
+static int pm_deinit(void)
+{
+    int i = 0;
+
+    assert(gp_pm_env);
+
+    for (i = 0; i < PM_EVENT_MAX; i++) {
+        pm_node_delete(&(gp_pm_env->pm_list)[i]);
+    }
+
+    bl_os_free(gp_pm_env->pm_list);
+    gp_pm_env->pm_list = NULL;
+
+    bl_os_mutex_delete(gp_pm_env->pm_mux);
+    gp_pm_env->pm_mux = NULL;
+
+    bl_os_free(gp_pm_env);
+    gp_pm_env = NULL;
+
+    return 0;
+}
+
+static int pm_set_wlan_capacity(uint32_t capacity)
+{
+    assert(gp_pm_env);
+
+    gp_pm_env->wlan_capacity.cap = capacity;
+
+    return 0;
+}
+
+static int pm_set_state(enum PM_STATE state)
+{
+    gp_pm_env->state = state;
+
+    return 0;
+}
+
+static enum PM_STATE pm_get_state(void)
+{
+    return gp_pm_env->state;
+}
+
+static void pm_node_add(struct pm_node *pnode, utils_dlist_t *queue)
+{
+    struct pm_node *node = NULL;
+    utils_dlist_t *tmp;
+    utils_dlist_t *pre_save;
+
+    pre_save = queue;
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        if (pnode->priority < node->priority) {
+            bl_os_mutex_lock(gp_pm_env->pm_mux);
+            utils_dlist_add(&(pnode->dlist_item), pre_save);
+            bl_os_mutex_unlock(gp_pm_env->pm_mux);
+            break;
+        }
+
+        pre_save = &(node->dlist_item);
+    }
+
+    if (&(node->dlist_item) == queue) {
+        bl_os_mutex_lock(gp_pm_env->pm_mux);
+        utils_dlist_add_tail(&(pnode->dlist_item), queue);
+        bl_os_mutex_unlock(gp_pm_env->pm_mux);
+    }
+}
+
+static int pm_node_ops_exec(struct pm_node *node)
+{
+    if (node->ops == NULL) {
+        return 0;
+    }
+
+    return node->ops(node->ctx);
+}
+
+static int pm_state_exec_func_check(enum PM_EVEMT event, uint32_t code)
+{
+    int ret;
+
+    if ((WLAN_PM_EVENT_CONTROL == event) || (PM_STATE_RUNNING == gp_pm_env->state)) {
+        ret = 0;
+    } else {
+        ret = 1;
+    }
+
+    return ret;
+}
+
+static int pm_pmlist_traverse(enum PM_EVEMT event, utils_dlist_t *queue, uint32_t code, uint32_t *retval)
+{
+    struct pm_node *node = NULL;
+    int ret = 0;
+    utils_dlist_t *tmp;
+
+    if (retval) {
+        *retval = 0;
+    }
+
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        if ((node->enable) && (code == node->code) && (gp_pm_env->wlan_capacity.cap & node->cap_bit) &&
+                (gp_pm_env->bt_capacity.cap & node->cap_bit)) {
+
+            if (pm_state_exec_func_check(event, code)) {
+                return -1;
+            }
+
+            ret = pm_node_ops_exec(node);
+            if (ret && retval) {
+                *retval |= 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int pm_internal_process_event(enum PM_EVEMT event, uint32_t code)
+{
+    int ret = 0;
+
+    switch (event) {
+        case WLAN_PM_EVENT_CONTROL:
+        {
+            switch (code) {
+                case WLAN_CODE_PM_NOTIFY_START:
+                {
+                    if ((PM_STATE_INITED != pm_get_state()) && (PM_STATE_STOPPED != pm_get_state())) {
+                        blog_error("pm not init or is running.\r\n");
+                        ret = -1;
+
+                        return ret;
+                    }
+                    pm_set_state(PM_STATE_START);
+                }
+                break;
+
+                case WLAN_CODE_PM_NOTIFY_STOP:
+                {
+                    if (PM_STATE_RUNNING != pm_get_state()) {
+                        blog_error("pm is not running.\r\n");
+                        ret = -1;
+
+                        return ret;
+                    }
+
+                    pm_set_state(PM_STATE_STOP);
+                }
+                break;
+
+                default:
+                {
+                }
+            }
+        }
+        break;
+
+        default:
+        {
+
+        }
+    }
+
+    return ret;
+}
+
+int pm_post_event(enum PM_EVEMT event, uint32_t code, uint32_t *retval)
+{
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    pm_pmlist_traverse(event, &(gp_pm_env->pm_list)[event], code, retval);
+    pm_internal_process_event(event, code);
+
+    return 0;
+}
+
+int bl_pm_event_register(enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t priority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable)
+{
+    struct pm_node *p_node;
+
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    p_node = bl_os_malloc(sizeof(struct pm_node));
+    assert(p_node);
+
+    memset(p_node, 0, sizeof(struct pm_node));
+    p_node->event = event;
+    p_node->code = code;
+    p_node->cap_bit = cap_bit;
+    p_node->priority = priority;
+    p_node->ops = ops;
+    p_node->ctx = arg;
+    p_node->enable = enable;
+
+    pm_node_add(p_node, &(gp_pm_env->pm_list)[event]);
+
+    return 0;
+}
+
+int bl_pm_event_switch(enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable)
+{
+    struct pm_node *node = NULL;
+    utils_dlist_t *tmp;
+    utils_dlist_t *queue;
+    int ret = -1;
+
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    queue = &(gp_pm_env->pm_list)[event];
+
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        if (code == node->code) {
+            node->enable = enable;
+
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+
+int bl_pm_state_run(void)
+{
+    int ret = -1;
+
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    switch (gp_pm_env->state) {
+        case PM_STATE_INITED:
+        {
+        }
+        break;
+
+        case PM_STATE_START:
+        {
+            pm_set_state(PM_STATE_RUNNING);
+            pm_post_event(WLAN_PM_EVENT_CONTROL, WLAN_CODE_PM_START, NULL);;
+            ret = 0;
+        }
+        break;
+
+        case PM_STATE_STOP:
+        {
+            pm_set_state(PM_STATE_STOPPED);
+            pm_post_event(WLAN_PM_EVENT_CONTROL, WLAN_CODE_PM_STOP, NULL);
+        }
+        break;
+
+        case PM_STATE_RUNNING:
+        {
+            ret = 0;
+        }
+        break;
+
+        case PM_STATE_STOPPED:
+        {
+        }
+        break;
+
+        default:
+        {
+
+        }
+    }
+
+    return ret;
+}
+
+int bl_pm_capacity_set(enum PM_LEVEL level)
+{
+    uint32_t capacity = 0;
+
+    switch (level) {
+        case PM_MODE_STA_NONE:
+        {
+            return -1;
+        }
+        break;
+
+        case PM_MODE_STA_IDLE:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+        }
+        break;
+
+        case PM_MODE_STA_MESH:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_WLAN_BLE_ABORT;
+            capacity |= NODE_CAP_BIT_FORCE_SLEEP;
+        }
+        break;
+
+        case PM_MODE_STA_DOZE:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+            capacity |= NODE_CAP_BIT_RF_ONOFF;
+            capacity |= NODE_CAP_BIT_FORCE_SLEEP;
+        }
+        break;
+
+        case PM_MODE_STA_COEX:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+            capacity |= NODE_CAP_BIT_RF_ONOFF;
+            capacity |= NODE_CAP_BIT_WLAN_BLE_ABORT;
+        }
+        break;
+
+        case PM_MODE_STA_DOWN:
+        {
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+            capacity |= NODE_CAP_BIT_RF_ONOFF;
+        }
+        break;
+
+        case PM_MODE_AP_IDLE:
+        {
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+        }
+        break;
+
+        default:
+        {
+            return -1;
+        }
+    }
+
+    pm_set_wlan_capacity(capacity);
+
+    return 0;
+}
+
+int bl_pm_init(void)
+{
+    pm_env_init();
+
+    return 0;
+}
+
+int bl_pm_deinit(void)
+{
+    pm_deinit();
+
+    return 0;
+}

+ 111 - 0
drv_wifi/bl_pm.h

@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_PM_H__
+#define __BL_PM_H__
+#include <stdint.h>
+#include <utils_list.h>
+
+#define    NODE_CAP_BIT_UAPSD_MODE        (1 << 0)
+#define    NODE_CAP_BIT_MAC_IDLE          (1 << 1)
+#define    NODE_CAP_BIT_MAC_DOZE          (1 << 2)
+#define    NODE_CAP_BIT_RF_ONOFF          (1 << 3)
+#define    NODE_CAP_BIT_WLAN_BLE_ABORT    (1 << 4)
+#define    NODE_CAP_BIT_FORCE_SLEEP       (1 << 5)
+#define    NODE_CAP_BIT_ALL_ALLOWED       (0xffff)
+
+enum PM_EVENT_ABLE {
+    PM_DISABLE = 0,
+    PM_ENABLE,
+};
+
+enum WLAN_CODE_SLEEP_CONTROL {
+    WLAN_CODE_PM_NOTIFY_START = 0,
+    WLAN_CODE_PM_NOTIFY_STOP,
+    WLAN_CODE_PM_START,
+    WLAN_CODE_PM_STOP,
+};
+
+enum WLAN_CODE_ENTER_SLEEP {
+    WLAN_CODE_PM_ENTER_SLEEP_PRE = 0,
+    WLAN_CODE_PM_ENTER_SLEEP,
+};
+
+enum WLAN_CODE_EXIT_SLEEP {
+    WLAN_CODE_PM_ENTER_SLEEP_PRE_FAILED = 0,
+    WLAN_CODE_PM_EXIT_SLEEP_PRE,
+    WLAN_CODE_PM_EXIT_SLEEP,
+};
+
+enum WLAN_CODE_BEACON_LOSS {
+    WLAN_CODE_BEACON_LOSS = 0,
+};
+
+enum WLAN_CODE_SEND_NULLDATA {
+   WLAN_CODE_PM_PAUSE = 0,
+   WLAN_CODE_PM_NULLDATA_NOACK,
+   WLAN_CODE_PM_NULLDATA_SEND_ERROR,
+};
+
+enum BLE_CODE_BLE_CONTROL {
+    BLE_CODE_PM_TURNON_RF = 0,
+    BLE_CODE_PM_TURNOFF_RF,
+};
+
+enum PM_LEVEL{
+    PM_MODE_STA_NONE = 0,
+    PM_MODE_STA_IDLE,
+    PM_MODE_STA_MESH,
+    PM_MODE_STA_DOZE,
+    PM_MODE_STA_COEX,
+    PM_MODE_STA_DOWN,
+    PM_MODE_AP_IDLE,
+    PM_MODE_MAX,
+};
+
+enum PM_EVEMT{
+    WLAN_PM_EVENT_CONTROL = 0,
+    WLAN_PM_EVENT_ENTER_SLEEP,
+    WLAN_PM_EVENT_EXIT_SLEEP,
+    WLAN_PM_EVENT_BEACON_LOSS,
+    WLAN_PM_EVENT_SEND_NULLDATA,
+    BLE_PM_EVENT_CONTROL,
+    PM_EVENT_MAX,
+};
+
+typedef int (*bl_pm_cb_t)(void *arg);
+
+int bl_pm_init(void);
+int bl_pm_event_register(enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t pirority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable);
+int bl_pm_deinit(void);
+int bl_pm_state_run(void);
+int bl_pm_capacity_set(enum PM_LEVEL level);
+int pm_post_event(enum PM_EVEMT event, uint32_t code, uint32_t *retval);
+int bl_pm_event_switch(enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable);
+#endif

+ 799 - 0
drv_wifi/bl_sec.c

@@ -0,0 +1,799 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+
+#include <sec_eng_reg.h>
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_sec_eng.h>
+#elif defined(BL606P)
+#include <bl606p_sec_eng.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include <aos/kernel.h>
+
+#include "bl_sec.h"
+// #include "bl_irq.h"
+
+#include <blog.h>
+
+#define xstr(a) str_macro(a)
+#define str_macro(a) #a
+#define TRNG_LOOP_COUNTER   (17)
+
+#define TRNG_SIZE_IN_WORD (8)
+#define TRNG_SIZE_IN_BYTES (32)
+static uint32_t trng_buffer[TRNG_SIZE_IN_WORD];
+static unsigned int trng_idx = 0;
+
+// BL_Sem_t g_bl_sec_sha_mutex = NULL;
+#if 0
+static inline void _trng_trigger()
+{
+    uint32_t TRNGx = SEC_ENG_BASE;
+    uint32_t val;
+
+    val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+    if (BL_IS_REG_BIT_SET(val, SEC_ENG_SE_TRNG_0_BUSY)) {
+        return;
+    }
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_1, trng_buffer[0]);
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_2, trng_buffer[1]);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_SET_1T);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_CLR_1T);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_EN);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_TRIG_1T);
+
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0, val);
+}
+
+
+static inline void wait_trng4feed()
+{
+    uint32_t TRNGx = SEC_ENG_BASE;
+    uint32_t val;
+
+    val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+
+    while (BL_IS_REG_BIT_SET(val, SEC_ENG_SE_TRNG_0_BUSY)) {
+        /*wait until trng is NOT busy*/
+        val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+    }
+
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_CLR_1T);
+    val = BL_CLR_REG_BIT(val, SEC_ENG_SE_TRNG_0_TRIG_1T);
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0, val);
+
+    blog_debug("Feed random number is %08lx\r\n", trng_buffer[0]);
+    trng_buffer[0] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_0);
+    trng_buffer[1] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_1);
+    trng_buffer[2] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_2);
+    trng_buffer[3] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_3);
+    trng_buffer[4] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_4);
+    trng_buffer[5] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_5);
+    trng_buffer[6] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_6);
+    trng_buffer[7] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_7);
+}
+
+uint32_t bl_sec_get_random_word(void)
+{
+    trng_idx = (trng_idx & 0x7);
+    if (0 == trng_idx) {
+        _trng_trigger();
+    }
+    return trng_buffer[trng_idx++];
+}
+#endif
+void bl_rand_stream(uint8_t *buf, int len)
+{
+    // int pos, copysize;
+
+    // pos = 0;
+    // if (trng_idx) {
+    //     /*reset trng_buffer*/
+    //     _trng_trigger();
+    //     wait_trng4feed();
+    //     trng_idx = 0;
+    // }
+
+    // while (len > 0) {
+    //     if (trng_idx) {
+    //         /*reset trng_buffer*/
+    //         _trng_trigger();
+    //         wait_trng4feed();
+    //         trng_idx = 0;
+    //     }
+    //     copysize = len > TRNG_SIZE_IN_BYTES ? TRNG_SIZE_IN_BYTES : len;
+    //     memcpy(buf + pos, trng_buffer, copysize);
+    //     pos += copysize;
+    //     len -= copysize;
+    //     trng_idx = TRNG_SIZE_IN_BYTES - 1;
+    // }
+    // _trng_trigger();
+    // wait_trng4feed();
+    // trng_idx = 0;
+    int i;
+
+    for (i = 0; i < len; i++) {
+        buf[i] = (uint8_t)bl_rand();
+    }
+}
+
+int bl_rand()
+{
+    // unsigned int val;
+    // int counter = 0;
+
+    // do {
+    //     val = bl_sec_get_random_word();
+    //     if ((counter++) > TRNG_LOOP_COUNTER) {
+    //         puts("[BL] [SEC] Failed after loop " xstr(TRNG_LOOP_COUNTER) "\r\n");
+    //         break;
+    //     }
+    // } while (0 == val);
+    // val >>= 1;//leave signe bit alone
+    return rand();
+}
+
+#if 0
+void sec_trng_IRQHandler(void)
+{
+    uint32_t TRNGx = SEC_ENG_BASE;
+    uint32_t val;
+
+    if (aos_now_ms() < 1000 * 2) {
+        /*debug when boot*/
+        puts("[BL] [SEC] TRNG Handler\r\n");
+    }
+    val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_CLR_1T);
+    val = BL_CLR_REG_BIT(val, SEC_ENG_SE_TRNG_0_TRIG_1T);
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0, val);
+
+    blog_debug("random number is %08lx\r\n", trng_buffer[0]);
+    trng_buffer[0] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_0);
+    trng_buffer[1] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_1);
+    trng_buffer[2] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_2);
+    trng_buffer[3] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_3);
+    trng_buffer[4] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_4);
+    trng_buffer[5] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_5);
+    trng_buffer[6] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_6);
+    trng_buffer[7] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_7);
+}
+#endif
+
+int bl_sec_init(void)
+{
+#if 0
+    if (g_bl_sec_sha_mutex) {
+        return 0;
+    }
+    g_bl_sec_sha_mutex = bl_os_mutex_create();
+    _trng_trigger();
+    wait_trng4feed();
+    /*Trigger again*/
+    _trng_trigger();
+    wait_trng4feed();
+    bl_irq_register(SEC_TRNG_IRQn, sec_trng_IRQHandler);
+    bl_irq_enable(SEC_TRNG_IRQn);
+#endif
+
+    return 0;
+}
+
+int bl_exp_mod(uint32_t *src, uint32_t *result, int len, uint32_t *exp, int exp_len, uint32_t *mod, int mod_len)
+{
+    return 0;
+}
+
+int bl_sec_test(void)
+{
+    blog_print("------------------TRNG TEST---------------------------------\r\n");
+    blog_print("**********TRNG TEST rand[%08x]**************\r\n", bl_rand());
+    blog_print("**********TRNG TEST rand[%08x]**************\r\n", bl_rand());
+    blog_print("------------------------------------------------------------\r\n");
+
+    return 0;
+}
+
+void _dump_rsa_data(const uint8_t *data, int size)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        switch (i & 0xF) {
+            case 0x0:
+            {
+                blog_print("[%04X]:", i);
+                blog_print(" %02X", data[i]);
+            }
+            break;
+            case 0xF:
+            {
+                blog_print(" %02X", data[i]);
+                puts("\r\n");
+            }
+            break;
+            default:
+            {
+                blog_print(" %02X", data[i]);
+            }
+        }
+    }
+}
+
+static void RSA_Compare_Data(const uint8_t *expected, const uint8_t *input, uint32_t len)
+{
+    int i = 0, is_failed = 0;
+
+    for (i = 0; i < len; i++) {
+        if (input[i] != expected[i]) {
+            is_failed = 1;
+            blog_info("%s[%02d], %02x %02x\r\n",
+                input[i] ==expected[i] ? "S" : "F",
+                i,
+                input[i],
+                expected[i]
+            );
+        }
+    }
+    if (is_failed) {
+        blog_error("====== Failed %lu Bytes======\r\n", len);
+    } else {
+        blog_info("====== Success %lu Bytes=====\r\n", len);
+    }
+}
+
+static void _pka_test_case2(void)
+{
+    static const uint8_t n[256] = {
+        0xd8, 0xa6, 0x4f, 0xea, 0x28, 0xf9, 0xdf, 0x07, 0x04, 0x55, 0xfa, 0xfb, 0x50, 0x5d, 0xbe, 0xb6,
+        0x9f, 0x7b, 0x53, 0x96, 0xef, 0x05, 0x5e, 0x0a, 0xf5, 0x2d, 0xe3, 0x67, 0x78, 0x07, 0x6b, 0xf6,
+        0xb2, 0x17, 0xac, 0x2e, 0x51, 0x42, 0x84, 0xbb, 0xfe, 0x3e, 0x5f, 0x0c, 0x85, 0xc4, 0x9d, 0xd4,
+        0x8b, 0xd5, 0xfa, 0x17, 0x2d, 0xb1, 0x26, 0x81, 0xe7, 0x79, 0x07, 0x45, 0x82, 0x42, 0x22, 0x3d,
+        0x0d, 0x97, 0xcf, 0xde, 0xea, 0xb8, 0xba, 0x16, 0x05, 0x8a, 0x5b, 0x0f, 0xec, 0x07, 0x30, 0xa4,
+        0xc6, 0xbf, 0xff, 0x20, 0x52, 0x1b, 0x94, 0xad, 0xfa, 0xb7, 0x6e, 0x83, 0x14, 0x48, 0x58, 0x14,
+        0x99, 0xe7, 0xa3, 0x9e, 0xc1, 0x08, 0xbd, 0xfe, 0x20, 0x11, 0x56, 0xdb, 0x96, 0x0a, 0xbb, 0x0b,
+        0xbc, 0xd4, 0x37, 0x55, 0xf9, 0x9c, 0x6d, 0x5b, 0x87, 0x4e, 0x50, 0x9f, 0x24, 0x0e, 0x3a, 0x1a,
+        0x0c, 0x54, 0x67, 0xbd, 0x0f, 0x34, 0x03, 0x5e, 0x45, 0x5b, 0x93, 0x42, 0xbe, 0x71, 0xe6, 0xa7,
+        0xf9, 0x49, 0x1a, 0xb3, 0xb2, 0xfb, 0x0e, 0xee, 0x3d, 0xcf, 0x0c, 0x5a, 0xf8, 0xb5, 0x80, 0x42,
+        0x7c, 0x0c, 0x75, 0xc5, 0xe1, 0x17, 0x29, 0x39, 0x55, 0x2b, 0xb1, 0xf5, 0x72, 0x06, 0x9e, 0x54,
+        0x0b, 0x0e, 0xf2, 0x95, 0xc8, 0x5b, 0x69, 0xaf, 0x5b, 0x81, 0x97, 0xae, 0xb1, 0x6e, 0xc4, 0x6d,
+        0x95, 0xd8, 0x22, 0x1e, 0x39, 0xf0, 0x76, 0x54, 0x19, 0x96, 0x03, 0x4c, 0x25, 0x85, 0x2f, 0xe1,
+        0x84, 0xd7, 0xc1, 0x62, 0xe1, 0x9e, 0x9f, 0x1f, 0xd4, 0xb8, 0xf0, 0xc2, 0x68, 0x76, 0x7c, 0xcf,
+        0x43, 0x3e, 0x60, 0x93, 0xd0, 0x89, 0x65, 0xae, 0x72, 0xcd, 0xd6, 0x00, 0x0d, 0x91, 0x42, 0x90,
+        0x98, 0x02, 0xa9, 0xf6, 0x82, 0x1b, 0xb5, 0x22, 0xfd, 0xb6, 0xc2, 0x5c, 0xad, 0x86, 0x81, 0x1d,
+    };
+    static const uint8_t m[256] = {
+        0x30, 0x31, 0x36, 0x64, 0x61, 0x34, 0x31, 0x66, 0x34, 0x62, 0x66, 0x35, 0x38, 0x61, 0x36, 0x32,
+        0x35, 0x61, 0x61, 0x35, 0x63, 0x33, 0x30, 0x37, 0x62, 0x63, 0x64, 0x31, 0x61, 0x37, 0x35, 0x30,
+        0x33, 0x64, 0x62, 0x30, 0x36, 0x63, 0x39, 0x37, 0x62, 0x30, 0x39, 0x31, 0x39, 0x33, 0x38, 0x61,
+        0x32, 0x31, 0x62, 0x35, 0x66, 0x36, 0x38, 0x65, 0x33, 0x37, 0x37, 0x61, 0x62, 0x38, 0x39, 0x39,
+        0x62, 0x65, 0x66, 0x37, 0x63, 0x61, 0x31, 0x36, 0x35, 0x30, 0x65, 0x38, 0x66, 0x30, 0x38, 0x64,
+        0x37, 0x32, 0x38, 0x37, 0x64, 0x64, 0x30, 0x66, 0x36, 0x64, 0x32, 0x61, 0x64, 0x36, 0x34, 0x31,
+        0x32, 0x38, 0x38, 0x33, 0x38, 0x63, 0x35, 0x39, 0x35, 0x61, 0x32, 0x64, 0x31, 0x30, 0x65, 0x34,
+        0x36, 0x37, 0x61, 0x62, 0x35, 0x34, 0x35, 0x33, 0x63, 0x34, 0x65, 0x63, 0x37, 0x37, 0x30, 0x35,
+        0x33, 0x38, 0x61, 0x63, 0x39, 0x66, 0x38, 0x30, 0x36, 0x66, 0x30, 0x38, 0x66, 0x66, 0x33, 0x30,
+        0x38, 0x65, 0x36, 0x65, 0x64, 0x62, 0x35, 0x35, 0x34, 0x31, 0x66, 0x39, 0x66, 0x30, 0x34, 0x36,
+        0x63, 0x36, 0x37, 0x32, 0x62, 0x31, 0x32, 0x30, 0x37, 0x37, 0x35, 0x35, 0x62, 0x30, 0x35, 0x66,
+        0x35, 0x36, 0x64, 0x33, 0x61, 0x36, 0x36, 0x31, 0x37, 0x64, 0x63, 0x37, 0x35, 0x34, 0x64, 0x35,
+        0x65, 0x32, 0x30, 0x34, 0x63, 0x31, 0x36, 0x31, 0x36, 0x61, 0x31, 0x33, 0x65, 0x33, 0x62, 0x31,
+        0x34, 0x65, 0x38, 0x65, 0x32, 0x39, 0x63, 0x39, 0x35, 0x33, 0x33, 0x38, 0x36, 0x65, 0x65, 0x64,
+        0x62, 0x63, 0x30, 0x39, 0x34, 0x30, 0x37, 0x62, 0x39, 0x34, 0x33, 0x34, 0x38, 0x37, 0x37, 0x36,
+        0x36, 0x37, 0x63, 0x62, 0x33, 0x30, 0x39, 0x63, 0x36, 0x33, 0x30, 0x34, 0x32, 0x32, 0x36, 0x32,
+    };
+    static const uint8_t e[4] = {
+        0x00, 0x01, 0x00, 0x01,
+    };
+    static const uint8_t nprime[256] = {
+        0x38, 0x62, 0xc1, 0xf5, 0x55, 0x2d, 0x3d, 0x60, 0x5e, 0x42, 0xe1, 0x65, 0xde, 0xed, 0x35, 0xd5,
+        0xc5, 0x85, 0xe4, 0x4e, 0xeb, 0x74, 0xa5, 0x22, 0xb3, 0xed, 0x5f, 0x5b, 0xb1, 0xb9, 0xe9, 0x0a,
+        0x7d, 0xa5, 0x74, 0x58, 0xf8, 0xa1, 0xab, 0x17, 0x74, 0xd0, 0x07, 0xa3, 0x7f, 0xd2, 0x9b, 0x50,
+        0x2a, 0xed, 0x5e, 0xdc, 0x5a, 0x69, 0xfe, 0x0e, 0xb1, 0xd8, 0x53, 0x35, 0x9b, 0xef, 0x1d, 0x76,
+        0x52, 0x9e, 0x87, 0x3c, 0xb0, 0x82, 0x4e, 0x03, 0xdf, 0x75, 0xed, 0x09, 0x9f, 0x3d, 0x37, 0xf6,
+        0xe8, 0x0d, 0xc9, 0x2e, 0x81, 0xf2, 0x9d, 0x2e, 0xaa, 0xe6, 0x53, 0x79, 0x6b, 0x99, 0xef, 0x46,
+        0x36, 0xd9, 0x2e, 0x9d, 0x15, 0xd1, 0x7f, 0x23, 0x14, 0xb9, 0xeb, 0x33, 0xa7, 0xd4, 0x8e, 0x86,
+        0x60, 0xc9, 0xd9, 0x7c, 0xca, 0x54, 0x59, 0x57, 0x94, 0x1e, 0x52, 0x4d, 0xc8, 0x3f, 0x9b, 0x24,
+        0x28, 0x25, 0xcb, 0x57, 0xca, 0x8f, 0x16, 0x5a, 0x37, 0xc2, 0xc6, 0xae, 0xc5, 0xe7, 0xc4, 0x2e,
+        0xf3, 0x24, 0x1c, 0xb7, 0xe9, 0xf5, 0x92, 0x4e, 0xd4, 0x51, 0x50, 0xff, 0xde, 0x44, 0x3c, 0xae,
+        0x72, 0xbd, 0x16, 0x39, 0x63, 0x8a, 0x22, 0x9c, 0x95, 0xda, 0x21, 0xf0, 0x4c, 0x12, 0x36, 0x2d,
+        0x00, 0xad, 0xb3, 0x89, 0xb5, 0x09, 0x9e, 0x3d, 0x24, 0x81, 0xfc, 0xef, 0x99, 0x95, 0x22, 0x9d,
+        0xb3, 0x94, 0x39, 0x32, 0xdd, 0xc4, 0x2b, 0x2f, 0xb0, 0x13, 0xfe, 0xb5, 0x5e, 0xc7, 0x64, 0x93,
+        0x7a, 0xb5, 0x81, 0x93, 0x1f, 0x9f, 0x96, 0x1e, 0x7a, 0x5c, 0x8d, 0xde, 0x8f, 0xae, 0xd9, 0xc8,
+        0xdd, 0x35, 0x1e, 0x17, 0x47, 0xb6, 0xab, 0xed, 0xb6, 0x82, 0x22, 0x4c, 0x62, 0xbd, 0x12, 0x4e,
+        0x44, 0x5c, 0x48, 0x2b, 0x75, 0x63, 0x1c, 0xde, 0xfa, 0x15, 0x0d, 0xb1, 0x50, 0x31, 0xb6, 0xcb,
+    };
+    static const uint8_t inv_r[256] = {
+        0x2f, 0xb7, 0xf5, 0x4a, 0xd2, 0x19, 0xde, 0x24, 0x7c, 0xdb, 0xcd, 0x52, 0x6e, 0xbc, 0x2c, 0x5c,
+        0x76, 0x9a, 0x36, 0xc3, 0x87, 0x33, 0xf7, 0xe9, 0x3d, 0x5b, 0x3d, 0xcd, 0x33, 0x7a, 0x3b, 0x4e,
+        0x55, 0xf5, 0xd9, 0x42, 0x76, 0x63, 0x28, 0x7a, 0xa8, 0x7c, 0xf7, 0xd1, 0xf6, 0x0d, 0x26, 0xba,
+        0xbe, 0x9f, 0x35, 0xf4, 0x86, 0xc5, 0x93, 0x4c, 0xe8, 0x76, 0xda, 0x88, 0xb8, 0xbe, 0xad, 0x25,
+        0x6b, 0xe7, 0x44, 0x3b, 0x1c, 0x2c, 0x99, 0x15, 0xee, 0x33, 0x46, 0xc6, 0xe0, 0xb0, 0x39, 0x6d,
+        0x20, 0xb2, 0x68, 0xc7, 0x75, 0x41, 0x2c, 0xff, 0xcb, 0x93, 0x1d, 0x40, 0xd2, 0x0e, 0x64, 0xea,
+        0x2e, 0x0a, 0x55, 0x9f, 0x04, 0x9d, 0xfd, 0x5e, 0x24, 0xa9, 0x28, 0x5c, 0x2d, 0x1b, 0x29, 0x87,
+        0x61, 0x6b, 0x50, 0x6a, 0x31, 0x31, 0x43, 0x12, 0x13, 0xe3, 0x1f, 0x47, 0x8a, 0x11, 0xd2, 0x5b,
+        0x26, 0x5e, 0x79, 0x04, 0x0b, 0xa8, 0xb0, 0x36, 0x22, 0xda, 0x3c, 0x5e, 0xb9, 0x09, 0x48, 0xb0,
+        0x32, 0x38, 0x25, 0xec, 0xfd, 0x5e, 0xef, 0xff, 0x80, 0x33, 0x9f, 0x94, 0x8c, 0x6e, 0x2a, 0xfb,
+        0xbf, 0x65, 0x18, 0x98, 0x7e, 0xff, 0x41, 0xde, 0x00, 0x2f, 0xd2, 0x7d, 0xbf, 0x4c, 0x54, 0x4e,
+        0x1c, 0x46, 0xd6, 0xab, 0xf6, 0x07, 0x34, 0x63, 0xe3, 0x0b, 0x81, 0xa0, 0x94, 0x7d, 0xaf, 0x7e,
+        0x37, 0xd6, 0xc5, 0xa6, 0x4a, 0x90, 0x6c, 0x44, 0x6a, 0xd9, 0x0f, 0x20, 0xb2, 0xef, 0x22, 0xa0,
+        0xdf, 0x38, 0x2d, 0x0b, 0xb3, 0x03, 0xb2, 0xc8, 0xe6, 0x8d, 0x74, 0xbf, 0x45, 0x91, 0xe0, 0x22,
+        0x16, 0xbf, 0xc4, 0xda, 0x54, 0x26, 0xaa, 0x65, 0x85, 0x88, 0xc3, 0xfb, 0x9f, 0xfc, 0x14, 0xc4,
+        0xff, 0x8b, 0x88, 0x47, 0x5f, 0xb1, 0x55, 0xdf, 0x47, 0x5c, 0xc0, 0x27, 0x39, 0x7b, 0xe8, 0xad,
+    };
+    uint32_t result[64];
+    static const uint8_t encrypted[256] = {
+        0x9e, 0xf6, 0x6f, 0x46, 0xf5, 0x51, 0x1a, 0xbc, 0xc2, 0x9c, 0x49, 0x02, 0x21, 0x6c, 0x20, 0xae,
+        0x49, 0x91, 0xcd, 0xba, 0xb9, 0x4f, 0xaf, 0xfd, 0x8d, 0x9a, 0x27, 0xbc, 0x0b, 0x69, 0x57, 0xc4,
+        0xba, 0x18, 0xe1, 0x56, 0x45, 0x55, 0xbb, 0x3f, 0x7b, 0xca, 0x45, 0xb3, 0x9a, 0x0e, 0xd7, 0x64,
+        0x6e, 0x71, 0xce, 0xd3, 0x08, 0xc9, 0x4b, 0x97, 0xab, 0x24, 0xe4, 0x6c, 0xe3, 0xc7, 0x52, 0x97,
+        0x3c, 0x45, 0x17, 0x3b, 0x17, 0x0a, 0x90, 0x50, 0xed, 0x73, 0x4b, 0x49, 0x07, 0xee, 0x13, 0xaf,
+        0x47, 0x1e, 0xd0, 0x24, 0xb1, 0xd2, 0xc8, 0x09, 0x75, 0xf3, 0x14, 0x9c, 0x71, 0x99, 0xe3, 0x94,
+        0x5b, 0xf6, 0xef, 0x2e, 0x79, 0xf5, 0x1d, 0xdc, 0xa7, 0xc5, 0xed, 0x0a, 0x3f, 0x1d, 0x43, 0xd0,
+        0x19, 0x14, 0x3a, 0xb7, 0x35, 0xc2, 0x3f, 0xa1, 0x9c, 0x00, 0xde, 0xf6, 0x96, 0x55, 0xf8, 0x0c,
+        0x79, 0x08, 0x68, 0xf3, 0x84, 0x7c, 0x2e, 0x0c, 0x51, 0xb6, 0x5e, 0x9e, 0xcd, 0x50, 0xcc, 0x5f,
+        0x71, 0x99, 0xc1, 0x0d, 0xf0, 0x3c, 0xd0, 0x80, 0x02, 0xf0, 0x8f, 0x12, 0x3e, 0x49, 0xa4, 0x9b,
+        0x1f, 0x14, 0x05, 0xf2, 0x7b, 0x41, 0xc1, 0x3e, 0x8a, 0xb2, 0xab, 0x70, 0x28, 0x2f, 0x20, 0x94,
+        0x17, 0x65, 0xf3, 0x89, 0x28, 0x6d, 0xcd, 0x0c, 0xea, 0x03, 0x4a, 0x10, 0x9d, 0xf9, 0x2e, 0xf4,
+        0x64, 0x79, 0x7a, 0xec, 0x46, 0xb4, 0xdf, 0xce, 0x6a, 0x8e, 0xd8, 0x35, 0x62, 0xb3, 0x04, 0xea,
+        0xf9, 0xc4, 0xde, 0xba, 0x2a, 0x5e, 0xbf, 0x59, 0xfa, 0xef, 0x2a, 0x42, 0x18, 0xc9, 0xf5, 0x7a,
+        0x73, 0xb8, 0x67, 0x78, 0x97, 0x6d, 0x75, 0x4b, 0xdd, 0xfb, 0x9b, 0xe6, 0x4c, 0x04, 0x9c, 0x61,
+        0x5f, 0x9a, 0x12, 0xbf, 0x2e, 0x75, 0x63, 0xdd, 0x50, 0xba, 0x2c, 0xef, 0xb0, 0x9a, 0x65, 0x24,
+    };
+
+    Sec_Eng_PKA_Reset();
+    Sec_Eng_PKA_BigEndian_Enable();
+
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  0, (uint32_t*)n, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  1, (uint32_t*)nprime, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  2, (uint32_t*)m, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  3, (uint32_t*)e, 1, 0);
+
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 4, 0, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 5, 0, 1);
+    Sec_Eng_PKA_LMUL2N(
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            2048,
+            0
+    );
+    Sec_Eng_PKA_MREM(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            0
+    );
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_512, 2, 0, 1);
+
+    Sec_Eng_PKA_MEXP(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 3,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            1
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            1
+    );
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  1, (uint32_t*)inv_r, 64, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 4, 0, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 5, 0, 1);
+    Sec_Eng_PKA_LMUL(
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_MREM(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            0
+    );
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_512, 2, 0, 1);
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, sizeof(result));
+    RSA_Compare_Data(encrypted, (uint8_t*)result, sizeof(result));
+}
+
+static void __attribute__((unused)) dump_xgcd_step(uint32_t result[64])
+{
+    puts(" ---- PKA 8:0\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:1\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:2\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:3\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 3,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:4\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:5\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:6\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:7\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+}
+
+
+static void _pka_test_case_xgcd(void)
+{
+    int count = 0;
+    static const uint8_t n[256] = {
+        0xd8, 0xa6, 0x4f, 0xea, 0x28, 0xf9, 0xdf, 0x07, 0x04, 0x55, 0xfa, 0xfb, 0x50, 0x5d, 0xbe, 0xb6,
+        0x9f, 0x7b, 0x53, 0x96, 0xef, 0x05, 0x5e, 0x0a, 0xf5, 0x2d, 0xe3, 0x67, 0x78, 0x07, 0x6b, 0xf6,
+        0xb2, 0x17, 0xac, 0x2e, 0x51, 0x42, 0x84, 0xbb, 0xfe, 0x3e, 0x5f, 0x0c, 0x85, 0xc4, 0x9d, 0xd4,
+        0x8b, 0xd5, 0xfa, 0x17, 0x2d, 0xb1, 0x26, 0x81, 0xe7, 0x79, 0x07, 0x45, 0x82, 0x42, 0x22, 0x3d,
+        0x0d, 0x97, 0xcf, 0xde, 0xea, 0xb8, 0xba, 0x16, 0x05, 0x8a, 0x5b, 0x0f, 0xec, 0x07, 0x30, 0xa4,
+        0xc6, 0xbf, 0xff, 0x20, 0x52, 0x1b, 0x94, 0xad, 0xfa, 0xb7, 0x6e, 0x83, 0x14, 0x48, 0x58, 0x14,
+        0x99, 0xe7, 0xa3, 0x9e, 0xc1, 0x08, 0xbd, 0xfe, 0x20, 0x11, 0x56, 0xdb, 0x96, 0x0a, 0xbb, 0x0b,
+        0xbc, 0xd4, 0x37, 0x55, 0xf9, 0x9c, 0x6d, 0x5b, 0x87, 0x4e, 0x50, 0x9f, 0x24, 0x0e, 0x3a, 0x1a,
+        0x0c, 0x54, 0x67, 0xbd, 0x0f, 0x34, 0x03, 0x5e, 0x45, 0x5b, 0x93, 0x42, 0xbe, 0x71, 0xe6, 0xa7,
+        0xf9, 0x49, 0x1a, 0xb3, 0xb2, 0xfb, 0x0e, 0xee, 0x3d, 0xcf, 0x0c, 0x5a, 0xf8, 0xb5, 0x80, 0x42,
+        0x7c, 0x0c, 0x75, 0xc5, 0xe1, 0x17, 0x29, 0x39, 0x55, 0x2b, 0xb1, 0xf5, 0x72, 0x06, 0x9e, 0x54,
+        0x0b, 0x0e, 0xf2, 0x95, 0xc8, 0x5b, 0x69, 0xaf, 0x5b, 0x81, 0x97, 0xae, 0xb1, 0x6e, 0xc4, 0x6d,
+        0x95, 0xd8, 0x22, 0x1e, 0x39, 0xf0, 0x76, 0x54, 0x19, 0x96, 0x03, 0x4c, 0x25, 0x85, 0x2f, 0xe1,
+        0x84, 0xd7, 0xc1, 0x62, 0xe1, 0x9e, 0x9f, 0x1f, 0xd4, 0xb8, 0xf0, 0xc2, 0x68, 0x76, 0x7c, 0xcf,
+        0x43, 0x3e, 0x60, 0x93, 0xd0, 0x89, 0x65, 0xae, 0x72, 0xcd, 0xd6, 0x00, 0x0d, 0x91, 0x42, 0x90,
+        0x98, 0x02, 0xa9, 0xf6, 0x82, 0x1b, 0xb5, 0x22, 0xfd, 0xb6, 0xc2, 0x5c, 0xad, 0x86, 0x81, 0x1d,
+    };
+#if 0
+    static const uint8_t nprime[256] = {
+        0x38, 0x62, 0xc1, 0xf5, 0x55, 0x2d, 0x3d, 0x60, 0x5e, 0x42, 0xe1, 0x65, 0xde, 0xed, 0x35, 0xd5,
+        0xc5, 0x85, 0xe4, 0x4e, 0xeb, 0x74, 0xa5, 0x22, 0xb3, 0xed, 0x5f, 0x5b, 0xb1, 0xb9, 0xe9, 0x0a,
+        0x7d, 0xa5, 0x74, 0x58, 0xf8, 0xa1, 0xab, 0x17, 0x74, 0xd0, 0x07, 0xa3, 0x7f, 0xd2, 0x9b, 0x50,
+        0x2a, 0xed, 0x5e, 0xdc, 0x5a, 0x69, 0xfe, 0x0e, 0xb1, 0xd8, 0x53, 0x35, 0x9b, 0xef, 0x1d, 0x76,
+        0x52, 0x9e, 0x87, 0x3c, 0xb0, 0x82, 0x4e, 0x03, 0xdf, 0x75, 0xed, 0x09, 0x9f, 0x3d, 0x37, 0xf6,
+        0xe8, 0x0d, 0xc9, 0x2e, 0x81, 0xf2, 0x9d, 0x2e, 0xaa, 0xe6, 0x53, 0x79, 0x6b, 0x99, 0xef, 0x46,
+        0x36, 0xd9, 0x2e, 0x9d, 0x15, 0xd1, 0x7f, 0x23, 0x14, 0xb9, 0xeb, 0x33, 0xa7, 0xd4, 0x8e, 0x86,
+        0x60, 0xc9, 0xd9, 0x7c, 0xca, 0x54, 0x59, 0x57, 0x94, 0x1e, 0x52, 0x4d, 0xc8, 0x3f, 0x9b, 0x24,
+        0x28, 0x25, 0xcb, 0x57, 0xca, 0x8f, 0x16, 0x5a, 0x37, 0xc2, 0xc6, 0xae, 0xc5, 0xe7, 0xc4, 0x2e,
+        0xf3, 0x24, 0x1c, 0xb7, 0xe9, 0xf5, 0x92, 0x4e, 0xd4, 0x51, 0x50, 0xff, 0xde, 0x44, 0x3c, 0xae,
+        0x72, 0xbd, 0x16, 0x39, 0x63, 0x8a, 0x22, 0x9c, 0x95, 0xda, 0x21, 0xf0, 0x4c, 0x12, 0x36, 0x2d,
+        0x00, 0xad, 0xb3, 0x89, 0xb5, 0x09, 0x9e, 0x3d, 0x24, 0x81, 0xfc, 0xef, 0x99, 0x95, 0x22, 0x9d,
+        0xb3, 0x94, 0x39, 0x32, 0xdd, 0xc4, 0x2b, 0x2f, 0xb0, 0x13, 0xfe, 0xb5, 0x5e, 0xc7, 0x64, 0x93,
+        0x7a, 0xb5, 0x81, 0x93, 0x1f, 0x9f, 0x96, 0x1e, 0x7a, 0x5c, 0x8d, 0xde, 0x8f, 0xae, 0xd9, 0xc8,
+        0xdd, 0x35, 0x1e, 0x17, 0x47, 0xb6, 0xab, 0xed, 0xb6, 0x82, 0x22, 0x4c, 0x62, 0xbd, 0x12, 0x4e,
+        0x44, 0x5c, 0x48, 0x2b, 0x75, 0x63, 0x1c, 0xde, 0xfa, 0x15, 0x0d, 0xb1, 0x50, 0x31, 0xb6, 0xcb,
+    };
+    static const uint8_t inv_r[256] = {
+        0x2f, 0xb7, 0xf5, 0x4a, 0xd2, 0x19, 0xde, 0x24, 0x7c, 0xdb, 0xcd, 0x52, 0x6e, 0xbc, 0x2c, 0x5c,
+        0x76, 0x9a, 0x36, 0xc3, 0x87, 0x33, 0xf7, 0xe9, 0x3d, 0x5b, 0x3d, 0xcd, 0x33, 0x7a, 0x3b, 0x4e,
+        0x55, 0xf5, 0xd9, 0x42, 0x76, 0x63, 0x28, 0x7a, 0xa8, 0x7c, 0xf7, 0xd1, 0xf6, 0x0d, 0x26, 0xba,
+        0xbe, 0x9f, 0x35, 0xf4, 0x86, 0xc5, 0x93, 0x4c, 0xe8, 0x76, 0xda, 0x88, 0xb8, 0xbe, 0xad, 0x25,
+        0x6b, 0xe7, 0x44, 0x3b, 0x1c, 0x2c, 0x99, 0x15, 0xee, 0x33, 0x46, 0xc6, 0xe0, 0xb0, 0x39, 0x6d,
+        0x20, 0xb2, 0x68, 0xc7, 0x75, 0x41, 0x2c, 0xff, 0xcb, 0x93, 0x1d, 0x40, 0xd2, 0x0e, 0x64, 0xea,
+        0x2e, 0x0a, 0x55, 0x9f, 0x04, 0x9d, 0xfd, 0x5e, 0x24, 0xa9, 0x28, 0x5c, 0x2d, 0x1b, 0x29, 0x87,
+        0x61, 0x6b, 0x50, 0x6a, 0x31, 0x31, 0x43, 0x12, 0x13, 0xe3, 0x1f, 0x47, 0x8a, 0x11, 0xd2, 0x5b,
+        0x26, 0x5e, 0x79, 0x04, 0x0b, 0xa8, 0xb0, 0x36, 0x22, 0xda, 0x3c, 0x5e, 0xb9, 0x09, 0x48, 0xb0,
+        0x32, 0x38, 0x25, 0xec, 0xfd, 0x5e, 0xef, 0xff, 0x80, 0x33, 0x9f, 0x94, 0x8c, 0x6e, 0x2a, 0xfb,
+        0xbf, 0x65, 0x18, 0x98, 0x7e, 0xff, 0x41, 0xde, 0x00, 0x2f, 0xd2, 0x7d, 0xbf, 0x4c, 0x54, 0x4e,
+        0x1c, 0x46, 0xd6, 0xab, 0xf6, 0x07, 0x34, 0x63, 0xe3, 0x0b, 0x81, 0xa0, 0x94, 0x7d, 0xaf, 0x7e,
+        0x37, 0xd6, 0xc5, 0xa6, 0x4a, 0x90, 0x6c, 0x44, 0x6a, 0xd9, 0x0f, 0x20, 0xb2, 0xef, 0x22, 0xa0,
+        0xdf, 0x38, 0x2d, 0x0b, 0xb3, 0x03, 0xb2, 0xc8, 0xe6, 0x8d, 0x74, 0xbf, 0x45, 0x91, 0xe0, 0x22,
+        0x16, 0xbf, 0xc4, 0xda, 0x54, 0x26, 0xaa, 0x65, 0x85, 0x88, 0xc3, 0xfb, 0x9f, 0xfc, 0x14, 0xc4,
+        0xff, 0x8b, 0x88, 0x47, 0x5f, 0xb1, 0x55, 0xdf, 0x47, 0x5c, 0xc0, 0x27, 0x39, 0x7b, 0xe8, 0xad,
+    };
+#endif
+    static const uint8_t n_exp[256] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    };
+    static const uint8_t all_zero[256] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    uint32_t result[64];
+    uint8_t pka_a_eq_0 = 0;
+
+
+    (void) count;
+    Sec_Eng_PKA_Reset();
+    Sec_Eng_PKA_BigEndian_Enable();
+
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  1, (uint32_t*)n, 64, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 2, 0, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 3, 0, 1);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  0, (uint32_t*)n_exp, 64, 0);
+
+
+    Sec_Eng_PKA_LMUL2N(
+            SEC_ENG_PKA_REG_SIZE_512, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            2048,
+            0
+    );
+    Sec_Eng_PKA_LDIV(
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            SEC_ENG_PKA_REG_SIZE_512, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_MREM(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_512, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_512, 1, 0, 1);
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            1
+    );
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  4, (uint32_t*)all_zero, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  5, (uint32_t*)n_exp, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  6, (uint32_t*)n_exp, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  7, (uint32_t*)all_zero, 64, 0);
+
+    Sec_Eng_PKA_LMUL(
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            0
+    );
+    Sec_Eng_PKA_LSUB(
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            0
+    );
+    Sec_Eng_PKA_LMUL(
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            0
+    );
+    Sec_Eng_PKA_LSUB(
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            1
+    );
+
+#if 0
+    blog_info("Dumping Step count %d\r\n", count++);
+    dump_xgcd_step(result);
+#endif
+    while (!pka_a_eq_0) {
+        Sec_Eng_PKA_LDIV(
+                SEC_ENG_PKA_REG_SIZE_256, 0,
+                SEC_ENG_PKA_REG_SIZE_256, 2,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                0
+        );
+        Sec_Eng_PKA_MREM(
+                SEC_ENG_PKA_REG_SIZE_256, 3,
+                SEC_ENG_PKA_REG_SIZE_256, 2,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                0
+        );
+        Sec_Eng_PKA_LMUL(
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                SEC_ENG_PKA_REG_SIZE_256, 0,
+                SEC_ENG_PKA_REG_SIZE_256, 5,
+                0
+        );
+        Sec_Eng_PKA_LSUB(
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                SEC_ENG_PKA_REG_SIZE_256, 4,
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                0
+        );
+        Sec_Eng_PKA_LMUL(
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                SEC_ENG_PKA_REG_SIZE_256, 0,
+                SEC_ENG_PKA_REG_SIZE_256, 7,
+                0
+        );
+        Sec_Eng_PKA_LSUB(
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                SEC_ENG_PKA_REG_SIZE_256, 6,
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 2,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 4,
+                SEC_ENG_PKA_REG_SIZE_256, 5,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 5,
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 6,
+                SEC_ENG_PKA_REG_SIZE_256, 7,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 7,
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                1
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                SEC_ENG_PKA_REG_SIZE_256, 3,
+                1
+        );
+        Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  10, (uint32_t*)n_exp, 64, 0);
+        Sec_Eng_PKA_LCMP(
+                &pka_a_eq_0,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                SEC_ENG_PKA_REG_SIZE_256, 10
+        );
+#if 0
+        blog_info("Dumping Step count %d\r\n", count++);
+        dump_xgcd_step(result);
+#endif
+    }
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, sizeof(result));
+    //RSA_Compare_Data(encrypted, (uint8_t*)result, sizeof(result));
+}
+
+int bl_pka_test(void)
+{
+#if 0
+    bl_irq_register(SEC_PKA_IRQn, bl_sec_pka_IRQHandler);
+    bl_irq_enable(SEC_PKA_IRQn);
+#endif
+
+    _pka_test_case2();
+    _pka_test_case_xgcd();
+    _pka_test_case2();
+
+    return 0;
+}
+
+void bl_sec_pka_IRQHandler(void)
+{
+    puts("--->>> PKA IRQ\r\n");
+    SEC_Eng_IntMask(SEC_ENG_INT_PKA, MASK);
+}

+ 83 - 0
drv_wifi/bl_sec.h

@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_SEC_H__
+#define __BL_SEC_H__
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+
+/* copied SEC_Eng_SHA256_Ctx from stddrv */
+typedef struct {
+    uint32_t total[2];
+    uint32_t *shaBuf;
+    uint32_t *shaPadding;
+    uint8_t  shaFeed;
+} _bl_sha_SEC_Eng_SHA256_Ctx_t;
+
+/* copied SEC_ENG_SHA_Type from stddrv, SHA1_RSVD removed */
+typedef enum {
+    BL_SHA256,
+    BL_SHA224,
+    BL_SHA1,
+} bl_sha_type_t;
+
+typedef struct bl_sha_ctx {
+    _bl_sha_SEC_Eng_SHA256_Ctx_t sha_ctx;
+    uint32_t tmp[16];
+    uint32_t pad[16];
+} bl_sha_ctx_t;
+
+// extern BL_Sem_t g_bl_sec_sha_mutex;
+
+int bl_sec_init(void);
+int bl_sec_test(void);
+int bl_pka_test(void);
+int bl_sec_aes_init(void);
+int bl_sec_aes_enc(uint8_t *key, int keysize, uint8_t *input, uint8_t *output);
+int bl_sec_aes_test(void);
+uint32_t bl_sec_get_random_word(void);
+void bl_rand_stream(uint8_t *buf, int len);
+int bl_rand(void);
+/*SHA Engine API*/
+int bl_sec_sha_test(void);
+
+int bl_sha_mutex_take();
+int bl_sha_mutex_give();
+void bl_sha_init(bl_sha_ctx_t *ctx, const bl_sha_type_t type);
+int bl_sha_update(bl_sha_ctx_t *ctx, const uint8_t *input, uint32_t len);
+int bl_sha_finish(bl_sha_ctx_t *ctx, uint8_t *hash);
+int bl_sec_ccm_encrypt_and_tag(const uint8_t *key, unsigned int key_bytelen, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len);
+int bl_sec_ccm_auth_decrypt(const uint8_t *key, unsigned int key_bytelen, size_t length,const unsigned char *iv, size_t iv_len, const unsigned char *add,
+                             size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len);
+int bl_sec_aes_ecb_encrypt(const uint8_t *key, unsigned int key_bytelen, size_t length, const unsigned char *input, unsigned char *output);
+int bl_sec_aes_ecb_decrypt(const uint8_t *key, unsigned int key_bytelen, size_t length, const unsigned char *input, unsigned char *output);
+#endif

+ 273 - 0
drv_wifi/bl_wifi.c

@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#undef ARCH_RISCV
+#include <rtthread.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "bl_wifi.h"
+// #include "bl_irq.h"
+
+typedef struct _bl_wifi_env {
+    uint8_t sta_mac_addr_board[6];
+    uint8_t sta_mac_addr_usr[6];
+    uint8_t ap_mac_addr_board[6];
+    uint8_t ap_mac_addr_usr[6];
+    uint8_t country_code;
+
+    bl_wifi_ap_info_t ap_info;
+    uint8_t ap_info_en;
+
+    bl_wifi_ap_info_t sta_info;
+    uint8_t sta_info_en;
+} bl_wifi_env_t;
+
+bl_wifi_env_t wifi_env = {
+    .sta_mac_addr_board = {0x18, 0xb9, 0x05, 0x88, 0x88, 0x88}
+};
+
+
+/****************************************************************************/ /**
+ * @brief  set wifi core clock divider
+ *
+ * @param  clkDiv: divider
+ *
+ * @return SUCCESS or ERROR
+ *
+*******************************************************************************/
+/* 0x3B0 : wifi_cfg0 */
+#define GLB_WIFI_CFG0_OFFSET                                    (0x3B0)
+#define GLB_WIFI_MAC_CORE_DIV                                   GLB_WIFI_MAC_CORE_DIV
+#define GLB_WIFI_MAC_CORE_DIV_POS                               (0U)
+#define GLB_WIFI_MAC_CORE_DIV_LEN                               (4U)
+#define GLB_WIFI_MAC_CORE_DIV_MSK                               (((1U<<GLB_WIFI_MAC_CORE_DIV_LEN)-1)<<GLB_WIFI_MAC_CORE_DIV_POS)
+#define GLB_WIFI_MAC_CORE_DIV_UMSK                              (~(((1U<<GLB_WIFI_MAC_CORE_DIV_LEN)-1)<<GLB_WIFI_MAC_CORE_DIV_POS))
+#define GLB_WIFI_MAC_WT_DIV                                     GLB_WIFI_MAC_WT_DIV
+#define GLB_WIFI_MAC_WT_DIV_POS                                 (4U)
+#define GLB_WIFI_MAC_WT_DIV_LEN                                 (4U)
+#define GLB_WIFI_MAC_WT_DIV_MSK                                 (((1U<<GLB_WIFI_MAC_WT_DIV_LEN)-1)<<GLB_WIFI_MAC_WT_DIV_POS)
+#define GLB_WIFI_MAC_WT_DIV_UMSK                                (~(((1U<<GLB_WIFI_MAC_WT_DIV_LEN)-1)<<GLB_WIFI_MAC_WT_DIV_POS))
+BL_Err_Type GLB_Set_WiFi_Core_CLK(uint8_t clkDiv)
+{
+    uint32_t tmpVal = 0;
+
+    CHECK_PARAM((clkDiv <= 0xF));
+
+    tmpVal = BL_RD_REG(GLB_BASE, GLB_WIFI_CFG0);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, GLB_WIFI_MAC_CORE_DIV, clkDiv);
+    BL_WR_REG(GLB_BASE, GLB_WIFI_CFG0, tmpVal);
+
+    return SUCCESS;
+}
+
+int bl_wifi_clock_enable(void)
+{
+    static int called = 0;
+    if (0 == called) {
+        called = 1;
+        //GLB_Set_System_CLK(PLL_XTAL_38P4M, GLB_PLL_CLK_160M);
+        GLB_Set_WiFi_Core_CLK(1);//0: 80MHZ, 1: 40MHZ
+    }
+    return 0;
+}
+
+void mac_irq(void);
+void bl_irq_handler(void);
+
+void mac_irq_callback(int irq, void *arg)
+{
+    mac_irq();
+}
+
+void bl_irq_callback(int irq, void *arg)
+{
+    bl_irq_handler();
+}
+
+int bl_wifi_enable_irq(void)
+{
+    // bl_irq_register(WIFI_IRQn, mac_irq);
+    // bl_irq_register(WIFI_IPC_PUBLIC_IRQn, bl_irq_handler);
+    // bl_irq_enable(WIFI_IRQn);
+    // bl_irq_enable(WIFI_IPC_PUBLIC_IRQn);
+
+    bflb_irq_attach(WIFI_IRQn, mac_irq_callback, NULL);
+    bflb_irq_attach(WIFI_IPC_PUBLIC_IRQn, bl_irq_callback, NULL);
+    bflb_irq_enable(WIFI_IRQn);	
+    bflb_irq_enable(WIFI_IPC_PUBLIC_IRQn);	
+
+    //NVIC_SetPriority((IRQn_Type)5, 0);
+    //NVIC_EnableIRQ((IRQn_Type)5);
+    puts("Enable BMX IRQ\r\n");
+    //NVIC_EnableIRQ((IRQn_Type)0);
+    //NVIC_EnableIRQ((IRQn_Type)1);
+    //NVIC_EnableIRQ((IRQn_Type)2);
+    //NVIC_EnableIRQ((IRQn_Type)3);
+    //NVIC_EnableIRQ((IRQn_Type)4);
+    //*(uint32_t*)0x40000050 = ((0xF << 28) | (1 << 24));
+
+    return 0;
+}
+
+
+int bl_wifi_sta_mac_addr_set(uint8_t mac[6])
+{
+    memcpy(wifi_env.sta_mac_addr_board, mac, 6);
+    return 0;
+}
+
+int bl_wifi_ap_mac_addr_set(uint8_t mac[6])
+{
+    memcpy(wifi_env.ap_mac_addr_board, mac, 6);
+    return 0;
+}
+
+int bl_wifi_mac_addr_set(uint8_t mac[6])
+{
+    memcpy(wifi_env.sta_mac_addr_usr, mac, 6);
+    return 0;
+}
+
+int bl_wifi_mac_addr_get(uint8_t mac[6])
+{
+    memcpy(mac, wifi_env.sta_mac_addr_board, 6);
+    return 0;
+}
+
+
+int bl_wifi_country_code_set(uint8_t country_code)
+{
+    wifi_env.country_code = country_code;
+    return 0;
+}
+
+#if 0
+int bl_wifi_power_table_set(bl_tx_pwr_tbl_t* tx_pwr_tbl)
+{
+    bl60x_fw_rf_tx_power_table_set(tx_pwr_tbl);
+    return 0;
+}
+#endif
+
+int bl_wifi_ap_info_set(uint8_t* ssid, uint8_t ssid_len,
+                      uint8_t* psk, uint8_t psk_len,
+                      uint8_t chan)
+{
+    memset(&wifi_env.ap_info, 0, sizeof(bl_wifi_ap_info_t));
+    memcpy(wifi_env.ap_info.ssid, ssid, ssid_len);
+    memcpy(wifi_env.ap_info.psk, psk, psk_len);
+    wifi_env.ap_info.chan = chan;
+    wifi_env.ap_info_en = 1;
+    return 0;
+}
+
+int bl_wifi_ap_info_get(bl_wifi_ap_info_t* ap_info)
+{
+    if (wifi_env.ap_info_en != 1) {
+        return -1;
+    }
+    memcpy(ap_info, &wifi_env.ap_info, sizeof(bl_wifi_ap_info_t));
+    return 0;
+}
+
+int bl_wifi_sta_info_set(uint8_t* ssid, uint8_t ssid_len, uint8_t* psk, uint8_t psk_len, int autoconnect)
+{
+    memset(&wifi_env.sta_info, 0, sizeof(bl_wifi_ap_info_t));
+    memcpy(wifi_env.sta_info.ssid, ssid, ssid_len);
+    memcpy(wifi_env.sta_info.psk, psk, psk_len);
+    wifi_env.sta_info_en = autoconnect;
+    return 0;
+}
+
+int bl_wifi_sta_info_get(bl_wifi_ap_info_t* sta_info)
+{
+    if (wifi_env.sta_info_en != 1) {
+        return -1;
+    }
+    memcpy(sta_info, &wifi_env.sta_info, sizeof(bl_wifi_ap_info_t));
+    return 0;
+}
+
+#if 0
+int bl_wifi_netif_init(void)
+{
+    struct netif *netif = &wifi_netif;
+    ip4_addr_t ipaddr;
+    ip4_addr_t netmask;
+    ip4_addr_t gw;
+
+    ipaddr.addr = 0;
+    netmask.addr = 0;
+    gw.addr = 0;
+
+    netif->hwaddr[0] =  0x18;
+    netif->hwaddr[1] =  0xB9;
+    netif->hwaddr[2] =  0x05;
+    netif->hwaddr[3] =  0x88;
+    netif->hwaddr[4] =  0x88;
+    netif->hwaddr[5] =  0x88;
+
+    /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
+    *  struct ip_addr *netmask, struct ip_addr *gw,
+    *  void *state, err_t (* init)(struct netif *netif),
+    *  err_t (* input)(struct pbuf *p, struct netif *netif))
+    *
+    *  Adds your network interface to the netif_list. Allocate a struct
+    *  netif and pass a pointer to this structure as the first argument.
+    *  Give pointers to cleared ip_addr structures when using DHCP,
+    *  or fill them with sane numbers otherwise. The state pointer may be NULL.
+    *
+    * The init function pointer must point to a initialization function for
+    * your ethernet netif interface. The following code illustrates it's use.*/
+
+    netif_add(netif, &ipaddr, &netmask, &gw, NULL, &bl606a0_wifi_netif_init, &tcpip_input);
+    netif->name[0] = 's';
+    netif->name[1] = 't';
+    netif->flags |= NETIF_FLAG_LINK_UP;
+    netif_set_default(netif);
+    netif_set_up(netif);
+    netifapi_dhcp_start(netif);
+
+    return 0;
+}
+#endif

+ 52 - 0
drv_wifi/bl_wifi.h

@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_WIFI_H__
+#define __BL_WIFI_H__
+typedef struct bl_wifi_ap_info {
+    uint8_t ssid[33];
+    uint8_t psk[65];
+    uint8_t chan;
+} bl_wifi_ap_info_t;
+
+
+int bl_wifi_enable_irq(void);
+int bl_wifi_clock_enable(void);
+int bl_wifi_sta_mac_addr_set(uint8_t mac[6]);
+int bl_wifi_ap_mac_addr_set(uint8_t mac[6]);
+int bl_wifi_mac_addr_set(uint8_t mac[6]);
+int bl_wifi_country_code_set(uint8_t country_code);
+int bl_wifi_ap_info_set(uint8_t* ssid, uint8_t ssid_len,
+                      uint8_t* psk, uint8_t psk_len,
+                      uint8_t chan);
+int bl_wifi_mac_addr_get(uint8_t mac[6]);
+int bl_wifi_ap_info_get(bl_wifi_ap_info_t* ap_info);
+int bl_wifi_sta_info_set(uint8_t* ssid, uint8_t ssid_len, uint8_t* psk, uint8_t psk_len, int autoconnect);
+int bl_wifi_sta_info_get(bl_wifi_ap_info_t* sta_info);
+#endif

+ 238 - 0
drv_wifi/hosal_adc.h

@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_ADC_H_
+#define __HOSAL_ADC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "hosal_dma.h"
+
+/** @addtogroup hosal_adc ADC
+ *  HOSAL ADC API
+ *
+ *  @{
+ */
+
+#define HOSAL_WAIT_FOREVER        0xFFFFFFFFU  /**< @brief Define the wait forever timeout macro */
+
+/**
+ * @brief ADC interrupt events
+ */
+typedef enum __ADC_INT_EVENTS__{
+    HOSAL_ADC_INT_OV,         /**< @brief Overrun error */
+    HOSAL_ADC_INT_EOS,        /**< @brief End of sample */
+    HOSAL_ADC_INT_DMA_TRH,    /**< @brief DMA transceive half */
+    HOSAL_ADC_INT_DMA_TRC,    /**< @brief DMA transceive complete */
+    HOSAL_ADC_INT_DMA_TRE,    /**< @briefDMA transceive error */
+} hosal_adc_event_t;
+
+/**
+ * @brief ADC data type
+ */
+typedef struct {
+    uint32_t size;  /**< @brief sampled data size */
+    void *data;     /**< @brief sampled data, aligned with resolution (until the next power of two) */
+} hosal_adc_data_t;
+
+/**
+ * @brief ADC MODE type
+ */
+typedef enum {
+    HOSAL_ADC_ONE_SHOT,       /**< @brief Single time sampling */
+    HOSAL_ADC_CONTINUE        /**< @brief Continuous sampling */
+} hosal_adc_sample_mode_t;
+
+/**
+ * @brief Define ADC config args
+ */
+typedef struct {
+    uint32_t sampling_freq;             /**< @brief sampling frequency in Hz */
+    uint32_t pin;                        /**< @brief adc pin */
+    hosal_adc_sample_mode_t mode;       /**< @brief adc sampling mode */
+    uint8_t sample_resolution;          /**< @brief adc sampling resolution */
+} hosal_adc_config_t;
+
+/**
+ * @brief ADC interrupt function
+ *
+ *@param[in] parg  Set the custom parameters specified
+ *
+ */
+typedef void (*hosal_adc_irq_t)(void *parg);
+
+/**
+ * @brief Define ADC dev hosal handle
+ */
+typedef struct {
+    uint8_t port;                    /**< @brief adc port */
+    hosal_adc_config_t config;        /**< @brief adc config */
+    hosal_dma_chan_t dma_chan;        /**< @brief adc dma channel */
+    hosal_adc_irq_t cb;               /**< @brief adc callback */
+    void *p_arg;                      /**< @brief p_arg data */
+    void *priv;                       /**< @brief priv data */
+} hosal_adc_dev_t;
+
+/**
+ * @brief ADC interrupt callback
+ *
+ * @param[in] parg  Set the custom parameters specified when the callback function is set
+ *
+ */
+typedef void (*hosal_adc_cb_t)(hosal_adc_event_t event, void *data, uint32_t size);
+
+/**
+ * @brief Initialises an ADC interface, Prepares an ADC hardware interface for sampling
+ *
+ * @param[in]  adc  the interface which should be initialised
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_init(hosal_adc_dev_t *adc);
+
+/**
+ * @brief Add a channel to an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[in]   channel  adc channel
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_add_channel(hosal_adc_dev_t *adc, uint32_t channel);
+
+/**
+ * @brief Remove a channel to an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[in]   channel  adc channel
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_remove_channel(hosal_adc_dev_t *adc, uint32_t channel);
+
+/**
+ * @brief Takes adc device handle from an ADC interface
+ *
+ * @return
+ *  - other  get adc device success
+ *  - NULL   if an error occurred with any step
+ */
+hosal_adc_dev_t *hosal_adc_device_get(void);
+
+/**
+ * @brief Takes a single sample from an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[in]   channel  adc channel
+ * @param[in]   timeout  ms timeout
+ *
+ * @return
+ *  - other  get adc data success
+ *  - -1     if an error occurred with any step
+ */
+int hosal_adc_value_get(hosal_adc_dev_t *adc, uint32_t channel, uint32_t timeout);
+
+/**
+ * @brief Takes a tsen sample from an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ *
+ * @return
+ *  - other  get adc data success
+ *  - -1     if an error occurred with any step
+ */
+int hosal_adc_tsen_value_get(hosal_adc_dev_t *adc);
+
+/**
+ * @brief ADC sampling cb register
+ *
+ * @param [in]   adc          the ADC interface
+ * @param [in]   cb           Non-zero pointer is the sample callback handler
+ *                            NULL pointer for send unregister operation
+ *                            adc in cb must be the same pointer with adc pointer passed to hosal_adc_sample_cb_reg
+ *                            driver must notify upper layer by calling cb if ADC data is ready in HW or memory(DMA)
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_sample_cb_reg(hosal_adc_dev_t *adc, hosal_adc_cb_t cb);
+
+/**
+ * @brief ADC sampling start
+ *
+ * @param[in]   adc             the ADC interface
+ * @param[in]   data            adc data buffer
+ * @param[in]   size            data buffer size aligned with resolution (until the next power of two)
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_start(hosal_adc_dev_t *adc, void *data, uint32_t size);
+
+/**
+ * @brief ADC sampling stop
+ *
+ * @param[in]   adc             the ADC interface
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_stop(hosal_adc_dev_t *adc);
+
+/**
+ * @brief De-initialises an ADC interface, Turns off an ADC hardware interface
+ *
+ * @param[in]  adc  the interface which should be de-initialised
+ *
+ * @return
+ *  - 0    on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_adc_finalize(hosal_adc_dev_t *adc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_ADC_H_ */
+
+/* end of file */

+ 152 - 0
drv_wifi/hosal_dma.h

@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_DMA_H__
+#define __HOSAL_DMA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_dma DMA
+ *  HOSAL DMA API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+/**
+ * @brief DMA irq callback function flag
+ */
+#define HOSAL_DMA_INT_TRANS_COMPLETE      0
+#define HOSAL_DMA_INT_TRANS_ERROR         1
+
+/**
+ * @brief DMA irq callback function
+ */
+typedef void (*hosal_dma_irq_t)(void *p_arg, uint32_t flag);
+
+/**
+ * @brief DMA channel describe
+ */
+struct hosal_dma_chan {
+    uint8_t used;
+    hosal_dma_irq_t callback;
+    void *p_arg;
+};
+
+/**
+ * @brief DMA device type
+ */
+typedef struct hosal_dma_dev {
+    int max_chans;
+    struct hosal_dma_chan *used_chan;
+    void *priv;
+} hosal_dma_dev_t;
+
+/**
+ * @brief DMA channel
+ */
+typedef int hosal_dma_chan_t;
+
+/**
+ * @brief Initialises a DMA interface
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_init(void);
+
+/**
+ * @brief Request a DMA channel
+ *
+ * @param[in] flag : DMA CHAN REQUEST FLAG
+ *
+ * @return  < 0 : an error occurred with any step, otherwise is DMA channel number
+ */
+hosal_dma_chan_t hosal_dma_chan_request(int flag);
+
+/**
+ * @brief Release a DMA channel
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_release(hosal_dma_chan_t chan);
+
+/**
+ * @brief DMA channel trans start
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_start(hosal_dma_chan_t chan);
+
+/**
+ * @brief DMA channel trans stop
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_stop(hosal_dma_chan_t chan);
+
+/**
+ * @brief DMA irq callback set
+ *
+ * @param[in] chan : DMA channel number
+ * @param[in] pfn : callback function
+ * @param[in] arg : callback function parameter
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_irq_callback_set(hosal_dma_chan_t chan, hosal_dma_irq_t pfn, void *p_arg);
+
+/**
+ * @brief Deinitialises a DMA interface
+ *
+ * @param[in]  DMA the interface which should be deinitialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_finalize(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_DMA_H__ */
+
+/* end of file */

+ 558 - 0
drv_wifi/sec_eng_reg.h

@@ -0,0 +1,558 @@
+/**
+  ******************************************************************************
+  * @file    sec_eng_reg.h
+  * @version V1.0
+  * @date    2022-08-15
+  * @brief   This file is the description of.IP register
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+#ifndef __HARDWARE_SEC_ENG_H__
+#define __HARDWARE_SEC_ENG_H__
+
+/****************************************************************************
+ * Pre-processor Definitions
+****************************************************************************/
+
+/* Register offsets *********************************************************/
+
+#define SEC_ENG_SE_SHA_0_CTRL_OFFSET        (0x0)   /* se_sha_0_ctrl */
+#define SEC_ENG_SE_SHA_0_MSA_OFFSET         (0x4)   /* se_sha_0_msa */
+#define SEC_ENG_SE_SHA_0_STATUS_OFFSET      (0x8)   /* se_sha_0_status */
+#define SEC_ENG_SE_SHA_0_ENDIAN_OFFSET      (0xC)   /* se_sha_0_endian */
+#define SEC_ENG_SE_SHA_0_HASH_L_0_OFFSET    (0x10)  /* se_sha_0_hash_l_0 */
+#define SEC_ENG_SE_SHA_0_HASH_L_1_OFFSET    (0x14)  /* se_sha_0_hash_l_1 */
+#define SEC_ENG_SE_SHA_0_HASH_L_2_OFFSET    (0x18)  /* se_sha_0_hash_l_2 */
+#define SEC_ENG_SE_SHA_0_HASH_L_3_OFFSET    (0x1C)  /* se_sha_0_hash_l_3 */
+#define SEC_ENG_SE_SHA_0_HASH_L_4_OFFSET    (0x20)  /* se_sha_0_hash_l_4 */
+#define SEC_ENG_SE_SHA_0_HASH_L_5_OFFSET    (0x24)  /* se_sha_0_hash_l_5 */
+#define SEC_ENG_SE_SHA_0_HASH_L_6_OFFSET    (0x28)  /* se_sha_0_hash_l_6 */
+#define SEC_ENG_SE_SHA_0_HASH_L_7_OFFSET    (0x2C)  /* se_sha_0_hash_l_7 */
+#define SEC_ENG_SE_SHA_0_HASH_H_0_OFFSET    (0x30)  /* se_sha_0_hash_h_0 */
+#define SEC_ENG_SE_SHA_0_HASH_H_1_OFFSET    (0x34)  /* se_sha_0_hash_h_1 */
+#define SEC_ENG_SE_SHA_0_HASH_H_2_OFFSET    (0x38)  /* se_sha_0_hash_h_2 */
+#define SEC_ENG_SE_SHA_0_HASH_H_3_OFFSET    (0x3C)  /* se_sha_0_hash_h_3 */
+#define SEC_ENG_SE_SHA_0_HASH_H_4_OFFSET    (0x40)  /* se_sha_0_hash_h_4 */
+#define SEC_ENG_SE_SHA_0_HASH_H_5_OFFSET    (0x44)  /* se_sha_0_hash_h_5 */
+#define SEC_ENG_SE_SHA_0_HASH_H_6_OFFSET    (0x48)  /* se_sha_0_hash_h_6 */
+#define SEC_ENG_SE_SHA_0_HASH_H_7_OFFSET    (0x4C)  /* se_sha_0_hash_h_7 */
+#define SEC_ENG_SE_SHA_0_LINK_OFFSET        (0x50)  /* se_sha_0_link */
+#define SEC_ENG_SE_SHA_0_CTRL_PROT_OFFSET   (0xFC)  /* se_sha_0_ctrl_prot */
+#define SEC_ENG_SE_AES_0_CTRL_OFFSET        (0x100) /* se_aes_0_ctrl */
+#define SEC_ENG_SE_AES_0_MSA_OFFSET         (0x104) /* se_aes_0_msa */
+#define SEC_ENG_SE_AES_0_MDA_OFFSET         (0x108) /* se_aes_0_mda */
+#define SEC_ENG_SE_AES_0_STATUS_OFFSET      (0x10C) /* se_aes_0_status */
+#define SEC_ENG_SE_AES_0_IV_0_OFFSET        (0x110) /* se_aes_0_iv_0 */
+#define SEC_ENG_SE_AES_0_IV_1_OFFSET        (0x114) /* se_aes_0_iv_1 */
+#define SEC_ENG_SE_AES_0_IV_2_OFFSET        (0x118) /* se_aes_0_iv_2 */
+#define SEC_ENG_SE_AES_0_IV_3_OFFSET        (0x11C) /* se_aes_0_iv_3 */
+#define SEC_ENG_SE_AES_0_KEY_0_OFFSET       (0x120) /* se_aes_0_key_0 */
+#define SEC_ENG_SE_AES_0_KEY_1_OFFSET       (0x124) /* se_aes_0_key_1 */
+#define SEC_ENG_SE_AES_0_KEY_2_OFFSET       (0x128) /* se_aes_0_key_2 */
+#define SEC_ENG_SE_AES_0_KEY_3_OFFSET       (0x12C) /* se_aes_0_key_3 */
+#define SEC_ENG_SE_AES_0_KEY_4_OFFSET       (0x130) /* se_aes_0_key_4 */
+#define SEC_ENG_SE_AES_0_KEY_5_OFFSET       (0x134) /* se_aes_0_key_5 */
+#define SEC_ENG_SE_AES_0_KEY_6_OFFSET       (0x138) /* se_aes_0_key_6 */
+#define SEC_ENG_SE_AES_0_KEY_7_OFFSET       (0x13C) /* se_aes_0_key_7 */
+#define SEC_ENG_SE_AES_0_KEY_SEL_OFFSET     (0x140) /* se_aes_0_key_sel */
+#define SEC_ENG_SE_AES_1_KEY_SEL_OFFSET     (0x144) /* se_aes_1_key_sel */
+#define SEC_ENG_SE_AES_0_ENDIAN_OFFSET      (0x148) /* se_aes_0_endian */
+#define SEC_ENG_SE_AES_0_SBOOT_OFFSET       (0x14C) /* se_aes_0_sboot */
+#define SEC_ENG_SE_AES_0_LINK_OFFSET        (0x150) /* se_aes_0_link */
+#define SEC_ENG_SE_AES_0_CTRL_PROT_OFFSET   (0x1FC) /* se_aes_0_ctrl_prot */
+#define SEC_ENG_SE_TRNG_0_CTRL_0_OFFSET     (0x200) /* se_trng_0_ctrl_0 */
+#define SEC_ENG_SE_TRNG_0_STATUS_OFFSET     (0x204) /* se_trng_0_status */
+#define SEC_ENG_SE_TRNG_0_DOUT_0_OFFSET     (0x208) /* se_trng_0_dout_0 */
+#define SEC_ENG_SE_TRNG_0_DOUT_1_OFFSET     (0x20C) /* se_trng_0_dout_1 */
+#define SEC_ENG_SE_TRNG_0_DOUT_2_OFFSET     (0x210) /* se_trng_0_dout_2 */
+#define SEC_ENG_SE_TRNG_0_DOUT_3_OFFSET     (0x214) /* se_trng_0_dout_3 */
+#define SEC_ENG_SE_TRNG_0_DOUT_4_OFFSET     (0x218) /* se_trng_0_dout_4 */
+#define SEC_ENG_SE_TRNG_0_DOUT_5_OFFSET     (0x21C) /* se_trng_0_dout_5 */
+#define SEC_ENG_SE_TRNG_0_DOUT_6_OFFSET     (0x220) /* se_trng_0_dout_6 */
+#define SEC_ENG_SE_TRNG_0_DOUT_7_OFFSET     (0x224) /* se_trng_0_dout_7 */
+#define SEC_ENG_SE_TRNG_0_TEST_OFFSET       (0x228) /* se_trng_0_test */
+#define SEC_ENG_SE_TRNG_0_CTRL_1_OFFSET     (0x22C) /* se_trng_0_ctrl_1 */
+#define SEC_ENG_SE_TRNG_0_CTRL_2_OFFSET     (0x230) /* se_trng_0_ctrl_2 */
+#define SEC_ENG_SE_TRNG_0_CTRL_3_OFFSET     (0x234) /* se_trng_0_ctrl_3 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_0_OFFSET (0x240) /* se_trng_0_test_out_0 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_1_OFFSET (0x244) /* se_trng_0_test_out_1 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_2_OFFSET (0x248) /* se_trng_0_test_out_2 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_3_OFFSET (0x24C) /* se_trng_0_test_out_3 */
+#define SEC_ENG_SE_TRNG_0_CTRL_PROT_OFFSET  (0x2FC) /* se_trng_0_ctrl_prot */
+#define SEC_ENG_SE_PKA_0_CTRL_0_OFFSET      (0x300) /* se_pka_0_ctrl_0 */
+#define SEC_ENG_SE_PKA_0_SEED_OFFSET        (0x30C) /* se_pka_0_seed */
+#define SEC_ENG_SE_PKA_0_CTRL_1_OFFSET      (0x310) /* se_pka_0_ctrl_1 */
+#define SEC_ENG_SE_PKA_0_RW_OFFSET          (0x340) /* se_pka_0_rw */
+#define SEC_ENG_SE_PKA_0_RW_BURST_OFFSET    (0x360) /* se_pka_0_rw_burst */
+#define SEC_ENG_SE_PKA_0_CTRL_PROT_OFFSET   (0x3FC) /* se_pka_0_ctrl_prot */
+#define SEC_ENG_SE_CDET_0_CTRL_0_OFFSET     (0x400) /* se_cdet_0_ctrl_0 */
+#define SEC_ENG_SE_CDET_0_CTRL_1_OFFSET     (0x404) /* se_cdet_0_ctrl_1 */
+#define SEC_ENG_SE_CDET_0_CTRL_2_OFFSET     (0x408) /* se_cdet_0_ctrl_2 */
+#define SEC_ENG_SE_CDET_0_CTRL_3_OFFSET     (0x40C) /* se_cdet_0_ctrl_3 */
+#define SEC_ENG_SE_CDET_0_CTRL_PROT_OFFSET  (0x4FC) /* se_cdet_0_ctrl_prot */
+#define SEC_ENG_SE_GMAC_0_CTRL_0_OFFSET     (0x500) /* se_gmac_0_ctrl_0 */
+#define SEC_ENG_SE_GMAC_0_LCA_OFFSET        (0x504) /* se_gmac_0_lca */
+#define SEC_ENG_SE_GMAC_0_STATUS_OFFSET     (0x508) /* se_gmac_0_status */
+#define SEC_ENG_SE_GMAC_0_CTRL_PROT_OFFSET  (0x5FC) /* se_gmac_0_ctrl_prot */
+#define SEC_ENG_SE_CTRL_PROT_RD_OFFSET      (0xF00) /* se_ctrl_prot_rd */
+#define SEC_ENG_SE_CTRL_RESERVED_0_OFFSET   (0xF04) /* se_ctrl_reserved_0 */
+#define SEC_ENG_SE_CTRL_RESERVED_1_OFFSET   (0xF08) /* se_ctrl_reserved_1 */
+#define SEC_ENG_SE_CTRL_RESERVED_2_OFFSET   (0xF0C) /* se_ctrl_reserved_2 */
+
+/* Register Bitfield definitions *****************************************************/
+
+/* 0x0 : se_sha_0_ctrl */
+#define SEC_ENG_SE_SHA_0_BUSY           (1 << 0U)
+#define SEC_ENG_SE_SHA_0_TRIG_1T        (1 << 1U)
+#define SEC_ENG_SE_SHA_0_MODE_SHIFT     (2U)
+#define SEC_ENG_SE_SHA_0_MODE_MASK      (0x7 << SEC_ENG_SE_SHA_0_MODE_SHIFT)
+#define SEC_ENG_SE_SHA_0_EN             (1 << 5U)
+#define SEC_ENG_SE_SHA_0_HASH_SEL       (1 << 6U)
+#define SEC_ENG_SE_SHA_0_INT            (1 << 8U)
+#define SEC_ENG_SE_SHA_0_INT_CLR_1T     (1 << 9U)
+#define SEC_ENG_SE_SHA_0_INT_SET_1T     (1 << 10U)
+#define SEC_ENG_SE_SHA_0_INT_MASK       (1 << 11U)
+#define SEC_ENG_SE_SHA_0_MODE_EXT_SHIFT (12U)
+#define SEC_ENG_SE_SHA_0_MODE_EXT_MASK  (0x3 << SEC_ENG_SE_SHA_0_MODE_EXT_SHIFT)
+#define SEC_ENG_SE_SHA_0_LINK_MODE      (1 << 15U)
+#define SEC_ENG_SE_SHA_0_MSG_LEN_SHIFT  (16U)
+#define SEC_ENG_SE_SHA_0_MSG_LEN_MASK   (0xffff << SEC_ENG_SE_SHA_0_MSG_LEN_SHIFT)
+
+/* 0x4 : se_sha_0_msa */
+#define SEC_ENG_SE_SHA_0_MSA_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_MSA_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_MSA_SHIFT)
+
+/* 0x8 : se_sha_0_status */
+#define SEC_ENG_SE_SHA_0_STATUS_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_STATUS_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_STATUS_SHIFT)
+
+/* 0xC : se_sha_0_endian */
+#define SEC_ENG_SE_SHA_0_DOUT_ENDIAN (1 << 0U)
+
+/* 0x10 : se_sha_0_hash_l_0 */
+#define SEC_ENG_SE_SHA_0_HASH_L_0_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_0_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_0_SHIFT)
+
+/* 0x14 : se_sha_0_hash_l_1 */
+#define SEC_ENG_SE_SHA_0_HASH_L_1_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_1_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_1_SHIFT)
+
+/* 0x18 : se_sha_0_hash_l_2 */
+#define SEC_ENG_SE_SHA_0_HASH_L_2_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_2_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_2_SHIFT)
+
+/* 0x1C : se_sha_0_hash_l_3 */
+#define SEC_ENG_SE_SHA_0_HASH_L_3_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_3_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_3_SHIFT)
+
+/* 0x20 : se_sha_0_hash_l_4 */
+#define SEC_ENG_SE_SHA_0_HASH_L_4_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_4_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_4_SHIFT)
+
+/* 0x24 : se_sha_0_hash_l_5 */
+#define SEC_ENG_SE_SHA_0_HASH_L_5_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_5_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_5_SHIFT)
+
+/* 0x28 : se_sha_0_hash_l_6 */
+#define SEC_ENG_SE_SHA_0_HASH_L_6_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_6_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_6_SHIFT)
+
+/* 0x2C : se_sha_0_hash_l_7 */
+#define SEC_ENG_SE_SHA_0_HASH_L_7_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_L_7_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_L_7_SHIFT)
+
+/* 0x30 : se_sha_0_hash_h_0 */
+#define SEC_ENG_SE_SHA_0_HASH_H_0_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_0_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_0_SHIFT)
+
+/* 0x34 : se_sha_0_hash_h_1 */
+#define SEC_ENG_SE_SHA_0_HASH_H_1_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_1_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_1_SHIFT)
+
+/* 0x38 : se_sha_0_hash_h_2 */
+#define SEC_ENG_SE_SHA_0_HASH_H_2_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_2_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_2_SHIFT)
+
+/* 0x3C : se_sha_0_hash_h_3 */
+#define SEC_ENG_SE_SHA_0_HASH_H_3_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_3_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_3_SHIFT)
+
+/* 0x40 : se_sha_0_hash_h_4 */
+#define SEC_ENG_SE_SHA_0_HASH_H_4_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_4_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_4_SHIFT)
+
+/* 0x44 : se_sha_0_hash_h_5 */
+#define SEC_ENG_SE_SHA_0_HASH_H_5_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_5_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_5_SHIFT)
+
+/* 0x48 : se_sha_0_hash_h_6 */
+#define SEC_ENG_SE_SHA_0_HASH_H_6_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_6_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_6_SHIFT)
+
+/* 0x4C : se_sha_0_hash_h_7 */
+#define SEC_ENG_SE_SHA_0_HASH_H_7_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_HASH_H_7_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_HASH_H_7_SHIFT)
+
+/* 0x50 : se_sha_0_link */
+#define SEC_ENG_SE_SHA_0_LCA_SHIFT (0U)
+#define SEC_ENG_SE_SHA_0_LCA_MASK  (0xffffffff << SEC_ENG_SE_SHA_0_LCA_SHIFT)
+
+/* 0xFC : se_sha_0_ctrl_prot */
+#define SEC_ENG_SE_SHA_ID0_EN (1 << 1U)
+#define SEC_ENG_SE_SHA_ID1_EN (1 << 2U)
+
+/* 0x100 : se_aes_0_ctrl */
+#define SEC_ENG_SE_AES_0_BUSY             (1 << 0U)
+#define SEC_ENG_SE_AES_0_TRIG_1T          (1 << 1U)
+#define SEC_ENG_SE_AES_0_EN               (1 << 2U)
+#define SEC_ENG_SE_AES_0_MODE_SHIFT       (3U)
+#define SEC_ENG_SE_AES_0_MODE_MASK        (0x3 << SEC_ENG_SE_AES_0_MODE_SHIFT)
+#define SEC_ENG_SE_AES_0_DEC_EN           (1 << 5U)
+#define SEC_ENG_SE_AES_0_DEC_KEY_SEL      (1 << 6U)
+#define SEC_ENG_SE_AES_0_HW_KEY_EN        (1 << 7U)
+#define SEC_ENG_SE_AES_0_INT              (1 << 8U)
+#define SEC_ENG_SE_AES_0_INT_CLR_1T       (1 << 9U)
+#define SEC_ENG_SE_AES_0_INT_SET_1T       (1 << 10U)
+#define SEC_ENG_SE_AES_0_INT_MASK         (1 << 11U)
+#define SEC_ENG_SE_AES_0_BLOCK_MODE_SHIFT (12U)
+#define SEC_ENG_SE_AES_0_BLOCK_MODE_MASK  (0x3 << SEC_ENG_SE_AES_0_BLOCK_MODE_SHIFT)
+#define SEC_ENG_SE_AES_0_IV_SEL           (1 << 14U)
+#define SEC_ENG_SE_AES_0_LINK_MODE        (1 << 15U)
+#define SEC_ENG_SE_AES_0_MSG_LEN_SHIFT    (16U)
+#define SEC_ENG_SE_AES_0_MSG_LEN_MASK     (0xffff << SEC_ENG_SE_AES_0_MSG_LEN_SHIFT)
+
+/* 0x104 : se_aes_0_msa */
+#define SEC_ENG_SE_AES_0_MSA_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_MSA_MASK  (0xffffffff << SEC_ENG_SE_AES_0_MSA_SHIFT)
+
+/* 0x108 : se_aes_0_mda */
+#define SEC_ENG_SE_AES_0_MDA_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_MDA_MASK  (0xffffffff << SEC_ENG_SE_AES_0_MDA_SHIFT)
+
+/* 0x10C : se_aes_0_status */
+#define SEC_ENG_SE_AES_0_STATUS_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_STATUS_MASK  (0xffffffff << SEC_ENG_SE_AES_0_STATUS_SHIFT)
+
+/* 0x110 : se_aes_0_iv_0 */
+#define SEC_ENG_SE_AES_0_IV_0_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_IV_0_MASK  (0xffffffff << SEC_ENG_SE_AES_0_IV_0_SHIFT)
+
+/* 0x114 : se_aes_0_iv_1 */
+#define SEC_ENG_SE_AES_0_IV_1_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_IV_1_MASK  (0xffffffff << SEC_ENG_SE_AES_0_IV_1_SHIFT)
+
+/* 0x118 : se_aes_0_iv_2 */
+#define SEC_ENG_SE_AES_0_IV_2_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_IV_2_MASK  (0xffffffff << SEC_ENG_SE_AES_0_IV_2_SHIFT)
+
+/* 0x11C : se_aes_0_iv_3 */
+#define SEC_ENG_SE_AES_0_IV_3_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_IV_3_MASK  (0xffffffff << SEC_ENG_SE_AES_0_IV_3_SHIFT)
+
+/* 0x120 : se_aes_0_key_0 */
+#define SEC_ENG_SE_AES_0_KEY_0_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_0_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_0_SHIFT)
+
+/* 0x124 : se_aes_0_key_1 */
+#define SEC_ENG_SE_AES_0_KEY_1_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_1_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_1_SHIFT)
+
+/* 0x128 : se_aes_0_key_2 */
+#define SEC_ENG_SE_AES_0_KEY_2_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_2_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_2_SHIFT)
+
+/* 0x12C : se_aes_0_key_3 */
+#define SEC_ENG_SE_AES_0_KEY_3_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_3_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_3_SHIFT)
+
+/* 0x130 : se_aes_0_key_4 */
+#define SEC_ENG_SE_AES_0_KEY_4_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_4_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_4_SHIFT)
+
+/* 0x134 : se_aes_0_key_5 */
+#define SEC_ENG_SE_AES_0_KEY_5_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_5_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_5_SHIFT)
+
+/* 0x138 : se_aes_0_key_6 */
+#define SEC_ENG_SE_AES_0_KEY_6_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_6_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_6_SHIFT)
+
+/* 0x13C : se_aes_0_key_7 */
+#define SEC_ENG_SE_AES_0_KEY_7_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_7_MASK  (0xffffffff << SEC_ENG_SE_AES_0_KEY_7_SHIFT)
+
+/* 0x140 : se_aes_0_key_sel */
+#define SEC_ENG_SE_AES_0_KEY_SEL_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_KEY_SEL_MASK  (0x3 << SEC_ENG_SE_AES_0_KEY_SEL_SHIFT)
+
+/* 0x144 : se_aes_1_key_sel */
+#define SEC_ENG_SE_AES_1_KEY_SEL_SHIFT (0U)
+#define SEC_ENG_SE_AES_1_KEY_SEL_MASK  (0x3 << SEC_ENG_SE_AES_1_KEY_SEL_SHIFT)
+
+/* 0x148 : se_aes_0_endian */
+#define SEC_ENG_SE_AES_0_DOUT_ENDIAN   (1 << 0U)
+#define SEC_ENG_SE_AES_0_DIN_ENDIAN    (1 << 1U)
+#define SEC_ENG_SE_AES_0_KEY_ENDIAN    (1 << 2U)
+#define SEC_ENG_SE_AES_0_IV_ENDIAN     (1 << 3U)
+#define SEC_ENG_SE_AES_0_TWK_ENDIAN    (1 << 4U)
+#define SEC_ENG_SE_AES_0_CTR_LEN_SHIFT (30U)
+#define SEC_ENG_SE_AES_0_CTR_LEN_MASK  (0x3 << SEC_ENG_SE_AES_0_CTR_LEN_SHIFT)
+
+/* 0x14C : se_aes_sboot */
+#define SEC_ENG_SE_AES_0_SBOOT_KEY_SEL (1 << 0U)
+#define SEC_ENG_SE_AES_0_XTS_MODE      (1 << 15U)
+#define SEC_ENG_SE_AES_0_UNI_LEN_SHIFT (16U)
+#define SEC_ENG_SE_AES_0_UNI_LEN_MASK  (0xffff << SEC_ENG_SE_AES_0_UNI_LEN_SHIFT)
+
+/* 0x150 : se_aes_0_link */
+#define SEC_ENG_SE_AES_0_LCA_SHIFT (0U)
+#define SEC_ENG_SE_AES_0_LCA_MASK  (0xffffffff << SEC_ENG_SE_AES_0_LCA_SHIFT)
+
+/* 0x1FC : se_aes_0_ctrl_prot */
+#define SEC_ENG_SE_AES_ID0_EN (1 << 1U)
+#define SEC_ENG_SE_AES_ID1_EN (1 << 2U)
+
+/* 0x200 : se_trng_0_ctrl_0 */
+#define SEC_ENG_SE_TRNG_0_BUSY           (1 << 0U)
+#define SEC_ENG_SE_TRNG_0_TRIG_1T        (1 << 1U)
+#define SEC_ENG_SE_TRNG_0_EN             (1 << 2U)
+#define SEC_ENG_SE_TRNG_0_DOUT_CLR_1T    (1 << 3U)
+#define SEC_ENG_SE_TRNG_0_HT_ERROR       (1 << 4U)
+#define SEC_ENG_SE_TRNG_0_INT            (1 << 8U)
+#define SEC_ENG_SE_TRNG_0_INT_CLR_1T     (1 << 9U)
+#define SEC_ENG_SE_TRNG_0_INT_SET_1T     (1 << 10U)
+#define SEC_ENG_SE_TRNG_0_INT_MASK       (1 << 11U)
+#define SEC_ENG_SE_TRNG_0_MANUAL_FUN_SEL (1 << 13U)
+#define SEC_ENG_SE_TRNG_0_MANUAL_RESEED  (1 << 14U)
+#define SEC_ENG_SE_TRNG_0_MANUAL_EN      (1 << 15U)
+
+/* 0x204 : se_trng_0_status */
+#define SEC_ENG_SE_TRNG_0_STATUS_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_STATUS_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_STATUS_SHIFT)
+
+/* 0x208 : se_trng_0_dout_0 */
+#define SEC_ENG_SE_TRNG_0_DOUT_0_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_0_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_0_SHIFT)
+
+/* 0x20C : se_trng_0_dout_1 */
+#define SEC_ENG_SE_TRNG_0_DOUT_1_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_1_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_1_SHIFT)
+
+/* 0x210 : se_trng_0_dout_2 */
+#define SEC_ENG_SE_TRNG_0_DOUT_2_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_2_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_2_SHIFT)
+
+/* 0x214 : se_trng_0_dout_3 */
+#define SEC_ENG_SE_TRNG_0_DOUT_3_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_3_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_3_SHIFT)
+
+/* 0x218 : se_trng_0_dout_4 */
+#define SEC_ENG_SE_TRNG_0_DOUT_4_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_4_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_4_SHIFT)
+
+/* 0x21C : se_trng_0_dout_5 */
+#define SEC_ENG_SE_TRNG_0_DOUT_5_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_5_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_5_SHIFT)
+
+/* 0x220 : se_trng_0_dout_6 */
+#define SEC_ENG_SE_TRNG_0_DOUT_6_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_6_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_6_SHIFT)
+
+/* 0x224 : se_trng_0_dout_7 */
+#define SEC_ENG_SE_TRNG_0_DOUT_7_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_DOUT_7_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_DOUT_7_SHIFT)
+
+/* 0x228 : se_trng_0_test */
+#define SEC_ENG_SE_TRNG_0_TEST_EN          (1 << 0U)
+#define SEC_ENG_SE_TRNG_0_CP_TEST_EN       (1 << 1U)
+#define SEC_ENG_SE_TRNG_0_CP_BYPASS        (1 << 2U)
+#define SEC_ENG_SE_TRNG_0_HT_DIS           (1 << 3U)
+#define SEC_ENG_SE_TRNG_0_HT_ALARM_N_SHIFT (4U)
+#define SEC_ENG_SE_TRNG_0_HT_ALARM_N_MASK  (0xff << SEC_ENG_SE_TRNG_0_HT_ALARM_N_SHIFT)
+
+/* 0x22C : se_trng_0_ctrl_1 */
+#define SEC_ENG_SE_TRNG_0_RESEED_N_LSB_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_RESEED_N_LSB_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_RESEED_N_LSB_SHIFT)
+
+/* 0x230 : se_trng_0_ctrl_2 */
+#define SEC_ENG_SE_TRNG_0_RESEED_N_MSB_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_RESEED_N_MSB_MASK  (0xffff << SEC_ENG_SE_TRNG_0_RESEED_N_MSB_SHIFT)
+
+/* 0x234 : se_trng_0_ctrl_3 */
+#define SEC_ENG_SE_TRNG_0_CP_RATIO_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_CP_RATIO_MASK  (0xff << SEC_ENG_SE_TRNG_0_CP_RATIO_SHIFT)
+#define SEC_ENG_SE_TRNG_0_HT_RCT_C_SHIFT (8U)
+#define SEC_ENG_SE_TRNG_0_HT_RCT_C_MASK  (0xff << SEC_ENG_SE_TRNG_0_HT_RCT_C_SHIFT)
+#define SEC_ENG_SE_TRNG_0_HT_APT_C_SHIFT (16U)
+#define SEC_ENG_SE_TRNG_0_HT_APT_C_MASK  (0x3ff << SEC_ENG_SE_TRNG_0_HT_APT_C_SHIFT)
+#define SEC_ENG_SE_TRNG_0_HT_OD_EN       (1 << 26U)
+#define SEC_ENG_SE_TRNG_0_ROSC_EN        (1 << 31U)
+
+/* 0x240 : se_trng_0_test_out_0 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_0_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_0_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_TEST_OUT_0_SHIFT)
+
+/* 0x244 : se_trng_0_test_out_1 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_1_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_1_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_TEST_OUT_1_SHIFT)
+
+/* 0x248 : se_trng_0_test_out_2 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_2_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_2_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_TEST_OUT_2_SHIFT)
+
+/* 0x24C : se_trng_0_test_out_3 */
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_3_SHIFT (0U)
+#define SEC_ENG_SE_TRNG_0_TEST_OUT_3_MASK  (0xffffffff << SEC_ENG_SE_TRNG_0_TEST_OUT_3_SHIFT)
+
+/* 0x2FC : se_trng_0_ctrl_prot */
+#define SEC_ENG_SE_TRNG_ID0_EN (1 << 1U)
+#define SEC_ENG_SE_TRNG_ID1_EN (1 << 2U)
+
+/* 0x300 : se_pka_0_ctrl_0 */
+#define SEC_ENG_SE_PKA_0_DONE          (1 << 0U)
+#define SEC_ENG_SE_PKA_0_DONE_CLR_1T   (1 << 1U)
+#define SEC_ENG_SE_PKA_0_BUSY          (1 << 2U)
+#define SEC_ENG_SE_PKA_0_EN            (1 << 3U)
+#define SEC_ENG_SE_PKA_0_PROT_MD_SHIFT (4U)
+#define SEC_ENG_SE_PKA_0_PROT_MD_MASK  (0xf << SEC_ENG_SE_PKA_0_PROT_MD_SHIFT)
+#define SEC_ENG_SE_PKA_0_INT           (1 << 8U)
+#define SEC_ENG_SE_PKA_0_INT_CLR_1T    (1 << 9U)
+#define SEC_ENG_SE_PKA_0_INT_SET       (1 << 10U)
+#define SEC_ENG_SE_PKA_0_INT_MASK      (1 << 11U)
+#define SEC_ENG_SE_PKA_0_ENDIAN        (1 << 12U)
+#define SEC_ENG_SE_PKA_0_RAM_CLR_MD    (1 << 13U)
+#define SEC_ENG_SE_PKA_0_STATUS_CLR_1T (1 << 15U)
+#define SEC_ENG_SE_PKA_0_STATUS_SHIFT  (16U)
+#define SEC_ENG_SE_PKA_0_STATUS_MASK   (0xffff << SEC_ENG_SE_PKA_0_STATUS_SHIFT)
+
+/* 0x30C : se_pka_0_seed */
+#define SEC_ENG_SE_PKA_0_SEED_SHIFT (0U)
+#define SEC_ENG_SE_PKA_0_SEED_MASK  (0xffffffff << SEC_ENG_SE_PKA_0_SEED_SHIFT)
+
+/* 0x310 : se_pka_0_ctrl_1 */
+#define SEC_ENG_SE_PKA_0_HBURST_SHIFT (0U)
+#define SEC_ENG_SE_PKA_0_HBURST_MASK  (0x7 << SEC_ENG_SE_PKA_0_HBURST_SHIFT)
+#define SEC_ENG_SE_PKA_0_HBYPASS      (1 << 3U)
+
+/* 0x340 : se_pka_0_rw */
+
+/* 0x360 : se_pka_0_rw_burst */
+
+/* 0x3FC : se_pka_0_ctrl_prot */
+#define SEC_ENG_SE_PKA_ID0_EN (1 << 1U)
+#define SEC_ENG_SE_PKA_ID1_EN (1 << 2U)
+
+/* 0x400 : se_cdet_0_ctrl_0 */
+#define SEC_ENG_SE_CDET_0_EN           (1 << 0U)
+#define SEC_ENG_SE_CDET_0_BUSY         (1 << 1U)
+#define SEC_ENG_SE_CDET_0_STATUS_SHIFT (3U)
+#define SEC_ENG_SE_CDET_0_STATUS_MASK  (0x1f << SEC_ENG_SE_CDET_0_STATUS_SHIFT)
+#define SEC_ENG_SE_CDET_0_INT          (1 << 8U)
+#define SEC_ENG_SE_CDET_0_INT_CLR      (1 << 9U)
+#define SEC_ENG_SE_CDET_0_INT_SET      (1 << 10U)
+#define SEC_ENG_SE_CDET_0_INT_MASK     (1 << 11U)
+#define SEC_ENG_SE_CDET_0_MODE         (1 << 12U)
+
+/* 0x404 : se_cdet_0_ctrl_1 */
+#define SEC_ENG_SE_CDET_0_G_LOOP_MAX_SHIFT (0U)
+#define SEC_ENG_SE_CDET_0_G_LOOP_MAX_MASK  (0xffff << SEC_ENG_SE_CDET_0_G_LOOP_MAX_SHIFT)
+#define SEC_ENG_SE_CDET_0_G_LOOP_MIN_SHIFT (16U)
+#define SEC_ENG_SE_CDET_0_G_LOOP_MIN_MASK  (0xffff << SEC_ENG_SE_CDET_0_G_LOOP_MIN_SHIFT)
+
+/* 0x408 : se_cdet_0_ctrl_2 */
+#define SEC_ENG_SE_CDET_0_T_LOOP_N_SHIFT (0U)
+#define SEC_ENG_SE_CDET_0_T_LOOP_N_MASK  (0xffff << SEC_ENG_SE_CDET_0_T_LOOP_N_SHIFT)
+#define SEC_ENG_SE_CDET_0_T_DLY_N_SHIFT  (16U)
+#define SEC_ENG_SE_CDET_0_T_DLY_N_MASK   (0xff << SEC_ENG_SE_CDET_0_T_DLY_N_SHIFT)
+#define SEC_ENG_SE_CDET_0_G_SLP_N_SHIFT  (24U)
+#define SEC_ENG_SE_CDET_0_G_SLP_N_MASK   (0xff << SEC_ENG_SE_CDET_0_G_SLP_N_SHIFT)
+
+/* 0x40C : se_cdet_0_ctrl_3 */
+#define SEC_ENG_SE_CDET_0_T_COUNT_SHIFT (0U)
+#define SEC_ENG_SE_CDET_0_T_COUNT_MASK  (0xffff << SEC_ENG_SE_CDET_0_T_COUNT_SHIFT)
+#define SEC_ENG_SE_CDET_0_G_COUNT_SHIFT (16U)
+#define SEC_ENG_SE_CDET_0_G_COUNT_MASK  (0xffff << SEC_ENG_SE_CDET_0_G_COUNT_SHIFT)
+
+/* 0x4FC : se_cdet_0_ctrl_prot */
+#define SEC_ENG_SE_CDET_PROT_EN (1 << 0U)
+#define SEC_ENG_SE_CDET_ID0_EN  (1 << 1U)
+#define SEC_ENG_SE_CDET_ID1_EN  (1 << 2U)
+
+/* 0x500 : se_gmac_0_ctrl_0 */
+#define SEC_ENG_SE_GMAC_0_BUSY       (1 << 0U)
+#define SEC_ENG_SE_GMAC_0_TRIG_1T    (1 << 1U)
+#define SEC_ENG_SE_GMAC_0_EN         (1 << 2U)
+#define SEC_ENG_SE_GMAC_0_INT        (1 << 8U)
+#define SEC_ENG_SE_GMAC_0_INT_CLR_1T (1 << 9U)
+#define SEC_ENG_SE_GMAC_0_INT_SET_1T (1 << 10U)
+#define SEC_ENG_SE_GMAC_0_INT_MASK   (1 << 11U)
+#define SEC_ENG_SE_GMAC_0_T_ENDIAN   (1 << 12U)
+#define SEC_ENG_SE_GMAC_0_H_ENDIAN   (1 << 13U)
+#define SEC_ENG_SE_GMAC_0_X_ENDIAN   (1 << 14U)
+
+/* 0x504 : se_gmac_0_lca */
+#define SEC_ENG_SE_GMAC_0_LCA_SHIFT (0U)
+#define SEC_ENG_SE_GMAC_0_LCA_MASK  (0xffffffff << SEC_ENG_SE_GMAC_0_LCA_SHIFT)
+
+/* 0x508 : se_gmac_0_status */
+#define SEC_ENG_SE_GMAC_0_STATUS_SHIFT (0U)
+#define SEC_ENG_SE_GMAC_0_STATUS_MASK  (0xffffffff << SEC_ENG_SE_GMAC_0_STATUS_SHIFT)
+
+/* 0x5FC : se_gmac_0_ctrl_prot */
+#define SEC_ENG_SE_GMAC_ID0_EN (1 << 1U)
+#define SEC_ENG_SE_GMAC_ID1_EN (1 << 2U)
+
+/* 0xF00 : se_ctrl_prot_rd */
+#define SEC_ENG_SE_SHA_ID0_EN_RD  (1 << 0U)
+#define SEC_ENG_SE_SHA_ID1_EN_RD  (1 << 1U)
+#define SEC_ENG_SE_AES_ID0_EN_RD  (1 << 2U)
+#define SEC_ENG_SE_AES_ID1_EN_RD  (1 << 3U)
+#define SEC_ENG_SE_TRNG_ID0_EN_RD (1 << 4U)
+#define SEC_ENG_SE_TRNG_ID1_EN_RD (1 << 5U)
+#define SEC_ENG_SE_PKA_ID0_EN_RD  (1 << 6U)
+#define SEC_ENG_SE_PKA_ID1_EN_RD  (1 << 7U)
+#define SEC_ENG_SE_CDET_ID0_EN_RD (1 << 8U)
+#define SEC_ENG_SE_CDET_ID1_EN_RD (1 << 9U)
+#define SEC_ENG_SE_GMAC_ID0_EN_RD (1 << 10U)
+#define SEC_ENG_SE_GMAC_ID1_EN_RD (1 << 11U)
+#define SEC_ENG_SE_DBG_DIS        (1 << 31U)
+
+/* 0xF04 : se_ctrl_reserved_0 */
+#define SEC_ENG_SE_CTRL_RESERVED_0_SHIFT (0U)
+#define SEC_ENG_SE_CTRL_RESERVED_0_MASK  (0xffffffff << SEC_ENG_SE_CTRL_RESERVED_0_SHIFT)
+
+/* 0xF08 : se_ctrl_reserved_1 */
+#define SEC_ENG_SE_CTRL_RESERVED_1_SHIFT (0U)
+#define SEC_ENG_SE_CTRL_RESERVED_1_MASK  (0xffffffff << SEC_ENG_SE_CTRL_RESERVED_1_SHIFT)
+
+/* 0xF0C : se_ctrl_reserved_2 */
+#define SEC_ENG_SE_CTRL_RESERVED_2_SHIFT (0U)
+#define SEC_ENG_SE_CTRL_RESERVED_2_MASK  (0xffffffff << SEC_ENG_SE_CTRL_RESERVED_2_SHIFT)
+
+#endif /* __HARDWARE_SEC_ENG_H__ */

+ 21 - 0
fs/vfs/include/device/vfs_adc.h

@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_ADC_H
+#define AOS_VFS_ADC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* adc driver struct */
+extern const struct file_ops adc_ops;
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_ADC_H */
+

+ 26 - 0
fs/vfs/include/device/vfs_device.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_DEVICE_H
+#define AOS_VFS_DEVICE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_adc.h"
+#include "vfs_gpio.h"
+#include "vfs_i2c.h"
+#include "vfs_pwm.h"
+#include "vfs_rtc.h"
+#include "vfs_spi.h"
+#include "vfs_uart.h"
+#include "vfs_wdg.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_DEVICE_H */
+

+ 75 - 0
fs/vfs/include/device/vfs_gpio.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_GPIO_H
+#define AOS_VFS_GPIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* gpio driver struct */
+extern const struct file_ops gpio_ops;
+
+/**
+ * This function is used to open gpio device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_gpio_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close gpio device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_gpio_close(file_t *fp);
+
+/**
+ * This function is used to send data through gpio.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return  The positive non-zero number of bytes read on success, 
+ * 0 on read nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_gpio_write(file_t *fp, const void *buf, size_t nbytes);
+
+/**
+ * This function is used to get data from gpio.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return  The positive non-zero number of bytes read on success, 
+ * 0 on read nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_gpio_read(file_t *fp, void *buf, size_t nbytes);
+
+/**
+ * This function performs device input and output operations.
+ *
+ * @param[in]  fp   device pointer.
+ * @param[in]  cmd  command of input and output operating.
+ * @param[in]  arg  argument of input and output operating. 
+ *
+ * @return  0 on success, negative on failure with errno set appropriately.
+ */
+int vfs_gpio_ioctl(file_t *fp, int cmd, unsigned long arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_GPIO_H */
+

+ 64 - 0
fs/vfs/include/device/vfs_i2c.h

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_I2C_H
+#define AOS_VFS_I2C_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* i2c driver struct */
+extern const struct file_ops i2c_ops;
+
+/**
+ * This function is used to open i2c device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_i2c_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close i2c device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_i2c_close(file_t *fp);
+
+/**
+ * This function is used to get data from i2c.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return  The positive non-zero number of bytes read on success, 
+ * 0 on read nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_i2c_read(file_t *fp, void *buf, size_t nbytes);
+
+/**
+ * This function is used to send data through i2c.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return   The positive non-zero number of bytes write on success, 
+ * 0 on write nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_i2c_write(file_t *fp, const void *buf, size_t nbytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_I2C_H */
+

+ 57 - 0
fs/vfs/include/device/vfs_pwm.h

@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_PWM_H
+#define AOS_VFS_PWM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* cmd for ioctl */
+#define IOCTL_PWM_OUTPUT_START 1 /* start output pwm */
+#define IOCTL_PWM_OUTPUT_STOP  2 /* stop output pwm */
+#define IOCTL_PWM_OUTPUT_DUTY  3 /* change duty pwm */
+#define IOCTL_PWM_OUTPUT_FREQ  4 /* change duty pwm */
+
+/* pwm driver struct */
+extern const struct file_ops pwm_ops;
+
+/**
+ * This function is used to open pwm device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_pwm_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close pwm device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_pwm_close(file_t *fp);
+
+/**
+ * This function performs device input and output operations.
+ *
+ * @param[in]  fp   device pointer.
+ * @param[in]  cmd  command of input and output operating.
+ * @param[in]  arg  argument of input and output operating. 
+ *
+ * @return  0 on success, negative on failure with errno set appropriately.
+ */
+int vfs_pwm_ioctl(file_t *fp, int cmd, unsigned long arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_PWM_H */
+

+ 64 - 0
fs/vfs/include/device/vfs_rtc.h

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_RTC_H
+#define AOS_VFS_RTC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* rtc driver struct */
+extern const struct file_ops rtc_ops;
+
+/**
+ * This function is used to open rtc device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_rtc_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close rtc device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_rtc_close(file_t *fp);
+
+/**
+ * This function is used to get Real-Time Clock.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return  The positive non-zero number of bytes read on success, 
+ * 0 on read nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_rtc_read(file_t *fp, void *buf, size_t nbytes);
+
+/**
+ * This function is used to set Real-Time Clock.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return   The positive non-zero number of bytes write on success, 
+ * 0 on write nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_rtc_write(file_t *fp, const void *buf, size_t nbytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_RTC_H */
+

+ 108 - 0
fs/vfs/include/device/vfs_spi.h

@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_SPI_H
+#define AOS_VFS_SPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+#include "stdint.h"
+
+/*section for SPI IOCTRL*/
+/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */
+#define IOCTL_SPI_IOC_RD_MODE               0 /* Read and write synchronization modification */
+#define IOCTL_SPI_IOC_WR_MODE               1 /* Read and write synchronization modification */
+/* Read / Write SPI bit justification */
+#define IOCTL_SPI_IOC_RD_LSB_FIRST          2 /* Unimplemented */
+#define IOCTL_SPI_IOC_WR_LSB_FIRST          3 /* Unimplemented */
+/* Read / Write SPI device word length (1..N) */
+#define IOCTL_SPI_IOC_RD_BITS_PER_WORD      4 /* Unimplemented */
+#define IOCTL_SPI_IOC_WR_BITS_PER_WORD      5 /* Unimplemented */
+/* Read / Write SPI device default max speed hz */
+#define IOCTL_SPI_IOC_RD_MAX_SPEED_HZ       6 /* Unimplemented */
+#define IOCTL_SPI_IOC_WR_MAX_SPEED_HZ       7 /* Unimplemented */
+/* Read / Write of the SPI mode field */
+#define IOCTL_SPI_IOC_RD_MODE32             8 /* Unimplemented */
+#define IOCTL_SPI_IOC_WR_MODE32             9 /* Unimplemented */
+#define IOCTL_SPI_IOC_MESSAGE(N)            (9 + N)
+
+/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) (limited to 8 bits) */
+#define IOCTL_SPI_CPHA      (0x01)
+#define IOCTL_SPI_CPOL      (0x02)
+#define IOCTL_SPI_MODE_0    (0|0)
+#define IOCTL_SPI_MODE_1    (0|IOCTL_SPI_CPHA)
+#define IOCTL_SPI_MODE_2    (IOCTL_SPI_CPOL|0)
+#define IOCTL_SPI_MODE_3    (IOCTL_SPI_CPOL|IOCTL_SPI_CPHA)
+
+typedef struct spi_ioc_transfer {
+    uint32_t   tx_buf;               /* uint64_t to uint32_t */
+    uint32_t   rx_buf;               /* uint64_t to uint32_t */
+    uint32_t   len;
+    uint32_t   speed_hz;
+    uint16_t   delay_usecs;          /* Unimplemented */
+    uint16_t   delay_msecs;          /* delay ms, bl add*/
+    uint8_t    bits_per_word;        /* Unimplemented */
+    uint8_t    cs_change;            /* 0: Keep CS activated */
+    uint8_t    tx_nbits;             /* Unimplemented */
+    uint8_t    rx_nbits;             /* Unimplemented */
+    uint8_t    word_delay_usecs;     /* Unimplemented */
+    uint8_t    pad;                  /* Unimplemented */
+} spi_ioc_transfer_t;
+
+/* spi driver struct */
+extern const struct file_ops spi_ops;
+
+/**
+ * This function is used to open spi device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_spi_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close spi device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_spi_close(file_t *fp);
+
+/**
+ * This function is used to get data from spi.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return  The positive non-zero number of bytes read on success,
+ * 0 on read nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_spi_read(file_t *fp, void *buf, size_t nbytes);
+
+/**
+ * This function is used to send data through spi.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return   The positive non-zero number of bytes write on success,
+ * 0 on write nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_spi_write(file_t *fp, const void *buf, size_t nbytes);
+
+int vfs_spi_ioctl(file_t *fp, int cmd, unsigned long arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_SPI_H */
+

+ 106 - 0
fs/vfs/include/device/vfs_uart.h

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_UART_H
+#define AOS_VFS_UART_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+#define IOCTL_UART_IOC_CLEAN_MODE                1 /* clean rx ringbuf */
+#define IOCTL_UART_IOC_FLUSH_MODE                2 /* flush */
+#define IOCTL_UART_IOC_BAUD_MODE                 3 /* baud */
+#define IOCTL_UART_IOC_WAITRD_MODE               4 /* waitread */
+#define IOCTL_UART_IOC_WAITRDFULL_MODE           5 /* waitread full */
+#define IOCTL_UART_IOC_READ_BLOCK                6 /* read block */
+#define IOCTL_UART_IOC_READ_NOBLOCK              7 /* read noblock */
+#define IOCTL_UART_IOC_PARITY_SET                8 /* set parity */
+#define IOCTL_UART_IOC_PARITY_GET                9 /* get parity */
+#define IOCTL_UART_IOC_STOPBITS_SET              10 /* set stop bits */
+#define IOCTL_UART_IOC_STOPBITS_GET              11 /* get stop bits */
+#define IOCTL_UART_IOC_HWFC_SET                  12 /* set hwfc */
+#define IOCTL_UART_IOC_HWFC_GET                  13 /* get hwfc */
+#define IOCTL_UART_IOC_DATABITS_SET              14 /* set data bits */
+#define IOCTL_UART_IOC_DATABITS_GET              15 /* set data bits */
+#define IOCTL_UART_IOC_WAITENDBYTE_MODE          16 /* last byte timeout */
+
+#define UART_READ_CFG_BLOCK   1
+#define UART_READ_CFG_NOBLOCK 2
+
+typedef enum {
+    IO_UART_PARITY_NONE,
+    IO_UART_PARITY_ODD,
+    IO_UART_PARITY_EVEN,
+} ioc_uart_parity_t;
+
+typedef struct _uart_ioctrl_wait_read {
+    char *buf;
+    int read_size;
+    uint32_t timeout; /* ms */
+} uart_ioc_waitread_t;
+
+/* uart driver struct */
+extern const struct file_ops uart_ops;
+
+/**
+ * This function is used to open uart device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_uart_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close uart device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_uart_close(file_t *fp);
+
+/**
+ * This function is used to get data from uart.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return  The positive non-zero number of bytes read on success,
+ * 0 on read nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_uart_read(file_t *fp, void *buf, size_t nbytes);
+
+/**
+ * This function is used to send data through uart.
+ *
+ * @param[in]   fp      device pointer.
+ * @param[out]  buf     data buffer for data.
+ * @param[in]   nbytes  the maximum size of the user-provided buffer.
+ *
+ * @return   The positive non-zero number of bytes write on success,
+ * 0 on write nothing, or negative on failure with errno set appropriately.
+ */
+ssize_t vfs_uart_write(file_t *fp, const void *buf, size_t nbytes);
+
+int vfs_uart_init(uint32_t fdt, uint32_t dtb_uart_offset, const char *node[], int node_max);
+
+int vfs_uart_poll(file_t *fp, bool setup, poll_notify_t notify, struct pollfd *fd, void *opa);
+
+int vfs_uart_ioctl(file_t *fp, int cmd, unsigned long arg);
+
+int vfs_uart_sync(file_t *fp);
+
+int vfs_uart_init_simple_mode(uint8_t id, uint8_t pin_tx, uint8_t pin_rx, int baudrate, const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_UART_H */
+

+ 54 - 0
fs/vfs/include/device/vfs_wdg.h

@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_WDG_H
+#define AOS_VFS_WDG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* cmd for ioctl */
+#define IOCTL_WDG_RELOAD 1 /* reload watchdog */
+
+/* wdg driver struct */
+extern const struct file_ops wdg_ops;
+
+/**
+ * This function is used to open wdg device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_wdg_open(inode_t *inode, file_t *fp);
+
+/**
+ * This function is used to close wdg device.
+ *
+ * @param[in]  fp  device pointer.
+ *
+ * @return  0 on success, others on failure with errno set appropriately.
+ */
+int vfs_wdg_close(file_t *fp);
+
+/**
+ * This function performs device input and output operations.
+ *
+ * @param[in]  fp   device pointer.
+ * @param[in]  cmd  command of input and output operating.
+ * @param[in]  arg  argument of input and output operating. 
+ *
+ * @return  0 on success, negative on failure with errno set appropriately.
+ */
+int vfs_wdg_ioctl(file_t *fp, int cmd, unsigned long arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_WDG_H */
+

+ 20 - 0
fs/vfs/include/fs/vfs_romfs.h

@@ -0,0 +1,20 @@
+#ifndef AOS_VFS_ROMFS_H
+#define AOS_VFS_ROMFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vfs_inode.h"
+
+/* romfs ioctl struct */
+typedef struct _romfs_file_buf {
+    char *buf;
+    uint32_t bufsize;
+} romfs_filebuf_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_ROMFS_H */

+ 115 - 0
fs/vfs/include/hal/soc/adc.h

@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_ADC_H
+#define HAL_ADC_H
+
+typedef struct {
+    uint32_t sampling_cycle;  /* sampling period in number of ADC clock cycles */
+} adc_config_t;
+
+typedef struct {
+    uint8_t      port;   /* adc port */
+    adc_config_t config; /* adc config */
+    void        *priv;   /* priv data */
+    void         *mutex;
+    void         *fd;
+    void         *poll_cb;
+    void         *poll_data;
+} adc_dev_t;
+
+/**
+ * Initialises an ADC interface, Prepares an ADC hardware interface for sampling
+ *
+ * @param[in]  adc  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_adc_init(adc_dev_t *adc);
+
+/**
+ * Takes a single sample from an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[out]  output   pointer to a variable which will receive the sample
+ * @param[in]   timeout  ms timeout
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_adc_value_get(adc_dev_t *adc, uint32_t *output, uint32_t timeout);
+
+/**
+ * De-initialises an ADC interface, Turns off an ADC hardware interface
+ *
+ * @param[in]  adc  the interface which should be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_adc_finalize(adc_dev_t *adc);
+
+/**
+ * Register notify on a ADC device
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ * @param[in]  cb    call back function
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_register(adc_dev_t *adc, void (*cb)(void *arg));
+
+/**
+ * Disable notify source. It's usually disable low level INT
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_register_config_disable(adc_dev_t *adc);
+
+/**
+ *  Config source to be high level trigger
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_register_config_high(adc_dev_t *adc);
+
+/**
+ *  Config source to be low level trigger
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_register_config_low(adc_dev_t *adc);
+
+/**
+ *  Config source to be trigger by voltage higher than specified
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_register_config_higher(adc_dev_t *adc, int level);
+
+/**
+ *  Config source to be trigger by voltage lower than specified
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_register_config_lower(adc_dev_t *adc, int level);
+/**
+ * Unregister notify on a ADC device
+ *
+ * @param[in]  adc  the adc device which notify should be noticed
+ * @param[in]  cb    call back function
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_adc_notify_unregister(adc_dev_t *adc, void (*cb)(void *arg));
+#endif /* HAL_ADC_H */
+

+ 73 - 0
fs/vfs/include/hal/soc/dac.h

@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_DAC_H
+#define HAL_DAC_H
+
+typedef struct {
+    uint8_t      port;   /* dac port */
+    void        *priv;   /* priv data */
+} dac_dev_t;
+
+/**
+ * Initialises an dac interface
+ *
+ * @param[in]  dac  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_dac_init(dac_dev_t *dac);
+
+/**
+ * Start output dac
+ *
+ * @param[in]   dac      the interface which should be started
+ * @param[out]  channel  the channel to output dac
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_dac_start(dac_dev_t *dac, uint32_t channel);
+
+/**
+ * Stop output dac
+ *
+ * @param[in]   dac      the interface which should be stopped
+ * @param[out]  channel  the channel to output dac
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_dac_stop(dac_dev_t *dac, uint32_t channel);
+
+/**
+ * Output a value to an dac interface
+ *
+ * @param[in]   dac      the interface to set value
+ * @param[out]  channel  the channel to output dac
+ * @param[in]   data     the value to output
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_dac_set_value(dac_dev_t *dac, uint32_t channel, uint32_t data);
+
+/**
+ * Returns the last data output value of the selected dac channel
+ *
+ * @param[in]   dac      the interface to get value
+ * @param[out]  channel  channel  the channel to output dac
+ *
+ * @return  dac output value
+ */
+int32_t hal_dac_get_value(dac_dev_t *dac, uint32_t channel);
+
+/**
+ * De-initialises an dac interface, Turns off an dac hardware interface
+ *
+ * @param[in]  dac  the interface which should be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_dac_finalize(dac_dev_t *dac);
+
+#endif /* HAL_DAC_H */
+

+ 157 - 0
fs/vfs/include/hal/soc/flash.h

@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_FLASH_H
+#define HAL_FLASH_H
+
+#define PAR_OPT_READ_POS  ( 0 )
+#define PAR_OPT_WRITE_POS ( 1 )
+
+#define PAR_OPT_READ_MASK  ( 0x1u << PAR_OPT_READ_POS )
+#define PAR_OPT_WRITE_MASK ( 0x1u << PAR_OPT_WRITE_POS )
+
+#define PAR_OPT_READ_DIS  ( 0x0u << PAR_OPT_READ_POS )
+#define PAR_OPT_READ_EN   ( 0x1u << PAR_OPT_READ_POS )
+#define PAR_OPT_WRITE_DIS ( 0x0u << PAR_OPT_WRITE_POS )
+#define PAR_OPT_WRITE_EN  ( 0x1u << PAR_OPT_WRITE_POS )
+
+typedef enum {
+    HAL_PARTITION_ERROR = -1,
+    HAL_PARTITION_BOOTLOADER,
+    HAL_PARTITION_APPLICATION,
+    HAL_PARTITION_ATE,
+    HAL_PARTITION_OTA_TEMP,
+    HAL_PARTITION_RF_FIRMWARE,
+    HAL_PARTITION_PARAMETER_1,
+    HAL_PARTITION_PARAMETER_2,
+    HAL_PARTITION_PARAMETER_3,
+    HAL_PARTITION_PARAMETER_4,
+    HAL_PARTITION_BT_FIRMWARE,
+    HAL_PARTITION_SPIFFS,
+    HAL_PARTITION_CUSTOM_1,
+    HAL_PARTITION_CUSTOM_2,
+    HAL_PARTITION_RECOVERY,
+    HAL_PARTITION_MAX,
+    HAL_PARTITION_NONE,
+} hal_partition_t;
+
+typedef enum {
+    HAL_FLASH_EMBEDDED,
+    HAL_FLASH_SPI,
+    HAL_FLASH_QSPI,
+    HAL_FLASH_MAX,
+    HAL_FLASH_NONE,
+} hal_flash_t;
+
+typedef struct {
+    hal_flash_t partition_owner;
+    const char *partition_description;
+    uint32_t    partition_start_addr;
+    uint32_t    partition_length;
+    uint32_t    partition_options;
+} hal_logic_partition_t;
+
+/**
+ * Get the infomation of the specified flash area
+ *
+ * @param[in]  in_partition  The target flash logical partition
+ *
+ * @return     HAL_logi_partition struct
+ */
+hal_logic_partition_t *hal_flash_get_info(hal_partition_t in_partition);
+
+/**
+ * Erase an area on a Flash logical partition
+ *
+ * @note  Erase on an address will erase all data on a sector that the
+ *        address is belonged to, this function does not save data that
+ *        beyond the address area but in the affected sector, the data
+ *        will be lost.
+ *
+ * @param[in]  in_partition  The target flash logical partition which should be erased
+ * @param[in]  off_set       Start address of the erased flash area
+ * @param[in]  size          Size of the erased flash area
+ *
+ * @return  0 : On success, EIO : If an error occurred with any step
+ */
+int32_t hal_flash_erase(hal_partition_t in_partition, uint32_t off_set, uint32_t size);
+
+/**
+ * Write data to an area on a flash logical partition without erase
+ *
+ * @param[in]  in_partition    The target flash logical partition which should be read which should be written
+ * @param[in]  off_set         Point to the start address that the data is written to, and
+ *                             point to the last unwritten address after this function is
+ *                             returned, so you can call this function serval times without
+ *                             update this start address.
+ * @param[in]  inBuffer        point to the data buffer that will be written to flash
+ * @param[in]  inBufferLength  The length of the buffer
+ *
+ * @return  0 : On success, EIO : If an error occurred with any step
+ */
+int32_t hal_flash_write(hal_partition_t in_partition, uint32_t *off_set,
+                        const void *in_buf, uint32_t in_buf_len);
+
+/**
+ * Write data to an area on a flash logical partition with erase first
+ *
+ * @param[in]  in_partition    The target flash logical partition which should be read which should be written
+ * @param[in]  off_set         Point to the start address that the data is written to, and
+ *                             point to the last unwritten address after this function is
+ *                             returned, so you can call this function serval times without
+ *                             update this start address.
+ * @param[in]  inBuffer        point to the data buffer that will be written to flash
+ * @param[in]  inBufferLength  The length of the buffer
+ *
+ * @return  0 : On success, EIO : If an error occurred with any step
+ */
+int32_t hal_flash_erase_write(hal_partition_t in_partition, uint32_t *off_set,
+                              const void *in_buf, uint32_t in_buf_len);
+
+/**
+ * Read data from an area on a Flash to data buffer in RAM
+ *
+ * @param[in]  in_partition    The target flash logical partition which should be read
+ * @param[in]  off_set         Point to the start address that the data is read, and
+ *                             point to the last unread address after this function is
+ *                             returned, so you can call this function serval times without
+ *                             update this start address.
+ * @param[in]  outBuffer       Point to the data buffer that stores the data read from flash
+ * @param[in]  inBufferLength  The length of the buffer
+ *
+ * @return  0 : On success, EIO : If an error occurred with any step
+ */
+int32_t hal_flash_read(hal_partition_t in_partition, uint32_t *off_set,
+                       void *out_buf, uint32_t in_buf_len);
+
+/**
+ * Set security options on a logical partition
+ *
+ * @param[in]  partition  The target flash logical partition
+ * @param[in]  offset     Point to the start address that the data is read, and
+ *                        point to the last unread address after this function is
+ *                        returned, so you can call this function serval times without
+ *                        update this start address.
+ * @param[in]  size       Size of enabled flash area
+ *
+ * @return  0 : On success, EIO : If an error occurred with any step
+ */
+int32_t hal_flash_enable_secure(hal_partition_t partition, uint32_t off_set, uint32_t size);
+
+/**
+ * Disable security options on a logical partition
+ *
+ * @param[in]  partition  The target flash logical partition
+ * @param[in]  offset     Point to the start address that the data is read, and
+ *                        point to the last unread address after this function is
+ *                        returned, so you can call this function serval times without
+ *                        update this start address.
+ * @param[in]  size       Size of disabled flash area
+ *
+ * @return  0 : On success, EIO : If an error occurred with any step
+ */
+int32_t hal_flash_dis_secure(hal_partition_t partition, uint32_t off_set, uint32_t size);
+
+#endif /* HAL_FLASH_H */
+

+ 158 - 0
fs/vfs/include/hal/soc/gpio.h

@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_GPIO_H
+#define HAL_GPIO_H
+
+/*
+ * Pin configuration
+ */
+typedef enum {
+    /*GPIO MODE*/
+    GPIO_CONFIG_MODE_AF = 0x1,
+    GPIO_CONFIG_MODE_OUTPUT = 0x2,
+    GPIO_CONFIG_MODE_INPUT = 0x3,
+
+    /*GPIO PULL MODE*/
+    GPIO_CONFIG_PULL_NONE = 0x10,
+    GPIO_CONFIG_PULL_UP = 0x20,
+    GPIO_CONFIG_PULL_DOWN = 0x30,
+} gpio_config_t;
+
+/*
+ * GPIO dev struct
+ */
+typedef struct {
+    uint8_t       port;    /* gpio port */
+    gpio_config_t config;  /* gpio config */
+    void         *priv;    /* priv data */
+    uint8_t       level;   /* record latest level */
+} gpio_dev_t;
+
+/*
+ * GPIO interrupt trigger
+ */
+typedef enum {
+    IRQ_TRIGGER_RISING_EDGE  = 0x1, /* Interrupt triggered at input signal's rising edge  */
+    IRQ_TRIGGER_FALLING_EDGE = 0x2, /* Interrupt triggered at input signal's falling edge */
+    IRQ_TRIGGER_BOTH_EDGES   = IRQ_TRIGGER_RISING_EDGE | IRQ_TRIGGER_FALLING_EDGE,
+} gpio_irq_trigger_t;
+
+/*
+ * GPIO interrupt callback handler
+ */
+typedef void (*gpio_irq_handler_t)(void *arg);
+
+/**
+ * Initialises a GPIO pin
+ *
+ * @note  Prepares a GPIO pin for use.
+ *
+ * @param[in]  gpio           the gpio pin which should be initialised
+ * @param[in]  configuration  A structure containing the required gpio configuration
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_init(gpio_dev_t *gpio);
+
+/**
+ * Sets an output GPIO pin high
+ *
+ * @note  Using this function on a gpio pin which is set to input mode is undefined.
+ *
+ * @param[in]  gpio  the gpio pin which should be set high
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_output_high(gpio_dev_t *gpio);
+
+/**
+ * Sets an output GPIO pin low
+ *
+ * @note  Using this function on a gpio pin which is set to input mode is undefined.
+ *
+ * @param[in]  gpio  the gpio pin which should be set low
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_output_low(gpio_dev_t *gpio);
+
+/**
+ * Trigger an output GPIO pin's output. Using this function on a
+ * gpio pin which is set to input mode is undefined.
+ *
+ * @param[in]  gpio  the gpio pin which should be set low
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_output_toggle(gpio_dev_t *gpio);
+
+/**
+ * Get the state of an input GPIO pin. Using this function on a
+ * gpio pin which is set to output mode will return an undefined value.
+ *
+ * @param[in]  gpio   the gpio pin which should be read
+ * @param[in]  value  gpio value
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_input_get(gpio_dev_t *gpio, uint8_t *value);
+
+/**
+ * Set the GPIO pulltype 
+ *
+ * @param[in]  gpio the gpio pin which should be set
+ * @param[in]  pulltype the gpio pulltype value
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hal_gpio_pulltype_set(gpio_dev_t *gpio, gpio_config_t conf);
+
+/**
+ * Enables an interrupt trigger for an input GPIO pin.
+ * Using this function on a gpio pin which is set to
+ * output mode is undefined.
+ *
+ * @param[in]  gpio     the gpio pin which will provide the interrupt trigger
+ * @param[in]  trigger  the type of trigger (rising/falling edge)
+ * @param[in]  handler  a function pointer to the interrupt handler
+ * @param[in]  arg      an argument that will be passed to the interrupt handler
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_enable_irq(gpio_dev_t *gpio, gpio_irq_trigger_t trigger,
+                            gpio_irq_handler_t handler, void *arg);
+
+/**
+ * Disables an interrupt trigger for an input GPIO pin.
+ * Using this function on a gpio pin which has not been set up
+ * using @ref hal_gpio_input_irq_enable is undefined.
+ *
+ * @param[in]  gpio  the gpio pin which provided the interrupt trigger
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_disable_irq(gpio_dev_t *gpio);
+
+/**
+ * Disables an interrupt trigger for an input GPIO pin.
+ * Using this function on a gpio pin which has not been set up
+ * using @ref hal_gpio_input_irq_enable is undefined.
+ *
+ * @param[in]  gpio  the gpio pin which provided the interrupt trigger
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_clear_irq(gpio_dev_t *gpio);
+
+/**
+ * Set a GPIO pin in default state.
+ *
+ * @param[in]  gpio  the gpio pin which should be deinitialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_gpio_finalize(gpio_dev_t *gpio);
+
+#endif /* HAL_GPIO_H */
+

+ 140 - 0
fs/vfs/include/hal/soc/i2c.h

@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_I2C_H
+#define HAL_I2C_H
+
+
+#define I2C_MODE_MASTER 1          /* i2c communication is master mode */
+#define I2C_MODE_SLAVE  2          /* i2c communication is slave mode */
+
+#define I2C_MEM_ADDR_SIZE_8BIT  1  /* i2c menory address size 8bit */
+#define I2C_MEM_ADDR_SIZE_16BIT 2  /* i2c menory address size 16bit */
+
+typedef struct {
+    uint32_t address_width;
+    uint32_t freq;
+    uint8_t  mode;
+    uint16_t dev_addr;
+} i2c_config_t;
+
+typedef struct {
+    uint8_t      port;    /* i2c port */
+    i2c_config_t config;  /* i2c config */
+    void        *priv;    /* priv data */
+} i2c_dev_t;
+
+/**
+ * Initialises an I2C interface
+ * Prepares an I2C hardware interface for communication as a master or slave
+ *
+ * @param[in]  i2c  the device for which the i2c port should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_init(i2c_dev_t *i2c);
+
+/**
+ * I2c master send
+ *
+ * @param[in]  i2c       the i2c device
+ * @param[in]  dev_addr  device address
+ * @param[in]  data      i2c send data
+ * @param[in]  size      i2c send data size
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_master_send(i2c_dev_t *i2c, uint16_t dev_addr, const uint8_t *data,
+                            uint16_t size, uint32_t timeout);
+
+/**
+ * I2c master recv
+ *
+ * @param[in]   i2c       the i2c device
+ * @param[in]   dev_addr  device address
+ * @param[out]  data      i2c receive data
+ * @param[in]   size      i2c receive data size
+ * @param[in]   timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                        if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_master_recv(i2c_dev_t *i2c, uint16_t dev_addr, uint8_t *data,
+                            uint16_t size, uint32_t timeout);
+
+/**
+ * I2c slave send
+ *
+ * @param[in]  i2c      the i2c device
+ * @param[in]  data     i2c slave send data
+ * @param[in]  size     i2c slave send data size
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_slave_send(i2c_dev_t *i2c, const uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * I2c slave receive
+ *
+ * @param[in]   i2c      tthe i2c device
+ * @param[out]  data     i2c slave receive data
+ * @param[in]   size     i2c slave receive data size
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_slave_recv(i2c_dev_t *i2c, uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * I2c mem write
+ *
+ * @param[in]  i2c            the i2c device
+ * @param[in]  dev_addr       device address
+ * @param[in]  mem_addr       mem address
+ * @param[in]  mem_addr_size  mem address
+ * @param[in]  data           i2c master send data
+ * @param[in]  size           i2c master send data size
+ * @param[in]  timeout        timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                            if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_mem_write(i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
+                          uint16_t mem_addr_size, const uint8_t *data, uint16_t size,
+                          uint32_t timeout);
+
+/**
+ * I2c master mem read
+ *
+ * @param[in]   i2c            the i2c device
+ * @param[in]   dev_addr       device address
+ * @param[in]   mem_addr       mem address
+ * @param[in]   mem_addr_size  mem address
+ * @param[out]  data           i2c master send data
+ * @param[in]   size           i2c master send data size
+ * @param[in]  timeout         timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                             if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred during initialisation
+ */
+int32_t hal_i2c_mem_read(i2c_dev_t *i2c, uint16_t dev_addr, uint16_t mem_addr,
+                         uint16_t mem_addr_size, uint8_t *data, uint16_t size,
+                         uint32_t timeout);
+
+/**
+ * Deinitialises an I2C device
+ *
+ * @param[in]  i2c  the i2c device
+ *
+ * @return  0 : on success, EIO : if an error occurred during deinitialisation
+ */
+int32_t hal_i2c_finalize(i2c_dev_t *i2c);
+
+#endif /* HAL_I2C_H */
+

+ 54 - 0
fs/vfs/include/hal/soc/interpt.h

@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_INTERPT_H
+#define HAL_INTERPT_H
+
+typedef void (*hal_interpt_t)(int32_t vec, void *para);
+
+typedef struct {
+    hal_interpt_t fun;
+    void         *para;
+} hal_interpt_desc_t;
+
+
+/**
+ * Interrupt vector init
+ *
+ * @return  0 : on success, -1 : if an error occurred with any step
+ */
+int32_t hal_interpt_init(void);
+
+/**
+ * Mask specified interrupt vector
+ *
+ *
+ * @param[in] vec specified interrupt vector
+ *
+ * @return  0 : on success, -1 : if an error occurred with any step
+ */
+int32_t hal_interpt_mask(int32_t vec);
+
+/**
+ * Unmask specified interrupt vector
+ *
+ *
+ * @param[in] vec specified interrupt vector
+ *
+ * @return  0 : on success, -1 : if an error occurred with any step
+ */
+int32_t hal_interpt_umask(int32_t vec);
+
+/**
+ * Install specified interrupt vector
+ *
+ *
+ * @param[in] vec specified interrupt vector
+ *
+ * @return  0 : on success, -1 : if an error occurred with any step
+ */
+int32_t hal_interpt_install(int32_t vec, hal_interpt_t handler, 
+                                     void *para,  char *name);
+#endif
+

+ 105 - 0
fs/vfs/include/hal/soc/nand.h

@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_NAND_H
+#define HAL_NAND_H
+
+typedef struct {
+    uint32_t page_size;         /* NAND memory page size w/o spare area */
+    uint32_t spare_area_size;   /* NAND memory spare area size */
+    uint32_t block_size;        /* NAND memory block size number of pages */
+    uint32_t zone_size;         /* NAND memory zone size measured in number of blocks */
+    uint32_t zone_number;       /* NAND memory number of zones */
+} nand_config_t;
+
+typedef struct {
+    uint16_t page;      /* NAND memory Page address */
+    uint16_t block;     /* NAND memory Block address */
+    uint16_t zone;      /* NAND memory Zone address */
+} nand_addr_t;
+
+typedef struct {
+    uint32_t         base_addr;
+    nand_config_t    config;
+    void            *priv;  
+} nand_dev_t;
+
+/**
+ * Initialises a nand flash interface
+ *
+ * @param[in]  nand  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_init(nand_dev_t *nand);
+
+/**
+ * Deinitialises a nand flash interface
+ *
+ * @param[in]  nand  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_finalize(nand_dev_t *nand);
+
+/**
+ * Read nand page(s)
+ *
+ * @param[in]   nand        the interface which should be initialised
+ * @param[out]  data        pointer to the buffer which will store incoming data
+ * @param[in]   addr        nand address
+ * @param[in]   page_count  the number of pages to read
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_read_page(nand_dev_t *nand, nand_addr_t *addr, uint8_t *data, uint32_t page_count);
+
+
+/**
+ * Write nand page(s)
+ *
+ * @param[in]   nand        the interface which should be initialised
+ * @param[in]   data        pointer to source buffer to write
+ * @param[in]   addr        nand address
+ * @param[in]   page_count  the number of pages to write
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_write_page(nand_dev_t *nand, nand_addr_t *addr, uint8_t *data, uint32_t page_count);
+
+/**
+ * Read nand spare area
+ *
+ * @param[in]   nand      the interface which should be initialised
+ * @param[out]  data      pointer to the buffer which will store incoming data
+ * @param[in]   addr      nand address
+ * @param[in]   data_len  the number of spares to read
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_read_spare(nand_dev_t *nand, nand_addr_t *addr, uint8_t *data, uint32_t data_len);
+
+
+/**
+ * Write nand spare area
+ *
+ * @param[in]   nand      the interface which should be initialised
+ * @param[in]   data      pointer to source buffer to write
+ * @param[in]   addr      nand address
+ * @param[in]   data_len  the number of spares to write
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_write_spare(nand_dev_t *nand, nand_addr_t *addr, uint8_t *data, uint32_t data_len);
+
+/**
+ * Erase nand block
+ *
+ * @param[in]   nand      the interface which should be initialised
+ * @param[in]   addr      nand address
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nand_erase_block(nand_dev_t *nand, nand_addr_t *addr);
+#endif

+ 83 - 0
fs/vfs/include/hal/soc/nor.h

@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_NOR_H
+#define HAL_NOR_H
+
+typedef struct {
+    uint32_t block_size;        /* NOR memory block size number of bytes */
+    uint32_t chip_size;         /* NOR memory chip size measured in number of blocks */
+} nor_config_t;
+
+typedef struct {
+    uint32_t         base_addr;
+    nor_config_t     config;
+    void            *priv;  
+} nor_dev_t;
+
+/**
+ * Initialises a nor flash interface
+ *
+ * @param[in]  nor  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nor_init(nor_dev_t *nor);
+
+/**
+ * Deinitialises a nor flash interface
+ *
+ * @param[in]  nand  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nor_finalize(nor_dev_t *nor);
+
+/**
+ * Read data from NOR memory
+ *
+ * @param[in]   nor         the interface which should be initialised
+ * @param[out]  data        pointer to the buffer which will store incoming data
+ * @param[in]   addr        nor memory address
+ * @param[in]   len         the number of bytes to read 
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nor_read(nor_dev_t *nor, uint32_t *addr, uint8_t *data, uint32_t len);
+
+
+/**
+ * Write data to NOR memory
+ *
+ * @param[in]   nor         the interface which should be initialised
+ * @param[in]   data        pointer to source buffer to write
+ * @param[in]   addr        nor memory address
+ * @param[in]   len         the number of bytes to write
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nor_write(nor_dev_t *nor, uint32_t *addr, uint8_t *data, uint32_t len);
+ 
+/*
+ * Erase the blocks of the NOR memory
+ *
+ * @param[in]   nor         the interface which should be initialised
+ * @param[in]   addr        nor memory address
+ * @param[in]   block_count the number of block to erase
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nor_erase_block(nor_dev_t *nor, uint32_t *addr, uint32_t block_count);
+
+/*
+ * Erase the entire NOR chip
+ *
+ * @param[in]   nor         the interface which should be initialised
+ * @param[in]   addr        nor memory address
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_nor_erase_chip(nor_dev_t *nor, uint32_t *addr);
+
+#endif

+ 68 - 0
fs/vfs/include/hal/soc/pwm.h

@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_PWM_H
+#define HAL_PWM_H
+
+typedef struct {
+    float    duty_cycle;  /* the pwm duty_cycle */
+    uint32_t freq;        /* the pwm freq */
+} pwm_config_t;
+
+typedef struct {
+    uint8_t      port;    /* pwm port */
+    pwm_config_t config;  /* spi config */
+    void        *priv;    /* priv data */
+} pwm_dev_t;
+
+/**
+ * Initialises a PWM pin
+ *
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_pwm_init_bydev(pwm_dev_t *pwm);
+
+/**
+ * Starts Pulse-Width Modulation signal output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_pwm_start_bydev(pwm_dev_t *pwm);
+
+/**
+ * Stops output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_pwm_stop_bydev(pwm_dev_t *pwm);
+
+/**
+ * change the para of pwm
+ *
+ * @param[in]  pwm  the PWM device
+ * @param[in]  para the para of pwm
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_pwm_para_chg_bydev(pwm_dev_t *pwm, pwm_config_t para);
+
+int32_t hal_pwm_set_duty_bydev(pwm_dev_t *pwm, float duty);
+int32_t hal_pwm_set_freq_bydev(pwm_dev_t *pwm, uint32_t freq);
+/**
+ * De-initialises an PWM interface, Turns off an PWM hardware interface
+ *
+ * @param[in]  pwm  the interface which should be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_pwm_finalize_bydev(pwm_dev_t *pwm);
+
+#endif /* HAL_PWM_H */

+ 93 - 0
fs/vfs/include/hal/soc/qspi.h

@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_QSPI_H
+#define HAL_QSPI_H
+
+typedef struct {
+    uint32_t freq;        /* communication frequency Hz */
+} qspi_config_t;
+
+typedef struct {
+    uint8_t       port;    /* qspi port */
+    qspi_config_t config;  /* qspi config */
+    void         *priv;    /* priv data */
+} qspi_dev_t;
+
+typedef struct {
+    uint32_t instruction;   /* qspi instruction */
+    uint32_t address;       /* qspi cmd address */
+    uint32_t size;          /* qspi cmd size */
+} qspi_cmd_t;
+
+/**
+ * Initialises the QSPI interface for a given QSPI device
+ *
+ * @param[in]  qspi  the spi device
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_qspi_init(qspi_dev_t *qspi);
+
+/**
+ * Qspi send
+ *
+ * @param[in]  qspi     the qspi device
+ * @param[in]  data     spi send data
+ * @param[in]  size     spi send data size
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_qspi_send(qspi_dev_t *qspi, const uint8_t *data, uint32_t timeout);
+
+/**
+ * Qspi recv
+ *
+ * @param[in]   qspi     the qspi device
+ * @param[out]  data     qspi recv data
+ * @param[in]   size     qspi recv data size
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_qspi_recv(qspi_dev_t *qspi, uint8_t *data, uint32_t timeout);
+
+/**
+ * Set qspi command
+ *
+ * @param[in]   qspi     the qspi device
+ * @param[out]  cmd      qspi cmd
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_qspi_command(qspi_dev_t *qspi, qspi_cmd_t *cmd, uint32_t timeout);
+
+/**
+ * Configure automatic polling mode to wait for processing
+ *
+ * @param[in]   qspi     the qspi device
+ * @param[out]  cmd      qspi cmd
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_qspi_auto_polling(qspi_dev_t *qspi, uint32_t cmd, uint32_t timeout);
+
+/**
+ * De-initialises a QSPI interface
+ *
+ * @param[in]  qspi the QSPI device to be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_qspi_finalize(qspi_dev_t *qspi);
+
+#endif /* HAL_QSPI_H */
+

+ 26 - 0
fs/vfs/include/hal/soc/rng.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_RNG_H
+#define HAL_RNG_H
+
+typedef struct {
+    uint8_t port; /* random device port */
+    void   *priv; /* priv data */
+} random_dev_t;
+
+/**
+ * Fill in a memory buffer with random data
+ *
+ * @param[in]   random       the random device
+ * @param[out]  inBuffer     Point to a valid memory buffer, this function will fill
+ *                           in this memory with random numbers after executed
+ * @param[in]   inByteCount  Length of the memory buffer (bytes)
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_random_num_read(random_dev_t random, void *buf, int32_t bytes);
+
+#endif /* HAL_RNG_H */
+

+ 74 - 0
fs/vfs/include/hal/soc/rtc.h

@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_RTC_H
+#define HAL_RTC_H
+
+#define HAL_RTC_FORMAT_DEC  1
+#define HAL_RTC_FORMAT_BCD  2
+
+typedef struct {
+    uint8_t  format;    /* time formart DEC or BCD */
+} rtc_config_t;
+
+typedef struct {
+    uint8_t port;        /* rtc port */
+    rtc_config_t config; /* rtc config */
+    void   *priv;        /* priv data */
+} rtc_dev_t;
+
+/*
+ * RTC time
+ */
+typedef struct {
+    uint8_t sec;         /* DEC format:value range from 0 to 59, BCD format:value range from 0x00 to 0x59 */
+    uint8_t min;         /* DEC format:value range from 0 to 59, BCD format:value range from 0x00 to 0x59 */
+    uint8_t hr;          /* DEC format:value range from 0 to 23, BCD format:value range from 0x00 to 0x23 */
+    uint8_t weekday;     /* DEC format:value range from 1 to  7, BCD format:value range from 0x01 to 0x07 */
+    uint8_t date;        /* DEC format:value range from 1 to 31, BCD format:value range from 0x01 to 0x31 */
+    uint8_t month;       /* DEC format:value range from 1 to 12, BCD format:value range from 0x01 to 0x12 */
+    uint8_t year;        /* DEC format:value range from 0 to 99, BCD format:value range from 0x00 to 0x99 */
+} rtc_time_t;
+
+/**
+ * This function will initialize the on board CPU real time clock
+ *
+ *
+ * @param[in]  rtc  rtc device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_rtc_init(rtc_dev_t *rtc);
+
+/**
+ * This function will return the value of time read from the on board CPU real time clock.
+ *
+ * @param[in]   rtc   rtc device
+ * @param[out]  time  pointer to a time structure
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_rtc_get_time(rtc_dev_t *rtc, rtc_time_t *time);
+
+/**
+ * This function will set MCU RTC time to a new value.
+ *
+ * @param[in]   rtc   rtc device
+ * @param[out]  time  pointer to a time structure
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_rtc_set_time(rtc_dev_t *rtc, const rtc_time_t *time);
+
+/**
+ * De-initialises an RTC interface, Turns off an RTC hardware interface
+ *
+ * @param[in]  RTC  the interface which should be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_rtc_finalize(rtc_dev_t *rtc);
+
+#endif /* HAL_RTC_H */
+

+ 118 - 0
fs/vfs/include/hal/soc/sd.h

@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_SD_H
+#define HAL_SD_H
+
+#include <stdint.h>
+
+typedef enum {
+    SD_STAT_RESET,
+    SD_STAT_READY,
+    SD_STAT_TIMEOUT,
+    SD_STAT_BUSY,
+    SD_STAT_PROGRAMMING,
+    SD_STAT_RECEIVING,
+    SD_STAT_TRANSFER,
+    SD_STAT_ERR
+} hal_sd_stat;
+
+typedef struct {
+    uint32_t blk_nums; /* sd total block nums */
+    uint32_t blk_size; /* sd block size */
+} hal_sd_info_t;
+
+/*
+ * UART configuration
+ */
+typedef struct {
+    uint32_t bus_wide;  /* sd bus wide */
+    uint32_t freq;      /* sd freq */
+} sd_config_t;
+
+typedef struct {
+    uint8_t       port;    /* sd port */
+    sd_config_t   config;  /* sd config */
+    void         *priv;    /* priv data */
+} sd_dev_t;
+
+/**
+ * Initialises a sd interface
+ *
+ * @param[in]  sd  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_init(sd_dev_t *sd);
+
+/**
+ * Read sd blocks
+ *
+ * @param[in]   sd        the interface which should be initialised
+ * @param[out]  data      pointer to the buffer which will store incoming data
+ * @param[in]   blk_addr  sd blk addr
+ * @param[in]   blks      sd blks
+ * @param[in]   timeout   timeout in milisecond
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_blks_read(sd_dev_t *sd, uint8_t *data, uint32_t blk_addr,
+                         uint32_t blks, uint32_t timeout);
+
+/**
+ * Write sd blocks
+ *
+ * @param[in]  sd        the interface which should be initialised
+ * @param[in]  data      pointer to the buffer which will store incoming data
+ * @param[in]  blk_addr  sd blk addr
+ * @param[in]  blks      sd blks
+ * @param[in]  timeout   timeout in milisecond
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_blks_write(sd_dev_t *sd, uint8_t *data, uint32_t blk_addr,
+                          uint32_t blks, uint32_t timeout);
+
+/**
+ * Erase sd blocks
+ *
+ * @param[in]  sd              the interface which should be initialised
+ * @param[in]  blk_start_addr  sd blocks start addr
+ * @param[in]  blk_end_addr    sd blocks end addr
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_erase(sd_dev_t *sd, uint32_t blk_start_addr, uint32_t blk_end_addr);
+
+/**
+ * Get sd state
+ *
+ * @param[in]   sd    the interface which should be initialised
+ * @param[out]  stat  pointer to the buffer which will store incoming data
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_stat_get(sd_dev_t *sd, hal_sd_stat *stat);
+
+/**
+ * Get sd info
+ *
+ * @param[in]   sd    the interface which should be initialised
+ * @param[out]  stat  pointer to the buffer which will store incoming data
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_info_get(sd_dev_t *sd, hal_sd_info_t *info);
+
+/**
+ * Deinitialises a sd interface
+ *
+ * @param[in]  sd  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_sd_finalize(sd_dev_t *sd);
+
+#endif /* HAL_SD_H */
+

+ 32 - 0
fs/vfs/include/hal/soc/soc.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_SOC_H
+#define HAL_SOC_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <hal/soc/adc.h>
+#include <hal/soc/flash.h>
+#include <hal/soc/gpio.h>
+#include <hal/soc/i2c.h>
+#include <hal/soc/nand.h>
+#include <hal/soc/nor.h>
+#include <hal/soc/pwm.h>
+#include <hal/soc/qspi.h>
+#include <hal/soc/rng.h>
+#include <hal/soc/rtc.h>
+#include <hal/soc/sd.h>
+#include <hal/soc/spi.h>
+#include <hal/soc/timer.h>
+#include <hal/soc/uart.h>
+#include <hal/soc/wdg.h>
+#include <hal/soc/interpt.h>
+#include <hal/soc/dac.h>
+
+#define HAL_WAIT_FOREVER  0xFFFFFFFFU
+
+#endif /* HAL_SOC_H */
+

+ 87 - 0
fs/vfs/include/hal/soc/spi.h

@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_SPI_H
+#define HAL_SPI_H
+
+#define HAL_SPI_MODE_MASTER 1  /* spi communication is master mode */
+#define HAL_SPI_MODE_SLAVE  2  /* spi communication is slave mode */
+
+typedef struct {
+    uint8_t mode;           /* spi communication mode */
+    uint32_t freq;          /* communication frequency Hz */
+} spi_config_t;
+
+typedef struct {
+    uint8_t      port;    /* spi port */
+    spi_config_t config;  /* spi config */
+    void        *priv;    /* priv data */
+} spi_dev_t;
+
+/**
+ * Initialises the SPI interface for a given SPI device
+ *
+ * @param[in]  spi  the spi device
+ *
+ * @return  0 : on success, EIO : if the SPI device could not be initialised
+ */
+int32_t hal_spi_init(spi_dev_t *spi);
+
+/**
+ * Spi send
+ *
+ * @param[in]  spi      the spi device
+ * @param[in]  data     spi send data
+ * @param[in]  size     spi send data size
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if the SPI device could not be initialised
+ */
+int32_t hal_spi_send(spi_dev_t *spi, const uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * spi_recv
+ *
+ * @param[in]   spi      the spi device
+ * @param[out]  data     spi recv data
+ * @param[in]   size     spi recv data size
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if the SPI device could not be initialised
+ */
+int32_t hal_spi_recv(spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * spi send data and recv
+ *
+ * @param[in]  spi      the spi device
+ * @param[in]  tx_data  spi send data
+ * @param[in]  rx_data  spi recv data
+ * @param[in]  size     spi data to be sent and recived
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  0, on success;  EIO : if the SPI device could not be initialised
+ */
+int32_t hal_spi_send_recv(spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data,
+                          uint16_t size, uint32_t timeout);
+
+/**
+ * De-initialises a SPI interface
+ *
+ *
+ * @param[in]  spi the SPI device to be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred
+ */
+int32_t hal_spi_finalize(spi_dev_t *spi);
+
+int hal_spi_set_rwmode(spi_dev_t *spi_dev, int mode);
+int hal_spi_set_rwspeed(spi_dev_t *spi_dev, uint32_t speed);
+int hal_spi_transfer(spi_dev_t *spi_dev, void *xfer, uint8_t size);/* spi_ioc_transfer_t */
+
+#endif /* HAL_SPI_H */
+

+ 63 - 0
fs/vfs/include/hal/soc/timer.h

@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_TIMER_H
+#define HAL_TIMER_H
+
+#define TIMER_RELOAD_AUTO  1  /* timer reload automatic */
+#define TIMER_RELOAD_MANU  2  /* timer reload manual */
+
+typedef void (*hal_timer_cb_t)(void *arg);
+
+typedef struct {
+    uint32_t       period;   /*us*/
+    uint8_t        reload_mode;
+    hal_timer_cb_t cb;
+    void          *arg;
+} timer_config_t;
+
+typedef struct {
+    int8_t         port;   /* timer port */
+    timer_config_t config; /* timer config */
+    void          *priv;   /* priv data */
+} timer_dev_t;
+
+/**
+ * init a hardware timer
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_timer_init(timer_dev_t *tim);
+
+/**
+ * start a hardware timer
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_timer_start(timer_dev_t *tim);
+
+/**
+ * stop a hardware timer
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  none
+ */
+void hal_timer_stop(timer_dev_t *tim);
+
+/**
+ * De-initialises an TIMER interface, Turns off an TIMER hardware interface
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_timer_finalize(timer_dev_t *tim);
+
+#endif /* HAL_TIMER_H*/
+

+ 229 - 0
fs/vfs/include/hal/soc/uart.h

@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_UART_H
+#define HAL_UART_H
+
+#include <hosal_uart.h>
+#if 0
+/*
+ * UART data width
+ */
+typedef enum {
+    DATA_WIDTH_5BIT,
+    DATA_WIDTH_6BIT,
+    DATA_WIDTH_7BIT,
+    DATA_WIDTH_8BIT,
+    DATA_WIDTH_9BIT
+} hal_uart_data_width_t;
+
+/*
+ * UART stop bits
+ */
+typedef enum {
+    STOP_BITS_1,
+    STOP_BITS_2
+} hal_uart_stop_bits_t;
+
+/*
+ * UART flow control
+ */
+typedef enum {
+    FLOW_CONTROL_DISABLED,
+    FLOW_CONTROL_CTS,
+    FLOW_CONTROL_RTS,
+    FLOW_CONTROL_CTS_RTS
+} hal_uart_flow_control_t;
+
+/*
+ * UART parity
+ */
+typedef enum {
+    NO_PARITY,
+    ODD_PARITY,
+    EVEN_PARITY
+} hal_uart_parity_t;
+
+/*
+ * UART mode
+ */
+typedef enum {
+    MODE_TX,
+    MODE_RX,
+    MODE_TX_RX
+} hal_uart_mode_t;
+
+/*
+ * UART int type
+ */
+typedef enum {
+    UART_TX_INT,
+    UART_RX_INT,
+} hal_uart_int_t;
+
+/*
+ * UART configuration
+ */
+typedef struct {
+    uint32_t                baud_rate;
+    hal_uart_data_width_t   data_width;
+    hal_uart_parity_t       parity;
+    hal_uart_stop_bits_t    stop_bits;
+    hal_uart_flow_control_t flow_control;
+    hal_uart_mode_t         mode;
+} uart_config_t;
+
+#define UART_READ_CFG_BLOCK   1
+#define UART_READ_CFG_NOBLOCK 2
+
+typedef struct {
+    uint8_t       port;    /* uart port */
+    uart_config_t config;  /* uart config */
+    void         *rx_ringbuf_handle;
+    void         *tx_ringbuf_handle;
+    uint32_t     rx_buf_size;
+    uint32_t     tx_buf_size;
+    void         *mutex;
+    void         *poll_cb;
+    void         *fd;
+    void         *poll_data;
+    void         *taskhdl;
+    uint8_t      read_block_flag; /* 1 or 2 from IOCTL_UART_IOC_READ_BLOCK, IOCTL_UART_IOC_READ_NOBLOCK */
+    void         *priv;    /* priv data */
+} uart_dev_t;
+
+/**
+ * Initialises a UART interface
+ *
+ *
+ * @param[in]  uart  the interface which should be initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_init(uart_dev_t *uart);
+
+/**
+  * Transmit data flush on a UART interface
+  *
+  * @param[in]  uart     the UART interface
+  * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+  *                      if you want to wait forever
+  *
+  * @return  0 : on success, EIO : if an error occurred with any step
+  */
+int32_t hal_uart_send_flush(uart_dev_t *uart, uint32_t timeout);
+
+/**
+  * set baudrate on a UART interface
+  *
+  * @param[in]  uart     the UART interface
+  * @param[in]  baud     uart baudrate. eg: 9600、115200...
+  *
+  * @return NULL
+  */
+void hal_uart_setbaud(uart_dev_t *uart, uint32_t baud);
+
+/**
+  * set config on a UART interface
+  *
+  * @param[in]  uart     the UART interface
+  * @param[in]  baud     uart baudrate. eg: 9600、115200...
+  * @param[in]  baud     uart parity. eg: NO_PARITY, ODD_PARITY, EVEN_PARITY
+  *
+  * @return NULL
+  */
+void hal_uart_setconfig(uart_dev_t *uart, uint32_t baud, hal_uart_parity_t parity);
+
+/**
+ * Transmit data on a UART interface
+ *
+ * @param[in]  uart     the UART interface
+ * @param[in]  data     pointer to the start of data
+ * @param[in]  size     number of bytes to transmit
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout);
+
+/**
+ * Transmit data Trigger on a UART interface
+ *
+ * @param[in]  uart     the UART interface
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_send_trigger(uart_dev_t *uart);
+
+/**
+ * Transmit data Trigger off a UART interface
+ *
+ * @param[in]  uart     the UART interface
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_send_trigger_off(uart_dev_t *uart);
+
+/**
+ * Receive data on a UART interface
+ *
+ * @param[in]   uart         the UART interface
+ * @param[out]  data         pointer to the buffer which will store incoming data
+ * @param[in]   expect_size  number of bytes to receive
+ * @param[in]   timeout      timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                           if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_recv(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t timeout);
+
+/**
+ * Receive data on a UART interface
+ *
+ * @param[in]   uart         the UART interface
+ * @param[out]  data         pointer to the buffer which will store incoming data
+ * @param[in]   expect_size  number of bytes to receive
+ * @param[out]  recv_size    number of bytes received
+ * @param[in]   timeout      timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                           if you want to wait forever
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_recv_II(uart_dev_t *uart, void *data, uint32_t expect_size,
+                         uint32_t *recv_size, uint32_t timeout);
+
+/**
+ * Deinitialises a UART interface
+ *
+ * @param[in]  uart  the interface which should be deinitialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_finalize(uart_dev_t *uart);
+
+/**
+ * Register notify on a UART interface
+ *
+ * @param[in]  uart  the interface which notify should be noticed
+ * @param[in]  type  the uart int type
+ * @param[in]  cb    call back function
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_notify_register(uart_dev_t *uart, hal_uart_int_t type, void (*cb)(void *arg));
+
+/**
+ * Unregister notify on a UART interface
+ *
+ * @param[in]  uart  the interface which notify should be noticed
+ * @param[in]  type  the uart int type
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_uart_notify_unregister(uart_dev_t *uart, hal_uart_int_t type, void (*cb)(void *arg));
+
+#endif
+#endif /* HAL_UART_H */
+

+ 108 - 0
fs/vfs/include/hal/soc/usb_hcd.h

@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef __HAL_USB_HCD_H
+#define __HAL_USB_HCD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * @brief Initialize The USB Host Controller
+ * 
+ * @param[in]  phost pointer to the usb host handler
+ * @param[in]  phcd  pointer to the usb hcd pointer
+ * 
+ * @return 0:success, otherwise is failed
+ */
+int hal_usbh_init(void *phost, void **phcd);
+
+/**
+ * @brief Finalize The USB Host Controller
+ * 
+ * @param[in]  hcd pointer to the usb hcd
+ * 
+ * @return 0:success, otherwise is failed
+ */
+int hal_usbh_finalize(void *hcd);
+
+/**
+ * @brief Reset Host Controller's Port
+ * 
+ * @param[in]  hcd pointer to the usb hcd
+ * 
+ * @return 0:success, otherwise is failed
+ */
+int hal_usbh_port_reset(void *hcd);
+
+/**
+ * @brief Get Device Speed
+ * 
+ * @param[in]  hcd pointer to the usb hcd
+ * 
+ * @return the usb host controller's speed (0, 1, 2)
+ */
+int hal_usbh_get_speed(void *hcd);
+
+/**
+ * @brief Free The Host Controll's Pipe
+ * 
+ * @param[in]  hcd      pointer to the usb hcd
+ * @param[in]  pipe_num the index of the pipe
+ * 
+ * @return 0:success, otherwise is failed
+ */
+int hal_usbh_pipe_free(void *hcd, uint8_t pipe_num);
+
+/**
+ * @brief Configure The Host Controller's Pipe
+ * 
+ * @param[in]  hcd      pointer to the usb hcd
+ * @param[in]  index    the index of the pipe
+ * @param[in]  ep_addr  the endpoint address
+ * @param[in]  dev_addr the device address
+ * @param[in]  speed    the device speed
+ * @param[in]  token    the transmit token
+ * @param[in]  ep_type  the endpoint type
+ * @param[in]  mps      the max packet size
+ * 
+ * @return 0:success, otherwise is failed
+ */
+int hal_usbh_pipe_configure(void *hcd, uint8_t index, 
+                            uint8_t ep_addr, uint8_t dev_addr, 
+                            uint8_t speed, uint8_t ep_type, uint16_t mps);
+
+/**
+ * @brief Submit The Urb
+ * 
+ * @param[in]      hcd       pointer to the usb hcd
+ * @param[in]      pipe_num  the index of the pipe
+ * @param[in]      direction the transmit direction
+ * @param[in]      ep_type   the endpoint type
+ * @param[in]      token     the transmit token
+ * @param[in/out]  buf       pointer to the buffer which will be send or recv
+ * @param[in]      length    the length of buffer
+ * 
+ * @return 0:success, otherwise is failed
+ */
+int hal_usbh_submit_urb(void *hcd, uint8_t pipe_num, 
+                           uint8_t direction, uint8_t ep_type, 
+                           uint8_t token, uint8_t *buf, uint16_t length);
+
+/**
+ * @brief Get The Urb Transmit State
+ * 
+ * @param[in]  hcd      pointer to the usb hcd
+ * @param[in]  pipe_num the index of the pipe
+ * 
+ * @return 0:Idle, 1:Done, 2:Not Ready, 3:Nyet, 4:Error, 5:Stall
+ */
+int hal_usbh_get_urb_state(void *hcd, uint8_t pipe_num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HAL_USB_HCD_H */

+ 44 - 0
fs/vfs/include/hal/soc/wdg.h

@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef HAL_WDG_H
+#define HAL_WDG_H
+
+typedef struct {
+    uint32_t timeout;  /* Watchdag timeout */
+} wdg_config_t;
+
+typedef struct {
+    uint8_t      port;   /* wdg port */
+    wdg_config_t config; /* wdg config */
+    void        *priv;   /* priv data */
+} wdg_dev_t;
+
+/**
+ * This function will initialize the on board CPU hardware watch dog
+ *
+ * @param[in]  wdg  the watch dog device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_wdg_init(wdg_dev_t *wdg);
+
+/**
+ * Reload watchdog counter.
+ *
+ * @param[in]  wdg  the watch dog device
+ */
+void hal_wdg_reload(wdg_dev_t *wdg);
+
+/**
+ * This function performs any platform-specific cleanup needed for hardware watch dog.
+ *
+ * @param[in]  wdg  the watch dog device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int32_t hal_wdg_finalize(wdg_dev_t *wdg);
+
+#endif /* HAL_WDG_H */
+

+ 270 - 0
fs/vfs/include/vfs.h

@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_H
+#define AOS_VFS_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "vfs_dir.h"
+#include "vfs_inode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*section for ADC IOCTRL*/
+#define IOCTL_ADC_TRIGGER_DISABLE                      (0)
+#define IOCTL_ADC_TRIGGER_ENABLE_HIGH_LEVEL            (1)
+#define IOCTL_ADC_TRIGGER_ENABLE_LOW_LEVEL             (2)
+#define IOCTL_ADC_TRIGGER_ENABLE_LEVEL_CUSTOM_HIGHER   (3)
+#define IOCTL_ADC_TRIGGER_ENABLE_LEVEL_CUSTOM_LOWER    (4)
+
+/* section for ROMFS IOCCTRL */
+#define IOCTL_ROMFS_GET_FILEBUF                        (1)
+
+/*section for GPIO IOCTRL*/
+#define IOCTL_GPIO_PULL_UP                             (0)  /* PULLUP */
+#define IOCTL_GPIO_PULL_DOWN                           (1)  /* PULLDOWN */
+#define IOCTL_GPIO_PULL_NONE                           (2)  /* PULLNONE */
+
+/*section for GPIO OUTPUT*/
+#define OUTPUT_LOW                                     (0)  /* low level output */
+#define OUTPUT_HIGH                                    (1)  /* high level output */
+#define OUTPUT_TOGGLE                                  (2)  /* toggle output */
+
+/**
+ * Init vfs.
+ *
+ * @param[in] NULL
+ *
+ * @return 0 on success, negative error on failure.
+ */
+int vfs_init(void);
+
+/**
+ * Open the file or device by its path.
+ *
+ * @param[in]  path   the path of the file or device to open.
+ * @param[in]  flags  the mode of open operation.
+ *
+ * @return  the new file descriptor, negative error on failure.
+ */
+int aos_open(const char *path, int flags);
+
+/**
+ * Close the file or device by its file descriptor.
+ *
+ * @param[in]  fd  the file descriptor of the file or device.
+ *
+ * @return  0 on success, negative error on failure.
+ */
+int aos_close(int fd);
+
+/**
+ * Read the contents of a file or device into a buffer.
+ *
+ * @param[in]   fd      the file descriptor of the file or device.
+ * @param[in]   nbytes  the number of bytes to read.
+ * @param[out]  buf     the buffer to read in to.
+ *
+ * @return  The number of bytes read, 0 at end of file, negative error on failure.
+ */
+ssize_t aos_read(int fd, void *buf, size_t nbytes);
+
+/**
+ * Write the contents of a buffer to file or device.
+ *
+ * @param[in]  fd      the file descriptor of the file or device.
+ * @param[in]  nbytes  the number of bytes to write.
+ * @param[in]  buf     the buffer to write from.
+ *
+ * @return  The number of bytes written, negative error on failure.
+ */
+ssize_t aos_write(int fd, const void *buf, size_t nbytes);
+
+/**
+ * This is a wildcard API for sending controller specific commands.
+ *
+ * @param[in]  fd   the file descriptior of the file or device.
+ * @param[in]  cmd  A controller specific command.
+ * @param[in]  arg  Argument to the command, interpreted according to the command.
+ *
+ * @return  any return from the command.
+ */
+int aos_ioctl(int fd, int cmd, unsigned long arg);
+
+/**
+ * A mechanism to multiplex input/output over a set of file descriptors.
+ * For every file descriptor provided, poll() examines it for any events registered for that particular file descriptor.
+ *
+ * @param[in]  fds      a point to the array of pollfd struct carrying a file descriptor and bitmasks of events.
+ * @param[in]  nfhs     number of file descriptors.
+ * @param[in]  timeout  timer value to timeout or -1 for loop forever.
+ *
+ * @return  number of file descriptors selected (for which revents is non-zero). 0 if timed out with nothing selected. -1 for error.
+ */
+int aos_poll(struct pollfd *fds, int nfds, int timeout);
+
+/**
+ * Performs one of the operations described below on the open file descriptor, The operation is determined by cmd.
+ *
+ * @param[in]  fd   the file descriptor of the file or device.
+ * @param[in]  cmd  the operation of the file or device.
+ * @param[in]  val  it depends on whether cmd need params.
+ *
+ * @return  0 on success, negative error on failure.
+ */
+int aos_fcntl(int fd, int cmd, int val);
+
+/**
+ * Move the file position to a given offset from a given location.
+ *
+ * @param[in]  fd      the file descriptor of the file.
+ * @param[in]  offset  The offset from whence to move to.
+ * @param[in]  whence  The start of where to seek.
+ *                     SEEK_SET to start from beginning of file.
+ *                     SEEK_CUR to start from current position in file.
+ *                     SEEK_END to start from end of file.
+ *
+ * @return  The new offset of the file.
+ */
+off_t aos_lseek(int fd, off_t offset, int whence);
+
+/**
+ * Flush any buffers associated with the file.
+ *
+ * @param[in]  fd  the file descriptor of the file.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_sync(int fd);
+
+/**
+ * Store information about the file in a stat structure.
+ *
+ * @param[in]   path  The path of the file to find information about.
+ * @param[out]  st    The stat buffer to write to.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_stat(const char *path, struct stat *st);
+
+/**
+ * Remove a file from the filesystem.
+ *
+ * @param[in]  path  The path of the file to remove.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_unlink(const char *path);
+
+/**
+ * Rename a file in the filesystem.
+ *
+ * @param[in]  oldpath  The path of the file to rename.
+ * @param[in]  newpath  The path to rename it to.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_rename(const char *oldpath, const char *newpath);
+
+/**
+ * Open a directory on the filesystem.
+ *
+ * @param[in]  path  the path of the directory to open.
+ *
+ * @return  a point of directory stream on success, NULL on failure.
+ */
+aos_dir_t *aos_opendir(const char *path);
+
+/**
+ * Close a directory.
+ *
+ * @param[in]  dir  the handle of the directory to close.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_closedir(aos_dir_t *dir);
+
+/**
+ * Read the next directory entry.
+ *
+ * @param[in]  dir  the handle of the directory to read.
+ *
+ * @return  a pointer to a dirent structure.
+ */
+aos_dirent_t *aos_readdir(aos_dir_t *dir);
+
+/**
+ * Create the directory, if they do not already exist.
+ *
+ * @param[in]  path  the path of the directory.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_mkdir(const char *path);
+
+/**
+ * Remove a directory.
+ *
+ * @param[in]  path  the path of the directory.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_rmdir(const char *path);
+
+/**
+ * Reset the position of a directory stream to the beginning of a directory.
+ *
+ * @param[in]  dir  the handle of the directory.
+ *
+ * @return  none.
+ */
+void aos_rewinddir(aos_dir_t *dir);
+
+/**
+ * Obtain the current location associated with the directory stream specified by dirp.
+ *
+ * @param[in]  dir  the handle of the directory.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+long aos_telldir(aos_dir_t *dir);
+
+/**
+ * Reset the position of a directory stream to the beginning of a directory.
+ *
+ * @param[in]  dir  the handle of the directory.
+ * @param[in]  loc  the position of the directory.
+ *
+ * @return  none.
+ */
+void aos_seekdir(aos_dir_t *dir, long loc);
+
+/**
+ * Store information about the file system in a statfs structure.
+ *
+ * @param[in]   path  The path of the file system to find information about.
+ * @param[out]  buf    The statfs buffer to write to.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_statfs(const char *path, struct statfs *buf);
+
+/**
+ * get access info.
+ *
+ * @param path The path of the file.
+ * @param mode the info to get.
+ *
+ * @return  0 on success, negative error code on failure.
+ */
+int aos_access(const char *path, int amode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* AOS_VFS_H */

+ 34 - 0
fs/vfs/include/vfs_conf.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_CONFIG_H
+#define AOS_VFS_CONFIG_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#define VFS_FALSE 0u
+#define VFS_TRUE 1u
+
+#define AOS_CONFIG_VFS_DEV_NODES 30
+/*mem 1000 byte*/
+#define AOS_CONFIG_VFS_POLL_SUPPORT 1
+#define AOS_CONFIG_VFS_FD_OFFSET 2
+
+#define MAX_FILE_NUM (AOS_CONFIG_VFS_DEV_NODES * 2)
+
+#define FILE_BITMAP_NUM ((MAX_FILE_NUM + 31) / 32)
+
+#ifdef _WIN32
+#define CHECK_IF_NON_VFS_FD(_SOCKET)         \
+    ((_SOCKET < AOS_CONFIG_VFS_FD_OFFSET) || \
+     (_SOCKET > (AOS_CONFIG_VFS_FD_OFFSET + AOS_CONFIG_VFS_DEV_NODES)))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 27 - 0
fs/vfs/include/vfs_dir.h

@@ -0,0 +1,27 @@
+#ifndef __VFS_DIR_H__
+#define __VFS_DIR_H__
+
+struct statfs {
+    long f_type;    /* fs type */
+    long f_bsize;   /* optimized transport block size */
+    long f_blocks;  /* total blocks */
+    long f_bfree;   /* available blocks */
+    long f_bavail;  /* number of blocks that non-super users can acquire */
+    long f_files;   /* total number of file nodes */
+    long f_ffree;   /* available file nodes */
+    long f_fsid;    /* fs id */
+    long f_namelen; /* max file name length */
+};
+
+typedef struct {
+    int     d_ino;    /* file number */
+    uint8_t d_type;   /* type of file */
+    char    d_name[]; /* file name */
+} aos_dirent_t;
+
+typedef struct {
+    int dd_vfs_fd;
+    int dd_rsv;
+} aos_dir_t;
+
+#endif

+ 30 - 0
fs/vfs/include/vfs_err.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef VFS_ERRNO_H
+#define VFS_ERRNO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <errno.h>
+
+#define    VFS_SUCCESS               0u
+
+#define VFS_ASSERT(cond)                                    \
+    do {                                                    \
+        if (!(cond)) {                                      \
+            puts("VFS_ASSERT:" #cond);                      \
+            printf(" %s:%d\r\n", __FILE__, __LINE__);   \
+            while(1);                                       \
+        }                                                   \
+    } while(0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VFS_ERRNO_H */
+

+ 28 - 0
fs/vfs/include/vfs_file.h

@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef AOS_VFS_FILE_H
+#define AOS_VFS_FILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int file_init(void);
+
+int get_fd(file_t *file);
+
+file_t *get_file(int fd);
+
+size_t get_all_file (file_t **file, int size);
+
+file_t *new_file(inode_t *node);
+
+void del_file(file_t *file);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 124 - 0
fs/vfs/include/vfs_inode.h

@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef VFS_INODE_H
+#define VFS_INODE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <vfs_conf.h>
+#include "vfs_dir.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    VFS_TYPE_NOT_INIT,
+    VFS_TYPE_CHAR_DEV,
+    VFS_TYPE_BLOCK_DEV,
+    VFS_TYPE_FS_DEV
+};
+
+#define INODE_IS_TYPE(i,t) \
+    ((i)->type == (t))
+
+#define INODE_IS_CHAR(i)   INODE_IS_TYPE(i, VFS_TYPE_CHAR_DEV)
+#define INODE_IS_BLOCK(i)  INODE_IS_TYPE(i, VFS_TYPE_BLOCK_DEV)
+#define INODE_IS_FS(i)     INODE_IS_TYPE(i, VFS_TYPE_FS_DEV)
+
+#define INODE_GET_TYPE(i) ((i)->type)
+#define INODE_SET_TYPE(i,t) \
+    do \
+      { \
+        (i)->type = (t); \
+      } \
+    while(0)
+
+#define INODE_SET_CHAR(i)  INODE_SET_TYPE(i, VFS_TYPE_CHAR_DEV)
+#define INODE_SET_BLOCK(i) INODE_SET_TYPE(i, VFS_TYPE_BLOCK_DEV)
+#define INODE_SET_FS(i)    INODE_SET_TYPE(i, VFS_TYPE_FS_DEV)
+
+typedef const struct file_ops file_ops_t;
+typedef const struct fs_ops   fs_ops_t;
+
+union inode_ops_t {
+    const file_ops_t *i_ops;  /* char driver operations */
+    const fs_ops_t   *i_fops; /* FS operations */
+};
+
+/* this structure represents inode for driver and fs*/
+typedef struct {
+    union inode_ops_t ops;     /* inode operations */
+    void             *i_arg;   /* per inode private data */
+    char             *i_name;  /* name of inode */
+    int               i_flags; /* flags for inode */
+    uint8_t           type;    /* type for inode */
+    uint8_t           refs;    /* refs for inode */
+} inode_t;
+
+typedef struct {
+    inode_t    *node;   /* node for file */
+    void       *f_arg;  /* f_arg for file */
+    size_t      offset; /* offset for file */
+    int         fd;     /* file fd */
+} file_t;
+
+struct pollfd;
+typedef void (*poll_notify_t)(struct pollfd *fd, void *arg);
+struct file_ops {
+    int     (*open)  (inode_t *node, file_t *fp);
+    int     (*close) (file_t *fp);
+    ssize_t (*read)  (file_t *fp, void *buf, size_t nbytes);
+    ssize_t (*write) (file_t *fp, const void *buf, size_t nbytes);
+    int     (*ioctl) (file_t *fp, int cmd, unsigned long arg);
+#ifdef AOS_CONFIG_VFS_POLL_SUPPORT
+    int     (*poll)  (file_t *fp, bool flag, poll_notify_t notify, struct pollfd *fd, void *arg);
+#endif
+    int     (*sync) (file_t *fp);
+};
+
+struct fs_ops {
+    int             (*open)     (file_t *fp, const char *path, int flags);
+    int             (*close)    (file_t *fp);
+    ssize_t         (*read)     (file_t *fp, char *buf, size_t len);
+    ssize_t         (*write)    (file_t *fp, const char *buf, size_t len);
+    off_t           (*lseek)    (file_t *fp, off_t off, int whence);
+    int             (*sync)     (file_t *fp);
+    int             (*stat)     (file_t *fp, const char *path, struct stat *st);
+    int             (*unlink)   (file_t *fp, const char *path);
+    int             (*rename)   (file_t *fp, const char *oldpath, const char *newpath);
+    aos_dir_t      *(*opendir)  (file_t *fp, const char *path);
+    aos_dirent_t   *(*readdir)  (file_t *fp, aos_dir_t *dir);
+    int             (*closedir) (file_t *fp, aos_dir_t *dir);
+    int             (*mkdir)    (file_t *fp, const char *path);
+    int             (*rmdir)    (file_t *fp, const char *path);
+    void            (*rewinddir)(file_t *fp, aos_dir_t *dir);
+    long            (*telldir)  (file_t *fp, aos_dir_t *dir);
+    void            (*seekdir)  (file_t *fp, aos_dir_t *dir, long loc);
+    int             (*ioctl)    (file_t *fp, int cmd, unsigned long arg);
+    int             (*statfs)   (file_t *fp, const char *path, struct statfs *suf);
+    int             (*access)   (file_t *fp, const char *path, int amode);
+};
+
+int     inode_init(void);
+int     inode_alloc(inode_t **node);
+int     inode_del(inode_t *node);
+inode_t *inode_open(const char *path);
+int     inode_ptr_get(int fd, inode_t **node);
+int     inode_avail_count(void);
+void    inode_ref(inode_t *);
+void    inode_unref(inode_t *);
+int     inode_busy(inode_t *);
+int     inode_reserve(const char *path, inode_t **inode);
+int     inode_release(const char *path);
+int     inode_forearch_name(int (*cb)(void *arg, inode_t *node), void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*VFS_INODE_H*/
+

+ 25 - 0
fs/vfs/include/vfs_register.h

@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef VFS_DRIVER_H
+#define VFS_DRIVER_H
+
+#include <vfs_inode.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int aos_register_driver(const char *path, file_ops_t *fops, void *arg);
+int aos_unregister_driver(const char *path);
+
+int aos_register_fs(const char *path, fs_ops_t *fops, void *arg);
+int aos_unregister_fs(const char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif    /*VFS_DRIVER_H*/
+

+ 86 - 0
fs/vfs/posix/dirent.c

@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 Alibaba Group Holding Limited
+ */
+
+#include <dirent.h>
+#include "aos/network.h"
+
+DIR *opendir(const char *dirname)
+{
+    return (DIR *)aos_opendir(dirname);
+}
+
+struct dirent *readdir(DIR *dirp)
+{
+    return (struct dirent *)aos_readdir(dirp);
+}
+
+int closedir(DIR *dirp)
+{
+    return aos_closedir((aos_dir_t *)dirp);
+}
+
+long telldir(DIR *dirp)
+{
+    return aos_telldir((aos_dir_t *)dirp);
+}
+
+void seekdir(DIR *dirp, long loc)
+{
+    return aos_seekdir((aos_dir_t *)dirp, loc);
+}
+
+off_t lseek(int fildes, off_t offset, int whence)
+{
+    return aos_lseek(fildes, offset, whence);
+}
+
+int stat(const char *path, struct stat *buf)
+{
+    return aos_stat(path, buf);
+}
+
+int statfs(const char *path, struct statfs *buf)
+{
+    return aos_statfs(path, buf);
+}
+
+int unlink(const char *path)
+{
+    return aos_unlink(path);
+}
+
+int remove(const char *filename)
+{
+    return aos_unlink(filename);
+}
+
+int rename(const char *oldname, const char *newname)
+{
+    return aos_rename(oldname, newname);
+}
+
+int fsync(int fd)
+{
+    return aos_sync(fd);
+}
+
+int mkdir(const char *path, mode_t mode)
+{
+    return aos_mkdir(path);
+}
+
+int rmdir(const char *path)
+{
+    return aos_rmdir(path);
+}
+
+void rewinddir(DIR *dirp)
+{
+    aos_rewinddir((aos_dir_t *)dirp);
+}
+
+int access(const char *filenpath, int mode)
+{
+    return aos_access(filenpath, mode);
+}

+ 86 - 0
fs/vfs/posix/include/dirent.h

@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 Alibaba Group Holding Limited
+ */
+
+/* dirent.h - POSIX directory handling definitions */
+
+#ifndef __INC_DIRENT_H__
+#define __INC_DIRENT_H__
+
+#include <vfs.h>
+#include <stdio.h>
+#include <vfs_inode.h>
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+    /* function declarations */
+
+    typedef aos_dir_t DIR;
+
+    struct dirent
+    {
+        int     d_ino;    /* file number    */
+        uint8_t d_type;   /* type of file   */
+        char    d_name[]; /* file name      */
+    };
+
+    /* device io functions, open,read,write are defined by newlib */
+    /************************************************************************
+    extern int open(const char *path, int oflag, ...);
+    extern int close(int fildes);
+    extern ssize_t read(int fildes, void *buf, size_t nbyte);
+    extern ssize_t write(int fildes, const void *buf, size_t nbyte);
+
+    extern FILE *fopen(const char *restrict filename, const char *restrict
+    mode); extern FILE *fdopen(int fildes,const char * mode); extern int
+    fclose(FILE *stream); extern size_t fread(void *restrict ptr, size_t size,
+    size_t nitems, FILE *restrict stream); extern size_t fwrite(const void
+    *restrict ptr, size_t size, size_t nitems, FILE *restrict stream); extern
+    int fseek(FILE *stream, long offset, int whence); extern long ftell(FILE
+    *stream); extern int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
+    extern int fsetpos(FILE *stream, const fpos_t *pos);
+    extern char *fgets(char *restrict s, int n, FILE *restrict stream);
+    extern int fputs(const char *restrict s, FILE *restrict stream);
+    extern int access(const char *path, int amode);
+    extern int fflush(FILE *stream);
+    extern int fprintf(FILE *restrict stream, const char *restrict format, ...);
+    **************************************************************************/
+
+    DIR *          opendir(const char *dirname);
+    struct dirent *readdir(DIR *dirp);
+    int            closedir(DIR *dirp);
+    long           telldir(DIR *dirp);
+    void           seekdir(DIR *dirp, long loc);
+    off_t          lseek(int fildes, off_t offset, int whence);
+    int            stat(const char *path, struct stat *buf);
+    int            statfs(const char *path, struct statfs *buf);
+    int            unlink(const char *path);
+    int            remove(const char *filename);
+    int            rename(const char *oldname, const char *newname);
+    int            fsync(int fd);
+    int            mkdir(const char *path, mode_t mode);
+    int            rmdir(const char *path);
+    void           rewinddir(DIR *dirp);
+    int            ioctl(int fildes, int request, ... /* arg */);
+
+    extern int ioctl(int fildes, int request, ... /* arg */);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INC_DIRENT_H__ */

+ 30 - 0
fs/vfs/posix/include/sys/prctl.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __INC_PRCTL_H__
+#define __INC_PRCTL_H__
+
+#include <k_api.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * PR_SET_NAME:
+ *
+ * Set the name of the calling thread, using the value in the
+ * location pointed to by (char *) arg2.
+ */
+
+#define PR_SET_NAME 0x00000000
+
+int prctl(int option, ...);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __INC_PRCTL_H__ */
+

+ 47 - 0
fs/vfs/posix/prctl.c

@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 Alibaba Group Holding Limited
+ */
+
+#include <sys/prctl.h>
+#include <stdarg.h>
+
+int prctl(int option, ...)
+{
+    va_list       ap;
+    unsigned long arg;
+    char         *p_str;
+    ktask_t      *p_tcb;
+    CPSR_ALLOC();
+
+    if (option == PR_SET_NAME) {
+        /* set ap to the start stack address of argument list */
+        va_start(ap, option);
+
+        /*
+         * checkout the first argument from argument list, and force it
+         * to  unsigned long, the ap address will be moved at same time.
+         */
+
+        arg = va_arg(ap, unsigned long);
+
+        va_end(ap);
+
+        p_str = (char *)arg;
+        if (NULL == p_str) {
+            return 1;
+        }
+
+        /* get TCB of current task */
+        RHINO_CRITICAL_ENTER();
+
+        p_tcb = g_active_task[cpu_cur_get()];
+        p_tcb->task_name = p_str;
+
+        RHINO_CRITICAL_EXIT();
+
+        return 0;
+    } else {
+        return 1;
+    }
+}
+

+ 869 - 0
fs/vfs/src/vfs.c

@@ -0,0 +1,869 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+// #include <FreeRTOS.h>
+// #include <semphr.h>
+#include <aos/kernel.h>
+
+#include <vfs_conf.h>
+#include <vfs_err.h>
+#include <vfs_inode.h>
+#include <vfs.h>
+#include <stdio.h>
+#include <limits.h>
+#include <string.h>
+#include <vfs_file.h>
+
+#ifdef IO_NEED_TRAP
+#include <vfs_trap.h>
+#endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+// SemaphoreHandle_t g_vfs_mutex = NULL;
+aos_mutex_t    g_vfs_mutex;
+
+int vfs_init(void)
+{
+    int ret = VFS_SUCCESS;
+
+    // if (NULL != g_vfs_mutex) {
+    //     goto exit;
+    // }
+
+    // if (NULL == (g_vfs_mutex = xSemaphoreCreateMutex())) {
+    //     ret = -1;
+    //     goto exit;
+    // }
+
+    if(aos_mutex_new(&g_vfs_mutex)) {
+        ret = -1;
+        goto exit;
+    }
+
+    if (0 != inode_init() || 0 != file_init()) {
+        // vSemaphoreDelete(g_vfs_mutex);
+        // g_vfs_mutex = NULL;
+        aos_mutex_free(&g_vfs_mutex);
+        ret = -1;
+        goto exit;
+    }
+
+exit:
+    return ret;
+}
+
+int aos_open(const char *path, int flags)
+{
+    file_t  *file;
+    inode_t *node;
+    size_t len = 0;
+    int ret = VFS_SUCCESS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    len = strlen(path);
+    if (len > PATH_MAX) {
+        return -ENAMETOOLONG;
+    }
+
+    // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        ret = -1;
+        return ret;
+    }
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+
+#ifdef IO_NEED_TRAP
+        return trap_open(path, flags);
+#else
+        return -ENOENT;
+#endif
+    }
+
+    node->i_flags = flags;
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return -ENFILE;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->open) != NULL) {
+            ret = (node->ops.i_fops->open)(file, path, flags);
+        }
+
+    } else {
+        if ((node->ops.i_ops->open) != NULL) {
+            ret = (node->ops.i_ops->open)(node, file);
+        }
+    }
+
+    if (ret != VFS_SUCCESS) {
+        del_file(file);
+        return ret;
+    }
+
+    return get_fd(file);
+}
+
+int aos_close(int fd)
+{
+    int ret = VFS_SUCCESS;
+    file_t  *f;
+    inode_t *node;
+
+    f = get_file(fd);
+
+    if (f == NULL) {
+#ifdef IO_NEED_TRAP
+        return trap_close(fd);
+#else
+        return -ENOENT;
+#endif
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->close) != NULL) {
+            ret = (node->ops.i_fops->close)(f);
+        }
+
+    } else {
+
+        if ((node->ops.i_ops->close) != NULL) {
+            ret = (node->ops.i_ops->close)(f);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        ret = -1;
+        return ret;
+    }
+    del_file(f);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    return ret;
+}
+
+ssize_t aos_read(int fd, void *buf, size_t nbytes)
+{
+    ssize_t  nread = -1;
+    file_t  *f;
+    inode_t *node;
+
+    f = get_file(fd);
+
+    if (f == NULL) {
+#ifdef IO_NEED_TRAP
+        return trap_read(fd, buf, nbytes);
+#else
+        return -ENOENT;
+#endif
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->read) != NULL) {
+            nread = (node->ops.i_fops->read)(f, buf, nbytes);
+        }
+    } else {
+        if ((node->ops.i_ops->read) != NULL) {
+            nread = (node->ops.i_ops->read)(f, buf, nbytes);
+        }
+    }
+
+    return nread;
+}
+
+ssize_t aos_write(int fd, const void *buf, size_t nbytes)
+{
+    ssize_t  nwrite = -1;
+    file_t  *f;
+    inode_t *node;
+
+    f = get_file(fd);
+
+    if (f == NULL) {
+#ifdef IO_NEED_TRAP
+        return trap_write(fd, buf, nbytes);
+#else
+        return -ENOENT;
+#endif
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->write) != NULL) {
+            nwrite = (node->ops.i_fops->write)(f, buf, nbytes);
+        }
+    } else {
+        if ((node->ops.i_ops->write) != NULL) {
+            nwrite = (node->ops.i_ops->write)(f, buf, nbytes);
+        }
+    }
+
+    return nwrite;
+}
+
+int aos_ioctl(int fd, int cmd, unsigned long arg)
+{
+    int ret = -ENOSYS;
+    file_t  *f;
+    inode_t *node;
+
+    if (fd < 0) {
+        return -EINVAL;
+    }
+
+    f = get_file(fd);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->ioctl) != NULL) {
+            ret = (node->ops.i_fops->ioctl)(f, cmd, arg);
+        }
+    } else {
+        if ((node->ops.i_ops->ioctl) != NULL) {
+            ret = (node->ops.i_ops->ioctl)(f, cmd, arg);
+        }
+    }
+
+    return ret;
+}
+
+off_t aos_lseek(int fd, off_t offset, int whence)
+{
+    file_t *f;
+    inode_t *node;
+    int ret = -ENOSYS;
+
+    f = get_file(fd);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->lseek) != NULL) {
+            ret = (node->ops.i_fops->lseek)(f, offset, whence);
+        }
+    }
+
+    return ret;
+}
+
+int aos_sync(int fd)
+{
+    file_t  *f;
+    inode_t *node;
+    int ret = -ENOSYS;
+
+    f = get_file(fd);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->sync) != NULL) {
+            ret = (node->ops.i_fops->sync)(f);
+        }
+    } else {
+        if ((node->ops.i_ops->sync) != NULL) {
+            ret = (node->ops.i_ops->sync)(f);
+        }
+    }
+
+    return ret;
+}
+
+int aos_stat(const char *path, struct stat *st)
+{
+    file_t  *file;
+    inode_t *node;
+    int err = 0, ret = -ENOSYS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->stat) != NULL) {
+            ret = (node->ops.i_fops->stat)(file, path, st);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    del_file(file);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+    return ret;
+}
+
+int aos_unlink(const char *path)
+{
+    file_t  *f;
+    inode_t *node;
+    int err, ret = -ENOSYS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    f = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->unlink) != NULL) {
+            ret = (node->ops.i_fops->unlink)(f, path);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    del_file(f);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+    return ret;
+}
+
+int aos_rename(const char *oldpath, const char *newpath)
+{
+    file_t  *f;
+    inode_t *node;
+    int err, ret = -ENOSYS;
+
+    if (oldpath == NULL || newpath == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    node = inode_open(oldpath);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    f = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->rename) != NULL) {
+            ret = (node->ops.i_fops->rename)(f, oldpath, newpath);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    del_file(f);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+    return ret;
+}
+
+aos_dir_t *aos_opendir(const char *path)
+{
+    file_t  *file;
+    inode_t *node;
+    aos_dir_t *dp = NULL;
+
+    if (path == NULL) {
+        return NULL;
+    }
+
+    // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        return NULL;
+    }
+
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return NULL;
+    }
+
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return NULL;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->opendir) != NULL) {
+            dp = (node->ops.i_fops->opendir)(file, path);
+        }
+    }
+
+    if (dp == NULL) {
+        // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+        if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+            return NULL;
+        }
+
+        del_file(file);
+
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return NULL;
+    }
+
+    dp->dd_vfs_fd = get_fd(file);
+    return dp;
+}
+
+int aos_closedir(aos_dir_t *dir)
+{
+    file_t  *f;
+    inode_t *node;
+    int err, ret = -ENOSYS;
+
+    if (dir == NULL) {
+        return -EINVAL;
+    }
+
+    f = get_file(dir->dd_vfs_fd);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->closedir) != NULL) {
+            ret = (node->ops.i_fops->closedir)(f, dir);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    del_file(f);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    return ret;
+}
+
+aos_dirent_t *aos_readdir(aos_dir_t *dir)
+{
+    file_t *f;
+    inode_t *node;
+    aos_dirent_t *ret = NULL;
+
+    if (dir == NULL) {
+        return NULL;
+    }
+
+    f = get_file(dir->dd_vfs_fd);
+    if (f == NULL) {
+        return NULL;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->readdir) != NULL) {
+            ret = (node->ops.i_fops->readdir)(f, dir);
+        }
+    }
+
+    if (ret != NULL) {
+        return ret;
+    }
+
+    return NULL;
+}
+
+int aos_mkdir(const char *path)
+{
+    file_t  *file;
+    inode_t *node;
+    int err, ret = -ENOSYS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+       aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->mkdir) != NULL) {
+            ret = (node->ops.i_fops->mkdir)(file, path);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    del_file(file);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+    return ret;
+}
+
+int aos_rmdir(const char *path)
+{
+    file_t  *file;
+    inode_t *node;
+    int err = -ENOSYS;
+    int ret = -ENOSYS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->rmdir) != NULL) {
+            ret = (node->ops.i_fops->rmdir)(file, path);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY))) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    del_file(file);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+    return ret;
+}
+
+void aos_rewinddir(aos_dir_t *dir)
+{
+    file_t  *f;
+    inode_t *node;
+
+    if (dir == NULL) {
+        return;
+    }
+
+    f = get_file(dir->dd_vfs_fd);
+
+    if (f == NULL) {
+        return;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->rewinddir) != NULL) {
+            (node->ops.i_fops->rewinddir)(f, dir);
+        }
+    }
+
+    return;
+}
+
+long aos_telldir(aos_dir_t *dir)
+{
+    file_t  *f;
+    inode_t *node;
+    long ret = 0;
+
+    if (dir == NULL) {
+        return -EINVAL;
+    }
+
+    f = get_file(dir->dd_vfs_fd);
+
+    if (f == NULL) {
+        return -ENOENT;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->telldir) != NULL) {
+            ret = (node->ops.i_fops->telldir)(f, dir);
+        }
+    }
+    return ret;
+}
+
+void aos_seekdir(aos_dir_t *dir, long loc)
+{
+    file_t  *f;
+    inode_t *node;
+
+    if (dir == NULL) {
+        return;
+    }
+
+    f = get_file(dir->dd_vfs_fd);
+
+    if (f == NULL) {
+        return;
+    }
+
+    node = f->node;
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->seekdir) != NULL) {
+            (node->ops.i_fops->seekdir)(f, dir, loc);
+        }
+    }
+}
+
+int aos_statfs(const char *path, struct statfs *buf)
+{
+    file_t  *file;
+    inode_t *node;
+    int err = -ENOSYS;
+    int ret = -ENOSYS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((err = xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) != 0) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        return err;
+    }
+
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->statfs) != NULL) {
+            ret = (node->ops.i_fops->statfs)(file, path, buf);
+        }
+    }
+
+    // if ((err = xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) != 0) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        return err;
+    }
+
+    del_file(file);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    return ret;
+}
+
+int aos_access(const char *path, int amode)
+{
+    file_t  *file;
+    inode_t *node;
+    int err = -ENOSYS;
+    int ret = -ENOSYS;
+
+    if (path == NULL) {
+        return -EINVAL;
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) != 0) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        return err;
+    }
+
+    node = inode_open(path);
+
+    if (node == NULL) {
+        // xSemaphoreGive(g_vfs_mutex);
+        aos_mutex_unlock(&g_vfs_mutex);
+        return -ENODEV;
+    }
+
+    file = new_file(node);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+
+    if (file == NULL) {
+        return -ENOENT;
+    }
+
+    if (INODE_IS_FS(node)) {
+        if ((node->ops.i_fops->access) != NULL) {
+            ret = (node->ops.i_fops->access)(file, path, amode);
+        }
+    }
+
+    // if ((pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) != 0) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        return err;
+    }
+
+    del_file(file);
+
+    // xSemaphoreGive(g_vfs_mutex);
+    aos_mutex_unlock(&g_vfs_mutex);
+    return ret;
+}
+

+ 157 - 0
fs/vfs/src/vfs_file.c

@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+// #include <FreeRTOS.h>
+#include <aos/kernel.h>
+
+#include <vfs_conf.h>
+#include <vfs_err.h>
+#include <vfs_inode.h>
+#include <stdio.h>
+#include <string.h>
+#include <utils_rbtree.h>
+#include <vfs_file.h>
+
+typedef struct files_handle {
+    struct rb_tree *file_rb_tree;
+    uint32_t fd_bitmap[FILE_BITMAP_NUM];
+} files_handle_t;
+
+static files_handle_t *files_handle_dev = NULL;
+
+static int file_cmp_cb(struct rb_tree *self, struct rb_node *node_a, struct rb_node *node_b)
+{
+    file_t *a = (file_t *) node_a->value;
+    file_t *b = (file_t *) node_b->value;
+    return (a->fd > b->fd) - (a->fd < b->fd);
+}
+
+int file_init(void)
+{
+    int ret = 0;
+    if (NULL == files_handle_dev) {
+        files_handle_dev = aos_malloc(sizeof(files_handle_t));
+        if (NULL == files_handle_dev) {
+            ret = -1;
+            goto exit;
+        }
+        memset(files_handle_dev, 0, sizeof(files_handle_t));
+        files_handle_dev->file_rb_tree = rb_tree_create(file_cmp_cb);
+        if (NULL == files_handle_dev->file_rb_tree) {
+            aos_free(files_handle_dev);
+            files_handle_dev = NULL;
+            ret = -1;
+            goto exit;
+        }
+    }
+exit:
+    return ret;
+}
+
+file_t *new_file(inode_t *node)
+{
+    file_t *f = NULL;
+    int fd = -1, i;
+
+    if (NULL == files_handle_dev || MAX_FILE_NUM <= rb_tree_size(files_handle_dev->file_rb_tree)) {
+        goto exit;
+    }
+
+    for (i = 0; i < MAX_FILE_NUM; i++) {
+        if ((files_handle_dev->fd_bitmap[i / 32] & (1 << (i % 32))) == 0) {
+            files_handle_dev->fd_bitmap[i / 32] |= (1 << (i % 32));
+            fd = i;
+            break;
+        }
+    }
+
+    if (fd < 0) {
+        goto exit;
+    }
+
+    f = aos_malloc(sizeof(file_t));
+
+    VFS_ASSERT(f != NULL);
+
+    f->node = node;
+    f->f_arg = NULL;
+    f->offset = 0;
+    f->fd = fd + AOS_CONFIG_VFS_FD_OFFSET;
+
+    if (!(rb_tree_insert(files_handle_dev->file_rb_tree, f))) {
+        files_handle_dev->fd_bitmap[fd / 32] &= ~(1 << (fd % 32));
+        aos_free(f);
+        f = NULL;
+        goto exit;
+    }
+    inode_ref(node);
+exit:
+    return f;
+}
+
+void del_file(file_t *file)
+{
+    int fd;
+    inode_unref(file->node);
+    file->node = NULL;
+    fd = file->fd - AOS_CONFIG_VFS_FD_OFFSET;
+    files_handle_dev->fd_bitmap[fd / 32] &= ~(1 << (fd % 32));
+    rb_tree_remove(files_handle_dev->file_rb_tree, file);
+    aos_free(file);
+}
+
+int get_fd(file_t *file)
+{
+    return file->fd;
+}
+
+file_t *get_file(int fd)
+{
+    file_t f;
+    if (fd < 0) {
+        return NULL;
+    }
+    f.fd = fd;
+
+    return (file_t *)rb_tree_find(files_handle_dev->file_rb_tree, &f);
+}
+
+size_t get_all_file(file_t **file, int size)
+{
+    size_t file_num;
+    struct rb_iter *iter;
+    file_num = rb_tree_size(files_handle_dev->file_rb_tree);
+
+    if (0 == file_num) {
+        goto exit;
+    }
+
+    file_num = size > file_num ? file_num : size;
+    iter = rb_iter_create();
+
+    if (NULL == iter) {
+        file_num = 0;
+        goto exit;
+    }
+
+    file[0] = rb_iter_first(iter, files_handle_dev->file_rb_tree);
+    
+    if (NULL == file[0]) {
+        rb_iter_dealloc(iter);
+        file_num = 0;
+        goto exit;
+    }
+
+    for (int i = 1; i < file_num; i++) {
+        file[i] = rb_iter_next(iter);
+        if (NULL == file[i]) {
+            file_num = i;
+            break;
+        }
+    }
+
+    rb_iter_dealloc(iter);
+exit:
+    return file_num;
+}

+ 242 - 0
fs/vfs/src/vfs_inode.c

@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#include <string.h>
+#include <stdio.h>
+// #include <FreeRTOS.h>
+#include <aos/kernel.h>
+
+#include <vfs_conf.h>
+#include <vfs_err.h>
+#include <utils_rbtree.h>
+#include <vfs_inode.h>
+
+#define VFS_NULL_PARA_CHK(para)     do { if (!(para)) return -EINVAL; } while(0)
+struct rb_tree *inode_rb_tree = NULL;
+
+static int inode_cmp_cb (struct rb_tree *self, struct rb_node *node_a, struct rb_node *node_b)
+{
+    int ret = 0;
+    inode_t *a = (inode_t *) node_a->value;
+    inode_t *b = (inode_t *) node_b->value;
+    if (INODE_IS_TYPE(a, VFS_TYPE_FS_DEV) ^ INODE_IS_TYPE(b, VFS_TYPE_FS_DEV)) {
+        ret = strncmp(a->i_name, b->i_name, INODE_IS_TYPE(a, VFS_TYPE_FS_DEV) ? strlen(a->i_name) : strlen(b->i_name));
+        if (!ret && strlen(a->i_name) != strlen(b->i_name)) {
+            ret = INODE_IS_TYPE(a, VFS_TYPE_FS_DEV) ? strncmp(b->i_name + strlen(a->i_name), "/", 1) : strncmp(a->i_name + strlen(b->i_name), "/", 1);
+            goto exit; 
+        }
+        goto exit;
+    }
+    ret = strcmp(a->i_name, b->i_name);
+exit:
+    return ret;
+}
+
+int inode_init()
+{
+    int ret = 0;
+    if (NULL == inode_rb_tree) {
+        inode_rb_tree = rb_tree_create(inode_cmp_cb);
+        if (NULL == inode_rb_tree) {
+            ret = -1;
+        }
+    }
+    return ret;
+}
+
+int inode_alloc(inode_t **node)
+{
+    *node = aos_malloc(sizeof(inode_t));
+
+    VFS_ASSERT(NULL != *node);
+
+    memset(*node, 0, sizeof(inode_t));
+
+    return 0;
+}
+
+int inode_del(inode_t *node)
+{
+    if (node->refs > 0) {
+        return -EBUSY;
+    }
+
+    if (node->refs == 0) {
+        rb_tree_remove(inode_rb_tree, node);
+        if (node->i_name != NULL) {
+            aos_free(node->i_name);
+        }
+        aos_free(node);
+    }
+
+    return VFS_SUCCESS;
+}
+
+inode_t *inode_open(const char *path)
+{
+    inode_t node;
+    memset(&node, 0, sizeof(inode_t));
+    node.i_name = (char *)path;
+    return (inode_t *)rb_tree_find(inode_rb_tree, &node);
+}
+
+int inode_forearch_name(int (*cb)(void *arg, inode_t *node), void *arg)
+{
+    int i;
+    size_t node_num;
+    inode_t *node;
+    struct rb_iter *iter;
+    node_num = rb_tree_size(inode_rb_tree);
+    
+    if (0 == node_num) {
+        goto exit;
+    }
+
+    iter = rb_iter_create();
+    
+    if (NULL == iter) {
+        node_num = 0;
+        goto exit;
+    }
+
+    node = rb_iter_first(iter, inode_rb_tree);
+    
+    if (NULL == node) {
+        rb_iter_dealloc(iter);
+        node_num = 0;
+        goto exit;
+    }
+
+    for (i = 0; i < node_num; i++) {
+        if (NULL != node->i_name) {
+            if (cb(arg, node)) {
+                break;
+            }
+        }
+        node = rb_iter_next(iter);
+        if (NULL == node) {
+            break;
+        }
+    }
+
+    rb_iter_dealloc(iter);
+exit:
+    return node_num;
+}
+
+int inode_ptr_get(int fd, inode_t **node)
+{
+    /*this API is useless if use rb_tree*/
+#if 0    
+    if (fd < 0 || fd >= AOS_CONFIG_VFS_DEV_NODES) {
+        return -EINVAL;
+    }
+
+    *node = &g_vfs_dev_nodes[fd];
+#endif
+    return VFS_SUCCESS;
+}
+
+void inode_ref(inode_t *node)
+{
+    node->refs++;
+}
+
+void inode_unref(inode_t *node)
+{
+    if (node->refs > 0) {
+        node->refs--;
+    }
+}
+
+int inode_busy(inode_t *node)
+{
+    return node->refs > 0;
+}
+
+int inode_avail_count(void)
+{
+    return AOS_CONFIG_VFS_DEV_NODES - rb_tree_size(inode_rb_tree);
+}
+
+static int inode_set_name(const char *path, inode_t **inode)
+{
+    size_t len;
+    void  *mem;
+
+    len = strlen(path);
+    mem = (void *)aos_malloc(len + 1);
+
+    VFS_ASSERT(NULL != mem);
+
+    memcpy(mem, (const void *)path, len);
+    (*inode)->i_name = (char *)mem;
+    (*inode)->i_name[len] = '\0';
+
+    return VFS_SUCCESS;
+}
+
+int inode_reserve(const char *path, inode_t **inode)
+{
+    int ret;
+    inode_t *node = NULL;
+
+    VFS_NULL_PARA_CHK(path != NULL && inode != NULL);
+    *inode = NULL;
+
+    /* Handle paths that are interpreted as the root directory */
+#ifdef _WIN32
+    if (path[0] == '\0' || path[1] != ':') {
+#else
+    if (path[0] == '\0' || path[0] != '/') {
+#endif
+        return -EINVAL;
+    }
+    
+    if (NULL == inode_rb_tree || AOS_CONFIG_VFS_DEV_NODES <= rb_tree_size(inode_rb_tree)) {
+        printf("inode_rb_tree is NULL when inode alloc\r\n");
+        return -EINVAL;
+    }
+
+    ret = inode_alloc(&node);
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = inode_set_name(path, &node);
+    if (ret < 0) {
+        aos_free(node);
+        return ret;
+    }
+
+    if (!(rb_tree_insert(inode_rb_tree, node))) {
+        aos_free(node->i_name);
+        aos_free(node);
+        return -ENOMEM;
+    }
+
+    *inode = node;
+    return VFS_SUCCESS;
+}
+
+int inode_release(const char *path)
+{
+    int ret;
+    inode_t *node;
+
+    VFS_NULL_PARA_CHK(path != NULL);
+
+    node = inode_open(path);
+    if (node == NULL) {
+        return -ENODEV;
+    }
+
+    ret = inode_del(node);
+    if (ret < 0) {
+        return ret;
+    }
+
+    return VFS_SUCCESS;
+}
+

+ 126 - 0
fs/vfs/src/vfs_register.c

@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#include <string.h>
+// #include <FreeRTOS.h>
+// #include <semphr.h>
+#include <aos/kernel.h>
+
+#include <vfs_conf.h>
+#include <vfs_err.h>
+#include <vfs_register.h>
+
+// extern SemaphoreHandle_t g_vfs_mutex;
+extern aos_mutex_t    g_vfs_mutex;
+
+int aos_register_driver(const char *path, file_ops_t *ops, void *arg)
+{
+    inode_t *node = NULL;
+    int err, ret;
+
+    // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    ret = inode_reserve(path, &node);
+    if (ret == VFS_SUCCESS) {
+        /* now populate it with char specific information */
+        INODE_SET_CHAR(node);
+
+        node->ops.i_ops = ops;
+        node->i_arg     = arg;
+    }
+
+    /* step out critical area for type is allocated */
+    // if (pdTRUE != xSemaphoreGive(g_vfs_mutex)) {
+    if (aos_mutex_unlock(&g_vfs_mutex)) {
+        err = -1;
+        if (node->i_name != NULL) {
+            aos_free(node->i_name);
+        }
+
+        memset(node, 0, sizeof(inode_t));
+        return err;
+    }
+
+    return ret;
+}
+
+int aos_unregister_driver(const char *path)
+{
+    int err, ret;
+
+    // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    ret = inode_release(path);
+
+    // if (pdTRUE != xSemaphoreGive(g_vfs_mutex)) {
+    if (aos_mutex_unlock(&g_vfs_mutex)) {
+        err = -1;
+        return err;
+    }
+
+    return ret;
+}
+
+int aos_register_fs(const char *path, fs_ops_t *ops, void *arg)
+{
+    inode_t *node = NULL;
+    int err, ret;
+
+    // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    ret = inode_reserve(path, &node);
+    if (ret == VFS_SUCCESS) {
+        INODE_SET_FS(node);
+
+        node->ops.i_fops = ops;
+        node->i_arg      = arg;
+    }
+
+    // if (pdTRUE != xSemaphoreGive(g_vfs_mutex)) {
+    if (aos_mutex_unlock(&g_vfs_mutex)) {
+        err = -1;
+        if (node->i_name != NULL) {
+            aos_free(node->i_name);
+        }
+
+        memset(node, 0, sizeof(inode_t));
+        return err;
+    }
+
+    return ret;
+}
+
+int aos_unregister_fs(const char *path)
+{
+    int err, ret;
+ 
+    // if (pdTRUE != xSemaphoreTake(g_vfs_mutex, portMAX_DELAY)) {
+    if(aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) {
+        err = -1;
+        return err;
+    }
+
+    ret = inode_release(path);
+
+    // if (pdTRUE != xSemaphoreGive(g_vfs_mutex)) {
+    if (aos_mutex_unlock(&g_vfs_mutex)) {
+        err = -1;
+        return err;
+    }
+
+    return ret;
+}
+

+ 579 - 0
network/wifi/include/bl60x_fw_api.h

@@ -0,0 +1,579 @@
+#ifndef __BL60x_FW_API_H__
+#define __BL60x_FW_API_H__
+
+//#include <bl_ro_params_mgt.h>
+#include <stdint.h>
+#include "bl_os_private.h"
+
+/// Tasks types.
+typedef enum wifi_fw_task_id
+{
+    TASK_NONE = (uint8_t) -1,
+
+    /// MAC Management task.
+    TASK_MM = 0,
+    /// SCAN task
+    TASK_SCAN,
+    /// SCAN task
+    TASK_SCANU,
+    /// SCAN task
+    TASK_ME,
+    /// SM task
+    TASK_SM,
+    /// APM task
+    TASK_APM,
+    /// BAM task
+    TASK_BAM,
+    /// RXU task
+    TASK_RXU,
+
+    TASK_CFG,
+
+    // This is used to define the last task that is running on the EMB processor
+    TASK_LAST_EMB = TASK_CFG,
+
+    // nX API task
+    TASK_API,
+    TASK_MAX,
+} ke_task_id_t;
+
+/// For MAC HW States.
+typedef enum hw_state_tag
+{
+    /// MAC HW IDLE State.
+    HW_IDLE = 0,
+    /// MAC HW RESERVED State.
+    HW_RESERVED,
+    /// MAC HW DOZE State.
+    HW_DOZE,
+    /// MAC HW ACTIVE State.
+    HW_ACTIVE
+} hw_state_tag_t;
+
+/// Possible States of the MM STA Task.
+typedef enum mm_state_tag
+{
+    /// MAC IDLE State.
+    MM_IDLE,
+    /// MAC ACTIVE State.
+    MM_ACTIVE,
+    /// MAC is going to IDLE
+    MM_GOING_TO_IDLE,
+    /// IDLE state internally controlled
+    MM_HOST_BYPASSED,
+    /// MAC Max Number of states.
+    MM_STATE_MAX
+} mm_state_tag_t;
+
+/**
+ ****************************************************************************************
+ * @brief Builds the first message ID of a task
+ * @param[in] task Task identifier
+ * @return The identifier of the first message of the task
+ ****************************************************************************************
+ */
+#define KE_FIRST_MSG(task) (((task) << 10))
+
+/// Message Identifier. The number of messages is limited to 0xFFFF.
+/// The message ID is divided in two parts:
+/// bits[15~8]: task index (no more than 255 tasks support)
+/// bits[7~0]: message index(no more than 255 messages per task)
+typedef enum wifi_fw_event_id
+{
+    /// RESET Request.
+    MM_RESET_REQ = KE_FIRST_MSG(TASK_MM),
+    /// RESET Confirmation.
+    MM_RESET_CFM,
+    /// START Request.
+    MM_START_REQ,
+    /// START Confirmation.
+    MM_START_CFM,
+    /// Read Version Request.
+    MM_VERSION_REQ,
+    /// Read Version Confirmation.
+    MM_VERSION_CFM,
+    /// ADD INTERFACE Request.
+    MM_ADD_IF_REQ,
+    /// ADD INTERFACE Confirmation.
+    MM_ADD_IF_CFM,
+    /// REMOVE INTERFACE Request.
+    MM_REMOVE_IF_REQ,
+    /// REMOVE INTERFACE Confirmation.
+    MM_REMOVE_IF_CFM,
+    /// STA ADD Request.
+    MM_STA_ADD_REQ,
+    /// STA ADD Confirm.
+    MM_STA_ADD_CFM,
+    /// STA DEL Request.
+    MM_STA_DEL_REQ,
+    /// STA DEL Confirm.
+    MM_STA_DEL_CFM,
+    /// CHANNEL CONFIGURATION Request.
+    MM_SET_CHANNEL_REQ,
+    /// CHANNEL CONFIGURATION Confirmation.
+    MM_SET_CHANNEL_CFM,
+    /// BEACON INTERVAL CONFIGURATION Request.
+    MM_SET_BEACON_INT_REQ,
+    /// BEACON INTERVAL CONFIGURATION Confirmation.
+    MM_SET_BEACON_INT_CFM,
+    /// BASIC RATES CONFIGURATION Request.
+    MM_SET_BASIC_RATES_REQ,
+    /// BASIC RATES CONFIGURATION Confirmation.
+    MM_SET_BASIC_RATES_CFM,
+    /// BSSID CONFIGURATION Request.
+    MM_SET_BSSID_REQ,
+    /// BSSID CONFIGURATION Confirmation.
+    MM_SET_BSSID_CFM,
+    /// EDCA PARAMETERS CONFIGURATION Request.
+    MM_SET_EDCA_REQ,
+    /// EDCA PARAMETERS CONFIGURATION Confirmation.
+    MM_SET_EDCA_CFM,
+    /// Request setting the VIF active state (i.e associated or AP started)
+    MM_SET_VIF_STATE_REQ,
+    /// Confirmation of the @ref MM_SET_VIF_STATE_REQ message.
+    MM_SET_VIF_STATE_CFM,
+    /// IDLE mode change Request.
+    MM_SET_IDLE_REQ,
+    /// IDLE mode change Confirm.
+    MM_SET_IDLE_CFM,
+    /// Indication of the primary TBTT to the upper MAC. Upon the reception of this
+    /// message the upper MAC has to push the beacon(s) to the beacon transmission queue.
+    MM_PRIMARY_TBTT_IND,
+    /// Indication of the secondary TBTT to the upper MAC. Upon the reception of this
+    /// message the upper MAC has to push the beacon(s) to the beacon transmission queue.
+    MM_SECONDARY_TBTT_IND,
+    /// Request to the LMAC to trigger the embedded logic analyzer and forward the debug
+    /// dump.
+    MM_DENOISE_REQ,
+    /// Set Power Save mode
+    MM_SET_PS_MODE_REQ,
+    /// Set Power Save mode confirmation
+    MM_SET_PS_MODE_CFM,
+    /// Request to add a channel context
+    MM_CHAN_CTXT_ADD_REQ,
+    /// Confirmation of the channel context addition
+    MM_CHAN_CTXT_ADD_CFM,
+    /// Request to delete a channel context
+    MM_CHAN_CTXT_DEL_REQ,
+    /// Confirmation of the channel context deletion
+    MM_CHAN_CTXT_DEL_CFM,
+    /// Request to link a channel context to a VIF
+    MM_CHAN_CTXT_LINK_REQ,
+    /// Confirmation of the channel context link
+    MM_CHAN_CTXT_LINK_CFM,
+    /// Request to unlink a channel context from a VIF
+    MM_CHAN_CTXT_UNLINK_REQ,
+    /// Confirmation of the channel context unlink
+    MM_CHAN_CTXT_UNLINK_CFM,
+    /// Request to update a channel context
+    MM_CHAN_CTXT_UPDATE_REQ,
+    /// Confirmation of the channel context update
+    MM_CHAN_CTXT_UPDATE_CFM,
+    /// Request to schedule a channel context
+    MM_CHAN_CTXT_SCHED_REQ,
+    /// Confirmation of the channel context scheduling
+    MM_CHAN_CTXT_SCHED_CFM,
+    /// Request to change the beacon template in LMAC
+    MM_BCN_CHANGE_REQ,
+    /// Confirmation of the beacon change
+    MM_BCN_CHANGE_CFM,
+    /// Request to update the TIM in the beacon (i.e to indicate traffic bufferized at AP)
+    MM_TIM_UPDATE_REQ,
+    /// Confirmation of the TIM update
+    MM_TIM_UPDATE_CFM,
+    /// Connection loss indication
+    MM_CONNECTION_LOSS_IND,
+    /// Channel context switch indication to the upper layers
+    MM_CHANNEL_SWITCH_IND,
+    /// Channel context pre-switch indication to the upper layers
+    MM_CHANNEL_PRE_SWITCH_IND,
+    /// Request to remain on channel or cancel remain on channel
+    MM_REMAIN_ON_CHANNEL_REQ,
+    /// Confirmation of the (cancel) remain on channel request
+    MM_REMAIN_ON_CHANNEL_CFM,
+    /// Remain on channel expired indication
+    MM_REMAIN_ON_CHANNEL_EXP_IND,
+    /// Indication of a PS state change of a peer device
+    MM_PS_CHANGE_IND,
+    /// Indication that some buffered traffic should be sent to the peer device
+    MM_TRAFFIC_REQ_IND,
+    /// Request to modify the STA Power-save mode options
+    MM_SET_PS_OPTIONS_REQ,
+    /// Confirmation of the PS options setting
+    MM_SET_PS_OPTIONS_CFM,
+    /// Indication of PS state change for a P2P VIF
+    MM_P2P_VIF_PS_CHANGE_IND,
+    /// Message containing channel information
+    MM_CHANNEL_SURVEY_IND,
+    /// Message containing Beamformer information
+    MM_BFMER_ENABLE_REQ,
+    /// Request to Start/Stop NOA - GO Only
+    MM_SET_P2P_NOA_REQ,
+    /// Request to Start/Stop Opportunistic PS - GO Only
+    MM_SET_P2P_OPPPS_REQ,
+    /// Start/Stop NOA Confirmation
+    MM_SET_P2P_NOA_CFM,
+    /// Start/Stop Opportunistic PS Confirmation
+    MM_SET_P2P_OPPPS_CFM,
+    /// P2P NoA Update Indication - GO Only
+    MM_P2P_NOA_UPD_IND,
+    /// Indication that RSSI is below or above the threshold
+    MM_RSSI_STATUS_IND,
+    /// Request to update the group information of a station
+    MM_MU_GROUP_UPDATE_REQ,
+    /// Confirmation of the @ref MM_MU_GROUP_UPDATE_REQ message
+    MM_MU_GROUP_UPDATE_CFM,
+    //Enable monitor mode
+    MM_MONITOR_REQ,
+    MM_MONITOR_CFM,
+    //Channel set under monitor mode
+    MM_MONITOR_CHANNEL_REQ,
+    MM_MONITOR_CHANNEL_CFM,
+
+    /*
+     * Section of internal MM messages. No MM API messages should be defined below this point
+     */
+    /// Internal request to force the HW going to IDLE
+    MM_FORCE_IDLE_REQ,
+    /// Message indicating that the switch to the scan channel is done
+    MM_SCAN_CHANNEL_START_IND,
+    /// Message indicating that the scan can end early
+    MM_SCAN_CHANNEL_END_EARLY,
+    /// Message indicating that the scan on the channel is finished
+    MM_SCAN_CHANNEL_END_IND,
+
+    /// MAX number of messages
+    MM_MAX,
+
+    /// Request to start the AP.
+    CFG_START_REQ = KE_FIRST_MSG(TASK_CFG),
+    CFG_START_CFM,
+    CFG_MAX,
+
+
+    /// Scanning start Request.
+    SCAN_START_REQ = KE_FIRST_MSG(TASK_SCAN),
+    /// Scanning start Confirmation.
+    SCAN_START_CFM,
+    /// End of scanning indication.
+    SCAN_DONE_IND,
+    /// Cancel scan request
+    SCAN_CANCEL_REQ,
+    /// Cancel scan confirmation
+    SCAN_CANCEL_CFM,
+
+    /// Abort scan request
+    SCAN_ABORT_REQ,
+    SCAN_ABORT_CFM,
+
+    /*
+     * Section of internal SCAN messages. No SCAN API messages should be defined below this point
+     */
+    SCAN_TIMER,
+
+    /// MAX number of messages
+    SCAN_MAX,
+
+    /// Request to start the AP.
+    APM_START_REQ = KE_FIRST_MSG(TASK_APM),
+    /// Confirmation of the AP start.
+    APM_START_CFM,
+    /// Request to stop the AP.
+    APM_STOP_REQ,
+    /// Confirmation of the AP stop.
+    APM_STOP_CFM,
+    /// Nofity host that a station has joined the network
+    APM_STA_ADD_IND,
+    /// Nofity host that a station has left the network
+    APM_STA_DEL_IND,
+    /// Check sta connect timeout
+    APM_STA_CONNECT_TIMEOUT_IND,
+    /// Request to delete STA
+    APM_STA_DEL_REQ,
+    /// Confirmation of delete STA
+    APM_STA_DEL_CFM,
+    /// CONF MAX STA Request
+    APM_CONF_MAX_STA_REQ,
+    /// CONF MAX STA Confirm
+    APM_CONF_MAX_STA_CFM,
+    /// MAX number of messages
+    APM_MAX,
+
+    /// BAM addition response timeout
+    BAM_ADD_BA_RSP_TIMEOUT_IND  = KE_FIRST_MSG(TASK_BAM),
+    /// BAM Inactivity timeout
+    BAM_INACTIVITY_TIMEOUT_IND,
+
+    /// Configuration request from host.
+    ME_CONFIG_REQ = KE_FIRST_MSG(TASK_ME),
+    /// Configuration confirmation.
+    ME_CONFIG_CFM,
+    /// Configuration request from host.
+    ME_CHAN_CONFIG_REQ,
+    /// Configuration confirmation.
+    ME_CHAN_CONFIG_CFM,
+    /// TKIP MIC failure indication.
+    ME_TKIP_MIC_FAILURE_IND,
+    /// Add a station to the FW (AP mode)
+    ME_STA_ADD_REQ,
+    /// Confirmation of the STA addition
+    ME_STA_ADD_CFM,
+    /// Delete a station from the FW (AP mode)
+    ME_STA_DEL_REQ,
+    /// Confirmation of the STA deletion
+    ME_STA_DEL_CFM,
+    /// Indication of a TX RA/TID queue credit update
+    ME_TX_CREDITS_UPDATE_IND,
+    /// Request indicating to the FW that there is traffic buffered on host
+    ME_TRAFFIC_IND_REQ,
+    /// Confirmation that the @ref ME_TRAFFIC_IND_REQ has been executed
+    ME_TRAFFIC_IND_CFM,
+    /// Request RC fixed rate
+    ME_RC_SET_RATE_REQ,
+
+    /*
+     * Section of internal ME messages. No ME API messages should be defined below this point
+     */
+    /// Internal request to indicate that a VIF needs to get the HW going to ACTIVE or IDLE
+    ME_SET_ACTIVE_REQ,
+    /// Confirmation that the switch to ACTIVE or IDLE has been executed
+    ME_SET_ACTIVE_CFM,
+    /// Internal request to indicate that a VIF desires to de-activate/activate the Power-Save mode
+    ME_SET_PS_DISABLE_REQ,
+    /// Confirmation that the PS state de-activate/activate has been executed
+    ME_SET_PS_DISABLE_CFM,
+    /// MAX number of messages
+    ME_MAX,
+
+    /// Management frame reception indication
+    RXU_MGT_IND = KE_FIRST_MSG(TASK_RXU),
+    /// NULL frame reception indication
+    RXU_NULL_DATA,
+
+    /// Scan request from host.
+    SCANU_START_REQ = KE_FIRST_MSG(TASK_SCANU),
+    /// Scanning start Confirmation.
+    SCANU_START_CFM,
+    /// Join request
+    SCANU_JOIN_REQ,
+    /// Join confirmation.
+    SCANU_JOIN_CFM,
+    /// Scan result indication.
+    SCANU_RESULT_IND,
+    /// Scan RAW Data Send from host
+    SCANU_RAW_SEND_REQ,
+    /// Scan result indication.
+    SCANU_RAW_SEND_CFM,
+
+    /// MAX number of messages
+    SCANU_MAX,
+
+    /// Request to connect to an AP
+    SM_CONNECT_REQ = KE_FIRST_MSG(TASK_SM),
+    /// Confirmation of connection
+    SM_CONNECT_CFM,
+    /// Indicates that the SM associated to the AP
+    SM_CONNECT_IND,
+    /// Request to disconnect
+    SM_DISCONNECT_REQ,
+    /// Confirmation of disconnection
+    SM_DISCONNECT_CFM,
+    /// Indicates that the SM disassociated the AP
+    SM_DISCONNECT_IND,
+    /// Timeout message for procedures requiring a response from peer
+    SM_RSP_TIMEOUT_IND,
+    /// Request to cancel connect when connecting
+    SM_CONNECT_ABORT_REQ,
+    /// Confirmation of connect abort
+    SM_CONNECT_ABORT_CFM,
+    /// Timeout message for requiring a SA Query Response from AP
+    SM_SA_QUERY_TIMEOUT_IND,
+    /// MAX number of messages
+    SM_MAX,
+} ke_msg_id_t;
+
+/*--------------------------------------------------------------------*/
+/* Status Codes - these codes are used in bouffalolab fw actions      */
+/* when an error action is taking place the status code can indicate  */
+/* what the status code.                                              */
+/* It is defined by bouffaloalb                                       */
+/*--------------------------------------------------------------------*/
+#define WLAN_FW_SUCCESSFUL                                        0 
+#define WLAN_FW_TX_AUTH_FRAME_ALLOCATE_FAIILURE                   1 
+#define WLAN_FW_AUTHENTICATION_FAIILURE                           2
+#define WLAN_FW_AUTH_ALGO_FAIILURE                                3
+#define WLAN_FW_TX_ASSOC_FRAME_ALLOCATE_FAIILURE                  4 
+#define WLAN_FW_ASSOCIATE_FAIILURE                                5
+#define WLAN_FW_DEAUTH_BY_AP_WHEN_NOT_CONNECTION                  6
+#define WLAN_FW_DEAUTH_BY_AP_WHEN_CONNECTION                      7
+#define WLAN_FW_4WAY_HANDSHAKE_ERROR_PSK_TIMEOUT_FAILURE          8
+#define WLAN_FW_4WAY_HANDSHAKE_TX_DEAUTH_FRAME_TRANSMIT_FAILURE   9
+#define WLAN_FW_4WAY_HANDSHAKE_TX_DEAUTH_FRAME_ALLOCATE_FAIILURE 10
+#define WLAN_FW_AUTH_OR_ASSOC_RESPONSE_TIMEOUT_FAILURE           11
+#define WLAN_FW_SCAN_NO_BSSID_AND_CHANNEL                        12
+#define WLAN_FW_CREATE_CHANNEL_CTX_FAILURE_WHEN_JOIN_NETWORK     13
+#define WLAN_FW_JOIN_NETWORK_FAILURE                             14
+#define WLAN_FW_ADD_STA_FAILURE                                  15
+#define WLAN_FW_BEACON_LOSS                                      16
+#define WLAN_FW_JOIN_NETWORK_SECURITY_NOMATCH                    17
+#define WLAN_FW_JOIN_NETWORK_WEPLEN_ERROR                        18
+#define WLAN_FW_DISCONNECT_BY_USER_WITH_DEAUTH                   19
+#define WLAN_FW_DISCONNECT_BY_USER_NO_DEAUTH                     20
+#define WLAN_FW_DISCONNECT_BY_FW_PS_TX_NULLFRAME_FAILURE         21
+#define WLAN_FW_TRAFFIC_LOSS                                     22
+#define WLAN_FW_CONNECT_ABORT_BY_USER_WITH_DEAUTH                23
+#define WLAN_FW_CONNECT_ABORT_BY_USER_NO_DEAUTH                  24
+#define WLAN_FW_CONNECT_ABORT_WHEN_JOINING_NETWORK               25
+#define WLAN_FW_CONNECT_ABORT_WHEN_SCANNING                      26 
+
+
+/*--------------------------------------------------------------------*/
+/* AP Mode Status Codes - these codes are used in bouffalolab fw actions      */
+/* when an error action is taking place the status code can indicate  */
+/* what the status code.                                              */
+/* It is defined by bouffaloalb                                       */
+/*--------------------------------------------------------------------*/
+#define WLAN_FW_APM_SUCCESSFUL                                        0 
+#define WLAN_FW_APM_DELETESTA_BY_USER                                 1
+#define WLAN_FW_APM_DEATUH_BY_STA                                     2
+#define WLAN_FW_APM_DISASSOCIATE_BY_STA                               3
+#define WLAN_FW_APM_DELETECONNECTION_TIMEOUT                          4
+#define WLAN_FW_APM_DELETESTA_FOR_NEW_CONNECTION                      5
+#define WLAN_FW_APM_DEAUTH_BY_AUTHENTICATOR                           6
+
+void bl60x_fw_xtal_capcode_set(uint8_t cap_in, uint8_t cap_out, uint8_t enable, uint8_t cap_in_max, uint8_t cap_out_max);
+void bl60x_fw_xtal_capcode_update(uint8_t cap_in, uint8_t cap_out);
+void bl60x_fw_xtal_capcode_restore(void);
+void bl60x_fw_xtal_capcode_autofit(void);
+void bl60x_fw_xtal_capcode_get(uint8_t *cap_in, uint8_t *cap_out);
+//void bl60x_fw_rf_tx_power_table_set(bl_tx_pwr_tbl_t* pwr_table);
+int bl60x_fw_password_hash(char *password, char *ssid, int ssidlength, char *output);
+void bl60x_fw_rf_table_set(uint32_t* channel_div_table_in, uint16_t* channel_cnt_table_in,
+                                                uint16_t lo_fcal_div);
+
+void bl60x_fw_dump_data(void);
+void bl60x_fw_dump_statistic(int forced);
+
+int bl60x_check_mac_status(int *is_ok);
+
+enum {
+    /// Background
+    API_AC_BK = 0,
+    /// Best-effort
+    API_AC_BE,
+    /// Video
+    API_AC_VI,
+    /// Voice
+    API_AC_VO,
+    /// Number of access categories
+    API_AC_MAX
+};
+
+int bl60x_edca_get(int ac, uint8_t *aifs, uint8_t *cwmin, uint8_t *cwmax, uint16_t *txop);
+
+/*Wi-Fi Firmware Entry*/
+void wifi_main(void *param);
+
+void bl_tpc_update_power_table(int8_t power_table_config[38]);
+void bl_tpc_update_power_table_rate(int8_t power_table[24]);
+void bl_tpc_update_power_table_channel_offset(int8_t power_table[14]);
+void bl_tpc_update_power_rate_11b(int8_t power_rate_table[4]);
+void bl_tpc_update_power_rate_11g(int8_t power_rate_table[8]);
+void bl_tpc_update_power_rate_11n(int8_t power_rate_table[8]);
+void bl_tpc_power_table_get(int8_t power_table_config[38]);
+
+void phy_cli_register(void);
+
+
+
+enum task_mm_cfg {
+    TASK_MM_CFG_KEEP_ALIVE_STATUS_ENABLED,
+    TASK_MM_CFG_KEEP_ALIVE_TIME_LAST_RECEIVED,
+    TASK_MM_CFG_KEEP_ALIVE_PACKET_COUNTER,
+};
+
+enum task_sm_cfg {
+    TASK_SM_CFG_AUTH_ASSOC_RETRY_LIMIT,
+};
+
+enum task_scan_cfg {
+    TASK_SCAN_CFG_DURATION_SCAN_PASSIVE,
+    TASK_SCAN_CFG_DURATION_SCAN_ACTIVE,
+    TASK_SCAN_CFG_DURATION_SCAN_JOIN_ACTIVE,
+};
+
+typedef enum{
+    /**version part**/
+    SM_CONNECTION_DATA_TLV_ID_VERSION,
+    /**Status part**/
+    SM_CONNECTION_DATA_TLV_ID_STATUS_CODE,
+    SM_CONNECTION_DATA_TLV_ID_DHCPSTATUS,
+    /**frame part**/
+    SM_CONNECTION_DATA_TLV_ID_AUTH_1,
+    SM_CONNECTION_DATA_TLV_ID_AUTH_2,
+    SM_CONNECTION_DATA_TLV_ID_AUTH_3,
+    SM_CONNECTION_DATA_TLV_ID_AUTH_4,
+    SM_CONNECTION_DATA_TLV_ID_ASSOC_REQ,
+    SM_CONNECTION_DATA_TLV_ID_ASSOC_RSP,
+    SM_CONNECTION_DATA_TLV_ID_4WAY_1,
+    SM_CONNECTION_DATA_TLV_ID_4WAY_2,
+    SM_CONNECTION_DATA_TLV_ID_4WAY_3,
+    SM_CONNECTION_DATA_TLV_ID_4WAY_4,
+    SM_CONNECTION_DATA_TLV_ID_2WAY_1,
+    SM_CONNECTION_DATA_TLV_ID_2WAY_2,
+    SM_CONNECTION_DATA_TLV_ID_DEAUTH,
+    /**striped frame part**/
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_AUTH_1,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_AUTH_2,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_AUTH_3,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_AUTH_4,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_AUTH_UNVALID,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_ASSOC_REQ,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_ASSOC_RSP,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_DEAUTH_FROM_REMOTE,
+    SM_CONNECTION_DATA_TLV_ID_STRIPED_DEASSOC_FROM_REMOTE,
+    SM_CONNECTION_DATA_TLV_ID_RESERVED,
+} sm_connection_data_tlv_id_t;
+
+/* structure of a list element header */
+struct sm_tlv_list_hdr
+{
+    struct sm_tlv_list_hdr *next;
+};
+
+/* structure of a list */
+struct sm_tlv_list
+{
+    struct sm_tlv_list_hdr *first;
+    struct sm_tlv_list_hdr *last;
+};
+
+/*
+ * TLV ID数据以链表的形式存储在struct sm_connect_tlv_desc中,
+ * callback需要遍历这个链表来获取所有的数据
+ */
+struct sm_connect_tlv_desc {
+    struct sm_tlv_list_hdr list_hdr;
+    sm_connection_data_tlv_id_t id;
+    uint16_t len;
+    uint8_t data[0];
+};
+
+#ifdef TD_DIAGNOSIS_STA
+typedef struct wifi_diagnosis_info
+{
+    uint32_t beacon_recv;
+    uint32_t beacon_loss;
+    uint32_t beacon_total;
+    uint64_t unicast_recv;
+    uint64_t unicast_send;
+    uint64_t multicast_recv;
+    uint64_t multicast_send;
+}wifi_diagnosis_info_t;
+
+wifi_diagnosis_info_t *bl_diagnosis_get(void);
+int wifi_td_diagnosis_init(void);
+int wifi_td_diagnosis_deinit(void);
+#endif
+
+#endif /*__BL60x_FW_API_H__*/

+ 70 - 0
network/wifi/include/bl_phy_api.h

@@ -0,0 +1,70 @@
+#ifndef __BL_PHY_API_H__
+#define __BL_PHY_API_H__
+
+void bl_mfg_phy_init();
+void bl_mfg_rf_cal();
+void bl_mfg_rx_start();
+void bl_mfg_rx_stop();
+void bl_mfg_channel_switch(uint8_t chan_no);
+int8_t bl_mfg_tx11n_start_raw(uint8_t mcs_n, uint16_t frame_len, uint8_t pwr_dbm);
+int8_t bl_mfg_tx11b_start_raw(uint8_t mcs_b, uint16_t frame_len, uint8_t pwr_dbm);
+void bl_mfg_tx_stop();
+void phy_powroffset_set(int8_t power_offset[14]);
+
+#define RFTLV_TYPE_XTAL_MODE           0X0001
+#define RFTLV_TYPE_XTAL                0X0002
+#define RFTLV_TYPE_PWR_MODE            0X0003
+#define RFTLV_TYPE_PWR_TABLE           0X0004
+#define RFTLV_TYPE_PWR_TABLE_11B       0X0005
+#define RFTLV_TYPE_PWR_TABLE_11G       0X0006
+#define RFTLV_TYPE_PWR_TABLE_11N       0X0007
+#define RFTLV_TYPE_PWR_OFFSET          0X0008
+#define RFTLV_TYPE_CHAN_DIV_TAB        0X0009
+#define RFTLV_TYPE_CHAN_CNT_TAB        0X000A
+#define RFTLV_TYPE_LO_FCAL_DIV         0X000B
+#define RFTLV_TYPE_EN_TCAL             0X0020
+#define RFTLV_TYPE_LINEAR_OR_FOLLOW    0X0021
+#define RFTLV_TYPE_TCHANNELS           0X0022
+#define RFTLV_TYPE_TCHANNEL_OS         0X0023
+#define RFTLV_TYPE_TCHANNEL_OS_LOW     0X0024
+#define RFTLV_TYPE_TROOM_OS            0X0025
+#define RFTLV_TYPE_PWR_TABLE_BLE       0X0030
+
+#define RFTLV_API_TYPE_XTAL_MODE           RFTLV_TYPE_XTAL_MODE       
+#define RFTLV_API_TYPE_XTAL                RFTLV_TYPE_XTAL            
+#define RFTLV_API_TYPE_PWR_MODE            RFTLV_TYPE_PWR_MODE        
+#define RFTLV_API_TYPE_PWR_TABLE           RFTLV_TYPE_PWR_TABLE       
+#define RFTLV_API_TYPE_PWR_TABLE_11B       RFTLV_TYPE_PWR_TABLE_11B   
+#define RFTLV_API_TYPE_PWR_TABLE_11G       RFTLV_TYPE_PWR_TABLE_11G   
+#define RFTLV_API_TYPE_PWR_TABLE_11N       RFTLV_TYPE_PWR_TABLE_11N   
+#define RFTLV_API_TYPE_PWR_OFFSET          RFTLV_TYPE_PWR_OFFSET      
+#define RFTLV_API_TYPE_CHAN_DIV_TAB        RFTLV_TYPE_CHAN_DIV_TAB    
+#define RFTLV_API_TYPE_CHAN_CNT_TAB        RFTLV_TYPE_CHAN_CNT_TAB    
+#define RFTLV_API_TYPE_LO_FCAL_DIV         RFTLV_TYPE_LO_FCAL_DIV     
+#define RFTLV_API_TYPE_EN_TCAL             RFTLV_TYPE_EN_TCAL         
+#define RFTLV_API_TYPE_LINEAR_OR_FOLLOW    RFTLV_TYPE_LINEAR_OR_FOLLOW
+#define RFTLV_API_TYPE_TCHANNELS           RFTLV_TYPE_TCHANNELS       
+#define RFTLV_API_TYPE_TCHANNEL_OS         RFTLV_TYPE_TCHANNEL_OS     
+#define RFTLV_API_TYPE_TCHANNEL_OS_LOW     RFTLV_TYPE_TCHANNEL_OS_LOW 
+#define RFTLV_API_TYPE_TROOM_OS            RFTLV_TYPE_TROOM_OS        
+#define RFTLV_API_TYPE_PWR_TABLE_BLE       RFTLV_TYPE_PWR_TABLE_BLE   
+
+/*
+ * input:
+ *       tlv_addr: rftlv info address
+ *
+ * return : 1-valid, other-invalid
+ */
+int rftlv_valid(uint32_t tlv_addr);
+
+/*
+ * input:
+ *        tlv_addr: rftlv info address
+ *        type: type
+ *        value_len: value max len
+ *        value: point value
+ * return : ">0"-success, "<0"-invalid and end, "==0"-invalid and can next
+ */
+int rftlv_get(uint32_t tlv_addr, uint16_t type, uint32_t value_len, void *value);
+
+#endif

+ 0 - 0
network/wifi/include/rd.h


+ 257 - 0
network/wifi/include/supplicant_api.h

@@ -0,0 +1,257 @@
+#ifndef SUPPLICANT_API_H
+#define SUPPLICANT_API_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#define BL_SAE_INVALID_PACKET -8
+
+// XXX: this struct should be compatible with internal(FULLMAC)
+typedef struct bl_wifi_timer {
+    void *_storage_0[3];
+    uint32_t exp_time;
+} bl_wifi_timer_t;
+
+/** Configuration structure for Protected Management Frame */
+typedef struct {
+    bool capable;            /**< Advertizes support for Protected Management Frame. Device will prefer to connect in PMF mode if other device also advertizes PMF capability. */
+    bool required;           /**< Advertizes that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */
+} wifi_pmf_config_t;
+
+typedef enum {
+    WIFI_CIPHER_TYPE_NONE = 0,   /**< the cipher type is none */
+    WIFI_CIPHER_TYPE_WEP40,      /**< the cipher type is WEP40 */
+    WIFI_CIPHER_TYPE_WEP104,     /**< the cipher type is WEP104 */
+    WIFI_CIPHER_TYPE_TKIP,       /**< the cipher type is TKIP */
+    WIFI_CIPHER_TYPE_CCMP,       /**< the cipher type is CCMP */
+    WIFI_CIPHER_TYPE_TKIP_CCMP,  /**< the cipher type is TKIP and CCMP */
+    WIFI_CIPHER_TYPE_AES_CMAC128,/**< the cipher type is AES-CMAC-128 */
+    WIFI_CIPHER_TYPE_SMS4,       /**< the cipher type is SMS4 */
+    WIFI_CIPHER_TYPE_UNKNOWN,    /**< the cipher type is unknown */
+} wifi_cipher_type_t;
+
+typedef enum {
+    WIFI_APPIE_WPA_RSN = 0, // WPA and/or RSN
+    WIFI_APPIE_WPS_PR,
+    WIFI_APPIE_WPS_AR,
+    WIFI_APPIE_CUSTOM,
+    WIFI_APPIE_MAX,
+} wifi_appie_t;
+
+typedef enum wpa_alg {
+    WIFI_WPA_ALG_NONE   = 0,
+    WIFI_WPA_ALG_WEP40  = 1,
+    WIFI_WPA_ALG_TKIP   = 2,
+    WIFI_WPA_ALG_CCMP   = 3,
+    WIFI_WAPI_ALG_SMS4  = 4,
+    WIFI_WPA_ALG_WEP104 = 5,
+    WIFI_WPA_ALG_WEP    = 6,
+    WIFI_WPA_ALG_IGTK   = 7,
+    WIFI_WPA_ALG_PMK    = 8,
+    WIFI_WPA_ALG_GCMP   = 9,
+} wpa_alg_t;
+
+typedef struct {
+    int proto;
+    int pairwise_cipher;
+    int group_cipher;
+    int key_mgmt;
+    int capabilities;
+    size_t num_pmkid;
+    const uint8_t *pmkid;
+    int mgmt_group_cipher;
+} wifi_wpa_ie_t;
+
+#ifndef BIT
+#define BIT(x) (1U << (x))
+#endif
+
+#define WPA_PROTO_WPA BIT(0)
+#define WPA_PROTO_RSN BIT(1)
+
+#define WPA_KEY_MGMT_IEEE8021X BIT(0)
+#define WPA_KEY_MGMT_PSK BIT(1)
+#define WPA_KEY_MGMT_NONE BIT(2)
+#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
+#define WPA_KEY_MGMT_WPA_NONE BIT(4)
+#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
+#define WPA_KEY_MGMT_FT_PSK BIT(6)
+#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
+#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
+#define WPA_KEY_MGMT_WPS BIT(9)
+#define WPA_KEY_MGMT_SAE BIT(10)
+#define WPA_KEY_MGMT_FT_SAE BIT(11)
+#define WPA_KEY_MGMT_WAPI_PSK BIT(12)
+#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
+#define WPA_KEY_MGMT_CCKM BIT(14)
+#define WPA_KEY_MGMT_OSEN BIT(15)
+#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
+#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17)
+
+typedef enum {
+    NONE_AUTH            = 0x01,
+    WPA_AUTH_UNSPEC      = 0x02,
+    WPA_AUTH_PSK         = 0x03,
+    WPA2_AUTH_ENT        = 0x04,
+    WPA2_AUTH_PSK        = 0x05,
+    WPA_AUTH_CCKM        = 0x06,
+    WPA2_AUTH_CCKM       = 0x07,
+    WPA2_AUTH_PSK_SHA256 = 0x08,
+    WPA3_AUTH_PSK        = 0x09,
+    WPA2_AUTH_ENT_SHA256 = 0x0a,
+    WAPI_AUTH_PSK        = 0x0b,
+    WAPI_AUTH_CERT       = 0x0c,
+    WPA2_AUTH_INVALID    = 0x0d,
+} wpa_auth_mode_t;
+
+typedef enum {
+    WIFI_AUTH_OPEN = 0,         /**< authenticate mode : open */
+    WIFI_AUTH_WEP,              /**< authenticate mode : WEP */
+    WIFI_AUTH_WPA_PSK,          /**< authenticate mode : WPA_PSK */
+    WIFI_AUTH_WPA2_PSK,         /**< authenticate mode : WPA2_PSK */
+    WIFI_AUTH_WPA_WPA2_PSK,     /**< authenticate mode : WPA_WPA2_PSK */
+    WIFI_AUTH_WPA2_ENTERPRISE,  /**< authenticate mode : WPA2_ENTERPRISE */
+    WIFI_AUTH_WPA3_PSK,         /**< authenticate mode : WPA3_PSK */
+    WIFI_AUTH_WPA2_WPA3_PSK,    /**< authenticate mode : WPA2_WPA3_PSK */
+    WIFI_AUTH_WAPI_PSK,         /**< authenticate mode : WAPI_PSK */
+    WIFI_AUTH_MAX
+} wifi_auth_mode_t;
+
+struct wifi_ssid {
+    int len;
+    uint8_t ssid[32];
+};
+
+
+#define WPA_AES_KEY_LEN    16
+#define WPA_TKIP_KEY_LEN   32
+#define WPA_WEP104_KEY_LEN 13
+#define WPA_WEP40_KEY_LEN  5
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+// XXX order matters!
+typedef enum {
+    SEC_PROTO_NONE,
+    SEC_PROTO_WEP_STATIC,
+    SEC_PROTO_WPA,
+    SEC_PROTO_WPA2,
+    SEC_PROTO_WPA3,
+    SEC_PROTO_WAPI,
+} sec_proto_t;
+
+typedef enum {
+    EAPOL_FRAME_4_1,
+    EAPOL_FRAME_4_2,
+    EAPOL_FRAME_4_3,
+    EAPOL_FRAME_4_4,
+    EAPOL_FRAME_2_1,
+    EAPOL_FRAME_2_2,
+} eapol_frame_id_t;
+
+typedef struct {
+    uint8_t vif_idx;
+    uint8_t sta_idx;
+    uint8_t mac[ETH_ALEN];
+    uint8_t bssid[ETH_ALEN];
+    struct wifi_ssid ssid;
+    sec_proto_t proto;
+    uint16_t key_mgmt;
+    uint8_t pairwise_cipher;
+    uint8_t group_cipher;
+    char passphrase[64 + 1];
+    bool pmf_required;
+    uint8_t mgmt_group_cipher; // should always be WPA_CIPHER_AES_128_CMAC if PMFR=1
+} wifi_connect_parm_t;
+
+typedef struct {
+    uint8_t vif_idx;
+    uint8_t mac[ETH_ALEN];
+    struct wifi_ssid ssid;
+    wifi_auth_mode_t auth_mode;
+    wifi_cipher_type_t pairwise_cipher;
+    char passphrase[64 + 1];
+} wifi_ap_parm_t;
+
+struct wpa_funcs {
+    bool (*wpa_sta_init)(void);
+    bool (*wpa_sta_deinit)(void);
+    void (*wpa_sta_config)(wifi_connect_parm_t *bssid);
+    void (*wpa_sta_connect)(wifi_connect_parm_t *bssid);
+    void (*wpa_sta_disconnected_cb)(uint8_t reason_code);
+    int (*wpa_sta_rx_eapol)(uint8_t *src_addr, uint8_t *buf, uint32_t len);
+    void *(*wpa_ap_init)(wifi_ap_parm_t *parm);
+    bool (*wpa_ap_deinit)(void *data);
+    bool (*wpa_ap_join)(void **sm, uint8_t *mac, uint8_t *wpa_ie, uint8_t wpa_ie_len);
+    void (*wpa_ap_sta_associated)(void *wpa_sm, uint8_t sta_idx);
+    bool (*wpa_ap_remove)(void *sm);
+    bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, uint8_t *data, size_t data_len);
+    int (*wpa_parse_wpa_ie)(const uint8_t *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data);
+    void (*wpa_reg_diag_tlv_cb)(void *tlv_pack_cb);
+    // XXX MIC failure countermeasure disabled for now
+    /* int (*wpa_michael_mic_failure)(uint16_t is_unicast); */
+    uint8_t *(*wpa3_build_sae_msg)(uint8_t *bssid, uint8_t *mac, uint8_t *passphrase, uint32_t sae_msg_type, size_t *sae_msg_len);
+    int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type, uint16_t status);
+    void (*wpa3_clear_sae)(void);
+};
+
+struct wps_scan_ie {
+    uint8_t    *bssid;
+    uint8_t    chan;
+    uint16_t   capinfo;
+    uint8_t    *ssid;
+    uint8_t    ssid_len;
+    uint8_t    *wpa;
+    uint8_t    *rsn;
+    uint8_t    *wps;
+};
+
+struct wps_funcs {
+    bool (*wps_parse_scan_result)(struct wps_scan_ie *scan);
+    int (*wps_sm_rx_eapol)(uint8_t *src_addr, uint8_t *buf, uint32_t len);
+    int (*wps_config)(uint8_t vif_idx, uint8_t sta_idx);
+    int (*wps_start_pending)(void);
+};
+
+typedef enum wps_status {
+    WPS_STATUS_DISABLE = 0,
+    WPS_STATUS_SCANNING,
+    WPS_STATUS_PENDING,
+    WPS_STATUS_SUCCESS,
+    WPS_STATUS_MAX,
+} wps_status_t;
+
+typedef void bl_wifi_timer_func_t(void *arg);
+typedef void(*wifi_tx_cb_t)(void *);
+
+int bl_wifi_ap_deauth_internal(uint8_t vif_idx, uint8_t sta_idx, uint32_t reason);
+bool bl_wifi_auth_done_internal(uint8_t sta_idx, uint16_t reason_code);
+void *bl_wifi_get_hostap_private_internal(void);
+void bl_wifi_timer_arm(bl_wifi_timer_t *ptimer, uint32_t time_ms, bool repeat_flag);
+void bl_wifi_timer_disarm(bl_wifi_timer_t *ptimer);
+void bl_wifi_timer_done(bl_wifi_timer_t *ptimer);
+void bl_wifi_timer_setfn(bl_wifi_timer_t *ptimer, bl_wifi_timer_func_t *pfunction, void *parg);
+int bl_wifi_set_appie_internal(uint8_t vif_idx, wifi_appie_t type, uint8_t *ie, uint16_t len, bool sta);
+int bl_wifi_unset_appie_internal(uint8_t vif_idx, wifi_appie_t type);
+bool bl_wifi_wpa_ptk_init_done_internal(uint8_t sta_idx);
+int bl_wifi_register_wpa_cb_internal(const struct wpa_funcs *cb);
+int bl_wifi_unregister_wpa_cb_internal(void);
+bool bl_wifi_skip_supp_pmkcaching(void);
+int bl_wifi_sta_update_ap_info_internal(void);
+uint8_t bl_wifi_sta_set_reset_param_internal(uint8_t reset_flag);
+bool bl_wifi_sta_is_ap_notify_completed_rsne_internal(void);
+bool bl_wifi_sta_is_running_internal(void);
+int bl_wifi_set_ap_key_internal(uint8_t vif_idx, uint8_t sta_idx, wpa_alg_t alg, int key_idx, uint8_t *key, size_t key_len, bool pairwise);
+int bl_wifi_set_sta_key_internal(uint8_t vif_idx, uint8_t sta_idx, wpa_alg_t alg, int key_idx, int set_tx, uint8_t *seq, size_t seq_len, uint8_t *key, size_t key_len, bool pairwise);
+
+int bl_wifi_set_igtk_internal(uint8_t vif_idx, uint8_t sta_idx, uint16_t key_idx, const uint8_t *pn, const uint8_t *key);
+int bl_wifi_get_sta_gtk(uint8_t vif_idx, uint8_t *out_buf, uint8_t *out_len);
+int bl_wifi_get_assoc_bssid_internal(uint8_t vif_idx, uint8_t *bssid);
+int bl_wifi_set_wps_cb_internal(const struct wps_funcs *wps_cb);
+wps_status_t bl_wifi_get_wps_status_internal(void);
+void bl_wifi_set_wps_status_internal(wps_status_t status);
+
+#endif /* end of include guard: SUPPLICANT_API_H */

二進制
network/wifi/lib/libwifi.a


+ 10 - 0
network/wifi/modules/bugkiller/inc/bugkiller_fw.h

@@ -0,0 +1,10 @@
+#ifndef __BUGKILLER_FW_H__
+#define __BUGKILLER_FW_H__
+
+#include <stdint.h>
+
+void bugkiller_fw_queue_init(void);
+
+void bugkiller_fw_task_init(void);
+
+#endif

+ 37 - 0
network/wifi_bt_coex/include/wifi_bt_coex.h

@@ -0,0 +1,37 @@
+#ifndef __WIFI_BT_COEX_BT_H__
+#define __WIFI_BT_COEX_BT_H__
+
+#include <stdint.h>
+#include <bl_os_hal.h>
+
+enum WIFI_BT_COEX_FORCE_MODE {
+    WIFI_BT_COEX_FORCE_MODE_PTA_FORCE,
+    WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE,
+    WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE,
+    WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2,
+};
+
+enum WIFI_BT_COEX_EVENT {
+    WIFI_BT_COEX_EVENT_BT_A2DP_UNDERRUN,
+};
+
+struct wifi_bt_coex_ctx {
+    BL_Timer_t coexTimer;
+    uint32_t timer_now;
+    uint32_t timer_max;
+    uint32_t timer_toggle_start;
+    uint32_t timer_toggle_end;
+    uint32_t timeus_last_called;
+    uint32_t time_step_inc;
+    uint32_t time_step_dec;
+};
+
+int wifi_bt_coex_cli_init(void);
+int wifi_bt_coex_dump_all(void);
+int wifi_bt_coex_force_wlan(void);
+int wifi_bt_coex_force_bt(void);
+int wifi_bt_coex_force_mode(enum WIFI_BT_COEX_FORCE_MODE mode);
+
+/*Following is the event section*/
+int wifi_bt_coex_event_notify(enum WIFI_BT_COEX_EVENT event, void *event_arg);
+#endif

+ 45 - 0
network/wifi_bt_coex/src/wifi_bt_coex.c

@@ -0,0 +1,45 @@
+#include <wifi_bt_coex.h>
+#include "wifi_bt_coex_impl.h"
+
+int wifi_bt_coex_dump_all(void)
+{
+    wifi_bt_coex_dump_all_impl();
+
+    return 0;
+}
+
+int wifi_bt_coex_force_wlan(void)
+{
+    return wifi_bt_coex_force_wlan_impl();
+}
+
+int wifi_bt_coex_force_bt(void)
+{
+    return wifi_bt_coex_force_bt_impl();
+}
+
+int wifi_bt_coex_force_mode(enum WIFI_BT_COEX_FORCE_MODE mode)
+{
+    switch (mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE:
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            return wifi_bt_coex_force_mode_impl(mode);
+        }
+        break;
+        default:
+        {
+            /*Empty Here*/
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int wifi_bt_coex_event_notify(enum WIFI_BT_COEX_EVENT event, void *event_arg)
+{
+    return wifi_bt_coex_event_handler_impl(event, event_arg);
+}

+ 78 - 0
network/wifi_bt_coex/src/wifi_bt_coex_cli.c

@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <wifi_bt_coex.h>
+#include <cli.h>
+
+static void cmd_coex_dump_all(char *buf, int len, int argc, char **argv)
+{
+    wifi_bt_coex_dump_all();
+}
+
+static void cmd_coex_wlan(char *buf, int len, int argc, char **argv)
+{
+    wifi_bt_coex_force_wlan();
+}
+
+static void cmd_coex_bt(char *buf, int len, int argc, char **argv)
+{
+    wifi_bt_coex_force_bt();
+}
+
+static void cmd_coex_mode(char *buf, int len, int argc, char **argv)
+{
+    int mode;
+    if (2 != argc) {
+        return;
+    }
+    mode = atoi(argv[1]);
+
+    switch (mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE:
+        {
+            printf("Use COEX Mode: WIFI_BT_COEX_FORCE_MODE_PTA_FORCE\r\n");
+            wifi_bt_coex_force_mode(mode);
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            printf("Use COEX Mode: WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE\r\n");
+            wifi_bt_coex_force_mode(mode);
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            printf("Use COEX Mode: WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE\r\n");
+            wifi_bt_coex_force_mode(mode);
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            printf("Use COEX Mode: WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2\r\n");
+            wifi_bt_coex_force_mode(mode);
+        }
+        break;
+        default:
+        {
+            /*Empty Here*/
+            printf("unknown coex mode %d\r\n", mode);
+        }
+    }
+}
+
+
+// STATIC_CLI_CMD_ATTRIBUTE makes this(these) command(s) static
+const static struct cli_command cmds_user[] STATIC_CLI_CMD_ATTRIBUTE = {
+        { "coex_dump_all", "COEX Dump All Status", cmd_coex_dump_all},
+        { "coex_wlan", "coex force wlan", cmd_coex_wlan},
+        { "coex_bt", "coex force bt", cmd_coex_bt},
+        { "coex_mode", "coex mode", cmd_coex_mode},
+};                                                                                   
+
+int wifi_bt_coex_cli_init(void)
+{
+    // static command(s) do NOT need to call aos_cli_register_command(s) to register.
+    // However, calling aos_cli_register_command(s) here is OK but is of no effect as cmds_user are included in cmds list.
+    // XXX NOTE: Calling this *empty* function is necessary to make cmds_user in this file to be kept in the final link.
+    //return aos_cli_register_commands(cmds_user, sizeof(cmds_user)/sizeof(cmds_user[0]));          
+    return 0;
+}

+ 24 - 0
network/wifi_bt_coex/src/wifi_bt_coex_ctx.c

@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <wifi_bt_coex.h>
+
+#define COEX_CTX_DEBUG(fmt, args...) printf(fmt, ##args)
+
+int wifi_bt_coex_bt_inc(struct wifi_bt_coex_ctx *ctx, int step)
+{
+    int target;
+
+    target = ctx->timer_toggle_end + step;
+    if (target <= 0 || ctx->timer_toggle_end > ctx->timer_max) {
+        return -1;
+    }
+    ctx->timer_toggle_end = target;
+
+    COEX_CTX_DEBUG("[COEX] [CTX] using timer_toggle_end %lu\r\n", ctx->timer_toggle_end); 
+
+    return 0;
+}
+
+int wifi_bt_coex_bt_dec(struct wifi_bt_coex_ctx *ctx, int step)
+{
+    return 0;
+}

+ 7 - 0
network/wifi_bt_coex/src/wifi_bt_coex_ctx.h

@@ -0,0 +1,7 @@
+#ifndef __WIFI_BT_COEX_CTX_H__
+#define __WIFI_BT_COEX_CTX_H__
+#include <wifi_bt_coex.h>
+
+int wifi_bt_coex_bt_inc(struct wifi_bt_coex_ctx *ctx, int step);
+int wifi_bt_coex_bt_dec(struct wifi_bt_coex_ctx *ctx, int step);
+#endif

+ 12 - 0
network/wifi_bt_coex/src/wifi_bt_coex_impl.h

@@ -0,0 +1,12 @@
+#ifndef __WIFI_BT_COEX_BT_IMPL_H__
+#define __WIFI_BT_COEX_BT_IMPL_H__
+#include <wifi_bt_coex.h>
+
+int wifi_bt_coex_dump_all_impl(void);
+int wifi_bt_coex_force_wlan_impl(void);
+int wifi_bt_coex_force_bt_impl(void);
+int wifi_bt_coex_force_mode_impl(enum WIFI_BT_COEX_FORCE_MODE mode);
+
+int wifi_bt_coex_event_handler_impl(enum WIFI_BT_COEX_EVENT event, void *event_arg);
+
+#endif

+ 166 - 0
network/wifi_bt_coex/src/wifi_bt_coex_impl_bl602.c

@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <wifi_bt_coex.h>
+
+#include "wifi_bt_coex_impl.h"
+#include "wifi_bt_coex_ctx.h"
+
+#define PTA_REG_BASE_ADDR               (0x44920000)
+#define PTA_REG_REVISION                (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x00))
+#define PTA_REG_CONFIG                  (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x04))
+#define PTA_REG_BT_TX                   (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x08))
+#define PTA_REG_BT_TX_ABORT             (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x0C))
+#define PTA_REG_BT_RX                   (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x10))
+#define PTA_REG_BT_RX_ABORT             (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x14))
+#define PTA_REG_WLAN_TX                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x18))
+#define PTA_REG_WLAN_TX_ABORT           (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x1C))
+#define PTA_REG_WLAN_RX                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x20))
+#define PTA_REG_WLAN_RX_ABORT           (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x24))
+
+#define WLAN_COEX_REG_BASE_ADDR         (0x44B00400)
+#define WLAN_COEX_REG_CoexControlReg    (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x00))
+#define WLAN_COEX_REG_CoexPTIReg        (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x04))
+#define WLAN_COEX_REG_CoexStatReg       (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x08))
+#define WLAN_COEX_REG_CoexIntReg        (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x0C))
+
+static enum WIFI_BT_COEX_FORCE_MODE wifi_bt_coex_bl602_mode = WIFI_BT_COEX_FORCE_MODE_PTA_FORCE;
+
+extern struct wifi_bt_coex_ctx coex_timing_control_ctx;
+
+int wifi_bt_coex_dump_all_impl(void)
+{
+    uint32_t val;
+
+    printf("============BL602 PTA Reg Dump============\r\n");
+    printf("REVISIOIN       %08lx\r\n", PTA_REG_REVISION);
+    printf("CONFIG          %08lx\r\n", PTA_REG_CONFIG);
+    printf("BT TX           %08lx\r\n", PTA_REG_BT_TX);
+    printf("BT TX Abort     %08lx\r\n", PTA_REG_BT_TX_ABORT);
+    printf("BT RX           %08lx\r\n", PTA_REG_BT_RX);
+    printf("BT RX Abort     %08lx\r\n", PTA_REG_BT_RX_ABORT);
+    printf("WLAN TX         %08lx\r\n", PTA_REG_WLAN_TX);
+    printf("WLAN TX Abort   %08lx\r\n", PTA_REG_WLAN_TX_ABORT);
+    printf("WLAN RX         %08lx\r\n", PTA_REG_WLAN_RX);
+    printf("WLAN RX Abort   %08lx\r\n", PTA_REG_WLAN_RX_ABORT);
+    printf("============BL602 Coex (Wi-Fi) Reg Dump============\r\n");
+    printf("CoexControlReg  %08lx\r\n", WLAN_COEX_REG_CoexControlReg);
+
+    val = WLAN_COEX_REG_CoexPTIReg;
+    printf("CoexPTIReg      %08lx\r\n", val);
+    printf("    ACK     %lu\r\n", (val >>  0) & 0xF);
+    printf("    Cntrl   %lu\r\n", (val >>  4) & 0xF);
+    printf("    Mgt     %lu\r\n", (val >>  8) & 0xF);
+    printf("    VO      %lu\r\n", (val >> 12) & 0xF);
+    printf("    VI      %lu\r\n", (val >> 16) & 0xF);
+    printf("    BE      %lu\r\n", (val >> 20) & 0xF);
+    printf("    BK      %lu\r\n", (val >> 24) & 0xF);
+    printf("    BCN     %lu\r\n", (val >> 28) & 0xF);
+
+    printf("CoexStatReg     %08lx\r\n", WLAN_COEX_REG_CoexStatReg);
+    printf("CoexIntReg      %08lx\r\n", WLAN_COEX_REG_CoexIntReg);
+
+    return 0;
+}
+
+int wifi_bt_coex_force_wlan_impl(void)
+{
+    //puts("BL602 COEX WLAN force impl called\r\n");
+    //Force to RF1/BT/WLAN
+    switch (wifi_bt_coex_bl602_mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE: 
+        {
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 16) | (1 << 17)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            //                              PTA En       WLAN      Default Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (0 << 4)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0xF48;
+            WLAN_COEX_REG_CoexPTIReg = 0xFFFFFFFF;
+            WLAN_COEX_REG_CoexControlReg = 0xF49;
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            WLAN_COEX_REG_CoexControlReg = 0xF0000F58;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0xF0000F59;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}
+
+int wifi_bt_coex_force_bt_impl(void)
+{
+    //puts("BL602 COEX BT force impl called\r\n");
+    //Force to RF1/BT/WLAN
+    switch (wifi_bt_coex_bl602_mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE: 
+        {
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 18) | (1 << 19)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            //                              PTA En       WLAN      Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (0 << 1) | (0 << 4)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0x48;
+            WLAN_COEX_REG_CoexPTIReg = 0x00;
+            WLAN_COEX_REG_CoexControlReg = 0x49;
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            WLAN_COEX_REG_CoexControlReg = 0x048;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0x049;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}
+
+int wifi_bt_coex_force_mode_impl(enum WIFI_BT_COEX_FORCE_MODE mode)
+{
+    wifi_bt_coex_bl602_mode = mode;
+    return 0;
+}
+
+int wifi_bt_coex_event_handler_impl(enum WIFI_BT_COEX_EVENT event, void *event_arg)
+{
+    switch (event) {
+        case WIFI_BT_COEX_EVENT_BT_A2DP_UNDERRUN:
+        {
+            wifi_bt_coex_bt_inc(&coex_timing_control_ctx, 1);
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}

+ 184 - 0
network/wifi_bt_coex/src/wifi_bt_coex_impl_bl606p.c

@@ -0,0 +1,184 @@
+#include <stdio.h>
+#include <wifi_bt_coex.h>
+
+#include "wifi_bt_coex_impl.h"
+#include "wifi_bt_coex_ctx.h"
+
+#define PTA_REG_BASE_ADDR               (0x24920400)
+#define PTA_REG_REVISION                (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x00))
+#define PTA_REG_CONFIG                  (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x04))
+#define PTA_REG_BT_TX                   (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x08))
+#define PTA_REG_BT_TX_ABORT             (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x0C))
+#define PTA_REG_BT_RX                   (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x10))
+#define PTA_REG_BT_RX_ABORT             (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x14))
+#define PTA_REG_WLAN_TX                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x18))
+#define PTA_REG_WLAN_TX_ABORT           (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x1C))
+#define PTA_REG_WLAN_RX                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x20))
+#define PTA_REG_WLAN_RX_ABORT           (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x24))
+#define PTA_REG_CONFIG2                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x28))
+
+#define WLAN_COEX_REG_BASE_ADDR         (0x24B00400)
+#define WLAN_COEX_REG_CoexControlReg    (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x00))
+#define WLAN_COEX_REG_CoexPTIReg        (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x04))
+#define WLAN_COEX_REG_CoexStatReg       (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x08))
+#define WLAN_COEX_REG_CoexIntReg        (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x0C))
+#define WLAN_COEX_REG_CoexControl2Reg   (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x10))
+
+static enum WIFI_BT_COEX_FORCE_MODE wifi_bt_coex_bl606p_mode = WIFI_BT_COEX_FORCE_MODE_PTA_FORCE;
+
+extern struct wifi_bt_coex_ctx coex_timing_control_ctx;
+
+int wifi_bt_coex_dump_all_impl(void)
+{
+    uint32_t val;
+
+    printf("============BL606P PTA Reg Dump============\r\n");
+    printf("REVISIOIN       %08lx\r\n", PTA_REG_REVISION);
+    printf("CONFIG          %08lx\r\n", PTA_REG_CONFIG);
+    printf("BT TX           %08lx\r\n", PTA_REG_BT_TX);
+    printf("BT TX Abort     %08lx\r\n", PTA_REG_BT_TX_ABORT);
+    printf("BT RX           %08lx\r\n", PTA_REG_BT_RX);
+    printf("BT RX Abort     %08lx\r\n", PTA_REG_BT_RX_ABORT);
+    printf("WLAN TX         %08lx\r\n", PTA_REG_WLAN_TX);
+    printf("WLAN TX Abort   %08lx\r\n", PTA_REG_WLAN_TX_ABORT);
+    printf("WLAN RX         %08lx\r\n", PTA_REG_WLAN_RX);
+    printf("WLAN RX Abort   %08lx\r\n", PTA_REG_WLAN_RX_ABORT);
+    printf("CONFIG2         %08lx\r\n", PTA_REG_CONFIG2);
+    printf("============BL606P Coex (Wi-Fi) Reg Dump============\r\n");
+    printf("CoexControlReg  %08lx\r\n", WLAN_COEX_REG_CoexControlReg);
+
+    val = WLAN_COEX_REG_CoexPTIReg;
+    printf("CoexPTIReg      %08lx\r\n", val);
+    printf("    ACK     %lu\r\n", (val >>  0) & 0xF);
+    printf("    Cntrl   %lu\r\n", (val >>  4) & 0xF);
+    printf("    Mgt     %lu\r\n", (val >>  8) & 0xF);
+    printf("    VO      %lu\r\n", (val >> 12) & 0xF);
+    printf("    VI      %lu\r\n", (val >> 16) & 0xF);
+    printf("    BE      %lu\r\n", (val >> 20) & 0xF);
+    printf("    BK      %lu\r\n", (val >> 24) & 0xF);
+    printf("    BCN     %lu\r\n", (val >> 28) & 0xF);
+
+    printf("CoexStatReg     %08lx\r\n", WLAN_COEX_REG_CoexStatReg);
+    printf("CoexIntReg      %08lx\r\n", WLAN_COEX_REG_CoexIntReg);
+    val = WLAN_COEX_REG_CoexControl2Reg;
+    printf("CoexControl2Reg %08lx\r\n", val);
+    printf("    Force BK    %lu\r\n", (val >> 0) & 0x1);
+    printf("    Force BE    %lu\r\n", (val >> 1) & 0x1);
+    printf("    Force VI    %lu\r\n", (val >> 2) & 0x1);
+    printf("    Force VO    %lu\r\n", (val >> 3) & 0x1);
+    printf("    Force BCN   %lu\r\n", (val >> 4) & 0x1);
+
+    return 0;
+}
+
+int wifi_bt_coex_force_wlan_impl(void)
+{
+    //puts("BL606P COEX WLAN force impl called\r\n");
+    //Force to RF1/BT/WLAN
+    switch (wifi_bt_coex_bl606p) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE: 
+        {
+            PTA_REG_CONFIG2 = 0;
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 16) | (1 << 17)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN      Default Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (0 << 4)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0xF48;
+            WLAN_COEX_REG_CoexPTIReg = 0xFFFFFFFF;
+            WLAN_COEX_REG_CoexControlReg = 0xF49;
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            PTA_REG_CONFIG2 = 0;
+            WLAN_COEX_REG_CoexControlReg = 0xF0000F58;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0xF0000F59;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}
+
+int wifi_bt_coex_force_bt_impl(void)
+{
+    //puts("BL606p COEX BT force impl called\r\n");
+    //Force to RF1/BT/WLAN
+    switch (wifi_bt_coex_bl606p_mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE: 
+        {
+            PTA_REG_CONFIG2 = 0;
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 18) | (1 << 19)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN      Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (0 << 1) | (0 << 4)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0x48;
+            WLAN_COEX_REG_CoexPTIReg = 0x00;
+            WLAN_COEX_REG_CoexControlReg = 0x49;
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            PTA_REG_CONFIG2 = 0;
+            WLAN_COEX_REG_CoexControlReg = 0x048;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0x049;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}
+
+int wifi_bt_coex_force_mode_impl(enum WIFI_BT_COEX_FORCE_MODE mode)
+{
+    wifi_bt_coex_bl606p_mode = mode;
+    return 0;
+}
+
+int wifi_bt_coex_event_handler_impl(enum WIFI_BT_COEX_EVENT event, void *event_arg)
+{
+    switch (event) {
+        case WIFI_BT_COEX_EVENT_BT_A2DP_UNDERRUN:
+        {
+            wifi_bt_coex_bt_inc(&coex_timing_control_ctx, 1);
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}

+ 184 - 0
network/wifi_bt_coex/src/wifi_bt_coex_impl_bl808.c

@@ -0,0 +1,184 @@
+#include <stdio.h>
+#include <wifi_bt_coex.h>
+
+#include "wifi_bt_coex_impl.h"
+#include "wifi_bt_coex_ctx.h"
+
+#define PTA_REG_BASE_ADDR               (0x24920400)
+#define PTA_REG_REVISION                (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x00))
+#define PTA_REG_CONFIG                  (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x04))
+#define PTA_REG_BT_TX                   (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x08))
+#define PTA_REG_BT_TX_ABORT             (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x0C))
+#define PTA_REG_BT_RX                   (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x10))
+#define PTA_REG_BT_RX_ABORT             (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x14))
+#define PTA_REG_WLAN_TX                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x18))
+#define PTA_REG_WLAN_TX_ABORT           (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x1C))
+#define PTA_REG_WLAN_RX                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x20))
+#define PTA_REG_WLAN_RX_ABORT           (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x24))
+#define PTA_REG_CONFIG2                 (*(volatile uint32_t *)(PTA_REG_BASE_ADDR + 0x28))
+
+#define WLAN_COEX_REG_BASE_ADDR         (0x24B00400)
+#define WLAN_COEX_REG_CoexControlReg    (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x00))
+#define WLAN_COEX_REG_CoexPTIReg        (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x04))
+#define WLAN_COEX_REG_CoexStatReg       (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x08))
+#define WLAN_COEX_REG_CoexIntReg        (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x0C))
+#define WLAN_COEX_REG_CoexControl2Reg   (*(volatile uint32_t *)(WLAN_COEX_REG_BASE_ADDR + 0x10))
+
+static enum WIFI_BT_COEX_FORCE_MODE wifi_bt_coex_bl808_mode = WIFI_BT_COEX_FORCE_MODE_PTA_FORCE;
+
+extern struct wifi_bt_coex_ctx coex_timing_control_ctx;
+
+int wifi_bt_coex_dump_all_impl(void)
+{
+    uint32_t val;
+
+    printf("============BL808 PTA Reg Dump============\r\n");
+    printf("REVISIOIN       %08lx\r\n", PTA_REG_REVISION);
+    printf("CONFIG          %08lx\r\n", PTA_REG_CONFIG);
+    printf("BT TX           %08lx\r\n", PTA_REG_BT_TX);
+    printf("BT TX Abort     %08lx\r\n", PTA_REG_BT_TX_ABORT);
+    printf("BT RX           %08lx\r\n", PTA_REG_BT_RX);
+    printf("BT RX Abort     %08lx\r\n", PTA_REG_BT_RX_ABORT);
+    printf("WLAN TX         %08lx\r\n", PTA_REG_WLAN_TX);
+    printf("WLAN TX Abort   %08lx\r\n", PTA_REG_WLAN_TX_ABORT);
+    printf("WLAN RX         %08lx\r\n", PTA_REG_WLAN_RX);
+    printf("WLAN RX Abort   %08lx\r\n", PTA_REG_WLAN_RX_ABORT);
+    printf("CONFIG2         %08lx\r\n", PTA_REG_CONFIG2);
+    printf("============BL808 Coex (Wi-Fi) Reg Dump============\r\n");
+    printf("CoexControlReg  %08lx\r\n", WLAN_COEX_REG_CoexControlReg);
+
+    val = WLAN_COEX_REG_CoexPTIReg;
+    printf("CoexPTIReg      %08lx\r\n", val);
+    printf("    ACK     %lu\r\n", (val >>  0) & 0xF);
+    printf("    Cntrl   %lu\r\n", (val >>  4) & 0xF);
+    printf("    Mgt     %lu\r\n", (val >>  8) & 0xF);
+    printf("    VO      %lu\r\n", (val >> 12) & 0xF);
+    printf("    VI      %lu\r\n", (val >> 16) & 0xF);
+    printf("    BE      %lu\r\n", (val >> 20) & 0xF);
+    printf("    BK      %lu\r\n", (val >> 24) & 0xF);
+    printf("    BCN     %lu\r\n", (val >> 28) & 0xF);
+
+    printf("CoexStatReg     %08lx\r\n", WLAN_COEX_REG_CoexStatReg);
+    printf("CoexIntReg      %08lx\r\n", WLAN_COEX_REG_CoexIntReg);
+    val = WLAN_COEX_REG_CoexControl2Reg;
+    printf("CoexControl2Reg %08lx\r\n", val);
+    printf("    Force BK    %lu\r\n", (val >> 0) & 0x1);
+    printf("    Force BE    %lu\r\n", (val >> 1) & 0x1);
+    printf("    Force VI    %lu\r\n", (val >> 2) & 0x1);
+    printf("    Force VO    %lu\r\n", (val >> 3) & 0x1);
+    printf("    Force BCN   %lu\r\n", (val >> 4) & 0x1);
+
+    return 0;
+}
+
+int wifi_bt_coex_force_wlan_impl(void)
+{
+    //puts("BL808 COEX WLAN force impl called\r\n");
+    //Force to RF1/BT/WLAN
+    switch (wifi_bt_coex_bl808_mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE: 
+        {
+            PTA_REG_CONFIG2 = 0;
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 16) | (1 << 17)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN      Default Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (0 << 4)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0xF48;
+            WLAN_COEX_REG_CoexPTIReg = 0xFFFFFFFF;
+            WLAN_COEX_REG_CoexControlReg = 0xF49;
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            PTA_REG_CONFIG2 = 0;
+            WLAN_COEX_REG_CoexControlReg = 0xF0000F58;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0xF0000F59;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}
+
+int wifi_bt_coex_force_bt_impl(void)
+{
+    //puts("BL808 COEX BT force impl called\r\n");
+    //Force to RF1/BT/WLAN
+    switch (wifi_bt_coex_bl808_mode) {
+        case WIFI_BT_COEX_FORCE_MODE_PTA_FORCE: 
+        {
+            PTA_REG_CONFIG2 = 0;
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 18) | (1 << 19)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_DEFAULT_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN      Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (0 << 1) | (0 << 4)));
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE:
+        {
+            PTA_REG_CONFIG2 = 0;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0x48;
+            WLAN_COEX_REG_CoexPTIReg = 0x00;
+            WLAN_COEX_REG_CoexControlReg = 0x49;
+        }
+        break;
+        case WIFI_BT_COEX_FORCE_MODE_PTI_PRIORITY_FORCE2:
+        {
+            PTA_REG_CONFIG2 = 0;
+            WLAN_COEX_REG_CoexControlReg = 0x048;
+            //                              PTA En       WLAN        Priority
+            PTA_REG_CONFIG = ((0x50000000 | (1 << 0) | (1 << 1) | (1 << 4)));
+            WLAN_COEX_REG_CoexControlReg = 0x049;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}
+
+int wifi_bt_coex_force_mode_impl(enum WIFI_BT_COEX_FORCE_MODE mode)
+{
+    wifi_bt_coex_bl808_mode = mode;
+    return 0;
+}
+
+int wifi_bt_coex_event_handler_impl(enum WIFI_BT_COEX_EVENT event, void *event_arg)
+{
+    switch (event) {
+        case WIFI_BT_COEX_EVENT_BT_A2DP_UNDERRUN:
+        {
+            wifi_bt_coex_bt_inc(&coex_timing_control_ctx, 1);
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+        }
+    }
+    return 0;
+}

+ 250 - 0
network/wifi_hosal/include/wifi_hosal.h

@@ -0,0 +1,250 @@
+/****************************************************************************
+ * components/network/wifi_hosal/include/wifi_hosal.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef _WIFI_HOSAL_H_
+#define _WIFI_HOSAL_H_
+
+#include <sys/_stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "stdint.h"
+#include "stddef.h"
+
+#include "hosal_adc.h"
+#include "bl_pm.h"
+
+/****************************************************************************
+ * Definition
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct wifi_hosal_funcs
+{
+  int (*efuse_read_mac)(uint8_t mac[6]);
+  int (*rf_turn_on)(void *arg);
+  int (*rf_turn_off)(void *arg);
+  hosal_adc_dev_t* (*adc_device_get)(void);
+  int (*adc_tsen_value_get)(hosal_adc_dev_t *adc);
+  int (*pm_init) (void);
+  int (*pm_event_register) (enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t pirority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable);
+  int (*pm_deinit) (void);
+  int (*pm_state_run) (void);
+  int (*pm_capacity_set) (enum PM_LEVEL level);
+  int (*pm_post_event) (enum PM_EVEMT event, uint32_t code, uint32_t *retval);
+  int (*pm_event_switch) (enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable);
+};
+
+typedef struct wifi_hosal_funcs wifi_hosal_funcs_t;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+extern wifi_hosal_funcs_t g_wifi_hosal_funcs;
+
+
+/****************************************************************************
+ * Private Function
+ ****************************************************************************/
+
+static inline int hosal_wifi_ret_zero(void *arg)
+{
+  return 0;
+}
+
+static inline int hosal_wifi_ret_non_zero(void *arg)
+{
+  return -1;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: wifi_hosal_efuse_read_mac
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_efuse_read_mac(uint8_t mac[6]);
+
+/****************************************************************************
+ * Name: wifi_hosal_pds_rf_turnon
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_rf_turn_on(void *arg);
+
+/****************************************************************************
+ * Name: wifi_hosal_pds_rf_turnoff
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_rf_turn_off(void *arg);
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_device_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+hosal_adc_dev_t* wifi_hosal_adc_device_get(void);
+
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_adc_tsen_value_get(hosal_adc_dev_t *adc);
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_pm_init(void);
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_event_register(enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t pirority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable);
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_deinit(void);
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_state_run(void);
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_capacity_set(enum PM_LEVEL level);
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_post_event(enum PM_EVEMT event, uint32_t code, uint32_t *retval);
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_event_switch(enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WIFI_HOSAL_H_ */

+ 70 - 0
network/wifi_hosal/port/wifi_hosal_bl602.c

@@ -0,0 +1,70 @@
+/****************************************************************************
+ * components/network/wifi_hosal/port/wifi_hosal_bl602.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "wifi_hosal.h"
+
+#include "bl_pds.h"
+#include "bl_efuse.h"
+
+#ifdef BL602_MATTER_SUPPORT
+#include <hosal_adc.c>
+#endif
+
+/****************************************************************************
+ * Definition
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+wifi_hosal_funcs_t g_wifi_hosal_funcs =
+{
+  .efuse_read_mac = bl_efuse_read_mac,
+  .rf_turn_on = bl_pds_rf_turnon,
+  .rf_turn_off = bl_pds_rf_turnoff,
+  .adc_device_get = hosal_adc_device_get,
+  .adc_tsen_value_get =
+  #ifdef CONF_ADC_ENABLE_TSEN
+    hosal_adc_tsen_value_get,
+  #else
+    hosal_wifi_ret_zero,
+  #endif
+  .pm_init = bl_pm_init,
+  .pm_event_register = bl_pm_event_register,
+  .pm_deinit = bl_pm_deinit,
+  .pm_state_run = bl_pm_state_run,
+  .pm_capacity_set = bl_pm_capacity_set,
+  .pm_post_event = pm_post_event,
+  .pm_event_switch = bl_pm_event_switch,
+};
+
+#ifdef __cplusplus
+}
+#endif
+

+ 63 - 0
network/wifi_hosal/port/wifi_hosal_bl606p.c

@@ -0,0 +1,63 @@
+
+/****************************************************************************
+ * components/network/wifi_hosal/port/wifi_hosal_bl808.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "wifi_hosal.h"
+
+/****************************************************************************
+ * Definition
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+wifi_hosal_funcs_t g_wifi_hosal_funcs =
+{
+  .efuse_read_mac = hosal_wifi_ret_zero,
+  .rf_turn_on = hosal_wifi_ret_zero,
+  .rf_turn_off = hosal_wifi_ret_zero,
+  .adc_device_get = hosal_wifi_ret_zero,
+  .adc_tsen_value_get = hosal_wifi_ret_zero,
+  .pm_init = bl_pm_init,
+  .pm_event_register = bl_pm_event_register,
+  .pm_deinit = bl_pm_deinit,
+  .pm_state_run = bl_pm_state_run,
+  .pm_capacity_set = bl_pm_capacity_set,
+  .pm_post_event = pm_post_event,
+  .pm_event_switch = bl_pm_event_switch,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+

+ 63 - 0
network/wifi_hosal/port/wifi_hosal_bl808.c

@@ -0,0 +1,63 @@
+
+/****************************************************************************
+ * components/network/wifi_hosal/port/wifi_hosal_bl808.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "wifi_hosal.h"
+
+/****************************************************************************
+ * Definition
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+wifi_hosal_funcs_t g_wifi_hosal_funcs =
+{
+  .efuse_read_mac = hosal_wifi_ret_zero,
+  .rf_turn_on = hosal_wifi_ret_zero,
+  .rf_turn_off = hosal_wifi_ret_zero,
+  .adc_device_get = hosal_wifi_ret_zero,
+  .adc_tsen_value_get = hosal_wifi_ret_zero,
+  .pm_init = bl_pm_init,
+  .pm_event_register = bl_pm_event_register,
+  .pm_deinit = bl_pm_deinit,
+  .pm_state_run = bl_pm_state_run,
+  .pm_capacity_set = bl_pm_capacity_set,
+  .pm_post_event = pm_post_event,
+  .pm_event_switch = bl_pm_event_switch,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+

+ 247 - 0
network/wifi_hosal/wifi_hosal.c

@@ -0,0 +1,247 @@
+/****************************************************************************
+ * components/network/wifi_hosal/wifi_hosal.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "wifi_hosal.h"
+
+/****************************************************************************
+ * Definition
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: wifi_hosal_efuse_read_mac
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_efuse_read_mac(uint8_t mac[6])
+{
+  return g_wifi_hosal_funcs.efuse_read_mac(mac);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_pds_rf_turnon
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_rf_turn_on(void *arg)
+{
+  return g_wifi_hosal_funcs.rf_turn_on(arg);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_pds_rf_turnoff
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_rf_turn_off(void *arg)
+{
+  return g_wifi_hosal_funcs.rf_turn_off(arg);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_device_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+hosal_adc_dev_t* wifi_hosal_adc_device_get(void)
+{
+  return g_wifi_hosal_funcs.adc_device_get();
+}
+
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+int wifi_hosal_adc_tsen_value_get(hosal_adc_dev_t *adc)
+{
+  return g_wifi_hosal_funcs.adc_tsen_value_get(adc);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_init(void)
+{
+  return g_wifi_hosal_funcs.pm_init();
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_event_register(enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t pirority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable)
+{
+  return g_wifi_hosal_funcs.pm_event_register(event, code, cap_bit, pirority, ops, arg, enable);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_deinit(void)
+{
+  return g_wifi_hosal_funcs.pm_deinit();
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_state_run(void)
+{
+  return g_wifi_hosal_funcs.pm_state_run();
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_capacity_set(enum PM_LEVEL level)
+{
+  return g_wifi_hosal_funcs.pm_capacity_set(level);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_post_event(enum PM_EVEMT event, uint32_t code, uint32_t *retval)
+{
+  return g_wifi_hosal_funcs.pm_post_event(event, code, retval);
+}
+
+/****************************************************************************
+ * Name: wifi_hosal_adc_tsen_value_get
+ *
+ * Description:
+ *   Disable irq num
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+int wifi_hosal_pm_event_switch(enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable)
+{
+  return g_wifi_hosal_funcs.pm_event_switch(event, code, enable);
+}
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+

+ 272 - 0
network/wifi_manager/bl60x_wifi_driver/bl_cmds.c

@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <bl_os_private.h>
+#include "bl_cmds.h"
+#include "bl_utils.h"
+#include "bl_strs.h"
+
+#undef bl_os_log_printf
+#define bl_os_log_printf(...) \
+    do {                      \
+    } while (0)
+
+static void cmd_dump(const struct bl_cmd *cmd)
+{
+    bl_os_log_debug("tkn[%d]  flags:%04x  result:%3d  cmd:%4d-%-24s - reqcfm(%4d-%-s)\n",
+           cmd->tkn, cmd->flags, cmd->result, cmd->id, RWNX_ID2STR(cmd->id),
+           cmd->reqid, cmd->reqid != (lmac_msg_id_t)-1 ? RWNX_ID2STR(cmd->reqid) : "none");
+}
+
+static void cmd_complete(struct bl_cmd_mgr *cmd_mgr, struct bl_cmd *cmd)
+{
+    bl_os_log_debug("[CMDS] CMD complete: %p\r\n", cmd);
+
+    cmd_mgr->queue_sz--;
+    list_del(&cmd->list);
+    cmd->flags |= RWNX_CMD_FLAG_DONE;
+    if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) {
+        bl_os_log_debug("[CMDS] NONBLOCK CMD, free now %p\r\n", cmd);
+        bl_os_free(cmd);
+    } else {
+        if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) {
+            bl_os_log_debug("[CMDS] BLOCK EVENT is ready, complete now %p\r\n", cmd);
+            cmd->result = 0;
+            bl_os_event_group_send(cmd->complete, 0x1);
+        }
+    }
+}
+
+static int cmd_mgr_queue(struct bl_cmd_mgr *cmd_mgr, struct bl_cmd *cmd)
+{
+    struct bl_hw *bl_hw = container_of(cmd_mgr, struct bl_hw, cmd_mgr);
+    struct bl_cmd *last;
+    bool defer_push = false;
+    uint32_t e;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    bl_os_mutex_lock(cmd_mgr->lock);
+
+    if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) {
+        bl_os_log_debug("cmd queue crashed\r\n");
+        cmd->result = EPIPE;
+        RWNX_DBG(RWNX_FN_LEAVE_STR);
+        bl_os_mutex_unlock(cmd_mgr->lock);
+        return -EPIPE;
+    }
+
+    if (!list_empty(&cmd_mgr->cmds)) {
+        if (cmd_mgr->queue_sz == cmd_mgr->max_queue_sz) {
+            bl_os_log_debug("Too many cmds (%d) already queued\r\n",
+                   cmd_mgr->max_queue_sz);
+            cmd->result = ENOMEM;
+            RWNX_DBG(RWNX_FN_LEAVE_STR);
+            bl_os_mutex_unlock(cmd_mgr->lock);
+            return -ENOMEM;
+        }
+        last = list_entry(cmd_mgr->cmds.prev, struct bl_cmd, list);
+        //FIXME comment out the following code block, since it is buggy
+#if 1
+        if (last->flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_PUSH)) {
+#if 0 // queue even NONBLOCK command.
+            if (cmd->flags & RWNX_CMD_FLAG_NONBLOCK) {
+                printk(KERN_CRIT"cmd queue busy\n");
+                cmd->result = -EBUSY;
+                spin_unlock_bh(&cmd_mgr->lock);
+                RWNX_DBG(RWNX_FN_LEAVE_STR);
+                return -EBUSY;
+            }
+#endif
+            cmd->flags |= RWNX_CMD_FLAG_WAIT_PUSH;
+            defer_push = true;
+        }
+#endif
+    }
+
+    cmd->flags |= RWNX_CMD_FLAG_WAIT_ACK;
+    if (cmd->flags & RWNX_CMD_FLAG_REQ_CFM)
+        cmd->flags |= RWNX_CMD_FLAG_WAIT_CFM;
+
+    cmd->tkn    = cmd_mgr->next_tkn++;
+    cmd->result = EINTR;
+
+    if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) {
+        cmd->complete = bl_os_event_group_create();
+    }
+
+
+    list_add_tail(&cmd->list, &cmd_mgr->cmds);
+    cmd_mgr->queue_sz++;
+    bl_os_mutex_unlock(cmd_mgr->lock);
+
+    if (!defer_push) {
+        bl_os_log_debug("pushing CMD, param_len is %d...\r\n", cmd->a2e_msg->param_len);
+        ipc_host_msg_push(bl_hw->ipc_env, cmd, sizeof(struct lmac_msg) + cmd->a2e_msg->param_len);
+        bl_os_free(cmd->a2e_msg);
+    }
+
+    if (!(cmd->flags & RWNX_CMD_FLAG_NONBLOCK)) {
+        bl_os_log_debug("Waiting ACK...\r\n");
+        e = bl_os_event_group_wait(cmd->complete,
+                                             (1 << 0),
+                                             BL_OS_TRUE,
+                                             BL_OS_FALSE,
+                                             BL_OS_WAITING_FOREVER);
+        if (e & (1 << 0)) {
+            bl_os_log_debug("cmd OK\r\n");
+        } else {
+            bl_os_log_debug("cmd timed-out\r\n");
+            cmd_dump(cmd);
+            bl_os_mutex_lock(cmd_mgr->lock);
+            cmd_mgr->state = RWNX_CMD_MGR_STATE_CRASHED;
+            if (!(cmd->flags & RWNX_CMD_FLAG_DONE)) {
+                cmd->result = ETIMEDOUT;
+                cmd_complete(cmd_mgr, cmd);
+            }
+            bl_os_mutex_unlock(cmd_mgr->lock);
+        }
+        bl_os_event_group_delete(cmd->complete);//detach after block read
+    } else {
+        bl_os_log_debug("No need to wait for CMD\r\n");
+        cmd->result = 0;
+    }
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return 0;
+}
+
+static void cmd_mgr_print(struct bl_cmd_mgr *cmd_mgr)
+{
+    struct bl_cmd *cur;
+
+    bl_os_mutex_lock(cmd_mgr->lock);
+    RWNX_DBG("q_sz/max: %2d / %2d - next tkn: %d\r\n",
+             cmd_mgr->queue_sz, cmd_mgr->max_queue_sz,
+             cmd_mgr->next_tkn);
+    list_for_each_entry(cur, &cmd_mgr->cmds, list) {
+        cmd_dump(cur);
+    }
+
+    bl_os_mutex_unlock(cmd_mgr->lock);
+}
+
+static void cmd_mgr_drain(struct bl_cmd_mgr *cmd_mgr)
+{
+    struct bl_cmd *cur, *nxt;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    bl_os_mutex_lock(cmd_mgr->lock);
+    list_for_each_entry_safe(cur, nxt, &cmd_mgr->cmds, list) {
+        list_del(&cur->list);
+        cmd_mgr->queue_sz--;
+        if (!(cur->flags & RWNX_CMD_FLAG_NONBLOCK)) {
+            bl_os_event_group_send(cur->complete, 0x1);
+        }
+    }
+    bl_os_mutex_unlock(cmd_mgr->lock);
+}
+
+static int cmd_mgr_llind(struct bl_cmd_mgr *cmd_mgr, struct bl_cmd *cmd)
+{
+    struct bl_cmd *cur, *acked = NULL, *next = NULL;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    bl_os_mutex_lock(cmd_mgr->lock);
+    list_for_each_entry(cur, &cmd_mgr->cmds, list) {
+        bl_os_log_debug("Search cmds list cmd %p vs cur %p...\r\n", cmd, cur);
+        if (!acked) {
+            bl_os_log_debug("Finding acked...\r\n");
+            if (cur->tkn == cmd->tkn) {
+                bl_os_log_debug("Found acked\r\n");
+                if (WARN_ON_ONCE(cur != cmd)) {
+                    cmd_dump(cmd);
+                }
+                acked = cur;
+                continue;
+            }
+        }
+        if (cur->flags & RWNX_CMD_FLAG_WAIT_PUSH) {
+                bl_os_log_debug("Found WAIT_PUSH\r\n");
+                next = cur;
+                break;
+        }
+    }
+    if (!acked) {
+        bl_os_log_debug("Error: acked cmd not found\r\n");
+    } else {
+        cmd->flags &= ~RWNX_CMD_FLAG_WAIT_ACK;
+        if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) {
+            bl_os_log_debug("[BUG] should cmd complete allowed here?\r\n");//FIXME attention
+            cmd_complete(cmd_mgr, cmd);// XXX potential buggy
+        } else {
+            bl_os_log_debug("[IPC] Wait Until ACKED for cmd %p, flags %08X\r\n", cmd, cmd->flags);
+        }
+    }
+    if (next) {
+        struct bl_hw *bl_hw = container_of(cmd_mgr, struct bl_hw, cmd_mgr);
+        next->flags &= ~RWNX_CMD_FLAG_WAIT_PUSH;
+        bl_os_log_debug("Pushing new CMD in llind...\r\n");
+        ipc_host_msg_push(bl_hw->ipc_env, next,
+                          sizeof(struct lmac_msg) + next->a2e_msg->param_len);
+        bl_os_free(next->a2e_msg);
+    }
+    bl_os_mutex_unlock(cmd_mgr->lock);
+
+    return 0;
+}
+
+static int cmd_mgr_msgind(struct bl_cmd_mgr *cmd_mgr, struct ipc_e2a_msg *msg, msg_cb_fct cb)
+{
+    struct bl_hw *bl_hw = container_of(cmd_mgr, struct bl_hw, cmd_mgr);
+    struct bl_cmd *cmd;
+    bool found = false;
+
+    bl_os_mutex_lock(cmd_mgr->lock);
+    list_for_each_entry(cmd, &cmd_mgr->cmds, list) {
+        if (cmd->reqid == msg->id &&
+            (cmd->flags & RWNX_CMD_FLAG_WAIT_CFM)) {
+            bl_os_log_debug("[IPC] Found cb %p for cmd %p , msg id %08X\r\n", cb, cmd, msg->id);
+            if (!cb || (cb && !cb(bl_hw, cmd, msg))) {
+                bl_os_log_debug("[IPC] NOT handed by static handler, cb %p\r\n", cb);
+                found = true;
+                cmd->flags &= ~RWNX_CMD_FLAG_WAIT_CFM;
+
+                if (cmd->e2a_msg && msg->param_len) {
+                    bl_os_log_debug("[IPC] copy back RSP to cmd %p, e2a_msg %p, len %d\r\n",
+                            cmd, cmd->e2a_msg, msg->param_len);
+                    memcpy(cmd->e2a_msg, &msg->param, msg->param_len);
+                }
+
+                if (RWNX_CMD_WAIT_COMPLETE(cmd->flags)) {
+                    cmd_complete(cmd_mgr, cmd);
+                }
+
+                break;
+            } else {
+                bl_os_log_debug("[IPC] MSG is handled by static handler\r\n");
+            }
+        }
+    }
+    bl_os_mutex_unlock(cmd_mgr->lock);
+
+    if (!found && cb)
+        cb(bl_hw, NULL, msg);
+
+    return 0;
+}
+
+void bl_cmd_mgr_init(struct bl_cmd_mgr *cmd_mgr)
+{
+    INIT_LIST_HEAD(&cmd_mgr->cmds);
+    cmd_mgr->lock = bl_os_mutex_create();
+    ASSERT_ERR(NULL != cmd_mgr->lock);
+
+    cmd_mgr->max_queue_sz = RWNX_CMD_MAX_QUEUED;
+    cmd_mgr->queue  = &cmd_mgr_queue;
+    cmd_mgr->print  = &cmd_mgr_print;
+    cmd_mgr->drain  = &cmd_mgr_drain;
+    cmd_mgr->llind  = &cmd_mgr_llind;
+    cmd_mgr->msgind = &cmd_mgr_msgind;
+}

+ 75 - 0
network/wifi_manager/bl60x_wifi_driver/bl_cmds.h

@@ -0,0 +1,75 @@
+#ifndef __RWNX_CMDS_H__
+#define __RWNX_CMDS_H__
+
+#include "list.h"
+
+#include "lmac_types.h"
+#include "lmac_msg.h"
+#include "ipc_shared.h"
+#include "bl_os_private.h"
+
+#define BIT(n) (0x1U << (n))
+
+#define RWNX_CMD_FLAG_NONBLOCK      BIT(0)
+#define RWNX_CMD_FLAG_REQ_CFM       BIT(1)
+#define RWNX_CMD_FLAG_WAIT_PUSH     BIT(2)
+#define RWNX_CMD_FLAG_WAIT_ACK      BIT(3)
+#define RWNX_CMD_FLAG_WAIT_CFM      BIT(4)
+#define RWNX_CMD_FLAG_DONE          BIT(5)
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_cmds.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#define RWNX_CMD_WAIT_COMPLETE(flags) \
+        (!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM)))
+
+//TODO fix the follow ugly declare
+struct bl_hw;
+struct bl_cmd;
+typedef int (*msg_cb_fct)(struct bl_hw *bl_hw, struct bl_cmd *cmd, struct ipc_e2a_msg *msg);
+
+#define RWNX_CMD_MAX_QUEUED         8
+struct bl_cmd {
+    struct list_head list;
+    ke_msg_id_t id;
+    ke_msg_id_t reqid;
+    struct lmac_msg *a2e_msg;
+    char            *e2a_msg;
+    u32 tkn;
+    u16 flags;
+
+    BL_EventGroup_t complete;
+    u32 result;
+};
+
+enum bl_cmd_mgr_state {
+     RWNX_CMD_MGR_STATE_DEINIT,
+     RWNX_CMD_MGR_STATE_INITED,
+     RWNX_CMD_MGR_STATE_CRASHED,
+};
+
+struct bl_cmd_mgr {
+    enum bl_cmd_mgr_state state;
+    u32 next_tkn;
+    u32 queue_sz;
+    u32 max_queue_sz;
+
+    struct list_head cmds;
+    BL_Mutex_t lock;
+
+    int  (*queue)(struct bl_cmd_mgr *, struct bl_cmd *);
+    int  (*llind)(struct bl_cmd_mgr *, struct bl_cmd *);
+    int  (*msgind)(struct bl_cmd_mgr *, struct ipc_e2a_msg *, msg_cb_fct);
+    void (*print)(struct bl_cmd_mgr *);
+    void (*drain)(struct bl_cmd_mgr *);
+};
+
+void bl_cmd_mgr_init(struct bl_cmd_mgr *cmd_mgr);
+
+#endif

+ 294 - 0
network/wifi_manager/bl60x_wifi_driver/bl_defs.h

@@ -0,0 +1,294 @@
+#ifndef __RWNX_DEFS_H__
+#define __RWNX_DEFS_H__
+#include "errno.h"
+#include "ipc_host.h"
+#include "ipc_shared.h"
+#include "bl_cmds.h"
+#include "bl_mod_params.h"
+
+#define ETH_ALEN    6       
+/**
+ ****************************************************************************************
+ *
+ * @file bl_defs.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#define ETH_P_PAE   0x888E      /* Port Access Entity (IEEE 802.1X) */
+
+#include "ieee80211.h"
+#include "cfg80211.h"
+#include "nl80211.h"
+
+//#define CONFIG_RWNX_DBG
+
+#define RWNX_RXBUFF_MAX (4 * 1)
+#define IEEE80211_MIN_AMPDU_BUF 0x8
+#define IEEE80211_MAX_AMPDU_BUF 0x40
+#define NX_VIRT_DEV_MAX 2
+#define NX_REMOTE_STA_MAX CFG_STA_MAX
+#define CONFIG_USER_MAX 1
+#define cpu_to_le16(v16) (v16)
+#define cpu_to_le32(v32) (v32)
+#define le16_to_cpu(v16) (v16)
+#define le32_to_cpu(v32) (v32)
+#define RWNX_TX_LIFETIME_MS             100
+
+#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT   2
+
+#define RWNX_HWTXHDR_ALIGN_SZ           4
+#define RWNX_HWTXHDR_ALIGN_MSK (RWNX_HWTXHDR_ALIGN_SZ - 1)
+#define RWNX_HWTXHDR_ALIGN_PADS(x) \
+                    ((RWNX_HWTXHDR_ALIGN_SZ - ((x) & RWNX_HWTXHDR_ALIGN_MSK)) \
+                     & RWNX_HWTXHDR_ALIGN_MSK)
+
+#define REG_SW_SET_PROFILING(env, value)   do{  }while(0)
+#define REG_SW_CLEAR_PROFILING(env, value)   do{  }while(0)
+
+enum {
+    SW_PROF_HOSTBUF_IDX = 12,
+    /****** IPC IRQs related signals ******/
+    /* E2A direction */
+    SW_PROF_IRQ_E2A_RXDESC = 16,    // to make sure we let 16 bits available for LMAC FW
+    SW_PROF_IRQ_E2A_TXCFM,
+    SW_PROF_IRQ_E2A_DBG,
+    SW_PROF_IRQ_E2A_MSG,
+    SW_PROF_IPC_MSGPUSH,
+    SW_PROF_MSGALLOC,
+    SW_PROF_MSGIND,
+    SW_PROF_DBGIND,
+
+    /* A2E direction */
+    SW_PROF_IRQ_A2E_TXCFM_BACK,
+
+    /****** Driver functions related signals ******/
+    SW_PROF_WAIT_QUEUE_STOP,
+    SW_PROF_WAIT_QUEUE_WAKEUP,
+    SW_PROF_RWNXDATAIND,
+    SW_PROF_RWNX_IPC_IRQ_HDLR,
+    SW_PROF_RWNX_IPC_THR_IRQ_HDLR,
+    SW_PROF_IEEE80211RX,
+    SW_PROF_RWNX_PATTERN,
+    SW_PROF_MAX
+};
+
+/*
+ *  * Maximum length of AMPDU that the STA can receive.
+ *   * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
+ *    */
+enum ieee80211_max_ampdu_length_exp {
+    IEEE80211_HT_MAX_AMPDU_8K = 0,
+    IEEE80211_HT_MAX_AMPDU_16K = 1,
+    IEEE80211_HT_MAX_AMPDU_32K = 2,
+    IEEE80211_HT_MAX_AMPDU_64K = 3
+};
+
+
+/* U-APSD queues for WMM IEs sent by STA */
+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO  (1<<0)
+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI  (1<<1)
+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK  (1<<2)
+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE  (1<<3)
+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK    0x0f
+/**
+* enum ieee80211_vht_mcs_support - VHT MCS support definitions
+* @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the
+* number of streams
+* @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported
+* @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported
+* @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported
+*
+* These definitions are used in each 2-bit subfield of the @rx_mcs_map
+* and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are
+* both split into 8 subfields by number of streams. These values indicate
+* which MCSes are supported for the number of streams the value appears
+* for.
+*/
+enum ieee80211_vht_mcs_support {
+    IEEE80211_VHT_MCS_SUPPORT_0_7   = 0,
+    IEEE80211_VHT_MCS_SUPPORT_0_8   = 1,
+    IEEE80211_VHT_MCS_SUPPORT_0_9   = 2,
+    IEEE80211_VHT_MCS_NOT_SUPPORTED = 3,
+};
+
+enum RWNX_INTERFACE_STATUS {
+    RWNX_INTERFACE_STATUS_DOWN = 0,
+    RWNX_INTERFACE_STATUS_UP = 1,
+};
+
+struct bl_stats {
+    int cfm_balance;
+    unsigned long last_rx, last_tx; /* jiffies */
+};
+
+struct bl_patternbuf {
+    u32 *buf;
+    u32 dma_addr;
+    int bufsz;
+};
+
+struct bl_dbginfo {
+    BL_Mutex_t mutex;
+    struct dbg_debug_dump_tag *buf;
+    u32 dma_addr;
+    int bufsz;
+};
+
+struct net_device_stats {
+	unsigned long	rx_packets;
+	unsigned long	tx_packets;
+	unsigned long	rx_bytes;
+	unsigned long	tx_bytes;
+	unsigned long	rx_errors;
+	unsigned long	tx_errors;
+	unsigned long	rx_dropped;
+	unsigned long	tx_dropped;
+	unsigned long	multicast;
+	unsigned long	collisions;
+	unsigned long	rx_length_errors;
+	unsigned long	rx_over_errors;
+	unsigned long	rx_crc_errors;
+	unsigned long	rx_frame_errors;
+	unsigned long	rx_fifo_errors;
+	unsigned long	rx_missed_errors;
+	unsigned long	tx_aborted_errors;
+	unsigned long	tx_carrier_errors;
+	unsigned long	tx_fifo_errors;
+	unsigned long	tx_heartbeat_errors;
+	unsigned long	tx_window_errors;
+	unsigned long	rx_compressed;
+	unsigned long	tx_compressed;
+};
+
+/*
+ * Structure used to save information relative to the managed stations.
+ */
+struct bl_sta {
+    struct mac_addr sta_addr;
+    u8 is_used;
+    u8 sta_idx;             /* Identifier of the station */
+    u8 vif_idx;             /* Identifier of the VIF (fw id) the station
+                               belongs to */
+    u8 vlan_idx;            /* Identifier of the VLAN VIF (fw id) the station
+                               belongs to (= vif_idx if no vlan in used) */
+    uint8_t qos;
+    int8_t rssi;
+    uint8_t data_rate;
+    uint32_t tsflo;
+    uint32_t tsfhi;
+};
+
+/**
+ * struct bl_bcn - Information of the beacon in used (AP mode)
+ *
+ * @head: head portion of beacon (before TIM IE)
+ * @tail: tail portion of beacon (after TIM IE)
+ * @ies: extra IEs (not used ?)
+ * @head_len: length of head data
+ * @tail_len: length of tail data
+ * @ies_len: length of extra IEs data
+ * @tim_len: length of TIM IE
+ * @len: Total beacon len (head + tim + tail + extra)
+ * @dtim: dtim period
+ */
+struct bl_bcn {
+    u8 *head;
+    u8 *tail;
+    u8 *ies;
+    size_t head_len;
+    size_t tail_len;
+    size_t ies_len;
+    size_t tim_len;
+    size_t len;
+    u8 dtim;
+};
+
+/*
+ * Structure used to save information relative to the managed interfaces.
+ * This is also linked within the bl_hw vifs list.
+ *
+ */
+struct bl_vif {
+    struct list_head list;
+    struct netif *dev;
+    bool up;                    /* Indicate if associated netdev is up
+                                   (i.e. Interface is created at fw level) */
+    union
+    {
+        struct
+        {
+            struct bl_sta *ap; /* Pointer to the peer STA entry allocated for
+                                    the AP */
+            struct bl_sta *tdls_sta; /* Pointer to the TDLS station */
+        } sta;
+        struct
+        {
+            struct list_head sta_list; /* List of STA connected to the AP */
+            u8 bcmc_index;             /* Index of the BCMC sta to use */
+        } ap;
+        struct
+        {
+            struct bl_vif *master;   /* pointer on master interface */
+            struct bl_sta *sta_4a;
+        } ap_vlan;
+    };
+};
+
+struct bl_hw {
+    int is_up;
+    struct bl_cmd_mgr cmd_mgr;
+    struct ipc_host_env_tag *ipc_env;           /* store the IPC environment */
+    struct list_head vifs;
+    struct bl_vif vif_table[NX_VIRT_DEV_MAX + NX_REMOTE_STA_MAX]; /* indexed with fw id */
+    struct bl_sta sta_table[NX_REMOTE_STA_MAX + NX_VIRT_DEV_MAX];
+    unsigned long drv_flags;
+    struct bl_mod_params *mod_params;
+    struct ieee80211_sta_ht_cap ht_cap;
+    int vif_index_sta;
+    int vif_index_ap;
+
+    /*custom added id*/
+    int sta_idx;
+    int ap_bcmc_idx;
+#ifdef CFG_BL_STATISTIC
+    struct bl_stats       stats;
+#endif
+};
+
+struct ethhdr {
+    unsigned char   h_dest[ETH_ALEN];   /* destination eth addr */
+    unsigned char   h_source[ETH_ALEN]; /* source ether addr    */
+    __be16      h_proto;        /* packet type ID field */
+} __attribute__((packed));
+
+/// Definitions of the RF bands
+enum
+{
+    /// 2.4GHz Band
+    PHY_BAND_2G4,
+    /// 5GHz band
+    PHY_BAND_5G,
+    /// Number of bands
+    PHY_BAND_MAX,
+};
+
+/// Definitions of the channel bandwidths
+enum
+{
+    /// 20MHz BW
+    PHY_CHNL_BW_20,
+    /// 40MHz BW
+    PHY_CHNL_BW_40,
+    /// 80MHz BW
+    PHY_CHNL_BW_80,
+    /// 160MHz BW
+    PHY_CHNL_BW_160,
+    /// 80+80MHz BW
+    PHY_CHNL_BW_80P80,
+    /// Reserved BW
+    PHY_CHNL_BW_OTHER,
+};
+
+#endif

+ 89 - 0
network/wifi_manager/bl60x_wifi_driver/bl_irqs.c

@@ -0,0 +1,89 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_irqs.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#include "bl_defs.h"
+#include "bl_irqs.h"
+#include "ipc_host.h"
+#include "bl_os_private.h"
+
+#define REG_SW_SET_PROFILING(env, value)   do{  }while(0)
+#define REG_SW_CLEAR_PROFILING(env, value)   do{  }while(0)
+#define REG_SW_CLEAR_HOSTBUF_IDX_PROFILING(env)   do{  }while(0)
+#define REG_SW_SET_HOSTBUF_IDX_PROFILING(env, val)   do{  }while(0)
+#define BIT_0    ( 1 << 0 )
+#define BIT_1    ( 1 << 1 )
+
+static uint32_t time_irq_start __attribute__((unused)), time_irq_end __attribute__((unused));
+
+static struct bl_hw *wifi_hw;
+#ifdef RWNX_IRQS_DEBUG_ENABLE
+#define RWNX_IRQS_DEBUG(...) \
+{ \
+    bl_os_printf(__VA_ARGS__); \
+}
+#else
+#define RWNX_IRQS_DEBUG(...) do {} while(0)
+#endif
+
+int bl_irqs_init(struct bl_hw *bl_hw)
+{
+    wifi_hw = bl_hw;
+
+    return 0;
+}
+
+int bl_irqs_enable(void)
+{
+    return 0;
+}
+
+int bl_irqs_disable(void)
+{
+    return 0;
+}
+
+void bl_irq_bottomhalf(struct bl_hw *bl_hw)
+{
+    u32 status, statuses = 0;
+#ifdef CFG_BL_STATISTIC
+    unsigned long now = bl_os_get_time_ms();
+#endif
+
+    REG_SW_SET_PROFILING(bl_hw, SW_PROF_RWNX_IPC_IRQ_HDLR);
+    status = ipc_host_get_rawstatus(bl_hw->ipc_env);
+
+redo:
+    while (status) {
+        statuses |= status;
+        /* All kinds of IRQs will be handled in one shot (RX, MSG, DBG, ...)
+         * this will ack IPC irqs not the cfpga irqs */
+        ipc_host_irq(bl_hw->ipc_env, status);
+        status = ipc_host_get_rawstatus(bl_hw->ipc_env);
+    }
+    // bl_os_log_warn("[BH] Handle Event %08X\r\n", statuses);
+#ifdef CFG_BL_STATISTIC
+    now = bl_os_get_time_ms();
+    if (statuses & IPC_IRQ_E2A_RXDESC) {
+        bl_hw->stats.last_rx = now;
+    }
+    if (statuses & IPC_IRQ_E2A_TXCFM) {
+        bl_hw->stats.last_tx = now;
+    }
+#endif
+
+    REG_SW_CLEAR_PROFILING(bl_hw, SW_PROF_RWNX_IPC_IRQ_HDLR);
+
+    ipc_host_enable_irq(bl_hw->ipc_env, IPC_IRQ_E2A_ALL);
+    /*we check irq status again, because we think there is corner case here*/
+    status = ipc_host_get_rawstatus(bl_hw->ipc_env);
+    if (status) {
+        goto redo;
+    }
+}

+ 23 - 0
network/wifi_manager/bl60x_wifi_driver/bl_irqs.h

@@ -0,0 +1,23 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_irqs.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#ifndef _RWNX_IRQS_H_
+#define _RWNX_IRQS_H_
+#include <stdint.h>
+#include "bl_defs.h"
+
+int bl_irqs_init(struct bl_hw *bl_hw);
+int bl_irqs_enable(void);
+int bl_irqs_disable(void);
+int bl_irqs_notify(void);
+int bl_irq_wait_event(uint32_t tick);
+void bl_irq_bottomhalf(struct bl_hw *bl_hw);
+
+#endif /* _RWNX_IRQS_H_ */

+ 618 - 0
network/wifi_manager/bl60x_wifi_driver/bl_main.c

@@ -0,0 +1,618 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <lwip/opt.h>
+#include <lwip/def.h>
+#include <lwip/mem.h>
+#include <lwip/pbuf.h>
+#include <netif/etharp.h>
+#include <bl_wifi.h>
+
+#include "bl_main.h"
+#include "bl_defs.h"
+#include "bl_utils.h"
+#include "bl_platform.h"
+#include "bl_msg_tx.h"
+#include "bl_irqs.h"
+#include "bl_tx.h"
+
+#ifdef CONFIG_BL_MAIN_DEBUG
+#define BL_MAIN_DBG        bl_os_printf
+#else
+#define BL_MAIN_DBG(a...) do {} while (0)
+#endif
+
+#include <bl_os_private.h>
+#define USER_UNUSED(a) ((void)(a))
+#define RWNX_PRINT_CFM_ERR(req) \
+        bl_os_printf("%s: Status Error(%d)\n", #req, (&req##_cfm)->status)
+
+struct bl_hw wifi_hw;
+
+int bl_cfg80211_connect(struct bl_hw *bl_hw, struct cfg80211_connect_params *sme);
+
+static void bl_set_vers(struct mm_version_cfm *version_cfm_ptr)
+{
+    u32 vers = version_cfm_ptr->version_lmac;
+
+    USER_UNUSED(vers);
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    bl_os_printf("[version] lmac %u.%u.%u.%u\r\n",
+        (unsigned int)((vers >> 24) & 0xFF),
+        (unsigned int)((vers >> 16) & 0xFF),
+        (unsigned int)((vers >>  8) & 0xFF),
+        (unsigned int)((vers >>  0) & 0xFF)
+    );
+    bl_os_printf("[version] version_machw_1 %08X\r\n", (unsigned int)version_cfm_ptr->version_machw_1);
+    bl_os_printf("[version] version_machw_2 %08X\r\n", (unsigned int)version_cfm_ptr->version_machw_2);
+    bl_os_printf("[version] version_phy_1 %08X\r\n", (unsigned int)version_cfm_ptr->version_phy_1);
+    bl_os_printf("[version] version_phy_2 %08X\r\n", (unsigned int)version_cfm_ptr->version_phy_2);
+    bl_os_printf("[version] features %08X\r\n", (unsigned int)version_cfm_ptr->features);
+
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+}
+
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_main.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+/**
+ * int (*ndo_open)(struct net_device *dev);
+ *     This function is called when network device transistions to the up
+ *     state.
+ *
+ * - Start FW if this is the first interface opened
+ * - Add interface at fw level
+ */
+int bl_open(struct bl_hw *bl_hw)
+{
+#if 0
+    struct mm_add_if_cfm add_if_cfm;
+#if 0
+    struct apm_start_cfm start_ap_cfm;
+#endif
+    int error = 0;
+    const unsigned char mac[] = {0x00, 0x50, 0x43, 0xC9, 0x00, 0x01};
+    struct cfg80211_connect_params sme;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    // Check if it is the first opened VIF
+    if (bl_hw->vif_started == 0)
+    {
+        // Start the FW
+       BL_MAIN_DBG("[WF] MM_START_REQ Sending\r\n");
+       error = bl_send_start(bl_hw);
+       BL_MAIN_DBG("[WF] MM_START_REQ Done\r\n");
+       if (error) {
+           return error;
+       }
+
+       /* Device is now started */
+       bl_hw->drv_flags |= (1 << RWNX_DEV_STARTED);
+    }
+
+#if 0
+    /* Forward the information to the LMAC,
+     *     p2p value not used in FMAC configuration, iftype is sufficient */
+    BL_MAIN_DBG("[WF] MM_ADD_IF_REQ Sending\r\n");
+    error = bl_send_add_if(bl_hw, mac, NL80211_IFTYPE_AP, false, &add_if_cfm);
+    BL_MAIN_DBG("[WF] MM_ADD_IF_REQ Done\r\n");
+    if (error) {
+        return error;
+    }
+
+    if (add_if_cfm.status != 0) {
+        RWNX_PRINT_CFM_ERR(add_if);
+        return -EIO;
+    }
+
+    /* Save the index retrieved from LMAC */
+    bl_hw->vif_index = add_if_cfm.inst_nbr;
+
+    BL_MAIN_DBG("[WF] vif_index from LAMC is %d\r\n", bl_hw->vif_index);
+
+    BL_MAIN_DBG("[WF] APM_START_REQ Sending\r\n");
+    bl_send_apm_start_req(bl_hw, &start_ap_cfm);
+    BL_MAIN_DBG("[WF] APM_START_REQ Done\r\n");
+#else
+    /* Forward the information to the LMAC,
+     *     p2p value not used in FMAC configuration, iftype is sufficient */
+    BL_MAIN_DBG("[WF] MM_ADD_IF_REQ Sending\r\n");
+    error = bl_send_add_if(bl_hw, mac, NL80211_IFTYPE_STATION, false, &add_if_cfm);
+    BL_MAIN_DBG("[WF] MM_ADD_IF_REQ Done\r\n");
+    if (error) {
+        return error;
+    }
+
+    if (add_if_cfm.status != 0) {
+        RWNX_PRINT_CFM_ERR(add_if);
+        return -EIO;
+    }
+
+    /* Save the index retrieved from LMAC */
+    bl_hw->vif_index = add_if_cfm.inst_nbr;
+
+#undef BL_MAIN_DBG
+    BL_MAIN_DBG("[WF] vif_index from LAMC is %d\r\n", bl_hw->vif_index);
+#define BL_MAIN_DBG(...) do {} while(0)
+
+#if 0
+    BL_MAIN_DBG("[WF] SM_CONNECT_REQ Sending\r\n");
+    memset(&sme, 0, sizeof(struct cfg80211_connect_params));
+    sme.crypto.n_ciphers_pairwise = 0;
+    sme.ssid_len = 7;
+    sme.ssid = "LEDE_4G";
+    sme.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+    bl_cfg80211_connect(bl_hw, &sme);
+    BL_MAIN_DBG("[WF] SM_CONNECT_REQ Done\r\n");
+#endif
+#endif
+
+    return error;
+#else
+    return 0;
+#endif
+}
+
+int bl_main_connect(const uint8_t* ssid, int ssid_len, const uint8_t *psk, int psk_len, const uint8_t *pmk, int pmk_len, const uint8_t *mac, const uint8_t band, const uint16_t freq, const uint32_t flags)
+{
+    struct cfg80211_connect_params sme;
+
+    memset(&sme, 0, sizeof(struct cfg80211_connect_params));
+    sme.crypto.n_ciphers_pairwise = 0;
+    sme.ssid_len = ssid_len;
+    sme.ssid = ssid;
+    sme.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
+    sme.key = psk;
+    sme.key_len = psk_len;
+    sme.pmk = pmk;
+    sme.pmk_len = pmk_len;
+    sme.flags = flags;
+
+    if (mac){
+        sme.bssid = mac;
+    }
+
+    if (freq > 0) {
+        sme.channel.center_freq = freq;
+        sme.channel.band = band;
+        sme.channel.flags = 0;
+    }
+
+    bl_cfg80211_connect(&wifi_hw, &sme);
+
+    return 0;
+}
+
+int bl_main_disconnect()
+{
+    bl_send_sm_disconnect_req(&wifi_hw);
+    return 0;
+}
+
+int bl_main_powersaving(int mode)
+{
+    return bl_send_mm_powersaving_req(&wifi_hw, mode);
+}
+
+int bl_main_denoise(int mode)
+{
+    return bl_send_mm_denoise_req(&wifi_hw, mode);
+}
+
+int bl_main_monitor()
+{
+    struct mm_monitor_cfm cfm;
+
+    memset(&cfm, 0, sizeof(cfm));
+    bl_send_monitor_enable(&wifi_hw, &cfm);
+    return 0;
+}
+
+int bl_main_monitor_disable()
+{
+    struct mm_monitor_cfm cfm;
+
+    memset(&cfm, 0, sizeof(cfm));
+    bl_send_monitor_disable(&wifi_hw, &cfm);
+    return 0;
+}
+
+int bl_main_phy_up()
+{
+    int error = 0;
+
+    error = bl_send_start(&wifi_hw);
+    if (error) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int bl_main_channel_set(int channel)
+{
+    bl_send_channel_set_req(&wifi_hw, channel);
+
+    return 0;
+}
+
+int bl_main_monitor_channel_set(int channel, int use_40MHZ)
+{
+    struct mm_monitor_channel_cfm cfm;
+
+    bl_send_monitor_channel_set(&wifi_hw, &cfm, channel, use_40MHZ);
+
+    return 0;
+}
+
+int bl_main_beacon_interval_set(uint16_t beacon_int)
+{
+    struct mm_set_beacon_int_cfm cfm;
+
+    bl_send_beacon_interval_set(&wifi_hw, &cfm, beacon_int);
+
+    return 0;
+}
+
+int bl_main_if_remove(uint8_t vif_index)
+{
+    bl_os_printf("[WF] MM_REMOVE_IF_REQ Sending with vif_index %u...\r\n", vif_index);
+    bl_send_remove_if(&wifi_hw, vif_index);
+    bl_os_printf("[WF] MM_REMOVE_IF_REQ Done\r\n");
+    return 0;
+}
+
+int bl_main_raw_send(uint8_t *pkt , int len)
+{
+    return bl_send_scanu_raw_send(&wifi_hw, pkt, len);
+}
+
+int bl_main_rate_config(uint8_t sta_idx, uint16_t fixed_rate_cfg)
+{
+    return bl_send_me_rate_config_req(&wifi_hw, sta_idx, fixed_rate_cfg);
+}
+
+int bl_main_set_country_code(char *country_code)
+{
+    bl_os_log_info("%s: country code: %s\r\n", __func__, country_code);
+    bl_msg_update_channel_cfg((const char *)country_code);
+    bl_send_me_chan_config_req(&wifi_hw);
+
+    return 0;
+}
+
+int bl_main_get_channel_nums()
+{
+    return bl_msg_get_channel_nums();
+}
+
+int bl_main_if_add(int is_sta, struct netif *netif, uint8_t *vif_index)
+{
+    struct mm_add_if_cfm add_if_cfm;
+    int error = 0;
+    uint8_t hwaddr[6];
+
+    bl_os_printf("[WF] MM_ADD_IF_REQ Sending: %s\r\n", is_sta ? "STA" : "AP");
+
+    wifi_mgmr_sta_mac_get(hwaddr);
+    bl_os_printf("hwaddr:%02x-%02x-%02x-%02x-%02x-%02x\r\n", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
+    error = bl_send_add_if(
+            &wifi_hw,
+            hwaddr,
+            is_sta ? NL80211_IFTYPE_STATION : NL80211_IFTYPE_AP,
+            false,
+            &add_if_cfm
+    );
+    bl_os_printf("[WF] MM_ADD_IF_REQ Done\r\n");
+    if (error) {
+        return error;
+    }
+
+    if (add_if_cfm.status != 0) {
+        RWNX_PRINT_CFM_ERR(add_if);
+        return -EIO;
+    }
+    /* Save the index retrieved from LMAC */
+    if (is_sta) {
+        wifi_hw.vif_index_sta = add_if_cfm.inst_nbr;
+    } else {
+        wifi_hw.vif_index_ap = add_if_cfm.inst_nbr;
+    }
+    *vif_index = add_if_cfm.inst_nbr;
+
+    bl_os_printf("[WF] vif_index from LAMC is %d\r\n", *vif_index);
+    wifi_hw.vif_table[add_if_cfm.inst_nbr].dev = netif;
+    wifi_hw.vif_table[add_if_cfm.inst_nbr].up = 1;
+
+    return error;
+}
+
+int bl_main_apm_start(char *ssid, char *password, int channel, uint8_t vif_index, uint8_t hidden_ssid, uint16_t bcn_int)
+{
+    int error = 0;
+    struct apm_start_cfm start_ap_cfm;
+
+    memset(&start_ap_cfm, 0, sizeof(start_ap_cfm));
+    bl_os_printf("[WF] APM_START_REQ Sending with vif_index %u\r\n", vif_index);
+    error = bl_send_apm_start_req(&wifi_hw, &start_ap_cfm, ssid, password, channel, vif_index, hidden_ssid, bcn_int);
+    bl_os_printf("[WF] APM_START_REQ Done\r\n");
+    bl_os_printf("[WF] status is %02X\r\n", start_ap_cfm.status);
+    bl_os_printf("[WF] vif_idx is %02X\r\n", start_ap_cfm.vif_idx);
+    bl_os_printf("[WF] ch_idx is %02X\r\n", start_ap_cfm.ch_idx);
+    bl_os_printf("[WF] bcmc_idx is %02X\r\n", start_ap_cfm.bcmc_idx);
+    wifi_hw.ap_bcmc_idx = start_ap_cfm.bcmc_idx;
+
+    return error;
+}
+
+int bl_main_apm_stop(uint8_t vif_index)
+{
+    int error = 0;
+
+    bl_os_printf("[WF] APM_STOP_REQ Sending with vif_index %u\r\n", vif_index);
+    error = bl_send_apm_stop_req(&wifi_hw, vif_index);
+    bl_os_printf("[WF] APM_STOP_REQ Done\r\n");
+
+    return error;
+}
+
+int bl_main_apm_sta_cnt_get(uint8_t *sta_cnt)
+{
+    struct bl_hw *bl_hw = &wifi_hw;
+    uint8_t cnt = 0, i;
+    struct bl_sta *sta;
+    uint8_t total_sta_cnt = sizeof(bl_hw->sta_table)/sizeof(bl_hw->sta_table[0]);
+
+    for (i = 0; i < total_sta_cnt; i++) {
+        sta = &(bl_hw->sta_table[i]);
+        if (0 == sta->is_used) {
+            /*empty entry*/
+            continue;
+        }
+        cnt++;
+    }
+    (*sta_cnt) = total_sta_cnt;
+    bl_os_log_info("Max limit sta cnt = %u, valid sta cnt = %u\r\n", total_sta_cnt, cnt);
+    return 0;
+}
+
+int bl_main_apm_sta_info_get(struct wifi_apm_sta_info *apm_sta_info, uint8_t idx)
+{
+    struct bl_hw *bl_hw = &wifi_hw;
+    struct bl_sta *sta;
+
+    sta = &(bl_hw->sta_table[idx]);
+    if (0 == sta->is_used) {
+        /*empty entry*/
+        return 0;
+    }
+    apm_sta_info->sta_idx = sta->sta_idx;
+    apm_sta_info->is_used = sta->is_used;
+    apm_sta_info->rssi = sta->rssi;
+    apm_sta_info->tsflo = sta->tsflo;
+    apm_sta_info->tsfhi = sta->tsfhi;
+    apm_sta_info->data_rate = sta->data_rate;
+    memcpy(apm_sta_info->sta_mac, sta->sta_addr.array, 6);
+
+    return 0;
+}
+
+int bl_main_apm_sta_delete(uint8_t sta_idx)
+{
+    struct bl_hw *bl_hw = &wifi_hw;
+    struct bl_sta *sta;
+    struct apm_sta_del_cfm sta_del_cfm;
+    uint8_t vif_idx = 0;
+
+    sta = &(bl_hw->sta_table[sta_idx]);
+    if (sta == NULL)
+        return -1;
+
+    memset(&sta_del_cfm, 0, sizeof(struct apm_sta_del_cfm));
+    vif_idx = sta->vif_idx;
+    bl_os_printf("[WF] APM_STA_DEL_REQ: sta_idx = %u, vif_idx = %u\r\n", sta_idx, vif_idx);
+
+    bl_send_apm_sta_del_req(bl_hw, &sta_del_cfm, sta_idx, vif_idx);
+    if (sta_del_cfm.status != 0) {
+        bl_os_log_info("del sta failure, cfm status = 0x%x\r\n", sta_del_cfm.status);
+        return -1;
+    }
+
+    memset(sta, 0, sizeof(struct bl_sta));
+    return 0;
+}
+
+int bl_main_apm_remove_all_sta()
+{
+    struct bl_hw *bl_hw = &wifi_hw;
+    struct bl_sta *sta;
+    uint8_t total_sta_cnt = sizeof(bl_hw->sta_table)/sizeof(bl_hw->sta_table[0]);
+    uint8_t i;
+
+    for (i = 0; i < total_sta_cnt; i++) {
+        sta = &(bl_hw->sta_table[i]);
+        if (1 == sta->is_used) {
+            bl_os_log_info("del sta[%u]\r\n", i);
+            bl_main_apm_sta_delete(i);
+        }
+    }
+    return 0;
+}
+
+int bl_main_conf_max_sta(uint8_t max_sta_supported)
+{
+    return bl_send_apm_conf_max_sta_req(&wifi_hw, max_sta_supported);
+}
+
+int bl_main_cfg_task_req(uint32_t ops, uint32_t task, uint32_t element, uint32_t type, void *arg1, void *arg2)
+{
+    return bl_send_cfg_task_req(&wifi_hw, ops, task, element, type, arg1, arg2);
+}
+
+int bl_main_scan(struct netif *netif, uint16_t *fixed_channels, uint16_t channel_num, struct mac_addr *bssid, struct mac_ssid *ssid, uint8_t scan_mode, uint32_t duration_scan)
+{
+    struct bl_send_scanu_para scanu_para;
+    
+    scanu_para.channels = fixed_channels;
+    scanu_para.channel_num = channel_num;
+    scanu_para.bssid = bssid;
+    scanu_para.ssid = ssid;
+    wifi_mgmr_sta_mac_get(scanu_para.mac);
+    // scanu_para.mac = netif->hwaddr;
+    scanu_para.scan_mode = scan_mode;
+    scanu_para.duration_scan = duration_scan;
+
+    if (0 == channel_num) {
+        scanu_para.channels = NULL;
+        scanu_para.channel_num = 0;
+        bl_send_scanu_req(&wifi_hw, &scanu_para);
+    } else {
+        if (bl_get_fixed_channels_is_valid(fixed_channels, channel_num)) {
+            bl_send_scanu_req(&wifi_hw, &scanu_para);
+        } else {
+            bl_os_printf("---->unvalid channel");
+        }
+    }
+    return 0;
+}
+
+int bl_main_connect_abort(uint8_t *status)
+{
+    struct sm_connect_abort_cfm connect_abort_cfm = {};
+    bl_send_sm_connect_abort_req(&wifi_hw, &connect_abort_cfm);
+    *status = connect_abort_cfm.status;
+    return 0;
+}
+
+static int cfg80211_init(struct bl_hw *bl_hw)
+{
+    int ret = 0;
+    struct mm_version_cfm version_cfm = {};
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    INIT_LIST_HEAD(&bl_hw->vifs);
+
+    bl_hw->mod_params = &bl_mod_params;
+
+    ret = bl_platform_on(bl_hw);
+    if (ret) {
+        bl_os_printf("bl_platform_on Error\r\n");
+        goto err_out;
+    }
+
+    ipc_host_enable_irq(bl_hw->ipc_env, IPC_IRQ_E2A_ALL);
+    bl_wifi_enable_irq();
+
+    /* Reset FW */
+    ret = bl_send_reset(bl_hw);
+    if (ret) {
+        bl_os_printf("bl_send_reset Error\r\n");
+        goto err_out;
+    }
+    bl_os_msleep(5);
+    ret = bl_send_version_req(bl_hw, &version_cfm);
+    if (ret) {
+        goto err_out;
+    }
+    bl_set_vers(&version_cfm);
+    ret = bl_handle_dynparams(bl_hw);
+    if (ret) {
+        bl_os_printf("bl_handle_dynparams Error\r\n");
+        goto err_out;
+    }
+
+    /* Set parameters to firmware */
+    bl_send_me_config_req(bl_hw);
+
+    /* Set channel parameters to firmware (must be done after WiPHY registration) */
+    bl_send_me_chan_config_req(bl_hw);
+
+
+err_out:
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return ret;
+}
+
+int bl_cfg80211_connect(struct bl_hw *bl_hw, struct cfg80211_connect_params *sme)
+{
+    struct sm_connect_cfm sm_connect_cfm;
+    int error = 0;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Forward the information to the LMAC */
+    error = bl_send_sm_connect_req(bl_hw, sme, &sm_connect_cfm);
+    if (error) {
+        return error;
+    }
+
+    // Check the status
+    switch (sm_connect_cfm.status)
+    {
+        case CO_OK:
+            error = 0;
+            break;
+        case CO_BUSY:
+            error = -EINPROGRESS;
+            break;
+        case CO_OP_IN_PROGRESS:
+            error = -EALREADY;
+            break;
+        default:
+            error = -EIO;
+            break;
+    }
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+
+    return error;
+}
+
+int bl_cfg80211_disconnect(struct bl_hw *bl_hw)
+{
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    return bl_send_sm_disconnect_req(bl_hw);
+}
+
+void bl_main_event_handle()
+{
+    bl_irq_bottomhalf(&wifi_hw);
+    bl_tx_try_flush();
+}
+
+void bl_main_lowlevel_init()
+{
+    /*Call IRQ init here, since GroupEvent is used here*/
+    bl_irqs_init(&wifi_hw);
+}
+
+
+int bl_main_tx_still_free(void)
+{
+    return ipc_host_txdesc_left(wifi_hw.ipc_env, 0, 0);
+}
+
+int bl_main_rtthread_start(struct bl_hw **bl_hw)
+{
+    int ret;
+
+    /*start the bl606 wifi service*/
+    bl_main_lowlevel_init();
+
+    /*startup wifi firmware*/
+    *bl_hw = &wifi_hw;
+    ret = cfg80211_init(&wifi_hw);
+    //TODO check ret from cfg80211_init
+    ret = bl_open(*bl_hw);
+    return ret;
+}

+ 197 - 0
network/wifi_manager/bl60x_wifi_driver/bl_main.h

@@ -0,0 +1,197 @@
+/**
+ ****************************************************************************************
+ *
+ * @file bl_main.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+#ifndef __RWNX_MAIN_H__
+#define __RWNX_MAIN_H__
+#include <stdint.h>
+#include <lwip/netif.h>
+#include "lmac_mac.h"
+#include <wifi_mgmr_ext.h>
+
+struct wifi_apm_sta_info
+{
+    uint8_t  sta_idx;
+    uint8_t  is_used;
+    uint8_t  sta_mac[6];
+    uint32_t tsfhi;
+    uint32_t tsflo;
+    int      rssi;
+    uint8_t  data_rate;
+};
+
+int bl_main_powersaving(int mode);
+int bl_main_denoise(int mode);
+int bl_main_disconnect(void);
+int bl_main_phy_up(void);
+int bl_main_channel_set(int channel);
+int bl_main_monitor_channel_set(int channel, int use_40MHZ);
+int bl_main_rate_config(uint8_t sta_idx, uint16_t fixed_rate_cfg);
+int bl_main_if_remove(uint8_t vif_index);
+int bl_main_if_add(int is_sta, struct netif *netif, uint8_t *vif_index);
+int bl_main_monitor(void);
+int bl_main_monitor_disable(void);
+int bl_main_connect(const uint8_t* ssid, int ssid_len, const uint8_t *psk, int psk_len, const uint8_t *pmk, int pmk_len, const uint8_t *mac, const uint8_t band, const uint16_t freq, const uint32_t flags);
+int bl_main_connect_abort(uint8_t *status);
+int bl_main_apm_start(char *ssid, char *password, int channel, uint8_t vif_index, uint8_t hidden_ssid, uint16_t bcn_int);
+int bl_main_apm_stop(uint8_t vif_index);
+int bl_main_apm_sta_cnt_get(uint8_t *sta_cnt);
+int bl_main_apm_sta_info_get(struct wifi_apm_sta_info *apm_sta_info, uint8_t idx);
+int bl_main_apm_sta_delete(uint8_t sta_idx);
+int bl_main_apm_remove_all_sta();
+int bl_main_conf_max_sta(uint8_t max_sta_supported);
+int bl_main_cfg_task_req(uint32_t ops, uint32_t task, uint32_t element, uint32_t type, void *arg1, void *arg2);
+int bl_main_scan(struct netif *netif, uint16_t *fixed_channels, uint16_t channel_num, struct mac_addr *bssid, struct mac_ssid *ssid, uint8_t scan_mode, uint32_t duration_scan);
+int bl_main_raw_send(uint8_t *pkt , int len);
+int bl_main_set_country_code(char *country_code);
+int bl_main_get_channel_nums();
+int bl_main_beacon_interval_set(uint16_t beacon_int);
+
+struct wifi_event_sm_connect_ind
+{
+    uint16_t status_code;
+    uint16_t reason_code;
+    /// BSSID
+    uint8_t bssid[6];
+    /// Index of the VIF for which the association process is complete
+    uint8_t vif_idx;
+    /// Index of the STA entry allocated for the AP
+    uint8_t ap_idx;
+    /// Index of the LMAC channel context the connection is attached to
+    uint8_t ch_idx;
+    /// Flag indicating if the AP is supporting QoS
+    int qos;
+    uint16_t aid;
+    uint8_t band;
+    uint16_t center_freq;
+    uint8_t width;
+    uint32_t center_freq1;
+    uint32_t center_freq2;
+    /// Pointer to the structure used for the diagnose module
+    struct sm_tlv_list connect_diagnose;
+};
+
+struct wifi_event_sm_disconnect_ind
+{
+    /// Status code of the disconnection procedure
+    uint16_t status_code;
+    /// Reason of the disconnection.
+    uint16_t reason_code;
+    /// Index of the VIF.
+    uint8_t vif_idx;
+    /// FT over DS is ongoing
+    int ft_over_ds;
+    /// Pointer to the structure used for the diagnose module
+    struct sm_tlv_list connect_diagnose;
+};
+
+typedef struct
+{
+    uint8_t  noRsn      : 1;
+    uint8_t  wepStatic  : 1;
+    uint8_t  wepDynamic : 1;
+    uint8_t  wpa        : 1;
+    uint8_t  wpaNone    : 1;
+    uint8_t  wpa2       : 1;
+    uint8_t  cckm       : 1;
+    uint8_t  wapi       : 1;
+    uint8_t  rsvd       : 8;
+} wifi_secmode_t;
+
+typedef struct
+{
+    uint8_t   wep40      : 1;
+    uint8_t   wep104     : 1;
+    uint8_t   tkip       : 1;
+    uint8_t   ccmp       : 1;
+    uint8_t   rsvd       : 4;
+} wifi_cipher_t;
+
+#define WIFI_EVENT_BEACON_IND_AUTH_OPEN            0
+#define WIFI_EVENT_BEACON_IND_AUTH_WEP             1
+#define WIFI_EVENT_BEACON_IND_AUTH_WPA_PSK         2
+#define WIFI_EVENT_BEACON_IND_AUTH_WPA2_PSK        3
+#define WIFI_EVENT_BEACON_IND_AUTH_WPA_WPA2_PSK    4
+#define WIFI_EVENT_BEACON_IND_AUTH_WPA_ENT         5
+#define WIFI_EVENT_BEACON_IND_AUTH_WPA3_SAE        6
+#define WIFI_EVENT_BEACON_IND_AUTH_WPA2_PSK_WPA3_SAE 7
+#define WIFI_EVENT_BEACON_IND_AUTH_UNKNOWN      0xff
+
+#define WIFI_EVENT_BEACON_IND_CIPHER_NONE           0
+#define WIFI_EVENT_BEACON_IND_CIPHER_WEP            1
+#define WIFI_EVENT_BEACON_IND_CIPHER_AES            2
+#define WIFI_EVENT_BEACON_IND_CIPHER_TKIP           3
+#define WIFI_EVENT_BEACON_IND_CIPHER_TKIP_AES       4
+
+struct wifi_event_beacon_ind
+{
+    int mode;
+    uint8_t bssid[6];
+    uint8_t ssid[33];
+    int8_t rssi;
+    int8_t ppm_abs;
+    int8_t ppm_rel;
+    uint8_t channel;
+    uint8_t auth;//0: open; 1:wep; 2:WPA/WPA2 - PSK; 3: WPA/WPA2 - Enterprise; 0xFF: unknown
+    uint8_t cipher;
+    wifi_cipher_t wpa_mcstCipher;
+    wifi_cipher_t wpa_ucstCipher;
+    wifi_cipher_t rsn_mcstCipher;
+    wifi_cipher_t rsn_ucstCipher;
+    wifi_secmode_t sec_mode;
+    int ssid_len;
+    uint8_t wps;
+    uint8_t group_cipher;
+};
+
+#pragma  pack(push,1)
+struct wifi_event_data_ind_channel_switch
+{
+    int channel;
+};
+
+struct wifi_event_data_ind_scan_done
+{
+    uint32_t nothing;
+};
+
+struct wifi_event
+{
+#define WIFI_EVENT_ID_IND_CHANNEL_SWITCH        0
+#define WIFI_EVENT_ID_IND_SCAN_DONE             1
+#define WIFI_EVENT_ID_IND_SCAN_DONE_ONJOIN      2
+    uint32_t id;
+    uint8_t data[0];
+};
+#pragma  pack(pop)
+
+//TODO: add general EVENT Framework
+typedef void (*wifi_event_sm_connect_ind_cb_t)(void *env, struct wifi_event_sm_connect_ind *ind);
+typedef void (*wifi_event_sm_disconnect_ind_cb_t)(void *env, struct wifi_event_sm_disconnect_ind *ind);
+typedef void (*wifi_event_beacon_ind_cb_t)(void *env, struct wifi_event_beacon_ind *ind);
+typedef void (*wifi_event_probe_resp_ind_cb_t)(void *env, long long timestamp);
+typedef void (*wifi_event_pkt_cb_t)(void *env, uint8_t *ieee80211_pkt, int len, bl_rx_info_t *info);
+typedef void (*wifi_event_pkt_cb_adv_t)(void *env, void *pkt_wrap, bl_rx_info_t *info);
+typedef void (*wifi_event_rssi_cb_t)(void *env, int8_t rssi);
+typedef void (*wifi_event_cb_t)(void *env, struct wifi_event *event);
+int bl_rx_sm_connect_ind_cb_register(void *env, wifi_event_sm_connect_ind_cb_t cb);
+int bl_rx_sm_connect_ind_cb_unregister(void *env, wifi_event_sm_connect_ind_cb_t cb);
+int bl_rx_sm_disconnect_ind_cb_register(void *env, wifi_event_sm_disconnect_ind_cb_t cb);
+int bl_rx_sm_disconnect_ind_cb_unregister(void *env, wifi_event_sm_disconnect_ind_cb_t cb);
+int bl_rx_beacon_ind_cb_register(void *env, wifi_event_beacon_ind_cb_t cb);
+int bl_rx_probe_resp_ind_cb_register(void *env, wifi_event_probe_resp_ind_cb_t cb);
+int bl_rx_beacon_ind_cb_unregister(void *env, wifi_event_beacon_ind_cb_t cb);
+int bl_rx_pkt_cb_register(void *env, wifi_event_pkt_cb_t cb);
+int bl_rx_pkt_cb_unregister(void *env);
+int bl_rx_pkt_adv_cb_register(void *env, wifi_event_pkt_cb_adv_t cb);
+int bl_rx_pkt_adv_cb_unregister(void *env);
+int bl_rx_rssi_cb_register(void *env, wifi_event_rssi_cb_t cb);
+int bl_rx_rssi_cb_unregister(void *env, wifi_event_rssi_cb_t cb);
+int bl_rx_event_register(void *env, wifi_event_cb_t cb);
+int bl_rx_event_unregister(void *env);
+int bl_main_tx_still_free(void);
+#endif

+ 62 - 0
network/wifi_manager/bl60x_wifi_driver/bl_mod_params.c

@@ -0,0 +1,62 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_mod_params.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#include "bl_defs.h"
+
+#define COMMON_PARAM(name, default_softmac, default_fullmac)    \
+    .name = default_fullmac,
+#define SOFTMAC_PARAM(name, default)
+#define FULLMAC_PARAM(name, default) .name = default,
+
+struct bl_mod_params bl_mod_params = {
+    /* common parameters */
+    COMMON_PARAM(ht_on, true, true)
+    COMMON_PARAM(vht_on, false, false)
+    COMMON_PARAM(mcs_map, IEEE80211_VHT_MCS_SUPPORT_0_7, IEEE80211_VHT_MCS_SUPPORT_0_7)
+    COMMON_PARAM(phy_cfg, 2, 2)
+    COMMON_PARAM(uapsd_timeout, 3000, 3000)
+    COMMON_PARAM(sgi, false, false)
+    COMMON_PARAM(sgi80, false, false)
+    COMMON_PARAM(listen_itv, 1, 1)
+    COMMON_PARAM(listen_bcmc, true, true)
+    COMMON_PARAM(lp_clk_ppm, 20, 20)
+    COMMON_PARAM(ps_on, false, false)
+    COMMON_PARAM(tx_lft, RWNX_TX_LIFETIME_MS, RWNX_TX_LIFETIME_MS)
+    COMMON_PARAM(amsdu_maxnb, NX_TX_PAYLOAD_MAX, NX_TX_PAYLOAD_MAX)
+    // By default, only enable UAPSD for Voice queue (see IEEE80211_DEFAULT_UAPSD_QUEUE comment)
+    COMMON_PARAM(uapsd_queues, 0, 0)
+};
+
+int bl_handle_dynparams(struct bl_hw *bl_hw)
+{
+    const int nss = 1;
+
+    if (bl_hw->mod_params->phy_cfg < 0 || bl_hw->mod_params->phy_cfg > 5)
+        bl_hw->mod_params->phy_cfg = 2;
+
+    if (bl_hw->mod_params->mcs_map < 0 || bl_hw->mod_params->mcs_map > 2)
+        bl_hw->mod_params->mcs_map = 0;
+
+    /* HT capabilities */
+    bl_hw->ht_cap.cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
+    bl_hw->ht_cap.mcs.rx_highest = cpu_to_le16(65 * nss);
+    //Fixed leo disable MCS5/6/7
+    bl_hw->ht_cap.mcs.rx_mask[0] = 0xFF;
+
+    if (bl_hw->mod_params->sgi) {
+        bl_hw->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+        bl_hw->ht_cap.mcs.rx_highest = cpu_to_le16(72 * nss);
+    }
+    bl_hw->ht_cap.cap |= IEEE80211_HT_CAP_SM_PS;
+    if (!bl_hw->mod_params->ht_on)
+        bl_hw->ht_cap.ht_supported = false;
+
+    return 0;
+}

+ 43 - 0
network/wifi_manager/bl60x_wifi_driver/bl_mod_params.h

@@ -0,0 +1,43 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_mod_params.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+
+#ifndef _RWNX_MOD_PARAM_H_
+#define _RWNX_MOD_PARAM_H_
+#include "lmac_types.h"
+#include "bl_defs.h"
+#include "cfg80211.h"
+
+struct bl_mod_params {
+    bool ht_on;
+    bool vht_on;
+    int mcs_map;
+    int phy_cfg;
+    int uapsd_timeout;
+    bool sgi;
+    bool sgi80;
+    bool use_2040;
+    int listen_itv;
+    bool listen_bcmc;
+    int lp_clk_ppm;
+    bool ps_on;
+    int tx_lft;
+    int amsdu_maxnb;
+    int uapsd_queues;
+};
+
+extern struct bl_mod_params bl_mod_params;
+
+struct bl_hw;
+void bl_enable_wapi(struct bl_hw *bl_hw);
+void bl_enable_mfp(struct bl_hw *bl_hw);
+int bl_handle_dynparams(struct bl_hw *bl_hw);
+
+#endif /* _RWNX_MOD_PARAM_H_ */

+ 1 - 0
network/wifi_manager/bl60x_wifi_driver/bl_msg_rx.c

@@ -0,0 +1 @@
+

+ 0 - 0
network/wifi_manager/bl60x_wifi_driver/bl_msg_rx.h


+ 1144 - 0
network/wifi_manager/bl60x_wifi_driver/bl_msg_tx.c

@@ -0,0 +1,1144 @@
+#include <string.h>
+#include <bl_os_private.h>
+#include <utils_tlv_bl.h>
+#include <bl60x_fw_api.h>
+
+// #include "errno.h"
+#include "bl_msg_tx.h"
+#include "bl_utils.h"
+
+// field definitions
+#define NXMAC_EN_DUPLICATE_DETECTION_BIT         ((uint32_t)0x80000000)
+#define NXMAC_EN_DUPLICATE_DETECTION_POS         31
+#define NXMAC_ACCEPT_UNKNOWN_BIT                 ((uint32_t)0x40000000)
+#define NXMAC_ACCEPT_UNKNOWN_POS                 30
+#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT       ((uint32_t)0x20000000)
+#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_POS       29
+#define NXMAC_ACCEPT_QO_S_NULL_BIT               ((uint32_t)0x10000000)
+#define NXMAC_ACCEPT_QO_S_NULL_POS               28
+#define NXMAC_ACCEPT_QCFWO_DATA_BIT              ((uint32_t)0x08000000)
+#define NXMAC_ACCEPT_QCFWO_DATA_POS              27
+#define NXMAC_ACCEPT_Q_DATA_BIT                  ((uint32_t)0x04000000)
+#define NXMAC_ACCEPT_Q_DATA_POS                  26
+#define NXMAC_ACCEPT_CFWO_DATA_BIT               ((uint32_t)0x02000000)
+#define NXMAC_ACCEPT_CFWO_DATA_POS               25
+#define NXMAC_ACCEPT_DATA_BIT                    ((uint32_t)0x01000000)
+#define NXMAC_ACCEPT_DATA_POS                    24
+#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT      ((uint32_t)0x00800000)
+#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_POS      23
+#define NXMAC_ACCEPT_CF_END_BIT                  ((uint32_t)0x00400000)
+#define NXMAC_ACCEPT_CF_END_POS                  22
+#define NXMAC_ACCEPT_ACK_BIT                     ((uint32_t)0x00200000)
+#define NXMAC_ACCEPT_ACK_POS                     21
+#define NXMAC_ACCEPT_CTS_BIT                     ((uint32_t)0x00100000)
+#define NXMAC_ACCEPT_CTS_POS                     20
+#define NXMAC_ACCEPT_RTS_BIT                     ((uint32_t)0x00080000)
+#define NXMAC_ACCEPT_RTS_POS                     19
+#define NXMAC_ACCEPT_PS_POLL_BIT                 ((uint32_t)0x00040000)
+#define NXMAC_ACCEPT_PS_POLL_POS                 18
+#define NXMAC_ACCEPT_BA_BIT                      ((uint32_t)0x00020000)
+#define NXMAC_ACCEPT_BA_POS                      17
+#define NXMAC_ACCEPT_BAR_BIT                     ((uint32_t)0x00010000)
+#define NXMAC_ACCEPT_BAR_POS                     16
+#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT       ((uint32_t)0x00008000)
+#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_POS       15
+#define NXMAC_ACCEPT_ALL_BEACON_BIT              ((uint32_t)0x00002000)
+#define NXMAC_ACCEPT_ALL_BEACON_POS              13
+#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT         ((uint32_t)0x00001000)
+#define NXMAC_ACCEPT_NOT_EXPECTED_BA_POS         12
+#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT    ((uint32_t)0x00000800)
+#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_POS    11
+#define NXMAC_ACCEPT_BEACON_BIT                  ((uint32_t)0x00000400)
+#define NXMAC_ACCEPT_BEACON_POS                  10
+#define NXMAC_ACCEPT_PROBE_RESP_BIT              ((uint32_t)0x00000200)
+#define NXMAC_ACCEPT_PROBE_RESP_POS              9
+#define NXMAC_ACCEPT_PROBE_REQ_BIT               ((uint32_t)0x00000100)
+#define NXMAC_ACCEPT_PROBE_REQ_POS               8
+#define NXMAC_ACCEPT_MY_UNICAST_BIT              ((uint32_t)0x00000080)
+#define NXMAC_ACCEPT_MY_UNICAST_POS              7
+#define NXMAC_ACCEPT_UNICAST_BIT                 ((uint32_t)0x00000040)
+#define NXMAC_ACCEPT_UNICAST_POS                 6
+#define NXMAC_ACCEPT_ERROR_FRAMES_BIT            ((uint32_t)0x00000020)
+#define NXMAC_ACCEPT_ERROR_FRAMES_POS            5
+#define NXMAC_ACCEPT_OTHER_BSSID_BIT             ((uint32_t)0x00000010)
+#define NXMAC_ACCEPT_OTHER_BSSID_POS             4
+#define NXMAC_ACCEPT_BROADCAST_BIT               ((uint32_t)0x00000008)
+#define NXMAC_ACCEPT_BROADCAST_POS               3
+#define NXMAC_ACCEPT_MULTICAST_BIT               ((uint32_t)0x00000004)
+#define NXMAC_ACCEPT_MULTICAST_POS               2
+#define NXMAC_DONT_DECRYPT_BIT                   ((uint32_t)0x00000002)
+#define NXMAC_DONT_DECRYPT_POS                   1
+#define NXMAC_EXC_UNENCRYPTED_BIT                ((uint32_t)0x00000001)
+#define NXMAC_EXC_UNENCRYPTED_POS                0
+
+static const struct mac_addr mac_addr_bcst = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+static const struct mac_addr mac_addr_zero = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+static const struct ieee80211_channel bl_channels_24_General[] = {
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, .max_power=20},
+    { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, .max_power=20},
+};
+
+static const struct ieee80211_dot_d country_list[] = 
+{
+    /*First Country is the default country*/
+    {
+        .code   = "CN",
+        .channel_num = 13,
+        .channels = bl_channels_24_General,
+    },
+    {
+        .code   = "JP",
+        .channel_num = 14,
+        .channels = bl_channels_24_General,
+    },
+    {
+        .code   = "US",
+        .channel_num = 11,
+        .channels = bl_channels_24_General,
+    },
+    {
+        .code   = "EU",
+        .channel_num = 13,
+        .channels = bl_channels_24_General,
+    },
+};
+
+static int channel_num_default;
+static const struct ieee80211_channel *channels_default;
+static const struct ieee80211_dot_d *country_default;
+
+static int cfg80211_get_channel_list(const char *code, int *channel_num, const struct ieee80211_channel **channels, const struct ieee80211_dot_d **country_default)
+{
+    int i;
+
+    for (i = 0; i < sizeof(country_list)/sizeof(country_list[0]); i++) {
+        if (0 == strcmp(country_list[i].code, code)) {
+            if(channel_num){
+                *channel_num = country_list[i].channel_num;
+            }
+            if (channels) {
+                *channels = country_list[i].channels;
+            }
+            if (country_default) {
+                *country_default = &country_list[i];
+            }
+            return 0;
+        }
+    }
+    /*NOT found code*/
+    return -1;
+}
+
+void bl_msg_update_channel_cfg(const char *code)
+{
+    if (cfg80211_get_channel_list(code, &channel_num_default, &channels_default, &country_default)) {
+        /*get channel list failed, so we set the default one*/
+        channel_num_default = sizeof(bl_channels_24_General)/sizeof(bl_channels_24_General[0]);
+        channels_default = bl_channels_24_General;
+        country_default = &country_list[0];
+        bl_os_printf("[WF] %s NOT found, using General instead, num of channel %d\r\n", code, channel_num_default);
+    } else {
+        bl_os_printf("[WF] country code %s used, num of channel %d\r\n", code, channel_num_default);
+    }
+
+}
+
+int bl_msg_get_channel_nums()
+{
+    return channel_num_default;
+}
+
+int bl_get_fixed_channels_is_valid(uint16_t *channels, uint16_t channel_num)
+{
+    int i;
+    int channel;
+
+    if (0 == channel_num) {
+        return 0;
+    }
+
+    for (i = 0; i < channel_num; i++) {
+        channel = channels[i];
+        if (0 == channel || (channel > bl_msg_get_channel_nums())) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+inline uint16_t phy_channel_to_freq(uint8_t band, int channel)
+{
+    uint16_t freq = 0xFFFF;
+
+    do
+    {
+        //2.4.GHz
+        if (band == PHY_BAND_2G4)
+        {
+            // Check if the channel number is in the expected range
+            if ((channel < 1) || (channel > 14))
+                break;
+
+            // Compute the channel number
+            if (channel == 14)
+                freq = 2484;
+            else
+                freq = 2407 + channel * 5;
+        }
+        //5 GHz
+        else if (band == PHY_BAND_5G)
+        {
+            // Check if frequency is in the expected range
+            if ((channel < 1) || (channel > 165))
+                break;
+
+            // Compute the channel number
+            freq = 5000 + channel * 5;
+        }
+    } while(0);
+
+    return (freq);
+}
+
+inline uint8_t phy_freq_to_channel(uint8_t band, uint16_t freq)
+{
+    uint8_t channel = 0;
+
+    do
+    {
+        //2.4.GHz
+        if (band == PHY_BAND_2G4)
+        {
+            // Check if the frequency is in the expected range
+            if ((freq < 2412) || (freq > 2484))
+                break;
+
+            if (freq == 2484)
+                channel = 14;
+            else
+                channel = (freq - 2407) / 5;
+        }
+#if 0
+        //5 GHz
+        else if (band == PHY_BAND_5G)
+        {
+            // Check if frequency is in the expected range (34-165)
+            if ((freq < 5170) || (freq > 5825))
+                break;
+
+            channel = (freq - 5000) / 5;
+        }
+#endif
+    } while (0);
+
+    return (channel);
+}
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_msg_tx.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+static inline void *bl_msg_zalloc(ke_msg_id_t const id,
+                                    ke_task_id_t const dest_id,
+                                    ke_task_id_t const src_id,
+                                    uint16_t const param_len)
+{
+    struct lmac_msg *msg;
+
+    msg = (struct lmac_msg *)bl_os_malloc(sizeof(struct lmac_msg) + param_len);
+    if (msg == NULL) {
+        bl_os_printf("%s: msg allocation failed\n", __func__);
+        return NULL;
+    }
+    memset(msg, 0, sizeof(struct lmac_msg) + param_len);
+
+    msg->id = id;
+    msg->dest_id = dest_id;
+    msg->src_id = src_id;
+    msg->param_len = param_len;
+
+    return msg->param;
+}
+
+static inline bool is_non_blocking_msg(int id) {
+    return ((id == MM_TIM_UPDATE_REQ) || (id == ME_RC_SET_RATE_REQ) ||
+            (id == MM_BFMER_ENABLE_REQ) || (id == ME_TRAFFIC_IND_REQ));
+}
+
+#define BITS_PER_LONG 32
+#define BIT_WORD(nr)        ((nr) / BITS_PER_LONG)
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+    return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
+static int bl_send_msg(struct bl_hw *bl_hw, const void *msg_params,
+                         int reqcfm, ke_msg_id_t reqid, void *cfm)
+{
+    struct lmac_msg *msg;
+    struct bl_cmd *cmd;
+    bool nonblock;
+    int ret;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    msg = container_of((void *)msg_params, struct lmac_msg, param);
+
+    if (!bl_hw->ipc_env) {
+        bl_os_printf("%s: bypassing (restart must have failed)\r\n", __func__);
+        bl_os_free(msg);
+        RWNX_DBG(RWNX_FN_LEAVE_STR);
+        return -EBUSY;
+    }
+
+    nonblock = is_non_blocking_msg(msg->id);
+
+    cmd = bl_os_malloc(sizeof(struct bl_cmd));
+    if (NULL == cmd) {
+        bl_os_free(msg);
+        bl_os_printf("%s: failed to allocate mem for cmd, size is %d\r\n", __func__, sizeof(struct bl_cmd));
+        return -ENOMEM;
+    }
+    memset(cmd, 0, sizeof(struct bl_cmd));
+    cmd->result  = EINTR;
+    cmd->id      = msg->id;
+    cmd->reqid   = reqid;
+    cmd->a2e_msg = msg;
+    cmd->e2a_msg = cfm;
+    if (nonblock)
+        cmd->flags = RWNX_CMD_FLAG_NONBLOCK;
+    if (reqcfm)
+        cmd->flags |= RWNX_CMD_FLAG_REQ_CFM;
+    ret = bl_hw->cmd_mgr.queue(&bl_hw->cmd_mgr, cmd);
+
+    if (!nonblock) {
+        bl_os_free(cmd);
+    } else {
+        ret = cmd->result;
+    }
+
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return ret;
+}
+
+int bl_send_reset(struct bl_hw *bl_hw)
+{
+    void *void_param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* RESET REQ has no parameter */
+    void_param = bl_msg_zalloc(MM_RESET_REQ, TASK_MM, DRV_TASK_ID, 0);
+    if (!void_param)
+        return -ENOMEM;
+
+    return bl_send_msg(bl_hw, void_param, 1, MM_RESET_CFM, NULL);
+}
+
+int bl_send_monitor_enable(struct bl_hw *bl_hw, struct mm_monitor_cfm *cfm)
+{
+    struct mm_monitor_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    req = bl_msg_zalloc(MM_MONITOR_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_monitor_req));
+    if (!req)
+        return -ENOMEM;
+
+    req->enable = 1;
+
+    return bl_send_msg(bl_hw, req, 1, MM_MONITOR_CFM, cfm);
+}
+
+int bl_send_monitor_disable(struct bl_hw *bl_hw, struct mm_monitor_cfm *cfm)
+{
+    struct mm_monitor_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    req = bl_msg_zalloc(MM_MONITOR_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_monitor_req));
+    if (!req)
+        return -ENOMEM;
+
+    req->enable = 0;
+
+    return bl_send_msg(bl_hw, req, 1, MM_MONITOR_CFM, cfm);
+}
+
+int bl_send_beacon_interval_set(struct bl_hw *bl_hw, struct mm_set_beacon_int_cfm *cfm, uint16_t beacon_int)
+{
+    struct mm_set_beacon_int_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    req = bl_msg_zalloc(MM_SET_BEACON_INT_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_beacon_int_req));
+    if (!req)
+        return -ENOMEM;
+
+    req->beacon_int = beacon_int;
+
+    return bl_send_msg(bl_hw, req, 1, MM_SET_BEACON_INT_CFM, cfm);
+}
+
+//TODO we only support 2.4GHz
+int bl_send_monitor_channel_set(struct bl_hw *bl_hw, struct mm_monitor_channel_cfm *cfm, int channel, int use_40Mhz)
+{
+    struct mm_monitor_channel_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    req = bl_msg_zalloc(MM_MONITOR_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_monitor_channel_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    req->freq = phy_channel_to_freq(PHY_BAND_2G4, channel);
+
+    return bl_send_msg(bl_hw, req, 1, MM_MONITOR_CHANNEL_CFM, cfm);
+}
+
+int bl_send_version_req(struct bl_hw *bl_hw, struct mm_version_cfm *cfm)
+{
+    int ret;
+    void *void_param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* VERSION REQ has no parameter */
+    void_param = bl_msg_zalloc(MM_VERSION_REQ, TASK_MM, DRV_TASK_ID, 0);
+    if (!void_param) {
+        RWNX_DBG(RWNX_FN_LEAVE_STR);
+        return -ENOMEM;
+    }
+    ret = bl_send_msg(bl_hw, void_param, 1, MM_VERSION_CFM, cfm);
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return ret;
+}
+
+int bl_send_me_config_req(struct bl_hw *bl_hw)
+{
+    struct me_config_req *req;
+    uint8_t *ht_mcs = (uint8_t *)&(bl_hw->ht_cap.mcs);
+    int i, ret;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the ME_CONFIG_REQ message */
+    req = bl_msg_zalloc(ME_CONFIG_REQ, TASK_ME, DRV_TASK_ID,
+                                   sizeof(struct me_config_req));
+    if (!req) {
+        RWNX_DBG(RWNX_FN_LEAVE_STR);
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the ME_CONFIG_REQ message */
+    bl_os_printf("[ME] HT supp %d, VHT supp %d\r\n", 1, 0);
+
+    req->ht_supp = 1;
+    req->vht_supp = 0;
+    req->ht_cap.ht_capa_info = cpu_to_le16(bl_hw->ht_cap.cap);
+
+    /*AMPDU MAX Length:  
+     * 0x0:8K
+     * 0x1:16K
+     * 0x2:32K
+     * 0x3:64K
+     */
+    req->ht_cap.a_mpdu_param = 0x3;
+
+    for (i = 0; i < sizeof(bl_hw->ht_cap.mcs); i++) {
+        req->ht_cap.mcs_rate[i] = ht_mcs[i];
+    }
+    req->ht_cap.ht_extended_capa = 0;
+    req->ht_cap.tx_beamforming_capa = 0;
+    req->ht_cap.asel_capa = 0;
+
+    //TODO talk with firmware guys
+#if 0
+    req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap);
+    req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest);
+    req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map);
+    req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest);
+    req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map);
+#endif
+
+    req->ps_on = bl_hw->mod_params->ps_on;
+    req->tx_lft = bl_hw->mod_params->tx_lft;
+
+    /* Send the ME_CONFIG_REQ message to LMAC FW */
+    ret = bl_send_msg(bl_hw, req, 1, ME_CONFIG_CFM, NULL);
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return ret;
+}
+
+static uint8_t passive_scan_flag(uint32_t flags) {
+    if (flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
+        return SCAN_PASSIVE_BIT;
+    return 0;
+}
+
+int bl_send_me_chan_config_req(struct bl_hw *bl_hw)
+{
+    struct me_chan_config_req *req;
+    int i;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the ME_CHAN_CONFIG_REQ message */
+    req = bl_msg_zalloc(ME_CHAN_CONFIG_REQ, TASK_ME, DRV_TASK_ID,
+                                            sizeof(struct me_chan_config_req));
+    if (!req)
+        return -ENOMEM;
+
+    req->chan2G4_cnt = 0;
+    for (i = 0; i < channel_num_default; i++) {
+        req->chan2G4[req->chan2G4_cnt].flags = 0;
+        if (channels_default[i].flags & IEEE80211_CHAN_DISABLED)
+            req->chan2G4[req->chan2G4_cnt].flags |= SCAN_DISABLED_BIT;
+        req->chan2G4[req->chan2G4_cnt].flags |= passive_scan_flag(channels_default[i].flags);
+        req->chan2G4[req->chan2G4_cnt].band = NL80211_BAND_2GHZ;
+        req->chan2G4[req->chan2G4_cnt].freq = channels_default[i].center_freq;
+        req->chan2G4[req->chan2G4_cnt].tx_power = channels_default[i].max_power;
+        req->chan2G4_cnt++;
+        if (req->chan2G4_cnt == SCAN_CHANNEL_2G4)
+            break;
+    }
+
+    /* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, ME_CHAN_CONFIG_CFM, NULL);
+}
+
+int bl_send_me_rate_config_req(struct bl_hw *bl_hw, uint8_t sta_idx, uint16_t fixed_rate_cfg)
+{
+    struct me_rc_set_rate_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the ME_RC_SET_RATE_REQ message */
+    req = bl_msg_zalloc(ME_RC_SET_RATE_REQ, TASK_ME, DRV_TASK_ID, sizeof(struct me_rc_set_rate_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+    req->sta_idx = sta_idx;
+    req->fixed_rate_cfg = fixed_rate_cfg;
+    req->power_table_req = 1;
+
+    return bl_send_msg(bl_hw, req, 0, 0, NULL);
+}
+
+int bl_send_start(struct bl_hw *bl_hw)
+{
+    struct mm_start_req *start_req_param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the START REQ message */
+    start_req_param = bl_msg_zalloc(MM_START_REQ, TASK_MM, DRV_TASK_ID,
+                                      sizeof(struct mm_start_req));
+    if (!start_req_param)
+        return -ENOMEM;
+
+    memset(&start_req_param->phy_cfg, 0, sizeof(start_req_param->phy_cfg));
+    //XXX magic number
+    start_req_param->phy_cfg.parameters[0] = 0x1;
+    start_req_param->uapsd_timeout = (u32_l)bl_hw->mod_params->uapsd_timeout;
+    start_req_param->lp_clk_accuracy = (u16_l)bl_hw->mod_params->lp_clk_ppm;
+
+    /* Send the START REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, start_req_param, 1, MM_START_CFM, NULL);
+}
+
+int bl_send_add_if(struct bl_hw *bl_hw, const unsigned char *mac,
+                     enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm)
+{
+    struct mm_add_if_req *add_if_req_param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the ADD_IF_REQ message */
+    add_if_req_param = bl_msg_zalloc(MM_ADD_IF_REQ, TASK_MM, DRV_TASK_ID,
+                                       sizeof(struct mm_add_if_req));
+    if (!add_if_req_param)
+        return -ENOMEM;
+
+    /* Set parameters for the ADD_IF_REQ message */
+    memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN);
+    switch (iftype) {
+    case NL80211_IFTYPE_P2P_CLIENT:
+        add_if_req_param->p2p = true;
+        __attribute__((fallthrough));
+        // no break
+    case NL80211_IFTYPE_STATION:
+        add_if_req_param->type = MM_STA;
+        break;
+
+    case NL80211_IFTYPE_ADHOC:
+        add_if_req_param->type = MM_IBSS;
+        break;
+
+    case NL80211_IFTYPE_P2P_GO:
+        add_if_req_param->p2p = true;
+        __attribute__((fallthrough));
+        // no break
+    case NL80211_IFTYPE_AP:
+        add_if_req_param->type = MM_AP;
+        break;
+    case NL80211_IFTYPE_MESH_POINT:
+        add_if_req_param->type = MM_MESH_POINT;
+        break;
+    case NL80211_IFTYPE_AP_VLAN:
+        return -1;
+    default:
+        add_if_req_param->type = MM_STA;
+        break;
+    }
+
+    /* Send the ADD_IF_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, add_if_req_param, 1, MM_ADD_IF_CFM, cfm);
+}
+
+int bl_send_remove_if(struct bl_hw *bl_hw, uint8_t inst_nbr)
+{
+    struct mm_remove_if_req *remove_if_req_param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    remove_if_req_param = bl_msg_zalloc(MM_REMOVE_IF_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_remove_if_req));
+    if (!remove_if_req_param) {
+        return -ENOMEM;
+    }
+    remove_if_req_param->inst_nbr = inst_nbr;
+
+    return bl_send_msg(bl_hw, remove_if_req_param, 1, MM_REMOVE_IF_CFM, NULL);
+}
+
+int bl_send_scanu_req(struct bl_hw *bl_hw, struct bl_send_scanu_para *scanu_para)
+{
+    struct scanu_start_req *req;
+    int i, index;
+    uint8_t chan_flags = 0;
+    const struct ieee80211_channel *chan;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the SCANU_START_REQ message */
+    req = bl_msg_zalloc(SCANU_START_REQ, TASK_SCANU, DRV_TASK_ID,
+                          sizeof(struct scanu_start_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters */
+    // Always use idx 0, because vif_idx in vif_entry could be 0, leading to probe_rep tx fail
+    req->vif_idx = 0;
+    if (0 == scanu_para->channel_num) {
+        req->chan_cnt = channel_num_default;
+    } else {
+        req->chan_cnt = scanu_para->channel_num;
+    }
+
+    req->ssid_cnt = 1;
+    if (scanu_para->ssid != NULL && scanu_para->ssid->length) {
+        req->ssid[0].length = scanu_para->ssid->length;
+        memcpy(req->ssid[0].array, scanu_para->ssid->array, req->ssid[0].length);
+    } else {
+        req->ssid[0].length = 0;
+        //if specfied ssid, ignore user setting passive mode
+        if (req->ssid_cnt == 0 || scanu_para->scan_mode == SCAN_PASSIVE) 
+        {
+            chan_flags |= SCAN_PASSIVE_BIT;
+        }
+    }
+    memcpy((uint8_t *)&(req->bssid), (uint8_t *)scanu_para->bssid, ETH_ALEN);
+    memcpy(&(req->mac), scanu_para->mac, ETH_ALEN);
+    req->no_cck = true;//FIXME params? talk with firmware guys
+
+#if 0
+    for (i = 0; i < req->ssid_cnt; i++) {
+        int j;
+        for (j = 0; j < param->ssids[i].ssid_len; j++)
+            req->ssid[i].array[j] = param->ssids[i].ssid[j];
+        req->ssid[i].length = param->ssids[i].ssid_len;
+    }
+#endif
+
+    //XXX custom ie can be added
+    req->add_ie_len = 0;
+    req->add_ies = 0;
+
+    for (i = 0; i < req->chan_cnt; i++) {
+        index = (channel_num_default == req->chan_cnt) ? i : (scanu_para->channels[i] - 1);
+        chan = &(channels_default[index]);
+
+        req->chan[i].band = chan->band;
+        req->chan[i].freq = chan->center_freq;
+        req->chan[i].flags = chan_flags | passive_scan_flag(chan->flags);
+        req->chan[i].tx_power = chan->max_reg_power;
+    }
+
+    req->duration_scan = scanu_para->duration_scan;
+
+    /* Send the SCANU_START_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 0, 0, NULL);
+}
+
+int bl_send_scanu_raw_send(struct bl_hw *bl_hw, uint8_t *pkt, int len)
+{
+    struct scanu_raw_send_req *req;
+    struct scanu_raw_send_cfm cfm;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the SCANU_RAW_SEND_REQ message */
+    req = bl_msg_zalloc(SCANU_RAW_SEND_REQ, TASK_SCANU, DRV_TASK_ID, sizeof(struct scanu_raw_send_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters */
+    req->pkt = pkt;
+    req->len = len;
+
+    /* Send the SCANU_RAW_SEND_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, SCANU_RAW_SEND_CFM, &cfm);
+}
+
+static inline bool use_pairwise_key(struct cfg80211_crypto_settings *crypto)
+{
+    if ((crypto->cipher_group ==  WLAN_CIPHER_SUITE_WEP40) ||
+        (crypto->cipher_group ==  WLAN_CIPHER_SUITE_WEP104))
+        return false;
+
+    return true;
+}
+
+int bl_send_sm_connect_req(struct bl_hw *bl_hw, struct cfg80211_connect_params *sme, struct sm_connect_cfm *cfm)
+{
+    struct sm_connect_req *req;
+    int i;
+    u32_l flags = sme->flags;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the SM_CONNECT_REQ message */
+    req = bl_msg_zalloc(SM_CONNECT_REQ, TASK_SM, DRV_TASK_ID,
+                                   sizeof(struct sm_connect_req));
+    if (!req)
+        return -ENOMEM;
+
+#if 0 // useless
+    /* Set parameters for the SM_CONNECT_REQ message */
+    if (sme->crypto.n_ciphers_pairwise &&
+        ((sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP40) ||
+         (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_TKIP) ||
+         (sme->crypto.ciphers_pairwise[0] == WLAN_CIPHER_SUITE_WEP104)))
+        flags |= DISABLE_HT;
+
+    if (sme->crypto.control_port)
+        flags |= CONTROL_PORT_HOST;
+
+    if (sme->crypto.control_port_no_encrypt)
+        flags |= CONTROL_PORT_NO_ENC;
+
+    if (use_pairwise_key(&sme->crypto))
+        flags |= WPA_WPA2_IN_USE;
+
+    if (sme->mfp == NL80211_MFP_REQUIRED)
+        flags |= MFP_IN_USE;
+
+    if (sme->crypto.control_port_ethertype)
+        req->ctrl_port_ethertype = sme->crypto.control_port_ethertype;
+    else
+        req->ctrl_port_ethertype = ETH_P_PAE;
+#endif
+    req->ctrl_port_ethertype = ETH_P_PAE;
+
+    if (sme->bssid && !MAC_ADDR_CMP(sme->bssid, mac_addr_bcst.array) && !MAC_ADDR_CMP(sme->bssid, mac_addr_zero.array)) {
+        for (i=0;i<ETH_ALEN;i++)
+            req->bssid.array[i] = sme->bssid[i];
+    }
+    else
+        req->bssid = mac_addr_bcst;
+    req->vif_idx = bl_hw->vif_index_sta;
+    if (sme->channel.center_freq) {
+        req->chan.band = sme->channel.band;
+        req->chan.freq = sme->channel.center_freq;
+        req->chan.flags = passive_scan_flag(sme->channel.flags);
+    } else {
+        req->chan.freq = (u16_l)-1;
+    }
+    for (i = 0; i < sme->ssid_len; i++)
+        req->ssid.array[i] = sme->ssid[i];
+    req->ssid.length = sme->ssid_len;
+    req->flags = flags;
+#if 0 // useless
+    if (WARN_ON(sme->ie_len > sizeof(req->ie_buf)))
+        return -EINVAL;
+    if (sme->ie_len)
+        memcpy(req->ie_buf, sme->ie, sme->ie_len);
+    req->ie_len = sme->ie_len;
+#endif
+    req->listen_interval = bl_mod_params.listen_itv;
+    req->dont_wait_bcmc = !bl_mod_params.listen_bcmc;
+
+    /* Set auth_type */
+    if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC)
+        req->auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
+    else
+        req->auth_type = sme->auth_type;
+
+    /* Set UAPSD queues */
+    req->uapsd_queues = bl_mod_params.uapsd_queues;
+    req->is_supplicant_enabled = 1;
+    if (sme->key_len) {
+        memcpy(req->phrase, sme->key, sme->key_len);
+    }
+    if (sme->pmk_len) {
+        memcpy(req->phrase_pmk, sme->pmk, sme->pmk_len);
+    }
+
+    /* Send the SM_CONNECT_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, SM_CONNECT_CFM, cfm);
+}
+
+int bl_send_sm_disconnect_req(struct bl_hw *bl_hw)
+{
+    struct sm_disconnect_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the SM_DISCONNECT_REQ message */
+    req = bl_msg_zalloc(SM_DISCONNECT_REQ, TASK_SM, DRV_TASK_ID, sizeof(struct sm_disconnect_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the SM_DISCONNECT_REQ message */
+    req->vif_idx = bl_hw->vif_index_sta;
+
+    /* Send the SM_DISCONNECT_REQ message to LMAC FW */
+    //return bl_send_msg(bl_hw, req, 1, SM_DISCONNECT_IND, NULL);
+    return bl_send_msg(bl_hw, req, 1, SM_DISCONNECT_CFM, NULL);
+}
+
+int bl_send_sm_connect_abort_req(struct bl_hw *bl_hw, struct sm_connect_abort_cfm *cfm)
+{
+    struct sm_connect_abort_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    req = bl_msg_zalloc(SM_CONNECT_ABORT_REQ, TASK_SM, DRV_TASK_ID, sizeof(struct sm_connect_abort_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+    /* Set parameters for the SM_CONNECT_ABORT_REQ message */
+    req->vif_idx = bl_hw->vif_index_sta;
+
+    return bl_send_msg(bl_hw, req, 1, SM_CONNECT_ABORT_CFM, cfm);
+}
+
+int bl_send_mm_powersaving_req(struct bl_hw *bl_hw, int mode)
+{
+    struct mm_set_ps_mode_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the MM_SET_PS_MODE_REQ message */
+    req = bl_msg_zalloc(MM_SET_PS_MODE_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_ps_mode_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the MM_SET_PS_MODE_REQ message */
+    req->new_state = mode;
+
+    /* Send the MM_SET_PS_MODE_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, MM_SET_PS_MODE_CFM, NULL);
+}
+
+int bl_send_mm_denoise_req(struct bl_hw *bl_hw, int mode)
+{
+    struct mm_set_denoise_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the MM_DENOISE_REQ message */
+    req = bl_msg_zalloc(MM_DENOISE_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_denoise_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the MM_SET_PS_MODE_REQ message */
+    req->denoise_mode = mode;
+
+    /* Send the MM_SET_PS_MODE_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, MM_SET_PS_MODE_CFM, NULL);
+}
+
+/* Country IE definition
+MAC_COUNTRY_2G4_USA       {7,  6, 'U', 'S', 32,  1, 11, 20} // X'10' FCC
+MAC_COUNTRY_2G4_CANADA    {7,  6, 'C', 'A', 32,  1, 11, 20} // X'20' DOC/IC
+MAC_COUNTRY_2G4_EUROPE    {7,  6, 'E', 'U', 32,  1, 13, 20} // X'30' ETSI
+MAC_COUNTRY_2G4_SPAIN     {7,  6, 'S', 'P', 32, 10,  2, 20} // X'31'
+MAC_COUNTRY_2G4_FRANCE    {7,  6, 'F', 'R', 32, 10,  4, 20} // X'32'
+MAC_COUNTRY_2G4_JAPAN     {7,  6, 'J', 'P', 32, 14,  1, 20} // X'40'
+MAC_COUNTRY_2G4_CHINA     {7,  6, 'C', 'N', 32,  1, 13, 20} // X'50'
+*/
+
+static int _fill_country_code_ie(uint8_t *buf, uint8_t buf_len_max)
+{
+    if (NULL == country_default || NULL == channels_default) {
+        return 0;
+    }
+
+    // Tag: Country Informance
+    buf[0] = 7;
+    // Tag lenth
+    buf[1] = 6;
+    //Country Code
+    buf[2] = country_default->code[0];
+    buf[3] = country_default->code[1];
+    //Environment
+    buf[4] = 32;//Any
+    //First Channel
+    buf[5] = 1;
+    //Channel Num
+    buf[6] = buf[5] - 1 + country_default ->channel_num;
+    //Max power
+    buf[7] = channels_default->max_power;
+
+    return 8;
+}
+
+int bl_send_apm_start_req(struct bl_hw *bl_hw, struct apm_start_cfm *cfm, char *ssid, char *password, int channel, uint8_t vif_index, uint8_t hidden_ssid, uint16_t bcn_int)
+{
+    struct apm_start_req *req;
+    uint8_t rate[] = {0x82,0x84,0x8b,0x96,0x12,0x24,0x48,0x6c,0x0c,0x18,0x30,0x60};
+
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the APM_START_REQ message */
+    req = bl_msg_zalloc(APM_START_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_start_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    req->chan.band = NL80211_BAND_2GHZ;
+    req->chan.freq = phy_channel_to_freq(req->chan.band, channel);
+    req->chan.flags = 0;
+    req->chan.tx_power = 0;
+
+    /* Set parameters for the APM_START_REQ message */
+    req->center_freq1 = req->chan.freq;
+    req->center_freq2 = 0;
+    req->ch_width = PHY_CHNL_BW_20;
+    req->hidden_ssid = hidden_ssid;
+    req->bcn_addr = 0;
+    req->bcn_len = 0;
+    req->tim_oft = 0;
+    req->bcn_int = bcn_int;
+    req->flags = 0x08;
+    //req->ctrl_port_ethertype = ETH_P_PAE;
+    req->ctrl_port_ethertype = 0x8e88;
+    req->tim_len = 0x6;
+    req->vif_idx = vif_index;
+
+    /*added for EMBEDED*/
+#if 0
+    /// Enable APM Embedded
+    bool apm_emb_enabled;
+    /// rate set
+    struct mac_rateset rate_set;
+    /// Beacon dtim period
+    uint8_t beacon_period;
+    /// Qos is supported
+    uint8_t qos_supported;
+    /// SSID of the AP
+    struct mac_ssid ssid;
+    /// AP Security type
+    uint8_t ap_sec_type;
+    /// AP Passphrase
+    uint8_t phrase[MAX_PSK_PASS_PHRASE_LEN];
+#else
+    if (strlen(password)) {
+        req->ap_sec_type = 1;
+    } else {
+        req->ap_sec_type = 0;
+    }
+    req->apm_emb_enabled = 1;
+    memcpy(req->ssid.array, ssid, strlen(ssid));//FIXME potential buffer overflow
+    memcpy(req->phrase, password, strlen(password));//FIXME potential buffer overflow
+    req->ssid.length = strlen(ssid);
+    req->rate_set.length = 12;
+    memcpy(req->rate_set.array, rate, req->rate_set.length);
+    req->beacon_period = 0x1; //force AP DTIM period
+    req->qos_supported = 1;
+#endif
+    req->bcn_buf_len = _fill_country_code_ie(req->bcn_buf, sizeof(req->bcn_buf));
+
+    /* Send the APM_START_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, APM_START_CFM, cfm);
+}
+
+int bl_send_apm_stop_req(struct bl_hw *bl_hw, uint8_t vif_idx)
+{
+    struct apm_stop_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the APM_STOP_REQ message */
+    req = bl_msg_zalloc(APM_STOP_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_stop_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the APM_STOP_REQ message */
+    req->vif_idx = vif_idx;
+
+    /* Send the APM_STOP_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, APM_STOP_CFM, NULL);
+}
+
+int bl_send_apm_sta_del_req(struct bl_hw *bl_hw, struct apm_sta_del_cfm *cfm, uint8_t sta_idx, uint8_t vif_idx)
+{
+    struct apm_sta_del_req *req;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    /* Build the APM_STOP_REQ message */
+    req = bl_msg_zalloc(APM_STA_DEL_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_sta_del_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the APM_STA_DEL_REQ message */
+    req->vif_idx = vif_idx;
+    req->sta_idx = sta_idx;
+
+    /* Send the APM_STA_DEL_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, APM_STA_DEL_CFM, cfm);
+}
+
+int bl_send_apm_conf_max_sta_req(struct bl_hw *bl_hw, uint8_t max_sta_supported)
+{
+    struct apm_conf_max_sta_req *req;
+
+    /* Build the APM_STOP_REQ message */
+    req = bl_msg_zalloc(APM_CONF_MAX_STA_REQ, TASK_APM, DRV_TASK_ID, sizeof(struct apm_conf_max_sta_req));
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the APM_STOP_REQ message */
+    req->max_sta_supported = max_sta_supported;
+
+    /* Send the APM_STOP_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, APM_CONF_MAX_STA_CFM, NULL);
+}
+
+int bl_send_cfg_task_req(struct bl_hw *bl_hw, uint32_t ops, uint32_t task, uint32_t element, uint32_t type, void *arg1, void *arg2)
+{
+    struct cfg_start_req *req;
+#define ENTRY_BUF_SIZE      (8)
+
+    /* Build the APM_STOP_REQ message */
+    //FIXME static allocated size
+    req = bl_msg_zalloc(CFG_START_REQ, TASK_CFG, DRV_TASK_ID, sizeof(struct cfg_start_req) + 32);
+    if (!req) {
+        return -ENOMEM;
+    }
+
+    /* Set parameters for the APM_STOP_REQ message */
+    req->ops = ops;
+    switch (req->ops) {
+        case CFG_ELEMENT_TYPE_OPS_SET:
+        {
+            req->u.set[0].task = task;
+            req->u.set[0].element = element;
+            req->u.set[0].type = type;
+            req->u.set[0].length = utils_tlv_bl_pack_auto(
+                req->u.set[0].buf,
+                ENTRY_BUF_SIZE,
+                type, 
+                arg1
+            );
+        }
+        break;
+        case CFG_ELEMENT_TYPE_OPS_GET:
+        {
+            //TODO
+        }
+        break;
+        case CFG_ELEMENT_TYPE_OPS_RESET:
+        {
+            //TODO
+        }
+        break;
+        case CFG_ELEMENT_TYPE_OPS_DUMP_DEBUG:
+        {
+            req->u.set[0].task = task;
+            req->u.set[0].element = element;
+            req->u.set[0].length = 0;
+        }
+        break;
+        default:
+        {
+            /*empty here*/
+            assert(0);
+        }
+    }
+
+    /* Send the APM_STOP_REQ message to LMAC FW */
+    return bl_send_msg(bl_hw, req, 1, CFG_START_CFM, NULL);
+}
+
+int bl_send_channel_set_req(struct bl_hw *bl_hw, int channel)
+{
+    struct mm_set_channel_req *param;
+    struct mm_set_channel_cfm cfm;
+
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    param = bl_msg_zalloc(MM_SET_CHANNEL_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_channel_req));
+    if (!param) {
+        return -ENOMEM;
+    }
+    memset(&cfm, 0, sizeof(struct mm_set_channel_cfm));
+
+    param->band = PHY_BAND_2G4;
+    param->type = PHY_CHNL_BW_20;
+    param->prim20_freq = phy_channel_to_freq(param->band, channel);
+    param->center1_freq = phy_channel_to_freq(param->band, channel);//useless when bandwidth bigger than 20MHZ?
+    param->center2_freq = phy_channel_to_freq(param->band, channel);//useless when bandwidth bigger than 20MHZ? 
+    param->index = 0;
+    param->tx_power = 15;//FIXME which value should be tx_power set?
+
+    return bl_send_msg(bl_hw, param, 1, MM_SET_CHANNEL_CFM, &cfm);
+}
+

+ 52 - 0
network/wifi_manager/bl60x_wifi_driver/bl_msg_tx.h

@@ -0,0 +1,52 @@
+#ifndef __RWNX_MSG_TX_H__
+#define __RWNX_MSG_TX_H__
+#include "bl_defs.h"
+
+struct bl_send_scanu_para {
+    uint16_t *channels;
+    uint16_t channel_num;
+    struct mac_addr *bssid;
+    struct mac_ssid *ssid;
+    uint8_t mac[6];
+    uint8_t scan_mode;
+    uint32_t duration_scan;
+};
+
+int bl_send_reset(struct bl_hw *bl_hw);
+int bl_send_monitor_enable(struct bl_hw *bl_hw, struct mm_monitor_cfm *cfm);
+int bl_send_monitor_disable(struct bl_hw *bl_hw, struct mm_monitor_cfm *cfm);
+/*
+ *  use_40MHZ:
+ *      0: Don't use 40MHZ
+ *      1: Use lower band as second band
+ *      2: Use higher band as second band
+ * */
+int bl_send_monitor_channel_set(struct bl_hw *bl_hw, struct mm_monitor_channel_cfm *cfm, int channel, int use_40Mhz);
+int bl_send_version_req(struct bl_hw *bl_hw, struct mm_version_cfm *cfm);
+int bl_send_me_config_req(struct bl_hw *bl_hw);
+int bl_send_me_chan_config_req(struct bl_hw *bl_hw);
+int bl_send_me_rate_config_req(struct bl_hw *bl_hw, uint8_t sta_idx, uint16_t fixed_rate_cfg);
+int bl_send_start(struct bl_hw *bl_hw);
+int bl_send_add_if(struct bl_hw *bl_hw, const unsigned char *mac,
+                     enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm);
+int bl_send_remove_if(struct bl_hw *bl_hw, uint8_t inst_nbr);
+int bl_send_scanu_req(struct bl_hw *bl_hw, struct bl_send_scanu_para *scanu_para);
+int bl_send_scanu_raw_send(struct bl_hw *bl_hw, uint8_t *pkt, int len);
+int bl_send_sm_connect_req(struct bl_hw *bl_hw, struct cfg80211_connect_params *sme, struct sm_connect_cfm *cfm);
+int bl_send_sm_connect_abort_req(struct bl_hw *bl_hw, struct sm_connect_abort_cfm *cfm);
+int bl_send_sm_disconnect_req(struct bl_hw *bl_hw);
+int bl_send_mm_powersaving_req(struct bl_hw *bl_hw, int mode);
+int bl_send_mm_denoise_req(struct bl_hw *bl_hw, int mode);
+int bl_send_apm_start_req(struct bl_hw *bl_hw, struct apm_start_cfm *cfm, char *ssid, char *password, int channel, uint8_t vif_index, uint8_t hidden_ssid, uint16_t bcn_int);
+int bl_send_apm_stop_req(struct bl_hw *bl_hw, uint8_t vif_idx);
+int bl_send_apm_sta_del_req(struct bl_hw *bl_hw, struct apm_sta_del_cfm *cfm, uint8_t sta_idx, uint8_t vif_idx);
+int bl_send_apm_conf_max_sta_req(struct bl_hw *bl_hw, uint8_t max_sta_supported);
+int bl_send_cfg_task_req(struct bl_hw *bl_hw, uint32_t ops, uint32_t task, uint32_t element, uint32_t type, void *arg1, void *arg2);
+int bl_send_channel_set_req(struct bl_hw *bl_hw, int channel);
+void bl_msg_update_channel_cfg(const char *code);
+int bl_msg_get_channel_nums();
+int bl_get_fixed_channels_is_valid(uint16_t *channels, uint16_t channel_num);
+int bl_send_beacon_interval_set(struct bl_hw *bl_hw, struct mm_set_beacon_int_cfm *cfm, uint16_t beacon_int);
+uint16_t phy_channel_to_freq(uint8_t band, int channel);
+uint8_t phy_freq_to_channel(uint8_t band, uint16_t freq);
+#endif

+ 56 - 0
network/wifi_manager/bl60x_wifi_driver/bl_platform.c

@@ -0,0 +1,56 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_platform.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#include "bl_platform.h"
+#include "bl_irqs.h"
+#include "bl_utils.h"
+#include "reg_access.h"
+#include "reg_ipc_app.h"
+
+/**
+ * bl_platform_on - Start the platform
+ *
+ * @bl_hw Main driver data
+ *
+ * It starts the platform :
+ * - initialize IPC
+ * - boot the fw
+ * - enable link communication/IRQ
+ *
+ * Called by 802.11 part
+ */
+struct ipc_shared_env_tag *ipc_shenv;
+int bl_platform_on(struct bl_hw *bl_hw)
+{
+    int ret;
+
+    ipc_shenv = (struct ipc_shared_env_tag *)(&ipc_shared_env);
+    ret = bl_ipc_init(bl_hw, ipc_shenv);
+    if (ret) {
+        return ret;
+    }
+
+    /*clear any pending IRQ*/
+    ipc_emb2app_ack_clear(0xFFFFFFFF);
+#if 0
+    RWNX_REG_WRITE(BOOTROM_ENABLE, BL606_WIFI_PLATFORM_ADDRESS, SYSCTRL_MISC_CNTL_ADDR);
+#endif
+
+    return 0;
+}
+
+void bl_platform_off(struct bl_hw *bl_hw)
+{
+    ipc_host_disable_irq(bl_hw->ipc_env, IPC_IRQ_E2A_ALL);
+#if 0
+    tasklet_kill(&bl_hw->task);
+    bl_ipc_deinit(bl_hw);
+#endif
+}

+ 23 - 0
network/wifi_manager/bl60x_wifi_driver/bl_platform.h

@@ -0,0 +1,23 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_platform.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+
+#ifndef _RWNX_PLAT_H_
+#define _RWNX_PLAT_H_
+#define BL606_WIFI_PLATFORM_ADDRESS (0x60000000)
+
+#define writel(b,addr) (*(volatile unsigned int *)(addr) = (b))
+#define RWNX_REG_WRITE(val, plat, offset)         \
+    writel(val, plat + offset)
+
+struct bl_hw;
+int bl_platform_on(struct bl_hw *bl_hw);
+void bl_platform_off(struct bl_hw *bl_hw);
+#endif /* _RWNX_PLAT_H_ */

+ 854 - 0
network/wifi_manager/bl60x_wifi_driver/bl_rx.c

@@ -0,0 +1,854 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_rx.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <lwip/inet.h>
+#include <lwip/netifapi.h>
+#include <aos/yloop.h>
+#include "bl_main.h"
+#include "bl_defs.h"
+#include "bl_cmds.h"
+#include "bl_rx.h"
+#include "bl_utils.h"
+#include "ieee80211.h"
+#include <bl60x_fw_api.h>
+#include <supplicant_api.h>
+#include <bl_wpa.h>
+
+#ifdef BL602_MATTER_SUPPORT
+#include <lwip/dhcp6.h>
+#endif
+
+#include <bl_os_private.h>
+#define USER_UNUSED(a) ((void)(a))
+
+static wifi_event_sm_connect_ind_cb_t cb_sm_connect_ind;
+static void* cb_sm_connect_ind_env;
+static wifi_event_sm_disconnect_ind_cb_t cb_sm_disconnect_ind;
+static void* cb_sm_disconnect_ind_env;
+static wifi_event_beacon_ind_cb_t cb_beacon_ind;
+static void* cb_beacon_ind_env;
+static wifi_event_probe_resp_ind_cb_t cb_probe_resp_ind;
+static void* cb_probe_resp_ind_env;
+static wifi_event_pkt_cb_t cb_pkt;
+static wifi_event_pkt_cb_adv_t cb_pkt_adv;
+static void* cb_pkt_env;
+static wifi_event_rssi_cb_t cb_rssi;
+static void* cb_rssi_env;
+static wifi_event_cb_t cb_event;
+static void* cb_event_env;
+extern struct bl_hw wifi_hw;
+
+static const struct reason_code sm_reason_list[] = {
+    {WLAN_FW_SUCCESSFUL, "sm connect ind ok"},
+    {WLAN_FW_TX_AUTH_FRAME_ALLOCATE_FAIILURE, "tx auth frame alloc failure"},
+    {WLAN_FW_AUTHENTICATION_FAIILURE, "Authentication failure"},
+    {WLAN_FW_AUTH_ALGO_FAIILURE, "Auth response but auth algo failure"},
+    {WLAN_FW_TX_ASSOC_FRAME_ALLOCATE_FAIILURE, "tx assoc frame alloc failure"},
+    {WLAN_FW_ASSOCIATE_FAIILURE, "Association failure"},
+    {WLAN_FW_DEAUTH_BY_AP_WHEN_NOT_CONNECTION, "deauth by AP when connecting"},
+    {WLAN_FW_DEAUTH_BY_AP_WHEN_CONNECTION, "deauth by AP when connected"},
+    {WLAN_FW_4WAY_HANDSHAKE_ERROR_PSK_TIMEOUT_FAILURE, "Passwd error, 4-way handshake timeout"},
+    {WLAN_FW_4WAY_HANDSHAKE_TX_DEAUTH_FRAME_TRANSMIT_FAILURE, "Passwd error, tx deauth frame transmit failure"},
+    {WLAN_FW_4WAY_HANDSHAKE_TX_DEAUTH_FRAME_ALLOCATE_FAIILURE, "Passwd error, tx deauth frame allocate failure"},
+    {WLAN_FW_AUTH_OR_ASSOC_RESPONSE_TIMEOUT_FAILURE, "auth or associate frame response timeout failure"},
+    {WLAN_FW_SCAN_NO_BSSID_AND_CHANNEL, "SSID error, scan no bssid and channel"},
+    {WLAN_FW_CREATE_CHANNEL_CTX_FAILURE_WHEN_JOIN_NETWORK, "create channel context failure when join network"},
+    {WLAN_FW_JOIN_NETWORK_FAILURE, "join network failure"},
+    {WLAN_FW_ADD_STA_FAILURE, "add sta failure"},
+    {WLAN_FW_BEACON_LOSS, "ap beacon loss"},
+    {WLAN_FW_JOIN_NETWORK_SECURITY_NOMATCH, "network security no match"},
+    {WLAN_FW_JOIN_NETWORK_WEPLEN_ERROR, "wep network psk len error"},
+    {WLAN_FW_DISCONNECT_BY_USER_WITH_DEAUTH, "user disconnect and send deauth"},
+    {WLAN_FW_DISCONNECT_BY_USER_NO_DEAUTH, "user disconnect but no send deauth"},
+    {WLAN_FW_DISCONNECT_BY_FW_PS_TX_NULLFRAME_FAILURE, "fw disconnect(tx nullframe failures)"},
+    {WLAN_FW_TRAFFIC_LOSS, "fw disconnect(traffic loss)"},
+    {WLAN_FW_CONNECT_ABORT_BY_USER_WITH_DEAUTH, "user connect abort and send deauth"},
+    {WLAN_FW_CONNECT_ABORT_BY_USER_NO_DEAUTH, "user connect abort without sending deauth"},
+    {WLAN_FW_CONNECT_ABORT_WHEN_JOINING_NETWORK, "user connect abort when joining network"}, 
+    {WLAN_FW_CONNECT_ABORT_WHEN_SCANNING, "user connect abort when scanning"},
+};
+
+static const struct reason_code apm_reason_list[] = {
+    {WLAN_FW_APM_SUCCESSFUL, "apm connect ind ok"},
+    {WLAN_FW_APM_DELETESTA_BY_USER, "User delete STA"},
+    {WLAN_FW_APM_DEATUH_BY_STA, "STA send deauth to AP"},
+    {WLAN_FW_APM_DISASSOCIATE_BY_STA, "STA send disassociate to AP"},
+    {WLAN_FW_APM_DELETECONNECTION_TIMEOUT, "timeout and delete connection"},
+    {WLAN_FW_APM_DELETESTA_FOR_NEW_CONNECTION, "Delete STA for new connection"},
+};
+int bl_rx_sm_connect_ind_cb_register(void *env, wifi_event_sm_connect_ind_cb_t cb)
+{
+    cb_sm_connect_ind = cb;
+    cb_sm_connect_ind_env = env;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_sm_connect_ind_cb_unregister(void *env, wifi_event_sm_connect_ind_cb_t cb)
+{
+    cb_sm_connect_ind = NULL;
+    cb_sm_connect_ind_env = NULL;
+
+    return 0;
+}
+
+int bl_rx_sm_disconnect_ind_cb_register(void *env, wifi_event_sm_disconnect_ind_cb_t cb)
+{
+    cb_sm_disconnect_ind = cb;
+    cb_sm_disconnect_ind_env = env;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_sm_disconnect_ind_cb_unregister(void *env, wifi_event_sm_disconnect_ind_cb_t cb)
+{
+    cb_sm_disconnect_ind = NULL;
+    cb_sm_disconnect_ind_env = NULL;
+
+    return 0;
+}
+
+int bl_rx_beacon_ind_cb_register(void *env, wifi_event_beacon_ind_cb_t cb)
+{
+    cb_beacon_ind = cb;
+    cb_beacon_ind_env = env;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_beacon_ind_cb_unregister(void *env, wifi_event_beacon_ind_cb_t cb)
+{
+    cb_beacon_ind = NULL;
+    cb_beacon_ind_env = NULL;
+
+    return 0;
+}
+
+int bl_rx_probe_resp_ind_cb_register(void *env, wifi_event_probe_resp_ind_cb_t cb)
+{
+    cb_probe_resp_ind = cb;
+    cb_probe_resp_ind_env = env;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_probe_resp_ind_cb_unregister(void *env, wifi_event_probe_resp_ind_cb_t cb)
+{
+    cb_probe_resp_ind = NULL;
+    cb_probe_resp_ind_env = NULL;
+
+    return 0;
+}
+
+
+int bl_rx_pkt_cb_register(void *env, wifi_event_pkt_cb_t cb)
+{
+    cb_pkt = cb;
+    cb_pkt_env = env;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_pkt_cb_unregister(void *env)
+{
+    cb_pkt = NULL;
+    cb_pkt_env = NULL;
+
+    return 0;
+}
+
+int bl_rx_pkt_adv_cb_register(void *env, wifi_event_pkt_cb_adv_t cb)
+{
+    cb_pkt_adv = cb;
+    cb_pkt_env = env;
+
+    return 0;
+}
+
+int bl_rx_pkt_adv_cb_unregister(void *env)
+{
+    cb_pkt_adv = NULL;
+    cb_pkt_env = NULL;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_rssi_cb_register(void *env, wifi_event_rssi_cb_t cb)
+{
+    cb_rssi = cb;
+    cb_rssi_env = env;
+
+    return 0;
+}
+
+int bl_rx_rssi_cb_unregister(void *env, wifi_event_rssi_cb_t cb)
+{
+    cb_rssi = NULL;
+    cb_rssi_env = NULL;
+
+    return 0;
+}
+
+//FIXME race condition protect?
+int bl_rx_event_register(void *env, wifi_event_cb_t cb)
+{
+    cb_event = cb;
+    cb_event_env = env;
+
+    return 0;
+}
+
+int bl_rx_event_unregister(void *env)
+{
+    cb_event = NULL;
+    cb_event_env = NULL;
+
+    return 0;
+}
+
+static void notify_event_channel_switch(int channel)
+{
+    uint8_t buffer[sizeof(struct wifi_event) + sizeof(struct wifi_event_data_ind_channel_switch)];
+    struct wifi_event *event;
+    struct wifi_event_data_ind_channel_switch *ind;
+
+    event = (struct wifi_event*)buffer;
+    ind = (struct wifi_event_data_ind_channel_switch*)event->data;
+    memset(event, 0, sizeof(struct wifi_event));
+    memset(ind, 0, sizeof(struct wifi_event_data_ind_channel_switch));
+
+    event->id = WIFI_EVENT_ID_IND_CHANNEL_SWITCH;
+    ind->channel = channel;
+
+    //FIXME race condition protect
+    if (cb_event) {
+        cb_event(cb_event_env, event);
+    }
+}
+
+static void notify_event_scan_done(int join_scan)
+{
+    uint8_t buffer[sizeof(struct wifi_event) + sizeof(struct wifi_event_data_ind_scan_done)];
+    struct wifi_event *event;
+    struct wifi_event_data_ind_scan_done *ind;
+
+    event = (struct wifi_event*)buffer;
+    ind = (struct wifi_event_data_ind_scan_done*)event->data;
+    memset(event, 0, sizeof(struct wifi_event));
+    memset(ind, 0, sizeof(struct wifi_event_data_ind_scan_done));
+
+    event->id = join_scan ? WIFI_EVENT_ID_IND_SCAN_DONE_ONJOIN : WIFI_EVENT_ID_IND_SCAN_DONE;
+    ind->nothing = __LINE__;
+
+    //FIXME race condition protect
+    if (cb_event) {
+        cb_event(cb_event_env, event);
+    }
+}
+
+static int bl_rx_chan_switch_ind(struct bl_hw *bl_hw,
+     struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    struct mm_channel_switch_ind *ind = (struct mm_channel_switch_ind *)msg->param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+    notify_event_channel_switch(ind->chan_index);
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return 0;
+}
+
+static int bl_comman_ind(struct bl_hw *bl_hw,
+     struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return 0;
+}
+
+static int bl_rx_rssi_status_ind(struct bl_hw *bl_hw,
+      struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    struct mm_rssi_status_ind *ind = (struct mm_rssi_status_ind *)msg->param;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    //bl_os_printf("------> rssi_status %u:%u:%d\r\n", ind->vif_index, ind->rssi_status, ind->rssi);
+    if (cb_rssi) {
+        cb_rssi(cb_rssi_env, ind->rssi);
+    }
+
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return 0;
+}
+
+const static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = {
+    [MSG_I(MM_CHANNEL_SWITCH_IND)]     = bl_rx_chan_switch_ind,
+    [MSG_I(MM_CHANNEL_PRE_SWITCH_IND)] = bl_comman_ind,
+    [MSG_I(MM_REMAIN_ON_CHANNEL_EXP_IND)] = bl_comman_ind,
+    [MSG_I(MM_PS_CHANGE_IND)]          = bl_comman_ind,
+    [MSG_I(MM_TRAFFIC_REQ_IND)]        = bl_comman_ind,
+    [MSG_I(MM_CHANNEL_SURVEY_IND)]     = bl_comman_ind,
+    [MSG_I(MM_RSSI_STATUS_IND)]        = bl_rx_rssi_status_ind,
+};
+
+static int bl_rx_scanu_start_cfm(struct bl_hw *bl_hw,
+      struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+#if 0
+    if (bl_hw->preq_ie.buf) {
+        dma_unmap_single(bl_hw->dev, bl_hw->preq_ie.dma_addr,
+                         bl_hw->preq_ie.bufsz, DMA_TO_DEVICE);
+        kfree(bl_hw->preq_ie.buf);
+        bl_hw->preq_ie.buf = NULL;
+    }
+
+    if (bl_hw->scan_request)
+        cfg80211_scan_done(bl_hw->scan_request, false);
+
+    bl_hw->scan_request = NULL;
+#endif
+    notify_event_scan_done(0);
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+
+    return 0;
+}
+
+static int bl_rx_scanu_join_cfm(struct bl_hw *bl_hw, struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    notify_event_scan_done(1);
+
+    return 0;
+}
+
+static int find_ie_ssid(uint8_t *buffer, int len, uint8_t *result, int *ssid_len)
+{
+    int i;
+
+    i = 0;
+    while (i < len) {
+#define IE_ID_SSID 0x00
+        if (IE_ID_SSID == buffer[0]) {//FIXME no magic ID for SSID
+            if (buffer[1] > 32) {
+                return -1;
+            }
+            *ssid_len = buffer[1];
+            memcpy(result, &(buffer[2]), buffer[1]);//NO check for len valid
+            result[buffer[1]] = '\0';
+            return 0;
+        } else {
+            /*move to next ie*/
+            i += buffer[1] + 2;//FIXME 2 is for id and len
+            buffer = buffer + buffer[1] + 2;
+        }
+    }
+
+    return -1;
+}
+
+static int find_ie_ds(uint8_t *buffer, int len, uint8_t *result)
+{
+    int i;
+
+    i = 0;
+    while (i < len) {
+#define IE_ID_DS_CHANNEL 0x03
+        if (IE_ID_DS_CHANNEL == buffer[0]) {//FIXME no magic DS for SSID
+            if (buffer[1] > 32) {
+                return -1;
+            }
+            *result = buffer[2];
+            return 0;
+        } else {
+            /*move to next ie*/
+            i += buffer[1] + 2;//FIXME 2 is for id and len
+            buffer = buffer + buffer[1] + 2;
+        }
+    }
+
+    return -1;
+}
+
+extern uint32_t mac_vsie_find(uint32_t addr, uint16_t buflen, uint8_t const *oui, uint8_t ouilen);
+extern uint32_t mac_ie_find(uint32_t addr, uint16_t buflen, uint8_t ie_id);
+static uint8_t co_read8p(uint32_t addr)
+{
+    return (*(uint8_t *)addr);
+}
+#define MAC_INFOELT_LEN_OFT               (1)
+#define MAC_INFOELT_INFO_OFT              (2)
+
+#define MAX_RSN_WPA_IE_LEN                (32)
+static void _rx_handle_beacon(struct scanu_result_ind *ind, struct ieee80211_mgmt *mgmt)
+{
+    struct wifi_event_beacon_ind ind_new;
+    uint32_t var_part_addr, var_part_len;
+    uint32_t elmt_addr;
+    uint32_t rsn_wpa_ie_len;
+    wifi_wpa_ie_t wpa_ie, rsn_ie;
+
+    memset(&ind_new, 0, sizeof(ind_new));
+
+    var_part_addr = (uint32_t)(mgmt->u.beacon.variable);
+    var_part_len = ind->length - (uint32_t)&(((struct ieee80211_mgmt*)NULL)->u.beacon.variable);
+
+    find_ie_ssid(mgmt->u.beacon.variable, ind->length, ind_new.ssid, &ind_new.ssid_len);
+    find_ie_ds(mgmt->u.beacon.variable, ind->length, &ind_new.channel);
+
+    elmt_addr = mac_vsie_find(var_part_addr, var_part_len, (const uint8_t *) "\x00\x50\xF2\x04", 4);
+    if (elmt_addr != 0)
+    {
+        /*wps is suoported*/
+        ind_new.wps = 1;
+    } else {
+        /*wps isn't supported*/
+        ind_new.wps = 0;
+    }
+
+    /* TODO: Only consider 2.4G and bgn mode 
+     * (NO 5G and a/ac/ax) / (NO g-only and n-only difference)
+     */
+    #define MAC_ELTID_HT_CAPA                45
+    #define MAC_ELTID_EXT_RATES              50
+    if (mac_ie_find(var_part_addr, var_part_len, MAC_ELTID_HT_CAPA))
+    {
+        ind_new.mode = (WIFI_MODE_802_11B | WIFI_MODE_802_11G | WIFI_MODE_802_11N_2_4);
+    }
+    else if (mac_ie_find(var_part_addr, var_part_len, MAC_ELTID_EXT_RATES))
+    {
+        ind_new.mode = (WIFI_MODE_802_11B | WIFI_MODE_802_11G);
+    }
+    else
+    {
+        ind_new.mode = (WIFI_MODE_802_11B);
+    }
+
+    if (WLAN_CAPABILITY_PRIVACY & (le16_to_cpu(mgmt->u.beacon.capab_info))) {
+        wifi_wpa_ie_t *parsed_wpa_ie[2] = {};
+        int parsed_wpa_ie_len = 0;
+        int i;
+        bool tkip = false, ccmp = false;
+        bool group_tkip = false, group_ccmp = false;
+
+        #define MAC_ELTID_RSN_IEEE               48
+        elmt_addr = mac_ie_find(var_part_addr, var_part_len, MAC_ELTID_RSN_IEEE);
+        if (elmt_addr != 0) {
+            rsn_wpa_ie_len = co_read8p(elmt_addr + MAC_INFOELT_LEN_OFT) + MAC_INFOELT_INFO_OFT;
+            memset(&rsn_ie, 0, sizeof(rsn_ie));
+            wpa_parse_wpa_ie_wrapper((uint8_t *)elmt_addr, rsn_wpa_ie_len, &rsn_ie);
+            parsed_wpa_ie[parsed_wpa_ie_len++] = &rsn_ie;
+        }
+
+        elmt_addr = mac_vsie_find(var_part_addr, var_part_len, (uint8_t const *)"\x00\x50\xF2\x01", 4);
+        if (elmt_addr != 0) {
+            rsn_wpa_ie_len = co_read8p(elmt_addr + MAC_INFOELT_LEN_OFT) + MAC_INFOELT_INFO_OFT;
+            wpa_parse_wpa_ie_wrapper((uint8_t *)elmt_addr, rsn_wpa_ie_len, &wpa_ie);
+            parsed_wpa_ie[parsed_wpa_ie_len++] = &wpa_ie;
+        }
+
+        for (i = 0; i < parsed_wpa_ie_len; ++i) {
+            wifi_wpa_ie_t *ie = parsed_wpa_ie[i];
+            int pc = ie->pairwise_cipher;
+            int gc = ie->group_cipher;
+            int ciphers[2] = { pc, gc };
+            int j;
+
+            if (ie->proto == WPA_PROTO_WPA) {
+                ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_WPA_PSK;
+            } else if (ie->proto == WPA_PROTO_RSN) {
+                if (ie->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_PSK_SHA256)) {
+                    ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_WPA2_PSK;
+                    if (ie->key_mgmt & WPA_KEY_MGMT_SAE) {
+                        ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_WPA2_PSK_WPA3_SAE;
+                    }
+                } else if (ie->key_mgmt & WPA_KEY_MGMT_SAE) {
+                    ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_WPA3_SAE;
+                }
+            }
+
+            for (j = 0; j < sizeof(ciphers) / sizeof(ciphers[0]); ++j) {
+                int cipher = ciphers[j];
+                if (cipher == WIFI_CIPHER_TYPE_TKIP) {
+                    tkip = true;
+                    if (cipher == gc)
+                        group_tkip = true;
+                }
+                if (cipher == WIFI_CIPHER_TYPE_CCMP) {
+                    ccmp = true;
+                    if (cipher == gc)
+                        group_ccmp = true;
+                }
+                if (cipher == WIFI_CIPHER_TYPE_TKIP_CCMP) {
+                    tkip = ccmp = true;
+                    if (cipher == gc)
+                        group_tkip = group_ccmp = true;
+                }
+            }
+        }
+        if (parsed_wpa_ie_len == sizeof(parsed_wpa_ie) / sizeof(parsed_wpa_ie[0])) {
+            ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_WPA_WPA2_PSK;
+        } else if (parsed_wpa_ie_len == 0) {
+            ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_WEP;
+            ind_new.cipher = WIFI_EVENT_BEACON_IND_CIPHER_WEP;
+        }
+
+        if (ccmp) {
+            ind_new.cipher = WIFI_EVENT_BEACON_IND_CIPHER_AES;
+        }
+        if (tkip) {
+            ind_new.cipher = WIFI_EVENT_BEACON_IND_CIPHER_TKIP;
+        }
+        if (tkip && ccmp) {
+            ind_new.cipher = WIFI_EVENT_BEACON_IND_CIPHER_TKIP_AES;
+        }
+        if (group_ccmp) {
+            ind_new.group_cipher = WIFI_EVENT_BEACON_IND_CIPHER_AES;
+        }
+        if (group_tkip) {
+            ind_new.group_cipher = WIFI_EVENT_BEACON_IND_CIPHER_TKIP;
+        }
+        if (group_tkip && group_ccmp) {
+            ind_new.group_cipher = WIFI_EVENT_BEACON_IND_CIPHER_TKIP_AES;
+        }
+    } else {
+        /*This is an open BSS*/
+        ind_new.auth = WIFI_EVENT_BEACON_IND_AUTH_OPEN;
+    }
+
+    ind_new.rssi = ind->rssi;
+    ind_new.ppm_abs = ind->ppm_abs;
+    ind_new.ppm_rel = ind->ppm_rel;
+    ind_new.bssid[0]  = mgmt->bssid[0];
+    ind_new.bssid[1]  = mgmt->bssid[1];
+    ind_new.bssid[2]  = mgmt->bssid[2];
+    ind_new.bssid[3]  = mgmt->bssid[3];
+    ind_new.bssid[4]  = mgmt->bssid[4];
+    ind_new.bssid[5]  = mgmt->bssid[5];
+    cb_beacon_ind(cb_beacon_ind_env, &ind_new);
+}
+
+static void _rx_handle_probersp(struct scanu_result_ind *ind, struct ieee80211_mgmt *mgmt)
+{
+    _rx_handle_beacon(ind, mgmt);
+}
+
+static int bl_rx_scanu_result_ind(struct bl_hw *bl_hw, struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    struct scanu_result_ind *ind = (struct scanu_result_ind *)msg->param;
+    struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)ind->payload;
+
+    if (ieee80211_is_beacon(mgmt->frame_control)) {
+        _rx_handle_beacon(ind, mgmt);
+    } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
+        _rx_handle_probersp(ind, mgmt);
+    } else {
+        bl_os_printf("Bug Scan IND?\r\n");
+    }
+
+    return 0;
+}
+
+const static msg_cb_fct scan_hdlrs[MSG_I(SCANU_MAX)] = {
+    [MSG_I(SCANU_START_CFM)]           = bl_rx_scanu_start_cfm,
+    [MSG_I(SCANU_JOIN_CFM)]            = bl_rx_scanu_join_cfm,
+    [MSG_I(SCANU_RESULT_IND)]          = bl_rx_scanu_result_ind,
+};
+
+const static msg_cb_fct me_hdlrs[MSG_I(ME_MAX)] = {
+    [MSG_I(ME_TKIP_MIC_FAILURE_IND)] = bl_comman_ind,
+    [MSG_I(ME_TX_CREDITS_UPDATE_IND)] = bl_comman_ind,
+};
+
+static const char* _get_status_code_str(const struct reason_code list[], uint16_t len, uint16_t status_code)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        if (list[i].reason_code == status_code) {
+            break;
+        }
+    }
+    if (len == i) {
+        return "Unknown Code";
+    }
+
+    return list[i].action;
+}
+
+const char* wifi_mgmr_get_sm_status_code_str(uint16_t status_code)
+{
+    return _get_status_code_str(sm_reason_list, sizeof(sm_reason_list)/sizeof(sm_reason_list[0]), status_code);
+}
+
+const char* wifi_mgmr_get_apm_status_code_str(uint16_t status_code)
+{
+    return _get_status_code_str(apm_reason_list, sizeof(apm_reason_list)/sizeof(apm_reason_list[0]), status_code);
+}
+
+static int bl_rx_sm_connect_ind(struct bl_hw *bl_hw,
+                                         struct bl_cmd *cmd,
+                                         struct ipc_e2a_msg *msg)
+{
+    struct sm_connect_ind *ind = (struct sm_connect_ind *)msg->param;
+    struct bl_sta *sta;
+    struct wifi_event_sm_connect_ind ind_new;
+    struct bl_vif *bl_vif = NULL;
+
+    // USER_UNUSED(index);
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    bl_os_printf("[RX] Connection Status\r\n");
+    bl_os_printf("[RX]   status_code %u\r\n", ind->status_code);
+    bl_os_printf("[RX]   reason_code %u\r\n", ind->reason_code);
+    bl_os_printf("[RX]   connect result: %s\r\n", wifi_mgmr_get_sm_status_code_str(ind->status_code));
+    bl_os_printf("[RX]   MAC %02X:%02X:%02X:%02X:%02X:%02X\r\n",
+            ind->bssid.array[0],
+            ind->bssid.array[1],
+            ind->bssid.array[2],
+            ind->bssid.array[3],
+            ind->bssid.array[4],
+            ind->bssid.array[5]
+    );
+    bl_os_printf("[RX]   vif_idx %u\r\n", ind->vif_idx);
+    bl_os_printf("[RX]   ap_idx %u\r\n", ind->ap_idx);
+    bl_os_printf("[RX]   ch_idx %u\r\n", ind->ch_idx);
+    bl_os_printf("[RX]   qos %u\r\n", ind->qos);
+    bl_os_printf("[RX]   acm %u\r\n", ind->acm);
+    bl_os_printf("[RX]   assoc_req_ie_len %u\r\n", ind->assoc_req_ie_len);
+    bl_os_printf("[RX]   assoc_rsp_ie_len %u\r\n", ind->assoc_rsp_ie_len);
+    bl_os_printf("[RX]   aid %u\r\n", ind->aid);
+    bl_os_printf("[RX]   band %u\r\n", ind->band);
+    bl_os_printf("[RX]   center_freq %u\r\n", ind->center_freq);
+    bl_os_printf("[RX]   width %u\r\n", ind->width);
+    bl_os_printf("[RX]   center_freq1 %u\r\n", (unsigned int)ind->center_freq1);
+    bl_os_printf("[RX]   center_freq2 %u\r\n", (unsigned int)ind->center_freq2);
+    bl_os_printf("[RX]   tlv_ptr first %p\r\n", ind->connect_diagnose.first);
+
+    if (0 == ind->status_code) {
+        bl_hw->sta_idx = ind->ap_idx;
+        bl_hw->is_up = 1;
+        sta = &(bl_hw->sta_table[bl_hw->sta_idx]);
+        sta->qos = ind->qos;
+    } else {
+        bl_hw->is_up = 0;
+    }
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+
+    memset(&ind_new, 0, sizeof(ind_new));
+    ind_new.status_code = ind->status_code;
+    ind_new.reason_code = ind->reason_code;
+    ind_new.bssid[0] = ind->bssid.array[0];
+    ind_new.bssid[1] = ind->bssid.array[1];
+    ind_new.bssid[2] = ind->bssid.array[2];
+    ind_new.bssid[3] = ind->bssid.array[3];
+    ind_new.bssid[4] = ind->bssid.array[4];
+    ind_new.bssid[5] = ind->bssid.array[5];
+    ind_new.vif_idx = ind->vif_idx;
+    ind_new.ap_idx = ind->ap_idx;
+    ind_new.ch_idx = ind->ch_idx;
+    ind_new.qos = ind->qos;
+    ind_new.aid = ind->aid;
+    ind_new.band = ind->band;
+    ind_new.center_freq = ind->center_freq;
+    ind_new.width = ind->width;
+    ind_new.center_freq1 = ind->center_freq1;
+    ind_new.center_freq2 = ind->center_freq2;
+    ind_new.connect_diagnose = ind->connect_diagnose;
+
+    if (cb_sm_connect_ind) {
+        cb_sm_connect_ind(cb_sm_connect_ind_env, &ind_new);
+    }
+
+    if (ind->status_code) {
+        /*empty here*/
+        //XXX no netif_set_link_down here?
+    } else {
+        #if 0
+        bl_vif = &(bl_hw->vif_table[ind->vif_idx]);
+        if (bl_vif && bl_vif->dev) {
+            netifapi_netif_set_link_up(bl_vif->dev);
+            netifapi_netif_set_default(bl_vif->dev);
+#ifdef BL602_MATTER_SUPPORT
+            netif_create_ip6_linklocal_address(bl_vif->dev, 1);
+            bl_vif->dev->ip6_autoconfig_enabled = 1;
+#endif
+        } else {
+            bl_os_printf("[RX]  -------- CRITICAL when check netif. ptr is %p:%p\r\n",
+                    bl_vif,
+                    bl_vif ? bl_vif->dev : NULL
+            );
+        }
+        #endif
+    }
+    return 0;
+}
+
+static int bl_rx_sm_disconnect_ind(struct bl_hw *bl_hw,
+                                            struct bl_cmd *cmd,
+                                            struct ipc_e2a_msg *msg)
+{
+    struct sm_disconnect_ind *ind  = (struct sm_disconnect_ind*)msg->param;
+    struct wifi_event_sm_disconnect_ind ind_new;
+    struct bl_vif *bl_vif = NULL;
+    ip4_addr_t addr_any;
+
+    RWNX_DBG(RWNX_FN_ENTRY_STR);
+
+    addr_any.addr = inet_addr("0.0.0.0");
+    bl_os_printf("[RX]   sm_disconnect_ind\r\n"
+              "       status_code %u\r\n"
+              "       802.11 reason_code %u\r\n", ind->status_code, ind->reason_code);
+    bl_os_printf("[RX]   disconnect reason: %s\r\n", wifi_mgmr_get_sm_status_code_str(ind->status_code));
+    bl_os_printf("[RX]   vif_idx %u\r\n", ind->vif_idx);
+    bl_os_printf("[RX]   ft_over_ds %u\r\n", ind->ft_over_ds);
+    bl_os_printf("[RX]   tlv_ptr first %p\r\n", ind->connect_diagnose.first);
+
+    if (cb_sm_disconnect_ind) {
+        memset(&ind_new, 0, sizeof(ind_new));
+        ind_new.status_code = ind->status_code;
+        ind_new.reason_code = ind->reason_code;
+        ind_new.vif_idx = ind->vif_idx;
+        ind_new.ft_over_ds = ind->ft_over_ds;
+        ind_new.connect_diagnose = ind->connect_diagnose;
+        cb_sm_disconnect_ind(cb_sm_disconnect_ind_env, &ind_new);
+    }
+
+    //TODO check vif_idx valid?
+    bl_vif = &(bl_hw->vif_table[ind->vif_idx]);
+    if (bl_vif && bl_vif->dev) {
+        netifapi_netif_set_link_down(bl_vif->dev);
+        netifapi_netif_set_addr(bl_vif->dev, &addr_any, &addr_any, &addr_any);
+    }
+    RWNX_DBG(RWNX_FN_LEAVE_STR);
+    return 0;
+}
+
+const static msg_cb_fct sm_hdlrs[MSG_I(SM_MAX)] = {
+    [MSG_I(SM_CONNECT_IND)]    = bl_rx_sm_connect_ind,
+    [MSG_I(SM_DISCONNECT_IND)] = bl_rx_sm_disconnect_ind,
+};
+
+static int bl_rx_apm_sta_add_ind(struct bl_hw *bl_hw, struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    struct apm_sta_add_ind *ind = (struct apm_sta_add_ind*)msg->param;
+    struct bl_sta *sta;
+
+    bl_os_printf("[WF] APM_STA_ADD_IND\r\n");
+    bl_os_printf("[WF]    flags %08X\r\n", (unsigned int)ind->flags);
+    bl_os_printf("[WF]    MAC %02X:%02X:%02X:%02X:%02X:%02X\r\n",
+            ind->sta_addr.array[0] & 0xFF,
+            ind->sta_addr.array[1] & 0xFF,
+            ind->sta_addr.array[2] & 0xFF,
+            ind->sta_addr.array[3] & 0xFF,
+            ind->sta_addr.array[4] & 0xFF,
+            ind->sta_addr.array[5] & 0xFF
+    );
+    bl_os_log_info("[WF]    tsflo: 0x%lx\r\n", ind->tsflo);
+    bl_os_log_info("[WF]    tsfhi: 0x%lx\r\n", ind->tsfhi);
+    bl_os_log_info("[WF]    rssi: %d\r\n", ind->rssi);
+    bl_os_log_info("[WF]    data rate: 0x%x\r\n", ind->data_rate);
+
+    bl_os_printf("[WF]    vif_idx %u\r\n", ind->vif_idx);
+    bl_os_printf("[WF]    sta_idx %u\r\n", ind->sta_idx);
+    if (ind->sta_idx < sizeof(bl_hw->sta_table)/sizeof(bl_hw->sta_table[0])) {
+        sta = &(bl_hw->sta_table[ind->sta_idx]);
+        if (sta->is_used) {
+            bl_os_log_info("-------------------------Warning: sta_idx already used: %d\r\n", ind->sta_idx);
+        }
+        memcpy(sta->sta_addr.array, ind->sta_addr.array, 6);
+        sta->sta_idx = ind->sta_idx;
+        sta->vif_idx = ind->vif_idx;
+        sta->is_used = 1;
+        sta->rssi = ind->rssi;
+        sta->tsflo = ind->tsflo;
+        sta->tsfhi = ind->tsfhi;
+        sta->data_rate = ind->data_rate;
+    } else {
+        bl_os_printf("[WF]    ------ Potential illegal sta_idx\r\n");
+    }
+    bl_os_event_notify(CODE_WIFI_ON_AP_STA_ADD, ind->sta_idx);
+
+    return 0;
+}
+
+static int bl_rx_apm_sta_del_ind(struct bl_hw *bl_hw, struct bl_cmd *cmd, struct ipc_e2a_msg *msg)
+{
+    struct apm_sta_del_ind *ind = (struct apm_sta_del_ind*)msg->param;
+    struct bl_sta *sta;
+
+    bl_os_printf("[WF] APM_STA_DEL_IND\r\n");
+    bl_os_printf("[WF]    sta_idx %u\r\n", ind->sta_idx);
+    bl_os_printf("[WF]    statuts_code %u\r\n", ind->status_code);
+    bl_os_printf("[WF]    reason_code %u\r\n", ind->reason_code);
+    bl_os_printf("[RX]    disconnect reason: %s\r\n", wifi_mgmr_get_apm_status_code_str(ind->status_code));
+
+    if (ind->sta_idx < sizeof(bl_hw->sta_table)/sizeof(bl_hw->sta_table[0])) {
+        sta = &(bl_hw->sta_table[ind->sta_idx]);
+        if (0 == sta->is_used) {
+            bl_os_log_info("[WF]    -------------------------Warning: sta_idx already empty: %d\r\n", ind->sta_idx);
+        }
+        sta->is_used = 0;
+    } else {
+        bl_os_printf("[WF]    --------- Potential illegal sta_idx\r\n");
+    }
+    bl_os_event_notify(CODE_WIFI_ON_AP_STA_DEL, ind->sta_idx);
+
+    return 0;
+}
+
+const static msg_cb_fct apm_hdlrs[MSG_I(APM_MAX)] = {
+    [MSG_I(APM_STA_ADD_IND)] = bl_rx_apm_sta_add_ind,
+    [MSG_I(APM_STA_DEL_IND)] = bl_rx_apm_sta_del_ind,
+};
+
+const static msg_cb_fct cfg_hdlrs[MSG_I(CFG_MAX)] = {
+};
+const static msg_cb_fct *msg_hdlrs[] = {
+    [TASK_MM]    = mm_hdlrs,
+    [TASK_SCANU] = scan_hdlrs,
+    [TASK_ME]    = me_hdlrs,
+    [TASK_SM]    = sm_hdlrs,
+    [TASK_APM]   = apm_hdlrs,
+    [TASK_CFG]  =  cfg_hdlrs,
+};
+
+void bl_rx_handle_msg(struct bl_hw *bl_hw, struct ipc_e2a_msg *msg)
+{
+    //FIXME potential Array index overflow
+    bl_hw->cmd_mgr.msgind(&bl_hw->cmd_mgr, msg, msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]);
+}
+
+void bl_rx_e2a_handler(void *arg)
+{
+    struct ipc_e2a_msg *msg = (struct ipc_e2a_msg*)arg;
+
+    //FIXME potential Array index overflow
+    wifi_hw.cmd_mgr.msgind(&wifi_hw.cmd_mgr, msg, msg_hdlrs[MSG_T(msg->id)][MSG_I(msg->id)]);
+}
+
+void bl_rx_pkt_cb(uint8_t *pkt, int len, void *pkt_wrap, bl_rx_info_t *info)
+{
+    if (cb_pkt) {
+        cb_pkt(cb_pkt_env, pkt, len, info);
+    }
+    if (cb_pkt_adv) {
+        cb_pkt_adv(cb_pkt_env, pkt_wrap, info);
+    }
+}

+ 199 - 0
network/wifi_manager/bl60x_wifi_driver/bl_rx.h

@@ -0,0 +1,199 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_rx.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#ifndef _RWNX_RX_H_
+#define _RWNX_RX_H_
+#include "bl_defs.h"
+#include "lmac_types.h"
+#include <wifi_mgmr_ext.h>
+
+enum rx_status_bits
+{
+    /// The buffer can be forwarded to the networking stack
+    RX_STAT_FORWARD = 1 << 0,
+    /// A new buffer has to be allocated
+    RX_STAT_ALLOC = 1 << 1,
+    /// The buffer has to be deleted
+    RX_STAT_DELETE = 1 << 2,
+    /// The length of the buffer has to be updated
+    RX_STAT_LEN_UPDATE = 1 << 3,
+    /// The length in the Ethernet header has to be updated
+    RX_STAT_ETH_LEN_UPDATE = 1 << 4,
+    /// Simple copy
+    RX_STAT_COPY = 1 << 5,
+};
+
+#define BL_RX_STATUS_AMSDU (1 << 0)
+// XXX Value must not conflict with PBUF_FLAG_PUSH, etc in pbuf.h
+#define PBUF_FLAG_AMSDU 0x80U
+
+/*
+ * Decryption status subfields.
+ * {
+ */
+#define RWNX_RX_HD_DECR_UNENC           0 // Frame unencrypted
+#define RWNX_RX_HD_DECR_ICVFAIL         1 // WEP/TKIP ICV failure
+#define RWNX_RX_HD_DECR_CCMPFAIL        2 // CCMP failure
+#define RWNX_RX_HD_DECR_AMSDUDISCARD    3 // A-MSDU discarded at HW
+#define RWNX_RX_HD_DECR_NULLKEY         4 // NULL key found
+#define RWNX_RX_HD_DECR_WEPSUCCESS      5 // Security type WEP
+#define RWNX_RX_HD_DECR_TKIPSUCCESS     6 // Security type TKIP
+#define RWNX_RX_HD_DECR_CCMPSUCCESS     7 // Security type CCMP
+// @}
+
+struct hw_vect {
+    /** Total length for the MPDU transfer */
+    u32 len                   :16;
+
+    u32 reserved              : 8;
+
+    /** AMPDU Status Information */
+    u32 mpdu_cnt              : 6;
+    u32 ampdu_cnt             : 2;
+
+
+    /** TSF Low */
+    __le32 tsf_lo;
+    /** TSF High */
+    __le32 tsf_hi;
+
+    /** Receive Vector 1a */
+    u32    leg_length         :12;
+    u32    leg_rate           : 4;
+    u32    ht_length          :16;
+
+    /** Receive Vector 1b */
+    u32    _ht_length         : 4; // FIXME
+    u32    short_gi           : 1;
+    u32    stbc               : 2;
+    u32    smoothing          : 1;
+    u32    mcs                : 7;
+    u32    pre_type           : 1;
+    u32    format_mod         : 3;
+    u32    ch_bw              : 2;
+    u32    n_sts              : 3;
+    u32    lsig_valid         : 1;
+    u32    sounding           : 1;
+    u32    num_extn_ss        : 2;
+    u32    aggregation        : 1;
+    u32    fec_coding         : 1;
+    u32    dyn_bw             : 1;
+    u32    doze_not_allowed   : 1;
+
+    /** Receive Vector 1c */
+    u32    antenna_set        : 8;
+    u32    partial_aid        : 9;
+    u32    group_id           : 6;
+    u32    reserved_1c        : 1;
+    s32    rssi1              : 8;
+
+    /** Receive Vector 1d */
+    s32    rssi2              : 8;
+    s32    rssi3              : 8;
+    s32    rssi4              : 8;
+    u32    reserved_1d        : 8;
+
+    /** Receive Vector 2a */
+    u32    rcpi               : 8;
+    u32    evm1               : 8;
+    u32    evm2               : 8;
+    u32    evm3               : 8;
+
+    /** Receive Vector 2b */
+    u32    evm4               : 8;
+    u32    reserved2b_1       : 8;
+    u32    reserved2b_2       : 8;
+    u32    reserved2b_3       : 8;
+
+    /** Status **/
+    u32    rx_vect2_valid     : 1;
+    u32    resp_frame         : 1;
+    /** Decryption Status */
+    u32    decr_status        : 3;
+    u32    rx_fifo_oflow      : 1;
+
+    /** Frame Unsuccessful */
+    u32    undef_err          : 1;
+    u32    phy_err            : 1;
+    u32    fcs_err            : 1;
+    u32    addr_mismatch      : 1;
+    u32    ga_frame           : 1;
+    u32    current_ac         : 2;
+
+    u32    frm_successful_rx  : 1;
+    /** Descriptor Done  */
+    u32    desc_done_rx       : 1;
+    /** Key Storage RAM Index */
+    u32    key_sram_index     : 10;
+    /** Key Storage RAM Index Valid */
+    u32    key_sram_v         : 1;
+    u32    type               : 2;
+    u32    subtype            : 4;
+};
+
+struct hw_rxhdr {
+    /** RX vector */
+    struct hw_vect hwvect;
+
+    /** PHY channel information 1 */
+    u32    phy_band           : 8;
+    u32    phy_channel_type   : 8;
+    u32    phy_prim20_freq    : 16;
+    /** PHY channel information 2 */
+    u32    phy_center1_freq   : 16;
+    u32    phy_center2_freq   : 16;
+    /** RX flags */
+    u32    flags_is_amsdu     : 1;
+    u32    flags_is_80211_mpdu: 1;
+    u32    flags_is_4addr     : 1;
+    u32    flags_new_peer     : 1;
+    u32    flags_user_prio    : 3;
+    u32    flags_rsvd0        : 1;
+    u32    flags_vif_idx      : 8;    // 0xFF if invalid VIF index
+    u32    flags_sta_idx      : 8;    // 0xFF if invalid STA index
+    u32    flags_dst_idx      : 8;    // 0xFF if unknown destination STA
+    /** Pattern indicating if the buffer is available for the driver */
+    u32    pattern;
+    u32    payl_offset;
+    u32    reserved_pad[2];
+    /*XXX wild buffer load for platform overwrite*/
+    u32    wild[8];
+};
+
+struct reason_code {
+    uint16_t reason_code;
+    const char *action;
+};
+
+typedef struct
+{
+    u16 noRsn      : 1;
+    u16 wepStatic  : 1;
+    u16 wepDynamic : 1;
+    u16 wpa        : 1;
+    u16 wpaNone    : 1;
+    u16 wpa2       : 1;
+    u16 cckm       : 1;
+    u16 wapi       : 1;
+    u16 wpa3       : 1;
+    u16 rsvd       : 7;
+
+} SecurityMode_t;
+
+extern const u8 legrates_lut[];
+
+int bl_txdatacfm(void *pthis, void *hostid);
+void bl_prim_tbtt_ind(void *pthis);
+void bl_sec_tbtt_ind(void *pthis);
+void bl_rx_handle_msg(struct bl_hw *bl_hw, struct ipc_e2a_msg *msg);
+void bl_rx_pkt_cb(uint8_t *pkt, int len, void *pkt_wrap, bl_rx_info_t *info);
+const char* wifi_mgmr_get_sm_status_code_str(uint16_t status_code);
+
+#endif /* _RWNX_RX_H_ */

+ 25 - 0
network/wifi_manager/bl60x_wifi_driver/bl_strs.h

@@ -0,0 +1,25 @@
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_strs.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+
+#ifndef _RWNX_STRS_H_
+#define _RWNX_STRS_H_
+
+#include "lmac_msg.h"
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define RWNX_ID2STR(tag) (((MSG_T(tag) < ARRAY_SIZE(bl_id2str)) &&        \
+                           (bl_id2str[MSG_T(tag)]) &&          \
+                           ((bl_id2str[MSG_T(tag)])[MSG_I(tag)])) ?   \
+                          (bl_id2str[MSG_T(tag)])[MSG_I(tag)] : "unknown")
+
+extern const char *const *bl_id2str[TASK_LAST_EMB + 1];
+
+#endif /* _RWNX_STRS_H_ */

+ 303 - 0
network/wifi_manager/bl60x_wifi_driver/bl_tx.c

@@ -0,0 +1,303 @@
+/**
+ ****************************************************************************************
+ *
+ * @file bl_tx.c
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <netif/etharp.h>
+#include <bl_os_private.h>
+
+#include "bl_tx.h"
+#include "bl_irqs.h"
+#include "bl_utils.h"
+
+
+struct utils_list tx_list_bl;
+
+int internel_cal_size_tx_hdr = sizeof(struct bl_txhdr);
+
+extern struct bl_hw wifi_hw;
+static struct bl_hw *bl_hw_static = &wifi_hw;
+
+#ifndef ARRAY_LEN
+#define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0]))
+#endif
+
+#if defined(CFG_CHIP_BL808) || defined(CFG_CHIP_BL606P)
+void bl_tx_push(struct bl_hw *bl_hw, struct bl_txhdr *txhdr)
+{
+    volatile struct hostdesc *host;
+    uint32_t* p = txhdr->p;
+    uint32_t len;
+
+    volatile struct txdesc_host *txdesc_host;
+
+    //host = &(ipc_host_txdesc_get(bl_hw->ipc_env)->host);
+    txdesc_host = ipc_host_txdesc_get(bl_hw->ipc_env);
+    ASSERT_ERR(txdesc_host);//TODO protect when host is NULL
+    host = &(txdesc_host->host);
+
+    memcpy((void *)host, &txhdr->host, sizeof(*host));
+
+    len = 0;
+    for (size_t i = 0; i < ARRAY_LEN(host->pbuf_chained_len); ++i) {
+        if (host->pbuf_chained_len[i] == 0) {
+            break;
+        }
+        memcpy((uint8_t *)txdesc_host->eth_packet + len, (void *)host->pbuf_chained_ptr[i], host->pbuf_chained_len[i]);
+        len += host->pbuf_chained_len[i];
+
+        host->pbuf_chained_ptr[i] = 0;
+        host->pbuf_chained_len[i] = 0;
+    }
+    host->pbuf_chained_ptr[0] = (uint32_t)(&(txdesc_host->eth_packet[0]));
+    host->pbuf_chained_len[0] = len;
+
+    ipc_host_txdesc_push(bl_hw->ipc_env, p);
+#ifdef CFG_BL_STATISTIC
+    bl_hw->stats.cfm_balance++;
+#endif
+}
+#else
+void bl_tx_push(struct bl_hw *bl_hw, struct bl_txhdr *txhdr)
+{
+    volatile struct hostdesc *host;
+    uint32_t* p = txhdr->p;
+    volatile struct txdesc_host *txdesc_host;
+
+    txdesc_host = ipc_host_txdesc_get(bl_hw->ipc_env);
+    ASSERT_ERR(txdesc_host);//TODO protect when host is NULL
+    host = &(txdesc_host->host);
+
+    memcpy((void *)host, &txhdr->host, sizeof(*host));
+
+    ipc_host_txdesc_push(bl_hw->ipc_env, p);
+#ifdef CFG_BL_STATISTIC
+    bl_hw->stats.cfm_balance++;
+#endif
+}
+#endif
+
+#define TXHDR_HODLER_LEN (8)
+#define TXHDR_HODLER_MSK (0x7)
+struct bl_txhdr *(txhdr_hodler[8]);
+uint32_t txhdr_pos_r = 0;
+uint32_t txhdr_pos_w = 0;
+
+void bl_tx_resend()
+{
+    bl_os_enter_critical();
+    while (txhdr_pos_r != txhdr_pos_w) {
+        if (NULL == ipc_host_txdesc_get(bl_hw_static->ipc_env)) {
+            break;
+        }
+        txhdr_hodler[txhdr_pos_r & TXHDR_HODLER_MSK]->status.value = 0;
+#if 0
+        bl_os_printf("Push back %p\r\n", txhdr_hodler[txhdr_pos_r & TXHDR_HODLER_MSK]);
+#endif
+        bl_tx_push(bl_hw_static, txhdr_hodler[txhdr_pos_r & TXHDR_HODLER_MSK]);
+        txhdr_pos_r++;
+    }
+    bl_os_exit_critical();
+}
+
+void bl_tx_try_flush()
+{
+    struct bl_txhdr *txhdr;
+
+    bl_os_enter_critical();
+    while (ipc_host_txdesc_get(bl_hw_static->ipc_env)) {
+        txhdr = (struct bl_txhdr*)utils_list_pop_front(&tx_list_bl);
+        if (NULL == txhdr) {
+            break;
+        }
+        bl_tx_push(bl_hw_static, txhdr);
+    }
+    bl_os_exit_critical();
+}
+
+int bl_txdatacfm(void *pthis, void *host_id)
+{
+#define RETRY_LIMIT_REACHED_BIT (1 << 16)
+    struct pbuf *p = (struct pbuf*)host_id;
+    struct bl_txhdr *txhdr;
+    union bl_hw_txstatus bl_txst;
+
+    txhdr = (struct bl_txhdr*)(((uint32_t)p->payload) + RWNX_HWTXHDR_ALIGN_PADS((uint32_t)p->payload));
+
+
+    /* Read status in the TX control header */
+    bl_txst = txhdr->status;
+
+    if (bl_txst.value == 0) {
+        return -1;
+    }
+    if (bl_txst.value & RETRY_LIMIT_REACHED_BIT) {
+#if 0
+        bl_os_printf("TX STATUS %08lX", bl_txst.value);
+        bl_os_printf(" Retry reached %p:%lu:%lu", txhdr, txhdr_pos_r, txhdr_pos_w);
+#endif
+        /*we don't pbuf_free here, because we will resend this packet*/
+        if (((txhdr_pos_w + 1) & TXHDR_HODLER_MSK) != (txhdr_pos_r & TXHDR_HODLER_MSK)) {
+            bl_os_log_warn(" push back\r\n");
+            txhdr_hodler[txhdr_pos_w & TXHDR_HODLER_MSK] = txhdr;
+            txhdr_pos_w++;
+        } else {
+            bl_os_log_warn(" NOT push back when no mem\r\n");
+            pbuf_free(p);
+        }
+    } else {
+        pbuf_free(p);
+        return 1;
+    }
+
+    return 0;
+}
+
+#if 0
+uint32_t drop_ack_now = 0;
+uint32_t droped_ack;
+#endif
+
+err_t bl_output(struct bl_hw *bl_hw, struct netif *netif, struct pbuf *p, int is_sta, struct bl_custom_tx_cfm *custom_cfm)
+{
+    struct bl_txhdr *txhdr;
+    struct pbuf *q;
+    uint32_t *link_header;
+    uint32_t *eth_header;
+    struct ethhdr *eth;
+    struct hostdesc *host;
+    int loop = 0;
+    u8 tid;
+    uint16_t packet_len;
+    struct bl_sta *sta;
+
+    eth_header = (uint32_t*)p->payload;
+    eth = (struct ethhdr *)(eth_header);
+
+    if (NULL == bl_hw) {		// || (0 == (NETIF_FLAG_LINK_UP & netif->flags) && eth->h_proto != 0x8e88)) {//TODO avoid call output when Wi-Fi is not ready
+        bl_os_printf("[TX] wifi is down, return now\r\n");
+        return ERR_CONN;
+    }
+#if 0
+    if (drop_ack_now) {
+        drop_ack_now++;
+        if (drop_ack_now & 0x02) {
+            droped_ack++;
+            return ERR_OK;
+        }
+    }
+#endif
+
+    bl_hw_static = bl_hw;
+    packet_len = p->tot_len;
+
+    /*Make room in the header for tx*/
+    if (pbuf_header(p, PBUF_LINK_ENCAPSULATION_HLEN)) {
+        bl_os_printf("[TX] Reserve room failed for header\r\n");
+        return ERR_IF;
+    }
+    /*Use aligned link_header*/
+    link_header = (uint32_t*)(((uint32_t)p->payload) + RWNX_HWTXHDR_ALIGN_PADS((uint32_t)p->payload));
+    if (16 + sizeof(struct bl_txhdr) + RWNX_HWTXHDR_ALIGN_PADS((uint32_t)p->payload) > PBUF_LINK_ENCAPSULATION_HLEN) {
+        bl_os_printf("link_header size is %ld vs header %u\r\n",
+                sizeof(struct bl_txhdr) + RWNX_HWTXHDR_ALIGN_PADS((uint32_t)p->payload),
+                PBUF_LINK_ENCAPSULATION_HLEN
+        );
+    }
+
+    tid = 0;//XXX set TID to 0 for quick test purpose
+
+    txhdr = (struct bl_txhdr *)(link_header);
+    memset(txhdr, 0, sizeof(struct bl_txhdr));
+    host = &(txhdr->host);
+
+    txhdr->p         = (uint32_t*)p;//XXX pattention to this filed
+    // Fill-in the descriptor
+    memcpy(&host->eth_dest_addr, eth->h_dest, ETH_ALEN);
+    memcpy(&host->eth_src_addr, eth->h_source, ETH_ALEN);
+    host->pbuf_addr = (uint32_t)p;
+    host->ethertype = eth->h_proto;
+    host->vif_idx = is_sta; // vif_idx field is used as is-sta flag here, fixed in ipc_emb
+    host->flags = 0;
+    host->packet_len = packet_len - sizeof(*eth);
+
+    (void)sta;
+    (void)tid;
+    /*
+    // fixed in ipc_emb
+    if (is_sta) {
+        host->staid = bl_hw->sta_idx;
+        sta = &(bl_hw->sta_table[bl_hw->sta_idx]);
+        if(sta->qos) {
+            tid = 0;//XXX set TID to 0 for quick test purpose
+        } else {
+            tid = 0xFF;
+        }
+
+    } else {
+        //AP mode need update whether support qos
+        host->staid = bl_utils_idx_lookup(bl_hw, eth->h_dest);
+    }
+    host->tid = tid;
+    */
+
+    loop = 0;
+    for (q = p; q != NULL; q = q->next) {
+        if (0 == loop) {
+            /*The first pbuf*/
+            host->pbuf_chained_ptr[loop] = (uint32_t)(((uint8_t*)q->payload) + sizeof(*eth)) + PBUF_LINK_ENCAPSULATION_HLEN;//eth header is skipped in the header
+            host->pbuf_chained_len[loop] = q->len - sizeof(*eth) - PBUF_LINK_ENCAPSULATION_HLEN;//eth header is skipped in the header
+        } else {
+            /*Chained pbuf after*/
+            if (loop >= 4) {
+                /*exceed the limit for pbuf chained*/
+                bl_os_printf("[TX] [PBUF] Please fix for bigger chained pbuf, total_len %d\r\n",
+                        p->tot_len
+                );
+            }
+            host->pbuf_chained_ptr[loop] = (uint32_t)(q->payload);
+            host->pbuf_chained_len[loop] = q->len;
+#if 0
+            bl_os_printf("[%d] ptr %p, size %lu\r\n",
+                    0,
+                    (void*)host->pbuf_chained_ptr[0],
+                    host->pbuf_chained_len[0]
+            );
+            bl_os_printf("[%d] ptr %p, size %lu\r\n",
+                    loop,
+                    (void*)host->pbuf_chained_ptr[loop],
+                    host->pbuf_chained_len[loop]
+            );
+#endif
+        }
+        loop++;
+    }
+    if (loop > 2) {
+        bl_os_printf("[TX] [LOOP] Chain Used %d\r\n", loop);
+    }
+
+    txhdr->status.value = 0;
+    /* Fill-in TX descriptor */
+    host->packet_addr = (uint32_t)(0x11111111);//FIXME we use this magic for unvaild packet_addr
+    host->status_addr = (uint32_t)(&(txhdr->status));
+
+    if (custom_cfm) {
+        memcpy(&txhdr->custom_cfm, custom_cfm, sizeof(*custom_cfm));
+    }
+    /*Ref this pbuf to avoid pbuf release*/
+    pbuf_ref(p);
+
+    bl_os_enter_critical();
+    utils_list_push_back(&tx_list_bl, &(txhdr->item));
+    bl_os_exit_critical();
+
+    bl_irq_handler();
+
+    return ERR_OK;
+}

+ 56 - 0
network/wifi_manager/bl60x_wifi_driver/bl_tx.h

@@ -0,0 +1,56 @@
+#ifndef __RWNX_TX_H__
+#define __RWNX_TX_H__
+#include <lwip/opt.h>
+#include <lwip/mem.h>
+#include <utils_list.h>
+
+#include "lmac_types.h"
+#include "ipc_shared.h"
+#include "bl_utils.h"
+
+/**
+ ****************************************************************************************
+ *
+ * @file bl_tx.h
+ * Copyright (C) Bouffalo Lab 2016-2018
+ *
+ ****************************************************************************************
+ */
+
+typedef void (*bl_custom_tx_callback_t)(void *cb_arg, bool tx_ok);
+
+struct bl_custom_tx_cfm {
+    bl_custom_tx_callback_t cb;
+    void *cb_arg;
+};
+
+/**
+ * struct bl_txhdr - Stucture to control transimission of packet
+ * (Added in skb headroom)
+ *
+ * @sw_hdr: Information from driver
+ * @hw_hdr: Information for/from hardware
+ */
+union bl_hw_txstatus {
+    struct {
+        u32 tx_done            : 1;
+        u32 retry_required     : 1;
+        u32 sw_retry_required  : 1;
+        u32 reserved           :29;
+    };
+    u32 value;
+};
+struct bl_txhdr {
+    struct utils_list_hdr item;
+    union bl_hw_txstatus status;
+    uint32_t *p;
+    struct hostdesc host;
+    struct bl_custom_tx_cfm custom_cfm;
+};
+
+err_t bl_output(struct bl_hw *bl_hw, struct netif *netif, struct pbuf *p, int is_sta, struct bl_custom_tx_cfm *custom_cfm);
+int bl_wifi_eth_tx(struct pbuf *p, bool is_sta, struct bl_custom_tx_cfm *custom_cfm);
+int bl_txdatacfm(void *pthis, void *host_id);
+void bl_tx_try_flush();
+void bl_irq_handler();
+#endif

部分文件因文件數量過多而無法顯示