From ef2be423d2c184230733ce5811869943301e0b73 Mon Sep 17 00:00:00 2001 From: fujr Date: Tue, 23 Jul 2024 15:21:43 +0800 Subject: [PATCH] remove unrelated package --- README.md | 63 - fibocom-dial/Makefile | 26 - fibocom-dial/src/GobiNetCM.c | 275 -- fibocom-dial/src/MPQCTL.h | 363 -- fibocom-dial/src/MPQMI.h | 287 -- fibocom-dial/src/MPQMUX.c | 437 -- fibocom-dial/src/MPQMUX.h | 3671 -------------- fibocom-dial/src/Makefile | 42 - fibocom-dial/src/QMIThread.c | 2551 ---------- fibocom-dial/src/QMIThread.h | 260 - fibocom-dial/src/QmiWwanCM.c | 426 -- fibocom-dial/src/default.script | 63 - fibocom-dial/src/fibo_qmimsg_server.c | 1331 ----- fibocom-dial/src/libmnl/README | 28 - fibocom-dial/src/libmnl/attr.c | 722 --- fibocom-dial/src/libmnl/callback.c | 167 - fibocom-dial/src/libmnl/dhcp/dhcp.h | 5 - fibocom-dial/src/libmnl/dhcp/dhcpclient.c | 515 -- fibocom-dial/src/libmnl/dhcp/dhcpmsg.c | 100 - fibocom-dial/src/libmnl/dhcp/dhcpmsg.h | 106 - fibocom-dial/src/libmnl/dhcp/packet.c | 247 - fibocom-dial/src/libmnl/dhcp/packet.h | 25 - fibocom-dial/src/libmnl/ifutils.c | 748 --- fibocom-dial/src/libmnl/ifutils.h | 53 - fibocom-dial/src/libmnl/libmnl.h | 202 - fibocom-dial/src/libmnl/nlmsg.c | 556 --- fibocom-dial/src/libmnl/socket.c | 351 -- fibocom-dial/src/main.c | 1770 ------- fibocom-dial/src/multi-pdn-manager.c | 1019 ---- fibocom-dial/src/multi-pdn.ini | 67 - fibocom-dial/src/qmap_bridge_mode.c | 438 -- fibocom-dial/src/query_pcie_mode.c | 160 - fibocom-dial/src/query_pcie_mode.h | 17 - fibocom-dial/src/udhcpc.c | 289 -- fibocom-dial/src/udhcpc_netlink.c | 421 -- fibocom-dial/src/util.c | 142 - fibocom-dial/src/util.h | 53 - fibocom_MHI/Makefile | 47 - fibocom_MHI/src/Kconfig | 14 - fibocom_MHI/src/Makefile | 29 - fibocom_MHI/src/controllers/mhi_qcom.c | 683 --- fibocom_MHI/src/controllers/mhi_qcom.h | 92 - fibocom_MHI/src/controllers/mhi_qcom_arm.h | 92 - fibocom_MHI/src/controllers/mhi_qcom_x86.h | 92 - fibocom_MHI/src/core/mhi.h | 891 ---- fibocom_MHI/src/core/mhi_boot.c | 878 ---- fibocom_MHI/src/core/mhi_common.h | 362 -- fibocom_MHI/src/core/mhi_dtr.c | 181 - fibocom_MHI/src/core/mhi_init.c | 1442 ------ fibocom_MHI/src/core/mhi_internal.h | 800 --- fibocom_MHI/src/core/mhi_main.c | 1612 ------ fibocom_MHI/src/core/mhi_pm.c | 1271 ----- fibocom_MHI/src/devices/mhi_netdev.c | 1313 ----- fibocom_MHI/src/devices/mhi_netdev.h | 18 - fibocom_MHI/src/devices/mhi_uci.c | 785 --- fibocom_QMI_WWAN/Makefile | 47 - fibocom_QMI_WWAN/src/Makefile | 38 - fibocom_QMI_WWAN/src/qmi_wwan_f.c | 2534 ---------- luci-app-cpe/Makefile | 34 - luci-app-cpe/luasrc/controller/admin/cpe.lua | 189 - luci-app-cpe/luasrc/model/cbi/cpe/modem.lua | 144 - luci-app-cpe/luasrc/view/cpe/at.htm | 152 - luci-app-cpe/luasrc/view/cpe/net_status.htm | 296 -- luci-app-cpe/po/zh-cn/modem.po | 73 - luci-app-cpe/po/zh_Hans | 1 - luci-app-cpe/root/etc/config/modem | 12 - luci-app-cpe/root/etc/init.d/cpeinit | 7 - luci-app-cpe/root/etc/init.d/modem | 103 - luci-app-cpe/root/etc/uci-defaults/luci-modem | 11 - luci-app-cpe/root/usr/bin/bmask128 | 19 - luci-app-cpe/root/usr/bin/chan2band.sh | 317 -- luci-app-cpe/root/usr/bin/encodemask | 24 - luci-app-cpe/root/usr/bin/jkillall | 9 - luci-app-cpe/root/usr/bin/rsrp2rssi | 21 - luci-app-cpe/root/usr/bin/set_gpio | 18 - luci-app-cpe/root/usr/share/cpe/Fibocom | 285 -- luci-app-cpe/root/usr/share/cpe/Quectel | 507 -- luci-app-cpe/root/usr/share/cpe/SIMCOM | 303 -- luci-app-cpe/root/usr/share/cpe/atcmd.sh | 3 - luci-app-cpe/root/usr/share/cpe/cpedebug | 27 - luci-app-cpe/root/usr/share/cpe/delatcmd.sh | 2 - luci-app-cpe/root/usr/share/cpe/rssi | 418 -- luci-app-gobinetmodem/Makefile | 17 - .../luasrc/controller/gobinetmodem.lua | 9 - .../luasrc/model/cbi/gobinetmodem.lua | 39 - luci-app-gobinetmodem/po/zh-cn/usbmodem.po | 24 - .../root/etc/config/gobinetmodem | 4 - .../root/etc/init.d/gobinetmodem | 80 - .../root/etc/uci-defaults/luci-gobinetmodem | 11 - luci-app-hypermodem/Makefile | 26 - luci-app-hypermodem/README.md | 20 - .../luasrc/controller/hypermodem.lua | 9 - .../luasrc/model/cbi/hypermodem.lua | 67 - luci-app-hypermodem/po/zh-cn/hypermodem.po | 63 - .../root/etc/config/hypermodem | 5 - .../root/etc/init.d/hypermodem | 186 - .../root/etc/uci-defaults/luci-hypermodem | 11 - luci-app-pcimodem/Makefile | 15 - .../luasrc/controller/pcimodem.lua | 9 - .../luasrc/model/cbi/pcimodem.lua | 39 - luci-app-pcimodem/po/zh-cn/pcimodem.po | 24 - luci-app-pcimodem/root/etc/config/pcimodem | 4 - luci-app-pcimodem/root/etc/init.d/pcimodem | 75 - .../root/etc/uci-defaults/luci-pcimodem | 11 - luci-app-sms-tool/LICENSE | 674 --- luci-app-sms-tool/Makefile | 32 - .../luci-static/resources/icons/delsms.png | Bin 9221 -> 0 bytes .../luci-static/resources/icons/delsms2.png | Bin 1365 -> 0 bytes .../luasrc/controller/modem/sms.lua | 242 - .../luasrc/model/cbi/modem/smsconfig.lua | 226 - .../luasrc/view/modem/atcommands.htm | 136 - .../luasrc/view/modem/readsms.htm | 285 -- .../luasrc/view/modem/sendsms.htm | 237 - luci-app-sms-tool/luasrc/view/modem/ussd.htm | 265 - luci-app-sms-tool/po/pl/sms-tool.po | 288 -- luci-app-sms-tool/po/zh-cn/sms-tool.po | 246 - luci-app-sms-tool/root/etc/config/atcmds.user | 28 - .../root/etc/config/phonebook.user | 1 - luci-app-sms-tool/root/etc/config/sms_tool | 14 - luci-app-sms-tool/root/etc/init.d/smsled | 26 - .../root/etc/uci-defaults/set_sms_ports.sh | 23 - .../root/etc/uci-defaults/start-smsled | 7 - luci-app-sms-tool/root/sbin/cronsync.sh | 21 - luci-app-sms-tool/root/sbin/set_sms_ports.sh | 24 - luci-app-sms-tool/root/sbin/smsled-init.sh | 21 - luci-app-sms-tool/root/sbin/smsled.sh | 39 - .../share/rpcd/acl.d/luci-app-sms-tool.json | 24 - luci-app-spdmodem/Makefile | 15 - .../luasrc/controller/spdmodem.lua | 9 - .../luasrc/model/cbi/spdmodem.lua | 39 - luci-app-spdmodem/po/zh-cn/spdmodem.po | 24 - luci-app-spdmodem/root/etc/config/spdmodem | 4 - luci-app-spdmodem/root/etc/init.d/spdmodem | 75 - .../root/etc/uci-defaults/luci-spdmodem | 11 - luci-app-usbmodem/Makefile | 19 - .../luasrc/controller/usbmodem.lua | 9 - .../luasrc/model/cbi/usbmodem.lua | 51 - luci-app-usbmodem/po/zh-cn/usbmodem.po | 24 - luci-app-usbmodem/root/etc/config/usbmodem | 5 - luci-app-usbmodem/root/etc/init.d/usbmodem | 80 - .../root/etc/uci-defaults/luci-usbmodem | 11 - quectel_Gobinet/Makefile | 47 - quectel_Gobinet/src/GobiUSBNet.c | 3202 ------------ quectel_Gobinet/src/Makefile | 43 - quectel_Gobinet/src/QMI.c | 1521 ------ quectel_Gobinet/src/QMI.h | 337 -- quectel_Gobinet/src/QMIDevice.c | 4363 ----------------- quectel_Gobinet/src/QMIDevice.h | 368 -- quectel_Gobinet/src/Readme.txt | 78 - quectel_Gobinet/src/ReleaseNote.txt | 166 - quectel_Gobinet/src/Structs.h | 529 -- quectel_MHI/Makefile | 47 - quectel_MHI/src/Makefile | 34 - quectel_MHI/src/README | 36 - quectel_MHI/src/ReleaseNote.txt | 103 - quectel_MHI/src/controllers/Kconfig | 13 - quectel_MHI/src/controllers/Makefile | 1 - quectel_MHI/src/controllers/mhi_arch_qti.c | 275 -- quectel_MHI/src/controllers/mhi_qcom.c | 715 --- quectel_MHI/src/controllers/mhi_qcom.h | 92 - quectel_MHI/src/controllers/mhi_qti.c | 1306 ----- quectel_MHI/src/controllers/mhi_qti.h | 44 - quectel_MHI/src/core/Makefile | 1 - quectel_MHI/src/core/mhi.h | 908 ---- quectel_MHI/src/core/mhi_boot.c | 860 ---- quectel_MHI/src/core/mhi_dtr.c | 274 -- quectel_MHI/src/core/mhi_init.c | 2773 ----------- quectel_MHI/src/core/mhi_internal.h | 1190 ----- quectel_MHI/src/core/mhi_main.c | 2722 ---------- quectel_MHI/src/core/mhi_pm.c | 1255 ----- quectel_MHI/src/core/mhi_sdx20.h | 362 -- quectel_MHI/src/core/sdx20_mhi.h | 426 -- quectel_MHI/src/devices/Kconfig | 33 - quectel_MHI/src/devices/Makefile | 3 - quectel_MHI/src/devices/mhi_netdev.c | 1063 ---- quectel_MHI/src/devices/mhi_netdev_quectel.c | 3034 ------------ quectel_MHI/src/devices/mhi_satellite.c | 1153 ----- quectel_MHI/src/devices/mhi_uci.c | 981 ---- quectel_MHI/src/devices/rmnet/Kconfig | 13 - quectel_MHI/src/devices/rmnet/Makefile | 11 - quectel_MHI/src/devices/rmnet/rmnet_config.c | 141 - quectel_MHI/src/devices/rmnet/rmnet_config.h | 174 - quectel_MHI/src/devices/rmnet/rmnet_data.c | 1150 ----- .../src/devices/rmnet/rmnet_descriptor.c | 661 --- .../src/devices/rmnet/rmnet_descriptor.h | 146 - .../src/devices/rmnet/rmnet_handlers.c | 374 -- .../src/devices/rmnet/rmnet_handlers.h | 32 - quectel_MHI/src/devices/rmnet/rmnet_map.h | 272 - .../src/devices/rmnet/rmnet_map_command.c | 143 - .../src/devices/rmnet/rmnet_map_data.c | 682 --- quectel_MHI/src/devices/rmnet/rmnet_private.h | 34 - quectel_MHI/src/devices/rmnet/rmnet_trace.h | 257 - quectel_MHI/src/devices/rmnet/rmnet_vnd.c | 382 -- quectel_MHI/src/devices/rmnet/rmnet_vnd.h | 29 - quectel_MHI/src/devices/rmnet_handler.c | 1129 ----- quectel_MHI/src/devices/rmnet_nss.c | 424 -- quectel_MHI/src/log/AT_OVER_PCIE.txt | 31 - quectel_MHI/src/log/MBIM_OVER_PCIE.txt | 145 - quectel_MHI/src/log/QMI_OVER_PCIE.txt | 134 - quectel_MHI/src/log/QXDM_OVER_PCIE.txt | 14 - quectel_SRPD_PCIE/Makefile | 46 - quectel_SRPD_PCIE/src/Makefile | 33 - quectel_SRPD_PCIE/src/include/mdm_ctrl.h | 31 - quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h | 49 - quectel_SRPD_PCIE/src/include/sipa.h | 59 - quectel_SRPD_PCIE/src/include/sipc.h | 1154 ----- .../src/include/sipc_big_to_little.h | 85 - quectel_SRPD_PCIE/src/include/sprd_mpm.h | 184 - .../src/include/sprd_pcie_ep_device.h | 99 - .../src/include/sprd_pcie_resource.h | 107 - quectel_SRPD_PCIE/src/mcd/Kconfig | 7 - quectel_SRPD_PCIE/src/mcd/Makefile | 1 - quectel_SRPD_PCIE/src/mcd/modem_ctrl.c | 814 --- quectel_SRPD_PCIE/src/pcie/Kconfig | 7 - quectel_SRPD_PCIE/src/pcie/Makefile | 6 - .../src/pcie/pcie_client_resource.c | 528 -- .../src/pcie/pcie_host_resource.c | 720 --- quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c | 195 - quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h | 37 - .../src/pcie/sprd_pcie_ep_device.c | 1663 ------- quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c | 126 - quectel_SRPD_PCIE/src/power_manager/Makefile | 1 - .../src/power_manager/power_manager.c | 964 ---- .../src/pwake_function/ipq4019/pcie-qcom.c | 2237 --------- quectel_SRPD_PCIE/src/sipa/Kconfig | 9 - quectel_SRPD_PCIE/src/sipa/Makefile | 6 - quectel_SRPD_PCIE/src/sipa/sipa_core.c | 333 -- quectel_SRPD_PCIE/src/sipa/sipa_core.h | 519 -- quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c | 590 --- quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c | 156 - quectel_SRPD_PCIE/src/sipa/sipa_dummy.c | 583 --- quectel_SRPD_PCIE/src/sipa/sipa_eth.c | 1087 ---- quectel_SRPD_PCIE/src/sipa/sipa_eth.h | 65 - quectel_SRPD_PCIE/src/sipa/sipa_nic.c | 332 -- .../src/sipa/sipa_phy_v0/Makefile | 1 - .../sipa/sipa_phy_v0/sipa_common_fifo_hal.c | 1234 ----- .../src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c | 74 - .../src/sipa/sipa_phy_v0/sipa_fifo_phy.h | 1413 ------ quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c | 674 --- quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c | 556 --- quectel_SRPD_PCIE/src/sipc/Kconfig | 26 - quectel_SRPD_PCIE/src/sipc/Makefile | 6 - quectel_SRPD_PCIE/src/sipc/sblock.c | 1911 -------- quectel_SRPD_PCIE/src/sipc/sblock.h | 173 - quectel_SRPD_PCIE/src/sipc/sbuf.c | 1755 ------- quectel_SRPD_PCIE/src/sipc/sbuf.h | 126 - quectel_SRPD_PCIE/src/sipc/sipc.c | 524 -- quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c | 51 - quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h | 37 - quectel_SRPD_PCIE/src/sipc/sipc_priv.h | 188 - quectel_SRPD_PCIE/src/sipc/smem.c | 559 --- quectel_SRPD_PCIE/src/sipc/smsg.c | 1103 ----- quectel_SRPD_PCIE/src/sipc/spipe.c | 480 -- quectel_SRPD_PCIE/src/sipc/spipe.h | 29 - quectel_SRPD_PCIE/src/sipc/spool.c | 538 -- quectel_SRPD_PCIE/src/sipc/spool.h | 29 - quectel_cm_5G/Makefile | 39 - quectel_cm_5G/files/dhcp | 48 - quectel_cm_5G/files/rmnet.script | 66 - quectel_cm_5G/files/rmnet.sh | 32 - quectel_cm_5G/files/rmnet6.script | 61 - quectel_cm_5G/files/rmnet6.sh | 32 - quectel_cm_5G/files/rmnet_init.sh | 31 - quectel_cm_5G/src/CMakeLists.txt | 36 - quectel_cm_5G/src/GobiNetCM.c | 246 - quectel_cm_5G/src/MPQCTL.h | 390 -- quectel_cm_5G/src/MPQMI.h | 325 -- quectel_cm_5G/src/MPQMUX.c | 477 -- quectel_cm_5G/src/MPQMUX.h | 4273 ---------------- quectel_cm_5G/src/Makefile | 45 - quectel_cm_5G/src/Makefile.am | 22 - quectel_cm_5G/src/NOTICE | 7 - quectel_cm_5G/src/QMIThread.c | 2993 ----------- quectel_cm_5G/src/QMIThread.h | 420 -- quectel_cm_5G/src/QmiWwanCM.c | 459 -- quectel_cm_5G/src/ReleaseNote.txt | 325 -- quectel_cm_5G/src/at_tok.c | 283 -- quectel_cm_5G/src/at_tok.h | 33 - quectel_cm_5G/src/atc.c | 1054 ---- quectel_cm_5G/src/atchannel.c | 1037 ---- quectel_cm_5G/src/atchannel.h | 152 - quectel_cm_5G/src/configure.ac | 48 - quectel_cm_5G/src/default.script | 63 - quectel_cm_5G/src/default.script_ip | 61 - quectel_cm_5G/src/device.c | 768 --- quectel_cm_5G/src/ethtool-copy.h | 1100 ----- quectel_cm_5G/src/log/cdc_mbim.txt | 71 - quectel_cm_5G/src/log/cdc_mbim_vlan.txt | 168 - quectel_cm_5G/src/log/ecm_ncm_rndis.txt | 129 - quectel_cm_5G/src/log/gobinet.txt | 62 - quectel_cm_5G/src/log/gobinet_bridge.txt | 60 - quectel_cm_5G/src/log/gobinet_qmap=1.txt | 45 - .../src/log/gobinet_qmap=1_bridge.txt | 62 - quectel_cm_5G/src/log/gobinet_qmap=4.txt | 146 - .../src/log/gobinet_qmap=4_bridge.txt | 114 - quectel_cm_5G/src/log/pcie_mhi_mbim.txt | 80 - .../src/log/pcie_mhi_mbim_qmap=4.txt | 170 - quectel_cm_5G/src/log/pcie_mhi_qmap=1.txt | 127 - .../src/log/pcie_mhi_qmap=1_bridge.txt | 76 - quectel_cm_5G/src/log/pcie_mhi_qmap=4.txt | 138 - .../src/log/pcie_mhi_qmap=4_bridge.txt | 147 - quectel_cm_5G/src/log/qmi_wwan_q.txt | 65 - quectel_cm_5G/src/log/qmi_wwan_q_bridge.txt | 57 - quectel_cm_5G/src/log/qmi_wwan_q_qmap=1.txt | 54 - .../src/log/qmi_wwan_q_qmap=1_bridge.txt | 86 - quectel_cm_5G/src/log/qmi_wwan_q_qmap=4.txt | 185 - .../src/log/qmi_wwan_q_qmap=4_bridge.txt | 132 - quectel_cm_5G/src/log/qmi_wwan_qmap=4.txt | 55 - quectel_cm_5G/src/log/usage_of_argument/6.txt | 68 - quectel_cm_5G/src/log/usage_of_argument/m.txt | 58 - quectel_cm_5G/src/main.c | 934 ---- quectel_cm_5G/src/mbim-cm.c | 2426 --------- quectel_cm_5G/src/qendian.h | 52 - quectel_cm_5G/src/qlist.h | 38 - quectel_cm_5G/src/qmap_bridge_mode.c | 402 -- quectel_cm_5G/src/qrtr.c | 657 --- quectel_cm_5G/src/qrtr.h | 74 - quectel_cm_5G/src/quectel-atc-proxy.c | 506 -- quectel_cm_5G/src/quectel-mbim-proxy.c | 453 -- quectel_cm_5G/src/quectel-qmi-proxy.c | 694 --- quectel_cm_5G/src/quectel-qrtr-proxy.c | 894 ---- quectel_cm_5G/src/rmnetctl.c | 342 -- quectel_cm_5G/src/udhcpc.c | 733 --- quectel_cm_5G/src/udhcpc_netlink.c | 179 - quectel_cm_5G/src/udhcpc_script.c | 132 - quectel_cm_5G/src/util.c | 361 -- quectel_cm_5G/src/util.h | 52 - rooter/0basicapps/ext-command/Makefile | 33 - .../usr/lib/lua/luci/controller/commands.lua | 296 -- .../usr/lib/lua/luci/model/cbi/commands.lua | 37 - .../files/usr/lib/lua/luci/view/cmdedit.htm | 186 - .../files/usr/lib/lua/luci/view/commands.htm | 176 - .../ext-command/files/usr/lib/scripts/dummy | 1 - rooter/0basicapps/ext-extra/Makefile | 35 - .../ext-extra/files/etc/config/schedule | 7 - .../usr/lib/lua/luci/controller/schedule.lua | 9 - .../luci/model/cbi/admin_system/cronnew.lua | 29 - .../usr/lib/lua/luci/model/cbi/schedule.lua | 133 - .../files/usr/lib/rooter/luci/croncat.sh | 36 - .../files/usr/lib/rooter/luci/reboot.sh | 32 - rooter/0basicapps/ext-p910nd/Makefile | 36 - .../files/etc/uci-defaults/40_luci-p910ndx | 11 - .../usr/lib/lua/luci/controller/p910ndx.lua | 15 - .../usr/lib/lua/luci/model/cbi/p910ndx.lua | 59 - rooter/0basicapps/usb-storage/Makefile | 38 - .../usb-storage/files/etc/config/umount | 2 - .../files/etc/hotplug.d/block/20-mount | 68 - .../files/etc/hotplug.d/block/30-mount | 88 - .../files/etc/hotplug.d/block/99-mount | 41 - .../files/etc/uci-defaults/40_luci-hd_idle | 11 - .../0basicapps/usb-storage/files/etc/umount | 18 - .../usr/lib/lua/luci/controller/hd_idle.lua | 15 - .../usr/lib/lua/luci/controller/umount.lua | 8 - .../usr/lib/lua/luci/model/cbi/hd_idle.lua | 29 - .../usr/lib/lua/luci/model/cbi/umount.lua | 20 - .../files/usr/lib/sdcard/sdcard.sh | 88 - rooter/0basicsupport/ext-buttons/Makefile | 35 - .../ext-buttons/files/etc/btnaction.sh | 56 - .../files/etc/hotplug.d/button/00-button | 26 - .../files/etc/hotplug.d/button/10-buttonchk | 10 - .../ext-buttons/files/etc/init.d/buttons | 16 - .../usr/lib/lua/luci/controller/buttons.lua | 14 - .../lua/luci/model/cbi/buttons/buttons.lua | 44 - rooter/0basicsupport/ext-sms/Makefile | 35 - .../files/usr/lib/lua/luci/controller/sms.lua | 162 - .../usr/lib/lua/luci/view/rooter/sms.htm | 556 --- .../ext-sms/files/usr/lib/sms/delall.sh | 35 - .../ext-sms/files/usr/lib/sms/delsms.sh | 43 - .../ext-sms/files/usr/lib/sms/merge.lua | 165 - .../ext-sms/files/usr/lib/sms/pack7bit.lua | 79 - .../ext-sms/files/usr/lib/sms/processsms | 168 - .../ext-sms/files/usr/lib/sms/sendsms.lua | 41 - .../ext-sms/files/usr/lib/sms/sendsms.sh | 10 - .../ext-sms/files/usr/lib/sms/smsout.lua | 24 - .../ext-sms/files/usr/lib/sms/smsout.sh | 38 - .../ext-sms/files/usr/lib/sms/smsread.lua | 863 ---- .../ext-sms/files/usr/lib/sms/sys2sms.lua | 82 - .../ext-sms/files/usr/lib/sms/sys2sms.sh | 65 - .../ext-sms/files/usr/lib/sms/toggle.sh | 7 - .../ext-sms/files/usr/lib/sms/utf8togsm.lua | 167 - .../0basicsupport/luci-app-guestwifi/Makefile | 33 - .../files/etc/config/guestwifi | 4 - .../files/usr/lib/guestwifi/create.sh | 32 - .../files/usr/lib/guestwifi/remove.sh | 8 - .../files/usr/lib/guestwifi/start.sh | 200 - .../files/usr/lib/guestwifi/stop.sh | 19 - .../usr/lib/lua/luci/controller/guestwifi.lua | 19 - .../lib/lua/luci/model/cbi/guestwifi-edit.lua | 72 - .../usr/lib/lua/luci/model/cbi/guestwifi.lua | 128 - .../view/guestwifi/cbi-select-input-add.htm | 60 - .../lib/lua/luci/view/guestwifi/ovpn_css.htm | 38 - rooter/0drivers/rmbim/.svn/entries | 65 - .../rmbim/.svn/text-base/Makefile.svn-base | 45 - rooter/0drivers/rmbim/Makefile | 45 - .../rmbim/files/lib/netifd/proto/mbim.sh | 627 --- .../files/usr/lib/rooter/mbim/mbimdata.sh | 115 - .../files/usr/lib/rooter/mbim/monitor.sh | 45 - rooter/0drivers/rqmi/Makefile | 48 - .../files/usr/lib/rooter/qmi/connectqmi.sh | 301 -- rooter/0optionalapps/bwallocate/Makefile | 34 - .../bwallocate/files/etc/init.d/textbwint | 14 - .../lib/lua/luci/controller/bwallocate.lua | 22 - .../lua/luci/model/cbi/fullmenu/bwmenu.lua | 267 - rooter/0optionalapps/bwmon/Makefile | 35 - .../bwmon/files/etc/config/bwmon | 9 - .../bwmon/files/etc/init.d/bwmon | 18 - .../bwmon/files/lib/upgrade/keep.d/bwmon | 1 - .../bwmon/files/usr/lib/bwmon/allocate.sh | 21 - .../bwmon/files/usr/lib/bwmon/amtleft.lua | 36 - .../files/usr/lib/bwmon/backup-daily.lua | 61 - .../bwmon/files/usr/lib/bwmon/backup-mon.lua | 81 - .../bwmon/files/usr/lib/bwmon/backup.sh | 51 - .../bwmon/files/usr/lib/bwmon/block | 28 - .../bwmon/files/usr/lib/bwmon/change.sh | 14 - .../bwmon/files/usr/lib/bwmon/chksms.sh | 21 - .../bwmon/files/usr/lib/bwmon/cleanup.lua | 32 - .../bwmon/files/usr/lib/bwmon/create.sh | 16 - .../bwmon/files/usr/lib/bwmon/create_data.lua | 193 - .../files/usr/lib/bwmon/data/placeholder | 1 - .../bwmon/files/usr/lib/bwmon/datainc.lua | 21 - .../bwmon/files/usr/lib/bwmon/dataper.lua | 17 - .../bwmon/files/usr/lib/bwmon/dotext.sh | 82 - .../bwmon/files/usr/lib/bwmon/editemail.sh | 29 - .../bwmon/files/usr/lib/bwmon/excede.sh | 94 - .../bwmon/files/usr/lib/bwmon/external.sh | 24 - .../bwmon/files/usr/lib/bwmon/float.lua | 9 - .../bwmon/files/usr/lib/bwmon/message | 4 - .../bwmon/files/usr/lib/bwmon/msmtprc | 12 - .../bwmon/files/usr/lib/bwmon/perday.lua | 204 - .../bwmon/files/usr/lib/bwmon/process.sh | 20 - .../bwmon/files/usr/lib/bwmon/rollover.sh | 11 - .../bwmon/files/usr/lib/bwmon/savetot.sh | 10 - .../bwmon/files/usr/lib/bwmon/sendsms.sh | 39 - .../bwmon/files/usr/lib/bwmon/textbw.sh | 153 - .../bwmon/files/usr/lib/bwmon/wrtbwmon.sh | 508 -- .../usr/lib/lua/luci/controller/bwmon.lua | 119 - .../usr/lib/lua/luci/view/bwmon/bwmon.htm | 610 --- .../bwmon/files/usr/sbin/readDB.awk | 157 - rooter/0optionalapps/ext-autoapn/Makefile | 33 - .../files/usr/lib/autoapn/apn.data | 2198 --------- rooter/0optionalapps/ext-blacklist/Makefile | 35 - .../ext-blacklist/files/etc/config/blacklist | 4 - .../files/usr/lib/blacklist/blacklist.sh | 32 - .../files/usr/lib/blacklist/chkblack.sh | 11 - .../usr/lib/lua/luci/controller/blacklist.lua | 10 - .../usr/lib/lua/luci/model/cbi/blacklist.lua | 21 - rooter/0optionalapps/ext-blockport/Makefile | 35 - .../ext-blockport/files/etc/config/blockport | 4 - .../files/usr/lib/blockport/blockport.sh | 37 - .../usr/lib/lua/luci/controller/blockport.lua | 15 - .../usr/lib/lua/luci/model/cbi/portblk.lua | 21 - rooter/0optionalapps/ext-domain/Makefile | 35 - .../ext-domain/files/etc/config/blockport | 4 - .../files/usr/lib/blockport/blockport.sh | 37 - .../usr/lib/lua/luci/controller/blockport.lua | 12 - .../usr/lib/lua/luci/model/cbi/portblk.lua | 21 - rooter/0optionalapps/ext-rspeedtest/Makefile | 34 - .../lib/lua/luci/controller/rspeedtest.lua | 79 - .../lua/luci/view/speedtest/rspeedtest.htm | 259 - .../files/usr/lib/speedtest/closest.lua | 62 - .../files/usr/lib/speedtest/getspeed.sh | 83 - .../files/usr/lib/speedtest/info.sh | 75 - .../files/usr/lib/speedtest/ping.sh | 26 - .../files/usr/lib/speedtest/servers.lua | 46 - .../files/usr/lib/speedtest/stop.sh | 28 - .../www/luci-static/resources/img/prov.png | Bin 23789 -> 0 bytes .../www/luci-static/resources/img/user.png | Bin 15663 -> 0 bytes rooter/0optionalapps/ext-speedtest/Makefile | 34 - .../usr/lib/lua/luci/controller/speedtest.lua | 7 - .../lib/lua/luci/view/speedtest/speedtest.htm | 45 - .../luci-static/speed/css/iconmoon_splash.css | 69 - .../www/luci-static/speed/css/splash.css | 341 -- .../speed/fonts/icomoon_splash.eot | Bin 4708 -> 0 bytes .../speed/fonts/icomoon_splash.svg | 22 - .../speed/fonts/icomoon_splash.ttf | Bin 4516 -> 0 bytes .../speed/fonts/icomoon_splash.woff | Bin 4592 -> 0 bytes .../www/luci-static/speed/img/favicon.gif | Bin 2441 -> 0 bytes .../luci-static/speed/img/kangaroo_800.png | Bin 5836 -> 0 bytes rooter/0optionalapps/ext-texting/Makefile | 33 - .../ext-texting/files/etc/config/texting | 32 - .../ext-texting/files/etc/init.d/texting | 12 - .../files/usr/lib/fullmenu/chksms.sh | 21 - .../files/usr/lib/fullmenu/dotext.sh | 123 - .../files/usr/lib/fullmenu/text-setup.sh | 63 - .../usr/lib/lua/luci/controller/texting.lua | 24 - .../lua/luci/model/cbi/fullmenu/texting.lua | 254 - .../lib/lua/luci/view/fullmenu/textarea.htm | 103 - .../files/usr/lib/throttle/throttle.sh | 47 - rooter/0optionalapps/ext-wireguard/Makefile | 35 - .../ext-wireguard/files/etc/config/wireguard | 5 - .../files/etc/config/wireguard_recipes | 36 - .../ext-wireguard/files/etc/init.d/wireguard | 92 - .../usr/lib/lua/luci/controller/wireguard.lua | 111 - .../lua/luci/model/cbi/wireguard-client.lua | 104 - .../lua/luci/model/cbi/wireguard-server.lua | 130 - .../usr/lib/lua/luci/model/cbi/wireguard.lua | 182 - .../view/wireguard/cbi-select-input-add.htm | 111 - .../usr/lib/lua/luci/view/wireguard/conf.htm | 27 - .../lib/lua/luci/view/wireguard/ovpn_css.htm | 38 - .../lua/luci/view/wireguard/pageswitch.htm | 30 - .../lib/lua/luci/view/wireguard/text_conf.htm | 61 - .../lib/lua/luci/view/wireguard/wireguard.htm | 228 - .../files/usr/lib/wireguard/conf.sh | 134 - .../files/usr/lib/wireguard/create.sh | 81 - .../files/usr/lib/wireguard/keygen.sh | 63 - .../files/usr/lib/wireguard/startvpn.sh | 323 -- .../files/usr/lib/wireguard/stopvpn.sh | 71 - .../files/usr/lib/wireguard/text.sh | 19 - .../luci-static/resources/icons/wireguard.png | Bin 22762 -> 0 bytes .../resources/icons/wireguard_disabled.png | Bin 23205 -> 0 bytes rooter/0optionalapps/ext-zerotier/Makefile | 34 - .../ext-zerotier/files/etc/init.d/zerofire | 37 - .../files/etc/uci-defaults/64-zerotier | 7 - .../usr/lib/lua/luci/controller/zerotier.lua | 62 - .../lua/luci/view/admin_status/index/zero.htm | 1 - .../lib/lua/luci/view/zerotier/zerotier.htm | 182 - .../lib/lua/luci/view/zerotier/zerotier1.htm | 22 - .../files/usr/lib/zerotier/netid.sh | 21 - rooter/0optionalapps/extramenu/Makefile | 33 - .../extramenu/files/etc/init.d/fullmenu | 18 - .../files/usr/lib/fullmenu/setmenu.sh | 18 - .../usr/lib/lua/luci/controller/fullmenu.lua | 39 - .../lib/lua/luci/view/fullmenu/fullmenu.htm | 181 - .../luci-app-dnsmasq-ipset/Makefile | 34 - .../files/etc/config/dnsmasq-ipset | 5 - .../files/etc/init.d/dnsmasq-ipset | 49 - .../lib/lua/luci/controller/dnsmasq-ipset.lua | 12 - .../lib/lua/luci/model/cbi/dnsmasq-ipset.lua | 24 - .../0optionalapps/luci-app-hotspot/Makefile | 34 - .../files/etc/config/travelmate | 17 - .../etc/hotplug.d/iface/99-travelmate-iface | 48 - .../files/etc/init.d/travelmate | 94 - .../luci-app-hotspot/files/etc/init.d/zhot | 17 - .../files/lib/upgrade/keep.d/hotspot | 1 - .../luci-app-hotspot/files/usr/bin/hkillall | 9 - .../files/usr/lib/hotspot/band.sh | 25 - .../files/usr/lib/hotspot/copyhot.sh | 9 - .../files/usr/lib/hotspot/dis_hot.sh | 15 - .../files/usr/lib/hotspot/enable.sh | 42 - .../files/usr/lib/hotspot/getssid.sh | 15 - .../files/usr/lib/hotspot/inrange.sh | 59 - .../files/usr/lib/hotspot/manual.sh | 10 - .../files/usr/lib/hotspot/mode.sh | 19 - .../files/usr/lib/hotspot/reconn.sh | 11 - .../files/usr/lib/hotspot/travelmate.sh | 429 -- .../usr/lib/lua/luci/controller/hotspot.lua | 307 -- .../usr/lib/lua/luci/controller/wifilog.lua | 33 - .../usr/lib/lua/luci/view/hotspot/hotspot.htm | 1139 ----- .../usr/lib/lua/luci/view/wifilog/wifilog.htm | 32 - .../files/usr/lib/rooter/log/wifilogger.sh | 14 - .../luci-app-hotspot/files/usr/sbin/wifilog | 7 - .../resources/icons/encryption.png | Bin 620 -> 0 bytes .../0optionalapps/luci-app-nft-qos/Makefile | 34 - .../usr/lib/lua/luci/controller/nft-qos.lua | 55 - .../lua/luci/model/cbi/nft-qos/nft-qos.lua | 229 - .../usr/lib/lua/luci/view/nft-qos/rate.htm | 167 - .../luci-app-nft-qos/po/bg/nft-qos.po | 233 - .../luci-app-nft-qos/po/ca/nft-qos.po | 239 - .../luci-app-nft-qos/po/cs/nft-qos.po | 239 - .../luci-app-nft-qos/po/de/nft-qos.po | 240 - .../luci-app-nft-qos/po/el/nft-qos.po | 239 - .../luci-app-nft-qos/po/en/nft-qos.po | 233 - .../luci-app-nft-qos/po/es/nft-qos.po | 246 - .../luci-app-nft-qos/po/fr/nft-qos.po | 239 - .../luci-app-nft-qos/po/he/nft-qos.po | 240 - .../luci-app-nft-qos/po/hi/nft-qos.po | 233 - .../luci-app-nft-qos/po/hu/nft-qos.po | 240 - .../luci-app-nft-qos/po/it/nft-qos.po | 239 - .../luci-app-nft-qos/po/ja/nft-qos.po | 239 - .../luci-app-nft-qos/po/ko/nft-qos.po | 239 - .../luci-app-nft-qos/po/mr/nft-qos.po | 239 - .../luci-app-nft-qos/po/ms/nft-qos.po | 239 - .../luci-app-nft-qos/po/nb_NO/nft-qos.po | 239 - .../luci-app-nft-qos/po/pl/nft-qos.po | 240 - .../luci-app-nft-qos/po/pt/nft-qos.po | 240 - .../luci-app-nft-qos/po/pt_BR/nft-qos.po | 239 - .../luci-app-nft-qos/po/ro/nft-qos.po | 240 - .../luci-app-nft-qos/po/ru/nft-qos.po | 240 - .../luci-app-nft-qos/po/sk/nft-qos.po | 239 - .../luci-app-nft-qos/po/sv/nft-qos.po | 239 - .../luci-app-nft-qos/po/templates/nft-qos.pot | 230 - .../luci-app-nft-qos/po/tr/nft-qos.po | 239 - .../luci-app-nft-qos/po/uk/nft-qos.po | 240 - .../luci-app-nft-qos/po/vi/nft-qos.po | 239 - .../luci-app-nft-qos/po/zh_Hans/nft-qos.po | 245 - .../luci-app-nft-qos/po/zh_Hant/nft-qos.po | 245 - .../share/rpcd/acl.d/luci-app-nft-qos.json | 11 - .../luci-app-rooterddns/Makefile | 34 - .../files/etc/uci-defaults/40_luci-ddns | 10 - .../usr/lib/lua/luci/controller/ddns.lua | 308 -- .../lib/lua/luci/model/cbi/ddns/detail.lua | 1479 ------ .../lib/lua/luci/model/cbi/ddns/global.lua | 121 - .../usr/lib/lua/luci/model/cbi/ddns/hints.lua | 166 - .../lib/lua/luci/model/cbi/ddns/overview.lua | 219 - .../files/usr/lib/lua/luci/tools/ddns.lua | 315 -- .../lua/luci/view/admin_status/index/ddns.htm | 1 - .../lib/lua/luci/view/ddns/detail_logview.htm | 56 - .../lib/lua/luci/view/ddns/detail_lvalue.htm | 23 - .../lib/lua/luci/view/ddns/detail_value.htm | 9 - .../lib/lua/luci/view/ddns/global_value.htm | 34 - .../luci/view/ddns/overview_doubleline.htm | 10 - .../lua/luci/view/ddns/overview_enabled.htm | 16 - .../lua/luci/view/ddns/overview_startstop.htm | 17 - .../lua/luci/view/ddns/overview_status.htm | 180 - .../lib/lua/luci/view/ddns/system_status.htm | 144 - .../0optionalapps/luci-app-rootervpn/Makefile | 34 - .../files/etc/config/openvpn_recipes | 293 -- .../files/etc/init.d/openvpn | 194 - .../files/etc/init.d/rootervpn | 183 - .../files/etc/openvpn/airvpn/ca.crt | 36 - .../files/etc/openvpn/airvpn/client.crt | 38 - .../files/etc/openvpn/airvpn/client.key | 52 - .../files/etc/openvpn/airvpn/ta.key | 18 - .../files/etc/openvpn/mullvad/mullvad_ca.crt | 109 - .../files/etc/openvpn/mullvad/mullvad_crl.pem | 36 - .../files/etc/openvpn/pia/ca.rsa.2048.crt | 33 - .../files/etc/openvpn/pia/crl.rsa.2048.pem | 15 - .../etc/openvpn/placeholder/placeholder.file | 2 - .../files/etc/openvpn/windscribe/ca.crt | 34 - .../files/etc/openvpn/windscribe/ta.key | 18 - .../files/lib/upgrade/keep.d/rootervpn | 1 - .../files/usr/bin/ovpn-userpass | 16 - .../luci-app-rootervpn/files/usr/bin/rkillall | 9 - .../files/usr/lib/easyrsa/dns.sh | 67 - .../files/usr/lib/easyrsa/firewall.sh | 73 - .../files/usr/lib/easyrsa/generate.sh | 131 - .../files/usr/lib/easyrsa/stop.sh | 11 - .../files/usr/lib/easyrsa/vpn.sh | 9 - .../files/usr/lib/easyrsa/vpng.sh | 128 - .../usr/lib/lua/luci/controller/openvpn.lua | 135 - .../lua/luci/model/cbi/openvpn-advanced.lua | 902 ---- .../lib/lua/luci/model/cbi/openvpn-basic.lua | 196 - .../lib/lua/luci/model/cbi/openvpn-file.lua | 82 - .../lib/lua/luci/model/cbi/openvpn-server.lua | 86 - .../usr/lib/lua/luci/model/cbi/openvpn.lua | 179 - .../lua/luci/view/admin_status/index/vpn.htm | 1 - .../usr/lib/lua/luci/view/easyrsa/easyrsa.htm | 172 - .../view/openvpn/cbi-select-input-add.htm | 111 - .../lib/lua/luci/view/openvpn/ovpn_css.htm | 38 - .../lib/lua/luci/view/openvpn/pageswitch.htm | 30 - .../usr/lib/lua/luci/view/openvpn/vpn1.htm | 120 - .../resources/icons/vpn-disabled.png | Bin 1014 -> 0 bytes .../resources/icons/vpn-started.png | Bin 858 -> 0 bytes .../resources/icons/vpn-stopped.png | Bin 886 -> 0 bytes rooter/0optionalapps/nft-qos/Makefile | 59 - .../0optionalapps/nft-qos/files/lib/core.sh | 93 - .../nft-qos/files/lib/dynamic.sh | 90 - .../nft-qos/files/lib/monitor.sh | 39 - .../nft-qos/files/lib/priority.sh | 93 - .../0optionalapps/nft-qos/files/lib/static.sh | 74 - .../nft-qos/files/nft-qos-dynamic.hotplug | 36 - .../nft-qos/files/nft-qos-monitor.hotplug | 23 - .../nft-qos/files/nft-qos.config | 107 - .../0optionalapps/nft-qos/files/nft-qos.init | 47 - rooter/0optionalapps/pingtest/Makefile | 36 - .../pingtest/files/etc/config/ping | 6 - .../pingtest/files/etc/init.d/pingtest | 14 - .../files/usr/lib/custom/johns_ping.sh | 99 - .../files/usr/lib/custom/test_ping.sh | 35 - .../usr/lib/lua/luci/controller/ping.lua | 16 - .../files/usr/lib/lua/luci/model/cbi/ping.lua | 42 - .../luci/view/admin_status/index/extping.htm | 1 - .../lib/lua/luci/view/pingtest/extping.htm | 26 - rooter/0optionalapps/qfirehose/Makefile | 40 - rooter/0optionalapps/qfirehose/src/Makefile | 7 - .../qfirehose/src/firehose_protocol.c | 970 ---- .../qfirehose/src/hostdl_packet.h | 178 - rooter/0optionalapps/qfirehose/src/md5.c | 343 -- rooter/0optionalapps/qfirehose/src/md5.h | 23 - .../0optionalapps/qfirehose/src/qfirehose.c | 633 --- .../qfirehose/src/sahara_protocol.c | 380 -- .../qfirehose/src/sahara_protocol.h | 385 -- .../qfirehose/src/stream_download_protocol.c | 766 --- rooter/0optionalapps/qfirehose/src/usb2tcp.c | 338 -- .../0optionalapps/qfirehose/src/usb_linux.c | 1197 ----- .../0optionalapps/qfirehose/src/usb_linux.h | 140 - rooter/0optionalapps/qlog/Makefile | 41 - .../T1.LinuxData-OTA-DataService-AP_V01.cfg | Bin 2012 -> 0 bytes .../usr/lib/conf/T2.RegServ-CotextAct_V01.cfg | Bin 2260 -> 0 bytes .../lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg | Bin 2144 -> 0 bytes .../files/usr/lib/conf/T4.Throughput_V01.cfg | Bin 2116 -> 0 bytes .../files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg | Bin 4226 -> 0 bytes ...T6.FullMessage.SimpleLogPacket(AT)_V01.cfg | Bin 4191 -> 0 bytes .../files/usr/lib/conf/T7.V2X_ALL_V01.cfg | Bin 2205 -> 0 bytes .../qlog/files/usr/lib/conf/default.cfg | Bin 3480 -> 0 bytes rooter/0optionalapps/qlog/src/Makefile | 8 - rooter/0optionalapps/qlog/src/asr.c | 87 - rooter/0optionalapps/qlog/src/main.c | 499 -- rooter/0optionalapps/qlog/src/mdm.c | 203 - rooter/0optionalapps/qlog/src/qlog.h | 44 - rooter/0optionalapps/qlog/src/sahara.c | 660 --- .../0optionalapps/qlog/src/sahara_protocol.h | 510 -- rooter/0optionalapps/qlog/src/tty2tcp.c | 174 - rooter/0optionalapps/udp-tunnel/Makefile | 40 - rooter/0optionalapps/udp-tunnel/src/Makefile | 36 - rooter/0optionalapps/udp-tunnel/src/log.c | 130 - rooter/0optionalapps/udp-tunnel/src/log.h | 67 - rooter/0optionalapps/udp-tunnel/src/network.c | 401 -- rooter/0optionalapps/udp-tunnel/src/network.h | 40 - .../0optionalapps/udp-tunnel/src/udptunnel.c | 523 -- rooter/0optionalapps/udp-tunnel/src/utils.c | 32 - rooter/0optionalapps/udp-tunnel/src/utils.h | 55 - rooter/0optionalapps/webconsole/Makefile | 35 - .../lib/lua/luci/controller/webconsole.lua | 31 - .../usr/lib/lua/luci/view/web/web_console.htm | 51 - rooter/0protocols/luci-proto-3x/Makefile | 62 - .../luci/model/cbi/admin_network/proto_3x.lua | 146 - .../lib/lua/luci/model/network/proto_3x.lua | 68 - rooter/0protocols/luci-proto-mbim/Makefile | 62 - .../model/cbi/admin_network/proto_mbim.lua | 45 - .../lib/lua/luci/model/network/proto_mbim.lua | 51 - rooter/0routerspecfic/rd05a1/Makefile | 37 - .../rd05a1/files/etc/init.d/pciepwr | 18 - .../firmware/ath10k/QCA9887/hw1.0/board.bin | Bin 1024 -> 0 bytes .../ath10k/QCA9887/hw1.0/firmware-5.bin | Bin 236104 -> 0 bytes .../firmware/ath10k/cal-pci-0000_00_00.0.bin | Bin 2116 -> 0 bytes rooter/0routerspecfic/we826q/Makefile | 35 - .../we826q/files/etc/init.d/wd-init | 14 - .../we826q/files/usr/lib/custom/watchdog.sh | 25 - .../files/usr/lib/rooter/changedevice.sh | 11 - rooter/0splash/ext-splash/Makefile | 35 - .../ext-splash/files/etc/config/iframe | 17 - .../ext-splash/files/etc/init.d/iframeint | 18 - .../ext-splash/files/usr/lib/iframe/band.html | 1 - .../ext-splash/files/usr/lib/iframe/bwdays.sh | 109 - .../files/usr/lib/iframe/bwtemplate.html | 85 - .../ext-splash/files/usr/lib/iframe/create.sh | 31 - .../files/usr/lib/iframe/daylist.html | 85 - .../files/usr/lib/iframe/iframe.html | 41 - .../files/usr/lib/iframe/image.html | 11 - .../files/usr/lib/iframe/mframe.html | 111 - .../files/usr/lib/iframe/modem2.html | 1 - .../ext-splash/files/usr/lib/iframe/open.html | 1 - .../files/usr/lib/iframe/speed.html | 114 - .../files/usr/lib/iframe/status.html | 154 - .../ext-splash/files/usr/lib/iframe/status.sh | 21 - .../files/usr/lib/iframe/stupdate.sh | 404 -- .../ext-splash/files/usr/lib/iframe/update.sh | 301 -- .../files/usr/lib/iframe/zerotier.html | 14 - .../files/www/luci-static/display.html | 1 - .../files/www/luci-static/iframe.html | 1 - .../files/www/luci-static/ifstatus.html | 1 - .../rooter/css/iconmoon_splash.css | 69 - .../www/luci-static/rooter/css/splash.css | 342 -- .../rooter/fonts/icomoon_splash.eot | Bin 4708 -> 0 bytes .../rooter/fonts/icomoon_splash.svg | 22 - .../rooter/fonts/icomoon_splash.ttf | Bin 4516 -> 0 bytes .../rooter/fonts/icomoon_splash.woff | Bin 4592 -> 0 bytes .../www/luci-static/rooter/img/favicon.gif | Bin 2441 -> 0 bytes .../luci-static/rooter/img/kangaroo_800.png | Bin 5836 -> 0 bytes .../files/www/splash_files/check1.gif | Bin 49 -> 0 bytes rooter/0splash/ext-splashconfig/Makefile | 36 - .../usr/lib/lua/luci/controller/splash.lua | 10 - .../usr/lib/lua/luci/model/cbi/splashm.lua | 44 - rooter/0splash/splash/Makefile | 35 - .../rooter/css/iconmoon_splash.css | 69 - .../www/luci-static/rooter/css/splash.css | 311 -- .../rooter/fonts/icomoon_splash.eot | Bin 4708 -> 0 bytes .../rooter/fonts/icomoon_splash.svg | 22 - .../rooter/fonts/icomoon_splash.ttf | Bin 4516 -> 0 bytes .../rooter/fonts/icomoon_splash.woff | Bin 4592 -> 0 bytes .../www/luci-static/rooter/img/favicon.gif | Bin 2441 -> 0 bytes .../luci-static/rooter/img/kangaroo_800.png | Bin 5836 -> 0 bytes rooter/0splash/splash/files/www/splash.html | 101 - .../files/www/splash_files/cellular.png | Bin 8344 -> 0 bytes .../splash/files/www/splash_files/check.gif | Bin 49 -> 0 bytes .../splash/files/www/splash_files/check.jpg | Bin 631 -> 0 bytes .../splash/files/www/splash_files/forum.png | Bin 3845 -> 0 bytes .../splash/files/www/splash_files/home.png | Bin 1262 -> 0 bytes .../splash/files/www/splash_files/kanga1.png | Bin 2532 -> 0 bytes .../splash/files/www/splash_files/openwrt.png | Bin 2422 -> 0 bytes .../splash/files/www/splash_files/rooter.png | Bin 311293 -> 0 bytes rooter/0splash/splash/files/www/status.html | 254 - rooter/0splash/status/Makefile | 35 - rooter/0splash/status/files/etc/config/splash | 4 - .../usr/lib/lua/luci/controller/splashset.lua | 11 - .../usr/lib/lua/luci/model/cbi/splash.lua | 22 - .../status/files/usr/lib/splash/check.gif | Bin 49 -> 0 bytes .../status/files/usr/lib/splash/full.gif | Bin 49 -> 0 bytes .../status/files/usr/lib/splash/splash.sh | 21 - .../rooter/css/iconmoon_splash.css | 69 - .../www/luci-static/rooter/css/splash.css | 311 -- .../rooter/fonts/icomoon_splash.eot | Bin 4708 -> 0 bytes .../rooter/fonts/icomoon_splash.svg | 22 - .../rooter/fonts/icomoon_splash.ttf | Bin 4516 -> 0 bytes .../rooter/fonts/icomoon_splash.woff | Bin 4592 -> 0 bytes .../www/luci-static/rooter/img/favicon.gif | Bin 2441 -> 0 bytes .../luci-static/rooter/img/kangaroo_800.png | Bin 5836 -> 0 bytes rooter/0splash/status/files/www/splash.html | 264 - .../files/www/splash_files/cellular.png | Bin 8344 -> 0 bytes .../status/files/www/splash_files/check.gif | Bin 49 -> 0 bytes .../status/files/www/splash_files/check.jpg | Bin 631 -> 0 bytes .../status/files/www/splash_files/forum.png | Bin 3845 -> 0 bytes .../status/files/www/splash_files/full.gif | Bin 49 -> 0 bytes .../status/files/www/splash_files/home.png | Bin 1262 -> 0 bytes .../status/files/www/splash_files/kanga1.png | Bin 2532 -> 0 bytes .../status/files/www/splash_files/openwrt.png | Bin 2422 -> 0 bytes .../status/files/www/splash_files/rooter.png | Bin 311293 -> 0 bytes .../0splash/status/files/www/splashfull.html | 101 - .../0splash/status/files/www/statusfull.html | 271 - rooter/ext-rooter-basic/Makefile | 43 - rooter/ext-rooter-basic/files/etc/codename | 1 - .../ext-rooter-basic/files/etc/config/custom | 64 - .../ext-rooter-basic/files/etc/config/modem | 18 - .../ext-rooter-basic/files/etc/config/profile | 19 - rooter/ext-rooter-basic/files/etc/config/ttl | 11 - rooter/ext-rooter-basic/files/etc/genericcmd | 4 - rooter/ext-rooter-basic/files/etc/header_msg | 4 - .../files/etc/hotplug.d/iface/10-lan | 27 - .../files/etc/hotplug.d/iface/19-rooter | 42 - .../files/etc/hotplug.d/tty/30-3x | 31 - .../files/etc/hotplug.d/usb/20-usb_mode | 3 - .../ext-rooter-basic/files/etc/init.d/clear | 21 - .../ext-rooter-basic/files/etc/init.d/iphone | 22 - .../ext-rooter-basic/files/etc/init.d/rooter | 9 - .../ext-rooter-basic/files/etc/init.d/usbmode | 14 - ...000000000000000000000000000000000000.plist | 0 rooter/ext-rooter-basic/files/etc/netspeed | 1 - rooter/ext-rooter-basic/files/etc/quectelcmd | 6 - rooter/ext-rooter-basic/files/etc/sierracmd | 4 - rooter/ext-rooter-basic/files/etc/ttl.user | 4 - .../ext-rooter-basic/files/etc/usb-mode.json | 3180 ------------ .../files/lib/netifd/proto/3x.sh | 164 - .../files/lib/upgrade/keep.d/cronfiles | 2 - .../files/lib/upgrade/keep.d/rc-local | 3 - .../ext-rooter-basic/files/usr/bin/bmask128 | 19 - .../files/usr/bin/chan2band.sh | 317 -- .../ext-rooter-basic/files/usr/bin/encodemask | 24 - .../ext-rooter-basic/files/usr/bin/jkillall | 9 - .../ext-rooter-basic/files/usr/bin/rsrp2rssi | 21 - .../ext-rooter-basic/files/usr/bin/set_gpio | 18 - .../files/usr/lib/custom/locktype.sh | 22 - .../files/usr/lib/custom/ttlx.sh | 11 - .../files/usr/lib/gps/smsreply.sh | 115 - .../lib/lua/luci/controller/admin/modem.lua | 664 --- .../usr/lib/lua/luci/controller/modlog.lua | 29 - .../usr/lib/lua/luci/controller/poweroff.lua | 13 - .../usr/lib/lua/luci/controller/profile.lua | 40 - .../lib/lua/luci/model/cbi/firewall/ttlx.lua | 30 - .../lua/luci/model/cbi/rooter/customize.lua | 156 - .../lua/luci/model/cbi/rooter/profiles.lua | 828 ---- .../luci/view/admin_status/index/external.htm | 1 - .../lua/luci/view/admin_system/poweroff.htm | 34 - .../usr/lib/lua/luci/view/modlog/modlog.htm | 32 - .../usr/lib/lua/luci/view/rooter/custom.htm | 126 - .../usr/lib/lua/luci/view/rooter/debug.htm | 87 - .../usr/lib/lua/luci/view/rooter/external.htm | 26 - .../usr/lib/lua/luci/view/rooter/log.htm | 53 - .../usr/lib/lua/luci/view/rooter/misc.htm | 2387 --------- .../lib/lua/luci/view/rooter/net_status.htm | 564 --- .../usr/lib/lua/luci/view/rooter/profile.htm | 75 - .../files/usr/lib/modlog/modlogger.sh | 20 - .../files/usr/lib/profile/loadcfg.sh | 14 - .../files/usr/lib/profile/restart.sh | 15 - .../files/usr/lib/profile/savecfg.sh | 16 - .../files/usr/lib/rooter/autoapn.sh | 7 - .../files/usr/lib/rooter/cdmafind.lua | 55 - .../files/usr/lib/rooter/chan2band.sh | 273 -- .../usr/lib/rooter/common/fibocomdata.sh | 476 -- .../files/usr/lib/rooter/common/gettype.sh | 254 - .../files/usr/lib/rooter/common/huaweidata.sh | 299 -- .../files/usr/lib/rooter/common/lockchk.sh | 104 - .../usr/lib/rooter/common/mdm9215data.sh | 127 - .../files/usr/lib/rooter/common/meigdata.sh | 281 -- .../files/usr/lib/rooter/common/modemchk.lua | 120 - .../usr/lib/rooter/common/novateldata.sh | 138 - .../files/usr/lib/rooter/common/otherdata.sh | 97 - .../files/usr/lib/rooter/common/phone.sh | 55 - .../files/usr/lib/rooter/common/processat.sh | 16 - .../files/usr/lib/rooter/common/quantadata.sh | 121 - .../usr/lib/rooter/common/quecteldata.sh | 376 -- .../files/usr/lib/rooter/common/sierradata.sh | 258 - .../files/usr/lib/rooter/common/simcomdata.sh | 172 - .../files/usr/lib/rooter/common/t77data.sh | 236 - .../files/usr/lib/rooter/common/telitdata.sh | 241 - .../files/usr/lib/rooter/common/ubloxdata.sh | 250 - .../files/usr/lib/rooter/common/ztedata.sh | 193 - .../files/usr/lib/rooter/connect/bandmask | 483 -- .../files/usr/lib/rooter/connect/conmon.sh | 188 - .../usr/lib/rooter/connect/create_connect.sh | 1367 ------ .../usr/lib/rooter/connect/create_hostless.sh | 713 --- .../usr/lib/rooter/connect/create_iphone.sh | 223 - .../usr/lib/rooter/connect/disablemw3.sh | 14 - .../usr/lib/rooter/connect/disconnect.sh | 73 - .../usr/lib/rooter/connect/get_profile.sh | 423 -- .../files/usr/lib/rooter/connect/handlettl.sh | 106 - .../usr/lib/rooter/connect/postconnect.sh | 19 - .../usr/lib/rooter/connect/preconnect.sh | 15 - .../usr/lib/rooter/connect/reconnect-ppp.sh | 59 - .../files/usr/lib/rooter/connect/reconnect.sh | 12 - .../files/usr/lib/rooter/customname.lua | 17 - .../files/usr/lib/rooter/gcom/auto.gcom | 31 - .../files/usr/lib/rooter/gcom/baseinfo.gcom | 33 - .../files/usr/lib/rooter/gcom/cellinfo.gcom | 50 - .../files/usr/lib/rooter/gcom/cellinfo0.gcom | 45 - .../files/usr/lib/rooter/gcom/cgpaddr.gcom | 46 - .../usr/lib/rooter/gcom/connect-directip.gcom | 64 - .../usr/lib/rooter/gcom/connect-fecm.gcom | 45 - .../usr/lib/rooter/gcom/connect-ncm.gcom | 48 - .../usr/lib/rooter/gcom/connect-ppp.gcom | 36 - .../usr/lib/rooter/gcom/connect-zecm.gcom | 45 - .../files/usr/lib/rooter/gcom/curc.gcom | 31 - .../usr/lib/rooter/gcom/fibocominfo.gcom | 65 - .../files/usr/lib/rooter/gcom/gcom-locked | 41 - .../files/usr/lib/rooter/gcom/gettype.gcom | 43 - .../files/usr/lib/rooter/gcom/huaweiinfo.gcom | 74 - .../files/usr/lib/rooter/gcom/lock-prov.gcom | 38 - .../usr/lib/rooter/gcom/mdm9215info.gcom | 43 - .../files/usr/lib/rooter/gcom/meiginfo.gcom | 69 - .../usr/lib/rooter/gcom/novatelinfo.gcom | 48 - .../files/usr/lib/rooter/gcom/otherinfo.gcom | 28 - .../files/usr/lib/rooter/gcom/quantainfo.gcom | 38 - .../usr/lib/rooter/gcom/quectelinfo.gcom | 76 - .../files/usr/lib/rooter/gcom/raw-ip.gcom | 31 - .../files/usr/lib/rooter/gcom/reset.gcom | 25 - .../files/usr/lib/rooter/gcom/run-at.gcom | 31 - .../files/usr/lib/rooter/gcom/sendsms-at.gcom | 45 - .../files/usr/lib/rooter/gcom/setapn.gcom | 45 - .../files/usr/lib/rooter/gcom/setpin.gcom | 53 - .../files/usr/lib/rooter/gcom/sierrainfo.gcom | 68 - .../files/usr/lib/rooter/gcom/simcominfo.gcom | 48 - .../files/usr/lib/rooter/gcom/smschk.gcom | 36 - .../files/usr/lib/rooter/gcom/smswrite.gcom | 39 - .../files/usr/lib/rooter/gcom/t77info.gcom | 70 - .../files/usr/lib/rooter/gcom/telitinfo.gcom | 48 - .../usr/lib/rooter/gcom/telitinfoln.gcom | 43 - .../files/usr/lib/rooter/gcom/ubloxinfo.gcom | 43 - .../files/usr/lib/rooter/gcom/ussd.gcom | 29 - .../files/usr/lib/rooter/gcom/zteinfo.gcom | 58 - .../files/usr/lib/rooter/gpio-set.sh | 23 - .../files/usr/lib/rooter/gpiomodel.lua | 221 - .../files/usr/lib/rooter/idown.lua | 22 - .../files/usr/lib/rooter/initialize.sh | 295 -- .../files/usr/lib/rooter/log/at-logger | 12 - .../files/usr/lib/rooter/log/logger | 17 - .../files/usr/lib/rooter/log/modlogger.sh | 26 - .../files/usr/lib/rooter/log/mrotate.lua | 39 - .../files/usr/lib/rooter/log/rotate.lua | 43 - .../files/usr/lib/rooter/logprint.sh | 5 - .../files/usr/lib/rooter/luci/atcmd.sh | 21 - .../files/usr/lib/rooter/luci/celltype.sh | 495 -- .../files/usr/lib/rooter/luci/em060-2xbands | 29 - .../files/usr/lib/rooter/luci/em12-2xbands | 46 - .../files/usr/lib/rooter/luci/em12-3xbands | 43 - .../files/usr/lib/rooter/luci/em20-2xbands | 50 - .../files/usr/lib/rooter/luci/em20-3xbands | 41 - .../files/usr/lib/rooter/luci/em20-4xbands | 8 - .../files/usr/lib/rooter/luci/em7411-2xbands | 29 - .../files/usr/lib/rooter/luci/em7411-3xbands | 8 - .../files/usr/lib/rooter/luci/em7511-2xbands | 60 - .../files/usr/lib/rooter/luci/em7511-3xbands | 55 - .../files/usr/lib/rooter/luci/em7565-2xbands | 14 - .../files/usr/lib/rooter/luci/em7565-3xbands | 51 - .../files/usr/lib/rooter/luci/ep06a-bands | 27 - .../files/usr/lib/rooter/luci/ep06e-bands | 32 - .../files/usr/lib/rooter/luci/l850-2xbands | 35 - .../files/usr/lib/rooter/luci/l850-3xbands | 27 - .../files/usr/lib/rooter/luci/lock.sh | 395 -- .../files/usr/lib/rooter/luci/luaops.sh | 8 - .../files/usr/lib/rooter/luci/mask.sh | 332 -- .../files/usr/lib/rooter/luci/mc7455-bands | 14 - .../files/usr/lib/rooter/luci/modechge.sh | 276 -- .../files/usr/lib/rooter/luci/modemchge.sh | 46 - .../files/usr/lib/rooter/luci/portchge.sh | 28 - .../files/usr/lib/rooter/luci/protochnge.sh | 155 - .../files/usr/lib/rooter/luci/restart.sh | 83 - .../files/usr/lib/rooter/luci/scancmd.sh | 412 -- .../files/usr/lib/rooter/luci/setcell.sh | 59 - .../files/usr/lib/rooter/luci/wifiradio.sh | 15 - .../files/usr/lib/rooter/mbimfind.lua | 92 - .../files/usr/lib/rooter/modeswitch.sh | 620 --- .../files/usr/lib/rooter/ncmfind.lua | 63 - .../files/usr/lib/rooter/nitz2sys.sh | 29 - .../files/usr/lib/rooter/portchge.sh | 28 - .../files/usr/lib/rooter/ppp/create_ppp.sh | 247 - .../files/usr/lib/rooter/proto.sh | 107 - .../files/usr/lib/rooter/protofind.lua | 247 - .../files/usr/lib/rooter/pwrtoggle.sh | 181 - .../files/usr/lib/rooter/shutall.sh | 14 - .../files/usr/lib/rooter/signal/basedata.sh | 78 - .../files/usr/lib/rooter/signal/celldata.sh | 136 - .../files/usr/lib/rooter/signal/celltype.lua | 142 - .../usr/lib/rooter/signal/huaweihostless.sh | 205 - .../files/usr/lib/rooter/signal/mccmnc.data | 11 - .../usr/lib/rooter/signal/modemsignal.sh | 287 -- .../usr/lib/rooter/signal/otherhostless.sh | 160 - .../files/usr/lib/rooter/signal/status.sh | 46 - .../usr/lib/rooter/signal/ztehostless.sh | 215 - .../files/usr/lib/rooter/simlock.sh | 57 - .../files/usr/lib/rooter/simlockc.sh | 8 - .../files/usr/lib/rooter/sms/check_sms.sh | 32 - .../files/usr/lib/rooter/timezone.sh | 19 - .../files/usr/lib/rooter/tzone.lua | 478 -- .../files/usr/lib/rooter/ussd.sh | 67 - rooter/ext-rooter-basic/files/usr/sbin/modlog | 7 - .../www/luci-static/background/main_bg.jpg | Bin 134812 -> 0 bytes .../files/www/luci-static/css/cascade.css | 3305 ------------- .../files/www/luci-static/css/dark.css | 1 - .../files/www/luci-static/css/fonts.css | 1 - .../files/www/luci-static/css/pure-min.css | 1 - .../fonts/Roboto-Medium-webfont.woff | Bin 70200 -> 0 bytes .../fonts/Roboto-Regular-webfont.woff | Bin 68776 -> 0 bytes .../www/luci-static/fonts/TypoGraphica.eot | Bin 33846 -> 0 bytes .../www/luci-static/fonts/TypoGraphica.svg | 1191 ----- .../www/luci-static/fonts/TypoGraphica.ttf | Bin 33632 -> 0 bytes .../www/luci-static/fonts/TypoGraphica.woff | Bin 17816 -> 0 bytes .../www/luci-static/fonts/advancedtomato.eot | Bin 8480 -> 0 bytes .../www/luci-static/fonts/advancedtomato.svg | 53 - .../www/luci-static/fonts/advancedtomato.ttf | Bin 8288 -> 0 bytes .../www/luci-static/fonts/advancedtomato.woff | Bin 6272 -> 0 bytes .../files/www/luci-static/fonts/argon.eot | Bin 8888 -> 0 bytes .../files/www/luci-static/fonts/argon.svg | 38 - .../files/www/luci-static/fonts/argon.ttf | Bin 8732 -> 0 bytes .../files/www/luci-static/fonts/argon.woff | Bin 8808 -> 0 bytes .../files/www/luci-static/fonts/font.eot | Bin 1912 -> 0 bytes .../files/www/luci-static/fonts/font.svg | 16 - .../files/www/luci-static/fonts/font.ttf | Bin 1748 -> 0 bytes .../files/www/luci-static/fonts/font.woff | Bin 1824 -> 0 bytes .../files/www/luci-static/fonts/fonts.css | 38 - .../luci-static/icon/android-icon-192x192.png | Bin 6411 -> 0 bytes .../luci-static/icon/apple-icon-144x144.png | Bin 5222 -> 0 bytes .../www/luci-static/icon/apple-icon-60x60.png | Bin 2561 -> 0 bytes .../www/luci-static/icon/apple-icon-72x72.png | Bin 2877 -> 0 bytes .../www/luci-static/icon/browserconfig.xml | 2 - .../www/luci-static/icon/favicon-16x16.png | Bin 1019 -> 0 bytes .../www/luci-static/icon/favicon-32x32.png | Bin 1720 -> 0 bytes .../www/luci-static/icon/favicon-96x96.png | Bin 3650 -> 0 bytes .../files/www/luci-static/icon/manifest.json | 41 - .../www/luci-static/icon/ms-icon-144x144.png | Bin 5222 -> 0 bytes .../files/www/luci-static/icons/arrow.svg | 1 - .../files/www/luci-static/icons/logout.svg | 1 - .../files/www/luci-static/icons/menu.svg | 1 - .../files/www/luci-static/icons/spinner.svg | 1 - .../files/www/luci-static/img/argon.svg | 61 - .../files/www/luci-static/img/blank.png | Bin 938 -> 0 bytes .../files/www/luci-static/img/open.png | Bin 7603 -> 0 bytes .../files/www/luci-static/img/volume_high.svg | 1 - .../files/www/luci-static/img/volume_off.svg | 1 - .../luci-static/resources/buttons/buttons.css | 702 --- .../www/luci-static/resources/icons/lock1.png | Bin 13833 -> 0 bytes .../luci-static/resources/icons/unlock1.png | Bin 12460 -> 0 bytes .../www/luci-static/resources/img/header.png | Bin 4141 -> 0 bytes .../www/luci-static/resources/img/rooter.png | Bin 4644 -> 0 bytes .../www/luci-static/resources/img/rosy.png | Bin 19473 -> 0 bytes sendat/Makefile | 33 - sendat/README.md | 5 - sendat/src/Makefile | 9 - sendat/src/pdu.c | 420 -- sendat/src/pdu.h | 52 - sendat/src/pdu_decoder.c | 107 - sendat/src/sendat.c | 450 -- sendat/src/ucs2_to_utf8.c | 53 - 1052 files changed, 206065 deletions(-) delete mode 100644 README.md delete mode 100644 fibocom-dial/Makefile delete mode 100644 fibocom-dial/src/GobiNetCM.c delete mode 100644 fibocom-dial/src/MPQCTL.h delete mode 100644 fibocom-dial/src/MPQMI.h delete mode 100644 fibocom-dial/src/MPQMUX.c delete mode 100644 fibocom-dial/src/MPQMUX.h delete mode 100644 fibocom-dial/src/Makefile delete mode 100644 fibocom-dial/src/QMIThread.c delete mode 100644 fibocom-dial/src/QMIThread.h delete mode 100644 fibocom-dial/src/QmiWwanCM.c delete mode 100644 fibocom-dial/src/default.script delete mode 100644 fibocom-dial/src/fibo_qmimsg_server.c delete mode 100644 fibocom-dial/src/libmnl/README delete mode 100644 fibocom-dial/src/libmnl/attr.c delete mode 100644 fibocom-dial/src/libmnl/callback.c delete mode 100644 fibocom-dial/src/libmnl/dhcp/dhcp.h delete mode 100644 fibocom-dial/src/libmnl/dhcp/dhcpclient.c delete mode 100644 fibocom-dial/src/libmnl/dhcp/dhcpmsg.c delete mode 100644 fibocom-dial/src/libmnl/dhcp/dhcpmsg.h delete mode 100644 fibocom-dial/src/libmnl/dhcp/packet.c delete mode 100644 fibocom-dial/src/libmnl/dhcp/packet.h delete mode 100644 fibocom-dial/src/libmnl/ifutils.c delete mode 100644 fibocom-dial/src/libmnl/ifutils.h delete mode 100644 fibocom-dial/src/libmnl/libmnl.h delete mode 100644 fibocom-dial/src/libmnl/nlmsg.c delete mode 100644 fibocom-dial/src/libmnl/socket.c delete mode 100644 fibocom-dial/src/main.c delete mode 100644 fibocom-dial/src/multi-pdn-manager.c delete mode 100644 fibocom-dial/src/multi-pdn.ini delete mode 100644 fibocom-dial/src/qmap_bridge_mode.c delete mode 100644 fibocom-dial/src/query_pcie_mode.c delete mode 100644 fibocom-dial/src/query_pcie_mode.h delete mode 100644 fibocom-dial/src/udhcpc.c delete mode 100644 fibocom-dial/src/udhcpc_netlink.c delete mode 100644 fibocom-dial/src/util.c delete mode 100644 fibocom-dial/src/util.h delete mode 100644 fibocom_MHI/Makefile delete mode 100644 fibocom_MHI/src/Kconfig delete mode 100644 fibocom_MHI/src/Makefile delete mode 100644 fibocom_MHI/src/controllers/mhi_qcom.c delete mode 100644 fibocom_MHI/src/controllers/mhi_qcom.h delete mode 100644 fibocom_MHI/src/controllers/mhi_qcom_arm.h delete mode 100644 fibocom_MHI/src/controllers/mhi_qcom_x86.h delete mode 100644 fibocom_MHI/src/core/mhi.h delete mode 100644 fibocom_MHI/src/core/mhi_boot.c delete mode 100644 fibocom_MHI/src/core/mhi_common.h delete mode 100644 fibocom_MHI/src/core/mhi_dtr.c delete mode 100644 fibocom_MHI/src/core/mhi_init.c delete mode 100644 fibocom_MHI/src/core/mhi_internal.h delete mode 100644 fibocom_MHI/src/core/mhi_main.c delete mode 100644 fibocom_MHI/src/core/mhi_pm.c delete mode 100644 fibocom_MHI/src/devices/mhi_netdev.c delete mode 100644 fibocom_MHI/src/devices/mhi_netdev.h delete mode 100644 fibocom_MHI/src/devices/mhi_uci.c delete mode 100644 fibocom_QMI_WWAN/Makefile delete mode 100644 fibocom_QMI_WWAN/src/Makefile delete mode 100644 fibocom_QMI_WWAN/src/qmi_wwan_f.c delete mode 100644 luci-app-cpe/Makefile delete mode 100644 luci-app-cpe/luasrc/controller/admin/cpe.lua delete mode 100644 luci-app-cpe/luasrc/model/cbi/cpe/modem.lua delete mode 100644 luci-app-cpe/luasrc/view/cpe/at.htm delete mode 100644 luci-app-cpe/luasrc/view/cpe/net_status.htm delete mode 100644 luci-app-cpe/po/zh-cn/modem.po delete mode 100644 luci-app-cpe/po/zh_Hans delete mode 100644 luci-app-cpe/root/etc/config/modem delete mode 100644 luci-app-cpe/root/etc/init.d/cpeinit delete mode 100644 luci-app-cpe/root/etc/init.d/modem delete mode 100644 luci-app-cpe/root/etc/uci-defaults/luci-modem delete mode 100644 luci-app-cpe/root/usr/bin/bmask128 delete mode 100644 luci-app-cpe/root/usr/bin/chan2band.sh delete mode 100644 luci-app-cpe/root/usr/bin/encodemask delete mode 100644 luci-app-cpe/root/usr/bin/jkillall delete mode 100644 luci-app-cpe/root/usr/bin/rsrp2rssi delete mode 100644 luci-app-cpe/root/usr/bin/set_gpio delete mode 100644 luci-app-cpe/root/usr/share/cpe/Fibocom delete mode 100644 luci-app-cpe/root/usr/share/cpe/Quectel delete mode 100644 luci-app-cpe/root/usr/share/cpe/SIMCOM delete mode 100644 luci-app-cpe/root/usr/share/cpe/atcmd.sh delete mode 100644 luci-app-cpe/root/usr/share/cpe/cpedebug delete mode 100644 luci-app-cpe/root/usr/share/cpe/delatcmd.sh delete mode 100644 luci-app-cpe/root/usr/share/cpe/rssi delete mode 100644 luci-app-gobinetmodem/Makefile delete mode 100644 luci-app-gobinetmodem/luasrc/controller/gobinetmodem.lua delete mode 100644 luci-app-gobinetmodem/luasrc/model/cbi/gobinetmodem.lua delete mode 100644 luci-app-gobinetmodem/po/zh-cn/usbmodem.po delete mode 100644 luci-app-gobinetmodem/root/etc/config/gobinetmodem delete mode 100644 luci-app-gobinetmodem/root/etc/init.d/gobinetmodem delete mode 100644 luci-app-gobinetmodem/root/etc/uci-defaults/luci-gobinetmodem delete mode 100644 luci-app-hypermodem/Makefile delete mode 100644 luci-app-hypermodem/README.md delete mode 100644 luci-app-hypermodem/luasrc/controller/hypermodem.lua delete mode 100644 luci-app-hypermodem/luasrc/model/cbi/hypermodem.lua delete mode 100644 luci-app-hypermodem/po/zh-cn/hypermodem.po delete mode 100644 luci-app-hypermodem/root/etc/config/hypermodem delete mode 100755 luci-app-hypermodem/root/etc/init.d/hypermodem delete mode 100755 luci-app-hypermodem/root/etc/uci-defaults/luci-hypermodem delete mode 100644 luci-app-pcimodem/Makefile delete mode 100644 luci-app-pcimodem/luasrc/controller/pcimodem.lua delete mode 100644 luci-app-pcimodem/luasrc/model/cbi/pcimodem.lua delete mode 100644 luci-app-pcimodem/po/zh-cn/pcimodem.po delete mode 100644 luci-app-pcimodem/root/etc/config/pcimodem delete mode 100644 luci-app-pcimodem/root/etc/init.d/pcimodem delete mode 100644 luci-app-pcimodem/root/etc/uci-defaults/luci-pcimodem delete mode 100644 luci-app-sms-tool/LICENSE delete mode 100644 luci-app-sms-tool/Makefile delete mode 100644 luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms.png delete mode 100644 luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms2.png delete mode 100644 luci-app-sms-tool/luasrc/controller/modem/sms.lua delete mode 100644 luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua delete mode 100644 luci-app-sms-tool/luasrc/view/modem/atcommands.htm delete mode 100644 luci-app-sms-tool/luasrc/view/modem/readsms.htm delete mode 100644 luci-app-sms-tool/luasrc/view/modem/sendsms.htm delete mode 100644 luci-app-sms-tool/luasrc/view/modem/ussd.htm delete mode 100644 luci-app-sms-tool/po/pl/sms-tool.po delete mode 100644 luci-app-sms-tool/po/zh-cn/sms-tool.po delete mode 100644 luci-app-sms-tool/root/etc/config/atcmds.user delete mode 100644 luci-app-sms-tool/root/etc/config/phonebook.user delete mode 100644 luci-app-sms-tool/root/etc/config/sms_tool delete mode 100755 luci-app-sms-tool/root/etc/init.d/smsled delete mode 100755 luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh delete mode 100755 luci-app-sms-tool/root/etc/uci-defaults/start-smsled delete mode 100755 luci-app-sms-tool/root/sbin/cronsync.sh delete mode 100755 luci-app-sms-tool/root/sbin/set_sms_ports.sh delete mode 100755 luci-app-sms-tool/root/sbin/smsled-init.sh delete mode 100755 luci-app-sms-tool/root/sbin/smsled.sh delete mode 100644 luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json delete mode 100644 luci-app-spdmodem/Makefile delete mode 100644 luci-app-spdmodem/luasrc/controller/spdmodem.lua delete mode 100644 luci-app-spdmodem/luasrc/model/cbi/spdmodem.lua delete mode 100644 luci-app-spdmodem/po/zh-cn/spdmodem.po delete mode 100644 luci-app-spdmodem/root/etc/config/spdmodem delete mode 100644 luci-app-spdmodem/root/etc/init.d/spdmodem delete mode 100644 luci-app-spdmodem/root/etc/uci-defaults/luci-spdmodem delete mode 100644 luci-app-usbmodem/Makefile delete mode 100644 luci-app-usbmodem/luasrc/controller/usbmodem.lua delete mode 100644 luci-app-usbmodem/luasrc/model/cbi/usbmodem.lua delete mode 100644 luci-app-usbmodem/po/zh-cn/usbmodem.po delete mode 100644 luci-app-usbmodem/root/etc/config/usbmodem delete mode 100644 luci-app-usbmodem/root/etc/init.d/usbmodem delete mode 100644 luci-app-usbmodem/root/etc/uci-defaults/luci-usbmodem delete mode 100644 quectel_Gobinet/Makefile delete mode 100644 quectel_Gobinet/src/GobiUSBNet.c delete mode 100644 quectel_Gobinet/src/Makefile delete mode 100644 quectel_Gobinet/src/QMI.c delete mode 100644 quectel_Gobinet/src/QMI.h delete mode 100644 quectel_Gobinet/src/QMIDevice.c delete mode 100644 quectel_Gobinet/src/QMIDevice.h delete mode 100644 quectel_Gobinet/src/Readme.txt delete mode 100644 quectel_Gobinet/src/ReleaseNote.txt delete mode 100644 quectel_Gobinet/src/Structs.h delete mode 100644 quectel_MHI/Makefile delete mode 100644 quectel_MHI/src/Makefile delete mode 100644 quectel_MHI/src/README delete mode 100644 quectel_MHI/src/ReleaseNote.txt delete mode 100644 quectel_MHI/src/controllers/Kconfig delete mode 100644 quectel_MHI/src/controllers/Makefile delete mode 100644 quectel_MHI/src/controllers/mhi_arch_qti.c delete mode 100644 quectel_MHI/src/controllers/mhi_qcom.c delete mode 100644 quectel_MHI/src/controllers/mhi_qcom.h delete mode 100644 quectel_MHI/src/controllers/mhi_qti.c delete mode 100644 quectel_MHI/src/controllers/mhi_qti.h delete mode 100644 quectel_MHI/src/core/Makefile delete mode 100644 quectel_MHI/src/core/mhi.h delete mode 100644 quectel_MHI/src/core/mhi_boot.c delete mode 100644 quectel_MHI/src/core/mhi_dtr.c delete mode 100644 quectel_MHI/src/core/mhi_init.c delete mode 100644 quectel_MHI/src/core/mhi_internal.h delete mode 100644 quectel_MHI/src/core/mhi_main.c delete mode 100644 quectel_MHI/src/core/mhi_pm.c delete mode 100644 quectel_MHI/src/core/mhi_sdx20.h delete mode 100644 quectel_MHI/src/core/sdx20_mhi.h delete mode 100644 quectel_MHI/src/devices/Kconfig delete mode 100644 quectel_MHI/src/devices/Makefile delete mode 100644 quectel_MHI/src/devices/mhi_netdev.c delete mode 100644 quectel_MHI/src/devices/mhi_netdev_quectel.c delete mode 100644 quectel_MHI/src/devices/mhi_satellite.c delete mode 100644 quectel_MHI/src/devices/mhi_uci.c delete mode 100644 quectel_MHI/src/devices/rmnet/Kconfig delete mode 100644 quectel_MHI/src/devices/rmnet/Makefile delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_config.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_config.h delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_data.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_descriptor.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_descriptor.h delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_handlers.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_handlers.h delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_map.h delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_map_command.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_map_data.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_private.h delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_trace.h delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_vnd.c delete mode 100644 quectel_MHI/src/devices/rmnet/rmnet_vnd.h delete mode 100644 quectel_MHI/src/devices/rmnet_handler.c delete mode 100644 quectel_MHI/src/devices/rmnet_nss.c delete mode 100644 quectel_MHI/src/log/AT_OVER_PCIE.txt delete mode 100644 quectel_MHI/src/log/MBIM_OVER_PCIE.txt delete mode 100644 quectel_MHI/src/log/QMI_OVER_PCIE.txt delete mode 100644 quectel_MHI/src/log/QXDM_OVER_PCIE.txt delete mode 100644 quectel_SRPD_PCIE/Makefile delete mode 100644 quectel_SRPD_PCIE/src/Makefile delete mode 100644 quectel_SRPD_PCIE/src/include/mdm_ctrl.h delete mode 100644 quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h delete mode 100644 quectel_SRPD_PCIE/src/include/sipa.h delete mode 100644 quectel_SRPD_PCIE/src/include/sipc.h delete mode 100644 quectel_SRPD_PCIE/src/include/sipc_big_to_little.h delete mode 100644 quectel_SRPD_PCIE/src/include/sprd_mpm.h delete mode 100644 quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h delete mode 100644 quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h delete mode 100644 quectel_SRPD_PCIE/src/mcd/Kconfig delete mode 100644 quectel_SRPD_PCIE/src/mcd/Makefile delete mode 100644 quectel_SRPD_PCIE/src/mcd/modem_ctrl.c delete mode 100644 quectel_SRPD_PCIE/src/pcie/Kconfig delete mode 100644 quectel_SRPD_PCIE/src/pcie/Makefile delete mode 100644 quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c delete mode 100644 quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c delete mode 100644 quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c delete mode 100644 quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h delete mode 100644 quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c delete mode 100644 quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c delete mode 100644 quectel_SRPD_PCIE/src/power_manager/Makefile delete mode 100644 quectel_SRPD_PCIE/src/power_manager/power_manager.c delete mode 100644 quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/Kconfig delete mode 100644 quectel_SRPD_PCIE/src/sipa/Makefile delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_core.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_core.h delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_dummy.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_eth.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_eth.h delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_nic.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c delete mode 100644 quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/Kconfig delete mode 100644 quectel_SRPD_PCIE/src/sipc/Makefile delete mode 100644 quectel_SRPD_PCIE/src/sipc/sblock.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/sblock.h delete mode 100644 quectel_SRPD_PCIE/src/sipc/sbuf.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/sbuf.h delete mode 100644 quectel_SRPD_PCIE/src/sipc/sipc.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h delete mode 100644 quectel_SRPD_PCIE/src/sipc/sipc_priv.h delete mode 100644 quectel_SRPD_PCIE/src/sipc/smem.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/smsg.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/spipe.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/spipe.h delete mode 100644 quectel_SRPD_PCIE/src/sipc/spool.c delete mode 100644 quectel_SRPD_PCIE/src/sipc/spool.h delete mode 100644 quectel_cm_5G/Makefile delete mode 100644 quectel_cm_5G/files/dhcp delete mode 100644 quectel_cm_5G/files/rmnet.script delete mode 100644 quectel_cm_5G/files/rmnet.sh delete mode 100644 quectel_cm_5G/files/rmnet6.script delete mode 100644 quectel_cm_5G/files/rmnet6.sh delete mode 100644 quectel_cm_5G/files/rmnet_init.sh delete mode 100644 quectel_cm_5G/src/CMakeLists.txt delete mode 100644 quectel_cm_5G/src/GobiNetCM.c delete mode 100644 quectel_cm_5G/src/MPQCTL.h delete mode 100644 quectel_cm_5G/src/MPQMI.h delete mode 100644 quectel_cm_5G/src/MPQMUX.c delete mode 100644 quectel_cm_5G/src/MPQMUX.h delete mode 100644 quectel_cm_5G/src/Makefile delete mode 100644 quectel_cm_5G/src/Makefile.am delete mode 100644 quectel_cm_5G/src/NOTICE delete mode 100644 quectel_cm_5G/src/QMIThread.c delete mode 100644 quectel_cm_5G/src/QMIThread.h delete mode 100644 quectel_cm_5G/src/QmiWwanCM.c delete mode 100644 quectel_cm_5G/src/ReleaseNote.txt delete mode 100644 quectel_cm_5G/src/at_tok.c delete mode 100644 quectel_cm_5G/src/at_tok.h delete mode 100644 quectel_cm_5G/src/atc.c delete mode 100644 quectel_cm_5G/src/atchannel.c delete mode 100644 quectel_cm_5G/src/atchannel.h delete mode 100644 quectel_cm_5G/src/configure.ac delete mode 100644 quectel_cm_5G/src/default.script delete mode 100644 quectel_cm_5G/src/default.script_ip delete mode 100644 quectel_cm_5G/src/device.c delete mode 100644 quectel_cm_5G/src/ethtool-copy.h delete mode 100644 quectel_cm_5G/src/log/cdc_mbim.txt delete mode 100644 quectel_cm_5G/src/log/cdc_mbim_vlan.txt delete mode 100644 quectel_cm_5G/src/log/ecm_ncm_rndis.txt delete mode 100644 quectel_cm_5G/src/log/gobinet.txt delete mode 100644 quectel_cm_5G/src/log/gobinet_bridge.txt delete mode 100644 quectel_cm_5G/src/log/gobinet_qmap=1.txt delete mode 100644 quectel_cm_5G/src/log/gobinet_qmap=1_bridge.txt delete mode 100644 quectel_cm_5G/src/log/gobinet_qmap=4.txt delete mode 100644 quectel_cm_5G/src/log/gobinet_qmap=4_bridge.txt delete mode 100644 quectel_cm_5G/src/log/pcie_mhi_mbim.txt delete mode 100644 quectel_cm_5G/src/log/pcie_mhi_mbim_qmap=4.txt delete mode 100644 quectel_cm_5G/src/log/pcie_mhi_qmap=1.txt delete mode 100644 quectel_cm_5G/src/log/pcie_mhi_qmap=1_bridge.txt delete mode 100644 quectel_cm_5G/src/log/pcie_mhi_qmap=4.txt delete mode 100644 quectel_cm_5G/src/log/pcie_mhi_qmap=4_bridge.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_q.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_q_bridge.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_q_qmap=1.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_q_qmap=1_bridge.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_q_qmap=4.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_q_qmap=4_bridge.txt delete mode 100644 quectel_cm_5G/src/log/qmi_wwan_qmap=4.txt delete mode 100644 quectel_cm_5G/src/log/usage_of_argument/6.txt delete mode 100644 quectel_cm_5G/src/log/usage_of_argument/m.txt delete mode 100644 quectel_cm_5G/src/main.c delete mode 100644 quectel_cm_5G/src/mbim-cm.c delete mode 100644 quectel_cm_5G/src/qendian.h delete mode 100644 quectel_cm_5G/src/qlist.h delete mode 100644 quectel_cm_5G/src/qmap_bridge_mode.c delete mode 100644 quectel_cm_5G/src/qrtr.c delete mode 100644 quectel_cm_5G/src/qrtr.h delete mode 100644 quectel_cm_5G/src/quectel-atc-proxy.c delete mode 100644 quectel_cm_5G/src/quectel-mbim-proxy.c delete mode 100644 quectel_cm_5G/src/quectel-qmi-proxy.c delete mode 100644 quectel_cm_5G/src/quectel-qrtr-proxy.c delete mode 100644 quectel_cm_5G/src/rmnetctl.c delete mode 100644 quectel_cm_5G/src/udhcpc.c delete mode 100644 quectel_cm_5G/src/udhcpc_netlink.c delete mode 100644 quectel_cm_5G/src/udhcpc_script.c delete mode 100644 quectel_cm_5G/src/util.c delete mode 100644 quectel_cm_5G/src/util.h delete mode 100644 rooter/0basicapps/ext-command/Makefile delete mode 100644 rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua delete mode 100644 rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua delete mode 100644 rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm delete mode 100644 rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm delete mode 100644 rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy delete mode 100644 rooter/0basicapps/ext-extra/Makefile delete mode 100644 rooter/0basicapps/ext-extra/files/etc/config/schedule delete mode 100644 rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua delete mode 100644 rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua delete mode 100644 rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua delete mode 100644 rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh delete mode 100644 rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh delete mode 100644 rooter/0basicapps/ext-p910nd/Makefile delete mode 100644 rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx delete mode 100644 rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua delete mode 100644 rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua delete mode 100644 rooter/0basicapps/usb-storage/Makefile delete mode 100644 rooter/0basicapps/usb-storage/files/etc/config/umount delete mode 100644 rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount delete mode 100644 rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount delete mode 100644 rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount delete mode 100644 rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle delete mode 100644 rooter/0basicapps/usb-storage/files/etc/umount delete mode 100644 rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua delete mode 100644 rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua delete mode 100644 rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua delete mode 100644 rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua delete mode 100644 rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh delete mode 100644 rooter/0basicsupport/ext-buttons/Makefile delete mode 100644 rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh delete mode 100644 rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button delete mode 100644 rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk delete mode 100644 rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons delete mode 100644 rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua delete mode 100644 rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua delete mode 100644 rooter/0basicsupport/ext-sms/Makefile delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/delall.sh delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/merge.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh delete mode 100644 rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/Makefile delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm delete mode 100644 rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm delete mode 100644 rooter/0drivers/rmbim/.svn/entries delete mode 100644 rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base delete mode 100644 rooter/0drivers/rmbim/Makefile delete mode 100644 rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh delete mode 100644 rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh delete mode 100644 rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh delete mode 100644 rooter/0drivers/rqmi/Makefile delete mode 100644 rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh delete mode 100644 rooter/0optionalapps/bwallocate/Makefile delete mode 100644 rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint delete mode 100644 rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua delete mode 100644 rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua delete mode 100644 rooter/0optionalapps/bwmon/Makefile delete mode 100644 rooter/0optionalapps/bwmon/files/etc/config/bwmon delete mode 100644 rooter/0optionalapps/bwmon/files/etc/init.d/bwmon delete mode 100644 rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua delete mode 100644 rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm delete mode 100644 rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk delete mode 100644 rooter/0optionalapps/ext-autoapn/Makefile delete mode 100644 rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data delete mode 100644 rooter/0optionalapps/ext-blacklist/Makefile delete mode 100644 rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist delete mode 100644 rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh delete mode 100644 rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh delete mode 100644 rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua delete mode 100644 rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua delete mode 100644 rooter/0optionalapps/ext-blockport/Makefile delete mode 100644 rooter/0optionalapps/ext-blockport/files/etc/config/blockport delete mode 100644 rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.sh delete mode 100644 rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua delete mode 100644 rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua delete mode 100644 rooter/0optionalapps/ext-domain/Makefile delete mode 100644 rooter/0optionalapps/ext-domain/files/etc/config/blockport delete mode 100644 rooter/0optionalapps/ext-domain/files/usr/lib/blockport/blockport.sh delete mode 100644 rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/blockport.lua delete mode 100644 rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/portblk.lua delete mode 100644 rooter/0optionalapps/ext-rspeedtest/Makefile delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/prov.png delete mode 100644 rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/user.png delete mode 100644 rooter/0optionalapps/ext-speedtest/Makefile delete mode 100644 rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua delete mode 100644 rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.eot delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.ttf delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.woff delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/favicon.gif delete mode 100644 rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/kangaroo_800.png delete mode 100644 rooter/0optionalapps/ext-texting/Makefile delete mode 100644 rooter/0optionalapps/ext-texting/files/etc/config/texting delete mode 100644 rooter/0optionalapps/ext-texting/files/etc/init.d/texting delete mode 100644 rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/chksms.sh delete mode 100644 rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh delete mode 100644 rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh delete mode 100644 rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua delete mode 100644 rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua delete mode 100644 rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm delete mode 100644 rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/Makefile delete mode 100644 rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard delete mode 100644 rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes delete mode 100644 rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh delete mode 100644 rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard.png delete mode 100644 rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard_disabled.png delete mode 100644 rooter/0optionalapps/ext-zerotier/Makefile delete mode 100644 rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire delete mode 100644 rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier delete mode 100644 rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua delete mode 100644 rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm delete mode 100644 rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm delete mode 100644 rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm delete mode 100644 rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh delete mode 100644 rooter/0optionalapps/extramenu/Makefile delete mode 100644 rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu delete mode 100644 rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh delete mode 100644 rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua delete mode 100644 rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm delete mode 100644 rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile delete mode 100644 rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset delete mode 100644 rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset delete mode 100644 rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua delete mode 100644 rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua delete mode 100644 rooter/0optionalapps/luci-app-hotspot/Makefile delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog delete mode 100644 rooter/0optionalapps/luci-app-hotspot/files/www/luci-static/resources/icons/encryption.png delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/Makefile delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/controller/nft-qos.lua delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/model/cbi/nft-qos/nft-qos.lua delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/view/nft-qos/rate.htm delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/bg/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/ca/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/cs/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/de/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/el/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/en/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/es/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/fr/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/he/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/hi/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/hu/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/it/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/ja/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/ko/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/mr/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/ms/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/nb_NO/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/pl/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/pt/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/pt_BR/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/ro/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/ru/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/sk/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/sv/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/templates/nft-qos.pot delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/tr/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/uk/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/vi/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/zh_Hans/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/po/zh_Hant/nft-qos.po delete mode 100644 rooter/0optionalapps/luci-app-nft-qos/root/usr/share/rpcd/acl.d/luci-app-nft-qos.json delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/Makefile delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/etc/uci-defaults/40_luci-ddns delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/controller/ddns.lua delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/detail.lua delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/global.lua delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/hints.lua delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/overview.lua delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/tools/ddns.lua delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/admin_status/index/ddns.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_logview.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_lvalue.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_value.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/global_value.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_doubleline.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_enabled.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_startstop.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_status.htm delete mode 100644 rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/system_status.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/Makefile delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-disabled.png delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-started.png delete mode 100644 rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-stopped.png delete mode 100644 rooter/0optionalapps/nft-qos/Makefile delete mode 100644 rooter/0optionalapps/nft-qos/files/lib/core.sh delete mode 100644 rooter/0optionalapps/nft-qos/files/lib/dynamic.sh delete mode 100644 rooter/0optionalapps/nft-qos/files/lib/monitor.sh delete mode 100644 rooter/0optionalapps/nft-qos/files/lib/priority.sh delete mode 100644 rooter/0optionalapps/nft-qos/files/lib/static.sh delete mode 100644 rooter/0optionalapps/nft-qos/files/nft-qos-dynamic.hotplug delete mode 100644 rooter/0optionalapps/nft-qos/files/nft-qos-monitor.hotplug delete mode 100644 rooter/0optionalapps/nft-qos/files/nft-qos.config delete mode 100644 rooter/0optionalapps/nft-qos/files/nft-qos.init delete mode 100644 rooter/0optionalapps/pingtest/Makefile delete mode 100644 rooter/0optionalapps/pingtest/files/etc/config/ping delete mode 100644 rooter/0optionalapps/pingtest/files/etc/init.d/pingtest delete mode 100644 rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh delete mode 100644 rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh delete mode 100644 rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua delete mode 100644 rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua delete mode 100644 rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm delete mode 100644 rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm delete mode 100644 rooter/0optionalapps/qfirehose/Makefile delete mode 100644 rooter/0optionalapps/qfirehose/src/Makefile delete mode 100644 rooter/0optionalapps/qfirehose/src/firehose_protocol.c delete mode 100644 rooter/0optionalapps/qfirehose/src/hostdl_packet.h delete mode 100644 rooter/0optionalapps/qfirehose/src/md5.c delete mode 100644 rooter/0optionalapps/qfirehose/src/md5.h delete mode 100644 rooter/0optionalapps/qfirehose/src/qfirehose.c delete mode 100644 rooter/0optionalapps/qfirehose/src/sahara_protocol.c delete mode 100644 rooter/0optionalapps/qfirehose/src/sahara_protocol.h delete mode 100644 rooter/0optionalapps/qfirehose/src/stream_download_protocol.c delete mode 100644 rooter/0optionalapps/qfirehose/src/usb2tcp.c delete mode 100644 rooter/0optionalapps/qfirehose/src/usb_linux.c delete mode 100644 rooter/0optionalapps/qfirehose/src/usb_linux.h delete mode 100644 rooter/0optionalapps/qlog/Makefile delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T1.LinuxData-OTA-DataService-AP_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T2.RegServ-CotextAct_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T4.Throughput_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T6.FullMessage.SimpleLogPacket(AT)_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/T7.V2X_ALL_V01.cfg delete mode 100644 rooter/0optionalapps/qlog/files/usr/lib/conf/default.cfg delete mode 100644 rooter/0optionalapps/qlog/src/Makefile delete mode 100644 rooter/0optionalapps/qlog/src/asr.c delete mode 100644 rooter/0optionalapps/qlog/src/main.c delete mode 100644 rooter/0optionalapps/qlog/src/mdm.c delete mode 100644 rooter/0optionalapps/qlog/src/qlog.h delete mode 100644 rooter/0optionalapps/qlog/src/sahara.c delete mode 100644 rooter/0optionalapps/qlog/src/sahara_protocol.h delete mode 100644 rooter/0optionalapps/qlog/src/tty2tcp.c delete mode 100644 rooter/0optionalapps/udp-tunnel/Makefile delete mode 100644 rooter/0optionalapps/udp-tunnel/src/Makefile delete mode 100644 rooter/0optionalapps/udp-tunnel/src/log.c delete mode 100644 rooter/0optionalapps/udp-tunnel/src/log.h delete mode 100644 rooter/0optionalapps/udp-tunnel/src/network.c delete mode 100644 rooter/0optionalapps/udp-tunnel/src/network.h delete mode 100644 rooter/0optionalapps/udp-tunnel/src/udptunnel.c delete mode 100644 rooter/0optionalapps/udp-tunnel/src/utils.c delete mode 100644 rooter/0optionalapps/udp-tunnel/src/utils.h delete mode 100644 rooter/0optionalapps/webconsole/Makefile delete mode 100644 rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua delete mode 100644 rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm delete mode 100644 rooter/0protocols/luci-proto-3x/Makefile delete mode 100644 rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua delete mode 100644 rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua delete mode 100644 rooter/0protocols/luci-proto-mbim/Makefile delete mode 100644 rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/cbi/admin_network/proto_mbim.lua delete mode 100644 rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua delete mode 100644 rooter/0routerspecfic/rd05a1/Makefile delete mode 100644 rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr delete mode 100644 rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/QCA9887/hw1.0/board.bin delete mode 100644 rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/QCA9887/hw1.0/firmware-5.bin delete mode 100644 rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/cal-pci-0000_00_00.0.bin delete mode 100644 rooter/0routerspecfic/we826q/Makefile delete mode 100644 rooter/0routerspecfic/we826q/files/etc/init.d/wd-init delete mode 100644 rooter/0routerspecfic/we826q/files/usr/lib/custom/watchdog.sh delete mode 100644 rooter/0routerspecfic/we826q/files/usr/lib/rooter/changedevice.sh delete mode 100644 rooter/0splash/ext-splash/Makefile delete mode 100644 rooter/0splash/ext-splash/files/etc/config/iframe delete mode 100644 rooter/0splash/ext-splash/files/etc/init.d/iframeint delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/band.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/image.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/mframe.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/open.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/status.html delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh delete mode 100644 rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/display.html delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/iframe.html delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/img/favicon.gif delete mode 100644 rooter/0splash/ext-splash/files/www/luci-static/rooter/img/kangaroo_800.png delete mode 100644 rooter/0splash/ext-splash/files/www/splash_files/check1.gif delete mode 100644 rooter/0splash/ext-splashconfig/Makefile delete mode 100644 rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua delete mode 100644 rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua delete mode 100644 rooter/0splash/splash/Makefile delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/img/favicon.gif delete mode 100644 rooter/0splash/splash/files/www/luci-static/rooter/img/kangaroo_800.png delete mode 100644 rooter/0splash/splash/files/www/splash.html delete mode 100644 rooter/0splash/splash/files/www/splash_files/cellular.png delete mode 100644 rooter/0splash/splash/files/www/splash_files/check.gif delete mode 100644 rooter/0splash/splash/files/www/splash_files/check.jpg delete mode 100644 rooter/0splash/splash/files/www/splash_files/forum.png delete mode 100644 rooter/0splash/splash/files/www/splash_files/home.png delete mode 100644 rooter/0splash/splash/files/www/splash_files/kanga1.png delete mode 100644 rooter/0splash/splash/files/www/splash_files/openwrt.png delete mode 100644 rooter/0splash/splash/files/www/splash_files/rooter.png delete mode 100644 rooter/0splash/splash/files/www/status.html delete mode 100644 rooter/0splash/status/Makefile delete mode 100644 rooter/0splash/status/files/etc/config/splash delete mode 100644 rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua delete mode 100644 rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua delete mode 100644 rooter/0splash/status/files/usr/lib/splash/check.gif delete mode 100644 rooter/0splash/status/files/usr/lib/splash/full.gif delete mode 100644 rooter/0splash/status/files/usr/lib/splash/splash.sh delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/css/splash.css delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.eot delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.ttf delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.woff delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/img/favicon.gif delete mode 100644 rooter/0splash/status/files/www/luci-static/rooter/img/kangaroo_800.png delete mode 100644 rooter/0splash/status/files/www/splash.html delete mode 100644 rooter/0splash/status/files/www/splash_files/cellular.png delete mode 100644 rooter/0splash/status/files/www/splash_files/check.gif delete mode 100644 rooter/0splash/status/files/www/splash_files/check.jpg delete mode 100644 rooter/0splash/status/files/www/splash_files/forum.png delete mode 100644 rooter/0splash/status/files/www/splash_files/full.gif delete mode 100644 rooter/0splash/status/files/www/splash_files/home.png delete mode 100644 rooter/0splash/status/files/www/splash_files/kanga1.png delete mode 100644 rooter/0splash/status/files/www/splash_files/openwrt.png delete mode 100644 rooter/0splash/status/files/www/splash_files/rooter.png delete mode 100644 rooter/0splash/status/files/www/splashfull.html delete mode 100644 rooter/0splash/status/files/www/statusfull.html delete mode 100644 rooter/ext-rooter-basic/Makefile delete mode 100644 rooter/ext-rooter-basic/files/etc/codename delete mode 100644 rooter/ext-rooter-basic/files/etc/config/custom delete mode 100644 rooter/ext-rooter-basic/files/etc/config/modem delete mode 100644 rooter/ext-rooter-basic/files/etc/config/profile delete mode 100644 rooter/ext-rooter-basic/files/etc/config/ttl delete mode 100644 rooter/ext-rooter-basic/files/etc/genericcmd delete mode 100644 rooter/ext-rooter-basic/files/etc/header_msg delete mode 100644 rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan delete mode 100644 rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter delete mode 100644 rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x delete mode 100644 rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode delete mode 100644 rooter/ext-rooter-basic/files/etc/init.d/clear delete mode 100644 rooter/ext-rooter-basic/files/etc/init.d/iphone delete mode 100644 rooter/ext-rooter-basic/files/etc/init.d/rooter delete mode 100644 rooter/ext-rooter-basic/files/etc/init.d/usbmode delete mode 100644 rooter/ext-rooter-basic/files/etc/lockdown/locks/0000000000000000000000000000000000000000.plist delete mode 100644 rooter/ext-rooter-basic/files/etc/netspeed delete mode 100644 rooter/ext-rooter-basic/files/etc/quectelcmd delete mode 100644 rooter/ext-rooter-basic/files/etc/sierracmd delete mode 100644 rooter/ext-rooter-basic/files/etc/ttl.user delete mode 100644 rooter/ext-rooter-basic/files/etc/usb-mode.json delete mode 100644 rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh delete mode 100644 rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles delete mode 100644 rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local delete mode 100644 rooter/ext-rooter-basic/files/usr/bin/bmask128 delete mode 100644 rooter/ext-rooter-basic/files/usr/bin/chan2band.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/bin/encodemask delete mode 100644 rooter/ext-rooter-basic/files/usr/bin/jkillall delete mode 100644 rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi delete mode 100644 rooter/ext-rooter-basic/files/usr/bin/set_gpio delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/proto.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua delete mode 100644 rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh delete mode 100644 rooter/ext-rooter-basic/files/usr/sbin/modlog delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/background/main_bg.jpg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/css/dark.css delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Medium-webfont.woff delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Regular-webfont.woff delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.eot delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.ttf delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.woff delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.eot delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.ttf delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.woff delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.eot delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.ttf delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.woff delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/font.eot delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/font.ttf delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/font.woff delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/fonts/fonts.css delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/android-icon-192x192.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-144x144.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-60x60.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-72x72.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-16x16.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-32x32.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-96x96.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/manifest.json delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icon/ms-icon-144x144.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/img/blank.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/img/open.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/resources/icons/lock1.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/resources/icons/unlock1.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/resources/img/header.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/resources/img/rooter.png delete mode 100644 rooter/ext-rooter-basic/files/www/luci-static/resources/img/rosy.png delete mode 100644 sendat/Makefile delete mode 100644 sendat/README.md delete mode 100644 sendat/src/Makefile delete mode 100644 sendat/src/pdu.c delete mode 100644 sendat/src/pdu.h delete mode 100644 sendat/src/pdu_decoder.c delete mode 100644 sendat/src/sendat.c delete mode 100644 sendat/src/ucs2_to_utf8.c diff --git a/README.md b/README.md deleted file mode 100644 index 9454492..0000000 --- a/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# 中文 | [English](https://github.com/Siriling/5G-Modem-Support/blob/main/EngLish.md) - -# 5G模块支持 - -# 目录 - -[一、说明](#一说明) - -[二、源代码地址 ](#二源代码地址) - -# 一、说明 - -## 5G驱动 - -- quectel_Gobinet -- quectel_MHI -- quectel_QMI_WWAN -- quectel_SRPD_PCIE -- fibocom_MHI -- fibocom_QMI_WWAN - -## 拨号工具 - -- quectel_cm_5G -- fibocom-dial - -## 图形化界面设置 - -### 拨号 - -- luci-app-modem(新) - -- luci-app-hypermodem -- luci-app-usbmodem -- luci-app-pcimodem -- luci-app-gobinetmodem -- luci-app-spdmodem - -### 信息插件 - -- rooter - -### 简化版信息插件 - -- luci-app-cpe - -### AT命令工具 - -- sendat -- sms-tool - -### 短信工具 - -- luci-app-sms-tool - -# 二、源代码地址 - -- luci-app-hypermodem:https://github.com/momokind/luci-app-hypermodem - -- sendat:https://github.com/ouyangzq/sendat -- luci-app-cpe:https://github.com/ouyangzq/luci-app-cpe -- sms-tool:https://github.com/obsy/sms_tool - diff --git a/fibocom-dial/Makefile b/fibocom-dial/Makefile deleted file mode 100644 index a454549..0000000 --- a/fibocom-dial/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=fibocom-dial -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/fibocom-dial - SECTION:=utils - CATEGORY:=Utilities - TITLE:=Fibocom Dial -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/fibocom-dial/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/fibocom-dial $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/fibo_qmimsg_server $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/multi-pdn-manager $(1)/usr/bin -endef - -$(eval $(call BuildPackage,fibocom-dial)) diff --git a/fibocom-dial/src/GobiNetCM.c b/fibocom-dial/src/GobiNetCM.c deleted file mode 100644 index d1f6464..0000000 --- a/fibocom-dial/src/GobiNetCM.c +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include -#include -#include - -#include "QMIThread.h" - -#ifdef CONFIG_GOBINET - -// IOCTL to generate a client ID for this service type -#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1 - -// IOCTL to get the VIDPID of the device -#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2 - -// IOCTL to get the MEID of the device -#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3 - -static int GobiNetSendQMI(PQCQMIMSG pRequest) -{ - int ret, fd; - - static int send_count = 0; - fd = qmiclientId[pRequest->QMIHdr.QMIType]; - - if (fd <= 0) { - dbg_time("%s QMIType: %d has no clientID", __func__, - pRequest->QMIHdr.QMIType); - return -ENODEV; - } - - // Always ready to write -re_write: - if (1 == 1) { - ssize_t nwrites = - le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR); - ret = write(fd, &pRequest->MUXMsg, nwrites); - if (ret == nwrites) - { - ret = 0; - send_count = 0; - } - else - { - send_count++; - dbg_time("%s write=%d, errno: %d (%s) send_count %d", __func__, ret, errno, strerror(errno), send_count); - if (send_count < 3) - { - sleep(1); - goto re_write; - } - } - - } else { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, - strerror(errno)); - } - - return ret; -} - -static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType) -{ - int ClientId; - ClientId = open(qcqmi, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (ClientId == -1) { - dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno, - strerror(errno)); - return -1; - } - - if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) { - dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType, - errno, strerror(errno)); - close(ClientId); - ClientId = 0; - } - - dbg_time("%s: QMIType = %d clientid %d", __func__, QMIType, ClientId); - - switch (QMIType) { - case QMUX_TYPE_WDS: - dbg_time("Get clientWDS = %d", ClientId); - break; - case QMUX_TYPE_DMS: - dbg_time("Get clientDMS = %d", ClientId); - break; - case QMUX_TYPE_NAS: - dbg_time("Get clientNAS = %d", ClientId); - break; - case QMUX_TYPE_QOS: - dbg_time("Get clientQOS = %d", ClientId); - break; - case QMUX_TYPE_WMS: - dbg_time("Get clientWMS = %d", ClientId); - break; - case QMUX_TYPE_PDS: - dbg_time("Get clientPDS = %d", ClientId); - break; - case QMUX_TYPE_UIM: - dbg_time("Get clientUIM = %d", ClientId); - break; - case QMUX_TYPE_WDS_ADMIN: - dbg_time("Get clientWDA = %d", ClientId); - break; - default: - break; - } - - return ClientId; -} - -static int GobiNetDeInit(void) -{ - unsigned int i; - for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) { - if (qmiclientId[i] != 0) { - close(qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} -static void *GobiNetThread(void *pData) -{ - PROFILE_T *profile = (PROFILE_T *)pData; - const char *qcqmi = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - dbg_time("%s %d", __func__, __LINE__); - if (profile->ipv4_flag) - qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); - if (profile->ipv6_flag) - qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); - qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS); - qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS); - qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM); - // qmiclientId[QMUX_TYPE_WDS_ADMIN] = -// GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN); - - //if ((qmiclientId[QMUX_TYPE_WDS] == 0) && (qmiclientId[QMUX_TYPE_WDS_IPV6] == 0)) /*|| (clientWDA == -1)*/ { - - if ((qmiclientId[QMUX_TYPE_DMS] == 0) || - (qmiclientId[QMUX_TYPE_NAS] == 0) || - (qmiclientId[QMUX_TYPE_UIM] == 0) || - (profile->ipv4_flag ? ((qmiclientId[QMUX_TYPE_WDS] == 0) ? 1 : 0):0)|| - (profile->ipv6_flag ? ((qmiclientId[QMUX_TYPE_WDS_IPV6] == 0) ? 1 : 0):0)) - { - GobiNetDeInit(); - dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno,strerror(errno)); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - pthread_exit(NULL); - return NULL; - } - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (1) { - struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}}; - int ne, ret, nevents = 1; - unsigned int i; - for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) { - if (qmiclientId[i] != 0) { - pollfds[nevents].fd = qmiclientId[i]; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents = 0; - nevents++; - } - } - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI( - NULL); // main thread may pending on QmiThreadSendQMI() - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, - strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (fd == qmidevice_control_fd[1]) { - } else { - } - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __GobiNetThread_quit; - } - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == - sizeof(triger_event)) { - // DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __GobiNetThread_quit; - break; - case SIGTERM: - wait_for_request_quit = 1; - break; - default: - break; - } - } - continue; - } - - { - ssize_t nreads; - static UCHAR QMIBuf[4096]; - PQCQMIMSG pResponse = (PQCQMIMSG)QMIBuf; - - nreads = read(fd, &pResponse->MUXMsg, - sizeof(QMIBuf) - sizeof(QCQMI_HDR)); - if (nreads <= 0) { - dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, - errno, strerror(errno)); - break; - } - - for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); - i++) { - if (qmiclientId[i] == fd) { - pResponse->QMIHdr.QMIType = i; - } - } - - pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pResponse->QMIHdr.Length = - cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1); - pResponse->QMIHdr.CtlFlags = 0x00; - pResponse->QMIHdr.ClientId = fd & 0xFF; - - QmiThreadRecvQMI(pResponse); - } - } - } - -__GobiNetThread_quit: - GobiNetDeInit(); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); // main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -#else -static int GobiNetSendQMI(PQCQMIMSG pRequest) { return -1; } -static void *GobiNetThread(void *pData) -{ - dbg_time("please set CONFIG_GOBINET"); - return NULL; -} -#endif - -const struct qmi_device_ops gobi_qmidev_ops = { - .deinit = GobiNetDeInit, - .send = GobiNetSendQMI, - .read = GobiNetThread, -}; diff --git a/fibocom-dial/src/MPQCTL.h b/fibocom-dial/src/MPQCTL.h deleted file mode 100644 index d9b4268..0000000 --- a/fibocom-dial/src/MPQCTL.h +++ /dev/null @@ -1,363 +0,0 @@ -/*=========================================================================== - - M P Q C T L. H -DESCRIPTION: - - This module contains QMI QCTL module. - -INITIALIZATION AND SEQUENCING REQUIREMENTS: - -Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. -===========================================================================*/ - -#ifndef MPQCTL_H -#define MPQCTL_H - -#include "MPQMI.h" - -#pragma pack(push, 1) - -// ================= QMICTL ================== - -// QMICTL Control Flags -#define QMICTL_CTL_FLAG_CMD 0x00 -#define QMICTL_CTL_FLAG_RSP 0x01 -#define QMICTL_CTL_FLAG_IND 0x02 - -#if 0 -typedef struct _QMICTL_TRANSACTION_ITEM -{ - LIST_ENTRY List; - UCHAR TransactionId; // QMICTL transaction id - PVOID Context; // Adapter or IocDev - PIRP Irp; -} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM; -#endif - -typedef struct _QCQMICTL_MSG_HDR { - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; -} __attribute__((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR; - -#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR) - -typedef struct _QCQMICTL_MSG_HDR_RESP { - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP; - -typedef struct _QCQMICTL_MSG { - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; - UCHAR Payload; -} __attribute__((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG; - -// TLV Header -typedef struct _QCQMICTL_TLV_HDR { - UCHAR TLVType; - USHORT TLVLength; -} __attribute__((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR; - -#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR) - -// QMICTL Type -#define QMICTL_SET_INSTANCE_ID_REQ 0x0020 -#define QMICTL_SET_INSTANCE_ID_RESP 0x0020 -#define QMICTL_GET_VERSION_REQ 0x0021 -#define QMICTL_GET_VERSION_RESP 0x0021 -#define QMICTL_GET_CLIENT_ID_REQ 0x0022 -#define QMICTL_GET_CLIENT_ID_RESP 0x0022 -#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023 -#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023 -#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024 -#define QMICTL_INVALID_CLIENT_ID_IND 0x0025 -#define QMICTL_SET_DATA_FORMAT_REQ 0x0026 -#define QMICTL_SET_DATA_FORMAT_RESP 0x0026 -#define QMICTL_SYNC_REQ 0x0027 -#define QMICTL_SYNC_RESP 0x0027 -#define QMICTL_SYNC_IND 0x0027 - -#define QMICTL_FLAG_REQUEST 0x00 -#define QMICTL_FLAG_RESPONSE 0x01 -#define QMICTL_FLAG_INDICATION 0x02 - -// QMICTL Message Definitions - -typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ - USHORT Length; // 4 - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR Value; // Host-unique QMI instance for this device driver -} __attribute__((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG, - *PQMICTL_SET_INSTANCE_ID_REQ_MSG; - -typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 0x0002 - USHORT QMI_ID; // Upper byte is assigned by MSM, - // lower assigned by host -} __attribute__((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG, - *PQMICTL_SET_INSTANCE_ID_RESP_MSG; - -typedef struct _QMICTL_GET_VERSION_REQ_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_VERSION_REQ - USHORT Length; // 0 - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // var - UCHAR QMUXTypes; // List of one byte QMUX_TYPE values - // 0xFF returns a list of versions for all - // QMUX_TYPEs implemented on the device -} __attribute__((packed)) QMICTL_GET_VERSION_REQ_MSG, - *PQMICTL_GET_VERSION_REQ_MSG; - -typedef struct _QMUX_TYPE_VERSION_STRUCT { - UCHAR QMUXType; - USHORT MajorVersion; - USHORT MinorVersion; -} __attribute__((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT; - -typedef struct _ADDENDUM_VERSION_PREAMBLE { - UCHAR LabelLength; - UCHAR Label; -} __attribute__((packed)) ADDENDUM_VERSION_PREAMBLE, - *PADDENDUM_VERSION_PREAMBLE; - -#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01 -#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10 - -typedef struct _QMICTL_GET_VERSION_RESP_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_VERSION_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // var - UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT - QMUX_TYPE_VERSION_STRUCT TypeVersion[0]; -} __attribute__((packed)) QMICTL_GET_VERSION_RESP_MSG, - *PQMICTL_GET_VERSION_RESP_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR QMIType; // QMUX type -} __attribute__((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG, - *PQMICTL_GET_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 2 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG, - *PQMICTL_GET_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG, - *PQMICTL_RELEASE_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 2 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG, - *PQMICTL_RELEASE_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG, - *PQMICTL_REVOKE_CLIENT_ID_IND_MSG; - -typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG, - *PQMICTL_INVALID_CLIENT_ID_IND_MSG; - -typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR DataFormat; // 0-default; 1-QoS hdr present -} __attribute__((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG, - *PQMICTL_SET_DATA_FORMAT_REQ_MSG; - -#ifdef QC_IP_MODE -#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10 -#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001 -#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT { - UCHAR TLVType; // Link-Layer Protocol - USHORT TLVLength; // 2 - USHORT LinkProt; // 0x1: ETH; 0x2: IP -} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT; - -#ifdef QCMP_UL_TLP -#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP { - UCHAR TLVType; // 0x11, Uplink TLP Setting - USHORT TLVLength; // 1 - UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP; -#endif // QCMP_UL_TLP - -#ifdef QCMP_DL_TLP -#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP { - UCHAR TLVType; // 0x11, Uplink TLP Setting - USHORT TLVLength; // 1 - UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP; -#endif // QCMP_DL_TLP - -#endif // QC_IP_MODE - -#ifdef MP_QCQOS_ENABLED -#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING { - UCHAR TLVType; // 0x12, QoS setting - USHORT TLVLength; // 1 - UCHAR QosSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING, - *PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING; -#endif // MP_QCQOS_ENABLED - -typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code -} __attribute__((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG, - *PQMICTL_SET_DATA_FORMAT_RESP_MSG; - -typedef struct _QMICTL_SYNC_REQ_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ - USHORT Length; // 0 -} __attribute__((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG; - -typedef struct _QMICTL_SYNC_RESP_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; -} __attribute__((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG; - -typedef struct _QMICTL_SYNC_IND_MSG { - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; -} __attribute__((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG; - -typedef struct _QMICTL_MSG { - union { - // Message Header - QCQMICTL_MSG_HDR QMICTLMsgHdr; - QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp; - - // QMICTL Message - QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq; - QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp; - QMICTL_GET_VERSION_REQ_MSG GetVersionReq; - QMICTL_GET_VERSION_RESP_MSG GetVersionRsp; - QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq; - QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp; - QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq; - QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp; - QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd; - QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd; - QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp; - QMICTL_SYNC_REQ_MSG SyncReq; - QMICTL_SYNC_RESP_MSG SyncRsp; - QMICTL_SYNC_IND_MSG SyncInd; - }; -} __attribute__((packed)) QMICTL_MSG, *PQMICTL_MSG; - -#endif // MPQCTL_H diff --git a/fibocom-dial/src/MPQMI.h b/fibocom-dial/src/MPQMI.h deleted file mode 100644 index f0063af..0000000 --- a/fibocom-dial/src/MPQMI.h +++ /dev/null @@ -1,287 +0,0 @@ -/*=========================================================================== - - M P Q M I. H -DESCRIPTION: - - This module contains forward references to the QMI module. - -INITIALIZATION AND SEQUENCING REQUIREMENTS: - -Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. -===========================================================================*/ -/*=========================================================================== - - EDIT HISTORY FOR FILE - $Header: //depot/QMI/win/qcdrivers/ndis/MPQMI.h#3 $ - -when who what, where, why --------- --- ---------------------------------------------------------- -11/20/04 hg Initial version. -===========================================================================*/ - -#ifndef USBQMI_H -#define USBQMI_H - -typedef char CHAR; -typedef unsigned char UCHAR; -typedef unsigned short USHORT; -typedef int INT; -typedef unsigned int UINT; -typedef long LONG; -typedef unsigned int ULONG; -typedef unsigned long long ULONG64; -typedef char *PCHAR; -typedef unsigned char *PUCHAR; -typedef int *PINT; -typedef int BOOL; - -#define TRUE (1 == 1) -#define FALSE (1 != 1) - -#define QMICTL_SUPPORTED_MAJOR_VERSION 1 -#define QMICTL_SUPPORTED_MINOR_VERSION 0 - -#pragma pack(push, 1) - -// ========= USB Control Message ========== - -#define USB_CTL_MSG_TYPE_QMI 0x01 - -// USB Control Message -typedef struct _QCUSB_CTL_MSG_HDR { - UCHAR IFType; -} __attribute__((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR; - -#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR) - -typedef struct _QCUSB_CTL_MSG { - UCHAR IFType; - UCHAR Message; -} __attribute__((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG; - -#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01 -#define QCTLV_TYPE_RESULT_CODE 0x02 - -// ================= QMI ================== - -// Define QMI Type -typedef enum _QMI_SERVICE_TYPE { - QMUX_TYPE_CTL = 0x00, - QMUX_TYPE_WDS = 0x01, - QMUX_TYPE_DMS = 0x02, - QMUX_TYPE_NAS = 0x03, - QMUX_TYPE_QOS = 0x04, - QMUX_TYPE_WMS = 0x05, - QMUX_TYPE_PDS = 0x06, - QMUX_TYPE_UIM = 0x0B, - QMUX_TYPE_WDS_IPV6 = 0x11, - QMUX_TYPE_WDS_ADMIN = 0x1A, - QMUX_TYPE_MAX = 0xFF, - QMUX_TYPE_ALL = 0xFF -} QMI_SERVICE_TYPE; - -typedef enum _QMI_RESULT_CODE_TYPE { - QMI_RESULT_SUCCESS = 0x0000, - QMI_RESULT_FAILURE = 0x0001 -} QMI_RESULT_CODE_TYPE; - -typedef enum _QMI_ERROR_CODE_TYPE { - QMI_ERR_NONE = 0x0000, - QMI_ERR_MALFORMED_MSG = 0x0001, - QMI_ERR_NO_MEMORY = 0x0002, - QMI_ERR_INTERNAL = 0x0003, - QMI_ERR_ABORTED = 0x0004, - QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005, - QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006, - QMI_ERR_INVALID_CLIENT_ID = 0x0007, - QMI_ERR_NO_THRESHOLDS = 0x0008, - QMI_ERR_INVALID_HANDLE = 0x0009, - QMI_ERR_INVALID_PROFILE = 0x000A, - QMI_ERR_INVALID_PINID = 0x000B, - QMI_ERR_INCORRECT_PIN = 0x000C, - QMI_ERR_NO_NETWORK_FOUND = 0x000D, - QMI_ERR_CALL_FAILED = 0x000E, - QMI_ERR_OUT_OF_CALL = 0x000F, - QMI_ERR_NOT_PROVISIONED = 0x0010, - QMI_ERR_MISSING_ARG = 0x0011, - QMI_ERR_ARG_TOO_LONG = 0x0013, - QMI_ERR_INVALID_TX_ID = 0x0016, - QMI_ERR_DEVICE_IN_USE = 0x0017, - QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018, - QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019, - QMI_ERR_NO_EFFECT = 0x001A, - QMI_ERR_NO_FREE_PROFILE = 0x001B, - QMI_ERR_INVALID_PDP_TYPE = 0x001C, - QMI_ERR_INVALID_TECH_PREF = 0x001D, - QMI_ERR_INVALID_PROFILE_TYPE = 0x001E, - QMI_ERR_INVALID_SERVICE_TYPE = 0x001F, - QMI_ERR_INVALID_REGISTER_ACTION = 0x0020, - QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021, - QMI_ERR_AUTHENTICATION_FAILED = 0x0022, - QMI_ERR_PIN_BLOCKED = 0x0023, - QMI_ERR_PIN_PERM_BLOCKED = 0x0024, - QMI_ERR_SIM_NOT_INITIALIZED = 0x0025, - QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026, - QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027, - QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028, - QMI_ERR_INVALID_QOS_ID = 0x0029, - QMI_ERR_INVALID_ID = 0x0029, - QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A, - QMI_ERR_INTERFACE_NOT_FOUND = 0x002B, - QMI_ERR_FLOW_SUSPENDED = 0x002C, - QMI_ERR_INVALID_DATA_FORMAT = 0x002D, - QMI_ERR_GENERAL = 0x002E, - QMI_ERR_UNKNOWN = 0x002F, - QMI_ERR_INVALID_ARG = 0x0030, - QMI_ERR_INVALID_INDEX = 0x0031, - QMI_ERR_NO_ENTRY = 0x0032, - QMI_ERR_DEVICE_STORAGE_FULL = 0x0033, - QMI_ERR_DEVICE_NOT_READY = 0x0034, - QMI_ERR_NETWORK_NOT_READY = 0x0035, - QMI_ERR_CAUSE_CODE = 0x0036, - QMI_ERR_MESSAGE_NOT_SENT = 0x0037, - QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038, - QMI_ERR_INVALID_MESSAGE_ID = 0x0039, - QMI_ERR_ENCODING = 0x003A, - QMI_ERR_AUTHENTICATION_LOCK = 0x003B, - QMI_ERR_INVALID_TRANSITION = 0x003C, - QMI_ERR_NOT_A_MCAST_IFACE = 0x003D, - QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E, - QMI_ERR_INVALID_MCAST_HANDLE = 0x003F, - QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040, - QMI_ERR_SESSION_INACTIVE = 0x0041, - QMI_ERR_SESSION_INVALID = 0x0042, - QMI_ERR_SESSION_OWNERSHIP = 0x0043, - QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044, - QMI_ERR_DISABLED = 0x0045, - QMI_ERR_INVALID_OPERATION = 0x0046, - QMI_ERR_INVALID_QMI_CMD = 0x0047, - QMI_ERR_TPDU_TYPE = 0x0048, - QMI_ERR_SMSC_ADDR = 0x0049, - QMI_ERR_INFO_UNAVAILABLE = 0x004A, - QMI_ERR_SEGMENT_TOO_LONG = 0x004B, - QMI_ERR_SEGMENT_ORDER = 0x004C, - QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D, - QMI_ERR_OP_PARTIAL_FAILURE = 0x004E, - QMI_ERR_POLICY_MISMATCH = 0x004F, - QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050, - QMI_ERR_EXTENDED_INTERNAL = 0x0051, - QMI_ERR_ACCESS_DENIED = 0x0052, - QMI_ERR_HARDWARE_RESTRICTED = 0x0053, - QMI_ERR_ACK_NOT_SENT = 0x0054, - QMI_ERR_INJECT_TIMEOUT = 0x0055, - QMI_ERR_INCOMPATIBLE_STATE = 0x005A, - QMI_ERR_FDN_RESTRICT = 0x005B, - QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C, - QMI_ERR_NO_RADIO = 0x005D, - QMI_ERR_NOT_SUPPORTED = 0x005E, - QMI_ERR_NO_SUBSCRIPTION = 0x005F, - QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060, - QMI_ERR_NETWORK_ABORTED = 0x0061, - QMI_ERR_MSG_BLOCKED = 0x0062, - QMI_ERR_INVALID_SESSION_TYPE = 0x0064, - QMI_ERR_INVALID_PB_TYPE = 0x0065, - QMI_ERR_NO_SIM = 0x0066, - QMI_ERR_PB_NOT_READY = 0x0067, - QMI_ERR_PIN_RESTRICTION = 0x0068, - QMI_ERR_PIN2_RESTRICTION = 0x0069, - QMI_ERR_PUK_RESTRICTION = 0x006A, - QMI_ERR_PUK2_RESTRICTION = 0x006B, - QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C, - QMI_ERR_PB_DELETE_IN_PROG = 0x006D, - QMI_ERR_PB_TEXT_TOO_LONG = 0x006E, - QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F, - QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070 -} QMI_ERROR_CODE_TYPE; - -#define QCQMI_CTL_FLAG_SERVICE 0x80 -#define QCQMI_CTL_FLAG_CTL_POINT 0x00 - -typedef struct _QCQMI_HDR { - UCHAR IFType; - USHORT Length; - UCHAR CtlFlags; // reserved - UCHAR QMIType; - UCHAR ClientId; -} __attribute__((packed)) QCQMI_HDR, *PQCQMI_HDR; - -#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR) - 1) - -typedef struct _QCQMI { - UCHAR IFType; - USHORT Length; - UCHAR CtlFlags; // reserved - UCHAR QMIType; - UCHAR ClientId; - UCHAR SDU; -} __attribute__((packed)) QCQMI, *PQCQMI; - -typedef struct _QMI_SERVICE_VERSION { - USHORT Major; - USHORT Minor; - USHORT AddendumMajor; - USHORT AddendumMinor; -} __attribute__((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION; - -// ================= QMUX ================== - -#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header - -#define QMUX_BROADCAST_CID 0xFF - -typedef struct _QCQMUX_HDR { - UCHAR CtlFlags; // 0: single QMUX Msg; 1: - USHORT TransactionId; -} __attribute__((packed)) QCQMUX_HDR, *PQCQMUX_HDR; - -typedef struct _QCQMUX { - UCHAR CtlFlags; // 0: single QMUX Msg; 1: - USHORT TransactionId; - UCHAR Message; // Type(2), Length(2), Value -} __attribute__((packed)) QCQMUX, *PQCQMUX; - -#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR) - -typedef struct _QCQMUX_MSG_HDR { - USHORT Type; - USHORT Length; -} __attribute__((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR; - -#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR) - -typedef struct _QCQMUX_MSG_HDR_RESP { - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP; - -typedef struct _QCQMUX_TLV { - UCHAR Type; - USHORT Length; - UCHAR Value; -} __attribute__((packed)) QCQMUX_TLV, *PQCQMUX_TLV; - -typedef struct _QMI_TLV_HDR { - UCHAR TLVType; - USHORT TLVLength; -} __attribute__((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR; - -// QMUX Message Definitions -- QMI SDU -#define QMUX_CTL_FLAG_SINGLE_MSG 0x00 -#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01 -#define QMUX_CTL_FLAG_TYPE_CMD 0x00 -#define QMUX_CTL_FLAG_TYPE_RSP 0x02 -#define QMUX_CTL_FLAG_TYPE_IND 0x04 -#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01 -#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind - -#pragma pack(pop) - -#endif // USBQMI_H diff --git a/fibocom-dial/src/MPQMUX.c b/fibocom-dial/src/MPQMUX.c deleted file mode 100644 index 2fd59e5..0000000 --- a/fibocom-dial/src/MPQMUX.c +++ /dev/null @@ -1,437 +0,0 @@ -#include "QMIThread.h" -static char line[1024]; -static pthread_mutex_t dumpQMIMutex = PTHREAD_MUTEX_INITIALIZER; -#undef dbg -#define dbg(format, arg...) \ - do { \ - if (strlen(line) < sizeof(line)) \ - snprintf(&line[strlen(line)], sizeof(line) - strlen(line), format, \ - ##arg); \ - } while (0) - -PQMI_TLV_HDR GetTLV(PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType); - -typedef struct { - UINT type; - const char *name; -} QMI_NAME_T; - -#define qmi_name_item(type) \ - { \ - type, #type \ - } - -static const QMI_NAME_T qmux_ctl_QMICTLType[] = { - // QMICTL Type - qmi_name_item(QMICTL_SET_INSTANCE_ID_REQ), // 0x0020 - qmi_name_item(QMICTL_SET_INSTANCE_ID_RESP), // 0x0020 - qmi_name_item(QMICTL_GET_VERSION_REQ), // 0x0021 - qmi_name_item(QMICTL_GET_VERSION_RESP), // 0x0021 - qmi_name_item(QMICTL_GET_CLIENT_ID_REQ), // 0x0022 - qmi_name_item(QMICTL_GET_CLIENT_ID_RESP), // 0x0022 - qmi_name_item(QMICTL_RELEASE_CLIENT_ID_REQ), // 0x0023 - qmi_name_item(QMICTL_RELEASE_CLIENT_ID_RESP), // 0x0023 - qmi_name_item(QMICTL_REVOKE_CLIENT_ID_IND), // 0x0024 - qmi_name_item(QMICTL_INVALID_CLIENT_ID_IND), // 0x0025 - qmi_name_item(QMICTL_SET_DATA_FORMAT_REQ), // 0x0026 - qmi_name_item(QMICTL_SET_DATA_FORMAT_RESP), // 0x0026 - qmi_name_item(QMICTL_SYNC_REQ), // 0x0027 - qmi_name_item(QMICTL_SYNC_RESP), // 0x0027 - qmi_name_item(QMICTL_SYNC_IND), // 0x0027 -}; - -static const QMI_NAME_T qmux_CtlFlags[] = { - qmi_name_item(QMUX_CTL_FLAG_TYPE_CMD), - qmi_name_item(QMUX_CTL_FLAG_TYPE_RSP), - qmi_name_item(QMUX_CTL_FLAG_TYPE_IND), -}; - -static const QMI_NAME_T qmux_wds_Type[] = { - qmi_name_item(QMIWDS_SET_EVENT_REPORT_REQ), // 0x0001 - qmi_name_item(QMIWDS_SET_EVENT_REPORT_RESP), // 0x0001 - qmi_name_item(QMIWDS_EVENT_REPORT_IND), // 0x0001 - qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_REQ), // 0x0020 - qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_RESP), // 0x0020 - qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_REQ), // 0x0021 - qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_RESP), // 0x0021 - qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_REQ), // 0x0022 - qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_RESP), // 0x0022 - qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_IND), // 0x0022 - qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ), // 0x0023 - qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP), // 0x0023 - qmi_name_item(QMIWDS_GET_PKT_STATISTICS_REQ), // 0x0024 - qmi_name_item(QMIWDS_GET_PKT_STATISTICS_RESP), // 0x0024 -//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 - qmi_name_item(QMIWDS_CREATE_PROFILE_SETTINGS_REQ), // 0x0027 - qmi_name_item(QMIWDS_CREATE_PROFILE_SETTINGS_RESP), // 0x0027 -//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 - qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ), // 0x0028 - qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_RESP), // 0x0028 - qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_REQ), // 0x002B - qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_RESP), // 0x002BD - qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_REQ), // 0x002C - qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_RESP), // 0x002C - qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_REQ), // 0x002D - qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_RESP), // 0x002D - qmi_name_item(QMIWDS_GET_MIP_MODE_REQ), // 0x002F - qmi_name_item(QMIWDS_GET_MIP_MODE_RESP), // 0x002F - qmi_name_item(QMIWDS_GET_DATA_BEARER_REQ), // 0x0037 - qmi_name_item(QMIWDS_GET_DATA_BEARER_RESP), // 0x0037 - qmi_name_item(QMIWDS_DUN_CALL_INFO_REQ), // 0x0038 - qmi_name_item(QMIWDS_DUN_CALL_INFO_RESP), // 0x0038 - qmi_name_item(QMIWDS_DUN_CALL_INFO_IND), // 0x0038 - qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ), // 0x004D - qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP), // 0x004D - qmi_name_item(QMIWDS_SET_AUTO_CONNECT_REQ), // 0x0051 - qmi_name_item(QMIWDS_SET_AUTO_CONNECT_RESP), // 0x0051 - qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_REQ), // 0x00A2 - qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_RESP), // 0x00A2 -}; - -static const QMI_NAME_T qmux_dms_Type[] = { - // ======================= DMS ============================== - qmi_name_item(QMIDMS_SET_EVENT_REPORT_REQ), // 0x0001 - qmi_name_item(QMIDMS_SET_EVENT_REPORT_RESP), // 0x0001 - qmi_name_item(QMIDMS_EVENT_REPORT_IND), // 0x0001 - qmi_name_item(QMIDMS_GET_DEVICE_CAP_REQ), // 0x0020 - qmi_name_item(QMIDMS_GET_DEVICE_CAP_RESP), // 0x0020 - qmi_name_item(QMIDMS_GET_DEVICE_MFR_REQ), // 0x0021 - qmi_name_item(QMIDMS_GET_DEVICE_MFR_RESP), // 0x0021 - qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_REQ), // 0x0022 - qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_RESP), // 0x0022 - qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_REQ), // 0x0023 - qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_RESP), // 0x0023 - qmi_name_item(QMIDMS_GET_MSISDN_REQ), // 0x0024 - qmi_name_item(QMIDMS_GET_MSISDN_RESP), // 0x0024 - qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ), // 0x0025 - qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP), // 0x0025 - qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_REQ), // 0x0027 - qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_RESP), // 0x0027 - qmi_name_item(QMIDMS_UIM_VERIFY_PIN_REQ), // 0x0028 - qmi_name_item(QMIDMS_UIM_VERIFY_PIN_RESP), // 0x0028 - qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_REQ), // 0x0029 - qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_RESP), // 0x0029 - qmi_name_item(QMIDMS_UIM_CHANGE_PIN_REQ), // 0x002A - qmi_name_item(QMIDMS_UIM_CHANGE_PIN_RESP), // 0x002A - qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_REQ), // 0x002B - qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_RESP), // 0x002B - qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_REQ), // 0x002C - qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_RESP), // 0x002C - qmi_name_item(QMIDMS_GET_OPERATING_MODE_REQ), // 0x002D - qmi_name_item(QMIDMS_GET_OPERATING_MODE_RESP), // 0x002D - qmi_name_item(QMIDMS_SET_OPERATING_MODE_REQ), // 0x002E - qmi_name_item(QMIDMS_SET_OPERATING_MODE_RESP), // 0x002E - qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_REQ), // 0x0031 - qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_RESP), // 0x0031 - qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_REQ), // 0x0032 - qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_RESP), // 0x0032 - qmi_name_item(QMIDMS_ACTIVATE_MANUAL_REQ), // 0x0033 - qmi_name_item(QMIDMS_ACTIVATE_MANUAL_RESP), // 0x0033 - qmi_name_item(QMIDMS_UIM_GET_ICCID_REQ), // 0x003C - qmi_name_item(QMIDMS_UIM_GET_ICCID_RESP), // 0x003C - qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_REQ), // 0x0040 - qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_RESP), // 0x0040 - qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_REQ), // 0x0041 - qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_RESP), // 0x0041 - qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_REQ), // 0x0042 - qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_RESP), // 0x0042 - qmi_name_item(QMIDMS_UIM_GET_IMSI_REQ), // 0x0043 - qmi_name_item(QMIDMS_UIM_GET_IMSI_RESP), // 0x0043 - qmi_name_item(QMIDMS_UIM_GET_STATE_REQ), // 0x0044 - qmi_name_item(QMIDMS_UIM_GET_STATE_RESP), // 0x0044 - qmi_name_item(QMIDMS_GET_BAND_CAP_REQ), // 0x0045 - qmi_name_item(QMIDMS_GET_BAND_CAP_RESP), // 0x0045 -}; - -static const QMI_NAME_T qmux_nas_Type[] = { - // ======================= NAS ============================== - qmi_name_item(QMINAS_SET_EVENT_REPORT_REQ), // 0x0002 - qmi_name_item(QMINAS_SET_EVENT_REPORT_RESP), // 0x0002 - qmi_name_item(QMINAS_EVENT_REPORT_IND), // 0x0002 - qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_REQ), // 0x0020 - qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_RESP), // 0x0020 - qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_REQ), // 0x0021 - qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_RESP), // 0x0021 - qmi_name_item(QMINAS_INITIATE_NW_REGISTER_REQ), // 0x0022 - qmi_name_item(QMINAS_INITIATE_NW_REGISTER_RESP), // 0x0022 - qmi_name_item(QMINAS_INITIATE_ATTACH_REQ), // 0x0023 - qmi_name_item(QMINAS_INITIATE_ATTACH_RESP), // 0x0023 - qmi_name_item(QMINAS_GET_SERVING_SYSTEM_REQ), // 0x0024 - qmi_name_item(QMINAS_GET_SERVING_SYSTEM_RESP), // 0x0024 - qmi_name_item(QMINAS_SERVING_SYSTEM_IND), // 0x0024 - qmi_name_item(QMINAS_GET_HOME_NETWORK_REQ), // 0x0025 - qmi_name_item(QMINAS_GET_HOME_NETWORK_RESP), // 0x0025 - qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_REQ), // 0x0026 - qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_RESP), // 0x0026 - qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_REQ), // 0x0027 - qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_RESP), // 0x0027 - qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_REQ), // 0x0028 - qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_RESP), // 0x0028 - qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_REQ), // 0x0029 - qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_RESP), // 0x0029 - qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_REQ), // 0x002A - qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_RESP), // 0x002A - qmi_name_item(QMINAS_GET_RF_BAND_INFO_REQ), // 0x0031 - qmi_name_item(QMINAS_GET_RF_BAND_INFO_RESP), // 0x0031 - qmi_name_item(QMINAS_GET_PLMN_NAME_REQ), // 0x0044 - qmi_name_item(QMINAS_GET_PLMN_NAME_RESP), // 0x0044 - qmi_name_item(FIBO_PACKET_TRANSFER_START_IND), // 0X100 - qmi_name_item(FIBO_PACKET_TRANSFER_END_IND), // 0X101 - qmi_name_item(QMINAS_GET_SYS_INFO_REQ), // 0x004D - qmi_name_item(QMINAS_GET_SYS_INFO_RESP), // 0x004D - qmi_name_item(QMINAS_SYS_INFO_IND), // 0x004D -}; - -static const QMI_NAME_T qmux_wms_Type[] = { - // ======================= WMS ============================== - qmi_name_item(QMIWMS_SET_EVENT_REPORT_REQ), // 0x0001 - qmi_name_item(QMIWMS_SET_EVENT_REPORT_RESP), // 0x0001 - qmi_name_item(QMIWMS_EVENT_REPORT_IND), // 0x0001 - qmi_name_item(QMIWMS_RAW_SEND_REQ), // 0x0020 - qmi_name_item(QMIWMS_RAW_SEND_RESP), // 0x0020 - qmi_name_item(QMIWMS_RAW_WRITE_REQ), // 0x0021 - qmi_name_item(QMIWMS_RAW_WRITE_RESP), // 0x0021 - qmi_name_item(QMIWMS_RAW_READ_REQ), // 0x0022 - qmi_name_item(QMIWMS_RAW_READ_RESP), // 0x0022 - qmi_name_item(QMIWMS_MODIFY_TAG_REQ), // 0x0023 - qmi_name_item(QMIWMS_MODIFY_TAG_RESP), // 0x0023 - qmi_name_item(QMIWMS_DELETE_REQ), // 0x0024 - qmi_name_item(QMIWMS_DELETE_RESP), // 0x0024 - qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_REQ), // 0x0030 - qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_RESP), // 0x0030 - qmi_name_item(QMIWMS_LIST_MESSAGES_REQ), // 0x0031 - qmi_name_item(QMIWMS_LIST_MESSAGES_RESP), // 0x0031 - qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_REQ), // 0x0034 - qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_RESP), // 0x0034 - qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_REQ), // 0x0035 - qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_RESP), // 0x0035 - qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_REQ), // 0x0036 - qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_RESP), // 0x0036 -}; - -static const QMI_NAME_T qmux_wds_admin_Type[] = { - qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ), // 0x0020 - qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_RESP), // 0x0020 - qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_REQ), // 0x0021 - qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_RESP), // 0x0021 - qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ), // 0x002B - qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP), // 0x002B - qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ), // 0x002C - qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP), // 0x002C -}; - -static const QMI_NAME_T qmux_uim_Type[] = { - qmi_name_item(QMIUIM_READ_TRANSPARENT_REQ), // 0x0020 - qmi_name_item(QMIUIM_READ_TRANSPARENT_RESP), // 0x0020 - qmi_name_item(QMIUIM_READ_TRANSPARENT_IND), // 0x0020 - qmi_name_item(QMIUIM_READ_RECORD_REQ), // 0x0021 - qmi_name_item(QMIUIM_READ_RECORD_RESP), // 0x0021 - qmi_name_item(QMIUIM_READ_RECORD_IND), // 0x0021 - qmi_name_item(QMIUIM_WRITE_TRANSPARENT_REQ), // 0x0022 - qmi_name_item(QMIUIM_WRITE_TRANSPARENT_RESP), // 0x0022 - qmi_name_item(QMIUIM_WRITE_TRANSPARENT_IND), // 0x0022 - qmi_name_item(QMIUIM_WRITE_RECORD_REQ), // 0x0023 - qmi_name_item(QMIUIM_WRITE_RECORD_RESP), // 0x0023 - qmi_name_item(QMIUIM_WRITE_RECORD_IND), // 0x0023 - qmi_name_item(QMIUIM_SET_PIN_PROTECTION_REQ), // 0x0025 - qmi_name_item(QMIUIM_SET_PIN_PROTECTION_RESP), // 0x0025 - qmi_name_item(QMIUIM_SET_PIN_PROTECTION_IND), // 0x0025 - qmi_name_item(QMIUIM_VERIFY_PIN_REQ), // 0x0026 - qmi_name_item(QMIUIM_VERIFY_PIN_RESP), // 0x0026 - qmi_name_item(QMIUIM_VERIFY_PIN_IND), // 0x0026 - qmi_name_item(QMIUIM_UNBLOCK_PIN_REQ), // 0x0027 - qmi_name_item(QMIUIM_UNBLOCK_PIN_RESP), // 0x0027 - qmi_name_item(QMIUIM_UNBLOCK_PIN_IND), // 0x0027 - qmi_name_item(QMIUIM_CHANGE_PIN_REQ), // 0x0028 - qmi_name_item(QMIUIM_CHANGE_PIN_RESP), // 0x0028 - qmi_name_item(QMIUIM_CHANGE_PIN_IND), // 0x0028 - qmi_name_item(QMIUIM_DEPERSONALIZATION_REQ), // 0x0029 - qmi_name_item(QMIUIM_DEPERSONALIZATION_RESP), // 0x0029 - qmi_name_item(QMIUIM_EVENT_REG_REQ), // 0x002E - qmi_name_item(QMIUIM_EVENT_REG_RESP), // 0x002E - qmi_name_item(QMIUIM_GET_CARD_STATUS_REQ), // 0x002F - qmi_name_item(QMIUIM_GET_CARD_STATUS_RESP), // 0x002F - qmi_name_item(QMIUIM_STATUS_CHANGE_IND), // 0x0032 -}; - -static const char *qmi_name_get(const QMI_NAME_T *table, size_t size, int type, - const char *tag) -{ - static char unknow[40]; - size_t i; - - if (qmux_CtlFlags == table) { - if (!strcmp(tag, "_REQ")) - tag = "_CMD"; - else if (!strcmp(tag, "_RESP")) - tag = "_RSP"; - } - - for (i = 0; i < size; i++) { - if (table[i].type == (UINT)type) { - if (!tag || (strstr(table[i].name, tag))) - return table[i].name; - } - } - sprintf(unknow, "unknow_%x", type); - return unknow; -} - -#define QMI_NAME(table, type) \ - qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, 0) -#define QMUX_NAME(table, type, tag) \ - qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, tag) - -void dump_tlv(PQCQMUX_MSG_HDR pQMUXMsgHdr) -{ - int TLVFind = 0; - int i; - // dbg("QCQMUX_TLV-----------------------------------\n"); - // dbg("{Type,\tLength,\tValue}\n"); - - while (1) { - PQMI_TLV_HDR TLVHdr = GetTLV(pQMUXMsgHdr, 0x1000 + (++TLVFind)); - if (TLVHdr == NULL) - break; - - // if ((TLVHdr->TLVType == 0x02) && ((USHORT *)(TLVHdr+1))[0]) - { - dbg("{%02x,\t%04x,\t", TLVHdr->TLVType, - le16_to_cpu(TLVHdr->TLVLength)); - for (i = 0; i < le16_to_cpu(TLVHdr->TLVLength); i++) { - dbg("%02x ", ((UCHAR *)(TLVHdr + 1))[i]); - } - dbg("}\n"); - } - } // while -} - -void dump_ctl(PQCQMICTL_MSG_HDR CTLHdr) -{ - const char *tag; - - // dbg("QCQMICTL_MSG--------------------------------------------\n"); - // dbg("CtlFlags: %02x\t\t%s\n", CTLHdr->CtlFlags, - // QMI_NAME(qmi_ctl_CtlFlags, CTLHdr->CtlFlags)); - dbg("TransactionId: %02x\n", CTLHdr->TransactionId); - switch (CTLHdr->CtlFlags) { - case QMICTL_FLAG_REQUEST: - tag = "_REQ"; - break; - case QMICTL_FLAG_RESPONSE: - tag = "_RESP"; - break; - case QMICTL_FLAG_INDICATION: - tag = "_IND"; - break; - default: - tag = 0; - break; - } - dbg("QMICTLType: %04x\t%s\n", le16_to_cpu(CTLHdr->QMICTLType), - QMUX_NAME(qmux_ctl_QMICTLType, le16_to_cpu(CTLHdr->QMICTLType), tag)); - dbg("Length: %04x\n", le16_to_cpu(CTLHdr->Length)); - - dump_tlv((PQCQMUX_MSG_HDR)(&CTLHdr->QMICTLType)); -} - -int dump_qmux(QMI_SERVICE_TYPE serviceType, PQCQMUX_HDR QMUXHdr) -{ - PQCQMUX_MSG_HDR QMUXMsgHdr = (PQCQMUX_MSG_HDR)(QMUXHdr + 1); - CHAR *tag; - - // dbg("QCQMUX--------------------------------------------\n"); - switch (QMUXHdr->CtlFlags & QMUX_CTL_FLAG_MASK_TYPE) { - case QMUX_CTL_FLAG_TYPE_CMD: - tag = "_REQ"; - break; - case QMUX_CTL_FLAG_TYPE_RSP: - tag = "_RESP"; - break; - case QMUX_CTL_FLAG_TYPE_IND: - tag = "_IND"; - break; - default: - tag = 0; - break; - } - // dbg("CtlFlags: %02x\t\t%s\n", QMUXHdr->CtlFlags, - // QMUX_NAME(qmux_CtlFlags, QMUXHdr->CtlFlags, tag)); - dbg("TransactionId: %04x\n", le16_to_cpu(QMUXHdr->TransactionId)); - - // dbg("QCQMUX_MSG_HDR-----------------------------------\n"); - switch (serviceType) { - case QMUX_TYPE_DMS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_dms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_NAS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_nas_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_WDS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_wds_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_WMS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_wms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_WDS_ADMIN: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_wds_admin_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_UIM: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_uim_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_PDS: - case QMUX_TYPE_QOS: - case QMUX_TYPE_CTL: - default: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - "PDS/QOS/CTL/unknown!"); - break; - } - dbg("Length: %04x\n", le16_to_cpu(QMUXMsgHdr->Length)); - - dump_tlv(QMUXMsgHdr); - - return 0; -} - -void dump_qmi(void *dataBuffer, int dataLen) -{ - PQCQMI_HDR QMIHdr = (PQCQMI_HDR)dataBuffer; - PQCQMUX_HDR QMUXHdr = (PQCQMUX_HDR)(QMIHdr + 1); - PQCQMICTL_MSG_HDR CTLHdr = (PQCQMICTL_MSG_HDR)(QMIHdr + 1); - - int i; - - if (!debug_qmi) - return; - - pthread_mutex_lock(&dumpQMIMutex); - line[0] = 0; - for (i = 0; i < dataLen; i++) { - dbg("%02x ", ((unsigned char *)dataBuffer)[i]); - } - dbg_time("%s", line); - line[0] = 0; - - // dbg("QCQMI_HDR-----------------------------------------"); - // dbg("IFType: %02x\t\t%s", QMIHdr->IFType, - // QMI_NAME(qmi_IFType, QMIHdr->IFType)); dbg("Length: %04x", - // le16_to_cpu(QMIHdr->Length)); dbg("CtlFlags: %02x\t\t%s", - // QMIHdr->CtlFlags, QMI_NAME(qmi_CtlFlags, QMIHdr->CtlFlags)); - // dbg("QMIType: %02x\t\t%s", QMIHdr->QMIType, QMI_NAME(qmi_QMIType, - // QMIHdr->QMIType)); dbg("ClientId: %02x", QMIHdr->ClientId); - - if (QMIHdr->QMIType == QMUX_TYPE_CTL) { - dump_ctl(CTLHdr); - } else { - dump_qmux(QMIHdr->QMIType, QMUXHdr); - } - dbg_time("%s", line); - pthread_mutex_unlock(&dumpQMIMutex); -} diff --git a/fibocom-dial/src/MPQMUX.h b/fibocom-dial/src/MPQMUX.h deleted file mode 100644 index bae0c4e..0000000 --- a/fibocom-dial/src/MPQMUX.h +++ /dev/null @@ -1,3671 +0,0 @@ -/*=========================================================================== - - M P Q M U X. H -DESCRIPTION: - - This file provides support for QMUX. - -INITIALIZATION AND SEQUENCING REQUIREMENTS: - -Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. -===========================================================================*/ - -#ifndef MPQMUX_H -#define MPQMUX_H - -#include "MPQMI.h" - -#pragma pack(push, 1) - -#define QMIWDS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIWDS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIWDS_EVENT_REPORT_IND 0x0001 -#define QMIWDS_START_NETWORK_INTERFACE_REQ 0x0020 -#define QMIWDS_START_NETWORK_INTERFACE_RESP 0x0020 -#define QMIWDS_STOP_NETWORK_INTERFACE_REQ 0x0021 -#define QMIWDS_STOP_NETWORK_INTERFACE_RESP 0x0021 -#define QMIWDS_GET_PKT_SRVC_STATUS_REQ 0x0022 -#define QMIWDS_GET_PKT_SRVC_STATUS_RESP 0x0022 -#define QMIWDS_GET_PKT_SRVC_STATUS_IND 0x0022 -#define QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ 0x0023 -#define QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP 0x0023 -#define QMIWDS_GET_PKT_STATISTICS_REQ 0x0024 -#define QMIWDS_GET_PKT_STATISTICS_RESP 0x0024 -//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 -#define QMIWDS_CREATE_PROFILE_SETTINGS_REQ 0x0027 -#define QMIWDS_CREATE_PROFILE_SETTINGS_RESP 0x0027 -//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 -#define QMIWDS_MODIFY_PROFILE_SETTINGS_REQ 0x0028 -#define QMIWDS_MODIFY_PROFILE_SETTINGS_RESP 0x0028 -#define QMIWDS_GET_PROFILE_SETTINGS_REQ 0x002B -#define QMIWDS_GET_PROFILE_SETTINGS_RESP 0x002B -#define QMIWDS_GET_DEFAULT_SETTINGS_REQ 0x002C -#define QMIWDS_GET_DEFAULT_SETTINGS_RESP 0x002C -#define QMIWDS_GET_RUNTIME_SETTINGS_REQ 0x002D -#define QMIWDS_GET_RUNTIME_SETTINGS_RESP 0x002D -#define QMIWDS_GET_MIP_MODE_REQ 0x002F -#define QMIWDS_GET_MIP_MODE_RESP 0x002F -#define QMIWDS_GET_DATA_BEARER_REQ 0x0037 -#define QMIWDS_GET_DATA_BEARER_RESP 0x0037 -#define QMIWDS_DUN_CALL_INFO_REQ 0x0038 -#define QMIWDS_DUN_CALL_INFO_RESP 0x0038 -#define QMIWDS_DUN_CALL_INFO_IND 0x0038 -#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ 0x004D -#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP 0x004D -#define QMIWDS_SET_AUTO_CONNECT_REQ 0x0051 -#define QMIWDS_SET_AUTO_CONNECT_RESP 0x0051 -#define QMIWDS_BIND_MUX_DATA_PORT_REQ 0x00A2 -#define QMIWDS_BIND_MUX_DATA_PORT_RESP 0x00A2 - -// Stats masks -#define QWDS_STAT_MASK_TX_PKT_OK 0x00000001 -#define QWDS_STAT_MASK_RX_PKT_OK 0x00000002 -#define QWDS_STAT_MASK_TX_PKT_ER 0x00000004 -#define QWDS_STAT_MASK_RX_PKT_ER 0x00000008 -#define QWDS_STAT_MASK_TX_PKT_OF 0x00000010 -#define QWDS_STAT_MASK_RX_PKT_OF 0x00000020 - -// TLV Types for xfer statistics -#define TLV_WDS_TX_GOOD_PKTS 0x10 -#define TLV_WDS_RX_GOOD_PKTS 0x11 -#define TLV_WDS_TX_ERROR 0x12 -#define TLV_WDS_RX_ERROR 0x13 -#define TLV_WDS_TX_OVERFLOW 0x14 -#define TLV_WDS_RX_OVERFLOW 0x15 -#define TLV_WDS_CHANNEL_RATE 0x16 -#define TLV_WDS_DATA_BEARER 0x17 -#define TLV_WDS_DORMANCY_STATUS 0x18 - -#define QWDS_PKT_DATA_DISCONNECTED 0x01 -#define QWDS_PKT_DATA_CONNECTED 0x02 -#define QWDS_PKT_DATA_SUSPENDED 0x03 -#define QWDS_PKT_DATA_AUTHENTICATING 0x04 - -#define QMIWDS_ADMIN_SET_DATA_FORMAT_REQ 0x0020 -#define QMIWDS_ADMIN_SET_DATA_FORMAT_RESP 0x0020 -#define QMIWDS_ADMIN_GET_DATA_FORMAT_REQ 0x0021 -#define QMIWDS_ADMIN_GET_DATA_FORMAT_RESP 0x0021 -#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ 0x002B -#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP 0x002B -#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ 0x002C -#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP 0x002C - -#define NETWORK_DESC_ENCODING_OCTET 0x00 -#define NETWORK_DESC_ENCODING_EXTPROTOCOL 0x01 -#define NETWORK_DESC_ENCODING_7BITASCII 0x02 -#define NETWORK_DESC_ENCODING_IA5 0x03 -#define NETWORK_DESC_ENCODING_UNICODE 0x04 -#define NETWORK_DESC_ENCODING_SHIFTJIS 0x05 -#define NETWORK_DESC_ENCODING_KOREAN 0x06 -#define NETWORK_DESC_ENCODING_LATINH 0x07 -#define NETWORK_DESC_ENCODING_LATIN 0x08 -#define NETWORK_DESC_ENCODING_GSM7BIT 0x09 -#define NETWORK_DESC_ENCODING_GSMDATA 0x0A -#define NETWORK_DESC_ENCODING_UNKNOWN 0xFF - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT { - USHORT Type; // QMUX type 0x0000 - USHORT Length; -} __attribute__((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT, - *PQMIWDS_ADMIN_SET_DATA_FORMAT; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS { - UCHAR TLVType; - USHORT TLVLength; - UCHAR QOSSetting; -} __attribute__((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS, - *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV { - UCHAR TLVType; - USHORT TLVLength; - ULONG Value; -} __attribute__((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV, - *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV; - -typedef struct _QMIWDS_ENDPOINT_TLV { - UCHAR TLVType; - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; -} __attribute__((packed)) QMIWDS_ENDPOINT_TLV, *PQMIWDS_ENDPOINT_TLV; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG { - USHORT Type; - USHORT Length; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv; -#if 0 - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxSizeTlv; -#else - QMIWDS_ENDPOINT_TLV epTlv; -#endif -} __attribute__((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG, - *PQMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG; - -#if 0 -typedef enum _QMI_RETURN_CODES { - QMI_SUCCESS = 0, - QMI_SUCCESS_NOT_COMPLETE, - QMI_FAILURE -}QMI_RETURN_CODES; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG -{ - USHORT Type; // 0x0022 - USHORT Length; // 0x0000 -} QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLVType2; - USHORT TLVLength2; - UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED - // 0x02: QWDS_PKT_DATA_CONNECTED - // 0x03: QWDS_PKT_DATA_SUSPENDED - // 0x04: QWDS_PKT_DATA_AUTHENTICATING -} QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED - // 0x02: QWDS_PKT_DATA_CONNECTED - // 0x03: QWDS_PKT_DATA_SUSPENDED - UCHAR ReconfigRequired; // 0x00: No need to reconfigure - // 0x01: Reconfiguration required -} QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_IND_MSG; - -typedef struct _WDS_PKT_SRVC_IP_FAMILY_TLV -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 1 - UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 -} WDS_PKT_SRVC_IP_FAMILY_TLV, *PWDS_PKT_SRVC_IP_FAMILY_TLV; - -typedef struct _QMIWDS_DUN_CALL_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG Mask; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR ReportConnectionStatus; -} QMIWDS_DUN_CALL_INFO_REQ_MSG, *PQMIWDS_DUN_CALL_INFO_REQ_MSG; - -typedef struct _QMIWDS_DUN_CALL_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWDS_DUN_CALL_INFO_RESP_MSG, *PQMIWDS_DUN_CALL_INFO_RESP_MSG; - -typedef struct _QMIWDS_DUN_CALL_INFO_IND_MSG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; -} QMIWDS_DUN_CALL_INFO_IND_MSG, *PQMIWDS_DUN_CALL_INFO_IND_MSG; - -typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; -} QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG; - -typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 16 - //ULONG CallHandle; // Context corresponding to reported channel - ULONG CurrentTxRate; // bps - ULONG CurrentRxRate; // bps - ULONG ServingSystemTxRate; // bps - ULONG ServingSystemRxRate; // bps - -} QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_RESP; - -#define QWDS_EVENT_REPORT_MASK_RATES 0x01 -#define QWDS_EVENT_REPORT_MASK_STATS 0x02 - -#ifdef QCUSB_MUX_PROTOCOL -#error code not present -#endif // QCUSB_MUX_PROTOCOL - -typedef struct _QMIWDS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0042 - USHORT Length; - - UCHAR TLVType; // 0x10 -- current channel rate indicator - USHORT TLVLength; // 1 - UCHAR Mode; // 0-do not report; 1-report when rate changes - - UCHAR TLV2Type; // 0x11 - USHORT TLV2Length; // 5 - UCHAR StatsPeriod; // seconds between reports; 0-do not report - ULONG StatsMask; // - - UCHAR TLV3Type; // 0x12 -- current data bearer indicator - USHORT TLV3Length; // 1 - UCHAR Mode3; // 0-do not report; 1-report when changes - - UCHAR TLV4Type; // 0x13 -- dormancy status indicator - USHORT TLV4Length; // 1 - UCHAR DormancyStatus; // 0-do not report; 1-report when changes -} QMIWDS_SET_EVENT_REPORT_REQ_MSG, *PQMIWDS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIWDS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0042 - USHORT Length; - - UCHAR TLVType; // 0x02 result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_NO_BATTERY - // QMI_ERR_FAULT -} QMIWDS_SET_EVENT_REPORT_RESP_MSG, *PQMIWDS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMIWDS_EVENT_REPORT_IND_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; -} QMIWDS_EVENT_REPORT_IND_MSG, *PQMIWDS_EVENT_REPORT_IND_MSG; - -// PQCTLV_PKT_STATISTICS - -typedef struct _QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV -{ - UCHAR Type; - USHORT Length; // 8 - ULONG TxRate; - ULONG RxRate; -} QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV, *PQMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV; - -#ifdef QCUSB_MUX_PROTOCOL -#error code not present -#endif // QCUSB_MUX_PROTOCOL - -typedef struct _QMIWDS_GET_PKT_STATISTICS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0041 - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 4 - ULONG StateMask; // 0x00000001 tx success packets - // 0x00000002 rx success packets - // 0x00000004 rx packet errors (checksum) - // 0x00000008 rx packets dropped (memory) - -} QMIWDS_GET_PKT_STATISTICS_REQ_MSG, *PQMIWDS_GET_PKT_STATISTICS_REQ_MSG; - -typedef struct _QMIWDS_GET_PKT_STATISTICS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0041 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIWDS_GET_PKT_STATISTICS_RESP_MSG, *PQMIWDS_GET_PKT_STATISTICS_RESP_MSG; - -// optional TLV for stats -typedef struct _QCTLV_PKT_STATISTICS -{ - UCHAR TLVType; // see above definitions for TLV types - USHORT TLVLength; // 4 - ULONG Count; -} QCTLV_PKT_STATISTICS, *PQCTLV_PKT_STATISTICS; -#endif - -//#ifdef QC_IP_MODE - -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR 0x0010 -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR 0x0100 -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR 0x0200 -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU 0x2000 - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG { - USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_REQ - USHORT Length; - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 0x0004 - ULONG Mask; // mask, bit 8: IP addr -- 0x0100 -} __attribute__((packed)) QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG, - *PQMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR MuxId; - UCHAR TLV3Type; - USHORT TLV3Length; - ULONG client_type; -} __attribute__((packed)) QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG, - *PQMIWDS_BIND_MUX_DATA_PORT_REQ_MSG; - -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS 0x15 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS 0x16 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 0x1E -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY 0x20 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET 0x21 - -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 0x25 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY 0x26 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS 0x27 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS 0x28 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU 0x29 - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU { - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU - USHORT TLVLength; // 4 - ULONG Mtu; // MTU -} __attribute__((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU, - *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR { - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 - USHORT TLVLength; // 4 - ULONG IPV4Address; // address -} __attribute__((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR, - *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR { - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 - USHORT TLVLength; // 16 - UCHAR IPV6Address[16]; // address - UCHAR PrefixLength; // prefix length -} __attribute__((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR, - *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR; - - typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_DNS_ADDR { - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 - USHORT TLVLength; // 16 - UCHAR IPV6Address[16]; // address - } __attribute__((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_DNS_ADDR, - *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_DNS_ADDR; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG { - USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMUXResult; // result code - USHORT QMUXError; // error code -} __attribute__((packed)) QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG, - *PQMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG; - -//#endif // QC_IP_MODE - -typedef struct _QMIWDS_IP_FAMILY_TLV { - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 1 - UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 -} __attribute__((packed)) QMIWDS_IP_FAMILY_TLV, *PQMIWDS_IP_FAMILY_TLV; - -typedef struct _QMIWDS_PKT_SRVC_TLV { - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; - UCHAR ReconfigReqd; -} __attribute__((packed)) QMIWDS_PKT_SRVC_TLV, *PQMIWDS_PKT_SRVC_TLV; - -typedef struct _QMIWDS_CALL_END_REASON_TLV { - UCHAR TLVType; - USHORT TLVLength; - USHORT CallEndReason; -} __attribute__((packed)) QMIWDS_CALL_END_REASON_TLV, - *PQMIWDS_CALL_END_REASON_TLV; - -typedef struct _QMIWDS_CALL_END_REASON_V_TLV { - UCHAR TLVType; - USHORT TLVLength; - USHORT CallEndReasonType; - USHORT CallEndReason; -} __attribute__((packed)) QMIWDS_CALL_END_REASON_V_TLV, - *PQMIWDS_CALL_END_REASON_V_TLV; - -typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG { - USHORT Type; // QMUX type 0x004D - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR IpPreference; // IPV4-0x04, IPV6-0x06 -} __attribute__((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG, - *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG; - -typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG { - USHORT Type; // QMUX type 0x0037 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS, QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INTERNAL, QMI_ERR_MALFORMED_MSG, - // QMI_ERR_INVALID_ARG -} __attribute__((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG, - *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG; - -typedef struct _QMIWDS_SET_AUTO_CONNECT_REQ_MSG { - USHORT Type; // QMUX type 0x0051 - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR autoconnect_setting; // 0x00 ?C Disabled, 0x01 ?C Enabled, 0x02 ?C - // Paused (resume on power cycle) -} __attribute__((packed)) QMIWDS_SET_AUTO_CONNECT_REQ_MSG, - *PQMIWDS_SET_AUTO_CONNECT_REQ_MSG; - -#if 0 -typedef struct _QMIWDS_GET_MIP_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; -} QMIWDS_GET_MIP_MODE_REQ_MSG, *PQMIWDS_GET_MIP_MODE_REQ_MSG; - -typedef struct _QMIWDS_GET_MIP_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 20 - UCHAR MipMode; // -} QMIWDS_GET_MIP_MODE_RESP_MSG, *PQMIWDS_GET_MIP_MODE_RESP_MSG; -#endif - -typedef struct _QMIWDS_TECHNOLOGY_PREFERECE { - UCHAR TLVType; - USHORT TLVLength; - UCHAR TechPreference; -} __attribute__((packed)) QMIWDS_TECHNOLOGY_PREFERECE, - *PQMIWDS_TECHNOLOGY_PREFERECE; - -typedef struct _QMIWDS_PROFILE_IDENTIFIER { - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileIndex; -} __attribute__((packed)) QMIWDS_PROFILE_IDENTIFIER, - *PQMIWDS_PROFILE_IDENTIFIER; - -#if 0 -typedef struct _QMIWDS_IPADDRESS -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG IPv4Address; -}QMIWDS_IPADDRESS, *PQMIWDS_IPADDRESS; - -/* -typedef struct _QMIWDS_UMTS_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TrafficClass; - ULONG MaxUplinkBitRate; - ULONG MaxDownlinkBitRate; - ULONG GuarUplinkBitRate; - ULONG GuarDownlinkBitRate; - UCHAR QOSDevOrder; - ULONG MAXSDUSize; - UCHAR SDUErrorRatio; - UCHAR ResidualBerRatio; - UCHAR DeliveryErrorSDUs; - ULONG TransferDelay; - ULONG TrafficHndPri; -}QMIWDS_UMTS_QOS, *PQMIWDS_UMTS_QOS; - -typedef struct _QMIWDS_GPRS_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG PrecedenceClass; - ULONG DelayClass; - ULONG ReliabilityClass; - ULONG PeekThroClass; - ULONG MeanThroClass; -}QMIWDS_GPRS_QOS, *PQMIWDS_GPRS_QOS; -*/ -#endif - -typedef struct _QMIWDS_PROFILENAME { - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileName; -} __attribute__((packed)) QMIWDS_PROFILENAME, *PQMIWDS_PROFILENAME; - -typedef struct _QMIWDS_PDPTYPE { - UCHAR TLVType; - USHORT TLVLength; - // 0 ?C PDP-IP (IPv4) - // 1 ?C PDP-PPP - // 2 ?C PDP-IPv6 - // 3 ?C PDP-IPv4v6 - UCHAR PdpType; -} __attribute__((packed)) QMIWDS_PDPTYPE, *PQMIWDS_PDPTYPE; - -typedef struct _QMIWDS_USERNAME { - UCHAR TLVType; - USHORT TLVLength; - UCHAR UserName; -} __attribute__((packed)) QMIWDS_USERNAME, *PQMIWDS_USERNAME; - -typedef struct _QMIWDS_PASSWD { - UCHAR TLVType; - USHORT TLVLength; - UCHAR Passwd; -} __attribute__((packed)) QMIWDS_PASSWD, *PQMIWDS_PASSWD; - -typedef struct _QMIWDS_AUTH_PREFERENCE { - UCHAR TLVType; - USHORT TLVLength; - UCHAR AuthPreference; -} __attribute__((packed)) QMIWDS_AUTH_PREFERENCE, *PQMIWDS_AUTH_PREFERENCE; - -typedef struct _QMIWDS_APNNAME { - UCHAR TLVType; - USHORT TLVLength; - UCHAR ApnName; -} __attribute__((packed)) QMIWDS_APNNAME, *PQMIWDS_APNNAME; - -typedef struct _QMIWDS_AUTOCONNECT { - UCHAR TLVType; - USHORT TLVLength; - UCHAR AutoConnect; -} __attribute__((packed)) QMIWDS_AUTOCONNECT, *PQMIWDS_AUTOCONNECT; - -typedef struct _QMIWDS_START_NETWORK_INTERFACE_REQ_MSG { - USHORT Type; - USHORT Length; -} __attribute__((packed)) QMIWDS_START_NETWORK_INTERFACE_REQ_MSG, - *PQMIWDS_START_NETWORK_INTERFACE_REQ_MSG; - -typedef struct _QMIWDS_CALLENDREASON { - UCHAR TLVType; - USHORT TLVLength; - USHORT Reason; -} __attribute__((packed)) QMIWDS_CALLENDREASON, *PQMIWDS_CALLENDREASON; - -typedef struct _QMIWDS_START_NETWORK_INTERFACE_RESP_MSG { - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 20 - ULONG Handle; // -} __attribute__((packed)) QMIWDS_START_NETWORK_INTERFACE_RESP_MSG, - *PQMIWDS_START_NETWORK_INTERFACE_RESP_MSG; - -typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG Handle; -} __attribute__((packed)) QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG, - *PQMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG; - -typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG { - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - -} __attribute__((packed)) QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG, - *PQMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG; - -typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; -} __attribute__((packed)) QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG, - *PQMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG, - *PQMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG; -//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 -typedef struct _QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; -} __attribute__((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG, - *PQMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG; - - -typedef struct _QMIWDS_CREATE_PROFILE_SETTINGS_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_RESP_MSG, - *PQMIWDS_CREATE_PROFILE_SETTINGS_RESP_MSG; -//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 -typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR ProfileIndex; -} __attribute__((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG, - *PQMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG, - *PQMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG; - -typedef struct _QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR ProfileIndex; -} __attribute__((packed)) QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG, - *PQMIWDS_GET_PROFILE_SETTINGS_REQ_MSG; - -#if 0 -typedef struct _QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR DataBearer; -} QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV, *PQMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV; - -typedef struct _QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR DormancyStatus; -} QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV, *PQMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV; - - -typedef struct _QMIWDS_GET_DATA_BEARER_REQ_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; -} QMIWDS_GET_DATA_BEARER_REQ_MSG, *PQMIWDS_GET_DATA_BEARER_REQ_MSG; - -typedef struct _QMIWDS_GET_DATA_BEARER_RESP_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INTERNAL - // QMI_ERR_MALFORMED_MSG - // QMI_ERR_NO_MEMORY - // QMI_ERR_OUT_OF_CALL - // QMI_ERR_INFO_UNAVAILABLE - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // - UCHAR Technology; // -} QMIWDS_GET_DATA_BEARER_RESP_MSG, *PQMIWDS_GET_DATA_BEARER_RESP_MSG; -#endif - -// ======================= DMS ============================== -#define QMIDMS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIDMS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIDMS_EVENT_REPORT_IND 0x0001 -#define QMIDMS_GET_DEVICE_CAP_REQ 0x0020 -#define QMIDMS_GET_DEVICE_CAP_RESP 0x0020 -#define QMIDMS_GET_DEVICE_MFR_REQ 0x0021 -#define QMIDMS_GET_DEVICE_MFR_RESP 0x0021 -#define QMIDMS_GET_DEVICE_MODEL_ID_REQ 0x0022 -#define QMIDMS_GET_DEVICE_MODEL_ID_RESP 0x0022 -#define QMIDMS_GET_DEVICE_REV_ID_REQ 0x0023 -#define QMIDMS_GET_DEVICE_REV_ID_RESP 0x0023 -#define QMIDMS_GET_MSISDN_REQ 0x0024 -#define QMIDMS_GET_MSISDN_RESP 0x0024 -#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ 0x0025 -#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP 0x0025 -#define QMIDMS_UIM_SET_PIN_PROTECTION_REQ 0x0027 -#define QMIDMS_UIM_SET_PIN_PROTECTION_RESP 0x0027 -#define QMIDMS_UIM_VERIFY_PIN_REQ 0x0028 -#define QMIDMS_UIM_VERIFY_PIN_RESP 0x0028 -#define QMIDMS_UIM_UNBLOCK_PIN_REQ 0x0029 -#define QMIDMS_UIM_UNBLOCK_PIN_RESP 0x0029 -#define QMIDMS_UIM_CHANGE_PIN_REQ 0x002A -#define QMIDMS_UIM_CHANGE_PIN_RESP 0x002A -#define QMIDMS_UIM_GET_PIN_STATUS_REQ 0x002B -#define QMIDMS_UIM_GET_PIN_STATUS_RESP 0x002B -#define QMIDMS_GET_DEVICE_HARDWARE_REV_REQ 0x002C -#define QMIDMS_GET_DEVICE_HARDWARE_REV_RESP 0x002C -#define QMIDMS_GET_OPERATING_MODE_REQ 0x002D -#define QMIDMS_GET_OPERATING_MODE_RESP 0x002D -#define QMIDMS_SET_OPERATING_MODE_REQ 0x002E -#define QMIDMS_SET_OPERATING_MODE_RESP 0x002E -#define QMIDMS_GET_ACTIVATED_STATUS_REQ 0x0031 -#define QMIDMS_GET_ACTIVATED_STATUS_RESP 0x0031 -#define QMIDMS_ACTIVATE_AUTOMATIC_REQ 0x0032 -#define QMIDMS_ACTIVATE_AUTOMATIC_RESP 0x0032 -#define QMIDMS_ACTIVATE_MANUAL_REQ 0x0033 -#define QMIDMS_ACTIVATE_MANUAL_RESP 0x0033 -#define QMIDMS_UIM_GET_ICCID_REQ 0x003C -#define QMIDMS_UIM_GET_ICCID_RESP 0x003C -#define QMIDMS_UIM_GET_CK_STATUS_REQ 0x0040 -#define QMIDMS_UIM_GET_CK_STATUS_RESP 0x0040 -#define QMIDMS_UIM_SET_CK_PROTECTION_REQ 0x0041 -#define QMIDMS_UIM_SET_CK_PROTECTION_RESP 0x0041 -#define QMIDMS_UIM_UNBLOCK_CK_REQ 0x0042 -#define QMIDMS_UIM_UNBLOCK_CK_RESP 0x0042 -#define QMIDMS_UIM_GET_IMSI_REQ 0x0043 -#define QMIDMS_UIM_GET_IMSI_RESP 0x0043 -#define QMIDMS_UIM_GET_STATE_REQ 0x0044 -#define QMIDMS_UIM_GET_STATE_RESP 0x0044 -#define QMIDMS_GET_BAND_CAP_REQ 0x0045 -#define QMIDMS_GET_BAND_CAP_RESP 0x0045 - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_MFR_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMIDMS_GET_DEVICE_MFR_REQ_MSG, *PQMIDMS_GET_DEVICE_MFR_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MFR_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - UCHAR DeviceManufacturer; // first byte of string -} QMIDMS_GET_DEVICE_MFR_RESP_MSG, *PQMIDMS_GET_DEVICE_MFR_RESP_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0004 - USHORT Length; -} QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0004 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the modem id string - UCHAR DeviceModelID; // device model id -} QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG; -#endif - -typedef struct _QMIDMS_GET_DEVICE_REV_ID_REQ_MSG { - USHORT Type; // QMUX type 0x0005 - USHORT Length; -} __attribute__((packed)) QMIDMS_GET_DEVICE_REV_ID_REQ_MSG, - *PQMIDMS_GET_DEVICE_REV_ID_REQ_MSG; - -typedef struct _DEVICE_REV_ID { - UCHAR TLVType; - USHORT TLVLength; - UCHAR RevisionID; -} __attribute__((packed)) DEVICE_REV_ID, *PDEVICE_REV_ID; - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_REV_ID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0023 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIDMS_GET_DEVICE_REV_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_REV_ID_RESP_MSG; - -typedef struct _QMIDMS_GET_MSISDN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} QMIDMS_GET_MSISDN_REQ_MSG, *PQMIDMS_GET_MSISDN_REQ_MSG; - -typedef struct _QCTLV_DEVICE_VOICE_NUMBERS -{ - UCHAR TLVType; // as defined above - USHORT TLVLength; // 4/7/7 - UCHAR VoideNumberString; // ESN, IMEI, or MEID - -} QCTLV_DEVICE_VOICE_NUMBERS, *PQCTLV_DEVICE_VOICE_NUMBERS; - - -typedef struct _QMIDMS_GET_MSISDN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG -} QMIDMS_GET_MSISDN_RESP_MSG, *PQMIDMS_GET_MSISDN_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_GET_IMSI_REQ_MSG { - USHORT Type; - USHORT Length; -} __attribute__((packed)) QMIDMS_UIM_GET_IMSI_REQ_MSG, - *PQMIDMS_UIM_GET_IMSI_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_IMSI_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR IMSI; -} __attribute__((packed)) QMIDMS_UIM_GET_IMSI_RESP_MSG, - *PQMIDMS_UIM_GET_IMSI_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0007 - USHORT Length; -} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG; - -#define QCTLV_TYPE_SER_NUM_ESN 0x10 -#define QCTLV_TYPE_SER_NUM_IMEI 0x11 -#define QCTLV_TYPE_SER_NUM_MEID 0x12 - -typedef struct _QCTLV_DEVICE_SERIAL_NUMBER -{ - UCHAR TLVType; // as defined above - USHORT TLVLength; // 4/7/7 - UCHAR SerialNumberString; // ESN, IMEI, or MEID - -} QCTLV_DEVICE_SERIAL_NUMBER, *PQCTLV_DEVICE_SERIAL_NUMBER; - -typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0007 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - // followed by optional TLV -} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP; - -typedef struct _QMIDMS_GET_DMS_BAND_CAP -{ - USHORT Type; - USHORT Length; -} QMIDMS_GET_BAND_CAP_REQ_MSG, *PQMIDMS_GET_BAND_CAP_REQ_MSG; - -typedef struct _QMIDMS_GET_BAND_CAP_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_NONE - // QMI_ERR_INTERNAL - // QMI_ERR_MALFORMED_MSG - // QMI_ERR_NO_MEMORY - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - ULONG64 BandCap; -} QMIDMS_GET_BAND_CAP_RESP_MSG, *PQMIDMS_GET_BAND_CAP_RESP; - -typedef struct _QMIDMS_GET_DEVICE_CAP_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_DEVICE_CAP_REQ_MSG, *PQMIDMS_GET_DEVICE_CAP_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_CAP_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - ULONG MaxTxChannelRate; - ULONG MaxRxChannelRate; - UCHAR VoiceCap; - UCHAR SimCap; - - UCHAR RadioIfListCnt; // #elements in radio interface list - UCHAR RadioIfList; // N 1-byte elements -} QMIDMS_GET_DEVICE_CAP_RESP_MSG, *PQMIDMS_GET_DEVICE_CAP_RESP_MSG; - -typedef struct _QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG, *PQMIDMS_GET_ACTIVATES_STATUD_REQ_MSG; - -typedef struct _QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - USHORT ActivatedStatus; -} QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG, *PQMIDMS_GET_ACTIVATED_STATUS_RESP_MSG; - -typedef struct _QMIDMS_GET_OPERATING_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_OPERATING_MODE_REQ_MSG, *PQMIDMS_GET_OPERATING_MODE_REQ_MSG; - -typedef struct _OFFLINE_REASON -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT OfflineReason; -} OFFLINE_REASON, *POFFLINE_REASON; - -typedef struct _HARDWARE_RESTRICTED_MODE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR HardwareControlledMode; -} HARDWARE_RESTRICTED_MODE, *PHARDWARE_RESTRICTED_MODE; - -typedef struct _QMIDMS_GET_OPERATING_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - UCHAR OperatingMode; -} QMIDMS_GET_OPERATING_MODE_RESP_MSG, *PQMIDMS_GET_OPERATING_MODE_RESP_MSG; - -typedef struct _QMIDMS_UIM_GET_ICCID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} QMIDMS_UIM_GET_ICCID_REQ_MSG, *PQMIDMS_UIM_GET_ICCID_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_ICCID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // var - UCHAR ICCID; // String of voice number -} QMIDMS_UIM_GET_ICCID_RESP_MSG, *PQMIDMS_UIM_GET_ICCID_RESP_MSG; -#endif - -typedef struct _QMIDMS_SET_OPERATING_MODE_REQ_MSG { - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR OperatingMode; -} __attribute__((packed)) QMIDMS_SET_OPERATING_MODE_REQ_MSG, - *PQMIDMS_SET_OPERATING_MODE_REQ_MSG; - -typedef struct _QMIDMS_SET_OPERATING_MODE_RESP_MSG { - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT -} __attribute__((packed)) QMIDMS_SET_OPERATING_MODE_RESP_MSG, - *PQMIDMS_SET_OPERATING_MODE_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR ActivateCodelen; - UCHAR ActivateCode; -} QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG; - -typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG; - - -typedef struct _SPC_MSG -{ - UCHAR SPC[6]; - USHORT SID; -} SPC_MSG, *PSPC_MSG; - -typedef struct _MDN_MSG -{ - UCHAR MDNLEN; - UCHAR MDN; -} MDN_MSG, *PMDN_MSG; - -typedef struct _MIN_MSG -{ - UCHAR MINLEN; - UCHAR MIN; -} MIN_MSG, *PMIN_MSG; - -typedef struct _PRL_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - USHORT PRLLEN; - UCHAR PRL; -} PRL_MSG, *PPRL_MSG; - -typedef struct _MN_HA_KEY_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR MN_HA_KEY_LEN; - UCHAR MN_HA_KEY; -} MN_HA_KEY_MSG, *PMN_HA_KEY_MSG; - -typedef struct _MN_AAA_KEY_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR MN_AAA_KEY_LEN; - UCHAR MN_AAA_KEY; -} MN_AAA_KEY_MSG, *PMN_AAA_KEY_MSG; - -typedef struct _QMIDMS_ACTIVATE_MANUAL_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR Value; -} QMIDMS_ACTIVATE_MANUAL_REQ_MSG, *PQMIDMS_ACTIVATE_MANUAL_REQ_MSG; - -typedef struct _QMIDMS_ACTIVATE_MANUAL_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIDMS_ACTIVATE_MANUAL_RESP_MSG, *PQMIDMS_ACTIVATE_MANUAL_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_GET_STATE_REQ_MSG { - USHORT Type; - USHORT Length; -} __attribute__((packed)) QMIDMS_UIM_GET_STATE_REQ_MSG, - *PQMIDMS_UIM_GET_STATE_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_STATE_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR UIMState; -} __attribute__((packed)) QMIDMS_UIM_GET_STATE_RESP_MSG, - *PQMIDMS_UIM_GET_STATE_RESP_MSG; - -typedef struct _QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG { - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} __attribute__((packed)) QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG, - *PQMIDMS_UIM_GET_PIN_STATUS_REQ_MSG; - -typedef struct _QMIDMS_UIM_PIN_STATUS { - UCHAR TLVType; - USHORT TLVLength; - UCHAR PINStatus; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__((packed)) QMIDMS_UIM_PIN_STATUS, *PQMIDMS_UIM_PIN_STATUS; - -#define QMI_PIN_STATUS_NOT_INIT 0 -#define QMI_PIN_STATUS_NOT_VERIF 1 -#define QMI_PIN_STATUS_VERIFIED 2 -#define QMI_PIN_STATUS_DISABLED 3 -#define QMI_PIN_STATUS_BLOCKED 4 -#define QMI_PIN_STATUS_PERM_BLOCKED 5 -#define QMI_PIN_STATUS_UNBLOCKED 6 -#define QMI_PIN_STATUS_CHANGED 7 - -typedef struct _QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG { - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR PinStatus; -} __attribute__((packed)) QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG, - *PQMIDMS_UIM_GET_PIN_STATUS_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_UIM_GET_CK_STATUS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; -} QMIDMS_UIM_GET_CK_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_CK_STATUS_REQ_MSG; - - -typedef struct _QMIDMS_UIM_CK_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR FacilityStatus; - UCHAR FacilityVerifyRetriesLeft; - UCHAR FacilityUnblockRetriesLeft; -} QMIDMS_UIM_CK_STATUS, *PQMIDMS_UIM_CK_STATUS; - -typedef struct _QMIDMS_UIM_CK_OPERATION_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR OperationBlocking; -} QMIDMS_UIM_CK_OPERATION_STATUS, *PQMIDMS_UIM_CK_OPERATION_STATUS; - -typedef struct _QMIDMS_UIM_GET_CK_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR CkStatus; -} QMIDMS_UIM_GET_CK_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_CK_STATUS_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_VERIFY_PIN_REQ_MSG { - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PINLen; - UCHAR PINValue; -} __attribute__((packed)) QMIDMS_UIM_VERIFY_PIN_REQ_MSG, - *PQMIDMS_UIM_VERIFY_PIN_REQ_MSG; - -typedef struct _QMIDMS_UIM_VERIFY_PIN_RESP_MSG { - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__((packed)) QMIDMS_UIM_VERIFY_PIN_RESP_MSG, - *PQMIDMS_UIM_VERIFY_PIN_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR ProtectionSetting; - UCHAR PINLen; - UCHAR PINValue; -} QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG; - -typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG; - -typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; - UCHAR FacilityState; - UCHAR FacliltyLen; - UCHAR FacliltyValue; -} QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG; - -typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR FacilityRetriesLeft; -} QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG; - - -typedef struct _UIM_PIN -{ - UCHAR PinLength; - UCHAR PinValue; -} UIM_PIN, *PUIM_PIN; - -typedef struct _QMIDMS_UIM_CHANGE_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PinDetails; -} QMIDMS_UIM_CHANGE_PIN_REQ_MSG, *PQMIDMS_UIM_CHANGE_PIN_REQ_MSG; - -typedef struct QMIDMS_UIM_CHANGE_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_CHANGE_PIN_RESP_MSG, *PQMIDMS_UIM_CHANGE_PIN_RESP_MSG; - -typedef struct _UIM_PUK -{ - UCHAR PukLength; - UCHAR PukValue; -} UIM_PUK, *PUIM_PUK; - -typedef struct _QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PinDetails; -} QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG, *PQMIDMS_UIM_BLOCK_PIN_REQ_MSG; - -typedef struct QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_PIN_RESP_MSG; - -typedef struct _QMIDMS_UIM_UNBLOCK_CK_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; - UCHAR FacliltyUnblockLen; - UCHAR FacliltyUnblockValue; -} QMIDMS_UIM_UNBLOCK_CK_REQ_MSG, *PQMIDMS_UIM_BLOCK_CK_REQ_MSG; - -typedef struct QMIDMS_UIM_UNBLOCK_CK_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR FacilityUnblockRetriesLeft; -} QMIDMS_UIM_UNBLOCK_CK_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_CK_RESP_MSG; - -typedef struct _QMIDMS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMIDMS_SET_EVENT_REPORT_REQ_MSG, *PQMIDMS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIDMS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG -} QMIDMS_SET_EVENT_REPORT_RESP_MSG, *PQMIDMS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _PIN_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportPinState; -} PIN_STATUS, *PPIN_STATUS; - -typedef struct _POWER_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PowerStatus; - UCHAR BatteryLvl; -} POWER_STATUS, *PPOWER_STATUS; - -typedef struct _ACTIVATION_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT ActivationState; -} ACTIVATION_STATE, *PACTIVATION_STATE; - -typedef struct _ACTIVATION_STATE_REQ -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ActivationState; -} ACTIVATION_STATE_REQ, *PACTIVATION_STATE_REQ; - -typedef struct _OPERATING_MODE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR OperatingMode; -} OPERATING_MODE, *POPERATING_MODE; - -typedef struct _UIM_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR UIMState; -} UIM_STATE, *PUIM_STATE; - -typedef struct _WIRELESS_DISABLE_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR WirelessDisableState; -} WIRELESS_DISABLE_STATE, *PWIRELESS_DISABLE_STATE; - -typedef struct _QMIDMS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMIDMS_EVENT_REPORT_IND_MSG, *PQMIDMS_EVENT_REPORT_IND_MSG; -#endif - -// ============================ END OF DMS =============================== - -// ======================= QOS ============================== -typedef struct _MPIOC_DEV_INFO MPIOC_DEV_INFO, *PMPIOC_DEV_INFO; - -#define QMI_QOS_SET_EVENT_REPORT_REQ 0x0001 -#define QMI_QOS_SET_EVENT_REPORT_RESP 0x0001 -#define QMI_QOS_EVENT_REPORT_IND 0x0001 - -#if 0 -typedef struct _QMI_QOS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; - // UCHAR TLVType; // 0x01 - physical link state - // USHORT TLVLength; // 1 - // UCHAR PhyLinkStatusRpt; // 0-enable; 1-disable - UCHAR TLVType2; // 0x02 = global flow reporting - USHORT TLVLength2; // 1 - UCHAR GlobalFlowRpt; // 1-enable; 0-disable -} QMI_QOS_SET_EVENT_REPORT_REQ_MSG, *PQMI_QOS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMI_QOS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0010 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT -} QMI_QOS_SET_EVENT_REPORT_RESP_MSG, *PQMI_QOS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMI_QOS_EVENT_REPORT_IND_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; - UCHAR TLVs; -} QMI_QOS_EVENT_REPORT_IND_MSG, *PQMI_QOS_EVENT_REPORT_IND_MSG; - -#define QOS_EVENT_RPT_IND_FLOW_ACTIVATED 0x01 -#define QOS_EVENT_RPT_IND_FLOW_MODIFIED 0x02 -#define QOS_EVENT_RPT_IND_FLOW_DELETED 0x03 -#define QOS_EVENT_RPT_IND_FLOW_SUSPENDED 0x04 -#define QOS_EVENT_RPT_IND_FLOW_ENABLED 0x05 -#define QOS_EVENT_RPT_IND_FLOW_DISABLED 0x06 - -#define QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE_TYPE 0x01 -#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_STATE 0x10 -#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_TYPE 0x10 -#define QOS_EVENT_RPT_IND_TLV_TX_FLOW_TYPE 0x11 -#define QOS_EVENT_RPT_IND_TLV_RX_FLOW_TYPE 0x12 -#define QOS_EVENT_RPT_IND_TLV_TX_FILTER_TYPE 0x13 -#define QOS_EVENT_RPT_IND_TLV_RX_FILTER_TYPE 0x14 -#define QOS_EVENT_RPT_IND_TLV_FLOW_SPEC 0x10 -#define QOS_EVENT_RPT_IND_TLV_FILTER_SPEC 0x10 - -typedef struct _QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE -{ - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR PhyLinkState; // 0-dormant, 1-active -} QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE, *PQOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE; - -typedef struct _QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 6 - ULONG QosId; - UCHAR NewFlow; // 1: newly added flow; 0: existing flow - UCHAR StateChange; // 1: activated; 2: modified; 3: deleted; - // 4: suspended(delete); 5: enabled; 6: disabled -} QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT, *PQOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT; - -// QOS Flow - -typedef struct _QOS_EVENT_RPT_IND_TLV_FLOW -{ - UCHAR TLVType; // 0x10-TX flow; 0x11-RX flow - USHORT TLVLength; // var - // embedded TLV's -} QOS_EVENT_RPT_IND_TLV_TX_FLOW, *PQOS_EVENT_RPT_IND_TLV_TX_FLOW; - -#define QOS_FLOW_TLV_IP_FLOW_IDX_TYPE 0x10 -#define QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS_TYPE 0x11 -#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX_TYPE 0x12 -#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET_TYPE 0x13 -#define QOS_FLOW_TLV_IP_FLOW_LATENCY_TYPE 0x14 -#define QOS_FLOW_TLV_IP_FLOW_JITTER_TYPE 0x15 -#define QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE_TYPE 0x16 -#define QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE_TYPE 0x17 -#define QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE_TYPE 0x18 -#define QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE_TYPE 0x19 -#define QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY_TYPE 0x1A -#define QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID_TYPE 0x1B - -typedef struct _QOS_FLOW_TLV_IP_FLOW_IDX -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 1 - UCHAR IpFlowIndex; -} QOS_FLOW_TLV_IP_FLOW_IDX, *PQOS_FLOW_TLV_IP_FLOW_IDX; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS -{ - UCHAR TLVType; // 0x11 - USHORT TLVLength; // 1 - UCHAR TrafficClass; -} QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS, *PQOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 8 - ULONG DataRateMax; - ULONG GuaranteedRate; -} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET -{ - UCHAR TLVType; // 0x13 - USHORT TLVLength; // 12 - ULONG PeakRate; - ULONG TokenRate; - ULONG BucketSize; -} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_LATENCY -{ - UCHAR TLVType; // 0x14 - USHORT TLVLength; // 4 - ULONG IpFlowLatency; -} QOS_FLOW_TLV_IP_FLOW_LATENCY, *PQOS_FLOW_TLV_IP_FLOW_LATENCY; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_JITTER -{ - UCHAR TLVType; // 0x15 - USHORT TLVLength; // 4 - ULONG IpFlowJitter; -} QOS_FLOW_TLV_IP_FLOW_JITTER, *PQOS_FLOW_TLV_IP_FLOW_JITTER; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE -{ - UCHAR TLVType; // 0x16 - USHORT TLVLength; // 4 - USHORT ErrRateMultiplier; - USHORT ErrRateExponent; -} QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE -{ - UCHAR TLVType; // 0x17 - USHORT TLVLength; // 4 - ULONG MinPolicedPktSize; -} QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE -{ - UCHAR TLVType; // 0x18 - USHORT TLVLength; // 4 - ULONG MaxAllowedPktSize; -} QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE -{ - UCHAR TLVType; // 0x19 - USHORT TLVLength; // 1 - UCHAR ResidualBitErrorRate; -} QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY -{ - UCHAR TLVType; // 0x1A - USHORT TLVLength; // 1 - UCHAR TrafficHandlingPriority; -} QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY, *PQOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID -{ - UCHAR TLVType; // 0x1B - USHORT TLVLength; // 2 - USHORT ProfileId; -} QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID, *PQOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID; - -// QOS Filter - -#define QOS_FILTER_TLV_IP_FILTER_IDX_TYPE 0x10 -#define QOS_FILTER_TLV_IP_VERSION_TYPE 0x11 -#define QOS_FILTER_TLV_IPV4_SRC_ADDR_TYPE 0x12 -#define QOS_FILTER_TLV_IPV4_DEST_ADDR_TYPE 0x13 -#define QOS_FILTER_TLV_NEXT_HDR_PROTOCOL_TYPE 0x14 -#define QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE_TYPE 0x15 -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TCP_TYPE 0x1B -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TCP_TYPE 0x1C -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_UDP_TYPE 0x1D -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_UDP_TYPE 0x1E -#define QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE_TYPE 0x1F -#define QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE_TYPE 0x20 -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TYPE 0x24 -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TYPE 0x25 - -typedef struct _QOS_EVENT_RPT_IND_TLV_FILTER -{ - UCHAR TLVType; // 0x12-TX filter; 0x13-RX filter - USHORT TLVLength; // var - // embedded TLV's -} QOS_EVENT_RPT_IND_TLV_RX_FILTER, *PQOS_EVENT_RPT_IND_TLV_RX_FILTER; - -typedef struct _QOS_FILTER_TLV_IP_FILTER_IDX -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 1 - UCHAR IpFilterIndex; -} QOS_FILTER_TLV_IP_FILTER_IDX, *PQOS_FILTER_TLV_IP_FILTER_IDX; - -typedef struct _QOS_FILTER_TLV_IP_VERSION -{ - UCHAR TLVType; // 0x11 - USHORT TLVLength; // 1 - UCHAR IpVersion; -} QOS_FILTER_TLV_IP_VERSION, *PQOS_FILTER_TLV_IP_VERSION; - -typedef struct _QOS_FILTER_TLV_IPV4_SRC_ADDR -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 8 - ULONG IpSrcAddr; - ULONG IpSrcSubnetMask; -} QOS_FILTER_TLV_IPV4_SRC_ADDR, *PQOS_FILTER_TLV_IPV4_SRC_ADDR; - -typedef struct _QOS_FILTER_TLV_IPV4_DEST_ADDR -{ - UCHAR TLVType; // 0x13 - USHORT TLVLength; // 8 - ULONG IpDestAddr; - ULONG IpDestSubnetMask; -} QOS_FILTER_TLV_IPV4_DEST_ADDR, *PQOS_FILTER_TLV_IPV4_DEST_ADDR; - -typedef struct _QOS_FILTER_TLV_NEXT_HDR_PROTOCOL -{ - UCHAR TLVType; // 0x14 - USHORT TLVLength; // 1 - UCHAR NextHdrProtocol; -} QOS_FILTER_TLV_NEXT_HDR_PROTOCOL, *PQOS_FILTER_TLV_NEXT_HDR_PROTOCOL; - -typedef struct _QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE -{ - UCHAR TLVType; // 0x15 - USHORT TLVLength; // 2 - UCHAR Ipv4TypeOfService; - UCHAR Ipv4TypeOfServiceMask; -} QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE, *PQOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE; - -typedef struct _QOS_FILTER_TLV_TCP_UDP_PORT -{ - UCHAR TLVType; // source port: 0x1B-TCP; 0x1D-UDP - // dest port: 0x1C-TCP; 0x1E-UDP - USHORT TLVLength; // 4 - USHORT FilterPort; - USHORT FilterPortRange; -} QOS_FILTER_TLV_TCP_UDP_PORT, *PQOS_FILTER_TLV_TCP_UDP_PORT; - -typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE -{ - UCHAR TLVType; // 0x1F - USHORT TLVLength; // 1 - UCHAR IcmpFilterMsgType; -} QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE; - -typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE -{ - UCHAR TLVType; // 0x20 - USHORT TLVLength; // 1 - UCHAR IcmpFilterMsgCode; -} QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_CODE; - -#define QOS_FILTER_PRECEDENCE_INVALID 256 -#define QOS_FILTER_TLV_PRECEDENCE_TYPE 0x22 -#define QOS_FILTER_TLV_ID_TYPE 0x23 - -typedef struct _QOS_FILTER_TLV_PRECEDENCE -{ - UCHAR TLVType; // 0x22 - USHORT TLVLength; // 2 - USHORT Precedence; // precedence of the filter -} QOS_FILTER_TLV_PRECEDENCE, *PQOS_FILTER_TLV_PRECEDENCE; - -typedef struct _QOS_FILTER_TLV_ID -{ - UCHAR TLVType; // 0x23 - USHORT TLVLength; // 2 - USHORT FilterId; // filter ID -} QOS_FILTER_TLV_ID, *PQOS_FILTER_TLV_ID; - -#ifdef QCQOS_IPV6 - -#define QOS_FILTER_TLV_IPV6_SRC_ADDR_TYPE 0x16 -#define QOS_FILTER_TLV_IPV6_DEST_ADDR_TYPE 0x17 -#define QOS_FILTER_TLV_IPV6_NEXT_HDR_PROTOCOL_TYPE 0x14 // same as IPV4 -#define QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS_TYPE 0x19 -#define QOS_FILTER_TLV_IPV6_FLOW_LABEL_TYPE 0x1A - -typedef struct _QOS_FILTER_TLV_IPV6_SRC_ADDR -{ - UCHAR TLVType; // 0x16 - USHORT TLVLength; // 17 - UCHAR IpSrcAddr[16]; - UCHAR IpSrcAddrPrefixLen; // [0..128] -} QOS_FILTER_TLV_IPV6_SRC_ADDR, *PQOS_FILTER_TLV_IPV6_SRC_ADDR; - -typedef struct _QOS_FILTER_TLV_IPV6_DEST_ADDR -{ - UCHAR TLVType; // 0x17 - USHORT TLVLength; // 17 - UCHAR IpDestAddr[16]; - UCHAR IpDestAddrPrefixLen; // [0..128] -} QOS_FILTER_TLV_IPV6_DEST_ADDR, *PQOS_FILTER_TLV_IPV6_DEST_ADDR; - -#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_TCP 0x06 -#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_UDP 0x11 - -typedef struct _QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS -{ - UCHAR TLVType; // 0x19 - USHORT TLVLength; // 2 - UCHAR TrafficClass; - UCHAR TrafficClassMask; // compare the first 6 bits only -} QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS, *PQOS_FILTER_TLV_IPV6_TRAFFIC_CLASS; - -typedef struct _QOS_FILTER_TLV_IPV6_FLOW_LABEL -{ - UCHAR TLVType; // 0x1A - USHORT TLVLength; // 4 - ULONG FlowLabel; -} QOS_FILTER_TLV_IPV6_FLOW_LABEL, *PQOS_FILTER_TLV_IPV6_FLOW_LABEL; - -#endif // QCQOS_IPV6 -#endif - -// ======================= WMS ============================== -#define QMIWMS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIWMS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIWMS_EVENT_REPORT_IND 0x0001 -#define QMIWMS_RAW_SEND_REQ 0x0020 -#define QMIWMS_RAW_SEND_RESP 0x0020 -#define QMIWMS_RAW_WRITE_REQ 0x0021 -#define QMIWMS_RAW_WRITE_RESP 0x0021 -#define QMIWMS_RAW_READ_REQ 0x0022 -#define QMIWMS_RAW_READ_RESP 0x0022 -#define QMIWMS_MODIFY_TAG_REQ 0x0023 -#define QMIWMS_MODIFY_TAG_RESP 0x0023 -#define QMIWMS_DELETE_REQ 0x0024 -#define QMIWMS_DELETE_RESP 0x0024 -#define QMIWMS_GET_MESSAGE_PROTOCOL_REQ 0x0030 -#define QMIWMS_GET_MESSAGE_PROTOCOL_RESP 0x0030 -#define QMIWMS_LIST_MESSAGES_REQ 0x0031 -#define QMIWMS_LIST_MESSAGES_RESP 0x0031 -#define QMIWMS_GET_SMSC_ADDRESS_REQ 0x0034 -#define QMIWMS_GET_SMSC_ADDRESS_RESP 0x0034 -#define QMIWMS_SET_SMSC_ADDRESS_REQ 0x0035 -#define QMIWMS_SET_SMSC_ADDRESS_RESP 0x0035 -#define QMIWMS_GET_STORE_MAX_SIZE_REQ 0x0036 -#define QMIWMS_GET_STORE_MAX_SIZE_RESP 0x0036 - -#define WMS_MESSAGE_PROTOCOL_CDMA 0x00 -#define WMS_MESSAGE_PROTOCOL_WCDMA 0x01 - -#if 0 -typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG; - -typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR MessageProtocol; -} QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG; - -typedef struct _QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_REQ_MSG; - -typedef struct _QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - ULONG MemStoreMaxSize; -} QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_RESP_MSG; - -typedef struct _REQUEST_TAG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TagType; -} REQUEST_TAG, *PREQUEST_TAG; - -typedef struct _QMIWMS_LIST_MESSAGES_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_LIST_MESSAGES_REQ_MSG, *PQMIWMS_LIST_MESSAGES_REQ_MSG; - -typedef struct _QMIWMS_MESSAGE -{ - ULONG MessageIndex; - UCHAR TagType; -} QMIWMS_MESSAGE, *PQMIWMS_MESSAGE; - -typedef struct _QMIWMS_LIST_MESSAGES_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - ULONG NumMessages; -} QMIWMS_LIST_MESSAGES_RESP_MSG, *PQMIWMS_LIST_MESSAGES_RESP_MSG; - -typedef struct _QMIWMS_RAW_READ_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG MemoryIndex; -} QMIWMS_RAW_READ_REQ_MSG, *PQMIWMS_RAW_READ_REQ_MSG; - -typedef struct _QMIWMS_RAW_READ_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR TagType; - UCHAR Format; - USHORT MessageLength; - UCHAR Message; -} QMIWMS_RAW_READ_RESP_MSG, *PQMIWMS_RAW_READ_RESP_MSG; - -typedef struct _QMIWMS_MODIFY_TAG_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG MemoryIndex; - UCHAR TagType; -} QMIWMS_MODIFY_TAG_REQ_MSG, *PQMIWMS_MODIFY_TAG_REQ_MSG; - -typedef struct _QMIWMS_MODIFY_TAG_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_MODIFY_TAG_RESP_MSG, *PQMIWMS_MODIFY_TAG_RESP_MSG; - -typedef struct _QMIWMS_RAW_SEND_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR SmsFormat; - USHORT SmsLength; - UCHAR SmsMessage; -} QMIWMS_RAW_SEND_REQ_MSG, *PQMIWMS_RAW_SEND_REQ_MSG; - -typedef struct _RAW_SEND_CAUSE_CODE -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CauseCode; -} RAW_SEND_CAUSE_CODE, *PRAW_SEND_CAUSE_CODE; - - -typedef struct _QMIWMS_RAW_SEND_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_RAW_SEND_RESP_MSG, *PQMIWMS_RAW_SEND_RESP_MSG; - - -typedef struct _WMS_DELETE_MESSAGE_INDEX -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG MemoryIndex; -} WMS_DELETE_MESSAGE_INDEX, *PWMS_DELETE_MESSAGE_INDEX; - -typedef struct _WMS_DELETE_MESSAGE_TAG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR MessageTag; -} WMS_DELETE_MESSAGE_TAG, *PWMS_DELETE_MESSAGE_TAG; - -typedef struct _QMIWMS_DELETE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_DELETE_REQ_MSG, *PQMIWMS_DELETE_REQ_MSG; - -typedef struct _QMIWMS_DELETE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_DELETE_RESP_MSG, *PQMIWMS_DELETE_RESP_MSG; - - -typedef struct _QMIWMS_GET_SMSC_ADDRESS_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMIWMS_GET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_GET_SMSC_ADDRESS_REQ_MSG; - -typedef struct _QMIWMS_SMSC_ADDRESS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SMSCAddressType[3]; - UCHAR SMSCAddressLength; - UCHAR SMSCAddressDigits; -} QMIWMS_SMSC_ADDRESS, *PQMIWMS_SMSC_ADDRESS; - - -typedef struct _QMIWMS_GET_SMSC_ADDRESS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR SMSCAddress; -} QMIWMS_GET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_GET_SMSC_ADDRESS_RESP_MSG; - -typedef struct _QMIWMS_SET_SMSC_ADDRESS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR SMSCAddress; -} QMIWMS_SET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_SET_SMSC_ADDRESS_REQ_MSG; - -typedef struct _QMIWMS_SET_SMSC_ADDRESS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_SET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_SET_SMSC_ADDRESS_RESP_MSG; - -typedef struct _QMIWMS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportNewMessage; -} QMIWMS_SET_EVENT_REPORT_REQ_MSG, *PQMIWMS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIWMS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_SET_EVENT_REPORT_RESP_MSG, *PQMIWMS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMIWMS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG StorageIndex; -} QMIWMS_EVENT_REPORT_IND_MSG, *PQMIWMS_EVENT_REPORT_IND_MSG; -#endif - -// ======================= End of WMS ============================== - -// ======================= NAS ============================== -#define QMINAS_SET_EVENT_REPORT_REQ 0x0002 -#define QMINAS_SET_EVENT_REPORT_RESP 0x0002 -#define QMINAS_EVENT_REPORT_IND 0x0002 -#define QMINAS_GET_SIGNAL_STRENGTH_REQ 0x0020 -#define QMINAS_GET_SIGNAL_STRENGTH_RESP 0x0020 -#define QMINAS_PERFORM_NETWORK_SCAN_REQ 0x0021 -#define QMINAS_PERFORM_NETWORK_SCAN_RESP 0x0021 -#define QMINAS_INITIATE_NW_REGISTER_REQ 0x0022 -#define QMINAS_INITIATE_NW_REGISTER_RESP 0x0022 -#define QMINAS_INITIATE_ATTACH_REQ 0x0023 -#define QMINAS_INITIATE_ATTACH_RESP 0x0023 -#define QMINAS_GET_SERVING_SYSTEM_REQ 0x0024 -#define QMINAS_GET_SERVING_SYSTEM_RESP 0x0024 -#define QMINAS_SERVING_SYSTEM_IND 0x0024 -#define QMINAS_GET_HOME_NETWORK_REQ 0x0025 -#define QMINAS_GET_HOME_NETWORK_RESP 0x0025 -#define QMINAS_GET_PREFERRED_NETWORK_REQ 0x0026 -#define QMINAS_GET_PREFERRED_NETWORK_RESP 0x0026 -#define QMINAS_SET_PREFERRED_NETWORK_REQ 0x0027 -#define QMINAS_SET_PREFERRED_NETWORK_RESP 0x0027 -#define QMINAS_GET_FORBIDDEN_NETWORK_REQ 0x0028 -#define QMINAS_GET_FORBIDDEN_NETWORK_RESP 0x0028 -#define QMINAS_SET_FORBIDDEN_NETWORK_REQ 0x0029 -#define QMINAS_SET_FORBIDDEN_NETWORK_RESP 0x0029 -#define QMINAS_SET_TECHNOLOGY_PREF_REQ 0x002A -#define QMINAS_SET_TECHNOLOGY_PREF_RESP 0x002A -#define QMINAS_GET_RF_BAND_INFO_REQ 0x0031 -#define QMINAS_GET_RF_BAND_INFO_RESP 0x0031 -#define QMINAS_GET_PLMN_NAME_REQ 0x0044 -#define QMINAS_GET_PLMN_NAME_RESP 0x0044 -#define FIBO_PACKET_TRANSFER_START_IND 0X100 -#define FIBO_PACKET_TRANSFER_END_IND 0X101 -#define QMINAS_GET_SYS_INFO_REQ 0x004D -#define QMINAS_GET_SYS_INFO_RESP 0x004D -#define QMINAS_SYS_INFO_IND 0x004D - -typedef struct _QMINAS_GET_HOME_NETWORK_REQ_MSG { - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} __attribute__((packed)) QMINAS_GET_HOME_NETWORK_REQ_MSG, - *PQMINAS_GET_HOME_NETWORK_REQ_MSG; - -typedef struct _HOME_NETWORK_SYSTEMID { - UCHAR TLVType; - USHORT TLVLength; - USHORT SystemID; - USHORT NetworkID; -} __attribute__((packed)) HOME_NETWORK_SYSTEMID, *PHOME_NETWORK_SYSTEMID; - -typedef struct _HOME_NETWORK { - UCHAR TLVType; - USHORT TLVLength; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} __attribute__((packed)) HOME_NETWORK, *PHOME_NETWORK; - -#if 0 -typedef struct _HOME_NETWORK_EXT -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDescDisp; - UCHAR NetworkDescEncoding; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} HOME_NETWORK_EXT, *PHOME_NETWORK_EXT; - -typedef struct _QMINAS_GET_HOME_NETWORK_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMINAS_GET_HOME_NETWORK_RESP_MSG, *PQMINAS_GET_HOME_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_PREFERRED_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_GET_PREFERRED_NETWORK_REQ_MSG; - - -typedef struct _PREFERRED_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - USHORT RadioAccess; -} PREFERRED_NETWORK, *PPREFERRED_NETWORK; - -typedef struct _QMINAS_GET_PREFERRED_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - USHORT NumPreferredNetwork; -} QMINAS_GET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_GET_PREFERRED_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG; - -typedef struct _FORBIDDEN_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; -} FORBIDDEN_NETWORK, *PFORBIDDEN_NETWORK; - -typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - USHORT NumForbiddenNetwork; -} QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_SERVING_SYSTEM_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_SERVING_SYSTEM_REQ_MSG, *PQMINAS_GET_SERVING_SYSTEM_REQ_MSG; - -typedef struct _QMINAS_ROAMING_INDICATOR_MSG -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - UCHAR RoamingIndicator; -} QMINAS_ROAMING_INDICATOR_MSG, *PQMINAS_ROAMING_INDICATOR_MSG; -#endif - -typedef struct _QMINAS_DATA_CAP { - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - UCHAR DataCapListLen; - UCHAR DataCap; -} __attribute__((packed)) QMINAS_DATA_CAP, *PQMINAS_DATA_CAP; - -typedef struct _QMINAS_CURRENT_PLMN_MSG { - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} __attribute__((packed)) QMINAS_CURRENT_PLMN_MSG, *PQMINAS_CURRENT_PLMN_MSG; - -typedef struct _QMINAS_GET_SERVING_SYSTEM_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMINAS_GET_SERVING_SYSTEM_RESP_MSG, - *PQMINAS_GET_SERVING_SYSTEM_RESP_MSG; - -typedef struct _SERVING_SYSTEM { - UCHAR TLVType; - USHORT TLVLength; - UCHAR RegistrationState; - UCHAR CSAttachedState; - UCHAR PSAttachedState; - UCHAR RegistredNetwork; - UCHAR InUseRadioIF; - UCHAR RadioIF; -} __attribute__((packed)) SERVING_SYSTEM, *PSERVING_SYSTEM; - -typedef struct _QMINAS_GET_SYS_INFO_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMINAS_GET_SYS_INFO_RESP_MSG, - *PQMINAS_GET_SYS_INFO_RESP_MSG; - -typedef struct _QMINAS_SYS_INFO_IND_MSG { - USHORT Type; - USHORT Length; -} __attribute__((packed)) QMINAS_SYS_INFO_IND_MSG, *PQMINAS_SYS_INFO_IND_MSG; - -typedef struct _SERVICE_STATUS_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvStatus; - UCHAR true_srv_status; - UCHAR IsPrefDataPath; -} __attribute__((packed)) SERVICE_STATUS_INFO, *PSERVICE_STATUS_INFO; - -typedef struct _CDMA_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR IsSysPrlMatchValid; - UCHAR IsSysPrlMatch; - UCHAR PRevInUseValid; - UCHAR PRevInUse; - UCHAR BSPRevValid; - UCHAR BSPRev; - UCHAR CCSSupportedValid; - UCHAR CCSSupported; - UCHAR CDMASysIdValid; - USHORT SID; - USHORT NID; - UCHAR BSInfoValid; - USHORT BaseID; - ULONG BaseLAT; - ULONG BaseLONG; - UCHAR PacketZoneValid; - USHORT PacketZone; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; -} __attribute__((packed)) CDMA_SYSTEM_INFO, *PCDMA_SYSTEM_INFO; - -typedef struct _HDR_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR IsSysPrlMatchValid; - UCHAR IsSysPrlMatch; - UCHAR HdrPersonalityValid; - UCHAR HdrPersonality; - UCHAR HdrActiveProtValid; - UCHAR HdrActiveProt; - UCHAR is856SysIdValid; - UCHAR is856SysId[16]; -} __attribute__((packed)) HDR_SYSTEM_INFO, *PHDR_SYSTEM_INFO; - -typedef struct _GSM_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR EgprsSuppValid; - UCHAR EgprsSupp; - UCHAR DtmSuppValid; - UCHAR DtmSupp; -} __attribute__((packed)) GSM_SYSTEM_INFO, *PGSM_SYSTEM_INFO; - -typedef struct _WCDMA_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR HsCallStatusValid; - UCHAR HsCallStatus; - UCHAR HsIndValid; - UCHAR HsInd; - UCHAR PscValid; - UCHAR Psc; -} __attribute__((packed)) WCDMA_SYSTEM_INFO, *PWCDMA_SYSTEM_INFO; - -typedef struct _LTE_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR TacValid; - USHORT Tac; -} __attribute__((packed)) LTE_SYSTEM_INFO, *PLTE_SYSTEM_INFO; -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 -typedef struct _NR5G_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR TacValid; - USHORT Tac; -} __attribute__((packed)) NR5G_SYSTEM_INFO, *PNR5G_SYSTEM_INFO; - -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 -typedef struct _TDSCDMA_SYSTEM_INFO { - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR HsCallStatusValid; - UCHAR HsCallStatus; - UCHAR HsIndValid; - UCHAR HsInd; - UCHAR CellParameterIdValid; - USHORT CellParameterId; - UCHAR CellBroadcastCapValid; - ULONG CellBroadcastCap; - UCHAR CsBarStatusValid; - ULONG CsBarStatus; - UCHAR PsBarStatusValid; - ULONG PsBarStatus; - UCHAR CipherDomainValid; - UCHAR CipherDomain; -} __attribute__((packed)) TDSCDMA_SYSTEM_INFO, *PTDSCDMA_SYSTEM_INFO; - -#if 0 -typedef struct _QMINAS_SERVING_SYSTEM_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_SERVING_SYSTEM_IND_MSG, *PQMINAS_SERVING_SYSTEM_IND_MSG; - -typedef struct _QMINAS_SET_PREFERRED_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT NumPreferredNetwork; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - USHORT RadioAccess; -} QMINAS_SET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_SET_PREFERRED_NETWORK_REQ_MSG; - -typedef struct _QMINAS_SET_PREFERRED_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_SET_PREFERRED_NETWORK_RESP_MSG; - -typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT NumForbiddenNetwork; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; -} QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG; - -typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_REQ_MSG; - -typedef struct _VISIBLE_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkStatus; - UCHAR NetworkDesclen; -} VISIBLE_NETWORK, *PVISIBLE_NETWORK; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_RESP_MSG; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO -{ - UCHAR TLVType; // 0x010 - required parameter - USHORT TLVLength; // length - USHORT NumNetworkInstances; -} QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO -{ - UCHAR TLVType; // 0x011 - required parameter - USHORT TLVLength; // length - USHORT NumInst; -} QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_RAT_INFO; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT -{ - USHORT MCC; - USHORT MNC; - UCHAR RAT; -} QMINAS_PERFORM_NETWORK_SCAN_RAT, *PQMINAS_PERFORM_NETWORK_SCAN_RAT; - - -typedef struct _QMINAS_MANUAL_NW_REGISTER -{ - UCHAR TLV2Type; // 0x02 - result code - USHORT TLV2Length; // 4 - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR RadioAccess; -} QMINAS_MANUAL_NW_REGISTER, *PQMINAS_MANUAL_NW_REGISTER; - -typedef struct _QMINAS_INITIATE_NW_REGISTER_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR RegisterAction; -} QMINAS_INITIATE_NW_REGISTER_REQ_MSG, *PQMINAS_INITIATE_NW_REGISTER_REQ_MSG; - -typedef struct _QMINAS_INITIATE_NW_REGISTER_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_INITIATE_NW_REGISTER_RESP_MSG, *PQMINAS_INITIATE_NW_REGISTER_RESP_MSG; - -typedef struct _QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT TechPref; - UCHAR Duration; -} QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_REQ_MSG; - -typedef struct _QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_RESP_MSG; - -typedef struct _QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_REQ_MSG; - -typedef struct _QMINAS_SIGNAL_STRENGTH -{ - CHAR SigStrength; - UCHAR RadioIf; -} QMINAS_SIGNAL_STRENGTH, *PQMINAS_SIGNAL_STRENGTH; - -typedef struct _QMINAS_SIGNAL_STRENGTH_LIST -{ - UCHAR TLV3Type; - USHORT TLV3Length; - USHORT NumInstance; -} QMINAS_SIGNAL_STRENGTH_LIST, *PQMINAS_SIGNAL_STRENGTH_LIST; - - -typedef struct _QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - CHAR SignalStrength; - UCHAR RadioIf; -} QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_RESP_MSG; - - -typedef struct _QMINAS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportSigStrength; - UCHAR NumTresholds; - CHAR TresholdList[2]; -} QMINAS_SET_EVENT_REPORT_REQ_MSG, *PQMINAS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMINAS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_EVENT_REPORT_RESP_MSG, *PQMINAS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMINAS_SIGNAL_STRENGTH_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - CHAR SigStrength; - UCHAR RadioIf; -} QMINAS_SIGNAL_STRENGTH_TLV, *PQMINAS_SIGNAL_STRENGTH_TLV; - -typedef struct _QMINAS_REJECT_CAUSE_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ServiceDomain; - USHORT RejectCause; -} QMINAS_REJECT_CAUSE_TLV, *PQMINAS_REJECT_CAUSE_TLV; - -typedef struct _QMINAS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_EVENT_REPORT_IND_MSG, *PQMINAS_EVENT_REPORT_IND_MSG; - -typedef struct _QMINAS_GET_RF_BAND_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_GET_RF_BAND_INFO_REQ_MSG, *PQMINAS_GET_RF_BAND_INFO_REQ_MSG; - -typedef struct _QMINASRF_BAND_INFO -{ - UCHAR RadioIf; - USHORT ActiveBand; - USHORT ActiveChannel; -} QMINASRF_BAND_INFO, *PQMINASRF_BAND_INFO; - -typedef struct _QMINAS_GET_RF_BAND_INFO_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR NumInstances; -} QMINAS_GET_RF_BAND_INFO_RESP_MSG, *PQMINAS_GET_RF_BAND_INFO_RESP_MSG; - - -typedef struct _QMINAS_GET_PLMN_NAME_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT MCC; - USHORT MNC; -} QMINAS_GET_PLMN_NAME_REQ_MSG, *PQMINAS_GET_PLMN_NAME_REQ_MSG; - -typedef struct _QMINAS_GET_PLMN_NAME_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_GET_PLMN_NAME_RESP_MSG, *PQMINAS_GET_PLMN_NAME_RESP_MSG; - -typedef struct _QMINAS_GET_PLMN_NAME_SPN -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SPN_Enc; - UCHAR SPN_Len; -} QMINAS_GET_PLMN_NAME_SPN, *PQMINAS_GET_PLMN_NAME_SPN; - -typedef struct _QMINAS_GET_PLMN_NAME_PLMN -{ - UCHAR PLMN_Enc; - UCHAR PLMN_Ci; - UCHAR PLMN_SpareBits; - UCHAR PLMN_Len; -} QMINAS_GET_PLMN_NAME_PLMN, *PQMINAS_GET_PLMN_NAME_PLMN; - -typedef struct _QMINAS_INITIATE_ATTACH_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR PsAttachAction; -} QMINAS_INITIATE_ATTACH_REQ_MSG, *PQMINAS_INITIATE_ATTACH_REQ_MSG; - -typedef struct _QMINAS_INITIATE_ATTACH_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_INITIATE_ATTACH_RESP_MSG, *PQMINAS_INITIATE_ATTACH_RESP_MSG; -#endif -// ======================= End of NAS ============================== - -// ======================= UIM ============================== -#define QMIUIM_READ_TRANSPARENT_REQ 0x0020 -#define QMIUIM_READ_TRANSPARENT_RESP 0x0020 -#define QMIUIM_READ_TRANSPARENT_IND 0x0020 -#define QMIUIM_READ_RECORD_REQ 0x0021 -#define QMIUIM_READ_RECORD_RESP 0x0021 -#define QMIUIM_READ_RECORD_IND 0x0021 -#define QMIUIM_WRITE_TRANSPARENT_REQ 0x0022 -#define QMIUIM_WRITE_TRANSPARENT_RESP 0x0022 -#define QMIUIM_WRITE_TRANSPARENT_IND 0x0022 -#define QMIUIM_WRITE_RECORD_REQ 0x0023 -#define QMIUIM_WRITE_RECORD_RESP 0x0023 -#define QMIUIM_WRITE_RECORD_IND 0x0023 -#define QMIUIM_SET_PIN_PROTECTION_REQ 0x0025 -#define QMIUIM_SET_PIN_PROTECTION_RESP 0x0025 -#define QMIUIM_SET_PIN_PROTECTION_IND 0x0025 -#define QMIUIM_VERIFY_PIN_REQ 0x0026 -#define QMIUIM_VERIFY_PIN_RESP 0x0026 -#define QMIUIM_VERIFY_PIN_IND 0x0026 -#define QMIUIM_UNBLOCK_PIN_REQ 0x0027 -#define QMIUIM_UNBLOCK_PIN_RESP 0x0027 -#define QMIUIM_UNBLOCK_PIN_IND 0x0027 -#define QMIUIM_CHANGE_PIN_REQ 0x0028 -#define QMIUIM_CHANGE_PIN_RESP 0x0028 -#define QMIUIM_CHANGE_PIN_IND 0x0028 -#define QMIUIM_DEPERSONALIZATION_REQ 0x0029 -#define QMIUIM_DEPERSONALIZATION_RESP 0x0029 -#define QMIUIM_EVENT_REG_REQ 0x002E -#define QMIUIM_EVENT_REG_RESP 0x002E -#define QMIUIM_GET_CARD_STATUS_REQ 0x002F -#define QMIUIM_GET_CARD_STATUS_RESP 0x002F -#define QMIUIM_STATUS_CHANGE_IND 0x0032 - -typedef struct _QMIUIM_GET_CARD_STATUS_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMIUIM_GET_CARD_STATUS_RESP_MSG, - *PQMIUIM_GET_CARD_STATUS_RESP_MSG; - -typedef struct _QMIUIM_PIN_STATE { - UCHAR UnivPIN; - UCHAR PIN1State; - UCHAR PIN1Retries; - UCHAR PUK1Retries; - UCHAR PIN2State; - UCHAR PIN2Retries; - UCHAR PUK2Retries; -} __attribute__((packed)) QMIUIM_PIN_STATE, *PQMIUIM_PIN_STATE; - -typedef struct _QMIUIM_APP_STATUS { - UCHAR AppType; - UCHAR AppState; - UCHAR PersoState; - UCHAR PersoFeature; - UCHAR PersoRetries; - UCHAR PersoUnblockRetries; - UCHAR AIDLength; - UCHAR AIDValue[16]; - QMIUIM_PIN_STATE PinState; -} __attribute__((packed)) QMIUIM_APP_STATUS, *PQMIUIM_APP_STATUS; - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -typedef struct _instance{ - UCHAR CardState; - UCHAR UPINState; - UCHAR UPINRetries; - UCHAR UPUKRetries; - UCHAR ErrorCode; - UCHAR NumApp; -}Instance; - -typedef struct _QMIUIM_CARD_STATUS { - UCHAR TLVType; - USHORT TLVLength; - USHORT IndexGWPri; - USHORT Index1XPri; - USHORT IndexGWSec; - USHORT Index1XSec; - UCHAR NumSlot; -/* - UCHAR CardState; - UCHAR UPINState; - UCHAR UPINRetries; - UCHAR UPUKRetries; - UCHAR ErrorCode; - UCHAR NumApp; - QMIUIM_APP_STATUS AppStatus[8]; -*/ -}__attribute__((packed)) QMIUIM_CARD_STATUS, *PQMIUIM_CARD_STATUS; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - -typedef struct _QMIUIM_VERIFY_PIN_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Session_Type; - UCHAR Aid_Len; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINID; - UCHAR PINLen; - UCHAR PINValue; -} __attribute__((packed)) QMIUIM_VERIFY_PIN_REQ_MSG, - *PQMIUIM_VERIFY_PIN_REQ_MSG; - -typedef struct _QMIUIM_VERIFY_PIN_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__((packed)) QMIUIM_VERIFY_PIN_RESP_MSG, - *PQMIUIM_VERIFY_PIN_RESP_MSG; - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -typedef struct _QMIUIM_BIND_PIN_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - uint8_t Value; -} __attribute__((packed)) QMIUIM_BIND_PIN_REQ_MSG, *PQMIUIM_BIND_PIN_REQ_MSG; - -typedef struct _QMIUIM_BIND_PIN_REQ_MSG_4 { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UINT Value; -} __attribute__((packed)) QMIUIM_BIND_PIN_REQ_MSG_4; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - -typedef struct _QMIUIM_READ_TRANSPARENT_REQ_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Session_Type; - UCHAR Aid_Len; - UCHAR TLV2Type; - USHORT TLV2Length; - USHORT file_id; - UCHAR path_len; - UCHAR path[]; -} __attribute__((packed)) QMIUIM_READ_TRANSPARENT_REQ_MSG, - *PQMIUIM_READ_TRANSPARENT_REQ_MSG; - -typedef struct _READ_TRANSPARENT_TLV { - UCHAR TLVType; - USHORT TLVLength; - USHORT Offset; - USHORT Length; -} __attribute__((packed)) READ_TRANSPARENT_TLV, *PREAD_TRANSPARENT_TLV; - -typedef struct _QMIUIM_CONTENT { - UCHAR TLVType; - USHORT TLVLength; - USHORT content_len; - UCHAR content[]; -} __attribute__((packed)) QMIUIM_CONTENT, *PQMIUIM_CONTENT; - -typedef struct _QMIUIM_READ_TRANSPARENT_RESP_MSG { - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__((packed)) QMIUIM_READ_TRANSPARENT_RESP_MSG, - *PQMIUIM_READ_TRANSPARENT_RESP_MSG; - -typedef struct _QMUX_MSG { - QCQMUX_HDR QMUXHdr; - union { - // Message Header - QCQMUX_MSG_HDR QMUXMsgHdr; - QCQMUX_MSG_HDR_RESP QMUXMsgHdrResp; - - // QMIWDS Message -#if 0 - QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG PacketServiceStatusReq; - QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG PacketServiceStatusRsp; - QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG PacketServiceStatusInd; - QMIWDS_EVENT_REPORT_IND_MSG EventReportInd; - QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG GetCurrChannelRateReq; - QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG GetCurrChannelRateRsp; - QMIWDS_GET_PKT_STATISTICS_REQ_MSG GetPktStatsReq; - QMIWDS_GET_PKT_STATISTICS_RESP_MSG GetPktStatsRsp; - QMIWDS_SET_EVENT_REPORT_REQ_MSG EventReportReq; - QMIWDS_SET_EVENT_REPORT_RESP_MSG EventReportRsp; -#endif - //#ifdef QC_IP_MODE - QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG GetRuntimeSettingsReq; - QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG GetRuntimeSettingsRsp; - //#endif // QC_IP_MODE - QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG SetClientIpFamilyPrefReq; - QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG SetClientIpFamilyPrefResp; - QMIWDS_SET_AUTO_CONNECT_REQ_MSG SetAutoConnectReq; -#if 0 - QMIWDS_GET_MIP_MODE_REQ_MSG GetMipModeReq; - QMIWDS_GET_MIP_MODE_RESP_MSG GetMipModeResp; -#endif - QMIWDS_START_NETWORK_INTERFACE_REQ_MSG StartNwInterfaceReq; - QMIWDS_START_NETWORK_INTERFACE_RESP_MSG StartNwInterfaceResp; - QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG StopNwInterfaceReq; - QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG StopNwInterfaceResp; - QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG GetDefaultSettingsReq; - QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG GetDefaultSettingsResp; -//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 - QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG CreateProfileSettingsReq; - QMIWDS_CREATE_PROFILE_SETTINGS_RESP_MSG CreateProfileSettingsResp; -//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 - QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG ModifyProfileSettingsReq; - QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG ModifyProfileSettingsResp; - QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG GetProfileSettingsReq; -#if 0 - QMIWDS_GET_DATA_BEARER_REQ_MSG GetDataBearerReq; - QMIWDS_GET_DATA_BEARER_RESP_MSG GetDataBearerResp; - QMIWDS_DUN_CALL_INFO_REQ_MSG DunCallInfoReq; - QMIWDS_DUN_CALL_INFO_RESP_MSG DunCallInfoResp; -#endif - QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG BindMuxDataPortReq; - - // QMIDMS Messages -#if 0 - QMIDMS_GET_DEVICE_MFR_REQ_MSG GetDeviceMfrReq; - QMIDMS_GET_DEVICE_MFR_RESP_MSG GetDeviceMfrRsp; - QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG GetDeviceModeIdReq; - QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG GetDeviceModeIdRsp; - QMIDMS_GET_DEVICE_REV_ID_REQ_MSG GetDeviceRevIdReq; - QMIDMS_GET_DEVICE_REV_ID_RESP_MSG GetDeviceRevIdRsp; - QMIDMS_GET_MSISDN_REQ_MSG GetMsisdnReq; - QMIDMS_GET_MSISDN_RESP_MSG GetMsisdnRsp; - QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG GetDeviceSerialNumReq; - QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG GetDeviceSerialNumRsp; - QMIDMS_GET_DEVICE_CAP_REQ_MSG GetDeviceCapReq; - QMIDMS_GET_DEVICE_CAP_RESP_MSG GetDeviceCapResp; - QMIDMS_GET_BAND_CAP_REQ_MSG GetBandCapReq; - QMIDMS_GET_BAND_CAP_RESP_MSG GetBandCapRsp; - QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG GetActivatedStatusReq; - QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG GetActivatedStatusResp; - QMIDMS_GET_OPERATING_MODE_REQ_MSG GetOperatingModeReq; - QMIDMS_GET_OPERATING_MODE_RESP_MSG GetOperatingModeResp; -#endif - QMIDMS_SET_OPERATING_MODE_REQ_MSG SetOperatingModeReq; - QMIDMS_SET_OPERATING_MODE_RESP_MSG SetOperatingModeResp; -#if 0 - QMIDMS_UIM_GET_ICCID_REQ_MSG GetICCIDReq; - QMIDMS_UIM_GET_ICCID_RESP_MSG GetICCIDResp; - QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG ActivateAutomaticReq; - QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG ActivateAutomaticResp; - QMIDMS_ACTIVATE_MANUAL_REQ_MSG ActivateManualReq; - QMIDMS_ACTIVATE_MANUAL_RESP_MSG ActivateManualResp; -#endif - QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG UIMGetPinStatusReq; - QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG UIMGetPinStatusResp; - QMIDMS_UIM_VERIFY_PIN_REQ_MSG UIMVerifyPinReq; - QMIDMS_UIM_VERIFY_PIN_RESP_MSG UIMVerifyPinResp; -#if 0 - QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG UIMSetPinProtectionReq; - QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG UIMSetPinProtectionResp; - QMIDMS_UIM_CHANGE_PIN_REQ_MSG UIMChangePinReq; - QMIDMS_UIM_CHANGE_PIN_RESP_MSG UIMChangePinResp; - QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG UIMUnblockPinReq; - QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG UIMUnblockPinResp; - QMIDMS_SET_EVENT_REPORT_REQ_MSG DmsSetEventReportReq; - QMIDMS_SET_EVENT_REPORT_RESP_MSG DmsSetEventReportResp; - QMIDMS_EVENT_REPORT_IND_MSG DmsEventReportInd; -#endif - QMIDMS_UIM_GET_STATE_REQ_MSG UIMGetStateReq; - QMIDMS_UIM_GET_STATE_RESP_MSG UIMGetStateResp; - QMIDMS_UIM_GET_IMSI_REQ_MSG UIMGetIMSIReq; - QMIDMS_UIM_GET_IMSI_RESP_MSG UIMGetIMSIResp; -#if 0 - QMIDMS_UIM_GET_CK_STATUS_REQ_MSG UIMGetCkStatusReq; - QMIDMS_UIM_GET_CK_STATUS_RESP_MSG UIMGetCkStatusResp; - QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG UIMSetCkProtectionReq; - QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG UIMSetCkProtectionResp; - QMIDMS_UIM_UNBLOCK_CK_REQ_MSG UIMUnblockCkReq; - QMIDMS_UIM_UNBLOCK_CK_RESP_MSG UIMUnblockCkResp; -#endif - - // QMIQOS Messages -#if 0 - QMI_QOS_SET_EVENT_REPORT_REQ_MSG QosSetEventReportReq; - QMI_QOS_SET_EVENT_REPORT_RESP_MSG QosSetEventReportRsp; - QMI_QOS_EVENT_REPORT_IND_MSG QosEventReportInd; -#endif - - // QMIWMS Messages -#if 0 - QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG GetMessageProtocolReq; - QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG GetMessageProtocolResp; - QMIWMS_GET_SMSC_ADDRESS_REQ_MSG GetSMSCAddressReq; - QMIWMS_GET_SMSC_ADDRESS_RESP_MSG GetSMSCAddressResp; - QMIWMS_SET_SMSC_ADDRESS_REQ_MSG SetSMSCAddressReq; - QMIWMS_SET_SMSC_ADDRESS_RESP_MSG SetSMSCAddressResp; - QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG GetStoreMaxSizeReq; - QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG GetStoreMaxSizeResp; - QMIWMS_LIST_MESSAGES_REQ_MSG ListMessagesReq; - QMIWMS_LIST_MESSAGES_RESP_MSG ListMessagesResp; - QMIWMS_RAW_READ_REQ_MSG RawReadMessagesReq; - QMIWMS_RAW_READ_RESP_MSG RawReadMessagesResp; - QMIWMS_SET_EVENT_REPORT_REQ_MSG WmsSetEventReportReq; - QMIWMS_SET_EVENT_REPORT_RESP_MSG WmsSetEventReportResp; - QMIWMS_EVENT_REPORT_IND_MSG WmsEventReportInd; - QMIWMS_DELETE_REQ_MSG WmsDeleteReq; - QMIWMS_DELETE_RESP_MSG WmsDeleteResp; - QMIWMS_RAW_SEND_REQ_MSG RawSendMessagesReq; - QMIWMS_RAW_SEND_RESP_MSG RawSendMessagesResp; - QMIWMS_MODIFY_TAG_REQ_MSG WmsModifyTagReq; - QMIWMS_MODIFY_TAG_RESP_MSG WmsModifyTagResp; -#endif - - // QMINAS Messages -#if 0 - QMINAS_GET_HOME_NETWORK_REQ_MSG GetHomeNetworkReq; - QMINAS_GET_HOME_NETWORK_RESP_MSG GetHomeNetworkResp; - QMINAS_GET_PREFERRED_NETWORK_REQ_MSG GetPreferredNetworkReq; - QMINAS_GET_PREFERRED_NETWORK_RESP_MSG GetPreferredNetworkResp; - QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG GetForbiddenNetworkReq; - QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG GetForbiddenNetworkResp; - QMINAS_GET_SERVING_SYSTEM_REQ_MSG GetServingSystemReq; -#endif - QMINAS_GET_SERVING_SYSTEM_RESP_MSG GetServingSystemResp; - QMINAS_GET_SYS_INFO_RESP_MSG GetSysInfoResp; - QMINAS_SYS_INFO_IND_MSG NasSysInfoInd; -#if 0 - QMINAS_SERVING_SYSTEM_IND_MSG NasServingSystemInd; - QMINAS_SET_PREFERRED_NETWORK_REQ_MSG SetPreferredNetworkReq; - QMINAS_SET_PREFERRED_NETWORK_RESP_MSG SetPreferredNetworkResp; - QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG SetForbiddenNetworkReq; - QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG SetForbiddenNetworkResp; - QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG PerformNetworkScanReq; - QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG PerformNetworkScanResp; - QMINAS_INITIATE_NW_REGISTER_REQ_MSG InitiateNwRegisterReq; - QMINAS_INITIATE_NW_REGISTER_RESP_MSG InitiateNwRegisterResp; - QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG SetTechnologyPrefReq; - QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG SetTechnologyPrefResp; - QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG GetSignalStrengthReq; - QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG GetSignalStrengthResp; - QMINAS_SET_EVENT_REPORT_REQ_MSG SetEventReportReq; - QMINAS_SET_EVENT_REPORT_RESP_MSG SetEventReportResp; - QMINAS_EVENT_REPORT_IND_MSG NasEventReportInd; - QMINAS_GET_RF_BAND_INFO_REQ_MSG GetRFBandInfoReq; - QMINAS_GET_RF_BAND_INFO_RESP_MSG GetRFBandInfoResp; - QMINAS_INITIATE_ATTACH_REQ_MSG InitiateAttachReq; - QMINAS_INITIATE_ATTACH_RESP_MSG InitiateAttachResp; - QMINAS_GET_PLMN_NAME_REQ_MSG GetPLMNNameReq; - QMINAS_GET_PLMN_NAME_RESP_MSG GetPLMNNameResp; -#endif - - // QMIUIM Messages - QMIUIM_GET_CARD_STATUS_RESP_MSG UIMGetCardStatus; - QMIUIM_VERIFY_PIN_REQ_MSG UIMUIMVerifyPinReq; - QMIUIM_VERIFY_PIN_RESP_MSG UIMUIMVerifyPinResp; -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - QMIUIM_BIND_PIN_REQ_MSG UIMUIMBindPinReq; - QMIUIM_BIND_PIN_REQ_MSG_4 UIMUIMBindPinReq_4; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -#if 0 - QMIUIM_SET_PIN_PROTECTION_REQ_MSG UIMUIMSetPinProtectionReq; - QMIUIM_SET_PIN_PROTECTION_RESP_MSG UIMUIMSetPinProtectionResp; - QMIUIM_CHANGE_PIN_REQ_MSG UIMUIMChangePinReq; - QMIUIM_CHANGE_PIN_RESP_MSG UIMUIMChangePinResp; - QMIUIM_UNBLOCK_PIN_REQ_MSG UIMUIMUnblockPinReq; - QMIUIM_UNBLOCK_PIN_RESP_MSG UIMUIMUnblockPinResp; -#endif - QMIUIM_READ_TRANSPARENT_REQ_MSG UIMUIMReadTransparentReq; - QMIUIM_READ_TRANSPARENT_RESP_MSG UIMUIMReadTransparentResp; - - QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - }; -} __attribute__((packed)) QMUX_MSG, *PQMUX_MSG; - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -#define QMI_WDS_BIND_SUBSCRIPTION_REQ_V01 0x00AF -#define QMI_WDS_BIND_SUBSCRIPTION_RESP_V01 0x00AF -#define QMI_DMS_BIND_SUBSCRIPTION_REQ_V01 0x0054 -#define QMI_DMS_BIND_SUBSCRIPTION_RESP_V01 0x0054 -#define QMI_NAS_BIND_SUBSCRIPTION_REQ_V01 0x0045 -#define QMI_NAS_BIND_SUBSCRIPTION_RESP_V01 0x0045 -#define QMI_QOS_BIND_SUBSCRIPTION_REQ_V01 0x002D -#define QMI_QOS_BIND_SUBSCRIPTION_RESP_V01 0x002D -#define QMI_WMS_BIND_SUBSCRIPTION_REQ_V01 0x004C -#define QMI_WMS_BIND_SUBSCRIPTION_RESP_V01 0x004C - -typedef enum { - QMI_RESULT_TYPE_MIN_ENUM_VAL_V01 = -2147483647, /**< To force a 32 bit signed enum. Do not change or use*/ - QMI_RESULT_SUCCESS_V01 = 0, - QMI_RESULT_FAILURE_V01 = 1, - QMI_RESULT_TYPE_MAX_ENUM_VAL_V01 = 2147483647 /**< To force a 32 bit signed enum. Do not change or use*/ -}qmi_result_type_v01; - -typedef enum { - QMI_ERROR_TYPE_MIN_ENUM_VAL_V01 = -2147483647, /**< To force a 32 bit signed enum. Do not change or use*/ - QMI_ERR_NONE_V01 = 0x0000, - QMI_ERR_MALFORMED_MSG_V01 = 0x0001, - QMI_ERR_NO_MEMORY_V01 = 0x0002, - QMI_ERR_INTERNAL_V01 = 0x0003, - QMI_ERR_ABORTED_V01 = 0x0004, - QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 = 0x0005, - QMI_ERR_UNABORTABLE_TRANSACTION_V01 = 0x0006, - QMI_ERR_INVALID_CLIENT_ID_V01 = 0x0007, - QMI_ERR_NO_THRESHOLDS_V01 = 0x0008, - QMI_ERR_INVALID_HANDLE_V01 = 0x0009, - QMI_ERR_INVALID_PROFILE_V01 = 0x000A, - QMI_ERR_INVALID_PINID_V01 = 0x000B, - QMI_ERR_INCORRECT_PIN_V01 = 0x000C, - QMI_ERR_NO_NETWORK_FOUND_V01 = 0x000D, - QMI_ERR_CALL_FAILED_V01 = 0x000E, - QMI_ERR_OUT_OF_CALL_V01 = 0x000F, - QMI_ERR_NOT_PROVISIONED_V01 = 0x0010, - QMI_ERR_MISSING_ARG_V01 = 0x0011, - QMI_ERR_ARG_TOO_LONG_V01 = 0x0013, - QMI_ERR_INVALID_TX_ID_V01 = 0x0016, - QMI_ERR_DEVICE_IN_USE_V01 = 0x0017, - QMI_ERR_OP_NETWORK_UNSUPPORTED_V01 = 0x0018, - QMI_ERR_OP_DEVICE_UNSUPPORTED_V01 = 0x0019, - QMI_ERR_NO_EFFECT_V01 = 0x001A, - QMI_ERR_NO_FREE_PROFILE_V01 = 0x001B, - QMI_ERR_INVALID_PDP_TYPE_V01 = 0x001C, - QMI_ERR_INVALID_TECH_PREF_V01 = 0x001D, - QMI_ERR_INVALID_PROFILE_TYPE_V01 = 0x001E, - QMI_ERR_INVALID_SERVICE_TYPE_V01 = 0x001F, - QMI_ERR_INVALID_REGISTER_ACTION_V01 = 0x0020, - QMI_ERR_INVALID_PS_ATTACH_ACTION_V01 = 0x0021, - QMI_ERR_AUTHENTICATION_FAILED_V01 = 0x0022, - QMI_ERR_PIN_BLOCKED_V01 = 0x0023, - QMI_ERR_PIN_PERM_BLOCKED_V01 = 0x0024, - QMI_ERR_SIM_NOT_INITIALIZED_V01 = 0x0025, - QMI_ERR_MAX_QOS_REQUESTS_IN_USE_V01 = 0x0026, - QMI_ERR_INCORRECT_FLOW_FILTER_V01 = 0x0027, - QMI_ERR_NETWORK_QOS_UNAWARE_V01 = 0x0028, - QMI_ERR_INVALID_ID_V01 = 0x0029, - QMI_ERR_INVALID_QOS_ID_V01 = 0x0029, - QMI_ERR_REQUESTED_NUM_UNSUPPORTED_V01 = 0x002A, - QMI_ERR_INTERFACE_NOT_FOUND_V01 = 0x002B, - QMI_ERR_FLOW_SUSPENDED_V01 = 0x002C, - QMI_ERR_INVALID_DATA_FORMAT_V01 = 0x002D, - QMI_ERR_GENERAL_V01 = 0x002E, - QMI_ERR_UNKNOWN_V01 = 0x002F, - QMI_ERR_INVALID_ARG_V01 = 0x0030, - QMI_ERR_INVALID_INDEX_V01 = 0x0031, - QMI_ERR_NO_ENTRY_V01 = 0x0032, - QMI_ERR_DEVICE_STORAGE_FULL_V01 = 0x0033, - QMI_ERR_DEVICE_NOT_READY_V01 = 0x0034, - QMI_ERR_NETWORK_NOT_READY_V01 = 0x0035, - QMI_ERR_CAUSE_CODE_V01 = 0x0036, - QMI_ERR_MESSAGE_NOT_SENT_V01 = 0x0037, - QMI_ERR_MESSAGE_DELIVERY_FAILURE_V01 = 0x0038, - QMI_ERR_INVALID_MESSAGE_ID_V01 = 0x0039, - QMI_ERR_ENCODING_V01 = 0x003A, - QMI_ERR_AUTHENTICATION_LOCK_V01 = 0x003B, - QMI_ERR_INVALID_TRANSITION_V01 = 0x003C, - QMI_ERR_NOT_A_MCAST_IFACE_V01 = 0x003D, - QMI_ERR_MAX_MCAST_REQUESTS_IN_USE_V01 = 0x003E, - QMI_ERR_INVALID_MCAST_HANDLE_V01 = 0x003F, - QMI_ERR_INVALID_IP_FAMILY_PREF_V01 = 0x0040, - QMI_ERR_SESSION_INACTIVE_V01 = 0x0041, - QMI_ERR_SESSION_INVALID_V01 = 0x0042, - QMI_ERR_SESSION_OWNERSHIP_V01 = 0x0043, - QMI_ERR_INSUFFICIENT_RESOURCES_V01 = 0x0044, - QMI_ERR_DISABLED_V01 = 0x0045, - QMI_ERR_INVALID_OPERATION_V01 = 0x0046, - QMI_ERR_INVALID_QMI_CMD_V01 = 0x0047, - QMI_ERR_TPDU_TYPE_V01 = 0x0048, - QMI_ERR_SMSC_ADDR_V01 = 0x0049, - QMI_ERR_INFO_UNAVAILABLE_V01 = 0x004A, - QMI_ERR_SEGMENT_TOO_LONG_V01 = 0x004B, - QMI_ERR_SEGMENT_ORDER_V01 = 0x004C, - QMI_ERR_BUNDLING_NOT_SUPPORTED_V01 = 0x004D, - QMI_ERR_OP_PARTIAL_FAILURE_V01 = 0x004E, - QMI_ERR_POLICY_MISMATCH_V01 = 0x004F, - QMI_ERR_SIM_FILE_NOT_FOUND_V01 = 0x0050, - QMI_ERR_EXTENDED_INTERNAL_V01 = 0x0051, - QMI_ERR_ACCESS_DENIED_V01 = 0x0052, - QMI_ERR_HARDWARE_RESTRICTED_V01 = 0x0053, - QMI_ERR_ACK_NOT_SENT_V01 = 0x0054, - QMI_ERR_INJECT_TIMEOUT_V01 = 0x0055, - QMI_ERR_INCOMPATIBLE_STATE_V01 = 0x005A, - QMI_ERR_FDN_RESTRICT_V01 = 0x005B, - QMI_ERR_SUPS_FAILURE_CAUSE_V01 = 0x005C, - QMI_ERR_NO_RADIO_V01 = 0x005D, - QMI_ERR_NOT_SUPPORTED_V01 = 0x005E, - QMI_ERR_NO_SUBSCRIPTION_V01 = 0x005F, - QMI_ERR_CARD_CALL_CONTROL_FAILED_V01 = 0x0060, - QMI_ERR_NETWORK_ABORTED_V01 = 0x0061, - QMI_ERR_MSG_BLOCKED_V01 = 0x0062, - QMI_ERR_INVALID_SESSION_TYPE_V01 = 0x0064, - QMI_ERR_INVALID_PB_TYPE_V01 = 0x0065, - QMI_ERR_NO_SIM_V01 = 0x0066, - QMI_ERR_PB_NOT_READY_V01 = 0x0067, - QMI_ERR_PIN_RESTRICTION_V01 = 0x0068, - QMI_ERR_PIN2_RESTRICTION_V01 = 0x0069, - QMI_ERR_PUK_RESTRICTION_V01 = 0x006A, - QMI_ERR_PUK2_RESTRICTION_V01 = 0x006B, - QMI_ERR_PB_ACCESS_RESTRICTED_V01 = 0x006C, - QMI_ERR_PB_DELETE_IN_PROG_V01 = 0x006D, - QMI_ERR_PB_TEXT_TOO_LONG_V01 = 0x006E, - QMI_ERR_PB_NUMBER_TOO_LONG_V01 = 0x006F, - QMI_ERR_PB_HIDDEN_KEY_RESTRICTION_V01 = 0x0070, - QMI_ERR_PB_NOT_AVAILABLE_V01 = 0x0071, - QMI_ERR_DEVICE_MEMORY_ERROR_V01 = 0x0072, - QMI_ERR_NO_PERMISSION_V01 = 0x0073, - QMI_ERR_TOO_SOON_V01 = 0x0074, - QMI_ERR_TIME_NOT_ACQUIRED_V01 = 0x0075, - QMI_ERR_OP_IN_PROGRESS_V01 = 0x0076, - QMI_ERR_EPERM_V01 = 0x101, /**< Operation not permitted */ - QMI_ERR_ENOENT_V01 = 0x102, /**< No such file or directory */ - QMI_ERR_ESRCH_V01 = 0x103, /**< No such process */ - QMI_ERR_EINTR_V01 = 0x104, /**< Interrupted system call */ - QMI_ERR_EIO_V01 = 0x105, /**< I/O error */ - QMI_ERR_ENXIO_V01 = 0x106, /**< No such device or address */ - QMI_ERR_E2BIG_V01 = 0x107, /**< Argument list too long */ - QMI_ERR_ENOEXEC_V01 = 0x108, /**< Exec format error */ - QMI_ERR_EBADF_V01 = 0x109, /**< Bad file number */ - QMI_ERR_ECHILD_V01 = 0x10A, /**< No child processes */ - QMI_ERR_EAGAIN_V01 = 0x10B, /**< Try again */ - QMI_ERR_ENOMEM_V01 = 0x10C, /**< Out of memory */ - QMI_ERR_EACCES_V01 = 0x10D, /**< Permission denied */ - QMI_ERR_EFAULT_V01 = 0x10E, /**< Bad address */ - QMI_ERR_ENOTBLK_V01 = 0x10F, /**< Block device required */ - QMI_ERR_EBUSY_V01 = 0x110, /**< Device or resource busy */ - QMI_ERR_EEXIST_V01 = 0x111, /**< File exists */ - QMI_ERR_EXDEV_V01 = 0x112, /**< Cross-device link */ - QMI_ERR_ENODEV_V01 = 0x113, /**< No such device */ - QMI_ERR_ENOTDIR_V01 = 0x114, /**< Not a directory */ - QMI_ERR_EISDIR_V01 = 0x115, /**< Is a directory */ - QMI_ERR_EINVAL_V01 = 0x116, /**< Invalid argument */ - QMI_ERR_ENFILE_V01 = 0x117, /**< File table overflow */ - QMI_ERR_EMFILE_V01 = 0x118, /**< Too many open files */ - QMI_ERR_ENOTTY_V01 = 0x119, /**< Not a typewriter */ - QMI_ERR_ETXTBSY_V01 = 0x11A, /**< Text file busy */ - QMI_ERR_EFBIG_V01 = 0x11B, /**< File too large */ - QMI_ERR_ENOSPC_V01 = 0x11C, /**< No space left on device */ - QMI_ERR_ESPIPE_V01 = 0x11D, /**< Illegal seek */ - QMI_ERR_EROFS_V01 = 0x11E, /**< Read-only file system */ - QMI_ERR_EMLINK_V01 = 0x11F, /**< Too many links */ - QMI_ERR_EPIPE_V01 = 0x120, /**< Broken pipe */ - QMI_ERR_EDOM_V01 = 0x121, /**< Math argument out of domain of func */ - QMI_ERR_ERANGE_V01 = 0x122, /**< Math result not representable */ - QMI_ERR_EDEADLK_V01 = 0x123, /**< Resource deadlock would occur */ - QMI_ERR_ENAMETOOLONG_V01 = 0x124, /**< File name too long */ - QMI_ERR_ENOLCK_V01 = 0x125, /**< No record locks available */ - QMI_ERR_ENOSYS_V01 = 0x126, /**< Function not implemented */ - QMI_ERR_ENOTEMPTY_V01 = 0x127, /**< Directory not empty */ - QMI_ERR_ELOOP_V01 = 0x128, /**< Too many symbolic links encountered */ - QMI_ERR_EWOULDBLOCK_V01 = 0x10B, /**< Operation would block */ - QMI_ERR_ENOMSG_V01 = 0x12A, /**< No message of desired type */ - QMI_ERR_EIDRM_V01 = 0x12B, /**< Identifier removed */ - QMI_ERR_ECHRNG_V01 = 0x12C, /**< Channel number out of range */ - QMI_ERR_EL2NSYNC_V01 = 0x12D, /**< Level 2 not synchronized */ - QMI_ERR_EL3HLT_V01 = 0x12E, /**< Level 3 halted */ - QMI_ERR_EL3RST_V01 = 0x12F, /**< Level 3 reset */ - QMI_ERR_ELNRNG_V01 = 0x130, /**< Link number out of range */ - QMI_ERR_EUNATCH_V01 = 0x131, /**< Protocol driver not attached */ - QMI_ERR_ENOCSI_V01 = 0x132, /**< No CSI structure available */ - QMI_ERR_EL2HLT_V01 = 0x133, /**< Level 2 halted */ - QMI_ERR_EBADE_V01 = 0x134, /**< Invalid exchange */ - QMI_ERR_EBADR_V01 = 0x135, /**< Invalid request descriptor */ - QMI_ERR_EXFULL_V01 = 0x136, /**< Exchange full */ - QMI_ERR_ENOANO_V01 = 0x137, /**< No anode */ - QMI_ERR_EBADRQC_V01 = 0x138, /**< Invalid request code */ - QMI_ERR_EBADSLT_V01 = 0x139, /**< Invalid slot */ - QMI_ERR_EDEADLOCK_V01 = 0x123, /**< Resource deadlock would occur */ - QMI_ERR_EBFONT_V01 = 0x13B, /**< Bad font file format */ - QMI_ERR_ENOSTR_V01 = 0x13C, /**< Device not a stream */ - QMI_ERR_ENODATA_V01 = 0x13D, /**< No data available */ - QMI_ERR_ETIME_V01 = 0x13E, /**< Timer expired */ - QMI_ERR_ENOSR_V01 = 0x13F, /**< Out of streams resources */ - QMI_ERR_ENONET_V01 = 0x140, /**< Machine is not on the network */ - QMI_ERR_ENOPKG_V01 = 0x141, /**< Package not installed */ - QMI_ERR_EREMOTE_V01 = 0x142, /**< Object is remote */ - QMI_ERR_ENOLINK_V01 = 0x143, /**< Link has been severed */ - QMI_ERR_EADV_V01 = 0x144, /**< Advertise error */ - QMI_ERR_ESRMNT_V01 = 0x145, /**< Srmount error */ - QMI_ERR_ECOMM_V01 = 0x146, /**< Communication error on send */ - QMI_ERR_EPROTO_V01 = 0x147, /**< Protocol error */ - QMI_ERR_EMULTIHOP_V01 = 0x148, /**< Multihop attempted */ - QMI_ERR_EDOTDOT_V01 = 0x149, /**< RFS specific error */ - QMI_ERR_EBADMSG_V01 = 0x14A, /**< Not a data message */ - QMI_ERR_EOVERFLOW_V01 = 0x14B, /**< Value too large for defined data type */ - QMI_ERR_ENOTUNIQ_V01 = 0x14C, /**< Name not unique on network */ - QMI_ERR_EBADFD_V01 = 0x14D, /**< File descriptor in bad state */ - QMI_ERR_EREMCHG_V01 = 0x14E, /**< Remote address changed */ - QMI_ERR_ELIBACC_V01 = 0x14F, /**< Can not access a needed shared library */ - QMI_ERR_ELIBBAD_V01 = 0x150, /**< Accessing a corrupted shared library */ - QMI_ERR_ELIBSCN_V01 = 0x151, /**< .lib section in a.out corrupted */ - QMI_ERR_ELIBMAX_V01 = 0x152, /**< Attempting to link in too many shared libraries */ - QMI_ERR_ELIBEXEC_V01 = 0x153, /**< Cannot exec a shared library directly */ - QMI_ERR_EILSEQ_V01 = 0x154, /**< Illegal byte sequence */ - QMI_ERR_ERESTART_V01 = 0x155, /**< Interrupted system call should be restarted */ - QMI_ERR_ESTRPIPE_V01 = 0x156, /**< Streams pipe error */ - QMI_ERR_EUSERS_V01 = 0x157, /**< Too many users */ - QMI_ERR_ENOTSOCK_V01 = 0x158, /**< Socket operation on non-socket */ - QMI_ERR_EDESTADDRREQ_V01 = 0x159, /**< Destination address required */ - QMI_ERR_EMSGSIZE_V01 = 0x15A, /**< Message too long */ - QMI_ERR_EPROTOTYPE_V01 = 0x15B, /**< Protocol wrong type for socket */ - QMI_ERR_ENOPROTOOPT_V01 = 0x15C, /**< Protocol not available */ - QMI_ERR_EPROTONOSUPPORT_V01 = 0x15D, /**< Protocol not supported */ - QMI_ERR_ESOCKTNOSUPPORT_V01 = 0x15E, /**< Socket type not supported */ - QMI_ERR_EOPNOTSUPP_V01 = 0x15F, /**< Operation not supported on transport endpoint */ - QMI_ERR_EPFNOSUPPORT_V01 = 0x160, /**< Protocol family not supported */ - QMI_ERR_EAFNOSUPPORT_V01 = 0x161, /**< Address family not supported by protocol */ - QMI_ERR_EADDRINUSE_V01 = 0x162, /**< Address already in use */ - QMI_ERR_EADDRNOTAVAIL_V01 = 0x163, /**< Cannot assign requested address */ - QMI_ERR_ENETDOWN_V01 = 0x164, /**< Network is down */ - QMI_ERR_ENETUNREACH_V01 = 0x165, /**< Network is unreachable */ - QMI_ERR_ENETRESET_V01 = 0x166, /**< Network dropped connection because of reset */ - QMI_ERR_ECONNABORTED_V01 = 0x167, /**< Software caused connection abort */ - QMI_ERR_ECONNRESET_V01 = 0x168, /**< Connection reset by peer */ - QMI_ERR_ENOBUFS_V01 = 0x169, /**< No buffer space available */ - QMI_ERR_EISCONN_V01 = 0x16A, /**< Transport endpoint is already connected */ - QMI_ERR_ENOTCONN_V01 = 0x16B, /**< Transport endpoint is not connected */ - QMI_ERR_ESHUTDOWN_V01 = 0x16C, /**< Cannot send after transport endpoint shutdown */ - QMI_ERR_ETOOMANYREFS_V01 = 0x16D, /**< Too many references: cannot splice */ - QMI_ERR_ETIMEDOUT_V01 = 0x16E, /**< Connection timed out */ - QMI_ERR_ECONNREFUSED_V01 = 0x16F, /**< Connection refused */ - QMI_ERR_EHOSTDOWN_V01 = 0x170, /**< Host is down */ - QMI_ERR_EHOSTUNREACH_V01 = 0x171, /**< No route to host */ - QMI_ERR_EALREADY_V01 = 0x172, /**< Operation already in progress */ - QMI_ERR_EINPROGRESS_V01 = 0x173, /**< Operation now in progress */ - QMI_ERR_ESTALE_V01 = 0x174, /**< Stale NFS file handle */ - QMI_ERR_EUCLEAN_V01 = 0x175, /**< Structure needs cleaning */ - QMI_ERR_ENOTNAM_V01 = 0x176, /**< Not a XENIX named type file */ - QMI_ERR_ENAVAIL_V01 = 0x177, /**< No XENIX semaphores available */ - QMI_ERR_EISNAM_V01 = 0x178, /**< Is a named type file */ - QMI_ERR_EREMOTEIO_V01 = 0x179, /**< Remote I/O error */ - QMI_ERR_EDQUOT_V01 = 0x17A, /**< Quota exceeded */ - QMI_ERR_ENOMEDIUM_V01 = 0x17B, /**< No medium found */ - QMI_ERR_EMEDIUMTYPE_V01 = 0x17C, /**< Wrong medium type */ - QMI_ERR_ECANCELED_V01 = 0x17D, /**< Operation Canceled */ - QMI_ERR_ENOKEY_V01 = 0x17E, /**< Required key not available */ - QMI_ERR_EKEYEXPIRED_V01 = 0x17F, /**< Key has expired */ - QMI_ERR_EKEYREVOKED_V01 = 0x180, /**< Key has been revoked */ - QMI_ERR_EKEYREJECTED_V01 = 0x181, /**< Key was rejected by service */ - QMI_ERR_EOWNERDEAD_V01 = 0x182, /**< Owner died */ - QMI_ERR_ENOTRECOVERABLE_V01 = 0x183, /**< State not recoverable */ - QMI_ERROR_TYPE_MAX_ENUM_VAL_V01 = 2147483647 /**< To force a 32 bit signed enum. Do not change or use*/ -}qmi_error_type_v01; - -typedef struct { - qmi_result_type_v01 result; - qmi_error_type_v01 error; -}qmi_response_type_v01; /* Type */ - -typedef enum { - NAS_SUBS_TYPE_ENUM_MIN_ENUM_VAL_V01 = -2147483647, /**< To force a 32 bit signed enum. Do not change or use*/ - NAS_PRIMARY_SUBSCRIPTION_V01 = 0x00, /**< Primary subscription \n */ - NAS_SECONDARY_SUBSCRIPTION_V01 = 0x01, /**< Secondary subscription \n */ - NAS_TERTIARY_SUBSCRIPTION_V01 = 0x02, /**< Tertiary subscription */ - NAS_SUBS_TYPE_ENUM_MAX_ENUM_VAL_V01 = 2147483647 /**< To force a 32 bit signed enum. Do not change or use*/ -}nas_subs_type_enum_v01; - -typedef struct { - nas_subs_type_enum_v01 subs_type; -}nas_bind_subscription_req_msg_v01; /* Message */ -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -#pragma pack(pop) - -#endif// MPQMUX_H diff --git a/fibocom-dial/src/Makefile b/fibocom-dial/src/Makefile deleted file mode 100644 index 992b951..0000000 --- a/fibocom-dial/src/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -ifneq ($(CROSS_COMPILE),) -CROSS-COMPILE:=$(CROSS_COMPILE) -endif - -CFLAGS += -DGHT_FEATURE_PCIE_AUTO - -ifeq ($(CC),cc) -CC:=$(CROSS-COMPILE)gcc -endif -LD:=$(CROSS-COMPILE)ld - -SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c query_pcie_mode.c - -FB_DHCP=udhcpc.c - -FIBO_PROXY_SRC=fibo_qmimsg_server.c - -LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c -FB_NDHCP=udhcpc_netlink.c -FB_NDHCP+=${LIBMNL} - -release: clean - $(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_NDHCP} -o fibocom-dial -lpthread -ldl - $(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.c util.c -o multi-pdn-manager -lpthread -ldl - $(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl - -dhcp: clean - $(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_DHCP} -o fibocom-dial -lpthread -ldl - $(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.c util.c -o multi-pdn-manager -lpthread -ldl - $(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl - -ndhcp: clean - $(CC) $(CFLAGS) -Wall -s ${SRC} ${FB_NDHCP} -o fibocom-dial -lpthread -ldl - $(CC) -Wall -s multi-pdn-manager.c query_pcie_mode.cutil.c -o multi-pdn-manager -lpthread -ldl - $(CC) -Wall -s ${FIBO_PROXY_SRC} -o fibo_qmimsg_server -lpthread -ldl - -qmi-proxy: - $(CC) -Wall -s fibo-qmi-proxy.c -o fibo-qmi-proxy -lpthread -ldl - -clean: - rm -rf fibocom-dial *~ multi-pdn-manager fibo_qmimsg_server - diff --git a/fibocom-dial/src/QMIThread.c b/fibocom-dial/src/QMIThread.c deleted file mode 100644 index ecce6b9..0000000 --- a/fibocom-dial/src/QMIThread.c +++ /dev/null @@ -1,2551 +0,0 @@ -#include "QMIThread.h" -#include "query_pcie_mode.h" -extern char *strndup(const char *__string, size_t __n); - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -//extern int *speed_arr; -//extern int *name_arr; - -PQCQMIMSG pResponse; -PQMUX_MSG pMUXMsg; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - -#define qmi_rsp_check_and_return()\ - do { \ - if (err < 0 || pResponse == NULL) { \ - dbg_time("%s err = %d", __func__, err); \ - return err; \ - } \ - pMUXMsg = &pResponse->MUXMsg; \ - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || \ - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { \ - USHORT QMUXError = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); \ - dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, \ - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), \ - QMUXError); \ - free(pResponse); \ - return QMUXError; \ - } \ - } while (0) - -#define qmi_rsp_check() \ - do { \ - if (err < 0 || pResponse == NULL) { \ - dbg_time("%s err = %d", __func__, err); \ - return err; \ - } \ - pMUXMsg = &pResponse->MUXMsg; \ - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || \ - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { \ - USHORT QMUXError = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); \ - dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, \ - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), \ - QMUXError); \ - } \ - } while (0) - -int qmiclientId[QMUX_TYPE_WDS_ADMIN + - 1]; // GobiNet use fd to indicate client ID, so type of - // qmiclientId must be int -static uint32_t WdsConnectionIPv4Handle = 0; -static uint32_t WdsConnectionIPv6Handle = 0; -static int s_is_cdma = 0; -static int s_hdr_personality = 0; // 0x01-HRPD, 0x02-eHRPD -static char *qstrcpy(char *to, const char *from) -{ // no __strcpy_chk - char *save = to; - for (; (*to = *from) != '\0'; ++from, ++to) - ; - return (save); -} - - - -typedef USHORT (*CUSTOMQMUX)(PQMUX_MSG pMUXMsg, void *arg); - -// To retrieve the ith (Index) TLV -PQMI_TLV_HDR GetTLV(PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType) -{ - int TLVFind = 0; - USHORT Length = le16_to_cpu(pQMUXMsgHdr->Length); - PQMI_TLV_HDR pTLVHdr = (PQMI_TLV_HDR)(pQMUXMsgHdr + 1); - - while (Length >= sizeof(QMI_TLV_HDR)) { - TLVFind++; - if (TLVType > 0x1000) { - if ((TLVFind + 0x1000) == TLVType) - return pTLVHdr; - } else if (pTLVHdr->TLVType == TLVType) { - return pTLVHdr; - } - - Length -= (le16_to_cpu((pTLVHdr->TLVLength)) + sizeof(QMI_TLV_HDR)); - pTLVHdr = (PQMI_TLV_HDR)(((UCHAR *)pTLVHdr) + - le16_to_cpu(pTLVHdr->TLVLength) + - sizeof(QMI_TLV_HDR)); - } - - return NULL; -} - -static USHORT GetQMUXTransactionId(void) -{ - static int TransactionId = 0; - if (++TransactionId > 0xFFFF) - TransactionId = 1; - return TransactionId; -} - -static PQCQMIMSG ComposeQMUXMsg(UCHAR QMIType, USHORT Type, - CUSTOMQMUX customQmuxMsgFunction, void *arg) -{ - UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE]; - PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf; - int Length; - - memset(QMIBuf, 0x00, sizeof(QMIBuf)); - pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRequest->QMIHdr.CtlFlags = 0x00; - pRequest->QMIHdr.QMIType = QMIType; - pRequest->QMIHdr.ClientId = qmiclientId[QMIType] & 0xFF; - - if (qmiclientId[QMIType] == 0) { - dbg_time("QMIType %d has no clientID", QMIType); - return NULL; - } - - pRequest->MUXMsg.QMUXHdr.CtlFlags = - QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD; - pRequest->MUXMsg.QMUXHdr.TransactionId = - cpu_to_le16(GetQMUXTransactionId()); - pRequest->MUXMsg.QMUXMsgHdr.Type = cpu_to_le16(Type); - if (customQmuxMsgFunction) - pRequest->MUXMsg.QMUXMsgHdr.Length = - cpu_to_le16(customQmuxMsgFunction(&pRequest->MUXMsg, arg) - - sizeof(QCQMUX_MSG_HDR)); - else - pRequest->MUXMsg.QMUXMsgHdr.Length = cpu_to_le16(0x0000); - - pRequest->QMIHdr.Length = cpu_to_le16( - le16_to_cpu(pRequest->MUXMsg.QMUXMsgHdr.Length) + - sizeof(QCQMUX_MSG_HDR) + sizeof(QCQMUX_HDR) + sizeof(QCQMI_HDR) - 1); - Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - - pRequest = (PQCQMIMSG)malloc(Length); - if (pRequest == NULL) { - dbg_time("%s fail to malloc", __func__); - } else { - memcpy(pRequest, QMIBuf, Length); - } - - return pRequest; -} - -static USHORT WdsStartNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) -{ - PQMIWDS_TECHNOLOGY_PREFERECE pTechPref; - PQMIWDS_AUTH_PREFERENCE pAuthPref; - PQMIWDS_USERNAME pUserName; - PQMIWDS_PASSWD pPasswd; - PQMIWDS_APNNAME pApnName; - PQMIWDS_IP_FAMILY_TLV pIpFamily; - USHORT TLVLength = 0; - UCHAR *pTLV; - PROFILE_T *profile = (PROFILE_T *)arg; - const char *profile_user = profile->user; - const char *profile_password = profile->password; - int profile_auth = profile->auth; - - if (s_is_cdma && (profile_user == NULL || profile_user[0] == '\0') && - (profile_password == NULL || profile_password[0] == '\0')) { - profile_user = "ctnet@mycdma.cn"; - profile_password = "vnet.mobi"; - profile_auth = 2; // chap - } - - pTLV = (UCHAR *)(&pMUXMsg->StartNwInterfaceReq + 1); - pMUXMsg->StartNwInterfaceReq.Length = 0; - - // Set technology Preferece - pTechPref = (PQMIWDS_TECHNOLOGY_PREFERECE)(pTLV + TLVLength); - pTechPref->TLVType = 0x30; - pTechPref->TLVLength = cpu_to_le16(0x01); - if (s_is_cdma == 0) - pTechPref->TechPreference = 0x01; - else - pTechPref->TechPreference = 0x02; - TLVLength += (le16_to_cpu(pTechPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - // Set APN Name - if (profile->apn && !s_is_cdma) { // cdma no apn - pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength); - pApnName->TLVType = 0x14; - pApnName->TLVLength = cpu_to_le16(strlen(profile->apn)); - qstrcpy((char *)&pApnName->ApnName, profile->apn); - TLVLength += - (le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set User Name - if (profile_user) { - pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength); - pUserName->TLVType = 0x17; - pUserName->TLVLength = cpu_to_le16(strlen(profile_user)); - qstrcpy((char *)&pUserName->UserName, profile_user); - TLVLength += - (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Password - if (profile_password) { - pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength); - pPasswd->TLVType = 0x18; - pPasswd->TLVLength = cpu_to_le16(strlen(profile_password)); - qstrcpy((char *)&pPasswd->Passwd, profile_password); - TLVLength += - (le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Auth Protocol - if (profile_user && profile_password) { - pAuthPref = (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength); - pAuthPref->TLVType = 0x16; - pAuthPref->TLVLength = cpu_to_le16(0x01); - pAuthPref->AuthPreference = - profile_auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2 - TLVLength += - (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Add IP Family Preference - pIpFamily = (PQMIWDS_IP_FAMILY_TLV)(pTLV + TLVLength); - pIpFamily->TLVType = 0x19; - pIpFamily->TLVLength = cpu_to_le16(0x01); - pIpFamily->IpFamily = profile->curIpFamily; - TLVLength += (le16_to_cpu(pIpFamily->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - // Set Profile Index - if (profile->pdp && !s_is_cdma) { // cdma only support one pdp, so no need - // to set profile index - PQMIWDS_PROFILE_IDENTIFIER pProfileIndex = - (PQMIWDS_PROFILE_IDENTIFIER)(pTLV + TLVLength); - pProfileIndex->TLVLength = cpu_to_le16(0x01); - pProfileIndex->TLVType = 0x31; - pProfileIndex->ProfileIndex = profile->pdpindex; - if (s_is_cdma && s_hdr_personality == 0x02) { - pProfileIndex->TLVType = 0x32; // profile_index_3gpp2 - pProfileIndex->ProfileIndex = 101; - } - TLVLength += - (le16_to_cpu(pProfileIndex->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - return sizeof(QMIWDS_START_NETWORK_INTERFACE_REQ_MSG) + TLVLength; -} - -static USHORT WdsStopNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->StopNwInterfaceReq.TLVType = 0x01; - pMUXMsg->StopNwInterfaceReq.TLVLength = cpu_to_le16(0x04); - if (*((int *)arg) == IpFamilyV4) - pMUXMsg->StopNwInterfaceReq.Handle = - cpu_to_le32(WdsConnectionIPv4Handle); - else - pMUXMsg->StopNwInterfaceReq.Handle = - cpu_to_le32(WdsConnectionIPv6Handle); - return sizeof(QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG); -} - -static USHORT WdsSetClientIPFamilyPref(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->SetClientIpFamilyPrefReq.TLVType = 0x01; - pMUXMsg->SetClientIpFamilyPrefReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->SetClientIpFamilyPrefReq.IpPreference = *((UCHAR *)arg); - return sizeof(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG); -} - -static USHORT WdsSetAutoConnect(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->SetAutoConnectReq.TLVType = 0x01; - pMUXMsg->SetAutoConnectReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->SetAutoConnectReq.autoconnect_setting = *((UCHAR *)arg); - return sizeof(QMIWDS_SET_AUTO_CONNECT_REQ_MSG); -} - -enum peripheral_ep_type { - DATA_EP_TYPE_RESERVED = 0x0, - DATA_EP_TYPE_HSIC = 0x1, - DATA_EP_TYPE_HSUSB = 0x2, - DATA_EP_TYPE_PCIE = 0x3, - DATA_EP_TYPE_EMBEDDED = 0x4, - DATA_EP_TYPE_BAM_DMUX = 0x5, -}; - -typedef struct { - UINT rx_urb_size; - enum peripheral_ep_type ep_type; - UINT iface_id; - UCHAR MuxId; -} QMAP_SETTING; -static USHORT WdsSetQMUXBindMuxDataPort(PQMUX_MSG pMUXMsg, void *arg) -{ - QMAP_SETTING *qmap_settings = (QMAP_SETTING *)arg; - - pMUXMsg->BindMuxDataPortReq.TLVType = 0x10; - pMUXMsg->BindMuxDataPortReq.TLVLength = cpu_to_le16(0x08); - pMUXMsg->BindMuxDataPortReq.ep_type = cpu_to_le32(qmap_settings->ep_type); - pMUXMsg->BindMuxDataPortReq.iface_id = cpu_to_le32(qmap_settings->iface_id); - pMUXMsg->BindMuxDataPortReq.TLV2Type = 0x11; - pMUXMsg->BindMuxDataPortReq.TLV2Length = cpu_to_le16(0x01); - pMUXMsg->BindMuxDataPortReq.MuxId = qmap_settings->MuxId; - pMUXMsg->BindMuxDataPortReq.TLV3Type = 0x13; - pMUXMsg->BindMuxDataPortReq.TLV3Length = cpu_to_le16(0x04); - pMUXMsg->BindMuxDataPortReq.client_type = - cpu_to_le32(1); // WDS_CLIENT_TYPE_TETHERED - - return sizeof(QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG); -} - -static USHORT WdaSetDataFormat(PQMUX_MSG pMUXMsg, void *arg) -{ - QMAP_SETTING *qmap_settings = (QMAP_SETTING *)arg; - - if (qmap_settings->rx_urb_size == 0) { - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS pWdsAdminQosTlv; - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV linkProto; - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV dlTlp; - - pWdsAdminQosTlv = - (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS)(&pMUXMsg->QMUXMsgHdr + 1); - pWdsAdminQosTlv->TLVType = 0x10; - pWdsAdminQosTlv->TLVLength = cpu_to_le16(0x0001); - pWdsAdminQosTlv->QOSSetting = 0; /* no-QOS header */ - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)(pWdsAdminQosTlv + 1); - linkProto->TLVType = 0x11; - linkProto->TLVLength = cpu_to_le16(4); - linkProto->Value = cpu_to_le32(0x01); /* Set Ethernet mode */ - - dlTlp = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)(linkProto + 1); - ; - dlTlp->TLVType = 0x13; - dlTlp->TLVLength = cpu_to_le16(4); - dlTlp->Value = cpu_to_le32(0x00); - - if (sizeof(*linkProto) != 7) - dbg_time("%s sizeof(*linkProto) = %d, is not 7!", __func__, - sizeof(*linkProto)); - - return sizeof(QCQMUX_MSG_HDR) + sizeof(*pWdsAdminQosTlv) + - sizeof(*linkProto) + sizeof(*dlTlp); - } else { - // Indicates whether the Quality of Service(QOS) data format is used by - // the client. - pMUXMsg->SetDataFormatReq.QosDataFormatTlv.TLVType = 0x10; - pMUXMsg->SetDataFormatReq.QosDataFormatTlv.TLVLength = - cpu_to_le16(0x0001); - pMUXMsg->SetDataFormatReq.QosDataFormatTlv.QOSSetting = - 0; /* no-QOS header */ - // Underlying Link Layer Protocol - pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVType = 0x11; - pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVLength = - cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.Value = - cpu_to_le32(0x02); /* Set IP mode */ - // Uplink (UL) data aggregation protocol to be used for uplink data - // transfer. - pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVType = - 0x12; - pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVLength = - cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.Value = - cpu_to_le32(0x05); // UL QMAP is enabled - // Downlink (DL) data aggregation protocol to be used for downlink data - // transfer - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVType = - 0x13; - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVLength = - cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.Value = - cpu_to_le32(0x05); // UL QMAP is enabled - // Maximum number of datagrams in a single aggregated packet on downlink - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv - .TLVType = 0x15; - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv - .TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.Value = - cpu_to_le32(qmap_settings->rx_urb_size / 512); - // Maximum size in bytes of a single aggregated packet allowed on - // downlink - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVType = - 0x16; - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVLength = - cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.Value = - cpu_to_le32(qmap_settings->rx_urb_size); - // Peripheral End Point ID - pMUXMsg->SetDataFormatReq.epTlv.TLVType = 0x17; - pMUXMsg->SetDataFormatReq.epTlv.TLVLength = cpu_to_le16(8); - pMUXMsg->SetDataFormatReq.epTlv.ep_type = - cpu_to_le32(qmap_settings->ep_type); - pMUXMsg->SetDataFormatReq.epTlv.iface_id = - cpu_to_le32(qmap_settings->iface_id); - - return sizeof(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG); - } -} - -#ifdef CONFIG_SIM - -static USHORT UimVerifyPinReqSend(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->UIMUIMVerifyPinReq.TLVType = 0x01; - pMUXMsg->UIMUIMVerifyPinReq.TLVLength = cpu_to_le16(0x02); - pMUXMsg->UIMUIMVerifyPinReq.Session_Type = 0x00; - pMUXMsg->UIMUIMVerifyPinReq.Aid_Len = 0x00; - pMUXMsg->UIMUIMVerifyPinReq.TLV2Type = 0x02; - pMUXMsg->UIMUIMVerifyPinReq.TLV2Length = - cpu_to_le16(2 + strlen((const char *)arg)); - pMUXMsg->UIMUIMVerifyPinReq.PINID = 0x01; // Pin1, not Puk - pMUXMsg->UIMUIMVerifyPinReq.PINLen = strlen((const char *)arg); - qstrcpy((PCHAR)&pMUXMsg->UIMUIMVerifyPinReq.PINValue, ((const char *)arg)); - return sizeof(QMIUIM_VERIFY_PIN_REQ_MSG) + (strlen((const char *)arg) - 1); -} -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -static USHORT UimBindPinReqSend_NAS_WMS(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->UIMUIMBindPinReq.TLVType = 0x01; - pMUXMsg->UIMUIMBindPinReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->UIMUIMBindPinReq.Value = 0x01; - return sizeof(QMIUIM_BIND_PIN_REQ_MSG); -} - -static USHORT UimBindPinReqSend_WDS_DMS_QOS(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->UIMUIMBindPinReq_4.TLVType = 0x01; - pMUXMsg->UIMUIMBindPinReq_4.TLVLength = cpu_to_le16(0x04); - pMUXMsg->UIMUIMBindPinReq_4.Value = 0x0002; - return sizeof(QMIUIM_BIND_PIN_REQ_MSG_4); -} -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -#ifdef CONFIG_IMSI_ICCID -static USHORT UimReadTransparentIMSIReqSend(PQMUX_MSG pMUXMsg, void *arg) -{ - PREAD_TRANSPARENT_TLV pReadTransparent; - - pMUXMsg->UIMUIMReadTransparentReq.TLVType = 0x01; - pMUXMsg->UIMUIMReadTransparentReq.TLVLength = cpu_to_le16(0x02); - if (!strcmp((char *)arg, "EF_ICCID")) { - pMUXMsg->UIMUIMReadTransparentReq.Session_Type = 0x06; - pMUXMsg->UIMUIMReadTransparentReq.Aid_Len = 0x00; - - pMUXMsg->UIMUIMReadTransparentReq.TLV2Type = 0x02; - pMUXMsg->UIMUIMReadTransparentReq.file_id = cpu_to_le16(0x2FE2); - pMUXMsg->UIMUIMReadTransparentReq.path_len = 0x02; - pMUXMsg->UIMUIMReadTransparentReq.path[0] = 0x00; - pMUXMsg->UIMUIMReadTransparentReq.path[1] = 0x3F; - } else if (!strcmp((char *)arg, "EF_IMSI")) { - pMUXMsg->UIMUIMReadTransparentReq.Session_Type = 0x00; - pMUXMsg->UIMUIMReadTransparentReq.Aid_Len = 0x00; - - pMUXMsg->UIMUIMReadTransparentReq.TLV2Type = 0x02; - pMUXMsg->UIMUIMReadTransparentReq.file_id = cpu_to_le16(0x6F07); - pMUXMsg->UIMUIMReadTransparentReq.path_len = 0x04; - pMUXMsg->UIMUIMReadTransparentReq.path[0] = 0x00; - pMUXMsg->UIMUIMReadTransparentReq.path[1] = 0x3F; - pMUXMsg->UIMUIMReadTransparentReq.path[2] = 0xFF; - pMUXMsg->UIMUIMReadTransparentReq.path[3] = 0x7F; - } - - pMUXMsg->UIMUIMReadTransparentReq.TLV2Length = - cpu_to_le16(3 + pMUXMsg->UIMUIMReadTransparentReq.path_len); - - pReadTransparent = (PREAD_TRANSPARENT_TLV)( - &pMUXMsg->UIMUIMReadTransparentReq - .path[pMUXMsg->UIMUIMReadTransparentReq.path_len]); - pReadTransparent->TLVType = 0x03; - pReadTransparent->TLVLength = cpu_to_le16(0x04); - pReadTransparent->Offset = cpu_to_le16(0x00); - pReadTransparent->Length = cpu_to_le16(0x00); - - return (sizeof(QMIUIM_READ_TRANSPARENT_REQ_MSG) + - pMUXMsg->UIMUIMReadTransparentReq.path_len + - sizeof(READ_TRANSPARENT_TLV)); -} -#endif -#endif - -#ifdef CONFIG_APN -static USHORT WdsGetProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) -{ - PROFILE_T *profile = (PROFILE_T *)arg; - pMUXMsg->GetProfileSettingsReq.Length = - cpu_to_le16(sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG) - 4); - pMUXMsg->GetProfileSettingsReq.TLVType = 0x01; - pMUXMsg->GetProfileSettingsReq.TLVLength = cpu_to_le16(0x02); - pMUXMsg->GetProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 - pMUXMsg->GetProfileSettingsReq.ProfileIndex = profile->pdpindex; - return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG); -} -//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 -static USHORT WdsCreateProfileSettingsReq(PQMUX_MSG pMUXMsg, void *arg) -{ - USHORT TLVLength = 0; - UCHAR *pTLV; - PROFILE_T *profile = (PROFILE_T *)arg; - PQMIWDS_PDPTYPE pPdpType; - - pMUXMsg->CreateProfileSettingsReq.Length = - cpu_to_le16(sizeof(QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG) - 4); - pMUXMsg->CreateProfileSettingsReq.TLVType = 0x01; - pMUXMsg->CreateProfileSettingsReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->CreateProfileSettingsReq.ProfileType = - 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 - - pTLV = (UCHAR *)(&pMUXMsg->CreateProfileSettingsReq + 1); - - pPdpType = (PQMIWDS_PDPTYPE)(pTLV + TLVLength); - pPdpType->TLVType = 0x11; - pPdpType->TLVLength = cpu_to_le16(0x01); - // 0 ?C PDP-IP (IPv4) - // 1 ?C PDP-PPP - // 2 ?C PDP-IPv6 - // 3 ?C PDP-IPv4v6 - if (profile->ipv4_flag && profile->ipv6_flag) - pPdpType->PdpType = 3; - else if (profile->ipv6_flag) - pPdpType->PdpType = 2; - else - pPdpType->PdpType = 0; - TLVLength += (le16_to_cpu(pPdpType->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - // Set APN Name - if (profile->apn) { - PQMIWDS_APNNAME pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength); - pApnName->TLVType = 0x14; - pApnName->TLVLength = cpu_to_le16(strlen(profile->apn)); - qstrcpy((char *)&pApnName->ApnName, profile->apn); - TLVLength += - (le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set User Name - if (profile->user) { - PQMIWDS_USERNAME pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength); - pUserName->TLVType = 0x1B; - - pUserName->TLVLength = cpu_to_le16(strlen(profile->user)); - qstrcpy((char *)&pUserName->UserName, profile->user); - TLVLength += - (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Password - if (profile->password) { - PQMIWDS_PASSWD pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength); - pPasswd->TLVType = 0x1C; - pPasswd->TLVLength = cpu_to_le16(strlen(profile->password)); - qstrcpy((char *)&pPasswd->Passwd, profile->password); - TLVLength += - (le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Auth Protocol - if (profile->user && profile->password) { - PQMIWDS_AUTH_PREFERENCE pAuthPref = - (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength); - pAuthPref->TLVType = 0x1D; - pAuthPref->TLVLength = cpu_to_le16(0x01); - pAuthPref->AuthPreference = - profile->auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2 - TLVLength += - (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - return sizeof(QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG) + TLVLength; -} -//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 -static USHORT WdsModifyProfileSettingsReq(PQMUX_MSG pMUXMsg, void *arg) -{ - USHORT TLVLength = 0; - UCHAR *pTLV; - PROFILE_T *profile = (PROFILE_T *)arg; - PQMIWDS_PDPTYPE pPdpType; - - pMUXMsg->ModifyProfileSettingsReq.Length = - cpu_to_le16(sizeof(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG) - 4); - pMUXMsg->ModifyProfileSettingsReq.TLVType = 0x01; - pMUXMsg->ModifyProfileSettingsReq.TLVLength = cpu_to_le16(0x02); - pMUXMsg->ModifyProfileSettingsReq.ProfileType = - 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 - pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->pdpindex; - - pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1); - - pPdpType = (PQMIWDS_PDPTYPE)(pTLV + TLVLength); - pPdpType->TLVType = 0x11; - pPdpType->TLVLength = cpu_to_le16(0x01); - // 0 ?C PDP-IP (IPv4) - // 1 ?C PDP-PPP - // 2 ?C PDP-IPv6 - // 3 ?C PDP-IPv4v6 - if (profile->ipv6_flag && profile->ipv4_flag) - pPdpType->PdpType = 3; - else if (profile->ipv6_flag) - pPdpType->PdpType = 2; - else - pPdpType->PdpType = 0; - TLVLength += (le16_to_cpu(pPdpType->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - // Set APN Name - if (profile->apn) { - PQMIWDS_APNNAME pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength); - pApnName->TLVType = 0x14; - pApnName->TLVLength = cpu_to_le16(strlen(profile->apn)); - qstrcpy((char *)&pApnName->ApnName, profile->apn); - TLVLength += - (le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set User Name - if (profile->user) { - PQMIWDS_USERNAME pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength); - pUserName->TLVType = 0x1B; - pUserName->TLVLength = cpu_to_le16(strlen(profile->user)); - qstrcpy((char *)&pUserName->UserName, profile->user); - TLVLength += - (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Password - if (profile->password) { - PQMIWDS_PASSWD pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength); - pPasswd->TLVType = 0x1C; - pPasswd->TLVLength = cpu_to_le16(strlen(profile->password)); - qstrcpy((char *)&pPasswd->Passwd, profile->password); - TLVLength += - (le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Auth Protocol - if (profile->user && profile->password) { - PQMIWDS_AUTH_PREFERENCE pAuthPref = - (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength); - pAuthPref->TLVType = 0x1D; - pAuthPref->TLVLength = cpu_to_le16(0x01); - pAuthPref->AuthPreference = - profile->auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2 - TLVLength += - (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - return sizeof(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG) + TLVLength; -} -#endif - -static USHORT WdsGetRuntimeSettingReq(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->GetRuntimeSettingsReq.TLVType = 0x10; - pMUXMsg->GetRuntimeSettingsReq.TLVLength = cpu_to_le16(0x04); - // the following mask also applies to IPV6 - pMUXMsg->GetRuntimeSettingsReq.Mask = - cpu_to_le32(QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR); // | - // QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_SV_ADDR | - // QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_DOM_NAME; - - return sizeof(QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG); -} - -static PQCQMIMSG s_pRequest; -static PQCQMIMSG s_pResponse; -static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER; - -static int is_response(const PQCQMIMSG pRequest, const PQCQMIMSG pResponse) -{ - if ((pRequest->QMIHdr.QMIType == pResponse->QMIHdr.QMIType) && - (pRequest->QMIHdr.ClientId == pResponse->QMIHdr.ClientId)) { - USHORT requestTID, responseTID; - if (pRequest->QMIHdr.QMIType == QMUX_TYPE_CTL) { - requestTID = pRequest->CTLMsg.QMICTLMsgHdr.TransactionId; - responseTID = pResponse->CTLMsg.QMICTLMsgHdr.TransactionId; - } else { - requestTID = le16_to_cpu(pRequest->MUXMsg.QMUXHdr.TransactionId); - responseTID = le16_to_cpu(pResponse->MUXMsg.QMUXHdr.TransactionId); - } - return (requestTID == responseTID); - } - return 0; -} - -int (*qmidev_send)(PQCQMIMSG pRequest); - -int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, - unsigned msecs) -{ - int ret; - - if (!pRequest) { - return -EINVAL; - } - - pthread_mutex_lock(&s_commandmutex); - - if (ppResponse) - *ppResponse = NULL; - - dump_qmi(pRequest, le16_to_cpu(pRequest->QMIHdr.Length) + 1); - - s_pRequest = pRequest; - s_pResponse = NULL; - - ret = qmidev_send(pRequest); - - if (ret == 0) { - ret = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, msecs); - if (!ret) { - if (s_pResponse && ppResponse) { - *ppResponse = s_pResponse; - } else { - if (s_pResponse) { - free(s_pResponse); - s_pResponse = NULL; - } - } - } else { - dbg_time("%s pthread_cond_timeout_np=%d, errno: %d (%s)", __func__, - ret, errno, strerror(errno)); - } - } - - pthread_mutex_unlock(&s_commandmutex); - - return ret; -} - -int QmiThreadSendQMI(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse) -{ - return QmiThreadSendQMITimeout(pRequest, ppResponse, 30 * 1000); -} - -void QmiThreadRecvQMI(PQCQMIMSG pResponse) -{ - pthread_mutex_lock(&s_commandmutex); - if (pResponse == NULL) { - if (s_pRequest) { - free(s_pRequest); - s_pRequest = NULL; - s_pResponse = NULL; - pthread_cond_signal(&s_commandcond); - } - pthread_mutex_unlock(&s_commandmutex); - return; - } - dump_qmi(pResponse, le16_to_cpu(pResponse->QMIHdr.Length) + 1); - if (s_pRequest && is_response(s_pRequest, pResponse)) { - free(s_pRequest); - s_pRequest = NULL; - s_pResponse = malloc(le16_to_cpu(pResponse->QMIHdr.Length) + 1); - if (s_pResponse != NULL) { - memcpy(s_pResponse, pResponse, - le16_to_cpu(pResponse->QMIHdr.Length) + 1); - } - pthread_cond_signal(&s_commandcond); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_NAS) && - (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == - QMINAS_SERVING_SYSTEM_IND)) { - qmidevice_send_event_to_main( - RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_WDS) && - (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == - QMIWDS_GET_PKT_SRVC_STATUS_IND)) { - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6) && - (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == - QMIWDS_GET_PKT_SRVC_STATUS_IND)) { - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_NAS) && - (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == - QMINAS_SYS_INFO_IND)) { - qmidevice_send_event_to_main( - RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } else { - if (debug_qmi) - dbg_time("nobody care this qmi msg!!"); - } - pthread_mutex_unlock(&s_commandmutex); -} - -int requestSetEthMode(PROFILE_T *profile) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse = NULL; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV linkProto; - UCHAR IpPreference; - UCHAR autoconnect_setting = 0; - QMAP_SETTING qmap_settings = {0, 0, 0, 0}; - - if (profile->qmap_mode) { - profile->rawIP = 1; - - - qmap_settings.MuxId = profile->muxid; - - if (qmidev_is_pciemhi(profile->qmichannel)) { // SDX20_PCIE - qmap_settings.rx_urb_size = 32*1024; //SDX24&SDX55 support 32KB - qmap_settings.ep_type = DATA_EP_TYPE_PCIE; - qmap_settings.iface_id = 0x04; - } else { // for MDM9x07&MDM9x40&SDX20 USB - qmap_settings.rx_urb_size = profile->qmap_size; - //profile->qmap_size; // SDX24&SDX55 support 32KB - qmap_settings.ep_type = DATA_EP_TYPE_HSUSB; -//2021-02-08 zhangkaibo@fibocom.com changed begin for mantis 0070613 - qmap_settings.iface_id = profile->interfacenum; -//2021-02-08 zhangkaibo@fibocom.com changed end for mantis 0070613 - } - - if (qmidev_is_gobinet( - profile->qmichannel)) { // GobiNet set data format - // in GobiNet driver - goto skip_WdaSetDataFormat; - } else if (profile->qmap_mode > - 1) { // QMAP MUX enabled, set data format in fibo-qmi-proxy - -//2021-06-03 willa.liu@fibocom.com changed begin for support mantis 0079541 -//2021-01-27 willa.liu@fibocom.com changed begin for support mantis 0068849 - //goto skip_WdaSetDataFormat; - goto skip_WdaSetDataFormat; -//2021-01-27 willa.liu@fibocom.com changed end for support mantis 0068849 -//2021-06-03 willa.liu@fibocom.com changed end for support mantis 0079541 - - } - } - - pRequest = - ComposeQMUXMsg(QMUX_TYPE_WDS_ADMIN, QMIWDS_ADMIN_SET_DATA_FORMAT_REQ, - WdaSetDataFormat, (void *)&qmap_settings); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (linkProto != NULL) { - profile->rawIP = (le32_to_cpu(linkProto->Value) == 2); - } - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, 0x16); - if (linkProto != NULL && profile->qmap_mode) { - qmap_settings.rx_urb_size = le32_to_cpu(linkProto->Value); - dbg_time( - "qmap_settings.rx_urb_size = %d", - qmap_settings.rx_urb_size); // must same as rx_urb_size defined - // in GobiNet&qmi_wwan driver - } - - free(pResponse); - -skip_WdaSetDataFormat: -//bind v4 client - // set ipv4 - if(profile->ipv4_flag) - { -/* IpPreference = IpFamilyV4; - pRequest = - ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, - WdsSetClientIPFamilyPref, (void *)&IpPreference); - err = QmiThreadSendQMI(pRequest, &pResponse); - if (pResponse) - free(pResponse); -*/ - if (profile->qmapnet_adapter) { - // bind wds mux data port - pRequest = ComposeQMUXMsg( - QMUX_TYPE_WDS, QMIWDS_BIND_MUX_DATA_PORT_REQ, - WdsSetQMUXBindMuxDataPort, (void *)&qmap_settings); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) - free(pResponse); - } -// set auto connect - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_SET_AUTO_CONNECT_REQ, - WdsSetAutoConnect, (void *)&autoconnect_setting); - QmiThreadSendQMI(pRequest, &pResponse); - if (pResponse) - free(pResponse); - } - -//bind v6 client - if(profile->ipv6_flag) - { - IpPreference = IpFamilyV6; - pRequest = ComposeQMUXMsg( - QMUX_TYPE_WDS_IPV6, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, - WdsSetClientIPFamilyPref, (void *)&IpPreference); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) - free(pResponse); - - if (profile->qmapnet_adapter) { - // bind wds mux data port - pRequest = ComposeQMUXMsg( - QMUX_TYPE_WDS_IPV6, QMIWDS_BIND_MUX_DATA_PORT_REQ, - WdsSetQMUXBindMuxDataPort, (void *)&qmap_settings); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) - free(pResponse); - } - IpPreference = IpFamilyV6; - pRequest = ComposeQMUXMsg( - QMUX_TYPE_WDS_IPV6, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, - WdsSetClientIPFamilyPref, (void *)&IpPreference); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) - free(pResponse); - -// set auto connect - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_IPV6, QMIWDS_SET_AUTO_CONNECT_REQ, - WdsSetAutoConnect, (void *)&autoconnect_setting); - QmiThreadSendQMI(pRequest, &pResponse); - if (pResponse) - free(pResponse); - } - return 0; -} - -#ifdef CONFIG_SIM -int requestGetPINStatus(SIM_Status *pSIMStatus) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIDMS_UIM_PIN_STATUS pPin1Status = NULL; - // PQMIDMS_UIM_PIN_STATUS pPin2Status = NULL; - - - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_GET_CARD_STATUS_REQ, - NULL, NULL); - - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pPin1Status = - (PQMIDMS_UIM_PIN_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - // pPin2Status = - // (PQMIDMS_UIM_PIN_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - - if (pPin1Status != NULL) { - if (pPin1Status->PINStatus == QMI_PIN_STATUS_NOT_VERIF) { - *pSIMStatus = SIM_PIN; - } else if (pPin1Status->PINStatus == QMI_PIN_STATUS_BLOCKED) { - *pSIMStatus = SIM_PUK; - } else if (pPin1Status->PINStatus == QMI_PIN_STATUS_PERM_BLOCKED) { - *pSIMStatus = SIM_BAD; - } - } - - free(pResponse); - return 0; -} - -static int requestGetSIMMode(PROFILE_T *profile) -{ - int i; - int fd; - int ret; - int len; - char buffer[1024] = {0}; - char *sendbuffer = "AT+GTDUALSIMEN?"; - int totallen = 0; - fd_set readfds; - struct timeval timeout; - struct termios tiosfd, tio; - int timeoutVal = 5; - char *dev = NULL; - if(qmidev_is_gobinet(profile->qmichannel)) - { - dev = "/dev/ttyUSB1"; //The port under Linux is operated by opening the device file - } - else - { - dev = "/dev/mhi_DUN"; //The port under Linux is operated by opening the device file - } - - fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); - if(fd < 0) - goto ERR; - fcntl(fd, F_SETFL, O_RDWR); - xget1(fd, &tio, &tiosfd); - - if(xset1(fd, &tio, dev)) - goto ERR; - - tcflush(fd, TCIOFLUSH); - - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - - sprintf(buffer, "%s\r", sendbuffer); - ret = write (fd, buffer, strlen(buffer)); - if(ret < 0) - { - dbg_time("write failed\n"); - goto ERR; - } - dbg_time("dev: %s\nsendbuffer:%s\n", dev, sendbuffer); - sleep(3); - - while(1) - { - timeout.tv_sec = timeoutVal; - timeout.tv_usec = 0; - - ret = select(fd+1, &readfds, (fd_set *)0, (fd_set *)0, &timeout); - if(ret > 0) - { - ret = read(fd, buffer+totallen, sizeof(buffer)-totallen-1); - if(ret < 0) - { - dbg_time("read failed\n"); - goto ERR; - } - - if(ret == 0) - { - goto ERR; - } - - totallen += ret; - buffer[totallen] = '\0'; - dbg_time("read %d %s", ret, &buffer[totallen-ret]); - -//current buffer is return value - if(strstr(buffer, "+GTDUALSIMEN: 1")) - { - close(fd); - dbg_time("read 1\n"); - return 1; - } - else - { - close(fd); - dbg_time("read 0/2/3\n"); - return 0; - } - } - else - { - dbg_time("select timeout\n"); - goto ERR; - } - - } - - close(fd); - -ERR: - if(fd > 0) - close(fd); - return -1; -} - - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -int requestGetSIMCardNumber(PROFILE_T *profile) -{ - int i; - int fd; - int ret; - int len; - char buffer[1024] = {0}; - int rate; - char *sendbuffer; - int totallen = 0; - fd_set readfds; - struct timeval timeout; - struct termios tiosfd, tio; - int timeoutVal = 5; - char *dev = NULL; - if(qmidev_is_gobinet(profile->qmichannel)) - { - dev = "/dev/ttyUSB1"; //The port under Linux is operated by opening the device file - } - else - { - dev = "/dev/mhi_DUN"; //The port under Linux is operated by opening the device file - } - rate = 115200; - sendbuffer = "AT+GTDUALSIM?"; - if(requestGetSIMMode(profile) != 1) - { - return 0; - } - fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); - if(fd < 0) - goto ERR; - fcntl(fd, F_SETFL, O_RDWR); - xget1(fd, &tio, &tiosfd); - - if(xset1(fd, &tio, dev)) - goto ERR; - - tcflush(fd, TCIOFLUSH); - - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - - sprintf(buffer, "%s\r", sendbuffer); - ret = write (fd, buffer, strlen(buffer)); - if(ret < 0) - { - dbg_time("write failed\n"); - goto ERR; - } - dbg_time("dev: %s\nrate:%d\nsendbuffer:%s\n", dev, rate, sendbuffer); - sleep(3); - goto read_result; - while(1) - { - timeout.tv_sec = timeoutVal; - timeout.tv_usec = 0; - - //ret = select(fd+1, &readfds, (fd_set *)0, (fd_set *)0, &timeout); - //if(ret > 0) - { - read_result: - ret = read(fd, buffer+totallen, sizeof(buffer)-totallen-1); - if(ret < 0) - { - dbg_time("read failed\n"); - goto ERR; - } - - if(ret == 0) - { - goto ERR; - } - - totallen += ret; - buffer[totallen] = '\0'; - dbg_time("read %d %s", ret, &buffer[totallen-ret]); - -//current buffer is return value - if(strstr(buffer, "+GTDUALSIM: 0")) - { - close(fd); - dbg_time("read 0\n"); - return 0; - } - else if(strstr(buffer, "+GTDUALSIM: 1")) - { - close(fd); - dbg_time("read 1\n"); - return 1; - } - else - continue; - } - //else - { - //dbg_time("select timeout\n"); - //goto ERR; - } - - } - - close(fd); - -ERR: - if(fd > 0) - close(fd); - return -1; -} - -int requestSimBindSubscription_NAS_WMS() -{ - PQCQMIMSG pRequest_nas; - PQCQMIMSG pResponse_nas; - int err; - - pRequest_nas = ComposeQMUXMsg(QMUX_TYPE_NAS, QMI_NAS_BIND_SUBSCRIPTION_REQ_V01, - UimBindPinReqSend_NAS_WMS, NULL); - err = QmiThreadSendQMI(pRequest_nas, &pResponse_nas); - free(pResponse_nas); - - return 0; -} - -int requestSimBindSubscription_WDS_DMS_QOS() -{ - PQCQMIMSG pRequest_wds; - PQCQMIMSG pRequest_dms; - - PQCQMIMSG pResponse_wds; - PQCQMIMSG pResponse_dms; - int err; - - pRequest_wds = ComposeQMUXMsg(QMUX_TYPE_WDS, QMI_WDS_BIND_SUBSCRIPTION_REQ_V01, - UimBindPinReqSend_WDS_DMS_QOS, NULL); - err = QmiThreadSendQMI(pRequest_wds, &pResponse_wds); - - pRequest_dms = ComposeQMUXMsg(QMUX_TYPE_DMS, QMI_DMS_BIND_SUBSCRIPTION_REQ_V01, - UimBindPinReqSend_WDS_DMS_QOS, NULL); - err = QmiThreadSendQMI(pRequest_dms, &pResponse_dms); - - free(pResponse_wds); - free(pResponse_dms); - - return 0; -} - -//int requestGetSIMStatus(SIM_Status *pSIMStatus) -int requestGetSIMStatus(SIM_Status *pSIMStatus, const int sim_select) -{ // RIL_REQUEST_GET_SIM_STATUS - int i; - dbg_time("sim_select = %d\n", sim_select); - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - const char *SIM_Status_String[] = { - "SIM_ABSENT", - "SIM_NOT_READY", - "SIM_READY", /* SIM_READY means the radio state is RADIO_STATE_SIM_READY - */ - "SIM_PIN", - "SIM_PUK", - "SIM_NETWORK_PERSONALIZATION"}; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_GET_CARD_STATUS_REQ, - NULL, NULL); - - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - *pSIMStatus = SIM_ABSENT; - PQMIUIM_CARD_STATUS pCardStatus = NULL; - PQMIUIM_PIN_STATE pPINState = NULL; - UCHAR CardState = 0x01; - UCHAR PIN1State = QMI_PIN_STATUS_NOT_VERIF; - // UCHAR PIN1Retries; - // UCHAR PUK1Retries; - // UCHAR PIN2State; - // UCHAR PIN2Retries; - // UCHAR PUK2Retries; - - void *temp = NULL; - QMIUIM_APP_STATUS * curr_app = NULL; - Instance * curr_ints = NULL; - - pCardStatus = - (PQMIUIM_CARD_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if(sim_select == 0) - { - temp =(void*)pCardStatus + sizeof(QMIUIM_CARD_STATUS); - curr_ints = temp; - dbg_time("curr_ints_sim1 %s", curr_ints); - temp = temp + sizeof(Instance); - curr_app = temp; - } - else - { - temp = (void*)pCardStatus + sizeof(QMIUIM_CARD_STATUS); - temp = temp + sizeof(Instance) + (sizeof(QMIUIM_APP_STATUS)*(((Instance *)temp)->NumApp)); - curr_ints = temp; - dbg_time("curr_ints_sim2 %s", curr_ints); - curr_app = temp + sizeof(Instance); - } -/* - if (pCardStatus != NULL) { - - for (i = 0; i < pCardStatus->NumApp; i++) { - if (pCardStatus->AppStatus[i].AppType == 2) { - pPINState = &(pCardStatus->AppStatus[i].PinState); - break; - } - } - if (i == pCardStatus->NumApp) { - dbg_time("no USIM Card info"); - return -1; - } - - CardState = pCardStatus->CardState; - if (pPINState->UnivPIN == 1) { - PIN1State = pCardStatus->UPINState; -*/ - if (curr_ints != NULL) { - dbg_time("curr_ints->CardState is %d", curr_ints->CardState); - dbg_time("curr_ints->NumApp is %d", curr_ints->NumApp); - for (i = 0; i < curr_ints->NumApp; i++) { - dbg_time("AppType = %d\n", curr_app[i].AppType); - if (curr_app[i].AppType == 2) { - pPINState = &(curr_app[i].PinState); - break; - } - } - if (i == curr_ints->NumApp) { - dbg_time("no USIM Card info"); - return -1; - } - - //CardState = pCardStatus->CardState; - CardState = curr_ints->CardState; - if (pPINState->UnivPIN == 1) { - PIN1State = curr_ints->UPINState; - // PIN1Retries = pCardStatus->UPINRetries; - // PUK1Retries = pCardStatus->UPUKRetries; - } else { - PIN1State = pPINState->PIN1State; - // PIN1Retries = pPINState->PIN1Retries; - // PUK1Retries = pPINState->PUK1Retries; - } - // PIN2State = pPINState->PIN2State; - // PIN2Retries = pPINState->PIN2Retries; - // PUK2Retries = pPINState->PUK2Retries; - } -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - *pSIMStatus = SIM_ABSENT; - if ((CardState == 0x01) && ((PIN1State == QMI_PIN_STATUS_VERIFIED) || - (PIN1State == QMI_PIN_STATUS_DISABLED))) { - *pSIMStatus = SIM_READY; - } else if (CardState == 0x01) { - if (PIN1State == QMI_PIN_STATUS_NOT_VERIF) { - *pSIMStatus = SIM_PIN; - } - if (PIN1State == QMI_PIN_STATUS_BLOCKED) { - *pSIMStatus = SIM_PUK; - } else if (PIN1State == QMI_PIN_STATUS_PERM_BLOCKED) { - *pSIMStatus = SIM_BAD; - } else if (PIN1State == QMI_PIN_STATUS_NOT_INIT || - PIN1State == QMI_PIN_STATUS_VERIFIED || - PIN1State == QMI_PIN_STATUS_DISABLED) { - *pSIMStatus = SIM_READY; - } - } else if (CardState == 0x00 || CardState == 0x02) { - } else { - } - - dbg_time("%s SIMStatus: %s", __func__, SIM_Status_String[*pSIMStatus]); - - free(pResponse); - - return 0; -} - -int requestEnterSimPin(const CHAR *pPinCode) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_VERIFY_PIN_REQ, - UimVerifyPinReqSend, (void *)pPinCode); - - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - free(pResponse); - return 0; -} - -#ifdef CONFIG_IMSI_ICCID -int requestGetICCID(void) -{ // RIL_REQUEST_GET_IMSI - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PQMIUIM_CONTENT pUimContent; - int err; - - pRequest = - ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_READ_TRANSPARENT_REQ, - UimReadTransparentIMSIReqSend, (void *)"EF_ICCID"); - err = QmiThreadSendQMI(pRequest, &pResponse); - - - qmi_rsp_check_and_return(); - - pUimContent = (PQMIUIM_CONTENT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pUimContent != NULL) { - static char DeviceICCID[32] = {'\0'}; - int i = 0, j = 0; - - for (i = 0, j = 0; i < le16_to_cpu(pUimContent->content_len); ++i) { - char charmaps[] = "0123456789ABCDEF"; - - DeviceICCID[j++] = charmaps[(pUimContent->content[i] & 0x0F)]; - DeviceICCID[j++] = - charmaps[((pUimContent->content[i] & 0xF0) >> 0x04)]; - } - DeviceICCID[j] = '\0'; - - dbg_time("%s DeviceICCID: %s", __func__, DeviceICCID); - } - - free(pResponse); - return 0; -} - -int requestGetIMSI(void) -{ // RIL_REQUEST_GET_IMSI - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PQMIUIM_CONTENT pUimContent; - int err; - - pRequest = - ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_READ_TRANSPARENT_REQ, - UimReadTransparentIMSIReqSend, (void *)"EF_IMSI"); - err = QmiThreadSendQMI(pRequest, &pResponse); - - - qmi_rsp_check_and_return(); - - pUimContent = (PQMIUIM_CONTENT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pUimContent != NULL) { - static char DeviceIMSI[32] = {'\0'}; - int i = 0, j = 0; - - for (i = 0, j = 0; i < le16_to_cpu(pUimContent->content[0]); ++i) { - if (i != 0) - DeviceIMSI[j++] = (pUimContent->content[i + 1] & 0x0F) + '0'; - DeviceIMSI[j++] = - ((pUimContent->content[i + 1] & 0xF0) >> 0x04) + '0'; - } - DeviceIMSI[j] = '\0'; - - dbg_time("%s DeviceIMSI: %s", __func__, DeviceIMSI); - } - - free(pResponse); - return 0; -} -#endif -#endif - -static void fibo_convert_cdma_mcc_2_ascii_mcc(USHORT *p_mcc, USHORT mcc) -{ - unsigned int d1, d2, d3, buf = mcc + 111; - - if (mcc == 0x3FF) // wildcard - { - *p_mcc = 3; - } else { - d3 = buf % 10; - buf = (d3 == 0) ? (buf - 10) / 10 : buf / 10; - - d2 = buf % 10; - buf = (d2 == 0) ? (buf - 10) / 10 : buf / 10; - - d1 = (buf == 10) ? 0 : buf; - - // dbg_time("d1:%d, d2:%d,d3:%d",d1,d2,d3); - if (d1 < 10 && d2 < 10 && d3 < 10) { - *p_mcc = d1 * 100 + d2 * 10 + d3; - } else { - // dbg_time( "invalid digits %d %d %d", d1, d2, d3 ); - *p_mcc = 0; - } - } -} - -static void fibo_convert_cdma_mnc_2_ascii_mnc(USHORT *p_mnc, USHORT imsi_11_12) -{ - unsigned int d1, d2, buf = imsi_11_12 + 11; - - if (imsi_11_12 == 0x7F) // wildcard - { - *p_mnc = 7; - } else { - d2 = buf % 10; - buf = (d2 == 0) ? (buf - 10) / 10 : buf / 10; - - d1 = (buf == 10) ? 0 : buf; - - if (d1 < 10 && d2 < 10) { - *p_mnc = d1 * 10 + d2; - } else { - // dbg_time( "invalid digits %d %d", d1, d2, 0 ); - *p_mnc = 0; - } - } -} - -int requestGetHomeNetwork(USHORT *p_mcc, USHORT *p_mnc, USHORT *p_sid, - USHORT *p_nid) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PHOME_NETWORK pHomeNetwork; - PHOME_NETWORK_SYSTEMID pHomeNetworkSystemID; - - pRequest = - ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_HOME_NETWORK_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pHomeNetwork = (PHOME_NETWORK)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (pHomeNetwork && p_mcc && p_mnc) { - *p_mcc = le16_to_cpu(pHomeNetwork->MobileCountryCode); - *p_mnc = le16_to_cpu(pHomeNetwork->MobileNetworkCode); - // dbg_time("%s MobileCountryCode: %d, MobileNetworkCode: %d", __func__, - // *pMobileCountryCode, *pMobileNetworkCode); - } - - pHomeNetworkSystemID = - (PHOME_NETWORK_SYSTEMID)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if (pHomeNetworkSystemID && p_sid && p_nid) { - *p_sid = le16_to_cpu( - pHomeNetworkSystemID->SystemID); // china-hefei: sid 14451 - *p_nid = le16_to_cpu(pHomeNetworkSystemID->NetworkID); - // dbg_time("%s SystemID: %d, NetworkID: %d", __func__, *pSystemID, - // *pNetworkID); - } - - free(pResponse); - - return 0; -} - -struct wwan_data_class_str class2str[] = { - {WWAN_DATA_CLASS_NONE, "UNKNOWN"}, - {WWAN_DATA_CLASS_GPRS, "GPRS"}, - {WWAN_DATA_CLASS_EDGE, "EDGE"}, - {WWAN_DATA_CLASS_UMTS, "UMTS"}, - {WWAN_DATA_CLASS_HSDPA, "HSDPA"}, - {WWAN_DATA_CLASS_HSUPA, "HSUPA"}, - {WWAN_DATA_CLASS_LTE, "LTE"}, - {WWAN_DATA_CLASS_1XRTT, "1XRTT"}, - {WWAN_DATA_CLASS_1XEVDO, "1XEVDO"}, - {WWAN_DATA_CLASS_1XEVDO_REVA, "1XEVDO_REVA"}, - {WWAN_DATA_CLASS_1XEVDV, "1XEVDV"}, - {WWAN_DATA_CLASS_3XRTT, "3XRTT"}, - {WWAN_DATA_CLASS_1XEVDO_REVB, "1XEVDO_REVB"}, - {WWAN_DATA_CLASS_UMB, "UMB"}, - {WWAN_DATA_CLASS_CUSTOM, "CUSTOM"}, -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - {WWAN_DATA_CLASS_5G, "NR5G"}, -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 -}; - -CHAR *wwan_data_class2str(ULONG class) -{ - unsigned int i = 0; - for (i = 0; i < sizeof(class2str) / sizeof(class2str[0]); i++) { - if (class2str[i].class == class) { - return class2str[i].str; - } - } - return "UNKNOWN"; -} - -int requestRegistrationState2(UCHAR *pPSAttachedState) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - USHORT MobileCountryCode = 0; - USHORT MobileNetworkCode = 0; - const char *pDataCapStr = "UNKNOW"; - LONG remainingLen; - PSERVICE_STATUS_INFO pServiceStatusInfo; - int is_lte = 0; - PCDMA_SYSTEM_INFO pCdmaSystemInfo; - PHDR_SYSTEM_INFO pHdrSystemInfo; - PGSM_SYSTEM_INFO pGsmSystemInfo; - PWCDMA_SYSTEM_INFO pWcdmaSystemInfo; - PLTE_SYSTEM_INFO pLteSystemInfo; -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - PNR5G_SYSTEM_INFO pNr5gSystemInfo; -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - PTDSCDMA_SYSTEM_INFO pTdscdmaSystemInfo; - UCHAR DeviceClass = 0; - ULONG DataCapList = 0; - - *pPSAttachedState = 0; - pRequest = - ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SYS_INFO_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pServiceStatusInfo = (PSERVICE_STATUS_INFO)( - ((PCHAR)&pMUXMsg->GetSysInfoResp) + QCQMUX_MSG_HDR_SIZE); - remainingLen = le16_to_cpu(pMUXMsg->GetSysInfoResp.Length); - - s_is_cdma = 0; - s_hdr_personality = 0; - while (remainingLen > 0) { - switch (pServiceStatusInfo->TLVType) { - case 0x10: // CDMA - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_1XRTT | WWAN_DATA_CLASS_1XEVDO | - WWAN_DATA_CLASS_1XEVDO_REVA | - WWAN_DATA_CLASS_1XEVDV | - WWAN_DATA_CLASS_1XEVDO_REVB; - DeviceClass = DEVICE_CLASS_CDMA; - s_is_cdma = (0 == is_lte); - } - break; - case 0x11: // HDR - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_3XRTT | WWAN_DATA_CLASS_UMB; - DeviceClass = DEVICE_CLASS_CDMA; - s_is_cdma = (0 == is_lte); - } - break; - case 0x12: // GSM - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_GPRS | WWAN_DATA_CLASS_EDGE; - DeviceClass = DEVICE_CLASS_GSM; - } - break; - case 0x13: // WCDMA - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_UMTS; - DeviceClass = DEVICE_CLASS_GSM; - } - break; -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - case 0x4A: // NR5G - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_5G; - DeviceClass = DEVICE_CLASS_GSM; - is_lte = 1; - s_is_cdma = 0; - } - break; -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - case 0x14: // LTE - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_LTE; - DeviceClass = DEVICE_CLASS_GSM; - is_lte = 1; - s_is_cdma = 0; - } - break; - case 0x24: // TDSCDMA - if (pServiceStatusInfo->SrvStatus == 0x02) { - pDataCapStr = "TD-SCDMA"; - } - break; - case 0x15: // CDMA - // CDMA_SYSTEM_INFO - pCdmaSystemInfo = (PCDMA_SYSTEM_INFO)pServiceStatusInfo; - if (pCdmaSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pCdmaSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#if 0 - if (pCdmaSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pCdmaSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#endif - if (pCdmaSystemInfo->NetworkIdValid == 0x01) { - int i; - CHAR temp[10]; - strncpy(temp, (CHAR *)pCdmaSystemInfo->MCC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileCountryCode = (USHORT)atoi(temp); - - strncpy(temp, (CHAR *)pCdmaSystemInfo->MNC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileNetworkCode = (USHORT)atoi(temp); - } - break; - case 0x16: // HDR - // HDR_SYSTEM_INFO - pHdrSystemInfo = (PHDR_SYSTEM_INFO)pServiceStatusInfo; - if (pHdrSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pHdrSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#if 0 - if (pHdrSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pHdrSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#endif - if (*pPSAttachedState && - pHdrSystemInfo->HdrPersonalityValid == 0x01) { - if (pHdrSystemInfo->HdrPersonality == 0x03) - s_hdr_personality = 0x02; - // else if (pHdrSystemInfo->HdrPersonality == 0x02) - // s_hdr_personality = 0x01; - } - USHORT cmda_mcc = 0, cdma_mnc = 0; - if (!requestGetHomeNetwork(&cmda_mcc, &cdma_mnc, NULL, NULL) && - cmda_mcc) { - fibo_convert_cdma_mcc_2_ascii_mcc(&MobileCountryCode, cmda_mcc); - fibo_convert_cdma_mnc_2_ascii_mnc(&MobileNetworkCode, cdma_mnc); - } - break; - case 0x17: // GSM - // GSM_SYSTEM_INFO - pGsmSystemInfo = (PGSM_SYSTEM_INFO)pServiceStatusInfo; - if (pGsmSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pGsmSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - } - } -#if 0 - if (pGsmSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pGsmSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - } - } -#endif - if (pGsmSystemInfo->NetworkIdValid == 0x01) { - int i; - CHAR temp[10]; - strncpy(temp, (CHAR *)pGsmSystemInfo->MCC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileCountryCode = (USHORT)atoi(temp); - - strncpy(temp, (CHAR *)pGsmSystemInfo->MNC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileNetworkCode = (USHORT)atoi(temp); - } - break; - case 0x18: // WCDMA - // WCDMA_SYSTEM_INFO - pWcdmaSystemInfo = (PWCDMA_SYSTEM_INFO)pServiceStatusInfo; - if (pWcdmaSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pWcdmaSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - } - } -#if 0 - if (pWcdmaSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pWcdmaSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - } - } -#endif - if (pWcdmaSystemInfo->NetworkIdValid == 0x01) { - int i; - CHAR temp[10]; - strncpy(temp, (CHAR *)pWcdmaSystemInfo->MCC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileCountryCode = (USHORT)atoi(temp); - - strncpy(temp, (CHAR *)pWcdmaSystemInfo->MNC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileNetworkCode = (USHORT)atoi(temp); - } - break; - case 0x19: // LTE_SYSTEM_INFO - // LTE_SYSTEM_INFO - pLteSystemInfo = (PLTE_SYSTEM_INFO)pServiceStatusInfo; - if (pLteSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pLteSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - is_lte = 1; - s_is_cdma = 0; - } - } -#if 0 - if (pLteSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pLteSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - is_lte = 1; - s_is_cdma = 0; - } - } -#endif - if (pLteSystemInfo->NetworkIdValid == 0x01) { - int i; - CHAR temp[10]; - strncpy(temp, (CHAR *)pLteSystemInfo->MCC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileCountryCode = (USHORT)atoi(temp); - - strncpy(temp, (CHAR *)pLteSystemInfo->MNC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileNetworkCode = (USHORT)atoi(temp); - } - break; -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - case 0x4b: // NR5G_SYSTEM_INFO - // NR5G_SYSTEM_INFO - pNr5gSystemInfo = (PNR5G_SYSTEM_INFO)pServiceStatusInfo; - if (pNr5gSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pNr5gSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - is_lte = 1; - s_is_cdma = 0; - } - } - - if (pNr5gSystemInfo->NetworkIdValid == 0x01) { - int i; - CHAR temp[10]; - strncpy(temp, (CHAR *)pNr5gSystemInfo->MCC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileCountryCode = (USHORT)atoi(temp); - - strncpy(temp, (CHAR *)pNr5gSystemInfo->MNC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileNetworkCode = (USHORT)atoi(temp); - } - break; -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - case 0x25: // TDSCDMA - // TDSCDMA_SYSTEM_INFO - pTdscdmaSystemInfo = (PTDSCDMA_SYSTEM_INFO)pServiceStatusInfo; - if (pTdscdmaSystemInfo->SrvDomainValid == 0x01) { - *pPSAttachedState = 0; - if (pTdscdmaSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - } - } -#if 0 - if (pTdscdmaSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pTdscdmaSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - } - } -#endif - if (pTdscdmaSystemInfo->NetworkIdValid == 0x01) { - int i; - CHAR temp[10]; - strncpy(temp, (CHAR *)pTdscdmaSystemInfo->MCC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileCountryCode = (USHORT)atoi(temp); - - strncpy(temp, (CHAR *)pTdscdmaSystemInfo->MNC, 3); - temp[3] = '\0'; - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - MobileNetworkCode = (USHORT)atoi(temp); - } - break; - default: - break; - } /* switch (pServiceStatusInfo->TLYType) */ - remainingLen -= (le16_to_cpu(pServiceStatusInfo->TLVLength) + 3); - pServiceStatusInfo = (PSERVICE_STATUS_INFO)( - (PCHAR)&pServiceStatusInfo->TLVLength + - le16_to_cpu(pServiceStatusInfo->TLVLength) + sizeof(USHORT)); - } /* while (remainingLen > 0) */ - - if (DeviceClass == DEVICE_CLASS_CDMA) { - if (s_hdr_personality == 2) { - pDataCapStr = s_hdr_personality == 2 ? "eHRPD" : "HRPD"; - } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO_REVB) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO_REVB); - } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO_REVA) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO_REVA); - } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO); - } else if (DataCapList & WWAN_DATA_CLASS_1XRTT) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XRTT); - } else if (DataCapList & WWAN_DATA_CLASS_3XRTT) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_3XRTT); - } else if (DataCapList & WWAN_DATA_CLASS_UMB) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_UMB); - } - } else { - if (DataCapList & WWAN_DATA_CLASS_LTE) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_LTE); - } else if ((DataCapList & WWAN_DATA_CLASS_HSDPA) && - (DataCapList & WWAN_DATA_CLASS_HSUPA)) { - pDataCapStr = "HSDPA_HSUPA"; - } else if (DataCapList & WWAN_DATA_CLASS_HSDPA) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_HSDPA); - } else if (DataCapList & WWAN_DATA_CLASS_HSUPA) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_HSUPA); - } else if (DataCapList & WWAN_DATA_CLASS_UMTS) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_UMTS); - } else if (DataCapList & WWAN_DATA_CLASS_EDGE) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_EDGE); - } else if (DataCapList & WWAN_DATA_CLASS_GPRS) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_GPRS); -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - } else if (DataCapList & WWAN_DATA_CLASS_5G) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_5G); -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - } - } - g_MobileCountryCode = MobileCountryCode; - g_MobileNetworkCode = MobileNetworkCode; - dbg_time("%s MCC: %d, MNC: %d, PS: %s, DataCap: %s", __func__, - MobileCountryCode, MobileNetworkCode, - (*pPSAttachedState == 1) ? "Attached" : "Detached", pDataCapStr); - - free(pResponse); - - return 0; -} - -int requestRegistrationState(UCHAR *pPSAttachedState) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMINAS_CURRENT_PLMN_MSG pCurrentPlmn; - PSERVING_SYSTEM pServingSystem; - PQMINAS_DATA_CAP pDataCap; - USHORT MobileCountryCode = 0; - USHORT MobileNetworkCode = 0; - const char *pDataCapStr = "UNKNOW"; -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - /* - for 9x07 later, QMINAS_GET_SERVING_SYSTEM_REQ has been declara as Deprecated - so sdx55 NR5G register info can not get by QMINAS_GET_SERVING_SYSTEM_REQ. - coninue use QMINAS_GET_SERVING_SYSTEM_REQ, fibocom-dial will show network as UNKNOWN - */ - //begin modified by zhaofei delete incorrect registration interface on x55/x24 platform. 20200603 -// #if 0 -// if (s_9x07) { -//eturn requestRegistrationState2(pPSAttachedState); -// } -// #endif - //end modified by zhaofei delete incorrect registration interface on x55/x24 platform.20200603 -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SERVING_SYSTEM_REQ, - NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pCurrentPlmn = - (PQMINAS_CURRENT_PLMN_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - if (pCurrentPlmn) { - MobileCountryCode = le16_to_cpu(pCurrentPlmn->MobileCountryCode); - MobileNetworkCode = le16_to_cpu(pCurrentPlmn->MobileNetworkCode); - } - - *pPSAttachedState = 0; - pServingSystem = - (PSERVING_SYSTEM)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (pServingSystem) { - // Packet-switched domain attach state of the mobile. - // 0x00 PS_UNKNOWN ?Unknown or not applicable - // 0x01 PS_ATTACHED ?Attached - // 0x02 PS_DETACHED ?Detached - *pPSAttachedState = pServingSystem->RegistrationState; - if (pServingSystem->RegistrationState == - 0x01) // 0x01 ?C REGISTERED ?C Registered with a network - *pPSAttachedState = pServingSystem->PSAttachedState; - else { - // MobileCountryCode = MobileNetworkCode = 0; - *pPSAttachedState = 0x02; - } - } - - pDataCap = (PQMINAS_DATA_CAP)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pDataCap && pDataCap->DataCapListLen) { - UCHAR *DataCap = &pDataCap->DataCap; - if (pDataCap->DataCapListLen == 2) { - if ((DataCap[0] == 0x06) && - ((DataCap[1] == 0x08) || (DataCap[1] == 0x0A))) - DataCap[0] = DataCap[1]; - } - switch (DataCap[0]) { - case 0x01: - pDataCapStr = "GPRS"; - break; - case 0x02: - pDataCapStr = "EDGE"; - break; - case 0x03: - pDataCapStr = "HSDPA"; - break; - case 0x04: - pDataCapStr = "HSUPA"; - break; - case 0x05: - pDataCapStr = "UMTS"; - break; - case 0x06: - pDataCapStr = "1XRTT"; - break; - case 0x07: - pDataCapStr = "1XEVDO"; - break; - case 0x08: - pDataCapStr = "1XEVDO_REVA"; - break; - case 0x09: - pDataCapStr = "GPRS"; - break; - case 0x0A: - pDataCapStr = "1XEVDO_REVB"; - break; - case 0x0B: - pDataCapStr = "LTE"; - break; - case 0x0C: - pDataCapStr = "HSDPA"; - break; - case 0x0D: - pDataCapStr = "HSDPA"; - break; - default: - pDataCapStr = "UNKNOW"; - break; - } - } - - if (pServingSystem && pServingSystem->RegistrationState == 0x01 && - pServingSystem->InUseRadioIF && pServingSystem->RadioIF == 0x09) { - pDataCapStr = "TD-SCDMA"; - } - - s_is_cdma = 0; - if (pServingSystem && pServingSystem->RegistrationState == 0x01 && - pServingSystem->InUseRadioIF && - (pServingSystem->RadioIF == 0x01 || pServingSystem->RadioIF == 0x02)) { - USHORT cmda_mcc = 0, cdma_mnc = 0; - s_is_cdma = 1; - if (!requestGetHomeNetwork(&cmda_mcc, &cdma_mnc, NULL, NULL) && - cmda_mcc) { - fibo_convert_cdma_mcc_2_ascii_mcc(&MobileCountryCode, cmda_mcc); - fibo_convert_cdma_mnc_2_ascii_mnc(&MobileNetworkCode, cdma_mnc); - } - if (1) { - PQCQMUX_TLV pTLV = - (PQCQMUX_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x23); - if (pTLV) - s_hdr_personality = pTLV->Value; - else - s_hdr_personality = 0; - if (s_hdr_personality == 2) - pDataCapStr = "eHRPD"; - } - } - - dbg_time("%s MCC: %d, MNC: %d, PS: %s, DataCap: %s", __func__, - MobileCountryCode, MobileNetworkCode, - (*pPSAttachedState == 1) ? "Attached" : "Detached", pDataCapStr); - - free(pResponse); - - return 0; -} - -int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_PKT_SRVC_TLV pPktSrvc; - UCHAR oldConnectionStatus = *pConnectionStatus; - UCHAR QMIType = - (curIpFamily == IpFamilyV4) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - - pRequest = - ComposeQMUXMsg(QMIType, QMIWDS_GET_PKT_SRVC_STATUS_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - pPktSrvc = - (PQMIWDS_PKT_SRVC_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (pPktSrvc) { - *pConnectionStatus = pPktSrvc->ConnectionStatus; - if ((le16_to_cpu(pPktSrvc->TLVLength) == 2) && - (pPktSrvc->ReconfigReqd == 0x01)) - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - - if (*pConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) { - if (curIpFamily == IpFamilyV4) - WdsConnectionIPv4Handle = 0; - else - WdsConnectionIPv6Handle = 0; - } - - if (oldConnectionStatus != *pConnectionStatus || debug_qmi) { - dbg_time("%s %sConnectionStatus: %s", __func__, - (curIpFamily == IpFamilyV4) ? "IPv4" : "IPv6", - (*pConnectionStatus == QWDS_PKT_DATA_CONNECTED) - ? "CONNECTED" - : "DISCONNECTED"); - } - - free(pResponse); - return 0; -} - -int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err = 0; - UCHAR QMIType = - (curIpFamily == IpFamilyV4) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - - // DualIPSupported means can get ipv4 & ipv6 address at the same time, one - // wds for ipv4, the other wds for ipv6 - profile->curIpFamily = curIpFamily; - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_START_NETWORK_INTERFACE_REQ, - WdsStartNwInterfaceReq, profile); - err = QmiThreadSendQMITimeout(pRequest, &pResponse, 120 * 1000); - qmi_rsp_check(); - - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { - PQMI_TLV_HDR pTLVHdr; - - pTLVHdr = GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if (pTLVHdr) { - uint16_t *data16 = (uint16_t *)(pTLVHdr + 1); - uint16_t call_end_reason = le16_to_cpu(data16[0]); - dbg_time("call_end_reason is %d", call_end_reason); - } - - pTLVHdr = GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pTLVHdr) { - uint16_t *data16 = (uint16_t *)(pTLVHdr + 1); - uint16_t call_end_reason_type = le16_to_cpu(data16[0]); - uint16_t verbose_call_end_reason = le16_to_cpu(data16[1]); - - dbg_time("call_end_reason_type is %d", call_end_reason_type); - dbg_time("call_end_reason_verbose is %d", verbose_call_end_reason); - } - - free(pResponse); - return le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); - } - - if (curIpFamily == IpFamilyV4) { - WdsConnectionIPv4Handle = - le32_to_cpu(pResponse->MUXMsg.StartNwInterfaceResp.Handle); - dbg_time("%s WdsConnectionIPv4Handle: 0x%08x", __func__, - WdsConnectionIPv4Handle); - } else { - WdsConnectionIPv6Handle = - le32_to_cpu(pResponse->MUXMsg.StartNwInterfaceResp.Handle); - dbg_time("%s WdsConnectionIPv6Handle: 0x%08x", __func__, - WdsConnectionIPv6Handle); - } - - free(pResponse); - - return 0; -} - -int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - UCHAR QMIType = (curIpFamily == 0x04) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - - if (curIpFamily == IpFamilyV4 && WdsConnectionIPv4Handle == 0) - return 0; - if (curIpFamily == IpFamilyV6 && WdsConnectionIPv6Handle == 0) - return 0; - - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_STOP_NETWORK_INTERFACE_REQ, - WdsStopNwInterfaceReq, &curIpFamily); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - if (curIpFamily == IpFamilyV4) - WdsConnectionIPv4Handle = 0; - else - WdsConnectionIPv6Handle = 0; - free(pResponse); - return 0; -} - -int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR pIpv4Addr; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR pIpv6Addr = NULL; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_DNS_ADDR pIpv6DNSAddr = NULL; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU pMtu; - IPV4_T *pIpv4 = &profile->ipv4; - IPV6_T *pIpv6 = &profile->ipv6; - UCHAR QMIType = (curIpFamily == 0x04) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - - if (curIpFamily == IpFamilyV4) { - memset(pIpv4, 0x00, sizeof(IPV4_T)); - if (WdsConnectionIPv4Handle == 0) - return 0; - } else if (curIpFamily == IpFamilyV6) { - memset(pIpv6, 0x00, sizeof(IPV6_T)); - if (WdsConnectionIPv6Handle == 0) - return 0; - } - - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_GET_RUNTIME_SETTINGS_REQ, - WdsGetRuntimeSettingReq, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS); - if (pIpv4Addr) { - pIpv4->DnsPrimary = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS); - if (pIpv4Addr) { - pIpv4->DnsSecondary = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY); - if (pIpv4Addr) { - pIpv4->Gateway = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET); - if (pIpv4Addr) { - pIpv4->SubnetMask = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4); - if (pIpv4Addr) { - pIpv4->Address = pIpv4Addr->IPV4Address; - } - - pIpv6DNSAddr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_DNS_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS); - if (pIpv6DNSAddr) { - memcpy(pIpv6->DnsPrimary, pIpv6DNSAddr->IPV6Address, 16); - } - - pIpv6DNSAddr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_DNS_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS); - if (pIpv6DNSAddr) { - memcpy(pIpv6->DnsSecondary, pIpv6DNSAddr->IPV6Address, 16); - } - -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 - -/* - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY); - if(pIpv6Addr) { - memcpy(pIpv6->Gateway, pIpv6Addr->IPV6Address, 16); - pIpv6->PrefixLengthGateway = pIpv6Addr->PrefixLength; - } -*/ - - if(profile->ipv6_prigateway_flag == 1) - { - char localip6gateway[1024] = {0}; - get_private_gateway(localip6gateway); - int length = sizeof(localip6gateway)/sizeof(localip6gateway[0]); - if (pIpv6Addr) - { - int i = 0; - char *token = strtok(localip6gateway, "."); - while(token != NULL) - { - pIpv6->Gateway[i++] = atoi(token); - //printf("token:%s, pIpv6->Gateway[%d]:%d\n", token, i-1, pIpv6->Gateway[i-1]); - token = strtok(NULL, "."); - } - pIpv6->PrefixLengthGateway = 16; - } - } - else - { - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY); - if(pIpv6Addr) - { - memcpy(pIpv6->Gateway, pIpv6Addr->IPV6Address, 16); - pIpv6->PrefixLengthGateway = pIpv6Addr->PrefixLength; - } - } -//2021-02-25 willa.liu@fibocom.com changed end for support eipd SN-20210129001 - - - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6); - if (pIpv6Addr) { - memcpy(pIpv6->Address, pIpv6Addr->IPV6Address, 16); - pIpv6->PrefixLengthIPAddr = pIpv6Addr->PrefixLength; - } - - pMtu = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU)GetTLV( - &pResponse->MUXMsg.QMUXMsgHdr, - QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU); - if (pMtu) { - pIpv4->Mtu = pIpv6->Mtu = le32_to_cpu(pMtu->Mtu); - } - - free(pResponse); - return 0; -} - -#ifdef CONFIG_APN -int requestSetProfile(PROFILE_T *profile) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - if (!profile->pdp) - return 0; - - dbg_time("%s[%d] %s/%s/%s/%d", __func__, profile->pdpindex, profile->apn, - profile->user, profile->password, profile->auth); - - UCHAR QMIType = (profile->ipv4_flag) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_MODIFY_PROFILE_SETTINGS_REQ, - WdsModifyProfileSettingsReq, profile); - err = QmiThreadSendQMI(pRequest, &pResponse); -//begin modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 - //modify profile no check return value, try create - qmi_rsp_check(); - if(le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) - { - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_CREATE_PROFILE_SETTINGS_REQ, - WdsCreateProfileSettingsReq, profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check(); - if(le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)){ - free(pResponse); - return -1; - } - dbg_time("WdsCreateProfileSettingsReq[%d] %s/%s/%s/%d", profile->pdpindex, profile->apn, - profile->user, profile->password, profile->auth); - } -//end modified by zhangkaibo add create profile qmi. mantis 0049137,0048741 20200610 - free(pResponse); - return 0; -} - -int requestGetProfile(PROFILE_T *profile) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - char *apn = NULL; - char *user = NULL; - char *password = NULL; - int auth = 0; - PQMIWDS_APNNAME pApnName; - PQMIWDS_USERNAME pUserName; - PQMIWDS_PASSWD pPassWd; - PQMIWDS_AUTH_PREFERENCE pAuthPref; - - if (!profile->pdp) - return 0; - - UCHAR QMIType = (profile->ipv4_flag) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_GET_PROFILE_SETTINGS_REQ, - WdsGetProfileSettingsReqSend, profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pApnName = (PQMIWDS_APNNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14); - pUserName = (PQMIWDS_USERNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1B); - pPassWd = (PQMIWDS_PASSWD)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1C); - pAuthPref = - (PQMIWDS_AUTH_PREFERENCE)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1D); - - if (pApnName /* && le16_to_cpu(pApnName->TLVLength)*/) - apn = strndup((const char *)(&pApnName->ApnName), - le16_to_cpu(pApnName->TLVLength)); - if (pUserName /* && pUserName->UserName*/) - user = strndup((const char *)(&pUserName->UserName), - le16_to_cpu(pUserName->TLVLength)); - if (pPassWd /* && le16_to_cpu(pPassWd->TLVLength)*/) - password = strndup((const char *)(&pPassWd->Passwd), - le16_to_cpu(pPassWd->TLVLength)); - if (pAuthPref /* && le16_to_cpu(pAuthPref->TLVLength)*/) { - auth = pAuthPref->AuthPreference; - } - -#if 0 - if (profile) { - profile->apn = apn; - profile->user = user; - profile->password = password; - profile->auth = auth; - } -#endif - - dbg_time("%s[%d] %s/%s/%s/%d", __func__, profile->pdpindex, apn, user, password, - auth); - - free(pResponse); - return 0; -} -#endif - -#ifdef CONFIG_VERSION -int requestBaseBandVersion(const char **pp_reversion) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PDEVICE_REV_ID revId; - int err; - - if (pp_reversion) - *pp_reversion = NULL; - - pRequest = - ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_GET_DEVICE_REV_ID_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - revId = (PDEVICE_REV_ID)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - - if (revId && le16_to_cpu(revId->TLVLength)) { - char *DeviceRevisionID = strndup((const char *)(&revId->RevisionID), - le16_to_cpu(revId->TLVLength)); - dbg_time("%s %s", __func__, DeviceRevisionID); - - if (pp_reversion) - *pp_reversion = DeviceRevisionID; - } - - free(pResponse); - return 0; -} -#endif - -#ifdef CONFIG_RESET_RADIO -static USHORT DmsSetOperatingModeReq(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->SetOperatingModeReq.TLVType = 0x01; - pMUXMsg->SetOperatingModeReq.TLVLength = cpu_to_le16(1); - pMUXMsg->SetOperatingModeReq.OperatingMode = *((UCHAR *)arg); - - return sizeof(QMIDMS_SET_OPERATING_MODE_REQ_MSG); -} - -int requestSetOperatingMode(UCHAR OperatingMode) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - dbg_time("%s(%d)", __func__, OperatingMode); - - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_SET_OPERATING_MODE_REQ, - DmsSetOperatingModeReq, &OperatingMode); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - free(pResponse); - return 0; -} -#endif diff --git a/fibocom-dial/src/QMIThread.h b/fibocom-dial/src/QMIThread.h deleted file mode 100644 index d3c8008..0000000 --- a/fibocom-dial/src/QMIThread.h +++ /dev/null @@ -1,260 +0,0 @@ -#ifndef __QMI_THREAD_H__ -#define __QMI_THREAD_H__ - -#define CONFIG_GOBINET -#define CONFIG_QMIWWAN -#define CONFIG_SIM -#define CONFIG_APN -#define CONFIG_VERSION -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -#define CONFIG_IMSI_ICCID -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -#define CONFIG_DEFAULT_PDP 1 -#define CONFIG_DEFAULT_PDPINDEX 1 -//#define CONFIG_IMSI_ICCID - -#define CONFIG_RESET_RADIO \ - (45) // Reset Radiao(AT+CFUN=4,AT+CFUN=1) when cann not register network or - // setup data call in 45 seconds - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "MPQCTL.h" -#include "MPQMI.h" -#include "MPQMUX.h" - -#define DEVICE_CLASS_UNKNOWN 0 -#define DEVICE_CLASS_CDMA 1 -#define DEVICE_CLASS_GSM 2 - -#define WWAN_DATA_CLASS_NONE 0x00000000 -#define WWAN_DATA_CLASS_GPRS 0x00000001 -#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */ -#define WWAN_DATA_CLASS_UMTS 0x00000004 -#define WWAN_DATA_CLASS_HSDPA 0x00000008 -#define WWAN_DATA_CLASS_HSUPA 0x00000010 -#define WWAN_DATA_CLASS_LTE 0x00000020 -//begin modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 -#define WWAN_DATA_CLASS_5G 0x00000040 -//end modified by zhangkaibo add 5G network detect feature on x55 platform. 20200605 -#define WWAN_DATA_CLASS_1XRTT 0x00010000 -#define WWAN_DATA_CLASS_1XEVDO 0x00020000 -#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000 -#define WWAN_DATA_CLASS_1XEVDV 0x00080000 -#define WWAN_DATA_CLASS_3XRTT 0x00100000 -#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */ -#define WWAN_DATA_CLASS_UMB 0x00400000 -#define WWAN_DATA_CLASS_CUSTOM 0x80000000 - -struct wwan_data_class_str { - ULONG class; - CHAR *str; -}; - -#pragma pack(push, 1) - -typedef struct _QCQMIMSG { - QCQMI_HDR QMIHdr; - union { - QMICTL_MSG CTLMsg; - QMUX_MSG MUXMsg; -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - QMUX_MSG QMUXMsgHdrResp; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - }; -} __attribute__((packed)) QCQMIMSG, *PQCQMIMSG; - -#pragma pack(pop) - -typedef struct __IPV4 { - uint32_t Address; - uint32_t Gateway; - uint32_t SubnetMask; - uint32_t DnsPrimary; - uint32_t DnsSecondary; - uint32_t Mtu; -} IPV4_T; - -typedef struct __IPV6 { - UCHAR Address[16]; - UCHAR Gateway[16]; - UCHAR SubnetMask[16]; - UCHAR DnsPrimary[16]; - UCHAR DnsSecondary[16]; - UCHAR PrefixLengthIPAddr; - UCHAR PrefixLengthGateway; - ULONG Mtu; -} IPV6_T; - -#define IpFamilyV4 (0x04) -#define IpFamilyV6 (0x06) - -struct __PROFILE; -struct qmi_device_ops { - int (*init)(struct __PROFILE *profile); - int (*deinit)(void); - int (*send)(PQCQMIMSG pRequest); - void *(*read)(void *pData); -}; -extern int (*qmidev_send)(PQCQMIMSG pRequest); - -#ifndef bool -#define bool uint8_t -#endif -//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037 -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int qmap_mode; - unsigned int qmap_version; - unsigned int dl_minimum_padding; - char ifname[8][16]; - unsigned char mux_id[8]; -} RMNET_INFO; -//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037 - -typedef struct __PROFILE { - char *qmichannel; - char *usbnet_adapter; - char *qmapnet_adapter; - const char *driver_name; - int qmap_mode; - int qmap_size; - int qmap_version; - const char *apn; - const char *user; - const char *password; - const char *pincode; - int auth; - int pdp; - int pdpindex; - int pdpnum; - int curIpFamily; - int rawIP; - int muxid; - IPV4_T ipv4; - IPV6_T ipv6; - int ipv4_flag; - int ipv6_flag; - -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 - int ipv6_prigateway_flag; -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 - - int dual_flag; - int apntype; - const struct qmi_device_ops *qmi_ops; - bool loopback_state; - int replication_factor; -//2021-02-08 zhangkaibo@fibocom.com changed begin for mantis 0070613 - int interfacenum; -//2021-02-08 zhangkaibo@fibocom.com changed end for mantis 0070613 -//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037 - RMNET_INFO rmnet_info; -//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037 -} PROFILE_T; - -typedef enum { - SIM_ABSENT = 0, - SIM_NOT_READY = 1, - SIM_READY = - 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ - SIM_PIN = 3, - SIM_PUK = 4, - SIM_NETWORK_PERSONALIZATION = 5, - SIM_BAD = 6, -} SIM_Status; -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -typedef enum { - SIM_Card0 = 0, - SIM_Card1 = 1 -} SIM_Select; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -#define WDM_DEFAULT_BUFSIZE 256 -#define RIL_REQUEST_QUIT 0x1000 -#define RIL_INDICATE_DEVICE_CONNECTED 0x1002 -#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003 -#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004 -#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005 - -extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t *mutex, - unsigned msecs); -extern int QmiThreadSendQMI(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse); -extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, - unsigned msecs); -extern void QmiThreadRecvQMI(PQCQMIMSG pResponse); -extern int fibo_raw_ip_mode_check(const char *ifname); -extern void udhcpc_start(PROFILE_T *profile); -extern void udhcpc_stop(PROFILE_T *profile); -extern void udhcpc_start_pcie(PROFILE_T *profile); -extern void udhcpc_stop_pcie(PROFILE_T *profile); - -extern void dump_qmi(void *dataBuffer, int dataLen); -extern void qmidevice_send_event_to_main(int triger_event); -extern int requestSetEthMode(PROFILE_T *profile); -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -//extern int requestGetSIMStatus(SIM_Status *pSIMStatus); -extern int requestGetSIMStatus(SIM_Status *pSIMStatus , const int sim_select); -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -extern int requestEnterSimPin(const CHAR *pPinCode); -extern int requestGetICCID(void); -extern int requestGetIMSI(void); -extern int requestRegistrationState(UCHAR *pPSAttachedState); -extern int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily); -extern int requestSetupDataCall(PROFILE_T *profile, int curIpFamily); -extern int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily); -extern int requestSetProfile(PROFILE_T *profile); -extern int requestGetProfile(PROFILE_T *profile); -extern int requestBaseBandVersion(const char **pp_reversion); -extern int requestGetIPAddress(PROFILE_T *profile, int curIpFamily); -extern int requestSetOperatingMode(UCHAR OperatingMode); -int requestRegistrationState2(UCHAR *pPSAttachedState); - -extern int fibo_qmap_mode_set(PROFILE_T *profile); -extern int fibo_bridge_mode_detect(PROFILE_T *profile); -extern int fibo_qmap_mode_detect(PROFILE_T *profile); -extern const struct qmi_device_ops qmiwwan_qmidev_ops; - -#define qmidev_is_gobinet(_qmichannel) \ - (strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0) -#define qmidev_is_qmiwwan(_qmichannel) \ - (strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0) -#define qmidev_is_pciemhi(_qmichannel) \ - (strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0) - -#define driver_is_qmi(_drv_name) \ - (strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0) -#define driver_is_mbim(_drv_name) \ - (strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0) - -extern FILE *logfilefp; -extern int debug_qmi; -extern USHORT g_MobileCountryCode; -extern USHORT g_MobileNetworkCode; -extern int qmidevice_control_fd[2]; -extern int qmiclientId[QMUX_TYPE_WDS_ADMIN + 1]; -extern void dbg_time(const char *fmt, ...); -extern USHORT le16_to_cpu(USHORT v16); -extern UINT le32_to_cpu(UINT v32); -extern USHORT cpu_to_le16(USHORT v16); -extern UINT cpu_to_le32(UINT v32); -#endif diff --git a/fibocom-dial/src/QmiWwanCM.c b/fibocom-dial/src/QmiWwanCM.c deleted file mode 100644 index ed1cccd..0000000 --- a/fibocom-dial/src/QmiWwanCM.c +++ /dev/null @@ -1,426 +0,0 @@ -#include -#include -#include -#include -typedef unsigned short sa_family_t; -#include - -#include "QMIThread.h" - -#ifdef CONFIG_QMIWWAN -#define FIBO_QMI_PROXY "fibo_qmimsg_server" -static int cdc_wdm_fd = -1; - -static UCHAR GetQCTLTransactionId(void) -{ - static int TransactionId = 0; - if (++TransactionId > 0xFF) - TransactionId = 1; - return TransactionId; -} - -typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg); - -static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType, - CUSTOMQCTL customQctlMsgFunction, void *arg) -{ - UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE]; - PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf; - int Length; - - pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRequest->QMIHdr.CtlFlags = 0x00; - pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL; - pRequest->QMIHdr.ClientId = 0x00; - - pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; - pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId(); - pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType); - if (customQctlMsgFunction) - pRequest->CTLMsg.QMICTLMsgHdr.Length = - cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) - - sizeof(QCQMICTL_MSG_HDR)); - else - pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000); - - pRequest->QMIHdr.Length = - cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) + - sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1); - Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - - pRequest = (PQCQMIMSG)malloc(Length); - if (pRequest == NULL) { - dbg_time("%s fail to malloc", __func__); - } else { - memcpy(pRequest, QMIBuf, Length); - } - - return pRequest; -} - -static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001); - QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL; - return sizeof(QMICTL_GET_VERSION_REQ_MSG); -} - -static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001); - QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0]; - return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG); -} - -static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002); - QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0]; - QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1]; - return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG); -} - -static int QmiWwanSendQMI(PQCQMIMSG pRequest) -{ - struct pollfd pollfds[] = {{cdc_wdm_fd, POLLOUT, 0}}; - int ret; - - if (cdc_wdm_fd == -1) { - dbg_time("%s cdc_wdm_fd = -1", __func__); - return -ENODEV; - } - - if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6) - pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS; - - do { - ret = poll(pollfds, sizeof(pollfds) / sizeof(pollfds[0]), 5000); - } while ((ret < 0) && (errno == EINTR)); - - if (pollfds[0].revents & POLLOUT) { - ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - ret = write(cdc_wdm_fd, pRequest, nwrites); - if (ret == nwrites) { - ret = 0; - } else { - dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, - strerror(errno)); - } - } else { - dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret, - pollfds[0].revents, errno, strerror(errno)); - } - - return ret; -} - -static int QmiWwanGetClientID(UCHAR QMIType) -{ - PQCQMIMSG pResponse; - - QmiThreadSendQMI( - ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType), - &pResponse); - - if (pResponse) { - USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp - .QMUXResult); // QMI_RESULT_SUCCESS - USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp - .QMUXError); // QMI_ERR_INVALID_ARG - // UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType; - UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId; - - dbg_time("%s: QMIType = %d clientid %d", __func__, QMIType, ClientId); - - if (!QMUXResult && !QMUXError && - (QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) { - switch (QMIType) { - case QMUX_TYPE_WDS: - dbg_time("Get clientWDS = %d", ClientId); - break; - case QMUX_TYPE_DMS: - dbg_time("Get clientDMS = %d", ClientId); - break; - case QMUX_TYPE_NAS: - dbg_time("Get clientNAS = %d", ClientId); - break; - case QMUX_TYPE_QOS: - dbg_time("Get clientQOS = %d", ClientId); - break; - case QMUX_TYPE_WMS: - dbg_time("Get clientWMS = %d", ClientId); - break; - case QMUX_TYPE_PDS: - dbg_time("Get clientPDS = %d", ClientId); - break; - case QMUX_TYPE_UIM: - dbg_time("Get clientUIM = %d", ClientId); - break; - case QMUX_TYPE_WDS_ADMIN: - dbg_time("Get clientWDA = %d", ClientId); - break; - default: - break; - } - return ClientId; - } - } - return 0; -} - -static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId) -{ - UCHAR argv[] = {QMIType, ClientId}; - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ, - CtlReleaseClientIdReq, argv), - NULL); - return 0; -} - -static int QmiWwanInit(PROFILE_T *profile) -{ - unsigned i; - int ret; - PQCQMIMSG pResponse; - - if (profile->qmap_mode == 0 || profile->qmap_mode == 1) { - for (i = 0; i < 10; i++) { - ret = QmiThreadSendQMITimeout( - ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000); - if (!ret) - break; - sleep(1); - } - if (ret) - return ret; - } - - QmiThreadSendQMI( - ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL), - &pResponse); - if (profile->qmap_mode) { - if (pResponse) { - if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 && - pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { - uint8_t NumElements = 0; - - for (NumElements = 0; - NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements; - NumElements++) { - if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements] - .QMUXType == QMUX_TYPE_WDS_ADMIN) - profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp - .TypeVersion[NumElements] - .MinorVersion > 16); - } - } - } - } - if (pResponse) - free(pResponse); - if (profile->ipv4_flag) - qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS); - if (profile->ipv6_flag) - qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS); - qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS); - qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS); - qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM); - if (profile->qmap_mode == 0 || profile->qmap_mode == 1) - qmiclientId[QMUX_TYPE_WDS_ADMIN] = - QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN); - - return 0; -} - -static int QmiWwanDeInit(void) -{ - unsigned int i; - for (i = 0; i < sizeof(qmiclientId) / sizeof(qmiclientId[0]); i++) { - if (qmiclientId[i] != 0) { - QmiWwanReleaseClientID(i, qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static int qmi_proxy_open(const char *name) -{ - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - (sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)); - if (sockfd < 0) - return sockfd; - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name)); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - if (connect(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dbg_time("%s connect %s errno: %d (%s)\n", __func__, name, errno, - strerror(errno)); - return -1; - } - (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, - sizeof(reuse_addr))); - - dbg_time("connect to %s sockfd = %d\n", name, sockfd); - - return sockfd; -} - -static ssize_t qmi_proxy_read(int fd, void *buf, size_t size) -{ - ssize_t nreads; - PQCQMI_HDR pHdr = (PQCQMI_HDR)buf; - - nreads = read(fd, pHdr, sizeof(QCQMI_HDR)); - if (nreads == sizeof(QCQMI_HDR)) { - nreads += read(fd, pHdr + 1, - le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR)); - } - - return nreads; -} - -static void *QmiWwanThread(void *pData) -{ - PROFILE_T *profile = (PROFILE_T *)pData; - const char *cdc_wdm = (const char *)profile->qmichannel; - - if (profile->qmap_mode == 0 || profile->qmap_mode == 1) - cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY); - else - cdc_wdm_fd = qmi_proxy_open(FIBO_QMI_PROXY); - - if (cdc_wdm_fd == -1) { - dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm, - errno, strerror(errno)); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - pthread_exit(NULL); - return NULL; - } - - fcntl(cdc_wdm_fd, F_SETFL, fcntl(cdc_wdm_fd, F_GETFL) | O_NONBLOCK); - fcntl(cdc_wdm_fd, F_SETFD, FD_CLOEXEC); - - dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd); - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (1) { - struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0}, - {cdc_wdm_fd, POLLIN, 0}}; - int ne, ret, nevents = sizeof(pollfds) / sizeof(pollfds[0]); - - do { - ret = poll(pollfds, nevents, -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, - strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - // dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events, - // pollfds[ne].revents); - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("poll fd = %d, events = 0x%04x", fd, revents); - if (fd == cdc_wdm_fd) { - } else { - } - if (revents & - (POLLHUP | POLLNVAL)) // EC20 bug, Can get POLLERR - goto __QmiWwanThread_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == - sizeof(triger_event)) { - // DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __QmiWwanThread_quit; - break; - case SIGTERM: - case SIGHUP: - case SIGINT: - QmiThreadRecvQMI(NULL); - break; - default: - break; - } - } - } - - if (fd == cdc_wdm_fd) { - ssize_t nreads; - UCHAR QMIBuf[4096]; - PQCQMIMSG pResponse = (PQCQMIMSG)QMIBuf; - - if (profile->qmap_mode == 0 || profile->qmap_mode == 1) - nreads = read(fd, QMIBuf, sizeof(QMIBuf)); - else - nreads = qmi_proxy_read(fd, QMIBuf, sizeof(QMIBuf)); - // dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, - // errno, strerror(errno)); - if (nreads <= 0) { - dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, - errno, strerror(errno)); - break; - } - - if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) { - dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d", - __func__, (int)nreads, - le16_to_cpu(pResponse->QMIHdr.Length)); - continue; - } - - QmiThreadRecvQMI(pResponse); - } - } - } - -__QmiWwanThread_quit: - if (cdc_wdm_fd != -1) { - close(cdc_wdm_fd); - cdc_wdm_fd = -1; - } - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); // main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -#endif - -const struct qmi_device_ops qmiwwan_qmidev_ops = { - .init = QmiWwanInit, - .deinit = QmiWwanDeInit, - .send = QmiWwanSendQMI, - .read = QmiWwanThread, -}; diff --git a/fibocom-dial/src/default.script b/fibocom-dial/src/default.script deleted file mode 100644 index 26b95c1..0000000 --- a/fibocom-dial/src/default.script +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert. -# -# Based on the busybox example scripts and the old udhcp source -# package default.* scripts. - -RESOLV_CONF="/etc/resolv.conf" - -case $1 in - bound|renew) - [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" - [ -n "$subnet" ] && NETMASK="netmask $subnet" - - /sbin/ifconfig $interface $ip $BROADCAST $NETMASK - - if [ -n "$router" ]; then - echo "$0: Resetting default routes" - while /sbin/route del default gw 0.0.0.0 dev $interface; do :; done - - metric=0 - for i in $router; do - /sbin/route add default gw $i dev $interface metric $metric - metric=$(($metric + 1)) - done - fi - - # Update resolver configuration file - R="" - [ -n "$domain" ] && R="domain $domain -" - for i in $dns; do - echo "$0: Adding DNS $i" - R="${R}nameserver $i -" - done - - if [ -x /sbin/resolvconf ]; then - echo -n "$R" | resolvconf -a "${interface}.udhcpc" - else - echo -n "$R" > "$RESOLV_CONF" - fi - ;; - - deconfig) - if [ -x /sbin/resolvconf ]; then - resolvconf -d "${interface}.udhcpc" - fi - /sbin/ifconfig $interface 0.0.0.0 - ;; - - leasefail) - echo "$0: Lease failed: $message" - ;; - - nak) - echo "$0: Received a NAK: $message" - ;; - - *) - echo "$0: Unknown udhcpc command: $1"; - exit 1; - ;; -esac diff --git a/fibocom-dial/src/fibo_qmimsg_server.c b/fibocom-dial/src/fibo_qmimsg_server.c deleted file mode 100644 index a7a29ef..0000000 --- a/fibocom-dial/src/fibo_qmimsg_server.c +++ /dev/null @@ -1,1331 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; - -#define cpu_to_le16(x) (x) -#define cpu_to_le32(x) (x) -#define le16_to_cpu(x) (x) -#define le32_to_cpu(x) (x) - -#define dprintf(fmt, arg...) do { printf(fmt, ##arg); } while(0) -#define SYSCHECK(c) do{if((c)<0) {dprintf("%s %d error: '%s' (code: %d)\n", __func__, __LINE__, strerror(errno), errno); return -1;}}while(0) -#define cfmakenoblock(fd) do{fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);}while(0) - -#define qmidev_is_pciemhi(_qmichannel) (strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0) - -typedef struct _QCQMI_HDR -{ - uint8_t IFType; - uint16_t Length; - uint8_t CtlFlags; // reserved - uint8_t QMIType; - uint8_t ClientId; -} __attribute__ ((packed)) QCQMI_HDR, *PQCQMI_HDR; - -typedef struct _QMICTL_SYNC_REQ_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_REQUEST - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_CTL_SYNC_REQ - uint16_t Length; // 0 -} __attribute__ ((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG; - -typedef struct _QMICTL_SYNC_RESP_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_RESPONSE - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_CTL_SYNC_RESP - uint16_t Length; - uint8_t TLVType; // QCTLV_TYPE_RESULT_CODE - uint16_t TLVLength; // 0x0004 - uint16_t QMIResult; - uint16_t QMIError; -} __attribute__ ((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG; - -typedef struct _QMICTL_SYNC_IND_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_INDICATION - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - uint16_t Length; -} __attribute__ ((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_REQUEST - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_GET_CLIENT_ID_REQ - uint16_t Length; - uint8_t TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - uint16_t TLVLength; // 1 - uint8_t QMIType; // QMUX type -} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG, *PQMICTL_GET_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_RESPONSE - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_GET_CLIENT_ID_RESP - uint16_t Length; - uint8_t TLVType; // QCTLV_TYPE_RESULT_CODE - uint16_t TLVLength; // 0x0004 - uint16_t QMIResult; // result code - uint16_t QMIError; // error code - uint8_t TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - uint16_t TLV2Length; // 2 - uint8_t QMIType; - uint8_t ClientId; -} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG, *PQMICTL_GET_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_REQUEST - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ - uint16_t Length; - uint8_t TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - uint16_t TLVLength; // 0x0002 - uint8_t QMIType; - uint8_t ClientId; -} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG, *PQMICTL_RELEASE_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_RESPONSE - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP - uint16_t Length; - uint8_t TLVType; // QCTLV_TYPE_RESULT_CODE - uint16_t TLVLength; // 0x0004 - uint16_t QMIResult; // result code - uint16_t QMIError; // error code - uint8_t TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - uint16_t TLV2Length; // 2 - uint8_t QMIType; - uint8_t ClientId; -} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG, *PQMICTL_RELEASE_CLIENT_ID_RESP_MSG; - -// QMICTL Control Flags -#define QMICTL_CTL_FLAG_CMD 0x00 -#define QMICTL_CTL_FLAG_RSP 0x01 -#define QMICTL_CTL_FLAG_IND 0x02 - -typedef struct _QCQMICTL_MSG_HDR -{ - uint8_t CtlFlags; // 00-cmd, 01-rsp, 10-ind - uint8_t TransactionId; - uint16_t QMICTLType; - uint16_t Length; -} __attribute__ ((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR; - -#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR) - -typedef struct _QCQMICTL_MSG_HDR_RESP -{ - uint8_t CtlFlags; // 00-cmd, 01-rsp, 10-ind - uint8_t TransactionId; - uint16_t QMICTLType; - uint16_t Length; - uint8_t TLVType; // 0x02 - result code - uint16_t TLVLength; // 4 - uint16_t QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - uint16_t QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__ ((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP; - -typedef struct _QMICTL_GET_VERSION_REQ_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_REQUEST - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_GET_VERSION_REQ - uint16_t Length; // 0 - uint8_t TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - uint16_t TLVLength; // var - uint8_t QMUXTypes; // List of one byte QMUX_TYPE values - // 0xFF returns a list of versions for all - // QMUX_TYPEs implemented on the device -} __attribute__ ((packed)) QMICTL_GET_VERSION_REQ_MSG, *PQMICTL_GET_VERSION_REQ_MSG; - -typedef struct _QMUX_TYPE_VERSION_STRUCT -{ - uint8_t QMUXType; - uint16_t MajorVersion; - uint16_t MinorVersion; -} __attribute__ ((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT; - -typedef struct _QMICTL_GET_VERSION_RESP_MSG -{ - uint8_t CtlFlags; // QMICTL_FLAG_RESPONSE - uint8_t TransactionId; - uint16_t QMICTLType; // QMICTL_GET_VERSION_RESP - uint16_t Length; - uint8_t TLVType; // QCTLV_TYPE_RESULT_CODE - uint16_t TLVLength; // 0x0004 - uint16_t QMIResult; - uint16_t QMIError; - uint8_t TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - uint16_t TLV2Length; // var - uint8_t NumElements; // Num of QMUX_TYPE_VERSION_STRUCT - QMUX_TYPE_VERSION_STRUCT TypeVersion[0]; -} __attribute__ ((packed)) QMICTL_GET_VERSION_RESP_MSG, *PQMICTL_GET_VERSION_RESP_MSG; - - -typedef struct _QMICTL_MSG -{ - union - { - // Message Header - QCQMICTL_MSG_HDR QMICTLMsgHdr; - QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp; - - // QMICTL Message - //QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq; - //QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp; - QMICTL_GET_VERSION_REQ_MSG GetVersionReq; - QMICTL_GET_VERSION_RESP_MSG GetVersionRsp; - QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq; - QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp; - //QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq; - QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp; - //QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd; - //QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd; - //QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - //QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp; - QMICTL_SYNC_REQ_MSG SyncReq; - QMICTL_SYNC_RESP_MSG SyncRsp; - QMICTL_SYNC_IND_MSG SyncInd; - }; -} __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG; - -typedef struct _QCQMUX_MSG_HDR -{ - uint8_t CtlFlags; // 0: single QMUX Msg; 1: - uint16_t TransactionId; - uint16_t Type; - uint16_t Length; - uint8_t payload[0]; -} __attribute__ ((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR; - -typedef struct _QCQMUX_MSG_HDR_RESP -{ - uint8_t CtlFlags; // 0: single QMUX Msg; 1: - uint16_t TransactionId; - uint16_t Type; - uint16_t Length; - uint8_t TLVType; // 0x02 - result code - uint16_t TLVLength; // 4 - uint16_t QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - uint16_t QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__ ((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT -{ - uint16_t Type; // QMUX type 0x0000 - uint16_t Length; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT, *PQMIWDS_ADMIN_SET_DATA_FORMAT; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS -{ - uint8_t TLVType; - uint16_t TLVLength; - uint8_t QOSSetting; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV -{ - uint8_t TLVType; - uint16_t TLVLength; - uint32_t Value; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV; - -typedef struct _QMIWDS_ENDPOINT_TLV -{ - uint8_t TLVType; - uint16_t TLVLength; - uint32_t ep_type; - uint32_t iface_id; -} __attribute__ ((packed)) QMIWDS_ENDPOINT_TLV, *PQMIWDS_ENDPOINT_TLV; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG -{ - uint8_t CtlFlags; // 0: single QMUX Msg; 1: - uint16_t TransactionId; - uint16_t Type; - uint16_t Length; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv; - QMIWDS_ENDPOINT_TLV epTlv; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG, *PQMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG; - -typedef struct _QCQMUX_TLV -{ - uint8_t Type; - uint16_t Length; - uint8_t Value[0]; -} __attribute__ ((packed)) QCQMUX_TLV, *PQCQMUX_TLV; - -typedef struct _QMUX_MSG -{ - union - { - // Message Header - QCQMUX_MSG_HDR QMUXMsgHdr; - QCQMUX_MSG_HDR_RESP QMUXMsgHdrResp; - QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - }; -} __attribute__ ((packed)) QMUX_MSG, *PQMUX_MSG; - -typedef struct _QCQMIMSG { - QCQMI_HDR QMIHdr; -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - //QMUX_MSG QMUXMsgHdrResp; -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - union { - QMICTL_MSG CTLMsg; - QMUX_MSG MUXMsg; - }; -} __attribute__ ((packed)) QCQMIMSG, *PQCQMIMSG; - -// QMUX Message Definitions -- QMI SDU -#define QMUX_CTL_FLAG_SINGLE_MSG 0x00 -#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01 -#define QMUX_CTL_FLAG_TYPE_CMD 0x00 -#define QMUX_CTL_FLAG_TYPE_RSP 0x02 -#define QMUX_CTL_FLAG_TYPE_IND 0x04 -#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01 -#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind - -#define USB_CTL_MSG_TYPE_QMI 0x01 - -#define QMICTL_FLAG_REQUEST 0x00 -#define QMICTL_FLAG_RESPONSE 0x01 -#define QMICTL_FLAG_INDICATION 0x02 - -// QMICTL Type -#define QMICTL_SET_INSTANCE_ID_REQ 0x0020 -#define QMICTL_SET_INSTANCE_ID_RESP 0x0020 -#define QMICTL_GET_VERSION_REQ 0x0021 -#define QMICTL_GET_VERSION_RESP 0x0021 -#define QMICTL_GET_CLIENT_ID_REQ 0x0022 -#define QMICTL_GET_CLIENT_ID_RESP 0x0022 -#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023 -#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023 -#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024 -#define QMICTL_INVALID_CLIENT_ID_IND 0x0025 -#define QMICTL_SET_DATA_FORMAT_REQ 0x0026 -#define QMICTL_SET_DATA_FORMAT_RESP 0x0026 -#define QMICTL_SYNC_REQ 0x0027 -#define QMICTL_SYNC_RESP 0x0027 -#define QMICTL_SYNC_IND 0x0027 - -#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01 - -// Define QMI Type -typedef enum _QMI_SERVICE_TYPE -{ - QMUX_TYPE_CTL = 0x00, - QMUX_TYPE_WDS = 0x01, - QMUX_TYPE_DMS = 0x02, - QMUX_TYPE_NAS = 0x03, - QMUX_TYPE_QOS = 0x04, - QMUX_TYPE_WMS = 0x05, - QMUX_TYPE_PDS = 0x06, - QMUX_TYPE_UIM = 0x0B, - QMUX_TYPE_WDS_IPV6 = 0x11, - QMUX_TYPE_WDS_ADMIN = 0x1A, - QMUX_TYPE_MAX = 0xFF, - QMUX_TYPE_ALL = 0xFF -} QMI_SERVICE_TYPE; - -#define QMIWDS_ADMIN_SET_DATA_FORMAT_REQ 0x0020 -#define QMIWDS_ADMIN_SET_DATA_FORMAT_RESP 0x0020 - -struct qlistnode -{ - struct qlistnode *next; - struct qlistnode *prev; -}; - -#define qnode_to_item(node, container, member) \ - (container *) (((char*) (node)) - offsetof(container, member)) - -#define qlist_for_each(node, list) \ - for (node = (list)->next; node != (list); node = node->next) - -#define qlist_empty(list) ((list) == (list)->next) -#define qlist_head(list) ((list)->next) -#define qlist_tail(list) ((list)->prev) - -typedef struct { - struct qlistnode qnode; - uint8_t ClientFd; - QCQMIMSG qmi[0]; -} QMI_PROXY_MSG; - -typedef struct { - struct qlistnode qnode; - uint8_t QMIType; - uint8_t ClientId; - unsigned AccessTime; -} QMI_PROXY_CLINET; - -typedef struct { - struct qlistnode qnode; - struct qlistnode client_qnode; - uint8_t ClientFd; - unsigned AccessTime; -} QMI_PROXY_CONNECTION; - -static int qmi_proxy_quit = 0; -static pthread_t thread_id = 0; -static int cdc_wdm_fd = -1; -static int qmi_proxy_server_fd = -1; -static struct qlistnode qmi_proxy_connection; -static struct qlistnode qmi_proxy_ctl_msg; -static PQCQMIMSG s_pCtlReq; -static PQCQMIMSG s_pCtlRsq; -static pthread_mutex_t s_ctlmutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t s_ctlcond = PTHREAD_COND_INITIALIZER; -static int verbose_debug = 0; - -static void qlist_init(struct qlistnode *node) -{ - node->next = node; - node->prev = node; -} - -static void qlist_add_tail(struct qlistnode *head, struct qlistnode *item) -{ - item->next = head; - item->prev = head->prev; - head->prev->next = item; - head->prev = item; -} - -static void qlist_remove(struct qlistnode *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; -} - - - -static void setTimespecRelative(struct timespec *p_ts, long long msec) -{ - struct timeval tv; - - gettimeofday(&tv, (struct timezone *) NULL); - - /* what's really funny about this is that I know - pthread_cond_timedwait just turns around and makes this - a relative time again */ - p_ts->tv_sec = tv.tv_sec + (msec / 1000); - p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; -} - -static int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs) { - if (msecs != 0) { - struct timespec ts; - setTimespecRelative(&ts, msecs); - return pthread_cond_timedwait(cond, mutex, &ts); - } else { - return pthread_cond_wait(cond, mutex); - } -} - -static int create_local_server(const char *name) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - SYSCHECK(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)); - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name) ); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - SYSCHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr))); - if(bind(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dprintf("%s bind %s errno: %d (%s)\n", __func__, name, errno, strerror(errno)); - return -1; - } - - dprintf("local server: %s sockfd = %d\n", name, sockfd); - cfmakenoblock(sockfd); - listen(sockfd, 1); - - return sockfd; -} - -static void accept_qmi_connection(int serverfd) { - int clientfd = -1; - unsigned char addr[128]; - socklen_t alen = sizeof(addr); - QMI_PROXY_CONNECTION *qmi_con; - - clientfd = accept(serverfd, (struct sockaddr *)addr, &alen); - - qmi_con = (QMI_PROXY_CONNECTION *)malloc(sizeof(QMI_PROXY_CONNECTION)); - if (qmi_con) { - qlist_init(&qmi_con->qnode); - qlist_init(&qmi_con->client_qnode); - qmi_con->ClientFd= clientfd; - qmi_con->AccessTime = 0; - dprintf("+++ ClientFd=%d\n", qmi_con->ClientFd); - qlist_add_tail(&qmi_proxy_connection, &qmi_con->qnode); - } - - cfmakenoblock(clientfd); -} - -static void cleanup_qmi_connection(int clientfd) { - struct qlistnode *con_node, *qmi_node; - - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - if (qmi_con->ClientFd == clientfd) { - while (!qlist_empty(&qmi_con->client_qnode)) { - QMI_PROXY_CLINET *qmi_client = qnode_to_item(qlist_head(&qmi_con->client_qnode), QMI_PROXY_CLINET, qnode); - - dprintf("xxx ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); - - qlist_remove(&qmi_client->qnode); - free(qmi_client); - } - - qlist_for_each(qmi_node, &qmi_proxy_ctl_msg) { - QMI_PROXY_MSG *qmi_msg = qnode_to_item(qmi_node, QMI_PROXY_MSG, qnode); - - if (qmi_msg->ClientFd == qmi_con->ClientFd) { - qlist_remove(&qmi_msg->qnode); - free(qmi_msg); - break; - } - } - - dprintf("--- ClientFd=%d\n", qmi_con->ClientFd); - close(qmi_con->ClientFd); - qlist_remove(&qmi_con->qnode); - free(qmi_con); - break; - } - } -} - -static void get_client_id(QMI_PROXY_CONNECTION *qmi_con, PQMICTL_GET_CLIENT_ID_RESP_MSG pClient) { - if (pClient->QMIResult == 0 && pClient->QMIError == 0) { - QMI_PROXY_CLINET *qmi_client = (QMI_PROXY_CLINET *)malloc(sizeof(QMI_PROXY_CLINET)); - - qlist_init(&qmi_client->qnode); - qmi_client->QMIType = pClient->QMIType; - qmi_client->ClientId = pClient->ClientId; - qmi_client->AccessTime = 0; - - dprintf("+++ ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); - qlist_add_tail(&qmi_con->client_qnode, &qmi_client->qnode); - } -} - -static void release_client_id(QMI_PROXY_CONNECTION *qmi_con, PQMICTL_RELEASE_CLIENT_ID_RESP_MSG pClient) { - struct qlistnode *client_node; - - if (pClient->QMIResult == 0 && pClient->QMIError == 0) { - qlist_for_each (client_node, &qmi_con->client_qnode) { - QMI_PROXY_CLINET *qmi_client = qnode_to_item(client_node, QMI_PROXY_CLINET, qnode); - - if (pClient->QMIType == qmi_client->QMIType && pClient->ClientId == qmi_client->ClientId) { - dprintf("--- ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); - qlist_remove(&qmi_client->qnode); - free(qmi_client); - break; - } - } - } -} - - -static int send_qmi_to_cdc_wdm(PQCQMIMSG pQMI) { - struct pollfd pollfds[]= {{cdc_wdm_fd, POLLOUT, 0}}; - ssize_t ret = 0; - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while ((ret < 0) && (errno == EINTR)); - - if (pollfds[0].revents & POLLOUT) { - ssize_t size = le16_to_cpu(pQMI->QMIHdr.Length) + 1; - ret = write(cdc_wdm_fd, pQMI, size); - if (verbose_debug) - { - ssize_t i; - printf("w %d %zd: ", cdc_wdm_fd, ret); - for (i = 0; i < 16; i++) - printf("%02x ", ((uint8_t *)pQMI)[i]); - printf("\n"); - } - } - - return ret; -} - -static int send_qmi_to_client(PQCQMIMSG pQMI, int clientFd) { - struct pollfd pollfds[]= {{clientFd, POLLOUT, 0}}; - ssize_t ret = 0; - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while ((ret < 0) && (errno == EINTR)); - - if (pollfds[0].revents & POLLOUT) { - ssize_t size = le16_to_cpu(pQMI->QMIHdr.Length) + 1; - ret = write(clientFd, pQMI, size); - if (verbose_debug) - { - ssize_t i; - printf("w %d %zd: ", clientFd, ret); - for (i = 0; i < 16; i++) - printf("%02x ", ((uint8_t *)pQMI)[i]); - printf("\n"); - } - } - - return ret; -} - - -static void recv_qmi(PQCQMIMSG pQMI, unsigned size) { - struct qlistnode *con_node, *client_node; - - if (qmi_proxy_server_fd <= 0) { - pthread_mutex_lock(&s_ctlmutex); - - if (s_pCtlReq != NULL) { - if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL - && s_pCtlReq->CTLMsg.QMICTLMsgHdrRsp.TransactionId == pQMI->CTLMsg.QMICTLMsgHdrRsp.TransactionId) { - s_pCtlRsq = malloc(size); - memcpy(s_pCtlRsq, pQMI, size); - pthread_cond_signal(&s_ctlcond); - } - else if (pQMI->QMIHdr.QMIType != QMUX_TYPE_CTL - && s_pCtlReq->MUXMsg.QMUXMsgHdr.TransactionId == pQMI->MUXMsg.QMUXMsgHdr.TransactionId) { - s_pCtlRsq = malloc(size); - memcpy(s_pCtlRsq, pQMI, size); - pthread_cond_signal(&s_ctlcond); - } - } - - pthread_mutex_unlock(&s_ctlmutex); - } - else if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) { - if (pQMI->CTLMsg.QMICTLMsgHdr.CtlFlags == QMICTL_CTL_FLAG_RSP) { - if (!qlist_empty(&qmi_proxy_ctl_msg)) { - QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode); - - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - if (qmi_con->ClientFd == qmi_msg->ClientFd) { - send_qmi_to_client(pQMI, qmi_msg->ClientFd); - - if (pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType == QMICTL_GET_CLIENT_ID_RESP) - get_client_id(qmi_con, &pQMI->CTLMsg.GetClientIdRsp); - else if (pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType == QMICTL_RELEASE_CLIENT_ID_RESP) - release_client_id(qmi_con, &pQMI->CTLMsg.ReleaseClientIdRsp); - else { - } - } - } - - qlist_remove(&qmi_msg->qnode); - free(qmi_msg); - } - } - - if (!qlist_empty(&qmi_proxy_ctl_msg)) { - QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode); - - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - if (qmi_con->ClientFd == qmi_msg->ClientFd) { - send_qmi_to_cdc_wdm(qmi_msg->qmi); - } - } - } - } - else { - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - qlist_for_each(client_node, &qmi_con->client_qnode) { - QMI_PROXY_CLINET *qmi_client = qnode_to_item(client_node, QMI_PROXY_CLINET, qnode); - if (pQMI->QMIHdr.QMIType == qmi_client->QMIType) { - if (pQMI->QMIHdr.ClientId == 0 || pQMI->QMIHdr.ClientId == qmi_client->ClientId) { - send_qmi_to_client(pQMI, qmi_con->ClientFd); - } - } - } - } - } -} - -static int send_qmi(PQCQMIMSG pQMI, unsigned size, int clientfd) { - if (qmi_proxy_server_fd <= 0) { - send_qmi_to_cdc_wdm(pQMI); - } - else if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) { - QMI_PROXY_MSG *qmi_msg; - - if (qlist_empty(&qmi_proxy_ctl_msg)) - send_qmi_to_cdc_wdm(pQMI); - - qmi_msg = malloc(sizeof(QMI_PROXY_MSG) + size); - qlist_init(&qmi_msg->qnode); - qmi_msg->ClientFd = clientfd; - memcpy(qmi_msg->qmi, pQMI, size); - qlist_add_tail(&qmi_proxy_ctl_msg, &qmi_msg->qnode); - } - else { - send_qmi_to_cdc_wdm(pQMI); - } - - return 0; -} - -static int send_qmi_timeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned mseconds) { - int ret; - - pthread_mutex_lock(&s_ctlmutex); - - s_pCtlReq = pRequest; - s_pCtlRsq = NULL; - if (ppResponse) *ppResponse = NULL; - - send_qmi_to_cdc_wdm(pRequest); - ret = pthread_cond_timeout_np(&s_ctlcond, &s_ctlmutex, mseconds); - if (!ret) { - if (s_pCtlRsq && ppResponse) { - *ppResponse = s_pCtlRsq; - } else if (s_pCtlRsq) { - free(s_pCtlRsq); - } - } else { - dprintf("%s ret=%d\n", __func__, ret); - } - - s_pCtlReq = NULL; - pthread_mutex_unlock(&s_ctlmutex); - - return ret; -} - -static PQCQMUX_TLV qmi_find_tlv (PQCQMIMSG pQMI, uint8_t TLVType) { - int Length = 0; - - while (Length < le16_to_cpu(pQMI->MUXMsg.QMUXMsgHdr.Length)) { - PQCQMUX_TLV pTLV = (PQCQMUX_TLV)(&pQMI->MUXMsg.QMUXMsgHdr.payload[Length]); - - //dprintf("TLV {%02x, %04x}\n", pTLV->Type, pTLV->Length); - if (pTLV->Type == TLVType) { - return pTLV; - } - - Length += (le16_to_cpu((pTLV->Length)) + sizeof(QCQMUX_TLV)); - } - - return NULL; -} - -static int qmi_proxy_init(char *qmi_device, char* getidproduct) { - unsigned i; - int ret; - QCQMIMSG _QMI; - PQCQMIMSG pQMI = &_QMI; - PQCQMIMSG pRsp; - uint8_t TransactionId = 0xC1; - uint8_t WDAClientId = 0; - unsigned rx_urb_size = 0; - unsigned ep_type, iface_id; - - dprintf("%s enter\n", __func__); - - pQMI->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pQMI->QMIHdr.CtlFlags = 0x00; - pQMI->QMIHdr.QMIType = QMUX_TYPE_CTL; - pQMI->QMIHdr.ClientId= 0x00; - - pQMI->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; - - for (i = 0; i < 10; i++) { - pQMI->CTLMsg.SyncReq.TransactionId = TransactionId++; - pQMI->CTLMsg.SyncReq.QMICTLType = QMICTL_SYNC_REQ; - pQMI->CTLMsg.SyncReq.Length = 0; - - pQMI->QMIHdr.Length = pQMI->CTLMsg.QMICTLMsgHdr.Length + sizeof(QCQMI_HDR) + sizeof(QCQMICTL_MSG_HDR) - 1; - - ret = send_qmi_timeout(pQMI, NULL, 1000); - if (!ret) - break; - } - - if (ret) - goto qmi_proxy_init_fail; - - pQMI->CTLMsg.GetVersionReq.TransactionId = TransactionId++; - pQMI->CTLMsg.GetVersionReq.QMICTLType = QMICTL_GET_VERSION_REQ; - pQMI->CTLMsg.GetVersionReq.Length = 0x0004; - pQMI->CTLMsg.GetVersionReq.TLVType= QCTLV_TYPE_REQUIRED_PARAMETER; - pQMI->CTLMsg.GetVersionReq.TLVLength = 0x0001; - pQMI->CTLMsg.GetVersionReq.QMUXTypes = QMUX_TYPE_ALL; - - pQMI->QMIHdr.Length = pQMI->CTLMsg.QMICTLMsgHdr.Length + sizeof(QCQMI_HDR) + sizeof(QCQMICTL_MSG_HDR) - 1; - - ret = send_qmi_timeout(pQMI, &pRsp, 3000); - if (ret || (pRsp == NULL)) - goto qmi_proxy_init_fail; - - if (pRsp) { - uint8_t NumElements = 0; - if (pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult ||pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError) { - dprintf("QMICTL_GET_VERSION_REQ QMUXResult=%d, QMUXError=%d\n", - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult, pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError); - goto qmi_proxy_init_fail; - } - - for (NumElements = 0; NumElements < pRsp->CTLMsg.GetVersionRsp.NumElements; NumElements++) { - if (verbose_debug) - dprintf("QMUXType = %02x Version = %d.%d\n", - pRsp->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType, - pRsp->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MajorVersion, - pRsp->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion); - } - } - free(pRsp); - - pQMI->CTLMsg.GetClientIdReq.TransactionId = TransactionId++; - pQMI->CTLMsg.GetClientIdReq.QMICTLType = QMICTL_GET_CLIENT_ID_REQ; - pQMI->CTLMsg.GetClientIdReq.Length = 0x0004; - pQMI->CTLMsg.GetClientIdReq.TLVType= QCTLV_TYPE_REQUIRED_PARAMETER; - pQMI->CTLMsg.GetClientIdReq.TLVLength = 0x0001; - pQMI->CTLMsg.GetClientIdReq.QMIType = QMUX_TYPE_WDS_ADMIN; - - pQMI->QMIHdr.Length = pQMI->CTLMsg.QMICTLMsgHdr.Length + sizeof(QCQMI_HDR) + sizeof(QCQMICTL_MSG_HDR) - 1; - - ret = send_qmi_timeout(pQMI, &pRsp, 3000); - if (ret || (pRsp == NULL)) - goto qmi_proxy_init_fail; - - if (pRsp) { - if (pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult ||pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError) { - dprintf("QMICTL_GET_CLIENT_ID_REQ QMUXResult=%d, QMUXError=%d\n", - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult, pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError); - goto qmi_proxy_init_fail; - } - - WDAClientId = pRsp->CTLMsg.GetClientIdRsp.ClientId; - if (verbose_debug) dprintf("WDAClientId = %d\n", WDAClientId); - } - free(pRsp); - - if(qmidev_is_pciemhi(qmi_device)) - { - rx_urb_size = 32*1024; //must same as rx_urb_size defined in GobiNet&qmi_wwan driver //SDX24&SDX55 support 32KB - ep_type = 0x03; - } - else - { - rx_urb_size = 4*1024; //must same as rx_urb_size defined in GobiNet&qmi_wwan driver //SDX24&SDX55 support 32KB - ep_type = 0x02; - } - - printf("getidproduct=%s\n", getidproduct); - if(!strncasecmp(getidproduct, "0104", 4)|| !strncasecmp(getidproduct, "1001", 4) || !strncasecmp(getidproduct, "9025", 4)) - iface_id = 0x04; - else if(!strncasecmp(getidproduct, "0109", 4) || !strncasecmp(getidproduct, "1000", 4)) - iface_id = 0x02; - else if(!strncasecmp(getidproduct, "0113", 4)) - iface_id = 0x00; - - /*begin added by minchao.zhao@fibocom.com for mantis 91283 on 2021-09-27*/ - if(qmidev_is_pciemhi(qmi_device)) - iface_id = 0x04; //mhi_QMI0 enumeration arrangement - /*end added by minchao.zhao@fibocom.com for mantis 91283 on 2021-09-27*/ - printf("iface_id=%d\n", iface_id); - - pQMI->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pQMI->QMIHdr.CtlFlags = 0x00; - pQMI->QMIHdr.QMIType = QMUX_TYPE_WDS_ADMIN; - pQMI->QMIHdr.ClientId= WDAClientId; - - pQMI->MUXMsg.QMUXMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; - pQMI->MUXMsg.QMUXMsgHdr.TransactionId = TransactionId++; - - pQMI->MUXMsg.SetDataFormatReq.Type = QMIWDS_ADMIN_SET_DATA_FORMAT_REQ; - pQMI->MUXMsg.SetDataFormatReq.Length = sizeof(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG) - sizeof(QCQMUX_MSG_HDR); - -//Indicates whether the Quality of Service(QOS) data format is used by the client. - pQMI->MUXMsg.SetDataFormatReq.QosDataFormatTlv.TLVType = 0x10; - pQMI->MUXMsg.SetDataFormatReq.QosDataFormatTlv.TLVLength = cpu_to_le16(0x0001); - pQMI->MUXMsg.SetDataFormatReq.QosDataFormatTlv.QOSSetting = 0; /* no-QOS header */ -//Underlying Link Layer Protocol - pQMI->MUXMsg.SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVType = 0x11; - pQMI->MUXMsg.SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVLength = cpu_to_le16(4); - pQMI->MUXMsg.SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.Value = cpu_to_le32(0x02); /* Set IP mode */ -//Uplink (UL) data aggregation protocol to be used for uplink data transfer. - pQMI->MUXMsg.SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVType = 0x12; - pQMI->MUXMsg.SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4); - pQMI->MUXMsg.SetDataFormatReq.UplinkDataAggregationProtocolTlv.Value = cpu_to_le32(0x05); //UL QMAP is enabled -//Downlink (DL) data aggregation protocol to be used for downlink data transfer - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVType = 0x13; - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4); - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationProtocolTlv.Value = cpu_to_le32(0x05); //UL QMAP is enabled -//Maximum number of datagrams in a single aggregated packet on downlink - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.TLVType = 0x15; - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4); - if(qmidev_is_pciemhi(qmi_device)) - { - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32((rx_urb_size>2048)?(rx_urb_size/512):1); - } - else - { - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32((rx_urb_size>2048)?(rx_urb_size/1024):1); - } -//Maximum size in bytes of a single aggregated packet allowed on downlink - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVType = 0x16; - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4); - pQMI->MUXMsg.SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(rx_urb_size); -//Peripheral End Point ID - pQMI->MUXMsg.SetDataFormatReq.epTlv.TLVType = 0x17; - pQMI->MUXMsg.SetDataFormatReq.epTlv.TLVLength = cpu_to_le16(8); - pQMI->MUXMsg.SetDataFormatReq.epTlv.ep_type = cpu_to_le32(ep_type); // DATA_EP_TYPE_BAM_DMUX - pQMI->MUXMsg.SetDataFormatReq.epTlv.iface_id = cpu_to_le32(iface_id); - - pQMI->QMIHdr.Length = pQMI->MUXMsg.QMUXMsgHdr.Length + sizeof(QCQMI_HDR) + sizeof(QCQMUX_MSG_HDR) - 1; - - ret = send_qmi_timeout(pQMI, &pRsp, 3000); - if (ret || (pRsp == NULL)) - goto qmi_proxy_init_fail; - - if (pRsp) { - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV pFormat; - - if (pRsp->MUXMsg.QMUXMsgHdrResp.QMUXResult || pRsp->MUXMsg.QMUXMsgHdrResp.QMUXError) { - dprintf("QMIWDS_ADMIN_SET_DATA_FORMAT_REQ QMUXResult=%d, QMUXError=%d\n", - pRsp->MUXMsg.QMUXMsgHdrResp.QMUXResult, pRsp->MUXMsg.QMUXMsgHdrResp.QMUXError); - goto qmi_proxy_init_fail; - } - - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x11); - if (pFormat) - dprintf("link_prot %d\n", le32_to_cpu(pFormat->Value)); - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x12); - if (pFormat) - dprintf("ul_data_aggregation_protocol %d\n", le32_to_cpu(pFormat->Value)); - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x13); - if (pFormat) - dprintf("dl_data_aggregation_protocol %d\n", le32_to_cpu(pFormat->Value)); - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x15); - if (pFormat) - dprintf("dl_data_aggregation_max_datagrams %d\n", le32_to_cpu(pFormat->Value)); - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x16); - if (pFormat) { - dprintf("dl_data_aggregation_max_size %d\n", le32_to_cpu(pFormat->Value)); - rx_urb_size = le32_to_cpu(pFormat->Value); - } - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x17); - if (pFormat) - dprintf("ul_data_aggregation_max_datagrams %d\n", le32_to_cpu(pFormat->Value)); - pFormat = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)qmi_find_tlv(pRsp, 0x18); - if (pFormat) - dprintf("ul_data_aggregation_max_size %d\n", le32_to_cpu(pFormat->Value)); - } - free(pRsp); - - dprintf("%s finished, rx_urb_size is %u\n", __func__, rx_urb_size); - return 0; - -qmi_proxy_init_fail: - dprintf("%s failed\n", __func__); - return -1; -} -//2021-06-03 willa.liu@fibocom.com changed begin -static void qmi_start_server(void) { - qmi_proxy_server_fd = create_local_server("fibo_qmimsg_server"); - printf("%s: qmi_proxy_server_fd = %d\n", __func__, qmi_proxy_server_fd); - if (qmi_proxy_server_fd == -1) { - dprintf("%s Failed to create %s, errno: %d (%s)\n", __func__, "fibocom-qmi-proxy", errno, strerror(errno)); - } -} - -static void qmi_close_server(void) { - if (qmi_proxy_server_fd != -1) { - dprintf("%s %s close server\n", __func__, "fibocom-qmi-proxy"); - close(qmi_proxy_server_fd); - qmi_proxy_server_fd = -1; - } -} -//2021-06-03 willa.liu@fibocom.com changed end -static void *qmi_proxy_loop(void *param) -{ - static uint8_t qmi_buf[2048]; - PQCQMIMSG pQMI = (PQCQMIMSG)qmi_buf; - struct qlistnode *con_node; - QMI_PROXY_CONNECTION *qmi_con; - - dprintf("%s enter thread_id %ld\n", __func__, pthread_self()); - - qlist_init(&qmi_proxy_connection); - qlist_init(&qmi_proxy_ctl_msg); - - while (cdc_wdm_fd > 0 && qmi_proxy_quit == 0) { - struct pollfd pollfds[2+64]; - int ne, ret, nevents = 0; - ssize_t nreads; - - pollfds[nevents].fd = cdc_wdm_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (qmi_proxy_server_fd > 0) { - pollfds[nevents].fd = qmi_proxy_server_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - } - - qlist_for_each(con_node, &qmi_proxy_connection) { - qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - pollfds[nevents].fd = qmi_con->ClientFd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (nevents == (sizeof(pollfds)/sizeof(pollfds[0]))) - break; - } - - do { - //ret = poll(pollfds, nevents, -1); - ret = poll(pollfds, nevents, (qmi_proxy_server_fd > 0) ? -1 : 200); - } while (ret < 0 && errno == EINTR && qmi_proxy_quit == 0); - - if (ret < 0) { - dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); - goto qmi_proxy_loop_exit; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dprintf("%s poll fd = %d, revents = %04x\n", __func__, fd, revents); - if (fd == cdc_wdm_fd) { - goto qmi_proxy_loop_exit; - } else if(fd == qmi_proxy_server_fd) { - - } else { - cleanup_qmi_connection(fd); - } - - continue; - } - - if (!(pollfds[ne].revents & POLLIN)) { - continue; - } - - if (fd == qmi_proxy_server_fd) { - accept_qmi_connection(fd); - } - else if (fd == cdc_wdm_fd) { - nreads = read(fd, pQMI, sizeof(qmi_buf)); - if (verbose_debug) - { - ssize_t i; - printf("r %d %zd: ", fd, nreads); - for (i = 0; i < 16; i++) - printf("%02x ", ((uint8_t *)pQMI)[i]); - printf("\n"); - } - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)\n", __func__, (int)nreads, errno, strerror(errno)); - goto qmi_proxy_loop_exit; - } - - if (nreads != ((pQMI->QMIHdr.Length) + 1)) { - dprintf("%s nreads=%d, pQCQMI->QMIHdr.Length = %d\n", __func__, (int)nreads, (pQMI->QMIHdr.Length)); - continue; - } - - recv_qmi(pQMI, nreads); - } - else { - nreads = read(fd, pQMI, sizeof(qmi_buf)); - if (verbose_debug) - { - ssize_t i; - printf("r %d %zd: ", fd, nreads); - for (i = 0; i < 16; i++) - printf("%02x ", ((uint8_t *)pQMI)[i]); - printf("\n"); - } - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - cleanup_qmi_connection(fd); - break; - } - - if (nreads != ((pQMI->QMIHdr.Length) + 1)) { - dprintf("%s nreads=%d, pQCQMI->QMIHdr.Length = %d\n", __func__, (int)nreads, (pQMI->QMIHdr.Length)); - continue; - } - - send_qmi(pQMI, nreads, fd); - } - } - } - -qmi_proxy_loop_exit: - while (!qlist_empty(&qmi_proxy_connection)) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(qlist_head(&qmi_proxy_connection), QMI_PROXY_CONNECTION, qnode); - - cleanup_qmi_connection(qmi_con->ClientFd); - } - - dprintf("%s exit, thread_id %ld\n", __func__, pthread_self()); - - return NULL; -} - -static void qmidevice_detect(char **device_name, char **idproduct) { - struct dirent* ent = NULL; - DIR *pDir; - - char dir[255] = "/sys/bus/usb/devices"; - pDir = opendir(dir); - if (pDir) { - struct { - char subdir[255 * 2]; - char qmifile[255 * 2]; - } *pl; - pl = (typeof(pl)) malloc(sizeof(*pl)); - memset(pl, 0x00, sizeof(*pl)); - - while ((ent = readdir(pDir)) != NULL) { - struct dirent* subent = NULL; - DIR *psubDir; - char idVendor[4+1] = {0}; - char idProduct[4+1] = {0}; - int fd = 0; - - memset(pl, 0x00, sizeof(*pl)); - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/idVendor", dir, ent->d_name); - fd = open(pl->subdir, O_RDONLY); - if (fd > 0) { - read(fd, idVendor, 4); - close(fd); - } - - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/idProduct", dir, ent->d_name); - fd = open(pl->subdir, O_RDONLY); - if (fd > 0) { - read(fd, idProduct, 4); - close(fd); - } - - - if (strncasecmp(idVendor, "05c6", 4) && strncasecmp(idVendor, "2cb7", 4) && strncasecmp(idVendor, "1508", 4)) - continue; - - dprintf("Find %s/%s idVendor=%s idProduct=%s\n", dir, ent->d_name, idVendor, idProduct); - - if(((!strncasecmp(idVendor, "2cb7", 4)) && (!strncasecmp(idProduct, "0104", 4))) || ((!strncasecmp(idVendor, "1508", 4)) && (!strncasecmp(idProduct, "1001", 4))) || ((!strncasecmp(idVendor, "05c6", 4)) && (!strncasecmp(idProduct, "9025", 4)))) - { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.4/usbmisc", dir, ent->d_name); - if (access(pl->subdir, R_OK)) { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.4/usb", dir, ent->d_name); - if (access(pl->subdir, R_OK)) { - dprintf("no GobiQMI/usbmic/usb found in %s/%s:1.4\n", dir, ent->d_name); - continue; - } - } - } - else if((!strncasecmp(idVendor, "2cb7", 4) && !strncasecmp(idProduct, "0109", 4)) || (!strncasecmp(idVendor, "1508", 4) && !strncasecmp(idProduct, "1000", 4))) - { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.2/usbmisc", dir, ent->d_name); - if (access(pl->subdir, R_OK)) { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.2/usb", dir, ent->d_name); - if (access(pl->subdir, R_OK)) { - dprintf("no GobiQMI/usbmic/usb found in %s/%s:1.2\n", dir, ent->d_name); - continue; - } - } - } - else if(!strncasecmp(idVendor, "2cb7", 4) && !strncasecmp(idProduct, "0113", 4)) - { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.0/usbmisc", dir, ent->d_name); - if (access(pl->subdir, R_OK)) { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.0/usb", dir, ent->d_name); - if (access(pl->subdir, R_OK)) { - dprintf("no GobiQMI/usbmic/usb found in %s/%s:1.0\n", dir, ent->d_name); - continue; - } - } - } - - strncpy(idproduct,idProduct, sizeof(idProduct)); - psubDir = opendir(pl->subdir); - if (pDir == NULL) { - dprintf("Cannot open directory: %s, errno: %d (%s)\n", dir, errno, strerror(errno)); - continue; - } - - while ((subent = readdir(psubDir)) != NULL) { - if (subent->d_name[0] == '.') - continue; - dprintf("Find %s/%s\n", pl->subdir, subent->d_name); - snprintf(pl->qmifile, sizeof(pl->qmifile), "/dev/%s", subent->d_name); - break; - } - *device_name = strdup(pl->qmifile); - closedir(psubDir); - } - closedir(pDir); - free(pl); - } -} - -static void usage(void) { - dprintf(" -d A valid qmi device\n" - " default /dev/cdc-wdm0, but cdc-wdm0 may be invalid\n" - " -v Will show all details\n"); -} - -static void sig_action(int sig) { - if (qmi_proxy_quit == 0) { - qmi_proxy_quit = 1; - if (thread_id) - pthread_kill(thread_id, sig); - } -} - -int main(int argc, char *argv[]) { - int opt; - char *cdc_wdm = NULL; - int retry_times = 0; - char getidproduct[5] = {0}; - optind = 1; - - signal(SIGINT, sig_action); - - while ( -1 != (opt = getopt(argc, argv, "d:v"))) { - switch (opt) { - case 'd': - cdc_wdm = strdup(optarg); - break; - case 'v': - verbose_debug = 1; - break; - default: - usage(); - break; - } - } - - if (cdc_wdm == NULL) - qmidevice_detect(&cdc_wdm, &getidproduct); - if (cdc_wdm == NULL) { - dprintf("Fail to find any /dev/cdc-wdm device. break\n"); - return -1; - } - - if (access(cdc_wdm, R_OK | W_OK)) { - dprintf("Fail to access %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno)); - free(cdc_wdm); - return -1; - } - - while (qmi_proxy_quit == 0) { - if (access(cdc_wdm, R_OK | W_OK)) { - dprintf("Fail to access %s, errno: %d (%s). continue\n", cdc_wdm, errno, strerror(errno)); - // wait device - sleep(3); - continue; - } - - dprintf("Will use cdc-wdm %s\n", cdc_wdm); - - cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (cdc_wdm_fd == -1) { - dprintf("Failed to open %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno)); - return -1; - } - cfmakenoblock(cdc_wdm_fd); - - /* no qmi_proxy_loop lives, create one */ - pthread_create(&thread_id, NULL, qmi_proxy_loop, NULL); - /* try to redo init if failed, init function must be successfully */ - while (qmi_proxy_init(cdc_wdm, getidproduct) != 0) { - if (retry_times < 5) { - dprintf("fail to init proxy, try again in 2 seconds.\n"); - sleep(2); - retry_times++; - } else { - dprintf("has failed too much times, restart the modem and have a try...\n"); - break; - } - /* break loop if modem is detached */ - if (access(cdc_wdm, F_OK|R_OK|W_OK)) - break; - } - retry_times = 0; - qmi_start_server(); - pthread_join(thread_id, NULL); - - /* close local server at last */ - qmi_close_server(); - close(cdc_wdm_fd); - } - - if (cdc_wdm) { - free(cdc_wdm); - } - return 0; -} diff --git a/fibocom-dial/src/libmnl/README b/fibocom-dial/src/libmnl/README deleted file mode 100644 index fbac9d2..0000000 --- a/fibocom-dial/src/libmnl/README +++ /dev/null @@ -1,28 +0,0 @@ -= What is libmnl? = - -libmnl is a minimalistic user-space library oriented to Netlink developers. -There are a lot of common tasks in parsing, validating, constructing of -both the Netlink header and TLVs that are repetitive and easy to get wrong. -This library aims to provide simple helpers that allows you to re-use code -and to avoid re-inventing the wheel. The main features of this library are: - -* Small: the shared library requires around 30KB for an x86-based computer. -* Simple: this library avoids complexity and elaborated abstractions that -tend to hide Netlink details. -* Easy to use: the library simplifies the work for Netlink-wise developers. -It provides functions to make socket handling, message building, validating, -parsing and sequence tracking, easier. -* Easy to re-use: you can use the library to build your own abstraction layer -on top of this library. -* Decoupling: the interdependency of the main bricks that compose the library -is reduced, i.e. the library provides many helpers, but the programmer is not -forced to use them. - -= Example files = - -You can find several example files under examples/ that you can compile by -invoking `make check'. - --- -08/sep/2010 -Pablo Neira Ayuso diff --git a/fibocom-dial/src/libmnl/attr.c b/fibocom-dial/src/libmnl/attr.c deleted file mode 100644 index 30eb537..0000000 --- a/fibocom-dial/src/libmnl/attr.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * (C) 2008-2012 by Pablo Neira Ayuso - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - */ -#include /* for INT_MAX */ -#include -#include - -#include "libmnl.h" - -/** - * \defgroup attr Netlink attribute helpers - * - * Netlink Type-Length-Value (TLV) attribute: - * \verbatim - |<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->| - ------------------------------------------------- - | length | type | value | - ------------------------------------------------- - |<--------- header ------------>|<-- payload --->| -\endverbatim - * The payload of the Netlink message contains sequences of attributes that are - * expressed in TLV format. - * - * @{ - */ - -/** - * mnl_attr_get_type - get type of netlink attribute - * \param attr pointer to netlink attribute - * - * This function returns the attribute type. - */ -uint16_t mnl_attr_get_type(const struct nlattr *attr) -{ - return attr->nla_type & NLA_TYPE_MASK; -} - -/** - * mnl_attr_get_len - get length of netlink attribute - * \param attr pointer to netlink attribute - * - * This function returns the attribute length that is the attribute header - * plus the attribute payload. - */ -uint16_t mnl_attr_get_len(const struct nlattr *attr) -{ - return attr->nla_len; -} - -/** - * mnl_attr_get_payload_len - get the attribute payload-value length - * \param attr pointer to netlink attribute - * - * This function returns the attribute payload-value length. - */ -uint16_t mnl_attr_get_payload_len(const struct nlattr *attr) -{ - return attr->nla_len - MNL_ATTR_HDRLEN; -} - -/** - * mnl_attr_get_payload - get pointer to the attribute payload - * \param attr pointer to netlink attribute - * - * This function return a pointer to the attribute payload. - */ -void *mnl_attr_get_payload(const struct nlattr *attr) -{ - return (void *)attr + MNL_ATTR_HDRLEN; -} - -/** - * mnl_attr_ok - check if there is room for an attribute in a buffer - * \param attr attribute that we want to check if there is room for - * \param len remaining bytes in a buffer that contains the attribute - * - * This function is used to check that a buffer, which is supposed to contain - * an attribute, has enough room for the attribute that it stores, i.e. this - * function can be used to verify that an attribute is neither malformed nor - * truncated. - * - * This function does not set errno in case of error since it is intended - * for iterations. Thus, it returns true on success and false on error. - * - * The len parameter may be negative in the case of malformed messages during - * attribute iteration, that is why we use a signed integer. - */ -bool mnl_attr_ok(const struct nlattr *attr, int len) -{ - return len >= (int)sizeof(struct nlattr) && - attr->nla_len >= sizeof(struct nlattr) && - (int)attr->nla_len <= len; -} - -/** - * mnl_attr_next - get the next attribute in the payload of a netlink message - * \param attr pointer to the current attribute - * - * This function returns a pointer to the next attribute after the one passed - * as parameter. You have to use mnl_attr_ok() to ensure that the next - * attribute is valid. - */ -struct nlattr *mnl_attr_next(const struct nlattr *attr) -{ - return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len)); -} - -/** - * mnl_attr_type_valid - check if the attribute type is valid - * \param attr pointer to attribute to be checked - * \param max maximum attribute type - * - * This function allows to check if the attribute type is higher than the - * maximum supported type. If the attribute type is invalid, this function - * returns -1 and errno is explicitly set. On success, this function returns 1. - * - * Strict attribute checking in user-space is not a good idea since you may - * run an old application with a newer kernel that supports new attributes. - * This leads to backward compatibility breakages in user-space. Better check - * if you support an attribute, if not, skip it. - */ -int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max) -{ - if (mnl_attr_get_type(attr) > max) { - errno = EOPNOTSUPP; - return -1; - } - return 1; -} - -static int __mnl_attr_validate(const struct nlattr *attr, - enum mnl_attr_data_type type, size_t exp_len) -{ - uint16_t attr_len = mnl_attr_get_payload_len(attr); - const char *attr_data = mnl_attr_get_payload(attr); - - if (attr_len < exp_len) { - errno = ERANGE; - return -1; - } - switch(type) { - case MNL_TYPE_FLAG: - if (attr_len > 0) { - errno = ERANGE; - return -1; - } - break; - case MNL_TYPE_NUL_STRING: - if (attr_len == 0) { - errno = ERANGE; - return -1; - } - if (attr_data[attr_len-1] != '\0') { - errno = EINVAL; - return -1; - } - break; - case MNL_TYPE_STRING: - if (attr_len == 0) { - errno = ERANGE; - return -1; - } - break; - case MNL_TYPE_NESTED: - /* empty nested attributes are OK. */ - if (attr_len == 0) - break; - /* if not empty, they must contain one header, eg. flag */ - if (attr_len < MNL_ATTR_HDRLEN) { - errno = ERANGE; - return -1; - } - break; - default: - /* make gcc happy. */ - break; - } - if (exp_len && attr_len > exp_len) { - errno = ERANGE; - return -1; - } - return 0; -} - -static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = { - [MNL_TYPE_U8] = sizeof(uint8_t), - [MNL_TYPE_U16] = sizeof(uint16_t), - [MNL_TYPE_U32] = sizeof(uint32_t), - [MNL_TYPE_U64] = sizeof(uint64_t), - [MNL_TYPE_MSECS] = sizeof(uint64_t), -}; - -/** - * mnl_attr_validate - validate netlink attribute (simplified version) - * \param attr pointer to netlink attribute that we want to validate - * \param type data type (see enum mnl_attr_data_type) - * - * The validation is based on the data type. Specifically, it checks that - * integers (u8, u16, u32 and u64) have enough room for them. This function - * returns -1 in case of error, and errno is explicitly set. - */ -int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type) -{ - int exp_len; - - if (type >= MNL_TYPE_MAX) { - errno = EINVAL; - return -1; - } - exp_len = mnl_attr_data_type_len[type]; - return __mnl_attr_validate(attr, type, exp_len); -} - -/** - * mnl_attr_validate2 - validate netlink attribute (extended version) - * \param attr pointer to netlink attribute that we want to validate - * \param type attribute type (see enum mnl_attr_data_type) - * \param exp_len expected attribute data size - * - * This function allows to perform a more accurate validation for attributes - * whose size is variable. If the size of the attribute is not what we expect, - * this functions returns -1 and errno is explicitly set. - */ -int mnl_attr_validate2(const struct nlattr *attr, - enum mnl_attr_data_type type, - size_t exp_len) -{ - if (type >= MNL_TYPE_MAX) { - errno = EINVAL; - return -1; - } - return __mnl_attr_validate(attr, type, exp_len); -} - -/** - * mnl_attr_parse - parse attributes - * \param nlh pointer to netlink message - * \param offset offset to start parsing from (if payload is after any header) - * \param cb callback function that is called for each attribute - * \param data pointer to data that is passed to the callback function - * - * This function allows to iterate over the sequence of attributes that compose - * the Netlink message. You can then put the attribute in an array as it - * usually happens at this stage or you can use any other data structure (such - * as lists or trees). - * - * This function propagates the return value of the callback, which can be - * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP. - */ -int mnl_attr_parse(const struct nlmsghdr *nlh, - unsigned int offset, mnl_attr_cb_t cb, - void *data) -{ - int ret = MNL_CB_OK; - const struct nlattr *attr; - - mnl_attr_for_each(attr, nlh, offset) - if ((ret = cb(attr, data)) <= MNL_CB_STOP) - return ret; - return ret; -} - -/** - * mnl_attr_parse_nested - parse attributes inside a nest - * \param nested pointer to netlink attribute that contains a nest - * \param cb callback function that is called for each attribute in the nest - * \param data pointer to data passed to the callback function - * - * This function allows to iterate over the sequence of attributes that compose - * the Netlink message. You can then put the attribute in an array as it - * usually happens at this stage or you can use any other data structure (such - * as lists or trees). - * - * This function propagates the return value of the callback, which can be - * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP. - */ -int mnl_attr_parse_nested(const struct nlattr *nested, - mnl_attr_cb_t cb, void *data) -{ - int ret = MNL_CB_OK; - const struct nlattr *attr; - - mnl_attr_for_each_nested(attr, nested) - if ((ret = cb(attr, data)) <= MNL_CB_STOP) - return ret; - return ret; -} - -/** - * mnl_attr_parse_payload - parse attributes in payload of Netlink message - * \param payload pointer to payload of the Netlink message - * \param payload_len payload length that contains the attributes - * \param cb callback function that is called for each attribute - * \param data pointer to data that is passed to the callback function - * - * This function takes a pointer to the area that contains the attributes, - * commonly known as the payload of the Netlink message. Thus, you have to - * pass a pointer to the Netlink message payload, instead of the entire - * message. - * - * This function allows you to iterate over the sequence of attributes that are - * located at some payload offset. You can then put the attributes in one array - * as usual, or you can use any other data structure (such as lists or trees). - * - * This function propagates the return value of the callback, which can be - * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP. - */ -int mnl_attr_parse_payload(const void *payload, - size_t payload_len, - mnl_attr_cb_t cb, void *data) -{ - int ret = MNL_CB_OK; - const struct nlattr *attr; - - mnl_attr_for_each_payload(payload, payload_len) - if ((ret = cb(attr, data)) <= MNL_CB_STOP) - return ret; - return ret; -} - -/** - * mnl_attr_get_u8 - returns 8-bit unsigned integer attribute payload - * \param attr pointer to netlink attribute - * - * This function returns the 8-bit value of the attribute payload. - */ -uint8_t mnl_attr_get_u8(const struct nlattr *attr) -{ - return *((uint8_t *)mnl_attr_get_payload(attr)); -} - -/** - * mnl_attr_get_u16 - returns 16-bit unsigned integer attribute payload - * \param attr pointer to netlink attribute - * - * This function returns the 16-bit value of the attribute payload. - */ -uint16_t mnl_attr_get_u16(const struct nlattr *attr) -{ - return *((uint16_t *)mnl_attr_get_payload(attr)); -} - -/** - * mnl_attr_get_u32 - returns 32-bit unsigned integer attribute payload - * \param attr pointer to netlink attribute - * - * This function returns the 32-bit value of the attribute payload. - */ -uint32_t mnl_attr_get_u32(const struct nlattr *attr) -{ - return *((uint32_t *)mnl_attr_get_payload(attr)); -} - -/** - * mnl_attr_get_u64 - returns 64-bit unsigned integer attribute. - * \param attr pointer to netlink attribute - * - * This function returns the 64-bit value of the attribute payload. This - * function is align-safe, since accessing 64-bit Netlink attributes is a - * common source of alignment issues. - */ -uint64_t mnl_attr_get_u64(const struct nlattr *attr) -{ - uint64_t tmp; - memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp)); - return tmp; -} - -/** - * mnl_attr_get_str - returns pointer to string attribute. - * \param attr pointer to netlink attribute - * - * This function returns the payload of string attribute value. - */ -const char *mnl_attr_get_str(const struct nlattr *attr) -{ - return mnl_attr_get_payload(attr); -} - -/** - * mnl_attr_put - add an attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type that you want to add - * \param len netlink attribute payload length - * \param data pointer to the data that will be stored by the new attribute - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, - size_t len, const void *data) -{ - struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh); - uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len; - int pad; - - attr->nla_type = type; - attr->nla_len = payload_len; - memcpy(mnl_attr_get_payload(attr), data, len); - pad = MNL_ALIGN(len) - len; - if (pad > 0) - memset(mnl_attr_get_payload(attr) + len, 0, pad); - - nlh->nlmsg_len += MNL_ALIGN(payload_len); -} - -/** - * mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * \param data 8-bit unsigned integer data that is stored by the new attribute - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, - uint8_t data) -{ - mnl_attr_put(nlh, type, sizeof(uint8_t), &data); -} - -/** - * mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * \param data 16-bit unsigned integer data that is stored by the new attribute - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, - uint16_t data) -{ - mnl_attr_put(nlh, type, sizeof(uint16_t), &data); -} - -/** - * mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * \param data 32-bit unsigned integer data that is stored by the new attribute - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, - uint32_t data) -{ - mnl_attr_put(nlh, type, sizeof(uint32_t), &data); -} - -/** - * mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * \param data 64-bit unsigned integer data that is stored by the new attribute - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, - uint64_t data) -{ - mnl_attr_put(nlh, type, sizeof(uint64_t), &data); -} - -/** - * mnl_attr_put_str - add string attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * \param data pointer to string data that is stored by the new attribute - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, - const char *data) -{ - mnl_attr_put(nlh, type, strlen(data), data); -} - -/** - * mnl_attr_put_strz - add string attribute to netlink message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * \param data pointer to string data that is stored by the new attribute - * - * This function is similar to mnl_attr_put_str, but it includes the - * NUL/zero ('\0') terminator at the end of the string. - * - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, - const char *data) -{ - mnl_attr_put(nlh, type, strlen(data)+1, data); -} - -/** - * mnl_attr_nest_start - start an attribute nest - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * - * This function adds the attribute header that identifies the beginning of - * an attribute nest. This function always returns a valid pointer to the - * beginning of the nest. - */ -struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, - uint16_t type) -{ - struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh); - - /* set start->nla_len in mnl_attr_nest_end() */ - start->nla_type = NLA_F_NESTED | type; - nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr)); - - return start; -} - -/** - * mnl_attr_put_check - add an attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type that you want to add - * \param len netlink attribute payload length - * \param data pointer to the data that will be stored by the new attribute - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - */ -bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, size_t len, - const void *data) -{ - if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen) - return false; - mnl_attr_put(nlh, type, len, data); - return true; -} - -/** - * mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type - * \param data 8-bit unsigned integer data that is stored by the new attribute - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - */ -bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint8_t data) -{ - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data); -} - -/** - * mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type - * \param data 16-bit unsigned integer data that is stored by the new attribute - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint16_t data) -{ - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data); -} - -/** - * mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type - * \param data 32-bit unsigned integer data that is stored by the new attribute - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint32_t data) -{ - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data); -} - -/** - * mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type - * \param data 64-bit unsigned integer data that is stored by the new attribute - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint64_t data) -{ - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data); -} - -/** - * mnl_attr_put_str_check - add string attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type - * \param data pointer to string data that is stored by the new attribute - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - * This function updates the length field of the Netlink message (nlmsg_len) - * by adding the size (header + payload) of the new attribute. - */ -bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, const char *data) -{ - return mnl_attr_put_check(nlh, buflen, type, strlen(data), data); -} - -/** - * mnl_attr_put_strz_check - add string attribute to netlink message - * \param nlh pointer to the netlink message - * \param buflen size of buffer which stores the message - * \param type netlink attribute type - * \param data pointer to string data that is stored by the new attribute - * - * This function is similar to mnl_attr_put_str, but it includes the - * NUL/zero ('\0') terminator at the end of the string. - * - * This function first checks that the data can be added to the message - * (fits into the buffer) and then updates the length field of the Netlink - * message (nlmsg_len) by adding the size (header + payload) of the new - * attribute. The function returns true if the attribute could be added - * to the message, otherwise false is returned. - */ -bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, const char *data) -{ - return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data); -} - -/** - * mnl_attr_nest_start_check - start an attribute nest - * \param buflen size of buffer which stores the message - * \param nlh pointer to the netlink message - * \param type netlink attribute type - * - * This function adds the attribute header that identifies the beginning of - * an attribute nest. If the nested attribute cannot be added then NULL, - * otherwise valid pointer to the beginning of the nest is returned. - */ -struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, - size_t buflen, - uint16_t type) -{ - if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen) - return NULL; - return mnl_attr_nest_start(nlh, type); -} - -/** - * mnl_attr_nest_end - end an attribute nest - * \param nlh pointer to the netlink message - * \param start pointer to the attribute nest returned by mnl_attr_nest_start() - * - * This function updates the attribute header that identifies the nest. - */ -void mnl_attr_nest_end(struct nlmsghdr *nlh, - struct nlattr *start) -{ - start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start; -} - -/** - * mnl_attr_nest_cancel - cancel an attribute nest - * \param nlh pointer to the netlink message - * \param start pointer to the attribute nest returned by mnl_attr_nest_start() - * - * This function updates the attribute header that identifies the nest. - */ -void mnl_attr_nest_cancel(struct nlmsghdr *nlh, - struct nlattr *start) -{ - nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start; -} - -/** - * @} - */ diff --git a/fibocom-dial/src/libmnl/callback.c b/fibocom-dial/src/libmnl/callback.c deleted file mode 100644 index 8283a93..0000000 --- a/fibocom-dial/src/libmnl/callback.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * (C) 2008-2010 by Pablo Neira Ayuso - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - */ - -#include - -#include "libmnl.h" - -static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data) -{ - return MNL_CB_OK; -} - -static int mnl_cb_error(const struct nlmsghdr *nlh, void *data) -{ - const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh); - - if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) { - errno = EBADMSG; - return MNL_CB_ERROR; - } - /* Netlink subsystems returns the errno value with different signess */ - if (err->error < 0) - errno = -err->error; - else - errno = err->error; - - return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; -} - -static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data) -{ - return MNL_CB_STOP; -} - -static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = { - [NLMSG_NOOP] = mnl_cb_noop, - [NLMSG_ERROR] = mnl_cb_error, - [NLMSG_DONE] = mnl_cb_stop, - [NLMSG_OVERRUN] = mnl_cb_noop, -}; - -static inline int __mnl_cb_run(const void *buf, size_t numbytes, - unsigned int seq, unsigned int portid, - mnl_cb_t cb_data, void *data, - const mnl_cb_t *cb_ctl_array, - unsigned int cb_ctl_array_len) -{ - int ret = MNL_CB_OK, len = numbytes; - const struct nlmsghdr *nlh = buf; - - while (mnl_nlmsg_ok(nlh, len)) { - /* check message source */ - if (!mnl_nlmsg_portid_ok(nlh, portid)) { - errno = ESRCH; - return -1; - } - /* perform sequence tracking */ - if (!mnl_nlmsg_seq_ok(nlh, seq)) { - errno = EPROTO; - return -1; - } - - /* dump was interrupted */ - if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) { - errno = EINTR; - return -1; - } - - /* netlink data message handling */ - if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { - if (cb_data){ - ret = cb_data(nlh, data); - if (ret <= MNL_CB_STOP) - goto out; - } - } else if (nlh->nlmsg_type < cb_ctl_array_len) { - if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) { - ret = cb_ctl_array[nlh->nlmsg_type](nlh, data); - if (ret <= MNL_CB_STOP) - goto out; - } - } else if (default_cb_array[nlh->nlmsg_type]) { - ret = default_cb_array[nlh->nlmsg_type](nlh, data); - if (ret <= MNL_CB_STOP) - goto out; - } - nlh = mnl_nlmsg_next(nlh, &len); - } -out: - return ret; -} - -/** - * \defgroup callback Callback helpers - * @{ - */ - -/** - * mnl_cb_run2 - callback runqueue for netlink messages - * \param buf buffer that contains the netlink messages - * \param numbytes number of bytes stored in the buffer - * \param seq sequence number that we expect to receive - * \param portid Netlink PortID that we expect to receive - * \param cb_data callback handler for data messages - * \param data pointer to data that will be passed to the data callback handler - * \param cb_ctl_array array of custom callback handlers from control messages - * \param cb_ctl_array_len array length of custom control callback handlers - * - * You can set the cb_ctl_array to NULL if you want to use the default control - * callback handlers, in that case, the parameter cb_ctl_array_len is not - * checked. - * - * Your callback may return three possible values: - * - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue. - * - MNL_CB_STOP (=0): stop callback runqueue. - * - MNL_CB_OK (>=1): no problem has occurred. - * - * This function propagates the callback return value. On error, it returns - * -1 and errno is explicitly set. If the portID is not the expected, errno - * is set to ESRCH. If the sequence number is not the expected, errno is set - * to EPROTO. If the dump was interrupted, errno is set to EINTR and you should - * request a new fresh dump again. - */ -int mnl_cb_run2(const void *buf, size_t numbytes, - unsigned int seq, unsigned int portid, - mnl_cb_t cb_data, void *data, - const mnl_cb_t *cb_ctl_array, - unsigned int cb_ctl_array_len) -{ - return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, - cb_ctl_array, cb_ctl_array_len); -} - -/** - * mnl_cb_run - callback runqueue for netlink messages (simplified version) - * \param buf buffer that contains the netlink messages - * \param numbytes number of bytes stored in the buffer - * \param seq sequence number that we expect to receive - * \param portid Netlink PortID that we expect to receive - * \param cb_data callback handler for data messages - * \param data pointer to data that will be passed to the data callback handler - * - * This function is like mnl_cb_run2() but it does not allow you to set - * the control callback handlers. - * - * Your callback may return three possible values: - * - MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue. - * - MNL_CB_STOP (=0): stop callback runqueue. - * - MNL_CB_OK (>=1): no problems has occurred. - * - * This function propagates the callback return value. - */ -int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, - unsigned int portid, mnl_cb_t cb_data, void *data) -{ - return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0); -} - -/** - * @} - */ diff --git a/fibocom-dial/src/libmnl/dhcp/dhcp.h b/fibocom-dial/src/libmnl/dhcp/dhcp.h deleted file mode 100644 index f480285..0000000 --- a/fibocom-dial/src/libmnl/dhcp/dhcp.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef __DHCP_H__ -#define __DHCP_H__ - -int do_dhcp(char *iname); -#endif //__DHCP_H__ \ No newline at end of file diff --git a/fibocom-dial/src/libmnl/dhcp/dhcpclient.c b/fibocom-dial/src/libmnl/dhcp/dhcpclient.c deleted file mode 100644 index ccb71b5..0000000 --- a/fibocom-dial/src/libmnl/dhcp/dhcpclient.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../ifutils.h" -#include "dhcpmsg.h" -#include "packet.h" - -#define VERBOSE 2 - -static int verbose = 1; -static char errmsg[2048]; - -typedef unsigned long long msecs_t; -#if VERBOSE -void dump_dhcp_msg(); -#endif - -msecs_t get_msecs(void) -{ - struct timespec ts; - - if (clock_gettime(CLOCK_MONOTONIC, &ts)) { - return 0; - } else { - return (((msecs_t) ts.tv_sec) * ((msecs_t) 1000)) + - (((msecs_t) ts.tv_nsec) / ((msecs_t) 1000000)); - } -} - -void printerr(char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsnprintf(errmsg, sizeof(errmsg), fmt, ap); - va_end(ap); - - printf("%s\n", errmsg); -} - -const char *dhcp_lasterror() -{ - return errmsg; -} - -int fatal(const char *reason) -{ - printerr("%s: %s\n", reason, strerror(errno)); - return -1; -// exit(1); -} - -typedef struct dhcp_info dhcp_info; - -struct dhcp_info { - uint32_t type; - - uint32_t ipaddr; - uint32_t gateway; - uint32_t prefixLength; - - uint32_t dns1; - uint32_t dns2; - - uint32_t serveraddr; - uint32_t lease; -}; - -dhcp_info last_good_info; - -void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *prefixLength, - uint32_t *dns1, uint32_t *dns2, uint32_t *server, - uint32_t *lease) -{ - *ipaddr = last_good_info.ipaddr; - *gateway = last_good_info.gateway; - *prefixLength = last_good_info.prefixLength; - *dns1 = last_good_info.dns1; - *dns2 = last_good_info.dns2; - *server = last_good_info.serveraddr; - *lease = last_good_info.lease; -} - -static int dhcp_configure(const char *ifname, dhcp_info *info) -{ - last_good_info = *info; - return if_set_network_v4(ifname, info->ipaddr, info->prefixLength, info->gateway, - info->dns1, info->dns2); -} - -static const char *dhcp_type_to_name(uint32_t type) -{ - switch(type) { - case DHCPDISCOVER: return "discover"; - case DHCPOFFER: return "offer"; - case DHCPREQUEST: return "request"; - case DHCPDECLINE: return "decline"; - case DHCPACK: return "ack"; - case DHCPNAK: return "nak"; - case DHCPRELEASE: return "release"; - case DHCPINFORM: return "inform"; - default: return "???"; - } -} - -void dump_dhcp_info(dhcp_info *info) -{ - char addr[20], gway[20]; - printf("--- dhcp %s (%d) ---\n", - dhcp_type_to_name(info->type), info->type); - strcpy(addr, ipaddr_to_string_v4(info->ipaddr)); - strcpy(gway, ipaddr_to_string_v4(info->gateway)); - printf("ip %s gw %s prefixLength %d\n", addr, gway, info->prefixLength); - if (info->dns1) printf("dns1: %s\n", ipaddr_to_string_v4(info->dns1)); - if (info->dns2) printf("dns2: %s\n", ipaddr_to_string_v4(info->dns2)); - printf("server %s, lease %d seconds\n", - ipaddr_to_string_v4(info->serveraddr), info->lease); -} - - -int decode_dhcp_msg(dhcp_msg *msg, int len, dhcp_info *info) -{ - uint8_t *x; - unsigned int opt; - int optlen; - - memset(info, 0, sizeof(dhcp_info)); - if (len < (DHCP_MSG_FIXED_SIZE + 4)) return -1; - - len -= (DHCP_MSG_FIXED_SIZE + 4); - - if (msg->options[0] != OPT_COOKIE1) return -1; - if (msg->options[1] != OPT_COOKIE2) return -1; - if (msg->options[2] != OPT_COOKIE3) return -1; - if (msg->options[3] != OPT_COOKIE4) return -1; - - x = msg->options + 4; - - while (len > 2) { - opt = *x++; - if (opt == OPT_PAD) { - len--; - continue; - } - if (opt == OPT_END) { - break; - } - optlen = *x++; - len -= 2; - if (optlen > len) { - break; - } - switch(opt) { - case OPT_SUBNET_MASK: - if (optlen >= 4) { - in_addr_t mask; - memcpy(&mask, x, 4); - info->prefixLength = mask_to_prefix_v4(mask); - } - break; - case OPT_GATEWAY: - if (optlen >= 4) memcpy(&info->gateway, x, 4); - break; - case OPT_DNS: - if (optlen >= 4) memcpy(&info->dns1, x + 0, 4); - if (optlen >= 8) memcpy(&info->dns2, x + 4, 4); - break; - case OPT_LEASE_TIME: - if (optlen >= 4) { - memcpy(&info->lease, x, 4); - info->lease = ntohl(info->lease); - } - break; - case OPT_SERVER_ID: - if (optlen >= 4) memcpy(&info->serveraddr, x, 4); - break; - case OPT_MESSAGE_TYPE: - info->type = *x; - break; - default: - break; - } - x += optlen; - len -= optlen; - } - - info->ipaddr = msg->yiaddr; - - return 0; -} - -#if VERBOSE - -static void hex2str(char *buf, size_t buf_size, const unsigned char *array, int len) -{ - int i; - char *cp = buf; - char *buf_end = buf + buf_size; - for (i = 0; i < len; i++) { - cp += snprintf(cp, buf_end - cp, " %02x ", array[i]); - } -} - -void dump_dhcp_msg(dhcp_msg *msg, int len) -{ - unsigned char *x; - unsigned int n,c; - int optsz; - const char *name; - char buf[2048]; - - if (len < DHCP_MSG_FIXED_SIZE) { - printf("Invalid length %d, should be %d", len, DHCP_MSG_FIXED_SIZE); - return; - } - - len -= DHCP_MSG_FIXED_SIZE; - - if (msg->op == OP_BOOTREQUEST) - name = "BOOTREQUEST"; - else if (msg->op == OP_BOOTREPLY) - name = "BOOTREPLY"; - else - name = "????"; - - c = msg->hlen > 16 ? 16 : msg->hlen; - hex2str(buf, sizeof(buf), msg->chaddr, c); - - for (n = 0; n < 64; n++) { - unsigned char x = msg->sname[n]; - if ((x < ' ') || (x > 127)) { - if (x == 0) break; - msg->sname[n] = '.'; - } - } - msg->sname[63] = 0; - - for (n = 0; n < 128; n++) { - unsigned char x = msg->file[n]; - if ((x < ' ') || (x > 127)) { - if (x == 0) break; - msg->file[n] = '.'; - } - } - msg->file[127] = 0; - - if (len < 4) return; - len -= 4; - x = msg->options + 4; - - while (len > 2) { - if (*x == 0) { - x++; - len--; - continue; - } - if (*x == OPT_END) { - break; - } - len -= 2; - optsz = x[1]; - if (optsz > len) break; - if (x[0] == OPT_DOMAIN_NAME || x[0] == OPT_MESSAGE) { - if ((unsigned int)optsz < sizeof(buf) - 1) { - n = optsz; - } else { - n = sizeof(buf) - 1; - } - memcpy(buf, &x[2], n); - buf[n] = '\0'; - } else { - hex2str(buf, sizeof(buf), &x[2], optsz); - } - if (x[0] == OPT_MESSAGE_TYPE) - name = dhcp_type_to_name(x[2]); - else - name = NULL; - len -= optsz; - x = x + optsz + 2; - } -} - -#endif - -static int send_message(int sock, int if_index, dhcp_msg *msg, int size) -{ -#if VERBOSE > 1 - dump_dhcp_msg(msg, size); -#endif - return send_packet(sock, if_index, msg, size, INADDR_ANY, INADDR_BROADCAST, - PORT_BOOTP_CLIENT, PORT_BOOTP_SERVER); -} - -static int is_valid_reply(dhcp_msg *msg, dhcp_msg *reply, int sz) -{ - if (sz < DHCP_MSG_FIXED_SIZE) { - if (verbose) printf("Wrong size %d != %d\n", sz, DHCP_MSG_FIXED_SIZE); - return 0; - } - if (reply->op != OP_BOOTREPLY) { - if (verbose) printf("Wrong Op %d != %d\n", reply->op, OP_BOOTREPLY); - return 0; - } - if (reply->xid != msg->xid) { - if (verbose) printf("Wrong Xid 0x%x != 0x%x\n", ntohl(reply->xid), - ntohl(msg->xid)); - return 0; - } - if (reply->htype != msg->htype) { - if (verbose) printf("Wrong Htype %d != %d\n", reply->htype, msg->htype); - return 0; - } - if (reply->hlen != msg->hlen) { - if (verbose) printf("Wrong Hlen %d != %d\n", reply->hlen, msg->hlen); - return 0; - } - if (memcmp(msg->chaddr, reply->chaddr, msg->hlen)) { - if (verbose) printf("Wrong chaddr %x != %x\n", *(reply->chaddr),*(msg->chaddr)); - return 0; - } - return 1; -} - -#define STATE_SELECTING 1 -#define STATE_REQUESTING 2 - -#define TIMEOUT_INITIAL 4000 -#define TIMEOUT_MAX 32000 - -int dhcp_init_ifc(const char *ifname) -{ - dhcp_msg discover_msg; - dhcp_msg request_msg; - dhcp_msg reply; - dhcp_msg *msg; - dhcp_info info; - int s, r, size; - int valid_reply; - uint32_t xid; - unsigned char hwaddr[6]; - struct pollfd pfd; - unsigned int state; - unsigned int timeout; - int if_index; - - xid = (uint32_t) get_msecs(); - - if (if_get_hwaddr(ifname, hwaddr)) { - return fatal("cannot obtain interface address"); - } - if ((if_index = if_nametoindex(ifname)) == 0) { - return fatal("cannot obtain interface index"); - } - - s = open_raw_socket(ifname, hwaddr, if_index); - - timeout = TIMEOUT_INITIAL; - state = STATE_SELECTING; - info.type = 0; - goto transmit; - - for (;;) { - pfd.fd = s; - pfd.events = POLLIN; - pfd.revents = 0; - r = poll(&pfd, 1, timeout); - - if (r == 0) { -#if VERBOSE - printerr("TIMEOUT\n"); -#endif - if (timeout >= TIMEOUT_MAX) { - printerr("timed out\n"); - if ( info.type == DHCPOFFER ) { - printerr("no acknowledgement from DHCP server\nconfiguring %s with offered parameters\n", ifname); - return dhcp_configure(ifname, &info); - } - errno = ETIME; - close(s); - return -1; - } - timeout = timeout * 2; - - transmit: - size = 0; - msg = NULL; - switch(state) { - case STATE_SELECTING: - msg = &discover_msg; - size = init_dhcp_discover_msg(msg, hwaddr, xid); - break; - case STATE_REQUESTING: - msg = &request_msg; - size = init_dhcp_request_msg(msg, hwaddr, xid, info.ipaddr, info.serveraddr); - break; - default: - r = 0; - } - if (size != 0) { - r = send_message(s, if_index, msg, size); - if (r < 0) { - printerr("error sending dhcp msg: %s\n", strerror(errno)); - } - } - continue; - } - - if (r < 0) { - if ((errno == EAGAIN) || (errno == EINTR)) { - continue; - } - return fatal("poll failed"); - } - - errno = 0; - r = receive_packet(s, &reply); - if (r < 0) { - if (errno != 0) { - printf("receive_packet failed (%d): %s", r, strerror(errno)); - if (errno == ENETDOWN || errno == ENXIO) { - return -1; - } - } - continue; - } - -#if VERBOSE > 1 - dump_dhcp_msg(&reply, r); -#endif - decode_dhcp_msg(&reply, r, &info); - - if (state == STATE_SELECTING) { - valid_reply = is_valid_reply(&discover_msg, &reply, r); - } else { - valid_reply = is_valid_reply(&request_msg, &reply, r); - } - if (!valid_reply) { - printerr("invalid reply\n"); - continue; - } - - if (verbose) dump_dhcp_info(&info); - - switch(state) { - case STATE_SELECTING: - if (info.type == DHCPOFFER) { - state = STATE_REQUESTING; - timeout = TIMEOUT_INITIAL; - xid++; - goto transmit; - } - break; - case STATE_REQUESTING: - if (info.type == DHCPACK) { - printerr("configuring %s\n", ifname); - close(s); - return dhcp_configure(ifname, &info); - } else if (info.type == DHCPNAK) { - printerr("configuration request denied\n"); - close(s); - return -1; - } else { - printerr("ignoring %s message in state %d\n", - dhcp_type_to_name(info.type), state); - } - break; - } - } - close(s); - return 0; -} - -int do_dhcp(char *iname) -{ - if (if_set_addr_v4(iname, 0, 32)) { - printerr("failed to set ip addr for %s to 0.0.0.0: %s\n", iname, strerror(errno)); - return -1; - } - - if (if_link_up(iname)) { - printerr("failed to bring up interface %s: %s\n", iname, strerror(errno)); - return -1; - } - - return dhcp_init_ifc(iname); -} diff --git a/fibocom-dial/src/libmnl/dhcp/dhcpmsg.c b/fibocom-dial/src/libmnl/dhcp/dhcpmsg.c deleted file mode 100644 index 1e0a233..0000000 --- a/fibocom-dial/src/libmnl/dhcp/dhcpmsg.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * 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. - */ - -#include -#include -#include -#include - -#include "dhcpmsg.h" - -static void *init_dhcp_msg(dhcp_msg *msg, int type, void *hwaddr, uint32_t xid) -{ - uint8_t *x; - - memset(msg, 0, sizeof(dhcp_msg)); - - msg->op = OP_BOOTREQUEST; - msg->htype = HTYPE_ETHER; - msg->hlen = 6; - msg->hops = 0; - - msg->flags = htons(FLAGS_BROADCAST); - - msg->xid = xid; - - memcpy(msg->chaddr, hwaddr, 6); - - x = msg->options; - - *x++ = OPT_COOKIE1; - *x++ = OPT_COOKIE2; - *x++ = OPT_COOKIE3; - *x++ = OPT_COOKIE4; - - *x++ = OPT_MESSAGE_TYPE; - *x++ = 1; - *x++ = type; - - return x; -} - -int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid) -{ - uint8_t *x; - - x = init_dhcp_msg(msg, DHCPDISCOVER, hwaddr, xid); - - *x++ = OPT_PARAMETER_LIST; - *x++ = 4; - *x++ = OPT_SUBNET_MASK; - *x++ = OPT_GATEWAY; - *x++ = OPT_DNS; - *x++ = OPT_BROADCAST_ADDR; - - *x++ = OPT_END; - - return DHCP_MSG_FIXED_SIZE + (x - msg->options); -} - -int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid, - uint32_t ipaddr, uint32_t serveraddr) -{ - uint8_t *x; - - x = init_dhcp_msg(msg, DHCPREQUEST, hwaddr, xid); - - *x++ = OPT_PARAMETER_LIST; - *x++ = 4; - *x++ = OPT_SUBNET_MASK; - *x++ = OPT_GATEWAY; - *x++ = OPT_DNS; - *x++ = OPT_BROADCAST_ADDR; - - *x++ = OPT_REQUESTED_IP; - *x++ = 4; - memcpy(x, &ipaddr, 4); - x += 4; - - *x++ = OPT_SERVER_ID; - *x++ = 4; - memcpy(x, &serveraddr, 4); - x += 4; - - *x++ = OPT_END; - - return DHCP_MSG_FIXED_SIZE + (x - msg->options); -} diff --git a/fibocom-dial/src/libmnl/dhcp/dhcpmsg.h b/fibocom-dial/src/libmnl/dhcp/dhcpmsg.h deleted file mode 100644 index fb99490..0000000 --- a/fibocom-dial/src/libmnl/dhcp/dhcpmsg.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * 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. - */ - -#ifndef _WIFI_DHCP_H_ -#define _WIFI_DHCP_H_ - -#include - -#define PORT_BOOTP_SERVER 67 -#define PORT_BOOTP_CLIENT 68 - -/* RFC 2131 p 9 */ -typedef struct dhcp_msg dhcp_msg; - -#define OP_BOOTREQUEST 1 -#define OP_BOOTREPLY 2 - -#define FLAGS_BROADCAST 0x8000 - -#define HTYPE_ETHER 1 - -struct dhcp_msg -{ - uint8_t op; /* BOOTREQUEST / BOOTREPLY */ - uint8_t htype; /* hw addr type */ - uint8_t hlen; /* hw addr len */ - uint8_t hops; /* client set to 0 */ - - uint32_t xid; /* transaction id */ - - uint16_t secs; /* seconds since start of acq */ - uint16_t flags; - - uint32_t ciaddr; /* client IP addr */ - uint32_t yiaddr; /* your (client) IP addr */ - uint32_t siaddr; /* ip addr of next server */ - /* (DHCPOFFER and DHCPACK) */ - uint32_t giaddr; /* relay agent IP addr */ - - uint8_t chaddr[16]; /* client hw addr */ - char sname[64]; /* asciiz server hostname */ - char file[128]; /* asciiz boot file name */ - - uint8_t options[1024]; /* optional parameters */ -}; - -#define DHCP_MSG_FIXED_SIZE 236 - -/* first four bytes of options are a cookie to indicate that -** the payload are DHCP options as opposed to some other BOOTP -** extension. -*/ -#define OPT_COOKIE1 0x63 -#define OPT_COOKIE2 0x82 -#define OPT_COOKIE3 0x53 -#define OPT_COOKIE4 0x63 - -/* BOOTP/DHCP options - see RFC 2132 */ -#define OPT_PAD 0 - -#define OPT_SUBNET_MASK 1 /* 4 */ -#define OPT_TIME_OFFSET 2 /* 4 */ -#define OPT_GATEWAY 3 /* 4*n * n */ -#define OPT_DNS 6 /* 4*n * n */ -#define OPT_DOMAIN_NAME 15 /* n */ -#define OPT_BROADCAST_ADDR 28 /* 4 */ - -#define OPT_REQUESTED_IP 50 /* 4 */ -#define OPT_LEASE_TIME 51 /* 4 */ -#define OPT_MESSAGE_TYPE 53 /* 1 */ -#define OPT_SERVER_ID 54 /* 4 */ -#define OPT_PARAMETER_LIST 55 /* n * n */ -#define OPT_MESSAGE 56 /* n */ -#define OPT_CLASS_ID 60 /* n */ -#define OPT_CLIENT_ID 61 /* n */ -#define OPT_END 255 - -/* DHCP message types */ -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 -#define DHCPINFORM 8 - -int init_dhcp_discover_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid); - -int init_dhcp_request_msg(dhcp_msg *msg, void *hwaddr, uint32_t xid, - uint32_t ipaddr, uint32_t serveraddr); - -#endif diff --git a/fibocom-dial/src/libmnl/dhcp/packet.c b/fibocom-dial/src/libmnl/dhcp/packet.c deleted file mode 100644 index 9515dd1..0000000 --- a/fibocom-dial/src/libmnl/dhcp/packet.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dhcpmsg.h" - -int fatal(); - -int open_raw_socket(const char *ifname __attribute__((unused)), uint8_t *hwaddr, int if_index) -{ - int s; - struct sockaddr_ll bindaddr; - - if((s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { - return fatal("socket(PF_PACKET)"); - } - - memset(&bindaddr, 0, sizeof(bindaddr)); - bindaddr.sll_family = AF_PACKET; - bindaddr.sll_protocol = htons(ETH_P_IP); - bindaddr.sll_halen = ETH_ALEN; - memcpy(bindaddr.sll_addr, hwaddr, ETH_ALEN); - bindaddr.sll_ifindex = if_index; - - if (bind(s, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) { - return fatal("Cannot bind raw socket to interface"); - } - - return s; -} - -static uint32_t checksum(void *buffer, unsigned int count, uint32_t startsum) -{ - uint16_t *up = (uint16_t *)buffer; - uint32_t sum = startsum; - uint32_t upper16; - - while (count > 1) { - sum += *up++; - count -= 2; - } - if (count > 0) { - sum += (uint16_t) *(uint8_t *)up; - } - while ((upper16 = (sum >> 16)) != 0) { - sum = (sum & 0xffff) + upper16; - } - return sum; -} - -static uint32_t finish_sum(uint32_t sum) -{ - return ~sum & 0xffff; -} - -int send_packet(int s, int if_index, struct dhcp_msg *msg, int size, - uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport) -{ - struct iphdr ip; - struct udphdr udp; - struct iovec iov[3]; - uint32_t udpsum; - uint16_t temp; - struct msghdr msghdr; - struct sockaddr_ll destaddr; - - ip.version = IPVERSION; - ip.ihl = sizeof(ip) >> 2; - ip.tos = 0; - ip.tot_len = htons(sizeof(ip) + sizeof(udp) + size); - ip.id = 0; - ip.frag_off = 0; - ip.ttl = IPDEFTTL; - ip.protocol = IPPROTO_UDP; - ip.check = 0; - ip.saddr = saddr; - ip.daddr = daddr; - ip.check = finish_sum(checksum(&ip, sizeof(ip), 0)); - - udp.source = htons(sport); - udp.dest = htons(dport); - udp.len = htons(sizeof(udp) + size); - udp.check = 0; - - /* Calculate checksum for pseudo header */ - udpsum = checksum(&ip.saddr, sizeof(ip.saddr), 0); - udpsum = checksum(&ip.daddr, sizeof(ip.daddr), udpsum); - temp = htons(IPPROTO_UDP); - udpsum = checksum(&temp, sizeof(temp), udpsum); - temp = udp.len; - udpsum = checksum(&temp, sizeof(temp), udpsum); - - /* Add in the checksum for the udp header */ - udpsum = checksum(&udp, sizeof(udp), udpsum); - - /* Add in the checksum for the data */ - udpsum = checksum(msg, size, udpsum); - udp.check = finish_sum(udpsum); - - iov[0].iov_base = (char *)&ip; - iov[0].iov_len = sizeof(ip); - iov[1].iov_base = (char *)&udp; - iov[1].iov_len = sizeof(udp); - iov[2].iov_base = (char *)msg; - iov[2].iov_len = size; - memset(&destaddr, 0, sizeof(destaddr)); - destaddr.sll_family = AF_PACKET; - destaddr.sll_protocol = htons(ETH_P_IP); - destaddr.sll_ifindex = if_index; - destaddr.sll_halen = ETH_ALEN; - memcpy(destaddr.sll_addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN); - - msghdr.msg_name = &destaddr; - msghdr.msg_namelen = sizeof(destaddr); - msghdr.msg_iov = iov; - msghdr.msg_iovlen = sizeof(iov) / sizeof(struct iovec); - msghdr.msg_flags = 0; - msghdr.msg_control = 0; - msghdr.msg_controllen = 0; - return sendmsg(s, &msghdr, 0); -} - -int receive_packet(int s, struct dhcp_msg *msg) -{ - int nread; - int is_valid; - struct dhcp_packet { - struct iphdr ip; - struct udphdr udp; - struct dhcp_msg dhcp; - } packet; - int dhcp_size; - uint32_t sum; - uint16_t temp; - uint32_t saddr, daddr; - - nread = read(s, &packet, sizeof(packet)); - if (nread < 0) { - return -1; - } - /* - * The raw packet interface gives us all packets received by the - * network interface. We need to filter out all packets that are - * not meant for us. - */ - is_valid = 0; - if (nread < (int)(sizeof(struct iphdr) + sizeof(struct udphdr))) { -#if VERBOSE - ALOGD("Packet is too small (%d) to be a UDP datagram", nread); -#endif - } else if (packet.ip.version != IPVERSION || packet.ip.ihl != (sizeof(packet.ip) >> 2)) { -#if VERBOSE - ALOGD("Not a valid IP packet"); -#endif - } else if (nread < ntohs(packet.ip.tot_len)) { -#if VERBOSE - ALOGD("Packet was truncated (read %d, needed %d)", nread, ntohs(packet.ip.tot_len)); -#endif - } else if (packet.ip.protocol != IPPROTO_UDP) { -#if VERBOSE - ALOGD("IP protocol (%d) is not UDP", packet.ip.protocol); -#endif - } else if (packet.udp.dest != htons(PORT_BOOTP_CLIENT)) { -#if VERBOSE - ALOGD("UDP dest port (%d) is not DHCP client", ntohs(packet.udp.dest)); -#endif - } else { - is_valid = 1; - } - - if (!is_valid) { - return -1; - } - - /* Seems like it's probably a valid DHCP packet */ - /* validate IP header checksum */ - sum = finish_sum(checksum(&packet.ip, sizeof(packet.ip), 0)); - if (sum != 0) { - printf("IP header checksum failure (0x%x)\n", packet.ip.check); - return -1; - } - /* - * Validate the UDP checksum. - * Since we don't need the IP header anymore, we "borrow" it - * to construct the pseudo header used in the checksum calculation. - */ - dhcp_size = ntohs(packet.udp.len) - sizeof(packet.udp); - /* - * check validity of dhcp_size. - * 1) cannot be negative or zero. - * 2) src buffer contains enough bytes to copy - * 3) cannot exceed destination buffer - */ - if ((dhcp_size <= 0) || - ((int)(nread - sizeof(struct iphdr) - sizeof(struct udphdr)) < dhcp_size) || - ((int)sizeof(struct dhcp_msg) < dhcp_size)) { -#if VERBOSE - printf("Malformed Packet\n"); -#endif - return -1; - } - saddr = packet.ip.saddr; - daddr = packet.ip.daddr; - nread = ntohs(packet.ip.tot_len); - memset(&packet.ip, 0, sizeof(packet.ip)); - packet.ip.saddr = saddr; - packet.ip.daddr = daddr; - packet.ip.protocol = IPPROTO_UDP; - packet.ip.tot_len = packet.udp.len; - temp = packet.udp.check; - packet.udp.check = 0; - sum = finish_sum(checksum(&packet, nread, 0)); - packet.udp.check = temp; - if (!sum) - sum = finish_sum(sum); - if (temp != sum) { - printf("UDP header checksum failure (0x%x should be 0x%x)\n", sum, temp); - return -1; - } - memcpy(msg, &packet.dhcp, dhcp_size); - return dhcp_size; -} diff --git a/fibocom-dial/src/libmnl/dhcp/packet.h b/fibocom-dial/src/libmnl/dhcp/packet.h deleted file mode 100644 index aade392..0000000 --- a/fibocom-dial/src/libmnl/dhcp/packet.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2008, The Android Open Source Project - * - * 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. - */ - -#ifndef _WIFI_PACKET_H_ -#define _WIFI_PACKET_H_ - -int open_raw_socket(const char *ifname, uint8_t *hwaddr, int if_index); -int send_packet(int s, int if_index, struct dhcp_msg *msg, int size, - uint32_t saddr, uint32_t daddr, uint32_t sport, uint32_t dport); -int receive_packet(int s, struct dhcp_msg *msg); - -#endif diff --git a/fibocom-dial/src/libmnl/ifutils.c b/fibocom-dial/src/libmnl/ifutils.c deleted file mode 100644 index 51ac9d8..0000000 --- a/fibocom-dial/src/libmnl/ifutils.c +++ /dev/null @@ -1,748 +0,0 @@ -/* This example is placed in the public domain. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -//#include - -#include "libmnl.h" -#include "ifutils.h" - -#define ERRMSG(v...) printf("%s-%d: error=%s %s\n", __func__, __LINE__, strerror(errno), ##v) -extern void dbg_time(const char *fmt, ...); -int mask_to_prefix_v4(uint32_t mask) -{ - int ret = 0; - while (mask) - { - mask = mask & (mask - 1); - ret++; - } - return ret; -} - -const char *ipaddr_to_string_v4(in_addr_t ipaddr) -{ - static char buf[INET6_ADDRSTRLEN] = {'\0'}; - buf[0] = '\0'; - uint32_t addr = ipaddr; - return inet_ntop(AF_INET, &addr, buf, sizeof(buf)); -} - -const char *ipaddr_to_string_v6(uint8_t *ipaddr) -{ - static char buf[INET6_ADDRSTRLEN] = {'\0'}; - buf[0] = '\0'; - return inet_ntop(AF_INET6, ipaddr, buf, sizeof(buf)); -} - -static void ifc_init_ifr(const char *name, struct ifreq *ifr) -{ - memset(ifr, 0, sizeof(struct ifreq)); - strncpy(ifr->ifr_name, name, IFNAMSIZ); - ifr->ifr_name[IFNAMSIZ - 1] = 0; -} - -int if_get_hwaddr(const char *name, void *ptr) -{ - int r; - struct ifreq ifr; - ifc_init_ifr(name, &ifr); - - int ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (ifc_ctl_sock < 0) - { - return -1; - } - r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr); - if (r < 0) - return -1; - - memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); - return 0; -} - -static int if_act_on_link(const char *ifname, int state) -{ - struct mnl_socket *nl; - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - struct ifinfomsg *ifm; - int ret; - unsigned int seq, portid, change = 0, flags = 0; - static int oldstate = -1; - - if (state == oldstate) - return 0; - oldstate = state; - - if (state) - { - change |= IFF_UP; - flags |= IFF_UP; - } - else - { - change |= IFF_UP; - flags &= ~IFF_UP; - } - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = RTM_NEWLINK; - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm)); - ifm->ifi_family = AF_UNSPEC; - ifm->ifi_change = change; - ifm->ifi_flags = flags; - - mnl_attr_put_str(nlh, IFLA_IFNAME, ifname); - - nl = mnl_socket_open(NETLINK_ROUTE); - if (nl == NULL) - { - ERRMSG("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) - { - ERRMSG(" mnl_socket_bind"); - return -1; - } - portid = mnl_socket_get_portid(nl); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) - { - ERRMSG(" mnl_socket_sendto"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - if (ret == -1) - { - ERRMSG(" mnl_socket_recvfrom"); - return -1; - } - - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret == -1) - { - ERRMSG(" mnl_cb_run"); - return -1; - } - - mnl_socket_close(nl); - - return 0; -} - -int if_link_up(const char *ifname) -{ - dbg_time("if_link_up %s",ifname); - return if_act_on_link(ifname, 1); -} - -int if_link_down(const char *ifname) -{ - - dbg_time("if_link_down %s",ifname); - return if_act_on_link(ifname, 0); -} - -int if_set_mtu(const char *ifname, uint32_t mtu) -{ - char buf[MNL_SOCKET_BUFFER_SIZE]; - unsigned int seq, portid; - struct mnl_socket *nl; - struct nlmsghdr *nlh; - struct ifinfomsg *ifm; - int ret; - int iface; - static uint32_t oldmtu = 1500; - - if (mtu == oldmtu) - return 0; - oldmtu = mtu; - - iface = if_nametoindex(ifname); - if (iface == 0) - { - ERRMSG(" if_nametoindex"); - return -1; - } - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = RTM_NEWLINK; - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg)); - ifm->ifi_family = AF_UNSPEC; - ifm->ifi_index = iface; - ifm->ifi_change = 0xFFFFFFFF; - ifm->ifi_type = 0; - ifm->ifi_flags = IFF_NOARP | IFF_MULTICAST; - - mnl_attr_put_u32(nlh, IFLA_MTU, mtu); - - nl = mnl_socket_open(NETLINK_ROUTE); - if (nl == NULL) - { - ERRMSG(" mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) - { - ERRMSG(" mnl_socket_bind"); - return -1; - } - portid = mnl_socket_get_portid(nl); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) - { - ERRMSG(" mnl_socket_sendto"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - if (ret == -1) - { - ERRMSG(" mnl_socket_recvfrom"); - return -1; - } - - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret == -1) - { - ERRMSG(" mnl_cb_run"); - return -1; - } - - mnl_socket_close(nl); - - return 0; -} - -/** - * @brief Set the ip addr object - * - * @param operate - * 0 -> add address on interface - * 1 -> delete address on interface - * @param ifname - * @param ipaddr - * @param prefix - * @return int - */ -static int if_act_on_addr(bool operate, int proto, const char *ifname, addr_t *ipaddr, uint32_t prefix) -{ - struct mnl_socket *nl; - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - struct ifaddrmsg *ifm; - uint32_t seq, portid; - int ret, family = proto; - - int iface; - - iface = if_nametoindex(ifname); - if (iface == 0) - { - ERRMSG(" if_nametoindex"); - return -1; - } - - nlh = mnl_nlmsg_put_header(buf); - if (operate) - nlh->nlmsg_type = RTM_NEWADDR; - else - nlh->nlmsg_type = RTM_DELADDR; - - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - - ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg)); - - ifm->ifa_family = family; - ifm->ifa_prefixlen = prefix; - ifm->ifa_flags = IFA_F_PERMANENT; - - ifm->ifa_scope = RT_SCOPE_UNIVERSE; - ifm->ifa_index = iface; - - /* - * The exact meaning of IFA_LOCAL and IFA_ADDRESS depend - * on the address family being used and the device type. - * For broadcast devices (like the interfaces we use), - * for IPv4 we specify both and they are used interchangeably. - * For IPv6, only IFA_ADDRESS needs to be set. - */ - if (family == AF_INET) - { - mnl_attr_put_u32(nlh, IFA_LOCAL, ipaddr->ip); - mnl_attr_put_u32(nlh, IFA_ADDRESS, ipaddr->ip); - } - else - { - mnl_attr_put(nlh, IFA_ADDRESS, sizeof(struct in6_addr), ipaddr); - } - - nl = mnl_socket_open(NETLINK_ROUTE); - if (nl == NULL) - { - ERRMSG(" mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) - { - ERRMSG(" mnl_socket_bind"); - return -1; - } - portid = mnl_socket_get_portid(nl); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) - { - ERRMSG(" mnl_socket_sendto"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - if (ret < 0) - { - ERRMSG(" mnl_socket_recvfrom"); - return -1; - } - - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret < 0) - { - ERRMSG(" mnl_cb_run"); - return -1; - } - - mnl_socket_close(nl); - - return 0; -} - -int if_set_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix) -{ - addr_t addr; - addr.ip = ipaddr; - return if_act_on_addr(1, AF_INET, ifname, &addr, prefix); -} - -int if_del_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix) -{ - addr_t addr; - addr.ip = ipaddr; - return if_act_on_addr(0, AF_INET, ifname, &addr, prefix); -} - -int if_set_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix) -{ - addr_t addr; - memcpy(&addr.ip6, ipaddr, 16); - return if_act_on_addr(1, AF_INET6, ifname, &addr, prefix); -} - -int if_del_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix) -{ - addr_t addr; - memcpy(&addr.ip6, ipaddr, 16); - return if_act_on_addr(0, AF_INET6, ifname, &addr, prefix); -} - -static int data_attr_cb(const struct nlattr *attr, void *data) -{ - const struct nlattr **tb = data; - int type = mnl_attr_get_type(attr); - - /* skip unsupported attribute in user-space */ - if (mnl_attr_type_valid(attr, IFA_MAX) < 0) - return MNL_CB_OK; - - switch (type) - { - case IFA_ADDRESS: - if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0) - { - ERRMSG(" mnl_attr_validate"); - return MNL_CB_ERROR; - } - break; - } - tb[type] = attr; - return MNL_CB_OK; -} - -static int data_cb(const struct nlmsghdr *nlh, void *data) -{ - struct nlattr *tb[IFA_MAX + 1] = {}; - struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh); - struct addrinfo_t *addrinfo = (struct addrinfo_t *)data; - void *addr = NULL; - - mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb); - if (tb[IFA_ADDRESS]) - { - char out[INET6_ADDRSTRLEN]; - - addr = mnl_attr_get_payload(tb[IFLA_ADDRESS]); - addr = mnl_attr_get_payload(tb[IFA_ADDRESS]); - if (!inet_ntop(ifa->ifa_family, addr, out, sizeof(out))) - ERRMSG("inet_ntop"); - // printf("%d %d-> %d %s\n", addrinfo->iface, ifa->ifa_index, ifa->ifa_scope, out); - - addrinfo->addrs[addrinfo->num].prefix = ifa->ifa_prefixlen; - if (ifa->ifa_index == addrinfo->iface) - { - if (ifa->ifa_family == AF_INET6) - memcpy(addrinfo->addrs[addrinfo->num].address.ip6.s6_addr, addr, 16); - if (ifa->ifa_family == AF_INET) - memcpy(&(addrinfo->addrs[addrinfo->num].address.ip), addr, 4); - addrinfo->num++; - } - } - - // ifa->ifa_scope - // 0: global - // 200: site - // 253: link - // 254: host - // 255: nowhere - - return MNL_CB_OK; -} - -/** - * @brief - * - * @param ifname - * @param proto - * AF_INET -> for IPv4 - * AF_INET6 -> for IPv6 - * @return int - */ -static int if_get_addr(const char *ifname, int proto, struct addrinfo_t *addrinfo) -{ - char buf[MNL_SOCKET_BUFFER_SIZE]; - unsigned int seq, portid; - struct mnl_socket *nl; - struct nlmsghdr *nlh; - struct rtgenmsg *rt; - int ret; - - addrinfo->iface = if_nametoindex(ifname); - if (addrinfo->iface == 0) - { - ERRMSG(" if_nametoindex"); - return -1; - } - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = RTM_GETADDR; - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - nlh->nlmsg_seq = seq = time(NULL); - rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg)); - if (proto == AF_INET) - rt->rtgen_family = AF_INET; - else if (proto == AF_INET6) - rt->rtgen_family = AF_INET6; - - nl = mnl_socket_open(NETLINK_ROUTE); - if (nl == NULL) - { - ERRMSG(" mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) - { - ERRMSG(" mnl_socket_bind"); - return -1; - } - portid = mnl_socket_get_portid(nl); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) - { - ERRMSG(" mnl_socket_sendto"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) - { - ret = mnl_cb_run(buf, ret, seq, portid, data_cb, addrinfo); - if (ret <= MNL_CB_STOP) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) - { - ERRMSG(" error"); - return -1; - } - mnl_socket_close(nl); - - return 0; -} - -int if_flush_v4_addr(const char *ifname) -{ - struct addrinfo_t addrinfo; - int i = 0; - - memset(&addrinfo, 0, sizeof(struct addrinfo_t)); - if_get_addr(ifname, AF_INET, &addrinfo); - for (; i < addrinfo.num; i++) - { - // printf("remove address: %s\n", ipaddr_to_string_v4(addrinfo.addrs[i].address.ip)); - if_del_addr_v4(ifname, addrinfo.addrs[i].address.ip, addrinfo.addrs[i].prefix); - } - return 0; -} - -int if_flush_v6_addr(const char *ifname) -{ - struct addrinfo_t addrinfo; - int i = 0; - - memset(&addrinfo, 0, sizeof(struct addrinfo_t)); - if_get_addr(ifname, AF_INET6, &addrinfo); - for (; i < addrinfo.num; i++) - { - // printf("remove address: %s\n", ipaddr_to_string_v6(addrinfo.addrs[i].address.ip6.s6_addr)); - if_del_addr_v6(ifname, addrinfo.addrs[i].address.ip6.s6_addr, addrinfo.addrs[i].prefix); - } - return 0; -} - -/** - * @brief Set the route addr object - * Usage: - * iface destination cidr [gateway] - * Example: - * eth0 10.0.1.12 32 10.0.1.11 - * eth0 ffff::10.0.1.12 128 fdff::1 - * @param operate - * add or del - * @param ifname - * @param dstaddr - * @param prefix - * @param gwaddr - * @return int - */ -int if_act_on_route(bool operate, int proto, const char *ifname, addr_t *dstaddr, uint32_t prefix, addr_t *gwaddr) -{ - struct mnl_socket *nl; - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - struct rtmsg *rtm; - uint32_t seq, portid; - int iface, ret, family = proto; - - iface = if_nametoindex(ifname); - if (iface == 0) - { - ERRMSG(" if_nametoindex"); - return -1; - } - - nlh = mnl_nlmsg_put_header(buf); - if (operate) - nlh->nlmsg_type = RTM_NEWROUTE; - else - nlh->nlmsg_type = RTM_DELROUTE; - - nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; - nlh->nlmsg_seq = seq = time(NULL); - - rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg)); - rtm->rtm_family = family; - rtm->rtm_dst_len = prefix; - rtm->rtm_src_len = 0; - rtm->rtm_tos = 0; - rtm->rtm_protocol = RTPROT_STATIC; - rtm->rtm_table = RT_TABLE_MAIN; - rtm->rtm_type = RTN_UNICAST; - /* is there any gateway? */ - rtm->rtm_scope = gwaddr ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK; - rtm->rtm_flags = 0; - - if (family == AF_INET) - mnl_attr_put_u32(nlh, RTA_DST, dstaddr->ip); - else - mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), dstaddr); - - mnl_attr_put_u32(nlh, RTA_OIF, iface); - if (gwaddr) - { - if (family == AF_INET) - mnl_attr_put_u32(nlh, RTA_GATEWAY, gwaddr->ip); - else - { - mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr), gwaddr); - } - } - - nl = mnl_socket_open(NETLINK_ROUTE); - if (nl == NULL) - { - ERRMSG(" mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) - { - ERRMSG(" mnl_socket_bind"); - return -1; - } - portid = mnl_socket_get_portid(nl); - - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) - { - ERRMSG(" mnl_socket_sendto"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - if (ret < 0) - { - ERRMSG(" mnl_socket_recvfrom"); - return -1; - } - - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret < 0) - { - ERRMSG(" mnl_cb_run"); - return -1; - } - - mnl_socket_close(nl); - - return 0; -} - -int if_set_default_route_v4(const char *ifname) -{ - return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL); -} - -int if_del_default_route_v4(const char *ifname) -{ - return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL); -} - -int if_set_default_route_v6(const char *ifname) -{ - return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL); -} - -int if_del_default_route_v6(const char *ifname) -{ - return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL); -} - -/** - * @brief Set the default gwaddr object - * set default gw - * @param operate - * @param ifname - * @param gwaddr - * gateway ip - * @return int - */ -int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr) -{ - addr_t addr; - memset(&addr, 0, sizeof(addr_t)); - addr.ip = gwaddr; - return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr); -} - -int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr) -{ - addr_t addr; - memset(&addr, 0, sizeof(addr_t)); - addr.ip = gwaddr; - return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr); -} - -int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr) -{ - addr_t addr; - memset(&addr, 0, sizeof(addr_t)); - memcpy(&addr.ip6, gwaddr, 16); - return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr); -} - -int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr) -{ - addr_t addr; - memset(&addr, 0, sizeof(addr_t)); - memcpy(&addr.ip6, gwaddr, 16); - return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr); -} - -int if_set_dns(const char *dns1, const char *dns2) -{ - int ret = 0; - char buf[128] = {'\0'}; - int fd = open("/etc/resolv.conf", O_CREAT | O_WRONLY | O_TRUNC); - if (fd < 0) - { - ERRMSG(" fail to open /etc/resolv.conf"); - return -1; - } - - if (dns1) - snprintf(buf, sizeof(buf), "nameserver %s\n", dns1); - if (dns2) - snprintf(buf, sizeof(buf), "nameserver %s\n", dns2); - ret = write(fd, buf, strlen(buf)); - if (ret < 0) - { - ERRMSG(" write dns"); - } - close(fd); - return ret > 0 ? 0 : -1; -} - -int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix, - in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2) -{ - if_link_up(ifname); - sleep(2); - if_set_addr_v4(ifname, ipaddr, prefix); - if_set_default_route_v4(ifname); - if_set_dns(ipaddr_to_string_v4(dns1), ipaddr_to_string_v4(dns2)); - return 0; -} - -int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix, - uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2) -{ - if_link_up(ifname); - sleep(2); - if_set_addr_v6(ifname, ipaddr, prefix); - if_set_default_route_v6(ifname); - if_set_dns(ipaddr_to_string_v6(dns1), ipaddr_to_string_v6(dns2)); - return 0; -} diff --git a/fibocom-dial/src/libmnl/ifutils.h b/fibocom-dial/src/libmnl/ifutils.h deleted file mode 100644 index 4c2b565..0000000 --- a/fibocom-dial/src/libmnl/ifutils.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __IFUTILS_H__ -#define __IFUTILS_H__ - -typedef union { - in_addr_t ip; - struct in6_addr ip6; -} addr_t; - -#define MAX_IP_NUM 32 -struct addrinfo_t -{ - int iface; - int num; - struct - { - int prefix; - addr_t address; - } addrs[MAX_IP_NUM]; -}; - -const char *ipaddr_to_string_v4(in_addr_t ipaddr); -const char *ipaddr_to_string_v6(uint8_t *ipaddr); -int mask_to_prefix_v4(in_addr_t mask); - -int if_get_hwaddr(const char *name, void *ptr); - -int if_link_down(const char *ifname); -int if_link_up(const char *ifname); -int if_set_mtu(const char *ifname, uint32_t mtu); - -int if_set_addr_v4(const char *name, in_addr_t address, uint32_t prefixlen); -int if_del_addr_v4(const char *name, in_addr_t address, uint32_t prefixlen); -int if_set_addr_v6(const char *name, uint8_t *address, uint32_t prefixlen); -int if_del_addr_v6(const char *name, uint8_t *address, uint32_t prefixlen); -int if_flush_v4_addr(const char *ifname); -int if_flush_v6_addr(const char *ifname); - -int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr); -int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr); -int if_set_default_route_v4(const char *ifname); -int if_del_default_route_v4(const char *ifname); - -int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr); -int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr); -int if_set_default_route_v6(const char *ifname); -int if_del_default_route_v6(const char *ifname); - -int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix, - in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2); -int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix, - uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2); - -#endif //__IFUTILS_H__ \ No newline at end of file diff --git a/fibocom-dial/src/libmnl/libmnl.h b/fibocom-dial/src/libmnl/libmnl.h deleted file mode 100644 index 4bd0b92..0000000 --- a/fibocom-dial/src/libmnl/libmnl.h +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef _LIBMNL_H_ -#define _LIBMNL_H_ - -#include -#include -#include -#include -#include /* for sa_family_t */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Netlink socket API - */ - -#define MNL_SOCKET_AUTOPID 0 -#define MNL_SOCKET_BUFFER_SIZE (sysconf(_SC_PAGESIZE) < 8192L ? sysconf(_SC_PAGESIZE) : 8192L) -#define MNL_SOCKET_DUMP_SIZE 32768 - -struct mnl_socket; - -extern struct mnl_socket *mnl_socket_open(int bus); -extern struct mnl_socket *mnl_socket_open2(int bus, int flags); -extern struct mnl_socket *mnl_socket_fdopen(int fd); -extern int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid); -extern int mnl_socket_close(struct mnl_socket *nl); -extern int mnl_socket_get_fd(const struct mnl_socket *nl); -extern unsigned int mnl_socket_get_portid(const struct mnl_socket *nl); -extern ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *req, size_t siz); -extern ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t siz); -extern int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len); -extern int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len); - -/* - * Netlink message API - */ - -#define MNL_ALIGNTO 4 -#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1)) -#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr)) - -extern size_t mnl_nlmsg_size(size_t len); -extern size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh); - -/* Netlink message header builder */ -extern struct nlmsghdr *mnl_nlmsg_put_header(void *buf); -extern void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size); - -/* Netlink message iterators */ -extern bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len); -extern struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len); - -/* Netlink sequence tracking */ -extern bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq); - -/* Netlink portID checking */ -extern bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid); - -/* Netlink message getters */ -extern void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh); -extern void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset); -extern void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh); - -/* Netlink message printer */ -extern void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size); - -/* Message batch helpers */ -struct mnl_nlmsg_batch; -extern struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, size_t bufsiz); -extern bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b); -extern void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b); -extern size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b); -extern void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b); -extern void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b); -extern void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b); -extern bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b); - -/* - * Netlink attributes API - */ -#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr)) - -/* TLV attribute getters */ -extern uint16_t mnl_attr_get_type(const struct nlattr *attr); -extern uint16_t mnl_attr_get_len(const struct nlattr *attr); -extern uint16_t mnl_attr_get_payload_len(const struct nlattr *attr); -extern void *mnl_attr_get_payload(const struct nlattr *attr); -extern uint8_t mnl_attr_get_u8(const struct nlattr *attr); -extern uint16_t mnl_attr_get_u16(const struct nlattr *attr); -extern uint32_t mnl_attr_get_u32(const struct nlattr *attr); -extern uint64_t mnl_attr_get_u64(const struct nlattr *attr); -extern const char *mnl_attr_get_str(const struct nlattr *attr); - -/* TLV attribute putters */ -extern void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data); -extern void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type, uint8_t data); -extern void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data); -extern void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data); -extern void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type, uint64_t data); -extern void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type, const char *data); -extern void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data); - -/* TLV attribute putters with buffer boundary checkings */ -extern bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, size_t len, const void *data); -extern bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint8_t data); -extern bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint16_t data); -extern bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint32_t data); -extern bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, uint64_t data); -extern bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data); -extern bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type, const char *data); - -/* TLV attribute nesting */ -extern struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type); -extern struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, uint16_t type); -extern void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start); -extern void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start); - -/* TLV validation */ -extern int mnl_attr_type_valid(const struct nlattr *attr, uint16_t maxtype); - -enum mnl_attr_data_type { - MNL_TYPE_UNSPEC, - MNL_TYPE_U8, - MNL_TYPE_U16, - MNL_TYPE_U32, - MNL_TYPE_U64, - MNL_TYPE_STRING, - MNL_TYPE_FLAG, - MNL_TYPE_MSECS, - MNL_TYPE_NESTED, - MNL_TYPE_NESTED_COMPAT, - MNL_TYPE_NUL_STRING, - MNL_TYPE_BINARY, - MNL_TYPE_MAX, -}; - -extern int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type); -extern int mnl_attr_validate2(const struct nlattr *attr, enum mnl_attr_data_type type, size_t len); - -/* TLV iterators */ -extern bool mnl_attr_ok(const struct nlattr *attr, int len); -extern struct nlattr *mnl_attr_next(const struct nlattr *attr); - -#define mnl_attr_for_each(attr, nlh, offset) \ - for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \ - mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \ - (attr) = mnl_attr_next(attr)) - -#define mnl_attr_for_each_nested(attr, nest) \ - for ((attr) = mnl_attr_get_payload(nest); \ - mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \ - (attr) = mnl_attr_next(attr)) - -#define mnl_attr_for_each_payload(payload, payload_size) \ - for ((attr) = (payload); \ - mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \ - (attr) = mnl_attr_next(attr)) - -/* TLV callback-based attribute parsers */ -typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data); - -extern int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, mnl_attr_cb_t cb, void *data); -extern int mnl_attr_parse_nested(const struct nlattr *attr, mnl_attr_cb_t cb, void *data); -extern int mnl_attr_parse_payload(const void *payload, size_t payload_len, mnl_attr_cb_t cb, void *data); - -/* - * callback API - */ -#define MNL_CB_ERROR -1 -#define MNL_CB_STOP 0 -#define MNL_CB_OK 1 - -typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data); - -extern int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, - unsigned int portid, mnl_cb_t cb_data, void *data); - -extern int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq, - unsigned int portid, mnl_cb_t cb_data, void *data, - const mnl_cb_t *cb_ctl_array, - unsigned int cb_ctl_array_len); - -/* - * other declarations - */ - -#ifndef SOL_NETLINK -#define SOL_NETLINK 270 -#endif - -#ifndef MNL_ARRAY_SIZE -#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/fibocom-dial/src/libmnl/nlmsg.c b/fibocom-dial/src/libmnl/nlmsg.c deleted file mode 100644 index d960cf3..0000000 --- a/fibocom-dial/src/libmnl/nlmsg.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * (C) 2008-2010 by Pablo Neira Ayuso - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - */ -#include -#include -#include -#include -#include -#include - -#include "libmnl.h" - -/** - * \defgroup nlmsg Netlink message helpers - * - * Netlink message: - * \verbatim - |<----------------- 4 bytes ------------------->| - |<----- 2 bytes ------>|<------- 2 bytes ------>| - |-----------------------------------------------| - | Message length (including header) | - |-----------------------------------------------| - | Message type | Message flags | - |-----------------------------------------------| - | Message sequence number | - |-----------------------------------------------| - | Netlink PortID | - |-----------------------------------------------| - | | - . Payload . - |_______________________________________________| -\endverbatim - * - * There is usually an extra header after the the Netlink header (at the - * beginning of the payload). This extra header is specific of the Netlink - * subsystem. After this extra header, it comes the sequence of attributes - * that are expressed in Type-Length-Value (TLV) format. - * - * @{ - */ - -/** - * mnl_nlmsg_size - calculate the size of Netlink message (without alignment) - * \param len length of the Netlink payload - * - * This function returns the size of a netlink message (header plus payload) - * without alignment. - */ -size_t mnl_nlmsg_size(size_t len) -{ - return len + MNL_NLMSG_HDRLEN; -} - -/** - * mnl_nlmsg_get_payload_len - get the length of the Netlink payload - * \param nlh pointer to the header of the Netlink message - * - * This function returns the Length of the netlink payload, ie. the length - * of the full message minus the size of the Netlink header. - */ -size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh) -{ - return nlh->nlmsg_len - MNL_NLMSG_HDRLEN; -} - -/** - * mnl_nlmsg_put_header - reserve and prepare room for Netlink header - * \param buf memory already allocated to store the Netlink header - * - * This function sets to zero the room that is required to put the Netlink - * header in the memory buffer passed as parameter. This function also - * initializes the nlmsg_len field to the size of the Netlink header. This - * function returns a pointer to the Netlink header structure. - */ -struct nlmsghdr *mnl_nlmsg_put_header(void *buf) -{ - int len = MNL_ALIGN(sizeof(struct nlmsghdr)); - struct nlmsghdr *nlh = buf; - - memset(buf, 0, len); - nlh->nlmsg_len = len; - return nlh; -} - -/** - * mnl_nlmsg_put_extra_header - reserve and prepare room for an extra header - * \param nlh pointer to Netlink header - * \param size size of the extra header that we want to put - * - * This function sets to zero the room that is required to put the extra - * header after the initial Netlink header. This function also increases - * the nlmsg_len field. You have to invoke mnl_nlmsg_put_header() before - * you call this function. This function returns a pointer to the extra - * header. - */ -void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, - size_t size) -{ - char *ptr = (char *)nlh + nlh->nlmsg_len; - size_t len = MNL_ALIGN(size); - nlh->nlmsg_len += len; - memset(ptr, 0, len); - return ptr; -} - -/** - * mnl_nlmsg_get_payload - get a pointer to the payload of the netlink message - * \param nlh pointer to a netlink header - * - * This function returns a pointer to the payload of the netlink message. - */ -void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh) -{ - return (void *)nlh + MNL_NLMSG_HDRLEN; -} - -/** - * mnl_nlmsg_get_payload_offset - get a pointer to the payload of the message - * \param nlh pointer to a netlink header - * \param offset offset to the payload of the attributes TLV set - * - * This function returns a pointer to the payload of the netlink message plus - * a given offset. - */ -void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, - size_t offset) -{ - return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); -} - -/** - * mnl_nlmsg_ok - check a there is room for netlink message - * \param nlh netlink message that we want to check - * \param len remaining bytes in a buffer that contains the netlink message - * - * This function is used to check that a buffer that contains a netlink - * message has enough room for the netlink message that it stores, ie. this - * function can be used to verify that a netlink message is not malformed nor - * truncated. - * - * This function does not set errno in case of error since it is intended - * for iterations. Thus, it returns true on success and false on error. - * - * The len parameter may become negative in malformed messages during message - * iteration, that is why we use a signed integer. - */ -bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len) -{ - return len >= (int)sizeof(struct nlmsghdr) && - nlh->nlmsg_len >= sizeof(struct nlmsghdr) && - (int)nlh->nlmsg_len <= len; -} - -/** - * mnl_nlmsg_next - get the next netlink message in a multipart message - * \param nlh current netlink message that we are handling - * \param len length of the remaining bytes in the buffer (passed by reference). - * - * This function returns a pointer to the next netlink message that is part - * of a multi-part netlink message. Netlink can batch several messages into - * one buffer so that the receiver has to iterate over the whole set of - * Netlink messages. - * - * You have to use mnl_nlmsg_ok() to check if the next Netlink message is - * valid. - */ -struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, - int *len) -{ - *len -= MNL_ALIGN(nlh->nlmsg_len); - return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len)); -} - -/** - * mnl_nlmsg_get_payload_tail - get the ending of the netlink message - * \param nlh pointer to netlink message - * - * This function returns a pointer to the netlink message tail. This is useful - * to build a message since we continue adding attributes at the end of the - * message. - */ -void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh) -{ - return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len); -} - -/** - * mnl_nlmsg_seq_ok - perform sequence tracking - * \param nlh current netlink message that we are handling - * \param seq last sequence number used to send a message - * - * This functions returns true if the sequence tracking is fulfilled, otherwise - * false is returned. We skip the tracking for netlink messages whose sequence - * number is zero since it is usually reserved for event-based kernel - * notifications. On the other hand, if seq is set but the message sequence - * number is not set (i.e. this is an event message coming from kernel-space), - * then we also skip the tracking. This approach is good if we use the same - * socket to send commands to kernel-space (that we want to track) and to - * listen to events (that we do not track). - */ -bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, - unsigned int seq) -{ - return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true; -} - -/** - * mnl_nlmsg_portid_ok - perform portID origin check - * \param nlh current netlink message that we are handling - * \param portid netlink portid that we want to check - * - * This functions returns true if the origin is fulfilled, otherwise - * false is returned. We skip the tracking for netlink message whose portID - * is zero since it is reserved for event-based kernel notifications. On the - * other hand, if portid is set but the message PortID is not (i.e. this - * is an event message coming from kernel-space), then we also skip the - * tracking. This approach is good if we use the same socket to send commands - * to kernel-space (that we want to track) and to listen to events (that we - * do not track). - */ -bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, - unsigned int portid) -{ - return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true; -} - -static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh) -{ - fprintf(fd, "----------------\t------------------\n"); - fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len); - fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n", - nlh->nlmsg_type, - nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-', - nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-', - nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-', - nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-'); - fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq); - fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid); - fprintf(fd, "----------------\t------------------\n"); -} - -static void mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh, - size_t extra_header_size) -{ - int rem = 0; - unsigned int i; - - for (i=sizeof(struct nlmsghdr); inlmsg_len; i+=4) { - char *b = (char *) nlh; - struct nlattr *attr = (struct nlattr *) (b+i); - - /* netlink control message. */ - if (nlh->nlmsg_type < NLMSG_MIN_TYPE) { - fprintf(fd, "| %.2x %.2x %.2x %.2x |\t", - 0xff & b[i], 0xff & b[i+1], - 0xff & b[i+2], 0xff & b[i+3]); - fprintf(fd, "| |\n"); - /* special handling for the extra header. */ - } else if (extra_header_size > 0) { - extra_header_size -= 4; - fprintf(fd, "| %.2x %.2x %.2x %.2x |\t", - 0xff & b[i], 0xff & b[i+1], - 0xff & b[i+2], 0xff & b[i+3]); - fprintf(fd, "| extra header |\n"); - /* this seems like an attribute header. */ - } else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) { - fprintf(fd, "|%c[%d;%dm" - "%.5u" - "%c[%dm" - "|" - "%c[%d;%dm" - "%c%c" - "%c[%dm" - "|" - "%c[%d;%dm" - "%.5u" - "%c[%dm|\t", - 27, 1, 31, - attr->nla_len, - 27, 0, - 27, 1, 32, - attr->nla_type & NLA_F_NESTED ? 'N' : '-', - attr->nla_type & - NLA_F_NET_BYTEORDER ? 'B' : '-', - 27, 0, - 27, 1, 34, - attr->nla_type & NLA_TYPE_MASK, - 27, 0); - fprintf(fd, "|len |flags| type|\n"); - - if (!(attr->nla_type & NLA_F_NESTED)) { - rem = NLA_ALIGN(attr->nla_len) - - sizeof(struct nlattr); - } - /* this is the attribute payload. */ - } else if (rem > 0) { - rem -= 4; - fprintf(fd, "| %.2x %.2x %.2x %.2x |\t", - 0xff & b[i], 0xff & b[i+1], - 0xff & b[i+2], 0xff & b[i+3]); - fprintf(fd, "| data |"); - fprintf(fd, "\t %c %c %c %c\n", - isprint(b[i]) ? b[i] : ' ', - isprint(b[i+1]) ? b[i+1] : ' ', - isprint(b[i+2]) ? b[i+2] : ' ', - isprint(b[i+3]) ? b[i+3] : ' '); - } - } - fprintf(fd, "----------------\t------------------\n"); -} - -/** - * mnl_nlmsg_fprintf - print netlink message to file - * \param fd pointer to file type - * \param data pointer to the buffer that contains messages to be printed - * \param datalen length of data stored in the buffer - * \param extra_header_size size of the extra header (if any) - * - * This function prints the netlink header to a file handle. - * It may be useful for debugging purposes. One example of the output - * is the following: - * - *\verbatim ----------------- ------------------ -| 0000000040 | | message length | -| 00016 | R-A- | | type | flags | -| 1289148991 | | sequence number| -| 0000000000 | | port ID | ----------------- ------------------ -| 00 00 00 00 | | extra header | -| 00 00 00 00 | | extra header | -| 01 00 00 00 | | extra header | -| 01 00 00 00 | | extra header | -|00008|--|00003| |len |flags| type| -| 65 74 68 30 | | data | e t h 0 ----------------- ------------------ -\endverbatim - * - * This example above shows the netlink message that is send to kernel-space - * to set up the link interface eth0. The netlink and attribute header data - * are displayed in base 10 whereas the extra header and the attribute payload - * are expressed in base 16. The possible flags in the netlink header are: - * - * - R, that indicates that NLM_F_REQUEST is set. - * - M, that indicates that NLM_F_MULTI is set. - * - A, that indicates that NLM_F_ACK is set. - * - E, that indicates that NLM_F_ECHO is set. - * - * The lack of one flag is displayed with '-'. On the other hand, the possible - * attribute flags available are: - * - * - N, that indicates that NLA_F_NESTED is set. - * - B, that indicates that NLA_F_NET_BYTEORDER is set. - */ -void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, - size_t extra_header_size) -{ - const struct nlmsghdr *nlh = data; - int len = datalen; - - while (mnl_nlmsg_ok(nlh, len)) { - mnl_nlmsg_fprintf_header(fd, nlh); - mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size); - nlh = mnl_nlmsg_next(nlh, &len); - } -} - -/** - * @} - */ - -/** - * \defgroup batch Netlink message batch helpers - * - * This library provides helpers to batch several messages into one single - * datagram. These helpers do not perform strict memory boundary checkings. - * - * The following figure represents a Netlink message batch: - * - * |<-------------- MNL_SOCKET_BUFFER_SIZE ------------->| - * |<-------------------- batch ------------------>| | - * |-----------|-----------|-----------|-----------|-----------| - * |<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->|<- nlmsg ->| - * |-----------|-----------|-----------|-----------|-----------| - * ^ ^ - * | | - * message N message N+1 - * - * To start the batch, you have to call mnl_nlmsg_batch_start() and you can - * use mnl_nlmsg_batch_stop() to release it. - * - * You have to invoke mnl_nlmsg_batch_next() to get room for a new message - * in the batch. If this function returns NULL, it means that the last - * message that was added (message N+1 in the figure above) does not fit the - * batch. Thus, you have to send the batch (which includes until message N) - * and, then, you have to call mnl_nlmsg_batch_reset() to re-initialize - * the batch (this moves message N+1 to the head of the buffer). For that - * reason, the buffer that you have to use to store the batch must be double - * of MNL_SOCKET_BUFFER_SIZE to ensure that the last message (message N+1) - * that did not fit into the batch is written inside valid memory boundaries. - * - * @{ - */ - -struct mnl_nlmsg_batch { - /* the buffer that is used to store the batch. */ - void *buf; - size_t limit; - size_t buflen; - /* the current netlink message in the batch. */ - void *cur; - bool overflow; -}; - -/** - * mnl_nlmsg_batch_start - initialize a batch - * \param buf pointer to the buffer that will store this batch - * \param limit maximum size of the batch (should be MNL_SOCKET_BUFFER_SIZE). - * - * The buffer that you pass must be double of MNL_SOCKET_BUFFER_SIZE. The - * limit must be half of the buffer size, otherwise expect funny memory - * corruptions 8-). - * - * You can allocate the buffer that you use to store the batch in the stack or - * the heap, no restrictions in this regard. This function returns NULL on - * error. - */ -struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, - size_t limit) -{ - struct mnl_nlmsg_batch *b; - - b = malloc(sizeof(struct mnl_nlmsg_batch)); - if (b == NULL) - return NULL; - - b->buf = buf; - b->limit = limit; - b->buflen = 0; - b->cur = buf; - b->overflow = false; - - return b; -} - -/** - * mnl_nlmsg_batch_stop - release a batch - * \param b pointer to batch - * - * This function releases the batch allocated by mnl_nlmsg_batch_start(). - */ -void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b) -{ - free(b); -} - -/** - * mnl_nlmsg_batch_next - get room for the next message in the batch - * \param b pointer to batch - * - * This function returns false if the last message did not fit into the - * batch. Otherwise, it prepares the batch to provide room for the new - * Netlink message in the batch and returns true. - * - * You have to put at least one message in the batch before calling this - * function, otherwise your application is likely to crash. - */ -bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b) -{ - struct nlmsghdr *nlh = b->cur; - - if (b->buflen + nlh->nlmsg_len > b->limit) { - b->overflow = true; - return false; - } - b->cur = b->buf + b->buflen + nlh->nlmsg_len; - b->buflen += nlh->nlmsg_len; - return true; -} - -/** - * mnl_nlmsg_batch_reset - reset the batch - * \param b pointer to batch - * - * This function allows to reset a batch, so you can reuse it to create a - * new one. This function moves the last message which does not fit the - * batch to the head of the buffer, if any. - */ -void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b) -{ - if (b->overflow) { - struct nlmsghdr *nlh = b->cur; - memcpy(b->buf, b->cur, nlh->nlmsg_len); - b->buflen = nlh->nlmsg_len; - b->cur = b->buf + b->buflen; - b->overflow = false; - } else { - b->buflen = 0; - b->cur = b->buf; - } -} - -/** - * mnl_nlmsg_batch_size - get current size of the batch - * \param b pointer to batch - * - * This function returns the current size of the batch. - */ -size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b) -{ - return b->buflen; -} - -/** - * mnl_nlmsg_batch_head - get head of this batch - * \param b pointer to batch - * - * This function returns a pointer to the head of the batch, which is the - * beginning of the buffer that is used. - */ -void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b) -{ - return b->buf; -} - -/** - * mnl_nlmsg_batch_current - returns current position in the batch - * \param b pointer to batch - * - * This function returns a pointer to the current position in the buffer - * that is used to store the batch. - */ -void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b) -{ - return b->cur; -} - -/** - * mnl_nlmsg_batch_is_empty - check if there is any message in the batch - * \param b pointer to batch - * - * This function returns true if the batch is empty. - */ -bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b) -{ - return b->buflen == 0; -} - -/** - * @} - */ diff --git a/fibocom-dial/src/libmnl/socket.c b/fibocom-dial/src/libmnl/socket.c deleted file mode 100644 index dd5ab66..0000000 --- a/fibocom-dial/src/libmnl/socket.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * (C) 2008-2010 by Pablo Neira Ayuso - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmnl.h" - -/** - * \mainpage - * - * libmnl is a minimalistic user-space library oriented to Netlink developers. - * There are a lot of common tasks in parsing, validating, constructing of - * both the Netlink header and TLVs that are repetitive and easy to get wrong. - * This library aims to provide simple helpers that allows you to avoid - * re-inventing the wheel in common Netlink tasks. - * - * \verbatim -"Simplify, simplify" -- Henry David Thoureau. Walden (1854) -\endverbatim - * - * The acronym libmnl stands for LIBrary Minimalistic NetLink. - * - * libmnl homepage is: - * http://www.netfilter.org/projects/libmnl/ - * - * \section features Main Features - * - Small: the shared library requires around 30KB for an x86-based computer. - * - Simple: this library avoids complex abstractions that tend to hide Netlink - * details. It avoids elaborated object-oriented infrastructure and complex - * callback-based workflow. - * - Easy to use: the library simplifies the work for Netlink-wise developers. - * It provides functions to make socket handling, message building, - * validating, parsing and sequence tracking, easier. - * - Easy to re-use: you can use this library to build your own abstraction - * layer upon this library, if you want to provide another library that - * hides Netlink details to your users. - * - Decoupling: the interdependency of the main bricks that compose this - * library is reduced, i.e. the library provides many helpers, but the - * programmer is not forced to use them. - * - * \section licensing Licensing terms - * This library is released under the LGPLv2.1 or any later (at your option). - * - * \section Dependencies - * You have to install the Linux kernel headers that you want to use to develop - * your application. Moreover, this library requires that you have some basics - * on Netlink. - * - * \section scm Git Tree - * The current development version of libmnl can be accessed at: - * http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=summary - * - * \section using Using libmnl - * You can access several example files under examples/ in the libmnl source - * code tree. - */ - -struct mnl_socket { - int fd; - struct sockaddr_nl addr; -}; - -/** - * \defgroup socket Netlink socket helpers - * @{ - */ - -/** - * mnl_socket_get_fd - obtain file descriptor from netlink socket - * \param nl netlink socket obtained via mnl_socket_open() - * - * This function returns the file descriptor of a given netlink socket. - */ -int mnl_socket_get_fd(const struct mnl_socket *nl) -{ - return nl->fd; -} - -/** - * mnl_socket_get_portid - obtain Netlink PortID from netlink socket - * \param nl netlink socket obtained via mnl_socket_open() - * - * This function returns the Netlink PortID of a given netlink socket. - * It's a common mistake to assume that this PortID equals the process ID - * which is not always true. This is the case if you open more than one - * socket that is binded to the same Netlink subsystem from the same process. - */ -unsigned int mnl_socket_get_portid(const struct mnl_socket *nl) -{ - return nl->addr.nl_pid; -} - -static struct mnl_socket *__mnl_socket_open(int bus, int flags) -{ - struct mnl_socket *nl; - - nl = calloc(1, sizeof(struct mnl_socket)); - if (nl == NULL) - return NULL; - - nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus); - if (nl->fd == -1) { - free(nl); - return NULL; - } - - return nl; -} - -/** - * mnl_socket_open - open a netlink socket - * \param bus the netlink socket bus ID (see NETLINK_* constants) - * - * On error, it returns NULL and errno is appropriately set. Otherwise, it - * returns a valid pointer to the mnl_socket structure. - */ -struct mnl_socket *mnl_socket_open(int bus) -{ - return __mnl_socket_open(bus, 0); -} - -/** - * mnl_socket_open2 - open a netlink socket with appropriate flags - * \param bus the netlink socket bus ID (see NETLINK_* constants) - * \param flags the netlink socket flags (see SOCK_* constants in socket(2)) - * - * This is similar to mnl_socket_open(), but allows to set flags like - * SOCK_CLOEXEC at socket creation time (useful for multi-threaded programs - * performing exec calls). - * - * On error, it returns NULL and errno is appropriately set. Otherwise, it - * returns a valid pointer to the mnl_socket structure. - */ -struct mnl_socket *mnl_socket_open2(int bus, int flags) -{ - return __mnl_socket_open(bus, flags); -} - -/** - * mnl_socket_fdopen - associates a mnl_socket object with pre-existing socket. - * \param fd pre-existing socket descriptor. - * - * On error, it returns NULL and errno is appropriately set. Otherwise, it - * returns a valid pointer to the mnl_socket structure. It also sets the portID - * if the socket fd is already bound and it is AF_NETLINK. - * - * Note that mnl_socket_get_portid() returns 0 if this function is used with - * non-netlink socket. - */ -struct mnl_socket *mnl_socket_fdopen(int fd) -{ - int ret; - struct mnl_socket *nl; - struct sockaddr_nl addr; - socklen_t addr_len = sizeof(struct sockaddr_nl); - - ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len); - if (ret == -1) - return NULL; - - nl = calloc(1, sizeof(struct mnl_socket)); - if (nl == NULL) - return NULL; - - nl->fd = fd; - if (addr.nl_family == AF_NETLINK) - nl->addr = addr; - - return nl; -} - -/** - * mnl_socket_bind - bind netlink socket - * \param nl netlink socket obtained via mnl_socket_open() - * \param groups the group of message you're interested in - * \param pid the port ID you want to use (use zero for automatic selection) - * - * On error, this function returns -1 and errno is appropriately set. On - * success, 0 is returned. You can use MNL_SOCKET_AUTOPID which is 0 for - * automatic port ID selection. - */ -int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, - pid_t pid) -{ - int ret; - socklen_t addr_len; - - nl->addr.nl_family = AF_NETLINK; - nl->addr.nl_groups = groups; - nl->addr.nl_pid = pid; - - ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr)); - if (ret < 0) - return ret; - - addr_len = sizeof(nl->addr); - ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len); - if (ret < 0) - return ret; - - if (addr_len != sizeof(nl->addr)) { - errno = EINVAL; - return -1; - } - if (nl->addr.nl_family != AF_NETLINK) { - errno = EINVAL; - return -1; - } - return 0; -} - -/** - * mnl_socket_sendto - send a netlink message of a certain size - * \param nl netlink socket obtained via mnl_socket_open() - * \param buf buffer containing the netlink message to be sent - * \param len number of bytes in the buffer that you want to send - * - * On error, it returns -1 and errno is appropriately set. Otherwise, it - * returns the number of bytes sent. - */ -ssize_t mnl_socket_sendto(const struct mnl_socket *nl, - const void *buf, size_t len) -{ - static const struct sockaddr_nl snl = { - .nl_family = AF_NETLINK - }; - return sendto(nl->fd, buf, len, 0, - (struct sockaddr *) &snl, sizeof(snl)); -} - -/** - * mnl_socket_recvfrom - receive a netlink message - * \param nl netlink socket obtained via mnl_socket_open() - * \param buf buffer that you want to use to store the netlink message - * \param bufsiz size of the buffer passed to store the netlink message - * - * On error, it returns -1 and errno is appropriately set. If errno is set - * to ENOSPC, it means that the buffer that you have passed to store the - * netlink message is too small, so you have received a truncated message. - * To avoid this, you have to allocate a buffer of MNL_SOCKET_BUFFER_SIZE - * (which is 8KB, see linux/netlink.h for more information). Using this - * buffer size ensures that your buffer is big enough to store the netlink - * message without truncating it. - */ -ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, - void *buf, size_t bufsiz) -{ - ssize_t ret; - struct sockaddr_nl addr; - struct iovec iov = { - .iov_base = buf, - .iov_len = bufsiz, - }; - struct msghdr msg = { - .msg_name = &addr, - .msg_namelen = sizeof(struct sockaddr_nl), - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, - }; - ret = recvmsg(nl->fd, &msg, 0); - if (ret == -1) - return ret; - - if (msg.msg_flags & MSG_TRUNC) { - errno = ENOSPC; - return -1; - } - if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { - errno = EINVAL; - return -1; - } - return ret; -} - -/** - * mnl_socket_close - close a given netlink socket - * \param nl netlink socket obtained via mnl_socket_open() - * - * On error, this function returns -1 and errno is appropriately set. - * On success, it returns 0. - */ -int mnl_socket_close(struct mnl_socket *nl) -{ - int ret = close(nl->fd); - free(nl); - return ret; -} - -/** - * mnl_socket_setsockopt - set Netlink socket option - * \param nl netlink socket obtained via mnl_socket_open() - * \param type type of Netlink socket options - * \param buf the buffer that contains the data about this option - * \param len the size of the buffer passed - * - * This function allows you to set some Netlink socket option. As of writing - * this (see linux/netlink.h), the existing options are: - * - * - \#define NETLINK_ADD_MEMBERSHIP 1 - * - \#define NETLINK_DROP_MEMBERSHIP 2 - * - \#define NETLINK_PKTINFO 3 - * - \#define NETLINK_BROADCAST_ERROR 4 - * - \#define NETLINK_NO_ENOBUFS 5 - * - * In the early days, Netlink only supported 32 groups expressed in a - * 32-bits mask. However, since 2.6.14, Netlink may have up to 2^32 multicast - * groups but you have to use setsockopt() with NETLINK_ADD_MEMBERSHIP to - * join a given multicast group. This function internally calls setsockopt() - * to join a given netlink multicast group. You can still use mnl_bind() - * and the 32-bit mask to join a set of Netlink multicast groups. - * - * On error, this function returns -1 and errno is appropriately set. - */ -int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, - void *buf, socklen_t len) -{ - return setsockopt(nl->fd, SOL_NETLINK, type, buf, len); -} - -/** - * mnl_socket_getsockopt - get a Netlink socket option - * \param nl netlink socket obtained via mnl_socket_open() - * \param type type of Netlink socket options - * \param buf pointer to the buffer to store the value of this option - * \param len size of the information written in the buffer - * - * On error, this function returns -1 and errno is appropriately set. - */ -int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, - void *buf, socklen_t *len) -{ - return getsockopt(nl->fd, SOL_NETLINK, type, buf, len); -} - -/** - * @} - */ diff --git a/fibocom-dial/src/main.c b/fibocom-dial/src/main.c deleted file mode 100644 index dd64293..0000000 --- a/fibocom-dial/src/main.c +++ /dev/null @@ -1,1770 +0,0 @@ -#include -#include -#include -#include - -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 -#include -#include -//2021-02-25 willa.liu@fibocom.com changed end for support eipd SN-20210129001 - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 -#include -#include -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - -#include "QMIThread.h" -#include "util.h" -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -#include "query_pcie_mode.h" -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - -#define MAJOR 2 -#define MINOR 0 -#define REVISION 10 -/* - * Generally, we do not modify version info, so several modifications will share - * the same version code. SUBVERSION is used for customized modification to - * distinguise this version from previous one. SUBVERSION adds up before you - * send the code to customers and it should be set to 0 if VERSION_STRING info - * is changed. - */ -#define SUBVERSION 0 -#define STRINGIFY_HELPER(v) #v -#define STRINGIFY(v) STRINGIFY_HELPER(v) -#define VERSION_STRING() \ - STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(REVISION) -#define MAX_PATH 256 - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 -struct sockaddr_un { - sa_family_t sun_family; - char sun_path[100]; -}; -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - -int query_pcie_mode = 0; -int debug_qmi = 0; -int main_loop = 0; -int qmidevice_control_fd[2]; -static int signal_control_fd[2]; -pthread_t gQmiThreadID; -USHORT g_MobileCountryCode = 0; -USHORT g_MobileNetworkCode = 0; - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 -sem_t sem; -int socket_server_fd = 0; -int cli_accept_fd = 0; -char fibo_dial_filepath[100] = {0}; -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - -extern const struct qmi_device_ops qmiwwan_qmidev_ops; -extern const struct qmi_device_ops gobi_qmidev_ops; - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -//extern int *speed_arr; -//extern int *name_arr; -//extern int get_private_gateway_debug; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - -static int s_link = -1; - -static int is_pcie_dial() -{ - return (access("/dev/mhi_QMI0", F_OK) == 0); -} - -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 -int split_gateway(char *str ,char* split, int index, char *outgateway) -{ - char chBuffer[1024]; - char *pchStrTmpIn = NULL; - char *pchTmp = NULL; - int i = 1; - strncpy(chBuffer, str, sizeof(chBuffer)-1); - pchTmp = chBuffer; - //printf("pchTmp is [%s]\n", pchTmp); - while(NULL != (pchTmp = strtok_r( pchTmp, split, &pchStrTmpIn))) - { - //printf("line %d::::::::::::[%s]\n", i, pchTmp); - if(i == index) - { - memcpy(outgateway, pchTmp, strlen(pchTmp)); - break; - } - //if(strstr(pchTmp, "+CGCONTRDP") != -1) - i++; - pchTmp = NULL; - } - return strlen(outgateway); -} - -int get_private_gateway(char *outgateway) -{ - int i; - int fd; - int ret; - char buffer[1024] = {0}; - int rate; - char *sendbuffer; - char prigateways[1024*2] = {0}; - char prigateway[256] = {0}; - int totallen = 0; - fd_set readfds; - struct timeval timeout; - struct termios tiosfd, tio; - - int timeoutVal = 5; - - char *dev = "/dev/ttyUSB1"; //The port under Linux is operated by opening the device file - rate = 115200; - sendbuffer = "AT+CGCONTRDP=1"; - - fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); - if(fd < 0) - goto ERR; - fcntl(fd, F_SETFL, O_RDWR); - - xget1(fd, &tio, &tiosfd); - - for(i = 0; i < sizeof(speed_arr)/sizeof(int); i++) - { - if(rate == name_arr[i])//Judge if the pass is equal to the pass - { - break; - } - } - - if(i >= sizeof(speed_arr)/sizeof(int)) - { - printf("bound rate set failed\n"); - goto ERR; - } - - cfsetspeed(&tio, speed_arr[i]); - if(xset1(fd, &tio, dev)) - goto ERR; - - tcflush(fd, TCIOFLUSH); - - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - - sprintf(buffer, "%s\r", sendbuffer); - ret = write (fd, buffer, strlen(buffer)); - if(ret < 0) - { - printf("write failed\n"); - goto ERR; - } - printf("dev: %s\nrate:%d\nsendbuffer:%s\n", dev, rate, sendbuffer); - sleep(1); - if(get_private_gateway_debug)printf("write %d\n", ret); - while(1) - { - timeout.tv_sec = timeoutVal; - timeout.tv_usec = 0; - - ret = select(fd+1, &readfds, (fd_set *)0, (fd_set *)0, &timeout); - if(ret > 0) - { - ret = read(fd, buffer+totallen, sizeof(buffer)-totallen-1); - if(ret < 0) - { - printf("read failed\n"); - goto ERR; - } - - if(ret == 0) - { - goto ERR; - } - - totallen += ret; - buffer[totallen] = '\0'; - if(get_private_gateway_debug)printf("read %d(%s)\n", ret, &buffer[totallen-ret]); - //printf("buffer is %s\n", buffer); - - if(totallen == sizeof(buffer)-1) - break; - - if(strstr(buffer, "\nOK")) - { - split_gateway(buffer, "\r", 3, prigateways); - //printf("test1 %s\n", prigateways); - split_gateway(prigateways, ",", 5, prigateway); - //printf("test2 %s\n", prigateway); - break; - } - else - { - goto ERR; - } - - } - else - { - printf("select timeout\n"); - goto ERR; - } - - } - - tcsetattr(fd, TCSAFLUSH, &tiosfd); - if(strstr(buffer, "\nERROR") || strstr(buffer, "\n+CME ERROR:") || strstr(buffer, "\n+CMS ERROR:")) - goto ERR; - - close(fd); - - memcpy(outgateway, prigateway+1, strlen(prigateway)-2); - printf("private gateway is %s\n", outgateway); - return 0; -ERR: - if(fd > 0) - close(fd); - return -1; -} -//2021-02-25 willa.liu@fibocom.com changed end for support eipd SN-20210129001 - -// UINT ifc_get_addr(const char *ifname); -static void usbnet_link_change(int link, PROFILE_T *profile) -{ - // static int s_link = 0; - dbg_time("%s :link:%d ", __func__, link); - - if (s_link == link) - return; - - s_link = link; - - if (link) { - if (profile->ipv4_flag) - requestGetIPAddress(profile, IpFamilyV4); - if (profile->ipv6_flag) - requestGetIPAddress(profile, IpFamilyV6); - if (qmidev_is_pciemhi(profile->qmichannel)) - udhcpc_start_pcie(profile); - else - udhcpc_start(profile); - } else { - if (qmidev_is_pciemhi(profile->qmichannel)) - udhcpc_stop_pcie(profile); - else - udhcpc_stop(profile); - } -} - -static int check_address(PROFILE_T *now_profile,int ipfamily) -{ - PROFILE_T new_profile_v; - PROFILE_T *new_profile = &new_profile_v; - static int time_out_count = 0; - int ret = 0; - #define QMITHREADSENDQMITIMEOUT 110 - - memcpy(new_profile, now_profile, sizeof(PROFILE_T)); - if(ipfamily == IpFamilyV4) - { - ret = requestGetIPAddress(new_profile, 0x04); - if (ret == 0) - { - time_out_count = 0; - if (new_profile->ipv4.Address != now_profile->ipv4.Address || debug_qmi) - { - unsigned char *l = (unsigned char *)&now_profile->ipv4.Address; - unsigned char *r = (unsigned char *)&new_profile->ipv4.Address; - dbg_time("localIP: %d.%d.%d.%d VS remoteIP: %d.%d.%d.%d", l[3], - l[2], l[1], l[0], r[3], r[2], r[1], r[0]); - } - return (new_profile->ipv4.Address == now_profile->ipv4.Address); - } - else if (ret == QMITHREADSENDQMITIMEOUT) - { - time_out_count++; - dbg_time("%s %d time_out_count %d\n", __func__, __LINE__, time_out_count); - if (time_out_count >= 3) - { - return 0; - } - else - { - return 1; - } - } - } - if(ipfamily == IpFamilyV6) - { - return 1; - } - - return 0; -} - -static void main_send_event_to_qmidevice(int triger_event) -{ - write(qmidevice_control_fd[0], &triger_event, sizeof(triger_event)); -} - -static void send_signo_to_main(int signo) -{ - write(signal_control_fd[0], &signo, sizeof(signo)); - dbg_time("write signo: %d to signal_control_fd",signo); -} - -void qmidevice_send_event_to_main(int triger_event) -{ - write(qmidevice_control_fd[1], &triger_event, sizeof(triger_event)); - dbg_time("write triger_event: %d to qmidevice_control_fd",triger_event); -} - -static int ls_dir(const char *dir, - int (*match)(const char *dir, const char *file, void *argv[]), - void *argv[]) -{ - DIR *pDir; - struct dirent *ent = NULL; - int match_times = 0; - - pDir = opendir(dir); - if (pDir == NULL) { - dbg_time("Cannot open directory: %s, errno: %d (%s)", dir, errno, - strerror(errno)); - return 0; - } - - while ((ent = readdir(pDir)) != NULL) { - match_times += match(dir, ent->d_name, argv); - } - closedir(pDir); - - return match_times; -} - -static int is_same_linkfile(const char *dir, const char *file, void *argv[]) -{ - const char *qmichannel = (const char *)argv[1]; - char linkname[MAX_PATH]; - char filename[MAX_PATH]; - int linksize; - - snprintf(linkname, MAX_PATH, "%s/%s", dir, file); - linksize = readlink(linkname, filename, MAX_PATH); - if (linksize <= 0) - return 0; - - filename[linksize] = 0; - if (strcmp(filename, qmichannel)) - return 0; - - dbg_time("%s -> %s", linkname, filename); - return 1; -} - -static int is_brother_process(const char *dir, const char *file, void *argv[]) -{ - // const char *myself = (const char *)argv[0]; - char linkname[MAX_PATH]; - char filename[MAX_PATH]; - int linksize; - int i = 0, kill_timeout = 15; - pid_t pid; - - // dbg_time("%s", file); - while (file[i]) { - if (!isdigit(file[i])) - break; - i++; - } - - if (file[i]) { - // dbg_time("%s not digit", file); - return 0; - } - - snprintf(linkname, MAX_PATH, "%s/%s/exe", dir, file); - linksize = readlink(linkname, filename, MAX_PATH); - if (linksize <= 0) - return 0; - - filename[linksize] = 0; - - pid = atoi(file); - if (pid >= getpid()) - return 0; - - snprintf(linkname, MAX_PATH, "%s/%s/fd", dir, file); - if (!ls_dir(linkname, is_same_linkfile, argv)) - return 0; - - dbg_time("%s/%s/exe -> %s", dir, file, filename); - while (kill_timeout-- && !kill(pid, 0)) { - kill(pid, SIGTERM); - sleep(1); - } - if (!kill(pid, 0)) { - dbg_time("force kill %s/%s/exe -> %s", dir, file, filename); - kill(pid, SIGKILL); - sleep(1); - } - - return 1; -} - -static int kill_brothers(const char *qmichannel) -{ - char myself[MAX_PATH]; - int filenamesize; - void *argv[2] = {myself, (void *)qmichannel}; - - filenamesize = readlink("/proc/self/exe", myself, MAX_PATH); - if (filenamesize <= 0) - return 0; - myself[filenamesize] = 0; - - if (ls_dir("/proc", is_brother_process, argv)) - sleep(1); - - return 0; -} - -static void fibo_sigaction(int signo) -{ - if (SIGCHLD == signo) - waitpid(-1, NULL, WNOHANG); - else if (SIGALRM == signo) - send_signo_to_main(SIGUSR1); - else { - if (SIGTERM == signo || SIGHUP == signo || SIGINT == signo) - main_loop = 0; - send_signo_to_main(signo); - main_send_event_to_qmidevice(signo); // main may be wating qmi response - } -} - -static int usage(const char *progname) -{ - dbg_time("Usage: %s [options]", progname); - dbg_time( - "-s [apn [user password auth]] Set " - "apn/user/password/auth get from your network provider"); - dbg_time( - "-p pincode Verify sim card pin if " - "sim card is locked"); - dbg_time( - "-f logfilename Save log message of this " - "program to file"); - dbg_time( - "-i interface Specify network " - "interface(default auto-detect)"); - dbg_time("-4 IPv4 protocol"); - dbg_time("-6 IPv6 protocol"); - -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 - dbg_time("-g IPv6 private gateway"); -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 - -//2020-12-29 willa.liu@fibocom.com changed begin for support mantis 0066901 - //dbg_time( - //"-P profile index Specify profile index " - //"when start network data connection(default 1)."); -//2020-12-29 willa.liu@fibocom.com changed end for support mantis 0066901 - - dbg_time( - "-m muxID Specify muxid when set " - "multi-pdn data connection."); - dbg_time( - "-n channelID Specify channelID when " - "set multi-pdn data connection(default 1)."); - dbg_time( - "-N Number of channel Specify total channels " - "when set multi-pdn data connection(default 1)."); - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 - dbg_time( - "-k number kill specified process "); -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - - dbg_time("[Examples]"); - dbg_time("Example 1: %s ", progname); - dbg_time("Example 2: %s -s 3gnet ", progname); - dbg_time("Example 3: %s -s 3gnet carl 1234 0 -p 1234 -f gobinet_log.txt", - progname); - return 0; -} - -static int charsplit(const char *src, char *desc, int n, const char *splitStr) -{ - char *p; - char *p1; - int len; - - len = strlen(splitStr); - p = strstr(src, splitStr); - if (p == NULL) - return -1; - p1 = strstr(p, "\n"); - if (p1 == NULL) - return -1; - memset(desc, 0, n); - memcpy(desc, p + len, p1 - p - len); - - return 0; -} - -static int get_dev_major_minor(char *path, int *major, int *minor) -{ - int fd = -1; - char desc[128] = {0}; - char devmajor[64], devminor[64]; - int n = 0; - if (access(path, R_OK | W_OK)) { - return 1; - } - if ((fd = open(path, O_RDWR)) < 0) { - return 1; - } - n = read(fd, desc, sizeof(desc)); - if (n == sizeof(desc)) { - dbg_time("may be overflow"); - } - close(fd); - if (charsplit(desc, devmajor, 64, "MAJOR=") == -1 || - charsplit(desc, devminor, 64, "MINOR=") == -1) { - return 2; - } - *major = atoi(devmajor); - *minor = atoi(devminor); - return 0; -} -#ifdef GHT_FEATURE_PCIE_AUTO -//begin modified by zhangkaibo add PCIe auto detect feature on x55/x24 platform. 20200605 -static int qmipciedevice_detect(char **pp_qmichannel, char **pp_usbnet_adapter) -{ - struct dirent *ent = NULL; - DIR *pDir; - char dir[255] = "/sys/bus/pci/devices"; - - struct { - char subdir[255 * 2]; - char subdir2[255 * 3 + 16]; - char qmifile[255 * 2]; - } * pl; - pl = (typeof(pl))malloc(sizeof(*pl)); - memset(pl, 0x00, sizeof(*pl)); - - pDir = opendir(dir); - if (pDir) { - while ((ent = readdir(pDir)) != NULL) { - - struct dirent *subent = NULL; - DIR *psubDir; - char idVendor[4 + 1] = {0}; - char idDevice[4 + 1] = {0}; - char tempNetpath[256] = {0}; - int fd = 0; - char netcard[32] = "\0"; - - memset(pl, 0x00, sizeof(*pl)); - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/vendor", dir, - ent->d_name); - fd = open(pl->subdir, O_RDONLY); - if (fd > 0) { - read(fd, idVendor, 6); - close(fd); - } - - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/device", dir, - ent->d_name); - fd = open(pl->subdir, O_RDONLY); - if (fd > 0) { - read(fd, idDevice, 6); - close(fd); - } - - if (!strncasecmp(idVendor, "0x17cb", 6)) - ; - else - continue; - - dbg_time("Find %s/%s vendor=%s device=%s", dir, ent->d_name, - idVendor,idDevice); - //find pcie netdevicename - snprintf(tempNetpath,256,"%s%s_IP_HW0", idDevice+2 , ent->d_name+2); - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/%s/net", dir, - ent->d_name,tempNetpath); - psubDir = opendir(pl->subdir); - if (psubDir == NULL) { - dbg_time("Cannot open directory: %s, errno: %d (%s)", - pl->subdir, errno, strerror(errno)); - continue; - } - - while ((subent = readdir(psubDir)) != NULL) { - if (subent->d_name[0] == '.') - continue; - dbg_time("Find pcienet_adapter = %s", subent->d_name); - strcpy(netcard, subent->d_name); - break; - } - - closedir(psubDir); - - if (netcard[0]) { - } else { - continue; - } - - *pp_usbnet_adapter = strdup(netcard); - break; - } - closedir(pDir); - } - //find pcie qmi control name - if ((pDir = opendir("/dev")) == NULL) { - dbg_time("Cannot open directory: %s, errno:%d (%s)", "/dev", errno, - strerror(errno)); - return -ENODEV; - } - - while ((ent = readdir(pDir)) != NULL) { - if ( strncmp(ent->d_name, "mhi_QMI", strlen("mhi_QMI")) == 0 ) { - *pp_qmichannel = (char *)malloc(32); - sprintf(*pp_qmichannel, "/dev/%s", ent->d_name); - dbg_time("Find qmichannel = %s", *pp_qmichannel); - break; - } - } - closedir(pDir); - free(pl); - - return (*pp_qmichannel && *pp_usbnet_adapter); -} -//end modified by zhangkaibo add PCIe auto detect feature on x55/x24 platform. 20200605 -#endif -static int qmidevice_detect(char **pp_qmichannel, char **pp_usbnet_adapter,PROFILE_T *profile) -{ - struct dirent *ent = NULL; - DIR *pDir; - char dir[255] = "/sys/bus/usb/devices"; - int major = 0, minor = 0; - int indexid = 4; - struct { - char subdir[255 * 3]; - char subdir2[255 * 4 + 16]; - char qmifile[255 * 2]; - } * pl; -#ifdef GHT_FEATURE_PCIE_AUTO -//begin modified by zhangkaibo add PCIe auto detect feature on x55/x24 platform. 20200605 - if (qmipciedevice_detect(pp_qmichannel, pp_usbnet_adapter)) - { - return (*pp_qmichannel && *pp_usbnet_adapter); - } -//end modified by zhangkaibo add PCIe auto detect feature on x55/x24 platform. 20200605 -#endif - pl = (typeof(pl))malloc(sizeof(*pl)); - memset(pl, 0x00, sizeof(*pl)); - - pDir = opendir(dir); - if (pDir) { - while ((ent = readdir(pDir)) != NULL) { - struct dirent *subent = NULL; - DIR *psubDir; - char idVendor[4 + 1] = {0}; - char idProduct[4 + 1] = {0}; - int fd = 0; - char netcard[32] = "\0"; - - memset(pl, 0x00, sizeof(*pl)); - - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/idVendor", dir, - ent->d_name); - fd = open(pl->subdir, O_RDONLY); - if (fd > 0) { - read(fd, idVendor, 4); - close(fd); - } - - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s/idProduct", dir, - ent->d_name); - fd = open(pl->subdir, O_RDONLY); - if (fd > 0) { - read(fd, idProduct, 4); - close(fd); - } - - if (!strncasecmp(idVendor, "05c6", 4) || - !strncasecmp(idVendor, "2cb7", 4)) - ; - else - continue; - - dbg_time("Find %s/%s idVendor=%s idProduct=%s", dir, ent->d_name, - idVendor, idProduct); -//2021-02-08 zhangkaibo@fibocom.com changed start for mantis 0070613 - if(!strncasecmp(idProduct, "0109", 4)) - { - indexid = 2; - profile->interfacenum = 2; - } -//2021-09-09 willa.liu@fibocom.com changed start for mantis 0086219 - else if(!strncasecmp(idProduct, "0113", 4)) - { - indexid = 0; - profile->interfacenum = 0; - } -//2021-09-09 willa.liu@fibocom.com changed end for mantis 0086219 - else - { - profile->interfacenum = 4; - } - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.%d/net", dir, - ent->d_name,indexid); - psubDir = opendir(pl->subdir); - if (psubDir == NULL) { - dbg_time("Cannot open directory: %s, errno: %d (%s)", - pl->subdir, errno, strerror(errno)); - continue; - } - - while ((subent = readdir(psubDir)) != NULL) { - if (subent->d_name[0] == '.') - continue; - dbg_time("Find %s/%s", pl->subdir, subent->d_name); - dbg_time("Find usbnet_adapter = %s", subent->d_name); - strcpy(netcard, subent->d_name); - break; - } - - closedir(psubDir); - - if (netcard[0]) { - } else { - continue; - } - - if (*pp_usbnet_adapter && strcmp(*pp_usbnet_adapter, netcard)) - continue; - - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.%d/GobiQMI", dir, - ent->d_name,indexid); - if (access(pl->subdir, R_OK)) { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.%d/usbmisc", - dir, ent->d_name,indexid); - if (access(pl->subdir, R_OK)) { - snprintf(pl->subdir, sizeof(pl->subdir), "%s/%s:1.%d/usb", - dir, ent->d_name,indexid); - if (access(pl->subdir, R_OK)) { - dbg_time("no GobiQMI/usbmic/usb found in %s/%s:1.%d", - dir, ent->d_name,indexid); - continue; - } - } - } - -//2021-02-08 zhangkaibo@fibocom.com changed end for mantis 0070613 - - psubDir = opendir(pl->subdir); - if (pDir == NULL) { - dbg_time("Cannot open directory: %s, errno: %d (%s)", dir, - errno, strerror(errno)); - continue; - } - - while ((subent = readdir(psubDir)) != NULL) { - if (subent->d_name[0] == '.') - continue; - dbg_time("Find %s/%s", pl->subdir, subent->d_name); - dbg_time("Find qmichannel = /dev/%s", subent->d_name); - snprintf(pl->qmifile, sizeof(pl->qmifile), "/dev/%s", - subent->d_name); - - // get major minor - snprintf(pl->subdir2, sizeof(pl->subdir2), "%s/%s/uevent", - pl->subdir, subent->d_name); - if (!get_dev_major_minor(pl->subdir2, &major, &minor)) { - // dbg_time("%s major = %d, minor = %d\n",pl->qmifile, - // major, minor); - } else { - dbg_time("get %s major and minor failed\n", pl->qmifile); - } - // get major minor - - if ((fd = open(pl->qmifile, R_OK)) < 0) { - dbg_time("%s open failed", pl->qmifile); - dbg_time("please mknod %s c %d %d", pl->qmifile, major, - minor); - } else { - close(fd); - } - break; - } - - closedir(psubDir); - - if (netcard[0] && pl->qmifile[0]) { - *pp_qmichannel = strdup(pl->qmifile); - *pp_usbnet_adapter = strdup(netcard); - closedir(pDir); - return 1; - } - } - - closedir(pDir); - } - - if ((pDir = opendir("/dev")) == NULL) { - dbg_time("Cannot open directory: %s, errno:%d (%s)", "/dev", errno, - strerror(errno)); - return -ENODEV; - } - - while ((ent = readdir(pDir)) != NULL) { - if ((strncmp(ent->d_name, "cdc-wdm", strlen("cdc-wdm")) == 0) || - (strncmp(ent->d_name, "qcqmi", strlen("qcqmi")) == 0)) { - char net_path[255*2]; - - *pp_qmichannel = (char *)malloc(32); - sprintf(*pp_qmichannel, "/dev/%s", ent->d_name); - dbg_time("Find qmichannel = %s", *pp_qmichannel); - - if (strncmp(ent->d_name, "cdc-wdm", strlen("cdc-wdm")) == 0) - sprintf(net_path, "/sys/class/net/wwan%s", - &ent->d_name[strlen("cdc-wdm")]); - else { - sprintf(net_path, "/sys/class/net/usb%s", - &ent->d_name[strlen("qcqmi")]); - - if (access(net_path, R_OK) && errno == ENOENT) - sprintf(net_path, "/sys/class/net/eth%s", - &ent->d_name[strlen("qcqmi")]); - } - - if (access(net_path, R_OK) == 0) { - if (*pp_usbnet_adapter && - strcmp(*pp_usbnet_adapter, - (net_path + strlen("/sys/class/net/")))) { - free(*pp_qmichannel); - *pp_qmichannel = NULL; - continue; - } - *pp_usbnet_adapter = - strdup(net_path + strlen("/sys/class/net/")); - dbg_time("Find usbnet_adapter = %s", *pp_usbnet_adapter); - break; - } else { - dbg_time("Failed to access %s, errno:%d (%s)", net_path, errno, - strerror(errno)); - free(*pp_qmichannel); - *pp_qmichannel = NULL; - } - } - } - closedir(pDir); - free(pl); - - return (*pp_qmichannel && *pp_usbnet_adapter); -} -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 -int IsInt(char* str) -{ - int len; - len = strlen(str); - int i=0; - for(; i < len ; i++) - { - if(!(isdigit(str[i]))) - return 0; - } - return 1; -} -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 -int rdwr_init(int clienfd, char * msg) -{ - char buf[512]; - int rv = 0; - memset(buf, 0, 512); - while(1) - { - if ((rv = read(clienfd, buf, 512)) < 0) - { - dbg_time("Read by socket[%d] error:%s", clienfd, strerror(errno)); - goto STOP; - } - else if (0 == rv) - { - goto STOP; - } - else if (rv > 0) - { - dbg_time("Read %d bytes data from client, there are :[%s]", rv, buf); - } - if ((rv =write(clienfd, msg, strlen(msg))) < 0) - { - dbg_time("write to cilent by socket[%d] error:%s",clienfd, strerror(errno)); - goto STOP; - } - } -STOP: - dbg_time("The socket[%d] will exit!", clienfd); - return 0; -} - -void *thread_socket_server(void *args) -{ - int on = 1; - int rv = 0; - struct sockaddr_un serv_addr; - struct sockaddr_un cli_addr; - socklen_t len = sizeof(serv_addr); - sprintf(fibo_dial_filepath,"/tmp/fibocom_dial_%d",*(int*)args); - char* msg = "receive quit request\n"; - if ((socket_server_fd = socket(AF_UNIX,SOCK_STREAM,0))< 0) - { - dbg_time("Socket error:%s\a\n", strerror(errno)); - return ; - } - dbg_time("socket[%d] successfuly!", socket_server_fd); - if (!access(fibo_dial_filepath, F_OK)) - { - unlink(fibo_dial_filepath); - } - setsockopt(socket_server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - memset(&serv_addr, 0, sizeof(serv_addr)); - serv_addr.sun_family = AF_UNIX; - strncpy(serv_addr.sun_path, fibo_dial_filepath, sizeof(serv_addr.sun_path) - 1); - if ((rv = bind(socket_server_fd, (struct sockaddr *)&serv_addr, len)) < 0) - { - dbg_time("Bind error %s", strerror(errno)); - goto EXIT; - } - if ((rv = listen(socket_server_fd, 13)) < 0) - { - dbg_time("Listen error:%s", strerror(errno)); - goto EXIT; - } - dbg_time("Waiting client to connect....."); - sem_post(&sem); - while(1) - { - if ((cli_accept_fd = accept(socket_server_fd, (struct sockaddr *)&cli_addr, &len))< 0) - { - dbg_time("accept error:%s", strerror(errno)); - goto EXIT; - } - dbg_time("client to connected"); - rv = rdwr_init(cli_accept_fd, msg); - goto EXIT; - } -EXIT: - unlink(fibo_dial_filepath); - close(socket_server_fd ); - close(cli_accept_fd ); - send_signo_to_main(SIGTERM); - return ((void *)0); - -} - -//2020-12-29 willa.liu@fibocom.com changed begin for support mantis 0066901 -int startSocketserver(int pdpindex) -{ - pthread_t ntid; - //sem_init(&sem, 0, 2); - sem_init(&sem, 0, 0); - if (pthread_create(&ntid, 0, thread_socket_server, - (void *)(&pdpindex)) != 0) { - dbg_time("%s Failed to create QMIThread: %d (%s)", __func__, errno, - strerror(errno)); - } - sem_wait(&sem); - sem_destroy(&sem); - return 0; -} -//2020-12-29 willa.liu@fibocom.com changed begin for support mantis 0066901 - -int startSocketclient(int pdpindex) -{ - int socket_client_fd; - int rv = -1; - struct sockaddr_un servaddr; - char fibo_dial_filepath[100] = {0}; - sprintf(fibo_dial_filepath,"/tmp/fibocom_dial_%d",pdpindex); - dbg_time("enter startSocketclient %s.",fibo_dial_filepath); - char* message = "fibocom-dial quit request"; - char buf[1024]; - - if(access(fibo_dial_filepath, F_OK) != 0) - { - return -1; - } - socket_client_fd = socket(AF_UNIX,SOCK_STREAM,0); - if(socket_client_fd < 0) - { - dbg_time("Cearte socket failure :%s\a",strerror(errno)); - return -1; - } - dbg_time("Create socket [%d] sucessfully.",socket_client_fd); - memset(&servaddr,0,sizeof(servaddr)); - servaddr.sun_family = AF_UNIX; - strncpy(servaddr.sun_path, fibo_dial_filepath, sizeof(servaddr.sun_path) - 1); - rv = connect(socket_client_fd,(struct sockaddr *)&servaddr,sizeof(servaddr)); - if(rv <0) - { - dbg_time("connect to server [%s] failure :%s\a",fibo_dial_filepath,strerror(errno)); - return -2; - } - dbg_time("connect to server [%s] successfully!",fibo_dial_filepath); - rv = write(socket_client_fd,message,strlen(message)); - if(rv <0) - { - dbg_time("Write to server failure by socket[%d] failure: %s",socket_client_fd,strerror(errno)); - return -3; - } - else - { - dbg_time("Write [%s] to server by socket[%d] successfuly!", message, socket_client_fd); - } - memset(buf,0,sizeof(buf)); - rv = read(socket_client_fd,buf,1024); - if(rv < 0) - { - dbg_time("Read to server socket[%d] failure: %s",socket_client_fd,strerror(errno)); - return -4; - } - else if(rv == 0) - { - dbg_time("socket [%d] get disconnected",socket_client_fd); - return -4; - } - else if(rv >0) - { - dbg_time("Read [%d] bytes data from Server: [%s]",rv,buf); - } - close(socket_client_fd); - unlink(fibo_dial_filepath); - - return 0; -} -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 - -int main(int argc, char *argv[]) -{ - int triger_event = 0; - int opt = 1; - int signo; -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - int sim_number = 0; -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - char argvtemp[256] = {0}; -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 - int killnumber = -1; -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - -#ifdef CONFIG_SIM - SIM_Select SIMNumber; -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - SIM_Status SIMStatus; -#endif - UCHAR PSAttachedState; - UCHAR IPv4ConnectionStatus = 0xff; // unknow state - UCHAR IPV6ConnectionStatus = 0xff; // unknow state - int qmierr = 0; - char *save_usbnet_adapter = NULL; - PROFILE_T profile; -#ifdef CONFIG_RESET_RADIO - struct timeval resetRadioTime = {0}; - struct timeval FailDailRadioTime = {0}; - struct timeval nowTime; - gettimeofday(&resetRadioTime, (struct timezone *)NULL); -#endif - - dbg_time("Fibocom-dial_Linux_Tool_V%s", VERSION_STRING()); - memset(&profile, 0x00, sizeof(profile)); - profile.pdp = CONFIG_DEFAULT_PDP; - profile.pdpindex = CONFIG_DEFAULT_PDPINDEX; - profile.pdpnum = 1; - - if (!strcmp(argv[argc - 1], "&")) - argc--; - - opt = 1; - while (opt < argc) { - if (argv[opt][0] != '-') - return usage(argv[0]); - - switch (argv[opt++][1]) { -#define has_more_argv() ((opt < argc) && (argv[opt][0] != '-')) - case 's': - profile.apn = profile.user = profile.password = ""; - if (has_more_argv()) - profile.apn = argv[opt++]; - if (has_more_argv()) - profile.user = argv[opt++]; - if (has_more_argv()) { - profile.password = argv[opt++]; - if (profile.password && profile.password[0]) - profile.auth = 2; // default chap, customers may miss auth - } - if (has_more_argv()) -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - { - memset(argvtemp,0,256); - strcpy(argvtemp,argv[opt++]); - if(strlen(argvtemp) > 1 || !IsInt(argvtemp)) - { - dbg_time("Invalid parament for \"-s\""); - return -1; - } - profile.auth = argvtemp[0] - '0'; -//begin modified by zhangkaibo limit input parameters. mantis 0077949 20200513 - if(profile.auth < 0 || profile.auth > 3) - { - dbg_time("auth must be 0~3"); -//end modified by zhangkaibo limit input parameters. mantis 0077949 20200513 - return -1; - } - } -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - break; - - case 'm': - if (has_more_argv()) - { - if (is_pcie_dial()) - profile.muxid = argv[opt++][0] - '0'; - else - { - memset(argvtemp,0,256); - strcpy(argvtemp,argv[opt++]); - if(strlen(argvtemp) > 1 || !IsInt(argvtemp)) - { - dbg_time("Invalid parament for \"-P\""); - return -1; - } - profile.pdpindex = argvtemp[0] - '0'; - if(profile.pdpindex < 1 || profile.pdpindex > 10) - { - dbg_time("pdpindex must be 1~10"); - return -1; - } - } - } - break; - - case 'p': - if (has_more_argv()) - profile.pincode = argv[opt++]; - break; -#if 0 - case 'P': - if (has_more_argv()) -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - { - memset(argvtemp,0,256); - strcpy(argvtemp,argv[opt++]); - if(strlen(argvtemp) > 1 || !IsInt(argvtemp)) - { - dbg_time("Invalid parament for \"-P\""); - return -1; - } - profile.pdpindex = argvtemp[0] - '0'; - if(profile.pdpindex < 1 || profile.pdpindex > 10) - { - dbg_time("pdpindex must be 1~10"); - return -1; - } - } -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - break; -#endif - case 'n': - if (has_more_argv()) -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - { - memset(argvtemp,0,256); - strcpy(argvtemp,argv[opt++]); - if(strlen(argvtemp) > 1 || !IsInt(argvtemp)) - { - dbg_time("Invalid parament for \"-n\""); - return -1; - } - profile.pdp = argvtemp[0] - '0'; - if(profile.pdp < 1 || profile.pdp > 8) - { - dbg_time("pdpindex must be 1~8"); - return -1; - } - - if (is_pcie_dial()) - profile.pdpindex = profile.pdp; - } - break; -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - case 'N': - if (has_more_argv()) -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - { - memset(argvtemp,0,256); - strcpy(argvtemp,argv[opt++]); - if(strlen(argvtemp) > 1 || !IsInt(argvtemp)) - { - dbg_time("Invalid parament for \"-N\""); - return -1; - } - profile.pdpnum = argvtemp[0] - '0'; - if(profile.pdpnum < 0 || profile.pdpnum > 8) - { - dbg_time("pdpnum must be 0~8"); - return -1; - } - } -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - break; - - case 'f': - if (has_more_argv()) { - const char *filename = argv[opt++]; - logfilefp = fopen(filename, "a+"); - if (!logfilefp) { - dbg_time("Fail to open %s, errno: %d(%s)", filename, errno, - strerror(errno)); - } - } - break; - - case 'i': - if (has_more_argv()) - profile.usbnet_adapter = save_usbnet_adapter = argv[opt++]; - break; - - case 'v': - debug_qmi = 1; - break; - - case 'l': - if (has_more_argv()) { - profile.replication_factor = atoi(argv[opt++]); - if (profile.replication_factor > 0) - profile.loopback_state = 1; - } - else - main_loop = 1; - - break; - - case '4': - profile.ipv4_flag = 1; - break; - - case '6': - profile.ipv6_flag = 1; - break; - -//2021-02-25 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 - case 'g': - profile.ipv6_prigateway_flag = 1; - break; -//2021-02-25 willa.liu@fibocom.com changed end for support eipd SN-20210129001 - - case 'd': - if (has_more_argv()) { - profile.qmichannel = argv[opt++]; - if (qmidev_is_pciemhi(profile.qmichannel)) - profile.usbnet_adapter = "pcie_mhi0"; - } - break; - - case 'U': - query_pcie_mode = 1; - break; - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 - case 'k': - if (has_more_argv()) - { - memset(argvtemp,0,256); - strcpy(argvtemp,argv[opt++]); - if(strlen(argvtemp) > 1 || !IsInt(argvtemp)) - { - dbg_time("Invalid parament for \"-n\""); - return -1; - } - killnumber = argvtemp[0] - '0'; -//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837 - //if(killnumber < 1 || killnumber > 5) - if(killnumber < 1 || killnumber > 8) - { - dbg_time("pdpindex must be 1~8"); - return -1; - } -//2021-02-01 willa.liu@fibocom.com changed end for support mantis 0069837 - } - break; -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - - default: - return usage(argv[0]); - break; - } - } - - if (profile.ipv4_flag != 1 && - profile.ipv6_flag != 1) { // default enable IPv4 - profile.ipv4_flag = 1; - } - - dbg_time("%s profile[%d] = %s/%s/%s/%d, pincode = %s", argv[0], profile.pdp, - profile.apn, profile.user, profile.password, profile.auth, - profile.pincode); - signal(SIGUSR1, fibo_sigaction); - signal(SIGUSR2, fibo_sigaction); - signal(SIGINT, fibo_sigaction); - signal(SIGTERM, fibo_sigaction); - signal(SIGHUP, fibo_sigaction); - signal(SIGCHLD, fibo_sigaction); - signal(SIGALRM, fibo_sigaction); - - //2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 - if(killnumber == -1) - { - startSocketserver(profile.pdp); - } - else{ - startSocketclient(killnumber); - return 0; - } - //2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, signal_control_fd) < 0) { - dbg_time("%s Faild to create main_control_fd: %d (%s)", __func__, errno, - strerror(errno)); - return -1; - } - - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, qmidevice_control_fd) < 0) { - dbg_time("%s Failed to create thread control socket pair: %d (%s)", - __func__, errno, strerror(errno)); - return 0; - } - -// sudo apt-get install udhcpc -// sudo apt-get remove ModemManager -__main_loop: - while (!profile.qmichannel) { -//2021-02-08 zhangkaibo@fibocom.com changed start for mantis 0070613 - if (qmidevice_detect(&profile.qmichannel, &profile.usbnet_adapter,&profile)) -//2021-02-08 zhangkaibo@fibocom.com changed end for mantis 0070613 - { - if (query_pcie_mode) - get_pcie_mode(); - break; - } - if (main_loop) { - int wait_for_device = 3000; - dbg_time("Wait for fibo modules connect"); - while (wait_for_device && main_loop) { - wait_for_device -= 100; - usleep(100 * 1000); - } - continue; - } - dbg_time( - "Cannot find qmichannel(%s) usbnet_adapter(%s) for fibo modules", - profile.qmichannel, profile.usbnet_adapter); - return -ENODEV; - } - - if (access(profile.qmichannel, R_OK | W_OK)) { - dbg_time("Fail to access %s, errno: %d (%s)", profile.qmichannel, errno, - strerror(errno)); - return errno; - } - dbg_time( - "qmichannel(%s) usbnet_adapter(%s) ", - profile.qmichannel, profile.usbnet_adapter); - - if (qmidev_is_gobinet(profile.qmichannel)) { - profile.qmi_ops = &gobi_qmidev_ops; - dbg_time("usb rmnet mode"); - } else { - profile.qmi_ops = &qmiwwan_qmidev_ops; - dbg_time("pcie mode"); - } - qmidev_send = profile.qmi_ops->send; - fibo_qmap_mode_detect(&profile); - if (profile.pdpnum > 1 && profile.pdpnum != profile.qmap_mode && !qmidev_is_pciemhi(profile.qmichannel)) { - if (profile.qmap_mode > 1) { - dbg_time("qmap_mode=%d,profile.pdpnum %d",profile.qmap_mode,profile.pdpnum); - kill_brothers(profile.qmichannel); - } - fibo_qmap_mode_set(&profile); - } - fibo_qmap_mode_detect(&profile); -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - if(profile.qmap_mode < profile.pdp && profile.qmap_mode > 0 && !qmidev_is_pciemhi(profile.qmichannel)) - { - dbg_time("invalid pdpindex"); - return -1; - } -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - if (profile.qmap_mode == 0 || profile.qmap_mode == 1) - { - dbg_time("qmap_mode=%d",profile.qmap_mode); - kill_brothers(profile.qmichannel); - } - if (pthread_create(&gQmiThreadID, 0, profile.qmi_ops->read, - (void *)&profile) != 0) { - dbg_time("%s Failed to create QMIThread: %d (%s)", __func__, errno, - strerror(errno)); - return 0; - } - - if ((read(qmidevice_control_fd[0], &triger_event, sizeof(triger_event)) != - sizeof(triger_event)) || - (triger_event != RIL_INDICATE_DEVICE_CONNECTED)) { - dbg_time("%s Failed to init QMIThread: %d (%s)", __func__, errno, - strerror(errno)); - return 0; - } - - if (profile.qmi_ops->init && profile.qmi_ops->init(&profile)) { - dbg_time("%s Failed to qmi init: %d (%s)", __func__, errno, - strerror(errno)); - return 0; - } - -#ifdef CONFIG_VERSION - requestBaseBandVersion(NULL); -#endif - requestSetEthMode(&profile); - -#ifdef CONFIG_SIM -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - sim_number = requestGetSIMCardNumber(&profile); - if(sim_number == 1){ - requestSimBindSubscription_NAS_WMS(); - requestSimBindSubscription_WDS_DMS_QOS(); - } - //qmierr = requestGetSIMStatus(&SIMStatus); - qmierr = requestGetSIMStatus(&SIMStatus, sim_number); - while (qmierr == QMI_ERR_OP_DEVICE_UNSUPPORTED) { - sleep(1); - //qmierr = requestGetSIMStatus(&SIMStatus); - qmierr = requestGetSIMStatus(&SIMStatus, sim_number); -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 - } - if ((SIMStatus == SIM_PIN) && profile.pincode) { - requestEnterSimPin(profile.pincode); - } -#ifdef CONFIG_IMSI_ICCID - if (SIMStatus == SIM_READY) { - requestGetICCID(); - requestGetIMSI(); - } -#endif -#endif -#ifdef CONFIG_APN - if (profile.apn || profile.user || profile.password) { - requestSetProfile(&profile); - } - requestGetProfile(&profile); -#endif - requestRegistrationState2(&PSAttachedState); - /* - if (!requestQueryDataCall(&IPv4ConnectionStatus, IpFamilyV4) && - (QWDS_PKT_DATA_CONNECTED == IPv4ConnectionStatus)) usbnet_link_change(1, - &profile); else usbnet_link_change(0, &profile); - */ - send_signo_to_main(SIGUSR2); - - while (1) { - struct pollfd pollfds[] = {{signal_control_fd[1], POLLIN, 0}, - {qmidevice_control_fd[0], POLLIN, 0}}; - int ne, ret, nevents = sizeof(pollfds) / sizeof(pollfds[0]); - - do { - ret = poll(pollfds, nevents, 15 * 1000); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0) { - send_signo_to_main(SIGUSR2); - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, - strerror(errno)); - goto __main_quit; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - main_send_event_to_qmidevice(RIL_REQUEST_QUIT); - if (revents & POLLHUP) - goto __main_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == signal_control_fd[1]) { - if (read(fd, &signo, sizeof(signo)) == sizeof(signo)) { - alarm(0); - dbg_time("get signo: %d ",signo); - switch (signo) { - case SIGUSR1: - { - if(profile.ipv4_flag) - { - if (QWDS_PKT_DATA_CONNECTED != IPv4ConnectionStatus) { - usbnet_link_change(0, &profile); - requestRegistrationState2(&PSAttachedState); - -//2021-02-05 willa.liu@fibocom.com changed begin for support mantis 0070460 - //if (PSAttachedState == 1 || profile.loopback_state == 0) { - if (PSAttachedState == 1 || profile.loopback_state == 1) { - qmierr = - requestSetupDataCall(&profile, IpFamilyV4); - - if ((qmierr > 0) && profile.user && - profile.user[0] && profile.password && - profile.password[0]) { - int old_auto = profile.auth; - - // may be fail because wrong auth mode, try - // pap->chap, or chap->pap - profile.auth = (profile.auth == 1) ? 2 : 1; - qmierr = requestSetupDataCall(&profile, - IpFamilyV4); - - if (qmierr) - profile.auth = - old_auto; // still fail, restore - // old auth moe - } - if (!qmierr) { - requestGetIPAddress(&profile, IpFamilyV4); - } - if (!qmierr){ - IPv4ConnectionStatus = QWDS_PKT_DATA_CONNECTED; - FailDailRadioTime.tv_sec = 0; - } - else if(FailDailRadioTime.tv_sec == 0) { - gettimeofday(&FailDailRadioTime, (struct timezone *)NULL); - } - } - } - } - if(profile.ipv6_flag) - { - if (QWDS_PKT_DATA_CONNECTED != IPV6ConnectionStatus) { - if(!profile.ipv4_flag) - { - usbnet_link_change(0, &profile); - requestRegistrationState2(&PSAttachedState); - } - else - { - profile.dual_flag = 1; - //PSAttachedState = 1; // for dual stack - requestRegistrationState2(&PSAttachedState); - } -//2021-02-05 willa.liu@fibocom.com changed end for support mantis 0070460 - - if (PSAttachedState == 1) { - qmierr = - requestSetupDataCall(&profile, IpFamilyV6); - if ((g_MobileCountryCode == 460) && (g_MobileNetworkCode == 1 || g_MobileNetworkCode == 6)) { - if (qmierr > 0 && profile.dual_flag == 1) { - profile.dual_flag = 0; - profile.ipv6_flag = 0; - dbg_time("%s Dual stack dial IPv6 failed, quit", __func__); - break; - } - } - if ((qmierr > 0) && profile.user && - profile.user[0] && profile.password && - profile.password[0]) { - int old_auto = profile.auth; - - // may be fail because wrong auth mode, try - // pap->chap, or chap->pap - profile.auth = (profile.auth == 1) ? 2 : 1; - qmierr = requestSetupDataCall(&profile, - IpFamilyV6); - - if (qmierr) - profile.auth = - old_auto; // still fail, restore - // old auth moe - } - if (!qmierr) { - requestGetIPAddress(&profile, IpFamilyV6); - } - - if (!qmierr){ - IPV6ConnectionStatus = QWDS_PKT_DATA_CONNECTED; - FailDailRadioTime.tv_sec = 0; - } - else if(FailDailRadioTime.tv_sec == 0) { - gettimeofday(&FailDailRadioTime, (struct timezone *)NULL); - } - } - } - } -#ifdef CONFIG_RESET_RADIO - if( ((profile.ipv4_flag)&&(IPv4ConnectionStatus != QWDS_PKT_DATA_CONNECTED))|| - ((profile.ipv6_flag)&&(IPV6ConnectionStatus != QWDS_PKT_DATA_CONNECTED))) - { - gettimeofday(&nowTime, (struct timezone *)NULL); - if( ((abs(nowTime.tv_sec - FailDailRadioTime.tv_sec) > CONFIG_RESET_RADIO)) - &&(FailDailRadioTime.tv_sec > resetRadioTime.tv_sec)){ - resetRadioTime = nowTime; - // requestSetOperatingMode(0x06); //same as - // AT+CFUN=0 - requestSetOperatingMode( - 0x01); // same as AT+CFUN=4 - requestSetOperatingMode( - 0x00); // same as AT+CFUN=1 - } - } -#endif - alarm(5); // try to setup data call 5 seconds later - } - break; - - case SIGUSR2: - { - - if (profile.ipv4_flag) - { - requestQueryDataCall(&IPv4ConnectionStatus, IpFamilyV4); - //local ip is different with remote ip - if (QWDS_PKT_DATA_CONNECTED == IPv4ConnectionStatus && check_address(&profile,IpFamilyV4) == 0) { - requestDeactivateDefaultPDP(&profile, IpFamilyV4); - IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - } - else - IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - if (profile.ipv6_flag) - requestQueryDataCall(&IPV6ConnectionStatus, IpFamilyV6); - else - IPV6ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - if(IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED && IPV6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) - { - usbnet_link_change(0, &profile); - } - if((profile.ipv6_flag && profile.ipv6_flag ) && ((IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED && IPV6ConnectionStatus == QWDS_PKT_DATA_CONNECTED)) ) - { - usbnet_link_change(1, &profile); - } - else - if(IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPV6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) - { - usbnet_link_change(1, &profile); - } - if((profile.ipv4_flag && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED ) || - (profile.ipv6_flag && IPV6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED )) - { - send_signo_to_main(SIGUSR1); - } - } - break; - - case SIGTERM: - case SIGHUP: - case SIGINT: - if(profile.ipv4_flag && IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED) - requestDeactivateDefaultPDP(&profile, IpFamilyV4); - if(profile.ipv6_flag && IPV6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) - requestDeactivateDefaultPDP(&profile, IpFamilyV6); - - usbnet_link_change(0, &profile); - if (profile.qmi_ops->deinit) - profile.qmi_ops->deinit(); - main_send_event_to_qmidevice(RIL_REQUEST_QUIT); - goto __main_quit; - break; - - default: - break; - } - } - } - - if (fd == qmidevice_control_fd[0]) { - if (read(fd, &triger_event, sizeof(triger_event)) == - sizeof(triger_event)) { - switch (triger_event) { - case RIL_INDICATE_DEVICE_DISCONNECTED: - usbnet_link_change(0, &profile); - if (main_loop) { - if (pthread_join(gQmiThreadID, NULL)) { - dbg_time( - "%s Error joining to listener thread (%s)", - __func__, strerror(errno)); - } - profile.qmichannel = NULL; - profile.usbnet_adapter = save_usbnet_adapter; - goto __main_loop; - } - goto __main_quit; - break; - - case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: - requestRegistrationState2(&PSAttachedState); - if (PSAttachedState == 1) - { -//begin modify for mantis 0050112 by kaibo.zhangkaibo@fibocom.com - if((profile.ipv4_flag && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) - ||(profile.ipv6_flag && IPV6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) -//end modify for mantis 0050112 by kaibo.zhangkaibo@fibocom.com - send_signo_to_main(SIGUSR1); - } - break; - - case RIL_UNSOL_DATA_CALL_LIST_CHANGED: - if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPV6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) - send_signo_to_main(SIGUSR2); - break; - - default: - break; - } - } - } - } - } - -__main_quit: - usbnet_link_change(0, &profile); - if (pthread_join(gQmiThreadID, NULL)) { - dbg_time("%s Error joining to listener thread (%s)", __func__, - strerror(errno)); - } - close(signal_control_fd[0]); - close(signal_control_fd[1]); - close(qmidevice_control_fd[0]); - close(qmidevice_control_fd[1]); - dbg_time("%s exit", __func__); - if (logfilefp) - fclose(logfilefp); - -//2020-12-23 willa.liu@fibocom.com changed begin for support mantis 0065286 - unlink(fibo_dial_filepath); - close(socket_server_fd ); - close(cli_accept_fd ); -//2020-12-23 willa.liu@fibocom.com changed end for support mantis 0065286 - - return 0; -} diff --git a/fibocom-dial/src/multi-pdn-manager.c b/fibocom-dial/src/multi-pdn-manager.c deleted file mode 100644 index 20d05e7..0000000 --- a/fibocom-dial/src/multi-pdn-manager.c +++ /dev/null @@ -1,1019 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -//begin modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 -#include -//end modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 -#include "util.h" -#include "query_pcie_mode.h" -#define MAJOR 1 -#define MINOR 0 -#define REVISION 4 -/* - * Generally, we do not modify version info, so several modifications will share - * the same version code. SUBVERSION is used for customized modification to - * distinguise this version from previous one. SUBVERSION adds up before you - * send the code to customers and it should be set to 0 if VERSION_STRING info - * is changed. - */ -#define SUBVERSION 0 -#define STRINGIFY_HELPER(v) #v -#define STRINGIFY(v) STRINGIFY_HELPER(v) -#define VERSION_STRING() \ - STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(REVISION) -#define MAX_PATH 256 - -#define _PARAM_GLOBALS_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -//begin modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 -#include -//end modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 -#define SECTION_MAX_LEN 256 -#define STRVALUE_MAX_LEN 256 -#define LINE_CONTENT_MAX_LEN 256 -#define READ_STR_ERR -1 -#define READ_STR_OK 0 -//begin modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 - -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -//#include "query_pcie_mode.h" -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 - -static int is_pcie_dial() -{ - return (access("/dev/mhi_QMI0", F_OK) == 0); -} - -static int is_gobinet_dial() -{ - return (access("/dev/qcqmi0", F_OK) == 0); -} - -static int is_qmiwwan_dial() -{ - return (access("/dev/cdc-wdm0", F_OK) == 0); -} - -static size_t fibo_fread(const char *filename, void *buf, size_t size) -{ - FILE *fp = fopen(filename, "r"); - size_t n = 0; - - memset(buf, 0x00, size); - - if (fp) { - n = fread(buf, 1, size, fp); - if (n <= 0 || n == size) { - dbg_time( - "warnning: fail to fread(%s), fread=%zd, buf_size=%zd, " - "errno: %d (%s)", - __func__, filename, n, size, errno, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -int get_qmap_num() -{ - int n; - int qmap_num=-1; - char buf[128]; - struct { - char filename[255 * 2]; - char linkname[255 * 2]; - } * pl; - - if (is_pcie_dial()) - return 8; - - pl = (typeof(pl))malloc(sizeof(*pl)); - - if(is_gobinet_dial()) - { - snprintf(pl->linkname, sizeof(pl->linkname), - "/sys/class/net/usb0/device/driver"); - n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); - pl->filename[n] = '\0'; - while (pl->filename[n] != '/') n--; - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/usb0/qmap_num"); - //2021-02-22 kaibo.zhangkaibo@fibocom.com changed begin for support mantis 0071171 - if (access(pl->filename, F_OK) == 0) { - dbg_time("access %s", pl->filename); - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, - strerror(errno)); - goto _out; - } - } - else - { - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/usb0/qmap_mode"); - if (access(pl->filename, F_OK) == 0) { - dbg_time("access %s", pl->filename); - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, - strerror(errno)); - goto _out; - } - } - } - } - if(is_qmiwwan_dial()) - { - snprintf(pl->linkname, sizeof(pl->linkname), - "/sys/class/net/wwan0/device/driver"); - n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); - pl->filename[n] = '\0'; - while (pl->filename[n] != '/') n--; - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/wwan0/qmap_mode"); - if (access(pl->filename, F_OK) == 0) { - dbg_time("access %s", pl->filename); - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, - strerror(errno)); - goto _out; - } - } - } - - dbg_time("access %s", pl->filename); - - if (!access(pl->filename, R_OK)) { - n = fibo_fread(pl->filename, buf, sizeof(buf)); - if (n > 0) { - qmap_num = atoi(buf); - } - } -_out: - free(pl); - - return qmap_num; -} -//end modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 -int IsInt(char* str) -{ - int len; - len = strlen(str-1); - len = len>=1?len:1; - int i=0; - for(; i < len ; i++) - { - if(!(isdigit(str[i]))) - return 0; - } - return 1; -} - -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 -// read value from .ini -void IniReadValue(char *section, char *key, char *val, const char *file) -{ - FILE *fp; - int i = 0; - int lineContentLen = 0; - int position = 0; - char lineContent[LINE_CONTENT_MAX_LEN]; - bool bFoundSection = false; - bool bFoundKey = false; - fp = fopen(file, "r"); - if (fp == NULL) { - printf("%s: Opent file %s failed.\n", __FILE__, file); - return; - } - while (feof(fp) == 0) { - memset(lineContent, 0, LINE_CONTENT_MAX_LEN); - fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); - if ((lineContent[0] == ';') || (lineContent[0] == '\0') || - (lineContent[0] == '\r') || (lineContent[0] == '\n')) { - continue; - } - - // check section - if (strncmp(lineContent, section, strlen(section)) == 0) { - bFoundSection = true; - // printf("Found section = %s\n", lineContent); - while (feof(fp) == 0) { - memset(lineContent, 0, LINE_CONTENT_MAX_LEN); - fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); - // check key - if (strncmp(lineContent, key, strlen(key)) == 0) { - bFoundKey = true; - lineContentLen = strlen(lineContent); - // find value - for (i = strlen(key); i < lineContentLen; i++) { - if (lineContent[i] == '=') { - position = i + 1; - break; - } - } - if (i >= lineContentLen) - break; - strncpy(val, lineContent + position, - strlen(lineContent + position)); - lineContentLen = strlen(val); - for (i = 0; i < lineContentLen; i++) { - if ((val[i] == '\0') || (val[i] == '\r') || - (val[i] == '\n')) { - val[i] = '\0'; - // break; - } - } - } else if (lineContent[0] == '[') { - break; - } - } - break; - } - } - if (!bFoundSection) { - printf("No section = %s\n", section); - } else if (!bFoundKey) { - printf("No key = %s\n", key); - } - - fclose(fp); -} - -int readStringValue(const char *section, char *key, char *val, const char *file) -{ - char sect[SECTION_MAX_LEN]; - // printf("section = %s, key = %s, file = %s\n", section, key, file); - if (section == NULL || key == NULL || val == NULL || file == NULL) { - printf("%s: input parameter(s) is NULL!\n", __func__); - return READ_STR_ERR; - } - - memset(sect, 0, SECTION_MAX_LEN); - sprintf(sect, "[%s]", section); - // printf("reading value...\n"); - IniReadValue(sect, key, val, file); - - return READ_STR_OK; -} - -char fileContents[80][LINE_CONTENT_MAX_LEN]; -int fileIndex = 0; - -void IniWriteValue(const char *section, char *key, char *val, const char *file) -{ - int err = 0; - char lineContent[LINE_CONTENT_MAX_LEN]; - char strWrite[LINE_CONTENT_MAX_LEN]; - bool bFoundSection = false; - bool bFoundKey = false; - int fileIndextemp = 0; - memset(lineContent, '\0', LINE_CONTENT_MAX_LEN); - memset(strWrite, '\0', LINE_CONTENT_MAX_LEN); - sprintf(strWrite, "%s=%s\n", key, val); - - while (fileIndextemp <= fileIndex) { - memset(lineContent, 0, LINE_CONTENT_MAX_LEN); - memcpy(lineContent, fileContents[fileIndextemp++], - LINE_CONTENT_MAX_LEN); - if ((lineContent[0] == ';') || (lineContent[0] == '\0') || - (lineContent[0] == '\r') || (lineContent[0] == '\n')) { - continue; - } - // check section - if (strncmp(lineContent, section, strlen(section)) == 0) { - bFoundSection = true; - while (fileIndextemp <= fileIndex) { - memset(lineContent, 0, LINE_CONTENT_MAX_LEN); - memcpy(lineContent, fileContents[fileIndextemp], - LINE_CONTENT_MAX_LEN); - // check key - if (strncmp(lineContent, key, strlen(key)) == 0) { - bFoundKey = true; - // printf("%s: %s=%s\n", __func__, key, val); - memset(fileContents[fileIndextemp], 0, - LINE_CONTENT_MAX_LEN); - memcpy(fileContents[fileIndextemp], strWrite, - strlen(strWrite)); - // printf("%s\n",strWrite); - if (err < 0) { - printf("%s err.\n", __func__); - } - break; - } else if (lineContent[0] == '[') { - fileIndextemp++; - break; - } - fileIndextemp++; - } - break; - } - } - if (!bFoundSection) { - printf("No section = %s\n", section); - } else if (!bFoundKey) { - printf("No key = %s\n", key); - } -} - -int writeStringVlaue(const char *section, char *key, char *val, - const char *file) -{ - char sect[SECTION_MAX_LEN]; - - // printf("section = %s, key = %s, value=%s , file = %s\n", section, key, - // val, file); - if (section == NULL || key == NULL || val == NULL || file == NULL) { - printf("%s: input parameter(s) is NULL!\n", __func__); - return READ_STR_ERR; - } - memset(sect, '\0', SECTION_MAX_LEN); - sprintf(sect, "[%s]", section); - IniWriteValue(sect, key, val, file); - return READ_STR_OK; -} - -int writeIntValue(const char *section, char *key, int val, const char *file) -{ - char strValue[STRVALUE_MAX_LEN]; - memset(strValue, '\0', STRVALUE_MAX_LEN); - sprintf(strValue, "%d", val); - - return writeStringVlaue(section, key, strValue, file); -} - -int readIntValue(const char *section, char *key, const char *file) -{ - char strValue[STRVALUE_MAX_LEN]; - memset(strValue, '\0', STRVALUE_MAX_LEN); - if (readStringValue(section, key, strValue, file) != READ_STR_OK) { - printf("%s: error", __func__); - return 0; - } - return (atoi(strValue)); -} - -int mygetch() -{ - struct termios oldt, newt; - int ch; - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - ch = getchar(); - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - return ch; -} - -#define CONFIG_FILE "multi-pdn.ini" -#define DIAL_PROCESS "fibocom-dial" -#define MAX_QMAP_NUM 8 - -struct profile { - char apn[MAX_PATH]; - char user[MAX_PATH]; - char password[MAX_PATH]; - int auth; - int ipfamily; -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - char pin[MAX_PATH]; -//end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 -}; - -int shmid; -void *shm; -int qmap_num = -1; - -bool connectState[MAX_QMAP_NUM]; -int lock_file = -1; - -void initShareMemory() -{ - shmid = shmget((key_t)9527, sizeof(int) * 8, 0666 | IPC_CREAT); - if (shmid == -1) { - fprintf(stderr, "shmget failed\n"); - exit(EXIT_FAILURE); - } - shm = shmat(shmid, 0, 0); - if (shm == (void *)-1) { - fprintf(stderr, "shmat failed\n"); - exit(EXIT_FAILURE); - } -} - -void destoryShareMemory() -{ - if (shmdt(shm) == -1) { - fprintf(stderr, "shmdt failed\n"); - exit(EXIT_FAILURE); - } - - if (shmctl(shmid, IPC_RMID, 0) == -1) { - fprintf(stderr, "shmctl(IPC_RMID) failed\n"); - exit(EXIT_FAILURE); - } -} - -void SIGINT_handle(int sig_num) - -{ - printf("reveice signal %d \n", sig_num); - { - int *connectPids = (int *)shm; - int cIndex; - for(cIndex = 1 ; cIndex <= qmap_num ; cIndex++) - { - dbg_time("kill pid %d", connectPids[cIndex - 1]); - kill(connectPids[cIndex - 1], SIGINT); - connectState[cIndex - 1] = false; - } - } - destoryShareMemory(); - close(lock_file); // 不要忘记释放文件指针 - exit(0); -} - -int loadConfigFromIni(struct profile *profileList, bool *connectState) -{ - int profileIndex; -//begin modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 - //qmap_num = readIntValue("Setting", "qmap_num", CONFIG_FILE); - qmap_num = get_qmap_num(); - if (qmap_num == 0 || qmap_num == -1 ) - return -1; -//end modified by zhangkaibo get qmap_num process flow. mantis 0048920,0048917 20200605 - for (profileIndex = 0; profileIndex < 8; profileIndex++) { - char profilename[MAX_PATH]; - sprintf(profilename, "profile%d", profileIndex + 1); - memset(profileList[profileIndex].apn, 0, MAX_PATH); - readStringValue(profilename, "apn", profileList[profileIndex].apn, - CONFIG_FILE); - memset(profileList[profileIndex].user, 0, MAX_PATH); - readStringValue(profilename, "user", profileList[profileIndex].user, - CONFIG_FILE); - memset(profileList[profileIndex].password, 0, MAX_PATH); - readStringValue(profilename, "password", - profileList[profileIndex].password, CONFIG_FILE); - profileList[profileIndex].auth = - readIntValue(profilename, "auth", CONFIG_FILE); - profileList[profileIndex].ipfamily = - readIntValue(profilename, "ipfamily", CONFIG_FILE); -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - memset(profileList[profileIndex].pin, 0, MAX_PATH); - readStringValue(profilename, "pin", profileList[profileIndex].pin, - CONFIG_FILE); -//end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - } - FILE *fp; - fileIndex = 0; - char lineContent[LINE_CONTENT_MAX_LEN]; - fp = fopen(CONFIG_FILE, "r+"); - if (fp == NULL) { - printf("%s: Opent file %s failed.\n", __FILE__, CONFIG_FILE); - return -2; - } - // read all - while (feof(fp) == 0) { - memset(lineContent, 0, LINE_CONTENT_MAX_LEN); - fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); - memcpy(fileContents[fileIndex], lineContent, strlen(lineContent)); - // printf("%s",fileContents[fileIndex]); - fileIndex++; - } - fclose(fp); - return 0; -} - -void saveConfigToIni() -{ - FILE *fp; - fp = fopen(CONFIG_FILE, "w"); - int fileIndextemp = 0; - fseek(fp, 0, SEEK_SET); - while (fileIndextemp <= fileIndex) { - fwrite(fileContents[fileIndextemp], strlen(fileContents[fileIndextemp]), - 1, fp); - // printf("%s",fileContents[fileIndextemp]); - fileIndextemp++; - } - fclose(fp); -} - -void modifyProfile(struct profile *profileList) -{ - int profileIndex; -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - struct profile tempprofile; -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - char *f; - // show current fprfile setting - for (profileIndex = 0; profileIndex < 8; profileIndex++) { - dbg_time( - "Fibocom manager \nprofile%d apn:\"%s\" username:\"%s\" password: " - "\"%s\" auth: \"%d\" ip family: \"%d\"", - profileIndex + 1, profileList[profileIndex].apn, - profileList[profileIndex].user, profileList[profileIndex].password, - profileList[profileIndex].auth, profileList[profileIndex].ipfamily); - } - // select instance to be set - int connectProfile; - printf("set profile index:"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - connectProfile = atoi(f); -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - if(!IsInt(f)){ - dbg_time("invalid input"); - return; - } -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - if (connectProfile < 0 || connectProfile > 8) { - dbg_time("error profile id"); - return; - } - free(f); - /* - * Begin: 2020-11-16, Lizhengyang for multi-pdn-manager, - * Solve the problem of setting length - * of apn/username/password, mantis 0062495. - */ - printf("profile apn:"); - f = malloc(MAX_PATH); - if (f == NULL) - { - printf("profile apn f malloc null\n"); - return; - } - fgets(f, MAX_PATH, stdin); - f[strlen(f) - 1] = '\0'; - strcpy(tempprofile.apn, f); - free(f); - - printf("profile username:"); - f = malloc(MAX_PATH); - if (f == NULL) - { - printf("profile username f malloc null\n"); - return; - } - fgets(f, MAX_PATH, stdin); - f[strlen(f) - 1] = '\0'; - strcpy(tempprofile.user, f); - free(f); - - printf("profile password:"); - f = malloc(MAX_PATH); - if (f == NULL) - { - printf("profile password f malloc null\n"); - return; - } - fgets(f, MAX_PATH, stdin); - f[strlen(f) - 1] = '\0'; - strcpy(tempprofile.password, f); - free(f); - /* - * End: 2020-11-16, Lizhengyang for multi-pdn-manager, - * Solve the problem of setting length - * of apn/username/password, mantis 0062495. - */ - printf("profile auth[0-3]:"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - tempprofile.auth = atoi(f); - if(!IsInt(f)){ - dbg_time("invalid input"); - return; - } - if(tempprofile.auth < 0 || tempprofile.auth > 3){ - dbg_time("invalid auth type"); - return; - } -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - free(f); - - printf("profile ipfamily[1-3]:"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); -//begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - tempprofile.ipfamily = atoi(f); - if(!IsInt(f)){ - dbg_time("invalid input"); - return; - } - free(f); - if(tempprofile.ipfamily < 1 || tempprofile.ipfamily > 3){ - dbg_time("invalid auth type"); - return; - } -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - printf("pin:"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - f[strlen(f)-1]='\0'; - strcpy(tempprofile.pin, f); - free(f); -//end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - memset(profileList[connectProfile-1].apn, 0, MAX_PATH); - memset(profileList[connectProfile-1].user, 0, MAX_PATH); - memset(profileList[connectProfile-1].password, 0, MAX_PATH); - - strcpy(profileList[connectProfile-1].apn , tempprofile.apn); - strcpy(profileList[connectProfile-1].user , tempprofile.user); - strcpy(profileList[connectProfile-1].password , tempprofile.password); - profileList[connectProfile-1].auth = tempprofile.auth; - profileList[connectProfile-1].ipfamily = tempprofile.ipfamily; -//end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - //strcpy(profileList[connectProfile].pin , tempprofile.pin); - strcpy(profileList[connectProfile-1].pin , tempprofile.pin); -//end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - // save in - for (profileIndex = 0; profileIndex < qmap_num; profileIndex++) { - dbg_time( - "Fibocom manager \nprofile%d apn:\"%s\" username:\"%s\" pawssword: " - "\"%s\" auth: \"%d\" ip family: \"%d\"", - profileIndex + 1, profileList[profileIndex].apn, - profileList[profileIndex].user, profileList[profileIndex].password, - profileList[profileIndex].auth, profileList[profileIndex].ipfamily); - char profilename[MAX_PATH]; - sprintf(profilename, "profile%d", profileIndex + 1); - writeStringVlaue(profilename, "apn", profileList[profileIndex].apn, - CONFIG_FILE); - writeStringVlaue(profilename, "user", profileList[profileIndex].user, - CONFIG_FILE); - writeStringVlaue(profilename, "password", - profileList[profileIndex].password, CONFIG_FILE); - writeIntValue(profilename, "auth", profileList[profileIndex].auth, - CONFIG_FILE); - writeIntValue(profilename, "ipfamily", - profileList[profileIndex].ipfamily, CONFIG_FILE); -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - writeStringVlaue(profilename, "pin", - profileList[profileIndex].pin, CONFIG_FILE); -//end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - } -} - -void startConnectCM(struct profile *profileList, bool *connectState) -{ - int connectIndex; - int connectProfile; - char *f; - printf("connect visual net interface use:"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - connectIndex = atoi(f); - free(f); - if (connectIndex < 1 || connectIndex > qmap_num) { - dbg_time("error visual net interface "); - return; - } - printf("connect profile use:"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - connectProfile = atoi(f); - free(f); - if (connectProfile < 1 || connectProfile > 8) { - dbg_time("error profile id"); - return; - } -//begin modified by zhangkaibo modify mantis0048806. 20200605 - if (connectState[connectIndex - 1] == true) { - dbg_time( - "visual net interface %d now is connected", - connectIndex); - return; - } -//end modified by zhangkaibo modify mantis0048806. 20200605 - dbg_time("Start connect network use instance %d profile %d", connectIndex, - connectProfile); - char cmd[1024]; - //./fibicom-dial -n -s -s apn user password auth -4 -6 - - sprintf(cmd, "-n %d -m %d -s %s %s %s %d", connectIndex, connectProfile, - profileList[connectProfile - 1].apn, - profileList[connectProfile - 1].user, - profileList[connectProfile - 1].password, - profileList[connectProfile - 1].auth); - char *argvCmd[30]; - int index = 0; - // DIAL_PROCESS,","-N","4,""-n","2","-m","1","-s","ctnet","","","","-4","-6","-f","temp.txt",NULL; - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%s", DIAL_PROCESS); - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-N"); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%d", qmap_num); - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-n"); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%d", connectIndex); - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-m"); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%d", connectProfile); - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-s"); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%s", profileList[connectProfile - 1].apn); - if (strlen(profileList[connectProfile - 1].user) > 0) { - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%s", profileList[connectProfile - 1].user); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%s", - profileList[connectProfile - 1].password); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%d", profileList[connectProfile - 1].auth); - } - - if (profileList[connectProfile - 1].ipfamily == 2) { - argvCmd[index] = malloc(5); -//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605 - sprintf(argvCmd[index++], "-6"); -//end modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605 - } else if (profileList[connectProfile - 1].ipfamily == 3) { - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-4"); - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-6"); - } else { - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-4"); - } -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - if (strlen(profileList[connectProfile - 1].pin) > 0) { - argvCmd[index] = malloc(5); - sprintf(argvCmd[index++], "-p"); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "%s", profileList[connectProfile - 1].pin); - } - - argvCmd[index] = malloc(5); -//end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - sprintf(argvCmd[index++], "-f"); - argvCmd[index] = malloc(256); - sprintf(argvCmd[index++], "instance%d.txt", connectIndex); - argvCmd[index] = NULL; - char temp[MAX_PATH]; - sprintf(temp, "rm -f instance%d.txt", connectIndex); - system(temp); - if (0 == fork()) { - int *connectPids = (int *)shm; - connectPids[connectIndex - 1] = getpid(); - dbg_time("exec pid %d", connectPids[connectIndex - 1]); - char tempcmd[MAX_PATH]; - sprintf(tempcmd, "./%s", DIAL_PROCESS); - execvp(tempcmd, argvCmd); - // system(cmd); -//begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - } -//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837 - //for(int ii=0; ii < index;ii++) - int ii; - for(ii = 0;ii < index;ii++) -//2021-02-01 willa.liu@fibocom.com changed end for support mantis 0069837 - { - printf("%s ",argvCmd[ii]); - free(argvCmd[ii]); - } - printf("\r\n"); - connectState[connectIndex - 1] = true; -} - -int main(int argc, char *argv[]) -{ - struct profile profileList[MAX_QMAP_NUM]; - char *f; - int profileIndex; - int opsCode = -1; - int ret=0; - - /* Exit if the process is already running */ - lock_file = open("/tmp/single_proc.lock", O_CREAT|O_RDWR, 0666); - ret = flock(lock_file, LOCK_EX|LOCK_NB); - if (ret) - { - if (EWOULDBLOCK == errno) - { - dbg_time("The Fibocom multi-pdn-manager is already running! So killall multi-pdn-manager!"); - system("killall -9 fibocom-dial"); - system("killall -9 multi-pdn-manager"); - } - } - else - { - char buffer[64]; - sprintf(buffer, "pid:%d\n", getpid()); - write(lock_file, buffer, strlen(buffer)); - system("killall -9 fibocom-dial"); - dbg_time("Start Fibocom multi-pdn-manager!\n"); - } - - system("clear"); - - get_pcie_mode(); - - signal(SIGCHLD, SIG_IGN); - - // read from config - ret = loadConfigFromIni(profileList, connectState); - if(ret == -1) - { - dbg_time("Fibocom multi-pdn-manager %s", VERSION_STRING()); - dbg_time("Fibocom manager current qmap_num is %d,not support multi-pdn", qmap_num); - dbg_time("please use \"echo 4 > /sys/class/net/usb0/qmap_num\",set driver to multi mode"); - return -1; - } - if(ret == -2) - return -2; - initShareMemory(); - signal(SIGINT, SIGINT_handle); - if (is_pcie_dial()) - { - dbg_time("start qmi proxy server"); - //system("./fibo_qmimsg_server -d /dev/mhi_QMI0 &"); - } - while (1) - { - // show tips - dbg_time("Fibocom multi-pdn-manager %s", VERSION_STRING()); - dbg_time("Fibocom manager current qmap_num is %d", qmap_num); - for (profileIndex = 0; profileIndex < qmap_num; profileIndex++) - { - dbg_time("Fibocom manager sub-instance%d %s", profileIndex + 1, - connectState[profileIndex] ? "Connected" : "Disconnected"); - } - printf("Please select an action[0-9]\n"); - printf("1.show profile setting\n"); - printf("2.set profile setting\n"); - printf("3.connect to network\n"); - printf("4.disconnect to network\n"); - printf("5.show connect log\n"); - printf("6.reload profile setting\n"); - printf("7.save profile setting\n"); - printf("8.show max instance number\n"); - printf("9.set max instance number\n"); - printf("0.exit\n"); - - // get operate - printf("input [0-9]: "); - f = malloc(sizeof(f)); - //begin modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - fgets(f,sizeof(f),stdin); - if(!IsInt(f)) - { - dbg_time("invalid input"); - printf("Press any key to continus"); - getchar(); - system("clear"); - continue; - } - //end modified by zhangkaibo limit input parameters. mantis 0048965 20200605 - opsCode = atoi(f); - free(f); - - // select operate - switch (opsCode) - { - case 1: - //begin modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - for (profileIndex = 0; profileIndex < qmap_num; profileIndex++) - { - dbg_time( - "Fibocom manager \nprofile%d apn:\"%s\" username:\"%s\" " - "password: \"%s\" auth: \"%d\" ip family: \"%d\" pin:\"%s\"", - profileIndex + 1, profileList[profileIndex].apn, - profileList[profileIndex].user, - profileList[profileIndex].password, - profileList[profileIndex].auth, - profileList[profileIndex].ipfamily, - profileList[profileIndex].pin); - } - //end modified by zhangkaibo add sim pin operate. mantis 0049142 20200612 - break; - case 2: - { - modifyProfile(profileList); - } - break; - case 3: - { - startConnectCM(profileList, connectState); - break; - } - case 4: - { - int connectIndex; - printf("disconnect visual net interface :"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - connectIndex = atoi(f); - free(f); - int *connectPids = (int *)shm; - if (connectIndex < 1 || connectIndex > qmap_num) - { - dbg_time("error visual net interface id"); - break; - } - if (connectState[connectIndex - 1] == false) - { - dbg_time("visual net interface %d now is disconnected", connectIndex); - break; - } - dbg_time("kill pid %d", connectPids[connectIndex - 1]); - kill(connectPids[connectIndex - 1], SIGINT); - connectState[connectIndex - 1] = false; - } - break; - case 5: - { - int connectIndex; - printf("show visual net interface :"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - connectIndex = atoi(f); - free(f); - if (connectIndex < 1 || connectIndex > qmap_num) - { - dbg_time("error visual net interface id"); - break; - } - char temp[MAX_PATH]; - sprintf(temp, "cat instance%d.txt", connectIndex); - system(temp); - } - break; - case 6: - { - loadConfigFromIni(profileList, connectState); - } - break; - case 7: - { - saveConfigToIni(profileList); - } - break; - case 8: - printf("qmap_num : %d", qmap_num); - break; - case 9: - { - int temp_qmap; - printf("set qmap_num :"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - temp_qmap = atoi(f); - free(f); - if (temp_qmap < 1 || temp_qmap > 8) - { - dbg_time("error qmap_num id"); - break; - } - qmap_num = temp_qmap; - } - break; - case 0: - printf("exit? [Y/N] :"); - f = malloc(sizeof(f)); - fgets(f,sizeof(f),stdin); - if (f[0] == 'y' || f[0] == 'Y') - goto __main_exit; - break; - default: - dbg_time("invalid input"); - }; - printf("Press any key to continus"); - getchar(); - system("clear"); - } -__main_exit: - { - int *connectPids = (int *)shm; - int cIndex; - for(cIndex = 1 ; cIndex <= qmap_num ; cIndex++) - { - dbg_time("kill pid %d", connectPids[cIndex - 1]); - kill(connectPids[cIndex - 1], SIGINT); - connectState[cIndex - 1] = false; - } - //system("ps -ef|grep fibo|grep -v grep|cut -c 9-15|xargs kill"); - } - destoryShareMemory(); - close(lock_file); // 不要忘记释放文件指针 - return 0; -} diff --git a/fibocom-dial/src/multi-pdn.ini b/fibocom-dial/src/multi-pdn.ini deleted file mode 100644 index 182a7ef..0000000 --- a/fibocom-dial/src/multi-pdn.ini +++ /dev/null @@ -1,67 +0,0 @@ -[Setting] -qmap_num=4 - -[profile1] -apn=1234567890 -user=qwertyuio -password=asdfghjkl -auth=2 -ipfamily=1 -pin= - -[profile2] -apn=ctnet -user= -password= -auth=0 -ipfamily=1 -pin= - -[profile3] -apn=ctnet -user= -password= -auth=0 -ipfamily=1 -pin= - -[profile4] -apn=ctnet -user= -password= -auth=0 -ipfamily=1 -pin= - -[profile5] -apn=ctnet -user= -password= -auth= -ipfamily=1 -pin= - -[profile6] -apn=ctnet -user= -password= -auth= -ipfamily=1 -pin= - -[profile7] -apn=ctnet -user= -password= -auth= -ipfamily=1 -pin= - -[profile8] -apn=ctnet -user= -password= -auth= -ipfamily=1 -pin= - diff --git a/fibocom-dial/src/qmap_bridge_mode.c b/fibocom-dial/src/qmap_bridge_mode.c deleted file mode 100644 index cabf76d..0000000 --- a/fibocom-dial/src/qmap_bridge_mode.c +++ /dev/null @@ -1,438 +0,0 @@ -#include "QMIThread.h" -//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037 -#include -//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037 - -static size_t fibo_fread(const char *filename, void *buf, size_t size) -{ - FILE *fp = fopen(filename, "r"); - size_t n = 0; - - memset(buf, 0x00, size); - - if (fp) { - n = fread(buf, 1, size, fp); - if (n <= 0 || n == size) { - dbg_time( - "warnning: fail to fread(%s), fread=%zd, buf_size=%zd, " - "errno: %d (%s)", - __func__, filename, n, size, errno, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -static size_t fibo_fwrite(const char *filename, const void *buf, size_t size) -{ - FILE *fp = fopen(filename, "w"); - size_t n = 0; - - if (fp) { - n = fwrite(buf, 1, size, fp); - if (n != size) { - dbg_time( - "warnning: fail to fwrite(%s), fwrite=%zd, buf_size=%zd, " - "errno: %d (%s)", - __func__, filename, n, size, errno, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -static int fibo_iface_is_in_bridge(const char *iface) -{ - char filename[256]; - - snprintf(filename, sizeof(filename), "/sys/class/net/%s/brport", iface); - return (access(filename, F_OK) == 0 || errno != ENOENT); -} - -int fibo_bridge_mode_detect(PROFILE_T *profile) -{ - const char *ifname = profile->qmapnet_adapter ? profile->qmapnet_adapter - : profile->usbnet_adapter; - const char *driver; - char bridge_mode[128]; - char bridge_ipv4[128]; - char ipv4[128]; - char buf[64]; - size_t n; - int in_bridge; - - driver = profile->driver_name; - snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode", - ifname); - snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4", - ifname); - - if (access(bridge_mode, F_OK) && errno == ENOENT) { - snprintf(bridge_mode, sizeof(bridge_mode), - "/sys/module/%s/parameters/bridge_mode", driver); - snprintf(bridge_ipv4, sizeof(bridge_ipv4), - "/sys/module/%s/parameters/bridge_ipv4", driver); - - if (access(bridge_mode, F_OK) && errno == ENOENT) { - bridge_mode[0] = '\0'; - } - } - - in_bridge = fibo_iface_is_in_bridge(ifname); - if (in_bridge) { - dbg_time("notice: iface %s had add to bridge\n", ifname); - } - - if (in_bridge && bridge_mode[0] == '\0') { - dbg_time("warnning: can not find bride_mode file for %s\n", ifname); - return 1; - } - - n = fibo_fread(bridge_mode, buf, sizeof(buf)); - - if (in_bridge) { - if (n <= 0 || buf[0] == '0') { - dbg_time("warnning: should set 1 to bride_mode file for %s\n", - ifname); - return 1; - } - } else { - if (n <= 0 || buf[0] == '0') { - return 0; - } - } - - memset(ipv4, 0, sizeof(ipv4)); - - if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 || - profile->qmap_mode == 1) { - snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address); - dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); - fibo_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); - } else { - snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address, - profile->muxid); - dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); - fibo_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); - } - - return 1; -} -//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037 -void fibo_get_driver_info(PROFILE_T *profile, RMNET_INFO *rmnet_info) { - int ifc_ctl_sock; - struct ifreq ifr; - int rc; - int request = 0x89F3; - unsigned char data[512]; - - memset(rmnet_info, 0x00, sizeof(*rmnet_info)); - - ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ifc_ctl_sock <= 0) { - dbg_time("socket() failed: %s\n", strerror(errno)); - return; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ - 1] = 0; - ifr.ifr_ifru.ifru_data = (void *)data; - rc = ioctl(ifc_ctl_sock, request, &ifr); - if (rc < 0) { - dbg_time("ioctl(0x%x, qmap_settings) failed: %s, rc=%d", request, strerror(errno), rc); - } - else { - memcpy(rmnet_info, data, sizeof(*rmnet_info)); - } - - close(ifc_ctl_sock); -} -//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037 -int fibo_qmap_mode_detect(PROFILE_T *profile) -{ - int n; - char buf[128]; - char qmap_netcard[128]; - struct { - char filename[255 * 2]; - char linkname[255 * 2]; - } * pl; - - pl = (typeof(pl))malloc(sizeof(*pl)); - - snprintf(pl->linkname, sizeof(pl->linkname), - "/sys/class/net/%s/device/driver", profile->usbnet_adapter); - n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); - pl->filename[n] = '\0'; - while (pl->filename[n] != '/') n--; - profile->driver_name = strdup(&pl->filename[n + 1]); - -//2021-03-15 zhangkaibo@fibocom.com changed begin for oa 20210311037 - fibo_get_driver_info(profile, &profile->rmnet_info); - if (profile->rmnet_info.size) { - profile->qmap_mode = profile->rmnet_info.qmap_mode; - if (profile->qmap_mode) { - int offset_id = profile->pdp - 1; - - if (profile->qmap_mode == 1) - offset_id = 0; - profile->muxid = profile->rmnet_info.mux_id[offset_id]; - profile->qmapnet_adapter = strdup( profile->rmnet_info.ifname[offset_id]); - profile->qmap_size = profile->rmnet_info.rx_urb_size; - profile->qmap_version = profile->rmnet_info.qmap_version; - } - - goto _out; - } -//2021-03-15 zhangkaibo@fibocom.com changed end for oa 20210311037 - - if (qmidev_is_pciemhi(profile->qmichannel)) { - profile->qmap_mode = 1; - - if (profile->muxid == 0 || profile->muxid == 0x81) - { - profile->muxid = 0x81; - } - else - { - if (profile->muxid < 0x80) - profile->muxid += 0x81; - profile->qmap_mode = 2; - } - - profile->qmapnet_adapter = strdup(profile->usbnet_adapter); - goto _final_process; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_num", - profile->usbnet_adapter); - -//2021-01-27 willa.liu@fibocom.com changed begin for support mantis 0068849 - if (access(pl->filename, F_OK) == 0) { - dbg_time("access %s", pl->filename); - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, - strerror(errno)); - goto _out; - } -//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837 -/* - snprintf(pl->filename, sizeof(pl->filename), - "/sys/module/%s/parameters/qmap_num", profile->driver_name); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, - errno, strerror(errno)); - goto _out; - } - - snprintf( - pl->filename, sizeof(pl->filename), - "/sys/class/net/%s/device/driver/module/parameters/qmap_num", - profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, - errno, strerror(errno)); - goto _out; - } - } - } -*/ -//2021-02-01 willa.liu@fibocom.com changed end for support mantis 0069837 - } - else - { - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode", - profile->usbnet_adapter); - - if (access(pl->filename, F_OK) == 0) { - dbg_time("access %s", pl->filename); - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, - strerror(errno)); - goto _out; - } - } - } - - if(!access(pl->filename, R_OK)) - { - n = fibo_fread(pl->filename, buf, sizeof(buf)); - if(n > 0) - { - profile->qmap_mode = atoi(buf); - if(profile->qmap_mode >= 1 && qmidev_is_pciemhi(profile->qmichannel)) - { - profile->muxid = - profile->pdp + 0x80; - sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp); - profile->qmapnet_adapter = strdup(qmap_netcard); - } - if(qmidev_is_gobinet(profile->qmichannel) || qmidev_is_qmiwwan(profile->qmichannel)) - { - if(profile->qmap_mode > 1) - { - profile->muxid = - profile->pdp + 0x80; - sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp); - profile->qmapnet_adapter = strdup(qmap_netcard); - } - if(profile->qmap_mode == 1) - { - profile->muxid = 0x81; - profile->qmapnet_adapter = strdup(profile->usbnet_adapter); - } - } - } - - - if (0) { - profile->qmap_mode = atoi(buf); - - if (profile->qmap_mode > 1 && qmidev_is_gobinet(profile->qmichannel)) { - profile->muxid = - profile->pdp + 0x80; // muxis is 0x8X for PDN-X - sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp); - profile->qmapnet_adapter = strdup(qmap_netcard); - } - if (profile->qmap_mode >= 1 && !qmidev_is_gobinet(profile->qmichannel)) { - profile->muxid = - profile->pdp + 0x80; // muxis is 0x8X for PDN-X - sprintf(qmap_netcard, "%s.%d", profile->usbnet_adapter,profile->pdp); - profile->qmapnet_adapter = strdup(qmap_netcard); - } - if (profile->qmap_mode == 1 && qmidev_is_gobinet(profile->qmichannel)) { - profile->muxid = 0x81; - profile->qmapnet_adapter = strdup(profile->usbnet_adapter); -//2021-01-27 willa.liu@fibocom.com changed end for support mantis 0068849 - - } - } - } else if (qmidev_is_qmiwwan(profile->qmichannel)) { - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d", - profile->pdp - 1); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, - errno, strerror(errno)); - } - goto _out; - } - - // upstream Kernel Style QMAP qmi_wwan.c - snprintf(pl->filename, sizeof(pl->filename), - "/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); - n = fibo_fread(pl->filename, buf, sizeof(buf)); - if (n >= 5) { - profile->qmap_mode = n / 5; // 0x81\n0x82\n0x83\n - if (profile->qmap_mode > 1) { - // PDN-X map to qmimux-X - profile->muxid = (buf[5 * (profile->pdp - 1) + 2] - '0') * 16 + - (buf[5 * (profile->pdp - 1) + 3] - '0'); - sprintf(qmap_netcard, "qmimux%d", profile->pdp - 1); - profile->qmapnet_adapter = strdup(qmap_netcard); - } else if (profile->qmap_mode == 1) { - profile->muxid = - (buf[5 * 0 + 2] - '0') * 16 + (buf[5 * 0 + 3] - '0'); - sprintf(qmap_netcard, "qmimux%d", 0); - profile->qmapnet_adapter = strdup(qmap_netcard); - } - } - } - -_out: - if (profile->qmap_mode) { - profile->qmap_size = 16 * 1024; - snprintf(pl->filename, sizeof(pl->filename), - "/sys/class/net/%s/qmap_size", profile->usbnet_adapter); - if (!access(pl->filename, R_OK)) { - size_t n; - char buf[32]; - n = fibo_fread(pl->filename, buf, sizeof(buf)); - if (n > 0) { - profile->qmap_size = atoi(buf); - } - } - } - -_final_process: - if (profile->qmap_mode) - dbg_time("qmap_mode = %d, muxid = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); - - free(pl); - - return 0; -} - -int fibo_qmap_mode_set(PROFILE_T *profile) -{ - int n; - char buf[128]; - struct { - char filename[255 * 2]; - char linkname[255 * 2]; - } * pl; - - if (qmidev_is_pciemhi(profile->qmichannel)) - { - dbg_time("pcie mode exit fibo_qmap_mode_set "); - return 0; - } - - pl = (typeof(pl))malloc(sizeof(*pl)); - - snprintf(pl->linkname, sizeof(pl->linkname), - "/sys/class/net/%s/device/driver", profile->usbnet_adapter); - n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); - pl->filename[n] = '\0'; - while (pl->filename[n] != '/') n--; - profile->driver_name = strdup(&pl->filename[n + 1]); - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_num", - profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, - strerror(errno)); - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), - "/sys/module/%s/parameters/qmap_mnum", profile->driver_name); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, - errno, strerror(errno)); - goto _out; - } - - snprintf( - pl->filename, sizeof(pl->filename), - "/sys/class/net/%s/device/driver/module/parameters/qmap_num", - profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, - errno, strerror(errno)); - goto _out; - } - } - } - } - - if (!access(pl->filename, R_OK)) { - snprintf(buf, sizeof(buf), "%d", profile->pdpnum); - n = fibo_fwrite(pl->filename, buf, strlen(buf)); - } - -_out: - - free(pl); - - return 0; -} diff --git a/fibocom-dial/src/query_pcie_mode.c b/fibocom-dial/src/query_pcie_mode.c deleted file mode 100644 index de3451d..0000000 --- a/fibocom-dial/src/query_pcie_mode.c +++ /dev/null @@ -1,160 +0,0 @@ -//2021-03-24 willa.liu@fibocom.com changed begin for support mantis 0071817 -#include "QMIThread.h" -#include "query_pcie_mode.h" -int speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300,// - B38400, B19200, B9600, B4800, B2400, B1200, B300, - }; -int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300, - 38400, 19200, 9600, 4800, 2400, 1200, 300, - }; - -int get_pcie_mode_debug = 0; - -//2021-02-24 willa.liu@fibocom.com changed begin for support eipd SN-20210129001 -int get_private_gateway_debug = 1; -//2021-02-24 willa.liu@fibocom.com changed end for support eipd SN-20210129001 - -//static int xset1(int fd, struct termios *tio, const char *device) -int xset1(int fd, struct termios *tio, const char *device) -{ - int ret = tcsetattr(fd, TCSAFLUSH, tio); - - if (ret) { - printf("can't tcsetattr for %s", device); - } - return ret; -} - -// set raw tty mode -//static void xget1(int fd, struct termios *t, struct termios *oldt) -void xget1(int fd, struct termios *t, struct termios *oldt) -{ - tcgetattr(fd, oldt); - *t = *oldt; - cfmakeraw(t); -// t->c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN); -// t->c_iflag &= ~(BRKINT|IXON|ICRNL); -// t->c_oflag &= ~(ONLCR); -// t->c_cc[VMIN] = 1; -// t->c_cc[VTIME] = 0; -} - -//static int get_pcie_mode() -int get_pcie_mode() -//2021-03-24 willa.liu@fibocom.com changed end for support mantis 0071817 -{ - int i; - int fd; - int ret; - char buffer[409600] = {0}; - int rate; - char* sendbuffer; - int totallen = 0; - fd_set readfds; - struct timeval timeout; - struct termios tio0, tiosfd, tio; - - int timeoutVal = 5; - - char *dev = "/dev/ttyUSB1"; //The port under Linux is operated by opening the device file - rate = 115200; - sendbuffer = "at+gtpcie=3"; - printf ( "dev: %s\nrate:%d\nsendbuffer:%s\n", dev,rate,sendbuffer); - - fd = open(dev, O_RDWR | O_NOCTTY | O_NONBLOCK); - if (fd < 0) - goto ERR; - fcntl(fd, F_SETFL, O_RDWR); - - // put device to "raw mode" - xget1(fd, &tio, &tiosfd); - // set device speed - for ( i = 0;i < sizeof ( speed_arr ) / sizeof ( int );i++ ) - { - if ( rate == name_arr[i] ) //Judge if the pass is equal to the pass - { - break; - } - } - - if(i >= sizeof ( speed_arr ) / sizeof ( int )) - { - printf("bound rate set failed\n"); - goto ERR; - } - - cfsetspeed(&tio, speed_arr[i]); - if (xset1(fd, &tio, dev)) - goto ERR; - - tcflush ( fd, TCIOFLUSH ); - - sprintf(buffer, "%s\r", sendbuffer); - ret = write ( fd, buffer, strlen(buffer) ); - if(ret < 0) - { - printf ( "write failed\n" ); - goto ERR; - } - if(get_pcie_mode_debug)printf("write %d\n", ret); - - FD_ZERO ( &readfds ); - FD_SET ( fd, &readfds ); - - while(1) - { - timeout.tv_sec = timeoutVal; - timeout.tv_usec = 0; - - ret = select ( fd+1, &readfds, ( fd_set * ) 0, ( fd_set * ) 0, &timeout ); - if(ret > 0) - { - ret = read ( fd, buffer+totallen, sizeof(buffer)-totallen-1 ); - if(ret < 0) - { - printf ( "read failed\n" ); - goto ERR; - } - - if(ret == 0) - { - goto ERR; - } - - totallen += ret; - buffer[totallen] = '\0'; - if(get_pcie_mode_debug)printf("read %d(%s)\n", ret, &buffer[totallen-ret]); - if(totallen == sizeof(buffer)-1) - break; - - if(strstr(buffer,"\nOK") || strstr(buffer,"\nERROR") - || strstr(buffer,"\n+CME ERROR:") || strstr(buffer,"\n+CMS ERROR:")) - { - if(get_pcie_mode_debug)printf("match OK/ERROR"); - if(get_pcie_mode_debug)printf("%s", buffer); - break; - } - - } - else - { - printf ( "select timeout\n" ); - goto ERR; - } - - } - - tcsetattr(fd, TCSAFLUSH, &tiosfd); - //printf("buffer:\n %s\n", buffer); - printf("%s\n", buffer); - if(strstr(buffer,"\nERROR") || strstr(buffer,"\n+CME ERROR:") || strstr(buffer,"\n+CMS ERROR:")) - goto ERR; - - close ( fd ); - return 0; - ERR: - if(fd > 0) - close(fd); - return -1; -} - diff --git a/fibocom-dial/src/query_pcie_mode.h b/fibocom-dial/src/query_pcie_mode.h deleted file mode 100644 index c6e9b9d..0000000 --- a/fibocom-dial/src/query_pcie_mode.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __QUERY_PCIE_MODE__ -#define __QUERY_PCIE_MODE__ - -extern int speed_arr[14]; -extern int name_arr[14]; - -extern int get_pcie_mode_debug; - -extern int get_private_gateway_debug; - -extern int xset1(int fd, struct termios *tio, const char *device); - -// set raw tty mode -extern void xget1(int fd, struct termios *t, struct termios *oldt); -extern int get_pcie_mode(); - -#endif diff --git a/fibocom-dial/src/udhcpc.c b/fibocom-dial/src/udhcpc.c deleted file mode 100644 index 966614b..0000000 --- a/fibocom-dial/src/udhcpc.c +++ /dev/null @@ -1,289 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "QMIThread.h" -#include "util.h" - -static int dibbler_client_alive = 0; - -static int fibo_system(const char *shell_cmd) -{ - int ret = 0; - dbg_time("%s", shell_cmd); - ret = system(shell_cmd); - if (ret) { - // dbg_time("Fail to system(\"%s\") = %d, errno: %d (%s)", shell_cmd, - // ret, errno, strerror(errno)); - } - return ret; -} - -static void fibo_set_mtu(const char *ifname, int ifru_mtu) -{ - int inet_sock; - struct ifreq ifr; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (inet_sock > 0) { - strcpy(ifr.ifr_name, ifname); - - if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) { - if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) { - dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu, - ifru_mtu); - ifr.ifr_ifru.ifru_mtu = ifru_mtu; - ioctl(inet_sock, SIOCSIFMTU, &ifr); - } - } - - close(inet_sock); - } -} - -static void *udhcpc_thread_function(void *arg) -{ - FILE *udhcpc_fp; - char *udhcpc_cmd = (char *)arg; - - if (udhcpc_cmd == NULL) - return NULL; - - dbg_time("%s", udhcpc_cmd); - udhcpc_fp = popen(udhcpc_cmd, "r"); - free(udhcpc_cmd); - if (udhcpc_fp) { - char buf[0xff]; - - buf[sizeof(buf) - 1] = '\0'; - while ((fgets(buf, sizeof(buf) - 1, udhcpc_fp)) != NULL) { - if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n')) - buf[strlen(buf) - 1] = '\0'; - dbg_time("%s", buf); - } - - pclose(udhcpc_fp); - } - - return NULL; -} - -void fibo_set_driver_link_state(PROFILE_T *profile, int link_state) -{ - char link_file[128]; - int fd; - int new_state = 0; - dbg_time("enter %s ", __func__); - - snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", - profile->usbnet_adapter); - fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) { - if (errno != ENOENT) - dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, - strerror(errno)); - return; - } - - if (profile->qmap_mode <= 1) - new_state = !!link_state; - else { - // 0x80 means link off this pdp - new_state = (link_state ? 0x00 : 0x80) + profile->pdp; - } - - snprintf(link_file, sizeof(link_file), "%d\n", new_state); - write(fd, link_file, sizeof(link_file)); - - if (link_state == 0 && profile->qmap_mode > 1) { - size_t rc; - - lseek(fd, 0, SEEK_SET); - rc = read(fd, link_file, sizeof(link_file)); - if (rc > 1 && (!strcasecmp(link_file, "0\n") || - !strcasecmp(link_file, "0x0\n"))) { - // snprintf(link_file, sizeof(link_file), "busybox ifconfig %s down", - // profile->usbnet_adapter); - // fibo_system(link_file); - } - } - - close(fd); -} - -int fibo_raw_ip_mode_check(const char *ifname) -{ - int fd; - char raw_ip[128]; - char shell_cmd[128]; - char mode[2] = "X"; - int mode_change = 0; - - snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); - if (access(raw_ip, F_OK)) - return 0; - - fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd < 0) { - dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, - raw_ip, errno, strerror(errno)); - return 0; - } - - read(fd, mode, 2); - if (mode[0] == '0' || mode[0] == 'N') { - snprintf(shell_cmd, sizeof(shell_cmd), "busybox ifconfig %s down", ifname); - fibo_system(shell_cmd); - dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); - mode[0] = 'Y'; - write(fd, mode, 2); - mode_change = 1; - snprintf(shell_cmd, sizeof(shell_cmd), "busybox ifconfig %s up", ifname); - fibo_system(shell_cmd); - } - - close(fd); - return mode_change; -} - -void udhcpc_start(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - char shell_cmd[128]; - - fibo_set_driver_link_state(profile, 1); - if (profile->qmapnet_adapter) { - ifname = profile->qmapnet_adapter; - } - dbg_time("1 %s", profile->qmichannel); - if (qmidev_is_qmiwwan(profile->qmichannel)) { - dbg_time("2 %s", ifname); - fibo_raw_ip_mode_check(ifname); - } - - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) { - fibo_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - fibo_system("echo 1 > /sys/module/fibo_mhi/parameters/macaddr_check"); - -//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605 -// if (strcmp(ifname, profile->usbnet_adapter)) { -// snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s up", -// profile->usbnet_adapter); -// fibo_system(shell_cmd); -// } -//begin modified by zhangkaibo fix ipv6 dial process flow. mantis 0048789 20200605 - // For IPv6, down & up will send protocol packets, and that's needed. - if (profile->ipv6_flag) { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", ifname); - fibo_system(shell_cmd); - } - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s up", ifname); - fibo_system(shell_cmd); - - //begin modified by zhangming Added NOARP and Multilcast on flag bit commands. mantis 0050106 20200713 - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s arp off multicast on", ifname); - fibo_system(shell_cmd); - //begin modified by zhangming Added NOARP and Multilcast on flag bit commands. mantis 0050106 20200713 - //Modified unicom dual stack dialing unsuccessful problem - - // for bridge mode, only one public IP, so do udhcpc manually - if (fibo_bridge_mode_detect(profile)) { - return; - } - - /* Do DHCP using busybox tools */ - { - char udhcpc_cmd[128]; - pthread_attr_t udhcpc_thread_attr; - pthread_t udhcpc_thread_id; - - pthread_attr_init(&udhcpc_thread_attr); - pthread_attr_setdetachstate(&udhcpc_thread_attr, - PTHREAD_CREATE_DETACHED); - - if (profile->ipv4.Address) { - if (access("/usr/share/udhcpc/default.script", X_OK)) { - dbg_time( - "Fail to access /usr/share/udhcpc/default.script, " - "errno: %d (%s)", - errno, strerror(errno)); - } - - //-f,--foreground Run in foreground - //-b,--background Background if lease is not obtained - //-n,--now Exit if lease is not obtained - //-q,--quit Exit after obtaining lease - //-t,--retries N Send up to N discover packets (default 3) - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), - "busybox udhcpc -f -n -q -t 5 -i %s", ifname); - - if (!access("/lib/netifd/dhcp.script", X_OK) && - !access("/sbin/ifup", X_OK) && - !access("/sbin/ifstatus", X_OK)) { - dbg_time("you are use OpenWrt?"); - dbg_time("should not calling udhcpc manually?"); - dbg_time("should modify /etc/config/network as below?"); - dbg_time("config interface wan"); - dbg_time("\toption ifname %s", ifname); - dbg_time("\toption proto dhcp"); - dbg_time( - "should use \"/sbin/ifstaus wan\" to check %s 's status?", - ifname); - } - - pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, - (void *)strdup(udhcpc_cmd)); - sleep(1); - } - - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { - // module do not support DHCPv6, only support 'Router Solicit' - // and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, - // Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) { - char forward_state[2]; - read(forward_fd, forward_state, 2); - if (forward_state[0] == '1') { - dbg_time( - "%s enabled, kernel maybe donot send 'Router Solicit'", - forward_file); - } - close(forward_fd); - } - } - } -} - -void udhcpc_stop(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - char shell_cmd[128]; - char reset_ip[128]; - dbg_time("enter %s ", __func__); - - if (profile->qmapnet_adapter) { - ifname = profile->qmapnet_adapter; - } - - if (dibbler_client_alive) { - system("killall dibbler-client"); - dibbler_client_alive = 0; - } - //snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", - // profile->usbnet_adapter); - //fibo_system(shell_cmd); - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "busybox ifconfig %s down", ifname); - fibo_system(shell_cmd); - snprintf(reset_ip, sizeof(reset_ip) - 1, "busybox ifconfig %s 0.0.0.0", ifname); - fibo_system(reset_ip); -} diff --git a/fibocom-dial/src/udhcpc_netlink.c b/fibocom-dial/src/udhcpc_netlink.c deleted file mode 100644 index fddf166..0000000 --- a/fibocom-dial/src/udhcpc_netlink.c +++ /dev/null @@ -1,421 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmnl/ifutils.h" -#include "libmnl/dhcp/dhcp.h" -#include "util.h" -#include "QMIThread.h" - -static int fibo_system(const char *shell_cmd) -{ - int ret = 0; - dbg_time("%s", shell_cmd); - ret = system(shell_cmd); - if (ret) { - // dbg_time("Fail to system(\"%s\") = %d, errno: %d (%s)", shell_cmd, - // ret, errno, strerror(errno)); - } - return ret; -} - -int fibo_raw_ip_mode_check(const char *ifname) -{ - int fd; - char raw_ip[128]; - char mode[2] = "X"; - int mode_change = 0; - - snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); - if (access(raw_ip, F_OK)) - return 0; - - fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd < 0) - { - dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); - return 0; - } - - read(fd, mode, 2); - if (mode[0] == '0' || mode[0] == 'N') - { - if_link_down(ifname); - dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); - mode[0] = 'Y'; - write(fd, mode, 2); - mode_change = 1; - if_link_up(ifname); - } - - close(fd); - return mode_change; -} - -static void fibo_set_driver_link_state(PROFILE_T *profile, int link_state) -{ - char link_file[128]; - int fd; - int new_state = 0; - dbg_time("enter %s ", __func__); - - snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); - fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) - { - if (errno != ENOENT) - dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); - return; - } - - if (profile->qmap_mode <= 1) - new_state = !!link_state; - else - { - //0x80 means link off this pdp - new_state = (link_state ? 0x00 : 0x80) + profile->pdp; - } - - snprintf(link_file, sizeof(link_file), "%d\n", new_state); - write(fd, link_file, sizeof(link_file)); - - if (link_state == 0 && profile->qmap_mode > 1) - { - size_t rc; - - lseek(fd, 0, SEEK_SET); - rc = read(fd, link_file, sizeof(link_file)); - if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n"))) - { - // if_link_down(profile->usbnet_adapter); - } - } - - close(fd); -} - -void udhcpc_start(PROFILE_T *profile) -{ -//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837 - char *ifname = profile->usbnet_adapter; - char shell_cmd[512]; - - fibo_set_driver_link_state(profile, 1); - fibo_raw_ip_mode_check(ifname); - - if (profile->qmapnet_adapter) - { - ifname = profile->qmapnet_adapter; - } - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) - { - if_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - if (strcmp(ifname, profile->usbnet_adapter)) - { - //if_link_up(profile->usbnet_adapter); - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", profile->usbnet_adapter); - fibo_system(shell_cmd); - } -//2021-02-01 willa.liu@fibocom.com changed begin for support mantis 0069837 - if_link_up(ifname); - -#if 1 //for bridge mode, only one public IP, so do udhcpc manually - if (fibo_bridge_mode_detect(profile)) - { - return; - } -#endif - // if use DHCP(should make with ${DHCP} src files) - // do_dhcp(ifname); - // return 0; - /* IPv4 Addr Info */ - if (profile->ipv4.Address) - { - dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu); - dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address))); - dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask))); - dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway))); - dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary))); - dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary))); - if_set_network_v4(ifname, ntohl(profile->ipv4.Address), - mask_to_prefix_v4(profile->ipv4.SubnetMask), - ntohl(profile->ipv4.Gateway), - ntohl(profile->ipv4.DnsPrimary), - ntohl(profile->ipv4.DnsSecondary)); - } - else - { - dbg_time("The IPv4 Address in profile is NULL"); - } - - if (profile->ipv6.Address && (profile->ipv6.PrefixLengthIPAddr != 0)) - { - //module do not support DHCPv6, only support 'Router Solicit' - //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) - { - char forward_state[2]; - read(forward_fd, forward_state, 2); - if (forward_state[0] == '1') - { - dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); - } - close(forward_fd); - } - - dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu); - dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address)); - dbg_time("IPv6 PrefixLengthIPAddr: %d", profile->ipv6.PrefixLengthIPAddr); - dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway)); - dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary)); - dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary)); - if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr, - profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary); - } - else - { - dbg_time("The IPv6 Address in profile is NULL"); - } -} - -void udhcpc_stop(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - dbg_time("enter %s ", __func__); - - fibo_set_driver_link_state(profile, 0); - - if (profile->qmapnet_adapter) - { - ifname = profile->qmapnet_adapter; - } - - if_flush_v4_addr(ifname); - if_flush_v6_addr(ifname); - if_link_down(ifname); -} - -static void fibo_set_mtu(const char *ifname, int ifru_mtu) { - int inet_sock; - struct ifreq ifr; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (inet_sock > 0) { - strcpy(ifr.ifr_name, ifname); - - if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) { - if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) { - dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu); - ifr.ifr_ifru.ifru_mtu = ifru_mtu; - ioctl(inet_sock, SIOCSIFMTU, &ifr); - } - } - - close(inet_sock); - } -} - -static void* udhcpc_thread_function(void* arg) { - FILE * udhcpc_fp; - char *udhcpc_cmd = (char *)arg; - - if (udhcpc_cmd == NULL) - return NULL; - - dbg_time("%s", udhcpc_cmd); - udhcpc_fp = popen(udhcpc_cmd, "r"); - free(udhcpc_cmd); - if (udhcpc_fp) { - char buf[0xff]; - - buf[sizeof(buf)-1] = '\0'; - while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) { - if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n')) - buf[strlen(buf) - 1] = '\0'; - dbg_time("%s", buf); - } - - pclose(udhcpc_fp); - } - - return NULL; -} - -void udhcpc_start_pcie(PROFILE_T *profile) { - char *ifname = profile->usbnet_adapter; - char sub_intf_name[100] = {0}; - int intf_id = 0; - char shell_cmd[512]; - dbg_time("enter %s ", __func__); - - if (profile->qmapnet_adapter) { - ifname = profile->qmapnet_adapter; - } - - if (profile->muxid > 0x81) - { - intf_id = profile->muxid - 0x81; - snprintf(sub_intf_name, sizeof(sub_intf_name) - 1, "%s.%d", ifname, intf_id); - } - - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) { - fibo_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - fibo_system("echo 1 > /sys/module/fibo_mhi/parameters/macaddr_check"); - - if (strcmp(ifname, profile->usbnet_adapter)) { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", profile->usbnet_adapter); - fibo_system(shell_cmd); - } - - // For IPv6, down & up will send protocol packets, and that's needed. - if (profile->ipv6_flag && profile->muxid <= 0x81) { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s down", ifname); - fibo_system(shell_cmd); - } - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s up", ifname); - fibo_system(shell_cmd); - - //for bridge mode, only one public IP, so do udhcpc manually - if (fibo_bridge_mode_detect(profile)) { - return; - } - -/* Do DHCP using busybox tools */ - { - char udhcpc_cmd[128]; - pthread_attr_t udhcpc_thread_attr; - pthread_t udhcpc_thread_id; - - pthread_attr_init(&udhcpc_thread_attr); - pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED); - - if (profile->ipv4.Address) - { - char v4add_str[32] = {0}; - char v4gw_str[32] = {0}; - char v4_netmask_str[32] = {0}; - uint32_t Address = ntohl(profile->ipv4.Address); - uint32_t Gateway = ntohl(profile->ipv4.Gateway); - uint32_t SubnetMask = ntohl(profile->ipv4.SubnetMask); - inet_ntop(AF_INET, &Address, v4add_str, sizeof(v4add_str)); - inet_ntop(AF_INET, &Gateway, v4gw_str, sizeof(v4gw_str)); - inet_ntop(AF_INET, &SubnetMask, v4_netmask_str, sizeof(v4_netmask_str)); - - if (profile->muxid == 0x81) - { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s %s netmask %s", ifname, v4add_str, v4_netmask_str); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route add default gw %s dev %s", v4gw_str, ifname); - fibo_system(shell_cmd); - } - else if (profile->muxid > 0x81) - { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link add link %s name %s type vlan id %d", ifname, sub_intf_name, intf_id); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", ifname); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", sub_intf_name); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s %s netmask %s", sub_intf_name, v4add_str, v4_netmask_str); - fibo_system(shell_cmd); - } - } - - if (profile->ipv6.PrefixLengthIPAddr) - { - //module do not support DHCPv6, only support 'Router Solicit' - //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) { - char forward_state[2]; - read(forward_fd, forward_state, 2); - if (forward_state[0] == '1') { - dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); - } - close(forward_fd); - } - - { - char v6add_str[100] = {0}; - char v6gw_str[100] = {0}; - inet_ntop(AF_INET6, profile->ipv6.Address, v6add_str, sizeof(v6add_str)); - inet_ntop(AF_INET6, profile->ipv6.Gateway, v6gw_str, sizeof(v6gw_str)); - - if (profile->muxid == 0x81) - { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s add %s/%d", ifname, v6add_str, profile->ipv6.PrefixLengthIPAddr); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route -A inet6 add ::/0 gw %s dev %s", v6gw_str, ifname); - fibo_system(shell_cmd); - } - else if (profile->muxid > 0x81) - { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link add link %s name %s type vlan id %d", ifname, sub_intf_name, intf_id); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", ifname); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link set %s up", sub_intf_name); - fibo_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s add %s/%d", sub_intf_name, v6add_str, profile->ipv6.PrefixLengthIPAddr); - fibo_system(shell_cmd); - /* start 2021-01-21 add by haopengfei to fix mantis 69056 */ - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "route -A inet6 add ::/0 gw %s dev %s", v6gw_str, sub_intf_name); - fibo_system(shell_cmd); - /* end 2021-01-21 add by haopengfei to fix mantis 69056 */ - } - } - - } - } -} - -void udhcpc_stop_pcie(PROFILE_T *profile) { - char *ifname = profile->usbnet_adapter; - char shell_cmd[128]; - char reset_ip[128]; - dbg_time("enter %s ", __func__); - - if (profile->qmapnet_adapter) { - ifname = profile->qmapnet_adapter; - } - - if (profile->muxid == 0x81) - { - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ifconfig %s down", ifname); - fibo_system(shell_cmd); - snprintf(reset_ip, sizeof(reset_ip) - 1, "ifconfig %s 0.0.0.0", ifname); - fibo_system(reset_ip); - } - else if (profile->muxid > 0x81) - { - char sub_intf_name[100]; - int intf_id = profile->muxid - 0x81; - snprintf(sub_intf_name, sizeof(sub_intf_name) - 1, "%s.%d", ifname, intf_id); - - snprintf(shell_cmd, sizeof(shell_cmd) - 1, "ip link del link dev %s", sub_intf_name); - fibo_system(shell_cmd); - } -} - diff --git a/fibocom-dial/src/util.c b/fibocom-dial/src/util.c deleted file mode 100644 index f2a2228..0000000 --- a/fibocom-dial/src/util.c +++ /dev/null @@ -1,142 +0,0 @@ -#include - -#include "QMIThread.h" - -#if defined(__STDC__) -#include -#define __V(x) x -#else -#include -#define __V(x) (va_alist) va_dcl -#define const -#define volatile -#endif - -#include - -#define is_bigendian() ((*(char *)&i) == 0) -FILE *logfilefp = NULL; -static pthread_mutex_t printfMutex = PTHREAD_MUTEX_INITIALIZER; -static char line[1024]; -const int i = 1; - -// defined in atchannel.c -static void setTimespecRelative(struct timespec *p_ts, long long msec) -{ - struct timeval tv; - - gettimeofday(&tv, (struct timezone *)NULL); - - /* what's really funny about this is that I know - pthread_cond_timedwait just turns around and makes this - a relative time again */ - p_ts->tv_sec = tv.tv_sec + (msec / 1000); - p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L) * 1000L; -} - -int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t *mutex, - unsigned msecs) -{ - if (msecs != 0) { - struct timespec ts; - setTimespecRelative(&ts, msecs); - return pthread_cond_timedwait(cond, mutex, &ts); - } else { - return pthread_cond_wait(cond, mutex); - } -} - -static const char *get_time(void) -{ - static char time_buf[50]; - struct timeval tv; - time_t time; - suseconds_t millitm; - struct tm *ti; - - gettimeofday(&tv, NULL); - - time = tv.tv_sec; - millitm = (tv.tv_usec + 500) / 1000; - - if (millitm == 1000) { - ++time; - millitm = 0; - } - - ti = localtime(&time); - sprintf(time_buf, "[%02d-%02d_%02d:%02d:%02d:%03d]", ti->tm_mon + 1, - ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); - return time_buf; -} - -void dbg_time(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - - pthread_mutex_lock(&printfMutex); - - snprintf(line, sizeof(line), "%s ", get_time()); - - vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, args); - fprintf(stdout, "%s\n", line); - - if (logfilefp) { - fprintf(logfilefp, "%s\n", line); - } - fflush(logfilefp); - pthread_mutex_unlock(&printfMutex); -} - -USHORT le16_to_cpu(USHORT v16) -{ - USHORT tmp = v16; - if (is_bigendian()) { - unsigned char *s = (unsigned char *)(&v16); - unsigned char *d = (unsigned char *)(&tmp); - d[0] = s[1]; - d[1] = s[0]; - } - return tmp; -} - -UINT le32_to_cpu(UINT v32) -{ - UINT tmp = v32; - if (is_bigendian()) { - unsigned char *s = (unsigned char *)(&v32); - unsigned char *d = (unsigned char *)(&tmp); - d[0] = s[3]; - d[1] = s[2]; - d[2] = s[1]; - d[3] = s[0]; - } - return tmp; -} - -USHORT cpu_to_le16(USHORT v16) -{ - USHORT tmp = v16; - if (is_bigendian()) { - unsigned char *s = (unsigned char *)(&v16); - unsigned char *d = (unsigned char *)(&tmp); - d[0] = s[1]; - d[1] = s[0]; - } - return tmp; -} - -UINT cpu_to_le32(UINT v32) -{ - UINT tmp = v32; - if (is_bigendian()) { - unsigned char *s = (unsigned char *)(&v32); - unsigned char *d = (unsigned char *)(&tmp); - d[0] = s[3]; - d[1] = s[2]; - d[2] = s[1]; - d[3] = s[0]; - } - return tmp; -} diff --git a/fibocom-dial/src/util.h b/fibocom-dial/src/util.h deleted file mode 100644 index 0a0ec48..0000000 --- a/fibocom-dial/src/util.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * 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. - */ - -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include - -struct listnode { - struct listnode *next; - struct listnode *prev; -}; - -#define node_to_item(node, container, member) \ - (container *)(((char *)(node)) - offsetof(container, member)) - -#define list_declare(name) \ - struct listnode name = { \ - .next = &name, \ - .prev = &name, \ - } - -#define list_for_each(node, list) \ - for (node = (list)->next; node != (list); node = node->next) - -#define list_for_each_reverse(node, list) \ - for (node = (list)->prev; node != (list); node = node->prev) -void dbg_time(const char *fmt, ...); -void list_init(struct listnode *list); -void list_add_tail(struct listnode *list, struct listnode *item); -void list_add_head(struct listnode *head, struct listnode *item); -void list_remove(struct listnode *item); - -#define list_empty(list) ((list) == (list)->next) -#define list_head(list) ((list)->next) -#define list_tail(list) ((list)->prev) - -int epoll_register(int epoll_fd, int fd, unsigned int events); -int epoll_deregister(int epoll_fd, int fd); -#endif diff --git a/fibocom_MHI/Makefile b/fibocom_MHI/Makefile deleted file mode 100644 index 156e01b..0000000 --- a/fibocom_MHI/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=pcie_mhi_fb -PKG_VERSION:=3.2 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/pcie_mhi_fb - SUBMENU:=WWAN Support - TITLE:=Kernel pcie driver for MHI device - DEPENDS:=+pciids +pciutils +fibocom-dial - FILES:=$(PKG_BUILD_DIR)/pcie_mhi_fb.ko - AUTOLOAD:=$(call AutoLoad,90,pcie_mhi_fb) -endef - -define KernelPackage/pcie_mhi_fb/description - Kernel module for register a custom pciemhi platform device. -endef - -MAKE_OPTS:= \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CXXFLAGS="$(TARGET_CXXFLAGS)" \ - M="$(PKG_BUILD_DIR)" \ - $(EXTRA_KCONFIG) - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,pcie_mhi_fb)) diff --git a/fibocom_MHI/src/Kconfig b/fibocom_MHI/src/Kconfig deleted file mode 100644 index ec1e587..0000000 --- a/fibocom_MHI/src/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -menu "pcie mhi device Drivers" - -config PCIE_MHI - tristate "MHI dev net interface" - help - This modules enables userspace software clients to communicate - with devices supporting the MHI protocol. Userspace clients - may open the device nodes exposed by MHI UCI and perform - read, write and ioctl operations to communicate with the - attached device. - -endmenu - - diff --git a/fibocom_MHI/src/Makefile b/fibocom_MHI/src/Makefile deleted file mode 100644 index 82ec28f..0000000 --- a/fibocom_MHI/src/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -ccflags-y += -g -Wno-incompatible-pointer-types -Wno-unused-variable -#ccflags-y += -DCONFIG_MHI_NETDEV_MBIM -#obj-${CONFIG_PCIE_MHI} := fibo_mhi.o -obj-m := fibo_mhi.o -fibo_mhi-objs := core/mhi_init.o core/mhi_main.o core/mhi_pm.o core/mhi_boot.o core/mhi_dtr.o devices/mhi_netdev.o devices/mhi_uci.o controllers/mhi_qcom.o - -PWD := $(shell pwd) -ifeq ($(ARCH),) -ARCH := $(shell uname -m) -endif -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := -endif -ifeq ($(KDIR),) -KDIR := /lib/modules/$(shell uname -r)/build -endif - - -fibo_mhi: clean -ifeq ($(findstring 86,$(ARCH)), 86) - cp -f $(PWD)/controllers/mhi_qcom_x86.h $(PWD)/controllers/mhi_qcom.h -else - cp -f $(PWD)/controllers/mhi_qcom_arm.h $(PWD)/controllers/mhi_qcom.h -endif - #ln -sf makefile Makefile - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules - -clean: - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) clean diff --git a/fibocom_MHI/src/controllers/mhi_qcom.c b/fibocom_MHI/src/controllers/mhi_qcom.c deleted file mode 100644 index 87e0fd4..0000000 --- a/fibocom_MHI/src/controllers/mhi_qcom.c +++ /dev/null @@ -1,683 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/mhi.h" -#include "mhi_qcom.h" - - -#ifndef PCI_IRQ_MSI -#define PCI_IRQ_MSI (1 << 1) /* Allow MSI interrupts */ - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 )) -int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) -{ - int nvec = maxvec; - int rc; - - if (maxvec < minvec) - return -ERANGE; - - do { - rc = pci_enable_msi_block(dev, nvec); - if (rc < 0) { - return rc; - } else if (rc > 0) { - if (rc < minvec) - return -ENOSPC; - nvec = rc; - } - } while (rc); - - return nvec; -} -#endif - -static int fibo_pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, - unsigned int max_vecs, unsigned int flags) -{ - return pci_enable_msi_range(dev, min_vecs, max_vecs); -} - -static void fibo_pci_free_irq_vectors(struct pci_dev *dev) -{ - pci_disable_msi(dev); -} - -static int fibo_pci_irq_vector(struct pci_dev *dev, unsigned int nr) -{ - return dev->irq + nr; -} -#else -static int fibo_pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, - unsigned int max_vecs, unsigned int flags) -{ - return pci_alloc_irq_vectors(dev, min_vecs, max_vecs, flags); -} - -static void fibo_pci_free_irq_vectors(struct pci_dev *dev) -{ - pci_free_irq_vectors(dev); -} - -static int fibo_pci_irq_vector(struct pci_dev *dev, unsigned int nr) -{ - return pci_irq_vector(dev, nr); -} -#endif - - -static struct pci_device_id mhi_pcie_device_id[] = { - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0300)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0301)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0302)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)},//SDX24 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0306)}, //SDX55 - {PCI_DEVICE(0x2C7C, 0x0512)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)}, - {0}, -}; - -static struct pci_driver mhi_pcie_driver; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_dev *pci_dev = mhi_dev->pci_dev; - - fibo_pci_free_irq_vectors(pci_dev); - iounmap(mhi_cntrl->regs); - mhi_cntrl->regs = NULL; - pci_clear_master(pci_dev); - pci_release_region(pci_dev, mhi_dev->resn); - pci_disable_device(pci_dev); -} - -static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - resource_size_t start, len; - int i; - - mhi_dev->resn = MHI_PCI_BAR_NUM; - ret = pci_assign_resource(pci_dev, mhi_dev->resn); - if (ret) { - MHI_ERR("Error assign pci resources, ret:%d\n", ret); - return ret; - } - - ret = pci_enable_device(pci_dev); - if (ret) { - MHI_ERR("Error enabling device, ret:%d\n", ret); - goto error_enable_device; - } - - ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi"); - if (ret) { - MHI_ERR("Error pci_request_region, ret:%d\n", ret); - goto error_request_region; - } - - pci_set_master(pci_dev); - - start = pci_resource_start(pci_dev, mhi_dev->resn); - len = pci_resource_len(pci_dev, mhi_dev->resn); - /*begin added by tony.du for mantis 0062018 on 2020-11-10*/ - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,6,0 )) - mhi_cntrl->regs = ioremap_nocache(start, len); - #else - mhi_cntrl->regs = ioremap(start, len); - #endif - /*end added by tony.du for mantis 0062018 on 2020-11-10*/ - MHI_LOG("mhi_cntrl->regs = %p\n", mhi_cntrl->regs); - if (!mhi_cntrl->regs) { - MHI_ERR("Error ioremap region\n"); - goto error_ioremap; - } - - ret = fibo_pci_alloc_irq_vectors(pci_dev, 1, mhi_cntrl->msi_required, PCI_IRQ_MSI); - if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) { - if (ret == -ENOSPC) { - } - //imx_4.1.15_2.0.0_ga & DELL_OPTIPLEX_7010 only alloc one msi interrupt for one pcie device - if (ret != 1) { - MHI_ERR("Failed to enable MSI, ret=%d, msi_required=%d\n", ret, mhi_cntrl->msi_required); - goto error_req_msi; - } - } - - mhi_cntrl->msi_allocated = ret; - MHI_LOG("msi_required = %d, msi_allocated = %d, msi_irq = %u\n", mhi_cntrl->msi_required, mhi_cntrl->msi_allocated, pci_dev->irq); - - for (i = 0; i < mhi_cntrl->msi_allocated; i++) { - mhi_cntrl->irq[i] = fibo_pci_irq_vector(pci_dev, i); - if (mhi_cntrl->irq[i] < 0) { - ret = mhi_cntrl->irq[i]; - goto error_get_irq_vec; - } - } - - return 0; - -error_get_irq_vec: - fibo_pci_free_irq_vectors(pci_dev); - -error_req_msi: - iounmap(mhi_cntrl->regs); - -error_ioremap: - pci_clear_master(pci_dev); - -error_request_region: - pci_disable_device(pci_dev); - -error_enable_device: - pci_release_region(pci_dev, mhi_dev->resn); - - return ret; -} - -#ifdef CONFIG_PM -static int mhi_runtime_idle(struct device *dev) -{ - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - MHI_LOG("Entered returning -EBUSY\n"); - - /* - * RPM framework during runtime resume always calls - * rpm_idle to see if device ready to suspend. - * If dev.power usage_count count is 0, rpm fw will call - * rpm_idle cb to see if device is ready to suspend. - * if cb return 0, or cb not defined the framework will - * assume device driver is ready to suspend; - * therefore, fw will schedule runtime suspend. - * In MHI power management, MHI host shall go to - * runtime suspend only after entering MHI State M2, even if - * usage count is 0. Return -EBUSY to disable automatic suspend. - */ - return -EBUSY; -} - -static int mhi_runtime_suspend(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - MHI_LOG("Enter\n"); - - mutex_lock(&mhi_cntrl->pm_mutex); - - ret = mhi_pm_suspend(mhi_cntrl); - if (ret) { - MHI_LOG("Abort due to ret:%d\n", ret); - goto exit_runtime_suspend; - } - - ret = mhi_arch_link_off(mhi_cntrl, true); - if (ret) - MHI_ERR("Failed to Turn off link ret:%d\n", ret); - -exit_runtime_suspend: - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Exited with ret:%d\n", ret); - - return ret; -} - -static int mhi_runtime_resume(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Enter\n"); - - mutex_lock(&mhi_cntrl->pm_mutex); - - if (!mhi_dev->powered_on) { - MHI_LOG("Not fully powered, return success\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return 0; - } - - /* turn on link */ - ret = mhi_arch_link_on(mhi_cntrl); - if (ret) - goto rpm_resume_exit; - - /* enter M0 state */ - ret = mhi_pm_resume(mhi_cntrl); - -rpm_resume_exit: - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Exited with :%d\n", ret); - - return ret; -} - -static int mhi_system_resume(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - ret = mhi_runtime_resume(dev); - if (ret) { - MHI_ERR("Failed to resume link\n"); - } else { - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - - return ret; -} - -int mhi_system_suspend(struct device *dev) -{ - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - MHI_LOG("Entered\n"); - - /* if rpm status still active then force suspend */ - if (!pm_runtime_status_suspended(dev)) - return mhi_runtime_suspend(dev); - - pm_runtime_set_suspended(dev); - pm_runtime_disable(dev); - - MHI_LOG("Exit\n"); - return 0; -} -#endif - -/* checks if link is down */ -static int mhi_link_status(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - u16 dev_id; - int ret; - - /* try reading device id, if dev id don't match, link is down */ - ret = pci_read_config_word(mhi_dev->pci_dev, PCI_DEVICE_ID, &dev_id); - - return (ret || dev_id != mhi_cntrl->dev_id) ? -EIO : 0; -} - -static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - return pm_runtime_get(dev); -} - -static void mhi_runtime_put(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - pm_runtime_put_noidle(dev); -} - -static void mhi_status_cb(struct mhi_controller *mhi_cntrl, - void *priv, - enum MHI_CB reason) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - if (reason == MHI_CB_IDLE) { - MHI_LOG("Schedule runtime suspend 1\n"); - pm_runtime_mark_last_busy(dev); - pm_request_autosuspend(dev); - } -} - -int mhi_debugfs_trigger_m0(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Trigger M3 Exit\n"); - pm_runtime_get(&mhi_dev->pci_dev->dev); - pm_runtime_put(&mhi_dev->pci_dev->dev); - - return 0; -} - -int mhi_debugfs_trigger_m3(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Trigger M3 Entry\n"); - pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev); - pm_request_autosuspend(&mhi_dev->pci_dev->dev); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m0_fops, NULL, - mhi_debugfs_trigger_m0, "%llu\n"); - -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m3_fops, NULL, - mhi_debugfs_trigger_m3, "%llu\n"); - -static int mhi_init_debugfs_trigger_go(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - - MHI_LOG("Trigger power up sequence\n"); - - mhi_async_power_up(mhi_cntrl); - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(mhi_init_debugfs_trigger_go_fops, NULL, - mhi_init_debugfs_trigger_go, "%llu\n"); - - -int mhi_init_debugfs_debug_show(struct seq_file *m, void *d) -{ - seq_puts(m, "Enable debug mode to debug external soc\n"); - seq_puts(m, - "Usage: echo 'devid,timeout,domain,smmu_cfg' > debug_mode\n"); - seq_puts(m, "No spaces between parameters\n"); - seq_puts(m, "\t1. devid : 0 or pci device id to register\n"); - seq_puts(m, "\t2. timeout: mhi cmd/state transition timeout\n"); - seq_puts(m, "\t3. domain: Rootcomplex\n"); - seq_puts(m, "\t4. smmu_cfg: smmu configuration mask:\n"); - seq_puts(m, "\t\t- BIT0: ATTACH\n"); - seq_puts(m, "\t\t- BIT1: S1 BYPASS\n"); - seq_puts(m, "\t\t-BIT2: FAST_MAP\n"); - seq_puts(m, "\t\t-BIT3: ATOMIC\n"); - seq_puts(m, "\t\t-BIT4: FORCE_COHERENT\n"); - seq_puts(m, "\t\t-BIT5: GEOMETRY\n"); - seq_puts(m, "\tAll timeout are in ms, enter 0 to keep default\n"); - seq_puts(m, "Examples inputs: '0x307,10000'\n"); - seq_puts(m, "\techo '0,10000,1'\n"); - seq_puts(m, "\techo '0x307,10000,0,0x3d'\n"); - seq_puts(m, "firmware image name will be changed to debug.mbn\n"); - - return 0; -} - -static int mhi_init_debugfs_debug_open(struct inode *node, struct file *file) -{ - return single_open(file, mhi_init_debugfs_debug_show, NULL); -} - -static ssize_t mhi_init_debugfs_debug_write(struct file *fp, - const char __user *ubuf, - size_t count, - loff_t *pos) -{ - char *buf = kmalloc(count + 1, GFP_KERNEL); - /* #,devid,timeout,domain,smmu-cfg */ - int args[5] = {0}; - static char const *dbg_fw = "debug.mbn"; - int ret; - struct mhi_controller *mhi_cntrl = fp->f_inode->i_private; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_device_id *id; - - if (!buf) - return -ENOMEM; - - ret = copy_from_user(buf, ubuf, count); - if (ret) - goto error_read; - buf[count] = 0; - get_options(buf, ARRAY_SIZE(args), args); - kfree(buf); - - /* override default parameters */ - mhi_cntrl->fw_image = dbg_fw; - mhi_cntrl->edl_image = dbg_fw; - - if (args[0] >= 2 && args[2]) - mhi_cntrl->timeout_ms = args[2]; - - if (args[0] >= 3 && args[3]) - mhi_cntrl->domain = args[3]; - - if (args[0] >= 4 && args[4]) - mhi_dev->smmu_cfg = args[4]; - - /* If it's a new device id register it */ - if (args[0] && args[1]) { - /* find the debug_id and overwrite it */ - for (id = mhi_pcie_device_id; id->vendor; id++) - if (id->device == MHI_PCIE_DEBUG_ID) { - id->device = args[1]; - pci_unregister_driver(&mhi_pcie_driver); - ret = pci_register_driver(&mhi_pcie_driver); - } - } - - mhi_dev->debug_mode = true; - debugfs_create_file("go", 0444, mhi_cntrl->parent, mhi_cntrl, - &mhi_init_debugfs_trigger_go_fops); - pr_info( - "%s: ret:%d pcidev:0x%x smm_cfg:%u timeout:%u\n", - __func__, ret, args[1], mhi_dev->smmu_cfg, - mhi_cntrl->timeout_ms); - return count; - -error_read: - kfree(buf); - return ret; -} - -static const struct file_operations debugfs_debug_ops = { - .open = mhi_init_debugfs_debug_open, - .release = single_release, - .read = seq_read, - .write = mhi_init_debugfs_debug_write, -}; - -static struct mhi_controller * mhi_platform_probe(struct pci_dev *pci_dev) -{ - struct mhi_controller *mhi_cntrl; - struct mhi_dev *mhi_dev; - u64 addr_win[2]; - int ret; - - mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev)); - if (!mhi_cntrl) { - pr_err("mhi_alloc_controller fail\n"); - return NULL; - } - - mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev_id = pci_dev->device; - mhi_cntrl->domain = pci_domain_nr(pci_dev->bus); - mhi_cntrl->bus = pci_dev->bus->number; - mhi_cntrl->slot = PCI_SLOT(pci_dev->devfn); - mhi_dev->smmu_cfg = 0; - - addr_win[0] = 0; - addr_win[1] = 0xFFFFFFFFF; //16GB - - mhi_cntrl->iova_start = addr_win[0]; - mhi_cntrl->iova_stop = addr_win[1]; - - mhi_dev->pci_dev = pci_dev; - mhi_cntrl->pci_dev = pci_dev; - - /* setup power management apis */ - mhi_cntrl->status_cb = mhi_status_cb; - mhi_cntrl->runtime_get = mhi_runtime_get; - mhi_cntrl->runtime_put = mhi_runtime_put; - mhi_cntrl->link_status = mhi_link_status; - - ret = mhi_arch_platform_init(mhi_dev); - if (ret) - goto error_probe; - - ret = mhi_register_mhi_controller(mhi_cntrl); - if (ret) - goto error_register; - - if (mhi_cntrl->parent) - debugfs_create_file("debug_mode", 0444, mhi_cntrl->parent, - mhi_cntrl, &debugfs_debug_ops); - - return mhi_cntrl; - -error_register: - mhi_arch_platform_deinit(mhi_dev); - -error_probe: - mhi_free_controller(mhi_cntrl); - - return NULL; -} - -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id) -{ - struct mhi_controller *mhi_cntrl = NULL; - u32 domain = pci_domain_nr(pci_dev->bus); - u32 bus = pci_dev->bus->number; - u32 slot = PCI_SLOT(pci_dev->devfn); - struct mhi_dev *mhi_dev; - int ret; - - pr_err("INFO:%s pci_dev->name = %s, domain=%d, bus=%d, slot=%d, vendor=%04X, device=%04X\n", - __func__, dev_name(&pci_dev->dev), domain, bus, slot, pci_dev->vendor, pci_dev->device); - - mhi_cntrl = mhi_platform_probe(pci_dev); - if (!mhi_cntrl) { - pr_err("mhi_platform_probe fail\n"); - return -EPROBE_DEFER; - } - - mhi_cntrl->dev_id = pci_dev->device; - mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - mhi_dev->pci_dev = pci_dev; - mhi_dev->powered_on = true; - - ret = mhi_arch_pcie_init(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_arch_pcie_init, ret:%d\n", ret); - return ret; - } - - ret = mhi_arch_iommu_init(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_arch_iommu_init, ret:%d\n", ret); - goto error_iommu_init; - } - - ret = mhi_init_pci_dev(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_init_pci_dev, ret:%d\n", ret); - goto error_init_pci; - } - - /* start power up sequence if not in debug mode */ - if (!mhi_dev->debug_mode) { - ret = mhi_async_power_up(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_async_power_up, ret:%d\n", ret); - goto error_power_up; - } - } - - if (mhi_cntrl->dentry) { - debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl, - &debugfs_trigger_m0_fops); - debugfs_create_file("m3", 0444, mhi_cntrl->dentry, mhi_cntrl, - &debugfs_trigger_m3_fops); - } - - dev_set_drvdata(&pci_dev->dev, mhi_cntrl); - MHI_LOG("Return successful\n"); - - return 0; - -error_power_up: - mhi_deinit_pci_dev(mhi_cntrl); - -error_init_pci: - mhi_arch_iommu_deinit(mhi_cntrl); - -error_iommu_init: - mhi_arch_pcie_deinit(mhi_cntrl); - - return ret; -} - -static void mhi_pci_remove(struct pci_dev *pci_dev) -{ - struct mhi_controller *mhi_cntrl = (struct mhi_controller *)dev_get_drvdata(&pci_dev->dev); - - if (mhi_cntrl && mhi_cntrl->pci_dev == pci_dev) { - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - MHI_LOG("%s\n", dev_name(&pci_dev->dev)); - if (!mhi_dev->debug_mode) { - mhi_power_down(mhi_cntrl, 1); - } - mhi_deinit_pci_dev(mhi_cntrl); - mhi_arch_iommu_deinit(mhi_cntrl); - mhi_arch_pcie_deinit(mhi_cntrl); - mhi_unregister_mhi_controller(mhi_cntrl); - } -} - -static const struct dev_pm_ops pm_ops = { - SET_RUNTIME_PM_OPS(mhi_runtime_suspend, - mhi_runtime_resume, - mhi_runtime_idle) - SET_SYSTEM_SLEEP_PM_OPS(mhi_system_suspend, mhi_system_resume) -}; - -static struct pci_driver mhi_pcie_driver = { - .name = "mhi", - .id_table = mhi_pcie_device_id, - .probe = mhi_pci_probe, - .remove = mhi_pci_remove, - .driver = { - .pm = &pm_ops - } -}; - -int __init mhi_controller_qcom_init(void) -{ - return pci_register_driver(&mhi_pcie_driver); -}; - -void mhi_controller_qcom_exit(void) -{ - pr_err("INFO:%s enter\n", __func__); - pci_unregister_driver(&mhi_pcie_driver); - pr_err("INFO:%s exit\n", __func__); -} diff --git a/fibocom_MHI/src/controllers/mhi_qcom.h b/fibocom_MHI/src/controllers/mhi_qcom.h deleted file mode 100644 index 4a80026..0000000 --- a/fibocom_MHI/src/controllers/mhi_qcom.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _MHI_QCOM_ -#define _MHI_QCOM_ - -/* iova cfg bitmask */ -#define MHI_SMMU_ATTACH BIT(0) -#define MHI_SMMU_S1_BYPASS BIT(1) -#define MHI_SMMU_FAST BIT(2) -#define MHI_SMMU_ATOMIC BIT(3) -#define MHI_SMMU_FORCE_COHERENT BIT(4) - -#define MHI_PCIE_VENDOR_ID (0x17cb) -#define MHI_PCIE_DEBUG_ID (0xffff) -#define MHI_RPM_SUSPEND_TMR_MS (3000) -#define MHI_PCI_BAR_NUM (0) - -struct mhi_dev { - struct pci_dev *pci_dev; - u32 smmu_cfg; - int resn; - void *arch_info; - bool powered_on; - bool debug_mode; -}; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl); -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id); - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 )) -static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) -{ - int rc = dma_set_mask(dev, mask); - if (rc == 0) - dma_set_coherent_mask(dev, mask); - return rc; -} -#endif - -static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev = &mhi_dev->pci_dev->dev; - - return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64)); -} - -static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev) -{ - return 0; -} - -static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev) -{ -} - -static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, - bool graceful) -{ - return 0; -} - -static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -#endif /* _MHI_QCOM_ */ diff --git a/fibocom_MHI/src/controllers/mhi_qcom_arm.h b/fibocom_MHI/src/controllers/mhi_qcom_arm.h deleted file mode 100644 index 4a80026..0000000 --- a/fibocom_MHI/src/controllers/mhi_qcom_arm.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _MHI_QCOM_ -#define _MHI_QCOM_ - -/* iova cfg bitmask */ -#define MHI_SMMU_ATTACH BIT(0) -#define MHI_SMMU_S1_BYPASS BIT(1) -#define MHI_SMMU_FAST BIT(2) -#define MHI_SMMU_ATOMIC BIT(3) -#define MHI_SMMU_FORCE_COHERENT BIT(4) - -#define MHI_PCIE_VENDOR_ID (0x17cb) -#define MHI_PCIE_DEBUG_ID (0xffff) -#define MHI_RPM_SUSPEND_TMR_MS (3000) -#define MHI_PCI_BAR_NUM (0) - -struct mhi_dev { - struct pci_dev *pci_dev; - u32 smmu_cfg; - int resn; - void *arch_info; - bool powered_on; - bool debug_mode; -}; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl); -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id); - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 )) -static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) -{ - int rc = dma_set_mask(dev, mask); - if (rc == 0) - dma_set_coherent_mask(dev, mask); - return rc; -} -#endif - -static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev = &mhi_dev->pci_dev->dev; - - return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64)); -} - -static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev) -{ - return 0; -} - -static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev) -{ -} - -static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, - bool graceful) -{ - return 0; -} - -static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -#endif /* _MHI_QCOM_ */ diff --git a/fibocom_MHI/src/controllers/mhi_qcom_x86.h b/fibocom_MHI/src/controllers/mhi_qcom_x86.h deleted file mode 100644 index 7b8e33e..0000000 --- a/fibocom_MHI/src/controllers/mhi_qcom_x86.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _MHI_QCOM_ -#define _MHI_QCOM_ - -/* iova cfg bitmask */ -#define MHI_SMMU_ATTACH BIT(0) -#define MHI_SMMU_S1_BYPASS BIT(1) -#define MHI_SMMU_FAST BIT(2) -#define MHI_SMMU_ATOMIC BIT(3) -#define MHI_SMMU_FORCE_COHERENT BIT(4) - -#define MHI_PCIE_VENDOR_ID (0x17cb) -#define MHI_PCIE_DEBUG_ID (0xffff) -#define MHI_RPM_SUSPEND_TMR_MS (3000) -#define MHI_PCI_BAR_NUM (0) - -struct mhi_dev { - struct pci_dev *pci_dev; - u32 smmu_cfg; - int resn; - void *arch_info; - bool powered_on; - bool debug_mode; -}; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl); -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id); - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 )) -static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) -{ - int rc = dma_set_mask(dev, mask); - if (rc == 0) - dma_set_coherent_mask(dev, mask); - return rc; -} -#endif - -static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev = &mhi_dev->pci_dev->dev; - - return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(32)); -} - -static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev) -{ - return 0; -} - -static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev) -{ -} - -static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, - bool graceful) -{ - return 0; -} - -static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -#endif /* _MHI_QCOM_ */ diff --git a/fibocom_MHI/src/core/mhi.h b/fibocom_MHI/src/core/mhi.h deleted file mode 100644 index f72fd63..0000000 --- a/fibocom_MHI/src/core/mhi.h +++ /dev/null @@ -1,891 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _MHI_H_ -#define _MHI_H_ - -#include - -typedef u64 uint64; -typedef u32 uint32; - -typedef enum -{ - MHI_CLIENT_LOOPBACK_OUT = 0, - MHI_CLIENT_LOOPBACK_IN = 1, - MHI_CLIENT_SAHARA_OUT = 2, - MHI_CLIENT_SAHARA_IN = 3, - MHI_CLIENT_DIAG_OUT = 4, - MHI_CLIENT_DIAG_IN = 5, - MHI_CLIENT_SSR_OUT = 6, - MHI_CLIENT_SSR_IN = 7, - MHI_CLIENT_QDSS_OUT = 8, - MHI_CLIENT_QDSS_IN = 9, - MHI_CLIENT_EFS_OUT = 10, - MHI_CLIENT_EFS_IN = 11, - MHI_CLIENT_MBIM_OUT = 12, - MHI_CLIENT_MBIM_IN = 13, - MHI_CLIENT_QMI_OUT = 14, - MHI_CLIENT_QMI_IN = 15, - MHI_CLIENT_QMI_2_OUT = 16, - MHI_CLIENT_QMI_2_IN = 17, - MHI_CLIENT_IP_CTRL_1_OUT = 18, - MHI_CLIENT_IP_CTRL_1_IN = 19, - MHI_CLIENT_IPCR_OUT = 20, - MHI_CLIENT_IPCR_IN = 21, - MHI_CLIENT_TEST_FW_OUT = 22, - MHI_CLIENT_TEST_FW_IN = 23, - MHI_CLIENT_RESERVED_0 = 24, - MHI_CLIENT_BOOT_LOG_IN = 25, - MHI_CLIENT_DCI_OUT = 26, - MHI_CLIENT_DCI_IN = 27, - MHI_CLIENT_QBI_OUT = 28, - MHI_CLIENT_QBI_IN = 29, - MHI_CLIENT_RESERVED_1_LOWER = 30, - MHI_CLIENT_RESERVED_1_UPPER = 31, - MHI_CLIENT_DUN_OUT = 32, - MHI_CLIENT_DUN_IN = 33, - MHI_CLIENT_EDL_OUT = 34, - MHI_CLIENT_EDL_IN = 35, - MHI_CLIENT_ADB_FB_OUT = 36, - MHI_CLIENT_ADB_FB_IN = 37, - MHI_CLIENT_RESERVED_2_LOWER = 38, - MHI_CLIENT_RESERVED_2_UPPER = 41, - MHI_CLIENT_CSVT_OUT = 42, - MHI_CLIENT_CSVT_IN = 43, - MHI_CLIENT_SMCT_OUT = 44, - MHI_CLIENT_SMCT_IN = 45, - MHI_CLIENT_IP_SW_0_OUT = 46, - MHI_CLIENT_IP_SW_0_IN = 47, - MHI_CLIENT_IP_SW_1_OUT = 48, - MHI_CLIENT_IP_SW_1_IN = 49, - MHI_CLIENT_GNSS_OUT = 50, - MHI_CLIENT_GNSS_IN = 51, - MHI_CLIENT_AUDIO_OUT = 52, - MHI_CLIENT_AUDIO_IN = 53, - MHI_CLIENT_RESERVED_3_LOWER = 54, - MHI_CLIENT_RESERVED_3_UPPER = 59, - MHI_CLIENT_TEST_0_OUT = 60, - MHI_CLIENT_TEST_0_IN = 61, - MHI_CLIENT_TEST_1_OUT = 62, - MHI_CLIENT_TEST_1_IN = 63, - MHI_CLIENT_TEST_2_OUT = 64, - MHI_CLIENT_TEST_2_IN = 65, - MHI_CLIENT_TEST_3_OUT = 66, - MHI_CLIENT_TEST_3_IN = 67, - MHI_CLIENT_RESERVED_4_LOWER = 68, - MHI_CLIENT_RESERVED_4_UPPER = 91, - MHI_CLIENT_OEM_0_OUT = 92, - MHI_CLIENT_OEM_0_IN = 93, - MHI_CLIENT_OEM_1_OUT = 94, - MHI_CLIENT_OEM_1_IN = 95, - MHI_CLIENT_OEM_2_OUT = 96, - MHI_CLIENT_OEM_2_IN = 97, - MHI_CLIENT_OEM_3_OUT = 98, - MHI_CLIENT_OEM_3_IN = 99, - MHI_CLIENT_IP_HW_0_OUT = 100, - MHI_CLIENT_IP_HW_0_IN = 101, - MHI_CLIENT_ADPL = 102, - MHI_CLIENT_RESERVED_5_LOWER = 103, - MHI_CLIENT_RESERVED_5_UPPER = 127, - MHI_MAX_CHANNELS = 128 -}MHI_CLIENT_CHANNEL_TYPE; - -#define MHI_VERSION 0x01000000 -#define MHIREGLEN_VALUE 0x100 /* **** WRONG VALUE *** */ -#define MHI_MSI_INDEX 1 -#define MAX_NUM_MHI_DEVICES 1 -#define NUM_MHI_XFER_RINGS 128 -#define NUM_MHI_EVT_RINGS 3 -#define PRIMARY_EVENT_RING 0 -#define IPA_OUT_EVENT_RING 1 -#define IPA_IN_EVENT_RING 2 -#define NUM_MHI_XFER_RING_ELEMENTS 16 -#define NUM_MHI_EVT_RING_ELEMENTS 256 -#define NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS 2048 -#define NUM_MHI_IPA_IN_EVT_RING_ELEMENTS 1024 -#define NUM_MHI_IPA_IN_RING_ELEMENTS 256 -#define NUM_MHI_IPA_OUT_RING_ELEMENTS 256 -#define NUM_MHI_DIAG_IN_RING_ELEMENTS 128 -#define NUM_MHI_CHAN_RING_ELEMENTS 8 -#define MHI_EVT_CMD_QUEUE_SIZE 160 -#define MHI_EVT_STATE_QUEUE_SIZE 128 -#define MHI_EVT_XFER_QUEUE_SIZE 1024 -#define MHI_ALIGN_4BYTE_OFFSET 0x3 -#define MHI_ALIGN_4K_OFFSET 0xFFF -#define MAX_TRB_DATA_SIZE 0xFFFF -#define RESERVED_VALUE_64 0xFFFFFFFFFFFFFFFF -#define RESERVED_VALUE 0xFFFFFFFF -#define PCIE_LINK_DOWN 0xFFFFFFFF -#define SECONDS 1000 -#define MINUTES 60000 - -#define MHI_FILE_MHI 0x4D4849 -#define MHI_FILE_INIT 0x494E4954 -#define MHI_FILE_MSI 0x4D5349 -#define MHI_FILE_OS 0x4F53 -#define MHI_FILE_SM 0x534D -#define MHI_FILE_THREADS 0x54485245 -#define MHI_FILE_TRANSFER 0x5452414E -#define MHI_FILE_UTILS 0x5554494C - - -#define MHI_ER_PRIORITY_HIGH 0 -#define MHI_ER_PRIORITY_MEDIUM 1 -#define MHI_ER_PRIORITY_SPECIAL 2 - -#undef FALSE -#undef TRUE -#define FALSE 0 -#define TRUE 1 - -typedef struct MHI_DEV_CTXT MHI_DEV_CTXT; -typedef struct PCI_CORE_INFO PCI_CORE_INFO; -typedef struct PCIE_DEV_INFO PCIE_DEV_INFO; - -/* Memory Segment Properties */ -typedef struct _MHI_MEM_PROPS -{ - uint64 VirtAligned; - uint64 VirtUnaligned; - uint64 PhysAligned; - uint64 PhysUnaligned; - uint64 Size; - void *Handle; -}MHI_MEM_PROPS, *PMHI_MEM_PROPS; - -/* Device Power State Type */ -typedef enum -{ - POWER_DEVICE_INVALID = 0, - POWER_DEVICE_D0 = 1, - POWER_DEVICE_D1 = 2, - POWER_DEVICE_D2 = 3, - POWER_DEVICE_D3 = 4, - POWER_DEVICE_D3FINAL = 5, // System shutting down - POWER_DEVICE_HIBARNATION = 6, // Entering system state S4 - POWER_DEVICE_MAX = 7 -}PWR_STATE_TYPE; - -/* Channel State */ -typedef enum -{ - CHAN_STATE_DISABLED = 0, - CHAN_STATE_ENABLED = 1, - CHAN_STATE_RUNNING = 2, - CHAN_STATE_SUSPENDED = 3, - CHAN_STATE_STOPPED = 4, - CHAN_STATE_ERROR = 5, - - CHAN_STATE_OTHER = RESERVED_VALUE -}CHAN_STATE_TYPE; - -/* Channel Type */ -typedef enum -{ - INVALID_CHAN = 0, - OUTBOUND_CHAN = 1, - INBOUND_CHAN = 2, - - OTHER_CHAN = RESERVED_VALUE -}CHAN_TYPE; - -/* Ring Type */ -typedef enum -{ - CMD_RING = 0, - XFER_RING = 1, - EVT_RING = 2, -}MHI_RING_TYPE; - -/* Event Ring */ -typedef enum -{ - EVT_RING_INVALID = 0x0, - EVT_RING_VALID = 0x1, - EVT_RING_RESERVED = RESERVED_VALUE -}MHI_EVENT_RING_TYPE; - -#pragma pack(push,1) - -/* MHI Ring Context */ -typedef /*_ALIGN(1)*/ struct _MHI_RING_CTXT_TYPE -{ - uint32 Info; - uint32 Type; - uint32 Index; - uint64 Base; - uint64 Length; - volatile uint64 RP; - uint64 WP; -}MHI_RING_CTXT_TYPE, *PMHI_RING_CTXT_TYPE; - -/* MHI Ring Element */ -typedef /*_ALIGN(1)*/ struct _MHI_ELEMENT_TYPE -{ - uint64 Ptr; - uint32 Status; - uint32 Control; -}MHI_ELEMENT_TYPE, *PMHI_ELEMENT_TYPE; - -#pragma pack(pop) - -/* Command Ring Element Type */ -typedef enum -{ - CMD_NONE = 0, - CMD_NOOP = 1, - CMD_RESET_CHAN = 16, - CMD_STOP_CHAN = 17, - CMD_START_CHAN = 18, - CMD_CANCEL_CHAN_XFERS = 21 -}MHI_CMD_TYPE; - -/* Event Ring Element Type */ -typedef enum -{ - STATE_CHANGE_EVT = 32, - CMD_COMPLETION_EVT = 33, - XFER_COMPLETION_EVT = 34, - EE_STATE_CHANGE_EVT = 64 -} MHI_EVT_TYPE; - -/* Ring Status Type */ -typedef enum -{ - RING_EMPTY = 0, - RING_FULL = 1, - RING_QUEUED = 2, -} MHI_RING_STATUS_TYPE; - -/* XFER Ring Element Type */ -#define XFER_RING_ELEMENT_TYPE 2 - -/* Event Ring Completion Status */ -typedef enum -{ - EVT_COMPLETION_INVALID = 0, - EVT_COMPLETION_SUCCESS = 1, - EVT_COMPLETION_EOT = 2, - EVT_COMPLETION_OVERFLOW = 3, - EVT_COMPLETION_EOB = 4, - EVT_COMPLETION_OOB = 5, /* Out-Of-Buffer */ - EVT_COMPLETION_DB_MODE = 6, - EVT_COMPLETION_UNDEFINED = 16, - EVT_COMPLETION_MALFORMED = 17, - - EVT_COMPLETION_OTHER = RESERVED_VALUE -}EVT_COMPLETION_STATUS_TYPE; - -/* *********************************************************************************************** */ -/* Macros */ -/* *********************************************************************************************** */ -#define ADVANCE_RING_PTR(RingCtxt, Ptr, Size) \ - *Ptr = ((*Ptr - RingCtxt->Base)/sizeof(MHI_ELEMENT_TYPE) == (Size - 1))? \ - RingCtxt->Base: (*Ptr + sizeof(MHI_ELEMENT_TYPE)) - -#define GET_VIRT_ADDR(MhiCtxt, PhysAddr) \ - ((MhiCtxt)->CtrlSegProps.VirtAligned + ((PhysAddr) - (MhiCtxt)->CtrlSegProps.PhysAligned)) \ - -#define GET_PHYS_ADDR(MhiCtxt, VirtAddr) \ - ((MhiCtxt)->CtrlSegProps.PhysAligned + ((VirtAddr) - (MhiCtxt)->CtrlSegProps.VirtAligned)) \ - -#define GET_RING_ELEMENT_INDEX(RingBase, Element) \ - (((Element) - (RingBase))/sizeof(MHI_ELEMENT_TYPE)) - -#define VALID_RING_PTR(Ring, Ptr) \ - (((Ptr) >= (Ring)->Base) && \ - ((Ptr) <= ((Ring)->Base + (Ring)->Length - sizeof(MHI_ELEMENT_TYPE)))) - -#define CHAN_INBOUND(_x) ((_x)%2) - -#define CHAN_SBL(_x) (((_x) == MHI_CLIENT_SAHARA_OUT) || \ - ((_x) == MHI_CLIENT_SAHARA_IN) || \ - ((_x) == MHI_CLIENT_BOOT_LOG_IN)) - -#define CHAN_EDL(_x) (((_x) == MHI_CLIENT_EDL_OUT) || \ - ((_x) == MHI_CLIENT_EDL_IN)) - -#define RESERVED_CHAN(_x) (((_x) == MHI_CLIENT_RESERVED_0) || \ - ((_x) >= MHI_CLIENT_RESERVED_1_LOWER && (_x) <= MHI_CLIENT_RESERVED_1_UPPER) || \ - ((_x) >= MHI_CLIENT_RESERVED_2_LOWER && (_x) <= MHI_CLIENT_RESERVED_2_UPPER) || \ - ((_x) >= MHI_CLIENT_RESERVED_3_LOWER && (_x) <= MHI_CLIENT_RESERVED_3_UPPER) || \ - ((_x) >= MHI_CLIENT_RESERVED_4_LOWER && (_x) <= MHI_CLIENT_RESERVED_4_UPPER) || \ - ((_x) >= MHI_CLIENT_RESERVED_5_LOWER)) - -#define VALID_CHAN(_x) ((((_x) >= 0) && ((_x) < MHI_MAX_CHANNELS))) - -#define MHI_HW_CHAN(_x) ((_x) == MHI_CLIENT_IP_HW_0_OUT || \ - (_x) == MHI_CLIENT_IP_HW_0_IN || \ - (_x) == MHI_CLIENT_ADPL) - -#define MIN(_x,_y) ((_x) < (_y) ? (_x): (_y)) - -struct mhi_chan; -struct mhi_event; -struct mhi_ctxt; -struct mhi_cmd; -struct image_info; -struct bhi_vec_entry; -struct mhi_cntrl_data; - -/** - * enum MHI_CB - MHI callback - * @MHI_CB_IDLE: MHI entered idle state - * @MHI_CB_PENDING_DATA: New data available for client to process - * @MHI_CB_LPM_ENTER: MHI host entered low power mode - * @MHI_CB_LPM_EXIT: MHI host about to exit low power mode - * @MHI_CB_EE_RDDM: MHI device entered RDDM execution enviornment - */ -enum MHI_CB { - MHI_CB_IDLE, - MHI_CB_PENDING_DATA, - MHI_CB_LPM_ENTER, - MHI_CB_LPM_EXIT, - MHI_CB_EE_RDDM, -}; - -/** - * enum MHI_DEBUG_LEVL - various debugging level - */ -enum MHI_DEBUG_LEVEL { - MHI_MSG_LVL_VERBOSE, - MHI_MSG_LVL_INFO, - MHI_MSG_LVL_ERROR, - MHI_MSG_LVL_CRITICAL, - MHI_MSG_LVL_MASK_ALL, -}; - -/** - * enum MHI_FLAGS - Transfer flags - * @MHI_EOB: End of buffer for bulk transfer - * @MHI_EOT: End of transfer - * @MHI_CHAIN: Linked transfer - */ -enum MHI_FLAGS { - MHI_EOB, - MHI_EOT, - MHI_CHAIN, -}; - -/** - * struct image_info - firmware and rddm table table - * @mhi_buf - Contain device firmware and rddm table - * @entries - # of entries in table - */ -struct image_info { - struct mhi_buf *mhi_buf; - struct bhi_vec_entry *bhi_vec; - u32 entries; -}; - -/** - * struct mhi_controller - Master controller structure for external modem - * @dev: Device associated with this controller - * @of_node: DT that has MHI configuration information - * @regs: Points to base of MHI MMIO register space - * @bhi: Points to base of MHI BHI register space - * @wake_db: MHI WAKE doorbell register address - * @dev_id: PCIe device id of the external device - * @domain: PCIe domain the device connected to - * @bus: PCIe bus the device assigned to - * @slot: PCIe slot for the modem - * @iova_start: IOMMU starting address for data - * @iova_stop: IOMMU stop address for data - * @fw_image: Firmware image name for normal booting - * @edl_image: Firmware image name for emergency download mode - * @fbc_download: MHI host needs to do complete image transfer - * @rddm_size: RAM dump size that host should allocate for debugging purpose - * @sbl_size: SBL image size - * @seg_len: BHIe vector size - * @fbc_image: Points to firmware image buffer - * @rddm_image: Points to RAM dump buffer - * @max_chan: Maximum number of channels controller support - * @mhi_chan: Points to channel configuration table - * @lpm_chans: List of channels that require LPM notifications - * @total_ev_rings: Total # of event rings allocated - * @hw_ev_rings: Number of hardware event rings - * @sw_ev_rings: Number of software event rings - * @msi_required: Number of msi required to operate - * @msi_allocated: Number of msi allocated by bus master - * @irq: base irq # to request - * @mhi_event: MHI event ring configurations table - * @mhi_cmd: MHI command ring configurations table - * @mhi_ctxt: MHI device context, shared memory between host and device - * @timeout_ms: Timeout in ms for state transitions - * @pm_state: Power management state - * @ee: MHI device execution environment - * @dev_state: MHI STATE - * @status_cb: CB function to notify various power states to but master - * @link_status: Query link status in case of abnormal value read from device - * @runtime_get: Async runtime resume function - * @runtimet_put: Release votes - * @priv_data: Points to bus master's private data - */ -struct mhi_controller { - struct list_head node; - - /* device node for iommu ops */ - struct device *dev; - struct pci_dev *pci_dev; - - /* mmio base */ - void __iomem *regs; - void __iomem *bhi; - void __iomem *wake_db; - - /* device topology */ - u32 dev_id; - u32 domain; - u32 bus; - u32 slot; - - /* addressing window */ - dma_addr_t iova_start; - dma_addr_t iova_stop; - - /* fw images */ - const char *fw_image; - const char *edl_image; - - /* mhi host manages downloading entire fbc images */ - bool fbc_download; - size_t rddm_size; - size_t sbl_size; - size_t seg_len; - u32 session_id; - u32 sequence_id; - struct image_info *fbc_image; - struct image_info *rddm_image; - - /* physical channel config data */ - u32 max_chan; - struct mhi_chan *mhi_chan; - struct list_head lpm_chans; /* these chan require lpm notification */ - - /* physical event config data */ - u32 total_ev_rings; - u32 hw_ev_rings; - u32 sw_ev_rings; - u32 msi_required; - u32 msi_allocated; - int irq[8]; /* interrupt table */ - struct mhi_event *mhi_event; - - /* cmd rings */ - struct mhi_cmd *mhi_cmd; - - /* mhi context (shared with device) */ - struct mhi_ctxt *mhi_ctxt; - - u32 timeout_ms; - - /* caller should grab pm_mutex for suspend/resume operations */ - struct mutex pm_mutex; - bool pre_init; - rwlock_t pm_lock; - u32 pm_state; - u32 ee; - u32 dev_state; - bool wake_set; - atomic_t dev_wake; - atomic_t alloc_size; - struct list_head transition_list; - spinlock_t transition_lock; - spinlock_t wlock; - - /* debug counters */ - u32 M0, M1, M2, M3; - - /* worker for different state transitions */ - struct work_struct st_worker; - struct work_struct fw_worker; - struct work_struct m1_worker; - struct work_struct syserr_worker; - wait_queue_head_t state_event; - - /* shadow functions */ - void (*status_cb)(struct mhi_controller *mhi_cntrl, void *piv, - enum MHI_CB reason); - int (*link_status)(struct mhi_controller *mhi_cntrl, void *priv); - void (*wake_get)(struct mhi_controller *mhi_cntrl, bool override); - void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override); - int (*runtime_get)(struct mhi_controller *mhi_cntrl, void *priv); - void (*runtime_put)(struct mhi_controller *mhi_cntrl, void *priv); - - /* channel to control DTR messaging */ - struct mhi_device *dtr_dev; - - /* kernel log level */ - enum MHI_DEBUG_LEVEL klog_lvl; - - /* private log level controller driver to set */ - enum MHI_DEBUG_LEVEL log_lvl; - - /* controller specific data */ - void *priv_data; - void *log_buf; - struct dentry *dentry; - struct dentry *parent; - struct mhi_cntrl_data *data; - - struct miscdevice miscdev; -}; - -/** - * struct mhi_device - mhi device structure associated bind to channel - * @dev: Device associated with the channels - * @mtu: Maximum # of bytes controller support - * @ul_chan_id: MHI channel id for UL transfer - * @dl_chan_id: MHI channel id for DL transfer - * @priv: Driver private data - */ -struct mhi_device { - struct device dev; - u32 dev_id; - u32 domain; - u32 bus; - u32 slot; - size_t mtu; - int ul_chan_id; - int dl_chan_id; - int ul_event_id; - int dl_event_id; - const struct mhi_device_id *id; - const char *chan_name; - struct mhi_controller *mhi_cntrl; - struct mhi_chan *ul_chan; - struct mhi_chan *dl_chan; - atomic_t dev_wake; - void *priv_data; - int (*ul_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS flags); - int (*dl_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS flags); - void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB reason); -}; - -/** - * struct mhi_result - Completed buffer information - * @buf_addr: Address of data buffer - * @dir: Channel direction - * @bytes_xfer: # of bytes transferred - * @transaction_status: Status of last trasnferred - */ -struct mhi_result { - void *buf_addr; - enum dma_data_direction dir; - size_t bytes_xferd; - int transaction_status; -}; - -/** - * struct mhi_buf - Describes the buffer - * @buf: cpu address for the buffer - * @phys_addr: physical address of the buffer - * @dma_addr: iommu address for the buffer - * @len: # of bytes - * @name: Buffer label, for offload channel configurations name must be: - * ECA - Event context array data - * CCA - Channel context array data - */ -struct mhi_buf { - void *buf; - phys_addr_t phys_addr; - dma_addr_t dma_addr; - size_t len; - const char *name; /* ECA, CCA */ -}; - -/** - * struct mhi_driver - mhi driver information - * @id_table: NULL terminated channel ID names - * @ul_xfer_cb: UL data transfer callback - * @dl_xfer_cb: DL data transfer callback - * @status_cb: Asynchronous status callback - */ -struct mhi_driver { - const struct mhi_device_id *id_table; - int (*probe)(struct mhi_device *mhi_dev, - const struct mhi_device_id *id); - void (*remove)(struct mhi_device *mhi_dev); - void (*ul_xfer_cb)(struct mhi_device *mhi_dev, - struct mhi_result *result); - void (*dl_xfer_cb)(struct mhi_device *mhi_dev, - struct mhi_result *result); - void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb); - struct device_driver driver; -}; - -#define to_mhi_driver(drv) container_of(drv, struct mhi_driver, driver) -#define to_mhi_device(dev) container_of(dev, struct mhi_device, dev) - -static inline void mhi_device_set_devdata(struct mhi_device *mhi_dev, - void *priv) -{ - mhi_dev->priv_data = priv; -} - -static inline void *mhi_device_get_devdata(struct mhi_device *mhi_dev) -{ - return mhi_dev->priv_data; -} - -/** - * mhi_queue_transfer - Queue a buffer to hardware - * All transfers are asyncronous transfers - * @mhi_dev: Device associated with the channels - * @dir: Data direction - * @buf: Data buffer (skb for hardware channels) - * @len: Size in bytes - * @mflags: Interrupt flags for the device - */ -static inline int mhi_queue_transfer(struct mhi_device *mhi_dev, - enum dma_data_direction dir, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - if (dir == DMA_TO_DEVICE) - return mhi_dev->ul_xfer(mhi_dev, mhi_dev->ul_chan, buf, len, - mflags); - else - return mhi_dev->dl_xfer(mhi_dev, mhi_dev->dl_chan, buf, len, - mflags); -} - -static inline void *mhi_controller_get_devdata(struct mhi_controller *mhi_cntrl) -{ - return mhi_cntrl->priv_data; -} - -static inline void mhi_free_controller(struct mhi_controller *mhi_cntrl) -{ - kfree(mhi_cntrl); -} - -/** - * mhi_driver_register - Register driver with MHI framework - * @mhi_drv: mhi_driver structure - */ -int mhi_driver_register(struct mhi_driver *mhi_drv); - -/** - * mhi_driver_unregister - Unregister a driver for mhi_devices - * @mhi_drv: mhi_driver structure - */ -void mhi_driver_unregister(struct mhi_driver *mhi_drv); - -/** - * mhi_device_configure - configure ECA or CCA context - * For offload channels that client manage, call this - * function to configure channel context or event context - * array associated with the channel - * @mhi_div: Device associated with the channels - * @dir: Direction of the channel - * @mhi_buf: Configuration data - * @elements: # of configuration elements - */ -int mhi_device_configure(struct mhi_device *mhi_div, - enum dma_data_direction dir, - struct mhi_buf *mhi_buf, - int elements); - -/** - * mhi_device_get - disable all low power modes - * Only disables lpm, does not immediately exit low power mode - * if controller already in a low power mode - * @mhi_dev: Device associated with the channels - */ -void mhi_device_get(struct mhi_device *mhi_dev); - -/** - * mhi_device_get_sync - disable all low power modes - * Synchronously disable all low power, exit low power mode if - * controller already in a low power state - * @mhi_dev: Device associated with the channels - */ -int mhi_device_get_sync(struct mhi_device *mhi_dev); - -/** - * mhi_device_put - re-enable low power modes - * @mhi_dev: Device associated with the channels - */ -void mhi_device_put(struct mhi_device *mhi_dev); - -/** - * mhi_prepare_for_transfer - setup channel for data transfer - * Moves both UL and DL channel from RESET to START state - * @mhi_dev: Device associated with the channels - */ -int mhi_prepare_for_transfer(struct mhi_device *mhi_dev); - -/** - * mhi_unprepare_from_transfer -unprepare the channels - * Moves both UL and DL channels to RESET state - * @mhi_dev: Device associated with the channels - */ -void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev); - -/** - * mhi_get_no_free_descriptors - Get transfer ring length - * Get # of TD available to queue buffers - * @mhi_dev: Device associated with the channels - * @dir: Direction of the channel - */ -int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, - enum dma_data_direction dir); - -/** - * mhi_poll - poll for any available data to consume - * This is only applicable for DL direction - * @mhi_dev: Device associated with the channels - * @budget: In descriptors to service before returning - */ -int mhi_poll(struct mhi_device *mhi_dev, u32 budget); - -/** - * mhi_ioctl - user space IOCTL support for MHI channels - * Native support for setting TIOCM - * @mhi_dev: Device associated with the channels - * @cmd: IOCTL cmd - * @arg: Optional parameter, iotcl cmd specific - */ -long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg); - -/** - * mhi_alloc_controller - Allocate mhi_controller structure - * Allocate controller structure and additional data for controller - * private data. You may get the private data pointer by calling - * mhi_controller_get_devdata - * @size: # of additional bytes to allocate - */ -struct mhi_controller *mhi_alloc_controller(size_t size); - -/** - * mhi_register_mhi_controller - Register MHI controller - * Registers MHI controller with MHI bus framework. DT must be supported - * @mhi_cntrl: MHI controller to register - */ -int mhi_register_mhi_controller(struct mhi_controller *mhi_cntrl); - -void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl); - -/** - * mhi_bdf_to_controller - Look up a registered controller - * Search for controller based on device identification - * @domain: RC domain of the device - * @bus: Bus device connected to - * @slot: Slot device assigned to - * @dev_id: Device Identification - */ -struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot, - u32 dev_id); - -/** - * mhi_prepare_for_power_up - Do pre-initialization before power up - * This is optional, call this before power up if controller do not - * want bus framework to automatically free any allocated memory during shutdown - * process. - * @mhi_cntrl: MHI controller - */ -int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl); - -/** - * mhi_async_power_up - Starts MHI power up sequence - * @mhi_cntrl: MHI controller - */ -int mhi_async_power_up(struct mhi_controller *mhi_cntrl); -int mhi_sync_power_up(struct mhi_controller *mhi_cntrl); - -/** - * mhi_power_down - Start MHI power down sequence - * @mhi_cntrl: MHI controller - * @graceful: link is still accessible, do a graceful shutdown process otherwise - * we will shutdown host w/o putting device into RESET state - */ -void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful); - -/** - * mhi_unprepare_after_powre_down - free any allocated memory for power up - * @mhi_cntrl: MHI controller - */ -void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl); - -/** - * mhi_pm_suspend - Move MHI into a suspended state - * Transition to MHI state M3 state from M0||M1||M2 state - * @mhi_cntrl: MHI controller - */ -int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); - -/** - * mhi_pm_resume - Resume MHI from suspended state - * Transition to MHI state M0 state from M3 state - * @mhi_cntrl: MHI controller - */ -int mhi_pm_resume(struct mhi_controller *mhi_cntrl); - -/** - * mhi_download_rddm_img - Download ramdump image from device for - * debugging purpose. - * @mhi_cntrl: MHI controller - * @in_panic: If we trying to capture image while in kernel panic - */ -int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic); - -/** - * mhi_force_rddm_mode - Force external device into rddm mode - * to collect device ramdump. This is useful if host driver assert - * and we need to see device state as well. - * @mhi_cntrl: MHI controller - */ -int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl); - -int mhi_cntrl_register_miscdev(struct mhi_controller *mhi_cntrl); -void mhi_cntrl_deregister_miscdev(struct mhi_controller *mhi_cntrl); - -extern int mhi_debug_mask; - -#define MHI_VERB(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_err("VERBOSE:[D][%s] " fmt, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MHI_LOG(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_INFO) \ - pr_err("INFO:[I][%s] " fmt, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MHI_ERR(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ -} while (0) - -#define MHI_CRITICAL(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_CRITICAL) \ - pr_err("ALERT:[C][%s] " fmt, __func__, ##__VA_ARGS__); \ -} while (0) - -#ifndef MHI_NAME_SIZE -#define MHI_NAME_SIZE 32 -/** - * * struct mhi_device_id - MHI device identification - * * @chan: MHI channel name - * * @driver_data: driver data; - * */ -struct mhi_device_id { - const char chan[MHI_NAME_SIZE]; - unsigned long driver_data; -}; -#endif - -#endif /* _MHI_H_ */ diff --git a/fibocom_MHI/src/core/mhi_boot.c b/fibocom_MHI/src/core/mhi_boot.c deleted file mode 100644 index a981841..0000000 --- a/fibocom_MHI/src/core/mhi_boot.c +++ /dev/null @@ -1,878 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -#define IOCTL_BHI_GETDEVINFO 0x8BE0 + 1 -#define IOCTL_BHI_WRITEIMAGE 0x8BE0 + 2 - -/* Software defines */ -/* BHI Version */ -#define BHI_MAJOR_VERSION 0x1 -#define BHI_MINOR_VERSION 0x1 - -#define MSMHWID_NUMDWORDS 6 /* Number of dwords that make the MSMHWID */ -#define OEMPKHASH_NUMDWORDS 48 /* Number of dwords that make the OEM PK HASH */ - -#define IsPBLExecEnv(ExecEnv) ((ExecEnv == MHI_EE_PBL) || (ExecEnv == MHI_EE_EDL) ) - -typedef u32 ULONG; - -typedef struct _bhi_info_type -{ - ULONG bhi_ver_minor; - ULONG bhi_ver_major; - ULONG bhi_image_address_low; - ULONG bhi_image_address_high; - ULONG bhi_image_size; - ULONG bhi_rsvd1; - ULONG bhi_imgtxdb; - ULONG bhi_rsvd2; - ULONG bhi_msivec; - ULONG bhi_rsvd3; - ULONG bhi_ee; - ULONG bhi_status; - ULONG bhi_errorcode; - ULONG bhi_errdbg1; - ULONG bhi_errdbg2; - ULONG bhi_errdbg3; - ULONG bhi_sernum; - ULONG bhi_sblantirollbackver; - ULONG bhi_numsegs; - ULONG bhi_msmhwid[6]; - ULONG bhi_oempkhash[48]; - ULONG bhi_rsvd5; -}BHI_INFO_TYPE, *PBHI_INFO_TYPE; - -#if 0 -static void PrintBhiInfo(BHI_INFO_TYPE *bhi_info) -{ - ULONG index; - - printk("BHI Device Info...\n"); - printk("BHI Version = { Major = 0x%X Minor = 0x%X}\n", bhi_info->bhi_ver_major, bhi_info->bhi_ver_minor); - printk("BHI Execution Environment = 0x%X\n", bhi_info->bhi_ee); - printk("BHI Status = 0x%X\n", bhi_info->bhi_status); - printk("BHI Error code = 0x%X { Dbg1 = 0x%X Dbg2 = 0x%X Dbg3 = 0x%X }\n", bhi_info->bhi_errorcode, bhi_info->bhi_errdbg1, bhi_info->bhi_errdbg2, bhi_info->bhi_errdbg3); - printk("BHI Serial Number = 0x%X\n", bhi_info->bhi_sernum); - printk("BHI SBL Anti-Rollback Ver = 0x%X\n", bhi_info->bhi_sblantirollbackver); - printk("BHI Number of Segments = 0x%X\n", bhi_info->bhi_numsegs); - printk("BHI MSM HW-Id = "); - for (index = 0; index < 6; index++) - { - printk("0x%X ", bhi_info->bhi_msmhwid[index]); - } - printk("\n"); - - printk("BHI OEM PK Hash = \n"); - for (index = 0; index < 24; index++) - { - printk("0x%X ", bhi_info->bhi_oempkhash[index]); - } - printk("\n"); -} -#endif - -static u32 bhi_read_reg(struct mhi_controller *mhi_cntrl, u32 offset) -{ - u32 out = 0; - int ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, offset, &out); - - return (ret) ? 0 : out; -} - -static int BhiRead(struct mhi_controller *mhi_cntrl, BHI_INFO_TYPE *bhi_info) -{ - ULONG index; - - memset(bhi_info, 0x00, sizeof(BHI_INFO_TYPE)); - - /* bhi_ver */ - bhi_info->bhi_ver_minor = bhi_read_reg(mhi_cntrl, BHI_BHIVERSION_MINOR); - bhi_info->bhi_ver_major = bhi_read_reg(mhi_cntrl, BHI_BHIVERSION_MINOR); - bhi_info->bhi_image_address_low = bhi_read_reg(mhi_cntrl, BHI_IMGADDR_LOW); - bhi_info->bhi_image_address_high = bhi_read_reg(mhi_cntrl, BHI_IMGADDR_HIGH); - bhi_info->bhi_image_size = bhi_read_reg(mhi_cntrl, BHI_IMGSIZE); - bhi_info->bhi_rsvd1 = bhi_read_reg(mhi_cntrl, BHI_RSVD1); - bhi_info->bhi_imgtxdb = bhi_read_reg(mhi_cntrl, BHI_IMGTXDB); - bhi_info->bhi_rsvd2 = bhi_read_reg(mhi_cntrl, BHI_RSVD2); - bhi_info->bhi_msivec = bhi_read_reg(mhi_cntrl, BHI_INTVEC); - bhi_info->bhi_rsvd3 = bhi_read_reg(mhi_cntrl, BHI_RSVD3); - bhi_info->bhi_ee = bhi_read_reg(mhi_cntrl, BHI_EXECENV); - bhi_info->bhi_status = bhi_read_reg(mhi_cntrl, BHI_STATUS); - bhi_info->bhi_errorcode = bhi_read_reg(mhi_cntrl, BHI_ERRCODE); - bhi_info->bhi_errdbg1 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG1); - bhi_info->bhi_errdbg2 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG2); - bhi_info->bhi_errdbg3 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG3); - bhi_info->bhi_sernum = bhi_read_reg(mhi_cntrl, BHI_SERIALNUM); - bhi_info->bhi_sblantirollbackver = bhi_read_reg(mhi_cntrl, BHI_SBLANTIROLLVER); - bhi_info->bhi_numsegs = bhi_read_reg(mhi_cntrl, BHI_NUMSEG); - for (index = 0; index < MSMHWID_NUMDWORDS; index++) - { - bhi_info->bhi_msmhwid[index] = bhi_read_reg(mhi_cntrl, BHI_MSMHWID(index)); - } - for (index = 0; index < OEMPKHASH_NUMDWORDS; index++) - { - bhi_info->bhi_oempkhash[index] = bhi_read_reg(mhi_cntrl, BHI_OEMPKHASH(index)); - } - bhi_info->bhi_rsvd5 = bhi_read_reg(mhi_cntrl, BHI_RSVD5); - //PrintBhiInfo(bhi_info); - /* Check the Execution Environment */ - if (!IsPBLExecEnv(bhi_info->bhi_ee)) - { - printk("E - EE: 0x%X Expected PBL/EDL\n", bhi_info->bhi_ee); - } - - /* Return the number of bytes read */ - return 0; -} - -/* setup rddm vector table for rddm transfer */ -static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, - struct image_info *img_info) -{ - struct mhi_buf *mhi_buf = img_info->mhi_buf; - struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; - int i = 0; - - for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { - MHI_VERB("Setting vector:%pad size:%zu\n", - &mhi_buf->dma_addr, mhi_buf->len); - bhi_vec->dma_addr = mhi_buf->dma_addr; - bhi_vec->size = mhi_buf->len; - } -} - -/* collect rddm during kernel panic */ -static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) -{ - int ret; - struct mhi_buf *mhi_buf; - u32 sequence_id; - u32 rx_status; - enum MHI_EE ee; - struct image_info *rddm_image = mhi_cntrl->rddm_image; - const u32 delayus = 100; - u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; - void __iomem *base = mhi_cntrl->bhi; - - MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - /* - * This should only be executing during a kernel panic, we expect all - * other cores to shutdown while we're collecting rddm buffer. After - * returning from this function, we expect device to reset. - * - * Normaly, we would read/write pm_state only after grabbing - * pm_lock, since we're in a panic, skipping it. - */ - - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - return -EIO; - - /* - * There is no gurantee this state change would take effect since - * we're setting it w/o grabbing pmlock, it's best effort - */ - mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; - /* update should take the effect immediately */ - smp_wmb(); - - /* setup the RX vector table */ - mhi_rddm_prepare(mhi_cntrl, rddm_image); - mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; - - MHI_LOG("Starting BHIe programming for RDDM\n"); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, - upper_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, - lower_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); - sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; - - if (unlikely(!sequence_id)) - sequence_id = 1; - - - mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, - BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, - sequence_id); - - MHI_LOG("Trigger device into RDDM mode\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); - - MHI_LOG("Waiting for image download completion\n"); - while (retry--) { - ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, - BHIE_RXVECSTATUS_STATUS_BMSK, - BHIE_RXVECSTATUS_STATUS_SHFT, - &rx_status); - if (ret) - return -EIO; - - if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) { - MHI_LOG("RDDM successfully collected\n"); - return 0; - } - - udelay(delayus); - } - - ee = mhi_get_exec_env(mhi_cntrl); - ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status); - - MHI_ERR("Did not complete RDDM transfer\n"); - MHI_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee)); - MHI_ERR("RXVEC_STATUS:0x%x, ret:%d\n", rx_status, ret); - - return -EIO; -} - -/* download ramdump image from device */ -int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) -{ - void __iomem *base = mhi_cntrl->bhi; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - struct image_info *rddm_image = mhi_cntrl->rddm_image; - struct mhi_buf *mhi_buf; - int ret; - u32 rx_status; - u32 sequence_id; - - if (!rddm_image) - return -ENOMEM; - - if (in_panic) - return __mhi_download_rddm_in_panic(mhi_cntrl); - - MHI_LOG("Waiting for device to enter RDDM state from EE:%s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_RDDM || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI is not in valid state, pm_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - return -EIO; - } - - mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); - - /* vector table is the last entry */ - mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; - - read_lock_bh(pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_unlock_bh(pm_lock); - return -EIO; - } - - MHI_LOG("Starting BHIe Programming for RDDM\n"); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, - upper_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, - lower_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); - - sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; - mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, - BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, - sequence_id); - read_unlock_bh(pm_lock); - - MHI_LOG("Upper:0x%x Lower:0x%x len:0x%zx sequence:%u\n", - upper_32_bits(mhi_buf->dma_addr), - lower_32_bits(mhi_buf->dma_addr), - mhi_buf->len, sequence_id); - MHI_LOG("Waiting for image download completion\n"); - - /* waiting for image download completion */ - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, - BHIE_RXVECSTATUS_OFFS, - BHIE_RXVECSTATUS_STATUS_BMSK, - BHIE_RXVECSTATUS_STATUS_SHFT, - &rx_status) || rx_status, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO; -} -EXPORT_SYMBOL(mhi_download_rddm_img); - -static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl, - const struct mhi_buf *mhi_buf) -{ - void __iomem *base = mhi_cntrl->bhi; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - u32 tx_status; - - read_lock_bh(pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_unlock_bh(pm_lock); - return -EIO; - } - - MHI_LOG("Starting BHIe Programming\n"); - - mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_HIGH_OFFS, - upper_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_LOW_OFFS, - lower_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len); - - mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK; - mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS, - BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, - mhi_cntrl->sequence_id); - read_unlock_bh(pm_lock); - - MHI_LOG("Upper:0x%x Lower:0x%x len:0x%zx sequence:%u\n", - upper_32_bits(mhi_buf->dma_addr), - lower_32_bits(mhi_buf->dma_addr), - mhi_buf->len, mhi_cntrl->sequence_id); - MHI_LOG("Waiting for image transfer completion\n"); - - /* waiting for image download completion */ - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, - BHIE_TXVECSTATUS_OFFS, - BHIE_TXVECSTATUS_STATUS_BMSK, - BHIE_TXVECSTATUS_STATUS_SHFT, - &tx_status) || tx_status, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - return (tx_status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO; -} - -static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, - void *buf, - size_t size) -{ - u32 tx_status, val; - int i, ret; - void __iomem *base = mhi_cntrl->bhi; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - dma_addr_t phys = dma_map_single(mhi_cntrl->dev, buf, size, - DMA_TO_DEVICE); - struct { - char *name; - u32 offset; - } error_reg[] = { - { "ERROR_CODE", BHI_ERRCODE }, - { "ERROR_DBG1", BHI_ERRDBG1 }, - { "ERROR_DBG2", BHI_ERRDBG2 }, - { "ERROR_DBG3", BHI_ERRDBG3 }, - { NULL }, - }; - - if (dma_mapping_error(mhi_cntrl->dev, phys)) - return -ENOMEM; - - MHI_LOG("Starting BHI programming\n"); - - /* program start sbl download via bhi protocol */ - read_lock_bh(pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_unlock_bh(pm_lock); - goto invalid_pm_state; - } - - mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, upper_32_bits(phys)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, lower_32_bits(phys)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size); - mhi_cntrl->session_id = prandom_u32() & BHI_TXDB_SEQNUM_BMSK; - mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, mhi_cntrl->session_id); - read_unlock_bh(pm_lock); - - MHI_LOG("Waiting for image transfer completion\n"); - - /* waiting for image download completion */ - wait_event_timeout(mhi_cntrl->state_event, - /*MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||*/ - mhi_read_reg_field(mhi_cntrl, base, BHI_STATUS, - BHI_STATUS_MASK, BHI_STATUS_SHIFT, - &tx_status) || tx_status, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - #if 0 - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - goto invalid_pm_state; - #endif - - MHI_LOG("image transfer status:%d\n", tx_status); - - if (tx_status == BHI_STATUS_ERROR) { - MHI_ERR("Image transfer failed\n"); - read_lock_bh(pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - for (i = 0; error_reg[i].name; i++) { - ret = mhi_read_reg(mhi_cntrl, base, - error_reg[i].offset, &val); - if (ret) - break; - MHI_ERR("reg:%s value:0x%x\n", - error_reg[i].name, val); - } - } - read_unlock_bh(pm_lock); - goto invalid_pm_state; - } - - dma_unmap_single(mhi_cntrl->dev, phys, size, DMA_TO_DEVICE); - - return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT; - -invalid_pm_state: - dma_unmap_single(mhi_cntrl->dev, phys, size, DMA_TO_DEVICE); - - return -EIO; -} - -void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info *image_info) -{ - int i; - struct mhi_buf *mhi_buf = image_info->mhi_buf; - - for (i = 0; i < image_info->entries; i++, mhi_buf++) - mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf, - mhi_buf->dma_addr); - - kfree(image_info->mhi_buf); - kfree(image_info); -} - -int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info **image_info, - size_t alloc_size) -{ - size_t seg_size = mhi_cntrl->seg_len; - /* requier additional entry for vec table */ - int segments = DIV_ROUND_UP(alloc_size, seg_size) + 1; - int i; - struct image_info *img_info; - struct mhi_buf *mhi_buf; - - MHI_LOG("Allocating bytes:%zu seg_size:%zu total_seg:%u\n", - alloc_size, seg_size, segments); - - img_info = kzalloc(sizeof(*img_info), GFP_KERNEL); - if (!img_info) - return -ENOMEM; - - /* allocate memory for entries */ - img_info->mhi_buf = kcalloc(segments, sizeof(*img_info->mhi_buf), - GFP_KERNEL); - if (!img_info->mhi_buf) - goto error_alloc_mhi_buf; - - /* allocate and populate vector table */ - mhi_buf = img_info->mhi_buf; - for (i = 0; i < segments; i++, mhi_buf++) { - size_t vec_size = seg_size; - - /* last entry is for vector table */ - if (i == segments - 1) - vec_size = sizeof(struct __packed bhi_vec_entry) * i; - - mhi_buf->len = vec_size; - mhi_buf->buf = mhi_alloc_coherent(mhi_cntrl, vec_size, - &mhi_buf->dma_addr, GFP_KERNEL); - if (!mhi_buf->buf) - goto error_alloc_segment; - - MHI_LOG("Entry:%d Address:0x%llx size:%zd\n", i, - (u64)mhi_buf->dma_addr, mhi_buf->len); - } - - img_info->bhi_vec = img_info->mhi_buf[segments - 1].buf; - img_info->entries = segments; - *image_info = img_info; - - MHI_LOG("Successfully allocated bhi vec table\n"); - - return 0; - -error_alloc_segment: - for (--i, --mhi_buf; i >= 0; i--, mhi_buf--) - mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf, - mhi_buf->dma_addr); - -error_alloc_mhi_buf: - kfree(img_info); - - return -ENOMEM; -} - -static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl, - const struct firmware *firmware, - struct image_info *img_info) -{ - size_t remainder = firmware->size; - size_t to_cpy; - const u8 *buf = firmware->data; - int i = 0; - struct mhi_buf *mhi_buf = img_info->mhi_buf; - struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; - - while (remainder) { - MHI_ASSERT(i >= img_info->entries, "malformed vector table"); - - to_cpy = min(remainder, mhi_buf->len); - memcpy(mhi_buf->buf, buf, to_cpy); - bhi_vec->dma_addr = mhi_buf->dma_addr; - bhi_vec->size = to_cpy; - - MHI_VERB("Setting Vector:0x%llx size: %llu\n", - bhi_vec->dma_addr, bhi_vec->size); - buf += to_cpy; - remainder -= to_cpy; - i++; - bhi_vec++; - mhi_buf++; - } -} - -void mhi_fw_load_worker(struct work_struct *work) -{ - int ret; - struct mhi_controller *mhi_cntrl; - const char *fw_name; - const struct firmware *firmware; - struct image_info *image_info; - void *buf; - size_t size; - - mhi_cntrl = container_of(work, struct mhi_controller, fw_worker); - - MHI_LOG("Waiting for device to enter PBL from EE:%s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - ret = wait_event_timeout(mhi_cntrl->state_event, - MHI_IN_PBL(mhi_cntrl->ee) || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI is not in valid state\n"); - return; - } - - MHI_LOG("Device current EE:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - /* if device in pthru, we do not have to load firmware */ - if (mhi_cntrl->ee == MHI_EE_PT) - return; - - fw_name = (mhi_cntrl->ee == MHI_EE_EDL) ? - mhi_cntrl->edl_image : mhi_cntrl->fw_image; - - if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size || - !mhi_cntrl->seg_len))) { - MHI_ERR("No firmware image defined or !sbl_size || !seg_len\n"); - return; - } - - ret = request_firmware(&firmware, fw_name, mhi_cntrl->dev); - if (ret) { - MHI_ERR("Error loading firmware, ret:%d\n", ret); - return; - } - - size = (mhi_cntrl->fbc_download) ? mhi_cntrl->sbl_size : firmware->size; - - /* the sbl size provided is maximum size, not necessarily image size */ - if (size > firmware->size) - size = firmware->size; - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) { - MHI_ERR("Could not allocate memory for image\n"); - release_firmware(firmware); - return; - } - - /* load sbl image */ - memcpy(buf, firmware->data, size); - ret = mhi_fw_load_sbl(mhi_cntrl, buf, size); - kfree(buf); - - if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL) - release_firmware(firmware); - - /* error or in edl, we're done */ - if (ret || mhi_cntrl->ee == MHI_EE_EDL) - return; - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_RESET; - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* - * if we're doing fbc, populate vector tables while - * device transitioning into MHI READY state - */ - if (mhi_cntrl->fbc_download) { - ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, - firmware->size); - if (ret) { - MHI_ERR("Error alloc size of %zu\n", firmware->size); - goto error_alloc_fw_table; - } - - MHI_LOG("Copying firmware image into vector table\n"); - - /* load the firmware into BHIE vec table */ - mhi_firmware_copy(mhi_cntrl, firmware, mhi_cntrl->fbc_image); - } - - /* transitioning into MHI RESET->READY state */ - ret = mhi_ready_state_transition(mhi_cntrl); - - MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - if (!mhi_cntrl->fbc_download) - return; - - if (ret) { - MHI_ERR("Did not transition to READY state\n"); - goto error_read; - } - - /* wait for BHIE event */ - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_BHIE || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI did not enter BHIE\n"); - goto error_read; - } - - /* start full firmware image download */ - image_info = mhi_cntrl->fbc_image; - ret = mhi_fw_load_amss(mhi_cntrl, - /* last entry is vec table */ - &image_info->mhi_buf[image_info->entries - 1]); - - MHI_LOG("amss fw_load, ret:%d\n", ret); - - release_firmware(firmware); - - return; - -error_read: - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - -error_alloc_fw_table: - release_firmware(firmware); -} - -int BhiWrite(struct mhi_controller *mhi_cntrl, void *buf, size_t size) -{ - int ret; - - MHI_LOG("Device current EE:%s,%d M:%s\n", - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)), - mhi_cntrl->ee, - TO_MHI_STATE_STR(mhi_get_m_state(mhi_cntrl))); - - mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); - - if (!MHI_IN_PBL(mhi_cntrl->ee)/* || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)*/) { - MHI_ERR("MHI is not in valid BHI state:%d\n", mhi_cntrl->ee); - return -EINVAL; - } - - if (mhi_cntrl->ee != MHI_EE_EDL) - return 0; - - ret = mhi_fw_load_sbl(mhi_cntrl, buf, size); - - if (ret) { - MHI_ERR("ret = %d, ee=%d\n", ret, mhi_cntrl->ee); - goto error_state; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_RESET; - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* transitioning into MHI RESET->READY state */ - ret = mhi_ready_state_transition(mhi_cntrl); - if (ret) { - MHI_ERR("Did not transition to READY state\n"); - goto error_state; - } - - MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - /* wait for BHIE event */ - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_FP || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI did not enter Flash Programmer Environment\n"); - goto error_state; - } - - MHI_LOG("MHI enter Flash Programmer Environment\n"); - return 0; - -error_state: - MHI_LOG("Device current EE:%s, M:%s\n", - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)), - TO_MHI_STATE_STR(mhi_get_m_state(mhi_cntrl))); - - return ret; -} - -static int mhi_cntrl_open(struct inode *inode, struct file *f) -{ - return 0; -} - -static int mhi_cntrl_release(struct inode *inode, struct file *f) -{ - return 0; -} - -static long mhi_cntrl_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) -{ - long ret = -EINVAL; - void *ubuf = (void *)__arg; - struct miscdevice *c = (struct miscdevice *)f->private_data; - struct mhi_controller *mhi_cntrl = container_of(c, struct mhi_controller, miscdev); - - switch (cmd) { - case IOCTL_BHI_GETDEVINFO: - { - BHI_INFO_TYPE bhi_info; - ret = BhiRead(mhi_cntrl, &bhi_info); - if (ret) { - MHI_ERR("IOCTL_BHI_GETDEVINFO BhiRead error, ret = %ld\n", ret); - return ret; - } - - ret = copy_to_user(ubuf, &bhi_info, sizeof(bhi_info)); - if (ret) { - MHI_ERR("IOCTL_BHI_GETDEVINFO copy error, ret = %ld\n", ret); - } - } - break; - - case IOCTL_BHI_WRITEIMAGE: - { - void *buf; - size_t size; - - ret = copy_from_user(&size, ubuf, sizeof(size)); - if (ret) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, ret = %ld\n", ret); - return ret; - } - - buf = kmalloc(size, GFP_KERNEL); - if (buf == NULL) { - return -ENOMEM; - } - - ret = copy_from_user(buf, ubuf+sizeof(size), size); - if (ret) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE copy buf error, ret = %ld\n", ret); - kfree(buf); - return ret; - } - - ret = BhiWrite(mhi_cntrl, buf, size); - if (ret) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE BhiWrite error, ret = %ld\n", ret); - } - kfree(buf); - } - break; - - default: - break; - } - - return ret; -} - -static const struct file_operations mhi_cntrl_fops = { - .unlocked_ioctl = mhi_cntrl_ioctl, - .open = mhi_cntrl_open, - .release = mhi_cntrl_release, -}; - -int mhi_cntrl_register_miscdev(struct mhi_controller *mhi_cntrl) -{ - mhi_cntrl->miscdev.minor = MISC_DYNAMIC_MINOR; - mhi_cntrl->miscdev.name = "mhi_BHI"; - mhi_cntrl->miscdev.fops = &mhi_cntrl_fops; - - return misc_register(&mhi_cntrl->miscdev); -} - -void mhi_cntrl_deregister_miscdev(struct mhi_controller *mhi_cntrl) -{ - misc_deregister(&mhi_cntrl->miscdev); -} diff --git a/fibocom_MHI/src/core/mhi_common.h b/fibocom_MHI/src/core/mhi_common.h deleted file mode 100644 index a554604..0000000 --- a/fibocom_MHI/src/core/mhi_common.h +++ /dev/null @@ -1,362 +0,0 @@ -#ifndef __MHI_COMMON_H -#define __MHI_COMMON_H - -#include - -/* MHI control data structures alloted by the host, including - * channel context array, event context array, command context and rings */ - -/* Channel context state */ -enum mhi_dev_ch_ctx_state { - MHI_DEV_CH_STATE_DISABLED, - MHI_DEV_CH_STATE_ENABLED, - MHI_DEV_CH_STATE_RUNNING, - MHI_DEV_CH_STATE_SUSPENDED, - MHI_DEV_CH_STATE_STOP, - MHI_DEV_CH_STATE_ERROR, - MHI_DEV_CH_STATE_RESERVED, - MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF -}; - -/* Channel type */ -enum mhi_dev_ch_ctx_type { - MHI_DEV_CH_TYPE_NONE, - MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL, - MHI_DEV_CH_TYPE_INBOUND_CHANNEL, - MHI_DEV_CH_RESERVED -}; - -/* Channel context type */ -struct mhi_dev_ch_ctx { - enum mhi_dev_ch_ctx_state ch_state; - enum mhi_dev_ch_ctx_type ch_type; - uint32_t err_indx; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -enum mhi_dev_ring_element_type_id { - MHI_DEV_RING_EL_INVALID = 0, - MHI_DEV_RING_EL_NOOP = 1, - MHI_DEV_RING_EL_TRANSFER = 2, - MHI_DEV_RING_EL_RESET = 16, - MHI_DEV_RING_EL_STOP = 17, - MHI_DEV_RING_EL_START = 18, - MHI_DEV_RING_EL_MHI_STATE_CHG = 32, - MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33, - MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34, - MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64, - MHI_DEV_RING_EL_UNDEF -}; - -enum mhi_dev_ring_state { - RING_STATE_UINT = 0, - RING_STATE_IDLE, - RING_STATE_PENDING, -}; - -enum mhi_dev_ring_type { - RING_TYPE_CMD = 0, - RING_TYPE_ER, - RING_TYPE_CH, - RING_TYPE_INVAL -}; - -/* Event context interrupt moderation */ -enum mhi_dev_evt_ctx_int_mod_timer { - MHI_DEV_EVT_INT_MODERATION_DISABLED -}; - -/* Event ring type */ -enum mhi_dev_evt_ctx_event_ring_type { - MHI_DEV_EVT_TYPE_DEFAULT, - MHI_DEV_EVT_TYPE_VALID, - MHI_DEV_EVT_RESERVED -}; - -/* Event ring context type */ -struct mhi_dev_ev_ctx { - uint32_t res1:16; - enum mhi_dev_evt_ctx_int_mod_timer intmodt:16; - enum mhi_dev_evt_ctx_event_ring_type ertype; - uint32_t msivec; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Command context */ -struct mhi_dev_cmd_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* generic context */ -struct mhi_dev_gen_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Transfer ring element */ -struct mhi_dev_transfer_ring_element { - uint64_t data_buf_ptr; - uint32_t len:16; - uint32_t res1:16; - uint32_t chain:1; - uint32_t res2:7; - uint32_t ieob:1; - uint32_t ieot:1; - uint32_t bei:1; - uint32_t res3:5; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res4:8; -} __packed; - -/* Command ring element */ -/* Command ring No op command */ -struct mhi_dev_cmd_ring_op { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring reset channel command */ -struct mhi_dev_cmd_ring_reset_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring stop channel command */ -struct mhi_dev_cmd_ring_stop_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring start channel command */ -struct mhi_dev_cmd_ring_start_channel_cmd { - uint64_t res1; - uint32_t seqnum; - uint32_t reliable:1; - uint32_t res2:15; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -enum mhi_dev_cmd_completion_code { - MHI_CMD_COMPL_CODE_INVALID = 0, - MHI_CMD_COMPL_CODE_SUCCESS = 1, - MHI_CMD_COMPL_CODE_EOT = 2, - MHI_CMD_COMPL_CODE_OVERFLOW = 3, - MHI_CMD_COMPL_CODE_EOB = 4, - MHI_CMD_COMPL_CODE_UNDEFINED = 16, - MHI_CMD_COMPL_CODE_RING_EL = 17, - MHI_CMD_COMPL_CODE_RES -}; - -/* Event ring elements */ -/* Transfer completion event */ -struct mhi_dev_event_ring_transfer_completion { - uint64_t ptr; - uint32_t len:16; - uint32_t res1:8; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command completion event */ -struct mhi_dev_event_ring_cmd_completion { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_state { - MHI_DEV_RESET_STATE = 0, - MHI_DEV_READY_STATE, - MHI_DEV_M0_STATE, - MHI_DEV_M1_STATE, - MHI_DEV_M2_STATE, - MHI_DEV_M3_STATE, - MHI_DEV_MAX_STATE, - MHI_DEV_SYSERR_STATE = 0xff -}; - -/* MHI state change event */ -struct mhi_dev_event_ring_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_state mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_execenv { - MHI_DEV_SBL_EE = 1, - MHI_DEV_AMSS_EE = 2, - MHI_DEV_UNRESERVED -}; - -/* EE state change event */ -struct mhi_dev_event_ring_ee_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_execenv execenv:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -/* Generic cmd to parse common details like type and channel id */ -struct mhi_dev_ring_generic { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_state mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -struct mhi_config { - uint32_t mhi_reg_len; - uint32_t version; - uint32_t event_rings; - uint32_t channels; - uint32_t chdb_offset; - uint32_t erdb_offset; -}; - -#define NUM_CHANNELS 128 -#define HW_CHANNEL_BASE 100 -#define HW_CHANNEL_END 107 -#define MHI_ENV_VALUE 2 -#define MHI_MASK_ROWS_CH_EV_DB 4 -#define TRB_MAX_DATA_SIZE 8192 -#define MHI_CTRL_STATE 25 -#define IPA_DMA_SYNC 1 -#define IPA_DMA_ASYNC 0 - -/*maximum trasnfer completion events buffer*/ -#define MAX_TR_EVENTS 50 -/*maximum event requests */ -#define MHI_MAX_EVT_REQ 50 - -/* Possible ring element types */ -union mhi_dev_ring_element_type { - struct mhi_dev_cmd_ring_op cmd_no_op; - struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset; - struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop; - struct mhi_dev_cmd_ring_start_channel_cmd cmd_start; - struct mhi_dev_transfer_ring_element tre; - struct mhi_dev_event_ring_transfer_completion evt_tr_comp; - struct mhi_dev_event_ring_cmd_completion evt_cmd_comp; - struct mhi_dev_event_ring_state_change evt_state_change; - struct mhi_dev_event_ring_ee_state_change evt_ee_state; - struct mhi_dev_ring_generic generic; -}; - -/* Transfer ring element type */ -union mhi_dev_ring_ctx { - struct mhi_dev_cmd_ctx cmd; - struct mhi_dev_ev_ctx ev; - struct mhi_dev_ch_ctx ch; - struct mhi_dev_gen_ctx generic; -}; - -/* MHI host Control and data address region */ -struct mhi_host_addr { - uint32_t ctrl_base_lsb; - uint32_t ctrl_base_msb; - uint32_t ctrl_limit_lsb; - uint32_t ctrl_limit_msb; - uint32_t data_base_lsb; - uint32_t data_base_msb; - uint32_t data_limit_lsb; - uint32_t data_limit_msb; -}; - -/* MHI physical and virtual address region */ -struct mhi_meminfo { - struct device *dev; - uintptr_t pa_aligned; - uintptr_t pa_unaligned; - uintptr_t va_aligned; - uintptr_t va_unaligned; - uintptr_t size; -}; - -struct mhi_addr { - uint64_t host_pa; - uintptr_t device_pa; - uintptr_t device_va; - size_t size; - dma_addr_t phy_addr; - void *virt_addr; - bool use_ipa_dma; -}; - -struct mhi_interrupt_state { - uint32_t mask; - uint32_t status; -}; - -enum mhi_dev_channel_state { - MHI_DEV_CH_UNINT, - MHI_DEV_CH_STARTED, - MHI_DEV_CH_PENDING_START, - MHI_DEV_CH_PENDING_STOP, - MHI_DEV_CH_STOPPED, - MHI_DEV_CH_CLOSED, -}; - -enum mhi_dev_ch_operation { - MHI_DEV_OPEN_CH, - MHI_DEV_CLOSE_CH, - MHI_DEV_READ_CH, - MHI_DEV_READ_WR, - MHI_DEV_POLL, -}; - -enum mhi_ctrl_info { - MHI_STATE_CONFIGURED = 0, - MHI_STATE_CONNECTED = 1, - MHI_STATE_DISCONNECTED = 2, - MHI_STATE_INVAL, -}; - -enum mhi_dev_tr_compl_evt_type { - SEND_EVENT_BUFFER, - SEND_EVENT_RD_OFFSET, -}; - -enum mhi_dev_transfer_type { - MHI_DEV_DMA_SYNC, - MHI_DEV_DMA_ASYNC, -}; -#endif /* _MHI_COMMON_H_ */ diff --git a/fibocom_MHI/src/core/mhi_dtr.c b/fibocom_MHI/src/core/mhi_dtr.c deleted file mode 100644 index 3651ee1..0000000 --- a/fibocom_MHI/src/core/mhi_dtr.c +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -struct __packed dtr_ctrl_msg { - u32 preamble; - u32 msg_id; - u32 dest_id; - u32 size; - u32 msg; -}; - -#define CTRL_MAGIC (0x4C525443) -#define CTRL_MSG_DTR BIT(0) -#define CTRL_MSG_ID (0x10) - -static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, - u32 tiocm) -{ - struct dtr_ctrl_msg *dtr_msg = NULL; - struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan; - int ret = 0; - - tiocm &= TIOCM_DTR; - if (mhi_chan->tiocm == tiocm) - return 0; - - mutex_lock(&dtr_chan->mutex); - - dtr_msg = kzalloc(sizeof(*dtr_msg), GFP_KERNEL); - if (!dtr_msg) { - ret = -ENOMEM; - goto tiocm_exit; - } - - dtr_msg->preamble = CTRL_MAGIC; - dtr_msg->msg_id = CTRL_MSG_ID; - dtr_msg->dest_id = mhi_chan->chan; - dtr_msg->size = sizeof(u32); - if (tiocm & TIOCM_DTR) - dtr_msg->msg |= CTRL_MSG_DTR; - - reinit_completion(&dtr_chan->completion); - ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg, - sizeof(*dtr_msg), MHI_EOT); - if (ret) - goto tiocm_exit; - - ret = wait_for_completion_timeout(&dtr_chan->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret) { - MHI_ERR("Failed to receive transfer callback\n"); - ret = -EIO; - goto tiocm_exit; - } - - ret = 0; - mhi_chan->tiocm = tiocm; - -tiocm_exit: - kfree(dtr_msg); - mutex_unlock(&dtr_chan->mutex); - - return ret; -} - -long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan = mhi_dev->ul_chan; - int ret; - - /* ioctl not supported by this controller */ - if (!mhi_cntrl->dtr_dev) - return -EIO; - - switch (cmd) { - case TIOCMGET: - return mhi_chan->tiocm; - case TIOCMSET: - { - u32 tiocm; - - ret = get_user(tiocm, (u32 *)arg); - if (ret) - return ret; - - return mhi_dtr_tiocmset(mhi_cntrl, mhi_chan, tiocm); - } - default: - break; - } - - return -EINVAL; -} -EXPORT_SYMBOL(mhi_ioctl); - -static void mhi_dtr_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan; - - MHI_VERB("Received with status:%d\n", mhi_result->transaction_status); - if (!mhi_result->transaction_status) - complete(&dtr_chan->completion); -} - -static void mhi_dtr_remove(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - mhi_cntrl->dtr_dev = NULL; -} - -static int mhi_dtr_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - int ret; - - MHI_LOG("Enter for DTR control channel\n"); - - ret = mhi_prepare_for_transfer(mhi_dev); - if (!ret) - mhi_cntrl->dtr_dev = mhi_dev; - - MHI_LOG("Exit with ret:%d\n", ret); - - return ret; -} - -static const struct mhi_device_id mhi_dtr_table[] = { - { .chan = "IP_CTRL" }, - { }, -}; - -static struct mhi_driver mhi_dtr_driver = { - .id_table = mhi_dtr_table, - .remove = mhi_dtr_remove, - .probe = mhi_dtr_probe, - .ul_xfer_cb = mhi_dtr_xfer_cb, - .dl_xfer_cb = mhi_dtr_xfer_cb, - .driver = { - .name = "MHI_DTR", - .owner = THIS_MODULE, - } -}; - -int __init mhi_dtr_init(void) -{ - return mhi_driver_register(&mhi_dtr_driver); -} - -void mhi_dtr_exit(void) { - mhi_driver_unregister(&mhi_dtr_driver); -} diff --git a/fibocom_MHI/src/core/mhi_init.c b/fibocom_MHI/src/core/mhi_init.c deleted file mode 100644 index d976411..0000000 --- a/fibocom_MHI/src/core/mhi_init.c +++ /dev/null @@ -1,1442 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -const char * const mhi_ee_str[MHI_EE_MAX] = { - [MHI_EE_PBL] = "PBL", - [MHI_EE_SBL] = "SBL", - [MHI_EE_AMSS] = "AMSS", - [MHI_EE_RDDM] = "RDDM", - [MHI_EE_WFW] = "WFW", - [MHI_EE_PT] = "PASS THRU", - [MHI_EE_EDL] = "EDL", - [MHI_EE_FP] = "FlashProg", - [MHI_EE_UEFI] = "UEFI", - [MHI_EE_DISABLE_TRANSITION] = "RESET", -}; - -const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX] = { - [MHI_ST_TRANSITION_PBL] = "PBL", - [MHI_ST_TRANSITION_READY] = "READY", - [MHI_ST_TRANSITION_SBL] = "SBL", - [MHI_ST_TRANSITION_AMSS] = "AMSS", - [MHI_ST_TRANSITION_FP] = "FlashProg", - [MHI_ST_TRANSITION_BHIE] = "BHIE", -}; - -const char * const mhi_state_str[MHI_STATE_MAX] = { - [MHI_STATE_RESET] = "RESET", - [MHI_STATE_READY] = "READY", - [MHI_STATE_M0] = "M0", - [MHI_STATE_M1] = "M1", - [MHI_STATE_M2] = "M2", - [MHI_STATE_M3] = "M3", - [MHI_STATE_D3] = "D3", - [MHI_STATE_BHI] = "BHI", - [MHI_STATE_SYS_ERR] = "SYS_ERR", -}; - -static const char * const mhi_pm_state_str[] = { - "DISABLE", - "POR", - "M0", - "M1", - "M1->M2", - "M2", - "M?->M3", - "M3", - "M3->M0", - "FW DL Error", - "SYS_ERR Detect", - "SYS_ERR Process", - "SHUTDOWN Process", - "LD or Error Fatal Detect", -}; - -struct mhi_bus mhi_bus; - -const char *to_mhi_pm_state_str(enum MHI_PM_STATE state) -{ - int index = find_last_bit((unsigned long *)&state, 32); - - if (index >= ARRAY_SIZE(mhi_pm_state_str)) - return "Invalid State"; - - return mhi_pm_state_str[index]; -} - -static void mhi_ring_aligned_check(struct mhi_controller *mhi_cntrl, u64 rbase, u64 rlen) { - uint64_t ra; - - ra = rbase; - do_div(ra, roundup_pow_of_two(rlen)); - - if (rbase != ra * roundup_pow_of_two(rlen)) { - MHI_ERR("bad params ring base not aligned 0x%llx align 0x%lx\n", rbase, roundup_pow_of_two(rlen)); - } -} - -void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - MHI_LOG("enter\n"); - - if (mhi_cntrl->msi_allocated == 1) { - free_irq(mhi_cntrl->irq[0], mhi_event); - return; - } - - - free_irq(mhi_cntrl->irq[0], mhi_cntrl); - - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - free_irq(mhi_cntrl->irq[mhi_event->msi], mhi_event); - } -} - -int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl) -{ - int i; - int ret; - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - - if (mhi_cntrl->msi_allocated == 1) { - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - mhi_event->msi = 0; - } - - ret = request_irq(mhi_cntrl->irq[0], - mhi_msi_handlr, IRQF_SHARED, "mhi", mhi_cntrl->mhi_event); - if (ret) { - MHI_ERR("Error requesting irq:%d, ret=%d\n", mhi_cntrl->irq[0], ret); - } - return ret; - } - - /* for BHI INTVEC msi */ - ret = request_threaded_irq(mhi_cntrl->irq[0], mhi_intvec_handlr, - mhi_intvec_threaded_handlr, IRQF_ONESHOT, - "mhi", mhi_cntrl); - if (ret) - return ret; - - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - ret = request_irq(mhi_cntrl->irq[mhi_event->msi], - mhi_msi_handlr, IRQF_SHARED, "mhi", - mhi_event); - if (ret) { - MHI_ERR("Error requesting irq:%d for ev:%d\n", - mhi_cntrl->irq[mhi_event->msi], i); - goto error_request; - } - } - - return 0; - -error_request: - for (--i, --mhi_event; i >= 0; i--, mhi_event--) { - if (mhi_event->offload_ev) - continue; - - free_irq(mhi_cntrl->irq[mhi_event->msi], mhi_event); - } - free_irq(mhi_cntrl->irq[0], mhi_cntrl); - - return ret; -} - -void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_ctxt *mhi_ctxt = mhi_cntrl->mhi_ctxt; - struct mhi_cmd *mhi_cmd; - struct mhi_event *mhi_event; - struct mhi_ring *ring; - MHI_LOG("enter\n"); - - mhi_cmd = mhi_cntrl->mhi_cmd; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++) { - ring = &mhi_cmd->ring; - - ring->base = NULL; - ring->iommu_base = 0; - } - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - ring = &mhi_event->ring; - - ring->base = NULL; - ring->iommu_base = 0; - } - - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->ctrl_seg), mhi_ctxt->ctrl_seg, mhi_ctxt->ctrl_seg_addr); - - mhi_cntrl->mhi_ctxt = NULL; -} - -static int mhi_init_debugfs_mhi_states_open(struct inode *inode, - struct file *fp) -{ - return single_open(fp, mhi_debugfs_mhi_states_show, inode->i_private); -} - -static int mhi_init_debugfs_mhi_event_open(struct inode *inode, struct file *fp) -{ - return single_open(fp, mhi_debugfs_mhi_event_show, inode->i_private); -} - -static int mhi_init_debugfs_mhi_chan_open(struct inode *inode, struct file *fp) -{ - return single_open(fp, mhi_debugfs_mhi_chan_show, inode->i_private); -} - -static const struct file_operations debugfs_state_ops = { - .open = mhi_init_debugfs_mhi_states_open, - .release = single_release, - .read = seq_read, -}; - -static const struct file_operations debugfs_ev_ops = { - .open = mhi_init_debugfs_mhi_event_open, - .release = single_release, - .read = seq_read, -}; - -static const struct file_operations debugfs_chan_ops = { - .open = mhi_init_debugfs_mhi_chan_open, - .release = single_release, - .read = seq_read, -}; - -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_reset_fops, NULL, - mhi_debugfs_trigger_reset, "%llu\n"); - -void mhi_init_debugfs(struct mhi_controller *mhi_cntrl) -{ - struct dentry *dentry; - char node[32]; - - if (!mhi_cntrl->parent) - return; - - snprintf(node, sizeof(node), "%04x_%02u:%02u.%02u", - mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus, - mhi_cntrl->slot); - - dentry = debugfs_create_dir(node, mhi_cntrl->parent); - if (IS_ERR_OR_NULL(dentry)) - return; - - debugfs_create_file("states", 0444, dentry, mhi_cntrl, - &debugfs_state_ops); - debugfs_create_file("events", 0444, dentry, mhi_cntrl, - &debugfs_ev_ops); - debugfs_create_file("chan", 0444, dentry, mhi_cntrl, &debugfs_chan_ops); - debugfs_create_file("reset", 0444, dentry, mhi_cntrl, - &debugfs_trigger_reset_fops); - mhi_cntrl->dentry = dentry; -} - -void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl) -{ - debugfs_remove_recursive(mhi_cntrl->dentry); - mhi_cntrl->dentry = NULL; -} - -int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) -{ - struct mhi_ctxt *mhi_ctxt; - struct mhi_chan_ctxt *chan_ctxt; - struct mhi_event_ctxt *er_ctxt; - struct mhi_cmd_ctxt *cmd_ctxt; - struct mhi_chan *mhi_chan; - struct mhi_event *mhi_event; - struct mhi_cmd *mhi_cmd; - int ret = -ENOMEM, i; - - atomic_set(&mhi_cntrl->dev_wake, 0); - atomic_set(&mhi_cntrl->alloc_size, 0); - - mhi_ctxt = &mhi_cntrl->data->mhi_ctxt; - - /* setup channel ctxt */ - mhi_ctxt->ctrl_seg = mhi_alloc_coherent(mhi_cntrl, sizeof(*mhi_ctxt->ctrl_seg), - &mhi_ctxt->ctrl_seg_addr, GFP_KERNEL); - if (!mhi_ctxt->ctrl_seg) - goto error_alloc_chan_ctxt; - - MHI_LOG("mhi_ctxt->ctrl_seg = %p\n", mhi_ctxt->ctrl_seg); - if ((unsigned long)mhi_ctxt->ctrl_seg & (4096-1)) { - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->ctrl_seg), mhi_ctxt->ctrl_seg, mhi_ctxt->ctrl_seg_addr); - goto error_alloc_chan_ctxt; - } - -/* -+Transfer rings -+-------------- -+MHI channels are logical, unidirectional data pipes between host and device. -+Each channel associated with a single transfer ring. The data direction can be -+either inbound (device to host) or outbound (host to device). Transfer -+descriptors are managed by using transfer rings, which are defined for each -+channel between device and host and resides in the host memory. -+ -+Transfer ring Pointer: Transfer Ring Array -+[Read Pointer (RP)] ----------->[Ring Element] } TD -+[Write Pointer (WP)]- [Ring Element] -+ - [Ring Element] -+ --------->[Ring Element] -+ [Ring Element] -+ -+1. Host allocate memory for transfer ring -+2. Host sets base, read pointer, write pointer in corresponding channel context -+3. Ring is considered empty when RP == WP -+4. Ring is considered full when WP + 1 == RP -+4. RP indicates the next element to be serviced by device -+4. When host new buffer to send, host update the Ring element with buffer information -+5. Host increment the WP to next element -+6. Ring the associated channel DB. -*/ - - mhi_ctxt->chan_ctxt = mhi_ctxt->ctrl_seg->chan_ctxt; - mhi_ctxt->chan_ctxt_addr = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, chan_ctxt); - - mhi_chan = mhi_cntrl->data->mhi_chan; - chan_ctxt = mhi_ctxt->chan_ctxt; - for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) { - /* If it's offload channel skip this step */ - if (mhi_chan->offload_ch) - continue; - - chan_ctxt->chstate = MHI_CH_STATE_DISABLED; - chan_ctxt->brstmode = mhi_chan->db_cfg.brstmode; - chan_ctxt->pollcfg = mhi_chan->db_cfg.pollcfg; - chan_ctxt->chtype = cpu_to_le32(mhi_chan->dir); - chan_ctxt->erindex = cpu_to_le32(mhi_chan->er_index); - - mhi_chan->ch_state = MHI_CH_STATE_DISABLED; - mhi_chan->tre_ring.db_addr = &chan_ctxt->wp; - } - -/* -+Event rings -+----------- -+Events from the device to host are organized in event rings and defined in event -+descriptors. Event rings are array of EDs that resides in the host memory. -+ -+Transfer ring Pointer: Event Ring Array -+[Read Pointer (RP)] ----------->[Ring Element] } ED -+[Write Pointer (WP)]- [Ring Element] -+ - [Ring Element] -+ --------->[Ring Element] -+ [Ring Element] -+ -+1. Host allocate memory for event ring -+2. Host sets base, read pointer, write pointer in corresponding channel context -+3. Both host and device has local copy of RP, WP -+3. Ring is considered empty (no events to service) when WP + 1 == RP -+4. Ring is full of events when RP == WP -+4. RP - 1 = last event device programmed -+4. When there is a new event device need to send, device update ED pointed by RP -+5. Device increment RP to next element -+6. Device trigger and interrupt -+ -+Example Operation for data transfer: -+ -+1. Host prepare TD with buffer information -+2. Host increment Chan[id].ctxt.WP -+3. Host ring channel DB register -+4. Device wakes up process the TD -+5. Device generate a completion event for that TD by updating ED -+6. Device increment Event[id].ctxt.RP -+7. Device trigger MSI to wake host -+8. Host wakes up and check event ring for completion event -+9. Host update the Event[i].ctxt.WP to indicate processed of completion event. -*/ - mhi_ctxt->er_ctxt = mhi_ctxt->ctrl_seg->er_ctxt; - mhi_ctxt->er_ctxt_addr = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, er_ctxt); - - er_ctxt = mhi_ctxt->er_ctxt; - mhi_event = mhi_cntrl->data->mhi_event; - for (i = 0; i < NUM_MHI_EVT_RINGS; i++, er_ctxt++, mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - /* it's a satellite ev, we do not touch it */ - if (mhi_event->offload_ev) - continue; - - er_ctxt->intmodc = 0; - er_ctxt->intmodt = cpu_to_le16(mhi_event->intmod); - er_ctxt->ertype = cpu_to_le32(MHI_ER_TYPE_VALID); - if (mhi_cntrl->msi_allocated == 1) { - mhi_event->msi = 0; - } - er_ctxt->msivec = cpu_to_le32(mhi_event->msi); - mhi_event->db_cfg.db_mode = true; - - ring->el_size = sizeof(struct __packed mhi_tre); - ring->len = ring->el_size * ring->elements; - - ring->alloc_size = ring->len; - - - if (i == 0) - { - ring->pre_aligned = mhi_ctxt->ctrl_seg->event_ring_0; - ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, event_ring_0); - } - else if (i == 1) - { - ring->pre_aligned = mhi_ctxt->ctrl_seg->event_ring_1; - ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, event_ring_1); - } - else if (i == 2) - { - ring->pre_aligned = mhi_ctxt->ctrl_seg->event_ring_2; - ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, event_ring_2); - } - - ring->iommu_base = ring->dma_handle; - ring->base = ring->pre_aligned + (ring->iommu_base - ring->dma_handle); - - ring->rp = ring->wp = ring->base; - er_ctxt->rbase = cpu_to_le64(ring->iommu_base); - er_ctxt->rp = er_ctxt->wp = er_ctxt->rbase; - er_ctxt->rlen = cpu_to_le64(ring->len); - ring->ctxt_wp = &er_ctxt->wp; - - mhi_ring_aligned_check(mhi_cntrl, er_ctxt->rbase, er_ctxt->rlen); - memset(ring->base, 0xCC, ring->len); - } - - mhi_ctxt->cmd_ctxt = mhi_ctxt->ctrl_seg->cmd_ctxt; - mhi_ctxt->cmd_ctxt_addr = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, cmd_ctxt); - - mhi_cmd = mhi_cntrl->data->mhi_cmd; - cmd_ctxt = mhi_ctxt->cmd_ctxt; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++, cmd_ctxt++) { - struct mhi_ring *ring = &mhi_cmd->ring; - - ring->el_size = sizeof(struct __packed mhi_tre); - ring->elements = CMD_EL_PER_RING; - ring->len = ring->el_size * ring->elements; - - ring->alloc_size = ring->len; - ring->pre_aligned = mhi_ctxt->ctrl_seg->cmd_ring[i]; - ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, cmd_ring[i]); - ring->iommu_base = ring->dma_handle; - ring->base = ring->pre_aligned + (ring->iommu_base - ring->dma_handle); - - ring->rp = ring->wp = ring->base; - cmd_ctxt->rbase = cpu_to_le64(ring->iommu_base); - cmd_ctxt->rp = cmd_ctxt->wp = cmd_ctxt->rbase; - cmd_ctxt->rlen = cpu_to_le64(ring->len); - ring->ctxt_wp = &cmd_ctxt->wp; - - mhi_ring_aligned_check(mhi_cntrl, cmd_ctxt->rbase, cmd_ctxt->rlen); - } - - mhi_cntrl->mhi_ctxt = mhi_ctxt; - - return 0; - -error_alloc_chan_ctxt: - - return ret; -} - -int mhi_init_mmio(struct mhi_controller *mhi_cntrl) -{ - u32 val; - int i, ret; - struct mhi_chan *mhi_chan; - struct mhi_event *mhi_event; - void __iomem *base = mhi_cntrl->regs; - struct { - u32 offset; - u32 mask; - u32 shift; - u32 val; - } reg_info[] = { - { - CCABAP_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr), - }, - { - CCABAP_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr), - }, - { - ECABAP_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr), - }, - { - ECABAP_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr), - }, - { - CRCBAP_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr), - }, - { - CRCBAP_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr), - }, - - { - MHICTRLBASE_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->iova_start), - }, - { - MHICTRLBASE_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->iova_start), - }, - { - MHIDATABASE_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->iova_start), - }, - { - MHIDATABASE_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->iova_start), - }, - { - MHICTRLLIMIT_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->iova_stop), - }, - { - MHICTRLLIMIT_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->iova_stop), - }, - { - MHIDATALIMIT_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->iova_stop), - }, - { - MHIDATALIMIT_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->iova_stop), - }, - { 0, 0, 0 } - }; - - MHI_LOG("Initializing MMIO\n"); - - MHI_LOG("iova_start = %llx, iova_stop = %llx\n", (u64)mhi_cntrl->iova_start, (u64)mhi_cntrl->iova_stop); - MHI_LOG("cmd_ctxt_addr = %llx\n", (u64)mhi_cntrl->mhi_ctxt->cmd_ctxt_addr); - MHI_LOG("chan_ctxt_addr = %llx\n", (u64)mhi_cntrl->mhi_ctxt->chan_ctxt_addr); - MHI_LOG("er_ctxt_addr = %llx\n", (u64)mhi_cntrl->mhi_ctxt->er_ctxt_addr); - - /* set up DB register for all the chan rings */ - ret = mhi_read_reg_field(mhi_cntrl, base, CHDBOFF, CHDBOFF_CHDBOFF_MASK, - CHDBOFF_CHDBOFF_SHIFT, &val); - if (ret) - return -EIO; - - MHI_LOG("CHDBOFF:0x%x\n", val); - - /* setup wake db */ - mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB); - mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 4, 0); - mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 0, 0); - mhi_cntrl->wake_set = false; - - /* setup channel db addresses */ - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, val += 8, mhi_chan++) - mhi_chan->tre_ring.db_addr = base + val; - - /* setup event ring db addresses */ - ret = mhi_read_reg_field(mhi_cntrl, base, ERDBOFF, ERDBOFF_ERDBOFF_MASK, - ERDBOFF_ERDBOFF_SHIFT, &val); - if (ret) - return -EIO; - - MHI_LOG("ERDBOFF:0x%x\n", val); - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, val += 8, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - mhi_event->ring.db_addr = base + val; - } - - /* set up DB register for primary CMD rings */ - mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING].ring.db_addr = base + CRDB_LOWER; - - MHI_LOG("Programming all MMIO values.\n"); - for (i = 0; reg_info[i].offset; i++) - mhi_write_reg_field(mhi_cntrl, base, reg_info[i].offset, - reg_info[i].mask, reg_info[i].shift, - reg_info[i].val); - - return 0; -} - -void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring; - struct mhi_ring *tre_ring; - struct mhi_chan_ctxt *chan_ctxt; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan]; - - kfree(buf_ring->base); - - buf_ring->base = tre_ring->base = NULL; - chan_ctxt->rbase = cpu_to_le64(0); -} - -int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring; - struct mhi_ring *tre_ring; - struct mhi_chan_ctxt *chan_ctxt; - struct mhi_ctxt *mhi_ctxt = mhi_cntrl->mhi_ctxt; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - tre_ring->el_size = sizeof(struct __packed mhi_tre); - tre_ring->len = tre_ring->el_size * tre_ring->elements; - chan_ctxt = &mhi_ctxt->chan_ctxt[mhi_chan->chan]; - - tre_ring->alloc_size = tre_ring->len; - if (MHI_CLIENT_IP_HW_0_IN == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_ctxt->ctrl_seg->hw_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, hw_in_chan_ring[mhi_chan->ring]); - } - else if (MHI_CLIENT_IP_HW_0_OUT == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_ctxt->ctrl_seg->hw_out_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, hw_out_chan_ring[mhi_chan->ring]); - } - else if (MHI_CLIENT_DIAG_IN == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_ctxt->ctrl_seg->diag_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, diag_in_chan_ring[mhi_chan->ring]); - } - else { - tre_ring->pre_aligned = &mhi_ctxt->ctrl_seg->chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, chan_ring[mhi_chan->ring]); - } - tre_ring->iommu_base = tre_ring->dma_handle; - tre_ring->base = tre_ring->pre_aligned + (tre_ring->iommu_base - tre_ring->dma_handle); - - buf_ring->el_size = sizeof(struct mhi_buf_info); - buf_ring->len = buf_ring->el_size * buf_ring->elements; - buf_ring->base = kzalloc(buf_ring->len, GFP_KERNEL); - MHI_LOG("%d size = %zd\n", __LINE__, buf_ring->len); - - if (!buf_ring->base) { - return -ENOMEM; - } - - chan_ctxt->chstate = MHI_CH_STATE_ENABLED; - chan_ctxt->rbase = cpu_to_le64(tre_ring->iommu_base); - chan_ctxt->rp = chan_ctxt->wp = chan_ctxt->rbase; - chan_ctxt->rlen = cpu_to_le64(tre_ring->len); - tre_ring->ctxt_wp = &chan_ctxt->wp; - - tre_ring->rp = tre_ring->wp = tre_ring->base; - buf_ring->rp = buf_ring->wp = buf_ring->base; - mhi_chan->db_cfg.db_mode = 1; - - mhi_ring_aligned_check(mhi_cntrl, chan_ctxt->rbase, chan_ctxt->rlen); - /* update to all cores */ - smp_wmb(); - - return 0; -} - -int mhi_device_configure(struct mhi_device *mhi_dev, - enum dma_data_direction dir, - struct mhi_buf *cfg_tbl, - int elements) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - struct mhi_event_ctxt *er_ctxt; - struct mhi_chan_ctxt *ch_ctxt; - int er_index, chan; - - mhi_chan = (dir == DMA_TO_DEVICE) ? mhi_dev->ul_chan : mhi_dev->dl_chan; - er_index = mhi_chan->er_index; - chan = mhi_chan->chan; - - for (; elements > 0; elements--, cfg_tbl++) { - /* update event context array */ - if (!strcmp(cfg_tbl->name, "ECA")) { - er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[er_index]; - if (sizeof(*er_ctxt) != cfg_tbl->len) { - MHI_ERR( - "Invalid ECA size, expected:%zu actual%zu\n", - sizeof(*er_ctxt), cfg_tbl->len); - return -EINVAL; - } - memcpy((void *)er_ctxt, cfg_tbl->buf, sizeof(*er_ctxt)); - continue; - } - - /* update channel context array */ - if (!strcmp(cfg_tbl->name, "CCA")) { - ch_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[chan]; - if (cfg_tbl->len != sizeof(*ch_ctxt)) { - MHI_ERR( - "Invalid CCA size, expected:%zu actual:%zu\n", - sizeof(*ch_ctxt), cfg_tbl->len); - return -EINVAL; - } - memcpy((void *)ch_ctxt, cfg_tbl->buf, sizeof(*ch_ctxt)); - continue; - } - - return -EINVAL; - } - - return 0; -} - -static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - int num, i; - struct mhi_event *mhi_event; - u32 bit_cfg; - - num = NUM_MHI_EVT_RINGS; - - mhi_cntrl->total_ev_rings = num; - mhi_cntrl->mhi_event = mhi_cntrl->data->mhi_event; - - /* populate ev ring */ - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - mhi_event->er_index = i; - mhi_event->ring.elements = NUM_MHI_EVT_RING_ELEMENTS; //Event ring length in elements - mhi_event->intmod = 1; //Interrupt moderation time in ms - mhi_event->priority = MHI_ER_PRIORITY_MEDIUM; //Event ring priority, set to 1 for now - - mhi_event->msi = 1 + i; //MSI associated with this event ring - if (i == IPA_OUT_EVENT_RING) - { - mhi_event->chan = MHI_CLIENT_IP_HW_0_OUT; //Dedicated channel number, if it's a dedicated event ring - mhi_event->ring.elements = NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS; - mhi_event->priority = MHI_ER_PRIORITY_HIGH; - } - else if (i == IPA_IN_EVENT_RING) - { - mhi_event->chan = MHI_CLIENT_IP_HW_0_IN; //Dedicated channel number, if it's a dedicated event ring - mhi_event->ring.elements = NUM_MHI_IPA_IN_EVT_RING_ELEMENTS; - mhi_event->priority = MHI_ER_PRIORITY_HIGH; - } - else - mhi_event->chan = 0; - - if (mhi_event->chan >= mhi_cntrl->max_chan) - goto error_ev_cfg; - - /* this event ring has a dedicated channel */ - if (mhi_event->chan) - mhi_event->mhi_chan = &mhi_cntrl->mhi_chan[mhi_event->chan]; - - //mhi_event->priority = 1; //Event ring priority, set to 1 for now - mhi_event->db_cfg.brstmode = MHI_BRSTMODE_DISABLE; - - if (mhi_event->chan == MHI_CLIENT_IP_HW_0_OUT || mhi_event->chan == MHI_CLIENT_IP_HW_0_IN) - mhi_event->db_cfg.brstmode = MHI_BRSTMODE_ENABLE; - - if (MHI_INVALID_BRSTMODE(mhi_event->db_cfg.brstmode)) - goto error_ev_cfg; - - mhi_event->db_cfg.process_db = - (mhi_event->db_cfg.brstmode == MHI_BRSTMODE_ENABLE) ? - mhi_db_brstmode : mhi_db_brstmode_disable; - - bit_cfg = (MHI_EV_CFG_BIT_CTRL_EV & 0); - if (bit_cfg & MHI_EV_CFG_BIT_HW_EV) { - mhi_event->hw_ring = true; - mhi_cntrl->hw_ev_rings++; - } else - mhi_cntrl->sw_ev_rings++; - - mhi_event->cl_manage = !!(bit_cfg & MHI_EV_CFG_BIT_CL_MANAGE); - mhi_event->offload_ev = !!(bit_cfg & MHI_EV_CFG_BIT_OFFLOAD_EV); - mhi_event->ctrl_ev = !!(bit_cfg & MHI_EV_CFG_BIT_CTRL_EV); - } - - /* we need msi for each event ring + additional one for BHI */ - mhi_cntrl->msi_required = mhi_cntrl->total_ev_rings + 1; - - return 0; - - error_ev_cfg: - return -EINVAL; -} -static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - u32 num, i; - u32 ring = 0; - - struct chan_cfg_t { - const char *chan_name; - u32 chan_id; - u32 elements; - }; - - static struct chan_cfg_t chan_cfg[] = { - //"Qualcomm PCIe Loopback" - {"LOOPBACK", MHI_CLIENT_LOOPBACK_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"LOOPBACK", MHI_CLIENT_LOOPBACK_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm PCIe Sahara" - {"SAHARA", MHI_CLIENT_SAHARA_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"SAHARA", MHI_CLIENT_SAHARA_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm PCIe Diagnostics" - {"DIAG", MHI_CLIENT_DIAG_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"DIAG", MHI_CLIENT_DIAG_IN, NUM_MHI_DIAG_IN_RING_ELEMENTS}, - //"Qualcomm PCIe QDSS Data" - {"QDSS", MHI_CLIENT_QDSS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"QDSS", MHI_CLIENT_QDSS_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm PCIe EFS" - {"EFS", MHI_CLIENT_EFS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"EFS", MHI_CLIENT_EFS_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -#ifdef CONFIG_MHI_NETDEV_MBIM - //"Qualcomm PCIe MBIM" - {"MBIM", MHI_CLIENT_MBIM_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"MBIM", MHI_CLIENT_MBIM_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -#else - //"Qualcomm PCIe QMI" - {"QMI0", MHI_CLIENT_QMI_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"QMI0", MHI_CLIENT_QMI_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm PCIe QMI" - //{"QMI1", MHI_CLIENT_QMI_2_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - //{"QMI1", MHI_CLIENT_QMI_2_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -#endif - //"Qualcomm PCIe IP CTRL" - {"IP_CTRL", MHI_CLIENT_IP_CTRL_1_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"IP_CTRL", MHI_CLIENT_IP_CTRL_1_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - - //"Qualcomm PCIe Boot Logging" - //{"BL", MHI_CLIENT_BOOT_LOG_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - //{"BL", MHI_CLIENT_BOOT_LOG_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm PCIe Modem" - {"DUN", MHI_CLIENT_DUN_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"DUN", MHI_CLIENT_DUN_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm EDL " - {"EDL", MHI_CLIENT_EDL_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"EDL", MHI_CLIENT_EDL_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - - {"GNSS", MHI_CLIENT_GNSS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"GNSS", MHI_CLIENT_GNSS_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - - {"AUDIO", MHI_CLIENT_AUDIO_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"AUDIO", MHI_CLIENT_AUDIO_IN, NUM_MHI_CHAN_RING_ELEMENTS}, - //"Qualcomm PCIe WWAN Adapter" - {"IP_HW0", MHI_CLIENT_IP_HW_0_OUT, NUM_MHI_IPA_OUT_RING_ELEMENTS}, - {"IP_HW0", MHI_CLIENT_IP_HW_0_IN, NUM_MHI_IPA_IN_RING_ELEMENTS}, - }; - - mhi_cntrl->max_chan = MHI_MAX_CHANNELS; - num = sizeof(chan_cfg)/sizeof(chan_cfg[0]); - - mhi_cntrl->mhi_chan = mhi_cntrl->data->mhi_chan, - INIT_LIST_HEAD(&mhi_cntrl->lpm_chans); - - /* populate channel configurations */ - for (i = 0; i < num; i++) { - struct mhi_chan *mhi_chan; - u32 chan_id = chan_cfg[i].chan_id; - u32 bit_cfg = 0; - u32 pollcfg = 0; - enum MHI_BRSTMODE brstmode = MHI_BRSTMODE_DISABLE; - - if (chan_id >= mhi_cntrl->max_chan) - goto error_chan_cfg; - - mhi_chan = &mhi_cntrl->mhi_chan[chan_id]; - mhi_chan->chan = chan_id; - mhi_chan->buf_ring.elements = chan_cfg[i].elements; - if (MHI_HW_CHAN(mhi_chan->chan) || mhi_chan->chan == MHI_CLIENT_DIAG_IN) { - mhi_chan->ring = 0; - } - else { - mhi_chan->ring = ring; - ring += mhi_chan->buf_ring.elements; - } - mhi_chan->tre_ring.elements = mhi_chan->buf_ring.elements; - if (chan_id == MHI_CLIENT_IP_HW_0_OUT) - mhi_chan->er_index = IPA_OUT_EVENT_RING; - else if (chan_id == MHI_CLIENT_IP_HW_0_IN) - mhi_chan->er_index = IPA_IN_EVENT_RING; - else - mhi_chan->er_index = PRIMARY_EVENT_RING; - mhi_chan->dir = (chan_cfg[i].chan_id&1) ? INBOUND_CHAN : OUTBOUND_CHAN; - - mhi_chan->db_cfg.pollcfg = pollcfg; - mhi_chan->ee = MHI_EE_AMSS; - if (CHAN_SBL(chan_cfg[i].chan_id)) - mhi_chan->ee = MHI_EE_SBL; - else if (CHAN_EDL(chan_cfg[i].chan_id)) - mhi_chan->ee = MHI_EE_FP; - - mhi_chan->xfer_type = MHI_XFER_BUFFER; - if ((chan_cfg[i].chan_id == MHI_CLIENT_IP_HW_0_OUT || chan_cfg[i].chan_id == MHI_CLIENT_IP_HW_0_IN) - || (chan_cfg[i].chan_id == MHI_CLIENT_IP_SW_0_OUT || chan_cfg[i].chan_id == MHI_CLIENT_IP_SW_0_IN)) - mhi_chan->xfer_type = MHI_XFER_SKB; - - switch (mhi_chan->xfer_type) { - case MHI_XFER_BUFFER: - mhi_chan->gen_tre = mhi_gen_tre; - mhi_chan->queue_xfer = mhi_queue_buf; - break; - case MHI_XFER_SKB: - mhi_chan->queue_xfer = mhi_queue_skb; - break; - case MHI_XFER_SCLIST: - mhi_chan->gen_tre = mhi_gen_tre; - mhi_chan->queue_xfer = mhi_queue_sclist; - break; - case MHI_XFER_NOP: - mhi_chan->queue_xfer = mhi_queue_nop; - break; - default: - goto error_chan_cfg; - } - - mhi_chan->lpm_notify = !!(bit_cfg & MHI_CH_CFG_BIT_LPM_NOTIFY); - mhi_chan->offload_ch = !!(bit_cfg & MHI_CH_CFG_BIT_OFFLOAD_CH); - mhi_chan->db_cfg.reset_req = - !!(bit_cfg & MHI_CH_CFG_BIT_DBMODE_RESET_CH); - mhi_chan->pre_alloc = !!(bit_cfg & MHI_CH_CFG_BIT_PRE_ALLOC); - - if (mhi_chan->pre_alloc && - (mhi_chan->dir != DMA_FROM_DEVICE || - mhi_chan->xfer_type != MHI_XFER_BUFFER)) - goto error_chan_cfg; - - /* if mhi host allocate the buffers then client cannot queue */ - if (mhi_chan->pre_alloc) - mhi_chan->queue_xfer = mhi_queue_nop; - - mhi_chan->name = chan_cfg[i].chan_name; - - if (!mhi_chan->offload_ch) { - if (mhi_chan->chan == MHI_CLIENT_IP_HW_0_OUT || mhi_chan->chan == MHI_CLIENT_IP_HW_0_IN) - brstmode = MHI_BRSTMODE_ENABLE; - - mhi_chan->db_cfg.brstmode = brstmode; - if (MHI_INVALID_BRSTMODE(mhi_chan->db_cfg.brstmode)) - goto error_chan_cfg; - - mhi_chan->db_cfg.process_db = - (mhi_chan->db_cfg.brstmode == - MHI_BRSTMODE_ENABLE) ? - mhi_db_brstmode : mhi_db_brstmode_disable; - } - mhi_chan->configured = true; - - if (mhi_chan->lpm_notify) - list_add_tail(&mhi_chan->node, &mhi_cntrl->lpm_chans); - } - - MHI_LOG("chan ring need %d, chan ring size %zd\n", - ring, sizeof(mhi_cntrl->data->mhi_ctxt.ctrl_seg->chan_ring)/sizeof(struct __packed mhi_tre)); - - if (ring > sizeof(mhi_cntrl->data->mhi_ctxt.ctrl_seg->chan_ring)/sizeof(struct __packed mhi_tre)) - return -ENOMEM; - - return 0; - -error_chan_cfg: - return -EINVAL; -} - -static int of_parse_dt(struct mhi_controller *mhi_cntrl, struct device_node *of_node) -{ - int ret; - - mhi_cntrl->fw_image = NULL; - mhi_cntrl->edl_image = NULL; - mhi_cntrl->fbc_download = 0; - mhi_cntrl->sbl_size = 0; - mhi_cntrl->seg_len = 0; - - /* parse MHI channel configuration */ - ret = of_parse_ch_cfg(mhi_cntrl, of_node); - if (ret) { - MHI_ERR("Error of_parse_ch_cfg ret:%d\n", ret); - return ret; - } - - /* parse MHI event configuration */ - ret = of_parse_ev_cfg(mhi_cntrl, of_node); - if (ret) { - MHI_ERR("Error of_parse_ch_cfg ret:%d\n", ret); - goto error_ev_cfg; - } - - mhi_cntrl->timeout_ms = MHI_TIMEOUT_MS; - - return 0; - - error_ev_cfg: - return ret; -} - -int mhi_register_mhi_controller(struct mhi_controller *mhi_cntrl) -{ - int ret; - int i; - struct mhi_event *mhi_event; - struct mhi_chan *mhi_chan; - struct mhi_cmd *mhi_cmd; - - mhi_cntrl->klog_lvl = MHI_MSG_LVL_ERROR; - - if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put) - return -EINVAL; - - if (!mhi_cntrl->status_cb || !mhi_cntrl->link_status) - return -EINVAL; - - ret = of_parse_dt(mhi_cntrl, NULL); - if (ret) { - MHI_ERR("Error of_parse_dt ret:%d\n", ret); - return -EINVAL; - } - - mhi_cntrl->mhi_cmd = &mhi_cntrl->data->mhi_cmd[0]; - - INIT_LIST_HEAD(&mhi_cntrl->transition_list); - mutex_init(&mhi_cntrl->pm_mutex); - rwlock_init(&mhi_cntrl->pm_lock); - spin_lock_init(&mhi_cntrl->transition_lock); - spin_lock_init(&mhi_cntrl->wlock); - INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); - INIT_WORK(&mhi_cntrl->fw_worker, mhi_fw_load_worker); - INIT_WORK(&mhi_cntrl->m1_worker, mhi_pm_m1_worker); - INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); - init_waitqueue_head(&mhi_cntrl->state_event); - - mhi_cmd = mhi_cntrl->mhi_cmd; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++) - spin_lock_init(&mhi_cmd->lock); - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - mhi_event->mhi_cntrl = mhi_cntrl; - spin_lock_init(&mhi_event->lock); - if (mhi_event->ctrl_ev) - tasklet_init(&mhi_event->task, mhi_ctrl_ev_task, - (ulong)mhi_event); - else - tasklet_init(&mhi_event->task, mhi_ev_task, - (ulong)mhi_event); - } - - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { - mutex_init(&mhi_chan->mutex); - init_completion(&mhi_chan->completion); - rwlock_init(&mhi_chan->lock); - } - - mhi_cntrl->parent = mhi_bus.dentry; - - /* add to list */ - mutex_lock(&mhi_bus.lock); - list_add_tail(&mhi_cntrl->node, &mhi_bus.controller_list); - mutex_unlock(&mhi_bus.lock); - - return 0; - -//error_alloc_cmd: - - return -ENOMEM; -}; - -void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl) -{ - mutex_lock(&mhi_bus.lock); - list_del(&mhi_cntrl->node); - mutex_unlock(&mhi_bus.lock); -} - -/* set ptr to control private data */ -static inline void mhi_controller_set_devdata(struct mhi_controller *mhi_cntrl, - void *priv) -{ - mhi_cntrl->priv_data = priv; -} - - -/* allocate mhi controller to register */ -struct mhi_controller *mhi_alloc_controller(size_t size) -{ - struct mhi_controller *mhi_cntrl; - - mhi_cntrl = kzalloc(size + sizeof(*mhi_cntrl) + sizeof(struct mhi_cntrl_data), GFP_KERNEL); - MHI_LOG("%d size = %zd\n", __LINE__, size + sizeof(*mhi_cntrl)); - - if (mhi_cntrl && size) - mhi_controller_set_devdata(mhi_cntrl, mhi_cntrl + 1); - - mhi_cntrl->data = (struct mhi_cntrl_data *)(((char *)mhi_cntrl) + (size + sizeof(*mhi_cntrl))); - - return mhi_cntrl; -} -EXPORT_SYMBOL(mhi_alloc_controller); - -int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) -{ - int ret; - - mutex_lock(&mhi_cntrl->pm_mutex); - - ret = mhi_init_dev_ctxt(mhi_cntrl); - if (ret) { - MHI_ERR("Error with init dev_ctxt\n"); - goto error_dev_ctxt; - } - - ret = mhi_init_irq_setup(mhi_cntrl); - if (ret) { - MHI_ERR("Error setting up irq\n"); - goto error_setup_irq; - } - - /* - * allocate rddm table if specified, this table is for debug purpose - * so we'll ignore erros - */ - if (mhi_cntrl->rddm_size) - mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image, - mhi_cntrl->rddm_size); - - mhi_cntrl->pre_init = true; - - mutex_unlock(&mhi_cntrl->pm_mutex); - - return 0; - -error_setup_irq: - mhi_deinit_dev_ctxt(mhi_cntrl); - -error_dev_ctxt: - mutex_unlock(&mhi_cntrl->pm_mutex); - - return ret; -} -EXPORT_SYMBOL(mhi_prepare_for_power_up); - -void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl) -{ - if (mhi_cntrl->fbc_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - } - - if (mhi_cntrl->rddm_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); - mhi_cntrl->rddm_image = NULL; - } - - mhi_deinit_free_irq(mhi_cntrl); - mhi_deinit_dev_ctxt(mhi_cntrl); - mhi_cntrl->pre_init = false; -} - -/* match dev to drv */ -static int mhi_match(struct device *dev, struct device_driver *drv) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_driver *mhi_drv = to_mhi_driver(drv); - const struct mhi_device_id *id; - - for (id = mhi_drv->id_table; id->chan != NULL && id->chan[0] != '\0'; id++) { - if (!strcmp(mhi_dev->chan_name, id->chan)) { - mhi_dev->id = id; - return 1; - } - } - - return 0; -}; - -static void mhi_release_device(struct device *dev) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - - kfree(mhi_dev); -} - -struct bus_type mhi_bus_type = { - .name = "mhi", - .dev_name = "mhi", - .match = mhi_match, -}; - -static int mhi_driver_probe(struct device *dev) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct device_driver *drv = dev->driver; - struct mhi_driver *mhi_drv = to_mhi_driver(drv); - struct mhi_event *mhi_event; - struct mhi_chan *ul_chan = mhi_dev->ul_chan; - struct mhi_chan *dl_chan = mhi_dev->dl_chan; - bool offload_ch = ((ul_chan && ul_chan->offload_ch) || - (dl_chan && dl_chan->offload_ch)); - - MHI_LOG("%s dev->name = %s\n", __func__, dev_name(dev)); - - /* all offload channels require status_cb to be defined */ - if (offload_ch) { - if (!mhi_dev->status_cb) - return -EINVAL; - mhi_dev->status_cb = mhi_drv->status_cb; - } - - if (ul_chan && !offload_ch) { - if (!mhi_drv->ul_xfer_cb) - return -EINVAL; - ul_chan->xfer_cb = mhi_drv->ul_xfer_cb; - } - - if (dl_chan && !offload_ch) { - if (!mhi_drv->dl_xfer_cb) - return -EINVAL; - dl_chan->xfer_cb = mhi_drv->dl_xfer_cb; - mhi_event = &mhi_cntrl->mhi_event[dl_chan->er_index]; - - /* - * if this channal event ring manage by client, then - * status_cb must be defined so we can send the async - * cb whenever there are pending data - */ - if (mhi_event->cl_manage && !mhi_drv->status_cb) - return -EINVAL; - mhi_dev->status_cb = mhi_drv->status_cb; - } - - return mhi_drv->probe(mhi_dev, mhi_dev->id); -} - -static int mhi_driver_remove(struct device *dev) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_driver *mhi_drv = to_mhi_driver(dev->driver); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - enum MHI_CH_STATE ch_state[] = { - MHI_CH_STATE_DISABLED, - MHI_CH_STATE_DISABLED - }; - int dir; - - MHI_LOG("Removing device for chan:%s\n", mhi_dev->chan_name); - - /* reset both channels */ - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - /* wake all threads waiting for completion */ - write_lock_irq(&mhi_chan->lock); - mhi_chan->ccs = MHI_EV_CC_INVALID; - complete_all(&mhi_chan->completion); - write_unlock_irq(&mhi_chan->lock); - - /* move channel state to disable, no more processing */ - mutex_lock(&mhi_chan->mutex); - write_lock_irq(&mhi_chan->lock); - ch_state[dir] = mhi_chan->ch_state; - mhi_chan->ch_state = MHI_CH_STATE_DISABLED; - write_unlock_irq(&mhi_chan->lock); - - /* reset the channel */ - if (!mhi_chan->offload_ch) - mhi_reset_chan(mhi_cntrl, mhi_chan); - } - - /* destroy the device */ - mhi_drv->remove(mhi_dev); - - /* de_init channel if it was enabled */ - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - if (ch_state[dir] == MHI_CH_STATE_ENABLED && - !mhi_chan->offload_ch) - mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); - - mutex_unlock(&mhi_chan->mutex); - } - - /* relinquish any pending votes */ - read_lock_bh(&mhi_cntrl->pm_lock); - while (atomic_read(&mhi_dev->dev_wake)) - mhi_device_put(mhi_dev); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; -} - -int mhi_driver_register(struct mhi_driver *mhi_drv) -{ - struct device_driver *driver = &mhi_drv->driver; - - if (!mhi_drv->probe || !mhi_drv->remove) - return -EINVAL; - - driver->bus = &mhi_bus_type; - driver->probe = mhi_driver_probe; - driver->remove = mhi_driver_remove; - return driver_register(driver); -} -EXPORT_SYMBOL(mhi_driver_register); - -void mhi_driver_unregister(struct mhi_driver *mhi_drv) -{ - driver_unregister(&mhi_drv->driver); -} -EXPORT_SYMBOL(mhi_driver_unregister); - -struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl) -{ - struct mhi_device *mhi_dev = kzalloc(sizeof(*mhi_dev), GFP_KERNEL); - struct device *dev; - //MHI_LOG("%d size = %zd\n", __LINE__, sizeof(*mhi_dev)); - - if (!mhi_dev) - return NULL; - - dev = &mhi_dev->dev; - device_initialize(dev); - dev->bus = &mhi_bus_type; - dev->release = mhi_release_device; - dev->parent = mhi_cntrl->dev; - mhi_dev->mhi_cntrl = mhi_cntrl; - mhi_dev->dev_id = mhi_cntrl->dev_id; - mhi_dev->domain = mhi_cntrl->domain; - mhi_dev->bus = mhi_cntrl->bus; - mhi_dev->slot = mhi_cntrl->slot; - mhi_dev->mtu = MHI_MAX_MTU; - atomic_set(&mhi_dev->dev_wake, 0); - - return mhi_dev; -} - -extern int mhi_dtr_init(void); -extern void mhi_dtr_exit(void); -extern int mhi_device_netdev_init(struct dentry *parent); -extern void mhi_device_netdev_exit(void); -extern int mhi_device_uci_init(void); -extern void mhi_device_uci_exit(void); -extern int mhi_controller_qcom_init(void); -extern void mhi_controller_qcom_exit(void); - -static char mhi_version[] = "Fibocom_Linux_PCIE_MHI_Driver_V1.0.5"; -module_param_string(mhi_version, mhi_version, sizeof(mhi_version), S_IRUGO); - -static int __init mhi_init(void) -{ - int ret; - struct dentry *dentry; - - pr_err("INFO:%s %s\n", __func__, mhi_version); - - mutex_init(&mhi_bus.lock); - INIT_LIST_HEAD(&mhi_bus.controller_list); - dentry = debugfs_create_dir("mhi", NULL); - if (!IS_ERR_OR_NULL(dentry)) - mhi_bus.dentry = dentry; - - ret = bus_register(&mhi_bus_type); - if (ret) { - pr_err("Error bus_register ret:%d\n", ret); - return ret; - } - - ret = mhi_dtr_init(); - if (ret) { - pr_err("Error mhi_dtr_init ret:%d\n", ret); - bus_unregister(&mhi_bus_type); - return ret; - } - - ret = mhi_device_netdev_init(dentry); - if (ret) { - pr_err("Error mhi_device_netdev_init ret:%d\n", ret); - } - - ret = mhi_device_uci_init(); - if (ret) { - pr_err("Error mhi_device_uci_init ret:%d\n", ret); - } - - ret = mhi_controller_qcom_init(); - if (ret) { - pr_err("Error mhi_controller_qcom_init ret:%d\n", ret); - } - - return ret; -} - -static void mhi_exit(void) -{ - mhi_controller_qcom_exit(); - mhi_device_uci_exit(); - mhi_device_netdev_exit(); - mhi_dtr_exit(); - bus_unregister(&mhi_bus_type); - debugfs_remove_recursive(mhi_bus.dentry); -} - -module_init(mhi_init); -module_exit(mhi_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("MHI_CORE"); -MODULE_DESCRIPTION("MHI Host Interface"); diff --git a/fibocom_MHI/src/core/mhi_internal.h b/fibocom_MHI/src/core/mhi_internal.h deleted file mode 100644 index 2ab1771..0000000 --- a/fibocom_MHI/src/core/mhi_internal.h +++ /dev/null @@ -1,800 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _MHI_INT_H -#define _MHI_INT_H - -#include -#ifndef writel_relaxed -#define writel_relaxed writel -#endif - -#ifndef U32_MAX -#define U32_MAX ((u32)~0U) -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 3,10,108 )) -static inline void reinit_completion(struct completion *x) -{ - x->done = 0; -} -#endif - -extern struct bus_type mhi_bus_type; - -/* MHI mmio register mapping */ -#define PCI_INVALID_READ(val) (val == U32_MAX) - -#define MHIREGLEN (0x0) -#define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF) -#define MHIREGLEN_MHIREGLEN_SHIFT (0) - -#define MHIVER (0x8) -#define MHIVER_MHIVER_MASK (0xFFFFFFFF) -#define MHIVER_MHIVER_SHIFT (0) - -#define MHICFG (0x10) -#define MHICFG_NHWER_MASK (0xFF000000) -#define MHICFG_NHWER_SHIFT (24) -#define MHICFG_NER_MASK (0xFF0000) -#define MHICFG_NER_SHIFT (16) -#define MHICFG_NHWCH_MASK (0xFF00) -#define MHICFG_NHWCH_SHIFT (8) -#define MHICFG_NCH_MASK (0xFF) -#define MHICFG_NCH_SHIFT (0) - -#define CHDBOFF (0x18) -#define CHDBOFF_CHDBOFF_MASK (0xFFFFFFFF) -#define CHDBOFF_CHDBOFF_SHIFT (0) - -#define ERDBOFF (0x20) -#define ERDBOFF_ERDBOFF_MASK (0xFFFFFFFF) -#define ERDBOFF_ERDBOFF_SHIFT (0) - -#define BHIOFF (0x28) -#define BHIOFF_BHIOFF_MASK (0xFFFFFFFF) -#define BHIOFF_BHIOFF_SHIFT (0) - -#define DEBUGOFF (0x30) -#define DEBUGOFF_DEBUGOFF_MASK (0xFFFFFFFF) -#define DEBUGOFF_DEBUGOFF_SHIFT (0) - -#define MHICTRL (0x38) -#define MHICTRL_MHISTATE_MASK (0x0000FF00) -#define MHICTRL_MHISTATE_SHIFT (8) -#define MHICTRL_RESET_MASK (0x2) -#define MHICTRL_RESET_SHIFT (1) - -#define MHISTATUS (0x48) -#define MHISTATUS_MHISTATE_MASK (0x0000FF00) -#define MHISTATUS_MHISTATE_SHIFT (8) -#define MHISTATUS_SYSERR_MASK (0x4) -#define MHISTATUS_SYSERR_SHIFT (2) -#define MHISTATUS_READY_MASK (0x1) -#define MHISTATUS_READY_SHIFT (0) - -#define CCABAP_LOWER (0x58) -#define CCABAP_LOWER_CCABAP_LOWER_MASK (0xFFFFFFFF) -#define CCABAP_LOWER_CCABAP_LOWER_SHIFT (0) - -#define CCABAP_HIGHER (0x5C) -#define CCABAP_HIGHER_CCABAP_HIGHER_MASK (0xFFFFFFFF) -#define CCABAP_HIGHER_CCABAP_HIGHER_SHIFT (0) - -#define ECABAP_LOWER (0x60) -#define ECABAP_LOWER_ECABAP_LOWER_MASK (0xFFFFFFFF) -#define ECABAP_LOWER_ECABAP_LOWER_SHIFT (0) - -#define ECABAP_HIGHER (0x64) -#define ECABAP_HIGHER_ECABAP_HIGHER_MASK (0xFFFFFFFF) -#define ECABAP_HIGHER_ECABAP_HIGHER_SHIFT (0) - -#define CRCBAP_LOWER (0x68) -#define CRCBAP_LOWER_CRCBAP_LOWER_MASK (0xFFFFFFFF) -#define CRCBAP_LOWER_CRCBAP_LOWER_SHIFT (0) - -#define CRCBAP_HIGHER (0x6C) -#define CRCBAP_HIGHER_CRCBAP_HIGHER_MASK (0xFFFFFFFF) -#define CRCBAP_HIGHER_CRCBAP_HIGHER_SHIFT (0) - -#define CRDB_LOWER (0x70) -#define CRDB_LOWER_CRDB_LOWER_MASK (0xFFFFFFFF) -#define CRDB_LOWER_CRDB_LOWER_SHIFT (0) - -#define CRDB_HIGHER (0x74) -#define CRDB_HIGHER_CRDB_HIGHER_MASK (0xFFFFFFFF) -#define CRDB_HIGHER_CRDB_HIGHER_SHIFT (0) - -#define MHICTRLBASE_LOWER (0x80) -#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_MASK (0xFFFFFFFF) -#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_SHIFT (0) - -#define MHICTRLBASE_HIGHER (0x84) -#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_MASK (0xFFFFFFFF) -#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_SHIFT (0) - -#define MHICTRLLIMIT_LOWER (0x88) -#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_MASK (0xFFFFFFFF) -#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_SHIFT (0) - -#define MHICTRLLIMIT_HIGHER (0x8C) -#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_MASK (0xFFFFFFFF) -#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_SHIFT (0) - -#define MHIDATABASE_LOWER (0x98) -#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_MASK (0xFFFFFFFF) -#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_SHIFT (0) - -#define MHIDATABASE_HIGHER (0x9C) -#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_MASK (0xFFFFFFFF) -#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_SHIFT (0) - -#define MHIDATALIMIT_LOWER (0xA0) -#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_MASK (0xFFFFFFFF) -#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_SHIFT (0) - -#define MHIDATALIMIT_HIGHER (0xA4) -#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF) -#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0) - -/* MHI BHI offfsets */ -#define BHI_BHIVERSION_MINOR (0x00) -#define BHI_BHIVERSION_MAJOR (0x04) -#define BHI_IMGADDR_LOW (0x08) -#define BHI_IMGADDR_HIGH (0x0C) -#define BHI_IMGSIZE (0x10) -#define BHI_RSVD1 (0x14) -#define BHI_IMGTXDB (0x18) -#define BHI_TXDB_SEQNUM_BMSK (0x3FFFFFFF) -#define BHI_TXDB_SEQNUM_SHFT (0) -#define BHI_RSVD2 (0x1C) -#define BHI_INTVEC (0x20) -#define BHI_RSVD3 (0x24) -#define BHI_EXECENV (0x28) -#define BHI_STATUS (0x2C) -#define BHI_ERRCODE (0x30) -#define BHI_ERRDBG1 (0x34) -#define BHI_ERRDBG2 (0x38) -#define BHI_ERRDBG3 (0x3C) -#define BHI_SERIALNUM ( 0x40 ) -#define BHI_SERIALNU (0x40) -#define BHI_SBLANTIROLLVER (0x44) -#define BHI_NUMSEG (0x48) -#define BHI_MSMHWID(n) (0x4C + (0x4 * n)) -#define BHI_OEMPKHASH(n) (0x64 + (0x4 * n)) -#define BHI_RSVD5 (0xC4) -#define BHI_STATUS_MASK (0xC0000000) -#define BHI_STATUS_SHIFT (30) -#define BHI_STATUS_ERROR (3) -#define BHI_STATUS_SUCCESS (2) -#define BHI_STATUS_RESET (0) - -/* MHI BHIE offsets */ -#define BHIE_OFFSET (0x0124) /* BHIE register space offset from BHI base */ -#define BHIE_MSMSOCID_OFFS (BHIE_OFFSET + 0x0000) -#define BHIE_TXVECADDR_LOW_OFFS (BHIE_OFFSET + 0x002C) -#define BHIE_TXVECADDR_HIGH_OFFS (BHIE_OFFSET + 0x0030) -#define BHIE_TXVECSIZE_OFFS (BHIE_OFFSET + 0x0034) -#define BHIE_TXVECDB_OFFS (BHIE_OFFSET + 0x003C) -#define BHIE_TXVECDB_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_TXVECDB_SEQNUM_SHFT (0) -#define BHIE_TXVECSTATUS_OFFS (BHIE_OFFSET + 0x0044) -#define BHIE_TXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_TXVECSTATUS_SEQNUM_SHFT (0) -#define BHIE_TXVECSTATUS_STATUS_BMSK (0xC0000000) -#define BHIE_TXVECSTATUS_STATUS_SHFT (30) -#define BHIE_TXVECSTATUS_STATUS_RESET (0x00) -#define BHIE_TXVECSTATUS_STATUS_XFER_COMPL (0x02) -#define BHIE_TXVECSTATUS_STATUS_ERROR (0x03) -#define BHIE_RXVECADDR_LOW_OFFS (BHIE_OFFSET + 0x0060) -#define BHIE_RXVECADDR_HIGH_OFFS (BHIE_OFFSET + 0x0064) -#define BHIE_RXVECSIZE_OFFS (BHIE_OFFSET + 0x0068) -#define BHIE_RXVECDB_OFFS (BHIE_OFFSET + 0x0070) -#define BHIE_RXVECDB_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_RXVECDB_SEQNUM_SHFT (0) -#define BHIE_RXVECSTATUS_OFFS (BHIE_OFFSET + 0x0078) -#define BHIE_RXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_RXVECSTATUS_SEQNUM_SHFT (0) -#define BHIE_RXVECSTATUS_STATUS_BMSK (0xC0000000) -#define BHIE_RXVECSTATUS_STATUS_SHFT (30) -#define BHIE_RXVECSTATUS_STATUS_RESET (0x00) -#define BHIE_RXVECSTATUS_STATUS_XFER_COMPL (0x02) -#define BHIE_RXVECSTATUS_STATUS_ERROR (0x03) - -struct __packed mhi_event_ctxt { - u32 reserved : 8; - u32 intmodc : 8; - u32 intmodt : 16; - u32 ertype; - u32 msivec; - u64 rbase; - u64 rlen; - u64 rp; - u64 wp; -}; - -struct __packed mhi_chan_ctxt { - u32 chstate : 8; - u32 brstmode : 2; - u32 pollcfg : 6; - u32 reserved : 16; - u32 chtype; - u32 erindex; - u64 rbase; - u64 rlen; - u64 rp; - u64 wp; -}; - -struct __packed mhi_cmd_ctxt { - u32 reserved0; - u32 reserved1; - u32 reserved2; - u64 rbase; - u64 rlen; - u64 rp; - u64 wp; -}; - -struct __packed mhi_tre { - u64 ptr; - u32 dword[2]; -}; - -struct __packed bhi_vec_entry { - u64 dma_addr; - u64 size; -}; - -/* no operation command */ -#define MHI_TRE_CMD_NOOP_PTR cpu_to_le64(0) -#define MHI_TRE_CMD_NOOP_DWORD0 cpu_to_le32(0) -#define MHI_TRE_CMD_NOOP_DWORD1 cpu_to_le32(1 << 16) - -/* channel reset command */ -#define MHI_TRE_CMD_RESET_PTR cpu_to_le64(0) -#define MHI_TRE_CMD_RESET_DWORD0 cpu_to_le32(0) -#define MHI_TRE_CMD_RESET_DWORD1(chid) cpu_to_le32((chid << 24) | (16 << 16)) - -/* channel stop command */ -#define MHI_TRE_CMD_STOP_PTR cpu_to_le64(0) -#define MHI_TRE_CMD_STOP_DWORD0 cpu_to_le32(0) -#define MHI_TRE_CMD_STOP_DWORD1(chid) cpu_to_le32((chid << 24) | (17 << 16)) - -/* channel start command */ -#define MHI_TRE_CMD_START_PTR cpu_to_le64(0) -#define MHI_TRE_CMD_START_DWORD0 cpu_to_le32(0) -#define MHI_TRE_CMD_START_DWORD1(chid) cpu_to_le32((chid << 24) | (18 << 16)) - -#define MHI_TRE_GET_CMD_CHID(tre) ((le32_to_cpu((tre)->dword[1]) >> 24) & 0xFF) - -/* event descriptor macros */ -//#define MHI_TRE_EV_PTR(ptr) (ptr) -//#define MHI_TRE_EV_DWORD0(code, len) ((code << 24) | len) -#define MHI_TRE_EV_DWORD1(chid, type) cpu_to_le32((chid << 24) | (type << 16)) -#define MHI_TRE_GET_EV_PTR(tre) le64_to_cpu((tre)->ptr) -#define MHI_TRE_GET_EV_CODE(tre) ((le32_to_cpu((tre)->dword[0]) >> 24) & 0xFF) -#define MHI_TRE_GET_EV_LEN(tre) (le32_to_cpu((tre)->dword[0]) & 0xFFFF) -#define MHI_TRE_GET_EV_CHID(tre) ((le32_to_cpu((tre)->dword[1]) >> 24) & 0xFF) -#define MHI_TRE_GET_EV_TYPE(tre) ((le32_to_cpu((tre)->dword[1]) >> 16) & 0xFF) -#define MHI_TRE_GET_EV_STATE(tre) ((le32_to_cpu((tre)->dword[0]) >> 24) & 0xFF) -#define MHI_TRE_GET_EV_EXECENV(tre) ((le32_to_cpu((tre)->dword[0]) >> 24) & 0xFF) - - -/* transfer descriptor macros */ -#define MHI_TRE_DATA_PTR(ptr) cpu_to_le64(ptr) -#define MHI_TRE_DATA_DWORD0(len) cpu_to_le32(len & MHI_MAX_MTU) -#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) cpu_to_le32((2 << 16) | (bei << 10) \ - | (ieot << 9) | (ieob << 8) | chain) - -enum MHI_CMD { - MHI_CMD_NOOP = 0x0, - MHI_CMD_RESET_CHAN = 0x1, - MHI_CMD_STOP_CHAN = 0x2, - MHI_CMD_START_CHAN = 0x3, - MHI_CMD_RESUME_CHAN = 0x4, -}; - -enum MHI_PKT_TYPE { - MHI_PKT_TYPE_INVALID = 0x0, - MHI_PKT_TYPE_NOOP_CMD = 0x1, - MHI_PKT_TYPE_TRANSFER = 0x2, - MHI_PKT_TYPE_RESET_CHAN_CMD = 0x10, - MHI_PKT_TYPE_STOP_CHAN_CMD = 0x11, - MHI_PKT_TYPE_START_CHAN_CMD = 0x12, - MHI_PKT_TYPE_STATE_CHANGE_EVENT = 0x20, - MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21, - MHI_PKT_TYPE_TX_EVENT = 0x22, - MHI_PKT_TYPE_EE_EVENT = 0x40, - MHI_PKT_TYPE_STALE_EVENT, /* internal event */ -}; - -/* MHI transfer completion events */ -enum MHI_EV_CCS { - MHI_EV_CC_INVALID = 0x0, - MHI_EV_CC_SUCCESS = 0x1, - MHI_EV_CC_EOT = 0x2, - MHI_EV_CC_OVERFLOW = 0x3, - MHI_EV_CC_EOB = 0x4, - MHI_EV_CC_OOB = 0x5, - MHI_EV_CC_DB_MODE = 0x6, - MHI_EV_CC_UNDEFINED_ERR = 0x10, - MHI_EV_CC_BAD_TRE = 0x11, -}; - -enum MHI_CH_STATE { - MHI_CH_STATE_DISABLED = 0x0, - MHI_CH_STATE_ENABLED = 0x1, - MHI_CH_STATE_RUNNING = 0x2, - MHI_CH_STATE_SUSPENDED = 0x3, - MHI_CH_STATE_STOP = 0x4, - MHI_CH_STATE_ERROR = 0x5, -}; - -enum MHI_CH_CFG { - MHI_CH_CFG_CHAN_ID = 0, - MHI_CH_CFG_ELEMENTS = 1, - MHI_CH_CFG_ER_INDEX = 2, - MHI_CH_CFG_DIRECTION = 3, - MHI_CH_CFG_BRSTMODE = 4, - MHI_CH_CFG_POLLCFG = 5, - MHI_CH_CFG_EE = 6, - MHI_CH_CFG_XFER_TYPE = 7, - MHI_CH_CFG_BITCFG = 8, - MHI_CH_CFG_MAX -}; - -#define MHI_CH_CFG_BIT_LPM_NOTIFY BIT(0) /* require LPM notification */ -#define MHI_CH_CFG_BIT_OFFLOAD_CH BIT(1) /* satellite mhi devices */ -#define MHI_CH_CFG_BIT_DBMODE_RESET_CH BIT(2) /* require db mode to reset */ -#define MHI_CH_CFG_BIT_PRE_ALLOC BIT(3) /* host allocate buffers for DL */ - -enum MHI_EV_CFG { - MHI_EV_CFG_ELEMENTS = 0, - MHI_EV_CFG_INTMOD = 1, - MHI_EV_CFG_MSI = 2, - MHI_EV_CFG_CHAN = 3, - MHI_EV_CFG_PRIORITY = 4, - MHI_EV_CFG_BRSTMODE = 5, - MHI_EV_CFG_BITCFG = 6, - MHI_EV_CFG_MAX -}; - -#define MHI_EV_CFG_BIT_HW_EV BIT(0) /* hw event ring */ -#define MHI_EV_CFG_BIT_CL_MANAGE BIT(1) /* client manages the event ring */ -#define MHI_EV_CFG_BIT_OFFLOAD_EV BIT(2) /* satellite driver manges it */ -#define MHI_EV_CFG_BIT_CTRL_EV BIT(3) /* ctrl event ring */ - -enum MHI_BRSTMODE { - MHI_BRSTMODE_DISABLE = 0x2, - MHI_BRSTMODE_ENABLE = 0x3, -}; - -#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_BRSTMODE_DISABLE && \ - mode != MHI_BRSTMODE_ENABLE) - -enum MHI_EE { - MHI_EE_PBL = 0x0, /* Primary Boot Loader */ - MHI_EE_SBL = 0x1, /* Secondary Boot Loader */ - MHI_EE_AMSS = 0x2, /* AMSS Firmware */ - MHI_EE_RDDM = 0x3, /* WIFI Ram Dump Debug Module */ - MHI_EE_WFW = 0x4, /* WIFI (WLAN) Firmware */ - MHI_EE_PT = 0x5, /* PassThrough, Non PCIe BOOT (PCIe is BIOS locked, not used for boot */ - MHI_EE_EDL = 0x6, /* PCIe enabled in PBL for emergency download (Non PCIe BOOT) */ - MHI_EE_FP = 0x7, /* FlashProg, Flash Programmer Environment */ - MHI_EE_BHIE = MHI_EE_FP, - MHI_EE_UEFI = 0x8, /* UEFI */ - - MHI_EE_DISABLE_TRANSITION = 0x9, - MHI_EE_MAX -}; - -extern const char * const mhi_ee_str[MHI_EE_MAX]; -#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \ - "INVALID_EE" : mhi_ee_str[ee]) - -#define MHI_IN_PBL(ee) (ee == MHI_EE_PBL || ee == MHI_EE_PT || ee == MHI_EE_EDL) - -enum MHI_ST_TRANSITION { - MHI_ST_TRANSITION_PBL, - MHI_ST_TRANSITION_READY, - MHI_ST_TRANSITION_SBL, - MHI_ST_TRANSITION_AMSS, - MHI_ST_TRANSITION_FP, - MHI_ST_TRANSITION_BHIE = MHI_ST_TRANSITION_FP, - MHI_ST_TRANSITION_MAX, -}; - -extern const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX]; -#define TO_MHI_STATE_TRANS_STR(state) (((state) >= MHI_ST_TRANSITION_MAX) ? \ - "INVALID_STATE" : mhi_state_tran_str[state]) - -enum MHI_STATE { - MHI_STATE_RESET = 0x0, - MHI_STATE_READY = 0x1, - MHI_STATE_M0 = 0x2, - MHI_STATE_M1 = 0x3, - MHI_STATE_M2 = 0x4, - MHI_STATE_M3 = 0x5, - MHI_STATE_D3 = 0x6, - MHI_STATE_BHI = 0x7, - MHI_STATE_SYS_ERR = 0xFF, - MHI_STATE_MAX, -}; - -extern const char * const mhi_state_str[MHI_STATE_MAX]; -#define TO_MHI_STATE_STR(state) ((state >= MHI_STATE_MAX || \ - !mhi_state_str[state]) ? \ - "INVALID_STATE" : mhi_state_str[state]) - -/* internal power states */ -enum MHI_PM_STATE { - MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */ - MHI_PM_POR = BIT(1), /* reset state */ - MHI_PM_M0 = BIT(2), - MHI_PM_M1 = BIT(3), - MHI_PM_M1_M2_TRANSITION = BIT(4), /* register access not allowed */ - MHI_PM_M2 = BIT(5), - MHI_PM_M3_ENTER = BIT(6), - MHI_PM_M3 = BIT(7), - MHI_PM_M3_EXIT = BIT(8), - MHI_PM_FW_DL_ERR = BIT(9), /* firmware download failure state */ - MHI_PM_SYS_ERR_DETECT = BIT(10), - MHI_PM_SYS_ERR_PROCESS = BIT(11), - MHI_PM_SHUTDOWN_PROCESS = BIT(12), - MHI_PM_LD_ERR_FATAL_DETECT = BIT(13), /* link not accessible */ -}; - -#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \ - MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ - MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \ - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR))) -#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR) -#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT) -#define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1)) -#define MHI_WAKE_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | \ - MHI_PM_M1 | MHI_PM_M2)) -#define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \ - MHI_PM_IN_ERROR_STATE(pm_state)) -#define MHI_PM_IN_SUSPEND_STATE(pm_state) (pm_state & \ - (MHI_PM_M3_ENTER | MHI_PM_M3)) - -/* accepted buffer type for the channel */ -enum MHI_XFER_TYPE { - MHI_XFER_BUFFER, - MHI_XFER_SKB, - MHI_XFER_SCLIST, - MHI_XFER_NOP, /* CPU offload channel, host does not accept transfer */ -}; - -#define NR_OF_CMD_RINGS (1) -#define CMD_EL_PER_RING (128) -#define PRIMARY_CMD_RING (0) -#define MHI_DEV_WAKE_DB (127) -#define MHI_M2_DEBOUNCE_TMR_US (10000) -#define MHI_MAX_MTU (0xffff) - -enum MHI_ER_TYPE { - MHI_ER_TYPE_INVALID = 0x0, - MHI_ER_TYPE_VALID = 0x1, -}; - -struct db_cfg { - bool reset_req; - bool db_mode; - u32 pollcfg; - enum MHI_BRSTMODE brstmode; - dma_addr_t db_val; - void (*process_db)(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_cfg, void __iomem *io_addr, - dma_addr_t db_val); -}; - -struct mhi_pm_transitions { - enum MHI_PM_STATE from_state; - u32 to_states; -}; - -struct state_transition { - struct list_head node; - enum MHI_ST_TRANSITION state; -}; - -/* Control Segment */ -struct mhi_ctrl_seg -{ - struct __packed mhi_tre hw_in_chan_ring[NUM_MHI_IPA_IN_RING_ELEMENTS] __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16); - struct __packed mhi_tre hw_out_chan_ring[NUM_MHI_IPA_OUT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); - struct __packed mhi_tre diag_in_chan_ring[NUM_MHI_IPA_OUT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); - struct __packed mhi_tre chan_ring[NUM_MHI_CHAN_RING_ELEMENTS*2*12] __aligned(NUM_MHI_CHAN_RING_ELEMENTS*16); - //struct __packed mhi_tre event_ring[NUM_MHI_EVT_RINGS][NUM_MHI_EVT_RING_ELEMENTS] __aligned(NUM_MHI_EVT_RING_ELEMENTS*16); - struct __packed mhi_tre event_ring_0[NUM_MHI_EVT_RING_ELEMENTS] __aligned(NUM_MHI_EVT_RING_ELEMENTS*16); - struct __packed mhi_tre event_ring_1[NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_OUT_EVT_RING_ELEMENTS*16); - struct __packed mhi_tre event_ring_2[NUM_MHI_IPA_IN_EVT_RING_ELEMENTS] __aligned(NUM_MHI_IPA_IN_EVT_RING_ELEMENTS*16); - struct __packed mhi_tre cmd_ring[NR_OF_CMD_RINGS][CMD_EL_PER_RING] __aligned(CMD_EL_PER_RING*16); - - struct mhi_chan_ctxt chan_ctxt[NUM_MHI_XFER_RINGS] __aligned(128); - struct mhi_event_ctxt er_ctxt[NUM_MHI_EVT_RINGS] __aligned(128); - struct mhi_cmd_ctxt cmd_ctxt[NR_OF_CMD_RINGS] __aligned(128); -} __aligned(4096); - -struct mhi_ctxt { - struct mhi_event_ctxt *er_ctxt; - struct mhi_chan_ctxt *chan_ctxt; - struct mhi_cmd_ctxt *cmd_ctxt; - dma_addr_t er_ctxt_addr; - dma_addr_t chan_ctxt_addr; - dma_addr_t cmd_ctxt_addr; - struct mhi_ctrl_seg *ctrl_seg; - dma_addr_t ctrl_seg_addr; -}; - -struct mhi_ring { - dma_addr_t dma_handle; - dma_addr_t iommu_base; - u64 *ctxt_wp; /* point to ctxt wp */ - void *pre_aligned; - void *base; - void *rp; - void *wp; - size_t el_size; - size_t len; - size_t elements; - size_t alloc_size; - void __iomem *db_addr; -}; - -struct mhi_cmd { - struct mhi_ring ring; - spinlock_t lock; -}; - -struct mhi_buf_info { - dma_addr_t p_addr; - void *v_addr; - void *wp; - size_t len; - void *cb_buf; - enum dma_data_direction dir; -}; - -struct mhi_event { - u32 er_index; - u32 intmod; - u32 msi; - int chan; /* this event ring is dedicated to a channel */ - u32 priority; - struct mhi_ring ring; - struct db_cfg db_cfg; - bool hw_ring; - bool cl_manage; - bool offload_ev; /* managed by a device driver */ - bool ctrl_ev; - spinlock_t lock; - struct mhi_chan *mhi_chan; /* dedicated to channel */ - struct tasklet_struct task; - struct mhi_controller *mhi_cntrl; -}; - -struct mhi_chan { - u32 chan; - u32 ring; - const char *name; - /* - * important, when consuming increment tre_ring first, when releasing - * decrement buf_ring first. If tre_ring has space, buf_ring - * guranteed to have space so we do not need to check both rings. - */ - struct mhi_ring buf_ring; - struct mhi_ring tre_ring; - u32 er_index; - u32 intmod; - u32 tiocm; - u32 full; - enum dma_data_direction dir; - struct db_cfg db_cfg; - enum MHI_EE ee; - enum MHI_XFER_TYPE xfer_type; - enum MHI_CH_STATE ch_state; - enum MHI_EV_CCS ccs; - bool lpm_notify; - bool configured; - bool offload_ch; - bool pre_alloc; - /* functions that generate the transfer ring elements */ - int (*gen_tre)(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, void *buf, void *cb, - size_t len, enum MHI_FLAGS flags); - int (*queue_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS flags); - /* xfer call back */ - struct mhi_device *mhi_dev; - void (*xfer_cb)(struct mhi_device *mhi_dev, struct mhi_result *res); - struct mutex mutex; - struct completion completion; - rwlock_t lock; - struct list_head node; -}; - -struct mhi_bus { - struct list_head controller_list; - struct mutex lock; - struct dentry *dentry; -}; - -struct mhi_cntrl_data { - struct mhi_ctxt mhi_ctxt; - struct mhi_cmd mhi_cmd[NR_OF_CMD_RINGS]; - struct mhi_event mhi_event[NUM_MHI_EVT_RINGS]; - struct mhi_chan mhi_chan[MHI_MAX_CHANNELS]; -}; - -/* default MHI timeout */ -#define MHI_TIMEOUT_MS (3000) -extern struct mhi_bus mhi_bus; - -/* debug fs related functions */ -int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d); -int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d); -int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d); -int mhi_debugfs_trigger_reset(void *data, u64 val); - -void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl); -void mhi_init_debugfs(struct mhi_controller *mhi_cntrl); - -/* power management apis */ -enum MHI_PM_STATE __must_check mhi_tryset_pm_state( - struct mhi_controller *mhi_cntrl, - enum MHI_PM_STATE state); -const char *to_mhi_pm_state_str(enum MHI_PM_STATE state); -void mhi_reset_chan(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -enum MHI_EE mhi_get_exec_env(struct mhi_controller *mhi_cntrl); -enum MHI_STATE mhi_get_m_state(struct mhi_controller *mhi_cntrl); -int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, - enum MHI_ST_TRANSITION state); -void mhi_pm_st_worker(struct work_struct *work); -void mhi_fw_load_worker(struct work_struct *work); -void mhi_pm_m1_worker(struct work_struct *work); -void mhi_pm_sys_err_worker(struct work_struct *work); -int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); -void mhi_ctrl_ev_task(unsigned long data); -int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl); -void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl); -int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl); -void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason); - -/* queue transfer buffer */ -int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, - void *buf, void *cb, size_t buf_len, enum MHI_FLAGS flags); -int mhi_queue_buf(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_skb(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_sclist(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_nop(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); - - -/* register access methods */ -void mhi_db_brstmode(struct mhi_controller *mhi_cntrl, struct db_cfg *db_cfg, - void __iomem *db_addr, dma_addr_t wp); -void mhi_db_brstmode_disable(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_mode, void __iomem *db_addr, - dma_addr_t wp); -int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl, - void __iomem *base, u32 offset, u32 *out); -int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl, - void __iomem *base, u32 offset, u32 mask, - u32 shift, u32 *out); -void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base, - u32 offset, u32 val); -void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base, - u32 offset, u32 mask, u32 shift, u32 val); -void mhi_ring_er_db(struct mhi_event *mhi_event); -void mhi_write_db(struct mhi_controller *mhi_cntrl, void __iomem *db_addr, - dma_addr_t wp); -void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd); -void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, enum MHI_STATE state); - -/* memory allocation methods */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 5,3,0 )) -static inline void *dma_zalloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) -{ - void *ret = dma_alloc_coherent(dev, size, dma_handle, - flag | __GFP_ZERO); - return ret; -} -#endif - -static inline void *mhi_alloc_coherent(struct mhi_controller *mhi_cntrl, - size_t size, - dma_addr_t *dma_handle, - gfp_t gfp) -{ - void *buf = dma_zalloc_coherent(mhi_cntrl->dev, size, dma_handle, gfp); - - MHI_LOG("size = %zd, dma_handle = %llx\n", size, (u64)*dma_handle); - if (buf) { - //if (*dma_handle < mhi_cntrl->iova_start || 0 == mhi_cntrl->iova_start) - // mhi_cntrl->iova_start = (*dma_handle)&0xFFF0000000; - //if ((*dma_handle + size) > mhi_cntrl->iova_stop || 0 == mhi_cntrl->iova_stop) - // mhi_cntrl->iova_stop = ((*dma_handle + size)+0x0FFFFFFF)&0xFFF0000000; - } - if (buf) - atomic_add(size, &mhi_cntrl->alloc_size); - - return buf; -} -static inline void mhi_free_coherent(struct mhi_controller *mhi_cntrl, - size_t size, - void *vaddr, - dma_addr_t dma_handle) -{ - atomic_sub(size, &mhi_cntrl->alloc_size); - dma_free_coherent(mhi_cntrl->dev, size, vaddr, dma_handle); -} -struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl); -static inline void mhi_dealloc_device(struct mhi_controller *mhi_cntrl, - struct mhi_device *mhi_dev) -{ - kfree(mhi_dev); -} -int mhi_destroy_device(struct device *dev, void *data); -void mhi_create_devices(struct mhi_controller *mhi_cntrl); -int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info **image_info, size_t alloc_size); -void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info *image_info); - -/* initialization methods */ -int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -int mhi_init_mmio(struct mhi_controller *mhi_cntrl); -int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl); -void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl); -int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl); -void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl); -int mhi_dtr_init(void); - -/* isr handlers */ -irqreturn_t mhi_msi_handlr(int irq_number, void *dev); -irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev); -irqreturn_t mhi_intvec_handlr(int irq_number, void *dev); -void mhi_ev_task(unsigned long data); - -#ifdef CONFIG_MHI_DEBUG - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) \ - panic(msg); \ -} while (0) - -#else - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) { \ - MHI_ERR(msg); \ - WARN_ON(cond); \ - } \ -} while (0) - -#endif - -#endif /* _MHI_INT_H */ diff --git a/fibocom_MHI/src/core/mhi_main.c b/fibocom_MHI/src/core/mhi_main.c deleted file mode 100644 index feae931..0000000 --- a/fibocom_MHI/src/core/mhi_main.c +++ /dev/null @@ -1,1612 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); - -int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 *out) -{ - u32 tmp = readl_relaxed(base + offset); - - /* unexpected value, query the link status */ - if (PCI_INVALID_READ(tmp) && - mhi_cntrl->link_status(mhi_cntrl, mhi_cntrl->priv_data)) - return -EIO; - - *out = tmp; - - return 0; -} - -int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 mask, - u32 shift, - u32 *out) -{ - u32 tmp; - int ret; - - ret = mhi_read_reg(mhi_cntrl, base, offset, &tmp); - if (ret) - return ret; - - *out = (tmp & mask) >> shift; - - return 0; -} - -void mhi_write_reg(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 val) -{ - writel_relaxed(val, base + offset); -} - -void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 mask, - u32 shift, - u32 val) -{ - int ret; - u32 tmp; - - ret = mhi_read_reg(mhi_cntrl, base, offset, &tmp); - if (ret) - return; - - tmp &= ~mask; - tmp |= (val << shift); - mhi_write_reg(mhi_cntrl, base, offset, tmp); -} - -void mhi_write_db(struct mhi_controller *mhi_cntrl, - void __iomem *db_addr, - dma_addr_t wp) -{ - mhi_write_reg(mhi_cntrl, db_addr, 4, upper_32_bits(wp)); - mhi_write_reg(mhi_cntrl, db_addr, 0, lower_32_bits(wp)); -} - -void mhi_db_brstmode(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_cfg, - void __iomem *db_addr, - dma_addr_t wp) -{ - if (db_cfg->db_mode) { - db_cfg->db_val = wp; - mhi_write_db(mhi_cntrl, db_addr, wp); - db_cfg->db_mode = 0; - } -} - -void mhi_db_brstmode_disable(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_cfg, - void __iomem *db_addr, - dma_addr_t wp) -{ - db_cfg->db_val = wp; - mhi_write_db(mhi_cntrl, db_addr, wp); -} - -void mhi_ring_er_db(struct mhi_event *mhi_event) -{ - struct mhi_ring *ring = &mhi_event->ring; - - mhi_event->db_cfg.process_db(mhi_event->mhi_cntrl, &mhi_event->db_cfg, - ring->db_addr, le64_to_cpu(*ring->ctxt_wp)); -} - -void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd) -{ - dma_addr_t db; - struct mhi_ring *ring = &mhi_cmd->ring; - - db = ring->iommu_base + (ring->wp - ring->base); - *ring->ctxt_wp = cpu_to_le64(db); - mhi_write_db(mhi_cntrl, ring->db_addr, db); -} - -void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *ring = &mhi_chan->tre_ring; - dma_addr_t db; - - db = ring->iommu_base + (ring->wp - ring->base); - *ring->ctxt_wp = cpu_to_le64(db); - mhi_chan->db_cfg.process_db(mhi_cntrl, &mhi_chan->db_cfg, ring->db_addr, - db); -} - -enum MHI_EE mhi_get_exec_env(struct mhi_controller *mhi_cntrl) -{ - u32 exec; - int ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_EXECENV, &exec); - - return (ret) ? MHI_EE_MAX : exec; -} - -enum MHI_STATE mhi_get_m_state(struct mhi_controller *mhi_cntrl) -{ - u32 state; - int ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MHISTATUS, - MHISTATUS_MHISTATE_MASK, - MHISTATUS_MHISTATE_SHIFT, &state); - return ret ? MHI_STATE_MAX : state; -} - -int mhi_queue_sclist(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - return -EINVAL; -} - -int mhi_queue_nop(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - return -EINVAL; -} - -static void mhi_add_ring_element(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - ring->wp += ring->el_size; - if (ring->wp >= (ring->base + ring->len)) - ring->wp = ring->base; - /* smp update */ - smp_wmb(); -} - -static void mhi_del_ring_element(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - ring->rp += ring->el_size; - if (ring->rp >= (ring->base + ring->len)) - ring->rp = ring->base; - /* smp update */ - smp_wmb(); -} - -static int get_nr_avail_ring_elements(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - int nr_el; - - if (ring->wp < ring->rp) - nr_el = ((ring->rp - ring->wp) / ring->el_size) - 1; - else { - nr_el = (ring->rp - ring->base) / ring->el_size; - nr_el += ((ring->base + ring->len - ring->wp) / - ring->el_size) - 1; - } - return nr_el; -} - -static void *mhi_to_virtual(struct mhi_ring *ring, dma_addr_t addr) -{ - return (addr - ring->iommu_base) + ring->base; -} - -dma_addr_t mhi_to_physical(struct mhi_ring *ring, void *addr) -{ - return (addr - ring->base) + ring->iommu_base; -} - -static void mhi_recycle_ev_ring_element(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - dma_addr_t ctxt_wp; - - /* update the WP */ - ring->wp += ring->el_size; - ctxt_wp = le64_to_cpu(*ring->ctxt_wp) + ring->el_size; - - if (ring->wp >= (ring->base + ring->len)) { - ring->wp = ring->base; - ctxt_wp = ring->iommu_base; - } - - *ring->ctxt_wp = cpu_to_le64(ctxt_wp); - - /* update the RP */ - //memset((unsigned char *)ring->rp, 0x55, ring->el_size); //carl.yin debug - ring->rp += ring->el_size; - if (ring->rp >= (ring->base + ring->len)) - ring->rp = ring->base; - - /* visible to other cores */ - smp_wmb(); -} - -static bool mhi_is_ring_full(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - void *tmp = ring->wp + ring->el_size; - - if (tmp >= (ring->base + ring->len)) - tmp = ring->base; - - return (tmp == ring->rp); -} - -int mhi_queue_skb(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - struct sk_buff *skb = buf; - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - struct mhi_ring *buf_ring = &mhi_chan->buf_ring; - struct mhi_buf_info *buf_info; - struct mhi_tre *mhi_tre; - - if (mhi_is_ring_full(mhi_cntrl, tre_ring)) - return -ENOMEM; - - read_lock_bh(&mhi_cntrl->pm_lock); - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_ERR("MHI is not in activate state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return -EIO; - } - - /* we're in M3 or transitioning to M3 */ - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - mhi_cntrl->wake_get(mhi_cntrl, false); - - /* generate the tre */ - buf_info = buf_ring->wp; - buf_info->v_addr = skb->data; - buf_info->cb_buf = skb; - buf_info->wp = tre_ring->wp; - buf_info->dir = mhi_chan->dir; - buf_info->len = len; - buf_info->p_addr = dma_map_single(mhi_cntrl->dev, buf_info->v_addr, len, - buf_info->dir); - - if (dma_mapping_error(mhi_cntrl->dev, buf_info->p_addr)) - goto map_error; - - mhi_tre = tre_ring->wp; - mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr); - mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_info->len); - mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(1, 1, 0, 0); - - MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, - (u64)mhi_to_physical(tre_ring, mhi_tre), le64_to_cpu(mhi_tre->ptr), - le32_to_cpu(mhi_tre->dword[0]), le32_to_cpu(mhi_tre->dword[1])); - - /* increment WP */ - mhi_add_ring_element(mhi_cntrl, tre_ring); - mhi_add_ring_element(mhi_cntrl, buf_ring); - - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) { - read_lock_bh(&mhi_chan->lock); - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - read_unlock_bh(&mhi_chan->lock); - } - - if (mhi_chan->dir == DMA_FROM_DEVICE) { - bool override = (mhi_cntrl->pm_state != MHI_PM_M0); - - mhi_cntrl->wake_put(mhi_cntrl, override); - } - - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; - -map_error: - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return -ENOMEM; -} - -int mhi_gen_tre(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, - void *buf, - void *cb, - size_t buf_len, - enum MHI_FLAGS flags) -{ - struct mhi_ring *buf_ring, *tre_ring; - struct mhi_tre *mhi_tre; - struct mhi_buf_info *buf_info; - int eot, eob, chain, bei; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - - buf_info = buf_ring->wp; - buf_info->v_addr = buf; - buf_info->cb_buf = cb; - buf_info->wp = tre_ring->wp; - buf_info->dir = mhi_chan->dir; - buf_info->len = buf_len; - buf_info->p_addr = dma_map_single(mhi_cntrl->dev, buf, buf_len, - buf_info->dir); - - if (dma_mapping_error(mhi_cntrl->dev, buf_info->p_addr)) - return -ENOMEM; - - eob = !!(flags & MHI_EOB); - eot = !!(flags & MHI_EOT); - chain = !!(flags & MHI_CHAIN); - bei = !!(mhi_chan->intmod); - - mhi_tre = tre_ring->wp; - mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr); - mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_len); - mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain); - - MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, - (u64)mhi_to_physical(tre_ring, mhi_tre), le64_to_cpu(mhi_tre->ptr), - le32_to_cpu(mhi_tre->dword[0]), le32_to_cpu(mhi_tre->dword[1])); - - /* increment WP */ - mhi_add_ring_element(mhi_cntrl, tre_ring); - mhi_add_ring_element(mhi_cntrl, buf_ring); - - return 0; -} - -int mhi_queue_buf(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_ring *tre_ring; - unsigned long flags; - int ret; - - read_lock_irqsave(&mhi_cntrl->pm_lock, flags); - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_ERR("MHI is not in active state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - - return -EIO; - } - - /* we're in M3 or transitioning to M3 */ - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - - tre_ring = &mhi_chan->tre_ring; - if (mhi_is_ring_full(mhi_cntrl, tre_ring)) - goto error_queue; - - ret = mhi_chan->gen_tre(mhi_cntrl, mhi_chan, buf, buf, len, mflags); - if (unlikely(ret)) - goto error_queue; - - read_lock_irqsave(&mhi_cntrl->pm_lock, flags); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) { - unsigned long flags; - - read_lock_irqsave(&mhi_chan->lock, flags); - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - read_unlock_irqrestore(&mhi_chan->lock, flags); - } - - if (mhi_chan->dir == DMA_FROM_DEVICE) { - bool override = (mhi_cntrl->pm_state != MHI_PM_M0); - - mhi_cntrl->wake_put(mhi_cntrl, override); - } - - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - - return 0; - -error_queue: - read_lock_irqsave(&mhi_cntrl->pm_lock, flags); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - - return -ENOMEM; -} - -/* destroy specific device */ -int mhi_destroy_device(struct device *dev, void *data) -{ - struct mhi_device *mhi_dev; - struct mhi_driver *mhi_drv; - struct mhi_controller *mhi_cntrl; - struct mhi_chan *mhi_chan; - int dir; - - if (dev->bus != &mhi_bus_type) - return 0; - - mhi_dev = to_mhi_device(dev); - mhi_drv = to_mhi_driver(dev->driver); - mhi_cntrl = mhi_dev->mhi_cntrl; - - MHI_LOG("destroy device for chan:%s\n", mhi_dev->chan_name); - - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - /* remove device associated with the channel */ - mutex_lock(&mhi_chan->mutex); - mutex_unlock(&mhi_chan->mutex); - } - - /* notify the client and remove the device from mhi bus */ - device_del(dev); - - return 0; -} - -void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason) -{ - struct mhi_driver *mhi_drv; - - if (!mhi_dev->dev.driver) - return; - - mhi_drv = to_mhi_driver(mhi_dev->dev.driver); - - if (mhi_drv->status_cb) - mhi_drv->status_cb(mhi_dev, cb_reason); -} - -/* bind mhi channels into mhi devices */ -void mhi_create_devices(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_chan *mhi_chan; - struct mhi_device *mhi_dev; - int ret; - - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { - if (!mhi_chan->configured || mhi_chan->ee != mhi_cntrl->ee) - continue; - mhi_dev = mhi_alloc_device(mhi_cntrl); - if (!mhi_dev) - return; - - if (mhi_chan->dir == DMA_TO_DEVICE) { - mhi_dev->ul_chan = mhi_chan; - mhi_dev->ul_chan_id = mhi_chan->chan; - mhi_dev->ul_xfer = mhi_chan->queue_xfer; - mhi_dev->ul_event_id = mhi_chan->er_index; - } else { - mhi_dev->dl_chan = mhi_chan; - mhi_dev->dl_chan_id = mhi_chan->chan; - mhi_dev->dl_xfer = mhi_chan->queue_xfer; - mhi_dev->dl_event_id = mhi_chan->er_index; - } - - mhi_chan->mhi_dev = mhi_dev; - - /* check next channel if it matches */ - if ((i + 1) < mhi_cntrl->max_chan && mhi_chan[1].configured) { - if (!strcmp(mhi_chan[1].name, mhi_chan->name)) { - i++; - mhi_chan++; - if (mhi_chan->dir == DMA_TO_DEVICE) { - mhi_dev->ul_chan = mhi_chan; - mhi_dev->ul_chan_id = mhi_chan->chan; - mhi_dev->ul_xfer = mhi_chan->queue_xfer; - mhi_dev->ul_event_id = - mhi_chan->er_index; - } else { - mhi_dev->dl_chan = mhi_chan; - mhi_dev->dl_chan_id = mhi_chan->chan; - mhi_dev->dl_xfer = mhi_chan->queue_xfer; - mhi_dev->dl_event_id = - mhi_chan->er_index; - } - mhi_chan->mhi_dev = mhi_dev; - } - } - - mhi_dev->chan_name = mhi_chan->name; - dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u_%s", - mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus, - mhi_dev->slot, mhi_dev->chan_name); - - ret = device_add(&mhi_dev->dev); - if (ret) { - MHI_ERR("Failed to register dev for chan:%s\n", - mhi_dev->chan_name); - mhi_dealloc_device(mhi_cntrl, mhi_dev); - } - } - - //mhi_cntrl->klog_lvl = MHI_MSG_LVL_ERROR; -} - -static int parse_xfer_event(struct mhi_controller *mhi_cntrl, - struct mhi_tre *event, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring, *tre_ring; - u32 ev_code; - struct mhi_result result; - unsigned long flags = 0; - - ev_code = MHI_TRE_GET_EV_CODE(event); - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - - if (CHAN_INBOUND(mhi_chan->chan) && (tre_ring->rp + tre_ring->el_size == tre_ring->wp)) { - mhi_chan->full++; - } - - result.transaction_status = (ev_code == MHI_EV_CC_OVERFLOW) ? - -EOVERFLOW : 0; - - /* - * if it's a DB Event then we need to grab the lock - * with preemption disable and as a write because we - * have to update db register and another thread could - * be doing same. - */ - if (ev_code >= MHI_EV_CC_OOB) - write_lock_irqsave(&mhi_chan->lock, flags); - else - read_lock_bh(&mhi_chan->lock); - - if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) - goto end_process_tx_event; - - switch (ev_code) { - case MHI_EV_CC_OVERFLOW: - case MHI_EV_CC_EOB: - case MHI_EV_CC_EOT: - { - dma_addr_t ptr = MHI_TRE_GET_EV_PTR(event); - struct mhi_tre *local_rp, *ev_tre; - void *dev_rp; - struct mhi_buf_info *buf_info; - u16 xfer_len; - - /* Get the TRB this event points to */ - ev_tre = mhi_to_virtual(tre_ring, ptr); - - /* device rp after servicing the TREs */ - dev_rp = ev_tre + 1; - if (dev_rp >= (tre_ring->base + tre_ring->len)) - dev_rp = tre_ring->base; - - result.dir = mhi_chan->dir; - - /* local rp */ - local_rp = tre_ring->rp; - MHI_VERB("base=%p, local_wp=%p, local_rp=%p, dev_rp=%p\n", tre_ring->base, tre_ring->wp, tre_ring->rp, dev_rp); - while (local_rp != dev_rp) { - buf_info = buf_ring->rp; - /* if it's last tre get len from the event */ - if (local_rp == ev_tre) - xfer_len = MHI_TRE_GET_EV_LEN(event); - else - xfer_len = buf_info->len; - - dma_unmap_single(mhi_cntrl->dev, buf_info->p_addr, - buf_info->len, buf_info->dir); - - result.buf_addr = buf_info->cb_buf; - result.bytes_xferd = xfer_len; - mhi_del_ring_element(mhi_cntrl, buf_ring); - mhi_del_ring_element(mhi_cntrl, tre_ring); - local_rp = tre_ring->rp; - - MHI_VERB("buf_addr=%p, bytes_xferd=%zd\n", result.buf_addr, result.bytes_xferd); - /* notify client */ - mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result); - - if (mhi_chan->dir == DMA_TO_DEVICE) { - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - } - - /* - * recycle the buffer if buffer is pre-allocated, - * if there is error, not much we can do apart from - * dropping the packet - */ - if (mhi_chan->pre_alloc) { - if (mhi_queue_buf(mhi_chan->mhi_dev, mhi_chan, - buf_info->cb_buf, - buf_info->len, MHI_EOT)) { - MHI_ERR( - "Error recycling buffer for chan:%d\n", - mhi_chan->chan); - kfree(buf_info->cb_buf); - } - } - }; - break; - } /* CC_EOT */ - case MHI_EV_CC_OOB: - case MHI_EV_CC_DB_MODE: - { - unsigned long flags; - - MHI_VERB("DB_MODE/OOB Detected chan %d.\n", mhi_chan->chan); - mhi_chan->db_cfg.db_mode = 1; - read_lock_irqsave(&mhi_cntrl->pm_lock, flags); - if (tre_ring->wp != tre_ring->rp && - MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state)) { - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - } - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - break; - } - case MHI_EV_CC_BAD_TRE: - MHI_ASSERT(1, "Received BAD TRE event for ring"); - break; - default: - MHI_CRITICAL("Unknown TX completion.\n"); - - break; - } /* switch(MHI_EV_READ_CODE(EV_TRB_CODE,event)) */ - -end_process_tx_event: - if (ev_code >= MHI_EV_CC_OOB) - write_unlock_irqrestore(&mhi_chan->lock, flags); - else - read_unlock_bh(&mhi_chan->lock); - - return 0; -} - -#include "mhi_common.h" -static void mhi_dump_tre(struct mhi_controller *mhi_cntrl, struct mhi_tre *_ev) { - union mhi_dev_ring_element_type *ev = (union mhi_dev_ring_element_type *)_ev; - - switch (ev->generic.type) { - case MHI_DEV_RING_EL_INVALID: { - MHI_ERR("carl_ev cmd_invalid, ptr=%llx, %x, %x\n", _ev->ptr, _ev->dword[0], _ev->dword[1]); - } - break; - case MHI_DEV_RING_EL_NOOP: { - MHI_LOG("carl_ev cmd_no_op chan=%u\n", ev->cmd_no_op.chid); - } - break; - case MHI_DEV_RING_EL_TRANSFER: { - MHI_LOG("carl_ev tre data=%llx, len=%u, chan=%u\n", - ev->tre.data_buf_ptr, ev->tre.len, ev->tre.chain); - } - break; - case MHI_DEV_RING_EL_RESET: { - MHI_LOG("carl_ev cmd_reset chan=%u\n", ev->cmd_reset.chid); - } - break; - case MHI_DEV_RING_EL_STOP: { - MHI_LOG("carl_ev cmd_stop chan=%u\n", ev->cmd_stop.chid); - } - break; - case MHI_DEV_RING_EL_START: { - MHI_LOG("carl_ev cmd_start chan=%u\n", ev->cmd_start.chid); - } - break; - case MHI_DEV_RING_EL_MHI_STATE_CHG: { - MHI_LOG("carl_ev evt_state_change mhistate=%u\n", ev->evt_state_change.mhistate); - } - break; - case MHI_DEV_RING_EL_CMD_COMPLETION_EVT:{ - MHI_LOG("carl_ev evt_cmd_comp code=%u\n", ev->evt_cmd_comp.code); - } - break; - case MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT:{ - MHI_VERB("carl_ev evt_tr_comp ptr=%llx, len=%u, code=%u, chan=%u\n", - ev->evt_tr_comp.ptr, ev->evt_tr_comp.len, ev->evt_tr_comp.code, ev->evt_tr_comp.chid); - } - break; - case MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY:{ - MHI_LOG("carl_ev evt_ee_state execenv=%u\n", ev->evt_ee_state.execenv); - } - break; - case MHI_DEV_RING_EL_UNDEF: - default: { - MHI_ERR("carl_ev el_undef type=%d\n", ev->generic.type); - }; - break; - } -} - - -static int mhi_process_event_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, - u32 event_quota) -{ - struct mhi_tre *dev_rp, *local_rp; - struct mhi_ring *ev_ring = &mhi_event->ring; - struct mhi_event_ctxt *er_ctxt = - &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; - int count = 0; - - read_lock_bh(&mhi_cntrl->pm_lock); - if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) { - MHI_ERR("No EV access, PM_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_unlock_bh(&mhi_cntrl->pm_lock); - return -EIO; - } - - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - dev_rp = mhi_to_virtual(ev_ring, le64_to_cpu(er_ctxt->rp)); - local_rp = ev_ring->rp; - - while (dev_rp != local_rp && event_quota > 0) { - enum MHI_PKT_TYPE type = MHI_TRE_GET_EV_TYPE(local_rp); - - mhi_dump_tre(mhi_cntrl, local_rp); - MHI_VERB("Processing Event:0x%llx 0x%08x 0x%08x\n", - local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); - - switch (type) { - case MHI_PKT_TYPE_TX_EVENT: - { - u32 chan; - struct mhi_chan *mhi_chan; - - chan = MHI_TRE_GET_EV_CHID(local_rp); - mhi_chan = &mhi_cntrl->mhi_chan[chan]; - parse_xfer_event(mhi_cntrl, local_rp, mhi_chan); - event_quota--; - break; - } - case MHI_PKT_TYPE_STATE_CHANGE_EVENT: - { - enum MHI_STATE new_state; - - new_state = MHI_TRE_GET_EV_STATE(local_rp); - - MHI_LOG("MHI state change event to state:%s\n", - TO_MHI_STATE_STR(new_state)); - - switch (new_state) { - case MHI_STATE_M0: - mhi_pm_m0_transition(mhi_cntrl); - break; - case MHI_STATE_M1: - mhi_pm_m1_transition(mhi_cntrl); - break; - case MHI_STATE_M3: - mhi_pm_m3_transition(mhi_cntrl); - break; - case MHI_STATE_SYS_ERR: - { - enum MHI_PM_STATE new_state; - - MHI_ERR("MHI system error detected\n"); - write_lock_irq(&mhi_cntrl->pm_lock); - new_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_SYS_ERR_DETECT); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (new_state == MHI_PM_SYS_ERR_DETECT) - schedule_work( - &mhi_cntrl->syserr_worker); - break; - } - default: - MHI_ERR("Unsupported STE:%s\n", - TO_MHI_STATE_STR(new_state)); - } - - break; - } - case MHI_PKT_TYPE_CMD_COMPLETION_EVENT: - { - dma_addr_t ptr = MHI_TRE_GET_EV_PTR(local_rp); - struct mhi_cmd *cmd_ring = - &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING]; - struct mhi_ring *mhi_ring = &cmd_ring->ring; - struct mhi_tre *cmd_pkt; - struct mhi_chan *mhi_chan; - u32 chan; - - cmd_pkt = mhi_to_virtual(mhi_ring, ptr); - - /* out of order completion received */ - MHI_ASSERT(cmd_pkt != mhi_ring->rp, - "Out of order cmd completion"); - - chan = MHI_TRE_GET_CMD_CHID(cmd_pkt); - - mhi_chan = &mhi_cntrl->mhi_chan[chan]; - write_lock_bh(&mhi_chan->lock); - mhi_chan->ccs = MHI_TRE_GET_EV_CODE(local_rp); - complete(&mhi_chan->completion); - write_unlock_bh(&mhi_chan->lock); - mhi_del_ring_element(mhi_cntrl, mhi_ring); - break; - } - case MHI_PKT_TYPE_EE_EVENT: - { - enum MHI_ST_TRANSITION st = MHI_ST_TRANSITION_MAX; - enum MHI_EE event = MHI_TRE_GET_EV_EXECENV(local_rp); - - MHI_LOG("MHI EE received event:%s, old EE:%s\n", - TO_MHI_EXEC_STR(event), TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - switch (event) { - case MHI_EE_SBL: - st = MHI_ST_TRANSITION_SBL; - break; - case MHI_EE_AMSS: - st = MHI_ST_TRANSITION_AMSS; - break; - case MHI_EE_RDDM: - mhi_cntrl->status_cb(mhi_cntrl, - mhi_cntrl->priv_data, - MHI_CB_EE_RDDM); - break; - /* fall thru to wake up the event */ - case MHI_EE_WFW: - case MHI_EE_PT: - case MHI_EE_EDL: - case MHI_EE_FP: - case MHI_EE_UEFI: - write_lock_irq(&mhi_cntrl->pm_lock); - if (event == MHI_EE_FP) - st = MHI_ST_TRANSITION_FP; - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up(&mhi_cntrl->state_event); - break; - default: - MHI_ERR("Unhandled EE event:%s\n", - TO_MHI_EXEC_STR(event)); - } - if (st != MHI_ST_TRANSITION_MAX) - mhi_queue_state_transition(mhi_cntrl, st); - break; - } - case MHI_PKT_TYPE_STALE_EVENT: - MHI_VERB("Stale Event received for chan:%u\n", - MHI_TRE_GET_EV_CHID(local_rp)); - break; - default: - //MHI_ERR("Unsupported packet type code 0x%x\n", type); - break; - } - - memset((unsigned char *)ev_ring->rp, 0x00, ev_ring->el_size); //carl.yin debug - mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring); - local_rp = ev_ring->rp; - dev_rp = mhi_to_virtual(ev_ring, le64_to_cpu(er_ctxt->rp)); - count++; - } - read_lock_bh(&mhi_cntrl->pm_lock); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_er_db(mhi_event); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - MHI_VERB("exit er_index:%u\n", mhi_event->er_index); - return count; -} - -void mhi_ev_task(unsigned long data) -{ - struct mhi_event *mhi_event = (struct mhi_event *)data; - struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; - - MHI_VERB("Enter for ev_index:%d\n", mhi_event->er_index); - - /* process all pending events */ - spin_lock_bh(&mhi_event->lock); - mhi_process_event_ring(mhi_cntrl, mhi_event, U32_MAX); - spin_unlock_bh(&mhi_event->lock); -} - -void mhi_ctrl_ev_task(unsigned long data) -{ - struct mhi_event *mhi_event = (struct mhi_event *)data; - struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; - enum MHI_STATE state = MHI_STATE_MAX; - enum MHI_PM_STATE pm_state = 0; - int ret; - - MHI_VERB("Enter for ev_index:%d\n", mhi_event->er_index); - - /* process ctrl events events */ - ret = mhi_process_event_ring(mhi_cntrl, mhi_event, U32_MAX); - - /* - * we received a MSI but no events to process maybe device went to - * SYS_ERR state, check the state - */ - if (!ret) { - write_lock_irq(&mhi_cntrl->pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - state = mhi_get_m_state(mhi_cntrl); - if (state == MHI_STATE_SYS_ERR) { - MHI_ERR("MHI system error detected\n"); - pm_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_SYS_ERR_DETECT); - } - write_unlock_irq(&mhi_cntrl->pm_lock); - if (pm_state == MHI_PM_SYS_ERR_DETECT) - schedule_work(&mhi_cntrl->syserr_worker); - } -} - -irqreturn_t mhi_msi_handlr(int irq_number, void *dev) -{ - struct mhi_event *mhi_event = dev; - struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; - struct mhi_event_ctxt *er_ctxt = - &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; - struct mhi_ring *ev_ring = &mhi_event->ring; - void *dev_rp = mhi_to_virtual(ev_ring, le64_to_cpu(er_ctxt->rp)); - - if (mhi_cntrl->msi_allocated == 1) - { - unsigned long flags; - int i; - enum MHI_STATE mhi_state = mhi_get_m_state(mhi_cntrl); - - if (mhi_state == MHI_STATE_SYS_ERR) { - enum MHI_PM_STATE pm_state = 0; - - MHI_ERR("MHI system error detected\n"); - write_lock_irqsave(&mhi_cntrl->pm_lock, flags); - pm_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT); - write_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - if (pm_state == MHI_PM_SYS_ERR_DETECT) - schedule_work(&mhi_cntrl->syserr_worker); - } else if (mhi_state != mhi_cntrl->dev_state) { - MHI_LOG("MHISTATUS %s -> %s\n", TO_MHI_STATE_STR(mhi_cntrl->dev_state), TO_MHI_STATE_STR(mhi_state)); - wake_up(&mhi_cntrl->state_event); - } - - er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; - mhi_event = mhi_cntrl->data->mhi_event; - for (i = 0; i < NUM_MHI_EVT_RINGS; i++, er_ctxt++, mhi_event++) { - struct mhi_ring *ev_ring = &mhi_event->ring; - void *dev_rp = mhi_to_virtual(ev_ring, le64_to_cpu(er_ctxt->rp)); - - if (ev_ring->rp != dev_rp) { - MHI_VERB("local_rp=%p vs dev_rp=%p\n", ev_ring->rp, dev_rp); - if (mhi_event->priority == MHI_ER_PRIORITY_HIGH) - { - tasklet_hi_schedule(&mhi_event->task); - } - else - { - tasklet_schedule(&mhi_event->task); - } - } - } - - return IRQ_HANDLED; - } - - /* confirm ER has pending events to process before scheduling work */ - if (ev_ring->rp == dev_rp) - return IRQ_HANDLED; - - /* client managed event ring, notify pending data */ - if (mhi_event->cl_manage) { - struct mhi_chan *mhi_chan = mhi_event->mhi_chan; - struct mhi_device *mhi_dev = mhi_chan->mhi_dev; - - if (mhi_dev) - mhi_dev->status_cb(mhi_dev, MHI_CB_PENDING_DATA); - } - else - { - if (mhi_event->priority == MHI_ER_PRIORITY_HIGH) - { - tasklet_hi_schedule(&mhi_event->task); - } - else - { - tasklet_schedule(&mhi_event->task); - } - } - - return IRQ_HANDLED; -} - -/* this is the threaded fn */ -irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) -{ - struct mhi_controller *mhi_cntrl = dev; - enum MHI_STATE state = MHI_STATE_MAX; - enum MHI_PM_STATE pm_state = 0; - - MHI_VERB("Enter\n"); - - write_lock_irq(&mhi_cntrl->pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - state = mhi_get_m_state(mhi_cntrl); - if (state == MHI_STATE_SYS_ERR) { - MHI_ERR("MHI system error detected\n"); - pm_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_SYS_ERR_DETECT); - } - write_unlock_irq(&mhi_cntrl->pm_lock); - if (pm_state == MHI_PM_SYS_ERR_DETECT) - schedule_work(&mhi_cntrl->syserr_worker); - - MHI_VERB("Exit\n"); - - return IRQ_HANDLED; -} - -irqreturn_t mhi_intvec_handlr(int irq_number, void *dev) -{ - - struct mhi_controller *mhi_cntrl = dev; - - /* wake up any events waiting for state change */ - MHI_VERB("Enter\n"); - wake_up(&mhi_cntrl->state_event); - MHI_VERB("Exit\n"); - - return IRQ_WAKE_THREAD; -} - -static int mhi_send_cmd(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, - enum MHI_CMD cmd) -{ - struct mhi_tre *cmd_tre = NULL; - struct mhi_cmd *mhi_cmd = &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING]; - struct mhi_ring *ring = &mhi_cmd->ring; - int chan = mhi_chan->chan; - - MHI_VERB("Entered, MHI pm_state:%s dev_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - /* MHI host currently handles RESET and START cmd */ - if (cmd != MHI_CMD_START_CHAN && cmd != MHI_CMD_RESET_CHAN) - return -EINVAL; - - spin_lock_bh(&mhi_cmd->lock); - if (!get_nr_avail_ring_elements(mhi_cntrl, ring)) { - spin_unlock_bh(&mhi_cmd->lock); - return -ENOMEM; - } - - /* prepare the cmd tre */ - cmd_tre = ring->wp; - if (cmd == MHI_CMD_START_CHAN) { - cmd_tre->ptr = MHI_TRE_CMD_START_PTR; - cmd_tre->dword[0] = MHI_TRE_CMD_START_DWORD0; - cmd_tre->dword[1] = MHI_TRE_CMD_START_DWORD1(chan); - } else { - cmd_tre->ptr = MHI_TRE_CMD_RESET_PTR; - cmd_tre->dword[0] = MHI_TRE_CMD_RESET_DWORD0; - cmd_tre->dword[1] = MHI_TRE_CMD_RESET_DWORD1(chan); - } - - MHI_VERB("WP:0x%llx TRE: 0x%llx 0x%08x 0x%08x\n", - (u64)mhi_to_physical(ring, cmd_tre), le64_to_cpu(cmd_tre->ptr), - le32_to_cpu(cmd_tre->dword[0]), le32_to_cpu(cmd_tre->dword[1])); - - /* queue to hardware */ - mhi_add_ring_element(mhi_cntrl, ring); - read_lock_bh(&mhi_cntrl->pm_lock); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_cmd_db(mhi_cntrl, mhi_cmd); - read_unlock_bh(&mhi_cntrl->pm_lock); - spin_unlock_bh(&mhi_cmd->lock); - - return 0; -} - -static int __mhi_prepare_channel(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - int ret = 0; - - MHI_LOG("Entered: preparing channel:%d\n", mhi_chan->chan); - - if (mhi_cntrl->ee != mhi_chan->ee) { - MHI_ERR("Current EE:%s Required EE:%s for chan:%s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee), - TO_MHI_EXEC_STR(mhi_chan->ee), - mhi_chan->name); - return -ENOTCONN; - } - - mutex_lock(&mhi_chan->mutex); - /* client manages channel context for offload channels */ - if (!mhi_chan->offload_ch) { - ret = mhi_init_chan_ctxt(mhi_cntrl, mhi_chan); - if (ret) { - MHI_ERR("Error with init chan\n"); - goto error_init_chan; - } - } - - reinit_completion(&mhi_chan->completion); - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI host is not in active state\n"); - read_unlock_bh(&mhi_cntrl->pm_lock); - ret = -EIO; - goto error_pm_state; - } - - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - - ret = mhi_send_cmd(mhi_cntrl, mhi_chan, MHI_CMD_START_CHAN); - if (ret) { - MHI_ERR("Failed to send start chan cmd\n"); - goto error_send_cmd; - } - - ret = wait_for_completion_timeout(&mhi_chan->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret || mhi_chan->ccs != MHI_EV_CC_SUCCESS) { - MHI_ERR("Failed to receive cmd completion for chan:%d\n", - mhi_chan->chan); - ret = -EIO; - goto error_send_cmd; - } - - write_lock_irq(&mhi_chan->lock); - mhi_chan->ch_state = MHI_CH_STATE_ENABLED; - write_unlock_irq(&mhi_chan->lock); - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - /* pre allocate buffer for xfer ring */ - if (mhi_chan->pre_alloc) { - struct mhi_device *mhi_dev = mhi_chan->mhi_dev; - int nr_el = get_nr_avail_ring_elements(mhi_cntrl, - &mhi_chan->tre_ring); - - while (nr_el--) { - void *buf; - - buf = kmalloc(MHI_MAX_MTU, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto error_pre_alloc; - } - - ret = mhi_queue_buf(mhi_dev, mhi_chan, buf, MHI_MAX_MTU, - MHI_EOT); - if (ret) { - MHI_ERR("Chan:%d error queue buffer\n", - mhi_chan->chan); - kfree(buf); - goto error_pre_alloc; - } - } - } - - mutex_unlock(&mhi_chan->mutex); - - MHI_LOG("Chan:%d successfully moved to start state\n", mhi_chan->chan); - - return 0; - -error_send_cmd: - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - -error_pm_state: - if (!mhi_chan->offload_ch) - mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); - -error_init_chan: - mutex_unlock(&mhi_chan->mutex); - - return ret; - -error_pre_alloc: - mutex_unlock(&mhi_chan->mutex); - __mhi_unprepare_channel(mhi_cntrl, mhi_chan); - - return ret; -} - -void mhi_reset_chan(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan) -{ - struct mhi_tre *dev_rp, *local_rp; - struct mhi_event_ctxt *er_ctxt; - struct mhi_event *mhi_event; - struct mhi_ring *ev_ring, *buf_ring, *tre_ring; - unsigned long flags; - int chan = mhi_chan->chan; - struct mhi_result result; - - /* nothing to reset, client don't queue buffers */ - if (mhi_chan->offload_ch) - return; - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_event = &mhi_cntrl->mhi_event[mhi_chan->er_index]; - ev_ring = &mhi_event->ring; - er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_chan->er_index]; - - MHI_LOG("Marking all events for chan:%d as stale\n", chan); - - /* mark all stale events related to channel as STALE event */ - spin_lock_irqsave(&mhi_event->lock, flags); - dev_rp = mhi_to_virtual(ev_ring, le64_to_cpu(er_ctxt->rp)); - if (!mhi_event->mhi_chan) { - local_rp = ev_ring->rp; - while (dev_rp != local_rp) { - if (MHI_TRE_GET_EV_TYPE(local_rp) == - MHI_PKT_TYPE_TX_EVENT && - chan == MHI_TRE_GET_EV_CHID(local_rp)) - local_rp->dword[1] = MHI_TRE_EV_DWORD1(chan, - MHI_PKT_TYPE_STALE_EVENT); - local_rp++; - if (local_rp == (ev_ring->base + ev_ring->len)) - local_rp = ev_ring->base; - } - } else { - /* dedicated event ring so move the ptr to end */ - ev_ring->rp = dev_rp; - ev_ring->wp = ev_ring->rp - ev_ring->el_size; - if (ev_ring->wp < ev_ring->base) - ev_ring->wp = ev_ring->base + ev_ring->len - - ev_ring->el_size; - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_er_db(mhi_event); - } - - MHI_LOG("Finished marking events as stale events\n"); - spin_unlock_irqrestore(&mhi_event->lock, flags); - - /* reset any pending buffers */ - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - result.transaction_status = -ENOTCONN; - result.bytes_xferd = 0; - while (tre_ring->rp != tre_ring->wp) { - struct mhi_buf_info *buf_info = buf_ring->rp; - - if (mhi_chan->dir == DMA_TO_DEVICE) - mhi_cntrl->wake_put(mhi_cntrl, false); - - dma_unmap_single(mhi_cntrl->dev, buf_info->p_addr, - buf_info->len, buf_info->dir); - mhi_del_ring_element(mhi_cntrl, buf_ring); - mhi_del_ring_element(mhi_cntrl, tre_ring); - - if (mhi_chan->pre_alloc) { - kfree(buf_info->cb_buf); - } else { - result.buf_addr = buf_info->cb_buf; - mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result); - } - } - - read_unlock_bh(&mhi_cntrl->pm_lock); - MHI_LOG("Reset complete.\n"); -} - -static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - int ret; - - MHI_LOG("Entered: unprepare channel:%d\n", mhi_chan->chan); - - /* no more processing events for this channel */ - mutex_lock(&mhi_chan->mutex); - write_lock_irq(&mhi_chan->lock); - if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) { - MHI_LOG("chan:%d is already disabled\n", mhi_chan->chan); - write_unlock_irq(&mhi_chan->lock); - mutex_unlock(&mhi_chan->mutex); - return; - } - - mhi_chan->ch_state = MHI_CH_STATE_DISABLED; - write_unlock_irq(&mhi_chan->lock); - - reinit_completion(&mhi_chan->completion); - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - read_unlock_bh(&mhi_cntrl->pm_lock); - goto error_invalid_state; - } - - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - ret = mhi_send_cmd(mhi_cntrl, mhi_chan, MHI_CMD_RESET_CHAN); - if (ret) { - MHI_ERR("Failed to send reset chan cmd\n"); - goto error_completion; - } - - /* even if it fails we will still reset */ - ret = wait_for_completion_timeout(&mhi_chan->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret || mhi_chan->ccs != MHI_EV_CC_SUCCESS) - MHI_ERR("Failed to receive cmd completion, still resetting\n"); - -error_completion: - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - -error_invalid_state: - if (!mhi_chan->offload_ch) { - mhi_reset_chan(mhi_cntrl, mhi_chan); - mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); - } - MHI_LOG("chan:%d successfully resetted\n", mhi_chan->chan); - mutex_unlock(&mhi_chan->mutex); -} - -int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d) -{ - struct mhi_controller *mhi_cntrl = m->private; - u32 reset=-1, ready=-1; - int ret; - - ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, - MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, &reset); - ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MHISTATUS, - MHISTATUS_READY_MASK, MHISTATUS_READY_SHIFT, &ready); - if (!ret) - seq_printf(m, - "Device current EE:%s, M:%s, RESET:%d, READY:%d\n", - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)), - TO_MHI_STATE_STR(mhi_get_m_state(mhi_cntrl)), - reset, ready); - - seq_printf(m, - "pm_state:%s dev_state:%s EE:%s M0:%u M1:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), - mhi_cntrl->M0, mhi_cntrl->M1, mhi_cntrl->M2, mhi_cntrl->M3, - mhi_cntrl->wake_set, - atomic_read(&mhi_cntrl->dev_wake), - atomic_read(&mhi_cntrl->alloc_size)); - - return 0; -} - -int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d) -{ - struct mhi_controller *mhi_cntrl = m->private; - struct mhi_event *mhi_event; - struct mhi_event_ctxt *er_ctxt; - - int i; - - er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, er_ctxt++, - mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev) { - seq_printf(m, "Index:%d offload event ring\n", i); - } else { - seq_printf(m, - "Index:%d modc:%d modt:%d base:0x%0llx len:0x%llx", - i, er_ctxt->intmodc, er_ctxt->intmodt, - er_ctxt->rbase, er_ctxt->rlen); - seq_printf(m, - " rp:0x%llx wp:0x%llx local_rp:0x%llx db:0x%llx\n", - er_ctxt->rp, er_ctxt->wp, - (u64)mhi_to_physical(ring, ring->rp), - (u64)mhi_event->db_cfg.db_val); - { - struct mhi_tre *tre = (struct mhi_tre *)ring->base; - size_t i; - for (i = 0; i < ring->elements; i++, tre++) { - seq_printf(m, - "%llx, %x, %x\n", - tre->ptr, tre->dword[0], tre->dword[1]); - } - } - } - } - - return 0; -} - -int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d) -{ - struct mhi_controller *mhi_cntrl = m->private; - struct mhi_chan *mhi_chan; - struct mhi_chan_ctxt *chan_ctxt; - int i; - - mhi_chan = mhi_cntrl->mhi_chan; - chan_ctxt = mhi_cntrl->mhi_ctxt->chan_ctxt; - for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) { - struct mhi_ring *ring = &mhi_chan->tre_ring; - - if (mhi_chan->offload_ch) { - seq_printf(m, "%s(%u) offload channel\n", - mhi_chan->name, mhi_chan->chan); - } else if (mhi_chan->mhi_dev) { - seq_printf(m, - "%s(%u) state:0x%x brstmode:0x%x pllcfg:0x%x type:0x%x erindex:%u", - mhi_chan->name, mhi_chan->chan, - chan_ctxt->chstate, chan_ctxt->brstmode, - chan_ctxt->pollcfg, chan_ctxt->chtype, - chan_ctxt->erindex); - seq_printf(m, - " base:0x%llx len:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx full:%d\n", - chan_ctxt->rbase, chan_ctxt->rlen, - chan_ctxt->wp, - (u64)mhi_to_physical(ring, ring->rp), - (u64)mhi_to_physical(ring, ring->wp), - (u64)mhi_chan->db_cfg.db_val, mhi_chan->full); - } - } - - return 0; -} - -/* move channel to start state */ -int mhi_prepare_for_transfer(struct mhi_device *mhi_dev) -{ - int ret, dir; - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - ret = __mhi_prepare_channel(mhi_cntrl, mhi_chan); - if (ret) { - MHI_ERR("Error moving chan %s,%d to START state\n", - mhi_chan->name, mhi_chan->chan); - goto error_open_chan; - } - } - - return 0; - -error_open_chan: - for (--dir; dir >= 0; dir--) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - __mhi_unprepare_channel(mhi_cntrl, mhi_chan); - } - - return ret; -} -EXPORT_SYMBOL(mhi_prepare_for_transfer); - -void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - int dir; - - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - __mhi_unprepare_channel(mhi_cntrl, mhi_chan); - } -} -EXPORT_SYMBOL(mhi_unprepare_from_transfer); - -int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, - enum dma_data_direction dir) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? - mhi_dev->ul_chan : mhi_dev->dl_chan; - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - - return get_nr_avail_ring_elements(mhi_cntrl, tre_ring); -} -EXPORT_SYMBOL(mhi_get_no_free_descriptors); - -struct mhi_controller *mhi_bdf_to_controller(u32 domain, - u32 bus, - u32 slot, - u32 dev_id) -{ - struct mhi_controller *itr, *tmp; - - list_for_each_entry_safe(itr, tmp, &mhi_bus.controller_list, node) - if (itr->domain == domain && itr->bus == bus && - itr->slot == slot && itr->dev_id == dev_id) - return itr; - - return NULL; -} -EXPORT_SYMBOL(mhi_bdf_to_controller); - -int mhi_poll(struct mhi_device *mhi_dev, - u32 budget) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan = mhi_dev->dl_chan; - struct mhi_event *mhi_event = &mhi_cntrl->mhi_event[mhi_chan->er_index]; - int ret; - - spin_lock_bh(&mhi_event->lock); - ret = mhi_process_event_ring(mhi_cntrl, mhi_event, budget); - spin_unlock_bh(&mhi_event->lock); - - return ret; -} -EXPORT_SYMBOL(mhi_poll); diff --git a/fibocom_MHI/src/core/mhi_pm.c b/fibocom_MHI/src/core/mhi_pm.c deleted file mode 100644 index 039de5b..0000000 --- a/fibocom_MHI/src/core/mhi_pm.c +++ /dev/null @@ -1,1271 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -/* - * Not all MHI states transitions are sync transitions. Linkdown, SSR, and - * shutdown can happen anytime asynchronously. This function will transition to - * new state only if we're allowed to transitions. - * - * Priority increase as we go down, example while in any states from L0, start - * state from L1, L2, or L3 can be set. Notable exception to this rule is state - * DISABLE. From DISABLE state we can transition to only POR or state. Also - * for example while in L2 state, user cannot jump back to L1 or L0 states. - * Valid transitions: - * L0: DISABLE <--> POR - * POR <--> POR - * POR -> M0 -> M1 -> M1_M2 -> M2 --> M0 - * POR -> FW_DL_ERR - * FW_DL_ERR <--> FW_DL_ERR - * M0 -> FW_DL_ERR - * M1_M2 -> M0 (Device can trigger it) - * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0 - * M1 -> M3_ENTER --> M3 - * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR - * L2: SHUTDOWN_PROCESS -> DISABLE - * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT - * LD_ERR_FATAL_DETECT -> SHUTDOWN_PROCESS - */ -static struct mhi_pm_transitions const mhi_state_transitions[] = { - /* L0 States */ - { - MHI_PM_DISABLE, - MHI_PM_POR - }, - { - MHI_PM_POR, - MHI_PM_POR | MHI_PM_DISABLE | MHI_PM_M0 | - MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_FW_DL_ERR - }, - { - MHI_PM_M0, - MHI_PM_M1 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT | - MHI_PM_FW_DL_ERR - }, - { - MHI_PM_M1, - MHI_PM_M1_M2_TRANSITION | MHI_PM_M3_ENTER | - MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M1_M2_TRANSITION, - MHI_PM_M2 | MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M2, - MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M3_ENTER, - MHI_PM_M3 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M3, - MHI_PM_M3_EXIT | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M3_EXIT, - MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_FW_DL_ERR, - MHI_PM_FW_DL_ERR | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT - }, - /* L1 States */ - { - MHI_PM_SYS_ERR_DETECT, - MHI_PM_SYS_ERR_PROCESS | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_SYS_ERR_PROCESS, - MHI_PM_POR | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - /* L2 States */ - { - MHI_PM_SHUTDOWN_PROCESS, - MHI_PM_DISABLE | MHI_PM_LD_ERR_FATAL_DETECT - }, - /* L3 States */ - { - MHI_PM_LD_ERR_FATAL_DETECT, - MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_SHUTDOWN_PROCESS - }, -}; - -enum MHI_PM_STATE __must_check mhi_tryset_pm_state( - struct mhi_controller *mhi_cntrl, - enum MHI_PM_STATE state) -{ - unsigned long cur_state = mhi_cntrl->pm_state; - int index = find_last_bit(&cur_state, 32); - - if (unlikely(index >= ARRAY_SIZE(mhi_state_transitions))) { - MHI_CRITICAL("cur_state:%s is not a valid pm_state\n", - to_mhi_pm_state_str(cur_state)); - return cur_state; - } - - if (unlikely(mhi_state_transitions[index].from_state != cur_state)) { - MHI_ERR("index:%u cur_state:%s != actual_state: %s\n", - index, to_mhi_pm_state_str(cur_state), - to_mhi_pm_state_str - (mhi_state_transitions[index].from_state)); - return cur_state; - } - - if (unlikely(!(mhi_state_transitions[index].to_states & state))) { - MHI_LOG( - "Not allowing pm state transition from:%s to:%s state\n", - to_mhi_pm_state_str(cur_state), - to_mhi_pm_state_str(state)); - return cur_state; - } - - MHI_VERB("Transition to pm state from:%s to:%s\n", - to_mhi_pm_state_str(cur_state), to_mhi_pm_state_str(state)); - - mhi_cntrl->pm_state = state; - return mhi_cntrl->pm_state; -} - -void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, enum MHI_STATE state) -{ - if (state == MHI_STATE_RESET) { - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, - MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 1); - } else { - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, - MHICTRL_MHISTATE_MASK, MHICTRL_MHISTATE_SHIFT, state); - } -} - -/* set device wake */ -void mhi_assert_dev_wake(struct mhi_controller *mhi_cntrl, bool force) -{ - unsigned long flags; - - /* if set, regardless of count set the bit if not set */ - if (unlikely(force)) { - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - atomic_inc(&mhi_cntrl->dev_wake); - if (MHI_WAKE_DB_ACCESS_VALID(mhi_cntrl->pm_state) && - !mhi_cntrl->wake_set) { - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 1); - mhi_cntrl->wake_set = true; - } - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); - } else { - /* if resources requested already, then increment and exit */ - if (likely(atomic_add_unless(&mhi_cntrl->dev_wake, 1, 0))) - return; - - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - if ((atomic_inc_return(&mhi_cntrl->dev_wake) == 1) && - MHI_WAKE_DB_ACCESS_VALID(mhi_cntrl->pm_state) && - !mhi_cntrl->wake_set) { - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 1); - mhi_cntrl->wake_set = true; - } - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); - } -} - -/* clear device wake */ -void mhi_deassert_dev_wake(struct mhi_controller *mhi_cntrl, bool override) -{ - unsigned long flags; - - if (atomic_read(&mhi_cntrl->dev_wake) == 0) { - MHI_LOG("%s 00000\n", __func__); - return; - } - - MHI_ASSERT(atomic_read(&mhi_cntrl->dev_wake) == 0, "dev_wake == 0"); - - /* resources not dropping to 0, decrement and exit */ - if (likely(atomic_add_unless(&mhi_cntrl->dev_wake, -1, 1))) - return; - - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - if ((atomic_dec_return(&mhi_cntrl->dev_wake) == 0) && - MHI_WAKE_DB_ACCESS_VALID(mhi_cntrl->pm_state) && !override && - mhi_cntrl->wake_set) { - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 0); - mhi_cntrl->wake_set = false; - } - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); -} - -int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl) -{ - void __iomem *base = mhi_cntrl->regs; - u32 reset = 1, ready = 0; - struct mhi_event *mhi_event; - enum MHI_PM_STATE cur_state; - int ret, i; - - MHI_LOG("Waiting to enter READY state\n"); - - MHI_LOG("Device current EE:%s, M:%s\n", - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)), - TO_MHI_STATE_STR(mhi_get_m_state(mhi_cntrl))); - - /* wait for RESET to be cleared and READY bit to be set */ - for (i = 0; i < mhi_cntrl->timeout_ms; i += 25) { //maybe miss msi interrupt? - ready = 0; - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, MHICTRL, - MHICTRL_RESET_MASK, - MHICTRL_RESET_SHIFT, &reset) || - mhi_read_reg_field(mhi_cntrl, base, MHISTATUS, - MHISTATUS_READY_MASK, - MHISTATUS_READY_SHIFT, &ready) || - (!reset && ready), - msecs_to_jiffies(25)); - - /* device enter into error state */ - if (MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state)) { - MHI_LOG("reset=0x%x, ready=0x%x, pm_state=0x%x\n", reset, reset, mhi_cntrl->pm_state); - return -EIO; - } - - if (!reset && ready) - break; - } - - /* device did not transition to ready state */ - if (reset || !ready) { - MHI_LOG("reset=0x%x, ready=0x%x, pm_state=0x%x\n", reset, reset, mhi_cntrl->pm_state); - return -ETIMEDOUT; - } - - MHI_LOG("Device in READY State\n"); - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_POR); - mhi_cntrl->dev_state = MHI_STATE_READY; - write_unlock_irq(&mhi_cntrl->pm_lock); - - if (cur_state != MHI_PM_POR) { - MHI_ERR("Error moving to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_POR), - to_mhi_pm_state_str(cur_state)); - return -EIO; - } - read_lock_bh(&mhi_cntrl->pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - goto error_mmio; - - ret = mhi_init_mmio(mhi_cntrl); - if (ret) { - MHI_ERR("Error programming mmio registers\n"); - goto error_mmio; - } - - /* add elements to all sw event rings */ - MHI_LOG("mhi_db_sw_ring\n"); - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev || mhi_event->hw_ring) - continue; - - ring->wp = ring->base + ring->len - ring->el_size; - *ring->ctxt_wp = cpu_to_le64(ring->iommu_base + ring->len - ring->el_size); - /* needs to update to all cores */ - smp_wmb(); - - /* ring the db for event rings */ - spin_lock_irq(&mhi_event->lock); - mhi_ring_er_db(mhi_event); - spin_unlock_irq(&mhi_event->lock); - } - - /* set device into M0 state */ - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M0); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; - -error_mmio: - read_unlock_bh(&mhi_cntrl->pm_lock); - - return -EIO; -} - -int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE cur_state; - struct mhi_chan *mhi_chan; - int i; - - MHI_LOG("Entered With State:%s PM_STATE:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_M0; - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M0); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (unlikely(cur_state != MHI_PM_M0)) { - MHI_ERR("Failed to transition to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_M0), - to_mhi_pm_state_str(cur_state)); - return -EIO; - } - mhi_cntrl->M0++; - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, true); - - /* ring all event rings and CMD ring only if we're in AMSS */ - if (mhi_cntrl->ee == MHI_EE_AMSS) { - //struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - struct mhi_cmd *mhi_cmd = - &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING]; - - MHI_LOG("mhi_db_all_ring\n"); - - /* only ring primary cmd ring */ - spin_lock_irq(&mhi_cmd->lock); - if (mhi_cmd->ring.rp != mhi_cmd->ring.wp) - mhi_ring_cmd_db(mhi_cntrl, mhi_cmd); - spin_unlock_irq(&mhi_cmd->lock); - } - - /* ring channel db registers */ - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - - write_lock_irq(&mhi_chan->lock); - if (mhi_chan->db_cfg.reset_req) - mhi_chan->db_cfg.db_mode = true; - - /* only ring DB if ring is not empty */ - if (tre_ring->base && tre_ring->wp != tre_ring->rp) - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - write_unlock_irq(&mhi_chan->lock); - } - - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - wake_up(&mhi_cntrl->state_event); - MHI_VERB("Exited\n"); - - return 0; -} - -void mhi_pm_m1_worker(struct work_struct *work) -{ - enum MHI_PM_STATE cur_state; - struct mhi_controller *mhi_cntrl; - - mhi_cntrl = container_of(work, struct mhi_controller, m1_worker); - - MHI_LOG("M1 state transition from dev_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - mutex_lock(&mhi_cntrl->pm_mutex); - write_lock_irq(&mhi_cntrl->pm_lock); - - /* we either Entered M3 or we did M3->M0 Exit */ - if (mhi_cntrl->pm_state != MHI_PM_M1) - goto invalid_pm_state; - - MHI_LOG("Transitioning to M2 Transition\n"); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1_M2_TRANSITION); - if (unlikely(cur_state != MHI_PM_M1_M2_TRANSITION)) { - MHI_ERR("Failed to transition to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_M1_M2_TRANSITION), - to_mhi_pm_state_str(cur_state)); - goto invalid_pm_state; - } - - mhi_cntrl->dev_state = MHI_STATE_M2; - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M2); - write_unlock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->M2++; - - /* during M2 transition we cannot access DB registers must sleep */ - usleep_range(MHI_M2_DEBOUNCE_TMR_US, MHI_M2_DEBOUNCE_TMR_US + 50); - write_lock_irq(&mhi_cntrl->pm_lock); - - /* during de-bounce time could be receiving M0 Event */ - if (mhi_cntrl->pm_state == MHI_PM_M1_M2_TRANSITION) { - MHI_LOG("Entered M2 State\n"); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2); - if (unlikely(cur_state != MHI_PM_M2)) { - MHI_ERR("Failed to transition to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_M2), - to_mhi_pm_state_str(cur_state)); - goto invalid_pm_state; - } - } - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* transfer pending, exit M2 */ - if (unlikely(atomic_read(&mhi_cntrl->dev_wake))) { - MHI_VERB("Exiting M2 Immediately, count:%d\n", - atomic_read(&mhi_cntrl->dev_wake)); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, true); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - } else - mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, - MHI_CB_IDLE); - - mutex_unlock(&mhi_cntrl->pm_mutex); - return; - -invalid_pm_state: - write_unlock_irq(&mhi_cntrl->pm_lock); - mutex_unlock(&mhi_cntrl->pm_mutex); -} - -void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE state; - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = mhi_get_m_state(mhi_cntrl); - if (mhi_cntrl->dev_state == MHI_STATE_M1) { - state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1); - - /* schedule M1->M2 transition */ - if (state == MHI_PM_M1) { - schedule_work(&mhi_cntrl->m1_worker); - mhi_cntrl->M1++; - } - } - write_unlock_irq(&mhi_cntrl->pm_lock); -} - -int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE state; - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_M3; - state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (state != MHI_PM_M3) { - MHI_ERR("Failed to transition to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_M3), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - wake_up(&mhi_cntrl->state_event); - mhi_cntrl->M3++; - - MHI_LOG("Entered mhi_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return 0; -} - -static int mhi_pm_amss_transition(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_event *mhi_event; - - MHI_LOG("Processing AMSS Transition\n"); - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = MHI_EE_AMSS; - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up(&mhi_cntrl->state_event); - - /* add elements to all HW event rings */ - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - read_unlock_bh(&mhi_cntrl->pm_lock); - return -EIO; - } - - MHI_LOG("mhi_db_hw_ring\n"); - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev || !mhi_event->hw_ring) - continue; - - ring->wp = ring->base + ring->len - ring->el_size; - *ring->ctxt_wp = cpu_to_le64(ring->iommu_base + ring->len - ring->el_size); - /* all ring updates must get updated immediately */ - smp_wmb(); - - spin_lock_irq(&mhi_event->lock); - if (MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state)) - mhi_ring_er_db(mhi_event); - spin_unlock_irq(&mhi_event->lock); - - } - read_unlock_bh(&mhi_cntrl->pm_lock); - - MHI_LOG("Adding new devices\n"); - - /* add supported devices */ - mhi_create_devices(mhi_cntrl); - - MHI_LOG("Exited\n"); - - return 0; -} - -/* handles both sys_err and shutdown transitions */ -static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, - enum MHI_PM_STATE transition_state) -{ - enum MHI_PM_STATE cur_state, prev_state; - struct mhi_event *mhi_event; - struct mhi_cmd_ctxt *cmd_ctxt; - struct mhi_cmd *mhi_cmd; - struct mhi_event_ctxt *er_ctxt; - int ret = 0, i; - u32 regVal; - - MHI_LOG("Enter with from pm_state:%s MHI_STATE:%s to pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(transition_state)); - - mutex_lock(&mhi_cntrl->pm_mutex); - write_lock_irq(&mhi_cntrl->pm_lock); - prev_state = mhi_cntrl->pm_state; - cur_state = mhi_tryset_pm_state(mhi_cntrl, transition_state); - if (cur_state == transition_state) { - mhi_cntrl->ee = MHI_EE_DISABLE_TRANSITION; - mhi_cntrl->dev_state = MHI_STATE_RESET; - } - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* not handling sys_err, could be middle of shut down */ - if (cur_state != transition_state) { - MHI_LOG("Failed to transition to state:0x%x from:0x%x\n", - transition_state, cur_state); - mutex_unlock(&mhi_cntrl->pm_mutex); - return; - } - - /* trigger MHI RESET so device will not access host ddr */ - if (MHI_REG_ACCESS_VALID(prev_state)) { - u32 in_reset = -1; - u32 i; - - MHI_LOG("Trigger device into MHI_RESET\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); - - /* wait for reset to be cleared */ - for (i = 0; i < mhi_cntrl->timeout_ms; i += 25) { //maybe miss msi interrupt - in_reset = -1; - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_read_reg_field(mhi_cntrl, - mhi_cntrl->regs, MHICTRL, - MHICTRL_RESET_MASK, - MHICTRL_RESET_SHIFT, &in_reset) - || !in_reset, msecs_to_jiffies(25)); - if (in_reset == 0) - break; - } - - if ((!ret || in_reset) && cur_state == MHI_PM_SYS_ERR_PROCESS) { - MHI_CRITICAL("Device failed to exit RESET state\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return; - } - - /* Set the numbers of Event Rings supported */ - ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICFG, MHICFG_NCH_MASK, MHICFG_NCH_SHIFT, ®Val); - MHI_LOG("%d channels, ret=%d\n", regVal, ret); - - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICFG, MHICFG_NER_MASK, MHICFG_NER_SHIFT, NUM_MHI_EVT_RINGS); - /* - * device cleares INTVEC as part of RESET processing, - * re-program it - */ - mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0); - } - - MHI_LOG("Waiting for all pending event ring processing to complete\n"); - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - tasklet_kill(&mhi_event->task); - } - - MHI_LOG("Reset all active channels and remove mhi devices\n"); - device_for_each_child(mhi_cntrl->dev, NULL, mhi_destroy_device); - - MHI_LOG("Finish resetting channels\n"); - - /* release lock and wait for all pending thread to complete */ - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Waiting for all pending threads to complete\n"); - wake_up(&mhi_cntrl->state_event); - flush_work(&mhi_cntrl->m1_worker); - flush_work(&mhi_cntrl->st_worker); - flush_work(&mhi_cntrl->fw_worker); - - mutex_lock(&mhi_cntrl->pm_mutex); - - MHI_ASSERT(atomic_read(&mhi_cntrl->dev_wake), "dev_wake != 0"); - - /* reset the ev rings and cmd rings */ - MHI_LOG("Resetting EV CTXT and CMD CTXT\n"); - mhi_cmd = mhi_cntrl->mhi_cmd; - cmd_ctxt = mhi_cntrl->mhi_ctxt->cmd_ctxt; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++, cmd_ctxt++) { - struct mhi_ring *ring = &mhi_cmd->ring; - - ring->rp = ring->base; - ring->wp = ring->base; - cmd_ctxt->rp = cmd_ctxt->rbase; - cmd_ctxt->wp = cmd_ctxt->rbase; - } - - mhi_event = mhi_cntrl->mhi_event; - er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, er_ctxt++, - mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - /* do not touch offload er */ - if (mhi_event->offload_ev) - continue; - - ring->rp = ring->base; - ring->wp = ring->base; - er_ctxt->rp = er_ctxt->rbase; - er_ctxt->wp = er_ctxt->rbase; - } - - if (cur_state == MHI_PM_SYS_ERR_PROCESS) { - mhi_ready_state_transition(mhi_cntrl); - } else { - /* move to disable state */ - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_DISABLE); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (unlikely(cur_state != MHI_PM_DISABLE)) - MHI_ERR("Error moving from pm state:%s to state:%s\n", - to_mhi_pm_state_str(cur_state), - to_mhi_pm_state_str(MHI_PM_DISABLE)); - } - - MHI_LOG("Exit with pm_state:%s mhi_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state)); - - mutex_unlock(&mhi_cntrl->pm_mutex); -} - -int mhi_debugfs_trigger_reset(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - enum MHI_PM_STATE cur_state; - int ret; - - MHI_LOG("Trigger MHI Reset\n"); - - /* exit lpm first */ - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT); - write_unlock_irq(&mhi_cntrl->pm_lock); - - if (cur_state == MHI_PM_SYS_ERR_DETECT) - schedule_work(&mhi_cntrl->syserr_worker); - - return 0; -} - -/* queue a new work item and scheduler work */ -int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, - enum MHI_ST_TRANSITION state) -{ - struct state_transition *item = kmalloc(sizeof(*item), GFP_ATOMIC); - unsigned long flags; - - if (!item) - return -ENOMEM; - - item->state = state; - spin_lock_irqsave(&mhi_cntrl->transition_lock, flags); - list_add_tail(&item->node, &mhi_cntrl->transition_list); - spin_unlock_irqrestore(&mhi_cntrl->transition_lock, flags); - - schedule_work(&mhi_cntrl->st_worker); - - return 0; -} - -void mhi_pm_sys_err_worker(struct work_struct *work) -{ - struct mhi_controller *mhi_cntrl = container_of(work, - struct mhi_controller, - syserr_worker); - - MHI_LOG("Enter with pm_state:%s MHI_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state)); - - mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS); -} - -void mhi_pm_st_worker(struct work_struct *work) -{ - struct state_transition *itr, *tmp; - LIST_HEAD(head); - struct mhi_controller *mhi_cntrl = container_of(work, - struct mhi_controller, - st_worker); - spin_lock_irq(&mhi_cntrl->transition_lock); - list_splice_tail_init(&mhi_cntrl->transition_list, &head); - spin_unlock_irq(&mhi_cntrl->transition_lock); - - list_for_each_entry_safe(itr, tmp, &head, node) { - list_del(&itr->node); - MHI_LOG("Transition to state:%s\n", - TO_MHI_STATE_TRANS_STR(itr->state)); - - if (mhi_cntrl->ee != mhi_get_exec_env(mhi_cntrl)) { - MHI_ERR("%s -> %s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee), - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl))); - } - - switch (itr->state) { - case MHI_ST_TRANSITION_PBL: - write_lock_irq(&mhi_cntrl->pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (MHI_IN_PBL(mhi_cntrl->ee)) - wake_up(&mhi_cntrl->state_event); - break; - case MHI_ST_TRANSITION_READY: - mhi_ready_state_transition(mhi_cntrl); - break; - case MHI_ST_TRANSITION_SBL: - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = MHI_EE_SBL; - write_unlock_irq(&mhi_cntrl->pm_lock); - mhi_create_devices(mhi_cntrl); - break; - case MHI_ST_TRANSITION_AMSS: - mhi_pm_amss_transition(mhi_cntrl); - break; - case MHI_ST_TRANSITION_FP: - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = MHI_EE_FP; - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up(&mhi_cntrl->state_event); - mhi_create_devices(mhi_cntrl); - break; - default: - break; - } - kfree(itr); - } -} - -int mhi_async_power_up(struct mhi_controller *mhi_cntrl) -{ - int ret; - u32 bhi_offset; - enum MHI_EE current_ee; - enum MHI_ST_TRANSITION next_state; - u32 mhi_cfg = 0xFFFFFFFF; - u32 mhi_timeout = 10; - enum MHI_STATE mhiDevState; - - MHI_LOG("Requested to power on\n"); - -//# echo 1 > /sys/module/ep_pcie_core/parameters/debug_mask -//# echo 3 > /sys/kernel/debug/pcie-ep/case -//in sdx20 mimo offset is 0x100 -//ep_pcie_reg_dump: 0x0100 00000100 00000000 01000000 b8efc7ae 00010880 ecd23c0b 00000300 00000000 - while (mhi_cfg == 0xFFFFFFFF && mhi_timeout != 0) { //refer to MhiInitNewDev - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, MHICFG, &mhi_cfg); - if (ret) { - - } - MHI_LOG("mhi_cfg = 0x%x\n", mhi_cfg); - msleep(50); - mhi_timeout--; - } - if (mhi_cfg == 0xFFFFFFFF) - return EBUSY; - - mhiDevState = mhi_get_m_state(mhi_cntrl); - MHI_LOG("mhi_state = %s\n", mhi_state_str[mhiDevState]); - - if (mhiDevState >= MHI_STATE_M0) { - MHI_LOG("Trigger device into MHI_RESET\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); - msleep(50); - mhiDevState = mhi_get_m_state(mhi_cntrl); - MHI_LOG("mhi_state = %s\n", mhi_state_str[mhiDevState]); - } - - /* set to default wake if not set */ - if (!mhi_cntrl->wake_get || !mhi_cntrl->wake_put) { - mhi_cntrl->wake_get = mhi_assert_dev_wake; - mhi_cntrl->wake_put = mhi_deassert_dev_wake; - } - - mutex_lock(&mhi_cntrl->pm_mutex); - mhi_cntrl->pm_state = MHI_PM_DISABLE; - - if (!mhi_cntrl->pre_init) { - /* setup device context */ - ret = mhi_init_dev_ctxt(mhi_cntrl); - if (ret) { - MHI_ERR("Error setting dev_context\n"); - goto error_dev_ctxt; - } - - ret = mhi_init_irq_setup(mhi_cntrl); - if (ret) { - MHI_ERR("Error setting up irq\n"); - goto error_setup_irq; - } - } - - /* setup bhi offset & intvec */ - write_lock_irq(&mhi_cntrl->pm_lock); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIOFF, &bhi_offset); - if (ret) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error getting bhi offset\n"); - goto error_bhi_offset; - } - - MHI_LOG("bhi_offset = 0x%x\n", bhi_offset); //this should be 0x100, in sdx20, bhi offset is 0x200 - mhi_cntrl->bhi = mhi_cntrl->regs + bhi_offset; - mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0); - mhi_cntrl->pm_state = MHI_PM_POR; - - mhi_timeout = 30; - while ((current_ee = mhi_get_exec_env(mhi_cntrl)) != MHI_EE_AMSS) - { - if (current_ee < MHI_EE_MAX) - { - MHI_LOG("wait for ee = %s\n", mhi_ee_str[current_ee]); - } - - msleep(500); - mhi_timeout--; - if (0 == mhi_timeout) - { - break; - } - } - - mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); - current_ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); - - MHI_LOG("current_ee = %s\n", mhi_ee_str[current_ee]); - - /* confirm device is in valid exec env */ - if (!MHI_IN_PBL(current_ee) && current_ee != MHI_EE_AMSS) { - MHI_ERR("Not a valid ee for power on\n"); - ret = -EIO; - goto error_bhi_offset; - } - - /* transition to next state */ - next_state = MHI_IN_PBL(current_ee) ? - MHI_ST_TRANSITION_PBL : MHI_ST_TRANSITION_READY; - - mhi_queue_state_transition(mhi_cntrl, next_state); - - mhi_init_debugfs(mhi_cntrl); - mhi_cntrl_register_miscdev(mhi_cntrl); - - mutex_unlock(&mhi_cntrl->pm_mutex); - - MHI_LOG("Power on setup success\n"); - - - return 0; - -error_bhi_offset: - if (!mhi_cntrl->pre_init) - mhi_deinit_free_irq(mhi_cntrl); - -error_setup_irq: - if (!mhi_cntrl->pre_init) - mhi_deinit_dev_ctxt(mhi_cntrl); - -error_dev_ctxt: - mutex_unlock(&mhi_cntrl->pm_mutex); - - return ret; -} -EXPORT_SYMBOL(mhi_async_power_up); - -void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful) -{ - enum MHI_PM_STATE cur_state; - MHI_LOG("enter\n"); - - /* if it's not graceful shutdown, force MHI to a linkdown state */ - if (!graceful) { - mutex_lock(&mhi_cntrl->pm_mutex); - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_LD_ERR_FATAL_DETECT); - write_unlock_irq(&mhi_cntrl->pm_lock); - mutex_unlock(&mhi_cntrl->pm_mutex); - if (cur_state != MHI_PM_LD_ERR_FATAL_DETECT) - MHI_ERR("Failed to move to state:%s from:%s\n", - to_mhi_pm_state_str(MHI_PM_LD_ERR_FATAL_DETECT), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SHUTDOWN_PROCESS); - } - else { - device_for_each_child(mhi_cntrl->dev, NULL, mhi_destroy_device); - } - - mhi_cntrl_deregister_miscdev(mhi_cntrl); - mhi_deinit_debugfs(mhi_cntrl); - - if (!mhi_cntrl->pre_init) { - /* free all allocated resources */ - if (mhi_cntrl->fbc_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - } - mhi_deinit_free_irq(mhi_cntrl); - mhi_deinit_dev_ctxt(mhi_cntrl); - } - -} -EXPORT_SYMBOL(mhi_power_down); - -int mhi_sync_power_up(struct mhi_controller *mhi_cntrl) -{ - int ret = mhi_async_power_up(mhi_cntrl); - - if (ret) - return ret; - - wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_AMSS || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - return (mhi_cntrl->ee == MHI_EE_AMSS) ? 0 : -EIO; -} -EXPORT_SYMBOL(mhi_sync_power_up); - -int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) -{ - int ret; - enum MHI_PM_STATE new_state; - struct mhi_chan *itr, *tmp; - - if (mhi_cntrl->pm_state == MHI_PM_DISABLE) - return -EINVAL; - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - /* do a quick check to see if any pending data, then exit */ - if (atomic_read(&mhi_cntrl->dev_wake)) { - MHI_VERB("Busy, aborting M3\n"); - return -EBUSY; - } - - /* exit MHI out of M2 state */ - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - mhi_cntrl->dev_state == MHI_STATE_M1 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR( - "Did not enter M0||M1 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - - if (atomic_read(&mhi_cntrl->dev_wake)) { - MHI_VERB("Busy, aborting M3\n"); - write_unlock_irq(&mhi_cntrl->pm_lock); - return -EBUSY; - } - - /* anytime after this, we will resume thru runtime pm framework */ - MHI_LOG("Allowing M3 transition\n"); - new_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3_ENTER); - if (new_state != MHI_PM_M3_ENTER) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error setting to pm_state:%s from pm_state:%s\n", - to_mhi_pm_state_str(MHI_PM_M3_ENTER), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - /* set dev to M3 and wait for completion */ - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M3); - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_LOG("Wait for M3 completion\n"); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M3 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M3 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - /* notify any clients we enter lpm */ - list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { - mutex_lock(&itr->mutex); - if (itr->mhi_dev) - mhi_notify(itr->mhi_dev, MHI_CB_LPM_ENTER); - mutex_unlock(&itr->mutex); - } - - return 0; -} -EXPORT_SYMBOL(mhi_pm_suspend); - -int mhi_pm_resume(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE cur_state; - int ret; - struct mhi_chan *itr, *tmp; - - MHI_LOG("Entered with pm_state:%s dev_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state)); - - if (mhi_cntrl->pm_state == MHI_PM_DISABLE) - return 0; - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - MHI_ASSERT(mhi_cntrl->pm_state != MHI_PM_M3, "mhi_pm_state != M3"); - - /* notify any clients we enter lpm */ - list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { - mutex_lock(&itr->mutex); - if (itr->mhi_dev) - mhi_notify(itr->mhi_dev, MHI_CB_LPM_EXIT); - mutex_unlock(&itr->mutex); - } - - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3_EXIT); - if (cur_state != MHI_PM_M3_EXIT) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error setting to pm_state:%s from pm_state:%s\n", - to_mhi_pm_state_str(MHI_PM_M3_EXIT), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - /* set dev to M0 and wait for completion */ - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M0); - write_unlock_irq(&mhi_cntrl->pm_lock); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - return 0; -} - -static int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) -{ - int ret; - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, false); - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - read_unlock_bh(&mhi_cntrl->pm_lock); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - return -EIO; - } - - return 0; -} - -void mhi_device_get(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - atomic_inc(&mhi_dev->dev_wake); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); -} -EXPORT_SYMBOL(mhi_device_get); - -int mhi_device_get_sync(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - int ret; - - ret = __mhi_device_get_sync(mhi_cntrl); - if (!ret) - atomic_inc(&mhi_dev->dev_wake); - - return ret; -} -EXPORT_SYMBOL(mhi_device_get_sync); - -void mhi_device_put(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - atomic_dec(&mhi_dev->dev_wake); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); -} -EXPORT_SYMBOL(mhi_device_put); - -int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) -{ - int ret; - - MHI_LOG("Enter with pm_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - /* before rddm mode, we need to enter M0 state */ - ret = __mhi_device_get_sync(mhi_cntrl); - if (ret) - return ret; - - mutex_lock(&mhi_cntrl->pm_mutex); - write_lock_irq(&mhi_cntrl->pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - goto no_reg_access; - - MHI_LOG("Triggering SYS_ERR to force rddm state\n"); - - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); - mhi_cntrl->wake_put(mhi_cntrl, false); - write_unlock_irq(&mhi_cntrl->pm_lock); - mutex_unlock(&mhi_cntrl->pm_mutex); - - /* wait for rddm event */ - MHI_LOG("Waiting for device to enter RDDM state\n"); - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_RDDM, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - ret = !ret ? 0 : -EIO; - - MHI_LOG("Exiting with pm_state:%s ee:%s ret:%d\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - return ret; - -no_reg_access: - mhi_cntrl->wake_put(mhi_cntrl, false); - write_unlock_irq(&mhi_cntrl->pm_lock); - mutex_unlock(&mhi_cntrl->pm_mutex); - - return -EIO; -} -EXPORT_SYMBOL(mhi_force_rddm_mode); diff --git a/fibocom_MHI/src/devices/mhi_netdev.c b/fibocom_MHI/src/devices/mhi_netdev.c deleted file mode 100644 index d34716e..0000000 --- a/fibocom_MHI/src/devices/mhi_netdev.c +++ /dev/null @@ -1,1313 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/mhi.h" -#include "mhi_netdev.h" - -struct qmap_hdr { - u8 cd_rsvd_pad; - u8 mux_id; - u16 pkt_len; -} __packed; -#define FIBO_QMAP_MUX_ID 0x81 - -#ifdef CONFIG_MHI_NETDEV_MBIM -#else -static uint __read_mostly qmap_mode = 1; -module_param(qmap_mode, uint, S_IRUGO); -#endif - -#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" -#define WATCHDOG_TIMEOUT (30 * HZ) - -#define MSG_VERB(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) { \ - MSG_ERR(msg); \ - WARN_ON(cond); \ - } \ -} while (0) - -#define MSG_LOG(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ - pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MSG_ERR(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ -} while (0) - -struct mhi_stats { - u32 rx_int; - u32 tx_full; - u32 tx_pkts; - u32 rx_budget_overflow; - u32 rx_frag; - u32 alloc_failed; -}; - -/* important: do not exceed sk_buf->cb (48 bytes) */ -struct mhi_skb_priv { - void *buf; - size_t size; - struct mhi_netdev *mhi_netdev; -}; - -struct mhi_netdev { - int alias; - struct mhi_device *mhi_dev; - spinlock_t rx_lock; - bool enabled; - rwlock_t pm_lock; /* state change lock */ - int (*rx_queue)(struct mhi_netdev *mhi_netdev, gfp_t gfp_t); - struct work_struct alloc_work; - int wake; - - struct sk_buff_head rx_allocated; - - u32 mru; - const char *interface_name; - struct napi_struct napi; - struct net_device *ndev; - struct sk_buff *frag_skb; - bool recycle_buf; - - struct mhi_stats stats; - struct dentry *dentry; - enum MHI_DEBUG_LEVEL msg_lvl; -#ifdef CONFIG_MHI_NETDEV_MBIM - u16 tx_seq; - u16 rx_seq; - u32 rx_max; -#endif -}; - -struct mhi_netdev_priv { - struct mhi_netdev *mhi_netdev; -}; - -static struct mhi_driver mhi_netdev_driver; -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev); - - -static struct mhi_netdev * g_mhi_netdev = NULL; - -static inline void qmap_hex_dump(const char *tag, unsigned char *data, unsigned len) { - //#define MHI_NETDEV_DEBUG - #ifdef MHI_NETDEV_DEBUG - if (g_mhi_netdev && g_mhi_netdev->msg_lvl > MHI_MSG_LVL_CRITICAL) - { - int i; - printk("dump %s,%s:len=%d \n", tag, g_mhi_netdev->ndev->name, len); - for (i = 0; i < len; i++) - { - printk(" 0x%02x", data[i]); - if (((i+1) % 16) == 0) - { - printk("\n"); - } - } - - printk("\n"); - } - #endif -} - - -static int macaddr_check = 0; -static int mhi_netdev_macaddr_check_get(char * buffer, const struct kernel_param * kp) -{ - char mac_str[32]; - - if (g_mhi_netdev == NULL) - { - return sprintf(buffer, "%s\n", "null");; - } - - snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x\n", - g_mhi_netdev->ndev->dev_addr[0], - g_mhi_netdev->ndev->dev_addr[1], - g_mhi_netdev->ndev->dev_addr[2], - g_mhi_netdev->ndev->dev_addr[3], - g_mhi_netdev->ndev->dev_addr[4], - g_mhi_netdev->ndev->dev_addr[5]); - - return sprintf(buffer, "%s", mac_str); - -} - - -static int mhi_netdev_macaddr_check_set(const char * val, const struct kernel_param * kp) -{ - if (g_mhi_netdev == NULL) - { - return 0; - } - - if (val[0] == '1') - { - if (!is_valid_ether_addr(g_mhi_netdev->ndev->dev_addr)) - { - eth_random_addr(g_mhi_netdev->ndev->dev_addr); - g_mhi_netdev->ndev->addr_assign_type = NET_ADDR_RANDOM; - - if (!is_valid_ether_addr(g_mhi_netdev->ndev->dev_addr)) - { - eth_random_addr(g_mhi_netdev->ndev->dev_addr); - } - else - { - printk("invalid ether addr\n"); - } - } - - return 0; - } - - return -EINVAL; -} - -module_param_call(macaddr_check, mhi_netdev_macaddr_check_set, mhi_netdev_macaddr_check_get, &macaddr_check, 0644); - - - -static void mhi_netdev_skb_destructor(struct sk_buff *skb) -{ - struct mhi_skb_priv *skb_priv = (struct mhi_skb_priv *)(skb->cb); - struct mhi_netdev *mhi_netdev = skb_priv->mhi_netdev; - - skb->data = skb->head; - skb_reset_tail_pointer(skb); - skb->len = 0; - MHI_ASSERT(skb->data != skb_priv->buf, "incorrect buf"); - skb_queue_tail(&mhi_netdev->rx_allocated, skb); -} - -static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) -{ - u32 cur_mru = mhi_netdev->mru; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct mhi_skb_priv *skb_priv; - int ret; - struct sk_buff *skb; - int no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - int i; - - for (i = 0; i < no_tre; i++) { - skb = alloc_skb(cur_mru + ETH_HLEN, gfp_t); - if (!skb) - return -ENOMEM; - - skb_reserve(skb, ETH_HLEN); - - read_lock_bh(&mhi_netdev->pm_lock); - if (unlikely(!mhi_netdev->enabled)) { - MSG_ERR("Interface not enabled\n"); - ret = -EIO; - goto error_queue; - } - - skb_priv = (struct mhi_skb_priv *)skb->cb; - skb_priv->buf = skb->data; - skb_priv->size = cur_mru; - skb_priv->mhi_netdev = mhi_netdev; - skb->dev = mhi_netdev->ndev; - - if (mhi_netdev->recycle_buf) - skb->destructor = mhi_netdev_skb_destructor; - - spin_lock_bh(&mhi_netdev->rx_lock); - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb, - skb_priv->size, MHI_EOT); - spin_unlock_bh(&mhi_netdev->rx_lock); - - if (ret) { - MSG_ERR("Failed to queue skb, ret:%d\n", ret); - ret = -EIO; - goto error_queue; - } - - read_unlock_bh(&mhi_netdev->pm_lock); - } - - return 0; - -error_queue: - skb->destructor = NULL; - read_unlock_bh(&mhi_netdev->pm_lock); - dev_kfree_skb_any(skb); - - return ret; -} - -static void mhi_netdev_alloc_work(struct work_struct *work) -{ - struct mhi_netdev *mhi_netdev = container_of(work, struct mhi_netdev, - alloc_work); - /* sleep about 1 sec and retry, that should be enough time - * for system to reclaim freed memory back. - */ - const int sleep_ms = 1000; - int retry = 60; - int ret; - - MSG_LOG("Entered\n"); - do { - ret = mhi_netdev_alloc_skb(mhi_netdev, GFP_KERNEL); - /* sleep and try again */ - if (ret == -ENOMEM) { - msleep(sleep_ms); - retry--; - } - } while (ret == -ENOMEM && retry); - - MSG_LOG("Exit with status:%d retry:%d\n", ret, retry); -} - -/* we will recycle buffers */ -static int mhi_netdev_skb_recycle(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) -{ - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int no_tre; - int ret = 0; - struct sk_buff *skb; - struct mhi_skb_priv *skb_priv; - - read_lock_bh(&mhi_netdev->pm_lock); - if (!mhi_netdev->enabled) { - read_unlock_bh(&mhi_netdev->pm_lock); - return -EIO; - } - - no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - - spin_lock_bh(&mhi_netdev->rx_lock); - while (no_tre) { - skb = skb_dequeue(&mhi_netdev->rx_allocated); - - /* no free buffers to recycle, reschedule work */ - if (!skb) { - ret = -ENOMEM; - goto error_queue; - } - - skb_priv = (struct mhi_skb_priv *)(skb->cb); - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb, - skb_priv->size, MHI_EOT); - - /* failed to queue buffer */ - if (ret) { - MSG_ERR("Failed to queue skb, ret:%d\n", ret); - skb_queue_tail(&mhi_netdev->rx_allocated, skb); - goto error_queue; - } - - no_tre--; - } - -error_queue: - spin_unlock_bh(&mhi_netdev->rx_lock); - read_unlock_bh(&mhi_netdev->pm_lock); - - return ret; -} - -static void mhi_netdev_dealloc(struct mhi_netdev *mhi_netdev) -{ - struct sk_buff *skb; - - skb = skb_dequeue(&mhi_netdev->rx_allocated); - while (skb) { - skb->destructor = NULL; - kfree_skb(skb); - skb = skb_dequeue(&mhi_netdev->rx_allocated); - } -} - -static int mhi_netdev_poll(struct napi_struct *napi, int budget) -{ - struct net_device *dev = napi->dev; - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int rx_work = 0; - int ret; - - MSG_VERB("Entered\n"); - - read_lock_bh(&mhi_netdev->pm_lock); - - if (!mhi_netdev->enabled) { - MSG_LOG("interface is disabled!\n"); - napi_complete(napi); - read_unlock_bh(&mhi_netdev->pm_lock); - return 0; - } - - mhi_device_get(mhi_dev); - - rx_work = mhi_poll(mhi_dev, budget); - if (rx_work < 0) { - MSG_ERR("Error polling ret:%d\n", rx_work); - rx_work = 0; - napi_complete(napi); - goto exit_poll; - } - - /* queue new buffers */ - ret = mhi_netdev->rx_queue(mhi_netdev, GFP_ATOMIC); - if (ret == -ENOMEM) { - MSG_LOG("out of tre, queuing bg worker\n"); - mhi_netdev->stats.alloc_failed++; - schedule_work(&mhi_netdev->alloc_work); - } - - /* complete work if # of packet processed less than allocated budget */ - if (rx_work < budget) - napi_complete(napi); - else - mhi_netdev->stats.rx_budget_overflow++; - -exit_poll: - mhi_device_put(mhi_dev); - read_unlock_bh(&mhi_netdev->pm_lock); - - MSG_VERB("polled %d pkts\n", rx_work); - - return rx_work; -} - -static int mhi_netdev_open(struct net_device *dev) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - MSG_LOG("Opened net dev interface\n"); - - /* tx queue may not necessarily be stopped already - * so stop the queue if tx path is not enabled - */ - if (!mhi_dev->ul_chan) - netif_stop_queue(dev); - else - netif_start_queue(dev); - - return 0; - -} - -static int mhi_netdev_change_mtu(struct net_device *dev, int new_mtu) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - if (new_mtu < 0 || mhi_dev->mtu < new_mtu) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - -#ifdef CONFIG_MHI_NETDEV_MBIM -static struct sk_buff *mhi_mbim_tx_fixup(struct mhi_netdev *mhi_netdev, struct sk_buff *skb, struct net_device *dev) { - struct usb_cdc_ncm_nth16 *nth16; - struct usb_cdc_ncm_ndp16 *ndp16; - __le32 sign; - u8 *c; - u16 tci = 0; - unsigned int skb_len; - - qmap_hex_dump(__func__, skb->data, skb->len); - - if (skb->len > VLAN_ETH_HLEN && __vlan_get_tag(skb, &tci) == 0) - { - skb_pull(skb, VLAN_ETH_HLEN); - } - else - { - skb_pull(skb, ETH_HLEN); - } - - skb_len = skb->len; - - if (skb_headroom(skb) < sizeof(struct usb_cdc_ncm_nth16)) { - printk("skb_headroom small!\n"); - return NULL; - } - - if (skb_tailroom(skb) < (sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16) * 2)) { - if (skb_pad(skb, (sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16) * 2))) { - printk("skb_tailroom small!\n"); - return NULL; - } - } - - skb_push(skb, sizeof(struct usb_cdc_ncm_nth16)); - skb_put(skb, sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16) * 2); - - nth16 = (struct usb_cdc_ncm_nth16 *)skb->data; - nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN); - nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16)); - nth16->wSequence = cpu_to_le16(mhi_netdev->tx_seq++); - nth16->wBlockLength = cpu_to_le16(skb->len); - nth16->wNdpIndex = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16) + skb_len); - - sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN); - c = (u8 *)&sign; - //tci = 0; - c[3] = tci; - - ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + nth16->wNdpIndex); - ndp16->dwSignature = sign; - ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16) * 2); - ndp16->wNextNdpIndex = 0; - - ndp16->dpe16[0].wDatagramIndex = sizeof(struct usb_cdc_ncm_nth16); - ndp16->dpe16[0].wDatagramLength = skb_len; - - ndp16->dpe16[1].wDatagramIndex = 0; - ndp16->dpe16[1].wDatagramLength = 0; - - return skb; -} - -static int mhi_mbim_rx_fixup(struct mhi_netdev *mhi_netdev, struct sk_buff *skb_in, struct net_device *dev) { - struct usb_cdc_ncm_nth16 *nth16; - int ndpoffset, len; - u16 wSequence; - struct mhi_netdev *ctx = mhi_netdev; - - if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16))) { - MSG_ERR("frame too short\n"); - goto error; - } - - nth16 = (struct usb_cdc_ncm_nth16 *)skb_in->data; - - if (nth16->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN)) { - MSG_ERR("invalid NTH16 signature <%#010x>\n", le32_to_cpu(nth16->dwSignature)); - goto error; - } - - len = le16_to_cpu(nth16->wBlockLength); - if (len > ctx->rx_max) { - MSG_ERR("unsupported NTB block length %u/%u\n", len, ctx->rx_max); - goto error; - } - - wSequence = le16_to_cpu(nth16->wSequence); - if (ctx->rx_seq != wSequence) { - MSG_ERR("sequence number glitch prev=%d curr=%d\n", ctx->rx_seq, wSequence); - } - ctx->rx_seq = wSequence + 1; - - ndpoffset = nth16->wNdpIndex; - - while (ndpoffset > 0) { - struct usb_cdc_ncm_ndp16 *ndp16 ; - struct usb_cdc_ncm_dpe16 *dpe16; - int nframes, x; - u8 *c; - u16 tci = 0; - - if (skb_in->len < (ndpoffset + sizeof(struct usb_cdc_ncm_ndp16))) { - MSG_ERR("invalid NDP offset <%u>\n", ndpoffset); - goto error; - } - - ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset); - - if (le16_to_cpu(ndp16->wLength) < 0x10) { - MSG_ERR("invalid DPT16 length <%u>\n", le16_to_cpu(ndp16->wLength)); - goto error; - } - - nframes = ((le16_to_cpu(ndp16->wLength) - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16)); - - if (skb_in->len < (sizeof(struct usb_cdc_ncm_ndp16) + nframes * (sizeof(struct usb_cdc_ncm_dpe16)))) { - MSG_ERR("Invalid nframes = %d\n", nframes); - goto error; - } - - switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) { - case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN): - c = (u8 *)&ndp16->dwSignature; - tci = c[3]; - /* tag IPS<0> packets too if MBIM_IPS0_VID exists */ - //if (!tci && info->flags & FLAG_IPS0_VLAN) - // tci = MBIM_IPS0_VID; - break; - case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN): - c = (u8 *)&ndp16->dwSignature; - tci = c[3] + 256; - break; - default: - MSG_ERR("unsupported NDP signature <0x%08x>\n", le32_to_cpu(ndp16->dwSignature)); - goto error; - } - - #if 0 - if (tci != 0) { - MSG_ERR("unsupported tci %d by now\n", tci); - goto error; - } - #endif - - dpe16 = ndp16->dpe16; - - for (x = 0; x < nframes; x++, dpe16++) { - int offset = le16_to_cpu(dpe16->wDatagramIndex); - int skb_len = le16_to_cpu(dpe16->wDatagramLength); - struct sk_buff *skb; - - if (offset == 0 || skb_len == 0) { - break; - } - - /* sanity checking */ - if (((offset + skb_len) > skb_in->len) || (skb_len > ctx->rx_max)) { - MSG_ERR("invalid frame detected (ignored) x=%d, offset=%d, skb_len=%u\n", x, offset, skb_len); - goto error; - } - - skb = skb_clone(skb_in, GFP_ATOMIC); - if (!skb) { - MSG_ERR("skb_clone fail\n"); - goto error; - } - - skb_pull(skb, offset); - skb_trim(skb, skb_len); - switch (skb->data[0] & 0xf0) { - case 0x40: - skb->protocol = htons(ETH_P_IP); - break; - case 0x60: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - MSG_ERR("unknow skb->protocol %02x\n", skb->data[0]); - goto error; - } - skb_reset_mac_header(skb); - - /* map MBIM session to VLAN */ - if (tci) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci); - - netif_receive_skb(skb); - } - - /* are there more NDPs to process? */ - ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex); - } - - return 1; -error: - MSG_ERR("%s error\n", __func__); - return 0; -} -#else -static struct sk_buff *mhi_qmap_tx_fixup(struct mhi_netdev *mhi_netdev, struct sk_buff *skb, struct net_device *dev) { - struct qmap_hdr *qhdr; - u16 tci = 0; - - if (skb->len > VLAN_ETH_HLEN && __vlan_get_tag(skb, &tci) == 0) - { - skb_pull(skb, VLAN_ETH_HLEN); - } - else - { - skb_pull(skb, ETH_HLEN); - } - - if (skb_headroom(skb) < sizeof(struct qmap_hdr)) { - printk("skb_headroom small!\n"); - return NULL; - } - - qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr)); - qhdr->cd_rsvd_pad = 0; - qhdr->mux_id = FIBO_QMAP_MUX_ID + tci; - qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr)); - - return skb; -} - -static int mhi_qmap_rx_fixup(struct mhi_netdev *mhi_netdev, struct sk_buff *skb_in, struct net_device *dev) -{ - while (skb_in->len > sizeof(struct qmap_hdr)) - { - struct qmap_hdr *qhdr = (struct qmap_hdr *)skb_in->data; - struct sk_buff *skb = NULL; - int pkt_len = be16_to_cpu(qhdr->pkt_len); - u16 tci = qhdr->mux_id - FIBO_QMAP_MUX_ID; - int skb_len; - int ret; - - if (skb_in->len < (pkt_len + sizeof(struct qmap_hdr))) - { - MSG_ERR("drop qmap unknow pkt, len=%d, pkt_len=%d\n", skb_in->len, pkt_len); - goto error; - } - - if (qhdr->cd_rsvd_pad & 0x80) - { - MSG_ERR("drop qmap command packet %x\n", qhdr->cd_rsvd_pad); - skb_pull(skb_in, pkt_len + sizeof(struct qmap_hdr)); - continue; - } - - skb_len = pkt_len - (qhdr->cd_rsvd_pad&0x3F); - - skb = netdev_alloc_skb_ip_align(dev, skb_len + ETH_HLEN); - if (!skb) - { - MSG_ERR("netdev_alloc_skb_ip_align fail\n"); - goto error; - } - - switch (skb_in->data[sizeof(struct qmap_hdr)] & 0xf0) - { - case 0x40: - { - skb->protocol = htons(ETH_P_IP); - break; - } - - case 0x60: - { - skb->protocol = htons(ETH_P_IPV6); - break; - } - - default: - { - MSG_ERR("unknow skb->protocol %02x\n", skb->data[0]); - kfree_skb(skb); - goto error; - } - } - - /* add an ethernet header */ - skb_put(skb, ETH_HLEN); - skb_reset_mac_header(skb); - eth_hdr(skb)->h_proto = skb->protocol;; - eth_zero_addr(eth_hdr(skb)->h_source); - memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, ETH_ALEN); - - /* add datagram */ - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,15,0 )) - fibo_skb_put_data(skb, skb_in->data + sizeof(struct qmap_hdr), skb_len); - #else - skb_put_data(skb, skb_in->data + sizeof(struct qmap_hdr), skb_len); - #endif - - skb_pull(skb, ETH_HLEN); - - /* map MBIM session to VLAN */ - if (tci) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci); - - ret = netif_receive_skb(skb); - - skb_pull(skb_in, pkt_len + sizeof(struct qmap_hdr)); - } - - return 1; - -error: - MSG_ERR("%s error\n", __func__); - return 0; -} -#endif - -static int mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int res = 0; - struct mhi_skb_priv *tx_priv; - - MSG_VERB("Entered\n"); - - tx_priv = (struct mhi_skb_priv *)(skb->cb); - tx_priv->mhi_netdev = mhi_netdev; - read_lock_bh(&mhi_netdev->pm_lock); - - if (unlikely(!mhi_netdev->enabled)) { - /* Only reason interface could be disabled and we get data - * is due to an SSR. We do not want to stop the queue and - * return error. Instead we will flush all the uplink packets - * and return successful - */ - res = NETDEV_TX_OK; - dev_kfree_skb_any(skb); - goto mhi_xmit_exit; - } - -#ifdef CONFIG_MHI_NETDEV_MBIM - if (mhi_mbim_tx_fixup(mhi_netdev, skb, dev) == NULL) { - res = NETDEV_TX_OK; - dev_kfree_skb_any(skb); - goto mhi_xmit_exit; - } -#else - if (qmap_mode) { - if (mhi_qmap_tx_fixup(mhi_netdev, skb, dev) == NULL) { - res = NETDEV_TX_OK; - dev_kfree_skb_any(skb); - goto mhi_xmit_exit; - } - } -#endif - - qmap_hex_dump(__func__, skb->data, skb->len); - - res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len, - MHI_EOT); - if (res) { - MSG_VERB("Failed to queue with reason:%d\n", res); - netif_stop_queue(dev); - mhi_netdev->stats.tx_full++; - res = NETDEV_TX_BUSY; - goto mhi_xmit_exit; - } - - mhi_netdev->stats.tx_pkts++; - -mhi_xmit_exit: - read_unlock_bh(&mhi_netdev->pm_lock); - MSG_VERB("Exited\n"); - - return res; -} - -static const struct net_device_ops mhi_netdev_ops_ip = { - .ndo_open = mhi_netdev_open, - .ndo_start_xmit = mhi_netdev_xmit, - .ndo_change_mtu = mhi_netdev_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static void mhi_netdev_setup(struct net_device *dev) -{ - dev->netdev_ops = &mhi_netdev_ops_ip; - ether_setup(dev); - - /* set this after calling ether_setup */ - dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; - dev->watchdog_timeo = WATCHDOG_TIMEOUT; -} - -/* enable mhi_netdev netdev, call only after grabbing mhi_netdev.mutex */ -static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev) -{ - int ret = 0; - char ifname[IFNAMSIZ]; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int no_tre; - - MSG_LOG("Prepare the channels for transfer\n"); - - ret = mhi_prepare_for_transfer(mhi_dev); - if (ret) { - MSG_ERR("Failed to start TX chan ret %d\n", ret); - goto mhi_failed_to_start; - } - - /* first time enabling the node */ - if (!mhi_netdev->ndev) { - struct mhi_netdev_priv *mhi_netdev_priv; - - snprintf(ifname, sizeof(ifname), "%s%%d", - mhi_netdev->interface_name); - - rtnl_lock(); -#ifdef NET_NAME_PREDICTABLE - mhi_netdev->ndev = alloc_netdev(sizeof(*mhi_netdev_priv), - ifname, NET_NAME_PREDICTABLE, - mhi_netdev_setup); -#else - mhi_netdev->ndev = alloc_netdev(sizeof(*mhi_netdev_priv), - ifname, - mhi_netdev_setup); -#endif - - if (!mhi_netdev->ndev) { - ret = -ENOMEM; - rtnl_unlock(); - goto net_dev_alloc_fail; - } - - //mhi_netdev->ndev->mtu = mhi_dev->mtu; - SET_NETDEV_DEV(mhi_netdev->ndev, &mhi_dev->dev); - mhi_netdev_priv = netdev_priv(mhi_netdev->ndev); - mhi_netdev_priv->mhi_netdev = mhi_netdev; - rtnl_unlock(); - - netif_napi_add(mhi_netdev->ndev, &mhi_netdev->napi, - mhi_netdev_poll, NAPI_POLL_WEIGHT); - ret = register_netdev(mhi_netdev->ndev); - if (ret) { - MSG_ERR("Network device registration failed\n"); - goto net_dev_reg_fail; - } - - skb_queue_head_init(&mhi_netdev->rx_allocated); - } - - write_lock_irq(&mhi_netdev->pm_lock); - mhi_netdev->enabled = true; - write_unlock_irq(&mhi_netdev->pm_lock); - - /* queue buffer for rx path */ - no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - ret = mhi_netdev_alloc_skb(mhi_netdev, GFP_KERNEL); - if (ret) - schedule_work(&mhi_netdev->alloc_work); - - /* if we recycle prepare one more set */ - if (mhi_netdev->recycle_buf) - for (; no_tre >= 0; no_tre--) { - struct sk_buff *skb = alloc_skb(mhi_netdev->mru + ETH_HLEN, - GFP_KERNEL); - struct mhi_skb_priv *skb_priv; - - if (!skb) - break; - - skb_reserve(skb, ETH_HLEN); - - skb_priv = (struct mhi_skb_priv *)skb->cb; - skb_priv->buf = skb->data; - skb_priv->size = mhi_netdev->mru; - skb_priv->mhi_netdev = mhi_netdev; - skb->dev = mhi_netdev->ndev; - skb->destructor = mhi_netdev_skb_destructor; - skb_queue_tail(&mhi_netdev->rx_allocated, skb); - } - - napi_enable(&mhi_netdev->napi); - - MSG_LOG("Exited.\n"); - - return 0; - -net_dev_reg_fail: - netif_napi_del(&mhi_netdev->napi); - free_netdev(mhi_netdev->ndev); - mhi_netdev->ndev = NULL; - -net_dev_alloc_fail: - mhi_unprepare_from_transfer(mhi_dev); - -mhi_failed_to_start: - MSG_ERR("Exited ret %d.\n", ret); - - return ret; -} - -static void mhi_netdev_xfer_ul_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct sk_buff *skb = mhi_result->buf_addr; - struct net_device *ndev = mhi_netdev->ndev; - - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb(skb); - - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); -} - -static int mhi_netdev_process_fragment(struct mhi_netdev *mhi_netdev, - struct sk_buff *skb) -{ - struct sk_buff *temp_skb; - - if (mhi_netdev->frag_skb) { - /* merge the new skb into the old fragment */ - temp_skb = skb_copy_expand(mhi_netdev->frag_skb, ETH_HLEN, skb->len, - GFP_ATOMIC); - if (!temp_skb) { - dev_kfree_skb(mhi_netdev->frag_skb); - mhi_netdev->frag_skb = NULL; - return -ENOMEM; - } - - dev_kfree_skb_any(mhi_netdev->frag_skb); - mhi_netdev->frag_skb = temp_skb; - memcpy(skb_put(mhi_netdev->frag_skb, skb->len), skb->data, - skb->len); - } else { - mhi_netdev->frag_skb = skb_copy(skb, GFP_ATOMIC); - if (!mhi_netdev->frag_skb) - return -ENOMEM; - } - - mhi_netdev->stats.rx_frag++; - - return 0; -} - -static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct sk_buff *skb = mhi_result->buf_addr; - struct net_device *dev = mhi_netdev->ndev; - int ret = 0; - static size_t bytes_xferd = 0; - - if (mhi_result->transaction_status == -ENOTCONN) { - dev_kfree_skb(skb); - return; - } - - if (mhi_result->bytes_xferd > bytes_xferd) { - bytes_xferd = mhi_result->bytes_xferd; - //printk("%s bytes_xferd=%zd\n", __func__, bytes_xferd); - } - - skb_put(skb, mhi_result->bytes_xferd); - dev->stats.rx_packets++; - dev->stats.rx_bytes += mhi_result->bytes_xferd; - - /* merge skb's together, it's a chain transfer */ - if (mhi_result->transaction_status == -EOVERFLOW || - mhi_netdev->frag_skb) { - ret = mhi_netdev_process_fragment(mhi_netdev, skb); - - /* recycle the skb */ - if (mhi_netdev->recycle_buf) - mhi_netdev_skb_destructor(skb); - else - dev_kfree_skb(skb); - - if (ret) - return; - } - - /* more data will come, don't submit the buffer */ - if (mhi_result->transaction_status == -EOVERFLOW) - return; - - if (mhi_netdev->frag_skb) { - skb = mhi_netdev->frag_skb; - skb->dev = dev; - mhi_netdev->frag_skb = NULL; - } - - qmap_hex_dump(__func__, skb->data, skb->len); - -#ifdef CONFIG_MHI_NETDEV_MBIM - mhi_mbim_rx_fixup(mhi_netdev, skb, dev); - dev_kfree_skb_any(skb); -#else - if (qmap_mode) { - mhi_qmap_rx_fixup(mhi_netdev, skb, dev); - dev_kfree_skb_any(skb); - } - else { - switch (skb->data[0] & 0xf0) { - case 0x40: - skb->protocol = htons(ETH_P_IP); - netif_receive_skb(skb); - break; - case 0x60: - skb->protocol = htons(ETH_P_IPV6); - netif_receive_skb(skb); - break; - default: - break; - } - } -#endif - - mhi_netdev->rx_queue(mhi_netdev, GFP_ATOMIC); -} - -static void mhi_netdev_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - - if (mhi_cb != MHI_CB_PENDING_DATA) - return; - - if (napi_schedule_prep(&mhi_netdev->napi)) { - __napi_schedule(&mhi_netdev->napi); - mhi_netdev->stats.rx_int++; - return; - } - -} - -#ifdef CONFIG_DEBUG_FS - -struct dentry *mhi_netdev_debugfs_dentry; - -static int mhi_netdev_debugfs_trigger_reset(void *data, u64 val) -{ - struct mhi_netdev *mhi_netdev = data; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int ret; - - MSG_LOG("Triggering channel reset\n"); - - /* disable the interface so no data processing */ - write_lock_irq(&mhi_netdev->pm_lock); - mhi_netdev->enabled = false; - write_unlock_irq(&mhi_netdev->pm_lock); - napi_disable(&mhi_netdev->napi); - - /* disable all hardware channels */ - mhi_unprepare_from_transfer(mhi_dev); - - /* clean up all alocated buffers */ - mhi_netdev_dealloc(mhi_netdev); - - MSG_LOG("Restarting iface\n"); - - ret = mhi_netdev_enable_iface(mhi_netdev); - if (ret) - return ret; - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(mhi_netdev_debugfs_trigger_reset_fops, NULL, - mhi_netdev_debugfs_trigger_reset, "%llu\n"); - -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev) -{ - char node_name[32]; - int i; - const umode_t mode = 0600; - struct dentry *file; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct dentry *dentry = mhi_netdev_debugfs_dentry; - - const struct { - char *name; - u32 *ptr; - } debugfs_table[] = { - { - "rx_int", - &mhi_netdev->stats.rx_int - }, - { - "tx_full", - &mhi_netdev->stats.tx_full - }, - { - "tx_pkts", - &mhi_netdev->stats.tx_pkts - }, - { - "rx_budget_overflow", - &mhi_netdev->stats.rx_budget_overflow - }, - { - "rx_fragmentation", - &mhi_netdev->stats.rx_frag - }, - { - "alloc_failed", - &mhi_netdev->stats.alloc_failed - }, - { - NULL, NULL - }, - }; - - /* Both tx & rx client handle contain same device info */ - snprintf(node_name, sizeof(node_name), "%s_%04x_%02u.%02u.%02u_%u", - mhi_netdev->interface_name, mhi_dev->dev_id, mhi_dev->domain, - mhi_dev->bus, mhi_dev->slot, mhi_netdev->alias); - - if (IS_ERR_OR_NULL(dentry)) - return; - - mhi_netdev->dentry = debugfs_create_dir(node_name, dentry); - if (IS_ERR_OR_NULL(mhi_netdev->dentry)) - return; - /*begin added by tony.du for mantis 0062018 on 2020-11-10*/ - debugfs_create_u32("msg_lvl", mode, mhi_netdev->dentry, - (u32 *)&mhi_netdev->msg_lvl); - /*end added by tony.du for mantis 0062018 on 2020-11-10*/ - - /* Add debug stats table */ - for (i = 0; debugfs_table[i].name; i++) { - /*begin added by tony.du for mantis 0062018 on 2020-11-10*/ - debugfs_create_u32(debugfs_table[i].name, mode, - mhi_netdev->dentry, - debugfs_table[i].ptr); - /*end added by tony.du for mantis 0062018 on 2020-11-10*/ - } - - debugfs_create_file("reset", mode, mhi_netdev->dentry, mhi_netdev, - &mhi_netdev_debugfs_trigger_reset_fops); -} - -static void mhi_netdev_create_debugfs_dir(struct dentry *parent) -{ - mhi_netdev_debugfs_dentry = debugfs_create_dir(MHI_NETDEV_DRIVER_NAME, parent); -} - -#else - -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev) -{ -} - -static void mhi_netdev_create_debugfs_dir(struct dentry *parent) -{ -} - -#endif - -static void mhi_netdev_remove(struct mhi_device *mhi_dev) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - - MSG_LOG("Remove notification received\n"); - - write_lock_irq(&mhi_netdev->pm_lock); - mhi_netdev->enabled = false; - write_unlock_irq(&mhi_netdev->pm_lock); - - napi_disable(&mhi_netdev->napi); - netif_napi_del(&mhi_netdev->napi); - mhi_netdev_dealloc(mhi_netdev); - unregister_netdev(mhi_netdev->ndev); - free_netdev(mhi_netdev->ndev); - flush_work(&mhi_netdev->alloc_work); - - if (!IS_ERR_OR_NULL(mhi_netdev->dentry)) - debugfs_remove_recursive(mhi_netdev->dentry); -} - -static int mhi_netdev_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - int ret; - struct mhi_netdev *mhi_netdev; - - mhi_netdev = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_netdev), - GFP_KERNEL); - if (!mhi_netdev) - return -ENOMEM; - - mhi_netdev->alias = 0; - - mhi_netdev->mhi_dev = mhi_dev; - mhi_device_set_devdata(mhi_dev, mhi_netdev); - - mhi_netdev->mru = 0x4000; - if (mhi_dev->dev_id == 0x0304) { //SDX24 - mhi_netdev->mru = 0x8000; - } -#ifdef CONFIG_MHI_NETDEV_MBIM - mhi_netdev->rx_max = 0x8000; -#endif - - if (!strcmp(id->chan, "IP_HW0")) - mhi_netdev->interface_name = "pcie_mhi"; - else if (!strcmp(id->chan, "IP_SW0")) - mhi_netdev->interface_name = "pcie_swip"; - else - mhi_netdev->interface_name = id->chan; - - mhi_netdev->recycle_buf = false; - - mhi_netdev->rx_queue = mhi_netdev->recycle_buf ? - mhi_netdev_skb_recycle : mhi_netdev_alloc_skb; - - spin_lock_init(&mhi_netdev->rx_lock); - rwlock_init(&mhi_netdev->pm_lock); - INIT_WORK(&mhi_netdev->alloc_work, mhi_netdev_alloc_work); - - mhi_netdev->msg_lvl = MHI_MSG_LVL_INFO; - - /* setup network interface */ - ret = mhi_netdev_enable_iface(mhi_netdev); - if (ret) { - pr_err("Error mhi_netdev_enable_iface ret:%d\n", ret); - return ret; - } - - mhi_netdev_create_debugfs(mhi_netdev); - - g_mhi_netdev = mhi_netdev; - - return 0; -} - -static const struct mhi_device_id mhi_netdev_match_table[] = { - { .chan = "IP_HW0" }, - { .chan = "IP_SW0" }, - { .chan = "IP_HW_ADPL" }, - { }, -}; - -static struct mhi_driver mhi_netdev_driver = { - .id_table = mhi_netdev_match_table, - .probe = mhi_netdev_probe, - .remove = mhi_netdev_remove, - .ul_xfer_cb = mhi_netdev_xfer_ul_cb, - .dl_xfer_cb = mhi_netdev_xfer_dl_cb, - .status_cb = mhi_netdev_status_cb, - .driver = { - .name = "mhi_netdev", - .owner = THIS_MODULE, - } -}; - -int __init mhi_device_netdev_init(struct dentry *parent) -{ - mhi_netdev_create_debugfs_dir(parent); - - return mhi_driver_register(&mhi_netdev_driver); -} - -void mhi_device_netdev_exit(void) -{ -#ifdef CONFIG_DEBUG_FS - debugfs_remove_recursive(mhi_netdev_debugfs_dentry); -#endif - mhi_driver_unregister(&mhi_netdev_driver); -} diff --git a/fibocom_MHI/src/devices/mhi_netdev.h b/fibocom_MHI/src/devices/mhi_netdev.h deleted file mode 100644 index 13735bb..0000000 --- a/fibocom_MHI/src/devices/mhi_netdev.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _FIBO_MHI_NETDEV_H -#define _FIBO_MHI_NETDEV_H - -#include - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,15,0 )) -static inline void *fibo_skb_put_data(struct sk_buff *skb, const void *data, - unsigned int len) -{ - void *tmp = skb_put(skb, len); - - memcpy(tmp,data, len); - - return tmp; -} -#endif - -#endif diff --git a/fibocom_MHI/src/devices/mhi_uci.c b/fibocom_MHI/src/devices/mhi_uci.c deleted file mode 100644 index 7195ab0..0000000 --- a/fibocom_MHI/src/devices/mhi_uci.c +++ /dev/null @@ -1,785 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/mhi.h" - -#define DEVICE_NAME "mhi" -#define MHI_UCI_DRIVER_NAME "mhi_uci" - -struct uci_chan { - wait_queue_head_t wq; - spinlock_t lock; - struct list_head pending; /* user space waiting to read */ - struct uci_buf *cur_buf; /* current buffer user space reading */ - size_t rx_size; -}; - -struct uci_buf { - void *data; - size_t len; - struct list_head node; -}; - -struct uci_dev { - struct list_head node; - dev_t devt; - struct device *dev; - struct mhi_device *mhi_dev; - const char *chan; - struct mutex mutex; /* sync open and close */ - struct uci_chan ul_chan; - struct uci_chan dl_chan; - size_t mtu; - int ref_count; - bool enabled; - bool disconnect; - struct ktermios termios; - int sigs; -}; - -struct mhi_uci_drv { - struct list_head head; - struct mutex lock; - struct class *class; - int major; - dev_t dev_t; -}; - -enum MHI_DEBUG_LEVEL msg_lvl = MHI_MSG_LVL_ERROR; - -typedef struct _QCQMI_HDR { - u8 IFType; - u16 Length; - u8 CtlFlags; // reserved - u8 QMIType; - u8 ClientId; -} __attribute__ ((packed)) *PQCQMI_HDR; - -#define MSG_VERB(fmt, ...) do { \ - if (msg_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -#define MSG_LOG(fmt, ...) do { \ - if (msg_lvl <= MHI_MSG_LVL_INFO) \ - pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -#define MSG_ERR(fmt, ...) do { \ - if (msg_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -#define MAX_UCI_DEVICES (64) -#define QUEC_MHI_UCI_ALWAYS_OPEN //by now, sdx20 can not handle "start-reset-start" operation, so the simply solution is keep start state - -static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); -static struct mhi_uci_drv mhi_uci_drv; - -static int mhi_queue_inbound(struct uci_dev *uci_dev) -{ - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - size_t mtu = uci_dev->mtu; - void *buf; - struct uci_buf *uci_buf; - int ret = -EIO, i; - - for (i = 0; i < nr_trbs; i++) { - buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - uci_buf = buf + mtu; - uci_buf->data = buf; - - MSG_VERB("Allocated buf %d of %d size %zd\n", i, nr_trbs, mtu); - - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, - MHI_EOT); - if (ret) { - kfree(buf); - MSG_ERR("Failed to queue buffer %d\n", i); - return ret; - } - } - - return ret; -} - -static long mhi_uci_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - long ret = -ERESTARTSYS; - - mutex_lock(&uci_dev->mutex); - if (uci_dev->enabled) { - switch (cmd) { - case TCGETS: -#ifndef TCGETS2 - ret = kernel_termios_to_user_termios((struct termios __user *)arg, &uci_dev->termios); -#else - ret = kernel_termios_to_user_termios_1((struct termios __user *)arg, &uci_dev->termios); -#endif - break; - - case TCSETSF: - case TCSETS: -#ifndef TCGETS2 - ret = user_termios_to_kernel_termios(&uci_dev->termios, (struct termios __user *)arg); -#else - ret = user_termios_to_kernel_termios_1(&uci_dev->termios, (struct termios __user *)arg); -#endif - break; - - case TIOCMSET: - case TIOCMBIS: - case TIOCMBIC: - { - uint32_t val; - - ret = get_user(val, (uint32_t *)arg); - if (ret) - return ret; - - switch (cmd) { - case TIOCMBIS: - uci_dev->sigs |= val; - break; - case TIOCMBIC: - uci_dev->sigs &= ~val; - break; - case TIOCMSET: - uci_dev->sigs = val; - break; - } - } - break; - - case TIOCMGET: - ret = put_user(uci_dev->sigs | TIOCM_RTS, (uint32_t *)arg); - break; - - case TCFLSH: - ret = 0; - break; - - default: - ret = mhi_ioctl(mhi_dev, cmd, arg); - break; - } - } - mutex_unlock(&uci_dev->mutex); - - return ret; -} - -static int mhi_uci_release(struct inode *inode, struct file *file) -{ - struct uci_dev *uci_dev = file->private_data; - - mutex_lock(&uci_dev->mutex); - uci_dev->ref_count--; - if (!uci_dev->ref_count) { - struct uci_buf *itr, *tmp; - struct uci_chan *uci_chan; - - MSG_LOG("Last client left, closing node\n"); - - if (uci_dev->enabled) - mhi_unprepare_from_transfer(uci_dev->mhi_dev); - - /* clean inbound channel */ - uci_chan = &uci_dev->dl_chan; - list_for_each_entry_safe(itr, tmp, &uci_chan->pending, node) { - list_del(&itr->node); - kfree(itr->data); - } - if (uci_chan->cur_buf) - kfree(uci_chan->cur_buf->data); - - uci_chan->cur_buf = NULL; - - if (!uci_dev->enabled) { - MSG_LOG("Node is deleted, freeing dev node\n"); - mutex_unlock(&uci_dev->mutex); - mutex_destroy(&uci_dev->mutex); - clear_bit(MINOR(uci_dev->devt), uci_minors); - kfree(uci_dev); - return 0; - } - } - - mutex_unlock(&uci_dev->mutex); - - MSG_LOG("exit: ref_count:%d\n", uci_dev->ref_count); - - return 0; -} - -static unsigned int mhi_uci_poll(struct file *file, poll_table *wait) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - struct uci_chan *uci_chan; - unsigned int mask = 0; - - poll_wait(file, &uci_dev->dl_chan.wq, wait); - poll_wait(file, &uci_dev->ul_chan.wq, wait); - - uci_chan = &uci_dev->dl_chan; - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - mask = POLLERR; - } else if (!list_empty(&uci_chan->pending) || uci_chan->cur_buf) { - MSG_VERB("Client can read from node\n"); - mask |= POLLIN | POLLRDNORM; - } - spin_unlock_bh(&uci_chan->lock); - - uci_chan = &uci_dev->ul_chan; - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - mask |= POLLERR; - } else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) { - MSG_VERB("Client can write to node\n"); - mask |= POLLOUT | POLLWRNORM; - } - - if (uci_dev->disconnect) - mask |= POLLHUP; - - spin_unlock_bh(&uci_chan->lock); - - MSG_VERB("Client attempted to poll, returning mask 0x%x\n", mask); - - return mask; -} - -static ssize_t mhi_uci_write(struct file *file, - const char __user *buf, - size_t count, - loff_t *offp) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - struct uci_chan *uci_chan = &uci_dev->ul_chan; - size_t bytes_xfered = 0; - int ret; - - if (!buf || !count) - return -EINVAL; - - /* confirm channel is active */ - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - spin_unlock_bh(&uci_chan->lock); - return -ERESTARTSYS; - } - - MSG_VERB("Enter: to xfer:%zd bytes\n", count); - - while (count) { - size_t xfer_size; - void *kbuf; - enum MHI_FLAGS flags; - - spin_unlock_bh(&uci_chan->lock); - - if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) == 0 && (file->f_mode & FMODE_NDELAY)) - break; - - /* wait for free descriptors */ - ret = wait_event_interruptible(uci_chan->wq, - (!uci_dev->enabled) || - mhi_get_no_free_descriptors - (mhi_dev, DMA_TO_DEVICE) > 0); - - if (ret == -ERESTARTSYS) { - MSG_LOG("Exit signal caught for node\n"); - return -ERESTARTSYS; - } - - xfer_size = min_t(size_t, count, uci_dev->mtu); - kbuf = kmalloc(xfer_size, GFP_KERNEL); - if (!kbuf) { - MSG_ERR("Failed to allocate memory %zd\n", xfer_size); - return -ENOMEM; - } - - ret = copy_from_user(kbuf, buf, xfer_size); - if (unlikely(ret)) { - kfree(kbuf); - return ret; - } - - spin_lock_bh(&uci_chan->lock); - flags = MHI_EOT; - if (uci_dev->enabled) - ret = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, kbuf, - xfer_size, flags); - else - ret = -ERESTARTSYS; - - if (ret) { - kfree(kbuf); - goto sys_interrupt; - } - - bytes_xfered += xfer_size; - count -= xfer_size; - buf += xfer_size; - } - - spin_unlock_bh(&uci_chan->lock); - MSG_VERB("Exit: Number of bytes xferred:%zd\n", bytes_xfered); - - return bytes_xfered; - -sys_interrupt: - spin_unlock_bh(&uci_chan->lock); - - return ret; -} - -static ssize_t mhi_uci_read(struct file *file, - char __user *buf, - size_t count, - loff_t *ppos) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - struct uci_chan *uci_chan = &uci_dev->dl_chan; - struct uci_buf *uci_buf; - char *ptr; - size_t to_copy; - int ret = 0; - - if (!buf) - return -EINVAL; - - MSG_VERB("Client provided buf len:%zd\n", count); - - /* confirm channel is active */ - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - spin_unlock_bh(&uci_chan->lock); - return -ERESTARTSYS; - } - - /* No data available to read, wait */ - if (!uci_chan->cur_buf && list_empty(&uci_chan->pending)) { - MSG_VERB("No data available to read waiting\n"); - - spin_unlock_bh(&uci_chan->lock); - - if (file->f_mode & FMODE_NDELAY) - return -EAGAIN; - - ret = wait_event_interruptible(uci_chan->wq, - (!uci_dev->enabled || - !list_empty(&uci_chan->pending))); - if (ret == -ERESTARTSYS) { - MSG_LOG("Exit signal caught for node\n"); - return -ERESTARTSYS; - } - - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - MSG_LOG("node is disabled\n"); - ret = -ERESTARTSYS; - goto read_error; - } - } - - /* new read, get the next descriptor from the list */ - if (!uci_chan->cur_buf) { - uci_buf = list_first_entry_or_null(&uci_chan->pending, - struct uci_buf, node); - if (unlikely(!uci_buf)) { - ret = -EIO; - goto read_error; - } - - list_del(&uci_buf->node); - uci_chan->cur_buf = uci_buf; - uci_chan->rx_size = uci_buf->len; - MSG_VERB("Got pkt of size:%zd\n", uci_chan->rx_size); - } - - uci_buf = uci_chan->cur_buf; - spin_unlock_bh(&uci_chan->lock); - - /* Copy the buffer to user space */ - to_copy = min_t(size_t, count, uci_chan->rx_size); - ptr = uci_buf->data + (uci_buf->len - uci_chan->rx_size); - ret = copy_to_user(buf, ptr, to_copy); - if (ret) - return ret; - - MSG_VERB("Copied %zd of %zd bytes\n", to_copy, uci_chan->rx_size); - uci_chan->rx_size -= to_copy; - - /* we finished with this buffer, queue it back to hardware */ - if (!uci_chan->rx_size) { - spin_lock_bh(&uci_chan->lock); - uci_chan->cur_buf = NULL; - - if (uci_dev->enabled) - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, - uci_buf->data, uci_dev->mtu, - MHI_EOT); - else - ret = -ERESTARTSYS; - - if (ret) { - MSG_ERR("Failed to recycle element\n"); - kfree(uci_buf->data); - goto read_error; - } - - spin_unlock_bh(&uci_chan->lock); - } - - MSG_VERB("Returning %zd bytes\n", to_copy); - - return to_copy; - -read_error: - spin_unlock_bh(&uci_chan->lock); - - return ret; -} - -static int mhi_uci_open(struct inode *inode, struct file *filp) -{ - struct uci_dev *uci_dev; - int ret = -EIO; - struct uci_buf *buf_itr, *tmp; - struct uci_chan *dl_chan; - - mutex_lock(&mhi_uci_drv.lock); - list_for_each_entry(uci_dev, &mhi_uci_drv.head, node) { - if (uci_dev->devt == inode->i_rdev) { - ret = 0; - break; - } - } - mutex_unlock(&mhi_uci_drv.lock); - - /* could not find a minor node */ - if (ret) - return ret; - - mutex_lock(&uci_dev->mutex); - if (!uci_dev->enabled) { - MSG_ERR("Node exist, but not in active state!\n"); - goto error_open_chan; - } - - uci_dev->ref_count++; - - MSG_LOG("Node open, ref counts %u\n", uci_dev->ref_count); - - if (uci_dev->ref_count == 1) { - MSG_LOG("Starting channel\n"); - ret = mhi_prepare_for_transfer(uci_dev->mhi_dev); - if (ret) { - MSG_ERR("Error starting transfer channels\n"); - uci_dev->ref_count--; - goto error_open_chan; - } - - ret = mhi_queue_inbound(uci_dev); - if (ret) - goto error_rx_queue; - -#ifdef QUEC_MHI_UCI_ALWAYS_OPEN - uci_dev->ref_count++; - if (uci_dev->mhi_dev->dl_chan_id == MHI_CLIENT_QMI_IN) { - } - if (uci_dev->mhi_dev->dl_chan_id == MHI_CLIENT_MBIM_IN) { - } -#endif - } - - filp->private_data = uci_dev; - mutex_unlock(&uci_dev->mutex); - - return 0; - - error_rx_queue: - dl_chan = &uci_dev->dl_chan; - mhi_unprepare_from_transfer(uci_dev->mhi_dev); - list_for_each_entry_safe(buf_itr, tmp, &dl_chan->pending, node) { - list_del(&buf_itr->node); - kfree(buf_itr->data); - } - - error_open_chan: - mutex_unlock(&uci_dev->mutex); - - return ret; -} - -static const struct file_operations mhidev_fops = { - .open = mhi_uci_open, - .release = mhi_uci_release, - .read = mhi_uci_read, - .write = mhi_uci_write, - .poll = mhi_uci_poll, - .unlocked_ioctl = mhi_uci_ioctl, -}; - -static void mhi_uci_remove(struct mhi_device *mhi_dev) -{ - struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev); - - MSG_LOG("Enter\n"); - - /* disable the node */ - mutex_lock(&uci_dev->mutex); - spin_lock_irq(&uci_dev->dl_chan.lock); - spin_lock_irq(&uci_dev->ul_chan.lock); - uci_dev->enabled = false; - uci_dev->disconnect = true; - spin_unlock_irq(&uci_dev->ul_chan.lock); - spin_unlock_irq(&uci_dev->dl_chan.lock); - wake_up(&uci_dev->dl_chan.wq); - wake_up(&uci_dev->ul_chan.wq); - - /* delete the node to prevent new opens */ - device_destroy(mhi_uci_drv.class, uci_dev->devt); - uci_dev->dev = NULL; - mutex_lock(&mhi_uci_drv.lock); - list_del(&uci_dev->node); - mutex_unlock(&mhi_uci_drv.lock); - -#ifdef QUEC_MHI_UCI_ALWAYS_OPEN - if (uci_dev->ref_count > 0) - uci_dev->ref_count--; -#endif - - /* safe to free memory only if all file nodes are closed */ - if (!uci_dev->ref_count) { - mutex_unlock(&uci_dev->mutex); - mutex_destroy(&uci_dev->mutex); - clear_bit(MINOR(uci_dev->devt), uci_minors); - kfree(uci_dev); - return; - } - - mutex_unlock(&uci_dev->mutex); - MSG_LOG("Exit\n"); -} - -static int mhi_uci_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - struct uci_dev *uci_dev; - int minor; - int dir; - - uci_dev = kzalloc(sizeof(*uci_dev), GFP_KERNEL); - if (!uci_dev) - return -ENOMEM; - - mutex_init(&uci_dev->mutex); - uci_dev->mhi_dev = mhi_dev; - - minor = find_first_zero_bit(uci_minors, MAX_UCI_DEVICES); - if (minor >= MAX_UCI_DEVICES) { - kfree(uci_dev); - return -ENOSPC; - } - - mutex_lock(&uci_dev->mutex); - mutex_lock(&mhi_uci_drv.lock); - - uci_dev->devt = MKDEV(mhi_uci_drv.major, minor); - - uci_dev->dev = device_create(mhi_uci_drv.class, &mhi_dev->dev, - uci_dev->devt, uci_dev, - DEVICE_NAME "_%s", - mhi_dev->chan_name); - - set_bit(minor, uci_minors); - - for (dir = 0; dir < 2; dir++) { - struct uci_chan *uci_chan = (dir) ? - &uci_dev->ul_chan : &uci_dev->dl_chan; - spin_lock_init(&uci_chan->lock); - init_waitqueue_head(&uci_chan->wq); - INIT_LIST_HEAD(&uci_chan->pending); - }; - - uci_dev->termios = tty_std_termios; - uci_dev->sigs = 0; - - uci_dev->mtu = id->driver_data; - mhi_device_set_devdata(mhi_dev, uci_dev); - uci_dev->enabled = true; - - list_add(&uci_dev->node, &mhi_uci_drv.head); - mutex_unlock(&mhi_uci_drv.lock); - mutex_unlock(&uci_dev->mutex); - - MSG_LOG("channel:%s successfully probed\n", mhi_dev->chan_name); - - return 0; -}; - -static void mhi_ul_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev); - struct uci_chan *uci_chan = &uci_dev->ul_chan; - - MSG_VERB("status:%d xfer_len:%zu\n", mhi_result->transaction_status, - mhi_result->bytes_xferd); - - kfree(mhi_result->buf_addr); - if (!mhi_result->transaction_status) - wake_up(&uci_chan->wq); -} - -static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev); - struct uci_chan *uci_chan = &uci_dev->dl_chan; - unsigned long flags; - struct uci_buf *buf; - - MSG_VERB("chan:mhi_dev->dl_chan_id:%d, status:%d receive_len:%zu\n", - mhi_dev->dl_chan_id, mhi_result->transaction_status, mhi_result->bytes_xferd); - - if (mhi_result->transaction_status == -ENOTCONN) { - kfree(mhi_result->buf_addr); - return; - } - - spin_lock_irqsave(&uci_chan->lock, flags); - buf = mhi_result->buf_addr + uci_dev->mtu; - if (buf->data != mhi_result->buf_addr) { - MSG_LOG("%p, %p\n", buf->data, mhi_result->buf_addr); - } - buf->data = mhi_result->buf_addr; - buf->len = mhi_result->bytes_xferd; - - if (uci_dev->mhi_dev->dl_chan_id == MHI_CLIENT_QMI_IN) { - PQCQMI_HDR pHdr = (PQCQMI_HDR) (buf->data); - u16 qmiLength = (le16_to_cpu(pHdr->Length) + 1); - -// open qmi chan, but not read data from the chan, will cause next error, donot know why by now, so it is not recomment to use uqmi&libqmi? -// dmesg -c > /dev/null; echo 1 > /dev/mhi_QMI0; sleep 3; ./FIBO-CM -d /dev/mhi_QMI0 -v - if (qmiLength != buf->len) { - unsigned char *d = (unsigned char *) pHdr; - MSG_ERR("bytes_xferd=%zd, qmiLength=%d %02x%02x%02x%02x - %02x%02x%02x%02x\n", buf->len, qmiLength, - d[0],d[1],d[2],d[3],d[qmiLength+0],d[qmiLength+1],d[qmiLength+2],d[qmiLength+3]); - if (buf->len > qmiLength) - buf->len = qmiLength; - } - } - - list_add_tail(&buf->node, &uci_chan->pending); - spin_unlock_irqrestore(&uci_chan->lock, flags); - - wake_up(&uci_chan->wq); -} - -#define DIAG_MAX_PCIE_PKT_SZ 2048 //define by module - -/* .driver_data stores max mtu */ -static const struct mhi_device_id mhi_uci_match_table[] = { - { .chan = "LOOPBACK", .driver_data = 0x1000 }, - { .chan = "SAHARA", .driver_data = 0x4000 }, - { .chan = "EDL", .driver_data = 0x4000 }, - { .chan = "DIAG", .driver_data = DIAG_MAX_PCIE_PKT_SZ }, - { .chan = "EFS", .driver_data = 0x1000 }, -#ifdef CONFIG_MHI_NETDEV_MBIM - { .chan = "MBIM", .driver_data = 0x1000 }, -#else - { .chan = "QMI0", .driver_data = 0x1000 }, - { .chan = "QMI1", .driver_data = 0x1000 }, -#endif - { .chan = "TF", .driver_data = 0x1000 }, - { .chan = "BL", .driver_data = 0x1000 }, - { .chan = "DUN", .driver_data = 0x1000 }, - { .chan = "GNSS", .driver_data = 0x1000 }, - { .chan = "AUDIO", .driver_data = 0x1000 }, - { }, -}; - -static struct mhi_driver mhi_uci_driver = { - .id_table = mhi_uci_match_table, - .remove = mhi_uci_remove, - .probe = mhi_uci_probe, - .ul_xfer_cb = mhi_ul_xfer_cb, - .dl_xfer_cb = mhi_dl_xfer_cb, - .driver = { - .name = MHI_UCI_DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -int mhi_device_uci_init(void) -{ - int ret; - - ret = register_chrdev(0, MHI_UCI_DRIVER_NAME, &mhidev_fops); - if (ret < 0) - return ret; - - mhi_uci_drv.major = ret; - mhi_uci_drv.class = class_create(THIS_MODULE, MHI_UCI_DRIVER_NAME); - if (IS_ERR(mhi_uci_drv.class)) { - unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); - return -ENODEV; - } - - mutex_init(&mhi_uci_drv.lock); - INIT_LIST_HEAD(&mhi_uci_drv.head); - - ret = mhi_driver_register(&mhi_uci_driver); - if (ret) { - class_destroy(mhi_uci_drv.class); - unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); - } - - return ret; -} - -void mhi_device_uci_exit(void) -{ - mhi_driver_unregister(&mhi_uci_driver); - class_destroy(mhi_uci_drv.class); - unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); -} diff --git a/fibocom_QMI_WWAN/Makefile b/fibocom_QMI_WWAN/Makefile deleted file mode 100644 index 836085e..0000000 --- a/fibocom_QMI_WWAN/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=qmi_wwan_f -PKG_VERSION:=1.0 -PKG_RELEASE:=2 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/qmi_wwan_f - SUBMENU:=WWAN Support - TITLE:=Fibocom Linux USB QMI WWAN Driver - DEPENDS:=+kmod-usb-net +kmod-usb-wdm - FILES:=$(PKG_BUILD_DIR)/qmi_wwan_f.ko - AUTOLOAD:=$(call AutoLoad,82,qmi_wwan_f) -endef - -define KernelPackage/qmi_wwan_f/description - Fibocom Linux USB QMI WWAN Driver -endef - -MAKE_OPTS:= \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CXXFLAGS="$(TARGET_CXXFLAGS)" \ - M="$(PKG_BUILD_DIR)" \ - $(EXTRA_KCONFIG) - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,qmi_wwan_f)) diff --git a/fibocom_QMI_WWAN/src/Makefile b/fibocom_QMI_WWAN/src/Makefile deleted file mode 100644 index 00250a1..0000000 --- a/fibocom_QMI_WWAN/src/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -obj-m += qmi_wwan_f.o - -PWD := $(shell pwd) -OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/ - -ifeq ($(ARCH),) -ARCH := $(shell uname -m) -endif -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := -endif -ifeq ($(KDIR),) -KDIR := /lib/modules/$(shell uname -r)/build -ifeq ($(ARCH),i686) -ifeq ($(wildcard $KDIR/arch/$ARCH),) -ARCH=i386 -endif -endif -endif - -ifneq ($(findstring &,${PWD}),) -$(warning "${PWD}") -$(warning "current directory contain special char '&' !") -$(error "please remove it!") -endif - -default: - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules - -install: default - cp $(PWD)/qmi_wwan_f.ko /lib/modules/$(shell uname -r)/kernel/drivers/net/usb/ - depmod - modprobe -r qmi_wwan_f - modprobe -r qmi_wwan - modprobe qmi_wwan_f -clean: - rm -rf *~ .tmp_versions modules.order Module.symvers - find . -type f -name "*~" -o -name "*.o" -o -name "*.ko" -o -name "*.cmd" -o -name "*.mod.c" | xargs rm -rf diff --git a/fibocom_QMI_WWAN/src/qmi_wwan_f.c b/fibocom_QMI_WWAN/src/qmi_wwan_f.c deleted file mode 100644 index 48efef7..0000000 --- a/fibocom_QMI_WWAN/src/qmi_wwan_f.c +++ /dev/null @@ -1,2534 +0,0 @@ -/* - * Copyright (c) 2012 Bjørn Mork - * - * The probing code is heavily inspired by cdc_ether, which is: - * Copyright (C) 2003-2005 by David Brownell - * Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(3,16,0) //8b094cd03b4a3793220d8d8d86a173bfea8c285b -#include -#else -#define timespec64 timespec -#define ktime_get_ts64 ktime_get_ts -#define timespec64_sub timespec_sub -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef ETH_P_MAP -#define ETH_P_MAP 0xDA1A -#endif - -#if (ETH_P_MAP == 0x00F9) -#undef ETH_P_MAP -#define ETH_P_MAP 0xDA1A -#endif - -#ifndef ARPHRD_RAWIP -#define ARPHRD_RAWIP ARPHRD_NONE -#endif - -#ifdef CONFIG_PINCTRL_IPQ807x -#define CONFIG_QCA_NSS_DRV -#endif - -#if 1//def CONFIG_QCA_NSS_DRV -#define _RMNET_NSS_H_ -#define _RMENT_NSS_H_ -struct rmnet_nss_cb { - int (*nss_create)(struct net_device *dev); - int (*nss_free)(struct net_device *dev); - int (*nss_tx)(struct sk_buff *skb); -}; -static struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; -#ifdef CONFIG_QCA_NSS_DRV -static uint __read_mostly qca_nss_enabled = 1; -module_param( qca_nss_enabled, uint, S_IRUGO); -#endif -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,0,0 )) //1e9e39f4a29857a396ac7b669d109f697f66695e -#define usbnet_set_skb_tx_stats(skb, packets, bytes_delta) do { dev->net->stats.tx_packets += packets; } while(0) -#endif - -/* This driver supports wwan (3G/LTE/?) devices using a vendor - * specific management protocol called Qualcomm MSM Interface (QMI) - - * in addition to the more common AT commands over serial interface - * management - * - * QMI is wrapped in CDC, using CDC encapsulated commands on the - * control ("master") interface of a two-interface CDC Union - * resembling standard CDC ECM. The devices do not use the control - * interface for any other CDC messages. Most likely because the - * management protocol is used in place of the standard CDC - * notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE - * - * Alternatively, control and data functions can be combined in a - * single USB interface. - * - * Handling a protocol like QMI is out of the scope for any driver. - * It is exported as a character device using the cdc-wdm driver as - * a subdriver, enabling userspace applications ("modem managers") to - * handle it. - * - * These devices may alternatively/additionally be configured using AT - * commands on a serial interface - */ -#define VERSION_NUMBER "V1.0.5" -#define FIBOCOM_WWAN_VERSION "Fibocom_QMI_WWAN_Driver_"VERSION_NUMBER -static const char driver_name[] = "qmi_wwan_f"; - -/* driver specific data */ -struct qmi_wwan_state { - struct usb_driver *subdriver; - atomic_t pmcount; - unsigned long unused; - struct usb_interface *control; - struct usb_interface *data; -}; - -/* default ethernet address used by the modem */ -static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3}; - -#if 1 -#define FIBOCOM_WWAN_QMAP 4 //MAX is 7 - -#if defined(FIBOCOM_WWAN_QMAP) -#define FIBOCOM_QMAP_MUX_ID 0x81 - -static uint __read_mostly qmap_mode = 0; -module_param( qmap_mode, uint, S_IRUGO); -module_param_named( rx_qmap, qmap_mode, uint, S_IRUGO ); -#endif - -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -#define FIBOCOM_BRIDGE_MODE -#endif - -#ifdef FIBOCOM_BRIDGE_MODE -static uint __read_mostly bridge_mode = 0/*|BIT(1)*/; -module_param( bridge_mode, uint, S_IRUGO ); -#endif - -#if defined(FIBOCOM_WWAN_QMAP) -#define FIBOCOM_UL_DATA_AGG 1 - -#if defined(FIBOCOM_UL_DATA_AGG) -struct tx_agg_ctx { - /* QMIWDS_ADMIN_SET_DATA_FORMAT_RESP TLV_0x17 and TLV_0x18 */ - uint ul_data_aggregation_max_datagrams; //UplinkDataAggregationMaxDatagramsTlv - uint ul_data_aggregation_max_size; //UplinkDataAggregationMaxSizeTlv - uint dl_minimum_padding; //0x1A -}; -#endif - -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int qmap_mode; - unsigned int qmap_version; - unsigned int dl_minimum_padding; - char ifname[8][16]; - unsigned char mux_id[8]; -} RMNET_INFO; - -typedef struct sQmiWwanQmap -{ - struct usbnet *mpNetDev; - struct driver_info driver_info; - atomic_t refcount; - struct net_device *mpQmapNetDev[FIBOCOM_WWAN_QMAP]; - uint link_state; - uint qmap_mode; - uint qmap_size; - uint qmap_version; - struct sk_buff_head skb_chain; - -#if defined(FIBOCOM_UL_DATA_AGG) - struct tx_agg_ctx tx_ctx; - struct tasklet_struct txq; -#endif - -#ifdef FIBOCOM_BRIDGE_MODE - uint bridge_mode; - uint bridge_ipv4; - unsigned char bridge_mac[ETH_ALEN]; -#endif - uint use_rmnet_usb; - RMNET_INFO rmnet_info; -} sQmiWwanQmap; -//2021-03-19 willa.liu@fibocom.com changed begin for support mantis 0073129 -//#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) -#if LINUX_VERSION_CODE > KERNEL_VERSION(3,15,0) -//2021-03-19 willa.liu@fibocom.com changed end for support mantis 0073129 -#define MHI_NETDEV_STATUS64 -#endif -struct qmap_priv { - struct usbnet *dev; - struct net_device *real_dev; - struct net_device *self_dev; - u8 offset_id; - u8 mux_id; - u8 qmap_version; - u8 link_state; - -#if defined(MHI_NETDEV_STATUS64) - struct pcpu_sw_netstats __percpu *stats64; -#endif - - spinlock_t agg_lock; - struct sk_buff *agg_skb; - unsigned agg_count; - struct timespec64 agg_time; - struct hrtimer agg_hrtimer; - struct work_struct agg_wq; - -#ifdef FIBOCOM_BRIDGE_MODE - uint bridge_mode; - uint bridge_ipv4; - unsigned char bridge_mac[ETH_ALEN]; -#endif -}; - -struct qmap_hdr { - u8 cd_rsvd_pad; - u8 mux_id; - u16 pkt_len; -} __packed; - -enum rmnet_map_v5_header_type { - RMNET_MAP_HEADER_TYPE_UNKNOWN, - RMNET_MAP_HEADER_TYPE_COALESCING = 0x1, - RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2, - RMNET_MAP_HEADER_TYPE_ENUM_LENGTH -}; - -/* Main QMAP header */ -struct rmnet_map_header { - u8 pad_len:6; - u8 next_hdr:1; - u8 cd_bit:1; - u8 mux_id; - __be16 pkt_len; -} __aligned(1); - -/* QMAP v5 headers */ -struct rmnet_map_v5_csum_header { - u8 next_hdr:1; - u8 header_type:7; - u8 hw_reserved:7; - u8 csum_valid_required:1; - __be16 reserved; -} __aligned(1); - -#ifdef FIBOCOM_BRIDGE_MODE -static int is_qmap_netdev(const struct net_device *netdev); -#endif -#endif - -#ifdef FIBOCOM_BRIDGE_MODE -static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4) { - struct arphdr *parp; - u8 *arpptr, *sha; - u8 sip[4], tip[4], ipv4[4]; - struct sk_buff *reply = NULL; - - ipv4[0] = (bridge_ipv4 >> 24) & 0xFF; - ipv4[1] = (bridge_ipv4 >> 16) & 0xFF; - ipv4[2] = (bridge_ipv4 >> 8) & 0xFF; - ipv4[3] = (bridge_ipv4 >> 0) & 0xFF; - - parp = arp_hdr(skb); - - if (parp->ar_hrd == htons(ARPHRD_ETHER) && parp->ar_pro == htons(ETH_P_IP) - && parp->ar_op == htons(ARPOP_REQUEST) && parp->ar_hln == 6 && parp->ar_pln == 4) { - arpptr = (u8 *)parp + sizeof(struct arphdr); - sha = arpptr; - arpptr += net->addr_len; /* sha */ - memcpy(sip, arpptr, sizeof(sip)); - arpptr += sizeof(sip); - arpptr += net->addr_len; /* tha */ - memcpy(tip, arpptr, sizeof(tip)); - - pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d, ipv4=%d.%d.%d.%d\n", netdev_name(net), - sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3], ipv4[0], ipv4[1], ipv4[2], ipv4[3]); - //wwan0 sip = 10.151.137.255, tip=10.151.138.0, ipv4=10.151.137.255 - if (tip[0] == ipv4[0] && tip[1] == ipv4[1] && (tip[2]&0xFC) == (ipv4[2]&0xFC) && tip[3] != ipv4[3]) - reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), net, *((__be32 *)tip), sha, default_modem_addr, sha); - - if (reply) { - skb_reset_mac_header(reply); - __skb_pull(reply, skb_network_offset(reply)); - reply->ip_summed = CHECKSUM_UNNECESSARY; - reply->pkt_type = PACKET_HOST; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) - netif_rx_ni(reply); -#else - netif_rx(reply); -#endif - } - return 1; - } - - return 0; -} - -static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4, unsigned char *bridge_mac) { - struct ethhdr *ehdr; - const struct iphdr *iph; - - skb_reset_mac_header(skb); - ehdr = eth_hdr(skb); - - if (ehdr->h_proto == htons(ETH_P_ARP)) { - if (bridge_ipv4) - bridge_arp_reply(net, skb, bridge_ipv4); - return NULL; - } - - iph = ip_hdr(skb); - //DBG("iphdr: "); - //PrintHex((void *)iph, sizeof(struct iphdr)); - -// 1 0.000000000 0.0.0.0 255.255.255.255 DHCP 362 DHCP Request - Transaction ID 0xe7643ad7 - if (ehdr->h_proto == htons(ETH_P_IP) && iph->protocol == IPPROTO_UDP && iph->saddr == 0x00000000 && iph->daddr == 0xFFFFFFFF) { - //if (udp_hdr(skb)->dest == htons(67)) //DHCP Request - { - memcpy(bridge_mac, ehdr->h_source, ETH_ALEN); - pr_info("%s PC Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net), - bridge_mac[0], bridge_mac[1], bridge_mac[2], bridge_mac[3], bridge_mac[4], bridge_mac[5]); - } - } - - if (memcmp(ehdr->h_source, bridge_mac, ETH_ALEN)) { - return NULL; - } - - return skb; -} - -static void bridge_mode_rx_fixup(sQmiWwanQmap *pQmapDev, struct net_device *net, struct sk_buff *skb) { - uint bridge_mode = 0; - unsigned char *bridge_mac; - - if (pQmapDev->qmap_mode > 1 || pQmapDev->use_rmnet_usb == 1) { - struct qmap_priv *priv = netdev_priv(net); - bridge_mode = priv->bridge_mode; - bridge_mac = priv->bridge_mac; - } - else { - bridge_mode = pQmapDev->bridge_mode; - bridge_mac = pQmapDev->bridge_mac; - } - - if (bridge_mode) - memcpy(eth_hdr(skb)->h_dest, bridge_mac, ETH_ALEN); - else - memcpy(eth_hdr(skb)->h_dest, net->dev_addr, ETH_ALEN); -} -#endif - -#if defined(FIBOCOM_WWAN_QMAP) -static ssize_t qmap_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - return snprintf(buf, PAGE_SIZE, "%d\n", pQmapDev->qmap_mode); -} - -static DEVICE_ATTR(qmap_mode, S_IRUGO, qmap_mode_show, NULL); - -static ssize_t qmap_size_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - return snprintf(buf, PAGE_SIZE, "%u\n", pQmapDev->qmap_size); -} - -static DEVICE_ATTR(qmap_size, S_IRUGO, qmap_size_show, NULL); - -static ssize_t link_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - return snprintf(buf, PAGE_SIZE, "0x%x\n", pQmapDev->link_state); -} - -static ssize_t link_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *netdev = to_net_dev(dev); - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - unsigned link_state = 0; - unsigned old_link = pQmapDev->link_state; - uint offset_id = 0; - - link_state = simple_strtoul(buf, NULL, 0); - - if (pQmapDev->qmap_mode == 1) { - pQmapDev->link_state = !!link_state; - } - else if (pQmapDev->qmap_mode > 1) { - offset_id = ((link_state&0x7F) - 1); - - if (offset_id >= pQmapDev->qmap_mode) { - dev_info(dev, "%s offset_id is %d. but qmap_mode is %d\n", __func__, offset_id, pQmapDev->qmap_mode); - return count; - } - - if (link_state&0x80) - pQmapDev->link_state &= ~(1 << offset_id); - else - pQmapDev->link_state |= (1 << offset_id); - } - - if (old_link != pQmapDev->link_state) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[offset_id]; - - if (pQmapDev->link_state) { - netif_carrier_on(usbnetdev->net); - } else { - netif_carrier_off(usbnetdev->net); - } - - if (qmap_net && qmap_net != netdev) { - struct qmap_priv *priv = netdev_priv(qmap_net); - - priv->link_state = !!(pQmapDev->link_state & (1 << offset_id)); - if (priv->link_state) { - netif_carrier_on(qmap_net); - if (netif_queue_stopped(qmap_net) && !netif_queue_stopped(usbnetdev->net)) - netif_wake_queue(qmap_net); - } - else { - netif_carrier_off(qmap_net); - } - } - - dev_info(dev, "link_state 0x%x -> 0x%x\n", old_link, pQmapDev->link_state); - } - - return count; -} - -#ifdef FIBOCOM_BRIDGE_MODE -static ssize_t bridge_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *netdev = to_net_dev(dev); - uint old_mode = 0; - uint bridge_mode = simple_strtoul(buf, NULL, 0); - - if (netdev->type != ARPHRD_ETHER) { - return count; - } - - if (is_qmap_netdev(netdev)) { - struct qmap_priv *priv = netdev_priv(netdev); - old_mode = priv->bridge_mode; - priv->bridge_mode = bridge_mode; - } - else { - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - old_mode = pQmapDev->bridge_mode; - pQmapDev->bridge_mode = bridge_mode; - } - - if (old_mode != bridge_mode) { - dev_info(dev, "bridge_mode change to 0x%x\n", bridge_mode); - } - - return count; -} - -static ssize_t bridge_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - uint bridge_mode = 0; - - if (is_qmap_netdev(netdev)) { - struct qmap_priv *priv = netdev_priv(netdev); - bridge_mode = priv->bridge_mode; - } - else { - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - bridge_mode = pQmapDev->bridge_mode; - } - - return snprintf(buf, PAGE_SIZE, "%u\n", bridge_mode); -} - -static ssize_t bridge_ipv4_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *netdev = to_net_dev(dev); - unsigned int bridge_ipv4 = 0; - unsigned char ipv4[4]; - - if (is_qmap_netdev(netdev)) { - struct qmap_priv *priv = netdev_priv(netdev); - bridge_ipv4 = priv->bridge_ipv4; - } - else { - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - bridge_ipv4 = pQmapDev->bridge_ipv4; - } - - ipv4[0] = (bridge_ipv4 >> 24) & 0xFF; - ipv4[1] = (bridge_ipv4 >> 16) & 0xFF; - ipv4[2] = (bridge_ipv4 >> 8) & 0xFF; - ipv4[3] = (bridge_ipv4 >> 0) & 0xFF; - - return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3]); -} - -static ssize_t bridge_ipv4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *netdev = to_net_dev(dev); - - if (is_qmap_netdev(netdev)) { - struct qmap_priv *priv = netdev_priv(netdev); - priv->bridge_ipv4 = simple_strtoul(buf, NULL, 16); - } - else { - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - pQmapDev->bridge_ipv4 = simple_strtoul(buf, NULL, 16); - } - - return count; -} -#endif - -static DEVICE_ATTR(link_state, S_IWUSR | S_IRUGO, link_state_show, link_state_store); -#ifdef FIBOCOM_BRIDGE_MODE -static DEVICE_ATTR(bridge_mode, S_IWUSR | S_IRUGO, bridge_mode_show, bridge_mode_store); -static DEVICE_ATTR(bridge_ipv4, S_IWUSR | S_IRUGO, bridge_ipv4_show, bridge_ipv4_store); -#endif - -static struct attribute *qmi_wwan_sysfs_attrs[] = { - &dev_attr_link_state.attr, - &dev_attr_qmap_mode.attr, - &dev_attr_qmap_size.attr, -#ifdef FIBOCOM_BRIDGE_MODE - &dev_attr_bridge_mode.attr, - &dev_attr_bridge_ipv4.attr, -#endif - NULL, -}; - -static struct attribute_group qmi_wwan_sysfs_attr_group = { - .attrs = qmi_wwan_sysfs_attrs, -}; - -#ifdef FIBOCOM_BRIDGE_MODE -static struct attribute *qmi_qmap_sysfs_attrs[] = { - &dev_attr_bridge_mode.attr, - &dev_attr_bridge_ipv4.attr, - NULL, -}; - -static struct attribute_group qmi_qmap_sysfs_attr_group = { - .attrs = qmi_qmap_sysfs_attrs, -}; -#endif - -static int qmap_open(struct net_device *dev) -{ - struct qmap_priv *priv = netdev_priv(dev); - struct net_device *real_dev = priv->real_dev; - - if (!(priv->real_dev->flags & IFF_UP)) - return -ENETDOWN; - - if (netif_carrier_ok(real_dev) && priv->link_state) - netif_carrier_on(dev); - - if (netif_carrier_ok(dev)) { - if (netif_queue_stopped(dev) && !netif_queue_stopped(real_dev)) - netif_wake_queue(dev); - } - - return 0; -} - -static int qmap_stop(struct net_device *pNet) -{ - netif_carrier_off(pNet); - return 0; -} - -static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) { - struct qmap_hdr *qhdr; - int pad = 0; - - pad = skb->len%4; - if (pad) { - pad = 4 - pad; - if (skb_tailroom(skb) < pad) { - printk("skb_tailroom small!\n"); - pad = 0; - } - if (pad) - __skb_put(skb, pad); - } - - qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr)); - qhdr->cd_rsvd_pad = pad; - qhdr->mux_id = mux_id; - qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr)); - - return skb; -} - -static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) { - struct rmnet_map_header *map_header; - struct rmnet_map_v5_csum_header *ul_header; - u32 padding, map_datalen; - - map_datalen = skb->len; - padding = map_datalen%4; - if (padding) { - padding = 4 - padding; - if (skb_tailroom(skb) < padding) { - printk("skb_tailroom small!\n"); - padding = 0; - } - if (padding) - __skb_put(skb, padding); - } - - map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); - map_header->cd_bit = 0; - map_header->next_hdr = 1; - map_header->pad_len = padding; - map_header->mux_id = mux_id; - map_header->pkt_len = htons(map_datalen + padding); - - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - memset(ul_header, 0, sizeof(*ul_header)); - ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD; - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if 0 //TODO - skb->ip_summed = CHECKSUM_NONE; - /* Ask for checksum offloading */ - ul_header->csum_valid_required = 1; -#endif - } - - return skb; -} - -static void rmnet_vnd_update_rx_stats(struct net_device *net, - unsigned rx_packets, unsigned rx_bytes) { -#if defined(MHI_NETDEV_STATUS64) - struct qmap_priv *dev = netdev_priv(net); - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); - - u64_stats_update_begin(&stats64->syncp); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) - stats64->rx_packets += rx_packets; - stats64->rx_bytes += rx_bytes; -#else - u64_stats_add(&stats64->rx_packets, rx_packets); - u64_stats_add(&stats64->rx_bytes, rx_bytes); -#endif - u64_stats_update_end(&stats64->syncp); -#else - net->stats.rx_packets += rx_packets; - net->stats.rx_bytes += rx_bytes; -#endif -} - -static void rmnet_vnd_update_tx_stats(struct net_device *net, - unsigned tx_packets, unsigned tx_bytes) { -#if defined(MHI_NETDEV_STATUS64) - struct qmap_priv *dev = netdev_priv(net); - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); - - u64_stats_update_begin(&stats64->syncp); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) - stats64->tx_packets += tx_packets; - stats64->tx_bytes += tx_bytes; -#else - u64_stats_add(&stats64->tx_packets, tx_packets); - u64_stats_add(&stats64->tx_bytes, tx_bytes); -#endif - u64_stats_update_end(&stats64->syncp); -#else - net->stats.tx_packets += tx_packets; - net->stats.tx_bytes += tx_bytes; -#endif -} - -#if defined(MHI_NETDEV_STATUS64) -static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) -{ - struct qmap_priv *dev = netdev_priv(net); - unsigned int start; - int cpu; - struct rmnet_nss_cb *nss_cb; - - netdev_stats_to_stats64(stats, &net->stats); - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { // rmnet_nss.c:rmnet_nss_tx() will update rx stats - stats->rx_packets = 0; - stats->rx_bytes = 0; - } - - for_each_possible_cpu(cpu) { - struct pcpu_sw_netstats *stats64; - u64 rx_packets, rx_bytes; - u64 tx_packets, tx_bytes; - - stats64 = per_cpu_ptr(dev->stats64, cpu); - - do { - start = u64_stats_fetch_begin_irq(&stats64->syncp); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) - rx_packets = stats64->rx_packets; - rx_bytes = stats64->rx_bytes; - tx_packets = stats64->tx_packets; - tx_bytes = stats64->tx_bytes; -#else - rx_packets = u64_stats_read(&stats64->rx_packets); - rx_bytes = u64_stats_read(&stats64->rx_bytes); - tx_packets = u64_stats_read(&stats64->tx_packets); - tx_bytes = u64_stats_read(&stats64->tx_bytes); -#endif - } while (u64_stats_fetch_retry_irq(&stats64->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; - stats->tx_packets += tx_packets; - stats->tx_bytes += tx_bytes; - } - - return stats; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,10,0 )) //bc1f44709cf27fb2a5766cadafe7e2ad5e9cb221 -static void rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { - _rmnet_vnd_get_stats64(net, stats); -} -#else -static struct rtnl_link_stats64 *rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { - return _rmnet_vnd_get_stats64(net, stats); -} -#endif -#endif - -#if defined(FIBOCOM_UL_DATA_AGG) -static void rmnet_usb_tx_wake_queue(unsigned long data) { - sQmiWwanQmap *pQmapDev = (void *)data; - int i; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - if (qmap_net) { - if (netif_queue_stopped(qmap_net) && !netif_queue_stopped(pQmapDev->mpNetDev->net)) { - netif_wake_queue(qmap_net); - } - } - } -} - -static void rmnet_usb_tx_skb_destructor(struct sk_buff *skb) { - struct net_device *net = skb->dev; - struct usbnet * dev = netdev_priv( net ); - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - if (pQmapDev && pQmapDev->use_rmnet_usb) { - int i; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - - if (qmap_net) { - if (netif_queue_stopped(qmap_net)) { - tasklet_schedule(&pQmapDev->txq); - break; - } - } - } - } -} - -static int rmnet_usb_tx_agg_skip(struct sk_buff *skb, int offset) -{ - u8 *packet_start = skb->data + offset; - int ready2send = 0; - - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *ip4h = (struct iphdr *)(packet_start); - - if (ip4h->protocol == IPPROTO_TCP) { - const struct tcphdr *th = (const struct tcphdr *)(packet_start + sizeof(struct iphdr)); - if (th->psh) { - ready2send = 1; - } - } - else if (ip4h->protocol == IPPROTO_ICMP) - ready2send = 1; - - } else if (skb->protocol == htons(ETH_P_IPV6)) { - struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start); - - if (ip6h->nexthdr == NEXTHDR_TCP) { - const struct tcphdr *th = (const struct tcphdr *)(packet_start + sizeof(struct ipv6hdr)); - if (th->psh) { - ready2send = 1; - } - } else if (ip6h->nexthdr == NEXTHDR_ICMP) { - ready2send = 1; - } else if (ip6h->nexthdr == NEXTHDR_FRAGMENT) { - struct frag_hdr *frag; - - frag = (struct frag_hdr *)(packet_start - + sizeof(struct ipv6hdr)); - if (frag->nexthdr == IPPROTO_ICMPV6) - ready2send = 1; - } - } - - return ready2send; -} - -static void rmnet_usb_tx_agg_work(struct work_struct *work) -{ - struct qmap_priv *priv = - container_of(work, struct qmap_priv, agg_wq); - struct sk_buff *skb = NULL; - unsigned long flags; - - spin_lock_irqsave(&priv->agg_lock, flags); - if (likely(priv->agg_skb)) { - skb = priv->agg_skb; - priv->agg_skb = NULL; - priv->agg_count = 0; - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - ktime_get_ts64(&priv->agg_time); - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - - if (skb) { - int err = dev_queue_xmit(skb); - if (err != NET_XMIT_SUCCESS) { - priv->self_dev->stats.tx_errors++; - } - } -} - -static enum hrtimer_restart rmnet_usb_tx_agg_timer_cb(struct hrtimer *timer) -{ - struct qmap_priv *priv = - container_of(timer, struct qmap_priv, agg_hrtimer); - - schedule_work(&priv->agg_wq); - return HRTIMER_NORESTART; -} - -static long agg_time_limit __read_mostly = 1000000L; //reduce this time, can get better TPUT performance, but will increase USB interrupts -module_param(agg_time_limit, long, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(agg_time_limit, "Maximum time packets sit in the agg buf"); - -static long agg_bypass_time __read_mostly = 10000000L; -module_param(agg_bypass_time, long, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this"); - -static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) { - struct qmi_wwan_state *info = (void *)&priv->dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - struct tx_agg_ctx *ctx = &pQmapDev->tx_ctx; - int ready2send = 0; - int xmit_more = 0; - struct timespec64 diff, now; - struct sk_buff *agg_skb = NULL; - unsigned long flags; - int err; - struct net_device *pNet = priv->self_dev; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0) //6b16f9ee89b8d5709f24bc3ac89ae8b5452c0d7c -#if LINUX_VERSION_CODE > KERNEL_VERSION(3,16,0) - xmit_more = skb->xmit_more; -#endif -#else - xmit_more = netdev_xmit_more(); -#endif - - rmnet_vnd_update_tx_stats(pNet, 1, skb->len); - - if (ctx->ul_data_aggregation_max_datagrams == 1) { - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - if (!skb->destructor) - skb->destructor = rmnet_usb_tx_skb_destructor; - err = dev_queue_xmit(skb); - if (err != NET_XMIT_SUCCESS) - pNet->stats.tx_errors++; - return NET_XMIT_SUCCESS; - } - -new_packet: - spin_lock_irqsave(&priv->agg_lock, flags); - agg_skb = NULL; - ready2send = 0; - ktime_get_ts64(&now); - diff = timespec64_sub(now, priv->agg_time); - - if (priv->agg_skb) { - if ((priv->agg_skb->len + skb->len) < ctx->ul_data_aggregation_max_size) { - memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len); - priv->agg_count++; - - if (diff.tv_sec > 0 || diff.tv_nsec > agg_time_limit) { - ready2send = 1; - } - else if (priv->agg_count == ctx->ul_data_aggregation_max_datagrams) { - ready2send = 1; - } - else if (xmit_more == 0) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data; - size_t offset = sizeof(struct rmnet_map_header); - if (map_header->next_hdr) - offset += sizeof(struct rmnet_map_v5_csum_header); - - ready2send = rmnet_usb_tx_agg_skip(skb, offset); - } - - dev_kfree_skb_any(skb); - skb = NULL; - } - else { - ready2send = 1; - } - - if (ready2send) { - agg_skb = priv->agg_skb; - priv->agg_skb = NULL; - priv->agg_count = 0; - } - } - else if (skb) { - if (diff.tv_sec > 0 || diff.tv_nsec > agg_bypass_time) { - ready2send = 1; - } - else if (xmit_more == 0) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data; - size_t offset = sizeof(struct rmnet_map_header); - if (map_header->next_hdr) - offset += sizeof(struct rmnet_map_v5_csum_header); - - ready2send = rmnet_usb_tx_agg_skip(skb, offset); - } - - if (ready2send == 0) { - priv->agg_skb = alloc_skb(ctx->ul_data_aggregation_max_size, GFP_ATOMIC); - if (priv->agg_skb) { - memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len); - priv->agg_count++; - dev_kfree_skb_any(skb); - skb = NULL; - } - else { - ready2send = 1; - } - } - - if (ready2send) { - agg_skb = skb; - skb = NULL; - } - } - - if (ready2send) { - priv->agg_time = now; - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - - if (agg_skb) { - agg_skb->protocol = htons(ETH_P_MAP); - agg_skb->dev = priv->real_dev; - if (!agg_skb->destructor) - agg_skb->destructor = rmnet_usb_tx_skb_destructor; - err = dev_queue_xmit(agg_skb); - if (err != NET_XMIT_SUCCESS) { - pNet->stats.tx_errors++; - } - } - - if (skb) { - goto new_packet; - } - - if (priv->agg_skb) { - if (!hrtimer_is_queued(&priv->agg_hrtimer)) - hrtimer_start(&priv->agg_hrtimer, ns_to_ktime(NSEC_PER_MSEC * 2), HRTIMER_MODE_REL); - } - - return NET_XMIT_SUCCESS; -} -#endif - -static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, - struct net_device *pNet) -{ - int err; - struct qmap_priv *priv = netdev_priv(pNet); - - if (netif_queue_stopped(priv->real_dev)) { - netif_stop_queue(pNet); - return NETDEV_TX_BUSY; - } - - //printk("%s 1 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - if (pNet->type == ARPHRD_ETHER) { - skb_reset_mac_header(skb); - -#ifdef FIBOCOM_BRIDGE_MODE - if (priv->bridge_mode && bridge_mode_tx_fixup(pNet, skb, priv->bridge_ipv4, priv->bridge_mac) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } -#endif - - if (skb_pull(skb, ETH_HLEN) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - //printk("%s 2 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (priv->qmap_version == 5) { - add_qhdr(skb, priv->mux_id); - } - else if (priv->qmap_version == 9) { - add_qhdr_v5(skb, priv->mux_id); - } - else { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - -#if 0 - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - err = dev_queue_xmit(skb); - - if (err == NET_XMIT_SUCCESS) { - rmnet_vnd_update_tx_stats(pNet, 1, skb->len); - } else { - pNet->stats.tx_errors++; - } -#else - err = rmnet_usb_tx_agg(skb, priv); -#endif - - return err; -} - -static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu) -{ - if (new_mtu < 0 || new_mtu > 1500) - return -EINVAL; - - rmnet_dev->mtu = new_mtu; - return 0; -} - -/* drivers may override default ethtool_ops in their bind() routine */ -static const struct ethtool_ops rmnet_vnd_ethtool_ops = { - .get_link = ethtool_op_get_link, -}; - -static int qmap_start_xmit(struct sk_buff *skb, struct net_device *pNet) -{ - int err; - struct qmap_priv *priv = netdev_priv(pNet); - - //printk("%s 1 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - if (pNet->type == ARPHRD_ETHER) { - skb_reset_mac_header(skb); - -#ifdef FIBOCOM_BRIDGE_MODE - if (priv->bridge_mode && bridge_mode_tx_fixup(pNet, skb, priv->bridge_ipv4, priv->bridge_mac) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } -#endif - - if (skb_pull(skb, ETH_HLEN) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - - - add_qhdr(skb, FIBOCOM_QMAP_MUX_ID + priv->offset_id); - - skb->dev = priv->real_dev; - err = dev_queue_xmit(skb); - if (err == NET_XMIT_SUCCESS) { - pNet->stats.tx_packets++; - pNet->stats.tx_bytes += skb->len; - } else { - pNet->stats.tx_errors++; - } - - return err; -} - -static const struct net_device_ops qmap_netdev_ops = { - .ndo_open = qmap_open, - .ndo_stop = qmap_stop, - .ndo_start_xmit = qmap_start_xmit, -}; - -static const struct net_device_ops rmnet_vnd_ops = { - .ndo_open = qmap_open, - .ndo_stop = qmap_stop, - .ndo_start_xmit = rmnet_vnd_start_xmit, - .ndo_change_mtu = rmnet_vnd_change_mtu, -#if defined(MHI_NETDEV_STATUS64) - .ndo_get_stats64 = rmnet_vnd_get_stats64, -#endif -}; - -static void rmnet_usb_vnd_setup(struct net_device *rmnet_dev) -{ - rmnet_dev->needed_headroom = 16; - - /* Raw IP mode */ - rmnet_dev->header_ops = NULL; /* No header */ - rmnet_dev->type = ARPHRD_RAWIP; - rmnet_dev->hard_header_len = 0; - rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); -} - -static rx_handler_result_t rmnet_usb_rx_priv_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_nss_cb *nss_cb; - - if (!skb) - return RX_HANDLER_CONSUMED; - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - /* Check this so that we dont loop around netif_receive_skb */ - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - return RX_HANDLER_PASS; - } - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { - nss_cb->nss_tx(skb); - return RX_HANDLER_CONSUMED; - } - - return RX_HANDLER_PASS; -} - -static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id) -{ - struct net_device *real_dev = pDev->mpNetDev->net; - struct net_device *qmap_net; - struct qmap_priv *priv; - int err; - struct rmnet_nss_cb *nss_cb; - - qmap_net = alloc_etherdev(sizeof(*priv)); - if (!qmap_net) - return -ENOBUFS; - - SET_NETDEV_DEV(qmap_net, &real_dev->dev); - priv = netdev_priv(qmap_net); - priv->offset_id = offset_id; - priv->real_dev = real_dev; - priv->self_dev = qmap_net; - priv->dev = pDev->mpNetDev; - priv->qmap_version = pDev->qmap_version; - priv->mux_id = FIBOCOM_QMAP_MUX_ID + offset_id; - sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1); - qmap_net->netdev_ops = &qmap_netdev_ops; - memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); - -#ifdef FIBOCOM_BRIDGE_MODE - priv->bridge_mode = !!(pDev->bridge_mode & BIT(offset_id)); - qmap_net->sysfs_groups[0] = &qmi_qmap_sysfs_attr_group; -#endif - - priv->agg_skb = NULL; - priv->agg_count = 0; - hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - priv->agg_hrtimer.function = rmnet_usb_tx_agg_timer_cb; - INIT_WORK(&priv->agg_wq, rmnet_usb_tx_agg_work); - ktime_get_ts64(&priv->agg_time); - spin_lock_init(&priv->agg_lock); - - if (pDev->use_rmnet_usb) { - qmap_net->ethtool_ops = &rmnet_vnd_ethtool_ops; - qmap_net->netdev_ops = &rmnet_vnd_ops; -#if defined(MHI_NETDEV_STATUS64) - priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!priv->stats64) { - err = -ENOBUFS; - goto out_free_newdev; - } -#endif - } - - nss_cb = rcu_dereference(rmnet_nss_callbacks); -#ifdef FIBOCOM_BRIDGE_MODE - if(nss_cb && !priv->bridge_mode) { -#else - if (nss_cb) { -#endif - rmnet_usb_vnd_setup(qmap_net); - } - - err = register_netdev(qmap_net); - dev_info(&real_dev->dev, "%s(%s)=%d\n", __func__, qmap_net->name, err); - if (err < 0) - goto out_free_newdev; - netif_device_attach (qmap_net); - netif_carrier_off(qmap_net); - - nss_cb = rcu_dereference(rmnet_nss_callbacks); -#ifdef FIBOCOM_BRIDGE_MODE - if(nss_cb && !priv->bridge_mode) { -#else - if (nss_cb) { -#endif - int rc = nss_cb->nss_create(qmap_net); - if (rc) { - /* Log, but don't fail the device creation */ - netdev_err(qmap_net, "Device will not use NSS path: %d\n", rc); - } else { - netdev_info(qmap_net, "NSS context created\n"); - rtnl_lock(); - netdev_rx_handler_register(qmap_net, rmnet_usb_rx_priv_handler, NULL); - rtnl_unlock(); - } - } - - if (pDev->use_rmnet_usb) { - strcpy(pDev->rmnet_info.ifname[offset_id], qmap_net->name); - pDev->rmnet_info.mux_id[offset_id] = priv->mux_id; - } - - pDev->mpQmapNetDev[offset_id] = qmap_net; - qmap_net->flags |= IFF_NOARP; - qmap_net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - - dev_info(&real_dev->dev, "%s %s\n", __func__, qmap_net->name); - - return 0; - -out_free_newdev: - free_netdev(qmap_net); - return err; -} - -static void qmap_unregister_device(sQmiWwanQmap * pDev, u8 offset_id) { - struct net_device *qmap_net = pDev->mpQmapNetDev[offset_id]; - - if (qmap_net != NULL && qmap_net != pDev->mpNetDev->net) { - struct rmnet_nss_cb *nss_cb; - struct qmap_priv *priv = netdev_priv(qmap_net); - unsigned long flags; - - pr_info("qmap_unregister_device(%s)\n", qmap_net->name); - pDev->mpQmapNetDev[offset_id] = NULL; - netif_carrier_off( qmap_net ); - netif_stop_queue( qmap_net ); - - hrtimer_cancel(&priv->agg_hrtimer); - cancel_work_sync(&priv->agg_wq); - spin_lock_irqsave(&priv->agg_lock, flags); - if (priv->agg_skb) { - kfree_skb(priv->agg_skb); - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - nss_cb = rcu_dereference(rmnet_nss_callbacks); - -#ifdef FIBOCOM_BRIDGE_MODE - if(nss_cb && !priv->bridge_mode) { -#else - if (nss_cb) { -#endif - rtnl_lock(); - netdev_rx_handler_unregister(qmap_net); - rtnl_unlock(); - nss_cb->nss_free(qmap_net); - } - -#if defined(MHI_NETDEV_STATUS64) - free_percpu(priv->stats64); -#endif - unregister_netdev (qmap_net); - free_netdev(qmap_net); - } -} - -#if 1//def CONFIG_ANDROID -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int MuxId; - unsigned int ul_data_aggregation_max_datagrams; //0x17 - unsigned int ul_data_aggregation_max_size ;//0x18 - unsigned int dl_minimum_padding; //0x1A -} QMAP_SETTING; - -int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) { - struct net_device *netdev = to_net_dev(dev); - struct usbnet * usbnetdev = netdev_priv( netdev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - if (qmap_settings->size != size) { - dev_err(dev, "ERROR: qmap_settings.size donot match!\n"); - return -EOPNOTSUPP; - } - -#ifdef FIBOCOM_UL_DATA_AGG - netif_tx_lock_bh(netdev); - if (pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams == 1 && qmap_settings->ul_data_aggregation_max_datagrams > 1) { - pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams = qmap_settings->ul_data_aggregation_max_datagrams; - pQmapDev->tx_ctx.ul_data_aggregation_max_size = qmap_settings->ul_data_aggregation_max_size; - pQmapDev->tx_ctx.dl_minimum_padding = qmap_settings->dl_minimum_padding; - dev_info(dev, "ul_data_aggregation_max_datagrams=%d, ul_data_aggregation_max_size=%d, dl_minimum_padding=%d\n", - pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams, - pQmapDev->tx_ctx.ul_data_aggregation_max_size, - pQmapDev->tx_ctx.dl_minimum_padding); - } - netif_tx_unlock_bh(netdev); - return 0; -#endif - - return -EOPNOTSUPP; -} - -static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct usbnet * usbnetdev = netdev_priv( dev ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - int rc = -EOPNOTSUPP; - uint link_state = 0; - QMAP_SETTING qmap_settings = {0}; - - switch (cmd) { - case 0x89F1: //SIOCDEVPRIVATE - rc = copy_from_user(&link_state, ifr->ifr_ifru.ifru_data, sizeof(link_state)); - if (!rc) { - char buf[32]; - snprintf(buf, sizeof(buf), "%u", link_state); - link_state_store(&dev->dev, NULL, buf, strlen(buf)); - } - break; - - case 0x89F2: //SIOCDEVPRIVATE - rc = copy_from_user(&qmap_settings, ifr->ifr_ifru.ifru_data, sizeof(qmap_settings)); - if (!rc) { - rc = qma_setting_store(&dev->dev, &qmap_settings, sizeof(qmap_settings)); - } - break; - - case 0x89F3: //SIOCDEVPRIVATE - if (pQmapDev->use_rmnet_usb) { - uint i; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - - if (!qmap_net) - break; - - strcpy(pQmapDev->rmnet_info.ifname[i], qmap_net->name); - } - rc = copy_to_user(ifr->ifr_ifru.ifru_data, &pQmapDev->rmnet_info, sizeof(pQmapDev->rmnet_info)); - } - break; - - default: - break; - } - - return rc; -} -#endif - -#ifdef FIBOCOM_BRIDGE_MODE -static int is_qmap_netdev(const struct net_device *netdev) { - return netdev->netdev_ops == &qmap_netdev_ops || netdev->netdev_ops == &rmnet_vnd_ops; -} -#endif -#endif - -static struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { - if ((dev->driver_info->flags & FLAG_NOARP) == 0) - return skb; - - // Skip Ethernet header from message - if (dev->net->hard_header_len == 0) - return skb; - else - skb_reset_mac_header(skb); - -#ifdef FIBOCOM_BRIDGE_MODE -{ - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - if (pQmapDev->bridge_mode && bridge_mode_tx_fixup(dev->net, skb, pQmapDev->bridge_ipv4, pQmapDev->bridge_mac) == NULL) { - dev_kfree_skb_any (skb); - return NULL; - } -} -#endif - - if (skb_pull(skb, ETH_HLEN)) { - return skb; - } else { - dev_err(&dev->intf->dev, "Packet Dropped "); - } - - // Filter the packet out, release it - dev_kfree_skb_any(skb); - return NULL; -} -#endif - -/* Make up an ethernet header if the packet doesn't have one. - * - * A firmware bug common among several devices cause them to send raw - * IP packets under some circumstances. There is no way for the - * driver/host to know when this will happen. And even when the bug - * hits, some packets will still arrive with an intact header. - * - * The supported devices are only capably of sending IPv4, IPv6 and - * ARP packets on a point-to-point link. Any packet with an ethernet - * header will have either our address or a broadcast/multicast - * address as destination. ARP packets will always have a header. - * - * This means that this function will reliably add the appropriate - * header if necessary, provided our hardware address does not start - * with 4 or 6. - * - * Another common firmware bug results in all packets being addressed - * to 00:a0:c6:00:00:00 despite the host address being different. - * This function will also fixup such packets. - */ -static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - __be16 proto; - - /* This check is no longer done by usbnet */ - if (skb->len < dev->net->hard_header_len) - return 0; - - switch (skb->data[0] & 0xf0) { - case 0x40: - proto = htons(ETH_P_IP); - break; - case 0x60: - proto = htons(ETH_P_IPV6); - break; - case 0x00: - if (is_multicast_ether_addr(skb->data)) - return 1; - /* possibly bogus destination - rewrite just in case */ - skb_reset_mac_header(skb); - goto fix_dest; - default: - /* pass along other packets without modifications */ - return 1; - } - if (skb_headroom(skb) < ETH_HLEN) - return 0; - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - eth_hdr(skb)->h_proto = proto; - memset(eth_hdr(skb)->h_source, 0, ETH_ALEN); -#if 1 //Added by Fibocom - //some kernel will drop ethernet packet which's souce mac is all zero - memcpy(eth_hdr(skb)->h_source, default_modem_addr, ETH_ALEN); -#endif - -fix_dest: -#ifdef FIBOCOM_BRIDGE_MODE -{ - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - bridge_mode_rx_fixup(pQmapDev, dev->net, skb); -} -#else - memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); -#endif - - return 1; -} - -#if defined(FIBOCOM_WWAN_QMAP) -static struct sk_buff *qmap_qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - struct qmap_hdr *qhdr; - - if (unlikely(pQmapDev == NULL)) { - goto drop_skb; - } else if (unlikely(pQmapDev->qmap_mode && !pQmapDev->link_state)) { - dev_dbg(&dev->net->dev, "link_state 0x%x, drop skb, len = %u\n", pQmapDev->link_state, skb->len); - goto drop_skb; - } else if (pQmapDev->qmap_mode == 0) { - skb = qmi_wwan_tx_fixup(dev, skb, flags); - } - else if (pQmapDev->qmap_mode > 1) { - if (likely(skb)) { - qhdr = (struct qmap_hdr *)skb->data; - if ((qhdr->mux_id&0xF0) != 0x80 || ((be16_to_cpu(qhdr->pkt_len) + sizeof(struct qmap_hdr)) != skb->len)) { - goto drop_skb; - } - } - } - else { - if (likely(skb)) { - skb = qmi_wwan_tx_fixup(dev, skb, flags); - - if (skb) { - add_qhdr(skb, FIBOCOM_QMAP_MUX_ID); - } - else { - return NULL; - } - } - } - - if (skb && (dev->driver_info->flags&FLAG_MULTI_PACKET)) { - usbnet_set_skb_tx_stats(skb, 1, 0); - } - - - return skb; -drop_skb: - dev_kfree_skb_any (skb); - return NULL; -} - -static int qmap_qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) -{ - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - unsigned headroom = 0; - const unsigned need_headroot = ETH_HLEN; - struct sk_buff *qmap_skb; - - if (pQmapDev->qmap_mode == 0) - return qmi_wwan_rx_fixup(dev, skb_in); - - headroom = skb_headroom(skb_in); - - while (skb_in->len > sizeof(struct qmap_hdr)) { - struct qmap_hdr *qhdr = (struct qmap_hdr *)skb_in->data; - struct net_device *qmap_net; - int pkt_len = be16_to_cpu(qhdr->pkt_len); - int skb_len; - __be16 protocol; - int mux_id; - - skb_len = pkt_len - (qhdr->cd_rsvd_pad&0x3F); - if (skb_len > 1500) { - dev_info(&dev->net->dev, "drop skb_len=%x larger than 1500\n", skb_len); - goto error_pkt; - } - - if (skb_in->len < (pkt_len + sizeof(struct qmap_hdr))) { - dev_info(&dev->net->dev, "drop qmap unknow pkt, len=%d, pkt_len=%d\n", skb_in->len, pkt_len); - goto error_pkt; - } - - if (qhdr->cd_rsvd_pad & 0x80) { - dev_info(&dev->net->dev, "skip qmap command packet %x\n", qhdr->cd_rsvd_pad); - goto skip_pkt; - } - - switch (skb_in->data[sizeof(struct qmap_hdr)] & 0xf0) { - case 0x40: - protocol = htons(ETH_P_IP); - break; - case 0x60: - protocol = htons(ETH_P_IPV6); - break; - default: - dev_info(&dev->net->dev, "unknow skb->protocol %02x\n", skb_in->data[sizeof(struct qmap_hdr)]); - goto error_pkt; - } - - mux_id = qhdr->mux_id - FIBOCOM_QMAP_MUX_ID; - if (mux_id >= pQmapDev->qmap_mode) { - dev_info(&dev->net->dev, "drop qmap unknow mux_id %x\n", qhdr->mux_id); - goto error_pkt; - } - - qmap_net = pQmapDev->mpQmapNetDev[mux_id]; - - if (qmap_net == NULL) { - dev_info(&dev->net->dev, "drop qmap unknow mux_id %x\n", qhdr->mux_id); - goto skip_pkt; - } - - if (headroom >= need_headroot) { - qmap_skb = skb_clone(skb_in, GFP_ATOMIC); - if (qmap_skb) { - qmap_skb->dev = qmap_net; - skb_pull(qmap_skb, sizeof(struct qmap_hdr)); - skb_trim(qmap_skb, skb_len); - } - headroom = (qhdr->cd_rsvd_pad&0x3F); - } - else { - qmap_skb = netdev_alloc_skb(qmap_net, need_headroot + skb_len); - if (qmap_skb) { - skb_reserve(qmap_skb, need_headroot); - skb_put(qmap_skb, skb_len); - memcpy(qmap_skb->data, skb_in->data + sizeof(struct qmap_hdr), skb_len); - } - headroom = pkt_len; - } - - if (qmap_skb == NULL) { - dev_info(&dev->net->dev, "fail to alloc skb, pkt_len = %d\n", skb_len); - return 0; - } - - skb_push(qmap_skb, ETH_HLEN); - skb_reset_mac_header(qmap_skb); - memcpy(eth_hdr(qmap_skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(qmap_skb)->h_dest, qmap_net->dev_addr, ETH_ALEN); - eth_hdr(qmap_skb)->h_proto = protocol; -#ifdef FIBOCOM_BRIDGE_MODE - bridge_mode_rx_fixup(pQmapDev, qmap_net, qmap_skb); -#endif - - if (qmap_net != dev->net) { - qmap_net->stats.rx_packets++; - qmap_net->stats.rx_bytes += qmap_skb->len; - } - - skb_queue_tail(&pQmapDev->skb_chain, qmap_skb); - -skip_pkt: - skb_pull(skb_in, pkt_len + sizeof(struct qmap_hdr)); - } - - while ((qmap_skb = skb_dequeue (&pQmapDev->skb_chain))) { - if (qmap_skb->dev != dev->net) { - qmap_skb->protocol = eth_type_trans (qmap_skb, qmap_skb->dev); - netif_rx(qmap_skb); - } - else { - qmap_skb->protocol = 0; - usbnet_skb_return(dev, qmap_skb); - } - } - -error_pkt: - return 0; -} -#endif - -/* very simplistic detection of IPv4 or IPv6 headers */ -static bool possibly_iphdr(const char *data) -{ - return (data[0] & 0xd0) == 0x40; -} - -/* disallow addresses which may be confused with IP headers */ -static int qmi_wwan_mac_addr(struct net_device *dev, void *p) -{ - int ret; - struct sockaddr *addr = p; - - ret = eth_prepare_mac_addr_change(dev, p); - if (ret < 0) - return ret; - if (possibly_iphdr(addr->sa_data)) - return -EADDRNOTAVAIL; - eth_commit_mac_addr_change(dev, p); - return 0; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,10,0 )) //bc1f44709cf27fb2a5766cadafe7e2ad5e9cb221 -static void (*_usbnet_get_stats64)(struct net_device *net, struct rtnl_link_stats64 *stats); - -static void qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { - if (_usbnet_get_stats64) ////c8b5d129ee293bcf972e7279ac996bb8a138505c - return _usbnet_get_stats64(net, stats); - - netdev_stats_to_stats64(stats, &net->stats); -} -#else -static struct rtnl_link_stats64 * (*_usbnet_get_stats64)(struct net_device *net, struct rtnl_link_stats64 *stats); - -static struct rtnl_link_stats64 * qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { - if (_usbnet_get_stats64) - return _usbnet_get_stats64(net, stats); - - netdev_stats_to_stats64(stats, &net->stats); - return stats; -} -#endif - -static netdev_tx_t qmi_wwan_start_xmit (struct sk_buff *skb, - struct net_device *net) -{ - struct usbnet * usbnetdev = netdev_priv( net ); - struct qmi_wwan_state *info = (void *)&usbnetdev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - int retval; - - retval = usbnet_start_xmit(skb, net); - - if (netif_queue_stopped(net) && pQmapDev && pQmapDev->use_rmnet_usb) { - int i; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - if (qmap_net) { - netif_stop_queue(qmap_net); - } - } - } - - return retval; -} - -static const struct net_device_ops qmi_wwan_netdev_ops = { - .ndo_open = usbnet_open, - .ndo_stop = usbnet_stop, - .ndo_start_xmit = qmi_wwan_start_xmit, - .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_change_mtu = usbnet_change_mtu, - .ndo_get_stats64 = qmi_wwan_get_stats64, - .ndo_set_mac_address = qmi_wwan_mac_addr, - .ndo_validate_addr = eth_validate_addr, -#if defined(FIBOCOM_WWAN_QMAP)// && defined(CONFIG_ANDROID) - .ndo_do_ioctl = qmap_ndo_do_ioctl, -#endif -}; - -static void ql_net_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) -{ - /* Inherit standard device info */ - usbnet_get_drvinfo(net, info); - strlcpy(info->driver, driver_name, sizeof(info->driver)); - strlcpy(info->version, VERSION_NUMBER, sizeof(info->version)); -} - -static struct ethtool_ops ql_net_ethtool_ops; - -/* using a counter to merge subdriver requests with our own into a - * combined state - */ -static int qmi_wwan_manage_power(struct usbnet *dev, int on) -{ - struct qmi_wwan_state *info = (void *)&dev->data; - int rv; - - dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, - atomic_read(&info->pmcount), on); - - if ((on && atomic_add_return(1, &info->pmcount) == 1) || - (!on && atomic_dec_and_test(&info->pmcount))) { - /* need autopm_get/put here to ensure the usbcore sees - * the new value - */ - rv = usb_autopm_get_interface(dev->intf); - dev->intf->needs_remote_wakeup = on; - if (!rv) - usb_autopm_put_interface(dev->intf); - } - return 0; -} - -static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on) -{ - struct usbnet *dev = usb_get_intfdata(intf); - - /* can be called while disconnecting */ - if (!dev) - return 0; - return qmi_wwan_manage_power(dev, on); -} - -/* collect all three endpoints and register subdriver */ -static int qmi_wwan_register_subdriver(struct usbnet *dev) -{ - int rv; - struct usb_driver *subdriver = NULL; - struct qmi_wwan_state *info = (void *)&dev->data; - - /* collect bulk endpoints */ - rv = usbnet_get_endpoints(dev, info->data); - if (rv < 0) - goto err; - - /* update status endpoint if separate control interface */ - if (info->control != info->data) - dev->status = &info->control->cur_altsetting->endpoint[0]; - - /* require interrupt endpoint for subdriver */ - if (!dev->status) { - rv = -EINVAL; - goto err; - } - - /* for subdriver power management */ - atomic_set(&info->pmcount, 0); - - /* register subdriver */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,12,0 )) //cac6fb015f719104e60b1c68c15ca5b734f57b9c - subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, - 4096, WWAN_PORT_QMI, &qmi_wwan_cdc_wdm_manage_power); -#else - subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc, - 4096, &qmi_wwan_cdc_wdm_manage_power); - -#endif - if (IS_ERR(subdriver)) { - dev_err(&info->control->dev, "subdriver registration failed\n"); - rv = PTR_ERR(subdriver); - goto err; - } - - /* prevent usbnet from using status endpoint */ - dev->status = NULL; - - /* save subdriver struct for suspend/resume wrappers */ - info->subdriver = subdriver; - -err: - return rv; -} - -static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int status = -1; - struct usb_driver *driver = driver_of(intf); - struct qmi_wwan_state *info = (void *)&dev->data; - - BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < - sizeof(struct qmi_wwan_state))); - - /* set up initial state */ - info->control = intf; - info->data = intf; - - status = qmi_wwan_register_subdriver(dev); - if (status < 0 && info->control != info->data) { - usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver, info->data); - } - - /* Never use the same address on both ends of the link, even - * if the buggy firmware told us to. - */ - if (ether_addr_equal(dev->net->dev_addr, default_modem_addr)) - eth_hw_addr_random(dev->net); - - /* make MAC addr easily distinguishable from an IP header */ - if (possibly_iphdr(dev->net->dev_addr)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) - dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */ - dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */ -#else - u8 addr = dev->net->dev_addr[0]; - - addr |= 0x02; /* set local assignment bit */ - addr &= 0xbf; /* clear "IP" bit */ - dev_addr_mod(dev->net, 0, &addr, 1); -#endif - } - if (!_usbnet_get_stats64) - _usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64; - dev->net->netdev_ops = &qmi_wwan_netdev_ops; - - ql_net_ethtool_ops = *dev->net->ethtool_ops; - ql_net_ethtool_ops.get_drvinfo = ql_net_get_drvinfo; - dev->net->ethtool_ops = &ql_net_ethtool_ops; - -#if 1 //Added by Fibocom - if (dev->driver_info->flags & FLAG_NOARP) { - int ret; - char buf[32] = "Module"; - - ret = usb_string(dev->udev, dev->udev->descriptor.iProduct, buf, sizeof(buf)); - if (ret > 0) { - buf[ret] = '\0'; - } - - dev_err(&intf->dev, "Fibocom %s work on RawIP mode\n", buf); - dev->net->flags |= IFF_NOARP; - dev->net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - - usb_control_msg( - interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), - 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE - 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - 1, //active CDC DTR - intf->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 100); - } - - dev->rx_urb_size = ETH_DATA_LEN + ETH_HLEN + 6; - -#if defined(FIBOCOM_WWAN_QMAP) - if (qmap_mode > FIBOCOM_WWAN_QMAP) - qmap_mode = FIBOCOM_WWAN_QMAP; - - if (!status) - { - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)kzalloc(sizeof(sQmiWwanQmap), GFP_KERNEL); - - if (pQmapDev == NULL) - return -ENODEV; - -#ifdef FIBOCOM_BRIDGE_MODE - pQmapDev->bridge_mode = bridge_mode; -#endif - pQmapDev->mpNetDev = dev; - pQmapDev->link_state = 1; - - dev->net->features |= (NETIF_F_VLAN_CHALLENGED); - - skb_queue_head_init(&pQmapDev->skb_chain); - - if (dev->driver_info->flags & FLAG_NOARP) - { - int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct); - int lte_a = (idProduct == 0x0104 || idProduct == 0x0109 || idProduct == 0x0113 || idProduct == 0x1000 || idProduct == 0x1001); - - pQmapDev->qmap_mode = qmap_mode; - if (lte_a || dev->udev->speed >= USB_SPEED_SUPER) { - if (pQmapDev->qmap_mode == 0) { - pQmapDev->qmap_mode = 1; - if(qmap_mode == 0) - qmap_mode = 1; - } - } - - if (pQmapDev->qmap_mode) { - pQmapDev->qmap_version = 5; - pQmapDev->qmap_size = (dev->udev->speed >= USB_SPEED_SUPER) ? 16*1024 : 4*1024; -/* - switch (idProduct) { - case 0x0104: - pQmapDev->qmap_version = 9; - pQmapDev->qmap_size = 31*1024; - break; - default: - break; - } -*/ - dev->rx_urb_size = pQmapDev->qmap_size; - //for these modules, if send pakcet before qmi_start_network, or cause host PC crash, or cause modules crash - if (lte_a || dev->udev->speed >= USB_SPEED_SUPER) - pQmapDev->link_state = 0; - } - -#if defined(FIBOCOM_UL_DATA_AGG) - if (pQmapDev->qmap_mode) { - struct tx_agg_ctx *ctx = &pQmapDev->tx_ctx; - ctx->ul_data_aggregation_max_datagrams = 1; - ctx->ul_data_aggregation_max_size = 1500; - } -#endif - - if (pQmapDev->qmap_mode == 0) { - pQmapDev->driver_info = *dev->driver_info; - pQmapDev->driver_info.flags &= ~(FLAG_MULTI_PACKET); //see usbnet.c rx_process() - dev->driver_info = &pQmapDev->driver_info; - } - } - - info->unused = (unsigned long)pQmapDev; - dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group; - - dev_info(&intf->dev, "rx_urb_size = %zd\n", dev->rx_urb_size); - } -#endif -#endif - - return status; -} - -static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf) -{ - struct qmi_wwan_state *info = (void *)&dev->data; - struct usb_driver *driver = driver_of(intf); - struct usb_interface *other; - - if (dev->udev && dev->udev->state == USB_STATE_CONFIGURED) { - usb_control_msg( - interface_to_usbdev(intf), - usb_sndctrlpipe(interface_to_usbdev(intf), 0), - 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE - 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - 0, //deactive CDC DTR - intf->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 100); - } - - if (info->subdriver && info->subdriver->disconnect) - info->subdriver->disconnect(info->control); - - /* allow user to unbind using either control or data */ - if (intf == info->control) - other = info->data; - else - other = info->control; - - /* only if not shared */ - if (other && intf != other) { - usb_set_intfdata(other, NULL); - usb_driver_release_interface(driver, other); - } - - info->subdriver = NULL; - info->data = NULL; - info->control = NULL; -} - -/* suspend/resume wrappers calling both usbnet and the cdc-wdm - * subdriver if present. - * - * NOTE: cdc-wdm also supports pre/post_reset, but we cannot provide - * wrappers for those without adding usbnet reset support first. - */ -static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct qmi_wwan_state *info = (void *)&dev->data; - int ret; - - /* Both usbnet_suspend() and subdriver->suspend() MUST return 0 - * in system sleep context, otherwise, the resume callback has - * to recover device from previous suspend failure. - */ - ret = usbnet_suspend(intf, message); - if (ret < 0) - goto err; - - if (intf == info->control && info->subdriver && - info->subdriver->suspend) - ret = info->subdriver->suspend(intf, message); - if (ret < 0) - usbnet_resume(intf); -err: - return ret; -} - -static int qmi_wwan_resume(struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct qmi_wwan_state *info = (void *)&dev->data; - int ret = 0; - bool callsub = (intf == info->control && info->subdriver && - info->subdriver->resume); - - if (callsub) - ret = info->subdriver->resume(intf); - if (ret < 0) - goto err; - ret = usbnet_resume(intf); - if (ret < 0 && callsub) - info->subdriver->suspend(intf, PMSG_SUSPEND); -err: - return ret; -} - -static int qmi_wwan_reset_resume(struct usb_interface *intf) -{ - dev_info(&intf->dev, "device do not support reset_resume\n"); - intf->needs_binding = 1; - return -EOPNOTSUPP; -} - -static int rmnet_usb_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int status = qmi_wwan_bind(dev, intf); - dev_err(&intf->dev, "rmnet_usb_bind\n"); - - if (!status) { - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - - if (pQmapDev && pQmapDev->qmap_mode) { - struct net_device *rmmet_usb = dev->net; - - pQmapDev->use_rmnet_usb = 1; - pQmapDev->rmnet_info.size = sizeof(RMNET_INFO); - pQmapDev->rmnet_info.rx_urb_size = pQmapDev->qmap_size; - pQmapDev->rmnet_info.ep_type = 2; //DATA_EP_TYPE_HSUSB - pQmapDev->rmnet_info.iface_id = 4; - pQmapDev->rmnet_info.qmap_mode = pQmapDev->qmap_mode; - pQmapDev->rmnet_info.qmap_version = pQmapDev->qmap_version; - pQmapDev->rmnet_info.dl_minimum_padding = 0; - - strcpy(rmmet_usb->name, "rmnet_usb%d"); - -#if 0 - rmmet_usb->header_ops = NULL; /* No header */ - rmmet_usb->type = ARPHRD_RAWIP; - rmmet_usb->hard_header_len = 0; - rmmet_usb->addr_len = 0; -#endif - rmmet_usb->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - rmmet_usb->flags |= (IFF_NOARP); - } - } - - return status; -} - -static struct sk_buff *rmnet_usb_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - if (skb->protocol != htons(ETH_P_MAP)) { - dev_kfree_skb_any(skb); - return NULL; - } - - return skb; -} - -static int rmnet_usb_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - struct net_device *net = dev->net; - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - if (net->type == ARPHRD_ETHER && skb_headroom(skb) >= ETH_HLEN) { - //usbnet.c rx_process() usbnet_skb_return() eth_type_trans() - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - memcpy(eth_hdr(skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(skb)->h_dest, net->dev_addr, ETH_ALEN); - eth_hdr(skb)->h_proto = htons(ETH_P_MAP); - - return 1; - } - - return 0; -} - -static void _rmnet_usb_rx_handler(struct usbnet *dev, struct sk_buff *skb_in) -{ - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - struct sk_buff *qmap_skb; - struct sk_buff_head skb_chain; - uint dl_minimum_padding = 0; - - if (pQmapDev->qmap_version == 9) - dl_minimum_padding = pQmapDev->tx_ctx.dl_minimum_padding; - - __skb_queue_head_init(&skb_chain); - - while (skb_in->len > sizeof(struct qmap_hdr)) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb_in->data; - struct rmnet_map_v5_csum_header *ul_header = NULL; - size_t hdr_size = sizeof(struct rmnet_map_header); - struct net_device *qmap_net; - int pkt_len = ntohs(map_header->pkt_len); - int skb_len; - __be16 protocol; - int mux_id; - - if (map_header->next_hdr) { - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - hdr_size += sizeof(struct rmnet_map_v5_csum_header); - } - - skb_len = pkt_len - (map_header->pad_len&0x3F); - skb_len -= dl_minimum_padding; - if (skb_len > 1500) { - dev_info(&dev->net->dev, "drop skb_len=%x larger than 1500\n", skb_len); - goto error_pkt; - } - - if (skb_in->len < (pkt_len + hdr_size)) { - dev_info(&dev->net->dev, "drop qmap unknow pkt, len=%d, pkt_len=%d\n", skb_in->len, pkt_len); - goto error_pkt; - } - - if (map_header->cd_bit) { - dev_info(&dev->net->dev, "skip qmap command packet\n"); - goto skip_pkt; - } - - switch (skb_in->data[hdr_size] & 0xf0) { - case 0x40: - protocol = htons(ETH_P_IP); - break; - case 0x60: - protocol = htons(ETH_P_IPV6); - break; - default: - dev_info(&dev->net->dev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]); - goto error_pkt; - } - - mux_id = map_header->mux_id - FIBOCOM_QMAP_MUX_ID; - if (mux_id >= pQmapDev->qmap_mode) { - dev_info(&dev->net->dev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - goto error_pkt; - } - - qmap_net = pQmapDev->mpQmapNetDev[mux_id]; - - if (qmap_net == NULL) { - dev_info(&dev->net->dev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - goto skip_pkt; - } - - qmap_skb = netdev_alloc_skb(qmap_net, skb_len); - if (qmap_skb) { - skb_put(qmap_skb, skb_len); - memcpy(qmap_skb->data, skb_in->data + hdr_size, skb_len); - } - - if (qmap_skb == NULL) { - dev_info(&dev->net->dev, "fail to alloc skb, pkt_len = %d\n", skb_len); - goto error_pkt; - } - - skb_reset_transport_header(qmap_skb); - skb_reset_network_header(qmap_skb); - qmap_skb->pkt_type = PACKET_HOST; - skb_set_mac_header(qmap_skb, 0); - qmap_skb->protocol = protocol; - - if (ul_header && ul_header->header_type == RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD - && ul_header->csum_valid_required) { -#if 0 //TODO - qmap_skb->ip_summed = CHECKSUM_UNNECESSARY; -#endif - } - - if (qmap_skb->dev->type == ARPHRD_ETHER) { - skb_push(qmap_skb, ETH_HLEN); - skb_reset_mac_header(qmap_skb); - memcpy(eth_hdr(qmap_skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(qmap_skb)->h_dest, qmap_net->dev_addr, ETH_ALEN); - eth_hdr(qmap_skb)->h_proto = protocol; -#ifdef FIBOCOM_BRIDGE_MODE - bridge_mode_rx_fixup(pQmapDev, qmap_net, qmap_skb); -#endif - __skb_pull(qmap_skb, ETH_HLEN); - } - - rmnet_vnd_update_rx_stats(qmap_net, 1, skb_len); - __skb_queue_tail(&skb_chain, qmap_skb); - -skip_pkt: - skb_pull(skb_in, pkt_len + hdr_size); - } - -error_pkt: - while ((qmap_skb = __skb_dequeue (&skb_chain))) { - netif_receive_skb(qmap_skb); - } -} - -static rx_handler_result_t rmnet_usb_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct usbnet *dev; - - if (!skb) - goto done; - - //printk("%s skb=%p, protocol=%x, len=%d\n", __func__, skb, skb->protocol, skb->len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - if (skb->protocol != htons(ETH_P_MAP)) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - /* when open hyfi function, run cm will make system crash */ - //dev = rcu_dereference(skb->dev->rx_handler_data); - dev = netdev_priv(skb->dev); - - if (dev == NULL) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - - _rmnet_usb_rx_handler(dev, skb); - consume_skb(skb); - -done: - return RX_HANDLER_CONSUMED; -} - -static const struct driver_info qmi_wwan_info = { - .description = "WWAN/QMI device", - .flags = FLAG_WWAN, - .bind = qmi_wwan_bind, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .rx_fixup = qmi_wwan_rx_fixup, -}; - -static const struct driver_info qmi_wwan_raw_ip_info = { - .description = "WWAN/QMI device", - .flags = FLAG_WWAN | FLAG_RX_ASSEMBLE | FLAG_NOARP | FLAG_SEND_ZLP | FLAG_MULTI_PACKET, - .bind = qmi_wwan_bind, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, -#if defined(FIBOCOM_WWAN_QMAP) - .tx_fixup = qmap_qmi_wwan_tx_fixup, - .rx_fixup = qmap_qmi_wwan_rx_fixup, -#else - .tx_fixup = qmi_wwan_tx_fixup, - .rx_fixup = qmi_wwan_rx_fixup, -#endif -}; - -static const struct driver_info rmnet_usb_info = { - .description = "RMNET/USB device", - .flags = FLAG_NOARP | FLAG_SEND_ZLP, - .bind = rmnet_usb_bind, - .unbind = qmi_wwan_unbind, - .manage_power = qmi_wwan_manage_power, - .tx_fixup = rmnet_usb_tx_fixup, - .rx_fixup = rmnet_usb_rx_fixup, -}; - -/* map QMI/wwan function by a fixed interface number */ -#define QMI_FIXED_INTF(vend, prod, num) \ - USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ - .driver_info = (unsigned long)&qmi_wwan_info - -#define QMI_FIXED_RAWIP_INTF(vend, prod, num) \ - USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ - .driver_info = (unsigned long)&qmi_wwan_raw_ip_info - -#define RMNET_USB_INTF(vend, prod, num) \ - USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \ - .driver_info = (unsigned long) &rmnet_usb_info - -static const struct usb_device_id products[] = { -#if 1 //Added by Fibocom - { QMI_FIXED_RAWIP_INTF(0x2cb7, 0x0104, 4) }, /* Fibocom FG150/FM150/NL952/FG101 */ - { QMI_FIXED_RAWIP_INTF(0x2cb7, 0x0109, 2) }, /* Fibocom FG150/FM150 */ - { QMI_FIXED_RAWIP_INTF(0x2cb7, 0x0113, 0) }, /* Fibocom FG101 */ - { QMI_FIXED_RAWIP_INTF(0x1508, 0x1000, 2) }, /* Fibocom NL668 */ - { QMI_FIXED_RAWIP_INTF(0x1508, 0x1001, 4) }, /* Fibocom NL668 */ - { QMI_FIXED_RAWIP_INTF(0x05c6, 0x9025, 4) }, /* Fibocom NL668 */ -#endif - { } /* END */ -}; -MODULE_DEVICE_TABLE(usb, products); - -static int qmi_wwan_probe(struct usb_interface *intf, - const struct usb_device_id *prod) -{ - struct usb_device_id *id = (struct usb_device_id *)prod; - - /* Workaround to enable dynamic IDs. This disables usbnet - * blacklisting functionality. Which, if required, can be - * reimplemented here by using a magic "blacklist" value - * instead of 0 in the static device id table - */ - if (!id->driver_info) { - dev_dbg(&intf->dev, "setting defaults for dynamic device id\n"); - id->driver_info = (unsigned long)&qmi_wwan_info; - } - - if (intf->cur_altsetting->desc.bInterfaceClass != 0xff) { - dev_info(&intf->dev, "Fibocom module not qmi_wwan mode!\n"); - return -ENODEV; - } - - return usbnet_probe(intf, id); -} - -#if defined(FIBOCOM_WWAN_QMAP) -static int qmap_qmi_wwan_probe(struct usb_interface *intf, - const struct usb_device_id *prod) -{ - int status = qmi_wwan_probe(intf, prod); - - if (!status) { - struct usbnet *dev = usb_get_intfdata(intf); - struct qmi_wwan_state *info = (void *)&dev->data; - sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; - unsigned i; - - if (!pQmapDev) - return status; - - tasklet_init(&pQmapDev->txq, rmnet_usb_tx_wake_queue, (unsigned long)pQmapDev); - - if (pQmapDev->qmap_mode == 1) { - pQmapDev->mpQmapNetDev[0] = dev->net; - if (pQmapDev->use_rmnet_usb) { - pQmapDev->mpQmapNetDev[0] = NULL; - qmap_register_device(pQmapDev, 0); - } - } - else if (pQmapDev->qmap_mode > 1) { - for (i = 0; i < pQmapDev->qmap_mode; i++) { - qmap_register_device(pQmapDev, i); - } - } - - if (pQmapDev->use_rmnet_usb) { - rtnl_lock(); - /* when open hyfi function, run cm will make system crash */ - //netdev_rx_handler_register(dev->net, rmnet_usb_rx_handler, dev); - netdev_rx_handler_register(dev->net, rmnet_usb_rx_handler, NULL); - rtnl_unlock(); - } - - if (pQmapDev->link_state == 0) { - netif_carrier_off(dev->net); - } - } - - return status; -} - -static void qmap_qmi_wwan_disconnect(struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - struct qmi_wwan_state *info; - sQmiWwanQmap *pQmapDev; - uint i; - - if (!dev) - return; - - info = (void *)&dev->data; - pQmapDev = (sQmiWwanQmap *)info->unused; - - if (!pQmapDev) { - return usbnet_disconnect(intf); - } - - pQmapDev->link_state = 0; - - if (pQmapDev->qmap_mode > 1) { - for (i = 0; i < pQmapDev->qmap_mode; i++) { - qmap_unregister_device(pQmapDev, i); - } - } - - if (pQmapDev->use_rmnet_usb) { - qmap_unregister_device(pQmapDev, 0); - rtnl_lock(); - netdev_rx_handler_unregister(dev->net); - rtnl_unlock(); - } - - tasklet_kill(&pQmapDev->txq); - - usbnet_disconnect(intf); - info->unused = 0; - kfree(pQmapDev); -} -#endif - -static struct usb_driver qmi_wwan_driver = { - .name = "qmi_wwan_f", - .id_table = products, - .probe = qmi_wwan_probe, -#if defined(FIBOCOM_WWAN_QMAP) - .probe = qmap_qmi_wwan_probe, - .disconnect = qmap_qmi_wwan_disconnect, -#else - .probe = qmi_wwan_probe, - .disconnect = usbnet_disconnect, -#endif - .suspend = qmi_wwan_suspend, - .resume = qmi_wwan_resume, - .reset_resume = qmi_wwan_reset_resume, - .supports_autosuspend = 1, - .disable_hub_initiated_lpm = 1, -}; - -#ifdef CONFIG_QCA_NSS_DRV -/* - EXTRA_CFLAGS="-I$(STAGING_DIR)/usr/include/qca-nss-drv $(EXTRA_CFLAGS)" - qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c -*/ -#include "rmnet_nss.c" -#endif - -static int __init qmi_wwan_driver_init(void) -{ - RCU_INIT_POINTER(rmnet_nss_callbacks, NULL); -#ifdef CONFIG_QCA_NSS_DRV - if (qca_nss_enabled) - rmnet_nss_init(); -#endif - return usb_register(&qmi_wwan_driver); -} -module_init(qmi_wwan_driver_init); -static void __exit qmi_wwan_driver_exit(void) -{ -#ifdef CONFIG_QCA_NSS_DRV - if (qca_nss_enabled) - rmnet_nss_exit(); -#endif - usb_deregister(&qmi_wwan_driver); -} -module_exit(qmi_wwan_driver_exit); - -MODULE_AUTHOR("Bjørn Mork "); -MODULE_DESCRIPTION("Qualcomm MSM Interface (QMI) WWAN driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(FIBOCOM_WWAN_VERSION); diff --git a/luci-app-cpe/Makefile b/luci-app-cpe/Makefile deleted file mode 100644 index d259239..0000000 --- a/luci-app-cpe/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#将openwrt顶层目录下的rules.mk文件中的内容导入进来 -include $(TOPDIR)/rules.mk -#软件包名 -PKG_NAME:=luci-app-cpe -#软件包版本 -PKG_VERSION:=5.0.1 -#真正编译当前软件包的目录 -PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME) - - - #将$(TOPDIR)/include目录下的package.mk文件中的内容导入进来 -include $(INCLUDE_DIR)/package.mk - -define Package/luci-app-cpe - PKGARCH:=all - SECTION:=wrtnode - CATEGORY:=Daocaoren - SUBMENU :=CPE - TITLE:=luci-app-cpe - DEPENDS:=+sendat + luci-compat +kmod-usb-net +kmod-usb-net-cdc-ether +kmod-usb-acm \ - +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis +kmod-usb-serial-qualcomm \ - +kmod-usb-net-sierrawireless +kmod-usb-ohci +kmod-usb-serial \ - +kmod-usb-serial-option +kmod-usb-wdm \ - +kmod-usb2 +kmod-usb3 \ - +quectel-CM-5G +kmod-usb-net-cdc-mbim +usbutils -endef - -PKG_LICENSE:=GPLv3 -PKG_LINCESE_FILES:=LICENSE -PKF_MAINTAINER:=daocaoren <168620188@qq.com> - -include $(TOPDIR)/feeds/luci/luci.mk -# call BuildPackage - OpenWrt buildroot signature - diff --git a/luci-app-cpe/luasrc/controller/admin/cpe.lua b/luci-app-cpe/luasrc/controller/admin/cpe.lua deleted file mode 100644 index 49dad2c..0000000 --- a/luci-app-cpe/luasrc/controller/admin/cpe.lua +++ /dev/null @@ -1,189 +0,0 @@ -module("luci.controller.admin.cpe", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - entry({"admin", "modem"}, firstchild(), translate("移动数据"), 25).dependent=false - entry({"admin", "modem", "nets"}, template("cpe/net_status"), translate("信号状态"), 0) - entry({"admin", "modem", "get_csq"}, call("action_get_csq")) - entry({"admin", "modem", "send_atcmd"}, call("action_send_atcmd")) - - -- entry({"admin", "modem", "sms"}, template("cpe/sms"), translate("短信信息"), 1) - -- entry({"admin", "modem", "band"}, template("cpe/band"), translate("锁频段/锁PCI"), 1) - entry({"admin", "modem", "at"}, template("cpe/at"), translate("AT工具"), 98) - - if not nixio.fs.access("/etc/config/modem") then - return - end - entry({"admin", "modem", "modem"}, cbi("cpe/modem"), _("模块设置"), 99) - -end - -function action_send_atcmd() - local rv ={} - local file - local p = luci.http.formvalue("p") - local set = luci.http.formvalue("set") - fixed = string.gsub(set, "\"", "~") - port= string.gsub(p, "\"", "~") - rv["at"] = fixed - rv["port"] = port - - os.execute("/usr/share/cpe/atcmd.sh \'" .. port .. "\' \'" .. fixed .. "\'") - result = "/tmp/result.at" - file = io.open(result, "r") - if file ~= nil then - rv["result"] = file:read("*all") - file:close() - else - rv["result"] = " " - end - os.execute("/usr/share/cpe/delatcmd.sh") - luci.http.prepare_content("application/json") - luci.http.write_json(rv) - -end - -function action_get_csq() - local file - stat = "/tmp/cpe_cell.file" - file = io.open(stat, "r") - local rv ={} - - -- echo 'RM520N-GL' - -- echo 'conntype' - -- echo '1e0e:9001' - -- echo $COPS #运营商 - -- echo '' #端口 - -- echo '' #温度 - -- echo '' #协议 - rv["modem"] = file:read("*line") - rv["conntype"] = file:read("*line") - rv["modid"] = file:read("*line") - rv["cops"] = file:read("*line") - rv["port"] = file:read("*line") - rv["tempur"] = file:read("*line") - rv["proto"] = file:read("*line") - file:read("*line") - - - -- echo $IMEI #imei - -- echo $IMSI #imsi - -- echo $ICCID #iccid - -- echo $phone #phone - rv["imei"] = file:read("*line") - rv["imsi"] = file:read("*line") - rv["iccid"] =file:read("*line") - rv["phone"] = file:read("*line") - file:read("*line") - - - -- echo $MODE - -- echo $CSQ - -- echo $CSQ_PER - -- echo $CSQ_RSSI - -- echo '' #参考信号接收质量 RSRQ ecio - -- echo '' #参考信号接收质量 RSRQ ecio1 - -- echo '' #参考信号接收功率 RSRP rscp - -- echo '' #参考信号接收功率 RSRP rscp1 - -- echo '' #信噪比 SINR rv["sinr"] - -- echo '' #连接状态监控 rv["netmode"] - rv["mode"] = file:read("*line") - rv["csq"] = file:read("*line") - rv["per"] = file:read("*line") - rv["rssi"] = file:read("*line") - rv["ecio"] = file:read("*line") - rv["ecio1"] = file:read("*line") - rv["rscp"] = file:read("*line") - rv["rscp1"] = file:read("*line") - rv["sinr"] = file:read("*line") - rv["netmode"] = file:read("*line") - file:read("*line") - - rssi = rv["rssi"] - ecio = rv["ecio"] - rscp = rv["rscp"] - ecio1 = rv["ecio1"] - rscp1 = rv["rscp1"] - if ecio == nil then - ecio = "-" - end - if ecio1 == nil then - ecio1 = "-" - end - if rscp == nil then - rscp = "-" - end - if rscp1 == nil then - rscp1 = "-" - end - - if ecio ~= "-" then - rv["ecio"] = ecio .. " dB" - end - if rscp ~= "-" then - rv["rscp"] = rscp .. " dBm" - end - if ecio1 ~= " " then - rv["ecio1"] = " (" .. ecio1 .. " dB)" - end - if rscp1 ~= " " then - rv["rscp1"] = " (" .. rscp1 .. " dBm)" - end - - rv["mcc"] = file:read("*line") - rv["mnc"] = file:read("*line") - rv["rnc"] = file:read("*line") - rv["rncn"] = file:read("*line") - rv["lac"] = file:read("*line") - rv["lacn"] = file:read("*line") - rv["cid"] = file:read("*line") - rv["cidn"] = file:read("*line") - rv["lband"] = file:read("*line") - rv["channel"] = file:read("*line") - rv["pci"] = file:read("*line") - - rv["date"] = file:read("*line") - - -- rv["phonen"] = file:read("*line") - --rv["host"] = "0" - - -- rv["simerr"] = "0" - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - - - -- rv["down"] = file:read("*line") - -- rv["up"] = file:read("*line") - -- - -- - - -- - -- rv["cell"] = file:read("*line") - -- rv["modtype"] = file:read("*line") - -- - -- - -- - -- - -- - -- - - - -- rv["lat"] = "-" - -- rv["long"] = "-" - - - - rv["crate"] = translate("快速(每10秒更新一次)") - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end \ No newline at end of file diff --git a/luci-app-cpe/luasrc/model/cbi/cpe/modem.lua b/luci-app-cpe/luasrc/model/cbi/cpe/modem.lua deleted file mode 100644 index 376c068..0000000 --- a/luci-app-cpe/luasrc/model/cbi/cpe/modem.lua +++ /dev/null @@ -1,144 +0,0 @@ -local m, section, m2, s2 - -m = Map("modem", translate("Mobile Network")) -m.description = translate("Modem Server For OpenWrt") - - --------------------------------Fibocom Wireless Inc. FM650 Module---------------------------------- -if (string.gsub(luci.sys.exec('lsusb |grep "ID 2cb7:0a05 " | wc -l'),"%s+","")=="1") then - section = m:section(TypedSection, "ndis", translate("FMFM650-CN Settings"), translate("[1]Automatic start upon startup: Check
[2] FMFMFM650-CN module default ECM (36) mode. If not, please modify it, otherwise dialing cannot proceed normally
")) - section.anonymous = true - section.addremove = false - enable = section:option(Flag, "enabled", translate("Enable")) - enable.rmempty = false -else - section = m:section(TypedSection, "ndis", translate("SIM Settings"), translate("Automatic operation upon startup \r\n ooo")) - section.anonymous = true - section.addremove = false - section:tab("general", translate("General Setup")) - section:tab("advanced", translate("Advanced Settings")) - - - enable = section:taboption("general", Flag, "enabled", translate("Enable")) - enable.rmempty = false - - device = section:taboption("general",Value, "device", translate("Modem device")) - device.rmempty = false - local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*") - if device_suggestions then - local node - for node in device_suggestions do - device:value(node) - end - end - apn = section:taboption("general", Value, "apn", translate("APN")) - username = section:taboption("general", Value, "username", translate("PAP/CHAP Username")) - password = section:taboption("general", Value, "password", translate("PAP/CHAP Password")) - password.password = true - pincode = section:taboption("general", Value, "pincode", translate("PIN Code")) - auth = section:taboption("general", Value, "auth", translate("Authentication Type")) - auth.rmempty = true - auth:value("", translate("-- Please choose --")) - auth:value("both", "PAP/CHAP (both)") - auth:value("pap", "PAP") - auth:value("chap", "CHAP") - auth:value("none", "NONE") - tool = section:taboption("general", Value, "tool", translate("Tools")) - tool:value("quectel-CM", "quectel-CM") - tool.rmempty = true - PdpType= section:taboption("general", Value, "pdptype", translate("PdpType")) - PdpType:value("IPV4", "IPV4") - PdpType:value("IPV6", "IPV6") - PdpType:value("IPV4V6", "IPV4V6") - PdpType.rmempty = true - - - ---------------------------advanced------------------------------ - bandlist = section:taboption("advanced", ListValue, "bandlist", translate("Lock Band List")) - -- if (string.gsub(luci.sys.exec('uci get system.@system[0].modem |grep lte |wc -l'),"%s+","")=="1") then - -- bandlist.default = "0" - -- bandlist:value("1", "LTE BAND1") - -- bandlist:value("2", "LTE BAND2") - -- bandlist:value("3", "LTE BAND3") - -- bandlist:value("4", "LTE BAND4") - -- bandlist:value("5", "LTE BAND5") - -- bandlist:value("7", "LTE BAND7") - -- bandlist:value("8", "LTE BAND8") - -- bandlist:value("20", "LTE BAND20") - -- bandlist:value("38", "LTE BAND38") - -- bandlist:value("40", "LTE BAND40") - -- bandlist:value("41", "LTE BAND41") - -- bandlist:value("28", "LTE BAND28") - -- bandlist:value("A", "AUTO") - -- end - bandlist:value("0", translate("Disable")) - - servertype = section:taboption("advanced", ListValue, "servertype", translate("Server Type")) - servertype.default = "0" - - --if (string.gsub(luci.sys.exec('uci get system.@system[0].modem |grep nr5g |wc -l'),"%s+","")=="1") then - servertype:value("1", "5G Only") - servertype:value("5", "4G/5G Only") - --end - servertype:value("2", "4G Only") - servertype:value("3", "3G Only") - servertype:value("4", "2G Only") - servertype:value("0", "AUTO") - - - -- s1 = m:section(TypedSection, "ndis", translate("AT Port Settings"),translate("Set tyyUSB port")) - -- s1.anonymous = true - -- s1.addremove = false - -- tyyusb= s1:option(Value, "tyyusb", translate("tyyUSB port")) - -- tyyusb.default = "2" - -- tyyusb:value("0", "0") - -- tyyusb:value("1", "1") - -- tyyusb:value("2", "2") - -- tyyusb:value("3", "3") - -- tyyusb:value("4", "4") - -- tyyusb.rmempty=false -end - - - - - - - - - -s2 = m:section(TypedSection, "ndis", translate("Network Diagnostics"),translate("Network exception handling: \ -check the network connection in a loop for 5 seconds. If the Ping IP address is not successful, After the network \ -exceeds the abnormal number, restart and search the registered network again.")) -s2.anonymous = true -s2.addremove = false - -en = s2:option(Flag, "en", translate("Enable")) -en.rmempty = false - - - -ipaddress= s2:option(Value, "ipaddress", translate("Ping IP address")) -ipaddress.default = "114.114.114.114" -ipaddress.rmempty=false - -an = s2:option(Value, "an", translate("Abnormal number")) -an.default = "15" -an:value("3", "3") -an:value("5", "5") -an:value("10", "10") -an:value("15", "15") -an:value("20", "20") -an:value("25", "25") -an:value("30", "30") -an.rmempty=false - - - -local apply = luci.http.formvalue("cbi.apply") -if apply then - -- io.popen("/etc/init.d/modeminit restart") - io.popen("/etc/init.d/modem restart") -end - -return m,m2 diff --git a/luci-app-cpe/luasrc/view/cpe/at.htm b/luci-app-cpe/luasrc/view/cpe/at.htm deleted file mode 100644 index 1c9a8a7..0000000 --- a/luci-app-cpe/luasrc/view/cpe/at.htm +++ /dev/null @@ -1,152 +0,0 @@ -<%+header%> -<% -local sys = require "luci.sys" -local utl = require "luci.util" -local fs = require "nixio.fs" -local uci = require "luci.model.uci".cursor() -local s = uci:get("custom", "bandlock", "enabled") -local a = uci:get("custom", "atcmd", "enabled") - -local multilock = uci:get("custom", "multiuser", "multi") or "0" -local rootlock = uci:get("custom", "multiuser", "root") or "0" -nomulti=1 -if (multilock == "0") or (multilock == "1" and rootlock == "1") then - nosms = 1 - if a == "1" then - nosms = 0 - end -else - nosms = 1 - nomulti = 0 -end -block = 1 -if s == "1" then - block = 0 -end - -function showicon(lck) -end - --%> - - - - -
-

<%:AT命令工具%>

-
<%:AT命令工具%>
- - - - -
- <%:AT命令终端%> - - - - - - - - - - - -
<%:模块端口 : %>
- -
<%:AT命令 : %>
- - -  
- - - -
- - - - -<%+footer%> diff --git a/luci-app-cpe/luasrc/view/cpe/net_status.htm b/luci-app-cpe/luasrc/view/cpe/net_status.htm deleted file mode 100644 index 96c569e..0000000 --- a/luci-app-cpe/luasrc/view/cpe/net_status.htm +++ /dev/null @@ -1,296 +0,0 @@ -<%+header%> -<% -local fs = require "nixio.fs" -nosms = 1 -if not fs.stat("/etc/nosim") then - nosms = 0 -end -havegps = 0 -if fs.stat("/etc/havegps") then - havegps = 1 -end --%> - - - - - -
-

<%:信号状态/模块信息%>

-
请注意该插件所有功能并无适配所有5G模块,不用妄想冷门模块插上就能用(有能力者自行适配) -
- - - - -
- <%:综合信息%> - - - - - - -
<%:模块 :%>-
<%:制造商 :%>
<%:温度 : %>
<%:更新时间 : %>
-
- -<% if nosms == 0 then %> -<% end %> - -
- <%:通信模块/SIM卡信息%> - - - - - - -
<%:运营商 : %>
<%:IMEI :%>
<%:IMSI : %>
<%:ICCID : %>
<%:SIM卡号码 : %>
-
- - -
- <%:信号状态%> - - - - - - - - - - -
<%:蜂窝网络类型 :%>
<%:CSQ : %>
<%:信号强度 : %>
<%:信号接收强度 RSSI : %>
<%:参考信号接收质量 RSRQ : %>
<%:参考信号接收功率 RSRP : %>
<%:信噪比 SINR : %>
<%:连接状态监控 : %>
-
- -
- <%:基站信息%> - - - - - - - - - - -
<%:MCC / MNC :%>
<%:eNB ID : %>
<%:TAC : %>
<%:Cell ID : %>
<%:频段 Band : %>
<%:频点 Channel : %>
<%:物理小区标识 PCI : %>
<%:最大Qos级别 Maximum Qos : %>
-
- - -<% if havegps == 1 then %> -
- <%:GPS 定位%> - - - - - - - - - - - -
<%:纬度 :%>
     
    <%:经度 :%>
       
      -
      -<% end %> - - -
      -<%+footer%> - diff --git a/luci-app-cpe/po/zh-cn/modem.po b/luci-app-cpe/po/zh-cn/modem.po deleted file mode 100644 index 25681b8..0000000 --- a/luci-app-cpe/po/zh-cn/modem.po +++ /dev/null @@ -1,73 +0,0 @@ -msgid "" -msgstr "" - -msgid "Mobile Network" -msgstr "模块设置" - - -msgid "Automatic operation upon startup ooo" -msgstr "开机自动启动:勾选" - -msgid "Tools" -msgstr "拨号工具" - -msgid "PAP/CHAP Username" -msgstr "PAP/CHAP 用户" - -msgid "PAP/CHAP Password" -msgstr "PAP/CHAP 密码" - - -msgid "Modem Server For OpenWrt" -msgstr "4G/5G模块管理" - - -msgid "SIM Settings" -msgstr "SIM 配置 (联通ANP:3gnet) (电信APN:ctnet) (移动APN:cmnet) (广电APN:cbnet) " - -msgid "PdpType" -msgstr "IP获取方式" - -msgid "AT Port Settings" -msgstr "AT 模块配置" - -msgid "Set tyyUSB port" -msgstr "AT 模块端口配置 (全模块指定端口)" - -msgid "tyyUSB port" -msgstr "ttyUSB 配置ID" - -msgid "Network Diagnostics" -msgstr "网络诊断" - - -msgid "Network Diagnostics" -msgstr "网络诊断" - - -msgid "Network exception handling: check the network connection in a loop for 5 seconds. If the Ping IP address is not successful, After the network exceeds the abnormal number, restart and search the registered network again." -msgstr "网络异常处理:循环检查网络连接5秒。如果Ping IP地址不成功,则在网络超过异常数量后,重新启动并搜索已注册的网络。" - -msgid "Ping IP address" -msgstr "Ping IP地址" - -msgid "Abnormal number" -msgstr "异常次数" - -msgid "Lock Band List" -msgstr "锁定频段列表" - -msgid "Server Type" -msgstr "服务类型" - -msgid "FMFM650-CN Settings" -msgstr "FMFM650-CN 设置" - -msgid "[1]Automatic start upon startup: Check
      [2] FMFMFM650-CN module default ECM (36) mode. If not, please modify it, otherwise dialing cannot proceed normally
      " -msgstr "【1】 开机自动启动:勾选
      【2】 FMFM650-CN 模块默认 ECM (36)模式如果不是请修改 否则不能正常进行拨号
      " - - - - - - diff --git a/luci-app-cpe/po/zh_Hans b/luci-app-cpe/po/zh_Hans deleted file mode 100644 index 41451e4..0000000 --- a/luci-app-cpe/po/zh_Hans +++ /dev/null @@ -1 +0,0 @@ -zh-cn \ No newline at end of file diff --git a/luci-app-cpe/root/etc/config/modem b/luci-app-cpe/root/etc/config/modem deleted file mode 100644 index 3b57bd5..0000000 --- a/luci-app-cpe/root/etc/config/modem +++ /dev/null @@ -1,12 +0,0 @@ -config ndis - option enabled '0' - option bandlist '0' - option servertype '0' - option ipaddress '114.114.114.114' - option en '0' - option an '5' - option model 'nr5g' - option tyyusb '2' - option tool 'quectel-CM' - option device '/dev/cdc-wdm0' - option pdptype 'IPV4V6' diff --git a/luci-app-cpe/root/etc/init.d/cpeinit b/luci-app-cpe/root/etc/init.d/cpeinit deleted file mode 100644 index c5f2299..0000000 --- a/luci-app-cpe/root/etc/init.d/cpeinit +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -start() { - /bin/sh /usr/share/cpe/rssi & -} \ No newline at end of file diff --git a/luci-app-cpe/root/etc/init.d/modem b/luci-app-cpe/root/etc/init.d/modem deleted file mode 100644 index dffe31c..0000000 --- a/luci-app-cpe/root/etc/init.d/modem +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2014 OpenWrt.org - -START=16 -STOP=16 -USE_PROCD=1 -#使用procd启动 - - -# start启动服务 -# stop停止服务 -# restart重新启动服务 -# reload重新加载配置文件(如果服务未实现重新加载,则重新启动) -# enable启用服务自动启动 -# disable禁用服务自动启动 -# enabled检查服务是否在启动时启动 -# 正在运行检查服务是否正在运行 -# status服务状态 -# trace从系统调用跟踪开始 - -runModem() -{ - local enabled - config_get_bool enabled $1 enabled - echo "run runModem" >> /tmp/log4g - if [ "$enabled" = "1" ]; then - - - local user - local password - local apn - local auth - local pincode - local device - local tool - local pdptype - - - config_get user $1 user - config_get password $1 password - config_get apn $1 apn - config_get auth $1 auth - config_get pincode $1 pincode - config_get device $1 device - config_get tool $1 tool - config_get pdptype $1 pdptype - config_get tty $1 tty - config_get atcmd $1 atcmd - - if [ "$pdptype" = "IPV4V6" ]; then - pdptype='-4 -6' - elif [ "$pdptype" = "IPV6" ]; then - pdptype='-6' - else - pdptype='' - fi - - devname="$(basename "$device")" - devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" - ifname="$( ls "$devpath"/net )" - - - procd_open_instance - #创建一个实例, 在procd看来一个应用程序可以多个实\E4\BE? - #ubus call service list 可以查看实例 - procd_set_param command $tool -i $ifname -s $apn $pdptype - if [ "$password" != "" ];then - procd_append_param command $user $password $auth - fi - if [ "$pincode" != "" ]; then - procd_append_param command -p $pincode - fi - # procd_append_param command -f /tmp/4g.log - procd_set_param respawn - echo "quectel-CM has started." - procd_close_instance - #关闭实例 - fi - - - -} - - - - -service_triggers() -{ - procd_add_reload_trigger "modem" -} - -start_service() { - config_load modem - config_foreach runModem ndis -} - -stop_service() -{ - echo "runModem stop" >> /tmp/log4g - killall quectel-CM - echo "quectel-CM has stoped." -} - diff --git a/luci-app-cpe/root/etc/uci-defaults/luci-modem b/luci-app-cpe/root/etc/uci-defaults/luci-modem deleted file mode 100644 index 3181024..0000000 --- a/luci-app-cpe/root/etc/uci-defaults/luci-modem +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@modem[-1] - add ucitrack modem - set ucitrack.@modem[-1].init=modem - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/luci-app-cpe/root/usr/bin/bmask128 b/luci-app-cpe/root/usr/bin/bmask128 deleted file mode 100644 index bfd5bde..0000000 --- a/luci-app-cpe/root/usr/bin/bmask128 +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# -printf "Band 128-bit bandmask\n" -LBAND=1 -BBAND=1 -while [ $LBAND -le 48 ] -do - printf "%-6s%016X%016X\n" "$LBAND" "0" "$BBAND" - LBAND=$(( $LBAND + 1 )) - BBAND=$(( $BBAND * 2 )) -done -LBAND=65 -BBAND=1 -while [ $LBAND -le 85 ] -do - printf "%-6s%016X%016X\n" "$LBAND" "$BBAND" "0" - LBAND=$(( $LBAND + 1 )) - BBAND=$(( $BBAND * 2 )) -done diff --git a/luci-app-cpe/root/usr/bin/chan2band.sh b/luci-app-cpe/root/usr/bin/chan2band.sh deleted file mode 100644 index 5b5bff0..0000000 --- a/luci-app-cpe/root/usr/bin/chan2band.sh +++ /dev/null @@ -1,317 +0,0 @@ -#!/bin/sh -CHAN=$1 -CHAN=$(echo "$CHAN" | grep -o "[0-9]*") - -decode_lte() { - if [ $CHAN -lt 600 ]; then - BAND="B1" - elif [ $CHAN -lt 1200 ]; then - BAND="B2" - elif [ $CHAN -lt 1950 ]; then - BAND="B3" - elif [ $CHAN -lt 2400 ]; then - BAND="B4" - elif [ $CHAN -lt 2650 ]; then - BAND="B5" - elif [ $CHAN -lt 2750 ]; then - BAND="B6" - elif [ $CHAN -lt 3450 ]; then - BAND="B7" - elif [ $CHAN -lt 3800 ]; then - BAND="B8" - elif [ $CHAN -lt 4150 ]; then - BAND="B9" - elif [ $CHAN -lt 4750 ]; then - BAND="B10" - elif [ $CHAN -lt 4950 ]; then - BAND="B11" - elif [ $CHAN -lt 5010 ]; then - BAND="-" - elif [ $CHAN -lt 5180 ]; then - BAND="B12" - elif [ $CHAN -lt 5280 ]; then - BAND="B13" - elif [ $CHAN -lt 5380 ]; then - BAND="B14" - elif [ $CHAN -lt 5730 ]; then - BAND="-" - elif [ $CHAN -lt 5850 ]; then - BAND="B17" - elif [ $CHAN -lt 6000 ]; then - BAND="B18" - elif [ $CHAN -lt 6150 ]; then - BAND="B19" - elif [ $CHAN -lt 6450 ]; then - BAND="B20" - elif [ $CHAN -lt 6600 ]; then - BAND="B21" - elif [ $CHAN -lt 7400 ]; then - BAND="B22" - elif [ $CHAN -lt 7500 ]; then - BAND="-" - elif [ $CHAN -lt 7700 ]; then - BAND="B23" - elif [ $CHAN -lt 8040 ]; then - BAND="B24" - elif [ $CHAN -lt 8690 ]; then - BAND="B25" - elif [ $CHAN -lt 9040 ]; then - BAND="B26" - elif [ $CHAN -lt 9210 ]; then - BAND="B27" - elif [ $CHAN -lt 9660 ]; then - BAND="B28" - elif [ $CHAN -lt 9770 ]; then - BAND="B29" - elif [ $CHAN -lt 9870 ]; then - BAND="B30" - elif [ $CHAN -lt 9920 ]; then - BAND="B31" - elif [ $CHAN -lt 10400 ]; then - BAND="B32" - elif [ $CHAN -lt 36000 ]; then - BAND="-" - elif [ $CHAN -lt 36200 ]; then - BAND="B33" - elif [ $CHAN -lt 36350 ]; then - BAND="B34" - elif [ $CHAN -lt 36950 ]; then - BAND="B35" - elif [ $CHAN -lt 37550 ]; then - BAND="B36" - elif [ $CHAN -lt 37750 ]; then - BAND="B37" - elif [ $CHAN -lt 38250 ]; then - BAND="B38" - elif [ $CHAN -lt 38650 ]; then - BAND="B39" - elif [ $CHAN -lt 39650 ]; then - BAND="B40" - elif [ $CHAN -lt 41590 ]; then - BAND="B41" - elif [ $CHAN -lt 43590 ]; then - BAND="B42" - elif [ $CHAN -lt 45590 ]; then - BAND="B43" - elif [ $CHAN -lt 46590 ]; then - BAND="B44" - elif [ $CHAN -lt 46790 ]; then - BAND="B45" - elif [ $CHAN -lt 54540 ]; then - BAND="B46" - elif [ $CHAN -lt 55240 ]; then - BAND="B47" - elif [ $CHAN -lt 56740 ]; then - BAND="B48" - elif [ $CHAN -lt 58240 ]; then - BAND="B49" - elif [ $CHAN -lt 59090 ]; then - BAND="B50" - elif [ $CHAN -lt 59140 ]; then - BAND="B51" - elif [ $CHAN -lt 60140 ]; then - BAND="B52" - elif [ $CHAN -lt 60255 ]; then - BAND="B53" - elif [ $CHAN -lt 65536 ]; then - BAND="-" - elif [ $CHAN -lt 66436 ]; then - BAND="B65" - elif [ $CHAN -lt 67336 ]; then - BAND="B66" - elif [ $CHAN -lt 67536 ]; then - BAND="B67" - elif [ $CHAN -lt 67836 ]; then - BAND="B68" - elif [ $CHAN -lt 68336 ]; then - BAND="B69" - elif [ $CHAN -lt 68586 ]; then - BAND="B70" - elif [ $CHAN -lt 68936 ]; then - BAND="B71" - elif [ $CHAN -lt 68986 ]; then - BAND="B72" - elif [ $CHAN -lt 69036 ]; then - BAND="B73" - elif [ $CHAN -lt 69466 ]; then - BAND="B74" - elif [ $CHAN -lt 70316 ]; then - BAND="B75" - elif [ $CHAN -lt 70366 ]; then - BAND="B76" - elif [ $CHAN -lt 70546 ]; then - BAND="B85" - elif [ $CHAN -lt 70596 ]; then - BAND="B87" - elif [ $CHAN -lt 70646 ]; then - BAND="B88" - else - BAND="-" - fi -} - -decode_nr5g() { - if [ $CHAN -lt 123400 ]; then - BAND="-" - elif [ $CHAN -le 130400 ]; then - BAND="n71" - elif [ $CHAN -lt 143400 ]; then - BAND="-" - elif [ $CHAN -lt 145600 ]; then - BAND="n29" - elif [ $CHAN -eq 145600 ]; then - BAND="n29|n85" - elif [ $CHAN -lt 145800 ]; then - BAND="n85" - elif [ $CHAN -eq 145800 ]; then - BAND="n12|n85" - elif [ $CHAN -lt 147600 ]; then - BAND="n12|n85" - elif [ $CHAN -lt 149200 ]; then - BAND="n12|n67|n85" - elif [ $CHAN -eq 149200 ]; then - BAND="n12|n13|n67|n85" - elif [ $CHAN -le 151200 ]; then - BAND="n13|n67" - elif [ $CHAN -lt 151600 ]; then - BAND="n67" - elif [ $CHAN -eq 151600 ]; then - BAND="n14|n28|n67" - elif [ $CHAN -le 153600 ]; then - BAND="n14|n28" - elif [ $CHAN -lt 158200 ]; then - BAND="n28" - elif [ $CHAN -eq 158200 ]; then - BAND="n14|n20|n28" - elif [ $CHAN -le 160600 ]; then - BAND="n20|n28" - elif [ $CHAN -le 164200 ]; then - BAND="n20" - elif [ $CHAN -lt 171800 ]; then - BAND="-" - elif [ $CHAN -lt 172000 ]; then - BAND="n26" - elif [ $CHAN -lt 173800 ]; then - BAND="n18|n26" - elif [ $CHAN -le 175000 ]; then - BAND="n5|n18|n26" - elif [ $CHAN -le 178800 ]; then - BAND="n5|n26" - elif [ $CHAN -lt 185000 ]; then - BAND="-" - elif [ $CHAN -le 192000 ]; then - BAND="n8" - elif [ $CHAN -lt 285400 ]; then - BAND="-" - elif [ $CHAN -lt 286400 ]; then - BAND="n51|n76|n91|n93" - elif [ $CHAN -eq 286400 ]; then - BAND="n50|n51|n75|n76|n91|92|n93|94" - elif [ $CHAN -lt 295000 ]; then - BAND="n50|n75|n92|n94" - elif [ $CHAN -eq 295000 ]; then - BAND="n50|n74|n75|n92|n94" - elif [ $CHAN -le 303400 ]; then - BAND="n50|n74|n75|n92|n94" - elif [ $CHAN -le 303600 ]; then - BAND="n74" - elif [ $CHAN -lt 305000 ]; then - BAND="-" - elif [ $CHAN -le 311800 ]; then - BAND="n24" - elif [ $CHAN -lt 361000 ]; then - BAND="-" - elif [ $CHAN -lt 376000 ]; then - BAND="n3" - elif [ $CHAN -eq 376000 ]; then - BAND="n3|n39" - elif [ $CHAN -le 384000 ]; then - BAND="n39" - elif [ $CHAN -lt 386000 ]; then - BAND="-" - elif [ $CHAN -le 398000 ]; then - BAND="n2|n25" - elif [ $CHAN -lt 399000 ]; then - BAND="n25" - elif [ $CHAN -eq 399000 ]; then - BAND="n25|n70" - elif [ $CHAN -lt 402000 ]; then - BAND="n70" - elif [ $CHAN -eq 402000 ]; then - BAND="n34|n70" - elif [ $CHAN -le 404000 ]; then - BAND="n34|n70" - elif [ $CHAN -le 405000 ]; then - BAND="n34" - elif [ $CHAN -lt 422000 ]; then - BAND="-" - elif [ $CHAN -le 434000 ]; then - BAND="n1|n65|n66" - elif [ $CHAN -le 440000 ]; then - BAND="n65|n66" - elif [ $CHAN -lt 460000 ]; then - BAND="-" - elif [ $CHAN -lt 470000 ]; then - BAND="n40" - elif [ $CHAN -eq 470000 ]; then - BAND="n30|n40" - elif [ $CHAN -le 472000 ]; then - BAND="n30|n40" - elif [ $CHAN -le 480000 ]; then - BAND="n40" - elif [ $CHAN -lt 496700 ]; then - BAND="-" - elif [ $CHAN -le 499000 ]; then - BAND="n53" - elif [ $CHAN -lt 499200 ]; then - BAND="-" - elif [ $CHAN -lt 514000 ]; then - BAND="n41|n90" - elif [ $CHAN -eq 514000 ]; then - BAND="n38|n41|n90" - elif [ $CHAN -lt 524000 ]; then - BAND="n38|n41|n90" - elif [ $CHAN -eq 524000 ]; then - BAND="n7|n38|n41|n90" - elif [ $CHAN -lt 538000 ]; then - BAND="n7|n41|n90" - elif [ $CHAN -eq 538000 ]; then - BAND="n7|n90" - elif [ $CHAN -lt 620000 ]; then - BAND="-" - elif [ $CHAN -lt 636667 ]; then - BAND="n77|n78" - elif [ $CHAN -le 646666 ]; then - BAND="n48|n77|n78" - elif [ $CHAN -le 653333 ]; then - BAND="n77|n78" - elif [ $CHAN -le 680000 ]; then - BAND="n77" - elif [ $CHAN -lt 693334 ]; then - BAND="-" - elif [ $CHAN -le 733333 ]; then - BAND="n79" - elif [ $CHAN -lt 743333 ]; then - BAND="-" - elif [ $CHAN -lt 795000 ]; then - BAND="n46" - elif [ $CHAN -eq 795000 ]; then - BAND="n46|n96" - elif [ $CHAN -le 875000 ]; then - BAND="n96" - else - BAND="-" - fi -} - -if [ -z "$CHAN" ]; then - BAND="-" -elif [ "$CHAN" -lt 123400 ]; then - decode_lte -elif [ "$CHAN" -le 875000 ]; then - decode_nr5g -else - BAND="-" -fi -echo $BAND -exit diff --git a/luci-app-cpe/root/usr/bin/encodemask b/luci-app-cpe/root/usr/bin/encodemask deleted file mode 100644 index 6b3ed14..0000000 --- a/luci-app-cpe/root/usr/bin/encodemask +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/lua - -mtab = {} -vtab = {1, 2, 4, 8} - -for i = 1, 32 do - mtab[i] = 0 -end - -numarg = #arg -for argval = 1, numarg do - band = arg[argval] - if tonumber(band) <= 128 then - idx = math.floor((band - 1) / 4) + 1 - idxr = 33 - idx - val = vtab[(band - ((idx - 1) * 4 ))] - mtab[idxr] = mtab[idxr] + val - end -end -for i = 1, 32 do - mtab[i] = string.format("%X", mtab[i]) -end - -print(table.concat(mtab)) diff --git a/luci-app-cpe/root/usr/bin/jkillall b/luci-app-cpe/root/usr/bin/jkillall deleted file mode 100644 index 3802082..0000000 --- a/luci-app-cpe/root/usr/bin/jkillall +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -LOOKFOR=$1 -KILLLIST=$(ps | grep $LOOKFOR) -echo "$KILLLIST" | while read line; do - if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then - PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") - kill $PIDV - fi -done \ No newline at end of file diff --git a/luci-app-cpe/root/usr/bin/rsrp2rssi b/luci-app-cpe/root/usr/bin/rsrp2rssi deleted file mode 100644 index 06ad5b6..0000000 --- a/luci-app-cpe/root/usr/bin/rsrp2rssi +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/lua - -rsrp = tonumber(arg[1]) -bw = tonumber(arg[2]) -if bw == 1.4 then - n = 6 -else - n = bw * 5 -end - -if tonumber(string.match(_VERSION, "%d+%.%d")) > 5.1 then - rssi = rsrp + (10 * math.log(n * 12, 10)) -else - rssi = rsrp + (10 * math.log10(n * 12)) -end -if rssi < -113 then - rssi = -113 -elseif rssi > -51 then - rssi = -51 -end -print(math.floor(rssi)) diff --git a/luci-app-cpe/root/usr/bin/set_gpio b/luci-app-cpe/root/usr/bin/set_gpio deleted file mode 100644 index 5fddfa7..0000000 --- a/luci-app-cpe/root/usr/bin/set_gpio +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -PIN=$1 -VALUE=$2 - -PIN_FILE=/sys/class/gpio/gpio$PIN - -if [ -z "$PIN" -o -z "$VALUE" ]; then - exit 1 -fi - -echo $PIN >/sys/class/gpio/export - -if [ $(cat $PIN_FILE/direction) = "out" ]; then - echo $VALUE >$PIN_FILE/value -fi - -echo $PIN >/sys/class/gpio/unexport \ No newline at end of file diff --git a/luci-app-cpe/root/usr/share/cpe/Fibocom b/luci-app-cpe/root/usr/share/cpe/Fibocom deleted file mode 100644 index 72bfe02..0000000 --- a/luci-app-cpe/root/usr/share/cpe/Fibocom +++ /dev/null @@ -1,285 +0,0 @@ -#!/bin/sh -ATPORT=1 - - - -# SIMCOM获取基站信息 -Fibocom_Cellinfo() -{ - #baseinfo.gcom - OX=$( sendat $ATPORT "ATI") - OX=$( sendat $ATPORT "AT+CGEQNEG=1") - - #cellinfo0.gcom - OX1=$( sendat $ATPORT "AT+COPS=3,0;+COPS?") - OX2=$( sendat $ATPORT "AT+COPS=3,2;+COPS?") - OX=$OX1" "$OX2 - - #cellinfo.gcom - OY1=$( sendat $ATPORT "AT+CREG=2;+CREG?;+CREG=0") - OY2=$( sendat $ATPORT "AT+CEREG=2;+CEREG?;+CEREG=0") - OY3=$( sendat $ATPORT "AT+C5GREG=2;+C5GREG?;+C5GREG=0") - OY=$OY1" "$OY2" "$OY3 - - - OXx=$OX - OX=$(echo $OX | tr 'a-z' 'A-Z') - OY=$(echo $OY | tr 'a-z' 'A-Z') - OX=$OX" "$OY - - #Debug "$OX" - #Debug "$OY" - - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - - if [ "x$COPSX" != "x" ]; then - COPS=$COPSX - fi - - COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - - if [ "x$COPSX" != "x" ]; then - COPS_MCC=${COPSX:0:3} - COPS_MNC=${COPSX:3:3} - if [ "$COPS" = "-" ]; then - COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data) - [ "x$COPS" = "x" ] && COPS="-" - fi - fi - - if [ "$COPS" = "-" ]; then - COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}') - if [ "x$COPS" = "x" ]; then - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - fi - fi - COPS_MNC=" "$COPS_MNC - - OX=$(echo "${OX//[ \"]/}") - CID="" - CID5="" - RAT="" - REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}") - if [ -n "$REGV" ]; then - LAC5=$(echo "$REGV" | cut -d, -f3) - LAC5=$LAC5" ($(printf "%d" 0x$LAC5))" - CID5=$(echo "$REGV" | cut -d, -f4) - CID5L=$(printf "%010X" 0x$CID5) - RNC5=${CID5L:1:6} - RNC5=$RNC5" ($(printf "%d" 0x$RNC5))" - CID5=${CID5L:7:3} - CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))" - RAT=$(echo "$REGV" | cut -d, -f5) - fi - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}") - REGFMT="3GPP" - if [ -z "$REGV" ]; then - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}") - REGFMT="SW" - fi - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - if [ $REGFMT = "3GPP" ]; then - CID=$(echo "$REGV" | cut -d, -f4) - else - CID=$(echo "$REGV" | cut -d, -f5) - fi - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:5} - RNC=$RNC" ($(printf "%d" 0x$RNC))" - CID=${CIDL:6:2} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - - else - REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}") - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - CID=$(echo "$REGV" | cut -d, -f4) - if [ ${#CID} -gt 4 ]; then - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:3} - CID=${CIDL:4:4} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - else - LAC="" - fi - else - LAC="" - fi - fi - REGSTAT=$(echo "$REGV" | cut -d, -f2) - if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then - COPS_MNC=$COPS_MNC" (Roaming)" - fi - if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then - LAC="4G $LAC, 5G $LAC5" - CID="4G $CID
      5G $CID5" - RNC="4G $RNC, 5G $RNC5" - elif [ -n "$CID5" ]; then - LAC=$LAC5 - CID=$CID5 - RNC=$RNC5 - fi - if [ -z "$LAC" ]; then - LAC="-" - CID="-" - RNC="-" - fi -} -Fibocom_SIMINFO() -{ - Debug "Fibocom_SIMINFO" - # 获取IMEI - IMEI=$( sendat $ATPORT "AT+CGSN" | sed -n '2p' ) - # 获取IMSI - IMSI=$( sendat $ATPORT "AT+CIMI" | sed -n '2p' ) - # 获取ICCID - ICCID=$( sendat $ATPORT "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" ) - # 获取电话号码 - phone=$( sendat $ATPORT "AT+CNUM" | grep "+CNUM:" ) -} - -#SIMCOM查找基站AT -Fibocom_AT() -{ - Debug "Fibocom_AT" - ATPORT - All_CSQ - Fibocom_SIMINFO - Fibocom_Cellinfo - - #温度 - OX=$( sendat $ATPORT "AT+CPMUTEMP") - TEMP=$(echo "$OX" | grep -o "+CPMUTEMP:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}") - if [ -n "$TEMP" ]; then - TEMP=$(echo $TEMP)$(printf "\xc2\xb0")"C" - fi - - - #基站信息 - OX=$( sendat $ATPORT "AT+CPSI?") - rec=$(echo "$OX" | grep "+CPSI:") - w=$(echo $rec |grep "NO SERVICE"| wc -l) - if [ $w -ge 1 ];then - Debug "NO SERVICE" - return - fi - w=$(echo $rec |grep "NR5G_"| wc -l) - if [ $w -ge 1 ];then - - w=$(echo $rec |grep "32768"| wc -l) - if [ $w -ge 1 ];then - Debug "-32768" - return - fi - - Debug "$rec" - rec1=${rec##*+CPSI:} - #echo "$rec1" - MODE="${rec1%%,*}" # MODE="NR5G" - rect1=${rec1#*,} - rect1s="${rect1%%,*}" #Online - rect2=${rect1#*,} - rect2s="${rect2%%,*}" #460-11 - rect3=${rect2#*,} - rect3s="${rect3%%,*}" #0xCFA102 - rect4=${rect3#*,} - rect4s="${rect4%%,*}" #55744245764 - rect5=${rect4#*,} - rect5s="${rect5%%,*}" #196 - rect6=${rect5#*,} - rect6s="${rect6%%,*}" #NR5G_BAND78 - rect7=${rect6#*,} - rect7s="${rect7%%,*}" #627264 - rect8=${rect7#*,} - rect8s="${rect8%%,*}" #-940 - rect9=${rect8#*,} - rect9s="${rect9%%,*}" #-110 - # "${rec1##*,}" #最后一位 - rect10=${rect9#*,} - rect10s="${rect10%%,*}" #最后一位 - PCI=$rect5s - LBAND="n"$(echo $rect6s | cut -d, -f0 | grep -o "BAND[0-9]\{1,3\}" | grep -o "[0-9]\+") - CHANNEL=$rect7s - RSCP=$(($(echo $rect8s | cut -d, -f0) / 10)) - ECIO=$(($(echo $rect9s | cut -d, -f0) / 10)) - if [ "$CSQ_PER" = "-" ]; then - CSQ_PER=$((100 - (($RSCP + 31) * 100/-125)))"%" - fi - SINR=$(($(echo $rect10s | cut -d, -f0) / 10))" dB" - fi - w=$(echo $rec |grep "LTE"|grep "EUTRAN"| wc -l) - if [ $w -ge 1 ];then - rec1=${rec#*EUTRAN-} - lte_band=${rec1%%,*} #EUTRAN-BAND - rec1=${rec1#*,} - rec1=${rec1#*,} - rec1=${rec1#*,} - rec1=${rec1#*,} - #rec1=${rec1#*,} - rec1=${rec1#*,} - lte_rssi=${rec1%%,*} #LTE_RSSI - lte_rssi=`expr $lte_rssi / 10` #LTE_RSSI - Debug "LTE_BAND=$lte_band LTE_RSSI=$lte_rssi" - if [ $rssi == 0 ];then - rssi=$lte_rssi - fi - fi - w=$(echo $rec |grep "WCDMA"| wc -l) - if [ $w -ge 1 ];then - w=$(echo $rec |grep "UNKNOWN"|wc -l) - if [ $w -ge 1 ];then - Debug "UNKNOWN BAND" - return - fi - fi - - - - - - - #CNMP - OX=$( sendat $ATPORT "AT+CNMP?") - CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") - if [ -n "$CNMP" ]; then - case $CNMP in - "2"|"55" ) - NETMODE="1" ;; - "13" ) - NETMODE="3" ;; - "14" ) - NETMODE="5" ;; - "38" ) - NETMODE="7" ;; - "71" ) - NETMODE="9" ;; - "109" ) - NETMODE="8" ;; - * ) - NETMODE="0" ;; - esac - fi - - # CMGRMI 信息 - OX=$( sendat $ATPORT "AT+CMGRMI=4") - CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':') - if [ -n "$CAINFO" ]; then - for CASV in $(echo "$CAINFO"); do - LBAND=$LBAND"
      B"$(echo "$CASV" | cut -d, -f4) - BW=$(echo "$CASV" | cut -d, -f5) - decode_bw - LBAND=$LBAND" (CA, Bandwidth $BW MHz)" - CHANNEL="$CHANNEL, "$(echo "$CASV" | cut -d, -f2) - PCI="$PCI, "$(echo "$CASV" | cut -d, -f7) - done - fi - -} \ No newline at end of file diff --git a/luci-app-cpe/root/usr/share/cpe/Quectel b/luci-app-cpe/root/usr/share/cpe/Quectel deleted file mode 100644 index 22974c1..0000000 --- a/luci-app-cpe/root/usr/share/cpe/Quectel +++ /dev/null @@ -1,507 +0,0 @@ -#!/bin/sh -ATPORT=1 -#Quectel -lte_bw() { - BW=$(echo $BW | grep -o "[0-5]\{1\}") - case $BW in - "0") - BW="1.4" ;; - "1") - BW="3" ;; - "2"|"3"|"4"|"5") - BW=$((($(echo $BW) - 1) * 5)) ;; - esac -} -#Quectel -nr_bw() { - BW=$(echo $BW | grep -o "[0-9]\{1,2\}") - case $BW in - "0"|"1"|"2"|"3"|"4"|"5") - BW=$((($(echo $BW) + 1) * 5)) ;; - "6"|"7"|"8"|"9"|"10"|"11"|"12") - BW=$((($(echo $BW) - 2) * 10)) ;; - "13") - BW="200" ;; - "14") - BW="400" ;; - esac -} - -#ѯϢǿ -All_CSQ() -{ - Debug "All_CSQ" - #ź - OX=$( sendat $ATPORT "AT+CSQ" |grep "+CSQ:") - OX=$(echo $OX | tr 'a-z' 'A-Z') - CSQ=$(echo "$OX" | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") - if [ $CSQ = "99" ]; then - CSQ="" - fi - if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi -} - -Quectel_SIMINFO() -{ - Debug "Quectel_SIMINFO" - # ȡIMEI - IMEI=$( sendat $ATPORT "AT+CGSN" | sed -n '2p' ) - # ȡIMSI - IMSI=$( sendat $ATPORT "AT+CIMI" | sed -n '2p' ) - # ȡICCID - ICCID=$( sendat $ATPORT "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" ) - # ȡ绰 - phone=$( sendat $ATPORT "AT+CNUM" | grep "+CNUM:" ) - -} -# SIMCOMȡվϢ -Quectel_Cellinfo() -{ - # return - #cellinfo0.gcom - OX1=$( sendat $ATPORT "AT+COPS=3,0;+COPS?") - OX2=$( sendat $ATPORT "AT+COPS=3,2;+COPS?") - OX=$OX1" "$OX2 - - #cellinfo.gcom - OY1=$( sendat $ATPORT "AT+CREG=2;+CREG?;+CREG=0") - OY2=$( sendat $ATPORT "AT+CEREG=2;+CEREG?;+CEREG=0") - OY3=$( sendat $ATPORT "AT+C5GREG=2;+C5GREG?;+C5GREG=0") - OY=$OY1" "$OY2" "$OY3 - - - OXx=$OX - OX=$(echo $OX | tr 'a-z' 'A-Z') - OY=$(echo $OY | tr 'a-z' 'A-Z') - OX=$OX" "$OY - - #Debug "$OX" - #Debug "$OY" - - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - - if [ "x$COPSX" != "x" ]; then - COPS=$COPSX - fi - - COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - - if [ "x$COPSX" != "x" ]; then - COPS_MCC=${COPSX:0:3} - COPS_MNC=${COPSX:3:3} - if [ "$COPS" = "-" ]; then - COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data) - [ "x$COPS" = "x" ] && COPS="-" - fi - fi - - if [ "$COPS" = "-" ]; then - COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}') - if [ "x$COPS" = "x" ]; then - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - fi - fi - COPS_MNC=" "$COPS_MNC - - OX=$(echo "${OX//[ \"]/}") - CID="" - CID5="" - RAT="" - REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}") - if [ -n "$REGV" ]; then - LAC5=$(echo "$REGV" | cut -d, -f3) - LAC5=$LAC5" ($(printf "%d" 0x$LAC5))" - CID5=$(echo "$REGV" | cut -d, -f4) - CID5L=$(printf "%010X" 0x$CID5) - RNC5=${CID5L:1:6} - RNC5=$RNC5" ($(printf "%d" 0x$RNC5))" - CID5=${CID5L:7:3} - CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))" - RAT=$(echo "$REGV" | cut -d, -f5) - fi - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}") - REGFMT="3GPP" - if [ -z "$REGV" ]; then - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}") - REGFMT="SW" - fi - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - if [ $REGFMT = "3GPP" ]; then - CID=$(echo "$REGV" | cut -d, -f4) - else - CID=$(echo "$REGV" | cut -d, -f5) - fi - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:5} - RNC=$RNC" ($(printf "%d" 0x$RNC))" - CID=${CIDL:6:2} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - - else - REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}") - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - CID=$(echo "$REGV" | cut -d, -f4) - if [ ${#CID} -gt 4 ]; then - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:3} - CID=${CIDL:4:4} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - else - LAC="" - fi - else - LAC="" - fi - fi - REGSTAT=$(echo "$REGV" | cut -d, -f2) - if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then - COPS_MNC=$COPS_MNC" (Roaming)" - fi - if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then - LAC="4G $LAC, 5G $LAC5" - CID="4G $CID
      5G $CID5" - RNC="4G $RNC, 5G $RNC5" - elif [ -n "$CID5" ]; then - LAC=$LAC5 - CID=$CID5 - RNC=$RNC5 - fi - if [ -z "$LAC" ]; then - LAC="-" - CID="-" - RNC="-" - fi -} - -#Quectel˾һվAT -Quectel_AT() -{ - Debug "Quectel_AT" - ATPORT - - Quectel_SIMINFO - All_CSQ - - Quectel_Cellinfo - - # - OX=$( sendat $ATPORT 'AT+QENG="servingcell"' | grep "+QENG:" ) - NR_NSA=$(echo $OX | grep -o -i "+QENG:[ ]\?\"NR5G-NSA\",") - NR_SA=$(echo $OX | grep -o -i "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",") - if [ -n "$NR_NSA" ]; then - QENG=",,"$(echo $OX" " | grep -o -i "+QENG: \"LTE\".\+\"NR5G-NSA\"," | tr " " ",") - QENG5=$(echo $OX | grep -o -i "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,5\},[-0-9]\{1,3\},-[0-9]\{2,3\},[0-9]\{1,7\},[0-9]\{1,3\}.\{1,6\}") - if [ -z "$QENG5" ]; then - QENG5=$(echo $OX | grep -o -i "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,3\},[-0-9]\{1,3\},-[0-9]\{2,3\}") - if [ -n "$QENG5" ]; then - QENG5=$QENG5",," - fi - fi - elif [ -n "$NR_SA" ]; then - QENG=$(echo $NR_SA | tr " " ",") - QENG5=$(echo $OX | grep -o -i "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",[ 0-9]\{3,4\},[0-9]\{2,3\},[0-9A-F]\{1,10\},[0-9]\{1,5\},[0-9A-F]\{2,6\},[0-9]\{6,7\},[0-9]\{1,3\},[0-9]\{1,2\},-[0-9]\{2,5\},-[0-9]\{2,3\},[-0-9]\{1,3\}") - else - QENG=$(echo $OX" " | grep -o -i "+QENG: [^ ]\+ " | tr " " ",") - fi - - - # Debug "$QENG" - # Debug "$QENG5" - - RAT=$(echo $QENG | cut -d, -f4 | grep -o "[-A-Z5]\{3,7\}") - case $RAT in - "GSM") - MODE="GSM" - ;; - "WCDMA") - MODE="WCDMA" - CHANNEL=$(echo $QENG | cut -d, -f9) - RSCP=$(echo $QENG | cut -d, -f12) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - ECIO=$(echo $QENG | cut -d, -f13) - ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") - ;; - "LTE"|"CAT-M"|"CAT-NB") - MODE=$(echo $QENG | cut -d, -f5 | grep -o "[DFT]\{3\}") - if [ -n "$MODE" ]; then - MODE="$RAT $MODE" - else - MODE="$RAT" - fi - PCI=$(echo $QENG | cut -d, -f9) - CHANNEL=$(echo $QENG | cut -d, -f10) - LBAND=$(echo $QENG | cut -d, -f11 | grep -o "[0-9]\{1,3\}") - BW=$(echo $QENG | cut -d, -f12) - lte_bw - BWU=$BW - BW=$(echo $QENG | cut -d, -f13) - lte_bw - BWD=$BW - if [ -z "$BWD" ]; then - BWD="unknown" - fi - if [ -z "$BWU" ]; then - BWU="unknown" - fi - if [ -n "$LBAND" ]; then - LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" - fi - RSRP=$(echo $QENG | cut -d, -f15 | grep -o "[0-9]\{1,3\}") - if [ -n "$RSRP" ]; then - RSCP="-"$RSRP - RSRPLTE=$RSCP - fi - RSRQ=$(echo $QENG | cut -d, -f16 | grep -o "[0-9]\{1,3\}") - if [ -n "$RSRQ" ]; then - ECIO="-"$RSRQ - fi - RSSI=$(echo $QENG | cut -d, -f17 | grep -o "\-[0-9]\{1,3\}") - if [ -n "$RSSI" ]; then - CSQ_RSSI=$RSSI" dBm" - fi - SINRR=$(echo $QENG | cut -d, -f18 | grep -o "[0-9]\{1,3\}") - if [ -n "$SINRR" ]; then - if [ $SINRR -le 25 ]; then - SINR=$((($(echo $SINRR) * 2) -20))" dB" - fi - fi - - if [ -n "$NR_NSA" ]; then - MODE="LTE/NR EN-DC" - echo "0" > /tmp/modnetwork - if [ -n "$QENG5" ] && [ -n "$LBAND" ] && [ "$RSCP" != "-" ] && [ "$ECIO" != "-" ]; then - PCI="$PCI, "$(echo $QENG5 | cut -d, -f4) - SCHV=$(echo $QENG5 | cut -d, -f8) - SLBV=$(echo $QENG5 | cut -d, -f9) - BW=$(echo $QENG5 | cut -d, -f10 | grep -o "[0-9]\{1,3\}") - if [ -n "$SLBV" ]; then - LBAND=$LBAND"
      n"$SLBV - if [ -n "$BW" ]; then - nr_bw - LBAND=$LBAND" (Bandwidth $BW MHz)" - fi - if [ "$SCHV" -ge 123400 ]; then - CHANNEL=$CHANNEL", "$SCHV - else - CHANNEL=$CHANNEL", -" - fi - else - LBAND=$LBAND"
      nxx (unknown NR5G band)" - CHANNEL=$CHANNEL", -" - fi - RSCP=$RSCP" dBm
      "$(echo $QENG5 | cut -d, -f5) - SINRR=$(echo $QENG5 | cut -d, -f6 | grep -o "[0-9]\{1,3\}") - if [ -n "$SINRR" ]; then - if [ $SINRR -le 30 ]; then - SINR=$SINR"
      "$((($(echo $SINRR) * 2) -20))" dB" - fi - fi - ECIO=$ECIO" (4G) dB
      "$(echo $QENG5 | cut -d, -f7)" (5G) " - fi - fi - if [ -z "$LBAND" ]; then - LBAND="-" - else - if [ -n "$QCA" ]; then - QCA=$(echo $QCA | grep -o "\"S[CS]\{2\}\"[-0-9A-Z,\"]\+") - for QCAL in $(echo "$QCA"); do - if [ $(echo "$QCAL" | cut -d, -f7) = "2" ]; then - SCHV=$(echo $QCAL | cut -d, -f2 | grep -o "[0-9]\+") - SRATP="B" - if [ -n "$SCHV" ]; then - CHANNEL="$CHANNEL, $SCHV" - if [ "$SCHV" -gt 123400 ]; then - SRATP="n" - fi - fi - SLBV=$(echo $QCAL | cut -d, -f6 | grep -o "[0-9]\{1,2\}") - if [ -n "$SLBV" ]; then - LBAND=$LBAND"
      "$SRATP$SLBV - BWD=$(echo $QCAL | cut -d, -f3 | grep -o "[0-9]\{1,3\}") - if [ -n "$BWD" ]; then - UPDOWN=$(echo $QCAL | cut -d, -f13) - case "$UPDOWN" in - "UL" ) - CATYPE="CA"$(printf "\xe2\x86\x91") ;; - "DL" ) - CATYPE="CA"$(printf "\xe2\x86\x93") ;; - * ) - CATYPE="CA" ;; - esac - if [ $BWD -gt 14 ]; then - LBAND=$LBAND" ("$CATYPE", Bandwidth "$(($(echo $BWD) / 5))" MHz)" - else - LBAND=$LBAND" ("$CATYPE", Bandwidth 1.4 MHz)" - fi - fi - LBAND=$LBAND - fi - PCI="$PCI, "$(echo $QCAL | cut -d, -f8) - fi - done - fi - fi - if [ $RAT = "CAT-M" ] || [ $RAT = "CAT-NB" ]; then - LBAND="B$(echo $QENG | cut -d, -f11) ($RAT)" - fi - ;; - "NR5G-SA") - MODE="NR5G-SA" - if [ -n "$QENG5" ]; then - #AT+qnwcfg="NR5G_AMBR" #ѯٶ - MODE="$RAT $(echo $QENG5 | cut -d, -f4)" - PCI=$(echo $QENG5 | cut -d, -f8) - CHANNEL=$(echo $QENG5 | cut -d, -f10) - LBAND=$(echo $QENG5 | cut -d, -f11) - BW=$(echo $QENG5 | cut -d, -f12) - nr_bw - LBAND="n"$LBAND" (Bandwidth $BW MHz)" - RSCP=$(echo $QENG5 | cut -d, -f13) - ECIO=$(echo $QENG5 | cut -d, -f14) - if [ "$CSQ_PER" = "-" ]; then - RSSI=$(rsrp2rssi $RSCP $BW) - CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" - CSQ=$((($RSSI + 113) / 2)) - CSQ_RSSI=$RSSI" dBm" - fi - SINRR=$(echo $QENG5 | cut -d, -f15 | grep -o "[0-9]\{1,3\}") - if [ -n "$SINRR" ]; then - if [ $SINRR -le 30 ]; then - SINR=$((($(echo $SINRR) * 2) -20))" dB" - fi - fi - fi - ;; - esac - - - - - - # - OX=$( sendat $ATPORT "AT+QCAINFO" | grep "+QCAINFO:" ) - QCA=$(echo $OX" " | grep -o -i "+QCAINFO: \"S[CS]\{2\}\".\+NWSCANMODE" | tr " " ",") - - - # - OX=$( sendat $ATPORT 'AT+QCFG="nwscanmode"' | grep "+QCAINFO:" ) - QNSM=$(echo $OX | grep -o -i "+QCFG: \"NWSCANMODE\",[0-9]") - QNSM=$(echo "$QNSM" | grep -o "[0-9]") - if [ -n "$QNSM" ]; then - MODTYPE="6" - case $QNSM in - "0" ) - NETMODE="1" ;; - "1" ) - NETMODE="3" ;; - "2"|"5" ) - NETMODE="5" ;; - "3" ) - NETMODE="7" ;; - esac - fi - if [ -n "$QNWP" ]; then - MODTYPE="6" - case $QNWP in - "AUTO" ) - NETMODE="1" ;; - "WCDMA" ) - NETMODE="5" ;; - "LTE" ) - NETMODE="7" ;; - "LTE:NR5G" ) - NETMODE="8" ;; - "NR5G" ) - NETMODE="9" ;; - esac - fi - - - # - OX=$( sendat $ATPORT 'AT+QNWPREFCFG="mode_pref"' | grep "+QNWPREFCFG:" ) - QNWP=$(echo $OX | grep -o -i "+QNWPREFCFG: \"MODE_PREF\",[A-Z5:]\+" | cut -d, -f2) - - #¶ - OX=$( sendat $ATPORT 'AT+QTEMP' | grep "+QTEMP:" ) - QTEMP=$(echo $OX | grep -o -i "+QTEMP: [0-9]\{1,3\}") - if [ -z "$QTEMP" ]; then - QTEMP=$(echo $OX | grep -o -i "+QTEMP:[ ]\?\"XO[_-]THERM[_-][^,]\+,[\"]\?[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") - fi - if [ -z "$QTEMP" ]; then - QTEMP=$(echo $OX | grep -o -i "+QTEMP:[ ]\?\"MDM-CORE-USR.\+[0-9]\{1,3\}\"" | cut -d\" -f4) - fi - if [ -z "$QTEMP" ]; then - QTEMP=$(echo $OX | grep -o -i "+QTEMP:[ ]\?\"MDMSS.\+[0-9]\{1,3\}\"" | cut -d\" -f4) - fi - if [ -n "$QTEMP" ]; then - CTEMP=$(echo $QTEMP | grep -o -i "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C" - fi - - - - # - OX=$( sendat $ATPORT "AT+QRSRP" | grep "+QRSRP:" ) - QRSRP=$(echo "$OX" | grep -o -i "+QRSRP:[^,]\+,-[0-9]\{1,5\},-[0-9]\{1,5\},-[0-9]\{1,5\}[^ ]*") - if [ -n "$QRSRP" ] && [ "$RAT" != "WCDMA" ]; then - QRSRP1=$(echo $QRSRP | cut -d, -f1 | grep -o "[-0-9]\+") - QRSRP2=$(echo $QRSRP | cut -d, -f2) - QRSRP3=$(echo $QRSRP | cut -d, -f3) - QRSRP4=$(echo $QRSRP | cut -d, -f4) - QRSRPtype=$(echo $QRSRP | cut -d, -f5) - if [ "$QRSRPtype" == "NR5G" ]; then - if [ -n "$NR_SA" ]; then - RSCP=$QRSRP1 - if [ -n "$QRPRP2" -a "$QRSRP2" != "-32768" ]; then - RSCP1="RxD "$QRSRP2 - fi - if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then - RSCP=$RSCP" dBm
      "$QRSRP3 - fi - if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then - RSCP1="RxD "$QRSRP4 - fi - else - RSCP=$RSRPLTE - if [ -n "$QRSRP1" -a "$QRSRP1" != "-32768" ]; then - RSCP=$RSCP" (4G) dBm
      "$QRSRP1 - if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then - RSCP="$RSCP,$QRSRP2" - if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then - RSCP="$RSCP,$QRSRP3" - if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then - RSCP="$RSCP,$QRSRP4" - fi - fi - RSCP=$RSCP" (5G) " - fi - fi - fi - elif [ "$QRSRP2$QRSRP3$QRSRP4" != "-44-44-44" -a -z "$QENG5" ]; then - RSCP=$QRSRP1 - if [ "$QRSRP3$QRSRP4" == "-140-140" -o "$QRSRP3$QRSRP4" == "-44-44" -o "$QRSRP3$QRSRP4" == "-32768-32768" ]; then - RSCP1="RxD "$(echo $QRSRP | cut -d, -f2) - else - RSCP=$RSCP" dBm (RxD "$QRSRP2" dBm)
      "$QRSRP3 - RSCP1="RxD "$QRSRP4 - fi - fi - fi - - -} \ No newline at end of file diff --git a/luci-app-cpe/root/usr/share/cpe/SIMCOM b/luci-app-cpe/root/usr/share/cpe/SIMCOM deleted file mode 100644 index 4d1cd41..0000000 --- a/luci-app-cpe/root/usr/share/cpe/SIMCOM +++ /dev/null @@ -1,303 +0,0 @@ -#!/bin/sh -ATPORT=1 - -#查询信息强度 -All_CSQ() -{ - Debug "All_CSQ" - #信号 - OX=$( sendat $ATPORT "AT+CSQ" |grep "+CSQ:") - OX=$(echo $OX | tr 'a-z' 'A-Z') - CSQ=$(echo "$OX" | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") - if [ $CSQ = "99" ]; then - CSQ="" - fi - if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi -} - -# SIMCOM获取基站信息 -SIMCOM_Cellinfo() -{ - #baseinfo.gcom - OX=$( sendat 2 "ATI") - OX=$( sendat 2 "AT+CGEQNEG=1") - - #cellinfo0.gcom - OX1=$( sendat 2 "AT+COPS=3,0;+COPS?") - OX2=$( sendat 2 "AT+COPS=3,2;+COPS?") - OX=$OX1" "$OX2 - - #cellinfo.gcom - OY1=$( sendat 2 "AT+CREG=2;+CREG?;+CREG=0") - OY2=$( sendat 2 "AT+CEREG=2;+CEREG?;+CEREG=0") - OY3=$( sendat 2 "AT+C5GREG=2;+C5GREG?;+C5GREG=0") - OY=$OY1" "$OY2" "$OY3 - - - OXx=$OX - OX=$(echo $OX | tr 'a-z' 'A-Z') - OY=$(echo $OY | tr 'a-z' 'A-Z') - OX=$OX" "$OY - - #Debug "$OX" - #Debug "$OY" - - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - - if [ "x$COPSX" != "x" ]; then - COPS=$COPSX - fi - - COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - - if [ "x$COPSX" != "x" ]; then - COPS_MCC=${COPSX:0:3} - COPS_MNC=${COPSX:3:3} - if [ "$COPS" = "-" ]; then - COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data) - [ "x$COPS" = "x" ] && COPS="-" - fi - fi - - if [ "$COPS" = "-" ]; then - COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}') - if [ "x$COPS" = "x" ]; then - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - fi - fi - COPS_MNC=" "$COPS_MNC - - OX=$(echo "${OX//[ \"]/}") - CID="" - CID5="" - RAT="" - REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}") - if [ -n "$REGV" ]; then - LAC5=$(echo "$REGV" | cut -d, -f3) - LAC5=$LAC5" ($(printf "%d" 0x$LAC5))" - CID5=$(echo "$REGV" | cut -d, -f4) - CID5L=$(printf "%010X" 0x$CID5) - RNC5=${CID5L:1:6} - RNC5=$RNC5" ($(printf "%d" 0x$RNC5))" - CID5=${CID5L:7:3} - CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))" - RAT=$(echo "$REGV" | cut -d, -f5) - fi - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}") - REGFMT="3GPP" - if [ -z "$REGV" ]; then - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}") - REGFMT="SW" - fi - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - if [ $REGFMT = "3GPP" ]; then - CID=$(echo "$REGV" | cut -d, -f4) - else - CID=$(echo "$REGV" | cut -d, -f5) - fi - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:5} - RNC=$RNC" ($(printf "%d" 0x$RNC))" - CID=${CIDL:6:2} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - - else - REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}") - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - CID=$(echo "$REGV" | cut -d, -f4) - if [ ${#CID} -gt 4 ]; then - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:3} - CID=${CIDL:4:4} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - else - LAC="" - fi - else - LAC="" - fi - fi - REGSTAT=$(echo "$REGV" | cut -d, -f2) - if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then - COPS_MNC=$COPS_MNC" (Roaming)" - fi - if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then - LAC="4G $LAC, 5G $LAC5" - CID="4G $CID
      5G $CID5" - RNC="4G $RNC, 5G $RNC5" - elif [ -n "$CID5" ]; then - LAC=$LAC5 - CID=$CID5 - RNC=$RNC5 - fi - if [ -z "$LAC" ]; then - LAC="-" - CID="-" - RNC="-" - fi -} -SIMCOM_SIMINFO() -{ - Debug "Quectel_SIMINFO" - # 获取IMEI - IMEI=$( sendat $ATPORT "AT+CGSN" | sed -n '2p' ) - # 获取IMSI - IMSI=$( sendat $ATPORT "AT+CIMI" | sed -n '2p' ) - # 获取ICCID - ICCID=$( sendat $ATPORT "AT+ICCID" | grep -o "+ICCID:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}" ) - # 获取电话号码 - phone=$( sendat $ATPORT "AT+CNUM" | grep "+CNUM:" ) -} -#SIMCOM查找基站AT -SIMCOM_AT() -{ - Debug "SIMCOM_AT" - ATPORT - All_CSQ - SIMCOM_SIMINFO - SIMCOM_Cellinfo - - #温度 - OX=$( sendat $ATPORT "AT+CPMUTEMP") - TEMP=$(echo "$OX" | grep -o "+CPMUTEMP:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}") - if [ -n "$TEMP" ]; then - TEMP=$(echo $TEMP)$(printf "\xc2\xb0")"C" - fi - - - #基站信息 - OX=$( sendat $ATPORT "AT+CPSI?") - rec=$(echo "$OX" | grep "+CPSI:") - w=$(echo $rec |grep "NO SERVICE"| wc -l) - if [ $w -ge 1 ];then - Debug "NO SERVICE" - return - fi - w=$(echo $rec |grep "NR5G_"| wc -l) - if [ $w -ge 1 ];then - - w=$(echo $rec |grep "32768"| wc -l) - if [ $w -ge 1 ];then - Debug "-32768" - return - fi - - Debug "$rec" - rec1=${rec##*+CPSI:} - #echo "$rec1" - MODE="${rec1%%,*}" # MODE="NR5G" - rect1=${rec1#*,} - rect1s="${rect1%%,*}" #Online - rect2=${rect1#*,} - rect2s="${rect2%%,*}" #460-11 - rect3=${rect2#*,} - rect3s="${rect3%%,*}" #0xCFA102 - rect4=${rect3#*,} - rect4s="${rect4%%,*}" #55744245764 - rect5=${rect4#*,} - rect5s="${rect5%%,*}" #196 - rect6=${rect5#*,} - rect6s="${rect6%%,*}" #NR5G_BAND78 - rect7=${rect6#*,} - rect7s="${rect7%%,*}" #627264 - rect8=${rect7#*,} - rect8s="${rect8%%,*}" #-940 - rect9=${rect8#*,} - rect9s="${rect9%%,*}" #-110 - # "${rec1##*,}" #最后一位 - rect10=${rect9#*,} - rect10s="${rect10%%,*}" #最后一位 - PCI=$rect5s - LBAND="n"$(echo $rect6s | cut -d, -f0 | grep -o "BAND[0-9]\{1,3\}" | grep -o "[0-9]\+") - CHANNEL=$rect7s - RSCP=$(($(echo $rect8s | cut -d, -f0) / 10)) - ECIO=$(($(echo $rect9s | cut -d, -f0) / 10)) - if [ "$CSQ_PER" = "-" ]; then - CSQ_PER=$((100 - (($RSCP + 31) * 100/-125)))"%" - fi - SINR=$(($(echo $rect10s | cut -d, -f0) / 10))" dB" - fi - w=$(echo $rec |grep "LTE"|grep "EUTRAN"| wc -l) - if [ $w -ge 1 ];then - rec1=${rec#*EUTRAN-} - lte_band=${rec1%%,*} #EUTRAN-BAND - rec1=${rec1#*,} - rec1=${rec1#*,} - rec1=${rec1#*,} - rec1=${rec1#*,} - #rec1=${rec1#*,} - rec1=${rec1#*,} - lte_rssi=${rec1%%,*} #LTE_RSSI - lte_rssi=`expr $lte_rssi / 10` #LTE_RSSI - Debug "LTE_BAND=$lte_band LTE_RSSI=$lte_rssi" - if [ $rssi == 0 ];then - rssi=$lte_rssi - fi - fi - w=$(echo $rec |grep "WCDMA"| wc -l) - if [ $w -ge 1 ];then - w=$(echo $rec |grep "UNKNOWN"|wc -l) - if [ $w -ge 1 ];then - Debug "UNKNOWN BAND" - return - fi - fi - - - - - - - #CNMP - OX=$( sendat $ATPORT "AT+CNMP?") - CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") - if [ -n "$CNMP" ]; then - case $CNMP in - "2"|"55" ) - NETMODE="1" ;; - "13" ) - NETMODE="3" ;; - "14" ) - NETMODE="5" ;; - "38" ) - NETMODE="7" ;; - "71" ) - NETMODE="9" ;; - "109" ) - NETMODE="8" ;; - * ) - NETMODE="0" ;; - esac - fi - - # CMGRMI 信息 - OX=$( sendat $ATPORT "AT+CMGRMI=4") - CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':') - if [ -n "$CAINFO" ]; then - for CASV in $(echo "$CAINFO"); do - LBAND=$LBAND"
      B"$(echo "$CASV" | cut -d, -f4) - BW=$(echo "$CASV" | cut -d, -f5) - decode_bw - LBAND=$LBAND" (CA, Bandwidth $BW MHz)" - CHANNEL="$CHANNEL, "$(echo "$CASV" | cut -d, -f2) - PCI="$PCI, "$(echo "$CASV" | cut -d, -f7) - done - fi - -} diff --git a/luci-app-cpe/root/usr/share/cpe/atcmd.sh b/luci-app-cpe/root/usr/share/cpe/atcmd.sh deleted file mode 100644 index 989adab..0000000 --- a/luci-app-cpe/root/usr/share/cpe/atcmd.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -rec=$(sendat $1 $2) -echo $rec >> /tmp/result.at \ No newline at end of file diff --git a/luci-app-cpe/root/usr/share/cpe/cpedebug b/luci-app-cpe/root/usr/share/cpe/cpedebug deleted file mode 100644 index 16d59fa..0000000 --- a/luci-app-cpe/root/usr/share/cpe/cpedebug +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -en=1 #调试开关:0关闭,1打开 ,2输出到文件 -outfile="/tmp/cpe.log" #输出文件 -#日志信息 -Debug() -{ - tim=$(date "+%Y-%m-%d %H:%M:%S") #获取系统时间 - if [ $en == 1 ]; then - echo $tim $1 #打印输出 - elif [ $en == 2 ]; then - echo $tim $1 >> $outfile #输出到文件 - fi -} -ATPORT() -{ - MODEMNAME="ALL" - # ATPORT=$(uci -q get modem.@ndis[0].tyyusb) - lsusb=$( lsusb ) - RDFM650=$(echo "$lsusb" | grep "ID 2cb7:0a05 " | wc -l) - if [ "$RDFM650" == 1 ]; then - ATPORT=0 - MODEMNAME="FM650CN" - else - ATPORT=2 - fi -} \ No newline at end of file diff --git a/luci-app-cpe/root/usr/share/cpe/delatcmd.sh b/luci-app-cpe/root/usr/share/cpe/delatcmd.sh deleted file mode 100644 index dd131f0..0000000 --- a/luci-app-cpe/root/usr/share/cpe/delatcmd.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -rm -f /tmp/result.at \ No newline at end of file diff --git a/luci-app-cpe/root/usr/share/cpe/rssi b/luci-app-cpe/root/usr/share/cpe/rssi deleted file mode 100644 index 0131323..0000000 --- a/luci-app-cpe/root/usr/share/cpe/rssi +++ /dev/null @@ -1,418 +0,0 @@ -#!/bin/sh -source /usr/share/cpe/cpedebug -source /usr/share/cpe/SIMCOM -source /usr/share/cpe/Quectel -source /usr/share/cpe/Fibocom - -#初值化数据结构 -InitData() -{ - Date='' - CHANNEL="-" - ECIO="-" - RSCP="-" - ECIO1=" " - RSCP1=" " - NETMODE="-" - LBAND="-" - PCI="-" - CTEMP="-" - MODE="-" - SINR="-" - IMEI='-' - IMSI='-' - ICCID='-' - phone='-' - conntype='' - Model='' - - -} -#写数据 -SETData() -{ - { - echo $Model #'RM520N-GL' - echo $conntype #'conntype' - echo '1e0e:9001' - echo $COPS #运营商 - echo 'ttyUSB2' #端口 - echo $TEMP #温度 - echo 'QMI' #协议 - echo '---------------------------------' - echo $IMEI #imei - echo $IMSI #imsi - echo $ICCID #iccid - echo $phone #phone - echo '---------------------------------' - - echo $MODE - echo $CSQ - echo $CSQ_PER - echo $CSQ_RSSI - echo $ECIO #参考信号接收质量 RSRQ ecio - echo $ECIO1 #参考信号接收质量 RSRQ ecio1 - echo $RSCP #参考信号接收功率 RSRP rscp0 - echo $RSCP1 #参考信号接收功率 RSRP rscp1 - echo $SINR #信噪比 SINR rv["sinr"] - echo $NETMODE #连接状态监控 rv["netmode"] - echo '---------------------------------' - - - echo $COPS_MCC #MCC - echo $$COPS_MNC #MNC - echo $LAC #eNB ID - echo '' #LAC_NUM - echo $RNC #TAC - echo '' #RNC_NUM - echo $CID - echo '' #CID_NUM - echo $LBAND - echo $CHANNEL - echo $PCI - - echo $Date - - - - echo $MODTYPE - echo $QTEMP - - } > /tmp/cpe_cell.file -} -ATPORT=1 - -# 自动处理模块信号 -AUTO_CPE() -{ - Debug "------------------------------端口$ATPORT---------------------------" - Debug "AUTO_CPE" - Date=$(date "+%Y-%m-%d %H:%M:%S") - - - #检测设备是否准备好 - rec=$(sendat $ATPORT "AT" 500 |grep OK |wc -l) - if [ $rec == "1" ];then - sleep 1s - else - sleep 5s - return - fi - #读取模块信息 - # if [ "$conntype" == "" ]; then - # { - # Debug "计算模块" - # ATATI=$( sendat $ATPORT "ATI") - # Getconntype=$(echo "$ATATI" | sed -n '2p') - # if [ "$Getconntype" == "" ]; then - # { - # sleep 5s - # return - # } - # fi - # Model=$(echo "$ATATI" | sed -n '3p') - # conntype=$Getconntype - # } - # fi - - Debug "读取模块信息 计算模块" - ATATI=$( sendat $ATPORT "ATI") - Getconntype=$(echo "$ATATI" | sed -n '2p') - if [ "$Getconntype" == "" ]; then - { - sleep 5s - return - } - fi - Model=$(echo "$ATATI" | sed -n '3p') - conntype=$Getconntype - - cpin=$( sendat $ATPORT "at+cpin?") - ERR=$(echo "$cpin" | grep "ERROR") - if [ ! -z "$ERR" ]; then # No SIM - Debug "No SIM" - sleep 5s - return - fi - RDY=$(echo "$cpin" | grep "READY") - if [ -z "$RDY" ]; then # SIM Locked - Debug "Correct Pin" - sleep 5s - return - else - Debug "Not Locked" - fi - #执行对应模块 - if [ $(echo $conntype |grep "Quectel"| wc -l) -ge 1 ];then - { - Quectel_AT - } - elif [ $(echo $conntype |grep "SIMCOM"| wc -l) -ge 1 ];then - { - SIMCOM_AT - } - elif [ $(echo $conntype |grep "Fibocom"| wc -l) -ge 1 ];then - { - Fibocom_AT - } - else - { - Debug "null " - } - fi -} -#重新联网 -modem_reset() -{ - - echo "Abnormal network restart" - lsusb=$( lsusb ) - RDFM650=$(echo "$lsusb" | grep "ID 2cb7:0a05 " | wc -l) - echo "RDFM650 $RDFM650" - if [ "$RDFM650" == 1 ]; then - { - GTRNDIS=$(sendat $ATPORT "AT+GTRNDIS=1,1" 500 |grep OK |wc -l) - sleep 2s - } - else - { - start="$( /etc/init.d/modem stop )" - sleep 2s - start="$( /etc/init.d/modem start )" - sleep 5s - } - fi -} -#检测SIM卡是否插入,10次检测不到则重启模块 -check_sim() -{ - while [ 1 ] - do - enabled=$(uci -q get modem.@ndis[0].enabled) - if [ $enabled == '1' ] ;then - echo "Check the sim" - rec=$( sendat 2 "AT+CPIN?") - rec1=$(echo $rec | grep "READY" | wc -l ) - if [ $rec1 == 1 ]; then - x=0 - echo "SIM is READY" - else - let x++ - if [ $x == 10 ]; then - echo "SIM abnormal restart" - modem_reset #重启模块 - x=0 - fi - fi - fi - sleep 6s - done -} -#检测网络状态第一次开机 -chenk_firstdns() -{ - while [ 1 ] - do - enabled=$(uci -q get modem.@ndis[0].enabled) - en1=$(uci -q get modem.@ndis[0].en) - if [ $enabled == '1' ] ;then - if [ $en1 == '1' ] ;then - echo "------------------------------开启任务---------------------------" - ipadd=$(uci -q get modem.@ndis[0].ipaddress) - ping -c 1 -w 1 $ipadd > /dev/null 2>&1 - if [ $? -eq 0 ];then - echo "网络连接正常" - xx=0 - return - else - echo "网络连接异常 $ipadd" - let xx++ - let pxx++ - fi - fi - if [ $xx == 5 ];then - xx=0 - modem_reset - fi - if [ $pxx == 10 ];then - xx=0 - pxx=0 - return - fi - echo "------------------------------结束任务---------------------------" - fi - sleep 1s - done -} -#检测网络状态 -chenk_dns() -{ - en1=$(uci -q get modem.@ndis[0].en) - if [ $en1 == '1' ] ;then - echo "------------------------------开启任务---------------------------" - ipadd=$(uci -q get modem.@ndis[0].ipaddress) - ping -c 1 -w 1 $ipadd > /dev/null 2>&1 - if [ $? -eq 0 ];then - echo "网络连接正常" - xx=0 - else - echo "网络连接异常 $ipadd 次数$xx" - let xx++ - fi - fi - an=$(uci -q get modem.@ndis[0].an) - if [ $xx == $an ];then - xx=0 - modem_reset - fi - echo "------------------------------结束任务---------------------------" - -} -# 信号任务 -chenk_Task() -{ - while [ 1 ] - do - enabled=$(uci -q get modem.@ndis[0].enabled) - if [ $enabled == '1' ] ;then - ATPORT - Debug "------------------------------开启任务---------------------------" - AUTO_CPE - SETData - chenk_dns - Debug "------------------------------结束任务---------------------------" - fi - sleep 10s - done -} - - -#注册网卡 -RegisterNetwork() -{ - # ATPORT - Debug "RegisterNetwork 注册网卡 $ $MODEMNAME" - # if [ "$MODEMNAME" == "FM650CN" ]; then - # getFM650=$(uci -q get network.wwan5g |grep "interface"| wc -l) - # if [ $getFM650 == "0" ] ;then - # uci set network.wwan5g=interface - # uci set network.wwan5g.ifname='usb0' - # uci set network.wwan5g.proto=dhcp - # uci commit network - - # uci set firewall.@zone[1].network="wan wan6 wwan5g wwan5g6 wlan" - # uci commit firewall - - # $(/etc/init.d/network reload) - # fi - # getFM650=$(uci -q get network.wwan5g6|grep "interface"| wc -l) - # if [ $getFM650 == "0" ] ;then - # uci set network.wwan5g6=interface - # uci set network.wwan5g6.ifname='usb0' - # uci set network.wwan5g6.proto='dhcpv6' - # uci set network.wwan5g6.reqaddress='try' - # uci set network.wwan5g6.reqprefix='auto' - # uci set network.wwan5g6._orig_ifname='usb0' - # uci set network.wwan5g6._orig_bridge='false' - # uci set network.wwan5g6.extendprefix='1' - # uci commit network - # uci set firewall.@zone[1].network="wan wan6 wwan wwan5g wwan5g6 wlan" - # uci commit firewall - # $(/etc/init.d/network reload) - # fi - # fi - - - - if [ $(uci -q get network.wwan5g |grep "interface"| wc -l) == "0" ] ;then - uci set network.wwan5g=interface - if [ "$MODEMNAME" == "FM650CN" ]; then - uci set network.wwan5g.ifname='usb0' - else - uci set network.wwan5g.ifname='wwan0' - fi - uci set network.wwan5g.proto=dhcp - uci commit network - uci set firewall.@zone[1].network="wan wan6 wwan5g wwan5g6 wlan" - uci commit firewall - $(/etc/init.d/network reload) - fi - if [ $(uci -q get network.wwan5g6 |grep "interface"| wc -l) == "0" ] ;then - uci set network.wwan5g6=interface - if [ "$MODEMNAME" == "FM650CN" ]; then - uci set network.wwan5g6.ifname='usb0' - uci set network.wwan5g6._orig_ifname='usb0' - else - uci set network.wwan5g6.ifname='wwan0' - uci set network.wwan5g6._orig_ifname='wwan0' - fi - uci set network.wwan5g6.proto='dhcpv6' - uci set network.wwan5g6.reqaddress='try' - uci set network.wwan5g6.reqprefix='auto' - uci set network.wwan5g6._orig_bridge='false' - uci set network.wwan5g6.extendprefix='1' - uci commit network - uci set firewall.@zone[1].network="wan wan6 wwan wwan5g wwan5g6 wlan" - uci commit firewall - $(/etc/init.d/network reload) - fi - if [ "$MODEMNAME" == "FM650CN" ]; then - if [ $(uci -q get network.wwan5g.ifname |grep "usb0"| wc -l) == "0" ] ;then - uci set network.wwan5g.ifname='usb0' - uci commit network - $(/etc/init.d/network reload) - fi - if [ $(uci -q get network.wwan5g6.ifname |grep "usb0"| wc -l) == "0" ] ;then - uci set network.wwan5g6.ifname='usb0' - uci commit network - $(/etc/init.d/network reload) - fi - else - if [ $(uci -q get network.wwan5g.ifname |grep "wwan0"| wc -l) == "0" ] ;then - uci set network.wwan5g.ifname='wwan0' - uci commit network - $(/etc/init.d/network reload) - fi - if [ $(uci -q get network.wwan5g6.ifname |grep "wwan0"| wc -l) == "0" ] ;then - uci set network.wwan5g6._orig_ifname='wwan0' - uci set network.wwan5g6.ifname='wwan0' - uci commit network - $(/etc/init.d/network reload) - fi - fi - - - -} - - - -# 运行入口 -first() -{ - Debug "开启RSSI服务" - # 初值化数据结构 - InitData - Debug "初值化数据完成" - sleep 1s - # 计算模块AT端口号 - ATPORT - # 注册网卡 - RegisterNetwork - # 第一次获取模块信息数据 - AUTO_CPE - # 保存结构数据 - SETData - #开机直接运行网络注册 - modem_reset - # 第一次开机检测是否联网 - chenk_firstdns - chenk_Task -} - -############################################# -# # -# 进入主函数 # -# # -############################################# -first diff --git a/luci-app-gobinetmodem/Makefile b/luci-app-gobinetmodem/Makefile deleted file mode 100644 index 634cff7..0000000 --- a/luci-app-gobinetmodem/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Modem Server -LUCI_DEPENDS:=+luci-compat +quectel-CM-5G +kmod-gobinet \ - +kmod-usb-net-cdc-ether +kmod-usb-net-qmi-wwan \ - +kmod-usb-net-rndis +kmod-usb-serial-option - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-gobinetmodem/luasrc/controller/gobinetmodem.lua b/luci-app-gobinetmodem/luasrc/controller/gobinetmodem.lua deleted file mode 100644 index 5b6de85..0000000 --- a/luci-app-gobinetmodem/luasrc/controller/gobinetmodem.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.gobinetmodem", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/gobinetmodem") then - return - end - - entry({"admin", "network", "gobinetmodem"}, cbi("gobinetmodem"), _("Gobinet Modem Server"), 80).dependent = false -end diff --git a/luci-app-gobinetmodem/luasrc/model/cbi/gobinetmodem.lua b/luci-app-gobinetmodem/luasrc/model/cbi/gobinetmodem.lua deleted file mode 100644 index 784130f..0000000 --- a/luci-app-gobinetmodem/luasrc/model/cbi/gobinetmodem.lua +++ /dev/null @@ -1,39 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -mp = Map("gobinetmodem") -mp.title = translate("gobinet Modem Server") -mp.description = translate("Modem Server For OpenWrt") - -s = mp:section(TypedSection, "service", "Base Setting") -s.anonymous = true - -enabled = s:option(Flag, "enabled", translate("Enable")) -enabled.default = 0 -enabled.rmempty = false - -apn = s:option(Value, "apn", translate("APN")) -apn.rmempty = true - -pincode = s:option(Value, "pincode", translate("PIN")) -pincode.rmempty = true - -username = s:option(Value, "username", translate("PAP/CHAP username")) -username.rmempty = true - -password = s:option(Value, "password", translate("PAP/CHAP password")) -password.rmempty = true - -auth = s:option(Value, "auth", translate("Authentication Type")) -auth.rmempty = true -auth:value("", translate("-- Please choose --")) -auth:value("both", "PAP/CHAP (both)") -auth:value("pap", "PAP") -auth:value("chap", "CHAP") -auth:value("none", "NONE") - -tool = s:option(Value, "tool", translate("Tools")) -tool:value("quectel-CM", "quectel-CM") -tool.rmempty = true - -return mp diff --git a/luci-app-gobinetmodem/po/zh-cn/usbmodem.po b/luci-app-gobinetmodem/po/zh-cn/usbmodem.po deleted file mode 100644 index df1f6df..0000000 --- a/luci-app-gobinetmodem/po/zh-cn/usbmodem.po +++ /dev/null @@ -1,24 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: dingpengyu \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"X-Generator: Poedit 2.3.1\n" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "gobinet Modem Server" -msgstr "gobinet移动网络拨号服务" - -msgid "Modem Server For OpenWrt" -msgstr "OpenWrt移动网络拨号服务" - -msgid "Tools" -msgstr "拨号工具" diff --git a/luci-app-gobinetmodem/root/etc/config/gobinetmodem b/luci-app-gobinetmodem/root/etc/config/gobinetmodem deleted file mode 100644 index 05fad9b..0000000 --- a/luci-app-gobinetmodem/root/etc/config/gobinetmodem +++ /dev/null @@ -1,4 +0,0 @@ -config service - option tool 'quectel-CM' - option enabled '0' - diff --git a/luci-app-gobinetmodem/root/etc/init.d/gobinetmodem b/luci-app-gobinetmodem/root/etc/init.d/gobinetmodem deleted file mode 100644 index 953ee96..0000000 --- a/luci-app-gobinetmodem/root/etc/init.d/gobinetmodem +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2014 OpenWrt.org - -START=99 -STOP=16 -USE_PROCD=1 -#使用procd启动 - -run_4g() -{ - local enabled - config_get_bool enabled $1 enabled - - echo "run 4G" >> /tmp/log4g - - if [ "$enabled" = "1" ]; then - local user - local password - local apn - local auth - local pincode - local device - local tool - - # echo "enable 4G" >> /tmp/log4g - config_get user $1 user - config_get password $1 password - config_get apn $1 apn - config_get auth $1 auth - config_get pincode $1 pincode - config_get device $1 device - config_get tool $1 tool - config_get tty $1 tty - config_get atcmd $1 atcmd - - devname="$(basename "$device")" - devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" - ifname="$( ls "$devpath"/net )" - - if [ "$tool" = "at" ];then - at_tool "$atcmd" -d $tty - else - procd_open_instance - #创建一个实例, 在procd看来一个应用程序可以多个实\E4\BE? - #ubus call service list 可以查看实例 - procd_set_param command $tool -i $ifname -s $apn - if [ "$password" != "" ];then - procd_append_param command $user $password $auth - fi - if [ "$pincode" != "" ]; then - procd_append_param command -p $pincode - fi - # procd_append_param command -f /tmp/4g.log - procd_set_param respawn - echo "quectel-CM has started." - procd_close_instance - #关闭实例 - fi - - fi -} - - -service_triggers() -{ - procd_add_reload_trigger "gobinetmodem" -} - -start_service() { - config_load gobinetmodem - config_foreach run_4g service -} - -stop_service() -{ - echo "4G stop" >> /tmp/log4g - killall quectel-CM - echo "quectel-CM has stoped." -} - diff --git a/luci-app-gobinetmodem/root/etc/uci-defaults/luci-gobinetmodem b/luci-app-gobinetmodem/root/etc/uci-defaults/luci-gobinetmodem deleted file mode 100644 index b4b7674..0000000 --- a/luci-app-gobinetmodem/root/etc/uci-defaults/luci-gobinetmodem +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@gobinetmodem[-1] - add ucitrack gobinetmodem - set ucitrack.@gobinetmodem[-1].init=gobinetmodem - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/luci-app-hypermodem/Makefile b/luci-app-hypermodem/Makefile deleted file mode 100644 index 98dc044..0000000 --- a/luci-app-hypermodem/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Hyper Modem Server -LUCI_DEPENDS:=+luci-compat +kmod-usb-net +kmod-usb-net-cdc-ether +kmod-usb-acm \ - +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis +kmod-usb-serial-qualcomm \ - +kmod-usb-net-sierrawireless +kmod-usb-ohci +kmod-usb-serial \ - +kmod-usb-serial-option +kmod-usb-wdm \ - +kmod-usb2 +kmod-usb3 \ - +kmod-usb-net-cdc-mbim \ - +usbutils \ - +luci-proto-qmi \ - +pciutils \ - +kmod-pcie_mhi \ - +quectel-CM-5G \ - +grep \ - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-hypermodem/README.md b/luci-app-hypermodem/README.md deleted file mode 100644 index e6fe7bb..0000000 --- a/luci-app-hypermodem/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# luci-app-hypermodem - -# 目录 - -[一、说明](#一说明) - -# 一、说明 - -原项目地址:https://github.com/momokind/luci-app-hypermodem - -插件功能 - -- 支持USB和PCIe两种通信方式的通信模组 - -- 支持IPv6 - -- 支持高通和紫光展锐两个平台的通信模组 - -- 支持常见厂商的通信模组(例如:移远,广和通等) - diff --git a/luci-app-hypermodem/luasrc/controller/hypermodem.lua b/luci-app-hypermodem/luasrc/controller/hypermodem.lua deleted file mode 100644 index d46e21b..0000000 --- a/luci-app-hypermodem/luasrc/controller/hypermodem.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.hypermodem", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/hypermodem") then - return - end - - entry({"admin", "network", "hypermodem"}, cbi("hypermodem"), _("Hyper Modem Server"), 80).dependent = false -end diff --git a/luci-app-hypermodem/luasrc/model/cbi/hypermodem.lua b/luci-app-hypermodem/luasrc/model/cbi/hypermodem.lua deleted file mode 100644 index 51e5459..0000000 --- a/luci-app-hypermodem/luasrc/model/cbi/hypermodem.lua +++ /dev/null @@ -1,67 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -mp = Map("hypermodem") -mp.title = translate("Hyper Modem Server") -mp.description = translate("Modem Server For OpenWrt") - -s = mp:section(TypedSection, "service", translate("Base Setting")) -s.anonymous = true - -enabled = s:option(Flag, "enabled", translate("Enable")) -enabled.default = 0 -enabled.rmempty = false - -ipv6 = s:option(Flag, "ipv6", translate("Enable IPv6")) -ipv6.default = 1 -ipv6.rmempty = false - -network_bridge = s:option(Flag, "network_bridge", translate("Enable Network bridge")) -network_bridge.description = translate("After checking, enable network interface bridge.") -network_bridge.default = 0 -network_bridge.rmempty = false - -device = s:option(Value, "device", translate("Modem device")) -device.rmempty = false - -local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*") - -if device_suggestions then - local node - for node in device_suggestions do - device:value(node) - end -end - -apn = s:option(Value, "apn", translate("APN")) -apn.default = "" -apn.rmempty = true -apn:value("", translate("Auto Choose")) -apn:value("cmnet", translate("China Mobile")) -apn:value("3gnet", translate("China Unicom")) -apn:value("ctnet", translate("China Telecom")) -apn:value("cbnet", translate("China Broadcast")) -apn:value("5gscuiot", translate("Skytone")) - -auth = s:option(ListValue, "auth", translate("Authentication Type")) -auth.default = "none" -auth.rmempty = false -auth:value("none", translate("NONE")) -auth:value("both", translate("PAP/CHAP (both)")) -auth:value("pap", "PAP") -auth:value("chap", "CHAP") - -username = s:option(Value, "username", translate("PAP/CHAP Username")) -username.rmempty = true -username:depends("auth", "both") -username:depends("auth", "pap") -username:depends("auth", "chap") - -password = s:option(Value, "password", translate("PAP/CHAP Password")) -password.rmempty = true -password.password = true -password:depends("auth", "both") -password:depends("auth", "pap") -password:depends("auth", "chap") - -return mp diff --git a/luci-app-hypermodem/po/zh-cn/hypermodem.po b/luci-app-hypermodem/po/zh-cn/hypermodem.po deleted file mode 100644 index 383e595..0000000 --- a/luci-app-hypermodem/po/zh-cn/hypermodem.po +++ /dev/null @@ -1,63 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: momokind \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"X-Generator: Poedit 2.3.1\n" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "Hyper Modem Server" -msgstr "超级移动网络拨号服务" - -msgid "Modem Server For OpenWrt" -msgstr "OpenWrt移动网络拨号服务" - -msgid "Enable IPv6" -msgstr "启用IPv6协商" - -msgid "Enable Network bridge" -msgstr "启用网络桥架" - -msgid "After checking, enable network interface bridge." -msgstr "勾选后,启用网络接口桥接。" - -msgid "APN" -msgstr "接入点" - -msgid "China Mobile" -msgstr "中国移动" - -msgid "China Unicom" -msgstr "中国联通" - -msgid "China Telecom" -msgstr "中国电信" - -msgid "China Broadcast" -msgstr "中国广电" - -msgid "Skytone" -msgstr "天际通" - -msgid "Authentication Type" -msgstr "认证类型" - -msgid "PAP/CHAP (both)" -msgstr "PAP/CHAP (均使用)" - -msgid "NONE" -msgstr "无" - -msgid "PAP/CHAP Username" -msgstr "PAP/CHAP 用户名" - -msgid "PAP/CHAP Password" -msgstr "PAP/CHAP 密码" \ No newline at end of file diff --git a/luci-app-hypermodem/root/etc/config/hypermodem b/luci-app-hypermodem/root/etc/config/hypermodem deleted file mode 100644 index 0e9654e..0000000 --- a/luci-app-hypermodem/root/etc/config/hypermodem +++ /dev/null @@ -1,5 +0,0 @@ -config service - option device '/dev/cdc-wdm0' - option ipv6 '1' - option enabled '0' - diff --git a/luci-app-hypermodem/root/etc/init.d/hypermodem b/luci-app-hypermodem/root/etc/init.d/hypermodem deleted file mode 100755 index b44da18..0000000 --- a/luci-app-hypermodem/root/etc/init.d/hypermodem +++ /dev/null @@ -1,186 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2014 OpenWrt.org - -START=94 -STOP=13 -USE_PROCD=1 - -#设置防火墙 -# $1:网络接口名称 -set_firewall() -{ - local interface_name="$1" - - local num=$(uci show firewall | grep "name='wan'" | wc -l) - local wwan_num=$(uci -q get firewall.@zone[$num].network | grep -w "${interface_name}" | wc -l) - if [ "$wwan_num" = "0" ]; then - uci add_list firewall.@zone[$num].network="${interface_name}" - fi - uci commit firewall -} - -#设置IPv4网络接口 -# $1:网络接口名称 -# $2:网络接口 -set_ipv4_interface() -{ - local interface_name="$1" - local network_interface="$2" - - #添加或修改网络配置 - uci set network.${interface_name}='interface' - uci set network.${interface_name}.proto='dhcp' - uci set network.${interface_name}.device="${network_interface}" - uci set network.${interface_name}.ifname="${network_interface}" - uci commit network - - #加入WAN防火墙 - set_firewall "${interface_name}" - - #启动网络接口 - ifup "${interface_name}" -} - -#设置IPv6网络接口 -# $1:网络接口名称 -# $2:网络接口 -set_ipv6_interface() -{ - local interface_name="$1" - local network_interface="$2" - - #添加或修改网络配置 - uci set network.${interface_name}='interface' - uci set network.${interface_name}.proto='dhcpv6' - uci set network.${interface_name}.extendprefix='1' - uci set network.${interface_name}.device="${network_interface}" - uci set network.${interface_name}.ifname="${network_interface}" - uci commit network - - #加入WAN防火墙 - set_firewall "${interface_name}" - - #启动网络接口 - ifup "${interface_name}" -} - -#设置IPV4和IPv6网络接口 -# $1:IPV4网络接口名称 -# $2:IPv6网络接口名称 -# $3:网络接口 -set_ipv4v6_interface() -{ - local ipv4_interface_name="$1" - local ipv6_interface_name="$2" - local network_interface="$3" - - #设置IPV4网络接口 - set_ipv4_interface "${ipv4_interface_name}" "${network_interface}" - #设置IPV6网络接口(别名) - set_ipv6_interface "${ipv6_interface_name}" "@${ipv4_interface_name}" -} - -#设置网络接口 -# $2:网络接口 -set_interface() -{ - local network_interface="$1" - - local pdp_type - [ "$ipv6" = "1" ] && { - pdp_type="ipv4v6" - } - - case $pdp_type in - "ipv4") set_ipv4_interface "wwan_5g" "${network_interface}" ;; - "ipv6") set_ipv6_interface "wwan6_5g" "${network_interface}" ;; - "ipv4v6") set_ipv4v6_interface "wwan_5g" "wwan6_5g" "${network_interface}" ;; - *) set_ipv4v6_interface "wwan_5g" "wwan6_5g" "${network_interface}" ;; - esac -} - -run_dial() -{ - local enabled - config_get_bool enabled $1 enabled - - if [ "$enabled" = "1" ]; then - local apn - local user - local password - local auth - local ipv6 - local network_bridge - local device - - config_get apn $1 apn - config_get user $1 user - config_get password $1 password - config_get auth $1 auth - config_get ipv6 $1 ipv6 - config_get network_bridge $1 network_bridge - config_get device $1 device - - devname="$(basename "${device}")" - devicepath="$(find /sys/class/ -name ${devname})" - devpath="$(readlink -f ${devicepath}/device/)" - network="$( ls "${devpath}"/net )" - - #拨号配置 - procd_open_instance - procd_set_param command quectel-CM - if [ "$ipv6" = 1 ]; then - procd_append_param command "-4" "-6" - fi - if [ "$network_bridge" = 1 ]; then - procd_append_param command "-b" - fi - if [ "$apn" != "" ];then - procd_append_param command "-s" "$apn" - fi - if [ "$username" != "" ]; then - procd_append_param command "$username" - fi - if [ "$password" != "" ]; then - procd_append_param command "$password" - fi - if [ "$auth" != "" ]; then - procd_append_param command "$auth" - fi - if [ "$device" != "" ]; then - procd_append_param command -i "$network" - fi - procd_set_param respawn - procd_close_instance - - #设置网络接口 - local network_interface - if [ -d /sys/class/net/rmnet_mhi0 ]; then - network_interface="rmnet_mhi0.1" - elif [ -d /sys/class/net/wwan0_1 ]; then - network_interface="wwan0_1" - elif [ -d /sys/class/net/wwan0.1 ]; then - network_interface="wwan0.1" - elif [ -d /sys/class/net/wwan0 ]; then - network_interface="wwan0" - fi - set_interface "${network_interface}" - fi - - sleep 15 -} - -service_triggers() -{ - procd_add_reload_trigger "hypermodem" -} - -start_service() { - config_load hypermodem - config_foreach run_dial service -} - -stop_service() -{ - killall quectel-CM >/dev/null 2>&1 -} diff --git a/luci-app-hypermodem/root/etc/uci-defaults/luci-hypermodem b/luci-app-hypermodem/root/etc/uci-defaults/luci-hypermodem deleted file mode 100755 index 531e07b..0000000 --- a/luci-app-hypermodem/root/etc/uci-defaults/luci-hypermodem +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@hypermodem[-1] - add ucitrack hypermodem - set ucitrack.@hypermodem[-1].init=hypermodem - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/luci-app-pcimodem/Makefile b/luci-app-pcimodem/Makefile deleted file mode 100644 index 1bcb748..0000000 --- a/luci-app-pcimodem/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=PCI Modem Server -LUCI_DEPENDS:=+kmod-pcie_mhi +pciutils +quectel-CM-5G - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-pcimodem/luasrc/controller/pcimodem.lua b/luci-app-pcimodem/luasrc/controller/pcimodem.lua deleted file mode 100644 index e1d3daf..0000000 --- a/luci-app-pcimodem/luasrc/controller/pcimodem.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.pcimodem", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/pcimodem") then - return - end - - entry({"admin", "network", "pcimodem"}, cbi("pcimodem"), _("PCI Modem Server"), 80).dependent = false -end diff --git a/luci-app-pcimodem/luasrc/model/cbi/pcimodem.lua b/luci-app-pcimodem/luasrc/model/cbi/pcimodem.lua deleted file mode 100644 index 258ce66..0000000 --- a/luci-app-pcimodem/luasrc/model/cbi/pcimodem.lua +++ /dev/null @@ -1,39 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -mp = Map("pcimodem") -mp.title = translate("PCI Modem Server") -mp.description = translate("Modem Server For OpenWrt") - -s = mp:section(TypedSection, "service", "Base Setting") -s.anonymous = true - -enabled = s:option(Flag, "enabled", translate("Enable")) -enabled.default = 0 -enabled.rmempty = false - -apn = s:option(Value, "apn", translate("APN")) -apn.rmempty = true - -pincode = s:option(Value, "pincode", translate("PIN")) -pincode.rmempty = true - -username = s:option(Value, "username", translate("PAP/CHAP username")) -username.rmempty = true - -password = s:option(Value, "password", translate("PAP/CHAP password")) -password.rmempty = true - -auth = s:option(Value, "auth", translate("Authentication Type")) -auth.rmempty = true -auth:value("", translate("-- Please choose --")) -auth:value("both", "PAP/CHAP (both)") -auth:value("pap", "PAP") -auth:value("chap", "CHAP") -auth:value("none", "NONE") - -tool = s:option(Value, "tool", translate("Tools")) -tool:value("quectel-CM", "quectel-CM") -tool.rmempty = true - -return mp diff --git a/luci-app-pcimodem/po/zh-cn/pcimodem.po b/luci-app-pcimodem/po/zh-cn/pcimodem.po deleted file mode 100644 index fea348d..0000000 --- a/luci-app-pcimodem/po/zh-cn/pcimodem.po +++ /dev/null @@ -1,24 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: dingpengyu \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"X-Generator: Poedit 2.3.1\n" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "PCI Modem Server" -msgstr "PCI移动网络拨号服务" - -msgid "Modem Server For OpenWrt" -msgstr "OpenWrt移动网络拨号服务" - -msgid "Tools" -msgstr "拨号工具" diff --git a/luci-app-pcimodem/root/etc/config/pcimodem b/luci-app-pcimodem/root/etc/config/pcimodem deleted file mode 100644 index 05fad9b..0000000 --- a/luci-app-pcimodem/root/etc/config/pcimodem +++ /dev/null @@ -1,4 +0,0 @@ -config service - option tool 'quectel-CM' - option enabled '0' - diff --git a/luci-app-pcimodem/root/etc/init.d/pcimodem b/luci-app-pcimodem/root/etc/init.d/pcimodem deleted file mode 100644 index f60124f..0000000 --- a/luci-app-pcimodem/root/etc/init.d/pcimodem +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2014 OpenWrt.org - -START=99 -STOP=16 -USE_PROCD=1 -#使用procd启动 - -run_5g() -{ - local enabled - config_get_bool enabled $1 enabled - - echo "run 4G" >> /tmp/log4g - - if [ "$enabled" = "1" ]; then - local user - local password - local apn - local auth - local pincode - local tool - - # echo "enable 5G" >> /tmp/log5g - config_get user $1 user - config_get password $1 password - config_get apn $1 apn - config_get auth $1 auth - config_get pincode $1 pincode - config_get tool $1 tool - config_get tty $1 tty - config_get atcmd $1 atcmd - - if [ "$tool" = "at" ];then - at_tool "$atcmd" -d $tty - else - procd_open_instance - #创建一个实例, 在procd看来一个应用程序可以多个实\E4\BE? - #ubus call service list 可以查看实例 - procd_set_param command $tool -i rmnet_mhi0 -s $apn - if [ "$password" != "" ];then - procd_append_param command $user $password $auth - fi - if [ "$pincode" != "" ]; then - procd_append_param command -p $pincode - fi - # procd_append_param command -f /tmp/4g.log - procd_set_param respawn - echo "quectel-CM has started." - procd_close_instance - #关闭实例 - fi - - fi -} - - -service_triggers() -{ - procd_add_reload_trigger "pcimodem" -} - -start_service() { - config_load pcimodem - config_foreach run_5g service -} - -stop_service() -{ - echo "5G stop" >> /tmp/log5g - killall quectel-CM - echo "quectel-CM has stoped." -} - - diff --git a/luci-app-pcimodem/root/etc/uci-defaults/luci-pcimodem b/luci-app-pcimodem/root/etc/uci-defaults/luci-pcimodem deleted file mode 100644 index 10f5ab8..0000000 --- a/luci-app-pcimodem/root/etc/uci-defaults/luci-pcimodem +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@pcimodem[-1] - add ucitrack pcimodem - set ucitrack.@pcimodem[-1].init=pcimodem - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/luci-app-sms-tool/LICENSE b/luci-app-sms-tool/LICENSE deleted file mode 100644 index f288702..0000000 --- a/luci-app-sms-tool/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/luci-app-sms-tool/Makefile b/luci-app-sms-tool/Makefile deleted file mode 100644 index db9d2a2..0000000 --- a/luci-app-sms-tool/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2023 Siriling -# This is free software, licensed under the GNU General Public License v3. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-sms-tool -LUCI_TITLE:=LuCI Support for sms_tool -LUCI_PKGARCH:=all -PKG_VERSION:=1.0.0 -PKG_LICENSE:=GPLv3 -PKG_LINCESE_FILES:=LICENSE -PKF_MAINTAINER:=siriling -LUCI_DEPENDS:=+sms-tool +luci-compat +kmod-usb-serial +kmod-usb-serial-option - -define Package/luci-app-sms-tool/postinst -#!/bin/sh -rm -rf /tmp/luci-indexcache -rm -rf /tmp/luci-modulecache/ -/sbin/set_sms_ports.sh -exit 0 -endef - -define Package/$(PKG_NAME)/config -# shown in make menuconfig -help - $(LUCI_TITLE) - Version: $(PKG_VERSION) -endef - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms.png b/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms.png deleted file mode 100644 index b036e813f546c56ad0e934e1c7ec9ee359f469b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9221 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 be4qXWXHQajJ#~#t00000NkvXXu0mjfyr5CZ diff --git a/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms2.png b/luci-app-sms-tool/htdocs/luci-static/resources/icons/delsms2.png deleted file mode 100644 index eeb13c5e674a1a826e0f8f0fdb809834922e1d3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1365 zcmV-b1*-aqP)EX>4Tx04R}tkv&MmKpe$iQ>7}k4(*`gkfAzR5EXHhDi*;)X)CnqU~=gfG-*gu zTpR`0f`cE6RRbkxtGNhls^O2g@DIiiS!&O&nHKjq-(z z!wTmu&T6^JTKD8H^yjpd6xV5vAciHxk$?ypRg_SMg$S)0DJGJ%A9e8$H~k56$>b`5 zkz)ZBsF0d|@IUz7t(l*ibdvm0p!>zPKSlxHF3_mi_V=-EH%AO zt%Z+(foN9LZ_VkgwU5&WAWdB@-v9@P zz*vE@*InM-)7jg_CX>@2HM@dakSAh-}0009lNkl3);i_xxh&zU`YW(NM_B_D3B3d(07uYwH%kIooE2pE9_0t8?{g8ocMJ&Yn~AB7-I z+Ae?e?(#S9$Oqf27a_h401ANtPS6r`J@AA;fvyK^5CX^ux!(_vDUoDAxb^4wd^V49 z&B%x_f{x&bU?1lm^c1sEW?}_>3}FG0Awot71m)4iqjB~q{f~ynA;AP^8^;O2qXNgQ zt}{`^QFc&vka!A}5rQKmif3{uPKfou2ROI!sA^kJ;By33^-7QeR3Ql@Hc-wZj1Xxs zGjit!w1gaDej5WWf&nGq zZ`N!m zkc$g}VtuA1;LF`L?*G&h7#1x~!NZPano6TIWNB!lWixgdD@bp#5TUq}&8xyw=XlgB zKYi|bR0NA!&E9*-fkaIzp(M#ne4n3p!Mw^>3FC9L4#RB-uU5}7bCix&OXKt222d@v~Uodcxa!gfjslTV}&Oh7^HfxJdQG= zl;LtF5)ep?Pzu2=1A(Ps@1Ci2bFD(BM7^UjpaH@nFal}FSt1LXAb~U}=O932w^k`9 z!Q(^^`j;e0A6Y8c{jZI{c~S{y%ZFJ zZteQY=9RNdw0vsBiB64t4fN_+N2Z=4sEU3nqE|j&`6JFskRLFn*FkQqzwle|{{sF2 XGLww0Jg8t@00000NkvXXu0mjfu%1_o diff --git a/luci-app-sms-tool/luasrc/controller/modem/sms.lua b/luci-app-sms-tool/luasrc/controller/modem/sms.lua deleted file mode 100644 index f807e9e..0000000 --- a/luci-app-sms-tool/luasrc/controller/modem/sms.lua +++ /dev/null @@ -1,242 +0,0 @@ - local util = require "luci.util" - local fs = require "nixio.fs" - local sys = require "luci.sys" - local http = require "luci.http" - local dispatcher = require "luci.dispatcher" - local http = require "luci.http" - local sys = require "luci.sys" - local uci = require "luci.model.uci".cursor() - -module("luci.controller.modem.sms", package.seeall) - -function index() - entry({"admin", "modem"}, firstchild(), "Modem", 30).dependent=false - entry({"admin", "modem", "sms"}, alias("admin", "modem", "sms", "readsms"), translate("短信"), 20) - entry({"admin", "modem", "sms", "readsms"},template("modem/readsms"),translate("收到的信息"), 10) - entry({"admin", "modem", "sms", "sendsms"},template("modem/sendsms"),translate("发送消息"), 20) - entry({"admin", "modem", "sms", "ussd"},template("modem/ussd"),translate("USSD 代码"), 30) - entry({"admin", "modem", "sms", "atcommands"},template("modem/atcommands"),translate("AT 命令"), 40) - entry({"admin", "modem", "sms", "smsconfig"},cbi("modem/smsconfig"),translate("配置"), 50) - entry({"admin", "modem", "sms", "delete_one"}, call("delete_sms", smsindex), nil).leaf = true - entry({"admin", "modem", "sms", "delete_all"}, call("delete_all_sms"), nil).leaf = true - entry({"admin", "modem", "sms", "run_ussd"}, call("ussd"), nil).leaf = true - entry({"admin", "modem", "sms", "run_at"}, call("at"), nil).leaf = true - entry({"admin", "modem", "sms", "run_sms"}, call("sms"), nil).leaf = true - entry({"admin", "modem", "sms", "readsim"}, call("slots"), nil).leaf = true - entry({"admin", "modem", "sms", "countsms"}, call("count_sms"), nil).leaf = true - entry({"admin", "modem", "sms", "user_ussd"}, call("userussd"), nil).leaf = true - entry({"admin", "modem", "sms", "user_atc"}, call("useratc"), nil).leaf = true - entry({"admin", "modem", "sms", "user_phonebook"}, call("userphb"), nil).leaf = true -end - - -function delete_sms(smsindex) -local devv = tostring(uci:get("sms_tool", "general", "readport")) -local s = smsindex -for d in s:gmatch("%d+") do - os.execute("sms_tool -d " .. devv .. " delete " .. d .. "") -end -end - -function delete_all_sms() - local devv = tostring(uci:get("sms_tool", "general", "readport")) - os.execute("sms_tool -d " .. devv .. " delete all") -end - -function get_ussd() - local cursor = luci.model.uci.cursor() - if cursor:get("sms_tool", "general", "ussd") == "1" then - return " -R" - else - return "" - end -end - - -function get_pdu() - local cursor = luci.model.uci.cursor() - if cursor:get("sms_tool", "general", "pdu") == "1" then - return " -r" - else - return "" - end -end - - -function ussd() - local devv = tostring(uci:get("sms_tool", "general", "ussdport")) - - local ussd = get_ussd() - local pdu = get_pdu() - - local ussd_code = http.formvalue("code") - if ussd_code then - local odpall = io.popen("sms_tool -d " .. devv .. ussd .. pdu .. " ussd " .. ussd_code .." 2>&1") - local odp = odpall:read("*a") - odpall:close() - http.write(tostring(odp)) - else - http.write_json(http.formvalue()) - end -end - - -function at() - local devv = tostring(uci:get("sms_tool", "general", "atport")) - - local at_code = http.formvalue("code") - if at_code then - local odpall = io.popen("sms_tool -d " .. devv .. " at " ..at_code:gsub("[$]", "\\\$"):gsub("\"", "\\\"").." 2>&1") - local odp = odpall:read("*a") - odpall:close() - http.write(tostring(odp)) - else - http.write_json(http.formvalue()) - end -end - - -function sms() - local devv = tostring(uci:get("sms_tool", "general", "sendport")) - local sms_code = http.formvalue("scode") - - nr = (string.sub(sms_code, 1, 20)) - msgall = string.sub(sms_code, 21) - msg = string.gsub(msgall, "\n", " ") - - if sms_code then - local odpall = io.popen("sms_tool -d " .. devv .. " send " .. nr .." '".. msg .."'") - local odp = odpall:read("*a") - odpall:close() - http.write(tostring(odp)) - else - http.write_json(http.formvalue()) - end - -end - -function slots() - local sim = { } - local devv = tostring(uci:get("sms_tool", "general", "readport")) - local led = tostring(uci:get("sms_tool", "general", "smsled")) - local dsled = tostring(uci:get("sms_tool", "general", "ledtype")) - local ln = tostring(uci:get("sms_tool", "general", "lednotify")) - - local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - - local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") - local usex = string.sub (statusb, 23, 27) - local max = statusb:match('[^: ]+$') - sim["use"] = string.match(usex, '%d+') - local smscount = string.match(usex, '%d+') - if ln == "1" then - luci.sys.call("echo " .. smscount .. " > /etc/config/sms_count") - if dsled == "S" then - luci.util.exec("/etc/init.d/led restart") - end - if dsled == "D" then - luci.sys.call("echo 0 > '/sys/class/leds/" .. led .. "/brightness'") - end - end - sim["all"] = string.match(max, '%d+') - luci.http.prepare_content("application/json") - luci.http.write_json(sim) -end - - -function count_sms() - os.execute("sleep 3") - local cursor = luci.model.uci.cursor() - if cursor:get("sms_tool", "general", "lednotify") == "1" then - local devv = tostring(uci:get("sms_tool", "general", "readport")) - - local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - - local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") - local smsnum = string.sub (statusb, 23, 27) - local smscount = string.match(smsnum, '%d+') - os.execute("echo " .. smscount .. " > /etc/config/sms_count") - end -end - - -function uussd(rv) - local c = nixio.fs.access("/etc/config/ussd.user") and - io.popen("cat /etc/config/ussd.user") - - if c then - for l in c:lines() do - local i = l - if i then - rv[#rv + 1] = { - usd = i - } - end - end - c:close() - end -end - - - -function userussd() - local usd = { } - uussd(usd) - luci.http.prepare_content("application/json") - luci.http.write_json(usd) -end - - -function uat(rv) - local c = nixio.fs.access("/etc/config/atcmds.user") and - io.popen("cat /etc/config/atcmds.user") - - if c then - for l in c:lines() do - local i = l - if i then - rv[#rv + 1] = { - atu = i - } - end - end - c:close() - end -end - - - -function useratc() - local atu = { } - uat(atu) - luci.http.prepare_content("application/json") - luci.http.write_json(atu) -end - - - -function uphb(rv) - local c = nixio.fs.access("/etc/config/phonebook.user") and - io.popen("cat /etc/config/phonebook.user") - - if c then - for l in c:lines() do - local i = l - if i then - rv[#rv + 1] = { - phb = i - } - end - end - c:close() - end -end - - - -function userphb() - local phb = { } - uphb(phb) - luci.http.prepare_content("application/json") - luci.http.write_json(phb) -end diff --git a/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua b/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua deleted file mode 100644 index dc756e5..0000000 --- a/luci-app-sms-tool/luasrc/model/cbi/modem/smsconfig.lua +++ /dev/null @@ -1,226 +0,0 @@ -local util = require "luci.util" -local fs = require "nixio.fs" -local sys = require "luci.sys" -local http = require "luci.http" -local dispatcher = require "luci.dispatcher" -local http = require "luci.http" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() - -local USSD_FILE_PATH = "/etc/config/ussd.user" -local PHB_FILE_PATH = "/etc/config/phonebook.user" -local SMSC_FILE_PATH = "/etc/config/smscommands.user" -local AT_FILE_PATH = "/etc/config/atcmds.user" - -local led = tostring(uci:get("sms_tool", "general", "smsled")) -local dsled = tostring(uci:get("sms_tool", "general", "ledtype")) -local ledtime = tostring(uci:get("sms_tool", "general", "checktime")) - -local m -local s -local dev1, dev2, dev3, dev4, leds -local try_devices1 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_devices2 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_devices3 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_devices4 = nixio.fs.glob("/dev/tty[A-Z][A-Z]*") -local try_leds = nixio.fs.glob("/sys/class/leds/*") - - -local devv = tostring(uci:get("sms_tool", "general", "readport")) - -local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - -local statusb = luci.util.exec("sms_tool -s".. smsmem .. " -d ".. devv .. " status") - -local smsnum = string.sub (statusb, 23, 27) - -local smscount = string.match(smsnum, '%d+') - -m = Map("sms_tool", translate("配置短信工具"), - translate("sms_tool和gui应用程序的配置面板。")) - -s = m:section(NamedSection, 'general' , "sms_tool" , "" .. translate("")) -s.anonymous = true -s:tab("sms", translate("SMS 设置")) -s:tab("ussd", translate("USSD 代码设置")) -s:tab("at", translate("AT 命令设置")) -s:tab("info", translate("通知设置")) - -this_tab = "sms" - -dev1 = s:taboption(this_tab, Value, "readport", translate("短信读取端口")) -if try_devices1 then -local node -for node in try_devices1 do -dev1:value(node, node) -end -end - -mem = s:taboption(this_tab, ListValue, "storage", translate("信息存储区"), translate("信息存储在一个特定的位置(例如,在SIM卡或调制解调器内存),但根据设备的类型,其他区域也可能是可用的。")) -mem.default = "SM" -mem:value("SM", translate("SIM 卡")) -mem:value("ME", translate("调制解调器内存")) -mem.rmempty = true - -local msm = s:taboption(this_tab, Flag, "mergesms", translate("合并分割的信息"), translate("勾选这个选项会使阅读信息更容易,但会导致显示和接收的信息数量不一致。")) -msm.rmempty = false - -dev2 = s:taboption(this_tab, Value, "sendport", translate("短信发送端口")) -if try_devices2 then -local node -for node in try_devices2 do -dev2:value(node, node) -end -end - -local t = s:taboption(this_tab, Value, "pnumber", translate("前缀号码"), translate("电话号码的前面应该有国家的前缀(波兰是48,没有'+')。如果号码是5个、4个或3个字符,它将被视为 '短',不应该在前面加上国家前缀。")) -t.rmempty = true -t.default = 48 - -local f = s:taboption(this_tab, Flag, "prefix", translate("为电话号码添加前缀"), translate("自动添加电话号码字段的前缀。")) -f.rmempty = false - - -local i = s:taboption(this_tab, Flag, "information", translate("号码和前缀的解释"), translate("在发送短信的标签中,显示前缀的解释和正确的电话号码。")) -i.rmempty = false - -local ta = s:taboption(this_tab, TextValue, "user_phonebook", translate("用户电话簿"), translate("每一行必须有以下格式。'联系人姓名;电话号码'。保存到文件'/etc/config/phonebook.user'。")) -ta.rows = 7 -ta.rmempty = false - -function ta.cfgvalue(self, section) - return fs.readfile(PHB_FILE_PATH) -end - -function ta.write(self, section, value) - value = value:gsub("\r\n", "\n") - fs.writefile(PHB_FILE_PATH, value) -end - -this_taba = "ussd" - -dev3 = s:taboption(this_taba, Value, "ussdport", translate("USSD发送端口")) -if try_devices3 then -local node -for node in try_devices3 do -dev3:value(node, node) -end -end - -local u = s:taboption(this_taba, Flag, "ussd", translate("以纯文本发送USSD代码"), translate("以纯文本发送USSD代码。命令没有被编码到PDU中。")) -u.rmempty = false - -local p = s:taboption(this_taba, Flag, "pdu", translate("接收没有PDU解码的信息"), translate("接收并显示消息,而不将其解码为PDU。")) -p.rmempty = false - -local tb = s:taboption(this_taba, TextValue, "user_ussd", translate("用户USSD代码"), translate("每一行必须有以下格式。'代码名称;代码'。保存到文件'/etc/config/ussd.user'。")) -tb.rows = 7 -tb.rmempty = true - -function tb.cfgvalue(self, section) - return fs.readfile(USSD_FILE_PATH) -end - -function tb.write(self, section, value) - value = value:gsub("\r\n", "\n") - fs.writefile(USSD_FILE_PATH, value) -end - -this_tabc = "at" - -dev4 = s:taboption(this_tabc, Value, "atport", translate("AT命令的发送端口")) -if try_devices4 then -local node -for node in try_devices4 do -dev4:value(node, node) -end -end - -local tat = s:taboption(this_tabc, TextValue, "user_at", translate("用户AT命令"), translate("每一行必须有以下格式。'AT命令名称;AT命令'。保存到文件'/etc/config/atcmds.user'。")) -tat.rows = 20 -tat.rmempty = true - -function tat.cfgvalue(self, section) - return fs.readfile(AT_FILE_PATH) -end - -function tat.write(self, section, value) - value = value:gsub("\r\n", "\n") - fs.writefile(AT_FILE_PATH, value) -end - -this_tabb = "info" - -local uw = s:taboption(this_tabb, Flag, "lednotify", translate("通知新消息"), translate("LED通知有新的信息。在激活这个功能之前,请配置并保存短信阅读端口,检查短信收件箱的时间,并选择通知LED。")) -uw.rmempty = false - -function uw.write(self, section, value) -if devv ~= nil or devv ~= '' then -if ( smscount ~= nil and led ~= nil ) then - if value == '1' then - - luci.sys.call("echo " .. smscount .. " > /etc/config/sms_count") - luci.sys.call("uci set sms_tool.general.lednotify=" .. 1 .. ";/etc/init.d/smsled enable;/etc/init.d/smsled start") - luci.sys.call("/sbin/cronsync.sh") - - elseif value == '0' then - luci.sys.call("uci set sms_tool.general.lednotify=" .. 0 .. ";/etc/init.d/smsled stop;/etc/init.d/smsled disable") - if dsled == 'D' then - luci.sys.call("echo 0 > '/sys/class/leds/" .. led .. "/brightness'") - end - luci.sys.call("/sbin/cronsync.sh") - - end -return Flag.write(self, section ,value) - end -end -end - -local time = s:taboption(this_tabb, Value, "checktime", translate("每(几)分钟检查一次收件箱"), translate("指定你想在多少分钟内检查你的收件箱。")) -time.rmempty = false -time.maxlength = 2 -time.default = 5 - -function time.validate(self, value) - if ( tonumber(value) < 60 and tonumber(value) > 0 ) then - return value - end -end - -sync = s:taboption(this_tabb, ListValue, "prestart", translate("每隔一段时间重新启动收件箱检查程序"), translate("该过程将在选定的时间间隔内重新启动。这将消除检查收件箱的延迟。")) -sync.default = "6" -sync:value("4", translate("4h")) -sync:value("6", translate("6h")) -sync:value("8", translate("8h")) -sync:value("12", translate("12h")) -sync.rmempty = true - - -leds = s:taboption(this_tabb, Value, "smsled", translate("通知LED"), translate("选择通知LED。")) -if try_leds then -local node -local status -for node in try_leds do -local status = node -local all = string.sub (status, 17) -leds:value(all, all) -end -end - -oled = s:taboption(this_tabb, ListValue, "ledtype", translate("该二极管只专门用于这些通知"), translate("如果路由器只有一个LED,或者LED是多任务的,就选'No'。")) -oled.default = "D" -oled:value("S", translate("No")) -oled:value("D", translate("Yes")) -oled.rmempty = true - -local timeon = s:taboption(this_tabb, Value, "ledtimeon", translate("每(几)秒打开LED灯"), translate("指定LED应该亮多长时间。")) -timeon.rmempty = false -timeon.maxlength = 3 -timeon.default = 1 - -local timeoff = s:taboption(this_tabb, Value, "ledtimeoff", translate("每(几)秒关闭LED灯"), translate("指定LED应该关闭多长时间。")) -timeoff.rmempty = false -timeoff.maxlength = 3 -timeoff.default = 5 - -return m diff --git a/luci-app-sms-tool/luasrc/view/modem/atcommands.htm b/luci-app-sms-tool/luasrc/view/modem/atcommands.htm deleted file mode 100644 index 3510d8b..0000000 --- a/luci-app-sms-tool/luasrc/view/modem/atcommands.htm +++ /dev/null @@ -1,136 +0,0 @@ -<%+header%> - - - -

      <%:AT 命令%>

      -
      <%:通过sms_tool处理AT命令的Web用户界面。关于sms-tool的更多信息,请见%> <%:eko.one.pl 论坛%>.
      -

      -

      <%:向调制解调器发送命令%>

      -
      - -
      -
      <%:用户AT命令%>:
      - -
      - -
      -
      -
      - -
      -
      <%:要发送的命令%>:
      -
      -
      - -
      - -
      -
      <%:回复%>: -

      -

      - -
      -
      -
      - -
      - - - -<%+footer%> - diff --git a/luci-app-sms-tool/luasrc/view/modem/readsms.htm b/luci-app-sms-tool/luasrc/view/modem/readsms.htm deleted file mode 100644 index dc8245e..0000000 --- a/luci-app-sms-tool/luasrc/view/modem/readsms.htm +++ /dev/null @@ -1,285 +0,0 @@ -<% - local util = require "luci.util" - local fs = require "nixio.fs" - local sys = require "luci.sys" - local http = require "luci.http" - local dispatcher = require "luci.dispatcher" - local uci = require "luci.model.uci".cursor() - - local devv = tostring(uci:get("sms_tool", "general", "readport")) - local smsmem = tostring(uci:get("sms_tool", "general", "storage")) - local sms = tostring(luci.sys.exec("sms_tool -s" .. smsmem .. " -d " .. devv .. " -f '%Y-%m-%d %H:%M' -j recv 2>/dev/null")) - local smsmer = tostring(uci:get("sms_tool", "general", "mergesms")) - local smscuta = string.sub (sms, 8) - local smscut = smscuta:sub(1, #smscuta - 2) - local statusb = luci.util.exec("sms_tool -s" .. smsmem .. " -d ".. devv .. " status") - local all = statusb:match('[^: ]+$') - local location = "" - local l = string.sub (statusb, 15, 16) - if l == "SM" then - location = translate("SIM card") - end - if l == "ME" then - location = translate("Modem memory") - end --%> - -<%+header%> - - - - - - - -

      <%:短信%>

      -
      <%:通过sms_tool接收信息的Web用户界面。关于短信工具的更多信息,请见%> <%:eko.one.pl 论坛%>
      -

      -

      <%:接收的信息%>

      -
      -
      <%:信息存储在%>:
      <%=location%>
      -
      <%:信息 (收件箱 / 最大值)%>:
      -
      - - - - - - - - - - -
      <%:来自%><%:收到%><%:信息%>
      - -
      -
      - -
      -
      -     - -
      -
      - -<%+footer%> diff --git a/luci-app-sms-tool/luasrc/view/modem/sendsms.htm b/luci-app-sms-tool/luasrc/view/modem/sendsms.htm deleted file mode 100644 index f9747c6..0000000 --- a/luci-app-sms-tool/luasrc/view/modem/sendsms.htm +++ /dev/null @@ -1,237 +0,0 @@ -<% - local util = require "luci.util" - local sys = require "luci.sys" - local uci = require "luci.model.uci".cursor() - - local pon = tostring(uci:get("sms_tool", "general", "prefix")) - local pnumber = tostring(uci:get("sms_tool", "general", "pnumber")) - local info = tostring(uci:get("sms_tool", "general", "information")) - --%> - -<%+header%> - - - - - - - - -

      <%:短信%>

      -
      <%:通过sms_tool发送信息的Web用户界面。关于短信工具的更多信息,请见%> <%:eko.one.pl 论坛%>.
      -

      - -

      <%:发送短信%>

      - -
      - -
      -
      <%:用户电话簿%>:
      -
      - - -
      -
      -
      - -
      -
      <%:发送至%>:
      -
      -
      -
      -
      -
      <%:消息正文%>:
      -
      160
      -
      -
      - -
      -
      <%:状态%>:
      - -
      - -
      -
      - -
      -
      -
      - -
      - - - -<%+footer%> diff --git a/luci-app-sms-tool/luasrc/view/modem/ussd.htm b/luci-app-sms-tool/luasrc/view/modem/ussd.htm deleted file mode 100644 index 38be1c3..0000000 --- a/luci-app-sms-tool/luasrc/view/modem/ussd.htm +++ /dev/null @@ -1,265 +0,0 @@ -<% - local util = require "luci.util" - local fs = require "nixio.fs" - local sys = require "luci.sys" - local http = require "luci.http" - local dispatcher = require "luci.dispatcher" - local uci = require "luci.model.uci".cursor() - --%> - - -<%+header%> - - - -

      <%:USSD 代码%>

      -
      <%:通过sms_tool处理USSD代码的Web用户界面。关于短信工具的更多信息,请见%> <%:eko.one.pl forum%>.
      -

      -

      <%:发送 USSD 代码%>

      -
      - -
      -
      <%:用户 USSD 代码%>:
      - -
      - -
      -
      -
      - -
      -
      <%:要发送的代码%>:
      -
      - -
      -
      -
      <%:回复%>:
      - -
      -
      - -
      -
      -
      -
      - -
      - - - -<%+footer%> diff --git a/luci-app-sms-tool/po/pl/sms-tool.po b/luci-app-sms-tool/po/pl/sms-tool.po deleted file mode 100644 index 2ef0778..0000000 --- a/luci-app-sms-tool/po/pl/sms-tool.po +++ /dev/null @@ -1,288 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" - -"Language: pl\n" -"Last-Translator: Rafał Wabik (IceG) - From eko.one.pl forum\n" - -msgid "SMS Messages" -msgstr "Wiadomości SMS" - -msgid "Received Messages" -msgstr "Odebrane wiadomości" - -msgid "Send Messages" -msgstr "Wysyłanie wiadomości" - -msgid "USSD" -msgstr "USSD" - -msgid "From" -msgstr "Nadawca" - -msgid "Received" -msgstr "Odebrano" - -msgid "Message" -msgstr "Wiadomość" - -msgid "Configuration" -msgstr "Ustawienia" - -msgid "Sample codes" -msgstr "Przykładowe kody" - -msgid "Sending USSD codes" -msgstr "Wysyłanie kodów USSD" - -msgid "Please enter phone number" -msgstr "Proszę podać numer telefonu" - -msgid "Please correct phone number" -msgstr "Proszę poprawić numer telefonu" - -msgid "Please enter a message text" -msgstr "Proszę podać treść wiadomości" - -msgid "Please select the message(s) to be deleted" -msgstr "Proszę wybrać wiadomość(-ci) do usunięcia" - -msgid "Reply" -msgstr "Odpowiedź" - -msgid "SMS sent sucessfully" -msgstr "SMS został wysłany" - -msgid "Please enter a USSD code" -msgstr "Proszę podać kod do wysłania" - -msgid "Delete selected message(s)?" -msgstr "Usunąć wybraną(-e) wiadomość(-ci)?" - -msgid "Delete all the messages?" -msgstr "Usunąć wszystkie wiadomości?" - -msgid "Configuration sms-tool" -msgstr "Konfiguracja sms-tool" - -msgid "Configuration panel for sms_tool and gui application." -msgstr "Panel ustawień dla aplikacji sms_tool oraz dla interfejsu użytkownika." - -msgid "Device" -msgstr "Urządzenie" - -msgid "Web UI for handling messages via sms_tool." -msgstr "Interfejs użytkownika dla sms_tool do obsługi wiadomości SMS." - -msgid "Web UI for handling USSD codes via sms_tool." -msgstr "Interfejs użytkownika dla sms_tool do obsługi kodów USSD." - -msgid "SIM card" -msgstr "Karta SIM" - -msgid "Modem memory" -msgstr "Pamięć modemu" - -msgid "Messages store in" -msgstr "Miejsce przechowywania wiadomości" - -msgid "Messages (Inbox / Maximum)" -msgstr "Wiadomości (Odebrane / Maksymalnie)" - -msgid "Delete Selected" -msgstr "Usuń wybraną" - -msgid "Delete message(s)" -msgstr "Usuń wiadomość(-ci)" - -msgid "Delete All" -msgstr "Usuń wszystkie" - -msgid "USSD Codes" -msgstr "Kody USSD" - -msgid "Send to" -msgstr "Wyślij do" - -msgid "Message text" -msgstr "Treść wiadomości" - -msgid "Send Message" -msgstr "Wyślij SMS" - -msgid "Code to send" -msgstr "Kod do wysłania" - -msgid "Send Code" -msgstr "Wyślij kod" - -msgid "SMS Settings" -msgstr "Ustawienia dla wiadomości SMS" - -msgid "USSD Codes Settings" -msgstr "Ustawienia dla kodów USSD" - -msgid "SMS Reading Port" -msgstr "Port do odczytu SMS" - -msgid "SMS Sending Port" -msgstr "Port do wysyłania SMS" - -msgid "USSD Sending Port" -msgstr "Port do wysyłania kodów USSD" - -msgid "Add Prefix to Phone Number" -msgstr "Dodaj prefiks do numeru telefonu" - -msgid "Automatically add prefix to the phone number field." -msgstr "Automatycznie uzupełnij pole numeru telefonu o prefiks." - -msgid "Prefix Number" -msgstr "Numer prefiks" - -msgid "PHONE_NUMBER" -msgstr "48NumerTelefonu" - -msgid "Refresh SMS" -msgstr "Odśwież" - -msgid "Sending USSD Code in plain text" -msgstr "Wysyłaj kod USSD jawnym tekstem" - -msgid "Receive message without PDU decoding" -msgstr "Odbierz wiadomość bez dekodowania jej jako PDU" - -msgid "Send the USSD code in plain text. Command is not being coded to the PDU." -msgstr "Wysyła kod USSD jawnym tekstem. Polecenie nie jest dekodowane na PDU." - -msgid "Receive and display the message without decoding it as a PDU." -msgstr "Odebrana wiadomość wyświetlana jest bez dekodowania jej jako PDU." - -msgid "Explanation of number and prefix" -msgstr "Wyjaśnienie dot. numeru i prefiksu" - -msgid "In the tab for sending SMSes, show an explanation of the prefix and the correct phone number." -msgstr "W zakładce umożliwiającej wysyłanie SMS-ów pokaż wyjaśnienie dotyczące prefiksu i poprawnego numeru telefonu." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without '+'). If the number is 5, 4 or 3 characters, it is treated as 'short' and should not be preceded by a country prefix." -msgstr "Numer telefonu należy poprzedzić prefiksem kraju (dla Polski jest to 48, bez znaku '+'). Jeżeli numer jest 5, 4 lub 3 znakowy to jest on traktowany jako 'krótki' i nie należy go poprzedzać prefiksem kraju." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without +). If the number is 5, 4 or 3 characters, it is treated as.. short and should not be preceded by a country prefix." -msgstr "Numer telefonu należy poprzedzić prefiksem kraju (dla Polski jest to 48, bez znaku +). Jeżeli numer jest 5, 4 lub 3 znakowy to jest on traktowany jako krótki i nie należy go poprzedzać prefiksem kraju." - -msgid "Each line must have the following format: 'Contact name;Phone number'. Save to file '/etc/config/phonebook.user'." -msgstr "Każda linijka powinna mieć następujący format: 'Nazwa kontaktu;Numer telefonu'. Dla wygody kontakty użytkownika zapisywane są w pliku '/etc/config/phonebook.user'." - -msgid "User Phonebook" -msgstr "Kontakty użytkownika" - -msgid "User USSD Codes" -msgstr "Kody USSD użytkownika" - -msgid "Each line must have the following format: 'Code name;Code'. Save to file '/etc/config/ussd.user'." -msgstr "Każda linijka powinna mieć następujący format: 'Etykieta kodu;Kod'. Dla wygody kody użytkownika zapisywane są w pliku '/etc/config/ussd.user'." - -msgid "Notification Settings" -msgstr "Ustawienia powiadomień" - -msgid "The LED informs about a new message. Before activating this function, please config and save the SMS reading port, time to check SMS inbox and select the notification LED." -msgstr "Powiadomienie diodą o nowej wiadomości. Przed uruchomieniem tej funkcji proszę ustawić port odczytu wiadomości, czas sprawdzania skrzynki odbiorczej oraz wybrać diodę powiadomień." - -msgid "Check inbox every minute(s)" -msgstr "Sprawdzaj skrzynkę odbiorczą co minut(-y)" - -msgid "Specify how many minutes you want your inbox to be checked." -msgstr "Podaj co ile minut ma być sprawdzana skrzynka odbiorcza w poszukiwaniu nowych wiadomości." - -msgid "Notification LED" -msgstr "Dioda powiadomień" - -msgid "Select the notification LED." -msgstr "Wybierz diodę powiadomień." - -msgid "Notify new messages" -msgstr "Powiadomienie o nowych wiadomościach" - -msgid "Turn on the LED for seconds(s)" -msgstr "Włącz diodę na sekund(-y)" - -msgid "Turn off the LED for seconds(s)" -msgstr "Wyłącz diodę na sekund(-y)" - -msgid "Specify for how long the LED should be on." -msgstr "Podaj przez jaki czas dioda ma być włączona." - -msgid "Specify for how long the LED should be off." -msgstr "Podaj przez jaki czas dioda ma być wyłączona." - -msgid "Merge split messages" -msgstr "Połącz podzielone wiadomości" - -msgid "Checking this option will make it easier to read the messages, but it will cause a discrepancy in the number of messages shown and received." -msgstr "Podzielone wiadomości zostaną złączone. Zaznaczenie tej opcji ułatwi czytanie SMS-ów, ale spowoduje niezgodność w ilości pokazanych, odebranych wiadomości." - -msgid "Message storage area" -msgstr "Miejsce przechowywania wiadomości" - -msgid "Messages are stored in a specific location (for example, on the SIM card or modem memory), but other areas may also be available depending on the type of device." -msgstr "Wiadomości przechowywane są w określonym miejscu (np. na karcie SIM lub pamięci modemu), ale w zależności od typu urządzenia mogą być dostępne także inne obszary." - -msgid "AT Commands" -msgstr "Polecenia AT" - -msgid "Web UI for handling AT commands via sms_tool." -msgstr "Interfejs użytkownika dla sms_tool do obsługi poleceń AT." - -msgid "Sending commands to modem" -msgstr "Wysyłanie poleceń do modemu" - -msgid "User AT Commands" -msgstr "Polecenia AT użytkownika" - -msgid "Command to send" -msgstr "Polecenie do wysłania" - -msgid "Please enter a AT Command" -msgstr "Proszę podać polecenie AT do wysłania" - -msgid "AT Commands Sending Port" -msgstr "Port do wysyłania poleceń AT" - -msgid "Send Command" -msgstr "Wyślij polecenie" - -msgid "AT Commands Settings" -msgstr "Ustawienia dla poleceń AT" - -msgid "Each line must have the following format: 'AT Command name;AT Command'. Save to file '/etc/config/atcmds.user'." -msgstr "Każda linijka powinna mieć następujący format: 'Etykieta polecenia;polecenie AT'. Dla wygody polecenia użytkownika zapisywane są w pliku '/etc/config/atcmds.user'." - -msgid "Restart the inbox checking process every" -msgstr "Uruchom proces ponownie po" - -msgid "The process will restart at the selected time interval. This will eliminate the delay in checking your inbox." -msgstr "Proces zostanie uruchomiony ponownie po wybranym przez użytkownika czasie. Pozwoli to wyeliminować opóźnienie w sprawdzaniu skrzynki odbiorczej." - -msgid "4h" -msgstr "4 godz." - -msgid "6h" -msgstr "6 godz." - -msgid "8h" -msgstr "8 godz." - -msgid "12h" -msgstr "12 godz." - -msgid "The diode is dedicated only to these notifications" -msgstr "Dioda jest dedykowana tylko tym powiadomieniom" - -msgid "Select 'No' in case the router has only one LED or if the LED is multi-tasking." -msgstr "Wybierz 'Nie' w przypadku, kiedy router ma tylko jedną diodę lub gdy dioda obsługuje wiele zadań." - -msgid "No" -msgstr "Nie" - -msgid "Yes" -msgstr "Tak" - diff --git a/luci-app-sms-tool/po/zh-cn/sms-tool.po b/luci-app-sms-tool/po/zh-cn/sms-tool.po deleted file mode 100644 index 4417c9c..0000000 --- a/luci-app-sms-tool/po/zh-cn/sms-tool.po +++ /dev/null @@ -1,246 +0,0 @@ -msgid "Modem" -msgstr "调制解调器" - -msgid "SMS Messages" -msgstr "SMS 信息" - -msgid "Received Messages" -msgstr "接收信息" - -msgid "Send Messages" -msgstr "发送信息" - -msgid "From" -msgstr "发件人" - -msgid "Received" -msgstr "接收时间" - -msgid "Message" -msgstr "信息" - -msgid "Configuration" -msgstr "参数配置" - -msgid "Sample codes" -msgstr "代码样本" - -msgid "Please enter phone number" -msgstr "请输入手机号" - -msgid "Please correct phone number" -msgstr "请更正手机号" - -msgid "Please enter a message text" -msgstr "请输入信息内容" - -msgid "Please select the message(s) to be deleted" -msgstr "请选择要删除的信息" - -msgid "Reply" -msgstr "回复" - -msgid "SMS sent sucessfully" -msgstr "信息发送成功" - -msgid "Delete selected message(s)?" -msgstr "删除选择的信息?" - -msgid "Delete all the messages?" -msgstr "删除所有信息?" - -msgid "Configuration sms-tool" -msgstr "配置 sms-tool" - -msgid "Configuration panel for sms_tool and gui application." -msgstr "sms_tool 和 gui 应用程序的配置面板." - -msgid "Device" -msgstr "设备" - -msgid "Web UI for handling messages via sms_tool." -msgstr "用于通过 sms_tool 处理信息的 Web UI." - -msgid "Web UI for sending messages via sms_tool." -msgstr "用于通过 sms_tool 发送信息的 Web UI." - -msgid "Web UI for receiveling messages via sms_tool." -msgstr "用于通过 sms_tool 接收信息的 Web UI." - -msgid "SIM card" -msgstr "SIM卡" - -msgid "Modem memory" -msgstr "Modem内存" - -msgid "Messages store in" -msgstr "信息存储在" - -msgid "Messages (Inbox / Maximum)" -msgstr "信息(收件箱/最大)" - -msgid "Delete Selected" -msgstr "删除所选" - -msgid "Delete message(s)" -msgstr "删除信息" - -msgid "Delete All" -msgstr "删除所有" - -msgid "Send to" -msgstr "发送到" - -msgid "Message text" -msgstr "信息文本" - -msgid "Send Message" -msgstr "发送信息" - -msgid "Code to send" -msgstr "代码发送" - -msgid "Send Code" -msgstr "发送代码" - -msgid "SMS Settings" -msgstr "SMS 设置" - -msgid "SMS Reading Port" -msgstr "SMS 读取端口" - -msgid "SMS Sending Port" -msgstr "SMS 发送端口" - -msgid "Add Prefix to Phone Number" -msgstr "为手机号码添加前缀" - -msgid "Automatically add prefix to the phone number field." -msgstr "自动为手机号码字段添加前缀." - -msgid "Prefix Number" -msgstr "前缀编号" - -msgid "PHONE_NUMBER" -msgstr "手机号码" - -msgid "Refresh SMS" -msgstr "刷新信息" - -msgid "Explanation of number and prefix" -msgstr "数字和前缀的解释" - -msgid "In the tab for sending SMSes, show an explanation of the prefix and the correct phone number." -msgstr "在发送短信的选项卡中,显示前缀说明和正确的电话号码." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without '+'). If the number is 5, 4 or 3 characters, it is treated as 'short' and should not be preceded by a country prefix." -msgstr "电话号码前面应有国家/地区前缀(中国为 86,不带“+”), 号码是 5、4 或 3 个字符的短号除外." - -msgid "The phone number should be preceded by the country prefix (for Poland it is 48, without +). If the number is 5, 4 or 3 characters, it is treated as.. short and should not be preceded by a country prefix." -msgstr "电话号码前面应有国家/地区前缀(中国为 86,不带“+”), 号码是 5、4 或 3 个字符的短号除外." - -msgid "Each line must have the following format: 'Contact name;Phone number'. Save to file '/etc/config/phonebook.user'." -msgstr "每行必须具有以下格式:“联系人姓名;电话号码”。 保存到文件“/etc/config/phonebook.user”." - -msgid "User Phonebook" -msgstr "电话簿" - -msgid "Notification Settings" -msgstr "通知设置" - -msgid "The LED informs about a new message. Before activating this function, please config and save the SMS reading port, time to check SMS inbox and select the notification LED." -msgstr "LED 新消息通知。 激活此功能前,请配置并保存短信阅读端口,及时查看短信收件箱并选择通知LED." - -msgid "Check inbox every minute(s)" -msgstr "每分钟检查收件箱" - -msgid "Specify how many minutes you want your inbox to be checked." -msgstr "指定要检查收件箱的分钟数." - -msgid "Notification LED" -msgstr "通知LED" - -msgid "Select the notification LED." -msgstr "选择通知LED." - -msgid "Notify new messages" -msgstr "通知新消息" - -msgid "Turn on the LED for seconds(s)" -msgstr "打开LED秒数" - -msgid "Turn off the LED for seconds(s)" -msgstr "关闭LED秒数" - -msgid "Specify for how long the LED should be on." -msgstr "指定 LED 应亮多长时间." - -msgid "Specify for how long the LED should be off." -msgstr "指定 LED 应关闭多长时间." - -msgid "Merge split messages" -msgstr "合并分割的消息" - -msgid "Checking this option will make it easier to read the messages, but it will cause a discrepancy in the number of messages shown and received." -msgstr "选中此选项将使阅读消息更容易,但会导致显示和接收的消息数量出现差异." - -msgid "Message storage area" -msgstr "消息存储区" - -msgid "Messages are stored in a specific location (for example, on the SIM card or modem memory), but other areas may also be available depending on the type of device." -msgstr "消息存储在特定位置(例如,SIM 卡或调制解调器内存中),但其他区域也可能可用,具体取决于设备类型." - -msgid "AT Commands" -msgstr "AT 命令" - -msgid "Web UI for handling AT commands via sms_tool." -msgstr "用于通过 sms_tool 处理 AT 命令的 Web UI." - -msgid "Sending commands to modem" -msgstr "向调制解调器发送命令" - -msgid "User AT Commands" -msgstr "用户 AT 命令" - -msgid "Command to send" -msgstr "命令发送" - -msgid "Please enter a AT Command" -msgstr "请输入 AT 命令" - -msgid "AT Commands Sending Port" -msgstr "AT命令发送端口" - -msgid "Send Command" -msgstr "发送命令" - -msgid "AT Commands Settings" -msgstr "AT命令设置" - -msgid "Each line must have the following format: 'AT Command name;AT Command'. Save to file '/etc/config/atcmds.user'." -msgstr "每行必须具有以下格式:'AT Command name;AT Command'。 保存到文件“/etc/config/atcmds.user”." - -msgid "Restart the inbox checking process every" -msgstr "每次重新启动收件箱检查过程" - -msgid "The process will restart at the selected time interval. This will eliminate the delay in checking your inbox." -msgstr "该过程将在选定的时间间隔重新开始。 这将消除检查收件箱的延迟." - -msgid "4h" -msgstr "4小时." - -msgid "6h" -msgstr "6小时." - -msgid "8h" -msgstr "8小时." - -msgid "12h" -msgstr "12小时." - -msgid "The diode is dedicated only to these notifications" -msgstr "二极管仅用于这些通知" - -msgid "Select 'No' in case the router has only one LED or if the LED is multi-tasking." -msgstr "如果路由器只有一个 LED 或者 LED 是多任务处理,请选择“否”." - diff --git a/luci-app-sms-tool/root/etc/config/atcmds.user b/luci-app-sms-tool/root/etc/config/atcmds.user deleted file mode 100644 index 44bafb9..0000000 --- a/luci-app-sms-tool/root/etc/config/atcmds.user +++ /dev/null @@ -1,28 +0,0 @@ -------查询------;AT -查看IMEI;AT+CGSN -固件版本信息;AT+GMR -信号强度;AT+CSQ -正在使用的网络信息;AT+QNWINFO -查询限速;AT+C5GQOSRDP=1 -模块温度;AT+QTEMP -查询运营商名称;AT+QSPN -查询小区信息;AT+QENG="servingcell" ------3/4/5G网络配置-----;AT -查询当前网络搜索模式;AT+QNWPREFCFG="mode_pref" -!切换仅3G;AT+QNWPREFCFG="mode_pref",WCDMA -切换仅4G;AT+QNWPREFCFG="mode_pref",LTE -切换仅5G;AT+QNWPREFCFG="mode_pref",NR5G -切换5,4G;AT+QNWPREFCFG="mode_pref",NR5G:LTE -切换AUTO;AT+QNWPREFCFG="mode_pref",AUTO ------锁频段-----;AT -查询支持的所有频段;AT+QNWPREFCFG=? -查询当前配置的5G频段;AT+QNWPREFCFG="nr5g_band" -查询当前配置的4G频段;AT+QNWPREFCFG="lte_band" -!5G锁频段(78);AT+QNWPREFCFG="nr5g_band",78 -5G默认频段;AT+QNWPREFCFG="nr5g_band",1:28:41:77:78:79 -!4G锁频段(1);AT+QNWPREFCFG="lte_band",1 -4G默认频段;AT+QNWPREFCFG="lte_band",1:2:3:5:7:8:20:28:34:38:39:40:41 ------MORE-----;AT -查看产品型号;ATI -挂断现有语音;ATH -!更改IMEI,需重启;AT+EGMR=1,7,"868227050701486" \ No newline at end of file diff --git a/luci-app-sms-tool/root/etc/config/phonebook.user b/luci-app-sms-tool/root/etc/config/phonebook.user deleted file mode 100644 index 74c98ab..0000000 --- a/luci-app-sms-tool/root/etc/config/phonebook.user +++ /dev/null @@ -1 +0,0 @@ -other user;8613188888888 diff --git a/luci-app-sms-tool/root/etc/config/sms_tool b/luci-app-sms-tool/root/etc/config/sms_tool deleted file mode 100644 index 7bff8f6..0000000 --- a/luci-app-sms-tool/root/etc/config/sms_tool +++ /dev/null @@ -1,14 +0,0 @@ - -config sms_tool 'general' - option pnumber '86' - option prefix '1' - option ledtimeon '1' - option ledtimeoff '5' - option lednotify '0' - option checktime '10' - option mergesms '0' - option information '0' - option pdu '0' - option storage 'SM' - option prestart '6' - option ledtype 'D' diff --git a/luci-app-sms-tool/root/etc/init.d/smsled b/luci-app-sms-tool/root/etc/init.d/smsled deleted file mode 100755 index 2442b14..0000000 --- a/luci-app-sms-tool/root/etc/init.d/smsled +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright 2020 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -USE_PROCD=1 -START=99 -STOP=01 - -start_service() { - procd_open_instance - procd_set_param command /bin/sh "/sbin/smsled-init.sh" - procd_close_instance -} - -stop_service() { - for KILLPID in `ps | grep 'smsled' | awk ' { print $1;}'`; do - (kill -9 $KILLPID >/dev/null 2>&1 )& - done - sleep 1 - return 0 -} - -restart_service() { - stop_service - start_service -} diff --git a/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh b/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh deleted file mode 100755 index fbc77d7..0000000 --- a/luci-app-sms-tool/root/etc/uci-defaults/set_sms_ports.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# Copyright 2020-2021 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -work=false -for port in /dev/ttyUSB* -do - [[ -e $port ]] || continue - gcom -d $port info &> /tmp/testusb - testUSB=`cat /tmp/testusb | grep "Error\|Can't"` - if [ -z "$testUSB" ]; then - work=$port - break - fi -done -rm -rf /tmp/testusb - -if [ $work != false ]; then -uci set sms_tool.@sms_tool[0].readport=$work -uci set sms_tool.@sms_tool[0].sendport=$work -uci set sms_tool.@sms_tool[0].atport=$work -uci commit sms_tool -fi diff --git a/luci-app-sms-tool/root/etc/uci-defaults/start-smsled b/luci-app-sms-tool/root/etc/uci-defaults/start-smsled deleted file mode 100755 index 95ca388..0000000 --- a/luci-app-sms-tool/root/etc/uci-defaults/start-smsled +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# Copyright 2020 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -/etc/init.d/smsled disable - -exit 0 diff --git a/luci-app-sms-tool/root/sbin/cronsync.sh b/luci-app-sms-tool/root/sbin/cronsync.sh deleted file mode 100755 index 39f7899..0000000 --- a/luci-app-sms-tool/root/sbin/cronsync.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -[ -e /etc/crontabs/root ] || touch /etc/crontabs/root - -SLED=$(uci -q get sms_tool.general.lednotify) -if [ "x$SLED" != "x1" ]; then - if grep -q "smsled" /etc/crontabs/root; then - grep -v "/init.d/smsled" /etc/crontabs/root > /tmp/new_cron - mv /tmp/new_cron /etc/crontabs/root - /etc/init.d/cron restart - fi - exit 0 -fi - -if ! grep -q "smsled" /etc/crontabs/root; then -PTR=$(uci -q get sms_tool.general.prestart) - echo "1 */$PTR * * * /etc/init.d/smsled enable" >> /etc/crontabs/root - /etc/init.d/cron restart -fi - -exit 0 diff --git a/luci-app-sms-tool/root/sbin/set_sms_ports.sh b/luci-app-sms-tool/root/sbin/set_sms_ports.sh deleted file mode 100755 index e89eb17..0000000 --- a/luci-app-sms-tool/root/sbin/set_sms_ports.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# Copyright 2020-2021 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -work=false -for port in /dev/ttyUSB* -do - [[ -e $port ]] || continue - gcom -d $port info &> /tmp/testusb - testUSB=`cat /tmp/testusb | grep "Error\|Can't"` - if [ -z "$testUSB" ]; then - work=$port - break - fi -done -rm -rf /tmp/testusb - -if [ $work != false ]; then -uci set sms_tool.@sms_tool[0].readport=$work -uci set sms_tool.@sms_tool[0].sendport=$work -uci set sms_tool.@sms_tool[0].ussdport=$work -uci set sms_tool.@sms_tool[0].atport=$work -uci commit sms_tool -fi diff --git a/luci-app-sms-tool/root/sbin/smsled-init.sh b/luci-app-sms-tool/root/sbin/smsled-init.sh deleted file mode 100755 index fa7d863..0000000 --- a/luci-app-sms-tool/root/sbin/smsled-init.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -# Copyright 2020 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - -sleep 10 -CT=$(uci -q get sms_tool.general.checktime) -TX=$(echo $CT | tr -dc '0-9') -TM=$(($TX * 60)) - -while [ 1 ]; do - LED=$(uci -q get sms_tool.general.lednotify) - if [ $LED == "1" ]; then - sleep $TM - (/sbin/smsled.sh >/dev/null 2>&1 )& - continue - fi - sleep 1 -done - -exit 0 - diff --git a/luci-app-sms-tool/root/sbin/smsled.sh b/luci-app-sms-tool/root/sbin/smsled.sh deleted file mode 100755 index fffd856..0000000 --- a/luci-app-sms-tool/root/sbin/smsled.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# Copyright 2020-2021 Rafał Wabik (IceG) - From eko.one.pl forum -# Licensed to the GNU General Public License v3.0. - - DEV=$(uci -q get sms_tool.general.readport) - LEDX=$(uci -q get sms_tool.general.smsled) - MEM=$(uci -q get sms_tool.general.storage) - STX=$(sms_tool -s $MEM -d $DEV status | cut -c23-27) - SMS=$(echo $STX | tr -dc '0-9') - SMSC=$(cat /etc/config/sms_count) - LEDT="/sys/class/leds/$LEDX/trigger" - LEDON="/sys/class/leds/$LEDX/delay_on" - LEDOFF="/sys/class/leds/$LEDX/delay_off" - LED="/sys/class/leds/$LEDX/brightness" - - LON=$(uci -q get sms_tool.general.ledtimeon) - TXON=$(echo $LON | tr -dc '0-9') - TMON=$(($TXON * 1000)) - - LOFF=$(uci -q get sms_tool.general.ledtimeoff) - TXOFF=$(echo $LOFF | tr -dc '0-9') - TMOFF=$(($TXOFF * 1000)) - -if [ $SMS == $SMSC ]; then - - exit 0 -fi - -if [ $SMS > $SMSC ]; then - -echo timer > $LEDT -echo $TMOFF > $LEDOFF -echo $TMON > $LEDON -exit 0 - -fi - - -exit 0 diff --git a/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json b/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json deleted file mode 100644 index 3f4e02f..0000000 --- a/luci-app-sms-tool/root/usr/share/rpcd/acl.d/luci-app-sms-tool.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "luci-app-sms-tool": { - "description": "Grant UCI and file access for luci-app-sms-tool", - "read": { - "file": { - "/usr/bin/sms_tool *": [ "exec" ], - }, - "uci": [ "sms_tool" ] - }, - "write": { - "file": { - "/usr/bin/sms_tool *": [ "exec" ], - - }, - "uci": [ "sms_tool" ] - } - } -} - - - - - - diff --git a/luci-app-spdmodem/Makefile b/luci-app-spdmodem/Makefile deleted file mode 100644 index 988ee1c..0000000 --- a/luci-app-spdmodem/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=SPD Modem Server -LUCI_DEPENDS:=+luci-compat +kmod-sprd_pcie - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-spdmodem/luasrc/controller/spdmodem.lua b/luci-app-spdmodem/luasrc/controller/spdmodem.lua deleted file mode 100644 index c0164bb..0000000 --- a/luci-app-spdmodem/luasrc/controller/spdmodem.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.spdmodem", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/spdmodem") then - return - end - - entry({"admin", "network", "spdmodem"}, cbi("spdmodem"), _("SPD Modem Server"), 80).dependent = false -end diff --git a/luci-app-spdmodem/luasrc/model/cbi/spdmodem.lua b/luci-app-spdmodem/luasrc/model/cbi/spdmodem.lua deleted file mode 100644 index c6bade4..0000000 --- a/luci-app-spdmodem/luasrc/model/cbi/spdmodem.lua +++ /dev/null @@ -1,39 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -mp = Map("spdmodem") -mp.title = translate("SPD Modem Server") -mp.description = translate("Modem Server For OpenWrt") - -s = mp:section(TypedSection, "service", "Base Setting") -s.anonymous = true - -enabled = s:option(Flag, "enabled", translate("Enable")) -enabled.default = 0 -enabled.rmempty = false - -apn = s:option(Value, "apn", translate("APN")) -apn.rmempty = true - -pincode = s:option(Value, "pincode", translate("PIN")) -pincode.rmempty = true - -username = s:option(Value, "username", translate("PAP/CHAP username")) -username.rmempty = true - -password = s:option(Value, "password", translate("PAP/CHAP password")) -password.rmempty = true - -auth = s:option(Value, "auth", translate("Authentication Type")) -auth.rmempty = true -auth:value("", translate("-- Please choose --")) -auth:value("both", "PAP/CHAP (both)") -auth:value("pap", "PAP") -auth:value("chap", "CHAP") -auth:value("none", "NONE") - -tool = s:option(Value, "tool", translate("Tools")) -tool:value("quectel-CM", "quectel-CM") -tool.rmempty = true - -return mp diff --git a/luci-app-spdmodem/po/zh-cn/spdmodem.po b/luci-app-spdmodem/po/zh-cn/spdmodem.po deleted file mode 100644 index b10da0f..0000000 --- a/luci-app-spdmodem/po/zh-cn/spdmodem.po +++ /dev/null @@ -1,24 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: dingpengyu \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"X-Generator: Poedit 2.3.1\n" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "SPD Modem Server" -msgstr "SPD移动网络拨号服务" - -msgid "Modem Server For OpenWrt" -msgstr "OpenWrt移动网络拨号服务" - -msgid "Tools" -msgstr "拨号工具" diff --git a/luci-app-spdmodem/root/etc/config/spdmodem b/luci-app-spdmodem/root/etc/config/spdmodem deleted file mode 100644 index 05fad9b..0000000 --- a/luci-app-spdmodem/root/etc/config/spdmodem +++ /dev/null @@ -1,4 +0,0 @@ -config service - option tool 'quectel-CM' - option enabled '0' - diff --git a/luci-app-spdmodem/root/etc/init.d/spdmodem b/luci-app-spdmodem/root/etc/init.d/spdmodem deleted file mode 100644 index eece321..0000000 --- a/luci-app-spdmodem/root/etc/init.d/spdmodem +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2014 OpenWrt.org - -START=99 -STOP=16 -USE_PROCD=1 -#使用procd启动 - -run_5g() -{ - local enabled - config_get_bool enabled $1 enabled - - echo "run 4G" >> /tmp/log4g - - if [ "$enabled" = "1" ]; then - local user - local password - local apn - local auth - local pincode - local tool - - # echo "enable 5G" >> /tmp/log5g - config_get user $1 user - config_get password $1 password - config_get apn $1 apn - config_get auth $1 auth - config_get pincode $1 pincode - config_get tool $1 tool - config_get tty $1 tty - config_get atcmd $1 atcmd - - if [ "$tool" = "at" ];then - at_tool "$atcmd" -d $tty - else - procd_open_instance - #创建一个实例, 在procd看来一个应用程序可以多个实\E4\BE? - #ubus call service list 可以查看实例 - procd_set_param command $tool -i -s $apn - if [ "$password" != "" ];then - procd_append_param command $user $password $auth - fi - if [ "$pincode" != "" ]; then - procd_append_param command -p $pincode - fi - # procd_append_param command -f /tmp/4g.log - procd_set_param respawn - echo "quectel-CM has started." - procd_close_instance - #关闭实例 - fi - - fi -} - - -service_triggers() -{ - procd_add_reload_trigger "spdmodem" -} - -start_service() { - config_load spdmodem - config_foreach run_5g service -} - -stop_service() -{ - echo "5G stop" >> /tmp/log5g - killall quectel-CM - echo "quectel-CM has stoped." -} - - diff --git a/luci-app-spdmodem/root/etc/uci-defaults/luci-spdmodem b/luci-app-spdmodem/root/etc/uci-defaults/luci-spdmodem deleted file mode 100644 index faa1d1e..0000000 --- a/luci-app-spdmodem/root/etc/uci-defaults/luci-spdmodem +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@spdmodem[-1] - add ucitrack spdmodem - set ucitrack.@spdmodem[-1].init=spdmodem - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/luci-app-usbmodem/Makefile b/luci-app-usbmodem/Makefile deleted file mode 100644 index 826ed02..0000000 --- a/luci-app-usbmodem/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Modem Server -LUCI_DEPENDS:=+luci-compat +quectel-CM-5G +kmod-usb-acm \ - +kmod-usb-net-cdc-ether +kmod-usb-net-cdc-mbim \ - +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis \ - +kmod-usb-serial-option +kmod-usb-wdm \ - +kmod-qmi_wwan_f +kmod-qmi_wwan_q +usbutils - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-usbmodem/luasrc/controller/usbmodem.lua b/luci-app-usbmodem/luasrc/controller/usbmodem.lua deleted file mode 100644 index 6cf943c..0000000 --- a/luci-app-usbmodem/luasrc/controller/usbmodem.lua +++ /dev/null @@ -1,9 +0,0 @@ -module("luci.controller.usbmodem", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/usbmodem") then - return - end - - entry({"admin", "network", "usbmodem"}, cbi("usbmodem"), _("USB Modem Server"), 80).dependent = false -end diff --git a/luci-app-usbmodem/luasrc/model/cbi/usbmodem.lua b/luci-app-usbmodem/luasrc/model/cbi/usbmodem.lua deleted file mode 100644 index 97af802..0000000 --- a/luci-app-usbmodem/luasrc/model/cbi/usbmodem.lua +++ /dev/null @@ -1,51 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -mp = Map("usbmodem") -mp.title = translate("USB Modem Server") -mp.description = translate("Modem Server For OpenWrt") - -s = mp:section(TypedSection, "service", "Base Setting") -s.anonymous = true - -enabled = s:option(Flag, "enabled", translate("Enable")) -enabled.default = 0 -enabled.rmempty = false - -device = s:option(Value, "device", translate("Modem device")) -device.rmempty = false - -local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*") - -if device_suggestions then - local node - for node in device_suggestions do - device:value(node) - end -end - -apn = s:option(Value, "apn", translate("APN")) -apn.rmempty = true - -pincode = s:option(Value, "pincode", translate("PIN")) -pincode.rmempty = true - -username = s:option(Value, "username", translate("PAP/CHAP username")) -username.rmempty = true - -password = s:option(Value, "password", translate("PAP/CHAP password")) -password.rmempty = true - -auth = s:option(Value, "auth", translate("Authentication Type")) -auth.rmempty = true -auth:value("", translate("-- Please choose --")) -auth:value("both", "PAP/CHAP (both)") -auth:value("pap", "PAP") -auth:value("chap", "CHAP") -auth:value("none", "NONE") - -tool = s:option(Value, "tool", translate("Tools")) -tool:value("quectel-CM", "quectel-CM") -tool.rmempty = true - -return mp diff --git a/luci-app-usbmodem/po/zh-cn/usbmodem.po b/luci-app-usbmodem/po/zh-cn/usbmodem.po deleted file mode 100644 index 6459a00..0000000 --- a/luci-app-usbmodem/po/zh-cn/usbmodem.po +++ /dev/null @@ -1,24 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: dingpengyu \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"X-Generator: Poedit 2.3.1\n" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "USB Modem Server" -msgstr "USB移动网络拨号服务" - -msgid "Modem Server For OpenWrt" -msgstr "OpenWrt移动网络拨号服务" - -msgid "Tools" -msgstr "拨号工具" diff --git a/luci-app-usbmodem/root/etc/config/usbmodem b/luci-app-usbmodem/root/etc/config/usbmodem deleted file mode 100644 index 8d7627b..0000000 --- a/luci-app-usbmodem/root/etc/config/usbmodem +++ /dev/null @@ -1,5 +0,0 @@ -config service - option tool 'quectel-CM' - option device '/dev/cdc-wdm0' - option enabled '0' - diff --git a/luci-app-usbmodem/root/etc/init.d/usbmodem b/luci-app-usbmodem/root/etc/init.d/usbmodem deleted file mode 100644 index e5f1081..0000000 --- a/luci-app-usbmodem/root/etc/init.d/usbmodem +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2014 OpenWrt.org - -START=99 -STOP=16 -USE_PROCD=1 -#使用procd启动 - -run_4g() -{ - local enabled - config_get_bool enabled $1 enabled - - echo "run 4G" >> /tmp/log4g - - if [ "$enabled" = "1" ]; then - local user - local password - local apn - local auth - local pincode - local device - local tool - - # echo "enable 4G" >> /tmp/log4g - config_get user $1 user - config_get password $1 password - config_get apn $1 apn - config_get auth $1 auth - config_get pincode $1 pincode - config_get device $1 device - config_get tool $1 tool - config_get tty $1 tty - config_get atcmd $1 atcmd - - devname="$(basename "$device")" - devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" - ifname="$( ls "$devpath"/net )" - - if [ "$tool" = "at" ];then - at_tool "$atcmd" -d $tty - else - procd_open_instance - #创建一个实例, 在procd看来一个应用程序可以多个实\E4\BE? - #ubus call service list 可以查看实例 - procd_set_param command $tool -i $ifname -s $apn - if [ "$password" != "" ];then - procd_append_param command $user $password $auth - fi - if [ "$pincode" != "" ]; then - procd_append_param command -p $pincode - fi - # procd_append_param command -f /tmp/4g.log - procd_set_param respawn - echo "quectel-CM has started." - procd_close_instance - #关闭实例 - fi - - fi -} - - -service_triggers() -{ - procd_add_reload_trigger "usbmodem" -} - -start_service() { - config_load usbmodem - config_foreach run_4g service -} - -stop_service() -{ - echo "4G stop" >> /tmp/log4g - killall quectel-CM - echo "quectel-CM has stoped." -} - diff --git a/luci-app-usbmodem/root/etc/uci-defaults/luci-usbmodem b/luci-app-usbmodem/root/etc/uci-defaults/luci-usbmodem deleted file mode 100644 index 1b2ba06..0000000 --- a/luci-app-usbmodem/root/etc/uci-defaults/luci-usbmodem +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@usbmodem[-1] - add ucitrack usbmodem - set ucitrack.@usbmodem[-1].init=usbmodem - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/quectel_Gobinet/Makefile b/quectel_Gobinet/Makefile deleted file mode 100644 index abdba44..0000000 --- a/quectel_Gobinet/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=gobinet -PKG_VERSION:=1.6.3 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/gobinet - SUBMENU:=WWAN Support - TITLE:=Quectel Linux USB Gobinet Driver - DEPENDS:=+kmod-usb-net - FILES:=$(PKG_BUILD_DIR)/GobiNet.ko - AUTOLOAD:=$(call AutoLoad,81,GobiNet) -endef - -define KernelPackage/gobinet/description - Quectel Linux USB gobinet Driver -endef - -MAKE_OPTS:= \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CXXFLAGS="$(TARGET_CXXFLAGS)" \ - M="$(PKG_BUILD_DIR)" \ - $(EXTRA_KCONFIG) - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,gobinet)) diff --git a/quectel_Gobinet/src/GobiUSBNet.c b/quectel_Gobinet/src/GobiUSBNet.c deleted file mode 100644 index 689c173..0000000 --- a/quectel_Gobinet/src/GobiUSBNet.c +++ /dev/null @@ -1,3202 +0,0 @@ -/*=========================================================================== -FILE: - GobiUSBNet.c - -DESCRIPTION: - Qualcomm USB Network device for Gobi 3000 - -FUNCTIONS: - GobiNetSuspend - GobiNetResume - GobiNetDriverBind - GobiNetDriverUnbind - GobiUSBNetURBCallback - GobiUSBNetTXTimeout - GobiUSBNetAutoPMThread - GobiUSBNetStartXmit - GobiUSBNetOpen - GobiUSBNetStop - GobiUSBNetProbe - GobiUSBNetModInit - GobiUSBNetModExit - -Copyright (c) 2011, Code Aurora Forum. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Code Aurora Forum 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 OWNER 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 Files -//--------------------------------------------------------------------------- - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if LINUX_VERSION_CODE > KERNEL_VERSION(3,16,0) //8b094cd03b4a3793220d8d8d86a173bfea8c285b -#include -#else -#define timespec64 timespec -#define ktime_get_ts64 ktime_get_ts -#define timespec64_sub timespec_sub -#endif - -#include "Structs.h" -#include "QMIDevice.h" -#include "QMI.h" - -#ifndef ETH_P_MAP -#define ETH_P_MAP 0xDA1A -#endif - -#if (ETH_P_MAP == 0x00F9) -#undef ETH_P_MAP -#define ETH_P_MAP 0xDA1A -#endif - -//----------------------------------------------------------------------------- -// Definitions -//----------------------------------------------------------------------------- - -// Version Information -//add new module or new feature, increase major version. fix bug, increase minor version -#define VERSION_NUMBER "V1.6.3" -#define DRIVER_VERSION "Quectel_Linux&Android_GobiNet_Driver_"VERSION_NUMBER -#define DRIVER_AUTHOR "Qualcomm Innovation Center" -#define DRIVER_DESC "GobiNet" -static const char driver_name[] = "GobiNet"; - -// Debug flag -int quec_debug = 0; - -// Allow user interrupts -//int interruptible = 1; - -// Number of IP packets which may be queued up for transmit -static int txQueueLength = 100; - -// Class should be created during module init, so needs to be global -static struct class * gpClass; - -static const unsigned char ec20_mac[ETH_ALEN] = {0x02, 0x50, 0xf3, 0x00, 0x00, 0x00}; -static const unsigned char default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3, 0x00, 0x00, 0x00}; -static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00}; -//static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -//setup data call by "AT$QCRMCALL=1,1" -static uint __read_mostly qcrmcall_mode = 0; -module_param( qcrmcall_mode, uint, S_IRUGO | S_IWUSR ); - -static struct sk_buff * ether_to_ip_fixup(struct net_device *dev, struct sk_buff *skb) { - const struct ethhdr *ehdr; - - skb_reset_mac_header(skb); - ehdr = eth_hdr(skb); - - if (ehdr->h_proto == htons(ETH_P_IP)) { - if (unlikely(skb->len <= (sizeof(struct ethhdr) + sizeof(struct iphdr)))) { - goto drop_skb; - } - } - else if (ehdr->h_proto == htons(ETH_P_IPV6)) { - if (unlikely(skb->len <= (sizeof(struct ethhdr) + sizeof(struct ipv6hdr)))) { - goto drop_skb; - } - } - else { - DBG("%s skb h_proto is %04x\n", dev->name, ntohs(ehdr->h_proto)); - goto drop_skb; - } - - if (unlikely(skb_pull(skb, ETH_HLEN))) - return skb; - -drop_skb: - return NULL; -} - -//#define QUECTEL_REMOVE_TX_ZLP -#define USB_CDC_SET_REMOVE_TX_ZLP_COMMAND 0x5D - -//#define QUECTEL_WWAN_MULTI_PACKAGES - -#ifdef QUECTEL_WWAN_MULTI_PACKAGES -static uint __read_mostly rx_packets = 10; -module_param( rx_packets, uint, S_IRUGO | S_IWUSR ); - -#define USB_CDC_SET_MULTI_PACKAGE_COMMAND (0x5C) -#define QUEC_NET_MSG_SPEC (0x80) -#define QUEC_NET_MSG_ID_IP_DATA (0x00) - -struct multi_package_config { - __le32 enable; - __le32 package_max_len; - __le32 package_max_count_in_queue; - __le32 timeout; -} __packed; - -struct quec_net_package_header { - unsigned char msg_spec; - unsigned char msg_id; - unsigned short payload_len; - unsigned char reserve[16]; -} __packed; -#endif - -#ifdef QUECTEL_WWAN_QMAP -/* - Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V1.9.pdf - 5.6. Test QMAP on GobiNet or QMI WWAN - 0 - no QMAP - 1 - QMAP (Aggregation protocol) - X - QMAP (Multiplexing and Aggregation protocol) -*/ -static uint __read_mostly qmap_mode = 0; -module_param( qmap_mode, uint, S_IRUGO | S_IWUSR ); - -struct qmap_hdr { - u8 cd_rsvd_pad; - u8 mux_id; - u16 pkt_len; -} __packed; - -enum rmnet_map_v5_header_type { - RMNET_MAP_HEADER_TYPE_UNKNOWN, - RMNET_MAP_HEADER_TYPE_COALESCING = 0x1, - RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2, - RMNET_MAP_HEADER_TYPE_ENUM_LENGTH -}; - -/* Main QMAP header */ -struct rmnet_map_header { -#if defined(__LITTLE_ENDIAN_BITFIELD) - u8 pad_len:6; - u8 next_hdr:1; - u8 cd_bit:1; -#elif defined (__BIG_ENDIAN_BITFIELD) - u8 cd_bit:1; - u8 next_hdr:1; - u8 pad_len:6; -#else -#error "Please fix " -#endif - u8 mux_id; - __be16 pkt_len; -} __aligned(1); - -/* QMAP v5 headers */ -struct rmnet_map_v5_csum_header { -#if defined(__LITTLE_ENDIAN_BITFIELD) - u8 next_hdr:1; - u8 header_type:7; - u8 hw_reserved:7; - u8 csum_valid_required:1; -#elif defined (__BIG_ENDIAN_BITFIELD) - u8 header_type:7; - u8 next_hdr:1; - u8 csum_valid_required:1; - u8 hw_reserved:7; -#else -#error "Please fix " -#endif - __be16 reserved; -} __aligned(1); - -struct qmap_priv { - struct net_device *real_dev; - struct net_device *self_dev; - uint qmap_version; - uint offset_id; - uint mux_id; - uint link_state; - -#if defined(QUECTEL_UL_DATA_AGG) - /* QMIWDS_ADMIN_SET_DATA_FORMAT_RESP TLV_0x17 and TLV_0x18 */ - uint ul_data_aggregation_max_datagrams; //UplinkDataAggregationMaxDatagramsTlv - uint ul_data_aggregation_max_size; //UplinkDataAggregationMaxSizeTlv - uint dl_minimum_padding; //0x1A - - spinlock_t agg_lock; - struct sk_buff *agg_skb; - unsigned agg_count; - struct timespec64 agg_time; - struct hrtimer agg_hrtimer; - struct work_struct agg_wq; -#endif - -#ifdef QUECTEL_BRIDGE_MODE - int m_bridge_mode; - uint m_bridge_ipv4; - unsigned char mHostMAC[6]; -#endif -}; - -#ifdef QUECTEL_BRIDGE_MODE -static int is_qmap_netdev(const struct net_device *netdev); -#endif - -#endif - -#ifdef QUECTEL_BRIDGE_MODE -static int __read_mostly bridge_mode = 0/*|BIT(1)*/; -module_param( bridge_mode, int, S_IRUGO | S_IWUSR ); - -static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4) { - struct arphdr *parp; - u8 *arpptr, *sha; - u8 sip[4], tip[4], ipv4[4]; - struct sk_buff *reply = NULL; - - ipv4[0] = (bridge_ipv4 >> 24) & 0xFF; - ipv4[1] = (bridge_ipv4 >> 16) & 0xFF; - ipv4[2] = (bridge_ipv4 >> 8) & 0xFF; - ipv4[3] = (bridge_ipv4 >> 0) & 0xFF; - - parp = arp_hdr(skb); - - if (parp->ar_hrd == htons(ARPHRD_ETHER) && parp->ar_pro == htons(ETH_P_IP) - && parp->ar_op == htons(ARPOP_REQUEST) && parp->ar_hln == 6 && parp->ar_pln == 4) { - arpptr = (u8 *)parp + sizeof(struct arphdr); - sha = arpptr; - arpptr += net->addr_len; /* sha */ - memcpy(sip, arpptr, sizeof(sip)); - arpptr += sizeof(sip); - arpptr += net->addr_len; /* tha */ - memcpy(tip, arpptr, sizeof(tip)); - - pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d, ipv4=%d.%d.%d.%d\n", netdev_name(net), - sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3], ipv4[0], ipv4[1], ipv4[2], ipv4[3]); - //wwan0 sip = 10.151.137.255, tip=10.151.138.0, ipv4=10.151.137.255 - if (tip[0] == ipv4[0] && tip[1] == ipv4[1] && (tip[2]&0xFC) == (ipv4[2]&0xFC) && tip[3] != ipv4[3]) - reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), net, *((__be32 *)tip), sha, ec20_mac, sha); - - if (reply) { - skb_reset_mac_header(reply); - __skb_pull(reply, skb_network_offset(reply)); - reply->ip_summed = CHECKSUM_UNNECESSARY; - reply->pkt_type = PACKET_HOST; - - netif_rx_ni(reply); - } - return 1; - } - - return 0; -} - -static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4, unsigned char *bridge_mac) { - struct ethhdr *ehdr; - const struct iphdr *iph; - - skb_reset_mac_header(skb); - ehdr = eth_hdr(skb); - - if (ehdr->h_proto == htons(ETH_P_ARP)) { - if (bridge_ipv4) - bridge_arp_reply(net, skb, bridge_ipv4); - return NULL; - } - - iph = ip_hdr(skb); - //DBG("iphdr: "); - //PrintHex((void *)iph, sizeof(struct iphdr)); - -// 1 0.000000000 0.0.0.0 255.255.255.255 DHCP 362 DHCP Request - Transaction ID 0xe7643ad7 - if (ehdr->h_proto == htons(ETH_P_IP) && iph->protocol == IPPROTO_UDP && iph->saddr == 0x00000000 && iph->daddr == 0xFFFFFFFF) { - //if (udp_hdr(skb)->dest == htons(67)) //DHCP Request - { - memcpy(bridge_mac, ehdr->h_source, ETH_ALEN); - pr_info("%s PC Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net), - bridge_mac[0], bridge_mac[1], bridge_mac[2], bridge_mac[3], bridge_mac[4], bridge_mac[5]); - } - } - - if (memcmp(ehdr->h_source, bridge_mac, ETH_ALEN)) { - return NULL; - } - - return skb; -} - -static void bridge_mode_rx_fixup(sGobiUSBNet *pQmapDev, struct net_device *net, struct sk_buff *skb) { - uint bridge_mode = 0; - unsigned char *bridge_mac; - - if (pQmapDev->qmap_mode > 1) { - struct qmap_priv *priv = netdev_priv(net); - bridge_mode = priv->m_bridge_mode; - bridge_mac = priv->mHostMAC; - } - else { - bridge_mode = pQmapDev->m_bridge_mode; - bridge_mac = pQmapDev->mHostMAC; - } - - if (bridge_mode) - memcpy(eth_hdr(skb)->h_dest, bridge_mac, ETH_ALEN); - else - memcpy(eth_hdr(skb)->h_dest, net->dev_addr, ETH_ALEN); -} - -static ssize_t bridge_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *pNet = to_net_dev(dev); - uint bridge_mode = 0; - - if (is_qmap_netdev(pNet)) { - struct qmap_priv *priv = netdev_priv(pNet); - bridge_mode = priv->m_bridge_mode; - } - else { - struct usbnet * pDev = netdev_priv( pNet ); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - bridge_mode = pGobiDev->m_bridge_mode; - } - - return snprintf(buf, PAGE_SIZE, "%d\n", bridge_mode); -} - -static ssize_t bridge_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *pNet = to_net_dev(dev); - uint old_mode = 0; - uint bridge_mode = simple_strtoul(buf, NULL, 0); - - if (pNet->type != ARPHRD_ETHER) { - return count; - } - - if (is_qmap_netdev(pNet)) { - struct qmap_priv *priv = netdev_priv(pNet); - - old_mode = priv->m_bridge_mode; - priv->m_bridge_mode = bridge_mode; - } - else { - struct usbnet * pDev = netdev_priv( pNet ); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - - old_mode = pGobiDev->m_bridge_mode; - pGobiDev->m_bridge_mode = bridge_mode; - } - - if (old_mode != bridge_mode) - dev_info(dev, "bridge_mode change to 0x%x\n", bridge_mode); - - return count; -} - -static ssize_t bridge_ipv4_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *pNet = to_net_dev(dev); - unsigned int bridge_ipv4 = 0; - unsigned char ipv4[4]; - - if (is_qmap_netdev(pNet)) { - struct qmap_priv *priv = netdev_priv(pNet); - bridge_ipv4 = priv->m_bridge_ipv4; - } - else { - struct usbnet * pDev = netdev_priv( pNet ); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - bridge_ipv4 = pGobiDev->m_bridge_ipv4; - } - - ipv4[0] = (bridge_ipv4 >> 24) & 0xFF; - ipv4[1] = (bridge_ipv4 >> 16) & 0xFF; - ipv4[2] = (bridge_ipv4 >> 8) & 0xFF; - ipv4[3] = (bridge_ipv4 >> 0) & 0xFF; - - return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3]); -} - -static ssize_t bridge_ipv4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *pNet = to_net_dev(dev); - - if (is_qmap_netdev(pNet)) { - struct qmap_priv *priv = netdev_priv(pNet); - priv->m_bridge_ipv4 = simple_strtoul(buf, NULL, 16); - } - else { - struct usbnet * pDev = netdev_priv( pNet ); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - pGobiDev->m_bridge_ipv4 = simple_strtoul(buf, NULL, 16); - } - - return count; -} - -static DEVICE_ATTR(bridge_mode, S_IWUSR | S_IRUGO, bridge_mode_show, bridge_mode_store); -static DEVICE_ATTR(bridge_ipv4, S_IWUSR | S_IRUGO, bridge_ipv4_show, bridge_ipv4_store); - -static struct attribute *qmi_qmap_sysfs_attrs[] = { - &dev_attr_bridge_mode.attr, - &dev_attr_bridge_ipv4.attr, - NULL, -}; - -static struct attribute_group qmi_qmap_sysfs_attr_group = { - .attrs = qmi_qmap_sysfs_attrs, -}; -#endif - -#ifdef QUECTEL_WWAN_QMAP -static sGobiUSBNet * net_to_qmap(struct net_device *dev) { - struct usbnet *usbnet = netdev_priv(dev); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)usbnet->data[0]; - - return pGobiDev; -} - -static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) { - struct qmap_hdr *qhdr; - int pad = 0; - - pad = skb->len%4; - if (pad) { - pad = 4 - pad; - if (skb_tailroom(skb) < pad) { - printk("skb_tailroom small!\n"); - pad = 0; - } - if (pad) - __skb_put(skb, pad); - } - - qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr)); - qhdr->cd_rsvd_pad = pad; - qhdr->mux_id = mux_id; - qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr)); - - return skb; -} - -static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) { - struct rmnet_map_header *map_header; - struct rmnet_map_v5_csum_header *ul_header; - u32 padding, map_datalen; - - map_datalen = skb->len; - padding = map_datalen%4; - if (padding) { - padding = 4 - padding; - if (skb_tailroom(skb) < padding) { - printk("skb_tailroom small!\n"); - padding = 0; - } - if (padding) - __skb_put(skb, padding); - } - - map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); - map_header->cd_bit = 0; - map_header->next_hdr = 1; - map_header->pad_len = padding; - map_header->mux_id = mux_id; - map_header->pkt_len = htons(map_datalen + padding); - - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - memset(ul_header, 0, sizeof(*ul_header)); - ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD; - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if 0 //TODO - skb->ip_summed = CHECKSUM_NONE; - /* Ask for checksum offloading */ - ul_header->csum_valid_required = 1; -#endif - } - - return skb; -} - -static void rmnet_usb_tx_wake_queue(unsigned long data) { - sGobiUSBNet *pQmapDev = (void *)data; - int i; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - if (qmap_net) { - if (netif_queue_stopped(qmap_net) && !netif_queue_stopped(pQmapDev->mpNetDev->net)) { - netif_wake_queue(qmap_net); - } - } - } -} - -static void rmnet_usb_tx_skb_destructor(struct sk_buff *skb) { - sGobiUSBNet *pQmapDev = net_to_qmap(skb->dev); - int i; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - - if (qmap_net) { - if (netif_queue_stopped(qmap_net)) { - tasklet_schedule(&pQmapDev->txq); - break; - } - } - } -} - -static void rmnet_vnd_update_rx_stats(struct net_device *net, - unsigned rx_packets, unsigned rx_bytes) { - net->stats.rx_packets += rx_packets; - net->stats.rx_bytes += rx_bytes; -} - -static void rmnet_vnd_update_tx_stats(struct net_device *net, - unsigned tx_packets, unsigned tx_bytes) { - net->stats.tx_packets += tx_packets; - net->stats.tx_bytes += tx_bytes; -} - -#if defined(QUECTEL_UL_DATA_AGG) -static long agg_time_limit __read_mostly = 1000000L; //reduce this time, can get better TPUT performance, but will increase USB interrupts -module_param(agg_time_limit, long, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(agg_time_limit, "Maximum time packets sit in the agg buf"); - -static long agg_bypass_time __read_mostly = 10000000L; -module_param(agg_bypass_time, long, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this"); - -static int rmnet_usb_tx_agg_skip(struct sk_buff *skb, int offset) -{ - u8 *packet_start = skb->data + offset; - int ready2send = 0; - - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *ip4h = (struct iphdr *)(packet_start); - - if (ip4h->protocol == IPPROTO_TCP) { - const struct tcphdr *th = (const struct tcphdr *)(packet_start + sizeof(struct iphdr)); - if (th->psh) { - ready2send = 1; - } - } - else if (ip4h->protocol == IPPROTO_ICMP) - ready2send = 1; - - } else if (skb->protocol == htons(ETH_P_IPV6)) { - struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start); - - if (ip6h->nexthdr == NEXTHDR_TCP) { - const struct tcphdr *th = (const struct tcphdr *)(packet_start + sizeof(struct ipv6hdr)); - if (th->psh) { - ready2send = 1; - } - } else if (ip6h->nexthdr == NEXTHDR_ICMP) { - ready2send = 1; - } else if (ip6h->nexthdr == NEXTHDR_FRAGMENT) { - struct frag_hdr *frag; - - frag = (struct frag_hdr *)(packet_start - + sizeof(struct ipv6hdr)); - if (frag->nexthdr == IPPROTO_ICMPV6) - ready2send = 1; - } - } - - return ready2send; -} - -static void rmnet_usb_tx_agg_work(struct work_struct *work) -{ - struct qmap_priv *priv = - container_of(work, struct qmap_priv, agg_wq); - struct sk_buff *skb = NULL; - unsigned long flags; - - spin_lock_irqsave(&priv->agg_lock, flags); - if (likely(priv->agg_skb)) { - skb = priv->agg_skb; - priv->agg_skb = NULL; - priv->agg_count = 0; - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - ktime_get_ts64(&priv->agg_time); - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - - if (skb) { - int err = dev_queue_xmit(skb); - if (err != NET_XMIT_SUCCESS) { - priv->self_dev->stats.tx_errors++; - } - } -} - -static enum hrtimer_restart rmnet_usb_tx_agg_timer_cb(struct hrtimer *timer) -{ - struct qmap_priv *priv = - container_of(timer, struct qmap_priv, agg_hrtimer); - - schedule_work(&priv->agg_wq); - return HRTIMER_NORESTART; -} - -static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) { - int ready2send = 0; - int xmit_more = 0; - struct timespec64 diff, now; - struct sk_buff *agg_skb = NULL; - unsigned long flags; - int err; - struct net_device *pNet = priv->self_dev; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0) //6b16f9ee89b8d5709f24bc3ac89ae8b5452c0d7c -#if LINUX_VERSION_CODE > KERNEL_VERSION(3,16,0) - xmit_more = skb->xmit_more; -#endif -#else - xmit_more = netdev_xmit_more(); -#endif - - rmnet_vnd_update_tx_stats(pNet, 1, skb->len); - - if (priv->ul_data_aggregation_max_datagrams == 1) { - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - if (!skb->destructor) - skb->destructor = rmnet_usb_tx_skb_destructor; - err = dev_queue_xmit(skb); - if (err != NET_XMIT_SUCCESS) - pNet->stats.tx_errors++; - return NET_XMIT_SUCCESS; - } - -new_packet: - spin_lock_irqsave(&priv->agg_lock, flags); - agg_skb = NULL; - ready2send = 0; - ktime_get_ts64(&now); - diff = timespec64_sub(now, priv->agg_time); - - if (priv->agg_skb) { - if ((priv->agg_skb->len + skb->len) < priv->ul_data_aggregation_max_size) { - memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len); - priv->agg_count++; - - if (diff.tv_sec > 0 || diff.tv_nsec > agg_time_limit) { - ready2send = 1; - } - else if (priv->agg_count == priv->ul_data_aggregation_max_datagrams) { - ready2send = 1; - } - else if (xmit_more == 0) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data; - size_t offset = sizeof(struct rmnet_map_header); - if (map_header->next_hdr) - offset += sizeof(struct rmnet_map_v5_csum_header); - - ready2send = rmnet_usb_tx_agg_skip(skb, offset); - } - - dev_kfree_skb_any(skb); - skb = NULL; - } - else { - ready2send = 1; - } - - if (ready2send) { - agg_skb = priv->agg_skb; - priv->agg_skb = NULL; - priv->agg_count = 0; - } - } - else if (skb) { - if (diff.tv_sec > 0 || diff.tv_nsec > agg_bypass_time) { - ready2send = 1; - } - else if (xmit_more == 0) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data; - size_t offset = sizeof(struct rmnet_map_header); - if (map_header->next_hdr) - offset += sizeof(struct rmnet_map_v5_csum_header); - - ready2send = rmnet_usb_tx_agg_skip(skb, offset); - } - - if (ready2send == 0) { - priv->agg_skb = alloc_skb(priv->ul_data_aggregation_max_size, GFP_ATOMIC); - if (priv->agg_skb) { - memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len); - priv->agg_count++; - dev_kfree_skb_any(skb); - skb = NULL; - } - else { - ready2send = 1; - } - } - - if (ready2send) { - agg_skb = skb; - skb = NULL; - } - } - - if (ready2send) { - priv->agg_time = now; - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - - if (agg_skb) { - agg_skb->protocol = htons(ETH_P_MAP); - agg_skb->dev = priv->real_dev; - if (!agg_skb->destructor) - agg_skb->destructor = rmnet_usb_tx_skb_destructor; - err = dev_queue_xmit(agg_skb); - if (err != NET_XMIT_SUCCESS) { - pNet->stats.tx_errors++; - } - } - - if (skb) { - goto new_packet; - } - - if (priv->agg_skb) { - if (!hrtimer_is_queued(&priv->agg_hrtimer)) - hrtimer_start(&priv->agg_hrtimer, ns_to_ktime(NSEC_PER_MSEC * 2), HRTIMER_MODE_REL); - } - - return NET_XMIT_SUCCESS; -} -#endif - -static int qmap_open(struct net_device *dev) -{ - struct qmap_priv *priv = netdev_priv(dev); - sGobiUSBNet * pGobiDev = net_to_qmap(priv->real_dev); - - if (!(priv->real_dev->flags & IFF_UP)) - return -ENETDOWN; - - if (!pGobiDev->mbQMIReady) - return -ENETDOWN; - -#if defined(QUECTEL_UL_DATA_AGG) - if (priv->ul_data_aggregation_max_datagrams == 1 && pGobiDev->agg_ctx.ul_data_aggregation_max_datagrams > 1) { - priv->ul_data_aggregation_max_datagrams = pGobiDev->agg_ctx.ul_data_aggregation_max_datagrams; - priv->ul_data_aggregation_max_size = pGobiDev->agg_ctx.ul_data_aggregation_max_size; - priv->dl_minimum_padding = pGobiDev->agg_ctx.dl_minimum_padding; - } -#endif - - if (netif_carrier_ok(priv->real_dev) && priv->link_state) - netif_carrier_on(dev); - - if (netif_carrier_ok(dev)) { - if (netif_queue_stopped(dev) && !netif_queue_stopped(priv->real_dev)) - netif_wake_queue(dev); - } - - return 0; -} - -static int qmap_stop(struct net_device *pNet) -{ - netif_carrier_off(pNet); - return 0; -} - -static int qmap_start_xmit(struct sk_buff *skb, struct net_device *pNet) -{ - int err; - struct qmap_priv *priv = netdev_priv(pNet); - - if (netif_queue_stopped(priv->real_dev)) { - //printk(KERN_DEBUG "s\n"); - netif_stop_queue(pNet); - return NETDEV_TX_BUSY; - } - - if (pNet->type == ARPHRD_ETHER) { -#ifdef QUECTEL_BRIDGE_MODE - if (priv->m_bridge_mode && bridge_mode_tx_fixup(pNet, skb, priv->m_bridge_ipv4, priv->mHostMAC) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } -#endif - - if (ether_to_ip_fixup(pNet, skb) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - - if (priv->qmap_version == 5) { - add_qhdr(skb, priv->mux_id); - } - else if (priv->qmap_version == 9) { - add_qhdr_v5(skb, priv->mux_id); - } - else { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - -#if defined(QUECTEL_UL_DATA_AGG) - err = rmnet_usb_tx_agg(skb, priv); -#else - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - if (!skb->destructor) - skb->destructor = rmnet_usb_tx_skb_destructor; - err = dev_queue_xmit(skb); -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 )) - if (err == NET_XMIT_SUCCESS) { - rmnet_vnd_update_tx_stats(pNet, 1, skb->len); - } else { - pNet->stats.tx_errors++; - } -#endif -#endif - - return err; -} - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) -#else -static const struct net_device_ops qmap_netdev_ops = { - .ndo_open = qmap_open, - .ndo_stop = qmap_stop, - .ndo_start_xmit = qmap_start_xmit, -}; -#endif - -#ifdef QUECTEL_BRIDGE_MODE -static int is_qmap_netdev(const struct net_device *netdev) { -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - return netdev->open == qmap_open; -#else - return netdev->netdev_ops == &qmap_netdev_ops; -#endif -} -#endif - -static int qmap_register_device(sGobiUSBNet * pDev, u8 offset_id) -{ - struct net_device *real_dev = pDev->mpNetDev->net; - struct net_device *qmap_net; - struct qmap_priv *priv; - int err; - - qmap_net = alloc_etherdev(sizeof(*priv)); - if (!qmap_net) - return -ENOBUFS; - - SET_NETDEV_DEV(qmap_net, &real_dev->dev); - priv = netdev_priv(qmap_net); - priv->offset_id = offset_id; - priv->mux_id = QUECTEL_QMAP_MUX_ID + offset_id; - priv->qmap_version = pDev->qmap_version; - priv->real_dev = real_dev; - priv->self_dev = qmap_net; - -#if defined(QUECTEL_UL_DATA_AGG) - priv->ul_data_aggregation_max_datagrams = 1; - priv->ul_data_aggregation_max_size = 2048; - priv->dl_minimum_padding = 0; - priv->agg_skb = NULL; - priv->agg_count = 0; - hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - priv->agg_hrtimer.function = rmnet_usb_tx_agg_timer_cb; - INIT_WORK(&priv->agg_wq, rmnet_usb_tx_agg_work); - ktime_get_ts64(&priv->agg_time); - spin_lock_init(&priv->agg_lock); -#endif - - sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1); -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - qmap_net->open = qmap_open; - qmap_net->stop = qmap_stop; - qmap_net->hard_start_xmit = qmap_start_xmit; -#else - qmap_net->netdev_ops = &qmap_netdev_ops; -#endif - memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); - -#ifdef QUECTEL_BRIDGE_MODE - priv->m_bridge_mode = !!(pDev->m_bridge_mode & BIT(offset_id)); - qmap_net->sysfs_groups[0] = &qmi_qmap_sysfs_attr_group; -#endif - - err = register_netdev(qmap_net); - if (err < 0) { - INFO("register_netdev(%s), err=%d\n", qmap_net->name, err); - goto out_free_newdev; - } - netif_device_attach (qmap_net); - - pDev->mpQmapNetDev[offset_id] = qmap_net; - qmap_net->flags |= IFF_NOARP; - qmap_net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - - INFO("%s\n", qmap_net->name); - - return 0; - -out_free_newdev: - free_netdev(qmap_net); - return err; -} - -static void qmap_unregister_device(sGobiUSBNet * pDev, u8 offset_id) { - struct net_device *qmap_net; -#if defined(QUECTEL_UL_DATA_AGG) - struct qmap_priv *priv; - unsigned long flags; -#endif - - qmap_net = pDev->mpQmapNetDev[offset_id]; - if (qmap_net == NULL) - return; - - netif_carrier_off(qmap_net); - netif_stop_queue(qmap_net); - -#if defined(QUECTEL_UL_DATA_AGG) - priv = netdev_priv(qmap_net); - hrtimer_cancel(&priv->agg_hrtimer); - cancel_work_sync(&priv->agg_wq); - spin_lock_irqsave(&priv->agg_lock, flags); - if (priv->agg_skb) { - kfree_skb(priv->agg_skb); - } - spin_unlock_irqrestore(&priv->agg_lock, flags); -#endif - - unregister_netdev(qmap_net); - free_netdev(qmap_net); -} - -static ssize_t qmap_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *pNet = to_net_dev(dev); - struct usbnet * pDev = netdev_priv( pNet ); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - - return snprintf(buf, PAGE_SIZE, "%d\n", pGobiDev->qmap_mode); -} - -static DEVICE_ATTR(qmap_mode, S_IRUGO, qmap_mode_show, NULL); - -static ssize_t qmap_size_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *pNet = to_net_dev(dev); - struct usbnet * pDev = netdev_priv( pNet ); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - - return snprintf(buf, PAGE_SIZE, "%d\n", pGobiDev->qmap_size); -} - -static DEVICE_ATTR(qmap_size, S_IRUGO, qmap_size_show, NULL); - -static ssize_t link_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - sGobiUSBNet *pQmapDev = net_to_qmap(to_net_dev(dev)); - - return snprintf(buf, PAGE_SIZE, "0x%x\n", pQmapDev->link_state); -} - -static ssize_t link_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *netdev = to_net_dev(dev); - sGobiUSBNet *pQmapDev = net_to_qmap(to_net_dev(dev)); - unsigned qmap_mode = pQmapDev->qmap_mode; - unsigned link_state = 0; - unsigned old_link = pQmapDev->link_state; - uint offset_id = 0; - - link_state = simple_strtoul(buf, NULL, 0); - if (qmap_mode == 1) { - pQmapDev->link_state = !!link_state; - } - else if (qmap_mode > 1) { - offset_id = ((link_state&0x7F) - 1); - - if (offset_id >= qmap_mode) { - dev_info(dev, "%s offset_id is %d. but qmap_mode is %d\n", __func__, offset_id, pQmapDev->qmap_mode); - return count; - } - - if (link_state&0x80) - pQmapDev->link_state &= ~(1 << offset_id); - else - pQmapDev->link_state |= (1 << offset_id); - } - - if (old_link != pQmapDev->link_state) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[offset_id]; - - if (pQmapDev->link_state) { - netif_carrier_on(netdev); - } else { - netif_carrier_off(netdev); - } - - if (qmap_net && qmap_net != netdev) { - struct qmap_priv *priv = netdev_priv(qmap_net); - - priv->link_state = !!(pQmapDev->link_state & (1 << offset_id)); - if (priv->link_state) { - netif_carrier_on(qmap_net); - if (netif_queue_stopped(qmap_net) && !netif_queue_stopped(priv->real_dev)) - netif_wake_queue(qmap_net); - } - else - netif_carrier_off(qmap_net); - } - } - - if (old_link != pQmapDev->link_state) - dev_info(dev, "link_state 0x%x -> 0x%x\n", old_link, pQmapDev->link_state); - - return count; -} - -static DEVICE_ATTR(link_state, S_IWUSR | S_IRUGO, link_state_show, link_state_store); -#endif - -static struct attribute *gobinet_sysfs_attrs[] = { -#ifdef QUECTEL_BRIDGE_MODE - &dev_attr_bridge_mode.attr, - &dev_attr_bridge_ipv4.attr, -#endif -#ifdef QUECTEL_WWAN_QMAP - &dev_attr_qmap_mode.attr, - &dev_attr_qmap_size.attr, - &dev_attr_link_state.attr, -#endif - NULL, -}; - -static struct attribute_group gobinet_sysfs_attr_group = { - .attrs = gobinet_sysfs_attrs, -}; - -#if defined(QUECTEL_WWAN_QMAP) -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int qmap_mode; - unsigned int qmap_version; - unsigned int dl_minimum_padding; - char ifname[8][16]; - unsigned char mux_id[8]; -} RMNET_INFO; - -static void rmnet_info_set(struct sGobiUSBNet *pQmapDev, RMNET_INFO *rmnet_info) -{ - int i; - - memset(rmnet_info, 0, sizeof(*rmnet_info)); - rmnet_info->size = sizeof(RMNET_INFO); - rmnet_info->rx_urb_size = pQmapDev->qmap_size; - rmnet_info->ep_type = 2; //DATA_EP_TYPE_HSUSB - rmnet_info->iface_id = 4; - rmnet_info->qmap_mode = pQmapDev->qmap_mode; - rmnet_info->qmap_version = pQmapDev->qmap_version; - rmnet_info->dl_minimum_padding = 0; - - for (i = 0; i < pQmapDev->qmap_mode; i++) { - struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; - - if (!qmap_net) - break; - - strcpy(rmnet_info->ifname[i], qmap_net->name); - rmnet_info->mux_id[i] = QUECTEL_QMAP_MUX_ID; - if (pQmapDev->qmap_mode > 1) { - struct qmap_priv *priv = netdev_priv(qmap_net); - - rmnet_info->mux_id[i] = priv->mux_id; - } - } -} - -static int qmap_ndo_do_ioctl(struct net_device *dev,struct ifreq *ifr, int cmd) { - int rc = -EOPNOTSUPP; - uint link_state = 0; - sGobiUSBNet *pQmapDev = net_to_qmap(dev); - - atomic_inc(&pQmapDev->refcount); - if (!pQmapDev->mbQMIReady) { - if (wait_for_completion_interruptible_timeout(&pQmapDev->mQMIReadyCompletion, 15*HZ) <= 0) { - if (atomic_dec_and_test(&pQmapDev->refcount)) { - kfree( pQmapDev ); - } - return -ETIMEDOUT; - } - } - atomic_dec(&pQmapDev->refcount); - - switch (cmd) { - case 0x89F1: //SIOCDEVPRIVATE - rc = copy_from_user(&link_state, ifr->ifr_ifru.ifru_data, sizeof(link_state)); - if (!rc) { - char buf[32]; - snprintf(buf, sizeof(buf), "%u", link_state); - link_state_store(&dev->dev, NULL, buf, strlen(buf)); - } - break; - - case 0x89F2: //SIOCDEVPRIVATE - rc = 0; - break; - - case 0x89F3: //SIOCDEVPRIVATE - if (pQmapDev->qmap_mode) { - RMNET_INFO rmnet_info; - - rmnet_info_set(pQmapDev, &rmnet_info); - rc = copy_to_user(ifr->ifr_ifru.ifru_data, &rmnet_info, sizeof(rmnet_info)); - } - break; - - default: - break; - } - - return rc; -} -#endif - -#ifdef CONFIG_PM -/*=========================================================================== -METHOD: - GobiNetSuspend (Public Method) - -DESCRIPTION: - Stops QMI traffic while device is suspended - -PARAMETERS - pIntf [ I ] - Pointer to interface - powerEvent [ I ] - Power management event - -RETURN VALUE: - int - 0 for success - negative errno for failure -===========================================================================*/ -static int GobiNetSuspend( - struct usb_interface * pIntf, - pm_message_t powerEvent ) -{ - struct usbnet * pDev; - sGobiUSBNet * pGobiDev; - - if (pIntf == 0) - { - return -ENOMEM; - } - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) - pDev = usb_get_intfdata( pIntf ); -#else - pDev = (struct usbnet *)pIntf->dev.platform_data; -#endif - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get netdevice\n" ); - return -ENXIO; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return -ENXIO; - } - - if (pGobiDev->mbQMISyncIng) - { - DBG( "QMI sync ing\n" ); - return -EBUSY; - } - - // Is this autosuspend or system suspend? - // do we allow remote wakeup? -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 )) -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) - if (pDev->udev->auto_pm == 0) -#else - if (1) -#endif -#else - if ((powerEvent.event & PM_EVENT_AUTO) == 0) -#endif - { - DBG( "device suspended to power level %d\n", - powerEvent.event ); - GobiSetDownReason( pGobiDev, DRIVER_SUSPENDED ); - } - else - { - DBG( "device autosuspend\n" ); - } - - if (powerEvent.event & PM_EVENT_SUSPEND) - { - // Stop QMI read callbacks - if (pGobiDev->m_qcrmcall_mode) { - } else { - KillRead( pGobiDev ); - } -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,22 )) - pDev->udev->reset_resume = 0; -#endif - - // Store power state to avoid duplicate resumes - pIntf->dev.power.power_state.event = powerEvent.event; - } - else - { - // Other power modes cause QMI connection to be lost -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,22 )) - pDev->udev->reset_resume = 1; -#endif - } - - // Run usbnet's suspend function - return usbnet_suspend( pIntf, powerEvent ); -} -int QuecGobiNetSuspend(struct usb_interface *pIntf, pm_message_t powerEvent ) { - return GobiNetSuspend(pIntf, powerEvent); -} - -/*=========================================================================== -METHOD: - GobiNetResume (Public Method) - -DESCRIPTION: - Resume QMI traffic or recreate QMI device - -PARAMETERS - pIntf [ I ] - Pointer to interface - -RETURN VALUE: - int - 0 for success - negative errno for failure -===========================================================================*/ -static int GobiNetResume( struct usb_interface * pIntf ) -{ - struct usbnet * pDev; - sGobiUSBNet * pGobiDev; - int nRet; - int oldPowerState; - - if (pIntf == 0) - { - return -ENOMEM; - } - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) - pDev = usb_get_intfdata( pIntf ); -#else - pDev = (struct usbnet *)pIntf->dev.platform_data; -#endif - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get netdevice\n" ); - return -ENXIO; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return -ENXIO; - } - - oldPowerState = pIntf->dev.power.power_state.event; - pIntf->dev.power.power_state.event = PM_EVENT_ON; - DBG( "resuming from power mode %d\n", oldPowerState ); - - if (oldPowerState & PM_EVENT_SUSPEND) - { - // It doesn't matter if this is autoresume or system resume - GobiClearDownReason( pGobiDev, DRIVER_SUSPENDED ); - - nRet = usbnet_resume( pIntf ); - if (nRet != 0) - { - DBG( "usbnet_resume error %d\n", nRet ); - return nRet; - } - - // Restart QMI read callbacks - if (pGobiDev->m_qcrmcall_mode) { - nRet = 0; - } else { - nRet = StartRead( pGobiDev ); - } - if (nRet != 0) - { - DBG( "StartRead error %d\n", nRet ); - return nRet; - } - -#ifdef CONFIG_PM - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - // Kick Auto PM thread to process any queued URBs - complete( &pGobiDev->mAutoPM.mThreadDoWork ); - #endif -#endif /* CONFIG_PM */ - -#if defined(QUECTEL_WWAN_QMAP) - if ((!netif_queue_stopped(pDev->net)) && (pGobiDev->qmap_mode > 1)) { - rmnet_usb_tx_wake_queue((unsigned long )pGobiDev); - } -#endif - } - else - { - DBG( "nothing to resume\n" ); - return 0; - } - - return nRet; -} -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,27 )) -static int GobiNetResetResume( struct usb_interface * pIntf ) -{ - INFO( "device do not support reset_resume\n" ); - pIntf->needs_binding = 1; - - return -EOPNOTSUPP; -} -#endif -#endif /* CONFIG_PM */ - -static void ql_net_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) -{ - usbnet_get_drvinfo(net, info); - /* Inherit standard device info */ - strlcpy(info->driver, driver_name, sizeof(info->driver)); - strlcpy(info->version, VERSION_NUMBER, sizeof(info->version)); -} - -static struct ethtool_ops ql_net_ethtool_ops; - -/*=========================================================================== -METHOD: - GobiNetDriverBind (Public Method) - -DESCRIPTION: - Setup in and out pipes - -PARAMETERS - pDev [ I ] - Pointer to usbnet device - pIntf [ I ] - Pointer to interface - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int GobiNetDriverBind( - struct usbnet * pDev, - struct usb_interface * pIntf ) -{ - int numEndpoints; - int endpointIndex; - struct usb_host_endpoint * pEndpoint = NULL; - struct usb_host_endpoint * pIn = NULL; - struct usb_host_endpoint * pOut = NULL; - - // Verify one altsetting - if (pIntf->num_altsetting != 1) - { - DBG( "invalid num_altsetting %u\n", pIntf->num_altsetting ); - return -ENODEV; - } - - // Verify correct interface (4 for UC20) - if ( !test_bit(pIntf->cur_altsetting->desc.bInterfaceNumber, &pDev->driver_info->data)) - { - DBG( "invalid interface %d\n", - pIntf->cur_altsetting->desc.bInterfaceNumber ); - return -ENODEV; - } - - if ( pIntf->cur_altsetting->desc.bInterfaceClass != 0xff) - { - struct usb_interface_descriptor *desc = &pIntf->cur_altsetting->desc; - const char *qcfg_usbnet = "UNKNOW"; - - if (desc->bInterfaceClass == 2 && desc->bInterfaceSubClass == 0x0e) { - qcfg_usbnet = "MBIM"; - } else if (desc->bInterfaceClass == 2 && desc->bInterfaceSubClass == 0x06) { - qcfg_usbnet = "ECM"; - } else if (desc->bInterfaceClass == 0xe0 && desc->bInterfaceSubClass == 1 && desc->bInterfaceProtocol == 3) { - qcfg_usbnet = "RNDIS"; - } - - INFO( "usbnet is %s not NDIS/RMNET!\n", qcfg_usbnet); - - return -ENODEV; - } - - // Collect In and Out endpoints - numEndpoints = pIntf->cur_altsetting->desc.bNumEndpoints; - for (endpointIndex = 0; endpointIndex < numEndpoints; endpointIndex++) - { - pEndpoint = pIntf->cur_altsetting->endpoint + endpointIndex; - if (pEndpoint == NULL) - { - DBG( "invalid endpoint %u\n", endpointIndex ); - return -ENODEV; - } - - if (usb_endpoint_dir_in( &pEndpoint->desc ) == true - && usb_endpoint_xfer_int( &pEndpoint->desc ) == false) - { - pIn = pEndpoint; - } - else if (usb_endpoint_dir_out( &pEndpoint->desc ) == true) - { - pOut = pEndpoint; - } - } - - if (pIn == NULL || pOut == NULL) - { - DBG( "invalid endpoints\n" ); - return -ENODEV; - } - - if (usb_set_interface( pDev->udev, - pIntf->cur_altsetting->desc.bInterfaceNumber, - 0 ) != 0) - { - DBG( "unable to set interface\n" ); - return -ENODEV; - } - - pDev->in = usb_rcvbulkpipe( pDev->udev, - pIn->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK ); - pDev->out = usb_sndbulkpipe( pDev->udev, - pOut->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK ); - -#if defined(QUECTEL_WWAN_MULTI_PACKAGES) - if (rx_packets && pDev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C)) { - struct multi_package_config rx_config = { - .enable = cpu_to_le32(1), - .package_max_len = cpu_to_le32((1500 + sizeof(struct quec_net_package_header)) * rx_packets), - .package_max_count_in_queue = cpu_to_le32(rx_packets), - .timeout = cpu_to_le32(10*1000), //10ms - }; - int ret = 0; - - ret = usb_control_msg( - interface_to_usbdev(pIntf), - usb_sndctrlpipe(interface_to_usbdev(pIntf), 0), - USB_CDC_SET_MULTI_PACKAGE_COMMAND, - 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - 1, - pIntf->cur_altsetting->desc.bInterfaceNumber, - &rx_config, sizeof(rx_config), 100); - - DBG( "Quectel EC21&EC25 rx_packets=%d, ret=%d\n", rx_packets, ret); - if (ret == sizeof(rx_config)) { - pDev->rx_urb_size = le32_to_cpu(rx_config.package_max_len); - } else { - rx_packets = 0; - } - } -#endif - -#if 1 //def DATA_MODE_RP - /* make MAC addr easily distinguishable from an IP header */ - if ((pDev->net->dev_addr[0] & 0xd0) == 0x40) { - /*clear this bit wil make usbnet apdater named as usbX(instead if ethX)*/ - pDev->net->dev_addr[0] |= 0x02; /* set local assignment bit */ - pDev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */ - } - memcpy (pDev->net->dev_addr, node_id, sizeof node_id); - pDev->net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - pDev->net->features |= (NETIF_F_VLAN_CHALLENGED); -#endif - - ql_net_ethtool_ops = *pDev->net->ethtool_ops; - ql_net_ethtool_ops.get_drvinfo = ql_net_get_drvinfo; - pDev->net->ethtool_ops = &ql_net_ethtool_ops; - - DBG( "in %x, out %x\n", - pIn->desc.bEndpointAddress, - pOut->desc.bEndpointAddress ); - - // In later versions of the kernel, usbnet helps with this -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,23 )) - pIntf->dev.platform_data = (void *)pDev; -#endif - - if (qcrmcall_mode == 0 && pDev->net->sysfs_groups[0] == NULL && gobinet_sysfs_attr_group.attrs[0] != NULL) { -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,32)) //see commit 0c509a6c9393b27a8c5a01acd4a72616206cfc24 - pDev->net->sysfs_groups[1] = &gobinet_sysfs_attr_group; //see netdev_register_sysfs() -#else - pDev->net->sysfs_groups[0] = &gobinet_sysfs_attr_group; -#endif - } - - if (!pDev->rx_urb_size) { -//to advoid module report mtu 1460, but rx 1500 bytes IP packets, and cause the customer's system crash -//next setting can make usbnet.c:usbnet_change_mtu() do not modify rx_urb_size according to mtu - pDev->rx_urb_size = ETH_DATA_LEN + ETH_HLEN + 6; - } - - return 0; -} - -/*=========================================================================== -METHOD: - GobiNetDriverUnbind (Public Method) - -DESCRIPTION: - Deregisters QMI device (Registration happened in the probe function) - -PARAMETERS - pDev [ I ] - Pointer to usbnet device - pIntfUnused [ I ] - Pointer to interface - -RETURN VALUE: - None -===========================================================================*/ -static void GobiNetDriverUnbind( - struct usbnet * pDev, - struct usb_interface * pIntf) -{ - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - - // Should already be down, but just in case... - netif_carrier_off( pDev->net ); - - if (pGobiDev->m_qcrmcall_mode) { - } else { - DeregisterQMIDevice( pGobiDev ); - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,29 )) - kfree( pDev->net->netdev_ops ); - pDev->net->netdev_ops = NULL; -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,23 )) - pIntf->dev.platform_data = NULL; -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,19 )) - pIntf->needs_remote_wakeup = 0; -#endif - - if (atomic_dec_and_test(&pGobiDev->refcount)) - kfree( pGobiDev ); - else - INFO("memory leak!\n"); -} - -#if 1 //def DATA_MODE_RP - -#if defined(QUECTEL_WWAN_QMAP) -static void _rmnet_usb_rx_handler(struct usbnet *dev, struct sk_buff *skb_in) -{ - sGobiUSBNet * pQmapDev = (sGobiUSBNet *)dev->data[0]; - struct sk_buff *qmap_skb; - struct sk_buff_head skb_chain; - uint dl_minimum_padding = 0; - -#if defined(QUECTEL_UL_DATA_AGG) - if (pQmapDev->qmap_version == 9) - dl_minimum_padding = pQmapDev->agg_ctx.dl_minimum_padding; -#endif - - __skb_queue_head_init(&skb_chain); - - while (skb_in->len > sizeof(struct qmap_hdr)) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb_in->data; - struct rmnet_map_v5_csum_header *ul_header = NULL; - size_t hdr_size = sizeof(struct rmnet_map_header); - struct net_device *qmap_net; - int pkt_len = ntohs(map_header->pkt_len); - int skb_len; - __be16 protocol; - int mux_id; - - if (map_header->next_hdr) { - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - hdr_size += sizeof(struct rmnet_map_v5_csum_header); - } - - skb_len = pkt_len - (map_header->pad_len&0x3F); - skb_len -= dl_minimum_padding; - if (skb_len > 1500) { - dev_info(&dev->net->dev, "drop skb_len=%x larger than 1500\n", skb_len); - goto error_pkt; - } - - if (skb_in->len < (pkt_len + hdr_size)) { - dev_info(&dev->net->dev, "drop qmap unknow pkt, len=%d, pkt_len=%d\n", skb_in->len, pkt_len); - goto error_pkt; - } - - if (map_header->cd_bit) { - dev_info(&dev->net->dev, "skip qmap command packet\n"); - goto skip_pkt; - } - - switch (skb_in->data[hdr_size] & 0xf0) { - case 0x40: - protocol = htons(ETH_P_IP); - break; - case 0x60: - protocol = htons(ETH_P_IPV6); - break; - default: - dev_info(&dev->net->dev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]); - goto error_pkt; - } - - mux_id = map_header->mux_id - QUECTEL_QMAP_MUX_ID; - if (mux_id >= pQmapDev->qmap_mode) { - dev_info(&dev->net->dev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - goto error_pkt; - } - - qmap_net = pQmapDev->mpQmapNetDev[mux_id]; - - if (qmap_net == NULL) { - dev_info(&dev->net->dev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - goto skip_pkt; - } - - qmap_skb = netdev_alloc_skb(qmap_net, skb_len); - if (qmap_skb) { - skb_put(qmap_skb, skb_len); - memcpy(qmap_skb->data, skb_in->data + hdr_size, skb_len); - } - - if (qmap_skb == NULL) { - dev_info(&dev->net->dev, "fail to alloc skb, pkt_len = %d\n", skb_len); - goto error_pkt; - } - - skb_reset_transport_header(qmap_skb); - skb_reset_network_header(qmap_skb); - qmap_skb->pkt_type = PACKET_HOST; - skb_set_mac_header(qmap_skb, 0); - qmap_skb->protocol = protocol; - - if (ul_header && ul_header->header_type == RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD - && ul_header->csum_valid_required) { -#if 0 //TODO - qmap_skb->ip_summed = CHECKSUM_UNNECESSARY; -#endif - } - - if (qmap_skb->dev->type == ARPHRD_ETHER) { - skb_push(qmap_skb, ETH_HLEN); - skb_reset_mac_header(qmap_skb); - memcpy(eth_hdr(qmap_skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(qmap_skb)->h_dest, qmap_net->dev_addr, ETH_ALEN); - eth_hdr(qmap_skb)->h_proto = protocol; -#ifdef QUECTEL_BRIDGE_MODE - bridge_mode_rx_fixup(pQmapDev, qmap_net, qmap_skb); -#endif - } - - __skb_queue_tail(&skb_chain, qmap_skb); - -skip_pkt: - skb_pull(skb_in, pkt_len + hdr_size); - } - -error_pkt: - while ((qmap_skb = __skb_dequeue (&skb_chain))) { - if (qmap_skb->dev != dev->net) { - if (qmap_skb->dev->type == ARPHRD_ETHER) - __skb_pull(qmap_skb, ETH_HLEN); - rmnet_vnd_update_rx_stats(qmap_skb->dev, 1, qmap_skb->len); - netif_rx(qmap_skb); - } - else { - qmap_skb->protocol = 0; - usbnet_skb_return(dev, qmap_skb); - } - } -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,35 )) //ab95bfe01f9872459c8678572ccadbf646badad0 -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,39 )) //8a4eb5734e8d1dc60a8c28576bbbdfdcc643626d -static struct sk_buff* rmnet_usb_rx_handler(struct sk_buff *skb) -{ - struct usbnet *dev; - - if (!skb) - goto done; - - //printk("%s skb=%p, protocol=%x, len=%d\n", __func__, skb, skb->protocol, skb->len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return skb; - - if (skb->protocol != htons(ETH_P_MAP)) { - WARN_ON(1); - return skb; - } - - dev = netdev_priv(skb->dev); - - if (dev == NULL) { - WARN_ON(1); - return skb; - } - - _rmnet_usb_rx_handler(dev, skb); - consume_skb(skb); - -done: - return NULL; -} -#else -static rx_handler_result_t rmnet_usb_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct usbnet *dev; - - if (!skb) - goto done; - - //printk("%s skb=%p, protocol=%x, len=%d\n", __func__, skb, skb->protocol, skb->len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - if (skb->protocol != htons(ETH_P_MAP)) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - - dev = netdev_priv(skb->dev); - - if (dev == NULL) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - - _rmnet_usb_rx_handler(dev, skb); - consume_skb(skb); - -done: - return RX_HANDLER_CONSUMED; -} -#endif -#endif -#endif -/*=========================================================================== -METHOD: - GobiNetDriverTxFixup (Public Method) - -DESCRIPTION: - Handling data format mode on transmit path - -PARAMETERS - pDev [ I ] - Pointer to usbnet device - pSKB [ I ] - Pointer to transmit packet buffer - flags [ I ] - os flags - -RETURN VALUE: - None -===========================================================================*/ -static struct sk_buff *GobiNetDriverTxFixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)dev->data[0]; - - if (!pGobiDev) { - DBG( "failed to get QMIDevice\n" ); - dev_kfree_skb_any(skb); - return NULL; - } - - if (unlikely(!skb)) { - return NULL; - } - - if (!pGobiDev->mbRawIPMode) - return skb; - -#ifdef QUECTEL_WWAN_QMAP - if (pGobiDev->qmap_mode > 1) { - if (skb->protocol == htons(ETH_P_MAP)) - return skb; - - goto drop_skb; - } - else if (pGobiDev->qmap_mode == 1) { - if (unlikely(!pGobiDev->link_state)) { - dev_info(&dev->net->dev, "link_state 0x%x, drop skb, len = %u\n", pGobiDev->link_state, skb->len); - goto drop_skb; - } - - if (dev->net->type == ARPHRD_ETHER) { -#ifdef QUECTEL_BRIDGE_MODE - if (pGobiDev->m_bridge_mode && bridge_mode_tx_fixup(dev->net, skb, pGobiDev->m_bridge_ipv4, pGobiDev->mHostMAC) == NULL) { - goto drop_skb; - } -#endif - - if (ether_to_ip_fixup(dev->net, skb) == NULL) - goto drop_skb; - } - - if (pGobiDev->qmap_version == 5) { - add_qhdr(skb, QUECTEL_QMAP_MUX_ID); - } - else if (pGobiDev->qmap_version == 9) { - add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID); - } - else { - goto drop_skb; - } - - return skb; - } -#endif - -#ifdef QUECTEL_BRIDGE_MODE - if (pGobiDev->m_bridge_mode && bridge_mode_tx_fixup(dev->net, skb, pGobiDev->m_bridge_ipv4, pGobiDev->mHostMAC) == NULL) { - goto drop_skb; - } -#endif - - // Skip Ethernet header from message - if (likely(ether_to_ip_fixup(dev->net, skb))) { - return skb; - } - else { -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,22 )) - dev_err(&dev->intf->dev, "Packet Dropped "); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) - dev_err(dev->net->dev.parent, "Packet Dropped "); -#else - INFO("Packet Dropped "); -#endif - } - -#if defined(QUECTEL_WWAN_QMAP) -drop_skb: -#endif -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,24 )) && defined(CONFIG_X86_32) - INFO("dev_kfree_skb_any() will make kernel panic on CentOS!\n"); - quec_debug=1;PrintHex(skb->data, 32);quec_debug=0; -#else - // Filter the packet out, release it - dev_kfree_skb_any(skb); -#endif - - return NULL; -} - -#if defined(QUECTEL_WWAN_MULTI_PACKAGES) -static int GobiNetDriverRxPktsFixup(struct usbnet *dev, struct sk_buff *skb) -{ - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)dev->data[0]; - - if (!pGobiDev->mbRawIPMode) - return 1; - - /* This check is no longer done by usbnet */ - if (skb->len < dev->net->hard_header_len) - return 0; - - if (!rx_packets) { - return GobiNetDriverRxFixup(dev, skb); - } - - while (likely(skb->len)) { - struct sk_buff* new_skb; - struct quec_net_package_header package_header; - - if (skb->len < sizeof(package_header)) - return 0; - - memcpy(&package_header, skb->data, sizeof(package_header)); - package_header.payload_len = be16_to_cpu(package_header.payload_len); - - if (package_header.msg_spec != QUEC_NET_MSG_SPEC || package_header.msg_id != QUEC_NET_MSG_ID_IP_DATA) - return 0; - - if (skb->len < (package_header.payload_len + sizeof(package_header))) - return 0; - - skb_pull(skb, sizeof(package_header)); - - if (skb->len == package_header.payload_len) - return GobiNetDriverRxFixup(dev, skb); - - new_skb = skb_clone(skb, GFP_ATOMIC); - if (new_skb) { - skb_trim(new_skb, package_header.payload_len); - if (GobiNetDriverRxFixup(dev, new_skb)) - usbnet_skb_return(dev, new_skb); - else - return 0; - } - - skb_pull(skb, package_header.payload_len); - } - - return 0; -} -#endif - -#ifdef QUECTEL_WWAN_QMAP -static int GobiNetDriverRxQmapFixup(struct usbnet *dev, struct sk_buff *skb) -{ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,35 )) //ab95bfe01f9872459c8678572ccadbf646badad0 - rx_handler_func_t *rx_handler; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,3,1 )) //7bdd402706cf26bfef9050dfee3f229b7f33ee4f - if (skb->dev == NULL) { - skb->dev = dev->net; - } -#endif - rx_handler = rcu_dereference(skb->dev->rx_handler); - - if (rx_handler == rmnet_usb_rx_handler) { -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,3,1 )) //7bdd402706cf26bfef9050dfee3f229b7f33ee4f - unsigned headroom = skb_headroom(skb); - if (headroom < ETH_HLEN) { - unsigned tailroom = skb_tailroom(skb); - if ((tailroom + headroom) >= ETH_HLEN) { - unsigned moveroom = ETH_HLEN - headroom; - memmove(skb->data + moveroom ,skb->data, skb->len); - skb->data += moveroom; - skb->tail += moveroom; - #ifdef WARN_ONCE - WARN_ONCE(1, "It is better reserve headroom in usbnet.c:rx_submit()!\n"); - #endif - } - } -#endif - - if (dev->net->type == ARPHRD_ETHER && skb_headroom(skb) >= ETH_HLEN) { - //usbnet.c rx_process() usbnet_skb_return() eth_type_trans() - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - memcpy(eth_hdr(skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); - eth_hdr(skb)->h_proto = htons(ETH_P_MAP); - - return 1; - } - -#ifdef WARN_ONCE - WARN_ONCE(1, "skb_headroom < ETH_HLEN\n"); -#endif - return 0; - } -#endif - - _rmnet_usb_rx_handler(dev, skb); - return 0; -} -#endif -/*=========================================================================== -METHOD: - GobiNetDriverRxFixup (Public Method) - -DESCRIPTION: - Handling data format mode on receive path - -PARAMETERS - pDev [ I ] - Pointer to usbnet device - pSKB [ I ] - Pointer to received packet buffer - -RETURN VALUE: - None -===========================================================================*/ -static int GobiNetDriverRxFixup(struct usbnet *dev, struct sk_buff *skb) -{ - __be16 proto; - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)dev->data[0]; - - if (!pGobiDev->mbRawIPMode) - return 1; - - /* This check is no longer done by usbnet */ - if (skb->len < dev->net->hard_header_len) - return 0; - -#ifdef QUECTEL_WWAN_QMAP - if (pGobiDev->qmap_mode) { - return GobiNetDriverRxQmapFixup(dev, skb); - } -#endif - - switch (skb->data[0] & 0xf0) { - case 0x40: - proto = htons(ETH_P_IP); - break; - case 0x60: - proto = htons(ETH_P_IPV6); - break; - case 0x00: - if (is_multicast_ether_addr(skb->data)) - return 1; - /* possibly bogus destination - rewrite just in case */ - skb_reset_mac_header(skb); - goto fix_dest; - default: - /* pass along other packets without modifications */ - return 1; - } - if (skb_headroom(skb) < ETH_HLEN && pskb_expand_head(skb, ETH_HLEN, 0, GFP_ATOMIC)) { - DBG("%s: couldn't pskb_expand_head\n", __func__); - return 0; - } - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - eth_hdr(skb)->h_proto = proto; - memcpy(eth_hdr(skb)->h_source, ec20_mac, ETH_ALEN); -fix_dest: -#ifdef QUECTEL_BRIDGE_MODE - bridge_mode_rx_fixup(pGobiDev, dev->net, skb); -#else - memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); -#endif - -#ifdef QUECTEL_BRIDGE_MODE -#if 0 - if (pGobiDev->m_bridge_mode) { - struct ethhdr *ehdr = eth_hdr(skb); -quec_debug = 1; - DBG(": "); - PrintHex(ehdr, sizeof(struct ethhdr)); -quec_debug = 0; - } -#endif -#endif - - return 1; -} -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) -#ifdef CONFIG_PM -/*=========================================================================== -METHOD: - GobiUSBNetURBCallback (Public Method) - -DESCRIPTION: - Write is complete, cleanup and signal that we're ready for next packet - -PARAMETERS - pURB [ I ] - Pointer to sAutoPM struct - -RETURN VALUE: - None -===========================================================================*/ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -void GobiUSBNetURBCallback( struct urb * pURB ) -#else -void GobiUSBNetURBCallback(struct urb *pURB, struct pt_regs *regs) -#endif -{ - unsigned long activeURBflags; - sAutoPM * pAutoPM = (sAutoPM *)pURB->context; - if (pAutoPM == NULL) - { - // Should never happen - DBG( "bad context\n" ); - return; - } - - if (pURB->status != 0) - { - // Note that in case of an error, the behaviour is no different - DBG( "urb finished with error %d\n", pURB->status ); - } - - // Remove activeURB (memory to be freed later) - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - - // EAGAIN used to signify callback is done - pAutoPM->mpActiveURB = ERR_PTR( -EAGAIN ); - - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - - complete( &pAutoPM->mThreadDoWork ); - -#ifdef URB_FREE_BUFFER_BY_SELF - if (pURB->transfer_flags & URB_FREE_BUFFER) - kfree(pURB->transfer_buffer); -#endif - usb_free_urb( pURB ); -} - -/*=========================================================================== -METHOD: - GobiUSBNetTXTimeout (Public Method) - -DESCRIPTION: - Timeout declared by the net driver. Stop all transfers - -PARAMETERS - pNet [ I ] - Pointer to net device - -RETURN VALUE: - None -===========================================================================*/ -void GobiUSBNetTXTimeout( struct net_device * pNet ) -{ - struct sGobiUSBNet * pGobiDev; - sAutoPM * pAutoPM; - sURBList * pURBListEntry; - unsigned long activeURBflags, URBListFlags; - struct usbnet * pDev = netdev_priv( pNet ); - struct urb * pURB; - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get usbnet device\n" ); - return; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return; - } - pAutoPM = &pGobiDev->mAutoPM; - - DBG( "\n" ); - - // Grab a pointer to active URB - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - pURB = pAutoPM->mpActiveURB; - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - // Stop active URB - if (pURB != NULL) - { - usb_kill_urb( pURB ); - } - - // Cleanup URB List - spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); - - pURBListEntry = pAutoPM->mpURBList; - while (pURBListEntry != NULL) - { - pAutoPM->mpURBList = pAutoPM->mpURBList->mpNext; - atomic_dec( &pAutoPM->mURBListLen ); - usb_free_urb( pURBListEntry->mpURB ); - kfree( pURBListEntry ); - pURBListEntry = pAutoPM->mpURBList; - } - - spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); - - complete( &pAutoPM->mThreadDoWork ); - - return; -} - -/*=========================================================================== -METHOD: - GobiUSBNetAutoPMThread (Public Method) - -DESCRIPTION: - Handle device Auto PM state asynchronously - Handle network packet transmission asynchronously - -PARAMETERS - pData [ I ] - Pointer to sAutoPM struct - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int GobiUSBNetAutoPMThread( void * pData ) -{ - unsigned long activeURBflags, URBListFlags; - sURBList * pURBListEntry; - int status; - struct usb_device * pUdev; - sAutoPM * pAutoPM = (sAutoPM *)pData; - struct urb * pURB; - - if (pAutoPM == NULL) - { - DBG( "passed null pointer\n" ); - return -EINVAL; - } - - pUdev = interface_to_usbdev( pAutoPM->mpIntf ); - - DBG( "traffic thread started\n" ); - - while (pAutoPM->mbExit == false) - { - // Wait for someone to poke us - wait_for_completion_interruptible( &pAutoPM->mThreadDoWork ); - - // Time to exit? - if (pAutoPM->mbExit == true) - { - // Stop activeURB - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - pURB = pAutoPM->mpActiveURB; - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - - // EAGAIN used to signify callback is done - if (IS_ERR( pAutoPM->mpActiveURB ) - && PTR_ERR( pAutoPM->mpActiveURB ) == -EAGAIN ) - { - pURB = NULL; - } - - if (pURB != NULL) - { - usb_kill_urb( pURB ); - } - // Will be freed in callback function - - // Cleanup URB List - spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); - - pURBListEntry = pAutoPM->mpURBList; - while (pURBListEntry != NULL) - { - pAutoPM->mpURBList = pAutoPM->mpURBList->mpNext; - atomic_dec( &pAutoPM->mURBListLen ); - usb_free_urb( pURBListEntry->mpURB ); - kfree( pURBListEntry ); - pURBListEntry = pAutoPM->mpURBList; - } - - spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); - - break; - } - - // Is our URB active? - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - - // EAGAIN used to signify callback is done - if (IS_ERR( pAutoPM->mpActiveURB ) - && PTR_ERR( pAutoPM->mpActiveURB ) == -EAGAIN ) - { - pAutoPM->mpActiveURB = NULL; - - // Restore IRQs so task can sleep - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - - // URB is done, decrement the Auto PM usage count - usb_autopm_put_interface( pAutoPM->mpIntf ); - - // Lock ActiveURB again - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - } - - if (pAutoPM->mpActiveURB != NULL) - { - // There is already a URB active, go back to sleep - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - continue; - } - - // Is there a URB waiting to be submitted? - spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); - if (pAutoPM->mpURBList == NULL) - { - // No more URBs to submit, go back to sleep - spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - continue; - } - - // Pop an element - pURBListEntry = pAutoPM->mpURBList; - pAutoPM->mpURBList = pAutoPM->mpURBList->mpNext; - atomic_dec( &pAutoPM->mURBListLen ); - spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); - - // Set ActiveURB - pAutoPM->mpActiveURB = pURBListEntry->mpURB; - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - - // Tell autopm core we need device woken up - status = usb_autopm_get_interface( pAutoPM->mpIntf ); - if (status < 0) - { - DBG( "unable to autoresume interface: %d\n", status ); - - // likely caused by device going from autosuspend -> full suspend - if (status == -EPERM) - { -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 )) -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) - pUdev->auto_pm = 0; -#else - pUdev = pUdev; -#endif -#endif - GobiNetSuspend( pAutoPM->mpIntf, PMSG_SUSPEND ); - } - - // Add pURBListEntry back onto pAutoPM->mpURBList - spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); - pURBListEntry->mpNext = pAutoPM->mpURBList; - pAutoPM->mpURBList = pURBListEntry; - atomic_inc( &pAutoPM->mURBListLen ); - spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); - - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - pAutoPM->mpActiveURB = NULL; - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - - // Go back to sleep - continue; - } - - // Submit URB - status = usb_submit_urb( pAutoPM->mpActiveURB, GFP_KERNEL ); - if (status < 0) - { - // Could happen for a number of reasons - DBG( "Failed to submit URB: %d. Packet dropped\n", status ); - spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); - usb_free_urb( pAutoPM->mpActiveURB ); - pAutoPM->mpActiveURB = NULL; - spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); - usb_autopm_put_interface( pAutoPM->mpIntf ); - - // Loop again - complete( &pAutoPM->mThreadDoWork ); - } - - kfree( pURBListEntry ); - } - - DBG( "traffic thread exiting\n" ); - pAutoPM->mpThread = NULL; - return 0; -} - -/*=========================================================================== -METHOD: - GobiUSBNetStartXmit (Public Method) - -DESCRIPTION: - Convert sk_buff to usb URB and queue for transmit - -PARAMETERS - pNet [ I ] - Pointer to net device - -RETURN VALUE: - NETDEV_TX_OK on success - NETDEV_TX_BUSY on error -===========================================================================*/ -int GobiUSBNetStartXmit( - struct sk_buff * pSKB, - struct net_device * pNet ) -{ - unsigned long URBListFlags; - struct sGobiUSBNet * pGobiDev; - sAutoPM * pAutoPM; - sURBList * pURBListEntry, ** ppURBListEnd; - void * pURBData; - struct usbnet * pDev = netdev_priv( pNet ); - - //DBG( "\n" ); - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get usbnet device\n" ); - return NETDEV_TX_BUSY; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return NETDEV_TX_BUSY; - } - pAutoPM = &pGobiDev->mAutoPM; - - if( NULL == pSKB ) - { - DBG( "Buffer is NULL \n" ); - return NETDEV_TX_BUSY; - } - - if (GobiTestDownReason( pGobiDev, DRIVER_SUSPENDED )) - { - // Should not happen - DBG( "device is suspended\n" ); - dump_stack(); - return NETDEV_TX_BUSY; - } - - if (GobiTestDownReason( pGobiDev, NO_NDIS_CONNECTION )) - { - //netif_carrier_off( pGobiDev->mpNetDev->net ); - //DBG( "device is disconnected\n" ); - //dump_stack(); - return NETDEV_TX_BUSY; - } - - // Convert the sk_buff into a URB - - // Check if buffer is full - if ( atomic_read( &pAutoPM->mURBListLen ) >= txQueueLength) - { - DBG( "not scheduling request, buffer is full\n" ); - return NETDEV_TX_BUSY; - } - - // Allocate URBListEntry - pURBListEntry = kmalloc( sizeof( sURBList ), GFP_ATOMIC ); - if (pURBListEntry == NULL) - { - DBG( "unable to allocate URBList memory\n" ); - return NETDEV_TX_BUSY; - } - pURBListEntry->mpNext = NULL; - - // Allocate URB - pURBListEntry->mpURB = usb_alloc_urb( 0, GFP_ATOMIC ); - if (pURBListEntry->mpURB == NULL) - { - DBG( "unable to allocate URB\n" ); - // release all memory allocated by now - if (pURBListEntry) - kfree( pURBListEntry ); - return NETDEV_TX_BUSY; - } - -#if 1 //def DATA_MODE_RP - GobiNetDriverTxFixup(pDev, pSKB, GFP_ATOMIC); -#endif - - // Allocate URB transfer_buffer - pURBData = kmalloc( pSKB->len, GFP_ATOMIC ); - if (pURBData == NULL) - { - DBG( "unable to allocate URB data\n" ); - // release all memory allocated by now - if (pURBListEntry) - { - usb_free_urb( pURBListEntry->mpURB ); - kfree( pURBListEntry ); - } - return NETDEV_TX_BUSY; - } - // Fill with SKB's data - memcpy( pURBData, pSKB->data, pSKB->len ); - - usb_fill_bulk_urb( pURBListEntry->mpURB, - pGobiDev->mpNetDev->udev, - pGobiDev->mpNetDev->out, - pURBData, - pSKB->len, - GobiUSBNetURBCallback, - pAutoPM ); - - /* Handle the need to send a zero length packet and release the - * transfer buffer - */ - pURBListEntry->mpURB->transfer_flags |= (URB_ZERO_PACKET | URB_FREE_BUFFER); - - // Aquire lock on URBList - spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); - - // Add URB to end of list - ppURBListEnd = &pAutoPM->mpURBList; - while ((*ppURBListEnd) != NULL) - { - ppURBListEnd = &(*ppURBListEnd)->mpNext; - } - *ppURBListEnd = pURBListEntry; - atomic_inc( &pAutoPM->mURBListLen ); - - spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); - - complete( &pAutoPM->mThreadDoWork ); - - // Start transfer timer - pNet->trans_start = jiffies; - // Free SKB - if (pSKB) - dev_kfree_skb_any( pSKB ); - - return NETDEV_TX_OK; -} -#endif -static int (*local_usbnet_start_xmit) (struct sk_buff *skb, struct net_device *net); -#endif - -static int GobiUSBNetStartXmit2( struct sk_buff *pSKB, struct net_device *pNet ){ - struct sGobiUSBNet * pGobiDev; - struct usbnet * pDev = netdev_priv( pNet ); - - //DBG( "\n" ); - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get usbnet device\n" ); - return NETDEV_TX_BUSY; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return NETDEV_TX_BUSY; - } - - if( NULL == pSKB ) - { - DBG( "Buffer is NULL \n" ); - return NETDEV_TX_BUSY; - } - - if (GobiTestDownReason( pGobiDev, DRIVER_SUSPENDED )) - { - // Should not happen - DBG( "device is suspended\n" ); - dump_stack(); - return NETDEV_TX_BUSY; - } - - if (GobiTestDownReason( pGobiDev, NO_NDIS_CONNECTION )) - { - //netif_carrier_off( pGobiDev->mpNetDev->net ); - //DBG( "device is disconnected\n" ); - //dump_stack(); - return NETDEV_TX_BUSY; - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - return local_usbnet_start_xmit(pSKB, pNet); -#else - return usbnet_start_xmit(pSKB, pNet); -#endif -} - -/*=========================================================================== -METHOD: - GobiUSBNetOpen (Public Method) - -DESCRIPTION: - Wrapper to usbnet_open, correctly handling autosuspend - Start AutoPM thread (if CONFIG_PM is defined) - -PARAMETERS - pNet [ I ] - Pointer to net device - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int GobiUSBNetOpen( struct net_device * pNet ) -{ - int status = 0; - struct sGobiUSBNet * pGobiDev; - struct usbnet * pDev = netdev_priv( pNet ); - - if (pDev == NULL) - { - DBG( "failed to get usbnet device\n" ); - return -ENXIO; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return -ENXIO; - } - - DBG( "\n" ); - -#ifdef CONFIG_PM - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - // Start the AutoPM thread - pGobiDev->mAutoPM.mpIntf = pGobiDev->mpIntf; - pGobiDev->mAutoPM.mbExit = false; - pGobiDev->mAutoPM.mpURBList = NULL; - pGobiDev->mAutoPM.mpActiveURB = NULL; - spin_lock_init( &pGobiDev->mAutoPM.mURBListLock ); - spin_lock_init( &pGobiDev->mAutoPM.mActiveURBLock ); - atomic_set( &pGobiDev->mAutoPM.mURBListLen, 0 ); - init_completion( &pGobiDev->mAutoPM.mThreadDoWork ); - - pGobiDev->mAutoPM.mpThread = kthread_run( GobiUSBNetAutoPMThread, - &pGobiDev->mAutoPM, - "GobiUSBNetAutoPMThread" ); - if (IS_ERR( pGobiDev->mAutoPM.mpThread )) - { - DBG( "AutoPM thread creation error\n" ); - return PTR_ERR( pGobiDev->mAutoPM.mpThread ); - } - #endif -#endif /* CONFIG_PM */ - - // Allow traffic - GobiClearDownReason( pGobiDev, NET_IFACE_STOPPED ); - - // Pass to usbnet_open if defined - if (pGobiDev->mpUSBNetOpen != NULL) - { - status = pGobiDev->mpUSBNetOpen( pNet ); -#ifdef CONFIG_PM - // If usbnet_open was successful enable Auto PM - if (status == 0) - { -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 )) - usb_autopm_enable( pGobiDev->mpIntf ); -#else - usb_autopm_put_interface( pGobiDev->mpIntf ); -#endif - } -#endif /* CONFIG_PM */ - } - else - { - DBG( "no USBNetOpen defined\n" ); - } - - return status; -} - -/*=========================================================================== -METHOD: - GobiUSBNetStop (Public Method) - -DESCRIPTION: - Wrapper to usbnet_stop, correctly handling autosuspend - Stop AutoPM thread (if CONFIG_PM is defined) - -PARAMETERS - pNet [ I ] - Pointer to net device - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int GobiUSBNetStop( struct net_device * pNet ) -{ - struct sGobiUSBNet * pGobiDev; - struct usbnet * pDev = netdev_priv( pNet ); - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get netdevice\n" ); - return -ENXIO; - } - - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev == NULL) - { - DBG( "failed to get QMIDevice\n" ); - return -ENXIO; - } - - // Stop traffic - GobiSetDownReason( pGobiDev, NET_IFACE_STOPPED ); - -#ifdef CONFIG_PM - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - // Tell traffic thread to exit - pGobiDev->mAutoPM.mbExit = true; - complete( &pGobiDev->mAutoPM.mThreadDoWork ); - - // Wait for it to exit - while( pGobiDev->mAutoPM.mpThread != NULL ) - { - msleep( 100 ); - } - DBG( "thread stopped\n" ); - #endif -#endif /* CONFIG_PM */ - - // Pass to usbnet_stop, if defined - if (pGobiDev->mpUSBNetStop != NULL) - { - return pGobiDev->mpUSBNetStop( pNet ); - } - else - { - return 0; - } -} - -static int GobiNetDriver_check_connect(struct usbnet *pDev) { - int status = 0; - struct sGobiUSBNet * pGobiDev = NULL; - - while (status++ < 10) { - pGobiDev = (sGobiUSBNet *)pDev->data[0]; - if (pGobiDev && pGobiDev->mbProbeDone) - break; - msleep(1); - } - - return 0; -} - -/*=========================================================================*/ -// Struct driver_info -/*=========================================================================*/ -static struct driver_info GobiNetInfo = -{ - .description = "GobiNet Ethernet Device", -#if 1//def CONFIG_ANDROID -#if defined(QUECTEL_WWAN_QMAP) && defined(FLAG_RX_ASSEMBLE) - .flags = FLAG_RX_ASSEMBLE, //usb0 -#endif -#else -#if defined(QUECTEL_WWAN_QMAP) && defined(FLAG_RX_ASSEMBLE) - .flags = FLAG_ETHER | FLAG_RX_ASSEMBLE, -#else - .flags = FLAG_ETHER, -#endif -#endif - .bind = GobiNetDriverBind, - .unbind = GobiNetDriverUnbind, -#if 1 //def DATA_MODE_RP -#if defined(QUECTEL_WWAN_MULTI_PACKAGES) - .rx_fixup = GobiNetDriverRxPktsFixup, -#else - .rx_fixup = GobiNetDriverRxFixup, -#endif - .tx_fixup = GobiNetDriverTxFixup, -#endif - .check_connect = GobiNetDriver_check_connect, - .data = (1 << 4), -}; - -/*=========================================================================*/ -// Qualcomm Gobi 3000 VID/PIDs -/*=========================================================================*/ -#define GOBI_FIXED_INTF(vend, prod) \ - { \ - USB_DEVICE( vend, prod ), \ - .driver_info = (unsigned long)&GobiNetInfo, \ - } -static const struct usb_device_id QuecGobiVIDPIDTable [] = -{ - GOBI_FIXED_INTF( 0x05c6, 0x9003 ), // Quectel UC20 - GOBI_FIXED_INTF( 0x05c6, 0x9215 ), // Quectel EC20 (MDM9215) - GOBI_FIXED_INTF( 0x2c7c, 0x0125 ), // Quectel EC20 (MDM9X07)/EC25/EG25 - GOBI_FIXED_INTF( 0x2c7c, 0x0121 ), // Quectel EC21 - GOBI_FIXED_INTF( 0x2c7c, 0x0306 ), // Quectel EP06 - GOBI_FIXED_INTF( 0x2c7c, 0x030B ), // Quectel EG065K,SDX12 - GOBI_FIXED_INTF( 0x2c7c, 0x0435 ), // Quectel AG35 - GOBI_FIXED_INTF( 0x2c7c, 0x0296 ), // Quectel BG96 - GOBI_FIXED_INTF( 0x2c7c, 0x0191 ), // Quectel EG91 - GOBI_FIXED_INTF( 0x2c7c, 0x0195 ), // Quectel EG95 - GOBI_FIXED_INTF( 0x2c7c, 0x0512 ), // Quectel EG12/EP12/EM12/EG16/EG18,SDx20 - GOBI_FIXED_INTF( 0x2c7c, 0x0620 ), // Quectel EG20,SDx24 - GOBI_FIXED_INTF( 0x2c7c, 0x0800 ), // Quectel RG500Q,RM500Q,RM510Q,SDX55 - GOBI_FIXED_INTF( 0x2c7c, 0x0801 ), // Quectel RG520Q,RM520Q,SG520Q,SDX6X - //Terminating entry - { } -}; - -MODULE_DEVICE_TABLE( usb, QuecGobiVIDPIDTable ); - -/*=========================================================================== -METHOD: - GobiUSBNetProbe (Public Method) - -DESCRIPTION: - Run usbnet_probe - Setup QMI device - -PARAMETERS - pIntf [ I ] - Pointer to interface - pVIDPIDs [ I ] - Pointer to VID/PID table - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int GobiUSBNetProbe( - struct usb_interface * pIntf, - const struct usb_device_id * pVIDPIDs ) -{ - int status; - struct usbnet * pDev; - sGobiUSBNet * pGobiDev; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,29 )) - struct net_device_ops * pNetDevOps; -#endif - - status = usbnet_probe( pIntf, pVIDPIDs ); - if (status < 0) - { - DBG( "usbnet_probe failed %d\n", status ); - return status; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,19 )) - pIntf->needs_remote_wakeup = 1; -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) - pDev = usb_get_intfdata( pIntf ); -#else - pDev = (struct usbnet *)pIntf->dev.platform_data; -#endif - - if (pDev == NULL || pDev->net == NULL) - { - DBG( "failed to get netdevice\n" ); - usbnet_disconnect( pIntf ); - return -ENXIO; - } - - pGobiDev = kzalloc( sizeof( sGobiUSBNet ), GFP_KERNEL ); - if (pGobiDev == NULL) - { - DBG( "fail to allocate device buffers" ); - usbnet_disconnect( pIntf ); - return -ENOMEM; - } - - atomic_set(&pGobiDev->refcount, 1); - - pDev->data[0] = (unsigned long)pGobiDev; - - pGobiDev->mpNetDev = pDev; - - // Clearing endpoint halt is a magic handshake that brings - // the device out of low power (airplane) mode - usb_clear_halt( pGobiDev->mpNetDev->udev, pDev->out ); - - // Overload PM related network functions -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - pGobiDev->mpUSBNetOpen = pDev->net->open; - pDev->net->open = GobiUSBNetOpen; - pGobiDev->mpUSBNetStop = pDev->net->stop; - pDev->net->stop = GobiUSBNetStop; -#if defined(CONFIG_PM) && (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 )) - pDev->net->hard_start_xmit = GobiUSBNetStartXmit; - pDev->net->tx_timeout = GobiUSBNetTXTimeout; -#else //quectel donot send dhcp request before ndis connect for uc20 - local_usbnet_start_xmit = pDev->net->hard_start_xmit; - pDev->net->hard_start_xmit = GobiUSBNetStartXmit2; -#endif -#else - pNetDevOps = kmalloc( sizeof( struct net_device_ops ), GFP_KERNEL ); - if (pNetDevOps == NULL) - { - DBG( "falied to allocate net device ops" ); - usbnet_disconnect( pIntf ); - return -ENOMEM; - } - memcpy( pNetDevOps, pDev->net->netdev_ops, sizeof( struct net_device_ops ) ); - - pGobiDev->mpUSBNetOpen = pNetDevOps->ndo_open; - pNetDevOps->ndo_open = GobiUSBNetOpen; - pGobiDev->mpUSBNetStop = pNetDevOps->ndo_stop; - pNetDevOps->ndo_stop = GobiUSBNetStop; -#if 1 //quectel donot send dhcp request before ndis connect for uc20 - pNetDevOps->ndo_start_xmit = GobiUSBNetStartXmit2; -#else - pNetDevOps->ndo_start_xmit = usbnet_start_xmit; -#endif - pNetDevOps->ndo_tx_timeout = usbnet_tx_timeout; - -#if defined(QUECTEL_WWAN_QMAP) - pNetDevOps->ndo_do_ioctl = qmap_ndo_do_ioctl; -#endif - - pDev->net->netdev_ops = pNetDevOps; -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 )) - memset( &(pGobiDev->mpNetDev->stats), 0, sizeof( struct net_device_stats ) ); -#else - memset( &(pGobiDev->mpNetDev->net->stats), 0, sizeof( struct net_device_stats ) ); -#endif - - pGobiDev->mpIntf = pIntf; - memset( &(pGobiDev->mMEID), '0', 14 ); - - DBG( "Mac Address:\n" ); - PrintHex( &pGobiDev->mpNetDev->net->dev_addr[0], 6 ); - - pGobiDev->mbQMIValid = false; - memset( &pGobiDev->mQMIDev, 0, sizeof( sQMIDev ) ); - pGobiDev->mQMIDev.mbCdevIsInitialized = false; - - pGobiDev->mQMIDev.mpDevClass = gpClass; - -#ifdef CONFIG_PM - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - init_completion( &pGobiDev->mAutoPM.mThreadDoWork ); - #endif -#endif /* CONFIG_PM */ - spin_lock_init( &pGobiDev->mQMIDev.mClientMemLock ); - - // Default to device down - pGobiDev->mDownReason = 0; - -//#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,11,0 )) - GobiSetDownReason( pGobiDev, NO_NDIS_CONNECTION ); - GobiSetDownReason( pGobiDev, NET_IFACE_STOPPED ); -//#endif - - // Register QMI - pGobiDev->mbMdm9x07 |= (pDev->udev->descriptor.idVendor == cpu_to_le16(0x2c7c)); - pGobiDev->mbMdm9x06 |= (pDev->udev->descriptor.idVendor == cpu_to_le16(0x2c7c) && pDev->udev->descriptor.idProduct == cpu_to_le16(0x0296)); - pGobiDev->mbRawIPMode = pGobiDev->mbMdm9x07; - if ( pGobiDev->mbRawIPMode) - pGobiDev->mpNetDev->net->flags |= IFF_NOARP; -#ifdef QUECTEL_BRIDGE_MODE - memcpy(pGobiDev->mHostMAC, pDev->net->dev_addr, 6); - pGobiDev->m_bridge_mode = bridge_mode; -#endif - -#ifdef QUECTEL_REMOVE_TX_ZLP - { - struct remove_tx_zlp_config { - __le32 enable; - } __packed; - - struct remove_tx_zlp_config cfg; - cfg.enable = cpu_to_le32(1); //1-enable 0-disable - - usb_control_msg( - interface_to_usbdev(pIntf), - usb_sndctrlpipe(interface_to_usbdev(pIntf), 0), - USB_CDC_SET_REMOVE_TX_ZLP_COMMAND, - 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - 0, - pIntf->cur_altsetting->desc.bInterfaceNumber, - &cfg, sizeof(cfg), 100); - } -#endif - - pGobiDev->m_qcrmcall_mode = qcrmcall_mode; - - if (pGobiDev->m_qcrmcall_mode) { - INFO("AT$QCRMCALL MODE!"); - - GobiClearDownReason( pGobiDev, NO_NDIS_CONNECTION ); - usb_control_msg( - interface_to_usbdev(pIntf), - usb_sndctrlpipe(interface_to_usbdev(pIntf), 0), - 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE - 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - 1, //active CDC DTR - pIntf->cur_altsetting->desc.bInterfaceNumber, - NULL, 0, 100); - status = 0; - } - else { -#if defined(QUECTEL_WWAN_QMAP) - if (pGobiDev->mbRawIPMode) { - unsigned idProduct = le16_to_cpu(pDev->udev->descriptor.idProduct); - - pGobiDev->qmap_mode = qmap_mode; - if (pGobiDev->qmap_mode == 0) { - if (idProduct == 0x0800 || idProduct == 0x0801) { - pGobiDev->qmap_mode = 1; - } - } - - pGobiDev->qmap_version = 5; - if (idProduct == 0x0800 || idProduct == 0x0801) { - pGobiDev->qmap_version = 9; - } - } - - if (pGobiDev->qmap_mode) { - netif_carrier_off(pDev->net); - } - - if (pGobiDev->qmap_mode > 1) { -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,35 )) //ab95bfe01f9872459c8678572ccadbf646badad0 - rtnl_lock(); - netdev_rx_handler_register(pDev->net, rmnet_usb_rx_handler, NULL); - rtnl_unlock(); -#endif - } - -#if defined(QUECTEL_UL_DATA_AGG) - if (pGobiDev->qmap_mode) { - struct ul_agg_ctx *agg_ctx = &pGobiDev->agg_ctx; - - agg_ctx->ul_data_aggregation_max_datagrams = 1; - agg_ctx->ul_data_aggregation_max_size = 2048; - agg_ctx->dl_minimum_padding = 0; - } -#endif -#endif - status = RegisterQMIDevice( pGobiDev ); - } - - if (status != 0) - { - // usbnet_disconnect() will call GobiNetDriverUnbind() which will call - // DeregisterQMIDevice() to clean up any partially created QMI device - usbnet_disconnect( pIntf ); - return status; - } - -#if defined(QUECTEL_WWAN_QMAP) - tasklet_init(&pGobiDev->txq, rmnet_usb_tx_wake_queue, (unsigned long)pGobiDev); - - if (pGobiDev->qmap_mode > 1) { - unsigned i; - - for (i = 0; i < pGobiDev->qmap_mode; i++) { - qmap_register_device(pGobiDev, i); - } - } else { - pGobiDev->mpQmapNetDev[0] = pDev->net; - } -#endif - - pGobiDev->mbProbeDone = 1; - // Success - return 0; -} - -static void GobiUSBNetDisconnect (struct usb_interface *intf) { -#if defined(QUECTEL_WWAN_QMAP) - struct usbnet *pDev = usb_get_intfdata(intf); - sGobiUSBNet * pGobiDev = (sGobiUSBNet *)pDev->data[0]; - unsigned i; - - if (pGobiDev->qmap_mode > 1) { - for (i = 0; i < pGobiDev->qmap_mode; i++) { - qmap_unregister_device(pGobiDev, i); - } - - } - - tasklet_kill(&pGobiDev->txq); -#endif - - usbnet_disconnect(intf); -} - -static struct usb_driver GobiNet = -{ - .name = "GobiNet", - .id_table = QuecGobiVIDPIDTable, - .probe = GobiUSBNetProbe, - .disconnect = GobiUSBNetDisconnect, -#ifdef CONFIG_PM - .suspend = GobiNetSuspend, - .resume = GobiNetResume, -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,27 )) - .reset_resume = GobiNetResetResume, -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) - .supports_autosuspend = true, -#endif -#endif /* CONFIG_PM */ -}; - -/*=========================================================================== -METHOD: - GobiUSBNetModInit (Public Method) - -DESCRIPTION: - Initialize module - Create device class - Register out usb_driver struct - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int __init GobiUSBNetModInit( void ) -{ - gpClass = class_create( THIS_MODULE, "GobiQMI" ); - if (IS_ERR( gpClass ) == true) - { - DBG( "error at class_create %ld\n", PTR_ERR( gpClass ) ); - return -ENOMEM; - } - - // This will be shown whenever driver is loaded - printk( KERN_INFO "%s: %s\n", DRIVER_DESC, DRIVER_VERSION ); - - return usb_register( &GobiNet ); -} -module_init( GobiUSBNetModInit ); - -/*=========================================================================== -METHOD: - GobiUSBNetModExit (Public Method) - -DESCRIPTION: - Deregister module - Destroy device class - -RETURN VALUE: - void -===========================================================================*/ -static void __exit GobiUSBNetModExit( void ) -{ - usb_deregister( &GobiNet ); - - class_destroy( gpClass ); -} -module_exit( GobiUSBNetModExit ); - -MODULE_VERSION( DRIVER_VERSION ); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("Dual BSD/GPL"); - -#ifdef bool -#undef bool -#endif - -module_param_named( debug, quec_debug, int, S_IRUGO | S_IWUSR ); -MODULE_PARM_DESC( debug, "Debuging enabled or not" ); - -//module_param_named( interruptible, Quecinterruptible, int, S_IRUGO | S_IWUSR ); -//MODULE_PARM_DESC( interruptible, "Listen for and return on user interrupt" ); -module_param( txQueueLength, int, S_IRUGO | S_IWUSR ); -MODULE_PARM_DESC( txQueueLength, - "Number of IP packets which may be queued up for transmit" ); - diff --git a/quectel_Gobinet/src/Makefile b/quectel_Gobinet/src/Makefile deleted file mode 100644 index fe4ccf1..0000000 --- a/quectel_Gobinet/src/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -obj-m := GobiNet.o -GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o - -PWD := $(shell pwd) -OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/ - -ifeq ($(ARCH),) -ARCH := $(shell uname -m) -endif -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := -endif -ifeq ($(KDIR),) -KDIR := /lib/modules/$(shell uname -r)/build -ifeq ($(ARCH),i686) -ifeq ($(wildcard $KDIR/arch/$ARCH),) -ARCH=i386 -endif -endif -endif - -$(shell rm -rf usbnet.h) -ifneq ($(wildcard $(KDIR)/drivers/usb/net/usbnet.h),) -$(shell ln -s $(KDIR)/drivers/usb/net/usbnet.h usbnet.h) -endif -ifneq ($(wildcard $(KDIR)/drivers/net/usb/usbnet.h),) -$(shell ln -s $(KDIR)/drivers/net/usb/usbnet.h usbnet.h) -endif - -default: - ln -sf makefile Makefile - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules - -install: default - mkdir -p $(OUTPUTDIR) - cp -f GobiNet.ko $(OUTPUTDIR) - depmod - modprobe -r GobiNet - modprobe GobiNet - -clean: - rm -rf Makefile usbnet.h - rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.* modules.order diff --git a/quectel_Gobinet/src/QMI.c b/quectel_Gobinet/src/QMI.c deleted file mode 100644 index eaf1cac..0000000 --- a/quectel_Gobinet/src/QMI.c +++ /dev/null @@ -1,1521 +0,0 @@ -#ifdef __QUEC_INCLUDE_QMI_C__ -/*=========================================================================== -FILE: - QMI.c - -DESCRIPTION: - Qualcomm QMI driver code - -FUNCTIONS: - Generic QMUX functions - ParseQMUX - FillQMUX - - Generic QMI functions - GetTLV - ValidQMIMessage - GetQMIMessageID - - Fill Buffers with QMI requests - QMICTLGetClientIDReq - QMICTLReleaseClientIDReq - QMICTLReadyReq - QMIWDSSetEventReportReq - QMIWDSGetPKGSRVCStatusReq - QMIDMSGetMEIDReq - QMIWDASetDataFormatReq - QMICTLSetDataFormatReq - QMICTLSyncReq - - Parse data from QMI responses - QMICTLGetClientIDResp - QMICTLReleaseClientIDResp - QMIWDSEventResp - QMIDMSGetMEIDResp - QMIWDASetDataFormatResp - QMICTLSyncResp - -Copyright (c) 2011, Code Aurora Forum. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Code Aurora Forum 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 OWNER 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 Files -//--------------------------------------------------------------------------- -#include -#include -#include "Structs.h" -#include "QMI.h" - -/*=========================================================================*/ -// Get sizes of buffers needed by QMI requests -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - QMUXHeaderSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMUXHeaderSize( void ) -{ - return sizeof( sQMUX ); -} - -/*=========================================================================== -METHOD: - QMICTLGetClientIDReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMICTLGetClientIDReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMICTLGetClientIDReqSize( void ) -{ - return sizeof( sQMUX ) + 10; -} - -/*=========================================================================== -METHOD: - QMICTLReleaseClientIDReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMICTLReleaseClientIDReq - -RETURN VALUE: - u16 - size of header -===========================================================================*/ -static u16 QMICTLReleaseClientIDReqSize( void ) -{ - return sizeof( sQMUX ) + 11; -} - -/*=========================================================================== -METHOD: - QMICTLReadyReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMICTLReadyReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMICTLReadyReqSize( void ) -{ - return sizeof( sQMUX ) + 6; -} - -/*=========================================================================== -METHOD: - QMIWDSSetEventReportReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMIWDSSetEventReportReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMIWDSSetEventReportReqSize( void ) -{ - return sizeof( sQMUX ) + 15; -} - -/*=========================================================================== -METHOD: - QMIWDSGetPKGSRVCStatusReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMIWDSGetPKGSRVCStatusReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMIWDSGetPKGSRVCStatusReqSize( void ) -{ - return sizeof( sQMUX ) + 7; -} - -/*=========================================================================== -METHOD: - QMIDMSGetMEIDReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMIDMSGetMEIDReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMIDMSGetMEIDReqSize( void ) -{ - return sizeof( sQMUX ) + 7; -} - -struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS -{ - u8 TLVType; - u16 TLVLength; - u8 QOSSetting; -} __packed; - -struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV -{ - u8 TLVType; - u16 TLVLength; - u32 Value; -} __packed; - -struct QMIWDS_ENDPOINT_TLV -{ - u8 TLVType; - u16 TLVLength; - u32 ep_type; - u32 iface_id; -} __packed; - -struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG -{ - u8 CtlFlags; // 0: single QMUX Msg; 1: - u16 TransactionId; - u16 Type; - u16 Length; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv; - struct QMIWDS_ENDPOINT_TLV epTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV dl_minimum_padding; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxDatagramsTlv; - struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxSizeTlv; -} __packed; - -/*=========================================================================== -METHOD: - QMIWDASetDataFormatReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMIWDASetDataFormatReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMIWDASetDataFormatReqSize( int qmap_version ) -{ -if (qmap_version) - return sizeof( sQMUX ) + sizeof(struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG); -else - return sizeof( sQMUX ) + 18; -} - -/*=========================================================================== -METHOD: - QMICTLSyncReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMICTLSyncReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMICTLSyncReqSize( void ) -{ - return sizeof( sQMUX ) + 6; -} - -/*=========================================================================*/ -// Generic QMUX functions -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - ParseQMUX (Public Method) - -DESCRIPTION: - Remove QMUX headers from a buffer - -PARAMETERS - pClientID [ O ] - On success, will point to Client ID - pBuffer [ I ] - Full Message passed in - buffSize [ I ] - Size of pBuffer - -RETURN VALUE: - int - Positive for size of QMUX header - Negative errno for error -===========================================================================*/ -static int ParseQMUX( - u16 * pClientID, - void * pBuffer, - u16 buffSize ) -{ - sQMUX * pQMUXHeader; - - if (pBuffer == 0 || buffSize < 12) - { - return -ENOMEM; - } - - // QMUX Header - pQMUXHeader = (sQMUX *)pBuffer; - - if (pQMUXHeader->mTF != 1 - || le16_to_cpu(get_unaligned(&pQMUXHeader->mLength)) != buffSize - 1 - || pQMUXHeader->mCtrlFlag != 0x80 ) - { - return -EINVAL; - } - - // Client ID - *pClientID = (pQMUXHeader->mQMIClientID << 8) + pQMUXHeader->mQMIService; - - return sizeof( sQMUX ); -} - -/*=========================================================================== -METHOD: - FillQMUX (Public Method) - -DESCRIPTION: - Fill buffer with QMUX headers - -PARAMETERS - clientID [ I ] - Client ID - pBuffer [ O ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer (must be at least 6) - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int FillQMUX( - u16 clientID, - void * pBuffer, - u16 buffSize ) -{ - sQMUX * pQMUXHeader; - - if (pBuffer == 0 || buffSize < sizeof( sQMUX )) - { - return -ENOMEM; - } - - // QMUX Header - pQMUXHeader = (sQMUX *)pBuffer; - - pQMUXHeader->mTF = 1; - put_unaligned(cpu_to_le16(buffSize - 1), &pQMUXHeader->mLength); - //DBG("pQMUXHeader->mLength = 0x%x, buffSize - 1 = 0x%x\n",pQMUXHeader->mLength, buffSize - 1); - pQMUXHeader->mCtrlFlag = 0; - - // Service and Client ID - pQMUXHeader->mQMIService = clientID & 0xff; - pQMUXHeader->mQMIClientID = clientID >> 8; - - return 0; -} - -/*=========================================================================*/ -// Generic QMI functions -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - GetTLV (Public Method) - -DESCRIPTION: - Get data buffer of a specified TLV from a QMI message - - QMI Message shall NOT include SDU - -PARAMETERS - pQMIMessage [ I ] - QMI Message buffer - messageLen [ I ] - Size of QMI Message buffer - type [ I ] - Desired Type - pOutDataBuf [ O ] - Buffer to be filled with TLV - messageLen [ I ] - Size of QMI Message buffer - -RETURN VALUE: - u16 - Size of TLV for success - Negative errno for error -===========================================================================*/ -static int GetTLV( - void * pQMIMessage, - u16 messageLen, - u8 type, - void * pOutDataBuf, - u16 bufferLen ) -{ - u16 pos; - u16 tlvSize = 0; - u16 cpyCount; - - if (pQMIMessage == 0 || pOutDataBuf == 0) - { - return -ENOMEM; - } - - for (pos = 4; - pos + 3 < messageLen; - pos += tlvSize + 3) - { - tlvSize = le16_to_cpu( get_unaligned(((u16 *)(pQMIMessage + pos + 1) )) ); - if (*(u8 *)(pQMIMessage + pos) == type) - { - if (bufferLen < tlvSize) - { - return -ENOMEM; - } - - for (cpyCount = 0; cpyCount < tlvSize; cpyCount++) - { - *((char*)(pOutDataBuf + cpyCount)) = *((char*)(pQMIMessage + pos + 3 + cpyCount)); - } - - return tlvSize; - } - } - - return -ENOMSG; -} - -/*=========================================================================== -METHOD: - ValidQMIMessage (Public Method) - -DESCRIPTION: - Check mandatory TLV in a QMI message - - QMI Message shall NOT include SDU - -PARAMETERS - pQMIMessage [ I ] - QMI Message buffer - messageLen [ I ] - Size of QMI Message buffer - -RETURN VALUE: - int - 0 for success (no error) - Negative errno for error - Positive for QMI error code -===========================================================================*/ -static int ValidQMIMessage( - void * pQMIMessage, - u16 messageLen ) -{ - char mandTLV[4]; - - if (GetTLV( pQMIMessage, messageLen, 2, &mandTLV[0], 4 ) == 4) - { - // Found TLV - if (*(u16 *)&mandTLV[0] != 0) - { - return le16_to_cpu( get_unaligned(&mandTLV[2]) ); - } - else - { - return 0; - } - } - else - { - return -ENOMSG; - } -} - -/*=========================================================================== -METHOD: - GetQMIMessageID (Public Method) - -DESCRIPTION: - Get the message ID of a QMI message - - QMI Message shall NOT include SDU - -PARAMETERS - pQMIMessage [ I ] - QMI Message buffer - messageLen [ I ] - Size of QMI Message buffer - -RETURN VALUE: - int - Positive for message ID - Negative errno for error -===========================================================================*/ -static int GetQMIMessageID( - void * pQMIMessage, - u16 messageLen ) -{ - if (messageLen < 2) - { - return -ENODATA; - } - else - { - return le16_to_cpu( get_unaligned((u16 *)pQMIMessage) ); - } -} - -/*=========================================================================*/ -// Fill Buffers with QMI requests -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - QMICTLGetClientIDReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI CTL Get Client ID Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - serviceType [ I ] - Service type requested - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMICTLGetClientIDReq( - void * pBuffer, - u16 buffSize, - u8 transactionID, - u8 serviceType ) -{ - if (pBuffer == 0 || buffSize < QMICTLGetClientIDReqSize() ) - { - return -ENOMEM; - } - - // QMI CTL GET CLIENT ID - // Request - *(u8 *)(pBuffer + sizeof( sQMUX ))= 0x00; - // Transaction ID - *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID; - // Message ID - put_unaligned(cpu_to_le16(0x0022), (u16 *)(pBuffer + sizeof( sQMUX ) + 2)); - // Size of TLV's - put_unaligned(cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 4)); - // QMI Service Type - *(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01; - // Size - put_unaligned(cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 7)); - // QMI svc type - *(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = serviceType; - - // success - return sizeof( sQMUX ) + 10; -} - -/*=========================================================================== -METHOD: - QMICTLReleaseClientIDReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI CTL Release Client ID Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - clientID [ I ] - Service type requested - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMICTLReleaseClientIDReq( - void * pBuffer, - u16 buffSize, - u8 transactionID, - u16 clientID ) -{ - if (pBuffer == 0 || buffSize < QMICTLReleaseClientIDReqSize() ) - { - return -ENOMEM; - } - - DBG( "buffSize: 0x%x, transactionID: 0x%x, clientID: 0x%x,\n", - buffSize, transactionID, clientID ); - - // QMI CTL RELEASE CLIENT ID REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - *(u8 *)(pBuffer + sizeof( sQMUX ) + 1 ) = transactionID; - // Message ID - put_unaligned( cpu_to_le16(0x0023), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) ); - // Size of TLV's - put_unaligned( cpu_to_le16(0x0005), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) ); - // Release client ID - *(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01; - // Size - put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 7)); - // QMI svs type / Client ID - put_unaligned(cpu_to_le16(clientID), (u16 *)(pBuffer + sizeof( sQMUX ) + 9)); - - // success - return sizeof( sQMUX ) + 11; -} - -/*=========================================================================== -METHOD: - QMICTLReadyReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI CTL Get Version Info Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMICTLReadyReq( - void * pBuffer, - u16 buffSize, - u8 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMICTLReadyReqSize() ) - { - return -ENOMEM; - } - - DBG("buffSize: 0x%x, transactionID: 0x%x\n", buffSize, transactionID); - - // QMI CTL GET VERSION INFO REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID; - // Message ID - put_unaligned( cpu_to_le16(0x0021), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) ); - // Size of TLV's - put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) ); - - // success - return sizeof( sQMUX ) + 6; -} - -/*=========================================================================== -METHOD: - QMIWDSSetEventReportReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI WDS Set Event Report Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMIWDSSetEventReportReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMIWDSSetEventReportReqSize() ) - { - return -ENOMEM; - } - - // QMI WDS SET EVENT REPORT REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1)); - // Message ID - put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 3)); - // Size of TLV's - put_unaligned(cpu_to_le16(0x0008), (u16 *)(pBuffer + sizeof( sQMUX ) + 5)); - // Report channel rate TLV - *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x11; - // Size - put_unaligned( cpu_to_le16(0x0005), (u16 *)(pBuffer + sizeof( sQMUX ) + 8)); - // Stats period - *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0x01; - // Stats mask - put_unaligned( cpu_to_le32(0x000000ff), (u32 *)(pBuffer + sizeof( sQMUX ) + 11) ); - - // success - return sizeof( sQMUX ) + 15; -} - -/*=========================================================================== -METHOD: - QMIWDSGetPKGSRVCStatusReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI WDS Get PKG SRVC Status Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMIWDSGetPKGSRVCStatusReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMIWDSGetPKGSRVCStatusReqSize() ) - { - return -ENOMEM; - } - - // QMI WDS Get PKG SRVC Status REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - put_unaligned(cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1)); - // Message ID - put_unaligned(cpu_to_le16(0x0022), (u16 *)(pBuffer + sizeof( sQMUX ) + 3)); - // Size of TLV's - put_unaligned(cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 5)); - - // success - return sizeof( sQMUX ) + 7; -} - -#if 0 -static u16 QMIWDSSetQMUXBindMuxDataPortSize( void ) -{ - return sizeof( sQMUX ) + 29; -} - -static u16 QMIWDSSetQMUXBindMuxDataPortReq( - void * pBuffer, - u16 buffSize, - u8 MuxId, - u16 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMIWDSSetQMUXBindMuxDataPortSize() ) - { - return -ENOMEM; - } - - // QMI WDS Set QMUX Bind Mux Data Port REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - put_unaligned(cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1)); - // Message ID - put_unaligned(cpu_to_le16(0x00a2), (u16 *)(pBuffer + sizeof( sQMUX ) + 3)); - // Size of TLV's - put_unaligned(cpu_to_le16(0x0016), (u16 *)(pBuffer + sizeof( sQMUX ) + 5)); - - *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10; - put_unaligned(cpu_to_le16(0x08), (u16 *)(pBuffer + sizeof( sQMUX ) + 8)); - put_unaligned(cpu_to_le32(0x02), (u32 *)(pBuffer + sizeof( sQMUX ) + 10)); // ep_type - put_unaligned(cpu_to_le32(0x04), (u32 *)(pBuffer + sizeof( sQMUX ) + 14)); // iface_id - - *(u8 *)(pBuffer + sizeof( sQMUX ) + 18) = 0x11; - put_unaligned(cpu_to_le16(0x01), (u16 *)(pBuffer + sizeof( sQMUX ) + 19)); - *(u8 *)(pBuffer + sizeof( sQMUX ) + 21) = MuxId; // MuxId - - *(u8 *)(pBuffer + sizeof( sQMUX ) + 22) = 0x13; - put_unaligned(cpu_to_le16(0x04), (u16 *)(pBuffer + sizeof( sQMUX ) + 23)); - put_unaligned(cpu_to_le32(0x01), (u32 *)(pBuffer + sizeof( sQMUX ) + 25)); - - // success - return sizeof( sQMUX ) + 29; -} -#endif - -/*=========================================================================== -METHOD: - QMIDMSGetMEIDReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI DMS Get Serial Numbers Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMIDMSGetMEIDReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMIDMSGetMEIDReqSize() ) - { - return -ENOMEM; - } - - // QMI DMS GET SERIAL NUMBERS REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) ); - // Message ID - put_unaligned( cpu_to_le16(0x0025), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) ); - // Size of TLV's - put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 5)); - - // success - return sizeof( sQMUX ) + 7; -} - -/*=========================================================================== -METHOD: - QMIWDASetDataFormatReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI WDA Set Data Format Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMIWDASetDataFormatReq( - void * pBuffer, - u16 buffSize, - bool bRawIPMode, int qmap_version, u32 rx_size, - u16 transactionID ) -{ -if (qmap_version) { - struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG *pMUXMsg = (struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG *)(pBuffer + sizeof( sQMUX )); - - pMUXMsg->CtlFlags = 0x00; - put_unaligned( cpu_to_le16(transactionID), &pMUXMsg->TransactionId); - put_unaligned( cpu_to_le16(0x0020), &pMUXMsg->Type); - put_unaligned( cpu_to_le16(sizeof( struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG) - 7), &pMUXMsg->Length); - - //Indicates whether the Quality of Service(QOS) data format is used by the client. - pMUXMsg->QosDataFormatTlv.TLVType = 0x10; - pMUXMsg->QosDataFormatTlv.TLVLength = cpu_to_le16(0x0001); - pMUXMsg->QosDataFormatTlv.QOSSetting = 0; /* no-QOS header */ -//Underlying Link Layer Protocol - pMUXMsg->UnderlyingLinkLayerProtocolTlv.TLVType = 0x11; - pMUXMsg->UnderlyingLinkLayerProtocolTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->UnderlyingLinkLayerProtocolTlv.Value = cpu_to_le32(0x02); /* Set Ethernet mode */ -//Uplink (UL) data aggregation protocol to be used for uplink data transfer. - pMUXMsg->UplinkDataAggregationProtocolTlv.TLVType = 0x12; - pMUXMsg->UplinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->UplinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //UL QMAP is enabled -//Downlink (DL) data aggregation protocol to be used for downlink data transfer - pMUXMsg->DownlinkDataAggregationProtocolTlv.TLVType = 0x13; - pMUXMsg->DownlinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->DownlinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //UL QMAP is enabled -//Maximum number of datagrams in a single aggregated packet on downlink - pMUXMsg->DownlinkDataAggregationMaxDatagramsTlv.TLVType = 0x15; - pMUXMsg->DownlinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->DownlinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(rx_size/1024); -//Maximum size in bytes of a single aggregated packet allowed on downlink - pMUXMsg->DownlinkDataAggregationMaxSizeTlv.TLVType = 0x16; - pMUXMsg->DownlinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->DownlinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(rx_size); -//Peripheral End Point ID - pMUXMsg->epTlv.TLVType = 0x17; - pMUXMsg->epTlv.TLVLength = cpu_to_le16(8); - pMUXMsg->epTlv.ep_type = cpu_to_le32(0x02); // DATA_EP_TYPE_BAM_DMUX - pMUXMsg->epTlv.iface_id = cpu_to_le32(0x04); -//Specifies the minimum padding bytes to be added in between aggregated downlink QMAP packets. - pMUXMsg->dl_minimum_padding.TLVType = 0x19; - pMUXMsg->dl_minimum_padding.TLVLength = cpu_to_le16(4); - pMUXMsg->dl_minimum_padding.Value = cpu_to_le32(0); -//Maximum number of datagrams in a single aggregated packet on uplink - pMUXMsg->UplinkDataAggregationMaxDatagramsTlv.TLVType = 27; - pMUXMsg->UplinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->UplinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(11); -//Maximum size in bytes of a single aggregated packet allowed on uplink - pMUXMsg->UplinkDataAggregationMaxSizeTlv.TLVType = 28; - pMUXMsg->UplinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->UplinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(8*1024); -} -else { - if (pBuffer == 0 || buffSize < QMIWDASetDataFormatReqSize(qmap_version) ) - { - return -ENOMEM; - } - - // QMI WDA SET DATA FORMAT REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - - // Transaction ID - put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) ); - - // Message ID - put_unaligned( cpu_to_le16(0x0020), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) ); - - // Size of TLV's - put_unaligned( cpu_to_le16(0x000b), (u16 *)(pBuffer + sizeof( sQMUX ) + 5)); - - /* TLVType QOS Data Format 1 byte */ - *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10; // type data format - - /* TLVLength 2 bytes - see spec */ - put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 8)); - - /* DataFormat: 0-default; 1-QoS hdr present 2 bytes */ -#ifdef QOS_MODE - *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 1; /* QOS header */ -#else - *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0; /* no-QOS header */ -#endif - - /* TLVType Link-Layer Protocol (Optional) 1 byte */ - *(u8 *)(pBuffer + sizeof( sQMUX ) + 11) = 0x11; - - /* TLVLength 2 bytes */ - put_unaligned( cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 12)); - - /* LinkProt: 0x1 - ETH; 0x2 - rawIP 4 bytes */ -if (bRawIPMode) { //#ifdef DATA_MODE_RP - /* Set RawIP mode */ - put_unaligned( cpu_to_le32(0x00000002), (u32 *)(pBuffer + sizeof( sQMUX ) + 14)); - DBG("Request RawIP Data Format\n"); -} else { //#else - /* Set Ethernet mode */ - put_unaligned( cpu_to_le32(0x00000001), (u32 *)(pBuffer + sizeof( sQMUX ) + 14)); - DBG("Request Ethernet Data Format\n"); -} //#endif - -} - - // success - return QMIWDASetDataFormatReqSize(qmap_version); -} - -#if 0 -static int QMIWDASetDataQmapReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ) -{ - // QMI WDA SET DATA FORMAT REQ - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - - // Transaction ID - put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) ); - - // Message ID - put_unaligned( cpu_to_le16(0x002B), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) ); - - // Size of TLV's - put_unaligned( cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 5)); - - /* TLVType QMAP In-Band Flow Control 1 byte */ - *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10; - put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 8)); - *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0x01; - - // success - return ( sizeof( sQMUX ) + 11); -} -#endif - -#if 0 -/*=========================================================================== -METHOD: - QMICTLSetDataFormatReqSize (Public Method) - -DESCRIPTION: - Get size of buffer needed for QMUX + QMICTLSetDataFormatReq - -RETURN VALUE: - u16 - size of buffer -===========================================================================*/ -static u16 QMICTLSetDataFormatReqSize( void ) -{ - return sizeof( sQMUX ) + 15; -} - -/*=========================================================================== -METHOD: - QMICTLSetDataFormatReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI CTL Set Data Format Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMICTLSetDataFormatReq( - void * pBuffer, - u16 buffSize, - u8 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMICTLSetDataFormatReqSize() ) - { - return -ENOMEM; - } - - /* QMI CTL Set Data Format Request */ - /* Request */ - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; // QMICTL_FLAG_REQUEST - - /* Transaction ID 1 byte */ - *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID; /* 1 byte as in spec */ - - /* QMICTLType 2 bytes */ - put_unaligned( cpu_to_le16(0x0026), (u16 *)(pBuffer + sizeof( sQMUX ) + 2)); - - /* Length 2 bytes of 2 TLVs each - see spec */ - put_unaligned( cpu_to_le16(0x0009), (u16 *)(pBuffer + sizeof( sQMUX ) + 4)); - - /* TLVType Data Format (Mandatory) 1 byte */ - *(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01; // type data format - - /* TLVLength 2 bytes - see spec */ - put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 7)); - - /* DataFormat: 0-default; 1-QoS hdr present 2 bytes */ -#ifdef QOS_MODE - *(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = 1; /* QOS header */ -#else - *(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = 0; /* no-QOS header */ -#endif - - /* TLVType Link-Layer Protocol (Optional) 1 byte */ - *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = TLV_TYPE_LINK_PROTO; - - /* TLVLength 2 bytes */ - put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 11)); - - /* LinkProt: 0x1 - ETH; 0x2 - rawIP 2 bytes */ -#ifdef DATA_MODE_RP - /* Set RawIP mode */ - put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 13)); - DBG("Request RawIP Data Format\n"); -#else - /* Set Ethernet mode */ - put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 13)); - DBG("Request Ethernet Data Format\n"); -#endif - - /* success */ - return sizeof( sQMUX ) + 15; - -} -#endif - -/*=========================================================================== -METHOD: - QMICTLSyncReq (Public Method) - -DESCRIPTION: - Fill buffer with QMI CTL Sync Request - -PARAMETERS - pBuffer [ 0 ] - Buffer to be filled - buffSize [ I ] - Size of pBuffer - transactionID [ I ] - Transaction ID - -RETURN VALUE: - int - Positive for resulting size of pBuffer - Negative errno for error -===========================================================================*/ -static int QMICTLSyncReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ) -{ - if (pBuffer == 0 || buffSize < QMICTLSyncReqSize() ) - { - return -ENOMEM; - } - - // Request - *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; - // Transaction ID - *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID; - // Message ID - put_unaligned( cpu_to_le16(0x0027), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) ); - // Size of TLV's - put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) ); - - // success - return sizeof( sQMUX ) + 6; -} - -/*=========================================================================*/ -// Parse data from QMI responses -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - QMICTLGetClientIDResp (Public Method) - -DESCRIPTION: - Parse the QMI CTL Get Client ID Resp - -PARAMETERS - pBuffer [ I ] - Buffer to be parsed - buffSize [ I ] - Size of pBuffer - pClientID [ 0 ] - Recieved client ID - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int QMICTLGetClientIDResp( - void * pBuffer, - u16 buffSize, - u16 * pClientID ) -{ - int result; - - // Ignore QMUX and SDU - // QMI CTL SDU is 2 bytes, not 3 - u8 offset = sizeof( sQMUX ) + 2; - - if (pBuffer == 0 || buffSize < offset) - { - return -ENOMEM; - } - - pBuffer = pBuffer + offset; - buffSize -= offset; - - result = GetQMIMessageID( pBuffer, buffSize ); - if (result != 0x22) - { - return -EFAULT; - } - - result = ValidQMIMessage( pBuffer, buffSize ); - if (result != 0) - { - return -EFAULT; - } - - result = GetTLV( pBuffer, buffSize, 0x01, pClientID, 2 ); - if (result != 2) - { - return -EFAULT; - } - - return 0; -} - -/*=========================================================================== -METHOD: - QMICTLReleaseClientIDResp (Public Method) - -DESCRIPTION: - Verify the QMI CTL Release Client ID Resp is valid - -PARAMETERS - pBuffer [ I ] - Buffer to be parsed - buffSize [ I ] - Size of pBuffer - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int QMICTLReleaseClientIDResp( - void * pBuffer, - u16 buffSize ) -{ - int result; - - // Ignore QMUX and SDU - // QMI CTL SDU is 2 bytes, not 3 - u8 offset = sizeof( sQMUX ) + 2; - - if (pBuffer == 0 || buffSize < offset) - { - return -ENOMEM; - } - - pBuffer = pBuffer + offset; - buffSize -= offset; - - result = GetQMIMessageID( pBuffer, buffSize ); - if (result != 0x23) - { - return -EFAULT; - } - - result = ValidQMIMessage( pBuffer, buffSize ); - if (result != 0) - { - return -EFAULT; - } - - return 0; -} - -/*=========================================================================== -METHOD: - QMIWDSEventResp (Public Method) - -DESCRIPTION: - Parse the QMI WDS Set Event Report Resp/Indication or - QMI WDS Get PKG SRVC Status Resp/Indication - - Return parameters will only be updated if value was received - -PARAMETERS - pBuffer [ I ] - Buffer to be parsed - buffSize [ I ] - Size of pBuffer - pTXOk [ O ] - Number of transmitted packets without errors - pRXOk [ O ] - Number of recieved packets without errors - pTXErr [ O ] - Number of transmitted packets with framing errors - pRXErr [ O ] - Number of recieved packets with framing errors - pTXOfl [ O ] - Number of transmitted packets dropped due to overflow - pRXOfl [ O ] - Number of recieved packets dropped due to overflow - pTXBytesOk [ O ] - Number of transmitted bytes without errors - pRXBytesOk [ O ] - Number of recieved bytes without errors - pbLinkState [ 0 ] - Is the link active? - pbReconfigure [ 0 ] - Must interface be reconfigured? (reset IP address) - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int QMIWDSEventResp( - void * pBuffer, - u16 buffSize, - u32 * pTXOk, - u32 * pRXOk, - u32 * pTXErr, - u32 * pRXErr, - u32 * pTXOfl, - u32 * pRXOfl, - u64 * pTXBytesOk, - u64 * pRXBytesOk, - bool * pbLinkState, - bool * pbReconfigure ) -{ - int result; - u8 pktStatusRead[2]; - - // Ignore QMUX and SDU - u8 offset = sizeof( sQMUX ) + 3; - - if (pBuffer == 0 - || buffSize < offset - || pTXOk == 0 - || pRXOk == 0 - || pTXErr == 0 - || pRXErr == 0 - || pTXOfl == 0 - || pRXOfl == 0 - || pTXBytesOk == 0 - || pRXBytesOk == 0 - || pbLinkState == 0 - || pbReconfigure == 0 ) - { - return -ENOMEM; - } - - pBuffer = pBuffer + offset; - buffSize -= offset; - - // Note: Indications. No Mandatory TLV required - - result = GetQMIMessageID( pBuffer, buffSize ); - // QMI WDS Set Event Report Resp - if (result == 0x01) - { - // TLV's are not mandatory - GetTLV( pBuffer, buffSize, 0x10, (void*)pTXOk, 4 ); - put_unaligned( le32_to_cpu(*pTXOk), pTXOk); - GetTLV( pBuffer, buffSize, 0x11, (void*)pRXOk, 4 ); - put_unaligned( le32_to_cpu(*pRXOk), pRXOk); - GetTLV( pBuffer, buffSize, 0x12, (void*)pTXErr, 4 ); - put_unaligned( le32_to_cpu(*pTXErr), pTXErr); - GetTLV( pBuffer, buffSize, 0x13, (void*)pRXErr, 4 ); - put_unaligned( le32_to_cpu(*pRXErr), pRXErr); - GetTLV( pBuffer, buffSize, 0x14, (void*)pTXOfl, 4 ); - put_unaligned( le32_to_cpu(*pTXOfl), pTXOfl); - GetTLV( pBuffer, buffSize, 0x15, (void*)pRXOfl, 4 ); - put_unaligned( le32_to_cpu(*pRXOfl), pRXOfl); - GetTLV( pBuffer, buffSize, 0x19, (void*)pTXBytesOk, 8 ); - put_unaligned( le64_to_cpu(*pTXBytesOk), pTXBytesOk); - GetTLV( pBuffer, buffSize, 0x1A, (void*)pRXBytesOk, 8 ); - put_unaligned( le64_to_cpu(*pRXBytesOk), pRXBytesOk); - } - // QMI WDS Get PKG SRVC Status Resp - else if (result == 0x22) - { - result = GetTLV( pBuffer, buffSize, 0x01, &pktStatusRead[0], 2 ); - // 1 or 2 bytes may be received - if (result >= 1) - { - if (pktStatusRead[0] == 0x02) - { - *pbLinkState = true; - } - else - { - *pbLinkState = false; - } - } - if (result == 2) - { - if (pktStatusRead[1] == 0x01) - { - *pbReconfigure = true; - } - else - { - *pbReconfigure = false; - } - } - - if (result < 0) - { - return result; - } - } - else - { - return -EFAULT; - } - - return 0; -} - -/*=========================================================================== -METHOD: - QMIDMSGetMEIDResp (Public Method) - -DESCRIPTION: - Parse the QMI DMS Get Serial Numbers Resp - -PARAMETERS - pBuffer [ I ] - Buffer to be parsed - buffSize [ I ] - Size of pBuffer - pMEID [ O ] - Device MEID - meidSize [ I ] - Size of MEID buffer (at least 14) - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int QMIDMSGetMEIDResp( - void * pBuffer, - u16 buffSize, - char * pMEID, - int meidSize ) -{ - int result; - - // Ignore QMUX and SDU - u8 offset = sizeof( sQMUX ) + 3; - - if (pBuffer == 0 || buffSize < offset || meidSize < 14) - { - return -ENOMEM; - } - - pBuffer = pBuffer + offset; - buffSize -= offset; - - result = GetQMIMessageID( pBuffer, buffSize ); - if (result != 0x25) - { - return -EFAULT; - } - - result = ValidQMIMessage( pBuffer, buffSize ); - if (result != 0) - { - return -EFAULT; - } - - result = GetTLV( pBuffer, buffSize, 0x12, (void*)pMEID, 14 ); - if (result != 14) - { - return -EFAULT; - } - - return 0; -} - -/*=========================================================================== -METHOD: - QMIWDASetDataFormatResp (Public Method) - -DESCRIPTION: - Parse the QMI WDA Set Data Format Response - -PARAMETERS - pBuffer [ I ] - Buffer to be parsed - buffSize [ I ] - Size of pBuffer - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int QMIWDASetDataFormatResp( - void * pBuffer, - u16 buffSize, bool bRawIPMode, int *qmap_version, int *rx_size, int *tx_size, QMAP_SETTING *set) -{ - - int result; - - u8 pktLinkProtocol[4]; - - // Ignore QMUX and SDU - // QMI SDU is 3 bytes - u8 offset = sizeof( sQMUX ) + 3; - - if (pBuffer == 0 || buffSize < offset) - { - return -ENOMEM; - } - - pBuffer = pBuffer + offset; - buffSize -= offset; - - result = GetQMIMessageID( pBuffer, buffSize ); - if (result != 0x20) - { - return -EFAULT; - } - - /* Check response message result TLV */ - result = ValidQMIMessage( pBuffer, buffSize ); - if (result != 0) - { - DBG("EFAULT: Data Format Mode Bad Response\n"); -// return -EFAULT; - return 0; - } - - /* Check response message link protocol */ - result = GetTLV( pBuffer, buffSize, 0x11, - &pktLinkProtocol[0], 4); - if (result != 4) - { - DBG("EFAULT: Wrong TLV format\n"); - return 0; - } - -if (bRawIPMode) { ////#ifdef DATA_MODE_RP - if (pktLinkProtocol[0] != 2) - { - DBG("EFAULT: Data Format Cannot be set to RawIP Mode\n"); - return pktLinkProtocol[0]; - } - DBG("Data Format Set to RawIP\n"); -} else { ////#else - if (pktLinkProtocol[0] != 1) - { - DBG("EFAULT: Data Format Cannot be set to Ethernet Mode\n"); - return pktLinkProtocol[0]; - } - DBG("Data Format Set to Ethernet Mode \n"); -} //#endif - - GetTLV( pBuffer, buffSize, 0x12, qmap_version, 4); - if (le32_to_cpu(*qmap_version)) - GetTLV( pBuffer, buffSize, 0x13, qmap_version, 4); - - GetTLV( pBuffer, buffSize, 0x16, rx_size, 4); - GetTLV( pBuffer, buffSize, 0x18, tx_size, 4); - - if (set) { - GetTLV( pBuffer, buffSize, 0x15, &set->dl_data_aggregation_max_datagrams, 4); - GetTLV( pBuffer, buffSize, 0x16, &set->dl_data_aggregation_max_size, 4); - GetTLV( pBuffer, buffSize, 0x17, &set->ul_data_aggregation_max_datagrams, 4); - GetTLV( pBuffer, buffSize, 0x18, &set->ul_data_aggregation_max_size, 4); - GetTLV( pBuffer, buffSize, 0x1a, &set->dl_minimum_padding, 4); - } - - return pktLinkProtocol[0]; -} - -/*=========================================================================== -METHOD: - QMICTLSyncResp (Public Method) - -DESCRIPTION: - Validate the QMI CTL Sync Response - -PARAMETERS - pBuffer [ I ] - Buffer to be parsed - buffSize [ I ] - Size of pBuffer - -RETURN VALUE: - int - 0 for success - Negative errno for error -===========================================================================*/ -static int QMICTLSyncResp( - void *pBuffer, - u16 buffSize ) -{ - int result; - - // Ignore QMUX (2 bytes for QMI CTL) and SDU - u8 offset = sizeof( sQMUX ) + 2; - - if (pBuffer == 0 || buffSize < offset) - { - return -ENOMEM; - } - - pBuffer = pBuffer + offset; - buffSize -= offset; - - result = GetQMIMessageID( pBuffer, buffSize ); - if (result != 0x27) - { - return -EFAULT; - } - - result = ValidQMIMessage( pBuffer, buffSize ); - - return result; -} -#endif diff --git a/quectel_Gobinet/src/QMI.h b/quectel_Gobinet/src/QMI.h deleted file mode 100644 index 4508be4..0000000 --- a/quectel_Gobinet/src/QMI.h +++ /dev/null @@ -1,337 +0,0 @@ -/*=========================================================================== -FILE: - QMI.h - -DESCRIPTION: - Qualcomm QMI driver header - -FUNCTIONS: - Generic QMUX functions - ParseQMUX - FillQMUX - - Generic QMI functions - GetTLV - ValidQMIMessage - GetQMIMessageID - - Get sizes of buffers needed by QMI requests - QMUXHeaderSize - QMICTLGetClientIDReqSize - QMICTLReleaseClientIDReqSize - QMICTLReadyReqSize - QMIWDSSetEventReportReqSize - QMIWDSGetPKGSRVCStatusReqSize - QMIDMSGetMEIDReqSize - QMICTLSyncReqSize - - Fill Buffers with QMI requests - QMICTLGetClientIDReq - QMICTLReleaseClientIDReq - QMICTLReadyReq - QMIWDSSetEventReportReq - QMIWDSGetPKGSRVCStatusReq - QMIDMSGetMEIDReq - QMICTLSetDataFormatReq - QMICTLSyncReq - - Parse data from QMI responses - QMICTLGetClientIDResp - QMICTLReleaseClientIDResp - QMIWDSEventResp - QMIDMSGetMEIDResp - -Copyright (c) 2011, Code Aurora Forum. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Code Aurora Forum 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 OWNER 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. -===========================================================================*/ - -#pragma once - -/*=========================================================================*/ -// Definitions -/*=========================================================================*/ - -extern int quec_debug; -// DBG macro -#define DBG( format, arg... ) do { \ - if (quec_debug == 1)\ - { \ - printk( KERN_INFO "GobiNet::%s " format, __FUNCTION__, ## arg ); \ - } }while(0) - -#if 0 -#define VDBG( format, arg... ) do { \ - if (debug == 1)\ - { \ - printk( KERN_INFO "GobiNet::%s " format, __FUNCTION__, ## arg ); \ - } } while(0) -#else -#define VDBG( format, arg... ) do { } while(0) -#endif - -#define INFO( format, arg... ) do { \ - printk( KERN_INFO "GobiNet::%s " format, __FUNCTION__, ## arg ); \ - }while(0) - -// QMI Service Types -#define QMICTL 0 -#define QMIWDS 1 -#define QMIDMS 2 -#define QMINAS 3 -#define QMIUIM 11 -#define QMIWDA 0x1A - -#define u8 unsigned char -#define u16 unsigned short -#define u32 unsigned int -#define u64 unsigned long long - -#define bool u8 -#define true 1 -#define false 0 - -#define ENOMEM 12 -#define EFAULT 14 -#define EINVAL 22 -#ifndef ENOMSG -#define ENOMSG 42 -#endif -#define ENODATA 61 - -#define TLV_TYPE_LINK_PROTO 0x10 - -/*=========================================================================*/ -// Struct sQMUX -// -// Structure that defines a QMUX header -/*=========================================================================*/ -typedef struct sQMUX -{ - /* T\F, always 1 */ - u8 mTF; - - /* Size of message */ - u16 mLength; - - /* Control flag */ - u8 mCtrlFlag; - - /* Service Type */ - u8 mQMIService; - - /* Client ID */ - u8 mQMIClientID; - -}__attribute__((__packed__)) sQMUX; - -#if 0 -/*=========================================================================*/ -// Generic QMUX functions -/*=========================================================================*/ - -// Remove QMUX headers from a buffer -int ParseQMUX( - u16 * pClientID, - void * pBuffer, - u16 buffSize ); - -// Fill buffer with QMUX headers -int FillQMUX( - u16 clientID, - void * pBuffer, - u16 buffSize ); - -/*=========================================================================*/ -// Generic QMI functions -/*=========================================================================*/ - -// Get data buffer of a specified TLV from a QMI message -int GetTLV( - void * pQMIMessage, - u16 messageLen, - u8 type, - void * pOutDataBuf, - u16 bufferLen ); - -// Check mandatory TLV in a QMI message -int ValidQMIMessage( - void * pQMIMessage, - u16 messageLen ); - -// Get the message ID of a QMI message -int GetQMIMessageID( - void * pQMIMessage, - u16 messageLen ); - -/*=========================================================================*/ -// Get sizes of buffers needed by QMI requests -/*=========================================================================*/ - -// Get size of buffer needed for QMUX -u16 QMUXHeaderSize( void ); - -// Get size of buffer needed for QMUX + QMICTLGetClientIDReq -u16 QMICTLGetClientIDReqSize( void ); - -// Get size of buffer needed for QMUX + QMICTLReleaseClientIDReq -u16 QMICTLReleaseClientIDReqSize( void ); - -// Get size of buffer needed for QMUX + QMICTLReadyReq -u16 QMICTLReadyReqSize( void ); - -// Get size of buffer needed for QMUX + QMIWDSSetEventReportReq -u16 QMIWDSSetEventReportReqSize( void ); - -// Get size of buffer needed for QMUX + QMIWDSGetPKGSRVCStatusReq -u16 QMIWDSGetPKGSRVCStatusReqSize( void ); - -u16 QMIWDSSetQMUXBindMuxDataPortSize( void ); - -// Get size of buffer needed for QMUX + QMIDMSGetMEIDReq -u16 QMIDMSGetMEIDReqSize( void ); - -// Get size of buffer needed for QMUX + QMIWDASetDataFormatReq -u16 QMIWDASetDataFormatReqSize( int qmap_mode ); - -// Get size of buffer needed for QMUX + QMICTLSyncReq -u16 QMICTLSyncReqSize( void ); - -/*=========================================================================*/ -// Fill Buffers with QMI requests -/*=========================================================================*/ - -// Fill buffer with QMI CTL Get Client ID Request -int QMICTLGetClientIDReq( - void * pBuffer, - u16 buffSize, - u8 transactionID, - u8 serviceType ); - -// Fill buffer with QMI CTL Release Client ID Request -int QMICTLReleaseClientIDReq( - void * pBuffer, - u16 buffSize, - u8 transactionID, - u16 clientID ); - -// Fill buffer with QMI CTL Get Version Info Request -int QMICTLReadyReq( - void * pBuffer, - u16 buffSize, - u8 transactionID ); - -// Fill buffer with QMI WDS Set Event Report Request -int QMIWDSSetEventReportReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ); - -// Fill buffer with QMI WDS Get PKG SRVC Status Request -int QMIWDSGetPKGSRVCStatusReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ); - -u16 QMIWDSSetQMUXBindMuxDataPortReq( - void * pBuffer, - u16 buffSize, - u8 MuxId, - u16 transactionID ); - -// Fill buffer with QMI DMS Get Serial Numbers Request -int QMIDMSGetMEIDReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ); - -// Fill buffer with QMI WDA Set Data Format Request -int QMIWDASetDataFormatReq( - void * pBuffer, - u16 buffSize, - bool bRawIPMode, int qmap_mode, u32 rx_size, - u16 transactionID ); - -#if 0 -int QMIWDASetDataQmapReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ); -#endif - -int QMICTLSyncReq( - void * pBuffer, - u16 buffSize, - u16 transactionID ); - -/*=========================================================================*/ -// Parse data from QMI responses -/*=========================================================================*/ - -// Parse the QMI CTL Get Client ID Resp -int QMICTLGetClientIDResp( - void * pBuffer, - u16 buffSize, - u16 * pClientID ); - -// Verify the QMI CTL Release Client ID Resp is valid -int QMICTLReleaseClientIDResp( - void * pBuffer, - u16 buffSize ); - -// Parse the QMI WDS Set Event Report Resp/Indication or -// QMI WDS Get PKG SRVC Status Resp/Indication -int QMIWDSEventResp( - void * pBuffer, - u16 buffSize, - u32 * pTXOk, - u32 * pRXOk, - u32 * pTXErr, - u32 * pRXErr, - u32 * pTXOfl, - u32 * pRXOfl, - u64 * pTXBytesOk, - u64 * pRXBytesOk, - bool * pbLinkState, - bool * pbReconfigure ); - -// Parse the QMI DMS Get Serial Numbers Resp -int QMIDMSGetMEIDResp( - void * pBuffer, - u16 buffSize, - char * pMEID, - int meidSize ); - -// Parse the QMI DMS Get Serial Numbers Resp -int QMIWDASetDataFormatResp( - void * pBuffer, - u16 buffSize, bool bRawIPMode, int *qmap_enabled, int *rx_size, int *tx_size); - -// Pasre the QMI CTL Sync Response -int QMICTLSyncResp( - void *pBuffer, - u16 buffSize ); -#endif diff --git a/quectel_Gobinet/src/QMIDevice.c b/quectel_Gobinet/src/QMIDevice.c deleted file mode 100644 index fe6b6cf..0000000 --- a/quectel_Gobinet/src/QMIDevice.c +++ /dev/null @@ -1,4363 +0,0 @@ -/*=========================================================================== -FILE: - QMIDevice.c - -DESCRIPTION: - Functions related to the QMI interface device - -FUNCTIONS: - Generic functions - IsDeviceValid - PrintHex - GobiSetDownReason - GobiClearDownReason - GobiTestDownReason - - Driver level asynchronous read functions - ResubmitIntURB - ReadCallback - IntCallback - StartRead - KillRead - - Internal read/write functions - ReadAsync - UpSem - ReadSync - WriteSyncCallback - WriteSync - - Internal memory management functions - GetClientID - ReleaseClientID - FindClientMem - AddToReadMemList - PopFromReadMemList - AddToNotifyList - NotifyAndPopNotifyList - AddToURBList - PopFromURBList - - Internal userspace wrapper functions - UserspaceunlockedIOCTL - - Userspace wrappers - UserspaceOpen - UserspaceIOCTL - UserspaceClose - UserspaceRead - UserspaceWrite - UserspacePoll - - Initializer and destructor - RegisterQMIDevice - DeregisterQMIDevice - - Driver level client management - QMIReady - QMIWDSCallback - SetupQMIWDSCallback - QMIDMSGetMEID - -Copyright (c) 2011, Code Aurora Forum. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Code Aurora Forum 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 OWNER 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 Files -//--------------------------------------------------------------------------- -#include -#include -#include -#include - -//----------------------------------------------------------------------------- -// Definitions -//----------------------------------------------------------------------------- - -#define __QUEC_INCLUDE_QMI_C__ -#include "QMI.c" -#define __QUECTEL_INTER__ -#include "QMIDevice.h" - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 )) -static int s_interval; -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,14 )) -#include -static char devfs_name[32]; -static int device_create(struct class *class, struct device *parent, dev_t devt, const char *fmt, ...) -{ - va_list vargs; - struct class_device *class_dev; - int err; - - va_start(vargs, fmt); - vsnprintf(devfs_name, sizeof(devfs_name), fmt, vargs); - va_end(vargs); - - class_dev = class_device_create(class, devt, parent, "%s", devfs_name); - if (IS_ERR(class_dev)) { - err = PTR_ERR(class_dev); - goto out; - } - - err = devfs_mk_cdev(devt, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, devfs_name); - if (err) { - class_device_destroy(class, devt); - goto out; - } - - return 0; - -out: - return err; -} - -static void device_destroy(struct class *class, dev_t devt) -{ - class_device_destroy(class, devt); - devfs_remove(devfs_name); -} -#endif - -#ifdef CONFIG_PM -// Prototype to GobiNetSuspend function -int QuecGobiNetSuspend( - struct usb_interface * pIntf, - pm_message_t powerEvent ); -#endif /* CONFIG_PM */ - -// IOCTL to generate a client ID for this service type -#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1 - -// IOCTL to get the VIDPID of the device -#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2 - -// IOCTL to get the MEID of the device -#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3 - -#define IOCTL_QMI_RELEASE_SERVICE_FILE_IOCTL (0x8BE0 + 4) - -// CDC GET_ENCAPSULATED_RESPONSE packet -#define CDC_GET_ENCAPSULATED_RESPONSE_LE 0x01A1ll -#define CDC_GET_ENCAPSULATED_RESPONSE_BE 0xA101000000000000ll -/* The following masks filter the common part of the encapsulated response - * packet value for Gobi and QMI devices, ie. ignore usb interface number - */ -#define CDC_RSP_MASK_BE 0xFFFFFFFF00FFFFFFll -#define CDC_RSP_MASK_LE 0xFFFFFFE0FFFFFFFFll - -static const int i = 1; -#define is_bigendian() ( (*(char*)&i) == 0 ) -#define CDC_GET_ENCAPSULATED_RESPONSE(pcdcrsp, pmask)\ -{\ - *pcdcrsp = is_bigendian() ? CDC_GET_ENCAPSULATED_RESPONSE_BE \ - : CDC_GET_ENCAPSULATED_RESPONSE_LE ; \ - *pmask = is_bigendian() ? CDC_RSP_MASK_BE \ - : CDC_RSP_MASK_LE; \ -} - -// CDC CONNECTION_SPEED_CHANGE indication packet -#define CDC_CONNECTION_SPEED_CHANGE_LE 0x2AA1ll -#define CDC_CONNECTION_SPEED_CHANGE_BE 0xA12A000000000000ll -/* The following masks filter the common part of the connection speed change - * packet value for Gobi and QMI devices - */ -#define CDC_CONNSPD_MASK_BE 0xFFFFFFFFFFFF7FFFll -#define CDC_CONNSPD_MASK_LE 0XFFF7FFFFFFFFFFFFll -#define CDC_GET_CONNECTION_SPEED_CHANGE(pcdccscp, pmask)\ -{\ - *pcdccscp = is_bigendian() ? CDC_CONNECTION_SPEED_CHANGE_BE \ - : CDC_CONNECTION_SPEED_CHANGE_LE ; \ - *pmask = is_bigendian() ? CDC_CONNSPD_MASK_BE \ - : CDC_CONNSPD_MASK_LE; \ -} - -#define SET_CONTROL_LINE_STATE_REQUEST_TYPE 0x21 -#define SET_CONTROL_LINE_STATE_REQUEST 0x22 -#define CONTROL_DTR 0x01 -#define CONTROL_RTS 0x02 - -/*=========================================================================*/ -// UserspaceQMIFops -// QMI device's userspace file operations -/*=========================================================================*/ -static struct file_operations UserspaceQMIFops = -{ - .owner = THIS_MODULE, - .read = UserspaceRead, - .write = UserspaceWrite, -#ifdef CONFIG_COMPAT - .compat_ioctl = UserspaceunlockedIOCTL, -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,36 )) - .unlocked_ioctl = UserspaceunlockedIOCTL, -#else - .ioctl = UserspaceIOCTL, -#endif - .open = UserspaceOpen, -#ifdef quectel_no_for_each_process - .release = UserspaceClose, -#else - .flush = UserspaceClose, -#endif - .poll = UserspacePoll, -}; - -/*=========================================================================*/ -// Generic functions -/*=========================================================================*/ -static u8 QMIXactionIDGet( sGobiUSBNet *pDev) -{ - u8 transactionID; - - if( 0 == (transactionID = atomic_add_return( 1, &pDev->mQMIDev.mQMICTLTransactionID)) ) - { - transactionID = atomic_add_return( 1, &pDev->mQMIDev.mQMICTLTransactionID ); - } - -#if 1 //free these ununsed qmi response, or when these transactionID re-used, they will be regarded as qmi response of the qmi request that have same transactionID - if (transactionID) { - unsigned long flags; - void * pReadBuffer; - u16 readBufferSize; - - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - while (PopFromReadMemList( pDev, - QMICTL, - transactionID, - &pReadBuffer, - &readBufferSize ) == true) - { - kfree( pReadBuffer ); - } - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - } -#endif - - return transactionID; -} - -static struct usb_endpoint_descriptor *GetEndpoint( - struct usb_interface *pintf, - int type, - int dir ) -{ - int i; - struct usb_host_interface *iface = pintf->cur_altsetting; - struct usb_endpoint_descriptor *pendp; - - for( i = 0; i < iface->desc.bNumEndpoints; i++) - { - pendp = &iface->endpoint[i].desc; - if( ((pendp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir) - && - (usb_endpoint_type(pendp) == type) ) - { - return pendp; - } - } - - return NULL; -} - -/*=========================================================================== -METHOD: - IsDeviceValid (Public Method) - -DESCRIPTION: - Basic test to see if device memory is valid - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - bool -===========================================================================*/ -static bool IsDeviceValid( sGobiUSBNet * pDev ) -{ - if (pDev == NULL) - { - return false; - } - - if (pDev->mbQMIValid == false) - { - return false; - } - - return true; -} - -/*=========================================================================== -METHOD: - PrintHex (Public Method) - -DESCRIPTION: - Print Hex data, for debug purposes - -PARAMETERS: - pBuffer [ I ] - Data buffer - bufSize [ I ] - Size of data buffer - -RETURN VALUE: - None -===========================================================================*/ -void QuecPrintHex( - void * pBuffer, - u16 bufSize ) -{ - char * pPrintBuf; - u16 pos; - int status; - - if (quec_debug != 1) - { - return; - } - - pPrintBuf = kmalloc( bufSize * 3 + 1, GFP_ATOMIC ); - if (pPrintBuf == NULL) - { - DBG( "Unable to allocate buffer\n" ); - return; - } - memset( pPrintBuf, 0 , bufSize * 3 + 1 ); - - for (pos = 0; pos < bufSize; pos++) - { - status = snprintf( (pPrintBuf + (pos * 3)), - 4, - "%02X ", - *(u8 *)(pBuffer + pos) ); - if (status != 3) - { - DBG( "snprintf error %d\n", status ); - kfree( pPrintBuf ); - return; - } - } - - DBG( " : %s\n", pPrintBuf ); - - kfree( pPrintBuf ); - pPrintBuf = NULL; - return; -} - -/*=========================================================================== -METHOD: - GobiSetDownReason (Public Method) - -DESCRIPTION: - Sets mDownReason and turns carrier off - -PARAMETERS - pDev [ I ] - Device specific memory - reason [ I ] - Reason device is down - -RETURN VALUE: - None -===========================================================================*/ -void QuecGobiSetDownReason( - sGobiUSBNet * pDev, - u8 reason ) -{ - DBG("%s reason=%d, mDownReason=%x\n", __func__, reason, (unsigned)pDev->mDownReason); - -#ifdef QUECTEL_WWAN_QMAP - if (reason == NO_NDIS_CONNECTION) - return; -#endif - - set_bit( reason, &pDev->mDownReason ); - - netif_carrier_off( pDev->mpNetDev->net ); -} - -/*=========================================================================== -METHOD: - GobiClearDownReason (Public Method) - -DESCRIPTION: - Clear mDownReason and may turn carrier on - -PARAMETERS - pDev [ I ] - Device specific memory - reason [ I ] - Reason device is no longer down - -RETURN VALUE: - None -===========================================================================*/ -void QuecGobiClearDownReason( - sGobiUSBNet * pDev, - u8 reason ) -{ - clear_bit( reason, &pDev->mDownReason ); - - DBG("%s reason=%d, mDownReason=%x\n", __func__, reason, (unsigned)pDev->mDownReason); -#if 0 //(LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) - netif_carrier_on( pDev->mpNetDev->net ); -#else - if (pDev->mDownReason == 0) - { -#ifdef QUECTEL_WWAN_QMAP - if (pDev->qmap_mode && !pDev->link_state) - ; - else -#endif - netif_carrier_on( pDev->mpNetDev->net ); - } -#endif -} - -/*=========================================================================== -METHOD: - GobiTestDownReason (Public Method) - -DESCRIPTION: - Test mDownReason and returns whether reason is set - -PARAMETERS - pDev [ I ] - Device specific memory - reason [ I ] - Reason device is down - -RETURN VALUE: - bool -===========================================================================*/ -bool QuecGobiTestDownReason( - sGobiUSBNet * pDev, - u8 reason ) -{ - return test_bit( reason, &pDev->mDownReason ); -} - -/*=========================================================================*/ -// Driver level asynchronous read functions -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - ResubmitIntURB (Public Method) - -DESCRIPTION: - Resubmit interrupt URB, re-using same values - -PARAMETERS - pIntURB [ I ] - Interrupt URB - -RETURN VALUE: - int - 0 for success - negative errno for failure -===========================================================================*/ -static int ResubmitIntURB( struct urb * pIntURB ) -{ - int status; - int interval; - - // Sanity test - if ( (pIntURB == NULL) - || (pIntURB->dev == NULL) ) - { - return -EINVAL; - } - - // Interval needs reset after every URB completion -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,22 )) - interval = max((int)(pIntURB->ep->desc.bInterval), - (pIntURB->dev->speed == USB_SPEED_HIGH) ? 7 : 3); -#else - interval = s_interval; -#endif - - // Reschedule interrupt URB - usb_fill_int_urb( pIntURB, - pIntURB->dev, - pIntURB->pipe, - pIntURB->transfer_buffer, - pIntURB->transfer_buffer_length, - pIntURB->complete, - pIntURB->context, - interval ); - status = usb_submit_urb( pIntURB, GFP_ATOMIC ); - if (status != 0) - { - DBG( "Error re-submitting Int URB %d\n", status ); - } - - return status; -} - - -#ifdef QUECTEL_QMI_MERGE -static int MergeRecQmiMsg( sQMIDev * pQMIDev, struct urb * pReadURB ) -{ - sQMIMsgHeader * mHeader; - sQMIMsgPacket * mPacket; - - DBG( "%s called \n", __func__ ); - mPacket = pQMIDev->mpQmiMsgPacket; - - if(pReadURB->actual_length < sizeof(sQMIMsgHeader)) - { - return -1; - } - - mHeader = (sQMIMsgHeader *)pReadURB->transfer_buffer; - if(le16_to_cpu(mHeader->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(mHeader->version) != MERGE_PACKET_VERSION || le16_to_cpu(mHeader->cur_len) > le16_to_cpu(mHeader->total_len)) - return -1; - - if(le16_to_cpu(mHeader->cur_len) == le16_to_cpu(mHeader->total_len)) { - mPacket->len = le16_to_cpu(mHeader->total_len); - memcpy(pReadURB->transfer_buffer, pReadURB->transfer_buffer + sizeof(sQMIMsgHeader), mPacket->len); - pReadURB->actual_length = mPacket->len; - mPacket->len = 0; - - return 0; - } - - memcpy(mPacket->buf + mPacket->len, pReadURB->transfer_buffer + sizeof(sQMIMsgHeader), le16_to_cpu(mHeader->cur_len)); - mPacket->len += le16_to_cpu(mHeader->cur_len); - - if (le16_to_cpu(mHeader->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || mPacket->len >= le16_to_cpu(mHeader->total_len)) { - memcpy(pReadURB->transfer_buffer, mPacket->buf, mPacket->len); - pReadURB->actual_length = mPacket->len; - mPacket->len = 0; - return 0; - } - - return -1; -} -#endif - -/*=========================================================================== -METHOD: - ReadCallback (Public Method) - -DESCRIPTION: - Put the data in storage and notify anyone waiting for data - -PARAMETERS - pReadURB [ I ] - URB this callback is run for - -RETURN VALUE: - None -===========================================================================*/ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -static void ReadCallback( struct urb * pReadURB ) -#else -static void ReadCallback(struct urb *pReadURB, struct pt_regs *regs) -#endif -{ - int result; - u16 clientID; - sClientMemList * pClientMem; - void * pData; - void * pDataCopy; - u16 dataSize; - sGobiUSBNet * pDev; - unsigned long flags; - u16 transactionID; - - if (pReadURB == NULL) - { - DBG( "bad read URB\n" ); - return; - } - - pDev = pReadURB->context; - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return; - } - -#ifdef READ_QMI_URB_ERROR - del_timer(&pDev->mQMIDev.mReadUrbTimer); - if ((pReadURB->status == -ECONNRESET) && (pReadURB->actual_length > 0)) - pReadURB->status = 0; -#endif - - if (pReadURB->status != 0) - { - DBG( "Read status = %d\n", pReadURB->status ); - - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); - - return; - } - DBG( "Read %d bytes\n", pReadURB->actual_length ); - -#ifdef QUECTEL_QMI_MERGE - if(MergeRecQmiMsg(&pDev->mQMIDev, pReadURB)) - { - DBG( "not a full packet, read again\n"); - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); - return; - } -#endif - - pData = pReadURB->transfer_buffer; - dataSize = pReadURB->actual_length; - - PrintHex( pData, dataSize ); - -#ifdef READ_QMI_URB_ERROR - if (dataSize < (le16_to_cpu(get_unaligned((u16*)(pData + 1))) + 1)) { - dataSize = (le16_to_cpu(get_unaligned((u16*)(pData + 1))) + 1); - memset(pReadURB->transfer_buffer + pReadURB->actual_length, 0x00, dataSize - pReadURB->actual_length); - INFO( "Read %d / %d bytes\n", pReadURB->actual_length, dataSize); - } -#endif - - result = ParseQMUX( &clientID, - pData, - dataSize ); - if (result < 0) - { - DBG( "Read error parsing QMUX %d\n", result ); - - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); - - return; - } - - // Grab transaction ID - - // Data large enough? - if (dataSize < result + 3) - { - DBG( "Data buffer too small to parse\n" ); - - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); - - return; - } - - // Transaction ID size is 1 for QMICTL, 2 for others - if (clientID == QMICTL) - { - transactionID = *(u8*)(pData + result + 1); - } - else - { - transactionID = le16_to_cpu( get_unaligned((u16*)(pData + result + 1)) ); - } - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Find memory storage for this service and Client ID - // Not using FindClientMem because it can't handle broadcasts - pClientMem = pDev->mQMIDev.mpClientMemList; - - while (pClientMem != NULL) - { - if (pClientMem->mClientID == clientID - || (pClientMem->mClientID | 0xff00) == clientID) - { - // Make copy of pData - pDataCopy = kmalloc( dataSize, GFP_ATOMIC ); - if (pDataCopy == NULL) - { - DBG( "Error allocating client data memory\n" ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); - - return; - } - - memcpy( pDataCopy, pData, dataSize ); - - if (AddToReadMemList( pDev, - pClientMem->mClientID, - transactionID, - pDataCopy, - dataSize ) == false) - { - DBG( "Error allocating pReadMemListEntry " - "read will be discarded\n" ); - kfree( pDataCopy ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); - - return; - } - - // Success - VDBG( "Creating new readListEntry for client 0x%04X, TID %x\n", - clientID, - transactionID ); - - // Notify this client data exists - NotifyAndPopNotifyList( pDev, - pClientMem->mClientID, - transactionID ); - - // Possibly notify poll() that data exists - wake_up_interruptible_sync( &pClientMem->mWaitQueue ); - - // Not a broadcast - if (clientID >> 8 != 0xff) - { - break; - } - } - - // Next element - pClientMem = pClientMem->mpNext; - } - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Resubmit the interrupt URB - ResubmitIntURB( pDev->mQMIDev.mpIntURB ); -} - -/*=========================================================================== -METHOD: - IntCallback (Public Method) - -DESCRIPTION: - Data is available, fire off a read URB - -PARAMETERS - pIntURB [ I ] - URB this callback is run for - -RETURN VALUE: - None -===========================================================================*/ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -static void IntCallback( struct urb * pIntURB ) -{ -#else -static void IntCallback(struct urb *pIntURB, struct pt_regs *regs) -{ -#endif - int status; - struct usb_cdc_notification *dr; - - sGobiUSBNet * pDev = (sGobiUSBNet *)pIntURB->context; - dr = (struct usb_cdc_notification *)pDev->mQMIDev.mpIntBuffer; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return; - } - - // Verify this was a normal interrupt - if (pIntURB->status != 0) - { - DBG( "IntCallback: Int status = %d\n", pIntURB->status ); - - // Ignore EOVERFLOW errors - if (pIntURB->status != -EOVERFLOW) - { - // Read 'thread' dies here - return; - } - } - else - { - //TODO cast transfer_buffer to struct usb_cdc_notification - - VDBG( "IntCallback: Encapsulated Response = 0x%llx\n", - (*(u64*)pIntURB->transfer_buffer)); - - switch (dr->bNotificationType) { - case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: //0x01 - { - // Time to read - usb_fill_control_urb( pDev->mQMIDev.mpReadURB, - pDev->mpNetDev->udev, - usb_rcvctrlpipe( pDev->mpNetDev->udev, 0 ), - (unsigned char *)pDev->mQMIDev.mpReadSetupPacket, - pDev->mQMIDev.mpReadBuffer, - DEFAULT_READ_URB_LENGTH, - ReadCallback, - pDev ); - #ifdef READ_QMI_URB_ERROR - mod_timer( &pDev->mQMIDev.mReadUrbTimer, jiffies + msecs_to_jiffies(300) ); - #endif - status = usb_submit_urb( pDev->mQMIDev.mpReadURB, GFP_ATOMIC ); - if (status != 0) - { - DBG("Error submitting Read URB %d\n", status); - // Resubmit the interrupt urb - ResubmitIntURB(pIntURB); - return; - } - - // Int URB will be resubmitted during ReadCallback - return; - } - case USB_CDC_NOTIFY_SPEED_CHANGE: //0x2a - { - DBG( "IntCallback: Connection Speed Change = 0x%llx\n", - (*(u64*)pIntURB->transfer_buffer)); - - // if upstream or downstream is 0, stop traffic. Otherwise resume it - if ((*(u32*)(pIntURB->transfer_buffer + 8) == 0) - || (*(u32*)(pIntURB->transfer_buffer + 12) == 0)) - { - GobiSetDownReason( pDev, CDC_CONNECTION_SPEED ); - DBG( "traffic stopping due to CONNECTION_SPEED_CHANGE\n" ); - } - else - { - GobiClearDownReason( pDev, CDC_CONNECTION_SPEED ); - DBG( "resuming traffic due to CONNECTION_SPEED_CHANGE\n" ); - } - } - break; - default: - { - DBG( "ignoring invalid interrupt in packet\n" ); - PrintHex( pIntURB->transfer_buffer, pIntURB->actual_length ); - } - } - - // Resubmit the interrupt urb - ResubmitIntURB( pIntURB ); - - return; - } -} - -#ifdef READ_QMI_URB_ERROR -static void ReadUrbTimerFunc( struct urb * pReadURB ) -{ - int result; - - INFO( "%s called (%ld).\n", __func__, jiffies ); - - if ((pReadURB != NULL) && (pReadURB->status == -EINPROGRESS)) - { - // Asynchronously unlink URB. On success, -EINPROGRESS will be returned, - // URB status will be set to -ECONNRESET, and ReadCallback() executed - result = usb_unlink_urb( pReadURB ); - INFO( "%s called usb_unlink_urb, result = %d\n", __func__, result); - } -} -#endif - -/*=========================================================================== -METHOD: - StartRead (Public Method) - -DESCRIPTION: - Start continuous read "thread" (callback driven) - - Note: In case of error, KillRead() should be run - to remove urbs and clean up memory. - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - int - 0 for success - negative errno for failure -===========================================================================*/ -int QuecStartRead( sGobiUSBNet * pDev ) -{ - int interval; - struct usb_endpoint_descriptor *pendp; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return -ENXIO; - } - - // Allocate URB buffers - pDev->mQMIDev.mpReadURB = usb_alloc_urb( 0, GFP_KERNEL ); - if (pDev->mQMIDev.mpReadURB == NULL) - { - DBG( "Error allocating read urb\n" ); - return -ENOMEM; - } - -#ifdef READ_QMI_URB_ERROR - setup_timer( &pDev->mQMIDev.mReadUrbTimer, (void*)ReadUrbTimerFunc, (unsigned long)pDev->mQMIDev.mpReadURB ); -#endif - - pDev->mQMIDev.mpIntURB = usb_alloc_urb( 0, GFP_KERNEL ); - if (pDev->mQMIDev.mpIntURB == NULL) - { - DBG( "Error allocating int urb\n" ); - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - return -ENOMEM; - } - - // Create data buffers - pDev->mQMIDev.mpReadBuffer = kmalloc( DEFAULT_READ_URB_LENGTH, GFP_KERNEL ); - if (pDev->mQMIDev.mpReadBuffer == NULL) - { - DBG( "Error allocating read buffer\n" ); - usb_free_urb( pDev->mQMIDev.mpIntURB ); - pDev->mQMIDev.mpIntURB = NULL; - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - return -ENOMEM; - } - - pDev->mQMIDev.mpIntBuffer = kmalloc( 64, GFP_KERNEL ); - if (pDev->mQMIDev.mpIntBuffer == NULL) - { - DBG( "Error allocating int buffer\n" ); - kfree( pDev->mQMIDev.mpReadBuffer ); - pDev->mQMIDev.mpReadBuffer = NULL; - usb_free_urb( pDev->mQMIDev.mpIntURB ); - pDev->mQMIDev.mpIntURB = NULL; - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - return -ENOMEM; - } - - pDev->mQMIDev.mpReadSetupPacket = kmalloc( sizeof( sURBSetupPacket ), - GFP_KERNEL ); - if (pDev->mQMIDev.mpReadSetupPacket == NULL) - { - DBG( "Error allocating setup packet buffer\n" ); - kfree( pDev->mQMIDev.mpIntBuffer ); - pDev->mQMIDev.mpIntBuffer = NULL; - kfree( pDev->mQMIDev.mpReadBuffer ); - pDev->mQMIDev.mpReadBuffer = NULL; - usb_free_urb( pDev->mQMIDev.mpIntURB ); - pDev->mQMIDev.mpIntURB = NULL; - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - return -ENOMEM; - } - - // CDC Get Encapsulated Response packet - pDev->mQMIDev.mpReadSetupPacket->mRequestType = 0xA1; - pDev->mQMIDev.mpReadSetupPacket->mRequestCode = 1; - pDev->mQMIDev.mpReadSetupPacket->mValue = 0; - pDev->mQMIDev.mpReadSetupPacket->mIndex = - cpu_to_le16(pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber); /* interface number */ - pDev->mQMIDev.mpReadSetupPacket->mLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH); - - pendp = GetEndpoint(pDev->mpIntf, USB_ENDPOINT_XFER_INT, USB_DIR_IN); - if (pendp == NULL) - { - DBG( "Invalid interrupt endpoint!\n" ); - kfree(pDev->mQMIDev.mpReadSetupPacket); - pDev->mQMIDev.mpReadSetupPacket = NULL; - kfree( pDev->mQMIDev.mpIntBuffer ); - pDev->mQMIDev.mpIntBuffer = NULL; - kfree( pDev->mQMIDev.mpReadBuffer ); - pDev->mQMIDev.mpReadBuffer = NULL; - usb_free_urb( pDev->mQMIDev.mpIntURB ); - pDev->mQMIDev.mpIntURB = NULL; - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - return -ENXIO; - } - -#ifdef QUECTEL_QMI_MERGE - pDev->mQMIDev.mpQmiMsgPacket = kmalloc( sizeof(sQMIMsgPacket), GFP_KERNEL ); - if (pDev->mQMIDev.mpQmiMsgPacket == NULL) - { - DBG( "Error allocating qmi msg merge packet buffer!\n" ); - kfree(pDev->mQMIDev.mpReadSetupPacket); - pDev->mQMIDev.mpReadSetupPacket = NULL; - kfree( pDev->mQMIDev.mpIntBuffer ); - pDev->mQMIDev.mpIntBuffer = NULL; - kfree( pDev->mQMIDev.mpReadBuffer ); - pDev->mQMIDev.mpReadBuffer = NULL; - usb_free_urb( pDev->mQMIDev.mpIntURB ); - pDev->mQMIDev.mpIntURB = NULL; - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - return -ENOMEM; - } -#endif - - // Interval needs reset after every URB completion - interval = max((int)(pendp->bInterval), - (pDev->mpNetDev->udev->speed == USB_SPEED_HIGH) ? 7 : 3); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 )) - s_interval = interval; -#endif - - // Schedule interrupt URB - usb_fill_int_urb( pDev->mQMIDev.mpIntURB, - pDev->mpNetDev->udev, - /* QMI interrupt endpoint for the following - * interface configuration: DM, NMEA, MDM, NET - */ - usb_rcvintpipe( pDev->mpNetDev->udev, - pendp->bEndpointAddress), - pDev->mQMIDev.mpIntBuffer, - min((int)le16_to_cpu(pendp->wMaxPacketSize), 64), - IntCallback, - pDev, - interval ); - return usb_submit_urb( pDev->mQMIDev.mpIntURB, GFP_KERNEL ); -} - -/*=========================================================================== -METHOD: - KillRead (Public Method) - -DESCRIPTION: - Kill continuous read "thread" - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - None -===========================================================================*/ -void QuecKillRead( sGobiUSBNet * pDev ) -{ - // Stop reading - if (pDev->mQMIDev.mpReadURB != NULL) - { - DBG( "Killng read URB\n" ); - usb_kill_urb( pDev->mQMIDev.mpReadURB ); - } - - if (pDev->mQMIDev.mpIntURB != NULL) - { - DBG( "Killng int URB\n" ); - usb_kill_urb( pDev->mQMIDev.mpIntURB ); - } - - // Release buffers - kfree( pDev->mQMIDev.mpReadSetupPacket ); - pDev->mQMIDev.mpReadSetupPacket = NULL; - kfree( pDev->mQMIDev.mpReadBuffer ); - pDev->mQMIDev.mpReadBuffer = NULL; - kfree( pDev->mQMIDev.mpIntBuffer ); - pDev->mQMIDev.mpIntBuffer = NULL; - - // Release URB's - usb_free_urb( pDev->mQMIDev.mpReadURB ); - pDev->mQMIDev.mpReadURB = NULL; - usb_free_urb( pDev->mQMIDev.mpIntURB ); - pDev->mQMIDev.mpIntURB = NULL; - -#ifdef QUECTEL_QMI_MERGE - kfree( pDev->mQMIDev.mpQmiMsgPacket ); - pDev->mQMIDev.mpQmiMsgPacket = NULL; -#endif -} - -/*=========================================================================*/ -// Internal read/write functions -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - ReadAsync (Public Method) - -DESCRIPTION: - Start asynchronous read - NOTE: Reading client's data store, not device - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - transactionID [ I ] - Transaction ID or 0 for any - pCallback [ I ] - Callback to be executed when data is available - pData [ I ] - Data buffer that willl be passed (unmodified) - to callback - -RETURN VALUE: - int - 0 for success - negative errno for failure -===========================================================================*/ -static int ReadAsync( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void (*pCallback)(sGobiUSBNet*, u16, void *), - void * pData ) -{ - sClientMemList * pClientMem; - sReadMemList ** ppReadMemList; - - unsigned long flags; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return -ENXIO; - } - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Find memory storage for this client ID - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find matching client ID 0x%04X\n", - clientID ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - return -ENXIO; - } - - ppReadMemList = &(pClientMem->mpList); - - // Does data already exist? - while (*ppReadMemList != NULL) - { - // Is this element our data? - if (transactionID == 0 - || transactionID == (*ppReadMemList)->mTransactionID) - { - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Run our own callback - pCallback( pDev, clientID, pData ); - - return 0; - } - - // Next - ppReadMemList = &(*ppReadMemList)->mpNext; - } - - // Data not found, add ourself to list of waiters - if (AddToNotifyList( pDev, - clientID, - transactionID, - pCallback, - pData ) == false) - { - DBG( "Unable to register for notification\n" ); - } - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Success - return 0; -} - -/*=========================================================================== -METHOD: - UpSem (Public Method) - -DESCRIPTION: - Notification function for synchronous read - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - pData [ I ] - Buffer that holds semaphore to be up()-ed - -RETURN VALUE: - None -===========================================================================*/ -#define QUEC_SEM_MAGIC 0x12345678 -struct QuecSem { - struct semaphore readSem; - int magic; -}; - -static void UpSem( - sGobiUSBNet * pDev, - u16 clientID, - void * pData ) -{ - struct QuecSem *pSem = (struct QuecSem *)pData; - - VDBG( "0x%04X\n", clientID ); - - if (pSem->magic == QUEC_SEM_MAGIC) - up( &(pSem->readSem) ); - else - kfree(pSem); - return; -} - -/*=========================================================================== -METHOD: - ReadSync (Public Method) - -DESCRIPTION: - Start synchronous read - NOTE: Reading client's data store, not device - -PARAMETERS: - pDev [ I ] - Device specific memory - ppOutBuffer [I/O] - On success, will be filled with a - pointer to read buffer - clientID [ I ] - Requester's client ID - transactionID [ I ] - Transaction ID or 0 for any - -RETURN VALUE: - int - size of data read for success - negative errno for failure -===========================================================================*/ -static int ReadSync( - sGobiUSBNet * pDev, - void ** ppOutBuffer, - u16 clientID, - u16 transactionID ) -{ - int result; - sClientMemList * pClientMem; - sNotifyList ** ppNotifyList, * pDelNotifyListEntry; - struct QuecSem readSem; - void * pData; - unsigned long flags; - u16 dataSize; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return -ENXIO; - } - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Find memory storage for this Client ID - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find matching client ID 0x%04X\n", - clientID ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - return -ENXIO; - } - - // Note: in cases where read is interrupted, - // this will verify client is still valid - while (PopFromReadMemList( pDev, - clientID, - transactionID, - &pData, - &dataSize ) == false) - { - // Data does not yet exist, wait - sema_init( &readSem.readSem, 0 ); - readSem.magic = QUEC_SEM_MAGIC; - - // Add ourself to list of waiters - if (AddToNotifyList( pDev, - clientID, - transactionID, - UpSem, - &readSem ) == false) - { - DBG( "unable to register for notification\n" ); - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - return -EFAULT; - } - - // End critical section while we block - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Wait for notification - result = down_interruptible( &readSem.readSem ); - //if (result) INFO("down_interruptible = %d\n", result); - if (result == -EINTR) { - result = down_timeout(&readSem.readSem, msecs_to_jiffies(200)); - //if (result) INFO("down_timeout = %d\n", result); - } - if (result != 0) - { - DBG( "Down Timeout %d\n", result ); - - // readSem will fall out of scope, - // remove from notify list so it's not referenced - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - ppNotifyList = &(pClientMem->mpReadNotifyList); - pDelNotifyListEntry = NULL; - - // Find and delete matching entry - while (*ppNotifyList != NULL) - { - if ((*ppNotifyList)->mpData == &readSem) - { - pDelNotifyListEntry = *ppNotifyList; - *ppNotifyList = (*ppNotifyList)->mpNext; - kfree( pDelNotifyListEntry ); - break; - } - - // Next - ppNotifyList = &(*ppNotifyList)->mpNext; - } - - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - return -EINTR; - } - - // Verify device is still valid - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return -ENXIO; - } - - // Restart critical section and continue loop - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - } - - // End Critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Success - *ppOutBuffer = pData; - - return dataSize; -} - -/*=========================================================================== -METHOD: - WriteSyncCallback (Public Method) - -DESCRIPTION: - Write callback - -PARAMETERS - pWriteURB [ I ] - URB this callback is run for - -RETURN VALUE: - None -===========================================================================*/ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -static void WriteSyncCallback( struct urb * pWriteURB ) -#else -static void WriteSyncCallback(struct urb *pWriteURB, struct pt_regs *regs) -#endif -{ - if (pWriteURB == NULL) - { - DBG( "null urb\n" ); - return; - } - - DBG( "Write status/size %d/%d\n", - pWriteURB->status, - pWriteURB->actual_length ); - - // Notify that write has completed by up()-ing semeaphore - up( (struct semaphore * )pWriteURB->context ); - - return; -} - -/*=========================================================================== -METHOD: - WriteSync (Public Method) - -DESCRIPTION: - Start synchronous write - -PARAMETERS: - pDev [ I ] - Device specific memory - pWriteBuffer [ I ] - Data to be written - writeBufferSize [ I ] - Size of data to be written - clientID [ I ] - Client ID of requester - -RETURN VALUE: - int - write size (includes QMUX) - negative errno for failure -===========================================================================*/ -static int WriteSync( - sGobiUSBNet * pDev, - char * pWriteBuffer, - int writeBufferSize, - u16 clientID ) -{ - int result; - struct semaphore writeSem; - struct urb * pWriteURB; - sURBSetupPacket *writeSetup; - unsigned long flags; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return -ENXIO; - } - - pWriteURB = usb_alloc_urb( 0, GFP_KERNEL ); - if (pWriteURB == NULL) - { - DBG( "URB mem error\n" ); - return -ENOMEM; - } - - // Fill writeBuffer with QMUX - result = FillQMUX( clientID, pWriteBuffer, writeBufferSize ); - if (result < 0) - { - usb_free_urb( pWriteURB ); - return result; - } - - // CDC Send Encapsulated Request packet - writeSetup = kmalloc(sizeof(sURBSetupPacket), GFP_KERNEL); - writeSetup->mRequestType = 0x21; - writeSetup->mRequestCode = 0; - writeSetup->mValue = 0; - writeSetup->mIndex = cpu_to_le16(pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber); - writeSetup->mLength = cpu_to_le16(writeBufferSize); - - // Create URB - usb_fill_control_urb( pWriteURB, - pDev->mpNetDev->udev, - usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ), - (unsigned char *)writeSetup, - (void*)pWriteBuffer, - writeBufferSize, - NULL, - pDev ); - - DBG( "Actual Write:\n" ); - PrintHex( pWriteBuffer, writeBufferSize ); - - sema_init( &writeSem, 0 ); - - pWriteURB->complete = WriteSyncCallback; - pWriteURB->context = &writeSem; - - // Wake device - result = usb_autopm_get_interface( pDev->mpIntf ); - if (result < 0) - { - DBG( "unable to resume interface: %d\n", result ); - - // Likely caused by device going from autosuspend -> full suspend - if (result == -EPERM) - { -#ifdef CONFIG_PM -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 )) -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) - pDev->mpNetDev->udev->auto_pm = 0; -#endif -#endif - QuecGobiNetSuspend( pDev->mpIntf, PMSG_SUSPEND ); -#endif /* CONFIG_PM */ - } - usb_free_urb( pWriteURB ); - kfree(writeSetup); - - return result; - } - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - if (AddToURBList( pDev, clientID, pWriteURB ) == false) - { - usb_free_urb( pWriteURB ); - kfree(writeSetup); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - usb_autopm_put_interface( pDev->mpIntf ); - return -EINVAL; - } - - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - result = usb_submit_urb( pWriteURB, GFP_KERNEL ); - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - if (result < 0) - { - DBG( "submit URB error %d\n", result ); - - // Get URB back so we can destroy it - if (PopFromURBList( pDev, clientID ) != pWriteURB) - { - // This shouldn't happen - DBG( "Didn't get write URB back\n" ); - //advoid ReleaseClientID() free again (no PopFromURBList) - } - else - { - usb_free_urb( pWriteURB ); - kfree(writeSetup); - } - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - usb_autopm_put_interface( pDev->mpIntf ); - return result; - } - - // End critical section while we block - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Wait for write to finish - if (1 != 0) //(interruptible != 0) - { - // Allow user interrupts - result = down_interruptible( &writeSem ); - //if (result) INFO("down_interruptible = %d\n", result); - if (result == -EINTR) { - result = down_timeout(&writeSem, msecs_to_jiffies(200)); - //if (result) INFO("down_interruptible = %d\n", result); - } - } - else - { - // Ignore user interrupts - result = 0; - down( &writeSem ); - } - - // Write is done, release device - usb_autopm_put_interface( pDev->mpIntf ); - - // Verify device is still valid - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - - usb_kill_urb( pWriteURB ); -#if 0 //advoid ReleaseClientID() free again (no PopFromURBList) - usb_free_urb( pWriteURB ); - kfree(writeSetup); -#endif - return -ENXIO; - } - - // Restart critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Get URB back so we can destroy it - if (PopFromURBList( pDev, clientID ) != pWriteURB) - { - // This shouldn't happen - DBG( "Didn't get write URB back\n" ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - usb_kill_urb( pWriteURB ); -#if 0 //advoid ReleaseClientID() free again (fail PopFromURBList) - usb_free_urb( pWriteURB ); - kfree(writeSetup); -#endif - return -EINVAL; - } - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - if (result == 0) - { - // Write is finished - if (pWriteURB->status == 0) - { - // Return number of bytes that were supposed to have been written, - // not size of QMI request - result = writeBufferSize; - } - else - { - DBG( "bad status = %d\n", pWriteURB->status ); - - // Return error value - result = pWriteURB->status; - } - } - else - { - // We have been forcibly interrupted - DBG( "Interrupted %d !!!\n", result ); - DBG( "Device may be in bad state and need reset !!!\n" ); - - // URB has not finished - usb_kill_urb( pWriteURB ); - } - - usb_free_urb( pWriteURB ); - kfree(writeSetup); - - return result; -} - -/*=========================================================================*/ -// Internal memory management functions -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - GetClientID (Public Method) - -DESCRIPTION: - Request a QMI client for the input service type and initialize memory - structure - -PARAMETERS: - pDev [ I ] - Device specific memory - serviceType [ I ] - Desired QMI service type - -RETURN VALUE: - int - Client ID for success (positive) - Negative errno for error -===========================================================================*/ -static int GetClientID( - sGobiUSBNet * pDev, - u8 serviceType ) -{ - u16 clientID; - sClientMemList ** ppClientMem; - int result; - void * pWriteBuffer; - u16 writeBufferSize; - void * pReadBuffer; - u16 readBufferSize; - unsigned long flags; - u8 transactionID; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device!\n" ); - return -ENXIO; - } - - // Run QMI request to be asigned a Client ID - if (serviceType != 0) - { - writeBufferSize = QMICTLGetClientIDReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - transactionID = QMIXactionIDGet( pDev ); - - result = QMICTLGetClientIDReq( pWriteBuffer, - writeBufferSize, - transactionID, - serviceType ); - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - QMICTL ); - kfree( pWriteBuffer ); - - if (result < 0) - { - return result; - } - - result = ReadSync( pDev, - &pReadBuffer, - QMICTL, - transactionID ); - if (result < 0) - { - DBG( "bad read data %d\n", result ); - return result; - } - readBufferSize = result; - - result = QMICTLGetClientIDResp( pReadBuffer, - readBufferSize, - &clientID ); - - /* Upon return from QMICTLGetClientIDResp, clientID - * low address contains the Service Number (SN), and - * clientID high address contains Client Number (CN) - * For the ReadCallback to function correctly,we swap - * the SN and CN on a Big Endian architecture. - */ - clientID = le16_to_cpu(clientID); - - kfree( pReadBuffer ); - - if (result < 0) - { - return result; - } - } - else - { - // QMI CTL will always have client ID 0 - clientID = 0; - } - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Verify client is not already allocated - if (FindClientMem( pDev, clientID ) != NULL) - { - DBG( "Client memory already exists\n" ); - - // End Critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - return -ETOOMANYREFS; - } - - // Go to last entry in client mem list - ppClientMem = &pDev->mQMIDev.mpClientMemList; - while (*ppClientMem != NULL) - { - ppClientMem = &(*ppClientMem)->mpNext; - } - - // Create locations for read to place data into - *ppClientMem = kmalloc( sizeof( sClientMemList ), GFP_ATOMIC ); - if (*ppClientMem == NULL) - { - DBG( "Error allocating read list\n" ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - return -ENOMEM; - } - - (*ppClientMem)->mClientID = clientID; - (*ppClientMem)->mpList = NULL; - (*ppClientMem)->mpReadNotifyList = NULL; - (*ppClientMem)->mpURBList = NULL; - (*ppClientMem)->mpNext = NULL; - - // Initialize workqueue for poll() - init_waitqueue_head( &(*ppClientMem)->mWaitQueue ); - - // End Critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - return (int)( (*ppClientMem)->mClientID ); -} - -/*=========================================================================== -METHOD: - ReleaseClientID (Public Method) - -DESCRIPTION: - Release QMI client and free memory - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - -RETURN VALUE: - None -===========================================================================*/ -static void ReleaseClientID( - sGobiUSBNet * pDev, - u16 clientID ) -{ - int result; - sClientMemList ** ppDelClientMem; - sClientMemList * pNextClientMem; - struct urb * pDelURB; - void * pDelData; - u16 dataSize; - void * pWriteBuffer; - u16 writeBufferSize; - void * pReadBuffer; - u16 readBufferSize; - unsigned long flags; - u8 transactionID; - - // Is device is still valid? - if (IsDeviceValid( pDev ) == false) - { - DBG( "invalid device\n" ); - return; - } - - DBG( "releasing 0x%04X\n", clientID ); - - // Run QMI ReleaseClientID if this isn't QMICTL - if (clientID != QMICTL && pDev->mpNetDev->udev->state) - { - // Note: all errors are non fatal, as we always want to delete - // client memory in latter part of function - - writeBufferSize = QMICTLReleaseClientIDReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - DBG( "memory error\n" ); - } - else - { - transactionID = QMIXactionIDGet( pDev ); - - result = QMICTLReleaseClientIDReq( pWriteBuffer, - writeBufferSize, - transactionID, - clientID ); - if (result < 0) - { - kfree( pWriteBuffer ); - DBG( "error %d filling req buffer\n", result ); - } - else - { - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - QMICTL ); - kfree( pWriteBuffer ); - - if (result < 0) - { - DBG( "bad write status %d\n", result ); - } - else - { - result = ReadSync( pDev, - &pReadBuffer, - QMICTL, - transactionID ); - if (result < 0) - { - DBG( "bad read status %d\n", result ); - } - else - { - readBufferSize = result; - - result = QMICTLReleaseClientIDResp( pReadBuffer, - readBufferSize ); - kfree( pReadBuffer ); - - if (result < 0) - { - DBG( "error %d parsing response\n", result ); - } - } - } - } - } - } - - // Cleaning up client memory - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Can't use FindClientMem, I need to keep pointer of previous - ppDelClientMem = &pDev->mQMIDev.mpClientMemList; - while (*ppDelClientMem != NULL) - { - if ((*ppDelClientMem)->mClientID == clientID) - { - pNextClientMem = (*ppDelClientMem)->mpNext; - - // Notify all clients - while (NotifyAndPopNotifyList( pDev, - clientID, - 0 ) == true ); - - // Kill and free all URB's - pDelURB = PopFromURBList( pDev, clientID ); - while (pDelURB != NULL) - { - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - usb_kill_urb( pDelURB ); - usb_free_urb( pDelURB ); - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - pDelURB = PopFromURBList( pDev, clientID ); - } - - // Free any unread data - while (PopFromReadMemList( pDev, - clientID, - 0, - &pDelData, - &dataSize ) == true ) - { - kfree( pDelData ); - } - - // Delete client Mem - if (!waitqueue_active( &(*ppDelClientMem)->mWaitQueue)) - kfree( *ppDelClientMem ); - else - INFO("memory leak!\n"); - - // Overwrite the pointer that was to this client mem - *ppDelClientMem = pNextClientMem; - } - else - { - // I now point to (a pointer of ((the node I was at)'s mpNext)) - ppDelClientMem = &(*ppDelClientMem)->mpNext; - } - } - - // End Critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - return; -} - -/*=========================================================================== -METHOD: - FindClientMem (Public Method) - -DESCRIPTION: - Find this client's memory - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - -RETURN VALUE: - sClientMemList - Pointer to requested sClientMemList for success - NULL for error -===========================================================================*/ -static sClientMemList * FindClientMem( - sGobiUSBNet * pDev, - u16 clientID ) -{ - sClientMemList * pClientMem; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return NULL; - } - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - pClientMem = pDev->mQMIDev.mpClientMemList; - while (pClientMem != NULL) - { - if (pClientMem->mClientID == clientID) - { - // Success - VDBG("Found client's 0x%x memory\n", clientID); - return pClientMem; - } - - pClientMem = pClientMem->mpNext; - } - - DBG( "Could not find client mem 0x%04X\n", clientID ); - return NULL; -} - -/*=========================================================================== -METHOD: - AddToReadMemList (Public Method) - -DESCRIPTION: - Add Data to this client's ReadMem list - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - transactionID [ I ] - Transaction ID or 0 for any - pData [ I ] - Data to add - dataSize [ I ] - Size of data to add - -RETURN VALUE: - bool -===========================================================================*/ -static bool AddToReadMemList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void * pData, - u16 dataSize ) -{ - sClientMemList * pClientMem; - sReadMemList ** ppThisReadMemList; - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - // Get this client's memory location - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", - clientID ); - - return false; - } - - // Go to last ReadMemList entry - ppThisReadMemList = &pClientMem->mpList; - while (*ppThisReadMemList != NULL) - { - ppThisReadMemList = &(*ppThisReadMemList)->mpNext; - } - - *ppThisReadMemList = kmalloc( sizeof( sReadMemList ), GFP_ATOMIC ); - if (*ppThisReadMemList == NULL) - { - DBG( "Mem error\n" ); - - return false; - } - - (*ppThisReadMemList)->mpNext = NULL; - (*ppThisReadMemList)->mpData = pData; - (*ppThisReadMemList)->mDataSize = dataSize; - (*ppThisReadMemList)->mTransactionID = transactionID; - - return true; -} - -/*=========================================================================== -METHOD: - PopFromReadMemList (Public Method) - -DESCRIPTION: - Remove data from this client's ReadMem list if it matches - the specified transaction ID. - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - transactionID [ I ] - Transaction ID or 0 for any - ppData [I/O] - On success, will be filled with a - pointer to read buffer - pDataSize [I/O] - On succces, will be filled with the - read buffer's size - -RETURN VALUE: - bool -===========================================================================*/ -static bool PopFromReadMemList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void ** ppData, - u16 * pDataSize ) -{ - sClientMemList * pClientMem; - sReadMemList * pDelReadMemList, ** ppReadMemList; - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - // Get this client's memory location - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", - clientID ); - - return false; - } - - ppReadMemList = &(pClientMem->mpList); - pDelReadMemList = NULL; - - // Find first message that matches this transaction ID - while (*ppReadMemList != NULL) - { - // Do we care about transaction ID? - if (transactionID == 0 - || transactionID == (*ppReadMemList)->mTransactionID ) - { - pDelReadMemList = *ppReadMemList; - VDBG( "*ppReadMemList = 0x%p pDelReadMemList = 0x%p\n", - *ppReadMemList, pDelReadMemList ); - break; - } - - VDBG( "skipping 0x%04X data TID = %x\n", clientID, (*ppReadMemList)->mTransactionID ); - - // Next - ppReadMemList = &(*ppReadMemList)->mpNext; - } - VDBG( "*ppReadMemList = 0x%p pDelReadMemList = 0x%p\n", - *ppReadMemList, pDelReadMemList ); - if (pDelReadMemList != NULL) - { - *ppReadMemList = (*ppReadMemList)->mpNext; - - // Copy to output - *ppData = pDelReadMemList->mpData; - *pDataSize = pDelReadMemList->mDataSize; - VDBG( "*ppData = 0x%p pDataSize = %u\n", - *ppData, *pDataSize ); - - // Free memory - kfree( pDelReadMemList ); - - return true; - } - else - { - DBG( "No read memory to pop, Client 0x%04X, TID = %x\n", - clientID, - transactionID ); - return false; - } -} - -/*=========================================================================== -METHOD: - AddToNotifyList (Public Method) - -DESCRIPTION: - Add Notify entry to this client's notify List - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - transactionID [ I ] - Transaction ID or 0 for any - pNotifyFunct [ I ] - Callback function to be run when data is available - pData [ I ] - Data buffer that willl be passed (unmodified) - to callback - -RETURN VALUE: - bool -===========================================================================*/ -static bool AddToNotifyList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void (* pNotifyFunct)(sGobiUSBNet *, u16, void *), - void * pData ) -{ - sClientMemList * pClientMem; - sNotifyList ** ppThisNotifyList; - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - // Get this client's memory location - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", clientID ); - return false; - } - - // Go to last URBList entry - ppThisNotifyList = &pClientMem->mpReadNotifyList; - while (*ppThisNotifyList != NULL) - { - ppThisNotifyList = &(*ppThisNotifyList)->mpNext; - } - - *ppThisNotifyList = kmalloc( sizeof( sNotifyList ), GFP_ATOMIC ); - if (*ppThisNotifyList == NULL) - { - DBG( "Mem error\n" ); - return false; - } - - (*ppThisNotifyList)->mpNext = NULL; - (*ppThisNotifyList)->mpNotifyFunct = pNotifyFunct; - (*ppThisNotifyList)->mpData = pData; - (*ppThisNotifyList)->mTransactionID = transactionID; - - return true; -} - -/*=========================================================================== -METHOD: - NotifyAndPopNotifyList (Public Method) - -DESCRIPTION: - Remove first Notify entry from this client's notify list - and Run function - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - transactionID [ I ] - Transaction ID or 0 for any - -RETURN VALUE: - bool -===========================================================================*/ -static bool NotifyAndPopNotifyList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID ) -{ - sClientMemList * pClientMem; - sNotifyList * pDelNotifyList, ** ppNotifyList; - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - // Get this client's memory location - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", clientID ); - return false; - } - - ppNotifyList = &(pClientMem->mpReadNotifyList); - pDelNotifyList = NULL; - - // Remove from list - while (*ppNotifyList != NULL) - { - // Do we care about transaction ID? - if (transactionID == 0 - || (*ppNotifyList)->mTransactionID == 0 - || transactionID == (*ppNotifyList)->mTransactionID) - { - pDelNotifyList = *ppNotifyList; - break; - } - - DBG( "skipping data TID = %x\n", (*ppNotifyList)->mTransactionID ); - - // next - ppNotifyList = &(*ppNotifyList)->mpNext; - } - - if (pDelNotifyList != NULL) - { - // Remove element - *ppNotifyList = (*ppNotifyList)->mpNext; - - // Run notification function - if (pDelNotifyList->mpNotifyFunct != NULL) - { - // Unlock for callback - spin_unlock( &pDev->mQMIDev.mClientMemLock ); - - pDelNotifyList->mpNotifyFunct( pDev, - clientID, - pDelNotifyList->mpData ); - - // Restore lock - spin_lock( &pDev->mQMIDev.mClientMemLock ); - } - - // Delete memory - kfree( pDelNotifyList ); - - return true; - } - else - { - DBG( "no one to notify for TID %x\n", transactionID ); - - return false; - } -} - -/*=========================================================================== -METHOD: - AddToURBList (Public Method) - -DESCRIPTION: - Add URB to this client's URB list - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - pURB [ I ] - URB to be added - -RETURN VALUE: - bool -===========================================================================*/ -static bool AddToURBList( - sGobiUSBNet * pDev, - u16 clientID, - struct urb * pURB ) -{ - sClientMemList * pClientMem; - sURBList ** ppThisURBList; - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - // Get this client's memory location - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", clientID ); - return false; - } - - // Go to last URBList entry - ppThisURBList = &pClientMem->mpURBList; - while (*ppThisURBList != NULL) - { - ppThisURBList = &(*ppThisURBList)->mpNext; - } - - *ppThisURBList = kmalloc( sizeof( sURBList ), GFP_ATOMIC ); - if (*ppThisURBList == NULL) - { - DBG( "Mem error\n" ); - return false; - } - - (*ppThisURBList)->mpNext = NULL; - (*ppThisURBList)->mpURB = pURB; - - return true; -} - -/*=========================================================================== -METHOD: - PopFromURBList (Public Method) - -DESCRIPTION: - Remove URB from this client's URB list - - Caller MUST have lock on mClientMemLock - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Requester's client ID - -RETURN VALUE: - struct urb - Pointer to requested client's URB - NULL for error -===========================================================================*/ -static struct urb * PopFromURBList( - sGobiUSBNet * pDev, - u16 clientID ) -{ - sClientMemList * pClientMem; - sURBList * pDelURBList; - struct urb * pURB; - -#ifdef CONFIG_SMP - // Verify Lock - if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0) - { - DBG( "unlocked\n" ); - BUG(); - } -#endif - - // Get this client's memory location - pClientMem = FindClientMem( pDev, clientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", clientID ); - return NULL; - } - - // Remove from list - if (pClientMem->mpURBList != NULL) - { - pDelURBList = pClientMem->mpURBList; - pClientMem->mpURBList = pClientMem->mpURBList->mpNext; - - // Copy to output - pURB = pDelURBList->mpURB; - - // Delete memory - kfree( pDelURBList ); - - return pURB; - } - else - { - DBG( "No URB's to pop\n" ); - - return NULL; - } -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,19,0 )) -#ifndef f_dentry -#define f_dentry f_path.dentry -#endif -#endif - -/*=========================================================================*/ -// Internal userspace wrappers -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - UserspaceunlockedIOCTL (Public Method) - -DESCRIPTION: - Internal wrapper for Userspace IOCTL interface - -PARAMETERS - pFilp [ I ] - userspace file descriptor - cmd [ I ] - IOCTL command - arg [ I ] - IOCTL argument - -RETURN VALUE: - long - 0 for success - Negative errno for failure -===========================================================================*/ -static long UserspaceunlockedIOCTL( - struct file * pFilp, - unsigned int cmd, - unsigned long arg ) -{ - int result; - u32 devVIDPID; - - sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data; - - if (pFilpData == NULL) - { - DBG( "Bad file data\n" ); - return -EBADF; - } - - if (IsDeviceValid( pFilpData->mpDev ) == false) - { - DBG( "Invalid device! Updating f_ops\n" ); - pFilp->f_op = pFilp->f_dentry->d_inode->i_fop; - return -ENXIO; - } - - switch (cmd) - { - case IOCTL_QMI_GET_SERVICE_FILE: - DBG( "Setting up QMI for service %lu\n", arg ); - if ((u8)arg == 0) - { - DBG( "Cannot use QMICTL from userspace\n" ); - return -EINVAL; - } - - // Connection is already setup - if (pFilpData->mClientID != (u16)-1) - { - DBG( "Close the current connection before opening a new one\n" ); - return -EBADR; - } - - result = GetClientID( pFilpData->mpDev, (u8)arg ); -// it seems QMIWDA only allow one client, if the last quectel-CM donot realese it (killed by SIGKILL). -// can force release it at here -#if 1 - if (result < 0 && (u8)arg == QMIWDA) - { - ReleaseClientID( pFilpData->mpDev, QMIWDA | (1 << 8) ); - result = GetClientID( pFilpData->mpDev, (u8)arg ); - } -#endif - if (result < 0) - { - return result; - } - pFilpData->mClientID = (u16)result; - DBG("pFilpData->mClientID = 0x%x\n", pFilpData->mClientID ); - return 0; - break; - - - case IOCTL_QMI_GET_DEVICE_VIDPID: - if (arg == 0) - { - DBG( "Bad VIDPID buffer\n" ); - return -EINVAL; - } - - // Extra verification - if (pFilpData->mpDev->mpNetDev == 0) - { - DBG( "Bad mpNetDev\n" ); - return -ENOMEM; - } - if (pFilpData->mpDev->mpNetDev->udev == 0) - { - DBG( "Bad udev\n" ); - return -ENOMEM; - } - - devVIDPID = ((le16_to_cpu( pFilpData->mpDev->mpNetDev->udev->descriptor.idVendor ) << 16) - + le16_to_cpu( pFilpData->mpDev->mpNetDev->udev->descriptor.idProduct ) ); - - result = copy_to_user( (unsigned int *)arg, &devVIDPID, 4 ); - if (result != 0) - { - DBG( "Copy to userspace failure %d\n", result ); - } - - return result; - - break; - - case IOCTL_QMI_GET_DEVICE_MEID: - if (arg == 0) - { - DBG( "Bad MEID buffer\n" ); - return -EINVAL; - } - - result = copy_to_user( (unsigned int *)arg, &pFilpData->mpDev->mMEID[0], 14 ); - if (result != 0) - { - DBG( "Copy to userspace failure %d\n", result ); - } - - return result; - - break; - - default: - return -EBADRQC; - } -} - -/*=========================================================================*/ -// Userspace wrappers -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - UserspaceOpen (Public Method) - -DESCRIPTION: - Userspace open - IOCTL must be called before reads or writes - -PARAMETERS - pInode [ I ] - kernel file descriptor - pFilp [ I ] - userspace file descriptor - -RETURN VALUE: - int - 0 for success - Negative errno for failure -===========================================================================*/ -static int UserspaceOpen( - struct inode * pInode, - struct file * pFilp ) -{ - sQMIFilpStorage * pFilpData; - - // Optain device pointer from pInode - sQMIDev * pQMIDev = container_of( pInode->i_cdev, - sQMIDev, - mCdev ); - sGobiUSBNet * pDev = container_of( pQMIDev, - sGobiUSBNet, - mQMIDev ); - - if (pDev->mbMdm9x07) - { - atomic_inc(&pDev->refcount); - if (!pDev->mbQMIReady) { - if (wait_for_completion_interruptible_timeout(&pDev->mQMIReadyCompletion, 15*HZ) <= 0) { - if (atomic_dec_and_test(&pDev->refcount)) { - kfree( pDev ); - } - return -ETIMEDOUT; - } - } - atomic_dec(&pDev->refcount); - } - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return -ENXIO; - } - - // Setup data in pFilp->private_data - pFilp->private_data = kmalloc( sizeof( sQMIFilpStorage ), GFP_KERNEL ); - if (pFilp->private_data == NULL) - { - DBG( "Mem error\n" ); - return -ENOMEM; - } - - pFilpData = (sQMIFilpStorage *)pFilp->private_data; - pFilpData->mClientID = (u16)-1; - pFilpData->mpDev = pDev; - atomic_inc(&pFilpData->mpDev->refcount); - - return 0; -} - -/*=========================================================================== -METHOD: - UserspaceIOCTL (Public Method) - -DESCRIPTION: - Userspace IOCTL functions - -PARAMETERS - pUnusedInode [ I ] - (unused) kernel file descriptor - pFilp [ I ] - userspace file descriptor - cmd [ I ] - IOCTL command - arg [ I ] - IOCTL argument - -RETURN VALUE: - int - 0 for success - Negative errno for failure -===========================================================================*/ -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,36 )) -static int UserspaceIOCTL( - struct inode * pUnusedInode, - struct file * pFilp, - unsigned int cmd, - unsigned long arg ) -{ - // call the internal wrapper function - return (int)UserspaceunlockedIOCTL( pFilp, cmd, arg ); -} -#endif - -#ifdef quectel_no_for_each_process -static int UserspaceClose( - struct inode * pInode, - struct file * pFilp ) -{ - sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data; - - if (pFilpData == NULL) - { - DBG( "bad file data\n" ); - return -EBADF; - } - - atomic_dec(&pFilpData->mpDev->refcount); - - if (IsDeviceValid( pFilpData->mpDev ) == false) - { - return -ENXIO; - } - - DBG( "0x%04X\n", pFilpData->mClientID ); - - // Disable pFilpData so they can't keep sending read or write - // should this function hang - // Note: memory pointer is still saved in pFilpData to be deleted later - pFilp->private_data = NULL; - - if (pFilpData->mClientID != (u16)-1) - { - if (pFilpData->mpDev->mbDeregisterQMIDevice) - pFilpData->mClientID = (u16)-1; //DeregisterQMIDevice() will release this ClientID - else - ReleaseClientID( pFilpData->mpDev, - pFilpData->mClientID ); - } - - kfree( pFilpData ); - return 0; -} -#else -/*=========================================================================== -METHOD: - UserspaceClose (Public Method) - -DESCRIPTION: - Userspace close - Release client ID and free memory - -PARAMETERS - pFilp [ I ] - userspace file descriptor - unusedFileTable [ I ] - (unused) file table - -RETURN VALUE: - int - 0 for success - Negative errno for failure -===========================================================================*/ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 )) -int UserspaceClose( - struct file * pFilp, - fl_owner_t unusedFileTable ) -#else -int UserspaceClose( struct file * pFilp ) -#endif -{ - sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data; - struct task_struct * pEachTask; - struct fdtable * pFDT; - int count = 0; - int used = 0; - unsigned long flags; - - if (pFilpData == NULL) - { - DBG( "bad file data\n" ); - return -EBADF; - } - - // Fallthough. If f_count == 1 no need to do more checks -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,24 )) - if (atomic_read( &pFilp->f_count ) != 1) -#else - if (atomic_long_read( &pFilp->f_count ) != 1) -#endif - { - rcu_read_lock(); - for_each_process( pEachTask ) - { - task_lock(pEachTask); - if (pEachTask == NULL || pEachTask->files == NULL) - { - // Some tasks may not have files (e.g. Xsession) - task_unlock(pEachTask); - continue; - } - spin_lock_irqsave( &pEachTask->files->file_lock, flags ); - task_unlock(pEachTask); //kernel/exit.c:do_exit() -> fs/file.c:exit_files() - pFDT = files_fdtable( pEachTask->files ); - for (count = 0; count < pFDT->max_fds; count++) - { - // Before this function was called, this file was removed - // from our task's file table so if we find it in a file - // table then it is being used by another task - if (pFDT->fd[count] == pFilp) - { - used++; - break; - } - } - spin_unlock_irqrestore( &pEachTask->files->file_lock, flags ); - } - rcu_read_unlock(); - - if (used > 0) - { - DBG( "not closing, as this FD is open by %d other process\n", used ); - return 0; - } - } - - if (IsDeviceValid( pFilpData->mpDev ) == false) - { - DBG( "Invalid device! Updating f_ops\n" ); - pFilp->f_op = pFilp->f_dentry->d_inode->i_fop; - return -ENXIO; - } - - DBG( "0x%04X\n", pFilpData->mClientID ); - - // Disable pFilpData so they can't keep sending read or write - // should this function hang - // Note: memory pointer is still saved in pFilpData to be deleted later - pFilp->private_data = NULL; - - if (pFilpData->mClientID != (u16)-1) - { - if (pFilpData->mpDev->mbDeregisterQMIDevice) - pFilpData->mClientID = (u16)-1; //DeregisterQMIDevice() will release this ClientID - else - ReleaseClientID( pFilpData->mpDev, - pFilpData->mClientID ); - } - atomic_dec(&pFilpData->mpDev->refcount); - - kfree( pFilpData ); - return 0; -} -#endif - -/*=========================================================================== -METHOD: - UserspaceRead (Public Method) - -DESCRIPTION: - Userspace read (synchronous) - -PARAMETERS - pFilp [ I ] - userspace file descriptor - pBuf [ I ] - read buffer - size [ I ] - size of read buffer - pUnusedFpos [ I ] - (unused) file position - -RETURN VALUE: - ssize_t - Number of bytes read for success - Negative errno for failure -===========================================================================*/ -static ssize_t UserspaceRead( - struct file * pFilp, - char __user * pBuf, - size_t size, - loff_t * pUnusedFpos ) -{ - int result; - void * pReadData = NULL; - void * pSmallReadData; - sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data; - - if (pFilpData == NULL) - { - DBG( "Bad file data\n" ); - return -EBADF; - } - - if (IsDeviceValid( pFilpData->mpDev ) == false) - { - DBG( "Invalid device! Updating f_ops\n" ); - pFilp->f_op = pFilp->f_dentry->d_inode->i_fop; - return -ENXIO; - } - - if (pFilpData->mClientID == (u16)-1) - { - DBG( "Client ID must be set before reading 0x%04X\n", - pFilpData->mClientID ); - return -EBADR; - } - - // Perform synchronous read - result = ReadSync( pFilpData->mpDev, - &pReadData, - pFilpData->mClientID, - 0 ); - if (result <= 0) - { - return result; - } - - // Discard QMUX header - result -= QMUXHeaderSize(); - pSmallReadData = pReadData + QMUXHeaderSize(); - - if (result > size) - { - DBG( "Read data is too large for amount user has requested\n" ); - kfree( pReadData ); - return -EOVERFLOW; - } - - DBG( "pBuf = 0x%p pSmallReadData = 0x%p, result = %d", - pBuf, pSmallReadData, result ); - - if (copy_to_user( pBuf, pSmallReadData, result ) != 0) - { - DBG( "Error copying read data to user\n" ); - result = -EFAULT; - } - - // Reader is responsible for freeing read buffer - kfree( pReadData ); - - return result; -} - -/*=========================================================================== -METHOD: - UserspaceWrite (Public Method) - -DESCRIPTION: - Userspace write (synchronous) - -PARAMETERS - pFilp [ I ] - userspace file descriptor - pBuf [ I ] - write buffer - size [ I ] - size of write buffer - pUnusedFpos [ I ] - (unused) file position - -RETURN VALUE: - ssize_t - Number of bytes read for success - Negative errno for failure -===========================================================================*/ -static ssize_t UserspaceWrite( - struct file * pFilp, - const char __user * pBuf, - size_t size, - loff_t * pUnusedFpos ) -{ - int status; - void * pWriteBuffer; - sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data; - - if (pFilpData == NULL) - { - DBG( "Bad file data\n" ); - return -EBADF; - } - - if (IsDeviceValid( pFilpData->mpDev ) == false) - { - DBG( "Invalid device! Updating f_ops\n" ); - pFilp->f_op = pFilp->f_dentry->d_inode->i_fop; - return -ENXIO; - } - - if (pFilpData->mClientID == (u16)-1) - { - DBG( "Client ID must be set before writing 0x%04X\n", - pFilpData->mClientID ); - return -EBADR; - } - - // Copy data from user to kernel space - pWriteBuffer = kmalloc( size + QMUXHeaderSize(), GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - status = copy_from_user( pWriteBuffer + QMUXHeaderSize(), pBuf, size ); - if (status != 0) - { - DBG( "Unable to copy data from userspace %d\n", status ); - kfree( pWriteBuffer ); - return status; - } - - status = WriteSync( pFilpData->mpDev, - pWriteBuffer, - size + QMUXHeaderSize(), - pFilpData->mClientID ); - - kfree( pWriteBuffer ); - - // On success, return requested size, not full QMI reqest size - if (status == size + QMUXHeaderSize()) - { - return size; - } - else - { - return status; - } -} - -/*=========================================================================== -METHOD: - UserspacePoll (Public Method) - -DESCRIPTION: - Used to determine if read/write operations are possible without blocking - -PARAMETERS - pFilp [ I ] - userspace file descriptor - pPollTable [I/O] - Wait object to notify the kernel when data - is ready - -RETURN VALUE: - unsigned int - bitmask of what operations can be done immediately -===========================================================================*/ -static unsigned int UserspacePoll( - struct file * pFilp, - struct poll_table_struct * pPollTable ) -{ - sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data; - sClientMemList * pClientMem; - unsigned long flags; - - // Always ready to write - unsigned long status = POLLOUT | POLLWRNORM; - - if (pFilpData == NULL) - { - DBG( "Bad file data\n" ); - return POLLERR; - } - - if (IsDeviceValid( pFilpData->mpDev ) == false) - { - DBG( "Invalid device! Updating f_ops\n" ); - pFilp->f_op = pFilp->f_dentry->d_inode->i_fop; - return POLLERR; - } - - if (pFilpData->mpDev->mbDeregisterQMIDevice) - { - DBG( "DeregisterQMIDevice ing\n" ); - return POLLHUP | POLLERR; - } - - if (pFilpData->mClientID == (u16)-1) - { - DBG( "Client ID must be set before polling 0x%04X\n", - pFilpData->mClientID ); - return POLLERR; - } - - // Critical section - spin_lock_irqsave( &pFilpData->mpDev->mQMIDev.mClientMemLock, flags ); - - // Get this client's memory location - pClientMem = FindClientMem( pFilpData->mpDev, - pFilpData->mClientID ); - if (pClientMem == NULL) - { - DBG( "Could not find this client's memory 0x%04X\n", - pFilpData->mClientID ); - - spin_unlock_irqrestore( &pFilpData->mpDev->mQMIDev.mClientMemLock, - flags ); - return POLLERR; - } - - poll_wait( pFilp, &pClientMem->mWaitQueue, pPollTable ); - - if (pClientMem->mpList != NULL) - { - status |= POLLIN | POLLRDNORM; - } - - // End critical section - spin_unlock_irqrestore( &pFilpData->mpDev->mQMIDev.mClientMemLock, flags ); - - // Always ready to write - return (status | POLLOUT | POLLWRNORM); -} - -/*=========================================================================*/ -// Initializer and destructor -/*=========================================================================*/ -static int QMICTLSyncProc(sGobiUSBNet *pDev) -{ - void *pWriteBuffer; - void *pReadBuffer; - int result; - u16 writeBufferSize; - u16 readBufferSize; - u8 transactionID; - unsigned long flags; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return -EFAULT; - } - - writeBufferSize= QMICTLSyncReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - transactionID = QMIXactionIDGet(pDev); - - /* send a QMI_CTL_SYNC_REQ (0x0027) */ - result = QMICTLSyncReq( pWriteBuffer, - writeBufferSize, - transactionID ); - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - QMICTL ); - - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - // QMI CTL Sync Response - result = ReadSync( pDev, - &pReadBuffer, - QMICTL, - transactionID ); - if (result < 0) - { - return result; - } - - result = QMICTLSyncResp( pReadBuffer, - (u16)result ); - - kfree( pReadBuffer ); - - if (result < 0) /* need to re-sync */ - { - DBG( "sync response error code %d\n", result ); - /* start timer and wait for the response */ - /* process response */ - return result; - } - -#if 1 //free these ununsed qmi response, or when these transactionID re-used, they will be regarded as qmi response of the qmi request that have same transactionID - // Enter critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Free any unread data - while (PopFromReadMemList( pDev, QMICTL, 0, &pReadBuffer, &readBufferSize) == true) { - kfree( pReadBuffer ); - } - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); -#endif - - // Success - return 0; -} - -static int qmi_sync_thread(void *data) { - sGobiUSBNet * pDev = (sGobiUSBNet *)data; - int result = 0; - -#if 1 - // Device is not ready for QMI connections right away - // Wait up to 30 seconds before failing - if (QMIReady( pDev, 30000 ) == false) - { - DBG( "Device unresponsive to QMI\n" ); - goto __qmi_sync_finished; - } - - // Initiate QMI CTL Sync Procedure - DBG( "Sending QMI CTL Sync Request\n" ); - result = QMICTLSyncProc(pDev); - if (result != 0) - { - DBG( "QMI CTL Sync Procedure Error\n" ); - goto __qmi_sync_finished; - } - else - { - DBG( "QMI CTL Sync Procedure Successful\n" ); - } - -#if defined(QUECTEL_WWAN_QMAP) -if (pDev->qmap_mode) { - // Setup Data Format - result = QMIWDASetDataFormat (pDev, pDev->qmap_mode, &pDev->qmap_size); - if (result != 0) - { - goto __qmi_sync_finished; - } - pDev->mpNetDev->rx_urb_size = pDev->qmap_size; -} -#endif - - // Setup WDS callback - result = SetupQMIWDSCallback( pDev ); - if (result != 0) - { - goto __qmi_sync_finished; - } - - // Fill MEID for device - result = QMIDMSGetMEID( pDev ); - if (result != 0) - { - goto __qmi_sync_finished; - } -#endif - -__qmi_sync_finished: - pDev->mbQMIReady = true; - complete_all(&pDev->mQMIReadyCompletion); - pDev->mbQMISyncIng = false; - if (atomic_dec_and_test(&pDev->refcount)) { - kfree( pDev ); - } - return result; -} - -/*=========================================================================== -METHOD: - RegisterQMIDevice (Public Method) - -DESCRIPTION: - QMI Device initialization function - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - int - 0 for success - Negative errno for failure -===========================================================================*/ -int RegisterQMIDevice( sGobiUSBNet * pDev ) -{ - int result; - int GobiQMIIndex = 0; - dev_t devno; - char * pDevName; - - if (pDev->mQMIDev.mbCdevIsInitialized == true) - { - // Should never happen, but always better to check - DBG( "device already exists\n" ); - return -EEXIST; - } - - pDev->mbQMIValid = true; - pDev->mbDeregisterQMIDevice = false; - - // Set up for QMICTL - // (does not send QMI message, just sets up memory) - result = GetClientID( pDev, QMICTL ); - if (result != 0) - { - pDev->mbQMIValid = false; - return result; - } - atomic_set( &pDev->mQMIDev.mQMICTLTransactionID, 1 ); - - // Start Async reading - result = StartRead( pDev ); - if (result != 0) - { - pDev->mbQMIValid = false; - return result; - } - - if (pDev->mbMdm9x07) - { - usb_control_msg( pDev->mpNetDev->udev, - usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ), - SET_CONTROL_LINE_STATE_REQUEST, - SET_CONTROL_LINE_STATE_REQUEST_TYPE, - CONTROL_DTR, - /* USB interface number to receive control message */ - pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber, - NULL, - 0, - 100 ); - } - - //for EC21&25, must wait about 15 seconds to wait QMI ready. it is too long for driver probe(will block other drivers probe). - if (pDev->mbMdm9x07) - { - struct task_struct *qmi_sync_task; - atomic_inc(&pDev->refcount); - init_completion(&pDev->mQMIReadyCompletion); - pDev->mbQMIReady = false; - pDev->mbQMISyncIng = true; - qmi_sync_task = kthread_run(qmi_sync_thread, (void *)pDev, "qmi_sync/%d", pDev->mpNetDev->udev->devnum); - if (IS_ERR(qmi_sync_task)) { - pDev->mbQMISyncIng = false; - atomic_dec(&pDev->refcount); - DBG( "Create qmi_sync_thread fail\n" ); - return PTR_ERR(qmi_sync_task); - } - goto __register_chardev_qccmi; - } - - // Device is not ready for QMI connections right away - // Wait up to 30 seconds before failing - if (QMIReady( pDev, 30000 ) == false) - { - DBG( "Device unresponsive to QMI\n" ); - return -ETIMEDOUT; - } - - // Initiate QMI CTL Sync Procedure - DBG( "Sending QMI CTL Sync Request\n" ); - result = QMICTLSyncProc(pDev); - if (result != 0) - { - DBG( "QMI CTL Sync Procedure Error\n" ); - return result; - } - else - { - DBG( "QMI CTL Sync Procedure Successful\n" ); - } - - // Setup Data Format -#if defined(QUECTEL_WWAN_QMAP) - result = QMIWDASetDataFormat (pDev, pDev->qmap_mode, NULL); -#else - result = QMIWDASetDataFormat (pDev, 0, NULL); -#endif - if (result != 0) - { - return result; - } - - // Setup WDS callback - result = SetupQMIWDSCallback( pDev ); - if (result != 0) - { - return result; - } - - // Fill MEID for device - result = QMIDMSGetMEID( pDev ); - if (result != 0) - { - return result; - } - -__register_chardev_qccmi: - // allocate and fill devno with numbers - result = alloc_chrdev_region( &devno, 0, 1, "qcqmi" ); - if (result < 0) - { - return result; - } - - // Create cdev - cdev_init( &pDev->mQMIDev.mCdev, &UserspaceQMIFops ); - pDev->mQMIDev.mCdev.owner = THIS_MODULE; - pDev->mQMIDev.mCdev.ops = &UserspaceQMIFops; - pDev->mQMIDev.mbCdevIsInitialized = true; - - result = cdev_add( &pDev->mQMIDev.mCdev, devno, 1 ); - if (result != 0) - { - DBG( "error adding cdev\n" ); - return result; - } - - // Match interface number (usb# or eth#) - if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "eth" ))) { - pDevName += strlen( "eth" ); - } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "usb" ))) { - pDevName += strlen( "usb" ); -#if 1 //openWRT like use ppp# or lte# - } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "ppp" ))) { - pDevName += strlen( "ppp" ); - } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "lte" ))) { - pDevName += strlen( "lte" ); -#endif - } else { - DBG( "Bad net name: %s\n", pDev->mpNetDev->net->name ); - return -ENXIO; - } - GobiQMIIndex = simple_strtoul( pDevName, NULL, 10 ); - if (GobiQMIIndex < 0) - { - DBG( "Bad minor number\n" ); - return -ENXIO; - } - - // Always print this output - printk( KERN_INFO "creating qcqmi%d\n", - GobiQMIIndex ); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,27 )) - // kernel 2.6.27 added a new fourth parameter to device_create - // void * drvdata : the data to be added to the device for callbacks - device_create( pDev->mQMIDev.mpDevClass, - &pDev->mpIntf->dev, - devno, - NULL, - "qcqmi%d", - GobiQMIIndex ); -#else - device_create( pDev->mQMIDev.mpDevClass, - &pDev->mpIntf->dev, - devno, - "qcqmi%d", - GobiQMIIndex ); -#endif - - pDev->mQMIDev.mDevNum = devno; - - // Success - return 0; -} - -/*=========================================================================== -METHOD: - DeregisterQMIDevice (Public Method) - -DESCRIPTION: - QMI Device cleanup function - - NOTE: When this function is run the device is no longer valid - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - None -===========================================================================*/ -void DeregisterQMIDevice( sGobiUSBNet * pDev ) -{ -#ifndef quectel_no_for_each_process - struct inode * pOpenInode; - struct list_head * pInodeList; - struct task_struct * pEachTask; - struct fdtable * pFDT; - struct file * pFilp; - int count = 0; -#endif - unsigned long flags; - int tries; - int result; - - // Should never happen, but check anyway - if (IsDeviceValid( pDev ) == false) - { - DBG( "wrong device\n" ); - return; - } - - pDev->mbDeregisterQMIDevice = true; - - for (tries = 0; tries < 3000; tries += 10) { - if (pDev->mbQMISyncIng == false) - break; - msleep(10); - } - - if (pDev->mbQMISyncIng) { - DBG( "QMI sync ing\n" ); - } - - // Release all clients - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - while (pDev->mQMIDev.mpClientMemList != NULL) - { - u16 mClientID = pDev->mQMIDev.mpClientMemList->mClientID; - if (waitqueue_active(&pDev->mQMIDev.mpClientMemList->mWaitQueue)) { - DBG("WaitQueue 0x%04X\n", mClientID); - wake_up_interruptible_sync( &pDev->mQMIDev.mpClientMemList->mWaitQueue ); - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - msleep(10); - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - continue; - } - - DBG( "release 0x%04X\n", pDev->mQMIDev.mpClientMemList->mClientID ); - - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - ReleaseClientID( pDev, mClientID ); - // NOTE: pDev->mQMIDev.mpClientMemList will - // be updated in ReleaseClientID() - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - } - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // Stop all reads - KillRead( pDev ); - - pDev->mbQMIValid = false; - - if (pDev->mQMIDev.mbCdevIsInitialized == false) - { - return; - } - -#ifndef quectel_no_for_each_process - // Find each open file handle, and manually close it - - // Generally there will only be only one inode, but more are possible - list_for_each( pInodeList, &pDev->mQMIDev.mCdev.list ) - { - // Get the inode - pOpenInode = container_of( pInodeList, struct inode, i_devices ); - if (pOpenInode != NULL && (IS_ERR( pOpenInode ) == false)) - { - // Look for this inode in each task - - rcu_read_lock(); - for_each_process( pEachTask ) - { - task_lock(pEachTask); - if (pEachTask == NULL || pEachTask->files == NULL) - { - // Some tasks may not have files (e.g. Xsession) - task_unlock(pEachTask); - continue; - } - // For each file this task has open, check if it's referencing - // our inode. - spin_lock_irqsave( &pEachTask->files->file_lock, flags ); - task_unlock(pEachTask); //kernel/exit.c:do_exit() -> fs/file.c:exit_files() - pFDT = files_fdtable( pEachTask->files ); - for (count = 0; count < pFDT->max_fds; count++) - { - pFilp = pFDT->fd[count]; - if (pFilp != NULL && pFilp->f_dentry != NULL) - { - if (pFilp->f_dentry->d_inode == pOpenInode) - { - // Close this file handle - rcu_assign_pointer( pFDT->fd[count], NULL ); - spin_unlock_irqrestore( &pEachTask->files->file_lock, flags ); - - DBG( "forcing close of open file handle\n" ); - filp_close( pFilp, pEachTask->files ); - - spin_lock_irqsave( &pEachTask->files->file_lock, flags ); - } - } - } - spin_unlock_irqrestore( &pEachTask->files->file_lock, flags ); - } - rcu_read_unlock(); - } - } -#endif - -if (pDev->mpNetDev->udev->state) { - // Send SetControlLineState request (USB_CDC) - result = usb_control_msg( pDev->mpNetDev->udev, - usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ), - SET_CONTROL_LINE_STATE_REQUEST, - SET_CONTROL_LINE_STATE_REQUEST_TYPE, - 0, // DTR not present - /* USB interface number to receive control message */ - pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber, - NULL, - 0, - 100 ); - if (result < 0) - { - DBG( "Bad SetControlLineState status %d\n", result ); - } -} - - // Remove device (so no more calls can be made by users) - if (IS_ERR( pDev->mQMIDev.mpDevClass ) == false) - { - device_destroy( pDev->mQMIDev.mpDevClass, - pDev->mQMIDev.mDevNum ); - } - - // Hold onto cdev memory location until everyone is through using it. - // Timeout after 30 seconds (10 ms interval). Timeout should never happen, - // but exists to prevent an infinate loop just in case. - for (tries = 0; tries < 30 * 100; tries++) - { -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,11,0 )) - int ref = atomic_read( &pDev->mQMIDev.mCdev.kobj.kref.refcount ); -#else - int ref = kref_read( &pDev->mQMIDev.mCdev.kobj.kref ); -#endif - if (ref > 1) - { - DBG( "cdev in use by %d tasks\n", ref - 1 ); - if (tries > 10) - INFO( "cdev in use by %d tasks\n", ref - 1 ); - msleep( 10 ); - } - else - { - break; - } - } - - cdev_del( &pDev->mQMIDev.mCdev ); - - unregister_chrdev_region( pDev->mQMIDev.mDevNum, 1 ); - - return; -} - -/*=========================================================================*/ -// Driver level client management -/*=========================================================================*/ - -/*=========================================================================== -METHOD: - QMIReady (Public Method) - -DESCRIPTION: - Send QMI CTL GET VERSION INFO REQ and SET DATA FORMAT REQ - Wait for response or timeout - -PARAMETERS: - pDev [ I ] - Device specific memory - timeout [ I ] - Milliseconds to wait for response - -RETURN VALUE: - bool -===========================================================================*/ -static bool QMIReady( - sGobiUSBNet * pDev, - u16 timeout ) -{ - int result; - void * pWriteBuffer; - u16 writeBufferSize; - void * pReadBuffer; - u16 readBufferSize; - u16 curTime; - unsigned long flags; - u8 transactionID; - u16 interval = 2000; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return false; - } - - writeBufferSize = QMICTLReadyReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return false; - } - - // An implimentation of down_timeout has not been agreed on, - // so it's been added and removed from the kernel several times. - // We're just going to ignore it and poll the semaphore. - - // Send a write every 1000 ms and see if we get a response - for (curTime = 0; curTime < timeout; curTime += interval) - { - // Start read - struct QuecSem *readSem = kmalloc(sizeof(struct QuecSem ), GFP_KERNEL); - readSem->magic = QUEC_SEM_MAGIC; - sema_init( &readSem->readSem, 0 ); - - transactionID = QMIXactionIDGet( pDev ); - - result = ReadAsync( pDev, QMICTL, transactionID, UpSem, readSem ); - if (result != 0) - { - kfree( pWriteBuffer ); - return false; - } - - // Fill buffer - result = QMICTLReadyReq( pWriteBuffer, - writeBufferSize, - transactionID ); - if (result < 0) - { - kfree( pWriteBuffer ); - return false; - } - - // Disregard status. On errors, just try again - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - QMICTL ); - - if (result < 0) //maybe caused by usb disconnect - { - kfree( pWriteBuffer ); - return false; - } - -#if 1 - if (down_timeout( &readSem->readSem, msecs_to_jiffies(interval) ) == 0) -#else - msleep( interval ); - if (down_trylock( &readSem->readSem ) == 0) -#endif - { - kfree(readSem); - // Enter critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Pop the read data - if (PopFromReadMemList( pDev, - QMICTL, - transactionID, - &pReadBuffer, - &readBufferSize ) == true) - { - // Success - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - // We don't care about the result - kfree( pReadBuffer ); - - break; - } - else - { - // Read mismatch/failure, unlock and continue - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - } - } - else - { - readSem->magic = 0; - // Enter critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - // Timeout, remove the async read - NotifyAndPopNotifyList( pDev, QMICTL, transactionID ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - } - - if (pDev->mbDeregisterQMIDevice) - { - kfree( pWriteBuffer ); - return false; - } - } - - kfree( pWriteBuffer ); - - // Did we time out? - if (curTime >= timeout) - { - return false; - } - - DBG( "QMI Ready after %u milliseconds\n", curTime ); - - // Success - return true; -} - -/*=========================================================================== -METHOD: - QMIWDSCallback (Public Method) - -DESCRIPTION: - QMI WDS callback function - Update net stats or link state - -PARAMETERS: - pDev [ I ] - Device specific memory - clientID [ I ] - Client ID - pData [ I ] - Callback data (unused) - -RETURN VALUE: - None -===========================================================================*/ -static void QMIWDSCallback( - sGobiUSBNet * pDev, - u16 clientID, - void * pData ) -{ - bool bRet; - int result; - void * pReadBuffer; - u16 readBufferSize; - -#if 0 -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 )) - struct net_device_stats * pStats = &(pDev->mpNetDev->stats); -#else - struct net_device_stats * pStats = &(pDev->mpNetDev->net->stats); -#endif -#endif - - u32 TXOk = (u32)-1; - u32 RXOk = (u32)-1; - u32 TXErr = (u32)-1; - u32 RXErr = (u32)-1; - u32 TXOfl = (u32)-1; - u32 RXOfl = (u32)-1; - u64 TXBytesOk = (u64)-1; - u64 RXBytesOk = (u64)-1; - bool bLinkState; - bool bReconfigure; - unsigned long flags; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return; - } - - // Critical section - spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags ); - - bRet = PopFromReadMemList( pDev, - clientID, - 0, - &pReadBuffer, - &readBufferSize ); - - // End critical section - spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags ); - - if (bRet == false) - { - DBG( "WDS callback failed to get data\n" ); - return; - } - - // Default values - bLinkState = ! GobiTestDownReason( pDev, NO_NDIS_CONNECTION ); - bReconfigure = false; - - result = QMIWDSEventResp( pReadBuffer, - readBufferSize, - &TXOk, - &RXOk, - &TXErr, - &RXErr, - &TXOfl, - &RXOfl, - &TXBytesOk, - &RXBytesOk, - &bLinkState, - &bReconfigure ); - if (result < 0) - { - DBG( "bad WDS packet\n" ); - } - else - { -#if 0 //usbbet.c will do this job - // Fill in new values, ignore max values - if (TXOfl != (u32)-1) - { - pStats->tx_fifo_errors = TXOfl; - } - - if (RXOfl != (u32)-1) - { - pStats->rx_fifo_errors = RXOfl; - } - - if (TXErr != (u32)-1) - { - pStats->tx_errors = TXErr; - } - - if (RXErr != (u32)-1) - { - pStats->rx_errors = RXErr; - } - - if (TXOk != (u32)-1) - { - pStats->tx_packets = TXOk + pStats->tx_errors; - } - - if (RXOk != (u32)-1) - { - pStats->rx_packets = RXOk + pStats->rx_errors; - } - - if (TXBytesOk != (u64)-1) - { - pStats->tx_bytes = TXBytesOk; - } - - if (RXBytesOk != (u64)-1) - { - pStats->rx_bytes = RXBytesOk; - } -#endif - - if (bReconfigure == true) - { - DBG( "Net device link reset\n" ); - GobiSetDownReason( pDev, NO_NDIS_CONNECTION ); - GobiClearDownReason( pDev, NO_NDIS_CONNECTION ); - } - else - { - if (bLinkState == true) - { - if (GobiTestDownReason( pDev, NO_NDIS_CONNECTION )) { - DBG( "Net device link is connected\n" ); - GobiClearDownReason( pDev, NO_NDIS_CONNECTION ); - } - } - else - { - if (!GobiTestDownReason( pDev, NO_NDIS_CONNECTION )) { - DBG( "Net device link is disconnected\n" ); - GobiSetDownReason( pDev, NO_NDIS_CONNECTION ); - } - } - } - } - - kfree( pReadBuffer ); - - // Setup next read - result = ReadAsync( pDev, - clientID, - 0, - QMIWDSCallback, - pData ); - if (result != 0) - { - DBG( "unable to setup next async read\n" ); - } - - return; -} - -/*=========================================================================== -METHOD: - SetupQMIWDSCallback (Public Method) - -DESCRIPTION: - Request client and fire off reqests and start async read for - QMI WDS callback - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - int - 0 for success - Negative errno for failure -===========================================================================*/ -static int SetupQMIWDSCallback( sGobiUSBNet * pDev ) -{ - int result; - void * pWriteBuffer; - u16 writeBufferSize; - u16 WDSClientID; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return -EFAULT; - } - - result = GetClientID( pDev, QMIWDS ); - if (result < 0) - { - return result; - } - WDSClientID = result; - -#if 0 // add for "AT$QCRMCALL=1,1", be careful: donot enable these codes if use quectel-CM, or cannot obtain IP by udhcpc - if (pDev->mbMdm9x07) - { - void * pReadBuffer; - u16 readBufferSize; - - writeBufferSize = QMIWDSSetQMUXBindMuxDataPortSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - result = QMIWDSSetQMUXBindMuxDataPortReq( pWriteBuffer, - writeBufferSize, - 0x81, - 3 ); - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - WDSClientID ); - kfree( pWriteBuffer ); - - if (result < 0) - { - return result; - } - - result = ReadSync( pDev, - &pReadBuffer, - WDSClientID, - 3 ); - if (result < 0) - { - return result; - } - readBufferSize = result; - - kfree( pReadBuffer ); - } -#endif - - // QMI WDS Set Event Report - writeBufferSize = QMIWDSSetEventReportReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - result = QMIWDSSetEventReportReq( pWriteBuffer, - writeBufferSize, - 1 ); - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - WDSClientID ); - kfree( pWriteBuffer ); - - if (result < 0) - { - return result; - } - - // QMI WDS Get PKG SRVC Status - writeBufferSize = QMIWDSGetPKGSRVCStatusReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - result = QMIWDSGetPKGSRVCStatusReq( pWriteBuffer, - writeBufferSize, - 2 ); - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - WDSClientID ); - kfree( pWriteBuffer ); - - if (result < 0) - { - return result; - } - - // Setup asnyc read callback - result = ReadAsync( pDev, - WDSClientID, - 0, - QMIWDSCallback, - NULL ); - if (result != 0) - { - DBG( "unable to setup async read\n" ); - return result; - } - - // Send SetControlLineState request (USB_CDC) - // Required for Autoconnect - result = usb_control_msg( pDev->mpNetDev->udev, - usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ), - SET_CONTROL_LINE_STATE_REQUEST, - SET_CONTROL_LINE_STATE_REQUEST_TYPE, - CONTROL_DTR, - /* USB interface number to receive control message */ - pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber, - NULL, - 0, - 100 ); - if (result < 0) - { - DBG( "Bad SetControlLineState status %d\n", result ); - return result; - } - - return 0; -} - -/*=========================================================================== -METHOD: - QMIDMSGetMEID (Public Method) - -DESCRIPTION: - Register DMS client - send MEID req and parse response - Release DMS client - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - None -===========================================================================*/ -static int QMIDMSGetMEID( sGobiUSBNet * pDev ) -{ - int result; - void * pWriteBuffer; - u16 writeBufferSize; - void * pReadBuffer; - u16 readBufferSize; - u16 DMSClientID; - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return -EFAULT; - } - - result = GetClientID( pDev, QMIDMS ); - if (result < 0) - { - return result; - } - DMSClientID = result; - - // QMI DMS Get Serial numbers Req - writeBufferSize = QMIDMSGetMEIDReqSize(); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - result = QMIDMSGetMEIDReq( pWriteBuffer, - writeBufferSize, - 1 ); - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - DMSClientID ); - kfree( pWriteBuffer ); - - if (result < 0) - { - return result; - } - - // QMI DMS Get Serial numbers Resp - result = ReadSync( pDev, - &pReadBuffer, - DMSClientID, - 1 ); - if (result < 0) - { - return result; - } - readBufferSize = result; - - result = QMIDMSGetMEIDResp( pReadBuffer, - readBufferSize, - &pDev->mMEID[0], - 14 ); - kfree( pReadBuffer ); - - if (result < 0) - { - DBG( "bad get MEID resp\n" ); - - // Non fatal error, device did not return any MEID - // Fill with 0's - memset( &pDev->mMEID[0], '0', 14 ); - } - - ReleaseClientID( pDev, DMSClientID ); - - // Success - return 0; -} - -/*=========================================================================== -METHOD: - QMIWDASetDataFormat (Public Method) - -DESCRIPTION: - Register WDA client - send Data format request and parse response - Release WDA client - -PARAMETERS: - pDev [ I ] - Device specific memory - -RETURN VALUE: - None -===========================================================================*/ -static int QMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ) -{ - int result; - void * pWriteBuffer; - u16 writeBufferSize; - void * pReadBuffer; - u16 readBufferSize; - u16 WDAClientID; - - DBG("\n"); - - if (IsDeviceValid( pDev ) == false) - { - DBG( "Invalid device\n" ); - return -EFAULT; - } - - result = GetClientID( pDev, QMIWDA ); - if (result < 0) - { - return result; - } - WDAClientID = result; - - // QMI WDA Set Data Format Request - writeBufferSize = QMIWDASetDataFormatReqSize(qmap_mode); - pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL ); - if (pWriteBuffer == NULL) - { - return -ENOMEM; - } - - result = QMIWDASetDataFormatReq( pWriteBuffer, - writeBufferSize, pDev->mbRawIPMode, - qmap_mode ? pDev->qmap_version : 0, (31*1024), - 1 ); - - if (result < 0) - { - kfree( pWriteBuffer ); - return result; - } - - result = WriteSync( pDev, - pWriteBuffer, - writeBufferSize, - WDAClientID ); - kfree( pWriteBuffer ); - - if (result < 0) - { - return result; - } - - // QMI DMS Get Serial numbers Resp - result = ReadSync( pDev, - &pReadBuffer, - WDAClientID, - 1 ); - if (result < 0) - { - return result; - } - readBufferSize = result; - -if (qmap_mode && rx_urb_size) { - int qmap_version = 0, rx_size = 0, tx_size = 0; - result = QMIWDASetDataFormatResp( pReadBuffer, - readBufferSize, pDev->mbRawIPMode, &qmap_version, &rx_size, &tx_size, &pDev->qmap_settings); - INFO( "qmap settings qmap_version=%d, rx_size=%d, tx_size=%d\n", - le32_to_cpu(qmap_version), le32_to_cpu(rx_size), le32_to_cpu(tx_size)); - - if (le32_to_cpu(qmap_version)) { -#if defined(QUECTEL_UL_DATA_AGG) - struct ul_agg_ctx *ctx = &pDev->agg_ctx; - - if (le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_datagrams) > 1) { - ctx->ul_data_aggregation_max_size = le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_size); - ctx->ul_data_aggregation_max_datagrams = le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_datagrams); - ctx->dl_minimum_padding = le32_to_cpu(pDev->qmap_settings.dl_minimum_padding); - } - INFO( "qmap settings ul_data_aggregation_max_size=%d, ul_data_aggregation_max_datagrams=%d\n", - ctx->ul_data_aggregation_max_size, ctx->ul_data_aggregation_max_datagrams); - if (ctx->ul_data_aggregation_max_datagrams > 11) - ctx->ul_data_aggregation_max_datagrams = 11; -#endif - *rx_urb_size = le32_to_cpu(rx_size); - } else { - *rx_urb_size = 0; - result = -EFAULT; - } -} else { - int qmap_enabled = 0, rx_size = 0, tx_size = 0; - result = QMIWDASetDataFormatResp( pReadBuffer, - readBufferSize, pDev->mbRawIPMode, &qmap_enabled, &rx_size, &tx_size, NULL); -} - - kfree( pReadBuffer ); - - if (result < 0) - { - DBG( "Data Format Cannot be set\n" ); - } - - ReleaseClientID( pDev, WDAClientID ); - - // Success - return 0; -} - -int QuecQMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ) { - return QMIWDASetDataFormat(pDev, qmap_mode, rx_urb_size); -} diff --git a/quectel_Gobinet/src/QMIDevice.h b/quectel_Gobinet/src/QMIDevice.h deleted file mode 100644 index 71af0af..0000000 --- a/quectel_Gobinet/src/QMIDevice.h +++ /dev/null @@ -1,368 +0,0 @@ -/*=========================================================================== -FILE: - QMIDevice.h - -DESCRIPTION: - Functions related to the QMI interface device - -FUNCTIONS: - Generic functions - IsDeviceValid - PrintHex - GobiSetDownReason - GobiClearDownReason - GobiTestDownReason - - Driver level asynchronous read functions - ResubmitIntURB - ReadCallback - IntCallback - StartRead - KillRead - - Internal read/write functions - ReadAsync - UpSem - ReadSync - WriteSyncCallback - WriteSync - - Internal memory management functions - GetClientID - ReleaseClientID - FindClientMem - AddToReadMemList - PopFromReadMemList - AddToNotifyList - NotifyAndPopNotifyList - AddToURBList - PopFromURBList - - Internal userspace wrapper functions - UserspaceunlockedIOCTL - - Userspace wrappers - UserspaceOpen - UserspaceIOCTL - UserspaceClose - UserspaceRead - UserspaceWrite - UserspacePoll - - Initializer and destructor - RegisterQMIDevice - DeregisterQMIDevice - - Driver level client management - QMIReady - QMIWDSCallback - SetupQMIWDSCallback - QMIDMSGetMEID - -Copyright (c) 2011, Code Aurora Forum. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Code Aurora Forum 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 OWNER 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. -===========================================================================*/ - -//--------------------------------------------------------------------------- -// Pragmas -//--------------------------------------------------------------------------- -#pragma once - -//--------------------------------------------------------------------------- -// Include Files -//--------------------------------------------------------------------------- -#include "Structs.h" -#include "QMI.h" - -/*=========================================================================*/ -// Generic functions -/*=========================================================================*/ - -#ifdef __QUECTEL_INTER__ - -// Basic test to see if device memory is valid -static bool IsDeviceValid( sGobiUSBNet * pDev ); - -/*=========================================================================*/ -// Driver level asynchronous read functions -/*=========================================================================*/ - -// Resubmit interrupt URB, re-using same values -static int ResubmitIntURB( struct urb * pIntURB ); - -// Read callback -// Put the data in storage and notify anyone waiting for data -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -static void ReadCallback( struct urb * pReadURB ); -#else -static void ReadCallback(struct urb *pReadURB, struct pt_regs *regs); -#endif - -// Inturrupt callback -// Data is available, start a read URB -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -static void IntCallback( struct urb * pIntURB ); -#else -static void IntCallback(struct urb *pIntURB, struct pt_regs *regs); -#endif - -/*=========================================================================*/ -// Internal read/write functions -/*=========================================================================*/ - -// Start asynchronous read -// Reading client's data store, not device -static int ReadAsync( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void (*pCallback)(sGobiUSBNet *, u16, void *), - void * pData ); - -// Notification function for synchronous read -static void UpSem( - sGobiUSBNet * pDev, - u16 clientID, - void * pData ); - -// Start synchronous read -// Reading client's data store, not device -static int ReadSync( - sGobiUSBNet * pDev, - void ** ppOutBuffer, - u16 clientID, - u16 transactionID ); - -// Write callback -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 )) -static void WriteSyncCallback( struct urb * pWriteURB ); -#else -static void WriteSyncCallback(struct urb *pWriteURB, struct pt_regs *regs); -#endif - -// Start synchronous write -static int WriteSync( - sGobiUSBNet * pDev, - char * pInWriteBuffer, - int size, - u16 clientID ); - -/*=========================================================================*/ -// Internal memory management functions -/*=========================================================================*/ - -// Create client and allocate memory -static int GetClientID( - sGobiUSBNet * pDev, - u8 serviceType ); - -// Release client and free memory -static void ReleaseClientID( - sGobiUSBNet * pDev, - u16 clientID ); - -// Find this client's memory -static sClientMemList * FindClientMem( - sGobiUSBNet * pDev, - u16 clientID ); - -// Add Data to this client's ReadMem list -static bool AddToReadMemList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void * pData, - u16 dataSize ); - -// Remove data from this client's ReadMem list if it matches -// the specified transaction ID. -static bool PopFromReadMemList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void ** ppData, - u16 * pDataSize ); - -// Add Notify entry to this client's notify List -static bool AddToNotifyList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID, - void (* pNotifyFunct)(sGobiUSBNet *, u16, void *), - void * pData ); - -// Remove first Notify entry from this client's notify list -// and Run function -static bool NotifyAndPopNotifyList( - sGobiUSBNet * pDev, - u16 clientID, - u16 transactionID ); - -// Add URB to this client's URB list -static bool AddToURBList( - sGobiUSBNet * pDev, - u16 clientID, - struct urb * pURB ); - -// Remove URB from this client's URB list -static struct urb * PopFromURBList( - sGobiUSBNet * pDev, - u16 clientID ); - -/*=========================================================================*/ -// Internal userspace wrappers -/*=========================================================================*/ - -// Userspace unlocked ioctl -static long UserspaceunlockedIOCTL( - struct file * pFilp, - unsigned int cmd, - unsigned long arg ); - -/*=========================================================================*/ -// Userspace wrappers -/*=========================================================================*/ - -// Userspace open -static int UserspaceOpen( - struct inode * pInode, - struct file * pFilp ); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,36 )) -// Userspace ioctl -static int UserspaceIOCTL( - struct inode * pUnusedInode, - struct file * pFilp, - unsigned int cmd, - unsigned long arg ); -#endif - -// Userspace close -#define quectel_no_for_each_process -#ifdef quectel_no_for_each_process -static int UserspaceClose( - struct inode * pInode, - struct file * pFilp ); -#else -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 )) -static int UserspaceClose( - struct file * pFilp, - fl_owner_t unusedFileTable ); -#else -static int UserspaceClose( struct file * pFilp ); -#endif -#endif - -// Userspace read (synchronous) -static ssize_t UserspaceRead( - struct file * pFilp, - char __user * pBuf, - size_t size, - loff_t * pUnusedFpos ); - -// Userspace write (synchronous) -static ssize_t UserspaceWrite( - struct file * pFilp, - const char __user * pBuf, - size_t size, - loff_t * pUnusedFpos ); - -static unsigned int UserspacePoll( - struct file * pFilp, - struct poll_table_struct * pPollTable ); - -/*=========================================================================*/ -// Driver level client management -/*=========================================================================*/ - -// Check if QMI is ready for use -static bool QMIReady( - sGobiUSBNet * pDev, - u16 timeout ); - -// QMI WDS callback function -static void QMIWDSCallback( - sGobiUSBNet * pDev, - u16 clientID, - void * pData ); - -// Fire off reqests and start async read for QMI WDS callback -static int SetupQMIWDSCallback( sGobiUSBNet * pDev ); - -// Register client, send req and parse MEID response, release client -static int QMIDMSGetMEID( sGobiUSBNet * pDev ); - -// Register client, send req and parse Data format response, release client -static int QMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ); -#endif - -// Print Hex data, for debug purposes -void QuecPrintHex( - void * pBuffer, - u16 bufSize ); - -// Sets mDownReason and turns carrier off -void QuecGobiSetDownReason( - sGobiUSBNet * pDev, - u8 reason ); - -// Clear mDownReason and may turn carrier on -void QuecGobiClearDownReason( - sGobiUSBNet * pDev, - u8 reason ); - -// Tests mDownReason and returns whether reason is set -bool QuecGobiTestDownReason( - sGobiUSBNet * pDev, - u8 reason ); - -// Start continuous read "thread" - int QuecStartRead( sGobiUSBNet * pDev ); - -// Kill continuous read "thread" - void QuecKillRead( sGobiUSBNet * pDev ); - -/*=========================================================================*/ -// Initializer and destructor -/*=========================================================================*/ - -// QMI Device initialization function -int QuecRegisterQMIDevice( sGobiUSBNet * pDev ); - -// QMI Device cleanup function -void QuecDeregisterQMIDevice( sGobiUSBNet * pDev ); - -int QuecQMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ); - -#define PrintHex QuecPrintHex -#define GobiSetDownReason QuecGobiSetDownReason -#define GobiClearDownReason QuecGobiClearDownReason -#define GobiTestDownReason QuecGobiTestDownReason -#define StartRead QuecStartRead -#define KillRead QuecKillRead -#define RegisterQMIDevice QuecRegisterQMIDevice -#define DeregisterQMIDevice QuecDeregisterQMIDevice diff --git a/quectel_Gobinet/src/Readme.txt b/quectel_Gobinet/src/Readme.txt deleted file mode 100644 index 28412fa..0000000 --- a/quectel_Gobinet/src/Readme.txt +++ /dev/null @@ -1,78 +0,0 @@ -Gobi3000 network driver 2011-07-29-1026 - -This readme covers important information concerning -the Gobi Net driver. - -Table of Contents - -1. What's new in this release -2. Known issues -3. Known platform issues - - -------------------------------------------------------------------------------- - -1. WHAT'S NEW - -This Release (Gobi3000 network driver 2011-07-29-1026) -a. Signal the device to leave low power mode on enumeration -b. Add "txQueueLength" parameter, which will set the Tx Queue Length -c. Send SetControlLineState message during driver/device removal -d. Change to new date-based versioning scheme - -Prior Release (Gobi3000 network driver 1.0.60) 06/29/2011 -a. Add UserspacePoll() function, to support select() -b. Fix possible deadlock on GobiUSBNetTXTimeout() -c. Fix memory leak on data transmission - -Prior Release (Gobi3000 network driver 1.0.50) 05/18/2011 -a. Add support for kernels up to 2.6.38 -b. Add support for dynamic interface binding - -Prior Release (Gobi3000 network driver 1.0.40) 02/28/2011 -a. In cases of QMI read errors, discard the error and continue reading. -b. Add "interruptible" parameter, which may be disabled for debugging purposes. - -Prior Release (Gobi3000 network driver 1.0.30) 01/05/2011 -a. Fix rare kernel PANIC if a process terminates while file handle close - or device removal is in progress. - -Prior Release (Gobi3000 network driver 1.0.20) 11/01/2010 -a. Fix possible kernel WARNING if device removed before QCWWANDisconnect(). -b. Fix multiple memory leaks in error cases. - -Prior Release (Gobi3000 network driver 1.0.10) 09/17/2010 -a. Initial release - -------------------------------------------------------------------------------- - -2. KNOWN ISSUES - -No known issues. - -------------------------------------------------------------------------------- - -3. KNOWN PLATFORM ISSUES - -a. Enabling autosuspend: - Autosuspend is supported by the Gobi3000 module and its drivers, - but by default it is not enabled by the open source kernel. As such, - the Gobi3000 module will not enter autosuspend unless the - user specifically turns on autosuspend with the command: - echo auto > /sys/bus/usb/devices/.../power/level -b. Ksoftirq using 100% CPU: - There is a known issue with the open source usbnet driver that can - result in infinite software interrupts. The fix for this is to test - (in the usbnet_bh() function) if the usb_device can submit URBs before - attempting to submit the response URB buffers. -c. NetworkManager does not recognize connection after resume: - After resuming from sleep/hibernate, NetworkManager may not recognize new - network connections by the Gobi device. This is a system issue not specific - to the Gobi device, which may result in dhcp not being run and the default - route not being updated. One way to fix this is to simply restart the - NetworkManager service. - -------------------------------------------------------------------------------- - - - diff --git a/quectel_Gobinet/src/ReleaseNote.txt b/quectel_Gobinet/src/ReleaseNote.txt deleted file mode 100644 index 72f6888..0000000 --- a/quectel_Gobinet/src/ReleaseNote.txt +++ /dev/null @@ -1,166 +0,0 @@ -Release Notes - -[V1.6.3] -Date: 9/26/2021 -enhancement: - 1. change version to 1.6.3 -fix: - -[V1.6.2.16] -Date: 9/17/2021 -enhancement: -fix: - 1. add sdx6x platform support - -[V1.6.2.15] -Date: 3/23/2021 -enhancement: -fix: - 1. add sdx12 platform support - -[V1.6.2.14] -Date: 3/18/2021 -enhancement: -fix: - 1. fix kasam: use-after-free when do modem reboot stress test - 2. wait qmi_sync_thread() finish in DeregisterQMIDevice(), usb will disconnect when driver is still in qmi_sync_thread() - -[V1.6.2.13] -Date: 12/31/2020 -enhancement: -fix: - 1. fix quectel-CM open error when driver is still in qmi_sync_thread() but SOC enter sleep. - -[V1.6.2.12] -Date: 12/31/2020 -enhancement: -fix: - 1. for multi-pdn-call, can not ping when usb resume for usb suspend state. - -[V1.6.2.11] -Date: 11/7/2020 -enhancement: - 1. support QUECTEL_QMI_MERGE, for some SOC, control endpoint only support read max 64 bytes QMI. - for QMI that size > 64, we need read serval times, and merge. -fix: - -[V1.6.2.10] -Date: 9/15/2020 -enhancement: -fix: - 1. for X55, fix panic on kernel V2.6 ~ V3.2 - -[V1.6.2.9] -Date: 7/24/2020 -enhancement: -fix: - 1. for X55, fix errors on Big Endian SOC. - -[V1.6.2.8] -Date: 7/2/2020 -enhancement: - 1. support QMAPV5, UL AGG (porting from qmi_wwan_q) -fix: - 1. fix errors kernel V2.6 . - -[V1.6.2.7] -Date: 6/9/2020 -enhancement: -fix: - 1. when send qmi ctl request, clear qmi ctl response which's TID is same - -[V1.6.2.6] -Date: 5/19/2020 -enhancement: - 1. support bridge mode for multi-pdn-call -fix: - -[V1.6.2.5] -Date: 4/26/2020 -enhancement: - 1. fix netcard name as usbX (from ethX) -fix: - -...... - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.5.0] -Date: 2018/04/17 -enhancement:: -1. support EG20&RG500 -2. fix set rx_urb_size as 1520. do not change accroding to MTU - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.4.3] -Date: 2018/04/16 -enhancement:: -1. increase QMAP's rx_urb_size to 32KB - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.4.2] -Date: 2018/04/03 -bug fix: -1. fix qmi client can not be released when quectel-CM killed by kill -9 - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.4.1] -Date: 2018/02/20 -bug fix: -1. fix a compiler error on Kernel lager than 4.11 - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.4.0] -Date: 2018/12/17 -bug fix: -1. fix a USB DMA error when built as GobiNet.ko on Kernel lager than 4.15 - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.8] -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.7] -Date: 2018/09/25 -enhancement: -1. check skb length in tx_fixup functions. -2. when QMAP enabled, set FLAG_RX_ASSEMBLE to advoid 'RX errors' of ifconfig - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.6] -Date: 2018/09/11 -enhancement: -1. support EG12 EM12 -2. optimization QMAP source code -3. fix compile errors and warnnings on kernel version 4.15 - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.5] -Date: 2018/05/12 -enhancement: -1. provide two method to enable QMAP function. - 1.1 set module parameters 'qmap_mode' to X(1~4) to enable QMAP. - 1.2 ifconfig usb0 down, then 'echo X > /sys/class/usbX/qmap_mode' to enable QMAP - for above two method, X(1) used to enable 'IP Aggregation' and X(2~4) to enable 'IP Mux' -2. support bridge mode, also provide two method to enable bridge mode. - 2.1 set module parameters 'bridge_mode' to 1 to enable bridge mode. - 2.2 'echo 1 > /sys/class/usbX/bridge_mode' to enable bridge mode. - bridge mode setups: - brctl addbr br0; brctl addif br0 eth0; brctl addif usb0; ./quectel-CM; ifconfig br0 up; ifconfig eth0 up - then connect eth0 to PC by ethernet cable. and PC run DHCP tool to obtain network public IP address. - - 'WCDMA<E_QConnectManager_Linux&Android_V1.1.40' and later version is required to use QMAP and bridge mode. - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.4] -Date: 2018/05/07 -enhancement: -1. support use 'AT$QCRMCALL=1,1' to setup data call. - when use 'AT$QCRMCALL=1,1', must set module parameters 'qcrmcall_mode' to 1, - and GobiNet Driver will do not tx&rx QMI. - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.3] -Date: 2018/04/04 -optimization: -1. optimization QMAP source code - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.2] -Date: 2018/03/23 -enhancement: -1. support Qualcomm Mux and Aggregation Protocol (QMAP) - 1.1 IP Mux: GobiNet Driver register multiple netcards, one netcards corresponding to one PDP. - and GobiNet Driver will tx/rx multiple IP packets maybe belong to different PDPs in one URB. - 1.2 IP Aggregation: GobiNet Driver will rx multiple IP packets in one URB, used to increase throughput theoretically by reducing the number of usb interrupts. - the max rx URB size of MDM9x07 is 4KB, the max rx URB size of MDM9x40&SDX20 is 16KB - -[Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.1] -Date: 2017/11/20 -enhancement: -1. support BG96 diff --git a/quectel_Gobinet/src/Structs.h b/quectel_Gobinet/src/Structs.h deleted file mode 100644 index 5b7ebbc..0000000 --- a/quectel_Gobinet/src/Structs.h +++ /dev/null @@ -1,529 +0,0 @@ -/*=========================================================================== -FILE: - Structs.h - -DESCRIPTION: - Declaration of structures used by the Qualcomm Linux USB Network driver - -FUNCTIONS: - none - -Copyright (c) 2011, Code Aurora Forum. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Code Aurora Forum 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 OWNER 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. -===========================================================================*/ - -//--------------------------------------------------------------------------- -// Pragmas -//--------------------------------------------------------------------------- -#pragma once - -//--------------------------------------------------------------------------- -// Include Files -//--------------------------------------------------------------------------- -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define QUECTEL_WWAN_QMAP 4 //MAX is 7 -#ifdef QUECTEL_WWAN_QMAP -#define QUECTEL_QMAP_MUX_ID 0x81 -#endif - -//#define QUECTEL_QMI_MERGE - -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -#define QUECTEL_BRIDGE_MODE -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,21 )) -static inline void skb_reset_mac_header(struct sk_buff *skb) -{ - skb->mac.raw = skb->data; -} -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 )) -#define bool u8 -#ifndef URB_FREE_BUFFER -#define URB_FREE_BUFFER_BY_SELF //usb_free_urb will not free, should free by self -#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */ -#endif - -/** - * usb_endpoint_type - get the endpoint's transfer type - * @epd: endpoint to be checked - * - * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according - * to @epd's transfer type. - */ -static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) -{ - return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; -} -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,18 )) -/** - * usb_endpoint_dir_in - check if the endpoint has IN direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type IN, otherwise it returns false. - */ -static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); -} - -/** - * usb_endpoint_dir_out - check if the endpoint has OUT direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type OUT, otherwise it returns false. - */ -static inline int usb_endpoint_dir_out( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); -} - -/** - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type interrupt, otherwise it returns - * false. - */ -static inline int usb_endpoint_xfer_int( - const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT); -} - -static inline int usb_autopm_set_interface(struct usb_interface *intf) -{ return 0; } - -static inline int usb_autopm_get_interface(struct usb_interface *intf) -{ return 0; } - -static inline int usb_autopm_get_interface_async(struct usb_interface *intf) -{ return 0; } - -static inline void usb_autopm_put_interface(struct usb_interface *intf) -{ } -static inline void usb_autopm_put_interface_async(struct usb_interface *intf) -{ } -static inline void usb_autopm_enable(struct usb_interface *intf) -{ } -static inline void usb_autopm_disable(struct usb_interface *intf) -{ } -static inline void usb_mark_last_busy(struct usb_device *udev) -{ } -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,24 )) - #include "usbnet.h" -#else - #include -#endif - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,25 )) - #include -#else - #include -#endif - -// Used in recursion, defined later below -struct sGobiUSBNet; - - -#if defined(QUECTEL_WWAN_QMAP) -#define QUECTEL_UL_DATA_AGG 1 - -#if defined(QUECTEL_UL_DATA_AGG) -struct ul_agg_ctx { - /* QMIWDS_ADMIN_SET_DATA_FORMAT_RESP TLV_0x17 and TLV_0x18 */ - uint ul_data_aggregation_max_datagrams; //UplinkDataAggregationMaxDatagramsTlv - uint ul_data_aggregation_max_size; //UplinkDataAggregationMaxSizeTlv - uint dl_minimum_padding; -}; -#endif -#endif - -/*=========================================================================*/ -// Struct sReadMemList -// -// Structure that defines an entry in a Read Memory linked list -/*=========================================================================*/ -typedef struct sReadMemList -{ - /* Data buffer */ - void * mpData; - - /* Transaction ID */ - u16 mTransactionID; - - /* Size of data buffer */ - u16 mDataSize; - - /* Next entry in linked list */ - struct sReadMemList * mpNext; - -} sReadMemList; - -/*=========================================================================*/ -// Struct sNotifyList -// -// Structure that defines an entry in a Notification linked list -/*=========================================================================*/ -typedef struct sNotifyList -{ - /* Function to be run when data becomes available */ - void (* mpNotifyFunct)(struct sGobiUSBNet *, u16, void *); - - /* Transaction ID */ - u16 mTransactionID; - - /* Data to provide as parameter to mpNotifyFunct */ - void * mpData; - - /* Next entry in linked list */ - struct sNotifyList * mpNext; - -} sNotifyList; - -/*=========================================================================*/ -// Struct sURBList -// -// Structure that defines an entry in a URB linked list -/*=========================================================================*/ -typedef struct sURBList -{ - /* The current URB */ - struct urb * mpURB; - - /* Next entry in linked list */ - struct sURBList * mpNext; - -} sURBList; - -/*=========================================================================*/ -// Struct sClientMemList -// -// Structure that defines an entry in a Client Memory linked list -// Stores data specific to a Service Type and Client ID -/*=========================================================================*/ -typedef struct sClientMemList -{ - /* Client ID for this Client */ - u16 mClientID; - - /* Linked list of Read entries */ - /* Stores data read from device before sending to client */ - sReadMemList * mpList; - - /* Linked list of Notification entries */ - /* Stores notification functions to be run as data becomes - available or the device is removed */ - sNotifyList * mpReadNotifyList; - - /* Linked list of URB entries */ - /* Stores pointers to outstanding URBs which need canceled - when the client is deregistered or the device is removed */ - sURBList * mpURBList; - - /* Next entry in linked list */ - struct sClientMemList * mpNext; - - /* Wait queue object for poll() */ - wait_queue_head_t mWaitQueue; - -} sClientMemList; - -/*=========================================================================*/ -// Struct sURBSetupPacket -// -// Structure that defines a USB Setup packet for Control URBs -// Taken from USB CDC specifications -/*=========================================================================*/ -typedef struct sURBSetupPacket -{ - /* Request type */ - u8 mRequestType; - - /* Request code */ - u8 mRequestCode; - - /* Value */ - u16 mValue; - - /* Index */ - u16 mIndex; - - /* Length of Control URB */ - u16 mLength; - -} sURBSetupPacket; - -// Common value for sURBSetupPacket.mLength -#define DEFAULT_READ_URB_LENGTH 0x1000 - -#ifdef QUECTEL_QMI_MERGE -#define MERGE_PACKET_IDENTITY 0x2c7c -#define MERGE_PACKET_VERSION 0x0001 -#define MERGE_PACKET_MAX_PAYLOAD_SIZE 56 -typedef struct sQMIMsgHeader { - u16 idenity; - u16 version; - u16 cur_len; - u16 total_len; -} sQMIMsgHeader; - -typedef struct sQMIMsgPacket { - sQMIMsgHeader header; - u16 len; - char buf[DEFAULT_READ_URB_LENGTH]; -} sQMIMsgPacket; -#endif - -#ifdef CONFIG_PM -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) -/*=========================================================================*/ -// Struct sAutoPM -// -// Structure used to manage AutoPM thread which determines whether the -// device is in use or may enter autosuspend. Also submits net -// transmissions asynchronously. -/*=========================================================================*/ -typedef struct sAutoPM -{ - /* Thread for atomic autopm function */ - struct task_struct * mpThread; - - /* Signal for completion when it's time for the thread to work */ - struct completion mThreadDoWork; - - /* Time to exit? */ - bool mbExit; - - /* List of URB's queued to be sent to the device */ - sURBList * mpURBList; - - /* URB list lock (for adding and removing elements) */ - spinlock_t mURBListLock; - - /* Length of the URB list */ - atomic_t mURBListLen; - - /* Active URB */ - struct urb * mpActiveURB; - - /* Active URB lock (for adding and removing elements) */ - spinlock_t mActiveURBLock; - - /* Duplicate pointer to USB device interface */ - struct usb_interface * mpIntf; - -} sAutoPM; -#endif -#endif /* CONFIG_PM */ - -/*=========================================================================*/ -// Struct sQMIDev -// -// Structure that defines the data for the QMI device -/*=========================================================================*/ -typedef struct sQMIDev -{ - /* Device number */ - dev_t mDevNum; - - /* Device class */ - struct class * mpDevClass; - - /* cdev struct */ - struct cdev mCdev; - - /* is mCdev initialized? */ - bool mbCdevIsInitialized; - - /* Pointer to read URB */ - struct urb * mpReadURB; - -//#define READ_QMI_URB_ERROR -#ifdef READ_QMI_URB_ERROR - struct timer_list mReadUrbTimer; -#endif - -#ifdef QUECTEL_QMI_MERGE - sQMIMsgPacket * mpQmiMsgPacket; -#endif - - /* Read setup packet */ - sURBSetupPacket * mpReadSetupPacket; - - /* Read buffer attached to current read URB */ - void * mpReadBuffer; - - /* Inturrupt URB */ - /* Used to asynchronously notify when read data is available */ - struct urb * mpIntURB; - - /* Buffer used by Inturrupt URB */ - void * mpIntBuffer; - - /* Pointer to memory linked list for all clients */ - sClientMemList * mpClientMemList; - - /* Spinlock for client Memory entries */ - spinlock_t mClientMemLock; - - /* Transaction ID associated with QMICTL "client" */ - atomic_t mQMICTLTransactionID; - -} sQMIDev; - -typedef struct { - u32 qmap_enabled; - u32 dl_data_aggregation_max_datagrams; - u32 dl_data_aggregation_max_size ; - u32 ul_data_aggregation_max_datagrams; - u32 ul_data_aggregation_max_size; - u32 dl_minimum_padding; -} QMAP_SETTING; - -/*=========================================================================*/ -// Struct sGobiUSBNet -// -// Structure that defines the data associated with the Qualcomm USB device -/*=========================================================================*/ -typedef struct sGobiUSBNet -{ - atomic_t refcount; - - /* Net device structure */ - struct usbnet * mpNetDev; -#ifdef QUECTEL_WWAN_QMAP - unsigned link_state; - int qmap_mode; - int qmap_size; - int qmap_version; - struct net_device *mpQmapNetDev[QUECTEL_WWAN_QMAP]; - struct tasklet_struct txq; - - QMAP_SETTING qmap_settings; -#if defined(QUECTEL_UL_DATA_AGG) - struct ul_agg_ctx agg_ctx; -#endif - -#ifdef QUECTEL_BRIDGE_MODE - int m_qmap_bridge_mode[QUECTEL_WWAN_QMAP]; -#endif -#endif - -#if 1 //def DATA_MODE_RP - bool mbMdm9x07; - bool mbMdm9x06; //for BG96 - /* QMI "device" work in IP Mode or ETH Mode */ - bool mbRawIPMode; -#ifdef QUECTEL_BRIDGE_MODE - int m_bridge_mode; - uint m_bridge_ipv4; - unsigned char mHostMAC[6]; -#endif - int m_qcrmcall_mode; -#endif - - struct completion mQMIReadyCompletion; - bool mbQMIReady; - bool mbProbeDone; - bool mbQMISyncIng; - - /* Usb device interface */ - struct usb_interface * mpIntf; - - /* Pointers to usbnet_open and usbnet_stop functions */ - int (* mpUSBNetOpen)(struct net_device *); - int (* mpUSBNetStop)(struct net_device *); - - /* Reason(s) why interface is down */ - /* Used by Gobi*DownReason */ - unsigned long mDownReason; -#define NO_NDIS_CONNECTION 0 -#define CDC_CONNECTION_SPEED 1 -#define DRIVER_SUSPENDED 2 -#define NET_IFACE_STOPPED 3 - - /* QMI "device" status */ - bool mbQMIValid; - - bool mbDeregisterQMIDevice; - - /* QMI "device" memory */ - sQMIDev mQMIDev; - - /* Device MEID */ - char mMEID[14]; - struct hrtimer timer; - struct tasklet_struct bh; - unsigned long - pending_num : 8, - pending_size : 16; - struct sk_buff *pending_pool[16]; - -#ifdef CONFIG_PM - #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,29 )) - /* AutoPM thread */ - sAutoPM mAutoPM; -#endif -#endif /* CONFIG_PM */ -} sGobiUSBNet; - -/*=========================================================================*/ -// Struct sQMIFilpStorage -// -// Structure that defines the storage each file handle contains -// Relates the file handle to a client -/*=========================================================================*/ -typedef struct sQMIFilpStorage -{ - /* Client ID */ - u16 mClientID; - - /* Device pointer */ - sGobiUSBNet * mpDev; - -} sQMIFilpStorage; - diff --git a/quectel_MHI/Makefile b/quectel_MHI/Makefile deleted file mode 100644 index 6322519..0000000 --- a/quectel_MHI/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=pcie_mhi -PKG_VERSION:=1.3.6 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/pcie_mhi - SUBMENU:=WWAN Support - TITLE:=Kernel pcie driver for MHI device - DEPENDS:=+pciids +pciutils +quectel-CM-5G - FILES:=$(PKG_BUILD_DIR)/pcie_mhi.ko - AUTOLOAD:=$(call AutoLoad,90,pcie_mhi) -endef - -define KernelPackage/pcie_mhi/description - Kernel module for register a custom pciemhi platform device. -endef - -MAKE_OPTS:= \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CXXFLAGS="$(TARGET_CXXFLAGS)" \ - M="$(PKG_BUILD_DIR)" \ - $(EXTRA_KCONFIG) - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,pcie_mhi)) diff --git a/quectel_MHI/src/Makefile b/quectel_MHI/src/Makefile deleted file mode 100644 index 1b2c1f5..0000000 --- a/quectel_MHI/src/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#ccflags-y += -g -obj-m += pcie_mhi.o -pcie_mhi-objs := core/mhi_init.o core/mhi_main.o core/mhi_pm.o core/mhi_boot.o core/mhi_dtr.o controllers/mhi_qti.o -pcie_mhi-objs += devices/mhi_uci.o - -ifeq (1,1) -pcie_mhi-objs += devices/mhi_netdev_quectel.o -else -pcie_mhi-objs += devices/mhi_netdev.o -pcie_mhi-objs += devices/rmnet_handler.o -endif - -PWD := $(shell pwd) -ifeq ($(ARCH),) -ARCH := $(shell uname -m) -endif -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := -endif -ifeq ($(KDIR),) -KDIR := /lib/modules/$(shell uname -r)/build -endif - -pcie_mhi: clean - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules - #cp pcie_mhi.ko /tftpboot/ - -clean: - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) clean - find . -name *.o.ur-safe | xargs rm -f - -install: pcie_mhi - sudo cp pcie_mhi.ko /lib/modules/${shell uname -r}/kernel/drivers/pci/ - sudo depmod diff --git a/quectel_MHI/src/README b/quectel_MHI/src/README deleted file mode 100644 index 927df0c..0000000 --- a/quectel_MHI/src/README +++ /dev/null @@ -1,36 +0,0 @@ -1. porting pcie_mhi driver as next - -$ git diff drivers/Makefile -diff --git a/drivers/Makefile b/drivers/Makefile -index 77fbc52..e45837e 100644 ---- a/drivers/Makefile -+++ b/drivers/Makefile -@@ -184,3 +184,4 @@ obj-$(CONFIG_FPGA) += fpga/ - obj-$(CONFIG_FSI) += fsi/ - obj-$(CONFIG_TEE) += tee/ - obj-$(CONFIG_MULTIPLEXER) += mux/ -+obj-y += pcie_mhi/ - -$ tree drivers/pcie_mhi/ -L 1 -drivers/pcie_mhi/ - controllers - core - devices - Makefile - -2. check RG500 attach pcie_mhi driver successful - -root@OpenWrt:/# lspci -00:00.0 Class 0604: 17cb:0302 -01:00.0 Class ff00: 17cb:0306 - -root@OpenWrt:~# dmesg | grep mhi -[ 138.483252] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.6 -[ 138.492350] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 - -3. how to use, see next logs - -log/QXDM_OVER_PCIE.txt -log/AT_OVER_PCIE.txt -log/MBIM_OVER_PCIE.txt -log/QMI_OVER_PCIE.txt diff --git a/quectel_MHI/src/ReleaseNote.txt b/quectel_MHI/src/ReleaseNote.txt deleted file mode 100644 index f70e45c..0000000 --- a/quectel_MHI/src/ReleaseNote.txt +++ /dev/null @@ -1,103 +0,0 @@ -Release Notes - -[V1.3.4] -Date: 12/8/2022 -enhancement: - 1. only allow to enable autosuspend when module is in MHI_EE_AMSS - 2. show pcie link speed and width when driver probe - 3. check pcie link status by read pcie vid and pid when driver probe, - if pcie link is down, return -EIO - 4. support RM520 (1eac:1004) - 5. support qmap command packet -fix: - 1. fix tx queue is wrong stop when do uplink TPUT - 2. fix after QFirehose, module fail to bootup at very small probability - 3. mhi uci add mutex lock for concurrent reads/writes - -[V1.3.3] -Date: 30/6/2022 -enhancement: - 1. remove one un-necessary kmalloc when do qfirehose - 2. support mhi monitor (like usbmon), usage: cat /sys/kernel/debug/mhi_q/0306_00\:01.00/mhimon - 3. set ring size of event 0 to 256 (from 1024), required by x6x - 4. support PCIE local network card mhi_swip0 (chan 46/47), default disabled - 5. porting IPQ5018 mhi rate controll code from spf11.5 - 6. set pcie rmnet download max qmap packet size to 15KB (same to IPQ MHI Driver) - 7. support set different mac address for rmnet net card - 8. when mhi netdev fail to malloc, use delay_work instead work - 9. optimize code for 'when driver load, modem is still in MHI_EE_PTHRU' -fix: - 1. Fix not synchronize access rp/wp when mhi_queue_xxx and mhi_process_xxx_ring run on different CPU - 2. set dma mask when driver probe, some SOC like rpi_4 need it - -[V1.3.2] -Date: 12/16/2021 -enhancement: - 1. support Linux Kernel V5.14 - 2. mhi_netdev_quectel.c do not print log in softirq context - -[V1.3.1] -Date: 9/26/2021 -enhancement: -fix: - -[V1.3.0.19] -Date: 9/18/2021 -enhancement: - 1. support sdx62 (17cb:0308) - 2. support IPQ5018's NSS - 3. use 'qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c' instead myself rmnet_nss.c - and pcie_mhi.ko must load after then rmnet_nss.ko - 4. allow bhi irq is not 0 (for ipq5018) -fix: - -[V1.3.0.18] -Date: 4/14/2021 -enhancement: - 1. support mbim multiple call, usage: - # insmod pcie_mhi.ko mhi_mbim_enabeld=1 qmap_mode=4 - # quectel-mbim-proxy -d /dev/mhi_MBIM & - # quectel-CM -n X -fix: - -[V1.3.0.17] -Date: 3/11/2021 -enhancement: -fix: - 1. fix CPU loading very high when TPUT test when only one MSI interrupt - 2. fix error on latest X24 modem - -[V1.3.0.16] -Date: 11/18/2020 -enhancement: -fix: - 1. add ring size to 32, for in-bound chan, if one ring is full, modem will not generate MSI interrupt for all chan - -[V1.3.0.15] -Date: 10/30/2020 -enhancement: - 1. support multi-modems, named as /dev/mhi_X -fix: - 1. fix compile error on kernel v5.8 - -[V1.3.0.14] -Date: 10/9/2020 -enhancement: - 1. suppport EM120&EM160 -fix: - 1. fix compile error on kernel v5.6 - 2. support runtime suspend - -[V1.3.0.13] -Date: 9/7/2020 -enhancement: - 1. suppport EM120&EM160 -fix: - 1. fix error on X55 + PCIE2.0(e.g IPQ4019) - 2. support runtime suspend - -[V1.3.0.12] -Date: 7/7/2020 -enhancement: - 1. suppport create only none netcard (enabled by marco MHI_NETDEV_ONE_CARD_MODE), -fix: \ No newline at end of file diff --git a/quectel_MHI/src/controllers/Kconfig b/quectel_MHI/src/controllers/Kconfig deleted file mode 100644 index e18b38b..0000000 --- a/quectel_MHI/src/controllers/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -menu "MHI controllers" - -config MHI_QTI - tristate "MHI QTI" - depends on MHI_BUS - help - If you say yes to this option, MHI bus support for QTI modem chipsets - will be enabled. QTI PCIe based modems uses MHI as the communication - protocol. MHI control driver is the bus master for such modems. As the - bus master driver, it oversees power management operations such as - suspend, resume, powering on and off the device. - -endmenu diff --git a/quectel_MHI/src/controllers/Makefile b/quectel_MHI/src/controllers/Makefile deleted file mode 100644 index ab9ec55..0000000 --- a/quectel_MHI/src/controllers/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_MHI_QTI) += mhi_qti.o mhi_arch_qti.o diff --git a/quectel_MHI/src/controllers/mhi_arch_qti.c b/quectel_MHI/src/controllers/mhi_arch_qti.c deleted file mode 100644 index de19d94..0000000 --- a/quectel_MHI/src/controllers/mhi_arch_qti.c +++ /dev/null @@ -1,275 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/mhi.h" -#include "mhi_qti.h" - -struct arch_info { - struct mhi_dev *mhi_dev; - struct msm_bus_scale_pdata *msm_bus_pdata; - u32 bus_client; - struct pci_saved_state *pcie_state; - struct pci_saved_state *ref_pcie_state; - struct dma_iommu_mapping *mapping; -}; - -struct mhi_bl_info { - struct mhi_device *mhi_device; - async_cookie_t cookie; - void *ipc_log; -}; - -/* ipc log markings */ -#define DLOG "Dev->Host: " -#define HLOG "Host: " - -#ifdef CONFIG_MHI_DEBUG - -#define MHI_IPC_LOG_PAGES (100) -enum MHI_DEBUG_LEVEL mhi_ipc_log_lvl = MHI_MSG_LVL_VERBOSE; - -#else - -#define MHI_IPC_LOG_PAGES (10) -enum MHI_DEBUG_LEVEL mhi_ipc_log_lvl = MHI_MSG_LVL_ERROR; - -#endif - -static int mhi_arch_set_bus_request(struct mhi_controller *mhi_cntrl, int index) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - - MHI_LOG("Setting bus request to index %d\n", index); - - if (arch_info->bus_client) - return msm_bus_scale_client_update_request( - arch_info->bus_client, - index); - - /* default return success */ - return 0; -} - -static void mhi_bl_dl_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_bl_info *mhi_bl_info = mhi_device_get_devdata(mhi_dev); - char *buf = mhi_result->buf_addr; - - /* force a null at last character */ - buf[mhi_result->bytes_xferd - 1] = 0; - - ipc_log_string(mhi_bl_info->ipc_log, "%s %s", DLOG, buf); -} - -static void mhi_bl_dummy_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ -} - -static void mhi_bl_remove(struct mhi_device *mhi_dev) -{ - struct mhi_bl_info *mhi_bl_info = mhi_device_get_devdata(mhi_dev); - - ipc_log_string(mhi_bl_info->ipc_log, HLOG "Received Remove notif.\n"); - - /* wait for boot monitor to exit */ - async_synchronize_cookie(mhi_bl_info->cookie + 1); -} - -static void mhi_bl_boot_monitor(void *data, async_cookie_t cookie) -{ - struct mhi_bl_info *mhi_bl_info = data; - struct mhi_device *mhi_device = mhi_bl_info->mhi_device; - struct mhi_controller *mhi_cntrl = mhi_device->mhi_cntrl; - /* 15 sec timeout for booting device */ - const u32 timeout = msecs_to_jiffies(15000); - - /* wait for device to enter boot stage */ - wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->ee == MHI_EE_AMSS - || mhi_cntrl->ee == MHI_EE_DISABLE_TRANSITION, - timeout); - - if (mhi_cntrl->ee == MHI_EE_AMSS) { - ipc_log_string(mhi_bl_info->ipc_log, HLOG - "Device successfully booted to mission mode\n"); - - mhi_unprepare_from_transfer(mhi_device); - } else { - ipc_log_string(mhi_bl_info->ipc_log, HLOG - "Device failed to boot to mission mode, ee = %s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - } -} - -static int mhi_bl_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - char node_name[32]; - struct mhi_bl_info *mhi_bl_info; - - mhi_bl_info = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_bl_info), - GFP_KERNEL); - if (!mhi_bl_info) - return -ENOMEM; - - snprintf(node_name, sizeof(node_name), "mhi_bl_%04x_%02u.%02u.%02u", - mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus, mhi_dev->slot); - - mhi_bl_info->ipc_log = ipc_log_context_create(MHI_IPC_LOG_PAGES, - node_name, 0); - if (!mhi_bl_info->ipc_log) - return -EINVAL; - - mhi_bl_info->mhi_device = mhi_dev; - mhi_device_set_devdata(mhi_dev, mhi_bl_info); - - ipc_log_string(mhi_bl_info->ipc_log, HLOG - "Entered SBL, Session ID:0x%x\n", - mhi_dev->mhi_cntrl->session_id); - - /* start a thread to monitor entering mission mode */ - mhi_bl_info->cookie = async_schedule(mhi_bl_boot_monitor, mhi_bl_info); - - return 0; -} - -static const struct mhi_device_id mhi_bl_match_table[] = { - { .chan = "BL" }, - {}, -}; - -static struct mhi_driver mhi_bl_driver = { - .id_table = mhi_bl_match_table, - .remove = mhi_bl_remove, - .probe = mhi_bl_probe, - .ul_xfer_cb = mhi_bl_dummy_cb, - .dl_xfer_cb = mhi_bl_dl_cb, - .driver = { - .name = "MHI_BL", - .owner = THIS_MODULE, - }, -}; - -int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - char node[32]; - - if (!arch_info) { - arch_info = devm_kzalloc(&mhi_dev->pci_dev->dev, - sizeof(*arch_info), GFP_KERNEL); - if (!arch_info) - return -ENOMEM; - - mhi_dev->arch_info = arch_info; - - snprintf(node, sizeof(node), "mhi_%04x_%02u.%02u.%02u", - mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus, - mhi_cntrl->slot); - mhi_cntrl->log_buf = ipc_log_context_create(MHI_IPC_LOG_PAGES, - node, 0); - mhi_cntrl->log_lvl = mhi_ipc_log_lvl; - - /* save reference state for pcie config space */ - arch_info->ref_pcie_state = pci_store_saved_state( - mhi_dev->pci_dev); - - mhi_driver_register(&mhi_bl_driver); - } - - return mhi_arch_set_bus_request(mhi_cntrl, 1); -} - -void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) -{ - mhi_arch_set_bus_request(mhi_cntrl, 0); -} - -int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, bool graceful) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - - MHI_LOG("Entered\n"); - - if (graceful) { - pci_clear_master(pci_dev); - ret = pci_save_state(mhi_dev->pci_dev); - if (ret) { - MHI_ERR("Failed with pci_save_state, ret:%d\n", ret); - return ret; - } - - arch_info->pcie_state = pci_store_saved_state(pci_dev); - pci_disable_device(pci_dev); - } - - /* - * We will always attempt to put link into D3hot, however - * link down may have happened due to error fatal, so - * ignoring the return code - */ - pci_set_power_state(pci_dev, PCI_D3hot); - - /* release the resources */ - mhi_arch_set_bus_request(mhi_cntrl, 0); - - MHI_LOG("Exited\n"); - - return 0; -} - -int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - - MHI_LOG("Entered\n"); - - /* request resources and establish link trainning */ - ret = mhi_arch_set_bus_request(mhi_cntrl, 1); - if (ret) - MHI_LOG("Could not set bus frequency, ret:%d\n", ret); - - ret = pci_set_power_state(pci_dev, PCI_D0); - if (ret) { - MHI_ERR("Failed to set PCI_D0 state, ret:%d\n", ret); - return ret; - } - - ret = pci_enable_device(pci_dev); - if (ret) { - MHI_ERR("Failed to enable device, ret:%d\n", ret); - return ret; - } - - ret = pci_load_and_free_saved_state(pci_dev, &arch_info->pcie_state); - if (ret) - MHI_LOG("Failed to load saved cfg state\n"); - - pci_restore_state(pci_dev); - pci_set_master(pci_dev); - - MHI_LOG("Exited\n"); - - return 0; -} diff --git a/quectel_MHI/src/controllers/mhi_qcom.c b/quectel_MHI/src/controllers/mhi_qcom.c deleted file mode 100644 index 70dd917..0000000 --- a/quectel_MHI/src/controllers/mhi_qcom.c +++ /dev/null @@ -1,715 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/mhi.h" -#include "mhi_qcom.h" - -#if 1 -#ifndef PCI_IRQ_MSI -#define PCI_IRQ_MSI (1 << 1) /* Allow MSI interrupts */ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,53 )) -int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) -{ - int nvec = maxvec; - int rc; - - if (maxvec < minvec) - return -ERANGE; - - do { - rc = pci_enable_msi_block(dev, nvec); - if (rc < 0) { - return rc; - } else if (rc > 0) { - if (rc < minvec) - return -ENOSPC; - nvec = rc; - } - } while (rc); - - return nvec; -} -#endif - -static int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, - unsigned int max_vecs, unsigned int flags) -{ - return pci_enable_msi_range(dev, min_vecs, max_vecs); -} - -static void pci_free_irq_vectors(struct pci_dev *dev) -{ - pci_disable_msi(dev); -} - -static int pci_irq_vector(struct pci_dev *dev, unsigned int nr) -{ - return dev->irq + nr; -} -#endif -#endif - -static struct pci_device_id mhi_pcie_device_id[] = { - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)}, //SDX20 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)}, //SDX24 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0306)}, //SDX55 - {PCI_DEVICE(0x2C7C, 0x0512)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)}, - {0}, -}; - -MODULE_DEVICE_TABLE(pci, mhi_pcie_device_id); - -static struct pci_driver mhi_pcie_driver; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_dev *pci_dev = mhi_dev->pci_dev; - - pci_free_irq_vectors(pci_dev); - iounmap(mhi_cntrl->regs); - mhi_cntrl->regs = NULL; - pci_clear_master(pci_dev); - pci_release_region(pci_dev, mhi_dev->resn); - pci_disable_device(pci_dev); -} - -static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - resource_size_t start, len; - int i; - - mhi_dev->resn = MHI_PCI_BAR_NUM; - ret = pci_assign_resource(pci_dev, mhi_dev->resn); - if (ret) { - MHI_ERR("Error assign pci resources, ret:%d\n", ret); - return ret; - } - - ret = pci_enable_device(pci_dev); - if (ret) { - MHI_ERR("Error enabling device, ret:%d\n", ret); - goto error_enable_device; - } - - ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi"); - if (ret) { - MHI_ERR("Error pci_request_region, ret:%d\n", ret); - goto error_request_region; - } - - pci_set_master(pci_dev); - - start = pci_resource_start(pci_dev, mhi_dev->resn); - len = pci_resource_len(pci_dev, mhi_dev->resn); - mhi_cntrl->regs = ioremap_nocache(start, len); - MHI_LOG("mhi_cntrl->regs = %p\n", mhi_cntrl->regs); - if (!mhi_cntrl->regs) { - MHI_ERR("Error ioremap region\n"); - goto error_ioremap; - } - - ret = pci_alloc_irq_vectors(pci_dev, 1, mhi_cntrl->msi_required, PCI_IRQ_MSI); - if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) { - if (ret == -ENOSPC) { - /* imx_3.14.52_1.1.0_ga - diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c - index f06e8f0..6a9614f 100644 - --- a/drivers/pci/host/pcie-designware.c - +++ b/drivers/pci/host/pcie-designware.c - @@ -376,6 +376,13 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, - if (msgvec > 5) - msgvec = 0; - - +#if 1 //Add by Quectel 20190419 - + if (msgvec > 0 && pdev->vendor == 0x17cb) { - + dev_info(&pdev->dev, "%s quectel fixup pos=%d, msg_ctr=%04x, msgvec=%d\n", __func__, desc->msi_attrib.pos, msg_ctr, msgvec); - + msgvec = 0; - + } - +#endif - + - irq = assign_irq((1 << msgvec), desc, &pos); - if (irq < 0) - return irq; - */ - } - //imx_4.1.15_2.0.0_ga & DELL_OPTIPLEX_7010 only alloc one msi interrupt for one pcie device - if (ret != 1) { - MHI_ERR("Failed to enable MSI, ret=%d, msi_required=%d\n", ret, mhi_cntrl->msi_required); - goto error_req_msi; - } - } - - mhi_cntrl->msi_allocated = ret; - MHI_LOG("msi_required = %d, msi_allocated = %d, msi_irq = %u\n", mhi_cntrl->msi_required, mhi_cntrl->msi_allocated, pci_dev->irq); - - for (i = 0; i < mhi_cntrl->msi_allocated; i++) { - mhi_cntrl->irq[i] = pci_irq_vector(pci_dev, i); - if (mhi_cntrl->irq[i] < 0) { - ret = mhi_cntrl->irq[i]; - goto error_get_irq_vec; - } - } - -#if 0 - /* configure runtime pm */ - pm_runtime_set_autosuspend_delay(&pci_dev->dev, MHI_RPM_SUSPEND_TMR_MS); - pm_runtime_dont_use_autosuspend(&pci_dev->dev); - pm_suspend_ignore_children(&pci_dev->dev, true); - - /* - * pci framework will increment usage count (twice) before - * calling local device driver probe function. - * 1st pci.c pci_pm_init() calls pm_runtime_forbid - * 2nd pci-driver.c local_pci_probe calls pm_runtime_get_sync - * Framework expect pci device driver to call - * pm_runtime_put_noidle to decrement usage count after - * successful probe and and call pm_runtime_allow to enable - * runtime suspend. - */ - pm_runtime_mark_last_busy(&pci_dev->dev); - pm_runtime_put_noidle(&pci_dev->dev); -#endif - - return 0; - -error_get_irq_vec: - pci_free_irq_vectors(pci_dev); - -error_req_msi: - iounmap(mhi_cntrl->regs); - -error_ioremap: - pci_clear_master(pci_dev); - -error_request_region: - pci_disable_device(pci_dev); - -error_enable_device: - pci_release_region(pci_dev, mhi_dev->resn); - - return ret; -} - -#ifdef CONFIG_PM -static int mhi_runtime_idle(struct device *dev) -{ - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - MHI_LOG("Entered returning -EBUSY\n"); - - /* - * RPM framework during runtime resume always calls - * rpm_idle to see if device ready to suspend. - * If dev.power usage_count count is 0, rpm fw will call - * rpm_idle cb to see if device is ready to suspend. - * if cb return 0, or cb not defined the framework will - * assume device driver is ready to suspend; - * therefore, fw will schedule runtime suspend. - * In MHI power management, MHI host shall go to - * runtime suspend only after entering MHI State M2, even if - * usage count is 0. Return -EBUSY to disable automatic suspend. - */ - return -EBUSY; -} - -static int mhi_runtime_suspend(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - MHI_LOG("Enter\n"); - - mutex_lock(&mhi_cntrl->pm_mutex); - - ret = mhi_pm_suspend(mhi_cntrl); - if (ret) { - MHI_LOG("Abort due to ret:%d\n", ret); - goto exit_runtime_suspend; - } - - ret = mhi_arch_link_off(mhi_cntrl, true); - if (ret) - MHI_ERR("Failed to Turn off link ret:%d\n", ret); - -exit_runtime_suspend: - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Exited with ret:%d\n", ret); - - return ret; -} - -static int mhi_runtime_resume(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Enter\n"); - - mutex_lock(&mhi_cntrl->pm_mutex); - - if (!mhi_dev->powered_on) { - MHI_LOG("Not fully powered, return success\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return 0; - } - - /* turn on link */ - ret = mhi_arch_link_on(mhi_cntrl); - if (ret) - goto rpm_resume_exit; - - /* enter M0 state */ - ret = mhi_pm_resume(mhi_cntrl); - -rpm_resume_exit: - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Exited with :%d\n", ret); - - return ret; -} - -static int mhi_system_resume(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - ret = mhi_runtime_resume(dev); - if (ret) { - MHI_ERR("Failed to resume link\n"); - } else { - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - - return ret; -} - -int mhi_system_suspend(struct device *dev) -{ - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - MHI_LOG("Entered\n"); - - /* if rpm status still active then force suspend */ - if (!pm_runtime_status_suspended(dev)) - return mhi_runtime_suspend(dev); - - pm_runtime_set_suspended(dev); - pm_runtime_disable(dev); - - MHI_LOG("Exit\n"); - return 0; -} -#endif - -/* checks if link is down */ -static int mhi_link_status(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - u16 dev_id; - int ret; - - /* try reading device id, if dev id don't match, link is down */ - ret = pci_read_config_word(mhi_dev->pci_dev, PCI_DEVICE_ID, &dev_id); - - return (ret || dev_id != mhi_cntrl->dev_id) ? -EIO : 0; -} - -static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - return pm_runtime_get(dev); -} - -static void mhi_runtime_put(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - pm_runtime_put_noidle(dev); -} - -static void mhi_status_cb(struct mhi_controller *mhi_cntrl, - void *priv, - enum MHI_CB reason) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - if (reason == MHI_CB_IDLE) { - MHI_LOG("Schedule runtime suspend 1\n"); - pm_runtime_mark_last_busy(dev); - pm_request_autosuspend(dev); - } -} - -int mhi_debugfs_trigger_m0(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Trigger M3 Exit\n"); - pm_runtime_get(&mhi_dev->pci_dev->dev); - pm_runtime_put(&mhi_dev->pci_dev->dev); - - return 0; -} - -int mhi_debugfs_trigger_m3(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Trigger M3 Entry\n"); - pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev); - pm_request_autosuspend(&mhi_dev->pci_dev->dev); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m0_fops, NULL, - mhi_debugfs_trigger_m0, "%llu\n"); - -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m3_fops, NULL, - mhi_debugfs_trigger_m3, "%llu\n"); - -static int mhi_init_debugfs_trigger_go(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - - MHI_LOG("Trigger power up sequence\n"); - - mhi_async_power_up(mhi_cntrl); - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(mhi_init_debugfs_trigger_go_fops, NULL, - mhi_init_debugfs_trigger_go, "%llu\n"); - - -int mhi_init_debugfs_debug_show(struct seq_file *m, void *d) -{ - seq_puts(m, "Enable debug mode to debug external soc\n"); - seq_puts(m, - "Usage: echo 'devid,timeout,domain,smmu_cfg' > debug_mode\n"); - seq_puts(m, "No spaces between parameters\n"); - seq_puts(m, "\t1. devid : 0 or pci device id to register\n"); - seq_puts(m, "\t2. timeout: mhi cmd/state transition timeout\n"); - seq_puts(m, "\t3. domain: Rootcomplex\n"); - seq_puts(m, "\t4. smmu_cfg: smmu configuration mask:\n"); - seq_puts(m, "\t\t- BIT0: ATTACH\n"); - seq_puts(m, "\t\t- BIT1: S1 BYPASS\n"); - seq_puts(m, "\t\t-BIT2: FAST_MAP\n"); - seq_puts(m, "\t\t-BIT3: ATOMIC\n"); - seq_puts(m, "\t\t-BIT4: FORCE_COHERENT\n"); - seq_puts(m, "\t\t-BIT5: GEOMETRY\n"); - seq_puts(m, "\tAll timeout are in ms, enter 0 to keep default\n"); - seq_puts(m, "Examples inputs: '0x307,10000'\n"); - seq_puts(m, "\techo '0,10000,1'\n"); - seq_puts(m, "\techo '0x307,10000,0,0x3d'\n"); - seq_puts(m, "firmware image name will be changed to debug.mbn\n"); - - return 0; -} - -static int mhi_init_debugfs_debug_open(struct inode *node, struct file *file) -{ - return single_open(file, mhi_init_debugfs_debug_show, NULL); -} - -static ssize_t mhi_init_debugfs_debug_write(struct file *fp, - const char __user *ubuf, - size_t count, - loff_t *pos) -{ - char *buf = kmalloc(count + 1, GFP_KERNEL); - /* #,devid,timeout,domain,smmu-cfg */ - int args[5] = {0}; - static char const *dbg_fw = "debug.mbn"; - int ret; - struct mhi_controller *mhi_cntrl = fp->f_inode->i_private; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_device_id *id; - - if (!buf) - return -ENOMEM; - - ret = copy_from_user(buf, ubuf, count); - if (ret) - goto error_read; - buf[count] = 0; - get_options(buf, ARRAY_SIZE(args), args); - kfree(buf); - - /* override default parameters */ - mhi_cntrl->fw_image = dbg_fw; - mhi_cntrl->edl_image = dbg_fw; - - if (args[0] >= 2 && args[2]) - mhi_cntrl->timeout_ms = args[2]; - - if (args[0] >= 3 && args[3]) - mhi_cntrl->domain = args[3]; - - if (args[0] >= 4 && args[4]) - mhi_dev->smmu_cfg = args[4]; - - /* If it's a new device id register it */ - if (args[0] && args[1]) { - /* find the debug_id and overwrite it */ - for (id = mhi_pcie_device_id; id->vendor; id++) - if (id->device == MHI_PCIE_DEBUG_ID) { - id->device = args[1]; - pci_unregister_driver(&mhi_pcie_driver); - ret = pci_register_driver(&mhi_pcie_driver); - } - } - - mhi_dev->debug_mode = true; - debugfs_create_file("go", 0444, mhi_cntrl->parent, mhi_cntrl, - &mhi_init_debugfs_trigger_go_fops); - pr_info( - "%s: ret:%d pcidev:0x%x smm_cfg:%u timeout:%u\n", - __func__, ret, args[1], mhi_dev->smmu_cfg, - mhi_cntrl->timeout_ms); - return count; - -error_read: - kfree(buf); - return ret; -} - -static const struct file_operations debugfs_debug_ops = { - .open = mhi_init_debugfs_debug_open, - .release = single_release, - .read = seq_read, - .write = mhi_init_debugfs_debug_write, -}; - -static struct mhi_controller * mhi_platform_probe(struct pci_dev *pci_dev) -{ - struct mhi_controller *mhi_cntrl; - struct mhi_dev *mhi_dev; - u64 addr_win[2]; - int ret; - - mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev)); - if (!mhi_cntrl) { - pr_err("mhi_alloc_controller fail\n"); - return NULL; - } - - mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev_id = pci_dev->device; - mhi_cntrl->domain = pci_domain_nr(pci_dev->bus); - mhi_cntrl->bus = pci_dev->bus->number; - mhi_cntrl->slot = PCI_SLOT(pci_dev->devfn); - mhi_dev->smmu_cfg = 0; - #if 0 //def CONFIG_HAVE_MEMBLOCK - addr_win[0] = memblock_start_of_DRAM(); - addr_win[1] = memblock_end_of_DRAM(); - #else -#define MHI_MEM_BASE_DEFAULT 0x000000000 -#define MHI_MEM_SIZE_DEFAULT 0x2000000000 - addr_win[0] = MHI_MEM_BASE_DEFAULT; - addr_win[1] = MHI_MEM_SIZE_DEFAULT; - if (sizeof(dma_addr_t) == 4) { - addr_win[1] = 0xFFFFFFFF; - } - #endif - - mhi_cntrl->iova_start = addr_win[0]; - mhi_cntrl->iova_stop = addr_win[1]; - - mhi_dev->pci_dev = pci_dev; - mhi_cntrl->pci_dev = pci_dev; - - /* setup power management apis */ - mhi_cntrl->status_cb = mhi_status_cb; - mhi_cntrl->runtime_get = mhi_runtime_get; - mhi_cntrl->runtime_put = mhi_runtime_put; - mhi_cntrl->link_status = mhi_link_status; - - ret = mhi_arch_platform_init(mhi_dev); - if (ret) - goto error_probe; - - ret = mhi_register_mhi_controller(mhi_cntrl); - if (ret) - goto error_register; - - if (mhi_cntrl->parent) - debugfs_create_file("debug_mode", 0444, mhi_cntrl->parent, - mhi_cntrl, &debugfs_debug_ops); - - return mhi_cntrl; - -error_register: - mhi_arch_platform_deinit(mhi_dev); - -error_probe: - mhi_free_controller(mhi_cntrl); - - return NULL; -} - -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id) -{ - struct mhi_controller *mhi_cntrl = NULL; - u32 domain = pci_domain_nr(pci_dev->bus); - u32 bus = pci_dev->bus->number; - u32 slot = PCI_SLOT(pci_dev->devfn); - struct mhi_dev *mhi_dev; - int ret; - - pr_info("%s pci_dev->name = %s, domain=%d, bus=%d, slot=%d, vendor=%04X, device=%04X\n", - __func__, dev_name(&pci_dev->dev), domain, bus, slot, pci_dev->vendor, pci_dev->device); - - mhi_cntrl = mhi_platform_probe(pci_dev); - if (!mhi_cntrl) { - pr_err("mhi_platform_probe fail\n"); - return -EPROBE_DEFER; - } - - mhi_cntrl->dev_id = pci_dev->device; - mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - mhi_dev->pci_dev = pci_dev; - mhi_dev->powered_on = true; - - ret = mhi_arch_pcie_init(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_arch_pcie_init, ret:%d\n", ret); - return ret; - } - - ret = mhi_arch_iommu_init(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_arch_iommu_init, ret:%d\n", ret); - goto error_iommu_init; - } - - ret = mhi_init_pci_dev(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_init_pci_dev, ret:%d\n", ret); - goto error_init_pci; - } - - /* start power up sequence if not in debug mode */ - if (!mhi_dev->debug_mode) { - ret = mhi_async_power_up(mhi_cntrl); - if (ret) { - MHI_ERR("Error mhi_async_power_up, ret:%d\n", ret); - goto error_power_up; - } - } - -#if 0 - pm_runtime_mark_last_busy(&pci_dev->dev); - pm_runtime_allow(&pci_dev->dev); - pm_runtime_disable(&pci_dev->dev); -#endif - - if (mhi_cntrl->dentry) { - debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl, - &debugfs_trigger_m0_fops); - debugfs_create_file("m3", 0444, mhi_cntrl->dentry, mhi_cntrl, - &debugfs_trigger_m3_fops); - } - - dev_set_drvdata(&pci_dev->dev, mhi_cntrl); - MHI_LOG("Return successful\n"); - - return 0; - -error_power_up: - mhi_deinit_pci_dev(mhi_cntrl); - -error_init_pci: - mhi_arch_iommu_deinit(mhi_cntrl); - -error_iommu_init: - mhi_arch_pcie_deinit(mhi_cntrl); - - return ret; -} - -static void mhi_pci_remove(struct pci_dev *pci_dev) -{ - struct mhi_controller *mhi_cntrl = (struct mhi_controller *)dev_get_drvdata(&pci_dev->dev); - - if (mhi_cntrl && mhi_cntrl->pci_dev == pci_dev) { - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - MHI_LOG("%s\n", dev_name(&pci_dev->dev)); - if (!mhi_dev->debug_mode) { - mhi_power_down(mhi_cntrl, 1); - } - mhi_deinit_pci_dev(mhi_cntrl); - mhi_arch_iommu_deinit(mhi_cntrl); - mhi_arch_pcie_deinit(mhi_cntrl); - mhi_unregister_mhi_controller(mhi_cntrl); - } -} - -static const struct dev_pm_ops pm_ops = { - SET_RUNTIME_PM_OPS(mhi_runtime_suspend, - mhi_runtime_resume, - mhi_runtime_idle) - SET_SYSTEM_SLEEP_PM_OPS(mhi_system_suspend, mhi_system_resume) -}; - -static struct pci_driver mhi_pcie_driver = { - .name = "mhi", - .id_table = mhi_pcie_device_id, - .probe = mhi_pci_probe, - .remove = mhi_pci_remove, - .driver = { - .pm = &pm_ops - } -}; - -int __init mhi_controller_qcom_init(void) -{ - return pci_register_driver(&mhi_pcie_driver); -}; - -void mhi_controller_qcom_exit(void) -{ - pr_info("%s enter\n", __func__); - pci_unregister_driver(&mhi_pcie_driver); - pr_info("%s exit\n", __func__); -} diff --git a/quectel_MHI/src/controllers/mhi_qcom.h b/quectel_MHI/src/controllers/mhi_qcom.h deleted file mode 100644 index 65ec5b8..0000000 --- a/quectel_MHI/src/controllers/mhi_qcom.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _MHI_QCOM_ -#define _MHI_QCOM_ - -/* iova cfg bitmask */ -#define MHI_SMMU_ATTACH BIT(0) -#define MHI_SMMU_S1_BYPASS BIT(1) -#define MHI_SMMU_FAST BIT(2) -#define MHI_SMMU_ATOMIC BIT(3) -#define MHI_SMMU_FORCE_COHERENT BIT(4) - -#define MHI_PCIE_VENDOR_ID (0x17cb) -#define MHI_PCIE_DEBUG_ID (0xffff) -#define MHI_RPM_SUSPEND_TMR_MS (3000) -#define MHI_PCI_BAR_NUM (0) - -struct mhi_dev { - struct pci_dev *pci_dev; - u32 smmu_cfg; - int resn; - void *arch_info; - bool powered_on; - bool debug_mode; -}; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl); -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 )) -static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) -{ - int rc = dma_set_mask(dev, mask); - if (rc == 0) - dma_set_coherent_mask(dev, mask); - return rc; -} -#endif - -static inline int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev = &mhi_dev->pci_dev->dev; - - return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64)); -} - -static inline void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -static inline void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) -{ -} - -static inline int mhi_arch_platform_init(struct mhi_dev *mhi_dev) -{ - return 0; -} - -static inline void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev) -{ -} - -static inline int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, - bool graceful) -{ - return 0; -} - -static inline int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) -{ - return 0; -} - -#endif /* _MHI_QCOM_ */ diff --git a/quectel_MHI/src/controllers/mhi_qti.c b/quectel_MHI/src/controllers/mhi_qti.c deleted file mode 100644 index 4a064a7..0000000 --- a/quectel_MHI/src/controllers/mhi_qti.c +++ /dev/null @@ -1,1306 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define MAX_MHI 8 -#ifdef CONFIG_PCI_MSM -#define QCOM_AP_AND_EFUSE_PCIE_SLEEP -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP -#include -#include -#endif -#endif -//#define QCOM_AP_SDM845_IOMMU_MAP -#ifdef QCOM_AP_SDM845_IOMMU_MAP -#include -#include -#include -#endif -#include "../core/mhi.h" -#include "../core/mhi_internal.h" -#include "mhi_qti.h" - -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP -extern int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val); -struct arch_info { - struct mhi_dev *mhi_dev; - struct msm_bus_scale_pdata *msm_bus_pdata; - u32 bus_client; - struct pci_saved_state *pcie_state; - struct pci_saved_state *ref_pcie_state; - struct dma_iommu_mapping *mapping; -}; -#endif - -#if 1 -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 )) -static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) -{ - int rc = dma_set_mask(dev, mask); - if (rc == 0) - dma_set_coherent_mask(dev, mask); - return rc; -} -#endif - -#ifdef PCI_IRQ_NOMSIX -#define PCI_IRQ_MSI PCI_IRQ_NOMSIX -#endif - -#ifndef PCI_IRQ_MSI -#define PCI_IRQ_MSI (1 << 1) /* Allow MSI interrupts */ - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,53 )) -int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) -{ - int nvec = maxvec; - int rc; - - if (maxvec < minvec) - return -ERANGE; - - do { - rc = pci_enable_msi_block(dev, nvec); - if (rc < 0) { - return rc; - } else if (rc > 0) { - if (rc < minvec) - return -ENOSPC; - nvec = rc; - } - } while (rc); - - return nvec; -} -#endif - -static int pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs, - unsigned int max_vecs, unsigned int flags) -{ - return pci_enable_msi_range(dev, min_vecs, max_vecs); -} - -static void pci_free_irq_vectors(struct pci_dev *dev) -{ - pci_disable_msi(dev); -} - -static int pci_irq_vector(struct pci_dev *dev, unsigned int nr) -{ -#if 0//defined(CONFIG_PINCTRL_IPQ5018) - struct pcie_port *pp = dev->bus->sysdata; - pp->msi[nr]; //msi maybe not continuous -#endif - return dev->irq + nr; -} -#endif -#endif - -struct firmware_info { - unsigned int dev_id; - const char *fw_image; - const char *edl_image; -}; - -static const struct firmware_info firmware_table[] = { - {.dev_id = 0x306, .fw_image = "sdx55m/sbl1.mbn"}, - {.dev_id = 0x305, .fw_image = "sdx50m/sbl1.mbn"}, - {.dev_id = 0x304, .fw_image = "sbl.mbn", .edl_image = "edl.mbn"}, - /* default, set to debug.mbn */ - {.fw_image = "debug.mbn"}, -}; - -static int debug_mode; -module_param_named(debug_mode, debug_mode, int, 0644); - -int mhi_debugfs_trigger_m0(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Trigger M3 Exit\n"); - pm_runtime_get(&mhi_dev->pci_dev->dev); - pm_runtime_put(&mhi_dev->pci_dev->dev); - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m0_fops, NULL, - mhi_debugfs_trigger_m0, "%llu\n"); - -int mhi_debugfs_trigger_m3(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Trigger M3 Entry\n"); - pm_runtime_mark_last_busy(&mhi_dev->pci_dev->dev); - pm_request_autosuspend(&mhi_dev->pci_dev->dev); - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_m3_fops, NULL, - mhi_debugfs_trigger_m3, "%llu\n"); - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_dev *pci_dev = mhi_dev->pci_dev; - - pm_runtime_mark_last_busy(&pci_dev->dev); - pm_runtime_dont_use_autosuspend(&pci_dev->dev); - pm_runtime_disable(&pci_dev->dev); - pci_free_irq_vectors(pci_dev); - kfree(mhi_cntrl->irq); - mhi_cntrl->irq = NULL; - iounmap(mhi_cntrl->regs); - mhi_cntrl->regs = NULL; - pci_clear_master(pci_dev); - pci_release_region(pci_dev, mhi_dev->resn); - pci_disable_device(pci_dev); -} - -static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - resource_size_t len; - int i; - - mhi_dev->resn = MHI_PCI_BAR_NUM; - ret = pci_assign_resource(pci_dev, mhi_dev->resn); - if (ret) { - MHI_ERR("Error assign pci resources, ret:%d\n", ret); - return ret; - } - - ret = pci_enable_device(pci_dev); - if (ret) { - MHI_ERR("Error enabling device, ret:%d\n", ret); - goto error_enable_device; - } - - ret = pci_request_region(pci_dev, mhi_dev->resn, "mhi"); - if (ret) { - MHI_ERR("Error pci_request_region, ret:%d\n", ret); - goto error_request_region; - } - - pci_set_master(pci_dev); - -#if 1 //some SOC like rpi_4b need next codes - ret = -EIO; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) - if (!dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64))) { - ret = dma_set_coherent_mask(&pci_dev->dev, DMA_BIT_MASK(64)); - } else if (!dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { - ret = dma_set_coherent_mask(&pci_dev->dev, DMA_BIT_MASK(32)); - } -#else - if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) { - ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(64)); - } else if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) { - ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(32)); - } -#endif - if (ret) { - MHI_ERR("Error dma mask\n"); - } -#endif - - mhi_cntrl->base_addr = pci_resource_start(pci_dev, mhi_dev->resn); - len = pci_resource_len(pci_dev, mhi_dev->resn); -#ifndef ioremap_nocache //4bdc0d676a643140bdf17dbf7eafedee3d496a3c -#define ioremap_nocache ioremap -#endif - mhi_cntrl->regs = ioremap_nocache(mhi_cntrl->base_addr, len); - if (!mhi_cntrl->regs) { - MHI_ERR("Error ioremap region\n"); - goto error_ioremap; - } - -#if 0 - ret = pci_alloc_irq_vectors(pci_dev, mhi_cntrl->msi_required, - mhi_cntrl->msi_required, PCI_IRQ_NOMSIX); - if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) { - MHI_ERR("Failed to enable MSI, ret:%d\n", ret); - goto error_req_msi; - } -#else - ret = pci_alloc_irq_vectors(pci_dev, 1, mhi_cntrl->msi_required, PCI_IRQ_MSI); - if (IS_ERR_VALUE((ulong)ret) || ret < mhi_cntrl->msi_required) { - if (ret == -ENOSPC) { - /* imx_3.14.52_1.1.0_ga - diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c - index f06e8f0..6a9614f 100644 - --- a/drivers/pci/host/pcie-designware.c - +++ b/drivers/pci/host/pcie-designware.c - @@ -376,6 +376,13 @@ static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, - if (msgvec > 5) - msgvec = 0; - - +#if 1 //Add by Quectel 20190419 - + if (msgvec > 0 && pdev->vendor == 0x17cb) { - + dev_info(&pdev->dev, "%s quectel fixup pos=%d, msg_ctr=%04x, msgvec=%d\n", __func__, desc->msi_attrib.pos, msg_ctr, msgvec); - + msgvec = 0; - + } - +#endif - + - irq = assign_irq((1 << msgvec), desc, &pos); - if (irq < 0) - return irq; - */ - } - //imx_4.1.15_2.0.0_ga & DELL_OPTIPLEX_7010 only alloc one msi interrupt for one pcie device - if (ret != 1) { - MHI_ERR("Failed to enable MSI, ret=%d, msi_required=%d\n", ret, mhi_cntrl->msi_required); - goto error_req_msi; - } - } - MHI_LOG("msi_required = %d, msi_allocated = %d, msi_irq = %u\n", mhi_cntrl->msi_required, ret, pci_dev->irq); -#endif - - mhi_cntrl->msi_allocated = ret; - mhi_cntrl->irq = kmalloc_array(mhi_cntrl->msi_allocated, - sizeof(*mhi_cntrl->irq), GFP_KERNEL); - if (!mhi_cntrl->irq) { - ret = -ENOMEM; - goto error_alloc_msi_vec; - } - - for (i = 0; i < mhi_cntrl->msi_allocated; i++) { - mhi_cntrl->irq[i] = pci_irq_vector(pci_dev, i); - if (mhi_cntrl->irq[i] < 0) { - ret = mhi_cntrl->irq[i]; - goto error_get_irq_vec; - } - } - - dev_set_drvdata(&pci_dev->dev, mhi_cntrl); - - /* configure runtime pm */ - pm_runtime_set_autosuspend_delay(&pci_dev->dev, MHI_RPM_SUSPEND_TMR_MS); - pm_runtime_use_autosuspend(&pci_dev->dev); - pm_suspend_ignore_children(&pci_dev->dev, true); - - /* - * pci framework will increment usage count (twice) before - * calling local device driver probe function. - * 1st pci.c pci_pm_init() calls pm_runtime_forbid - * 2nd pci-driver.c local_pci_probe calls pm_runtime_get_sync - * Framework expect pci device driver to call - * pm_runtime_put_noidle to decrement usage count after - * successful probe and and call pm_runtime_allow to enable - * runtime suspend. - */ - pm_runtime_mark_last_busy(&pci_dev->dev); - pm_runtime_put_noidle(&pci_dev->dev); - - return 0; - -error_get_irq_vec: - kfree(mhi_cntrl->irq); - mhi_cntrl->irq = NULL; - -error_alloc_msi_vec: - pci_free_irq_vectors(pci_dev); - -error_req_msi: - iounmap(mhi_cntrl->regs); - -error_ioremap: - pci_clear_master(pci_dev); - -error_request_region: - pci_disable_device(pci_dev); - -error_enable_device: - pci_release_region(pci_dev, mhi_dev->resn); - - return ret; -} - -#ifdef CONFIG_PM -static int mhi_runtime_suspend(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Enter\n"); - - mutex_lock(&mhi_cntrl->pm_mutex); - - if (!mhi_dev->powered_on) { - MHI_LOG("Not fully powered, return success\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return 0; - } - - if (mhi_cntrl->ee != MHI_EE_AMSS) { - MHI_LOG("Not AMSS, return busy\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return -EBUSY; - } - - ret = mhi_pm_suspend(mhi_cntrl); - if (ret) { - MHI_LOG("Abort due to ret:%d\n", ret); - goto exit_runtime_suspend; - } - - ret = mhi_arch_link_off(mhi_cntrl, true); - if (ret) - MHI_ERR("Failed to Turn off link ret:%d\n", ret); - -exit_runtime_suspend: - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Exited with ret:%d\n", ret); - - return ret; -} - -static int mhi_runtime_idle(struct device *dev) -{ - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - if ((mhi_cntrl->dev_state == MHI_STATE_M0 || mhi_cntrl->dev_state == MHI_STATE_M3) - && mhi_cntrl->ee == MHI_EE_AMSS) { - return 0; - } - MHI_LOG("Entered returning -EBUSY, mhi_state:%s exec_env:%s\n", - TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl)), TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl))); - - /* - * RPM framework during runtime resume always calls - * rpm_idle to see if device ready to suspend. - * If dev.power usage_count count is 0, rpm fw will call - * rpm_idle cb to see if device is ready to suspend. - * if cb return 0, or cb not defined the framework will - * assume device driver is ready to suspend; - * therefore, fw will schedule runtime suspend. - * In MHI power management, MHI host shall go to - * runtime suspend only after entering MHI State M2, even if - * usage count is 0. Return -EBUSY to disable automatic suspend. - */ - return -EBUSY; -} - -static int mhi_runtime_resume(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - MHI_LOG("Enter\n"); - - mutex_lock(&mhi_cntrl->pm_mutex); - - if (!mhi_dev->powered_on) { - MHI_LOG("Not fully powered, return success\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return 0; - } - - /* turn on link */ - ret = mhi_arch_link_on(mhi_cntrl); - if (ret) - goto rpm_resume_exit; - - /* enter M0 state */ - ret = mhi_pm_resume(mhi_cntrl); - -rpm_resume_exit: - mutex_unlock(&mhi_cntrl->pm_mutex); - MHI_LOG("Exited with :%d\n", ret); - - return ret; -} - -static int mhi_system_resume(struct device *dev) -{ - int ret = 0; - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - - ret = mhi_runtime_resume(dev); - if (ret) { - MHI_ERR("Failed to resume link\n"); - } else { - //pm_runtime_set_active(dev); - //pm_runtime_enable(dev); - } - - return ret; -} - -int mhi_system_suspend(struct device *dev) -{ - struct mhi_controller *mhi_cntrl = dev_get_drvdata(dev); - int ret; - - MHI_LOG("Entered\n"); - - if (atomic_read(&mhi_cntrl->pending_pkts)) { - MHI_LOG("Abort due to pending_pkts:%d\n", atomic_read(&mhi_cntrl->pending_pkts)); - return -EBUSY; - } - - /* if rpm status still active then force suspend */ - if (!pm_runtime_status_suspended(dev)) { - ret = mhi_runtime_suspend(dev); - if (ret) { - MHI_LOG("suspend failed ret:%d\n", ret); - return ret; - } - } - - //pm_runtime_set_suspended(dev); - //pm_runtime_disable(dev); - - MHI_LOG("Exit\n"); - return 0; -} -#endif - -/* checks if link is down */ -static int mhi_link_status(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - u16 dev_id; - int ret; - - /* try reading device id, if dev id don't match, link is down */ - ret = pci_read_config_word(mhi_dev->pci_dev, PCI_DEVICE_ID, &dev_id); - - return (ret || dev_id != mhi_cntrl->dev_id) ? -EIO : 0; -} - -/* disable PCIe L1 */ -static int mhi_lpm_disable(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int lnkctl = pci_dev->pcie_cap + PCI_EXP_LNKCTL; - u8 val; - int ret; - - ret = pci_read_config_byte(pci_dev, lnkctl, &val); - if (ret) { - MHI_ERR("Error reading LNKCTL, ret:%d\n", ret); - return ret; - } - - /* L1 is not supported or already disabled */ - if (!(val & PCI_EXP_LNKCTL_ASPM_L1)) - return 0; - - val &= ~PCI_EXP_LNKCTL_ASPM_L1; - ret = pci_write_config_byte(pci_dev, lnkctl, val); - if (ret) { - MHI_ERR("Error writing LNKCTL to disable LPM, ret:%d\n", ret); - return ret; - } - - mhi_dev->lpm_disabled = true; - - return ret; -} - -/* enable PCIe L1 */ -static int mhi_lpm_enable(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int lnkctl = pci_dev->pcie_cap + PCI_EXP_LNKCTL; - u8 val; - int ret; - - /* L1 is not supported or already disabled */ - if (!mhi_dev->lpm_disabled) - return 0; - - ret = pci_read_config_byte(pci_dev, lnkctl, &val); - if (ret) { - MHI_ERR("Error reading LNKCTL, ret:%d\n", ret); - return ret; - } - - val |= PCI_EXP_LNKCTL_ASPM_L1; - ret = pci_write_config_byte(pci_dev, lnkctl, val); - if (ret) { - MHI_ERR("Error writing LNKCTL to enable LPM, ret:%d\n", ret); - return ret; - } - - mhi_dev->lpm_disabled = false; - - return ret; -} - -static int mhi_power_up(struct mhi_controller *mhi_cntrl) -{ - enum mhi_dev_state dev_state = mhi_get_mhi_state(mhi_cntrl); - const u32 delayus = 10; - int itr = DIV_ROUND_UP(mhi_cntrl->timeout_ms * 1000, delayus); - int ret; - - MHI_LOG("dev_state:%s\n", TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); - - /* - * It's possible device did not go thru a cold reset before - * power up and still in error state. If device in error state, - * we need to trigger a soft reset before continue with power - * up - */ - if (dev_state == MHI_STATE_SYS_ERR) { - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); - while (itr--) { - dev_state = mhi_get_mhi_state(mhi_cntrl); - if (dev_state != MHI_STATE_SYS_ERR) - break; - usleep_range(delayus, delayus << 1); - } - MHI_LOG("dev_state:%s\n", TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); - - /* device still in error state, abort power up */ - if (dev_state == MHI_STATE_SYS_ERR) - return -EIO; - } - - ret = mhi_async_power_up(mhi_cntrl); - - /* power up create the dentry */ - if (mhi_cntrl->dentry) { - debugfs_create_file("m0", 0444, mhi_cntrl->dentry, mhi_cntrl, - &debugfs_trigger_m0_fops); - debugfs_create_file("m3", 0444, mhi_cntrl->dentry, mhi_cntrl, - &debugfs_trigger_m3_fops); - } - - return ret; -} - -static int mhi_runtime_get(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - return pm_runtime_get(dev); -} - -static void mhi_runtime_put(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - pm_runtime_mark_last_busy(dev); - pm_runtime_put(dev); -} - -static void mhi_runtime_mark_last_busy(struct mhi_controller *mhi_cntrl, void *priv) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - pm_runtime_mark_last_busy(dev); -} - -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP -static void mhi_pci_event_cb(struct msm_pcie_notify *notify) -{ - struct pci_dev *pci_dev = notify->user; - struct device *dev = &pci_dev->dev; - - dev_info(&pci_dev->dev, "Received PCIe event %d", notify->event); - switch (notify->event) { - case MSM_PCIE_EVENT_WAKEUP: - if (dev && pm_runtime_status_suspended(dev)) { - pm_request_resume(dev); - pm_runtime_mark_last_busy(dev); - } - break; - default: - break; - } -} - -static struct msm_pcie_register_event mhi_pcie_events[MAX_MHI]; -#endif - -static void mhi_status_cb(struct mhi_controller *mhi_cntrl, - void *priv, - enum MHI_CB reason) -{ - struct mhi_dev *mhi_dev = priv; - struct device *dev = &mhi_dev->pci_dev->dev; - - switch (reason) { - case MHI_CB_FATAL_ERROR: - case MHI_CB_SYS_ERROR: - pm_runtime_forbid(dev); - break; - case MHI_CB_EE_MISSION_MODE: - //pm_runtime_allow(dev); - break; - default: - break; - } -} - -/* capture host SoC XO time in ticks */ -static u64 mhi_time_get(struct mhi_controller *mhi_cntrl, void *priv) -{ - return 0; -} - -static ssize_t timeout_ms_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - /* buffer provided by sysfs has a minimum size of PAGE_SIZE */ - return snprintf(buf, PAGE_SIZE, "%u\n", mhi_cntrl->timeout_ms); -} - -static ssize_t timeout_ms_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - u32 timeout_ms; - - if (kstrtou32(buf, 0, &timeout_ms) < 0) - return -EINVAL; - - mhi_cntrl->timeout_ms = timeout_ms; - - return count; -} -static DEVICE_ATTR_RW(timeout_ms); - -static ssize_t power_up_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int ret; - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - ret = mhi_power_up(mhi_cntrl); - if (ret) - return ret; - - return count; -} -static DEVICE_ATTR_WO(power_up); - -static struct attribute *mhi_attrs[] = { - &dev_attr_timeout_ms.attr, - &dev_attr_power_up.attr, - NULL -}; - -static const struct attribute_group mhi_group = { - .attrs = mhi_attrs, -}; - -static struct mhi_controller *mhi_register_controller(struct pci_dev *pci_dev) -{ - struct mhi_controller *mhi_cntrl; - struct mhi_dev *mhi_dev; - struct device_node *of_node = pci_dev->dev.of_node; - const struct firmware_info *firmware_info; - bool use_bb; - u64 addr_win[2]; - int ret, i; - - //if (!of_node) - // return ERR_PTR(-ENODEV); - - mhi_cntrl = mhi_alloc_controller(sizeof(*mhi_dev)); - if (!mhi_cntrl) - return ERR_PTR(-ENOMEM); - - mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_cntrl->dev = &pci_dev->dev; - mhi_cntrl->domain = pci_domain_nr(pci_dev->bus); - mhi_cntrl->vendor = pci_dev->vendor; - mhi_cntrl->dev_id = pci_dev->device; - mhi_cntrl->bus = pci_dev->bus->number; - mhi_cntrl->slot = PCI_SLOT(pci_dev->devfn); - -#if 0 - use_bb = of_property_read_bool(of_node, "mhi,use-bb"); - - /* - * if s1 translation enabled or using bounce buffer pull iova addr - * from dt - */ - if (use_bb || (mhi_dev->smmu_cfg & MHI_SMMU_ATTACH && - !(mhi_dev->smmu_cfg & MHI_SMMU_S1_BYPASS))) { - ret = of_property_count_elems_of_size(of_node, "qti,addr-win", - sizeof(addr_win)); - if (ret != 1) - goto error_register; - ret = of_property_read_u64_array(of_node, "qti,addr-win", - addr_win, 2); - if (ret) - goto error_register; - } else { - addr_win[0] = memblock_start_of_DRAM(); - addr_win[1] = memblock_end_of_DRAM(); - } -#else - use_bb = false; - (void)use_bb; - addr_win[0] = 0x000000000; - addr_win[1] = 0x2000000000; //MHI_MEM_SIZE_DEFAULT - if (sizeof(dma_addr_t) == 4) { - addr_win[1] = 0xFFFFFFFF; - } -#endif - - mhi_dev->iova_start = addr_win[0]; - mhi_dev->iova_stop = addr_win[1]; - - /* - * If S1 is enabled, set MHI_CTRL start address to 0 so we can use low - * level mapping api to map buffers outside of smmu domain - */ - if (mhi_dev->smmu_cfg & MHI_SMMU_ATTACH && - !(mhi_dev->smmu_cfg & MHI_SMMU_S1_BYPASS)) - mhi_cntrl->iova_start = 0; - else - mhi_cntrl->iova_start = addr_win[0]; - - mhi_cntrl->iova_stop = mhi_dev->iova_stop; - mhi_cntrl->of_node = of_node; - - mhi_dev->pci_dev = pci_dev; - - /* setup power management apis */ - mhi_cntrl->status_cb = mhi_status_cb; - mhi_cntrl->runtime_get = mhi_runtime_get; - mhi_cntrl->runtime_put = mhi_runtime_put; - mhi_cntrl->runtime_mark_last_busy = mhi_runtime_mark_last_busy; - mhi_cntrl->link_status = mhi_link_status; - - mhi_cntrl->lpm_disable = mhi_lpm_disable; - mhi_cntrl->lpm_enable = mhi_lpm_enable; - mhi_cntrl->time_get = mhi_time_get; - - ret = of_register_mhi_controller(mhi_cntrl); - if (ret) - goto error_register; - - for (i = 0; i < ARRAY_SIZE(firmware_table); i++) { - firmware_info = firmware_table + i; - - /* debug mode always use default */ - if (!debug_mode && mhi_cntrl->dev_id == firmware_info->dev_id) - break; - } - -#if 0 - mhi_cntrl->fw_image = firmware_info->fw_image; - mhi_cntrl->edl_image = firmware_info->edl_image; -#endif - - if (sysfs_create_group(&mhi_cntrl->mhi_dev->dev.kobj, &mhi_group)) - MHI_ERR("Error while creating the sysfs group\n"); - - return mhi_cntrl; - -error_register: - mhi_free_controller(mhi_cntrl); - - return ERR_PTR(-EINVAL); -} - -static bool mhi_pci_is_alive(struct pci_dev *pdev) -{ - u16 vendor = 0; - - if (pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor)) - return false; - - if (vendor == (u16) ~0 || vendor == 0) - return false; - - return true; -} - -static void mhi_pci_show_link(struct mhi_controller *mhi_cntrl, struct pci_dev *pci_dev) -{ - int pcie_cap_reg; - u16 stat; - u32 caps; - const char *speed; - - pcie_cap_reg = pci_find_capability(pci_dev, PCI_CAP_ID_EXP); - - if (!pcie_cap_reg) - return; - - pci_read_config_word(pci_dev, - pcie_cap_reg + PCI_EXP_LNKSTA, - &stat); - pci_read_config_dword(pci_dev, - pcie_cap_reg + PCI_EXP_LNKCAP, - &caps); - - switch (caps & PCI_EXP_LNKCAP_SLS) { - case PCI_EXP_LNKCAP_SLS_2_5GB: speed = "2.5"; break; - case PCI_EXP_LNKCAP_SLS_5_0GB: speed = "5"; break; - case 3: speed = "8"; break; - case 4: speed = "16"; break; - case 5: speed = "32"; break; - case 6: speed = "64"; break; - default: speed = "0"; break; - } - - MHI_LOG("LnkCap: Speed %sGT/s, Width x%d\n", speed, - (caps & PCI_EXP_LNKCAP_MLW) >> 4); - - switch (stat & PCI_EXP_LNKSTA_CLS) { - case PCI_EXP_LNKSTA_CLS_2_5GB: speed = "2.5"; break; - case PCI_EXP_LNKSTA_CLS_5_0GB: speed = "5"; break; - case 3: speed = "8"; break; - case 4: speed = "16"; break; - case 5: speed = "32"; break; - case 6: speed = "64"; break; - default: speed = "0"; break; - } - - MHI_LOG("LnkSta: Speed %sGT/s, Width x%d\n", speed, - (stat & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT); - -} - -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id) -{ - struct mhi_controller *mhi_cntrl; - u32 domain = pci_domain_nr(pci_dev->bus); - u32 bus = pci_dev->bus->number; - u32 dev_id = pci_dev->device; - u32 slot = PCI_SLOT(pci_dev->devfn); - struct mhi_dev *mhi_dev; - int ret; - - pr_info("%s pci_dev->name = %s, domain=%d, bus=%d, slot=%d, vendor=%04X, device=%04X\n", - __func__, dev_name(&pci_dev->dev), domain, bus, slot, pci_dev->vendor, pci_dev->device); - -#if !defined(CONFIG_PCI_MSI) - /* MT7621 RTL8198D EcoNet-EN7565 */ - #error "pcie msi is not support by this soc! and i donot support INTx (SW1SDX55-2688)" -#endif - - if (!mhi_pci_is_alive(pci_dev)) { - /* - root@OpenWrt:~# hexdump /sys/bus/pci/devices/0000:01:00.0/config - 0000000 ffff ffff ffff ffff ffff ffff ffff ffff - * - 0001000 - */ - pr_err("mhi_pci is not alive! pcie link is down\n"); - pr_err("double check by 'hexdump /sys/bus/pci/devices/%s/config'\n", dev_name(&pci_dev->dev)); - return -EIO; - } - - /* see if we already registered */ - mhi_cntrl = mhi_bdf_to_controller(domain, bus, slot, dev_id); - if (!mhi_cntrl) - mhi_cntrl = mhi_register_controller(pci_dev); - - if (IS_ERR(mhi_cntrl)) - return PTR_ERR(mhi_cntrl); - - mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - mhi_dev->powered_on = true; - - mhi_arch_iommu_init(mhi_cntrl); - - ret = mhi_arch_pcie_init(mhi_cntrl); - if (ret) - goto error_init_pci_arch; - - mhi_cntrl->dev = &pci_dev->dev; - ret = mhi_init_pci_dev(mhi_cntrl); - if (ret) - goto error_init_pci; - - /* start power up sequence */ - if (!debug_mode) { - ret = mhi_power_up(mhi_cntrl); - if (ret) - goto error_power_up; - } - - pm_runtime_mark_last_busy(&pci_dev->dev); - - mhi_pci_show_link(mhi_cntrl, pci_dev); - -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP - { - struct msm_pcie_register_event *pcie_event = &mhi_pcie_events[mhi_cntrl->cntrl_idx]; - - pcie_event->events = MSM_PCIE_EVENT_WAKEUP; -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,14,117 )) - pcie_event->pcie_event.user = pci_dev; - pcie_event->pcie_event.mode = MSM_PCIE_TRIGGER_CALLBACK; - pcie_event->pcie_event.callback = mhi_pci_event_cb; -#else - pcie_event->user = pci_dev; - pcie_event->mode = MSM_PCIE_TRIGGER_CALLBACK; - pcie_event->callback = mhi_pci_event_cb; -#endif - - ret = msm_pcie_register_event(pcie_event); - if (ret) { - MHI_LOG("Failed to register for PCIe event"); - } - } -#endif - - MHI_LOG("Return successful\n"); - - return 0; - - mhi_unregister_mhi_controller(mhi_cntrl); -error_power_up: - mhi_deinit_pci_dev(mhi_cntrl); - -error_init_pci: - mhi_arch_pcie_deinit(mhi_cntrl); -error_init_pci_arch: - mhi_arch_iommu_deinit(mhi_cntrl); - - return ret; -} - -void mhi_pci_device_removed(struct pci_dev *pci_dev) -{ - struct mhi_controller *mhi_cntrl; - u32 domain = pci_domain_nr(pci_dev->bus); - u32 bus = pci_dev->bus->number; - u32 dev_id = pci_dev->device; - u32 slot = PCI_SLOT(pci_dev->devfn); - - mhi_cntrl = mhi_bdf_to_controller(domain, bus, slot, dev_id); - - if (mhi_cntrl) { - - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP - { - struct msm_pcie_register_event *pcie_event = &mhi_pcie_events[mhi_cntrl->cntrl_idx]; - - msm_pcie_deregister_event(pcie_event); - } -#endif - - pm_stay_awake(&mhi_cntrl->mhi_dev->dev); - - /* if link is in drv suspend, wake it up */ - pm_runtime_get_sync(&pci_dev->dev); - - mutex_lock(&mhi_cntrl->pm_mutex); - if (!mhi_dev->powered_on) { - MHI_LOG("Not in active state\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - pm_runtime_put_noidle(&pci_dev->dev); - return; - } - mhi_dev->powered_on = false; - mutex_unlock(&mhi_cntrl->pm_mutex); - - pm_runtime_put_noidle(&pci_dev->dev); - - MHI_LOG("Triggering shutdown process\n"); - mhi_power_down(mhi_cntrl, false); - - /* turn the link off */ - mhi_deinit_pci_dev(mhi_cntrl); - mhi_arch_link_off(mhi_cntrl, false); - - mhi_arch_pcie_deinit(mhi_cntrl); - mhi_arch_iommu_deinit(mhi_cntrl); - - pm_relax(&mhi_cntrl->mhi_dev->dev); - - mhi_unregister_mhi_controller(mhi_cntrl); - } -} - -static const struct dev_pm_ops pm_ops = { - SET_RUNTIME_PM_OPS(mhi_runtime_suspend, - mhi_runtime_resume, - mhi_runtime_idle) - SET_SYSTEM_SLEEP_PM_OPS(mhi_system_suspend, mhi_system_resume) -}; - -static struct pci_device_id mhi_pcie_device_id[] = { - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0303)}, - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0304)}, //SDX20 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0305)}, //SDX24 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0306)}, //SDX55 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, 0x0308)}, //SDX62 - {PCI_DEVICE(0x1eac, 0x1001)}, //EM120 - {PCI_DEVICE(0x1eac, 0x1002)}, //EM160 - {PCI_DEVICE(0x1eac, 0x1004)}, //RM520 - {PCI_DEVICE(MHI_PCIE_VENDOR_ID, MHI_PCIE_DEBUG_ID)}, - {0}, -}; - -MODULE_DEVICE_TABLE(pci, mhi_pcie_device_id); - -static struct pci_driver mhi_pcie_driver = { - .name = "mhi_q", - .id_table = mhi_pcie_device_id, - .probe = mhi_pci_probe, - .remove = mhi_pci_device_removed, - .driver = { - .pm = &pm_ops - } -}; - -#if 0 -module_pci_driver(mhi_pcie_driver); -#else -int __init mhi_controller_qcom_init(void) -{ - return pci_register_driver(&mhi_pcie_driver); -}; - -void mhi_controller_qcom_exit(void) -{ - pr_info("%s enter\n", __func__); - pci_unregister_driver(&mhi_pcie_driver); - pr_info("%s exit\n", __func__); -} - -#ifdef QCOM_AP_SDM845_IOMMU_MAP -struct dma_iommu_mapping *mhi_smmu_mapping[MAX_MHI]; - -#define SMMU_BASE 0x10000000 -#define SMMU_SIZE 0x40000000 -static struct dma_iommu_mapping * sdm845_smmu_init(struct pci_dev *pdev) { - int ret = 0; - int atomic_ctx = 1; - int s1_bypass = 1; - struct dma_iommu_mapping *mapping; - - mapping = arm_iommu_create_mapping(&platform_bus_type, SMMU_BASE, SMMU_SIZE); - if (IS_ERR(mapping)) { - ret = PTR_ERR(mapping); - dev_err(&pdev->dev, "Create mapping failed, err = %d\n", ret); - return NULL; - } - - ret = iommu_domain_set_attr(mapping->domain, DOMAIN_ATTR_ATOMIC, &atomic_ctx); - if (ret < 0) { - dev_err(&pdev->dev, "Set atomic_ctx attribute failed, err = %d\n", ret); - goto set_attr_fail; - } - - ret = iommu_domain_set_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS, &s1_bypass); - if (ret < 0) { - dev_err(&pdev->dev, "Set s1_bypass attribute failed, err = %d\n", ret); - arm_iommu_release_mapping(mapping); - goto set_attr_fail; - } - - ret = arm_iommu_attach_device(&pdev->dev, mapping); - if (ret < 0) { - dev_err(&pdev->dev, "Attach device failed, err = %d\n", ret); - goto attach_fail; - } - - return mapping; - -attach_fail: -set_attr_fail: - arm_iommu_release_mapping(mapping); - return NULL; -} -#endif - -int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl) -{ -#ifdef QCOM_AP_SDM845_IOMMU_MAP - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - mhi_smmu_mapping[mhi_cntrl->cntrl_idx] = sdm845_smmu_init(mhi_dev->pci_dev); -#endif - - return 0; -} - -void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl) -{ -#ifdef QCOM_AP_SDM845_IOMMU_MAP - if (mhi_smmu_mapping[mhi_cntrl->cntrl_idx]) { - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - - arm_iommu_detach_device(&mhi_dev->pci_dev->dev); - arm_iommu_release_mapping(mhi_smmu_mapping[mhi_cntrl->cntrl_idx]); - mhi_smmu_mapping[mhi_cntrl->cntrl_idx] = NULL; - } -#endif -} - -static int mhi_arch_set_bus_request(struct mhi_controller *mhi_cntrl, int index) -{ - MHI_LOG("Setting bus request to index %d\n", index); - return 0; -} - -int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) -{ -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - - if (!arch_info) { - arch_info = devm_kzalloc(&mhi_dev->pci_dev->dev, - sizeof(*arch_info), GFP_KERNEL); - if (!arch_info) - return -ENOMEM; - - mhi_dev->arch_info = arch_info; - - /* save reference state for pcie config space */ - arch_info->ref_pcie_state = pci_store_saved_state( - mhi_dev->pci_dev); - } -#endif - - return mhi_arch_set_bus_request(mhi_cntrl, 1); -} - -void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) -{ - mhi_arch_set_bus_request(mhi_cntrl, 0); -} - -int mhi_arch_platform_init(struct mhi_dev *mhi_dev) -{ - return 0; -} - -void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev) -{ -} - -int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, - bool graceful) -{ -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - - MHI_LOG("Entered\n"); - - if (graceful) { - pci_clear_master(pci_dev); - ret = pci_save_state(mhi_dev->pci_dev); - if (ret) { - MHI_ERR("Failed with pci_save_state, ret:%d\n", ret); - return ret; - } - - arch_info->pcie_state = pci_store_saved_state(pci_dev); - pci_disable_device(pci_dev); - } - - /* - * We will always attempt to put link into D3hot, however - * link down may have happened due to error fatal, so - * ignoring the return code - */ - pci_set_power_state(pci_dev, PCI_D3hot); - - ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, mhi_cntrl->bus, pci_dev, - NULL, 0); - MHI_ERR("msm_pcie_pm_control(MSM_PCIE_SUSPEND), ret:%d\n", ret); - - /* release the resources */ - mhi_arch_set_bus_request(mhi_cntrl, 0); - - MHI_LOG("Exited\n"); -#endif - - return 0; -} - -int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) -{ -#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP - struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); - struct arch_info *arch_info = mhi_dev->arch_info; - struct pci_dev *pci_dev = mhi_dev->pci_dev; - int ret; - - MHI_LOG("Entered\n"); - - /* request resources and establish link trainning */ - ret = mhi_arch_set_bus_request(mhi_cntrl, 1); - if (ret) - MHI_LOG("Could not set bus frequency, ret:%d\n", ret); - - ret = msm_pcie_pm_control(MSM_PCIE_RESUME, mhi_cntrl->bus, pci_dev, - NULL, 0); - MHI_LOG("msm_pcie_pm_control(MSM_PCIE_RESUME), ret:%d\n", ret); - if (ret) { - MHI_ERR("Link training failed, ret:%d\n", ret); - return ret; - } - - ret = pci_set_power_state(pci_dev, PCI_D0); - if (ret) { - MHI_ERR("Failed to set PCI_D0 state, ret:%d\n", ret); - return ret; - } - - ret = pci_enable_device(pci_dev); - if (ret) { - MHI_ERR("Failed to enable device, ret:%d\n", ret); - return ret; - } - - ret = pci_load_and_free_saved_state(pci_dev, &arch_info->pcie_state); - if (ret) - MHI_LOG("Failed to load saved cfg state\n"); - - pci_restore_state(pci_dev); - pci_set_master(pci_dev); - - MHI_LOG("Exited\n"); -#endif - - return 0; -} -#endif diff --git a/quectel_MHI/src/controllers/mhi_qti.h b/quectel_MHI/src/controllers/mhi_qti.h deleted file mode 100644 index 7ac021a..0000000 --- a/quectel_MHI/src/controllers/mhi_qti.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/ - -#ifndef _MHI_QTI_ -#define _MHI_QTI_ - -/* iova cfg bitmask */ -#define MHI_SMMU_ATTACH BIT(0) -#define MHI_SMMU_S1_BYPASS BIT(1) -#define MHI_SMMU_FAST BIT(2) -#define MHI_SMMU_ATOMIC BIT(3) -#define MHI_SMMU_FORCE_COHERENT BIT(4) - -#define MHI_PCIE_VENDOR_ID (0x17cb) -#define MHI_PCIE_DEBUG_ID (0xffff) - -/* runtime suspend timer */ -#define MHI_RPM_SUSPEND_TMR_MS (2000) -#define MHI_PCI_BAR_NUM (0) - -struct mhi_dev { - struct pci_dev *pci_dev; - u32 smmu_cfg; - int resn; - void *arch_info; - bool powered_on; - dma_addr_t iova_start; - dma_addr_t iova_stop; - bool lpm_disabled; -}; - -void mhi_deinit_pci_dev(struct mhi_controller *mhi_cntrl); -int mhi_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *device_id); - -void mhi_pci_device_removed(struct pci_dev *pci_dev); -int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl); -void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl); -int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl); -void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl); -int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, bool graceful); -int mhi_arch_link_on(struct mhi_controller *mhi_cntrl); - -#endif /* _MHI_QTI_ */ diff --git a/quectel_MHI/src/core/Makefile b/quectel_MHI/src/core/Makefile deleted file mode 100644 index a743fbf..0000000 --- a/quectel_MHI/src/core/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_MHI_BUS) +=mhi_init.o mhi_main.o mhi_pm.o mhi_boot.o mhi_dtr.o diff --git a/quectel_MHI/src/core/mhi.h b/quectel_MHI/src/core/mhi.h deleted file mode 100644 index fad6504..0000000 --- a/quectel_MHI/src/core/mhi.h +++ /dev/null @@ -1,908 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ - -#ifndef _MHI_H_ -#define _MHI_H_ - -#define PCIE_MHI_DRIVER_VERSION "V1.3.6" -#define ENABLE_MHI_MON -//#define ENABLE_IP_SW0 - -// #define ENABLE_ADPL - -// #define ENABLE_QDSS - -#include -typedef enum -{ - MHI_CLIENT_LOOPBACK_OUT = 0, - MHI_CLIENT_LOOPBACK_IN = 1, - MHI_CLIENT_SAHARA_OUT = 2, - MHI_CLIENT_SAHARA_IN = 3, - MHI_CLIENT_DIAG_OUT = 4, - MHI_CLIENT_DIAG_IN = 5, - MHI_CLIENT_SSR_OUT = 6, - MHI_CLIENT_SSR_IN = 7, - MHI_CLIENT_QDSS_OUT = 8, - MHI_CLIENT_QDSS_IN = 9, - MHI_CLIENT_EFS_OUT = 10, - MHI_CLIENT_EFS_IN = 11, - MHI_CLIENT_MBIM_OUT = 12, - MHI_CLIENT_MBIM_IN = 13, - MHI_CLIENT_QMI_OUT = 14, - MHI_CLIENT_QMI_IN = 15, - MHI_CLIENT_QMI_2_OUT = 16, - MHI_CLIENT_QMI_2_IN = 17, - MHI_CLIENT_IP_CTRL_1_OUT = 18, - MHI_CLIENT_IP_CTRL_1_IN = 19, - MHI_CLIENT_IPCR_OUT = 20, - MHI_CLIENT_IPCR_IN = 21, - MHI_CLIENT_TEST_FW_OUT = 22, - MHI_CLIENT_TEST_FW_IN = 23, - MHI_CLIENT_RESERVED_0 = 24, - MHI_CLIENT_BOOT_LOG_IN = 25, - MHI_CLIENT_DCI_OUT = 26, - MHI_CLIENT_DCI_IN = 27, - MHI_CLIENT_QBI_OUT = 28, - MHI_CLIENT_QBI_IN = 29, - MHI_CLIENT_RESERVED_1_LOWER = 30, - MHI_CLIENT_RESERVED_1_UPPER = 31, - MHI_CLIENT_DUN_OUT = 32, - MHI_CLIENT_DUN_IN = 33, - MHI_CLIENT_EDL_OUT = 34, - MHI_CLIENT_EDL_IN = 35, - MHI_CLIENT_ADB_FB_OUT = 36, - MHI_CLIENT_ADB_FB_IN = 37, - MHI_CLIENT_RESERVED_2_LOWER = 38, - MHI_CLIENT_RESERVED_2_UPPER = 41, - MHI_CLIENT_CSVT_OUT = 42, - MHI_CLIENT_CSVT_IN = 43, - MHI_CLIENT_SMCT_OUT = 44, - MHI_CLIENT_SMCT_IN = 45, - MHI_CLIENT_IP_SW_0_OUT = 46, - MHI_CLIENT_IP_SW_0_IN = 47, - MHI_CLIENT_IP_SW_1_OUT = 48, - MHI_CLIENT_IP_SW_1_IN = 49, - MHI_CLIENT_RESERVED_3_LOWER = 50, - MHI_CLIENT_RESERVED_3_UPPER = 59, - MHI_CLIENT_TEST_0_OUT = 60, - MHI_CLIENT_TEST_0_IN = 61, - MHI_CLIENT_TEST_1_OUT = 62, - MHI_CLIENT_TEST_1_IN = 63, - MHI_CLIENT_TEST_2_OUT = 64, - MHI_CLIENT_TEST_2_IN = 65, - MHI_CLIENT_TEST_3_OUT = 66, - MHI_CLIENT_TEST_3_IN = 67, - MHI_CLIENT_RESERVED_4_LOWER = 68, - MHI_CLIENT_RESERVED_4_UPPER = 91, - MHI_CLIENT_OEM_0_OUT = 92, - MHI_CLIENT_OEM_0_IN = 93, - MHI_CLIENT_OEM_1_OUT = 94, - MHI_CLIENT_OEM_1_IN = 95, - MHI_CLIENT_OEM_2_OUT = 96, - MHI_CLIENT_OEM_2_IN = 97, - MHI_CLIENT_OEM_3_OUT = 98, - MHI_CLIENT_OEM_3_IN = 99, - MHI_CLIENT_IP_HW_0_OUT = 100, - MHI_CLIENT_IP_HW_0_IN = 101, - MHI_CLIENT_ADPL = 102, - MHI_CLIENT_IP_HW_QDSS = 103, - // MHI_CLIENT_RESERVED_5_LOWER = 103, - MHI_CLIENT_RESERVED_5_UPPER = 127, - MHI_MAX_CHANNELS = 128 -}MHI_CLIENT_CHANNEL_TYPE; - -/* Event Ring Index */ -typedef enum -{ - SW_EVT_RING = 0, - PRIMARY_EVENT_RING = SW_EVT_RING, -#ifdef ENABLE_IP_SW0 - SW_0_OUT_EVT_RING, - SW_0_IN_EVT_RING, -#endif - IPA_OUT_EVENT_RING, - IPA_IN_EVENT_RING, -#ifdef ENABLE_ADPL - ADPL_EVT_RING, -#endif -#ifdef ENABLE_QDSS - QDSS_EVT_RING, -#endif - - MAX_EVT_RING_IDX -}MHI_EVT_RING_IDX; - -#define MHI_VERSION 0x01000000 -#define MHIREGLEN_VALUE 0x100 /* **** WRONG VALUE *** */ -#define MHI_MSI_INDEX 1 -#define MAX_NUM_MHI_DEVICES 1 -#define NUM_MHI_XFER_RINGS 128 -#define NUM_MHI_EVT_RINGS MAX_EVT_RING_IDX -#define NUM_MHI_HW_EVT_RINGS 4 -#define NUM_MHI_XFER_RING_ELEMENTS 16 -#define NUM_MHI_EVT_RING_ELEMENTS (NUM_MHI_IPA_IN_RING_ELEMENTS*2) //must *2, event ring full will make x55 dump -#define NUM_MHI_IPA_IN_RING_ELEMENTS 512 -#define NUM_MHI_IPA_OUT_RING_ELEMENTS 512 //donot use ul agg, so increase -#define NUM_MHI_DIAG_IN_RING_ELEMENTS 128 -#define NUM_MHI_SW_IP_RING_ELEMENTS 512 - -#ifdef ENABLE_ADPL -#define NUM_MHI_ADPL_RING_ELEMENTS 256 -#endif - -#ifdef ENABLE_QDSS -#define NUM_MHI_QDSS_RING_ELEMENTS 256 -#endif - -/* -* for if set Interrupt moderation time as 1ms, -and transfer more than NUM_MHI_CHAN_RING_ELEMENTS data are sent to the modem in 1ms. -e.g. firehose upgrade. -modem will not trigger irq for these transfer. -*/ -#define NUM_MHI_CHAN_RING_ELEMENTS 32 //8 -#define MHI_EVT_CMD_QUEUE_SIZE 160 -#define MHI_EVT_STATE_QUEUE_SIZE 128 -#define MHI_EVT_XFER_QUEUE_SIZE 1024 - -#define CHAN_INBOUND(_x) ((_x)%2) - -#define CHAN_SBL(_x) (((_x) == MHI_CLIENT_SAHARA_OUT) || \ - ((_x) == MHI_CLIENT_SAHARA_IN) || \ - ((_x) == MHI_CLIENT_BOOT_LOG_IN)) - -#define CHAN_EDL(_x) (((_x) == MHI_CLIENT_EDL_OUT) || \ - ((_x) == MHI_CLIENT_EDL_IN)) - -struct mhi_chan; -struct mhi_event; -struct mhi_ctxt; -struct mhi_cmd; -struct image_info; -struct bhi_vec_entry; -struct mhi_timesync; -struct mhi_buf_info; - -/** - * enum MHI_CB - MHI callback - * @MHI_CB_IDLE: MHI entered idle state - * @MHI_CB_PENDING_DATA: New data available for client to process - * @MHI_CB_LPM_ENTER: MHI host entered low power mode - * @MHI_CB_LPM_EXIT: MHI host about to exit low power mode - * @MHI_CB_EE_RDDM: MHI device entered RDDM execution enviornment - * @MHI_CB_EE_MISSION_MODE: MHI device entered Mission Mode exec env - * @MHI_CB_SYS_ERROR: MHI device enter error state (may recover) - * @MHI_CB_FATAL_ERROR: MHI device entered fatal error - */ -enum MHI_CB { - MHI_CB_IDLE, - MHI_CB_PENDING_DATA, - MHI_CB_LPM_ENTER, - MHI_CB_LPM_EXIT, - MHI_CB_EE_RDDM, - MHI_CB_EE_MISSION_MODE, - MHI_CB_SYS_ERROR, - MHI_CB_FATAL_ERROR, -}; - -/** - * enum MHI_DEBUG_LEVL - various debugging level - */ -enum MHI_DEBUG_LEVEL { - MHI_MSG_LVL_VERBOSE, - MHI_MSG_LVL_INFO, - MHI_MSG_LVL_ERROR, - MHI_MSG_LVL_CRITICAL, - MHI_MSG_LVL_MASK_ALL, -}; - -/* -GSI_XFER_FLAG_BEI: Block event interrupt -1: Event generated by this ring element must not assert an interrupt to the host -0: Event generated by this ring element must assert an interrupt to the host - -GSI_XFER_FLAG_EOT: Interrupt on end of transfer -1: If an EOT condition is encountered when processing this ring element, an event is generated by the device with its completion code set to EOT. -0: If an EOT condition is encountered for this ring element, a completion event is not be generated by the device, unless IEOB is 1 - -GSI_XFER_FLAG_EOB: Interrupt on end of block -1: Device notifies host after processing this ring element by sending a completion event -0: Completion event is not required after processing this ring element - -GSI_XFER_FLAG_CHAIN: Chain bit that identifies the ring elements in a TD -*/ - -/** - * enum MHI_FLAGS - Transfer flags - * @MHI_EOB: End of buffer for bulk transfer - * @MHI_EOT: End of transfer - * @MHI_CHAIN: Linked transfer - */ -enum MHI_FLAGS { - MHI_EOB, - MHI_EOT, - MHI_CHAIN, -}; - -/** - * enum mhi_device_type - Device types - * @MHI_XFER_TYPE: Handles data transfer - * @MHI_TIMESYNC_TYPE: Use for timesync feature - * @MHI_CONTROLLER_TYPE: Control device - */ -enum mhi_device_type { - MHI_XFER_TYPE, - MHI_TIMESYNC_TYPE, - MHI_CONTROLLER_TYPE, -}; - -/** - * enum mhi_ee - device current execution enviornment - * @MHI_EE_PBL - device in PBL - * @MHI_EE_SBL - device in SBL - * @MHI_EE_AMSS - device in mission mode (firmware fully loaded) - * @MHI_EE_RDDM - device in ram dump collection mode - * @MHI_EE_WFW - device in WLAN firmware mode - * @MHI_EE_PTHRU - device in PBL but configured in pass thru mode - * @MHI_EE_EDL - device in emergency download mode - */ -enum mhi_ee { - MHI_EE_PBL = 0x0, - MHI_EE_SBL = 0x1, - MHI_EE_AMSS = 0x2, - MHI_EE_RDDM = 0x3, - MHI_EE_WFW = 0x4, - MHI_EE_PTHRU = 0x5, - MHI_EE_EDL = 0x6, - MHI_EE_FP = 0x7, /* FlashProg, Flash Programmer Environment */ - MHI_EE_MAX_SUPPORTED = MHI_EE_FP, - MHI_EE_DISABLE_TRANSITION, /* local EE, not related to mhi spec */ - MHI_EE_MAX, -}; - -/** - * enum mhi_dev_state - device current MHI state - */ -enum mhi_dev_state { - MHI_STATE_RESET = 0x0, - MHI_STATE_READY = 0x1, - MHI_STATE_M0 = 0x2, - MHI_STATE_M1 = 0x3, - MHI_STATE_M2 = 0x4, - MHI_STATE_M3 = 0x5, - MHI_STATE_BHI = 0x7, - MHI_STATE_SYS_ERR = 0xFF, - MHI_STATE_MAX, -}; - -extern const char * const mhi_ee_str[MHI_EE_MAX]; -#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \ - "INVALID_EE" : mhi_ee_str[ee]) - -/** - * struct image_info - firmware and rddm table table - * @mhi_buf - Contain device firmware and rddm table - * @entries - # of entries in table - */ -struct image_info { - struct mhi_buf *mhi_buf; - struct bhi_vec_entry *bhi_vec; - u32 entries; -}; - -/** - * struct mhi_controller - Master controller structure for external modem - * @dev: Device associated with this controller - * @of_node: DT that has MHI configuration information - * @regs: Points to base of MHI MMIO register space - * @bhi: Points to base of MHI BHI register space - * @bhie: Points to base of MHI BHIe register space - * @wake_db: MHI WAKE doorbell register address - * @dev_id: PCIe device id of the external device - * @domain: PCIe domain the device connected to - * @bus: PCIe bus the device assigned to - * @slot: PCIe slot for the modem - * @iova_start: IOMMU starting address for data - * @iova_stop: IOMMU stop address for data - * @fw_image: Firmware image name for normal booting - * @edl_image: Firmware image name for emergency download mode - * @fbc_download: MHI host needs to do complete image transfer - * @rddm_size: RAM dump size that host should allocate for debugging purpose - * @sbl_size: SBL image size - * @seg_len: BHIe vector size - * @fbc_image: Points to firmware image buffer - * @rddm_image: Points to RAM dump buffer - * @max_chan: Maximum number of channels controller support - * @mhi_chan: Points to channel configuration table - * @lpm_chans: List of channels that require LPM notifications - * @total_ev_rings: Total # of event rings allocated - * @hw_ev_rings: Number of hardware event rings - * @sw_ev_rings: Number of software event rings - * @msi_required: Number of msi required to operate - * @msi_allocated: Number of msi allocated by bus master - * @irq: base irq # to request - * @mhi_event: MHI event ring configurations table - * @mhi_cmd: MHI command ring configurations table - * @mhi_ctxt: MHI device context, shared memory between host and device - * @timeout_ms: Timeout in ms for state transitions - * @pm_state: Power management state - * @ee: MHI device execution environment - * @dev_state: MHI STATE - * @status_cb: CB function to notify various power states to but master - * @link_status: Query link status in case of abnormal value read from device - * @runtime_get: Async runtime resume function - * @runtimet_put: Release votes - * @time_get: Return host time in us - * @lpm_disable: Request controller to disable link level low power modes - * @lpm_enable: Controller may enable link level low power modes again - * @priv_data: Points to bus master's private data - */ -struct mhi_controller { - struct list_head node; - struct mhi_device *mhi_dev; - - /* device node for iommu ops */ - struct device *dev; - struct device_node *of_node; - - /* mmio base */ - phys_addr_t base_addr; - void __iomem *regs; - void __iomem *bhi; - void __iomem *bhie; - void __iomem *wake_db; - - /* device topology */ - u32 vendor; - u32 dev_id; - u32 domain; - u32 bus; - u32 slot; - u32 cntrl_idx; - struct device *cntrl_dev; - - /* addressing window */ - dma_addr_t iova_start; - dma_addr_t iova_stop; - - /* fw images */ - const char *fw_image; - const char *edl_image; - - /* mhi host manages downloading entire fbc images */ - bool fbc_download; - size_t rddm_size; - size_t sbl_size; - size_t seg_len; - u32 session_id; - u32 sequence_id; - struct image_info *fbc_image; - struct image_info *rddm_image; - - /* physical channel config data */ - u32 max_chan; - struct mhi_chan *mhi_chan; - struct list_head lpm_chans; /* these chan require lpm notification */ - - /* physical event config data */ - u32 total_ev_rings; - u32 hw_ev_rings; - u32 sw_ev_rings; - u32 msi_required; - u32 msi_allocated; - u32 msi_irq_base; - int *irq; /* interrupt table */ - struct mhi_event *mhi_event; - - /* cmd rings */ - struct mhi_cmd *mhi_cmd; - - /* mhi context (shared with device) */ - struct mhi_ctxt *mhi_ctxt; - - u32 timeout_ms; - - /* caller should grab pm_mutex for suspend/resume operations */ - struct mutex pm_mutex; - bool pre_init; - rwlock_t pm_lock; - u32 pm_state; - enum mhi_ee ee; - enum mhi_dev_state dev_state; - bool wake_set; - atomic_t dev_wake; - atomic_t alloc_size; - atomic_t pending_pkts; - struct list_head transition_list; - spinlock_t transition_lock; - spinlock_t wlock; - - /* debug counters */ - u32 M0, M2, M3; - - /* worker for different state transitions */ - struct work_struct st_worker; - struct work_struct fw_worker; - struct work_struct syserr_worker; - struct delayed_work ready_worker; - wait_queue_head_t state_event; - - /* shadow functions */ - void (*status_cb)(struct mhi_controller *mhi_cntrl, void *priv, - enum MHI_CB reason); - int (*link_status)(struct mhi_controller *mhi_cntrl, void *priv); - void (*wake_get)(struct mhi_controller *mhi_cntrl, bool override); - void (*wake_put)(struct mhi_controller *mhi_cntrl, bool override); - int (*runtime_get)(struct mhi_controller *mhi_cntrl, void *priv); - void (*runtime_put)(struct mhi_controller *mhi_cntrl, void *priv); - void (*runtime_mark_last_busy)(struct mhi_controller *mhi_cntrl, void *priv); - u64 (*time_get)(struct mhi_controller *mhi_cntrl, void *priv); - int (*lpm_disable)(struct mhi_controller *mhi_cntrl, void *priv); - int (*lpm_enable)(struct mhi_controller *mhi_cntrl, void *priv); - int (*map_single)(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf); - void (*unmap_single)(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf); - - /* channel to control DTR messaging */ - struct mhi_device *dtr_dev; - - /* bounce buffer settings */ - bool bounce_buf; - size_t buffer_len; - - /* supports time sync feature */ - struct mhi_timesync *mhi_tsync; - struct mhi_device *tsync_dev; - - /* kernel log level */ - enum MHI_DEBUG_LEVEL klog_lvl; - int klog_slient; - - /* private log level controller driver to set */ - enum MHI_DEBUG_LEVEL log_lvl; - - /* controller specific data */ - void *priv_data; - void *log_buf; - struct dentry *dentry; - struct dentry *parent; - - struct miscdevice miscdev; - -#ifdef ENABLE_MHI_MON - spinlock_t lock; - - /* Ref */ - int nreaders; /* Under mon_lock AND mbus->lock */ - struct list_head r_list; /* Chain of readers (usually one) */ - struct kref ref; /* Under mon_lock */ - - /* Stats */ - unsigned int cnt_events; - unsigned int cnt_text_lost; -#endif -}; - -#ifdef ENABLE_MHI_MON -struct mhi_tre; -struct mon_reader { - struct list_head r_link; - struct mhi_controller *m_bus; - void *r_data; /* Use container_of instead? */ - - void (*rnf_submit)(void *data, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len); - void (*rnf_receive)(void *data, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len); - void (*rnf_complete)(void *data, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre); -}; -#endif - -/** - * struct mhi_device - mhi device structure associated bind to channel - * @dev: Device associated with the channels - * @mtu: Maximum # of bytes controller support - * @ul_chan_id: MHI channel id for UL transfer - * @dl_chan_id: MHI channel id for DL transfer - * @tiocm: Device current terminal settings - * @priv: Driver private data - */ -struct mhi_device { - struct device dev; - u32 vendor; - u32 dev_id; - u32 domain; - u32 bus; - u32 slot; - size_t mtu; - int ul_chan_id; - int dl_chan_id; - int ul_event_id; - int dl_event_id; - u32 tiocm; - const struct mhi_device_id *id; - const char *chan_name; - struct mhi_controller *mhi_cntrl; - struct mhi_chan *ul_chan; - struct mhi_chan *dl_chan; - atomic_t dev_wake; - enum mhi_device_type dev_type; - void *priv_data; - int (*ul_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS flags); - int (*dl_xfer)(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t size, enum MHI_FLAGS flags); - void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB reason); -}; - -/** - * struct mhi_result - Completed buffer information - * @buf_addr: Address of data buffer - * @dir: Channel direction - * @bytes_xfer: # of bytes transferred - * @transaction_status: Status of last trasnferred - */ -struct mhi_result { - void *buf_addr; - enum dma_data_direction dir; - size_t bytes_xferd; - int transaction_status; -}; - -/** - * struct mhi_buf - Describes the buffer - * @page: buffer as a page - * @buf: cpu address for the buffer - * @phys_addr: physical address of the buffer - * @dma_addr: iommu address for the buffer - * @skb: skb of ip packet - * @len: # of bytes - * @name: Buffer label, for offload channel configurations name must be: - * ECA - Event context array data - * CCA - Channel context array data - */ -struct mhi_buf { - struct list_head node; - struct page *page; - void *buf; - phys_addr_t phys_addr; - dma_addr_t dma_addr; - struct sk_buff *skb; - size_t len; - const char *name; /* ECA, CCA */ -}; - -/** - * struct mhi_driver - mhi driver information - * @id_table: NULL terminated channel ID names - * @ul_xfer_cb: UL data transfer callback - * @dl_xfer_cb: DL data transfer callback - * @status_cb: Asynchronous status callback - */ -struct mhi_driver { - const struct mhi_device_id *id_table; - int (*probe)(struct mhi_device *mhi_dev, - const struct mhi_device_id *id); - void (*remove)(struct mhi_device *mhi_dev); - void (*ul_xfer_cb)(struct mhi_device *mhi_dev, struct mhi_result *res); - void (*dl_xfer_cb)(struct mhi_device *mhi_dev, struct mhi_result *res); - void (*status_cb)(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb); - struct device_driver driver; -}; - -#define to_mhi_driver(drv) container_of(drv, struct mhi_driver, driver) -#define to_mhi_device(dev) container_of(dev, struct mhi_device, dev) - -static inline void mhi_device_set_devdata(struct mhi_device *mhi_dev, - void *priv) -{ - mhi_dev->priv_data = priv; -} - -static inline void *mhi_device_get_devdata(struct mhi_device *mhi_dev) -{ - return mhi_dev->priv_data; -} - -/** - * mhi_queue_transfer - Queue a buffer to hardware - * All transfers are asyncronous transfers - * @mhi_dev: Device associated with the channels - * @dir: Data direction - * @buf: Data buffer (skb for hardware channels) - * @len: Size in bytes - * @mflags: Interrupt flags for the device - */ -static inline int mhi_queue_transfer(struct mhi_device *mhi_dev, - enum dma_data_direction dir, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - if (dir == DMA_TO_DEVICE) - return mhi_dev->ul_xfer(mhi_dev, mhi_dev->ul_chan, buf, len, - mflags); - else - return mhi_dev->dl_xfer(mhi_dev, mhi_dev->dl_chan, buf, len, - mflags); -} - -static inline void *mhi_controller_get_devdata(struct mhi_controller *mhi_cntrl) -{ - return mhi_cntrl->priv_data; -} - -static inline void mhi_free_controller(struct mhi_controller *mhi_cntrl) -{ - kfree(mhi_cntrl); -} - -/** - * mhi_driver_register - Register driver with MHI framework - * @mhi_drv: mhi_driver structure - */ -int mhi_driver_register(struct mhi_driver *mhi_drv); - -/** - * mhi_driver_unregister - Unregister a driver for mhi_devices - * @mhi_drv: mhi_driver structure - */ -void mhi_driver_unregister(struct mhi_driver *mhi_drv); - -/** - * mhi_device_configure - configure ECA or CCA context - * For offload channels that client manage, call this - * function to configure channel context or event context - * array associated with the channel - * @mhi_div: Device associated with the channels - * @dir: Direction of the channel - * @mhi_buf: Configuration data - * @elements: # of configuration elements - */ -int mhi_device_configure(struct mhi_device *mhi_div, - enum dma_data_direction dir, - struct mhi_buf *mhi_buf, - int elements); - -/** - * mhi_device_get - disable all low power modes - * Only disables lpm, does not immediately exit low power mode - * if controller already in a low power mode - * @mhi_dev: Device associated with the channels - */ -void mhi_device_get(struct mhi_device *mhi_dev); - -/** - * mhi_device_get_sync - disable all low power modes - * Synchronously disable all low power, exit low power mode if - * controller already in a low power state - * @mhi_dev: Device associated with the channels - */ -int mhi_device_get_sync(struct mhi_device *mhi_dev); - -/** - * mhi_device_put - re-enable low power modes - * @mhi_dev: Device associated with the channels - */ -void mhi_device_put(struct mhi_device *mhi_dev); - -/** - * mhi_prepare_for_transfer - setup channel for data transfer - * Moves both UL and DL channel from RESET to START state - * @mhi_dev: Device associated with the channels - */ -int mhi_prepare_for_transfer(struct mhi_device *mhi_dev); - -/** - * mhi_unprepare_from_transfer -unprepare the channels - * Moves both UL and DL channels to RESET state - * @mhi_dev: Device associated with the channels - */ -void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev); - -/** - * mhi_get_no_free_descriptors - Get transfer ring length - * Get # of TD available to queue buffers - * @mhi_dev: Device associated with the channels - * @dir: Direction of the channel - */ -int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, - enum dma_data_direction dir); - -/** - * mhi_poll - poll for any available data to consume - * This is only applicable for DL direction - * @mhi_dev: Device associated with the channels - * @budget: In descriptors to service before returning - */ -int mhi_poll(struct mhi_device *mhi_dev, u32 budget); - -/** - * mhi_ioctl - user space IOCTL support for MHI channels - * Native support for setting TIOCM - * @mhi_dev: Device associated with the channels - * @cmd: IOCTL cmd - * @arg: Optional parameter, iotcl cmd specific - */ -long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg); - -/** - * mhi_alloc_controller - Allocate mhi_controller structure - * Allocate controller structure and additional data for controller - * private data. You may get the private data pointer by calling - * mhi_controller_get_devdata - * @size: # of additional bytes to allocate - */ -struct mhi_controller *mhi_alloc_controller(size_t size); - -/** - * of_register_mhi_controller - Register MHI controller - * Registers MHI controller with MHI bus framework. DT must be supported - * @mhi_cntrl: MHI controller to register - */ -int of_register_mhi_controller(struct mhi_controller *mhi_cntrl); - -void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl); - -/** - * mhi_bdf_to_controller - Look up a registered controller - * Search for controller based on device identification - * @domain: RC domain of the device - * @bus: Bus device connected to - * @slot: Slot device assigned to - * @dev_id: Device Identification - */ -struct mhi_controller *mhi_bdf_to_controller(u32 domain, u32 bus, u32 slot, - u32 dev_id); - -/** - * mhi_prepare_for_power_up - Do pre-initialization before power up - * This is optional, call this before power up if controller do not - * want bus framework to automatically free any allocated memory during shutdown - * process. - * @mhi_cntrl: MHI controller - */ -int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl); - -/** - * mhi_async_power_up - Starts MHI power up sequence - * @mhi_cntrl: MHI controller - */ -int mhi_async_power_up(struct mhi_controller *mhi_cntrl); -int mhi_sync_power_up(struct mhi_controller *mhi_cntrl); - -/** - * mhi_power_down - Start MHI power down sequence - * @mhi_cntrl: MHI controller - * @graceful: link is still accessible, do a graceful shutdown process otherwise - * we will shutdown host w/o putting device into RESET state - */ -void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful); - -/** - * mhi_unprepare_after_powre_down - free any allocated memory for power up - * @mhi_cntrl: MHI controller - */ -void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl); - -/** - * mhi_pm_suspend - Move MHI into a suspended state - * Transition to MHI state M3 state from M0||M1||M2 state - * @mhi_cntrl: MHI controller - */ -int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); - -/** - * mhi_pm_resume - Resume MHI from suspended state - * Transition to MHI state M0 state from M3 state - * @mhi_cntrl: MHI controller - */ -int mhi_pm_resume(struct mhi_controller *mhi_cntrl); - -/** - * mhi_download_rddm_img - Download ramdump image from device for - * debugging purpose. - * @mhi_cntrl: MHI controller - * @in_panic: If we trying to capture image while in kernel panic - */ -int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic); - -/** - * mhi_force_rddm_mode - Force external device into rddm mode - * to collect device ramdump. This is useful if host driver assert - * and we need to see device state as well. - * @mhi_cntrl: MHI controller - */ -int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl); - -/** - * mhi_get_remote_time_sync - Get external soc time relative to local soc time - * using MMIO method. - * @mhi_dev: Device associated with the channels - * @t_host: Pointer to output local soc time - * @t_dev: Pointer to output remote soc time - */ -int mhi_get_remote_time_sync(struct mhi_device *mhi_dev, - u64 *t_host, - u64 *t_dev); - -/** - * mhi_get_mhi_state - Return MHI state of device - * @mhi_cntrl: MHI controller - */ -enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl); - -/** - * mhi_set_mhi_state - Set device state - * @mhi_cntrl: MHI controller - * @state: state to set - */ -void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, - enum mhi_dev_state state); - - -/** - * mhi_is_active - helper function to determine if MHI in active state - * @mhi_dev: client device - */ -static inline bool mhi_is_active(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - return (mhi_cntrl->dev_state >= MHI_STATE_M0 && - mhi_cntrl->dev_state <= MHI_STATE_M3); -} - -/** - * mhi_debug_reg_dump - dump MHI registers for debug purpose - * @mhi_cntrl: MHI controller - */ -void mhi_debug_reg_dump(struct mhi_controller *mhi_cntrl); - -#ifdef CONFIG_MHI_DEBUG - -#define MHI_VERB(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_debug("[D][mhi%d][%s] " fmt, mhi_cntrl->cntrl_idx, __func__, ##__VA_ARGS__);\ -} while (0) - -#else - -#define MHI_VERB(fmt, ...) - -#endif - -#define MHI_LOG(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_INFO) \ - pr_info("[I][mhi%d][%s] " fmt, mhi_cntrl->cntrl_idx, __func__, ##__VA_ARGS__);\ - else if (!mhi_cntrl->klog_slient) \ - printk(KERN_DEBUG "[I][mhi%d][%s] " fmt, mhi_cntrl->cntrl_idx, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MHI_ERR(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][mhi%d][%s] " fmt, mhi_cntrl->cntrl_idx, __func__, ##__VA_ARGS__); \ -} while (0) - -#define MHI_CRITICAL(fmt, ...) do { \ - if (mhi_cntrl->klog_lvl <= MHI_MSG_LVL_CRITICAL) \ - pr_alert("[C][mhi%d][%s] " fmt, mhi_cntrl->cntrl_idx, __func__, ##__VA_ARGS__); \ -} while (0) - -int mhi_register_mhi_controller(struct mhi_controller *mhi_cntrl); -void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl); - -#ifndef MHI_NAME_SIZE -#define MHI_NAME_SIZE 32 -/** - * * struct mhi_device_id - MHI device identification - * * @chan: MHI channel name - * * @driver_data: driver data; - * */ -struct mhi_device_id { - const char chan[MHI_NAME_SIZE]; - unsigned long driver_data; -}; -#endif - -#endif /* _MHI_H_ */ diff --git a/quectel_MHI/src/core/mhi_boot.c b/quectel_MHI/src/core/mhi_boot.c deleted file mode 100644 index 8f1924f..0000000 --- a/quectel_MHI/src/core/mhi_boot.c +++ /dev/null @@ -1,860 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -/* Software defines */ -/* BHI Version */ -#define BHI_MAJOR_VERSION 0x1 -#define BHI_MINOR_VERSION 0x1 - -#define MSMHWID_NUMDWORDS 6 /* Number of dwords that make the MSMHWID */ -#define OEMPKHASH_NUMDWORDS 48 /* Number of dwords that make the OEM PK HASH */ - -#define IsPBLExecEnv(ExecEnv) ((ExecEnv == MHI_EE_PBL) || (ExecEnv == MHI_EE_EDL) ) - -typedef u32 ULONG; - -typedef struct _bhi_info_type -{ - ULONG bhi_ver_minor; - ULONG bhi_ver_major; - ULONG bhi_image_address_low; - ULONG bhi_image_address_high; - ULONG bhi_image_size; - ULONG bhi_rsvd1; - ULONG bhi_imgtxdb; - ULONG bhi_rsvd2; - ULONG bhi_msivec; - ULONG bhi_rsvd3; - ULONG bhi_ee; - ULONG bhi_status; - ULONG bhi_errorcode; - ULONG bhi_errdbg1; - ULONG bhi_errdbg2; - ULONG bhi_errdbg3; - ULONG bhi_sernum; - ULONG bhi_sblantirollbackver; - ULONG bhi_numsegs; - ULONG bhi_msmhwid[6]; - ULONG bhi_oempkhash[48]; - ULONG bhi_rsvd5; -}BHI_INFO_TYPE, *PBHI_INFO_TYPE; - -static void PrintBhiInfo(struct mhi_controller *mhi_cntrl, BHI_INFO_TYPE *bhi_info) -{ - ULONG index; - char str[128]; - - MHI_LOG("BHI Device Info...\n"); - MHI_LOG("BHI Version = { Major = 0x%X Minor = 0x%X}\n", bhi_info->bhi_ver_major, bhi_info->bhi_ver_minor); - MHI_LOG("BHI Execution Environment = 0x%X\n", bhi_info->bhi_ee); - MHI_LOG("BHI Status = 0x%X\n", bhi_info->bhi_status); - MHI_LOG("BHI Error code = 0x%X { Dbg1 = 0x%X Dbg2 = 0x%X Dbg3 = 0x%X }\n", bhi_info->bhi_errorcode, bhi_info->bhi_errdbg1, bhi_info->bhi_errdbg2, bhi_info->bhi_errdbg3); - MHI_LOG("BHI Serial Number = 0x%X\n", bhi_info->bhi_sernum); - MHI_LOG("BHI SBL Anti-Rollback Ver = 0x%X\n", bhi_info->bhi_sblantirollbackver); - MHI_LOG("BHI Number of Segments = 0x%X\n", bhi_info->bhi_numsegs); - for (index = 0; index < 6; index++) - { - snprintf(str+3*index, sizeof(str)-3*index, "%02x ", bhi_info->bhi_msmhwid[index]); - } - MHI_LOG("BHI MSM HW-Id = %s\n", str); - - for (index = 0; index < 24; index++) - { - snprintf(str+3*index, sizeof(str)-3*index, "%02x ", bhi_info->bhi_oempkhash[index]); - } - MHI_LOG("BHI OEM PK Hash = %s\n", str); -} - -static u32 bhi_read_reg(struct mhi_controller *mhi_cntrl, u32 offset) -{ - u32 out = 0; - int ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_EXECENV, &out); - - return (ret) ? 0 : out; -} - -static int BhiRead(struct mhi_controller *mhi_cntrl, BHI_INFO_TYPE *bhi_info) -{ - ULONG index; - - memset(bhi_info, 0x00, sizeof(BHI_INFO_TYPE)); - - /* bhi_ver */ - bhi_info->bhi_ver_minor = bhi_read_reg(mhi_cntrl, BHI_BHIVERSION_MINOR); - bhi_info->bhi_ver_major = bhi_read_reg(mhi_cntrl, BHI_BHIVERSION_MINOR); - bhi_info->bhi_image_address_low = bhi_read_reg(mhi_cntrl, BHI_IMGADDR_LOW); - bhi_info->bhi_image_address_high = bhi_read_reg(mhi_cntrl, BHI_IMGADDR_HIGH); - bhi_info->bhi_image_size = bhi_read_reg(mhi_cntrl, BHI_IMGSIZE); - bhi_info->bhi_rsvd1 = bhi_read_reg(mhi_cntrl, BHI_RSVD1); - bhi_info->bhi_imgtxdb = bhi_read_reg(mhi_cntrl, BHI_IMGTXDB); - bhi_info->bhi_rsvd2 = bhi_read_reg(mhi_cntrl, BHI_RSVD2); - bhi_info->bhi_msivec = bhi_read_reg(mhi_cntrl, BHI_INTVEC); - bhi_info->bhi_rsvd3 = bhi_read_reg(mhi_cntrl, BHI_RSVD3); - bhi_info->bhi_ee = bhi_read_reg(mhi_cntrl, BHI_EXECENV); - bhi_info->bhi_status = bhi_read_reg(mhi_cntrl, BHI_STATUS); - bhi_info->bhi_errorcode = bhi_read_reg(mhi_cntrl, BHI_ERRCODE); - bhi_info->bhi_errdbg1 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG1); - bhi_info->bhi_errdbg2 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG2); - bhi_info->bhi_errdbg3 = bhi_read_reg(mhi_cntrl, BHI_ERRDBG3); - bhi_info->bhi_sernum = bhi_read_reg(mhi_cntrl, BHI_SERIALNU); - bhi_info->bhi_sblantirollbackver = bhi_read_reg(mhi_cntrl, BHI_SBLANTIROLLVER); - bhi_info->bhi_numsegs = bhi_read_reg(mhi_cntrl, BHI_NUMSEG); - for (index = 0; index < MSMHWID_NUMDWORDS; index++) - { - bhi_info->bhi_msmhwid[index] = bhi_read_reg(mhi_cntrl, BHI_MSMHWID(index)); - } - for (index = 0; index < OEMPKHASH_NUMDWORDS; index++) - { - bhi_info->bhi_oempkhash[index] = bhi_read_reg(mhi_cntrl, BHI_OEMPKHASH(index)); - } - bhi_info->bhi_rsvd5 = bhi_read_reg(mhi_cntrl, BHI_RSVD5); - PrintBhiInfo(mhi_cntrl, bhi_info); - /* Check the Execution Environment */ - if (!IsPBLExecEnv(bhi_info->bhi_ee)) - { - MHI_LOG("E - EE: 0x%X Expected PBL/EDL\n", bhi_info->bhi_ee); - } - - /* Return the number of bytes read */ - return 0; -} - -/* setup rddm vector table for rddm transfer */ -static void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, - struct image_info *img_info) -{ - struct mhi_buf *mhi_buf = img_info->mhi_buf; - struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; - int i = 0; - - for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { - MHI_VERB("Setting vector:%pad size:%zu\n", - &mhi_buf->dma_addr, mhi_buf->len); - bhi_vec->dma_addr = mhi_buf->dma_addr; - bhi_vec->size = mhi_buf->len; - } -} - -/* collect rddm during kernel panic */ -static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) -{ - int ret; - struct mhi_buf *mhi_buf; - u32 sequence_id; - u32 rx_status; - enum mhi_ee ee; - struct image_info *rddm_image = mhi_cntrl->rddm_image; - const u32 delayus = 2000; - u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; - const u32 rddm_timeout_us = 200000; - int rddm_retry = rddm_timeout_us / delayus; /* time to enter rddm */ - void __iomem *base = mhi_cntrl->bhie; - - MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - /* - * This should only be executing during a kernel panic, we expect all - * other cores to shutdown while we're collecting rddm buffer. After - * returning from this function, we expect device to reset. - * - * Normaly, we would read/write pm_state only after grabbing - * pm_lock, since we're in a panic, skipping it. Also there is no - * gurantee this state change would take effect since - * we're setting it w/o grabbing pmlock, it's best effort - */ - mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; - /* update should take the effect immediately */ - smp_wmb(); - - /* setup the RX vector table */ - mhi_rddm_prepare(mhi_cntrl, rddm_image); - mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; - - MHI_LOG("Starting BHIe programming for RDDM\n"); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, - upper_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, - lower_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) - sequence_id = get_random_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; -#else - sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; -#endif - if (unlikely(!sequence_id)) - sequence_id = 1; - - - mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, - BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, - sequence_id); - - MHI_LOG("Trigger device into RDDM mode\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); - - MHI_LOG("Waiting for device to enter RDDM\n"); - while (rddm_retry--) { - ee = mhi_get_exec_env(mhi_cntrl); - if (ee == MHI_EE_RDDM) - break; - - udelay(delayus); - } - - if (rddm_retry <= 0) { - /* This is a hardware reset, will force device to enter rddm */ - MHI_LOG( - "Did not enter RDDM triggering host req. reset to force rddm\n"); - mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, - MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); - udelay(delayus); - } - - ee = mhi_get_exec_env(mhi_cntrl); - MHI_LOG("Waiting for image download completion, current EE:%s\n", - TO_MHI_EXEC_STR(ee)); - while (retry--) { - ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, - BHIE_RXVECSTATUS_STATUS_BMSK, - BHIE_RXVECSTATUS_STATUS_SHFT, - &rx_status); - if (ret) - return -EIO; - - if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) { - MHI_LOG("RDDM successfully collected\n"); - return 0; - } - - udelay(delayus); - } - - ee = mhi_get_exec_env(mhi_cntrl); - ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status); - - MHI_ERR("Did not complete RDDM transfer\n"); - MHI_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee)); - MHI_ERR("RXVEC_STATUS:0x%x, ret:%d\n", rx_status, ret); - - return -EIO; -} - -/* download ramdump image from device */ -int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) -{ - void __iomem *base = mhi_cntrl->bhie; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - struct image_info *rddm_image = mhi_cntrl->rddm_image; - struct mhi_buf *mhi_buf; - int ret; - u32 rx_status; - u32 sequence_id; - - if (!rddm_image) - return -ENOMEM; - - if (in_panic) - return __mhi_download_rddm_in_panic(mhi_cntrl); - - MHI_LOG("Waiting for device to enter RDDM state from EE:%s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_RDDM || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI is not in valid state, pm_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - return -EIO; - } - - mhi_rddm_prepare(mhi_cntrl, mhi_cntrl->rddm_image); - - /* vector table is the last entry */ - mhi_buf = &rddm_image->mhi_buf[rddm_image->entries - 1]; - - read_lock_bh(pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_unlock_bh(pm_lock); - return -EIO; - } - - MHI_LOG("Starting BHIe Programming for RDDM\n"); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_HIGH_OFFS, - upper_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECADDR_LOW_OFFS, - lower_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) - sequence_id = get_random_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; -#else - sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; -#endif - mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS, - BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT, - sequence_id); - read_unlock_bh(pm_lock); - - MHI_LOG("Upper:0x%x Lower:0x%x len:0x%zx sequence:%u\n", - upper_32_bits(mhi_buf->dma_addr), - lower_32_bits(mhi_buf->dma_addr), - mhi_buf->len, sequence_id); - MHI_LOG("Waiting for image download completion\n"); - - /* waiting for image download completion */ - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, - BHIE_RXVECSTATUS_OFFS, - BHIE_RXVECSTATUS_STATUS_BMSK, - BHIE_RXVECSTATUS_STATUS_SHFT, - &rx_status) || rx_status, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - return (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO; -} -EXPORT_SYMBOL(mhi_download_rddm_img); - -static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl, - const struct mhi_buf *mhi_buf) -{ - void __iomem *base = mhi_cntrl->bhie; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - u32 tx_status; - - read_lock_bh(pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_unlock_bh(pm_lock); - return -EIO; - } - - MHI_LOG("Starting BHIe Programming\n"); - - mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_HIGH_OFFS, - upper_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_LOW_OFFS, - lower_32_bits(mhi_buf->dma_addr)); - - mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) - mhi_cntrl->sequence_id = get_random_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK; -#else - mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK; -#endif - mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS, - BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, - mhi_cntrl->sequence_id); - read_unlock_bh(pm_lock); - - MHI_LOG("Upper:0x%x Lower:0x%x len:0x%zx sequence:%u\n", - upper_32_bits(mhi_buf->dma_addr), - lower_32_bits(mhi_buf->dma_addr), - mhi_buf->len, mhi_cntrl->sequence_id); - MHI_LOG("Waiting for image transfer completion\n"); - - /* waiting for image download completion */ - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, - BHIE_TXVECSTATUS_OFFS, - BHIE_TXVECSTATUS_STATUS_BMSK, - BHIE_TXVECSTATUS_STATUS_SHFT, - &tx_status) || tx_status, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - return (tx_status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO; -} - -static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, - dma_addr_t dma_addr, - size_t size) -{ - u32 tx_status, val; - u32 ImgTxDb = 0x1; - int i, ret; - void __iomem *base = mhi_cntrl->bhi; - rwlock_t *pm_lock = &mhi_cntrl->pm_lock; - struct { - char *name; - u32 offset; - } error_reg[] = { - { "ERROR_CODE", BHI_ERRCODE }, - { "ERROR_DBG1", BHI_ERRDBG1 }, - { "ERROR_DBG2", BHI_ERRDBG2 }, - { "ERROR_DBG3", BHI_ERRDBG3 }, - { NULL }, - }; - - MHI_LOG("Starting BHI programming\n"); - - /* program start sbl download via bhi protocol */ - read_lock_bh(pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_unlock_bh(pm_lock); - goto invalid_pm_state; - } - - mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH, - upper_32_bits(dma_addr)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW, - lower_32_bits(dma_addr)); - mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size); - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICFG, MHICFG_NER_MASK, MHICFG_NER_SHIFT, NUM_MHI_EVT_RINGS); - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICFG, MHICFG_NHWER_MASK, MHICFG_NHWER_SHIFT, NUM_MHI_HW_EVT_RINGS); - mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, mhi_cntrl->msi_irq_base); - mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, ImgTxDb); - read_unlock_bh(pm_lock); - - MHI_LOG("Waiting for image transfer completion\n"); - - /* waiting for image download completion */ - ret = wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, BHI_STATUS, - BHI_STATUS_MASK, BHI_STATUS_SHIFT, - &tx_status) || tx_status, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - goto invalid_pm_state; - - if (tx_status == BHI_STATUS_ERROR) { - MHI_ERR("Image transfer failed\n"); - read_lock_bh(pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - for (i = 0; error_reg[i].name; i++) { - ret = mhi_read_reg(mhi_cntrl, base, - error_reg[i].offset, &val); - if (ret) - break; - MHI_ERR("reg:%s value:0x%x\n", - error_reg[i].name, val); - } - } - read_unlock_bh(pm_lock); - goto invalid_pm_state; - } - - return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT; - -invalid_pm_state: - - return -EIO; -} - -void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info *image_info) -{ - int i; - struct mhi_buf *mhi_buf = image_info->mhi_buf; - - for (i = 0; i < image_info->entries; i++, mhi_buf++) - mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf, - mhi_buf->dma_addr); - - kfree(image_info->mhi_buf); - kfree(image_info); -} - -int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info **image_info, - size_t alloc_size) -{ - size_t seg_size = mhi_cntrl->seg_len; - /* requier additional entry for vec table */ - int segments = DIV_ROUND_UP(alloc_size, seg_size) + 1; - int i; - struct image_info *img_info; - struct mhi_buf *mhi_buf; - - MHI_LOG("Allocating bytes:%zu seg_size:%zu total_seg:%u\n", - alloc_size, seg_size, segments); - - img_info = kzalloc(sizeof(*img_info), GFP_KERNEL); - if (!img_info) - return -ENOMEM; - - /* allocate memory for entries */ - img_info->mhi_buf = kcalloc(segments, sizeof(*img_info->mhi_buf), - GFP_KERNEL); - if (!img_info->mhi_buf) - goto error_alloc_mhi_buf; - - /* allocate and populate vector table */ - mhi_buf = img_info->mhi_buf; - for (i = 0; i < segments; i++, mhi_buf++) { - size_t vec_size = seg_size; - - /* last entry is for vector table */ - if (i == segments - 1) - vec_size = sizeof(struct bhi_vec_entry) * i; - - mhi_buf->len = vec_size; - mhi_buf->buf = mhi_alloc_coherent(mhi_cntrl, vec_size, - &mhi_buf->dma_addr, GFP_KERNEL); - if (!mhi_buf->buf) - goto error_alloc_segment; - - MHI_LOG("Entry:%d Address:0x%llx size:%zu\n", i, - (unsigned long long)mhi_buf->dma_addr, - mhi_buf->len); - } - - img_info->bhi_vec = img_info->mhi_buf[segments - 1].buf; - img_info->entries = segments; - *image_info = img_info; - - MHI_LOG("Successfully allocated bhi vec table\n"); - - return 0; - -error_alloc_segment: - for (--i, --mhi_buf; i >= 0; i--, mhi_buf--) - mhi_free_coherent(mhi_cntrl, mhi_buf->len, mhi_buf->buf, - mhi_buf->dma_addr); - -error_alloc_mhi_buf: - kfree(img_info); - - return -ENOMEM; -} - -static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl, - const struct firmware *firmware, - struct image_info *img_info) -{ - size_t remainder = firmware->size; - size_t to_cpy; - const u8 *buf = firmware->data; - int i = 0; - struct mhi_buf *mhi_buf = img_info->mhi_buf; - struct bhi_vec_entry *bhi_vec = img_info->bhi_vec; - - while (remainder) { - MHI_ASSERT(i >= img_info->entries, "malformed vector table"); - - to_cpy = min(remainder, mhi_buf->len); - memcpy(mhi_buf->buf, buf, to_cpy); - bhi_vec->dma_addr = mhi_buf->dma_addr; - bhi_vec->size = to_cpy; - - MHI_VERB("Setting Vector:0x%llx size: %llu\n", - bhi_vec->dma_addr, bhi_vec->size); - buf += to_cpy; - remainder -= to_cpy; - i++; - bhi_vec++; - mhi_buf++; - } -} - -void mhi_fw_load_worker(struct work_struct *work) -{ - int ret; - struct mhi_controller *mhi_cntrl; - const char *fw_name; - const struct firmware *firmware; - struct image_info *image_info; - void *buf; - dma_addr_t dma_addr; - size_t size; - - mhi_cntrl = container_of(work, struct mhi_controller, fw_worker); - - MHI_LOG("Waiting for device to enter PBL from EE:%s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - ret = wait_event_timeout(mhi_cntrl->state_event, - MHI_IN_PBL(mhi_cntrl->ee) || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI is not in valid state\n"); - return; - } - - MHI_LOG("Device current EE:%s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - /* if device in pthru, we do not have to load firmware */ - if (mhi_cntrl->ee == MHI_EE_PTHRU) - return; - - fw_name = (mhi_cntrl->ee == MHI_EE_EDL) ? - mhi_cntrl->edl_image : mhi_cntrl->fw_image; - - if (!fw_name || (mhi_cntrl->fbc_download && (!mhi_cntrl->sbl_size || - !mhi_cntrl->seg_len))) { - MHI_ERR("No firmware image defined or !sbl_size || !seg_len\n"); - return; - } - - ret = request_firmware(&firmware, fw_name, mhi_cntrl->dev); - if (ret) { - MHI_ERR("Error loading firmware, ret:%d\n", ret); - return; - } - - size = (mhi_cntrl->fbc_download) ? mhi_cntrl->sbl_size : firmware->size; - - /* the sbl size provided is maximum size, not necessarily image size */ - if (size > firmware->size) - size = firmware->size; - - buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL); - if (!buf) { - MHI_ERR("Could not allocate memory for image\n"); - release_firmware(firmware); - return; - } - - /* load sbl image */ - memcpy(buf, firmware->data, size); - ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size); - mhi_free_coherent(mhi_cntrl, size, buf, dma_addr); - - /* error or in edl, we're done */ - if (ret || mhi_cntrl->ee == MHI_EE_EDL) { - release_firmware(firmware); - return; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_RESET; - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* - * if we're doing fbc, populate vector tables while - * device transitioning into MHI READY state - */ - if (mhi_cntrl->fbc_download) { - ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, - firmware->size); - if (ret) { - MHI_ERR("Error alloc size of %zu\n", firmware->size); - goto error_alloc_fw_table; - } - - MHI_LOG("Copying firmware image into vector table\n"); - - /* load the firmware into BHIE vec table */ - mhi_firmware_copy(mhi_cntrl, firmware, mhi_cntrl->fbc_image); - } - - /* transitioning into MHI RESET->READY state */ - ret = mhi_ready_state_transition(mhi_cntrl); - - MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - if (!mhi_cntrl->fbc_download) { - release_firmware(firmware); - return; - } - - if (ret) { - MHI_ERR("Did not transition to READY state\n"); - goto error_read; - } - - /* wait for SBL event */ - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_SBL || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI did not enter BHIE\n"); - goto error_read; - } - - /* start full firmware image download */ - image_info = mhi_cntrl->fbc_image; - ret = mhi_fw_load_amss(mhi_cntrl, - /* last entry is vec table */ - &image_info->mhi_buf[image_info->entries - 1]); - - MHI_LOG("amss fw_load, ret:%d\n", ret); - - release_firmware(firmware); - - return; - -error_read: - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - -error_alloc_fw_table: - release_firmware(firmware); -} - -int BhiWrite(struct mhi_controller *mhi_cntrl, void __user *ubuf, size_t size) -{ - int ret; - dma_addr_t dma_addr; - void *dma_buf; - - MHI_LOG("Device current EE:%s, M:%s, PM:%s\n", - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)), - TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl)), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - -#if 0 - if (mhi_get_exec_env(mhi_cntrl) == MHI_EE_EDL && mhi_cntrl->ee != MHI_EE_EDL) { - mhi_cntrl->ee = MHI_EE_EDL; - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms + 500)); - } -#endif - -#if 0 - if (!MHI_IN_PBL(mhi_cntrl->ee) || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI is not in valid BHI state\n"); - return -EINVAL; - } -#endif - - if (mhi_cntrl->ee != MHI_EE_EDL) { - MHI_ERR("MHI is not in EDL state\n"); - return -EINVAL; - } - - dma_buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL); - if (!dma_buf) { - MHI_ERR("Could not allocate memory for image\n"); - return -ENOMEM; - } - - ret = copy_from_user(dma_buf, ubuf, size); - if (ret) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE copy buf error, ret = %d\n", ret); - mhi_free_coherent(mhi_cntrl, size, dma_buf, dma_addr);; - return ret; - } - - ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size); - mhi_free_coherent(mhi_cntrl, size, dma_buf, dma_addr); - - if (ret) { - MHI_ERR("ret = %d, ee=%d\n", ret, mhi_cntrl->ee); - goto error_state; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_RESET; - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* transitioning into MHI RESET->READY state */ - ret = mhi_ready_state_transition(mhi_cntrl); - if (ret) { - MHI_ERR("Did not transition to READY state\n"); - goto error_state; - } - - MHI_LOG("To Reset->Ready PM_STATE:%s MHI_STATE:%s EE:%s, ret:%d\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - /* wait for BHIE event */ - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_FP || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI did not enter Flash Programmer Environment\n"); - goto error_state; - } - - MHI_LOG("MHI enter Flash Programmer Environment\n"); - return 0; - -error_state: - MHI_LOG("Device current EE:%s, M:%s\n", - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl)), - TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); - - return ret; -} - -long bhi_get_dev_info(struct mhi_controller *mhi_cntrl, void __user *ubuf) -{ - long ret = -EINVAL; - BHI_INFO_TYPE bhi_info; - - ret = BhiRead(mhi_cntrl, &bhi_info); - if (ret) { - MHI_ERR("IOCTL_BHI_GETDEVINFO BhiRead error, ret = %ld\n", ret); - return ret; - } - - ret = copy_to_user(ubuf, &bhi_info, sizeof(bhi_info)); - if (ret) { - MHI_ERR("IOCTL_BHI_GETDEVINFO copy error, ret = %ld\n", ret); - } - - return ret; -} - -long bhi_write_image(struct mhi_controller *mhi_cntrl, void __user *ubuf) -{ - long ret = -EINVAL; - size_t size; - - ret = copy_from_user(&size, ubuf, sizeof(size)); - if (ret) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, ret = %ld\n", ret); - return ret; - } - if (size <= 0) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, size\n"); - return -EINVAL; - } - ret = BhiWrite(mhi_cntrl, ubuf+sizeof(size), size); - if (ret) { - MHI_ERR("IOCTL_BHI_WRITEIMAGE BhiWrite error, ret = %ld\n", ret); - } - - return ret; -} diff --git a/quectel_MHI/src/core/mhi_dtr.c b/quectel_MHI/src/core/mhi_dtr.c deleted file mode 100644 index 7ce44b3..0000000 --- a/quectel_MHI/src/core/mhi_dtr.c +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -struct __packed dtr_ctrl_msg { - u32 preamble; - u32 msg_id; - u32 dest_id; - u32 size; - u32 msg; -}; - -#define CTRL_MAGIC (0x4C525443) -#define CTRL_MSG_DTR BIT(0) -#define CTRL_MSG_RTS BIT(1) -#define CTRL_MSG_DCD BIT(0) -#define CTRL_MSG_DSR BIT(1) -#define CTRL_MSG_RI BIT(3) -#define CTRL_HOST_STATE (0x10) -#define CTRL_DEVICE_STATE (0x11) -#define CTRL_GET_CHID(dtr) (dtr->dest_id & 0xFF) - -static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl, - struct mhi_device *mhi_dev, - u32 tiocm) -{ - struct dtr_ctrl_msg *dtr_msg = NULL; - struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan; - spinlock_t *res_lock = &mhi_dev->dev.devres_lock; - u32 cur_tiocm; - int ret = 0; - - cur_tiocm = mhi_dev->tiocm & ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI); - - tiocm &= (TIOCM_DTR | TIOCM_RTS); - - /* state did not changed */ - if (cur_tiocm == tiocm) - return 0; - - mutex_lock(&dtr_chan->mutex); - - dtr_msg = kzalloc(sizeof(*dtr_msg), GFP_KERNEL); - if (!dtr_msg) { - ret = -ENOMEM; - goto tiocm_exit; - } - - dtr_msg->preamble = CTRL_MAGIC; - dtr_msg->msg_id = CTRL_HOST_STATE; - dtr_msg->dest_id = mhi_dev->ul_chan_id; - dtr_msg->size = sizeof(u32); - if (tiocm & TIOCM_DTR) - dtr_msg->msg |= CTRL_MSG_DTR; - if (tiocm & TIOCM_RTS) - dtr_msg->msg |= CTRL_MSG_RTS; - -/* -* 'minicom -D /dev/mhi_DUN' will send RTS:1 when open, and RTS:0 when exit. -* RTS:0 will prevent modem output AT response. -* But 'busybox microcom' do not send any RTS to modem. -* [75094.969783] mhi_uci_q 0306_00.03.00_DUN: mhi_dtr_tiocmset DTR:0 RTS:1 -* [75100.210994] mhi_uci_q 0306_00.03.00_DUN: mhi_dtr_tiocmset DTR:0 RTS:0 -*/ - dev_dbg(&mhi_dev->dev, "%s DTR:%d RTS:%d\n", __func__, - !!(tiocm & TIOCM_DTR), !!(tiocm & TIOCM_RTS)); - - reinit_completion(&dtr_chan->completion); - ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg, - sizeof(*dtr_msg), MHI_EOT); - if (ret) - goto tiocm_exit; - - ret = wait_for_completion_timeout(&dtr_chan->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret) { - MHI_ERR("Failed to receive transfer callback\n"); - ret = -EIO; - goto tiocm_exit; - } - - ret = 0; - spin_lock_irq(res_lock); - mhi_dev->tiocm &= ~(TIOCM_DTR | TIOCM_RTS); - mhi_dev->tiocm |= tiocm; - spin_unlock_irq(res_lock); - -tiocm_exit: - kfree(dtr_msg); - mutex_unlock(&dtr_chan->mutex); - - return ret; -} - -long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - int ret; - - /* ioctl not supported by this controller */ - if (!mhi_cntrl->dtr_dev) - return -EIO; - - switch (cmd) { - case TIOCMGET: - return mhi_dev->tiocm; - case TIOCMSET: - { - u32 tiocm; - - ret = get_user(tiocm, (u32 *)arg); - if (ret) - return ret; - - return mhi_dtr_tiocmset(mhi_cntrl, mhi_dev, tiocm); - } - default: - break; - } - - return -EINVAL; -} -EXPORT_SYMBOL(mhi_ioctl); - -static int mhi_dtr_queue_inbound(struct mhi_controller *mhi_cntrl) -{ - struct mhi_device *mhi_dev = mhi_cntrl->dtr_dev; - int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - size_t mtu = mhi_dev->mtu; - void *buf; - int ret = -EIO, i; - - for (i = 0; i < nr_trbs; i++) { - buf = kmalloc(mtu, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, - MHI_EOT); - if (ret) { - kfree(buf); - return ret; - } - } - - return ret; -} - -static void mhi_dtr_dl_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct dtr_ctrl_msg *dtr_msg = mhi_result->buf_addr; - u32 chan; - spinlock_t *res_lock; - - if (mhi_result->transaction_status == -ENOTCONN) { - kfree(mhi_result->buf_addr); - return; - } - - if (mhi_result->bytes_xferd != sizeof(*dtr_msg)) { - MHI_ERR("Unexpected length %zu received\n", - mhi_result->bytes_xferd); - return; - } - - MHI_LOG("preamble:0x%x msg_id:%u dest_id:%u msg:0x%x\n", - dtr_msg->preamble, dtr_msg->msg_id, dtr_msg->dest_id, - dtr_msg->msg); - - chan = CTRL_GET_CHID(dtr_msg); - if (chan >= mhi_cntrl->max_chan) - goto auto_queue; - - mhi_dev = mhi_cntrl->mhi_chan[chan].mhi_dev; - if (!mhi_dev) - goto auto_queue; - - res_lock = &mhi_dev->dev.devres_lock; - spin_lock_irq(res_lock); - mhi_dev->tiocm &= ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI); - - if (dtr_msg->msg & CTRL_MSG_DCD) - mhi_dev->tiocm |= TIOCM_CD; - - if (dtr_msg->msg & CTRL_MSG_DSR) - mhi_dev->tiocm |= TIOCM_DSR; - - if (dtr_msg->msg & CTRL_MSG_RI) - mhi_dev->tiocm |= TIOCM_RI; - spin_unlock_irq(res_lock); - -auto_queue: - mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_FROM_DEVICE, mhi_result->buf_addr, - mhi_cntrl->dtr_dev->mtu, MHI_EOT); -} - -static void mhi_dtr_ul_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan; - - MHI_VERB("Received with status:%d\n", mhi_result->transaction_status); - if (!mhi_result->transaction_status) - complete(&dtr_chan->completion); -} - -static void mhi_dtr_remove(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - mhi_cntrl->dtr_dev = NULL; -} - -static int mhi_dtr_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - int ret; - - MHI_LOG("Enter for DTR control channel\n"); - - mhi_dev->mtu = min_t(size_t, id->driver_data, mhi_dev->mtu); - ret = mhi_prepare_for_transfer(mhi_dev); - if (!ret) - mhi_cntrl->dtr_dev = mhi_dev; - - if (!ret) - ret = mhi_dtr_queue_inbound(mhi_cntrl); - - MHI_LOG("Exit with ret:%d\n", ret); - - return ret; -} - -static const struct mhi_device_id mhi_dtr_table[] = { - { .chan = "IP_CTRL", .driver_data = sizeof(struct dtr_ctrl_msg) }, - {}, -}; - -static struct mhi_driver mhi_dtr_driver = { - .id_table = mhi_dtr_table, - .remove = mhi_dtr_remove, - .probe = mhi_dtr_probe, - .ul_xfer_cb = mhi_dtr_ul_xfer_cb, - .dl_xfer_cb = mhi_dtr_dl_xfer_cb, - .driver = { - .name = "MHI_DTR", - .owner = THIS_MODULE, - } -}; - -int __init mhi_dtr_init(void) -{ - return mhi_driver_register(&mhi_dtr_driver); -} -void mhi_dtr_exit(void) { - mhi_driver_unregister(&mhi_dtr_driver); -} diff --git a/quectel_MHI/src/core/mhi_init.c b/quectel_MHI/src/core/mhi_init.c deleted file mode 100644 index e0c933d..0000000 --- a/quectel_MHI/src/core/mhi_init.c +++ /dev/null @@ -1,2773 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,11,0 )) -#include -#else -#include -#endif -#include "mhi.h" -#include "mhi_internal.h" - -struct mhi_controller_map { - u32 dev_id; - u32 domain; - u32 bus; - u32 slot; - struct mhi_controller *mhi_cntrl; -}; - -#define MAX_MHI_CONTROLLER 16 -struct mhi_controller_map mhi_controller_minors[MAX_MHI_CONTROLLER]; - -#define MHI_CNTRL_DRIVER_NAME "mhi_cntrl_q" -struct mhi_cntrl_drv { - struct list_head head; - struct mutex lock; - struct class *class; - int major; -}; -static struct mhi_cntrl_drv mhi_cntrl_drv; - -const char * const mhi_ee_str[MHI_EE_MAX] = { - [MHI_EE_PBL] = "PBL", - [MHI_EE_SBL] = "SBL", - [MHI_EE_AMSS] = "AMSS", - [MHI_EE_RDDM] = "RDDM", - [MHI_EE_WFW] = "WFW", - [MHI_EE_PTHRU] = "PASS THRU", - [MHI_EE_EDL] = "EDL", - [MHI_EE_FP] = "FlashProg", - [MHI_EE_DISABLE_TRANSITION] = "DISABLE", -}; - -const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX] = { - [MHI_ST_TRANSITION_PBL] = "PBL", - [MHI_ST_TRANSITION_READY] = "READY", - [MHI_ST_TRANSITION_SBL] = "SBL", - [MHI_ST_TRANSITION_MISSION_MODE] = "MISSION MODE", - [MHI_ST_TRANSITION_FP] = "FlashProg", -}; - -const char * const mhi_state_str[MHI_STATE_MAX] = { - [MHI_STATE_RESET] = "RESET", - [MHI_STATE_READY] = "READY", - [MHI_STATE_M0] = "M0", - [MHI_STATE_M1] = "M1", - [MHI_STATE_M2] = "M2", - [MHI_STATE_M3] = "M3", - [MHI_STATE_BHI] = "BHI", - [MHI_STATE_SYS_ERR] = "SYS_ERR", -}; - -static const char * const mhi_pm_state_str[] = { - [MHI_PM_BIT_DISABLE] = "DISABLE", - [MHI_PM_BIT_POR] = "POR", - [MHI_PM_BIT_M0] = "M0", - [MHI_PM_BIT_M2] = "M2", - [MHI_PM_BIT_M3_ENTER] = "M?->M3", - [MHI_PM_BIT_M3] = "M3", - [MHI_PM_BIT_M3_EXIT] = "M3->M0", - [MHI_PM_BIT_FW_DL_ERR] = "FW DL Error", - [MHI_PM_BIT_SYS_ERR_DETECT] = "SYS_ERR Detect", - [MHI_PM_BIT_SYS_ERR_PROCESS] = "SYS_ERR Process", - [MHI_PM_BIT_SHUTDOWN_PROCESS] = "SHUTDOWN Process", - [MHI_PM_BIT_LD_ERR_FATAL_DETECT] = "LD or Error Fatal Detect", -}; - -struct mhi_bus mhi_bus; - -const char *to_mhi_pm_state_str(enum MHI_PM_STATE state) -{ - int index = find_last_bit((unsigned long *)&state, 32); - - if (index >= ARRAY_SIZE(mhi_pm_state_str)) - return "Invalid State"; - - return mhi_pm_state_str[index]; -} - -#if 0 -/* MHI protocol require transfer ring to be aligned to ring length */ -static int mhi_alloc_aligned_ring(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring, - u64 len) -{ - ring->alloc_size = len + (len - 1); - ring->pre_aligned = mhi_alloc_coherent(mhi_cntrl, ring->alloc_size, - &ring->dma_handle, GFP_KERNEL); - if (!ring->pre_aligned) - return -ENOMEM; - - ring->iommu_base = (ring->dma_handle + (len - 1)) & ~(len - 1); - ring->base = ring->pre_aligned + (ring->iommu_base - ring->dma_handle); - return 0; -} -#endif - -static void mhi_ring_aligned_check(struct mhi_controller *mhi_cntrl, u64 rbase, u64 rlen) { - uint64_t ra; - - ra = rbase; - do_div(ra, roundup_pow_of_two(rlen)); - - if (rbase != ra * roundup_pow_of_two(rlen)) { - MHI_ERR("bad params ring base not aligned 0x%llx align 0x%lx\n", rbase, roundup_pow_of_two(rlen)); - } -} - -void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - - - if (mhi_cntrl->msi_allocated == 1) { - free_irq(mhi_cntrl->irq[mhi_cntrl->msi_irq_base], mhi_cntrl); - return; - } - - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - free_irq(mhi_cntrl->irq[mhi_event->msi], mhi_event); - } - - free_irq(mhi_cntrl->irq[mhi_cntrl->msi_irq_base], mhi_cntrl); -} - -int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl) -{ - int i; - int ret; - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - - if (mhi_cntrl->msi_allocated == 1) { - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - mhi_event->msi = 0; - } - - ret = request_threaded_irq(mhi_cntrl->irq[0], NULL, - mhi_one_msi_handlr, IRQF_ONESHOT, "mhi", mhi_cntrl); - if (ret) { - MHI_ERR("Error requesting irq:%d, ret=%d\n", mhi_cntrl->irq[0], ret); - } - return ret; - } - - /* for BHI INTVEC msi */ - ret = request_threaded_irq(mhi_cntrl->irq[mhi_cntrl->msi_irq_base], mhi_intvec_handlr, - mhi_intvec_threaded_handlr, IRQF_ONESHOT, - "mhi", mhi_cntrl); - if (ret) - return ret; - - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - ret = request_irq(mhi_cntrl->irq[mhi_event->msi], - mhi_msi_handlr, IRQF_SHARED, "mhi", - mhi_event); - if (ret) { - MHI_ERR("Error requesting irq:%d for ev:%d\n", - mhi_cntrl->irq[mhi_event->msi], i); - goto error_request; - } - } - - return 0; - -error_request: - for (--i, --mhi_event; i >= 0; i--, mhi_event--) { - if (mhi_event->offload_ev) - continue; - - free_irq(mhi_cntrl->irq[mhi_event->msi], mhi_event); - } - free_irq(mhi_cntrl->irq[0], mhi_cntrl); - - return ret; -} - -void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_ctxt *mhi_ctxt = mhi_cntrl->mhi_ctxt; - struct mhi_cmd *mhi_cmd; - struct mhi_event *mhi_event; - struct mhi_ring *ring; - - mhi_cmd = mhi_cntrl->mhi_cmd; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++) { - ring = &mhi_cmd->ring; -#if 0 - mhi_free_coherent(mhi_cntrl, ring->alloc_size, - ring->pre_aligned, ring->dma_handle); -#endif - ring->base = NULL; - ring->iommu_base = 0; - } - -#if 0 - mhi_free_coherent(mhi_cntrl, - sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS, - mhi_ctxt->cmd_ctxt, mhi_ctxt->cmd_ctxt_addr); -#endif - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - ring = &mhi_event->ring; -#if 0 - mhi_free_coherent(mhi_cntrl, ring->alloc_size, - ring->pre_aligned, ring->dma_handle); -#endif - ring->base = NULL; - ring->iommu_base = 0; - } - -#if 0 - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->er_ctxt) * - mhi_cntrl->total_ev_rings, mhi_ctxt->er_ctxt, - mhi_ctxt->er_ctxt_addr); - - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->chan_ctxt) * - mhi_cntrl->max_chan, mhi_ctxt->chan_ctxt, - mhi_ctxt->chan_ctxt_addr); -#endif - - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->ctrl_seg), mhi_ctxt->ctrl_seg, mhi_ctxt->ctrl_seg_addr); - kfree(mhi_ctxt); - mhi_cntrl->mhi_ctxt = NULL; -} - -static int mhi_init_debugfs_mhi_states_open(struct inode *inode, - struct file *fp) -{ - return single_open(fp, mhi_debugfs_mhi_states_show, inode->i_private); -} - -static int mhi_init_debugfs_mhi_event_open(struct inode *inode, struct file *fp) -{ - return single_open(fp, mhi_debugfs_mhi_event_show, inode->i_private); -} - -static int mhi_init_debugfs_mhi_chan_open(struct inode *inode, struct file *fp) -{ - return single_open(fp, mhi_debugfs_mhi_chan_show, inode->i_private); -} - -static const struct file_operations debugfs_state_ops = { - .open = mhi_init_debugfs_mhi_states_open, - .release = single_release, - .read = seq_read, -}; - -static const struct file_operations debugfs_ev_ops = { - .open = mhi_init_debugfs_mhi_event_open, - .release = single_release, - .read = seq_read, -}; - -static const struct file_operations debugfs_chan_ops = { - .open = mhi_init_debugfs_mhi_chan_open, - .release = single_release, - .read = seq_read, -}; - -DEFINE_SIMPLE_ATTRIBUTE(debugfs_trigger_reset_fops, NULL, - mhi_debugfs_trigger_reset, "%llu\n"); - -#ifdef ENABLE_MHI_MON -struct mon_event_text { - struct list_head e_link; - int type; /* submit, complete, etc. */ - unsigned int tstamp; - u32 chan; - dma_addr_t wp; - struct mhi_tre mhi_tre; - u8 data[32]; - size_t len; -}; - -#define EVENT_MAX (16*PAGE_SIZE / sizeof(struct mon_event_text)) -#define PRINTF_DFL 250 -#define SLAB_NAME_SZ 30 - -struct mon_reader_text { - struct kmem_cache *e_slab; - int nevents; - struct list_head e_list; - struct mon_reader r; /* In C, parent class can be placed anywhere */ - - wait_queue_head_t wait; - int printf_size; - char *printf_buf; - int left_size; - int left_pos; - struct mutex printf_lock; - - char slab_name[SLAB_NAME_SZ]; -}; - -struct mon_text_ptr { - int cnt, limit; - char *pbuf; -}; - -static DEFINE_MUTEX(mon_lock); - -static inline unsigned int mon_get_timestamp(void) -{ - struct timespec64 now; - unsigned int stamp; - - ktime_get_ts64(&now); - stamp = now.tv_sec & 0xFFF; /* 2^32 = 4294967296. Limit to 4096s. */ - stamp = stamp * USEC_PER_SEC + now.tv_nsec / NSEC_PER_USEC; - return stamp; -} - -static void mon_text_event(struct mon_reader_text *rp, - u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len, - char ev_type) -{ - struct mon_event_text *ep; - - if (rp->nevents >= EVENT_MAX || - (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) { - rp->r.m_bus->cnt_text_lost++; - return; - } - - ep->type = ev_type; - ep->tstamp = mon_get_timestamp(); - ep->chan = chan; - ep->wp = wp; - ep->mhi_tre = *mhi_tre; - if (len > sizeof(ep->data)) - len = sizeof(ep->data); - memcpy(ep->data, buf, len); - ep->len = len; - rp->nevents++; - list_add_tail(&ep->e_link, &rp->e_list); - wake_up(&rp->wait); -} - -static void mon_text_submit(void *data, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len) -{ - struct mon_reader_text *rp = data; - mon_text_event(rp, chan, wp, mhi_tre, buf, len, 'W'); -} - -static void mon_text_receive(void *data, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len) -{ - struct mon_reader_text *rp = data; - mon_text_event(rp, chan, wp, mhi_tre, buf, len, 'R'); -} - -static void mon_text_complete(void *data, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre) -{ - struct mon_reader_text *rp = data; - mon_text_event(rp, chan, wp, mhi_tre, NULL, 0, 'E'); -} - -static void mon_reader_add(struct mhi_controller *mbus, struct mon_reader *r) -{ - unsigned long flags; - - spin_lock_irqsave(&mbus->lock, flags); - mbus->nreaders++; - list_add_tail(&r->r_link, &mbus->r_list); - spin_unlock_irqrestore(&mbus->lock, flags); - - kref_get(&mbus->ref); -} - -static void mon_bus_drop(struct kref *r) -{ - struct mhi_controller *mbus = container_of(r, struct mhi_controller, ref); - kfree(mbus); -} - -static void mon_reader_del(struct mhi_controller *mbus, struct mon_reader *r) -{ - unsigned long flags; - - spin_lock_irqsave(&mbus->lock, flags); - list_del(&r->r_link); - --mbus->nreaders; - spin_unlock_irqrestore(&mbus->lock, flags); - - kref_put(&mbus->ref, mon_bus_drop); -} - -static void mon_text_ctor(void *mem) -{ - /* - * Nothing to initialize. No, really! - * So, we fill it with garbage to emulate a reused object. - */ - memset(mem, 0xe5, sizeof(struct mon_event_text)); -} - -static int mon_text_open(struct inode *inode, struct file *file) -{ - struct mhi_controller *mbus; - struct mon_reader_text *rp; - int rc; - - mutex_lock(&mon_lock); - mbus = inode->i_private; - - rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL); - if (rp == NULL) { - rc = -ENOMEM; - goto err_alloc; - } - INIT_LIST_HEAD(&rp->e_list); - init_waitqueue_head(&rp->wait); - mutex_init(&rp->printf_lock); - - rp->printf_size = PRINTF_DFL; - rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL); - if (rp->printf_buf == NULL) { - rc = -ENOMEM; - goto err_alloc_pr; - } - - rp->r.m_bus = mbus; - rp->r.r_data = rp; - rp->r.rnf_submit = mon_text_submit; - rp->r.rnf_receive = mon_text_receive; - rp->r.rnf_complete = mon_text_complete; - - snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp); - rp->e_slab = kmem_cache_create(rp->slab_name, - sizeof(struct mon_event_text), sizeof(long), 0, - mon_text_ctor); - if (rp->e_slab == NULL) { - rc = -ENOMEM; - goto err_slab; - } - - mon_reader_add(mbus, &rp->r); - - file->private_data = rp; - mutex_unlock(&mon_lock); - return 0; - -// err_busy: -// kmem_cache_destroy(rp->e_slab); -err_slab: - kfree(rp->printf_buf); -err_alloc_pr: - kfree(rp); -err_alloc: - mutex_unlock(&mon_lock); - return rc; -} - -static struct mon_event_text *mon_text_fetch(struct mon_reader_text *rp, - struct mhi_controller *mbus) -{ - struct list_head *p; - unsigned long flags; - - spin_lock_irqsave(&mbus->lock, flags); - if (list_empty(&rp->e_list)) { - spin_unlock_irqrestore(&mbus->lock, flags); - return NULL; - } - p = rp->e_list.next; - list_del(p); - --rp->nevents; - spin_unlock_irqrestore(&mbus->lock, flags); - return list_entry(p, struct mon_event_text, e_link); -} - -static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp, - struct file *file) -{ - struct mhi_controller *mbus = rp->r.m_bus; - DECLARE_WAITQUEUE(waita, current); - struct mon_event_text *ep; - - add_wait_queue(&rp->wait, &waita); - set_current_state(TASK_INTERRUPTIBLE); - while ((ep = mon_text_fetch(rp, mbus)) == NULL) { - if (file->f_flags & O_NONBLOCK) { - set_current_state(TASK_RUNNING); - remove_wait_queue(&rp->wait, &waita); - return ERR_PTR(-EWOULDBLOCK); - } - /* - * We do not count nwaiters, because ->release is supposed - * to be called when all openers are gone only. - */ - schedule(); - if (signal_pending(current)) { - remove_wait_queue(&rp->wait, &waita); - return ERR_PTR(-EINTR); - } - set_current_state(TASK_INTERRUPTIBLE); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&rp->wait, &waita); - return ep; -} - -static ssize_t mon_text_read_u(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) -{ - struct mon_reader_text *rp = file->private_data; - struct mon_event_text *ep; - struct mon_text_ptr ptr; - - if (rp->left_size) { - int cnt = rp->left_size; - - if (cnt > nbytes) - cnt = nbytes; - if (copy_to_user(buf, rp->printf_buf + rp->left_pos, cnt)) - return -EFAULT; - rp->left_pos += cnt; - rp->left_size -= cnt; - return cnt; - } - - if (IS_ERR(ep = mon_text_read_wait(rp, file))) - return PTR_ERR(ep); - mutex_lock(&rp->printf_lock); - ptr.cnt = 0; - ptr.pbuf = rp->printf_buf; - ptr.limit = rp->printf_size; - - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, - "%u %c %03d WP:%llx TRE: %llx %08x %08x", - ep->tstamp, ep->type, ep->chan, (long long unsigned int)ep->wp, - ep->mhi_tre.ptr, ep->mhi_tre.dword[0], ep->mhi_tre.dword[1]); - - if (ep->len) { - struct mon_text_ptr *p = &ptr; - size_t i = 0; - - for (i = 0; i < ep->len; i++) { - if (i % 4 == 0) { - p->cnt += snprintf(p->pbuf + p->cnt, - p->limit - p->cnt, - " "); - } - p->cnt += snprintf(p->pbuf + p->cnt, - p->limit - p->cnt, - "%02x", ep->data[i]); - } - - } - - ptr.cnt += snprintf(ptr.pbuf +ptr.cnt, ptr.limit - ptr.cnt, "\n"); - - if (ptr.cnt > nbytes) { - rp->left_pos = nbytes; - rp->left_size = ptr.cnt - nbytes; - ptr.cnt = nbytes; - } - - if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) - ptr.cnt = -EFAULT; - mutex_unlock(&rp->printf_lock); - kmem_cache_free(rp->e_slab, ep); - return ptr.cnt; -} - -static int mon_text_release(struct inode *inode, struct file *file) -{ - struct mon_reader_text *rp = file->private_data; - struct mhi_controller *mbus; - /* unsigned long flags; */ - struct list_head *p; - struct mon_event_text *ep; - - mutex_lock(&mon_lock); - mbus = inode->i_private; - - if (mbus->nreaders <= 0) { - mutex_unlock(&mon_lock); - return 0; - } - mon_reader_del(mbus, &rp->r); - - /* - * In theory, e_list is protected by mbus->lock. However, - * after mon_reader_del has finished, the following is the case: - * - we are not on reader list anymore, so new events won't be added; - * - whole mbus may be dropped if it was orphaned. - * So, we better not touch mbus. - */ - /* spin_lock_irqsave(&mbus->lock, flags); */ - while (!list_empty(&rp->e_list)) { - p = rp->e_list.next; - ep = list_entry(p, struct mon_event_text, e_link); - list_del(p); - --rp->nevents; - kmem_cache_free(rp->e_slab, ep); - } - /* spin_unlock_irqrestore(&mbus->lock, flags); */ - - kmem_cache_destroy(rp->e_slab); - kfree(rp->printf_buf); - kfree(rp); - - mutex_unlock(&mon_lock); - return 0; -} - - -static const struct file_operations mon_fops_text_u = { - .owner = THIS_MODULE, - .open = mon_text_open, - .llseek = no_llseek, - .read = mon_text_read_u, - .release = mon_text_release, -}; -#endif - -void mhi_init_debugfs(struct mhi_controller *mhi_cntrl) -{ - struct dentry *dentry; - char node[64]; - -#ifdef ENABLE_MHI_MON - struct mhi_controller *mbus = mhi_cntrl; - - mbus->nreaders = 0; - kref_init(&mbus->ref); - spin_lock_init(&mbus->lock); - INIT_LIST_HEAD(&mbus->r_list); -#endif - - if (!mhi_cntrl->parent) - snprintf(node, sizeof(node), "mhi_%04x_%02x:%02x.%02x", - mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus, - mhi_cntrl->slot); - else - snprintf(node, sizeof(node), "%04x_%02x:%02x.%02x", - mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus, - mhi_cntrl->slot); - - dentry = debugfs_create_dir(node, mhi_cntrl->parent); - if (IS_ERR_OR_NULL(dentry)) - return; - - debugfs_create_file("states", 0444, dentry, mhi_cntrl, - &debugfs_state_ops); - debugfs_create_file("events", 0444, dentry, mhi_cntrl, - &debugfs_ev_ops); - debugfs_create_file("chan", 0444, dentry, mhi_cntrl, - &debugfs_chan_ops); - debugfs_create_file("reset", 0444, dentry, mhi_cntrl, - &debugfs_trigger_reset_fops); -#ifdef ENABLE_MHI_MON - debugfs_create_file("mhimon", 0444, dentry, mhi_cntrl, - &mon_fops_text_u); -#endif - mhi_cntrl->dentry = dentry; -} - -void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl) -{ - debugfs_remove_recursive(mhi_cntrl->dentry); - mhi_cntrl->dentry = NULL; -} - -int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl) -{ - struct mhi_ctxt *mhi_ctxt; - struct mhi_chan_ctxt *chan_ctxt; - struct mhi_event_ctxt *er_ctxt; - struct mhi_cmd_ctxt *cmd_ctxt; - struct mhi_chan *mhi_chan; - struct mhi_event *mhi_event; - struct mhi_cmd *mhi_cmd; - int ret = -ENOMEM, i; - - atomic_set(&mhi_cntrl->dev_wake, 0); - atomic_set(&mhi_cntrl->alloc_size, 0); - atomic_set(&mhi_cntrl->pending_pkts, 0); - - mhi_ctxt = kzalloc(sizeof(*mhi_ctxt), GFP_KERNEL); - if (!mhi_ctxt) - return -ENOMEM; - - mhi_ctxt->ctrl_seg = mhi_alloc_coherent(mhi_cntrl, sizeof(*mhi_ctxt->ctrl_seg), - &mhi_ctxt->ctrl_seg_addr, GFP_KERNEL); - MHI_LOG("mhi_ctxt->ctrl_seg = %p\n", mhi_ctxt->ctrl_seg); - if (!mhi_ctxt->ctrl_seg) - goto error_alloc_chan_ctxt; - - if ((unsigned long)mhi_ctxt->ctrl_seg & (4096-1)) { - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->ctrl_seg), mhi_ctxt->ctrl_seg, mhi_ctxt->ctrl_seg_addr); - goto error_alloc_chan_ctxt; - } - - /* setup channel ctxt */ -#if 1 - mhi_ctxt->chan_ctxt = mhi_ctxt->ctrl_seg->chan_ctxt; - mhi_ctxt->chan_ctxt_addr = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, chan_ctxt); -#else - mhi_ctxt->chan_ctxt = mhi_alloc_coherent(mhi_cntrl, - sizeof(*mhi_ctxt->chan_ctxt) * mhi_cntrl->max_chan, - &mhi_ctxt->chan_ctxt_addr, GFP_KERNEL); - if (!mhi_ctxt->chan_ctxt) - goto error_alloc_chan_ctxt; -#endif - - mhi_chan = mhi_cntrl->mhi_chan; - chan_ctxt = mhi_ctxt->chan_ctxt; - for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) { - /* If it's offload channel skip this step */ - if (mhi_chan->offload_ch) - continue; - - chan_ctxt->chstate = MHI_CH_STATE_DISABLED; - chan_ctxt->brstmode = mhi_chan->db_cfg.brstmode; - chan_ctxt->pollcfg = mhi_chan->db_cfg.pollcfg; - chan_ctxt->chtype = mhi_chan->type; - chan_ctxt->erindex = mhi_chan->er_index; - - mhi_chan->ch_state = MHI_CH_STATE_DISABLED; - mhi_chan->tre_ring.db_addr = &chan_ctxt->wp; - } - - /* setup event context */ -#if 1 - mhi_ctxt->er_ctxt = mhi_ctxt->ctrl_seg->er_ctxt; - mhi_ctxt->er_ctxt_addr = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, er_ctxt); -#else - mhi_ctxt->er_ctxt = mhi_alloc_coherent(mhi_cntrl, - sizeof(*mhi_ctxt->er_ctxt) * mhi_cntrl->total_ev_rings, - &mhi_ctxt->er_ctxt_addr, GFP_KERNEL); - if (!mhi_ctxt->er_ctxt) - goto error_alloc_er_ctxt; -#endif - - er_ctxt = mhi_ctxt->er_ctxt; - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, er_ctxt++, - mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - /* it's a satellite ev, we do not touch it */ - if (mhi_event->offload_ev) - continue; - - er_ctxt->intmodc = 0; - er_ctxt->intmodt = mhi_event->intmod; - er_ctxt->ertype = MHI_ER_TYPE_VALID; - if (mhi_cntrl->msi_allocated == 1) { - mhi_event->msi = 0; - } - er_ctxt->msivec = mhi_event->msi; - mhi_event->db_cfg.db_mode = true; - - ring->el_size = sizeof(struct mhi_tre); - ring->len = ring->el_size * ring->elements; -#if 1 - ring->alloc_size = ring->len; - ring->pre_aligned = mhi_ctxt->ctrl_seg->event_ring[i]; - ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, event_ring[i]); - ring->iommu_base = ring->dma_handle; - ring->base = ring->pre_aligned + (ring->iommu_base - ring->dma_handle); -#else - ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len); - if (ret) - goto error_alloc_er; -#endif - - ring->rp = ring->wp = ring->base; - er_ctxt->rbase = ring->iommu_base; - er_ctxt->rp = er_ctxt->wp = er_ctxt->rbase; - er_ctxt->rlen = ring->len; - ring->ctxt_wp = &er_ctxt->wp; - - mhi_ring_aligned_check(mhi_cntrl, er_ctxt->rbase, er_ctxt->rlen); - memset(ring->base, 0xCC, ring->len); - } - - /* setup cmd context */ -#if 1 - mhi_ctxt->cmd_ctxt = mhi_ctxt->ctrl_seg->cmd_ctxt; - mhi_ctxt->cmd_ctxt_addr = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, cmd_ctxt); -#else - mhi_ctxt->cmd_ctxt = mhi_alloc_coherent(mhi_cntrl, - sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS, - &mhi_ctxt->cmd_ctxt_addr, GFP_KERNEL); - if (!mhi_ctxt->cmd_ctxt) - goto error_alloc_er; -#endif - - mhi_cmd = mhi_cntrl->mhi_cmd; - cmd_ctxt = mhi_ctxt->cmd_ctxt; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++, cmd_ctxt++) { - struct mhi_ring *ring = &mhi_cmd->ring; - - ring->el_size = sizeof(struct mhi_tre); - ring->elements = CMD_EL_PER_RING; - ring->len = ring->el_size * ring->elements; -#if 1 - ring->alloc_size = ring->len; - ring->pre_aligned = mhi_ctxt->ctrl_seg->cmd_ring[i]; - ring->dma_handle = mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, cmd_ring[i]); - ring->iommu_base = ring->dma_handle; - ring->base = ring->pre_aligned + (ring->iommu_base - ring->dma_handle); -#else - ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len); - if (ret) - goto error_alloc_cmd; -#endif - - ring->rp = ring->wp = ring->base; - cmd_ctxt->rbase = ring->iommu_base; - cmd_ctxt->rp = cmd_ctxt->wp = cmd_ctxt->rbase; - cmd_ctxt->rlen = ring->len; - ring->ctxt_wp = &cmd_ctxt->wp; - - mhi_ring_aligned_check(mhi_cntrl, cmd_ctxt->rbase, cmd_ctxt->rlen); - } - - mhi_cntrl->mhi_ctxt = mhi_ctxt; - - return 0; - -#if 0 -error_alloc_cmd: - for (--i, --mhi_cmd; i >= 0; i--, mhi_cmd--) { - struct mhi_ring *ring = &mhi_cmd->ring; - - mhi_free_coherent(mhi_cntrl, ring->alloc_size, - ring->pre_aligned, ring->dma_handle); - } - mhi_free_coherent(mhi_cntrl, - sizeof(*mhi_ctxt->cmd_ctxt) * NR_OF_CMD_RINGS, - mhi_ctxt->cmd_ctxt, mhi_ctxt->cmd_ctxt_addr); - i = mhi_cntrl->total_ev_rings; - mhi_event = mhi_cntrl->mhi_event + i; - -error_alloc_er: - for (--i, --mhi_event; i >= 0; i--, mhi_event--) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev) - continue; - - mhi_free_coherent(mhi_cntrl, ring->alloc_size, - ring->pre_aligned, ring->dma_handle); - } - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->er_ctxt) * - mhi_cntrl->total_ev_rings, mhi_ctxt->er_ctxt, - mhi_ctxt->er_ctxt_addr); - -error_alloc_er_ctxt: - mhi_free_coherent(mhi_cntrl, sizeof(*mhi_ctxt->chan_ctxt) * - mhi_cntrl->max_chan, mhi_ctxt->chan_ctxt, - mhi_ctxt->chan_ctxt_addr); -#endif - -error_alloc_chan_ctxt: - kfree(mhi_ctxt); - - return ret; -} - -static int mhi_get_tsync_er_cfg(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - - /* find event ring with timesync support */ - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) - if (mhi_event->data_type == MHI_ER_TSYNC_ELEMENT_TYPE) - return mhi_event->er_index; - - return -ENOENT; -} - -int mhi_init_timesync(struct mhi_controller *mhi_cntrl) -{ - struct mhi_timesync *mhi_tsync; - u32 time_offset, db_offset; - int ret; - - read_lock_bh(&mhi_cntrl->pm_lock); - - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - ret = -EIO; - goto exit_timesync; - } - - ret = mhi_get_capability_offset(mhi_cntrl, TIMESYNC_CAP_ID, - &time_offset); - if (ret) { - MHI_LOG("No timesync capability found\n"); - goto exit_timesync; - } - - read_unlock_bh(&mhi_cntrl->pm_lock); - - if (!mhi_cntrl->time_get || !mhi_cntrl->lpm_disable || - !mhi_cntrl->lpm_enable) - return -EINVAL; - - /* register method supported */ - mhi_tsync = kzalloc(sizeof(*mhi_tsync), GFP_KERNEL); - if (!mhi_tsync) - return -ENOMEM; - - spin_lock_init(&mhi_tsync->lock); - INIT_LIST_HEAD(&mhi_tsync->head); - init_completion(&mhi_tsync->completion); - - /* save time_offset for obtaining time */ - MHI_LOG("TIME OFFS:0x%x\n", time_offset); - mhi_tsync->time_reg = mhi_cntrl->regs + time_offset - + TIMESYNC_TIME_LOW_OFFSET; - - mhi_cntrl->mhi_tsync = mhi_tsync; - - ret = mhi_create_timesync_sysfs(mhi_cntrl); - if (unlikely(ret)) { - /* kernel method still work */ - MHI_ERR("Failed to create timesync sysfs nodes\n"); - } - - read_lock_bh(&mhi_cntrl->pm_lock); - - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - ret = -EIO; - goto exit_timesync; - } - - /* get DB offset if supported, else return */ - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, - time_offset + TIMESYNC_DB_OFFSET, &db_offset); - if (ret || !db_offset) { - ret = 0; - goto exit_timesync; - } - - MHI_LOG("TIMESYNC_DB OFFS:0x%x\n", db_offset); - mhi_tsync->db = mhi_cntrl->regs + db_offset; - - read_unlock_bh(&mhi_cntrl->pm_lock); - - /* get time-sync event ring configuration */ - ret = mhi_get_tsync_er_cfg(mhi_cntrl); - if (ret < 0) { - MHI_LOG("Could not find timesync event ring\n"); - return ret; - } - - mhi_tsync->er_index = ret; - - ret = mhi_send_cmd(mhi_cntrl, NULL, MHI_CMD_TIMSYNC_CFG); - if (ret) { - MHI_ERR("Failed to send time sync cfg cmd\n"); - return ret; - } - - ret = wait_for_completion_timeout(&mhi_tsync->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || mhi_tsync->ccs != MHI_EV_CC_SUCCESS) { - MHI_ERR("Failed to get time cfg cmd completion\n"); - return -EIO; - } - - return 0; - -exit_timesync: - read_unlock_bh(&mhi_cntrl->pm_lock); - - return ret; -} - -int mhi_init_mmio(struct mhi_controller *mhi_cntrl) -{ - u32 val = 0; - int i, ret; - struct mhi_chan *mhi_chan; - struct mhi_event *mhi_event; - void __iomem *base = mhi_cntrl->regs; - struct { - u32 offset; - u32 mask; - u32 shift; - u32 val; - } reg_info[] = { - { - CCABAP_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr), - }, - { - CCABAP_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->chan_ctxt_addr), - }, - { - ECABAP_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr), - }, - { - ECABAP_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->er_ctxt_addr), - }, - { - CRCBAP_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr), - }, - { - CRCBAP_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->cmd_ctxt_addr), - }, -#if 0 //carl.yin 20190527 UDE-WIN-InitMmio - { - MHICFG, MHICFG_NER_MASK, MHICFG_NER_SHIFT, - mhi_cntrl->total_ev_rings, - }, - { - MHICFG, MHICFG_NHWER_MASK, MHICFG_NHWER_SHIFT, - mhi_cntrl->hw_ev_rings, - }, -#endif - { - MHICTRLBASE_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->ctrl_seg_addr), - }, - { - MHICTRLBASE_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->ctrl_seg_addr), - }, - { - MHIDATABASE_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->iova_start), - }, - { - MHIDATABASE_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->iova_start), - }, - { - MHICTRLLIMIT_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->mhi_ctxt->ctrl_seg_addr+sizeof(struct mhi_ctrl_seg)), - }, - { - MHICTRLLIMIT_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->mhi_ctxt->ctrl_seg_addr+sizeof(struct mhi_ctrl_seg)), - }, - { - MHIDATALIMIT_HIGHER, U32_MAX, 0, - upper_32_bits(mhi_cntrl->iova_stop), - }, - { - MHIDATALIMIT_LOWER, U32_MAX, 0, - lower_32_bits(mhi_cntrl->iova_stop), - }, - { 0, 0, 0, 0 } - }; - - MHI_LOG("Initializing MMIO\n"); - - /* set up DB register for all the chan rings */ - ret = mhi_read_reg_field(mhi_cntrl, base, CHDBOFF, CHDBOFF_CHDBOFF_MASK, - CHDBOFF_CHDBOFF_SHIFT, &val); - if (ret) - return -EIO; - - MHI_LOG("CHDBOFF:0x%x\n", val); - - /* setup wake db */ - mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB); -#if 0 //'EM120RGLAPR02A07M4G_11' will treate as chan 127's interrput, and report complete event over cmd ring, but cmd ring is not set by now - mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 4, 0); - mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 0, 0); - mhi_cntrl->wake_set = false; -#endif - - /* setup channel db addresses */ - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, val += 8, mhi_chan++) - mhi_chan->tre_ring.db_addr = base + val; - - /* setup event ring db addresses */ - ret = mhi_read_reg_field(mhi_cntrl, base, ERDBOFF, ERDBOFF_ERDBOFF_MASK, - ERDBOFF_ERDBOFF_SHIFT, &val); - if (ret) - return -EIO; - - MHI_LOG("ERDBOFF:0x%x\n", val); - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, val += 8, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - mhi_event->ring.db_addr = base + val; - } - - /* set up DB register for primary CMD rings */ - mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING].ring.db_addr = base + CRDB_LOWER; - - MHI_LOG("Programming all MMIO values.\n"); - for (i = 0; reg_info[i].offset; i++) - mhi_write_reg_field(mhi_cntrl, base, reg_info[i].offset, - reg_info[i].mask, reg_info[i].shift, - reg_info[i].val); - - return 0; -} - -void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring; - struct mhi_ring *tre_ring; - struct mhi_chan_ctxt *chan_ctxt; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan]; - -#if 0 - mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size, - tre_ring->pre_aligned, tre_ring->dma_handle); -#endif - kfree(buf_ring->base); - - buf_ring->base = tre_ring->base = NULL; - chan_ctxt->rbase = 0; -} - -int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring; - struct mhi_ring *tre_ring; - struct mhi_chan_ctxt *chan_ctxt; - int ret; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - tre_ring->el_size = sizeof(struct mhi_tre); - tre_ring->len = tre_ring->el_size * tre_ring->elements; - chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan]; -#if 1 - tre_ring->alloc_size = tre_ring->len; - if (MHI_CLIENT_IP_HW_0_IN == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->hw_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, hw_in_chan_ring[mhi_chan->ring]); - } - else if (MHI_CLIENT_IP_HW_0_OUT == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->hw_out_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, hw_out_chan_ring[mhi_chan->ring]); - } -#ifdef ENABLE_IP_SW0 - else if (MHI_CLIENT_IP_SW_0_IN == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->sw_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, sw_in_chan_ring[mhi_chan->ring]); - } - else if (MHI_CLIENT_IP_SW_0_OUT == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->sw_out_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, sw_out_chan_ring[mhi_chan->ring]); - } -#endif - -#ifdef ENABLE_ADPL - else if (MHI_CLIENT_ADPL == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->adpl_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, adpl_in_chan_ring[mhi_chan->ring]); - } -#endif - -#ifdef ENABLE_QDSS - else if (MHI_CLIENT_IP_HW_QDSS == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->qdss_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, qdss_in_chan_ring[mhi_chan->ring]); - } -#endif - - else if (MHI_CLIENT_DIAG_IN == mhi_chan->chan) { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->diag_in_chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, diag_in_chan_ring[mhi_chan->ring]); - } - else { - tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->chan_ring[mhi_chan->ring]; - tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, chan_ring[mhi_chan->ring]); - } - tre_ring->iommu_base = tre_ring->dma_handle; - tre_ring->base = tre_ring->pre_aligned + (tre_ring->iommu_base - tre_ring->dma_handle); - ret = 0; -#else - ret = mhi_alloc_aligned_ring(mhi_cntrl, tre_ring, tre_ring->len); -#endif - if (ret) - return -ENOMEM; - - buf_ring->el_size = sizeof(struct mhi_buf_info); - buf_ring->len = buf_ring->el_size * buf_ring->elements; - buf_ring->base = kzalloc(buf_ring->len, GFP_KERNEL); - - if (!buf_ring->base) { -#if 0 - mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size, - tre_ring->pre_aligned, tre_ring->dma_handle); -#endif - return -ENOMEM; - } - - chan_ctxt->chstate = MHI_CH_STATE_ENABLED; - chan_ctxt->rbase = tre_ring->iommu_base; - chan_ctxt->rp = chan_ctxt->wp = chan_ctxt->rbase; - chan_ctxt->rlen = tre_ring->len; - tre_ring->ctxt_wp = &chan_ctxt->wp; - - tre_ring->rp = tre_ring->wp = tre_ring->base; - buf_ring->rp = buf_ring->wp = buf_ring->base; - mhi_chan->db_cfg.db_mode = true; - - mhi_ring_aligned_check(mhi_cntrl, chan_ctxt->rbase, chan_ctxt->rlen); - /* update to all cores */ - smp_wmb(); - - return 0; -} - -int mhi_device_configure(struct mhi_device *mhi_dev, - enum dma_data_direction dir, - struct mhi_buf *cfg_tbl, - int elements) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - struct mhi_event_ctxt *er_ctxt; - struct mhi_chan_ctxt *ch_ctxt; - int er_index, chan; - - switch (dir) { - case DMA_TO_DEVICE: - mhi_chan = mhi_dev->ul_chan; - break; - case DMA_BIDIRECTIONAL: - case DMA_FROM_DEVICE: - case DMA_NONE: - mhi_chan = mhi_dev->dl_chan; - break; - default: - return -EINVAL; - } - - er_index = mhi_chan->er_index; - chan = mhi_chan->chan; - - for (; elements > 0; elements--, cfg_tbl++) { - /* update event context array */ - if (!strcmp(cfg_tbl->name, "ECA")) { - er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[er_index]; - if (sizeof(*er_ctxt) != cfg_tbl->len) { - MHI_ERR( - "Invalid ECA size, expected:%zu actual%zu\n", - sizeof(*er_ctxt), cfg_tbl->len); - return -EINVAL; - } - memcpy((void *)er_ctxt, cfg_tbl->buf, sizeof(*er_ctxt)); - continue; - } - - /* update channel context array */ - if (!strcmp(cfg_tbl->name, "CCA")) { - ch_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[chan]; - if (cfg_tbl->len != sizeof(*ch_ctxt)) { - MHI_ERR( - "Invalid CCA size, expected:%zu actual:%zu\n", - sizeof(*ch_ctxt), cfg_tbl->len); - return -EINVAL; - } - memcpy((void *)ch_ctxt, cfg_tbl->buf, sizeof(*ch_ctxt)); - continue; - } - - return -EINVAL; - } - - return 0; -} - -#if 0 -static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - int i, ret, num = 0; - struct mhi_event *mhi_event; - struct device_node *child; - - of_node = of_find_node_by_name(of_node, "mhi_events"); - if (!of_node) - return -EINVAL; - - for_each_available_child_of_node(of_node, child) { - if (!strcmp(child->name, "mhi_event")) - num++; - } - - if (!num) - return -EINVAL; - - mhi_cntrl->total_ev_rings = num; - mhi_cntrl->mhi_event = kcalloc(num, sizeof(*mhi_cntrl->mhi_event), - GFP_KERNEL); - if (!mhi_cntrl->mhi_event) - return -ENOMEM; - - /* populate ev ring */ - mhi_event = mhi_cntrl->mhi_event; - i = 0; - for_each_available_child_of_node(of_node, child) { - if (strcmp(child->name, "mhi_event")) - continue; - - mhi_event->er_index = i++; - ret = of_property_read_u32(child, "mhi,num-elements", - (u32 *)&mhi_event->ring.elements); - if (ret) - goto error_ev_cfg; - - ret = of_property_read_u32(child, "mhi,intmod", - &mhi_event->intmod); - if (ret) - goto error_ev_cfg; - - ret = of_property_read_u32(child, "mhi,msi", - &mhi_event->msi); - if (ret) - goto error_ev_cfg; - - ret = of_property_read_u32(child, "mhi,chan", - &mhi_event->chan); - if (!ret) { - if (mhi_event->chan >= mhi_cntrl->max_chan) - goto error_ev_cfg; - /* this event ring has a dedicated channel */ - mhi_event->mhi_chan = - &mhi_cntrl->mhi_chan[mhi_event->chan]; - } - - ret = of_property_read_u32(child, "mhi,priority", - &mhi_event->priority); - if (ret) - goto error_ev_cfg; - - ret = of_property_read_u32(child, "mhi,brstmode", - &mhi_event->db_cfg.brstmode); - if (ret || MHI_INVALID_BRSTMODE(mhi_event->db_cfg.brstmode)) - goto error_ev_cfg; - - mhi_event->db_cfg.process_db = - (mhi_event->db_cfg.brstmode == MHI_BRSTMODE_ENABLE) ? - mhi_db_brstmode : mhi_db_brstmode_disable; - - ret = of_property_read_u32(child, "mhi,data-type", - &mhi_event->data_type); - if (ret) - mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE; - - if (mhi_event->data_type > MHI_ER_DATA_TYPE_MAX) - goto error_ev_cfg; - - switch (mhi_event->data_type) { - case MHI_ER_DATA_ELEMENT_TYPE: - mhi_event->process_event = mhi_process_data_event_ring; - break; - case MHI_ER_CTRL_ELEMENT_TYPE: - mhi_event->process_event = mhi_process_ctrl_ev_ring; - break; - case MHI_ER_TSYNC_ELEMENT_TYPE: - mhi_event->process_event = mhi_process_tsync_event_ring; - break; - } - - mhi_event->hw_ring = of_property_read_bool(child, "mhi,hw-ev"); - if (mhi_event->hw_ring) - mhi_cntrl->hw_ev_rings++; - else - mhi_cntrl->sw_ev_rings++; - mhi_event->cl_manage = of_property_read_bool(child, - "mhi,client-manage"); - mhi_event->offload_ev = of_property_read_bool(child, - "mhi,offload"); - mhi_event++; - } - - /* we need msi for each event ring + additional one for BHI */ - mhi_cntrl->msi_required = mhi_cntrl->total_ev_rings + 1; - - return 0; - -error_ev_cfg: - - kfree(mhi_cntrl->mhi_event); - return -EINVAL; -} -static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - int ret; - struct device_node *child; - u32 chan; - - ret = of_property_read_u32(of_node, "mhi,max-channels", - &mhi_cntrl->max_chan); - if (ret) - return ret; - - of_node = of_find_node_by_name(of_node, "mhi_channels"); - if (!of_node) - return -EINVAL; - - mhi_cntrl->mhi_chan = kcalloc(mhi_cntrl->max_chan, - sizeof(*mhi_cntrl->mhi_chan), GFP_KERNEL); - if (!mhi_cntrl->mhi_chan) - return -ENOMEM; - - INIT_LIST_HEAD(&mhi_cntrl->lpm_chans); - - /* populate channel configurations */ - for_each_available_child_of_node(of_node, child) { - struct mhi_chan *mhi_chan; - - if (strcmp(child->name, "mhi_chan")) - continue; - - ret = of_property_read_u32(child, "reg", &chan); - if (ret || chan >= mhi_cntrl->max_chan) - goto error_chan_cfg; - - mhi_chan = &mhi_cntrl->mhi_chan[chan]; - - ret = of_property_read_string(child, "label", - &mhi_chan->name); - if (ret) - goto error_chan_cfg; - - mhi_chan->chan = chan; - - ret = of_property_read_u32(child, "mhi,num-elements", - (u32 *)&mhi_chan->tre_ring.elements); - if (!ret && !mhi_chan->tre_ring.elements) - goto error_chan_cfg; - - /* - * For some channels, local ring len should be bigger than - * transfer ring len due to internal logical channels in device. - * So host can queue much more buffers than transfer ring len. - * Example, RSC channels should have a larger local channel - * than transfer ring length. - */ - ret = of_property_read_u32(child, "mhi,local-elements", - (u32 *)&mhi_chan->buf_ring.elements); - if (ret) - mhi_chan->buf_ring.elements = - mhi_chan->tre_ring.elements; - - ret = of_property_read_u32(child, "mhi,event-ring", - &mhi_chan->er_index); - if (ret) - goto error_chan_cfg; - - ret = of_property_read_u32(child, "mhi,chan-dir", - &mhi_chan->dir); - if (ret) - goto error_chan_cfg; - - /* - * For most channels, chtype is identical to channel directions, - * if not defined, assign ch direction to chtype - */ - ret = of_property_read_u32(child, "mhi,chan-type", - &mhi_chan->type); - if (ret) - mhi_chan->type = (enum mhi_ch_type)mhi_chan->dir; - - ret = of_property_read_u32(child, "mhi,ee", &mhi_chan->ee_mask); - if (ret) - goto error_chan_cfg; - - of_property_read_u32(child, "mhi,pollcfg", - &mhi_chan->db_cfg.pollcfg); - - ret = of_property_read_u32(child, "mhi,data-type", - &mhi_chan->xfer_type); - if (ret) - goto error_chan_cfg; - - switch (mhi_chan->xfer_type) { - case MHI_XFER_BUFFER: - mhi_chan->gen_tre = mhi_gen_tre; - mhi_chan->queue_xfer = mhi_queue_buf; - break; - case MHI_XFER_SKB: - mhi_chan->queue_xfer = mhi_queue_skb; - break; - case MHI_XFER_SCLIST: - mhi_chan->gen_tre = mhi_gen_tre; - mhi_chan->queue_xfer = mhi_queue_sclist; - break; - case MHI_XFER_NOP: - mhi_chan->queue_xfer = mhi_queue_nop; - break; - case MHI_XFER_DMA: - case MHI_XFER_RSC_DMA: - mhi_chan->queue_xfer = mhi_queue_dma; - break; - default: - goto error_chan_cfg; - } - - mhi_chan->lpm_notify = of_property_read_bool(child, - "mhi,lpm-notify"); - mhi_chan->offload_ch = of_property_read_bool(child, - "mhi,offload-chan"); - mhi_chan->db_cfg.reset_req = of_property_read_bool(child, - "mhi,db-mode-switch"); - mhi_chan->pre_alloc = of_property_read_bool(child, - "mhi,auto-queue"); - mhi_chan->auto_start = of_property_read_bool(child, - "mhi,auto-start"); - mhi_chan->wake_capable = of_property_read_bool(child, - "mhi,wake-capable"); - - if (mhi_chan->pre_alloc && - (mhi_chan->dir != DMA_FROM_DEVICE || - mhi_chan->xfer_type != MHI_XFER_BUFFER)) - goto error_chan_cfg; - - /* bi-dir and dirctionless channels must be a offload chan */ - if ((mhi_chan->dir == DMA_BIDIRECTIONAL || - mhi_chan->dir == DMA_NONE) && !mhi_chan->offload_ch) - goto error_chan_cfg; - - /* if mhi host allocate the buffers then client cannot queue */ - if (mhi_chan->pre_alloc) - mhi_chan->queue_xfer = mhi_queue_nop; - - if (!mhi_chan->offload_ch) { - ret = of_property_read_u32(child, "mhi,doorbell-mode", - &mhi_chan->db_cfg.brstmode); - if (ret || - MHI_INVALID_BRSTMODE(mhi_chan->db_cfg.brstmode)) - goto error_chan_cfg; - - mhi_chan->db_cfg.process_db = - (mhi_chan->db_cfg.brstmode == - MHI_BRSTMODE_ENABLE) ? - mhi_db_brstmode : mhi_db_brstmode_disable; - } - - mhi_chan->configured = true; - - if (mhi_chan->lpm_notify) - list_add_tail(&mhi_chan->node, &mhi_cntrl->lpm_chans); - } - - return 0; - -error_chan_cfg: - kfree(mhi_cntrl->mhi_chan); - - return -EINVAL; -} -#else -static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - int i, num = 0; - struct mhi_event *mhi_event; - - num = NUM_MHI_EVT_RINGS; - mhi_cntrl->total_ev_rings = num; - mhi_cntrl->mhi_event = kcalloc(num, sizeof(*mhi_cntrl->mhi_event), - GFP_KERNEL); - if (!mhi_cntrl->mhi_event) - return -ENOMEM; - - mhi_cntrl->msi_irq_base = 0; - /* populate ev ring */ - mhi_event = mhi_cntrl->mhi_event; - i = 0; - - for (i = 0; i < mhi_cntrl->total_ev_rings; i++) { - mhi_event->er_index = i; - - mhi_event->ring.elements = NUM_MHI_EVT_RING_ELEMENTS; //Event ring length in elements - if (i == PRIMARY_EVENT_RING) - mhi_event->ring.elements = 256; //256 is enough, and 1024 some times make driver fail to open channel (reason is x6x fail to malloc) - - mhi_event->intmod = 1; //Interrupt moderation time in ms - -#ifdef ENABLE_ADPL - if (i == ADPL_EVT_RING) - mhi_event->ring.elements = 256; -#endif - -#ifdef ENABLE_QDSS - if (i == QDSS_EVT_RING) - mhi_event->ring.elements = 512; -#endif - - /* see mhi_netdev_status_cb(), when interrupt come, the napi_poll maybe scheduled, so can reduce interrupts - root@OpenWrt:/# cat /proc/interrupts | grep mhi - root@OpenWrt:/# cat /sys/kernel/debug/mhi_q/mhi_netdev/pcie_mhi_0306_00.01.00_0/rx_int - */ - if (i == IPA_IN_EVENT_RING) - mhi_event->intmod = 5; - -#ifdef ENABLE_IP_SW0 - if (i == SW_0_IN_EVT_RING) - mhi_event->intmod = 5; -#endif - -#ifdef ENABLE_ADPL - if (i == ADPL_EVT_RING) - mhi_event->intmod = 0; -#endif - -#ifdef ENABLE_QDSS - if (i == QDSS_EVT_RING) - mhi_event->intmod = 0; -#endif - - mhi_event->msi = 1 + i + mhi_cntrl->msi_irq_base; //MSI associated with this event ring - - if (i == IPA_OUT_EVENT_RING) - mhi_event->chan = MHI_CLIENT_IP_HW_0_OUT; //Dedicated channel number, if it's a dedicated event ring - else if (i == IPA_IN_EVENT_RING) - mhi_event->chan = MHI_CLIENT_IP_HW_0_IN; //Dedicated channel number, if it's a dedicated event ring -#ifdef ENABLE_IP_SW0 - else if (i == SW_0_OUT_EVT_RING) - mhi_event->chan = MHI_CLIENT_IP_SW_0_OUT; - else if (i == SW_0_IN_EVT_RING) - mhi_event->chan = MHI_CLIENT_IP_SW_0_IN; -#endif - -#ifdef ENABLE_ADPL - else if (i == ADPL_EVT_RING) - mhi_event->chan = MHI_CLIENT_ADPL; -#endif - -#ifdef ENABLE_QDSS - else if (i == QDSS_EVT_RING) - mhi_event->chan = MHI_CLIENT_IP_HW_QDSS; -#endif - else - mhi_event->chan = 0; - - /* this event ring has a dedicated channel */ - mhi_event->mhi_chan = - &mhi_cntrl->mhi_chan[mhi_event->chan]; - - mhi_event->priority = 1; //Event ring priority, set to 1 for now - - if (mhi_event->chan && mhi_event->mhi_chan->db_cfg.brstmode == MHI_BRSTMODE_ENABLE) - mhi_event->db_cfg.brstmode = MHI_BRSTMODE_ENABLE; - else - mhi_event->db_cfg.brstmode = MHI_BRSTMODE_DISABLE; - - mhi_event->db_cfg.process_db = - (mhi_event->db_cfg.brstmode == MHI_BRSTMODE_ENABLE) ? - mhi_db_brstmode : mhi_db_brstmode_disable; - - if (i == IPA_OUT_EVENT_RING || i == IPA_IN_EVENT_RING) - mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE; -#ifdef ENABLE_IP_SW0 - else if (i == SW_0_OUT_EVT_RING || i == SW_0_IN_EVT_RING) - mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE; -#endif - -#ifdef ENABLE_ADPL - else if (i == ADPL_EVT_RING) - mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE; -#endif - -#ifdef ENABLE_QDSS - else if (i == QDSS_EVT_RING) - mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE; -#endif - else - mhi_event->data_type = MHI_ER_CTRL_ELEMENT_TYPE; - - switch (mhi_event->data_type) { - case MHI_ER_DATA_ELEMENT_TYPE: - mhi_event->process_event = mhi_process_data_event_ring; - break; - case MHI_ER_CTRL_ELEMENT_TYPE: - mhi_event->process_event = mhi_process_ctrl_ev_ring; - break; - case MHI_ER_TSYNC_ELEMENT_TYPE: - mhi_event->process_event = mhi_process_tsync_event_ring; - break; - } - - if (i == IPA_OUT_EVENT_RING || i == IPA_IN_EVENT_RING -#ifdef ENABLE_ADPL - || i == ADPL_EVT_RING -#endif -#ifdef ENABLE_QDSS - || i == QDSS_EVT_RING -#endif - ) - mhi_event->hw_ring = true; - else - mhi_event->hw_ring = false; - - if (mhi_event->hw_ring) - mhi_cntrl->hw_ev_rings++; - else - mhi_cntrl->sw_ev_rings++; - - mhi_event->cl_manage = false; - if (mhi_event->chan == MHI_CLIENT_IP_HW_0_IN || mhi_event->chan == MHI_CLIENT_IP_SW_0_IN) - mhi_event->cl_manage = true; - mhi_event->offload_ev = false; - mhi_event++; - } - - /* we need msi for each event ring + additional one for BHI */ - mhi_cntrl->msi_required = mhi_cntrl->total_ev_rings + 1 + mhi_cntrl->msi_irq_base; - - return 0; -} - -struct chan_cfg_t { - const char *chan_name; - u32 chan_id; - u32 elements; -}; - -static struct chan_cfg_t chan_cfg[] = { -//"Qualcomm PCIe Loopback" - {"LOOPBACK", MHI_CLIENT_LOOPBACK_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"LOOPBACK", MHI_CLIENT_LOOPBACK_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe Sahara" - {"SAHARA", MHI_CLIENT_SAHARA_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"SAHARA", MHI_CLIENT_SAHARA_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe Diagnostics" - {"DIAG", MHI_CLIENT_DIAG_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"DIAG", MHI_CLIENT_DIAG_IN, NUM_MHI_DIAG_IN_RING_ELEMENTS}, -//"Qualcomm PCIe QDSS Data" -//"Do not use this QDSS. xingduo.du 2023-02-16" -// {"QDSS", MHI_CLIENT_QDSS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, -// {"QDSS", MHI_CLIENT_QDSS_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe EFS" - {"EFS", MHI_CLIENT_EFS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"EFS", MHI_CLIENT_EFS_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe MBIM" - {"MBIM", MHI_CLIENT_MBIM_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"MBIM", MHI_CLIENT_MBIM_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe QMI" - {"QMI0", MHI_CLIENT_QMI_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"QMI0", MHI_CLIENT_QMI_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe QMI" - //{"QMI1", MHI_CLIENT_QMI_2_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - //{"QMI1", MHI_CLIENT_QMI_2_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe IP CTRL" - {"IP_CTRL", MHI_CLIENT_IP_CTRL_1_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"IP_CTRL", MHI_CLIENT_IP_CTRL_1_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -#if 0 //AG15 -//"Qualcomm PCIe IPCR" - {"IPCR", MHI_CLIENT_DIAG_CONS_IF_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"IPCR", MHI_CLIENT_DIAG_CONS_IF_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -#endif -//"Qualcomm PCIe Boot Logging" - //{"BL", MHI_CLIENT_BOOT_LOG_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - //{"BL", MHI_CLIENT_BOOT_LOG_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm PCIe Modem" - {"DUN", MHI_CLIENT_DUN_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"DUN", MHI_CLIENT_DUN_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -//"Qualcomm EDL " - {"EDL", MHI_CLIENT_EDL_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, - {"EDL", MHI_CLIENT_EDL_IN, NUM_MHI_CHAN_RING_ELEMENTS}, -#ifdef ENABLE_IP_SW0 -//"Qualcomm PCIe LOCAL Adapter" - {"IP_SW0", MHI_CLIENT_IP_SW_0_OUT, NUM_MHI_SW_IP_RING_ELEMENTS}, - {"IP_SW0", MHI_CLIENT_IP_SW_0_IN, NUM_MHI_SW_IP_RING_ELEMENTS}, -#endif -//"Qualcomm PCIe WWAN Adapter" - {"IP_HW0", MHI_CLIENT_IP_HW_0_OUT, NUM_MHI_IPA_OUT_RING_ELEMENTS}, - {"IP_HW0", MHI_CLIENT_IP_HW_0_IN, NUM_MHI_IPA_IN_RING_ELEMENTS}, -#ifdef ENABLE_ADPL - {"ADPL", MHI_CLIENT_ADPL, NUM_MHI_ADPL_RING_ELEMENTS}, -#endif - -#ifdef ENABLE_QDSS - {"QDSS", MHI_CLIENT_IP_HW_QDSS, NUM_MHI_QDSS_RING_ELEMENTS}, -#endif -}; - -extern int mhi_netdev_mbin_enabled(void); -static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - u32 chan; - u32 i, num; - u32 ring = 0; - - mhi_cntrl->max_chan = MHI_MAX_CHANNELS; - num = sizeof(chan_cfg)/sizeof(chan_cfg[0]); - - mhi_cntrl->mhi_chan = kcalloc(mhi_cntrl->max_chan, - sizeof(*mhi_cntrl->mhi_chan), GFP_KERNEL); - if (!mhi_cntrl->mhi_chan) - return -ENOMEM; - - INIT_LIST_HEAD(&mhi_cntrl->lpm_chans); - - /* populate channel configurations */ - for (i = 0; i < num; i++) { - struct mhi_chan *mhi_chan; - - if (!strncmp( chan_cfg[i].chan_name, "MBIM", 4)) { - if (!mhi_netdev_mbin_enabled()) - continue; - } - else if (!strncmp( chan_cfg[i].chan_name, "QMI", 3)) { - if (mhi_netdev_mbin_enabled()) - continue; - } - - chan = chan_cfg[i].chan_id; - - mhi_chan = &mhi_cntrl->mhi_chan[chan]; - - mhi_chan->name = chan_cfg[i].chan_name; - - mhi_chan->chan = chan; - - mhi_chan->tre_ring.elements = chan_cfg[i].elements; - - /* - * For some channels, local ring len should be bigger than - * transfer ring len due to internal logical channels in device. - * So host can queue much more buffers than transfer ring len. - * Example, RSC channels should have a larger local channel - * than transfer ring length. - */ - mhi_chan->buf_ring.elements = mhi_chan->tre_ring.elements; - - if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_DIAG_IN - || chan == MHI_CLIENT_IP_SW_0_OUT || chan == MHI_CLIENT_IP_SW_0_IN -#ifdef ENABLE_ADPL - || chan == MHI_CLIENT_ADPL -#endif -#ifdef ENABLE_QDSS - || chan == MHI_CLIENT_IP_HW_QDSS -#endif - ) { - mhi_chan->ring = 0; - } - else { - mhi_chan->ring = ring; - ring += mhi_chan->buf_ring.elements; - } - - if (chan == MHI_CLIENT_IP_HW_0_OUT) - mhi_chan->er_index = IPA_OUT_EVENT_RING; - else if (chan == MHI_CLIENT_IP_HW_0_IN) - mhi_chan->er_index = IPA_IN_EVENT_RING; -#ifdef ENABLE_IP_SW0 - else if (chan == MHI_CLIENT_IP_SW_0_OUT) - mhi_chan->er_index = SW_0_OUT_EVT_RING; - else if (chan == MHI_CLIENT_IP_SW_0_IN) - mhi_chan->er_index = SW_0_IN_EVT_RING; -#endif - -#ifdef ENABLE_ADPL - else if (chan == MHI_CLIENT_ADPL) - mhi_chan->er_index = ADPL_EVT_RING; -#endif -#ifdef ENABLE_QDSS - else if (chan == MHI_CLIENT_IP_HW_QDSS) - mhi_chan->er_index = QDSS_EVT_RING; -#endif - else - mhi_chan->er_index = PRIMARY_EVENT_RING; - - mhi_chan->dir = CHAN_INBOUND(chan) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; - -#ifdef ENABLE_ADPL - if (chan == MHI_CLIENT_ADPL) - mhi_chan->dir = DMA_FROM_DEVICE; -#endif - -#ifdef ENABLE_QDSS - if (chan == MHI_CLIENT_IP_HW_QDSS) - mhi_chan->dir = DMA_FROM_DEVICE; -#endif - /* - * For most channels, chtype is identical to channel directions, - * if not defined, assign ch direction to chtype - */ - mhi_chan->type = (enum mhi_ch_type)mhi_chan->dir; - - mhi_chan->ee_mask = BIT(MHI_EE_AMSS); - if (CHAN_SBL(chan)) - mhi_chan->ee_mask = BIT(MHI_EE_SBL); - else if (CHAN_EDL(chan)) - mhi_chan->ee_mask = BIT(MHI_EE_FP); - - mhi_chan->db_cfg.pollcfg = 0; - - if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_SW_0_OUT) - mhi_chan->xfer_type = MHI_XFER_SKB; - else if (chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_IP_SW_0_IN) - mhi_chan->xfer_type = MHI_XFER_SKB; //MHI_XFER_DMA; -#ifdef ENABLE_ADPL - else if (chan == MHI_CLIENT_ADPL) - mhi_chan->xfer_type = MHI_XFER_BUFFER; -#endif -#ifdef ENABLE_QDSS - else if (chan == MHI_CLIENT_IP_HW_QDSS) - mhi_chan->xfer_type = MHI_XFER_BUFFER; -#endif - else - mhi_chan->xfer_type = MHI_XFER_BUFFER; - - if (chan_cfg[i].elements == 0) { - mhi_chan->dir = DMA_BIDIRECTIONAL; - mhi_chan->xfer_type = MHI_XFER_NOP; - } - - switch (mhi_chan->xfer_type) { - case MHI_XFER_BUFFER: - mhi_chan->gen_tre = mhi_gen_tre; - mhi_chan->queue_xfer = mhi_queue_buf; - break; - case MHI_XFER_SKB: - mhi_chan->queue_xfer = mhi_queue_skb; - break; - case MHI_XFER_SCLIST: - mhi_chan->gen_tre = mhi_gen_tre; - mhi_chan->queue_xfer = mhi_queue_sclist; - break; - case MHI_XFER_NOP: - mhi_chan->queue_xfer = mhi_queue_nop; - break; - case MHI_XFER_DMA: - case MHI_XFER_RSC_DMA: - mhi_chan->queue_xfer = mhi_queue_dma; - break; - default: - goto error_chan_cfg; - } - - mhi_chan->lpm_notify = false; - mhi_chan->offload_ch = (chan_cfg[i].elements == 0); - mhi_chan->db_cfg.reset_req = false; - mhi_chan->pre_alloc = false; - mhi_chan->auto_start = false; - mhi_chan->wake_capable = false; - - if (mhi_chan->pre_alloc && - (mhi_chan->dir != DMA_FROM_DEVICE || - mhi_chan->xfer_type != MHI_XFER_BUFFER)) - goto error_chan_cfg; - - /* bi-dir and dirctionless channels must be a offload chan */ - if ((mhi_chan->dir == DMA_BIDIRECTIONAL || - mhi_chan->dir == DMA_NONE) && !mhi_chan->offload_ch) - goto error_chan_cfg; - - /* if mhi host allocate the buffers then client cannot queue */ - if (mhi_chan->pre_alloc) - mhi_chan->queue_xfer = mhi_queue_nop; - - if (!mhi_chan->offload_ch) { - mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_DISABLE; - if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_HW_0_IN) - mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_ENABLE; - -#ifdef ENABLE_ADPL - if (chan == MHI_CLIENT_ADPL) - mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_DISABLE; -#endif -#ifdef ENABLE_QDSS - if (chan == MHI_CLIENT_IP_HW_QDSS) - mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_DISABLE; -#endif - if (MHI_INVALID_BRSTMODE(mhi_chan->db_cfg.brstmode)) - goto error_chan_cfg; - - mhi_chan->db_cfg.process_db = - (mhi_chan->db_cfg.brstmode == - MHI_BRSTMODE_ENABLE) ? - mhi_db_brstmode : mhi_db_brstmode_disable; - } - - mhi_chan->configured = true; - - if (mhi_chan->lpm_notify) - list_add_tail(&mhi_chan->node, &mhi_cntrl->lpm_chans); - } - - return 0; - -error_chan_cfg: - kfree(mhi_cntrl->mhi_chan); - - return -EINVAL; -} -#endif - -static int of_parse_dt(struct mhi_controller *mhi_cntrl, - struct device_node *of_node) -{ - int ret; - - /* parse MHI channel configuration */ - ret = of_parse_ch_cfg(mhi_cntrl, of_node); - if (ret) - return ret; - - /* parse MHI event configuration */ - ret = of_parse_ev_cfg(mhi_cntrl, of_node); - if (ret) - goto error_ev_cfg; -#if defined(QCOM_AP_QCA6490_DMA_IOMMU) - /* for QCS6490 iommu-dma is fastmap - for SG845 iommu-dma is set in driver - for ipq iommu-dma is disabled - */ - const char *str; - ret = of_property_read_string(of_node, "qcom,iommu-dma", &str); - if (ret) - MHI_ERR("mhi qcom,iommu-dma need set"); - -#endif -#if 0 - ret = of_property_read_u32(of_node, "mhi,timeout", - &mhi_cntrl->timeout_ms); - if (ret) - mhi_cntrl->timeout_ms = MHI_TIMEOUT_MS; - - mhi_cntrl->bounce_buf = of_property_read_bool(of_node, "mhi,use-bb"); - ret = of_property_read_u32(of_node, "mhi,buffer-len", - (u32 *)&mhi_cntrl->buffer_len); - if (ret) - mhi_cntrl->buffer_len = MHI_MAX_MTU; -#else - mhi_cntrl->timeout_ms = MHI_TIMEOUT_MS; - mhi_cntrl->bounce_buf = false; - mhi_cntrl->buffer_len = MHI_MAX_MTU; -#endif - - return 0; - -error_ev_cfg: - kfree(mhi_cntrl->mhi_chan); - - return ret; -} - -int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) -{ - int ret; - int i; - struct mhi_event *mhi_event; - struct mhi_chan *mhi_chan; - struct mhi_cmd *mhi_cmd; - struct mhi_device *mhi_dev; - - //if (!mhi_cntrl->of_node) - // return -EINVAL; - - for (i = 0; i < MAX_MHI_CONTROLLER; i++) { - if (mhi_controller_minors[i].dev_id == mhi_cntrl->dev_id - && mhi_controller_minors[i].domain == mhi_cntrl->domain - && mhi_controller_minors[i].bus == mhi_cntrl->bus - && mhi_controller_minors[i].slot == mhi_cntrl->slot) { - mhi_cntrl->cntrl_idx = i; - break; - } - else if (mhi_controller_minors[i].dev_id == 0 - && mhi_controller_minors[i].domain == 0 - && mhi_controller_minors[i].bus == 0 - && mhi_controller_minors[i].slot == 0) { - mhi_controller_minors[i].dev_id = mhi_cntrl->dev_id; - mhi_controller_minors[i].domain = mhi_cntrl->domain; - mhi_controller_minors[i].bus = mhi_cntrl->bus; - mhi_controller_minors[i].slot = mhi_cntrl->slot; - mhi_controller_minors[i].mhi_cntrl = mhi_cntrl; - mhi_cntrl->cntrl_idx = i; - break; - } - } - - if (i == MAX_MHI_CONTROLLER) - return -EINVAL; - - if (!mhi_cntrl->runtime_get || !mhi_cntrl->runtime_put) - return -EINVAL; - - if (!mhi_cntrl->status_cb || !mhi_cntrl->link_status) - return -EINVAL; - - ret = of_parse_dt(mhi_cntrl, mhi_cntrl->of_node); - if (ret) - return -EINVAL; - - mhi_cntrl->mhi_cmd = kcalloc(NR_OF_CMD_RINGS, - sizeof(*mhi_cntrl->mhi_cmd), GFP_KERNEL); - if (!mhi_cntrl->mhi_cmd) { - ret = -ENOMEM; - goto error_alloc_cmd; - } - - INIT_LIST_HEAD(&mhi_cntrl->transition_list); - mutex_init(&mhi_cntrl->pm_mutex); - rwlock_init(&mhi_cntrl->pm_lock); - spin_lock_init(&mhi_cntrl->transition_lock); - spin_lock_init(&mhi_cntrl->wlock); - INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); - INIT_WORK(&mhi_cntrl->fw_worker, mhi_fw_load_worker); - INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); - INIT_DELAYED_WORK(&mhi_cntrl->ready_worker, mhi_pm_ready_worker); - init_waitqueue_head(&mhi_cntrl->state_event); - - mhi_cmd = mhi_cntrl->mhi_cmd; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++) - spin_lock_init(&mhi_cmd->lock); - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - mhi_event->mhi_cntrl = mhi_cntrl; - spin_lock_init(&mhi_event->lock); - if (mhi_event->data_type == MHI_ER_CTRL_ELEMENT_TYPE) - tasklet_init(&mhi_event->task, mhi_ctrl_ev_task, - (ulong)mhi_event); - else - tasklet_init(&mhi_event->task, mhi_ev_task, - (ulong)mhi_event); - } - - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { - mutex_init(&mhi_chan->mutex); - init_completion(&mhi_chan->completion); - rwlock_init(&mhi_chan->lock); - } - - if (mhi_cntrl->bounce_buf) { - mhi_cntrl->map_single = mhi_map_single_use_bb; - mhi_cntrl->unmap_single = mhi_unmap_single_use_bb; - } else { - mhi_cntrl->map_single = mhi_map_single_no_bb; - mhi_cntrl->unmap_single = mhi_unmap_single_no_bb; - } - - /* register controller with mhi_bus */ - mhi_dev = mhi_alloc_device(mhi_cntrl); - if (!mhi_dev) { - ret = -ENOMEM; - goto error_alloc_dev; - } - - mhi_dev->dev_type = MHI_CONTROLLER_TYPE; - mhi_dev->mhi_cntrl = mhi_cntrl; - dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u", mhi_dev->dev_id, - mhi_dev->domain, mhi_dev->bus, mhi_dev->slot); - - ret = device_add(&mhi_dev->dev); - if (ret) - goto error_add_dev; - - if (mhi_cntrl->cntrl_idx) - mhi_cntrl->cntrl_dev = device_create(mhi_cntrl_drv.class, mhi_cntrl->dev, - MKDEV(mhi_cntrl_drv.major, mhi_cntrl->cntrl_idx), NULL, - "mhi_BHI%d", mhi_cntrl->cntrl_idx); - else - mhi_cntrl->cntrl_dev = device_create(mhi_cntrl_drv.class, mhi_cntrl->dev, - MKDEV(mhi_cntrl_drv.major, mhi_cntrl->cntrl_idx), NULL, - "mhi_BHI"); - - mhi_cntrl->mhi_dev = mhi_dev; - - mhi_cntrl->parent = mhi_bus.dentry; - mhi_cntrl->klog_lvl = MHI_MSG_LVL_ERROR; - - /* adding it to this list only for debug purpose */ - mutex_lock(&mhi_bus.lock); - list_add_tail(&mhi_cntrl->node, &mhi_bus.controller_list); - mutex_unlock(&mhi_bus.lock); - - return 0; - -error_add_dev: - mhi_dealloc_device(mhi_cntrl, mhi_dev); - -error_alloc_dev: - kfree(mhi_cntrl->mhi_cmd); - -error_alloc_cmd: - kfree(mhi_cntrl->mhi_chan); - kfree(mhi_cntrl->mhi_event); - - return ret; -}; -EXPORT_SYMBOL(of_register_mhi_controller); - -void mhi_unregister_mhi_controller(struct mhi_controller *mhi_cntrl) -{ - struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; - - kfree(mhi_cntrl->mhi_cmd); - kfree(mhi_cntrl->mhi_event); - kfree(mhi_cntrl->mhi_chan); - kfree(mhi_cntrl->mhi_tsync); - - if (mhi_cntrl->cntrl_dev) - device_destroy(mhi_cntrl_drv.class, MKDEV(mhi_cntrl_drv.major, mhi_cntrl->cntrl_idx)); - device_del(&mhi_dev->dev); - put_device(&mhi_dev->dev); - - mutex_lock(&mhi_bus.lock); - list_del(&mhi_cntrl->node); - mutex_unlock(&mhi_bus.lock); -} - -/* set ptr to control private data */ -static inline void mhi_controller_set_devdata(struct mhi_controller *mhi_cntrl, - void *priv) -{ - mhi_cntrl->priv_data = priv; -} - - -/* allocate mhi controller to register */ -struct mhi_controller *mhi_alloc_controller(size_t size) -{ - struct mhi_controller *mhi_cntrl; - - mhi_cntrl = kzalloc(size + sizeof(*mhi_cntrl), GFP_KERNEL); - - if (mhi_cntrl && size) - mhi_controller_set_devdata(mhi_cntrl, mhi_cntrl + 1); - - return mhi_cntrl; -} -EXPORT_SYMBOL(mhi_alloc_controller); - -int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) -{ - int ret; - u32 bhie_off; - - mutex_lock(&mhi_cntrl->pm_mutex); - - ret = mhi_init_dev_ctxt(mhi_cntrl); - if (ret) { - MHI_ERR("Error with init dev_ctxt\n"); - goto error_dev_ctxt; - } - - ret = mhi_init_irq_setup(mhi_cntrl); - if (ret) { - MHI_ERR("Error setting up irq\n"); - goto error_setup_irq; - } - - /* - * allocate rddm table if specified, this table is for debug purpose - * so we'll ignore erros - */ - if (mhi_cntrl->rddm_size) { - mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image, - mhi_cntrl->rddm_size); - - /* - * This controller supports rddm, we need to manually clear - * BHIE RX registers since por values are undefined. - */ - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, - &bhie_off); - if (ret) { - MHI_ERR("Error getting bhie offset\n"); - goto bhie_error; - } - - memset_io(mhi_cntrl->regs + bhie_off + BHIE_RXVECADDR_LOW_OFFS, - 0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + - 4); - } - - mhi_cntrl->pre_init = true; - - mutex_unlock(&mhi_cntrl->pm_mutex); - - return 0; - -bhie_error: - if (mhi_cntrl->rddm_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); - mhi_cntrl->rddm_image = NULL; - } - mhi_deinit_free_irq(mhi_cntrl); - -error_setup_irq: - mhi_deinit_dev_ctxt(mhi_cntrl); - -error_dev_ctxt: - mutex_unlock(&mhi_cntrl->pm_mutex); - - return ret; -} -EXPORT_SYMBOL(mhi_prepare_for_power_up); - -void mhi_unprepare_after_power_down(struct mhi_controller *mhi_cntrl) -{ - if (mhi_cntrl->fbc_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - } - - if (mhi_cntrl->rddm_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); - mhi_cntrl->rddm_image = NULL; - } - - mhi_deinit_free_irq(mhi_cntrl); - mhi_deinit_dev_ctxt(mhi_cntrl); - mhi_cntrl->pre_init = false; -} - -/* match dev to drv */ -static int mhi_match(struct device *dev, struct device_driver *drv) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_driver *mhi_drv = to_mhi_driver(drv); - const struct mhi_device_id *id; - - /* if controller type there is no client driver associated with it */ - if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) - return 0; - - for (id = mhi_drv->id_table; id->chan[0]; id++) - if (!strcmp(mhi_dev->chan_name, id->chan)) { - mhi_dev->id = id; - return 1; - } - - return 0; -}; - -static void mhi_release_device(struct device *dev) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - - if (mhi_dev->ul_chan) - mhi_dev->ul_chan->mhi_dev = NULL; - - if (mhi_dev->dl_chan) - mhi_dev->dl_chan->mhi_dev = NULL; - - kfree(mhi_dev); -} - -struct bus_type mhi_bus_type = { - .name = "mhi_q", - .dev_name = "mhi_q", - .match = mhi_match, -}; - -static int mhi_driver_probe(struct device *dev) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct device_driver *drv = dev->driver; - struct mhi_driver *mhi_drv = to_mhi_driver(drv); - struct mhi_event *mhi_event; - struct mhi_chan *ul_chan = mhi_dev->ul_chan; - struct mhi_chan *dl_chan = mhi_dev->dl_chan; - bool auto_start = false; - int ret; - - /* bring device out of lpm */ - ret = mhi_device_get_sync(mhi_dev); - if (ret) - return ret; - - ret = -EINVAL; - if (ul_chan) { - /* lpm notification require status_cb */ - if (ul_chan->lpm_notify && !mhi_drv->status_cb) - goto exit_probe; - - if (!ul_chan->offload_ch && !mhi_drv->ul_xfer_cb) - goto exit_probe; - - ul_chan->xfer_cb = mhi_drv->ul_xfer_cb; - mhi_dev->status_cb = mhi_drv->status_cb; - auto_start = ul_chan->auto_start; - } - - if (dl_chan) { - if (dl_chan->lpm_notify && !mhi_drv->status_cb) - goto exit_probe; - - if (!dl_chan->offload_ch && !mhi_drv->dl_xfer_cb) - goto exit_probe; - - mhi_event = &mhi_cntrl->mhi_event[dl_chan->er_index]; - - /* - * if this channal event ring manage by client, then - * status_cb must be defined so we can send the async - * cb whenever there are pending data - */ - if (mhi_event->cl_manage && !mhi_drv->status_cb) - goto exit_probe; - - dl_chan->xfer_cb = mhi_drv->dl_xfer_cb; - - /* ul & dl uses same status cb */ - mhi_dev->status_cb = mhi_drv->status_cb; - auto_start = (auto_start || dl_chan->auto_start); - } - - ret = mhi_drv->probe(mhi_dev, mhi_dev->id); - - if (!ret && auto_start) - mhi_prepare_for_transfer(mhi_dev); - -exit_probe: - mhi_device_put(mhi_dev); - - return ret; -} - -static int mhi_driver_remove(struct device *dev) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_driver *mhi_drv = to_mhi_driver(dev->driver); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - enum MHI_CH_STATE ch_state[] = { - MHI_CH_STATE_DISABLED, - MHI_CH_STATE_DISABLED - }; - int dir; - - /* control device has no work to do */ - if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) - return 0; - - MHI_LOG("Removing device for chan:%s\n", mhi_dev->chan_name); - - /* reset both channels */ - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - /* wake all threads waiting for completion */ - write_lock_irq(&mhi_chan->lock); - mhi_chan->ccs = MHI_EV_CC_INVALID; - complete_all(&mhi_chan->completion); - write_unlock_irq(&mhi_chan->lock); - - /* move channel state to disable, no more processing */ - mutex_lock(&mhi_chan->mutex); - write_lock_irq(&mhi_chan->lock); - ch_state[dir] = mhi_chan->ch_state; - mhi_chan->ch_state = MHI_CH_STATE_SUSPENDED; - write_unlock_irq(&mhi_chan->lock); - - /* reset the channel */ - if (!mhi_chan->offload_ch) - mhi_reset_chan(mhi_cntrl, mhi_chan); - - mutex_unlock(&mhi_chan->mutex); - } - - /* destroy the device */ - mhi_drv->remove(mhi_dev); - - /* de_init channel if it was enabled */ - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - mutex_lock(&mhi_chan->mutex); - - if (ch_state[dir] == MHI_CH_STATE_ENABLED && - !mhi_chan->offload_ch) - mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); - - mhi_chan->ch_state = MHI_CH_STATE_DISABLED; - - mutex_unlock(&mhi_chan->mutex); - } - - - if (mhi_cntrl->tsync_dev == mhi_dev) - mhi_cntrl->tsync_dev = NULL; - - /* relinquish any pending votes */ - read_lock_bh(&mhi_cntrl->pm_lock); - while (atomic_read(&mhi_dev->dev_wake)) - mhi_device_put(mhi_dev); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; -} - -int mhi_driver_register(struct mhi_driver *mhi_drv) -{ - struct device_driver *driver = &mhi_drv->driver; - - if (!mhi_drv->probe || !mhi_drv->remove) - return -EINVAL; - - driver->bus = &mhi_bus_type; - driver->probe = mhi_driver_probe; - driver->remove = mhi_driver_remove; - return driver_register(driver); -} -EXPORT_SYMBOL(mhi_driver_register); - -void mhi_driver_unregister(struct mhi_driver *mhi_drv) -{ - driver_unregister(&mhi_drv->driver); -} -EXPORT_SYMBOL(mhi_driver_unregister); - -struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl) -{ - struct mhi_device *mhi_dev = kzalloc(sizeof(*mhi_dev), GFP_KERNEL); - struct device *dev; - - if (!mhi_dev) - return NULL; - - dev = &mhi_dev->dev; - device_initialize(dev); - dev->bus = &mhi_bus_type; - dev->release = mhi_release_device; - dev->parent = mhi_cntrl->dev; - mhi_dev->mhi_cntrl = mhi_cntrl; - mhi_dev->vendor = mhi_cntrl->vendor; - mhi_dev->dev_id = mhi_cntrl->dev_id; - mhi_dev->domain = mhi_cntrl->domain; - mhi_dev->bus = mhi_cntrl->bus; - mhi_dev->slot = mhi_cntrl->slot; - mhi_dev->mtu = MHI_MAX_MTU; - atomic_set(&mhi_dev->dev_wake, 0); - - return mhi_dev; -} - -static int mhi_cntrl_open(struct inode *inode, struct file *f) -{ - int ret = -ENODEV; - struct mhi_controller *mhi_cntrl; - - mutex_lock(&mhi_bus.lock); - list_for_each_entry(mhi_cntrl, &mhi_bus.controller_list, node) { - if (MINOR(inode->i_rdev) == mhi_cntrl->cntrl_idx) { - ret = 0; - f->private_data = mhi_cntrl; - break; - } - } - mutex_unlock(&mhi_bus.lock); - - return ret; -} - -static int mhi_cntrl_release(struct inode *inode, struct file *f) -{ - f->private_data = NULL; - return 0; -} - -#define IOCTL_BHI_GETDEVINFO 0x8BE0 + 1 -#define IOCTL_BHI_WRITEIMAGE 0x8BE0 + 2 -long bhi_get_dev_info(struct mhi_controller *mhi_cntrl, void __user *to); -long bhi_write_image(struct mhi_controller *mhi_cntrl, void __user *from); - -static long mhi_cntrl_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) -{ - long ret = -ENODEV; - struct mhi_controller *mhi_cntrl; - - mutex_lock(&mhi_bus.lock); - list_for_each_entry(mhi_cntrl, &mhi_bus.controller_list, node) { - if (mhi_cntrl == (struct mhi_controller *)f->private_data) { - ret = 0; - break; - } - } - mutex_unlock(&mhi_bus.lock); - - if (ret) - return ret; - - switch (cmd) { - case IOCTL_BHI_GETDEVINFO: - ret = bhi_get_dev_info(mhi_cntrl, (void __user *)__arg); - break; - - case IOCTL_BHI_WRITEIMAGE: - ret = bhi_write_image(mhi_cntrl, (void __user *)__arg); - break; - - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct file_operations mhi_cntrl_fops = { - .unlocked_ioctl = mhi_cntrl_ioctl, - .open = mhi_cntrl_open, - .release = mhi_cntrl_release, -}; - -static int __init mhi_cntrl_init(void) -{ - int ret; - - ret = register_chrdev(0, MHI_CNTRL_DRIVER_NAME, &mhi_cntrl_fops); - if (ret < 0) - return ret; - - mhi_cntrl_drv.major = ret; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) - mhi_cntrl_drv.class = class_create(MHI_CNTRL_DRIVER_NAME); -#else - mhi_cntrl_drv.class = class_create(THIS_MODULE, MHI_CNTRL_DRIVER_NAME); -#endif - if (IS_ERR(mhi_cntrl_drv.class)) { - unregister_chrdev(mhi_cntrl_drv.major, MHI_CNTRL_DRIVER_NAME); - return -ENODEV; - } - - mutex_init(&mhi_cntrl_drv.lock); - INIT_LIST_HEAD(&mhi_cntrl_drv.head); - - return 0; -} - -void mhi_cntrl_exit(void) -{ - class_destroy(mhi_cntrl_drv.class); - unregister_chrdev(mhi_cntrl_drv.major, MHI_CNTRL_DRIVER_NAME); -} - -extern int mhi_dtr_init(void); -extern void mhi_dtr_exit(void); -extern int mhi_device_netdev_init(struct dentry *parent); -extern void mhi_device_netdev_exit(void); -extern int mhi_device_uci_init(void); -extern void mhi_device_uci_exit(void); -extern int mhi_controller_qcom_init(void); -extern void mhi_controller_qcom_exit(void); - -static char mhi_version[] = "Quectel_Linux_PCIE_MHI_Driver_"PCIE_MHI_DRIVER_VERSION; -module_param_string(mhi_version, mhi_version, sizeof(mhi_version), S_IRUGO); - -static int __init mhi_init(void) -{ - int ret; - - pr_info("%s %s\n", __func__, mhi_version); - - mutex_init(&mhi_bus.lock); - INIT_LIST_HEAD(&mhi_bus.controller_list); - - /* parent directory */ - mhi_bus.dentry = debugfs_create_dir(mhi_bus_type.name, NULL); - - ret = bus_register(&mhi_bus_type); - if (ret) { - pr_err("Error bus_register ret:%d\n", ret); - return ret; - } - - ret = mhi_dtr_init(); - if (ret) { - pr_err("Error mhi_dtr_init ret:%d\n", ret); - bus_unregister(&mhi_bus_type); - return ret; - } - - ret = mhi_device_netdev_init(mhi_bus.dentry); - if (ret) { - pr_err("Error mhi_device_netdev_init ret:%d\n", ret); - } - - ret = mhi_device_uci_init(); - if (ret) { - pr_err("Error mhi_device_uci_init ret:%d\n", ret); - } - - ret = mhi_cntrl_init(); - if (ret) { - pr_err("Error mhi_cntrl_init ret:%d\n", ret); - } - - ret = mhi_controller_qcom_init(); - if (ret) { - pr_err("Error mhi_controller_qcom_init ret:%d\n", ret); - } - - return ret; -} - -static void mhi_exit(void) -{ - mhi_controller_qcom_exit(); - mhi_cntrl_exit(); - mhi_device_uci_exit(); - mhi_device_netdev_exit(); - mhi_dtr_exit(); - bus_unregister(&mhi_bus_type); - debugfs_remove_recursive(mhi_bus.dentry); -} - -module_init(mhi_init); -module_exit(mhi_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("MHI_CORE"); -MODULE_DESCRIPTION("MHI Host Interface"); diff --git a/quectel_MHI/src/core/mhi_internal.h b/quectel_MHI/src/core/mhi_internal.h deleted file mode 100644 index 09f3aac..0000000 --- a/quectel_MHI/src/core/mhi_internal.h +++ /dev/null @@ -1,1190 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ - -#ifndef _MHI_INT_H -#define _MHI_INT_H - -#include -#ifndef writel_relaxed -#define writel_relaxed writel -#endif - -#ifndef writel_relaxed_no_log -#define writel_relaxed_no_log writel_relaxed -#endif - -#ifndef readq -static inline u64 readq(void __iomem *reg) -{ - return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32); -} -#endif - -#ifndef readq_relaxed -#define readq_relaxed readq -#endif - -#ifndef readq_relaxed_no_log -#define readq_relaxed_no_log readq_relaxed -#endif - -#ifndef U32_MAX -#define U32_MAX ((u32)~0U) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,53 )) -static inline void reinit_completion(struct completion *x) -{ - x->done = 0; -} -#endif - -#ifndef __ATTR_RO -#define __ATTR_RO(_name) { \ - .attr = { .name = __stringify(_name), .mode = S_IRUGO }, \ - .show = _name##_show, \ -} -#endif -#ifndef __ATTR_WO -#define __ATTR_WO(_name) { \ - .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ - .store = _name##_store, \ -} -#endif -#ifndef __ATTR_RW -#define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ - _name##_show, _name##_store) -#endif -#ifndef DEVICE_ATTR_RO -#define DEVICE_ATTR_RO(_name) \ - struct device_attribute dev_attr_##_name = __ATTR_RO(_name) -#endif -#ifndef DEVICE_ATTR_WO -#define DEVICE_ATTR_WO(_name) \ - struct device_attribute dev_attr_##_name = __ATTR_WO(_name) -#endif -#ifndef DEVICE_ATTR_RW -#define DRIVER_ATTR_RW(_name) \ - struct driver_attribute driver_attr_##_name = __ATTR_RW(_name) -#endif - -#ifdef EXPORT_SYMBOL -#undef EXPORT_SYMBOL -#define EXPORT_SYMBOL(sym) -#endif - -extern struct bus_type mhi_bus_type; - -/* MHI mmio register mapping */ -#define PCI_INVALID_READ(val) (val == U32_MAX) - -#define MHIREGLEN (0x0) -#define MHIREGLEN_MHIREGLEN_MASK (0xFFFFFFFF) -#define MHIREGLEN_MHIREGLEN_SHIFT (0) - -#define MHIVER (0x8) -#define MHIVER_MHIVER_MASK (0xFFFFFFFF) -#define MHIVER_MHIVER_SHIFT (0) - -#define MHICFG (0x10) -#define MHICFG_NHWER_MASK (0xFF000000) -#define MHICFG_NHWER_SHIFT (24) -#define MHICFG_NER_MASK (0xFF0000) -#define MHICFG_NER_SHIFT (16) -#define MHICFG_NHWCH_MASK (0xFF00) -#define MHICFG_NHWCH_SHIFT (8) -#define MHICFG_NCH_MASK (0xFF) -#define MHICFG_NCH_SHIFT (0) - -#define CHDBOFF (0x18) -#define CHDBOFF_CHDBOFF_MASK (0xFFFFFFFF) -#define CHDBOFF_CHDBOFF_SHIFT (0) - -#define ERDBOFF (0x20) -#define ERDBOFF_ERDBOFF_MASK (0xFFFFFFFF) -#define ERDBOFF_ERDBOFF_SHIFT (0) - -#define BHIOFF (0x28) -#define BHIOFF_BHIOFF_MASK (0xFFFFFFFF) -#define BHIOFF_BHIOFF_SHIFT (0) - -#define BHIEOFF (0x2C) -#define BHIEOFF_BHIEOFF_MASK (0xFFFFFFFF) -#define BHIEOFF_BHIEOFF_SHIFT (0) - -#define DEBUGOFF (0x30) -#define DEBUGOFF_DEBUGOFF_MASK (0xFFFFFFFF) -#define DEBUGOFF_DEBUGOFF_SHIFT (0) - -#define MHICTRL (0x38) -#define MHICTRL_MHISTATE_MASK (0x0000FF00) -#define MHICTRL_MHISTATE_SHIFT (8) -#define MHICTRL_RESET_MASK (0x2) -#define MHICTRL_RESET_SHIFT (1) - -#define MHISTATUS (0x48) -#define MHISTATUS_MHISTATE_MASK (0x0000FF00) -#define MHISTATUS_MHISTATE_SHIFT (8) -#define MHISTATUS_SYSERR_MASK (0x4) -#define MHISTATUS_SYSERR_SHIFT (2) -#define MHISTATUS_READY_MASK (0x1) -#define MHISTATUS_READY_SHIFT (0) - -#define CCABAP_LOWER (0x58) -#define CCABAP_LOWER_CCABAP_LOWER_MASK (0xFFFFFFFF) -#define CCABAP_LOWER_CCABAP_LOWER_SHIFT (0) - -#define CCABAP_HIGHER (0x5C) -#define CCABAP_HIGHER_CCABAP_HIGHER_MASK (0xFFFFFFFF) -#define CCABAP_HIGHER_CCABAP_HIGHER_SHIFT (0) - -#define ECABAP_LOWER (0x60) -#define ECABAP_LOWER_ECABAP_LOWER_MASK (0xFFFFFFFF) -#define ECABAP_LOWER_ECABAP_LOWER_SHIFT (0) - -#define ECABAP_HIGHER (0x64) -#define ECABAP_HIGHER_ECABAP_HIGHER_MASK (0xFFFFFFFF) -#define ECABAP_HIGHER_ECABAP_HIGHER_SHIFT (0) - -#define CRCBAP_LOWER (0x68) -#define CRCBAP_LOWER_CRCBAP_LOWER_MASK (0xFFFFFFFF) -#define CRCBAP_LOWER_CRCBAP_LOWER_SHIFT (0) - -#define CRCBAP_HIGHER (0x6C) -#define CRCBAP_HIGHER_CRCBAP_HIGHER_MASK (0xFFFFFFFF) -#define CRCBAP_HIGHER_CRCBAP_HIGHER_SHIFT (0) - -#define CRDB_LOWER (0x70) -#define CRDB_LOWER_CRDB_LOWER_MASK (0xFFFFFFFF) -#define CRDB_LOWER_CRDB_LOWER_SHIFT (0) - -#define CRDB_HIGHER (0x74) -#define CRDB_HIGHER_CRDB_HIGHER_MASK (0xFFFFFFFF) -#define CRDB_HIGHER_CRDB_HIGHER_SHIFT (0) - -#define MHICTRLBASE_LOWER (0x80) -#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_MASK (0xFFFFFFFF) -#define MHICTRLBASE_LOWER_MHICTRLBASE_LOWER_SHIFT (0) - -#define MHICTRLBASE_HIGHER (0x84) -#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_MASK (0xFFFFFFFF) -#define MHICTRLBASE_HIGHER_MHICTRLBASE_HIGHER_SHIFT (0) - -#define MHICTRLLIMIT_LOWER (0x88) -#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_MASK (0xFFFFFFFF) -#define MHICTRLLIMIT_LOWER_MHICTRLLIMIT_LOWER_SHIFT (0) - -#define MHICTRLLIMIT_HIGHER (0x8C) -#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_MASK (0xFFFFFFFF) -#define MHICTRLLIMIT_HIGHER_MHICTRLLIMIT_HIGHER_SHIFT (0) - -#define MHIDATABASE_LOWER (0x98) -#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_MASK (0xFFFFFFFF) -#define MHIDATABASE_LOWER_MHIDATABASE_LOWER_SHIFT (0) - -#define MHIDATABASE_HIGHER (0x9C) -#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_MASK (0xFFFFFFFF) -#define MHIDATABASE_HIGHER_MHIDATABASE_HIGHER_SHIFT (0) - -#define MHIDATALIMIT_LOWER (0xA0) -#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_MASK (0xFFFFFFFF) -#define MHIDATALIMIT_LOWER_MHIDATALIMIT_LOWER_SHIFT (0) - -#define MHIDATALIMIT_HIGHER (0xA4) -#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF) -#define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0) - -#define MHI_READ_REG_FIELD(_VAR,_REG,_FIELD) \ - ((_VAR & _REG ## _ ## _FIELD ## _MASK) >> _REG ## _ ## _FIELD ## _SHIFT) - -#define MHI_WRITE_REG_FIELD(_VAR,_REG,_FIELD,_VAL) \ - do { \ - _VAR &= ~_REG ## _ ## _FIELD ## _MASK; \ - _VAR |= (_VAL << _REG ## _ ## _FIELD ## _SHIFT); \ - } while(0) - -/* Host request register */ -#define MHI_SOC_RESET_REQ_OFFSET (0xB0) -#define MHI_SOC_RESET_REQ BIT(0) - -/* MHI misc capability registers */ -#define MISC_OFFSET (0x24) -#define MISC_CAP_MASK (0xFFFFFFFF) -#define MISC_CAP_SHIFT (0) - -#define CAP_CAPID_MASK (0xFF000000) -#define CAP_CAPID_SHIFT (24) -#define CAP_NEXT_CAP_MASK (0x00FFF000) -#define CAP_NEXT_CAP_SHIFT (12) - -/* MHI Timesync offsets */ -#define TIMESYNC_CFG_OFFSET (0x00) -#define TIMESYNC_CFG_CAPID_MASK (CAP_CAPID_MASK) -#define TIMESYNC_CFG_CAPID_SHIFT (CAP_CAPID_SHIFT) -#define TIMESYNC_CFG_NEXT_OFF_MASK (CAP_NEXT_CAP_MASK) -#define TIMESYNC_CFG_NEXT_OFF_SHIFT (CAP_NEXT_CAP_SHIFT) -#define TIMESYNC_CFG_NUMCMD_MASK (0xFF) -#define TIMESYNC_CFG_NUMCMD_SHIFT (0) -#define TIMESYNC_DB_OFFSET (0x4) -#define TIMESYNC_TIME_LOW_OFFSET (0x8) -#define TIMESYNC_TIME_HIGH_OFFSET (0xC) - -#define TIMESYNC_CAP_ID (2) - -/* MHI BHI offfsets */ -#define BHI_BHIVERSION_MINOR (0x00) -#define BHI_BHIVERSION_MAJOR (0x04) -#define BHI_IMGADDR_LOW (0x08) -#define BHI_IMGADDR_HIGH (0x0C) -#define BHI_IMGSIZE (0x10) -#define BHI_RSVD1 (0x14) -#define BHI_IMGTXDB (0x18) -#define BHI_TXDB_SEQNUM_BMSK (0x3FFFFFFF) -#define BHI_TXDB_SEQNUM_SHFT (0) -#define BHI_RSVD2 (0x1C) -#define BHI_INTVEC (0x20) -#define BHI_RSVD3 (0x24) -#define BHI_EXECENV (0x28) -#define BHI_STATUS (0x2C) -#define BHI_ERRCODE (0x30) -#define BHI_ERRDBG1 (0x34) -#define BHI_ERRDBG2 (0x38) -#define BHI_ERRDBG3 (0x3C) -#define BHI_SERIALNU (0x40) -#define BHI_SBLANTIROLLVER (0x44) -#define BHI_NUMSEG (0x48) -#define BHI_MSMHWID(n) (0x4C + (0x4 * n)) -#define BHI_OEMPKHASH(n) (0x64 + (0x4 * n)) -#define BHI_RSVD5 (0xC4) -#define BHI_STATUS_MASK (0xC0000000) -#define BHI_STATUS_SHIFT (30) -#define BHI_STATUS_ERROR (3) -#define BHI_STATUS_SUCCESS (2) -#define BHI_STATUS_RESET (0) - -/* MHI BHIE offsets */ -#define BHIE_MSMSOCID_OFFS (0x0000) -#define BHIE_TXVECADDR_LOW_OFFS (0x002C) -#define BHIE_TXVECADDR_HIGH_OFFS (0x0030) -#define BHIE_TXVECSIZE_OFFS (0x0034) -#define BHIE_TXVECDB_OFFS (0x003C) -#define BHIE_TXVECDB_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_TXVECDB_SEQNUM_SHFT (0) -#define BHIE_TXVECSTATUS_OFFS (0x0044) -#define BHIE_TXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_TXVECSTATUS_SEQNUM_SHFT (0) -#define BHIE_TXVECSTATUS_STATUS_BMSK (0xC0000000) -#define BHIE_TXVECSTATUS_STATUS_SHFT (30) -#define BHIE_TXVECSTATUS_STATUS_RESET (0x00) -#define BHIE_TXVECSTATUS_STATUS_XFER_COMPL (0x02) -#define BHIE_TXVECSTATUS_STATUS_ERROR (0x03) -#define BHIE_RXVECADDR_LOW_OFFS (0x0060) -#define BHIE_RXVECADDR_HIGH_OFFS (0x0064) -#define BHIE_RXVECSIZE_OFFS (0x0068) -#define BHIE_RXVECDB_OFFS (0x0070) -#define BHIE_RXVECDB_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_RXVECDB_SEQNUM_SHFT (0) -#define BHIE_RXVECSTATUS_OFFS (0x0078) -#define BHIE_RXVECSTATUS_SEQNUM_BMSK (0x3FFFFFFF) -#define BHIE_RXVECSTATUS_SEQNUM_SHFT (0) -#define BHIE_RXVECSTATUS_STATUS_BMSK (0xC0000000) -#define BHIE_RXVECSTATUS_STATUS_SHFT (30) -#define BHIE_RXVECSTATUS_STATUS_RESET (0x00) -#define BHIE_RXVECSTATUS_STATUS_XFER_COMPL (0x02) -#define BHIE_RXVECSTATUS_STATUS_ERROR (0x03) - -/* convert ticks to micro seconds by dividing by 19.2 */ -#define TIME_TICKS_TO_US(x) (div_u64((x) * 10, 192)) - -struct mhi_event_ctxt { - u32 reserved : 8; - u32 intmodc : 8; - u32 intmodt : 16; - u32 ertype; - u32 msivec; - - u64 rbase __packed __aligned(4); - u64 rlen __packed __aligned(4); - u64 rp __packed __aligned(4); - u64 wp __packed __aligned(4); -}; - -struct mhi_chan_ctxt { - u32 chstate : 8; - u32 brstmode : 2; - u32 pollcfg : 6; - u32 reserved : 16; - u32 chtype; - u32 erindex; - - u64 rbase __packed __aligned(4); - u64 rlen __packed __aligned(4); - u64 rp __packed __aligned(4); - u64 wp __packed __aligned(4); -}; - -struct mhi_cmd_ctxt { - u32 reserved0; - u32 reserved1; - u32 reserved2; - - u64 rbase __packed __aligned(4); - u64 rlen __packed __aligned(4); - u64 rp __packed __aligned(4); - u64 wp __packed __aligned(4); -}; - -struct mhi_tre { - u64 ptr; - u32 dword[2]; -}; - -/* Channel context state */ -enum mhi_dev_ch_ctx_state { - MHI_DEV_CH_STATE_DISABLED, - MHI_DEV_CH_STATE_ENABLED, - MHI_DEV_CH_STATE_RUNNING, - MHI_DEV_CH_STATE_SUSPENDED, - MHI_DEV_CH_STATE_STOP, - MHI_DEV_CH_STATE_ERROR, - MHI_DEV_CH_STATE_RESERVED, - MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF -}; - -/* Channel type */ -enum mhi_dev_ch_ctx_type { - MHI_DEV_CH_TYPE_NONE, - MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL, - MHI_DEV_CH_TYPE_INBOUND_CHANNEL, - MHI_DEV_CH_RESERVED -}; - -/* Channel context type */ -struct mhi_dev_ch_ctx { - enum mhi_dev_ch_ctx_state ch_state; - enum mhi_dev_ch_ctx_type ch_type; - uint32_t err_indx; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -enum mhi_dev_ring_element_type_id { - MHI_DEV_RING_EL_INVALID = 0, - MHI_DEV_RING_EL_NOOP = 1, - MHI_DEV_RING_EL_TRANSFER = 2, - MHI_DEV_RING_EL_RESET = 16, - MHI_DEV_RING_EL_STOP = 17, - MHI_DEV_RING_EL_START = 18, - MHI_DEV_RING_EL_MHI_STATE_CHG = 32, - MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33, - MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34, - MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64, - MHI_DEV_RING_EL_UNDEF -}; - -enum mhi_dev_ring_state { - RING_STATE_UINT = 0, - RING_STATE_IDLE, - RING_STATE_PENDING, -}; - -enum mhi_dev_ring_type { - RING_TYPE_CMD = 0, - RING_TYPE_ER, - RING_TYPE_CH, - RING_TYPE_INVAL -}; - -/* Event context interrupt moderation */ -enum mhi_dev_evt_ctx_int_mod_timer { - MHI_DEV_EVT_INT_MODERATION_DISABLED -}; - -/* Event ring type */ -enum mhi_dev_evt_ctx_event_ring_type { - MHI_DEV_EVT_TYPE_DEFAULT, - MHI_DEV_EVT_TYPE_VALID, - MHI_DEV_EVT_RESERVED -}; - -/* Event ring context type */ -struct mhi_dev_ev_ctx { - uint32_t res1:16; - enum mhi_dev_evt_ctx_int_mod_timer intmodt:16; - enum mhi_dev_evt_ctx_event_ring_type ertype; - uint32_t msivec; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Command context */ -struct mhi_dev_cmd_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* generic context */ -struct mhi_dev_gen_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Transfer ring element */ -struct mhi_dev_transfer_ring_element { - uint64_t data_buf_ptr; - uint32_t len:16; - uint32_t res1:16; - uint32_t chain:1; - uint32_t res2:7; - uint32_t ieob:1; - uint32_t ieot:1; - uint32_t bei:1; - uint32_t res3:5; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res4:8; -} __packed; - -/* Command ring element */ -/* Command ring No op command */ -struct mhi_dev_cmd_ring_op { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring reset channel command */ -struct mhi_dev_cmd_ring_reset_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring stop channel command */ -struct mhi_dev_cmd_ring_stop_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring start channel command */ -struct mhi_dev_cmd_ring_start_channel_cmd { - uint64_t res1; - uint32_t seqnum; - uint32_t reliable:1; - uint32_t res2:15; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -enum mhi_dev_cmd_completion_code { - MHI_CMD_COMPL_CODE_INVALID = 0, - MHI_CMD_COMPL_CODE_SUCCESS = 1, - MHI_CMD_COMPL_CODE_EOT = 2, - MHI_CMD_COMPL_CODE_OVERFLOW = 3, - MHI_CMD_COMPL_CODE_EOB = 4, - MHI_CMD_COMPL_CODE_UNDEFINED = 16, - MHI_CMD_COMPL_CODE_RING_EL = 17, - MHI_CMD_COMPL_CODE_RES -}; - -/* Event ring elements */ -/* Transfer completion event */ -struct mhi_dev_event_ring_transfer_completion { - uint64_t ptr; - uint32_t len:16; - uint32_t res1:8; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command completion event */ -struct mhi_dev_event_ring_cmd_completion { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -/* MHI state change event */ -struct mhi_dev_event_ring_state_change { - uint64_t ptr; - uint32_t res1:24; - uint32_t /*enum mhi_dev_state*/ mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_execenv { - MHI_DEV_SBL_EE = 1, - MHI_DEV_AMSS_EE = 2, - MHI_DEV_UNRESERVED -}; - -/* EE state change event */ -struct mhi_dev_event_ring_ee_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_execenv execenv:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -/* Generic cmd to parse common details like type and channel id */ -struct mhi_dev_ring_generic { - uint64_t ptr; - uint32_t res1:24; - uint32_t /*enum mhi_dev_state*/ mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -struct mhi_config { - uint32_t mhi_reg_len; - uint32_t version; - uint32_t event_rings; - uint32_t channels; - uint32_t chdb_offset; - uint32_t erdb_offset; -}; - -/* Possible ring element types */ -union mhi_dev_ring_element_type { - struct mhi_dev_cmd_ring_op cmd_no_op; - struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset; - struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop; - struct mhi_dev_cmd_ring_start_channel_cmd cmd_start; - struct mhi_dev_transfer_ring_element cmd_transfer; - struct mhi_dev_event_ring_transfer_completion evt_tr_comp; - struct mhi_dev_event_ring_cmd_completion evt_cmd_comp; - struct mhi_dev_event_ring_state_change evt_state_change; - struct mhi_dev_event_ring_ee_state_change evt_ee_state; - struct mhi_dev_ring_generic generic; -}; - -struct bhi_vec_entry { - u64 dma_addr; - u64 size; -}; - -enum mhi_cmd_type { - MHI_CMD_TYPE_NOP = 1, - MHI_CMD_TYPE_RESET = 16, - MHI_CMD_TYPE_STOP = 17, - MHI_CMD_TYPE_START = 18, - MHI_CMD_TYPE_TSYNC = 24, -}; - -/* no operation command */ -#define MHI_TRE_CMD_NOOP_PTR (0) -#define MHI_TRE_CMD_NOOP_DWORD0 (0) -#define MHI_TRE_CMD_NOOP_DWORD1 (MHI_CMD_TYPE_NOP << 16) - -/* channel reset command */ -#define MHI_TRE_CMD_RESET_PTR (0) -#define MHI_TRE_CMD_RESET_DWORD0 (0) -#define MHI_TRE_CMD_RESET_DWORD1(chid) ((chid << 24) | \ - (MHI_CMD_TYPE_RESET << 16)) - -/* channel stop command */ -#define MHI_TRE_CMD_STOP_PTR (0) -#define MHI_TRE_CMD_STOP_DWORD0 (0) -#define MHI_TRE_CMD_STOP_DWORD1(chid) ((chid << 24) | (MHI_CMD_TYPE_STOP << 16)) - -/* channel start command */ -#define MHI_TRE_CMD_START_PTR (0) -#define MHI_TRE_CMD_START_DWORD0 (0) -#define MHI_TRE_CMD_START_DWORD1(chid) ((chid << 24) | \ - (MHI_CMD_TYPE_START << 16)) - -/* time sync cfg command */ -#define MHI_TRE_CMD_TSYNC_CFG_PTR (0) -#define MHI_TRE_CMD_TSYNC_CFG_DWORD0 (0) -#define MHI_TRE_CMD_TSYNC_CFG_DWORD1(er) ((MHI_CMD_TYPE_TSYNC << 16) | \ - (er << 24)) - -#define MHI_TRE_GET_CMD_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF) -#define MHI_TRE_GET_CMD_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF) - -/* event descriptor macros */ -#define MHI_TRE_EV_PTR(ptr) (ptr) -#define MHI_TRE_EV_DWORD0(code, len) ((code << 24) | len) -#define MHI_TRE_EV_DWORD1(chid, type) ((chid << 24) | (type << 16)) -#define MHI_TRE_GET_EV_PTR(tre) ((tre)->ptr) -#define MHI_TRE_GET_EV_CODE(tre) (((tre)->dword[0] >> 24) & 0xFF) -#define MHI_TRE_GET_EV_LEN(tre) ((tre)->dword[0] & 0xFFFF) -#define MHI_TRE_GET_EV_CHID(tre) (((tre)->dword[1] >> 24) & 0xFF) -#define MHI_TRE_GET_EV_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF) -#define MHI_TRE_GET_EV_STATE(tre) (((tre)->dword[0] >> 24) & 0xFF) -#define MHI_TRE_GET_EV_EXECENV(tre) (((tre)->dword[0] >> 24) & 0xFF) -#define MHI_TRE_GET_EV_SEQ(tre) ((tre)->dword[0]) -#define MHI_TRE_GET_EV_TIME(tre) ((tre)->ptr) -#define MHI_TRE_GET_EV_COOKIE(tre) lower_32_bits((tre)->ptr) -#define MHI_TRE_GET_EV_VEID(tre) (((tre)->dword[0] >> 16) & 0xFF) - -/* transfer descriptor macros */ -#define MHI_TRE_DATA_PTR(ptr) (ptr) -#define MHI_TRE_DATA_DWORD0(len) (len & MHI_MAX_MTU) -#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) ((2 << 16) | (bei << 10) \ - | (ieot << 9) | (ieob << 8) | chain) - -/* rsc transfer descriptor macros */ -#define MHI_RSCTRE_DATA_PTR(ptr, len) (((u64)len << 48) | ptr) -#define MHI_RSCTRE_DATA_DWORD0(cookie) (cookie) -#define MHI_RSCTRE_DATA_DWORD1 (MHI_PKT_TYPE_COALESCING << 16) - -enum MHI_CMD { - MHI_CMD_RESET_CHAN, - MHI_CMD_START_CHAN, - MHI_CMD_TIMSYNC_CFG, -}; - -enum MHI_PKT_TYPE { - MHI_PKT_TYPE_INVALID = 0x0, - MHI_PKT_TYPE_NOOP_CMD = 0x1, - MHI_PKT_TYPE_TRANSFER = 0x2, - MHI_PKT_TYPE_COALESCING = 0x8, - MHI_PKT_TYPE_RESET_CHAN_CMD = 0x10, - MHI_PKT_TYPE_STOP_CHAN_CMD = 0x11, - MHI_PKT_TYPE_START_CHAN_CMD = 0x12, - MHI_PKT_TYPE_STATE_CHANGE_EVENT = 0x20, - MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21, - MHI_PKT_TYPE_TX_EVENT = 0x22, - MHI_PKT_TYPE_RSC_TX_EVENT = 0x28, - MHI_PKT_TYPE_EE_EVENT = 0x40, - MHI_PKT_TYPE_TSYNC_EVENT = 0x48, - MHI_PKT_TYPE_STALE_EVENT, /* internal event */ -}; - -/* MHI transfer completion events */ -enum MHI_EV_CCS { - MHI_EV_CC_INVALID = 0x0, - MHI_EV_CC_SUCCESS = 0x1, - MHI_EV_CC_EOT = 0x2, - MHI_EV_CC_OVERFLOW = 0x3, - MHI_EV_CC_EOB = 0x4, - MHI_EV_CC_OOB = 0x5, - MHI_EV_CC_DB_MODE = 0x6, - MHI_EV_CC_UNDEFINED_ERR = 0x10, - MHI_EV_CC_BAD_TRE = 0x11, -}; - -enum MHI_CH_STATE { - MHI_CH_STATE_DISABLED = 0x0, - MHI_CH_STATE_ENABLED = 0x1, - MHI_CH_STATE_RUNNING = 0x2, - MHI_CH_STATE_SUSPENDED = 0x3, - MHI_CH_STATE_STOP = 0x4, - MHI_CH_STATE_ERROR = 0x5, -}; - -enum MHI_BRSTMODE { - MHI_BRSTMODE_DISABLE = 0x2, - MHI_BRSTMODE_ENABLE = 0x3, -}; - -#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_BRSTMODE_DISABLE && \ - mode != MHI_BRSTMODE_ENABLE) - -#define MHI_IN_PBL(ee) (ee == MHI_EE_PBL || ee == MHI_EE_PTHRU || \ - ee == MHI_EE_EDL) - -#define MHI_IN_MISSION_MODE(ee) (ee == MHI_EE_AMSS || ee == MHI_EE_WFW) - -enum MHI_ST_TRANSITION { - MHI_ST_TRANSITION_PBL, - MHI_ST_TRANSITION_READY, - MHI_ST_TRANSITION_SBL, - MHI_ST_TRANSITION_MISSION_MODE, - MHI_ST_TRANSITION_FP, - MHI_ST_TRANSITION_MAX, -}; - -extern const char * const mhi_state_tran_str[MHI_ST_TRANSITION_MAX]; -#define TO_MHI_STATE_TRANS_STR(state) (((state) >= MHI_ST_TRANSITION_MAX) ? \ - "INVALID_STATE" : mhi_state_tran_str[state]) - -extern const char * const mhi_state_str[MHI_STATE_MAX]; -#define TO_MHI_STATE_STR(state) ((state >= MHI_STATE_MAX || \ - !mhi_state_str[state]) ? \ - "INVALID_STATE" : mhi_state_str[state]) - -enum { - MHI_PM_BIT_DISABLE, - MHI_PM_BIT_POR, - MHI_PM_BIT_M0, - MHI_PM_BIT_M2, - MHI_PM_BIT_M3_ENTER, - MHI_PM_BIT_M3, - MHI_PM_BIT_M3_EXIT, - MHI_PM_BIT_FW_DL_ERR, - MHI_PM_BIT_SYS_ERR_DETECT, - MHI_PM_BIT_SYS_ERR_PROCESS, - MHI_PM_BIT_SHUTDOWN_PROCESS, - MHI_PM_BIT_LD_ERR_FATAL_DETECT, - MHI_PM_BIT_MAX -}; - -/* internal power states */ -enum MHI_PM_STATE { - MHI_PM_DISABLE = BIT(MHI_PM_BIT_DISABLE), /* MHI is not enabled */ - MHI_PM_POR = BIT(MHI_PM_BIT_POR), /* reset state */ - MHI_PM_M0 = BIT(MHI_PM_BIT_M0), - MHI_PM_M2 = BIT(MHI_PM_BIT_M2), - MHI_PM_M3_ENTER = BIT(MHI_PM_BIT_M3_ENTER), - MHI_PM_M3 = BIT(MHI_PM_BIT_M3), - MHI_PM_M3_EXIT = BIT(MHI_PM_BIT_M3_EXIT), - /* firmware download failure state */ - MHI_PM_FW_DL_ERR = BIT(MHI_PM_BIT_FW_DL_ERR), - MHI_PM_SYS_ERR_DETECT = BIT(MHI_PM_BIT_SYS_ERR_DETECT), - MHI_PM_SYS_ERR_PROCESS = BIT(MHI_PM_BIT_SYS_ERR_PROCESS), - MHI_PM_SHUTDOWN_PROCESS = BIT(MHI_PM_BIT_SHUTDOWN_PROCESS), - /* link not accessible */ - MHI_PM_LD_ERR_FATAL_DETECT = BIT(MHI_PM_BIT_LD_ERR_FATAL_DETECT), -}; - -#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \ - MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ - MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \ - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR))) -#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR) -#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT) -#define MHI_DB_ACCESS_VALID(pm_state) (pm_state & MHI_PM_M0) -#define MHI_WAKE_DB_CLEAR_VALID(pm_state) (pm_state & (MHI_PM_M0 | \ - MHI_PM_M2 | MHI_PM_M3_EXIT)) -#define MHI_WAKE_DB_SET_VALID(pm_state) (pm_state & MHI_PM_M2) -#define MHI_WAKE_DB_FORCE_SET_VALID(pm_state) MHI_WAKE_DB_CLEAR_VALID(pm_state) -#define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \ - MHI_PM_IN_ERROR_STATE(pm_state)) -#define MHI_PM_IN_SUSPEND_STATE(pm_state) (pm_state & \ - (MHI_PM_M3_ENTER | MHI_PM_M3)) - -/* accepted buffer type for the channel */ -enum MHI_XFER_TYPE { - MHI_XFER_BUFFER, - MHI_XFER_SKB, - MHI_XFER_SCLIST, - MHI_XFER_NOP, /* CPU offload channel, host does not accept transfer */ - MHI_XFER_DMA, /* receive dma address, already mapped by client */ - MHI_XFER_RSC_DMA, /* RSC type, accept premapped buffer */ -}; - -#define NR_OF_CMD_RINGS (1) -#define CMD_EL_PER_RING (128) -#define PRIMARY_CMD_RING (0) -#define MHI_DEV_WAKE_DB (127) -#define MHI_MAX_MTU (0xffff) - -enum MHI_ER_TYPE { - MHI_ER_TYPE_INVALID = 0x0, - MHI_ER_TYPE_VALID = 0x1, -}; - -enum mhi_er_data_type { - MHI_ER_DATA_ELEMENT_TYPE, - MHI_ER_CTRL_ELEMENT_TYPE, - MHI_ER_TSYNC_ELEMENT_TYPE, - MHI_ER_DATA_TYPE_MAX = MHI_ER_TSYNC_ELEMENT_TYPE, -}; - -enum mhi_ch_ee_mask { - MHI_CH_EE_PBL = BIT(MHI_EE_PBL), - MHI_CH_EE_SBL = BIT(MHI_EE_SBL), - MHI_CH_EE_AMSS = BIT(MHI_EE_AMSS), - MHI_CH_EE_RDDM = BIT(MHI_EE_RDDM), - MHI_CH_EE_PTHRU = BIT(MHI_EE_PTHRU), - MHI_CH_EE_WFW = BIT(MHI_EE_WFW), - MHI_CH_EE_EDL = BIT(MHI_EE_EDL), -}; - -enum mhi_ch_type { - MHI_CH_TYPE_INVALID = 0, - MHI_CH_TYPE_OUTBOUND = DMA_TO_DEVICE, - MHI_CH_TYPE_INBOUND = DMA_FROM_DEVICE, - MHI_CH_TYPE_INBOUND_COALESCED = 3, -}; - -struct db_cfg { - bool reset_req; - bool db_mode; - u32 pollcfg; - enum MHI_BRSTMODE brstmode; - dma_addr_t db_val; - void (*process_db)(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_cfg, void __iomem *io_addr, - dma_addr_t db_val); -}; - -struct mhi_pm_transitions { - enum MHI_PM_STATE from_state; - u32 to_states; -}; - -struct state_transition { - struct list_head node; - enum MHI_ST_TRANSITION state; -}; - -/* Control Segment */ -struct mhi_ctrl_seg -{ - struct mhi_tre hw_in_chan_ring[NUM_MHI_IPA_IN_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16); - struct mhi_tre hw_out_chan_ring[NUM_MHI_IPA_OUT_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); -#ifdef ENABLE_IP_SW0 - struct mhi_tre sw_in_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16); - struct mhi_tre sw_out_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); -#endif - -#ifdef ENABLE_ADPL - struct mhi_tre adpl_in_chan_ring[NUM_MHI_ADPL_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16); -#endif - -#ifdef ENABLE_QDSS - struct mhi_tre qdss_in_chan_ring[NUM_MHI_QDSS_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16); -#endif - - struct mhi_tre diag_in_chan_ring[NUM_MHI_DIAG_IN_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); - struct mhi_tre chan_ring[NUM_MHI_CHAN_RING_ELEMENTS*2*12] __packed __aligned(NUM_MHI_CHAN_RING_ELEMENTS*16); - struct mhi_tre event_ring[NUM_MHI_EVT_RINGS][NUM_MHI_EVT_RING_ELEMENTS] __packed __aligned(NUM_MHI_EVT_RING_ELEMENTS*16); - struct mhi_tre cmd_ring[NR_OF_CMD_RINGS][CMD_EL_PER_RING] __packed __aligned(CMD_EL_PER_RING*16); - - struct mhi_chan_ctxt chan_ctxt[NUM_MHI_XFER_RINGS] __aligned(128); - struct mhi_event_ctxt er_ctxt[NUM_MHI_EVT_RINGS] __aligned(128); - struct mhi_cmd_ctxt cmd_ctxt[NR_OF_CMD_RINGS] __aligned(128); -} __aligned(4096); - -struct mhi_ctxt { - struct mhi_event_ctxt *er_ctxt; - struct mhi_chan_ctxt *chan_ctxt; - struct mhi_cmd_ctxt *cmd_ctxt; - dma_addr_t er_ctxt_addr; - dma_addr_t chan_ctxt_addr; - dma_addr_t cmd_ctxt_addr; - struct mhi_ctrl_seg *ctrl_seg; - dma_addr_t ctrl_seg_addr; -}; - -struct mhi_ring { - dma_addr_t dma_handle; - dma_addr_t iommu_base; - u64 *ctxt_wp; /* point to ctxt wp */ - void *pre_aligned; - void *base; - void *rp; - void *wp; - size_t el_size; - size_t len; - size_t elements; - size_t alloc_size; - void __iomem *db_addr; -}; - -struct mhi_cmd { - struct mhi_ring ring; - spinlock_t lock; -}; - -struct mhi_buf_info { - dma_addr_t p_addr; - void *v_addr; - void *bb_addr; - void *wp; - size_t len; - void *cb_buf; - bool used; /* indicate element is free to use */ - bool pre_mapped; /* already pre-mapped by client */ - enum dma_data_direction dir; -}; - -struct mhi_event { - u32 er_index; - u32 intmod; - u32 msi; - int chan; /* this event ring is dedicated to a channel */ - u32 priority; - enum mhi_er_data_type data_type; - struct mhi_ring ring; - struct db_cfg db_cfg; - u32 used_elements; - bool hw_ring; - bool cl_manage; - bool offload_ev; /* managed by a device driver */ - spinlock_t lock; - struct mhi_chan *mhi_chan; /* dedicated to channel */ - struct tasklet_struct task; - int (*process_event)(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, - u32 event_quota); - struct mhi_controller *mhi_cntrl; -}; - -struct mhi_chan { - u32 chan; - const char *name; - /* - * important, when consuming increment tre_ring first, when releasing - * decrement buf_ring first. If tre_ring has space, buf_ring - * guranteed to have space so we do not need to check both rings. - */ - struct mhi_ring buf_ring; - struct mhi_ring tre_ring; - - u32 used_elements; - u32 used_events[MHI_EV_CC_DB_MODE+1]; - - u32 er_index; - u32 intmod; - enum mhi_ch_type type; - enum dma_data_direction dir; - struct db_cfg db_cfg; - u32 ee_mask; - enum MHI_XFER_TYPE xfer_type; - enum MHI_CH_STATE ch_state; - enum MHI_EV_CCS ccs; - bool lpm_notify; - bool configured; - bool offload_ch; - bool pre_alloc; - bool auto_start; - bool wake_capable; /* channel should wake up system */ - /* functions that generate the transfer ring elements */ - int (*gen_tre)(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, void *buf, void *cb, - size_t len, enum MHI_FLAGS flags); - int (*queue_xfer)(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, void *buf, - size_t len, enum MHI_FLAGS flags); - /* xfer call back */ - struct mhi_device *mhi_dev; - void (*xfer_cb)(struct mhi_device *mhi_dev, struct mhi_result *result); - struct mutex mutex; - struct completion completion; - rwlock_t lock; - u32 ring; - u32 tiocm; - struct list_head node; -}; - -struct tsync_node { - struct list_head node; - u32 sequence; - u64 local_time; - u64 remote_time; - struct mhi_device *mhi_dev; - void (*cb_func)(struct mhi_device *mhi_dev, u32 sequence, - u64 local_time, u64 remote_time); -}; - -struct mhi_timesync { - u32 er_index; - void __iomem *db; - void __iomem *time_reg; - enum MHI_EV_CCS ccs; - struct completion completion; - spinlock_t lock; /* list protection */ - struct mutex lpm_mutex; /* lpm protection */ - struct list_head head; -}; - -struct mhi_bus { - struct list_head controller_list; - struct mutex lock; - struct dentry *dentry; -}; - -/* default MHI timeout */ -#define MHI_TIMEOUT_MS (3000) -extern struct mhi_bus mhi_bus; - -/* debug fs related functions */ -int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d); -int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d); -int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d); -int mhi_debugfs_trigger_reset(void *data, u64 val); - -void mhi_deinit_debugfs(struct mhi_controller *mhi_cntrl); -void mhi_init_debugfs(struct mhi_controller *mhi_cntrl); - -/* power management apis */ -enum MHI_PM_STATE __must_check mhi_tryset_pm_state( - struct mhi_controller *mhi_cntrl, - enum MHI_PM_STATE state); -const char *to_mhi_pm_state_str(enum MHI_PM_STATE state); -void mhi_reset_chan(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl); -int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, - enum MHI_ST_TRANSITION state); -void mhi_pm_st_worker(struct work_struct *work); -void mhi_fw_load_worker(struct work_struct *work); -void mhi_pm_sys_err_worker(struct work_struct *work); -void mhi_pm_ready_worker(struct work_struct *work); -int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); -void mhi_ctrl_ev_task(unsigned long data); -int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl); -void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl); -int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl); -void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason); -int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, u32 event_quota); -int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, u32 event_quota); -int mhi_process_tsync_event_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, u32 event_quota); -int mhi_send_cmd(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, - enum MHI_CMD cmd); -int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl); - -/* queue transfer buffer */ -int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, - void *buf, void *cb, size_t buf_len, enum MHI_FLAGS flags); -int mhi_queue_buf(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_skb(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_sclist(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_nop(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); -int mhi_queue_dma(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, - void *buf, size_t len, enum MHI_FLAGS mflags); - -/* register access methods */ -void mhi_db_brstmode(struct mhi_controller *mhi_cntrl, struct db_cfg *db_cfg, - void __iomem *db_addr, dma_addr_t wp); -void mhi_db_brstmode_disable(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_mode, void __iomem *db_addr, - dma_addr_t wp); -int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl, - void __iomem *base, u32 offset, u32 *out); -int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl, - void __iomem *base, u32 offset, u32 mask, - u32 shift, u32 *out); -void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *base, - u32 offset, u32 val); -void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, void __iomem *base, - u32 offset, u32 mask, u32 shift, u32 val); -void mhi_ring_er_db(struct mhi_event *mhi_event); -void mhi_write_db(struct mhi_controller *mhi_cntrl, void __iomem *db_addr, - dma_addr_t wp); -void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd); -void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, u32 capability, - u32 *offset); -int mhi_init_timesync(struct mhi_controller *mhi_cntrl); -int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl); -void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl); - -/* memory allocation methods */ -static inline void *mhi_alloc_coherent(struct mhi_controller *mhi_cntrl, - size_t size, - dma_addr_t *dma_handle, - gfp_t gfp) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,0,0 )) - void *buf = dma_zalloc_coherent(mhi_cntrl->dev, size, dma_handle, gfp); -#else - void *buf = dma_alloc_coherent(mhi_cntrl->dev, size, dma_handle, gfp | __GFP_ZERO); -#endif - - MHI_LOG("size = %zd, dma_handle = %llx\n", size, (u64)*dma_handle); - if (buf) - atomic_add(size, &mhi_cntrl->alloc_size); - - return buf; -} -static inline void mhi_free_coherent(struct mhi_controller *mhi_cntrl, - size_t size, - void *vaddr, - dma_addr_t dma_handle) -{ - atomic_sub(size, &mhi_cntrl->alloc_size); - dma_free_coherent(mhi_cntrl->dev, size, vaddr, dma_handle); -} -struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl); -static inline void mhi_dealloc_device(struct mhi_controller *mhi_cntrl, - struct mhi_device *mhi_dev) -{ - kfree(mhi_dev); -} -int mhi_destroy_device(struct device *dev, void *data); -void mhi_create_devices(struct mhi_controller *mhi_cntrl); -int mhi_alloc_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info **image_info, size_t alloc_size); -void mhi_free_bhie_table(struct mhi_controller *mhi_cntrl, - struct image_info *image_info); - -int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info); -int mhi_map_single_use_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info); -void mhi_unmap_single_no_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info); -void mhi_unmap_single_use_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info); - -/* initialization methods */ -int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); -int mhi_init_mmio(struct mhi_controller *mhi_cntrl); -int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl); -void mhi_deinit_dev_ctxt(struct mhi_controller *mhi_cntrl); -int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl); -void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl); -int mhi_dtr_init(void); - -/* isr handlers */ -irqreturn_t mhi_one_msi_handlr(int irq_number, void *dev); -irqreturn_t mhi_msi_handlr(int irq_number, void *dev); -irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev); -irqreturn_t mhi_intvec_handlr(int irq_number, void *dev); -void mhi_ev_task(unsigned long data); - -#ifdef CONFIG_MHI_DEBUG - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) \ - panic(msg); \ -} while (0) - -#else - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) { \ - MHI_ERR(msg); \ - WARN_ON(cond); \ - } \ -} while (0) - -#endif - -#endif /* _MHI_INT_H */ diff --git a/quectel_MHI/src/core/mhi_main.c b/quectel_MHI/src/core/mhi_main.c deleted file mode 100644 index 12d44e6..0000000 --- a/quectel_MHI/src/core/mhi_main.c +++ /dev/null @@ -1,2722 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan); - -int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 *out) -{ - u32 tmp = readl_relaxed(base + offset); - - /* unexpected value, query the link status */ - if (PCI_INVALID_READ(tmp) && - mhi_cntrl->link_status(mhi_cntrl, mhi_cntrl->priv_data)) - return -EIO; - - *out = tmp; - - return 0; -} - -int __must_check mhi_read_reg_field(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 mask, - u32 shift, - u32 *out) -{ - u32 tmp; - int ret; - - ret = mhi_read_reg(mhi_cntrl, base, offset, &tmp); - if (ret) - return ret; - - *out = (tmp & mask) >> shift; - - return 0; -} - -int mhi_get_capability_offset(struct mhi_controller *mhi_cntrl, - u32 capability, - u32 *offset) -{ - u32 cur_cap, next_offset; - int ret; - - /* get the 1st supported capability offset */ - ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MISC_OFFSET, - MISC_CAP_MASK, MISC_CAP_SHIFT, offset); - if (ret) - return ret; - if (*offset >= 0x1000) - return -ENXIO; - do { - ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, *offset, - CAP_CAPID_MASK, CAP_CAPID_SHIFT, - &cur_cap); - if (ret) - return ret; - - if (cur_cap == capability) - return 0; - - ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, *offset, - CAP_NEXT_CAP_MASK, CAP_NEXT_CAP_SHIFT, - &next_offset); - if (ret) - return ret; - - *offset += next_offset; - } while (next_offset); - - return -ENXIO; -} - -void mhi_write_reg(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 val) -{ - writel_relaxed(val, base + offset); -} - -void mhi_write_reg_field(struct mhi_controller *mhi_cntrl, - void __iomem *base, - u32 offset, - u32 mask, - u32 shift, - u32 val) -{ - int ret; - u32 tmp; - - ret = mhi_read_reg(mhi_cntrl, base, offset, &tmp); - if (ret) - return; - - tmp &= ~mask; - tmp |= (val << shift); - mhi_write_reg(mhi_cntrl, base, offset, tmp); -} - -void mhi_write_db(struct mhi_controller *mhi_cntrl, - void __iomem *db_addr, - dma_addr_t wp) -{ - mhi_write_reg(mhi_cntrl, db_addr, 4, upper_32_bits(wp)); - mhi_write_reg(mhi_cntrl, db_addr, 0, lower_32_bits(wp)); -#if 0 //carl.yin 20190527 for debug - if ((lower_32_bits(db_addr)&0xFFF) != 0x620) - { - u32 out = 0; - int ret = mhi_read_reg(mhi_cntrl, db_addr, 0, &out); - if (out != lower_32_bits(wp)) - MHI_ERR("%s db=%x, wp=w:%x - r:%x, ret=%d\n", __func__, lower_32_bits(db_addr), lower_32_bits(wp), out, ret); - } -#endif -} - -void mhi_db_brstmode(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_cfg, - void __iomem *db_addr, - dma_addr_t wp) -{ - if (db_cfg->db_mode) { - db_cfg->db_val = wp; - mhi_write_db(mhi_cntrl, db_addr, wp); - db_cfg->db_mode = false; - } -} - -void mhi_db_brstmode_disable(struct mhi_controller *mhi_cntrl, - struct db_cfg *db_cfg, - void __iomem *db_addr, - dma_addr_t wp) -{ - db_cfg->db_val = wp; - mhi_write_db(mhi_cntrl, db_addr, wp); -} - -void mhi_ring_er_db(struct mhi_event *mhi_event) -{ - struct mhi_ring *ring = &mhi_event->ring; - - mhi_event->db_cfg.process_db(mhi_event->mhi_cntrl, &mhi_event->db_cfg, - ring->db_addr, *ring->ctxt_wp); -} - -void mhi_ring_cmd_db(struct mhi_controller *mhi_cntrl, struct mhi_cmd *mhi_cmd) -{ - dma_addr_t db; - struct mhi_ring *ring = &mhi_cmd->ring; - - db = ring->iommu_base + (ring->wp - ring->base); - *ring->ctxt_wp = db; - mhi_write_db(mhi_cntrl, ring->db_addr, db); -} - -//#define DEBUG_CHAN100_DB -#ifdef DEBUG_CHAN100_DB -static atomic_t chan100_seq = ATOMIC_INIT(0); -#define CHAN100_SIZE 0x1000 -static unsigned int chan100_t[CHAN100_SIZE]; -#endif - -void mhi_ring_chan_db(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *ring = &mhi_chan->tre_ring; - dma_addr_t db; - - db = ring->iommu_base + (ring->wp - ring->base); - /* - * Writes to the new ring element must be visible to the hardware - * before letting h/w know there is new element to fetch. - */ - dma_wmb(); - *ring->ctxt_wp = db; - mhi_chan->db_cfg.process_db(mhi_cntrl, &mhi_chan->db_cfg, ring->db_addr, - db); -} - -enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl) -{ - u32 exec; - int ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_EXECENV, &exec); - - return (ret) ? MHI_EE_MAX : exec; -} - -enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl) -{ - u32 state; - int ret = mhi_read_reg_field(mhi_cntrl, mhi_cntrl->regs, MHISTATUS, - MHISTATUS_MHISTATE_MASK, - MHISTATUS_MHISTATE_SHIFT, &state); - return ret ? MHI_STATE_MAX : state; -} - -int mhi_queue_sclist(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - return -EINVAL; -} - -int mhi_queue_nop(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - return -EINVAL; -} - -static void mhi_add_ring_element(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - void *wp = ring->wp; - wp += ring->el_size; - if (wp >= (ring->base + ring->len)) - wp = ring->base; - ring->wp = wp; - /* smp update */ - smp_wmb(); -} - -static void mhi_del_ring_element(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - void *rp = ring->rp; - rp += ring->el_size; - if (rp >= (ring->base + ring->len)) - rp = ring->base; - ring->rp = rp; - /* smp update */ - smp_wmb(); -} - -static int get_nr_avail_ring_elements(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - int nr_el; - - if (ring->wp < ring->rp) - nr_el = ((ring->rp - ring->wp) / ring->el_size) - 1; - else { - nr_el = (ring->rp - ring->base) / ring->el_size; - nr_el += ((ring->base + ring->len - ring->wp) / - ring->el_size) - 1; - } - return nr_el; -} - -static u32 get_used_ring_elements(void *rp, void *wp, u32 el_num) -{ - u32 nr_el; - - if (wp >= rp) - nr_el = (wp - rp)/sizeof(struct mhi_tre); - else { - nr_el = (rp - wp)/sizeof(struct mhi_tre); - nr_el = el_num - nr_el; - } - return nr_el; -} - -static void *mhi_to_virtual(struct mhi_ring *ring, dma_addr_t addr) -{ - return (addr - ring->iommu_base) + ring->base; -} - -dma_addr_t mhi_to_physical(struct mhi_ring *ring, void *addr) -{ - return (addr - ring->base) + ring->iommu_base; -} - -static void mhi_recycle_ev_ring_element(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - void *rp, *wp; - - /* update the WP */ - wp = ring->wp; - wp += ring->el_size; - if (wp >= (ring->base + ring->len)) { - wp = ring->base; - } - ring->wp = wp; - - *ring->ctxt_wp = ring->iommu_base + (ring->wp - ring->base); - - /* update the RP */ - rp = ring->rp; - rp += ring->el_size; - if (rp >= (ring->base + ring->len)) - rp = ring->base; - ring->rp = rp; - - /* visible to other cores */ - smp_wmb(); -} - -static bool mhi_is_ring_full(struct mhi_controller *mhi_cntrl, - struct mhi_ring *ring) -{ - void *tmp = ring->wp + ring->el_size; - - if (tmp >= (ring->base + ring->len)) - tmp = ring->base; - - return (tmp == ring->rp); -} - -int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info) -{ - buf_info->p_addr = dma_map_single(mhi_cntrl->dev, buf_info->v_addr, - buf_info->len, buf_info->dir); - if (dma_mapping_error(mhi_cntrl->dev, buf_info->p_addr)) - return -ENOMEM; - - return 0; -} - -int mhi_map_single_use_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info) -{ - void *buf = mhi_alloc_coherent(mhi_cntrl, buf_info->len, - &buf_info->p_addr, GFP_ATOMIC); - - if (!buf) - return -ENOMEM; - - if (buf_info->dir == DMA_TO_DEVICE) - memcpy(buf, buf_info->v_addr, buf_info->len); - - buf_info->bb_addr = buf; - - return 0; -} - -void mhi_unmap_single_no_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info) -{ - dma_unmap_single(mhi_cntrl->dev, buf_info->p_addr, buf_info->len, - buf_info->dir); -} - -void mhi_unmap_single_use_bb(struct mhi_controller *mhi_cntrl, - struct mhi_buf_info *buf_info) -{ - if (buf_info->dir == DMA_FROM_DEVICE) - memcpy(buf_info->v_addr, buf_info->bb_addr, buf_info->len); - - mhi_free_coherent(mhi_cntrl, buf_info->len, buf_info->bb_addr, - buf_info->p_addr); -} - -#ifdef ENABLE_MHI_MON -static void mon_bus_submit(struct mhi_controller *mbus, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len) -{ - unsigned long flags; - struct list_head *pos; - struct mon_reader *r; - - spin_lock_irqsave(&mbus->lock, flags); - mbus->cnt_events++; - list_for_each (pos, &mbus->r_list) { - r = list_entry(pos, struct mon_reader, r_link); - r->rnf_submit(r->r_data, chan, wp, mhi_tre, buf, len); - } - spin_unlock_irqrestore(&mbus->lock, flags); -} - -static void mon_bus_receive(struct mhi_controller *mbus, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre, void *buf, size_t len) -{ - unsigned long flags; - struct list_head *pos; - struct mon_reader *r; - - spin_lock_irqsave(&mbus->lock, flags); - mbus->cnt_events++; - list_for_each (pos, &mbus->r_list) { - r = list_entry(pos, struct mon_reader, r_link); - r->rnf_receive(r->r_data, chan, wp, mhi_tre, buf, len); - } - spin_unlock_irqrestore(&mbus->lock, flags); -} - -static void mon_bus_complete(struct mhi_controller *mbus, u32 chan, dma_addr_t wp, struct mhi_tre *mhi_tre) -{ - unsigned long flags; - struct list_head *pos; - struct mon_reader *r; - - spin_lock_irqsave(&mbus->lock, flags); - mbus->cnt_events++; - list_for_each (pos, &mbus->r_list) { - r = list_entry(pos, struct mon_reader, r_link); - r->rnf_complete(r->r_data, chan, wp, mhi_tre); - } - spin_unlock_irqrestore(&mbus->lock, flags); -} -#endif - -int mhi_queue_skb(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - struct sk_buff *skb = buf; - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - struct mhi_ring *buf_ring = &mhi_chan->buf_ring; - struct mhi_buf_info *buf_info; - struct mhi_tre *mhi_tre; - bool assert_wake = false; - int ret; - - if (mhi_is_ring_full(mhi_cntrl, tre_ring)) - return -ENOMEM; - - read_lock_bh(&mhi_cntrl->pm_lock); - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_VERB("MHI is not in activate state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return -EIO; - } - - /* we're in M3 or transitioning to M3 */ - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - - /* - * For UL channels always assert WAKE until work is done, - * For DL channels only assert if MHI is in a LPM - */ - if (mhi_chan->dir == DMA_TO_DEVICE || - (mhi_chan->dir == DMA_FROM_DEVICE && - mhi_cntrl->pm_state != MHI_PM_M0)) { - assert_wake = true; - mhi_cntrl->wake_get(mhi_cntrl, false); - } - - /* generate the tre */ - buf_info = buf_ring->wp; - buf_info->v_addr = skb->data; - buf_info->cb_buf = skb; - buf_info->wp = tre_ring->wp; - buf_info->dir = mhi_chan->dir; - buf_info->len = len; - ret = mhi_cntrl->map_single(mhi_cntrl, buf_info); - if (ret) - goto map_error; - - mhi_tre = tre_ring->wp; - - mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr); - mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_info->len); - mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(1, 1, 0, 0); - -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - mon_bus_submit(mhi_cntrl, mhi_chan->chan, - mhi_to_physical(tre_ring, mhi_tre), mhi_tre, buf_info->v_addr, mhi_chan->chan&0x1 ? 0 : buf_info->len); - } -#endif - - MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, - (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, - mhi_tre->dword[0], mhi_tre->dword[1]); - - if (mhi_chan->dir == DMA_TO_DEVICE) { - if (atomic_inc_return(&mhi_cntrl->pending_pkts) == 1) - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - } - - read_lock_bh(&mhi_chan->lock); - /* increment WP */ - mhi_add_ring_element(mhi_cntrl, tre_ring); - mhi_add_ring_element(mhi_cntrl, buf_ring); - -#ifdef DEBUG_CHAN100_DB - if (mhi_chan->chan == 100) { - chan100_t[atomic_inc_return(&chan100_seq)&(CHAN100_SIZE-1)] = (((unsigned long)tre_ring->wp)&0xffff) | (mhi_chan->db_cfg.db_mode<<31) | (0<<30); - } -#endif - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) { - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - } - read_unlock_bh(&mhi_chan->lock); - - if (mhi_chan->dir == DMA_FROM_DEVICE && assert_wake) - mhi_cntrl->wake_put(mhi_cntrl, true); - - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; - -map_error: - if (assert_wake) - mhi_cntrl->wake_put(mhi_cntrl, false); - - read_unlock_bh(&mhi_cntrl->pm_lock); - - return ret; -} - -int mhi_queue_dma(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - struct mhi_buf *mhi_buf = buf; - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - struct mhi_ring *buf_ring = &mhi_chan->buf_ring; - struct mhi_buf_info *buf_info; - struct mhi_tre *mhi_tre; - bool assert_wake = false; - - if (mhi_is_ring_full(mhi_cntrl, tre_ring)) - return -ENOMEM; - - read_lock_bh(&mhi_cntrl->pm_lock); - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_VERB("MHI is not in activate state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return -EIO; - } - - /* we're in M3 or transitioning to M3 */ - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - - /* - * For UL channels always assert WAKE until work is done, - * For DL channels only assert if MHI is in a LPM - */ - if (mhi_chan->dir == DMA_TO_DEVICE || - (mhi_chan->dir == DMA_FROM_DEVICE && - mhi_cntrl->pm_state != MHI_PM_M0)) { - assert_wake = true; - mhi_cntrl->wake_get(mhi_cntrl, false); - } - - /* generate the tre */ - buf_info = buf_ring->wp; - MHI_ASSERT(buf_info->used, "TRE Not Freed\n"); - buf_info->p_addr = mhi_buf->dma_addr; - buf_info->pre_mapped = true; - buf_info->cb_buf = mhi_buf; - buf_info->wp = tre_ring->wp; - buf_info->dir = mhi_chan->dir; - buf_info->len = len; - - mhi_tre = tre_ring->wp; - - if (mhi_chan->xfer_type == MHI_XFER_RSC_DMA) { - buf_info->used = true; - mhi_tre->ptr = - MHI_RSCTRE_DATA_PTR(buf_info->p_addr, buf_info->len); - mhi_tre->dword[0] = - MHI_RSCTRE_DATA_DWORD0(buf_ring->wp - buf_ring->base); - mhi_tre->dword[1] = MHI_RSCTRE_DATA_DWORD1; - } else { - mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr); - mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_info->len); - mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(1, 1, 0, 0); - } - -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - mon_bus_submit(mhi_cntrl, mhi_chan->chan, - mhi_to_physical(tre_ring, mhi_tre), mhi_tre, buf_info->v_addr, mhi_chan->chan&0x1 ? 0: buf_info->len); - } -#endif - - MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, - (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, - mhi_tre->dword[0], mhi_tre->dword[1]); - - if (mhi_chan->dir == DMA_TO_DEVICE) { - if (atomic_inc_return(&mhi_cntrl->pending_pkts) == 1) - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - } - - read_lock_bh(&mhi_chan->lock); - /* increment WP */ - mhi_add_ring_element(mhi_cntrl, tre_ring); - mhi_add_ring_element(mhi_cntrl, buf_ring); - - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) { - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - } - read_unlock_bh(&mhi_chan->lock); - - if (mhi_chan->dir == DMA_FROM_DEVICE && assert_wake) - mhi_cntrl->wake_put(mhi_cntrl, true); - - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; -} - -int mhi_gen_tre(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, - void *buf, - void *cb, - size_t buf_len, - enum MHI_FLAGS flags) -{ - struct mhi_ring *buf_ring, *tre_ring; - struct mhi_tre *mhi_tre; - struct mhi_buf_info *buf_info; - int eot, eob, chain, bei; - int ret; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - - buf_info = buf_ring->wp; - buf_info->v_addr = buf; - buf_info->cb_buf = cb; - buf_info->wp = tre_ring->wp; - buf_info->dir = mhi_chan->dir; - buf_info->len = buf_len; - - ret = mhi_cntrl->map_single(mhi_cntrl, buf_info); - if (ret) - return ret; - - eob = !!(flags & MHI_EOB); - eot = !!(flags & MHI_EOT); - chain = !!(flags & MHI_CHAIN); - bei = !!(mhi_chan->intmod); - - mhi_tre = tre_ring->wp; - mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr); - mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_len); - mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain); - -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - mon_bus_submit(mhi_cntrl, mhi_chan->chan, - mhi_to_physical(tre_ring, mhi_tre), mhi_tre, buf_info->v_addr, mhi_chan->chan&0x1 ? 0 : buf_info->len); - } -#endif - MHI_VERB("chan:%d WP:0x%llx TRE:0x%llx 0x%08x 0x%08x\n", mhi_chan->chan, - (u64)mhi_to_physical(tre_ring, mhi_tre), mhi_tre->ptr, - mhi_tre->dword[0], mhi_tre->dword[1]); - - /* increment WP */ - mhi_add_ring_element(mhi_cntrl, tre_ring); - mhi_add_ring_element(mhi_cntrl, buf_ring); - - return 0; -} - -int mhi_queue_buf(struct mhi_device *mhi_dev, - struct mhi_chan *mhi_chan, - void *buf, - size_t len, - enum MHI_FLAGS mflags) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_ring *tre_ring; - unsigned long flags; - bool assert_wake = false; - int ret; - - /* - * this check here only as a guard, it's always - * possible mhi can enter error while executing rest of function, - * which is not fatal so we do not need to hold pm_lock - */ - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_VERB("MHI is not in active state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - return -EIO; - } - - tre_ring = &mhi_chan->tre_ring; - if (mhi_is_ring_full(mhi_cntrl, tre_ring)) - return -ENOMEM; - - ret = mhi_chan->gen_tre(mhi_cntrl, mhi_chan, buf, buf, len, mflags); - if (unlikely(ret)) - return ret; - - read_lock_irqsave(&mhi_cntrl->pm_lock, flags); - - /* we're in M3 or transitioning to M3 */ - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - - /* - * For UL channels always assert WAKE until work is done, - * For DL channels only assert if MHI is in a LPM - */ - if (mhi_chan->dir == DMA_TO_DEVICE || - (mhi_chan->dir == DMA_FROM_DEVICE && - mhi_cntrl->pm_state != MHI_PM_M0)) { - assert_wake = true; - mhi_cntrl->wake_get(mhi_cntrl, false); - } - - if (mhi_chan->dir == DMA_TO_DEVICE) { - if (atomic_inc_return(&mhi_cntrl->pending_pkts) == 1) - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - } - - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) { - unsigned long flags; - - read_lock_irqsave(&mhi_chan->lock, flags); - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - read_unlock_irqrestore(&mhi_chan->lock, flags); - } - - if (mhi_chan->dir == DMA_FROM_DEVICE && assert_wake) - mhi_cntrl->wake_put(mhi_cntrl, true); - - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - - return 0; -} - -static ssize_t ul_chan_id_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct mhi_device *mhi_dev = to_mhi_device(dev); - - return snprintf(buf, PAGE_SIZE, "%d\n", mhi_dev->ul_chan_id); -} - -static DEVICE_ATTR_RO(ul_chan_id); - -static struct attribute *mhi_dev_attrs[] = { - &dev_attr_ul_chan_id.attr, - NULL, -}; - -static struct attribute_group mhi_dev_attr_group = { - .attrs = mhi_dev_attrs, -}; - -/* destroy specific device */ -int mhi_destroy_device(struct device *dev, void *data) -{ - struct mhi_device *mhi_dev; - struct mhi_controller *mhi_cntrl; - - if (dev->bus != &mhi_bus_type) - return 0; - - mhi_dev = to_mhi_device(dev); - mhi_cntrl = mhi_dev->mhi_cntrl; - - /* only destroying virtual devices thats attached to bus */ - if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE) - return 0; - - MHI_LOG("destroy device for chan:%s\n", mhi_dev->chan_name); - - sysfs_remove_group(&mhi_dev->dev.kobj, &mhi_dev_attr_group); - /* notify the client and remove the device from mhi bus */ - device_del(dev); - put_device(dev); - - return 0; -} - -void mhi_notify(struct mhi_device *mhi_dev, enum MHI_CB cb_reason) -{ - struct mhi_driver *mhi_drv; - - if (!mhi_dev->dev.driver) - return; - - mhi_drv = to_mhi_driver(mhi_dev->dev.driver); - - if (mhi_drv->status_cb) - mhi_drv->status_cb(mhi_dev, cb_reason); -} - -static void mhi_assign_of_node(struct mhi_controller *mhi_cntrl, - struct mhi_device *mhi_dev) -{ - struct device_node *controller, *node; - const char *dt_name; - int ret; - - controller = of_find_node_by_name(mhi_cntrl->of_node, "mhi_devices"); - if (!controller) - return; - - for_each_available_child_of_node(controller, node) { - ret = of_property_read_string(node, "mhi,chan", &dt_name); - if (ret) - continue; - if (!strcmp(mhi_dev->chan_name, dt_name)) { - mhi_dev->dev.of_node = node; - break; - } - } -} - -static ssize_t time_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - u64 t_host, t_device; - int ret; - - ret = mhi_get_remote_time_sync(mhi_dev, &t_host, &t_device); - if (ret) { - MHI_ERR("Failed to obtain time, ret:%d\n", ret); - return ret; - } - - return scnprintf(buf, PAGE_SIZE, "local: %llu remote: %llu (ticks)\n", - t_host, t_device); -} -static DEVICE_ATTR_RO(time); - -static ssize_t time_us_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - u64 t_host, t_device; - int ret; - - ret = mhi_get_remote_time_sync(mhi_dev, &t_host, &t_device); - if (ret) { - MHI_ERR("Failed to obtain time, ret:%d\n", ret); - return ret; - } - - return scnprintf(buf, PAGE_SIZE, "local: %llu remote: %llu (us)\n", - TIME_TICKS_TO_US(t_host), TIME_TICKS_TO_US(t_device)); -} -static DEVICE_ATTR_RO(time_us); - -static struct attribute *mhi_tsync_attrs[] = { - &dev_attr_time.attr, - &dev_attr_time_us.attr, - NULL, -}; - -static const struct attribute_group mhi_tsync_group = { - .attrs = mhi_tsync_attrs, -}; - -void mhi_destroy_timesync(struct mhi_controller *mhi_cntrl) -{ - if (mhi_cntrl->mhi_tsync) { - sysfs_remove_group(&mhi_cntrl->mhi_dev->dev.kobj, - &mhi_tsync_group); - kfree(mhi_cntrl->mhi_tsync); - mhi_cntrl->mhi_tsync = NULL; - } -} - -int mhi_create_timesync_sysfs(struct mhi_controller *mhi_cntrl) -{ - return sysfs_create_group(&mhi_cntrl->mhi_dev->dev.kobj, - &mhi_tsync_group); -} - -static void mhi_create_time_sync_dev(struct mhi_controller *mhi_cntrl) -{ - struct mhi_device *mhi_dev; - int ret; - - if (!MHI_IN_MISSION_MODE(mhi_cntrl->ee)) - return; - - mhi_dev = mhi_alloc_device(mhi_cntrl); - if (!mhi_dev) - return; - - mhi_dev->dev_type = MHI_TIMESYNC_TYPE; - mhi_dev->chan_name = "TIME_SYNC"; - dev_set_name(&mhi_dev->dev, "%04x_%02x.%02x.%02x_%s", mhi_dev->dev_id, - mhi_dev->domain, mhi_dev->bus, mhi_dev->slot, - mhi_dev->chan_name); - - /* add if there is a matching DT node */ - mhi_assign_of_node(mhi_cntrl, mhi_dev); - - ret = device_add(&mhi_dev->dev); - if (ret) { - MHI_ERR("Failed to register dev for chan:%s\n", - mhi_dev->chan_name); - mhi_dealloc_device(mhi_cntrl, mhi_dev); - return; - } - - mhi_cntrl->tsync_dev = mhi_dev; -} - -/* bind mhi channels into mhi devices */ -void mhi_create_devices(struct mhi_controller *mhi_cntrl) -{ - int i; - struct mhi_chan *mhi_chan; - struct mhi_device *mhi_dev; - int ret; - - /* - * we need to create time sync device before creating other - * devices, because client may try to capture time during - * clint probe. - */ - mhi_create_time_sync_dev(mhi_cntrl); - - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { - if (!mhi_chan->configured || mhi_chan->mhi_dev || - !(mhi_chan->ee_mask & BIT(mhi_cntrl->ee))) - continue; - mhi_dev = mhi_alloc_device(mhi_cntrl); - if (!mhi_dev) - return; - - mhi_dev->dev_type = MHI_XFER_TYPE; - switch (mhi_chan->dir) { - case DMA_TO_DEVICE: - mhi_dev->ul_chan = mhi_chan; - mhi_dev->ul_chan_id = mhi_chan->chan; - mhi_dev->ul_xfer = mhi_chan->queue_xfer; - mhi_dev->ul_event_id = mhi_chan->er_index; - break; - case DMA_NONE: - case DMA_BIDIRECTIONAL: - mhi_dev->ul_chan_id = mhi_chan->chan; - mhi_dev->ul_event_id = mhi_chan->er_index; - mhi_dev->dl_chan = mhi_chan; - mhi_dev->dl_chan_id = mhi_chan->chan; - mhi_dev->dl_xfer = mhi_chan->queue_xfer; - mhi_dev->dl_event_id = mhi_chan->er_index; - break; - case DMA_FROM_DEVICE: - /* we use dl_chan for offload channels */ - mhi_dev->dl_chan = mhi_chan; - mhi_dev->dl_chan_id = mhi_chan->chan; - mhi_dev->dl_xfer = mhi_chan->queue_xfer; - mhi_dev->dl_event_id = mhi_chan->er_index; - break; - } - - mhi_chan->mhi_dev = mhi_dev; - - /* check next channel if it matches */ - if ((i + 1) < mhi_cntrl->max_chan && mhi_chan[1].configured) { - if (!strcmp(mhi_chan[1].name, mhi_chan->name)) { - i++; - mhi_chan++; - if (mhi_chan->dir == DMA_TO_DEVICE) { - mhi_dev->ul_chan = mhi_chan; - mhi_dev->ul_chan_id = mhi_chan->chan; - mhi_dev->ul_xfer = mhi_chan->queue_xfer; - mhi_dev->ul_event_id = - mhi_chan->er_index; - } else { - mhi_dev->dl_chan = mhi_chan; - mhi_dev->dl_chan_id = mhi_chan->chan; - mhi_dev->dl_xfer = mhi_chan->queue_xfer; - mhi_dev->dl_event_id = - mhi_chan->er_index; - } - mhi_chan->mhi_dev = mhi_dev; - } - } - - mhi_dev->chan_name = mhi_chan->name; - dev_set_name(&mhi_dev->dev, "%04x_%02x.%02x.%02x_%s", - mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus, - mhi_dev->slot, mhi_dev->chan_name); - - /* add if there is a matching DT node */ - mhi_assign_of_node(mhi_cntrl, mhi_dev); - - /* init wake source */ - if (mhi_dev->dl_chan && mhi_dev->dl_chan->wake_capable) - device_init_wakeup(&mhi_dev->dev, true); - - ret = device_add(&mhi_dev->dev); - if (ret) { - MHI_ERR("Failed to register dev for chan:%s\n", - mhi_dev->chan_name); - mhi_dealloc_device(mhi_cntrl, mhi_dev); - } - ret = sysfs_create_group(&mhi_dev->dev.kobj, &mhi_dev_attr_group); - } -} - -static void mhi_dump_tre(struct mhi_controller *mhi_cntrl, struct mhi_tre *_ev) { - union mhi_dev_ring_element_type *ev = (union mhi_dev_ring_element_type *)_ev; - - switch (ev->generic.type) { - case MHI_DEV_RING_EL_INVALID: { - MHI_ERR("carl_ev cmd_invalid, ptr=%llx, %x, %x\n", _ev->ptr, _ev->dword[0], _ev->dword[1]); - } - break; - case MHI_DEV_RING_EL_NOOP: { - MHI_LOG("carl_ev cmd_no_op chan=%u\n", ev->cmd_no_op.chid); - } - break; - case MHI_DEV_RING_EL_TRANSFER: { - MHI_LOG("carl_ev cmd_transfer data=%llx, len=%u, chan=%u\n", - ev->cmd_transfer.data_buf_ptr, ev->cmd_transfer.len, ev->cmd_transfer.chain); - } - break; - case MHI_DEV_RING_EL_RESET: { - MHI_LOG("carl_ev cmd_reset chan=%u\n", ev->cmd_reset.chid); - } - break; - case MHI_DEV_RING_EL_STOP: { - MHI_LOG("carl_ev cmd_stop chan=%u\n", ev->cmd_stop.chid); - } - break; - case MHI_DEV_RING_EL_START: { - MHI_LOG("carl_ev cmd_start chan=%u\n", ev->cmd_start.chid); - } - break; - case MHI_DEV_RING_EL_MHI_STATE_CHG: { - MHI_LOG("carl_ev evt_state_change mhistate=%u\n", ev->evt_state_change.mhistate); - } - break; - case MHI_DEV_RING_EL_CMD_COMPLETION_EVT:{ - MHI_LOG("carl_ev evt_cmd_comp code=%u, type=%u\n", ev->evt_cmd_comp.code, ev->evt_cmd_comp.type); - } - break; - case MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT:{ - MHI_VERB("carl_ev evt_tr_comp ptr=%llx, len=%u, code=%u, chan=%u\n", - ev->evt_tr_comp.ptr, ev->evt_tr_comp.len, ev->evt_tr_comp.code, ev->evt_tr_comp.chid); - } - break; - case MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY:{ - MHI_LOG("carl_ev evt_ee_state execenv=%u\n", ev->evt_ee_state.execenv); - } - break; - case MHI_DEV_RING_EL_UNDEF: - default: { - MHI_ERR("carl_ev el_undef type=%d\n", ev->generic.type); - }; - break; - } -} - -static int parse_xfer_event(struct mhi_controller *mhi_cntrl, - struct mhi_tre *event, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring, *tre_ring; - u32 ev_code; - struct mhi_result result; - unsigned long flags = 0; - - ev_code = MHI_TRE_GET_EV_CODE(event); - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - - result.transaction_status = (ev_code == MHI_EV_CC_OVERFLOW) ? - -EOVERFLOW : 0; - - /* - * if it's a DB Event then we need to grab the lock - * with preemption disable and as a write because we - * have to update db register and another thread could - * be doing same. - */ - if (ev_code >= MHI_EV_CC_OOB) - write_lock_irqsave(&mhi_chan->lock, flags); - else - read_lock_bh(&mhi_chan->lock); - - if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) - goto end_process_tx_event; - - switch (ev_code) { - case MHI_EV_CC_OVERFLOW: - case MHI_EV_CC_EOB: - case MHI_EV_CC_EOT: - { - dma_addr_t ptr = MHI_TRE_GET_EV_PTR(event); - struct mhi_tre *local_rp, *ev_tre; - void *dev_rp; - struct mhi_buf_info *buf_info; - u16 xfer_len; - - /* Get the TRB this event points to */ - ev_tre = mhi_to_virtual(tre_ring, ptr); - - /* device rp after servicing the TREs */ - dev_rp = ev_tre + 1; - if (dev_rp >= (tre_ring->base + tre_ring->len)) - dev_rp = tre_ring->base; - - mhi_chan->used_events[ev_code]++; - - result.dir = mhi_chan->dir; - - /* local rp */ - local_rp = tre_ring->rp; - while (local_rp != dev_rp) { - buf_info = buf_ring->rp; - /* Always get the get len from the event */ - xfer_len = MHI_TRE_GET_EV_LEN(event); - - /* unmap if it's not premapped by client */ - if (likely(!buf_info->pre_mapped)) - mhi_cntrl->unmap_single(mhi_cntrl, buf_info); - - result.buf_addr = buf_info->cb_buf; - result.bytes_xferd = xfer_len; -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - void *buf = NULL; - size_t len = 0; - - if (mhi_chan->queue_xfer == mhi_queue_skb) { - struct sk_buff *skb = result.buf_addr; - buf = skb->data; - len = result.bytes_xferd; - } - else if (CHAN_INBOUND(mhi_chan->chan)) { - buf = result.buf_addr; - len = result.bytes_xferd; - } - mon_bus_receive(mhi_cntrl, mhi_chan->chan, - mhi_to_physical(tre_ring, local_rp), local_rp, buf, len); - } -#endif - mhi_del_ring_element(mhi_cntrl, buf_ring); - mhi_del_ring_element(mhi_cntrl, tre_ring); - local_rp = tre_ring->rp; - - /* notify client */ - mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result); - - if (mhi_chan->dir == DMA_TO_DEVICE) { - if (atomic_dec_return(&mhi_cntrl->pending_pkts) == 0) - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - - if (mhi_chan->dir == DMA_TO_DEVICE) { - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - } - - /* - * recycle the buffer if buffer is pre-allocated, - * if there is error, not much we can do apart from - * dropping the packet - */ - if (mhi_chan->pre_alloc) { - if (mhi_queue_buf(mhi_chan->mhi_dev, mhi_chan, - buf_info->cb_buf, - buf_info->len, MHI_EOT)) { - MHI_ERR( - "Error recycling buffer for chan:%d\n", - mhi_chan->chan); - kfree(buf_info->cb_buf); - } - } - } - break; - } /* CC_EOT */ - case MHI_EV_CC_OOB: - case MHI_EV_CC_DB_MODE: - { - unsigned long flags; - - mhi_chan->used_events[ev_code]++; - MHI_VERB("DB_MODE/OOB Detected chan %d.\n", mhi_chan->chan); - mhi_chan->db_cfg.db_mode = true; - read_lock_irqsave(&mhi_cntrl->pm_lock, flags); -#ifdef DEBUG_CHAN100_DB - if (mhi_chan->chan == 100) { - chan100_t[atomic_inc_return(&chan100_seq)&(CHAN100_SIZE-1)] = (((unsigned long)tre_ring->rp)&0xffff) | (0xf0000); - chan100_t[atomic_inc_return(&chan100_seq)&(CHAN100_SIZE-1)] = (((unsigned long)tre_ring->wp)&0xffff) | (mhi_chan->db_cfg.db_mode<<31) | (1<<30); - } -#endif - if (tre_ring->wp != tre_ring->rp && - MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state)) { - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - } - read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - break; - } - case MHI_EV_CC_BAD_TRE: - MHI_ASSERT(1, "Received BAD TRE event for ring"); - break; - default: - MHI_CRITICAL("Unknown TX completion.\n"); - - break; - } /* switch(MHI_EV_READ_CODE(EV_TRB_CODE,event)) */ - -end_process_tx_event: - if (ev_code >= MHI_EV_CC_OOB) - write_unlock_irqrestore(&mhi_chan->lock, flags); - else - read_unlock_bh(&mhi_chan->lock); - - return 0; -} - -static int parse_rsc_event(struct mhi_controller *mhi_cntrl, - struct mhi_tre *event, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring, *tre_ring; - struct mhi_buf_info *buf_info; - struct mhi_result result; - int ev_code; - u32 cookie; /* offset to local descriptor */ - u16 xfer_len; - - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - - ev_code = MHI_TRE_GET_EV_CODE(event); - cookie = MHI_TRE_GET_EV_COOKIE(event); - xfer_len = MHI_TRE_GET_EV_LEN(event); - - /* received out of bound cookie */ - MHI_ASSERT(cookie >= buf_ring->len, "Invalid Cookie\n"); - - buf_info = buf_ring->base + cookie; - - result.transaction_status = (ev_code == MHI_EV_CC_OVERFLOW) ? - -EOVERFLOW : 0; - result.bytes_xferd = xfer_len; - result.buf_addr = buf_info->cb_buf; - result.dir = mhi_chan->dir; - - read_lock_bh(&mhi_chan->lock); - - if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) - goto end_process_rsc_event; - - MHI_ASSERT(!buf_info->used, "TRE already Freed\n"); - - /* notify the client */ - mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result); - - /* - * Note: We're arbitrarily incrementing RP even though, completion - * packet we processed might not be the same one, reason we can do this - * is because device guaranteed to cache descriptors in order it - * receive, so even though completion event is different we can re-use - * all descriptors in between. - * Example: - * Transfer Ring has descriptors: A, B, C, D - * Last descriptor host queue is D (WP) and first descriptor - * host queue is A (RP). - * The completion event we just serviced is descriptor C. - * Then we can safely queue descriptors to replace A, B, and C - * even though host did not receive any completions. - */ - mhi_del_ring_element(mhi_cntrl, tre_ring); - buf_info->used = false; - -end_process_rsc_event: - read_unlock_bh(&mhi_chan->lock); - - return 0; -} - -static void mhi_process_cmd_completion(struct mhi_controller *mhi_cntrl, - struct mhi_tre *tre) -{ - dma_addr_t ptr = MHI_TRE_GET_EV_PTR(tre); - struct mhi_cmd *cmd_ring = &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING]; - struct mhi_ring *mhi_ring = &cmd_ring->ring; - struct mhi_tre *cmd_pkt; - struct mhi_chan *mhi_chan; - struct mhi_timesync *mhi_tsync; - enum mhi_cmd_type type; - u32 chan; - - cmd_pkt = mhi_to_virtual(mhi_ring, ptr); - - /* out of order completion received */ - MHI_ASSERT(cmd_pkt != mhi_ring->rp, "Out of order cmd completion"); - - type = MHI_TRE_GET_CMD_TYPE(cmd_pkt); - - if (type == MHI_CMD_TYPE_TSYNC) { - mhi_tsync = mhi_cntrl->mhi_tsync; - mhi_tsync->ccs = MHI_TRE_GET_EV_CODE(tre); - complete(&mhi_tsync->completion); - } else { - chan = MHI_TRE_GET_CMD_CHID(cmd_pkt); - mhi_chan = &mhi_cntrl->mhi_chan[chan]; - write_lock_bh(&mhi_chan->lock); - mhi_chan->ccs = MHI_TRE_GET_EV_CODE(tre); - complete(&mhi_chan->completion); - write_unlock_bh(&mhi_chan->lock); - } - - mhi_del_ring_element(mhi_cntrl, mhi_ring); -} - -int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, - u32 event_quota) -{ - struct mhi_tre *dev_rp, *local_rp; - struct mhi_ring *ev_ring = &mhi_event->ring; - struct mhi_event_ctxt *er_ctxt = - &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; - int count = 0; - - /* - * this is a quick check to avoid unnecessary event processing - * in case we already in error state, but it's still possible - * to transition to error state while processing events - */ - if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) { - MHI_ERR("No EV access, PM_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - local_rp = ev_ring->rp; - - while (dev_rp != local_rp) { - enum MHI_PKT_TYPE type = MHI_TRE_GET_EV_TYPE(local_rp); - -//#define QL_READ_EVENT_WA //from Quectel Windows driver -#ifdef QL_READ_EVENT_WA - if (mhi_event->er_index == 0) { - if (local_rp->ptr == 0 && local_rp->dword[0] == 0 && local_rp->dword[1] == 0) { - // event content no sync to memory, just break and wait next event. - MHI_ERR("Zero Event!\n"); - break; - } - } -#endif - - mhi_dump_tre(mhi_cntrl, local_rp); - MHI_VERB("Processing Event:0x%llx 0x%08x 0x%08x\n", - local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - mon_bus_complete(mhi_cntrl, mhi_event->er_index, mhi_to_physical(ev_ring, local_rp), local_rp); - } -#endif - - switch (type) { - case MHI_PKT_TYPE_STATE_CHANGE_EVENT: - { - enum mhi_dev_state new_state; - - new_state = MHI_TRE_GET_EV_STATE(local_rp); - - MHI_LOG("MHI state change event to state:%s\n", - TO_MHI_STATE_STR(new_state)); - - switch (new_state) { - case MHI_STATE_M0: - mhi_pm_m0_transition(mhi_cntrl); - break; - case MHI_STATE_M1: - mhi_pm_m1_transition(mhi_cntrl); - break; - case MHI_STATE_M3: - mhi_pm_m3_transition(mhi_cntrl); - break; - case MHI_STATE_SYS_ERR: - { - enum MHI_PM_STATE new_state; - - MHI_ERR("MHI system error detected\n"); - write_lock_irq(&mhi_cntrl->pm_lock); - new_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_SYS_ERR_DETECT); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (new_state == MHI_PM_SYS_ERR_DETECT) - schedule_work( - &mhi_cntrl->syserr_worker); - break; - } - default: - MHI_ERR("Unsupported STE:%s\n", - TO_MHI_STATE_STR(new_state)); - } - - break; - } - case MHI_PKT_TYPE_CMD_COMPLETION_EVENT: - mhi_process_cmd_completion(mhi_cntrl, local_rp); - break; - case MHI_PKT_TYPE_EE_EVENT: - { - enum MHI_ST_TRANSITION st = MHI_ST_TRANSITION_MAX; - enum mhi_ee event = MHI_TRE_GET_EV_EXECENV(local_rp); - - MHI_LOG("MHI EE received event:%s\n", - TO_MHI_EXEC_STR(event)); - switch (event) { - case MHI_EE_SBL: - st = MHI_ST_TRANSITION_SBL; - break; - case MHI_EE_FP: - st = MHI_ST_TRANSITION_FP; - break; - case MHI_EE_WFW: - case MHI_EE_AMSS: - st = MHI_ST_TRANSITION_MISSION_MODE; - break; - case MHI_EE_RDDM: - mhi_cntrl->status_cb(mhi_cntrl, - mhi_cntrl->priv_data, - MHI_CB_EE_RDDM); - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = event; - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up_all(&mhi_cntrl->state_event); - break; - default: - MHI_ERR("Unhandled EE event:%s\n", - TO_MHI_EXEC_STR(event)); - } - if (st != MHI_ST_TRANSITION_MAX) - mhi_queue_state_transition(mhi_cntrl, st); - break; - } -#if 1 //Add by Quectel - case MHI_PKT_TYPE_TX_EVENT: - case MHI_PKT_TYPE_RSC_TX_EVENT: - { - u32 chan = MHI_TRE_GET_EV_CHID(local_rp); - struct mhi_chan *mhi_chan = &mhi_cntrl->mhi_chan[chan]; - - if (likely(type == MHI_PKT_TYPE_TX_EVENT)) { - parse_xfer_event(mhi_cntrl, local_rp, mhi_chan); - } else if (type == MHI_PKT_TYPE_RSC_TX_EVENT) { - parse_rsc_event(mhi_cntrl, local_rp, mhi_chan); - } - break; - } -#endif - default: - MHI_ASSERT(1, "Unsupported ev type"); - break; - } - -#ifdef QL_READ_EVENT_WA - if (mhi_event->er_index == 0) { - local_rp->ptr = 0; - local_rp->dword[0] = local_rp->dword[1] = 0; - } -#endif - - mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring); - local_rp = ev_ring->rp; - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - count++; - } - - if (count > mhi_event->used_elements) { - mhi_event->used_elements = count; - } - - read_lock_bh(&mhi_cntrl->pm_lock); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_er_db(mhi_event); - read_unlock_bh(&mhi_cntrl->pm_lock); - - MHI_VERB("exit er_index:%u\n", mhi_event->er_index); - - return count; -} - -int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, - u32 event_quota) -{ - struct mhi_tre *dev_rp, *local_rp; - struct mhi_ring *ev_ring = &mhi_event->ring; - struct mhi_event_ctxt *er_ctxt = - &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; - int count = 0; - u32 chan; - struct mhi_chan *mhi_chan = NULL; - u32 chan_count = 0; - void *chan_local_rp = NULL; - - if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) { - MHI_ERR("No EV access, PM_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - local_rp = ev_ring->rp; - - while (dev_rp != local_rp && event_quota > 0) { - enum MHI_PKT_TYPE type = MHI_TRE_GET_EV_TYPE(local_rp); - - mhi_dump_tre(mhi_cntrl, local_rp); - MHI_VERB("Processing Event:0x%llx 0x%08x 0x%08x\n", - local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); - - chan = MHI_TRE_GET_EV_CHID(local_rp); - mhi_chan = &mhi_cntrl->mhi_chan[chan]; - chan_local_rp = mhi_chan->tre_ring.rp; - -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - mon_bus_complete(mhi_cntrl, mhi_event->er_index, mhi_to_physical(ev_ring, local_rp), local_rp); - } -#endif - if (likely(type == MHI_PKT_TYPE_TX_EVENT)) { - parse_xfer_event(mhi_cntrl, local_rp, mhi_chan); - event_quota--; - } else if (type == MHI_PKT_TYPE_RSC_TX_EVENT) { - parse_rsc_event(mhi_cntrl, local_rp, mhi_chan); - event_quota--; - } - - chan_count += get_used_ring_elements(chan_local_rp, mhi_chan->tre_ring.rp, mhi_chan->tre_ring.elements); - mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring); - local_rp = ev_ring->rp; - if (local_rp == dev_rp || event_quota == 0) { - if (chan_count > mhi_chan->used_elements) - mhi_chan->used_elements = chan_count; - chan_count = 0; - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - } - count++; - } - - if (count > mhi_event->used_elements) { - mhi_event->used_elements = count; - } - - read_lock_bh(&mhi_cntrl->pm_lock); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_er_db(mhi_event); - read_unlock_bh(&mhi_cntrl->pm_lock); - - MHI_VERB("exit er_index:%u\n", mhi_event->er_index); - - return count; -} - -int mhi_process_tsync_event_ring(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, - u32 event_quota) -{ - struct mhi_tre *dev_rp, *local_rp; - struct mhi_ring *ev_ring = &mhi_event->ring; - struct mhi_event_ctxt *er_ctxt = - &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; - struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; - int count = 0; - u32 sequence; - u64 remote_time; - - if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state))) { - MHI_ERR("No EV access, PM_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_unlock_bh(&mhi_cntrl->pm_lock); - return -EIO; - } - - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - local_rp = ev_ring->rp; - - while (dev_rp != local_rp) { - enum MHI_PKT_TYPE type = MHI_TRE_GET_EV_TYPE(local_rp); - struct tsync_node *tsync_node; - - MHI_VERB("Processing Event:0x%llx 0x%08x 0x%08x\n", - local_rp->ptr, local_rp->dword[0], local_rp->dword[1]); - - MHI_ASSERT(type != MHI_PKT_TYPE_TSYNC_EVENT, "!TSYNC event"); - - sequence = MHI_TRE_GET_EV_SEQ(local_rp); - remote_time = MHI_TRE_GET_EV_TIME(local_rp); - - do { - spin_lock_irq(&mhi_tsync->lock); - tsync_node = list_first_entry_or_null(&mhi_tsync->head, - struct tsync_node, node); - MHI_ASSERT(!tsync_node, "Unexpected Event"); - - if (unlikely(!tsync_node)) - break; - - list_del(&tsync_node->node); - spin_unlock_irq(&mhi_tsync->lock); - - /* - * device may not able to process all time sync commands - * host issue and only process last command it receive - */ - if (tsync_node->sequence == sequence) { - tsync_node->cb_func(tsync_node->mhi_dev, - sequence, - tsync_node->local_time, - remote_time); - kfree(tsync_node); - } else { - kfree(tsync_node); - } - } while (true); - - mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring); - local_rp = ev_ring->rp; - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - count++; - } - - read_lock_bh(&mhi_cntrl->pm_lock); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_er_db(mhi_event); - read_unlock_bh(&mhi_cntrl->pm_lock); - - MHI_VERB("exit er_index:%u\n", mhi_event->er_index); - - return count; -} - -void mhi_ev_task(unsigned long data) -{ - struct mhi_event *mhi_event = (struct mhi_event *)data; - struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; - - MHI_VERB("Enter for ev_index:%d\n", mhi_event->er_index); - - mhi_cntrl->runtime_mark_last_busy(mhi_cntrl, mhi_cntrl->priv_data); - /* process all pending events */ - spin_lock_bh(&mhi_event->lock); - mhi_event->process_event(mhi_cntrl, mhi_event, U32_MAX); - spin_unlock_bh(&mhi_event->lock); -} - -void mhi_ctrl_ev_task(unsigned long data) -{ - struct mhi_event *mhi_event = (struct mhi_event *)data; - struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; - enum mhi_dev_state state; - enum MHI_PM_STATE pm_state = 0; - int ret; - - MHI_VERB("Enter for ev_index:%d\n", mhi_event->er_index); - - /* - * we can check pm_state w/o a lock here because there is no way - * pm_state can change from reg access valid to no access while this - * therad being executed. - */ - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - return; - - mhi_cntrl->runtime_mark_last_busy(mhi_cntrl, mhi_cntrl->priv_data); - /* process ctrl events events */ - ret = mhi_event->process_event(mhi_cntrl, mhi_event, U32_MAX); - - /* - * we received a MSI but no events to process maybe device went to - * SYS_ERR state, check the state - */ - if (!ret) { - write_lock_irq(&mhi_cntrl->pm_lock); - state = mhi_get_mhi_state(mhi_cntrl); - if (state == MHI_STATE_SYS_ERR) { - MHI_ERR("MHI system error detected\n"); - pm_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_SYS_ERR_DETECT); - } - write_unlock_irq(&mhi_cntrl->pm_lock); - if (pm_state == MHI_PM_SYS_ERR_DETECT) - schedule_work(&mhi_cntrl->syserr_worker); - } -} - -irqreturn_t mhi_msi_handlr(int irq_number, void *dev) -{ - struct mhi_event *mhi_event = dev; - struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; - struct mhi_event_ctxt *er_ctxt = - &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index]; - struct mhi_ring *ev_ring = &mhi_event->ring; - void *dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - - /* confirm ER has pending events to process before scheduling work */ - if (ev_ring->rp == dev_rp) - return IRQ_HANDLED; - - /* client managed event ring, notify pending data */ - if (mhi_event->cl_manage) { - struct mhi_chan *mhi_chan = mhi_event->mhi_chan; - struct mhi_device *mhi_dev = mhi_chan->mhi_dev; - - if (mhi_dev) - mhi_dev->status_cb(mhi_dev, MHI_CB_PENDING_DATA); - } else - tasklet_schedule(&mhi_event->task); - - return IRQ_HANDLED; -} - -/* this is the threaded fn */ -irqreturn_t mhi_intvec_threaded_handlr(int irq_number, void *dev) -{ - struct mhi_controller *mhi_cntrl = dev; - enum mhi_dev_state state = MHI_STATE_MAX; - enum MHI_PM_STATE pm_state = 0; - enum mhi_ee ee = MHI_EE_MAX; - unsigned long flags; - - MHI_VERB("Enter\n"); - - write_lock_irqsave(&mhi_cntrl->pm_lock, flags); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) { - state = mhi_get_mhi_state(mhi_cntrl); - ee = mhi_get_exec_env(mhi_cntrl); - if (mhi_cntrl->msi_allocated >= 5 ||(mhi_cntrl->msi_allocated == 1 && (mhi_cntrl->dev_state != state || mhi_cntrl->ee != ee))) - MHI_LOG("device ee:%s dev_state:%s, pm_state:%s\n", TO_MHI_EXEC_STR(ee), - TO_MHI_STATE_STR(state), to_mhi_pm_state_str(mhi_cntrl->pm_state)); - } - - if (state == MHI_STATE_SYS_ERR) { - MHI_ERR("MHI system error detected\n"); - if (mhi_cntrl->pm_state != MHI_PM_SYS_ERR_DETECT) - pm_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_SYS_ERR_DETECT); - } - write_unlock_irqrestore(&mhi_cntrl->pm_lock, flags); - if (pm_state == MHI_PM_SYS_ERR_DETECT) { - wake_up_all(&mhi_cntrl->state_event); - - if (mhi_cntrl->ee != ee) { - MHI_LOG("device ee:%s -> %s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee), TO_MHI_EXEC_STR(ee)); - schedule_work(&mhi_cntrl->syserr_worker); - } - /* for fatal errors, we let controller decide next step */ - else if (MHI_IN_PBL(ee)) - mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, - MHI_CB_FATAL_ERROR); - else - schedule_work(&mhi_cntrl->syserr_worker); - } - if (mhi_cntrl->msi_allocated >= 5||(mhi_cntrl->msi_allocated == 1 && (mhi_cntrl->dev_state != state || mhi_cntrl->ee != ee))) - MHI_LOG("device ee:%s dev_state:%s, %s\n", TO_MHI_EXEC_STR(ee), - TO_MHI_STATE_STR(state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - if (pm_state == MHI_PM_POR) { - wake_up_all(&mhi_cntrl->state_event); - } - - MHI_VERB("Exit\n"); - - return IRQ_HANDLED; -} - -irqreturn_t mhi_intvec_handlr(int irq_number, void *dev) -{ - - struct mhi_controller *mhi_cntrl = dev; - - /* wake up any events waiting for state change */ - MHI_VERB("Enter\n"); - wake_up_all(&mhi_cntrl->state_event); - MHI_VERB("Exit\n"); - - return IRQ_WAKE_THREAD; -} - -irqreturn_t mhi_one_msi_handlr(int irq_number, void *dev) -{ - struct mhi_controller *mhi_cntrl = dev; - struct mhi_event_ctxt *er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - u32 i; - u32 handle = 0; - - for (i = 0; i < NUM_MHI_EVT_RINGS; i++, er_ctxt++, mhi_event++) { - struct mhi_ring *ev_ring = &mhi_event->ring; - void *dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - if (ev_ring->rp != dev_rp) { - handle++; - mhi_msi_handlr(irq_number, mhi_event); - } - } - - if (handle ==0) { - mhi_intvec_threaded_handlr(irq_number, dev); - } - - return IRQ_HANDLED; -} - -int mhi_send_cmd(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan, - enum MHI_CMD cmd) -{ - struct mhi_tre *cmd_tre = NULL; - struct mhi_cmd *mhi_cmd = &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING]; - struct mhi_ring *ring = &mhi_cmd->ring; - int chan = 0; - - MHI_VERB("Entered, MHI pm_state:%s dev_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - if (mhi_chan) - chan = mhi_chan->chan; - - spin_lock_bh(&mhi_cmd->lock); - if (!get_nr_avail_ring_elements(mhi_cntrl, ring)) { - spin_unlock_bh(&mhi_cmd->lock); - return -ENOMEM; - } - - /* prepare the cmd tre */ - cmd_tre = ring->wp; - switch (cmd) { - case MHI_CMD_RESET_CHAN: - cmd_tre->ptr = MHI_TRE_CMD_RESET_PTR; - cmd_tre->dword[0] = MHI_TRE_CMD_RESET_DWORD0; - cmd_tre->dword[1] = MHI_TRE_CMD_RESET_DWORD1(chan); - break; - case MHI_CMD_START_CHAN: - cmd_tre->ptr = MHI_TRE_CMD_START_PTR; - cmd_tre->dword[0] = MHI_TRE_CMD_START_DWORD0; - cmd_tre->dword[1] = MHI_TRE_CMD_START_DWORD1(chan); - break; - case MHI_CMD_TIMSYNC_CFG: - cmd_tre->ptr = MHI_TRE_CMD_TSYNC_CFG_PTR; - cmd_tre->dword[0] = MHI_TRE_CMD_TSYNC_CFG_DWORD0; - cmd_tre->dword[1] = MHI_TRE_CMD_TSYNC_CFG_DWORD1 - (mhi_cntrl->mhi_tsync->er_index); - break; - } - -#ifdef ENABLE_MHI_MON - if (mhi_cntrl->nreaders) { - mon_bus_submit(mhi_cntrl, 128, mhi_to_physical(ring, cmd_tre), cmd_tre, NULL, 0); - } -#endif - MHI_VERB("WP:0x%llx TRE: 0x%llx 0x%08x 0x%08x\n", - (u64)mhi_to_physical(ring, cmd_tre), cmd_tre->ptr, - cmd_tre->dword[0], cmd_tre->dword[1]); - - /* queue to hardware */ - mhi_add_ring_element(mhi_cntrl, ring); - read_lock_bh(&mhi_cntrl->pm_lock); - if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state))) - mhi_ring_cmd_db(mhi_cntrl, mhi_cmd); - read_unlock_bh(&mhi_cntrl->pm_lock); - spin_unlock_bh(&mhi_cmd->lock); - - return 0; -} - -static int __mhi_prepare_channel(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - int ret = 0; - - MHI_LOG("Entered: preparing channel:%d\n", mhi_chan->chan); - - if (!(BIT(mhi_cntrl->ee) & mhi_chan->ee_mask)) { - MHI_ERR("Current EE:%s Required EE Mask:0x%x for chan:%s\n", - TO_MHI_EXEC_STR(mhi_cntrl->ee), mhi_chan->ee_mask, - mhi_chan->name); - return -ENOTCONN; - } - - mutex_lock(&mhi_chan->mutex); - - /* if channel is not disable state do not allow to start */ - if (mhi_chan->ch_state != MHI_CH_STATE_DISABLED) { - ret = -EIO; - MHI_LOG("channel:%d is not in disabled state, ch_state%d\n", - mhi_chan->chan, mhi_chan->ch_state); - goto error_init_chan; - } - - /* client manages channel context for offload channels */ - if (!mhi_chan->offload_ch) { - ret = mhi_init_chan_ctxt(mhi_cntrl, mhi_chan); - if (ret) { - MHI_ERR("Error with init chan\n"); - goto error_init_chan; - } - } - - reinit_completion(&mhi_chan->completion); - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("MHI host is not in active state\n"); - read_unlock_bh(&mhi_cntrl->pm_lock); - ret = -EIO; - goto error_pm_state; - } - - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - - ret = mhi_send_cmd(mhi_cntrl, mhi_chan, MHI_CMD_START_CHAN); - if (ret) { - MHI_ERR("Failed to send start chan cmd\n"); - goto error_send_cmd; - } - - ret = wait_for_completion_timeout(&mhi_chan->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret || mhi_chan->ccs != MHI_EV_CC_SUCCESS) { - MHI_ERR("Failed to receive cmd completion for chan:%d\n", - mhi_chan->chan); - ret = -EIO; - goto error_send_cmd; - } - - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - - write_lock_irq(&mhi_chan->lock); - mhi_chan->ch_state = MHI_CH_STATE_ENABLED; - write_unlock_irq(&mhi_chan->lock); - - /* pre allocate buffer for xfer ring */ - if (mhi_chan->pre_alloc) { - int nr_el = get_nr_avail_ring_elements(mhi_cntrl, - &mhi_chan->tre_ring); - size_t len = mhi_cntrl->buffer_len; - - while (nr_el--) { - void *buf; - - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto error_pre_alloc; - } - - /* prepare transfer descriptors */ - ret = mhi_chan->gen_tre(mhi_cntrl, mhi_chan, buf, buf, - len, MHI_EOT); - if (ret) { - MHI_ERR("Chan:%d error prepare buffer\n", - mhi_chan->chan); - kfree(buf); - goto error_pre_alloc; - } - } - - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state)) { - read_lock_irq(&mhi_chan->lock); - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - read_unlock_irq(&mhi_chan->lock); - } - read_unlock_bh(&mhi_cntrl->pm_lock); - } - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - mutex_unlock(&mhi_chan->mutex); - - MHI_LOG("Chan:%d successfully moved to start state\n", mhi_chan->chan); - - return 0; - -error_send_cmd: - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - -error_pm_state: - if (!mhi_chan->offload_ch) - mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); - -error_init_chan: - mutex_unlock(&mhi_chan->mutex); - - return ret; - -error_pre_alloc: - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - mutex_unlock(&mhi_chan->mutex); - __mhi_unprepare_channel(mhi_cntrl, mhi_chan); - - return ret; -} - -static void mhi_mark_stale_events(struct mhi_controller *mhi_cntrl, - struct mhi_event *mhi_event, - struct mhi_event_ctxt *er_ctxt, - int chan) -{ - struct mhi_tre *dev_rp, *local_rp; - struct mhi_ring *ev_ring; - unsigned long flags; - - MHI_LOG("Marking all events for chan:%d as stale\n", chan); - - ev_ring = &mhi_event->ring; - - /* mark all stale events related to channel as STALE event */ - spin_lock_irqsave(&mhi_event->lock, flags); - dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp); - - local_rp = ev_ring->rp; - while (dev_rp != local_rp) { - if (MHI_TRE_GET_EV_TYPE(local_rp) == - MHI_PKT_TYPE_TX_EVENT && - chan == MHI_TRE_GET_EV_CHID(local_rp)) - local_rp->dword[1] = MHI_TRE_EV_DWORD1(chan, - MHI_PKT_TYPE_STALE_EVENT); - local_rp++; - if (local_rp == (ev_ring->base + ev_ring->len)) - local_rp = ev_ring->base; - } - - - MHI_LOG("Finished marking events as stale events\n"); - spin_unlock_irqrestore(&mhi_event->lock, flags); -} - -static void mhi_reset_data_chan(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring, *tre_ring; - struct mhi_result result; - - /* reset any pending buffers */ - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - result.transaction_status = -ENOTCONN; - result.bytes_xferd = 0; - while (tre_ring->rp != tre_ring->wp) { - struct mhi_buf_info *buf_info = buf_ring->rp; - - if (mhi_chan->dir == DMA_TO_DEVICE) { - if (atomic_dec_return(&mhi_cntrl->pending_pkts) == 0) - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - - if (mhi_chan->dir == DMA_TO_DEVICE) - mhi_cntrl->wake_put(mhi_cntrl, false); - if (!buf_info->pre_mapped) - mhi_cntrl->unmap_single(mhi_cntrl, buf_info); - mhi_del_ring_element(mhi_cntrl, buf_ring); - mhi_del_ring_element(mhi_cntrl, tre_ring); - - if (mhi_chan->pre_alloc) { - kfree(buf_info->cb_buf); - } else { - result.buf_addr = buf_info->cb_buf; - mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result); - } - } -} - -static void mhi_reset_rsc_chan(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - struct mhi_ring *buf_ring, *tre_ring; - struct mhi_result result; - struct mhi_buf_info *buf_info; - - /* reset any pending buffers */ - buf_ring = &mhi_chan->buf_ring; - tre_ring = &mhi_chan->tre_ring; - result.transaction_status = -ENOTCONN; - result.bytes_xferd = 0; - - buf_info = buf_ring->base; - for (; (void *)buf_info < buf_ring->base + buf_ring->len; buf_info++) { - if (!buf_info->used) - continue; - - result.buf_addr = buf_info->cb_buf; - mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result); - buf_info->used = false; - } -} - -void mhi_reset_chan(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan) -{ - - struct mhi_event *mhi_event; - struct mhi_event_ctxt *er_ctxt; - int chan = mhi_chan->chan; - - /* nothing to reset, client don't queue buffers */ - if (mhi_chan->offload_ch) - return; - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_event = &mhi_cntrl->mhi_event[mhi_chan->er_index]; - er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_chan->er_index]; - - mhi_mark_stale_events(mhi_cntrl, mhi_event, er_ctxt, chan); - - if (mhi_chan->xfer_type == MHI_XFER_RSC_DMA) - mhi_reset_rsc_chan(mhi_cntrl, mhi_chan); - else - mhi_reset_data_chan(mhi_cntrl, mhi_chan); - - read_unlock_bh(&mhi_cntrl->pm_lock); - MHI_LOG("Reset complete.\n"); -} - -static void __mhi_unprepare_channel(struct mhi_controller *mhi_cntrl, - struct mhi_chan *mhi_chan) -{ - int ret; - - MHI_LOG("Entered: unprepare channel:%d\n", mhi_chan->chan); - - /* no more processing events for this channel */ - mutex_lock(&mhi_chan->mutex); - write_lock_irq(&mhi_chan->lock); - if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) { - MHI_LOG("chan:%d is already disabled\n", mhi_chan->chan); - write_unlock_irq(&mhi_chan->lock); - mutex_unlock(&mhi_chan->mutex); - return; - } - - mhi_chan->ch_state = MHI_CH_STATE_DISABLED; - write_unlock_irq(&mhi_chan->lock); - - reinit_completion(&mhi_chan->completion); - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - read_unlock_bh(&mhi_cntrl->pm_lock); - goto error_invalid_state; - } - - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - ret = mhi_send_cmd(mhi_cntrl, mhi_chan, MHI_CMD_RESET_CHAN); - if (ret) { - MHI_ERR("Failed to send reset chan cmd\n"); - goto error_completion; - } - - /* even if it fails we will still reset */ - ret = wait_for_completion_timeout(&mhi_chan->completion, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - if (!ret || mhi_chan->ccs != MHI_EV_CC_SUCCESS) - MHI_ERR("Failed to receive cmd completion, still resetting\n"); - -error_completion: - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - -error_invalid_state: - if (!mhi_chan->offload_ch) { - mhi_reset_chan(mhi_cntrl, mhi_chan); - mhi_deinit_chan_ctxt(mhi_cntrl, mhi_chan); - } - MHI_LOG("chan:%d successfully resetted\n", mhi_chan->chan); - mutex_unlock(&mhi_chan->mutex); -} - -int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d) -{ - struct mhi_controller *mhi_cntrl = m->private; - int reg = 0; - int ret; - u32 val[4]; - - seq_printf(m, - "pm_state:%s dev_state:%s EE:%s M0:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), - mhi_cntrl->M0, mhi_cntrl->M2, mhi_cntrl->M3, - mhi_cntrl->wake_set, - atomic_read(&mhi_cntrl->dev_wake), - atomic_read(&mhi_cntrl->alloc_size)); - - seq_printf(m, - "mhi_state:%s exec_env:%s\n", - TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl)), TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl))); - - seq_printf(m, "dump mhi reg addr:%p\n", mhi_cntrl->regs); - for (reg = 0; reg < 0x100; reg+=16) { - val[0] = val[1] = val[2] = val[3] = 0xFFFFFFFF; - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, reg+0, &val[0]); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, reg+4, &val[1]); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, reg+8, &val[2]); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, reg+12, &val[3]); - seq_printf(m, "%02x: %08x %08x %08x %08x\n", reg, val[0], val[1], val[2], val[3]); - } - - seq_printf(m, "dump bhi reg addr:%p\n", mhi_cntrl->bhi); - for (reg = 0; reg < 0x100; reg+=16) { - val[0] = val[1] = val[2] = val[3] = 0xFFFFFFFF; - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, reg+0, &val[0]); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, reg+4, &val[1]); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, reg+8, &val[2]); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, reg+12, &val[3]); - seq_printf(m, "%02x: %08x %08x %08x %08x\n", reg, val[0], val[1], val[2], val[3]); - } - - return 0; -} - -int mhi_debugfs_mhi_event_show(struct seq_file *m, void *d) -{ - struct mhi_controller *mhi_cntrl = m->private; - struct mhi_event *mhi_event; - struct mhi_event_ctxt *er_ctxt; - - int i; - - er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, er_ctxt++, - mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev) { - seq_printf(m, "Index:%d offload event ring\n", i); - } else { - seq_printf(m, - "Index:%d modc:%d modt:%d base:0x%0llx len:0x%llx", - i, er_ctxt->intmodc, er_ctxt->intmodt, - er_ctxt->rbase, er_ctxt->rlen); - seq_printf(m, - " rp:0x%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n", - er_ctxt->rp, er_ctxt->wp, - (unsigned long long)mhi_to_physical(ring, ring->rp), - (unsigned long long)mhi_to_physical(ring, ring->wp), - (unsigned long long)mhi_event->db_cfg.db_val); - seq_printf(m, "used:%u\n", mhi_event->used_elements); - -#ifdef DEBUG_CHAN100_DB - if (mhi_event->mhi_chan && mhi_event->chan == 100) { - struct mhi_tre *tre = (struct mhi_tre *)ring->base; - size_t j; - - for (j = 0; j < ring->elements; j++, tre++) { - seq_printf(m, - "%08x: %llx, %08x, %08x\n", - (unsigned int)(j*sizeof(struct mhi_tre)), - tre->ptr, tre->dword[0], tre->dword[1]); - } - } -#endif - } - } - - return 0; -} - -int mhi_debugfs_mhi_chan_show(struct seq_file *m, void *d) -{ - struct mhi_controller *mhi_cntrl = m->private; - struct mhi_chan *mhi_chan; - struct mhi_chan_ctxt *chan_ctxt; - int i; - - mhi_chan = mhi_cntrl->mhi_chan; - chan_ctxt = mhi_cntrl->mhi_ctxt->chan_ctxt; - for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) { - struct mhi_ring *ring = &mhi_chan->tre_ring; - - if (mhi_chan->ch_state == MHI_CH_STATE_DISABLED) - continue; - - if (mhi_chan->offload_ch) { - seq_printf(m, "%s(%u) offload channel\n", - mhi_chan->name, mhi_chan->chan); - } else if (mhi_chan->mhi_dev) { - seq_printf(m, - "%s(%u) state:0x%x brstmode:0x%x pllcfg:0x%x type:0x%x erindex:%u", - mhi_chan->name, mhi_chan->chan, - chan_ctxt->chstate, chan_ctxt->brstmode, - chan_ctxt->pollcfg, chan_ctxt->chtype, - chan_ctxt->erindex); - seq_printf(m, - " base:0x%llx len:0x%llx rp:%llx wp:0x%llx local_rp:0x%llx local_wp:0x%llx db:0x%llx\n", - chan_ctxt->rbase, chan_ctxt->rlen, - chan_ctxt->rp, chan_ctxt->wp, - (unsigned long long)mhi_to_physical(ring, ring->rp), - (unsigned long long)mhi_to_physical(ring, ring->wp), - (unsigned long long)mhi_chan->db_cfg.db_val); - seq_printf(m, "used:%u, EOB:%u, EOT:%u, OOB:%u, DB_MODE:%u\n", mhi_chan->used_elements, - mhi_chan->used_events[MHI_EV_CC_EOB], mhi_chan->used_events[MHI_EV_CC_EOT], - mhi_chan->used_events[MHI_EV_CC_OOB],mhi_chan->used_events[MHI_EV_CC_DB_MODE]); - -#ifdef DEBUG_CHAN100_DB - if (mhi_chan->chan == 100) { - unsigned int n = 0; - seq_printf(m, "chan100_seq = %04x\n", atomic_read(&chan100_seq)%CHAN100_SIZE); - for (n = 0; n < CHAN100_SIZE; n++) { - seq_printf(m, "%04x: %08x\n", n, chan100_t[n]); - } - } -#endif - -#if 0 - if (ring->base && /*(i&1) &&*/ (i < MHI_CLIENT_IP_HW_0_OUT)) { - struct mhi_tre *tre = (struct mhi_tre *)ring->base; - size_t e; - - for (e = 0; e < ring->elements; e++, tre++) { - seq_printf(m, "[%03d] %llx, %08x, %08x\n", i, tre->ptr, tre->dword[0], tre->dword[1]); - } - } -#endif - } - } - - return 0; -} - -/* move channel to start state */ -int mhi_prepare_for_transfer(struct mhi_device *mhi_dev) -{ - int ret, dir; - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->dl_chan : mhi_dev->ul_chan; - - if (!mhi_chan) - continue; - - ret = __mhi_prepare_channel(mhi_cntrl, mhi_chan); - if (ret) { - MHI_ERR("Error moving chan %s,%d to START state\n", - mhi_chan->name, mhi_chan->chan); - goto error_open_chan; - } - - if (mhi_dev->dl_chan == mhi_dev->ul_chan) { - break; - } - } - - return 0; - -error_open_chan: - for (--dir; dir >= 0; dir--) { - mhi_chan = dir ? mhi_dev->dl_chan : mhi_dev->ul_chan; - - if (!mhi_chan) - continue; - - __mhi_unprepare_channel(mhi_cntrl, mhi_chan); - } - - return ret; -} -EXPORT_SYMBOL(mhi_prepare_for_transfer); - -void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan; - int dir; - - for (dir = 0; dir < 2; dir++) { - mhi_chan = dir ? mhi_dev->ul_chan : mhi_dev->dl_chan; - - if (!mhi_chan) - continue; - - __mhi_unprepare_channel(mhi_cntrl, mhi_chan); - - if (mhi_dev->dl_chan == mhi_dev->ul_chan) { - break; - } - } -} -EXPORT_SYMBOL(mhi_unprepare_from_transfer); - -int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, - enum dma_data_direction dir) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? - mhi_dev->ul_chan : mhi_dev->dl_chan; - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - - if (mhi_chan->offload_ch) - return 0; - - return get_nr_avail_ring_elements(mhi_cntrl, tre_ring); -} -EXPORT_SYMBOL(mhi_get_no_free_descriptors); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,3,0 )) -static int __mhi_bdf_to_controller(struct device *dev, void *tmp) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - struct mhi_device *match = tmp; - - /* return any none-zero value if match */ - if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE && - mhi_dev->domain == match->domain && mhi_dev->bus == match->bus && - mhi_dev->slot == match->slot && mhi_dev->dev_id == match->dev_id) - return 1; - - return 0; -} -#else -static int __mhi_bdf_to_controller(struct device *dev, const void *tmp) -{ - struct mhi_device *mhi_dev = to_mhi_device(dev); - const struct mhi_device *match = tmp; - - /* return any none-zero value if match */ - if (mhi_dev->dev_type == MHI_CONTROLLER_TYPE && - mhi_dev->domain == match->domain && mhi_dev->bus == match->bus && - mhi_dev->slot == match->slot && mhi_dev->dev_id == match->dev_id) - return 1; - - return 0; -} -#endif - -struct mhi_controller *mhi_bdf_to_controller(u32 domain, - u32 bus, - u32 slot, - u32 dev_id) -{ - struct mhi_device tmp, *mhi_dev; - struct device *dev; - - tmp.domain = domain; - tmp.bus = bus; - tmp.slot = slot; - tmp.dev_id = dev_id; - - dev = bus_find_device(&mhi_bus_type, NULL, &tmp, - __mhi_bdf_to_controller); - if (!dev) - return NULL; - - mhi_dev = to_mhi_device(dev); - - return mhi_dev->mhi_cntrl; -} -EXPORT_SYMBOL(mhi_bdf_to_controller); - -int mhi_poll(struct mhi_device *mhi_dev, - u32 budget) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_chan *mhi_chan = mhi_dev->dl_chan; - struct mhi_event *mhi_event = &mhi_cntrl->mhi_event[mhi_chan->er_index]; - int ret; - - spin_lock_bh(&mhi_event->lock); - ret = mhi_event->process_event(mhi_cntrl, mhi_event, budget); - spin_unlock_bh(&mhi_event->lock); - - return ret; -} -EXPORT_SYMBOL(mhi_poll); - -int mhi_get_remote_time_sync(struct mhi_device *mhi_dev, - u64 *t_host, - u64 *t_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; - int ret; - - /* not all devices support time feature */ - if (!mhi_tsync) - return -EIO; - - /* bring to M0 state */ - ret = __mhi_device_get_sync(mhi_cntrl); - if (ret) - return ret; - - mutex_lock(&mhi_tsync->lpm_mutex); - - read_lock_bh(&mhi_cntrl->pm_lock); - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_ERR("MHI is not in active state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - ret = -EIO; - goto error_invalid_state; - } - - /* disable link level low power modes */ - ret = mhi_cntrl->lpm_disable(mhi_cntrl, mhi_cntrl->priv_data); - if (ret) - goto error_invalid_state; - - /* - * time critical code to fetch device times, - * delay between these two steps should be - * deterministic as possible. - */ - preempt_disable(); - local_irq_disable(); - - *t_host = mhi_cntrl->time_get(mhi_cntrl, mhi_cntrl->priv_data); - *t_dev = readq_relaxed_no_log(mhi_tsync->time_reg); - - local_irq_enable(); - preempt_enable(); - - mhi_cntrl->lpm_enable(mhi_cntrl, mhi_cntrl->priv_data); - -error_invalid_state: - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - mutex_unlock(&mhi_tsync->lpm_mutex); - - return ret; -} -EXPORT_SYMBOL(mhi_get_remote_time_sync); - -/** - * mhi_get_remote_time - Get external modem time relative to host time - * Trigger event to capture modem time, also capture host time so client - * can do a relative drift comparision. - * Recommended only tsync device calls this method and do not call this - * from atomic context - * @mhi_dev: Device associated with the channels - * @sequence:unique sequence id track event - * @cb_func: callback function to call back - */ -int mhi_get_remote_time(struct mhi_device *mhi_dev, - u32 sequence, - void (*cb_func)(struct mhi_device *mhi_dev, - u32 sequence, - u64 local_time, - u64 remote_time)) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; - struct tsync_node *tsync_node; - int ret; - - /* not all devices support time feature */ - if (!mhi_tsync) - return -EIO; - - /* tsync db can only be rung in M0 state */ - ret = __mhi_device_get_sync(mhi_cntrl); - if (ret) - return ret; - - /* - * technically we can use GFP_KERNEL, but wants to avoid - * # of times scheduling out - */ - tsync_node = kzalloc(sizeof(*tsync_node), GFP_ATOMIC); - if (!tsync_node) { - ret = -ENOMEM; - goto error_no_mem; - } - - tsync_node->sequence = sequence; - tsync_node->cb_func = cb_func; - tsync_node->mhi_dev = mhi_dev; - - /* disable link level low power modes */ - mhi_cntrl->lpm_disable(mhi_cntrl, mhi_cntrl->priv_data); - - read_lock_bh(&mhi_cntrl->pm_lock); - if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { - MHI_ERR("MHI is not in active state, pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - ret = -EIO; - goto error_invalid_state; - } - - spin_lock_irq(&mhi_tsync->lock); - list_add_tail(&tsync_node->node, &mhi_tsync->head); - spin_unlock_irq(&mhi_tsync->lock); - - /* - * time critical code, delay between these two steps should be - * deterministic as possible. - */ - preempt_disable(); - local_irq_disable(); - - tsync_node->local_time = - mhi_cntrl->time_get(mhi_cntrl, mhi_cntrl->priv_data); - writel_relaxed_no_log(tsync_node->sequence, mhi_tsync->db); - /* write must go thru immediately */ - wmb(); - - local_irq_enable(); - preempt_enable(); - - ret = 0; - -error_invalid_state: - if (ret) - kfree(tsync_node); - read_unlock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->lpm_enable(mhi_cntrl, mhi_cntrl->priv_data); - -error_no_mem: - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return ret; -} -EXPORT_SYMBOL(mhi_get_remote_time); - -void mhi_debug_reg_dump(struct mhi_controller *mhi_cntrl) -{ - enum mhi_dev_state state; - enum mhi_ee ee; - int i, ret; - u32 val = 0; - void __iomem *mhi_base = mhi_cntrl->regs; - void __iomem *bhi_base = mhi_cntrl->bhi; - void __iomem *bhie_base = mhi_cntrl->bhie; - void __iomem *wake_db = mhi_cntrl->wake_db; - struct { - const char *name; - int offset; - void *base; - } debug_reg[] = { - { "MHI_CNTRL", MHICTRL, mhi_base}, - { "MHI_STATUS", MHISTATUS, mhi_base}, - { "MHI_WAKE_DB", 0, wake_db}, - { "BHI_EXECENV", BHI_EXECENV, bhi_base}, - { "BHI_STATUS", BHI_STATUS, bhi_base}, - { "BHI_ERRCODE", BHI_ERRCODE, bhi_base}, - { "BHI_ERRDBG1", BHI_ERRDBG1, bhi_base}, - { "BHI_ERRDBG2", BHI_ERRDBG2, bhi_base}, - { "BHI_ERRDBG3", BHI_ERRDBG3, bhi_base}, - { "BHIE_TXVEC_DB", BHIE_TXVECDB_OFFS, bhie_base}, - { "BHIE_TXVEC_STATUS", BHIE_TXVECSTATUS_OFFS, bhie_base}, - { "BHIE_RXVEC_DB", BHIE_RXVECDB_OFFS, bhie_base}, - { "BHIE_RXVEC_STATUS", BHIE_RXVECSTATUS_OFFS, bhie_base}, - { NULL }, - }; - - MHI_LOG("host pm_state:%s dev_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - state = mhi_get_mhi_state(mhi_cntrl); - ee = mhi_get_exec_env(mhi_cntrl); - - MHI_LOG("device ee:%s dev_state:%s\n", TO_MHI_EXEC_STR(ee), - TO_MHI_STATE_STR(state)); - - for (i = 0; debug_reg[i].name; i++) { - ret = mhi_read_reg(mhi_cntrl, debug_reg[i].base, - debug_reg[i].offset, &val); - MHI_LOG("reg:%s val:0x%x, ret:%d\n", debug_reg[i].name, val, - ret); - } -} -EXPORT_SYMBOL(mhi_debug_reg_dump); diff --git a/quectel_MHI/src/core/mhi_pm.c b/quectel_MHI/src/core/mhi_pm.c deleted file mode 100644 index 117a600..0000000 --- a/quectel_MHI/src/core/mhi_pm.c +++ /dev/null @@ -1,1255 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mhi.h" -#include "mhi_internal.h" - -/* - * Not all MHI states transitions are sync transitions. Linkdown, SSR, and - * shutdown can happen anytime asynchronously. This function will transition to - * new state only if we're allowed to transitions. - * - * Priority increase as we go down, example while in any states from L0, start - * state from L1, L2, or L3 can be set. Notable exception to this rule is state - * DISABLE. From DISABLE state we can transition to only POR or state. Also - * for example while in L2 state, user cannot jump back to L1 or L0 states. - * Valid transitions: - * L0: DISABLE <--> POR - * POR <--> POR - * POR -> M0 -> M2 --> M0 - * POR -> FW_DL_ERR - * FW_DL_ERR <--> FW_DL_ERR - * M0 -> FW_DL_ERR - * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0 - * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR - * L2: SHUTDOWN_PROCESS -> DISABLE - * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT - * LD_ERR_FATAL_DETECT -> SHUTDOWN_PROCESS - */ -static struct mhi_pm_transitions const mhi_state_transitions[] = { - /* L0 States */ - { - MHI_PM_DISABLE, - MHI_PM_POR - }, - { - MHI_PM_POR, - MHI_PM_POR | MHI_PM_DISABLE | MHI_PM_M0 | - MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_FW_DL_ERR - }, - { - MHI_PM_M0, - MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT | - MHI_PM_FW_DL_ERR - }, - { - MHI_PM_M2, - MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M3_ENTER, - MHI_PM_M3 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M3, - MHI_PM_M3_EXIT | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_M3_EXIT, - MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_FW_DL_ERR, - MHI_PM_FW_DL_ERR | MHI_PM_SYS_ERR_DETECT | - MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT - }, - /* L1 States */ - { - MHI_PM_SYS_ERR_DETECT, - MHI_PM_SYS_ERR_PROCESS | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - { - MHI_PM_SYS_ERR_PROCESS, - MHI_PM_POR | MHI_PM_SHUTDOWN_PROCESS | - MHI_PM_LD_ERR_FATAL_DETECT - }, - /* L2 States */ - { - MHI_PM_SHUTDOWN_PROCESS, - MHI_PM_DISABLE | MHI_PM_LD_ERR_FATAL_DETECT - }, - /* L3 States */ - { - MHI_PM_LD_ERR_FATAL_DETECT, - MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_SHUTDOWN_PROCESS - }, -}; - -enum MHI_PM_STATE __must_check mhi_tryset_pm_state( - struct mhi_controller *mhi_cntrl, - enum MHI_PM_STATE state) -{ - unsigned long cur_state = mhi_cntrl->pm_state; - int index = find_last_bit(&cur_state, 32); - - if (unlikely(index >= ARRAY_SIZE(mhi_state_transitions))) { - MHI_CRITICAL("cur_state:%s is not a valid pm_state\n", - to_mhi_pm_state_str(cur_state)); - return cur_state; - } - - if (unlikely(mhi_state_transitions[index].from_state != cur_state)) { - MHI_ERR("index:%u cur_state:%s != actual_state: %s\n", - index, to_mhi_pm_state_str(cur_state), - to_mhi_pm_state_str - (mhi_state_transitions[index].from_state)); - return cur_state; - } - - if (unlikely(!(mhi_state_transitions[index].to_states & state))) { - MHI_LOG( - "Not allowing pm state transition from:%s to:%s state\n", - to_mhi_pm_state_str(cur_state), - to_mhi_pm_state_str(state)); - return cur_state; - } - - MHI_LOG("Transition to pm state from:%s to:%s\n", - to_mhi_pm_state_str(cur_state), to_mhi_pm_state_str(state)); - - mhi_cntrl->pm_state = state; - return mhi_cntrl->pm_state; -} - -void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, - enum mhi_dev_state state) -{ - if (state == MHI_STATE_RESET) { - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, - MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 1); - } else { - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICTRL, - MHICTRL_MHISTATE_MASK, MHICTRL_MHISTATE_SHIFT, state); - } -} - -/* set device wake */ -void mhi_assert_dev_wake(struct mhi_controller *mhi_cntrl, bool force) -{ - unsigned long flags; - -#if 1 //carl.yin 20200907, according to WIN driver, only in M2 state, need to assert, and do not need to deassert - if (mhi_cntrl->dev_state == MHI_STATE_M2) { - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 1); - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); - } - return; -#endif - - /* if set, regardless of count set the bit if not set */ - if (unlikely(force)) { - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - atomic_inc(&mhi_cntrl->dev_wake); - if (MHI_WAKE_DB_FORCE_SET_VALID(mhi_cntrl->pm_state) && - !mhi_cntrl->wake_set) { - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 1); - mhi_cntrl->wake_set = true; - } - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); - } else { - /* if resources requested already, then increment and exit */ - if (likely(atomic_add_unless(&mhi_cntrl->dev_wake, 1, 0))) - return; - - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - if ((atomic_inc_return(&mhi_cntrl->dev_wake) == 1) && - MHI_WAKE_DB_SET_VALID(mhi_cntrl->pm_state) && - !mhi_cntrl->wake_set) { - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 1); - mhi_cntrl->wake_set = true; - } - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); - } -} - -/* clear device wake */ -void mhi_deassert_dev_wake(struct mhi_controller *mhi_cntrl, bool override) -{ - unsigned long flags; - -#if 1 //carl.yin 20200907, according to WIN driver, only in M2 state, need to assert, and do not need to deassert - return; -#endif - -#if 1 //Add by Quectel - if (atomic_read(&mhi_cntrl->dev_wake) == 0) - return; -#endif - - MHI_ASSERT(atomic_read(&mhi_cntrl->dev_wake) == 0, "dev_wake == 0"); - - /* resources not dropping to 0, decrement and exit */ - if (likely(atomic_add_unless(&mhi_cntrl->dev_wake, -1, 1))) - return; - - spin_lock_irqsave(&mhi_cntrl->wlock, flags); - if ((atomic_dec_return(&mhi_cntrl->dev_wake) == 0) && - MHI_WAKE_DB_CLEAR_VALID(mhi_cntrl->pm_state) && !override && - mhi_cntrl->wake_set) { - mhi_write_db(mhi_cntrl, mhi_cntrl->wake_db, 0); - mhi_cntrl->wake_set = false; - } - spin_unlock_irqrestore(&mhi_cntrl->wlock, flags); -} - -int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl) -{ - void __iomem *base = mhi_cntrl->regs; - u32 reset = 1, ready = 0; - struct mhi_event *mhi_event; - enum MHI_PM_STATE cur_state; - int ret, i; - - MHI_LOG("Waiting to enter READY state\n"); - - /* wait for RESET to be cleared and READY bit to be set */ - wait_event_timeout(mhi_cntrl->state_event, - MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state) || - mhi_read_reg_field(mhi_cntrl, base, MHICTRL, - MHICTRL_RESET_MASK, - MHICTRL_RESET_SHIFT, &reset) || - mhi_read_reg_field(mhi_cntrl, base, MHISTATUS, - MHISTATUS_READY_MASK, - MHISTATUS_READY_SHIFT, &ready) || - (!reset && ready), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - /* device enter into error state */ - if (MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state)) - return -EIO; - - /* device did not transition to ready state */ - if (reset || !ready) - return -ETIMEDOUT; - - MHI_LOG("Device in READY State\n"); - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_POR); - mhi_cntrl->dev_state = MHI_STATE_READY; - write_unlock_irq(&mhi_cntrl->pm_lock); - - if (cur_state != MHI_PM_POR) { - MHI_ERR("Error moving to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_POR), - to_mhi_pm_state_str(cur_state)); - return -EIO; - } - read_lock_bh(&mhi_cntrl->pm_lock); - if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - goto error_mmio; - - ret = mhi_init_mmio(mhi_cntrl); - if (ret) { - MHI_ERR("Error programming mmio registers\n"); - goto error_mmio; - } - - /* add elements to all sw event rings */ - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev || mhi_event->hw_ring) - continue; - - ring->wp = ring->base + ring->len - ring->el_size; - *ring->ctxt_wp = ring->iommu_base + ring->len - ring->el_size; - /* needs to update to all cores */ - smp_wmb(); - - /* ring the db for event rings */ - spin_lock_irq(&mhi_event->lock); - mhi_ring_er_db(mhi_event); - spin_unlock_irq(&mhi_event->lock); - } - - /* set device into M0 state */ - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M0); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return 0; - -error_mmio: - read_unlock_bh(&mhi_cntrl->pm_lock); - - return -EIO; -} - -int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE cur_state; - struct mhi_chan *mhi_chan; - int i; - - MHI_LOG("Entered With State:%s PM_STATE:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_M0; - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M0); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (unlikely(cur_state != MHI_PM_M0)) { - MHI_ERR("Failed to transition to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_M0), - to_mhi_pm_state_str(cur_state)); - return -EIO; - } - mhi_cntrl->M0++; - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, false); - - /* ring all event rings and CMD ring only if we're in mission mode */ - if (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) { - struct mhi_event *mhi_event = mhi_cntrl->mhi_event; - struct mhi_cmd *mhi_cmd = - &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING]; - - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - - spin_lock_irq(&mhi_event->lock); - mhi_ring_er_db(mhi_event); - spin_unlock_irq(&mhi_event->lock); - } - - /* only ring primary cmd ring */ - spin_lock_irq(&mhi_cmd->lock); - if (mhi_cmd->ring.rp != mhi_cmd->ring.wp) - mhi_ring_cmd_db(mhi_cntrl, mhi_cmd); - spin_unlock_irq(&mhi_cmd->lock); - } - - /* ring channel db registers */ - mhi_chan = mhi_cntrl->mhi_chan; - for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) { - struct mhi_ring *tre_ring = &mhi_chan->tre_ring; - - write_lock_irq(&mhi_chan->lock); - if (mhi_chan->db_cfg.reset_req) - mhi_chan->db_cfg.db_mode = true; - - /* only ring DB if ring is not empty */ - if (tre_ring->base && tre_ring->wp != tre_ring->rp) - mhi_ring_chan_db(mhi_cntrl, mhi_chan); - write_unlock_irq(&mhi_chan->lock); - } - - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - wake_up_all(&mhi_cntrl->state_event); - MHI_VERB("Exited\n"); - - return 0; -} - -void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE state; - - write_lock_irq(&mhi_cntrl->pm_lock); - /* if it fails, means we transition to M3 */ - state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2); - if (state == MHI_PM_M2) { - MHI_VERB("Entered M2 State\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M2); - mhi_cntrl->dev_state = MHI_STATE_M2; - mhi_cntrl->M2++; - - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up_all(&mhi_cntrl->state_event); - - /* transfer pending, exit M2 immediately */ - if (unlikely(atomic_read(&mhi_cntrl->dev_wake))) { - MHI_VERB("Exiting M2 Immediately, count:%d\n", - atomic_read(&mhi_cntrl->dev_wake)); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, true); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - } else { - mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, - MHI_CB_IDLE); - } - } else { - write_unlock_irq(&mhi_cntrl->pm_lock); - } -} - -int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE state; - - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->dev_state = MHI_STATE_M3; - state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (state != MHI_PM_M3) { - MHI_ERR("Failed to transition to state %s from %s\n", - to_mhi_pm_state_str(MHI_PM_M3), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - wake_up_all(&mhi_cntrl->state_event); - mhi_cntrl->M3++; - - MHI_LOG("Entered mhi_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return 0; -} - -static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl) -{ - int i, ret; - struct mhi_event *mhi_event; - - MHI_LOG("Processing Mission Mode Transition\n"); - mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_EE_MISSION_MODE); - - /* force MHI to be in M0 state before continuing */ - ret = __mhi_device_get_sync(mhi_cntrl); - if (ret) - return ret; - - ret = -EIO; - - write_lock_irq(&mhi_cntrl->pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); - - read_lock_bh(&mhi_cntrl->pm_lock); - if (!MHI_IN_MISSION_MODE(mhi_cntrl->ee)) - goto error_mission_mode; - - wake_up_all(&mhi_cntrl->state_event); - - /* add elements to all HW event rings */ - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - goto error_mission_mode; - - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - if (mhi_event->offload_ev || !mhi_event->hw_ring) - continue; - - ring->wp = ring->base + ring->len - ring->el_size; - *ring->ctxt_wp = ring->iommu_base + ring->len - ring->el_size; - /* all ring updates must get updated immediately */ - smp_wmb(); - - spin_lock_irq(&mhi_event->lock); - if (MHI_DB_ACCESS_VALID(mhi_cntrl->pm_state)) - mhi_ring_er_db(mhi_event); - spin_unlock_irq(&mhi_event->lock); - - } - - read_unlock_bh(&mhi_cntrl->pm_lock); - - /* setup support for time sync */ - mhi_init_timesync(mhi_cntrl); - - MHI_LOG("Adding new devices\n"); - - /* add supported devices */ - mhi_create_devices(mhi_cntrl); - - ret = 0; - - read_lock_bh(&mhi_cntrl->pm_lock); - -error_mission_mode: - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - MHI_LOG("Exit with ret:%d\n", ret); - - return ret; -} - -/* handles both sys_err and shutdown transitions */ -static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, - enum MHI_PM_STATE transition_state) -{ - enum MHI_PM_STATE cur_state, prev_state; - struct mhi_event *mhi_event; - struct mhi_cmd_ctxt *cmd_ctxt; - struct mhi_cmd *mhi_cmd; - struct mhi_event_ctxt *er_ctxt; - int ret, i; - - MHI_LOG("Enter with from pm_state:%s MHI_STATE:%s to pm_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(transition_state)); - - /* We must notify MHI control driver so it can clean up first */ - if (transition_state == MHI_PM_SYS_ERR_PROCESS) - mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, - MHI_CB_SYS_ERROR); - - mutex_lock(&mhi_cntrl->pm_mutex); - write_lock_irq(&mhi_cntrl->pm_lock); - prev_state = mhi_cntrl->pm_state; - cur_state = mhi_tryset_pm_state(mhi_cntrl, transition_state); - if (cur_state == transition_state) { - mhi_cntrl->ee = MHI_EE_DISABLE_TRANSITION; - mhi_cntrl->dev_state = MHI_STATE_RESET; - } - write_unlock_irq(&mhi_cntrl->pm_lock); - - /* wake up any threads waiting for state transitions */ - wake_up_all(&mhi_cntrl->state_event); - - /* not handling sys_err, could be middle of shut down */ - if (cur_state != transition_state) { - MHI_LOG("Failed to transition to state:0x%x from:0x%x\n", - transition_state, cur_state); - mutex_unlock(&mhi_cntrl->pm_mutex); - return; - } - - /* trigger MHI RESET so device will not access host ddr */ - if (MHI_REG_ACCESS_VALID(prev_state)) { - u32 in_reset = -1; - unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms); - - MHI_LOG("Trigger device into MHI_RESET\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); - - /* wait for reset to be cleared */ - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_read_reg_field(mhi_cntrl, - mhi_cntrl->regs, MHICTRL, - MHICTRL_RESET_MASK, - MHICTRL_RESET_SHIFT, &in_reset) - || !in_reset, timeout); - if ((!ret || in_reset) && cur_state == MHI_PM_SYS_ERR_PROCESS) { - MHI_CRITICAL("Device failed to exit RESET state\n"); - mutex_unlock(&mhi_cntrl->pm_mutex); - return; - } - - /* Set the numbers of Event Rings supported */ - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICFG, MHICFG_NER_MASK, MHICFG_NER_SHIFT, NUM_MHI_EVT_RINGS); - mhi_write_reg_field(mhi_cntrl, mhi_cntrl->regs, MHICFG, MHICFG_NHWER_MASK, MHICFG_NHWER_SHIFT, NUM_MHI_HW_EVT_RINGS); - - /* - * device cleares INTVEC as part of RESET processing, - * re-program it - */ - mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, mhi_cntrl->msi_irq_base); - } - - MHI_LOG("Waiting for all pending event ring processing to complete\n"); - mhi_event = mhi_cntrl->mhi_event; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) { - if (mhi_event->offload_ev) - continue; - tasklet_kill(&mhi_event->task); - } - - mutex_unlock(&mhi_cntrl->pm_mutex); - - MHI_LOG("Reset all active channels and remove mhi devices\n"); - mhi_cntrl->klog_slient = 1; - device_for_each_child(mhi_cntrl->dev, NULL, mhi_destroy_device); - mhi_cntrl->klog_slient = 0; - - MHI_LOG("Finish resetting channels\n"); - - MHI_LOG("Waiting for all pending threads to complete\n"); - wake_up_all(&mhi_cntrl->state_event); - flush_delayed_work(&mhi_cntrl->ready_worker); - flush_work(&mhi_cntrl->st_worker); - flush_work(&mhi_cntrl->fw_worker); - - mutex_lock(&mhi_cntrl->pm_mutex); - - MHI_ASSERT(atomic_read(&mhi_cntrl->dev_wake), "dev_wake != 0"); - - /* reset the ev rings and cmd rings */ - MHI_LOG("Resetting EV CTXT and CMD CTXT\n"); - mhi_cmd = mhi_cntrl->mhi_cmd; - cmd_ctxt = mhi_cntrl->mhi_ctxt->cmd_ctxt; - for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++, cmd_ctxt++) { - struct mhi_ring *ring = &mhi_cmd->ring; - - ring->rp = ring->base; - ring->wp = ring->base; - cmd_ctxt->rp = cmd_ctxt->rbase; - cmd_ctxt->wp = cmd_ctxt->rbase; - } - - mhi_event = mhi_cntrl->mhi_event; - er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; - for (i = 0; i < mhi_cntrl->total_ev_rings; i++, er_ctxt++, - mhi_event++) { - struct mhi_ring *ring = &mhi_event->ring; - - /* do not touch offload er */ - if (mhi_event->offload_ev) - continue; - - ring->rp = ring->base; - ring->wp = ring->base; - er_ctxt->rp = er_ctxt->rbase; - er_ctxt->wp = er_ctxt->rbase; - } - - /* remove support for time sync */ - mhi_destroy_timesync(mhi_cntrl); - - if (cur_state == MHI_PM_SYS_ERR_PROCESS) { - if (mhi_get_exec_env(mhi_cntrl) == MHI_EE_EDL && mhi_get_mhi_state(mhi_cntrl) == MHI_STATE_RESET) { - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = MHI_EE_EDL; - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_POR); - write_unlock_irq(&mhi_cntrl->pm_lock); - } - else - mhi_ready_state_transition(mhi_cntrl); - } else { - /* move to disable state */ - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_DISABLE); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (unlikely(cur_state != MHI_PM_DISABLE)) - MHI_ERR("Error moving from pm state:%s to state:%s\n", - to_mhi_pm_state_str(cur_state), - to_mhi_pm_state_str(MHI_PM_DISABLE)); - } - - MHI_LOG("Exit with pm_state:%s mhi_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state)); - - mutex_unlock(&mhi_cntrl->pm_mutex); -} - -int mhi_debugfs_trigger_reset(void *data, u64 val) -{ - struct mhi_controller *mhi_cntrl = data; - enum MHI_PM_STATE cur_state; - int ret; - - MHI_LOG("Trigger MHI Reset\n"); - - /* exit lpm first */ - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT); - write_unlock_irq(&mhi_cntrl->pm_lock); - - if (cur_state == MHI_PM_SYS_ERR_DETECT) - schedule_work(&mhi_cntrl->syserr_worker); - - return 0; -} - -/* queue a new work item and scheduler work */ -int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, - enum MHI_ST_TRANSITION state) -{ - struct state_transition *item = kmalloc(sizeof(*item), GFP_ATOMIC); - unsigned long flags; - - if (!item) - return -ENOMEM; - - item->state = state; - spin_lock_irqsave(&mhi_cntrl->transition_lock, flags); - list_add_tail(&item->node, &mhi_cntrl->transition_list); - spin_unlock_irqrestore(&mhi_cntrl->transition_lock, flags); - - schedule_work(&mhi_cntrl->st_worker); - - return 0; -} - -void mhi_pm_sys_err_worker(struct work_struct *work) -{ - struct mhi_controller *mhi_cntrl = container_of(work, - struct mhi_controller, - syserr_worker); - - MHI_LOG("Enter with pm_state:%s MHI_STATE:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state)); - - mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS); -} - -void mhi_pm_ready_worker(struct work_struct *work) -{ - struct mhi_controller *mhi_cntrl = container_of(work, - struct mhi_controller, - ready_worker.work); - enum mhi_ee ee = MHI_EE_MAX; - - if (mhi_cntrl->dev_state != MHI_STATE_RESET) - return; - - write_lock_irq(&mhi_cntrl->pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); - - if (ee == MHI_EE_PTHRU) - schedule_delayed_work(&mhi_cntrl->ready_worker, msecs_to_jiffies(10)); - else if (ee == MHI_EE_AMSS || ee == MHI_EE_SBL) - mhi_queue_state_transition(mhi_cntrl, MHI_ST_TRANSITION_READY); - else if (ee == MHI_EE_EDL) - mhi_queue_state_transition(mhi_cntrl, MHI_ST_TRANSITION_PBL); -} - -void mhi_pm_st_worker(struct work_struct *work) -{ - struct state_transition *itr, *tmp; - LIST_HEAD(head); - struct mhi_controller *mhi_cntrl = container_of(work, - struct mhi_controller, - st_worker); - spin_lock_irq(&mhi_cntrl->transition_lock); - list_splice_tail_init(&mhi_cntrl->transition_list, &head); - spin_unlock_irq(&mhi_cntrl->transition_lock); - - list_for_each_entry_safe(itr, tmp, &head, node) { - list_del(&itr->node); - MHI_LOG("Transition to state:%s\n", - TO_MHI_STATE_TRANS_STR(itr->state)); - - if (mhi_cntrl->ee != mhi_get_exec_env(mhi_cntrl)) { - MHI_LOG("%s -> %s\n", TO_MHI_EXEC_STR(mhi_cntrl->ee), - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl))); - } - - switch (itr->state) { - case MHI_ST_TRANSITION_PBL: - write_lock_irq(&mhi_cntrl->pm_lock); - if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) - mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); - if (MHI_IN_PBL(mhi_cntrl->ee)) - wake_up_all(&mhi_cntrl->state_event); - break; - case MHI_ST_TRANSITION_SBL: - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = MHI_EE_SBL; - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up_all(&mhi_cntrl->state_event); - mhi_create_devices(mhi_cntrl); - break; - case MHI_ST_TRANSITION_MISSION_MODE: - mhi_pm_mission_mode_transition(mhi_cntrl); - break; - case MHI_ST_TRANSITION_READY: - mhi_ready_state_transition(mhi_cntrl); - break; - case MHI_ST_TRANSITION_FP: - write_lock_irq(&mhi_cntrl->pm_lock); - mhi_cntrl->ee = MHI_EE_FP; - write_unlock_irq(&mhi_cntrl->pm_lock); - wake_up(&mhi_cntrl->state_event); - mhi_create_devices(mhi_cntrl); - break; - default: - break; - } - kfree(itr); - } -} - -int mhi_async_power_up(struct mhi_controller *mhi_cntrl) -{ - int ret; - u32 val, regVal; - enum mhi_ee current_ee; - enum MHI_ST_TRANSITION next_state; - - MHI_LOG("Requested to power on\n"); - -#if 0 - if (mhi_cntrl->msi_allocated < mhi_cntrl->total_ev_rings) - return -EINVAL; -#endif - - if (mhi_get_mhi_state(mhi_cntrl) >= MHI_STATE_M0) { - MHI_LOG("mhi_state = %s\n", mhi_state_str[mhi_get_mhi_state(mhi_cntrl)]); - MHI_LOG("Trigger device into MHI_RESET\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET); - msleep(50); - MHI_LOG("mhi_state = %s\n", mhi_state_str[mhi_get_mhi_state(mhi_cntrl)]); - } - -#if 1 //GLUE.SDX55_LE.1.0-00098-NOOP_TEST-1\common\hostdrivers\win\MhiHost MhiInitNewDev() - /* Check device Channels support */ - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, MHICFG, ®Val); -#if 0 - val = MHI_READ_REG_FIELD(regVal, MHICFG, NCH); - MHI_LOG("Device CHs: %d\n", val); - val = MHI_READ_REG_FIELD(regVal, MHICFG, NHWCH); - MHI_LOG("Device HW CHs: %d\n", val); - val = MHI_READ_REG_FIELD(regVal, MHICFG, NER); - MHI_LOG("Device ERs: %d\n", val); - val = MHI_READ_REG_FIELD(regVal, MHICFG, NHWER); - MHI_LOG("Device HW ERs: %d\n", val); -#endif - /* Set the numbers of Event Rings supported */ - MHI_WRITE_REG_FIELD(regVal, MHICFG, NER, NUM_MHI_EVT_RINGS); - MHI_WRITE_REG_FIELD(regVal, MHICFG, NHWER, NUM_MHI_HW_EVT_RINGS); - mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHICFG, regVal); -#endif - - /* set to default wake if not set */ - if (!mhi_cntrl->wake_get || !mhi_cntrl->wake_put) { - mhi_cntrl->wake_get = mhi_assert_dev_wake; - mhi_cntrl->wake_put = mhi_deassert_dev_wake; - } - - mutex_lock(&mhi_cntrl->pm_mutex); - mhi_cntrl->pm_state = MHI_PM_DISABLE; - mhi_cntrl->dev_state = MHI_STATE_RESET; - - if (!mhi_cntrl->pre_init) { - /* setup device context */ - ret = mhi_init_dev_ctxt(mhi_cntrl); - if (ret) { - MHI_ERR("Error setting dev_context\n"); - goto error_dev_ctxt; - } - - ret = mhi_init_irq_setup(mhi_cntrl); - if (ret) { - MHI_ERR("Error setting up irq\n"); - goto error_setup_irq; - } - } - - /* setup bhi offset & intvec */ - write_lock_irq(&mhi_cntrl->pm_lock); - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIOFF, &val); - if (ret) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error getting bhi offset\n"); - goto error_bhi_offset; - } - - mhi_cntrl->bhi = mhi_cntrl->regs + val; - - /* setup bhie offset */ - if (mhi_cntrl->fbc_download || true) { - ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, &val); - if (ret) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error getting bhie offset\n"); - goto error_bhi_offset; - } - - mhi_cntrl->bhie = mhi_cntrl->regs + val; - } - - mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, mhi_cntrl->msi_irq_base); - mhi_cntrl->pm_state = MHI_PM_POR; - mhi_cntrl->ee = MHI_EE_MAX; - current_ee = mhi_get_exec_env(mhi_cntrl); - write_unlock_irq(&mhi_cntrl->pm_lock); - - MHI_LOG("dev_state:%s ee:%s\n", - TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl)), - TO_MHI_EXEC_STR(mhi_get_exec_env(mhi_cntrl))); - - /* confirm device is in valid exec env */ - if (!MHI_IN_PBL(current_ee) && current_ee != MHI_EE_AMSS) { - //MHI_ERR("Not a valid ee for power on\n"); - //ret = -EIO; - //goto error_bhi_offset; - } - - /* transition to next state */ - next_state = MHI_IN_PBL(current_ee) ? - MHI_ST_TRANSITION_PBL : MHI_ST_TRANSITION_READY; - - //if (next_state == MHI_ST_TRANSITION_PBL) - // schedule_work(&mhi_cntrl->fw_worker); - - if (next_state == MHI_ST_TRANSITION_PBL) - schedule_delayed_work(&mhi_cntrl->ready_worker, msecs_to_jiffies(10)); - else - mhi_queue_state_transition(mhi_cntrl, next_state); - - mhi_init_debugfs(mhi_cntrl); - - mutex_unlock(&mhi_cntrl->pm_mutex); - - MHI_LOG("Power on setup success\n"); - - return 0; - -error_bhi_offset: - if (!mhi_cntrl->pre_init) - mhi_deinit_free_irq(mhi_cntrl); - -error_setup_irq: - if (!mhi_cntrl->pre_init) - mhi_deinit_dev_ctxt(mhi_cntrl); - -error_dev_ctxt: - mutex_unlock(&mhi_cntrl->pm_mutex); - - return ret; -} -EXPORT_SYMBOL(mhi_async_power_up); - -void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful) -{ - enum MHI_PM_STATE cur_state; - - /* if it's not graceful shutdown, force MHI to a linkdown state */ - if (!graceful) { - mutex_lock(&mhi_cntrl->pm_mutex); - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, - MHI_PM_LD_ERR_FATAL_DETECT); - write_unlock_irq(&mhi_cntrl->pm_lock); - mutex_unlock(&mhi_cntrl->pm_mutex); - if (cur_state != MHI_PM_LD_ERR_FATAL_DETECT) - MHI_ERR("Failed to move to state:%s from:%s\n", - to_mhi_pm_state_str(MHI_PM_LD_ERR_FATAL_DETECT), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - } - mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SHUTDOWN_PROCESS); - - mhi_deinit_debugfs(mhi_cntrl); - - if (!mhi_cntrl->pre_init) { - /* free all allocated resources */ - if (mhi_cntrl->fbc_image) { - mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image); - mhi_cntrl->fbc_image = NULL; - } - mhi_deinit_free_irq(mhi_cntrl); - mhi_deinit_dev_ctxt(mhi_cntrl); - } -} -EXPORT_SYMBOL(mhi_power_down); - -int mhi_sync_power_up(struct mhi_controller *mhi_cntrl) -{ - int ret = mhi_async_power_up(mhi_cntrl); - - if (ret) - return ret; - - wait_event_timeout(mhi_cntrl->state_event, - MHI_IN_MISSION_MODE(mhi_cntrl->ee) || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - return (MHI_IN_MISSION_MODE(mhi_cntrl->ee)) ? 0 : -EIO; -} -EXPORT_SYMBOL(mhi_sync_power_up); - -int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) -{ - int ret; - enum MHI_PM_STATE new_state; - struct mhi_chan *itr, *tmp; - - if (mhi_cntrl->pm_state == MHI_PM_DISABLE) - return -EINVAL; - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - /* do a quick check to see if any pending data, then exit */ - if (atomic_read(&mhi_cntrl->dev_wake)) { - MHI_VERB("Busy, aborting M3\n"); - return -EBUSY; - } - - /* exit MHI out of M2 state */ - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - mhi_cntrl->dev_state == MHI_STATE_M1 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR( - "Did not enter M0||M1 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - ret = -EIO; - goto error_m0_entry; - } - - write_lock_irq(&mhi_cntrl->pm_lock); - - /* we're asserting wake so count would be @ least 1 */ - if (atomic_read(&mhi_cntrl->dev_wake) > 1) { - MHI_VERB("Busy, aborting M3\n"); - write_unlock_irq(&mhi_cntrl->pm_lock); - ret = -EBUSY; - goto error_m0_entry; - } - - /* anytime after this, we will resume thru runtime pm framework */ - MHI_LOG("Allowing M3 transition\n"); - new_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3_ENTER); - if (new_state != MHI_PM_M3_ENTER) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error setting to pm_state:%s from pm_state:%s\n", - to_mhi_pm_state_str(MHI_PM_M3_ENTER), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - ret = -EIO; - goto error_m0_entry; - } - - /* set dev to M3 and wait for completion */ - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M3); - mhi_cntrl->wake_put(mhi_cntrl, false); - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_LOG("Wait for M3 completion\n"); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M3 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M3 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - /* notify any clients we enter lpm */ - list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { - mutex_lock(&itr->mutex); - if (itr->mhi_dev) - mhi_notify(itr->mhi_dev, MHI_CB_LPM_ENTER); - mutex_unlock(&itr->mutex); - } - - return 0; - -error_m0_entry: - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - return ret; -} -EXPORT_SYMBOL(mhi_pm_suspend); - -int mhi_pm_resume(struct mhi_controller *mhi_cntrl) -{ - enum MHI_PM_STATE cur_state; - int ret; - struct mhi_chan *itr, *tmp; - - MHI_LOG("Entered with pm_state:%s dev_state:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_STATE_STR(mhi_cntrl->dev_state)); - - if (mhi_cntrl->pm_state == MHI_PM_DISABLE) - return 0; - - if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) - return -EIO; - - MHI_ASSERT(mhi_cntrl->pm_state != MHI_PM_M3, "mhi_pm_state != M3"); - - /* notify any clients we enter lpm */ - list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { - mutex_lock(&itr->mutex); - if (itr->mhi_dev) - mhi_notify(itr->mhi_dev, MHI_CB_LPM_EXIT); - mutex_unlock(&itr->mutex); - } - - write_lock_irq(&mhi_cntrl->pm_lock); - cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3_EXIT); - if (cur_state != MHI_PM_M3_EXIT) { - write_unlock_irq(&mhi_cntrl->pm_lock); - MHI_ERR("Error setting to pm_state:%s from pm_state:%s\n", - to_mhi_pm_state_str(MHI_PM_M3_EXIT), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - return -EIO; - } - - /* set dev to M0 and wait for completion */ - mhi_cntrl->wake_get(mhi_cntrl, true); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M0); - write_unlock_irq(&mhi_cntrl->pm_lock); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->dev_state == MHI_STATE_M0 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - - /* - * It's possible device already in error state and we didn't - * process it due to low power mode, force a check - */ - mhi_intvec_threaded_handlr(0, mhi_cntrl); - return -EIO; - } - - return 0; -} - -int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) -{ - int ret; - - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, true); - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl, mhi_cntrl->priv_data); - mhi_cntrl->runtime_put(mhi_cntrl, mhi_cntrl->priv_data); - } - read_unlock_bh(&mhi_cntrl->pm_lock); - - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->pm_state == MHI_PM_M0 || - MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - - if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { - MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", - TO_MHI_STATE_STR(mhi_cntrl->dev_state), - to_mhi_pm_state_str(mhi_cntrl->pm_state)); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); - return -EIO; - } - - return 0; -} - -void mhi_device_get(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - atomic_inc(&mhi_dev->dev_wake); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, true); - read_unlock_bh(&mhi_cntrl->pm_lock); -} -EXPORT_SYMBOL(mhi_device_get); - -int mhi_device_get_sync(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - int ret; - - ret = __mhi_device_get_sync(mhi_cntrl); - if (!ret) - atomic_inc(&mhi_dev->dev_wake); - - return ret; -} -EXPORT_SYMBOL(mhi_device_get_sync); - -void mhi_device_put(struct mhi_device *mhi_dev) -{ - struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - - atomic_dec(&mhi_dev->dev_wake); - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); -} -EXPORT_SYMBOL(mhi_device_put); - -int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) -{ - int ret; - - MHI_LOG("Enter with pm_state:%s ee:%s\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee)); - - MHI_LOG("Triggering SYS_ERR to force rddm state\n"); - mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); - - /* wait for rddm event */ - MHI_LOG("Waiting for device to enter RDDM state\n"); - ret = wait_event_timeout(mhi_cntrl->state_event, - mhi_cntrl->ee == MHI_EE_RDDM, - msecs_to_jiffies(mhi_cntrl->timeout_ms)); - ret = ret ? 0 : -EIO; - - MHI_LOG("Exiting with pm_state:%s ee:%s ret:%d\n", - to_mhi_pm_state_str(mhi_cntrl->pm_state), - TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); - - return ret; -} -EXPORT_SYMBOL(mhi_force_rddm_mode); diff --git a/quectel_MHI/src/core/mhi_sdx20.h b/quectel_MHI/src/core/mhi_sdx20.h deleted file mode 100644 index 2bc5dc7..0000000 --- a/quectel_MHI/src/core/mhi_sdx20.h +++ /dev/null @@ -1,362 +0,0 @@ -#ifndef __SDX20_MHI_H -#define __SDX20_MHI_H - -#include - -/* MHI control data structures alloted by the host, including - * channel context array, event context array, command context and rings */ - -/* Channel context state */ -enum mhi_dev_ch_ctx_state { - MHI_DEV_CH_STATE_DISABLED, - MHI_DEV_CH_STATE_ENABLED, - MHI_DEV_CH_STATE_RUNNING, - MHI_DEV_CH_STATE_SUSPENDED, - MHI_DEV_CH_STATE_STOP, - MHI_DEV_CH_STATE_ERROR, - MHI_DEV_CH_STATE_RESERVED, - MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF -}; - -/* Channel type */ -enum mhi_dev_ch_ctx_type { - MHI_DEV_CH_TYPE_NONE, - MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL, - MHI_DEV_CH_TYPE_INBOUND_CHANNEL, - MHI_DEV_CH_RESERVED -}; - -/* Channel context type */ -struct mhi_dev_ch_ctx { - enum mhi_dev_ch_ctx_state ch_state; - enum mhi_dev_ch_ctx_type ch_type; - uint32_t err_indx; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -enum mhi_dev_ring_element_type_id { - MHI_DEV_RING_EL_INVALID = 0, - MHI_DEV_RING_EL_NOOP = 1, - MHI_DEV_RING_EL_TRANSFER = 2, - MHI_DEV_RING_EL_RESET = 16, - MHI_DEV_RING_EL_STOP = 17, - MHI_DEV_RING_EL_START = 18, - MHI_DEV_RING_EL_MHI_STATE_CHG = 32, - MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33, - MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34, - MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64, - MHI_DEV_RING_EL_UNDEF -}; - -enum mhi_dev_ring_state { - RING_STATE_UINT = 0, - RING_STATE_IDLE, - RING_STATE_PENDING, -}; - -enum mhi_dev_ring_type { - RING_TYPE_CMD = 0, - RING_TYPE_ER, - RING_TYPE_CH, - RING_TYPE_INVAL -}; - -/* Event context interrupt moderation */ -enum mhi_dev_evt_ctx_int_mod_timer { - MHI_DEV_EVT_INT_MODERATION_DISABLED -}; - -/* Event ring type */ -enum mhi_dev_evt_ctx_event_ring_type { - MHI_DEV_EVT_TYPE_DEFAULT, - MHI_DEV_EVT_TYPE_VALID, - MHI_DEV_EVT_RESERVED -}; - -/* Event ring context type */ -struct mhi_dev_ev_ctx { - uint32_t res1:16; - enum mhi_dev_evt_ctx_int_mod_timer intmodt:16; - enum mhi_dev_evt_ctx_event_ring_type ertype; - uint32_t msivec; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Command context */ -struct mhi_dev_cmd_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* generic context */ -struct mhi_dev_gen_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Transfer ring element */ -struct mhi_dev_transfer_ring_element { - uint64_t data_buf_ptr; - uint32_t len:16; - uint32_t res1:16; - uint32_t chain:1; - uint32_t res2:7; - uint32_t ieob:1; - uint32_t ieot:1; - uint32_t bei:1; - uint32_t res3:5; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res4:8; -} __packed; - -/* Command ring element */ -/* Command ring No op command */ -struct mhi_dev_cmd_ring_op { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring reset channel command */ -struct mhi_dev_cmd_ring_reset_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring stop channel command */ -struct mhi_dev_cmd_ring_stop_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring start channel command */ -struct mhi_dev_cmd_ring_start_channel_cmd { - uint64_t res1; - uint32_t seqnum; - uint32_t reliable:1; - uint32_t res2:15; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -enum mhi_dev_cmd_completion_code { - MHI_CMD_COMPL_CODE_INVALID = 0, - MHI_CMD_COMPL_CODE_SUCCESS = 1, - MHI_CMD_COMPL_CODE_EOT = 2, - MHI_CMD_COMPL_CODE_OVERFLOW = 3, - MHI_CMD_COMPL_CODE_EOB = 4, - MHI_CMD_COMPL_CODE_UNDEFINED = 16, - MHI_CMD_COMPL_CODE_RING_EL = 17, - MHI_CMD_COMPL_CODE_RES -}; - -/* Event ring elements */ -/* Transfer completion event */ -struct mhi_dev_event_ring_transfer_completion { - uint64_t ptr; - uint32_t len:16; - uint32_t res1:8; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command completion event */ -struct mhi_dev_event_ring_cmd_completion { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_state { - MHI_DEV_RESET_STATE = 0, - MHI_DEV_READY_STATE, - MHI_DEV_M0_STATE, - MHI_DEV_M1_STATE, - MHI_DEV_M2_STATE, - MHI_DEV_M3_STATE, - MHI_DEV_MAX_STATE, - MHI_DEV_SYSERR_STATE = 0xff -}; - -/* MHI state change event */ -struct mhi_dev_event_ring_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_state mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_execenv { - MHI_DEV_SBL_EE = 1, - MHI_DEV_AMSS_EE = 2, - MHI_DEV_UNRESERVED -}; - -/* EE state change event */ -struct mhi_dev_event_ring_ee_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_execenv execenv:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -/* Generic cmd to parse common details like type and channel id */ -struct mhi_dev_ring_generic { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_state mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -struct mhi_config { - uint32_t mhi_reg_len; - uint32_t version; - uint32_t event_rings; - uint32_t channels; - uint32_t chdb_offset; - uint32_t erdb_offset; -}; - -#define NUM_CHANNELS 128 -#define HW_CHANNEL_BASE 100 -#define HW_CHANNEL_END 107 -#define MHI_ENV_VALUE 2 -#define MHI_MASK_ROWS_CH_EV_DB 4 -#define TRB_MAX_DATA_SIZE 8192 -#define MHI_CTRL_STATE 25 -#define IPA_DMA_SYNC 1 -#define IPA_DMA_ASYNC 0 - -/*maximum trasnfer completion events buffer*/ -#define MAX_TR_EVENTS 50 -/*maximum event requests */ -#define MHI_MAX_EVT_REQ 50 - -/* Possible ring element types */ -union mhi_dev_ring_element_type { - struct mhi_dev_cmd_ring_op cmd_no_op; - struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset; - struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop; - struct mhi_dev_cmd_ring_start_channel_cmd cmd_start; - struct mhi_dev_transfer_ring_element cmd_transfer; - struct mhi_dev_event_ring_transfer_completion evt_tr_comp; - struct mhi_dev_event_ring_cmd_completion evt_cmd_comp; - struct mhi_dev_event_ring_state_change evt_state_change; - struct mhi_dev_event_ring_ee_state_change evt_ee_state; - struct mhi_dev_ring_generic generic; -}; - -/* Transfer ring element type */ -union mhi_dev_ring_ctx { - struct mhi_dev_cmd_ctx cmd; - struct mhi_dev_ev_ctx ev; - struct mhi_dev_ch_ctx ch; - struct mhi_dev_gen_ctx generic; -}; - -/* MHI host Control and data address region */ -struct mhi_host_addr { - uint32_t ctrl_base_lsb; - uint32_t ctrl_base_msb; - uint32_t ctrl_limit_lsb; - uint32_t ctrl_limit_msb; - uint32_t data_base_lsb; - uint32_t data_base_msb; - uint32_t data_limit_lsb; - uint32_t data_limit_msb; -}; - -/* MHI physical and virtual address region */ -struct mhi_meminfo { - struct device *dev; - uintptr_t pa_aligned; - uintptr_t pa_unaligned; - uintptr_t va_aligned; - uintptr_t va_unaligned; - uintptr_t size; -}; - -struct mhi_addr { - uint64_t host_pa; - uintptr_t device_pa; - uintptr_t device_va; - size_t size; - dma_addr_t phy_addr; - void *virt_addr; - bool use_ipa_dma; -}; - -struct mhi_interrupt_state { - uint32_t mask; - uint32_t status; -}; - -enum mhi_dev_channel_state { - MHI_DEV_CH_UNINT, - MHI_DEV_CH_STARTED, - MHI_DEV_CH_PENDING_START, - MHI_DEV_CH_PENDING_STOP, - MHI_DEV_CH_STOPPED, - MHI_DEV_CH_CLOSED, -}; - -enum mhi_dev_ch_operation { - MHI_DEV_OPEN_CH, - MHI_DEV_CLOSE_CH, - MHI_DEV_READ_CH, - MHI_DEV_READ_WR, - MHI_DEV_POLL, -}; - -enum mhi_ctrl_info { - MHI_STATE_CONFIGURED = 0, - MHI_STATE_CONNECTED = 1, - MHI_STATE_DISCONNECTED = 2, - MHI_STATE_INVAL, -}; - -enum mhi_dev_tr_compl_evt_type { - SEND_EVENT_BUFFER, - SEND_EVENT_RD_OFFSET, -}; - -enum mhi_dev_transfer_type { - MHI_DEV_DMA_SYNC, - MHI_DEV_DMA_ASYNC, -}; -#endif /* _SDX20_MHI_H_ */ diff --git a/quectel_MHI/src/core/sdx20_mhi.h b/quectel_MHI/src/core/sdx20_mhi.h deleted file mode 100644 index 29c4a3a..0000000 --- a/quectel_MHI/src/core/sdx20_mhi.h +++ /dev/null @@ -1,426 +0,0 @@ -#ifndef __SDX20_MHI_H -#define __SDX20_MHI_H - -#include - -/* MHI control data structures alloted by the host, including - * channel context array, event context array, command context and rings */ - -/* Channel context state */ -enum mhi_dev_ch_ctx_state { - MHI_DEV_CH_STATE_DISABLED, - MHI_DEV_CH_STATE_ENABLED, - MHI_DEV_CH_STATE_RUNNING, - MHI_DEV_CH_STATE_SUSPENDED, - MHI_DEV_CH_STATE_STOP, - MHI_DEV_CH_STATE_ERROR, - MHI_DEV_CH_STATE_RESERVED, - MHI_DEV_CH_STATE_32BIT = 0x7FFFFFFF -}; - -/* Channel type */ -enum mhi_dev_ch_ctx_type { - MHI_DEV_CH_TYPE_NONE, - MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL, - MHI_DEV_CH_TYPE_INBOUND_CHANNEL, - MHI_DEV_CH_RESERVED -}; - -/* Channel context type */ -struct mhi_dev_ch_ctx { - enum mhi_dev_ch_ctx_state ch_state; - enum mhi_dev_ch_ctx_type ch_type; - uint32_t err_indx; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -enum mhi_dev_ring_element_type_id { - MHI_DEV_RING_EL_INVALID = 0, - MHI_DEV_RING_EL_NOOP = 1, - MHI_DEV_RING_EL_TRANSFER = 2, - MHI_DEV_RING_EL_RESET = 16, - MHI_DEV_RING_EL_STOP = 17, - MHI_DEV_RING_EL_START = 18, - MHI_DEV_RING_EL_MHI_STATE_CHG = 32, - MHI_DEV_RING_EL_CMD_COMPLETION_EVT = 33, - MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT = 34, - MHI_DEV_RING_EL_EE_STATE_CHANGE_NOTIFY = 64, - MHI_DEV_RING_EL_UNDEF -}; - -enum mhi_dev_ring_state { - RING_STATE_UINT = 0, - RING_STATE_IDLE, - RING_STATE_PENDING, -}; - -enum mhi_dev_ring_type { - RING_TYPE_CMD = 0, - RING_TYPE_ER, - RING_TYPE_CH, - RING_TYPE_INVAL -}; - -/* Event context interrupt moderation */ -enum mhi_dev_evt_ctx_int_mod_timer { - MHI_DEV_EVT_INT_MODERATION_DISABLED -}; - -/* Event ring type */ -enum mhi_dev_evt_ctx_event_ring_type { - MHI_DEV_EVT_TYPE_DEFAULT, - MHI_DEV_EVT_TYPE_VALID, - MHI_DEV_EVT_RESERVED -}; - -/* Event ring context type */ -struct mhi_dev_ev_ctx { - uint32_t res1:16; - enum mhi_dev_evt_ctx_int_mod_timer intmodt:16; - enum mhi_dev_evt_ctx_event_ring_type ertype; - uint32_t msivec; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Command context */ -struct mhi_dev_cmd_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* generic context */ -struct mhi_dev_gen_ctx { - uint32_t res1; - uint32_t res2; - uint32_t res3; - uint64_t rbase; - uint64_t rlen; - uint64_t rp; - uint64_t wp; -} __packed; - -/* Transfer ring element */ -struct mhi_dev_transfer_ring_element { - uint64_t data_buf_ptr; - uint32_t len:16; - uint32_t res1:16; - uint32_t chain:1; - uint32_t res2:7; - uint32_t ieob:1; - uint32_t ieot:1; - uint32_t bei:1; - uint32_t res3:5; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res4:8; -} __packed; - -/* Command ring element */ -/* Command ring No op command */ -struct mhi_dev_cmd_ring_op { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring reset channel command */ -struct mhi_dev_cmd_ring_reset_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring stop channel command */ -struct mhi_dev_cmd_ring_stop_channel_cmd { - uint64_t res1; - uint32_t res2; - uint32_t res3:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command ring start channel command */ -struct mhi_dev_cmd_ring_start_channel_cmd { - uint64_t res1; - uint32_t seqnum; - uint32_t reliable:1; - uint32_t res2:15; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -enum mhi_dev_cmd_completion_code { - MHI_CMD_COMPL_CODE_INVALID = 0, - MHI_CMD_COMPL_CODE_SUCCESS = 1, - MHI_CMD_COMPL_CODE_EOT = 2, - MHI_CMD_COMPL_CODE_OVERFLOW = 3, - MHI_CMD_COMPL_CODE_EOB = 4, - MHI_CMD_COMPL_CODE_UNDEFINED = 16, - MHI_CMD_COMPL_CODE_RING_EL = 17, - MHI_CMD_COMPL_CODE_RES -}; - -/* Event ring elements */ -/* Transfer completion event */ -struct mhi_dev_event_ring_transfer_completion { - uint64_t ptr; - uint32_t len:16; - uint32_t res1:8; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -/* Command completion event */ -struct mhi_dev_event_ring_cmd_completion { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_cmd_completion_code code:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_state { - MHI_DEV_RESET_STATE = 0, - MHI_DEV_READY_STATE, - MHI_DEV_M0_STATE, - MHI_DEV_M1_STATE, - MHI_DEV_M2_STATE, - MHI_DEV_M3_STATE, - MHI_DEV_MAX_STATE, - MHI_DEV_SYSERR_STATE = 0xff -}; - -/* MHI state change event */ -struct mhi_dev_event_ring_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_state mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -enum mhi_dev_execenv { - MHI_DEV_SBL_EE = 1, - MHI_DEV_AMSS_EE = 2, - MHI_DEV_UNRESERVED -}; - -/* EE state change event */ -struct mhi_dev_event_ring_ee_state_change { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_execenv execenv:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t res3:8; -} __packed; - -/* Generic cmd to parse common details like type and channel id */ -struct mhi_dev_ring_generic { - uint64_t ptr; - uint32_t res1:24; - enum mhi_dev_state mhistate:8; - uint32_t res2:16; - enum mhi_dev_ring_element_type_id type:8; - uint32_t chid:8; -} __packed; - -struct mhi_config { - uint32_t mhi_reg_len; - uint32_t version; - uint32_t event_rings; - uint32_t channels; - uint32_t chdb_offset; - uint32_t erdb_offset; -}; - -#define NUM_CHANNELS 128 -#define HW_CHANNEL_BASE 100 -#define HW_CHANNEL_END 107 -#define MHI_ENV_VALUE 2 -#define MHI_MASK_ROWS_CH_EV_DB 4 -#define TRB_MAX_DATA_SIZE 8192 -#define MHI_CTRL_STATE 25 -#define IPA_DMA_SYNC 1 -#define IPA_DMA_ASYNC 0 - -/*maximum trasnfer completion events buffer*/ -#define MAX_TR_EVENTS 50 -/*maximum event requests */ -#define MHI_MAX_EVT_REQ 50 - -/* Possible ring element types */ -union mhi_dev_ring_element_type { - struct mhi_dev_cmd_ring_op cmd_no_op; - struct mhi_dev_cmd_ring_reset_channel_cmd cmd_reset; - struct mhi_dev_cmd_ring_stop_channel_cmd cmd_stop; - struct mhi_dev_cmd_ring_start_channel_cmd cmd_start; - struct mhi_dev_transfer_ring_element tre; - struct mhi_dev_event_ring_transfer_completion evt_tr_comp; - struct mhi_dev_event_ring_cmd_completion evt_cmd_comp; - struct mhi_dev_event_ring_state_change evt_state_change; - struct mhi_dev_event_ring_ee_state_change evt_ee_state; - struct mhi_dev_ring_generic generic; -}; - -/* Transfer ring element type */ -union mhi_dev_ring_ctx { - struct mhi_dev_cmd_ctx cmd; - struct mhi_dev_ev_ctx ev; - struct mhi_dev_ch_ctx ch; - struct mhi_dev_gen_ctx generic; -}; - -/* MHI host Control and data address region */ -struct mhi_host_addr { - uint32_t ctrl_base_lsb; - uint32_t ctrl_base_msb; - uint32_t ctrl_limit_lsb; - uint32_t ctrl_limit_msb; - uint32_t data_base_lsb; - uint32_t data_base_msb; - uint32_t data_limit_lsb; - uint32_t data_limit_msb; -}; - -/* MHI physical and virtual address region */ -struct mhi_meminfo { - struct device *dev; - uintptr_t pa_aligned; - uintptr_t pa_unaligned; - uintptr_t va_aligned; - uintptr_t va_unaligned; - uintptr_t size; -}; - -struct mhi_addr { - uint64_t host_pa; - uintptr_t device_pa; - uintptr_t device_va; - size_t size; - dma_addr_t phy_addr; - void *virt_addr; - bool use_ipa_dma; -}; - -struct mhi_interrupt_state { - uint32_t mask; - uint32_t status; -}; - -enum mhi_dev_channel_state { - MHI_DEV_CH_UNINT, - MHI_DEV_CH_STARTED, - MHI_DEV_CH_PENDING_START, - MHI_DEV_CH_PENDING_STOP, - MHI_DEV_CH_STOPPED, - MHI_DEV_CH_CLOSED, -}; - -enum mhi_dev_ch_operation { - MHI_DEV_OPEN_CH, - MHI_DEV_CLOSE_CH, - MHI_DEV_READ_CH, - MHI_DEV_READ_WR, - MHI_DEV_POLL, -}; - -enum mhi_ctrl_info { - MHI_STATE_CONFIGURED = 0, - MHI_STATE_CONNECTED = 1, - MHI_STATE_DISCONNECTED = 2, - MHI_STATE_INVAL, -}; - -enum mhi_dev_tr_compl_evt_type { - SEND_EVENT_BUFFER, - SEND_EVENT_RD_OFFSET, -}; - -enum mhi_dev_transfer_type { - MHI_DEV_DMA_SYNC, - MHI_DEV_DMA_ASYNC, -}; - -#if 0 -/* SW channel client list */ -enum mhi_client_channel { - MHI_CLIENT_LOOPBACK_OUT = 0, - MHI_CLIENT_LOOPBACK_IN = 1, - MHI_CLIENT_SAHARA_OUT = 2, - MHI_CLIENT_SAHARA_IN = 3, - MHI_CLIENT_DIAG_OUT = 4, - MHI_CLIENT_DIAG_IN = 5, - MHI_CLIENT_SSR_OUT = 6, - MHI_CLIENT_SSR_IN = 7, - MHI_CLIENT_QDSS_OUT = 8, - MHI_CLIENT_QDSS_IN = 9, - MHI_CLIENT_EFS_OUT = 10, - MHI_CLIENT_EFS_IN = 11, - MHI_CLIENT_MBIM_OUT = 12, - MHI_CLIENT_MBIM_IN = 13, - MHI_CLIENT_QMI_OUT = 14, - MHI_CLIENT_QMI_IN = 15, - MHI_CLIENT_IP_CTRL_0_OUT = 16, - MHI_CLIENT_IP_CTRL_0_IN = 17, - MHI_CLIENT_IP_CTRL_1_OUT = 18, - MHI_CLIENT_IP_CTRL_1_IN = 19, - MHI_CLIENT_DCI_OUT = 20, - MHI_CLIENT_DCI_IN = 21, - MHI_CLIENT_IP_CTRL_3_OUT = 22, - MHI_CLIENT_IP_CTRL_3_IN = 23, - MHI_CLIENT_IP_CTRL_4_OUT = 24, - MHI_CLIENT_IP_CTRL_4_IN = 25, - MHI_CLIENT_IP_CTRL_5_OUT = 26, - MHI_CLIENT_IP_CTRL_5_IN = 27, - MHI_CLIENT_IP_CTRL_6_OUT = 28, - MHI_CLIENT_IP_CTRL_6_IN = 29, - MHI_CLIENT_IP_CTRL_7_OUT = 30, - MHI_CLIENT_IP_CTRL_7_IN = 31, - MHI_CLIENT_DUN_OUT = 32, - MHI_CLIENT_DUN_IN = 33, - MHI_CLIENT_IP_SW_0_OUT = 34, - MHI_CLIENT_IP_SW_0_IN = 35, - MHI_CLIENT_IP_SW_1_OUT = 36, - MHI_CLIENT_IP_SW_1_IN = 37, - MHI_CLIENT_IP_SW_2_OUT = 38, - MHI_CLIENT_IP_SW_2_IN = 39, - MHI_CLIENT_IP_SW_3_OUT = 40, - MHI_CLIENT_IP_SW_3_IN = 41, - MHI_CLIENT_CSVT_OUT = 42, - MHI_CLIENT_CSVT_IN = 43, - MHI_CLIENT_SMCT_OUT = 44, - MHI_CLIENT_SMCT_IN = 45, - MHI_CLIENT_IP_SW_4_OUT = 46, - MHI_CLIENT_IP_SW_4_IN = 47, - MHI_MAX_SOFTWARE_CHANNELS = 48, - MHI_CLIENT_TEST_OUT = 60, - MHI_CLIENT_TEST_IN = 61, - MHI_CLIENT_RESERVED_1_LOWER = 62, - MHI_CLIENT_RESERVED_1_UPPER = 99, - MHI_CLIENT_IP_HW_0_OUT = 100, - MHI_CLIENT_IP_HW_0_IN = 101, - MHI_CLIENT_RESERVED_2_LOWER = 102, - MHI_CLIENT_RESERVED_2_UPPER = 127, - MHI_MAX_CHANNELS = 102, -}; -#endif -#endif /* _SDX20_MHI_H_ */ diff --git a/quectel_MHI/src/devices/Kconfig b/quectel_MHI/src/devices/Kconfig deleted file mode 100644 index d92e95b..0000000 --- a/quectel_MHI/src/devices/Kconfig +++ /dev/null @@ -1,33 +0,0 @@ -menu "MHI device support" - -config MHI_NETDEV - tristate "MHI NETDEV" - depends on MHI_BUS - help - MHI based net device driver for transferring IP traffic - between host and modem. By enabling this driver, clients - can transfer data using standard network interface. Over - the air traffic goes thru mhi netdev interface. - -config MHI_UCI - tristate "MHI UCI" - depends on MHI_BUS - help - MHI based uci driver is for transferring data between host and - modem using standard file operations from user space. Open, read, - write, ioctl, and close operations are supported by this driver. - Please check mhi_uci_match_table for all supported channels that - are exposed to userspace. - -config MHI_SATELLITE - tristate "MHI SATELLITE" - depends on MHI_BUS - help - MHI proxy satellite device driver enables NON-HLOS MHI satellite - drivers to communicate with device over PCIe link without host - involvement. Host facilitates propagation of events from device - to NON-HLOS MHI satellite drivers, channel states, and power - management over IPC communication. It helps in HLOS power - savings. - -endmenu diff --git a/quectel_MHI/src/devices/Makefile b/quectel_MHI/src/devices/Makefile deleted file mode 100644 index e720069..0000000 --- a/quectel_MHI/src/devices/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_MHI_NETDEV) +=mhi_netdev.o -obj-$(CONFIG_MHI_UCI) +=mhi_uci.o -obj-$(CONFIG_MHI_SATELLITE) +=mhi_satellite.o diff --git a/quectel_MHI/src/devices/mhi_netdev.c b/quectel_MHI/src/devices/mhi_netdev.c deleted file mode 100644 index ed7b24b..0000000 --- a/quectel_MHI/src/devices/mhi_netdev.c +++ /dev/null @@ -1,1063 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/ - -#include -#include -#include -#include -//#include -#include -#include -#include -//#include -#if 1 -static inline void *ipc_log_context_create(int max_num_pages, - const char *modname, uint16_t user_version) -{ return NULL; } -static inline int ipc_log_string(void *ilctxt, const char *fmt, ...) -{ return -EINVAL; } -#endif -#include -#include -#include -#include -#include -#include "../core/mhi.h" - -#define QUECTEL_NO_DTS - -extern void rmnet_data_init(struct net_device *real_dev, u32 nr_rmnet_devs); -extern void rmnet_data_deinit(struct net_device *real_dev, u32 nr_rmnet_devs); - -static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00}; -static const unsigned char default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3, 0x00, 0x00, 0x00}; -static void qmap_hex_dump(const char *tag, unsigned char *data, unsigned len) { - uint i; - uint *d = (uint *)data; - - printk(KERN_DEBUG "%s data=%p, len=%x\n", tag, data, len); - len = (len+3)/4; - for (i = 0; i < len; i+=4) { - printk(KERN_DEBUG "%08x %08x %08x %08x %08x\n", i*4, d[i+0], d[i+1], d[i+2], d[i+3]); - } -} - -#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" -#define WATCHDOG_TIMEOUT (30 * HZ) -#define IPC_LOG_PAGES (100) -#define MAX_NETBUF_SIZE (128) - -#ifdef CONFIG_MHI_DEBUG - -#define IPC_LOG_LVL (MHI_MSG_LVL_VERBOSE) - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) \ - panic(msg); \ -} while (0) - -#define MSG_VERB(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ - if (mhi_netdev->ipc_log && (mhi_netdev->ipc_log_lvl <= \ - MHI_MSG_LVL_VERBOSE)) \ - ipc_log_string(mhi_netdev->ipc_log, "[D][%s] " fmt, \ - __func__, ##__VA_ARGS__); \ -} while (0) - -#else - -#define IPC_LOG_LVL (MHI_MSG_LVL_ERROR) - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) { \ - MSG_ERR(msg); \ - WARN_ON(cond); \ - } \ -} while (0) - -#define MSG_VERB(fmt, ...) - -#endif - -#define MSG_LOG(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ - pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ - if (mhi_netdev->ipc_log && (mhi_netdev->ipc_log_lvl <= \ - MHI_MSG_LVL_INFO)) \ - ipc_log_string(mhi_netdev->ipc_log, "[I][%s] " fmt, \ - __func__, ##__VA_ARGS__); \ -} while (0) - -#define MSG_ERR(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ - if (mhi_netdev->ipc_log && (mhi_netdev->ipc_log_lvl <= \ - MHI_MSG_LVL_ERROR)) \ - ipc_log_string(mhi_netdev->ipc_log, "[E][%s] " fmt, \ - __func__, ##__VA_ARGS__); \ -} while (0) - -struct mhi_net_chain { - struct sk_buff *head, *tail; /* chained skb */ -}; - -struct mhi_netdev { - int alias; - struct mhi_device *mhi_dev; - struct mhi_netdev *rsc_dev; /* rsc linked node */ - bool is_rsc_dev; - int wake; - - u32 mru; - u32 order; - const char *interface_name; - struct napi_struct *napi; - struct net_device *ndev; - bool ethernet_interface; - - struct mhi_netbuf **netbuf_pool; - int pool_size; /* must be power of 2 */ - int current_index; - bool chain_skb; - struct mhi_net_chain *chain; - - struct dentry *dentry; - enum MHI_DEBUG_LEVEL msg_lvl; - enum MHI_DEBUG_LEVEL ipc_log_lvl; - void *ipc_log; - - //struct rmnet_port port; -}; - -struct mhi_netdev_priv { - struct mhi_netdev *mhi_netdev; -}; - -/* Try not to make this structure bigger than 128 bytes, since this take space - * in payload packet. - * Example: If MRU = 16K, effective MRU = 16K - sizeof(mhi_netbuf) - */ -struct mhi_netbuf { - struct mhi_buf mhi_buf; /* this must be first element */ - void (*unmap)(struct device *dev, dma_addr_t addr, size_t size, - enum dma_data_direction dir); -}; - -static struct mhi_driver mhi_netdev_driver; -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev); - -static __be16 mhi_netdev_ip_type_trans(u8 data) -{ - __be16 protocol = 0; - - /* determine L3 protocol */ - switch (data & 0xf0) { - case 0x40: - protocol = htons(ETH_P_IP); - break; - case 0x60: - protocol = htons(ETH_P_IPV6); - break; - default: - /* default is QMAP */ - protocol = htons(ETH_P_MAP); - break; - } - protocol = htons(ETH_P_MAP); //carl.yin fix set - return protocol; -} - -static struct mhi_netbuf *mhi_netdev_alloc(struct device *dev, - gfp_t gfp, - unsigned int order) -{ - struct page *page; - struct mhi_netbuf *netbuf; - struct mhi_buf *mhi_buf; - void *vaddr; - - page = __dev_alloc_pages(gfp, order); - if (!page) - return NULL; - - vaddr = page_address(page); - - /* we going to use the end of page to store cached data */ - netbuf = vaddr + (PAGE_SIZE << order) - sizeof(*netbuf); - - mhi_buf = (struct mhi_buf *)netbuf; - mhi_buf->page = page; - mhi_buf->buf = vaddr; - mhi_buf->len = (void *)netbuf - vaddr; - mhi_buf->dma_addr = dma_map_page(dev, page, 0, mhi_buf->len, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, mhi_buf->dma_addr)) { - __free_pages(mhi_buf->page, order); - return NULL; - } - - return netbuf; -} - -static void mhi_netdev_unmap_page(struct device *dev, - dma_addr_t dma_addr, - size_t len, - enum dma_data_direction dir) -{ - dma_unmap_page(dev, dma_addr, len, dir); -} - -static int mhi_netdev_tmp_alloc(struct mhi_netdev *mhi_netdev, int nr_tre) -{ - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct device *dev = mhi_dev->dev.parent; - const u32 order = mhi_netdev->order; - int i, ret; - - for (i = 0; i < nr_tre; i++) { - struct mhi_buf *mhi_buf; - struct mhi_netbuf *netbuf = mhi_netdev_alloc(dev, GFP_ATOMIC, - order); - if (!netbuf) - return -ENOMEM; - - mhi_buf = (struct mhi_buf *)netbuf; - netbuf->unmap = mhi_netdev_unmap_page; - - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, mhi_buf, - mhi_buf->len, MHI_EOT); - if (unlikely(ret)) { - MSG_ERR("Failed to queue transfer, ret:%d\n", ret); - mhi_netdev_unmap_page(dev, mhi_buf->dma_addr, - mhi_buf->len, DMA_FROM_DEVICE); - __free_pages(mhi_buf->page, order); - return ret; - } - } - - return 0; -} - -static void mhi_netdev_queue(struct mhi_netdev *mhi_netdev) -{ - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct device *dev = mhi_dev->dev.parent; - struct mhi_netbuf *netbuf; - struct mhi_buf *mhi_buf; - struct mhi_netbuf **netbuf_pool = mhi_netdev->netbuf_pool; - int nr_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - int i, peak, cur_index, ret; - const int pool_size = mhi_netdev->pool_size - 1, max_peak = 4; - - MSG_VERB("Enter free_desc:%d\n", nr_tre); - - if (!nr_tre) - return; - - /* try going thru reclaim pool first */ - for (i = 0; i < nr_tre; i++) { - /* peak for the next buffer, we going to peak several times, - * and we going to give up if buffers are not yet free - */ - cur_index = mhi_netdev->current_index; - netbuf = NULL; - for (peak = 0; peak < max_peak; peak++) { - struct mhi_netbuf *tmp = netbuf_pool[cur_index]; - - mhi_buf = &tmp->mhi_buf; - - cur_index = (cur_index + 1) & pool_size; - - /* page == 1 idle, buffer is free to reclaim */ - if (page_count(mhi_buf->page) == 1) { - netbuf = tmp; - break; - } - } - - /* could not find a free buffer */ - if (!netbuf) - break; - - /* increment reference count so when network stack is done - * with buffer, the buffer won't be freed - */ - get_page(mhi_buf->page); - dma_sync_single_for_device(dev, mhi_buf->dma_addr, mhi_buf->len, - DMA_FROM_DEVICE); - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, mhi_buf, - mhi_buf->len, MHI_EOT); - if (unlikely(ret)) { - MSG_ERR("Failed to queue buffer, ret:%d\n", ret); - netbuf->unmap(dev, mhi_buf->dma_addr, mhi_buf->len, - DMA_FROM_DEVICE); - put_page(mhi_buf->page); - return; - } - mhi_netdev->current_index = cur_index; - } - - /* recyling did not work, buffers are still busy allocate temp pkts */ - if (i < nr_tre) - mhi_netdev_tmp_alloc(mhi_netdev, nr_tre - i); -} - -/* allocating pool of memory */ -static int mhi_netdev_alloc_pool(struct mhi_netdev *mhi_netdev) -{ - int i; - struct mhi_netbuf *netbuf, **netbuf_pool; - struct mhi_buf *mhi_buf; - const u32 order = mhi_netdev->order; - struct device *dev = mhi_netdev->mhi_dev->dev.parent; - - netbuf_pool = kmalloc_array(mhi_netdev->pool_size, sizeof(*netbuf_pool), - GFP_KERNEL); - if (!netbuf_pool) - return -ENOMEM; - - for (i = 0; i < mhi_netdev->pool_size; i++) { - /* allocate paged data */ - netbuf = mhi_netdev_alloc(dev, GFP_KERNEL, order); - if (!netbuf) - goto error_alloc_page; - - netbuf->unmap = dma_sync_single_for_cpu; - netbuf_pool[i] = netbuf; - } - - mhi_netdev->netbuf_pool = netbuf_pool; - - return 0; - -error_alloc_page: - for (--i; i >= 0; i--) { - netbuf = netbuf_pool[i]; - mhi_buf = &netbuf->mhi_buf; - dma_unmap_page(dev, mhi_buf->dma_addr, mhi_buf->len, - DMA_FROM_DEVICE); - __free_pages(mhi_buf->page, order); - } - - kfree(netbuf_pool); - - return -ENOMEM; -} - -static void mhi_netdev_free_pool(struct mhi_netdev *mhi_netdev) -{ - int i; - struct mhi_netbuf *netbuf, **netbuf_pool = mhi_netdev->netbuf_pool; - struct device *dev = mhi_netdev->mhi_dev->dev.parent; - struct mhi_buf *mhi_buf; - - for (i = 0; i < mhi_netdev->pool_size; i++) { - netbuf = netbuf_pool[i]; - mhi_buf = &netbuf->mhi_buf; - dma_unmap_page(dev, mhi_buf->dma_addr, mhi_buf->len, - DMA_FROM_DEVICE); - __free_pages(mhi_buf->page, mhi_netdev->order); - } - - kfree(mhi_netdev->netbuf_pool); - mhi_netdev->netbuf_pool = NULL; -} - -static int mhi_netdev_poll(struct napi_struct *napi, int budget) -{ - struct net_device *dev = napi->dev; - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct mhi_netdev *rsc_dev = mhi_netdev->rsc_dev; - struct mhi_net_chain *chain = mhi_netdev->chain; - int rx_work = 0; - - MSG_VERB("Entered\n"); - - rx_work = mhi_poll(mhi_dev, budget); - - /* chained skb, push it to stack */ - if (chain && chain->head) { - netif_receive_skb(chain->head); - chain->head = NULL; - } - - if (rx_work < 0) { - MSG_ERR("Error polling ret:%d\n", rx_work); - napi_complete(napi); - return 0; - } - - /* queue new buffers */ - mhi_netdev_queue(mhi_netdev); - - if (rsc_dev) - mhi_netdev_queue(rsc_dev); - - /* complete work if # of packet processed less than allocated budget */ - if (rx_work < budget) - napi_complete(napi); - - MSG_VERB("polled %d pkts\n", rx_work); - - return rx_work; -} - -static int mhi_netdev_open(struct net_device *dev) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - MSG_LOG("Opened net dev interface\n"); - - /* tx queue may not necessarily be stopped already - * so stop the queue if tx path is not enabled - */ - if (!mhi_dev->ul_chan) - netif_stop_queue(dev); - else - netif_start_queue(dev); - - return 0; - -} - -static int mhi_netdev_change_mtu(struct net_device *dev, int new_mtu) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - if (new_mtu < 0 || mhi_dev->mtu < new_mtu) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - -static int mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int res = 0; - - MSG_VERB("Entered\n"); - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - //qmap_hex_dump(__func__, skb->data, 32); - if (skb->protocol != htons(ETH_P_MAP)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len, - MHI_EOT); - if (res) { - MSG_VERB("Failed to queue with reason:%d\n", res); - netif_stop_queue(dev); - res = NETDEV_TX_BUSY; - } - - MSG_VERB("Exited\n"); - - return res; -} - -#if 0 -static int mhi_netdev_ioctl_extended(struct net_device *dev, struct ifreq *ifr) -{ - struct rmnet_ioctl_extended_s ext_cmd; - int rc = 0; - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - rc = copy_from_user(&ext_cmd, ifr->ifr_ifru.ifru_data, - sizeof(struct rmnet_ioctl_extended_s)); - if (rc) - return rc; - - switch (ext_cmd.extended_ioctl) { - case RMNET_IOCTL_GET_SUPPORTED_FEATURES: - ext_cmd.u.data = 0; - break; - case RMNET_IOCTL_GET_DRIVER_NAME: - strlcpy(ext_cmd.u.if_name, mhi_netdev->interface_name, - sizeof(ext_cmd.u.if_name)); - break; - case RMNET_IOCTL_SET_SLEEP_STATE: - if (ext_cmd.u.data && mhi_netdev->wake) { - /* Request to enable LPM */ - MSG_VERB("Enable MHI LPM"); - mhi_netdev->wake--; - mhi_device_put(mhi_dev); - } else if (!ext_cmd.u.data && !mhi_netdev->wake) { - /* Request to disable LPM */ - MSG_VERB("Disable MHI LPM"); - mhi_netdev->wake++; - mhi_device_get(mhi_dev); - } - break; - default: - rc = -EINVAL; - break; - } - - rc = copy_to_user(ifr->ifr_ifru.ifru_data, &ext_cmd, - sizeof(struct rmnet_ioctl_extended_s)); - return rc; -} - -static int mhi_netdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - int rc = 0; - struct rmnet_ioctl_data_s ioctl_data; - - switch (cmd) { - case RMNET_IOCTL_SET_LLP_IP: /* set RAWIP protocol */ - break; - case RMNET_IOCTL_GET_LLP: /* get link protocol state */ - ioctl_data.u.operation_mode = RMNET_MODE_LLP_IP; - if (copy_to_user(ifr->ifr_ifru.ifru_data, &ioctl_data, - sizeof(struct rmnet_ioctl_data_s))) - rc = -EFAULT; - break; - case RMNET_IOCTL_GET_OPMODE: /* get operation mode */ - ioctl_data.u.operation_mode = RMNET_MODE_LLP_IP; - if (copy_to_user(ifr->ifr_ifru.ifru_data, &ioctl_data, - sizeof(struct rmnet_ioctl_data_s))) - rc = -EFAULT; - break; - case RMNET_IOCTL_SET_QOS_ENABLE: - rc = -EINVAL; - break; - case RMNET_IOCTL_SET_QOS_DISABLE: - rc = 0; - break; - case RMNET_IOCTL_OPEN: - case RMNET_IOCTL_CLOSE: - /* we just ignore them and return success */ - rc = 0; - break; - case RMNET_IOCTL_EXTENDED: - rc = mhi_netdev_ioctl_extended(dev, ifr); - break; - default: - /* don't fail any IOCTL right now */ - rc = 0; - break; - } - - return rc; -} -#endif - -static void mhi_netdev_get_drvinfo (struct net_device *ndev, struct ethtool_drvinfo *info) -{ - //struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - - strlcpy (info->driver, "pcie_mhi", sizeof info->driver); - strlcpy (info->version, PCIE_MHI_DRIVER_VERSION, sizeof info->version); -} - -static const struct ethtool_ops mhi_netdev_ethtool_ops = { - .get_drvinfo = mhi_netdev_get_drvinfo, -}; - -static const struct net_device_ops mhi_netdev_ops_ip = { - .ndo_open = mhi_netdev_open, - .ndo_start_xmit = mhi_netdev_xmit, - //.ndo_do_ioctl = mhi_netdev_ioctl, - .ndo_change_mtu = mhi_netdev_change_mtu, - .ndo_set_mac_address = 0, - .ndo_validate_addr = 0, -}; - -static void mhi_netdev_setup(struct net_device *dev) -{ - dev->netdev_ops = &mhi_netdev_ops_ip; - ether_setup(dev); - - /* set this after calling ether_setup */ - dev->header_ops = 0; /* No header */ - dev->type = ARPHRD_RAWIP; - dev->hard_header_len = 0; - dev->addr_len = 0; - dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - dev->watchdog_timeo = WATCHDOG_TIMEOUT; - - dev->ethtool_ops = &mhi_netdev_ethtool_ops; - memcpy (dev->dev_addr, node_id, sizeof node_id); - dev->flags |= IFF_NOARP; -} - -/* enable mhi_netdev netdev, call only after grabbing mhi_netdev.mutex */ -static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev) -{ - int ret = 0; - char ifalias[IFALIASZ]; - char ifname[IFNAMSIZ]; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; -#ifndef QUECTEL_NO_DTS - struct device_node *of_node = mhi_dev->dev.of_node; -#endif - struct mhi_netdev_priv *mhi_netdev_priv; - - mhi_netdev->alias = 0;//of_alias_get_id(of_node, "mhi-netdev"); - if (mhi_netdev->alias < 0) - mhi_netdev->alias = 0; - -#ifdef QUECTEL_NO_DTS - mhi_netdev->interface_name = "rmnet_mhi"; -#else - - ret = of_property_read_string(of_node, "mhi,interface-name", - &mhi_netdev->interface_name); -#endif - if (ret) - mhi_netdev->interface_name = mhi_netdev_driver.driver.name; - - snprintf(ifalias, sizeof(ifalias), "%s_%04x_%02u.%02u.%02u_%u", - mhi_netdev->interface_name, mhi_dev->dev_id, mhi_dev->domain, - mhi_dev->bus, mhi_dev->slot, mhi_netdev->alias); - - snprintf(ifname, sizeof(ifname), "%s%%d", mhi_netdev->interface_name); - -#ifdef QUECTEL_NO_DTS - mhi_netdev->ethernet_interface = 0; -#else - mhi_netdev->ethernet_interface = of_property_read_bool(of_node, - "mhi,ethernet-interface"); -#endif - rtnl_lock(); - mhi_netdev->ndev = alloc_netdev(sizeof(*mhi_netdev_priv), - ifname, NET_NAME_PREDICTABLE, - mhi_netdev_setup); - if (!mhi_netdev->ndev) { - rtnl_unlock(); - return -ENOMEM; - } - - mhi_netdev->ndev->mtu = mhi_dev->mtu; - SET_NETDEV_DEV(mhi_netdev->ndev, &mhi_dev->dev); - //dev_set_alias(mhi_netdev->ndev, ifalias, strlen(ifalias)); - mhi_netdev_priv = netdev_priv(mhi_netdev->ndev); - mhi_netdev_priv->mhi_netdev = mhi_netdev; - rtnl_unlock(); - - mhi_netdev->napi = devm_kzalloc(&mhi_dev->dev, - sizeof(*mhi_netdev->napi), GFP_KERNEL); - if (!mhi_netdev->napi) { - ret = -ENOMEM; - goto napi_alloc_fail; - } - - netif_napi_add(mhi_netdev->ndev, mhi_netdev->napi, - mhi_netdev_poll, NAPI_POLL_WEIGHT); - ret = register_netdev(mhi_netdev->ndev); - if (ret) { - MSG_ERR("Network device registration failed\n"); - goto net_dev_reg_fail; - } - - napi_enable(mhi_netdev->napi); - - MSG_LOG("Exited.\n"); - - return 0; - -net_dev_reg_fail: - netif_napi_del(mhi_netdev->napi); - -napi_alloc_fail: - free_netdev(mhi_netdev->ndev); - mhi_netdev->ndev = NULL; - - return ret; -} - -static void mhi_netdev_xfer_ul_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct sk_buff *skb = mhi_result->buf_addr; - struct net_device *ndev = mhi_netdev->ndev; - - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb(skb); - - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); -} - -static void mhi_netdev_push_skb(struct mhi_netdev *mhi_netdev, - struct mhi_buf *mhi_buf, - struct mhi_result *mhi_result) -{ - struct sk_buff *skb; - - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) { - __free_pages(mhi_buf->page, mhi_netdev->order); - return; - } - - if (!mhi_netdev->ethernet_interface) { - skb_add_rx_frag(skb, 0, mhi_buf->page, 0, - mhi_result->bytes_xferd, mhi_netdev->mru); - skb->dev = mhi_netdev->ndev; - skb->protocol = mhi_netdev_ip_type_trans(*(u8 *)mhi_buf->buf); - if (skb_linearize(skb)) - return; - } else { - skb_add_rx_frag(skb, 0, mhi_buf->page, ETH_HLEN, - mhi_result->bytes_xferd - ETH_HLEN, - mhi_netdev->mru); - skb->dev = mhi_netdev->ndev; - skb->protocol = mhi_netdev_ip_type_trans(((u8 *)mhi_buf->buf)[ETH_HLEN]); - } - netif_receive_skb(skb); -} - -static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct mhi_netbuf *netbuf = mhi_result->buf_addr; - struct mhi_buf *mhi_buf = &netbuf->mhi_buf; - struct sk_buff *skb; - struct net_device *ndev = mhi_netdev->ndev; - struct device *dev = mhi_dev->dev.parent; - struct mhi_net_chain *chain = mhi_netdev->chain; - - netbuf->unmap(dev, mhi_buf->dma_addr, mhi_buf->len, DMA_FROM_DEVICE); - - /* modem is down, drop the buffer */ - if (mhi_result->transaction_status == -ENOTCONN) { - __free_pages(mhi_buf->page, mhi_netdev->order); - return; - } - - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += mhi_result->bytes_xferd; - - if (unlikely(!chain)) { - mhi_netdev_push_skb(mhi_netdev, mhi_buf, mhi_result); - return; - } - - /* we support chaining */ - skb = alloc_skb(0, GFP_ATOMIC); - if (likely(skb)) { - if (!mhi_netdev->ethernet_interface) { - skb_add_rx_frag(skb, 0, mhi_buf->page, 0, - mhi_result->bytes_xferd, mhi_netdev->mru); - } else { - skb_add_rx_frag(skb, 0, mhi_buf->page, ETH_HLEN, - mhi_result->bytes_xferd - ETH_HLEN, - mhi_netdev->mru); - } - - /* this is first on list */ - if (!chain->head) { - skb->dev = ndev; - if (!mhi_netdev->ethernet_interface) { - skb->protocol = - mhi_netdev_ip_type_trans(*(u8 *)mhi_buf->buf); - } else { - skb->protocol = - mhi_netdev_ip_type_trans(((u8 *)mhi_buf->buf)[ETH_HLEN]); - } - chain->head = skb; - } else { - skb_shinfo(chain->tail)->frag_list = skb; - } - - chain->tail = skb; - } else { - __free_pages(mhi_buf->page, mhi_netdev->order); - } -} - -static void mhi_netdev_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - - if (mhi_cb != MHI_CB_PENDING_DATA) - return; - - napi_schedule(mhi_netdev->napi); -} - -#ifdef CONFIG_DEBUG_FS - -struct dentry *dentry; - -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev) -{ - char node_name[32]; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - /* Both tx & rx client handle contain same device info */ - snprintf(node_name, sizeof(node_name), "%s_%04x_%02u.%02u.%02u_%u", - mhi_netdev->interface_name, mhi_dev->dev_id, mhi_dev->domain, - mhi_dev->bus, mhi_dev->slot, mhi_netdev->alias); - - if (IS_ERR_OR_NULL(dentry)) - return; - - mhi_netdev->dentry = debugfs_create_dir(node_name, dentry); - if (IS_ERR_OR_NULL(mhi_netdev->dentry)) - return; -} - -static void mhi_netdev_create_debugfs_dir(void) -{ - dentry = debugfs_create_dir(MHI_NETDEV_DRIVER_NAME, 0); -} - -#else - -static void mhi_netdev_create_debugfs(struct mhi_netdev_private *mhi_netdev) -{ -} - -static void mhi_netdev_create_debugfs_dir(void) -{ -} - -#endif - -static void mhi_netdev_remove(struct mhi_device *mhi_dev) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - - MSG_LOG("Remove notification received\n"); - - /* rsc parent takes cares of the cleanup */ - if (mhi_netdev->is_rsc_dev) { - mhi_netdev_free_pool(mhi_netdev); - return; - } - - rmnet_data_deinit(mhi_netdev->ndev, 1); - netif_stop_queue(mhi_netdev->ndev); - napi_disable(mhi_netdev->napi); - unregister_netdev(mhi_netdev->ndev); - netif_napi_del(mhi_netdev->napi); - free_netdev(mhi_netdev->ndev); - mhi_netdev_free_pool(mhi_netdev); - - if (!IS_ERR_OR_NULL(mhi_netdev->dentry)) - debugfs_remove_recursive(mhi_netdev->dentry); -} - -static int mhi_netdev_match(struct device *dev, void *data) -{ - /* if phandle dt == device dt, we found a match */ - return (dev->of_node == data); -} - -static void mhi_netdev_clone_dev(struct mhi_netdev *mhi_netdev, - struct mhi_netdev *parent) -{ - mhi_netdev->ndev = parent->ndev; - mhi_netdev->napi = parent->napi; - mhi_netdev->ipc_log = parent->ipc_log; - mhi_netdev->msg_lvl = parent->msg_lvl; - mhi_netdev->ipc_log_lvl = parent->ipc_log_lvl; - mhi_netdev->is_rsc_dev = true; - mhi_netdev->chain = parent->chain; -} - -static int mhi_netdev_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - int ret; - struct mhi_netdev *mhi_netdev, *p_netdev = NULL; -#ifndef QUECTEL_NO_DTS - struct device_node *of_node = mhi_dev->dev.of_node; -#endif - int nr_tre; - char node_name[32]; - struct device_node *phandle; - bool no_chain; - -#ifndef QUECTEL_NO_DTS - if (!of_node) - return -ENODEV; -#endif - - mhi_netdev = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_netdev), - GFP_KERNEL); - if (!mhi_netdev) - return -ENOMEM; - - mhi_netdev->mhi_dev = mhi_dev; - mhi_device_set_devdata(mhi_dev, mhi_netdev); - -#ifdef QUECTEL_NO_DTS - mhi_netdev->mru = 16384; - ret = 0; -#else - ret = of_property_read_u32(of_node, "mhi,mru", &mhi_netdev->mru); -#endif - if (ret) - return -ENODEV; - - /* MRU must be multiplication of page size */ - mhi_netdev->order = __ilog2_u32(mhi_netdev->mru / PAGE_SIZE); - if ((PAGE_SIZE << mhi_netdev->order) < mhi_netdev->mru) - return -EINVAL; - - /* check if this device shared by a parent device */ -#ifdef QUECTEL_NO_DTS - phandle = NULL; -#else - phandle = of_parse_phandle(of_node, "mhi,rsc-parent", 0); -#endif - if (phandle) { - struct device *dev; - struct mhi_device *pdev; - /* find the parent device */ - dev = driver_find_device(mhi_dev->dev.driver, NULL, phandle, - mhi_netdev_match); - if (!dev) - return -ENODEV; - - /* this device is shared with parent device. so we won't be - * creating a new network interface. Clone parent - * information to child node - */ - pdev = to_mhi_device(dev); - p_netdev = mhi_device_get_devdata(pdev); - mhi_netdev_clone_dev(mhi_netdev, p_netdev); - put_device(dev); - } else { - mhi_netdev->msg_lvl = MHI_MSG_LVL_ERROR; -#ifdef QUECTEL_NO_DTS - no_chain = 0; -#else - no_chain = of_property_read_bool(of_node, - "mhi,disable-chain-skb"); -#endif - if (!no_chain) { - mhi_netdev->chain = devm_kzalloc(&mhi_dev->dev, - sizeof(*mhi_netdev->chain), - GFP_KERNEL); - if (!mhi_netdev->chain) - return -ENOMEM; - } - - ret = mhi_netdev_enable_iface(mhi_netdev); - if (ret) - return ret; - - /* create ipc log buffer */ - snprintf(node_name, sizeof(node_name), - "%s_%04x_%02u.%02u.%02u_%u", - mhi_netdev->interface_name, mhi_dev->dev_id, - mhi_dev->domain, mhi_dev->bus, mhi_dev->slot, - mhi_netdev->alias); - mhi_netdev->ipc_log = ipc_log_context_create(IPC_LOG_PAGES, - node_name, 0); - mhi_netdev->ipc_log_lvl = IPC_LOG_LVL; - - mhi_netdev_create_debugfs(mhi_netdev); - } - - /* move mhi channels to start state */ - ret = mhi_prepare_for_transfer(mhi_dev); - if (ret) { - MSG_ERR("Failed to start channels ret %d\n", ret); - goto error_start; - } - - rmnet_data_init(mhi_netdev->ndev, 1); - - /* setup pool size ~2x ring length*/ - nr_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - mhi_netdev->pool_size = 1 << __ilog2_u32(nr_tre); - if (nr_tre > mhi_netdev->pool_size) - mhi_netdev->pool_size <<= 1; - mhi_netdev->pool_size <<= 1; - - /* allocate memory pool */ - ret = mhi_netdev_alloc_pool(mhi_netdev); - if (ret) - goto error_start; - - /* link child node with parent node if it's children dev */ - if (p_netdev) - p_netdev->rsc_dev = mhi_netdev; - - /* now we have a pool of buffers allocated, queue to hardware - * by triggering a napi_poll - */ - napi_schedule(mhi_netdev->napi); - - return 0; - -error_start: - if (phandle) - return ret; - - netif_stop_queue(mhi_netdev->ndev); - napi_disable(mhi_netdev->napi); - unregister_netdev(mhi_netdev->ndev); - netif_napi_del(mhi_netdev->napi); - free_netdev(mhi_netdev->ndev); - - return ret; -} - -static const struct mhi_device_id mhi_netdev_match_table[] = { - { .chan = "IP_HW0" }, - { .chan = "IP_HW_ADPL" }, - { .chan = "IP_HW0_RSC" }, - { .chan = "IP_SW0" }, - {}, -}; - -static struct mhi_driver mhi_netdev_driver = { - .id_table = mhi_netdev_match_table, - .probe = mhi_netdev_probe, - .remove = mhi_netdev_remove, - .ul_xfer_cb = mhi_netdev_xfer_ul_cb, - .dl_xfer_cb = mhi_netdev_xfer_dl_cb, - .status_cb = mhi_netdev_status_cb, - .driver = { - .name = "mhi_netdev", - .owner = THIS_MODULE, - } -}; - -static int __init mhi_netdev_init(void) -{ - BUILD_BUG_ON(sizeof(struct mhi_netbuf) > MAX_NETBUF_SIZE); - mhi_netdev_create_debugfs_dir(); - - return mhi_driver_register(&mhi_netdev_driver); -} -//module_init(mhi_netdev_init); - -int __init mhi_device_netdev_init(struct dentry *parent) -{ - BUILD_BUG_ON(sizeof(struct mhi_netbuf) > MAX_NETBUF_SIZE); - - return mhi_netdev_init(); -} - -void mhi_device_netdev_exit(void) -{ -#ifdef CONFIG_DEBUG_FS - debugfs_remove_recursive(dentry); -#endif - mhi_driver_unregister(&mhi_netdev_driver); -} - diff --git a/quectel_MHI/src/devices/mhi_netdev_quectel.c b/quectel_MHI/src/devices/mhi_netdev_quectel.c deleted file mode 100644 index 1812c02..0000000 --- a/quectel_MHI/src/devices/mhi_netdev_quectel.c +++ /dev/null @@ -1,3034 +0,0 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#define CONFIG_IPQ5018_RATE_CONTROL //Only used with spf11.5 for IPQ5018 -#if defined(CONFIG_IPQ5018_RATE_CONTROL) -//#include -#include -#endif - -#include "../core/mhi.h" -//#define MHI_NETDEV_ONE_CARD_MODE -//#define ANDROID_gki //some fuction not allow used in this TEST - -#ifndef ETH_P_MAP -#define ETH_P_MAP 0xDA1A -#endif - -#if (ETH_P_MAP == 0x00F9) -#undef ETH_P_MAP -#define ETH_P_MAP 0xDA1A -#endif - -#ifndef ARPHRD_RAWIP -#define ARPHRD_RAWIP ARPHRD_NONE -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,2,0 )) -static bool netdev_is_rx_handler_busy(struct net_device *dev) -{ - ASSERT_RTNL(); - return dev && rtnl_dereference(dev->rx_handler); -} -#endif - -struct rmnet_nss_cb { - int (*nss_create)(struct net_device *dev); - int (*nss_free)(struct net_device *dev); - int (*nss_tx)(struct sk_buff *skb); -}; -static struct rmnet_nss_cb __read_mostly *nss_cb = NULL; -#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074) -//#ifdef CONFIG_RMNET_DATA //spf12.x have no macro defined, just for spf11.x -#define CONFIG_QCA_NSS_DRV -/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x -/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x -/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */ -/* need add DEPENDS:= kmod-rmnet-core in feeds/makefile */ -extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; -//#endif -#endif - -static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00}; -static const unsigned char default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3, 0x00, 0x00, 0x00}; - -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -#define QUECTEL_BRIDGE_MODE -#endif - -#define QUECTEL_RMNET_MODE - -#ifdef QUECTEL_BRIDGE_MODE -static uint __read_mostly bridge_mode = 0/*|BIT(1)*/; -module_param( bridge_mode, uint, S_IRUGO ); -#endif - -struct qmap_hdr { - u8 cd_rsvd_pad; - u8 mux_id; - u16 pkt_len; -} __packed; -#define QUECTEL_QMAP_MUX_ID 0x81 - -enum rmnet_map_v5_header_type { - RMNET_MAP_HEADER_TYPE_UNKNOWN, - RMNET_MAP_HEADER_TYPE_COALESCING = 0x1, - RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2, - RMNET_MAP_HEADER_TYPE_ENUM_LENGTH -}; - -enum rmnet_map_commands { - RMNET_MAP_COMMAND_NONE, - RMNET_MAP_COMMAND_FLOW_DISABLE, - RMNET_MAP_COMMAND_FLOW_ENABLE, - RMNET_MAP_COMMAND_FLOW_START = 7, - RMNET_MAP_COMMAND_FLOW_END = 8, - /* These should always be the last 2 elements */ - RMNET_MAP_COMMAND_UNKNOWN, - RMNET_MAP_COMMAND_ENUM_LENGTH -}; - -#define RMNET_MAP_COMMAND_REQUEST 0 -#define RMNET_MAP_COMMAND_ACK 1 -#define RMNET_MAP_COMMAND_UNSUPPORTED 2 -#define RMNET_MAP_COMMAND_INVALID 3 - -/* Main QMAP header */ -struct rmnet_map_header { - u8 pad_len:6; - u8 next_hdr:1; - u8 cd_bit:1; - u8 mux_id; - __be16 pkt_len; -} __aligned(1); - -/* QMAP v5 headers */ -struct rmnet_map_v5_csum_header { - u8 next_hdr:1; - u8 header_type:7; - u8 hw_reserved:7; - u8 csum_valid_required:1; - __be16 reserved; -} __aligned(1); - -struct rmnet_map_control_command { - u8 command_name; - u8 cmd_type:2; - u8 reserved:6; - u16 reserved2; - u32 transaction_id; - union { - struct { - u8 reserved2; - u8 ip_family:2; - u8 reserved:6; - __be16 flow_control_seq_num; - __be32 qos_id; - } flow_control; - u8 data[0]; - }; -} __aligned(1); - -struct mhi_mbim_hdr { - struct usb_cdc_ncm_nth16 nth16; - struct usb_cdc_ncm_ndp16 ndp16; - struct usb_cdc_ncm_dpe16 dpe16[2]; -} __attribute__ ((packed)); - -#define QCUSB_MRECEIVE_MAX_BUFFER_SIZE (1024*32) //maybe 31KB is enough -#define QCUSB_MTRANSMIT_MAX_BUFFER_SIZE (1024*16) -#define NTB_OUT_MAX_DATAGRAMS 16 - -static const struct usb_cdc_ncm_ntb_parameters ncmNTBParams = { - .bmNtbFormatsSupported = USB_CDC_NCM_NTB16_SUPPORTED, - .dwNtbInMaxSize = QCUSB_MRECEIVE_MAX_BUFFER_SIZE, - .wNdpInDivisor = 0x04, - .wNdpInPayloadRemainder = 0x0, - .wNdpInAlignment = 0x4, - - .dwNtbOutMaxSize = QCUSB_MTRANSMIT_MAX_BUFFER_SIZE, - .wNdpOutDivisor = 0x04, - .wNdpOutPayloadRemainder = 0x0, - .wNdpOutAlignment = 0x4, - .wNtbOutMaxDatagrams = NTB_OUT_MAX_DATAGRAMS, -}; - -#if 0 -static void qmap_hex_dump(const char *tag, unsigned char *data, unsigned len) { - uint i; - uint *d = (uint *)data; - - printk(KERN_DEBUG "%s data=%p, len=%x\n", tag, data, len); - len = (len+3)/4; - for (i = 0; i < len; i+=4) { - printk(KERN_DEBUG "%08x %08x %08x %08x %08x\n", i*4, d[i+0], d[i+1], d[i+2], d[i+3]); - } -} -#else -static void qmap_hex_dump(const char *tag, unsigned char *data, unsigned len) { -} -#endif - -static uint __read_mostly mhi_mbim_enabled = 0; -module_param(mhi_mbim_enabled, uint, S_IRUGO); -int mhi_netdev_mbin_enabled(void) { return mhi_mbim_enabled; } - -static uint __read_mostly qmap_mode = 1; -module_param(qmap_mode, uint, S_IRUGO); - -static uint __read_mostly poll_weight = NAPI_POLL_WEIGHT; -module_param(poll_weight, uint, S_IRUGO); - -#define MHI_NETDEV_DRIVER_NAME "mhi_netdev" -#define WATCHDOG_TIMEOUT (30 * HZ) - -#define MSG_VERB(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MHI_ASSERT(cond, msg) do { \ - if (cond) { \ - MSG_ERR(msg); \ - WARN_ON(cond); \ - } \ -} while (0) - -#define MSG_LOG(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_INFO) \ - pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__);\ -} while (0) - -#define MSG_ERR(fmt, ...) do { \ - if (mhi_netdev->msg_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ -} while (0) - -struct mhi_stats { - u32 rx_int; - u32 tx_full; - u32 tx_pkts; - u32 rx_budget_overflow; - u32 tx_allocated; - u32 rx_allocated; - u32 alloc_failed; -}; - -/* important: do not exceed sk_buf->cb (48 bytes) */ -struct mhi_skb_priv { - void *buf; - size_t size; - struct mhi_netdev *bind_netdev; -}; - -struct skb_data { /* skb->cb is one of these */ - struct mhi_netdev *bind_netdev; - unsigned int length; - unsigned int packets; -}; - -#define MHI_NETDEV_STATUS64 1 - -typedef struct { - uint size; - uint rx_urb_size; - uint ep_type; - uint iface_id; - uint MuxId; - uint ul_data_aggregation_max_datagrams; //0x17 - uint ul_data_aggregation_max_size ;//0x18 - uint dl_minimum_padding; //0x1A -} QMAP_SETTING; - -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int qmap_mode; - unsigned int qmap_version; - unsigned int dl_minimum_padding; - char ifname[8][16]; - unsigned char mux_id[8]; -} RMNET_INFO; - -typedef struct { - u16 tx_seq; - u16 rx_seq; - u32 rx_max; -} MHI_MBIM_CTX; - -enum mhi_net_type { - MHI_NET_UNKNOW, - MHI_NET_RMNET, - MHI_NET_MBIM, - MHI_NET_ETHER -}; - -//#define TS_DEBUG -struct mhi_netdev { - int alias; - struct mhi_device *mhi_dev; - spinlock_t rx_lock; - bool enabled; - rwlock_t pm_lock; /* state change lock */ - int (*rx_queue)(struct mhi_netdev *mhi_netdev, gfp_t gfp_t); - struct delayed_work alloc_work; - int wake; - - struct sk_buff_head tx_allocated; - struct sk_buff_head rx_allocated; - struct sk_buff_head qmap_chain; - struct sk_buff_head skb_chain; -#ifdef TS_DEBUG - uint clear_ts; - struct timespec diff_ts; - struct timespec qmap_ts; - struct timespec skb_ts; -#endif - - MHI_MBIM_CTX mbim_ctx; - - u32 mru; - u32 max_mtu; - const char *interface_name; - struct napi_struct napi; - struct net_device *ndev; - enum mhi_net_type net_type; - struct sk_buff *frag_skb; - bool recycle_buf; - -#if defined(MHI_NETDEV_STATUS64) - struct pcpu_sw_netstats __percpu *stats64; -#endif - struct mhi_stats stats; - - struct dentry *dentry; - enum MHI_DEBUG_LEVEL msg_lvl; - - struct net_device *mpQmapNetDev[8]; - u32 qmap_mode; - u32 qmap_version; // 5 ~ QMAP V1, 9 ~ QMAP V5 - u32 qmap_size; - u32 link_state; - u32 flow_control; - u32 dl_minimum_padding; - -#ifdef QUECTEL_BRIDGE_MODE - uint bridge_mode; - uint bridge_ipv4; - unsigned char bridge_mac[ETH_ALEN]; -#endif - uint use_rmnet_usb; - RMNET_INFO rmnet_info; - -#if defined(CONFIG_IPQ5018_RATE_CONTROL) - u64 first_jiffy; - u64 bytes_received_1; - u64 bytes_received_2; - u32 cntfrq_per_msec; - bool mhi_rate_control; -#endif - - u32 rmnet_map_command_stats[RMNET_MAP_COMMAND_ENUM_LENGTH]; -}; - -struct mhi_netdev_priv { - struct mhi_netdev *mhi_netdev; -}; - -struct qmap_priv { - void *pQmapDev; - struct net_device *real_dev; - struct net_device *self_dev; - u8 offset_id; - u8 mux_id; - u8 qmap_version; // 5~v1, 9~v5 - -#if defined(MHI_NETDEV_STATUS64) - struct pcpu_sw_netstats __percpu *stats64; -#endif - - spinlock_t agg_lock; - struct sk_buff *agg_skb; - unsigned agg_count; - struct timespec64 agg_time; - struct hrtimer agg_hrtimer; - struct work_struct agg_wq; - -#ifdef QUECTEL_BRIDGE_MODE - uint bridge_mode; - uint bridge_ipv4; - unsigned char bridge_mac[ETH_ALEN]; -#endif - uint use_qca_nss; -}; - -static struct mhi_netdev *ndev_to_mhi(struct net_device *ndev) { - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(ndev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - return mhi_netdev; -} - -static struct mhi_driver mhi_netdev_driver; -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev); - -#if 0 -static void mhi_netdev_skb_destructor(struct sk_buff *skb) -{ - struct mhi_skb_priv *skb_priv = (struct mhi_skb_priv *)(skb->cb); - struct mhi_netdev *mhi_netdev = skb_priv->mhi_netdev; - - skb->data = skb->head; - skb_reset_tail_pointer(skb); - skb->len = 0; - MHI_ASSERT(skb->data != skb_priv->buf, "incorrect buf"); - skb_queue_tail(&mhi_netdev->rx_allocated, skb); -} -#endif - -#ifdef QUECTEL_BRIDGE_MODE -static const struct net_device_ops mhi_netdev_ops_ip; -static const struct net_device_ops rmnet_vnd_ops; - -static int is_qmap_netdev(const struct net_device *ndev) { - return ndev->netdev_ops == &rmnet_vnd_ops; -} - -static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4) { - struct arphdr *parp; - u8 *arpptr, *sha; - u8 sip[4], tip[4], ipv4[4]; - struct sk_buff *reply = NULL; - - ipv4[0] = (bridge_ipv4 >> 24) & 0xFF; - ipv4[1] = (bridge_ipv4 >> 16) & 0xFF; - ipv4[2] = (bridge_ipv4 >> 8) & 0xFF; - ipv4[3] = (bridge_ipv4 >> 0) & 0xFF; - - parp = arp_hdr(skb); - - if (parp->ar_hrd == htons(ARPHRD_ETHER) && parp->ar_pro == htons(ETH_P_IP) - && parp->ar_op == htons(ARPOP_REQUEST) && parp->ar_hln == 6 && parp->ar_pln == 4) { - arpptr = (u8 *)parp + sizeof(struct arphdr); - sha = arpptr; - arpptr += net->addr_len; /* sha */ - memcpy(sip, arpptr, sizeof(sip)); - arpptr += sizeof(sip); - arpptr += net->addr_len; /* tha */ - memcpy(tip, arpptr, sizeof(tip)); - - pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d, ipv4=%d.%d.%d.%d\n", netdev_name(net), - sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3], ipv4[0], ipv4[1], ipv4[2], ipv4[3]); - //wwan0 sip = 10.151.137.255, tip=10.151.138.0, ipv4=10.151.137.255 -#ifndef ANDROID_gki - if (tip[0] == ipv4[0] && tip[1] == ipv4[1] && (tip[2]&0xFC) == (ipv4[2]&0xFC) && tip[3] != ipv4[3]) - reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), net, *((__be32 *)tip), sha, default_modem_addr, sha); -#endif - - if (reply) { - skb_reset_mac_header(reply); - __skb_pull(reply, skb_network_offset(reply)); - reply->ip_summed = CHECKSUM_UNNECESSARY; - reply->pkt_type = PACKET_HOST; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) - netif_rx(reply); -#else - netif_rx_ni(reply); -#endif - } - return 1; - } - - return 0; -} - -static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4, unsigned char *bridge_mac) { - struct ethhdr *ehdr; - const struct iphdr *iph; - - skb_reset_mac_header(skb); - ehdr = eth_hdr(skb); - - if (ehdr->h_proto == htons(ETH_P_ARP)) { - if (bridge_ipv4) - bridge_arp_reply(net, skb, bridge_ipv4); - return NULL; - } - - iph = ip_hdr(skb); - //DBG("iphdr: "); - //PrintHex((void *)iph, sizeof(struct iphdr)); - -// 1 0.000000000 0.0.0.0 255.255.255.255 DHCP 362 DHCP Request - Transaction ID 0xe7643ad7 - if (ehdr->h_proto == htons(ETH_P_IP) && iph->protocol == IPPROTO_UDP && iph->saddr == 0x00000000 && iph->daddr == 0xFFFFFFFF) { - //if (udp_hdr(skb)->dest == htons(67)) //DHCP Request - { - memcpy(bridge_mac, ehdr->h_source, ETH_ALEN); - pr_info("%s PC Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net), - bridge_mac[0], bridge_mac[1], bridge_mac[2], bridge_mac[3], bridge_mac[4], bridge_mac[5]); - } - } - - if (memcmp(ehdr->h_source, bridge_mac, ETH_ALEN)) { - return NULL; - } - - return skb; -} - -static void bridge_mode_rx_fixup(struct mhi_netdev *mhi_netdev, struct net_device *net, struct sk_buff *skb) { - uint bridge_mode = 0; - unsigned char *bridge_mac; - - if (mhi_netdev->qmap_mode > 0) { - struct qmap_priv *priv = netdev_priv(net); - bridge_mode = priv->bridge_mode; - bridge_mac = priv->bridge_mac; - } - else { - bridge_mode = mhi_netdev->bridge_mode; - bridge_mac = mhi_netdev->bridge_mac; - } - - if (bridge_mode) - memcpy(eth_hdr(skb)->h_dest, bridge_mac, ETH_ALEN); -} - -static ssize_t bridge_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *ndev = to_net_dev(dev); - uint bridge_mode = 0; - - if (is_qmap_netdev(ndev)) { - struct qmap_priv *priv = netdev_priv(ndev); - bridge_mode = priv->bridge_mode; - } - else { - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - bridge_mode = mhi_netdev->bridge_mode; - } - - return snprintf(buf, PAGE_SIZE, "%u\n", bridge_mode); -} - -static ssize_t bridge_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *ndev = to_net_dev(dev); - uint bridge_mode = simple_strtoul(buf, NULL, 0); - - if (ndev->type != ARPHRD_ETHER) { - if (bridge_mode) - netdev_err(ndev, "netdevice is not ARPHRD_ETHER\n"); - return count; - } - - if (is_qmap_netdev(ndev)) { - struct qmap_priv *priv = netdev_priv(ndev); - priv->bridge_mode = bridge_mode; - } - else { - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - mhi_netdev->bridge_mode = bridge_mode; - } - - return count; -} - - -static ssize_t bridge_ipv4_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *ndev = to_net_dev(dev); - unsigned int bridge_ipv4 = 0; - unsigned char ipv4[4]; - - if (is_qmap_netdev(ndev)) { - struct qmap_priv *priv = netdev_priv(ndev); - bridge_ipv4 = priv->bridge_ipv4; - } - else { - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - bridge_ipv4 = mhi_netdev->bridge_ipv4; - } - - ipv4[0] = (bridge_ipv4 >> 24) & 0xFF; - ipv4[1] = (bridge_ipv4 >> 16) & 0xFF; - ipv4[2] = (bridge_ipv4 >> 8) & 0xFF; - ipv4[3] = (bridge_ipv4 >> 0) & 0xFF; - - return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3]); -} - -static ssize_t bridge_ipv4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *ndev = to_net_dev(dev); - - if (is_qmap_netdev(ndev)) { - struct qmap_priv *priv = netdev_priv(ndev); - priv->bridge_ipv4 = simple_strtoul(buf, NULL, 16); - } - else { - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - mhi_netdev->bridge_ipv4 = simple_strtoul(buf, NULL, 16); - } - - return count; -} - -static DEVICE_ATTR(bridge_mode, S_IWUSR | S_IRUGO, bridge_mode_show, bridge_mode_store); -static DEVICE_ATTR(bridge_ipv4, S_IWUSR | S_IRUGO, bridge_ipv4_show, bridge_ipv4_store); - -#ifndef MHI_NETDEV_ONE_CARD_MODE -static struct attribute *pcie_mhi_qmap_sysfs_attrs[] = { - &dev_attr_bridge_mode.attr, - &dev_attr_bridge_ipv4.attr, - NULL, -}; - -static struct attribute_group pcie_mhi_qmap_sysfs_attr_group = { - .attrs = pcie_mhi_qmap_sysfs_attrs, -}; -#endif -#endif - -static struct sk_buff * add_mbim_hdr(struct sk_buff *skb, u8 mux_id) { - struct mhi_mbim_hdr *mhdr; - __le32 sign; - u8 *c; - u16 tci = mux_id - QUECTEL_QMAP_MUX_ID; - unsigned int skb_len = skb->len; - - if (qmap_mode > 1) - tci += 1; //rmnet_mhi0.X map to session X - - if (skb_headroom(skb) < sizeof(struct mhi_mbim_hdr)) { - printk("skb_headroom small! headroom is %u, need %zd\n", skb_headroom(skb), sizeof(struct mhi_mbim_hdr)); - return NULL; - } - - skb_push(skb, sizeof(struct mhi_mbim_hdr)); - - mhdr = (struct mhi_mbim_hdr *)skb->data; - - //printk("%s %p\n", __func__, skb->data); - mhdr->nth16.dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN); - mhdr->nth16.wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16)); -/* - Sequence number. The transmitter of a block shall set this to zero in the first NTB transferred after every 'function reset' event, - and shall increment for every NTB subsequently transferred. - The effect of an out-of-sequence block on the receiver is not specified. - Thespecification allows the receiver to decide whether tocheck the sequence number, - and to decide how to respond if it's incorrect. The sequence number is pri-marily supplied for debugging purposes. -*/ - //mhdr->nth16.wSequence = cpu_to_le16(mhi_netdev->tx_seq++); -/* - Size of this NTB in bytes. Represented in little-endian form. - NTB size (IN/OUT) shall not exceed dwNtbInMaxSize or dwNtbOutMaxSize respectively -*/ - mhdr->nth16.wBlockLength = cpu_to_le16(skb->len); -/* - Offset, in little endian, of the first NDP16 from byte zeroof the NTB. - This value must be a multiple of 4, and must be >= 0x000C -*/ - mhdr->nth16.wNdpIndex = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16)); - - sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN); - c = (u8 *)&sign; - c[3] = tci; - - mhdr->ndp16.dwSignature = sign; - mhdr->ndp16.wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16) * 2); - mhdr->ndp16.wNextNdpIndex = 0; - - mhdr->ndp16.dpe16[0].wDatagramIndex = sizeof(struct mhi_mbim_hdr); - mhdr->ndp16.dpe16[0].wDatagramLength = skb_len; - - mhdr->ndp16.dpe16[1].wDatagramIndex = 0; - mhdr->ndp16.dpe16[1].wDatagramLength = 0; - - return skb; -} - -static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) { - struct qmap_hdr *qhdr; - int pad = 0; - - pad = skb->len%4; - if (pad) { - pad = 4 - pad; - if (skb_tailroom(skb) < pad) { - printk("skb_tailroom small!\n"); - pad = 0; - } - if (pad) - __skb_put(skb, pad); - } - - qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr)); - qhdr->cd_rsvd_pad = pad; - qhdr->mux_id = mux_id; - qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr)); - - return skb; -} - -static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) { - struct rmnet_map_header *map_header; - struct rmnet_map_v5_csum_header *ul_header; - u32 padding, map_datalen; - - map_datalen = skb->len; - padding = map_datalen%4; - if (padding) { - padding = 4 - padding; - if (skb_tailroom(skb) < padding) { - printk("skb_tailroom small!\n"); - padding = 0; - } - if (padding) - __skb_put(skb, padding); - } - - map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); - map_header->cd_bit = 0; - map_header->next_hdr = 1; - map_header->pad_len = padding; - map_header->mux_id = mux_id; - map_header->pkt_len = htons(map_datalen + padding); - - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - memset(ul_header, 0, sizeof(*ul_header)); - ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD; - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if 0 //TODO - skb->ip_summed = CHECKSUM_NONE; - /* Ask for checksum offloading */ - ul_header->csum_valid_required = 1; -#endif - } - - return skb; -} - -static void rmnet_map_send_ack(struct mhi_netdev *pQmapDev, - unsigned char type, - struct rmnet_map_header *map_header) -{ - struct rmnet_map_control_command *cmd; - struct sk_buff *skb; - size_t skb_len = sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_control_command); - - skb = alloc_skb(skb_len, GFP_ATOMIC); - if (!skb) - return; - - skb_put(skb, skb_len); - memcpy(skb->data, map_header, skb_len); - cmd = (struct rmnet_map_control_command *)(skb->data + sizeof(struct rmnet_map_header)); - cmd->cmd_type = type & 0x03; - skb->protocol = htons(ETH_P_MAP); - skb->dev = pQmapDev->ndev; - dev_queue_xmit(skb); -} - -static int rmnet_data_vnd_do_flow_control(struct net_device *dev, - uint32_t map_flow_id, - uint16_t v4_seq, - uint16_t v6_seq, - int enable) -{ - //TODO - return 0; -} - -static uint8_t rmnet_map_do_flow_control(struct mhi_netdev *pQmapDev, - struct rmnet_map_header *map_header, - int enable) { - struct net_device *ndev = pQmapDev->ndev; - struct rmnet_map_control_command *cmd; - struct net_device *vnd; - uint8_t mux_id; - uint16_t ip_family; - uint16_t fc_seq; - uint32_t qos_id; - int r; - - cmd = (struct rmnet_map_control_command *)(map_header + 1); - - mux_id = map_header->mux_id - QUECTEL_QMAP_MUX_ID; - if (mux_id >= pQmapDev->qmap_mode) { - netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - return RMNET_MAP_COMMAND_UNSUPPORTED; - } - - vnd = pQmapDev->mpQmapNetDev[mux_id]; - if (vnd == NULL) { - netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - return RMNET_MAP_COMMAND_UNSUPPORTED; - } - - ip_family = cmd->flow_control.ip_family; - fc_seq = ntohs(cmd->flow_control.flow_control_seq_num); - qos_id = ntohl(cmd->flow_control.qos_id); - - if (enable) - pQmapDev->flow_control |= (1 << mux_id); - else - pQmapDev->flow_control &= ~(1 << mux_id); - /* Ignore the ip family and pass the sequence number for both v4 and v6 - * sequence. User space does not support creating dedicated flows for - * the 2 protocols - */ - r = rmnet_data_vnd_do_flow_control(vnd, qos_id, fc_seq, fc_seq, enable); - netdev_dbg(vnd, "qos_id:0x%08X, ip_family:%hd, fc_seq %hd, en:%d", - qos_id, ip_family & 3, fc_seq, enable); - - return RMNET_MAP_COMMAND_ACK; -} - -static void rmnet_data_map_command(struct mhi_netdev *pQmapDev, - struct rmnet_map_header *map_header) { - struct net_device *ndev = pQmapDev->ndev; - struct rmnet_map_control_command *cmd; - unsigned char command_name; - unsigned char rc = 0; - - cmd = (struct rmnet_map_control_command *)(map_header + 1); - command_name = cmd->command_name; - - if (command_name < RMNET_MAP_COMMAND_ENUM_LENGTH) - pQmapDev->rmnet_map_command_stats[command_name]++; - - switch (command_name) { - case RMNET_MAP_COMMAND_FLOW_ENABLE: - rc = rmnet_map_do_flow_control(pQmapDev, map_header, 1); - break; - - case RMNET_MAP_COMMAND_FLOW_DISABLE: - rc = rmnet_map_do_flow_control(pQmapDev, map_header, 0); - break; - - default: - pQmapDev->rmnet_map_command_stats[RMNET_MAP_COMMAND_UNKNOWN]++; - netdev_info(ndev, "UNSupport MAP command: %d", command_name); - rc = RMNET_MAP_COMMAND_UNSUPPORTED; - break; - } - - if (rc == RMNET_MAP_COMMAND_ACK) - rmnet_map_send_ack(pQmapDev, rc, map_header); - - return; -} - -#ifndef MHI_NETDEV_ONE_CARD_MODE -static void rmnet_vnd_upate_rx_stats(struct net_device *net, - unsigned rx_packets, unsigned rx_bytes) { -#if defined(MHI_NETDEV_STATUS64) - struct qmap_priv *dev = netdev_priv(net); - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); - - u64_stats_update_begin(&stats64->syncp); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) - stats64->rx_packets += rx_packets; - stats64->rx_bytes += rx_bytes; -#else - u64_stats_add(&stats64->rx_packets, rx_packets); - u64_stats_add(&stats64->rx_bytes, rx_bytes); -#endif - u64_stats_update_end(&stats64->syncp); -#else - priv->self_dev->stats.rx_packets += rx_packets; - priv->self_dev->stats.rx_bytes += rx_bytes; -#endif -} - -static void rmnet_vnd_upate_tx_stats(struct net_device *net, - unsigned tx_packets, unsigned tx_bytes) { -#if defined(MHI_NETDEV_STATUS64) - struct qmap_priv *dev = netdev_priv(net); - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); - - u64_stats_update_begin(&stats64->syncp); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) - stats64->tx_packets += tx_packets; - stats64->tx_bytes += tx_bytes; -#else - u64_stats_add(&stats64->tx_packets, tx_packets); - u64_stats_add(&stats64->tx_bytes, tx_bytes); -#endif - u64_stats_update_end(&stats64->syncp); -#else - net->stats.rx_packets += tx_packets; - net->stats.rx_bytes += tx_bytes; -#endif -} - -#if defined(MHI_NETDEV_STATUS64) -#ifdef ANDROID_gki -static void _netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, - const struct net_device_stats *netdev_stats) -{ -#if BITS_PER_LONG == 64 - BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats)); - memcpy(stats64, netdev_stats, sizeof(*netdev_stats)); - /* zero out counters that only exist in rtnl_link_stats64 */ - memset((char *)stats64 + sizeof(*netdev_stats), 0, - sizeof(*stats64) - sizeof(*netdev_stats)); -#else - size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long); - const unsigned long *src = (const unsigned long *)netdev_stats; - u64 *dst = (u64 *)stats64; - - BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64)); - for (i = 0; i < n; i++) - dst[i] = src[i]; - /* zero out counters that only exist in rtnl_link_stats64 */ - memset((char *)stats64 + n * sizeof(u64), 0, - sizeof(*stats64) - n * sizeof(u64)); -#endif -} -#else -static void my_netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, - const struct net_device_stats *netdev_stats) -{ - netdev_stats_to_stats64(stats64, netdev_stats); -} -#endif - -static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) -{ - struct qmap_priv *dev = netdev_priv(net); - unsigned int start; - int cpu; - - my_netdev_stats_to_stats64(stats, &net->stats); - - if (nss_cb && dev->use_qca_nss) { // rmnet_nss.c:rmnet_nss_tx() will update rx stats - stats->rx_packets = 0; - stats->rx_bytes = 0; - } - - for_each_possible_cpu(cpu) { - struct pcpu_sw_netstats *stats64; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) - u64 rx_packets, rx_bytes; - u64 tx_packets, tx_bytes; - - stats64 = per_cpu_ptr(dev->stats64, cpu); - - do { - start = u64_stats_fetch_begin_irq(&stats64->syncp); - rx_packets = stats64->rx_packets; - rx_bytes = stats64->rx_bytes; - tx_packets = stats64->tx_packets; - tx_bytes = stats64->tx_bytes; - } while (u64_stats_fetch_retry_irq(&stats64->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; - stats->tx_packets += tx_packets; - stats->tx_bytes += tx_bytes; -#else - u64_stats_t rx_packets, rx_bytes; - u64_stats_t tx_packets, tx_bytes; - - stats64 = per_cpu_ptr(dev->stats64, cpu); - - do { - start = u64_stats_fetch_begin(&stats64->syncp); - rx_packets = stats64->rx_packets; - rx_bytes = stats64->rx_bytes; - tx_packets = stats64->tx_packets; - tx_bytes = stats64->tx_bytes; - } while (u64_stats_fetch_retry(&stats64->syncp, start)); - - stats->rx_packets += u64_stats_read(&rx_packets); - stats->rx_bytes += u64_stats_read(&rx_bytes); - stats->tx_packets += u64_stats_read(&tx_packets); - stats->tx_bytes += u64_stats_read(&tx_bytes); -#endif - } - - return stats; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,10,0 )) //bc1f44709cf27fb2a5766cadafe7e2ad5e9cb221 -static void rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { - _rmnet_vnd_get_stats64(net, stats); -} -#else -static struct rtnl_link_stats64 *rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { - return _rmnet_vnd_get_stats64(net, stats); -} -#endif -#endif - -static void rmnet_vnd_tx_agg_work(struct work_struct *work) -{ - struct qmap_priv *priv = - container_of(work, struct qmap_priv, agg_wq); - struct sk_buff *skb = NULL; - unsigned long flags; - - spin_lock_irqsave(&priv->agg_lock, flags); - if (likely(priv->agg_skb)) { - skb = priv->agg_skb; - priv->agg_skb = NULL; - priv->agg_count = 0; - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - ktime_get_ts64(&priv->agg_time); - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - - if (skb) - dev_queue_xmit(skb); -} - -static enum hrtimer_restart rmnet_vnd_tx_agg_timer_cb(struct hrtimer *timer) -{ - struct qmap_priv *priv = - container_of(timer, struct qmap_priv, agg_hrtimer); - - schedule_work(&priv->agg_wq); - return HRTIMER_NORESTART; -} - -static int rmnet_vnd_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) { - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - - return dev_queue_xmit(skb); -} - - -static int rmnet_vnd_open(struct net_device *dev) -{ - struct qmap_priv *priv = netdev_priv(dev); - struct net_device *real_dev = priv->real_dev; - - if (!(priv->real_dev->flags & IFF_UP)) - return -ENETDOWN; - - if (netif_carrier_ok(real_dev)) - netif_carrier_on(dev); - - return 0; -} - -static int rmnet_vnd_stop(struct net_device *pNet) -{ - netif_carrier_off(pNet); - return 0; -} - -static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, - struct net_device *pNet) -{ - int err; - struct qmap_priv *priv = netdev_priv(pNet); - struct mhi_netdev *mhi_netdev = ndev_to_mhi(priv->real_dev); - int skb_len = skb->len; - - if (netif_queue_stopped(priv->real_dev)) { - netif_stop_queue(pNet); - return NETDEV_TX_BUSY; - } - - //printk("%s 1 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - if (pNet->type == ARPHRD_ETHER) { - skb_reset_mac_header(skb); - -#ifdef QUECTEL_BRIDGE_MODE - if (priv->bridge_mode && bridge_mode_tx_fixup(pNet, skb, priv->bridge_ipv4, priv->bridge_mac) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } -#endif - - if (skb_pull(skb, ETH_HLEN) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - //printk("%s 2 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - if (mhi_netdev->net_type == MHI_NET_MBIM) { - if (add_mbim_hdr(skb, priv->mux_id) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - else { - if (priv->qmap_version == 5) { - add_qhdr(skb, priv->mux_id); - } - else if (priv->qmap_version == 9) { - add_qhdr_v5(skb, priv->mux_id); - } - else { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - err = rmnet_vnd_tx_agg(skb, priv); - if (err == NET_XMIT_SUCCESS) { - rmnet_vnd_upate_tx_stats(pNet, 1, skb_len); - } else { - pNet->stats.tx_errors++; - } - - return err; -} - -static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu) -{ - struct mhi_netdev *mhi_netdev; - - mhi_netdev = (struct mhi_netdev *)ndev_to_mhi(rmnet_dev); - - if (mhi_netdev == NULL) { - printk("warning, mhi_netdev == null\n"); - return -EINVAL; - } - - if (new_mtu < 0 ) - return -EINVAL; - - if (new_mtu > mhi_netdev->max_mtu) { - printk("warning, set mtu=%d greater than max mtu=%d\n", new_mtu, mhi_netdev->max_mtu); - return -EINVAL; - } - - rmnet_dev->mtu = new_mtu; - return 0; -} - -/* drivers may override default ethtool_ops in their bind() routine */ -static const struct ethtool_ops rmnet_vnd_ethtool_ops = { - .get_link = ethtool_op_get_link, -}; - -static void rmnet_vnd_rawip_setup(struct net_device *rmnet_dev) -{ - rmnet_dev->needed_headroom = 16; - - /* Raw IP mode */ - rmnet_dev->header_ops = NULL; /* No header */ -//for Qualcomm's NSS, must set type as ARPHRD_RAWIP, or NSS performace is very bad. - rmnet_dev->type = ARPHRD_RAWIP; // do not support moify mac, for dev_set_mac_address() need ARPHRD_ETHER - rmnet_dev->hard_header_len = 0; -//for Qualcomm's SFE, do not add IFF_POINTOPOINT to type, or SFE donot work. - rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); -} - -static const struct net_device_ops rmnet_vnd_ops = { - .ndo_open = rmnet_vnd_open, - .ndo_stop = rmnet_vnd_stop, - .ndo_start_xmit = rmnet_vnd_start_xmit, -#if defined(MHI_NETDEV_STATUS64) - .ndo_get_stats64 = rmnet_vnd_get_stats64, -#endif - .ndo_change_mtu = rmnet_vnd_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static rx_handler_result_t qca_nss_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - - if (!skb) - return RX_HANDLER_CONSUMED; - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - /* Check this so that we dont loop around netif_receive_skb */ - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - return RX_HANDLER_PASS; - } - - if (nss_cb) { - nss_cb->nss_tx(skb); - return RX_HANDLER_CONSUMED; - } - - return RX_HANDLER_PASS; -} -#endif - -static void rmnet_mbim_rx_handler(void *dev, struct sk_buff *skb_in) -{ - struct mhi_netdev *pQmapDev = (struct mhi_netdev *)dev; - struct mhi_netdev *mhi_netdev = (struct mhi_netdev *)dev; - MHI_MBIM_CTX *ctx = &pQmapDev->mbim_ctx; - //struct net_device *ndev = pQmapDev->ndev; - struct usb_cdc_ncm_nth16 *nth16; - int ndpoffset, len; - u16 wSequence; - struct sk_buff_head skb_chain; - struct sk_buff *qmap_skb; - - __skb_queue_head_init(&skb_chain); - - if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16))) { - MSG_ERR("frame too short\n"); - goto error; - } - - nth16 = (struct usb_cdc_ncm_nth16 *)skb_in->data; - - if (nth16->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN)) { - MSG_ERR("invalid NTH16 signature <%#010x>\n", le32_to_cpu(nth16->dwSignature)); - goto error; - } - - len = le16_to_cpu(nth16->wBlockLength); - if (len > ctx->rx_max) { - MSG_ERR("unsupported NTB block length %u/%u\n", len, ctx->rx_max); - goto error; - } - - wSequence = le16_to_cpu(nth16->wSequence); - if (ctx->rx_seq != wSequence) { - MSG_ERR("sequence number glitch prev=%d curr=%d\n", ctx->rx_seq, wSequence); - } - ctx->rx_seq = wSequence + 1; - - ndpoffset = nth16->wNdpIndex; - - while (ndpoffset > 0) { - struct usb_cdc_ncm_ndp16 *ndp16 ; - struct usb_cdc_ncm_dpe16 *dpe16; - int nframes, x; - u8 *c; - u16 tci = 0; - struct net_device *qmap_net; - - if (skb_in->len < (ndpoffset + sizeof(struct usb_cdc_ncm_ndp16))) { - MSG_ERR("invalid NDP offset <%u>\n", ndpoffset); - goto error; - } - - ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset); - - if (le16_to_cpu(ndp16->wLength) < 0x10) { - MSG_ERR("invalid DPT16 length <%u>\n", le16_to_cpu(ndp16->wLength)); - goto error; - } - - nframes = ((le16_to_cpu(ndp16->wLength) - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16)); - - if (skb_in->len < (sizeof(struct usb_cdc_ncm_ndp16) + nframes * (sizeof(struct usb_cdc_ncm_dpe16)))) { - MSG_ERR("Invalid nframes = %d\n", nframes); - goto error; - } - - switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) { - case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN): - c = (u8 *)&ndp16->dwSignature; - tci = c[3]; - /* tag IPS<0> packets too if MBIM_IPS0_VID exists */ - //if (!tci && info->flags & FLAG_IPS0_VLAN) - // tci = MBIM_IPS0_VID; - break; - case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN): - c = (u8 *)&ndp16->dwSignature; - tci = c[3] + 256; - break; - default: - MSG_ERR("unsupported NDP signature <0x%08x>\n", le32_to_cpu(ndp16->dwSignature)); - goto error; - } - - if ((qmap_mode == 1 && tci != 0) || (qmap_mode > 1 && tci > qmap_mode)) { - MSG_ERR("unsupported tci %d by now\n", tci); - goto error; - } - tci = abs(tci); - qmap_net = pQmapDev->mpQmapNetDev[qmap_mode == 1 ? 0 : tci - 1]; - - dpe16 = ndp16->dpe16; - - for (x = 0; x < nframes; x++, dpe16++) { - int offset = le16_to_cpu(dpe16->wDatagramIndex); - int skb_len = le16_to_cpu(dpe16->wDatagramLength); - - if (offset == 0 || skb_len == 0) { - break; - } - - /* sanity checking */ - if (((offset + skb_len) > skb_in->len) || (skb_len > ctx->rx_max)) { - MSG_ERR("invalid frame detected (ignored) x=%d, offset=%d, skb_len=%u\n", x, offset, skb_len); - goto error; - } - - qmap_skb = netdev_alloc_skb(qmap_net, skb_len); - if (!qmap_skb) { - mhi_netdev->stats.alloc_failed++; - //MSG_ERR("skb_clone fail\n"); //do not print in softirq - goto error; - } - - switch (skb_in->data[offset] & 0xf0) { - case 0x40: -#ifdef CONFIG_QCA_NSS_PACKET_FILTER - { - struct iphdr *ip4h = (struct iphdr *)(&skb_in->data[offset]); - if (ip4h->protocol == IPPROTO_ICMP) { - qmap_skb->cb[0] = 1; - } - } -#endif - qmap_skb->protocol = htons(ETH_P_IP); - break; - case 0x60: -#ifdef CONFIG_QCA_NSS_PACKET_FILTER - { - struct ipv6hdr *ip6h = (struct ipv6hdr *)(&skb_in->data[offset]); - if (ip6h->nexthdr == NEXTHDR_ICMP) { - qmap_skb->cb[0] = 1; - } - } -#endif - qmap_skb->protocol = htons(ETH_P_IPV6); - break; - default: - MSG_ERR("unknow skb->protocol %02x\n", skb_in->data[offset]); - goto error; - } - - skb_put(qmap_skb, skb_len); - memcpy(qmap_skb->data, skb_in->data + offset, skb_len); - - skb_reset_transport_header(qmap_skb); - skb_reset_network_header(qmap_skb); - qmap_skb->pkt_type = PACKET_HOST; - skb_set_mac_header(qmap_skb, 0); - - if (qmap_skb->dev->type == ARPHRD_ETHER) { - skb_push(qmap_skb, ETH_HLEN); - skb_reset_mac_header(qmap_skb); - memcpy(eth_hdr(qmap_skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(qmap_skb)->h_dest, qmap_net->dev_addr, ETH_ALEN); - eth_hdr(qmap_skb)->h_proto = qmap_skb->protocol; -#ifdef QUECTEL_BRIDGE_MODE - bridge_mode_rx_fixup(pQmapDev, qmap_net, qmap_skb); -#endif - __skb_pull(qmap_skb, ETH_HLEN); - } - -#ifndef MHI_NETDEV_ONE_CARD_MODE - rmnet_vnd_upate_rx_stats(qmap_net, 1, skb_len); -#endif - __skb_queue_tail(&skb_chain, qmap_skb); - } - - /* are there more NDPs to process? */ - ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex); - } - -error: - while ((qmap_skb = __skb_dequeue (&skb_chain))) { - netif_receive_skb(qmap_skb); - } -} - -static void rmnet_qmi_rx_handler(void *dev, struct sk_buff *skb_in) -{ - struct mhi_netdev *pQmapDev = (struct mhi_netdev *)dev; - struct net_device *ndev = pQmapDev->ndev; - struct sk_buff *qmap_skb; - struct sk_buff_head skb_chain; - uint dl_minimum_padding = 0; - - if (pQmapDev->qmap_version == 9) - dl_minimum_padding = pQmapDev->dl_minimum_padding; - - __skb_queue_head_init(&skb_chain); - - while (skb_in->len > sizeof(struct qmap_hdr)) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb_in->data; - struct rmnet_map_v5_csum_header *ul_header = NULL; - size_t hdr_size = sizeof(struct rmnet_map_header); - struct net_device *qmap_net; - int pkt_len = ntohs(map_header->pkt_len); - int skb_len; - __be16 protocol; - int mux_id; - int skip_nss = 0; - - if (map_header->next_hdr) { - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - hdr_size += sizeof(struct rmnet_map_v5_csum_header); - } - - skb_len = pkt_len - (map_header->pad_len&0x3F); -#if 0 //just for debug dl_minimum_padding BUG - if ((skb_in->data[hdr_size] & 0xf0) == 0x45) { - struct iphdr *ip4h = (struct iphdr *)(&skb_in->data[hdr_size]); - if (ntohs(ip4h->tot_len) != skb_len) { - netdev_info(ndev, "tot_len=%d skb_len=%d\n", ntohs(ip4h->tot_len), skb_len); - } - } -#endif - skb_len -= dl_minimum_padding; - - mux_id = map_header->mux_id - QUECTEL_QMAP_MUX_ID; - if (mux_id >= pQmapDev->qmap_mode) { - netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - goto error_pkt; - } - mux_id = abs(mux_id); - qmap_net = pQmapDev->mpQmapNetDev[mux_id]; - if (qmap_net == NULL) { - netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id); - goto skip_pkt; - } - - if (skb_len > qmap_net->mtu) { - netdev_info(ndev, "drop skb_len=%x larger than qmap mtu=%d\n", skb_len, qmap_net->mtu); - goto error_pkt; - } - - if (skb_in->len < (pkt_len + hdr_size)) { - netdev_info(ndev, "drop qmap unknow pkt, len=%d, pkt_len=%d\n", skb_in->len, pkt_len); - goto error_pkt; - } - - if (map_header->cd_bit) { - rmnet_data_map_command(pQmapDev, map_header); - goto skip_pkt; - } - - switch (skb_in->data[hdr_size] & 0xf0) { - case 0x40: -#ifdef CONFIG_QCA_NSS_PACKET_FILTER - { - struct iphdr *ip4h = (struct iphdr *)(&skb_in->data[hdr_size]); - if (ip4h->protocol == IPPROTO_ICMP) { - skip_nss = 1; - } - } -#endif - protocol = htons(ETH_P_IP); - break; - case 0x60: -#ifdef CONFIG_QCA_NSS_PACKET_FILTER - { - struct ipv6hdr *ip6h = (struct ipv6hdr *)(&skb_in->data[hdr_size]); - if (ip6h->nexthdr == NEXTHDR_ICMP) { - skip_nss = 1; - } - } -#endif - protocol = htons(ETH_P_IPV6); - break; - default: - netdev_info(ndev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]); - goto error_pkt; - } - -//for Qualcomm's SFE, do not use skb_clone(), or SFE 's performace is very bad. -//for Qualcomm's NSS, do not use skb_clone(), or NSS 's performace is very bad. - qmap_skb = netdev_alloc_skb(qmap_net, skb_len); - if (qmap_skb) { - skb_put(qmap_skb, skb_len); - memcpy(qmap_skb->data, skb_in->data + hdr_size, skb_len); - } - - if (qmap_skb == NULL) { - pQmapDev->stats.alloc_failed++; - //netdev_info(ndev, "fail to alloc skb, pkt_len = %d\n", skb_len); //do not print in softirq - goto error_pkt; - } - - skb_reset_transport_header(qmap_skb); - skb_reset_network_header(qmap_skb); - qmap_skb->pkt_type = PACKET_HOST; - skb_set_mac_header(qmap_skb, 0); - qmap_skb->protocol = protocol; - - if(skip_nss) - qmap_skb->cb[0] = 1; - - if (ul_header && ul_header->header_type == RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD - && ul_header->csum_valid_required) { -#if 0 //TODO - qmap_skb->ip_summed = CHECKSUM_UNNECESSARY; -#endif - } - - if (qmap_skb->dev->type == ARPHRD_ETHER) { - skb_push(qmap_skb, ETH_HLEN); - skb_reset_mac_header(qmap_skb); - memcpy(eth_hdr(qmap_skb)->h_source, default_modem_addr, ETH_ALEN); - memcpy(eth_hdr(qmap_skb)->h_dest, qmap_net->dev_addr, ETH_ALEN); - eth_hdr(qmap_skb)->h_proto = protocol; -#ifdef QUECTEL_BRIDGE_MODE - bridge_mode_rx_fixup(pQmapDev, qmap_net, qmap_skb); -#endif - __skb_pull(qmap_skb, ETH_HLEN); - } - -#ifndef MHI_NETDEV_ONE_CARD_MODE - rmnet_vnd_upate_rx_stats(qmap_net, 1, skb_len); -#endif - __skb_queue_tail(&skb_chain, qmap_skb); - -skip_pkt: - skb_pull(skb_in, pkt_len + hdr_size); - } - -error_pkt: - while ((qmap_skb = __skb_dequeue (&skb_chain))) { - netif_receive_skb(qmap_skb); - } -} - -#ifndef MHI_NETDEV_ONE_CARD_MODE -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct mhi_netdev *mhi_netdev; - - if (!skb) - goto done; - - //printk("%s skb=%p, protocol=%x, len=%d\n", __func__, skb, skb->protocol, skb->len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - if (skb->protocol != htons(ETH_P_MAP)) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - /* when open hyfi function, run cm will make system crash */ - //dev = rcu_dereference(skb->dev->rx_handler_data); - mhi_netdev = (struct mhi_netdev *)ndev_to_mhi(skb->dev); - - if (mhi_netdev == NULL) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - - if (mhi_netdev->net_type == MHI_NET_MBIM) - rmnet_mbim_rx_handler(mhi_netdev, skb); - else - rmnet_qmi_rx_handler(mhi_netdev, skb); - - if (!skb_cloned(skb)) { - if (skb_queue_len(&mhi_netdev->rx_allocated) < 128) { - skb->data = skb->head; - skb_reset_tail_pointer(skb); - skb->len = 0; - skb_queue_tail(&mhi_netdev->rx_allocated, skb); - return RX_HANDLER_CONSUMED; - } - } - - consume_skb(skb); - -done: - return RX_HANDLER_CONSUMED; -} - -static struct net_device * rmnet_vnd_register_device(struct mhi_netdev *pQmapDev, u8 offset_id, u8 mux_id) -{ - struct net_device *real_dev = pQmapDev->ndev; - struct net_device *qmap_net; - struct qmap_priv *priv; - int err; - int use_qca_nss = !!nss_cb; - unsigned char temp_addr[ETH_ALEN]; - - qmap_net = alloc_etherdev(sizeof(*priv)); - if (!qmap_net) - return NULL; - - SET_NETDEV_DEV(qmap_net, &real_dev->dev); - priv = netdev_priv(qmap_net); - priv->offset_id = offset_id; - priv->real_dev = pQmapDev->ndev; - priv->self_dev = qmap_net; - priv->pQmapDev = pQmapDev; - priv->qmap_version = pQmapDev->qmap_version; - priv->mux_id = mux_id; - sprintf(qmap_net->name, "%.12s.%d", real_dev->name, offset_id + 1); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) - __dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN); -#else - memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); -#endif - //qmap_net->dev_addr[5] = offset_id + 1; - //eth_random_addr(qmap_net->dev_addr); - memcpy(temp_addr, qmap_net->dev_addr, ETH_ALEN); - temp_addr[5] = offset_id + 1; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) - __dev_addr_set(qmap_net, temp_addr, ETH_ALEN); -#else - memcpy(qmap_net->dev_addr, temp_addr, ETH_ALEN); -#endif -#if defined(MHI_NETDEV_STATUS64) - priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!priv->stats64) - goto out_free_newdev; -#endif - -#ifdef QUECTEL_BRIDGE_MODE - priv->bridge_mode = !!(pQmapDev->bridge_mode & BIT(offset_id)); - qmap_net->sysfs_groups[0] = &pcie_mhi_qmap_sysfs_attr_group; - if (priv->bridge_mode) - use_qca_nss = 0; -#endif - - priv->agg_skb = NULL; - priv->agg_count = 0; - hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - priv->agg_hrtimer.function = rmnet_vnd_tx_agg_timer_cb; - INIT_WORK(&priv->agg_wq, rmnet_vnd_tx_agg_work); - ktime_get_ts64(&priv->agg_time); - spin_lock_init(&priv->agg_lock); - priv->use_qca_nss = 0; - - qmap_net->ethtool_ops = &rmnet_vnd_ethtool_ops; - qmap_net->netdev_ops = &rmnet_vnd_ops; - qmap_net->flags |= IFF_NOARP; - qmap_net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - qmap_net->max_mtu = pQmapDev->max_mtu; -#endif - - if (nss_cb && use_qca_nss) { - rmnet_vnd_rawip_setup(qmap_net); - } -#ifdef CONFIG_PINCTRL_IPQ9574 - rmnet_vnd_rawip_setup(qmap_net); -#endif - if (pQmapDev->net_type == MHI_NET_MBIM) { - qmap_net->needed_headroom = sizeof(struct mhi_mbim_hdr); - } - - err = register_netdev(qmap_net); - pr_info("%s(%s)=%d\n", __func__, qmap_net->name, err); - if (err == -EEXIST) { - //'ifdown wan' for openwrt, why? - } - if (err < 0) - goto out_free_newdev; - - netif_device_attach (qmap_net); - netif_carrier_off(qmap_net); - - if (nss_cb && use_qca_nss) { - int rc = nss_cb->nss_create(qmap_net); - WARN_ON(rc); - if (rc) { - /* Log, but don't fail the device creation */ - netdev_err(qmap_net, "Device will not use NSS path: %d\n", rc); - } else { - priv->use_qca_nss = 1; - netdev_info(qmap_net, "NSS context created\n"); - rtnl_lock(); - netdev_rx_handler_register(qmap_net, qca_nss_rx_handler, NULL); - rtnl_unlock(); - } - } - - return qmap_net; - -out_free_newdev: - free_netdev(qmap_net); - return qmap_net; -} - -static void rmnet_vnd_unregister_device(struct net_device *qmap_net) { - struct qmap_priv *priv; - unsigned long flags; - - pr_info("%s(%s)\n", __func__, qmap_net->name); - netif_carrier_off(qmap_net); - - priv = netdev_priv(qmap_net); - hrtimer_cancel(&priv->agg_hrtimer); - cancel_work_sync(&priv->agg_wq); - - spin_lock_irqsave(&priv->agg_lock, flags); - if (priv->agg_skb) { - kfree_skb(priv->agg_skb); - priv->agg_skb = NULL; - priv->agg_count = 0; - } - spin_unlock_irqrestore(&priv->agg_lock, flags); - - if (nss_cb && priv->use_qca_nss) { - rtnl_lock(); - netdev_rx_handler_unregister(qmap_net); - rtnl_unlock(); - nss_cb->nss_free(qmap_net); - } -#if defined(MHI_NETDEV_STATUS64) - free_percpu(priv->stats64); -#endif - unregister_netdev (qmap_net); - free_netdev(qmap_net); -} -#endif - -static void rmnet_info_set(struct mhi_netdev *pQmapDev, RMNET_INFO *rmnet_info) -{ - rmnet_info->size = sizeof(RMNET_INFO); - rmnet_info->rx_urb_size = pQmapDev->qmap_size; - rmnet_info->ep_type = 3; //DATA_EP_TYPE_PCIE - rmnet_info->iface_id = 4; - rmnet_info->qmap_mode = pQmapDev->qmap_mode; - rmnet_info->qmap_version = pQmapDev->qmap_version; - rmnet_info->dl_minimum_padding = 0; -} - -static ssize_t qmap_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *ndev = to_net_dev(dev); - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - - return snprintf(buf, PAGE_SIZE, "%u\n", mhi_netdev->qmap_mode); -} - -static DEVICE_ATTR(qmap_mode, S_IRUGO, qmap_mode_show, NULL); - -static ssize_t qmap_size_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *ndev = to_net_dev(dev); - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - - return snprintf(buf, PAGE_SIZE, "%u\n", mhi_netdev->qmap_size); -} - -static DEVICE_ATTR(qmap_size, S_IRUGO, qmap_size_show, NULL); - -static ssize_t link_state_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct net_device *ndev = to_net_dev(dev); - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - - return snprintf(buf, PAGE_SIZE, "0x%x\n", mhi_netdev->link_state); -} - -static ssize_t link_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct net_device *ndev = to_net_dev(dev); - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - //struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - unsigned link_state = 0; - unsigned old_link = mhi_netdev->link_state; - uint offset_id = 0; - - link_state = simple_strtoul(buf, NULL, 0); - if (mhi_netdev->qmap_mode > 1) { - offset_id = ((link_state&0xF) - 1); - - if (0 < link_state && link_state <= mhi_netdev->qmap_mode) - mhi_netdev->link_state |= (1 << offset_id); - else if (0x80 < link_state && link_state <= (0x80 + mhi_netdev->qmap_mode)) - mhi_netdev->link_state &= ~(1 << offset_id); - } - else { - mhi_netdev->link_state = !!link_state; - } - - if (old_link != mhi_netdev->link_state) { - struct net_device *qmap_net = mhi_netdev->mpQmapNetDev[offset_id]; - - if (mhi_netdev->link_state) - netif_carrier_on(mhi_netdev->ndev); - else { - netif_carrier_off(mhi_netdev->ndev); - } - - if (qmap_net) { - if (mhi_netdev->link_state & (1 << offset_id)) - netif_carrier_on(qmap_net); - else - netif_carrier_off(qmap_net); - } - - dev_info(dev, "link_state 0x%x -> 0x%x\n", old_link, mhi_netdev->link_state); - } - - return count; -} - -static DEVICE_ATTR(link_state, S_IWUSR | S_IRUGO, link_state_show, link_state_store); - -static struct attribute *pcie_mhi_sysfs_attrs[] = { - &dev_attr_qmap_mode.attr, - &dev_attr_qmap_size.attr, - &dev_attr_link_state.attr, -#ifdef QUECTEL_BRIDGE_MODE - &dev_attr_bridge_mode.attr, - &dev_attr_bridge_ipv4.attr, -#endif - NULL, -}; - -static struct attribute_group pcie_mhi_sysfs_attr_group = { - .attrs = pcie_mhi_sysfs_attrs, -}; - -static void mhi_netdev_upate_rx_stats(struct mhi_netdev *mhi_netdev, - unsigned rx_packets, unsigned rx_bytes) { -#if defined(MHI_NETDEV_STATUS64) - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(mhi_netdev->stats64); - - u64_stats_update_begin(&stats64->syncp); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) - stats64->rx_packets += rx_packets; - stats64->rx_bytes += rx_bytes; -#else - u64_stats_add(&stats64->rx_packets, rx_packets); - u64_stats_add(&stats64->rx_bytes, rx_bytes); -#endif - u64_stats_update_begin(&stats64->syncp); -#else - mhi_netdev->ndev->stats.rx_packets += rx_packets; - mhi_netdev->ndev->stats.rx_bytes += rx_bytes; -#endif -} - -static void mhi_netdev_upate_tx_stats(struct mhi_netdev *mhi_netdev, - unsigned tx_packets, unsigned tx_bytes) { -#if defined(MHI_NETDEV_STATUS64) - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(mhi_netdev->stats64); - - u64_stats_update_begin(&stats64->syncp); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) - stats64->tx_packets += tx_packets; - stats64->tx_bytes += tx_bytes; -#else - u64_stats_add(&stats64->tx_packets, tx_packets); - u64_stats_add(&stats64->tx_bytes, tx_bytes); -#endif - u64_stats_update_begin(&stats64->syncp); -#else - mhi_netdev->ndev->stats.tx_packets += tx_packets; - mhi_netdev->ndev->stats.tx_bytes += tx_bytes; -#endif -} - -static __be16 mhi_netdev_ip_type_trans(u8 data) -{ - __be16 protocol = 0; - - /* determine L3 protocol */ - switch (data & 0xf0) { - case 0x40: - protocol = htons(ETH_P_IP); - break; - case 0x60: - protocol = htons(ETH_P_IPV6); - break; - default: - protocol = htons(ETH_P_MAP); - break; - } - - return protocol; -} - -static int mhi_netdev_alloc_skb(struct mhi_netdev *mhi_netdev, gfp_t gfp_t) -{ - u32 cur_mru = mhi_netdev->mru; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct mhi_skb_priv *skb_priv; - int ret; - struct sk_buff *skb; - int no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - int i; - - for (i = 0; i < no_tre; i++) { - skb = skb_dequeue(&mhi_netdev->rx_allocated); - if (!skb) { - skb = alloc_skb(/*32+*/cur_mru, gfp_t); - if (skb) - mhi_netdev->stats.rx_allocated++; - } - if (!skb) - return -ENOMEM; - - read_lock_bh(&mhi_netdev->pm_lock); - if (unlikely(!mhi_netdev->enabled)) { - MSG_ERR("Interface not enabled\n"); - ret = -EIO; - goto error_queue; - } - - skb_priv = (struct mhi_skb_priv *)skb->cb; - skb_priv->buf = skb->data; - skb_priv->size = cur_mru; - skb_priv->bind_netdev = mhi_netdev; - skb->dev = mhi_netdev->ndev; - //skb_reserve(skb, 32); //for ethernet header - - spin_lock_bh(&mhi_netdev->rx_lock); - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, skb, - skb_priv->size, MHI_EOT); - spin_unlock_bh(&mhi_netdev->rx_lock); - - if (ret) { - skb_priv->bind_netdev = NULL; - MSG_ERR("Failed to queue skb, ret:%d\n", ret); - ret = -EIO; - goto error_queue; - } - - read_unlock_bh(&mhi_netdev->pm_lock); - } - - return 0; - -error_queue: - skb->destructor = NULL; - read_unlock_bh(&mhi_netdev->pm_lock); - dev_kfree_skb_any(skb); - - return ret; -} - -static void mhi_netdev_alloc_work(struct work_struct *work) -{ - struct mhi_netdev *mhi_netdev = container_of(work, struct mhi_netdev, - alloc_work.work); - /* sleep about 1 sec and retry, that should be enough time - * for system to reclaim freed memory back. - */ - const int sleep_ms = 1000; - int retry = 60; - int ret; - - MSG_LOG("Entered\n"); - do { - ret = mhi_netdev_alloc_skb(mhi_netdev, GFP_KERNEL); - /* sleep and try again */ - if (ret == -ENOMEM) { - schedule_delayed_work(&mhi_netdev->alloc_work, msecs_to_jiffies(20)); - return; - msleep(sleep_ms); - retry--; - } - } while (ret == -ENOMEM && retry); - - MSG_LOG("Exit with status:%d retry:%d\n", ret, retry); -} - -static void mhi_netdev_dealloc(struct mhi_netdev *mhi_netdev) -{ - struct sk_buff *skb; - - skb = skb_dequeue(&mhi_netdev->rx_allocated); - while (skb) { - skb->destructor = NULL; - kfree_skb(skb); - skb = skb_dequeue(&mhi_netdev->rx_allocated); - } -} - -static int mhi_netdev_poll(struct napi_struct *napi, int budget) -{ - struct net_device *dev = napi->dev; - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct sk_buff *skb; - int rx_work = 0; - int ret; - - MSG_VERB("Entered\n"); - - rx_work = mhi_poll(mhi_dev, budget); - - if (rx_work < 0) { - MSG_ERR("Error polling ret:%d\n", rx_work); - napi_complete(napi); - return 0; - } - - if (mhi_netdev->net_type == MHI_NET_MBIM || mhi_netdev->net_type == MHI_NET_RMNET) { - while ((skb = skb_dequeue (&mhi_netdev->qmap_chain))) { -#ifdef MHI_NETDEV_ONE_CARD_MODE - int recly_skb = 0; - - mhi_netdev_upate_rx_stats(mhi_netdev, 1, skb->len); - if (mhi_netdev->net_type == MHI_NET_MBIM) - rmnet_mbim_rx_handler(mhi_netdev, skb); - else - rmnet_qmi_rx_handler(mhi_netdev, skb); - - if (!skb_cloned(skb)) { - if (skb_queue_len(&mhi_netdev->rx_allocated) < 128) { - skb->data = skb->head; - skb_reset_tail_pointer(skb); - skb->len = 0; - skb_queue_tail(&mhi_netdev->rx_allocated, skb); - recly_skb = 1; - } - } - if (recly_skb == 0) - dev_kfree_skb(skb); -#else - mhi_netdev_upate_rx_stats(mhi_netdev, 1, skb->len); - skb->dev = mhi_netdev->ndev; - skb->protocol = htons(ETH_P_MAP); - netif_receive_skb(skb); -#endif - } - } - else if (mhi_netdev->net_type == MHI_NET_ETHER) { - while ((skb = skb_dequeue (&mhi_netdev->qmap_chain))) { - mhi_netdev_upate_rx_stats(mhi_netdev, 1, skb->len); - skb->dev = mhi_netdev->ndev; - skb->protocol = mhi_netdev_ip_type_trans(skb->data[0]); - netif_receive_skb(skb); - } - } - - /* queue new buffers */ - if (!delayed_work_pending(&mhi_netdev->alloc_work)) { - ret = mhi_netdev->rx_queue(mhi_netdev, GFP_ATOMIC); - if (ret == -ENOMEM) { - //MSG_LOG("out of tre, queuing bg worker\n"); //do not print in softirq - mhi_netdev->stats.alloc_failed++; - schedule_delayed_work(&mhi_netdev->alloc_work, msecs_to_jiffies(20)); - } - } - - /* complete work if # of packet processed less than allocated budget */ - if (rx_work < budget) - napi_complete(napi); - - MSG_VERB("polled %d pkts\n", rx_work); - - return rx_work; -} - -static int mhi_netdev_open(struct net_device *ndev) -{ - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - MSG_LOG("Opened net dev interface\n"); - - /* tx queue may not necessarily be stopped already - * so stop the queue if tx path is not enabled - */ - if (!mhi_dev->ul_chan) - netif_stop_queue(ndev); - else - netif_start_queue(ndev); - - return 0; - -} - -static int mhi_netdev_change_mtu(struct net_device *ndev, int new_mtu) -{ - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - - if (new_mtu < 0 || mhi_dev->mtu < new_mtu) - return -EINVAL; - - ndev->mtu = new_mtu; - return 0; -} - -static netdev_tx_t mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); - struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int res = 0; - struct skb_data *entry = (struct skb_data *)(skb->cb); - - entry->packets = 1; - entry->length = skb->len; - entry->bind_netdev = mhi_netdev; - - MSG_VERB("Entered\n"); - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - //qmap_hex_dump(__func__, skb->data, 32); - -#ifdef MHI_NETDEV_ONE_CARD_MODE - //printk("%s dev->type=%d\n", __func__, dev->type); - - if (dev->type == ARPHRD_ETHER) { - skb_reset_mac_header(skb); - -#ifdef QUECTEL_BRIDGE_MODE - if (mhi_netdev->bridge_mode && bridge_mode_tx_fixup(dev, skb, mhi_netdev->bridge_ipv4, mhi_netdev->bridge_mac) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } -#endif - - if ((mhi_netdev->net_type == MHI_NET_RMNET || mhi_netdev->net_type == MHI_NET_MBIM) - && (skb_pull(skb, ETH_HLEN) == NULL)) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - - if (mhi_netdev->net_type == MHI_NET_MBIM) { - if (add_mbim_hdr(skb, QUECTEL_QMAP_MUX_ID) == NULL) { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } - else if (mhi_netdev->net_type == MHI_NET_RMNET) { - if (mhi_netdev->qmap_version == 5) { - add_qhdr(skb, QUECTEL_QMAP_MUX_ID); - } - else if (mhi_netdev->qmap_version == 9) { - add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID); - } - else { - dev_kfree_skb_any (skb); - return NETDEV_TX_OK; - } - } -#else - if ((mhi_netdev->net_type == MHI_NET_RMNET || mhi_netdev->net_type == MHI_NET_MBIM) - && skb->protocol != htons(ETH_P_MAP)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } -#endif - - if (mhi_netdev->net_type == MHI_NET_MBIM) { - struct mhi_mbim_hdr *mhdr = (struct mhi_mbim_hdr *)skb->data; - mhdr->nth16.wSequence = cpu_to_le16(mhi_netdev->mbim_ctx.tx_seq++); - } - - if (unlikely(mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) < 16)) { - u32 i = 0; - for (i = 0; i < mhi_netdev->qmap_mode; i++) { - struct net_device *qmap_net = mhi_netdev->mpQmapNetDev[i]; - if (qmap_net) { - netif_stop_queue(qmap_net); - } - } - - netif_stop_queue(dev); - } - - res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len, - MHI_EOT); - - //printk("%s transfer res=%d\n", __func__, res); - if (unlikely(res)) { - dev_kfree_skb_any(skb); - dev->stats.tx_errors++; - } - - MSG_VERB("Exited\n"); - - return NETDEV_TX_OK; -} - -#if defined(MHI_NETDEV_STATUS64) -static struct rtnl_link_stats64 * _mhi_netdev_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats) -{ - struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - - unsigned int start; - int cpu; - - netdev_stats_to_stats64(stats, &ndev->stats); - - for_each_possible_cpu(cpu) { - struct pcpu_sw_netstats *stats64; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) - u64 rx_packets, rx_bytes; - u64 tx_packets, tx_bytes; - - stats64 = per_cpu_ptr(mhi_netdev->stats64, cpu); - - do { - start = u64_stats_fetch_begin_irq(&stats64->syncp); - rx_packets = stats64->rx_packets; - rx_bytes = stats64->rx_bytes; - tx_packets = stats64->tx_packets; - tx_bytes = stats64->tx_bytes; - } while (u64_stats_fetch_retry_irq(&stats64->syncp, start)); - - stats->rx_packets += rx_packets; - stats->rx_bytes += rx_bytes; - stats->tx_packets += tx_packets; - stats->tx_bytes += tx_bytes; -#else - u64_stats_t rx_packets, rx_bytes; - u64_stats_t tx_packets, tx_bytes; - - stats64 = per_cpu_ptr(mhi_netdev->stats64, cpu); - - do { - start = u64_stats_fetch_begin(&stats64->syncp); - rx_packets = stats64->rx_packets; - rx_bytes = stats64->rx_bytes; - tx_packets = stats64->tx_packets; - tx_bytes = stats64->tx_bytes; - } while (u64_stats_fetch_retry(&stats64->syncp, start)); - - stats->rx_packets += u64_stats_read(&rx_packets); - stats->rx_bytes += u64_stats_read(&rx_bytes); - stats->tx_packets += u64_stats_read(&tx_packets); - stats->tx_bytes += u64_stats_read(&tx_bytes); -#endif - } - - return stats; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,10,0 )) //bc1f44709cf27fb2a5766cadafe7e2ad5e9cb221 -static void mhi_netdev_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats) { - _mhi_netdev_get_stats64(ndev, stats); -} -#else -static struct rtnl_link_stats64 * mhi_netdev_get_stats64(struct net_device *ndev, struct rtnl_link_stats64 *stats) { - _mhi_netdev_get_stats64(ndev, stats); - return stats; -} -#endif -#endif - -static int qmap_setting_store(struct mhi_netdev *mhi_netdev, QMAP_SETTING *qmap_settings, size_t size) { - if (qmap_settings->size != size) { - netdev_err(mhi_netdev->ndev, "ERROR: qmap_settings.size donot match!\n"); - return -EOPNOTSUPP; - } - - mhi_netdev->dl_minimum_padding = qmap_settings->dl_minimum_padding; - - return 0; -} - -static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct mhi_netdev *mhi_netdev = ndev_to_mhi(dev); - int rc = -EOPNOTSUPP; - uint link_state = 0; - QMAP_SETTING qmap_settings = {0}; - - switch (cmd) { - case 0x89F1: //SIOCDEVPRIVATE - rc = copy_from_user(&link_state, ifr->ifr_ifru.ifru_data, sizeof(link_state)); - if (!rc) { - char buf[32]; - snprintf(buf, sizeof(buf), "%u", link_state); - link_state_store(&dev->dev, NULL, buf, strlen(buf)); - } - break; - - case 0x89F2: //SIOCDEVPRIVATE - rc = copy_from_user(&qmap_settings, ifr->ifr_ifru.ifru_data, sizeof(qmap_settings)); - if (!rc) { - rc = qmap_setting_store(mhi_netdev, &qmap_settings, sizeof(qmap_settings)); - } - break; - - case 0x89F3: //SIOCDEVPRIVATE - if (mhi_netdev->use_rmnet_usb) { - rc = copy_to_user(ifr->ifr_ifru.ifru_data, &mhi_netdev->rmnet_info, sizeof(RMNET_INFO)); - } - break; - - default: - break; - } - - return rc; -} - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,14,0 )) //b9067f5dc4a07c8e24e01a1b277c6722d91be39e -#define use_ndo_siocdevprivate -#endif -#ifdef use_ndo_siocdevprivate -static int qmap_ndo_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data, int cmd) { - return qmap_ndo_do_ioctl(dev, ifr, cmd); -} -#endif - -static const struct net_device_ops mhi_netdev_ops_ip = { - .ndo_open = mhi_netdev_open, - .ndo_start_xmit = mhi_netdev_xmit, - //.ndo_do_ioctl = mhi_netdev_ioctl, - .ndo_change_mtu = mhi_netdev_change_mtu, -#if defined(MHI_NETDEV_STATUS64) - .ndo_get_stats64 = mhi_netdev_get_stats64, -#endif - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, - .ndo_do_ioctl = qmap_ndo_do_ioctl, -#ifdef use_ndo_siocdevprivate - .ndo_siocdevprivate = qmap_ndo_siocdevprivate, -#endif -}; - -static void mhi_netdev_get_drvinfo (struct net_device *ndev, struct ethtool_drvinfo *info) -{ - //struct mhi_netdev *mhi_netdev = ndev_to_mhi(ndev); - - strlcpy (info->driver, "pcie_mhi", sizeof info->driver); - strlcpy (info->version, PCIE_MHI_DRIVER_VERSION, sizeof info->version); -} - -static const struct ethtool_ops mhi_netdev_ethtool_ops = { - .get_drvinfo = mhi_netdev_get_drvinfo, - .get_link = ethtool_op_get_link, -}; - -static void mhi_netdev_setup(struct net_device *dev) -{ - dev->netdev_ops = &mhi_netdev_ops_ip; - ether_setup(dev); - - dev->ethtool_ops = &mhi_netdev_ethtool_ops; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) - __dev_addr_set (dev, node_id, sizeof node_id); -#else - memcpy (dev->dev_addr, node_id, sizeof node_id); -#endif - /* set this after calling ether_setup */ - dev->header_ops = 0; /* No header */ - dev->hard_header_len = 0; - dev->type = ARPHRD_NONE; - dev->addr_len = 0; - dev->flags |= IFF_NOARP; - dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); //POINTOPOINT will make SFE work wrong - dev->watchdog_timeo = WATCHDOG_TIMEOUT; - //on OpenWrt, if set rmnet_mhi0.1 as WAN, '/sbin/netifd' will auto create VLAN for rmnet_mhi0 - dev->features |= (NETIF_F_VLAN_CHALLENGED); - -#ifdef MHI_NETDEV_ONE_CARD_MODE - if (mhi_mbim_enabled) { - dev->needed_headroom = sizeof(struct mhi_mbim_hdr); - } -#endif -} - -/* enable mhi_netdev netdev, call only after grabbing mhi_netdev.mutex */ -static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev) -{ - int ret = 0; -#if 0 - char ifalias[IFALIASZ]; -#endif - char ifname[IFNAMSIZ]; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int no_tre; - - MSG_LOG("Prepare the channels for transfer\n"); - - ret = mhi_prepare_for_transfer(mhi_dev); - if (ret) { - MSG_ERR("Failed to start TX chan ret %d\n", ret); - goto mhi_failed_to_start; - } - - /* first time enabling the node */ - if (!mhi_netdev->ndev) { - struct mhi_netdev_priv *mhi_netdev_priv; - -#if 0 - snprintf(ifalias, sizeof(ifalias), "%s_%04x_%02u.%02u.%02u_%u", - mhi_netdev->interface_name, mhi_dev->dev_id, - mhi_dev->domain, mhi_dev->bus, mhi_dev->slot, - mhi_netdev->alias); -#endif - - snprintf(ifname, sizeof(ifname), "%s%d", - mhi_netdev->interface_name, mhi_netdev->mhi_dev->mhi_cntrl->cntrl_idx); - - rtnl_lock(); -#ifdef NET_NAME_PREDICTABLE - mhi_netdev->ndev = alloc_netdev(sizeof(*mhi_netdev_priv), - ifname, NET_NAME_PREDICTABLE, - mhi_netdev_setup); -#else - mhi_netdev->ndev = alloc_netdev(sizeof(*mhi_netdev_priv), - ifname, - mhi_netdev_setup); -#endif - - if (!mhi_netdev->ndev) { - ret = -ENOMEM; - rtnl_unlock(); - goto net_dev_alloc_fail; - } - - //mhi_netdev->ndev->mtu = mhi_dev->mtu; - SET_NETDEV_DEV(mhi_netdev->ndev, &mhi_dev->dev); -#if 0 - dev_set_alias(mhi_netdev->ndev, ifalias, strlen(ifalias)); -#endif - mhi_netdev_priv = netdev_priv(mhi_netdev->ndev); - mhi_netdev_priv->mhi_netdev = mhi_netdev; - - if (mhi_netdev->net_type == MHI_NET_RMNET || mhi_netdev->net_type == MHI_NET_MBIM) { -#ifdef QUECTEL_BRIDGE_MODE - mhi_netdev->bridge_mode = bridge_mode; -#endif - mhi_netdev->ndev->sysfs_groups[0] = &pcie_mhi_sysfs_attr_group; - } - else if (mhi_netdev->net_type == MHI_NET_ETHER) { - mhi_netdev->ndev->mtu = mhi_netdev->mru; - } - rtnl_unlock(); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - mhi_netdev->ndev->max_mtu = mhi_netdev->max_mtu; //first net card -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) - netif_napi_add_weight(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight); -#else - netif_napi_add(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight); -#endif - ret = register_netdev(mhi_netdev->ndev); - if (ret) { - MSG_ERR("Network device registration failed\n"); - goto net_dev_reg_fail; - } - - netif_carrier_off(mhi_netdev->ndev); - } - - write_lock_irq(&mhi_netdev->pm_lock); - mhi_netdev->enabled = true; - write_unlock_irq(&mhi_netdev->pm_lock); - - /* queue buffer for rx path */ - no_tre = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - ret = mhi_netdev_alloc_skb(mhi_netdev, GFP_KERNEL); - if (ret) - schedule_delayed_work(&mhi_netdev->alloc_work, msecs_to_jiffies(20)); - - napi_enable(&mhi_netdev->napi); - - MSG_LOG("Exited.\n"); - - return 0; - -net_dev_reg_fail: - netif_napi_del(&mhi_netdev->napi); - free_netdev(mhi_netdev->ndev); - mhi_netdev->ndev = NULL; - -net_dev_alloc_fail: - mhi_unprepare_from_transfer(mhi_dev); - -mhi_failed_to_start: - MSG_ERR("Exited ret %d.\n", ret); - - return ret; -} - -static void mhi_netdev_xfer_ul_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct sk_buff *skb = mhi_result->buf_addr; - struct net_device *ndev = mhi_netdev->ndev; - struct skb_data *entry = (struct skb_data *)(skb->cb); - - if (entry->bind_netdev != mhi_netdev) { - MSG_ERR("%s error!\n", __func__); - return; - } - - if (likely(mhi_result->transaction_status == 0)) { - mhi_netdev_upate_tx_stats(mhi_netdev, entry->packets, entry->length); - - if (netif_queue_stopped(ndev) && mhi_netdev->enabled - && mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 32) { - int i = 0; - - netif_wake_queue(ndev); - for (i = 0; i < mhi_netdev->qmap_mode; i++) { - struct net_device *qmap_net = mhi_netdev->mpQmapNetDev[i]; - if (qmap_net) { - if (netif_queue_stopped(qmap_net)) - netif_wake_queue(qmap_net); - } - } - } - } - - entry->bind_netdev = NULL; - entry->packets = 1; - entry->length = 0; - dev_kfree_skb(skb); -} - -static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct sk_buff *skb = mhi_result->buf_addr; - struct mhi_skb_priv *skb_priv = (struct mhi_skb_priv *)(skb->cb); - - if (unlikely(skb_priv->bind_netdev != mhi_netdev)) { - MSG_ERR("%s error!\n", __func__); - return; - } - - if (unlikely(mhi_result->transaction_status)) { - if (mhi_result->transaction_status != -ENOTCONN) - MSG_ERR("%s transaction_status = %d!\n", __func__, mhi_result->transaction_status); - skb_priv->bind_netdev = NULL; - dev_kfree_skb(skb); - return; - } - -#if defined(CONFIG_IPQ5018_RATE_CONTROL) - if (likely(mhi_netdev->mhi_rate_control)) { - u32 time_interval = 0; - u32 time_difference = 0; - u32 cntfrq; - u64 second_jiffy; - u64 bytes_received_2; - struct net_device *ndev = mhi_netdev->ndev; - - if (mhi_netdev->first_jiffy) { - #if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0) - second_jiffy = arch_counter_get_cntvct(); - #else - second_jiffy = __arch_counter_get_cntvct(); - #endif - bytes_received_2 = mhi_netdev->bytes_received_2; - if ((second_jiffy > mhi_netdev->first_jiffy) && - (bytes_received_2 > mhi_netdev->bytes_received_1)) { - - time_difference = (second_jiffy - mhi_netdev->first_jiffy); - time_interval = (time_difference / mhi_netdev->cntfrq_per_msec); - - /* 1.8Gbps is 225,000,000bytes per second */ - /* We wills sample at 100ms interval */ - /* For 1ms 225000 bytes */ - /* For 100ms 22,500,000 bytes */ - /* For 10ms 2,250,000 bytes */ - - /* 1.7Gbps is 212,500,000bytes per second */ - /* We wills sample at 100ms interval */ - /* For 1ms 212500 bytes */ - /* For 100ms 21,250,000 bytes */ - /* For 10ms 2,125,000 bytes */ - - /* 1.6Gbps is 200,000,000bytes per second */ - /* We wills sample at 100ms interval */ - /* For 1ms 200,000 bytes */ - /* For 100ms 20,000,000 bytes */ - /* For 10ms 2,000,000 bytes */ - - if (time_interval < 100) { - if ((bytes_received_2 - mhi_netdev->bytes_received_1) > 22500000) { - ndev->stats.rx_dropped ++; - dev_kfree_skb(skb); - return; - } - } else { - mhi_netdev->first_jiffy = second_jiffy; - mhi_netdev->bytes_received_1 = bytes_received_2; - } - } else { - mhi_netdev->first_jiffy = second_jiffy; - mhi_netdev->bytes_received_1 = bytes_received_2; - } - } else { - #if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0) - mhi_netdev->first_jiffy = arch_counter_get_cntvct(); - #else - mhi_netdev->first_jiffy = __arch_counter_get_cntvct(); - #endif - - cntfrq = arch_timer_get_cntfrq(); - mhi_netdev->cntfrq_per_msec = cntfrq / 1000; - } - mhi_netdev->bytes_received_2 += mhi_result->bytes_xferd; - } -#endif - -#if 0 - { - static size_t bytes_xferd = 0; - if (mhi_result->bytes_xferd > bytes_xferd) { - bytes_xferd = mhi_result->bytes_xferd; - printk(KERN_DEBUG "bytes_xferd=%zd\n", bytes_xferd); - } - } -#endif - - skb_put(skb, mhi_result->bytes_xferd); - - qmap_hex_dump(__func__, skb->data, skb->len); - - skb_priv->bind_netdev = NULL; - skb_queue_tail(&mhi_netdev->qmap_chain, skb); -} - -static void mhi_netdev_status_cb(struct mhi_device *mhi_dev, enum MHI_CB mhi_cb) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - - if (mhi_cb != MHI_CB_PENDING_DATA) - return; - - if (napi_schedule_prep(&mhi_netdev->napi)) { - __napi_schedule(&mhi_netdev->napi); - mhi_netdev->stats.rx_int++; - return; - } -} - -#ifdef CONFIG_DEBUG_FS - -struct dentry *mhi_netdev_debugfs_dentry; - -static int mhi_netdev_init_debugfs_states_show(struct seq_file *m, void *d) -{ - struct mhi_netdev *mhi_netdev = m->private; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - -#ifdef TS_DEBUG - struct timespec now_ts, diff_ts; - getnstimeofday(&now_ts); - diff_ts = timespec_sub(now_ts, mhi_netdev->diff_ts); - mhi_netdev->diff_ts = now_ts; -#endif - - seq_printf(m, - "tx_tre:%d rx_tre:%d qmap_chain:%u skb_chain:%u tx_allocated:%u rx_allocated:%u\n", - mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE), - mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE), - mhi_netdev->qmap_chain.qlen, - mhi_netdev->skb_chain.qlen, - mhi_netdev->tx_allocated.qlen, - mhi_netdev->rx_allocated.qlen); - - seq_printf(m, - "netif_queue_stopped:%d, link_state:0x%x, flow_control:0x%x\n", - netif_queue_stopped(mhi_netdev->ndev), mhi_netdev->link_state, mhi_netdev->flow_control); - - seq_printf(m, - "rmnet_map_command_stats: %u, %u, %u, %u, %u, %u, %u, %u, %u, %u\n", - mhi_netdev->rmnet_map_command_stats[RMNET_MAP_COMMAND_NONE], - mhi_netdev->rmnet_map_command_stats[RMNET_MAP_COMMAND_FLOW_DISABLE], - mhi_netdev->rmnet_map_command_stats[RMNET_MAP_COMMAND_FLOW_ENABLE], - mhi_netdev->rmnet_map_command_stats[3], - mhi_netdev->rmnet_map_command_stats[4], - mhi_netdev->rmnet_map_command_stats[5], - mhi_netdev->rmnet_map_command_stats[6], - mhi_netdev->rmnet_map_command_stats[RMNET_MAP_COMMAND_FLOW_START], - mhi_netdev->rmnet_map_command_stats[RMNET_MAP_COMMAND_FLOW_END], - mhi_netdev->rmnet_map_command_stats[RMNET_MAP_COMMAND_UNKNOWN]); - -#ifdef TS_DEBUG - seq_printf(m, - "qmap_ts:%ld.%ld, skb_ts:%ld.%ld, diff_ts:%ld.%ld\n", - mhi_netdev->qmap_ts.tv_sec, mhi_netdev->qmap_ts.tv_nsec, - mhi_netdev->skb_ts.tv_sec, mhi_netdev->skb_ts.tv_nsec, - diff_ts.tv_sec, diff_ts.tv_nsec); - mhi_netdev->clear_ts = 1; -#endif - - return 0; -} - -static int mhi_netdev_init_debugfs_states_open(struct inode *inode, - struct file *fp) -{ - return single_open(fp, mhi_netdev_init_debugfs_states_show, inode->i_private); -} - -static const struct file_operations mhi_netdev_debugfs_state_ops = { - .open = mhi_netdev_init_debugfs_states_open, - .release = single_release, - .read = seq_read, -}; - -static int mhi_netdev_debugfs_trigger_reset(void *data, u64 val) -{ - struct mhi_netdev *mhi_netdev = data; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int ret; - - MSG_LOG("Triggering channel reset\n"); - - /* disable the interface so no data processing */ - write_lock_irq(&mhi_netdev->pm_lock); - mhi_netdev->enabled = false; - write_unlock_irq(&mhi_netdev->pm_lock); - napi_disable(&mhi_netdev->napi); - - /* disable all hardware channels */ - mhi_unprepare_from_transfer(mhi_dev); - - /* clean up all alocated buffers */ - mhi_netdev_dealloc(mhi_netdev); - - MSG_LOG("Restarting iface\n"); - - ret = mhi_netdev_enable_iface(mhi_netdev); - if (ret) - return ret; - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(mhi_netdev_debugfs_trigger_reset_fops, NULL, - mhi_netdev_debugfs_trigger_reset, "%llu\n"); - -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev) -{ - char node_name[32]; - int i; - const umode_t mode = 0600; - struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - struct dentry *dentry = mhi_netdev_debugfs_dentry; - - const struct { - char *name; - u32 *ptr; - } debugfs_table[] = { - { - "rx_int", - &mhi_netdev->stats.rx_int - }, - { - "tx_full", - &mhi_netdev->stats.tx_full - }, - { - "tx_pkts", - &mhi_netdev->stats.tx_pkts - }, - { - "rx_budget_overflow", - &mhi_netdev->stats.rx_budget_overflow - }, - { - "rx_allocated", - &mhi_netdev->stats.rx_allocated - }, - { - "tx_allocated", - &mhi_netdev->stats.tx_allocated - }, - { - "alloc_failed", - &mhi_netdev->stats.alloc_failed - }, - { - NULL, NULL - }, - }; - - /* Both tx & rx client handle contain same device info */ - snprintf(node_name, sizeof(node_name), "%s_%04x_%02u.%02u.%02u_%u", - mhi_netdev->interface_name, mhi_dev->dev_id, mhi_dev->domain, - mhi_dev->bus, mhi_dev->slot, mhi_netdev->alias); - - if (IS_ERR_OR_NULL(dentry)) - return; - - mhi_netdev->dentry = debugfs_create_dir(node_name, dentry); - if (IS_ERR_OR_NULL(mhi_netdev->dentry)) - return; - - debugfs_create_u32("msg_lvl", mode, mhi_netdev->dentry, - (u32 *)&mhi_netdev->msg_lvl); - - /* Add debug stats table */ - for (i = 0; debugfs_table[i].name; i++) { - debugfs_create_u32(debugfs_table[i].name, mode, - mhi_netdev->dentry, - debugfs_table[i].ptr); - } - - debugfs_create_file("reset", mode, mhi_netdev->dentry, mhi_netdev, - &mhi_netdev_debugfs_trigger_reset_fops); - debugfs_create_file("states", 0444, mhi_netdev->dentry, mhi_netdev, - &mhi_netdev_debugfs_state_ops); -} - -static void mhi_netdev_create_debugfs_dir(struct dentry *parent) -{ - mhi_netdev_debugfs_dentry = debugfs_create_dir(MHI_NETDEV_DRIVER_NAME, parent); -} - -#else - -static void mhi_netdev_create_debugfs(struct mhi_netdev *mhi_netdev) -{ -} - -static void mhi_netdev_create_debugfs_dir(struct dentry *parent) -{ -} - -#endif - -static void mhi_netdev_remove(struct mhi_device *mhi_dev) -{ - struct mhi_netdev *mhi_netdev = mhi_device_get_devdata(mhi_dev); - struct sk_buff *skb; - - MSG_LOG("Remove notification received\n"); - - write_lock_irq(&mhi_netdev->pm_lock); - mhi_netdev->enabled = false; - write_unlock_irq(&mhi_netdev->pm_lock); - - if (mhi_netdev->use_rmnet_usb) { -#ifndef MHI_NETDEV_ONE_CARD_MODE - unsigned i; - - for (i = 0; i < mhi_netdev->qmap_mode; i++) { - if (mhi_netdev->mpQmapNetDev[i]) { - rmnet_vnd_unregister_device(mhi_netdev->mpQmapNetDev[i]); - mhi_netdev->mpQmapNetDev[i] = NULL; - } - } - - rtnl_lock(); -#ifdef ANDROID_gki - if (mhi_netdev->ndev && rtnl_dereference(mhi_netdev->ndev->rx_handler)) -#else - if (netdev_is_rx_handler_busy(mhi_netdev->ndev)) -#endif - netdev_rx_handler_unregister(mhi_netdev->ndev); - rtnl_unlock(); -#endif - } - - while ((skb = skb_dequeue (&mhi_netdev->skb_chain))) - dev_kfree_skb_any(skb); - while ((skb = skb_dequeue (&mhi_netdev->qmap_chain))) - dev_kfree_skb_any(skb); - while ((skb = skb_dequeue (&mhi_netdev->rx_allocated))) - dev_kfree_skb_any(skb); - while ((skb = skb_dequeue (&mhi_netdev->tx_allocated))) - dev_kfree_skb_any(skb); - - napi_disable(&mhi_netdev->napi); - netif_napi_del(&mhi_netdev->napi); - mhi_netdev_dealloc(mhi_netdev); - unregister_netdev(mhi_netdev->ndev); -#if defined(MHI_NETDEV_STATUS64) - free_percpu(mhi_netdev->stats64); -#endif - free_netdev(mhi_netdev->ndev); - flush_delayed_work(&mhi_netdev->alloc_work); - - if (!IS_ERR_OR_NULL(mhi_netdev->dentry)) - debugfs_remove_recursive(mhi_netdev->dentry); -} - -static int mhi_netdev_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - int ret; - struct mhi_netdev *mhi_netdev; - - mhi_netdev = devm_kzalloc(&mhi_dev->dev, sizeof(*mhi_netdev), - GFP_KERNEL); - if (!mhi_netdev) - return -ENOMEM; - - if (!strcmp(id->chan, "IP_HW0")) { - if (mhi_mbim_enabled) - mhi_netdev->net_type = MHI_NET_MBIM; - else - mhi_netdev->net_type = MHI_NET_RMNET; - } - else if (!strcmp(id->chan, "IP_SW0")) { - mhi_netdev->net_type = MHI_NET_ETHER; - } - else { - return -EINVAL; - } - - mhi_netdev->alias = 0; - - mhi_netdev->mhi_dev = mhi_dev; - mhi_device_set_devdata(mhi_dev, mhi_netdev); - - mhi_netdev->mru = (15*1024); ///etc/data/qnicorn_config.xml dataformat_agg_dl_size 15*1024 - mhi_netdev->max_mtu = mhi_netdev->mru - (sizeof(struct rmnet_map_v5_csum_header) + sizeof(struct rmnet_map_header)); - if (mhi_netdev->net_type == MHI_NET_MBIM) { - mhi_netdev->mru = ncmNTBParams.dwNtbInMaxSize; - mhi_netdev->mbim_ctx.rx_max = mhi_netdev->mru; - mhi_netdev->max_mtu = mhi_netdev->mru - sizeof(struct mhi_mbim_hdr); - } - else if (mhi_netdev->net_type == MHI_NET_ETHER) { - mhi_netdev->mru = 8*1024; - mhi_netdev->max_mtu = mhi_netdev->mru; - } - mhi_netdev->qmap_size = mhi_netdev->mru; - -#if defined(MHI_NETDEV_STATUS64) - mhi_netdev->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!mhi_netdev->stats64) - return -ENOMEM; -#endif - - if (!strcmp(id->chan, "IP_HW0")) - mhi_netdev->interface_name = "rmnet_mhi"; - else if (!strcmp(id->chan, "IP_SW0")) - mhi_netdev->interface_name = "mhi_swip"; - else - mhi_netdev->interface_name = id->chan; - - mhi_netdev->qmap_mode = qmap_mode; - mhi_netdev->qmap_version = 5; - mhi_netdev->use_rmnet_usb = 1; - if ((mhi_dev->vendor == 0x17cb && mhi_dev->dev_id == 0x0306) - || (mhi_dev->vendor == 0x17cb && mhi_dev->dev_id == 0x0308) - || (mhi_dev->vendor == 0x1eac && mhi_dev->dev_id == 0x1004) - ) { - mhi_netdev->qmap_version = 9; - } - if (mhi_netdev->net_type == MHI_NET_ETHER) { - mhi_netdev->qmap_mode = 1; - mhi_netdev->qmap_version = 0; - mhi_netdev->use_rmnet_usb = 0; - } - rmnet_info_set(mhi_netdev, &mhi_netdev->rmnet_info); - - mhi_netdev->rx_queue = mhi_netdev_alloc_skb; - - spin_lock_init(&mhi_netdev->rx_lock); - rwlock_init(&mhi_netdev->pm_lock); - INIT_DELAYED_WORK(&mhi_netdev->alloc_work, mhi_netdev_alloc_work); - skb_queue_head_init(&mhi_netdev->qmap_chain); - skb_queue_head_init(&mhi_netdev->skb_chain); - skb_queue_head_init(&mhi_netdev->tx_allocated); - skb_queue_head_init(&mhi_netdev->rx_allocated); - - mhi_netdev->msg_lvl = MHI_MSG_LVL_INFO; - - /* setup network interface */ - ret = mhi_netdev_enable_iface(mhi_netdev); - if (ret) { - pr_err("Error mhi_netdev_enable_iface ret:%d\n", ret); - return ret; - } - - mhi_netdev_create_debugfs(mhi_netdev); - - if (mhi_netdev->net_type == MHI_NET_ETHER) { - mhi_netdev->mpQmapNetDev[0] = mhi_netdev->ndev; - netif_carrier_on(mhi_netdev->ndev); - } - else if (mhi_netdev->use_rmnet_usb) { -#ifdef MHI_NETDEV_ONE_CARD_MODE - mhi_netdev->mpQmapNetDev[0] = mhi_netdev->ndev; - strcpy(mhi_netdev->rmnet_info.ifname[0], mhi_netdev->mpQmapNetDev[0]->name); - mhi_netdev->rmnet_info.mux_id[0] = QUECTEL_QMAP_MUX_ID; -#else - unsigned i; - - for (i = 0; i < mhi_netdev->qmap_mode; i++) { - u8 mux_id = QUECTEL_QMAP_MUX_ID+i; - mhi_netdev->mpQmapNetDev[i] = rmnet_vnd_register_device(mhi_netdev, i, mux_id); - if (mhi_netdev->mpQmapNetDev[i]) { - strcpy(mhi_netdev->rmnet_info.ifname[i], mhi_netdev->mpQmapNetDev[i]->name); - mhi_netdev->rmnet_info.mux_id[i] = mux_id; - } - } - - rtnl_lock(); - /* when open hyfi function, run cm will make system crash */ - //netdev_rx_handler_register(mhi_netdev->ndev, rmnet_rx_handler, mhi_netdev); - netdev_rx_handler_register(mhi_netdev->ndev, rmnet_rx_handler, NULL); - rtnl_unlock(); -#endif - } - -#if defined(CONFIG_IPQ5018_RATE_CONTROL) - mhi_netdev->mhi_rate_control = 1; -#endif - - return 0; -} - -static const struct mhi_device_id mhi_netdev_match_table[] = { - { .chan = "IP_HW0" }, - { .chan = "IP_SW0" }, - // ADPL do not register as a netcard. xingduo.du 2023-02-20 - // { .chan = "IP_HW_ADPL" }, - { }, -}; - -static struct mhi_driver mhi_netdev_driver = { - .id_table = mhi_netdev_match_table, - .probe = mhi_netdev_probe, - .remove = mhi_netdev_remove, - .ul_xfer_cb = mhi_netdev_xfer_ul_cb, - .dl_xfer_cb = mhi_netdev_xfer_dl_cb, - .status_cb = mhi_netdev_status_cb, - .driver = { - .name = "mhi_netdev", - .owner = THIS_MODULE, - } -}; - -int __init mhi_device_netdev_init(struct dentry *parent) -{ -#ifdef CONFIG_QCA_NSS_DRV - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (!nss_cb) { - printk(KERN_ERR "mhi_device_netdev_init: driver load must after '/etc/modules.d/42-rmnet-nss'\n"); - } -#endif - - mhi_netdev_create_debugfs_dir(parent); - - return mhi_driver_register(&mhi_netdev_driver); -} - -void mhi_device_netdev_exit(void) -{ -#ifdef CONFIG_DEBUG_FS - debugfs_remove_recursive(mhi_netdev_debugfs_dentry); -#endif - mhi_driver_unregister(&mhi_netdev_driver); -} diff --git a/quectel_MHI/src/devices/mhi_satellite.c b/quectel_MHI/src/devices/mhi_satellite.c deleted file mode 100644 index d1071ec..0000000 --- a/quectel_MHI/src/devices/mhi_satellite.c +++ /dev/null @@ -1,1153 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2019, The Linux Foundation. All rights reserved.*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MHI_SAT_DRIVER_NAME "mhi_satellite" - -static bool mhi_sat_defer_init = true; /* set by default */ - -/* logging macros */ -#define IPC_LOG_PAGES (10) -#define IPC_LOG_LVL (MHI_MSG_LVL_INFO) -#define KLOG_LVL (MHI_MSG_LVL_ERROR) - -#define MHI_SUBSYS_LOG(fmt, ...) do { \ - if (!subsys) \ - break; \ - if (mhi_sat_driver.klog_lvl <= MHI_MSG_LVL_INFO) \ - pr_info("[I][%s][%s] " fmt, __func__, subsys->name, \ - ##__VA_ARGS__);\ - if (subsys->ipc_log && mhi_sat_driver.ipc_log_lvl <= \ - MHI_MSG_LVL_INFO) \ - ipc_log_string(subsys->ipc_log, "[I][%s] " fmt, __func__, \ - ##__VA_ARGS__); \ -} while (0) - -#define MHI_SAT_LOG(fmt, ...) do { \ - if (!subsys || !sat_cntrl) \ - break; \ - if (mhi_sat_driver.klog_lvl <= MHI_MSG_LVL_INFO) \ - pr_info("[I][%s][%s][%x] " fmt, __func__, subsys->name, \ - sat_cntrl->dev_id, ##__VA_ARGS__);\ - if (subsys->ipc_log && mhi_sat_driver.ipc_log_lvl <= \ - MHI_MSG_LVL_INFO) \ - ipc_log_string(subsys->ipc_log, "[I][%s][%x] " fmt, __func__, \ - sat_cntrl->dev_id, ##__VA_ARGS__); \ -} while (0) - -#define MHI_SAT_ERR(fmt, ...) do { \ - if (!subsys || !sat_cntrl) \ - break; \ - if (mhi_sat_driver.klog_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s][%s][%x] " fmt, __func__, subsys->name, \ - sat_cntrl->dev_id, ##__VA_ARGS__); \ - if (subsys->ipc_log && mhi_sat_driver.ipc_log_lvl <= \ - MHI_MSG_LVL_ERROR) \ - ipc_log_string(subsys->ipc_log, "[E][%s][%x] " fmt, __func__, \ - sat_cntrl->dev_id, ##__VA_ARGS__); \ -} while (0) - -#define MHI_SAT_ASSERT(cond, msg) do { \ - if (cond) \ - panic(msg); \ -} while (0) - -/* mhi sys error command */ -#define MHI_TRE_CMD_SYS_ERR_PTR (0) -#define MHI_TRE_CMD_SYS_ERR_D0 (0) -#define MHI_TRE_CMD_SYS_ERR_D1 (MHI_PKT_TYPE_SYS_ERR_CMD << 16) - -/* mhi state change event */ -#define MHI_TRE_EVT_MHI_STATE_PTR (0) -#define MHI_TRE_EVT_MHI_STATE_D0(state) (state << 24) -#define MHI_TRE_EVT_MHI_STATE_D1 (MHI_PKT_TYPE_STATE_CHANGE_EVENT << 16) - -/* mhi exec env change event */ -#define MHI_TRE_EVT_EE_PTR (0) -#define MHI_TRE_EVT_EE_D0(ee) (ee << 24) -#define MHI_TRE_EVT_EE_D1 (MHI_PKT_TYPE_EE_EVENT << 16) - -/* mhi config event */ -#define MHI_TRE_EVT_CFG_PTR(base_addr) (base_addr) -#define MHI_TRE_EVT_CFG_D0(er_base, num) ((er_base << 16) | (num & 0xFFFF)) -#define MHI_TRE_EVT_CFG_D1 (MHI_PKT_TYPE_CFG_EVENT << 16) - -/* command completion event */ -#define MHI_TRE_EVT_CMD_COMPLETION_PTR(ptr) (ptr) -#define MHI_TRE_EVT_CMD_COMPLETION_D0(code) (code << 24) -#define MHI_TRE_EVT_CMD_COMPLETION_D1 (MHI_PKT_TYPE_CMD_COMPLETION_EVENT << 16) - -/* packet parser macros */ -#define MHI_TRE_GET_PTR(tre) ((tre)->ptr) -#define MHI_TRE_GET_SIZE(tre) ((tre)->dword[0]) -#define MHI_TRE_GET_CCS(tre) (((tre)->dword[0] >> 24) & 0xFF) -#define MHI_TRE_GET_ID(tre) (((tre)->dword[1] >> 24) & 0xFF) -#define MHI_TRE_GET_TYPE(tre) (((tre)->dword[1] >> 16) & 0xFF) -#define MHI_TRE_IS_ER_CTXT_TYPE(tre) (((tre)->dword[1]) & 0x1) - -/* creates unique device ID based on connection topology */ -#define MHI_SAT_CREATE_DEVICE_ID(dev, domain, bus, slot) \ - ((dev & 0xFFFF) << 16 | (domain & 0xF) << 12 | (bus & 0xFF) << 4 | \ - (slot & 0xF)) - -/* mhi core definitions */ -#define MHI_CTXT_TYPE_GENERIC (0xA) - -struct __packed mhi_generic_ctxt { - u32 reserved0; - u32 type; - u32 reserved1; - u64 ctxt_base; - u64 ctxt_size; - u64 reserved[2]; -}; - -enum mhi_pkt_type { - MHI_PKT_TYPE_INVALID = 0x0, - MHI_PKT_TYPE_RESET_CHAN_CMD = 0x10, - MHI_PKT_TYPE_STOP_CHAN_CMD = 0x11, - MHI_PKT_TYPE_START_CHAN_CMD = 0x12, - MHI_PKT_TYPE_STATE_CHANGE_EVENT = 0x20, - MHI_PKT_TYPE_CMD_COMPLETION_EVENT = 0x21, - MHI_PKT_TYPE_EE_EVENT = 0x40, - MHI_PKT_TYPE_CTXT_UPDATE_CMD = 0x64, - MHI_PKT_TYPE_IOMMU_MAP_CMD = 0x65, - MHI_PKT_TYPE_CFG_EVENT = 0x6E, - MHI_PKT_TYPE_SYS_ERR_CMD = 0xFF, -}; - -enum mhi_cmd_type { - MHI_CMD_TYPE_RESET = 0x10, - MHI_CMD_TYPE_STOP = 0x11, - MHI_CMD_TYPE_START = 0x12, -}; - -/* mhi event completion codes */ -enum mhi_ev_ccs { - MHI_EV_CC_INVALID = 0x0, - MHI_EV_CC_SUCCESS = 0x1, - MHI_EV_CC_BAD_TRE = 0x11, -}; - -/* satellite subsystem definitions */ -enum subsys_id { - SUBSYS_ADSP, - SUBSYS_CDSP, - SUBSYS_SLPI, - SUBSYS_MODEM, - SUBSYS_MAX, -}; - -static const char * const subsys_names[SUBSYS_MAX] = { - [SUBSYS_ADSP] = "adsp", - [SUBSYS_CDSP] = "cdsp", - [SUBSYS_SLPI] = "slpi", - [SUBSYS_MODEM] = "modem", -}; - -struct mhi_sat_subsys { - const char *name; - - struct rpmsg_device *rpdev; /* rpmsg device */ - - /* - * acquire either mutex or spinlock to walk controller list - * acquire both when modifying list - */ - struct list_head cntrl_list; /* controllers list */ - struct mutex cntrl_mutex; /* mutex to walk/modify controllers list */ - spinlock_t cntrl_lock; /* lock to walk/modify controllers list */ - - void *ipc_log; -}; - -/* satellite IPC definitions */ -#define SAT_MAJOR_VERSION (1) -#define SAT_MINOR_VERSION (0) -#define SAT_RESERVED_SEQ_NUM (0xFFFF) -#define SAT_MSG_SIZE(n) (sizeof(struct sat_header) + \ - (n * sizeof(struct sat_tre))) -#define SAT_TRE_SIZE(msg_size) (msg_size - sizeof(struct sat_header)) -#define SAT_TRE_OFFSET(msg) (msg + sizeof(struct sat_header)) -#define SAT_TRE_NUM_PKTS(payload_size) ((payload_size) / sizeof(struct sat_tre)) - -/* satellite IPC msg type */ -enum sat_msg_id { - SAT_MSG_ID_ACK = 0xA, - SAT_MSG_ID_CMD = 0xC, - SAT_MSG_ID_EVT = 0xE, -}; - -/* satellite IPC context type */ -enum sat_ctxt_type { - SAT_CTXT_TYPE_CHAN = 0x0, - SAT_CTXT_TYPE_EVENT = 0x1, - SAT_CTXT_TYPE_MAX, -}; - -/* satellite IPC context string */ -#define TO_SAT_CTXT_TYPE_STR(type) (type >= SAT_CTXT_TYPE_MAX ? "INVALID" : \ - sat_ctxt_str[type]) - -const char * const sat_ctxt_str[SAT_CTXT_TYPE_MAX] = { - [SAT_CTXT_TYPE_CHAN] = "CCA", - [SAT_CTXT_TYPE_EVENT] = "ECA", -}; - -/* satellite IPC transfer ring element */ -struct __packed sat_tre { - u64 ptr; - u32 dword[2]; -}; - -/* satellite IPC header */ -struct __packed sat_header { - u16 major_ver; - u16 minor_ver; - u16 msg_id; - u16 seq; - u16 reply_seq; - u16 payload_size; - u32 dev_id; - u8 reserved[8]; -}; - -/* satellite driver definitions */ -struct mhi_sat_packet { - struct list_head node; - - struct mhi_sat_cntrl *cntrl; /* satellite controller reference */ - void *msg; /* incoming message */ -}; - -struct mhi_sat_cntrl { - struct list_head node; - - struct mhi_controller *mhi_cntrl; /* device MHI controller reference */ - struct mhi_sat_subsys *subsys; - - struct list_head dev_list; - struct list_head addr_map_list; /* IOMMU mapped addresses list */ - struct mutex list_mutex; /* mutex for devices and address map lists */ - - struct list_head packet_list; - spinlock_t pkt_lock; /* lock to walk/modify received packets list */ - - struct work_struct connect_work; /* subsystem connection worker */ - struct work_struct process_work; /* incoming packets processor */ - - /* mhi core/controller configurations */ - u32 dev_id; /* unique device ID with BDF as per connection topology */ - int er_base; /* event rings base index */ - int er_max; /* event rings max index */ - int num_er; /* total number of event rings */ - - /* satellite controller function counts */ - int num_devices; /* mhi devices current count */ - int max_devices; /* count of maximum devices for subsys/controller */ - u16 seq; /* internal sequence number for all outgoing packets */ - bool active; /* flag set if hello packet/MHI_CFG event was sent */ - - /* command completion variables */ - u16 last_cmd_seq; /* sequence number of last sent command packet */ - enum mhi_ev_ccs last_cmd_ccs; /* last command completion event code */ - struct completion completion; /* command completion event wait */ - struct mutex cmd_wait_mutex; /* command completion wait mutex */ -}; - -struct mhi_sat_device { - struct list_head node; - - struct mhi_device *mhi_dev; /* mhi device pointer */ - struct mhi_sat_cntrl *cntrl; /* parent controller */ - - bool chan_started; -}; - -struct mhi_sat_driver { - enum MHI_DEBUG_LEVEL ipc_log_lvl; /* IPC log level */ - enum MHI_DEBUG_LEVEL klog_lvl; /* klog/dmesg levels */ - - struct mhi_sat_subsys *subsys; /* pointer to subsystem array */ - unsigned int num_subsys; - - struct dentry *dentry; /* debugfs directory */ - bool deferred_init_done; /* flag for deferred init protection */ -}; - -static struct mhi_sat_driver mhi_sat_driver; - -static struct mhi_sat_subsys *find_subsys_by_name(const char *name) -{ - int i; - struct mhi_sat_subsys *subsys = mhi_sat_driver.subsys; - - for (i = 0; i < mhi_sat_driver.num_subsys; i++, subsys++) { - if (!strcmp(name, subsys->name)) - return subsys; - } - - return NULL; -} - -static struct mhi_sat_cntrl *find_sat_cntrl_by_id(struct mhi_sat_subsys *subsys, - u32 dev_id) -{ - struct mhi_sat_cntrl *sat_cntrl; - unsigned long flags; - - spin_lock_irqsave(&subsys->cntrl_lock, flags); - list_for_each_entry(sat_cntrl, &subsys->cntrl_list, node) { - if (sat_cntrl->dev_id == dev_id) { - spin_unlock_irqrestore(&subsys->cntrl_lock, flags); - return sat_cntrl; - } - } - spin_unlock_irqrestore(&subsys->cntrl_lock, flags); - - return NULL; -} - -static struct mhi_sat_device *find_sat_dev_by_id( - struct mhi_sat_cntrl *sat_cntrl, int id, - enum sat_ctxt_type evt) -{ - struct mhi_sat_device *sat_dev; - int compare_id; - - mutex_lock(&sat_cntrl->list_mutex); - list_for_each_entry(sat_dev, &sat_cntrl->dev_list, node) { - compare_id = (evt == SAT_CTXT_TYPE_EVENT) ? - sat_dev->mhi_dev->dl_event_id : - sat_dev->mhi_dev->dl_chan_id; - - if (compare_id == id) { - mutex_unlock(&sat_cntrl->list_mutex); - return sat_dev; - } - } - mutex_unlock(&sat_cntrl->list_mutex); - - return NULL; -} - -static bool mhi_sat_isvalid_header(struct sat_header *hdr, int len) -{ - /* validate payload size */ - if (len >= sizeof(*hdr) && (len != hdr->payload_size + sizeof(*hdr))) - return false; - - /* validate SAT IPC version */ - if (hdr->major_ver != SAT_MAJOR_VERSION && - hdr->minor_ver != SAT_MINOR_VERSION) - return false; - - /* validate msg ID */ - if (hdr->msg_id != SAT_MSG_ID_CMD && hdr->msg_id != SAT_MSG_ID_EVT) - return false; - - return true; -} - -static int mhi_sat_wait_cmd_completion(struct mhi_sat_cntrl *sat_cntrl) -{ - struct mhi_sat_subsys *subsys = sat_cntrl->subsys; - int ret; - - reinit_completion(&sat_cntrl->completion); - - MHI_SAT_LOG("Wait for command completion\n"); - ret = wait_for_completion_timeout(&sat_cntrl->completion, - msecs_to_jiffies(sat_cntrl->mhi_cntrl->timeout_ms)); - if (!ret || sat_cntrl->last_cmd_ccs != MHI_EV_CC_SUCCESS) { - MHI_SAT_ERR("Command completion failure:seq:%u:ret:%d:ccs:%d\n", - sat_cntrl->last_cmd_seq, ret, sat_cntrl->last_cmd_ccs); - return -EIO; - } - - MHI_SAT_LOG("Command completion successful for seq:%u\n", - sat_cntrl->last_cmd_seq); - - return 0; -} - -static int mhi_sat_send_msg(struct mhi_sat_cntrl *sat_cntrl, - enum sat_msg_id type, u16 reply_seq, - void *msg, u16 msg_size) -{ - struct mhi_sat_subsys *subsys = sat_cntrl->subsys; - struct sat_header *hdr = msg; - - /* create sequence number for controller */ - sat_cntrl->seq++; - if (sat_cntrl->seq == SAT_RESERVED_SEQ_NUM) - sat_cntrl->seq = 0; - - /* populate header */ - hdr->major_ver = SAT_MAJOR_VERSION; - hdr->minor_ver = SAT_MINOR_VERSION; - hdr->msg_id = type; - hdr->seq = sat_cntrl->seq; - hdr->reply_seq = reply_seq; - hdr->payload_size = SAT_TRE_SIZE(msg_size); - hdr->dev_id = sat_cntrl->dev_id; - - /* save last sent command sequence number for completion event */ - if (type == SAT_MSG_ID_CMD) - sat_cntrl->last_cmd_seq = sat_cntrl->seq; - - return rpmsg_send(subsys->rpdev->ept, msg, msg_size); -} - -static void mhi_sat_process_cmds(struct mhi_sat_cntrl *sat_cntrl, - struct sat_header *hdr, struct sat_tre *pkt) -{ - struct mhi_sat_subsys *subsys = sat_cntrl->subsys; - int num_pkts = SAT_TRE_NUM_PKTS(hdr->payload_size), i; - - for (i = 0; i < num_pkts; i++, pkt++) { - enum mhi_ev_ccs code = MHI_EV_CC_INVALID; - - switch (MHI_TRE_GET_TYPE(pkt)) { - case MHI_PKT_TYPE_IOMMU_MAP_CMD: - { - struct mhi_buf *buf; - struct mhi_controller *mhi_cntrl = sat_cntrl->mhi_cntrl; - dma_addr_t iova = DMA_ERROR_CODE; - - buf = kmalloc(sizeof(*buf), GFP_ATOMIC); - if (!buf) - goto iommu_map_cmd_completion; - - buf->phys_addr = MHI_TRE_GET_PTR(pkt); - buf->len = MHI_TRE_GET_SIZE(pkt); - - iova = dma_map_resource(mhi_cntrl->dev, buf->phys_addr, - buf->len, DMA_BIDIRECTIONAL, 0); - if (dma_mapping_error(mhi_cntrl->dev, iova)) { - kfree(buf); - goto iommu_map_cmd_completion; - } - - buf->dma_addr = iova; - - mutex_lock(&sat_cntrl->list_mutex); - list_add_tail(&buf->node, - &sat_cntrl->addr_map_list); - mutex_unlock(&sat_cntrl->list_mutex); - - code = MHI_EV_CC_SUCCESS; - -iommu_map_cmd_completion: - MHI_SAT_LOG("IOMMU MAP 0x%llx CMD processing %s\n", - MHI_TRE_GET_PTR(pkt), - (code == MHI_EV_CC_SUCCESS) ? "successful" : - "failed"); - - pkt->ptr = MHI_TRE_EVT_CMD_COMPLETION_PTR(iova); - pkt->dword[0] = MHI_TRE_EVT_CMD_COMPLETION_D0(code); - pkt->dword[1] = MHI_TRE_EVT_CMD_COMPLETION_D1; - break; - } - case MHI_PKT_TYPE_CTXT_UPDATE_CMD: - { - u64 ctxt_ptr = MHI_TRE_GET_PTR(pkt); - u64 ctxt_size = MHI_TRE_GET_SIZE(pkt); - int id = MHI_TRE_GET_ID(pkt); - enum sat_ctxt_type evt = MHI_TRE_IS_ER_CTXT_TYPE(pkt); - struct mhi_generic_ctxt gen_ctxt; - struct mhi_buf buf; - struct mhi_sat_device *sat_dev = find_sat_dev_by_id( - sat_cntrl, id, evt); - int ret; - - MHI_SAT_ASSERT(!sat_dev, - "No device with given chan/evt ID"); - - memset(&gen_ctxt, 0, sizeof(gen_ctxt)); - memset(&buf, 0, sizeof(buf)); - - gen_ctxt.type = MHI_CTXT_TYPE_GENERIC; - gen_ctxt.ctxt_base = ctxt_ptr; - gen_ctxt.ctxt_size = ctxt_size; - - buf.buf = &gen_ctxt; - buf.len = sizeof(gen_ctxt); - buf.name = TO_SAT_CTXT_TYPE_STR(evt); - - ret = mhi_device_configure(sat_dev->mhi_dev, - DMA_BIDIRECTIONAL, &buf, 1); - if (!ret) - code = MHI_EV_CC_SUCCESS; - - MHI_SAT_LOG("CTXT UPDATE CMD %s:%d processing %s\n", - buf.name, id, (code == MHI_EV_CC_SUCCESS) ? - "successful" : "failed"); - - pkt->ptr = MHI_TRE_EVT_CMD_COMPLETION_PTR(0); - pkt->dword[0] = MHI_TRE_EVT_CMD_COMPLETION_D0(code); - pkt->dword[1] = MHI_TRE_EVT_CMD_COMPLETION_D1; - break; - } - case MHI_PKT_TYPE_START_CHAN_CMD: - { - int id = MHI_TRE_GET_ID(pkt); - struct mhi_sat_device *sat_dev = find_sat_dev_by_id( - sat_cntrl, id, - SAT_CTXT_TYPE_CHAN); - int ret; - - MHI_SAT_ASSERT(!sat_dev, - "No device with given channel ID\n"); - - MHI_SAT_ASSERT(sat_dev->chan_started, - "Channel already started!"); - - ret = mhi_prepare_for_transfer(sat_dev->mhi_dev); - if (!ret) { - sat_dev->chan_started = true; - code = MHI_EV_CC_SUCCESS; - } - - MHI_SAT_LOG("START CHANNEL %d CMD processing %s\n", - id, (code == MHI_EV_CC_SUCCESS) ? "successful" : - "failure"); - - pkt->ptr = MHI_TRE_EVT_CMD_COMPLETION_PTR(0); - pkt->dword[0] = MHI_TRE_EVT_CMD_COMPLETION_D0(code); - pkt->dword[1] = MHI_TRE_EVT_CMD_COMPLETION_D1; - break; - } - case MHI_PKT_TYPE_RESET_CHAN_CMD: - { - int id = MHI_TRE_GET_ID(pkt); - struct mhi_sat_device *sat_dev = - find_sat_dev_by_id(sat_cntrl, id, - SAT_CTXT_TYPE_CHAN); - - MHI_SAT_ASSERT(!sat_dev, - "No device with given channel ID\n"); - - MHI_SAT_ASSERT(!sat_dev->chan_started, - "Resetting unstarted channel!"); - - mhi_unprepare_from_transfer(sat_dev->mhi_dev); - sat_dev->chan_started = false; - - MHI_SAT_LOG( - "RESET CHANNEL %d CMD processing successful\n", - id); - - pkt->ptr = MHI_TRE_EVT_CMD_COMPLETION_PTR(0); - pkt->dword[0] = MHI_TRE_EVT_CMD_COMPLETION_D0( - MHI_EV_CC_SUCCESS); - pkt->dword[1] = MHI_TRE_EVT_CMD_COMPLETION_D1; - break; - } - default: - MHI_SAT_ASSERT(1, "Unhandled command!"); - break; - } - } -} - -static void mhi_sat_process_worker(struct work_struct *work) -{ - struct mhi_sat_cntrl *sat_cntrl = container_of(work, - struct mhi_sat_cntrl, process_work); - struct mhi_sat_subsys *subsys = sat_cntrl->subsys; - struct mhi_sat_packet *packet, *tmp; - struct sat_header *hdr; - struct sat_tre *pkt; - LIST_HEAD(head); - - MHI_SAT_LOG("Entered\n"); - - spin_lock_irq(&sat_cntrl->pkt_lock); - list_splice_tail_init(&sat_cntrl->packet_list, &head); - spin_unlock_irq(&sat_cntrl->pkt_lock); - - list_for_each_entry_safe(packet, tmp, &head, node) { - hdr = packet->msg; - pkt = SAT_TRE_OFFSET(packet->msg); - - list_del(&packet->node); - - mhi_sat_process_cmds(sat_cntrl, hdr, pkt); - - /* send response event(s) */ - mhi_sat_send_msg(sat_cntrl, SAT_MSG_ID_EVT, hdr->seq, - packet->msg, - SAT_MSG_SIZE(SAT_TRE_NUM_PKTS( - hdr->payload_size))); - - kfree(packet); - } - - MHI_SAT_LOG("Exited\n"); -} - -static void mhi_sat_connect_worker(struct work_struct *work) -{ - struct mhi_sat_cntrl *sat_cntrl = container_of(work, - struct mhi_sat_cntrl, connect_work); - struct mhi_sat_subsys *subsys = sat_cntrl->subsys; - struct sat_tre *pkt; - void *msg; - int ret; - - if (!subsys->rpdev || sat_cntrl->max_devices != sat_cntrl->num_devices - || sat_cntrl->active) - return; - - MHI_SAT_LOG("Entered\n"); - - msg = kmalloc(SAT_MSG_SIZE(3), GFP_ATOMIC); - if (!msg) - return; - - sat_cntrl->active = true; - - pkt = SAT_TRE_OFFSET(msg); - - /* prepare #1 MHI_CFG HELLO event */ - pkt->ptr = MHI_TRE_EVT_CFG_PTR(sat_cntrl->mhi_cntrl->base_addr); - pkt->dword[0] = MHI_TRE_EVT_CFG_D0(sat_cntrl->er_base, - sat_cntrl->num_er); - pkt->dword[1] = MHI_TRE_EVT_CFG_D1; - pkt++; - - /* prepare M0 event */ - pkt->ptr = MHI_TRE_EVT_MHI_STATE_PTR; - pkt->dword[0] = MHI_TRE_EVT_MHI_STATE_D0(MHI_STATE_M0); - pkt->dword[1] = MHI_TRE_EVT_MHI_STATE_D1; - pkt++; - - /* prepare AMSS event */ - pkt->ptr = MHI_TRE_EVT_EE_PTR; - pkt->dword[0] = MHI_TRE_EVT_EE_D0(MHI_EE_AMSS); - pkt->dword[1] = MHI_TRE_EVT_EE_D1; - - ret = mhi_sat_send_msg(sat_cntrl, SAT_MSG_ID_EVT, SAT_RESERVED_SEQ_NUM, - msg, SAT_MSG_SIZE(3)); - kfree(msg); - if (ret) { - MHI_SAT_ERR("Failed to send hello packet:%d\n", ret); - sat_cntrl->active = false; - return; - } - - MHI_SAT_LOG("Device 0x%x sent hello packet\n", sat_cntrl->dev_id); -} - -static void mhi_sat_process_events(struct mhi_sat_cntrl *sat_cntrl, - struct sat_header *hdr, struct sat_tre *pkt) -{ - int num_pkts = SAT_TRE_NUM_PKTS(hdr->payload_size); - int i; - - for (i = 0; i < num_pkts; i++, pkt++) { - if (MHI_TRE_GET_TYPE(pkt) == - MHI_PKT_TYPE_CMD_COMPLETION_EVENT) { - if (hdr->reply_seq != sat_cntrl->last_cmd_seq) - continue; - - sat_cntrl->last_cmd_ccs = MHI_TRE_GET_CCS(pkt); - complete(&sat_cntrl->completion); - } - } -} - -static int mhi_sat_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len, - void *priv, u32 src) -{ - struct mhi_sat_subsys *subsys = dev_get_drvdata(&rpdev->dev); - struct sat_header *hdr = data; - struct sat_tre *pkt = SAT_TRE_OFFSET(data); - struct mhi_sat_cntrl *sat_cntrl; - struct mhi_sat_packet *packet; - - MHI_SAT_ASSERT(!mhi_sat_isvalid_header(hdr, len), "Invalid header!\n"); - - /* find controller packet was sent for */ - sat_cntrl = find_sat_cntrl_by_id(subsys, hdr->dev_id); - - MHI_SAT_ASSERT(!sat_cntrl, "Packet for unknown device!\n"); - - /* handle events directly regardless of controller active state */ - if (hdr->msg_id == SAT_MSG_ID_EVT) { - mhi_sat_process_events(sat_cntrl, hdr, pkt); - return 0; - } - - /* Inactive controller cannot process incoming commands */ - if (unlikely(!sat_cntrl->active)) { - MHI_SAT_ERR("Message for inactive controller!\n"); - return 0; - } - - /* offload commands to process worker */ - packet = kmalloc(sizeof(*packet) + len, GFP_ATOMIC); - if (!packet) - return 0; - - packet->cntrl = sat_cntrl; - packet->msg = packet + 1; - memcpy(packet->msg, data, len); - - spin_lock_irq(&sat_cntrl->pkt_lock); - list_add_tail(&packet->node, &sat_cntrl->packet_list); - spin_unlock_irq(&sat_cntrl->pkt_lock); - - schedule_work(&sat_cntrl->process_work); - - return 0; -} - -static void mhi_sat_rpmsg_remove(struct rpmsg_device *rpdev) -{ - struct mhi_sat_subsys *subsys = dev_get_drvdata(&rpdev->dev); - struct mhi_sat_cntrl *sat_cntrl; - struct mhi_sat_device *sat_dev; - struct mhi_buf *buf, *tmp; - - MHI_SUBSYS_LOG("Enter\n"); - - /* unprepare each controller/device from transfer */ - mutex_lock(&subsys->cntrl_mutex); - list_for_each_entry(sat_cntrl, &subsys->cntrl_list, node) { - sat_cntrl->active = false; - - flush_work(&sat_cntrl->connect_work); - flush_work(&sat_cntrl->process_work); - - mutex_lock(&sat_cntrl->list_mutex); - list_for_each_entry(sat_dev, &sat_cntrl->dev_list, node) { - if (sat_dev->chan_started) { - mhi_unprepare_from_transfer(sat_dev->mhi_dev); - sat_dev->chan_started = false; - } - } - - list_for_each_entry_safe(buf, tmp, &sat_cntrl->addr_map_list, - node) { - dma_unmap_resource(sat_cntrl->mhi_cntrl->dev, - buf->dma_addr, buf->len, - DMA_BIDIRECTIONAL, 0); - list_del(&buf->node); - kfree(buf); - } - mutex_unlock(&sat_cntrl->list_mutex); - - MHI_SAT_LOG("Removed RPMSG link\n"); - } - mutex_unlock(&subsys->cntrl_mutex); - - subsys->rpdev = NULL; -} - -static int mhi_sat_rpmsg_probe(struct rpmsg_device *rpdev) -{ - struct mhi_sat_subsys *subsys; - struct mhi_sat_cntrl *sat_cntrl; - const char *subsys_name; - int ret; - - ret = of_property_read_string(rpdev->dev.parent->of_node, "label", - &subsys_name); - if (ret) - return ret; - - /* find which subsystem has probed */ - subsys = find_subsys_by_name(subsys_name); - if (!subsys) - return -EINVAL; - - MHI_SUBSYS_LOG("Received RPMSG probe\n"); - - dev_set_drvdata(&rpdev->dev, subsys); - - subsys->rpdev = rpdev; - - /* schedule work for each controller as GLINK has connected */ - spin_lock_irq(&subsys->cntrl_lock); - list_for_each_entry(sat_cntrl, &subsys->cntrl_list, node) - schedule_work(&sat_cntrl->connect_work); - spin_unlock_irq(&subsys->cntrl_lock); - - return 0; -} - -static struct rpmsg_device_id mhi_sat_rpmsg_match_table[] = { - { .name = "mhi_sat" }, - { }, -}; - -static struct rpmsg_driver mhi_sat_rpmsg_driver = { - .id_table = mhi_sat_rpmsg_match_table, - .probe = mhi_sat_rpmsg_probe, - .remove = mhi_sat_rpmsg_remove, - .callback = mhi_sat_rpmsg_cb, - .drv = { - .name = "mhi,sat_rpmsg", - }, -}; - -static void mhi_sat_dev_status_cb(struct mhi_device *mhi_dev, - enum MHI_CB mhi_cb) -{ -} - -static void mhi_sat_dev_remove(struct mhi_device *mhi_dev) -{ - struct mhi_sat_device *sat_dev = mhi_device_get_devdata(mhi_dev); - struct mhi_sat_cntrl *sat_cntrl = sat_dev->cntrl; - struct mhi_sat_subsys *subsys = sat_cntrl->subsys; - struct mhi_buf *buf, *tmp; - struct sat_tre *pkt; - void *msg; - int ret; - - /* remove device node from probed list */ - mutex_lock(&sat_cntrl->list_mutex); - list_del(&sat_dev->node); - mutex_unlock(&sat_cntrl->list_mutex); - - sat_cntrl->num_devices--; - - /* prepare SYS_ERR command if first device is being removed */ - if (sat_cntrl->active) { - sat_cntrl->active = false; - - /* flush all pending work */ - flush_work(&sat_cntrl->connect_work); - flush_work(&sat_cntrl->process_work); - - msg = kmalloc(SAT_MSG_SIZE(1), GFP_KERNEL); - - MHI_SAT_ASSERT(!msg, "Unable to malloc for SYS_ERR message!\n"); - - pkt = SAT_TRE_OFFSET(msg); - pkt->ptr = MHI_TRE_CMD_SYS_ERR_PTR; - pkt->dword[0] = MHI_TRE_CMD_SYS_ERR_D0; - pkt->dword[1] = MHI_TRE_CMD_SYS_ERR_D1; - - /* acquire cmd_wait_mutex before sending command */ - mutex_lock(&sat_cntrl->cmd_wait_mutex); - - ret = mhi_sat_send_msg(sat_cntrl, SAT_MSG_ID_CMD, - SAT_RESERVED_SEQ_NUM, msg, - SAT_MSG_SIZE(1)); - kfree(msg); - if (ret) { - MHI_SAT_ERR("Failed to notify SYS_ERR\n"); - mutex_unlock(&sat_cntrl->cmd_wait_mutex); - goto exit_sys_err_send; - } - - MHI_SAT_LOG("SYS_ERR command sent\n"); - - /* blocking call to wait for command completion event */ - mhi_sat_wait_cmd_completion(sat_cntrl); - - mutex_unlock(&sat_cntrl->cmd_wait_mutex); - } - -exit_sys_err_send: - /* exit if some devices are still present */ - if (sat_cntrl->num_devices) - return; - - /* remove address mappings */ - mutex_lock(&sat_cntrl->list_mutex); - list_for_each_entry_safe(buf, tmp, &sat_cntrl->addr_map_list, node) { - dma_unmap_resource(sat_cntrl->mhi_cntrl->dev, buf->dma_addr, - buf->len, DMA_BIDIRECTIONAL, 0); - list_del(&buf->node); - kfree(buf); - } - mutex_unlock(&sat_cntrl->list_mutex); - - /* remove controller */ - mutex_lock(&subsys->cntrl_mutex); - spin_lock_irq(&subsys->cntrl_lock); - list_del(&sat_cntrl->node); - spin_unlock_irq(&subsys->cntrl_lock); - mutex_unlock(&subsys->cntrl_mutex); - - mutex_destroy(&sat_cntrl->cmd_wait_mutex); - mutex_destroy(&sat_cntrl->list_mutex); - MHI_SAT_LOG("Satellite controller node removed\n"); - kfree(sat_cntrl); -} - -static int mhi_sat_dev_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - struct mhi_sat_device *sat_dev; - struct mhi_sat_cntrl *sat_cntrl; - struct device_node *of_node = mhi_dev->dev.of_node; - struct mhi_sat_subsys *subsys = &mhi_sat_driver.subsys[id->driver_data]; - u32 dev_id = MHI_SAT_CREATE_DEVICE_ID(mhi_dev->dev_id, mhi_dev->domain, - mhi_dev->bus, mhi_dev->slot); - int ret; - - /* find controller with unique device ID based on topology */ - sat_cntrl = find_sat_cntrl_by_id(subsys, dev_id); - if (!sat_cntrl) { - sat_cntrl = kzalloc(sizeof(*sat_cntrl), GFP_KERNEL); - if (!sat_cntrl) - return -ENOMEM; - - /* - * max_devices will be read from device tree node. Set it to - * -1 before it is populated to avoid false positive when - * RPMSG probe schedules connect worker but no device has - * probed in which case num_devices and max_devices are both - * zero. - */ - sat_cntrl->max_devices = -1; - sat_cntrl->dev_id = dev_id; - sat_cntrl->er_base = mhi_dev->dl_event_id; - sat_cntrl->mhi_cntrl = mhi_dev->mhi_cntrl; - sat_cntrl->last_cmd_seq = SAT_RESERVED_SEQ_NUM; - sat_cntrl->subsys = subsys; - init_completion(&sat_cntrl->completion); - mutex_init(&sat_cntrl->list_mutex); - mutex_init(&sat_cntrl->cmd_wait_mutex); - spin_lock_init(&sat_cntrl->pkt_lock); - INIT_WORK(&sat_cntrl->connect_work, mhi_sat_connect_worker); - INIT_WORK(&sat_cntrl->process_work, mhi_sat_process_worker); - INIT_LIST_HEAD(&sat_cntrl->dev_list); - INIT_LIST_HEAD(&sat_cntrl->addr_map_list); - INIT_LIST_HEAD(&sat_cntrl->packet_list); - - mutex_lock(&subsys->cntrl_mutex); - spin_lock_irq(&subsys->cntrl_lock); - list_add(&sat_cntrl->node, &subsys->cntrl_list); - spin_unlock_irq(&subsys->cntrl_lock); - mutex_unlock(&subsys->cntrl_mutex); - - MHI_SAT_LOG("Controller allocated for 0x%x\n", dev_id); - } - - /* set maximum devices for subsystem from device tree */ - if (of_node) { - ret = of_property_read_u32(of_node, "mhi,max-devices", - &sat_cntrl->max_devices); - if (ret) { - MHI_SAT_ERR("Could not find max-devices in DT node\n"); - return -EINVAL; - } - } - - /* get event ring base and max indexes */ - sat_cntrl->er_base = min(sat_cntrl->er_base, mhi_dev->dl_event_id); - sat_cntrl->er_max = max(sat_cntrl->er_base, mhi_dev->dl_event_id); - - sat_dev = devm_kzalloc(&mhi_dev->dev, sizeof(*sat_dev), GFP_KERNEL); - if (!sat_dev) - return -ENOMEM; - - sat_dev->mhi_dev = mhi_dev; - sat_dev->cntrl = sat_cntrl; - - mutex_lock(&sat_cntrl->list_mutex); - list_add(&sat_dev->node, &sat_cntrl->dev_list); - mutex_unlock(&sat_cntrl->list_mutex); - - mhi_device_set_devdata(mhi_dev, sat_dev); - - sat_cntrl->num_devices++; - - /* schedule connect worker if all devices for controller have probed */ - if (sat_cntrl->num_devices == sat_cntrl->max_devices) { - /* number of event rings is 1 more than difference in IDs */ - sat_cntrl->num_er = (sat_cntrl->er_max - sat_cntrl->er_base) + - 1; - MHI_SAT_LOG("All satellite channels probed!\n"); - schedule_work(&sat_cntrl->connect_work); - } - - return 0; -} - -/* .driver_data stores subsys id */ -static const struct mhi_device_id mhi_sat_dev_match_table[] = { - /* ADSP */ - { .chan = "ADSP_0", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_1", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_2", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_3", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_4", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_5", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_6", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_7", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_8", .driver_data = SUBSYS_ADSP }, - { .chan = "ADSP_9", .driver_data = SUBSYS_ADSP }, - /* CDSP */ - { .chan = "CDSP_0", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_1", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_2", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_3", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_4", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_5", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_6", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_7", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_8", .driver_data = SUBSYS_CDSP }, - { .chan = "CDSP_9", .driver_data = SUBSYS_CDSP }, - /* SLPI */ - { .chan = "SLPI_0", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_1", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_2", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_3", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_4", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_5", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_6", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_7", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_8", .driver_data = SUBSYS_SLPI }, - { .chan = "SLPI_9", .driver_data = SUBSYS_SLPI }, - /* MODEM */ - { .chan = "MODEM_0", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_1", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_2", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_3", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_4", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_5", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_6", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_7", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_8", .driver_data = SUBSYS_MODEM }, - { .chan = "MODEM_9", .driver_data = SUBSYS_MODEM }, - {}, -}; - -static struct mhi_driver mhi_sat_dev_driver = { - .id_table = mhi_sat_dev_match_table, - .probe = mhi_sat_dev_probe, - .remove = mhi_sat_dev_remove, - .status_cb = mhi_sat_dev_status_cb, - .driver = { - .name = MHI_SAT_DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -int mhi_sat_trigger_init(void *data, u64 val) -{ - struct mhi_sat_subsys *subsys; - int i, ret; - - if (mhi_sat_driver.deferred_init_done) - return -EIO; - - ret = register_rpmsg_driver(&mhi_sat_rpmsg_driver); - if (ret) - goto error_sat_trigger_init; - - ret = mhi_driver_register(&mhi_sat_dev_driver); - if (ret) - goto error_sat_trigger_register; - - mhi_sat_driver.deferred_init_done = true; - - return 0; - -error_sat_trigger_register: - unregister_rpmsg_driver(&mhi_sat_rpmsg_driver); - -error_sat_trigger_init: - subsys = mhi_sat_driver.subsys; - for (i = 0; i < mhi_sat_driver.num_subsys; i++, subsys++) { - ipc_log_context_destroy(subsys->ipc_log); - mutex_destroy(&subsys->cntrl_mutex); - } - kfree(mhi_sat_driver.subsys); - mhi_sat_driver.subsys = NULL; - - return ret; -} - -DEFINE_SIMPLE_ATTRIBUTE(mhi_sat_debugfs_fops, NULL, - mhi_sat_trigger_init, "%llu\n"); - -static int mhi_sat_init(void) -{ - struct mhi_sat_subsys *subsys; - int i, ret; - - subsys = kcalloc(SUBSYS_MAX, sizeof(*subsys), GFP_KERNEL); - if (!subsys) - return -ENOMEM; - - mhi_sat_driver.subsys = subsys; - mhi_sat_driver.num_subsys = SUBSYS_MAX; - mhi_sat_driver.klog_lvl = KLOG_LVL; - mhi_sat_driver.ipc_log_lvl = IPC_LOG_LVL; - - for (i = 0; i < mhi_sat_driver.num_subsys; i++, subsys++) { - char log[32]; - - subsys->name = subsys_names[i]; - mutex_init(&subsys->cntrl_mutex); - spin_lock_init(&subsys->cntrl_lock); - INIT_LIST_HEAD(&subsys->cntrl_list); - scnprintf(log, sizeof(log), "mhi_sat_%s", subsys->name); - subsys->ipc_log = ipc_log_context_create(IPC_LOG_PAGES, log, 0); - } - - /* create debugfs entry if defer_init is enabled */ - if (mhi_sat_defer_init) { - mhi_sat_driver.dentry = debugfs_create_dir("mhi_sat", NULL); - if (IS_ERR_OR_NULL(mhi_sat_driver.dentry)) { - ret = -ENODEV; - goto error_sat_init; - } - - debugfs_create_file("debug", 0444, mhi_sat_driver.dentry, NULL, - &mhi_sat_debugfs_fops); - - return 0; - } - - ret = register_rpmsg_driver(&mhi_sat_rpmsg_driver); - if (ret) - goto error_sat_init; - - ret = mhi_driver_register(&mhi_sat_dev_driver); - if (ret) - goto error_sat_register; - - return 0; - -error_sat_register: - unregister_rpmsg_driver(&mhi_sat_rpmsg_driver); - -error_sat_init: - subsys = mhi_sat_driver.subsys; - for (i = 0; i < mhi_sat_driver.num_subsys; i++, subsys++) { - ipc_log_context_destroy(subsys->ipc_log); - mutex_destroy(&subsys->cntrl_mutex); - } - kfree(mhi_sat_driver.subsys); - mhi_sat_driver.subsys = NULL; - - return ret; -} - -module_init(mhi_sat_init); - diff --git a/quectel_MHI/src/devices/mhi_uci.c b/quectel_MHI/src/devices/mhi_uci.c deleted file mode 100644 index 474b022..0000000 --- a/quectel_MHI/src/devices/mhi_uci.c +++ /dev/null @@ -1,981 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#if 1 -static inline void *ipc_log_context_create(int max_num_pages, - const char *modname, uint16_t user_version) -{ return NULL; } -static inline int ipc_log_string(void *ilctxt, const char *fmt, ...) -{ return -EINVAL; } -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/mhi.h" - -#define DEVICE_NAME "mhi" -#define MHI_UCI_DRIVER_NAME "mhi_uci_q" - -struct uci_chan { - wait_queue_head_t wq; - spinlock_t lock; - struct list_head pending; /* user space waiting to read */ - struct uci_buf *cur_buf; /* current buffer user space reading */ - size_t rx_size; -}; - -struct uci_buf { - struct page *page; - void *data; - size_t len; - unsigned nr_trb; - struct list_head node; -}; - -struct uci_dev { - struct list_head node; - dev_t devt; - struct device *dev; - struct mhi_device *mhi_dev; - const char *chan; - struct mutex mutex; /* sync open and close */ - struct mutex r_mutex; - struct mutex w_mutex; - struct uci_chan ul_chan; - struct uci_chan dl_chan; - size_t mtu; - int ref_count; - bool enabled; - unsigned rx_error; - unsigned nr_trb; - unsigned nr_trbs; - struct uci_buf *uci_buf; - struct ktermios termios; - size_t bytes_xferd; -}; - -struct mhi_uci_drv { - struct list_head head; - struct mutex lock; - struct class *class; - int major; - dev_t dev_t; -}; - -static int uci_msg_lvl = MHI_MSG_LVL_ERROR; -module_param( uci_msg_lvl, uint, S_IRUGO | S_IWUSR); - -#define MSG_VERB(fmt, ...) do { \ - if (uci_msg_lvl <= MHI_MSG_LVL_VERBOSE) \ - pr_err("[D][%s] " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -#define MSG_LOG(fmt, ...) do { \ - if (uci_msg_lvl <= MHI_MSG_LVL_INFO) \ - pr_err("[I][%s] " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -#define MSG_ERR(fmt, ...) do { \ - if (uci_msg_lvl <= MHI_MSG_LVL_ERROR) \ - pr_err("[E][%s] " fmt, __func__, ##__VA_ARGS__); \ - } while (0) - -#define MAX_UCI_DEVICES (64) -#define QUEC_MHI_UCI_ALWAYS_OPEN //by now, sdx20 can not handle "start-reset-start" operation, so the simply solution is keep start state - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) -#ifdef TCGETS2 -__weak int user_termios_to_kernel_termios(struct ktermios *k, - struct termios2 __user *u) -{ - return copy_from_user(k, u, sizeof(struct termios2)); -} -__weak int kernel_termios_to_user_termios(struct termios2 __user *u, - struct ktermios *k) -{ - return copy_to_user(u, k, sizeof(struct termios2)); -} -__weak int user_termios_to_kernel_termios_1(struct ktermios *k, - struct termios __user *u) -{ - return copy_from_user(k, u, sizeof(struct termios)); -} -__weak int kernel_termios_to_user_termios_1(struct termios __user *u, - struct ktermios *k) -{ - return copy_to_user(u, k, sizeof(struct termios)); -} - -#else - -__weak int user_termios_to_kernel_termios(struct ktermios *k, - struct termios __user *u) -{ - return copy_from_user(k, u, sizeof(struct termios)); -} -__weak int kernel_termios_to_user_termios(struct termios __user *u, - struct ktermios *k) -{ - return copy_to_user(u, k, sizeof(struct termios)); -} -#endif /* TCGETS2 */ -#endif - -static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); -static struct mhi_uci_drv mhi_uci_drv; - -static int mhi_queue_inbound(struct uci_dev *uci_dev) -{ - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - int nr_trbs = mhi_get_no_free_descriptors(mhi_dev, DMA_FROM_DEVICE); - size_t mtu = uci_dev->mtu; - void *buf; - struct uci_buf *uci_buf; - int ret = -EIO, i; - - if (uci_dev->uci_buf == NULL) { - uci_dev->nr_trb = 0; - uci_dev->nr_trbs = (nr_trbs + 1); - uci_dev->uci_buf = kmalloc_array(uci_dev->nr_trbs, sizeof(*uci_buf), GFP_KERNEL); - if (!uci_dev->uci_buf) - return -ENOMEM; - - uci_buf = uci_dev->uci_buf; - for (i = 0; i < uci_dev->nr_trbs; i++, uci_buf++) { - uci_buf->page = alloc_pages(GFP_KERNEL, get_order(mtu)); - if (!uci_buf->page) - return -ENOMEM; - uci_buf->data = page_address(uci_buf->page); - uci_buf->len = 0; - uci_buf->nr_trb = i; - if (mhi_dev->dl_chan_id == MHI_CLIENT_DUN_IN) { - //MSG_ERR("[%d] = %p\n", i, uci_buf->data); - } - } - } - - for (i = 0; i < nr_trbs; i++) { - #if 0 - buf = kmalloc(mtu + sizeof(*uci_buf), GFP_KERNEL); - if (!buf) - return -ENOMEM; - - uci_buf = buf + mtu; - uci_buf->data = buf; - #else - uci_buf = &uci_dev->uci_buf[i]; - buf = uci_buf->data; - #endif - - MSG_VERB("Allocated buf %d of %d size %zu\n", i, nr_trbs, mtu); - - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, buf, mtu, - MHI_EOT); - if (ret) { - #if 0 - kfree(buf); - #endif - MSG_ERR("Failed to queue buffer %d\n", i); - return ret; - } - } - - return ret; -} - -static long mhi_uci_ioctl(struct file *file, - unsigned int cmd, - unsigned long arg) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - long ret = -ERESTARTSYS; - - mutex_lock(&uci_dev->mutex); - if (uci_dev->enabled) - ret = mhi_ioctl(mhi_dev, cmd, arg); - - if (uci_dev->enabled) { - switch (cmd) { - case TCGETS: -#ifndef TCGETS2 - ret = kernel_termios_to_user_termios((struct termios __user *)arg, &uci_dev->termios); -#else - ret = kernel_termios_to_user_termios_1((struct termios __user *)arg, &uci_dev->termios); -#endif - break; - - case TCSETSF: - case TCSETS: -#ifndef TCGETS2 - ret = user_termios_to_kernel_termios(&uci_dev->termios, (struct termios __user *)arg); -#else - ret = user_termios_to_kernel_termios_1(&uci_dev->termios, (struct termios __user *)arg); -#endif - break; - - case TCFLSH: - ret = 0; - break; - - default: - break; - } - } - mutex_unlock(&uci_dev->mutex); - - return ret; -} - -static int mhi_uci_release(struct inode *inode, struct file *file) -{ - struct uci_dev *uci_dev = file->private_data; - - mutex_lock(&uci_dev->mutex); - uci_dev->ref_count--; - if (!uci_dev->ref_count) { - struct uci_chan *uci_chan; - - MSG_LOG("Last client left, closing node\n"); - - if (uci_dev->enabled) - mhi_unprepare_from_transfer(uci_dev->mhi_dev); - - /* clean inbound channel */ - uci_chan = &uci_dev->dl_chan; - if (uci_dev->uci_buf) { - unsigned nr_trb = 0; - - for (nr_trb = 0; nr_trb < uci_dev->nr_trbs; nr_trb++) { - if (uci_dev->uci_buf[nr_trb].page) - __free_pages(uci_dev->uci_buf[nr_trb].page, get_order(uci_dev->mtu)); - } - kfree(uci_dev->uci_buf); - } - - uci_chan->cur_buf = NULL; - - if (!uci_dev->enabled) { - MSG_LOG("Node is deleted, freeing dev node\n"); - mutex_unlock(&uci_dev->mutex); - mutex_destroy(&uci_dev->mutex); - clear_bit(MINOR(uci_dev->devt), uci_minors); - kfree(uci_dev); - return 0; - } - } - - MSG_LOG("exit: ref_count:%d\n", uci_dev->ref_count); - - mutex_unlock(&uci_dev->mutex); - - return 0; -} - -static unsigned int mhi_uci_poll(struct file *file, poll_table *wait) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - struct uci_chan *uci_chan; - unsigned int mask = 0; - - poll_wait(file, &uci_dev->dl_chan.wq, wait); - // ADPL and QDSS do not need poll write. xingduo.du 2023-02-16 - // poll_wait(file, &uci_dev->ul_chan.wq, wait); - - uci_chan = &uci_dev->dl_chan; - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - mask = POLLERR; - } else if (!list_empty(&uci_chan->pending) || uci_chan->cur_buf) { - MSG_VERB("Client can read from node\n"); - mask |= POLLIN | POLLRDNORM; - } - spin_unlock_bh(&uci_chan->lock); - - // ADPL and QDSS are single channel, ul_chan not be initilized. xingduo.du 2023-02-27 - if (mhi_dev->ul_chan) { - poll_wait(file, &uci_dev->ul_chan.wq, wait); - uci_chan = &uci_dev->ul_chan; - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - mask |= POLLERR; - } else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) { - MSG_VERB("Client can write to node\n"); - mask |= POLLOUT | POLLWRNORM; - } - - if (!uci_dev->enabled) - mask |= POLLHUP; - if (uci_dev->rx_error) - mask |= POLLERR; - - spin_unlock_bh(&uci_chan->lock); - } - - MSG_LOG("Client attempted to poll, returning mask 0x%x\n", mask); - - return mask; -} - -static ssize_t mhi_uci_write(struct file *file, - const char __user *buf, - size_t count, - loff_t *offp) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - struct uci_chan *uci_chan = &uci_dev->ul_chan; - size_t bytes_xfered = 0; - int ret, nr_avail; - - if (!buf || !count || uci_dev->rx_error) - return -EINVAL; - - /* confirm channel is active */ - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - spin_unlock_bh(&uci_chan->lock); - return -ERESTARTSYS; - } - - MSG_VERB("Enter: to xfer:%zu bytes\n", count); - - while (count) { - size_t xfer_size; - void *kbuf; - enum MHI_FLAGS flags; - - spin_unlock_bh(&uci_chan->lock); - - nr_avail = mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE); - if ((nr_avail == 0) && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; - - /* wait for free descriptors */ - ret = wait_event_interruptible(uci_chan->wq, - (!uci_dev->enabled) || - (nr_avail = mhi_get_no_free_descriptors(mhi_dev, - DMA_TO_DEVICE)) > 0); - - if (ret == -ERESTARTSYS || !uci_dev->enabled) { - MSG_LOG("Exit signal caught for node or not enabled\n"); - return -ERESTARTSYS; - } - - xfer_size = min_t(size_t, count, uci_dev->mtu); - kbuf = kmalloc(xfer_size, GFP_KERNEL); - if (!kbuf) { - MSG_ERR("Failed to allocate memory %zu\n", xfer_size); - return -ENOMEM; - } - - ret = copy_from_user(kbuf, buf, xfer_size); - if (unlikely(ret)) { - kfree(kbuf); - return ret; - } - - spin_lock_bh(&uci_chan->lock); - - /* if ring is full after this force EOT */ - if (nr_avail > 1 && (count - xfer_size)) - flags = MHI_CHAIN; - else - flags = MHI_EOT; - - if (uci_dev->enabled) - ret = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, kbuf, - xfer_size, flags); - else - ret = -ERESTARTSYS; - - if (ret) { - kfree(kbuf); - goto sys_interrupt; - } - - bytes_xfered += xfer_size; - count -= xfer_size; - buf += xfer_size; - } - - spin_unlock_bh(&uci_chan->lock); - MSG_VERB("Exit: Number of bytes xferred:%zu\n", bytes_xfered); - - return bytes_xfered; - -sys_interrupt: - spin_unlock_bh(&uci_chan->lock); - - return ret; -} - -static ssize_t mhi_uci_read(struct file *file, - char __user *buf, - size_t count, - loff_t *ppos) -{ - struct uci_dev *uci_dev = file->private_data; - struct mhi_device *mhi_dev = uci_dev->mhi_dev; - struct uci_chan *uci_chan = &uci_dev->dl_chan; - struct uci_buf *uci_buf; - char *ptr; - size_t to_copy; - int ret = 0; - - if (!buf || uci_dev->rx_error) - return -EINVAL; - - MSG_VERB("Client provided buf len:%zu\n", count); - - /* confirm channel is active */ - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - spin_unlock_bh(&uci_chan->lock); - return -ERESTARTSYS; - } - - /* No data available to read, wait */ - if (!uci_chan->cur_buf && list_empty(&uci_chan->pending)) { - MSG_VERB("No data available to read waiting\n"); - - spin_unlock_bh(&uci_chan->lock); - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - ret = wait_event_interruptible(uci_chan->wq, - (!uci_dev->enabled || - !list_empty(&uci_chan->pending))); - if (ret == -ERESTARTSYS) { - MSG_LOG("Exit signal caught for node\n"); - return -ERESTARTSYS; - } - - spin_lock_bh(&uci_chan->lock); - if (!uci_dev->enabled) { - MSG_LOG("node is disabled\n"); - ret = -ERESTARTSYS; - goto read_error; - } - } - - /* new read, get the next descriptor from the list */ - if (!uci_chan->cur_buf) { - uci_buf = list_first_entry_or_null(&uci_chan->pending, - struct uci_buf, node); - if (unlikely(!uci_buf)) { - ret = -EIO; - goto read_error; - } - - if (uci_buf->node.next == LIST_POISON1 || uci_buf->node.prev == LIST_POISON1) { - dump_stack(); - ret = -EIO; - MSG_ERR("chan[%d] data=%p, len=%zd, nr_trb=%d\n", - mhi_dev->dl_chan_id, uci_buf->data, uci_buf->len, uci_buf->nr_trb); - goto read_error; - } - - list_del(&uci_buf->node); - uci_chan->cur_buf = uci_buf; - uci_chan->rx_size = uci_buf->len; - MSG_VERB("Got pkt of size:%zu\n", uci_chan->rx_size); - } - - uci_buf = uci_chan->cur_buf; - spin_unlock_bh(&uci_chan->lock); - - /* Copy the buffer to user space */ - to_copy = min_t(size_t, count, uci_chan->rx_size); - ptr = uci_buf->data + (uci_buf->len - uci_chan->rx_size); - ret = copy_to_user(buf, ptr, to_copy); - if (ret) - return ret; - - MSG_VERB("Copied %zu of %zu bytes\n", to_copy, uci_chan->rx_size); - uci_chan->rx_size -= to_copy; - - /* we finished with this buffer, queue it back to hardware */ - if (!uci_chan->rx_size) { - spin_lock_bh(&uci_chan->lock); - uci_chan->cur_buf = NULL; - - if (uci_dev->enabled) -#if 1 //this can make the address in ring do not change - { - if (uci_buf->page) { - unsigned nr_trb = uci_buf->nr_trb ? (uci_buf->nr_trb - 1) : (uci_dev->nr_trbs - 1); - - uci_buf = &uci_dev->uci_buf[nr_trb]; - ret = mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, - uci_buf->data, uci_dev->mtu, - MHI_EOT); - } else { - kfree(uci_buf); - ret = 0; - } - } -#endif - else - ret = -ERESTARTSYS; - - if (ret) { - MSG_ERR("Failed to recycle element for chan:%d , ret=%d\n", mhi_dev->ul_chan_id, ret); -#if 0 - kfree(uci_buf->data); -#endif - goto read_error; - } - - spin_unlock_bh(&uci_chan->lock); - } - - MSG_VERB("Returning %zu bytes\n", to_copy); - - return to_copy; - -read_error: - spin_unlock_bh(&uci_chan->lock); - - return ret; -} - -static ssize_t mhi_uci_write_mutex(struct file *file, - const char __user *buf, - size_t count, - loff_t *offp) -{ - struct uci_dev *uci_dev = file->private_data; - int ret; - - ret = mutex_lock_interruptible(&uci_dev->w_mutex); /*concurrent writes */ - if (ret < 0) - return -ERESTARTSYS; - - ret = mhi_uci_write(file, buf, count, offp); - mutex_unlock(&uci_dev->w_mutex); - - return ret; -} - -static ssize_t mhi_uci_read_mutex(struct file *file, - char __user *buf, - size_t count, - loff_t *ppos) -{ - struct uci_dev *uci_dev = file->private_data; - int ret; - - ret = mutex_lock_interruptible(&uci_dev->r_mutex); /*concurrent reads */ - if (ret < 0) - return -ERESTARTSYS; - - ret = mhi_uci_read(file, buf, count, ppos); - mutex_unlock(&uci_dev->r_mutex); - - return ret; -} - -static int mhi_uci_open(struct inode *inode, struct file *filp) -{ - struct uci_dev *uci_dev = NULL, *tmp_dev; - int ret = -EIO; - struct uci_chan *dl_chan; - - mutex_lock(&mhi_uci_drv.lock); - list_for_each_entry(tmp_dev, &mhi_uci_drv.head, node) { - if (tmp_dev->devt == inode->i_rdev) { - uci_dev = tmp_dev; - break; - } - } - - /* could not find a minor node */ - if (!uci_dev) - goto error_exit; - - mutex_lock(&uci_dev->mutex); - if (!uci_dev->enabled) { - MSG_ERR("Node exist, but not in active state!\n"); - goto error_open_chan; - } - - uci_dev->ref_count++; - - MSG_LOG("Node open, ref counts %u\n", uci_dev->ref_count); - - if (uci_dev->ref_count == 1) { - MSG_LOG("Starting channel\n"); - ret = mhi_prepare_for_transfer(uci_dev->mhi_dev); - if (ret) { - MSG_ERR("Error starting transfer channels\n"); - uci_dev->ref_count--; - goto error_open_chan; - } - - ret = mhi_queue_inbound(uci_dev); - if (ret) - goto error_rx_queue; - -#ifdef QUEC_MHI_UCI_ALWAYS_OPEN - uci_dev->ref_count++; -#endif - } - - filp->private_data = uci_dev; - mutex_unlock(&uci_dev->mutex); - mutex_unlock(&mhi_uci_drv.lock); - - return 0; - - error_rx_queue: - dl_chan = &uci_dev->dl_chan; - mhi_unprepare_from_transfer(uci_dev->mhi_dev); - if (uci_dev->uci_buf) { - unsigned nr_trb = 0; - - for (nr_trb = 0; nr_trb < uci_dev->nr_trbs; nr_trb++) { - if (uci_dev->uci_buf[nr_trb].page) - __free_pages(uci_dev->uci_buf[nr_trb].page, get_order(uci_dev->mtu)); - } - kfree(uci_dev->uci_buf); - } - - error_open_chan: - mutex_unlock(&uci_dev->mutex); - -error_exit: - mutex_unlock(&mhi_uci_drv.lock); - - return ret; -} - -static const struct file_operations mhidev_fops = { - .open = mhi_uci_open, - .release = mhi_uci_release, - .read = mhi_uci_read_mutex, - .write = mhi_uci_write_mutex, - .poll = mhi_uci_poll, - .unlocked_ioctl = mhi_uci_ioctl, -}; - -static void mhi_uci_remove(struct mhi_device *mhi_dev) -{ - struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev); - - MSG_LOG("Enter\n"); - - - mutex_lock(&mhi_uci_drv.lock); - mutex_lock(&uci_dev->mutex); - - /* disable the node */ - spin_lock_irq(&uci_dev->dl_chan.lock); - spin_lock_irq(&uci_dev->ul_chan.lock); - uci_dev->enabled = false; - spin_unlock_irq(&uci_dev->ul_chan.lock); - spin_unlock_irq(&uci_dev->dl_chan.lock); - wake_up(&uci_dev->dl_chan.wq); - wake_up(&uci_dev->ul_chan.wq); - - /* delete the node to prevent new opens */ - device_destroy(mhi_uci_drv.class, uci_dev->devt); - uci_dev->dev = NULL; - list_del(&uci_dev->node); - -#ifdef QUEC_MHI_UCI_ALWAYS_OPEN - if (uci_dev->ref_count > 0) - uci_dev->ref_count--; -#endif - - /* safe to free memory only if all file nodes are closed */ - if (!uci_dev->ref_count) { - mutex_unlock(&uci_dev->mutex); - mutex_destroy(&uci_dev->mutex); - clear_bit(MINOR(uci_dev->devt), uci_minors); - kfree(uci_dev); - mutex_unlock(&mhi_uci_drv.lock); - return; - } - - MSG_LOG("Exit\n"); - mutex_unlock(&uci_dev->mutex); - mutex_unlock(&mhi_uci_drv.lock); - -} - -static int mhi_uci_probe(struct mhi_device *mhi_dev, - const struct mhi_device_id *id) -{ - struct uci_dev *uci_dev; - int minor; - char node_name[32]; - int dir; - - uci_dev = kzalloc(sizeof(*uci_dev), GFP_KERNEL); - if (!uci_dev) - return -ENOMEM; - - mutex_init(&uci_dev->mutex); - mutex_init(&uci_dev->r_mutex); - mutex_init(&uci_dev->w_mutex); - uci_dev->mhi_dev = mhi_dev; - - minor = find_first_zero_bit(uci_minors, MAX_UCI_DEVICES); - if (minor >= MAX_UCI_DEVICES) { - kfree(uci_dev); - return -ENOSPC; - } - - mutex_lock(&uci_dev->mutex); - mutex_lock(&mhi_uci_drv.lock); - - uci_dev->devt = MKDEV(mhi_uci_drv.major, minor); -#if 1 - if (mhi_dev->mhi_cntrl->cntrl_idx) - uci_dev->dev = device_create(mhi_uci_drv.class, &mhi_dev->dev, - uci_dev->devt, uci_dev, - DEVICE_NAME "_%s%d", - mhi_dev->chan_name, mhi_dev->mhi_cntrl->cntrl_idx); - else - uci_dev->dev = device_create(mhi_uci_drv.class, &mhi_dev->dev, - uci_dev->devt, uci_dev, - DEVICE_NAME "_%s", - mhi_dev->chan_name); -#else - uci_dev->dev = device_create(mhi_uci_drv.class, &mhi_dev->dev, - uci_dev->devt, uci_dev, - DEVICE_NAME "_%04x_%02u.%02u.%02u%s%d", - mhi_dev->dev_id, mhi_dev->domain, - mhi_dev->bus, mhi_dev->slot, "_pipe_", - mhi_dev->ul_chan_id); -#endif - - set_bit(minor, uci_minors); - - /* create debugging buffer */ - snprintf(node_name, sizeof(node_name), "mhi_uci_%04x_%02u.%02u.%02u_%d", - mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus, mhi_dev->slot, - mhi_dev->ul_chan_id); - - for (dir = 0; dir < 2; dir++) { - struct uci_chan *uci_chan = (dir) ? - &uci_dev->ul_chan : &uci_dev->dl_chan; - spin_lock_init(&uci_chan->lock); - init_waitqueue_head(&uci_chan->wq); - INIT_LIST_HEAD(&uci_chan->pending); - } - - uci_dev->termios = tty_std_termios; - - uci_dev->mtu = min_t(size_t, id->driver_data, mhi_dev->mtu); - mhi_device_set_devdata(mhi_dev, uci_dev); - uci_dev->enabled = true; - - list_add(&uci_dev->node, &mhi_uci_drv.head); - mutex_unlock(&mhi_uci_drv.lock); - mutex_unlock(&uci_dev->mutex); - - MSG_LOG("channel:%s successfully probed\n", mhi_dev->chan_name); - - return 0; -}; - -static void mhi_ul_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev); - struct uci_chan *uci_chan = &uci_dev->ul_chan; - - MSG_VERB("status:%d xfer_len:%zu\n", mhi_result->transaction_status, - mhi_result->bytes_xferd); - - kfree(mhi_result->buf_addr); - if (!mhi_result->transaction_status) - wake_up(&uci_chan->wq); -} - -static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev, - struct mhi_result *mhi_result) -{ - struct uci_dev *uci_dev = mhi_device_get_devdata(mhi_dev); - struct uci_chan *uci_chan = &uci_dev->dl_chan; - unsigned long flags; - struct uci_buf *buf; - unsigned nr_trb = uci_dev->nr_trb; - - buf = &uci_dev->uci_buf[nr_trb]; - if (buf == NULL) { - MSG_ERR("buf = NULL"); - return; - } - if (buf->nr_trb != nr_trb || buf->data != mhi_result->buf_addr) - { - uci_dev->rx_error++; - MSG_ERR("chan[%d]: uci_buf[%u] = %p , mhi_result[%u] = %p\n", - mhi_dev->dl_chan_id, buf->nr_trb, buf->data, nr_trb, mhi_result->buf_addr); - return; - } - - uci_dev->nr_trb++; - if (uci_dev->nr_trb == uci_dev->nr_trbs) - uci_dev->nr_trb = 0; - - if (mhi_result->transaction_status == -ENOTCONN) { - return; - } - - if (mhi_result->bytes_xferd > uci_dev->mtu || mhi_result->bytes_xferd <= 0) - { - MSG_ERR("chan[%d]: bytes_xferd = %zd , mtu = %zd\n", - mhi_dev->dl_chan_id, mhi_result->bytes_xferd, uci_dev->mtu); - return; - } - if (mhi_result->bytes_xferd > uci_dev->bytes_xferd) - { - uci_dev->bytes_xferd = mhi_result->bytes_xferd; - //MSG_ERR("chan[%d]: bytes_xferd = %zd , mtu = %zd\n", - // mhi_dev->dl_chan_id, mhi_result->bytes_xferd, uci_dev->mtu); - } - - MSG_VERB("status:%d receive_len:%zu\n", mhi_result->transaction_status, - mhi_result->bytes_xferd); - - spin_lock_irqsave(&uci_chan->lock, flags); -#if 0 - buf = mhi_result->buf_addr + uci_dev->mtu; - buf->data = mhi_result->buf_addr; -#endif - buf->len = mhi_result->bytes_xferd; - if (mhi_dev->dl_chan_id == MHI_CLIENT_DUN_IN - || mhi_dev->dl_chan_id == MHI_CLIENT_QMI_IN - || mhi_dev->dl_chan_id == MHI_CLIENT_MBIM_IN) - { - struct uci_buf *tmp_buf = NULL; - int skip_buf = 0; - -#ifdef QUEC_MHI_UCI_ALWAYS_OPEN - if (uci_dev->ref_count == 1) - skip_buf++; -#endif - if (!skip_buf) - tmp_buf = (struct uci_buf *)kmalloc(buf->len + sizeof(struct uci_buf), GFP_ATOMIC);; - - if (tmp_buf) { - tmp_buf->page = NULL; - tmp_buf->data = ((void *)tmp_buf) + sizeof(struct uci_buf); - tmp_buf->len = buf->len; - memcpy(tmp_buf->data, buf->data, buf->len); - } - - if (buf) { - struct uci_buf *uci_buf = buf; - unsigned nr_trb = uci_buf->nr_trb ? (uci_buf->nr_trb - 1) : (uci_dev->nr_trbs - 1); - - uci_buf = &uci_dev->uci_buf[nr_trb]; - mhi_queue_transfer(mhi_dev, DMA_FROM_DEVICE, uci_buf->data, uci_dev->mtu, MHI_EOT); - } - - buf = tmp_buf; - } - - if (buf) - list_add_tail(&buf->node, &uci_chan->pending); - spin_unlock_irqrestore(&uci_chan->lock, flags); - -#ifdef CONFIG_PM_SLEEP - if (mhi_dev->dev.power.wakeup) - __pm_wakeup_event(mhi_dev->dev.power.wakeup, 0); -#endif - - wake_up(&uci_chan->wq); -} - -// repaire sdx6x module can not read qdb file. xingduo.du 2023-01-18 -#define DIAG_MAX_PCIE_PKT_SZ 8192 //define by module - -/* .driver_data stores max mtu */ -static const struct mhi_device_id mhi_uci_match_table[] = { - { .chan = "LOOPBACK", .driver_data = 0x1000 }, - { .chan = "SAHARA", .driver_data = 0x4000 }, - { .chan = "EDL", .driver_data = 0x4000 }, - { .chan = "DIAG", .driver_data = DIAG_MAX_PCIE_PKT_SZ }, - { .chan = "MBIM", .driver_data = 0x1000 }, - { .chan = "QMI0", .driver_data = 0x1000 }, - { .chan = "QMI1", .driver_data = 0x1000 }, - { .chan = "DUN", .driver_data = 0x1000 }, -#ifdef ENABLE_ADPL - { .chan = "ADPL", .driver_data = 0x1000 }, -#endif -#ifdef ENABLE_QDSS - { .chan = "QDSS", .driver_data = 0x1000 }, -#endif - {}, -}; - -static struct mhi_driver mhi_uci_driver = { - .id_table = mhi_uci_match_table, - .remove = mhi_uci_remove, - .probe = mhi_uci_probe, - .ul_xfer_cb = mhi_ul_xfer_cb, - .dl_xfer_cb = mhi_dl_xfer_cb, - .driver = { - .name = MHI_UCI_DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -int mhi_device_uci_init(void) -{ - int ret; - - ret = register_chrdev(0, MHI_UCI_DRIVER_NAME, &mhidev_fops); - if (ret < 0) - return ret; - - mhi_uci_drv.major = ret; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) - mhi_uci_drv.class = class_create(MHI_UCI_DRIVER_NAME); -#else - mhi_uci_drv.class = class_create(THIS_MODULE, MHI_UCI_DRIVER_NAME); -#endif - if (IS_ERR(mhi_uci_drv.class)) { - unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); - return -ENODEV; - } - - mutex_init(&mhi_uci_drv.lock); - INIT_LIST_HEAD(&mhi_uci_drv.head); - - ret = mhi_driver_register(&mhi_uci_driver); - if (ret) { - class_destroy(mhi_uci_drv.class); - unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); - } - - return ret; -} - -void mhi_device_uci_exit(void) -{ - mhi_driver_unregister(&mhi_uci_driver); - class_destroy(mhi_uci_drv.class); - unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); -} diff --git a/quectel_MHI/src/devices/rmnet/Kconfig b/quectel_MHI/src/devices/rmnet/Kconfig deleted file mode 100644 index 9bb06d2..0000000 --- a/quectel_MHI/src/devices/rmnet/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# -# RMNET MAP driver -# - -menuconfig RMNET - tristate "RmNet MAP driver" - default n - select GRO_CELLS - ---help--- - If you select this, you will enable the RMNET module which is used - for handling data in the multiplexing and aggregation protocol (MAP) - format in the embedded data path. RMNET devices can be attached to - any IP mode physical device. diff --git a/quectel_MHI/src/devices/rmnet/Makefile b/quectel_MHI/src/devices/rmnet/Makefile deleted file mode 100644 index b175fbb..0000000 --- a/quectel_MHI/src/devices/rmnet/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the RMNET module -# - -rmnet-y := rmnet_config.o -rmnet-y += rmnet_vnd.o -rmnet-y += rmnet_handlers.o -rmnet-y += rmnet_map_data.o -rmnet-y += rmnet_map_command.o -rmnet-y += rmnet_descriptor.o -obj-$(CONFIG_RMNET) += rmnet.o diff --git a/quectel_MHI/src/devices/rmnet/rmnet_config.c b/quectel_MHI/src/devices/rmnet/rmnet_config.c deleted file mode 100644 index c5ec0c8..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_config.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET configuration engine - * - */ - -#include -#include -#include -#include -#include -#include "rmnet_config.h" -#include "rmnet_handlers.h" -#include "rmnet_vnd.h" -#include "rmnet_private.h" -#include "rmnet_map.h" -#include "rmnet_descriptor.h" - -/* Locking scheme - - * The shared resource which needs to be protected is realdev->rx_handler_data. - * For the writer path, this is using rtnl_lock(). The writer paths are - * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These - * paths are already called with rtnl_lock() acquired in. There is also an - * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For - * dereference here, we will need to use rtnl_dereference(). Dev list writing - * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link(). - * For the reader path, the real_dev->rx_handler_data is called in the TX / RX - * path. We only need rcu_read_lock() for these scenarios. In these cases, - * the rcu_read_lock() is held in __dev_queue_xmit() and - * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl() - * to get the relevant information. For dev list reading, we again acquire - * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu(). - * We also use unregister_netdevice_many() to free all rmnet devices in - * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in - * same context. - */ - -/* Local Definitions and Declarations */ - -static int rmnet_is_real_dev_registered(const struct net_device *real_dev) -{ - return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler; -} - -/* Needs rtnl lock */ -static struct rmnet_port* -rmnet_get_port_rtnl(const struct net_device *real_dev) -{ - return rtnl_dereference(real_dev->rx_handler_data); -} - -static int rmnet_unregister_real_device(struct net_device *real_dev, - struct rmnet_port *port) -{ - if (port->nr_rmnet_devs) - return -EINVAL; - - rmnet_map_cmd_exit(port); - rmnet_map_tx_aggregate_exit(port); - - rmnet_descriptor_deinit(port); - - kfree(port); - - netdev_rx_handler_unregister(real_dev); - - /* release reference on real_dev */ - dev_put(real_dev); - - netdev_dbg(real_dev, "Removed from rmnet\n"); - return 0; -} - -static int rmnet_register_real_device(struct net_device *real_dev) -{ - struct rmnet_port *port; - int rc, entry; - - ASSERT_RTNL(); - - if (rmnet_is_real_dev_registered(real_dev)) - return 0; - - port = kzalloc(sizeof(*port), GFP_ATOMIC); - if (!port) - return -ENOMEM; - - port->dev = real_dev; - rc = netdev_rx_handler_register(real_dev, rmnet_rx_handler, port); - if (rc) { - kfree(port); - return -EBUSY; - } - /* hold on to real dev for MAP data */ - dev_hold(real_dev); - - for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++) - INIT_HLIST_HEAD(&port->muxed_ep[entry]); - - rc = rmnet_descriptor_init(port); - if (rc) { - rmnet_descriptor_deinit(port); - return rc; - } - - rmnet_map_tx_aggregate_init(port); - rmnet_map_cmd_init(port); - - netdev_dbg(real_dev, "registered with rmnet\n"); - return 0; -} - -/* Needs either rcu_read_lock() or rtnl lock */ -static struct rmnet_port *rmnet_get_port(struct net_device *real_dev) -{ - if (rmnet_is_real_dev_registered(real_dev)) - return rcu_dereference_rtnl(real_dev->rx_handler_data); - else - return NULL; -} - -static struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id) -{ - struct rmnet_endpoint *ep; - - hlist_for_each_entry_rcu(ep, &port->muxed_ep[mux_id], hlnode) { - if (ep->mux_id == mux_id) - return ep; - } - - return NULL; -} diff --git a/quectel_MHI/src/devices/rmnet/rmnet_config.h b/quectel_MHI/src/devices/rmnet/rmnet_config.h deleted file mode 100644 index c74fcdf..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_config.h +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (c) 2013-2017, 2019 The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Data configuration engine - * - */ - -#include -#include - -#ifndef _RMNET_CONFIG_H_ -#define _RMNET_CONFIG_H_ - -#define RMNET_MAX_LOGICAL_EP 255 -#define RMNET_MAX_VEID 4 - -struct rmnet_endpoint { - u8 mux_id; - struct net_device *egress_dev; - struct hlist_node hlnode; -}; - -struct rmnet_port_priv_stats { - u64 dl_hdr_last_qmap_vers; - u64 dl_hdr_last_ep_id; - u64 dl_hdr_last_trans_id; - u64 dl_hdr_last_seq; - u64 dl_hdr_last_bytes; - u64 dl_hdr_last_pkts; - u64 dl_hdr_last_flows; - u64 dl_hdr_count; - u64 dl_hdr_total_bytes; - u64 dl_hdr_total_pkts; - u64 dl_trl_last_seq; - u64 dl_trl_count; -}; - -struct rmnet_egress_agg_params { - u16 agg_size; - u16 agg_count; - u32 agg_time; -}; - -/* One instance of this structure is instantiated for each real_dev associated - * with rmnet. - */ -struct rmnet_port { - struct net_device *dev; - u32 data_format; - u8 nr_rmnet_devs; - u8 rmnet_mode; - struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP]; - struct net_device *bridge_ep; - void *rmnet_perf; - - struct rmnet_egress_agg_params egress_agg_params; - - /* Protect aggregation related elements */ - spinlock_t agg_lock; - - struct sk_buff *agg_skb; - int agg_state; - u8 agg_count; - struct timespec agg_time; - struct timespec agg_last; - struct hrtimer hrtimer; - struct work_struct agg_wq; - - /* dl marker elements */ - struct list_head dl_list; - struct rmnet_port_priv_stats stats; - int dl_marker_flush; - - /* Descriptor pool */ - spinlock_t desc_pool_lock; - struct rmnet_frag_descriptor_pool *frag_desc_pool; - struct sk_buff *chain_head; - struct sk_buff *chain_tail; -}; - -extern struct rtnl_link_ops rmnet_link_ops; - -struct rmnet_vnd_stats { - u64 rx_pkts; - u64 rx_bytes; - u64 tx_pkts; - u64 tx_bytes; - u32 tx_drops; -}; - -struct rmnet_pcpu_stats { - struct rmnet_vnd_stats stats; - struct u64_stats_sync syncp; -}; - -struct rmnet_coal_close_stats { - u64 non_coal; - u64 ip_miss; - u64 trans_miss; - u64 hw_nl; - u64 hw_pkt; - u64 hw_byte; - u64 hw_time; - u64 hw_evict; - u64 coal; -}; - -struct rmnet_coal_stats { - u64 coal_rx; - u64 coal_pkts; - u64 coal_hdr_nlo_err; - u64 coal_hdr_pkt_err; - u64 coal_csum_err; - u64 coal_reconstruct; - u64 coal_ip_invalid; - u64 coal_trans_invalid; - struct rmnet_coal_close_stats close; - u64 coal_veid[RMNET_MAX_VEID]; -}; - -struct rmnet_priv_stats { - u64 csum_ok; - u64 csum_valid_unset; - u64 csum_validation_failed; - u64 csum_err_bad_buffer; - u64 csum_err_invalid_ip_version; - u64 csum_err_invalid_transport; - u64 csum_fragmented_pkt; - u64 csum_skipped; - u64 csum_sw; - u64 csum_hw; - struct rmnet_coal_stats coal; -}; - -struct rmnet_priv { - u8 mux_id; - struct net_device *real_dev; - struct rmnet_pcpu_stats __percpu *pcpu_stats; - struct gro_cells gro_cells; - struct rmnet_priv_stats stats; -}; - -enum rmnet_dl_marker_prio { - RMNET_PERF, - RMNET_SHS, -}; - -enum rmnet_trace_func { - RMNET_MODULE, - NW_STACK_MODULE, -}; - -enum rmnet_trace_evt { - RMNET_DLVR_SKB, - RMNET_RCV_FROM_PND, - RMNET_TX_UL_PKT, - NW_STACK_DEV_Q_XMIT, - NW_STACK_NAPI_GRO_FLUSH, - NW_STACK_RX, - NW_STACK_TX, -}; - -static int rmnet_is_real_dev_registered(const struct net_device *real_dev); -static struct rmnet_port *rmnet_get_port(struct net_device *real_dev); -static struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id); -#endif /* _RMNET_CONFIG_H_ */ diff --git a/quectel_MHI/src/devices/rmnet/rmnet_data.c b/quectel_MHI/src/devices/rmnet/rmnet_data.c deleted file mode 100644 index ad8953c..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_data.c +++ /dev/null @@ -1,1150 +0,0 @@ -#if 0 - -#define RMNET_MAX_PACKET_SIZE 16384 -#define RMNET_DFLT_PACKET_SIZE 1500 -#define RMNET_NEEDED_HEADROOM 16 -#define RMNET_TX_QUEUE_LEN 1000 - -#define RMNET_MAX_LOGICAL_EP 255 -#define RMNET_MAP_DESC_HEADROOM 128 -#define RMNET_FRAG_DESCRIPTOR_POOL_SIZE 64 - -/* Pass the frame up the stack with no modifications to skb->dev */ -#define RMNET_EPMODE_NONE (0) -/* Replace skb->dev to a virtual rmnet device and pass up the stack */ -#define RMNET_EPMODE_VND (1) -/* Pass the frame directly to another device with dev_queue_xmit() */ -#define RMNET_EPMODE_BRIDGE (2) - -/* rmnet section */ - -#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) -#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) -#define RMNET_FLAGS_INGRESS_COALESCE (1U << 4) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5 (1U << 5) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5 (1U << 6) - -enum rmnet_map_v5_header_type { - RMNET_MAP_HEADER_TYPE_UNKNOWN, - RMNET_MAP_HEADER_TYPE_COALESCING = 0x1, - RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2, - RMNET_MAP_HEADER_TYPE_ENUM_LENGTH -}; - -/* Main QMAP header */ -struct rmnet_map_header { - u8 pad_len:6; - u8 next_hdr:1; - u8 cd_bit:1; - u8 mux_id; - __be16 pkt_len; -} __aligned(1); - -/* QMAP v5 headers */ -struct rmnet_map_v5_csum_header { - u8 next_hdr:1; - u8 header_type:7; - u8 hw_reserved:7; - u8 csum_valid_required:1; - __be16 reserved; -} __aligned(1); - -struct rmnet_map_v5_nl_pair { - __be16 pkt_len; - u8 csum_error_bitmap; - u8 num_packets; -} __aligned(1); - -/* NLO: Number-length object */ -#define RMNET_MAP_V5_MAX_NLOS (6) -#define RMNET_MAP_V5_MAX_PACKETS (48) - -struct rmnet_map_v5_coal_header { - u8 next_hdr:1; - u8 header_type:7; - u8 reserved1:4; - u8 num_nlos:3; - u8 csum_valid:1; - u8 close_type:4; - u8 close_value:4; - u8 reserved2:4; - u8 virtual_channel_id:4; - - struct rmnet_map_v5_nl_pair nl_pairs[RMNET_MAP_V5_MAX_NLOS]; -} __aligned(1); - -/* QMAP v4 headers */ -struct rmnet_map_dl_csum_trailer { - u8 reserved1; - u8 valid:1; - u8 reserved2:7; - u16 csum_start_offset; - u16 csum_length; - __be16 csum_value; -} __aligned(1); - -struct rmnet_frag_descriptor_pool { - struct list_head free_list; - u32 pool_size; -}; - -struct rmnet_frag_descriptor { - struct list_head list; - struct list_head sub_frags; - skb_frag_t frag; - u8 *hdr_ptr; - struct net_device *dev; - u32 hash; - __be32 tcp_seq; - __be16 ip_id; - u16 data_offset; - u16 gso_size; - u16 gso_segs; - u16 ip_len; - u16 trans_len; - u8 ip_proto; - u8 trans_proto; - u8 pkt_id; - u8 csum_valid:1, - hdrs_valid:1, - ip_id_set:1, - tcp_seq_set:1, - flush_shs:1, - reserved:3; -}; - -struct rmnet_endpoint { - u8 rmnet_mode; - u8 mux_id; - struct net_device *rmnet_dev; -}; - -/* One instance of this structure is instantiated for each real_dev associated - * with rmnet. - */ -struct rmnet_port { - struct net_device *dev; - u8 rmnet_mode; - u32 data_format; - u32 nr_rmnet_devs; - struct rmnet_endpoint muxed_ep[16]; - - /* Descriptor pool */ - spinlock_t desc_pool_lock; - struct rmnet_frag_descriptor_pool *frag_desc_pool; - struct sk_buff *chain_head; - struct sk_buff *chain_tail; -}; - -static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) -{ - struct rmnet_map_header *map_header; - struct rmnet_map_v5_csum_header *ul_header; - u32 padding, map_datalen; - - map_datalen = skb->len; - padding = map_datalen%4; - if (padding) { - padding = 4 - padding; - if (skb_tailroom(skb) < padding) { - printk("skb_tailroom small!\n"); - padding = 0; - } - if (padding) - __skb_put(skb, padding); - } - - map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); - - BUILD_BUG_ON((sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header)) != 8); - - map_header->cd_bit = 0; - map_header->next_hdr = 1; - map_header->pad_len = padding; - map_header->mux_id = mux_id; - map_header->pkt_len = htons(map_datalen + padding); - - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - memset(ul_header, 0, sizeof(*ul_header)); - ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD; - - return skb; -} - -struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id) -{ - return &port->muxed_ep[0]; -} - -static void -rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port) -{ - struct rmnet_nss_cb *nss_cb; - - //rmnet_vnd_rx_fixup(skb->dev, skb->len); - - /* Pass off the packet to NSS driver if we can */ - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { - if (!port->chain_head) - port->chain_head = skb; - else - skb_shinfo(port->chain_tail)->frag_list = skb; - - port->chain_tail = skb; - return; - } - - skb_reset_transport_header(skb); - skb_reset_network_header(skb); - - skb->pkt_type = PACKET_HOST; - skb_set_mac_header(skb, 0); - - //if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { - //} else { - //if (!rmnet_check_skb_can_gro(skb)) - // gro_cells_receive(&priv->gro_cells, skb); - //else - netif_receive_skb(skb); - //} -} - -static inline unsigned char *rmnet_map_data_ptr(struct sk_buff *skb) -{ - /* Nonlinear packets we receive are entirely within frag 0 */ - if (skb_is_nonlinear(skb) && skb->len == skb->data_len) - return skb_frag_address(skb_shinfo(skb)->frags); - - return skb->data; -} - -static inline void *rmnet_frag_data_ptr(struct rmnet_frag_descriptor *frag_desc) -{ - return skb_frag_address(&frag_desc->frag); -} - -static struct rmnet_frag_descriptor * -rmnet_get_frag_descriptor(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool; - struct rmnet_frag_descriptor *frag_desc; - - spin_lock(&port->desc_pool_lock); - if (!list_empty(&pool->free_list)) { - frag_desc = list_first_entry(&pool->free_list, - struct rmnet_frag_descriptor, - list); - list_del_init(&frag_desc->list); - } else { - frag_desc = kzalloc(sizeof(*frag_desc), GFP_ATOMIC); - if (!frag_desc) - goto out; - - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - pool->pool_size++; - } - -out: - spin_unlock(&port->desc_pool_lock); - return frag_desc; -} - -static void rmnet_recycle_frag_descriptor(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool; - struct page *page = skb_frag_page(&frag_desc->frag); - - list_del(&frag_desc->list); - if (page) - put_page(page); - - memset(frag_desc, 0, sizeof(*frag_desc)); - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - spin_lock(&port->desc_pool_lock); - list_add_tail(&frag_desc->list, &pool->free_list); - spin_unlock(&port->desc_pool_lock); -} - -static inline void rmnet_frag_fill(struct rmnet_frag_descriptor *frag_desc, - struct page *p, u32 page_offset, u32 len) -{ - get_page(p); - __skb_frag_set_page(&frag_desc->frag, p); - skb_frag_size_set(&frag_desc->frag, len); - frag_desc->frag.page_offset = page_offset; -} - -static inline void *rmnet_frag_pull(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - unsigned int size) -{ - if (size >= skb_frag_size(&frag_desc->frag)) { - pr_info("%s(): Pulling %u bytes from %u byte pkt. Dropping\n", - __func__, size, skb_frag_size(&frag_desc->frag)); - rmnet_recycle_frag_descriptor(frag_desc, port); - return NULL; - } - - frag_desc->frag.page_offset += size; - skb_frag_size_sub(&frag_desc->frag, size); - - return rmnet_frag_data_ptr(frag_desc); -} - -static inline void *rmnet_frag_trim(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - unsigned int size) -{ - if (!size) { - pr_info("%s(): Trimming %u byte pkt to 0. Dropping\n", - __func__, skb_frag_size(&frag_desc->frag)); - rmnet_recycle_frag_descriptor(frag_desc, port); - return NULL; - } - - if (size < skb_frag_size(&frag_desc->frag)) - skb_frag_size_set(&frag_desc->frag, size); - - return rmnet_frag_data_ptr(frag_desc); -} - -static inline u8 -rmnet_frag_get_next_hdr_type(struct rmnet_frag_descriptor *frag_desc) -{ - unsigned char *data = rmnet_frag_data_ptr(frag_desc); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_coal_header *)data)->header_type; -} - -static inline bool -rmnet_frag_get_csum_valid(struct rmnet_frag_descriptor *frag_desc) -{ - unsigned char *data = rmnet_frag_data_ptr(frag_desc); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_csum_header *)data)->csum_valid_required; -} - -static void rmnet_descriptor_add_frag(struct rmnet_port *port, struct list_head *list, - struct page *p, u32 page_offset, u32 len) -{ - struct rmnet_frag_descriptor *frag_desc; - - frag_desc = rmnet_get_frag_descriptor(port); - if (!frag_desc) - return; - - rmnet_frag_fill(frag_desc, p, page_offset, len); - list_add_tail(&frag_desc->list, list); -} - -static void rmnet_frag_deaggregate(skb_frag_t *frag, struct rmnet_port *port, - struct list_head *list) -{ - struct rmnet_map_header *maph; - u8 *data = skb_frag_address(frag); - u32 offset = 0; - u32 packet_len; - - while (offset < skb_frag_size(frag)) { - maph = (struct rmnet_map_header *)data; - packet_len = ntohs(maph->pkt_len); - - /* Some hardware can send us empty frames. Catch them */ - if (packet_len == 0) - return; - - packet_len += sizeof(*maph); - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) { - packet_len += sizeof(struct rmnet_map_dl_csum_trailer); - WARN_ON(1); - } else if (port->data_format & - (RMNET_FLAGS_INGRESS_MAP_CKSUMV5 | - RMNET_FLAGS_INGRESS_COALESCE) && !maph->cd_bit) { - u32 hsize = 0; - u8 type; - - type = ((struct rmnet_map_v5_coal_header *) - (data + sizeof(*maph)))->header_type; - switch (type) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - hsize = sizeof(struct rmnet_map_v5_coal_header); - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - hsize = sizeof(struct rmnet_map_v5_csum_header); - break; - } - - packet_len += hsize; - } - else { - qmap_hex_dump(__func__, data, 64); - WARN_ON(1); - } - - if ((int)skb_frag_size(frag) - (int)packet_len < 0) - return; - - rmnet_descriptor_add_frag(port, list, skb_frag_page(frag), - frag->page_offset + offset, - packet_len); - - offset += packet_len; - data += packet_len; - } -} - - -#define RMNET_IP_VERSION_4 0x40 -#define RMNET_IP_VERSION_6 0x60 - -/* Helper Functions */ - -static void rmnet_set_skb_proto(struct sk_buff *skb) -{ - switch (rmnet_map_data_ptr(skb)[0] & 0xF0) { - case RMNET_IP_VERSION_4: - skb->protocol = htons(ETH_P_IP); - break; - case RMNET_IP_VERSION_6: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - skb->protocol = htons(ETH_P_MAP); - WARN_ON(1); - break; - } -} - -/* Allocate and populate an skb to contain the packet represented by the - * frag descriptor. - */ -static struct sk_buff *rmnet_alloc_skb(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct sk_buff *head_skb, *current_skb, *skb; - struct skb_shared_info *shinfo; - struct rmnet_frag_descriptor *sub_frag, *tmp; - - /* Use the exact sizes if we know them (i.e. RSB/RSC, rmnet_perf) */ - if (frag_desc->hdrs_valid) { - u16 hdr_len = frag_desc->ip_len + frag_desc->trans_len; - - head_skb = alloc_skb(hdr_len + RMNET_MAP_DESC_HEADROOM, - GFP_ATOMIC); - if (!head_skb) - return NULL; - - skb_reserve(head_skb, RMNET_MAP_DESC_HEADROOM); - skb_put_data(head_skb, frag_desc->hdr_ptr, hdr_len); - skb_reset_network_header(head_skb); - - if (frag_desc->trans_len) - skb_set_transport_header(head_skb, frag_desc->ip_len); - - /* Packets that have no data portion don't need any frags */ - if (hdr_len == skb_frag_size(&frag_desc->frag)) - goto skip_frags; - - /* If the headers we added are the start of the page, - * we don't want to add them twice - */ - if (frag_desc->hdr_ptr == rmnet_frag_data_ptr(frag_desc)) { - if (!rmnet_frag_pull(frag_desc, port, hdr_len)) { - kfree_skb(head_skb); - return NULL; - } - } - } else { - /* Allocate enough space to avoid penalties in the stack - * from __pskb_pull_tail() - */ - head_skb = alloc_skb(256 + RMNET_MAP_DESC_HEADROOM, - GFP_ATOMIC); - if (!head_skb) - return NULL; - - skb_reserve(head_skb, RMNET_MAP_DESC_HEADROOM); - } - - /* Add main fragment */ - get_page(skb_frag_page(&frag_desc->frag)); - skb_add_rx_frag(head_skb, 0, skb_frag_page(&frag_desc->frag), - frag_desc->frag.page_offset, - skb_frag_size(&frag_desc->frag), - skb_frag_size(&frag_desc->frag)); - - shinfo = skb_shinfo(head_skb); - current_skb = head_skb; - - /* Add in any frags from rmnet_perf */ - list_for_each_entry_safe(sub_frag, tmp, &frag_desc->sub_frags, list) { - skb_frag_t *frag; - u32 frag_size; - - frag = &sub_frag->frag; - frag_size = skb_frag_size(frag); - -add_frag: - if (shinfo->nr_frags < MAX_SKB_FRAGS) { - get_page(skb_frag_page(frag)); - skb_add_rx_frag(current_skb, shinfo->nr_frags, - skb_frag_page(frag), frag->page_offset, - frag_size, frag_size); - if (current_skb != head_skb) { - head_skb->len += frag_size; - head_skb->data_len += frag_size; - } - } else { - /* Alloc a new skb and try again */ - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) - break; - - if (current_skb == head_skb) - shinfo->frag_list = skb; - else - current_skb->next = skb; - - current_skb = skb; - shinfo = skb_shinfo(current_skb); - goto add_frag; - } - - rmnet_recycle_frag_descriptor(sub_frag, port); - } - -skip_frags: - head_skb->dev = frag_desc->dev; - rmnet_set_skb_proto(head_skb); - - /* Handle any header metadata that needs to be updated after RSB/RSC - * segmentation - */ - if (frag_desc->ip_id_set) { - struct iphdr *iph; - - iph = (struct iphdr *)rmnet_map_data_ptr(head_skb); - csum_replace2(&iph->check, iph->id, frag_desc->ip_id); - iph->id = frag_desc->ip_id; - } - - if (frag_desc->tcp_seq_set) { - struct tcphdr *th; - - th = (struct tcphdr *) - (rmnet_map_data_ptr(head_skb) + frag_desc->ip_len); - th->seq = frag_desc->tcp_seq; - } - - /* Handle csum offloading */ - if (frag_desc->csum_valid && frag_desc->hdrs_valid) { - /* Set the partial checksum information */ - //rmnet_frag_partial_csum(head_skb, frag_desc); - WARN_ON(1); - } else if (frag_desc->csum_valid) { - /* Non-RSB/RSC/perf packet. The current checksum is fine */ - head_skb->ip_summed = CHECKSUM_UNNECESSARY; - } else if (frag_desc->hdrs_valid && - (frag_desc->trans_proto == IPPROTO_TCP || - frag_desc->trans_proto == IPPROTO_UDP)) { - /* Unfortunately, we have to fake a bad checksum here, since - * the original bad value is lost by the hardware. The only - * reliable way to do it is to calculate the actual checksum - * and corrupt it. - */ - __sum16 *check; - __wsum csum; - unsigned int offset = skb_transport_offset(head_skb); - __sum16 pseudo; - - WARN_ON(1); - /* Calculate pseudo header and update header fields */ - if (frag_desc->ip_proto == 4) { - struct iphdr *iph = ip_hdr(head_skb); - __be16 tot_len = htons(head_skb->len); - - csum_replace2(&iph->check, iph->tot_len, tot_len); - iph->tot_len = tot_len; - pseudo = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - head_skb->len - - frag_desc->ip_len, - frag_desc->trans_proto, 0); - } else { - struct ipv6hdr *ip6h = ipv6_hdr(head_skb); - - ip6h->payload_len = htons(head_skb->len - - sizeof(*ip6h)); - pseudo = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - head_skb->len - - frag_desc->ip_len, - frag_desc->trans_proto, 0); - } - - if (frag_desc->trans_proto == IPPROTO_TCP) { - check = &tcp_hdr(head_skb)->check; - } else { - udp_hdr(head_skb)->len = htons(head_skb->len - - frag_desc->ip_len); - check = &udp_hdr(head_skb)->check; - } - - *check = pseudo; - csum = skb_checksum(head_skb, offset, head_skb->len - offset, - 0); - /* Add 1 to corrupt. This cannot produce a final value of 0 - * since csum_fold() can't return a value of 0xFFFF - */ - *check = csum16_add(csum_fold(csum), htons(1)); - head_skb->ip_summed = CHECKSUM_NONE; - } - - /* Handle any rmnet_perf metadata */ - if (frag_desc->hash) { - head_skb->hash = frag_desc->hash; - head_skb->sw_hash = 1; - } - - if (frag_desc->flush_shs) - head_skb->cb[0] = 1; - - /* Handle coalesced packets */ - //if (frag_desc->gso_segs > 1) - // rmnet_frag_gso_stamp(head_skb, frag_desc); - - return head_skb; -} - -/* Deliver the packets contained within a frag descriptor */ -static void rmnet_frag_deliver(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct sk_buff *skb; - - skb = rmnet_alloc_skb(frag_desc, port); - if (skb) - rmnet_deliver_skb(skb, port); - rmnet_recycle_frag_descriptor(frag_desc, port); -} - -/* Process a QMAPv5 packet header */ -static int rmnet_frag_process_next_hdr_packet(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - struct list_head *list, - u16 len) -{ - int rc = 0; - - switch (rmnet_frag_get_next_hdr_type(frag_desc)) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - rc = -1; - WARN_ON(1); - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - if (rmnet_frag_get_csum_valid(frag_desc)) { - frag_desc->csum_valid = true; - } else { - } - - if (!rmnet_frag_pull(frag_desc, port, - sizeof(struct rmnet_map_header) + - sizeof(struct rmnet_map_v5_csum_header))) { - rc = -EINVAL; - break; - } - - frag_desc->hdr_ptr = rmnet_frag_data_ptr(frag_desc); - - /* Remove padding only for csum offload packets. - * Coalesced packets should never have padding. - */ - if (!rmnet_frag_trim(frag_desc, port, len)) { - rc = -EINVAL; - break; - } - - list_del_init(&frag_desc->list); - list_add_tail(&frag_desc->list, list); - break; - default: - qmap_hex_dump(__func__, rmnet_frag_data_ptr(frag_desc), 64); - rc = -EINVAL; - break; - } - - return rc; -} - -static void -__rmnet_frag_ingress_handler(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct rmnet_map_header *qmap; - struct rmnet_endpoint *ep; - struct rmnet_frag_descriptor *frag, *tmp; - LIST_HEAD(segs); - u16 len, pad; - u8 mux_id; - - qmap = (struct rmnet_map_header *)skb_frag_address(&frag_desc->frag); - mux_id = qmap->mux_id; - pad = qmap->pad_len; - len = ntohs(qmap->pkt_len) - pad; - - if (qmap->cd_bit) { - goto recycle; - } - - if (mux_id >= RMNET_MAX_LOGICAL_EP) - goto recycle; - - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) - goto recycle; - - frag_desc->dev = ep->rmnet_dev; - - /* Handle QMAPv5 packet */ - if (qmap->next_hdr && - (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5))) { - if (rmnet_frag_process_next_hdr_packet(frag_desc, port, &segs, - len)) - goto recycle; - } else { - /* We only have the main QMAP header to worry about */ - if (!rmnet_frag_pull(frag_desc, port, sizeof(*qmap))) - return; - - frag_desc->hdr_ptr = rmnet_frag_data_ptr(frag_desc); - - if (!rmnet_frag_trim(frag_desc, port, len)) - return; - - list_add_tail(&frag_desc->list, &segs); - } - - list_for_each_entry_safe(frag, tmp, &segs, list) { - list_del_init(&frag->list); - rmnet_frag_deliver(frag, port); - } - return; - -recycle: - rmnet_recycle_frag_descriptor(frag_desc, port); -} - -static void rmnet_frag_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - LIST_HEAD(desc_list); - int i = 0; - struct rmnet_nss_cb *nss_cb; - - /* Deaggregation and freeing of HW originating - * buffers is done within here - */ - while (skb) { - struct sk_buff *skb_frag; - - port->chain_head = NULL; - port->chain_tail = NULL; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - rmnet_frag_deaggregate(&skb_shinfo(skb)->frags[i], port, - &desc_list); - if (!list_empty(&desc_list)) { - struct rmnet_frag_descriptor *frag_desc, *tmp; - - list_for_each_entry_safe(frag_desc, tmp, - &desc_list, list) { - list_del_init(&frag_desc->list); - __rmnet_frag_ingress_handler(frag_desc, - port); - } - } - } - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb && port->chain_head) { - port->chain_head->cb[0] = 0; - netif_receive_skb(port->chain_head); - } - - skb_frag = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; - consume_skb(skb); - skb = skb_frag; - } -} - -static void -rmnet_map_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - if (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5)) { - if (skb_is_nonlinear(skb)) { - rmnet_frag_ingress_handler(skb, port); - return; - } - } - - WARN_ON(1); -} - -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb); -static int rmnet_is_real_dev_registered(const struct net_device *real_dev) -{ - return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler; -} - - -/* Needs either rcu_read_lock() or rtnl lock */ -struct rmnet_port *rmnet_get_port(struct net_device *real_dev) -{ - if (rmnet_is_real_dev_registered(real_dev)) - return rcu_dereference_rtnl(real_dev->rx_handler_data); - else - return NULL; -} - -static rx_handler_result_t rmnet_rx_priv_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_nss_cb *nss_cb; - - if (!skb) - return RX_HANDLER_CONSUMED; - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - /* Check this so that we dont loop around netif_receive_skb */ - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - skb->dev->stats.rx_packets++; - return RX_HANDLER_PASS; - } - - while (skb) { - struct sk_buff *skb_frag = skb_shinfo(skb)->frag_list; - - skb_shinfo(skb)->frag_list = NULL; - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) - nss_cb->nss_tx(skb); - - skb = skb_frag; - } - - return RX_HANDLER_CONSUMED; -} - -/* Ingress / Egress Entry Points */ - -/* Processes packet as per ingress data format for receiving device. Logical - * endpoint is determined from packet inspection. Packet is then sent to the - * egress device listed in the logical endpoint configuration. - */ -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_port *port; - struct net_device *dev; - - if (!skb) - goto done; - - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - if (skb->protocol != htons(ETH_P_MAP)) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - - dev = skb->dev; - port = rmnet_get_port(dev); - - if (port == NULL) - return RX_HANDLER_PASS; - - port->chain_head = NULL; - port->chain_tail = NULL; - - switch (port->rmnet_mode) { - case RMNET_EPMODE_VND: - rmnet_map_ingress_handler(skb, port); - break; - case RMNET_EPMODE_BRIDGE: - //rmnet_bridge_handler(skb, port->bridge_ep); - break; - } - -done: - return RX_HANDLER_CONSUMED; -} - -static void rmnet_descriptor_deinit(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool; - struct rmnet_frag_descriptor *frag_desc, *tmp; - - pool = port->frag_desc_pool; - - list_for_each_entry_safe(frag_desc, tmp, &pool->free_list, list) { - kfree(frag_desc); - pool->pool_size--; - } - - kfree(pool); -} - -static int rmnet_descriptor_init(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool; - int i; - - spin_lock_init(&port->desc_pool_lock); - pool = kzalloc(sizeof(*pool), GFP_ATOMIC); - if (!pool) - return -ENOMEM; - - INIT_LIST_HEAD(&pool->free_list); - port->frag_desc_pool = pool; - - for (i = 0; i < RMNET_FRAG_DESCRIPTOR_POOL_SIZE; i++) { - struct rmnet_frag_descriptor *frag_desc; - - frag_desc = kzalloc(sizeof(*frag_desc), GFP_ATOMIC); - if (!frag_desc) - return -ENOMEM; - - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - list_add_tail(&frag_desc->list, &pool->free_list); - pool->pool_size++; - } - - return 0; -} - -struct rmnet_priv { - //struct rmnet_endpoint local_ep; - struct net_device *real_dev; - u8 mux_id; -}; - -static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rmnet_priv *priv; - - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - priv = netdev_priv(dev); - if (priv->real_dev) { - add_qhdr_v5(skb, priv->mux_id); - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - dev_queue_xmit(skb); - dev->stats.tx_packets++; - //rmnet_egress_handler(skb); - } else { - //this_cpu_inc(priv->pcpu_stats->stats.tx_drops); - kfree_skb(skb); - } - return NETDEV_TX_OK; -} - -static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu) -{ - if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE) - return -EINVAL; - - rmnet_dev->mtu = new_mtu; - return 0; -} - -static const struct net_device_ops rmnet_vnd_ops = { - .ndo_start_xmit = rmnet_vnd_start_xmit, - .ndo_change_mtu = rmnet_vnd_change_mtu, - //.ndo_get_iflink = rmnet_vnd_get_iflink, - //.ndo_add_slave = rmnet_add_bridge, - //.ndo_del_slave = rmnet_del_bridge, - //.ndo_init = rmnet_vnd_init, - //.ndo_uninit = rmnet_vnd_uninit, - //.ndo_get_stats64 = rmnet_get_stats64, -}; - -static void rmnet_vnd_setup(struct net_device *rmnet_dev) -{ - rmnet_dev->netdev_ops = &rmnet_vnd_ops; - rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE; - rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM; - random_ether_addr(rmnet_dev->dev_addr); - rmnet_dev->tx_queue_len = RMNET_TX_QUEUE_LEN; - - /* Raw IP mode */ - rmnet_dev->header_ops = NULL; /* No header */ - rmnet_dev->type = ARPHRD_RAWIP; - rmnet_dev->hard_header_len = 0; - rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - - //rmnet_dev->needs_free_netdev = true; - - rmnet_dev->hw_features = NETIF_F_RXCSUM; - rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - //rmnet_dev->hw_features |= NETIF_F_SG; - //rmnet_dev->hw_features |= NETIF_F_GRO_HW; -} -#else -#include -#include -#include -#include -#include -#include -#include -#include - -static uint nss_debug = 0; -module_param( nss_debug, uint, S_IRUGO | S_IWUSR); - -/* rmnet section */ - -#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) -#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) -#define RMNET_FLAGS_INGRESS_COALESCE (1U << 4) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5 (1U << 5) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5 (1U << 6) - -#ifdef CONFIG_ARCH_IPQ807x -#define CONFIG_QCA_NSS_DRV -#endif -#ifdef CONFIG_QCA_NSS_DRV -#include "rmnet_nss.c" -#else -#include "rmnet_nss.h" -#endif - -#include "rmnet_vnd.c" -#include "rmnet_map_command.c" -#include "rmnet_map_data.c" -#include "rmnet_descriptor.c" -#include "rmnet_config.c" -#include "rmnet_handlers.c" - -struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; - -void rmnet_data_init(struct net_device *real_dev, u32 nr_rmnet_devs) -{ - struct rmnet_port *port; - struct rmnet_endpoint *ep; - struct net_device *rmnet_dev = NULL; - u32 nr = 0; - struct rmnet_nss_cb *nss_cb; - int rc = 0; - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (!nss_cb) - { -#ifdef CONFIG_QCA_NSS_DRV - pr_err("%s(): initializing rmnet_nss\n", __func__); - RCU_INIT_POINTER(rmnet_nss_callbacks, &rmnet_nss); -#endif - } - - rtnl_lock(); - rc = rmnet_register_real_device(real_dev); - rtnl_unlock(); - - if (rc) { - pr_err("%s rmnet_register_real_device = %d\n", __func__, rc); - return; - } - - port = rmnet_get_port_rtnl(real_dev); - port->data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION - | RMNET_FLAGS_INGRESS_MAP_CKSUMV5 | RMNET_FLAGS_EGRESS_MAP_CKSUMV5; - port->rmnet_mode = RMNET_EPMODE_VND; - - for (nr = 0; nr < nr_rmnet_devs; nr++) { - u8 mux_id = 0x81+nr; - - ep = kzalloc(sizeof(*ep), GFP_ATOMIC); - - rtnl_lock(); - rmnet_dev = alloc_netdev(sizeof(struct rmnet_priv), - "rmnet_data%d", NET_NAME_PREDICTABLE, - rmnet_vnd_setup); - - rmnet_vnd_newlink(mux_id, rmnet_dev, port, real_dev, ep); - netdev_rx_handler_register(rmnet_dev, rmnet_rx_priv_handler, NULL); - rtnl_unlock(); - - hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]); - } - - port->nr_rmnet_devs = nr_rmnet_devs; -} - -void rmnet_data_deinit(struct net_device *real_dev, u32 nr_rmnet_devs) -{ - struct rmnet_port *port; - u32 nr = 0; - struct rmnet_nss_cb *nss_cb; - - if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) - return; - - port = rmnet_get_port_rtnl(real_dev); - - for (nr = 0; nr < nr_rmnet_devs; nr++) { - struct rmnet_endpoint *ep; - u8 mux_id = 0x81+nr; - - ep = rmnet_get_endpoint(port, mux_id); - if (ep) { - hlist_del_init_rcu(&ep->hlnode); - rmnet_vnd_dellink(mux_id, port, ep); - synchronize_rcu(); - kfree(ep); - } - } - - rmnet_unregister_real_device(real_dev, port); - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { -#ifdef CONFIG_QCA_NSS_DRV - struct hlist_node *tmp; - struct rmnet_nss_ctx *ctx; - int bkt; - - pr_err("%s(): exiting rmnet_nss\n", __func__); - RCU_INIT_POINTER(rmnet_nss_callbacks, NULL); - - /* Tear down all NSS contexts */ - hash_for_each_safe(rmnet_nss_ctx_hashtable, bkt, tmp, ctx, hnode) - rmnet_nss_free_ctx(ctx); -#endif - } -} -#endif diff --git a/quectel_MHI/src/devices/rmnet/rmnet_descriptor.c b/quectel_MHI/src/devices/rmnet/rmnet_descriptor.c deleted file mode 100644 index 75006d1..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_descriptor.c +++ /dev/null @@ -1,661 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Packet Descriptor Framework - * - */ - -#include -#include -#include -#include -#include "rmnet_config.h" -#include "rmnet_descriptor.h" -#include "rmnet_handlers.h" -#include "rmnet_private.h" -#include "rmnet_vnd.h" - -#define RMNET_FRAG_DESCRIPTOR_POOL_SIZE 64 -#define RMNET_DL_IND_HDR_SIZE (sizeof(struct rmnet_map_dl_ind_hdr) + \ - sizeof(struct rmnet_map_header) + \ - sizeof(struct rmnet_map_control_command_header)) -#define RMNET_DL_IND_TRL_SIZE (sizeof(struct rmnet_map_dl_ind_trl) + \ - sizeof(struct rmnet_map_header) + \ - sizeof(struct rmnet_map_control_command_header)) - -typedef void (*rmnet_perf_desc_hook_t)(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port); -typedef void (*rmnet_perf_chain_hook_t)(void); - -static struct rmnet_frag_descriptor * -rmnet_get_frag_descriptor(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool; - struct rmnet_frag_descriptor *frag_desc; - - spin_lock(&port->desc_pool_lock); - if (!list_empty(&pool->free_list)) { - frag_desc = list_first_entry(&pool->free_list, - struct rmnet_frag_descriptor, - list); - list_del_init(&frag_desc->list); - } else { - frag_desc = kzalloc(sizeof(*frag_desc), GFP_ATOMIC); - if (!frag_desc) - goto out; - - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - pool->pool_size++; - } - -out: - spin_unlock(&port->desc_pool_lock); - return frag_desc; -} - -static void rmnet_recycle_frag_descriptor(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool; - struct page *page = skb_frag_page(&frag_desc->frag); - - list_del(&frag_desc->list); - if (page) - put_page(page); - - memset(frag_desc, 0, sizeof(*frag_desc)); - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - spin_lock(&port->desc_pool_lock); - list_add_tail(&frag_desc->list, &pool->free_list); - spin_unlock(&port->desc_pool_lock); -} - -static void rmnet_descriptor_add_frag(struct rmnet_port *port, struct list_head *list, - struct page *p, u32 page_offset, u32 len) -{ - struct rmnet_frag_descriptor *frag_desc; - - frag_desc = rmnet_get_frag_descriptor(port); - if (!frag_desc) - return; - - rmnet_frag_fill(frag_desc, p, page_offset, len); - list_add_tail(&frag_desc->list, list); -} - -static u8 rmnet_frag_do_flow_control(struct rmnet_map_header *qmap, - struct rmnet_port *port, - int enable) -{ - struct rmnet_map_control_command *cmd; - struct rmnet_endpoint *ep; - struct net_device *vnd; - u16 ip_family; - u16 fc_seq; - u32 qos_id; - u8 mux_id; - int r; - - mux_id = qmap->mux_id; - cmd = (struct rmnet_map_control_command *) - ((char *)qmap + sizeof(*qmap)); - - if (mux_id >= RMNET_MAX_LOGICAL_EP) - return RX_HANDLER_CONSUMED; - - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) - return RX_HANDLER_CONSUMED; - - vnd = ep->egress_dev; - - ip_family = cmd->flow_control.ip_family; - fc_seq = ntohs(cmd->flow_control.flow_control_seq_num); - qos_id = ntohl(cmd->flow_control.qos_id); - - /* Ignore the ip family and pass the sequence number for both v4 and v6 - * sequence. User space does not support creating dedicated flows for - * the 2 protocols - */ - r = rmnet_vnd_do_flow_control(vnd, enable); - if (r) - return RMNET_MAP_COMMAND_UNSUPPORTED; - else - return RMNET_MAP_COMMAND_ACK; -} - -static void rmnet_frag_send_ack(struct rmnet_map_header *qmap, - unsigned char type, - struct rmnet_port *port) -{ - struct rmnet_map_control_command *cmd; - struct net_device *dev = port->dev; - struct sk_buff *skb; - u16 alloc_len = ntohs(qmap->pkt_len) + sizeof(*qmap); - - skb = alloc_skb(alloc_len, GFP_ATOMIC); - if (!skb) - return; - - skb->protocol = htons(ETH_P_MAP); - skb->dev = dev; - - cmd = rmnet_map_get_cmd_start(skb); - cmd->cmd_type = type & 0x03; - - netif_tx_lock(dev); - dev->netdev_ops->ndo_start_xmit(skb, dev); - netif_tx_unlock(dev); -} - - -/* Process MAP command frame and send N/ACK message as appropriate. Message cmd - * name is decoded here and appropriate handler is called. - */ -static void rmnet_frag_command(struct rmnet_map_header *qmap, struct rmnet_port *port) -{ - struct rmnet_map_control_command *cmd; - unsigned char command_name; - unsigned char rc = 0; - - cmd = (struct rmnet_map_control_command *) - ((char *)qmap + sizeof(*qmap)); - command_name = cmd->command_name; - - switch (command_name) { - case RMNET_MAP_COMMAND_FLOW_ENABLE: - rc = rmnet_frag_do_flow_control(qmap, port, 1); - break; - - case RMNET_MAP_COMMAND_FLOW_DISABLE: - rc = rmnet_frag_do_flow_control(qmap, port, 0); - break; - - default: - rc = RMNET_MAP_COMMAND_UNSUPPORTED; - break; - } - if (rc == RMNET_MAP_COMMAND_ACK) - rmnet_frag_send_ack(qmap, rc, port); -} - -static void rmnet_frag_deaggregate(skb_frag_t *frag, struct rmnet_port *port, - struct list_head *list) -{ - struct rmnet_map_header *maph; - u8 *data = skb_frag_address(frag); - u32 offset = 0; - u32 packet_len; - - while (offset < skb_frag_size(frag)) { - maph = (struct rmnet_map_header *)data; - packet_len = ntohs(maph->pkt_len); - - /* Some hardware can send us empty frames. Catch them */ - if (packet_len == 0) - return; - - packet_len += sizeof(*maph); - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) { - packet_len += sizeof(struct rmnet_map_dl_csum_trailer); - WARN_ON(1); - } else if (port->data_format & - (RMNET_FLAGS_INGRESS_MAP_CKSUMV5 | - RMNET_FLAGS_INGRESS_COALESCE) && !maph->cd_bit) { - u32 hsize = 0; - u8 type; - - type = ((struct rmnet_map_v5_coal_header *) - (data + sizeof(*maph)))->header_type; - switch (type) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - hsize = sizeof(struct rmnet_map_v5_coal_header); - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - hsize = sizeof(struct rmnet_map_v5_csum_header); - break; - } - - packet_len += hsize; - } - else { - //qmap_hex_dump(__func__, data, 64); - WARN_ON(1); - } - - if ((int)skb_frag_size(frag) - (int)packet_len < 0) - return; - - rmnet_descriptor_add_frag(port, list, skb_frag_page(frag), - frag->page_offset + offset, - packet_len); - - offset += packet_len; - data += packet_len; - } -} - -/* Allocate and populate an skb to contain the packet represented by the - * frag descriptor. - */ -static struct sk_buff *rmnet_alloc_skb(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct sk_buff *head_skb, *current_skb, *skb; - struct skb_shared_info *shinfo; - struct rmnet_frag_descriptor *sub_frag, *tmp; - - /* Use the exact sizes if we know them (i.e. RSB/RSC, rmnet_perf) */ - if (frag_desc->hdrs_valid) { - u16 hdr_len = frag_desc->ip_len + frag_desc->trans_len; - - head_skb = alloc_skb(hdr_len + RMNET_MAP_DESC_HEADROOM, - GFP_ATOMIC); - if (!head_skb) - return NULL; - - skb_reserve(head_skb, RMNET_MAP_DESC_HEADROOM); - skb_put_data(head_skb, frag_desc->hdr_ptr, hdr_len); - skb_reset_network_header(head_skb); - - if (frag_desc->trans_len) - skb_set_transport_header(head_skb, frag_desc->ip_len); - - /* Packets that have no data portion don't need any frags */ - if (hdr_len == skb_frag_size(&frag_desc->frag)) - goto skip_frags; - - /* If the headers we added are the start of the page, - * we don't want to add them twice - */ - if (frag_desc->hdr_ptr == rmnet_frag_data_ptr(frag_desc)) { - if (!rmnet_frag_pull(frag_desc, port, hdr_len)) { - kfree_skb(head_skb); - return NULL; - } - } - } else { - /* Allocate enough space to avoid penalties in the stack - * from __pskb_pull_tail() - */ - head_skb = alloc_skb(256 + RMNET_MAP_DESC_HEADROOM, - GFP_ATOMIC); - if (!head_skb) - return NULL; - - skb_reserve(head_skb, RMNET_MAP_DESC_HEADROOM); - } - - /* Add main fragment */ - get_page(skb_frag_page(&frag_desc->frag)); - skb_add_rx_frag(head_skb, 0, skb_frag_page(&frag_desc->frag), - frag_desc->frag.page_offset, - skb_frag_size(&frag_desc->frag), - skb_frag_size(&frag_desc->frag)); - - shinfo = skb_shinfo(head_skb); - current_skb = head_skb; - - /* Add in any frags from rmnet_perf */ - list_for_each_entry_safe(sub_frag, tmp, &frag_desc->sub_frags, list) { - skb_frag_t *frag; - u32 frag_size; - - frag = &sub_frag->frag; - frag_size = skb_frag_size(frag); - -add_frag: - if (shinfo->nr_frags < MAX_SKB_FRAGS) { - get_page(skb_frag_page(frag)); - skb_add_rx_frag(current_skb, shinfo->nr_frags, - skb_frag_page(frag), frag->page_offset, - frag_size, frag_size); - if (current_skb != head_skb) { - head_skb->len += frag_size; - head_skb->data_len += frag_size; - } - } else { - /* Alloc a new skb and try again */ - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) - break; - - if (current_skb == head_skb) - shinfo->frag_list = skb; - else - current_skb->next = skb; - - current_skb = skb; - shinfo = skb_shinfo(current_skb); - goto add_frag; - } - - rmnet_recycle_frag_descriptor(sub_frag, port); - } - -skip_frags: - head_skb->dev = frag_desc->dev; - rmnet_set_skb_proto(head_skb); - - /* Handle any header metadata that needs to be updated after RSB/RSC - * segmentation - */ - if (frag_desc->ip_id_set) { - struct iphdr *iph; - - iph = (struct iphdr *)rmnet_map_data_ptr(head_skb); - csum_replace2(&iph->check, iph->id, frag_desc->ip_id); - iph->id = frag_desc->ip_id; - } - - if (frag_desc->tcp_seq_set) { - struct tcphdr *th; - - th = (struct tcphdr *) - (rmnet_map_data_ptr(head_skb) + frag_desc->ip_len); - th->seq = frag_desc->tcp_seq; - } - - /* Handle csum offloading */ - if (frag_desc->csum_valid && frag_desc->hdrs_valid) { - /* Set the partial checksum information */ - //rmnet_frag_partial_csum(head_skb, frag_desc); - WARN_ON(1); - } else if (frag_desc->csum_valid) { - /* Non-RSB/RSC/perf packet. The current checksum is fine */ - head_skb->ip_summed = CHECKSUM_UNNECESSARY; - } else if (frag_desc->hdrs_valid && - (frag_desc->trans_proto == IPPROTO_TCP || - frag_desc->trans_proto == IPPROTO_UDP)) { - /* Unfortunately, we have to fake a bad checksum here, since - * the original bad value is lost by the hardware. The only - * reliable way to do it is to calculate the actual checksum - * and corrupt it. - */ - __sum16 *check; - __wsum csum; - unsigned int offset = skb_transport_offset(head_skb); - __sum16 pseudo; - - WARN_ON(1); - /* Calculate pseudo header and update header fields */ - if (frag_desc->ip_proto == 4) { - struct iphdr *iph = ip_hdr(head_skb); - __be16 tot_len = htons(head_skb->len); - - csum_replace2(&iph->check, iph->tot_len, tot_len); - iph->tot_len = tot_len; - pseudo = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - head_skb->len - - frag_desc->ip_len, - frag_desc->trans_proto, 0); - } else { - struct ipv6hdr *ip6h = ipv6_hdr(head_skb); - - ip6h->payload_len = htons(head_skb->len - - sizeof(*ip6h)); - pseudo = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - head_skb->len - - frag_desc->ip_len, - frag_desc->trans_proto, 0); - } - - if (frag_desc->trans_proto == IPPROTO_TCP) { - check = &tcp_hdr(head_skb)->check; - } else { - udp_hdr(head_skb)->len = htons(head_skb->len - - frag_desc->ip_len); - check = &udp_hdr(head_skb)->check; - } - - *check = pseudo; - csum = skb_checksum(head_skb, offset, head_skb->len - offset, - 0); - /* Add 1 to corrupt. This cannot produce a final value of 0 - * since csum_fold() can't return a value of 0xFFFF - */ - *check = csum16_add(csum_fold(csum), htons(1)); - head_skb->ip_summed = CHECKSUM_NONE; - } - - /* Handle any rmnet_perf metadata */ - if (frag_desc->hash) { - head_skb->hash = frag_desc->hash; - head_skb->sw_hash = 1; - } - - if (frag_desc->flush_shs) - head_skb->cb[0] = 1; - - /* Handle coalesced packets */ - //if (frag_desc->gso_segs > 1) - // rmnet_frag_gso_stamp(head_skb, frag_desc); - - return head_skb; -} - -/* Deliver the packets contained within a frag descriptor */ -static void rmnet_frag_deliver(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct sk_buff *skb; - - skb = rmnet_alloc_skb(frag_desc, port); - if (skb) - rmnet_deliver_skb(skb, port); - rmnet_recycle_frag_descriptor(frag_desc, port); -} - -/* Process a QMAPv5 packet header */ -static int rmnet_frag_process_next_hdr_packet(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - struct list_head *list, - u16 len) -{ - int rc = 0; - - switch (rmnet_frag_get_next_hdr_type(frag_desc)) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - rc = -1; - WARN_ON(1); - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - if (rmnet_frag_get_csum_valid(frag_desc)) { - frag_desc->csum_valid = true; - } else { - } - - if (!rmnet_frag_pull(frag_desc, port, - sizeof(struct rmnet_map_header) + - sizeof(struct rmnet_map_v5_csum_header))) { - rc = -EINVAL; - break; - } - - frag_desc->hdr_ptr = rmnet_frag_data_ptr(frag_desc); - - /* Remove padding only for csum offload packets. - * Coalesced packets should never have padding. - */ - if (!rmnet_frag_trim(frag_desc, port, len)) { - rc = -EINVAL; - break; - } - - list_del_init(&frag_desc->list); - list_add_tail(&frag_desc->list, list); - break; - default: - //qmap_hex_dump(__func__, rmnet_frag_data_ptr(frag_desc), 64); - rc = -EINVAL; - break; - } - - return rc; -} - -static void -__rmnet_frag_ingress_handler(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct rmnet_map_header *qmap; - struct rmnet_endpoint *ep; - struct rmnet_frag_descriptor *frag, *tmp; - LIST_HEAD(segs); - u16 len, pad; - u8 mux_id; - - qmap = (struct rmnet_map_header *)skb_frag_address(&frag_desc->frag); - mux_id = qmap->mux_id; - pad = qmap->pad_len; - len = ntohs(qmap->pkt_len) - pad; - - if (qmap->cd_bit) { - if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { - //rmnet_frag_flow_command(qmap, port, len); - goto recycle; - } - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS) - rmnet_frag_command(qmap, port); - - goto recycle; - } - - if (mux_id >= RMNET_MAX_LOGICAL_EP) - goto recycle; - - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) - goto recycle; - - frag_desc->dev = ep->egress_dev; - - /* Handle QMAPv5 packet */ - if (qmap->next_hdr && - (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5))) { - if (rmnet_frag_process_next_hdr_packet(frag_desc, port, &segs, - len)) - goto recycle; - } else { - /* We only have the main QMAP header to worry about */ - if (!rmnet_frag_pull(frag_desc, port, sizeof(*qmap))) - return; - - frag_desc->hdr_ptr = rmnet_frag_data_ptr(frag_desc); - - if (!rmnet_frag_trim(frag_desc, port, len)) - return; - - list_add_tail(&frag_desc->list, &segs); - } - - list_for_each_entry_safe(frag, tmp, &segs, list) { - list_del_init(&frag->list); - rmnet_frag_deliver(frag, port); - } - return; - -recycle: - rmnet_recycle_frag_descriptor(frag_desc, port); -} - -static void rmnet_frag_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - LIST_HEAD(desc_list); - int i = 0; - struct rmnet_nss_cb *nss_cb; - - /* Deaggregation and freeing of HW originating - * buffers is done within here - */ - while (skb) { - struct sk_buff *skb_frag; - - port->chain_head = NULL; - port->chain_tail = NULL; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - rmnet_frag_deaggregate(&skb_shinfo(skb)->frags[i], port, - &desc_list); - if (!list_empty(&desc_list)) { - struct rmnet_frag_descriptor *frag_desc, *tmp; - - list_for_each_entry_safe(frag_desc, tmp, - &desc_list, list) { - list_del_init(&frag_desc->list); - __rmnet_frag_ingress_handler(frag_desc, - port); - } - } - } - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb && port->chain_head) { - port->chain_head->cb[0] = 0; - netif_receive_skb(port->chain_head); - } - - skb_frag = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; - consume_skb(skb); - skb = skb_frag; - } -} - -void rmnet_descriptor_deinit(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool; - struct rmnet_frag_descriptor *frag_desc, *tmp; - - pool = port->frag_desc_pool; - - list_for_each_entry_safe(frag_desc, tmp, &pool->free_list, list) { - kfree(frag_desc); - pool->pool_size--; - } - - kfree(pool); -} - -int rmnet_descriptor_init(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool; - int i; - - spin_lock_init(&port->desc_pool_lock); - pool = kzalloc(sizeof(*pool), GFP_ATOMIC); - if (!pool) - return -ENOMEM; - - INIT_LIST_HEAD(&pool->free_list); - port->frag_desc_pool = pool; - - for (i = 0; i < RMNET_FRAG_DESCRIPTOR_POOL_SIZE; i++) { - struct rmnet_frag_descriptor *frag_desc; - - frag_desc = kzalloc(sizeof(*frag_desc), GFP_ATOMIC); - if (!frag_desc) - return -ENOMEM; - - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - list_add_tail(&frag_desc->list, &pool->free_list); - pool->pool_size++; - } - - return 0; -} diff --git a/quectel_MHI/src/devices/rmnet/rmnet_descriptor.h b/quectel_MHI/src/devices/rmnet/rmnet_descriptor.h deleted file mode 100644 index 962c663..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_descriptor.h +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Packet Descriptor Framework - * - */ - -#ifndef _RMNET_DESCRIPTOR_H_ -#define _RMNET_DESCRIPTOR_H_ - -#include -#include -#include -#include "rmnet_config.h" -#include "rmnet_map.h" - -struct rmnet_frag_descriptor_pool { - struct list_head free_list; - u32 pool_size; -}; - -struct rmnet_frag_descriptor { - struct list_head list; - struct list_head sub_frags; - skb_frag_t frag; - u8 *hdr_ptr; - struct net_device *dev; - u32 hash; - __be32 tcp_seq; - __be16 ip_id; - u16 data_offset; - u16 gso_size; - u16 gso_segs; - u16 ip_len; - u16 trans_len; - u8 ip_proto; - u8 trans_proto; - u8 pkt_id; - u8 csum_valid:1, - hdrs_valid:1, - ip_id_set:1, - tcp_seq_set:1, - flush_shs:1, - reserved:3; -}; - -/* Descriptor management */ -static struct rmnet_frag_descriptor * -rmnet_get_frag_descriptor(struct rmnet_port *port); -static void rmnet_recycle_frag_descriptor(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port); -static void rmnet_descriptor_add_frag(struct rmnet_port *port, struct list_head *list, - struct page *p, u32 page_offset, u32 len); - -/* QMAP command packets */ - -/* Ingress data handlers */ -static void rmnet_frag_deaggregate(skb_frag_t *frag, struct rmnet_port *port, - struct list_head *list); -static void rmnet_frag_deliver(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port); -static int rmnet_frag_process_next_hdr_packet(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - struct list_head *list, - u16 len); -static void rmnet_frag_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port); - -static int rmnet_descriptor_init(struct rmnet_port *port); -static void rmnet_descriptor_deinit(struct rmnet_port *port); - -static inline void *rmnet_frag_data_ptr(struct rmnet_frag_descriptor *frag_desc) -{ - return skb_frag_address(&frag_desc->frag); -} - -static inline void *rmnet_frag_pull(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - unsigned int size) -{ - if (size >= skb_frag_size(&frag_desc->frag)) { - pr_info("%s(): Pulling %u bytes from %u byte pkt. Dropping\n", - __func__, size, skb_frag_size(&frag_desc->frag)); - rmnet_recycle_frag_descriptor(frag_desc, port); - return NULL; - } - - frag_desc->frag.page_offset += size; - skb_frag_size_sub(&frag_desc->frag, size); - - return rmnet_frag_data_ptr(frag_desc); -} - -static inline void *rmnet_frag_trim(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - unsigned int size) -{ - if (!size) { - pr_info("%s(): Trimming %u byte pkt to 0. Dropping\n", - __func__, skb_frag_size(&frag_desc->frag)); - rmnet_recycle_frag_descriptor(frag_desc, port); - return NULL; - } - - if (size < skb_frag_size(&frag_desc->frag)) - skb_frag_size_set(&frag_desc->frag, size); - - return rmnet_frag_data_ptr(frag_desc); -} - -static inline void rmnet_frag_fill(struct rmnet_frag_descriptor *frag_desc, - struct page *p, u32 page_offset, u32 len) -{ - get_page(p); - __skb_frag_set_page(&frag_desc->frag, p); - skb_frag_size_set(&frag_desc->frag, len); - frag_desc->frag.page_offset = page_offset; -} - -static inline u8 -rmnet_frag_get_next_hdr_type(struct rmnet_frag_descriptor *frag_desc) -{ - unsigned char *data = rmnet_frag_data_ptr(frag_desc); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_coal_header *)data)->header_type; -} - -static inline bool -rmnet_frag_get_csum_valid(struct rmnet_frag_descriptor *frag_desc) -{ - unsigned char *data = rmnet_frag_data_ptr(frag_desc); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_csum_header *)data)->csum_valid_required; -} - -#endif /* _RMNET_DESCRIPTOR_H_ */ diff --git a/quectel_MHI/src/devices/rmnet/rmnet_handlers.c b/quectel_MHI/src/devices/rmnet/rmnet_handlers.c deleted file mode 100644 index 6f1ce9d..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_handlers.c +++ /dev/null @@ -1,374 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Data ingress/egress handler - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "rmnet_private.h" -#include "rmnet_config.h" -#include "rmnet_vnd.h" -#include "rmnet_map.h" -#include "rmnet_handlers.h" -#include "rmnet_descriptor.h" - -#define RMNET_IP_VERSION_4 0x40 -#define RMNET_IP_VERSION_6 0x60 - -/* Helper Functions */ - -static void rmnet_set_skb_proto(struct sk_buff *skb) -{ - switch (rmnet_map_data_ptr(skb)[0] & 0xF0) { - case RMNET_IP_VERSION_4: - skb->protocol = htons(ETH_P_IP); - break; - case RMNET_IP_VERSION_6: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - skb->protocol = htons(ETH_P_MAP); - break; - } -} - -/* Generic handler */ - -static void -rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port) -{ - struct rmnet_nss_cb *nss_cb; - - rmnet_vnd_rx_fixup(skb->dev, skb->len); - - /* Pass off the packet to NSS driver if we can */ - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { - if (!port->chain_head) - port->chain_head = skb; - else - skb_shinfo(port->chain_tail)->frag_list = skb; - - port->chain_tail = skb; - return; - } - - skb_reset_transport_header(skb); - skb_reset_network_header(skb); - - skb->pkt_type = PACKET_HOST; - skb_set_mac_header(skb, 0); - - //if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { - //} else { - //if (!rmnet_check_skb_can_gro(skb)) - // gro_cells_receive(&priv->gro_cells, skb); - //else - netif_receive_skb(skb); - //} -} - -/* Deliver a list of skbs after undoing coalescing */ -static void rmnet_deliver_skb_list(struct sk_buff_head *head, - struct rmnet_port *port) -{ - struct sk_buff *skb; - - while ((skb = __skb_dequeue(head))) { - rmnet_set_skb_proto(skb); - rmnet_deliver_skb(skb, port); - } -} - -/* MAP handler */ - -static void -_rmnet_map_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - struct rmnet_map_header *qmap; - struct rmnet_endpoint *ep; - struct sk_buff_head list; - u16 len, pad; - u8 mux_id; - - /* We don't need the spinlock since only we touch this */ - __skb_queue_head_init(&list); - - qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb); - if (qmap->cd_bit) { - if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { - //if (!rmnet_map_flow_command(skb, port, false)) - return; - } - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_COMMANDS) - return rmnet_map_command(skb, port); - - goto free_skb; - } - - mux_id = qmap->mux_id; - pad = qmap->pad_len; - len = ntohs(qmap->pkt_len) - pad; - - if (mux_id >= RMNET_MAX_LOGICAL_EP) - goto free_skb; - - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) - goto free_skb; - - skb->dev = ep->egress_dev; - - /* Handle QMAPv5 packet */ - if (qmap->next_hdr && - (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5))) { - if (rmnet_map_process_next_hdr_packet(skb, &list, len)) - goto free_skb; - } else { - /* We only have the main QMAP header to worry about */ - pskb_pull(skb, sizeof(*qmap)); - - rmnet_set_skb_proto(skb); - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) { - //if (!rmnet_map_checksum_downlink_packet(skb, len + pad)) - // skb->ip_summed = CHECKSUM_UNNECESSARY; - } - - pskb_trim(skb, len); - - /* Push the single packet onto the list */ - __skb_queue_tail(&list, skb); - } - - rmnet_deliver_skb_list(&list, port); - return; - -free_skb: - kfree_skb(skb); -} - -static void -rmnet_map_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - struct sk_buff *skbn; - - if (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5)) { - if (skb_is_nonlinear(skb)) { - rmnet_frag_ingress_handler(skb, port); - return; - } - } - - /* Deaggregation and freeing of HW originating - * buffers is done within here - */ - while (skb) { - struct sk_buff *skb_frag = skb_shinfo(skb)->frag_list; - - skb_shinfo(skb)->frag_list = NULL; - while ((skbn = rmnet_map_deaggregate(skb, port)) != NULL) { - _rmnet_map_ingress_handler(skbn, port); - - if (skbn == skb) - goto next_skb; - } - - consume_skb(skb); -next_skb: - skb = skb_frag; - } -} - -static int rmnet_map_egress_handler(struct sk_buff *skb, - struct rmnet_port *port, u8 mux_id, - struct net_device *orig_dev) -{ - int required_headroom, additional_header_len, csum_type; - struct rmnet_map_header *map_header; - - additional_header_len = 0; - required_headroom = sizeof(struct rmnet_map_header); - csum_type = 0; - - if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV4) { - additional_header_len = sizeof(struct rmnet_map_ul_csum_header); - csum_type = RMNET_FLAGS_EGRESS_MAP_CKSUMV4; - } else if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV5) { - additional_header_len = sizeof(struct rmnet_map_v5_csum_header); - csum_type = RMNET_FLAGS_EGRESS_MAP_CKSUMV5; - } - - required_headroom += additional_header_len; - - if (skb_headroom(skb) < required_headroom) { - if (pskb_expand_head(skb, required_headroom, 0, GFP_ATOMIC)) - return -ENOMEM; - } - - if (csum_type) - rmnet_map_checksum_uplink_packet(skb, orig_dev, csum_type); - - map_header = rmnet_map_add_map_header(skb, additional_header_len, 0, - port); - if (!map_header) - return -ENOMEM; - - map_header->mux_id = mux_id; - - if (port->data_format & RMNET_EGRESS_FORMAT_AGGREGATION) { - if (rmnet_map_tx_agg_skip(skb, required_headroom)) - goto done; - - rmnet_map_tx_aggregate(skb, port); - return -EINPROGRESS; - } - -done: - skb->protocol = htons(ETH_P_MAP); - return 0; -} - -static void -rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev) -{ - if (bridge_dev) { - skb->dev = bridge_dev; - dev_queue_xmit(skb); - } -} - -/* Ingress / Egress Entry Points */ - -/* Processes packet as per ingress data format for receiving device. Logical - * endpoint is determined from packet inspection. Packet is then sent to the - * egress device listed in the logical endpoint configuration. - */ -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_port *port; - struct net_device *dev; - - if (!skb) - goto done; - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - dev = skb->dev; - port = rmnet_get_port(dev); - - port->chain_head = NULL; - port->chain_tail = NULL; - - switch (port->rmnet_mode) { - case RMNET_EPMODE_VND: - rmnet_map_ingress_handler(skb, port); - break; - case RMNET_EPMODE_BRIDGE: - rmnet_bridge_handler(skb, port->bridge_ep); - break; - } - -done: - return RX_HANDLER_CONSUMED; -} - -static rx_handler_result_t rmnet_rx_priv_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_nss_cb *nss_cb; - - if (!skb) - return RX_HANDLER_CONSUMED; - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - /* Check this so that we dont loop around netif_receive_skb */ - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - skb->dev->stats.rx_packets++; - return RX_HANDLER_PASS; - } - - while (skb) { - struct sk_buff *skb_frag = skb_shinfo(skb)->frag_list; - - skb_shinfo(skb)->frag_list = NULL; - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) - nss_cb->nss_tx(skb); - - skb = skb_frag; - } - - return RX_HANDLER_CONSUMED; -} - -/* Modifies packet as per logical endpoint configuration and egress data format - * for egress device configured in logical endpoint. Packet is then transmitted - * on the egress device. - */ -static void rmnet_egress_handler(struct sk_buff *skb) -{ - struct net_device *orig_dev; - struct rmnet_port *port; - struct rmnet_priv *priv; - u8 mux_id; - int err; - u32 skb_len; - - skb_orphan(skb); - - orig_dev = skb->dev; - priv = netdev_priv(orig_dev); - skb->dev = priv->real_dev; - mux_id = priv->mux_id; - - port = rmnet_get_port(skb->dev); - if (!port) - goto drop; - - skb_len = skb->len; - err = rmnet_map_egress_handler(skb, port, mux_id, orig_dev); - if (err == -ENOMEM) - goto drop; - else if (err == -EINPROGRESS) { - rmnet_vnd_tx_fixup(orig_dev, skb_len); - return; - } - - rmnet_vnd_tx_fixup(orig_dev, skb_len); - - dev_queue_xmit(skb); - return; - -drop: - this_cpu_inc(priv->pcpu_stats->stats.tx_drops); - kfree_skb(skb); -} diff --git a/quectel_MHI/src/devices/rmnet/rmnet_handlers.h b/quectel_MHI/src/devices/rmnet/rmnet_handlers.h deleted file mode 100644 index 29837ba..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_handlers.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (c) 2013, 2016-2017, 2019 - * The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Data ingress/egress handler - * - */ - -#ifndef _RMNET_HANDLERS_H_ -#define _RMNET_HANDLERS_H_ - -#include "rmnet_config.h" - -enum rmnet_packet_context { - RMNET_NET_RX_CTX, - RMNET_WQ_CTX, -}; - -static void rmnet_egress_handler(struct sk_buff *skb); -static void rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port); -static void rmnet_set_skb_proto(struct sk_buff *skb); -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb); -static rx_handler_result_t rmnet_rx_priv_handler(struct sk_buff **pskb); -#endif /* _RMNET_HANDLERS_H_ */ diff --git a/quectel_MHI/src/devices/rmnet/rmnet_map.h b/quectel_MHI/src/devices/rmnet/rmnet_map.h deleted file mode 100644 index ab49149..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_map.h +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _RMNET_MAP_H_ -#define _RMNET_MAP_H_ - -#include -#include "rmnet_config.h" - -struct rmnet_map_control_command { - u8 command_name; - u8 cmd_type:2; - u8 reserved:6; - u16 reserved2; - u32 transaction_id; - union { - struct { - u16 ip_family:2; - u16 reserved:14; - __be16 flow_control_seq_num; - __be32 qos_id; - } flow_control; - u8 data[0]; - }; -} __aligned(1); - -enum rmnet_map_commands { - RMNET_MAP_COMMAND_NONE, - RMNET_MAP_COMMAND_FLOW_DISABLE, - RMNET_MAP_COMMAND_FLOW_ENABLE, - RMNET_MAP_COMMAND_FLOW_START = 7, - RMNET_MAP_COMMAND_FLOW_END = 8, - /* These should always be the last 2 elements */ - RMNET_MAP_COMMAND_UNKNOWN, - RMNET_MAP_COMMAND_ENUM_LENGTH -}; - -enum rmnet_map_v5_header_type { - RMNET_MAP_HEADER_TYPE_UNKNOWN, - RMNET_MAP_HEADER_TYPE_COALESCING = 0x1, - RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2, - RMNET_MAP_HEADER_TYPE_ENUM_LENGTH -}; - -enum rmnet_map_v5_close_type { - RMNET_MAP_COAL_CLOSE_NON_COAL, - RMNET_MAP_COAL_CLOSE_IP_MISS, - RMNET_MAP_COAL_CLOSE_TRANS_MISS, - RMNET_MAP_COAL_CLOSE_HW, - RMNET_MAP_COAL_CLOSE_COAL, -}; - -enum rmnet_map_v5_close_value { - RMNET_MAP_COAL_CLOSE_HW_NL, - RMNET_MAP_COAL_CLOSE_HW_PKT, - RMNET_MAP_COAL_CLOSE_HW_BYTE, - RMNET_MAP_COAL_CLOSE_HW_TIME, - RMNET_MAP_COAL_CLOSE_HW_EVICT, -}; - -/* Main QMAP header */ -struct rmnet_map_header { - u8 pad_len:6; - u8 next_hdr:1; - u8 cd_bit:1; - u8 mux_id; - __be16 pkt_len; -} __aligned(1); - -/* QMAP v5 headers */ -struct rmnet_map_v5_csum_header { - u8 next_hdr:1; - u8 header_type:7; - u8 hw_reserved:7; - u8 csum_valid_required:1; - __be16 reserved; -} __aligned(1); - -struct rmnet_map_v5_nl_pair { - __be16 pkt_len; - u8 csum_error_bitmap; - u8 num_packets; -} __aligned(1); - -/* NLO: Number-length object */ -#define RMNET_MAP_V5_MAX_NLOS (6) -#define RMNET_MAP_V5_MAX_PACKETS (48) - -struct rmnet_map_v5_coal_header { - u8 next_hdr:1; - u8 header_type:7; - u8 reserved1:4; - u8 num_nlos:3; - u8 csum_valid:1; - u8 close_type:4; - u8 close_value:4; - u8 reserved2:4; - u8 virtual_channel_id:4; - - struct rmnet_map_v5_nl_pair nl_pairs[RMNET_MAP_V5_MAX_NLOS]; -} __aligned(1); - -/* QMAP v4 headers */ -struct rmnet_map_dl_csum_trailer { - u8 reserved1; - u8 valid:1; - u8 reserved2:7; - u16 csum_start_offset; - u16 csum_length; - __be16 csum_value; -} __aligned(1); - -struct rmnet_map_ul_csum_header { - __be16 csum_start_offset; - u16 csum_insert_offset:14; - u16 udp_ind:1; - u16 csum_enabled:1; -} __aligned(1); - -struct rmnet_map_control_command_header { - u8 command_name; - u8 cmd_type:2; - u8 reserved:5; - u8 e:1; - u16 source_id:15; - u16 ext:1; - u32 transaction_id; -} __aligned(1); - -struct rmnet_map_flow_info_le { - __be32 mux_id; - __be32 flow_id; - __be32 bytes; - __be32 pkts; -} __aligned(1); - -struct rmnet_map_flow_info_be { - u32 mux_id; - u32 flow_id; - u32 bytes; - u32 pkts; -} __aligned(1); - -struct rmnet_map_dl_ind_hdr { - union { - struct { - u32 seq; - u32 bytes; - u32 pkts; - u32 flows; - struct rmnet_map_flow_info_le flow[0]; - } le __aligned(1); - struct { - __be32 seq; - __be32 bytes; - __be32 pkts; - __be32 flows; - struct rmnet_map_flow_info_be flow[0]; - } be __aligned(1); - } __aligned(1); -} __aligned(1); - -struct rmnet_map_dl_ind_trl { - union { - __be32 seq_be; - u32 seq_le; - } __aligned(1); -} __aligned(1); - -struct rmnet_map_dl_ind { - u8 priority; - union { - void (*dl_hdr_handler)(struct rmnet_map_dl_ind_hdr *); - void (*dl_hdr_handler_v2)(struct rmnet_map_dl_ind_hdr *, - struct - rmnet_map_control_command_header *); - } __aligned(1); - union { - void (*dl_trl_handler)(struct rmnet_map_dl_ind_trl *); - void (*dl_trl_handler_v2)(struct rmnet_map_dl_ind_trl *, - struct - rmnet_map_control_command_header *); - } __aligned(1); - struct list_head list; -}; - -#define RMNET_MAP_GET_MUX_ID(Y) (((struct rmnet_map_header *) \ - (Y)->data)->mux_id) -#define RMNET_MAP_GET_CD_BIT(Y) (((struct rmnet_map_header *) \ - (Y)->data)->cd_bit) -#define RMNET_MAP_GET_PAD(Y) (((struct rmnet_map_header *) \ - (Y)->data)->pad_len) -#define RMNET_MAP_GET_CMD_START(Y) ((struct rmnet_map_control_command *) \ - ((Y)->data + \ - sizeof(struct rmnet_map_header))) -#define RMNET_MAP_GET_LENGTH(Y) (ntohs(((struct rmnet_map_header *) \ - (Y)->data)->pkt_len)) - -#define RMNET_MAP_DEAGGR_SPACING 64 -#define RMNET_MAP_DEAGGR_HEADROOM (RMNET_MAP_DEAGGR_SPACING / 2) -#define RMNET_MAP_DESC_HEADROOM 128 - -#define RMNET_MAP_COMMAND_REQUEST 0 -#define RMNET_MAP_COMMAND_ACK 1 -#define RMNET_MAP_COMMAND_UNSUPPORTED 2 -#define RMNET_MAP_COMMAND_INVALID 3 - -#define RMNET_MAP_NO_PAD_BYTES 0 -#define RMNET_MAP_ADD_PAD_BYTES 1 - -static inline unsigned char *rmnet_map_data_ptr(struct sk_buff *skb) -{ - /* Nonlinear packets we receive are entirely within frag 0 */ - if (skb_is_nonlinear(skb) && skb->len == skb->data_len) - return skb_frag_address(skb_shinfo(skb)->frags); - - return skb->data; -} - -static inline struct rmnet_map_control_command * -rmnet_map_get_cmd_start(struct sk_buff *skb) -{ - unsigned char *data = rmnet_map_data_ptr(skb); - - data += sizeof(struct rmnet_map_header); - return (struct rmnet_map_control_command *)data; -} - -static inline u8 rmnet_map_get_next_hdr_type(struct sk_buff *skb) -{ - unsigned char *data = rmnet_map_data_ptr(skb); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_coal_header *)data)->header_type; -} - -static inline bool rmnet_map_get_csum_valid(struct sk_buff *skb) -{ - unsigned char *data = rmnet_map_data_ptr(skb); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_csum_header *)data)->csum_valid_required; -} - -static struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, - struct rmnet_port *port); -static struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb, - int hdrlen, int pad, - struct rmnet_port *port); -static void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port); -static void rmnet_map_checksum_uplink_packet(struct sk_buff *skb, - struct net_device *orig_dev, - int csum_type); -static int rmnet_map_process_next_hdr_packet(struct sk_buff *skb, - struct sk_buff_head *list, - u16 len); -static int rmnet_map_tx_agg_skip(struct sk_buff *skb, int offset); -static void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port); -static void rmnet_map_tx_aggregate_init(struct rmnet_port *port); -static void rmnet_map_tx_aggregate_exit(struct rmnet_port *port); -static void rmnet_map_cmd_init(struct rmnet_port *port); -static void rmnet_map_cmd_exit(struct rmnet_port *port); -#endif /* _RMNET_MAP_H_ */ diff --git a/quectel_MHI/src/devices/rmnet/rmnet_map_command.c b/quectel_MHI/src/devices/rmnet/rmnet_map_command.c deleted file mode 100644 index 6c33184..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_map_command.c +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include "rmnet_config.h" -#include "rmnet_map.h" -#include "rmnet_private.h" -#include "rmnet_vnd.h" - -#define RMNET_DL_IND_HDR_SIZE (sizeof(struct rmnet_map_dl_ind_hdr) + \ - sizeof(struct rmnet_map_header) + \ - sizeof(struct rmnet_map_control_command_header)) - -#define RMNET_MAP_CMD_SIZE (sizeof(struct rmnet_map_header) + \ - sizeof(struct rmnet_map_control_command_header)) - -#define RMNET_DL_IND_TRL_SIZE (sizeof(struct rmnet_map_dl_ind_trl) + \ - sizeof(struct rmnet_map_header) + \ - sizeof(struct rmnet_map_control_command_header)) - -static u8 rmnet_map_do_flow_control(struct sk_buff *skb, - struct rmnet_port *port, - int enable) -{ - struct rmnet_map_header *qmap; - struct rmnet_map_control_command *cmd; - struct rmnet_endpoint *ep; - struct net_device *vnd; - u16 ip_family; - u16 fc_seq; - u32 qos_id; - u8 mux_id; - int r; - - qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb); - mux_id = qmap->mux_id; - cmd = rmnet_map_get_cmd_start(skb); - - if (mux_id >= RMNET_MAX_LOGICAL_EP) { - kfree_skb(skb); - return RX_HANDLER_CONSUMED; - } - - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) { - kfree_skb(skb); - return RX_HANDLER_CONSUMED; - } - - vnd = ep->egress_dev; - - ip_family = cmd->flow_control.ip_family; - fc_seq = ntohs(cmd->flow_control.flow_control_seq_num); - qos_id = ntohl(cmd->flow_control.qos_id); - - /* Ignore the ip family and pass the sequence number for both v4 and v6 - * sequence. User space does not support creating dedicated flows for - * the 2 protocols - */ - r = rmnet_vnd_do_flow_control(vnd, enable); - if (r) { - kfree_skb(skb); - return RMNET_MAP_COMMAND_UNSUPPORTED; - } else { - return RMNET_MAP_COMMAND_ACK; - } -} - -static void rmnet_map_send_ack(struct sk_buff *skb, - unsigned char type, - struct rmnet_port *port) -{ - struct rmnet_map_control_command *cmd; - struct net_device *dev = skb->dev; - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) - pskb_trim(skb, - skb->len - sizeof(struct rmnet_map_dl_csum_trailer)); - - skb->protocol = htons(ETH_P_MAP); - - cmd = rmnet_map_get_cmd_start(skb); - cmd->cmd_type = type & 0x03; - - netif_tx_lock(dev); - dev->netdev_ops->ndo_start_xmit(skb, dev); - netif_tx_unlock(dev); -} - -/* Process MAP command frame and send N/ACK message as appropriate. Message cmd - * name is decoded here and appropriate handler is called. - */ -static void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port) -{ - struct rmnet_map_control_command *cmd; - unsigned char command_name; - unsigned char rc = 0; - - cmd = rmnet_map_get_cmd_start(skb); - command_name = cmd->command_name; - - switch (command_name) { - case RMNET_MAP_COMMAND_FLOW_ENABLE: - rc = rmnet_map_do_flow_control(skb, port, 1); - break; - - case RMNET_MAP_COMMAND_FLOW_DISABLE: - rc = rmnet_map_do_flow_control(skb, port, 0); - break; - - default: - rc = RMNET_MAP_COMMAND_UNSUPPORTED; - kfree_skb(skb); - break; - } - if (rc == RMNET_MAP_COMMAND_ACK) - rmnet_map_send_ack(skb, rc, port); -} - - -static void rmnet_map_cmd_exit(struct rmnet_port *port) -{ - struct rmnet_map_dl_ind *tmp, *idx; - - list_for_each_entry_safe(tmp, idx, &port->dl_list, list) - list_del_rcu(&tmp->list); -} - -static void rmnet_map_cmd_init(struct rmnet_port *port) -{ - INIT_LIST_HEAD(&port->dl_list); - - port->dl_marker_flush = -1; -} diff --git a/quectel_MHI/src/devices/rmnet/rmnet_map_data.c b/quectel_MHI/src/devices/rmnet/rmnet_map_data.c deleted file mode 100644 index 783412c..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_map_data.c +++ /dev/null @@ -1,682 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Data MAP protocol - * - */ - -#include -#include -#include -#include -#include "rmnet_config.h" -#include "rmnet_map.h" -#include "rmnet_private.h" -#include "rmnet_handlers.h" - -#define RMNET_MAP_PKT_COPY_THRESHOLD 64 -#define RMNET_MAP_DEAGGR_SPACING 64 -#define RMNET_MAP_DEAGGR_HEADROOM (RMNET_MAP_DEAGGR_SPACING / 2) - -struct rmnet_map_coal_metadata { - void *ip_header; - void *trans_header; - u16 ip_len; - u16 trans_len; - u16 data_offset; - u16 data_len; - u8 ip_proto; - u8 trans_proto; - u8 pkt_id; - u8 pkt_count; -}; - -static __sum16 *rmnet_map_get_csum_field(unsigned char protocol, - const void *txporthdr) -{ - __sum16 *check = NULL; - - switch (protocol) { - case IPPROTO_TCP: - check = &(((struct tcphdr *)txporthdr)->check); - break; - - case IPPROTO_UDP: - check = &(((struct udphdr *)txporthdr)->check); - break; - - default: - check = NULL; - break; - } - - return check; -} - -static void rmnet_map_complement_ipv4_txporthdr_csum_field(void *iphdr) -{ - struct iphdr *ip4h = (struct iphdr *)iphdr; - void *txphdr; - u16 *csum; - - txphdr = iphdr + ip4h->ihl * 4; - - if (ip4h->protocol == IPPROTO_TCP || ip4h->protocol == IPPROTO_UDP) { - csum = (u16 *)rmnet_map_get_csum_field(ip4h->protocol, txphdr); - *csum = ~(*csum); - } -} - -static void -rmnet_map_ipv4_ul_csum_header(void *iphdr, - struct rmnet_map_ul_csum_header *ul_header, - struct sk_buff *skb) -{ - struct iphdr *ip4h = (struct iphdr *)iphdr; - __be16 *hdr = (__be16 *)ul_header, offset; - - offset = htons((__force u16)(skb_transport_header(skb) - - (unsigned char *)iphdr)); - ul_header->csum_start_offset = offset; - ul_header->csum_insert_offset = skb->csum_offset; - ul_header->csum_enabled = 1; - if (ip4h->protocol == IPPROTO_UDP) - ul_header->udp_ind = 1; - else - ul_header->udp_ind = 0; - - /* Changing remaining fields to network order */ - hdr++; - *hdr = htons((__force u16)*hdr); - - skb->ip_summed = CHECKSUM_NONE; - - rmnet_map_complement_ipv4_txporthdr_csum_field(iphdr); -} - -#if IS_ENABLED(CONFIG_IPV6) -static void rmnet_map_complement_ipv6_txporthdr_csum_field(void *ip6hdr) -{ - struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr; - void *txphdr; - u16 *csum; - - txphdr = ip6hdr + sizeof(struct ipv6hdr); - - if (ip6h->nexthdr == IPPROTO_TCP || ip6h->nexthdr == IPPROTO_UDP) { - csum = (u16 *)rmnet_map_get_csum_field(ip6h->nexthdr, txphdr); - *csum = ~(*csum); - } -} - -static void -rmnet_map_ipv6_ul_csum_header(void *ip6hdr, - struct rmnet_map_ul_csum_header *ul_header, - struct sk_buff *skb) -{ - struct ipv6hdr *ip6h = (struct ipv6hdr *)ip6hdr; - __be16 *hdr = (__be16 *)ul_header, offset; - - offset = htons((__force u16)(skb_transport_header(skb) - - (unsigned char *)ip6hdr)); - ul_header->csum_start_offset = offset; - ul_header->csum_insert_offset = skb->csum_offset; - ul_header->csum_enabled = 1; - - if (ip6h->nexthdr == IPPROTO_UDP) - ul_header->udp_ind = 1; - else - ul_header->udp_ind = 0; - - /* Changing remaining fields to network order */ - hdr++; - *hdr = htons((__force u16)*hdr); - - skb->ip_summed = CHECKSUM_NONE; - - rmnet_map_complement_ipv6_txporthdr_csum_field(ip6hdr); -} -#endif - -/* Adds MAP header to front of skb->data - * Padding is calculated and set appropriately in MAP header. Mux ID is - * initialized to 0. - */ -static struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb, - int hdrlen, int pad, - struct rmnet_port *port) -{ - struct rmnet_map_header *map_header; - u32 padding, map_datalen; - u8 *padbytes; - - map_datalen = skb->len - hdrlen; - map_header = (struct rmnet_map_header *) - skb_push(skb, sizeof(struct rmnet_map_header)); - memset(map_header, 0, sizeof(struct rmnet_map_header)); - - /* Set next_hdr bit for csum offload packets */ - if (port->data_format & RMNET_FLAGS_EGRESS_MAP_CKSUMV5) - map_header->next_hdr = 1; - - if (pad == RMNET_MAP_NO_PAD_BYTES) { - map_header->pkt_len = htons(map_datalen); - return map_header; - } - - padding = ALIGN(map_datalen, 4) - map_datalen; - - if (padding == 0) - goto done; - - if (skb_tailroom(skb) < padding) - return NULL; - - padbytes = (u8 *)skb_put(skb, padding); - memset(padbytes, 0, padding); - -done: - map_header->pkt_len = htons(map_datalen + padding); - map_header->pad_len = padding & 0x3F; - - return map_header; -} - -/* Deaggregates a single packet - * A whole new buffer is allocated for each portion of an aggregated frame. - * Caller should keep calling deaggregate() on the source skb until 0 is - * returned, indicating that there are no more packets to deaggregate. Caller - * is responsible for freeing the original skb. - */ -static struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb, - struct rmnet_port *port) -{ - struct rmnet_map_header *maph; - struct sk_buff *skbn; - unsigned char *data = rmnet_map_data_ptr(skb), *next_hdr = NULL; - u32 packet_len; - - if (skb->len == 0) - return NULL; - - maph = (struct rmnet_map_header *)data; - packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header); - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) - packet_len += sizeof(struct rmnet_map_dl_csum_trailer); - else if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV5) { - if (!maph->cd_bit) { - packet_len += sizeof(struct rmnet_map_v5_csum_header); - - /* Coalescing headers require MAPv5 */ - next_hdr = data + sizeof(*maph); - } - } - - if (((int)skb->len - (int)packet_len) < 0) - return NULL; - - /* Some hardware can send us empty frames. Catch them */ - if (ntohs(maph->pkt_len) == 0) - return NULL; - - if (next_hdr && - ((struct rmnet_map_v5_coal_header *)next_hdr)->header_type == - RMNET_MAP_HEADER_TYPE_COALESCING) - return skb; - - if (skb_is_nonlinear(skb)) { - skb_frag_t *frag0 = skb_shinfo(skb)->frags; - struct page *page = skb_frag_page(frag0); - - skbn = alloc_skb(RMNET_MAP_DEAGGR_HEADROOM, GFP_ATOMIC); - if (!skbn) - return NULL; - - skb_append_pagefrags(skbn, page, frag0->page_offset, - packet_len); - skbn->data_len += packet_len; - skbn->len += packet_len; - } else { - skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, - GFP_ATOMIC); - if (!skbn) - return NULL; - - skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM); - skb_put(skbn, packet_len); - memcpy(skbn->data, data, packet_len); - } - - pskb_pull(skb, packet_len); - - return skbn; -} - -static void rmnet_map_v4_checksum_uplink_packet(struct sk_buff *skb, - struct net_device *orig_dev) -{ - struct rmnet_priv *priv = netdev_priv(orig_dev); - struct rmnet_map_ul_csum_header *ul_header; - void *iphdr; - - ul_header = (struct rmnet_map_ul_csum_header *) - skb_push(skb, sizeof(struct rmnet_map_ul_csum_header)); - - if (unlikely(!(orig_dev->features & - (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)))) - goto sw_csum; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - iphdr = (char *)ul_header + - sizeof(struct rmnet_map_ul_csum_header); - - if (skb->protocol == htons(ETH_P_IP)) { - rmnet_map_ipv4_ul_csum_header(iphdr, ul_header, skb); - priv->stats.csum_hw++; - return; - } else if (skb->protocol == htons(ETH_P_IPV6)) { -#if IS_ENABLED(CONFIG_IPV6) - rmnet_map_ipv6_ul_csum_header(iphdr, ul_header, skb); - priv->stats.csum_hw++; - return; -#else - priv->stats.csum_err_invalid_ip_version++; - goto sw_csum; -#endif - } else { - priv->stats.csum_err_invalid_ip_version++; - } - } - -sw_csum: - ul_header->csum_start_offset = 0; - ul_header->csum_insert_offset = 0; - ul_header->csum_enabled = 0; - ul_header->udp_ind = 0; - - priv->stats.csum_sw++; -} - -static void rmnet_map_v5_checksum_uplink_packet(struct sk_buff *skb, - struct net_device *orig_dev) -{ - struct rmnet_priv *priv = netdev_priv(orig_dev); - struct rmnet_map_v5_csum_header *ul_header; - - ul_header = (struct rmnet_map_v5_csum_header *) - skb_push(skb, sizeof(*ul_header)); - memset(ul_header, 0, sizeof(*ul_header)); - ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - void *iph = (char *)ul_header + sizeof(*ul_header); - void *trans; - __sum16 *check; - u8 proto; - - if (skb->protocol == htons(ETH_P_IP)) { - u16 ip_len = ((struct iphdr *)iph)->ihl * 4; - - proto = ((struct iphdr *)iph)->protocol; - trans = iph + ip_len; - } else if (skb->protocol == htons(ETH_P_IPV6)) { - u16 ip_len = sizeof(struct ipv6hdr); - - proto = ((struct ipv6hdr *)iph)->nexthdr; - trans = iph + ip_len; - } else { - priv->stats.csum_err_invalid_ip_version++; - goto sw_csum; - } - - check = rmnet_map_get_csum_field(proto, trans); - if (check) { - *check = 0; - skb->ip_summed = CHECKSUM_NONE; - /* Ask for checksum offloading */ - ul_header->csum_valid_required = 1; - priv->stats.csum_hw++; - return; - } - } - -sw_csum: - priv->stats.csum_sw++; -} - - -/* Generates UL checksum meta info header for IPv4 and IPv6 over TCP and UDP - * packets that are supported for UL checksum offload. - */ -void rmnet_map_checksum_uplink_packet(struct sk_buff *skb, - struct net_device *orig_dev, - int csum_type) -{ - switch (csum_type) { - case RMNET_FLAGS_EGRESS_MAP_CKSUMV4: - rmnet_map_v4_checksum_uplink_packet(skb, orig_dev); - break; - case RMNET_FLAGS_EGRESS_MAP_CKSUMV5: - rmnet_map_v5_checksum_uplink_packet(skb, orig_dev); - break; - default: - break; - } -} - -static void rmnet_map_move_headers(struct sk_buff *skb) -{ - struct iphdr *iph; - u16 ip_len; - u16 trans_len = 0; - u8 proto; - - /* This only applies to non-linear SKBs */ - if (!skb_is_nonlinear(skb)) - return; - - iph = (struct iphdr *)rmnet_map_data_ptr(skb); - if (iph->version == 4) { - ip_len = iph->ihl * 4; - proto = iph->protocol; - if (iph->frag_off & htons(IP_OFFSET)) - /* No transport header information */ - goto pull; - } else if (iph->version == 6) { - struct ipv6hdr *ip6h = (struct ipv6hdr *)iph; - __be16 frag_off; - u8 nexthdr = ip6h->nexthdr; - - ip_len = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr, - &frag_off); - if (ip_len < 0) - return; - - proto = nexthdr; - } else { - return; - } - - if (proto == IPPROTO_TCP) { - struct tcphdr *tp = (struct tcphdr *)((u8 *)iph + ip_len); - - trans_len = tp->doff * 4; - } else if (proto == IPPROTO_UDP) { - trans_len = sizeof(struct udphdr); - } else if (proto == NEXTHDR_FRAGMENT) { - /* Non-first fragments don't have the fragment length added by - * ipv6_skip_exthdr() and sho up as proto NEXTHDR_FRAGMENT, so - * we account for the length here. - */ - ip_len += sizeof(struct frag_hdr); - } - -pull: - __pskb_pull_tail(skb, ip_len + trans_len); - skb_reset_network_header(skb); - if (trans_len) - skb_set_transport_header(skb, ip_len); -} - - -/* Process a QMAPv5 packet header */ -static int rmnet_map_process_next_hdr_packet(struct sk_buff *skb, - struct sk_buff_head *list, - u16 len) -{ - struct rmnet_priv *priv = netdev_priv(skb->dev); - int rc = 0; - - switch (rmnet_map_get_next_hdr_type(skb)) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - priv->stats.coal.coal_rx++; - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - if (rmnet_map_get_csum_valid(skb)) { - priv->stats.csum_ok++; - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - priv->stats.csum_valid_unset++; - } - - /* Pull unnecessary headers and move the rest to the linear - * section of the skb. - */ - pskb_pull(skb, - (sizeof(struct rmnet_map_header) + - sizeof(struct rmnet_map_v5_csum_header))); - rmnet_map_move_headers(skb); - - /* Remove padding only for csum offload packets. - * Coalesced packets should never have padding. - */ - pskb_trim(skb, len); - __skb_queue_tail(list, skb); - break; - default: - rc = -EINVAL; - break; - } - - return rc; -} - -long rmnet_agg_time_limit __read_mostly = 1000000L; -long rmnet_agg_bypass_time __read_mostly = 10000000L; - -static int rmnet_map_tx_agg_skip(struct sk_buff *skb, int offset) -{ - u8 *packet_start = skb->data + offset; - int is_icmp = 0; - - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *ip4h = (struct iphdr *)(packet_start); - - if (ip4h->protocol == IPPROTO_ICMP) - is_icmp = 1; - } else if (skb->protocol == htons(ETH_P_IPV6)) { - struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start); - - if (ip6h->nexthdr == IPPROTO_ICMPV6) { - is_icmp = 1; - } else if (ip6h->nexthdr == NEXTHDR_FRAGMENT) { - struct frag_hdr *frag; - - frag = (struct frag_hdr *)(packet_start - + sizeof(struct ipv6hdr)); - if (frag->nexthdr == IPPROTO_ICMPV6) - is_icmp = 1; - } - } - - return is_icmp; -} - -static void rmnet_map_flush_tx_packet_work(struct work_struct *work) -{ - struct sk_buff *skb = NULL; - struct rmnet_port *port; - unsigned long flags; - - port = container_of(work, struct rmnet_port, agg_wq); - - spin_lock_irqsave(&port->agg_lock, flags); - if (likely(port->agg_state == -EINPROGRESS)) { - /* Buffer may have already been shipped out */ - if (likely(port->agg_skb)) { - skb = port->agg_skb; - port->agg_skb = NULL; - port->agg_count = 0; - memset(&port->agg_time, 0, sizeof(struct timespec)); - } - port->agg_state = 0; - } - - spin_unlock_irqrestore(&port->agg_lock, flags); - if (skb) - dev_queue_xmit(skb); -} - -static enum hrtimer_restart rmnet_map_flush_tx_packet_queue(struct hrtimer *t) -{ - struct rmnet_port *port; - - port = container_of(t, struct rmnet_port, hrtimer); - - schedule_work(&port->agg_wq); - return HRTIMER_NORESTART; -} - -static void rmnet_map_linearize_copy(struct sk_buff *dst, struct sk_buff *src) -{ - unsigned int linear = src->len - src->data_len, target = src->len; - unsigned char *src_buf; - struct sk_buff *skb; - - src_buf = src->data; - skb_put_data(dst, src_buf, linear); - target -= linear; - - skb = src; - - while (target) { - unsigned int i = 0, non_linear = 0; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - non_linear = skb_frag_size(&skb_shinfo(skb)->frags[i]); - src_buf = skb_frag_address(&skb_shinfo(skb)->frags[i]); - - skb_put_data(dst, src_buf, non_linear); - target -= non_linear; - } - - if (skb_shinfo(skb)->frag_list) { - skb = skb_shinfo(skb)->frag_list; - continue; - } - - if (skb->next) - skb = skb->next; - } -} - -static void rmnet_map_tx_aggregate(struct sk_buff *skb, struct rmnet_port *port) -{ - struct timespec diff, last; - int size, agg_count = 0; - struct sk_buff *agg_skb; - unsigned long flags; - -new_packet: - spin_lock_irqsave(&port->agg_lock, flags); - memcpy(&last, &port->agg_last, sizeof(struct timespec)); - getnstimeofday(&port->agg_last); - - if (!port->agg_skb) { - /* Check to see if we should agg first. If the traffic is very - * sparse, don't aggregate. We will need to tune this later - */ - diff = timespec_sub(port->agg_last, last); - size = port->egress_agg_params.agg_size - skb->len; - - if (diff.tv_sec > 0 || diff.tv_nsec > rmnet_agg_bypass_time || - size <= 0) { - spin_unlock_irqrestore(&port->agg_lock, flags); - skb->protocol = htons(ETH_P_MAP); - dev_queue_xmit(skb); - return; - } - - port->agg_skb = alloc_skb(port->egress_agg_params.agg_size, - GFP_ATOMIC); - if (!port->agg_skb) { - port->agg_skb = 0; - port->agg_count = 0; - memset(&port->agg_time, 0, sizeof(struct timespec)); - spin_unlock_irqrestore(&port->agg_lock, flags); - skb->protocol = htons(ETH_P_MAP); - dev_queue_xmit(skb); - return; - } - rmnet_map_linearize_copy(port->agg_skb, skb); - port->agg_skb->dev = skb->dev; - port->agg_skb->protocol = htons(ETH_P_MAP); - port->agg_count = 1; - getnstimeofday(&port->agg_time); - dev_kfree_skb_any(skb); - goto schedule; - } - diff = timespec_sub(port->agg_last, port->agg_time); - size = port->egress_agg_params.agg_size - port->agg_skb->len; - - if (skb->len > size || - port->agg_count >= port->egress_agg_params.agg_count || - diff.tv_sec > 0 || diff.tv_nsec > rmnet_agg_time_limit) { - agg_skb = port->agg_skb; - agg_count = port->agg_count; - port->agg_skb = 0; - port->agg_count = 0; - memset(&port->agg_time, 0, sizeof(struct timespec)); - port->agg_state = 0; - spin_unlock_irqrestore(&port->agg_lock, flags); - hrtimer_cancel(&port->hrtimer); - dev_queue_xmit(agg_skb); - goto new_packet; - } - - rmnet_map_linearize_copy(port->agg_skb, skb); - port->agg_count++; - dev_kfree_skb_any(skb); - -schedule: - if (port->agg_state != -EINPROGRESS) { - port->agg_state = -EINPROGRESS; - hrtimer_start(&port->hrtimer, - ns_to_ktime(port->egress_agg_params.agg_time), - HRTIMER_MODE_REL); - } - spin_unlock_irqrestore(&port->agg_lock, flags); -} - -static void rmnet_map_tx_aggregate_init(struct rmnet_port *port) -{ - hrtimer_init(&port->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - port->hrtimer.function = rmnet_map_flush_tx_packet_queue; - port->egress_agg_params.agg_size = 8192; - port->egress_agg_params.agg_count = 20; - port->egress_agg_params.agg_time = 3000000; - spin_lock_init(&port->agg_lock); - - INIT_WORK(&port->agg_wq, rmnet_map_flush_tx_packet_work); -} - -static void rmnet_map_tx_aggregate_exit(struct rmnet_port *port) -{ - unsigned long flags; - - hrtimer_cancel(&port->hrtimer); - cancel_work_sync(&port->agg_wq); - - spin_lock_irqsave(&port->agg_lock, flags); - if (port->agg_state == -EINPROGRESS) { - if (port->agg_skb) { - kfree_skb(port->agg_skb); - port->agg_skb = NULL; - port->agg_count = 0; - memset(&port->agg_time, 0, sizeof(struct timespec)); - } - - port->agg_state = 0; - } - - spin_unlock_irqrestore(&port->agg_lock, flags); -} diff --git a/quectel_MHI/src/devices/rmnet/rmnet_private.h b/quectel_MHI/src/devices/rmnet/rmnet_private.h deleted file mode 100644 index d384b7b..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_private.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _RMNET_PRIVATE_H_ -#define _RMNET_PRIVATE_H_ - -#define RMNET_MAX_PACKET_SIZE 16384 -#define RMNET_DFLT_PACKET_SIZE 1500 -#define RMNET_NEEDED_HEADROOM 16 -#define RMNET_TX_QUEUE_LEN 1000 - -/* Constants */ -#define RMNET_EGRESS_FORMAT_AGGREGATION BIT(31) -#define RMNET_INGRESS_FORMAT_DL_MARKER_V1 BIT(30) -#define RMNET_INGRESS_FORMAT_DL_MARKER_V2 BIT(29) - -#define RMNET_INGRESS_FORMAT_DL_MARKER (RMNET_INGRESS_FORMAT_DL_MARKER_V1 |\ -RMNET_INGRESS_FORMAT_DL_MARKER_V2) - -/* Replace skb->dev to a virtual rmnet device and pass up the stack */ -#define RMNET_EPMODE_VND (1) -/* Pass the frame directly to another device with dev_queue_xmit() */ -#define RMNET_EPMODE_BRIDGE (2) - -#endif /* _RMNET_PRIVATE_H_ */ diff --git a/quectel_MHI/src/devices/rmnet/rmnet_trace.h b/quectel_MHI/src/devices/rmnet/rmnet_trace.h deleted file mode 100644 index d453fc5..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_trace.h +++ /dev/null @@ -1,257 +0,0 @@ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM rmnet -#define TRACE_INCLUDE_FILE rmnet_trace - -#if !defined(_RMNET_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) -#define _RMNET_TRACE_H_ - -#include -#include -#include - -/*****************************************************************************/ -/* Trace events for rmnet module */ -/*****************************************************************************/ -DECLARE_EVENT_CLASS - (rmnet_mod_template, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2), - - TP_STRUCT__entry( - __field(u8, func) - __field(u8, evt) - __field(u32, uint1) - __field(u32, uint2) - __field(u64, ulong1) - __field(u64, ulong2) - __field(void *, ptr1) - __field(void *, ptr2) - ), - - TP_fast_assign( - __entry->func = func; - __entry->evt = evt; - __entry->uint1 = uint1; - __entry->uint2 = uint2; - __entry->ulong1 = ulong1; - __entry->ulong2 = ulong2; - __entry->ptr1 = ptr1; - __entry->ptr2 = ptr2; - ), - -TP_printk("fun:%u ev:%u u1:%u u2:%u ul1:%llu ul2:%llu p1:0x%pK p2:0x%pK", - __entry->func, __entry->evt, - __entry->uint1, __entry->uint2, - __entry->ulong1, __entry->ulong2, - __entry->ptr1, __entry->ptr2) -) - -DEFINE_EVENT - (rmnet_mod_template, rmnet_low, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_high, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_err, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -/*****************************************************************************/ -/* Trace events for rmnet_perf module */ -/*****************************************************************************/ -DEFINE_EVENT - (rmnet_mod_template, rmnet_perf_low, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_perf_high, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_perf_err, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -/*****************************************************************************/ -/* Trace events for rmnet_shs module */ -/*****************************************************************************/ -DEFINE_EVENT - (rmnet_mod_template, rmnet_shs_low, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_shs_high, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_shs_err, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_shs_wq_low, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_shs_wq_high, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DEFINE_EVENT - (rmnet_mod_template, rmnet_shs_wq_err, - - TP_PROTO(u8 func, u8 evt, u32 uint1, u32 uint2, - u64 ulong1, u64 ulong2, void *ptr1, void *ptr2), - - TP_ARGS(func, evt, uint1, uint2, ulong1, ulong2, ptr1, ptr2) - -); - -DECLARE_EVENT_CLASS - (rmnet_freq_template, - - TP_PROTO(u8 core, u32 newfreq), - - TP_ARGS(core, newfreq), - - TP_STRUCT__entry( - __field(u8, core) - __field(u32, newfreq) - ), - - TP_fast_assign( - __entry->core = core; - __entry->newfreq = newfreq; - - ), - -TP_printk("freq policy core:%u freq floor :%u", - __entry->core, __entry->newfreq) - -); - -DEFINE_EVENT - (rmnet_freq_template, rmnet_freq_boost, - - TP_PROTO(u8 core, u32 newfreq), - - TP_ARGS(core, newfreq) -); - -DEFINE_EVENT - (rmnet_freq_template, rmnet_freq_reset, - - TP_PROTO(u8 core, u32 newfreq), - - TP_ARGS(core, newfreq) -); - -TRACE_EVENT - (rmnet_freq_update, - - TP_PROTO(u8 core, u32 lowfreq, u32 highfreq), - - TP_ARGS(core, lowfreq, highfreq), - - TP_STRUCT__entry( - __field(u8, core) - __field(u32, lowfreq) - __field(u32, highfreq) - ), - - TP_fast_assign( - __entry->core = core; - __entry->lowfreq = lowfreq; - __entry->highfreq = highfreq; - - ), - -TP_printk("freq policy update core:%u policy freq floor :%u freq ceil :%u", - __entry->core, __entry->lowfreq, __entry->highfreq) -); -#endif /* _RMNET_TRACE_H_ */ - -/* This part must be outside protection */ -#undef TRACE_INCLUDE_PATH -#define TRACE_INCLUDE_PATH ../drivers/net/ethernet/qualcomm/rmnet -#include diff --git a/quectel_MHI/src/devices/rmnet/rmnet_vnd.c b/quectel_MHI/src/devices/rmnet/rmnet_vnd.c deleted file mode 100644 index 4ef645d..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_vnd.c +++ /dev/null @@ -1,382 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * - * RMNET Data virtual network driver - * - */ - -#include -#include -#include -#include -#include "rmnet_config.h" -#include "rmnet_handlers.h" -#include "rmnet_private.h" -#include "rmnet_map.h" -#include "rmnet_vnd.h" - -/* RX/TX Fixup */ - -static void rmnet_vnd_rx_fixup(struct net_device *dev, u32 skb_len) -{ - struct rmnet_priv *priv = netdev_priv(dev); - struct rmnet_pcpu_stats *pcpu_ptr; - - pcpu_ptr = this_cpu_ptr(priv->pcpu_stats); - - u64_stats_update_begin(&pcpu_ptr->syncp); - pcpu_ptr->stats.rx_pkts++; - pcpu_ptr->stats.rx_bytes += skb_len; - u64_stats_update_end(&pcpu_ptr->syncp); -} - -static void rmnet_vnd_tx_fixup(struct net_device *dev, u32 skb_len) -{ - struct rmnet_priv *priv = netdev_priv(dev); - struct rmnet_pcpu_stats *pcpu_ptr; - - pcpu_ptr = this_cpu_ptr(priv->pcpu_stats); - - u64_stats_update_begin(&pcpu_ptr->syncp); - pcpu_ptr->stats.tx_pkts++; - pcpu_ptr->stats.tx_bytes += skb_len; - u64_stats_update_end(&pcpu_ptr->syncp); -} - -/* Network Device Operations */ - -static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rmnet_priv *priv; - - priv = netdev_priv(dev); - if (priv->real_dev) { - rmnet_egress_handler(skb); - } else { - this_cpu_inc(priv->pcpu_stats->stats.tx_drops); - kfree_skb(skb); - } - return NETDEV_TX_OK; -} - -static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu) -{ - if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE) - return -EINVAL; - - rmnet_dev->mtu = new_mtu; - return 0; -} - -static int rmnet_vnd_get_iflink(const struct net_device *dev) -{ - struct rmnet_priv *priv = netdev_priv(dev); - - return priv->real_dev->ifindex; -} - -static int rmnet_vnd_init(struct net_device *dev) -{ - struct rmnet_priv *priv = netdev_priv(dev); - int err; - - priv->pcpu_stats = alloc_percpu(struct rmnet_pcpu_stats); - if (!priv->pcpu_stats) - return -ENOMEM; - - err = gro_cells_init(&priv->gro_cells, dev); - if (err) { - free_percpu(priv->pcpu_stats); - return err; - } - - return 0; -} - -static void rmnet_vnd_uninit(struct net_device *dev) -{ - struct rmnet_priv *priv = netdev_priv(dev); - - gro_cells_destroy(&priv->gro_cells); - free_percpu(priv->pcpu_stats); -} - -static struct rtnl_link_stats64* rmnet_get_stats64(struct net_device *dev, - struct rtnl_link_stats64 *s) -{ - struct rmnet_priv *priv = netdev_priv(dev); - struct rmnet_vnd_stats total_stats; - struct rmnet_pcpu_stats *pcpu_ptr; - unsigned int cpu, start; - - memset(&total_stats, 0, sizeof(struct rmnet_vnd_stats)); - - for_each_possible_cpu(cpu) { - pcpu_ptr = per_cpu_ptr(priv->pcpu_stats, cpu); - - do { - start = u64_stats_fetch_begin_irq(&pcpu_ptr->syncp); - total_stats.rx_pkts += pcpu_ptr->stats.rx_pkts; - total_stats.rx_bytes += pcpu_ptr->stats.rx_bytes; - total_stats.tx_pkts += pcpu_ptr->stats.tx_pkts; - total_stats.tx_bytes += pcpu_ptr->stats.tx_bytes; - } while (u64_stats_fetch_retry_irq(&pcpu_ptr->syncp, start)); - - total_stats.tx_drops += pcpu_ptr->stats.tx_drops; - } - - s->rx_packets = total_stats.rx_pkts; - s->rx_bytes = total_stats.rx_bytes; - s->tx_packets = total_stats.tx_pkts; - s->tx_bytes = total_stats.tx_bytes; - s->tx_dropped = total_stats.tx_drops; - - return s; -} - -static const struct net_device_ops rmnet_vnd_ops = { - .ndo_start_xmit = rmnet_vnd_start_xmit, - .ndo_change_mtu = rmnet_vnd_change_mtu, - .ndo_get_iflink = rmnet_vnd_get_iflink, - //.ndo_add_slave = rmnet_add_bridge, - //.ndo_del_slave = rmnet_del_bridge, - .ndo_init = rmnet_vnd_init, - .ndo_uninit = rmnet_vnd_uninit, - .ndo_get_stats64 = rmnet_get_stats64, -}; - -static const char rmnet_gstrings_stats[][ETH_GSTRING_LEN] = { - "Checksum ok", - "Checksum valid bit not set", - "Checksum validation failed", - "Checksum error bad buffer", - "Checksum error bad ip version", - "Checksum error bad transport", - "Checksum skipped on ip fragment", - "Checksum skipped", - "Checksum computed in software", - "Checksum computed in hardware", - "Coalescing packets received", - "Coalesced packets", - "Coalescing header NLO errors", - "Coalescing header pcount errors", - "Coalescing checksum errors", - "Coalescing packet reconstructs", - "Coalescing IP version invalid", - "Coalescing L4 header invalid", - "Coalescing close Non-coalescable", - "Coalescing close L3 mismatch", - "Coalescing close L4 mismatch", - "Coalescing close HW NLO limit", - "Coalescing close HW packet limit", - "Coalescing close HW byte limit", - "Coalescing close HW time limit", - "Coalescing close HW eviction", - "Coalescing close Coalescable", - "Coalescing packets over VEID0", - "Coalescing packets over VEID1", - "Coalescing packets over VEID2", - "Coalescing packets over VEID3", -}; - -static const char rmnet_port_gstrings_stats[][ETH_GSTRING_LEN] = { - "MAP Cmd last version", - "MAP Cmd last ep id", - "MAP Cmd last transaction id", - "DL header last seen sequence", - "DL header last seen bytes", - "DL header last seen packets", - "DL header last seen flows", - "DL header pkts received", - "DL header total bytes received", - "DL header total pkts received", - "DL trailer last seen sequence", - "DL trailer pkts received", -}; - -static void rmnet_get_strings(struct net_device *dev, u32 stringset, u8 *buf) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(buf, &rmnet_gstrings_stats, - sizeof(rmnet_gstrings_stats)); - memcpy(buf + sizeof(rmnet_gstrings_stats), - &rmnet_port_gstrings_stats, - sizeof(rmnet_port_gstrings_stats)); - break; - } -} - -static int rmnet_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rmnet_gstrings_stats) + - ARRAY_SIZE(rmnet_port_gstrings_stats); - default: - return -EOPNOTSUPP; - } -} - -static void rmnet_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rmnet_priv *priv = netdev_priv(dev); - struct rmnet_priv_stats *st = &priv->stats; - struct rmnet_port_priv_stats *stp; - struct rmnet_port *port; - - port = rmnet_get_port(priv->real_dev); - - if (!data || !port) - return; - - stp = &port->stats; - - memcpy(data, st, ARRAY_SIZE(rmnet_gstrings_stats) * sizeof(u64)); - memcpy(data + ARRAY_SIZE(rmnet_gstrings_stats), stp, - ARRAY_SIZE(rmnet_port_gstrings_stats) * sizeof(u64)); -} - -static int rmnet_stats_reset(struct net_device *dev) -{ - struct rmnet_priv *priv = netdev_priv(dev); - struct rmnet_port_priv_stats *stp; - struct rmnet_port *port; - - port = rmnet_get_port(priv->real_dev); - if (!port) - return -EINVAL; - - stp = &port->stats; - - memset(stp, 0, sizeof(*stp)); - return 0; -} - -static const struct ethtool_ops rmnet_ethtool_ops = { - .get_ethtool_stats = rmnet_get_ethtool_stats, - .get_strings = rmnet_get_strings, - .get_sset_count = rmnet_get_sset_count, - .nway_reset = rmnet_stats_reset, -}; - -/* Called by kernel whenever a new rmnet device is created. Sets MTU, - * flags, ARP type, needed headroom, etc... - */ -void rmnet_vnd_setup(struct net_device *rmnet_dev) -{ - rmnet_dev->netdev_ops = &rmnet_vnd_ops; - rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE; - rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM; - random_ether_addr(rmnet_dev->dev_addr); - rmnet_dev->tx_queue_len = RMNET_TX_QUEUE_LEN; - - /* Raw IP mode */ - rmnet_dev->header_ops = NULL; /* No header */ - rmnet_dev->type = ARPHRD_RAWIP; - rmnet_dev->hard_header_len = 0; - rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - - //rmnet_dev->needs_free_netdev = true; - - rmnet_dev->hw_features = NETIF_F_RXCSUM; - rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - //rmnet_dev->hw_features |= NETIF_F_SG; - //rmnet_dev->hw_features |= NETIF_F_GRO_HW; -} - -/* Exposed API */ - -static int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev, - struct rmnet_port *port, - struct net_device *real_dev, - struct rmnet_endpoint *ep) -{ - struct rmnet_priv *priv = netdev_priv(rmnet_dev); - struct rmnet_nss_cb *nss_cb; - int rc; - - if (ep->egress_dev) - return -EINVAL; - - if (rmnet_get_endpoint(port, id)) - return -EBUSY; - - rmnet_dev->hw_features = NETIF_F_RXCSUM; - rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - rmnet_dev->hw_features |= NETIF_F_SG; - - priv->real_dev = real_dev; - - rc = register_netdevice(rmnet_dev); - if (!rc) { - ep->egress_dev = rmnet_dev; - ep->mux_id = id; - port->nr_rmnet_devs++; - - //rmnet_dev->rtnl_link_ops = &rmnet_link_ops; - - priv->mux_id = id; - - netdev_dbg(rmnet_dev, "rmnet dev created\n"); - } - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { - rc = nss_cb->nss_create(rmnet_dev); - if (rc) { - /* Log, but don't fail the device creation */ - netdev_err(rmnet_dev, "Device will not use NSS path: %d\n", rc); - rc = 0; - } else { - netdev_dbg(rmnet_dev, "NSS context created\n"); - } - } - - return rc; -} - -static int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, - struct rmnet_endpoint *ep) -{ - struct rmnet_nss_cb *nss_cb; - - if (id >= RMNET_MAX_LOGICAL_EP || !ep->egress_dev) - return -EINVAL; - - if (ep->egress_dev) { - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) - nss_cb->nss_free(ep->egress_dev); - } - ep->egress_dev = NULL; - port->nr_rmnet_devs--; - - return 0; -} - -static int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable) -{ - netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable); - /* Although we expect similar number of enable/disable - * commands, optimize for the disable. That is more - * latency sensitive than enable - */ - if (unlikely(enable)) - netif_wake_queue(rmnet_dev); - else - netif_stop_queue(rmnet_dev); - - return 0; -} diff --git a/quectel_MHI/src/devices/rmnet/rmnet_vnd.h b/quectel_MHI/src/devices/rmnet/rmnet_vnd.h deleted file mode 100644 index f8a65a9..0000000 --- a/quectel_MHI/src/devices/rmnet/rmnet_vnd.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * RMNET Data Virtual Network Device APIs - * - */ - -#ifndef _RMNET_VND_H_ -#define _RMNET_VND_H_ - -static int rmnet_vnd_do_flow_control(struct net_device *dev, int enable); -static int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev, - struct rmnet_port *port, - struct net_device *real_dev, - struct rmnet_endpoint *ep); -static int rmnet_vnd_dellink(u8 id, struct rmnet_port *port, - struct rmnet_endpoint *ep); -static void rmnet_vnd_rx_fixup(struct net_device *dev, u32 skb_len); -static void rmnet_vnd_tx_fixup(struct net_device *dev, u32 skb_len); -static void rmnet_vnd_setup(struct net_device *dev); -#endif /* _RMNET_VND_H_ */ diff --git a/quectel_MHI/src/devices/rmnet_handler.c b/quectel_MHI/src/devices/rmnet_handler.c deleted file mode 100644 index b100262..0000000 --- a/quectel_MHI/src/devices/rmnet_handler.c +++ /dev/null @@ -1,1129 +0,0 @@ -#if 0 - -#define RMNET_MAX_PACKET_SIZE 16384 -#define RMNET_DFLT_PACKET_SIZE 1500 -#define RMNET_NEEDED_HEADROOM 16 -#define RMNET_TX_QUEUE_LEN 1000 - -#define RMNET_MAX_LOGICAL_EP 255 -#define RMNET_MAP_DESC_HEADROOM 128 -#define RMNET_FRAG_DESCRIPTOR_POOL_SIZE 64 - -/* Pass the frame up the stack with no modifications to skb->dev */ -#define RMNET_EPMODE_NONE (0) -/* Replace skb->dev to a virtual rmnet device and pass up the stack */ -#define RMNET_EPMODE_VND (1) -/* Pass the frame directly to another device with dev_queue_xmit() */ -#define RMNET_EPMODE_BRIDGE (2) - -/* rmnet section */ - -#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) -#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) -#define RMNET_FLAGS_INGRESS_COALESCE (1U << 4) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5 (1U << 5) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5 (1U << 6) - -enum rmnet_map_v5_header_type { - RMNET_MAP_HEADER_TYPE_UNKNOWN, - RMNET_MAP_HEADER_TYPE_COALESCING = 0x1, - RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2, - RMNET_MAP_HEADER_TYPE_ENUM_LENGTH -}; - -/* Main QMAP header */ -struct rmnet_map_header { - u8 pad_len:6; - u8 next_hdr:1; - u8 cd_bit:1; - u8 mux_id; - __be16 pkt_len; -} __aligned(1); - -/* QMAP v5 headers */ -struct rmnet_map_v5_csum_header { - u8 next_hdr:1; - u8 header_type:7; - u8 hw_reserved:7; - u8 csum_valid_required:1; - __be16 reserved; -} __aligned(1); - -struct rmnet_map_v5_nl_pair { - __be16 pkt_len; - u8 csum_error_bitmap; - u8 num_packets; -} __aligned(1); - -/* NLO: Number-length object */ -#define RMNET_MAP_V5_MAX_NLOS (6) -#define RMNET_MAP_V5_MAX_PACKETS (48) - -struct rmnet_map_v5_coal_header { - u8 next_hdr:1; - u8 header_type:7; - u8 reserved1:4; - u8 num_nlos:3; - u8 csum_valid:1; - u8 close_type:4; - u8 close_value:4; - u8 reserved2:4; - u8 virtual_channel_id:4; - - struct rmnet_map_v5_nl_pair nl_pairs[RMNET_MAP_V5_MAX_NLOS]; -} __aligned(1); - -/* QMAP v4 headers */ -struct rmnet_map_dl_csum_trailer { - u8 reserved1; - u8 valid:1; - u8 reserved2:7; - u16 csum_start_offset; - u16 csum_length; - __be16 csum_value; -} __aligned(1); - -struct rmnet_frag_descriptor_pool { - struct list_head free_list; - u32 pool_size; -}; - -struct rmnet_frag_descriptor { - struct list_head list; - struct list_head sub_frags; - skb_frag_t frag; - u8 *hdr_ptr; - struct net_device *dev; - u32 hash; - __be32 tcp_seq; - __be16 ip_id; - u16 data_offset; - u16 gso_size; - u16 gso_segs; - u16 ip_len; - u16 trans_len; - u8 ip_proto; - u8 trans_proto; - u8 pkt_id; - u8 csum_valid:1, - hdrs_valid:1, - ip_id_set:1, - tcp_seq_set:1, - flush_shs:1, - reserved:3; -}; - -struct rmnet_endpoint { - u8 rmnet_mode; - u8 mux_id; - struct net_device *rmnet_dev; -}; - -/* One instance of this structure is instantiated for each real_dev associated - * with rmnet. - */ -struct rmnet_port { - struct net_device *dev; - u8 rmnet_mode; - u32 data_format; - u32 nr_rmnet_devs; - struct rmnet_endpoint muxed_ep[16]; - - /* Descriptor pool */ - spinlock_t desc_pool_lock; - struct rmnet_frag_descriptor_pool *frag_desc_pool; - struct sk_buff *chain_head; - struct sk_buff *chain_tail; -}; - -static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) -{ - struct rmnet_map_header *map_header; - struct rmnet_map_v5_csum_header *ul_header; - u32 padding, map_datalen; - - map_datalen = skb->len; - padding = map_datalen%4; - if (padding) { - padding = 4 - padding; - if (skb_tailroom(skb) < padding) { - printk("skb_tailroom small!\n"); - padding = 0; - } - if (padding) - __skb_put(skb, padding); - } - - map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); - - BUILD_BUG_ON((sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header)) != 8); - - map_header->cd_bit = 0; - map_header->next_hdr = 1; - map_header->pad_len = padding; - map_header->mux_id = mux_id; - map_header->pkt_len = htons(map_datalen + padding); - - ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); - memset(ul_header, 0, sizeof(*ul_header)); - ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD; - - return skb; -} - -struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id) -{ - return &port->muxed_ep[0]; -} - -static void -rmnet_deliver_skb(struct sk_buff *skb, struct rmnet_port *port) -{ - struct rmnet_nss_cb *nss_cb; - - //rmnet_vnd_rx_fixup(skb->dev, skb->len); - - /* Pass off the packet to NSS driver if we can */ - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) { - if (!port->chain_head) - port->chain_head = skb; - else - skb_shinfo(port->chain_tail)->frag_list = skb; - - port->chain_tail = skb; - return; - } - - skb_reset_transport_header(skb); - skb_reset_network_header(skb); - - skb->pkt_type = PACKET_HOST; - skb_set_mac_header(skb, 0); - - //if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) { - //} else { - //if (!rmnet_check_skb_can_gro(skb)) - // gro_cells_receive(&priv->gro_cells, skb); - //else - netif_receive_skb(skb); - //} -} - -static inline unsigned char *rmnet_map_data_ptr(struct sk_buff *skb) -{ - /* Nonlinear packets we receive are entirely within frag 0 */ - if (skb_is_nonlinear(skb) && skb->len == skb->data_len) - return skb_frag_address(skb_shinfo(skb)->frags); - - return skb->data; -} - -static inline void *rmnet_frag_data_ptr(struct rmnet_frag_descriptor *frag_desc) -{ - return skb_frag_address(&frag_desc->frag); -} - -static struct rmnet_frag_descriptor * -rmnet_get_frag_descriptor(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool; - struct rmnet_frag_descriptor *frag_desc; - - spin_lock(&port->desc_pool_lock); - if (!list_empty(&pool->free_list)) { - frag_desc = list_first_entry(&pool->free_list, - struct rmnet_frag_descriptor, - list); - list_del_init(&frag_desc->list); - } else { - frag_desc = kzalloc(sizeof(*frag_desc), GFP_ATOMIC); - if (!frag_desc) - goto out; - - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - pool->pool_size++; - } - -out: - spin_unlock(&port->desc_pool_lock); - return frag_desc; -} - -static void rmnet_recycle_frag_descriptor(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool = port->frag_desc_pool; - struct page *page = skb_frag_page(&frag_desc->frag); - - list_del(&frag_desc->list); - if (page) - put_page(page); - - memset(frag_desc, 0, sizeof(*frag_desc)); - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - spin_lock(&port->desc_pool_lock); - list_add_tail(&frag_desc->list, &pool->free_list); - spin_unlock(&port->desc_pool_lock); -} - -static inline void rmnet_frag_fill(struct rmnet_frag_descriptor *frag_desc, - struct page *p, u32 page_offset, u32 len) -{ - get_page(p); - __skb_frag_set_page(&frag_desc->frag, p); - skb_frag_size_set(&frag_desc->frag, len); - frag_desc->frag.page_offset = page_offset; -} - -static inline void *rmnet_frag_pull(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - unsigned int size) -{ - if (size >= skb_frag_size(&frag_desc->frag)) { - pr_info("%s(): Pulling %u bytes from %u byte pkt. Dropping\n", - __func__, size, skb_frag_size(&frag_desc->frag)); - rmnet_recycle_frag_descriptor(frag_desc, port); - return NULL; - } - - frag_desc->frag.page_offset += size; - skb_frag_size_sub(&frag_desc->frag, size); - - return rmnet_frag_data_ptr(frag_desc); -} - -static inline void *rmnet_frag_trim(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - unsigned int size) -{ - if (!size) { - pr_info("%s(): Trimming %u byte pkt to 0. Dropping\n", - __func__, skb_frag_size(&frag_desc->frag)); - rmnet_recycle_frag_descriptor(frag_desc, port); - return NULL; - } - - if (size < skb_frag_size(&frag_desc->frag)) - skb_frag_size_set(&frag_desc->frag, size); - - return rmnet_frag_data_ptr(frag_desc); -} - -static inline u8 -rmnet_frag_get_next_hdr_type(struct rmnet_frag_descriptor *frag_desc) -{ - unsigned char *data = rmnet_frag_data_ptr(frag_desc); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_coal_header *)data)->header_type; -} - -static inline bool -rmnet_frag_get_csum_valid(struct rmnet_frag_descriptor *frag_desc) -{ - unsigned char *data = rmnet_frag_data_ptr(frag_desc); - - data += sizeof(struct rmnet_map_header); - return ((struct rmnet_map_v5_csum_header *)data)->csum_valid_required; -} - -static void rmnet_descriptor_add_frag(struct rmnet_port *port, struct list_head *list, - struct page *p, u32 page_offset, u32 len) -{ - struct rmnet_frag_descriptor *frag_desc; - - frag_desc = rmnet_get_frag_descriptor(port); - if (!frag_desc) - return; - - rmnet_frag_fill(frag_desc, p, page_offset, len); - list_add_tail(&frag_desc->list, list); -} - -static void rmnet_frag_deaggregate(skb_frag_t *frag, struct rmnet_port *port, - struct list_head *list) -{ - struct rmnet_map_header *maph; - u8 *data = skb_frag_address(frag); - u32 offset = 0; - u32 packet_len; - - while (offset < skb_frag_size(frag)) { - maph = (struct rmnet_map_header *)data; - packet_len = ntohs(maph->pkt_len); - - /* Some hardware can send us empty frames. Catch them */ - if (packet_len == 0) - return; - - packet_len += sizeof(*maph); - - if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4) { - packet_len += sizeof(struct rmnet_map_dl_csum_trailer); - WARN_ON(1); - } else if (port->data_format & - (RMNET_FLAGS_INGRESS_MAP_CKSUMV5 | - RMNET_FLAGS_INGRESS_COALESCE) && !maph->cd_bit) { - u32 hsize = 0; - u8 type; - - type = ((struct rmnet_map_v5_coal_header *) - (data + sizeof(*maph)))->header_type; - switch (type) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - hsize = sizeof(struct rmnet_map_v5_coal_header); - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - hsize = sizeof(struct rmnet_map_v5_csum_header); - break; - } - - packet_len += hsize; - } - else { - qmap_hex_dump(__func__, data, 64); - WARN_ON(1); - } - - if ((int)skb_frag_size(frag) - (int)packet_len < 0) - return; - - rmnet_descriptor_add_frag(port, list, skb_frag_page(frag), - frag->page_offset + offset, - packet_len); - - offset += packet_len; - data += packet_len; - } -} - - -#define RMNET_IP_VERSION_4 0x40 -#define RMNET_IP_VERSION_6 0x60 - -/* Helper Functions */ - -static void rmnet_set_skb_proto(struct sk_buff *skb) -{ - switch (rmnet_map_data_ptr(skb)[0] & 0xF0) { - case RMNET_IP_VERSION_4: - skb->protocol = htons(ETH_P_IP); - break; - case RMNET_IP_VERSION_6: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - skb->protocol = htons(ETH_P_MAP); - WARN_ON(1); - break; - } -} - -/* Allocate and populate an skb to contain the packet represented by the - * frag descriptor. - */ -static struct sk_buff *rmnet_alloc_skb(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct sk_buff *head_skb, *current_skb, *skb; - struct skb_shared_info *shinfo; - struct rmnet_frag_descriptor *sub_frag, *tmp; - - /* Use the exact sizes if we know them (i.e. RSB/RSC, rmnet_perf) */ - if (frag_desc->hdrs_valid) { - u16 hdr_len = frag_desc->ip_len + frag_desc->trans_len; - - head_skb = alloc_skb(hdr_len + RMNET_MAP_DESC_HEADROOM, - GFP_ATOMIC); - if (!head_skb) - return NULL; - - skb_reserve(head_skb, RMNET_MAP_DESC_HEADROOM); - skb_put_data(head_skb, frag_desc->hdr_ptr, hdr_len); - skb_reset_network_header(head_skb); - - if (frag_desc->trans_len) - skb_set_transport_header(head_skb, frag_desc->ip_len); - - /* Packets that have no data portion don't need any frags */ - if (hdr_len == skb_frag_size(&frag_desc->frag)) - goto skip_frags; - - /* If the headers we added are the start of the page, - * we don't want to add them twice - */ - if (frag_desc->hdr_ptr == rmnet_frag_data_ptr(frag_desc)) { - if (!rmnet_frag_pull(frag_desc, port, hdr_len)) { - kfree_skb(head_skb); - return NULL; - } - } - } else { - /* Allocate enough space to avoid penalties in the stack - * from __pskb_pull_tail() - */ - head_skb = alloc_skb(256 + RMNET_MAP_DESC_HEADROOM, - GFP_ATOMIC); - if (!head_skb) - return NULL; - - skb_reserve(head_skb, RMNET_MAP_DESC_HEADROOM); - } - - /* Add main fragment */ - get_page(skb_frag_page(&frag_desc->frag)); - skb_add_rx_frag(head_skb, 0, skb_frag_page(&frag_desc->frag), - frag_desc->frag.page_offset, - skb_frag_size(&frag_desc->frag), - skb_frag_size(&frag_desc->frag)); - - shinfo = skb_shinfo(head_skb); - current_skb = head_skb; - - /* Add in any frags from rmnet_perf */ - list_for_each_entry_safe(sub_frag, tmp, &frag_desc->sub_frags, list) { - skb_frag_t *frag; - u32 frag_size; - - frag = &sub_frag->frag; - frag_size = skb_frag_size(frag); - -add_frag: - if (shinfo->nr_frags < MAX_SKB_FRAGS) { - get_page(skb_frag_page(frag)); - skb_add_rx_frag(current_skb, shinfo->nr_frags, - skb_frag_page(frag), frag->page_offset, - frag_size, frag_size); - if (current_skb != head_skb) { - head_skb->len += frag_size; - head_skb->data_len += frag_size; - } - } else { - /* Alloc a new skb and try again */ - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) - break; - - if (current_skb == head_skb) - shinfo->frag_list = skb; - else - current_skb->next = skb; - - current_skb = skb; - shinfo = skb_shinfo(current_skb); - goto add_frag; - } - - rmnet_recycle_frag_descriptor(sub_frag, port); - } - -skip_frags: - head_skb->dev = frag_desc->dev; - rmnet_set_skb_proto(head_skb); - - /* Handle any header metadata that needs to be updated after RSB/RSC - * segmentation - */ - if (frag_desc->ip_id_set) { - struct iphdr *iph; - - iph = (struct iphdr *)rmnet_map_data_ptr(head_skb); - csum_replace2(&iph->check, iph->id, frag_desc->ip_id); - iph->id = frag_desc->ip_id; - } - - if (frag_desc->tcp_seq_set) { - struct tcphdr *th; - - th = (struct tcphdr *) - (rmnet_map_data_ptr(head_skb) + frag_desc->ip_len); - th->seq = frag_desc->tcp_seq; - } - - /* Handle csum offloading */ - if (frag_desc->csum_valid && frag_desc->hdrs_valid) { - /* Set the partial checksum information */ - //rmnet_frag_partial_csum(head_skb, frag_desc); - WARN_ON(1); - } else if (frag_desc->csum_valid) { - /* Non-RSB/RSC/perf packet. The current checksum is fine */ - head_skb->ip_summed = CHECKSUM_UNNECESSARY; - } else if (frag_desc->hdrs_valid && - (frag_desc->trans_proto == IPPROTO_TCP || - frag_desc->trans_proto == IPPROTO_UDP)) { - /* Unfortunately, we have to fake a bad checksum here, since - * the original bad value is lost by the hardware. The only - * reliable way to do it is to calculate the actual checksum - * and corrupt it. - */ - __sum16 *check; - __wsum csum; - unsigned int offset = skb_transport_offset(head_skb); - __sum16 pseudo; - - WARN_ON(1); - /* Calculate pseudo header and update header fields */ - if (frag_desc->ip_proto == 4) { - struct iphdr *iph = ip_hdr(head_skb); - __be16 tot_len = htons(head_skb->len); - - csum_replace2(&iph->check, iph->tot_len, tot_len); - iph->tot_len = tot_len; - pseudo = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - head_skb->len - - frag_desc->ip_len, - frag_desc->trans_proto, 0); - } else { - struct ipv6hdr *ip6h = ipv6_hdr(head_skb); - - ip6h->payload_len = htons(head_skb->len - - sizeof(*ip6h)); - pseudo = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, - head_skb->len - - frag_desc->ip_len, - frag_desc->trans_proto, 0); - } - - if (frag_desc->trans_proto == IPPROTO_TCP) { - check = &tcp_hdr(head_skb)->check; - } else { - udp_hdr(head_skb)->len = htons(head_skb->len - - frag_desc->ip_len); - check = &udp_hdr(head_skb)->check; - } - - *check = pseudo; - csum = skb_checksum(head_skb, offset, head_skb->len - offset, - 0); - /* Add 1 to corrupt. This cannot produce a final value of 0 - * since csum_fold() can't return a value of 0xFFFF - */ - *check = csum16_add(csum_fold(csum), htons(1)); - head_skb->ip_summed = CHECKSUM_NONE; - } - - /* Handle any rmnet_perf metadata */ - if (frag_desc->hash) { - head_skb->hash = frag_desc->hash; - head_skb->sw_hash = 1; - } - - if (frag_desc->flush_shs) - head_skb->cb[0] = 1; - - /* Handle coalesced packets */ - //if (frag_desc->gso_segs > 1) - // rmnet_frag_gso_stamp(head_skb, frag_desc); - - return head_skb; -} - -/* Deliver the packets contained within a frag descriptor */ -static void rmnet_frag_deliver(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct sk_buff *skb; - - skb = rmnet_alloc_skb(frag_desc, port); - if (skb) - rmnet_deliver_skb(skb, port); - rmnet_recycle_frag_descriptor(frag_desc, port); -} - -/* Process a QMAPv5 packet header */ -static int rmnet_frag_process_next_hdr_packet(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port, - struct list_head *list, - u16 len) -{ - int rc = 0; - - switch (rmnet_frag_get_next_hdr_type(frag_desc)) { - case RMNET_MAP_HEADER_TYPE_COALESCING: - rc = -1; - WARN_ON(1); - break; - case RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD: - if (rmnet_frag_get_csum_valid(frag_desc)) { - frag_desc->csum_valid = true; - } else { - } - - if (!rmnet_frag_pull(frag_desc, port, - sizeof(struct rmnet_map_header) + - sizeof(struct rmnet_map_v5_csum_header))) { - rc = -EINVAL; - break; - } - - frag_desc->hdr_ptr = rmnet_frag_data_ptr(frag_desc); - - /* Remove padding only for csum offload packets. - * Coalesced packets should never have padding. - */ - if (!rmnet_frag_trim(frag_desc, port, len)) { - rc = -EINVAL; - break; - } - - list_del_init(&frag_desc->list); - list_add_tail(&frag_desc->list, list); - break; - default: - qmap_hex_dump(__func__, rmnet_frag_data_ptr(frag_desc), 64); - rc = -EINVAL; - break; - } - - return rc; -} - -static void -__rmnet_frag_ingress_handler(struct rmnet_frag_descriptor *frag_desc, - struct rmnet_port *port) -{ - struct rmnet_map_header *qmap; - struct rmnet_endpoint *ep; - struct rmnet_frag_descriptor *frag, *tmp; - LIST_HEAD(segs); - u16 len, pad; - u8 mux_id; - - qmap = (struct rmnet_map_header *)skb_frag_address(&frag_desc->frag); - mux_id = qmap->mux_id; - pad = qmap->pad_len; - len = ntohs(qmap->pkt_len) - pad; - - if (qmap->cd_bit) { - goto recycle; - } - - if (mux_id >= RMNET_MAX_LOGICAL_EP) - goto recycle; - - ep = rmnet_get_endpoint(port, mux_id); - if (!ep) - goto recycle; - - frag_desc->dev = ep->rmnet_dev; - - /* Handle QMAPv5 packet */ - if (qmap->next_hdr && - (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5))) { - if (rmnet_frag_process_next_hdr_packet(frag_desc, port, &segs, - len)) - goto recycle; - } else { - /* We only have the main QMAP header to worry about */ - if (!rmnet_frag_pull(frag_desc, port, sizeof(*qmap))) - return; - - frag_desc->hdr_ptr = rmnet_frag_data_ptr(frag_desc); - - if (!rmnet_frag_trim(frag_desc, port, len)) - return; - - list_add_tail(&frag_desc->list, &segs); - } - - list_for_each_entry_safe(frag, tmp, &segs, list) { - list_del_init(&frag->list); - rmnet_frag_deliver(frag, port); - } - return; - -recycle: - rmnet_recycle_frag_descriptor(frag_desc, port); -} - -static void rmnet_frag_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - LIST_HEAD(desc_list); - int i = 0; - struct rmnet_nss_cb *nss_cb; - - /* Deaggregation and freeing of HW originating - * buffers is done within here - */ - while (skb) { - struct sk_buff *skb_frag; - - port->chain_head = NULL; - port->chain_tail = NULL; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - rmnet_frag_deaggregate(&skb_shinfo(skb)->frags[i], port, - &desc_list); - if (!list_empty(&desc_list)) { - struct rmnet_frag_descriptor *frag_desc, *tmp; - - list_for_each_entry_safe(frag_desc, tmp, - &desc_list, list) { - list_del_init(&frag_desc->list); - __rmnet_frag_ingress_handler(frag_desc, - port); - } - } - } - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb && port->chain_head) { - port->chain_head->cb[0] = 0; - netif_receive_skb(port->chain_head); - } - - skb_frag = skb_shinfo(skb)->frag_list; - skb_shinfo(skb)->frag_list = NULL; - consume_skb(skb); - skb = skb_frag; - } -} - -static void -rmnet_map_ingress_handler(struct sk_buff *skb, - struct rmnet_port *port) -{ - if (port->data_format & (RMNET_FLAGS_INGRESS_COALESCE | - RMNET_FLAGS_INGRESS_MAP_CKSUMV5)) { - if (skb_is_nonlinear(skb)) { - rmnet_frag_ingress_handler(skb, port); - return; - } - } - - WARN_ON(1); -} - -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb); -static int rmnet_is_real_dev_registered(const struct net_device *real_dev) -{ - return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler; -} - - -/* Needs either rcu_read_lock() or rtnl lock */ -struct rmnet_port *rmnet_get_port(struct net_device *real_dev) -{ - if (rmnet_is_real_dev_registered(real_dev)) - return rcu_dereference_rtnl(real_dev->rx_handler_data); - else - return NULL; -} - -static rx_handler_result_t rmnet_rx_priv_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_nss_cb *nss_cb; - - if (!skb) - return RX_HANDLER_CONSUMED; - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - /* Check this so that we dont loop around netif_receive_skb */ - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - skb->dev->stats.rx_packets++; - return RX_HANDLER_PASS; - } - - while (skb) { - struct sk_buff *skb_frag = skb_shinfo(skb)->frag_list; - - skb_shinfo(skb)->frag_list = NULL; - - nss_cb = rcu_dereference(rmnet_nss_callbacks); - if (nss_cb) - nss_cb->nss_tx(skb); - - skb = skb_frag; - } - - return RX_HANDLER_CONSUMED; -} - -/* Ingress / Egress Entry Points */ - -/* Processes packet as per ingress data format for receiving device. Logical - * endpoint is determined from packet inspection. Packet is then sent to the - * egress device listed in the logical endpoint configuration. - */ -static rx_handler_result_t rmnet_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_port *port; - struct net_device *dev; - - if (!skb) - goto done; - - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - if (skb->pkt_type == PACKET_LOOPBACK) - return RX_HANDLER_PASS; - - if (skb->protocol != htons(ETH_P_MAP)) { - WARN_ON(1); - return RX_HANDLER_PASS; - } - - dev = skb->dev; - port = rmnet_get_port(dev); - - if (port == NULL) - return RX_HANDLER_PASS; - - port->chain_head = NULL; - port->chain_tail = NULL; - - switch (port->rmnet_mode) { - case RMNET_EPMODE_VND: - rmnet_map_ingress_handler(skb, port); - break; - case RMNET_EPMODE_BRIDGE: - //rmnet_bridge_handler(skb, port->bridge_ep); - break; - } - -done: - return RX_HANDLER_CONSUMED; -} - -static void rmnet_descriptor_deinit(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool; - struct rmnet_frag_descriptor *frag_desc, *tmp; - - pool = port->frag_desc_pool; - - list_for_each_entry_safe(frag_desc, tmp, &pool->free_list, list) { - kfree(frag_desc); - pool->pool_size--; - } - - kfree(pool); -} - -static int rmnet_descriptor_init(struct rmnet_port *port) -{ - struct rmnet_frag_descriptor_pool *pool; - int i; - - spin_lock_init(&port->desc_pool_lock); - pool = kzalloc(sizeof(*pool), GFP_ATOMIC); - if (!pool) - return -ENOMEM; - - INIT_LIST_HEAD(&pool->free_list); - port->frag_desc_pool = pool; - - for (i = 0; i < RMNET_FRAG_DESCRIPTOR_POOL_SIZE; i++) { - struct rmnet_frag_descriptor *frag_desc; - - frag_desc = kzalloc(sizeof(*frag_desc), GFP_ATOMIC); - if (!frag_desc) - return -ENOMEM; - - INIT_LIST_HEAD(&frag_desc->list); - INIT_LIST_HEAD(&frag_desc->sub_frags); - list_add_tail(&frag_desc->list, &pool->free_list); - pool->pool_size++; - } - - return 0; -} - -struct rmnet_priv { - //struct rmnet_endpoint local_ep; - struct net_device *real_dev; - u8 mux_id; -}; - -static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rmnet_priv *priv; - - if (nss_debug) printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - priv = netdev_priv(dev); - if (priv->real_dev) { - add_qhdr_v5(skb, priv->mux_id); - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; - dev_queue_xmit(skb); - dev->stats.tx_packets++; - //rmnet_egress_handler(skb); - } else { - //this_cpu_inc(priv->pcpu_stats->stats.tx_drops); - kfree_skb(skb); - } - return NETDEV_TX_OK; -} - -static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu) -{ - if (new_mtu < 0 || new_mtu > RMNET_MAX_PACKET_SIZE) - return -EINVAL; - - rmnet_dev->mtu = new_mtu; - return 0; -} - -static const struct net_device_ops rmnet_vnd_ops = { - .ndo_start_xmit = rmnet_vnd_start_xmit, - .ndo_change_mtu = rmnet_vnd_change_mtu, - //.ndo_get_iflink = rmnet_vnd_get_iflink, - //.ndo_add_slave = rmnet_add_bridge, - //.ndo_del_slave = rmnet_del_bridge, - //.ndo_init = rmnet_vnd_init, - //.ndo_uninit = rmnet_vnd_uninit, - //.ndo_get_stats64 = rmnet_get_stats64, -}; - -static void rmnet_vnd_setup(struct net_device *rmnet_dev) -{ - rmnet_dev->netdev_ops = &rmnet_vnd_ops; - rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE; - rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM; - random_ether_addr(rmnet_dev->dev_addr); - rmnet_dev->tx_queue_len = RMNET_TX_QUEUE_LEN; - - /* Raw IP mode */ - rmnet_dev->header_ops = NULL; /* No header */ - rmnet_dev->type = ARPHRD_RAWIP; - rmnet_dev->hard_header_len = 0; - rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - - //rmnet_dev->needs_free_netdev = true; - - rmnet_dev->hw_features = NETIF_F_RXCSUM; - rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - //rmnet_dev->hw_features |= NETIF_F_SG; - //rmnet_dev->hw_features |= NETIF_F_GRO_HW; -} -#else -#include -#include -#include -#include -#include -#include -#include -#include - -static uint nss_debug = 0; -module_param( nss_debug, uint, S_IRUGO | S_IWUSR); - -/* rmnet section */ - -#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) -#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) -#define RMNET_FLAGS_INGRESS_COALESCE (1U << 4) -#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5 (1U << 5) -#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5 (1U << 6) - -#ifdef CONFIG_ARCH_IPQ807x -#define CONFIG_QCA_NSS_DRV -#endif -#ifdef CONFIG_QCA_NSS_DRV -#include "rmnet/rmnet_nss.c" -#else -#include "rmnet_nss.h" -#endif - -#include "rmnet/rmnet_vnd.c" -#include "rmnet/rmnet_map_command.c" -#include "rmnet/rmnet_map_data.c" -#include "rmnet/rmnet_descriptor.c" -#include "rmnet/rmnet_config.c" -#include "rmnet/rmnet_handlers.c" - -struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; - -void rmnet_init(struct net_device *real_dev, u32 nr_rmnet_devs) -{ - struct rmnet_port *port; - struct rmnet_endpoint *ep; - struct net_device *rmnet_dev = NULL; - u32 nr = 0; - struct rmnet_nss_cb *nss_cb = rcu_dereference(rmnet_nss_callbacks); - - if (!nss_cb) { -#ifdef CONFIG_QCA_NSS_DRV - rmnet_nss_init(); -#endif - } - - rmnet_register_real_device(real_dev); - - port = rmnet_get_port_rtnl(real_dev); - - port->data_format = RMNET_FLAGS_INGRESS_DEAGGREGATION - | RMNET_FLAGS_INGRESS_MAP_CKSUMV5 | RMNET_FLAGS_EGRESS_MAP_CKSUMV5; - port->rmnet_mode = RMNET_EPMODE_VND; - - for (nr = 0; nr < nr_rmnet_devs; nr++) { - u8 mux_id = 0x81+nr; - - rmnet_dev = alloc_netdev(sizeof(struct rmnet_priv), - "rmnet_data%d", NET_NAME_PREDICTABLE, - rmnet_vnd_setup); - - ep = kzalloc(sizeof(*ep), GFP_ATOMIC); - - rmnet_vnd_newlink(mux_id, rmnet_dev, port, real_dev, ep); - netdev_rx_handler_register(rmnet_dev, rmnet_rx_priv_handler, NULL); - hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]); - } - - port->nr_rmnet_devs = nr_rmnet_devs; -} - -void rmnet_deinit(struct net_device *real_dev, u32 nr_rmnet_devs) -{ - struct rmnet_port *port; - u32 nr = 0; - struct rmnet_nss_cb *nss_cb = rcu_dereference(rmnet_nss_callbacks); - - port = rmnet_get_port_rtnl(real_dev); - - if (!real_dev || !rmnet_is_real_dev_registered(real_dev)) - return; - - port = rmnet_get_port_rtnl(real_dev); - - for (nr = 0; nr < nr_rmnet_devs; nr++) { - struct rmnet_endpoint *ep; - u8 mux_id = 0x81+nr; - - ep = rmnet_get_endpoint(port, mux_id); - if (ep) { - hlist_del_init_rcu(&ep->hlnode); - rmnet_vnd_dellink(mux_id, port, ep); - synchronize_rcu(); - kfree(ep); - } - } - - rmnet_unregister_real_device(real_dev, port); - - if (nss_cb) { -#ifdef CONFIG_QCA_NSS_DRV - rmnet_nss_exit(); -#endif - } -} -#endif diff --git a/quectel_MHI/src/devices/rmnet_nss.c b/quectel_MHI/src/devices/rmnet_nss.c deleted file mode 100644 index e6e8414..0000000 --- a/quectel_MHI/src/devices/rmnet_nss.c +++ /dev/null @@ -1,424 +0,0 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define RMNET_NSS_HASH_BITS 8 -#define hash_add_ptr(table, node, key) \ - hlist_add_head(node, &table[hash_ptr(key, HASH_BITS(table))]) - -static DEFINE_HASHTABLE(rmnet_nss_ctx_hashtable, RMNET_NSS_HASH_BITS); - -struct rmnet_nss_ctx { - struct hlist_node hnode; - struct net_device *rmnet_dev; - struct nss_rmnet_rx_handle *nss_ctx; -}; - -enum __rmnet_nss_stat { - RMNET_NSS_RX_ETH, - RMNET_NSS_RX_FAIL, - RMNET_NSS_RX_NON_ETH, - RMNET_NSS_RX_BUSY, - RMNET_NSS_TX_NO_CTX, - RMNET_NSS_TX_SUCCESS, - RMNET_NSS_TX_FAIL, - RMNET_NSS_TX_NONLINEAR, - RMNET_NSS_TX_BAD_IP, - RMNET_NSS_EXCEPTIONS, - RMNET_NSS_EX_BAD_HDR, - RMNET_NSS_EX_BAD_IP, - RMNET_NSS_EX_SUCCESS, - RMNET_NSS_TX_BAD_FRAGS, - RMNET_NSS_TX_LINEARIZE_FAILS, - RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS, - RMNET_NSS_TX_BUSY_LOOP, - RMNET_NSS_NUM_STATS, -}; - -static unsigned long rmnet_nss_stats[RMNET_NSS_NUM_STATS]; - -#define RMNET_NSS_STAT(name, counter, desc) \ - module_param_named(name, rmnet_nss_stats[counter], ulong, 0444); \ - MODULE_PARM_DESC(name, desc) - -RMNET_NSS_STAT(rmnet_nss_rx_ethernet, RMNET_NSS_RX_ETH, - "Number of Ethernet headers successfully removed"); -RMNET_NSS_STAT(rmnet_nss_rx_fail, RMNET_NSS_RX_FAIL, - "Number of Ethernet headers that could not be removed"); -RMNET_NSS_STAT(rmnet_nss_rx_non_ethernet, RMNET_NSS_RX_NON_ETH, - "Number of non-Ethernet packets received"); -RMNET_NSS_STAT(rmnet_nss_rx_busy, RMNET_NSS_RX_BUSY, - "Number of packets dropped decause rmnet_data device was busy"); -RMNET_NSS_STAT(rmnet_nss_tx_slow, RMNET_NSS_TX_NO_CTX, - "Number of packets sent over non-NSS-accelerated rmnet device"); -RMNET_NSS_STAT(rmnet_nss_tx_fast, RMNET_NSS_TX_SUCCESS, - "Number of packets sent over NSS-accelerated rmnet device"); -RMNET_NSS_STAT(rmnet_nss_tx_fail, RMNET_NSS_TX_FAIL, - "Number of packets that NSS could not transmit"); -RMNET_NSS_STAT(rmnet_nss_tx_nonlinear, RMNET_NSS_TX_NONLINEAR, - "Number of non linear sent over NSS-accelerated rmnet device"); -RMNET_NSS_STAT(rmnet_nss_tx_invalid_ip, RMNET_NSS_TX_BAD_IP, - "Number of ingress packets with invalid IP headers"); -RMNET_NSS_STAT(rmnet_nss_tx_invalid_frags, RMNET_NSS_TX_BAD_FRAGS, - "Number of ingress packets with invalid frag format"); -RMNET_NSS_STAT(rmnet_nss_tx_linearize_fail, RMNET_NSS_TX_LINEARIZE_FAILS, - "Number of ingress packets where linearize in tx fails"); -RMNET_NSS_STAT(rmnet_nss_tx_exceptions, RMNET_NSS_EXCEPTIONS, - "Number of times our DL exception handler was invoked"); -RMNET_NSS_STAT(rmnet_nss_exception_non_ethernet, RMNET_NSS_EX_BAD_HDR, - "Number of non-Ethernet exception packets"); -RMNET_NSS_STAT(rmnet_nss_exception_invalid_ip, RMNET_NSS_EX_BAD_IP, - "Number of exception packets with invalid IP headers"); -RMNET_NSS_STAT(rmnet_nss_exception_success, RMNET_NSS_EX_SUCCESS, - "Number of exception packets handled successfully"); -RMNET_NSS_STAT(rmnet_nss_tx_non_zero_headlen_frags, RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS, - "Number of packets with non zero headlen"); -RMNET_NSS_STAT(rmnet_nss_tx_busy_loop, RMNET_NSS_TX_BUSY_LOOP, - "Number of times tx packets busy looped"); - -static void rmnet_nss_inc_stat(enum __rmnet_nss_stat stat) -{ - if (stat >= 0 && stat < RMNET_NSS_NUM_STATS) - rmnet_nss_stats[stat]++; -} - -static struct rmnet_nss_ctx *rmnet_nss_find_ctx(struct net_device *dev) -{ - struct rmnet_nss_ctx *ctx; - struct hlist_head *bucket; - u32 hash; - - hash = hash_ptr(dev, HASH_BITS(rmnet_nss_ctx_hashtable)); - bucket = &rmnet_nss_ctx_hashtable[hash]; - hlist_for_each_entry(ctx, bucket, hnode) { - if (ctx->rmnet_dev == dev) - return ctx; - } - - return NULL; -} - -static void rmnet_nss_free_ctx(struct rmnet_nss_ctx *ctx) -{ - if (ctx) { - hash_del(&ctx->hnode); - nss_rmnet_rx_xmit_callback_unregister(ctx->nss_ctx); - nss_rmnet_rx_destroy_sync(ctx->nss_ctx); - kfree(ctx); - } -} - -/* Pull off an ethernet header, if possible */ -static int rmnet_nss_ethhdr_pull(struct sk_buff *skb) -{ - if (!skb->protocol || skb->protocol == htons(ETH_P_802_3)) { - void *ret = skb_pull(skb, sizeof(struct ethhdr)); - - rmnet_nss_inc_stat((ret) ? RMNET_NSS_RX_ETH : - RMNET_NSS_RX_FAIL); - return !ret; - } - - rmnet_nss_inc_stat(RMNET_NSS_RX_NON_ETH); - return -1; -} - -/* Copy headers to linear section for non linear packets */ -static int rmnet_nss_adjust_header(struct sk_buff *skb) -{ - struct iphdr *iph; - skb_frag_t *frag; - int bytes = 0; - u8 transport; - - if (skb_shinfo(skb)->nr_frags != 1) { - rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_FRAGS); - return -EINVAL; - } - - if (skb_headlen(skb)) { - rmnet_nss_inc_stat(RMNET_NSS_TX_NON_ZERO_HEADLEN_FRAGS); - return 0; - } - - frag = &skb_shinfo(skb)->frags[0]; - - iph = (struct iphdr *)(skb_frag_address(frag)); - - if (iph->version == 4) { - bytes = iph->ihl*4; - transport = iph->protocol; - } else if (iph->version == 6) { - struct ipv6hdr *ip6h = (struct ipv6hdr *)iph; - - bytes = sizeof(struct ipv6hdr); - /* Dont have to account for extension headers yet */ - transport = ip6h->nexthdr; - } else { - rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_IP); - return -EINVAL; - } - - if (transport == IPPROTO_TCP) { - struct tcphdr *th; - - th = (struct tcphdr *)((u8 *)iph + bytes); - bytes += th->doff * 4; - } else if (transport == IPPROTO_UDP) { - bytes += sizeof(struct udphdr); - } else { - /* cant do anything else here unfortunately so linearize */ - if (skb_linearize(skb)) { - rmnet_nss_inc_stat(RMNET_NSS_TX_LINEARIZE_FAILS); - return -EINVAL; - } else { - return 0; - } - } - - if (bytes > skb_frag_size(frag)) { - rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_FRAGS); - return -EINVAL; - } - - skb_push(skb, bytes); - memcpy(skb->data, iph, bytes); - - /* subtract to account for skb_push */ - skb->len -= bytes; - - frag->page_offset += bytes; - skb_frag_size_sub(frag, bytes); - - /* subtract to account for skb_frag_size_sub */ - skb->data_len -= bytes; - - return 0; -} - -/* Main downlink handler - * Looks up NSS contex associated with the device. If the context is found, - * we add a dummy ethernet header with the approriate protocol field set, - * the pass the packet off to NSS for hardware acceleration. - */ -int rmnet_nss_tx(struct sk_buff *skb) -{ - struct ethhdr *eth; - struct rmnet_nss_ctx *ctx; - struct net_device *dev = skb->dev; - nss_tx_status_t rc; - unsigned int len; - u8 version; - - if (skb_is_nonlinear(skb)) { - if (rmnet_nss_adjust_header(skb)) - goto fail; - else - rmnet_nss_inc_stat(RMNET_NSS_TX_NONLINEAR); - } - - version = ((struct iphdr *)skb->data)->version; - - ctx = rmnet_nss_find_ctx(dev); - if (!ctx) { - rmnet_nss_inc_stat(RMNET_NSS_TX_NO_CTX); - return -EINVAL; - } - - eth = (struct ethhdr *)skb_push(skb, sizeof(*eth)); - memset(ð->h_dest, 0, ETH_ALEN * 2); - if (version == 4) { - eth->h_proto = htons(ETH_P_IP); - } else if (version == 6) { - eth->h_proto = htons(ETH_P_IPV6); - } else { - rmnet_nss_inc_stat(RMNET_NSS_TX_BAD_IP); - goto fail; - } - - skb->protocol = htons(ETH_P_802_3); - /* Get length including ethhdr */ - len = skb->len; - -transmit: - rc = nss_rmnet_rx_tx_buf(ctx->nss_ctx, skb); - if (rc == NSS_TX_SUCCESS) { - /* Increment rmnet_data device stats. - * Don't call rmnet_data_vnd_rx_fixup() to do this, as - * there's no guarantee the skb pointer is still valid. - */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; - rmnet_nss_inc_stat(RMNET_NSS_TX_SUCCESS); - return 0; - } else if (rc == NSS_TX_FAILURE_QUEUE) { - rmnet_nss_inc_stat(RMNET_NSS_TX_BUSY_LOOP); - goto transmit; - } - -fail: - rmnet_nss_inc_stat(RMNET_NSS_TX_FAIL); - kfree_skb(skb); - return 1; -} - -/* Called by NSS in the DL exception case. - * Since the packet cannot be sent over the accelerated path, we need to - * handle it. Remove the ethernet header and pass it onward to the stack - * if possible. - */ -void rmnet_nss_receive(struct net_device *dev, struct sk_buff *skb, - struct napi_struct *napi) -{ - rmnet_nss_inc_stat(RMNET_NSS_EXCEPTIONS); - - if (!skb) - return; - - if (rmnet_nss_ethhdr_pull(skb)) { - rmnet_nss_inc_stat(RMNET_NSS_EX_BAD_HDR); - goto drop; - } - - /* reset header pointers */ - skb_reset_transport_header(skb); - skb_reset_network_header(skb); - skb_reset_mac_header(skb); - - /* reset packet type */ - skb->pkt_type = PACKET_HOST; - - skb->dev = dev; - - /* reset protocol type */ - switch (skb->data[0] & 0xF0) { - case 0x40: - skb->protocol = htons(ETH_P_IP); - break; - case 0x60: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - rmnet_nss_inc_stat(RMNET_NSS_EX_BAD_IP); - goto drop; - } - - rmnet_nss_inc_stat(RMNET_NSS_EX_SUCCESS); - - /* Set this so that we dont loop around netif_receive_skb */ - - skb->cb[0] = 1; - - netif_receive_skb(skb); - return; - -drop: - kfree_skb(skb); -} - -/* Called by NSS in the UL acceleration case. - * We are guaranteed to have an ethernet packet here from the NSS hardware, - * We need to pull the header off and invoke our ndo_start_xmit function - * to handle transmitting the packet to the network stack. - */ -void rmnet_nss_xmit(struct net_device *dev, struct sk_buff *skb) -{ - netdev_tx_t ret; - - skb_pull(skb, sizeof(struct ethhdr)); - rmnet_nss_inc_stat(RMNET_NSS_RX_ETH); - - /* NSS takes care of shaping, so bypassing Qdiscs like this is OK */ - ret = dev->netdev_ops->ndo_start_xmit(skb, dev); - if (unlikely(ret == NETDEV_TX_BUSY)) { - dev_kfree_skb_any(skb); - rmnet_nss_inc_stat(RMNET_NSS_RX_BUSY); - } -} - -/* Create and register an NSS context for an rmnet_data device */ -int rmnet_nss_create_vnd(struct net_device *dev) -{ - struct rmnet_nss_ctx *ctx; - - ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC); - if (!ctx) - return -ENOMEM; - - ctx->rmnet_dev = dev; - ctx->nss_ctx = nss_rmnet_rx_create_sync_nexthop(dev, NSS_N2H_INTERFACE, - NSS_C2C_TX_INTERFACE); - if (!ctx->nss_ctx) { - kfree(ctx); - return -1; - } - - nss_rmnet_rx_register(ctx->nss_ctx, rmnet_nss_receive, dev); - nss_rmnet_rx_xmit_callback_register(ctx->nss_ctx, rmnet_nss_xmit); - hash_add_ptr(rmnet_nss_ctx_hashtable, &ctx->hnode, dev); - return 0; -} - -/* Unregister and destroy the NSS context for an rmnet_data device */ -int rmnet_nss_free_vnd(struct net_device *dev) -{ - struct rmnet_nss_ctx *ctx; - - ctx = rmnet_nss_find_ctx(dev); - rmnet_nss_free_ctx(ctx); - - return 0; -} - -static const struct rmnet_nss_cb rmnet_nss = { - .nss_create = rmnet_nss_create_vnd, - .nss_free = rmnet_nss_free_vnd, - .nss_tx = rmnet_nss_tx, -}; - -int __init rmnet_nss_init(void) -{ - pr_err("%s(): initializing rmnet_nss\n", __func__); - RCU_INIT_POINTER(rmnet_nss_callbacks, &rmnet_nss); - return 0; -} - -void __exit rmnet_nss_exit(void) -{ - struct hlist_node *tmp; - struct rmnet_nss_ctx *ctx; - int bkt; - - pr_err("%s(): exiting rmnet_nss\n", __func__); - RCU_INIT_POINTER(rmnet_nss_callbacks, NULL); - - /* Tear down all NSS contexts */ - hash_for_each_safe(rmnet_nss_ctx_hashtable, bkt, tmp, ctx, hnode) - rmnet_nss_free_ctx(ctx); -} - -#if 0 -MODULE_LICENSE("GPL v2"); -module_init(rmnet_nss_init); -module_exit(rmnet_nss_exit); -#endif diff --git a/quectel_MHI/src/log/AT_OVER_PCIE.txt b/quectel_MHI/src/log/AT_OVER_PCIE.txt deleted file mode 100644 index bc48504..0000000 --- a/quectel_MHI/src/log/AT_OVER_PCIE.txt +++ /dev/null @@ -1,31 +0,0 @@ -root@imx6qsabresd:~# busybox microcom /dev/mhi_DUN -[ 384.652992] [I][mhi_uci_open] Node open, ref counts 1 -[ 384.658144] [I][mhi_uci_open] Starting channel -[ 384.662612] [I][__mhi_prepare_channel] Entered: preparing channel:32 -[ 384.680397] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 384.685890] [I][__mhi_prepare_channel] Chan:32 successfully moved to start state -[ 384.693312] [I][__mhi_prepare_channel] Entered: preparing channel:33 -[ 384.708692] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 384.714324] [I][__mhi_prepare_channel] Chan:33 successfully moved to start state - -RDY - -+CFUN: 1 - -+CPIN: READY - -+QUSIM: 1 - -+QIND: SMS DONE - -+QIND: PB DONE -ati -Quectel -EM20 -Revision: EM20GR01A01M4G - -OK -at+cpin? -+CPIN: READY - -OK diff --git a/quectel_MHI/src/log/MBIM_OVER_PCIE.txt b/quectel_MHI/src/log/MBIM_OVER_PCIE.txt deleted file mode 100644 index 927a9b2..0000000 --- a/quectel_MHI/src/log/MBIM_OVER_PCIE.txt +++ /dev/null @@ -1,145 +0,0 @@ -root@OpenWrt:~# insmod pcie_mhi.ko mhi_mbim_enabled=1 -root@OpenWrt:~# dmesg | grep mhi -[ 65.587160] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.6 -[ 65.597089] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 65.602250] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x20300000-0x20300fff 64bit] -[ 65.611690] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 65.619307] [I][mhi_init_pci_dev] msi_required = 5, msi_allocated = 5, msi_irq = 63 -[ 65.619327] [I][mhi_power_up] dev_state:RESET -[ 65.619331] [I][mhi_async_power_up] Requested to power on -[ 65.619449] [I][mhi_alloc_coherent] size = 114688, dma_handle = 6fca0000 -[ 65.619462] [I][mhi_init_dev_ctxt] mhi_ctxt->ctrl_seg = c221e000 -[ 65.619731] [I][mhi_async_power_up] dev_state:RESET ee:AMSS -[ 65.619747] [I][mhi_pm_st_worker] Transition to state:READY -[ 65.619760] [I][mhi_pm_st_worker] INVALID_EE -> AMSS -[ 65.619764] [I][mhi_ready_state_transition] Waiting to enter READY state -[ 65.619885] [I][mhi_async_power_up] Power on setup success -[ 65.619897] [I][mhi_pci_probe] Return successful -[ 65.665114] [I][mhi_ready_state_transition] Device in READY State -[ 65.665125] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, pm_state:POR -[ 65.665131] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, INVALID_EE -[ 65.665133] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:POR -[ 65.665137] [I][mhi_init_mmio] Initializing MMIO -[ 65.665142] [I][mhi_init_mmio] CHDBOFF:0x300 -[ 65.665151] [I][mhi_init_mmio] ERDBOFF:0x700 -[ 65.665156] [I][mhi_init_mmio] Programming all MMIO values. -[ 65.786283] [I][mhi_dump_tre] carl_ev evt_state_change mhistate=2 -[ 65.786289] [I][mhi_process_ctrl_ev_ring] MHI state change event to state:M0 -[ 65.786295] [I][mhi_pm_m0_transition] Entered With State:READY PM_STATE:POR -[ 65.786300] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:M0 -[ 65.789734] [I][mhi_dump_tre] carl_ev evt_ee_state execenv=2 -[ 65.789739] [I][mhi_process_ctrl_ev_ring] MHI EE received event:AMSS -[ 65.789756] [I][mhi_pm_st_worker] Transition to state:MISSION MODE -[ 65.789767] [I][mhi_pm_st_worker] INVALID_EE -> AMSS -[ 65.789771] [I][mhi_pm_mission_mode_transition] Processing Mission Mode Transition -[ 65.789787] [I][mhi_init_timesync] No timesync capability found -[ 65.789791] [I][mhi_pm_mission_mode_transition] Adding new devices -[ 65.790570] [I][mhi_dtr_probe] Enter for DTR control channel -[ 65.790577] [I][__mhi_prepare_channel] Entered: preparing channel:18 -[ 65.797036] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 65.797051] [I][__mhi_prepare_channel] Chan:18 successfully moved to start state -[ 65.797055] [I][__mhi_prepare_channel] Entered: preparing channel:19 -[ 65.802457] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 65.802469] [I][__mhi_prepare_channel] Chan:19 successfully moved to start state -[ 65.802485] [I][mhi_dtr_probe] Exit with ret:0 -[ 65.802748] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 65.802772] [I][__mhi_prepare_channel] Entered: preparing channel:100 -[ 65.825279] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 65.825293] [I][__mhi_prepare_channel] Chan:100 successfully moved to start state -[ 65.825297] [I][__mhi_prepare_channel] Entered: preparing channel:101 -[ 65.835565] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 65.835578] [I][__mhi_prepare_channel] Chan:101 successfully moved to start state -[ 65.839141] [I][mhi_netdev_enable_iface] Exited. -[ 65.839875] rmnet_vnd_register_device(rmnet_mhi0.1)=0 -[ 65.843278] net rmnet_mhi0 rmnet_mhi0.1: NSS context created -[ 65.861808] [I][mhi_pm_mission_mode_transition] Exit with ret:0 -[ 68.625595] [I][__mhi_prepare_channel] Entered: preparing channel:12 -[ 68.634610] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 68.634622] [I][__mhi_prepare_channel] Chan:12 successfully moved to start state -[ 68.634625] [I][__mhi_prepare_channel] Entered: preparing channel:13 -[ 68.644978] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 68.644987] [I][__mhi_prepare_channel] Chan:13 successfully moved to start state -[ 69.170666] net rmnet_mhi0: link_state 0x0 -> 0x1 -[ 69.177035] [I][mhi_netdev_open] Opened net dev interface -[ 71.655431] [I][mhi_netdev_open] Opened net dev interface - -root@OpenWrt:~# ./quectel-CM & -[04-02_04:14:12:134] Quectel_QConnectManager_Linux_V1.6.0.5 -[04-02_04:14:12:134] Find /sys/bus/usb/devices/4-1 idVendor=0x2c7c idProduct=0x800, bus=0x004, dev=0x002 -[04-02_04:14:12:135] network interface '' or qmidev '' is not exist -[04-02_04:14:12:135] netcard driver = pcie_mhi, driver version = V1.3.0.6 -[04-02_04:14:12:135] Modem works in MBIM mode -[04-02_04:14:12:135] apn (null), user (null), passwd (null), auth 0 -[04-02_04:14:12:135] IP Proto MBIMContextIPTypeIPv4 -[04-02_04:14:12:154] mbim_read_thread is created -sh: can't create /sys/class/net/rmnet_mhi0/mbim/link_state: nonexistent directory -[04-02_04:14:12:156] system(echo 0 > /sys/class/net/rmnet_mhi0/mbim/link_state)=256 -[04-02_04:14:12:185] system(ip address flush dev rmnet_mhi0)=0 -[04-02_04:14:12:187] system(ip link set dev rmnet_mhi0 down)=0 -[04-02_04:14:12:188] mbim_open_device() -[04-02_04:14:12:605] mbim_device_caps_query() -[04-02_04:14:12:610] DeviceId: 869710030002905 -[04-02_04:14:12:610] HardwareInfo: 0 -[04-02_04:14:12:610] mbim_set_radio_state( 1 ) -[04-02_04:14:12:613] HwRadioState: 1, SwRadioState: 1 -[04-02_04:14:12:613] mbim_subscriber_status_query() -[04-02_04:14:12:620] SubscriberReadyState NotInitialized -> Initialized -[04-02_04:14:12:620] mbim_register_state_query() -[04-02_04:14:12:625] RegisterState Unknown -> Home -[04-02_04:14:12:625] mbim_packet_service_query() -[04-02_04:14:12:629] PacketServiceState Unknown -> Attached -[04-02_04:14:12:629] mbim_query_connect(sessionID=0) -[04-02_04:14:12:633] ActivationState Unknown -> Deactivated -[04-02_04:14:12:633] mbim_set_connect(onoff=1, sessionID=0) -[ 69.170666] net rmnet_mhi0: link_state 0x0 -> 0x1 -[04-02_04:14:12:680] ActivationState Deactivated -> Activated -[ 69.177035] [I][mhi_netdev_open] Opened net dev interface -[04-02_04:14:12:680] mbim_ip_config(sessionID=0) -[04-02_04:14:12:683] < SessionId = 0 -[04-02_04:14:12:683] < IPv4ConfigurationAvailable = 0xf -[04-02_04:14:12:683] < IPv6ConfigurationAvailable = 0x0 -[04-02_04:14:12:683] < IPv4AddressCount = 0x1 -[04-02_04:14:12:683] < IPv4AddressOffset = 0x3c -[04-02_04:14:12:683] < IPv6AddressCount = 0x0 -[04-02_04:14:12:683] < IPv6AddressOffset = 0x0 -[04-02_04:14:12:683] < IPv4 = 10.129.59.93/30 -[04-02_04:14:12:683] < gw = 10.129.59.94 -[04-02_04:14:12:683] < dns1 = 211.138.180.2 -[04-02_04:14:12:683] < dns2 = 211.138.180.3 -[04-02_04:14:12:683] < ipv4 mtu = 1500 -sh: can't create /sys/class/net/rmnet_mhi0/mbim/link_state: nonexistent directory -[04-02_04:14:12:684] system(echo 1 > /sys/class/net/rmnet_mhi0/mbim/link_state)=256 -[04-02_04:14:12:689] system(ip link set dev rmnet_mhi0 up)=0 -[04-02_04:14:12:692] system(ip -4 address flush dev rmnet_mhi0)=0 -[04-02_04:14:12:694] system(ip -4 address add 10.129.59.93/30 dev rmnet_mhi0)=0 -[04-02_04:14:12:697] system(ip -4 route add default via 10.129.59.94 dev rmnet_mhi0)=0 -[04-02_04:14:12:699] system(ip -4 link set dev rmnet_mhi0 mtu 1500)=0 - -root@OpenWrt:~# ifconfig rmnet_mhi0 -rmnet_mhi0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:99379 errors:0 dropped:0 overruns:0 frame:0 - TX packets:176569 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:1528181052 (1.4 GiB) TX bytes:62467192 (59.5 MiB) - -root@OpenWrt:~# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:UNSPEC HWaddr 02-50-F4-00-00-00-00-00-00-00-00-00-00-00-00-00 - inet addr:10.129.59.93 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:1089360 errors:0 dropped:0 overruns:0 frame:0 - TX packets:176581 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:1521449058 (1.4 GiB) TX bytes:57525792 (54.8 MiB) - -# adjust CPU load balancing -root@OpenWrt:~# echo 2 > /sys/class/net/rmnet_mhi0/queues/rx-0/rps_cpus -root@OpenWrt:~# echo 4 > /sys/class/net/rmnet_mhi0.1/queues/rx-0/rps_cpus -root@OpenWrt:~# echo 2000 > /proc/sys/net/core/netdev_max_backlog -root@OpenWrt:~# cat /sys/class/net/rmnet_mhi0/queues/rx-0/rps_cpus -2 -root@OpenWrt:~# cat /sys/class/net/rmnet_mhi0.1/queues/rx-0/rps_cpus -4 -root@OpenWrt:~# cat /proc/sys/net/core/netdev_max_backlog -2000 diff --git a/quectel_MHI/src/log/QMI_OVER_PCIE.txt b/quectel_MHI/src/log/QMI_OVER_PCIE.txt deleted file mode 100644 index 14a64f9..0000000 --- a/quectel_MHI/src/log/QMI_OVER_PCIE.txt +++ /dev/null @@ -1,134 +0,0 @@ -disable ccflags-y += -DCONFIG_MHI_NETDEV_MBIM in pcie_mhi/Makefile - -root@OpenWrt:~# insmod pcie_mhi.ko - -root@OpenWrt:~# dmesg | grep mhi -[ 138.483252] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.6 -[ 138.492350] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 138.497564] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x20300000-0x20300fff 64bit] -[ 138.506952] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 138.514562] [I][mhi_init_pci_dev] msi_required = 5, msi_allocated = 5, msi_irq = 63 -[ 138.514581] [I][mhi_power_up] dev_state:RESET -[ 138.514587] [I][mhi_async_power_up] Requested to power on -[ 138.514728] [I][mhi_alloc_coherent] size = 114688, dma_handle = 72160000 -[ 138.514734] [I][mhi_init_dev_ctxt] mhi_ctxt->ctrl_seg = c221f000 -[ 138.515030] [I][mhi_async_power_up] dev_state:RESET ee:AMSS -[ 138.515056] [I][mhi_pm_st_worker] Transition to state:READY -[ 138.515067] [I][mhi_pm_st_worker] INVALID_EE -> AMSS -[ 138.515073] [I][mhi_ready_state_transition] Waiting to enter READY state -[ 138.515210] [I][mhi_async_power_up] Power on setup success -[ 138.515227] [I][mhi_pci_probe] Return successful -[ 138.589013] [I][mhi_ready_state_transition] Device in READY State -[ 138.589029] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, pm_state:POR -[ 138.589038] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, INVALID_EE -[ 138.589041] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:POR -[ 138.589046] [I][mhi_init_mmio] Initializing MMIO -[ 138.589050] [I][mhi_init_mmio] CHDBOFF:0x300 -[ 138.589060] [I][mhi_init_mmio] ERDBOFF:0x700 -[ 138.589065] [I][mhi_init_mmio] Programming all MMIO values. -[ 138.706124] [I][mhi_dump_tre] carl_ev evt_state_change mhistate=2 -[ 138.706132] [I][mhi_process_ctrl_ev_ring] MHI state change event to state:M0 -[ 138.706140] [I][mhi_pm_m0_transition] Entered With State:READY PM_STATE:POR -[ 138.706146] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:M0 -[ 138.708699] [I][mhi_dump_tre] carl_ev evt_ee_state execenv=2 -[ 138.708706] [I][mhi_process_ctrl_ev_ring] MHI EE received event:AMSS -[ 138.708726] [I][mhi_pm_st_worker] Transition to state:MISSION MODE -[ 138.708736] [I][mhi_pm_st_worker] INVALID_EE -> AMSS -[ 138.708742] [I][mhi_pm_mission_mode_transition] Processing Mission Mode Transition -[ 138.708758] [I][mhi_init_timesync] No timesync capability found -[ 138.708764] [I][mhi_pm_mission_mode_transition] Adding new devices -[ 138.709785] [I][mhi_dtr_probe] Enter for DTR control channel -[ 138.709794] [I][__mhi_prepare_channel] Entered: preparing channel:18 -[ 138.715378] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 138.715397] [I][__mhi_prepare_channel] Chan:18 successfully moved to start state -[ 138.715403] [I][__mhi_prepare_channel] Entered: preparing channel:19 -[ 138.720201] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 138.720218] [I][__mhi_prepare_channel] Chan:19 successfully moved to start state -[ 138.720236] [I][mhi_dtr_probe] Exit with ret:0 -[ 138.720590] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 138.720630] [I][__mhi_prepare_channel] Entered: preparing channel:100 -[ 138.757230] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 138.757253] [I][__mhi_prepare_channel] Chan:100 successfully moved to start state -[ 138.757259] [I][__mhi_prepare_channel] Entered: preparing channel:101 -[ 138.774352] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 138.774370] [I][__mhi_prepare_channel] Chan:101 successfully moved to start state -[ 138.778137] [I][mhi_netdev_enable_iface] Exited. -[ 138.779018] rmnet_vnd_register_device(rmnet_mhi0.1)=0 -[ 138.782283] net rmnet_mhi0 rmnet_mhi0.1: NSS context created -[ 138.800865] [I][mhi_pm_mission_mode_transition] Exit with ret:0 - -root@OpenWrt:~# ./quectel-CM & -root@OpenWrt:~# [04-02_04:12:16:477] Quectel_QConnectManager_Linux_V1.6.0.5 -[04-02_04:12:16:477] Find /sys/bus/usb/devices/4-1 idVendor=0x2c7c idProduct=0x800, bus=0x004, dev=0x002 -[04-02_04:12:16:478] network interface '' or qmidev '' is not exist -[04-02_04:12:16:478] netcard driver = pcie_mhi, driver version = V1.3.0.6 -[04-02_04:12:16:479] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 -[04-02_04:12:16:479] Modem works in QMI mode -[04-02_04:12:16:505] cdc_wdm_fd = 7 -[04-02_04:12:17:506] QmiThreadSendQMITimeout pthread_cond_timeout_np timeout -[04-02_04:12:18:516] Get clientWDS = 19 -[04-02_04:12:18:520] Get clientDMS = 1 -[04-02_04:12:18:524] Get clientNAS = 3 -[04-02_04:12:18:527] Get clientUIM = 1 -[04-02_04:12:18:531] Get clientWDA = 1 -[04-02_04:12:18:535] requestBaseBandVersion RM500QGLAAR03A01M4G_BETA_20200107F 1 [Dec 30 2019 17:00:00] -[04-02_04:12:18:539] qmap_settings.rx_urb_size = 16384 -[04-02_04:12:18:539] qmap_settings.ul_data_aggregation_max_datagrams = 16 -[04-02_04:12:18:539] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-02_04:12:18:539] qmap_settings.dl_minimum_padding = 0 -[04-02_04:12:18:550] requestSetLoopBackState(loopback_state=1, replication_factor=14) -[04-02_04:12:18:557] requestGetSIMStatus SIMStatus: SIM_ABSENT -[04-02_04:12:18:560] requestGetProfile[1] ///0 -[04-02_04:12:18:563] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-02_04:12:18:565] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-02_04:12:18:566] ifconfig rmnet_mhi0.1 down -[04-02_04:12:18:571] ifconfig rmnet_mhi0.1 0.0.0.0 -ifconfig: SIOCSIFFLAGS: Network is down -[04-02_04:12:18:575] SetLoopBackInd: loopback_state=1, replication_factor=14 -[04-02_04:12:18:591] requestSetupDataCall WdsConnectionIPv4Handle: 0xe40182a0 -[04-02_04:12:18:601] ifconfig rmnet_mhi0 up -[04-02_04:12:18:607] ifconfig rmnet_mhi0.1 up -[04-02_04:12:18:613] you are use OpenWrt? -[04-02_04:12:18:614] should not calling udhcpc manually? -[04-02_04:12:18:614] should modify /etc/config/network as below? -[04-02_04:12:18:614] config interface wan -[04-02_04:12:18:614] option ifname rmnet_mhi0.1 -[04-02_04:12:18:614] option proto dhcp -[04-02_04:12:18:614] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? -[04-02_04:12:18:614] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 -udhcpc: started, v1.28.3 -udhcpc: sending discover -udhcpc: sending select for 192.168.48.171 -udhcpc: lease of 192.168.48.171 obtained, lease time 7200 -[04-02_04:12:18:809] udhcpc: ifconfig rmnet_mhi0.1 192.168.48.171 netmask 255.255.255.248 broadcast + -[04-02_04:12:18:819] udhcpc: setting default routers: 192.168.48.172 - -root@OpenWrt:~# ifconfig rmnet_mhi0 -rmnet_mhi0 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:608 (608.0 B) TX bytes:672 (672.0 B) - -root@OpenWrt:~# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:UNSPEC HWaddr 02-50-F4-00-00-00-00-00-00-00-00-00-00-00-00-00 - inet addr:192.168.48.171 Mask:255.255.255.248 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:592 (592.0 B) TX bytes:656 (656.0 B) - -# adjust CPU load balancing -root@OpenWrt:~# echo 2 > /sys/class/net/rmnet_mhi0/queues/rx-0/rps_cpus -root@OpenWrt:~# echo 4 > /sys/class/net/rmnet_mhi0.1/queues/rx-0/rps_cpus -root@OpenWrt:~# echo 2000 > /proc/sys/net/core/netdev_max_backlog -root@OpenWrt:~# cat /sys/class/net/rmnet_mhi0/queues/rx-0/rps_cpus -2 -root@OpenWrt:~# cat /sys/class/net/rmnet_mhi0.1/queues/rx-0/rps_cpus -4 -root@OpenWrt:~# cat /proc/sys/net/core/netdev_max_backlog -2000 \ No newline at end of file diff --git a/quectel_MHI/src/log/QXDM_OVER_PCIE.txt b/quectel_MHI/src/log/QXDM_OVER_PCIE.txt deleted file mode 100644 index f7cff56..0000000 --- a/quectel_MHI/src/log/QXDM_OVER_PCIE.txt +++ /dev/null @@ -1,14 +0,0 @@ -root@imx6qsabresd:~# ./QLog -p /dev/mhi_DIAG -s log & -root@imx6qsabresd:~# [000.000]QLog Version: Quectel_QLog_Linux&Android_V1.2.4 -[ 298.597963] [I][mhi_uci_open] Node open, ref counts 1 -[ 298.605601] [I][mhi_uci_open] Starting channel -[ 298.612159] [I][__mhi_prepare_channel] Entered: preparing channel:4 -[ 298.629906] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 298.635415] [I][__mhi_prepare_channel] Chan:4 successfully moved to start state -[ 298.642749] [I][__mhi_prepare_channel] Entered: preparing channel:5 -[ 298.658043] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1 -[ 298.663543] [I][__mhi_prepare_channel] Chan:5 successfully moved to start state -[000.075]open /dev/mhi_DIAG ttyfd = 3 -[000.075]Press CTRL+C to stop catch log. -[000.096]qlog_logfile_create log/20160920_145758_0000.qmdl logfd=4 -[005.268]recv: 0M 70K 490B in 5181 msec diff --git a/quectel_SRPD_PCIE/Makefile b/quectel_SRPD_PCIE/Makefile deleted file mode 100644 index 7e0f6b5..0000000 --- a/quectel_SRPD_PCIE/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (C) 2015 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=sprd_pcie -PKG_VERSION:=1.6 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/kernel.mk -include $(INCLUDE_DIR)/package.mk - -define KernelPackage/sprd_pcie - SUBMENU:=WWAN Support - TITLE:=Kernel pcie driver for SPRD device - FILES:=$(PKG_BUILD_DIR)/sprd_pcie.ko - AUTOLOAD:=$(call AutoLoad,41,sprd_pcie) -endef - -define KernelPackage/sprd_pcie/description - Kernel module for register a custom pcispd platform device. -endef - -MAKE_OPTS:= \ - ARCH="$(LINUX_KARCH)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - CXXFLAGS="$(TARGET_CXXFLAGS)" \ - M="$(PKG_BUILD_DIR)" \ - $(EXTRA_KCONFIG) - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,sprd_pcie)) diff --git a/quectel_SRPD_PCIE/src/Makefile b/quectel_SRPD_PCIE/src/Makefile deleted file mode 100644 index 8fc450f..0000000 --- a/quectel_SRPD_PCIE/src/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# Makefile for the sprd staging modem files -# -EXTRA_CFLAGS += -Wno-error -Wno-packed-bitfield-compat -ccflags-y += -DCONFIG_SPRD_PCIE_EP_DEVICE -DCONFIG_SPRD_SIPA -DCONFIG_SPRD_ETHERNET -obj-m += sprd_pcie.o -sprd_pcie-objs := pcie/sprd_pcie_ep_device.o pcie/pcie_host_resource.o pcie/sprd_pcie_quirks.o sipc/sipc.o sipc/sblock.o sipc/sbuf.o \ - sipc/sipc_debugfs.o sipc/smem.o sipc/smsg.o sipc/spipe.o sipc/spool.o power_manager/power_manager.o \ - sipa/sipa_core.o sipa/sipa_eth.o sipa/sipa_nic.o sipa/sipa_skb_send.o sipa/sipa_skb_recv.o sipa/sipa_dummy.o sipa/sipa_debugfs.o sipa/sipa_dele_cmn.o \ - sipa/sipa_phy_v0/sipa_fifo_irq_hal.o sipa/sipa_phy_v0/sipa_common_fifo_hal.o - -PWD := $(shell pwd) -ifeq ($(ARCH),) -ARCH := $(shell uname -m) -endif -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := -endif -ifeq ($(KDIR),) -KDIR := /lib/modules/$(shell uname -r)/build -endif - -sprd_pcie: clean - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) modules - #cp sprd_pcie.ko /tftpboot/ - -clean: - $(MAKE) ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} -C $(KDIR) M=$(PWD) clean - find . -name *.o.ur-safe | xargs rm -f - -install: sprd_pcie - sudo cp sprd_pcie.ko /lib/modules/${shell uname -r}/kernel/drivers/pci/ - sudo depmod diff --git a/quectel_SRPD_PCIE/src/include/mdm_ctrl.h b/quectel_SRPD_PCIE/src/include/mdm_ctrl.h deleted file mode 100644 index 677b837..0000000 --- a/quectel_SRPD_PCIE/src/include/mdm_ctrl.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef _MDM_CTRL_H -#define _MDM_CTRL_H -/* - * For mcd driver,it offer modem_ctrl_send_abnormal_to_ap - * function for others. It means you can use this function to notify ap, - * some errors has been catched,by this way,ap will triger this error - * and to do something for recovery. - */ - -#include - -enum { - MDM_CTRL_POWER_OFF = 0, - MDM_CTRL_POWER_ON, - MDM_CTRL_WARM_RESET, - MDM_CTRL_COLD_RESET, - MDM_WATCHDOG_RESET, - MDM_ASSERT, - MDM_PANIC, - MDM_CTRL_PCIE_RECOVERY, - MDM_POWER_OFF, - MDM_CTRL_SET_CFG -}; - -void modem_ctrl_send_abnormal_to_ap(int status); -void modem_ctrl_poweron_modem(int on); -void modem_ctrl_enable_cp_event(void); -int modem_ctrl_register_notifier(struct notifier_block *nb); -void modem_ctrl_unregister_notifier(struct notifier_block *nb); - -#endif diff --git a/quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h b/quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h deleted file mode 100644 index 4a42963..0000000 --- a/quectel_SRPD_PCIE/src/include/pcie-rc-sprd.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _PCIE_RC_SPRD_H -#define _PCIE_RC_SPRD_H - -#include - -enum sprd_pcie_event { - SPRD_PCIE_EVENT_INVALID = 0, - SPRD_PCIE_EVENT_LINKDOWN = 0x1, - SPRD_PCIE_EVENT_LINKUP = 0x2, - SPRD_PCIE_EVENT_WAKEUP = 0x4, -}; - -struct sprd_pcie_register_event { - u32 events; - struct platform_device *pdev; - void (*callback)(enum sprd_pcie_event event, void *data); - void *data; -}; - -/* - * SPRD PCIe root complex (e.g. UD710 SoC) can't support PCI hotplug - * capability. Therefore, the standard hotplug driver can't be used. - * - * Whenever one endpoint is plugged or powered on, the EP driver must - * call sprd_pcie_configure_device() in order to add EP device to system - * and probe EP driver. If one endpoint is unplugged or powered off, - * the EP driver must call sprd_pcie_unconfigure_device() in order to - * remove all PCI devices on PCI bus. - * - * return 0 on success, otherwise return a negative number. - */ -/* dumy sprd api */ -static inline int sprd_pcie_configure_device(struct platform_device *pdev) { return 0; } -static inline int sprd_pcie_unconfigure_device(struct platform_device *pdev) { return 0; } -static inline void sprd_pcie_teardown_msi_irq(unsigned int irq) { } -static inline void sprd_pcie_dump_rc_regs(struct platform_device *pdev) { } -static inline int sprd_pcie_register_event(struct sprd_pcie_register_event *reg) { return 0; } -static inline int sprd_pcie_deregister_event(struct sprd_pcie_register_event *reg) { return 0; } - -#ifdef CONFIG_SPRD_PCIE_AER -void sprd_pcie_alloc_irq_vectors(struct pci_dev *dev, int *irqs, int services) { } -#else -static inline void sprd_pcie_alloc_irq_vectors(struct pci_dev *dev, int *irqs, - int services) -{ -} -#endif - -#endif diff --git a/quectel_SRPD_PCIE/src/include/sipa.h b/quectel_SRPD_PCIE/src/include/sipa.h deleted file mode 100644 index 9e4c664..0000000 --- a/quectel_SRPD_PCIE/src/include/sipa.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _SIPA_H_ -#define _SIPA_H_ - -#include -#include -#include - -enum sipa_evt_type { - SIPA_RECEIVE, - SIPA_ENTER_FLOWCTRL, - SIPA_LEAVE_FLOWCTRL, - SIPA_ERROR, -}; - -typedef void (*sipa_notify_cb)(void *priv, enum sipa_evt_type evt, - unsigned int data); - -enum sipa_term_type { - SIPA_TERM_PCIE0 = 0x10, - SIPA_TERM_PCIE1 = 0x11, - SIPA_TERM_PCIE2 = 0x12, - SIPA_TERM_CP0 = 0x4, - SIPA_TERM_CP1 = 0x5, - SIPA_TERM_VCP = 0x6, - - SIPA_TERM_MAX = 0x20, /* max 5-bit register */ -}; - -enum sipa_nic_id { - SIPA_NIC_BB0, - SIPA_NIC_BB1, - SIPA_NIC_BB2, - SIPA_NIC_BB3, - SIPA_NIC_BB4, - SIPA_NIC_BB5, - SIPA_NIC_BB6, - SIPA_NIC_BB7, - SIPA_NIC_BB8, - SIPA_NIC_BB9, - SIPA_NIC_BB10, - SIPA_NIC_BB11, - SIPA_NIC_MAX, -}; - -struct sk_buff *sipa_recv_skb(int *netid, int index); -bool sipa_check_recv_tx_fifo_empty(void); -int sipa_nic_open(enum sipa_term_type src, int netid, - sipa_notify_cb cb, void *priv); -void sipa_nic_close(enum sipa_nic_id nic_id); -int sipa_nic_tx(enum sipa_nic_id nic_id, enum sipa_term_type dst, - int netid, struct sk_buff *skb); -int sipa_nic_rx(int *netid, struct sk_buff **out_skb, int index); -int sipa_nic_rx_has_data(enum sipa_nic_id nic_id); -int sipa_nic_trigger_flow_ctrl_work(enum sipa_nic_id nic_id, int err); - -u32 sipa_nic_get_filled_num(void); -void sipa_nic_restore_irq(void); -void sipa_nic_set_tx_fifo_rp(u32 rptr); -#endif diff --git a/quectel_SRPD_PCIE/src/include/sipc.h b/quectel_SRPD_PCIE/src/include/sipc.h deleted file mode 100644 index fe01b64..0000000 --- a/quectel_SRPD_PCIE/src/include/sipc.h +++ /dev/null @@ -1,1154 +0,0 @@ -/* - * Copyright (C) 2012-2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SIPC_H -#define __SIPC_H - -#include - -/* ****************************************************************** */ -/* SMSG interfaces */ - -/* sipc processor ID definition */ -enum { - SIPC_ID_AP = 0, /* Application Processor */ - SIPC_ID_MINIAP, /* mini AP processor */ - SIPC_ID_CPW, /* WCDMA processor */ - SIPC_ID_WCN, /* Wireless Connectivity */ - SIPC_ID_GNSS, /* Gps processor(gnss) */ - SIPC_ID_PSCP, /* Protocol stack processor */ - SIPC_ID_PM_SYS, /* Power management processor */ - SIPC_ID_NR_PHY, /* New Radio PHY processor */ - SIPC_ID_V3_PHY, /* MODEM v3 PHY processor */ - SIPC_ID_NR, /* Max processor number */ -}; - -#define SIPC_ID_LTE SIPC_ID_PSCP - -/* share-mem ring buffer short message */ -struct smsg { - u8 channel; /* channel index */ - u8 type; /* msg type */ - u16 flag; /* msg flag */ - u32 value; /* msg value */ -}; - -/* smsg channel definition */ -enum { - SMSG_CH_CTRL = 0, /* some emergency control */ - SMSG_CH_COMM, /* general communication channel */ - SMSG_CH_IMSBR_DATA, /* ims bridge data channel */ - SMSG_CH_IMSBR_CTRL, /* ims bridge control channel */ - SMSG_CH_PIPE, /* general pipe channel */ - SMSG_CH_PLOG, /* pipe for debug log/dump */ - SMSG_CH_TTY, /* virtual serial for telephony */ - SMSG_CH_DATA0, /* 2G/3G wirleless data */ - SMSG_CH_DATA1, /* 2G/3G wirleless data */ - SMSG_CH_DATA2, /* 2G/3G wirleless data */ - SMSG_CH_VBC, /* audio conrol channel */ - SMSG_CH_PLAYBACK, /* audio playback channel */ - SMSG_CH_CAPTURE, /* audio capture channel */ - SMSG_CH_MONITOR_AUDIO, /* audio monitor channel */ - SMSG_CH_CTRL_VOIP, /* audio voip conrol channel */ - SMSG_CH_PLAYBACK_VOIP, /* audio voip playback channel */ - SMSG_CH_CAPTURE_VOIP, /* audio voip capture channel */ - SMSG_CH_MONITOR_VOIP, /* audio voip monitor channel */ - SMSG_CH_DATA3, /* 2G/3G wirleless data */ - SMSG_CH_DATA4, /* 2G/3G wirleless data */ - SMSG_CH_DATA5, /* 2G/3G wirleless data */ - SMSG_CH_DIAG, /* pipe for debug log/dump */ - SMSG_CH_PM_CTRL, /* power management control */ - SMSG_CH_DUAL_SIM_PLUG, /* dual sim plug channel */ - SMSG_CH_END /* will not allow add channel in here */ -}; - -/* smsg channel definition */ -enum { - /* 2G/3G wirleless data, channel 24~39 */ - SMSG_CH_DATA_BASE = 24, - SMSG_CH_DATA6 = SMSG_CH_DATA_BASE, - SMSG_CH_DATA7, - SMSG_CH_DATA8, - SMSG_CH_DATA9, - SMSG_CH_DATA10, - SMSG_CH_DATA11, - SMSG_CH_DATA12, - SMSG_CH_DATA13, - - /* general pipe channel, channel 40~59 */ - SMSG_CH_PIPE_BASE = 40, - SMSG_CH_NV = SMSG_CH_PIPE_BASE, - SMSG_CH_DVFS, - SMSG_CH_PIPE2, - SMSG_CH_PIPE3, - - /* pipe for debug log/dump channel 60~79 */ - SMSG_CH_PLOG_BASE = 60, - SMSG_CH_PLOG0 = SMSG_CH_PLOG_BASE, - SMSG_CH_PLOG1, - SMSG_CH_PLOG2, - SMSG_CH_PLOG3, - - /* virtual serial for telephony, channel 80~99*/ - SMSG_CH_TTY_BASE = 80, - SMSG_CH_TTY0 = SMSG_CH_TTY_BASE, - SMSG_CH_TTY1, - SMSG_CH_TTY2, - SMSG_CH_TTY3, - - /* some emergency control, channel 100~119 */ - SMSG_CH_CTRL_BASE = 100, - SMSG_CH_PMSYS_DBG = SMSG_CH_CTRL_BASE, - SMSG_CH_CTRL1, - SMSG_CH_CTRL2, - SMSG_CH_CTRL3, - - /* general communication, channel 120~129 */ - SMSG_CH_COMM_BASE = 120, - SMSG_CH_COMM_SIPA = SMSG_CH_COMM_BASE, - SMSG_CH_COMM1, - SMSG_CH_COMM2, - SMSG_CH_COMM3, - - /* audio channel, channel 130 ~149 */ - SMSG_CH_AUDIO_BASE = 130, - SMSG_CH_AGDSP_ACCESS = SMSG_CH_AUDIO_BASE,/* audio conrol channel */ - SMSG_CH_PLAYBACK_DEEP, - SMSG_CH_AUDIO2, - SMSG_CH_AUDIO3, - - /* VOIP channel, channel 150 ~169 */ - SMSG_CH_VOIP_BASE = 150, - SMSG_CH_VOIP0 = SMSG_CH_VOIP_BASE,/* audio voip conrol channel */ - SMSG_CH_VOIP_DEEP, /* audio voip playback channel */ - SMSG_CH_VOIP2, /* audio voip capture channel */ - SMSG_CH_VOIP3, /* audio voip monitor channel */ - - /* RPC server channel, channel 170~189 */ - SMSG_CH_RPC_BASE = 170, - SMSG_CH_RPC0 = SMSG_CH_RPC_BASE, - SMSG_CH_RPC1, - SMSG_CH_RPC2, - SMSG_CH_RPC3, - - /* RESERVE group 1, channel 190 ~209 */ - SMSG_CH_RESERVE1_BASE = 190, - - /* RESERVE group 2, channel 210 ~129 */ - SMSG_CH_RESERVE2_BASE = 210, - - /* RESERVE group 3, channel 230 ~244 */ - SMSG_CH_RESERVE3_BASE = 230, - - /* RESERVE group 4, channel 245 ~254 */ - SMSG_CH_RESERVE4_BASE = 245, - - /* total channel number 255, the max chanel number is 254*/ - SMSG_CH_NR = 255 -}; -#define INVALID_CHANEL_INDEX SMSG_CH_NR - -/* modem type */ -enum { - SOC_MODEM = 0, - PCIE_MODEM, -}; - -/* only be configed in sipc_config is valid channel */ -struct sipc_config { - u8 channel; - char *name; -}; - -static const struct sipc_config sipc_cfg[] = { - {SMSG_CH_CTRL, "com control"}, /* chanel 0 */ - {SMSG_CH_COMM, "com communication"}, /* chanel 1 */ - {SMSG_CH_PM_CTRL, "pm contrl"}, /* chanel 22 */ - {SMSG_CH_PMSYS_DBG, "pm debug contrl"}, /* chanel 100 */ - {SMSG_CH_DUAL_SIM_PLUG, "dual sim plug"}, /* chanel 23 */ - {SMSG_CH_PIPE, "pipe0"}, /* chanel 4 */ - {SMSG_CH_PLOG, "plog"}, /* chanel 5 */ - {SMSG_CH_DIAG, "diag"}, /* chanel 21 */ - {SMSG_CH_TTY, "stty chanel"}, /* chanel 6 */ - {SMSG_CH_DATA0, "seth0"}, /* chanel 7 */ - {SMSG_CH_DATA1, "seth1"}, /* chanel 8 */ - {SMSG_CH_DATA2, "seth2"}, /* chanel 9 */ - {SMSG_CH_DATA3, "seth3"}, /* chanel 18 */ - {SMSG_CH_DATA4, "seth4"}, /* chanel 19 */ - {SMSG_CH_DATA5, "seth5"}, /* chanel 20 */ - {SMSG_CH_DATA6, "seth6"}, /* chanel 24 */ - {SMSG_CH_DATA7, "seth7"}, /* chanel 25 */ - {SMSG_CH_DATA8, "seth8"}, /* chanel 26 */ - {SMSG_CH_DATA9, "seth9"}, /* chanel 27 */ - {SMSG_CH_DATA10, "seth10"}, /* chanel 28 */ - {SMSG_CH_DATA11, "seth11"}, /* chanel 29 */ - {SMSG_CH_DATA12, "seth12"}, /* chanel 30 */ - {SMSG_CH_DATA13, "seth13"}, /* chanel 31 */ - {SMSG_CH_VBC, "audio control"}, /* chanel 10 */ - {SMSG_CH_PLAYBACK, "audio playback"}, /* chanel 11 */ - {SMSG_CH_CAPTURE, "audio capture"}, /* chanel 12 */ - {SMSG_CH_MONITOR_AUDIO, "audio monitor"}, /* chanel 13 */ - {SMSG_CH_AGDSP_ACCESS, "agdsp access"}, /* chanel 13 */ - {SMSG_CH_CTRL_VOIP, "VOIP conrol"}, /* chanel 14 */ - {SMSG_CH_PLAYBACK_VOIP, "VOIP playback"}, /* chanel 15 */ - {SMSG_CH_CAPTURE_VOIP, "VOIP capture"}, /* chanel 16 */ - {SMSG_CH_MONITOR_VOIP, "VOIP monitor"}, /* chanel 17 */ - {SMSG_CH_PLAYBACK_DEEP, "audio playback deep"}, /*channel 131*/ - {SMSG_CH_IMSBR_DATA, "imsbr data"}, /* chanel 2 */ - {SMSG_CH_IMSBR_CTRL, "imsbr control"}, /* channel 3 */ - {SMSG_CH_VOIP_DEEP, "audio voip deep"}, /*channel 151*/ - {SMSG_CH_DVFS, "dvfs"}, /* channel 41 */ - {SMSG_CH_COMM_SIPA, "sipa"}, /* channel 120 */ - {SMSG_CH_NV, "nvsync"}, /* channel 40 */ -}; - -#define SMSG_VALID_CH_NR (sizeof(sipc_cfg)/sizeof(struct sipc_config)) - - -/* smsg type definition */ -enum { - SMSG_TYPE_NONE = 0, - SMSG_TYPE_OPEN, /* first msg to open a channel */ - SMSG_TYPE_CLOSE, /* last msg to close a channel */ - SMSG_TYPE_DATA, /* data, value=addr, no ack */ - SMSG_TYPE_EVENT, /* event with value, no ack */ - SMSG_TYPE_CMD, /* command, value=cmd */ - SMSG_TYPE_DONE, /* return of command */ - SMSG_TYPE_SMEM_ALLOC, /* allocate smem, flag=order */ - SMSG_TYPE_SMEM_FREE, /* free smem, flag=order, value=addr */ - SMSG_TYPE_SMEM_DONE, /* return of alloc/free smem */ - SMSG_TYPE_FUNC_CALL, /* RPC func, value=addr */ - SMSG_TYPE_FUNC_RETURN, /* return of RPC func */ - SMSG_TYPE_DIE, - SMSG_TYPE_DFS, - SMSG_TYPE_DFS_RSP, - SMSG_TYPE_ASS_TRG, - SMSG_TYPE_HIGH_OFFSET, /* client sipc get high offset from host */ - SMSG_TYPE_NR, /* total type number */ -}; - -/* flag for OPEN/CLOSE msg type */ -#define SMSG_OPEN_MAGIC 0xBEEE -#define SMSG_CLOSE_MAGIC 0xEDDD - -/** -* sipc_get_wakeup_flag -* after the wakeup flag be set, the fist smsg will be print -* @parameters: void -* @return: int -*/ -int sipc_get_wakeup_flag(void); - -/** -* sipc_set_wakeup_flag -* after the wakeup flag be set, the fist smsg will be print -* @parameters: void -* @return: no return value -*/ -void sipc_set_wakeup_flag(void); - -/** -* sipc_clear_wakeup_flag -* clear the wake up flag -* @parameters: void -* @return: no return value -*/ -void sipc_clear_wakeup_flag(void); - -/** - * smsg_ch_open -- open a channel for smsg - * - * @dst: dest processor ID - * @channel: channel ID - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_ch_open(u8 dst, u8 channel, int timeout); - -/** - * smsg_ch_close -- close a channel for smsg - * - * @dst: dest processor ID - * @channel: channel ID - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_ch_close(u8 dst, u8 channel, int timeout); - - /** - * smsg_senddie -- send a MSG_TYPE_DIE message to pubcp - * - * @dst: dest processor ID - * @return: 0 on success, <0 on failure - */ -int smsg_senddie(u8 dst); - -/** - * smsg_send -- send smsg - * - * @dst: dest processor ID - * @msg: smsg body to be sent - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_send(u8 dst, struct smsg *msg, int timeout); - -/** - * smsg_recv -- poll and recv smsg - * - * @dst: dest processor ID - * @msg: smsg body to be received, channel should be filled as input - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int smsg_recv(u8 dst, struct smsg *msg, int timeout); - -/** - * sipc_channel2index - * - * only be configed in sipc_config is valid channel - * @ch: channel number - * @return: channel index ,if return index is INVALID_CHANEL_INDEX , - * it indicate it is a invalid chanel - */ -u8 sipc_channel2index(u8 ch); - -int smsg_ch_wake_unlock(u8 dst, u8 channel); - -#if defined(CONFIG_DEBUG_FS) -void sipc_debug_putline(struct seq_file *m, char c, int n); -#endif - -/* quickly fill a smsg body */ -static inline void smsg_set(struct smsg *msg, u8 channel, - u8 type, u16 flag, u32 value) -{ - msg->channel = channel; - msg->type = type; - msg->flag = flag; - msg->value = value; -} - -/* ack an open msg for modem recovery */ -static inline void smsg_open_ack(u8 dst, u16 channel) -{ - struct smsg mopen; - - pr_info("%s: channel %d-%d!\n", __func__, dst, channel); - smsg_set(&mopen, channel, SMSG_TYPE_OPEN, SMSG_OPEN_MAGIC, 0); - smsg_send(dst, &mopen, -1); -} - -/* ack an close msg for modem recovery */ -static inline void smsg_close_ack(u8 dst, u16 channel) -{ - struct smsg mclose; - - pr_info("%s: channel %d-%d!\n", __func__, dst, channel); - smsg_set(&mclose, channel, SMSG_TYPE_CLOSE, SMSG_CLOSE_MAGIC, 0); - smsg_send(dst, &mclose, -1); -} - -/* ****************************************************************** */ -/* SMEM interfaces */ -/** - * smem_get_area -- get sipc smem - * - * @dst: dest processor ID - * @base: base pointer - * @size: size pointer - * @return: 0 success, < 0 failed - */ -int smem_get_area(u8 dst, u32 *base, u32 *size); - -/** - * smem_alloc -- allocate shared memory block - * - * @dst: dest processor ID - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -u32 smem_alloc(u8 dst, u32 size); - -/** - * smem_free -- free shared memory block - * - * @dst: dest processor ID - * @addr: smem phys addr to be freed - * @order: size to be freed - */ -void smem_free(u8 dst, u32 addr, u32 size); - -/** - * shmem_ram_unmap -- for sipc unmap ram address - * - * @mem: vir mem - */ -void shmem_ram_unmap(u8 dst, const void *mem); - -/** - * shmem_ram_vmap_nocache -- for sipc map ram address - * - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *shmem_ram_vmap_nocache(u8 dst, phys_addr_t start, size_t size); - -/** - * shmem_ram_vmap_cache -- for sipc map ram address - * - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *shmem_ram_vmap_cache(u8 dst, phys_addr_t start, size_t size); - -void smem_free(u8 dst, u32 addr, u32 size); - -/** - * modem_ram_unmap -- for modem unmap ram address - * - * @mem: vir mem - * @modem_type: soc modem, pcie modem - */ -void modem_ram_unmap(u32 modem_type, const void *mem); - -/** - * shmem_ram_vmap_nocache -- for modem map ram address - * - * @modem_type: soc modem, pcie modem - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *modem_ram_vmap_nocache(u32 modem_type, phys_addr_t start, size_t size); - -/** - * modem_ram_vmap_cache -- for modem map ram address - * - * @modem_type: soc modem, pcie modem - * @start: start address - * @size: size to be allocated, page-aligned - * @return: phys addr or 0 if failed - */ -void *modem_ram_vmap_cache(u32 modem_type, phys_addr_t start, size_t size); -/** - * sbuf_set_no_need_wake_lock - * - * @dst: dest processor ID - * @bufnum: which buffer to be set - * @return: none - */ - -void sbuf_set_no_need_wake_lock(u8 dst, u8 channel, u32 bufnum); - -/** - * sbuf_create -- create pipe ring buffers on a channel - * - * @dst: dest processor ID - * @channel: channel ID - * @txbufsize: tx buffer size - * @rxbufsize: rx buffer size - * @bufnum: how many buffers to be created - * @return: 0 on success, <0 on failure - */ - -int sbuf_create(u8 dst, u8 channel, u32 bufnum, - u32 txbufsize, u32 rxbufsize); - -/** - * sbuf_destroy -- destroy the pipe ring buffers on a channel - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -void sbuf_destroy(u8 dst, u8 channel); -void sbuf_down(u8 dst, u8 channel); - -/** - * sbuf_write -- write data to a sbuf - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buffer ID - * @buf: data to be written - * @len: data length - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: written bytes on success, <0 on failure - */ -int sbuf_write(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout); - -/** - * sbuf_read -- write data to a sbuf - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buffer ID - * @buf: data to be written - * @len: data length - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: read bytes on success, <0 on failure - */ -int sbuf_read(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout); - -/** - * sbuf_poll_wait -- poll sbuf read/write, used in spipe driver - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buffer ID - * @file: struct file handler - * @wait: poll table - * @return: POLLIN or POLLOUT - */ -int sbuf_poll_wait(u8 dst, u8 channel, u32 bufid, - struct file *file, poll_table *wait); - -/** - * sbuf_status -- get sbuf status - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 when ready, <0 when broken - */ -int sbuf_status(u8 dst, u8 channel); - -#define SBUF_NOTIFY_READY 0x00 -#define SBUF_NOTIFY_READ 0x01 -#define SBUF_NOTIFY_WRITE 0x02 -/** - * sbuf_register_notifier -- register a callback that's called - * when a tx sbuf is available or a rx sbuf is received. - * non-blocked sbuf_read can be called. - * - * @dst: dest processor ID - * @channel: channel ID - * @bufid: buf ID - * @handler: a callback handler - * @event: NOTIFY_READ, NOTIFY_WRITE, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sbuf_register_notifier(u8 dst, u8 channel, u32 bufid, - void (*handler)(int event, void *data), void *data); - - -int sipc_init(void); -void sipc_exit(void); - -int spipe_init(void); -void spipe_exit(void); -void spipe_device_down(void); -void spool_device_down(void); - -int spool_init(void); -void spool_exit(void); - -int modem_power_manager_init(void); -void modem_power_manager_exit(void); - -#if 0 -int modem_ctrl_init(void); -void modem_ctrl_exit(void); -#endif - -int sipc_init_debugfs(void); - -/* ****************************************************************** */ -/* SBLOCK interfaces */ - -/* sblock structure: addr is the uncached virtual address */ -struct sblock { - void *addr; - u32 length; -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX - u16 index; - u16 offset; -#endif -}; - -/** - * sblock_create -- create sblock manager on a channel - * - * @dst: dest processor ID - * @channel: channel ID - * @txblocknum: tx block number - * @txblocksize: tx block size - * @rxblocknum: rx block number - * @rxblocksize: rx block size - * @return: 0 on success, <0 on failure - */ -int sblock_create(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize); - -/** - * sblock_create_ex -- merge sblock_create and block_register_notifier - * in one function - * - * @dst: dest processor ID - * @channel: channel ID - * @txblocknum: tx block number - * @txblocksize: tx block size - * @rxblocknum: rx block number - * @rxblocksize: rx block size - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sblock_create_ex(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize, - void (*handler)(int event, void *data), void *data); - -/* sblock_pcfg_create -- create preconfigured SBLOCK channel. - * - * @dst: dest processor ID - * @channel: channel ID - * @tx_blk_num: tx block number - * @tx_blk_sz: tx block size - * @rx_blk_num: rx block number - * @rx_blk_sz: rx block size - * @return: 0 on success, <0 on failure - * - * The function only allocates the memory for the channel, and will not - * open the channel. The client shall open the channel using - * sblock_pcfg_open and close the channel using sblock_close. - */ -int sblock_pcfg_create(u8 dst, u8 channel, - u32 tx_blk_num, u32 tx_blk_sz, - u32 rx_blk_num, u32 rx_blk_sz); - -/* sblock_pcfg_open -- request to open preconfigured SBLOCK channel. - * - * @dst: dest processor ID - * @channel: channel ID - * @notifier: the event notification callback function. This function can - * not sleep. If this parameter is NULL, no event will be - * reported. - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @client: opaque data passed to the receiver - * @return: if the channel is established, return 0; if the open procedure - * is started and not finished, return SIPC_ERR_IN_PROGRESS; - * otherwise return a negative error code. - * - * The function starts the open procedure. If the open procedure is not - * finished when the function returns, the SBLOCK system will report - * the open result later through the notifier callback. - */ -int sblock_pcfg_open(uint8_t dest, uint8_t channel, - void (*notifier)(int event, void *client), - void *client); - -/* sblock_close -- request to close SBLOCK channel. - * - * @dst: dest processor ID - * @channel: channel ID - * @return: if the channel is closed, return 0; if the close procedure - * is started and not finished, return SIPC_ERR_IN_PROGRESS; - * otherwise return a negative error code. - * - * The function starts the close procedure. If the close procedure is not - * finished when the function returns, the SBLOCK system will report - * the close result later through the notification callback that the - * client set by sblock_pcfg_open. - */ -int sblock_close(uint8_t dest, uint8_t channel); - -/* sblock_get_smem_cp_addr - get the shared memory CP address. - * @dest: destination ID - * @channel: channel number - * @paddr: pointer to the variable to receive the address. - */ -int sblock_get_smem_cp_addr(uint8_t dest, uint8_t channel, - uint32_t *paddr); -/** - * sblock_destroy -- destroy sblock manager on a channel - * - * @dst: dest processor ID - * @channel: channel ID - */ -void sblock_destroy(u8 dst, u8 channel); -void sblock_down(u8 dst, u8 channel); - -#define SBLOCK_NOTIFY_GET 0x01 -#define SBLOCK_NOTIFY_RECV 0x02 -#define SBLOCK_NOTIFY_STATUS 0x04 -#define SBLOCK_NOTIFY_OPEN 0x08 -#define SBLOCK_NOTIFY_CLOSE 0x10 -#define SBLOCK_NOTIFY_OPEN_FAILED 0x20 - -/** - * sblock_register_notifier -- register a callback that's called - * when a tx sblock is available or a rx block is received. - * non-blocked sblock_get or sblock_receive can be called. - * - * @dst: dest processor ID - * @channel: channel ID - * @handler: a callback handler - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sblock_register_notifier(u8 dst, u8 channel, - void (*handler)(int event, void *data), void *data); - -/** - * sblock_get -- get a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a gotten sblock pointer - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int sblock_get(u8 dst, u8 channel, struct sblock *blk, int timeout); - -/** - * sblock_send -- send a sblock with smsg, it should be from sblock_get - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: the sblock to be sent - * @return: 0 on success, <0 on failure - */ -int sblock_send(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_send_prepare -- send a sblock without smsg, - * it should be from sblock_get - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: the sblock to be sent - * @return: 0 on success, <0 on failure - */ -int sblock_send_prepare(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_send_finish -- trigger an smsg to notify that sblock has been sent - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sblock_send_finish(u8 dst, u8 channel); - -/** - * sblock_receive -- receive a sblock, it should be released after it's handled - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a received sblock pointer - * @timeout: milliseconds, 0 means no wait, -1 means unlimited - * @return: 0 on success, <0 on failure - */ -int sblock_receive(u8 dst, u8 channel, - struct sblock *blk, int timeout); - -/** - * sblock_release -- release a sblock from reveiver - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sblock_release(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_get_arrived_count -- get the count of sblock(s) arrived at - * AP (sblock_send on CP) but not received (sblock_receive on AP). - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sblock_get_arrived_count(u8 dst, u8 channel); - - - -/** - * sblock_get_free_count -- get the count of available sblock(s) resident in - * sblock pool on AP. - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sblock_get_free_count(u8 dst, u8 channel); - - -/** - * sblock_put -- put a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: sblock pointer - * @return: void - */ -void sblock_put(u8 dst, u8 channel, struct sblock *blk); - -/** - * sblock_poll_wait -- poll sblock read/write - * - * @dst: dest processor ID - * @channel: channel ID - * @filp: strcut file handle - * @wait: poll table - * @return: POLLIN or POLLOUT - */ -unsigned int sblock_poll_wait(u8 dst, u8 channel, struct file *filp, poll_table *wait); - -/** - * sblock_query -- sblock query status - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sblock_query(u8 dst, u8 channel); - - -/* ****************************************************************** */ - -#define SIPX_ACK_BLK_LEN (100) - -/** - * sipx_chan_create -- create a sipx channel - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sipx_chan_create(u8 dst, u8 channel); - -/** - * sipx_chan_destroy -- destroy seblock manager on a channel - * - * @dst: dest processor ID - * @channel: channel ID - */ -int sipx_chan_destroy(u8 dst, u8 channel); - -/** - * sipx_get_ack_blk_len -- get sipx ack block max length - * - * @dst: dest processor ID - * @return: length - */ -u32 sipx_get_ack_blk_len(u8 dst); - -/** - * sipx_get -- get a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a gotten sblock pointer - * @is_ack: if want to get block for ack packet - * @return: 0 on success, <0 on failure - */ -int sipx_get(u8 dst, u8 channel, struct sblock *blk, int is_ack); - -/** - * sipx_chan_register_notifier -- register a callback that's called - * when a tx sblock is available or a rx block is received. - * on-blocked sblock_get or sblock_receive can be called. - * - * @dst: dest processor ID - * @channel: channel ID - * @handler: a callback handler - * @event: SBLOCK_NOTIFY_GET, SBLOCK_NOTIFY_RECV, or both - * @data: opaque data passed to the receiver - * @return: 0 on success, <0 on failure - */ -int sipx_chan_register_notifier(u8 dst, u8 channel, - void (*handler)(int event, void *data), void *data); - -/** - * sipx_send -- send a sblock with smsg, it should be from seblock_get - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: the sblock to be sent - * @return: 0 on success, <0 on failure - */ -int sipx_send(u8 dst, u8 channel, struct sblock *blk); - -/** - * sipx_flush -- trigger an smsg to notify that sblock has been sent - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sipx_flush(u8 dst, u8 channel); - -/** - * sipx_receive -- receive a sblock, it should be released after it's handled - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: return a received sblock pointer - * @return: 0 on success, <0 on failure - */ -int sipx_receive(u8 dst, u8 channel, struct sblock *blk); - -/** - * sipx_release -- release a sblock from reveiver - * - * @dst: dest processor ID - * @channel: channel ID - * @return: 0 on success, <0 on failure - */ -int sipx_release(u8 dst, u8 channel, struct sblock *blk); - -/** - * sipx_get_arrived_count -- get the count of sblock(s) arrived at - * AP (sblock_send on CP) but not received (sblock_receive on AP). - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sipx_get_arrived_count(u8 dst, u8 channel); - -/** - * sipx_get_free_count -- get the count of available sblock(s) resident in - * normal pool on AP. - * - * @dst: dest processor ID - * @channel: channel ID - * @return: >=0 the count of blocks - */ -int sipx_get_free_count(u8 dst, u8 channel); - -/** - * sipx_put -- put a free sblock for sender - * - * @dst: dest processor ID - * @channel: channel ID - * @blk: sblock pointer - * @return: void - */ -int sipx_put(u8 dst, u8 channel, struct sblock *blk); - -/* ****************************************************************** */ - -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX - -#define SBLOCK_CREATE(dst, channel,\ - txblocknum, txblocksize, txpoolsize, \ - rxblocknum, rxblocksize, rxpoolsize) \ -sipx_chan_create(dst, channel) - - -#define SBLOCK_DESTROY(dst, channel) \ - sipx_chan_destroy(dst, channel) - -#define SBLOCK_GET(dst, channel, blk, ack, timeout) \ - sipx_get(dst, channel, blk, ack) - -#define SBLOCK_REGISTER_NOTIFIER(dst, channel, handler, data) \ - sipx_chan_register_notifier(dst, channel, handler, data) - -#define SBLOCK_SEND(dst, channel, blk) \ - sipx_send(dst, channel, blk) - -#define SBLOCK_SEND_PREPARE(dst, channel, blk) \ - sipx_send(dst, channel, blk) - -#define SBLOCK_SEND_FINISH(dst, channel)\ - sipx_flush(dst, channel) - -#define SBLOCK_RECEIVE(dst, channel, blk, timeout) \ - sipx_receive(dst, channel, blk) - -#define SBLOCK_RELEASE(dst, channel, blk) \ - sipx_release(dst, channel, blk) - -#define SBLOCK_GET_ARRIVED_COUNT(dst, channel) \ - sipx_get_arrived_count(dst, channel) - -#define SBLOCK_GET_FREE_COUNT(dst, channel) \ - sipx_get_free_count(dst, channel) - -#define SBLOCK_PUT(dst, channel, blk) \ - sipx_put(dst, channel, blk) - - -#else /* CONFIG_SPRD_SIPC_ZERO_COPY_SIPX */ - -#define SBLOCK_CREATE(dst, channel,\ - txblocknum, txblocksize, txpoolsize, \ - rxblocknum, rxblocksize, rxpoolsize) \ -sblock_create(dst, channel,\ - txblocknum, txblocksize,\ - rxblocknum, rxblocksize) - -#define SBLOCK_DESTROY(dst, channel) \ - sblock_destroy(dst, channel) - -#define SBLOCK_GET(dst, channel, blk, ack, timeout) \ - sblock_get(dst, channel, blk, timeout) - -#define SBLOCK_REGISTER_NOTIFIER(dst, channel, handler, data) \ - sblock_register_notifier(dst, channel, handler, data) - -#define SBLOCK_SEND(dst, channel, blk) \ - sblock_send(dst, channel, blk) - -#define SBLOCK_SEND_PREPARE(dst, channel, blk) \ - sblock_send_prepare(dst, channel, blk) - -#define SBLOCK_SEND_FINISH(dst, channel)\ - sblock_send_finish(dst, channel) - -#define SBLOCK_RECEIVE(dst, channel, blk, timeout) \ - sblock_receive(dst, channel, blk, timeout) - -#define SBLOCK_RELEASE(dst, channel, blk) \ - sblock_release(dst, channel, blk) - -#define SBLOCK_GET_ARRIVED_COUNT(dst, channel) \ - sblock_get_arrived_count(dst, channel) - -#define SBLOCK_GET_FREE_COUNT(dst, channel) \ - sblock_get_free_count(dst, channel) - -#define SBLOCK_PUT(dst, channel, blk) \ - sblock_put(dst, channel, blk) - -#endif /* CONFIG_SPRD_SIPC_ZERO_COPY_SIPX */ - -#ifdef CONFIG_ARM64 -/** - * unalign_copy_from_user -- unaligned data accesses to addresses - * marked as device will always trigger an exception, this fuction - * can avoid this exception - * - * @to: dest, normal memory - * @from: src, device memory and alignment access must be considered - * @n: bytes - * @return: bytes not copied - */ -static inline unsigned long unalign_copy_to_user(void __user *to, - const void *from, - unsigned long n) -{ - /* from is not 8 byte aligned and n is less than 16 bytes */ - if (((unsigned long)from & 7) && (n < 16)) { - while (n) { - if (copy_to_user(to++, from++, 1)) - break; - n--; - } - return n; - } - - return copy_to_user(to, from, n); -} - -/** - * unalign_copy_from_user -- unaligned data accesses to addresses - * marked as device will always trigger an exception, this fuction - * can avoid this exception - * - * @to: dest, device memory and alignment access must be considered - * @from: src, normal memory - * @n: bytes - * @return: bytes not copied - */ -static inline unsigned long unalign_copy_from_user(void *to, - const void __user *from, - unsigned long n) -{ - unsigned c1, c2, c3; - - /* to is 8 byte aligned and n is less than 16 bytes */ - c1 = !((unsigned long)to & 0x7) && (n < 16); - if (c1) - return copy_from_user(to, from, n); - - /* to and from are 8 byte aligned */ - c2 = !((unsigned long)to & 0x7) && !((unsigned long)from & 0x7); - if (c2) - return copy_from_user(to, from, n); - - /* to and from are the same offset and n is more than 15 bytes */ - c3 = !(((unsigned long)to ^ (unsigned long)from) & 0x7) && (n > 15); - if (c3) - return copy_from_user(to, from, n); - - while (n) { - if (copy_from_user(to++, from++, 1)) - break; - n--; - } - - return n; -} - -static inline void unalign_memcpy(void *to, const void *from, size_t n) -{ - if (((unsigned long)to & 7) == ((unsigned long)from & 7)) { - while (((unsigned long)from & 7) && n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - memcpy(to, from, n); - } else if (((unsigned long)to & 3) == ((unsigned long)from & 3)) { - while (((unsigned long)from & 3) && n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - while (n >= 4) { - *(u32 *)(to) = *(u32 *)(from); - to += 4; - from += 4; - n -= 4; - } - while (n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - } else { - while (n) { - *(char *)(to++) = *(char *)(from++); - n--; - } - } -} -#else -static inline unsigned long unalign_copy_to_user(void __user *to, - const void *from, - unsigned long n) -{ - return copy_to_user(to, from, n); -} -static inline unsigned long unalign_copy_from_user(void *to, - const void __user *from, - unsigned long n) -{ - return copy_from_user(to, from, n); -} -static inline void *unalign_memcpy(void *to, const void *from, size_t n) -{ - return memcpy(to, from, n); -} -#endif - -#endif diff --git a/quectel_SRPD_PCIE/src/include/sipc_big_to_little.h b/quectel_SRPD_PCIE/src/include/sipc_big_to_little.h deleted file mode 100644 index d70e61b..0000000 --- a/quectel_SRPD_PCIE/src/include/sipc_big_to_little.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SIPC_BIG_TO_LITTLE_H -#define __SIPC_BIG_TO_LITTLE_H -//#define CONFIG_SIPC_BIG_TO_LITTLE /* sipc little */ - -#define BL_READB(addr) \ - ({ unsigned char __v = (*(volatile unsigned char *) (addr)); __v; }) -#define BL_WRITEB(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b)) - -#define BL_GETB(v) ((v)) -#define BL_SETB(v, b) ((v) = (b)) - - -#ifdef CONFIG_SIPC_BIG_TO_LITTLE -/* little 0x78563412 - 0x12 - 0x34 - 0x56 - 0x78 - read: - big: 0x12345678==>0x78563412 - write: 0x78563412 ===> 0x12345678*/ -#define BL_READW(addr) \ - ({ unsigned short __t = (*(volatile unsigned short *) (addr)); \ - unsigned short __v = ((__t & 0x00ff) << 8) + ((__t & 0xff00) >> 8); \ - __v; }) -#define BL_READL(addr) \ - ({ unsigned int __t = (*(volatile unsigned int *) (addr)); \ - unsigned int __v = ((__t & 0x000000ff) << 24) + ((__t & 0x0000ff00) << 8) + \ - ((__t & 0x00ff0000) >> 8) + ((__t & 0xff000000) >> 24); \ - __v; }) - -#define BL_WRITEW(b,addr) \ - ({ unsigned short __v = (((b) & 0x00ff) << 8) + (((b) & 0xff00) >> 8); \ - (*(volatile unsigned short *) (addr)) = __v; }) - -#define BL_WRITEL(b,addr) \ - ({ unsigned int __v = (((b) & 0x000000ff) << 24) + (((b) & 0xff00) >> 8) + \ - (((b) & 0x00ff0000) >> 8) + (((b) & 0xff000000) >> 24); \ - (*(volatile unsigned int *) (addr)) = __v; }) - -#define BL_GETL(v) \ -({unsigned int __v = (((v) & 0x000000ff) << 24) + (((v) & 0x0000ff00) << 8) + \ - (((v) & 0x00ff0000) >> 8) + (((v) & 0xff000000) >> 24); \ - __v; }) -#define BL_SETL(v, b) \ - ((v) = (((b) & 0x000000ff) << 24) + (((b) & 0x0000ff00) << 8) + \ - (((b) & 0x00ff0000) >> 8) + (((b) & 0xff000000) >> 24)) -#define BL_GETW(v) \ - ({unsigned int __v = (((v) & 0x00ff) << 8) + (((v) & 0xff00) >> 8); \ - __v; }) -#define BL_SETW(v, b) \ - ((v) = (((b) & 0x00ff) << 8) + (((b) & 0xff00) >> 8)) - -#else -#define BL_GETW(v) v -#define BL_GETL(v) v - -#define BL_SETW(v, b) ((v) = (b)) -#define BL_SETL(v, b) ((v) = (b)) - -#define BL_READW(addr) \ - ({ unsigned short __v = (*(volatile unsigned short *) (addr)); __v; }) -#define BL_READL(addr) \ - ({ unsigned int __v = (*(volatile unsigned int *) (addr)); __v; }) - -#define BL_WRITEW(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b)) -#define BL_WRITEL(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b)) - -#endif - -#endif - diff --git a/quectel_SRPD_PCIE/src/include/sprd_mpm.h b/quectel_SRPD_PCIE/src/include/sprd_mpm.h deleted file mode 100644 index f9ffe74..0000000 --- a/quectel_SRPD_PCIE/src/include/sprd_mpm.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - /* MPM: modem power manger - * PMS: power manage source which be used to request - * a modem power manage resource. - */ -#ifndef _SPRD_MPM_H -#define _SPRD_MPM_H -/* - * MPM modem powermanger source state define, - * if in idle state, we can release - * the related resources(such as pcie) of modem. - */ -enum { - SPRD_MPM_IDLE = 0, - SPRD_MPM_BUSY -}; - -/* - * @sprd_pms: the power manager source data struct, - * can usd it to request wake lock or request modem resource. - * - * @name: the name of a pms. - * @data: the point of MPM. - * @multitask: whether to support multitasking, default is false. - * false, the source can only be used in single task context. - * true, the source can be used multitask context. - * @awake: whether stay awake. - * @awake_cnt: total awake times. - * @pre_awake_cnt pre_awake_cnt. - * @active_cnt: the active counter of the pms. - * @expires: the timer expires value. - * @active_lock: use for protect the active_cnt member. - * @expires_lock: use for protect expires member. - * @entry: an entry of all pms list. - * @wake_timer: used for delay release wakelock. - */ -struct sprd_pms { - const char *name; - void *data; - bool multitask; - bool awake; - unsigned int awake_cnt; - unsigned int pre_awake_cnt; - unsigned int active_cnt; - unsigned long expires; - spinlock_t active_lock; - spinlock_t expires_lock; - struct list_head entry; - struct timer_list wake_timer; -}; - -/** - * sprd_mpm_create - create a modem powermanger source instacnce. - * - * @dst, which mpm (PSCP, SP, WCN, etc.) will be created. - * @later_idle, will release resource later (in ms). - */ -int sprd_mpm_create(unsigned int dst, - const char *name, - unsigned int later_idle); - -/** - * sprd_mpm_init_resource_ops - int resource ops for mpm. - * - * @wait_resource, used to wait request resource ready. - * @request_resource, used to request a resource - * @release_resource, used to release a resource - */ -int sprd_mpm_init_resource_ops(unsigned int dst, - int (*wait_resource)(unsigned int dst, - int timeout), - int (*request_resource)(unsigned int dst), - int (*release_resource)(unsigned int dst)); - -/** - * sprd_mpm_destroy - destroy a modem powermanger source instacnce. - * - * @dst, which mpm (PSCP, SP, WCN, etc.) will be destroyed. - */ -int sprd_mpm_destroy(unsigned int dst); - -/** - * sprd_pms_create - init a pms, - * a module which used it to request a modem power manage resource. - * All the pms interface are not safe in multi-thread or multi-cpu. - * if you want use in multi-thread, please use the pms_ext interface. - * - * @dst, the pms belong to which mpm. - * @name, the name of this pms. - * @pms, the point of this pms. - * @multitask: support multitask. - * - * Returns: NULL failed, > 0 succ. - */ -struct sprd_pms *sprd_pms_create(unsigned int dst, - const char *name, bool multitask); - -/** - * sprd_pms_destroy - destroy a pms. - * - * @pms, the point of this pms. - */ -void sprd_pms_destroy(struct sprd_pms *pms); - -/** - * sprd_pms_request_resource - request mpm resource - * - * @pms, the point of this pms. - * @timeout, in ms. - * - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pms_request_resource(struct sprd_pms *pms, int timeout); - -/** - * sprd_pms_release_resource - release mpm resource. - * - * @pms, the point of this pms. - */ -void sprd_pms_release_resource(struct sprd_pms *pms); - -/** - * sprd_pms_request_wakelock - request wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_request_wakelock(struct sprd_pms *pms); - -/** - * sprd_pms_release_wakelock - release wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_release_wakelock(struct sprd_pms *pms); - -/** - * sprd_pms_request_wakelock_period - - * request wake lock, and will auto reaslse in msec ms. - * - * @pms, the point of this pms. - * @msec, will auto reaslse in msec ms - */ -void sprd_pms_request_wakelock_period(struct sprd_pms *pms, unsigned int msec); - -/** - * sprd_pms_release_wakelock_later - release wakelock later. - * - * @pms, the point of this pms. - * @msec, later time (in ms). - */ -void sprd_pms_release_wakelock_later(struct sprd_pms *pms, - unsigned int msec); - -/** - * sprd_pms_power_up - just powe up, not wait result. - * - * @pms, the point of this pms. - */ -void sprd_pms_power_up(struct sprd_pms *pms); - -/** - * sprd_pms_power_up - just power down,. - * - * @pms, the point of this pms. - * @immediately, whether immediately power down. - */ -void sprd_pms_power_down(struct sprd_pms *pms, bool immediately); - -#endif diff --git a/quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h b/quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h deleted file mode 100644 index 7b62456..0000000 --- a/quectel_SRPD_PCIE/src/include/sprd_pcie_ep_device.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * SPRD ep device driver in host side for Spreadtrum SoCs - * - * Copyright (C) 2019 Spreadtrum Co., Ltd. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * This program is used to control ep device driver in host side for - * Spreadtrum SoCs. - */ - -#ifndef __SPRD_PCIE_EP_DEVICE_H -#define __SPRD_PCIE_EP_DEVICE_H - -#include - -/* host receive msi irq */ -enum { - PCIE_MSI_SIPC_IRQ = 0, - PCIE_MSI_REQUEST_RES, - PCIE_MSI_EP_READY_FOR_RESCAN, - PCIE_MSI_RELEASE_RES, - PCIE_MSI_SCANNED_RESPOND, - PCIE_MSI_REMOVE_RESPOND, - PCIE_MSI_IPA, - PCIE_MSI_MAX_IRQ -}; - -/* host send doorbell irq */ -enum { - PCIE_DBELL_SIPC_IRQ = 0, - PCIE_DBEL_EP_SCANNED, - PCIE_DBEL_EP_REMOVING, - PCIE_DBEL_IRQ_MAX -}; - -enum { - PCIE_EP_MODEM = 0, - /* PCIE_EP_WCN, */ - PCIE_EP_NR -}; - -enum { - PCIE_EP_PROBE = 0, - PCIE_EP_REMOVE, - PCIE_EP_PROBE_BEFORE_SPLIT_BAR -}; - -#ifdef CONFIG_SPRD_SIPA -enum { - PCIE_IPA_TYPE_MEM = 0, - PCIE_IPA_TYPE_REG -}; -#endif - -#define MINI_REGION_SIZE 0x10000 /*64 K default */ - -int sprd_ep_dev_register_notify(int ep, - void (*notify)(int event, void *data), - void *data); -int sprd_ep_dev_unregister_notify(int ep); -int sprd_ep_dev_register_irq_handler(int ep, - int irq, - irq_handler_t handler, - void *data); -int sprd_ep_dev_unregister_irq_handler(int ep, int irq); -int sprd_ep_dev_register_irq_handler_ex(int ep, - int from_irq, - int to_irq, - irq_handler_t handler, - void *data); -int sprd_ep_dev_unregister_irq_handler_ex(int ep, - int from_irq, - int to_irq); -int sprd_ep_dev_set_irq_addr(int ep, void __iomem *irq_addr); -int sprd_ep_dev_raise_irq(int ep, int irq); -int sprd_ep_dev_clear_doolbell_irq(int ep, int irq); -int sprd_ep_dev_set_backup(int ep); -int sprd_ep_dev_clear_backup(int ep); - -void __iomem *sprd_ep_map_memory(int ep, - phys_addr_t cpu_addr, - size_t size); -void sprd_ep_unmap_memory(int ep, const void __iomem *bar_addr); -int sprd_ep_dev_pass_smem(int ep, u32 base, u32 size); -int sipa_module_init(struct device *dev); -void sipa_module_exit(void); -int sipa_eth_init(void); -void sipa_eth_exit(void); -int sipa_dummy_init(void); -void sipa_dummy_exit(void); - -#ifdef CONFIG_SPRD_SIPA -phys_addr_t sprd_ep_ipa_map(int type, phys_addr_t target_addr, size_t size); -int sprd_ep_ipa_unmap(int type, phys_addr_t cpu_addr); -#endif -#endif diff --git a/quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h b/quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h deleted file mode 100644 index 902de45..0000000 --- a/quectel_SRPD_PCIE/src/include/sprd_pcie_resource.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - /* mpms: modem powermanger source */ -#ifndef _SPRD_PCIE_RESOURCE_H -#define _SPRD_PCIE_RESOURCE_H - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE -#include -#endif - -#if 0 -//#undef pr_debug -//#define pr_debug pr_emerg - -#undef pr_info -#define pr_info pr_emerg - -#undef pr_err -#define pr_err pr_emerg - -#undef dev_dbg -#define dev_dbg dev_emerg - -#undef dev_info -#define dev_info dev_emerg - -#undef dev_err -#define dev_err dev_emerg -#endif - -#if defined(CONFIG_SPRD_PCIE_EP_DEVICE) || defined(CONFIG_PCIE_EPF_SPRD) -/* - * sprd_pcie_wait_resource - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pcie_wait_resource(u32 dst, int timeout); - -int sprd_pcie_request_resource(u32 dst); -int sprd_pcie_release_resource(u32 dst); -int sprd_pcie_resource_trash(u32 dst); -bool sprd_pcie_is_defective_chip(void); -#else -/* dummy functions */ -static inline int sprd_pcie_wait_resource(u32 dst, int timeout) {return 0; } - -static inline int sprd_pcie_request_resource(u32 dst) {return 0; } -static inline int sprd_pcie_release_resource(u32 dst) {return 0; } -static inline int sprd_pcie_resource_trash(u32 dst) {return 0; } -static inline bool sprd_pcie_is_defective_chip(void) {return false; } -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD -int sprd_pcie_resource_client_init(u32 dst, u32 ep_fun); -int sprd_register_pcie_resource_first_ready(u32 dst, - void (*notify)(void *p), - void *data); -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE -int sprd_pcie_resource_host_init(u32 dst, u32 ep_dev, - struct platform_device *pcie_dev); - -/* - * sprd_pcie_resource_reboot_ep - * reboot ep contains rescan ep device. - */ -void sprd_pcie_resource_reboot_ep(u32 dst); - -/* - * sprd_pcie_wait_load_resource - * In case of the open the feature CONFIG_PCIE_SPRD_SPLIT_BAR, - * It has 2 times pcie scan action in host side boot process. - * After the first scan, the ep only have 2 bar can be used for - * memory map, the pcie resource is not completely ready, - * but the host can load images for ep, so we add the special api - * sprd_pcie_wait_load_resource, this api will return after - * the first scan action. - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pcie_wait_load_resource(u32 dst); - - -/* Because the ep bar can only be split by ep itself, - * After all modem images be loaded, notify pcie resource - * can rescan ep now. - */ -void sprd_pcie_resource_notify_load_done(u32 dst); -#endif /* CONFIG_SPRD_PCIE_EP_DEVICE */ - -#endif /* _SPRD_PCIE_RESOURCE_H */ diff --git a/quectel_SRPD_PCIE/src/mcd/Kconfig b/quectel_SRPD_PCIE/src/mcd/Kconfig deleted file mode 100644 index a7f3db5..0000000 --- a/quectel_SRPD_PCIE/src/mcd/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config SPRD_MCD - tristate "SPRD modem power control module" - default n - help - mcd is a module for spreadtrum AP/CP communicaiton control driver, - it can control modem power on/off,triger modem event of assert,watchdog - reset,panic. diff --git a/quectel_SRPD_PCIE/src/mcd/Makefile b/quectel_SRPD_PCIE/src/mcd/Makefile deleted file mode 100644 index 78cb075..0000000 --- a/quectel_SRPD_PCIE/src/mcd/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += modem_ctrl.o diff --git a/quectel_SRPD_PCIE/src/mcd/modem_ctrl.c b/quectel_SRPD_PCIE/src/mcd/modem_ctrl.c deleted file mode 100644 index 720b923..0000000 --- a/quectel_SRPD_PCIE/src/mcd/modem_ctrl.c +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_PCIE_PM_NOTIFY -#include -#endif - -#include "../include/sprd_pcie_resource.h" -#include "../include/sipc.h" -#include "../include/mdm_ctrl.h" - -enum { - ROC1_SOC = 0, - ORCA_SOC -}; - -static char *const mdm_stat[] = { - "mdm_power_off", "mdm_power_on", "mdm_warm_reset", "mdm_cold_reset", - "mdm_watchdog_reset", "mdm_assert", "mdm_panic" -}; - -#define REBOOT_MODEM_DELAY 1000 -#define POWERREST_MODEM_DELAY 2000 -#define RESET_MODEM_DELAY 50 - -char cdev_name[] = "mdm_ctrl"; - -struct modem_ctrl_init_data { - char *name; - struct gpio_desc *gpio_poweron; /* Poweron */ - struct gpio_desc *gpio_reset; /* Reset modem */ - struct gpio_desc *gpio_preset; /* Pcie reset */ - struct gpio_desc *gpio_cpwatchdog; - struct gpio_desc *gpio_cpassert; - struct gpio_desc *gpio_cppanic; - struct gpio_desc *gpio_cppoweroff; - u32 irq_cpwatchdog; - u32 irq_cpassert; - u32 irq_cppanic; - u32 irq_cppoweroff; - u32 modem_status; - bool enable_cp_event; -}; - -struct modem_ctrl_device { - struct modem_ctrl_init_data *init; - int major; - int minor; - struct cdev cdev; - struct device *dev; - int soc_type; -}; - -static struct class *modem_ctrl_class; -static struct modem_ctrl_device *mcd_dev; - -/* modem control evnet notify */ -static ATOMIC_NOTIFIER_HEAD(modem_ctrl_chain); - -int modem_ctrl_register_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&modem_ctrl_chain, nb); -} -EXPORT_SYMBOL(modem_ctrl_register_notifier); - -void modem_ctrl_unregister_notifier(struct notifier_block *nb) -{ - atomic_notifier_chain_unregister(&modem_ctrl_chain, nb); -} -EXPORT_SYMBOL(modem_ctrl_unregister_notifier); - -static void send_event_msg(struct kobject *kobj) -{ - char *msg[3]; - char buff[100]; - char mbuff[100]; - - memset(mbuff, 0, sizeof(mbuff)); - if (!mcd_dev || !mcd_dev->init || !kobj) - return; - - snprintf(buff, sizeof(buff), "MODEM_STAT=%d", - mcd_dev->init->modem_status); - snprintf(mbuff, sizeof(mbuff), "MODEM_EVENT=%s", - mdm_stat[mcd_dev->init->modem_status]); - msg[0] = buff; - msg[1] = mbuff; - msg[2] = NULL; - kobject_uevent_env(kobj, KOBJ_CHANGE, msg); - dev_dbg(mcd_dev->dev, "send uevent to userspace\n"); -} - -static irqreturn_t cpwatchdogtriger_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init || !mcd_dev->init->enable_cp_event) - return IRQ_NONE; - - mcd_dev->init->modem_status = MDM_WATCHDOG_RESET; - atomic_notifier_call_chain(&modem_ctrl_chain, MDM_WATCHDOG_RESET, NULL); - send_event_msg(&mcd_dev->dev->kobj); - return IRQ_HANDLED; -} - -static irqreturn_t cpasserttriger_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init || !mcd_dev->init->enable_cp_event) - return IRQ_NONE; - - mcd_dev->init->modem_status = MDM_ASSERT; - atomic_notifier_call_chain(&modem_ctrl_chain, MDM_ASSERT, NULL); - send_event_msg(&mcd_dev->dev->kobj); - return IRQ_HANDLED; -} - -static irqreturn_t cppanictriger_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init || !mcd_dev->init->enable_cp_event) - return IRQ_NONE; - - mcd_dev->init->modem_status = MDM_PANIC; - atomic_notifier_call_chain(&modem_ctrl_chain, MDM_PANIC, NULL); - send_event_msg(&mcd_dev->dev->kobj); - return IRQ_HANDLED; -} - -static irqreturn_t cppoweroff_handler(int irq, void *dev_id) -{ - if (!mcd_dev || !mcd_dev->init) - return IRQ_NONE; - /* To this reserve here for receve power off event from AP*/ - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_POWER_OFF, NULL); - kernel_power_off(); - return IRQ_HANDLED; -} - -static int request_gpio_to_irq(struct gpio_desc *cp_gpio, - struct modem_ctrl_device *mcd_dev) -{ - int ret = 0; - - if (!mcd_dev || !mcd_dev->init) - return -EINVAL; - - ret = gpiod_to_irq(cp_gpio); - if (ret < 0) { - dev_err(mcd_dev->dev, "requset irq %d failed\n", ret); - return ret; - } - dev_dbg(mcd_dev->dev, "gpio to irq %d\n", ret); - if (cp_gpio == mcd_dev->init->gpio_cpwatchdog) { - mcd_dev->init->irq_cpwatchdog = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cpwatchdog, - NULL, cpwatchdogtriger_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "cpwatchdog_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, "can not request irq for cp watchdog\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cpwatchdog); - } else if (cp_gpio == mcd_dev->init->gpio_cpassert) { - mcd_dev->init->irq_cpassert = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cpassert, - NULL, cpasserttriger_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "cpassert_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, "can not request irq for cp assert\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cpassert); - } else if (cp_gpio == mcd_dev->init->gpio_cppanic) { - mcd_dev->init->irq_cppanic = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cppanic, - NULL, cppanictriger_handler, - IRQF_ONESHOT | IRQF_TRIGGER_FALLING, - "cppanic_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, - "can not request irq for panic\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cppanic); - } else if (cp_gpio == mcd_dev->init->gpio_cppoweroff) { - mcd_dev->init->irq_cppoweroff = ret; - ret = devm_request_threaded_irq(mcd_dev->dev, - mcd_dev->init->irq_cppoweroff, - NULL, cppoweroff_handler, - IRQF_ONESHOT | IRQF_TRIGGER_LOW, - "cppoweroff_irq", mcd_dev); - if (ret < 0) { - dev_err(mcd_dev->dev, - "can not request irq for cppoweroff\n"); - return ret; - } - enable_irq_wake(mcd_dev->init->irq_cppoweroff); - } - return 0; -} - -static int modem_gpios_init(struct modem_ctrl_device *mcd_dev, int soc_type) -{ - int ret; - - if (!mcd_dev || !mcd_dev->init) - return -EINVAL; - if (soc_type == ROC1_SOC) { - gpiod_direction_input(mcd_dev->init->gpio_cpwatchdog); - gpiod_direction_input(mcd_dev->init->gpio_cpassert); - gpiod_direction_input(mcd_dev->init->gpio_cppanic); - - ret = request_gpio_to_irq(mcd_dev->init->gpio_cpwatchdog, - mcd_dev); - if (ret) - return ret; - ret = request_gpio_to_irq(mcd_dev->init->gpio_cpassert, - mcd_dev); - if (ret) - return ret; - ret = request_gpio_to_irq(mcd_dev->init->gpio_cppanic, - mcd_dev); - if (ret) - return ret; - - /* IRQF_TRIGGER_LOW, default must set to high */ - gpiod_set_value_cansleep(mcd_dev->init->gpio_cppoweroff, 1); - } else { - gpiod_direction_input(mcd_dev->init->gpio_cppoweroff); - ret = request_gpio_to_irq(mcd_dev->init->gpio_cppoweroff, - mcd_dev); - if (ret) - return ret; - - /* TRIGGER_FALLING, defaultmust set to high */ - gpiod_set_value_cansleep(mcd_dev->init->gpio_cpwatchdog, 1); - gpiod_set_value_cansleep(mcd_dev->init->gpio_cpassert, 1); - gpiod_set_value_cansleep(mcd_dev->init->gpio_cppanic, 1); - } - return 0; -} - -void modem_ctrl_enable_cp_event(void) -{ - if (mcd_dev && mcd_dev->init) - mcd_dev->init->enable_cp_event = true; -} -EXPORT_SYMBOL_GPL(modem_ctrl_enable_cp_event); - -void modem_ctrl_send_abnormal_to_ap(int status) -{ - struct gpio_desc *gpiodesc; - - if (!mcd_dev || !mcd_dev->init) - return; - if (mcd_dev->soc_type != ORCA_SOC) { - dev_err(mcd_dev->dev, "operation not be allowed for %d\n", - mcd_dev->soc_type); - return; - } - switch (status) { - case MDM_WATCHDOG_RESET: - gpiodesc = mcd_dev->init->gpio_cpwatchdog; - break; - case MDM_ASSERT: - gpiodesc = mcd_dev->init->gpio_cpassert; - break; - case MDM_PANIC: - gpiodesc = mcd_dev->init->gpio_cppanic; - break; - default: - dev_info(mcd_dev->dev, - "get status %d is not right for operation\n", status); - return; - } - mcd_dev->init->modem_status = status; - dev_info(mcd_dev->dev, - "operation unnormal status %d send to ap\n", - status); - if (!IS_ERR(gpiodesc)) - gpiod_set_value_cansleep(gpiodesc, 0); -} - -static void modem_ctrl_send_cmd_to_cp(int status) -{ - struct gpio_desc *gpiodesc = NULL; - - if (!mcd_dev || !mcd_dev->init) - return; - if (mcd_dev->soc_type != ROC1_SOC) { - dev_err(mcd_dev->dev, "operation not be allowed for %d\n", - mcd_dev->soc_type); - return; - } - if (status == MDM_POWER_OFF) - gpiodesc = mcd_dev->init->gpio_cppoweroff; - - mcd_dev->init->modem_status = status; - dev_info(mcd_dev->dev, - "operation cmd %d ms send to cp\n", - status); - if (!IS_ERR(gpiodesc)) { - gpiod_set_value_cansleep(gpiodesc, 0); - msleep(20); - gpiod_set_value_cansleep(gpiodesc, 20); - } -} - -static void modem_ctrl_notify_abnormal_status(int status) -{ - if (!mcd_dev || !mcd_dev->init) - return; - if (mcd_dev->soc_type != ORCA_SOC) { - dev_err(mcd_dev->dev, "operation not be allowed for %d\n", - mcd_dev->soc_type); - return; - } - if (status < MDM_WATCHDOG_RESET || status > MDM_PANIC) { - dev_err(mcd_dev->dev, - "operation not be allowed for status %d\n", status); - return; - } - modem_ctrl_send_abnormal_to_ap(status); -} - -void modem_ctrl_poweron_modem(int on) -{ - if (!mcd_dev || !mcd_dev->init) - return; - switch (on) { - case MDM_CTRL_POWER_ON: - if (!IS_ERR(mcd_dev->init->gpio_poweron)) { - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_CTRL_POWER_ON, NULL); - dev_info(mcd_dev->dev, "set modem_poweron: %d\n", on); - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 1); - /* Base the spec modem boot flow that need to wait 1s */ - msleep(REBOOT_MODEM_DELAY); - mcd_dev->init->modem_status = MDM_CTRL_POWER_ON; - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 0); - } - break; - case MDM_CTRL_POWER_OFF: - /* - *To do - */ - break; - case MDM_CTRL_SET_CFG: - /* - *To do - */ - break; - case MDM_CTRL_WARM_RESET: - if (!IS_ERR(mcd_dev->init->gpio_reset)) { - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_CTRL_WARM_RESET, NULL); - dev_dbg(mcd_dev->dev, "set warm reset: %d\n", on); - gpiod_set_value_cansleep(mcd_dev->init->gpio_reset, 1); - /* Base the spec modem that need to wait 50ms */ - msleep(RESET_MODEM_DELAY); - mcd_dev->init->modem_status = MDM_CTRL_WARM_RESET; - gpiod_set_value_cansleep(mcd_dev->init->gpio_reset, 0); - } - break; - case MDM_CTRL_COLD_RESET: - if (!IS_ERR(mcd_dev->init->gpio_poweron)) { - mcd_dev->init->enable_cp_event = false; - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_CTRL_COLD_RESET, NULL); - dev_info(mcd_dev->dev, "modem_power reset: %d\n", on); - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 1); - /* Base the spec modem boot flow that need to wait 2s */ - msleep(POWERREST_MODEM_DELAY); - mcd_dev->init->modem_status = MDM_CTRL_COLD_RESET; - gpiod_set_value_cansleep(mcd_dev->init->gpio_poweron, - 0); - } - break; - case MDM_CTRL_PCIE_RECOVERY: -#ifdef CONFIG_PCIE_PM_NOTIFY - pcie_ep_pm_notify(PCIE_EP_POWER_OFF); - /* PCIE poweroff to poweron need 100ms*/ - msleep(100); - pcie_ep_pm_notify(PCIE_EP_POWER_ON); -#endif - break; - case MDM_POWER_OFF: - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_POWER_OFF, NULL); - modem_ctrl_send_cmd_to_cp(MDM_POWER_OFF); - break; - default: - dev_err(mcd_dev->dev, "cmd not support: %d\n", on); - } -} -EXPORT_SYMBOL_GPL(modem_ctrl_poweron_modem); - -#if defined(CONFIG_DEBUG_FS) -static int modem_ctrl_debug_show(struct seq_file *m, void *private) -{ - dev_dbg(mcd_dev->dev, "%s\n", __func__); - return 0; -} - -static int modem_ctrl_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, modem_ctrl_debug_show, inode->i_private); -} - -static const struct file_operations modem_ctrl_debug_fops = { - .open = modem_ctrl_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#endif /* CONFIG_DEBUG_FS */ - -static int modem_ctrl_open(struct inode *inode, struct file *filp) -{ - struct modem_ctrl_device *modem_ctrl; - - modem_ctrl = container_of(inode->i_cdev, - struct modem_ctrl_device, cdev); - filp->private_data = modem_ctrl; - dev_dbg(modem_ctrl->dev, "modem_ctrl: %s\n", __func__); - return 0; -} - -static int modem_ctrl_release(struct inode *inode, struct file *filp) -{ - struct modem_ctrl_device *modem_ctrl; - - modem_ctrl = container_of(inode->i_cdev, - struct modem_ctrl_device, cdev); - dev_dbg(modem_ctrl->dev, "modem_ctrl: %s\n", __func__); - - return 0; -} - -static ssize_t modem_ctrl_read(struct file *filp, - char __user *buf, - size_t count, - loff_t *ppos) -{ - char tmpbuf[30]; - int r; - struct modem_ctrl_device *mcd_dev = filp->private_data; - - if (!mcd_dev || !mcd_dev->init) - return -EINVAL; - - r = snprintf(tmpbuf, sizeof(tmpbuf), "%s\n", - mdm_stat[mcd_dev->init->modem_status]); - - return simple_read_from_buffer(buf, count, ppos, tmpbuf, r); -} - -static ssize_t modem_ctrl_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - char sbuf[100]; - int ret; - u32 mcd_cmd; - struct modem_ctrl_device *mcd_dev = filp->private_data; - - if (!mcd_dev) - return -EINVAL; - - if (unalign_copy_from_user((void *)sbuf, buf, count)) { - dev_err(mcd_dev->dev, "copy buf %s error\n", buf); - return -EFAULT; - } - dev_dbg(mcd_dev->dev, "get info:%s", sbuf); - sbuf[count - 1] = '\0'; - ret = kstrtouint(sbuf, 10, &mcd_cmd); - if (ret) { - dev_err(mcd_dev->dev, "Invalid input!\n"); - return ret; - } - if (mcd_dev->soc_type == ROC1_SOC) { - if (mcd_cmd >= MDM_CTRL_POWER_OFF && - mcd_cmd <= MDM_CTRL_SET_CFG) - modem_ctrl_poweron_modem(mcd_cmd); - else - dev_info(mcd_dev->dev, "cmd not support!\n"); - } else { - modem_ctrl_notify_abnormal_status(mcd_cmd); - } - return count; -} - -static long modem_ctrl_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - - if (!mcd_dev || mcd_dev->soc_type == ORCA_SOC) - return -EINVAL; - switch (cmd) { - case MDM_CTRL_POWER_OFF: - modem_ctrl_poweron_modem(MDM_CTRL_POWER_OFF); - break; - case MDM_CTRL_POWER_ON: - modem_ctrl_poweron_modem(MDM_CTRL_POWER_ON); - break; - case MDM_CTRL_WARM_RESET: - modem_ctrl_poweron_modem(MDM_CTRL_WARM_RESET); - break; - case MDM_CTRL_COLD_RESET: - modem_ctrl_poweron_modem(MDM_CTRL_COLD_RESET); - break; - case MDM_CTRL_PCIE_RECOVERY: - modem_ctrl_poweron_modem(MDM_CTRL_PCIE_RECOVERY); - break; - case MDM_CTRL_SET_CFG: - break; - default: - return -EINVAL; - } - return 0; -} - -static const struct file_operations modem_ctrl_fops = { - .open = modem_ctrl_open, - .release = modem_ctrl_release, - .read = modem_ctrl_read, - .write = modem_ctrl_write, - .unlocked_ioctl = modem_ctrl_ioctl, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -static int modem_ctrl_parse_modem_dt(struct modem_ctrl_init_data **init, - struct device *dev) -{ - struct modem_ctrl_init_data *pdata = NULL; - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->name = cdev_name; - - /* Triger watchdog,assert,panic of orca */ - pdata->gpio_cpwatchdog = devm_gpiod_get(dev, - "cpwatchdog", - GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cpwatchdog)) - return PTR_ERR(pdata->gpio_cpwatchdog); - - pdata->gpio_cpassert = devm_gpiod_get(dev, "cpassert", GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cpassert); - - pdata->gpio_cppanic = devm_gpiod_get(dev, "cppanic", GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cppanic)) - return PTR_ERR(pdata->gpio_cppanic); - - pdata->gpio_cppoweroff = devm_gpiod_get(dev, "cppoweroff", GPIOD_IN); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cppoweroff); - - *init = pdata; - return 0; -} - -static int modem_ctrl_parse_dt(struct modem_ctrl_init_data **init, - struct device *dev) -{ - struct modem_ctrl_init_data *pdata; - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->name = cdev_name; - pdata->gpio_poweron = devm_gpiod_get(dev, "poweron", GPIOD_OUT_LOW); - if (IS_ERR(pdata->gpio_poweron)) - return PTR_ERR(pdata->gpio_poweron); - - pdata->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(pdata->gpio_reset)) - return PTR_ERR(pdata->gpio_reset); - - /* Triger watchdog,assert,panic of orca */ - pdata->gpio_cpwatchdog = devm_gpiod_get(dev, "cpwatchdog", GPIOD_IN); - if (IS_ERR(pdata->gpio_cpwatchdog)) - return PTR_ERR(pdata->gpio_cpwatchdog); - - pdata->gpio_cpassert = devm_gpiod_get(dev, "cpassert", GPIOD_IN); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cpassert); - - pdata->gpio_cppanic = devm_gpiod_get(dev, "cppanic", GPIOD_IN); - if (IS_ERR(pdata->gpio_cppanic)) - return PTR_ERR(pdata->gpio_cppanic); - - pdata->gpio_cppoweroff = devm_gpiod_get(dev, - "cppoweroff", GPIOD_OUT_HIGH); - if (IS_ERR(pdata->gpio_cpassert)) - return PTR_ERR(pdata->gpio_cppoweroff); - - pdata->modem_status = MDM_CTRL_POWER_OFF; - *init = pdata; - return 0; -} - -static inline void -modem_ctrl_destroy_pdata(struct modem_ctrl_init_data **init) -{ - struct modem_ctrl_init_data *pdata = *init; - - pdata = NULL; -} - -static int modem_ctrl_restart_handle(struct notifier_block *this, - unsigned long mode, void *cmd) -{ - if (!mcd_dev || mcd_dev->soc_type == ROC1_SOC) - return NOTIFY_DONE; - modem_ctrl_notify_abnormal_status(MDM_PANIC); - while (1) - ; - return NOTIFY_DONE; -} - -static struct notifier_block modem_ctrl_restart_handler = { - .notifier_call = modem_ctrl_restart_handle, - .priority = 150, -}; - -static int modem_ctrl_probe(struct platform_device *pdev) -{ - struct modem_ctrl_init_data *init = pdev->dev.platform_data; - struct modem_ctrl_device *modem_ctrl_dev; - dev_t devid; - int rval; - struct device *dev = &pdev->dev; - - modem_ctrl_dev = devm_kzalloc(dev, sizeof(*modem_ctrl_dev), GFP_KERNEL); - if (!modem_ctrl_dev) - return -ENOMEM; - mcd_dev = modem_ctrl_dev; - if (of_device_is_compatible(pdev->dev.of_node, "sprd,roc1-modem-ctrl")) - modem_ctrl_dev->soc_type = ROC1_SOC; - else - modem_ctrl_dev->soc_type = ORCA_SOC; - - if (modem_ctrl_dev->soc_type == ROC1_SOC) { - rval = modem_ctrl_parse_dt(&init, &pdev->dev); - if (rval) { - dev_err(dev, - "Failed to parse modem_ctrl device tree, ret=%d\n", - rval); - return rval; - } - } else { - rval = modem_ctrl_parse_modem_dt(&init, &pdev->dev); - if (rval) { - dev_err(dev, - "Failed to parse modem_ctrl device tree, ret=%d\n", - rval); - return rval; - } - } - - dev_dbg(dev, "after parse device tree, name=%s soctype=%d\n", - init->name, - modem_ctrl_dev->soc_type); - - rval = alloc_chrdev_region(&devid, 0, 1, init->name); - if (rval != 0) { - dev_err(dev, "Failed to alloc modem_ctrl chrdev\n"); - goto error3; - } - cdev_init(&modem_ctrl_dev->cdev, &modem_ctrl_fops); - rval = cdev_add(&modem_ctrl_dev->cdev, devid, 1); - if (rval != 0) { - dev_err(dev, "Failed to add modem_ctrl cdev\n"); - goto error2; - } - - modem_ctrl_dev->major = MAJOR(devid); - modem_ctrl_dev->minor = MINOR(devid); - modem_ctrl_dev->dev = device_create(modem_ctrl_class, NULL, - MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor), - NULL, "%s", init->name); - if (!modem_ctrl_dev->dev) { - dev_err(dev, "create dev failed\n"); - rval = -ENODEV; - goto error1; - } - modem_ctrl_dev->init = init; - platform_set_drvdata(pdev, modem_ctrl_dev); - rval = modem_gpios_init(modem_ctrl_dev, modem_ctrl_dev->soc_type); - if (rval) { - dev_err(dev, "request gpios error\n"); - goto error0; - } - - rval = register_restart_handler(&modem_ctrl_restart_handler); - if (rval) { - dev_err(dev, "cannot register restart handler err=%d\n", rval); - goto error0; - } - return 0; -error0: - device_destroy(modem_ctrl_class, - MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor)); -error1: - cdev_del(&modem_ctrl_dev->cdev); -error2: - unregister_chrdev_region(devid, 1); -error3: - modem_ctrl_destroy_pdata(&init); - return rval; -} - -static int modem_ctrl_remove(struct platform_device *pdev) -{ - struct modem_ctrl_device *modem_ctrl_dev = platform_get_drvdata(pdev); - - unregister_reboot_notifier(&modem_ctrl_restart_handler); - device_destroy(modem_ctrl_class, - MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor)); - cdev_del(&modem_ctrl_dev->cdev); - unregister_chrdev_region(MKDEV(modem_ctrl_dev->major, - modem_ctrl_dev->minor), 1); - modem_ctrl_destroy_pdata(&modem_ctrl_dev->init); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static void modem_ctrl_shutdown(struct platform_device *pdev) -{ - if (mcd_dev->soc_type == ROC1_SOC) { - atomic_notifier_call_chain(&modem_ctrl_chain, - MDM_POWER_OFF, NULL); - /* - * sleep 50 ms for other module to do something - * before orca power down. - */ - msleep(50); - modem_ctrl_send_cmd_to_cp(MDM_POWER_OFF); - /* Sleep 500ms for cp to deal power down process otherwise - * cp will not power down clearly. - */ - msleep(500); - } -} - -static const struct of_device_id modem_ctrl_match_table[] = { - {.compatible = "sprd,roc1-modem-ctrl", }, - {.compatible = "sprd,orca-modem-ctrl", }, -}; - -static struct platform_driver modem_ctrl_driver = { - .driver = { - .name = "modem_ctrl", - .of_match_table = modem_ctrl_match_table, - }, - .probe = modem_ctrl_probe, - .remove = modem_ctrl_remove, - .shutdown = modem_ctrl_shutdown, -}; - -int modem_ctrl_init(void) -{ - modem_ctrl_class = class_create(THIS_MODULE, "modem_ctrl"); - if (IS_ERR(modem_ctrl_class)) - return PTR_ERR(modem_ctrl_class); - return platform_driver_register(&modem_ctrl_driver); -} -EXPORT_SYMBOL_GPL(modem_ctrl_init); - -void modem_ctrl_exit(void) -{ - class_destroy(modem_ctrl_class); - platform_driver_unregister(&modem_ctrl_driver); -} -EXPORT_SYMBOL_GPL(modem_ctrl_exit); diff --git a/quectel_SRPD_PCIE/src/pcie/Kconfig b/quectel_SRPD_PCIE/src/pcie/Kconfig deleted file mode 100644 index ac88510..0000000 --- a/quectel_SRPD_PCIE/src/pcie/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ - -config SPRD_PCIE_EP_DEVICE - tristate "SPRD PCIE EP device" - default n - depends on PCI - help - SPRD pcie ep device driver in host side for Spreadtrum. \ No newline at end of file diff --git a/quectel_SRPD_PCIE/src/pcie/Makefile b/quectel_SRPD_PCIE/src/pcie/Makefile deleted file mode 100644 index 0f62c8a..0000000 --- a/quectel_SRPD_PCIE/src/pcie/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -ccflags-y += -DCONFIG_SPRD_PCIE_EP_DEVICE -DCONFIG_SPRD_SIPA -obj-y += sprd_pcie_ep_device.o -obj-y += pcie_host_resource.o -obj-y += sprd_pcie_quirks.o -obj-$(CONFIG_PCIE_EPF_SPRD) += pcie_client_resource.o -obj-$(CONFIG_SPRD_SIPA_RES) += pcie_sipa_res.o diff --git a/quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c b/quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c deleted file mode 100644 index 74e5d72..0000000 --- a/quectel_SRPD_PCIE/src/pcie/pcie_client_resource.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sprd_pcie_resource.h" -#ifdef CONFIG_SPRD_SIPA_RES -#include "pcie_sipa_res.h" -#endif - -enum ep_msg { - RC_SCANNED_MSG = 0, - RC_REMOVING_MSG, - EPC_UNLINK_MSG, - EPC_LINKUP_MSG -}; - -enum pcie_ep_state { - SPRD_PCIE_WAIT_FIRST_READY = 0, - SPRD_PCIE_WAIT_SCANNED, - SPRD_PCIE_SCANNED, - SPRD_PCIE_WAIT_REMOVED, - SPRD_PCIE_REMOVED, - SPRD_PCIE_WAIT_POWER_OFF -}; - -struct sprd_pci_res_notify { - void (*notify)(void *p); - void *data; -}; - -struct sprd_pcie_res { - u32 dst; - u32 ep_fun; - enum pcie_ep_state state; - bool msi_later; - bool wakeup_later; - -#ifdef CONFIG_SPRD_SIPA_RES - void *sipa_res; -#endif - - /* - * in client(Orca), The PCIE module wll blocks the chip Deep, - * so we must get a wake lock when pcie work to avoid this situation: - * the system is deep, but the PCIE is still working. - */ - struct wakeup_source ws; - wait_queue_head_t wait_pcie_ready; - struct sprd_pci_res_notify first_ready_notify; -}; - -static struct sprd_pcie_res *g_pcie_res[SIPC_ID_NR]; - -/* the state machine of ep, init SPRD_PCIE_WAIT_FIRST_READY. - * SPRD_PCIE_WAIT_FIRST_READY (receive RC scanned) ==> SPRD_PCIE_SCANNED - * SPRD_PCIE_SCANNED (receive RC removing)==> SPRD_PCIE_WAIT_REMOVED - * SPRD_PCIE_WAIT_REMOVED(receive epc unlink)==>SPRD_PCIE_REMOVED - * SPRD_PCIE_REMOVED(receive epc linkup)==>SPRD_PCIE_WAIT_SCANNED - * SPRD_PCIE_WAIT_SCANNED(receive RC scanned)==>SPRD_PCIE_SCANNED - * SPRD_PCIE_WAIT_POWER_OFF can do nothing, just wait shutdown. - */ -static const char *change_msg[EPC_LINKUP_MSG + 1] = { - "rc scanned", - "rc removing", - "epc unlink", - "epc linkup" -}; - -static const char *state_msg[SPRD_PCIE_REMOVED + 1] = { - "wait first ready", - "wait sacanned", - "scanned", - "wait remove", - "removed" -}; - -static void pcie_resource_client_change_state(struct sprd_pcie_res *res, - enum ep_msg msg) -{ - u32 old_state = res->state; - - if (old_state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - pr_debug("pcie res: change state msg=%s, old_state=%s.\n", - change_msg[msg], state_msg[old_state]); - - switch (msg) { - case RC_SCANNED_MSG: - if (old_state != SPRD_PCIE_WAIT_FIRST_READY - && old_state != SPRD_PCIE_WAIT_SCANNED) { - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_SCANNED; - break; - - case RC_REMOVING_MSG: - if (old_state != SPRD_PCIE_SCANNED) { - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_WAIT_REMOVED; - break; - - case EPC_UNLINK_MSG: - if (old_state != SPRD_PCIE_WAIT_REMOVED) { - if (old_state != SPRD_PCIE_WAIT_FIRST_READY) - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_REMOVED; - break; - - case EPC_LINKUP_MSG: - if (old_state != SPRD_PCIE_REMOVED) { - if (old_state != SPRD_PCIE_WAIT_FIRST_READY) - pr_err("pcie res: %s msg err, old state=%s", - change_msg[msg], state_msg[old_state]); - return; - } - res->state = SPRD_PCIE_WAIT_SCANNED; - break; - } - - pr_info("pcie res: change state from %s to %s.\n", - state_msg[old_state], state_msg[res->state]); -} - -static void sprd_pcie_resource_first_ready_notify(struct sprd_pcie_res *res) -{ - void (*notify)(void *p); - - pr_info("pcie res: first ready.\n"); - -#ifdef CONFIG_SPRD_SIPA_RES - /* - * in client side, producer res id is SIPA_RM_RES_PROD_PCIE_EP, - * consumer res id is SIPA_RM_RES_CONS_WWAN_DL. - */ - res->sipa_res = pcie_sipa_res_create(res->dst, - SIPA_RM_RES_PROD_PCIE_EP, - SIPA_RM_RES_CONS_WWAN_DL); - if (!res->sipa_res) - pr_err("pcie res:create ipa res failed.\n"); -#endif - - notify = res->first_ready_notify.notify; - if (notify) - notify(res->first_ready_notify.data); -} - -static void pcie_resource_client_epf_notify(int event, void *private) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)private; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - switch (event) { - case SPRD_EPF_BIND: - pr_info("pcie res: epf be binded.\n"); - if (sprd_pcie_is_defective_chip()) - sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_EP_READY_FOR_RESCAN); - break; - - case SPRD_EPF_UNBIND: - pr_info("pcie res: epf be unbinded.\n"); - break; - - case SPRD_EPF_REMOVE: - pr_info("pcie res: epf be removed.\n"); - break; - - case SPRD_EPF_LINK_UP: - /* get a wakelock */ - __pm_stay_awake(&res->ws); - - pr_info("pcie res: epf linkup.\n"); - pcie_resource_client_change_state(res, EPC_LINKUP_MSG); - - /* first ready notify */ - if (res->state == SPRD_PCIE_WAIT_FIRST_READY) - sprd_pcie_resource_first_ready_notify(res); - - break; - - case SPRD_EPF_UNLINK: - /* Here need this log to debug pcie scan and remove */ - pr_info("pcie res: epf unlink.\n"); - pcie_resource_client_change_state(res, EPC_UNLINK_MSG); - - /* if has wakeup pending, send wakeup to rc */ - if (res->wakeup_later) { - res->wakeup_later = false; - pr_info("pcie res: send wakeup to rc.\n"); - if (sprd_pci_epf_start(res->ep_fun)) - pr_err("pcie res: send wakeup to rc failed.\n"); - } - - /* relax a wakelock */ - __pm_relax(&res->ws); - break; - - default: - break; - } -} - -static irqreturn_t pcie_resource_client_irq_handler(int irq, void *private) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)private; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return IRQ_HANDLED; - - if (irq == PCIE_DBEL_EP_SCANNED) { - pcie_resource_client_change_state(res, RC_SCANNED_MSG); - - /* wakeup all blocked thread */ - pr_info("pcie res: scanned, wakup all.\n"); - wake_up_interruptible_all(&res->wait_pcie_ready); - - /* if has msi pending, send msi to rc */ - if (res->msi_later) { - res->msi_later = false; - pr_info("pcie res: request msi to rc.\n"); - sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_REQUEST_RES); - } - } else if (irq == PCIE_DBEL_EP_REMOVING) { - pr_info("pcie res: removing.\n"); - pcie_resource_client_change_state(res, RC_REMOVING_MSG); - } - - return IRQ_HANDLED; -} - -static int sprd_pcie_resource_client_mcd(struct notifier_block *nb, - unsigned long mode, void *cmd) -{ - struct sprd_pcie_res *res; - int i; - - pr_info("pcie res: mcd event mode=%ld.\n", mode); - - if (mode != MDM_POWER_OFF) - return NOTIFY_DONE; - - for (i = 0; i < SIPC_ID_NR; i++) { - res = g_pcie_res[i]; - if (res) - res->state = SPRD_PCIE_WAIT_POWER_OFF; - } - - return NOTIFY_DONE; -} - -static struct notifier_block mcd_notify = { - .notifier_call = sprd_pcie_resource_client_mcd, - .priority = 149, -}; - -int sprd_pcie_resource_client_init(u32 dst, u32 ep_fun) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - res->dst = dst; - res->state = SPRD_PCIE_WAIT_FIRST_READY; - res->ep_fun = ep_fun; - - wakeup_source_init(&res->ws, "pcie_res"); - - init_waitqueue_head(&res->wait_pcie_ready); - sprd_pci_epf_register_irq_handler_ex(res->ep_fun, - PCIE_DBEL_EP_SCANNED, - PCIE_DBEL_EP_REMOVING, - pcie_resource_client_irq_handler, - res); - sprd_pci_epf_register_notify(res->ep_fun, - pcie_resource_client_epf_notify, - res); - - modem_ctrl_register_notifier(&mcd_notify); - - g_pcie_res[dst] = res; - - return 0; -} - -int sprd_pcie_resource_trash(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - -#ifdef CONFIG_SPRD_SIPA_RES - if (res->sipa_res) - pcie_sipa_res_destroy(res->sipa_res); -#endif - - sprd_pci_epf_unregister_irq_handler_ex(res->ep_fun, - PCIE_DBEL_EP_SCANNED, - PCIE_DBEL_EP_REMOVING); - sprd_pci_epf_unregister_notify(res->ep_fun); - modem_ctrl_unregister_notifier(&mcd_notify); - - kfree(res); - g_pcie_res[dst] = NULL; - - return 0; -} - -int sprd_pcie_wait_resource(u32 dst, int timeout) -{ - struct sprd_pcie_res *res; - int ret, wait; - unsigned long delay; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* pcie ready, return succ immediately */ - if (res->state == SPRD_PCIE_SCANNED) - return 0; - - if (timeout == 0) - return -ETIME; - - if (timeout < 0) { - wait = wait_event_interruptible( - res->wait_pcie_ready, - res->state == SPRD_PCIE_SCANNED - ); - ret = wait; - } else { - /* - * timeout must add 1s, - * because the pcie rescan may took some time. - */ - delay = msecs_to_jiffies(timeout + 1000); - wait = wait_event_interruptible_timeout(res->wait_pcie_ready, - res->state == - SPRD_PCIE_SCANNED, - delay); - if (wait == 0) - ret = -ETIME; - else if (wait > 0) - ret = 0; - else - ret = wait; - } - - if (ret < 0 && ret != -ERESTARTSYS) - pr_err("pcie res: wait resource, val=%d.\n", ret); - - return ret; -} - -int sprd_pcie_request_resource(u32 dst) -{ - struct sprd_pcie_res *res; - int ret = 0; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return -EINVAL; - - pr_debug("pcie res: request res, state=%d.\n", res->state); - - switch (res->state) { - case SPRD_PCIE_WAIT_FIRST_READY: - case SPRD_PCIE_WAIT_SCANNED: - pr_info("pcie res: later send request msi to rc.\n"); - res->msi_later = true; - break; - - case SPRD_PCIE_WAIT_REMOVED: - pr_info("pcie res: later send wakeup to rc.\n"); - res->wakeup_later = true; - break; - - case SPRD_PCIE_SCANNED: - /* - * if pcie state is SCANNED, just send - * PCIE_MSI_REQUEST_RES to the host. - * After host receive res msi interrupt, - * it will increase one vote in modem power manger. - */ - pr_info("pcie res: send request msi to rc.\n"); - ret = sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_REQUEST_RES); - break; - - case SPRD_PCIE_REMOVED: - /* - * if pcie state is removed, poll wake_up singnal - * to host, and he host will rescan the pcie. - */ - pr_info("pcie res: send wakeup to rc.\n"); - if (sprd_pci_epf_start(res->ep_fun) == 0) - break; - - /* may receive ep reset, wait linkup and scanned */ - pr_info("pcie res: later send request msi to rc.\n"); - res->msi_later = true; - break; - - default: - pr_err("pcie res: request res err, state=%d.\n", - res->state); - ret = -EPERM; - break; - } - - return ret; -} - -int sprd_pcie_release_resource(u32 dst) -{ - struct sprd_pcie_res *res; - int ret = 0; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return -EINVAL; - - switch (res->state) { - case SPRD_PCIE_SCANNED: - /* - * if pcie state is SCANNED, send PCIE_MSI_RELEASE_RES - * to the host, else, do nothing. After host receive res msi - * interrupt, it will decrease one vote in modem power manger, - * and if modem power manger is idle, the host will remove - * the pcie. - */ - pr_info("pcie res: send release msi to rc.\n"); - ret = sprd_pci_epf_raise_irq(res->ep_fun, - PCIE_MSI_RELEASE_RES); - break; - - case SPRD_PCIE_WAIT_FIRST_READY: - /* if has msi pending, remove it */ - if (res->msi_later) - res->msi_later = false; - break; - - default: - pr_err("pcie res: release res state=%d.\n", res->state); - ret = -EPERM; - break; - } - - return ret; -} - -int sprd_register_pcie_resource_first_ready(u32 dst, - void (*notify)(void *p), void *data) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - res->first_ready_notify.data = data; - res->first_ready_notify.notify = notify; - - return 0; -} - -bool sprd_pcie_is_defective_chip(void) -{ - static bool first_read = true, defective; - - if (first_read) { - first_read = false; - defective = sprd_kproperty_chipid("UD710-AB") == 0; - } - - return defective; -} diff --git a/quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c b/quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c deleted file mode 100644 index 5b75344..0000000 --- a/quectel_SRPD_PCIE/src/pcie/pcie_host_resource.c +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPRD_SIPA_RES -#include "pcie_sipa_res.h" -#endif - -#include "../include/pcie-rc-sprd.h" -#include "../include/sipc.h" -//#include "../include/mdm_ctrl.h" -#include "../include/sprd_pcie_ep_device.h" -#include "../include/sprd_mpm.h" -#include "../include/sprd_pcie_resource.h" - -#define PCIE_REMOVE_SCAN_GAP msecs_to_jiffies(200) -#define MAX_PMS_WAIT_TIME 5000 -#define MAX_PMS_DEFECTIVE_CHIP_FIRST_WAIT_TIME (55 * 1000) - -enum rc_state { - SPRD_PCIE_WAIT_FIRST_READY = 0, - SPRD_PCIE_WAIT_SCANNED, - SPRD_PCIE_SCANNED, - SPRD_PCIE_WAIT_REMOVED, - SPRD_PCIE_REMOVED, - SPRD_PCIE_SCANNED_2BAR, - SPRD_PCIE_WAIT_POWER_OFF -}; - -struct sprd_pcie_res { - u32 dst; - u32 ep_dev; - u32 state; - u32 scan_cnt; - u32 max_wait_time; - bool ep_power_on; - bool ep_dev_probe; - bool smem_send_to_ep; - unsigned long action_jiff; - - struct sprd_pms *pms; - char pms_name[20]; - - wait_queue_head_t wait_pcie_ready; - bool ep_ready_for_rescan; - wait_queue_head_t wait_load_ready; - wait_queue_head_t wait_first_rescan; - struct task_struct *thread; - -#ifdef CONFIG_SPRD_SIPA_RES - void *sipa_res; -#endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - struct wakeup_source *ws; -#else - struct wakeup_source ws; -#endif - struct work_struct scan_work; - struct work_struct remove_work; - struct workqueue_struct *wq; - - struct platform_device *pcie_dev; - struct sprd_pcie_register_event reg_event; -}; - -static int sprd_pcie_resource_rescan(struct sprd_pcie_res *res); - -static struct sprd_pcie_res *g_pcie_res[SIPC_ID_NR]; - -static void sprd_pcie_resource_host_first_rescan_do(struct sprd_pcie_res *res) -{ - int ret = sprd_pcie_register_event(&res->reg_event); - - if (ret) - pr_err("pcie res: register pci ret=%d.\n", ret); - - /* power up for ep after the first scan. */ - res->ep_power_on = true; - sprd_pms_power_up(res->pms); - -#ifdef CONFIG_SPRD_SIPA_RES - /* - * in host side, producer res id is SIPA_RM_RES_PROD_PCIE3, - * consumer res id is SIPA_RM_RES_CONS_WWAN_UL. - */ - res->sipa_res = pcie_sipa_res_create(res->dst, - SIPA_RM_RES_PROD_PCIE3, - SIPA_RM_RES_CONS_WWAN_UL); - if (!res->sipa_res) - pr_err("pcie res:create ipa res failed.\n"); -#endif - -} - -static void sprd_pcie_resource_host_ep_notify(int event, void *data) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)data; - u32 base, size; - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - switch (event) { - case PCIE_EP_PROBE: - /* set state to scanned */ - res->state = SPRD_PCIE_SCANNED; - res->scan_cnt++; - res->ep_dev_probe = true; - //modem_ctrl_enable_cp_event(); - - if (smem_get_area(SIPC_ID_MINIAP, &base, &size) == 0) - sprd_ep_dev_pass_smem(res->ep_dev, base, size); - - pr_info("pcie res: ep_notify, probed cnt=%d.\n", - res->scan_cnt); - - /* firsrt scan do somtehing */ - if (res->scan_cnt == 1) - sprd_pcie_resource_host_first_rescan_do(res); - - /* clear removed irq and notify ep scanned */ - sprd_ep_dev_clear_doolbell_irq(res->ep_dev, - PCIE_DBEL_EP_REMOVING); - sprd_ep_dev_raise_irq(res->ep_dev, PCIE_DBEL_EP_SCANNED); - - /* wakeup all blocked thread */ - wake_up_interruptible_all(&res->wait_pcie_ready); - break; - - case PCIE_EP_REMOVE: - pr_info("pcie res: ep_notify, removed.\n"); - res->state = SPRD_PCIE_REMOVED; - res->ep_dev_probe = false; - break; - - case PCIE_EP_PROBE_BEFORE_SPLIT_BAR: - res->state = SPRD_PCIE_SCANNED_2BAR; - res->ep_dev_probe = true; - pr_info("pcie res: probed before split bar.\n"); - if (!res->ep_ready_for_rescan) { - wake_up_interruptible_all(&res->wait_load_ready); - } else { - pr_info("pcie res: bar err, rescan.\n"); - sprd_pcie_resource_rescan(res); - } - break; - - default: - break; - } -} - -static irqreturn_t sprd_pcie_resource_host_irq_handler(int irq, void *private) -{ - struct sprd_pcie_res *res = (struct sprd_pcie_res *)private; - - if (irq == PCIE_MSI_REQUEST_RES) { - pr_info("pcie res: ep request res.\n"); - /* - * client modem power up, - * no need wake lock and no need wait resource. - */ - if (!res->ep_power_on) { - res->ep_power_on = true; - sprd_pms_power_up(res->pms); - } - - /* only after received ep request can backup the ep configs. */ - sprd_ep_dev_set_backup(res->ep_dev); - } else if (irq == PCIE_MSI_RELEASE_RES) { - pr_info("pcie res: ep release res.\n"); - /* - * client modem power down, - * no need wake lock. - */ - if (res->ep_power_on) { - res->ep_power_on = false; - sprd_pms_power_down(res->pms, false); - } - } else if (irq == PCIE_MSI_EP_READY_FOR_RESCAN) { - pr_info("pcie res: ep ready for rescan.\n"); - res->ep_ready_for_rescan = true; - wake_up_interruptible_all(&res->wait_first_rescan); - } - - return IRQ_HANDLED; -} - -static void sprd_pcie_resource_scan_fn(struct work_struct *work) -{ - unsigned long diff; - unsigned int delay; - int ret; - struct sprd_pcie_res *res = container_of(work, struct sprd_pcie_res, - scan_work); - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - /* request wakelock */ - sprd_pms_request_wakelock(res->pms); - - diff = jiffies - res->action_jiff; - if (diff < PCIE_REMOVE_SCAN_GAP) { - /* must ensure that the scan starts after a period of remove. */ - delay = jiffies_to_msecs(PCIE_REMOVE_SCAN_GAP - diff); - msleep(delay); - } - - pr_info("pcie res: scan\n"); - - ret = sprd_pcie_configure_device(res->pcie_dev); - if (ret) - pr_err("pcie res: scan error = %d!\n", ret); - - /* record the last scan jiffies */ - res->action_jiff = jiffies; - - /* release wakelock */ - sprd_pms_release_wakelock(res->pms); -} - -static void sprd_pcie_resource_remove_fn(struct work_struct *work) -{ - unsigned long diff; - unsigned int delay; - int ret; - struct sprd_pcie_res *res = container_of(work, struct sprd_pcie_res, - remove_work); - /* request wakelock */ - sprd_pms_request_wakelock(res->pms); - - pr_info("pcie res: remove work!\n"); - - diff = jiffies - res->action_jiff; - if (diff < PCIE_REMOVE_SCAN_GAP) { - /* must ensure that the remove starts after a period of scan. */ - delay = jiffies_to_msecs(PCIE_REMOVE_SCAN_GAP - diff); - msleep(delay); - } - - /* - * in wait power off state, or ep device is not probing, - * can't access ep. - */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF || - !res->ep_dev_probe) { - /* release wakelock */ - sprd_pms_release_wakelock(res->pms); - return; - } - - /* notify ep removed, must before removed */ - sprd_ep_dev_clear_doolbell_irq(res->ep_dev, PCIE_DBEL_EP_SCANNED); - sprd_ep_dev_raise_irq(res->ep_dev, PCIE_DBEL_EP_REMOVING); - - /* waiting for the doorbell irq to ep */ - msleep(50); - - pr_info("pcie res: remove\n"); - - /* start removed ep*/ - ret = sprd_pcie_unconfigure_device(res->pcie_dev); - if (ret) - pr_err("pcie res: remove error = %d.\n!", ret); - - /* record the last remov jiffies */ - res->action_jiff = jiffies; - - /* release wakelock */ - sprd_pms_release_wakelock(res->pms); -} - -static void sprd_pcie_resource_start_scan(struct sprd_pcie_res *res) -{ - if (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_WAIT_SCANNED) { - pr_info("pcie res: scanned, do nothing!\n"); - } else { - pr_info("pcie res: start scan!\n"); - queue_work(res->wq, &res->scan_work); - } -} - -static void sprd_pcie_resource_start_remove(struct sprd_pcie_res *res) -{ - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - if (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_WAIT_FIRST_READY - || (res->state == SPRD_PCIE_SCANNED_2BAR) - ) { - res->state = SPRD_PCIE_WAIT_REMOVED; - pr_info("pcie res: start remove."); - queue_work(res->wq, &res->remove_work); - } else { - pr_err("pcie res: start remove, err=%d.", res->state); - } -} - -static void sprd_pcie_resource_event_process(enum sprd_pcie_event event, - void *data) -{ - struct sprd_pcie_res *res = data; - - if (event == SPRD_PCIE_EVENT_WAKEUP) { - pr_info("pcie res: wakeup by ep, event=%d.\n", event); - if (!res->ep_power_on) { - res->ep_power_on = true; - sprd_pms_power_up(res->pms); - } - } -} - -/* - * sprd_pcie_resource_rescan - * Because the ep bar can only be split by ep itself, - * After all modem images be loaded at the first time, - * the ep will run and split 2 64bit bar to 4 32bit bar. - * host must rescan the pcie ep device agian by this api, - * after receive ep driver ready for rescan msg and all - * modem images load done. - */ -static int sprd_pcie_resource_rescan(struct sprd_pcie_res *res) -{ - pr_info("pcie res: rescan.\n"); - - sprd_pcie_resource_start_remove(res); - sprd_pcie_resource_start_scan(res); - - return 0; -} - -static int sprd_pcie_resource_check_first_rescan(void *data) -{ - struct sprd_pcie_res *res = data; - int ret; - - pr_info("pcie res: check first rescan.\n"); - - while (!kthread_should_stop()) { - ret = wait_event_interruptible( - res->wait_first_rescan, - res->ep_ready_for_rescan); - if (!ret) { - pr_info("pcie res:first resacn ready.\n"); - sprd_pcie_resource_rescan(res); - break; - } - } - - /* After the first rescan, restore the normal wait time. */ - if (sprd_pcie_is_defective_chip()) - res->max_wait_time = MAX_PMS_WAIT_TIME; - - res->thread = NULL; - return 0; -} - -#if 0 -static int sprd_pcie_resource_host_mcd(struct notifier_block *nb, - unsigned long mode, void *cmd) -{ - struct sprd_pcie_res *res; - int i; - u32 state; - - pr_info("pcie res: mcd mode=%ld.\n", mode); - - switch (mode) { - case MDM_POWER_OFF: - state = SPRD_PCIE_WAIT_POWER_OFF; - break; - - default: - return NOTIFY_DONE; - } - - for (i = 0; i < SIPC_ID_NR; i++) { - res = g_pcie_res[i]; - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - continue; - - if (res) { - res->state = state; - cancel_work_sync(&res->scan_work); - cancel_work_sync(&res->remove_work); - } - } - - return NOTIFY_DONE; -} - -static struct notifier_block mcd_notify = { - .notifier_call = sprd_pcie_resource_host_mcd, - .priority = 149, -}; -#endif - -/* Because the ep bar can only be split by ep itself, - * After all modem images be loaded, notify the pcie resource. - */ -void sprd_pcie_resource_notify_load_done(u32 dst) -{ - struct sprd_pcie_res *res; - - pr_info("pcie res: load done.\n"); - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return; - - res = g_pcie_res[dst]; - - res->thread = kthread_create(sprd_pcie_resource_check_first_rescan, res, - "first rescan"); - if (IS_ERR(res->thread)) - pr_err("pcie res: Failed to create rescan thread.\n"); - else - wake_up_process(res->thread); -} - -int sprd_pcie_wait_load_resource(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* can load image, return immediately */ - if (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_SCANNED_2BAR) - return 0; - - return wait_event_interruptible( - res->wait_load_ready, - (res->state == SPRD_PCIE_SCANNED || - res->state == SPRD_PCIE_SCANNED_2BAR)); -} - -void sprd_pcie_resource_reboot_ep(u32 dst) -{ - struct sprd_pcie_res *res; - - pr_info("pcie res: reboot ep.\n"); - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return; - - res = g_pcie_res[dst]; - - /* wait power off, do nothing */ - if (res->state == SPRD_PCIE_WAIT_POWER_OFF) - return; - - res->state = SPRD_PCIE_WAIT_FIRST_READY; - res->smem_send_to_ep = false; - res->ep_ready_for_rescan = false; - - /* The defective chip , the first wait time must be enough long. */ - if (sprd_pcie_is_defective_chip()) - res->max_wait_time = MAX_PMS_DEFECTIVE_CHIP_FIRST_WAIT_TIME; - else - res->max_wait_time = MAX_PMS_WAIT_TIME; - - /* after ep reboot, can't backup ep configs*/ - sprd_ep_dev_clear_backup(res->ep_dev); - - sprd_pcie_resource_start_remove(res); - //modem_ctrl_poweron_modem(MDM_CTRL_COLD_RESET); - sprd_pcie_resource_start_scan(res); -} - -int sprd_pcie_resource_host_init(u32 dst, u32 ep_dev, - struct platform_device *pcie_dev) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return -ENOMEM; - - res->wq = create_singlethread_workqueue("pcie_res"); - if (!res->wq) { - pr_err("pcie res:create wq failed.\n"); - kfree(res); - return -ENOMEM; - } - - init_waitqueue_head(&res->wait_load_ready); - init_waitqueue_head(&res->wait_first_rescan); - -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - res->ws = wakeup_source_register(NULL, "pcie_res"); -#else - wakeup_source_init(&res->ws, "pcie_res"); -#endif - - res->dst = dst; - res->state = SPRD_PCIE_WAIT_FIRST_READY; - res->pcie_dev = pcie_dev; - - /* The defective chip , the first wait time must be enough long. */ - if (sprd_pcie_is_defective_chip()) - res->max_wait_time = MAX_PMS_DEFECTIVE_CHIP_FIRST_WAIT_TIME; - else - res->max_wait_time = MAX_PMS_WAIT_TIME; - - init_waitqueue_head(&res->wait_pcie_ready); - INIT_WORK(&res->scan_work, sprd_pcie_resource_scan_fn); - INIT_WORK(&res->remove_work, sprd_pcie_resource_remove_fn); - - sprintf(res->pms_name, "ep-request-%d", dst); - res->pms = sprd_pms_create(dst, res->pms_name, false); - if (!res->pms) - pr_err("pcie res:create pms failed.\n"); - - sprd_ep_dev_register_irq_handler_ex(res->ep_dev, - PCIE_MSI_REQUEST_RES, - PCIE_MSI_RELEASE_RES, - sprd_pcie_resource_host_irq_handler, res); - - sprd_ep_dev_register_notify(res->ep_dev, - sprd_pcie_resource_host_ep_notify, res); - - //modem_ctrl_register_notifier(&mcd_notify); - - /* init wake up event callback */ - res->reg_event.events = SPRD_PCIE_EVENT_WAKEUP; - res->reg_event.pdev = pcie_dev; - res->reg_event.callback = sprd_pcie_resource_event_process; - res->reg_event.data = res; - - g_pcie_res[dst] = res; - - return 0; -} - -int sprd_pcie_resource_trash(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - if (!IS_ERR_OR_NULL(res->thread)) - kthread_stop(res->thread); - -#ifdef CONFIG_SPRD_SIPA_RES - if (res->sipa_res) - pcie_sipa_res_destroy(res->sipa_res); -#endif - - cancel_work_sync(&res->scan_work); - cancel_work_sync(&res->remove_work); - destroy_workqueue(res->wq); - - sprd_pcie_deregister_event(&res->reg_event); - - sprd_ep_dev_unregister_irq_handler_ex(res->ep_dev, - PCIE_MSI_REQUEST_RES, - PCIE_MSI_RELEASE_RES); - sprd_ep_dev_unregister_notify(res->ep_dev); - //modem_ctrl_unregister_notifier(&mcd_notify); - sprd_pms_destroy(res->pms); - - kfree(res); - g_pcie_res[dst] = NULL; - - return 0; -} - -int sprd_pcie_wait_resource(u32 dst, int timeout) -{ - struct sprd_pcie_res *res; - int ret, wait; - unsigned long delay; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* pcie ready, return succ immediately. */ - if (res->state == SPRD_PCIE_SCANNED) - return 0; - - if (timeout == 0) - return -ETIME; - - /* - * In some case, orca may has an exception, And the pcie - * resource may never ready again. So we must set a - * maximum wait time for let user to know thereis an - * exception in pcie, and can return an error code to the user. - */ - if (timeout < 0 || timeout > res->max_wait_time) - timeout = res->max_wait_time; - - /* - * timeout must add 1s, - * because the pcie scan may took some time. - */ - delay = msecs_to_jiffies(timeout + 1000); - wait = wait_event_interruptible_timeout(res->wait_pcie_ready, - res->state == - SPRD_PCIE_SCANNED, - delay); - if (wait == 0) - ret = -ETIME; - else if (wait > 0) - ret = 0; - else - ret = wait; - - - if (ret < 0 && ret != -ERESTARTSYS) - pr_err("pcie res: wait resource, val=%d.\n", ret); - - return ret; -} - -int sprd_pcie_request_resource(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* get a wakelock */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_stay_awake(res->ws); -#else - __pm_stay_awake(&res->ws); -#endif - - pr_info("pcie res: request resource, state=%d.\n", res->state); - -#ifdef CONFIG_SPRD_PCIE - /* The first scan is start by pcie driver automatically. */ - if (res->state != SPRD_PCIE_WAIT_FIRST_READY) - sprd_pcie_resource_start_scan(res); -#endif - - return 0; -} - -int sprd_pcie_release_resource(u32 dst) -{ - struct sprd_pcie_res *res; - - if (dst >= SIPC_ID_NR || !g_pcie_res[dst]) - return -EINVAL; - - res = g_pcie_res[dst]; - - /* relax a wakelock */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_relax(res->ws); -#else - __pm_relax(&res->ws); -#endif - -#ifdef CONFIG_SPRD_PCIE - pr_info("pcie res: release resource.\n"); - - sprd_pcie_resource_start_remove(res); -#endif - return 0; -} - -bool sprd_pcie_is_defective_chip(void) -{ -#ifndef CONFIG_SPRD_PCIE - return false; -#else - static bool first_read = true, defective; - - if (first_read) { - first_read = false; - defective = sprd_kproperty_chipid("UD710-AB") == 0; - } - - return defective; -#endif -} diff --git a/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c b/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c deleted file mode 100644 index dea3da3..0000000 --- a/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2018-2019 Unisoc Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ -#include -#include -#include -#include - -#include "pcie_sipa_res.h" -#include "../include/sprd_pcie_resource.h" - -struct pcie_sipa_res_prod { - u8 dst; - enum sipa_rm_res_id prod_id; /* producer res id */ - enum sipa_rm_res_id cons_id; /* consumer res id */ - struct sprd_pms *pms; - char pms_name[20]; - struct work_struct wait_work; - struct delayed_work rm_work; -}; - -static void pcie_sipa_res_wait_res_work_fn(struct work_struct *work) -{ - int ret; - struct pcie_sipa_res_prod *res = container_of(work, - struct pcie_sipa_res_prod, - wait_work); - - ret = sprd_pcie_wait_resource(res->dst, -1); - - /* pcie not ready, just return. */ - if (ret) { - pr_err("pcie_sipa_res: wait res error = %d!\n", ret); - return; - } - - /* notify ipa module that pcie is ready. */ - sipa_rm_notify_completion(SIPA_RM_EVT_GRANTED, - res->prod_id); -} - -static int pcie_sipa_res_request_resource(void *data) -{ - int ret; - struct pcie_sipa_res_prod *res = data; - - pr_info("pcie_sipa_res: request resource.\n"); - - sprd_pms_power_up(res->pms); - - /* - * when the resource is not ready, the IPA module doesn't want be - * blocked in here until the pcie ready, the IPA owner designed - * a notification api sipa_rm_notify_completion to notify the - * IPA module that the resource requested by IPA is ready. - * The designated error value is -EINPROGRESS, so we must override the - * return value -ETIME to -EINPROGRESS. - */ - ret = sprd_pcie_wait_resource(res->dst, 0); - - if (ret == -ETIME) { - /* add a work to wait pcie ready */ - schedule_work(&res->wait_work); - ret = -EINPROGRESS; - } - - return ret; -} - -static int pcie_sipa_res_release_resource(void *data) -{ - struct pcie_sipa_res_prod *res = data; - - pr_info("pcie_sipa_res: release resource.\n"); - - sprd_pms_release_resource(res->pms); - - return 0; -} - -static void pcie_sipa_res_create_rm_work_fn(struct work_struct *work) -{ - int ret; - struct sipa_rm_create_params rm_params; - struct pcie_sipa_res_prod *res = container_of(to_delayed_work(work), - struct pcie_sipa_res_prod, - rm_work); - - rm_params.name = res->prod_id; - rm_params.floor_voltage = 0; - rm_params.reg_params.notify_cb = NULL; - rm_params.reg_params.user_data = res; - rm_params.request_resource = pcie_sipa_res_request_resource; - rm_params.release_resource = pcie_sipa_res_release_resource; - ret = sipa_rm_create_resource(&rm_params); - - /* defer to create rm */ - if (ret == -EPROBE_DEFER) { - schedule_delayed_work(&res->rm_work, msecs_to_jiffies(1000)); - return; - } - - /* add dependencys */ - ret = sipa_rm_add_dependency(res->cons_id, res->prod_id); - if (ret < 0 && ret != -EINPROGRESS) { - pr_err("pcie_sipa_res: add_dependency error = %d!\n", ret); - sipa_rm_delete_resource(res->prod_id); - sprd_pms_destroy(res->pms); - kfree(res); - } -} - -void *pcie_sipa_res_create(u8 dst, enum sipa_rm_res_id prod_id, - enum sipa_rm_res_id cons_id) -{ - int ret; - struct sipa_rm_create_params rm_params; - struct pcie_sipa_res_prod *res; - - res = kzalloc(sizeof(*res), GFP_KERNEL); - if (!res) - return NULL; - - /* init wait pcie res work */ - INIT_WORK(&res->wait_work, pcie_sipa_res_wait_res_work_fn); - INIT_DELAYED_WORK(&res->rm_work, pcie_sipa_res_create_rm_work_fn); - - /* create pms */ - strncpy(res->pms_name, "sipa", sizeof(res->pms_name)); - res->pms = sprd_pms_create(dst, res->pms_name, false); - if (!res->pms) { - pr_err("pcie_sipa_res: create pms failed!\n"); - kfree(res); - return NULL; - } - - res->dst = dst; - res->prod_id = prod_id; - res->cons_id = cons_id; - - /* create prod */ - rm_params.name = prod_id; - rm_params.floor_voltage = 0; - rm_params.reg_params.notify_cb = NULL; - rm_params.reg_params.user_data = res; - rm_params.request_resource = pcie_sipa_res_request_resource; - rm_params.release_resource = pcie_sipa_res_release_resource; - ret = sipa_rm_create_resource(&rm_params); - - /* defer to create rm */ - if (ret == -EPROBE_DEFER) { - schedule_delayed_work(&res->rm_work, msecs_to_jiffies(1000)); - return res; - } else if (ret) { - pr_err("pcie_sipa_res: create rm error = %d!\n", ret); - sprd_pms_destroy(res->pms); - kfree(res); - return NULL; - } - - /* add dependencys */ - ret = sipa_rm_add_dependency(cons_id, prod_id); - if (ret < 0 && ret != -EINPROGRESS) { - pr_err("pcie_sipa_res: add_dependency error = %d!\n", ret); - sipa_rm_delete_resource(prod_id); - sprd_pms_destroy(res->pms); - kfree(res); - return NULL; - } - - return res; -} - -void pcie_sipa_res_destroy(void *data) -{ - struct pcie_sipa_res_prod *res = data; - - cancel_work_sync(&res->wait_work); - cancel_delayed_work_sync(&res->rm_work); - - sprd_pms_destroy(res->pms); - sipa_rm_delete_dependency(res->cons_id, res->prod_id); - sipa_rm_delete_resource(res->prod_id); - kfree(res); -} - diff --git a/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h b/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h deleted file mode 100644 index 144bcc5..0000000 --- a/quectel_SRPD_PCIE/src/pcie/pcie_sipa_res.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018-2019 Unisoc Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#ifndef PCIE_SIPA_RES_H -#define PCIE_SIPA_RES_H - -#include "../include/sipa.h" - -/* - * pcie_sipa_res_create - create pcie res for sipa module. - * @prod_id: which res is the producer. - * @cons_id: which res is the consumer. - * - * Returns: - * failed, return NULL, - * succ, return a void * pointer. - */ -void *pcie_sipa_res_create(u8 dst, enum sipa_rm_res_id prod_id, - enum sipa_rm_res_id cons_id); - -/* - * pcie_sipa_res_destroy -detroy pcie res for sipa module - * @res_id: the return point of call function pcie_sipa_res_create. - */ -void pcie_sipa_res_destroy(void *res); -#endif - diff --git a/quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c b/quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c deleted file mode 100644 index af6b922..0000000 --- a/quectel_SRPD_PCIE/src/pcie/sprd_pcie_ep_device.c +++ /dev/null @@ -1,1663 +0,0 @@ -/** - * SPRD ep device driver in host side for Spreadtrum SoCs - * - * Copyright (C) 2018 Spreadtrum Co., Ltd. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * This program is used to control ep device driver in host side for - * Spreadtrum SoCs. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../include/pcie-rc-sprd.h" -#include "../include/sprd_pcie_ep_device.h" -#include "../include/sipc_big_to_little.h" -#include "../include/sprd_pcie_resource.h" -#include "../include/sipc.h" -#include "../include/sipa.h" -#include "../sipa/sipa_core.h" - -#define DRV_MODULE_NAME "sprd-pcie-ep-device" -#define CONFIG_SPRD_IPA_PCIE_WORKROUND - -enum dev_pci_barno { - BAR_0 = 0, - BAR_1, - BAR_2, - BAR_3, - BAR_4, - BAR_5, - BAR_CNT -}; - -#define MAX_SUPPORT_IRQ 32 -#define IPA_HW_IRQ_CNT 4 -#define IPA_HW_IRQ_BASE 16 -#define IPA_HW_IRQ_BASE_DEFECT 0 - -#define REQUEST_BASE_IRQ (IPA_HW_IRQ_BASE + IPA_HW_IRQ_CNT) -#define REQUEST_BASE_IRQ_DEFECT 16 - -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND -/* the bar0 and the bar1 are used for ipa */ -#define IPA_MEM_BAR BAR_0 -#define IPA_REG_BAR BAR_1 -#define BAR_MIN BAR_2 -#else -#define BAR_MIN BAR_0 -#endif - -/* the bar4 and the bar5 are specail bars */ -#define BAR_MAX BAR_4 - -#define PCI_VENDOR_ID_SPRD 0x16c3 -#define PCI_DEVICE_ID_SPRD_ORCA 0xabcd -#define PCI_CLASS_ID_SPRD_ORCA 0x80d00 - -/* Parameters for the waiting for iATU enabled routine */ -#define LINK_WAIT_MAX_IATU_RETRIES 5 -#define LINK_WAIT_IATU_MIN 9000 -#define LINK_WAIT_IATU_MAX 10000 - -/* ep config bar bar4 , can config ep iatu reg and door bell reg */ -#define EP_CFG_BAR BAR_4 -#define DOOR_BELL_BASE 0x00000 -#define IATU_REG_BASE 0x10000 - -#define DOOR_BELL_ENABLE 0x10 -#define DOOR_BELL_STATUS 0x14 - -/* used 0x18 & 0x1c to save the smem base & size. */ -#define DOOR_BELL_SMEMBASE 0x18 -#define DOOR_BELL_SMEMSIZE 0x1C - -/* one bit can indicate one irq , if stauts[i] & enable[i] , irq = i */ -#define DOOR_BELL_IRQ_VALUE(irq) BIT((irq)) -#define DOOR_BELL_IRQ_CNT 32 -#define IATU_MAX_REGION 8 -#define PCIE_ATU_VIEWPORT 0x900 -#define PCIE_ATU_CR1 0x904 -#define PCIE_ATU_CR2 0x908 -#define PCIE_ATU_LOWER_BASE 0x90c -#define PCIE_ATU_UPPER_BASE 0x910 -#define PCIE_ATU_LIMIT 0x914 -#define PCIE_ATU_LOWER_TARGET 0x918 -#define PCIE_ATU_UPPER_TARGET 0x91c - -#define PCIE_ATU_REGION_INBOUND BIT(31) -#define PCIE_ATU_ENABLE BIT(31) -#define PCIE_ATU_BAR_MODE_ENABLE BIT(30) -#define PCIE_ATU_TYPE_MEM 0x0 - -#define PCIE_ATU_UNR_REGION_CTRL1 0x00 -#define PCIE_ATU_UNR_REGION_CTRL2 0x04 -#define PCIE_ATU_UNR_LOWER_BASE 0x08 -#define PCIE_ATU_UNR_UPPER_BASE 0x0c -#define PCIE_ATU_UNR_LIMIT 0x10 -#define PCIE_ATU_UNR_LOWER_TARGET 0x14 -#define PCIE_ATU_UNR_UPPER_TARGET 0x18 - -/* bar4 + 0x10000 has map to ep base + 0x18000 ((0x3 << 15)) */ -#define PCIE_ATU_IB_REGION(region) (((region) << 9) | (0x1 << 8)) -#define PCIE_ATU_OB_REGION(region) ((region) << 9) - -#define PCIE_SAVE_REGION_NUM (IATU_MAX_REGION * 2) -#define PCIE_SAVE_REG_NUM 8 - -#define PCIE_LEGACY_CLEAR_BASE 0x29000000 -#define PCIE_LEGACY_CLEAR_REG 0x2c -#define PCIE_LEGACY_CLEAR_MASK BIT(0) -#define BIT_SET_OFFSET 0x1000 -#define BIT_CLR_OFFSET 0x2000 - -struct sprd_ep_dev_notify { - void (*notify)(int event, void *data); - void *data; -}; - -struct sprd_pci_ep_dev { - struct pci_dev *pdev; - void __iomem *cfg_base; /* ep config bar base in rc */ - spinlock_t irq_lock; /* irq spinlock */ - spinlock_t bar_lock; /* bar spinlock */ - spinlock_t set_irq_lock; /* set irq spinlock */ - spinlock_t set_bar_lock; /* set bar spinlock */ - unsigned long bar_res; - - u32 base_irq; - u32 ipa_base_irq; - u32 bak_irq_status; - u8 iatu_unroll_enabled; - u8 ep; - u8 irq_cnt; - bool no_msi; - bool need_backup; - void __iomem *legacy_addr; - - struct resource *bar[BAR_CNT]; - void __iomem *bar_vir[BAR_MAX]; - void __iomem *cpu_vir[BAR_MAX]; - dma_addr_t src_addr[BAR_MAX]; - dma_addr_t target_addr[BAR_MAX]; - size_t map_size[BAR_MAX]; - int event; - struct work_struct notify_work; -}; - -struct sprd_pci_ep_dev_save { - bool save_succ; - unsigned long bar_res; - void __iomem *bar_vir[BAR_MAX]; - void __iomem *cpu_vir[BAR_MAX]; - dma_addr_t src_addr[BAR_MAX]; - dma_addr_t target_addr[BAR_MAX]; - size_t map_size[BAR_MAX]; - u32 doorbell_enable; - u32 doorbell_status; - void __iomem *cfg_base; - u32 save_reg[PCIE_SAVE_REGION_NUM][PCIE_SAVE_REG_NUM]; -}; - -#define VERSION_NUMBER "V1.1.6" -#define QUECTEL_SPRD_PCIE_VERSION "Quectel_Linux&Android_SPRD_PCIE_Driver_"VERSION_NUMBER - -static void __iomem *g_irq_addr[PCIE_EP_NR]; -static struct sprd_pci_ep_dev_save g_ep_save[PCIE_EP_NR]; -static struct sprd_pci_ep_dev *g_ep_dev[PCIE_EP_NR]; -static irq_handler_t ep_dev_handler[PCIE_EP_NR][PCIE_MSI_MAX_IRQ]; -static void *ep_dev_handler_data[PCIE_EP_NR][PCIE_MSI_MAX_IRQ]; -static struct sprd_ep_dev_notify g_ep_dev_notify[PCIE_EP_NR]; - -static int sprd_ep_dev_get_bar(int ep); -static int sprd_ep_dev_put_bar(int ep, int bar); -static int sprd_ep_dev_adjust_region(struct sprd_pci_ep_dev *ep_dev, - int bar, dma_addr_t *cpu_addr_ptr, - size_t *size_ptr, dma_addr_t *offset_ptr); -static int sprd_ep_dev_just_map_bar(struct sprd_pci_ep_dev *ep_dev, int bar, - dma_addr_t cpu_addr, size_t size); -static int sprd_ep_dev_just_unmap_bar(struct sprd_pci_ep_dev *ep_dev, int bar); -static void __iomem *sprd_ep_dev_map_bar(int ep, int bar, - dma_addr_t cpu_addr, - size_t size); -static int sprd_ep_dev_unmap_bar(int ep, int bar); -static void sprd_pci_ep_dev_backup(struct sprd_pci_ep_dev *ep_dev); - -static void sprd_pcie_iommu_init(struct device *dev) -{ - struct iommu_domain *domain = NULL; - unsigned long pg_size; - dma_addr_t start, end, addr; - u32 base, size; - int ret = 0; - - domain = iommu_get_domain_for_dev(dev); - if(!domain) { - dev_info(dev, "sprd_pcie_iommu_init domian null"); - return; - } - - pg_size = 1UL << __ffs(domain->pgsize_bitmap); - smem_get_area(SIPC_ID_MINIAP, &base, &size); - start = ALIGN(base, pg_size); - end = ALIGN(base + size, pg_size); - - for (addr = start; addr < end; addr += pg_size) { - phys_addr_t phys_addr; - - phys_addr = iommu_iova_to_phys(domain, addr); - if (phys_addr) { - dev_info(dev, "sprd_pcie_iommu_init iova:%d have been used", (u32)addr); - continue; - } - ret = iommu_map(domain, addr, addr, pg_size, IOMMU_READ | IOMMU_WRITE); - if (ret) { - dev_info(dev, "sprd_pcie_iommu_init iommu_map failed"); - return; - } - } -} - - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,11,0 )) -int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) -{ - int nvec = maxvec; - int rc; - - if (maxvec < minvec) - return -ERANGE; - - do { - rc = pci_enable_msi_block(dev, nvec); - if (rc < 0) { - return rc; - } else if (rc > 0) { - if (rc < minvec) - return -ENOSPC; - nvec = rc; - } - } while (rc); - - return nvec; -} -#endif - -int sprd_ep_dev_register_notify(int ep, - void (*notify)(int event, void *data), - void *data) -{ - struct sprd_ep_dev_notify *dev_notify; - - if (ep >= PCIE_EP_NR) - return -EINVAL; - - dev_notify = &g_ep_dev_notify[ep]; - dev_notify->notify = notify; - dev_notify->data = data; - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_register_notify); - -int sprd_ep_dev_unregister_notify(int ep) -{ - struct sprd_ep_dev_notify *notify; - - if (ep >= PCIE_EP_NR) - return -EINVAL; - - notify = &g_ep_dev_notify[ep]; - notify->notify = NULL; - notify->data = NULL; - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_unregister_notify); - -int sprd_ep_dev_set_irq_addr(int ep, void __iomem *irq_addr) -{ - if (ep >= PCIE_EP_NR) - return -EINVAL; - - g_irq_addr[ep] = irq_addr; - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_set_irq_addr); - -int sprd_ep_dev_register_irq_handler(int ep, int irq, - irq_handler_t handler, void *data) -{ - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || irq >= PCIE_MSI_MAX_IRQ) - return -EINVAL; - - ep_dev_handler[ep][irq] = handler; - ep_dev_handler_data[ep][irq] = data; - ep_dev = g_ep_dev[ep]; - - if (handler && ep_dev && - (BIT(irq) & ep_dev->bak_irq_status)) { - ep_dev->bak_irq_status &= ~BIT(irq); - handler(irq, data); - } - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_register_irq_handler); - -int sprd_ep_dev_unregister_irq_handler(int ep, int irq) -{ - if (ep < PCIE_EP_NR && irq < PCIE_MSI_MAX_IRQ) { - ep_dev_handler[ep][irq] = NULL; - ep_dev_handler_data[ep][irq] = NULL; - return 0; - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_unregister_irq_handler); - -int sprd_ep_dev_register_irq_handler_ex(int ep, - int from_irq, - int to_irq, - irq_handler_t handler, - void *data) -{ - int i, ret; - - for (i = from_irq; i < to_irq + 1; i++) { - ret = sprd_ep_dev_register_irq_handler(ep, - i, handler, data); - if (ret) - return ret; - } - - return 0; -} - -int sprd_ep_dev_unregister_irq_handler_ex(int ep, - int from_irq, - int to_irq) -{ - int i, ret; - - for (i = from_irq; i < to_irq + 1; i++) { - ret = sprd_ep_dev_unregister_irq_handler(ep, i); - if (ret) - return ret; - } - - return 0; -} - -void __iomem *sprd_ep_map_memory(int ep, - phys_addr_t cpu_addr, - size_t size) -{ - int bar; - void __iomem *bar_addr; - - bar = sprd_ep_dev_get_bar(ep); - if (bar < 0) { - pr_err("%s: get bar err = %d\n", __func__, bar); - return NULL; - } - - bar_addr = sprd_ep_dev_map_bar(ep, bar, cpu_addr, size); - if (!bar_addr) { - pr_err("%s: map bar = %d err!\n", __func__, bar); - sprd_ep_dev_put_bar(ep, bar); - return NULL; - } - - return bar_addr; -} -EXPORT_SYMBOL_GPL(sprd_ep_map_memory); - -void sprd_ep_unmap_memory(int ep, const void __iomem *bar_addr) -{ - int bar; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return; - - ep_dev = g_ep_dev[ep]; - - for (bar = 0; bar < BAR_MAX; bar++) { - if (bar_addr == ep_dev->cpu_vir[bar]) { - sprd_ep_dev_unmap_bar(ep, bar); - sprd_ep_dev_put_bar(ep, bar); - break; - } - } -} -EXPORT_SYMBOL_GPL(sprd_ep_unmap_memory); - -#ifdef CONFIG_SPRD_SIPA -phys_addr_t sprd_ep_ipa_map(int type, phys_addr_t target_addr, size_t size) -{ - int bar, ep = PCIE_EP_MODEM; - dma_addr_t offset; - struct sprd_pci_ep_dev *ep_dev; - struct pci_dev *pdev; - struct device *dev; - struct resource *res; - - ep_dev = g_ep_dev[ep]; - if (!ep_dev) - return 0; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - bar = type == PCIE_IPA_TYPE_MEM ? IPA_MEM_BAR : IPA_REG_BAR; -#else - bar = sprd_ep_dev_get_bar(ep); - if (bar < 0) { - dev_err(dev, "ep: ipa map, get bar err = %d\n", bar); - return 0; - } -#endif - res = &pdev->resource[bar]; - - dev_info(dev, "ep: ipa map type=%d, addr=0x%lx, size=0x%lx\n", - type, - (unsigned long)target_addr, - (unsigned long)size); - - /* 1st, adjust the map region */ - if (sprd_ep_dev_adjust_region(ep_dev, bar, &target_addr, - &size, &offset)) - return 0; - - /* than, map bar */ - if (sprd_ep_dev_just_map_bar(ep_dev, bar, target_addr, size)) - return 0; - - /* save for unmap */ - ep_dev->src_addr[bar] = res->start + offset; - ep_dev->target_addr[bar] = target_addr; - ep_dev->map_size[bar] = size; - - /* return the cpu phy address */ - return res->start + offset; -} - -int sprd_ep_ipa_unmap(int type, const phys_addr_t cpu_addr) -{ - int bar, ep = PCIE_EP_MODEM; - bool find_bar = false; - struct sprd_pci_ep_dev *ep_dev; - struct pci_dev *pdev; - struct resource *res; - - ep_dev = g_ep_dev[ep]; - if (!ep_dev) - return -EINVAL; - - pdev = ep_dev->pdev; - res = &pdev->resource[bar]; - - dev_info(&pdev->dev, "ep: ipa unmap cpu_addr=0x%lx\n", - (unsigned long)cpu_addr); - -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - bar = type == PCIE_IPA_TYPE_MEM ? IPA_MEM_BAR : IPA_REG_BAR; - if (ep_dev->src_addr[bar] == cpu_addr) - find_bar = true; -#else - for (bar = 0; bar < BAR_MAX; bar++) { - if (cpu_addr == ep_dev->src_addr[bar]) { - find_bar = true; - break; - } - } -#endif - - if (!find_bar) { - dev_err(&pdev->dev, "ep: ipa unmap can't find bar!"); - return -EINVAL; - } - - ep_dev->target_addr[bar] = 0; - ep_dev->target_addr[bar] = 0; - ep_dev->map_size[bar] = 0; - return sprd_ep_dev_just_unmap_bar(ep_dev, bar); -} -#endif - -int sprd_ep_dev_raise_irq(int ep, int irq) -{ - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - void __iomem *base; - u32 value; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: raise, ep=%d, irq=%d\n", ep, irq); - - if (irq >= DOOR_BELL_IRQ_CNT) { - dev_err(&pdev->dev, "raise err, irq=%d\n", irq); - return -EINVAL; - } - - spin_lock(&ep_dev->set_irq_lock); - base = ep_dev->cfg_base + DOOR_BELL_BASE; - value = readl_relaxed(base + DOOR_BELL_STATUS); - writel_relaxed(value | DOOR_BELL_IRQ_VALUE(irq), - base + DOOR_BELL_STATUS); - spin_unlock(&ep_dev->set_irq_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(sprd_ep_dev_raise_irq); - -int sprd_ep_dev_clear_doolbell_irq(int ep, int irq) -{ - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - void __iomem *base; - u32 value; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: clear doorbell, ep=%d, irq=%d\n", ep, irq); - - if (irq >= DOOR_BELL_IRQ_CNT) - return -EINVAL; - - spin_lock(&ep_dev->set_irq_lock); - base = ep_dev->cfg_base + DOOR_BELL_BASE; - value = readl_relaxed(base + DOOR_BELL_STATUS); - if (value & DOOR_BELL_IRQ_VALUE(irq)) - writel_relaxed(value & (~DOOR_BELL_IRQ_VALUE(irq)), - base + DOOR_BELL_STATUS); - spin_unlock(&ep_dev->set_irq_lock); - - return 0; -} - -int sprd_ep_dev_set_backup(int ep) -{ - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - ep_dev->need_backup = true; - - /* backup once immediately. */ - sprd_pci_ep_dev_backup(ep_dev); - - return 0; -} - -int sprd_ep_dev_clear_backup(int ep) -{ - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - ep_dev->need_backup = false; - - return 0; -} - -int sprd_ep_dev_pass_smem(int ep, u32 base, u32 size) -{ - struct sprd_pci_ep_dev *ep_dev; - void __iomem *reg_base; - struct pci_dev *pdev; - struct device *dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - dev_info(&pdev->dev, - "pass_smem, base=0x%x,size=0x%x\n", - base, size); - - reg_base = ep_dev->cfg_base + DOOR_BELL_BASE; - - writel_relaxed(base, reg_base + DOOR_BELL_SMEMBASE); - writel_relaxed(size, reg_base + DOOR_BELL_SMEMSIZE); - - return 0; -} - -static inline u32 sprd_pci_ep_iatu_readl(struct sprd_pci_ep_dev *ep_dev, - u32 offset) -{ - return readl_relaxed(ep_dev->cfg_base + IATU_REG_BASE + offset); -} - -static inline void sprd_pci_ep_iatu_writel(struct sprd_pci_ep_dev *ep_dev, - u32 offset, u32 value) -{ - writel_relaxed(value, ep_dev->cfg_base + IATU_REG_BASE + offset); -} - -static int sprd_ep_dev_get_bar(int ep) -{ - int bar; - int ret = -EBUSY; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - spin_lock(&ep_dev->bar_lock); - for (bar = BAR_MIN; bar < BAR_MAX; bar++) { - if (ep_dev->bar[bar] && !test_bit(bar, &ep_dev->bar_res)) { - set_bit(bar, &ep_dev->bar_res); - ret = bar; - break; - } - } - spin_unlock(&ep_dev->bar_lock); - - return ret; -} - -static int sprd_ep_dev_put_bar(int ep, int bar) -{ - int ret = -ENODEV; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - spin_lock(&ep_dev->bar_lock); - if (test_and_clear_bit(bar, &ep_dev->bar_res)) - ret = bar; - spin_unlock(&ep_dev->bar_lock); - - return ret; -} - -static int sprd_ep_dev_unr_set_bar(struct sprd_pci_ep_dev *ep_dev, - int bar, - dma_addr_t cpu_addr, size_t size) -{ - u32 retries, val; - struct pci_dev *pdev = ep_dev->pdev; - - spin_lock(&ep_dev->set_bar_lock); - - /* bar n use region n to map, map to bar match mode */ - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_LOWER_TARGET, - lower_32_bits(cpu_addr)); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_UPPER_TARGET, - upper_32_bits(cpu_addr)); - - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL1, - PCIE_ATU_TYPE_MEM); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL2, - PCIE_ATU_ENABLE | - PCIE_ATU_BAR_MODE_ENABLE | (bar << 8)); - - spin_unlock(&ep_dev->set_bar_lock); - - /* - * Make sure ATU enable takes effect before any subsequent config - * and I/O accesses. - */ - for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { - val = sprd_pci_ep_iatu_readl(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL2); - if (val & PCIE_ATU_ENABLE) - return 0; - - dev_dbg(&pdev->dev, - "ep: unr set bar[%d], var = 0x%x\n", - bar, - val); - /* wait a moment for polling ep atu enable bit */ - usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX); - } - - return -EINVAL; -} - -static int sprd_ep_dev_unr_clear_bar(struct sprd_pci_ep_dev *ep_dev, int bar) -{ - struct pci_dev *pdev = ep_dev->pdev; - - dev_dbg(&pdev->dev, "ep: unr clear map bar=%d\n", bar); - - spin_lock(&ep_dev->set_bar_lock); - - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_IB_REGION(bar) + - PCIE_ATU_UNR_REGION_CTRL2, - (u32)(~PCIE_ATU_ENABLE)); - spin_unlock(&ep_dev->set_bar_lock); - - return 0; -} - -static int sprd_ep_dev_adjust_region(struct sprd_pci_ep_dev *ep_dev, int bar, - dma_addr_t *cpu_addr_ptr, - size_t *size_ptr, - dma_addr_t *offset_ptr) -{ - dma_addr_t cpu_addr, base, offset; - resource_size_t bar_size, size; - struct pci_dev *pdev = ep_dev->pdev; - struct resource *res = &pdev->resource[bar]; - - size = (resource_size_t)*size_ptr; - cpu_addr = *cpu_addr_ptr; - bar_size = resource_size(res); - - /* size must align with page */ - size = PAGE_ALIGN(size); - - /* base must be divisible by bar size for bar match mode */ - base = cpu_addr / bar_size * bar_size; - offset = cpu_addr - base; - size += PAGE_ALIGN(offset); - - /* size must < bar size */ - if (size > bar_size) { - dev_err(&pdev->dev, - "bar[%d]:size=0x%lx > 0x%lx\n", - bar, - (unsigned long)size, - (unsigned long)bar_size); - return -EINVAL; - } - - dev_dbg(&pdev->dev, - "bar[%d]: base=0x%lx,size=0x%lx,offset=0x%lx\n", - bar, (unsigned long)base, - (unsigned long)size, - (unsigned long)offset); - - *size_ptr = (size_t)size; - *offset_ptr = offset; - *cpu_addr_ptr = base; - - return 0; -} - -static int sprd_ep_dev_just_map_bar(struct sprd_pci_ep_dev *ep_dev, int bar, - dma_addr_t cpu_addr, size_t size) -{ - u32 retries, val; - struct pci_dev *pdev; - struct device *dev; - - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: map bar=%d, addr=0x%lx, size=0x%lx\n", - bar, - (unsigned long)cpu_addr, - (unsigned long)size); - - if (ep_dev->iatu_unroll_enabled) - return sprd_ep_dev_unr_set_bar(ep_dev, bar, cpu_addr, size); - - spin_lock(&ep_dev->set_bar_lock); - - /* bar n use region n to map, map to bar match mode */ - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_VIEWPORT, - PCIE_ATU_REGION_INBOUND | bar); - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_LOWER_TARGET, - lower_32_bits(cpu_addr)); - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_UPPER_TARGET, - upper_32_bits(cpu_addr)); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_CR1, - PCIE_ATU_TYPE_MEM); - sprd_pci_ep_iatu_writel(ep_dev, - PCIE_ATU_CR2, - PCIE_ATU_ENABLE | - PCIE_ATU_BAR_MODE_ENABLE | (bar << 8)); - - spin_unlock(&ep_dev->set_bar_lock); - - /* - * Make sure ATU enable takes effect - * before any subsequent config and I/O accesses. - */ - for (retries = 0; - retries < LINK_WAIT_MAX_IATU_RETRIES; - retries++) { - val = sprd_pci_ep_iatu_readl(ep_dev, PCIE_ATU_CR2); - if (val & PCIE_ATU_ENABLE) - return 0; - - /* wait a moment for polling ep atu enable bit */ - usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX); - } - - return -EINVAL; -} - -static int sprd_ep_dev_just_unmap_bar(struct sprd_pci_ep_dev *ep_dev, int bar) -{ - struct pci_dev *pdev; - struct device *dev; - - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_dbg(dev, "ep: unmap bar = %d\n", bar); - - if (ep_dev->iatu_unroll_enabled) - return sprd_ep_dev_unr_clear_bar(ep_dev, bar); - - spin_lock(&ep_dev->set_bar_lock); - - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_VIEWPORT, - PCIE_ATU_REGION_INBOUND | bar); - sprd_pci_ep_iatu_writel(ep_dev, PCIE_ATU_CR2, - (u32)(~PCIE_ATU_ENABLE)); - - spin_unlock(&ep_dev->set_bar_lock); - - return 0; -} - -static void __iomem *sprd_ep_dev_map_bar(int ep, int bar, - dma_addr_t cpu_addr, size_t size) -{ - resource_size_t offset; - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - void __iomem *bar_vir; - struct resource *res; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return NULL; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - /* bar is be used */ - if (ep_dev->bar_vir[bar]) { - dev_err(dev, "ep: bar[%d] is used!", bar); - return NULL; - } - - /* 1st, adjust the map region */ - if (sprd_ep_dev_adjust_region(ep_dev, bar, &cpu_addr, &size, &offset)) - return NULL; - - /* than, ioremap, if map failed, no need to set bar */ - res = &pdev->resource[bar]; -#ifndef ioremap_nocache -#define ioremap_nocache ioremap -#endif - bar_vir = ioremap_nocache(res->start, size); - if (!bar_vir) { - dev_err(dev, "ep: map error, bar=%d, addr=0x%lx, size=0x%lx\n", - bar, - (unsigned long)cpu_addr, - (unsigned long)size); - return NULL; - } - - if (sprd_ep_dev_just_map_bar(ep_dev, bar, cpu_addr, size)) { - dev_err(dev, "ep: map bar =%d\n", bar); - iounmap(ep_dev->bar_vir[bar]); - return NULL; - } - - ep_dev->bar_vir[bar] = (void __iomem *)bar_vir; - ep_dev->cpu_vir[bar] = (void __iomem *)(bar_vir + offset); - ep_dev->src_addr[bar] = res->start + offset; - ep_dev->target_addr[bar] = cpu_addr; - ep_dev->map_size[bar] = size; - - return ep_dev->cpu_vir[bar]; -} - -static int sprd_ep_dev_unmap_bar(int ep, int bar) -{ - struct pci_dev *pdev; - struct device *dev; - struct sprd_pci_ep_dev *ep_dev; - - if (ep >= PCIE_EP_NR || !g_ep_dev[ep]) - return -ENODEV; - - ep_dev = g_ep_dev[ep]; - pdev = ep_dev->pdev; - dev = &pdev->dev; - - dev_info(dev, "ep: unmap bar = %d\n", bar); - - if (!ep_dev->bar_vir[bar]) - return -ENODEV; - - sprd_ep_dev_just_unmap_bar(ep_dev, bar); - - iounmap(ep_dev->bar_vir[bar]); - ep_dev->bar_vir[bar] = NULL; - ep_dev->cpu_vir[bar] = NULL; - ep_dev->src_addr[bar] = 0; - ep_dev->target_addr[bar] = 0; - ep_dev->map_size[bar] = 0; - - return 0; -} - -static void sprd_pci_ep_dev_clear_legacy_irq(struct sprd_pci_ep_dev *ep_dev) -{ - if (!ep_dev->legacy_addr) - return; - - writel_relaxed(PCIE_LEGACY_CLEAR_MASK, - ep_dev->legacy_addr + BIT_CLR_OFFSET + PCIE_LEGACY_CLEAR_REG); -} - -static irqreturn_t sprd_pci_ep_dev_irqhandler(int irq, void *dev_ptr) -{ - struct sprd_pci_ep_dev *ep_dev = dev_ptr; - struct pci_dev *pdev = ep_dev->pdev; - struct device *dev = &pdev->dev; - irq_handler_t handler; - u32 i, j, value; - int ipa_irq; - - if (ep_dev->no_msi) { - /* clear irq */ - sprd_pci_ep_dev_clear_legacy_irq(ep_dev); - - /* workaroud for IPA */ - handler = ep_dev_handler[ep_dev->ep][PCIE_MSI_IPA]; - if (handler) - handler(irq, ep_dev_handler_data[ep_dev->ep][PCIE_MSI_IPA]); - - - value = BL_READL(g_irq_addr[ep_dev->ep]); - dev_dbg(dev, "ep: irq handler. irq = 0x%x, base=%d\n", value, ep_dev->base_irq); - for (i = 0; i < 32; i++) { - if (value & BIT(i)) { - /* clear iqr bit*/ - value = BL_READL(g_irq_addr[ep_dev->ep]); - value &= ~(BIT(i)); - BL_WRITEL(value,g_irq_addr[ep_dev->ep]); - j = i - ep_dev->base_irq; - if (j >= PCIE_MSI_MAX_IRQ) - continue; - - handler = ep_dev_handler[ep_dev->ep][j]; - if (handler) - handler(irq, ep_dev_handler_data[ep_dev->ep][j]); - else - ep_dev->bak_irq_status |= BIT(j); - } - } - return IRQ_HANDLED; - } - - dev_dbg(dev, "ep: irq handler. irq = %d\n", irq); - /* for ipa hw irq. */ - ipa_irq = irq - (pdev->irq + ep_dev->ipa_base_irq); - if (ipa_irq >= 0 && ipa_irq < IPA_HW_IRQ_CNT) { - handler = ep_dev_handler[ep_dev->ep][PCIE_MSI_IPA]; - if (handler) - handler(ipa_irq, ep_dev_handler_data[ep_dev->ep][PCIE_MSI_IPA]); - else - ep_dev->bak_irq_status |= BIT(PCIE_MSI_IPA); - - return IRQ_HANDLED; - } - - - irq -= (pdev->irq + ep_dev->base_irq); - if (irq >= PCIE_MSI_MAX_IRQ || irq < 0) { - dev_err(dev, "ep: error, irq = %d", irq); - return IRQ_HANDLED; - } - - handler = ep_dev_handler[ep_dev->ep][irq]; - if (handler) - handler(irq, ep_dev_handler_data[ep_dev->ep][irq]); - else - ep_dev->bak_irq_status |= BIT(irq); - - return IRQ_HANDLED; -} - -static void sprd_pci_ep_save_reg(struct sprd_pci_ep_dev *ep_dev) -{ - int i, j; - u32 (*save_reg)[PCIE_SAVE_REG_NUM]; - static struct sprd_pci_ep_dev_save *ep_save; - - ep_save = &g_ep_save[ep_dev->ep]; - save_reg = ep_save->save_reg; - - for (i = 0; i < PCIE_SAVE_REGION_NUM; i += 2) { - for (j = 0; j < PCIE_SAVE_REG_NUM; j++) { - save_reg[i][j] = - sprd_pci_ep_iatu_readl(ep_dev, - PCIE_ATU_OB_REGION(i) + - j * sizeof(u32)); - save_reg[i + 1][j] = - sprd_pci_ep_iatu_readl(ep_dev, - PCIE_ATU_IB_REGION(i) + - j * sizeof(u32)); - } - } - - ep_save->doorbell_enable = sprd_pci_ep_iatu_readl(ep_dev, - DOOR_BELL_BASE + - DOOR_BELL_ENABLE); - ep_save->doorbell_status = sprd_pci_ep_iatu_readl(ep_dev, - DOOR_BELL_BASE + - DOOR_BELL_STATUS); - ep_save->cfg_base = ep_dev->cfg_base; - - ep_save->save_succ = true; -} - -static void sprd_pci_ep_dev_backup(struct sprd_pci_ep_dev *ep_dev) -{ - struct pci_dev *pdev = ep_dev->pdev; - struct device *dev = &pdev->dev; - struct sprd_pci_ep_dev_save *ep_save; - int i; - - ep_save = &g_ep_save[ep_dev->ep]; - - /* save some member */ - ep_save->bar_res = ep_dev->bar_res; - for (i = 0; i < BAR_MAX; i++) { - if (!ep_dev->src_addr[i]) - continue; - - dev_info(dev, "ep: backup bar=%d, addr=0x%lx, size=0x%lx\n", - i, - (unsigned long)ep_save->target_addr[i], - (unsigned long)ep_save->map_size[i]); - - ep_save->bar_vir[i] = ep_dev->bar_vir[i]; - ep_save->cpu_vir[i] = ep_dev->cpu_vir[i]; - ep_save->src_addr[i] = ep_dev->src_addr[i]; - ep_save->target_addr[i] = ep_dev->target_addr[i]; - ep_save->map_size[i] = ep_dev->map_size[i]; - } - - /* save ep reg */ - sprd_pci_ep_save_reg(ep_dev); -} - -static void sprd_pci_ep_dev_restore(struct sprd_pci_ep_dev *ep_dev) -{ - struct pci_dev *pdev = ep_dev->pdev; - struct device *dev = &pdev->dev; - struct sprd_pci_ep_dev_save *ep_save; - int i; - - ep_save = &g_ep_save[ep_dev->ep]; - - /* save some member */ - ep_dev->bar_res = ep_save->bar_res; - for (i = 0; i < BAR_MAX; i++) { - if (!ep_save->src_addr[i]) - continue; - - ep_dev->bar_vir[i] = ep_save->bar_vir[i]; - ep_dev->cpu_vir[i] = ep_save->cpu_vir[i]; - ep_dev->src_addr[i] = ep_save->src_addr[i]; - ep_dev->target_addr[i] = ep_save->target_addr[i]; - ep_dev->map_size[i] = ep_save->map_size[i]; - - dev_info(dev, "ep: restore bar=%d, addr=0x%lx, size=0x%lx\n", - i, - (unsigned long)ep_dev->target_addr[i], - (unsigned long)ep_dev->map_size[i]); - - if (sprd_ep_dev_just_map_bar(ep_dev, - i, - ep_dev->target_addr[i], - ep_dev->map_size[i])) - dev_err(dev, "ep: restore map err i = %d.\n", i); - } -} - -static void sprd_pci_ep_notify_fn(struct work_struct *work) -{ - struct sprd_ep_dev_notify *notify; - struct sprd_pci_ep_dev *ep_dev = container_of(work, - struct sprd_pci_ep_dev, - notify_work); - - notify = &g_ep_dev_notify[ep_dev->ep]; - if (notify->notify) - notify->notify(ep_dev->event, notify->data); -} - -static int sprd_pci_ep_dev_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int i, err, irq_cnt = 0; - u32 val; - enum dev_pci_barno bar; - struct device *dev = &pdev->dev; - struct sprd_pci_ep_dev *ep_dev; - struct resource *res; - - dev_info(dev, "ep: probe\n"); - - sprd_pcie_iommu_init(dev); - - ep_dev = devm_kzalloc(dev, sizeof(*ep_dev), GFP_KERNEL); - if (!ep_dev) - return -ENOMEM; - - ep_dev->pdev = pdev; - - if (ent->device == PCI_DEVICE_ID_SPRD_ORCA) - ep_dev->ep = PCIE_EP_MODEM; - else { - dev_err(dev, "ep: Cannot support ep device = 0x%x\n", - ent->device); - return -EINVAL; - } - - err = pci_enable_device(pdev); - if (err) { - dev_err(dev, "ep: Cannot enable PCI device\n"); - return err; - } - - err = pci_request_regions(pdev, DRV_MODULE_NAME); - if (err) { - dev_err(dev, "ep: Cannot obtain PCI resources\n"); - goto err_disable_pdev; - } - - pci_set_master(pdev); - -#ifdef PCI_IRQ_MSI - irq_cnt = pci_alloc_irq_vectors(pdev, - 1, - MAX_SUPPORT_IRQ, - PCI_IRQ_MSI); -#else - irq_cnt = pci_enable_msi_range(pdev, 1, MAX_SUPPORT_IRQ); -#endif - - if (sprd_pcie_is_defective_chip()) { - ep_dev->base_irq = REQUEST_BASE_IRQ_DEFECT; - ep_dev->ipa_base_irq = IPA_HW_IRQ_BASE_DEFECT; - } else { - ep_dev->base_irq = REQUEST_BASE_IRQ; - ep_dev->ipa_base_irq = IPA_HW_IRQ_BASE; - } - - for (bar = BAR_0; bar <= BAR_5; bar++) { - res = &pdev->resource[bar]; - dev_info(dev, "ep: BAR[%d] %pR\n", bar, res); - /* only save mem bar */ - if (resource_type(res) == IORESOURCE_MEM) - ep_dev->bar[bar] = res; - } - - ep_dev->cfg_base = pci_ioremap_bar(pdev, EP_CFG_BAR); - if (!ep_dev->cfg_base) { - dev_err(dev, "ep: failed to map cfg bar.\n"); - err = -ENOMEM; - goto err_disable_msi; - } - - /* clear all 32 bit door bell */ - writel_relaxed(0x0, - ep_dev->cfg_base + DOOR_BELL_BASE + DOOR_BELL_STATUS); - - pci_set_drvdata(pdev, ep_dev); - pci_read_config_dword(ep_dev->pdev, PCIE_ATU_VIEWPORT, &val); - /* - * this atu view port reg is 0xffffffff means that the ep device - * doesn't support atu view port, we need unroll iatu registers - */ - dev_info(dev, "ep: atu_view_port val = 0x%x", val); - ep_dev->iatu_unroll_enabled = val == 0xffffffff; - - /* default , PCIE_EP_PROBE */ - ep_dev->event = PCIE_EP_PROBE; - g_ep_dev[ep_dev->ep] = ep_dev; - - if (!ep_dev->bar[BAR_1] || !ep_dev->bar[BAR_3]) { - /* only 2 bar, set PCIE_EP_PROBE_BEFORE_SPLIT_BAR */ - ep_dev->event = PCIE_EP_PROBE_BEFORE_SPLIT_BAR; - dev_info(dev, "ep:bar not ready, wait the next probe!"); - } - - /* restore all the config */ - if (ep_dev->event == PCIE_EP_PROBE) - sprd_pci_ep_dev_restore(ep_dev); - - /* start notify work */ - INIT_WORK(&ep_dev->notify_work, sprd_pci_ep_notify_fn); - schedule_work(&ep_dev->notify_work); - - if (irq_cnt < MAX_SUPPORT_IRQ) { - err = irq_cnt < 0 ? irq_cnt : -EINVAL; - ep_dev->no_msi = true; - dev_info(dev, "ep: failed to get MSI, err=%d, irq=%d\n", err, pdev->irq); - - ep_dev->legacy_addr = sprd_ep_map_memory(ep_dev->ep, PCIE_LEGACY_CLEAR_BASE, 0x4000); - /* request legacy irq */ - err = devm_request_irq(dev, pdev->irq, sprd_pci_ep_dev_irqhandler, - IRQF_SHARED, DRV_MODULE_NAME, ep_dev); - if (err) - dev_warn(dev, - "ep: failed to request legacy %d\n", - pdev->irq); - - } else { - ep_dev->irq_cnt = irq_cnt; - dev_info(dev, "ep: request IRQ = %d, cnt =%d\n", - pdev->irq, - ep_dev->irq_cnt); - - /* request msi irq */ - for (i = ep_dev->base_irq; - i < ep_dev->base_irq + PCIE_MSI_MAX_IRQ; - i++) { - err = devm_request_irq(dev, pdev->irq + i, - sprd_pci_ep_dev_irqhandler, - IRQF_SHARED, DRV_MODULE_NAME, ep_dev); - if (err) - dev_warn(dev, - "ep: failed to request IRQ %d for MSI %d\n", - pdev->irq + i, i + 1); - } - - #ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - for (i = ep_dev->ipa_base_irq; - i < ep_dev->ipa_base_irq + IPA_HW_IRQ_CNT; - i++) { - err = devm_request_irq(dev, pdev->irq + i, - sprd_pci_ep_dev_irqhandler, - IRQF_SHARED, DRV_MODULE_NAME, - ep_dev); - if (!err) - sprd_pcie_teardown_msi_irq(pdev->irq + i); - } - #endif - } - -#ifndef SPRD_PCIE_USE_DTS - sipa_module_init(dev); - sipa_eth_init(); - sipa_dummy_init(); -#endif - - return 0; - -err_disable_msi: - pci_disable_msi(pdev); - pci_release_regions(pdev); - -err_disable_pdev: - pci_disable_device(pdev); - - return err; -} - -static void sprd_pci_ep_dev_remove(struct pci_dev *pdev) -{ - u32 i; - struct sprd_ep_dev_notify *notify; - struct sprd_pci_ep_dev *ep_dev = pci_get_drvdata(pdev); - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - dev_info(&pdev->dev, "ep: remove\n"); - ctrl->remote_ready = false; - spipe_device_down(); - spool_device_down(); - - cancel_work_sync(&ep_dev->notify_work); - - /* first notify PCIE_EP_REMOVE */ - notify = &g_ep_dev_notify[ep_dev->ep]; - if (notify->notify) - notify->notify(PCIE_EP_REMOVE, notify->data); - - /* back up some config before remove */ - if (ep_dev->need_backup) - sprd_pci_ep_dev_backup(ep_dev); - - if (ep_dev->no_msi) { - devm_free_irq(&pdev->dev, pdev->irq, ep_dev); - } else { - for (i = ep_dev->base_irq; i < ep_dev->base_irq + PCIE_MSI_MAX_IRQ; i++) - devm_free_irq(&pdev->dev, pdev->irq + i, ep_dev); - - #ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND - for (i = ep_dev->ipa_base_irq; - i < ep_dev->ipa_base_irq + IPA_HW_IRQ_CNT; - i++) - devm_free_irq(&pdev->dev, pdev->irq + i, ep_dev); - #endif - } - - pci_disable_msi(pdev); - -#ifndef SPRD_PCIE_USE_DTS - sipa_dummy_exit(); - sipa_eth_exit(); - sipa_module_exit(); -#endif - - if (ep_dev->legacy_addr) { - sprd_ep_unmap_memory(ep_dev->ep, ep_dev->legacy_addr); - ep_dev->legacy_addr = NULL; - dev_info(&ep_dev->pdev->dev, "set ep_dev->legacy_addr = %lx\n", (long)ep_dev->legacy_addr); - } - - if (ep_dev->cfg_base) { - iounmap(ep_dev->cfg_base); - ep_dev->cfg_base = NULL; - } - - pci_release_regions(pdev); - pci_disable_device(pdev); - - g_ep_dev[ep_dev->ep] = NULL; - ep_dev->bar_res = 0; -} - -static const struct pci_device_id sprd_pci_ep_dev_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_SPRD, PCI_DEVICE_ID_SPRD_ORCA) }, - { } -}; -MODULE_DEVICE_TABLE(pci, sprd_pci_ep_dev_tbl); - -#ifdef CONFIG_PM_SLEEP -static int sprd_pci_ep_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int rc; - - dev_info(dev, "suspend\n"); - - /* Exec pci PCI_D3cold one time */ - if (pdev->current_state != PCI_D0) { - dev_info(dev, "done for pm %d\n", pdev->current_state); - return 0; - } - - /* - * TODO: The HAL will ask the shared memory layer whether D3 is allowed. - */ - - /* Save the PCI configuration space of a device before suspending. */ - rc = pci_save_state(pdev); - if (rc) { - dev_err(dev, "pci_save_state error=%d\n", rc); - return rc; - } - - /* Set the power state of a PCI device. - * Transition a device to a new power state, using the device's PCI PM - * registers. - */ - rc = pci_set_power_state(pdev, PCI_D3cold); - if (rc) { - dev_err(dev, "pci_set_power_state error=%d\n", rc); - return rc; - } - return 0; -} - -static int sprd_pci_ep_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int rc; - - dev_info(dev, "resume\n"); - - /* Set the power state of a PCI device. */ - rc = pci_set_power_state(pdev, PCI_D0); - if (rc) { - dev_err(dev, "pci_set_power_state error=%d\n", rc); - return rc; - } - - /* Restore the saved state of a PCI device. */ - pci_restore_state(pdev); - - /* TODO: The HAL shall inform that the device is active. */ - return 0; -} -#endif /* CONFIG_PM_SLEEP */ - -static const struct dev_pm_ops sprd_pci_ep_pm = { - SET_SYSTEM_SLEEP_PM_OPS(sprd_pci_ep_suspend, - sprd_pci_ep_resume) -}; - -static struct pci_driver sprd_pci_ep_dev_driver = { - .name = DRV_MODULE_NAME, - .id_table = sprd_pci_ep_dev_tbl, - .probe = sprd_pci_ep_dev_probe, - .remove = sprd_pci_ep_dev_remove, - .driver = { - .pm = &sprd_pci_ep_pm, - } -}; -//module_pci_driver(sprd_pci_ep_dev_driver); - -#if defined(CONFIG_DEBUG_FS) -static void sprd_pci_ep_dev_save_show(struct seq_file *m, - struct sprd_pci_ep_dev_save *ep_save, - int ep) -{ - u32 i; - - seq_printf(m, "ep-save-%d configs:\n", ep); - seq_printf(m, "bar_res = 0x%lx\n", ep_save->bar_res); - - for (i = 0; i < BAR_MAX; i++) { - seq_printf(m, "src_addr[%d] = 0x%lx\n", - i, - (unsigned long)ep_save->src_addr[i]); - seq_printf(m, "target_addr[%d] = 0x%lx\n", - i, - (unsigned long)ep_save->target_addr[i]); - seq_printf(m, "map_size[%d] = 0x%lx\n", - i, - (unsigned long)ep_save->map_size[i]); - } -} - -static void sprd_pci_ep_dev_config_show(struct seq_file *m, - struct sprd_pci_ep_dev *ep_dev) -{ - u32 i; - void __iomem *base; - - seq_printf(m, "ep-%d configs:\n", ep_dev->ep); - - /* doorbell regs */ - seq_puts(m, "door bell regs:\n"); - base = ep_dev->cfg_base + DOOR_BELL_BASE; - - seq_printf(m, "irq_enable = 0x%08x\n irq_status = 0x%08x\n", - readl_relaxed(base + DOOR_BELL_ENABLE), - readl_relaxed(base + DOOR_BELL_STATUS)); - - /* iatu reg regs */ - seq_puts(m, "iatu regs reg:\n"); - for (i = 0; i < IATU_MAX_REGION * 2; i++) { - base = ep_dev->cfg_base + IATU_REG_BASE + i * 100; - seq_printf(m, "IATU[%d]:\n", i); - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - readl_relaxed(base + 0x0), - readl_relaxed(base + 0x4), - readl_relaxed(base + 0x8), - readl_relaxed(base + 0xc)); - base += 0x10; - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - readl_relaxed(base + 0x0), - readl_relaxed(base + 0x4), - readl_relaxed(base + 0x8), - readl_relaxed(base + 0x10)); - } -} - -static void sprd_pci_ep_dev_backup_show(struct seq_file *m, - struct sprd_pci_ep_dev_save *ep_save, - int ep) -{ - int i; - u32 (*save_reg)[PCIE_SAVE_REG_NUM]; - void __iomem *base; - - save_reg = ep_save->save_reg; - - seq_printf(m, "ep-%d backup configs:\n", ep); - - /* doorbell regs */ - seq_puts(m, "door bell regs:\n"); - seq_printf(m, "irq_enable = 0x%08x\n irq_status = 0x%08x\n", - ep_save->doorbell_enable, - ep_save->doorbell_status); - - /* iatu reg regs */ - seq_puts(m, "iatu regs reg:\n"); - for (i = 0; i < PCIE_SAVE_REGION_NUM; i++) { - seq_printf(m, "IATU[%d]:\n", i); - base = ep_save->cfg_base + IATU_REG_BASE + i * 100; - - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - save_reg[i][0], - save_reg[i][1], - save_reg[i][2], - save_reg[i][3]); - base += 0x10; - seq_printf(m, "0x%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", - base, - save_reg[i][4], - save_reg[i][5], - save_reg[i][6], - save_reg[i][7]); - } -} - -static int sprd_pci_ep_dev_show(struct seq_file *m, void *unused) -{ - u32 i; - struct sprd_pci_ep_dev *ep_dev; - struct sprd_pci_ep_dev_save *ep_save; - - for (i = 0; i < PCIE_EP_NR; i++) { - /* ep_save configus */ - ep_save = &g_ep_save[i]; - ep_dev = g_ep_dev[i]; - - if (!ep_dev && !ep_save->save_succ) - continue; - - if (ep_save) - sprd_pci_ep_dev_save_show(m, ep_save, i); - - if (ep_dev) - sprd_pci_ep_dev_config_show(m, ep_dev); - else - sprd_pci_ep_dev_backup_show(m, ep_save, i); - } - - return 0; -} - -static int sprd_pci_ep_dev_open(struct inode *inode, struct file *file) -{ - return single_open(file, sprd_pci_ep_dev_show, NULL); -} - -static const struct file_operations sprd_pci_ep_dev_fops = { - .owner = THIS_MODULE, - .open = sprd_pci_ep_dev_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static struct dentry *g_ep_debugfs_root; - -static int sprd_pci_ep_dev_init_debugfs(void) -{ - struct dentry *g_ep_debugfs_root = debugfs_create_dir("ep_dev", NULL); - - if (!g_ep_debugfs_root) - return -ENXIO; - - debugfs_create_file("ep", 0444, - g_ep_debugfs_root, - NULL, &sprd_pci_ep_dev_fops); - return 0; -} - -static void sprd_pci_ep_dev_remove_debugfs(void) -{ - debugfs_remove_recursive(g_ep_debugfs_root); -} -#endif - -static int __init sprd_pci_ep_dev_init(void) -{ - pr_info("%s %s\n", __func__, QUECTEL_SPRD_PCIE_VERSION); -#if defined(CONFIG_DEBUG_FS) - sprd_pci_ep_dev_init_debugfs(); - sipc_init_debugfs(); -#endif - sipc_init(); - spipe_init(); - spool_init(); - modem_power_manager_init(); - return pci_register_driver(&sprd_pci_ep_dev_driver); -} - -static void __exit sprd_pci_ep_dev_exit(void) -{ - spipe_exit(); - spool_exit(); - modem_power_manager_exit(); - pci_unregister_driver(&sprd_pci_ep_dev_driver); -#if defined(CONFIG_DEBUG_FS) - sprd_pci_ep_dev_remove_debugfs(); -#endif - sipc_exit(); -} - -module_init(sprd_pci_ep_dev_init); -module_exit(sprd_pci_ep_dev_exit); - - -MODULE_DESCRIPTION("SPRD PCI EP DEVICE HOST DRIVER"); -MODULE_AUTHOR("Wenping Zhou "); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(QUECTEL_SPRD_PCIE_VERSION); diff --git a/quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c b/quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c deleted file mode 100644 index d8e9853..0000000 --- a/quectel_SRPD_PCIE/src/pcie/sprd_pcie_quirks.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file contains work-arounds for many known PCI hardware - * bugs. Devices present only on certain architectures (host - * bridges et cetera) should be handled in arch-specific code. - * - * Note: any quirks for hotpluggable devices must _NOT_ be declared __init. - * - * Copyright (c) 1999 Martin Mares - * - * Init/reset quirks for USB host controllers should be in the - * USB quirks file, where their drivers can access reuse it. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,4,0 )) -#include -#endif -#include -#include -#include -#include -#include /* isa_dma_bridge_buggy */ - -#ifndef PCI_VENDOR_ID_SYNOPSYS -#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 -#endif - - - /* - * It's possible that ep bar size is larger than rc allocated - * memory, so need to resize ep bar to small size. - * Original ep bar size:bar0:256MB, bar1:64kb, bar2:256MB, - * bar3: 64kb, bar4:256MB, bar5:64kb. - * resize to bar0:8MB, bar1:64kb, bar2:2MB, bar3: 64kb, - * bar4:2MB, bar5:64kb. - */ -#define SPRD_PCI_BAR0 0x10 -#define SPRD_BAR_NUM 0x6 -#define SPRD_PCI_MISC_CTRL1_OFF 0x8bc -#define SPRD_PCI_DBI_RO_WR_EN (0x1 << 0) -#define SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAP_HEADER 0x260 -#define SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAPID 0x15 -/* Resizable BAR Capability Register */ -#define SPRD_PCI_RESIZABLE_BAR0 0x264 -#define SPRD_PCI_RESIZABLE_BAR2 0x26c -#define SPRD_PCI_RESIZABLE_BAR4 0x274 -#define SPRD_BAR_SUPPORT_2MB (0x1 << 5) -#define SPRD_BAR_SUPPORT_4MB (0x1 << 6) -#define SPRD_BAR_SUPPORT_8MB (0x1 << 7) -/* Resizable BAR Control Register */ -#define SPRD_PCI_RESIZABLE_BAR0_CTL 0x268 -#define SPRD_PCI_RESIZABLE_BAR2_CTL 0x270 -#define SPRD_PCI_RESIZABLE_BAR4_CTL 0x278 -/* bit[13:8] is bar size */ -#define SPRD_PCI_RESIZABLE_BAR_SIZE_MASK 0x3F00 -#define SPRD_PCI_RESIZABLE_2MB (0x1 << 8) -#define SPRD_PCI_RESIZABLE_4MB (0x2 << 8) -#define SPRD_PCI_RESIZABLE_8MB (0x3 << 8) -#define SIZE(val) ((~(val & 0xFFFFFFF0)) + 1) - -static void quirk_sprd_pci_resizebar(struct pci_dev *dev) -{ - u32 val, i, backup; - - pci_read_config_dword(dev, - SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAP_HEADER, &val); - if ((val & SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAPID) != - SPRD_PCI_RESIZABLE_BAR_EXTENDED_CAPID) { - dev_info(&dev->dev, "%s: not support resize bar\n", __func__); - return; - } - - pci_read_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, &val); - val |= SPRD_PCI_DBI_RO_WR_EN; - pci_write_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, val); - - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0, - val | SPRD_BAR_SUPPORT_4MB | - SPRD_BAR_SUPPORT_8MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2, - val | SPRD_BAR_SUPPORT_4MB | - SPRD_BAR_SUPPORT_8MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4, - val | SPRD_BAR_SUPPORT_4MB | - SPRD_BAR_SUPPORT_8MB); - - pci_read_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, &val); - val &= ~SPRD_PCI_DBI_RO_WR_EN; - pci_write_config_dword(dev, SPRD_PCI_MISC_CTRL1_OFF, val); - - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0_CTL, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR0_CTL, - (val & (~SPRD_PCI_RESIZABLE_BAR_SIZE_MASK)) | - SPRD_PCI_RESIZABLE_4MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2_CTL, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR2_CTL, - (val & (~SPRD_PCI_RESIZABLE_BAR_SIZE_MASK)) | - SPRD_PCI_RESIZABLE_4MB); - pci_read_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4_CTL, &val); - pci_write_config_dword(dev, SPRD_PCI_RESIZABLE_BAR4_CTL, - (val & (~SPRD_PCI_RESIZABLE_BAR_SIZE_MASK)) | - SPRD_PCI_RESIZABLE_4MB); - - for (i = 0; i < SPRD_BAR_NUM; i++) { - pci_read_config_dword(dev, SPRD_PCI_BAR0 + i * 4, &backup); - pci_write_config_dword(dev, SPRD_PCI_BAR0 + i * 4, 0xFFFFFFFF); - pci_read_config_dword(dev, SPRD_PCI_BAR0 + i * 4, &val); - pci_write_config_dword(dev, SPRD_PCI_BAR0 + i * 4, backup); - - dev_info(&dev->dev, "%s: bar%d size 0x%x\n", - __func__, i, SIZE(val)); - } -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_sprd_pci_resizebar); \ No newline at end of file diff --git a/quectel_SRPD_PCIE/src/power_manager/Makefile b/quectel_SRPD_PCIE/src/power_manager/Makefile deleted file mode 100644 index 6d5c499..0000000 --- a/quectel_SRPD_PCIE/src/power_manager/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += power_manager.o diff --git a/quectel_SRPD_PCIE/src/power_manager/power_manager.c b/quectel_SRPD_PCIE/src/power_manager/power_manager.c deleted file mode 100644 index 077c31e..0000000 --- a/quectel_SRPD_PCIE/src/power_manager/power_manager.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sprd_mpm.h" -#include "../include/sipc.h" -/* - * The data struct of modem power manager. - */ -struct sprd_mpm_data { -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - struct wakeup_source *ws; -#else - struct wakeup_source ws; -#endif - struct list_head pms_list; - struct timer_list timer; - spinlock_t mpm_lock; - char name[20]; - const char *last_name; - unsigned int dst; - unsigned int up_cnt; - unsigned int awake_cnt; - unsigned int wakelock_cnt; - unsigned int mpm_state; - unsigned long expires; - unsigned int later_idle; - - /* resource ops functions */ - int (*wait_resource)(unsigned int dst, int timeout); - int (*request_resource)(unsigned int dst); - int (*release_resource)(unsigned int dst); - - struct work_struct release_res_work; - struct work_struct request_res_work; -}; - -/* - * Save all the instance of mpm in here. - */ -static struct sprd_mpm_data *g_sprd_mpm[SIPC_ID_NR]; - -/** - * sprd_mpm_print_awake - * print the wake up list to known who prevent system sleep. - */ -static void sprd_mpm_print_awake(struct sprd_mpm_data *mpm) -{ - struct sprd_pms *pms; - char *awake_info; - int len = 0, max_len = 512; - - awake_info = kmalloc(max_len, GFP_KERNEL); - if (!awake_info) - return; - - /* print pms list */ - list_for_each_entry(pms, &mpm->pms_list, entry) { - if (!pms->awake && pms->pre_awake_cnt == pms->awake_cnt) - continue; - - pms->pre_awake_cnt = pms->awake_cnt; - snprintf(awake_info + len, - max_len - len, - "%s is awake, awake_cnt = %d\n", - pms->name, - pms->awake_cnt); - len = strlen(awake_info); - } - - if (len) - pr_info("mpm: %s\n", awake_info); - - kfree(awake_info); -} - -/** - * sprd_mpm_pm_event - * monitor the PM_SUSPEND_PREPARE event. - */ -static int sprd_mpm_pm_event(struct notifier_block *notifier, - unsigned long pm_event, void *unused) -{ - unsigned int i; - struct sprd_mpm_data *cur; - - switch (pm_event) { - case PM_SUSPEND_PREPARE: - case PM_POST_SUSPEND: - /* check if has wake lock. */ - for (i = 0; i < SIPC_ID_NR; i++) { - if (!g_sprd_mpm[i]) - continue; - - cur = g_sprd_mpm[i]; - sprd_mpm_print_awake(cur); - } - break; - - default: - break; - } - - return NOTIFY_DONE; -} - -/* - * The pm event notify data, for the register pm notifier. - */ -static struct notifier_block sprd_mpm_notifier_block = { - .notifier_call = sprd_mpm_pm_event, -}; - -/** - * sprd_mpm_request_resource - * request resource. - */ -static void sprd_mpm_request_resource(struct sprd_mpm_data *mpm) -{ - if (mpm->request_resource) - schedule_work(&mpm->request_res_work); -} - -/** - * sprd_mpm_release_resource - * release resource. - */ -static void sprd_mpm_release_resource(struct sprd_mpm_data *mpm) -{ - if (mpm->release_resource) - schedule_work(&mpm->release_res_work); -} - -/** - * sprd_mpm_wait_resource -wait resource. - */ -static int sprd_mpm_wait_resource(struct sprd_mpm_data *mpm, int timeout) -{ - int ret = 0; - - if (mpm->wait_resource) { - ret = mpm->wait_resource(mpm->dst, timeout); - if (ret < 0 && ret != -ERESTARTSYS && timeout) - pr_err("mpm: %s wait resource, ret=%d, timeout=%d.\n", - mpm->name, ret, timeout); - } - - return ret; -} - -/** - * sprd_mpm_active - * set the state to busy. - */ -static void sprd_mpm_active(struct sprd_mpm_data *mpm) -{ - pr_debug("mpm: %s active, set state to busy.\n", mpm->name); - - mpm->mpm_state = SPRD_MPM_BUSY; - sprd_mpm_request_resource(mpm); -} - -/** - * sprd_mpm_deactive - * del the idle timer, - * set the state to idle. - */ -static void sprd_mpm_deactive(struct sprd_mpm_data *mpm) -{ - pr_debug("mpm: %s deactive, set state to idle.\n", mpm->name); - - mpm->mpm_state = SPRD_MPM_IDLE; - mpm->expires = 0; - sprd_mpm_release_resource(mpm); -} - -/** - * sprd_mpm_start_deactive - * start the deactive timer. - */ -static void sprd_mpm_start_deactive(struct sprd_mpm_data *mpm) -{ - pr_debug("mpm: %s start deactive.\n", mpm->name); - - mpm->expires = jiffies + msecs_to_jiffies(mpm->later_idle); - if (!mpm->expires) - mpm->expires = 1; - - mod_timer(&mpm->timer, mpm->expires); -} - -/** - * sprd_mpm_request_res_work_fn - * do release resource call in here. - */ -static void sprd_mpm_request_res_work_fn(struct work_struct *work) -{ - struct sprd_mpm_data *mpm = container_of(work, struct sprd_mpm_data, - request_res_work); - int ret; - - pr_debug("mpm: %s request res work.\n", mpm->name); - - ret = mpm->request_resource(mpm->dst); - if (ret) - pr_err("mpm: %s request res, ret = %d.\n", mpm->name, ret); -} - -/** - * sprd_mpm_release_res_work_fn - * do relase resource call in here - */ -static void sprd_mpm_release_res_work_fn(struct work_struct *work) -{ - struct sprd_mpm_data *mpm = container_of(work, struct sprd_mpm_data, - release_res_work); - int ret; - - pr_debug("mpm: %s releae res work.\n", mpm->name); - - ret = mpm->release_resource(mpm->dst); - if (ret) - pr_err("mpm: %s request res, ret = %d.\n", mpm->name, ret); -} - -/** - * sprd_mpm_deactive_timer_fn - * in a period of time (mpm->later_idle), - * have no modem resource request, - * we consider that it doesn't need modem resource, - * than set the state to idle. - */ -static void sprd_mpm_deactive_timer_fn( -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - unsigned long data) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)data; -#else - struct timer_list *t) -{ - struct sprd_mpm_data *mpm = from_timer(mpm, t, timer); -#endif - - unsigned long flags; - - pr_debug("mpm: %s deactive timer.\n", mpm->name); - - spin_lock_irqsave(&mpm->mpm_lock, flags); - /* expires is 0, means the timer has been cancelled. */ - if (mpm->expires) - sprd_mpm_deactive(mpm); - spin_unlock_irqrestore(&mpm->mpm_lock, flags); -} - -/** - * sprd_pms_cancel_timer - * cancel the pms wakelock timer. - */ -static void sprd_pms_cancel_timer(struct sprd_pms *pms) -{ - unsigned long flags; - bool print = false; - - spin_lock_irqsave(&pms->expires_lock, flags); - if (pms->expires) { - print = true; - pms->expires = 0; - del_timer(&pms->wake_timer); - } - spin_unlock_irqrestore(&pms->expires_lock, flags); - - if (print) - pr_debug("pms: %s del timer.\n", pms->name); - -} - -/** - * sprd_mpm_cancel_timer - * cancel the deactive timer. - */ -static void sprd_mpm_cancel_timer(struct sprd_mpm_data *mpm) -{ - if (mpm->expires) { - pr_debug("mpm: %s del timer.\n", mpm->name); - - mpm->expires = 0; - del_timer(&mpm->timer); - } -} - -/** - * sprd_mpm_up - * modem power manger power up. - */ -static void sprd_mpm_up(struct sprd_mpm_data *mpm, const char *name) -{ - unsigned long flags; - - spin_lock_irqsave(&mpm->mpm_lock, flags); - - /* first cancel deactive timer */ - sprd_mpm_cancel_timer(mpm); - mpm->last_name = name; - - mpm->up_cnt++; - /* when up_cnt is change form 0 to 1, ready active pms. - * Although the cnt is 0, but later down, the state may is still busy, - * so here must see whether the mpm state is idle. - */ - if (mpm->up_cnt == 1 && - mpm->mpm_state == SPRD_MPM_IDLE) - sprd_mpm_active(mpm); - - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s up, up_cnt=%d.\n", mpm->name, mpm->up_cnt); -} - -/** - * sprd_mpm_down - * modem power manger power down. - */ -static void sprd_mpm_down(struct sprd_mpm_data *mpm, bool immediately) -{ - unsigned long flags; - - /* - * when up_cnt count is change form 1 to 0, - * start deactive pms. - */ - spin_lock_irqsave(&mpm->mpm_lock, flags); - mpm->up_cnt--; - if (!mpm->up_cnt) { - if (mpm->later_idle && !immediately) - sprd_mpm_start_deactive(mpm); - else - sprd_mpm_deactive(mpm); - } - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s down, up_cnt=%d.\n", mpm->name, mpm->up_cnt); -} - -/** - * sprd_mpm_stay_awake - * modem power manager stay awake. - */ -static void sprd_mpm_stay_awake(struct sprd_mpm_data *mpm) -{ - unsigned long flags; - - /* - * when wakelock_cnt is change form 0 to 1, - * get the system wake lock. - */ - spin_lock_irqsave(&mpm->mpm_lock, flags); - mpm->wakelock_cnt++; - if (mpm->wakelock_cnt == 1) { - mpm->awake_cnt++; -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_stay_awake(mpm->ws); -#else - __pm_stay_awake(&mpm->ws); -#endif - } - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s wake, wake_cnt=%d\n", - mpm->name, mpm->wakelock_cnt); -} - -/** - * sprd_mpm_relax - * modem power manager relax wakelock. - */ -static void sprd_mpm_relax(struct sprd_mpm_data *mpm) -{ - unsigned long flags; - - /* - * when wakelock_cnt is change form 0 to 1, - * release the system wake lock. - */ - spin_lock_irqsave(&mpm->mpm_lock, flags); - mpm->wakelock_cnt--; - if (!mpm->wakelock_cnt) -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - __pm_relax(mpm->ws); -#else - __pm_relax(&mpm->ws); -#endif - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - pr_debug("mpm: %s relax wake, wake_cnt=%d\n", - mpm->name, mpm->wakelock_cnt); -} - -/** - * sprd_pms_do_up_single - * do pms power up. - */ -static void sprd_pms_do_up_single(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - - /* - * when active_cnt is change form 0 to 1, mpm up. - */ - pms->active_cnt++; - if (pms->active_cnt == 1) - sprd_mpm_up(mpm, pms->name); - - pr_debug("pms: %s up, active_cnt=%d.\n", - pms->name, pms->active_cnt); -} - -/** - * sprd_pms_do_up_multi - * do pms power up. - */ -static void sprd_pms_do_up_multi(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - unsigned long flags; - bool active = false; - - /* - * when active_cnt is change form 0 to 1, mpm up. - */ - spin_lock_irqsave(&pms->active_lock, flags); - - pms->active_cnt++; - if (pms->active_cnt == 1) - active = true; - - spin_unlock_irqrestore(&pms->active_lock, flags); - - pr_debug("pms: %s up, active_cnt=%d.\n", - pms->name, pms->active_cnt); - - if (active) - sprd_mpm_up(mpm, pms->name); -} - -static void sprd_pms_do_up(struct sprd_pms *pms) -{ - if (pms->multitask) - sprd_pms_do_up_multi(pms); - else - sprd_pms_do_up_single(pms); -} - -/** - * sprd_pms_do_down_single - * do pms power down. - */ -static void sprd_pms_do_down_single(struct sprd_pms *pms, bool immediately) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - /* - * when active_cnt is change form 1 to 0, mpm down. - */ - if (pms->active_cnt > 0) { - pms->active_cnt--; - if (pms->active_cnt == 0) - sprd_mpm_down(mpm, immediately); - } - - pr_debug("pms: %s down, active_cnt=%d.\n", - pms->name, pms->active_cnt); -} - -/** - * sprd_pms_do_down - * do pms power down. - */ -static void sprd_pms_do_down_multi(struct sprd_pms *pms, bool immediately) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - unsigned long flags; - bool deactive = false; - - /* - * when active_cnt is change form 1 to 0, mpm down. - */ - spin_lock_irqsave(&pms->active_lock, flags); - - if (pms->active_cnt > 0) { - pms->active_cnt--; - if (pms->active_cnt == 0) - deactive = true; - } - - spin_unlock_irqrestore(&pms->active_lock, flags); - - pr_debug("pms: %s down, active_cnt=%d.\n", - pms->name, pms->active_cnt); - - if (deactive) - sprd_mpm_down(mpm, immediately); -} - -static void sprd_pms_do_down(struct sprd_pms *pms, bool immediately) -{ - if (pms->multitask) - sprd_pms_do_down_multi(pms, immediately); - else - sprd_pms_do_down_single(pms, immediately); -} - -/** - * sprd_pms_stay_awake - * power manger source stay awake. - */ -static void sprd_pms_stay_awake(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - - pr_debug("pms: %s stay awake.\n", pms->name); - - pms->awake_cnt++; - if (!pms->awake) { - pms->awake = true; - sprd_mpm_stay_awake(mpm); - } -} - -/** - * sprd_pms_relax - * power manger source release wakelock. - */ -static void sprd_pms_relax(struct sprd_pms *pms) -{ - struct sprd_mpm_data *mpm = (struct sprd_mpm_data *)pms->data; - - pr_debug("pms: %s relax awake.\n", pms->name); - - if (pms->awake) { - pms->awake = false; - sprd_mpm_relax(mpm); - } -} - -/** - * sprd_pms_relax_wakelock_timer - * the timer process function of pms delay release wakelock. - */ -static void sprd_pms_relax_wakelock_timer( -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - unsigned long data) -{ - struct sprd_pms *pms = (struct sprd_pms *)data; -#else - struct timer_list *t) -{ - struct sprd_pms *pms = from_timer(pms, t, wake_timer); -#endif - - unsigned long flags; - bool relax = false; - - pr_debug("pms: %s timer down.\n", pms->name); - - spin_lock_irqsave(&pms->expires_lock, flags); - /* - * if jiffies < pms->expires, mpm called has been canceled, - * don't call sprd_pms_down. - */ - if (pms->expires && time_after_eq(jiffies, pms->expires)) { - pms->expires = 0; - relax = true; - } - spin_unlock_irqrestore(&pms->expires_lock, flags); - - if (relax) - sprd_pms_relax(pms); -} - -int sprd_mpm_create(unsigned int dst, const char *name, - unsigned int later_idle) -{ - struct sprd_mpm_data *mpm; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - mpm = kzalloc(sizeof(*mpm), GFP_KERNEL); - if (!mpm) - return -ENOMEM; - - snprintf(mpm->name, sizeof(mpm->name), "%s-mpm-%d", name, dst); - - mpm->dst = dst; - mpm->later_idle = later_idle; - - spin_lock_init(&mpm->mpm_lock); - INIT_LIST_HEAD(&mpm->pms_list); -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,18,0 )) - mpm->ws = wakeup_source_register(NULL, mpm->name); -#else - wakeup_source_init(&mpm->ws, mpm->name); -#endif - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - setup_timer(&mpm->timer, - sprd_mpm_deactive_timer_fn, - (unsigned long)mpm); -#else - timer_setup(&mpm->timer, - sprd_mpm_deactive_timer_fn, - 0); -#endif - - INIT_WORK(&mpm->request_res_work, sprd_mpm_request_res_work_fn); - INIT_WORK(&mpm->release_res_work, sprd_mpm_release_res_work_fn); - - g_sprd_mpm[dst] = mpm; - - return 0; -} - -int sprd_mpm_init_resource_ops(unsigned int dst, - int (*wait_resource)(unsigned int dst, - int timeout), - int (*request_resource)(unsigned int dst), - int (*release_resource)(unsigned int dst)) -{ - struct sprd_mpm_data *mpm; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - mpm = g_sprd_mpm[dst]; - if (!mpm) - return -ENODEV; - - mpm->wait_resource = wait_resource; - mpm->request_resource = request_resource; - mpm->release_resource = release_resource; - - return 0; -} - -int sprd_mpm_destroy(unsigned int dst) -{ - struct sprd_pms *pms, *temp; - struct sprd_mpm_data *mpm; - unsigned long flags; - - if (dst >= SIPC_ID_NR) - return -EINVAL; - - mpm = g_sprd_mpm[dst]; - if (!mpm) - return -ENODEV; - - sprd_mpm_cancel_timer(mpm); - cancel_work_sync(&mpm->request_res_work); - cancel_work_sync(&mpm->release_res_work); - - spin_lock_irqsave(&mpm->mpm_lock, flags); - list_for_each_entry_safe(pms, - temp, - &mpm->pms_list, - entry) { - sprd_pms_cancel_timer(pms); - list_del(&pms->entry); - } - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - kfree(mpm); - g_sprd_mpm[dst] = NULL; - - return 0; -} - -struct sprd_pms *sprd_pms_create(unsigned int dst, - const char *name, bool multitask) -{ - unsigned long flags; - struct sprd_pms *pms; - struct sprd_mpm_data *mpm; - - if (dst >= SIPC_ID_NR) - return NULL; - - mpm = g_sprd_mpm[dst]; - if (!mpm) { - pr_err("mpm: %s pms init failed, dst=%d.\n", name, dst); - return NULL; - } - - pms = kzalloc(sizeof(*pms), GFP_KERNEL); - if (!pms) - return NULL; - - pms->multitask = multitask; - pms->name = name; - pms->data = (void *)mpm; - - spin_lock_init(&pms->expires_lock); - spin_lock_init(&pms->active_lock); - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - setup_timer(&pms->wake_timer, - sprd_pms_relax_wakelock_timer, (unsigned long)pms); -#else - timer_setup(&pms->wake_timer, - sprd_pms_relax_wakelock_timer, 0); -#endif - - spin_lock_irqsave(&mpm->mpm_lock, flags); - list_add(&pms->entry, &mpm->pms_list); - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - - return pms; -} - -void sprd_pms_destroy(struct sprd_pms *pms) -{ - unsigned long flags; - struct sprd_mpm_data *mpm; - - if (pms) { - sprd_pms_cancel_timer(pms); - mpm = (struct sprd_mpm_data *)pms->data; - spin_lock_irqsave(&mpm->mpm_lock, flags); - list_del(&pms->entry); - spin_unlock_irqrestore(&mpm->mpm_lock, flags); - kfree(pms); - } -} - -/** - * sprd_pms_request_resource - request mpm resource - * - * @pms, the point of this pms. - * @timeout, in ms. - * - * Returns: - * 0 resource ready, - * < 0 resoure not ready, - * -%ERESTARTSYS if it was interrupted by a signal. - */ -int sprd_pms_request_resource(struct sprd_pms *pms, int timeout) -{ - int ret; - struct sprd_mpm_data *mpm; - - if (!pms) - return -EINVAL; - - sprd_pms_do_up(pms); - - /* wait resource */ - mpm = (struct sprd_mpm_data *)pms->data; - ret = sprd_mpm_wait_resource(mpm, timeout); - if (ret) - sprd_pms_do_down(pms, false); - - return ret; -} - -/** - * sprd_pms_release_resource - release mpm resource. - * - * @pms, the point of this pms. - */ -void sprd_pms_release_resource(struct sprd_pms *pms) -{ - if (pms) - sprd_pms_do_down(pms, false); -} - -/** - * sprd_pms_request_wakelock - request wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_request_wakelock(struct sprd_pms *pms) -{ - if (pms) { - sprd_pms_cancel_timer(pms); - sprd_pms_stay_awake(pms); - } -} - -/** - * sprd_pms_release_wakelock - release wakelock - * - * @pms, the point of this pms. - */ -void sprd_pms_release_wakelock(struct sprd_pms *pms) -{ - if (pms) { - sprd_pms_cancel_timer(pms); - sprd_pms_relax(pms); - } -} - -/** - * sprd_pms_request_wakelock_period - - * request wake lock, and will auto reaslse in msec ms. - * - * @pms, the point of this pms. - * @msec, will auto reaslse in msec ms - */ -void sprd_pms_request_wakelock_period(struct sprd_pms *pms, unsigned int msec) -{ - sprd_pms_request_wakelock(pms); - sprd_pms_release_wakelock_later(pms, msec); -} - -/** - * sprd_pms_release_wakelock_later - release wakelock later. - * - * @pms, the point of this pms. - * @msec, later time (in ms). - */ -void sprd_pms_release_wakelock_later(struct sprd_pms *pms, - unsigned int msec) -{ - unsigned long expires; - unsigned long flags; - - if (pms) { - pr_debug("pms: %s release wakelock after %d ms.\n", - pms->name, msec); - - spin_lock_irqsave(&pms->expires_lock, flags); - expires = jiffies + msecs_to_jiffies(msec); - if (!expires) - expires = 1; - - /* always update the timer with new time */ - pms->expires = expires; - mod_timer(&pms->wake_timer, expires); - spin_unlock_irqrestore(&pms->expires_lock, flags); - } -} - -void sprd_pms_power_up(struct sprd_pms *pms) -{ - if (pms) - sprd_pms_do_up(pms); -} - -void sprd_pms_power_down(struct sprd_pms *pms, bool immediately) -{ - if (pms) - sprd_pms_do_down(pms, immediately); -} - -#if defined(CONFIG_DEBUG_FS) -static int sprd_mpm_stats_show(struct seq_file *m, void *unused) -{ - unsigned long flags; - struct sprd_pms *pms; - struct sprd_mpm_data *cur; - unsigned int i, ms; - - seq_puts(m, "---------------------------------------------\n"); - seq_puts(m, "All mpm list:\n"); - - for (i = 0; i < SIPC_ID_NR; i++) { - if (!g_sprd_mpm[i]) - continue; - - cur = g_sprd_mpm[i]; - seq_puts(m, "------------------------------------\n"); - seq_printf(m, "mpm = %s info:\n", cur->name); - seq_printf(m, "last up module = %s info:\n", - cur->last_name ? cur->last_name : "null"); - - if (cur->expires > 0) { - ms = jiffies_to_msecs(cur->expires - jiffies); - seq_printf(m, "left %d ms to idle\n", ms); - } - - seq_printf(m, "up_cnt=%d, state=%d.\n", - cur->up_cnt, cur->mpm_state); - seq_printf(m, "wakelock_cnt=%d, awake_cnt=%d\n", - cur->wakelock_cnt, cur->awake_cnt); - seq_puts(m, "------------------------------------\n"); - - seq_puts(m, "active pms list:\n"); - spin_lock_irqsave(&cur->mpm_lock, flags); - list_for_each_entry(pms, &cur->pms_list, entry) { - if (!pms->active_cnt && !pms->awake) - continue; - - seq_printf(m, " %s: active_cnt=%d, awake=%d\n", - pms->name, pms->active_cnt, pms->awake); - } - spin_unlock_irqrestore(&cur->mpm_lock, flags); - } - - seq_puts(m, "---------------------------------------------\n"); - - return 0; -} - -static int sprd_mpm_stats_open(struct inode *inode, struct file *file) -{ - return single_open(file, sprd_mpm_stats_show, NULL); -} - -static const struct file_operations sprd_mpm_stats_fops = { - .owner = THIS_MODULE, - .open = sprd_mpm_stats_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int sprd_mpm_init_debugfs(void) -{ - struct dentry *root = debugfs_create_dir("mpm", NULL); - - if (!root) - return -ENXIO; - - debugfs_create_file("power_manage", 0444, - (struct dentry *)root, - NULL, &sprd_mpm_stats_fops); - return 0; -} -#endif - - -int modem_power_manager_init(void) -{ - register_pm_notifier(&sprd_mpm_notifier_block); - -#if defined(CONFIG_DEBUG_FS) - sprd_mpm_init_debugfs(); -#endif - - return 0; -} -EXPORT_SYMBOL(modem_power_manager_init); - -void modem_power_manager_exit(void) -{ - unregister_pm_notifier(&sprd_mpm_notifier_block); -} -EXPORT_SYMBOL(modem_power_manager_exit); diff --git a/quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c b/quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c deleted file mode 100644 index fcd0d30..0000000 --- a/quectel_SRPD_PCIE/src/pwake_function/ipq4019/pcie-qcom.c +++ /dev/null @@ -1,2237 +0,0 @@ -/* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. - * Copyright 2015 Linaro Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pcie-designware.h" - -#define PCIE20_PARF_SYS_CTRL 0x00 -#define ECAM_BLOCKER_EN_RANGE2 BIT(30) -#define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29) -#define ECAM_REMOVE_OFFSET_EN BIT(27) -#define ECAM_BLOCKER_EN BIT(26) -#define MST_WAKEUP_EN BIT(13) -#define SLV_WAKEUP_EN BIT(12) -#define MSTR_ACLK_CGC_DIS BIT(10) -#define SLV_ACLK_CGC_DIS BIT(9) -#define CORE_CLK_CGC_DIS BIT(6) -#define AUX_PWR_DET BIT(4) -#define CORE_CLK_2AUX_CLK_MUX_DIS BIT(3) -#define L23_CLK_RMV_DIS BIT(2) -#define L1_CLK_RMV_DIS BIT(1) - -#define PCIE20_PARF_Q2A_FLUSH 0x1AC - -#define PCIE20_PARF_LTSSM 0x1B0 -#define LTSSM_EN (1 << 8) - -#define PCIE20_PARF_PHY_CTRL 0x40 -#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK (0x1f << 16) -#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) (x << 16) - -#define PCIE20_PARF_PHY_REFCLK 0x4C -#define REF_SSP_EN BIT(16) -#define REF_USE_PAD BIT(12) - -#define PCIE20_PARF_DBI_BASE_ADDR 0x168 -#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c -#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 - -#define PARF_MHI_CLOCK_RESET_CTRL 0x174 -#define BYPASS BIT(4) -#define MSTR_AXI_CLK_EN BIT(1) -#define AHB_CLK_EN BIT(0) - -#define PARF_BLOCK_SLV_AXI_WR_BASE 0x360 -#define PARF_BLOCK_SLV_AXI_WR_LIMIT 0x368 -#define PARF_BLOCK_SLV_AXI_RD_BASE 0x370 -#define PARF_BLOCK_SLV_AXI_RD_LIMIT 0x378 -#define PARF_ECAM_BASE 0x380 -#define PARF_ECAM_OFFSET_REMOVAL_BASE 0x388 -#define PARF_ECAM_OFFSET_REMOVAL_LIMIT 0x390 -#define PARF_BLOCK_SLV_AXI_WR_BASE_2 0x398 -#define PARF_BLOCK_SLV_AXI_WR_LIMIT_2 0x3A0 -#define PARF_BLOCK_SLV_AXI_RD_BASE_2 0x3A8 -#define PARF_BLOCK_SLV_AXI_RD_LIMIT_2 0x3B0 -#define PARF_BDF_TO_SID_TABLE 0x2000 - -#define PCIE_PARF_DEVICE_TYPE 0x1000 -#define DEVICE_TYPE_RC 0x4 - -#define PCIE20_ELBI_SYS_CTRL 0x04 -#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) -#define PCIE20_ELBI_SYS_STTS 0x08 -#define XMLH_LINK_UP 0x400 - -#define PCIE20_CAP 0x70 -#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10) - -#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818 -#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c - -#define PCIE20_PLR_IATU_VIEWPORT 0x900 -#define PCIE20_PLR_IATU_REGION_OUTBOUND (0x0 << 31) -#define PCIE20_PLR_IATU_REGION_INDEX(x) (x << 0) - -#define PCIE20_PLR_IATU_CTRL1 0x904 -#define PCIE20_PLR_IATU_TYPE_CFG0 (0x4 << 0) -#define PCIE20_PLR_IATU_TYPE_MEM (0x0 << 0) - -#define PCIE20_PLR_IATU_CTRL2 0x908 -#define PCIE20_PLR_IATU_ENABLE BIT(31) - -#define PCIE20_PLR_IATU_LBAR 0x90C -#define PCIE20_PLR_IATU_UBAR 0x910 -#define PCIE20_PLR_IATU_LAR 0x914 -#define PCIE20_PLR_IATU_LTAR 0x918 -#define PCIE20_PLR_IATU_UTAR 0x91c - -#define MSM_PCIE_DEV_CFG_ADDR 0x01000000 -#define PCIE20_CAP_LINK_CAPABILITIES (PCIE20_CAP + 0xC) -#define PCIE20_CAP_LINK_1 (PCIE20_CAP + 0x14) -#define PCIE_CAP_LINK1_VAL 0x2fd7f - - -#define PCIE20_COMMAND_STATUS 0x04 -#define CMD_BME_VAL 0x4 -#define BUS_MASTER_EN 0x7 - -#define PCIE20_DEVICE_CONTROL2_STATUS2 0x98 -#define PCIE_CAP_CPL_TIMEOUT_DISABLE 0x10 - -#define PCIE30_GEN3_RELATED_OFF 0x890 -#define GEN3_EQUALIZATION_DISABLE BIT(16) -#define RXEQ_RGRDLESS_RXTS BIT(13) -#define GEN3_ZRXDC_NONCOMPL BIT(0) - -#define PCIE20_MISC_CONTROL_1_REG 0x8BC -#define DBI_RO_WR_EN 1 - -#define PERST_DELAY_US 1000 -/* PARF registers */ -#define PCIE20_PARF_PCS_DEEMPH 0x34 -#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) (x << 16) -#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) (x << 8) -#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) (x << 0) - -#define PCIE20_PARF_PCS_SWING 0x38 -#define PCS_SWING_TX_SWING_FULL(x) (x << 8) -#define PCS_SWING_TX_SWING_LOW(x) (x << 0) - -#define PCIE20_PARF_CONFIG_BITS 0x50 -#define PHY_RX0_EQ(x) (x << 24) - -#define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xA0 -#define PCIE_CAP_CURR_DEEMPHASIS BIT(16) -#define SPEED_GEN1 0x1 -#define SPEED_GEN2 0x2 -#define SPEED_GEN3 0x3 -#define PCIE_CAP_TARGET_LINK_SPEED_MASK __mask(3, 0) - -#define __set(v, a, b) (((v) << (b)) & GENMASK(a, b)) -#define __mask(a, b) (((1 << ((a) + 1)) - 1) & ~((1 << (b)) - 1)) -#define PCIE20_DEV_CAS 0x78 -#define PCIE20_MRRS_MASK __mask(14, 12) -#define PCIE20_MRRS(x) __set(x, 14, 12) -#define PCIE20_MPS_MASK __mask(7, 5) -#define PCIE20_MPS(x) __set(x, 7, 5) - -#define AXI_CLK_RATE 200000000 -#define RCHNG_CLK_RATE 100000000 - -#define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358 -#define SLV_ADDR_SPACE_SZ 0x10000000 - -#define PCIE_V2_PARF_SIZE 0x2000 - -#define PCIE20_INT_ALL_STATUS 0x224 -#define PCIE20_INT_ALL_CLEAR 0x228 -#define PCIE20_INT_ALL_MASK 0x22c -#define PCIE_LINK_UP 0x2000 -#define PCIE_LINK_DOWN 0x2 - -#define PCIE_ATU_CR1_OUTBOUND_6_GEN3 0xC00 -#define PCIE_ATU_CR2_OUTBOUND_6_GEN3 0xC04 -#define PCIE_ATU_LOWER_BASE_OUTBOUND_6_GEN3 0xC08 -#define PCIE_ATU_UPPER_BASE_OUTBOUND_6_GEN3 0xC0C -#define PCIE_ATU_LIMIT_OUTBOUND_6_GEN3 0xC10 -#define PCIE_ATU_LOWER_TARGET_OUTBOUND_6_GEN3 0xC14 -#define PCIE_ATU_UPPER_TARGET_OUTBOUND_6_GEN3 0xC18 - -#define PCIE_ATU_CR1_OUTBOUND_7_GEN3 0xE00 -#define PCIE_ATU_CR2_OUTBOUND_7_GEN3 0xE04 -#define PCIE_ATU_LOWER_BASE_OUTBOUND_7_GEN3 0xE08 -#define PCIE_ATU_UPPER_BASE_OUTBOUND_7_GEN3 0xE0C -#define PCIE_ATU_LIMIT_OUTBOUND_7_GEN3 0xE10 -#define PCIE_ATU_LOWER_TARGET_OUTBOUND_7_GEN3 0xE14 -#define PCIE_ATU_UPPER_TARGET_OUTBOUND_7_GEN3 0xE18 - -#define PCIE_ASPM_MASK 0x3 -#define PCIE_ASPM_POS 10 - -struct qcom_pcie_resources_v0 { - struct clk *iface_clk; - struct clk *core_clk; - struct clk *phy_clk; - struct clk *aux_clk; - struct clk *ref_clk; - struct reset_control *pci_reset; - struct reset_control *axi_reset; - struct reset_control *ahb_reset; - struct reset_control *por_reset; - struct reset_control *phy_reset; - struct reset_control *ext_reset; - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; - uint8_t phy_tx0_term_offset; -}; - -struct qcom_pcie_resources_v1 { - struct clk *iface; - struct clk *aux; - struct clk *master_bus; - struct clk *slave_bus; - struct reset_control *core; - struct regulator *vdda; -}; - -struct qcom_pcie_resources_v2 { - struct clk *ahb_clk; - struct clk *axi_m_clk; - struct clk *axi_s_clk; - struct reset_control *axi_m_reset; - struct reset_control *axi_s_reset; - struct reset_control *pipe_reset; - struct reset_control *axi_m_vmid_reset; - struct reset_control *axi_s_xpu_reset; - struct reset_control *parf_reset; - struct reset_control *phy_reset; - struct reset_control *axi_m_sticky_reset; - struct reset_control *pipe_sticky_reset; - struct reset_control *pwr_reset; - struct reset_control *ahb_reset; - struct reset_control *phy_ahb_reset; - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; -}; - -struct qcom_pcie_resources_v3 { - struct clk *sys_noc_clk; - struct clk *axi_m_clk; - struct clk *axi_s_clk; - struct clk *ahb_clk; - struct clk *aux_clk; - struct clk *axi_bridge_clk; - struct clk *rchng_clk; - struct reset_control *axi_m_reset; - struct reset_control *axi_s_reset; - struct reset_control *pipe_reset; - struct reset_control *axi_m_sticky_reset; - struct reset_control *axi_s_sticky_reset; - struct reset_control *ahb_reset; - struct reset_control *sticky_reset; - struct reset_control *sleep_reset; - - struct regulator *vdda; - struct regulator *vdda_phy; - struct regulator *vdda_refclk; -}; - -union qcom_pcie_resources { - struct qcom_pcie_resources_v0 v0; - struct qcom_pcie_resources_v1 v1; - struct qcom_pcie_resources_v2 v2; - struct qcom_pcie_resources_v3 v3; -}; - -struct qcom_pcie; - -struct qcom_pcie_ops { - int (*get_resources)(struct qcom_pcie *pcie); - int (*init)(struct qcom_pcie *pcie); - void (*deinit)(struct qcom_pcie *pcie); -}; - -struct qcom_pcie { - struct pcie_port pp; - struct device *dev; - union qcom_pcie_resources res; - void __iomem *parf; - void __iomem *dbi; - void __iomem *elbi; - void __iomem *dm_iatu; - struct phy *phy; - struct gpio_desc *reset; - struct qcom_pcie_ops *ops; - struct work_struct handle_wake_work; - struct work_struct handle_e911_work; - uint32_t force_gen1; - uint32_t force_gen2; - u32 is_emulation; - u32 compliance; - u32 use_delay; - u32 link_retries_count; - u32 slot_id; - u32 cap_active_state_link_pm; - u32 is_gen3; - int global_irq; - int wake_irq; - int link_down_irq; - int link_up_irq; - int mdm2ap_e911_irq; - bool enumerated; - uint32_t rc_idx; - struct qcom_pcie_register_event *event_reg; - struct notifier_block pci_reboot_notifier; -}; - -#define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp) - -#define MAX_RC_NUM 3 -static struct qcom_pcie *qcom_pcie_dev[MAX_RC_NUM]; -struct gpio_desc *mdm2ap_e911; - -static inline void -writel_masked(void __iomem *addr, u32 clear_mask, u32 set_mask) -{ - u32 val = readl(addr); - - val &= ~clear_mask; - val |= set_mask; - writel(val, addr); -} - -static void qcom_ep_reset_assert(struct qcom_pcie *pcie) -{ - gpiod_set_value(pcie->reset, 1); - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); -} - -static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) -{ - msleep(100); - gpiod_set_value(pcie->reset, 0); - usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); -} - -static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg) -{ - struct pcie_port *pp = arg; - - return dw_handle_msi_irq(pp); -} - -static int qcom_pcie_establish_link(struct qcom_pcie *pcie) -{ - u32 val; - - if (dw_pcie_link_up(&pcie->pp)) - return 0; - - /* enable link training */ - val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL); - val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE; - writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL); - - return dw_pcie_wait_for_link(&pcie->pp); -} - -static void qcom_pcie_notify_client(struct qcom_pcie *dev, - enum qcom_pcie_event event) -{ - if (dev->event_reg && dev->event_reg->callback && - (dev->event_reg->events & event)) { - struct qcom_pcie_notify *notify = &dev->event_reg->notify; - notify->event = event; - notify->user = dev->event_reg->user; - pr_info("PCIe: callback RC%d for event %d.\n", - dev->rc_idx, event); - dev->event_reg->callback(notify); - - } else { - pr_info( - "PCIe: Client of RC%d does not have registered for event %d.\n", - dev->rc_idx, event); - } -} - -static irqreturn_t handle_link_down_irq(int irq, void *data) -{ - struct qcom_pcie *qcom_pcie = data; - - pr_info("PCIe: link_down IRQ for RC=%d\n", qcom_pcie->rc_idx); - - qcom_pcie_notify_client(qcom_pcie, QCOM_PCIE_EVENT_LINKDOWN); - return IRQ_HANDLED; -} - -static irqreturn_t handle_link_up_irq(int irq, void *data) -{ - struct qcom_pcie *qcom_pcie = data; - - pr_info("PCIe: link_up IRQ for RC=%d\n", qcom_pcie->rc_idx); - - return IRQ_HANDLED; -} - -/* PCIe wake-irq handler */ -static void handle_wake_func(struct work_struct *work) -{ - int ret; - struct qcom_pcie *pcie = container_of(work, struct qcom_pcie, - handle_wake_work); - struct pcie_port *pp = &pcie->pp; - - pci_lock_rescan_remove(); - if (pcie->enumerated) { - pr_info("PCIe: RC%d has been already enumerated\n", pcie->rc_idx); - pci_unlock_rescan_remove(); - return; - } - - if (!gpiod_get_value(mdm2ap_e911)) { - ret = dw_pcie_host_init_pm(pp); - - if (ret) - pr_err("PCIe: failed to enable RC%d upon wake request from the device\n", - pcie->rc_idx); - else { - pcie->enumerated = true; - pr_info("PCIe: enumerated RC%d successfully upon wake request from the device\n", - pcie->rc_idx); - } - } - - pci_unlock_rescan_remove(); -} - -static irqreturn_t qcom_pcie_wake_irq_handler(int irq, void *data) -{ - struct qcom_pcie *pcie = data; - - schedule_work(&pcie->handle_wake_work); - - return IRQ_HANDLED; -} - -/* PCIe global int handler */ -static irqreturn_t qcom_pcie_global_irq_handler(int irq, void *data) -{ - u32 status = 0; - unsigned long val, val_status, val_mask; - irqreturn_t ret = IRQ_HANDLED; - struct qcom_pcie *pcie = data; - - val_status = readl_relaxed(pcie->parf + PCIE20_INT_ALL_STATUS); - val_mask = readl_relaxed(pcie->parf + PCIE20_INT_ALL_MASK); - status = val_status & val_mask; - - /* Clear PARF status register */ - val = readl_relaxed(pcie->parf + PCIE20_INT_ALL_CLEAR) | status; - writel_relaxed(val, pcie->parf + PCIE20_INT_ALL_CLEAR); - /* ensure data is written to hw register */ - wmb(); - - if (status & PCIE_LINK_DOWN) - pr_info("PCIe: link_up IRQ for RC=%d\n", pcie->rc_idx); - if (status & PCIE_LINK_UP) - pr_info("PCIe: link_down IRQ for RC=%d\n", pcie->rc_idx); - - return ret; -} - -static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev) -{ - struct pcie_port *pp = &pcie->pp; - - /* - * program and enable address translation region 0 (device config - * address space); region type config; - * axi config address range to device config address range - */ - writel(PCIE20_PLR_IATU_REGION_OUTBOUND | - PCIE20_PLR_IATU_REGION_INDEX(0), - pcie->dbi + PCIE20_PLR_IATU_VIEWPORT); - - writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->dbi + PCIE20_PLR_IATU_CTRL1); - writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2); - writel(pp->cfg0_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); - writel((pp->cfg0_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); - writel((pp->cfg0_base + pp->cfg0_size - 1), - pcie->dbi + PCIE20_PLR_IATU_LAR); - writel(busdev, pcie->dbi + PCIE20_PLR_IATU_LTAR); - writel(0, pcie->dbi + PCIE20_PLR_IATU_UTAR); -} - -static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie) -{ - struct pcie_port *pp = &pcie->pp; - - /* - * program and enable address translation region 2 (device resource - * address space); region type memory; - * axi device bar address range to device bar address range - */ - writel(PCIE20_PLR_IATU_REGION_OUTBOUND | - PCIE20_PLR_IATU_REGION_INDEX(2), - pcie->dbi + PCIE20_PLR_IATU_VIEWPORT); - - writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->dbi + PCIE20_PLR_IATU_CTRL1); - writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2); - writel(pp->mem_base, pcie->dbi + PCIE20_PLR_IATU_LBAR); - writel((pp->mem_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR); - writel(pp->mem_base + pp->mem_size - 1, - pcie->dbi + PCIE20_PLR_IATU_LAR); - writel(pp->mem_bus_addr, pcie->dbi + PCIE20_PLR_IATU_LTAR); - writel(upper_32_bits(pp->mem_bus_addr), - pcie->dbi + PCIE20_PLR_IATU_UTAR); - - /* 256B PCIE buffer setting */ - writel(0x1, pcie->dbi + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); - writel(0x1, pcie->dbi + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); -} - -static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); - if (IS_ERR(res->vdda_phy)) - return PTR_ERR(res->vdda_phy); - - res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); - if (IS_ERR(res->vdda_refclk)) - return PTR_ERR(res->vdda_refclk); - - res->iface_clk = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface_clk)) - return PTR_ERR(res->iface_clk); - - res->core_clk = devm_clk_get(dev, "core"); - if (IS_ERR(res->core_clk)) - return PTR_ERR(res->core_clk); - - res->phy_clk = devm_clk_get(dev, "phy"); - if (IS_ERR(res->phy_clk)) - return PTR_ERR(res->phy_clk); - - res->aux_clk = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); - - res->ref_clk = devm_clk_get(dev, "ref"); - if (IS_ERR(res->ref_clk)) - return PTR_ERR(res->ref_clk); - - res->pci_reset = devm_reset_control_get(dev, "pci"); - if (IS_ERR(res->pci_reset)) - return PTR_ERR(res->pci_reset); - - res->axi_reset = devm_reset_control_get(dev, "axi"); - if (IS_ERR(res->axi_reset)) - return PTR_ERR(res->axi_reset); - - res->ahb_reset = devm_reset_control_get(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - res->por_reset = devm_reset_control_get(dev, "por"); - if (IS_ERR(res->por_reset)) - return PTR_ERR(res->por_reset); - - res->phy_reset = devm_reset_control_get(dev, "phy"); - if (IS_ERR(res->phy_reset)) - return PTR_ERR(res->phy_reset); - - res->ext_reset = devm_reset_control_get(dev, "ext"); - if (IS_ERR(res->ext_reset)) - return PTR_ERR(res->ext_reset); - - if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset", - &res->phy_tx0_term_offset)) - res->phy_tx0_term_offset = 0; - - return 0; -} - -static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->iface = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface)) - return PTR_ERR(res->iface); - - res->aux = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux)) - return PTR_ERR(res->aux); - - res->master_bus = devm_clk_get(dev, "master_bus"); - if (IS_ERR(res->master_bus)) - return PTR_ERR(res->master_bus); - - res->slave_bus = devm_clk_get(dev, "slave_bus"); - if (IS_ERR(res->slave_bus)) - return PTR_ERR(res->slave_bus); - - res->core = devm_reset_control_get(dev, "core"); - if (IS_ERR(res->core)) - return PTR_ERR(res->core); - - return 0; -} - -static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); - if (IS_ERR(res->vdda_phy)) - return PTR_ERR(res->vdda_phy); - - res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); - if (IS_ERR(res->vdda_refclk)) - return PTR_ERR(res->vdda_refclk); - - res->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(res->ahb_clk)) - return PTR_ERR(res->ahb_clk); - - res->axi_m_clk = devm_clk_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_clk)) - return PTR_ERR(res->axi_m_clk); - - res->axi_s_clk = devm_clk_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_clk)) - return PTR_ERR(res->axi_s_clk); - - res->axi_m_reset = devm_reset_control_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_reset)) - return PTR_ERR(res->axi_m_reset); - - res->axi_s_reset = devm_reset_control_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_reset)) - return PTR_ERR(res->axi_s_reset); - - res->pipe_reset = devm_reset_control_get(dev, "pipe"); - if (IS_ERR(res->pipe_reset)) - return PTR_ERR(res->pipe_reset); - - res->axi_m_vmid_reset = devm_reset_control_get(dev, "axi_m_vmid"); - if (IS_ERR(res->axi_m_vmid_reset)) - return PTR_ERR(res->axi_m_vmid_reset); - - res->axi_s_xpu_reset = devm_reset_control_get(dev, "axi_s_xpu"); - if (IS_ERR(res->axi_s_xpu_reset)) - return PTR_ERR(res->axi_s_xpu_reset); - - res->parf_reset = devm_reset_control_get(dev, "parf"); - if (IS_ERR(res->parf_reset)) - return PTR_ERR(res->parf_reset); - - res->phy_reset = devm_reset_control_get(dev, "phy"); - if (IS_ERR(res->phy_reset)) - return PTR_ERR(res->phy_reset); - - res->axi_m_sticky_reset = devm_reset_control_get(dev, "axi_m_sticky"); - if (IS_ERR(res->axi_m_sticky_reset)) - return PTR_ERR(res->axi_m_sticky_reset); - - res->pipe_sticky_reset = devm_reset_control_get(dev, "pipe_sticky"); - if (IS_ERR(res->pipe_sticky_reset)) - return PTR_ERR(res->pipe_sticky_reset); - - res->pwr_reset = devm_reset_control_get(dev, "pwr"); - if (IS_ERR(res->pwr_reset)) - return PTR_ERR(res->pwr_reset); - - res->ahb_reset = devm_reset_control_get(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - res->phy_ahb_reset = devm_reset_control_get(dev, "phy_ahb"); - if (IS_ERR(res->phy_ahb_reset)) - return PTR_ERR(res->phy_ahb_reset); - - return 0; -} - - -static int qcom_pcie_get_resources_v3(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - struct device *dev = pcie->dev; - - res->vdda = devm_regulator_get(dev, "vdda"); - if (IS_ERR(res->vdda)) - return PTR_ERR(res->vdda); - - res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); - if (IS_ERR(res->vdda_phy)) - return PTR_ERR(res->vdda_phy); - - res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); - if (IS_ERR(res->vdda_refclk)) - return PTR_ERR(res->vdda_refclk); - - res->sys_noc_clk = devm_clk_get(dev, "sys_noc"); - if (IS_ERR(res->sys_noc_clk)) - return PTR_ERR(res->sys_noc_clk); - - res->axi_m_clk = devm_clk_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_clk)) - return PTR_ERR(res->axi_m_clk); - - res->axi_s_clk = devm_clk_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_clk)) - return PTR_ERR(res->axi_s_clk); - - res->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(res->ahb_clk)) - return PTR_ERR(res->ahb_clk); - - res->aux_clk = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); - - if (pcie->is_gen3) { - res->axi_bridge_clk = devm_clk_get(dev, "axi_bridge"); - if (IS_ERR(res->axi_bridge_clk)) - return PTR_ERR(res->axi_bridge_clk); - - res->rchng_clk = devm_clk_get(dev, "rchng"); - if (IS_ERR(res->rchng_clk)) - res->rchng_clk = NULL; - } - - res->axi_m_reset = devm_reset_control_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_reset)) - return PTR_ERR(res->axi_m_reset); - - res->axi_s_reset = devm_reset_control_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_reset)) - return PTR_ERR(res->axi_s_reset); - - res->pipe_reset = devm_reset_control_get(dev, "pipe"); - if (IS_ERR(res->pipe_reset)) - return PTR_ERR(res->pipe_reset); - - res->axi_m_sticky_reset = devm_reset_control_get(dev, "axi_m_sticky"); - if (IS_ERR(res->axi_m_sticky_reset)) - return PTR_ERR(res->axi_m_sticky_reset); - - if (pcie->is_gen3) { - res->axi_s_sticky_reset = devm_reset_control_get(dev, "axi_s_sticky"); - if (IS_ERR(res->axi_s_sticky_reset)) - return PTR_ERR(res->axi_s_sticky_reset); - } - res->sticky_reset = devm_reset_control_get(dev, "sticky"); - if (IS_ERR(res->sticky_reset)) - return PTR_ERR(res->sticky_reset); - - res->ahb_reset = devm_reset_control_get(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - res->sleep_reset = devm_reset_control_get(dev, "sleep"); - if (IS_ERR(res->sleep_reset)) - return PTR_ERR(res->sleep_reset); - - return 0; -} - -static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; - - clk_disable_unprepare(res->phy_clk); - reset_control_assert(res->phy_reset); - reset_control_assert(res->axi_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->por_reset); - reset_control_assert(res->pci_reset); - reset_control_assert(res->ext_reset); - clk_disable_unprepare(res->iface_clk); - clk_disable_unprepare(res->core_clk); - clk_disable_unprepare(res->aux_clk); - clk_disable_unprepare(res->ref_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); -} - -static int qcom_pcie_init_v0(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v0 *res = &pcie->res.v0; - struct device *dev = pcie->dev; - int ret; - - ret = reset_control_assert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot assert ahb reset\n"); - return ret; - } - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - return ret; - } - - ret = regulator_enable(res->vdda_refclk); - if (ret) { - dev_err(dev, "cannot enable vdda_refclk regulator\n"); - goto err_refclk; - } - - ret = regulator_enable(res->vdda_phy); - if (ret) { - dev_err(dev, "cannot enable vdda_phy regulator\n"); - goto err_vdda_phy; - } - - ret = reset_control_deassert(res->ext_reset); - if (ret) { - dev_err(dev, "cannot assert ext reset\n"); - goto err_reset_ext; - } - - ret = clk_prepare_enable(res->iface_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_iface; - } - - ret = clk_prepare_enable(res->core_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_core; - } - - ret = clk_prepare_enable(res->aux_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_clk_aux; - } - - ret = clk_prepare_enable(res->ref_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable ref clock\n"); - goto err_clk_ref; - } - - ret = reset_control_deassert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot deassert ahb reset\n"); - goto err_deassert_ahb; - } - - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); - - /* Set Tx termination offset */ - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, - PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK, - PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset)); - - /* PARF programming */ - writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) | - PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) | - PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22), - pcie->parf + PCIE20_PARF_PCS_DEEMPH); - writel(PCS_SWING_TX_SWING_FULL(0x78) | - PCS_SWING_TX_SWING_LOW(0x78), - pcie->parf + PCIE20_PARF_PCS_SWING); - writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS); - - /* Enable reference clock */ - writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, - REF_USE_PAD, REF_SSP_EN); - - - ret = reset_control_deassert(res->phy_reset); - if (ret) { - dev_err(dev, "cannot deassert phy reset\n"); - return ret; - } - - ret = reset_control_deassert(res->pci_reset); - if (ret) { - dev_err(dev, "cannot deassert pci reset\n"); - return ret; - } - - ret = reset_control_deassert(res->por_reset); - if (ret) { - dev_err(dev, "cannot deassert por reset\n"); - return ret; - } - - ret = reset_control_deassert(res->axi_reset); - if (ret) { - dev_err(dev, "cannot deassert axi reset\n"); - return ret; - } - - ret = clk_prepare_enable(res->phy_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable phy clock\n"); - goto err_deassert_ahb; - } - - /* wait for clock acquisition */ - usleep_range(1000, 1500); - if (pcie->force_gen1) { - writel_relaxed(((readl_relaxed( - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2) - & (~PCIE_CAP_TARGET_LINK_SPEED_MASK)) | SPEED_GEN1), - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - } - - qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR); - qcom_pcie_prog_viewport_mem2_outbound(pcie); - - return 0; - -err_deassert_ahb: - clk_disable_unprepare(res->ref_clk); -err_clk_ref: - clk_disable_unprepare(res->aux_clk); -err_clk_aux: - clk_disable_unprepare(res->core_clk); -err_clk_core: - clk_disable_unprepare(res->iface_clk); -err_iface: - reset_control_assert(res->ext_reset); -err_reset_ext: - regulator_disable(res->vdda_phy); -err_vdda_phy: - regulator_disable(res->vdda_refclk); -err_refclk: - regulator_disable(res->vdda); - - return ret; -} - -static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; - - reset_control_assert(res->core); - clk_disable_unprepare(res->slave_bus); - clk_disable_unprepare(res->master_bus); - clk_disable_unprepare(res->iface); - clk_disable_unprepare(res->aux); - regulator_disable(res->vdda); -} - -static int qcom_pcie_init_v1(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v1 *res = &pcie->res.v1; - struct device *dev = pcie->dev; - int ret; - - ret = reset_control_deassert(res->core); - if (ret) { - dev_err(dev, "cannot deassert core reset\n"); - return ret; - } - - ret = clk_prepare_enable(res->aux); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_res; - } - - ret = clk_prepare_enable(res->iface); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_aux; - } - - ret = clk_prepare_enable(res->master_bus); - if (ret) { - dev_err(dev, "cannot prepare/enable master_bus clock\n"); - goto err_iface; - } - - ret = clk_prepare_enable(res->slave_bus); - if (ret) { - dev_err(dev, "cannot prepare/enable slave_bus clock\n"); - goto err_master; - } - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - goto err_slave; - } - - /* change DBI base address */ - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); - - val |= BIT(31); - writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); - } - - return 0; -err_slave: - clk_disable_unprepare(res->slave_bus); -err_master: - clk_disable_unprepare(res->master_bus); -err_iface: - clk_disable_unprepare(res->iface); -err_aux: - clk_disable_unprepare(res->aux); -err_res: - reset_control_assert(res->core); - - return ret; -} - -static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - - /* Assert pcie_pipe_ares */ - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->pipe_reset); - reset_control_assert(res->pipe_sticky_reset); - reset_control_assert(res->phy_reset); - reset_control_assert(res->phy_ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->axi_m_sticky_reset); - reset_control_assert(res->pwr_reset); - reset_control_assert(res->ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - clk_disable_unprepare(res->ahb_clk); - clk_disable_unprepare(res->axi_m_clk); - clk_disable_unprepare(res->axi_s_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); -} - -static int qcom_pcie_enable_resources_v2(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - struct device *dev = pcie->dev; - int ret; - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - return ret; - } - - ret = regulator_enable(res->vdda_refclk); - if (ret) { - dev_err(dev, "cannot enable vdda_refclk regulator\n"); - goto err_refclk; - } - - ret = regulator_enable(res->vdda_phy); - if (ret) { - dev_err(dev, "cannot enable vdda_phy regulator\n"); - goto err_vdda_phy; - } - - ret = clk_prepare_enable(res->ahb_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_ahb; - } - - ret = clk_prepare_enable(res->axi_m_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_axi_m; - } - - ret = clk_prepare_enable(res->axi_s_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable phy clock\n"); - goto err_clk_axi_s; - } - - udelay(1); - - return 0; - -err_clk_axi_s: - clk_disable_unprepare(res->axi_m_clk); -err_clk_axi_m: - clk_disable_unprepare(res->ahb_clk); -err_ahb: - regulator_disable(res->vdda_phy); -err_vdda_phy: - regulator_disable(res->vdda_refclk); -err_refclk: - regulator_disable(res->vdda); - return ret; -} - -static void qcom_pcie_v2_reset(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v2 *res = &pcie->res.v2; - /* Assert pcie_pipe_ares */ - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->pipe_reset); - reset_control_assert(res->pipe_sticky_reset); - reset_control_assert(res->phy_reset); - reset_control_assert(res->phy_ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_assert(res->axi_m_sticky_reset); - reset_control_assert(res->pwr_reset); - reset_control_assert(res->ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_deassert(res->phy_ahb_reset); - reset_control_deassert(res->phy_reset); - reset_control_deassert(res->pipe_reset); - reset_control_deassert(res->pipe_sticky_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_deassert(res->axi_m_reset); - reset_control_deassert(res->axi_m_sticky_reset); - reset_control_deassert(res->axi_s_reset); - reset_control_deassert(res->pwr_reset); - reset_control_deassert(res->ahb_reset); - usleep_range(10000, 12000); /* wait 12ms */ - wmb(); /* ensure data is written to hw register */ -} - -static int qcom_pcie_init_v2(struct qcom_pcie *pcie) -{ - int ret; - - qcom_pcie_v2_reset(pcie); - qcom_ep_reset_assert(pcie); - - ret = qcom_pcie_enable_resources_v2(pcie); - if (ret) - return ret; - - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); - - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); - - writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS - | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | - AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, - pcie->parf + PCIE20_PARF_SYS_CTRL); - writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); - writel(CMD_BME_VAL, pcie->dbi + PCIE20_COMMAND_STATUS); - writel(DBI_RO_WR_EN, pcie->dbi + PCIE20_MISC_CONTROL_1_REG); - writel(PCIE_CAP_LINK1_VAL, pcie->dbi + PCIE20_CAP_LINK_1); - - writel_masked(pcie->dbi + PCIE20_CAP_LINK_CAPABILITIES, - BIT(10) | BIT(11), 0); - writel(PCIE_CAP_CPL_TIMEOUT_DISABLE, pcie->dbi + - PCIE20_DEVICE_CONTROL2_STATUS2); - writel(LTSSM_EN, pcie->parf + PCIE20_PARF_LTSSM); - - return 0; -} - -static void qcom_pcie_deinit_v3(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - - clk_disable_unprepare(res->axi_m_clk); - clk_disable_unprepare(res->axi_s_clk); - clk_disable_unprepare(res->ahb_clk); - clk_disable_unprepare(res->aux_clk); - clk_disable_unprepare(res->sys_noc_clk); - regulator_disable(res->vdda); - regulator_disable(res->vdda_phy); - regulator_disable(res->vdda_refclk); -} - -static void qcom_pcie_v3_reset(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - /* Assert pcie_pipe_ares */ - reset_control_assert(res->pipe_reset); - reset_control_assert(res->sleep_reset); - reset_control_assert(res->sticky_reset); - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->axi_m_sticky_reset); - if (pcie->is_gen3) - reset_control_assert(res->axi_s_sticky_reset); - usleep_range(10000, 12000); /* wait 12ms */ - - reset_control_deassert(res->pipe_reset); - reset_control_deassert(res->sleep_reset); - reset_control_deassert(res->sticky_reset); - reset_control_deassert(res->axi_m_reset); - reset_control_deassert(res->axi_s_reset); - reset_control_deassert(res->ahb_reset); - reset_control_deassert(res->axi_m_sticky_reset); - if (pcie->is_gen3) - reset_control_deassert(res->axi_s_sticky_reset); - usleep_range(10000, 12000); /* wait 12ms */ - wmb(); /* ensure data is written to hw register */ -} - -static int qcom_pcie_enable_resources_v3(struct qcom_pcie *pcie) -{ - struct qcom_pcie_resources_v3 *res = &pcie->res.v3; - struct device *dev = pcie->dev; - int ret; - - ret = regulator_enable(res->vdda); - if (ret) { - dev_err(dev, "cannot enable vdda regulator\n"); - return ret; - } - - ret = regulator_enable(res->vdda_refclk); - if (ret) { - dev_err(dev, "cannot enable vdda_refclk regulator\n"); - goto err_refclk; - } - - ret = regulator_enable(res->vdda_phy); - if (ret) { - dev_err(dev, "cannot enable vdda_phy regulator\n"); - goto err_vdda_phy; - } - - ret = clk_prepare_enable(res->sys_noc_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_sys_noc; - } - - ret = clk_prepare_enable(res->axi_m_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_axi_m; - } - - ret = clk_set_rate(res->axi_m_clk, AXI_CLK_RATE); - if (ret) { - dev_err(dev, "MClk rate set failed (%d)\n", ret); - goto err_clk_axi_m; - } - - ret = clk_prepare_enable(res->axi_s_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable axi slave clock\n"); - goto err_clk_axi_s; - } - - ret = clk_set_rate(res->axi_s_clk, AXI_CLK_RATE); - if (ret) { - dev_err(dev, "MClk rate set failed (%d)\n", ret); - goto err_clk_axi_s; - } - - ret = clk_prepare_enable(res->ahb_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable ahb clock\n"); - goto err_clk_ahb; - } - - ret = clk_prepare_enable(res->aux_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_clk_aux; - } - - if (pcie->is_gen3) { - ret = clk_prepare_enable(res->axi_bridge_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable axi_bridge clock\n"); - goto err_clk_axi_bridge; - } - - if (res->rchng_clk) { - ret = clk_prepare_enable(res->rchng_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable rchng_clk clock\n"); - goto err_clk_rchng; - } - - ret = clk_set_rate(res->rchng_clk, RCHNG_CLK_RATE); - if (ret) { - dev_err(dev, "rchng_clk rate set failed (%d)\n", - ret); - goto err_clk_rchng; - } - } - } - - - udelay(1); - - return 0; - -err_clk_rchng: - clk_disable_unprepare(res->axi_bridge_clk); -err_clk_axi_bridge: - clk_disable_unprepare(res->aux_clk); -err_clk_aux: - clk_disable_unprepare(res->ahb_clk); -err_clk_ahb: - clk_disable_unprepare(res->axi_s_clk); -err_clk_axi_s: - clk_disable_unprepare(res->axi_m_clk); -err_clk_axi_m: - clk_disable_unprepare(res->sys_noc_clk); -err_clk_sys_noc: - regulator_disable(res->vdda_phy); -err_vdda_phy: - regulator_disable(res->vdda_refclk); -err_refclk: - regulator_disable(res->vdda); - return ret; -} - - -static int qcom_pcie_init_v3(struct qcom_pcie *pcie) -{ - int ret, i; - - qcom_pcie_v3_reset(pcie); - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - ret = qcom_pcie_enable_resources_v3(pcie); - if (ret) - return ret; - - writel(SLV_ADDR_SPACE_SZ, pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE); - - ret = phy_power_on(pcie->phy); - if (ret) - return ret; - - writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0); - - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); - - if (pcie->is_gen3) { - writel(DEVICE_TYPE_RC, pcie->parf + PCIE_PARF_DEVICE_TYPE); - writel(BYPASS | MSTR_AXI_CLK_EN | AHB_CLK_EN, - pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - writel(RXEQ_RGRDLESS_RXTS | - GEN3_ZRXDC_NONCOMPL, pcie->dbi + PCIE30_GEN3_RELATED_OFF); - } - - writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS - | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | - AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, - pcie->parf + PCIE20_PARF_SYS_CTRL); - - writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); - if (pcie->is_gen3) - writel(BUS_MASTER_EN, pcie->dbi + PCIE20_COMMAND_STATUS); - else - writel(CMD_BME_VAL, pcie->dbi + PCIE20_COMMAND_STATUS); - writel(DBI_RO_WR_EN, pcie->dbi + PCIE20_MISC_CONTROL_1_REG); - writel(PCIE_CAP_LINK1_VAL, pcie->dbi + PCIE20_CAP_LINK_1); - - /* Configure PCIe link capabilities for ASPM */ - writel_masked(pcie->dbi + PCIE20_CAP_LINK_CAPABILITIES, - PCIE_ASPM_MASK << PCIE_ASPM_POS, - (pcie->cap_active_state_link_pm & PCIE_ASPM_MASK) << PCIE_ASPM_POS); - - writel(PCIE_CAP_CPL_TIMEOUT_DISABLE, pcie->dbi + - PCIE20_DEVICE_CONTROL2_STATUS2); - - if (pcie->is_gen3 && !pcie->force_gen2) - writel_relaxed(PCIE_CAP_CURR_DEEMPHASIS | SPEED_GEN3, - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - else if (pcie->force_gen2) - writel_relaxed(PCIE_CAP_CURR_DEEMPHASIS | SPEED_GEN2, - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - - if (pcie->force_gen1) { - writel_relaxed(((readl_relaxed( - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2) - & (~PCIE_CAP_TARGET_LINK_SPEED_MASK)) | SPEED_GEN1), - pcie->dbi + PCIE20_LNK_CONTROL2_LINK_STATUS2); - } - - writel(LTSSM_EN, pcie->parf + PCIE20_PARF_LTSSM); - if (pcie->is_emulation) - qcom_ep_reset_deassert(pcie); - - if (pcie->is_gen3) { - for (i = 0; i < 255; i++) - writel(0x0, pcie->parf + PARF_BDF_TO_SID_TABLE + (4 * i)); - writel( 0x4, pcie->dm_iatu + PCIE_ATU_CR1_OUTBOUND_6_GEN3); - writel( 0x90000000, pcie->dm_iatu + PCIE_ATU_CR2_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_LOWER_BASE_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_UPPER_BASE_OUTBOUND_6_GEN3); - writel( 0x00107FFFF, pcie->dm_iatu + PCIE_ATU_LIMIT_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_LOWER_TARGET_OUTBOUND_6_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_UPPER_TARGET_OUTBOUND_6_GEN3); - writel( 0x5, pcie->dm_iatu + PCIE_ATU_CR1_OUTBOUND_7_GEN3); - writel( 0x90000000, pcie->dm_iatu + PCIE_ATU_CR2_OUTBOUND_7_GEN3); - writel( 0x200000, pcie->dm_iatu + PCIE_ATU_LOWER_BASE_OUTBOUND_7_GEN3); - writel( 0x0, pcie->dm_iatu+ PCIE_ATU_UPPER_BASE_OUTBOUND_7_GEN3); - writel( 0x7FFFFF, pcie->dm_iatu + PCIE_ATU_LIMIT_OUTBOUND_7_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_LOWER_TARGET_OUTBOUND_7_GEN3); - writel( 0x0, pcie->dm_iatu + PCIE_ATU_UPPER_TARGET_OUTBOUND_7_GEN3); - } - - phy_power_off(pcie->phy); - return 0; -} - -static int qcom_pcie_link_up(struct pcie_port *pp) -{ - struct qcom_pcie *pcie = to_qcom_pcie(pp); - u32 val; - - val = readl_relaxed(pcie->elbi + PCIE20_ELBI_SYS_STTS); - if (val & XMLH_LINK_UP) - return 1; - return 0; -} - -static int qcom_pcie_host_init(struct pcie_port *pp) -{ - struct qcom_pcie *pcie = to_qcom_pcie(pp); - int ret; - - if (gpiod_get_value(mdm2ap_e911)) - return -EBUSY; - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - ret = pcie->ops->init(pcie); - if (ret) - goto err_deinit; - - ret = phy_power_on(pcie->phy); - if (ret) - goto err_deinit; - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - if (!pp->msi_gicm_addr) - dw_pcie_msi_init(pp); - } - - if (!pcie->is_emulation) - qcom_ep_reset_deassert(pcie); - - ret = qcom_pcie_establish_link(pcie); - if (ret) - goto err; - - return 0; - -err: - if (pcie->compliance == 1) - return 0; - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - phy_power_off(pcie->phy); - -err_deinit: - if (pcie->compliance == 1) - return 0; - - pcie->ops->deinit(pcie); - return ret; -} - -static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, - u32 *val) -{ - /* the device class is not reported correctly from the register */ - if (where == PCI_CLASS_REVISION && size == 4) { - *val = readl(pp->dbi_base + PCI_CLASS_REVISION); - *val &= 0xff; /* keep revision id */ - *val |= PCI_CLASS_BRIDGE_PCI << 16; - return PCIBIOS_SUCCESSFUL; - } - - return dw_pcie_cfg_read(pp->dbi_base + where, size, val); -} - -static struct pcie_host_ops qcom_pcie_dw_ops = { - .link_up = qcom_pcie_link_up, - .host_init = qcom_pcie_host_init, - .rd_own_conf = qcom_pcie_rd_own_conf, -}; - -static const struct qcom_pcie_ops ops_v0 = { - .get_resources = qcom_pcie_get_resources_v0, - .init = qcom_pcie_init_v0, - .deinit = qcom_pcie_deinit_v0, -}; - -static const struct qcom_pcie_ops ops_v1 = { - .get_resources = qcom_pcie_get_resources_v1, - .init = qcom_pcie_init_v1, - .deinit = qcom_pcie_deinit_v1, -}; - -static const struct qcom_pcie_ops ops_v2 = { - .get_resources = qcom_pcie_get_resources_v2, - .init = qcom_pcie_init_v2, - .deinit = qcom_pcie_deinit_v2, -}; - -static const struct qcom_pcie_ops ops_v3 = { - .get_resources = qcom_pcie_get_resources_v3, - .init = qcom_pcie_init_v3, - .deinit = qcom_pcie_deinit_v3, -}; - -static void qcom_slot_remove(int val) -{ - - struct pcie_port *pp; - pci_lock_rescan_remove(); - - if ((val >= 0) && (val < MAX_RC_NUM)) { - if (qcom_pcie_dev[val]) { - if (!qcom_pcie_dev[val]->enumerated) { - pr_notice("\nPCIe: RC%d already removed", val); - } else { - pr_notice("---> Removing %d", val); - pp = &qcom_pcie_dev[val]->pp; - pci_stop_root_bus(pp->pci_bus); - pci_remove_root_bus(pp->pci_bus); - if (!qcom_pcie_dev[val]->is_emulation) - qcom_ep_reset_assert(qcom_pcie_dev[val]); - phy_power_off(qcom_pcie_dev[val]->phy); - qcom_pcie_dev[val]->ops->deinit(qcom_pcie_dev[val]); - pp->pci_bus = NULL; - qcom_pcie_dev[val]->enumerated = false; - pr_notice(" ... done<---\n"); - } - } - } - pci_unlock_rescan_remove(); -} - -static void qcom_slot_rescan(int val) -{ - - int ret; - struct pcie_port *pp; - pci_lock_rescan_remove(); - - if ((val >= 0) && (val < MAX_RC_NUM)) { - if (qcom_pcie_dev[val]) { - if (qcom_pcie_dev[val]->enumerated) { - pr_notice("PCIe: RC%d already enumerated", val); - } else { - pp = &qcom_pcie_dev[val]->pp; - ret = dw_pcie_host_init_pm(pp); - if (!ret) - qcom_pcie_dev[val]->enumerated = true; - } - } - } - pci_unlock_rescan_remove(); - -} - -int qcom_pcie_rescan(void) -{ - int i, ret; - struct pcie_port *pp; - - for (i = 0; i < MAX_RC_NUM; i++) { - /* reset and enumerate the pcie devices */ - if (qcom_pcie_dev[i]) { - pr_notice("---> Initializing %d\n", i); - if (qcom_pcie_dev[i]->enumerated) - continue; - - pp = &qcom_pcie_dev[i]->pp; - ret = dw_pcie_host_init_pm(pp); - if (!ret) - qcom_pcie_dev[i]->enumerated = true; - pr_notice(" ... done<---\n"); - } - } - return 0; -} - -void qcom_pcie_remove_bus(void) -{ - int i; - - for (i = 0; i < MAX_RC_NUM; i++) { - if (qcom_pcie_dev[i]) { - struct pcie_port *pp; - struct qcom_pcie *pcie; - - pr_notice("---> Removing %d\n", i); - - pcie = qcom_pcie_dev[i]; - if (!pcie->enumerated) - continue; - - pp = &qcom_pcie_dev[i]->pp; - pci_stop_root_bus(pp->pci_bus); - pci_remove_root_bus(pp->pci_bus); - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - phy_power_off(pcie->phy); - - qcom_pcie_dev[i]->ops->deinit(qcom_pcie_dev[i]); - pp->pci_bus = NULL; - pcie->enumerated = false; - pr_notice(" ... done<---\n"); - } - } -} - -static void handle_e911_func(struct work_struct *work) -{ - - int slot_id; - struct qcom_pcie *pcie = container_of(work, struct qcom_pcie, - handle_e911_work); - slot_id = pcie->slot_id; - - if (gpiod_get_value(mdm2ap_e911)) - qcom_slot_remove(slot_id); - else - qcom_slot_rescan(slot_id); -} - -static irqreturn_t handle_mdm2ap_e911_irq(int irq, void *data) -{ - struct qcom_pcie *pcie = data; - - schedule_work(&pcie->handle_e911_work); - - return IRQ_HANDLED; -} - -static ssize_t qcom_bus_rescan_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - if (gpiod_get_value(mdm2ap_e911)) - return -EBUSY; - - if (val) { - pci_lock_rescan_remove(); - qcom_pcie_rescan(); - pci_unlock_rescan_remove(); - } - return count; -} -static BUS_ATTR(rcrescan, (S_IWUSR|S_IWGRP), NULL, qcom_bus_rescan_store); - -static ssize_t qcom_bus_remove_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - if (val) { - pci_lock_rescan_remove(); - qcom_pcie_remove_bus(); - pci_unlock_rescan_remove(); - } - return count; -} -static BUS_ATTR(rcremove, (S_IWUSR|S_IWGRP), NULL, qcom_bus_remove_store); - -static ssize_t qcom_slot_rescan_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - qcom_slot_rescan(val); - - return count; -} -static BUS_ATTR(slot_rescan, (S_IWUSR|S_IWGRP), NULL, qcom_slot_rescan_store); - -static ssize_t qcom_slot_remove_store(struct bus_type *bus, const char *buf, - size_t count) -{ - unsigned long val; - - if (kstrtoul(buf, 0, &val) < 0) - return -EINVAL; - - qcom_slot_remove(val); - - return count; -} -static BUS_ATTR(slot_remove, (S_IWUSR|S_IWGRP), NULL, qcom_slot_remove_store); - -int qcom_pcie_register_event(struct qcom_pcie_register_event *reg) -{ - int ret = 0; - struct pci_dev *pci_dev; - struct pcie_port *pp; - struct qcom_pcie *qcom_pcie; - - if (!reg) { - pr_err("PCIe: Event registration is NULL\n"); - return -ENODEV; - } - - if (!reg->user) { - pr_err("PCIe: User of event registration is NULL\n"); - return -ENODEV; - } - pci_dev = (struct pci_dev *)reg->user; - pp = pci_dev->bus->sysdata; - qcom_pcie = to_qcom_pcie(pp); - - if (qcom_pcie) { - qcom_pcie->event_reg = reg; - pr_info("Event 0x%x is registered for RC %d\n", reg->events, - qcom_pcie->rc_idx); - } else { - pr_err("PCIe: did not find RC for pci endpoint device %p\n", - reg->user); - ret = -ENODEV; - } - - return ret; -} -EXPORT_SYMBOL(qcom_pcie_register_event); - -int qcom_pcie_deregister_event(struct qcom_pcie_register_event *reg) -{ - int ret = 0; - struct pci_dev *pci_dev; - struct pcie_port *pp; - struct qcom_pcie *qcom_pcie; - - if (!reg) { - pr_err("PCIe: Event deregistration is NULL\n"); - return -ENODEV; - } - - if (!reg->user) { - pr_err("PCIe: User of event deregistration is NULL\n"); - return -ENODEV; - } - pci_dev = (struct pci_dev *)reg->user; - pp = pci_dev->bus->sysdata; - qcom_pcie = to_qcom_pcie(pp); - - if (qcom_pcie) { - qcom_pcie->event_reg = NULL; - pr_info("Event is deregistered for RC %d\n", - qcom_pcie->rc_idx); - } else { - pr_err("PCIe: did not find RC for pci endpoint device %p\n", - reg->user); - ret = -ENODEV; - } - - return ret; -} -EXPORT_SYMBOL(qcom_pcie_deregister_event); - -static int pci_reboot_handler(struct notifier_block *this, - unsigned long event, void *ptr) -{ - pci_lock_rescan_remove(); - qcom_pcie_remove_bus(); - pci_unlock_rescan_remove(); - - return 0; -} - -static int qcom_pcie_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *res; - struct qcom_pcie *pcie; - struct pcie_port *pp; - int ret; - uint32_t force_gen1 = 0; - uint32_t force_gen2 = 0; - struct device_node *np = pdev->dev.of_node; - u32 is_emulation = 0; - u32 use_delay = 0; - u32 link_retries_count = 0; - u32 slot_id = -1; - u32 compliance = 0; - static int rc_idx; - int i; - char irq_name[20]; - u32 soc_version_major; - int index = 0; - - pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); - if (!pcie) - return -ENOMEM; - - pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev); - pcie->dev = dev; - - of_property_read_u32(np, "compliance", &compliance); - pcie->compliance = compliance; - - of_property_read_u32(np, "is_emulation", &is_emulation); - pcie->is_emulation = is_emulation; - - of_property_read_u32(np, "use_delay", &use_delay); - pcie->use_delay = use_delay; - - of_property_read_u32(np, "link_retries_count", &link_retries_count); - pcie->link_retries_count = link_retries_count; - - of_property_read_u32(np, "slot_id", &slot_id); - pcie->slot_id = slot_id; - - of_property_read_u32(np, "pcie-cap-active-state-link-pm", - &pcie->cap_active_state_link_pm); - - pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH); - if (IS_ERR(pcie->reset)) - return PTR_ERR(pcie->reset); - - of_property_read_u32(np, "force_gen1", &force_gen1); - pcie->force_gen1 = force_gen1; - - of_property_read_u32(np, "force_gen2", &force_gen2); - pcie->force_gen2 = force_gen2; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - pcie->dbi = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->dbi)) - return PTR_ERR(pcie->dbi); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); - pcie->elbi = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->elbi)) - return PTR_ERR(pcie->elbi); - - pcie->is_gen3 = 0; - if (of_device_is_compatible(pdev->dev.of_node, "qcom,pcie-ipq807x")) { - soc_version_major = read_ipq_soc_version_major(); - BUG_ON(soc_version_major <= 0); - index = of_property_match_string(dev->of_node, "phy-names", - "pciephy"); - if (index < 0) { - if (soc_version_major == 1) { - pcie->phy = devm_phy_optional_get(dev, "pciephy-gen2"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - pcie->is_gen3 = 0; - } else if (soc_version_major == 2) { - pcie->phy = devm_phy_optional_get(dev, "pciephy-gen3"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - pcie->is_gen3 = 1; - } else { - dev_err(dev, "missing phy-names\n"); - return index; - } - } else { - pcie->phy = devm_phy_optional_get(dev, "pciephy"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - pcie->is_gen3 = 0; - } - } else if (of_device_is_compatible(pdev->dev.of_node, "qcom,pcie-ipq6018")) { - if (!pcie->is_emulation) { - pcie->phy = devm_phy_optional_get(dev, "pciephy"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - } - pcie->is_gen3 = 1; - } else if (of_device_is_compatible(pdev->dev.of_node, - "qcom,pcie-ipq5018")) { - if (!pcie->is_emulation) { - pcie->phy = devm_phy_optional_get(dev, "pciephy"); - if (IS_ERR(pcie->phy)) - return PTR_ERR(pcie->phy); - } - pcie->is_gen3 = 1; - } - - if (pcie->is_gen3) { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dm_iatu"); - pcie->dm_iatu = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->dm_iatu)) - return PTR_ERR(pcie->dm_iatu); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); - if (res) - res->end += PCIE_V2_PARF_SIZE; - pcie->parf = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->parf)) - return PTR_ERR(pcie->parf); - } else { - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); - pcie->parf = devm_ioremap_resource(dev, res); - if (IS_ERR(pcie->parf)) - return PTR_ERR(pcie->parf); - } - - ret = pcie->ops->get_resources(pcie); - if (ret) - return ret; - - pp = &pcie->pp; - pp->dev = dev; - pp->dbi_base = pcie->dbi; - pp->dm_iatu = pcie->dm_iatu; - pp->is_gen3 = pcie->is_gen3; - pp->use_delay = pcie->use_delay; - pp->link_retries_count = pcie->link_retries_count; - pp->root_bus_nr = -1; - pp->ops = &qcom_pcie_dw_ops; - - pcie->mdm2ap_e911_irq = platform_get_irq_byname(pdev, - "mdm2ap_e911"); - if (pcie->mdm2ap_e911_irq >= 0) { - mdm2ap_e911 = devm_gpiod_get_optional(&pdev->dev, "e911", - GPIOD_IN); - - if (IS_ERR(mdm2ap_e911)) { - pr_err("requesting for e911 gpio failed %ld\n", - PTR_ERR(mdm2ap_e911)); - return PTR_ERR(mdm2ap_e911); - } - - INIT_WORK(&pcie->handle_e911_work, handle_e911_func); - - ret = devm_request_irq(&pdev->dev, pcie->mdm2ap_e911_irq, - handle_mdm2ap_e911_irq, - IRQ_TYPE_EDGE_BOTH, "mdm2ap_e911", - pcie); - - if (ret) { - dev_err(&pdev->dev, "Unable to request mdm2ap_e911 irq\n"); - return ret; - } - - pcie->pci_reboot_notifier.notifier_call = pci_reboot_handler; - ret = register_reboot_notifier(&pcie->pci_reboot_notifier); - if (ret) { - pr_warn("%s: Failed to register notifier (%d)\n", - __func__, ret); - return ret; - } - } - - pcie->link_down_irq = platform_get_irq_byname(pdev, - "int_link_down"); - if (pcie->link_down_irq >= 0) { - ret = devm_request_irq(&pdev->dev, pcie->link_down_irq, - handle_link_down_irq, - IRQF_TRIGGER_RISING, "pci_link_down", - pcie); - } - - pcie->link_up_irq = platform_get_irq_byname(pdev, "int_link_up"); - if (pcie->link_up_irq >= 0) { - ret = devm_request_irq(&pdev->dev, pcie->link_up_irq, - handle_link_up_irq, - IRQF_TRIGGER_RISING, "pci_link_up", - pcie); - } - - pcie->global_irq = platform_get_irq_byname(pdev, "global"); - if (pcie->global_irq >= 0) { - ret = devm_request_irq(&pdev->dev, pcie->global_irq, - qcom_pcie_global_irq_handler, - IRQF_TRIGGER_RISING, "qcom-pcie-global", pcie); - if (ret) { - dev_err(&pdev->dev, "cannot request global irq\n"); - return ret; - } - } - - pp->msi_gicm_addr = 0; - pp->msi_gicm_base = 0; - of_property_read_u32(np, "qcom,msi-gicm-addr", &pp->msi_gicm_addr); - of_property_read_u32(np, "qcom,msi-gicm-base", &pp->msi_gicm_base); - - if (IS_ENABLED(CONFIG_PCI_MSI)) { - pp->msi_irq = platform_get_irq_byname(pdev, "msi"); - if (pp->msi_irq < 0) - return pp->msi_irq; - - ret = devm_request_irq(dev, pp->msi_irq, - qcom_pcie_msi_irq_handler, - IRQF_SHARED, "qcom-pcie-msi", pp); - if (ret) { - dev_err(dev, "cannot request msi irq\n"); - return ret; - } - for (i = 0; i < MAX_MSI_IRQS; i++) { - snprintf(irq_name, sizeof(irq_name), "msi_%d", i); - pp->msi[i] = platform_get_irq_byname(pdev, irq_name); - if (pp->msi[i] < 0) - break; - } - } - - ret = phy_init(pcie->phy); - if (ret) - return ret; - - pcie->wake_irq = platform_get_irq_byname(pdev, "wake_gpio"); - - ret = dw_pcie_host_init(pp); - - if (ret) { - if (pcie->wake_irq < 0) { - dev_err(dev, "cannot initialize host\n"); - return ret; - } - pr_info("PCIe: RC%d is not enabled during bootup;it will be enumerated upon client request\n", - rc_idx); - } else { - pcie->enumerated = true; - pr_info("PCIe: RC%d enabled during bootup\n", rc_idx); - } - - if (pcie->wake_irq >= 0) { - INIT_WORK(&pcie->handle_wake_work, handle_wake_func); - - ret = devm_request_irq(&pdev->dev, pcie->wake_irq, - qcom_pcie_wake_irq_handler, - IRQF_TRIGGER_FALLING, "qcom-pcie-wake", pcie); - if (ret) { - dev_err(&pdev->dev, "Unable to request wake irq\n"); - return ret; - } - } - - /* - ####ipq-4019, add pcie_wake control - static irqreturn_t quectel_pcie_wake_irq(int irq, void *data) - { - return IRQ_WAKE_THREAD; - } - - static irqreturn_t quectel_pcie_wake_thread_irq(int irq, void *data) - { - struct qcom_pcie *pcie = data; - int val = gpiod_get_value(pcie->quectel_pwake); - struct dw_pcie *pci = ep->pci; - - pr_info("pwake val: %d\n", val); - if (val){ - //up: rescan - pci_lock_rescan_remove(); - qcom_pcie_rescan(); - pci_unlock_rescan_remove(); - }else{ - //down: remove - pci_lock_rescan_remove(); - qcom_pcie_remove_bus(); - pci_unlock_rescan_remove(); - } - return IRQ_HANDLED; - } - - pcie->quectel_pwake = devm_gpiod_get_index(dev, "pcie-wake", 0, GPIOD_IN); - if (IS_ERR(pcie->quectel_pwake)) { - dev_err(&pdev->dev, "Please set pcie-wake gpio in DTS\n"); - return PTR_ERR(pcie->quectel_pwake); - } - - pcie->quectel_pwake_irq = gpiod_to_irq(pcie->quectel_pwake); - - ret = devm_request_threaded_irq(&pdev->dev, pcie->quectel_pwake_irq, - quectel_pcie_wake_irq, - quectel_pcie_wake_thread_irq, - IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND, - "quectel-pcie-wake", pcie); - - enable_irq_wake(pcie->quectel_pcie_wake); - */ - - platform_set_drvdata(pdev, pcie); - - if (!rc_idx) { - ret = bus_create_file(&pci_bus_type, &bus_attr_rcrescan); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcrescan file\n"); - return ret; - } - - ret = bus_create_file(&pci_bus_type, &bus_attr_rcremove); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcremove file\n"); - return ret; - } - } - - /* create sysfs files to support slot rescan and remove*/ - if (!rc_idx) { - ret = bus_create_file(&pci_bus_type, &bus_attr_slot_rescan); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcrescan file\n"); - return ret; - } - - ret = bus_create_file(&pci_bus_type, &bus_attr_slot_remove); - if (ret != 0) { - dev_err(&pdev->dev, - "Failed to create sysfs rcremove file\n"); - return ret; - } - } - - pcie->rc_idx = rc_idx; - qcom_pcie_dev[rc_idx++] = pcie; - - return 0; -} - -static int qcom_pcie_remove(struct platform_device *pdev) -{ - struct qcom_pcie *pcie = platform_get_drvdata(pdev); - - if (!pcie->is_emulation) - qcom_ep_reset_assert(pcie); - - phy_power_off(pcie->phy); - phy_exit(pcie->phy); - pcie->ops->deinit(pcie); - - return 0; -} - -static void qcom_pcie_fixup_final(struct pci_dev *dev) -{ - int cap, err; - u16 ctl, reg_val; - - cap = pci_pcie_cap(dev); - if (!cap) - return; - - err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl); - - if (err) - return; - - reg_val = ctl; - - if (((reg_val & PCIE20_MRRS_MASK) >> 12) > 1) - reg_val = (reg_val & ~(PCIE20_MRRS_MASK)) | PCIE20_MRRS(0x1); - - if (((ctl & PCIE20_MPS_MASK) >> 5) > 1) - reg_val = (reg_val & ~(PCIE20_MPS_MASK)) | PCIE20_MPS(0x1); - - err = pci_write_config_word(dev, cap + PCI_EXP_DEVCTL, reg_val); - - if (err) - pr_err("pcie config write failed %d\n", err); -} -DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, qcom_pcie_fixup_final); - -static const struct of_device_id qcom_pcie_match[] = { - { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, - { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, - { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, - { .compatible = "qcom,pcie-ipq4019", .data = &ops_v2 }, - { .compatible = "qcom,pcie-ipq807x", .data = &ops_v3 }, - { .compatible = "qcom,pcie-ipq6018", .data = &ops_v3 }, - { .compatible = "qcom,pcie-ipq5018", .data = &ops_v3 }, - { } -}; -MODULE_DEVICE_TABLE(of, qcom_pcie_match); - -static struct platform_driver qcom_pcie_driver = { - .probe = qcom_pcie_probe, - .remove = qcom_pcie_remove, - .driver = { - .name = "qcom-pcie", - .of_match_table = qcom_pcie_match, - }, -}; - -module_platform_driver(qcom_pcie_driver); - -MODULE_AUTHOR("Stanimir Varbanov "); -MODULE_DESCRIPTION("Qualcomm PCIe root complex driver"); -MODULE_LICENSE("GPL v2"); diff --git a/quectel_SRPD_PCIE/src/sipa/Kconfig b/quectel_SRPD_PCIE/src/sipa/Kconfig deleted file mode 100644 index f648033..0000000 --- a/quectel_SRPD_PCIE/src/sipa/Kconfig +++ /dev/null @@ -1,9 +0,0 @@ -menu "SIPA modules" - -config SPRD_SIPA - bool "sipa ipa" - default n - help - sipa is a module for spreadtrum ip packet accelator driver. - -endmenu diff --git a/quectel_SRPD_PCIE/src/sipa/Makefile b/quectel_SRPD_PCIE/src/sipa/Makefile deleted file mode 100644 index 1d5101b..0000000 --- a/quectel_SRPD_PCIE/src/sipa/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -EXTRA_CFLAGS += -Wno-error -Wno-packed-bitfield-compat -ccflags-y += -DCONFIG_SPRD_SIPA -obj-y += sipa_core.o sipa_skb_send.o sipa_skb_recv.o \ - sipa_nic.o sipa_debugfs.o sipa_dele_cmn.o \ - sipa_eth.o sipa_dummy.o -obj-y += sipa_phy_v0/ diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_core.c b/quectel_SRPD_PCIE/src/sipa/sipa_core.c deleted file mode 100644 index bcde7e5..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_core.c +++ /dev/null @@ -1,333 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note. - * - * UNISOC 'virt sipa' driver - * - * Qingsheng.Li - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License v2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipa.h" -#include "../include/sprd_pcie_ep_device.h" -#include "../include/sipc.h" -#include "sipa_core.h" - -#define DRV_NAME "virt_sipa" - -struct sipa_core *sipa_ctrl; - -struct sipa_core *sipa_get_ctrl_pointer(void) -{ - return sipa_ctrl; -} -EXPORT_SYMBOL(sipa_get_ctrl_pointer); - -static void sipa_notify_sender_flow_ctrl(struct work_struct *work) -{ - struct sipa_core *sipa_ctrl = container_of(work, struct sipa_core, - flow_ctrl_work); - - if (sipa_ctrl->sender && sipa_ctrl->sender->free_notify_net) - wake_up(&sipa_ctrl->sender->free_waitq); -} - -static int sipa_init_cmn_fifo(struct sipa_core *ipa, - enum sipa_cmn_fifo_index id) -{ - size_t size; - dma_addr_t dma_addr; - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - - cmn_fifo = &ipa->cmn_fifo_cfg[id]; - cmn_fifo->fifo_id = id; - cmn_fifo->dst = SIPA_TERM_VCP; - cmn_fifo->cur = SIPA_TERM_PCIE0; - size = cmn_fifo->tx_fifo.depth * - sizeof(struct sipa_node_description_tag); - cmn_fifo->tx_fifo.virtual_addr = dma_alloc_coherent(ipa->pci_dev, size, - &dma_addr, - GFP_KERNEL); - if (!cmn_fifo->tx_fifo.virtual_addr) - return -ENOMEM; - cmn_fifo->tx_fifo.dma_ptr = dma_addr; - memset(cmn_fifo->tx_fifo.virtual_addr, 0, size); - pr_info("comfifo%d tx_fifo addr-0x%lx\n", id, (long unsigned int)cmn_fifo->tx_fifo.virtual_addr); - - cmn_fifo->tx_fifo.fifo_base_addr_l = lower_32_bits(dma_addr); - cmn_fifo->tx_fifo.fifo_base_addr_h = 0x2; - - size = cmn_fifo->rx_fifo.depth * - sizeof(struct sipa_node_description_tag); - cmn_fifo->rx_fifo.virtual_addr = dma_alloc_coherent(ipa->pci_dev, size, - &dma_addr, - GFP_KERNEL); - if (!cmn_fifo->rx_fifo.virtual_addr) - return -ENOMEM; - cmn_fifo->rx_fifo.dma_ptr = dma_addr; - memset(cmn_fifo->rx_fifo.virtual_addr, 0, size); - pr_info("comfifo%d rx_fifo addr-0x%lx\n", id, (long unsigned int)cmn_fifo->rx_fifo.virtual_addr); - - cmn_fifo->rx_fifo.fifo_base_addr_l = lower_32_bits(dma_addr); - cmn_fifo->rx_fifo.fifo_base_addr_h = 0x2; - - return 0; -} - -static void sipa_free_cmn_fifo(struct sipa_core *ipa, enum sipa_cmn_fifo_index id) -{ - size_t size; - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - - cmn_fifo = &ipa->cmn_fifo_cfg[id]; - size = cmn_fifo->tx_fifo.depth * sizeof(struct sipa_node_description_tag); - dma_free_coherent(ipa->dev, size, cmn_fifo->tx_fifo.virtual_addr, cmn_fifo->tx_fifo.dma_ptr); - size = cmn_fifo->rx_fifo.depth * sizeof(struct sipa_node_description_tag); - dma_free_coherent(ipa->dev, size, cmn_fifo->rx_fifo.virtual_addr, cmn_fifo->rx_fifo.dma_ptr); -} - -static void sipa_init_ep(struct sipa_core *ipa) -{ - struct sipa_endpoint *ep = &ipa->ep; - - ep->send_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - ep->recv_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; -} - -#ifdef SPRD_PCIE_USE_DTS -static int sipa_parse_dts_configuration(struct platform_device *pdev, - struct sipa_core *ipa) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - - ipa->reg_res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "ipa-base"); - if (!ipa->reg_res) { - dev_err(&pdev->dev, "get ipa-base res fail\n"); - return -EINVAL; - } - - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - ret = of_property_read_u32(pdev->dev.of_node, "pcie-dl-tx-fifo-depth", - &cmn_fifo->tx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-dl-tx-fifo-depth ret = %d\n", ret); - return ret; - } - - ret = of_property_read_u32(pdev->dev.of_node, "pcie-dl-rx-fifo-depth", - &cmn_fifo->rx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-dl-rx-fifo-depth ret = %d\n", ret); - return ret; - } - - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - ret = of_property_read_u32(pdev->dev.of_node, "pcie-ul-tx-fifo-depth", - &cmn_fifo->tx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-ul-tx-fifo-depth ret = %d\n", ret); - return ret; - } - - ret = of_property_read_u32(pdev->dev.of_node, "pcie-ul-rx-fifo-depth", - &cmn_fifo->rx_fifo.depth); - if (ret) { - dev_err(&pdev->dev, - "get pcie-ul-rx-fifo-depth ret = %d\n", ret); - return ret; - } - - return 0; -} -#else -static struct resource ipa_res = { - .start = 0x2e000000, - .end = 0x2e000000 + 0x2000 -1, - .flags = IORESOURCE_MEM, -}; - -static int sipa_parse_dts_configuration(struct platform_device *pdev, - struct sipa_core *ipa) -{ - struct sipa_cmn_fifo_cfg_tag *cmn_fifo; - ipa->reg_res = &ipa_res; - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - cmn_fifo->tx_fifo.depth = 4096; - cmn_fifo->rx_fifo.depth = 4096; - cmn_fifo = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - cmn_fifo->tx_fifo.depth = 4096; - cmn_fifo->rx_fifo.depth = 4096; - return 0; -} -#endif - -static int sipa_plat_drv_probe(struct platform_device *pdev) -{ - int ret; - struct sipa_core *ipa; - struct device *dev = &pdev->dev; - struct device *pci_dev; - - pci_dev = (struct device *)dev_get_drvdata(dev); - if(!pci_dev) - return -1; - - ipa = devm_kzalloc(dev, sizeof(*ipa), GFP_KERNEL); - if (!ipa) - return -ENOMEM; - - sipa_ctrl = ipa; - ipa->dev = dev; - ipa->pci_dev = pci_dev; - ipa->pcie_mem_offset = SIPA_PCIE_MEM_OFFSET; - dev_set_drvdata(dev, ipa); - ret = sipa_parse_dts_configuration(pdev, ipa); - if (ret) - return ret; - - ret = sipa_init_cmn_fifo(ipa, SIPA_FIFO_PCIE_DL); - if (ret) - return ret; - - ret = sipa_init_cmn_fifo(ipa, SIPA_FIFO_PCIE_UL); - if (ret) - return ret; - - sipa_init_ep(ipa); - - sipa_fifo_ops_init(&ipa->hal_ops); - INIT_WORK(&ipa->flow_ctrl_work, sipa_notify_sender_flow_ctrl); - - create_sipa_skb_receiver(&ipa->ep, &ipa->receiver); - create_sipa_skb_sender(&ipa->ep, &ipa->sender); - device_init_wakeup(dev, true); - - sipa_create_smsg_channel(ipa); - - sprd_ep_dev_register_irq_handler(PCIE_EP_MODEM, PCIE_MSI_IPA, - (irq_handler_t)sipa_int_callback_func, - (void *)ipa); - sipa_init_debugfs(ipa); - - return 0; -} - -extern void destroy_sipa_skb_receiver(struct sipa_skb_receiver *receiver); -extern void destroy_sipa_skb_sender(struct sipa_skb_sender *sender); - -static int sipa_plat_drv_remove(struct platform_device *pdev) -{ - struct sipa_core *ipa; - - ipa = dev_get_drvdata(&pdev->dev); - smsg_ch_close(SIPC_ID_MINIAP, SMSG_CH_COMM_SIPA, 1000); - if(ipa->smsg_thread){ - kthread_stop(ipa->smsg_thread); - ipa->smsg_thread = NULL; - } - destroy_sipa_skb_sender(ipa->sender); - destroy_sipa_skb_receiver(ipa->receiver); - cancel_work_sync(&ipa->flow_ctrl_work); - mdelay(1000); - sipa_free_cmn_fifo(ipa, SIPA_FIFO_PCIE_UL); - sipa_free_cmn_fifo(ipa, SIPA_FIFO_PCIE_DL); - if (!IS_ERR_OR_NULL(ipa->dentry)) - debugfs_remove_recursive(ipa->dentry); - devm_kfree(&pdev->dev, ipa); - platform_set_drvdata(pdev, NULL); - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipa_plat_drv_match[] = { - { .compatible = "sprd,virt-sipa"}, -}; -#endif - -static struct platform_driver sipa_plat_drv = { - .probe = sipa_plat_drv_probe, - .remove = sipa_plat_drv_remove, - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipa_plat_drv_match, -#endif - }, -}; - -#ifndef SPRD_PCIE_USE_DTS -static struct platform_device *sipa_plat_dev; -static int sipa_core_platform_device_reigster(struct device *dev) -{ - int retval = -ENOMEM; - - sipa_plat_dev = platform_device_alloc("virt_sipa", -1); - if (!sipa_plat_dev) - return retval; - - sipa_plat_dev->dev.dma_mask = dev->dma_mask; - sipa_plat_dev->dev.coherent_dma_mask = dev->coherent_dma_mask; - sipa_plat_dev->dev.archdata = dev->archdata; - dev_set_drvdata(&sipa_plat_dev->dev, dev); - retval = platform_device_add(sipa_plat_dev); - if (retval < 0) - platform_device_put(sipa_plat_dev); - - return retval; -} -#endif - -int sipa_module_init(struct device *dev) -{ -#ifndef SPRD_PCIE_USE_DTS - sipa_core_platform_device_reigster(dev); -#endif - return platform_driver_register(&sipa_plat_drv); -} -EXPORT_SYMBOL(sipa_module_init); - -void sipa_module_exit(void) -{ - platform_driver_unregister(&sipa_plat_drv); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(sipa_plat_dev); - #endif -} -EXPORT_SYMBOL(sipa_module_exit); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_core.h b/quectel_SRPD_PCIE/src/sipa/sipa_core.h deleted file mode 100644 index f67853b..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_core.h +++ /dev/null @@ -1,519 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _SIPA_CORE_H_ -#define _SIPA_CORE_H_ - -#include -#include -#include -#include -#include -#include -#include - -enum sipa_cmn_fifo_index { - SIPA_FIFO_PCIE_DL, - SIPA_FIFO_PCIE_UL, - SIPA_FIFO_MAX, -}; - -enum sipa_irq_evt_type { - SIPA_IRQ_TX_FIFO_THRESHOLD_SW = BIT(22), - SIPA_IRQ_EXIT_FLOW_CTRL = BIT(20), - SIPA_IRQ_ENTER_FLOW_CTRL = BIT(19), - SIPA_IRQ_TXFIFO_FULL_INT = BIT(18), - SIPA_IRQ_TXFIFO_OVERFLOW = BIT(17), - SIPA_IRQ_ERRORCODE_IN_TX_FIFO = BIT(16), - SIPA_IRQ_INTR_BIT = BIT(15), - SIPA_IRQ_THRESHOLD = BIT(14), - SIPA_IRQ_DELAY_TIMER = BIT(13), - SIPA_IRQ_DROP_PACKT_OCCUR = BIT(12), - - SIPA_IRQ_ERROR = 0x0, -}; - -#define SIPA_FIFO_THRESHOLD_IRQ_EN BIT(1) -#define SIPA_FIFO_DELAY_TIMER_IRQ_EN BIT(0) - -#define SIPA_PCIE_MEM_OFFSET 0x200000000ULL - -enum sipa_nic_status_e { - NIC_OPEN, - NIC_CLOSE -}; - -#define SIPA_RECV_EVT (SIPA_IRQ_INTR_BIT | SIPA_IRQ_THRESHOLD | \ - SIPA_IRQ_DELAY_TIMER | SIPA_IRQ_TX_FIFO_THRESHOLD_SW) - -#define SIPA_RECV_WARN_EVT (SIPA_IRQ_TXFIFO_FULL_INT | SIPA_IRQ_TXFIFO_OVERFLOW) - -#define SMSG_FLG_DELE_REQUEST 0x1 -#define SMSG_FLG_DELE_RELEASE 0x2 - -typedef void (*sipa_irq_notify_cb)(void *priv, - enum sipa_irq_evt_type evt, - u32 data); - -struct sipa_node_description_tag { - /*soft need to set*/ - u64 address : 40; - /*soft need to set*/ - u32 length : 20; - /*soft need to set*/ - u16 offset : 12; - /*soft need to set*/ - u8 net_id; - /*soft need to set*/ - u8 src : 5; - /*soft need to set*/ - u8 dst : 5; - u8 prio : 3; - u8 bear_id : 7; - /*soft need to set*/ - u8 intr : 1; - /*soft need to set*/ - u8 indx : 1; - u8 err_code : 4; - u32 reserved : 22; -} __attribute__((__packed__)); - -struct sipa_cmn_fifo_params { - u32 tx_intr_delay_us; - u32 tx_intr_threshold; - bool flowctrl_in_tx_full; - u32 flow_ctrl_cfg; - u32 flow_ctrl_irq_mode; - u32 tx_enter_flowctrl_watermark; - u32 tx_leave_flowctrl_watermark; - u32 rx_enter_flowctrl_watermark; - u32 rx_leave_flowctrl_watermark; - - u32 data_ptr_cnt; - u32 buf_size; - dma_addr_t data_ptr; -}; - -struct sipa_skb_dma_addr_node { - struct sk_buff *skb; - u64 dma_addr; - struct list_head list; -}; - -struct sipa_cmn_fifo_tag { - u32 depth; - u32 wr; - u32 rd; - - u32 fifo_base_addr_l; - u32 fifo_base_addr_h; - - void *virtual_addr; - dma_addr_t dma_ptr; -}; - -struct sipa_cmn_fifo_cfg_tag { - const char *fifo_name; - - void *priv; - - enum sipa_cmn_fifo_index fifo_id; - - bool state; - u32 dst; - u32 cur; - - void __iomem *fifo_reg_base; - - struct sipa_cmn_fifo_tag rx_fifo; - struct sipa_cmn_fifo_tag tx_fifo; - - u32 enter_flow_ctrl_cnt; - u32 exit_flow_ctrl_cnt; - - sipa_irq_notify_cb irq_cb; -}; - -struct sipa_endpoint { - /* Centered on CPU/PAM */ - struct sipa_cmn_fifo_cfg_tag *send_fifo; - struct sipa_cmn_fifo_cfg_tag *recv_fifo; - - struct sipa_cmn_fifo_params send_fifo_param; - struct sipa_cmn_fifo_params recv_fifo_param; - - bool inited; - bool connected; - bool suspended; -}; - -struct sipa_nic { - enum sipa_nic_id nic_id; - struct sipa_endpoint *send_ep; - struct sk_buff_head rx_skb_q; - int need_notify; - u32 src_mask; - int netid; - struct list_head list; - sipa_notify_cb cb; - void *cb_priv; - atomic_t status; - bool flow_ctrl_status; - bool continue_notify; - bool rm_flow_ctrl; -}; - -struct sipa_skb_array { - struct sipa_skb_dma_addr_node *array; - u32 rp; - u32 wp; - u32 depth; -}; - -struct sipa_skb_sender { - struct device *dev; - - struct sipa_endpoint *ep; - - atomic_t left_cnt; - /* To be used for add/remove nic device */ - spinlock_t nic_lock; - /* To be used for send skb process */ - spinlock_t send_lock; - spinlock_t exit_lock; - struct list_head nic_list; - struct list_head sending_list; - struct list_head pair_free_list; - struct sipa_skb_dma_addr_node *pair_cache; - - bool free_notify_net; - bool ep_cover_net; - bool send_notify_net; - - wait_queue_head_t free_waitq; - - struct task_struct *free_thread; - struct task_struct *send_thread; - - bool init_flag; - u32 no_mem_cnt; - u32 no_free_cnt; - u32 enter_flow_ctrl_cnt; - u32 exit_flow_ctrl_cnt; - u32 run; -}; - -struct sipa_skb_receiver { - struct sipa_endpoint *ep; - u32 rsvd; - struct sipa_skb_array recv_array; - wait_queue_head_t recv_waitq; - wait_queue_head_t fill_recv_waitq; - spinlock_t lock; - spinlock_t exit_lock; - u32 nic_cnt; - atomic_t need_fill_cnt; - struct sipa_nic *nic_array[SIPA_NIC_MAX]; - - struct task_struct *fill_thread; - - u32 tx_danger_cnt; - u32 rx_danger_cnt; - u32 run; -}; - -struct sipa_fifo_hal_ops { - int (*open)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, void *cookie); - int (*close)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - int (*set_rx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, u32 depth); - int (*set_tx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, u32 depth); - u32 (*get_rx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - int (*hal_set_tx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 depth); - u32 (*get_tx_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - int (*set_intr_drop_packet)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_error_code)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_timeout)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, sipa_irq_notify_cb cb); - int (*set_hw_intr_timeout)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, sipa_irq_notify_cb cb); - int (*set_intr_threshold)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, sipa_irq_notify_cb cb); - int (*set_hw_intr_thres)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, sipa_irq_notify_cb cb); - int (*set_src_dst_term)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 src, u32 dst); - int (*enable_local_flowctrl_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 enable, u32 irq_mode, - sipa_irq_notify_cb cb); - int (*enable_remote_flowctrl_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 work_mode, - u32 tx_entry_watermark, - u32 tx_exit_watermark, - u32 rx_entry_watermark, - u32 rx_exit_watermark); - int (*set_interrupt_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_txfifo_overflow)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*set_intr_txfifo_full)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb); - int (*put_node_to_rx_fifo)(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - struct sipa_node_description_tag *node, - u32 force_intr, u32 num); - u32 (*get_left_cnt)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*recv_node_from_tx_fifo)(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 num); - void (*get_rx_ptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd); - void (*get_tx_ptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd); - void (*get_filled_depth)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *rx_filled, u32 *tx_filled); - u32 (*get_tx_full_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*get_tx_empty_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*get_rx_full_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - u32 (*get_rx_empty_status)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); - bool (*set_rx_fifo_wptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr); - bool (*set_tx_fifo_wptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr); - int (*set_rx_tx_fifo_ptr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 rx_rd, u32 rx_wr, u32 tx_rd, u32 tx_wr); - int (*ctrl_receive)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool stop); - struct sipa_node_description_tag * - (*get_tx_fifo_rp)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index); - struct sipa_node_description_tag * - (*get_rx_fifo_wr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index); - int (*set_tx_fifo_rp)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 tx_rd); - int (*set_rx_fifo_wr)(struct device *dev, enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 num); - int (*set_intr_eb)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool eb, u32 type); - void (*clr_tout_th_intr)(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base); -}; - -struct sipa_core { - const char *name; - - struct device *dev; - struct device *pci_dev; - struct dentry *dentry; - struct sipa_endpoint ep; - - struct sipa_cmn_fifo_cfg_tag cmn_fifo_cfg[SIPA_FIFO_MAX]; - - struct work_struct flow_ctrl_work; - - /* ipa low power*/ - bool remote_ready; - - struct resource *reg_res; - phys_addr_t reg_mapped; - void __iomem *virt_reg_addr; - /* IPA NIC interface */ - struct sipa_nic *nic[SIPA_NIC_MAX]; - - /* sender & receiver */ - struct sipa_skb_sender *sender; - struct sipa_skb_receiver *receiver; - - atomic_t recv_cnt; - u64 pcie_mem_offset; - - struct sipa_fifo_hal_ops hal_ops; - - struct task_struct *smsg_thread; - - struct dentry *debugfs_root; - const void *debugfs_data; -}; - -void sipa_fifo_ops_init(struct sipa_fifo_hal_ops *ops); -struct sipa_core *sipa_get_ctrl_pointer(void); - -void sipa_receiver_add_nic(struct sipa_skb_receiver *receiver, - struct sipa_nic *nic); -void sipa_receiver_open_cmn_fifo(struct sipa_skb_receiver *receiver); - -void sipa_sender_open_cmn_fifo(struct sipa_skb_sender *sender); -int create_sipa_skb_sender(struct sipa_endpoint *ep, - struct sipa_skb_sender **sender_pp); -void destroy_sipa_skb_sender(struct sipa_skb_sender *sender); -void sipa_skb_sender_add_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic); -void sipa_skb_sender_remove_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic); -int sipa_skb_sender_send_data(struct sipa_skb_sender *sender, - struct sk_buff *skb, - enum sipa_term_type dst, - u8 netid); -int create_sipa_skb_receiver(struct sipa_endpoint *ep, - struct sipa_skb_receiver **receiver_pp); - -void sipa_nic_notify_evt(struct sipa_nic *nic, enum sipa_evt_type evt); -void sipa_nic_try_notify_recv(struct sipa_nic *nic); -void sipa_nic_push_skb(struct sipa_nic *nic, struct sk_buff *skb); -void sipa_nic_check_flow_ctrl(void); - -int sipa_create_smsg_channel(struct sipa_core *ipa); - -int sipa_init_debugfs(struct sipa_core *ipa); - -int sipa_int_callback_func(int evt, void *cookie); - -#if defined (__BIG_ENDIAN_BITFIELD) -static inline int sipa_get_node_desc(u8 *node_addr, - struct sipa_node_description_tag *node) -{ - if (!node_addr || !node) - return -EINVAL; - - node->address = node_addr[0] + ((u32)node_addr[1] << 8) + - ((u32)node_addr[2] << 16) + ((u32)node_addr[3] << 24) + - ((u64)node_addr[4] << 32); -#if 0 - node->length = node_addr[5] + ((u32)node_addr[6] << 8) + - ((u32)(node_addr[7] & 0xf) << 16); - node->offset = ((node_addr[7] & 0xf0) >> 4) + - ((u16)node_addr[8] << 4); -#endif - node->net_id = node_addr[9]; - node->src = node_addr[10] & 0x1f; -#if 0 - node->dst = ((node_addr[11] & 0x3) << 3) + - ((node_addr[10] & 0xe0) >> 5); -#endif - node->err_code = ((node_addr[12] & 0xc0) >> 6) + - ((node_addr[13] & 0x03) << 2); -#if 0 - node->prio = (node_addr[11] & 0x1c) >> 2; - node->bear_id = ((node_addr[11] & 0xe0) >> 5) + - ((node_addr[12] & 0xf) << 3); - node->intr = !!(node_addr[12] & BIT(4)); - node->indx = !!(node_addr[12] & BIT(5)); - node->reserved = ((node_addr[13] & 0xfc) >> 2) + - ((u32)node_addr[14] << 6) + ((u32)node_addr[15] << 14); -#endif - smp_rmb(); - - return 0; -} - -static inline int sipa_set_node_desc(u8 *dst_addr, u8 *src_addr) -{ - if (!dst_addr || !src_addr) - return -EINVAL; - - /* address */ - dst_addr[0] = src_addr[4]; - dst_addr[1] = src_addr[3]; - dst_addr[2] = src_addr[2]; - dst_addr[3] = src_addr[1]; - dst_addr[4] = src_addr[0]; - - /* length */ - dst_addr[5] = (src_addr[7] >> 4) + ((src_addr[6] & 0x0f) << 4); - dst_addr[6] = (src_addr[6] >> 4) + ((src_addr[5] & 0x0f) << 4); - dst_addr[7] = src_addr[5] >> 4; - - /* offset */ - dst_addr[7] += ((src_addr[8] & 0x0f) << 4); - dst_addr[8] = (src_addr[7] << 4) + (src_addr[8] >> 4); - - /* netid */ - dst_addr[9] = src_addr[9]; - - /* src */ - dst_addr[10] = ((src_addr[10] & 0xf8) >> 3); - - /* dst */ - dst_addr[10] += - ((src_addr[11] >> 6) + ((src_addr[10] & 0x01) << 2)) << 5; - dst_addr[11] = (src_addr[10] & 0x6) >> 1; - - /* prio */ - dst_addr[11] += ((src_addr[11] & 0x38) >> 1); - - /* bear_id */ - dst_addr[11] += ((src_addr[12] & 0x70) << 1); - dst_addr[12] = ((src_addr[11] & 0x7) << 1) + (src_addr[12] >> 7); - - /* intx */ - dst_addr[12] += ((src_addr[12] & 0x8) << 1); - - /* indx */ - dst_addr[12] += ((src_addr[12] & 0x4) << 3); - - /* err code */ - dst_addr[12] += (src_addr[13] & 0xc0); - dst_addr[13] = src_addr[12] & 0x3; - - /* reserved */ - dst_addr[13] += src_addr[15] << 2; - dst_addr[14] = (src_addr[15] & 0x3) + (src_addr[14] << 2); - dst_addr[15] = ((src_addr[13] & 0x3f) << 2) + - ((src_addr[14] & 0xc0) >> 6); - smp_wmb(); - - return 0; -} -#endif -#endif diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c b/quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c deleted file mode 100644 index 13dba60..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_debugfs.c +++ /dev/null @@ -1,590 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipa.h" -#include "sipa_core.h" - -static u32 debug_cmd[5], data_buf[5]; -static struct sipa_node_description_tag ipa_node; - -static int sipa_params_debug_show(struct seq_file *s, void *unused) -{ - int i; - u32 tmp; - struct sipa_core *ipa = (struct sipa_core *)s->private; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - seq_printf(s, "dma_mask = 0x%llx coherent_dma_mask = 0x%llx\n", - (u64)*ipa->pci_dev->dma_mask, (u64)ipa->pci_dev->coherent_dma_mask); - seq_printf(s, "remote ready = %d reg_mapped = 0x%llx virt_reg_addr = 0x%p\n", - ipa->remote_ready, (long long unsigned int)ipa->reg_mapped, ipa->virt_reg_addr); - seq_printf(s, "ipa reg start = 0x%llx size = 0x%llx pcie_mem_offset = %llx\n", - (long long unsigned int)ipa->reg_res->start, (long long unsigned int)resource_size(ipa->reg_res), - (long long unsigned int)ipa->pcie_mem_offset); - for (i = 0; i < SIPA_NIC_MAX; i++) { - if (!ipa->nic[i]) - continue; - - seq_printf(s, "open = %d src_mask = 0x%x netid = %d flow_ctrl_status = %d", - atomic_read(&ipa->nic[i]->status), ipa->nic[i]->src_mask, - ipa->nic[i]->netid, ipa->nic[i]->flow_ctrl_status); - seq_printf(s, " qlen = %d need_notify = %d continue_notify = %d\n", - ipa->nic[i]->rx_skb_q.qlen, ipa->nic[i]->need_notify, - ipa->nic[i]->continue_notify); - } - - seq_printf(s, "sender no_mem_cnt = %d no_free_cnt = %d left_cnt = %d\n", - ipa->sender->no_mem_cnt, ipa->sender->no_free_cnt, - atomic_read(&ipa->sender->left_cnt)); - seq_printf(s, "sender enter_flow_ctrl_cnt=%d, exit_flow_ctrl_cnt=%d, free_notify_net=%d, ep_cover_net=%d\n", - ipa->sender->enter_flow_ctrl_cnt, ipa->sender->exit_flow_ctrl_cnt, - ipa->sender->free_notify_net, ipa->sender->ep_cover_net); - seq_printf(s, "receiver need_fill_cnt = %d", - atomic_read(&ipa->receiver->need_fill_cnt)); - seq_printf(s, " tx_danger_cnt = %d rx_danger_cnt = %d\n", - ipa->receiver->tx_danger_cnt, ipa->receiver->rx_danger_cnt); - - fifo_cfg = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - seq_printf(s, "[PCIE_DL]state = %d fifo_reg_base = %p\n", - fifo_cfg->state, fifo_cfg->fifo_reg_base); - seq_printf(s, "[PCIE_DL]rx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->rx_fifo.depth, - fifo_cfg->rx_fifo.wr, - fifo_cfg->rx_fifo.rd); - seq_printf(s, "[PCIE_DL]rx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->rx_fifo.fifo_base_addr_l, - fifo_cfg->rx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_DL]rx fifo virt addr = %p\n", - fifo_cfg->rx_fifo.virtual_addr); - seq_printf(s, "[PCIE_DL]tx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->tx_fifo.depth, fifo_cfg->tx_fifo.wr, - fifo_cfg->tx_fifo.rd); - seq_printf(s, "[PCIE_DL]tx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->tx_fifo.fifo_base_addr_l, - fifo_cfg->tx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_DL]tx fifo virt addr = %p\n", - fifo_cfg->tx_fifo.virtual_addr); - fifo_cfg = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - seq_printf(s, "[PCIE_UL]state = %d fifo_reg_base = %p\n", - fifo_cfg->state, fifo_cfg->fifo_reg_base); - seq_printf(s, "[PCIE_UL]rx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->rx_fifo.depth, - fifo_cfg->rx_fifo.wr, - fifo_cfg->rx_fifo.rd); - seq_printf(s, "[PCIE_UL]rx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->rx_fifo.fifo_base_addr_l, - fifo_cfg->rx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_UL]rx fifo virt addr = %p\n", - fifo_cfg->rx_fifo.virtual_addr); - seq_printf(s, "[PCIE_UL]tx fifo depth = 0x%x wr = 0x%x rd = 0x%x\n", - fifo_cfg->tx_fifo.depth, fifo_cfg->tx_fifo.wr, - fifo_cfg->tx_fifo.rd); - seq_printf(s, "[PCIE_UL]tx_fifo fifo_addrl = 0x%x fifo_addrh = 0x%x\n", - fifo_cfg->tx_fifo.fifo_base_addr_l, - fifo_cfg->tx_fifo.fifo_base_addr_h); - seq_printf(s, "[PCIE_UL]tx fifo virt addr = %p\n", - fifo_cfg->tx_fifo.virtual_addr); - - //ep: IPA_COMMON_TX_FIFO_DEPTH 0x0Cl - tmp = readl_relaxed(ipa->virt_reg_addr + 0xc00 + 0x0C); - seq_printf(s, "neil: read IPA_COMMON_TX_FIFO_DEPTH, value = %x\n", (tmp >> 16)); - - //ep: IPA_COMMON_TX_FIFO_WR 0x10l - tmp = readl_relaxed(ipa->virt_reg_addr + 0xc00 + 0x10); - seq_printf(s, "neil: read IPA_COMMON_TX_FIFO_WR, value = %x\n", (tmp >> 16)); - - //ep: IPA_COMMON_TX_FIFO_RD 0x14l - tmp = readl_relaxed(ipa->virt_reg_addr + 0xc00 + 0x14); - seq_printf(s, "neil: read IPA_COMMON_TX_FIFO_RD, value = %x\n", (tmp >> 16)); - return 0; -} - -static int sipa_params_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_params_debug_show, - inode->i_private); -} - -static ssize_t sipa_endian_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - u32 debug_cmd[24], data_buf[24]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%x %x %x %x %x %x %x %x %x %x %x %x\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4], &debug_cmd[5], - &debug_cmd[6], &debug_cmd[7], &debug_cmd[8], - &debug_cmd[9], &debug_cmd[10], &debug_cmd[11]); - - ipa_node.address = debug_cmd[0]; - ipa_node.length = debug_cmd[1]; - ipa_node.offset = debug_cmd[2]; - ipa_node.net_id = debug_cmd[3]; - ipa_node.src = debug_cmd[4]; - ipa_node.dst = debug_cmd[5]; - ipa_node.prio = debug_cmd[6]; - ipa_node.bear_id = debug_cmd[7]; - ipa_node.intr = debug_cmd[8]; - ipa_node.indx = debug_cmd[9]; - ipa_node.err_code = debug_cmd[10]; - ipa_node.reserved = debug_cmd[11]; - - return size; -} - -static int sipa_endian_debug_show(struct seq_file *s, void *unused) -{ - int i; - u8 *byte; - - seq_printf(s, "address = 0x%llx length = 0x%x offset = 0x%x net_id = 0x%x\n", - (u64)ipa_node.address, ipa_node.length, ipa_node.offset, - ipa_node.net_id); - seq_printf(s, "src = 0x%x dst = 0x%x prio = 0x%x bear_id = 0x%x\n", - ipa_node.src, ipa_node.dst, ipa_node.prio, ipa_node.bear_id); - seq_printf(s, "intr = 0x%x indx = 0x%x err_code = 0x%x reserved = 0x%x\n", - ipa_node.intr, ipa_node.indx, - ipa_node.err_code, ipa_node.reserved); - - byte = (u8 *)&ipa_node; - for (i = 0; i < sizeof(ipa_node); i++) - seq_printf(s, "0x%x ", *(byte + i)); - - seq_puts(s, "\n"); - - return 0; -} - -static const struct file_operations sipa_params_fops = { - .open = sipa_params_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int sipa_endian_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_endian_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_endian_fops = { - .open = sipa_endian_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_endian_debug_write, -}; - -static ssize_t sipa_get_node_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - int i; - ssize_t len; - u8 debug_cmd[16], data_buf[128]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx %4hhx\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4], &debug_cmd[5], - &debug_cmd[6], &debug_cmd[7], &debug_cmd[8], - &debug_cmd[9], &debug_cmd[10], &debug_cmd[11], - &debug_cmd[12], &debug_cmd[13], &debug_cmd[14], - &debug_cmd[15]); - - for (i = 0; i < 16; i++) - pr_err("0x%x ", debug_cmd[i]); - pr_err("\n"); - -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc(debug_cmd, &ipa_node); -#else - ipa_node.address = debug_cmd[4] + ((u32)debug_cmd[3] << 8) + - ((u32)debug_cmd[2] << 16) + ((u32)debug_cmd[1] << 24) + - ((u64)debug_cmd[0] << 32); - ipa_node.net_id = debug_cmd[9]; - ipa_node.src = debug_cmd[10] & 0x1f; - ipa_node.err_code = ((debug_cmd[13] & 0xc0) >> 6) + - ((debug_cmd[12] & 0x03) << 2); -#endif - return size; -} - -static int sipa_get_node_debug_show(struct seq_file *s, void *unused) -{ - int i; - u8 *byte; - - seq_printf(s, "address = 0x%llx length = 0x%x offset = 0x%x net_id = 0x%x\n", - (u64)ipa_node.address, ipa_node.length, ipa_node.offset, - ipa_node.net_id); - seq_printf(s, "src = 0x%x dst = 0x%x prio = 0x%x bear_id = 0x%x\n", - ipa_node.src, ipa_node.dst, ipa_node.prio, ipa_node.bear_id); - seq_printf(s, "intr = 0x%x indx = 0x%x err_code = 0x%x reserved = 0x%x\n", - ipa_node.intr, ipa_node.indx, - ipa_node.err_code, ipa_node.reserved); - - byte = (u8 *)&ipa_node; - for (i = 0; i < sizeof(ipa_node); i++) - seq_printf(s, "0x%x ", *(byte + i)); - - seq_puts(s, "\n"); - - return 0; -} - -static int sipa_get_node_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_get_node_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_get_node_fops = { - .open = sipa_get_node_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_get_node_debug_write, -}; - -static ssize_t sipa_set_node_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - u32 debug_cmd[24], data_buf[24]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%x %x %x %x %x %x %x %x %x %x %x %x\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4], &debug_cmd[5], - &debug_cmd[6], &debug_cmd[7], &debug_cmd[8], - &debug_cmd[9], &debug_cmd[10], &debug_cmd[11]); - - ipa_node.address = debug_cmd[0]; - ipa_node.length = debug_cmd[1]; - ipa_node.offset = debug_cmd[2]; - ipa_node.net_id = debug_cmd[3]; - ipa_node.src = debug_cmd[4]; - ipa_node.dst = debug_cmd[5]; - ipa_node.prio = debug_cmd[6]; - ipa_node.bear_id = debug_cmd[7]; - ipa_node.intr = debug_cmd[8]; - ipa_node.indx = debug_cmd[9]; - ipa_node.err_code = debug_cmd[10]; - ipa_node.reserved = debug_cmd[11]; - - return size; -} - -static int sipa_set_node_debug_show(struct seq_file *s, void *unused) -{ -#if defined (__BIG_ENDIAN_BITFIELD) - int i; - u8 node_buf[16]; -#endif - - seq_printf(s, "address = 0x%llx length = 0x%x offset = 0x%x net_id = 0x%x\n", - (u64)ipa_node.address, ipa_node.length, ipa_node.offset, - ipa_node.net_id); - seq_printf(s, "src = 0x%x dst = 0x%x prio = 0x%x bear_id = 0x%x\n", - ipa_node.src, ipa_node.dst, ipa_node.prio, ipa_node.bear_id); - seq_printf(s, "intr = 0x%x indx = 0x%x err_code = 0x%x reserved = 0x%x\n", - ipa_node.intr, ipa_node.indx, - ipa_node.err_code, ipa_node.reserved); - -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_set_node_desc(node_buf, (u8 *)&ipa_node); - for (i = 0; i < sizeof(node_buf); i++) - seq_printf(s, "0x%x ", node_buf[i]); -#endif - - seq_puts(s, "\n"); - - return 0; -} - -static int sipa_set_node_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_set_node_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_set_node_fops = { - .open = sipa_set_node_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_set_node_debug_write, -}; - -static ssize_t sipa_reg_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - struct sipa_core *ipa = f->f_inode->i_private; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%x %x %x %x %x\n", - &debug_cmd[0], &debug_cmd[1], &debug_cmd[2], - &debug_cmd[3], &debug_cmd[4]); - if (debug_cmd[2]) - writel_relaxed(debug_cmd[1], ipa->virt_reg_addr + debug_cmd[0]); - - return size; -} - -static int sipa_reg_debug_show(struct seq_file *s, void *unused) -{ - u32 tx_filled, rx_filled; - u32 tx_wr, tx_rd, rx_wr, rx_rd; - struct sipa_core *ipa = (struct sipa_core *)s->private; - - seq_printf(s, "0x%x\n", - readl_relaxed(ipa->virt_reg_addr + debug_cmd[0])); - - seq_printf(s, "pcie dl tx fifo empty = %d full = %d rx fifo empty = %d full = %d\n", - ipa->hal_ops.get_tx_empty_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_tx_full_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_empty_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_full_status(SIPA_FIFO_PCIE_DL, - ipa->cmn_fifo_cfg)); - seq_printf(s, "pcie ul tx fifo empty = %d full = %d rx fifo empty = %d full = %d\n", - ipa->hal_ops.get_tx_empty_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_tx_full_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_empty_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg), - ipa->hal_ops.get_rx_full_status(SIPA_FIFO_PCIE_UL, - ipa->cmn_fifo_cfg)); - ipa->hal_ops.get_filled_depth(SIPA_FIFO_PCIE_DL, ipa->cmn_fifo_cfg, - &rx_filled, &tx_filled); - seq_printf(s, "pcie dl tx filled = 0x%x rx filled = 0x%x\n", - tx_filled, rx_filled); - ipa->hal_ops.get_filled_depth(SIPA_FIFO_PCIE_UL, ipa->cmn_fifo_cfg, - &rx_filled, &tx_filled); - seq_printf(s, "pcie ul tx filled = 0x%x rx filled = 0x%x\n", - tx_filled, rx_filled); - - ipa->hal_ops.get_rx_ptr(SIPA_FIFO_PCIE_UL, ipa->cmn_fifo_cfg, &rx_wr, &rx_rd); - ipa->hal_ops.get_tx_ptr(SIPA_FIFO_PCIE_UL, ipa->cmn_fifo_cfg, &tx_wr, &tx_rd); - seq_printf(s, "pcie ul rx_wr = 0x%x, rx_rd = 0x%x, tx_wr = 0x%x, tx_rd = 0x%x\n", - rx_wr, rx_rd, tx_wr, tx_rd); - - ipa->hal_ops.get_rx_ptr(SIPA_FIFO_PCIE_DL, ipa->cmn_fifo_cfg, &rx_wr, &rx_rd); - ipa->hal_ops.get_tx_ptr(SIPA_FIFO_PCIE_DL, ipa->cmn_fifo_cfg, &tx_wr, &tx_rd); - seq_printf(s, "pcie dl rx_wr = 0x%x, rx_rd = 0x%x, tx_wr = 0x%x, tx_rd = 0x%x\n", - rx_wr, rx_rd, tx_wr, tx_rd); - - sipa_int_callback_func(0, NULL); - - return 0; -} - -static int sipa_reg_debug_open(struct inode *inode, - struct file *file) -{ - return single_open(file, sipa_reg_debug_show, - inode->i_private); -} - -static const struct file_operations sipa_reg_debug_fops = { - .open = sipa_reg_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_reg_debug_write, -}; - -static int sipa_send_test_show(struct seq_file *s, void *unused) -{ - struct sk_buff *skb = NULL; - struct sipa_core *ipa = (struct sipa_core *)s->private; - - if (!skb) { - skb = __dev_alloc_skb(256, GFP_KERNEL | GFP_NOWAIT); - if (!skb) { - dev_err(ipa->dev, "failed to alloc skb!\n"); - return 0; - } - skb_put(skb, 128); - memset(skb->data, 0xE7, skb->len); - - sipa_skb_sender_send_data(ipa->sender, skb, 0x19, 0); - } - - return 0; -} - -static int sipa_send_test_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_send_test_show, inode->i_private); -} - -static const struct file_operations sipa_send_test_fops = { - .open = sipa_send_test_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static ssize_t sipa_nic_debug_write(struct file *f, const char __user *buf, - size_t size, loff_t *l) -{ - ssize_t len; - u8 debug_cmd[24], data_buf[24]; - - len = min(size, sizeof(data_buf) - 1); - if (copy_from_user((char *)data_buf, buf, len)) - return -EFAULT; - - len = sscanf((char *)data_buf, "%4hhx %4hhx\n", - &debug_cmd[0], &debug_cmd[1]); - if (debug_cmd[1]) - sipa_nic_open(debug_cmd[0], 0, NULL, NULL); - else - sipa_nic_close(debug_cmd[0]); - - return size; -} - -static int sipa_nic_debug_show(struct seq_file *s, void *unused) -{ - //struct sk_buff *skb = NULL; - struct sipa_core *ipa = (struct sipa_core *)s->private; - struct sipa_cmn_fifo_cfg_tag *pcie_dl = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]; - //struct sipa_cmn_fifo_cfg_tag *pcie_ul = &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]; - //struct sipa_cmn_fifo_tag *dl_tx_fifo = &pcie_dl->tx_fifo; - struct sipa_cmn_fifo_tag *dl_rx_fifo = &pcie_dl->rx_fifo; - //struct sipa_cmn_fifo_tag *ul_tx_fifo = &pcie_ul->tx_fifo; - //struct sipa_cmn_fifo_tag *ul_rx_fifo = &pcie_ul->rx_fifo; - struct sipa_node_description_tag *node; - int i = 0; - - pr_info("dl rx_fifo addr: 0x%lx wp-%d rp-%d\n", (long unsigned int)dl_rx_fifo->virtual_addr, - dl_rx_fifo->wr, dl_rx_fifo->rd); - node = (struct sipa_node_description_tag *)dl_rx_fifo->virtual_addr; - for (i = 0; i < dl_rx_fifo->depth; i++, node++) { - pr_info("node addr 0x%lx\n", (long unsigned int)node); - pr_info("node info i-%d, addr-0x%llx len-%u off-%u netid-%u src-%u dst-%u pro-%u bearid-%u intr-%u indx-%u err-%u resd-%u\n", - i, (long long unsigned int)node->address, node->length, node->offset, node->net_id, - node->src, node->dst, node->prio, node->bear_id, node->intr, - node->indx, node->err_code, node->reserved); - } - - - return 0; -} - -static int sipa_nic_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_nic_debug_show, inode->i_private); -} - -static const struct file_operations sipa_nic_debug_fops = { - .open = sipa_nic_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = sipa_nic_debug_write, -}; - -int sipa_init_debugfs(struct sipa_core *ipa) -{ - struct dentry *root; - struct dentry *file; - - root = debugfs_create_dir(dev_name(ipa->dev), NULL); - if (!root) { - dev_err(ipa->dev, "sipa create debugfs fail\n"); - return -ENOMEM; - } - - file = debugfs_create_file("params", 0444, root, ipa, - &sipa_params_fops); - if (!file) { - dev_err(ipa->dev, "sipa create params file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("endian", 0444, root, ipa, - &sipa_endian_fops); - if (!file) { - dev_err(ipa->dev, "sipa create endian file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("get_node", 0444, root, ipa, - &sipa_get_node_fops); - if (!file) { - dev_err(ipa->dev, "sipa create endian file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("set_node", 0444, root, ipa, - &sipa_set_node_fops); - if (!file) { - dev_err(ipa->dev, "sipa create set node file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("reg", 0444, root, ipa, - &sipa_reg_debug_fops); - if (!file) { - dev_err(ipa->dev, "sipa create reg debug file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("send_test", 0444, root, ipa, - &sipa_send_test_fops); - if (!file) { - dev_err(ipa->dev, "sipa create send_test debug file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - - file = debugfs_create_file("nic", 0444, root, ipa, - &sipa_nic_debug_fops); - if (!file) { - dev_err(ipa->dev, "sipa create nic debug file debugfs fail\n"); - debugfs_remove_recursive(root); - return -ENOMEM; - } - ipa->dentry = root; - - return 0; -} -EXPORT_SYMBOL(sipa_init_debugfs); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c b/quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c deleted file mode 100644 index e90895b..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_dele_cmn.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (C) 2018-2019 Unisoc Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipa.h" -#include "../include/sipc.h" -#include "../include/sprd_pcie_ep_device.h" -#include "sipa_core.h" - -#define SIPA_PCIE_DL_CMN_FIFO_REG_OFFSET 0x980 -#define SIPA_PCIE_UL_CMN_FIFO_REG_OFFSET 0x200 - -static int sipa_dele_start_req_work(void) -{ - struct smsg msg; - - msg.channel = SMSG_CH_COMM_SIPA; - msg.type = SMSG_TYPE_CMD; - msg.flag = SMSG_FLG_DELE_REQUEST; - msg.value = 0; - - return smsg_send(SIPC_ID_MINIAP, &msg, -1); -} - -static int sipa_init_cmn_fifo_reg_addr(struct sipa_core *ipa) -{ - ipa->reg_mapped = sprd_ep_ipa_map(PCIE_IPA_TYPE_REG, - ipa->reg_res->start, - resource_size(ipa->reg_res)); -#ifndef devm_ioremap_nocache -#define devm_ioremap_nocache devm_ioremap -#endif - ipa->virt_reg_addr = devm_ioremap_nocache(ipa->dev, - (resource_size_t)ipa->reg_mapped, - (resource_size_t)(resource_size(ipa->reg_res))); - if (!ipa->virt_reg_addr) { - dev_err(ipa->dev, "ipa reg base remap fail\n"); - return -ENOMEM; - } - - ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL].fifo_reg_base = - ipa->virt_reg_addr + SIPA_PCIE_DL_CMN_FIFO_REG_OFFSET; - ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL].fifo_reg_base = - ipa->virt_reg_addr + SIPA_PCIE_UL_CMN_FIFO_REG_OFFSET; - - return 0; -} - -static int conn_thread(void *data) -{ - struct smsg mrecv; - int ret, timeout = 500; - struct sipa_core *ipa = data; - - /* since the channel open may hang, we call it in the thread context */ - ret = smsg_ch_open(SIPC_ID_MINIAP, SMSG_CH_COMM_SIPA, -1); - if (ret != 0) { - dev_err(ipa->dev, "sipa_delegator failed to open dst %d channel %d\n", - SIPC_ID_MINIAP, SMSG_CH_COMM_SIPA); - /* assign NULL to thread poniter as failed to open channel */ - return ret; - } - - while (sipa_dele_start_req_work() && timeout--) - usleep_range(5000, 10000); - - /* start listen the smsg events */ - while (!kthread_should_stop()) { - /* monitor seblock recv smsg */ - smsg_set(&mrecv, SMSG_CH_COMM_SIPA, 0, 0, 0); - ret = smsg_recv(SIPC_ID_MINIAP, &mrecv, -1); - if (ret == -EIO || ret == -ENODEV) { - /* channel state is FREE */ - usleep_range(5000, 10000); - continue; - } - - dev_dbg(ipa->dev, "sipa type=%d, flag=0x%x, value=0x%08x\n", - mrecv.type, mrecv.flag, mrecv.value); - - switch (mrecv.type) { - case SMSG_TYPE_OPEN: - /* just ack open */ - smsg_open_ack(SIPC_ID_AP, SMSG_CH_COMM_SIPA); - break; - case SMSG_TYPE_CLOSE: - /* handle channel close */ - smsg_close_ack(SIPC_ID_AP, SMSG_CH_COMM_SIPA); - break; - case SMSG_TYPE_CMD: - /* handle commads */ - break; - case SMSG_TYPE_DONE: - sipa_init_cmn_fifo_reg_addr(ipa); - dev_info(ipa->dev, "remote ipa ready reg_mapped = 0x%llx\n", (long long unsigned int)ipa->reg_mapped); - sipa_receiver_open_cmn_fifo(ipa->receiver); - sipa_sender_open_cmn_fifo(ipa->sender); - sipa_nic_check_flow_ctrl(); - ipa->remote_ready = true; - /* handle cmd done */ - break; - case SMSG_TYPE_EVENT: - /* handle events */ - break; - default: - ret = 1; - break; - }; - - if (ret) { - dev_info(ipa->dev, "unknown msg in conn_thrd: %d, %d, %d\n", - mrecv.type, mrecv.flag, mrecv.value); - ret = 0; - } - } - - return ret; -} - -int sipa_create_smsg_channel(struct sipa_core *ipa) -{ - /* create channel thread for this seblock channel */ - ipa->smsg_thread = kthread_create(conn_thread, ipa, "sipa-dele"); - if (IS_ERR(ipa->smsg_thread)) { - dev_err(ipa->dev, "Failed to create monitor smsg kthread\n"); - return PTR_ERR(ipa->smsg_thread); - } - - wake_up_process(ipa->smsg_thread); - - return 0; -} -EXPORT_SYMBOL(sipa_create_smsg_channel); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_dummy.c b/quectel_SRPD_PCIE/src/sipa/sipa_dummy.c deleted file mode 100644 index 6d3c8f9..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_dummy.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (C) 2020 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "sipa_dummy: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sipa_eth.h" -#include "sipa_core.h" -#include "../include/sipa.h" - - -/* Device status */ -#define DEV_ON 1 -#define DEV_OFF 0 - -#define SIPA_DUMMY_NAPI_WEIGHT 64 - -extern struct sipa_eth_netid_device * dev_list[]; -static struct net_device *dummy_dev; -static struct dentry *dummy_root; -static int sipa_dummy_debugfs_mknod(void *data); - -#ifndef CONFIG_SPRD_ETHERNET -static int sipa_arp_reply(struct net_device *net, struct sk_buff *skb) { - struct arphdr *parp; - u8 *arpptr, *sha; - u8 sip[4], tip[4]; - struct sk_buff *reply = NULL; - - parp = arp_hdr(skb); - - if (parp->ar_hrd == htons(ARPHRD_ETHER) && parp->ar_pro == htons(ETH_P_IP) - && parp->ar_op == htons(ARPOP_REQUEST) && parp->ar_hln == 6 && parp->ar_pln == 4) { - arpptr = (u8 *)parp + sizeof(struct arphdr); - sha = arpptr; - arpptr += net->addr_len; /* sha */ - memcpy(sip, arpptr, sizeof(sip)); - arpptr += sizeof(sip); - arpptr += net->addr_len; /* tha */ - memcpy(tip, arpptr, sizeof(tip)); - - pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d\n", netdev_name(net), sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3]); - reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), skb->dev, *((__be32 *)tip), sha, net->dev_addr, sha); - if (reply) { - dev_queue_xmit(reply); - } - return 1; - } - - return 0; -} - -static void sipa_get_modem_mac(struct sk_buff *skb, struct SIPA_ETH *sipa_eth) -{ - struct ethhdr *ehdr; - struct iphdr *iph; - struct udphdr *udph; - struct sipa_eth_init_data *pdata = sipa_eth->pdata; - - ehdr = (struct ethhdr *)(skb->data - ETH_HLEN); - iph = ip_hdr(skb); - udph = (struct udphdr *)(skb->data + iph->ihl*4); - - if (ehdr->h_proto == htons(ETH_P_ARP)) { - sipa_arp_reply(skb->dev, skb); - return; - } - - //printk("%s skb=%p, h_proto=%x, protocol=%x, saddr=%x, daddr=%x dest=%x\n", __func__, skb, ehdr->h_proto, iph->protocol, iph->saddr, iph->daddr, udph->dest); - if (ehdr->h_proto == htons(ETH_P_IP) && iph->protocol == IPPROTO_UDP && iph->saddr != 0x00000000 && iph->daddr == 0xFFFFFFFF) { - if (udph->dest == htons(68)) //DHCP offer/ACK - { - memcpy(pdata->modem_mac, ehdr->h_source, ETH_ALEN); - pr_info("Modem Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", - pdata->modem_mac[0], pdata->modem_mac[1], pdata->modem_mac[2], pdata->modem_mac[3], pdata->modem_mac[4], pdata->modem_mac[5]); - } - } -} -#endif - -/* Term type 0x6 means we are in direct mode, currently. - * we will recv pkt with a dummy mac header, which will - * cause us fail to get skb->pkt_type and skb->protocol. - */ -static void sipa_dummy_prepare_skb(struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ipv6h; - struct net_device *dev; - unsigned int real_len = 0, payload_len = 0; - bool ip_arp = true; - - dev = skb->dev; - - skb->protocol = eth_type_trans(skb, dev); - skb_reset_network_header(skb); - - switch (ntohs(skb->protocol)) { - case ETH_P_IP: - iph = ip_hdr(skb); - real_len = ntohs(iph->tot_len); - break; - case ETH_P_IPV6: - ipv6h = ipv6_hdr(skb); - payload_len = ntohs(ipv6h->payload_len); - real_len = payload_len + sizeof(struct ipv6hdr); - break; - case ETH_P_ARP: - real_len = arp_hdr_len(dev); - break; - default: - ip_arp = false; - break; - } - - if (ip_arp) - skb_trim(skb, real_len); - - /* TODO chechsum ... */ - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_HOST; -} - -/* Term type 0x6 means we are in direct mode, currently. - * we will recv pkt with a dummy mac header, which will - * cause us fail to get skb->pkt_type and skb->protocol. - */ -static void sipa_dummy_direct_mode_prepare_skb(struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ipv6h; - unsigned int real_len = 0, payload_len = 0; - - skb_pull_inline(skb, ETH_HLEN); - skb_reset_network_header(skb); - iph = ip_hdr(skb); - if (iph->version == 4) { - skb->protocol = htons(ETH_P_IP); - iph = ip_hdr(skb); - real_len = ntohs(iph->tot_len); - skb_trim(skb, real_len); - } else if(iph->version == 6){ - skb->protocol = htons(ETH_P_IPV6); - ipv6h = ipv6_hdr(skb); - payload_len = ntohs(ipv6h->payload_len); - real_len = payload_len + sizeof(struct ipv6hdr); - skb_trim(skb, real_len); - } else { - pr_err("unrecognized ip version %d\n", iph->version); - } - - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_HOST; -} - -static int sipa_dummy_rx(struct SIPA_DUMMY *sipa_dummy, int budget) -{ - struct sk_buff *skb; - struct sipa_eth_netid_device *netid_dev_info; - struct SIPA_ETH *sipa_eth; - int real_netid = 0; - int skb_cnt = 0; - int ret; - - if (!sipa_dummy) { - pr_err("no sipa_dummy device\n"); - return -EINVAL; - } - - atomic_set(&sipa_dummy->rx_evt, 0); - while (skb_cnt < budget) { - ret = sipa_nic_rx(&real_netid, &skb, skb_cnt); - - if (ret) { - switch (ret) { - case -ENODEV: - pr_err("sipa fail to find dev\n"); - sipa_dummy->stats.rx_errors++; - sipa_dummy->netdev->stats.rx_errors++; - break; - case -ENODATA: - pr_err("sipa no data\n"); - atomic_set(&sipa_dummy->rx_busy, 0); - break; - } - break; - } - - skb_cnt++; - sipa_dummy->stats.rx_packets++; - sipa_dummy->stats.rx_bytes += skb->len; - if (real_netid < 0) { - pr_err("sipa invaild netid"); - break; - } - /* - * We should determine the real device before we do eth_types_tran, - */ - if (real_netid < 0 || real_netid >= SIPA_DUMMY_IFACE_NUM) { - pr_err("illegal real_netid %d\n", real_netid); - dev_kfree_skb_any(skb); - break; - } - netid_dev_info = dev_list[real_netid]; - if (!netid_dev_info || netid_dev_info->state == DEV_OFF) { - pr_info("netid= %d net is not DEV_ON\n", real_netid); - dev_kfree_skb_any(skb); - break; - } - - skb->dev = netid_dev_info->ndev; - sipa_eth = netdev_priv(skb->dev); - sipa_eth->stats.rx_packets++; - sipa_eth->stats.rx_bytes += skb->len; - if (sipa_eth->pdata->term_type == 0x6) { - sipa_dummy_direct_mode_prepare_skb(skb); - } else { - sipa_dummy_prepare_skb(skb); -#ifndef CONFIG_SPRD_ETHERNET - sipa_get_modem_mac(skb, sipa_eth); -#endif - } - napi_gro_receive(&sipa_dummy->napi, skb); - } - - return skb_cnt; -} - -static int sipa_dummy_rx_poll_handler(struct napi_struct *napi, int budget) -{ - int pkts = 0, num, tmp = 0; - - struct SIPA_DUMMY *sipa_dummy = container_of(napi, struct SIPA_DUMMY, napi); - -READ_AGAIN: - num = sipa_nic_get_filled_num(); - if (!num) - goto check; - if (num > budget) - num = budget; - - pkts = sipa_dummy_rx(sipa_dummy, num); - if (pkts > 0) - sipa_nic_set_tx_fifo_rp(pkts); - tmp += pkts; - - budget -= pkts; - if (!budget) - goto out; - -check: - if (!sipa_check_recv_tx_fifo_empty() || - atomic_read(&sipa_dummy->rx_evt)) { - atomic_set(&sipa_dummy->rx_evt, 0); - goto READ_AGAIN; - } - - atomic_set(&sipa_dummy->rx_busy, 0); - napi_complete(napi); - sipa_nic_restore_irq(); - if (atomic_read(&sipa_dummy->rx_evt) || - atomic_read(&sipa_dummy->rx_busy) || - !sipa_check_recv_tx_fifo_empty()) { - atomic_set(&sipa_dummy->rx_evt, 0); - napi_schedule(&sipa_dummy->napi); - } - -out: - return tmp; -} - -static void sipa_dummy_rx_handler (void *priv) -{ - struct SIPA_DUMMY *sipa_dummy = (struct SIPA_DUMMY *)priv; - - if (!sipa_dummy) { - pr_err("data is NULL\n"); - return; - } - - if (!atomic_cmpxchg(&sipa_dummy->rx_busy, 0, 1)) { - atomic_set(&sipa_dummy->rx_evt, 0); - napi_schedule(&sipa_dummy->napi); - } -} - -/* for sipa to invoke */ -void sipa_dummy_recv_trigger(void) -{ - struct SIPA_DUMMY *sipa_dummy; - - if (!dummy_dev) - return; - - sipa_dummy = netdev_priv(dummy_dev); - - atomic_set(&sipa_dummy->rx_evt, 1); - sipa_dummy_rx_handler(sipa_dummy); -} - -static int sipa_dummy_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - - /* update netdev statistics */ - sipa_dummy->stats.tx_packets++; - sipa_dummy->stats.tx_bytes += skb->len; - - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -/* Open interface */ -static int sipa_dummy_open(struct net_device *dev) -{ - struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - return -EINVAL; - } - - if(!ctrl->remote_ready) - return -EINVAL; - - pr_info("dummy open\n"); - if (!netif_carrier_ok(sipa_dummy->netdev)) { - netif_carrier_on(sipa_dummy->netdev); - } - - netif_start_queue(dev); - //napi_enable(&sipa_dummy->napi); - - napi_schedule(&sipa_dummy->napi); - return 0; -} - -/* Close interface */ -static int sipa_dummy_close(struct net_device *dev) -{ - //struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - pr_info("close dummy!\n"); - - //napi_disable(&sipa_dummy->napi); - netif_stop_queue(dev); - netif_carrier_off(dev); - - return 0; -} - -static struct net_device_stats *sipa_dummy_get_stats(struct net_device *dev) -{ - struct SIPA_DUMMY *sipa_dummy = netdev_priv(dev); - - return &sipa_dummy->stats; -} - -static const struct net_device_ops sipa_dummy_ops = { - .ndo_open = sipa_dummy_open, - .ndo_stop = sipa_dummy_close, - .ndo_start_xmit = sipa_dummy_start_xmit, - .ndo_get_stats = sipa_dummy_get_stats, -}; - -static void s_setup(struct net_device *dev) -{ - ether_setup(dev); -} - -static int sipa_dummy_probe(struct platform_device *pdev) -{ - struct SIPA_DUMMY *sipa_dummy; - struct net_device *netdev; - int ret; - -#ifdef NET_NAME_PREDICTABLE - netdev = alloc_netdev( - sizeof(struct SIPA_DUMMY), - "sipa_dummy0", - NET_NAME_PREDICTABLE, - s_setup); -#else - netdev = alloc_netdev( - sizeof(struct SIPA_DUMMY), - "sipa_dummy0", - s_setup); -#endif - - if (!netdev) { - pr_err("alloc_netdev() failed.\n"); - return -ENOMEM; - } - - dummy_dev = netdev; - netdev->type = ARPHRD_ETHER; - sipa_dummy = netdev_priv(netdev); - sipa_dummy->netdev = netdev; - netdev->netdev_ops = &sipa_dummy_ops; - netdev->watchdog_timeo = 1 * HZ; - netdev->irq = 0; - netdev->dma = 0; - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM); - random_ether_addr(netdev->dev_addr); - - netif_napi_add(netdev, - &sipa_dummy->napi, - sipa_dummy_rx_poll_handler, - SIPA_DUMMY_NAPI_WEIGHT); - - /* Register new Ethernet interface */ - ret = register_netdev(netdev); - if (ret) { - pr_err("register_netdev() failed (%d)\n", ret); - netif_napi_del(&sipa_dummy->napi); - free_netdev(netdev); - return ret; - } - - /* Set link as disconnected */ - netif_carrier_off(netdev); - platform_set_drvdata(pdev, sipa_dummy); - sipa_dummy_debugfs_mknod((void *)sipa_dummy); - napi_enable(&sipa_dummy->napi); - return 0; -} - -/* Cleanup Ethernet device driver. */ -static int sipa_dummy_remove(struct platform_device *pdev) -{ - struct SIPA_DUMMY *sipa_dummy= platform_get_drvdata(pdev); - netif_stop_queue(sipa_dummy->netdev); - napi_disable(&sipa_dummy->napi); - netif_napi_del(&sipa_dummy->napi); - unregister_netdev(sipa_dummy->netdev); - free_netdev(sipa_dummy->netdev); - platform_set_drvdata(pdev, NULL); - if (!IS_ERR_OR_NULL(dummy_root)) - debugfs_remove_recursive(dummy_root); - - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipa_dummy_match_table[] = { - { .compatible = "sprd,sipa_dummy"}, - { } -}; -#endif - -static struct platform_driver sipa_dummy_driver = { - .probe = sipa_dummy_probe, - .remove = sipa_dummy_remove, - .driver = { - .owner = THIS_MODULE, - .name = "sipa_dummy", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipa_dummy_match_table -#endif - } -}; - -#ifndef SPRD_PCIE_USE_DTS -static struct platform_device *sipa_dummy_device; - -static int sipa_dummy_platform_device_reigster(void) -{ - int retval = -ENOMEM; - - sipa_dummy_device = platform_device_alloc("sipa_dummy", -1); - if (!sipa_dummy_device) - return retval; - - retval = platform_device_add(sipa_dummy_device); - if (retval < 0) - platform_device_put(sipa_dummy_device); - - return retval; -} -#endif - - -static int sipa_dummy_debug_show(struct seq_file *m, void *v) -{ - struct SIPA_DUMMY *sipa_dummy = (struct SIPA_DUMMY *)(m->private); - - if (!sipa_dummy) { - pr_err("invalid data, sipa_dummy is NULL\n"); - return -EINVAL; - } - - seq_puts(m, "*************************************************\n"); - seq_printf(m, "DEVICE: %s rx_busy=%d rx_evt=%d\n", - sipa_dummy->netdev->name, atomic_read(&sipa_dummy->rx_busy), - atomic_read(&sipa_dummy->rx_evt)); - seq_puts(m, "*************************************************\n"); - - return 0; -} - -static int sipa_dummy_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_dummy_debug_show, inode->i_private); -} - -static const struct file_operations sipa_dummy_debug_fops = { - .open = sipa_dummy_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int sipa_dummy_debugfs_mknod(void *data) -{ - if (!dummy_root) { - pr_err("dummy dir is NULL\n"); - return -ENXIO; - } - debugfs_create_file("stats", - 0444, - dummy_root, - data, - &sipa_dummy_debug_fops); - - return 0; -} - -static void __init sipa_dummy_debugfs_init(void) -{ - dummy_root = debugfs_create_dir("sipa_dummy", NULL); - if (!dummy_root) - pr_err("failed to create sipa_dummy debugfs dir\n"); -} - -int sipa_dummy_init(void) -{ - sipa_dummy_debugfs_init(); -#ifndef SPRD_PCIE_USE_DTS - sipa_dummy_platform_device_reigster(); -#endif - return platform_driver_register(&sipa_dummy_driver); -} -EXPORT_SYMBOL(sipa_dummy_init); - -void sipa_dummy_exit(void) -{ - platform_driver_unregister(&sipa_dummy_driver); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(sipa_dummy_device); -#endif -} -EXPORT_SYMBOL(sipa_dummy_exit); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_eth.c b/quectel_SRPD_PCIE/src/sipa/sipa_eth.c deleted file mode 100644 index c790725..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_eth.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define pr_fmt(fmt) "sipa_eth: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sipa_eth.h" -#include "../include/sipa.h" - -#ifndef ARPHRD_RAWIP -#define ARPHRD_RAWIP ARPHRD_NONE -#endif - -#ifdef CONFIG_PINCTRL_IPQ807x -//#define CONFIG_QCA_NSS_DRV -#endif - -#if 1//def CONFIG_QCA_NSS_DRV -#define _RMNET_NSS_H_ -#define _RMENT_NSS_H_ -struct rmnet_nss_cb { - int (*nss_create)(struct net_device *dev); - int (*nss_free)(struct net_device *dev); - int (*nss_tx)(struct sk_buff *skb); -}; -static struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; -#ifdef CONFIG_QCA_NSS_DRV -static uint __read_mostly qca_nss_enabled = 1; -module_param( qca_nss_enabled, uint, S_IRUGO); -#define rmnet_nss_dereference(nss_cb) do { \ - rcu_read_lock(); \ - nss_cb = rcu_dereference(rmnet_nss_callbacks); \ - rcu_read_unlock(); \ -} while(0) -#else -#define rmnet_nss_dereference(nss_cb) do { nss_cb = NULL; } while(0) -#endif -#endif - -/* Device status */ -#define DEV_ON 1 -#define DEV_OFF 0 - -#define SIPA_ETH_NAPI_WEIGHT 64 -#define SIPA_ETH_IFACE_PREF "seth" -#define SIPA_ETH_VPCIE_PREF "pcie" -#define SIPA_ETH_VPCIE_IDX 8 - -#define SIPA_DUMMY_IFACE_NUM 4 - -static struct dentry *root; -static int sipa_eth_debugfs_mknod(void *root, void *data); -static void sipa_eth_poll_rx_handler (void *priv); -static u64 gro_enable; - -struct sipa_eth_netid_device * dev_list[SIPA_DUMMY_IFACE_NUM]; - - -static const unsigned char dhcp_dst_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -//static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3}; -//static const u8 default_dev_addr[ETH_ALEN] = {0x02, 0x50, 0xf4}; - -static inline void sipa_eth_dt_stats_init(struct sipa_eth_dtrans_stats *stats) -{ - memset(stats, 0, sizeof(*stats)); -} - -static inline void sipa_eth_rx_stats_update( - struct sipa_eth_dtrans_stats *stats, u32 len) -{ - stats->rx_sum += len; - stats->rx_cnt++; -} - -static inline void sipa_eth_tx_stats_update( - struct sipa_eth_dtrans_stats *stats, u32 len) -{ - stats->tx_sum += len; - stats->tx_cnt++; -} - -static void sipa_eth_prepare_skb(struct SIPA_ETH *sipa_eth, struct sk_buff *skb) -{ - struct iphdr *iph; - struct ipv6hdr *ipv6h; - struct net_device *dev; - unsigned int real_len = 0, payload_len = 0; - bool ip_arp = true; - - dev = sipa_eth->netdev; - - skb->protocol = eth_type_trans(skb, dev); - skb_reset_network_header(skb); - - switch (ntohs(skb->protocol)) { - case ETH_P_IP: - iph = ip_hdr(skb); - real_len = ntohs(iph->tot_len); - break; - case ETH_P_IPV6: - ipv6h = ipv6_hdr(skb); - payload_len = ntohs(ipv6h->payload_len); - real_len = payload_len + sizeof(struct ipv6hdr); - break; - case ETH_P_ARP: - real_len = arp_hdr_len(dev); - break; - default: - ip_arp = false; - break; - } - - if (ip_arp) - skb_trim(skb, real_len); - - /* TODO chechsum ... */ - skb->ip_summed = CHECKSUM_NONE; - skb->dev = dev; -} - -static int sipa_eth_rx(struct SIPA_ETH *sipa_eth, int budget) -{ - struct sk_buff *skb; - struct net_device *dev; - struct sipa_eth_dtrans_stats *dt_stats; - int netid; - int skb_cnt = 0; - int ret; - - dt_stats = &sipa_eth->dt_stats; - - if (!sipa_eth) { - pr_err("no sipa_eth device\n"); - return -EINVAL; - } - - dev = sipa_eth->netdev; - atomic_set(&sipa_eth->rx_evt, 0); - while (skb_cnt < budget) { - ret = sipa_nic_rx(&netid, &skb, skb_cnt); - if (ret) { - switch (ret) { - case -ENODEV: - pr_err("fail to find dev"); - sipa_eth->stats.rx_errors++; - dt_stats->rx_fail++; - dev->stats.rx_errors++; - break; - case -ENODATA: - atomic_set(&sipa_eth->rx_busy, 0); - break; - } - break; - } - - if (!skb) { - pr_err("recv skb is null\n"); - return -EINVAL; - } - - sipa_eth_prepare_skb(sipa_eth, skb); - - sipa_eth->stats.rx_packets++; - sipa_eth->stats.rx_bytes += skb->len; - sipa_eth_rx_stats_update(dt_stats, skb->len); - napi_gro_receive(&sipa_eth->napi, skb); - //netif_receive_skb(skb); - skb_cnt++; - } - - return skb_cnt; -} - -static int sipa_eth_rx_poll_handler(struct napi_struct *napi, int budget) -{ - struct SIPA_ETH *sipa_eth = container_of(napi, struct SIPA_ETH, napi); - int tmp = 0, pkts; - - /* If the number of pkt is more than weight(64), - * we cannot read them all with a single poll. - * When the return value of poll func equals to weight(64), - * napi structure invokes the poll func one more time by - * __raise_softirq_irqoff.(See napi_poll for details) - * So do not do napi_complete in that case. - */ -READ_AGAIN: - /* For example: - * pkts = 60, tmp = 60, budget = 4 - * if rx_evt is true, we goto READ_AGAIN, - * pkts = 4, tmp = 64, budget = 0, - * then we goto out, return 64 to napi, - * In that case, we force napi to do polling again. - */ - pkts = sipa_eth_rx(sipa_eth, budget); - tmp += pkts; - budget -= pkts; - /* - * If budget is 0 here, means we has not finished reading yet, - * so we should return a weight-number(64) to napi to ask it - * do another polling. - */ - if (!budget) - goto out; - - /* Due to a cuncurrency issue, we have to do napi_complete - * cautiously. If a socket is in the process of napi polling, - * a SIPA_RECEIVE is arriving to trigger another socket to do receiving, - * we must record it because it will be blocked by rx_busy - * at the first beginning. - * Since this SIPA_RECEIVE notification is a one-shot behaviour - * in sipa_nic. if we chose to ignore this event, we may lose - * the chance to receive forever. - */ - if (atomic_read(&sipa_eth->rx_evt)) - goto READ_AGAIN; - - /* If the number of budget is more than 0, it means the pkts - * we received is smaller than napi weight(64). - * Then we are okay to do napi_complete. - */ - if (budget) { - napi_complete(napi); - /* Test in a lab, ten threads of TCP streams, - * TPUT reaches to 1Gbps, another edge case occurs, - * rx_busy might be 0, and rx_evt might be 1, - * after we do napi_complete. - * So do rx_handler manually to prevent - * sipa_eth from stopping receiving pkts. - */ - if (atomic_read(&sipa_eth->rx_evt) || - atomic_read(&sipa_eth->rx_busy)) { - pr_debug("rx evt recv after napi complete"); - atomic_set(&sipa_eth->rx_evt, 0); - napi_schedule(&sipa_eth->napi); - } - } - -out: - return tmp; -} - -/* Attention, The whole RX is deprecated, we use sipa_dummy to rx. */ -static void sipa_eth_poll_rx_handler (void *priv) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)priv; - - if (!sipa_eth) { - pr_err("data is NULL\n"); - return; - } - - if (!atomic_cmpxchg(&sipa_eth->rx_busy, 0, 1)) { - atomic_set(&sipa_eth->rx_evt, 0); - napi_schedule(&sipa_eth->napi); - /* Trigger a NET_RX_SOFTIRQ softirq directly, - * or there will be a delay - */ - //raise_softirq(NET_RX_SOFTIRQ); - } -} - -static void sipa_eth_flowctrl_handler(void *priv, int flowctrl) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)priv; - struct net_device *dev = sipa_eth->netdev; - - if (flowctrl) { - netif_stop_queue(dev); - } else if (netif_queue_stopped(dev)) { - netif_wake_queue(dev); - } -} - -static void sipa_eth_notify_cb(void *priv, enum sipa_evt_type evt, - unsigned int data) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)priv; - - switch (evt) { - case SIPA_RECEIVE: - atomic_set(&sipa_eth->rx_evt, 1); - sipa_eth_poll_rx_handler(priv); - break; - case SIPA_LEAVE_FLOWCTRL: - pr_info("SIPA LEAVE FLOWCTRL\n"); - sipa_eth_flowctrl_handler(priv, 0); - break; - case SIPA_ENTER_FLOWCTRL: - pr_info("SIPA ENTER FLOWCTRL\n"); - sipa_eth_flowctrl_handler(priv, 1); - break; - default: - break; - } -} - -static int sipa_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - struct sipa_eth_init_data *pdata = sipa_eth->pdata; - struct sipa_eth_dtrans_stats *dt_stats; - int ret = 0, dhcp = 0; - int netid; - - dt_stats = &sipa_eth->dt_stats; - if (sipa_eth->state != DEV_ON) { - pr_err("called when %s is down\n", dev->name); - dt_stats->tx_fail++; - netif_carrier_off(dev); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - netid = pdata->netid; - - - if (dev->type != ARPHRD_ETHER) { - switch (skb->data[0] & 0xf0) { - case 0x40: - { - struct iphdr *ip4h = (struct iphdr *)(&skb->data[0]); - if (ip4h->protocol == IPPROTO_UDP && ip4h->saddr == 0x00000000 && ip4h->daddr == 0xFFFFFFFF) { - dhcp = 1; - } - skb->protocol = htons(ETH_P_IP); - } - break; - case 0x60: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - if(skb->protocol != htons(ETH_P_ARP)) { - pr_err("unknow skb->protocol %02x\n", skb->data[0]); - goto err; - } - skb->protocol = htons(ETH_P_ARP); - arp_hdr(skb)->ar_hrd = htons(ARPHRD_ETHER); - break; - - } - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - - memcpy(eth_hdr(skb)->h_source, dev->dev_addr, ETH_ALEN); - if(dhcp) - memcpy(eth_hdr(skb)->h_dest, dhcp_dst_addr, ETH_ALEN); - else - memcpy(eth_hdr(skb)->h_dest, pdata->modem_mac, ETH_ALEN); - eth_hdr(skb)->h_proto = skb->protocol; - } - - ret = sipa_nic_tx(sipa_eth->nic_id, pdata->term_type, netid, skb); - if (unlikely(ret != 0)) { - if (ret == -EAGAIN) { - /* - * resume skb, otherwise - * we may pull this skb ETH_HLEN-bytes twice - */ - if (!pdata->mac_h) - skb_push(skb, ETH_HLEN); - dt_stats->tx_fail++; - sipa_eth->stats.tx_errors++; - /* - if (ret == -EAGAIN) { - netif_stop_queue(dev); - sipa_nic_trigger_flow_ctrl_work(sipa_eth->nic_id, ret); - } - */ - return NETDEV_TX_BUSY; - } - pr_err("fail to send skb, dev 0x%p eth 0x%p nic_id %d, ret %d\n", - dev, sipa_eth, sipa_eth->nic_id, ret); - goto err; - } - - /* update netdev statistics */ - sipa_eth->stats.tx_packets++; - sipa_eth->stats.tx_bytes += skb->len; - sipa_eth_tx_stats_update(dt_stats, skb->len); - - return NETDEV_TX_OK; - -err: - sipa_eth->netdev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static int sipa_eth_change_dev_list_state(struct SIPA_ETH *sipa_eth, int state) { - struct sipa_eth_netid_device *netid_dev_info; - int netid = sipa_eth->pdata->netid; - - if (strncmp(sipa_eth->netdev->name, - SIPA_ETH_VPCIE_PREF, - strlen(SIPA_ETH_VPCIE_PREF))) - return 0; - - if (netid < 0 || netid >= SIPA_DUMMY_IFACE_NUM) { - pr_info("illegal netid %d\n", netid); - return -EINVAL; - } - - netid_dev_info = dev_list[netid]; - netid_dev_info->state = state; - - pr_info("set %s netid %d %s for dummy\n", - sipa_eth->netdev->name, netid, state ? "DEV_ON" : "DEV_OFF"); - return 0; -} - -/* Open interface */ -static int sipa_eth_open(struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - struct sipa_eth_init_data *pdata = sipa_eth->pdata; - int ret = 0; - - pr_info("dev 0x%p eth 0x%p open %s netid %d term %d mac_h %d\n", - dev, sipa_eth, dev->name, pdata->netid, pdata->term_type, - pdata->mac_h); - ret = sipa_nic_open( - pdata->term_type, - pdata->netid, - sipa_eth_notify_cb, - (void *)sipa_eth); - - if (ret < 0) - return -EINVAL; - - sipa_eth->nic_id = ret; - sipa_eth->state = DEV_ON; - sipa_eth_dt_stats_init(&sipa_eth->dt_stats); - memset(&sipa_eth->stats, 0, sizeof(sipa_eth->stats)); - - if (!netif_carrier_ok(sipa_eth->netdev)) { - pr_info("set netif_carrier_on\n"); - netif_carrier_on(sipa_eth->netdev); - } - - atomic_set(&sipa_eth->rx_busy, 0); - sipa_eth_change_dev_list_state(sipa_eth, DEV_ON); - netif_start_queue(dev); - napi_enable(&sipa_eth->napi); - - return 0; -} - -/* Close interface */ -static int sipa_eth_close(struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - pr_info("close %s!\n", dev->name); - - sipa_nic_close(sipa_eth->nic_id); - sipa_eth->state = DEV_OFF; - - napi_disable(&sipa_eth->napi); - netif_stop_queue(dev); - - sipa_eth_change_dev_list_state(sipa_eth, DEV_OFF); - return 0; -} - -static struct net_device_stats *sipa_eth_get_stats(struct net_device *dev) -{ - struct SIPA_ETH *sipa_eth = netdev_priv(dev); - - return &sipa_eth->stats; -} - -/* - * For example, if an application starts a tcp connection, - * it finally invokes tcp_connect func to send out a TCP SYN. - * In a func tcp_init_nondata_skb, the skb->ip_summed is set - * to CHECKSUM_PARTIAL. Because only the pesuode header is - * calculated and stored. It expects that the netdevice - * to calculate the checksum for TCP header&TCP paylod and store - * the final checksum into tcphdr->check. - * Then __dev_queue_xmit -> validate_xmit_skb, it check the features - * of this current network card, if it with - * NETIF_F_IP_CSUM/NETIF_F_IPV6_CSUM/NETIF_F_HW_CSUM, - * skb_checksum_help func will be invoked for this calculation. - * - * So we have to implement ndo_features_check func, since we - * have any ability to calculate a checksum for a pkt. - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) -netdev_features_t sipa_eth_features_check(struct sk_buff *skb, struct net_device *dev, - netdev_features_t features) -{ - features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM); - - return features; -} -#endif - -static const struct net_device_ops sipa_eth_ops = { - .ndo_open = sipa_eth_open, - .ndo_stop = sipa_eth_close, - .ndo_start_xmit = sipa_eth_start_xmit, - .ndo_get_stats = sipa_eth_get_stats, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) - .ndo_features_check = sipa_eth_features_check, -#endif -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) -static int sipa_eth_parse_dt( - struct sipa_eth_init_data **init, - struct device *dev) -{ - struct sipa_eth_init_data *pdata = NULL; - struct device_node *np = dev->of_node; - int ret; - u32 udata, id; - s32 sdata; - - if (!np) - pr_err("dev of_node np is null\n"); - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - id = of_alias_get_id(np, "eth"); - switch (id) { - case 0 ... 7: - snprintf(pdata->name, IFNAMSIZ, "%s%d", - SIPA_ETH_IFACE_PREF, id); - break; - case 8 ... 11: - snprintf(pdata->name, IFNAMSIZ, "%s%d", - SIPA_ETH_VPCIE_PREF, id - SIPA_ETH_VPCIE_IDX); - break; - default: - pr_err("wrong alias id from dts, id %d\n", id); - return -EINVAL; - } - - ret = of_property_read_u32(np, "sprd,netid", &sdata); - if (ret) { - pr_err("read sprd,netid ret %d\n", ret); - return ret; - } - /* dts reflect */ - pdata->netid = sdata - 1; - - ret = of_property_read_u32(np, "sprd,term-type", &udata); - if (ret) { - pr_err("read sprd,term-type ret %d\n", ret); - return ret; - } - - pdata->term_type = udata; - - pdata->mac_h = of_property_read_bool(np, "sprd,mac-header"); - - *init = pdata; - pr_debug("after dt parse, name %s netid %d term-type %d mac_h %d\n", - pdata->name, pdata->netid, pdata->term_type, pdata->mac_h); - return 0; -} -#endif - -static void s_setup(struct net_device *dev) -{ -#ifndef CONFIG_SPRD_ETHERNET - ether_setup(dev); - dev->needed_headroom = 16; - - /* Raw IP mode */ - dev->header_ops = NULL; /* No header */ - dev->type = ARPHRD_RAWIP; - dev->hard_header_len = 0; - dev->flags |= IFF_NOARP | IFF_PROMISC; - dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); - dev->addr_len = ETH_ALEN; - eth_hw_addr_random(dev); -#else - ether_setup(dev); - dev->flags |= IFF_PROMISC; -#endif -} - -static ssize_t sipa_eth_get_direct_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct net_device *netdev = to_net_dev(dev); - struct SIPA_ETH *sipa_eth = netdev_priv(netdev); - - - if (sipa_eth->pdata->term_type == 0x0) - return sprintf(buf, "\n %s in mode: normal\n", sipa_eth->netdev->name); - else if (sipa_eth->pdata->term_type == 0x6) - return sprintf(buf, "\n %s in mode: direct\n", sipa_eth->netdev->name); - else - return sprintf(buf, "\n %s in mode: illegal\n", sipa_eth->netdev->name); -} - -static ssize_t sipa_eth_set_direct_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct net_device *netdev = to_net_dev(dev); - struct SIPA_ETH *sipa_eth = netdev_priv(netdev); - - if (!strncmp(buf, "normal", count - 1)) { - sipa_eth->pdata->term_type = 0x0; - } else if (!strncmp(buf, "direct", count - 1)) { -#ifndef CONFIG_SPRD_ETHERNET - sipa_eth->pdata->term_type = 0x6; -#else - pr_info("mode only can be set as normal when CONFIG_SPRD_ETHERNET is enabled!\n"); - return -EINVAL; -#endif - } else { - return -EINVAL; - } - - return count; -} - -static DEVICE_ATTR(mode, 0664, sipa_eth_get_direct_mode, sipa_eth_set_direct_mode); - -static struct attribute *sipa_eth_attributes[] = { - &dev_attr_mode.attr, - NULL, -}; - -static struct attribute_group sipa_eth_attribute_group = { - .attrs = sipa_eth_attributes, -}; - -static rx_handler_result_t sipa_eth_rx_handler(struct sk_buff **pskb) -{ - struct sk_buff *skb = *pskb; - struct rmnet_nss_cb *nss_cb; - - if (!skb) - return RX_HANDLER_CONSUMED; - - //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - - /* Check this so that we dont loop around netif_receive_skb */ - - if (skb->cb[0] == 1) { - skb->cb[0] = 0; - - return RX_HANDLER_PASS; - } - - rmnet_nss_dereference(nss_cb); - if (nss_cb) { - nss_cb->nss_tx(skb); - return RX_HANDLER_CONSUMED; - } - - return RX_HANDLER_PASS; -} - -static int sipa_eth_probe(struct platform_device *pdev) -{ - struct sipa_eth_netid_device *netid_dev_info = NULL; - struct sipa_eth_init_data *pdata = pdev->dev.platform_data; - struct net_device *netdev; - struct SIPA_ETH *sipa_eth; - char ifname[IFNAMSIZ]; - struct rmnet_nss_cb *nss_cb; - int ret; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 )) - if (pdev->dev.of_node && !pdata) { - ret = sipa_eth_parse_dt(&pdata, &pdev->dev); - if (ret) { - pr_err("failed to parse device tree, ret=%d\n", ret); - return ret; - } - pdev->dev.platform_data = pdata; - } -#endif - - rmnet_nss_dereference(nss_cb); - strlcpy(ifname, pdata->name, IFNAMSIZ); -#ifdef NET_NAME_PREDICTABLE - netdev = alloc_netdev( - sizeof(struct SIPA_ETH), - ifname, - NET_NAME_PREDICTABLE, - s_setup); -#else - netdev = alloc_netdev( - sizeof(struct SIPA_ETH), - ifname, - s_setup); -#endif - - if (!netdev) { - pr_err("alloc_netdev() failed.\n"); - return -ENOMEM; - } - - sipa_eth = netdev_priv(netdev); - sipa_eth_dt_stats_init(&sipa_eth->dt_stats); - sipa_eth->netdev = netdev; - sipa_eth->pdata = pdata; - atomic_set(&sipa_eth->rx_busy, 0); - atomic_set(&sipa_eth->rx_evt, 0); - netdev->netdev_ops = &sipa_eth_ops; - netdev->watchdog_timeo = 1 * HZ; - netdev->irq = 0; - netdev->dma = 0; - netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_HW_CSUM); - random_ether_addr(netdev->dev_addr); - netdev->sysfs_groups[0] = &sipa_eth_attribute_group; - - netif_napi_add(netdev, - &sipa_eth->napi, - sipa_eth_rx_poll_handler, - SIPA_ETH_NAPI_WEIGHT); - - /* Register new Ethernet interface */ - ret = register_netdev(netdev); - if (ret) { - pr_err("register_netdev() failed (%d)\n", ret); - netif_napi_del(&sipa_eth->napi); - free_netdev(netdev); - return ret; - } - - sipa_eth->state = DEV_OFF; - /* Set link as disconnected */ - netif_carrier_off(netdev); - platform_set_drvdata(pdev, sipa_eth); - sipa_eth_debugfs_mknod(root, (void *)sipa_eth); - - if (!strncmp(netdev->name, SIPA_ETH_VPCIE_PREF, strlen(SIPA_ETH_VPCIE_PREF))) { - netid_dev_info = kzalloc(sizeof(*netid_dev_info), GFP_ATOMIC); - if (!netid_dev_info) - return -ENOMEM; - - if (nss_cb) { - int rc = nss_cb->nss_create(netdev); - if (rc) { - /* Log, but don't fail the device creation */ - netdev_err(netdev, "Device will not use NSS path: %d\n", rc); - } else { - netdev_info(netdev, "NSS context created\n"); - rtnl_lock(); - netdev_rx_handler_register(netdev, sipa_eth_rx_handler, NULL); - rtnl_unlock(); - } - } - - netid_dev_info->ndev = netdev; - netid_dev_info->napi = sipa_eth->napi; - netid_dev_info->state = DEV_OFF; - netid_dev_info->netid = pdata->netid; - dev_list[pdata->netid] = netid_dev_info; - } - //sysfs_create_group(&pdev->dev.kobj, &sipa_eth_attribute_group); - return 0; -} - -/* Cleanup Ethernet device driver. */ -static int sipa_eth_remove(struct platform_device *pdev) -{ - struct SIPA_ETH *sipa_eth = platform_get_drvdata(pdev); - struct rmnet_nss_cb *nss_cb; - rx_handler_func_t *rx_handler; - struct sipa_eth_init_data *pdata = pdev->dev.platform_data; - - - rmnet_nss_dereference(nss_cb); - rcu_read_lock(); - rx_handler = rcu_dereference(sipa_eth->netdev->rx_handler); - rcu_read_unlock(); - if (nss_cb && rx_handler == sipa_eth_rx_handler) { - rtnl_lock(); - netdev_rx_handler_unregister(sipa_eth->netdev); - rtnl_unlock(); - nss_cb->nss_free(sipa_eth->netdev); - } - - netif_napi_del(&sipa_eth->napi); - unregister_netdev(sipa_eth->netdev); - - if(dev_list[pdata->netid]) { - kfree(dev_list[pdata->netid]); - dev_list[pdata->netid] = NULL; - } - - if (!IS_ERR_OR_NULL(sipa_eth->subroot)) - debugfs_remove_recursive(sipa_eth->subroot); - free_netdev(sipa_eth->netdev); - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipa_eth_match_table[] = { - { .compatible = "sprd,sipa_eth"}, - { } -}; -#endif - -static struct platform_driver sipa_eth_driver = { - .probe = sipa_eth_probe, - .remove = sipa_eth_remove, - .driver = { - .owner = THIS_MODULE, - .name = SIPA_ETH_IFACE_PREF, -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipa_eth_match_table -#endif - } -}; - -#ifndef SPRD_PCIE_USE_DTS -static struct platform_device *sipa_eth_pdev[SIPA_ETH_NUM]; -static struct sipa_eth_init_data *sipa_eth_data[SIPA_ETH_NUM]; - -static int sipa_eth_platform_device_reigster(void) -{ - int retval = -ENOMEM; - int i; - - for(i = 0; i < SIPA_ETH_NUM; i++) { - sipa_eth_pdev[i] = platform_device_alloc(SIPA_ETH_IFACE_PREF, i); - if (!sipa_eth_pdev[i]) { - i--; - while (i >= 0) - platform_device_put(sipa_eth_pdev[i--]); - return retval; - } - } - - for (i = 0; i < SIPA_ETH_NUM; i++) { - sipa_eth_data[i] = kzalloc(sizeof(struct sipa_eth_init_data), GFP_KERNEL); - if (!sipa_eth_data[i]) { - retval = -ENOMEM; - goto err_add_pdata; - } - - snprintf(sipa_eth_data[i]->name, IFNAMSIZ, "%s%d", - SIPA_ETH_VPCIE_PREF, i); -#ifndef CONFIG_SPRD_ETHERNET - sipa_eth_data[i]->term_type = 0x6; -#else - sipa_eth_data[i]->term_type = 0x0; -#endif - sipa_eth_data[i]->netid = i; - sipa_eth_data[i]->mac_h = true; - - retval = platform_device_add_data(sipa_eth_pdev[i], sipa_eth_data[i], - sizeof(struct sipa_eth_init_data)); - if (retval) - goto err_add_pdata; - } - - for (i = 0; i < SIPA_ETH_NUM; i++) { - retval = platform_device_add(sipa_eth_pdev[i]); - if (retval < 0) { - i--; - while (i >= 0) - platform_device_del(sipa_eth_pdev[i]); - goto err_add_pdata; - } - } - - return retval; -err_add_pdata: - for (i = 0; i < SIPA_ETH_NUM; i++) { - if(sipa_eth_data[i]) - kfree(sipa_eth_data[i]); - } - for (i = 0; i < SIPA_ETH_NUM; i++) - platform_device_put(sipa_eth_pdev[i]); - return retval; -} - -static void sipa_eth_platform_device_unreigster(void) -{ - int i; - - for (i = 0; i < SIPA_ETH_NUM; i++) { - struct sipa_eth_init_data *init_data; - - init_data = dev_get_platdata(&sipa_eth_pdev[i]->dev); - platform_device_unregister(sipa_eth_pdev[i]); - } - - if (!IS_ERR_OR_NULL(root)) - debugfs_remove_recursive(root); - -} -#endif - -static int sipa_eth_debug_show(struct seq_file *m, void *v) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)(m->private); - struct sipa_eth_dtrans_stats *stats; - struct sipa_eth_init_data *pdata; - int i; - - if (!sipa_eth) { - pr_err("invalid data, sipa_eth is NULL\n"); - return -EINVAL; - } - pdata = sipa_eth->pdata; - stats = &sipa_eth->dt_stats; - - seq_puts(m, "*************************************************\n"); - seq_printf(m, "DEVICE: %s, term_type %d, netid %d, state %s mac_h %d\n", - pdata->name, pdata->term_type, pdata->netid, - sipa_eth->state == DEV_ON ? "UP" : "DOWN", pdata->mac_h); - seq_puts(m, "\nRX statistics:\n"); - seq_printf(m, "rx_sum=%u, rx_cnt=%u\n", - stats->rx_sum, - stats->rx_cnt); - seq_printf(m, "rx_fail=%u\n", - stats->rx_fail); - - seq_printf(m, "rx_busy=%d\n", atomic_read(&sipa_eth->rx_busy)); - seq_printf(m, "rx_evt=%d\n", atomic_read(&sipa_eth->rx_evt)); - - seq_puts(m, "\nTX statistics:\n"); - seq_printf(m, "tx_sum=%u, tx_cnt=%u\n", - stats->tx_sum, - stats->tx_cnt); - seq_printf(m, "tx_fail=%u\n", - stats->tx_fail); - - for (i = 0; i < SIPA_DUMMY_IFACE_NUM; i++) { - if(dev_list[i] == NULL) { - break; - } - seq_printf(m, "dev %s, netid %d state %d\n", - dev_list[i]->ndev->name, dev_list[i]->netid, dev_list[i]->state); - } - - seq_puts(m, "*************************************************\n"); - - return 0; -} - -static int sipa_eth_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sipa_eth_debug_show, inode->i_private); -} - -static const struct file_operations sipa_eth_debug_fops = { - .open = sipa_eth_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int debugfs_gro_enable_get(void *data, u64 *val) -{ - *val = *(u64 *)data; - return 0; -} - -static int debugfs_gro_enable_set(void *data, u64 val) -{ - *(u64 *)data = val; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(fops_gro_enable, - debugfs_gro_enable_get, - debugfs_gro_enable_set, - "%llu\n"); - -static int sipa_eth_debugfs_mknod(void *root, void *data) -{ - struct SIPA_ETH *sipa_eth = (struct SIPA_ETH *)data; - struct dentry *subroot; - - if (!sipa_eth) - return -ENODEV; - - if (!root) - return -ENXIO; - subroot = debugfs_create_dir(sipa_eth->netdev->name, (struct dentry *)root); - if (!subroot) - return -ENOMEM; - - sipa_eth->subroot = subroot; - debugfs_create_file("stats", - 0444, - subroot, - data, - &sipa_eth_debug_fops); - - debugfs_create_file("gro_enable", - 0600, - (struct dentry *)root, - &gro_enable, - &fops_gro_enable); - - return 0; -} - -static void __init sipa_eth_debugfs_init(void) -{ - root = debugfs_create_dir(SIPA_ETH_IFACE_PREF, NULL); - if (!root) - pr_err("failed to create sipa_eth debugfs dir\n"); -} - -#ifdef CONFIG_QCA_NSS_DRV -/* - EXTRA_CFLAGS="-I$(STAGING_DIR)/usr/include/qca-nss-drv $(EXTRA_CFLAGS)" - qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c -*/ -#include "rmnet_nss.c" -#endif - -int sipa_eth_init(void) -{ - sipa_eth_debugfs_init(); - - RCU_INIT_POINTER(rmnet_nss_callbacks, NULL); -#ifdef CONFIG_QCA_NSS_DRV - if (qca_nss_enabled) - rmnet_nss_init(); -#endif - -#ifndef SPRD_PCIE_USE_DTS - sipa_eth_platform_device_reigster(); -#endif - return platform_driver_register(&sipa_eth_driver); -} -EXPORT_SYMBOL(sipa_eth_init); - -void sipa_eth_exit(void) -{ - int i; -#ifdef CONFIG_QCA_NSS_DRV - if (qca_nss_enabled) - rmnet_nss_exit(); -#endif - platform_driver_unregister(&sipa_eth_driver); -#ifndef SPRD_PCIE_USE_DTS - sipa_eth_platform_device_unreigster(); -#endif - for (i = 0; i < SIPA_ETH_NUM; i++) { - if(sipa_eth_data[i]){ - kfree(sipa_eth_data[i]); - } - } -} -EXPORT_SYMBOL(sipa_eth_exit); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_eth.h b/quectel_SRPD_PCIE/src/sipa/sipa_eth.h deleted file mode 100644 index 0519225..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_eth.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _SIPA_ETH_H_ -#define _SIPA_ETH_H_ - -#include "../include/sipa.h" -#include - -#define SIPA_ETH_NUM 2 -#define SIPA_DUMMY_IFACE_NUM 4 - -/* Struct of data transfer statistics */ -struct sipa_eth_dtrans_stats { - u32 rx_sum; - u32 rx_cnt; - u32 rx_fail; - - u32 tx_sum; - u32 tx_cnt; - u32 tx_fail; -}; - -/* Device instance data. */ -struct SIPA_ETH { - int state; - atomic_t rx_busy; - atomic_t rx_evt; - struct net_device *netdev;/* Linux net device */ - enum sipa_nic_id nic_id; - struct napi_struct napi;/* Napi instance */ - /* Record data_transfer statistics */ - struct sipa_eth_dtrans_stats dt_stats; - struct net_device_stats stats;/* Net statistics */ - struct sipa_eth_init_data *pdata;/* Platform data */ - struct dentry *subroot; -}; - -struct sipa_eth_init_data { - char name[IFNAMSIZ]; - unsigned char modem_mac[ETH_ALEN]; - u32 term_type; - s32 netid; - bool mac_h; -}; - -struct sipa_eth_netid_device { - int state; - int netid; - struct net_device *ndev; - struct napi_struct napi;/* Napi instance */ - /* Record data_transfer statistics */ - struct net_device_stats stats;/* Net statistics */ -}; - -/* Device instance data. */ -struct SIPA_DUMMY { - atomic_t rx_busy; - atomic_t rx_evt; - struct net_device *netdev;/* Linux net device */ - struct napi_struct napi;/* Napi instance */ - struct net_device_stats stats;/* Net statistics */ -}; - -void sipa_dummy_recv_trigger(void); - -#endif - diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_nic.c b/quectel_SRPD_PCIE/src/sipa/sipa_nic.c deleted file mode 100644 index 6a69b0d..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_nic.c +++ /dev/null @@ -1,332 +0,0 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../include/sipa.h" -#include "sipa_core.h" - -#define SIPA_CP_SRC ((1 << SIPA_TERM_CP0) | \ - (1 << SIPA_TERM_CP1) | (1 << SIPA_TERM_VCP) | \ - (1 << 0x19) | (1 << 0x18)) - -struct sipa_nic_statics_info { - u32 src_mask; - int netid; -}; - -static struct sipa_nic_statics_info s_spia_nic_statics[SIPA_NIC_MAX] = { - { - .src_mask = SIPA_CP_SRC, - .netid = 0, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 1, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 2, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 3, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 4, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 5, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 6, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 7, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 8, - }, - { - .src_mask = SIPA_CP_SRC, - .netid = 9, - }, -}; - -int sipa_nic_open(enum sipa_term_type src, int netid, - sipa_notify_cb cb, void *priv) -{ - struct sipa_nic *nic = NULL; - struct sk_buff *skb; - enum sipa_nic_id nic_id = SIPA_NIC_MAX; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - return -EINVAL; - } - - if(!ctrl->remote_ready) - return -EINVAL; - - nic_id = netid; - dev_info(ctrl->dev, "open nic_id = %d\n", nic_id); - if (nic_id == SIPA_NIC_MAX) - return -EINVAL; - - if (ctrl->nic[nic_id]) { - nic = ctrl->nic[nic_id]; - if (atomic_read(&nic->status) == NIC_OPEN) - return -EBUSY; - while ((skb = skb_dequeue(&nic->rx_skb_q)) != NULL) - dev_kfree_skb_any(skb); - } else { - nic = kzalloc(sizeof(*nic), GFP_KERNEL); - if (!nic) - return -ENOMEM; - ctrl->nic[nic_id] = nic; - skb_queue_head_init(&nic->rx_skb_q); - } - - atomic_set(&nic->status, NIC_OPEN); - nic->nic_id = nic_id; - nic->send_ep = &ctrl->ep; - nic->need_notify = 0; - nic->src_mask = s_spia_nic_statics[nic_id].src_mask; - nic->netid = netid; - nic->cb = cb; - nic->cb_priv = priv; - nic->continue_notify = true; - - /* every receiver may receive cp packets */ - //sipa_receiver_add_nic(ctrl->receiver, nic); - sipa_skb_sender_add_nic(ctrl->sender, nic); - - return nic_id; -} -EXPORT_SYMBOL(sipa_nic_open); - -void sipa_nic_close(enum sipa_nic_id nic_id) -{ - struct sipa_nic *nic = NULL; - struct sk_buff *skb; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - dev_err(ctrl->dev, "sipa driver may not register\n"); - return; - } - - if (nic_id == SIPA_NIC_MAX || !ctrl->nic[nic_id]) - return; - - nic = ctrl->nic[nic_id]; - nic->continue_notify = false; - atomic_set(&nic->status, NIC_CLOSE); - /* free all pending skbs */ - while ((skb = skb_dequeue(&nic->rx_skb_q)) != NULL) - dev_kfree_skb_any(skb); - - sipa_skb_sender_remove_nic(ctrl->sender, nic); - dev_info(ctrl->dev, "close nic_id = %d\n", nic_id); -} -EXPORT_SYMBOL(sipa_nic_close); - -void sipa_nic_notify_evt(struct sipa_nic *nic, enum sipa_evt_type evt) -{ - struct sipa_core *ipa = sipa_get_ctrl_pointer(); - if (!ipa->remote_ready) { - return; - } - - if (nic->cb) - nic->cb(nic->cb_priv, evt, 0); -} -EXPORT_SYMBOL(sipa_nic_notify_evt); - -void sipa_nic_check_flow_ctrl(void) -{ - int i; - struct sipa_nic *nic; - struct sipa_core *ipa = sipa_get_ctrl_pointer(); - - for (i = 0; i < SIPA_NIC_MAX; i++) { - nic = ipa->nic[i]; - if (nic && nic->rm_flow_ctrl) { - nic->rm_flow_ctrl = false; - nic->cb(nic->cb_priv, SIPA_LEAVE_FLOWCTRL, 0); - } - } -} -EXPORT_SYMBOL(sipa_nic_check_flow_ctrl); - -void sipa_nic_try_notify_recv(struct sipa_nic *nic) -{ - if (atomic_read(&nic->status) == NIC_CLOSE) - return; - - if (nic->cb) - nic->cb(nic->cb_priv, SIPA_RECEIVE, 0); -} -EXPORT_SYMBOL(sipa_nic_try_notify_recv); - -void sipa_nic_push_skb(struct sipa_nic *nic, struct sk_buff *skb) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - atomic_inc(&ctrl->recv_cnt); - skb_queue_tail(&nic->rx_skb_q, skb); - if (nic->rx_skb_q.qlen == 1 || nic->continue_notify) - nic->need_notify = 1; -} -EXPORT_SYMBOL(sipa_nic_push_skb); - -int sipa_nic_tx(enum sipa_nic_id nic_id, enum sipa_term_type dst, - int netid, struct sk_buff *skb) -{ - int ret; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl || !ctrl->sender) { - dev_err(ctrl->dev, "sipa driver may not register\n"); - return -EINVAL; - } - - if (!ctrl->remote_ready) { - ctrl->nic[nic_id]->rm_flow_ctrl = true; -// dev_err(ctrl->dev, "remote ipa not ready\n"); - return -EINPROGRESS; - } - - ret = sipa_skb_sender_send_data(ctrl->sender, skb, dst, netid); -// if (ret == -EAGAIN) -// ctrl->nic[nic_id]->flow_ctrl_status = true; - - return ret; -} -EXPORT_SYMBOL(sipa_nic_tx); - -int sipa_nic_rx(int *netid, struct sk_buff **out_skb, int index) -{ - struct sk_buff *skb; - - skb = sipa_recv_skb(netid, index); - *out_skb = skb; - - return (skb) ? 0 : -ENODATA; -} -EXPORT_SYMBOL(sipa_nic_rx); - -int sipa_nic_rx_has_data(enum sipa_nic_id nic_id) -{ - struct sipa_nic *nic; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - pr_err("sipa driver may not register\n"); - return -EINVAL; - } - if (!ctrl->nic[nic_id] || - atomic_read(&ctrl->nic[nic_id]->status) == NIC_CLOSE) - return 0; - - nic = ctrl->nic[nic_id]; - - return (!!nic->rx_skb_q.qlen); -} -EXPORT_SYMBOL(sipa_nic_rx_has_data); - -int sipa_nic_trigger_flow_ctrl_work(enum sipa_nic_id nic_id, int err) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (!ctrl) { - pr_err("sipa driver may not register\n"); - return -EINVAL; - } - - if (!ctrl->sender) - return -ENODEV; - - switch (err) { - case -EAGAIN: - //ctrl->sender->free_notify_net = true; - schedule_work(&ctrl->flow_ctrl_work); - break; - default: - dev_warn(ctrl->dev, - "don't have this flow ctrl err type\n"); - break; - } - - return 0; -} -EXPORT_SYMBOL(sipa_nic_trigger_flow_ctrl_work); - -u32 sipa_nic_get_filled_num(void) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) { - dev_err(ctrl->dev, "remote sipa not ready %d\n", - ctrl->remote_ready); - return 0; - } - - return ctrl->hal_ops.recv_node_from_tx_fifo(ctrl->dev, id, - ctrl->cmn_fifo_cfg, -1); -} -EXPORT_SYMBOL(sipa_nic_get_filled_num); - -void sipa_nic_restore_irq(void) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) { - dev_err(ctrl->dev, "remote sipa not ready %d\n", - ctrl->remote_ready); - return; - } - - ctrl->hal_ops.clr_tout_th_intr(id, ctrl->cmn_fifo_cfg); - ctrl->hal_ops.set_intr_eb(id, ctrl->cmn_fifo_cfg, true, - SIPA_FIFO_THRESHOLD_IRQ_EN | - SIPA_FIFO_DELAY_TIMER_IRQ_EN); -} -EXPORT_SYMBOL(sipa_nic_restore_irq); - -void sipa_nic_set_tx_fifo_rp(u32 rptr) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) { - dev_err(ctrl->dev, "remote sipa not ready %d\n", - ctrl->remote_ready); - return; - } - - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, rptr); -} -EXPORT_SYMBOL(sipa_nic_set_tx_fifo_rp); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile b/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile deleted file mode 100644 index dd44ed6..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += sipa_common_fifo_hal.o sipa_fifo_irq_hal.o diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c b/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c deleted file mode 100644 index 5121968..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_common_fifo_hal.c +++ /dev/null @@ -1,1234 +0,0 @@ -#include -#include - -#include "../../include/sipa.h" -#include "../sipa_core.h" -#include "sipa_fifo_phy.h" - -#define PTR_MASK(depth) (depth | (depth - 1)) - -static inline int -ipa_put_pkt_to_cache_rx_fifo(struct device *dev, - struct sipa_cmn_fifo_cfg_tag *fifo_cfg, - struct sipa_node_description_tag *desc, - u32 num) -{ - dma_addr_t dma_addr; - u32 tmp = 0, tmp1 = 0, ret = 0, index = 0, left_cnt = 0; - ssize_t node_size = sizeof(struct sipa_node_description_tag); - struct sipa_node_description_tag *node = - (struct sipa_node_description_tag *) - fifo_cfg->rx_fifo.virtual_addr; - - dma_addr = fifo_cfg->rx_fifo.fifo_base_addr_l; - - left_cnt = fifo_cfg->rx_fifo.depth - - ipa_phy_get_rx_fifo_filled_depth(fifo_cfg->fifo_reg_base); - - if (!left_cnt) - return -ENOSPC; - - if (left_cnt < num) - num = left_cnt; - - index = fifo_cfg->rx_fifo.wr & (fifo_cfg->rx_fifo.depth - 1); - if (index + num <= fifo_cfg->rx_fifo.depth) { - memcpy(node + index, desc, node_size * num); - } else { - tmp = fifo_cfg->rx_fifo.depth - index; - memcpy(node + index, desc, tmp * node_size); - tmp1 = num - tmp; - memcpy(node, desc + tmp, tmp1 * node_size); - } - - fifo_cfg->rx_fifo.wr = (fifo_cfg->rx_fifo.wr + num) & - PTR_MASK(fifo_cfg->rx_fifo.depth); - smp_wmb(); - ret = ipa_phy_update_rx_fifo_wptr(fifo_cfg->fifo_reg_base, - fifo_cfg->rx_fifo.wr); - - if (!ret) - pr_err("sipa_phy_update_rx_fifo_rptr fail\n"); - - return num; -} - -static inline u32 -ipa_recv_pkts_from_tx_fifo(struct device *dev, - struct sipa_cmn_fifo_cfg_tag *fifo_cfg, - u32 num) -{ - return ipa_phy_get_tx_fifo_filled_depth(fifo_cfg->fifo_reg_base); -} - -static int ipa_common_fifo_hal_open(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - void *cookie) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo = NULL; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (ipa_term_fifo->state) { - pr_err("sipa fifo_id = %d has already opened state = %d\n", - ipa_term_fifo->fifo_id, ipa_term_fifo->state); - return -EBUSY; - } - - ipa_phy_set_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->rx_fifo.depth); - ipa_phy_set_rx_fifo_addr(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->rx_fifo.fifo_base_addr_l, - ipa_term_fifo->rx_fifo.fifo_base_addr_h); - - ipa_phy_set_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->tx_fifo.depth); - ipa_phy_set_tx_fifo_addr(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->tx_fifo.fifo_base_addr_l, - ipa_term_fifo->tx_fifo.fifo_base_addr_h); - - ipa_phy_set_cur_term_num(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->cur); - ipa_phy_set_dst_term_num(ipa_term_fifo->fifo_reg_base, - ipa_term_fifo->dst); - - ipa_phy_update_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_clear_stop_receive(ipa_term_fifo->fifo_reg_base); - - ipa_term_fifo->rx_fifo.rd = 0; - ipa_term_fifo->rx_fifo.wr = 0; - ipa_term_fifo->tx_fifo.rd = 0; - ipa_term_fifo->tx_fifo.wr = 0; - - ipa_term_fifo->fifo_name = cookie; - ipa_term_fifo->state = true; - - return 0; -} - -static int ipa_common_fifo_hal_close(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - ipa_phy_set_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_set_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, 0); - - ipa_phy_update_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base, 0); - ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, 0); - - ipa_term_fifo->rx_fifo.rd = 0; - ipa_term_fifo->rx_fifo.wr = 0; - ipa_term_fifo->tx_fifo.rd = 0; - ipa_term_fifo->tx_fifo.wr = 0; - - ipa_term_fifo->state = 0; - - return 0; -} - -static int -ipa_common_fifo_hal_set_rx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 depth) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - return ipa_phy_set_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - depth); -} - -static u32 -ipa_common_fifo_hal_get_rx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_rx_fifo_total_depth(ipa_term_fifo->fifo_reg_base); -} - -static int -ipa_common_fifo_hal_set_tx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 depth) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return 0; - } - - return ipa_phy_set_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base, - depth); -} - -static u32 -ipa_common_fifo_hal_get_tx_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base); -} - -static int -ipa_common_fifo_hal_set_intr_drop_packet(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) - return ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_DROP_PACKET_OCCUR_INT_EN); - else - return ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_DROP_PACKET_OCCUR_INT_EN); -} - -static int -ipa_common_fifo_hal_set_intr_error_code(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) - return ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_ERRORCODE_IN_TX_FIFO_EN); - else - return ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_ERRORCODE_IN_TX_FIFO_EN); -} - -static int -ipa_common_fifo_hal_set_intr_timeout(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("sipa don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_delay_timer( - ipa_term_fifo->fifo_reg_base, - time); - if (ret) - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_DELAY_TIMER_SW_EN); - else - pr_err("fifo(%d) set timeout threshold fail\n", id); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_DELAY_TIMER_SW_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_hw_intr_timeout(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 time, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_delay_timer( - ipa_term_fifo->fifo_reg_base, time); - if (!ret) - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_DELAY_TIMER_EN); - else - pr_err("fifo(%d) set timeout threshold fail\n", id); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_DELAY_TIMER_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_intr_threshold(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_threshold( - ipa_term_fifo->fifo_reg_base, cnt); - if (!ret) { - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_THRESHOLD_ONESHOT_EN); - } else { - pr_err("fifo(%d) set threshold fail\n", id); - } - } else { - ret = - ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_INT_THRESHOLD_ONESHOT_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_hw_intr_thres(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, u32 cnt, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_set_tx_fifo_interrupt_threshold( - ipa_term_fifo->fifo_reg_base, cnt); - if (!ret) - ret = ipa_phy_enable_int_bit( - ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_THRESHOLD_EN); - else - pr_err("fifo(%d) set threshold fail\n", id); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_THRESHOLD_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_src_dst_term(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 src, u32 dst) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - ret = ipa_phy_set_cur_term_num(ipa_term_fifo->fifo_reg_base, src); - if (ret) { - pr_err("fifo %d set cur failed\n", id); - return ret; - } - - ret = ipa_phy_set_dst_term_num(ipa_term_fifo->fifo_reg_base, dst); - if (ret) { - pr_err("fifo %d set dst failed\n", id); - return ret; - } - - return 0; -} - -static int -ipa_common_fifo_hal_enable_local_flowctrl_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 enable, - u32 irq_mode, - sipa_irq_notify_cb cb) -{ - int ret; - u32 irq; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - switch (irq_mode) { - case 0: - irq = IPA_RX_FIFO_INT_EXIT_FLOW_CTRL_EN; - break; - case 1: - irq = IPA_RX_FIFO_INT_ENTER_FLOW_CTRL_EN; - break; - case 2: - irq = IPA_RX_FIFO_INT_EXIT_FLOW_CTRL_EN | - IPA_RX_FIFO_INT_ENTER_FLOW_CTRL_EN; - break; - default: - pr_err("don't have this %d irq type\n", irq_mode); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, irq); - if (ret) { - pr_err("fifo_id = %d irq_mode = %d set failed\n", - id, irq); - return ret; - } - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - irq); - } - - return ret; -} - -static int -ipa_common_fifo_hal_enable_remote_flowctrl_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 work_mode, - u32 tx_entry_watermark, - u32 tx_exit_watermark, - u32 rx_entry_watermark, - u32 rx_exit_watermark) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - ret = ipa_phy_set_tx_fifo_exit_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, tx_exit_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d tx_exit_watermark(0x%x) failed\n", - id, tx_exit_watermark); - return ret; - } - - ret = ipa_phy_set_tx_fifo_entry_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, tx_entry_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d tx_entry_watermark(0x%x) failed\n", - id, tx_entry_watermark); - return ret; - } - - ret = ipa_phy_set_rx_fifo_exit_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, rx_exit_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d rx_exit_watermark(0x%x) failed\n", - id, rx_exit_watermark); - return ret; - } - - ret = ipa_phy_set_rx_fifo_entry_flow_ctrl_watermark( - ipa_term_fifo->fifo_reg_base, rx_entry_watermark); - if (unlikely(!ret)) { - pr_err("fifo_id = %d rx_entry_watermark(0x%x) failed\n", - id, rx_entry_watermark); - return ret; - } - - ret = ipa_phy_set_flow_ctrl_config(ipa_term_fifo->fifo_reg_base, - work_mode); - - return ret; -} - -static int -ipa_common_fifo_hal_set_interrupt_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_INTR_SW_BIT_EN); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TX_FIFO_INTR_SW_BIT_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_intr_txfifo_overflow(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 enable, - sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_OVERFLOW_EN); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_OVERFLOW_EN); - } - - return ret; -} - -static int -ipa_common_fifo_hal_set_intr_txfifo_full(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 enable, sipa_irq_notify_cb cb) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (enable) { - ret = ipa_phy_enable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_FULL_INT_EN); - } else { - ret = ipa_phy_disable_int_bit(ipa_term_fifo->fifo_reg_base, - IPA_TXFIFO_FULL_INT_EN); - } - - return ret; -} - -/** - * Description: Receive Node from tx fifo. - * Input: - * @id: The FIFO id that need to be operated. - * @pkt: The node that need to be stored address. - * @num: The num of receive. - * OUTPUT: - * @The num that has be received from tx fifo successful. - * Note: - */ -static int -ipa_common_fifo_hal_put_node_to_rx_fifo(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - struct sipa_node_description_tag *node, - u32 force_intr, u32 num) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - return ipa_put_pkt_to_cache_rx_fifo(dev, ipa_term_fifo, - node, num); -} - -static u32 -ipa_common_fifo_hal_get_left_cnt(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - u32 left_cnt; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo = NULL; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - left_cnt = - ipa_phy_get_tx_fifo_total_depth(ipa_term_fifo->fifo_reg_base) - - ipa_phy_get_tx_fifo_filled_depth(ipa_term_fifo->fifo_reg_base); - - return left_cnt; -} - -/* - * Description: Send Node to rx fifo. - * Input: - * id: The FIFO id that need to be operated. - * pkt: The node address that need send to rx fifo. - * num: The number of need to send. - * OUTPUT: - * The number that has get from tx fifo successful. - * Note: - */ -static u32 -ipa_common_fifo_hal_recv_node_from_tx_fifo(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 num) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_recv_pkts_from_tx_fifo(dev, ipa_term_fifo, num); -} - -static void -ipa_common_fifo_hal_get_rx_ptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return; - } - - if (rd) - *rd = ipa_phy_get_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - if (wr) - *wr = ipa_phy_get_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base); -} - -static void -ipa_common_fifo_hal_get_tx_ptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *wr, u32 *rd) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return; - } - - if (rd) - *rd = ipa_phy_get_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - if (wr) - *wr = ipa_phy_get_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base); -} - -static void -ipa_common_fifo_hal_get_filled_depth(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 *rx_filled, u32 *tx_filled) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - void __iomem *reg_base; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return; - } - - reg_base = ipa_term_fifo->fifo_reg_base; - if (tx_filled) - *tx_filled = ipa_phy_get_tx_fifo_filled_depth(reg_base); - if (rx_filled) - *rx_filled = ipa_phy_get_rx_fifo_filled_depth(reg_base); -} - -static u32 -ipa_common_fifo_hal_get_tx_full_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_tx_fifo_full_status(ipa_term_fifo->fifo_reg_base); -} - -static u32 -ipa_common_fifo_hal_get_tx_empty_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_tx_fifo_empty_status(ipa_term_fifo->fifo_reg_base); -} - -static u32 -ipa_common_fifo_hal_get_rx_full_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_rx_fifo_full_status(ipa_term_fifo->fifo_reg_base); -} - -static u32 -ipa_common_fifo_hal_get_rx_empty_status(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return 0; - } - - return ipa_phy_get_rx_fifo_empty_status(ipa_term_fifo->fifo_reg_base); -} - -static bool -ipa_common_fifo_hal_set_rx_fifo_wptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr) -{ - u32 ret; - u32 rx_wptr; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return false; - } - - rx_wptr = ipa_phy_get_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - - if (wptr != rx_wptr) { - wptr = wptr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->rx_fifo.wr = wptr; - ret = ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - wptr); - if (!ret) { - pr_err("fifo id = %d update rx fifo wptr = 0x%x failed !!!", - id, wptr); - return false; - } - } - - return true; -} - -static bool -ipa_common_fifo_hal_set_tx_fifo_wptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 wptr) -{ - u32 ret; - u32 tx_wptr; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return false; - } - - tx_wptr = ipa_phy_get_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - - if (wptr != tx_wptr) { - wptr = wptr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->tx_fifo.wr = wptr; - ret = ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - wptr); - if (!ret) { - pr_err("fifo id = %d update tx fifo wptr = 0x%x failed !!!", - id, wptr); - return false; - } - } - - return true; -} - -static int -ipa_common_fifo_hal_set_rx_tx_fifo_ptr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 rx_rd, u32 rx_wr, - u32 tx_rd, u32 tx_wr) -{ - int ret = 0, ret1 = 0; - u32 rx_rptr = 0, rx_wptr = 0; - u32 tx_rptr = 0, tx_wptr = 0; - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - tx_wptr = ipa_phy_get_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - tx_rptr = ipa_phy_get_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - rx_wptr = ipa_phy_get_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base); - rx_rptr = ipa_phy_get_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base); - - if (rx_rd != rx_rptr) { - rx_rd = rx_rd & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->rx_fifo.rd = rx_rd; - ret = ipa_phy_update_rx_fifo_rptr(ipa_term_fifo->fifo_reg_base, - rx_rd); - if (!ret) { - ret1 = -EIO; - pr_err("update rx fifo rptr = 0x%x failed !!!", rx_rd); - } - } - - if (rx_wr != rx_wptr) { - rx_wr = rx_wr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->rx_fifo.wr = rx_wr; - ret = ipa_phy_update_rx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - rx_wr); - if (!ret) { - ret1 = -EIO; - pr_err("update rx fifo wptr = 0x%x failed !!!", rx_wr); - } - } - - if (tx_rd != tx_rptr) { - tx_rd = tx_rd & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->tx_fifo.rd = tx_rd; - ret = ipa_phy_update_tx_fifo_rptr(ipa_term_fifo->fifo_reg_base, - tx_rd); - if (!ret) { - ret1 = -EIO; - pr_err("update tx fifo rptr = 0x%x failed !!!", tx_rd); - } - } - - if (tx_wr != tx_wptr) { - tx_wr = tx_wr & PTR_MASK(ipa_term_fifo->rx_fifo.depth); - ipa_term_fifo->tx_fifo.wr = tx_wr; - ret = ipa_phy_update_tx_fifo_wptr(ipa_term_fifo->fifo_reg_base, - tx_wr); - if (!ret) { - ret1 = -EIO; - pr_err("update tx fifo wptr = 0x%x failed !!!", tx_wr); - } - } - - return ret1; -} - -static int -ipa_common_fifo_hal_ctrl_receive(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool stop) -{ - struct sipa_cmn_fifo_cfg_tag *ipa_term_fifo; - - if (likely(id < SIPA_FIFO_MAX)) { - ipa_term_fifo = cfg_base + id; - } else { - pr_err("don't have this id %d\n", id); - return -EINVAL; - } - - if (stop) - return ipa_phy_stop_receive(ipa_term_fifo->fifo_reg_base); - else - return ipa_phy_clear_stop_receive(ipa_term_fifo->fifo_reg_base); -} - -static struct sipa_node_description_tag * -ipa_common_fifo_hal_get_tx_fifo_rp(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index) -{ - u32 tmp; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - struct sipa_node_description_tag *node; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return NULL; - - fifo_cfg = cfg_base + id; - node = (struct sipa_node_description_tag *) - fifo_cfg->tx_fifo.virtual_addr; - - if (unlikely(!node)) - return NULL; - - tmp = (fifo_cfg->tx_fifo.rd + index) & (fifo_cfg->tx_fifo.depth - 1); - - return node + tmp; -} - -static struct sipa_node_description_tag * -ipa_common_fifo_hal_get_rx_fifo_wr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - u32 index) -{ - u32 tmp; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - struct sipa_node_description_tag *node; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return NULL; - - fifo_cfg = cfg_base + id; - node = (struct sipa_node_description_tag *) - fifo_cfg->rx_fifo.virtual_addr; - - if (unlikely(!node)) - return NULL; - - if (index >= fifo_cfg->rx_fifo.depth) - return NULL; - - tmp = (fifo_cfg->rx_fifo.wr + index) & (fifo_cfg->rx_fifo.depth - 1); - - return node + tmp; -} - -static int ipa_common_fifo_hal_set_tx_fifo_rp(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 tx_rd) -{ - int ret; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return -EINVAL; - - fifo_cfg = cfg_base + id; - fifo_cfg->tx_fifo.rd = (fifo_cfg->tx_fifo.rd + tx_rd) & - PTR_MASK(fifo_cfg->tx_fifo.depth); - ret = ipa_phy_update_tx_fifo_rptr(fifo_cfg->fifo_reg_base, - fifo_cfg->tx_fifo.rd); - - if (ret) { - pr_err("update tx fifo rptr fail !!!\n"); - return -EINVAL; - } - - return 0; -} - -static int ipa_common_fifo_hal_set_rx_fifo_wr(struct device *dev, - enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base, u32 num) -{ - int ret; - dma_addr_t dma_addr; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - u32 tmp = 0, tmp1 = 0, index = 0, left_cnt = 0; - ssize_t node_size = sizeof(struct sipa_node_description_tag); - - if (unlikely(id >= SIPA_FIFO_MAX)) - return -EINVAL; - - fifo_cfg = cfg_base + id; - dma_addr = fifo_cfg->rx_fifo.fifo_base_addr_l; - - left_cnt = fifo_cfg->rx_fifo.depth - - ipa_phy_get_rx_fifo_filled_depth(fifo_cfg->fifo_reg_base); - - if (!left_cnt) - return -ENOSPC; - - if (left_cnt < num) - num = left_cnt; - - index = fifo_cfg->rx_fifo.wr & (fifo_cfg->rx_fifo.depth - 1); - if (index + num <= fifo_cfg->rx_fifo.depth) { - dma_sync_single_for_device(dev, dma_addr + index * node_size, - node_size * num, DMA_TO_DEVICE); - } else { - tmp = fifo_cfg->rx_fifo.depth - index; - dma_sync_single_for_device(dev, dma_addr + index * node_size, - node_size * tmp, DMA_TO_DEVICE); - tmp1 = num - tmp; - dma_sync_single_for_device(dev, dma_addr, - node_size * tmp1, DMA_TO_DEVICE); - } - - fifo_cfg->rx_fifo.wr = (fifo_cfg->rx_fifo.wr + num) & - PTR_MASK(fifo_cfg->rx_fifo.depth); - ret = ipa_phy_update_rx_fifo_wptr(fifo_cfg->fifo_reg_base, - fifo_cfg->rx_fifo.wr); - - if (ret) { - pr_err("update rx fifo rptr fail !!!\n"); - return -EIO; - } - - return 0; -} - -static int ipa_common_fifo_set_intr_eb(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *cfg_base, - bool eb, u32 type) -{ - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return -EINVAL; - - fifo_cfg = cfg_base + id; - - if (eb) - return ipa_phy_enable_int_bit(fifo_cfg->fifo_reg_base, type); - else - return ipa_phy_disable_int_bit(fifo_cfg->fifo_reg_base, type); -} - -static void ipa_common_fifo_clr_tout_th_intr(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag * - cfg_base) -{ - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - - if (unlikely(id >= SIPA_FIFO_MAX)) - return; - - fifo_cfg = cfg_base + id; - - ipa_phy_clear_int(fifo_cfg->fifo_reg_base, - IPA_TX_FIFO_TIMER_CLR_BIT | - IPA_TX_FIFO_THRESHOLD_CLR_BIT); -} - -void sipa_fifo_ops_init(struct sipa_fifo_hal_ops *ops) -{ - ops->open = ipa_common_fifo_hal_open; - - ops->close = ipa_common_fifo_hal_close; - - ops->enable_remote_flowctrl_intr = - ipa_common_fifo_hal_enable_remote_flowctrl_intr; - - ops->enable_local_flowctrl_intr = - ipa_common_fifo_hal_enable_local_flowctrl_intr; - - ops->get_left_cnt = ipa_common_fifo_hal_get_left_cnt; - - ops->put_node_to_rx_fifo = - ipa_common_fifo_hal_put_node_to_rx_fifo; - - ops->recv_node_from_tx_fifo = - ipa_common_fifo_hal_recv_node_from_tx_fifo; - - ops->set_intr_drop_packet = - ipa_common_fifo_hal_set_intr_drop_packet; - - ops->set_intr_error_code = - ipa_common_fifo_hal_set_intr_error_code; - - ops->set_intr_threshold = - ipa_common_fifo_hal_set_intr_threshold; - - ops->set_intr_timeout = - ipa_common_fifo_hal_set_intr_timeout; - - ops->set_hw_intr_thres = - ipa_common_fifo_hal_set_hw_intr_thres; - - ops->set_hw_intr_timeout = - ipa_common_fifo_hal_set_hw_intr_timeout; - - ops->set_interrupt_intr = - ipa_common_fifo_hal_set_interrupt_intr; - - ops->set_intr_txfifo_full = - ipa_common_fifo_hal_set_intr_txfifo_full; - - ops->set_intr_txfifo_overflow = - ipa_common_fifo_hal_set_intr_txfifo_overflow; - - ops->set_rx_depth = - ipa_common_fifo_hal_set_rx_depth; - - ops->set_tx_depth = - ipa_common_fifo_hal_set_tx_depth; - - ops->get_rx_depth = - ipa_common_fifo_hal_get_rx_depth; - - ops->get_tx_depth = - ipa_common_fifo_hal_get_tx_depth; - - ops->get_tx_ptr = - ipa_common_fifo_hal_get_tx_ptr; - - ops->get_rx_ptr = - ipa_common_fifo_hal_get_rx_ptr; - - ops->get_filled_depth = - ipa_common_fifo_hal_get_filled_depth; - - ops->get_tx_empty_status = - ipa_common_fifo_hal_get_tx_empty_status; - - ops->get_tx_full_status = - ipa_common_fifo_hal_get_tx_full_status; - - ops->get_rx_empty_status = - ipa_common_fifo_hal_get_rx_empty_status; - - ops->get_rx_full_status = - ipa_common_fifo_hal_get_rx_full_status; - - ops->set_rx_tx_fifo_ptr = - ipa_common_fifo_hal_set_rx_tx_fifo_ptr; - - ops->set_tx_fifo_wptr = - ipa_common_fifo_hal_set_tx_fifo_wptr; - - ops->set_rx_fifo_wptr = - ipa_common_fifo_hal_set_rx_fifo_wptr; - - ops->set_src_dst_term = - ipa_common_fifo_hal_set_src_dst_term; - - ops->ctrl_receive = - ipa_common_fifo_hal_ctrl_receive; - - ops->set_tx_fifo_rp = ipa_common_fifo_hal_set_tx_fifo_rp; - ops->get_tx_fifo_rp = ipa_common_fifo_hal_get_tx_fifo_rp; - ops->get_rx_fifo_wr = ipa_common_fifo_hal_get_rx_fifo_wr; - ops->set_rx_fifo_wr = ipa_common_fifo_hal_set_rx_fifo_wr; - - ops->set_intr_eb = ipa_common_fifo_set_intr_eb; - ops->clr_tout_th_intr = ipa_common_fifo_clr_tout_th_intr; -} -EXPORT_SYMBOL(sipa_fifo_ops_init); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c b/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c deleted file mode 100644 index 36fa1dc..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_irq_hal.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "../../include/sipa.h" - -#include "../sipa_core.h" -#include "sipa_fifo_phy.h" - -static void ipa_fifo_traverse_int_bit(enum sipa_cmn_fifo_index id, - struct sipa_cmn_fifo_cfg_tag *ipa_cfg) -{ - void __iomem *fifo_base; - u32 clr_sts = 0; - u32 int_status = 0; - - fifo_base = ipa_cfg->fifo_reg_base; - int_status = ipa_phy_get_fifo_all_int_sts(fifo_base); - - if (!(int_status & IPA_INT_STS_GROUP)) - return; - - if (int_status & IPA_INT_EXIT_FLOW_CTRL_STS) { - ipa_cfg->exit_flow_ctrl_cnt++; - clr_sts |= IPA_EXIT_FLOW_CONTROL_CLR_BIT; - } - - if (int_status & IPA_INT_ERRORCODE_IN_TX_FIFO_STS) - clr_sts |= IPA_ERROR_CODE_INTR_CLR_BIT; - - if (int_status & IPA_INT_ENTER_FLOW_CTRL_STS) { - ipa_cfg->enter_flow_ctrl_cnt++; - clr_sts |= IPA_ENTRY_FLOW_CONTROL_CLR_BIT; - } - - if (int_status & IPA_INT_INTR_BIT_STS) - clr_sts |= IPA_TX_FIFO_INTR_CLR_BIT; - - if (int_status & IPA_INT_THRESHOLD_STS || - int_status & IPA_INT_DELAY_TIMER_STS) { - ipa_phy_disable_int_bit(ipa_cfg->fifo_reg_base, - IPA_TX_FIFO_THRESHOLD_EN | - IPA_TX_FIFO_DELAY_TIMER_EN); - clr_sts |= IPA_TX_FIFO_THRESHOLD_CLR_BIT | - IPA_TX_FIFO_TIMER_CLR_BIT; - } - - if (int_status & IPA_INT_DROP_PACKT_OCCUR) - clr_sts |= IPA_DROP_PACKET_INTR_CLR_BIT; - - if (int_status & IPA_INT_TXFIFO_OVERFLOW_STS) - clr_sts |= IPA_TX_FIFO_OVERFLOW_CLR_BIT; - - if (int_status & IPA_INT_TXFIFO_FULL_INT_STS) - clr_sts |= IPA_TX_FIFO_FULL_INT_CLR_BIT; - - if (ipa_cfg->irq_cb) - ipa_cfg->irq_cb(ipa_cfg->priv, int_status, id); - else - pr_err("Don't register this fifo(%d) irq callback\n", id); - - ipa_phy_clear_int(ipa_cfg->fifo_reg_base, clr_sts); -} - -int sipa_int_callback_func(int evt, void *cookie) -{ - struct sipa_core *ipa = sipa_get_ctrl_pointer(); - - if (ipa->remote_ready) { - ipa_fifo_traverse_int_bit(SIPA_FIFO_PCIE_DL, - &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_DL]); - ipa_fifo_traverse_int_bit(SIPA_FIFO_PCIE_UL, - &ipa->cmn_fifo_cfg[SIPA_FIFO_PCIE_UL]); - } - - return 0; -} -EXPORT_SYMBOL(sipa_int_callback_func); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h b/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h deleted file mode 100644 index d578585..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_phy_v0/sipa_fifo_phy.h +++ /dev/null @@ -1,1413 +0,0 @@ -#ifndef _IPA_CP0_FIFO_PHY_H_ -#define _IPA_CP0_FIFO_PHY_H_ - -#include - -/* Common fifo reg */ -#define IPA_COMMON_RX_FIFO_DEPTH 0x00UL -#define IPA_COMMON_RX_FIFO_WR 0x04UL -#define IPA_COMMON_RX_FIFO_RD 0x08UL -#define IPA_COMMON_TX_FIFO_DEPTH 0x0CUL -#define IPA_COMMON_TX_FIFO_WR 0x10UL -#define IPA_COMMON_TX_FIFO_RD 0x14UL -#define IPA_COMMON_RX_FIFO_ADDRL 0x18UL -#define IPA_COMMON_RX_FIFO_ADDRH 0x1CUL -#define IPA_COMMON_TX_FIFO_ADDRL 0x20UL -#define IPA_COMMON_TX_FIFO_ADDRH 0x24UL -#define IPA_PERFETCH_FIFO_CTL 0x28UL -#define IPA_INT_GEN_CTL_TX_FIFO_VALUE 0x2CUL -#define IPA_INT_GEN_CTL_EN 0x30UL -#define IPA_DROP_PACKET_CNT 0x34UL -#define IPA_FLOW_CTRL_CONFIG 0x38UL -#define IPA_TX_FIFO_FLOW_CTRL 0x3CUL -#define IPA_RX_FIFO_FLOW_CTRL 0x40UL -#define IPA_RX_FIFO_FULL_NEG_PULSE_NUM 0x44UL -#define IPA_INT_GEN_CTL_CLR 0x48UL -#define IPA_INTR_RX_FIFO_FULL_ADDR_HIGH 0x4CUL -#define IPA_INTR_MEM_WR_ADDR_LOW 0x50UL -#define IPA_RXFIFO_FULL_MEM_WR_ADDR_LOW 0x54UL -#define IPA_INTR_MEM_WR_PATTERN 0x58UL -#define IPA_RX_FIFO_FULL_MEM_WR_PATTERN 0x5CUL -#define IPA_TX_FIFO_WR_INIT 0x60UL -#define IPA_COMMON_RX_FIFO_AXI_STS 0x64UL -#define IPA_ERRCODE_INT_ADDR_LOW 0x68UL -#define IPA_ERRCODE_INT_PATTERN 0x6CUL - -/* Fifo interrupt enable bit */ -#define IPA_TXFIFO_INT_THRESHOLD_ONESHOT_EN BIT(11) -#define IPA_TXFIFO_INT_THRESHOLD_SW_EN BIT(10) -#define IPA_TXFIFO_INT_DELAY_TIMER_SW_EN BIT(9) -#define IPA_TXFIFO_FULL_INT_EN BIT(8) -#define IPA_TXFIFO_OVERFLOW_EN BIT(7) -#define IPA_ERRORCODE_IN_TX_FIFO_EN BIT(6) -#define IPA_DROP_PACKET_OCCUR_INT_EN BIT(5) -#define IPA_RX_FIFO_INT_EXIT_FLOW_CTRL_EN BIT(4) -#define IPA_RX_FIFO_INT_ENTER_FLOW_CTRL_EN BIT(3) -#define IPA_TX_FIFO_INTR_SW_BIT_EN BIT(2) -#define IPA_TX_FIFO_THRESHOLD_EN BIT(1) -#define IPA_TX_FIFO_DELAY_TIMER_EN BIT(0) -#define IPA_INT_EN_BIT_GROUP 0x00000FFFUL - -/* Fifo interrupt status bit */ -#define IPA_INT_TX_FIFO_THRESHOLD_SW_STS BIT(22) -#define IPA_INT_EXIT_FLOW_CTRL_STS BIT(20) -#define IPA_INT_ENTER_FLOW_CTRL_STS BIT(19) -#define IPA_INT_TXFIFO_FULL_INT_STS BIT(18) -#define IPA_INT_TXFIFO_OVERFLOW_STS BIT(17) -#define IPA_INT_ERRORCODE_IN_TX_FIFO_STS BIT(16) -#define IPA_INT_INTR_BIT_STS BIT(15) -#define IPA_INT_THRESHOLD_STS BIT(14) -#define IPA_INT_DELAY_TIMER_STS BIT(13) -#define IPA_INT_DROP_PACKT_OCCUR BIT(12) -#define IPA_INT_STS_GROUP 0x5FF000UL - -/* Fifo interrupt clear bit */ -#define IPA_TX_FIFO_TIMER_CLR_BIT BIT(0) -#define IPA_TX_FIFO_THRESHOLD_CLR_BIT BIT(1) -#define IPA_TX_FIFO_INTR_CLR_BIT BIT(2) -#define IPA_ENTRY_FLOW_CONTROL_CLR_BIT BIT(3) -#define IPA_EXIT_FLOW_CONTROL_CLR_BIT BIT(4) -#define IPA_DROP_PACKET_INTR_CLR_BIT BIT(5) -#define IPA_ERROR_CODE_INTR_CLR_BIT BIT(6) -#define IPA_TX_FIFO_OVERFLOW_CLR_BIT BIT(7) -#define IPA_TX_FIFO_FULL_INT_CLR_BIT BIT(8) -#define IPA_INT_STS_CLR_GROUP 0x000001FFUL - -#define NODE_DESCRIPTION_SIZE 128UL - -/** - * Description: set rx fifo total depth. - * Input: - * @fifo_base: Need to set total depth of the fifo, - * the base address of the FIFO. - * @depth: the size of depth. - * return: - * 0: set successfully. - * non-zero: set failed. - * Note: - */ -static inline int ipa_phy_set_rx_fifo_total_depth(void __iomem *fifo_base, - u32 depth) -{ - u32 tmp; - - if (depth > 0xFFFF) - return -EINVAL; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - tmp &= 0x0000FFFFUL; - tmp |= (depth << 16); - writel_relaxed(tmp, fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - if ((tmp & 0xFFFF0000UL) == tmp) - return 0; - else - return -EINVAL; -} - -/** - * Description: get rx fifo total depth. - * Input: - * @fifo_base: Need to get total depth of the fifo, the base address of the - * FIFO. - * return: The size of toal depth. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_total_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - - return (tmp >> 16) & 0x0000FFFFUL; -} - -/** - * Description: get rx fifo filled depth. - * Input: - * @fifo_base: Need to get filled depth of the FIFO, the base address of the - * FIFO. - * return: - * TRUE: The size of rx filled depth - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_filled_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_DEPTH); - - return tmp & 0x0000FFFFUL; -} - -/** - * Description: get rx fifo full status. - * Input: - * @fifo_base: Need to get rx fifo full status of the FIFO, the base address - * of the FIFO. - * return: - * 1: rx fifo full. - * 0: rx fifo not full. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_full_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_WR); - - return tmp & 0x1UL; -} - -/** - * Description: update rx fifo write pointer. - * Input: - * @fifo_base: Need to update rx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update rx fifo write pointer successfully, - * non-zero: update rx fifo write pointer failed. - * Note: - */ -static inline int ipa_phy_update_rx_fifo_wptr(void __iomem *fifo_base, - u32 wptr) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_RX_FIFO_WR; - - if (wptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (wptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp >> 16) == wptr) - return 0; - else - return -EIO; -} - -/** - * Description: get rx fifo write pointer. - * Input: - * @fifo_base: Need to get rx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * The write pointer of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_wptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_WR); - - return (tmp >> 16); -} - -/** - * Description: update rx fifo read pointer. - * Input: - * @fifo_base: Need to update rx fifo read pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update rx fifo read pointer successfully, - * non-zero: update rx fifo read pointer failed. - * Note: - */ -static inline int ipa_phy_update_rx_fifo_rptr(void __iomem *fifo_base, - u32 rptr) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_RX_FIFO_RD; - - if (rptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (rptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == rptr) - return 0; - else - return -EIO; -} - -/** - * Description: get rx fifo read pointer. - * Input: - * @fifo_base: Need to get rx fifo read pointer of the FIFO, the base - * address of the FIFO. - * return: - * The read pointer of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_rptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_RD); - - return (tmp >> 16); -} - -/** - * Description: get rx fifo empty status. - * Input: - * @fifo_base: Need to get rx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * The empty status of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_empty_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_RD); - - return tmp & 0x1UL; -} - -/** - * Description: set tx fifo total depth. - * Input: - * @fifo_base: Need to set tx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * 0: set tx fifo total depth successfully. - * non-zero: set tx fifo total_depth failed. - * Note: - */ -static inline int ipa_phy_set_tx_fifo_total_depth(void __iomem *fifo_base, - u32 depth) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_TX_FIFO_DEPTH; - - if (depth > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (depth << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp >> 16) == depth) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo total depth. - * Input: - * @fifo_base: Need to get tx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * The total depth of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_total_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_DEPTH); - - return ((tmp >> 16) & 0x0000FFFF); -} - -/** - * Description: get tx fifo filled depth. - * Input: - * @fifo_base: Need to get tx fifo filled depth of the FIFO, the base - * address of the FIFO. - * return: - * The tx fifo filled depth. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_filled_depth(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_DEPTH); - - return (tmp & 0x0000FFFFUL); -} - -/** - * Description: get tx fifo full status. - * Input: - * @fifo_base: Need to get tx fifo full status of the FIFO, the base - * address of the FIFO. - * return: - * The full status of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_full_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_WR); - - return (tmp & 0x1UL); -} - -/** - * Description: get tx fifo empty status. - * Input: - * @fifo_base: Need to get tx fifo empty status of the FIFO, the base - * address of the FIFO. - * return: - * The empty status of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_empty_status(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_RD); - - return (tmp & 0x1UL); -} - -/** - * Description: update tx fifo write pointer. - * Input: - * @fifo_base: Need to update tx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update tx fifo write pointer successfully. - * non-zero: update tx fifo write pointer failed. - * Note: - */ -static inline int ipa_phy_update_tx_fifo_wptr(void __iomem *fifo_base, - u32 wptr) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_TX_FIFO_WR_INIT; - - if (wptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (wptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= 0x2; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFFDUL; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == wptr) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo write pointer. - * Input: - * @fifo_base: Need to get tx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * The write pointer of tx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_wptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_WR); - - return (tmp >> 16); -} - -/** - * Description: update tx fifo read pointer. - * Input: - * @fifo_base: Need to update tx fifo read pointer of the FIFO, the base - * address of the FIFO. - * return: - * 0: update tx fifo read pointer successfully. - * non-zero: update tx fifo read pointer failed. - * Note: - */ -static inline int ipa_phy_update_tx_fifo_rptr(void __iomem *fifo_base, - u32 rptr) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_COMMON_TX_FIFO_RD; - - if (rptr > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFF; - tmp |= (rptr << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == rptr) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo write pointer. - * Input: - * @fifo_base: Need to get tx fifo write pointer of the FIFO, the base - * address of the FIFO. - * return: - * The write pointer of rx fifo. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_rptr(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_RD); - - return (tmp >> 16); -} - -/** - * Description: set rx fifo address of iram. - * Input: - * @fifo_base: Need to set rx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * 0: update rx fifo address of iram successfully. - * non-zero: update rx fifo address of iram failed. - * Note: - */ -static inline int ipa_phy_set_rx_fifo_addr(void __iomem *fifo_base, - u32 addr_l, u32 addr_h) -{ - u32 tmp_l, tmp_h; - - writel_relaxed(addr_l, fifo_base + IPA_COMMON_RX_FIFO_ADDRL); - writel_relaxed(addr_h, fifo_base + IPA_COMMON_RX_FIFO_ADDRH); - - tmp_l = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRL); - tmp_h = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRH); - - if ((tmp_l == addr_l) && (tmp_h == addr_h)) - return 0; - else - return -EIO; -} - -/** - * Description: get rx fifo address of iram. - * Input: - * @fifo_base: Need to get rx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * void. - * Note: - */ -static inline void ipa_phy_get_rx_fifo_addr(void __iomem *fifo_base, - u32 *addr_l, u32 *addr_h) -{ - *addr_l = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRL); - *addr_h = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_ADDRH); -} - -/** - * Description: set tx fifo address of iram. - * Input: - * @fifo_base: Need to set tx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * 0: update tx fifo address of iram successfully. - * non-zero: update tx fifo address of iram failed. - * Note: - */ -static inline int ipa_phy_set_tx_fifo_addr(void __iomem *fifo_base, - u32 addr_l, u32 addr_h) -{ - u32 tmp_l, tmp_h; - - writel_relaxed(addr_l, fifo_base + IPA_COMMON_TX_FIFO_ADDRL); - writel_relaxed(addr_h, fifo_base + IPA_COMMON_TX_FIFO_ADDRH); - - tmp_l = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRL); - tmp_h = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRH); - - if ((tmp_l == addr_l) && (tmp_h == addr_h)) - return 0; - else - return -EIO; -} - -/** - * Description: get tx fifo address of iram. - * Input: - * @fifo_base: Need to get tx fifo address of the FIFO, the base - * address of the FIFO. - * @addr_l: low 32 bit. - * @addr_h: high 8 bit. - * return: - * void. - * Note: - */ -static inline void ipa_phy_get_tx_fifo_addr(void __iomem *fifo_base, - u32 *addr_l, u32 *addr_h) -{ - *addr_l = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRL); - *addr_h = readl_relaxed(fifo_base + IPA_COMMON_TX_FIFO_ADDRH); -} - -/** - * Description: Enable interrupt bit. - * Input: - * @fifo_base: Need to enable interrupr bit of the FIFO, the base - * address of the FIFO. - * @int_bit: The interrupt bit that need to enable. - * return: - * 0: Enable successfully. - * non-zero: Enable successfully. - * Note: - */ -static inline int ipa_phy_enable_int_bit(void __iomem *fifo_base, - u32 int_bit) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_EN; - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= int_bit; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & int_bit) == int_bit) - return 0; - else - return -EIO; -} - -/** - * Description: Disable interrupt bit. - * Input: - * @fifo_base: Need to Disable interrupr bit of the FIFO, the base - * address of the FIFO. - * @int_bit: The interrupt bit that need to disable. - * return: - * 0: Disable successfully. - * non-zero: Disable failed. - * Note: - */ -static inline int ipa_phy_disable_int_bit(void __iomem *fifo_base, - u32 int_bit) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_EN; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= (~int_bit); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= int_bit; - - if (tmp) { - pr_err("Disable interrupt bit = 0x%x set failed!\n", - int_bit); - return -EIO; - } - - return 0; -} - -static inline u32 ipa_phy_get_all_intr_enable_status(void __iomem *fifo_base) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_EN; - - tmp = readl_relaxed(fifo_reg_addr); - - tmp &= IPA_INT_EN_BIT_GROUP; - - return tmp; -} - -/** - * Description: Get specified interrupt bit status. - * Input: - * @fifo_base: Need to get interrupt bit of the FIFO, the base - * address of the FIFO. - * @int_bit: The specified interrupt bit that need to get. - * return: - * 0: interrupt bit enable. - * non-zero: interrupt bit disable. - * Note: - */ -static inline int ipa_phy_get_fifo_int_sts(void __iomem *fifo_base, u32 sts) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_EN); - - if (tmp & sts) - return 0; - else - return -EIO; -} - -/** - * Description: Get interrupt group status. - * Input: - * @fifo_base: Need to get interrupt group status of the FIFO, the base - * address of the FIFO. - * return: - * Interrupt group status. - * Note: - */ -static inline u32 ipa_phy_get_fifo_all_int_sts(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_EN); - - return (tmp & IPA_INT_STS_GROUP); -} - -/** - * Description: Clear interrupt flag, need to write 1, then write 0. - * Input: - * @fifo_base: Need to clear interrupt flag of the FIFO, the base - * address of the FIFO. - * return: - * void. - * Note: - */ -static inline void ipa_phy_clear_int(void __iomem *fifo_base, u32 clr_bit) -{ - writel_relaxed(clr_bit, fifo_base + IPA_INT_GEN_CTL_CLR); -} - -/** - * Description: Get drop packet count. - * Input: - * @fifo_base: Need to get drop packet count of the FIFO, the base - * address of the FIFO. - * return: - * Drop packet count. - * Note: - */ -static inline u32 ipa_phy_get_drop_packet_cnt(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_DROP_PACKET_CNT); - - return tmp; -} - -/** - * Description: Get tx fifo threshold interrupt. - * Input: - * @fifo_base: Need to get threshold interrupt of the FIFO, the base - * address of the FIFO. - * OUTPUT: - * threshold value. - * Note: - */ -static inline u32 ipa_phy_get_tx_fifo_interrupt_threshold(void __iomem - *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE); - - return (tmp >> 16); -} - -/** - * Description: Set tx fifo interrupt threshold of value. - * Input: - * @fifo_base: Need to get threshold interrupt value of the FIFO, the base - * address of the FIFO. - * return: - * TRUE: set successfully. - * FALSE: set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_interrupt_threshold(void __iomem *fifo_base, u32 threshold) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE; - - if (threshold > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (threshold << 16); - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == threshold) - return 0; - else - return -EIO; -} - -/** - * Description: Get tx fifo interrupt of delay timer value. - * Input: - * @fifo_base: Need to get delay timer interrupt of the FIFO, the base - * address of the FIFO. - * OUTPUT: - * delay timer value. - * Note: - */ -static inline u32 -ipa_phy_get_tx_fifo_interrupt_delay_timer(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE); - - return (tmp & 0x0000FFFFUL); -} - -/** - * Description: Set tx fifo interrupt of delay timer value. - * Input: - * @fifo_base: Need to set delay timer interrupt of the FIFO, the base - * address of the FIFO. - * @threshold: The overflow value that need to set. - * return: - * 0: Set successfully. - * non-zero: set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_interrupt_delay_timer(void __iomem *fifo_base, - u32 threshold) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_INT_GEN_CTL_TX_FIFO_VALUE; - - if (threshold > 0xFFFFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFF0000UL; - tmp |= threshold; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & 0x0000FFFF) == threshold) - return 0; - else - return -EIO; -} - -/** - * Description: Get current term number. - * Input: - * @fifo_base: Need to get current term number of the FIFO, the base - * address of the FIFO. - * return: - * Current term number. - * Note: - */ -static inline u32 ipa_phy_get_cur_term_num(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return ((tmp & 0x0003E000UL) >> 13); -} - -/** - * Description: Set current term number. - * Input: - * @fifo_base: Need to set current term number of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_cur_term_num(void __iomem *fifo_base, - u32 num) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_PERFETCH_FIFO_CTL; - - if (num > 0x1FUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFC1FFFUL; - tmp |= (num << 13); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (((tmp & 0x0003E000) >> 13) == num) - return 0; - else - return -EIO; -} - -/** - * Description: Get dst term number. - * Input: - * @fifo_base: Need to get dst term number of the FIFO, the base - * address of the FIFO. - * return: - * Dst term number. - * Note: - */ -static inline u32 ipa_phy_get_dst_term_num(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return ((tmp & 0x00001F00UL) >> 8); -} - -/** - * Description: Set dst term number. - * Input: - * @fifo_base: Need to set dst term number of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_dst_term_num(void __iomem *fifo_base, - u32 num) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_PERFETCH_FIFO_CTL; - if (num > 0x1FUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFE0FFUL; - tmp |= (num << 8); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (((tmp & 0x00001F00UL) >> 8) == num) - return 0; - else - return -EIO; -} - -/** - * Description: Get prefetch fifo priority. - * Input: - * @fifo_base: Need to get prefetch fifo priority of the FIFO, the base - * address of the FIFO. - * return: - * Prefetch fifo priority. - * Note: - */ -static inline u32 ipa_phy_get_prefetch_fifo_priority(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return ((tmp & 0x000000F0UL) >> 4); -} - -/** - * Description: Set prefetch fifo priority. - * Input: - * @fifo_base: Need to set prefetch fifo priority of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_prefetch_fifo_priority(void __iomem *fifo_base, - u32 pri) -{ - u32 tmp = 0; - void __iomem *fifo_reg_base; - - fifo_reg_base = fifo_base + IPA_PERFETCH_FIFO_CTL; - - if (pri > 0xFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_base); - tmp &= 0xFFFFFF0FUL; - tmp |= (pri << 4); - writel_relaxed(tmp, fifo_reg_base); - - tmp = readl_relaxed(fifo_reg_base); - if (((tmp & 0x000000F0UL) >> 4) == pri) - return 0; - else - return -EIO; -} - -/** - * Description: Get prefetch threshold. - * Input: - * @fifo_base: Need to get prefetch threshold of the FIFO, the base - * address of the FIFO. - * return: - * Prefetch threshold. - * Note: - */ -static inline u32 ipa_phy_get_prefetch_threshold(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_PERFETCH_FIFO_CTL); - - return (tmp & 0xFUL); -} - -/** - * Description: Set prefetch threshold. - * Input: - * @fifo_base: Need to get threshold of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_prefetch_threshold(void __iomem *fifo_base, - u32 threshold) -{ - u32 tmp = 0; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_PERFETCH_FIFO_CTL; - - if (threshold > 0xFUL) - return -EINVAL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFF0UL; - tmp |= threshold; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp & 0xFUL) == threshold) - return 0; - else - return -EIO; -} - -/** - * Description: Set stop receive bit. - * Input: - * @fifo_base: Need to set stop receive bit of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_stop_receive(void __iomem *fifo_base) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= 0x8; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (tmp & 0x8) - return 0; - else - return -EIO; -} - -/** - * Description: Clear stop receive bit. - * Input: - * @fifo_base: Need to clear stop receive bit of the FIFO, the base - * address of the FIFO. - * return: - * 0: clear successfully. - * non-zero: clear failed. - * Note: - */ -static inline int ipa_phy_clear_stop_receive(void __iomem *fifo_base) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFF7; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if (!(tmp & 0x8)) - return 0; - else - return -EIO; -} - -/** - * Description: recover fifo work. - * Input: - * @fifo_base: Need to be recovered of the FIFO, the base - * address of the FIFO. - * return: - * 0: Recover successfully. - * non-zero: Recover failed. - * Note: - */ -static inline int ipa_phy_flow_ctrl_recover(void __iomem *fifo_base) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp |= 0x4UL; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (tmp & 0x4UL) { - tmp &= 0xFFFFFFFBUL; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if (!(tmp & 0x4UL)) - return 0; - else - return -EIO; - } else { - return -EINVAL; - } -} - -/** - * Description: Set flow ctrl mode. - * Input: - * @fifo_base: Need to set flow ctrl mode of the FIFO, the base - * address of the FIFO. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int ipa_phy_set_flow_ctrl_config(void __iomem *fifo_base, - u32 config) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_FLOW_CTRL_CONFIG; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFFFFFC; - tmp |= config; - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp & 0x00000003) == config) - return 0; - else - return -EIO; -} - -/** - * Description: Get flow ctrl mode. - * Input: - * @fifo_base: Need to get flow ctrl mode of the FIFO, the base - * address of the FIFO. - * return: - * Flow ctrl config - * Note: - */ -static inline u32 ipa_phy_get_flow_ctrl_config(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_FLOW_CTRL_CONFIG); - - return (tmp & 0x00000003); -} - -/** - * Description: Set tx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The need to be set. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_TX_FIFO_FLOW_CTRL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (watermark << 16); - writel_relaxed(tmp, fifo_reg_addr); - - tmp = readl_relaxed(fifo_reg_addr); - if ((tmp >> 16) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get tx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * Tx fifo exit watermark. - * Note: - */ -static inline u32 -ipa_phy_get_tx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_TX_FIFO_FLOW_CTRL); - - return (tmp >> 16); -} - -/** - * Description: Set tx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The need to be set. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int -ipa_phy_set_tx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_TX_FIFO_FLOW_CTRL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFF0000UL; - tmp |= watermark; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & 0x0000FFFFUL) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get tx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * @The value of tx fifo entry watermark. - * Note: - */ -static inline u32 -ipa_phy_get_tx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_TX_FIFO_FLOW_CTRL); - - return (tmp & 0x0000FFFF); -} - -/** - * Description: Set rx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The value of rx fifo exit watermark. - * return: - * 0: Set successfully. - * non-zero: Set failed. - * Note: - */ -static inline int -ipa_phy_set_rx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_RX_FIFO_FLOW_CTRL; - - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0x0000FFFFUL; - tmp |= (watermark << 16); - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp >> 16) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get rx fifo exit flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * The value of rx fifo exit watermark. - * Note: - */ -static inline u32 -ipa_phy_get_rx_fifo_exit_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_RX_FIFO_FLOW_CTRL); - - return (tmp >> 16); -} - -/** - * Description: Set rx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be set of the FIFO, the base - * address of the FIFO. - * @watermark: The value of rx fifo entry watermark. - * return: - * TRUE: Set successfully. - * FALSE: Set failed. - * Note: - */ -static inline int -ipa_phy_set_rx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base, - u32 watermark) -{ - u32 tmp; - void __iomem *fifo_reg_addr; - - fifo_reg_addr = fifo_base + IPA_RX_FIFO_FLOW_CTRL; - tmp = readl_relaxed(fifo_reg_addr); - tmp &= 0xFFFF0000UL; - tmp |= watermark; - writel_relaxed(tmp, fifo_reg_addr); - tmp = readl_relaxed(fifo_reg_addr); - - if ((tmp & 0x0000FFFFUL) == watermark) - return 0; - else - return -EIO; -} - -/** - * Description: Get rx fifo entry flow ctrl watermark. - * Input: - * @fifo_base: Need to be get of the FIFO, the base - * address of the FIFO. - * return: - * The value of rx fifo entry watermark. - * Note: - */ -static inline u32 -ipa_phy_get_rx_fifo_entry_flow_ctrl_watermark(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_RX_FIFO_FLOW_CTRL); - - return (tmp & 0x0000FFFF); -} - -/** - * Description: Get rx_axi_read_cmd_sts - * return: - * rx_axi_read_cmd_sts. - * Note: - */ -static inline u32 ipa_phy_get_rx_fifo_axi_sts(void __iomem *fifo_base) -{ - u32 tmp; - - tmp = readl_relaxed(fifo_base + IPA_COMMON_RX_FIFO_AXI_STS); - - return (tmp & 0x00000003); -} -#endif diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c b/quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c deleted file mode 100644 index 63c60b9..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_skb_recv.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Copyright (C) 2020 Unisoc Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - - -#include "../include/sipa.h" -#include "sipa_core.h" -#include "sipa_eth.h" - -#define SIPA_RECV_BUF_LEN 1600 -#define SIPA_RECV_RSVD_LEN 128 - -static int put_recv_array_node(struct sipa_skb_array *p, - struct sk_buff *skb, u64 *dma_addr) -{ - u32 pos; - - if ((p->wp - p->rp) < p->depth) { - pos = p->wp & (p->depth - 1); - p->array[pos].skb = skb; - p->array[pos].dma_addr = *dma_addr; - /* - * Ensure that we put the item to the fifo before - * we update the fifo wp. - */ - smp_wmb(); - p->wp++; - return 0; - } else { - return -1; - } -} - -static int get_recv_array_node(struct sipa_skb_array *p, - struct sk_buff **skb, u64 *dma_addr) -{ - u32 pos; - - if (p->rp != p->wp) { - pos = p->rp & (p->depth -1); - *skb = p->array[pos].skb; - *dma_addr = p->array[pos].dma_addr; - /* - * Ensure that we remove the item from the fifo before - * we update the fifo rp. - */ - smp_wmb(); - p->rp++; - return 0; - } else { - return -1; - } -} - -static int create_recv_array(struct sipa_skb_array *p, u32 depth) -{ - p->array = kzalloc(sizeof(*p->array) * depth, - GFP_KERNEL); - if (!p->array) - return -ENOMEM; - p->rp = 0; - p->wp = 0; - p->depth = depth; - - return 0; -} - -static void destroy_recv_array(struct sipa_skb_array *p) -{ - kfree(p->array); - - p->array = NULL; - p->rp = 0; - p->wp = 0; - p->depth = 0; -} - -static struct sk_buff *alloc_recv_skb(u32 req_len, u8 rsvd) -{ - struct sk_buff *skb; - u32 hr; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - skb = __dev_alloc_skb(req_len + rsvd, GFP_KERNEL | GFP_NOWAIT); - if (!skb) { - dev_err(ctrl->dev, "failed to alloc skb!\n"); - return NULL; - } - - /* save skb ptr to skb->data */ - hr = skb_headroom(skb); - if (hr < rsvd) - skb_reserve(skb, rsvd - hr); - - return skb; -} - -static void sipa_prepare_free_node_init(struct sipa_skb_receiver *receiver, - u32 cnt) -{ - struct sk_buff *skb; - u32 tmp, fail_cnt = 0; - int i; - u32 success_cnt = 0; - u64 dma_addr; - struct sipa_node_description_tag *node; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node_tmp; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *cmn = receiver->ep->recv_fifo; - - for (i = 0; i < cnt; i++) { - skb = alloc_recv_skb(SIPA_RECV_BUF_LEN, receiver->rsvd); - if (!skb) { - fail_cnt++; - break; - } - - tmp = skb_headroom(skb); - if (unlikely(tmp > SIPA_RECV_RSVD_LEN)) { - tmp -= SIPA_RECV_RSVD_LEN; - skb_put(skb, SIPA_RECV_BUF_LEN - tmp); - skb_push(skb, tmp); - } else { - skb_put(skb, SIPA_RECV_BUF_LEN); - } - - dma_addr = (u64)dma_map_single(ctrl->pci_dev, - skb->head, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - if (dma_mapping_error(ctrl->pci_dev, (dma_addr_t)dma_addr)) { - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "prepare free node dma map err\n"); - fail_cnt++; - break; - } - - node = ctrl->hal_ops.get_rx_fifo_wr(cmn->fifo_id, - ctrl->cmn_fifo_cfg, - i); - if (!node) { - dma_unmap_single(ctrl->pci_dev, dma_addr, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "get node fail index = %d\n", i); - fail_cnt++; - break; - } - - dma_addr += ctrl->pcie_mem_offset; -#if defined (__BIG_ENDIAN_BITFIELD) - memset(&node_tmp, 0, sizeof(node_tmp)); - node_tmp.address = dma_addr; - node_tmp.length = skb->len; - node_tmp.offset = skb_headroom(skb); - node_tmp.dst = ctrl->ep.recv_fifo->dst; - node_tmp.src = ctrl->ep.recv_fifo->cur; - node_tmp.intr = 0; - node_tmp.net_id = 0; - node_tmp.err_code = 0; - sipa_set_node_desc((u8 *)node, (u8 *)&node_tmp); -#else - node->address = dma_addr; - node->length = skb->len; - node->offset = skb_headroom(skb); - node->dst = ctrl->ep.recv_fifo->dst; - node->src = ctrl->ep.recv_fifo->cur; - node->intr = 0; - node->net_id = 0; - node->err_code = 0; -#endif - if (dma_addr == 0 || node->address == 0) - pr_info("cnt = %d, i = %d, dma_addr 0x%llx, node->address 0x%llx\n", - cnt, i, dma_addr, (long long unsigned int)node->address); - put_recv_array_node(&receiver->recv_array, skb, &dma_addr); - success_cnt++; - } - if (fail_cnt) - dev_err(ctrl->dev, - "fail_cnt = %d success_cnt = %d\n", - fail_cnt, success_cnt); -} - -static void fill_free_fifo(struct sipa_skb_receiver *receiver, u32 cnt) -{ - struct sk_buff *skb; - u32 tmp, fail_cnt = 0; - int i; - u32 success_cnt = 0, depth; - u64 dma_addr; - struct sipa_node_description_tag *node; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node_tmp; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *cmn = receiver->ep->recv_fifo; - - depth = cmn->rx_fifo.depth; - if (cnt > (depth - depth / 4)) { -// dev_warn(ctrl->dev, "free node is not enough,need fill %d\n", cnt); - receiver->rx_danger_cnt++; - } - - for (i = 0; i < cnt; i++) { - skb = alloc_recv_skb(SIPA_RECV_BUF_LEN, receiver->rsvd); - if (!skb) { - fail_cnt++; - break; - } - - tmp = skb_headroom(skb); - if (unlikely(tmp > SIPA_RECV_RSVD_LEN)) { - tmp -= SIPA_RECV_RSVD_LEN; - skb_put(skb, SIPA_RECV_BUF_LEN - tmp); - skb_push(skb, tmp); - } else { - skb_put(skb, SIPA_RECV_BUF_LEN); - } - - dma_addr = (u64)dma_map_single(ctrl->pci_dev, - skb->head, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - if (dma_mapping_error(ctrl->pci_dev, (dma_addr_t)dma_addr)) { - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "prepare free node dma map err\n"); - fail_cnt++; - break; - } - node = ctrl->hal_ops.get_rx_fifo_wr(cmn->fifo_id, - ctrl->cmn_fifo_cfg, - i); - if (!node) { - dma_unmap_single(ctrl->pci_dev, dma_addr, - SIPA_RECV_BUF_LEN + - skb_headroom(skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(skb); - dev_err(ctrl->dev, - "get node fail index = %d\n", i); - fail_cnt++; - break; - } - - dma_addr += ctrl->pcie_mem_offset; -#if defined (__BIG_ENDIAN_BITFIELD) - memset(&node_tmp, 0, sizeof(node_tmp)); - node_tmp.address = dma_addr; - node_tmp.length = skb->len; - node_tmp.offset = skb_headroom(skb); - node_tmp.dst = ctrl->ep.recv_fifo->dst; - node_tmp.src = ctrl->ep.recv_fifo->cur; - node_tmp.intr = 0; - node_tmp.net_id = 0; - node_tmp.err_code = 0; - sipa_set_node_desc((u8 *)node, (u8 *)&node_tmp); -#else - node->address = dma_addr; - node->length = skb->len; - node->offset = skb_headroom(skb); - node->dst = ctrl->ep.recv_fifo->dst; - node->src = ctrl->ep.recv_fifo->cur; - node->intr = 0; - node->net_id = 0; - node->err_code = 0; -#endif - - put_recv_array_node(&receiver->recv_array, skb, &dma_addr); - success_cnt++; - } - - if (success_cnt) { - ctrl->hal_ops.set_rx_fifo_wr(ctrl->pci_dev, - cmn->fifo_id, - ctrl->cmn_fifo_cfg, - success_cnt); - if (atomic_read(&receiver->need_fill_cnt) > 0) - atomic_sub(success_cnt, - &receiver->need_fill_cnt); - } - - if (fail_cnt) - dev_err(ctrl->dev, - "fill free fifo fail_cnt = %d\n", fail_cnt); -} - -static void sipa_fill_free_node(struct sipa_skb_receiver *receiver, u32 cnt) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - ctrl->hal_ops.set_rx_fifo_wr(ctrl->pci_dev, - receiver->ep->recv_fifo->fifo_id, - ctrl->cmn_fifo_cfg, cnt); - - if (atomic_read(&receiver->need_fill_cnt) > 0) - dev_info(ctrl->dev, - "a very serious problem, mem cover may appear\n"); - - atomic_set(&receiver->need_fill_cnt, 0); -} - -static void sipa_receiver_notify_cb(void *priv, enum sipa_irq_evt_type evt, - unsigned long data) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_skb_receiver *receiver = (struct sipa_skb_receiver *)priv; - - if (evt & SIPA_RECV_WARN_EVT) { - dev_dbg(ctrl->dev, - "sipa maybe poor resources evt = 0x%x\n", evt); - receiver->tx_danger_cnt++; - } - - sipa_dummy_recv_trigger(); -} - -static void sipa_free_recv_skb(struct sipa_skb_receiver *receiver) -{ - u64 addr = 0; - struct sk_buff *recv_skb = NULL; - while(!get_recv_array_node(&receiver->recv_array, &recv_skb, &addr)) - { - dev_kfree_skb_any(recv_skb); - } -} - -struct sk_buff *sipa_recv_skb(int *netid, int index) -{ - int ret = -1; - u32 retry_cnt = 10; - u64 addr = 0; - struct sk_buff *recv_skb = NULL; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node; -#else - struct sipa_node_description_tag *node; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_skb_receiver *receiver = ctrl->receiver; - enum sipa_cmn_fifo_index id = receiver->ep->recv_fifo->fifo_id; - - ret = get_recv_array_node(&receiver->recv_array, - &recv_skb, &addr); -read_again: -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, index), &node); -#else - node = ctrl->hal_ops.get_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, index); -#endif - -#if defined (__BIG_ENDIAN_BITFIELD) - if (!node.address) { -#else - if (!node->address) { -#endif - if (retry_cnt--) { - udelay(1); - goto read_again; - } - -#if defined (__BIG_ENDIAN_BITFIELD) - dev_err(ctrl->dev, "phy addr is null = %llx\n", - (u64)node.address); -#else - dev_err(ctrl->dev, "phy addr is null = %llx\n", - (u64)node->address); -#endif - if(!ret) { - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(addr - ctrl->pcie_mem_offset), - SIPA_RECV_BUF_LEN + skb_headroom(recv_skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(recv_skb); - atomic_add(1, &receiver->need_fill_cnt); - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, 1); - dev_err(ctrl->dev, - "recv addr is null, but recv_array addr:0x%llx\n", - addr); - } - return NULL; - } - - retry_cnt = 10; -check_again: - if (ret) { -#if defined (__BIG_ENDIAN_BITFIELD) - dev_err(ctrl->dev, - "recv addr:0x%llx, but recv_array is empty\n", - (u64)node.address); -#else - dev_err(ctrl->dev, - "recv addr:0x%llx, but recv_array is empty\n", - (u64)node->address); -#endif - return NULL; -#if defined (__BIG_ENDIAN_BITFIELD) - } else if (addr != node.address && retry_cnt) { -#else - } else if (addr != node->address && retry_cnt) { -#endif - retry_cnt--; - udelay(1); -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, index), &node); -#endif - goto check_again; -#if defined (__BIG_ENDIAN_BITFIELD) - } else if (addr != node.address && !retry_cnt) { -#else - } else if (addr != node->address && !retry_cnt) { -#endif - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(addr - ctrl->pcie_mem_offset), - SIPA_RECV_BUF_LEN + skb_headroom(recv_skb), - DMA_FROM_DEVICE); - dev_kfree_skb_any(recv_skb); - atomic_add(1, &receiver->need_fill_cnt); - dev_err(ctrl->dev, - "recv addr:0x%llx, but recv_array addr:0x%llx not equal\n", -#if defined (__BIG_ENDIAN_BITFIELD) - (u64)node.address, addr); -#else - (u64)node->address, addr); -#endif - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, 1); - return NULL; - } - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(addr - ctrl->pcie_mem_offset), - SIPA_RECV_BUF_LEN + skb_headroom(recv_skb), - DMA_FROM_DEVICE); - - atomic_add(1, &receiver->need_fill_cnt); - if (atomic_read(&receiver->need_fill_cnt) > 0x30) - wake_up(&receiver->fill_recv_waitq); - -#if defined (__BIG_ENDIAN_BITFIELD) - *netid = node.net_id; -#else - *netid = node->net_id; -#endif - return recv_skb; -} -EXPORT_SYMBOL(sipa_recv_skb); - -static int fill_recv_thread(void *data) -{ - int ret; - struct sipa_skb_receiver *receiver = (struct sipa_skb_receiver *)data; - struct sched_param param = {.sched_priority = 92}; - unsigned long flags; - - sched_setscheduler(current, SCHED_RR, ¶m); - - while (!kthread_should_stop()) { - ret = wait_event_interruptible(receiver->fill_recv_waitq, - (atomic_read(&receiver->need_fill_cnt) > 0) || receiver->run == 0); - spin_lock_irqsave(&receiver->exit_lock, flags); - if(receiver->run == 0) { - spin_unlock_irqrestore(&receiver->exit_lock, flags); - break; - } - spin_unlock_irqrestore(&receiver->exit_lock, flags); - if (!ret) - fill_free_fifo(receiver, atomic_read(&receiver->need_fill_cnt)); - } - - sipa_free_recv_skb(receiver); - if (receiver->recv_array.array) - destroy_recv_array(&receiver->recv_array); - - kfree(receiver); - return 0; -} - -bool sipa_check_recv_tx_fifo_empty(void) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = ctrl->receiver->ep->recv_fifo->fifo_id; - - if (!ctrl->remote_ready) - return true; - - return ctrl->hal_ops.get_tx_empty_status(id, ctrl->cmn_fifo_cfg); -} -EXPORT_SYMBOL(sipa_check_recv_tx_fifo_empty); - -void sipa_receiver_open_cmn_fifo(struct sipa_skb_receiver *receiver) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *fifo_cfg = receiver->ep->recv_fifo; - - if (unlikely(!ctrl || !receiver)) { - pr_err("ctrl %p receiver %p not ready\n", ctrl, receiver); - return; - } - - ctrl->hal_ops.open(fifo_cfg->fifo_id, ctrl->cmn_fifo_cfg, NULL); - sipa_fill_free_node(receiver, fifo_cfg->rx_fifo.depth); - - ctrl->hal_ops.set_hw_intr_thres(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, - true, 64, NULL); - /* timeout = 1 / ipa_sys_clk * 1024 * value */ - ctrl->hal_ops.set_hw_intr_timeout(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, - true, 0x32, NULL); - -// ctrl->hal_ops.set_intr_txfifo_full(fifo_cfg->fifo_id, -// ctrl->cmn_fifo_cfg, -// true, NULL); -} -EXPORT_SYMBOL(sipa_receiver_open_cmn_fifo); - -static void sipa_receiver_init(struct sipa_skb_receiver *receiver, u32 rsvd) -{ - u32 depth; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index fifo_id = receiver->ep->recv_fifo->fifo_id; - - dev_info(ctrl->dev, - "fifo_id = %d rx_fifo depth = 0x%x\n", - receiver->ep->recv_fifo->fifo_id, - receiver->ep->recv_fifo->rx_fifo.depth); - - ctrl->cmn_fifo_cfg[fifo_id].irq_cb = - (sipa_irq_notify_cb)sipa_receiver_notify_cb; - ctrl->cmn_fifo_cfg[fifo_id].priv = receiver; - - /* reserve space for dma flushing cache issue */ - receiver->rsvd = rsvd; - depth = receiver->ep->recv_fifo->rx_fifo.depth; - - sipa_prepare_free_node_init(receiver, depth); -} - -void sipa_receiver_add_nic(struct sipa_skb_receiver *receiver, - struct sipa_nic *nic) -{ - int i; - unsigned long flags; - - for (i = 0; i < receiver->nic_cnt; i++) - if (receiver->nic_array[i] == nic) - return; - spin_lock_irqsave(&receiver->lock, flags); - if (receiver->nic_cnt < SIPA_NIC_MAX) - receiver->nic_array[receiver->nic_cnt++] = nic; - spin_unlock_irqrestore(&receiver->lock, flags); -} -EXPORT_SYMBOL(sipa_receiver_add_nic); - -void sipa_reinit_recv_array(struct sipa_skb_receiver *receiver) -{ - if (!receiver) { - pr_err("sipa receiver is null\n"); - return; - } - - if (!receiver->recv_array.array) { - pr_err("sipa p->array is null\n"); - return; - } - - receiver->recv_array.rp = 0; - receiver->recv_array.wp = receiver->recv_array.depth; -} - -int create_sipa_skb_receiver(struct sipa_endpoint *ep, - struct sipa_skb_receiver **receiver_pp) -{ - int ret; - struct sipa_skb_receiver *receiver = NULL; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - receiver = kzalloc(sizeof(*receiver), GFP_KERNEL); - if (!receiver) - return -ENOMEM; - - receiver->ep = ep; - receiver->rsvd = SIPA_RECV_RSVD_LEN; - - atomic_set(&receiver->need_fill_cnt, 0); - - ret = create_recv_array(&receiver->recv_array, - receiver->ep->recv_fifo->rx_fifo.depth); - if (ret) { - dev_err(ctrl->dev, - "create_sipa_sipa_receiver: recv_array kzalloc err.\n"); - kfree(receiver); - return -ENOMEM; - } - - spin_lock_init(&receiver->lock); - spin_lock_init(&receiver->exit_lock); - init_waitqueue_head(&receiver->fill_recv_waitq); - - sipa_receiver_init(receiver, SIPA_RECV_RSVD_LEN); - receiver->run = 1; - receiver->fill_thread = kthread_create(fill_recv_thread, receiver, - "sipa-fill"); - if (IS_ERR(receiver->fill_thread)) { - dev_err(ctrl->dev, "Failed to create kthread: ipa-fill\n"); - ret = PTR_ERR(receiver->fill_thread); - kfree(receiver->recv_array.array); - kfree(receiver); - return ret; - } - - wake_up_process(receiver->fill_thread); - - *receiver_pp = receiver; - return 0; -} -EXPORT_SYMBOL(create_sipa_skb_receiver); - -void destroy_sipa_skb_receiver(struct sipa_skb_receiver *receiver) -{ - unsigned long flags; - - spin_lock_irqsave(&receiver->exit_lock, flags); - receiver->run = 0; - wake_up_interruptible_all(&receiver->fill_recv_waitq); - spin_unlock_irqrestore(&receiver->exit_lock, flags); -} -EXPORT_SYMBOL(destroy_sipa_skb_receiver); diff --git a/quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c b/quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c deleted file mode 100644 index f70bd16..0000000 --- a/quectel_SRPD_PCIE/src/sipa/sipa_skb_send.c +++ /dev/null @@ -1,556 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - - -#include "sipa_phy_v0/sipa_fifo_phy.h" -#include "../include/sipa.h" -#include "sipa_core.h" -#include "sipa_eth.h" - -#define SIPA_RECEIVER_BUF_LEN 1600 - -static void sipa_inform_evt_to_nics(struct sipa_skb_sender *sender, - enum sipa_evt_type evt) -{ - - struct sipa_nic *nic; - unsigned long flags; - spin_lock_irqsave(&sender->nic_lock, flags); - - if(SIPA_LEAVE_FLOWCTRL == evt){ - if(sender->free_notify_net == true){ - pr_info("%s, not leave flowctl, free_notify_net is true\n", __func__); - return; - } - - if(sender->ep_cover_net == true){ - pr_info("%s, not leave flowctl, ep_cover_net is true\n", __func__); - return; - } - - pr_info("%s, leave flowctl\n", __func__); - list_for_each_entry(nic, &sender->nic_list, list) { - if (nic->flow_ctrl_status == true) { - nic->flow_ctrl_status = false; - sipa_nic_notify_evt(nic, evt); - } - } - }else{ - pr_info("%s, enter flowctl\n", __func__); - list_for_each_entry(nic, &sender->nic_list, list) { - if (nic->flow_ctrl_status == false) { - nic->flow_ctrl_status = true; - sipa_nic_notify_evt(nic, evt); - } - } - } - - spin_unlock_irqrestore(&sender->nic_lock, flags); -} - -static void sipa_sender_notify_cb(void *priv, enum sipa_irq_evt_type evt, - unsigned long data) -{ - unsigned long flags; - struct sipa_skb_sender *sender = (struct sipa_skb_sender *)priv; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - if (evt & SIPA_RECV_WARN_EVT) { - dev_err(ctrl->dev, - "sipa overflow on ep\n"); - sender->no_free_cnt++; - } - - if (evt & SIPA_IRQ_ENTER_FLOW_CTRL) { - spin_lock_irqsave(&sender->send_lock, flags); - pr_info("sipa_sender_notify_cb set ep_cover_net true!!!!!\n"); - sender->enter_flow_ctrl_cnt++; - sender->ep_cover_net = true; - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - } - - if (evt & SIPA_IRQ_EXIT_FLOW_CTRL) { - spin_lock_irqsave(&sender->send_lock, flags); - sender->exit_flow_ctrl_cnt++; - sender->ep_cover_net = false; - sipa_inform_evt_to_nics(sender, SIPA_LEAVE_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - } - wake_up(&sender->free_waitq); -} - -static void sipa_free_sent_items(struct sipa_skb_sender *sender) -{ - bool status = false; - unsigned long flags; - u32 i, num, success_cnt = 0, retry_cnt = 10, failed_cnt = 0; - struct sipa_skb_dma_addr_node *iter, *_iter; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag node; -#else - struct sipa_node_description_tag *node; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = sender->ep->send_fifo->fifo_id; - u32 tx_wr, tx_rd, rx_wr, rx_rd; - int exit_flow = 0; - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - void __iomem *fifo_base; - u32 clr_sts = 0; - u32 int_status = 0; - u32 read_count = 0; - - num = ctrl->hal_ops.recv_node_from_tx_fifo(ctrl->dev, id, - ctrl->cmn_fifo_cfg, -1); - for (i = 0; i < num; i++) { - retry_cnt = 10; -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, i), &node); -#else - node = ctrl->hal_ops.get_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, i); -#endif - -#if defined (__BIG_ENDIAN_BITFIELD) - if (node.err_code) - dev_err(ctrl->dev, "have node transfer err = %d\n", - node.err_code); -#else - if (node->err_code) - dev_err(ctrl->dev, "have node transfer err = %d\n", - node->err_code); -#endif - -check_again: - spin_lock_irqsave(&sender->send_lock, flags); - if (list_empty(&sender->sending_list)) { - ctrl->hal_ops.get_rx_ptr(SIPA_FIFO_PCIE_UL, ctrl->cmn_fifo_cfg, &rx_wr, &rx_rd); - ctrl->hal_ops.get_tx_ptr(SIPA_FIFO_PCIE_UL, ctrl->cmn_fifo_cfg, &tx_wr, &tx_rd); - dev_err(ctrl->dev, "fifo id %d: send list is empty, old tx_wr=%x tx_rd=%x, rx_wr=%x, rx_rd=%x, left_cnt=%d\n", - sender->ep->send_fifo->fifo_id, tx_wr, tx_rd, rx_wr, rx_rd, atomic_read(&sender->left_cnt)); - - spin_unlock_irqrestore(&sender->send_lock, flags); - goto sipa_free_end; - } - - list_for_each_entry_safe(iter, _iter, &sender->sending_list, list) { -#if defined (__BIG_ENDIAN_BITFIELD) - if (iter->dma_addr == node.address) { -#else - if (iter->dma_addr == node->address) { -#endif - list_del(&iter->list); - list_add_tail(&iter->list, - &sender->pair_free_list); - status = true; - break; - } - } - spin_unlock_irqrestore(&sender->send_lock, flags); - - if (status) { - dma_unmap_single(ctrl->pci_dev, - (dma_addr_t)(iter->dma_addr - ctrl->pcie_mem_offset), - iter->skb->len + - skb_headroom(iter->skb), - DMA_TO_DEVICE); - - dev_kfree_skb_any(iter->skb); - success_cnt++; - status = false; - } else { - if (retry_cnt--) { -#if defined (__BIG_ENDIAN_BITFIELD) - sipa_get_node_desc((u8 *)ctrl->hal_ops.get_tx_fifo_rp(id, - ctrl->cmn_fifo_cfg, i), &node); -#endif - //dev_err(ctrl->dev, "free send skb warning, retry_cnt = %d\n", retry_cnt); - goto check_again; - } - failed_cnt++; - } - } - if(failed_cnt >0){ - dev_err(ctrl->dev, "can't find matching nodes num=%d\n", failed_cnt); - } - - ctrl->hal_ops.set_tx_fifo_rp(id, ctrl->cmn_fifo_cfg, i); - atomic_add(success_cnt, &sender->left_cnt); - if (num != success_cnt) - dev_err(ctrl->dev, "recv num = %d release num = %d\n", num, success_cnt); - -sipa_free_end: - if (sender->free_notify_net && atomic_read(&sender->left_cnt) > sender->ep->send_fifo->rx_fifo.depth / 4) { - sender->free_notify_net = false; - exit_flow = 1; - } - - if(sender->ep_cover_net == true){ - fifo_cfg = ctrl->cmn_fifo_cfg + sender->ep->send_fifo->fifo_id; - fifo_base = fifo_cfg->fifo_reg_base; - - int_status = ipa_phy_get_fifo_all_int_sts(fifo_base); - - if (int_status & IPA_INT_EXIT_FLOW_CTRL_STS) { - exit_flow = 1; - sender->ep_cover_net = false; - clr_sts |= IPA_EXIT_FLOW_CONTROL_CLR_BIT; - ipa_phy_clear_int(fifo_base, clr_sts); - pr_info("%s, exit flow control\n", __func__); - }else{ - pr_info("%s, still in flow control\n", __func__); - } - } - - if(exit_flow == 1){ - spin_lock_irqsave(&sender->send_lock, flags); - sipa_inform_evt_to_nics(sender, SIPA_LEAVE_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - } -} - -static bool sipa_sender_ck_unfree(struct sipa_skb_sender *sender) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = sender->ep->send_fifo->fifo_id; - if (!ctrl->remote_ready) { - printk("%s: need wait remote_ready!\n", __func__); - return false; - } - - if (ctrl->hal_ops.get_tx_empty_status(id, ctrl->cmn_fifo_cfg)) { - ctrl->hal_ops.clr_tout_th_intr(id, ctrl->cmn_fifo_cfg); - ctrl->hal_ops.set_intr_eb(id, ctrl->cmn_fifo_cfg, true, - SIPA_FIFO_THRESHOLD_IRQ_EN | - SIPA_FIFO_DELAY_TIMER_IRQ_EN); - return false; - } else { - return true; - } -} - -static void sipa_free_send_skb(struct sipa_skb_sender *sender) -{ - struct sipa_skb_dma_addr_node *iter, *_iter; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - unsigned long flags; - - spin_lock_irqsave(&sender->send_lock, flags); - if (list_empty(&sender->sending_list)) { - dev_err(ctrl->dev, "fifo id %d: send list is empty\n", sender->ep->send_fifo->fifo_id); - spin_unlock_irqrestore(&sender->send_lock, flags); - return; - } - - list_for_each_entry_safe(iter, _iter, &sender->sending_list, list) { - list_del(&iter->list); - list_add_tail(&iter->list, &sender->pair_free_list); - dma_unmap_single(ctrl->pci_dev, (dma_addr_t)(iter->dma_addr - ctrl->pcie_mem_offset), - iter->skb->len + skb_headroom(iter->skb), DMA_TO_DEVICE); - dev_kfree_skb_any(iter->skb); - } - spin_unlock_irqrestore(&sender->send_lock, flags); -} - -static int sipa_free_thread(void *data) -{ - struct sipa_skb_sender *sender = (struct sipa_skb_sender *)data; - struct sched_param param = {.sched_priority = 90}; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - enum sipa_cmn_fifo_index id = sender->ep->send_fifo->fifo_id; - unsigned long flags; - struct sipa_nic *iter, *_iter; - sched_setscheduler(current, SCHED_RR, ¶m); - - while (!kthread_should_stop()) { - wait_event_interruptible(sender->free_waitq, - sender->free_notify_net || sender->run == 0 || sender->ep_cover_net || - sipa_sender_ck_unfree(sender)); - - spin_lock_irqsave(&sender->exit_lock, flags); - if(sender->run == 0) { - spin_unlock_irqrestore(&sender->exit_lock, flags); - break; - } - spin_unlock_irqrestore(&sender->exit_lock, flags); - sipa_free_sent_items(sender); - - if (!ctrl->hal_ops.get_tx_empty_status(id, ctrl->cmn_fifo_cfg)) { - usleep_range(100, 200); - //pr_info("%s, not empty\n", __func__); - } - } - - sipa_free_send_skb(sender); - kfree(sender->pair_cache); - - list_for_each_entry_safe(iter, _iter, &sender->nic_list, list) { - list_del(&iter->list); - kfree(iter); - } - - kfree(sender); - - return 0; -} - -void sipa_sender_open_cmn_fifo(struct sipa_skb_sender *sender) -{ - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *fifo_cfg = sender->ep->send_fifo; - - if (unlikely(!ctrl || !sender)) { - pr_err("ctrl %p sender %p not ready\n", ctrl, sender); - return; - } - - fifo_cfg->irq_cb = (sipa_irq_notify_cb)sipa_sender_notify_cb; - fifo_cfg->priv = sender; - ctrl->hal_ops.open(fifo_cfg->fifo_id, ctrl->cmn_fifo_cfg, NULL); - - ctrl->hal_ops.set_hw_intr_thres(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, true, - 128, NULL); - ctrl->hal_ops.set_hw_intr_timeout(fifo_cfg->fifo_id, ctrl->cmn_fifo_cfg, - true, 0x64, NULL); - - ctrl->hal_ops.set_intr_txfifo_full(fifo_cfg->fifo_id, - ctrl->cmn_fifo_cfg, true, NULL); -} -EXPORT_SYMBOL(sipa_sender_open_cmn_fifo); - -int create_sipa_skb_sender(struct sipa_endpoint *ep, - struct sipa_skb_sender **sender_pp) -{ - int i, ret; - struct sipa_skb_sender *sender = NULL; - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - - dev_info(ctrl->dev, "sender create start\n"); - sender = kzalloc(sizeof(*sender), GFP_KERNEL); - if (!sender) { - dev_err(ctrl->dev, "alloc sender failed\n"); - return -ENOMEM; - } - - sender->pair_cache = kcalloc(ep->send_fifo->rx_fifo.depth, - sizeof(struct sipa_skb_dma_addr_node), - GFP_KERNEL); - if (!sender->pair_cache) { - dev_err(ctrl->dev, "alloc sender->pair_cache fail\n"); - kfree(sender); - return -ENOMEM; - } - - INIT_LIST_HEAD(&sender->nic_list); - INIT_LIST_HEAD(&sender->sending_list); - INIT_LIST_HEAD(&sender->pair_free_list); - spin_lock_init(&sender->nic_lock); - spin_lock_init(&sender->send_lock); - spin_lock_init(&sender->exit_lock); - for (i = 0; i < ep->send_fifo->rx_fifo.depth; i++) - list_add_tail(&((sender->pair_cache + i)->list), - &sender->pair_free_list); - - sender->ep = ep; - - atomic_set(&sender->left_cnt, ep->send_fifo->rx_fifo.depth / 4 * 3); - - init_waitqueue_head(&sender->free_waitq); - sender->run = 1; - sender->free_thread = kthread_create(sipa_free_thread, sender, - "sipa-free"); - if (IS_ERR(sender->free_thread)) { - dev_err(ctrl->dev, "Failed to create kthread: ipa-free\n"); - ret = PTR_ERR(sender->free_thread); - kfree(sender->pair_cache); - kfree(sender); - return ret; - } - - *sender_pp = sender; - wake_up_process(sender->free_thread); - return 0; -} -EXPORT_SYMBOL(create_sipa_skb_sender); - -void destroy_sipa_skb_sender(struct sipa_skb_sender *sender) -{ - unsigned long flags; - - spin_lock_irqsave(&sender->exit_lock, flags); - sender->run = 0; - wake_up_interruptible_all(&sender->free_waitq); - spin_unlock_irqrestore(&sender->exit_lock, flags); -} -EXPORT_SYMBOL(destroy_sipa_skb_sender); - -void sipa_skb_sender_add_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&sender->nic_lock, flags); - list_add_tail(&nic->list, &sender->nic_list); - spin_unlock_irqrestore(&sender->nic_lock, flags); -} -EXPORT_SYMBOL(sipa_skb_sender_add_nic); - -void sipa_skb_sender_remove_nic(struct sipa_skb_sender *sender, - struct sipa_nic *nic) -{ - unsigned long flags; - - spin_lock_irqsave(&sender->nic_lock, flags); - list_del(&nic->list); - spin_unlock_irqrestore(&sender->nic_lock, flags); -} -EXPORT_SYMBOL(sipa_skb_sender_remove_nic); - -int sipa_skb_sender_send_data(struct sipa_skb_sender *sender, - struct sk_buff *skb, - enum sipa_term_type dst, - u8 netid) -{ - unsigned long flags; - u64 dma_addr; - struct sipa_skb_dma_addr_node *node; -#if defined (__BIG_ENDIAN_BITFIELD) - struct sipa_node_description_tag des; -#else - struct sipa_node_description_tag *des; -#endif - struct sipa_core *ctrl = sipa_get_ctrl_pointer(); - struct sipa_cmn_fifo_cfg_tag *fifo_cfg; - void __iomem *fifo_base; - u32 clr_sts = 0; - u32 int_status = 0; - - spin_lock_irqsave(&sender->send_lock, flags); - - if (sender->ep_cover_net == true){ - pr_info("%s, ep_cover_net is true, so return EAGAIN\n", __func__); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - }else{ - fifo_cfg = ctrl->cmn_fifo_cfg + sender->ep->send_fifo->fifo_id; - fifo_base = fifo_cfg->fifo_reg_base; - int_status = ipa_phy_get_fifo_all_int_sts(fifo_base); - if(int_status == 0x5FF000){ - pr_err("%s: check sts failed, maybe ep is down\n", __func__); - spin_unlock_irqrestore(&sender->send_lock, flags); - return -EINPROGRESS; - } - - if (int_status & IPA_INT_ENTER_FLOW_CTRL_STS) { - pr_info("sipa_skb_sender_send_data set ep_cover_net true!!!!!\n"); - sender->ep_cover_net = true; - sender->enter_flow_ctrl_cnt++; - clr_sts |= IPA_ENTRY_FLOW_CONTROL_CLR_BIT; - ipa_phy_clear_int(fifo_base, clr_sts); - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - } - - if (sender->free_notify_net == true){ - pr_info("%s: free_notify_net is true, so return EAGAIN\n", __func__); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - - if (!atomic_read(&sender->left_cnt)) { - sender->no_free_cnt++; - sender->free_notify_net = true; - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - - dma_addr = (u64)dma_map_single(ctrl->pci_dev, skb->head, - skb->len + skb_headroom(skb), - DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(ctrl->pci_dev, (dma_addr_t)dma_addr))) { - sender->free_notify_net = true; - sipa_inform_evt_to_nics(sender, SIPA_ENTER_FLOWCTRL); - spin_unlock_irqrestore(&sender->send_lock, flags); - wake_up(&sender->free_waitq); - return -EAGAIN; - } - - dma_addr += ctrl->pcie_mem_offset; -#if defined (__BIG_ENDIAN_BITFIELD) - memset(&des, 0, sizeof(des)); - des.address = dma_addr; - des.length = skb->len; - des.offset = skb_headroom(skb); - des.net_id = netid; - des.dst = dst; - des.src = sender->ep->send_fifo->cur; - des.err_code = 0; - des.intr = 0; - sipa_set_node_desc((u8 *)ctrl->hal_ops.get_rx_fifo_wr(sender->ep->send_fifo->fifo_id, - ctrl->cmn_fifo_cfg, 0), (u8 *)&des); -#else - des = ctrl->hal_ops.get_rx_fifo_wr(sender->ep->send_fifo->fifo_id, - ctrl->cmn_fifo_cfg, 0); - des->address = dma_addr; - des->length = skb->len; - des->offset = skb_headroom(skb); - des->net_id = netid; - des->dst = dst; - des->src = sender->ep->send_fifo->cur; - des->err_code = 0; - des->intr = 0; -#endif - node = list_first_entry(&sender->pair_free_list, - struct sipa_skb_dma_addr_node, - list); - node->skb = skb; - node->dma_addr = dma_addr; - list_del(&node->list); - list_add_tail(&node->list, &sender->sending_list); - ctrl->hal_ops.set_rx_fifo_wr(ctrl->pci_dev, - sender->ep->send_fifo->fifo_id, - ctrl->cmn_fifo_cfg, 1); - atomic_dec(&sender->left_cnt); - spin_unlock_irqrestore(&sender->send_lock, flags); - - return 0; -} -EXPORT_SYMBOL(sipa_skb_sender_send_data); diff --git a/quectel_SRPD_PCIE/src/sipc/Kconfig b/quectel_SRPD_PCIE/src/sipc/Kconfig deleted file mode 100644 index 9fe1419..0000000 --- a/quectel_SRPD_PCIE/src/sipc/Kconfig +++ /dev/null @@ -1,26 +0,0 @@ -menu "SIPC modules" - -config SPRD_SIPC - bool "Sprd IPC" - default n - select GENERIC_ALLOCATOR - help - SIPC is a module for spreadtrum AP/CP communicaiton system. - -config SPRD_SIPC_SPIPE - bool "SPRD pipe driver based on SBUF" - default n - depends on SPRD_SIPC - help - This driver is a pipe driver base on SBUF, which create - general pipes between AP & CP. - -config SPRD_SIPC_SPOOL - bool "SPRD pool driver based on SBLOCK" - default n - depends on SPRD_SIPC - help - This driver is a pool driver base on SBLOCK, which create - general pools between AP & CP. - -endmenu diff --git a/quectel_SRPD_PCIE/src/sipc/Makefile b/quectel_SRPD_PCIE/src/sipc/Makefile deleted file mode 100644 index caed73a..0000000 --- a/quectel_SRPD_PCIE/src/sipc/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -ccflags-y += -DCONFIG_SPRD_PCIE_EP_DEVICE -DCONFIG_SPRD_SIPA - -obj-y += sipc.o smsg.o smem.o sbuf.o sblock.o sipc_debugfs.o -obj-y += spipe.o -obj-y += spool.o - diff --git a/quectel_SRPD_PCIE/src/sipc/sblock.c b/quectel_SRPD_PCIE/src/sipc/sblock.c deleted file mode 100644 index 730f531..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sblock.c +++ /dev/null @@ -1,1911 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "sblock.h" - -static struct sblock_mgr *sblocks[SIPC_ID_NR][SMSG_VALID_CH_NR]; - -/* put one block pack to the pool */ -void sblock_put(u8 dst, u8 channel, struct sblock *blk) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - unsigned long flags; - int txpos; - int index; - u8 ch_index; - struct sblock_ring_header_op *poolhd_op; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock) - return; - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - spin_lock_irqsave(&ring->p_txlock, flags); - txpos = sblock_get_ringpos(*(poolhd_op->tx_rd_p) - 1, - poolhd_op->tx_count); - ring->p_txblks[txpos].addr = blk->addr - - sblock->smem_virt + - sblock->stored_smem_addr; - ring->p_txblks[txpos].length = poolhd_op->tx_size; - *(poolhd_op->tx_rd_p) = *(poolhd_op->tx_rd_p) - 1; - if ((int)(*(poolhd_op->tx_wt_p) - *(poolhd_op->tx_rd_p)) == 1) - wake_up_interruptible_all(&(ring->getwait)); - index = sblock_get_index((blk->addr - ring->txblk_virt), - sblock->txblksz); - ring->txrecord[index] = SBLOCK_BLK_STATE_DONE; - - spin_unlock_irqrestore(&ring->p_txlock, flags); - - /* set write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* request in sblock_get, release here */ - sipc_smem_release_resource(ring->tx_pms, dst); -} -EXPORT_SYMBOL_GPL(sblock_put); - -static bool sblock_has_data(struct sblock_mgr *sblock, bool tx) -{ - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - struct sblock_ring *ring = sblock->ring; - bool has_data; - unsigned long flags; - - /* if it is local share memory, - * check the read and write point directly. - */ - if (smsg_ipcs[sblock->dst]->smem_type == SMEM_LOCAL) { - if (tx) { - poolhd_op = &ring->header_op.poolhd_op; - return *(poolhd_op->tx_rd_p) != *(poolhd_op->tx_wt_p); - } - - ringhd_op = &ring->header_op.ringhd_op; - return *(ringhd_op->rx_wt_p) != *(ringhd_op->rx_rd_p); - } - - /* - * if it is remote share memmory read the poll_mask, this situation - * requires that the poll_mask must be accurate enough. - */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (tx) - has_data = ring->poll_mask & (POLLOUT | POLLWRNORM); - else - has_data = ring->poll_mask & (POLLIN | POLLRDNORM); - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return has_data; -} - -/* clean rings and recover pools */ -static int sblock_recover(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring = NULL; - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - unsigned long pflags, qflags; - int i, j, rval; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock) - return -ENODEV; - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - ringhd_op = &(ring->header_op.ringhd_op); - - sblock->state = SBLOCK_STATE_IDLE; - wake_up_interruptible_all(&ring->getwait); - wake_up_interruptible_all(&ring->recvwait); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, -1); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->r_txlock, pflags); - /* clean txblks ring */ - *(ringhd_op->tx_wt_p) = *(ringhd_op->tx_rd_p); - - spin_lock_irqsave(&ring->p_txlock, qflags); - /* recover txblks pool */ - *(poolhd_op->tx_rd_p) = *(poolhd_op->tx_wt_p); - for (i = 0, j = 0; i < poolhd_op->tx_count; i++) { - if (ring->txrecord[i] == SBLOCK_BLK_STATE_DONE) { - ring->p_txblks[j].addr = i * sblock->txblksz + - poolhd_op->tx_addr; - ring->p_txblks[j].length = sblock->txblksz; - *(poolhd_op->tx_wt_p) = *(poolhd_op->tx_wt_p) + 1; - j++; - } - } - spin_unlock_irqrestore(&ring->p_txlock, qflags); - spin_unlock_irqrestore(&ring->r_txlock, pflags); - - spin_lock_irqsave(&ring->r_rxlock, pflags); - /* clean rxblks ring */ - *(ringhd_op->rx_rd_p) = *(ringhd_op->rx_wt_p); - - spin_lock_irqsave(&ring->p_rxlock, qflags); - /* recover rxblks pool */ - *(poolhd_op->rx_wt_p) = *(poolhd_op->rx_rd_p); - for (i = 0, j = 0; i < poolhd_op->rx_count; i++) { - if (ring->rxrecord[i] == SBLOCK_BLK_STATE_DONE) { - ring->p_rxblks[j].addr = i * sblock->rxblksz + - poolhd_op->rx_addr; - ring->p_rxblks[j].length = sblock->rxblksz; - *(poolhd_op->rx_wt_p) = *(poolhd_op->rx_wt_p) + 1; - j++; - } - } - spin_unlock_irqrestore(&ring->p_rxlock, qflags); - spin_unlock_irqrestore(&ring->r_rxlock, pflags); - - /* restore write mask. */ - spin_lock_irqsave(&ring->poll_lock, qflags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, qflags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - - return 0; -} - -static int sblock_host_init(struct smsg_ipc *sipc, struct sblock_mgr *sblock, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize) -{ - volatile struct sblock_ring_header *ringhd; - volatile struct sblock_ring_header *poolhd; - struct sblock_ring_header_op *ringhd_op; - struct sblock_ring_header_op *poolhd_op; - - u32 hsize; - int i, rval = -ENOMEM; - phys_addr_t offset = 0; - u8 dst = sblock->dst; - - txblocksize = ALIGN(txblocksize, SBLOCK_ALIGN_BYTES); - rxblocksize = ALIGN(rxblocksize, SBLOCK_ALIGN_BYTES); - sblock->txblksz = txblocksize; - sblock->rxblksz = rxblocksize; - sblock->txblknum = txblocknum; - sblock->rxblknum = rxblocknum; - - pr_debug("%s: channel %d-%d, txblocksize=%#x, rxblocksize=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocksize, - rxblocksize); - - pr_debug("%s: channel %d-%d, txblocknum=%#x, rxblocknum=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocknum, - rxblocknum); - - /* allocate smem */ - hsize = sizeof(struct sblock_header); - /* for header*/ - sblock->smem_size = hsize + - /* for blks */ - txblocknum * txblocksize + rxblocknum * rxblocksize + - /* for ring */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks) + - /* for pool */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks); - - sblock->smem_addr = smem_alloc(dst, sblock->smem_size); - if (!sblock->smem_addr) { - pr_err("%s: channel %d-%d, Failed to alloc smem for sblock\n", - __func__, - sblock->dst, - sblock->channel); - return -ENOMEM; - } - - pr_debug("%s: channel %d-%d, smem_addr=%#lx, smem_size=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - (unsigned long)(sblock->smem_addr + offset), - sblock->smem_size); - - sblock->dst_smem_addr = sblock->smem_addr - - sipc->smem_base + sipc->dst_smem_base; - - /* in host mode, it is client physial address. */ - sblock->stored_smem_addr = sblock->dst_smem_addr; - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; -#endif - pr_debug("%s: channel %d-%d, offset = 0x%lx!\n", - __func__, - sblock->dst, - sblock->channel, - (unsigned long)offset); - sblock->smem_virt = shmem_ram_vmap_nocache(dst, - sblock->smem_addr + offset, - sblock->smem_size); - if (!sblock->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sblock\n", - __func__, - sblock->dst, - sblock->channel); - goto sblock_host_smem_free; - } - - /* alloc ring */ - sblock->ring->txrecord = kcalloc(txblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->txrecord) - goto sblock_host_unmap; - - sblock->ring->rxrecord = kcalloc(rxblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->rxrecord) - goto sblock_host_tx_free; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) - goto sblock_host_rx_free; - - /* initialize header */ - ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt); - ringhd->txblk_addr = sblock->stored_smem_addr + hsize; - ringhd->txblk_count = txblocknum; - ringhd->txblk_size = txblocksize; - ringhd->txblk_rdptr = 0; - ringhd->txblk_wrptr = 0; - ringhd->txblk_blks = ringhd->txblk_addr + - txblocknum * txblocksize + rxblocknum * rxblocksize; - ringhd->rxblk_addr = ringhd->txblk_addr + txblocknum * txblocksize; - ringhd->rxblk_count = rxblocknum; - ringhd->rxblk_size = rxblocksize; - ringhd->rxblk_rdptr = 0; - ringhd->rxblk_wrptr = 0; - ringhd->rxblk_blks = ringhd->txblk_blks + - txblocknum * sizeof(struct sblock_blks); - - poolhd = ringhd + 1; - poolhd->txblk_addr = sblock->stored_smem_addr + hsize; - poolhd->txblk_count = txblocknum; - poolhd->txblk_size = txblocksize; - poolhd->txblk_rdptr = 0; - poolhd->txblk_wrptr = 0; - poolhd->txblk_blks = ringhd->rxblk_blks + - rxblocknum * sizeof(struct sblock_blks); - poolhd->rxblk_addr = ringhd->txblk_addr + txblocknum * txblocksize; - poolhd->rxblk_count = rxblocknum; - poolhd->rxblk_size = rxblocksize; - poolhd->rxblk_rdptr = 0; - poolhd->rxblk_wrptr = 0; - poolhd->rxblk_blks = poolhd->txblk_blks + - txblocknum * sizeof(struct sblock_blks); - - pr_debug("%s: channel %d-%d, int ring!\n", - __func__, - sblock->dst, - sblock->channel); - - /* initialize ring */ - sblock->ring->header = sblock->smem_virt; - sblock->ring->txblk_virt = sblock->smem_virt + - (ringhd->txblk_addr - sblock->stored_smem_addr); - sblock->ring->r_txblks = sblock->smem_virt + - (ringhd->txblk_blks - sblock->stored_smem_addr); - sblock->ring->rxblk_virt = sblock->smem_virt + - (ringhd->rxblk_addr - sblock->stored_smem_addr); - sblock->ring->r_rxblks = sblock->smem_virt + - (ringhd->rxblk_blks - sblock->stored_smem_addr); - sblock->ring->p_txblks = sblock->smem_virt + - (poolhd->txblk_blks - sblock->stored_smem_addr); - sblock->ring->p_rxblks = sblock->smem_virt + - (poolhd->rxblk_blks - sblock->stored_smem_addr); - - for (i = 0; i < txblocknum; i++) { - sblock->ring->p_txblks[i].addr = poolhd->txblk_addr + - i * txblocksize; - sblock->ring->p_txblks[i].length = txblocksize; - sblock->ring->txrecord[i] = SBLOCK_BLK_STATE_DONE; - poolhd->txblk_wrptr++; - } - for (i = 0; i < rxblocknum; i++) { - sblock->ring->p_rxblks[i].addr = poolhd->rxblk_addr + - i * rxblocksize; - sblock->ring->p_rxblks[i].length = rxblocksize; - sblock->ring->rxrecord[i] = SBLOCK_BLK_STATE_DONE; - poolhd->rxblk_wrptr++; - } - - /* init, set write mask. */ - sblock->ring->poll_mask = POLLOUT | POLLWRNORM; - - /* init header op */ - ringhd_op = &((sblock->ring->header_op).ringhd_op); - ringhd_op->tx_rd_p = &ringhd->txblk_rdptr; - ringhd_op->tx_wt_p = &ringhd->txblk_wrptr; - ringhd_op->rx_rd_p = &ringhd->rxblk_rdptr; - ringhd_op->rx_wt_p = &ringhd->rxblk_wrptr; - ringhd_op->tx_addr = ringhd->txblk_addr; - ringhd_op->tx_count = ringhd->txblk_count; - ringhd_op->tx_size = ringhd->txblk_size; - ringhd_op->tx_blks = ringhd->txblk_blks; - ringhd_op->rx_addr = ringhd->rxblk_addr; - ringhd_op->rx_count = ringhd->rxblk_count; - ringhd_op->rx_size = ringhd->rxblk_size; - ringhd_op->rx_blks = ringhd->rxblk_blks; - poolhd_op = &((sblock->ring->header_op).poolhd_op); - poolhd_op->tx_rd_p = &poolhd->txblk_rdptr; - poolhd_op->tx_wt_p = &poolhd->txblk_wrptr; - poolhd_op->rx_rd_p = &poolhd->rxblk_rdptr; - poolhd_op->rx_wt_p = &poolhd->rxblk_wrptr; - poolhd_op->tx_addr = poolhd->txblk_addr; - poolhd_op->tx_count = poolhd->txblk_count; - poolhd_op->tx_size = poolhd->txblk_size; - poolhd_op->tx_blks = poolhd->txblk_blks; - poolhd_op->rx_addr = poolhd->rxblk_addr; - poolhd_op->rx_count = poolhd->rxblk_count; - poolhd_op->rx_size = poolhd->rxblk_size; - poolhd_op->rx_blks = poolhd->rxblk_blks; - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - return 0; - -sblock_host_rx_free: - kfree(sblock->ring->rxrecord); -sblock_host_tx_free: - kfree(sblock->ring->txrecord); -sblock_host_unmap: - shmem_ram_unmap(dst, sblock->smem_virt); -sblock_host_smem_free: - smem_free(dst, sblock->smem_addr, sblock->smem_size); - - pr_err("%s: channel %d-%d, failed, ENOMEM!\n", - __func__, - sblock->dst, - sblock->channel); - - return rval; -} - -static int sblock_client_init(struct smsg_ipc *sipc, struct sblock_mgr *sblock) -{ - volatile struct sblock_ring_header *ringhd; - volatile struct sblock_ring_header *poolhd; - struct sblock_ring_header_op *ringhd_op; - struct sblock_ring_header_op *poolhd_op; - u32 hsize; - u8 dst = sblock->dst; - phys_addr_t offset = 0; - u32 txblocknum, txblocksize, rxblocknum, rxblocksize; - int rval = -ENOMEM; - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; - pr_debug("%s: channel %d-%d, offset = 0x%llx!\n", - __func__, - sblock->dst, - sblock->channel, - offset); -#endif - - /* get blcok num and block size */ - hsize = sizeof(struct sblock_header); - sblock->smem_virt = shmem_ram_vmap_nocache(dst, - sblock->smem_addr + offset, - hsize); - if (!sblock->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sblock\n", - __func__, - sblock->dst, - sblock->channel); - return -ENOMEM; - } - ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt); - /* client mode, tx <==> rx */ - txblocknum = ringhd->rxblk_count; - txblocksize = ringhd->rxblk_size; - rxblocknum = ringhd->txblk_count; - rxblocksize = ringhd->txblk_size; - - sblock->txblksz = txblocksize; - sblock->rxblksz = rxblocksize; - sblock->txblknum = txblocknum; - sblock->rxblknum = rxblocknum; - shmem_ram_unmap(dst, sblock->smem_virt); - - pr_debug("%s: channel %d-%d, txblocksize=%#x, rxblocksize=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocksize, - rxblocksize); - - pr_debug("%s: channel %d-%d, txblocknum=%#x, rxblocknum=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - txblocknum, - rxblocknum); - - /* allocate smem */ - /* for header*/ - sblock->smem_size = hsize + - /* for blks */ - txblocknum * txblocksize + rxblocknum * rxblocksize + - /* for ring */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks) + - /* for pool */ - (txblocknum + rxblocknum) * sizeof(struct sblock_blks); - - sblock->smem_addr_debug = smem_alloc(dst, sblock->smem_size); - if (!sblock->smem_addr_debug) { - pr_err("%s: channel %d-%d, Failed to allocate smem\n", - __func__, - sblock->dst, - sblock->channel); - return -ENOMEM; - } - - pr_debug("%s: channel %d-%d, smem_addr=%#lx, smem_size=%#x!\n", - __func__, - sblock->dst, - sblock->channel, - (unsigned long)(sblock->smem_addr + offset), - sblock->smem_size); - - /* in client mode, it is own physial address. */ - sblock->stored_smem_addr = sblock->smem_addr; - - /* get smem virtual address */ - sblock->smem_virt = shmem_ram_vmap_nocache(dst, - sblock->smem_addr + offset, - sblock->smem_size); - if (!sblock->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sblock!\n", - __func__, - sblock->dst, - sblock->channel); - goto sblock_client_smem_free; - } - - /* initialize ring and header */ - sblock->ring->txrecord = kcalloc(txblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->txrecord) - goto sblock_client_unmap; - - sblock->ring->rxrecord = kcalloc(rxblocknum, sizeof(int), GFP_KERNEL); - if (!sblock->ring->rxrecord) - goto sblock_client_tx_free; - - ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt); - poolhd = ringhd + 1; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) - goto sblock_client_tx_free; - - /* client mode, tx <==> rx */ - sblock->ring->header = sblock->smem_virt; - sblock->ring->txblk_virt = sblock->smem_virt + - (ringhd->rxblk_addr - sblock->stored_smem_addr); - sblock->ring->rxblk_virt = sblock->smem_virt + - (ringhd->txblk_addr - sblock->stored_smem_addr); - sblock->ring->r_txblks = sblock->smem_virt + - (ringhd->rxblk_blks - sblock->stored_smem_addr); - sblock->ring->r_rxblks = sblock->smem_virt + - (ringhd->txblk_blks - sblock->stored_smem_addr); - sblock->ring->p_txblks = sblock->smem_virt + - (poolhd->rxblk_blks - sblock->stored_smem_addr); - sblock->ring->p_rxblks = sblock->smem_virt + - (poolhd->txblk_blks - sblock->stored_smem_addr); - - /* init header op, tx <==> rx */ - ringhd_op = &((sblock->ring->header_op).ringhd_op); - ringhd_op->tx_rd_p = &ringhd->rxblk_rdptr; - ringhd_op->tx_wt_p = &ringhd->rxblk_wrptr; - ringhd_op->rx_rd_p = &ringhd->txblk_rdptr; - ringhd_op->rx_wt_p = &ringhd->txblk_wrptr; - ringhd_op->tx_addr = ringhd->rxblk_addr; - ringhd_op->tx_count = ringhd->rxblk_count; - ringhd_op->tx_size = ringhd->rxblk_size; - ringhd_op->tx_blks = ringhd->rxblk_blks; - ringhd_op->rx_addr = ringhd->txblk_addr; - ringhd_op->rx_count = ringhd->txblk_count; - ringhd_op->rx_size = ringhd->txblk_size; - ringhd_op->rx_blks = ringhd->txblk_blks; - poolhd_op = &((sblock->ring->header_op).poolhd_op); - poolhd_op->tx_rd_p = &poolhd->rxblk_rdptr; - poolhd_op->tx_wt_p = &poolhd->rxblk_wrptr; - poolhd_op->rx_rd_p = &poolhd->txblk_rdptr; - poolhd_op->rx_wt_p = &poolhd->txblk_wrptr; - poolhd_op->tx_addr = poolhd->rxblk_addr; - poolhd_op->tx_count = poolhd->rxblk_count; - poolhd_op->tx_size = poolhd->rxblk_size; - poolhd_op->tx_blks = poolhd->rxblk_blks; - poolhd_op->rx_addr = poolhd->txblk_addr; - poolhd_op->rx_count = poolhd->txblk_count; - poolhd_op->rx_size = poolhd->txblk_size; - poolhd_op->rx_blks = poolhd->txblk_blks; - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - return 0; - -sblock_client_tx_free: - kfree(sblock->ring->txrecord); -sblock_client_unmap: - shmem_ram_unmap(dst, sblock->smem_virt); -sblock_client_smem_free: - smem_free(dst, sblock->smem_addr_debug, sblock->smem_size); - - return rval; -} - -static int sblock_thread(void *data) -{ - struct sblock_mgr *sblock = data; - struct smsg mcmd, mrecv; - unsigned long flags; - int rval; - int recovery = 0; - struct smsg_ipc *sipc; - struct sblock_ring *ring; - - /* since the channel open may hang, we call it in the sblock thread */ - rval = smsg_ch_open(sblock->dst, sblock->channel, -1); - if (rval != 0) { - pr_err("Failed to open channel %d\n", - sblock->channel); - - if (sblock->pre_cfg && sblock->handler) { - sblock->handler(SBLOCK_NOTIFY_OPEN_FAILED, - sblock->data); - } - - return rval; - } - - if (sblock->pre_cfg) { - sblock->state = SBLOCK_STATE_READY; - recovery = 1; - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_OPEN, sblock->data); - } - - /* if client, send SMSG_CMD_SBLOCK_INIT, wait SMSG_DONE_SBLOCK_INIT */ - sipc = smsg_ipcs[sblock->dst]; - if (sipc->client) { - smsg_set(&mcmd, sblock->channel, SMSG_TYPE_CMD, - SMSG_CMD_SBLOCK_INIT, 0); - smsg_send(sblock->dst, &mcmd, -1); - do { - smsg_set(&mrecv, sblock->channel, 0, 0, 0); - rval = smsg_recv(sblock->dst, &mrecv, -1); - if (rval != 0) { - sblock->thread = NULL; - return rval; - } - } while (mrecv.type != SMSG_TYPE_DONE || - mrecv.flag != SMSG_DONE_SBLOCK_INIT); - sblock->smem_addr = mrecv.value; - pr_info("%s: channel %d-%d, done_sblock_init, address=0x%x!\n", - __func__, - sblock->dst, - sblock->channel, - sblock->smem_addr); - if (sblock_client_init(sipc, sblock)) { - sblock->thread = NULL; - return 0; - } - sblock->state = SBLOCK_STATE_READY; - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_OPEN, - sblock->data); - } - - /* handle the sblock events */ - while (!kthread_should_stop()) { - /* monitor sblock recv smsg */ - smsg_set(&mrecv, sblock->channel, 0, 0, 0); - rval = smsg_recv(sblock->dst, &mrecv, -1); - if (rval == -EIO || rval == -ENODEV) { - /* channel state is FREE */ - msleep(20); - continue; - } - - pr_debug("sblock thread recv msg: dst=%d, channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - sblock->dst, sblock->channel, - mrecv.type, mrecv.flag, mrecv.value); - - switch (mrecv.type) { - case SMSG_TYPE_OPEN: - pr_info("%s: channel %d-%d,revc open!\n", - __func__, - sblock->dst, - sblock->channel); - /* handle channel recovery */ - if (recovery) { - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_CLOSE, - sblock->data); - sblock_recover(sblock->dst, sblock->channel); - } - smsg_open_ack(sblock->dst, sblock->channel); - if (sblock->pre_cfg) - sblock->state = SBLOCK_STATE_READY; - break; - case SMSG_TYPE_CLOSE: - /* handle channel recovery */ - smsg_close_ack(sblock->dst, sblock->channel); - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_CLOSE, - sblock->data); - sblock->state = SBLOCK_STATE_IDLE; - break; - case SMSG_TYPE_CMD: - if (!sblock->pre_cfg) { - /* respond cmd done for sblock init */ - WARN_ON(mrecv.flag != SMSG_CMD_SBLOCK_INIT); - smsg_set(&mcmd, - sblock->channel, - SMSG_TYPE_DONE, - SMSG_DONE_SBLOCK_INIT, - sblock->dst_smem_addr); - smsg_send(sblock->dst, &mcmd, -1); - sblock->state = SBLOCK_STATE_READY; - recovery = 1; - pr_info("%s: channel %d-%d, SMSG_CMD_SBLOCK_INIT, dst address = 0x%x!\n", - __func__, - sblock->dst, - sblock->channel, - sblock->dst_smem_addr); - - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_OPEN, - sblock->data); - } - break; - case SMSG_TYPE_EVENT: - /* handle sblock send/release events */ - switch (mrecv.flag) { - case SMSG_EVENT_SBLOCK_SEND: - ring = sblock->ring; - /* set read mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - wake_up_interruptible_all(&sblock->ring->recvwait); - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_RECV, - sblock->data); - break; - case SMSG_EVENT_SBLOCK_RELEASE: - ring = sblock->ring; - /* set write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - wake_up_interruptible_all(&sblock->ring->getwait); - if (sblock->handler) - sblock->handler(SBLOCK_NOTIFY_GET, - sblock->data); - break; - default: - rval = 1; - break; - } - break; - default: - rval = 1; - break; - }; - - if (rval) { - pr_info("non-handled sblock msg: %d-%d, %d, %d, %d\n", - sblock->dst, sblock->channel, - mrecv.type, mrecv.flag, mrecv.value); - rval = 0; - } - } - - pr_info("sblock %d-%d thread stop", - sblock->dst, sblock->channel); - return rval; -} - -static void sblock_pms_init(uint8_t dst, uint8_t ch, struct sblock_ring *ring) -{ - sprintf(ring->tx_pms_name, "sblock-%d-%d-tx", dst, ch); - ring->tx_pms = sprd_pms_create(dst, ring->tx_pms_name, true); - if (!ring->tx_pms) - pr_warn("create pms %s failed!\n", ring->tx_pms_name); - - sprintf(ring->rx_pms_name, "sblock-%d-%d-rx", dst, ch); - ring->rx_pms = sprd_pms_create(dst, ring->rx_pms_name, true); - if (!ring->rx_pms) - pr_warn("create pms %s failed!\n", ring->rx_pms_name); -} - -static void sblock_pms_destroy(struct sblock_ring *ring) -{ - sprd_pms_destroy(ring->tx_pms); - sprd_pms_destroy(ring->rx_pms); - ring->tx_pms = NULL; - ring->rx_pms = NULL; -} - -static int sblock_mgr_create(uint8_t dst, - uint8_t channel, - int pre_cfg, - uint32_t tx_blk_num, uint32_t tx_blk_sz, - uint32_t rx_blk_num, uint32_t rx_blk_sz, - struct sblock_mgr **sb_mgr) -{ - struct sblock_mgr *sblock = NULL; - struct smsg_ipc *sipc = smsg_ipcs[dst]; - int ret; - - pr_debug("%s: dst=%d channel=%d\n", __func__, dst, channel); - - if (!sipc) - return -EINVAL; - - sblock = kzalloc(sizeof(struct sblock_mgr), GFP_KERNEL); - if (!sblock) - return -ENOMEM; - - sblock->ring = kzalloc(sizeof(struct sblock_ring), GFP_KERNEL); - if (!sblock->ring) { - kfree(sblock); - return -ENOMEM; - } - - sblock->dst = dst; - sblock->channel = channel; - sblock->pre_cfg = pre_cfg; - sblock->state = SBLOCK_STATE_IDLE; - - if (!sipc->client) { - ret = sblock_host_init(sipc, sblock, - tx_blk_num, tx_blk_sz, - rx_blk_num, rx_blk_sz); - if (ret) { - kfree(sblock->ring); - kfree(sblock); - return ret; - } - } - - sblock_pms_init(dst, channel, sblock->ring); - init_waitqueue_head(&sblock->ring->getwait); - init_waitqueue_head(&sblock->ring->recvwait); - spin_lock_init(&sblock->ring->r_txlock); - spin_lock_init(&sblock->ring->r_rxlock); - spin_lock_init(&sblock->ring->p_txlock); - spin_lock_init(&sblock->ring->p_rxlock); - spin_lock_init(&sblock->ring->poll_lock); - - *sb_mgr = sblock; - - return 0; -} - -int sblock_create_ex(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize, - void (*handler)(int event, void *data), void *data) -{ - struct sblock_mgr *sblock = NULL; - int result; - u8 ch_index; - struct smsg_ipc *sipc; - struct sched_param param = {.sched_priority = 11}; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - if (dst >= SIPC_ID_NR) { - pr_err("%s: dst = %d is invalid\n", __func__, dst); - return -EINVAL; - } - - pr_debug("%s: dst=%d channel=%d\n", __func__, dst, channel); - - result = sblock_mgr_create(dst, channel, 0, - txblocknum, txblocksize, - rxblocknum, rxblocksize, - &sblock); - if (!result) { - sblock->thread = kthread_create(sblock_thread, sblock, - "sblock-%d-%d", dst, channel); - if (IS_ERR(sblock->thread)) { - pr_err("Failed to create kthread: sblock-%d-%d\n", - dst, channel); - sipc = smsg_ipcs[sblock->dst]; - if (!sipc->client) { - shmem_ram_unmap(dst, sblock->smem_virt); - smem_free(dst, - sblock->smem_addr, - sblock->smem_size); - kfree(sblock->ring->txrecord); - kfree(sblock->ring->rxrecord); - } - kfree(sblock->ring); - result = PTR_ERR(sblock->thread); - kfree(sblock); - return result; - } - - /* Prevent the thread task_struct from being destroyed. */ - get_task_struct(sblock->thread); - - sblocks[dst][ch_index] = sblock; - if ((handler != NULL) && (data != NULL)) { - result = sblock_register_notifier(dst, channel, - handler, data); - if (result < 0) { - sblock_destroy(dst, channel); - return result; - } - } - /*set the thread as a real time thread, and its priority is 11*/ - sched_setscheduler(sblock->thread, SCHED_RR, ¶m); - wake_up_process(sblock->thread); - } - - pr_debug("%s: sblock-%d-%d create over, result = %d\n", - __func__, dst, channel, result); - - return result; -} -EXPORT_SYMBOL_GPL(sblock_create_ex); - -int sblock_create(u8 dst, u8 channel, - u32 txblocknum, u32 txblocksize, - u32 rxblocknum, u32 rxblocksize) -{ - return sblock_create_ex(dst, channel, txblocknum, txblocksize, - rxblocknum, rxblocksize, NULL, NULL); -} -EXPORT_SYMBOL_GPL(sblock_create); - -int sblock_pcfg_create(u8 dst, u8 channel, - u32 tx_blk_num, u32 tx_blk_sz, - u32 rx_blk_num, u32 rx_blk_sz) -{ - struct sblock_mgr *sblock = NULL; - int result; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - if (dst >= SIPC_ID_NR) { - pr_err("sblock_create_ex: dst = %d is invalid\n", dst); - return -EINVAL; - } - - pr_debug("%s: dst=%d channel=%d\n", __func__, dst, channel); - - result = sblock_mgr_create(dst, - channel, - 1, - tx_blk_num, tx_blk_sz, - rx_blk_num, rx_blk_sz, - &sblock); - if (!result) { - struct sched_param param = {.sched_priority = 11}; - - sblock->thread = kthread_create(sblock_thread, sblock, - "sblock-%d-%d", dst, channel); - if (IS_ERR(sblock->thread)) { - struct smsg_ipc *sipc; - - pr_err("Failed to create kthread: sblock-%d-%d\n", - dst, channel); - sipc = smsg_ipcs[sblock->dst]; - if (!sipc->client) { - shmem_ram_unmap(dst, sblock->smem_virt); - smem_free(dst, - sblock->smem_addr, - sblock->smem_size); - kfree(sblock->ring->txrecord); - kfree(sblock->ring->rxrecord); - } - kfree(sblock->ring); - result = PTR_ERR(sblock->thread); - kfree(sblock); - return result; - } - - /* Prevent the thread task_struct from being destroyed. */ - get_task_struct(sblock->thread); - - sblocks[dst][ch_index] = sblock; - /* - * Set the thread as a real time thread, and its priority - * is 11. - */ - sched_setscheduler(sblock->thread, SCHED_RR, ¶m); - wake_up_process(sblock->thread); - } - - return result; -} -EXPORT_SYMBOL_GPL(sblock_pcfg_create); - -void sblock_down(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - u8 ch_index; - int i; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sblock = sblocks[dst][ch_index]; - if (sblock == NULL) - return; - - sblock->state = SBLOCK_STATE_IDLE; - if (sblock->ring) { - wake_up_interruptible_all(&sblock->ring->recvwait); - wake_up_interruptible_all(&sblock->ring->getwait); - } - pr_info("%s: channel=%d sblock down success\n", __func__, channel); - -} -EXPORT_SYMBOL_GPL(sblock_down); - -void sblock_destroy(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - u8 ch_index; - struct smsg_ipc *sipc; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sblock = sblocks[dst][ch_index]; - if (sblock == NULL) - return; - - sblock->state = SBLOCK_STATE_IDLE; - smsg_ch_close(dst, channel, -1); - - /* stop sblock thread if it's created successfully and still alive */ - if (!IS_ERR_OR_NULL(sblock->thread)) { - kthread_stop(sblock->thread); - put_task_struct(sblock->thread); - sblock->thread = NULL; - } - - if (sblock->ring) { - sblock_pms_destroy(sblock->ring); - wake_up_interruptible_all(&sblock->ring->recvwait); - wake_up_interruptible_all(&sblock->ring->getwait); - /* kfree(NULL) is safe */ - /* if (sblock->ring->txrecord) */ - kfree(sblock->ring->txrecord); - /* if (sblock->ring->rxrecord) */ - kfree(sblock->ring->rxrecord); - kfree(sblock->ring); - } - if (sblock->smem_virt) - shmem_ram_unmap(dst, sblock->smem_virt); - - sipc = smsg_ipcs[dst]; - if (sipc->client) - smem_free(dst, sblock->smem_addr_debug, sblock->smem_size); - else - smem_free(dst, sblock->smem_addr, sblock->smem_size); - kfree(sblock); - - sblocks[dst][ch_index] = NULL; -} -EXPORT_SYMBOL_GPL(sblock_destroy); - -int sblock_pcfg_open(uint8_t dest, uint8_t channel, - void (*notifier)(int event, void *client), - void *client) -{ - struct sblock_mgr *sblock; - uint8_t idx; - int ret; - struct sched_param param = {.sched_priority = 11}; - - pr_debug("%s: dst=%d channel=%d\n", __func__, dest, channel); - - if (!notifier) - return -EINVAL; - - idx = sipc_channel2index(channel); - if (idx == INVALID_CHANEL_INDEX) { - pr_err("%s: invalid channel %d!\n", __func__, channel); - return -ENODEV; - } - - sblock = sblocks[dest][idx]; - if (!sblock) - return -ENODEV; - - if (!sblock->pre_cfg) - return -EINVAL; - - if (sblock->thread) { - pr_err("%s: SBLOCK %u/%u already open", - __func__, - (unsigned int)sblock->dst, - (unsigned int)sblock->channel); - return -EPROTO; - } - - ret = 0; - sblock->thread = kthread_create(sblock_thread, sblock, - "sblock-%d-%d", dest, channel); - if (IS_ERR(sblock->thread)) { - pr_err("%s: create thread error\n", __func__); - sblock->thread = NULL; - ret = -EBUSY; - } else { - /* Prevent the thread task_struct from being destroyed. */ - get_task_struct(sblock->thread); - - sblock->handler = notifier; - sblock->data = client; - /*set the thread as a real time thread, and its priority is 11*/ - sched_setscheduler(sblock->thread, SCHED_RR, ¶m); - wake_up_process(sblock->thread); - } - - return ret; -} -EXPORT_SYMBOL_GPL(sblock_pcfg_open); - -int sblock_close(uint8_t dest, uint8_t channel) -{ - return -ENOTSUPP; -} -EXPORT_SYMBOL_GPL(sblock_close); - -int sblock_register_notifier(u8 dst, u8 channel, - void (*handler)(int event, void *data), - void *data) -{ - struct sblock_mgr *sblock; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } -#ifndef CONFIG_SPRD_SIPC_WCN - if (sblock->handler) { - pr_err("sblock handler already registered\n"); - return -EBUSY; - } -#endif - sblock->handler = handler; - sblock->data = data; - - return 0; -} -EXPORT_SYMBOL_GPL(sblock_register_notifier); - -int sblock_get_smem_cp_addr(uint8_t dest, uint8_t channel, - uint32_t *paddr) -{ - struct sblock_mgr *sblock; - uint8_t idx; - - if (!paddr) - return -EINVAL; - - idx = sipc_channel2index(channel); - if (idx == INVALID_CHANEL_INDEX) { - pr_err("%s: invalid channel %d!\n", __func__, channel); - return -ENODEV; - } - - sblock = sblocks[dest][idx]; - if (!sblock) - return -ENODEV; - - *paddr = sblock->dst_smem_addr; - - return 0; -} -EXPORT_SYMBOL_GPL(sblock_get_smem_cp_addr); - -int sblock_get(u8 dst, u8 channel, struct sblock *blk, int timeout) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - - int txpos, index; - int rval = 0; - unsigned long flags; - u8 ch_index; - bool no_data; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, timeout); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->poll_lock, flags); - no_data = *(poolhd_op->tx_rd_p) == *(poolhd_op->tx_wt_p); - /* update write mask */ - if (no_data) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - - if (no_data) { - if (timeout == 0) { - /* no wait */ - pr_err("%s: %d-%d is empty!\n", __func__, dst, channel); - rval = -ENODATA; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible(ring->getwait, - sblock_has_data(sblock, true) || - sblock->state == SBLOCK_STATE_IDLE); - if (rval < 0) - pr_debug("%s: wait interrupted!\n", __func__); - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_err("%s: state is idle!\n", __func__); - rval = -EIO; - } - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout(ring->getwait, - sblock_has_data(sblock, true) || - sblock == SBLOCK_STATE_IDLE, - timeout); - if (rval < 0) { - pr_debug("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_info("%s: state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) - return rval; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, timeout); - if (rval < 0) - return rval; - - /* multi-gotter may cause got failure */ - spin_lock_irqsave(&ring->p_txlock, flags); - if (*(poolhd_op->tx_rd_p) != *(poolhd_op->tx_wt_p) && - sblock->state == SBLOCK_STATE_READY) { - txpos = sblock_get_ringpos(*(poolhd_op->tx_rd_p), - poolhd_op->tx_count); - blk->addr = sblock->smem_virt + - (ring->p_txblks[txpos].addr - - sblock->stored_smem_addr); - blk->length = poolhd_op->tx_size; - *(poolhd_op->tx_rd_p) = *(poolhd_op->tx_rd_p) + 1; - index = sblock_get_index((blk->addr - ring->txblk_virt), - sblock->txblksz); - ring->txrecord[index] = SBLOCK_BLK_STATE_PENDING; - } else { - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - rval = sblock->state == SBLOCK_STATE_READY ? -EAGAIN : -EIO; - } - spin_unlock_irqrestore(&ring->p_txlock, flags); - - spin_lock_irqsave(&ring->poll_lock, flags); - /* update write mask */ - if (*(poolhd_op->tx_wt_p) == *(poolhd_op->tx_rd_p)) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return rval; -} -EXPORT_SYMBOL_GPL(sblock_get); - -static int sblock_send_ex(u8 dst, u8 channel, - struct sblock *blk, bool yell) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - struct smsg mevt; - int txpos, index; - int rval = 0; - unsigned long flags; - u8 ch_index; - bool send_event = false; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - pr_debug("sblock_send: dst=%d, channel=%d, addr=%p, len=%d\n", - dst, channel, blk->addr, blk->length); - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - spin_lock_irqsave(&ring->r_txlock, flags); - - txpos = sblock_get_ringpos(*(ringhd_op->tx_wt_p), ringhd_op->tx_count); - ring->r_txblks[txpos].addr = blk->addr - - sblock->smem_virt + - sblock->stored_smem_addr; - ring->r_txblks[txpos].length = blk->length; - pr_debug("sblock_send: channel=%d, wrptr=%d, txpos=%d, addr=%x\n", - channel, *(ringhd_op->tx_wt_p), - txpos, ring->r_txblks[txpos].addr); - *(ringhd_op->tx_wt_p) = *(ringhd_op->tx_wt_p) + 1; - - if (sblock->state == SBLOCK_STATE_READY) { - if (yell) { - send_event = true; - } else if (!ring->yell) { - if ((int)(*(ringhd_op->tx_wt_p) - - *(ringhd_op->tx_rd_p)) == 1) - ring->yell = 1; - } - } - index = sblock_get_index((blk->addr - ring->txblk_virt), - sblock->txblksz); - ring->txrecord[index] = SBLOCK_BLK_STATE_DONE; - - spin_unlock_irqrestore(&ring->r_txlock, flags); - - /* request in sblock_get, release here */ - sipc_smem_release_resource(ring->tx_pms, dst); - - /* - * smsg_send may caused schedule, - * can't be called in spinlock protected context. - */ - if (send_event) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBLOCK_SEND, - 0); - rval = smsg_send(dst, &mevt, -1); - } - - return rval; -} - -int sblock_send(u8 dst, u8 channel, struct sblock *blk) -{ - return sblock_send_ex(dst, channel, blk, true); -} -EXPORT_SYMBOL_GPL(sblock_send); - -int sblock_send_prepare(u8 dst, u8 channel, struct sblock *blk) -{ - return sblock_send_ex(dst, channel, blk, false); -} -EXPORT_SYMBOL_GPL(sblock_send_prepare); - -int sblock_send_finish(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - struct smsg mevt; - int rval = 0; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - /* must wait resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, -1); - if (rval) - return rval; - - if (*(ringhd_op->tx_wt_p) != *(ringhd_op->tx_rd_p)) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBLOCK_SEND, 0); - rval = smsg_send(dst, &mevt, -1); - } - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - - return rval; -} -EXPORT_SYMBOL_GPL(sblock_send_finish); - -int sblock_receive(u8 dst, u8 channel, - struct sblock *blk, int timeout) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - int rxpos, index, rval = 0; - unsigned long flags; - u8 ch_index; - bool no_data; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return sblock ? -EIO : -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, timeout=%d\n", - __func__, dst, channel, timeout); - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, timeout); - if (rval < 0) - return rval; - - pr_debug("%s: channel=%d, wrptr=%d, rdptr=%d", - __func__, channel, - *(ringhd_op->rx_wt_p), - *(ringhd_op->rx_rd_p)); - - spin_lock_irqsave(&ring->poll_lock, flags); - no_data = *(ringhd_op->rx_wt_p) == *(ringhd_op->rx_rd_p); - /* update read mask */ - if (no_data) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - - if (no_data) { - if (timeout == 0) { - /* no wait */ - pr_debug("%s: %d-%d is empty!\n", - __func__, dst, channel); - rval = -ENODATA; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible(ring->recvwait, - sblock_has_data(sblock, false)); - if (rval < 0) - pr_info("%s: wait interrupted!\n", __func__); - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_info("%s: state is idle!\n", __func__); - rval = -EIO; - } - - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout(ring->recvwait, - sblock_has_data(sblock, false), - timeout); - if (rval < 0) { - pr_info("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sblock->state == SBLOCK_STATE_IDLE) { - pr_info("%s: state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) - return rval; - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, timeout); - if (rval < 0) - return rval; - - /* multi-receiver may cause recv failure */ - spin_lock_irqsave(&ring->r_rxlock, flags); - - if (*(ringhd_op->rx_wt_p) != *(ringhd_op->rx_rd_p) && - sblock->state == SBLOCK_STATE_READY) { - rxpos = sblock_get_ringpos(*(ringhd_op->rx_rd_p), - ringhd_op->rx_count); - blk->addr = ring->r_rxblks[rxpos].addr - - sblock->stored_smem_addr + - sblock->smem_virt; - blk->length = ring->r_rxblks[rxpos].length; - *(ringhd_op->rx_rd_p) = *(ringhd_op->rx_rd_p) + 1; - pr_debug("%s: channel=%d, rxpos=%d, addr=%p, len=%d\n", - __func__, channel, rxpos, blk->addr, blk->length); - index = sblock_get_index((blk->addr - ring->rxblk_virt), - sblock->rxblksz); - ring->rxrecord[index] = SBLOCK_BLK_STATE_PENDING; - } else { - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - rval = sblock->state == SBLOCK_STATE_READY ? -EAGAIN : -EIO; - } - spin_unlock_irqrestore(&ring->r_rxlock, flags); - - spin_lock_irqsave(&ring->poll_lock, flags); - /* update read mask */ - if (*(ringhd_op->rx_wt_p) == *(ringhd_op->rx_rd_p)) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return rval; -} -EXPORT_SYMBOL_GPL(sblock_receive); - -int sblock_get_arrived_count(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *ringhd_op; - int blk_count = 0; - unsigned long flags; - u8 ch_index; - int rval; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } - - ring = sblock->ring; - ringhd_op = &(ring->header_op.ringhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, dst, -1); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->r_rxlock, flags); - blk_count = (int)(*(ringhd_op->rx_wt_p) - *(ringhd_op->rx_rd_p)); - spin_unlock_irqrestore(&ring->r_rxlock, flags); - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, dst); - - return blk_count; - -} -EXPORT_SYMBOL_GPL(sblock_get_arrived_count); - -int sblock_get_free_count(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - int blk_count = 0, rval; - unsigned long flags; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, dst, -1); - if (rval < 0) - return rval; - - spin_lock_irqsave(&ring->p_txlock, flags); - blk_count = (int)(*(poolhd_op->tx_wt_p) - *(poolhd_op->tx_rd_p)); - spin_unlock_irqrestore(&ring->p_txlock, flags); - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, dst); - - return blk_count; -} -EXPORT_SYMBOL_GPL(sblock_get_free_count); - -int sblock_release(u8 dst, u8 channel, struct sblock *blk) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - struct smsg mevt; - unsigned long flags; - int rxpos; - int index; - u8 ch_index; - bool send_event = false; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock || sblock->state != SBLOCK_STATE_READY) { - pr_err("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, addr=%p, len=%d\n", - __func__, dst, channel, blk->addr, blk->length); - - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - - spin_lock_irqsave(&ring->p_rxlock, flags); - rxpos = sblock_get_ringpos(*(poolhd_op->rx_wt_p), poolhd_op->rx_count); - ring->p_rxblks[rxpos].addr = blk->addr - - sblock->smem_virt + - sblock->stored_smem_addr; - ring->p_rxblks[rxpos].length = poolhd_op->rx_size; - *(poolhd_op->rx_wt_p) = *(poolhd_op->rx_wt_p) + 1; - pr_debug("%s: addr=%x\n", __func__, ring->p_rxblks[rxpos].addr); - - if ((int)(*(poolhd_op->rx_wt_p) - *(poolhd_op->rx_rd_p)) == 1 && - sblock->state == SBLOCK_STATE_READY) { - /* send smsg to notify the peer side */ - send_event = true; - } - - index = sblock_get_index((blk->addr - ring->rxblk_virt), - sblock->rxblksz); - ring->rxrecord[index] = SBLOCK_BLK_STATE_DONE; - - spin_unlock_irqrestore(&ring->p_rxlock, flags); - - /* request in sblock_receive, release here */ - sipc_smem_release_resource(ring->rx_pms, dst); - - /* - * smsg_send may caused schedule, - * can't be called in spinlock protected context. - */ - if (send_event) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBLOCK_RELEASE, - 0); - smsg_send(dst, &mevt, -1); - } - - return 0; -} -EXPORT_SYMBOL_GPL(sblock_release); - -unsigned int sblock_poll_wait(u8 dst, u8 channel, - struct file *filp, poll_table *wait) -{ - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - unsigned int mask = 0; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return mask; - } - sblock = sblocks[dst][ch_index]; - - if (!sblock) - return mask; - ring = sblock->ring; - poolhd_op = &(ring->header_op.poolhd_op); - ringhd_op = &(ring->header_op.ringhd_op); - - if (sblock->state != SBLOCK_STATE_READY) { - pr_debug("%s:sblock-%d-%d not ready to poll !\n", - __func__, dst, channel); - return mask; - } - poll_wait(filp, &ring->recvwait, wait); - poll_wait(filp, &ring->getwait, wait); - - if (sblock_has_data(sblock, true)) - mask |= POLLOUT | POLLWRNORM; - - if (sblock_has_data(sblock, false)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} -EXPORT_SYMBOL_GPL(sblock_poll_wait); - -int sblock_query(u8 dst, u8 channel) -{ - struct sblock_mgr *sblock = NULL; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sblock = sblocks[dst][ch_index]; - if (!sblock) - return -ENODEV; - if (sblock->state != SBLOCK_STATE_READY) { - pr_debug("%s:sblock-%d-%d not ready!\n", __func__, dst, channel); - return -EINVAL; - } - return 0; -} -EXPORT_SYMBOL_GPL(sblock_query); - -#if defined(CONFIG_DEBUG_FS) -static int sblock_debug_show(struct seq_file *m, void *private) -{ - struct smsg_ipc *sipc = NULL; - struct sblock_mgr *sblock; - struct sblock_ring *ring; - struct sblock_ring_header_op *poolhd_op; - struct sblock_ring_header_op *ringhd_op; - int i, j; - - for (i = 0; i < SIPC_ID_NR; i++) { - sipc = smsg_ipcs[i]; - if (!sipc) - continue; - - /* must request resource before read or write share memory */ - if (sipc_smem_request_resource(sipc->sipc_pms, - sipc->dst, 1000) < 0) - continue; - - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - sblock = sblocks[i][j]; - if (!sblock) - continue; - - sipc_debug_putline(m, '*', 170); - seq_printf(m, "sblock dst %d, channel: %3d, state: %d, smem_virt: 0x%lx, smem_addr: 0x%0x, dst_smem_addr: 0x%0x, smem_size: 0x%0x, txblksz: %d, rxblksz: %d\n", - sblock->dst, - sblock->channel, - sblock->state, - (unsigned long)sblock->smem_virt, - sblock->smem_addr, - sblock->dst_smem_addr, - sblock->smem_size, - sblock->txblksz, - sblock->rxblksz); - - /* - * in precfg channel, the ring pinter can be null - * before the the block manger has been created - * and ring->header pointer can also be null - * before the block handshake with host, - * so must add null pointer protect here. - */ - ring = sblock->ring; - if (!ring || !ring->header) - continue; - - poolhd_op = &(ring->header_op.poolhd_op); - ringhd_op = &(ring->header_op.ringhd_op); - seq_printf(m, "sblock ring: txblk_virt :0x%lx, rxblk_virt :0x%lx, poll_mask=0x%x\n", - (unsigned long)ring->txblk_virt, - (unsigned long)ring->rxblk_virt, - ring->poll_mask); - seq_printf(m, "sblock ring header: rxblk_addr :0x%0x, rxblk_rdptr :0x%0x, rxblk_wrptr :0x%0x, rxblk_size :%d, rxblk_count :%d, rxblk_blks: 0x%0x\n", - ringhd_op->rx_addr, *(ringhd_op->rx_rd_p), - *(ringhd_op->rx_wt_p), ringhd_op->rx_size, - ringhd_op->rx_count, ringhd_op->rx_blks); - seq_printf(m, "sblock ring header: txblk_addr :0x%0x, txblk_rdptr :0x%0x, txblk_wrptr :0x%0x, txblk_size :%d, txblk_count :%d, txblk_blks: 0x%0x\n", - ringhd_op->tx_addr, *(ringhd_op->tx_rd_p), - *(ringhd_op->tx_wt_p), ringhd_op->tx_size, - ringhd_op->tx_count, ringhd_op->tx_blks); - seq_printf(m, "sblock pool header: rxblk_addr :0x%0x, rxblk_rdptr :0x%0x, rxblk_wrptr :0x%0x, rxblk_size :%d, rxpool_count :%d, rxblk_blks: 0x%0x\n", - poolhd_op->rx_addr, *(poolhd_op->rx_rd_p), - *(poolhd_op->rx_wt_p), poolhd_op->rx_size, - poolhd_op->rx_count, poolhd_op->rx_blks); - seq_printf(m, "sblock pool header: txblk_addr :0x%0x, txblk_rdptr :0x%0x, txblk_wrptr :0x%0x, txblk_size :%d, txpool_count :%d, txblk_blks: 0x%0x\n", - poolhd_op->tx_addr, *(poolhd_op->tx_rd_p), - *(poolhd_op->tx_wt_p), poolhd_op->tx_size, - poolhd_op->tx_count, poolhd_op->tx_blks); - } - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - } - - return 0; -} - -static int sblock_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sblock_debug_show, inode->i_private); -} - -static const struct file_operations sblock_debug_fops = { - .open = sblock_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int sblock_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("sblock", 0444, - (struct dentry *)root, - NULL, &sblock_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(sblock_init_debugfs); - -#endif /* CONFIG_DEBUG_FS */ - - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SBLOCK driver"); -MODULE_LICENSE("GPL v2"); diff --git a/quectel_SRPD_PCIE/src/sipc/sblock.h b/quectel_SRPD_PCIE/src/sipc/sblock.h deleted file mode 100644 index 13d67af..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sblock.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SBLOCK_H -#define __SBLOCK_H - -/* flag for CMD/DONE msg type */ -#define SMSG_CMD_SBLOCK_INIT 0x1 -#define SMSG_DONE_SBLOCK_INIT 0x2 - -/* flag for EVENT msg type */ -#define SMSG_EVENT_SBLOCK_SEND 0x1 -#define SMSG_EVENT_SBLOCK_RELEASE 0x2 - -#define SBLOCK_STATE_IDLE 0 -#define SBLOCK_STATE_READY 1 - -#define SBLOCK_BLK_STATE_DONE 0 -#define SBLOCK_BLK_STATE_PENDING 1 - -struct sblock_blks { - u32 addr; /*phy address*/ - u32 length; -}; - -/* ring block header */ -struct sblock_ring_header { - /* get|send-block info */ - u32 txblk_addr; /* tx blocks start addr */ - u32 txblk_count; /* tx blocks num */ - u32 txblk_size; /* one tx block size */ - u32 txblk_blks; /* tx_ring or tx_pool start addr */ - u32 txblk_rdptr; /* tx_ring or tx_pool read point */ - u32 txblk_wrptr; /* tx_ring or tx_pool write point */ - - /* release|recv-block info */ - u32 rxblk_addr; - u32 rxblk_count; - u32 rxblk_size; - u32 rxblk_blks; - u32 rxblk_rdptr; - u32 rxblk_wrptr; -}; - -struct sblock_header { - struct sblock_ring_header ring; - struct sblock_ring_header pool; -}; - -struct sblock_ring_header_op { - /* - * this points point to share memory - * for update rdptr and wtptr on share memory - */ - volatile u32 *tx_rd_p; - volatile u32 *tx_wt_p; - volatile u32 *rx_rd_p; - volatile u32 *rx_wt_p; - - /* - * this member copy from share memory, - * because this contents will not change on share memory - */ - u32 tx_addr; /* txblk_addr */ - u32 tx_count; /* txblk_count */ - u32 tx_size; /* txblk_size */ - u32 tx_blks; /* txblk_blks */ - u32 rx_addr; - u32 rx_count; - u32 rx_size; - u32 rx_blks; -}; - -struct sblock_header_op { - struct sblock_ring_header_op ringhd_op; - struct sblock_ring_header_op poolhd_op; -}; - -struct sblock_ring { - struct sblock_header *header; - struct sblock_header_op header_op; - - struct sprd_pms *tx_pms; - struct sprd_pms *rx_pms; - char tx_pms_name[20]; - char rx_pms_name[20]; - - void *txblk_virt; /* virt of header->txblk_addr */ - void *rxblk_virt; /* virt of header->rxblk_addr */ - - /* virt of header->ring->txblk_blks */ - struct sblock_blks *r_txblks; - /* virt of header->ring->rxblk_blks */ - struct sblock_blks *r_rxblks; - /* virt of header->pool->txblk_blks */ - struct sblock_blks *p_txblks; - /* virt of header->pool->rxblk_blks */ - struct sblock_blks *p_rxblks; - - unsigned int poll_mask; - /* protect the poll_mask menber */ - spinlock_t poll_lock; - - int *txrecord; /* record the state of every txblk */ - int *rxrecord; /* record the state of every rxblk */ - int yell; /* need to notify cp */ - spinlock_t r_txlock; /* send */ - spinlock_t r_rxlock; /* recv */ - spinlock_t p_txlock; /* get */ - spinlock_t p_rxlock; /* release */ - - wait_queue_head_t getwait; - wait_queue_head_t recvwait; -}; - -struct sblock_mgr { - u8 dst; - u8 channel; - int pre_cfg; /*support in host mode only */ - u32 state; - - void *smem_virt; - u32 smem_addr; - u32 smem_addr_debug; - u32 smem_size; - u32 dst_smem_addr; - - /* - * this address stored in share memory, - * be used to calculte the block virt address. - * in host mode, it is client physial address(dst_smem_addr), - * in client mode, it is own physial address(smem_addr). - */ - u32 stored_smem_addr; - - u32 txblksz; - u32 rxblksz; - u32 txblknum; - u32 rxblknum; - - struct sblock_ring *ring; - struct task_struct *thread; - - void (*handler)(int event, void *data); - void *data; -}; - -#ifdef CONFIG_64BIT -#define SBLOCK_ALIGN_BYTES (8) -#else -#define SBLOCK_ALIGN_BYTES (4) -#endif - -static inline u32 sblock_get_index(u32 x, u32 y) -{ - return (x / y); -} - -static inline u32 sblock_get_ringpos(u32 x, u32 y) -{ - return is_power_of_2(y) ? (x & (y - 1)) : (x % y); -} -#endif diff --git a/quectel_SRPD_PCIE/src/sipc/sbuf.c b/quectel_SRPD_PCIE/src/sipc/sbuf.c deleted file mode 100644 index 2a50b72..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sbuf.c +++ /dev/null @@ -1,1755 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,4,60 )) -#include -#include -#endif - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "sbuf.h" - -#if defined(CONFIG_DEBUG_FS) -#include "sipc_debugfs.h" -#endif - -#define VOLA_SBUF_SMEM volatile struct sbuf_smem_header -#define VOLA_SBUF_RING volatile struct sbuf_ring_header - -struct name_node { - struct list_head list; - char comm[TASK_COMM_LEN]; - pid_t pid; - u8 latest; -}; - -union sbuf_buf { - void *buf; - void __user *ubuf; -}; - -enum task_type { - TASK_RXWAIT = 0, - TASK_TXWAIT, - TASK_SELECT -}; - -static struct sbuf_mgr *sbufs[SIPC_ID_NR][SMSG_VALID_CH_NR]; - -static bool sbuf_has_data(struct sbuf_ring *ring, u8 dst, bool tx) -{ - struct sbuf_ring_header_op *hd_op = &ring->header_op; - bool has_data; - unsigned long flags; - - /* - * if it is local share memory, - * check the read and write point directly. - */ - if (smsg_ipcs[dst]->smem_type == SMEM_LOCAL) { - if (tx) - return (int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) < - hd_op->tx_size; - - return BL_READL(hd_op->rx_wt_p) != BL_READL(hd_op->rx_rd_p); - } - - /* - * if it is remote share memmory read the poll_mask, - * this situation requires that the poll_mask must be accurate enough. - */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (tx) - has_data = ring->poll_mask & (POLLOUT | POLLWRNORM); - else - has_data = ring->poll_mask & (POLLIN | POLLRDNORM); - spin_unlock_irqrestore(&ring->poll_lock, flags); - - return has_data; -} - -static bool sbuf_is_task_pointer(const void *ptr) -{ - struct task_struct *task; - struct thread_info *thread_info; - - task = (struct task_struct *)ptr; - if (IS_ERR_OR_NULL(task) || !virt_addr_valid(task)) - return false; - -#ifndef CONFIG_THREAD_INFO_IN_TASK - /* in this case thread_info is in the same addres with stack thread_union*/ - if (IS_ERR_OR_NULL(task->stack) || !virt_addr_valid(task->stack)) - return false; -#endif - - thread_info = task_thread_info(task); - - if (IS_ERR_OR_NULL(thread_info) || !virt_addr_valid(thread_info)) - return false; - - return true; -} - -static struct task_struct *sbuf_wait_get_task( -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - wait_queue_t *pos, -#else - wait_queue_entry_t *pos, -#endif - u32 *b_select) -{ - struct task_struct *task; - struct poll_wqueues *table; - - if (!pos->private) - return NULL; - - /* if the private is put into wait list by sbuf_read, the struct of - * pos->private is struct task_struct - * if the private is put into list by sbuf_poll, the struct of - * pos->private is struct poll_wqueues - */ - - /* firstly, try struct poll_wqueues */ - table = (struct poll_wqueues *)pos->private; - task = table->polling_task; - if (sbuf_is_task_pointer(task)) { - *b_select = 1; - return task; - } - - /* firstly, try convert it with the struct task_struct */ - task = (struct task_struct *)pos->private; - - if (sbuf_is_task_pointer(task)) { - *b_select = 0; - return task; - } - - return NULL; -} - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) -static void sbuf_record_rdwt_owner(struct sbuf_ring *ring, int b_rx) -{ - int b_add; - int cnt = 0; - struct name_node *pos = NULL; - struct name_node *temp = NULL; - struct list_head *owner_list; - unsigned long flags; - - b_add = 1; - owner_list = b_rx ? (&ring->rx_list) : (&ring->tx_list); - - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_for_each_entry(pos, owner_list, list) { - cnt++; - if (pos->pid == current->pid) { - b_add = 0; - pos->latest = 1; - continue; - } - if (pos->latest) - pos->latest = 0; - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - - if (b_add) { - /* delete head next */ - if (cnt == MAX_RECORD_CNT) { - temp = list_first_entry(owner_list, - struct name_node, list); - list_del(&temp->list); - kfree(temp); - } - - pos = kzalloc(sizeof(*pos), GFP_KERNEL); - if (pos) { - memcpy(pos->comm, current->comm, TASK_COMM_LEN); - pos->pid = current->pid; - pos->latest = 1; - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_add_tail(&pos->list, owner_list); - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - } - } -} - -static void sbuf_destroy_rdwt_owner(struct sbuf_ring *ring) -{ - struct name_node *pos, *temp; - unsigned long flags; - - spin_lock_irqsave(&ring->rxwait.lock, flags); - /* free task node */ - list_for_each_entry_safe(pos, - temp, - &ring->rx_list, - list) { - list_del(&pos->list); - kfree(pos); - } - - list_for_each_entry_safe(pos, - temp, - &ring->tx_list, - list) { - list_del(&pos->list); - kfree(pos); - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); -} -#endif - -static void sbuf_skip_old_data(struct sbuf_mgr *sbuf) -{ - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op = NULL; - u32 i, v; - unsigned long flags; - - ring = &sbuf->rings[0]; - /* must reques resource before read or write share memory */ - if (sipc_smem_request_resource(ring->rx_pms, sbuf->dst, -1) < 0) - return; - - for (i = 0; i < sbuf->ringnr; i++) { - ring = &sbuf->rings[i]; - hd_op = &ring->header_op; - - /* clean sbuf tx ring , sbuf tx ring no need to clear */ - /* *(hd_op->tx_wt_p) = *(hd_op->tx_rd_p); */ - /* clean sbuf rx ring */ - v = BL_READL(hd_op->rx_wt_p); - BL_WRITEL(v, hd_op->rx_rd_p); - /* restore write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask = POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - } - ring = &sbuf->rings[0]; - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); -} - -static void sbuf_pms_init(struct sbuf_ring *ring, - uint8_t dst, uint8_t ch, int index) -{ - ring->need_wake_lock = true; - sprintf(ring->tx_pms_name, "sbuf-%d-%d-%d-tx", dst, ch, index); - ring->tx_pms = sprd_pms_create(dst, ring->tx_pms_name, false); - if (!ring->tx_pms) - pr_warn("create pms %s failed!\n", ring->tx_pms_name); - - sprintf(ring->rx_pms_name, "sbuf-%d-%d-%d-rx", dst, ch, index); - ring->rx_pms = sprd_pms_create(dst, ring->rx_pms_name, false); - if (!ring->rx_pms) - pr_warn("create pms %s failed!\n", ring->rx_pms_name); -} - -static void sbuf_comm_init(struct sbuf_mgr *sbuf) -{ - u32 bufnum = sbuf->ringnr; - int i; - struct sbuf_ring *ring; - - for (i = 0; i < bufnum; i++) { - ring = &sbuf->rings[i]; - init_waitqueue_head(&ring->txwait); - init_waitqueue_head(&ring->rxwait); -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - INIT_LIST_HEAD(&ring->tx_list); - INIT_LIST_HEAD(&ring->rx_list); -#endif - mutex_init(&ring->txlock); - mutex_init(&ring->rxlock); - spin_lock_init(&ring->poll_lock); - spin_lock_init(&ring->rxwait.lock); - - /* init, set write mask. */ - ring->poll_mask = POLLOUT | POLLWRNORM; - sbuf_pms_init(ring, sbuf->dst, sbuf->channel, i); - } -} - -static int sbuf_host_init(struct smsg_ipc *sipc, struct sbuf_mgr *sbuf, - u32 bufnum, u32 txbufsize, u32 rxbufsize) -{ - VOLA_SBUF_SMEM *smem; - VOLA_SBUF_RING *ringhd; - struct sbuf_ring_header_op *hd_op; - int hsize, i, rval; - phys_addr_t offset = 0; - u8 dst = sbuf->dst; - struct sbuf_ring *ring; - u32 txbuf_addr; - - sbuf->ringnr = bufnum; - - /* allocate smem */ - hsize = sizeof(struct sbuf_smem_header) + - sizeof(struct sbuf_ring_header) * bufnum; - sbuf->smem_size = hsize + (txbufsize + rxbufsize) * bufnum; - sbuf->smem_addr = smem_alloc(dst, sbuf->smem_size); - if (!sbuf->smem_addr) { - pr_err("%s: channel %d-%d, Failed to allocate smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - return -ENOMEM; - } - sbuf->dst_smem_addr = sbuf->smem_addr - sipc->smem_base + - sipc->dst_smem_base; - - pr_debug("%s: channel %d-%d, smem_addr=0x%x, smem_size=0x%x, dst_smem_addr=0x%x\n", - __func__, - sbuf->dst, - sbuf->channel, - sbuf->smem_addr, - sbuf->smem_size, - sbuf->dst_smem_addr); - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; -#endif - - pr_info("%s: channel %d-%d, offset = 0x%lx!\n", - __func__, sbuf->dst, sbuf->channel, (unsigned long)offset); - sbuf->smem_virt = shmem_ram_vmap_nocache(dst, - sbuf->smem_addr + offset, - sbuf->smem_size); - if (!sbuf->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - return -EFAULT; - } - - /* allocate rings description */ - sbuf->rings = kcalloc(bufnum, sizeof(struct sbuf_ring), GFP_KERNEL); - if (!sbuf->rings) { - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - return -ENOMEM; - } - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) { - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - kfree(sbuf->rings); - return rval; - } - - /* initialize all ring bufs */ - smem = (VOLA_SBUF_SMEM *)sbuf->smem_virt; - BL_SETL(smem->ringnr, bufnum); - for (i = 0; i < bufnum; i++) { - ringhd = (VOLA_SBUF_RING *)&smem->headers[i]; - txbuf_addr = sbuf->dst_smem_addr + hsize + - (txbufsize + rxbufsize) * i; - BL_SETL(ringhd->txbuf_addr, txbuf_addr); - BL_SETL(ringhd->txbuf_size, txbufsize); - BL_SETL(ringhd->txbuf_rdptr, 0); - BL_SETL(ringhd->txbuf_wrptr, 0); - BL_SETL(ringhd->rxbuf_addr, txbuf_addr + txbufsize); - BL_SETL(ringhd->rxbuf_size, rxbufsize); - BL_SETL(ringhd->rxbuf_rdptr, 0); - BL_SETL(ringhd->rxbuf_wrptr, 0); - - ring = &sbuf->rings[i]; - ring->header = ringhd; - ring->txbuf_virt = sbuf->smem_virt + hsize + - (txbufsize + rxbufsize) * i; - ring->rxbuf_virt = ring->txbuf_virt + txbufsize; - /* init header op */ - hd_op = &ring->header_op; - hd_op->rx_rd_p = &ringhd->rxbuf_rdptr; - hd_op->rx_wt_p = &ringhd->rxbuf_wrptr; - hd_op->rx_size = ringhd->rxbuf_size; - hd_op->tx_rd_p = &ringhd->txbuf_rdptr; - hd_op->tx_wt_p = &ringhd->txbuf_wrptr; - hd_op->tx_size = ringhd->txbuf_size; - } - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - sbuf_comm_init(sbuf); - - return 0; -} - -static int sbuf_client_init(struct smsg_ipc *sipc, struct sbuf_mgr *sbuf) -{ - VOLA_SBUF_SMEM *smem; - VOLA_SBUF_RING *ringhd; - struct sbuf_ring_header_op *hd_op; - struct sbuf_ring *ring; - int hsize, i, rval; - u32 txbufsize, rxbufsize; - phys_addr_t offset = 0; - u32 bufnum; - u8 dst = sbuf->dst; - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = sipc->high_offset; - offset = offset << 32; - pr_info("%s: channel %d-%d, offset = 0x%llx!\n", - __func__, sbuf->dst, sbuf->channel, offset); -#endif - - /* get bufnum and bufsize */ - hsize = sizeof(struct sbuf_smem_header) + - sizeof(struct sbuf_ring_header) * 1; - sbuf->smem_virt = shmem_ram_vmap_nocache(dst, - sbuf->smem_addr + offset, - hsize); - if (!sbuf->smem_virt) { - pr_err("%s: channel %d-%d, Failed to map smem for sbuf head\n", - __func__, sbuf->dst, sbuf->channel); - return -EFAULT; - } - smem = (VOLA_SBUF_SMEM *)sbuf->smem_virt; - sbuf->ringnr = smem->ringnr; - bufnum = sbuf->ringnr; - ringhd = (VOLA_SBUF_RING *)&smem->headers[0]; - txbufsize = BL_GETL(ringhd->rxbuf_size); - rxbufsize = BL_GETL(ringhd->txbuf_size); - hsize = sizeof(struct sbuf_smem_header) + - sizeof(struct sbuf_ring_header) * bufnum; - sbuf->smem_size = hsize + (txbufsize + rxbufsize) * bufnum; - pr_debug("%s: channel %d-%d, txbufsize = 0x%x, rxbufsize = 0x%x!\n", - __func__, sbuf->dst, sbuf->channel, txbufsize, rxbufsize); - pr_debug("%s: channel %d-%d, smem_size = 0x%x, ringnr = %d!\n", - __func__, sbuf->dst, sbuf->channel, sbuf->smem_size, bufnum); - shmem_ram_unmap(dst, sbuf->smem_virt); - - /* alloc debug smem */ - sbuf->smem_addr_debug = smem_alloc(dst, sbuf->smem_size); - if (!sbuf->smem_addr_debug) { - pr_err("%s: channel %d-%d,Failed to allocate debug smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - return -ENOMEM; - } - - /* get smem virtual address */ - sbuf->smem_virt = shmem_ram_vmap_nocache(dst, - sbuf->smem_addr + offset, - sbuf->smem_size); - if (!sbuf->smem_virt) { - pr_err("%s: channel %d-%d,Failed to map smem for sbuf\n", - __func__, sbuf->dst, sbuf->channel); - smem_free(dst, sbuf->smem_addr_debug, sbuf->smem_size); - return -EFAULT; - } - - /* allocate rings description */ - sbuf->rings = kcalloc(bufnum, sizeof(struct sbuf_ring), GFP_KERNEL); - if (!sbuf->rings) { - smem_free(dst, sbuf->smem_addr_debug, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - return -ENOMEM; - } - pr_info("%s: channel %d-%d, ringns = 0x%p!\n", - __func__, sbuf->dst, sbuf->channel, sbuf->rings); - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(sipc->sipc_pms, sipc->dst, -1); - if (rval < 0) { - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - shmem_ram_unmap(dst, sbuf->smem_virt); - kfree(sbuf->rings); - return rval; - } - - /* initialize all ring bufs */ - smem = (VOLA_SBUF_SMEM *)sbuf->smem_virt; - for (i = 0; i < bufnum; i++) { - ringhd = (VOLA_SBUF_RING *)&smem->headers[i]; - ring = &sbuf->rings[i]; - ring->header = ringhd; - /* host txbuf_addr */ - ring->rxbuf_virt = sbuf->smem_virt + hsize + - (txbufsize + rxbufsize) * i; - /* host rxbuf_addr */ - ring->txbuf_virt = ring->rxbuf_virt + rxbufsize; - /* init header op , client mode, rx <==> tx */ - hd_op = &ring->header_op; - hd_op->rx_rd_p = &ringhd->txbuf_rdptr; - hd_op->rx_wt_p = &ringhd->txbuf_wrptr; - hd_op->rx_size = ringhd->txbuf_size; - hd_op->tx_rd_p = &ringhd->rxbuf_rdptr; - hd_op->tx_wt_p = &ringhd->rxbuf_wrptr; - hd_op->tx_size = ringhd->rxbuf_size; - } - - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - - sbuf_comm_init(sbuf); - - return 0; -} - -static int sbuf_thread(void *data) -{ - struct sbuf_mgr *sbuf = data; - struct sbuf_ring *ring; - struct smsg mcmd, mrecv; - int rval, bufid; - struct smsg_ipc *sipc; - unsigned long flags; - - /* since the channel open may hang, we call it in the sbuf thread */ - rval = smsg_ch_open(sbuf->dst, sbuf->channel, -1); - if (rval != 0) { - pr_err("Failed to open channel %d\n", sbuf->channel); - /* assign NULL to thread poniter as failed to open channel */ - sbuf->thread = NULL; - return rval; - } - - /* if client, send SMSG_CMD_SBUF_INIT, wait sbuf SMSG_DONE_SBUF_INIT */ - sipc = smsg_ipcs[sbuf->dst]; - if (sipc->client) { - smsg_set(&mcmd, sbuf->channel, SMSG_TYPE_CMD, - SMSG_CMD_SBUF_INIT, 0); - smsg_send(sbuf->dst, &mcmd, -1); - do { - smsg_set(&mrecv, sbuf->channel, 0, 0, 0); - rval = smsg_recv(sbuf->dst, &mrecv, -1); - if (rval != 0) { - sbuf->thread = NULL; - return rval; - } - } while (mrecv.type != SMSG_TYPE_DONE || - mrecv.flag != SMSG_DONE_SBUF_INIT); - sbuf->smem_addr = mrecv.value; - pr_info("%s: channel %d-%d, done_sbuf_init, address = 0x%x!\n", - __func__, sbuf->dst, sbuf->channel, sbuf->smem_addr); - if (sbuf_client_init(sipc, sbuf)) { - sbuf->thread = NULL; - return 0; - } - sbuf->state = SBUF_STATE_READY; - } - - /* sbuf init done, handle the ring rx events */ - while (!kthread_should_stop()) { - /* monitor sbuf rdptr/wrptr update smsg */ - smsg_set(&mrecv, sbuf->channel, 0, 0, 0); - rval = smsg_recv(sbuf->dst, &mrecv, -1); - if (rval == -EIO) { - /* channel state is free */ - msleep(20); - continue; - } - - pr_debug("sbuf thread recv msg: dst=%d, channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - sbuf->dst, - sbuf->channel, - mrecv.type, - mrecv.flag, - mrecv.value); - - switch (mrecv.type) { - case SMSG_TYPE_OPEN: - pr_info("%s: channel %d-%d, state=%d, recv open msg!\n", - __func__, sbuf->dst, - sbuf->channel, sbuf->state); - if (sipc->client) - break; - - /* if channel state is already reay, reopen it - * (such as modem reset), we must skip the old - * buf data , than give open ack and reset state - * to idle - */ - if (sbuf->state == SBUF_STATE_READY) { - sbuf_skip_old_data(sbuf); - sbuf->state = SBUF_STATE_IDLE; - } - /* handle channel open */ - smsg_open_ack(sbuf->dst, sbuf->channel); - break; - case SMSG_TYPE_CLOSE: - /* handle channel close */ - sbuf_skip_old_data(sbuf); - smsg_close_ack(sbuf->dst, sbuf->channel); - sbuf->state = SBUF_STATE_IDLE; - break; - case SMSG_TYPE_CMD: - pr_info("%s: channel %d-%d state = %d, recv cmd msg, flag = %d!\n", - __func__, sbuf->dst, sbuf->channel, - sbuf->state, mrecv.flag); - if (sipc->client) - break; - - /* respond cmd done for sbuf init only state is idle */ - if (sbuf->state == SBUF_STATE_IDLE && - mrecv.flag == SMSG_CMD_SBUF_INIT) { - smsg_set(&mcmd, - sbuf->channel, - SMSG_TYPE_DONE, - SMSG_DONE_SBUF_INIT, - sbuf->dst_smem_addr); - smsg_send(sbuf->dst, &mcmd, -1); - sbuf->state = SBUF_STATE_READY; - for (bufid = 0; bufid < sbuf->ringnr; bufid++) { - ring = &sbuf->rings[bufid]; - if (ring->handler) - ring->handler(SBUF_NOTIFY_READY, - ring->data); - } - } - break; - case SMSG_TYPE_EVENT: - bufid = mrecv.value; - WARN_ON(bufid >= sbuf->ringnr); - ring = &sbuf->rings[bufid]; - switch (mrecv.flag) { - case SMSG_EVENT_SBUF_RDPTR: - if (ring->need_wake_lock) - sprd_pms_request_wakelock_period(ring->tx_pms, - 500); - /* set write mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - wake_up_interruptible_all(&ring->txwait); - if (ring->handler) - ring->handler(SBUF_NOTIFY_WRITE, - ring->data); - break; - case SMSG_EVENT_SBUF_WRPTR: - /* set read mask. */ - spin_lock_irqsave(&ring->poll_lock, flags); - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - if (ring->need_wake_lock) - sprd_pms_request_wakelock_period(ring->rx_pms, - 500); - wake_up_interruptible_all(&ring->rxwait); - if (ring->handler) - ring->handler(SBUF_NOTIFY_READ, - ring->data); - break; - default: - rval = 1; - break; - } - break; - default: - rval = 1; - break; - }; - - if (rval) { - pr_info("non-handled sbuf msg: %d-%d, %d, %d, %d\n", - sbuf->dst, - sbuf->channel, - mrecv.type, - mrecv.flag, - mrecv.value); - rval = 0; - } - /* unlock sipc channel wake lock */ - smsg_ch_wake_unlock(sbuf->dst, sbuf->channel); - } - - return 0; -} - - -int sbuf_create(u8 dst, u8 channel, u32 bufnum, u32 txbufsize, u32 rxbufsize) -{ - struct sbuf_mgr *sbuf; - u8 ch_index; - int ret; - struct smsg_ipc *sipc = NULL; - struct sched_param param = {.sched_priority = 10}; - - sipc = smsg_ipcs[dst]; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - pr_debug("%s dst=%d, chanel=%d, bufnum=%d, txbufsize=0x%x, rxbufsize=0x%x\n", - __func__, - dst, - channel, - bufnum, - txbufsize, - rxbufsize); - - if (dst >= SIPC_ID_NR || !sipc) { - pr_err("%s: dst = %d is invalid\n", __func__, dst); - return -EINVAL; - } - - sbuf = kzalloc(sizeof(*sbuf), GFP_KERNEL); - if (!sbuf) - return -ENOMEM; - - sbuf->state = SBUF_STATE_IDLE; - sbuf->dst = dst; - sbuf->channel = channel; - - /* The dst smem type is pcie, need force send smsg in sbuf_write. */ - if (sipc->type == SIPC_BASE_PCIE && sipc->smem_type == SMEM_LOCAL) - sbuf->force_send = true; - - if (!sipc->client) { - ret = sbuf_host_init(sipc, sbuf, bufnum, txbufsize, rxbufsize); - if (ret) { - kfree(sbuf); - return ret; - } - } - - sbuf->thread = kthread_create(sbuf_thread, sbuf, - "sbuf-%d-%d", dst, channel); - if (IS_ERR(sbuf->thread)) { - pr_err("Failed to create kthread: sbuf-%d-%d\n", dst, channel); - if (!sipc->client) { - kfree(sbuf->rings); - shmem_ram_unmap(dst, sbuf->smem_virt); - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - } - ret = PTR_ERR(sbuf->thread); - kfree(sbuf); - return ret; - } - - sbufs[dst][ch_index] = sbuf; - - /*set the thread as a real time thread, and its priority is 10*/ - sched_setscheduler(sbuf->thread, SCHED_FIFO, ¶m); - wake_up_process(sbuf->thread); - - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_create); - -void sbuf_set_no_need_wake_lock(u8 dst, u8 channel, u32 bufnum) -{ - u8 ch_index; - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf || sbuf->ringnr <= bufnum) - return; - - ring = &sbuf->rings[bufnum]; - ring->need_wake_lock = false; -} -EXPORT_SYMBOL_GPL(sbuf_set_no_need_wake_lock); - - -void sbuf_down(u8 dst, u8 channel) -{ - struct sbuf_mgr *sbuf; - u8 ch_index; - int i; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return; - sbuf->state = SBUF_STATE_IDLE; - if (sbuf->rings) { - for (i = 0; i < sbuf->ringnr; i++) { - wake_up_interruptible_all(&sbuf->rings[i].txwait); - wake_up_interruptible_all(&sbuf->rings[i].rxwait); - } - } - pr_info("%s: channel=%d sbuf down success\n", __func__, channel); -} - -void sbuf_destroy(u8 dst, u8 channel) -{ - struct sbuf_mgr *sbuf; - int i; - u8 ch_index; - struct smsg_ipc *sipc; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return; - - sbuf->state = SBUF_STATE_IDLE; - smsg_ch_close(dst, channel, -1); - - /* stop sbuf thread if it's created successfully and still alive */ - if (!IS_ERR_OR_NULL(sbuf->thread)) - kthread_stop(sbuf->thread); - - if (sbuf->rings) { - for (i = 0; i < sbuf->ringnr; i++) { - wake_up_interruptible_all(&sbuf->rings[i].txwait); - wake_up_interruptible_all(&sbuf->rings[i].rxwait); -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - sbuf_destroy_rdwt_owner(&sbuf->rings[i]); -#endif - sprd_pms_destroy(sbuf->rings[i].tx_pms); - sprd_pms_destroy(sbuf->rings[i].rx_pms); - } - kfree(sbuf->rings); - } - - if (sbuf->smem_virt) - shmem_ram_unmap(dst, sbuf->smem_virt); - - sipc = smsg_ipcs[dst]; - if (sipc->client) - smem_free(dst, sbuf->smem_addr_debug, sbuf->smem_size); - else - smem_free(dst, sbuf->smem_addr, sbuf->smem_size); - - kfree(sbuf); - - sbufs[dst][ch_index] = NULL; -} -EXPORT_SYMBOL_GPL(sbuf_destroy); - -int sbuf_write(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - struct smsg mevt; - void *txpos; - int rval, left, tail, txsize; - u8 ch_index; - union sbuf_buf u_buf; - bool no_data; - unsigned long flags; - u32 v; - - u_buf.buf = buf; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return -ENODEV; - ring = &sbuf->rings[bufid]; - hd_op = &ring->header_op; - if (sbuf->state != SBUF_STATE_READY) { - pr_info("sbuf-%d-%d not ready to write!\n", - dst, channel); - return -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, bufid=%d, len=%d, timeout=%d\n", - __func__, - dst, - channel, - bufid, - len, - timeout); - - rval = 0; - left = len; - - if (timeout) { - mutex_lock_interruptible(&ring->txlock); - } else { - if (!mutex_trylock(&ring->txlock)) { - pr_debug("sbuf_read busy, dst=%d, channel=%d, bufid=%d\n", - dst, channel, bufid); - return -EBUSY; - } - } - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - sbuf_record_rdwt_owner(ring, 0); -#endif - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->txlock); - return rval; - } - - pr_debug("%s: channel=%d, wrptr=%d, rdptr=%d\n", - __func__, - channel, - BL_READL(hd_op->tx_wt_p), - BL_READL(hd_op->tx_rd_p)); - no_data = ((int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) >= - hd_op->tx_size); - - /* update write mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (no_data) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, sbuf->dst); - - if (no_data) { - if (timeout == 0) { - pr_info("%s: %d-%d ring %d txbuf is full!\n", - __func__, dst, channel, bufid); - rval = -EBUSY; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible( - ring->txwait, - sbuf_has_data(ring, dst, true) || - sbuf->state == SBUF_STATE_IDLE); - if (rval < 0) - pr_debug("%s: wait interrupted!\n", __func__); - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: sbuf state is idle!\n", __func__); - rval = -EIO; - } - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout( - ring->txwait, - sbuf_has_data(ring, dst, true) || - sbuf->state == SBUF_STATE_IDLE, - timeout); - if (rval < 0) { - pr_debug("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: sbuf state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) { - mutex_unlock(&ring->txlock); - return rval; - } - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->tx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->txlock); - return rval; - } - - while (left && (int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) < - hd_op->tx_size && sbuf->state == SBUF_STATE_READY) { - /* calc txpos & txsize */ - txpos = ring->txbuf_virt + - BL_READL(hd_op->tx_wt_p) % hd_op->tx_size; - txsize = hd_op->tx_size - - (int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)); - txsize = min(txsize, left); - - tail = txpos + txsize - (ring->txbuf_virt + hd_op->tx_size); - if (tail > 0) { - /* ring buffer is rounded */ - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(txpos, u_buf.buf, txsize - tail); - unalign_memcpy(ring->txbuf_virt, - u_buf.buf + txsize - tail, tail); - } else { - if (unalign_copy_from_user( - txpos, - u_buf.ubuf, - txsize - tail) || - unalign_copy_from_user( - ring->txbuf_virt, - u_buf.ubuf + txsize - tail, - tail)) { - pr_err("%s:failed to copy from user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } else { - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(txpos, u_buf.buf, txsize); - } else { - /* handle the user space address */ - if (unalign_copy_from_user( - txpos, - u_buf.ubuf, - txsize)) { - pr_err("%s:failed to copy from user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } - - pr_debug("%s: channel=%d, txpos=%p, txsize=%d\n", - __func__, channel, txpos, txsize); - - /* update tx wrptr */ - v = BL_READL(hd_op->tx_wt_p) + txsize; - BL_WRITEL(v, hd_op->tx_wt_p); - /* - * force send be true or tx ringbuf is empty, - * need to notify peer side - */ - if (sbuf->force_send || - BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p) == txsize) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBUF_WRPTR, - bufid); - smsg_send(dst, &mevt, -1); - } - - left -= txsize; - u_buf.buf += txsize; - } - - /* update write mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if ((int)(BL_READL(hd_op->tx_wt_p) - BL_READL(hd_op->tx_rd_p)) >= - hd_op->tx_size) - ring->poll_mask &= ~(POLLOUT | POLLWRNORM); - else - ring->poll_mask |= POLLOUT | POLLWRNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->tx_pms, sbuf->dst); - if (ring->need_wake_lock) - sprd_pms_release_wakelock_later(ring->tx_pms, 20); - - mutex_unlock(&ring->txlock); - - pr_debug("%s: done, channel=%d, len=%d\n", - __func__, channel, len - left); - - if (len == left) - return rval; - else - return (len - left); -} -EXPORT_SYMBOL_GPL(sbuf_write); - -int sbuf_read(u8 dst, u8 channel, u32 bufid, - void *buf, u32 len, int timeout) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - struct smsg mevt; - void *rxpos; - int rval, left, tail, rxsize; - u8 ch_index; - union sbuf_buf u_buf; - bool no_data; - unsigned long flags; - u32 v; - - u_buf.buf = buf; - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return -ENODEV; - ring = &sbuf->rings[bufid]; - hd_op = &ring->header_op; - - if (sbuf->state != SBUF_STATE_READY) { - pr_debug("sbuf-%d-%d not ready to read!\n", dst, channel); - return -ENODEV; - } - - pr_debug("%s:dst=%d, channel=%d, bufid=%d, len=%d, timeout=%d\n", - __func__, dst, channel, bufid, len, timeout); - - rval = 0; - left = len; - - if (timeout) { - mutex_lock_interruptible(&ring->rxlock); - } else { - if (!mutex_trylock(&ring->rxlock)) { - pr_debug("%s: busy!,dst=%d, channel=%d, bufid=%d\n", - __func__, dst, channel, bufid); - return -EBUSY; - } - } - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - sbuf_record_rdwt_owner(ring, 1); -#endif - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->rxlock); - return rval; - } - - pr_debug("%s: channel=%d, wrptr=%d, rdptr=%d\n", - __func__, - channel, - BL_READL(hd_op->rx_wt_p), - BL_READL(hd_op->rx_rd_p)); - no_data = (BL_READL(hd_op->rx_wt_p) == BL_READL(hd_op->rx_rd_p)); - /* update read mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (no_data) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); - - if (no_data) { - if (timeout == 0) { - /* no wait */ - pr_debug("%s: %d-%d ring %d rxbuf is empty!\n", - __func__, dst, channel, bufid); - rval = -ENODATA; - } else if (timeout < 0) { - /* wait forever */ - rval = wait_event_interruptible( - ring->rxwait, - sbuf_has_data(ring, dst, false) || - sbuf->state == SBUF_STATE_IDLE); - if (rval < 0) - pr_debug("%s: wait interrupted!\n", __func__); - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: sbuf state is idle!\n", __func__); - rval = -EIO; - } - } else { - /* wait timeout */ - rval = wait_event_interruptible_timeout( - ring->rxwait, - sbuf_has_data(ring, dst, false) || - sbuf->state == SBUF_STATE_IDLE, timeout); - if (rval < 0) { - pr_debug("%s: wait interrupted!\n", __func__); - } else if (rval == 0) { - pr_info("%s: wait timeout!\n", __func__); - rval = -ETIME; - } - - if (sbuf->state == SBUF_STATE_IDLE) { - pr_err("%s: state is idle!\n", __func__); - rval = -EIO; - } - } - } - - if (rval < 0) { - mutex_unlock(&ring->rxlock); - return rval; - } - - /* must request resource before read or write share memory */ - rval = sipc_smem_request_resource(ring->rx_pms, sbuf->dst, -1); - if (rval < 0) { - mutex_unlock(&ring->rxlock); - return rval; - } - - while (left && - (BL_READL(hd_op->rx_wt_p) != BL_READL(hd_op->rx_rd_p)) && - sbuf->state == SBUF_STATE_READY) { - /* calc rxpos & rxsize */ - rxpos = ring->rxbuf_virt + - BL_READL(hd_op->rx_rd_p) % hd_op->rx_size; - rxsize = (int)(BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p)); - /* check overrun */ - if (rxsize > hd_op->rx_size) - pr_err("%s: bufid = %d, channel= %d rxsize=0x%x, rdptr=%d, wrptr=%d", - __func__, - bufid, - channel, - rxsize, - BL_READL(hd_op->rx_wt_p), - BL_READL(hd_op->rx_rd_p)); - - rxsize = min(rxsize, left); - - pr_debug("%s: channel=%d, buf=%p, rxpos=%p, rxsize=%d\n", - __func__, channel, u_buf.buf, rxpos, rxsize); - - tail = rxpos + rxsize - (ring->rxbuf_virt + hd_op->rx_size); - - if (tail > 0) { - /* ring buffer is rounded */ - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(u_buf.buf, rxpos, rxsize - tail); - unalign_memcpy(u_buf.buf + rxsize - tail, - ring->rxbuf_virt, tail); - } else { - /* handle the user space address */ - if (unalign_copy_to_user(u_buf.ubuf, - rxpos, - rxsize - tail) || - unalign_copy_to_user(u_buf.ubuf - + rxsize - tail, - ring->rxbuf_virt, - tail)) { - pr_err("%s: failed to copy to user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } else { - if ((uintptr_t)u_buf.buf > TASK_SIZE) { - unalign_memcpy(u_buf.buf, rxpos, rxsize); - } else { - /* handle the user space address */ - if (unalign_copy_to_user(u_buf.ubuf, - rxpos, rxsize)) { - pr_err("%s: failed to copy to user!\n", - __func__); - rval = -EFAULT; - break; - } - } - } - - /* update rx rdptr */ - v = BL_READL(hd_op->rx_rd_p) + rxsize; - BL_WRITEL(v, hd_op->rx_rd_p); - /* rx ringbuf is full ,so need to notify peer side */ - if (BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p) == - hd_op->rx_size - rxsize) { - smsg_set(&mevt, channel, - SMSG_TYPE_EVENT, - SMSG_EVENT_SBUF_RDPTR, - bufid); - smsg_send(dst, &mevt, -1); - } - - left -= rxsize; - u_buf.buf += rxsize; - } - - /* update read mask */ - spin_lock_irqsave(&ring->poll_lock, flags); - if (BL_READL(hd_op->rx_wt_p) == BL_READL(hd_op->rx_rd_p)) - ring->poll_mask &= ~(POLLIN | POLLRDNORM); - else - ring->poll_mask |= POLLIN | POLLRDNORM; - spin_unlock_irqrestore(&ring->poll_lock, flags); - - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); - if (ring->need_wake_lock) - sprd_pms_release_wakelock_later(ring->rx_pms, 20); - - mutex_unlock(&ring->rxlock); - - pr_debug("%s: done, channel=%d, len=%d", __func__, channel, len - left); - - if (len == left) - return rval; - else - return (len - left); -} -EXPORT_SYMBOL_GPL(sbuf_read); - -int sbuf_poll_wait(u8 dst, u8 channel, u32 bufid, - struct file *filp, poll_table *wait) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - unsigned int mask = 0; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return mask; - } - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return mask; - ring = &sbuf->rings[bufid]; - hd_op = &ring->header_op; - if (sbuf->state != SBUF_STATE_READY) { - pr_err("sbuf-%d-%d not ready to poll !\n", dst, channel); - return mask; - } - - poll_wait(filp, &ring->txwait, wait); - poll_wait(filp, &ring->rxwait, wait); - - - if (sbuf_has_data(ring, dst, true)) - mask |= POLLOUT | POLLWRNORM; - - if (sbuf_has_data(ring, dst, false)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} -EXPORT_SYMBOL_GPL(sbuf_poll_wait); - -int sbuf_status(u8 dst, u8 channel) -{ - struct sbuf_mgr *sbuf; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - sbuf = sbufs[dst][ch_index]; - - if (!sbuf) - return -ENODEV; - if (sbuf->state != SBUF_STATE_READY) - return -ENODEV; - - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_status); - -int sbuf_register_notifier(u8 dst, u8 channel, u32 bufid, - void (*handler)(int event, void *data), void *data) -{ - struct sbuf_mgr *sbuf; - struct sbuf_ring *ring = NULL; - u8 ch_index; - - ch_index = sipc_channel2index(channel); - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - sbuf = sbufs[dst][ch_index]; - if (!sbuf) - return -ENODEV; - ring = &sbuf->rings[bufid]; - ring->handler = handler; - ring->data = data; - - if (sbuf->state == SBUF_STATE_READY) - handler(SBUF_NOTIFY_READ, data); - - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_register_notifier); - -void sbuf_get_status(u8 dst, char *status_info, int size) -{ - struct sbuf_mgr *sbuf = NULL; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - wait_queue_t *pos; -#else - wait_queue_entry_t *pos; -#endif - struct task_struct *task; - unsigned long flags; - int i, n, len, cnt; - u32 b_select; - char *phead; -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - struct name_node *node = NULL; -#endif - - len = strlen(status_info); - if (!status_info || size < 0 || dst >= SIPC_ID_NR) - return; - - for (i = 0; i < SMSG_VALID_CH_NR; i++) { - sbuf = sbufs[dst][i]; - if (!sbuf) - continue; - - ring = &sbuf->rings[0]; - /* must request resource before read or write share memory */ - if (sipc_smem_request_resource(ring->rx_pms, dst, 1000) < 0) - continue; - - for (n = 0; n < sbuf->ringnr && len < size; n++) { - ring = &sbuf->rings[n]; - hd_op = &ring->header_op; - - if ((BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p)) - < hd_op->rx_size) - continue; - - snprintf(status_info + len, - size - len, - "ch-%d-ring-%d is full.\n", - sbuf->channel, - n); - len = strlen(status_info); - - /* show all rxwait task */ - spin_lock_irqsave(&ring->rxwait.lock, flags); - cnt = 0; - - list_for_each_entry(pos, -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - &ring->rxwait.task_list, - task_list -#else - &ring->rxwait.head, - entry -#endif - ) { - task = sbuf_wait_get_task(pos, &b_select); - if (!task) - continue; - - if (b_select) - phead = "rxwait task"; - else - phead = "select task"; - - snprintf( - status_info + len, - size - len, - "%s %d: %s, state=0x%lx, pid=%d.\n", - phead, - cnt, task->comm, - task->state, task->pid); - cnt++; - len = strlen(status_info); - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - - /* only show the latest ever read task */ -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_for_each_entry(node, &ring->rx_list, list) { - if (node->latest) { - snprintf( - status_info + len, - size - len, - "read task: %s, pid = %d.\n", - node->comm, - node->pid); - break; - } - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); -#endif - } - ring = &sbuf->rings[0]; - /* release resource */ - sipc_smem_release_resource(ring->rx_pms, sbuf->dst); - } -} -EXPORT_SYMBOL_GPL(sbuf_get_status); - -#if defined(CONFIG_DEBUG_FS) -static void sbuf_debug_task_show(struct seq_file *m, - struct sbuf_mgr *sbuf, int task_type) -{ - int n, cnt; - u32 b_select; - unsigned long flags; - struct sbuf_ring *ring = NULL; - wait_queue_head_t *phead; - char *buf; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - wait_queue_t *pos; -#else - wait_queue_entry_t *pos; -#endif - struct task_struct *task; - - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - cnt = 0; - - if (task_type == TASK_RXWAIT) { - phead = &ring->rxwait; - buf = "rxwait task"; - } else if (task_type == TASK_TXWAIT) { - phead = &ring->txwait; - buf = "txwait task"; - } else { - phead = &ring->rxwait; - buf = "select task"; - } - - spin_lock_irqsave(&phead->lock, flags); - - list_for_each_entry(pos, -#if (LINUX_VERSION_CODE <= KERNEL_VERSION( 4,10,0 )) - &phead->task_list, task_list -#else - &phead->head, entry -#endif - ){ - task = sbuf_wait_get_task(pos, &b_select); - if (!task) - continue; - - if (b_select && (task_type != TASK_SELECT)) - continue; - - seq_printf(m, " ring[%2d]: %s %d ", - n, - buf, - cnt); - seq_printf(m, ": %s, state = 0x%lx, pid = %d\n", - task->comm, - task->state, - task->pid); - cnt++; - } - spin_unlock_irqrestore( - &phead->lock, - flags); - } -} - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) -static void sbuf_debug_list_show(struct seq_file *m, - struct sbuf_mgr *sbuf, int b_rx) -{ - int n, cnt; - struct sbuf_ring *ring = NULL; - struct list_head *plist; - char *buf; - struct name_node *node = NULL; - unsigned long flags; - - /* list all sbuf task list */ - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - cnt = 0; - - if (b_rx) { - plist = &ring->rx_list; - buf = "read task"; - } else { - plist = &ring->tx_list; - buf = "write task"; - } - - spin_lock_irqsave(&ring->rxwait.lock, flags); - list_for_each_entry(node, plist, list) { - seq_printf(m, " ring[%2d]: %s %d : %s, pid = %d, latest = %d\n", - n, - buf, - cnt, - node->comm, - node->pid, - node->latest); - cnt++; - } - spin_unlock_irqrestore(&ring->rxwait.lock, flags); - } -} -#endif - -static int sbuf_debug_show(struct seq_file *m, void *private) -{ - struct sbuf_mgr *sbuf = NULL; - struct sbuf_ring *ring = NULL; - struct sbuf_ring_header_op *hd_op; - int i, j, n, cnt; - struct smsg_ipc *sipc = NULL; - - for (i = 0; i < SIPC_ID_NR; i++) { - sipc = smsg_ipcs[i]; - if (!sipc) - continue; - - /* must request resource before read or write share memory */ - if (sipc_smem_request_resource(sipc->sipc_pms, - sipc->dst, 1000) < 0) - continue; - - sipc_debug_putline(m, '*', 120); - seq_printf(m, "dst: 0x%0x, sipc: %s:\n", i, sipc->name); - sipc_debug_putline(m, '*', 120); - - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - sbuf = sbufs[i][j]; - if (!sbuf) - continue; - /* list a sbuf channel */ - sipc_debug_putline(m, '-', 100); - seq_printf(m, "sbuf_%d_%03d, state: %d, force: %d", - sbuf->dst, - sbuf->channel, - sbuf->state, - sbuf->force_send); - seq_printf(m, "virt: 0x%lx, phy: 0x%0x, map: 0x%x", - (unsigned long)sbuf->smem_virt, - sbuf->smem_addr, - sbuf->dst_smem_addr); - seq_printf(m, " size: 0x%0x, ringnr: %d\n", - sbuf->smem_size, - sbuf->ringnr); - sipc_debug_putline(m, '-', 100); - - /* list all sbuf ring info list in a chanel */ - sipc_debug_putline(m, '-', 80); - seq_puts(m, " 1. all sbuf ring info list:\n"); - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - hd_op = &ring->header_op; - if (BL_READL(hd_op->tx_wt_p) == 0 && - BL_READL(hd_op->rx_wt_p) == 0) - continue; - - seq_printf(m, " rx ring[%2d]: addr: 0x%0x, mask: 0x%x", - n, ring->header->rxbuf_addr, - ring->poll_mask); - seq_printf(m, "rp: 0x%0x, wp: 0x%0x, size: 0x%0x\n", - BL_READL(hd_op->rx_rd_p), - BL_READL(hd_op->rx_wt_p), - hd_op->rx_size); - - seq_printf(m, " tx ring[%2d]: addr: 0x%0x, ", - n, ring->header->txbuf_addr); - seq_printf(m, "rp: 0x%0x, wp: 0x%0x, size: 0x%0x\n", - BL_READL(hd_op->tx_rd_p), - BL_READL(hd_op->tx_wt_p), - hd_op->tx_size); - } - - /* list all sbuf rxwait/txwait in a chanel */; - sipc_debug_putline(m, '-', 80); - seq_puts(m, " 2. all waittask list:\n"); - sbuf_debug_task_show(m, sbuf, TASK_RXWAIT); - sbuf_debug_task_show(m, sbuf, TASK_TXWAIT); - sbuf_debug_task_show(m, sbuf, TASK_SELECT); - -#ifdef SIPC_DEBUG_SBUF_RDWT_OWNER - /* list all sbuf ever read task list in a chanel */; - sipc_debug_putline(m, '-', 80); - seq_puts(m, " 3. all ever rdwt list:\n"); - sbuf_debug_list_show(m, sbuf, 1); - sbuf_debug_list_show(m, sbuf, 0); -#endif - - /* list all rx full ring list in a chanel */ - cnt = 0; - for (n = 0; n < sbuf->ringnr; n++) { - ring = &sbuf->rings[n]; - hd_op = &ring->header_op; - if ((BL_READL(hd_op->rx_wt_p) - BL_READL(hd_op->rx_rd_p)) - == hd_op->rx_size) { - if (cnt == 0) { - sipc_debug_putline(m, '-', 80); - seq_puts(m, " x. all rx full ring list:\n"); - } - cnt++; - seq_printf(m, " ring[%2d]\n", n); - } - } - } - /* release resource */ - sipc_smem_release_resource(sipc->sipc_pms, sipc->dst); - } - - return 0; -} - -static int sbuf_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, sbuf_debug_show, inode->i_private); -} - -static const struct file_operations sbuf_debug_fops = { - .open = sbuf_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int sbuf_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("sbuf", 0444, - (struct dentry *)root, - NULL, &sbuf_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(sbuf_init_debugfs); - -#endif /* CONFIG_DEBUG_FS */ - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SBUF driver"); -MODULE_LICENSE("GPL v2"); diff --git a/quectel_SRPD_PCIE/src/sipc/sbuf.h b/quectel_SRPD_PCIE/src/sipc/sbuf.h deleted file mode 100644 index 80104f0..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sbuf.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SBUF_H -#define __SBUF_H - -/* flag for CMD/DONE msg type */ -#define SMSG_CMD_SBUF_INIT 0x0001 -#define SMSG_DONE_SBUF_INIT 0x0002 - -/* flag for EVENT msg type */ -#define SMSG_EVENT_SBUF_WRPTR 0x0001 -#define SMSG_EVENT_SBUF_RDPTR 0x0002 - -#if defined(CONFIG_DEBUG_FS) -#define SIPC_DEBUG_SBUF_RDWT_OWNER -#define MAX_RECORD_CNT 0x10 -#endif - -/* ring buf header */ -struct sbuf_ring_header { - /* send-buffer info */ - u32 txbuf_addr; - u32 txbuf_size; - u32 txbuf_rdptr; - u32 txbuf_wrptr; - - /* recv-buffer info */ - u32 rxbuf_addr; - u32 rxbuf_size; - u32 rxbuf_rdptr; - u32 rxbuf_wrptr; -}; - -struct sbuf_ring_header_op { - /* - * this points point to share memory - * for update rdptr and wtptr on share memory - */ - volatile u32 *rx_rd_p; - volatile u32 *rx_wt_p; - volatile u32 *tx_rd_p; - volatile u32 *tx_wt_p; - - /* - * this member copy from share memory, - * because this contents will not change on share memory - */ - u32 rx_size;/* rxbuf_size */ - u32 tx_size;/* txbuf_size */ -}; - -/* sbuf_mem is the structure of smem for rings */ -struct sbuf_smem_header { - u32 ringnr; - - struct sbuf_ring_header headers[0]; -}; - -struct sbuf_ring { - /* tx/rx buffer info */ - volatile struct sbuf_ring_header *header; - struct sbuf_ring_header_op header_op; - - void *txbuf_virt; - void *rxbuf_virt; - - /* send/recv wait queue */ - wait_queue_head_t txwait; - wait_queue_head_t rxwait; - -#if defined(SIPC_DEBUG_SBUF_RDWT_OWNER) - /* record all task histoy */ - struct list_head tx_list; - struct list_head rx_list; -#endif - - /* send/recv mutex */ - struct mutex txlock; - struct mutex rxlock; - - struct sprd_pms *tx_pms; - struct sprd_pms *rx_pms; - char tx_pms_name[20]; - char rx_pms_name[20]; - - bool need_wake_lock; - unsigned int poll_mask; - /* protect poll_mask member */ - spinlock_t poll_lock; - - void (*handler)(int event, void *data); - void *data; -}; - -#define SBUF_STATE_IDLE 0 -#define SBUF_STATE_READY 1 - -struct sbuf_mgr { - u8 dst; - u8 channel; - bool force_send; - u32 state; - - void *smem_virt; - u32 smem_addr; - u32 smem_size; - - u32 smem_addr_debug; - u32 dst_smem_addr; - u32 ringnr; - - struct sbuf_ring *rings; - struct task_struct *thread; -}; -#endif diff --git a/quectel_SRPD_PCIE/src/sipc/sipc.c b/quectel_SRPD_PCIE/src/sipc/sipc.c deleted file mode 100644 index ee256fa..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sipc.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "sipc_priv.h" - -#define MBOX_BAMK "mbox" -#define PCIE_BAMK "pcie" - -enum { - NORMAL_MODE = 0, - CHARGE_MODE, - CALI_MODE -}; - -#define CALI_LATENCY (10000 * 1000) -#define NORMAL_LATENCY (1 * 1000) - -/* - * In charge mode, will only boot pm system, - * so just create pm systen sipc. - */ -static u8 g_boot_mode = NORMAL_MODE; -/* -static int __init sipc_early_mode(char *str) -{ - if (!memcmp(str, "charger", 7)) - g_boot_mode = CHARGE_MODE; - else if (!memcmp(str, "cali", 4)) - g_boot_mode = CALI_MODE; - else - g_boot_mode = NORMAL_MODE; - - return 0; -} - -early_param("androidboot.mode", sipc_early_mode); -*/ - -#if defined(CONFIG_DEBUG_FS) -void sipc_debug_putline(struct seq_file *m, char c, int n) -{ - char buf[300]; - int i, max, len; - - /* buf will end with '\n' and 0 */ - max = ARRAY_SIZE(buf) - 2; - len = (n > max) ? max : n; - - for (i = 0; i < len; i++) - buf[i] = c; - - buf[i] = '\n'; - buf[i + 1] = 0; - - seq_puts(m, buf); -} -EXPORT_SYMBOL_GPL(sipc_debug_putline); -#endif - -static u32 sipc_rxirq_status(u8 dst) -{ - return 0; -} - -static void sipc_rxirq_clear(u8 dst) -{ - -} - -static void sipc_txirq_trigger(u8 dst, u64 msg) -{ - struct smsg_ipc *ipc; - - ipc = smsg_ipcs[dst]; - - if (ipc) { -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_raw_sent(ipc->core_id, msg); - return; - } -#endif - - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - sprd_ep_dev_raise_irq(ipc->ep_dev, PCIE_DBELL_SIPC_IRQ); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - sprd_pci_epf_raise_irq(ipc->ep_fun, PCIE_MSI_SIPC_IRQ); -#endif - return; - } - } -} - -#ifdef SPRD_PCIE_USE_DTS -static int sipc_parse_dt(struct smsg_ipc *ipc, - struct device_node *np, struct device *dev) -{ - u32 val[3]; - int ret; - const char *type; - - /* get name */ - ret = of_property_read_string(np, "sprd,name", &ipc->name); - if (ret) - return ret; - - pr_info("sipc: name=%s\n", ipc->name); - - /* get sipc type, optional */ - if (of_property_read_string(np, "sprd,type", &type) == 0) { - pr_info("sipc: type=%s\n", type); - if (strcmp(MBOX_BAMK, type) == 0) - ipc->type = SIPC_BASE_MBOX; - else if (strcmp(PCIE_BAMK, type) == 0) - ipc->type = SIPC_BASE_PCIE; - } - - /* get sipc client, optional */ - if (of_property_read_u32_array(np, "sprd,client", val, 1) == 0) { - ipc->client = (u8)val[0]; - pr_info("sipc: client=%d\n", ipc->client); - } - - /* get sipc dst */ - ret = of_property_read_u32_array(np, "sprd,dst", val, 1); - if (!ret) { - ipc->dst = (u8)val[0]; - pr_info("sipc: dst =%d\n", ipc->dst); - } - - if (ret || ipc->dst >= SIPC_ID_NR) { - pr_err("sipc: dst err, ret =%d.\n", ret); - return ret; - } - -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - /* get core id */ - ipc->core_id = (u8)MBOX_INVALID_CORE; - ret = of_property_read_u32_array(np, "sprd,core", val, 1); - if (!ret) { - ipc->core_id = (u8)val[0]; - pr_info("sipc: core=%d\n", ipc->core_id); - } else { - pr_err("sipc: core err, ret =%d.\n", ret); - return ret; - } - - /* get core sensor id, optional*/ - ipc->core_sensor_id = (u8)MBOX_INVALID_CORE; - if (of_property_read_u32_array(np, "sprd,core_sensor", - val, 1) == 0) { - ipc->core_sensor_id = (u8)val[0]; - pr_info("sipc: core_sensor=%d\n", ipc->core_sensor_id); - } - } -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_SPRD_PCIE - struct device_node *pdev_node; -#endif - - ret = of_property_read_u32_array(np, - "sprd,ep-dev", - &ipc->ep_dev, - 1); - pr_info("sipc: ep_dev=%d\n", ipc->ep_dev); - if (ret || ipc->ep_dev >= PCIE_EP_NR) { - pr_err("sipc: ep_dev err, ret =%d.\n", ret); - return ret; - } - -#ifdef CONFIG_SPRD_PCIE - /* get pcie rc ctrl device */ - pdev_node = of_parse_phandle(np, "sprd,rc-ctrl", 0); - if (!pdev_node) { - pr_err("sipc: sprd,rc-ctrl err.\n"); - return -ENODEV; - } - ipc->pcie_dev = of_find_device_by_node(pdev_node); - of_node_put(pdev_node); - - if (!ipc->pcie_dev) { - pr_err("sipc: find pcie_dev err.\n"); - return -ENODEV; - } -#endif - } -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - if (ipc->type == SIPC_BASE_PCIE) { - ret = of_property_read_u32_array(np, - "sprd,ep-fun", - &ipc->ep_fun, - 1); - pr_info("sipc: ep_fun=%d\n", ipc->ep_fun); - if (ret || ipc->ep_fun >= SPRD_FUNCTION_MAX) { - pr_err("sipc: ep_fun err, ret =%d.\n", ret); - return ret; - } - - /* parse doolbell irq */ - ret = of_irq_get(np, 0); - if (ret < 0) { - pr_err("sipc: doorbell irq err, ret=%d\n", ret); - return -EINVAL; - } - ipc->irq = ret; - pr_info("sipc: irq=%d\n", ipc->irq); - } -#endif - - /* get smem type */ - ret = of_property_read_u32_array(np, - "sprd,smem-type", - &val[0], - 1); - if (!ret) - ipc->smem_type = (enum smem_type)val[0]; - else - ipc->smem_type = SMEM_LOCAL; - - pr_info("sipc: smem_type = %d, ret =%d\n", ipc->smem_type, ret); - - /* get smem info */ - ret = of_property_read_u32_array(np, - "sprd,smem-info", - val, - 3); - if (ret) { - pr_err("sipc: parse smem info failed.\n"); - return ret; - } - ipc->smem_base = val[0]; - ipc->dst_smem_base = val[1]; - ipc->smem_size = val[2]; - pr_info("sipc: smem_base=0x%x, dst_smem_base=0x%x, smem_size=0x%x\n", - ipc->smem_base, ipc->dst_smem_base, ipc->smem_size); - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - /* try to get high_offset */ - ret = of_property_read_u32(np, - "sprd,high-offset", - val); - if (!ret) { - ipc->high_offset = val[0]; - pr_info("sipc: high_offset=0x%xn", ipc->high_offset); - } -#endif - - if (ipc->type == SIPC_BASE_PCIE) { - /* pcie sipc, the host must use loacal SMEM_LOCAL */ - if (!ipc->client && ipc->smem_type != SMEM_LOCAL) { - pr_err("sipc: host must use local smem!"); - return -EINVAL; - } - - if (ipc->client && ipc->smem_type != SMEM_PCIE) { - pr_err("sipc: client must use pcie smem!"); - return -EINVAL; - } - } - - return 0; -} -#else -static u32 sipc_get_smem_base(size_t size) -{ - unsigned long order = get_order(size); - struct page *page, *p, *e; - - page = alloc_pages(GFP_KERNEL, order); - if(page == NULL) { - printk("sipc alloc pages fail\n"); - return 0; - } - split_page(page, order); - for (p = page +(size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++) - __free_page(p); - - if (PageHighMem(page)) { - phys_addr_t base = __pfn_to_phys(page_to_pfn(page)); - //phys_addr_t end = base + size; - while (size > 0) { - void *ptr = kmap_atomic(page); - memset(ptr, 0, PAGE_SIZE); - kunmap_atomic(ptr); - page++; - size -= PAGE_SIZE; - } - - return base; - } else { - void *ptr = page_address(page); - memset(ptr, 0, size); - return __pa(ptr); - } -} - -static int sipc_parse_dt(struct smsg_ipc *ipc, - struct device_node *np, struct device *dev) -{ - u32 val[3]; - int ret = 0; - //dma_addr_t *dma_handle; - - /* get name */ - ipc->name = "sprd,sipc"; - pr_info("sipc: name=%s\n", ipc->name); - - /* get sipc type, optional */ - ipc->type = SIPC_BASE_PCIE; - pr_info("sipc: type=%d\n", ipc->type); - - /* get sipc client, optional */ - - /* get sipc dst */ - ipc->dst = 1; - pr_info("sipc: dst =%d\n", ipc->dst); - - if (ipc->dst >= SIPC_ID_NR) { - pr_err("sipc: dst err\n"); - return ret; - } - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - if (ipc->type == SIPC_BASE_PCIE) { - ipc->ep_dev = 0; - pr_info("sipc: ep_dev=%d\n", ipc->ep_dev); - if (ipc->ep_dev >= PCIE_EP_NR) { - pr_err("sipc: ep_dev err\n"); - return -1; - } - - } -#endif - /* get smem type */ - ipc->smem_type = SMEM_LOCAL; - - pr_info("sipc: smem_type = %d\n", ipc->smem_type); - - /* get smem info */ - val[0] = sipc_get_smem_base(0x0300000); - val[1] = val[0]; - val[2] = 0x0300000; - ipc->smem_base = val[0]; - ipc->dst_smem_base = val[1]; - ipc->smem_size = val[2]; - pr_info("sipc: smem_base=0x%x, dst_smem_base=0x%x, smem_size=0x%x\n", - ipc->smem_base, ipc->dst_smem_base, ipc->smem_size); - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - /* try to get high_offset */ - ipc->high_offset = 0; - pr_info("sipc: high_offset=0x%xn", ipc->high_offset); - -#endif - - if (ipc->type == SIPC_BASE_PCIE) { - /* pcie sipc, the host must use loacal SMEM_LOCAL */ - if (!ipc->client && ipc->smem_type != SMEM_LOCAL) { - pr_err("sipc: host must use local smem!"); - return -EINVAL; - } - - if (ipc->client && ipc->smem_type != SMEM_PCIE) { - pr_err("sipc: client must use pcie smem!"); - return -EINVAL; - } - } - - return 0; -} -#endif - -static int sipc_probe(struct platform_device *pdev) -{ - struct smsg_ipc *ipc; - struct device_node *np; - - if (1) { - np = pdev->dev.of_node; - ipc = devm_kzalloc(&pdev->dev, - sizeof(struct smsg_ipc), - GFP_KERNEL); - if (!ipc) - return -ENOMEM; - - if (sipc_parse_dt(ipc, np, &pdev->dev)) { - pr_err("%s: failed to parse dt!\n", __func__); - return -ENODEV; - } - - /* - * In charge mode, will only boot pm system, - * so just create pm systen sipc. - */ - if (g_boot_mode == CHARGE_MODE && ipc->dst != SIPC_ID_PM_SYS) - return -ENODEV; - - ipc->rxirq_status = sipc_rxirq_status; - ipc->rxirq_clear = sipc_rxirq_clear; - ipc->txirq_trigger = sipc_txirq_trigger; - spin_lock_init(&ipc->txpinlock); - - if (ipc->type == SIPC_BASE_PCIE) { - /* init mpm delay enter idle time for pcie. */ - if (g_boot_mode == CALI_MODE) - ipc->latency = CALI_LATENCY; - else - ipc->latency = NORMAL_LATENCY; - } - - smsg_ipc_create(ipc); - platform_set_drvdata(pdev, ipc); - } - return 0; -} - -static int sipc_remove(struct platform_device *pdev) -{ - struct smsg_ipc *ipc = platform_get_drvdata(pdev); - - smsg_ipc_destroy(ipc); - - devm_kfree(&pdev->dev, ipc); - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id sipc_match_table[] = { - { .compatible = "sprd,sipc", }, - { }, -}; -#endif - -static struct platform_driver sipc_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "sipc", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = sipc_match_table, -#endif - }, - .probe = sipc_probe, - .remove = sipc_remove, -}; - -#ifndef SPRD_PCIE_USE_DTS -static void sipc_platform_device_release(struct device *dev) {} -static struct platform_device sipc_device = { - .name = "sipc", - .id = -1, - .dev = { - .release = sipc_platform_device_release, - } -}; -#endif - -int sipc_init(void) -{ - int ret; - - smsg_init_channel2index(); -#ifndef SPRD_PCIE_USE_DTS - if((ret = platform_device_register(&sipc_device))) - return ret; -#endif - - if((ret = platform_driver_register(&sipc_driver))) { -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&sipc_device); -#endif - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(sipc_init); - -void sipc_exit(void) -{ - platform_driver_unregister(&sipc_driver); - printk("dayin is here0\n"); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&sipc_device); -#endif -} -EXPORT_SYMBOL_GPL(sipc_exit); \ No newline at end of file diff --git a/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c b/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c deleted file mode 100644 index 135f139..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#if defined(CONFIG_DEBUG_FS) -#include "sipc_debugfs.h" - -int sipc_init_debugfs(void) -{ - struct dentry *root = debugfs_create_dir("sipc", NULL); - - if (!root) - return -ENXIO; - - smsg_init_debugfs(root); -#if defined(CONFIG_SPRD_SIPC_SMSGC) - smsgc_init_debugfs(root); -#endif - sbuf_init_debugfs(root); - sblock_init_debugfs(root); -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX - sipx_init_debugfs(root); -#endif -#ifdef CONFIG_SPRD_SIPC_SWCNBLK - swcnblk_init_debugfs(root); -#endif - smem_init_debugfs(root); -#ifdef CONFIG_SPRD_MAILBOX - mbox_init_debugfs(root); -#endif - return 0; -} -EXPORT_SYMBOL_GPL(sipc_init_debugfs); -#endif /* CONFIG_DEBUG_FS */ diff --git a/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h b/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h deleted file mode 100644 index e7849f5..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sipc_debugfs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef __SIPC_DEBUGFS_H -#define __SIPC_DEBUGFS_H - -int sbuf_init_debugfs(void *root); -int smsg_init_debugfs(void *root); -int sblock_init_debugfs(void *root); -int smem_init_debugfs(void *root); - -#ifdef CONFIG_SPRD_SIPC_ZERO_COPY_SIPX -int sipx_init_debugfs(void *root); -#endif - -#ifdef CONFIG_SPRD_SIPC_SWCNBLK -int swcnblk_init_debugfs(void *root); -#endif - -#if defined(CONFIG_SPRD_SIPC_SMSGC) -int smsgc_init_debugfs(void *root); -#endif - -#ifdef CONFIG_SPRD_MAILBOX -int mbox_init_debugfs(void *root); -#endif -#endif /* !__SIPC_DEBUGFS_H */ - diff --git a/quectel_SRPD_PCIE/src/sipc/sipc_priv.h b/quectel_SRPD_PCIE/src/sipc/sipc_priv.h deleted file mode 100644 index 0702faf..0000000 --- a/quectel_SRPD_PCIE/src/sipc/sipc_priv.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SIPC_PRIV_H -#define __SIPC_PRIV_H -#include -#include -#include - -#include "../include/sprd_mpm.h" -#ifdef CONFIG_SPRD_MAILBOX -#include -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE -#include "../include/sprd_pcie_ep_device.h" -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD -#include -#endif - -#ifdef CONFIG_PCI -#include "../include/sprd_pcie_resource.h" -#endif - -#include "../include/sipc_big_to_little.h" - -#ifndef SZ_1K -#define SZ_1K 0x00000400 -#define SZ_4K 0x00001000 -#endif - -enum { - SIPC_BASE_MBOX = 0, - SIPC_BASE_PCIE, - SIPC_BASE_IPI, - SIPC_BASE_NR -}; - -enum smem_type { - SMEM_LOCAL = 0, - SMEM_PCIE -}; - -extern struct smsg_ipc *smsg_ipcs[]; -#define SMSG_CACHE_NR 256 - -struct smsg_channel { - /* wait queue for recv-buffer */ - wait_queue_head_t rxwait; - struct mutex rxlock; - struct sprd_pms *tx_pms; - struct sprd_pms *rx_pms; - char tx_name[16]; - char rx_name[16]; - - /* cached msgs for recv */ - uintptr_t wrptr[1]; - uintptr_t rdptr[1]; - struct smsg caches[SMSG_CACHE_NR]; -}; - -/* smsg ring-buffer between AP/CP ipc */ -struct smsg_ipc { - const char *name; - struct sprd_pms *sipc_pms; - - u8 dst; - u8 client; /* sipc is client mode */ - /* target core_id over mailbox */ - u8 core_id; - u8 core_sensor_id; - u32 type; /* sipc type, mbox, ipi, pcie */ - - void __iomem *write_addr; - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - u32 ep_dev; - struct platform_device *pcie_dev; -#endif -#ifdef CONFIG_PCIE_EPF_SPRD - u32 ep_fun; -#endif - u32 latency; - - /* send-buffer info */ - uintptr_t txbuf_addr; - u32 txbuf_size; /* must be 2^n */ - uintptr_t txbuf_rdptr; - uintptr_t txbuf_wrptr; - - /* recv-buffer info */ - uintptr_t rxbuf_addr; - u32 rxbuf_size; /* must be 2^n */ - uintptr_t rxbuf_rdptr; - uintptr_t rxbuf_wrptr; - - /* sipc irq related */ - int irq; - u32 (*rxirq_status)(u8 id); - void (*rxirq_clear)(u8 id); - void (*txirq_trigger)(u8 id, u64 msg); - - u32 ring_base; - u32 ring_size; - void *smem_vbase; - u32 smem_base; - u32 smem_size; - enum smem_type smem_type; - u32 dst_smem_base; -#ifdef CONFIG_PHYS_ADDR_T_64BIT - u32 high_offset; -#endif - /* lock for send-buffer */ - spinlock_t txpinlock; - /* all fixed channels receivers */ - struct smsg_channel *channels[SMSG_VALID_CH_NR]; - /* record the runtime status of smsg channel */ - atomic_t busy[SMSG_VALID_CH_NR]; - /* all channel states: 0 unused, 1 be opened by other core, 2 opend */ - u8 states[SMSG_VALID_CH_NR]; -}; - -#define CHAN_STATE_UNUSED 0 -#define CHAN_STATE_CLIENT_OPENED 1 -#define CHAN_STATE_HOST_OPENED 2 -#define CHAN_STATE_OPENED 3 -#define CHAN_STATE_FREE 4 - -void smsg_init_channel2index(void); -void smsg_ipc_create(struct smsg_ipc *ipc); -void smsg_ipc_destroy(struct smsg_ipc *ipc); - -/*smem alloc size align*/ -#define SMEM_ALIGN_POOLSZ 0x40000 /*256KB*/ - -#ifdef CONFIG_64BIT -#define SMEM_ALIGN_BYTES 8 -#define SMEM_MIN_ORDER 3 -#else -#define SMEM_ALIGN_BYTES 4 -#define SMEM_MIN_ORDER 2 -#endif - -/* initialize smem pool for AP/CP */ -int smem_init(u32 addr, u32 size, u32 dst, u32 mem_type); -void sbuf_get_status(u8 dst, char *status_info, int size); - -#if defined(CONFIG_DEBUG_FS) -void sipc_debug_putline(struct seq_file *m, char c, int n); -#endif - -#ifdef CONFIG_SPRD_MAILBOX -#define MBOX_INVALID_CORE 0xff -#endif - -/* sipc_smem_request_resource - * local smem no need request resource, just return 0. - */ -static inline int sipc_smem_request_resource(struct sprd_pms *pms, - u8 dst, int timeout) -{ - if (smsg_ipcs[dst]->smem_type == SMEM_LOCAL) - return 0; - - return sprd_pms_request_resource(pms, timeout); -} - -/* sipc_smem_release_resource - * local smem no need release resource, do nothing. - */ -static inline void sipc_smem_release_resource(struct sprd_pms *pms, u8 dst) -{ - if (smsg_ipcs[dst]->smem_type != SMEM_LOCAL) - sprd_pms_release_resource(pms); -} -#endif diff --git a/quectel_SRPD_PCIE/src/sipc/smem.c b/quectel_SRPD_PCIE/src/sipc/smem.c deleted file mode 100644 index 12640c2..0000000 --- a/quectel_SRPD_PCIE/src/sipc/smem.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "sipc_priv.h" -#define CONFIG_SPRD_IPA_PCIE_WORKROUND -/* - * workround: Due to orca ipa hardware limitations - * the sipc share memory must map from - * 0x2x0000000(orca side) to 0xx0000000(roc1 - * side), and the size must be 256M - */ -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND -#define IPA_GET_SRC_BASE(addr) (((addr) & 0xf0000000) + 0x200000000) -#define IPA_GET_DST_BASE(addr) ((addr) & 0xf0000000) -#define IPA_SIZE 0x10000000 -#endif - -struct smem_phead { - struct list_head smem_phead; - spinlock_t lock; - u32 poolnum; -}; - -struct smem_pool { - struct list_head smem_head; - struct list_head smem_plist; - spinlock_t lock; - - void *pcie_base; - u32 addr; - u32 size; - u32 dst; - u32 mem_type; - - atomic_t used; - struct gen_pool *gen; -}; - -struct smem_record { - struct list_head smem_list; - struct task_struct *task; - u32 size; - u32 addr; -}; - -struct smem_map_list { - struct list_head map_head; - spinlock_t lock; - u32 inited; -}; - -struct smem_map { - struct list_head map_list; - struct task_struct *task; - const void *mem; - unsigned int count; -}; - -static struct smem_phead sipc_smem_phead; -static struct smem_map_list mem_mp; - -static struct smem_pool *shmem_find_pool(u8 dst) -{ - struct smem_phead *phead = &sipc_smem_phead; - struct smem_pool *spool = NULL; - struct smem_pool *pos; - unsigned long flags; - - /* The num of one pool is 0, means the poll is not ready */ - if (!phead->poolnum) - return NULL; - - spin_lock_irqsave(&phead->lock, flags); - list_for_each_entry(pos, &phead->smem_phead, smem_plist) { - if (pos->dst == dst) { - spool = pos; - break; - } - } - spin_unlock_irqrestore(&phead->lock, flags); - return spool; -} - -static void *soc_modem_ram_vmap(phys_addr_t start, size_t size, int noncached) -{ - struct page **pages; - phys_addr_t page_start; - unsigned int page_count; - pgprot_t prot; - unsigned int i; - void *vaddr; - phys_addr_t addr; - unsigned long flags; - struct smem_map *map; - struct smem_map_list *smem = &mem_mp; - - map = kzalloc(sizeof(struct smem_map), GFP_KERNEL); - if (!map) - return NULL; - - page_start = start - offset_in_page(start); - page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE); - if (noncached) - prot = pgprot_noncached(PAGE_KERNEL); - else - prot = PAGE_KERNEL; - - pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL); - if (!pages) { - kfree(map); - return NULL; - } - - for (i = 0; i < page_count; i++) { - addr = page_start + i * PAGE_SIZE; - pages[i] = pfn_to_page(addr >> PAGE_SHIFT); - } - -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 5,10,0 )) - vaddr = vm_map_ram(pages, page_count, -1, prot); -#else - vaddr = vmap(pages, page_count, -1, prot); - //vaddr = vm_map_ram(pages, page_count, -1); -#endif - - kfree(pages); - - if (!vaddr) { - pr_err("smem: vm map failed.\n"); - kfree(map); - return NULL; - } - - vaddr += offset_in_page(start); - map->count = page_count; - map->mem = vaddr; - map->task = current; - - if (smem->inited) { - spin_lock_irqsave(&smem->lock, flags); - list_add_tail(&map->map_list, &smem->map_head); - spin_unlock_irqrestore(&smem->lock, flags); - } - return vaddr; -} - -static void *pcie_modem_ram_vmap(phys_addr_t start, size_t size, int noncached) -{ - if (noncached == 0) { - pr_err("%s: cache not support!\n", __func__); - return NULL; - } - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - return sprd_ep_map_memory(PCIE_EP_MODEM, start, size); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - return sprd_pci_epf_map_memory(SPRD_FUNCTION_0, start, size); -#endif - - return NULL; -} - -static void pcie_modem_ram_unmap(const void *mem) -{ -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - return sprd_ep_unmap_memory(PCIE_EP_MODEM, mem); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - return sprd_pci_epf_unmap_memory(SPRD_FUNCTION_0, mem); -#endif -} - -static void soc_modem_ram_unmap(const void *mem) -{ - struct smem_map *map, *next; - unsigned long flags; - struct smem_map_list *smem = &mem_mp; - bool found = false; - - if (smem->inited) { - spin_lock_irqsave(&smem->lock, flags); - list_for_each_entry_safe(map, next, &smem->map_head, map_list) { - if (map->mem == mem) { - list_del(&map->map_list); - found = true; - break; - } - } - spin_unlock_irqrestore(&smem->lock, flags); - - if (found) { - vm_unmap_ram(mem - offset_in_page(mem), map->count); - kfree(map); - } - } -} - -static void *shmem_ram_vmap(u8 dst, phys_addr_t start, - size_t size, - int noncached) -{ - struct smem_pool *spool; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return NULL; - } - - if (spool->mem_type == SMEM_PCIE) { - if (start < spool->addr - || start + size > spool->addr + spool->size) { - pr_info("%s: error, start = 0x%lx, size = 0x%lx.\n", - __func__, - (unsigned long)start, - (unsigned long)size); - return NULL; - } - - pr_info("%s: succ, start = 0x%lx, size = 0x%lx.\n", - __func__, (unsigned long)start, (unsigned long)size); - return (spool->pcie_base + start - spool->addr); - } - - return soc_modem_ram_vmap(start, size, noncached); - -} - -int smem_init(u32 addr, u32 size, u32 dst, u32 mem_type) -{ - struct smem_phead *phead = &sipc_smem_phead; - struct smem_map_list *smem = &mem_mp; - struct smem_pool *spool; - unsigned long flags; - - /* fisrt init, create the pool head */ - if (!phead->poolnum) { - spin_lock_init(&phead->lock); - INIT_LIST_HEAD(&phead->smem_phead); - } - - if (shmem_find_pool(dst)) - return 0; - - spool = kzalloc(sizeof(struct smem_pool), GFP_KERNEL); - if (!spool) - return -1; - - spin_lock_irqsave(&phead->lock, flags); - list_add_tail(&spool->smem_plist, &phead->smem_phead); - phead->poolnum++; - spin_unlock_irqrestore(&phead->lock, flags); - - spool->addr = addr; - spool->dst = dst; - spool->mem_type = mem_type; - - if (size >= SMEM_ALIGN_POOLSZ) - size = PAGE_ALIGN(size); - else - size = ALIGN(size, SMEM_ALIGN_BYTES); - - spool->size = size; - atomic_set(&spool->used, 0); - spin_lock_init(&spool->lock); - INIT_LIST_HEAD(&spool->smem_head); - - spin_lock_init(&smem->lock); - INIT_LIST_HEAD(&smem->map_head); - smem->inited = 1; - - /* allocator block size is times of pages */ - if (spool->size >= SMEM_ALIGN_POOLSZ) - spool->gen = gen_pool_create(PAGE_SHIFT, -1); - else - spool->gen = gen_pool_create(SMEM_MIN_ORDER, -1); - - if (!spool->gen) { - pr_err("Failed to create smem gen pool!\n"); - return -1; - } - - if (gen_pool_add(spool->gen, spool->addr, spool->size, -1) != 0) { - pr_err("Failed to add smem gen pool!\n"); - return -1; - } - pr_info("%s: pool addr = 0x%x, size = 0x%x added.\n", - __func__, spool->addr, spool->size); - - if (mem_type == SMEM_PCIE) { -#ifdef CONFIG_SPRD_IPA_PCIE_WORKROUND -#ifdef CONFIG_PCIE_EPF_SPRD - spool->pcie_base = sprd_epf_ipa_map(IPA_GET_SRC_BASE(addr), - IPA_GET_DST_BASE(addr), - IPA_SIZE); - if (!spool->pcie_base) - return -ENOMEM; - - spool->pcie_base += (addr - IPA_GET_DST_BASE(addr)); -#else - pr_err("Failed to pcie map, can't run here!\n"); - return -ENOMEM; -#endif -#else - spool->pcie_base = pcie_modem_ram_vmap(addr, size, 1); -#endif - } - return 0; -} - -/* ****************************************************************** */ - -int smem_get_area(u8 dst, u32 *base, u32 *size) -{ - struct smem_pool *spool; - - if (!base || !size) - return -EINVAL; - - spool = shmem_find_pool(dst); - if (!spool) { - pr_err("%s: err, dst = %d!\n", __func__, dst); - return -EINVAL; - } - - pr_info("%s: addr = 0x%x, size = 0x%x.\n", - __func__, spool->addr, spool->size); - - *base = spool->addr; - *size = spool->size; - - return 0; -} -EXPORT_SYMBOL_GPL(smem_get_area); - -u32 smem_alloc(u8 dst, u32 size) -{ - struct smem_pool *spool; - struct smem_record *recd; - unsigned long flags; - u32 addr = 0; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return 0; - } - - recd = kzalloc(sizeof(struct smem_record), GFP_KERNEL); - if (!recd) - return 0; - - if (spool->size >= SMEM_ALIGN_POOLSZ) - size = PAGE_ALIGN(size); - else - size = ALIGN(size, SMEM_ALIGN_BYTES); - - addr = gen_pool_alloc(spool->gen, size); - if (!addr) { - pr_err("%s:pool dst=%d, size=0x%x failed to alloc smem!\n", - __func__, dst, size); - kfree(recd); - return 0; - } - - /* record smem alloc info */ - atomic_add(size, &spool->used); - recd->size = size; - recd->task = current; - recd->addr = addr; - spin_lock_irqsave(&spool->lock, flags); - list_add_tail(&recd->smem_list, &spool->smem_head); - spin_unlock_irqrestore(&spool->lock, flags); - - return addr; -} -EXPORT_SYMBOL_GPL(smem_alloc); - -void smem_free(u8 dst, u32 addr, u32 size) -{ - struct smem_pool *spool; - struct smem_record *recd, *next; - unsigned long flags; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return; - } - - if (size >= SMEM_ALIGN_POOLSZ) - size = PAGE_ALIGN(size); - else - size = ALIGN(size, SMEM_ALIGN_BYTES); - - atomic_sub(size, &spool->used); - gen_pool_free(spool->gen, addr, size); - /* delete record node from list */ - spin_lock_irqsave(&spool->lock, flags); - list_for_each_entry_safe(recd, next, &spool->smem_head, smem_list) { - if (recd->addr == addr) { - list_del(&recd->smem_list); - kfree(recd); - break; - } - } - spin_unlock_irqrestore(&spool->lock, flags); -} -EXPORT_SYMBOL_GPL(smem_free); - -void *shmem_ram_vmap_nocache(u8 dst, phys_addr_t start, size_t size) -{ - return shmem_ram_vmap(dst, start, size, 1); -} -EXPORT_SYMBOL_GPL(shmem_ram_vmap_nocache); - - -void *shmem_ram_vmap_cache(u8 dst, phys_addr_t start, size_t size) -{ - return shmem_ram_vmap(dst, start, size, 0); -} -EXPORT_SYMBOL_GPL(shmem_ram_vmap_cache); - -void shmem_ram_unmap(u8 dst, const void *mem) -{ - struct smem_pool *spool; - - spool = shmem_find_pool(dst); - if (spool == NULL) { - pr_err("%s: pool dst %d is not existed!\n", __func__, dst); - return; - } - - if (spool->mem_type == SMEM_PCIE) - /* do nothing, because it also do nothing in shmem_ram_vmap */ - return; - else - return soc_modem_ram_unmap(mem); -} -EXPORT_SYMBOL_GPL(shmem_ram_unmap); - -void *modem_ram_vmap_nocache(u32 modem_type, phys_addr_t start, size_t size) -{ - if (modem_type == PCIE_MODEM) - return pcie_modem_ram_vmap(start, size, 1); - else - return soc_modem_ram_vmap(start, size, 1); -} -EXPORT_SYMBOL_GPL(modem_ram_vmap_nocache); - - -void *modem_ram_vmap_cache(u32 modem_type, phys_addr_t start, size_t size) -{ - if (modem_type == PCIE_MODEM) - return pcie_modem_ram_vmap(start, size, 0); - else - return soc_modem_ram_vmap(start, size, 0); -} -EXPORT_SYMBOL_GPL(modem_ram_vmap_cache); - -void modem_ram_unmap(u32 modem_type, const void *mem) -{ - if (modem_type == PCIE_MODEM) - return pcie_modem_ram_unmap(mem); - else - return soc_modem_ram_unmap(mem); -} -EXPORT_SYMBOL_GPL(modem_ram_unmap); - -#ifdef CONFIG_DEBUG_FS -static int smem_debug_show(struct seq_file *m, void *private) -{ - struct smem_phead *phead = &sipc_smem_phead; - struct smem_pool *spool, *pos; - struct smem_record *recd; - u32 fsize; - unsigned long flags; - u32 cnt = 1; - - spin_lock_irqsave(&phead->lock, flags); - list_for_each_entry(pos, &phead->smem_phead, smem_plist) { - spool = pos; - fsize = gen_pool_avail(spool->gen); - - sipc_debug_putline(m, '*', 80); - seq_printf(m, "%d, dst:%d, name: %s, smem pool info:\n", - cnt++, spool->dst, - (smsg_ipcs[spool->dst])->name); - seq_printf(m, "phys_addr=0x%x, total=0x%x, used=0x%x, free=0x%x\n", - spool->addr, spool->size, spool->used.counter, fsize); - seq_puts(m, "smem record list:\n"); - - list_for_each_entry(recd, &spool->smem_head, smem_list) { - seq_printf(m, "task %s: pid=%u, addr=0x%x, size=0x%x\n", - recd->task->comm, - recd->task->pid, - recd->addr, - recd->size); - } - } - spin_unlock_irqrestore(&phead->lock, flags); - return 0; -} - -static int smem_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, smem_debug_show, inode->i_private); -} - -static const struct file_operations smem_debug_fops = { - .open = smem_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int smem_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("smem", 0444, - (struct dentry *)root, NULL, - &smem_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(smem_init_debugfs); - -#endif /* endof CONFIG_DEBUG_FS */ - - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SMEM driver"); -MODULE_LICENSE("GPL v2"); diff --git a/quectel_SRPD_PCIE/src/sipc/smsg.c b/quectel_SRPD_PCIE/src/sipc/smsg.c deleted file mode 100644 index 051800d..0000000 --- a/quectel_SRPD_PCIE/src/sipc/smsg.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SPRD_MAILBOX -#include -#endif - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "../include/sprd_pcie_resource.h" - -#if defined(CONFIG_DEBUG_FS) -#include "sipc_debugfs.h" -#endif - -#define SMSG_TXBUF_ADDR (0) -#define SMSG_TXBUF_SIZE (SZ_1K) -#define SMSG_RXBUF_ADDR (SMSG_TXBUF_SIZE) -#define SMSG_RXBUF_SIZE (SZ_1K) - -#define SMSG_RINGHDR (SMSG_TXBUF_SIZE + SMSG_RXBUF_SIZE) -#define SMSG_TXBUF_RDPTR (SMSG_RINGHDR + 0) -#define SMSG_TXBUF_WRPTR (SMSG_RINGHDR + 4) -#define SMSG_RXBUF_RDPTR (SMSG_RINGHDR + 8) -#define SMSG_RXBUF_WRPTR (SMSG_RINGHDR + 12) - -#define SMSG_RESERVE_BASE (SMSG_RINGHDR + SZ_1K) -#define SMSG_PCIE_WRPTR (SMSG_RESERVE_BASE + 0) -#define SMSG_PCIE_IRQPTR (SMSG_RESERVE_BASE + 4) - -#define SIPC_READL(addr) readl((__force void __iomem *)(addr)) -#define SIPC_WRITEL(b, addr) writel(b, (__force void __iomem *)(addr)) - -static u8 g_wakeup_flag; - -struct smsg_ipc *smsg_ipcs[SIPC_ID_NR]; -EXPORT_SYMBOL_GPL(smsg_ipcs); - -static ushort debug_enable; - -module_param_named(debug_enable, debug_enable, ushort, 0644); -static u8 channel2index[SMSG_CH_NR + 1]; - -static int smsg_ipc_smem_init(struct smsg_ipc *ipc); - -void smsg_init_channel2index(void) -{ - u16 i, j; - - for (i = 0; i < ARRAY_SIZE(channel2index); i++) { - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - /* find the index of channel i */ - if (sipc_cfg[j].channel == i) - break; - } - - /* if not find, init with INVALID_CHANEL_INDEX, - * else init whith j - */ - if (j == SMSG_VALID_CH_NR) - channel2index[i] = INVALID_CHANEL_INDEX; - else - channel2index[i] = j; - } -} - -static void get_channel_status(u8 dst, char *status, int size) -{ - int i, len; - struct smsg_channel *ch; - - len = strlen(status); - for (i = 0; i < SMSG_VALID_CH_NR && len < size; i++) { - ch = smsg_ipcs[dst]->channels[i]; - if (!ch) - continue; - if (SIPC_READL(ch->rdptr) < SIPC_READL(ch->wrptr)) - snprintf( - status + len, - size - len, - "dst-%d-ch-%d: rd = %u, wr = %u.\n", - dst, - i, - SIPC_READL(ch->rdptr), - SIPC_READL(ch->wrptr) - ); - } -} - -static void smsg_wakeup_print(struct smsg_ipc *ipc, struct smsg *msg) -{ - /* if the first msg come after the irq wake up by sipc, - * use prin_fo to output log - */ - if (g_wakeup_flag) { - g_wakeup_flag = 0; - pr_info("irq read smsg: dst=%d, channel=%d,type=%d, flag=0x%04x, value=0x%08x\n", - ipc->dst, - msg->channel, - msg->type, - msg->flag, - msg->value); - } else { - pr_debug("irq read smsg: dst=%d, channel=%d,type=%d, flag=0x%04x, value=0x%08x\n", - ipc->dst, - msg->channel, - msg->type, - msg->flag, - msg->value); - } -} - -static void smsg_die_process(struct smsg_ipc *ipc, struct smsg *msg) -{ - if (msg->type == SMSG_TYPE_DIE) { - if (debug_enable) { - char sipc_status[100] = {0}; - - get_channel_status(ipc->dst, - sipc_status, - sizeof(sipc_status)); - sbuf_get_status(ipc->dst, - sipc_status, - sizeof(sipc_status)); - panic("cpcrash: %s", sipc_status); - while (1) - ; - } - } -} - -static void smsg_msg_process(struct smsg_ipc *ipc, - struct smsg *msg, bool wake_lock) -{ - struct smsg_channel *ch = NULL; - u32 wr; - u8 ch_index; - - smsg_wakeup_print(ipc, msg); - smsg_die_process(ipc, msg); - - ch_index = channel2index[msg->channel]; - atomic_inc(&ipc->busy[ch_index]); - - pr_debug("smsg:get dst=%d msg channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - ipc->dst, msg->channel, - msg->type, msg->flag, - msg->value); - - if (msg->type >= SMSG_TYPE_NR) { - /* invalid msg */ - pr_err("invalid smsg: channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, msg->flag, msg->value); - goto exit_msg_proc; - } - - ch = ipc->channels[ch_index]; - if (!ch) { - if (ipc->states[ch_index] == CHAN_STATE_UNUSED && - msg->type == SMSG_TYPE_OPEN && - msg->flag == SMSG_OPEN_MAGIC) - ipc->states[ch_index] = CHAN_STATE_CLIENT_OPENED; - else - /* drop this bad msg since channel - * is not opened - */ - pr_info("smsg channel %d not opened! drop smsg: type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, - msg->flag, msg->value); - - goto exit_msg_proc; - } - - if ((int)(SIPC_READL(ch->wrptr) - SIPC_READL(ch->rdptr)) >= - SMSG_CACHE_NR) { - /* msg cache is full, drop this msg */ - pr_info("smsg channel %d recv cache is full! drop smsg: type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, msg->flag, msg->value); - } else { - /* write smsg to cache */ - wr = SIPC_READL(ch->wrptr) & (SMSG_CACHE_NR - 1); - memcpy(&ch->caches[wr], msg, sizeof(struct smsg)); - SIPC_WRITEL(SIPC_READL(ch->wrptr) + 1, ch->wrptr); - } - - wake_up_interruptible_all(&ch->rxwait); - - if (wake_lock) - sprd_pms_request_wakelock_period(ch->rx_pms, 500); - -exit_msg_proc: - atomic_dec(&ipc->busy[ch_index]); -} - -#ifdef CONFIG_SPRD_MAILBOX -static irqreturn_t smsg_mbox_irq_handler(void *ptr, void *private) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)private; - struct smsg *msg; - - msg = ptr; - smsg_msg_process(ipc, msg, true); - - return IRQ_HANDLED; -} - -static irqreturn_t smsg_mbox_sensor_irq_handler(void *ptr, void *private) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)private; - struct smsg *msg; - - msg = ptr; - smsg_msg_process(ipc, msg, false); - - return IRQ_HANDLED; -} - -#endif - -static int sipc_process_all_msg(struct smsg_ipc *ipc) -{ - struct smsg *msg; - struct smsg msg_recv; - uintptr_t rxpos; - - /* msg coming, means resource ok, don't wait */ - sipc_smem_request_resource(ipc->sipc_pms, ipc->dst, 0); - - while (BL_READL(ipc->rxbuf_wrptr) != BL_READL(ipc->rxbuf_rdptr)) { - rxpos = (BL_READL(ipc->rxbuf_rdptr) & (ipc->rxbuf_size - 1)) * - sizeof(struct smsg) + ipc->rxbuf_addr; - msg = (struct smsg *)rxpos; - - /* share memory smsg to ipc msg */ - msg_recv.channel = msg->channel; - msg_recv.type = msg->type; - msg_recv.flag = BL_GETW(msg->flag); - msg_recv.value= BL_GETL(msg->value); - smsg_msg_process(ipc, &msg_recv, true); - /* update smsg rdptr */ - BL_WRITEL(BL_READL(ipc->rxbuf_rdptr) + 1, ipc->rxbuf_rdptr); - } - - sipc_smem_release_resource(ipc->sipc_pms, ipc->dst); - - return 0; -} - - -static irqreturn_t smsg_irq_handler(int irq, void *private) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)private; - - if (ipc->rxirq_status(ipc->dst)) - ipc->rxirq_clear(ipc->dst); - - sipc_process_all_msg(ipc); - - return IRQ_HANDLED; -} - -static void smsg_ipc_init_smsg_irq_callback(struct smsg_ipc *ipc) -{ -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_register_irq_handle(ipc->core_id, - smsg_mbox_irq_handler, ipc); - - if ((ipc->dst == SIPC_ID_PM_SYS) && - (ipc->core_sensor_id != MBOX_INVALID_CORE)) - mbox_register_irq_handle(ipc->core_sensor_id, - smsg_mbox_sensor_irq_handler, - ipc); - return; - } -#endif - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - if (ipc->type == SIPC_BASE_PCIE) { - sprd_ep_dev_register_irq_handler(ipc->ep_dev, - PCIE_MSI_SIPC_IRQ, - smsg_irq_handler, ipc); - sprd_ep_dev_set_irq_addr(ipc->ep_dev, ipc->write_addr + 4); - return; - } -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - if (ipc->type == SIPC_BASE_PCIE) { - sprd_pci_epf_register_irq_handler(ipc->ep_fun, - PCIE_DBELL_SIPC_IRQ, - smsg_irq_handler, - ipc); - sprd_pci_epf_set_write_addr(ipc->ep_fun, ipc->write_addr); - return; - } -#endif - - if (ipc->type == SIPC_BASE_IPI) { - int ret; - - /* explicitly call irq handler in case of missing irq on boot */ - smsg_irq_handler(ipc->irq, ipc); - - /* register IPI irq */ - ret = request_irq(ipc->irq, - smsg_irq_handler, - IRQF_NO_SUSPEND, - ipc->name, - ipc); - if (ret) - pr_info("%s: request irq err = %d!\n", ipc->name, ret); - } -} - -static int smsg_ipc_smem_init(struct smsg_ipc *ipc) -{ - void __iomem *base, *p; - phys_addr_t offset = 0; - int ret; - - pr_debug("%s: %s, smem_type = %d!\n", - __func__, ipc->name, ipc->smem_type); - - ret = smem_init(ipc->smem_base, ipc->smem_size, - ipc->dst, ipc->smem_type); - if (ret) { - pr_err("%s: %s err = %d!\n", __func__, ipc->name, ret); - return ret; - } - - if (ipc->type != SIPC_BASE_MBOX) { - ipc->ring_base = smem_alloc(ipc->dst, SZ_4K); - ipc->ring_size = SZ_4K; - pr_info("%s: ring_base = 0x%x, ring_size = 0x%x\n", - __func__, - ipc->ring_base, - ipc->ring_size); - } - -#ifdef CONFIG_PHYS_ADDR_T_64BIT - offset = ipc->high_offset; - offset = offset << 32; -#endif - - if (ipc->ring_base) { - base = (void __iomem *)shmem_ram_vmap_nocache(ipc->dst, - ipc->ring_base + offset, - ipc->ring_size); - if (!base) { - pr_err("%s: ioremap failed!\n", __func__); - smem_free(ipc->dst, ipc->ring_base, SZ_4K); - ipc->ring_base = 0; - return -ENOMEM; - } - - /* assume client is boot later than host */ - if (!ipc->client) { - /** - * memset(base, 0, ipc->ring_size); - * the instruction dc avz - * will abort for nocache memory - */ - for (p = base; p < base + ipc->ring_size;) { -#ifdef CONFIG_64BIT - *(uint64_t *)p = 0x0; - p += sizeof(uint64_t); -#else - *(u32 *)p = 0x0; - p += sizeof(u32); -#endif - } - } - - if (ipc->client) { - /* clent mode, tx is host rx , rx is host tx*/ - ipc->smem_vbase = (void *)base; - ipc->txbuf_size = SMSG_RXBUF_SIZE / - sizeof(struct smsg); - ipc->txbuf_addr = (uintptr_t)base + - SMSG_RXBUF_ADDR; - ipc->txbuf_rdptr = (uintptr_t)base + - SMSG_RXBUF_RDPTR; - ipc->txbuf_wrptr = (uintptr_t)base + - SMSG_RXBUF_WRPTR; - ipc->rxbuf_size = SMSG_TXBUF_SIZE / - sizeof(struct smsg); - ipc->rxbuf_addr = (uintptr_t)base + - SMSG_TXBUF_ADDR; - ipc->rxbuf_rdptr = (uintptr_t)base + - SMSG_TXBUF_RDPTR; - ipc->rxbuf_wrptr = (uintptr_t)base + - SMSG_TXBUF_WRPTR; - } else { - ipc->smem_vbase = (void *)base; - ipc->txbuf_size = SMSG_TXBUF_SIZE / - sizeof(struct smsg); - ipc->txbuf_addr = (uintptr_t)base + - SMSG_TXBUF_ADDR; - ipc->txbuf_rdptr = (uintptr_t)base + - SMSG_TXBUF_RDPTR; - ipc->txbuf_wrptr = (uintptr_t)base + - SMSG_TXBUF_WRPTR; - ipc->rxbuf_size = SMSG_RXBUF_SIZE / - sizeof(struct smsg); - ipc->rxbuf_addr = (uintptr_t)base + - SMSG_RXBUF_ADDR; - ipc->rxbuf_rdptr = (uintptr_t)base + - SMSG_RXBUF_RDPTR; - ipc->rxbuf_wrptr = (uintptr_t)base + - SMSG_RXBUF_WRPTR; - } - ipc->write_addr = base + SMSG_PCIE_WRPTR; - } - - /* after smem_init complete, regist msg irq */ - smsg_ipc_init_smsg_irq_callback(ipc); - - return 0; -} - -#ifdef CONFIG_PCIE_EPF_SPRD -static void smsg_pcie_first_ready(void *data) -{ - struct smsg_ipc *ipc = (struct smsg_ipc *)data; - - if (ipc->smem_type == SMEM_PCIE) - smsg_ipc_smem_init(ipc); - else - pr_err("%s: pcie first ready, smem_type =%d!\n", - ipc->name, ipc->smem_type); -} -#endif - -static void smsg_ipc_mpm_init(struct smsg_ipc *ipc) -{ - /* create modem power manger instance for this sipc */ - sprd_mpm_create(ipc->dst, ipc->name, ipc->latency); - - /* init a power manager source */ - ipc->sipc_pms = sprd_pms_create(ipc->dst, ipc->name, true); - if (!ipc->sipc_pms) - pr_warn("create pms %s failed!\n", ipc->name); - - if (ipc->type == SIPC_BASE_PCIE) { - /* int mpm resource ops */ - sprd_mpm_init_resource_ops(ipc->dst, - sprd_pcie_wait_resource, - sprd_pcie_request_resource, - sprd_pcie_release_resource); - -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - /* in pcie host side, init pcie host resource */ - sprd_pcie_resource_host_init(ipc->dst, - ipc->ep_dev, ipc->pcie_dev); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - /* in pcie ep side, init pcie client resource */ - sprd_pcie_resource_client_init(ipc->dst, ipc->ep_fun); -#endif - } -} - -void smsg_ipc_create(struct smsg_ipc *ipc) -{ - pr_info("%s: %s\n", __func__, ipc->name); - - smsg_ipcs[ipc->dst] = ipc; - - smsg_ipc_mpm_init(ipc); - - - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_PCIE_EPF_SPRD - /* set epf door bell irq number */ - sprd_pci_epf_set_irq_number(ipc->ep_fun, ipc->irq); - - /* register first pcie ready notify */ - sprd_register_pcie_resource_first_ready(ipc->dst, - smsg_pcie_first_ready, - ipc); -#endif - } - - /* if SMEM_PCIE, must init after pcie ready */ - if (ipc->smem_type != SMEM_PCIE) - smsg_ipc_smem_init(ipc); -} - -void smsg_ipc_destroy(struct smsg_ipc *ipc) -{ - shmem_ram_unmap(ipc->dst, ipc->smem_vbase); - smem_free(ipc->dst, ipc->ring_base, SZ_4K); - -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_unregister_irq_handle(ipc->core_id); - - if ((ipc->dst == SIPC_ID_PM_SYS) && - (ipc->core_sensor_id != MBOX_INVALID_CORE)) - mbox_unregister_irq_handle(ipc->core_sensor_id); - } -#endif - - if (ipc->type == SIPC_BASE_PCIE) { -#ifdef CONFIG_SPRD_PCIE_EP_DEVICE - sprd_ep_dev_unregister_irq_handler(ipc->ep_dev, ipc->irq); -#endif - -#ifdef CONFIG_PCIE_EPF_SPRD - sprd_pci_epf_unregister_irq_handler(ipc->ep_fun, ipc->irq); -#endif - sprd_pcie_resource_trash(ipc->dst); - } else { - free_irq(ipc->irq, ipc); - } - - smsg_ipcs[ipc->dst] = NULL; -} - -int sipc_get_wakeup_flag(void) -{ - return (int)g_wakeup_flag; -} -EXPORT_SYMBOL_GPL(sipc_get_wakeup_flag); - -void sipc_set_wakeup_flag(void) -{ - g_wakeup_flag = 1; -} -EXPORT_SYMBOL_GPL(sipc_set_wakeup_flag); - -void sipc_clear_wakeup_flag(void) -{ - g_wakeup_flag = 0; -} -EXPORT_SYMBOL_GPL(sipc_clear_wakeup_flag); - -int smsg_ch_wake_unlock(u8 dst, u8 channel) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - u8 ch_index; - - ch_index = channel2index[channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - ch = ipc->channels[ch_index]; - if (!ch) - return -ENODEV; - - sprd_pms_release_wakelock(ch->rx_pms); - return 0; -} -EXPORT_SYMBOL_GPL(smsg_ch_wake_unlock); - -int smsg_ch_open(u8 dst, u8 channel, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - struct smsg mopen; - struct smsg mrecv; - int rval = 0; - u8 ch_index; - - ch_index = channel2index[channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - ch = kzalloc(sizeof(*ch), GFP_KERNEL); - if (!ch) - return -ENOMEM; - - sprintf(ch->tx_name, "smsg-%d-%d-tx", dst, channel); - ch->tx_pms = sprd_pms_create(dst, ch->tx_name, true); - if (!ch->tx_pms) - pr_warn("create pms %s failed!\n", ch->tx_name); - - sprintf(ch->rx_name, "smsg-%d-%d-rx", dst, channel); - ch->rx_pms = sprd_pms_create(dst, ch->rx_name, true); - if (!ch->rx_pms) - pr_warn("create pms %s failed!\n", ch->rx_name); - - atomic_set(&ipc->busy[ch_index], 1); - init_waitqueue_head(&ch->rxwait); - mutex_init(&ch->rxlock); - ipc->channels[ch_index] = ch; - - pr_info("%s: channel %d-%d send open msg!\n", - __func__, dst, channel); - - smsg_set(&mopen, channel, SMSG_TYPE_OPEN, SMSG_OPEN_MAGIC, 0); - rval = smsg_send(dst, &mopen, timeout); - if (rval != 0) { - pr_err("%s: channel %d-%d send open msg error = %d!\n", - __func__, dst, channel, rval); - ipc->states[ch_index] = CHAN_STATE_UNUSED; - ipc->channels[ch_index] = NULL; - atomic_dec(&ipc->busy[ch_index]); - /* guarantee that channel resource isn't used in irq handler */ - while (atomic_read(&ipc->busy[ch_index])) - ; - - kfree(ch); - - return rval; - } - - /* open msg might be got before */ - if (ipc->states[ch_index] == CHAN_STATE_CLIENT_OPENED) - goto open_done; - - ipc->states[ch_index] = CHAN_STATE_HOST_OPENED; - - do { - smsg_set(&mrecv, channel, 0, 0, 0); - rval = smsg_recv(dst, &mrecv, timeout); - if (rval != 0) { - pr_err("%s: channel %d-%d smsg receive error = %d!\n", - __func__, dst, channel, rval); - ipc->states[ch_index] = CHAN_STATE_UNUSED; - ipc->channels[ch_index] = NULL; - atomic_dec(&ipc->busy[ch_index]); - /* guarantee that channel resource isn't used - * in irq handler - */ - while (atomic_read(&ipc->busy[ch_index])) - ; - - kfree(ch); - return rval; - } - } while (mrecv.type != SMSG_TYPE_OPEN || mrecv.flag != SMSG_OPEN_MAGIC); - - pr_info("%s: channel %d-%d receive open msg!\n", - __func__, dst, channel); - -open_done: - pr_info("%s: channel %d-%d success\n", __func__, dst, channel); - ipc->states[ch_index] = CHAN_STATE_OPENED; - atomic_dec(&ipc->busy[ch_index]); - - return 0; -} -EXPORT_SYMBOL_GPL(smsg_ch_open); - -int smsg_ch_close(u8 dst, u8 channel, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - struct smsg mclose; - u8 ch_index; - - ch_index = channel2index[channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, channel); - return -EINVAL; - } - - ch = ipc->channels[ch_index]; - if (!ch) - return 0; - - smsg_set(&mclose, channel, SMSG_TYPE_CLOSE, SMSG_CLOSE_MAGIC, 0); - smsg_send(dst, &mclose, timeout); - - ipc->states[ch_index] = CHAN_STATE_FREE; - wake_up_interruptible_all(&ch->rxwait); - - /* wait for the channel being unused */ - while (atomic_read(&ipc->busy[ch_index])) - ; - - /* maybe channel has been free for smsg_ch_open failed */ - if (ipc->channels[ch_index]) { - ipc->channels[ch_index] = NULL; - /* guarantee that channel resource isn't used in irq handler */ - while (atomic_read(&ipc->busy[ch_index])) - ; - sprd_pms_destroy(ch->rx_pms); - sprd_pms_destroy(ch->tx_pms); - kfree(ch); - } - - /* finally, update the channel state*/ - ipc->states[ch_index] = CHAN_STATE_UNUSED; - - return 0; -} -EXPORT_SYMBOL_GPL(smsg_ch_close); - -static void smsg_bl_cpoy_msg(struct smsg *dst, struct smsg *src) -{ - dst->channel = src->channel; - dst->type = src->type; - BL_SETW(dst->flag, src->flag); - BL_SETL(dst->value, src->value); -} - -int smsg_senddie(u8 dst) -{ - struct smsg msg; - struct smsg_ipc *ipc = smsg_ipcs[dst]; - uintptr_t txpos; - int rval = 0; - - if (!ipc) - return -ENODEV; - - msg.channel = SMSG_CH_CTRL; - msg.type = SMSG_TYPE_DIE; - msg.flag = 0; - msg.value = 0; - -#ifdef CONFIG_SPRD_MAILBOX - if (ipc->type == SIPC_BASE_MBOX) { - mbox_just_sent(ipc->core_id, *((u64 *)&msg)); - return 0; - } -#endif - - if (ipc->ring_base) { - /* must wait resource before read or write share memory */ - rval = sprd_pms_request_resource(ipc->sipc_pms, 0); - if (rval < 0) - return rval; - - if (((int)(BL_READL(ipc->txbuf_wrptr) - - BL_READL(ipc->txbuf_rdptr)) >= - ipc->txbuf_size)) { - pr_info("%s: smsg txbuf is full!\n", __func__); - rval = -EBUSY; - } else { - /* calc txpos and write smsg */ - txpos = (BL_READL(ipc->txbuf_wrptr) & - (ipc->txbuf_size - 1)) * - sizeof(struct smsg) + ipc->txbuf_addr; - smsg_bl_cpoy_msg((void *)txpos, &msg); - - /* update wrptr */ - BL_WRITEL(BL_READL(ipc->txbuf_wrptr) + 1, - ipc->txbuf_wrptr); - } - ipc->txirq_trigger(ipc->dst, *((u64 *)&msg)); - sprd_pms_release_resource(ipc->sipc_pms); - } - - return rval; -} -EXPORT_SYMBOL_GPL(smsg_senddie); - -int smsg_send(u8 dst, struct smsg *msg, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - uintptr_t txpos; - int rval = 0; - unsigned long flags; - u8 ch_index; - - ch_index = channel2index[msg->channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, msg->channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - if (!ipc->channels[ch_index]) { - pr_err("%s: channel %d not inited!\n", __func__, msg->channel); - return -ENODEV; - } - - if (ipc->states[ch_index] != CHAN_STATE_OPENED && - msg->type != SMSG_TYPE_OPEN && - msg->type != SMSG_TYPE_CLOSE) { - pr_err("%s: channel %d not opened!\n", __func__, msg->channel); - return -EINVAL; - } - - ch = ipc->channels[ch_index]; - - pr_debug("send smsg: channel=%d, type=%d, flag=0x%04x, value=0x%08x\n", - msg->channel, msg->type, msg->flag, msg->value); - - /* - * Must wait resource before read or write share memory, - * and must wait resource before trigger irq, - * And it must before if (ipc->ring_base), - * because it be inited as the same time as resource ready. - */ - rval = sprd_pms_request_resource(ch->tx_pms, timeout); - if (rval < 0) - return rval; - - if (ipc->ring_base) { - spin_lock_irqsave(&ipc->txpinlock, flags); - if (((int)(BL_READL(ipc->txbuf_wrptr) - - BL_READL(ipc->txbuf_rdptr)) >= - ipc->txbuf_size)) { - pr_err("write smsg: txbuf full, wrptr=0x%x, rdptr=0x%x\n", - BL_READL(ipc->txbuf_wrptr), - BL_READL(ipc->txbuf_rdptr)); - rval = -EBUSY; - } else { - /* calc txpos and write smsg */ - txpos = (BL_READL(ipc->txbuf_wrptr) & - (ipc->txbuf_size - 1)) * - sizeof(struct smsg) + ipc->txbuf_addr; - smsg_bl_cpoy_msg((void *)txpos, msg); - - /* update wrptr */ - BL_WRITEL(BL_READL(ipc->txbuf_wrptr) + 1, - ipc->txbuf_wrptr); - } - spin_unlock_irqrestore(&ipc->txpinlock, flags); - } else if (ipc->type != SIPC_BASE_MBOX) { - pr_err("send smsg:ring_base is NULL"); - sprd_pms_release_resource(ch->tx_pms); - return -EINVAL; - } - - ipc->txirq_trigger(ipc->dst, *(u64 *)msg); - sprd_pms_release_resource(ch->tx_pms); - - return rval; -} -EXPORT_SYMBOL_GPL(smsg_send); - -int smsg_recv(u8 dst, struct smsg *msg, int timeout) -{ - struct smsg_ipc *ipc = smsg_ipcs[dst]; - struct smsg_channel *ch; - u32 rd; - int rval = 0; - u8 ch_index; - - ch_index = channel2index[msg->channel]; - if (ch_index == INVALID_CHANEL_INDEX) { - pr_err("%s:channel %d invalid!\n", __func__, msg->channel); - return -EINVAL; - } - - if (!ipc) - return -ENODEV; - - atomic_inc(&ipc->busy[ch_index]); - - ch = ipc->channels[ch_index]; - - if (!ch) { - pr_err("%s: channel %d not opened!\n", __func__, msg->channel); - atomic_dec(&ipc->busy[ch_index]); - return -ENODEV; - } - - pr_debug("%s: dst=%d, channel=%d, timeout=%d, ch_index = %d\n", - __func__, dst, msg->channel, timeout, ch_index); - - if (timeout == 0) { - if (!mutex_trylock(&ch->rxlock)) { - pr_err("dst=%d, channel=%d recv smsg busy!\n", - dst, msg->channel); - atomic_dec(&ipc->busy[ch_index]); - - return -EBUSY; - } - - /* no wait */ - if (SIPC_READL(ch->wrptr) == SIPC_READL(ch->rdptr)) { - pr_info("dst=%d, channel=%d smsg rx cache is empty!\n", - dst, msg->channel); - - rval = -ENODATA; - - goto recv_failed; - } - } else if (timeout < 0) { - mutex_lock_interruptible(&ch->rxlock); - /* wait forever */ - rval = wait_event_interruptible( - ch->rxwait, - (SIPC_READL(ch->wrptr) != - SIPC_READL(ch->rdptr)) || - (ipc->states[ch_index] == CHAN_STATE_FREE)); - if (rval < 0) { - pr_debug("%s: dst=%d, channel=%d wait interrupted!\n", - __func__, dst, msg->channel); - - goto recv_failed; - } - - if (ipc->states[ch_index] == CHAN_STATE_FREE) { - pr_info("%s: dst=%d, channel=%d channel is free!\n", - __func__, dst, msg->channel); - - rval = -EIO; - - goto recv_failed; - } - } else { - mutex_lock_interruptible(&ch->rxlock); - /* wait timeout */ - rval = wait_event_interruptible_timeout( - ch->rxwait, - (SIPC_READL(ch->wrptr) != SIPC_READL(ch->rdptr)) || - (ipc->states[ch_index] == CHAN_STATE_FREE), - timeout); - if (rval < 0) { - pr_debug("%s: dst=%d, channel=%d wait interrupted!\n", - __func__, dst, msg->channel); - - goto recv_failed; - } else if (rval == 0) { - pr_debug("%s: dst=%d, channel=%d wait timeout!\n", - __func__, dst, msg->channel); - - rval = -ETIME; - - goto recv_failed; - } - - if (ipc->states[ch_index] == CHAN_STATE_FREE) { - pr_info("%s: dst=%d, channel=%d channel is free!\n", - __func__, dst, msg->channel); - - rval = -EIO; - - goto recv_failed; - } - } - - /* read smsg from cache */ - rd = SIPC_READL(ch->rdptr) & (SMSG_CACHE_NR - 1); - memcpy(msg, &ch->caches[rd], sizeof(struct smsg)); - SIPC_WRITEL(SIPC_READL(ch->rdptr) + 1, ch->rdptr); - - if (ipc->ring_base) - pr_debug("read smsg: dst=%d, channel=%d, wrptr=%d, rdptr=%d, rd=%d\n", - dst, - msg->channel, - SIPC_READL(ch->wrptr), - SIPC_READL(ch->rdptr), - rd); - - pr_debug("recv smsg: dst=%d, channel=%d, type=%d, flag=0x%04x, value=0x%08x, rval = %d\n", - dst, msg->channel, msg->type, msg->flag, msg->value, rval); - -recv_failed: - mutex_unlock(&ch->rxlock); - atomic_dec(&ipc->busy[ch_index]); - return rval; -} -EXPORT_SYMBOL_GPL(smsg_recv); - -u8 sipc_channel2index(u8 channel) -{ - return channel2index[channel]; -} -EXPORT_SYMBOL_GPL(sipc_channel2index); - -#if defined(CONFIG_DEBUG_FS) -static int smsg_debug_show(struct seq_file *m, void *private) -{ - struct smsg_ipc *ipc = NULL; - struct smsg_channel *ch; - - int i, j, cnt; - - for (i = 0; i < SIPC_ID_NR; i++) { - ipc = smsg_ipcs[i]; - if (!ipc) - continue; - - sipc_debug_putline(m, '*', 120); - seq_printf(m, "sipc: %s:\n", ipc->name); - seq_printf(m, "dst: 0x%0x, irq: 0x%0x\n", - ipc->dst, ipc->irq); - if (ipc->ring_base) { - /* - * must wait resource before - * read or write share memory. - */ - if (sipc_smem_request_resource(ipc->sipc_pms, - ipc->dst, 1000) < 0) - continue; - - seq_printf(m, "txbufAddr: 0x%p, txbufsize: 0x%x, txbufrdptr: [0x%p]=%d, txbufwrptr: [0x%p]=%d\n", - (void *)ipc->txbuf_addr, - ipc->txbuf_size, - (void *)ipc->txbuf_rdptr, - BL_READL(ipc->txbuf_rdptr), - (void *)ipc->txbuf_wrptr, - BL_READL(ipc->txbuf_wrptr)); - seq_printf(m, "rxbufAddr: 0x%p, rxbufsize: 0x%x, rxbufrdptr: [0x%p]=%d, rxbufwrptr: [0x%p]=%d\n", - (void *)ipc->rxbuf_addr, - ipc->rxbuf_size, - (void *)ipc->rxbuf_rdptr, - BL_READL(ipc->rxbuf_rdptr), - (void *)ipc->rxbuf_wrptr, - BL_READL(ipc->rxbuf_wrptr)); - - /* release resource */ - sipc_smem_release_resource(ipc->sipc_pms, ipc->dst); - } - sipc_debug_putline(m, '-', 80); - seq_puts(m, "1. all channel state list:\n"); - - for (j = 0; j < SMSG_VALID_CH_NR; j++) - seq_printf(m, - "%2d. channel[%3d] states: %d, name: %s\n", - j, - sipc_cfg[j].channel, - ipc->states[j], - sipc_cfg[j].name); - - sipc_debug_putline(m, '-', 80); - seq_puts(m, "2. channel rdpt < wrpt list:\n"); - - cnt = 1; - for (j = 0; j < SMSG_VALID_CH_NR; j++) { - ch = ipc->channels[j]; - if (!ch) - continue; - - if (SIPC_READL(ch->rdptr) < SIPC_READL(ch->wrptr)) - seq_printf(m, "%2d. channel[%3d] rd: %d, wt: %d, name: %s\n", - cnt++, - sipc_cfg[j].channel, - SIPC_READL(ch->rdptr), - SIPC_READL(ch->wrptr), - sipc_cfg[j].name); - } - } - return 0; -} - -static int smsg_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, smsg_debug_show, inode->i_private); -} - -static const struct file_operations smsg_debug_fops = { - .open = smsg_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -int smsg_init_debugfs(void *root) -{ - if (!root) - return -ENXIO; - debugfs_create_file("smsg", 0444, - (struct dentry *)root, - NULL, - &smsg_debug_fops); - return 0; -} -EXPORT_SYMBOL_GPL(smsg_init_debugfs); - -#endif /* CONFIG_DEBUG_FS */ - - -MODULE_AUTHOR("Chen Gaopeng"); -MODULE_DESCRIPTION("SIPC/SMSG driver"); -MODULE_LICENSE("GPL v2"); diff --git a/quectel_SRPD_PCIE/src/sipc/spipe.c b/quectel_SRPD_PCIE/src/sipc/spipe.c deleted file mode 100644 index 7fbd7bc..0000000 --- a/quectel_SRPD_PCIE/src/sipc/spipe.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * Copyright (C) 2018 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "sipc_priv.h" -#include "spipe.h" - -#define SPIPE_NR_BASE_NUM MKDEV(254, 0) -#define SDIAG_NR_BASE_NUM MKDEV(253, 0) -#define STTY_NR_BASE_NUM MKDEV(252, 0) -#define SNV_NR_BASE_NUM MKDEV(251, 0) - -struct spipe_device { - struct spipe_init_data *init; - int major; - int minor; - struct cdev cdev; -}; - -struct spipe_sbuf { - u8 dst; - u8 channel; - u32 bufid; -}; - -static struct class *spipe_class; - -static int spipe_open(struct inode *inode, struct file *filp) -{ - int minor = iminor(filp->f_path.dentry->d_inode); - struct spipe_device *spipe; - struct spipe_sbuf *sbuf; - - spipe = container_of(inode->i_cdev, struct spipe_device, cdev); - if (sbuf_status(spipe->init->dst, spipe->init->channel) != 0) { - printk("spipe %d-%d not ready to open!\n", - spipe->init->dst, spipe->init->channel); - filp->private_data = NULL; - return -ENODEV; - } - - sbuf = kmalloc(sizeof(struct spipe_sbuf), GFP_KERNEL); - if (!sbuf) - return -ENOMEM; - filp->private_data = sbuf; - - sbuf->dst = spipe->init->dst; - sbuf->channel = spipe->init->channel; - sbuf->bufid = minor - spipe->minor; - - return 0; -} - -static int spipe_release(struct inode *inode, struct file *filp) -{ - struct spipe_sbuf *sbuf = filp->private_data; - - kfree(sbuf); - - return 0; -} - -static ssize_t spipe_read(struct file *filp, - char __user *buf, size_t count, loff_t *ppos) -{ - struct spipe_sbuf *sbuf = filp->private_data; - int timeout = -1; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - return sbuf_read(sbuf->dst, sbuf->channel, sbuf->bufid, - (void *)buf, count, timeout); -} - -static ssize_t spipe_write(struct file *filp, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct spipe_sbuf *sbuf = filp->private_data; - int timeout = -1; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - return sbuf_write(sbuf->dst, sbuf->channel, sbuf->bufid, - (void *)buf, count, timeout); -} - -static unsigned int spipe_poll(struct file *filp, poll_table *wait) -{ - struct spipe_sbuf *sbuf = filp->private_data; - - return sbuf_poll_wait(sbuf->dst, sbuf->channel, sbuf->bufid, - filp, wait); -} - -static long spipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static const struct file_operations spipe_fops = { - .open = spipe_open, - .release = spipe_release, - .read = spipe_read, - .write = spipe_write, - .poll = spipe_poll, - .unlocked_ioctl = spipe_ioctl, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -#ifdef SPRD_PCIE_USE_DTS -static int spipe_parse_dt(struct spipe_init_data **init, - struct device_node *np, struct device *dev, dev_t *devid) -{ - struct spipe_init_data *pdata = NULL; - int ret; - u32 data; - - pdata = devm_kzalloc(dev, sizeof(struct spipe_init_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - ret = of_property_read_string(np, - "sprd,name", - (const char **)&pdata->name); - if (ret) - goto error; - - if (!strcmp(pdata->name, "spipe_nr")) - *devid = SPIPE_NR_BASE_NUM; - else if (!strcmp(pdata->name, "sdiag_nr")) - *devid = SDIAG_NR_BASE_NUM; - else if (!strcmp(pdata->name, "stty_nr")) - *devid = STTY_NR_BASE_NUM; - else if (!strcmp(pdata->name, "snv_nr")) - *devid = SNV_NR_BASE_NUM; - - ret = of_property_read_u32(np, "sprd,dst", (u32 *)&data); - if (ret) - goto error; - pdata->dst = (u8)data; - - ret = of_property_read_u32(np, "sprd,channel", (u32 *)&data); - if (ret) - goto error; - pdata->channel = (u8)data; - - ret = of_property_read_u32(np, - "sprd,ringnr", - (u32 *)&pdata->ringnr); - if (ret) - goto error; - - ret = of_property_read_u32(np, - "sprd,size-rxbuf", - (u32 *)&pdata->rxbuf_size); - if (ret) - goto error; - - ret = of_property_read_u32(np, - "sprd,size-txbuf", - (u32 *)&pdata->txbuf_size); - if (ret) - goto error; - - *init = pdata; - return ret; -error: - devm_kfree(dev, pdata); - *init = NULL; - return ret; -} -#else -static int spipe_parse_dt(struct spipe_init_data **init, - struct device_node *np, struct device *dev, dev_t *devid) -{ - struct spipe_init_data *pdata = *init; - - if (!strcmp(pdata->name, "spipe_nr")) - *devid = SPIPE_NR_BASE_NUM; - else if (!strcmp(pdata->name, "sdiag_nr")) - *devid = SDIAG_NR_BASE_NUM; - else if (!strcmp(pdata->name, "stty_nr")) - *devid = STTY_NR_BASE_NUM; - else if (!strcmp(pdata->name, "snv_nr")) - *devid = SNV_NR_BASE_NUM; - - return 0; -} -#endif - -static inline void spipe_destroy_pdata(struct spipe_init_data **init, - struct device *dev) -{ - *init = NULL; -} - -static int spipe_probe(struct platform_device *pdev) -{ - struct spipe_init_data *init = pdev->dev.platform_data; - struct spipe_device *spipe; - dev_t devid; - int i, rval; - struct device_node *np; - - printk("%s!\n", __func__); - - if (1) { - np = pdev->dev.of_node; - rval = spipe_parse_dt(&init, np, &pdev->dev, &devid); - if (rval) { - pr_err("Failed to parse spipe device tree, ret=%d\n", rval); - return rval; - } - - printk("spipe: after parse device tree, name=%s, dst=%u, channel=%u, ringnr=%u, rxbuf_size=0x%x, txbuf_size=0x%x\n", - init->name, - init->dst, - init->channel, - init->ringnr, - init->rxbuf_size, - init->txbuf_size); - - rval = sbuf_create(init->dst, init->channel, init->ringnr, - init->txbuf_size, init->rxbuf_size); - if (rval != 0) { - printk("Failed to create sbuf: %d\n", rval); - spipe_destroy_pdata(&init, &pdev->dev); - return rval; - } - - spipe = devm_kzalloc(&pdev->dev, - sizeof(struct spipe_device), - GFP_KERNEL); - if (spipe == NULL) { - sbuf_destroy(init->dst, init->channel); - spipe_destroy_pdata(&init, &pdev->dev); - printk("Failed to allocate spipe_device\n"); - return -ENOMEM; - } - - rval = alloc_chrdev_region(&devid, 0, init->ringnr, init->name); - //rval = register_chrdev_region(devid, init->ringnr, init->name); - if (rval != 0) { - sbuf_destroy(init->dst, init->channel); - devm_kfree(&pdev->dev, spipe); - spipe_destroy_pdata(&init, &pdev->dev); - printk("Failed to alloc spipe chrdev\n"); - return rval; - } - - cdev_init(&(spipe->cdev), &spipe_fops); - rval = cdev_add(&(spipe->cdev), devid, init->ringnr); - if (rval != 0) { - sbuf_destroy(init->dst, init->channel); - devm_kfree(&pdev->dev, spipe); - unregister_chrdev_region(devid, init->ringnr); - spipe_destroy_pdata(&init, &pdev->dev); - printk("Failed to add spipe cdev\n"); - return rval; - } - - spipe->major = MAJOR(devid); - spipe->minor = MINOR(devid); - if (init->ringnr > 1) { - for (i = 0; i < init->ringnr; i++) { - device_create(spipe_class, NULL, - MKDEV(spipe->major, spipe->minor + i), - NULL, "%s%d", init->name, i); - } - } else { - device_create(spipe_class, NULL, - MKDEV(spipe->major, spipe->minor), - NULL, "%s", init->name); - } - - spipe->init = init; - - platform_set_drvdata(pdev, spipe); - } - - return 0; -} - -static int spipe_remove(struct platform_device *pdev) -{ - struct spipe_device *spipe = platform_get_drvdata(pdev); - int i; - - if (spipe) { - for (i = 0; i < spipe->init->ringnr; i++) { - device_destroy(spipe_class, MKDEV(spipe->major, spipe->minor + i)); - } - cdev_del(&(spipe->cdev)); - unregister_chrdev_region(MKDEV(spipe->major, spipe->minor), spipe->init->ringnr); - - sbuf_destroy(spipe->init->dst, spipe->init->channel); - - spipe_destroy_pdata(&spipe->init, &pdev->dev); - - devm_kfree(&pdev->dev, spipe); - - platform_set_drvdata(pdev, NULL); - } - - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id spipe_match_table[] = { - {.compatible = "sprd,spipe", }, - { }, -}; -#endif - -static struct platform_driver spipe_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "spipe", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = spipe_match_table, -#endif - }, - .probe = spipe_probe, - .remove = spipe_remove, -}; - -static struct platform_device *spipe_pdev[MAX_SPIPE_CHN_NUM]; -static struct spipe_init_data spipe_data[MAX_SPIPE_CHN_NUM] = { - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "spipe_nr", - .dst = 1, - .channel = 4, - .ringnr = 15, - .txbuf_size = 0x1000, - .rxbuf_size = 0x1000 - }, - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "sdiag_nr", - .dst = 1, - .channel = 21, - .ringnr = 1, - .txbuf_size = 0x40000, - .rxbuf_size = 0x8000 - }, - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "stty_nr", - .dst = 1, - .channel = 6, - .ringnr = 32, - .txbuf_size = 0x0800, - .rxbuf_size = 0x0800 - }, - { - .sipc_name = SPIPE_DRVIER_NMAE, - .name = "snv_nr", - .dst = 1, - .channel = 40, - .ringnr = 1, - .txbuf_size = 0x40400, - .rxbuf_size = 0x1000 - } - -}; - -static int spipe_platform_device_reigster(void) -{ - int retval = -ENOMEM; - int i; - - for(i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - spipe_pdev[i] = platform_device_alloc(SPIPE_DRVIER_NMAE, i); - if (!spipe_pdev[i]) { - i--; - while (i >= 0) - platform_device_put(spipe_pdev[i--]); - return retval; - } - } - - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - retval = platform_device_add_data(spipe_pdev[i], &spipe_data[i], - sizeof(struct spipe_init_data)); - if (retval) - goto err_add_pdata; - } - - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - retval = platform_device_add(spipe_pdev[i]); - if (retval < 0) { - i--; - while (i >= 0) - platform_device_del(spipe_pdev[i]); - goto err_add_pdata; - } - } - - return retval; - -err_add_pdata: - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) - platform_device_put(spipe_pdev[i]); - return retval; -} - -static void spipe_platform_device_unreigster(void) -{ - int i; - for (i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - platform_device_unregister(spipe_pdev[i]); - } -} - - -int spipe_init(void) -{ - int ret; - - spipe_class = class_create(THIS_MODULE, "spipe"); - if (IS_ERR(spipe_class)) - return PTR_ERR(spipe_class); -#ifndef SPRD_PCIE_USE_DTS - if((ret = spipe_platform_device_reigster())) - return ret; -#endif - - if((ret = platform_driver_register(&spipe_driver))) { -#ifndef SPRD_PCIE_USE_DTS - spipe_platform_device_unreigster(); -#endif - return ret; - } - return ret; -} -EXPORT_SYMBOL_GPL(spipe_init); - -void spipe_exit(void) -{ - platform_driver_unregister(&spipe_driver); -#ifndef SPRD_PCIE_USE_DTS - spipe_platform_device_unreigster(); -#endif - class_destroy(spipe_class); -} - -void spipe_device_down(void) -{ - int retval = -ENOMEM; - int i; - - for(i = 0; i < MAX_SPIPE_CHN_NUM; i++) { - sbuf_down(spipe_data[i].dst, spipe_data[i].channel); - } -} - -EXPORT_SYMBOL_GPL(spipe_exit); -EXPORT_SYMBOL_GPL(spipe_device_down); diff --git a/quectel_SRPD_PCIE/src/sipc/spipe.h b/quectel_SRPD_PCIE/src/sipc/spipe.h deleted file mode 100644 index eacca6c..0000000 --- a/quectel_SRPD_PCIE/src/sipc/spipe.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SPIPE_H -#define __SPIPE_H - -#define MAX_SPIPE_CHN_NUM 4 -#define SPIPE_DRVIER_NMAE "spipe" - -struct spipe_init_data { - char *name; - char *sipc_name; - u8 dst; - u8 channel; - u32 ringnr; - u32 txbuf_size; - u32 rxbuf_size; -}; -#endif diff --git a/quectel_SRPD_PCIE/src/sipc/spool.c b/quectel_SRPD_PCIE/src/sipc/spool.c deleted file mode 100644 index 724dc96..0000000 --- a/quectel_SRPD_PCIE/src/sipc/spool.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright (C) 2018 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "../include/sipc.h" -#include "spool.h" - -#define SLOG_NR_BASE_NUM MKDEV(156, 0) - -struct spool_device; - -struct spool_device { - struct spool_init_data *init; - int major; - int minor; - struct cdev cdev; - struct platform_device *plt_dev; - - struct device *sys_dev; /* Device object in sysfs */ -}; - -struct spool_sblock { - u8 dst; - u8 channel; - bool is_hold; - struct sblock hold; -}; - -static struct class *spool_class; - -static int spool_open(struct inode *inode, struct file *filp) -{ - struct spool_device *spool; - struct spool_sblock *sblock; - int ret; - - spool = container_of(inode->i_cdev, struct spool_device, cdev); - ret = sblock_query(spool->init->dst, spool->init->channel); - if (ret) - return ret; - sblock = kmalloc(sizeof(struct spool_sblock), GFP_KERNEL); - if (!sblock) - return -ENOMEM; - filp->private_data = sblock; - - sblock->dst = spool->init->dst; - sblock->channel = spool->init->channel; - sblock->is_hold = 0; - - return 0; -} - -static int spool_release(struct inode *inode, struct file *filp) -{ - struct spool_sblock *sblock = filp->private_data; - - if (sblock->is_hold) { - if (sblock_release(sblock->dst, sblock->channel, &sblock->hold)) - pr_debug("failed to release block!\n"); - } - kfree(sblock); - - return 0; -} - -static ssize_t spool_read(struct file *filp, - char __user *buf, size_t count, loff_t *ppos) -{ - struct spool_sblock *sblock = filp->private_data; - int timeout = -1; - int ret = 0; - int rdsize = 0; - struct sblock blk = {0}; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - if (sblock->is_hold) { - if (count < sblock->hold.length - *ppos) { - rdsize = count; - } else { - rdsize = sblock->hold.length - *ppos; - sblock->is_hold = 0; - } - blk = sblock->hold; - } else{ - *ppos = 0; - ret = sblock_receive(sblock->dst, - sblock->channel, &blk, timeout); - if (ret < 0) { - pr_debug("%s: failed to receive block!\n", __func__); - return ret; - } - if (blk.length <= count) - rdsize = blk.length; - else { - rdsize = count; - sblock->is_hold = 1; - sblock->hold = blk; - } - } - - if (unalign_copy_to_user(buf, blk.addr + *ppos, rdsize)) { - pr_err("%s: failed to copy to user!\n", __func__); - sblock->is_hold = 0; - *ppos = 0; - ret = -EFAULT; - } else { - ret = rdsize; - *ppos += rdsize; - } - - if (sblock->is_hold == 0) { - if (sblock_release(sblock->dst, sblock->channel, &blk)) - pr_err("%s: failed to release block!\n", __func__); - } - - return ret; -} - -static ssize_t spool_write(struct file *filp, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct spool_sblock *sblock = filp->private_data; - int timeout = -1; - int ret = 0; - int wrsize = 0; - int pos = 0; - struct sblock blk = {0}; - size_t len = count; - - if (filp->f_flags & O_NONBLOCK) - timeout = 0; - - do { - ret = sblock_get(sblock->dst, sblock->channel, &blk, timeout); - if (ret < 0) { - pr_info("%s: failed to get block!\n", __func__); - return ret; - } - - wrsize = (blk.length > len ? len : blk.length); - if (unalign_copy_from_user(blk.addr, buf + pos, wrsize)) { - pr_info("%s: failed to copy from user!\n", __func__); - ret = -EFAULT; - } else { - blk.length = wrsize; - len -= wrsize; - pos += wrsize; - } - - if (sblock_send(sblock->dst, sblock->channel, &blk)) - pr_debug("%s: failed to send block!", __func__); - } while (len > 0 && ret == 0); - - return count - len; -} - -static unsigned int spool_poll(struct file *filp, poll_table *wait) -{ - struct spool_sblock *sblock = filp->private_data; - - return sblock_poll_wait(sblock->dst, sblock->channel, filp, wait); -} - -static long spool_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - return 0; -} - -static const struct file_operations spool_fops = { - .open = spool_open, - .release = spool_release, - .read = spool_read, - .write = spool_write, - .poll = spool_poll, - .unlocked_ioctl = spool_ioctl, - .owner = THIS_MODULE, - .llseek = default_llseek, -}; - -#ifdef SPRD_PCIE_USE_DTS -static int spool_parse_dt(struct spool_init_data **init, struct device *dev, - struct device_node *np, dev_t *dev_no) -{ - struct spool_init_data *pdata = NULL; - int ret; - u32 data; - - pdata = devm_kzalloc(dev, sizeof(struct spool_init_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - ret = of_property_read_string(np, "sprd,name", - (const char **)&pdata->name); - if (ret) - goto error; - - if (!strcmp(pdata->name, "slog_nr")) - *dev_no = SLOG_NR_BASE_NUM; - - ret = of_property_read_u32(np, "sprd,dst", (u32 *)&data); - if (ret) - goto error; - pdata->dst = (u8)data; - - ret = of_property_read_u32(np, "sprd,channel", (u32 *)&data); - if (ret) - goto error; - pdata->channel = (u8)data; - - ret = of_property_read_u32(np, "sprd,preconfigured", (u32 *)&data); - if (!ret) - pdata->pre_cfg = (int)data; - - ret = of_property_read_u32(np, "sprd,tx-blksize", - (u32 *)&pdata->txblocksize); - if (ret) - goto error; - ret = of_property_read_u32(np, "sprd,tx-blknum", - (u32 *)&pdata->txblocknum); - if (ret) - goto error; - ret = of_property_read_u32(np, "sprd,rx-blksize", - (u32 *)&pdata->rxblocksize); - if (ret) - goto error; - ret = of_property_read_u32(np, "sprd,rx-blknum", - (u32 *)&pdata->rxblocknum); - if (ret) - goto error; - - if (!of_property_read_u32(np, "sprd,nodev", (u32 *)&data)) - pdata->nodev = (u8)data; - - *init = pdata; - return ret; -error: - devm_kfree(dev, pdata); - *init = NULL; - return ret; -} -#else -static int spool_parse_dt(struct spool_init_data **init, struct device *dev, - struct device_node *np, dev_t *dev_no) -{ - struct spool_init_data *pdata = NULL; - - pdata = devm_kzalloc(dev, sizeof(struct spool_init_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - pdata->name = "slog_nr"; - if (!strcmp(pdata->name, "slog_nr")) - *dev_no = SLOG_NR_BASE_NUM; - pdata->dst = 1; - pdata->channel = 5; - pdata->txblocksize = 0; - pdata->txblocknum = 0; - pdata->rxblocksize = 0x10000; - pdata->rxblocknum = 32; - *init = pdata; - - return 0; -} -#endif - - -static ssize_t base_addr_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct spool_device *spool = (struct spool_device *) - dev_get_drvdata(dev); - struct spool_init_data *init = spool->init; - uint32_t addr; - int ret; - - ret = sblock_get_smem_cp_addr(init->dst, init->channel, - &addr); - if (ret < 0) - return ret; - - return snprintf(buf, PAGE_SIZE, "%u %u 0x%08X %d %u %u %u %u\n", - (unsigned int)init->dst, - (unsigned int)init->channel, - addr, - init->pre_cfg, - (unsigned int)init->txblocknum, - (unsigned int)init->txblocksize, - (unsigned int)init->rxblocknum, - (unsigned int)init->rxblocksize); -} - -static DEVICE_ATTR(base_addr, 0440, - base_addr_show, NULL); - -static int create_spool(struct platform_device *pdev, - struct spool_init_data *init, - struct spool_device **out, dev_t dev_no) -{ - int rval; - struct spool_device *spool; - //dev_t dev_no; - char sp_name[16]; - - snprintf(sp_name, sizeof(sp_name), "spool-%u-%u", - (unsigned int)init->dst, - (unsigned int)init->channel); - //rval = alloc_chrdev_region(&dev_no, 0, 1, sp_name); - rval = register_chrdev_region(dev_no, 1, sp_name); - if (rval) - return rval; - - if (init->pre_cfg) - rval = sblock_pcfg_create(init->dst, - init->channel, - init->txblocknum, - init->txblocksize, - init->rxblocknum, - init->rxblocksize); - else - rval = sblock_create(init->dst, - init->channel, - init->txblocknum, - init->txblocksize, - init->rxblocknum, - init->rxblocksize); - if (rval) { - pr_info("Failed to create sblock: %d\n", rval); - goto free_devno; - } - - spool = devm_kzalloc(&pdev->dev, - sizeof(struct spool_device), - GFP_KERNEL); - if (!spool) { - pr_info("Failed to allocate spool_device\n"); - rval = -ENOMEM; - goto free_sblock; - } - - spool->init = init; - spool->major = MAJOR(dev_no); - spool->minor = MINOR(dev_no); - spool->plt_dev = pdev; - - if (!init->nodev) { - cdev_init(&spool->cdev, &spool_fops); - - rval = cdev_add(&spool->cdev, dev_no, 1); - if (rval) { - pr_info("Failed to add spool cdev\n"); - goto free_spool; - } - } - - spool->sys_dev = device_create(spool_class, NULL, - dev_no, - spool, "%s", init->name); - device_create_file(&pdev->dev, &dev_attr_base_addr); - - platform_set_drvdata(pdev, spool); - - *out = spool; - - return 0; - -free_spool: - devm_kfree(&pdev->dev, spool); - -free_sblock: - sblock_destroy(init->dst, init->channel); - -free_devno: - unregister_chrdev_region(dev_no, 1); - return rval; -} - -static int destroy_spool(struct spool_device *spool) -{ - dev_t dev_no = MKDEV(spool->major, spool->minor); - struct spool_init_data *init = spool->init; - - if (spool->sys_dev) { - device_destroy(spool_class, dev_no); - spool->sys_dev = NULL; - } - if (!init->nodev) - cdev_del(&spool->cdev); - sblock_destroy(init->dst, init->channel); - unregister_chrdev_region(dev_no, 1); - devm_kfree(&spool->plt_dev->dev, init); - devm_kfree(&spool->plt_dev->dev, spool); - - return 0; -} - -static int spool_probe(struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - int rval; - struct spool_init_data *init; - struct spool_device *spool; - dev_t dev_no; - -#ifdef SPRD_PCIE_USE_DTS - if (!np) - return -ENODEV; -#endif - - rval = spool_parse_dt(&init, &pdev->dev, np, &dev_no); - if (rval) { - pr_err("Failed to parse spool device tree, ret=%d\n", - rval); - return rval; - } - - pr_info("spool: name=%s, dst=%u, channel=%u, pre_cfg=%u\n", - init->name, - init->dst, - init->channel, - init->pre_cfg); - - pr_info("spool: tx_num=%u, tx_size=%u, rx_num=%u, rx_size=%u\n", - init->txblocknum, - init->txblocksize, - init->rxblocknum, - init->rxblocksize); - - rval = create_spool(pdev, init, &spool, dev_no); - if (rval) { - pr_err("Failed to create spool device %u:%u, ret=%d\n", - (unsigned int)init->dst, - (unsigned int)init->channel, rval); - devm_kfree(&pdev->dev, init); - } - - return 0; -} - -static int spool_remove(struct platform_device *pdev) -{ - struct spool_device *priv = (struct spool_device *) - platform_get_drvdata(pdev); - - destroy_spool(priv); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef SPRD_PCIE_USE_DTS -static const struct of_device_id spool_match_table[] = { - { .compatible = "sprd,spool", }, - { }, -}; -#endif - -static struct platform_driver spool_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "spool", -#ifdef SPRD_PCIE_USE_DTS - .of_match_table = spool_match_table, -#endif - }, - .probe = spool_probe, - .remove = spool_remove, -}; - -#ifndef SPRD_PCIE_USE_DTS -static void spool_platform_device_release(struct device *dev) {} -static struct platform_device spool_device = { - .name = "spool", - .id = -1, - .dev = { - .release = spool_platform_device_release, - } -}; -#endif - -int spool_init(void) -{ - int ret; - - spool_class = class_create(THIS_MODULE, "spool"); - if (IS_ERR(spool_class)) - return PTR_ERR(spool_class); -#ifndef SPRD_PCIE_USE_DTS - if((ret = platform_device_register(&spool_device))) - return ret; -#endif - if((ret = platform_driver_register(&spool_driver))) { -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&spool_device); -#endif - return ret; - } - - return ret; -} -EXPORT_SYMBOL_GPL(spool_init); - -void spool_exit(void) -{ - platform_driver_unregister(&spool_driver); -#ifndef SPRD_PCIE_USE_DTS - platform_device_unregister(&spool_device); -#endif - class_destroy(spool_class); -} - - -void spool_device_down(void) -{ - sblock_down(1, 5); -} - -EXPORT_SYMBOL_GPL(spool_exit); -EXPORT_SYMBOL_GPL(spool_device_down); diff --git a/quectel_SRPD_PCIE/src/sipc/spool.h b/quectel_SRPD_PCIE/src/sipc/spool.h deleted file mode 100644 index c0c5d2e..0000000 --- a/quectel_SRPD_PCIE/src/sipc/spool.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2019 Spreadtrum Communications Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __SPOOL_H -#define __SPOOL_H - -struct spool_init_data { - char *name; - u8 dst; - u8 channel; - u8 nodev; - /* Preconfigured channel */ - int pre_cfg; - u32 txblocknum; - u32 txblocksize; - u32 rxblocknum; - u32 rxblocksize; -}; -#endif diff --git a/quectel_cm_5G/Makefile b/quectel_cm_5G/Makefile deleted file mode 100644 index 5eff117..0000000 --- a/quectel_cm_5G/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:= quectel-CM-5G -PKG_VERSION:=1.6.4 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/quectel-CM-5G - SECTION:=utils - CATEGORY:=Utilities - TITLE:=quectel-CM-5G app -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - CC="$(TARGET_CC)" -endef - -define Package/quectel-CM-5G/install - $(INSTALL_DIR) $(1)/usr/bin $(1)/lib/netifd/proto - $(INSTALL_BIN) $(PKG_BUILD_DIR)/quectel-CM $(1)/usr/bin - $(INSTALL_BIN) ./files/rmnet_init.sh $(1)/lib/netifd - $(INSTALL_BIN) ./files/rmnet.script $(1)/lib/netifd - $(INSTALL_BIN) ./files/rmnet.sh $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/rmnet6.sh $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/rmnet6.script $(1)/lib/netifd -endef - -$(eval $(call BuildPackage,quectel-CM-5G)) diff --git a/quectel_cm_5G/files/dhcp b/quectel_cm_5G/files/dhcp deleted file mode 100644 index 7673927..0000000 --- a/quectel_cm_5G/files/dhcp +++ /dev/null @@ -1,48 +0,0 @@ - -config dnsmasq - option domainneeded '1' - option boguspriv '1' - option filterwin2k '0' - option localise_queries '1' - option rebind_protection '1' - option rebind_localhost '1' - option local '/lan/' - option domain 'lan' - option expandhosts '1' - option nonegcache '0' - option authoritative '1' - option readethers '1' - option leasefile '/tmp/dhcp.leases' - option resolvfile '/tmp/resolv.conf.auto' - option nonwildcard '1' - option localservice '1' - -config dhcp 'lan' - option interface 'lan' - option start '100' - option limit '150' - option leasetime '12h' - option ra 'relay' - option dhcpv6 'disabled' - option ndp 'relay' - -config dhcp 'wan' - option interface 'wan' - option ignore '1' - option ra 'relay' - option dhcpv6 'disabled' - option ndp 'relay' - option ndproxy_routing '0' - option master '1' - -config dhcp 'wan6' - option ra 'relay' - option dhcpv6 'disabled' - option ndp 'relay' - option ndproxy_routing '0' - option master '1' - option interface 'wan6' - -config odhcpd 'odhcpd' - option loglevel '7' - diff --git a/quectel_cm_5G/files/rmnet.script b/quectel_cm_5G/files/rmnet.script deleted file mode 100644 index 5bafb90..0000000 --- a/quectel_cm_5G/files/rmnet.script +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - - -[ -z "$1" ] && echo "Error: should be run by rmnet" && exit 1 -[ -z "$2" ] && echo "Error: should be run by rmnet" && exit 1 - -. /lib/functions.sh -. /lib/functions/network.sh -. /lib/netifd/netifd-proto.sh - -setup_interface() { - INTERFACE=$1 - CONFIG=/tmp/rmnet_$2_ipv4config - logger "rmnet setup_interface $1 $2 here" - #Fetch information from lower. - [ -f ${CONFIG} ] || { - proto_notify_error "$INTERFACE" "RMNET data call Not ready" - proto_block_restart "$INTERFACE" - return - } - . ${CONFIG} - ip=$PUBLIC_IP - DNS=$DNSSERVERS - router=$GATEWAY - subnet=$NETMASK - interface=$IFNAME - #Send the information to the netifd - proto_init_update "$interface" 1 1 - #ip and subnet - proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}" - - #Any router? if not, remove below scripts - #router format should be separated by space - for i in $router; do - proto_add_ipv4_route "$i" 32 "" "$ip" - proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" - done - - #dns information tell the netifd. - for dns in $DNS; do - proto_add_dns_server "$dns" - done - - #Domain information tell the netifd - for domain in $domain; do - proto_add_dns_search "$domain" - done - - #proto_add_data - [ -n "$ZONE" ] && json_add_string zone "$ZONE" - proto_close_data - - proto_send_update "$INTERFACE" - -} - -case "$1" in - renew) - setup_interface $2 $3 - ;; -esac - -exit 0 diff --git a/quectel_cm_5G/files/rmnet.sh b/quectel_cm_5G/files/rmnet.sh deleted file mode 100644 index 101ee60..0000000 --- a/quectel_cm_5G/files/rmnet.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - -. /lib/functions.sh -. /lib/functions/network.sh -. ../netifd-proto.sh - -init_proto "$@" - -proto_rmnet_setup() { - local cfg="$1" - local iface="$2" - - logger "rmnet started" - #Call rmnet management script below!! - logger "rmnet updated ${cfg} ${iface}" - /lib/netifd/rmnet.script renew $cfg $iface -} - -proto_rmnet_teardown() { - local cfg="$1" - #Tear down rmnet manager script here.*/ -} - -proto_rmnet_init_config() { - #ddno_device=1 - available=1 -} - -add_protocol rmnet diff --git a/quectel_cm_5G/files/rmnet6.script b/quectel_cm_5G/files/rmnet6.script deleted file mode 100644 index bbe05b2..0000000 --- a/quectel_cm_5G/files/rmnet6.script +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - - -[ -z "$1" ] && echo "Error: should be run by rmnet" && exit 1 -[ -z "$2" ] && echo "Error: should be run by rmnet" && exit 1 - -. /lib/functions.sh -. /lib/functions/network.sh -. /lib/netifd/netifd-proto.sh - -setup_interface() { - INTERFACE=$1 - CONFIG=/tmp/rmnet_$2_ipv6config - logger "rmnet setup_interface $1 $2 here" - #Fetch information from lower. - [ -f ${CONFIG} ] || { - proto_notify_error "$INTERFACE" "RMNET data call NOT ready" - proto_block_restart "$INTERFACE" - return - } - . ${CONFIG} - ADDRESSES=$PUBLIC_IP - interface=$IFNAME - #Send the information to the netifd - proto_init_update "$interface" 1 1 - - #ip and subnet - proto_add_ipv6_address "${PUBLIC_IP}" "128" - proto_add_ipv6_prefix "${PUBLIC_IP}/${PrefixLength}" - - #router format should be separated by space - proto_add_ipv6_route "$GATEWAY" 128 - proto_add_ipv6_route "::0" 0 "$GATEWAY" "" "" "${PUBLIC_IP}/${PrefixLength}" - - #dns information tell the netifd. - for dns in $DNSSERVERS; do - proto_add_dns_server "$dns" - done - - #Domain information tell the netifd - for domain in $domain; do - proto_add_dns_search "$domain" - done - - #proto_add_data - [ -n "$ZONE" ] && json_add_string zone "$ZONE" - proto_close_data - - proto_send_update "$INTERFACE" -} - -case "$1" in - renew|bound) - setup_interface $2 $3 - ;; -esac - -exit 0 diff --git a/quectel_cm_5G/files/rmnet6.sh b/quectel_cm_5G/files/rmnet6.sh deleted file mode 100644 index 57a5495..0000000 --- a/quectel_cm_5G/files/rmnet6.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - -. /lib/functions.sh -. /lib/functions/network.sh -. ../netifd-proto.sh - -init_proto "$@" - -proto_rmnet6_setup() { - local cfg="$1" - local iface="$2" - - logger "rmnet6 started" - #Call rmnet management script below!! - /lib/netifd/rmnet6.script renew $cfg $iface - logger "rmnet6 updated" -} - -proto_rmnet6_teardown() { - local cfg="$1" - #Tear down rmnet manager script here.*/ -} - -proto_rmnet6_init_config() { - #ddno_device=1 - available=1 -} - -add_protocol rmnet6 diff --git a/quectel_cm_5G/files/rmnet_init.sh b/quectel_cm_5G/files/rmnet_init.sh deleted file mode 100644 index 3d55438..0000000 --- a/quectel_cm_5G/files/rmnet_init.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -uci set network.wan='interface' -uci set network.wan.ifname='wwan0' -uci set network.wan.proto='rmnet' - -uci set network.wan6='interface' -uci set network.wan6.ifname='wwan0' -uci set network.wan6.proto='rmnet6' - -uci set dhcp.lan.ra='relay' -uci set dhcp.lan.dhcpv6='disabled' -uci set dhcp.lan.ndp='relay' - -uci set dhcp.wan.ra='relay' -uci set dhcp.wan.dhcpv6='disabled' -uci set dhcp.wan.ndp='relay' -uci set dhcp.wan.ndproxy_routing='0' - -uci set dhcp.wan6=dhcp -uci set dhcp.wan6.interface='wan6' -uci set dhcp.wan6.ra='relay' -uci set dhcp.wan6.dhcpv6='disabled' -uci set dhcp.wan6.ndp='relay' -uci set dhcp.wan6.ndproxy_routing='0' -uci set dhcp.wan6.master='1' - -uci set dhcp.odhcpd=odhcpd -uci set dhcp.odhcpd.loglevel='7' - -uci commit diff --git a/quectel_cm_5G/src/CMakeLists.txt b/quectel_cm_5G/src/CMakeLists.txt deleted file mode 100644 index 8ce3f5a..0000000 --- a/quectel_cm_5G/src/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -cmake_minimum_required(VERSION 2.4) - -project(quectel-CM) -add_definitions(-Wall -Wextra -Werror -O1) -option(USE_QRTR "Enable QRTR" OFF) - -set( QL_CM_SRC - QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c - atc.c atchannel.c at_tok.c - udhcpc.c - ) - -if(USE_QRTR) -add_definitions(-DCONFIG_QRTR) -set( QRTR_SRC qrtr.c rmnetctl.c) -endif() - -add_executable(quectel-CM ${QL_CM_SRC} ${QRTR_SRC}) -target_link_libraries(quectel-CM PUBLIC pthread) -install (TARGETS quectel-CM DESTINATION bin) - -add_executable(quectel-qmi-proxy quectel-qmi-proxy.c) -target_link_libraries(quectel-qmi-proxy PUBLIC pthread) -install (TARGETS quectel-qmi-proxy DESTINATION bin) - -add_executable(quectel-mbim-proxy quectel-mbim-proxy.c) -target_link_libraries(quectel-mbim-proxy PUBLIC pthread) -install (TARGETS quectel-mbim-proxy DESTINATION bin) - -add_executable(quectel-atc-proxy quectel-atc-proxy.c atchannel.c at_tok.c util.c) -target_link_libraries(quectel-atc-proxy PUBLIC pthread) -install (TARGETS quectel-atc-proxy DESTINATION bin) - -add_executable(quectel-qrtr-proxy quectel-qrtr-proxy.c) -target_link_libraries(quectel-qrtr-proxy PUBLIC pthread) -install (TARGETS quectel-qrtr-proxy DESTINATION bin) diff --git a/quectel_cm_5G/src/GobiNetCM.c b/quectel_cm_5G/src/GobiNetCM.c deleted file mode 100644 index a270fd8..0000000 --- a/quectel_cm_5G/src/GobiNetCM.c +++ /dev/null @@ -1,246 +0,0 @@ -/****************************************************************************** - @file GobiNetCM.c - @brief GobiNet driver. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include "QMIThread.h" - -#ifdef CONFIG_GOBINET -static int qmiclientId[QMUX_TYPE_ALL]; - -// IOCTL to generate a client ID for this service type -#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1 - -// IOCTL to get the VIDPID of the device -#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2 - -// IOCTL to get the MEID of the device -#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3 - -static int GobiNetSendQMI(PQCQMIMSG pRequest) { - int ret, fd; - - fd = qmiclientId[pRequest->QMIHdr.QMIType]; - pRequest->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pRequest->QMIHdr.QMIType; - - if (fd <= 0) { - dbg_time("%s QMIType: %d has no clientID", __func__, pRequest->QMIHdr.QMIType); - return -ENODEV; - } - - // Always ready to write - if (1 == 1) { - ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR); - ret = write(fd, &pRequest->MUXMsg, nwrites); - if (ret == nwrites) { - ret = 0; - } else { - dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - } - } else { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - } - - return ret; -} - -static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType) { - int ClientId; - ClientId = cm_open_dev(qcqmi); - if (ClientId == -1) { - dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno, strerror(errno)); - return -1; - } - - if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) { - dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType, errno, strerror(errno)); - close(ClientId); - ClientId = 0; - } - - switch (QMIType) { - case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; - case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; - case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; - case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; - case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; - case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; - case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; - case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break; - case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); - break; - default: break; - } - - return ClientId; -} - -static int GobiNetDeInit(void) { - unsigned int i; - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - close(qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static void * GobiNetThread(void *pData) { - PROFILE_T *profile = (PROFILE_T *)pData; - const char *qcqmi = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - - qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); - if (profile->enable_ipv6) - qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); - qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS); - qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS); - qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM); -#ifdef CONFIG_COEX_WWAN_STATE - qmiclientId[QMUX_TYPE_COEX] = GobiNetGetClientID(qcqmi, QMUX_TYPE_COEX); -#endif - if (profile->qmap_mode == 0 || profile->loopback_state) {//when QMAP enabled, set data format in GobiNet Driver - qmiclientId[QMUX_TYPE_WDS_ADMIN] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN); - profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; - } - - //donot check clientWDA, there is only one client for WDA, if quectel-CM is killed by SIGKILL, i cannot get client ID for WDA again! - if (qmiclientId[QMUX_TYPE_WDS] == 0) /*|| (clientWDA == -1)*/ { - GobiNetDeInit(); - dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno, strerror(errno)); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - pthread_exit(NULL); - return NULL; - } - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (1) { - struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}}; - int ne, ret, nevents = 1; - unsigned int i; - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - pollfds[nevents].fd = qmiclientId[i]; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents = 0; - nevents++; - } - } - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000: -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (fd == qmidevice_control_fd[1]) { - } else { - } - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __GobiNetThread_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __GobiNetThread_quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - continue; - } - - { - ssize_t nreads; - PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; - - nreads = read(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR)); - if (nreads <= 0) - { - dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - break; - } - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] == fd) - { - pResponse->QMIHdr.QMIType = i; - } - } - - pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pResponse->QMIHdr.Length = cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1); - pResponse->QMIHdr.CtlFlags = 0x00; - pResponse->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pResponse->QMIHdr.QMIType;; - - QmiThreadRecvQMI(pResponse); - } - } - } - -__GobiNetThread_quit: - GobiNetDeInit(); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -const struct qmi_device_ops gobi_qmidev_ops = { - .deinit = GobiNetDeInit, - .send = GobiNetSendQMI, - .read = GobiNetThread, -}; -#endif - diff --git a/quectel_cm_5G/src/MPQCTL.h b/quectel_cm_5G/src/MPQCTL.h deleted file mode 100644 index 49fe5c3..0000000 --- a/quectel_cm_5G/src/MPQCTL.h +++ /dev/null @@ -1,390 +0,0 @@ -/*=========================================================================== - - M P Q C T L. H -DESCRIPTION: - - This module contains QMI QCTL module. - -INITIALIZATION AND SEQUENCING REQUIREMENTS: - -Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. -===========================================================================*/ - -#ifndef MPQCTL_H -#define MPQCTL_H - -#include "MPQMI.h" - -#pragma pack(push, 1) - -// ================= QMICTL ================== - -// QMICTL Control Flags -#define QMICTL_CTL_FLAG_CMD 0x00 -#define QMICTL_CTL_FLAG_RSP 0x01 -#define QMICTL_CTL_FLAG_IND 0x02 - -#if 0 -typedef struct _QMICTL_TRANSACTION_ITEM -{ - LIST_ENTRY List; - UCHAR TransactionId; // QMICTL transaction id - PVOID Context; // Adapter or IocDev - PIRP Irp; -} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM; -#endif - -typedef struct _QCQMICTL_MSG_HDR -{ - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; -} __attribute__ ((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR; - -#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR) - -typedef struct _QCQMICTL_MSG_HDR_RESP -{ - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__ ((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP; - -typedef struct _QCQMICTL_MSG -{ - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; - UCHAR Payload; -} __attribute__ ((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG; - -// TLV Header -typedef struct _QCQMICTL_TLV_HDR -{ - UCHAR TLVType; - USHORT TLVLength; -} __attribute__ ((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR; - -#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR) - -// QMICTL Type -#define QMICTL_SET_INSTANCE_ID_REQ 0x0020 -#define QMICTL_SET_INSTANCE_ID_RESP 0x0020 -#define QMICTL_GET_VERSION_REQ 0x0021 -#define QMICTL_GET_VERSION_RESP 0x0021 -#define QMICTL_GET_CLIENT_ID_REQ 0x0022 -#define QMICTL_GET_CLIENT_ID_RESP 0x0022 -#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023 -#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023 -#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024 -#define QMICTL_INVALID_CLIENT_ID_IND 0x0025 -#define QMICTL_SET_DATA_FORMAT_REQ 0x0026 -#define QMICTL_SET_DATA_FORMAT_RESP 0x0026 -#define QMICTL_SYNC_REQ 0x0027 -#define QMICTL_SYNC_RESP 0x0027 -#define QMICTL_SYNC_IND 0x0027 -#define QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN 0xFF00 - -#define QMICTL_FLAG_REQUEST 0x00 -#define QMICTL_FLAG_RESPONSE 0x01 -#define QMICTL_FLAG_INDICATION 0x02 - -// QMICTL Message Definitions - -typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ - USHORT Length; // 4 - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR Value; // Host-unique QMI instance for this device driver -} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG, *PQMICTL_SET_INSTANCE_ID_REQ_MSG; - -typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 0x0002 - USHORT QMI_ID; // Upper byte is assigned by MSM, - // lower assigned by host -} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG, *PQMICTL_SET_INSTANCE_ID_RESP_MSG; - -typedef struct _QMICTL_GET_VERSION_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_VERSION_REQ - USHORT Length; // 0 - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // var - UCHAR QMUXTypes; // List of one byte QMUX_TYPE values - // 0xFF returns a list of versions for all - // QMUX_TYPEs implemented on the device -} __attribute__ ((packed)) QMICTL_GET_VERSION_REQ_MSG, *PQMICTL_GET_VERSION_REQ_MSG; - -typedef struct _QMUX_TYPE_VERSION_STRUCT -{ - UCHAR QMUXType; - USHORT MajorVersion; - USHORT MinorVersion; -} __attribute__ ((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT; - -typedef struct _ADDENDUM_VERSION_PREAMBLE -{ - UCHAR LabelLength; - UCHAR Label; -} __attribute__ ((packed)) ADDENDUM_VERSION_PREAMBLE, *PADDENDUM_VERSION_PREAMBLE; - -#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01 -#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10 - -typedef struct _QMICTL_GET_VERSION_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_VERSION_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // var - UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT - QMUX_TYPE_VERSION_STRUCT TypeVersion[0]; -} __attribute__ ((packed)) QMICTL_GET_VERSION_RESP_MSG, *PQMICTL_GET_VERSION_RESP_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR QMIType; // QMUX type -} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG, *PQMICTL_GET_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 2 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG, *PQMICTL_GET_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG, *PQMICTL_RELEASE_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 2 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG, *PQMICTL_RELEASE_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG, *PQMICTL_REVOKE_CLIENT_ID_IND_MSG; - -typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG, *PQMICTL_INVALID_CLIENT_ID_IND_MSG; - -typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR DataFormat; // 0-default; 1-QoS hdr present -} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG, *PQMICTL_SET_DATA_FORMAT_REQ_MSG; - -#ifdef QC_IP_MODE -#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10 -#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001 -#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT -{ - UCHAR TLVType; // Link-Layer Protocol - USHORT TLVLength; // 2 - USHORT LinkProt; // 0x1: ETH; 0x2: IP -} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT; - -#ifdef QCMP_UL_TLP -#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP -{ - UCHAR TLVType; // 0x11, Uplink TLP Setting - USHORT TLVLength; // 1 - UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP; -#endif // QCMP_UL_TLP - -#ifdef QCMP_DL_TLP -#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP -{ - UCHAR TLVType; // 0x11, Uplink TLP Setting - USHORT TLVLength; // 1 - UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP; -#endif // QCMP_DL_TLP - -#endif // QC_IP_MODE - -#ifdef MP_QCQOS_ENABLED -#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING -{ - UCHAR TLVType; // 0x12, QoS setting - USHORT TLVLength; // 1 - UCHAR QosSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING, *PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING; -#endif // MP_QCQOS_ENABLED - -typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code -} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG, *PQMICTL_SET_DATA_FORMAT_RESP_MSG; - -typedef struct _QMICTL_SYNC_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ - USHORT Length; // 0 -} __attribute__ ((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG; - -typedef struct _QMICTL_SYNC_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; -} __attribute__ ((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG; - -typedef struct _QMICTL_SYNC_IND_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; -} __attribute__ ((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG; - -typedef struct _QMICTL_LIBQMI_PROXY_OPEN_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - char device_path[0]; // result code -} __attribute__ ((packed)) QMICTL_LIBQMI_PROXY_OPEN_MSG, *PQMICTL_LIBQMI_PROXY_OPEN_MSG; - -typedef struct _QMICTL_MSG -{ - union - { - // Message Header - QCQMICTL_MSG_HDR QMICTLMsgHdr; - QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp; - - // QMICTL Message - QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq; - QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp; - QMICTL_GET_VERSION_REQ_MSG GetVersionReq; - QMICTL_GET_VERSION_RESP_MSG GetVersionRsp; - QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq; - QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp; - QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq; - QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp; - QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd; - QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd; - QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp; - QMICTL_SYNC_REQ_MSG SyncReq; - QMICTL_SYNC_RESP_MSG SyncRsp; - QMICTL_SYNC_IND_MSG SyncInd; - QMICTL_LIBQMI_PROXY_OPEN_MSG LibQmiProxyOpenReq; - }; -} __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG; -#pragma pack(pop) - -#endif // MPQCTL_H diff --git a/quectel_cm_5G/src/MPQMI.h b/quectel_cm_5G/src/MPQMI.h deleted file mode 100644 index 1d2204b..0000000 --- a/quectel_cm_5G/src/MPQMI.h +++ /dev/null @@ -1,325 +0,0 @@ -/*=========================================================================== - - M P Q M I. H -DESCRIPTION: - - This module contains forward references to the QMI module. - -INITIALIZATION AND SEQUENCING REQUIREMENTS: - -Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. -===========================================================================*/ -/*=========================================================================== - - EDIT HISTORY FOR FILE - $Header: //depot/QMI/win/qcdrivers/ndis/MPQMI.h#3 $ - -when who what, where, why --------- --- ---------------------------------------------------------- -11/20/04 hg Initial version. -===========================================================================*/ - -#ifndef USBQMI_H -#define USBQMI_H - -typedef uint8_t uint8; -typedef int8_t int8; -typedef uint16_t uint16; -typedef int16_t int16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -typedef signed char CHAR; -typedef unsigned char UCHAR; -typedef short SHORT; -typedef unsigned short USHORT; -typedef int INT; -typedef unsigned int UINT; -typedef long LONG; -typedef unsigned int ULONG; -typedef unsigned long long ULONG64; -typedef signed char *PCHAR; -typedef unsigned char *PUCHAR; -typedef int *PINT; -typedef int BOOL; - -#define TRUE (1 == 1) -#define FALSE (1 != 1) - -#define QMICTL_SUPPORTED_MAJOR_VERSION 1 -#define QMICTL_SUPPORTED_MINOR_VERSION 0 - -#pragma pack(push, 1) - -// ========= USB Control Message ========== - -#define USB_CTL_MSG_TYPE_QMI 0x01 - -// USB Control Message -typedef struct _QCUSB_CTL_MSG_HDR -{ - UCHAR IFType; -} __attribute__ ((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR; - -#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR) - -typedef struct _QCUSB_CTL_MSG -{ - UCHAR IFType; - UCHAR Message; -} __attribute__ ((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG; - -#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01 -#define QCTLV_TYPE_RESULT_CODE 0x02 - -// ================= QMI ================== - -// Define QMI Type -typedef enum _QMI_SERVICE_TYPE -{ - QMUX_TYPE_CTL = 0x00, - QMUX_TYPE_WDS = 0x01, - QMUX_TYPE_DMS = 0x02, - QMUX_TYPE_NAS = 0x03, - QMUX_TYPE_QOS = 0x04, - QMUX_TYPE_WMS = 0x05, - QMUX_TYPE_PDS = 0x06, - QMUX_TYPE_UIM = 0x0B, - QMUX_TYPE_WDS_IPV6 = 0x11, - QMUX_TYPE_WDS_ADMIN = 0x1A, - QMUX_TYPE_COEX = 0x22, - QMUX_TYPE_MAX = 0xFF, - QMUX_TYPE_ALL = 0xFF -} QMI_SERVICE_TYPE; - -typedef enum _QMI_RESULT_CODE_TYPE -{ - QMI_RESULT_SUCCESS = 0x0000, - QMI_RESULT_FAILURE = 0x0001 -} QMI_RESULT_CODE_TYPE; - -typedef enum _QMI_ERROR_CODE_TYPE -{ - QMI_ERR_NONE = 0x0000 - ,QMI_ERR_MALFORMED_MSG = 0x0001 - ,QMI_ERR_NO_MEMORY = 0x0002 - ,QMI_ERR_INTERNAL = 0x0003 - ,QMI_ERR_ABORTED = 0x0004 - ,QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005 - ,QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006 - ,QMI_ERR_INVALID_CLIENT_ID = 0x0007 - ,QMI_ERR_NO_THRESHOLDS = 0x0008 - ,QMI_ERR_INVALID_HANDLE = 0x0009 - ,QMI_ERR_INVALID_PROFILE = 0x000A - ,QMI_ERR_INVALID_PINID = 0x000B - ,QMI_ERR_INCORRECT_PIN = 0x000C - ,QMI_ERR_NO_NETWORK_FOUND = 0x000D - ,QMI_ERR_CALL_FAILED = 0x000E - ,QMI_ERR_OUT_OF_CALL = 0x000F - ,QMI_ERR_NOT_PROVISIONED = 0x0010 - ,QMI_ERR_MISSING_ARG = 0x0011 - ,QMI_ERR_ARG_TOO_LONG = 0x0013 - ,QMI_ERR_INVALID_TX_ID = 0x0016 - ,QMI_ERR_DEVICE_IN_USE = 0x0017 - ,QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018 - ,QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019 - ,QMI_ERR_NO_EFFECT = 0x001A - ,QMI_ERR_NO_FREE_PROFILE = 0x001B - ,QMI_ERR_INVALID_PDP_TYPE = 0x001C - ,QMI_ERR_INVALID_TECH_PREF = 0x001D - ,QMI_ERR_INVALID_PROFILE_TYPE = 0x001E - ,QMI_ERR_INVALID_SERVICE_TYPE = 0x001F - ,QMI_ERR_INVALID_REGISTER_ACTION = 0x0020 - ,QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021 - ,QMI_ERR_AUTHENTICATION_FAILED = 0x0022 - ,QMI_ERR_PIN_BLOCKED = 0x0023 - ,QMI_ERR_PIN_PERM_BLOCKED = 0x0024 - ,QMI_ERR_SIM_NOT_INITIALIZED = 0x0025 - ,QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026 - ,QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027 - ,QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028 - ,QMI_ERR_INVALID_QOS_ID = 0x0029 - ,QMI_ERR_INVALID_ID = 0x0029 - ,QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A - ,QMI_ERR_INTERFACE_NOT_FOUND = 0x002B - ,QMI_ERR_FLOW_SUSPENDED = 0x002C - ,QMI_ERR_INVALID_DATA_FORMAT = 0x002D - ,QMI_ERR_GENERAL = 0x002E - ,QMI_ERR_UNKNOWN = 0x002F - ,QMI_ERR_INVALID_ARG = 0x0030 - ,QMI_ERR_INVALID_INDEX = 0x0031 - ,QMI_ERR_NO_ENTRY = 0x0032 - ,QMI_ERR_DEVICE_STORAGE_FULL = 0x0033 - ,QMI_ERR_DEVICE_NOT_READY = 0x0034 - ,QMI_ERR_NETWORK_NOT_READY = 0x0035 - ,QMI_ERR_CAUSE_CODE = 0x0036 - ,QMI_ERR_MESSAGE_NOT_SENT = 0x0037 - ,QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038 - ,QMI_ERR_INVALID_MESSAGE_ID = 0x0039 - ,QMI_ERR_ENCODING = 0x003A - ,QMI_ERR_AUTHENTICATION_LOCK = 0x003B - ,QMI_ERR_INVALID_TRANSITION = 0x003C - ,QMI_ERR_NOT_A_MCAST_IFACE = 0x003D - ,QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E - ,QMI_ERR_INVALID_MCAST_HANDLE = 0x003F - ,QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040 - ,QMI_ERR_SESSION_INACTIVE = 0x0041 - ,QMI_ERR_SESSION_INVALID = 0x0042 - ,QMI_ERR_SESSION_OWNERSHIP = 0x0043 - ,QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044 - ,QMI_ERR_DISABLED = 0x0045 - ,QMI_ERR_INVALID_OPERATION = 0x0046 - ,QMI_ERR_INVALID_QMI_CMD = 0x0047 - ,QMI_ERR_TPDU_TYPE = 0x0048 - ,QMI_ERR_SMSC_ADDR = 0x0049 - ,QMI_ERR_INFO_UNAVAILABLE = 0x004A - ,QMI_ERR_SEGMENT_TOO_LONG = 0x004B - ,QMI_ERR_SEGMENT_ORDER = 0x004C - ,QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D - ,QMI_ERR_OP_PARTIAL_FAILURE = 0x004E - ,QMI_ERR_POLICY_MISMATCH = 0x004F - ,QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050 - ,QMI_ERR_EXTENDED_INTERNAL = 0x0051 - ,QMI_ERR_ACCESS_DENIED = 0x0052 - ,QMI_ERR_HARDWARE_RESTRICTED = 0x0053 - ,QMI_ERR_ACK_NOT_SENT = 0x0054 - ,QMI_ERR_INJECT_TIMEOUT = 0x0055 - ,QMI_ERR_INCOMPATIBLE_STATE = 0x005A - ,QMI_ERR_FDN_RESTRICT = 0x005B - ,QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C - ,QMI_ERR_NO_RADIO = 0x005D - ,QMI_ERR_NOT_SUPPORTED = 0x005E - ,QMI_ERR_NO_SUBSCRIPTION = 0x005F - ,QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060 - ,QMI_ERR_NETWORK_ABORTED = 0x0061 - ,QMI_ERR_MSG_BLOCKED = 0x0062 - ,QMI_ERR_INVALID_SESSION_TYPE = 0x0064 - ,QMI_ERR_INVALID_PB_TYPE = 0x0065 - ,QMI_ERR_NO_SIM = 0x0066 - ,QMI_ERR_PB_NOT_READY = 0x0067 - ,QMI_ERR_PIN_RESTRICTION = 0x0068 - ,QMI_ERR_PIN2_RESTRICTION = 0x0069 - ,QMI_ERR_PUK_RESTRICTION = 0x006A - ,QMI_ERR_PUK2_RESTRICTION = 0x006B - ,QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C - ,QMI_ERR_PB_DELETE_IN_PROG = 0x006D - ,QMI_ERR_PB_TEXT_TOO_LONG = 0x006E - ,QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F - ,QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070 -} QMI_ERROR_CODE_TYPE; - -#define QCQMI_CTL_FLAG_SERVICE 0x80 -#define QCQMI_CTL_FLAG_CTL_POINT 0x00 - -typedef struct _QCQMI_HDR -{ - UCHAR IFType; - USHORT Length; - UCHAR CtlFlags; // reserved - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QCQMI_HDR, *PQCQMI_HDR; - -#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR)-1) - -typedef struct _QCQMI -{ - UCHAR IFType; - USHORT Length; - UCHAR CtlFlags; // reserved - UCHAR QMIType; - UCHAR ClientId; - UCHAR SDU; -} __attribute__ ((packed)) QCQMI, *PQCQMI; - -typedef struct _QMI_SERVICE_VERSION -{ - USHORT Major; - USHORT Minor; - USHORT AddendumMajor; - USHORT AddendumMinor; -} __attribute__ ((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION; - -// ================= QMUX ================== - -#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header - -#define QMUX_BROADCAST_CID 0xFF - -typedef struct _QCQMUX_HDR -{ - UCHAR CtlFlags; // 0: single QMUX Msg; 1: - USHORT TransactionId; -} __attribute__ ((packed)) QCQMUX_HDR, *PQCQMUX_HDR; - -typedef struct _QCQMUX -{ - UCHAR CtlFlags; // 0: single QMUX Msg; 1: - USHORT TransactionId; - UCHAR Message; // Type(2), Length(2), Value -} __attribute__ ((packed)) QCQMUX, *PQCQMUX; - -#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR) - -typedef struct _QCQMUX_MSG_HDR -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR; - -#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR) - -typedef struct _QCQMUX_MSG_HDR_RESP -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__ ((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP; - -typedef struct _QCQMUX_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR Value; -} __attribute__ ((packed)) QCQMUX_TLV, *PQCQMUX_TLV; - -typedef struct _QMI_TLV_HDR -{ - UCHAR TLVType; - USHORT TLVLength; -} __attribute__ ((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR; - -typedef struct _QMI_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - union { - int8_t s8; - uint8_t u8; - int16_t s16; - uint16_t u16; - int32_t s32; - uint32_t u32; - uint64_t u64; - }; -} __attribute__ ((packed)) QMI_TLV, *PQMI_TLV; - -// QMUX Message Definitions -- QMI SDU -#define QMUX_CTL_FLAG_SINGLE_MSG 0x00 -#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01 -#define QMUX_CTL_FLAG_TYPE_CMD 0x00 -#define QMUX_CTL_FLAG_TYPE_RSP 0x02 -#define QMUX_CTL_FLAG_TYPE_IND 0x04 -#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01 -#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind - -#pragma pack(pop) - -#endif // USBQMI_H diff --git a/quectel_cm_5G/src/MPQMUX.c b/quectel_cm_5G/src/MPQMUX.c deleted file mode 100644 index 7c8dfb3..0000000 --- a/quectel_cm_5G/src/MPQMUX.c +++ /dev/null @@ -1,477 +0,0 @@ -/****************************************************************************** - @file MPQMUX.c - @brief QMI mux. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - -#include "QMIThread.h" -static char line[1024]; -static pthread_mutex_t dumpQMIMutex = PTHREAD_MUTEX_INITIALIZER; -#undef dbg -#define dbg( format, arg... ) do {if (strlen(line) < sizeof(line)) snprintf(&line[strlen(line)], sizeof(line) - strlen(line), format, ## arg);} while (0) - -PQMI_TLV_HDR GetTLV (PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType); - -typedef struct { - UINT type; - const char *name; -} QMI_NAME_T; - -#define qmi_name_item(type) {type, #type} - -#if 0 -static const QMI_NAME_T qmi_IFType[] = { -{USB_CTL_MSG_TYPE_QMI, "USB_CTL_MSG_TYPE_QMI"}, -}; - -static const QMI_NAME_T qmi_CtlFlags[] = { -qmi_name_item(QMICTL_CTL_FLAG_CMD), -qmi_name_item(QCQMI_CTL_FLAG_SERVICE), -}; - -static const QMI_NAME_T qmi_QMIType[] = { -qmi_name_item(QMUX_TYPE_CTL), -qmi_name_item(QMUX_TYPE_WDS), -qmi_name_item(QMUX_TYPE_DMS), -qmi_name_item(QMUX_TYPE_NAS), -qmi_name_item(QMUX_TYPE_QOS), -qmi_name_item(QMUX_TYPE_WMS), -qmi_name_item(QMUX_TYPE_PDS), -qmi_name_item(QMUX_TYPE_WDS_ADMIN), -qmi_name_item(QMUX_TYPE_COEX), -}; - -static const QMI_NAME_T qmi_ctl_CtlFlags[] = { -qmi_name_item(QMICTL_FLAG_REQUEST), -qmi_name_item(QMICTL_FLAG_RESPONSE), -qmi_name_item(QMICTL_FLAG_INDICATION), -}; -#endif - -static const QMI_NAME_T qmux_ctl_QMICTLType[] = { -// QMICTL Type -qmi_name_item(QMICTL_SET_INSTANCE_ID_REQ), // 0x0020 -qmi_name_item(QMICTL_SET_INSTANCE_ID_RESP), // 0x0020 -qmi_name_item(QMICTL_GET_VERSION_REQ), // 0x0021 -qmi_name_item(QMICTL_GET_VERSION_RESP), // 0x0021 -qmi_name_item(QMICTL_GET_CLIENT_ID_REQ), // 0x0022 -qmi_name_item(QMICTL_GET_CLIENT_ID_RESP), // 0x0022 -qmi_name_item(QMICTL_RELEASE_CLIENT_ID_REQ), // 0x0023 -qmi_name_item(QMICTL_RELEASE_CLIENT_ID_RESP), // 0x0023 -qmi_name_item(QMICTL_REVOKE_CLIENT_ID_IND), // 0x0024 -qmi_name_item(QMICTL_INVALID_CLIENT_ID_IND), // 0x0025 -qmi_name_item(QMICTL_SET_DATA_FORMAT_REQ), // 0x0026 -qmi_name_item(QMICTL_SET_DATA_FORMAT_RESP), // 0x0026 -qmi_name_item(QMICTL_SYNC_REQ), // 0x0027 -qmi_name_item(QMICTL_SYNC_RESP), // 0x0027 -qmi_name_item(QMICTL_SYNC_IND), // 0x0027 -}; - -static const QMI_NAME_T qmux_CtlFlags[] = { -qmi_name_item(QMUX_CTL_FLAG_TYPE_CMD), -qmi_name_item(QMUX_CTL_FLAG_TYPE_RSP), -qmi_name_item(QMUX_CTL_FLAG_TYPE_IND), -}; - - -static const QMI_NAME_T qmux_wds_Type[] = { -qmi_name_item(QMIWDS_SET_EVENT_REPORT_REQ), // 0x0001 -qmi_name_item(QMIWDS_SET_EVENT_REPORT_RESP), // 0x0001 -qmi_name_item(QMIWDS_EVENT_REPORT_IND), // 0x0001 -qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_REQ), // 0x0020 -qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_RESP), // 0x0020 -qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_REQ), // 0x0021 -qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_RESP), // 0x0021 -qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_REQ), // 0x0022 -qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_RESP), // 0x0022 -qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_IND), // 0x0022 -qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ), // 0x0023 -qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP), // 0x0023 -qmi_name_item(QMIWDS_GET_PKT_STATISTICS_REQ), // 0x0024 -qmi_name_item(QMIWDS_GET_PKT_STATISTICS_RESP), // 0x0024 -qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ), // 0x0028 -qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_RESP), // 0x0028 -qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_REQ), // 0x002B -qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_RESP), // 0x002BD -qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_REQ), // 0x002C -qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_RESP), // 0x002C -qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_REQ), // 0x002D -qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_RESP), // 0x002D -qmi_name_item(QMIWDS_GET_MIP_MODE_REQ), // 0x002F -qmi_name_item(QMIWDS_GET_MIP_MODE_RESP), // 0x002F -qmi_name_item(QMIWDS_GET_DATA_BEARER_REQ), // 0x0037 -qmi_name_item(QMIWDS_GET_DATA_BEARER_RESP), // 0x0037 -qmi_name_item(QMIWDS_DUN_CALL_INFO_REQ), // 0x0038 -qmi_name_item(QMIWDS_DUN_CALL_INFO_RESP), // 0x0038 -qmi_name_item(QMIWDS_DUN_CALL_INFO_IND), // 0x0038 -qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ), // 0x004D -qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP), // 0x004D -qmi_name_item(QMIWDS_SET_AUTO_CONNECT_REQ), // 0x0051 -qmi_name_item(QMIWDS_SET_AUTO_CONNECT_RESP), // 0x0051 -qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_REQ), // 0x00A2 -qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_RESP), // 0x00A2 -}; - -static const QMI_NAME_T qmux_dms_Type[] = { -// ======================= DMS ============================== -qmi_name_item(QMIDMS_SET_EVENT_REPORT_REQ), // 0x0001 -qmi_name_item(QMIDMS_SET_EVENT_REPORT_RESP), // 0x0001 -qmi_name_item(QMIDMS_EVENT_REPORT_IND), // 0x0001 -qmi_name_item(QMIDMS_GET_DEVICE_CAP_REQ), // 0x0020 -qmi_name_item(QMIDMS_GET_DEVICE_CAP_RESP), // 0x0020 -qmi_name_item(QMIDMS_GET_DEVICE_MFR_REQ), // 0x0021 -qmi_name_item(QMIDMS_GET_DEVICE_MFR_RESP), // 0x0021 -qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_REQ), // 0x0022 -qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_RESP), // 0x0022 -qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_REQ), // 0x0023 -qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_RESP), // 0x0023 -qmi_name_item(QMIDMS_GET_MSISDN_REQ), // 0x0024 -qmi_name_item(QMIDMS_GET_MSISDN_RESP), // 0x0024 -qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ), // 0x0025 -qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP), // 0x0025 -qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_REQ), // 0x0027 -qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_RESP), // 0x0027 -qmi_name_item(QMIDMS_UIM_VERIFY_PIN_REQ), // 0x0028 -qmi_name_item(QMIDMS_UIM_VERIFY_PIN_RESP), // 0x0028 -qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_REQ), // 0x0029 -qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_RESP), // 0x0029 -qmi_name_item(QMIDMS_UIM_CHANGE_PIN_REQ), // 0x002A -qmi_name_item(QMIDMS_UIM_CHANGE_PIN_RESP), // 0x002A -qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_REQ), // 0x002B -qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_RESP), // 0x002B -qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_REQ), // 0x002C -qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_RESP), // 0x002C -qmi_name_item(QMIDMS_GET_OPERATING_MODE_REQ), // 0x002D -qmi_name_item(QMIDMS_GET_OPERATING_MODE_RESP), // 0x002D -qmi_name_item(QMIDMS_SET_OPERATING_MODE_REQ), // 0x002E -qmi_name_item(QMIDMS_SET_OPERATING_MODE_RESP), // 0x002E -qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_REQ), // 0x0031 -qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_RESP), // 0x0031 -qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_REQ), // 0x0032 -qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_RESP), // 0x0032 -qmi_name_item(QMIDMS_ACTIVATE_MANUAL_REQ), // 0x0033 -qmi_name_item(QMIDMS_ACTIVATE_MANUAL_RESP), // 0x0033 -qmi_name_item(QMIDMS_UIM_GET_ICCID_REQ), // 0x003C -qmi_name_item(QMIDMS_UIM_GET_ICCID_RESP), // 0x003C -qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_REQ), // 0x0040 -qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_RESP), // 0x0040 -qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_REQ), // 0x0041 -qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_RESP), // 0x0041 -qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_REQ), // 0x0042 -qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_RESP), // 0x0042 -qmi_name_item(QMIDMS_UIM_GET_IMSI_REQ), // 0x0043 -qmi_name_item(QMIDMS_UIM_GET_IMSI_RESP), // 0x0043 -qmi_name_item(QMIDMS_UIM_GET_STATE_REQ), // 0x0044 -qmi_name_item(QMIDMS_UIM_GET_STATE_RESP), // 0x0044 -qmi_name_item(QMIDMS_GET_BAND_CAP_REQ), // 0x0045 -qmi_name_item(QMIDMS_GET_BAND_CAP_RESP), // 0x0045 -}; - -static const QMI_NAME_T qmux_qos_Type[] = { -qmi_name_item( QMI_QOS_SET_EVENT_REPORT_REQ), // 0x0001 -qmi_name_item( QMI_QOS_SET_EVENT_REPORT_RESP), // 0x0001 -qmi_name_item( QMI_QOS_SET_EVENT_REPORT_IND), // 0x0001 -qmi_name_item( QMI_QOS_BIND_DATA_PORT_REQ), // 0x002B -qmi_name_item( QMI_QOS_BIND_DATA_PORT_RESP), // 0x002B -qmi_name_item( QMI_QOS_INDICATION_REGISTER_REQ), // 0x002F -qmi_name_item( QMI_QOS_INDICATION_REGISTER_RESP), // 0x002F -qmi_name_item( QMI_QOS_GLOBAL_QOS_FLOW_IND), // 0x0031 -qmi_name_item( QMI_QOS_GET_QOS_INFO_REQ), // 0x0033 -qmi_name_item( QMI_QOS_GET_QOS_INFO_RESP), // 0x0033 -}; - -static const QMI_NAME_T qmux_nas_Type[] = { -// ======================= NAS ============================== -qmi_name_item(QMINAS_SET_EVENT_REPORT_REQ), // 0x0002 -qmi_name_item(QMINAS_SET_EVENT_REPORT_RESP), // 0x0002 -qmi_name_item(QMINAS_EVENT_REPORT_IND), // 0x0002 -qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_REQ), // 0x0020 -qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_RESP), // 0x0020 -qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_REQ), // 0x0021 -qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_RESP), // 0x0021 -qmi_name_item(QMINAS_INITIATE_NW_REGISTER_REQ), // 0x0022 -qmi_name_item(QMINAS_INITIATE_NW_REGISTER_RESP), // 0x0022 -qmi_name_item(QMINAS_INITIATE_ATTACH_REQ), // 0x0023 -qmi_name_item(QMINAS_INITIATE_ATTACH_RESP), // 0x0023 -qmi_name_item(QMINAS_GET_SERVING_SYSTEM_REQ), // 0x0024 -qmi_name_item(QMINAS_GET_SERVING_SYSTEM_RESP), // 0x0024 -qmi_name_item(QMINAS_SERVING_SYSTEM_IND), // 0x0024 -qmi_name_item(QMINAS_GET_HOME_NETWORK_REQ), // 0x0025 -qmi_name_item(QMINAS_GET_HOME_NETWORK_RESP), // 0x0025 -qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_REQ), // 0x0026 -qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_RESP), // 0x0026 -qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_REQ), // 0x0027 -qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_RESP), // 0x0027 -qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_REQ), // 0x0028 -qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_RESP), // 0x0028 -qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_REQ), // 0x0029 -qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_RESP), // 0x0029 -qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_REQ), // 0x002A -qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_RESP), // 0x002A -qmi_name_item(QMINAS_GET_RF_BAND_INFO_REQ), // 0x0031 -qmi_name_item(QMINAS_GET_RF_BAND_INFO_RESP), // 0x0031 -qmi_name_item(QMINAS_GET_CELL_LOCATION_INFO_REQ), -qmi_name_item(QMINAS_GET_CELL_LOCATION_INFO_RESP), -qmi_name_item(QMINAS_GET_PLMN_NAME_REQ), // 0x0044 -qmi_name_item(QMINAS_GET_PLMN_NAME_RESP), // 0x0044 -qmi_name_item(QUECTEL_PACKET_TRANSFER_START_IND), // 0X100 -qmi_name_item(QUECTEL_PACKET_TRANSFER_END_IND), // 0X101 -qmi_name_item(QMINAS_GET_SYS_INFO_REQ), // 0x004D -qmi_name_item(QMINAS_GET_SYS_INFO_RESP), // 0x004D -qmi_name_item(QMINAS_SYS_INFO_IND), // 0x004D -qmi_name_item(QMINAS_GET_SIG_INFO_REQ), -qmi_name_item(QMINAS_GET_SIG_INFO_RESP), - -}; - -static const QMI_NAME_T qmux_wms_Type[] = { -// ======================= WMS ============================== -qmi_name_item(QMIWMS_SET_EVENT_REPORT_REQ), // 0x0001 -qmi_name_item(QMIWMS_SET_EVENT_REPORT_RESP), // 0x0001 -qmi_name_item(QMIWMS_EVENT_REPORT_IND), // 0x0001 -qmi_name_item(QMIWMS_RAW_SEND_REQ), // 0x0020 -qmi_name_item(QMIWMS_RAW_SEND_RESP), // 0x0020 -qmi_name_item(QMIWMS_RAW_WRITE_REQ), // 0x0021 -qmi_name_item(QMIWMS_RAW_WRITE_RESP), // 0x0021 -qmi_name_item(QMIWMS_RAW_READ_REQ), // 0x0022 -qmi_name_item(QMIWMS_RAW_READ_RESP), // 0x0022 -qmi_name_item(QMIWMS_MODIFY_TAG_REQ), // 0x0023 -qmi_name_item(QMIWMS_MODIFY_TAG_RESP), // 0x0023 -qmi_name_item(QMIWMS_DELETE_REQ), // 0x0024 -qmi_name_item(QMIWMS_DELETE_RESP), // 0x0024 -qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_REQ), // 0x0030 -qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_RESP), // 0x0030 -qmi_name_item(QMIWMS_LIST_MESSAGES_REQ), // 0x0031 -qmi_name_item(QMIWMS_LIST_MESSAGES_RESP), // 0x0031 -qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_REQ), // 0x0034 -qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_RESP), // 0x0034 -qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_REQ), // 0x0035 -qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_RESP), // 0x0035 -qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_REQ), // 0x0036 -qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_RESP), // 0x0036 -}; - -static const QMI_NAME_T qmux_wds_admin_Type[] = { -qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ), // 0x0020 -qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_RESP), // 0x0020 -qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_REQ), // 0x0021 -qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_RESP), // 0x0021 -qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ), // 0x002B -qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP), // 0x002B -qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ), // 0x002C -qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP), // 0x002C -qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_REQ), // 0x002F -qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_RESP), // 0x002F -qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_IND), // 0x002F -}; - -static const QMI_NAME_T qmux_uim_Type[] = { -qmi_name_item( QMIUIM_READ_TRANSPARENT_REQ), // 0x0020 -qmi_name_item( QMIUIM_READ_TRANSPARENT_RESP), // 0x0020 -qmi_name_item( QMIUIM_READ_TRANSPARENT_IND), // 0x0020 -qmi_name_item( QMIUIM_READ_RECORD_REQ), // 0x0021 -qmi_name_item( QMIUIM_READ_RECORD_RESP), // 0x0021 -qmi_name_item( QMIUIM_READ_RECORD_IND), // 0x0021 -qmi_name_item( QMIUIM_WRITE_TRANSPARENT_REQ), // 0x0022 -qmi_name_item( QMIUIM_WRITE_TRANSPARENT_RESP), // 0x0022 -qmi_name_item( QMIUIM_WRITE_TRANSPARENT_IND), // 0x0022 -qmi_name_item( QMIUIM_WRITE_RECORD_REQ), // 0x0023 -qmi_name_item( QMIUIM_WRITE_RECORD_RESP), // 0x0023 -qmi_name_item( QMIUIM_WRITE_RECORD_IND), // 0x0023 -qmi_name_item( QMIUIM_SET_PIN_PROTECTION_REQ), // 0x0025 -qmi_name_item( QMIUIM_SET_PIN_PROTECTION_RESP), // 0x0025 -qmi_name_item( QMIUIM_SET_PIN_PROTECTION_IND), // 0x0025 -qmi_name_item( QMIUIM_VERIFY_PIN_REQ), // 0x0026 -qmi_name_item( QMIUIM_VERIFY_PIN_RESP), // 0x0026 -qmi_name_item( QMIUIM_VERIFY_PIN_IND), // 0x0026 -qmi_name_item( QMIUIM_UNBLOCK_PIN_REQ), // 0x0027 -qmi_name_item( QMIUIM_UNBLOCK_PIN_RESP), // 0x0027 -qmi_name_item( QMIUIM_UNBLOCK_PIN_IND), // 0x0027 -qmi_name_item( QMIUIM_CHANGE_PIN_REQ), // 0x0028 -qmi_name_item( QMIUIM_CHANGE_PIN_RESP), // 0x0028 -qmi_name_item( QMIUIM_CHANGE_PIN_IND), // 0x0028 -qmi_name_item( QMIUIM_DEPERSONALIZATION_REQ), // 0x0029 -qmi_name_item( QMIUIM_DEPERSONALIZATION_RESP), // 0x0029 -qmi_name_item( QMIUIM_EVENT_REG_REQ), // 0x002E -qmi_name_item( QMIUIM_EVENT_REG_RESP), // 0x002E -qmi_name_item( QMIUIM_GET_CARD_STATUS_REQ), // 0x002F -qmi_name_item( QMIUIM_GET_CARD_STATUS_RESP), // 0x002F -qmi_name_item( QMIUIM_STATUS_CHANGE_IND), // 0x0032 -}; - -static const QMI_NAME_T qmux_coex_Type[] = { -qmi_name_item(QMI_COEX_GET_WWAN_STATE_REQ), // 0x0022 -qmi_name_item(QMI_COEX_GET_WWAN_STATE_RESP), // 0x0022 -}; - -static const char * qmi_name_get(const QMI_NAME_T *table, size_t size, int type, const char *tag) { - static char unknow[40]; - size_t i; - - if (qmux_CtlFlags == table) { - if (!strcmp(tag, "_REQ")) - tag = "_CMD"; - else if (!strcmp(tag, "_RESP")) - tag = "_RSP"; - } - - for (i = 0; i < size; i++) { - if (table[i].type == (UINT)type) { - if (!tag || (strstr(table[i].name, tag))) - return table[i].name; - } - } - sprintf(unknow, "unknow_%x", type); - return unknow; -} - -#define QMI_NAME(table, type) qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, 0) -#define QMUX_NAME(table, type, tag) qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, tag) - -void dump_tlv(PQCQMUX_MSG_HDR pQMUXMsgHdr) { - int TLVFind = 0; - int i; - //dbg("QCQMUX_TLV-----------------------------------\n"); - //dbg("{Type,\tLength,\tValue}\n"); - - while (1) { - PQMI_TLV_HDR TLVHdr = GetTLV(pQMUXMsgHdr, 0x1000 + (++TLVFind)); - if (TLVHdr == NULL) - break; - - //if ((TLVHdr->TLVType == 0x02) && ((USHORT *)(TLVHdr+1))[0]) - { - dbg("{%02x,\t%04x,\t", TLVHdr->TLVType, le16_to_cpu(TLVHdr->TLVLength)); - for (i = 0; i < le16_to_cpu(TLVHdr->TLVLength); i++) { - dbg("%02x ", ((UCHAR *)(TLVHdr+1))[i]); - } - dbg("}\n"); - } - } // while -} - -void dump_ctl(PQCQMICTL_MSG_HDR CTLHdr) { - const char *tag; - - //dbg("QCQMICTL_MSG--------------------------------------------\n"); - //dbg("CtlFlags: %02x\t\t%s\n", CTLHdr->CtlFlags, QMI_NAME(qmi_ctl_CtlFlags, CTLHdr->CtlFlags)); - dbg("TransactionId: %02x\n", CTLHdr->TransactionId); - switch (CTLHdr->CtlFlags) { - case QMICTL_FLAG_REQUEST: tag = "_REQ"; break; - case QMICTL_FLAG_RESPONSE: tag = "_RESP"; break; - case QMICTL_FLAG_INDICATION: tag = "_IND"; break; - default: tag = 0; break; - } - dbg("QMICTLType: %04x\t%s\n", le16_to_cpu(CTLHdr->QMICTLType), - QMUX_NAME(qmux_ctl_QMICTLType, le16_to_cpu(CTLHdr->QMICTLType), tag)); - dbg("Length: %04x\n", le16_to_cpu(CTLHdr->Length)); - - dump_tlv((PQCQMUX_MSG_HDR)(&CTLHdr->QMICTLType)); -} - -int dump_qmux(QMI_SERVICE_TYPE serviceType, PQCQMUX_HDR QMUXHdr) { - PQCQMUX_MSG_HDR QMUXMsgHdr = (PQCQMUX_MSG_HDR) (QMUXHdr + 1); - const char *tag; - - //dbg("QCQMUX--------------------------------------------\n"); - switch (QMUXHdr->CtlFlags&QMUX_CTL_FLAG_MASK_TYPE) { - case QMUX_CTL_FLAG_TYPE_CMD: tag = "_REQ"; break; - case QMUX_CTL_FLAG_TYPE_RSP: tag = "_RESP"; break; - case QMUX_CTL_FLAG_TYPE_IND: tag = "_IND"; break; - default: tag = 0; break; - } - //dbg("CtlFlags: %02x\t\t%s\n", QMUXHdr->CtlFlags, QMUX_NAME(qmux_CtlFlags, QMUXHdr->CtlFlags, tag)); - dbg("TransactionId: %04x\n", le16_to_cpu(QMUXHdr->TransactionId)); - - //dbg("QCQMUX_MSG_HDR-----------------------------------\n"); - switch (serviceType) { - case QMUX_TYPE_DMS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_dms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_NAS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_nas_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_WDS: - case QMUX_TYPE_WDS_IPV6: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_wds_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_WMS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_wms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_WDS_ADMIN: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_wds_admin_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_UIM: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_uim_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_PDS: - case QMUX_TYPE_QOS: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_qos_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_COEX: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), - QMUX_NAME(qmux_coex_Type, le16_to_cpu(QMUXMsgHdr->Type), tag)); - break; - case QMUX_TYPE_CTL: - default: - dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), "PDS/QOS/CTL/unknown!"); - break; - } - dbg("Length: %04x\n", le16_to_cpu(QMUXMsgHdr->Length)); - - dump_tlv(QMUXMsgHdr); - - return 0; -} - -void dump_qmi(void *dataBuffer, int dataLen) -{ - PQCQMI_HDR QMIHdr = (PQCQMI_HDR)dataBuffer; - PQCQMUX_HDR QMUXHdr = (PQCQMUX_HDR) (QMIHdr + 1); - PQCQMICTL_MSG_HDR CTLHdr = (PQCQMICTL_MSG_HDR) (QMIHdr + 1); - - int i; - - if (!debug_qmi) - return; - - pthread_mutex_lock(&dumpQMIMutex); - line[0] = 0; - for (i = 0; i < dataLen; i++) { - dbg("%02x ", ((unsigned char *)dataBuffer)[i]); - } - dbg_time("%s", line); - line[0] = 0; - - //dbg("QCQMI_HDR-----------------------------------------"); - //dbg("IFType: %02x\t\t%s", QMIHdr->IFType, QMI_NAME(qmi_IFType, QMIHdr->IFType)); - //dbg("Length: %04x", le16_to_cpu(QMIHdr->Length)); - //dbg("CtlFlags: %02x\t\t%s", QMIHdr->CtlFlags, QMI_NAME(qmi_CtlFlags, QMIHdr->CtlFlags)); - //dbg("QMIType: %02x\t\t%s", QMIHdr->QMIType, QMI_NAME(qmi_QMIType, QMIHdr->QMIType)); - //dbg("ClientId: %02x", QMIHdr->ClientId); - - if (QMIHdr->QMIType == QMUX_TYPE_CTL) { - dump_ctl(CTLHdr); - } else { - dump_qmux(QMIHdr->QMIType, QMUXHdr); - } - dbg_time("%s", line); - pthread_mutex_unlock(&dumpQMIMutex); -} diff --git a/quectel_cm_5G/src/MPQMUX.h b/quectel_cm_5G/src/MPQMUX.h deleted file mode 100644 index b7d7bc3..0000000 --- a/quectel_cm_5G/src/MPQMUX.h +++ /dev/null @@ -1,4273 +0,0 @@ -/*=========================================================================== - - M P Q M U X. H -DESCRIPTION: - - This file provides support for QMUX. - -INITIALIZATION AND SEQUENCING REQUIREMENTS: - -Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. -===========================================================================*/ - -#ifndef MPQMUX_H -#define MPQMUX_H - -#include "MPQMI.h" - -#pragma pack(push, 1) - -#define QMIWDS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIWDS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIWDS_EVENT_REPORT_IND 0x0001 -#define QMIWDS_START_NETWORK_INTERFACE_REQ 0x0020 -#define QMIWDS_START_NETWORK_INTERFACE_RESP 0x0020 -#define QMIWDS_STOP_NETWORK_INTERFACE_REQ 0x0021 -#define QMIWDS_STOP_NETWORK_INTERFACE_RESP 0x0021 -#define QMIWDS_GET_PKT_SRVC_STATUS_REQ 0x0022 -#define QMIWDS_GET_PKT_SRVC_STATUS_RESP 0x0022 -#define QMIWDS_GET_PKT_SRVC_STATUS_IND 0x0022 -#define QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ 0x0023 -#define QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP 0x0023 -#define QMIWDS_GET_PKT_STATISTICS_REQ 0x0024 -#define QMIWDS_GET_PKT_STATISTICS_RESP 0x0024 -#define QMIWDS_CREATE_PROFILE_REQ 0x0027 -#define QMIWDS_CREATE_PROFILE_RESP 0x0027 -#define QMIWDS_MODIFY_PROFILE_SETTINGS_REQ 0x0028 -#define QMIWDS_MODIFY_PROFILE_SETTINGS_RESP 0x0028 -#define QMIWDS_GET_PROFILE_SETTINGS_REQ 0x002B -#define QMIWDS_GET_PROFILE_SETTINGS_RESP 0x002B -#define QMIWDS_GET_DEFAULT_SETTINGS_REQ 0x002C -#define QMIWDS_GET_DEFAULT_SETTINGS_RESP 0x002C -#define QMIWDS_GET_RUNTIME_SETTINGS_REQ 0x002D -#define QMIWDS_GET_RUNTIME_SETTINGS_RESP 0x002D -#define QMIWDS_GET_MIP_MODE_REQ 0x002F -#define QMIWDS_GET_MIP_MODE_RESP 0x002F -#define QMIWDS_GET_DATA_BEARER_REQ 0x0037 -#define QMIWDS_GET_DATA_BEARER_RESP 0x0037 -#define QMIWDS_DUN_CALL_INFO_REQ 0x0038 -#define QMIWDS_DUN_CALL_INFO_RESP 0x0038 -#define QMIWDS_DUN_CALL_INFO_IND 0x0038 -#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ 0x004D -#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP 0x004D -#define QMIWDS_SET_AUTO_CONNECT_REQ 0x0051 -#define QMIWDS_SET_AUTO_CONNECT_RESP 0x0051 -#define QMIWDS_BIND_MUX_DATA_PORT_REQ 0x00A2 -#define QMIWDS_BIND_MUX_DATA_PORT_RESP 0x00A2 - - -// Stats masks -#define QWDS_STAT_MASK_TX_PKT_OK 0x00000001 -#define QWDS_STAT_MASK_RX_PKT_OK 0x00000002 -#define QWDS_STAT_MASK_TX_PKT_ER 0x00000004 -#define QWDS_STAT_MASK_RX_PKT_ER 0x00000008 -#define QWDS_STAT_MASK_TX_PKT_OF 0x00000010 -#define QWDS_STAT_MASK_RX_PKT_OF 0x00000020 - -// TLV Types for xfer statistics -#define TLV_WDS_TX_GOOD_PKTS 0x10 -#define TLV_WDS_RX_GOOD_PKTS 0x11 -#define TLV_WDS_TX_ERROR 0x12 -#define TLV_WDS_RX_ERROR 0x13 -#define TLV_WDS_TX_OVERFLOW 0x14 -#define TLV_WDS_RX_OVERFLOW 0x15 -#define TLV_WDS_CHANNEL_RATE 0x16 -#define TLV_WDS_DATA_BEARER 0x17 -#define TLV_WDS_DORMANCY_STATUS 0x18 - -#define QWDS_PKT_DATA_UNKNOW 0x00 -#define QWDS_PKT_DATA_DISCONNECTED 0x01 -#define QWDS_PKT_DATA_CONNECTED 0x02 -#define QWDS_PKT_DATA_SUSPENDED 0x03 -#define QWDS_PKT_DATA_AUTHENTICATING 0x04 - -#define QMIWDS_ADMIN_SET_DATA_FORMAT_REQ 0x0020 -#define QMIWDS_ADMIN_SET_DATA_FORMAT_RESP 0x0020 -#define QMIWDS_ADMIN_GET_DATA_FORMAT_REQ 0x0021 -#define QMIWDS_ADMIN_GET_DATA_FORMAT_RESP 0x0021 -#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ 0x002B -#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP 0x002B -#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ 0x002C -#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP 0x002C -#define QMI_WDA_SET_LOOPBACK_CONFIG_REQ 0x002F -#define QMI_WDA_SET_LOOPBACK_CONFIG_RESP 0x002F -#define QMI_WDA_SET_LOOPBACK_CONFIG_IND 0x002F - -#define NETWORK_DESC_ENCODING_OCTET 0x00 -#define NETWORK_DESC_ENCODING_EXTPROTOCOL 0x01 -#define NETWORK_DESC_ENCODING_7BITASCII 0x02 -#define NETWORK_DESC_ENCODING_IA5 0x03 -#define NETWORK_DESC_ENCODING_UNICODE 0x04 -#define NETWORK_DESC_ENCODING_SHIFTJIS 0x05 -#define NETWORK_DESC_ENCODING_KOREAN 0x06 -#define NETWORK_DESC_ENCODING_LATINH 0x07 -#define NETWORK_DESC_ENCODING_LATIN 0x08 -#define NETWORK_DESC_ENCODING_GSM7BIT 0x09 -#define NETWORK_DESC_ENCODING_GSMDATA 0x0A -#define NETWORK_DESC_ENCODING_UNKNOWN 0xFF - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT -{ - USHORT Type; // QMUX type 0x0000 - USHORT Length; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT, *PQMIWDS_ADMIN_SET_DATA_FORMAT; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR QOSSetting; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG Value; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV; - -typedef struct _QMIWDS_ENDPOINT_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; -} __attribute__ ((packed)) QMIWDS_ENDPOINT_TLV, *PQMIWDS_ENDPOINT_TLV; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv; - QMIWDS_ENDPOINT_TLV epTlv; -#ifdef QUECTEL_UL_DATA_AGG - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DlMinimumPassingTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxSizeTlv; -#endif -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG, *PQMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG; - -typedef struct _QMI_U8_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TLVVaule; -} __attribute__ ((packed)) QMI_U8_TLV, *PQMI_U8_TLV; - -typedef struct _QMI_U32_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG TLVVaule; -} __attribute__ ((packed)) QMI_U32_TLV, *PQMI_U32_TLV; - -typedef struct _QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG { - USHORT Type; - USHORT Length; - QMI_U8_TLV loopback_state; //0x01 - QMI_U32_TLV replication_factor; //0x10 -} __attribute__ ((packed)) QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG, *PQMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG; - -typedef struct _QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG -{ - USHORT Type; - USHORT Length; - QMI_U8_TLV loopback_state; //0x01 - QMI_U32_TLV replication_factor; //0x10 -} __attribute__ ((packed)) QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG, *PQMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG; - -#if 0 -typedef enum _QMI_RETURN_CODES { - QMI_SUCCESS = 0, - QMI_SUCCESS_NOT_COMPLETE, - QMI_FAILURE -}QMI_RETURN_CODES; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG -{ - USHORT Type; // 0x0022 - USHORT Length; // 0x0000 -} QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLVType2; - USHORT TLVLength2; - UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED - // 0x02: QWDS_PKT_DATA_CONNECTED - // 0x03: QWDS_PKT_DATA_SUSPENDED - // 0x04: QWDS_PKT_DATA_AUTHENTICATING -} QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED - // 0x02: QWDS_PKT_DATA_CONNECTED - // 0x03: QWDS_PKT_DATA_SUSPENDED - UCHAR ReconfigRequired; // 0x00: No need to reconfigure - // 0x01: Reconfiguration required -} QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_IND_MSG; - -typedef struct _WDS_PKT_SRVC_IP_FAMILY_TLV -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 1 - UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 -} WDS_PKT_SRVC_IP_FAMILY_TLV, *PWDS_PKT_SRVC_IP_FAMILY_TLV; - -typedef struct _QMIWDS_DUN_CALL_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG Mask; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR ReportConnectionStatus; -} QMIWDS_DUN_CALL_INFO_REQ_MSG, *PQMIWDS_DUN_CALL_INFO_REQ_MSG; - -typedef struct _QMIWDS_DUN_CALL_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWDS_DUN_CALL_INFO_RESP_MSG, *PQMIWDS_DUN_CALL_INFO_RESP_MSG; - -typedef struct _QMIWDS_DUN_CALL_INFO_IND_MSG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; -} QMIWDS_DUN_CALL_INFO_IND_MSG, *PQMIWDS_DUN_CALL_INFO_IND_MSG; - -typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; -} QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG; - -typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 16 - //ULONG CallHandle; // Context corresponding to reported channel - ULONG CurrentTxRate; // bps - ULONG CurrentRxRate; // bps - ULONG ServingSystemTxRate; // bps - ULONG ServingSystemRxRate; // bps - -} QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_RESP; - -#define QWDS_EVENT_REPORT_MASK_RATES 0x01 -#define QWDS_EVENT_REPORT_MASK_STATS 0x02 - -#ifdef QCUSB_MUX_PROTOCOL -#error code not present -#endif // QCUSB_MUX_PROTOCOL - -typedef struct _QMIWDS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0042 - USHORT Length; - - UCHAR TLVType; // 0x10 -- current channel rate indicator - USHORT TLVLength; // 1 - UCHAR Mode; // 0-do not report; 1-report when rate changes - - UCHAR TLV2Type; // 0x11 - USHORT TLV2Length; // 5 - UCHAR StatsPeriod; // seconds between reports; 0-do not report - ULONG StatsMask; // - - UCHAR TLV3Type; // 0x12 -- current data bearer indicator - USHORT TLV3Length; // 1 - UCHAR Mode3; // 0-do not report; 1-report when changes - - UCHAR TLV4Type; // 0x13 -- dormancy status indicator - USHORT TLV4Length; // 1 - UCHAR DormancyStatus; // 0-do not report; 1-report when changes -} QMIWDS_SET_EVENT_REPORT_REQ_MSG, *PQMIWDS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIWDS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0042 - USHORT Length; - - UCHAR TLVType; // 0x02 result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_NO_BATTERY - // QMI_ERR_FAULT -} QMIWDS_SET_EVENT_REPORT_RESP_MSG, *PQMIWDS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMIWDS_EVENT_REPORT_IND_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; -} QMIWDS_EVENT_REPORT_IND_MSG, *PQMIWDS_EVENT_REPORT_IND_MSG; - -// PQCTLV_PKT_STATISTICS - -typedef struct _QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV -{ - UCHAR Type; - USHORT Length; // 8 - ULONG TxRate; - ULONG RxRate; -} QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV, *PQMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV; - -#ifdef QCUSB_MUX_PROTOCOL -#error code not present -#endif // QCUSB_MUX_PROTOCOL - -typedef struct _QMIWDS_GET_PKT_STATISTICS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0041 - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 4 - ULONG StateMask; // 0x00000001 tx success packets - // 0x00000002 rx success packets - // 0x00000004 rx packet errors (checksum) - // 0x00000008 rx packets dropped (memory) - -} QMIWDS_GET_PKT_STATISTICS_REQ_MSG, *PQMIWDS_GET_PKT_STATISTICS_REQ_MSG; - -typedef struct _QMIWDS_GET_PKT_STATISTICS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0041 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIWDS_GET_PKT_STATISTICS_RESP_MSG, *PQMIWDS_GET_PKT_STATISTICS_RESP_MSG; - -// optional TLV for stats -typedef struct _QCTLV_PKT_STATISTICS -{ - UCHAR TLVType; // see above definitions for TLV types - USHORT TLVLength; // 4 - ULONG Count; -} QCTLV_PKT_STATISTICS, *PQCTLV_PKT_STATISTICS; -#endif - -//#ifdef QC_IP_MODE - -/* - ?Bit 0 ?Profile identifier - ?Bit 1 ?Profile name - ?Bit 2 ?PDP type - ?Bit 3 ?APN name - ?Bit 4 ?DNS address - ?Bit 5 ?UMTS/GPRS granted QoS - ?Bit 6 ?Username - ?Bit 7 ?Authentication Protocol - ?Bit 8 ?IP address - ?Bit 9 ?Gateway information (address and subnet mask) - ?Bit 10 ?PCSCF address using a PCO flag - ?Bit 11 ?PCSCF server address list - ?Bit 12 ?PCSCF domain name list - ?Bit 13 ?MTU - ?Bit 14 ?Domain name list - ?Bit 15 ?IP family - ?Bit 16 ?IM_CM flag - ?Bit 17 ?Technology name - ?Bit 18 ?Operator reserved PCO -*/ -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR (1 << 4) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR (1 << 8) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR (1 << 9) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU (1 << 13) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_SV_ADDR (1 << 11) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_DOM_NAME (1 << 14) - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG -{ - USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_REQ - USHORT Length; - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 0x0004 - ULONG Mask; // mask, bit 8: IP addr -- 0x0100 -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG, *PQMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR MuxId; - UCHAR TLV3Type; - USHORT TLV3Length; - ULONG client_type; -} __attribute__ ((packed)) QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG, *PQMIWDS_BIND_MUX_DATA_PORT_REQ_MSG; - -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS 0x15 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS 0x16 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 0x1E -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY 0x20 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET 0x21 - -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 0x25 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY 0x26 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS 0x27 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS 0x28 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU 0x29 - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU -{ - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU - USHORT TLVLength; // 4 - ULONG Mtu; // MTU -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR -{ - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 - USHORT TLVLength; // 4 - ULONG IPV4Address; // address -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR -{ - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 - USHORT TLVLength; // 16 - UCHAR IPV6Address[16]; // address - UCHAR PrefixLength; // prefix length -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR; - -typedef struct _QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PCSCFNumber; -} __attribute__ ((packed)) QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR, *PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR; - -typedef struct _QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PCSCFNumber; -} __attribute__ ((packed)) QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR, *PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG -{ - USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMUXResult; // result code - USHORT QMUXError; // error code -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG, *PQMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG; - -//#endif // QC_IP_MODE - -typedef struct _QMIWDS_IP_FAMILY_TLV -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 1 - UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 -} __attribute__ ((packed)) QMIWDS_IP_FAMILY_TLV, *PQMIWDS_IP_FAMILY_TLV; - -typedef struct _QMIWDS_PKT_SRVC_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; - UCHAR ReconfigReqd; -} __attribute__ ((packed)) QMIWDS_PKT_SRVC_TLV, *PQMIWDS_PKT_SRVC_TLV; - -typedef struct _QMIWDS_CALL_END_REASON_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CallEndReason; -} __attribute__ ((packed)) QMIWDS_CALL_END_REASON_TLV, *PQMIWDS_CALL_END_REASON_TLV; - -typedef struct _QMIWDS_CALL_END_REASON_V_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CallEndReasonType; - USHORT CallEndReason; -} __attribute__ ((packed)) QMIWDS_CALL_END_REASON_V_TLV, *PQMIWDS_CALL_END_REASON_V_TLV; - -typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG -{ - USHORT Type; // QMUX type 0x004D - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR IpPreference; // IPV4-0x04, IPV6-0x06 -} __attribute__ ((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG, *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG; - -typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS, QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INTERNAL, QMI_ERR_MALFORMED_MSG, QMI_ERR_INVALID_ARG -} __attribute__ ((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG, *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG; - -typedef struct _QMIWDS_SET_AUTO_CONNECT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0051 - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR autoconnect_setting; // 0x00 ?C Disabled, 0x01 ?C Enabled, 0x02 ?C Paused (resume on power cycle) -} __attribute__ ((packed)) QMIWDS_SET_AUTO_CONNECT_REQ_MSG, *PQMIWDS_SET_AUTO_CONNECT_REQ_MSG; - -#if 0 -typedef struct _QMIWDS_GET_MIP_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; -} QMIWDS_GET_MIP_MODE_REQ_MSG, *PQMIWDS_GET_MIP_MODE_REQ_MSG; - -typedef struct _QMIWDS_GET_MIP_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 20 - UCHAR MipMode; // -} QMIWDS_GET_MIP_MODE_RESP_MSG, *PQMIWDS_GET_MIP_MODE_RESP_MSG; -#endif - -typedef struct _QMIWDS_TECHNOLOGY_PREFERECE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TechPreference; -} __attribute__ ((packed)) QMIWDS_TECHNOLOGY_PREFERECE, *PQMIWDS_TECHNOLOGY_PREFERECE; - -typedef struct _QMIWDS_PROFILE_IDENTIFIER -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileIndex; -} __attribute__ ((packed)) QMIWDS_PROFILE_IDENTIFIER, *PQMIWDS_PROFILE_IDENTIFIER; - -#if 0 -typedef struct _QMIWDS_IPADDRESS -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG IPv4Address; -}QMIWDS_IPADDRESS, *PQMIWDS_IPADDRESS; - -/* -typedef struct _QMIWDS_UMTS_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TrafficClass; - ULONG MaxUplinkBitRate; - ULONG MaxDownlinkBitRate; - ULONG GuarUplinkBitRate; - ULONG GuarDownlinkBitRate; - UCHAR QOSDevOrder; - ULONG MAXSDUSize; - UCHAR SDUErrorRatio; - UCHAR ResidualBerRatio; - UCHAR DeliveryErrorSDUs; - ULONG TransferDelay; - ULONG TrafficHndPri; -}QMIWDS_UMTS_QOS, *PQMIWDS_UMTS_QOS; - -typedef struct _QMIWDS_GPRS_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG PrecedenceClass; - ULONG DelayClass; - ULONG ReliabilityClass; - ULONG PeekThroClass; - ULONG MeanThroClass; -}QMIWDS_GPRS_QOS, *PQMIWDS_GPRS_QOS; -*/ -#endif - -typedef struct _QMIWDS_PROFILENAME -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileName; -} __attribute__ ((packed)) QMIWDS_PROFILENAME, *PQMIWDS_PROFILENAME; - -typedef struct _QMIWDS_PDPTYPE -{ - UCHAR TLVType; - USHORT TLVLength; -// 0 ?C PDP-IP (IPv4) -// 1 ?C PDP-PPP -// 2 ?C PDP-IPv6 -// 3 ?C PDP-IPv4v6 - UCHAR PdpType; -} __attribute__ ((packed)) QMIWDS_PDPTYPE, *PQMIWDS_PDPTYPE; - -typedef struct _QMIWDS_USERNAME -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR UserName; -} __attribute__ ((packed)) QMIWDS_USERNAME, *PQMIWDS_USERNAME; - -typedef struct _QMIWDS_PASSWD -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR Passwd; -} __attribute__ ((packed)) QMIWDS_PASSWD, *PQMIWDS_PASSWD; - -typedef struct _QMIWDS_AUTH_PREFERENCE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR AuthPreference; -} __attribute__ ((packed)) QMIWDS_AUTH_PREFERENCE, *PQMIWDS_AUTH_PREFERENCE; - -typedef struct _QMIWDS_IPTYPE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR IPType; -} __attribute__ ((packed)) QMIWDS_IPTYPE, *PQMIWDS_IPTYPE; - -typedef struct _QMIWDS_APNNAME -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ApnName; -} __attribute__ ((packed)) QMIWDS_APNNAME, *PQMIWDS_APNNAME; - -typedef struct _QMIWDS_AUTOCONNECT -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR AutoConnect; -} __attribute__ ((packed)) QMIWDS_AUTOCONNECT, *PQMIWDS_AUTOCONNECT; - -typedef struct _QMIWDS_START_NETWORK_INTERFACE_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIWDS_START_NETWORK_INTERFACE_REQ_MSG, *PQMIWDS_START_NETWORK_INTERFACE_REQ_MSG; - -typedef struct _QMIWDS_CALLENDREASON -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT Reason; -}__attribute__ ((packed)) QMIWDS_CALLENDREASON, *PQMIWDS_CALLENDREASON; - -typedef struct _QMIWDS_START_NETWORK_INTERFACE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 20 - ULONG Handle; // -} __attribute__ ((packed)) QMIWDS_START_NETWORK_INTERFACE_RESP_MSG, *PQMIWDS_START_NETWORK_INTERFACE_RESP_MSG; - -typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG Handle; -} __attribute__ ((packed)) QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG, *PQMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG; - -typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - -} __attribute__ ((packed)) QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG, *PQMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG; - -typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; -} __attribute__ ((packed)) QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG, *PQMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG, *PQMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG; - -typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR ProfileIndex; -} __attribute__ ((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG, *PQMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG; - -typedef struct _QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR ProfileIndex; -} __attribute__ ((packed)) QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_GET_PROFILE_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR TLV2Type; //0x25 - USHORT TLV2Length; - UCHAR pdp_context; -} __attribute__ ((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG; - -#if 0 -typedef struct _QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR DataBearer; -} QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV, *PQMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV; - -typedef struct _QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR DormancyStatus; -} QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV, *PQMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV; - - -typedef struct _QMIWDS_GET_DATA_BEARER_REQ_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; -} QMIWDS_GET_DATA_BEARER_REQ_MSG, *PQMIWDS_GET_DATA_BEARER_REQ_MSG; - -typedef struct _QMIWDS_GET_DATA_BEARER_RESP_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INTERNAL - // QMI_ERR_MALFORMED_MSG - // QMI_ERR_NO_MEMORY - // QMI_ERR_OUT_OF_CALL - // QMI_ERR_INFO_UNAVAILABLE - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // - UCHAR Technology; // -} QMIWDS_GET_DATA_BEARER_RESP_MSG, *PQMIWDS_GET_DATA_BEARER_RESP_MSG; -#endif - -// ======================= DMS ============================== -#define QMIDMS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIDMS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIDMS_EVENT_REPORT_IND 0x0001 -#define QMIDMS_GET_DEVICE_CAP_REQ 0x0020 -#define QMIDMS_GET_DEVICE_CAP_RESP 0x0020 -#define QMIDMS_GET_DEVICE_MFR_REQ 0x0021 -#define QMIDMS_GET_DEVICE_MFR_RESP 0x0021 -#define QMIDMS_GET_DEVICE_MODEL_ID_REQ 0x0022 -#define QMIDMS_GET_DEVICE_MODEL_ID_RESP 0x0022 -#define QMIDMS_GET_DEVICE_REV_ID_REQ 0x0023 -#define QMIDMS_GET_DEVICE_REV_ID_RESP 0x0023 -#define QMIDMS_GET_MSISDN_REQ 0x0024 -#define QMIDMS_GET_MSISDN_RESP 0x0024 -#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ 0x0025 -#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP 0x0025 -#define QMIDMS_UIM_SET_PIN_PROTECTION_REQ 0x0027 -#define QMIDMS_UIM_SET_PIN_PROTECTION_RESP 0x0027 -#define QMIDMS_UIM_VERIFY_PIN_REQ 0x0028 -#define QMIDMS_UIM_VERIFY_PIN_RESP 0x0028 -#define QMIDMS_UIM_UNBLOCK_PIN_REQ 0x0029 -#define QMIDMS_UIM_UNBLOCK_PIN_RESP 0x0029 -#define QMIDMS_UIM_CHANGE_PIN_REQ 0x002A -#define QMIDMS_UIM_CHANGE_PIN_RESP 0x002A -#define QMIDMS_UIM_GET_PIN_STATUS_REQ 0x002B -#define QMIDMS_UIM_GET_PIN_STATUS_RESP 0x002B -#define QMIDMS_GET_DEVICE_HARDWARE_REV_REQ 0x002C -#define QMIDMS_GET_DEVICE_HARDWARE_REV_RESP 0x002C -#define QMIDMS_GET_OPERATING_MODE_REQ 0x002D -#define QMIDMS_GET_OPERATING_MODE_RESP 0x002D -#define QMIDMS_SET_OPERATING_MODE_REQ 0x002E -#define QMIDMS_SET_OPERATING_MODE_RESP 0x002E -#define QMIDMS_GET_ACTIVATED_STATUS_REQ 0x0031 -#define QMIDMS_GET_ACTIVATED_STATUS_RESP 0x0031 -#define QMIDMS_ACTIVATE_AUTOMATIC_REQ 0x0032 -#define QMIDMS_ACTIVATE_AUTOMATIC_RESP 0x0032 -#define QMIDMS_ACTIVATE_MANUAL_REQ 0x0033 -#define QMIDMS_ACTIVATE_MANUAL_RESP 0x0033 -#define QMIDMS_UIM_GET_ICCID_REQ 0x003C -#define QMIDMS_UIM_GET_ICCID_RESP 0x003C -#define QMIDMS_UIM_GET_CK_STATUS_REQ 0x0040 -#define QMIDMS_UIM_GET_CK_STATUS_RESP 0x0040 -#define QMIDMS_UIM_SET_CK_PROTECTION_REQ 0x0041 -#define QMIDMS_UIM_SET_CK_PROTECTION_RESP 0x0041 -#define QMIDMS_UIM_UNBLOCK_CK_REQ 0x0042 -#define QMIDMS_UIM_UNBLOCK_CK_RESP 0x0042 -#define QMIDMS_UIM_GET_IMSI_REQ 0x0043 -#define QMIDMS_UIM_GET_IMSI_RESP 0x0043 -#define QMIDMS_UIM_GET_STATE_REQ 0x0044 -#define QMIDMS_UIM_GET_STATE_RESP 0x0044 -#define QMIDMS_GET_BAND_CAP_REQ 0x0045 -#define QMIDMS_GET_BAND_CAP_RESP 0x0045 - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_MFR_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMIDMS_GET_DEVICE_MFR_REQ_MSG, *PQMIDMS_GET_DEVICE_MFR_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MFR_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - UCHAR DeviceManufacturer; // first byte of string -} QMIDMS_GET_DEVICE_MFR_RESP_MSG, *PQMIDMS_GET_DEVICE_MFR_RESP_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0004 - USHORT Length; -} QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0004 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the modem id string - UCHAR DeviceModelID; // device model id -} QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG; -#endif - -typedef struct _QMIDMS_GET_DEVICE_REV_ID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0005 - USHORT Length; -} __attribute__ ((packed)) QMIDMS_GET_DEVICE_REV_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_REV_ID_REQ_MSG; - -typedef struct _DEVICE_REV_ID -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR RevisionID; -} __attribute__ ((packed)) DEVICE_REV_ID, *PDEVICE_REV_ID; - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_REV_ID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0023 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIDMS_GET_DEVICE_REV_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_REV_ID_RESP_MSG; - -typedef struct _QMIDMS_GET_MSISDN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} QMIDMS_GET_MSISDN_REQ_MSG, *PQMIDMS_GET_MSISDN_REQ_MSG; - -typedef struct _QCTLV_DEVICE_VOICE_NUMBERS -{ - UCHAR TLVType; // as defined above - USHORT TLVLength; // 4/7/7 - UCHAR VoideNumberString; // ESN, IMEI, or MEID - -} QCTLV_DEVICE_VOICE_NUMBERS, *PQCTLV_DEVICE_VOICE_NUMBERS; - - -typedef struct _QMIDMS_GET_MSISDN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG -} QMIDMS_GET_MSISDN_RESP_MSG, *PQMIDMS_GET_MSISDN_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_GET_IMSI_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIDMS_UIM_GET_IMSI_REQ_MSG, *PQMIDMS_UIM_GET_IMSI_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_IMSI_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR IMSI; -} __attribute__ ((packed)) QMIDMS_UIM_GET_IMSI_RESP_MSG, *PQMIDMS_UIM_GET_IMSI_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0007 - USHORT Length; -} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG; - -#define QCTLV_TYPE_SER_NUM_ESN 0x10 -#define QCTLV_TYPE_SER_NUM_IMEI 0x11 -#define QCTLV_TYPE_SER_NUM_MEID 0x12 - -typedef struct _QCTLV_DEVICE_SERIAL_NUMBER -{ - UCHAR TLVType; // as defined above - USHORT TLVLength; // 4/7/7 - UCHAR SerialNumberString; // ESN, IMEI, or MEID - -} QCTLV_DEVICE_SERIAL_NUMBER, *PQCTLV_DEVICE_SERIAL_NUMBER; - -typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0007 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - // followed by optional TLV -} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP; - -typedef struct _QMIDMS_GET_DMS_BAND_CAP -{ - USHORT Type; - USHORT Length; -} QMIDMS_GET_BAND_CAP_REQ_MSG, *PQMIDMS_GET_BAND_CAP_REQ_MSG; - -typedef struct _QMIDMS_GET_BAND_CAP_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_NONE - // QMI_ERR_INTERNAL - // QMI_ERR_MALFORMED_MSG - // QMI_ERR_NO_MEMORY - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - ULONG64 BandCap; -} QMIDMS_GET_BAND_CAP_RESP_MSG, *PQMIDMS_GET_BAND_CAP_RESP; - -typedef struct _QMIDMS_GET_DEVICE_CAP_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_DEVICE_CAP_REQ_MSG, *PQMIDMS_GET_DEVICE_CAP_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_CAP_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - ULONG MaxTxChannelRate; - ULONG MaxRxChannelRate; - UCHAR VoiceCap; - UCHAR SimCap; - - UCHAR RadioIfListCnt; // #elements in radio interface list - UCHAR RadioIfList; // N 1-byte elements -} QMIDMS_GET_DEVICE_CAP_RESP_MSG, *PQMIDMS_GET_DEVICE_CAP_RESP_MSG; - -typedef struct _QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG, *PQMIDMS_GET_ACTIVATES_STATUD_REQ_MSG; - -typedef struct _QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - USHORT ActivatedStatus; -} QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG, *PQMIDMS_GET_ACTIVATED_STATUS_RESP_MSG; - -typedef struct _QMIDMS_GET_OPERATING_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_OPERATING_MODE_REQ_MSG, *PQMIDMS_GET_OPERATING_MODE_REQ_MSG; - -typedef struct _OFFLINE_REASON -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT OfflineReason; -} OFFLINE_REASON, *POFFLINE_REASON; - -typedef struct _HARDWARE_RESTRICTED_MODE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR HardwareControlledMode; -} HARDWARE_RESTRICTED_MODE, *PHARDWARE_RESTRICTED_MODE; - -typedef struct _QMIDMS_GET_OPERATING_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - UCHAR OperatingMode; -} QMIDMS_GET_OPERATING_MODE_RESP_MSG, *PQMIDMS_GET_OPERATING_MODE_RESP_MSG; - -typedef struct _QMIDMS_UIM_GET_ICCID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} QMIDMS_UIM_GET_ICCID_REQ_MSG, *PQMIDMS_UIM_GET_ICCID_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_ICCID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // var - UCHAR ICCID; // String of voice number -} QMIDMS_UIM_GET_ICCID_RESP_MSG, *PQMIDMS_UIM_GET_ICCID_RESP_MSG; -#endif - -typedef struct _QMIDMS_SET_OPERATING_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR OperatingMode; -} __attribute__ ((packed)) QMIDMS_SET_OPERATING_MODE_REQ_MSG, *PQMIDMS_SET_OPERATING_MODE_REQ_MSG; - -typedef struct _QMIDMS_SET_OPERATING_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT -} __attribute__ ((packed)) QMIDMS_SET_OPERATING_MODE_RESP_MSG, *PQMIDMS_SET_OPERATING_MODE_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR ActivateCodelen; - UCHAR ActivateCode; -} QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG; - -typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG; - - -typedef struct _SPC_MSG -{ - UCHAR SPC[6]; - USHORT SID; -} SPC_MSG, *PSPC_MSG; - -typedef struct _MDN_MSG -{ - UCHAR MDNLEN; - UCHAR MDN; -} MDN_MSG, *PMDN_MSG; - -typedef struct _MIN_MSG -{ - UCHAR MINLEN; - UCHAR MIN; -} MIN_MSG, *PMIN_MSG; - -typedef struct _PRL_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - USHORT PRLLEN; - UCHAR PRL; -} PRL_MSG, *PPRL_MSG; - -typedef struct _MN_HA_KEY_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR MN_HA_KEY_LEN; - UCHAR MN_HA_KEY; -} MN_HA_KEY_MSG, *PMN_HA_KEY_MSG; - -typedef struct _MN_AAA_KEY_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR MN_AAA_KEY_LEN; - UCHAR MN_AAA_KEY; -} MN_AAA_KEY_MSG, *PMN_AAA_KEY_MSG; - -typedef struct _QMIDMS_ACTIVATE_MANUAL_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR Value; -} QMIDMS_ACTIVATE_MANUAL_REQ_MSG, *PQMIDMS_ACTIVATE_MANUAL_REQ_MSG; - -typedef struct _QMIDMS_ACTIVATE_MANUAL_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMIDMS_ACTIVATE_MANUAL_RESP_MSG, *PQMIDMS_ACTIVATE_MANUAL_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_GET_STATE_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIDMS_UIM_GET_STATE_REQ_MSG, *PQMIDMS_UIM_GET_STATE_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_STATE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR UIMState; -} __attribute__ ((packed)) QMIDMS_UIM_GET_STATE_RESP_MSG, *PQMIDMS_UIM_GET_STATE_RESP_MSG; - -typedef struct _QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} __attribute__ ((packed)) QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_PIN_STATUS_REQ_MSG; - -typedef struct _QMIDMS_UIM_PIN_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PINStatus; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__ ((packed)) QMIDMS_UIM_PIN_STATUS, *PQMIDMS_UIM_PIN_STATUS; - -#define QMI_PIN_STATUS_NOT_INIT 0 -#define QMI_PIN_STATUS_NOT_VERIF 1 -#define QMI_PIN_STATUS_VERIFIED 2 -#define QMI_PIN_STATUS_DISABLED 3 -#define QMI_PIN_STATUS_BLOCKED 4 -#define QMI_PIN_STATUS_PERM_BLOCKED 5 -#define QMI_PIN_STATUS_UNBLOCKED 6 -#define QMI_PIN_STATUS_CHANGED 7 - - -typedef struct _QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR PinStatus; -} __attribute__ ((packed)) QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_PIN_STATUS_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_UIM_GET_CK_STATUS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; -} QMIDMS_UIM_GET_CK_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_CK_STATUS_REQ_MSG; - - -typedef struct _QMIDMS_UIM_CK_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR FacilityStatus; - UCHAR FacilityVerifyRetriesLeft; - UCHAR FacilityUnblockRetriesLeft; -} QMIDMS_UIM_CK_STATUS, *PQMIDMS_UIM_CK_STATUS; - -typedef struct _QMIDMS_UIM_CK_OPERATION_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR OperationBlocking; -} QMIDMS_UIM_CK_OPERATION_STATUS, *PQMIDMS_UIM_CK_OPERATION_STATUS; - -typedef struct _QMIDMS_UIM_GET_CK_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR CkStatus; -} QMIDMS_UIM_GET_CK_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_CK_STATUS_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_VERIFY_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PINLen; - UCHAR PINValue; -} __attribute__ ((packed)) QMIDMS_UIM_VERIFY_PIN_REQ_MSG, *PQMIDMS_UIM_VERIFY_PIN_REQ_MSG; - -typedef struct _QMIDMS_UIM_VERIFY_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__ ((packed)) QMIDMS_UIM_VERIFY_PIN_RESP_MSG, *PQMIDMS_UIM_VERIFY_PIN_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR ProtectionSetting; - UCHAR PINLen; - UCHAR PINValue; -} QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG; - -typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG; - -typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; - UCHAR FacilityState; - UCHAR FacliltyLen; - UCHAR FacliltyValue; -} QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG; - -typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR FacilityRetriesLeft; -} QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG; - - -typedef struct _UIM_PIN -{ - UCHAR PinLength; - UCHAR PinValue; -} UIM_PIN, *PUIM_PIN; - -typedef struct _QMIDMS_UIM_CHANGE_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PinDetails; -} QMIDMS_UIM_CHANGE_PIN_REQ_MSG, *PQMIDMS_UIM_CHANGE_PIN_REQ_MSG; - -typedef struct QMIDMS_UIM_CHANGE_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_CHANGE_PIN_RESP_MSG, *PQMIDMS_UIM_CHANGE_PIN_RESP_MSG; - -typedef struct _UIM_PUK -{ - UCHAR PukLength; - UCHAR PukValue; -} UIM_PUK, *PUIM_PUK; - -typedef struct _QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PinDetails; -} QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG, *PQMIDMS_UIM_BLOCK_PIN_REQ_MSG; - -typedef struct QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_PIN_RESP_MSG; - -typedef struct _QMIDMS_UIM_UNBLOCK_CK_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; - UCHAR FacliltyUnblockLen; - UCHAR FacliltyUnblockValue; -} QMIDMS_UIM_UNBLOCK_CK_REQ_MSG, *PQMIDMS_UIM_BLOCK_CK_REQ_MSG; - -typedef struct QMIDMS_UIM_UNBLOCK_CK_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR FacilityUnblockRetriesLeft; -} QMIDMS_UIM_UNBLOCK_CK_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_CK_RESP_MSG; - -typedef struct _QMIDMS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMIDMS_SET_EVENT_REPORT_REQ_MSG, *PQMIDMS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIDMS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG -} QMIDMS_SET_EVENT_REPORT_RESP_MSG, *PQMIDMS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _PIN_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportPinState; -} PIN_STATUS, *PPIN_STATUS; - -typedef struct _POWER_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PowerStatus; - UCHAR BatteryLvl; -} POWER_STATUS, *PPOWER_STATUS; - -typedef struct _ACTIVATION_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT ActivationState; -} ACTIVATION_STATE, *PACTIVATION_STATE; - -typedef struct _ACTIVATION_STATE_REQ -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ActivationState; -} ACTIVATION_STATE_REQ, *PACTIVATION_STATE_REQ; - -typedef struct _OPERATING_MODE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR OperatingMode; -} OPERATING_MODE, *POPERATING_MODE; - -typedef struct _UIM_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR UIMState; -} UIM_STATE, *PUIM_STATE; - -typedef struct _WIRELESS_DISABLE_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR WirelessDisableState; -} WIRELESS_DISABLE_STATE, *PWIRELESS_DISABLE_STATE; - -typedef struct _QMIDMS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMIDMS_EVENT_REPORT_IND_MSG, *PQMIDMS_EVENT_REPORT_IND_MSG; -#endif - -// ============================ END OF DMS =============================== - -// ======================= QOS ============================== -typedef struct _MPIOC_DEV_INFO MPIOC_DEV_INFO, *PMPIOC_DEV_INFO; - -#define QMI_QOS_SET_EVENT_REPORT_REQ 0x0001 -#define QMI_QOS_SET_EVENT_REPORT_RESP 0x0001 -#define QMI_QOS_SET_EVENT_REPORT_IND 0x0001 -#define QMI_QOS_BIND_DATA_PORT_REQ 0x002B -#define QMI_QOS_BIND_DATA_PORT_RESP 0x002B -#define QMI_QOS_INDICATION_REGISTER_REQ 0x002F -#define QMI_QOS_INDICATION_REGISTER_RESP 0x002F -#define QMI_QOS_GLOBAL_QOS_FLOW_IND 0x0031 -#define QMI_QOS_GET_QOS_INFO_REQ 0x0033 -#define QMI_QOS_GET_QOS_INFO_RESP 0x0033 - - -#if 1 -typedef struct _QMI_QOS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; - // UCHAR TLVType; // 0x01 - physical link state - // USHORT TLVLength; // 1 - // UCHAR PhyLinkStatusRpt; // 0-enable; 1-disable - UCHAR TLVType2; // 0x02 = global flow reporting - USHORT TLVLength2; // 1 - UCHAR GlobalFlowRpt; // 1-enable; 0-disable -} QMI_QOS_SET_EVENT_REPORT_REQ_MSG, *PQMI_QOS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMI_QOS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0010 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT -} QMI_QOS_SET_EVENT_REPORT_RESP_MSG, *PQMI_QOS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMI_QOS_SET_EVENT_REPORT_IND_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; - UCHAR TLVs; -} QMI_QOS_SET_EVENT_REPORT_IND_MSG, *PQMI_QOS_SET_EVENT_REPORT_IND_MSG; - - -typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_EP_ID -{ - UCHAR TLVType; //0x10 - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_EP_ID, *PQMI_QOS_BIND_DATA_PORT_TLV_EP_ID; - -typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID -{ - UCHAR TLVType; //0x11 - USHORT TLVLength; - UCHAR mux_id; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID, *PQMI_QOS_BIND_DATA_PORT_TLV_MUX_ID; - -typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT -{ - UCHAR TLVType; //0x12 - USHORT TLVLength; - USHORT data_port; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT, *PQMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT; - -typedef struct _QMI_QOS_BIND_DATA_PORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_BIND_DATA_PORT_TLV_EP_ID EpIdTlv; - QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID MuxIdTlv; - //QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT DataPortTlv; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_REQ_MSG, *PQMI_QOS_BIND_DATA_PORT_REQ_MSG; - -typedef struct _QMI_QOS_BIND_DATA_PORT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; //0x02 - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_RESP_MSG, *PQMI_QOS_BIND_DATA_PORT_RESP_MSG; - -typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW -{ - UCHAR TLVType; //0x10 - USHORT TLVLength; - UCHAR report_global_qos_flows; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW, *PQMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW; - -typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL -{ - UCHAR TLVType; //0x11 - USHORT TLVLength; - UCHAR suppress_report_flow_control; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL, *PQMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL; - -typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND -{ - UCHAR TLVType; //0x12 - USHORT TLVLength; - UCHAR suppress_network_status_ind; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND, *PQMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND; - -typedef struct _QMI_QOS_INDICATION_REGISTER_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW ReportGlobalQosFlowTlv; - //QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL SuppressReportFlowCtlTlv; - //QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND SuppressNWStatusIndTlv; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_REQ_MSG, *PQMI_QOS_INDICATION_REGISTER_REQ_MSG; - -typedef struct _QMI_QOS_INDICATION_REGISTER_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; //0x02 - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_RESP_MSG, *PQMI_QOS_INDICATION_REGISTER_RESP_MSG; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE -{ - UCHAR TLVType; //0x01 - USHORT TLVLength; - ULONG qos_id; - UCHAR new_flow; - ULONG state_change; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED -{ - UCHAR TLVType; //0x10 0x11 - USHORT TLVLength; - ULONG64 flow_valid_params; - ULONG ip_flow_trf_cls; - ULONG64 data_rate_max; - ULONG64 guaranteed_rate; - ULONG peak_rate; - ULONG token_rate; - ULONG bucket_size; - ULONG ip_flow_latency; - ULONG ip_flow_jitter; - USHORT ip_flow_pkt_error_rate_multiplier; - USHORT ip_flow_pkt_error_rate_exponent; - ULONG ip_flow_min_policed_packet_size; - ULONG ip_flow_max_allowed_packet_size; - ULONG ip_flow_3gpp_residual_bit_error_rate; - ULONG ip_flow_3gpp_traffic_handling_priority; - USHORT ip_flow_3gpp2_profile_id; - UCHAR ip_flow_3gpp2_flow_priority; - UCHAR ip_flow_3gpp_im_cn_flag; - UCHAR ip_flow_3gpp_sig_ind; - ULONG ip_flow_lte_qci; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER -{ - UCHAR TLVType; //0x12 0x13 - USHORT TLVLength; - UCHAR tx_rx_qos_filter_len; - UCHAR ip_version; - ULONG64 valid_params0; - ULONG ipv4_addr0; - ULONG subnet_mask0; - ULONG ipv4_addr1; - ULONG subnet_mask1; - UCHAR val4; - UCHAR mask4; - ULONG64 valid_params01; - UCHAR ipv6_address00; - UCHAR ipv6_address01; - UCHAR ipv6_address02; - UCHAR ipv6_address03; - UCHAR ipv6_address04; - UCHAR ipv6_address05; - UCHAR ipv6_address06; - UCHAR ipv6_address07; - UCHAR ipv6_address08; - UCHAR ipv6_address09; - UCHAR ipv6_address010; - UCHAR ipv6_address011; - UCHAR ipv6_address012; - UCHAR ipv6_address013; - UCHAR ipv6_address014; - ULONG ipv6_address015; - UCHAR prefix_len0; - UCHAR ipv6_address10; - UCHAR ipv6_address11; - UCHAR ipv6_address12; - UCHAR ipv6_address13; - UCHAR ipv6_address14; - UCHAR ipv6_address15; - UCHAR ipv6_address16; - UCHAR ipv6_address17; - UCHAR ipv6_address18; - UCHAR ipv6_address19; - UCHAR ipv6_address110; - UCHAR ipv6_address111; - UCHAR ipv6_address112; - UCHAR ipv6_address113; - UCHAR ipv6_address114; - ULONG ipv6_address115; - UCHAR prefix_len1; - UCHAR val6; - UCHAR mask6; - ULONG flow_label; - ULONG xport_protocol; - ULONG64 valid_params2; - USHORT port0; - USHORT range0; - USHORT port1; - USHORT range1; - ULONG64 valid_params3; - USHORT port2; - USHORT range2; - USHORT port3; - USHORT range3; - ULONG64 valid_params4; - UCHAR type; - UCHAR code; - ULONG64 valid_params5; - ULONG spi0; - ULONG64 valid_params6; - ULONG spi1; - USHORT filter_id; - USHORT filter_precedence; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE -{ - UCHAR TLVType; //0x14 - USHORT TLVLength; - ULONG flow_type; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID -{ - UCHAR TLVType; //0x15 - USHORT TLVLength; - UCHAR bearer_id; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM -{ - UCHAR TLVType; //0x16 - USHORT TLVLength; - USHORT fc_seq_num; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI -{ - UCHAR TLVType; //0x17 0x18 - USHORT TLVLength; - ULONG tx_rx_5g_qci; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW -{ - UCHAR TLVType; //0x19 0x1A - USHORT TLVLength; - USHORT tx_rx_avg_window; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL -{ - UCHAR TLVType; //0x1B - USHORT TLVLength; - UCHAR tx_filter_match_all_len; - USHORT filter_id; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE FlowStateTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED TxFlowGrantedTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED RxFlowGrantedTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER TxFilterTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER RxFilterTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE FlowTypeTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID BearerIdTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM FlowCtlSeqNumTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI Tx5GQciTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI Rx5GQciTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW AvgWindowTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL TxFilterMatchAllTlv; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG, *PQMI_QOS_GLOBAL_QOS_FLOW_IND_MSG; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_QOS_ID -{ - UCHAR TLVType; //0x01 - USHORT TLVLength; - ULONG qos_id; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_QOS_ID, *PQMI_QOS_GET_QOS_INFO_TLV_QOS_ID; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS -{ - UCHAR TLVType; //0x10 - USHORT TLVLength; - UCHAR flow_status; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS, *PQMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW -{ - UCHAR TLVType; //0x11 0x12 - USHORT TLVLength; - ULONG64 flow_valid_params; - ULONG ip_flow_trf_cls; - ULONG64 data_rate_max; - ULONG64 guaranteed_rate; - ULONG peak_rate; - ULONG token_rate; - ULONG bucket_size; - ULONG ip_flow_latency; - ULONG ip_flow_jitter; - USHORT ip_flow_pkt_error_rate_multiplier; - USHORT ip_flow_pkt_error_rate_exponent; - ULONG ip_flow_min_policed_packet_size; - ULONG ip_flow_max_allowed_packet_size; - ULONG ip_flow_3gpp_residual_bit_error_rate; - ULONG ip_flow_3gpp_traffic_handling_priority; - USHORT ip_flow_3gpp2_profile_id; - UCHAR ip_flow_3gpp2_flow_priority; - UCHAR ip_flow_3gpp_im_cn_flag; - UCHAR ip_flow_3gpp_sig_ind; - ULONG ip_flow_lte_qci; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW, *PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS -{ - UCHAR TLVType; //0x13 0x14 - USHORT TLVLength; - UCHAR tx_rx_qos_filter_len; - UCHAR ip_version; - ULONG64 valid_params0; - ULONG ipv4_addr0; - ULONG subnet_mask0; - ULONG ipv4_addr1; - ULONG subnet_mask1; - UCHAR val4; - UCHAR mask4; - ULONG64 valid_params01; - UCHAR ipv6_address00; - UCHAR ipv6_address01; - UCHAR ipv6_address02; - UCHAR ipv6_address03; - UCHAR ipv6_address04; - UCHAR ipv6_address05; - UCHAR ipv6_address06; - UCHAR ipv6_address07; - UCHAR ipv6_address08; - UCHAR ipv6_address09; - UCHAR ipv6_address010; - UCHAR ipv6_address011; - UCHAR ipv6_address012; - UCHAR ipv6_address013; - UCHAR ipv6_address014; - ULONG ipv6_address015; - UCHAR prefix_len0; - UCHAR ipv6_address10; - UCHAR ipv6_address11; - UCHAR ipv6_address12; - UCHAR ipv6_address13; - UCHAR ipv6_address14; - UCHAR ipv6_address15; - UCHAR ipv6_address16; - UCHAR ipv6_address17; - UCHAR ipv6_address18; - UCHAR ipv6_address19; - UCHAR ipv6_address110; - UCHAR ipv6_address111; - UCHAR ipv6_address112; - UCHAR ipv6_address113; - UCHAR ipv6_address114; - ULONG ipv6_address115; - UCHAR prefix_len1; - UCHAR val6; - UCHAR mask6; - ULONG flow_label; - ULONG xport_protocol; - ULONG64 valid_params2; - USHORT port0; - USHORT range0; - USHORT port1; - USHORT range1; - ULONG64 valid_params3; - USHORT port2; - USHORT range2; - USHORT port3; - USHORT range3; - ULONG64 valid_params4; - UCHAR type; - UCHAR code; - ULONG64 valid_params5; - ULONG spi0; - ULONG64 valid_params6; - ULONG spi1; - USHORT filter_id; - USHORT filter_precedence; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS, *PQMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO -{ - UCHAR TLVType; //0x15 - USHORT TLVLength; - USHORT ext_error_info; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO, *PQMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_5G_QCI -{ - UCHAR TLVType; //0x16 0x17 - USHORT TLVLength; - ULONG tx_rx_5g_qci; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_5G_QCI, *PQMI_QOS_GET_QOS_INFO_TLV_5G_QCI; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW -{ - UCHAR TLVType; //0x18 0x19 - USHORT TLVLength; - USHORT tx_rx_averaging_window; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW, *PQMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL -{ - UCHAR TLVType; //0x1A - USHORT TLVLength; - UCHAR tx_filter_match_all_len; - USHORT filter_id; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL, *PQMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL; - -typedef struct _QMI_QOS_GET_QOS_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_GET_QOS_INFO_TLV_QOS_ID QosIdTlv; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_REQ_MSG, *PQMI_QOS_GET_QOS_INFO_REQ_MSG; - -typedef struct _QMI_QOS_GET_QOS_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; //0x02 - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - //QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS FlowStatusTlv; - //QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW TxGrantedFlowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW RxGrantedFlowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS TxFilterSpecsTlv; - //QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS RxFilterSpecsTlv; - //QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO ExtErrorInfoTlv; - //QMI_QOS_GET_QOS_INFO_TLV_5G_QCI Tx5GQciTlv; - //QMI_QOS_GET_QOS_INFO_TLV_5G_QCI Rx5GQciTlv; - //QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW TxAvgWindowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW RxAvgWindowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL TxFilterMatchAllTlv; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_RESP_MSG, *PQMI_QOS_GET_QOS_INFO_RESP_MSG; - -#define QOS_IND_FLOW_STATE_ACTIVATED 0x00 -#define QOS_IND_FLOW_STATE_MODIFIED 0x01 -#define QOS_IND_FLOW_STATE_DELETED 0x02 -#define QOS_IND_FLOW_STATE_SUSPENDED 0x03 -#define QOS_IND_FLOW_STATE_ENABLED 0x04 -#define QOS_IND_FLOW_STATE_DISABLED 0x05 -#define QOS_IND_FLOW_STATE_INVALID 0x06 - -#define QOS_EVENT_RPT_IND_FLOW_ACTIVATED 0x01 -#define QOS_EVENT_RPT_IND_FLOW_MODIFIED 0x02 -#define QOS_EVENT_RPT_IND_FLOW_DELETED 0x03 -#define QOS_EVENT_RPT_IND_FLOW_SUSPENDED 0x04 -#define QOS_EVENT_RPT_IND_FLOW_ENABLED 0x05 -#define QOS_EVENT_RPT_IND_FLOW_DISABLED 0x06 - -#define QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE_TYPE 0x01 -#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_STATE 0x10 -#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_TYPE 0x10 -#define QOS_EVENT_RPT_IND_TLV_TX_FLOW_TYPE 0x11 -#define QOS_EVENT_RPT_IND_TLV_RX_FLOW_TYPE 0x12 -#define QOS_EVENT_RPT_IND_TLV_TX_FILTER_TYPE 0x13 -#define QOS_EVENT_RPT_IND_TLV_RX_FILTER_TYPE 0x14 -#define QOS_EVENT_RPT_IND_TLV_FLOW_SPEC 0x10 -#define QOS_EVENT_RPT_IND_TLV_FILTER_SPEC 0x10 - -typedef struct _QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE -{ - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR PhyLinkState; // 0-dormant, 1-active -} QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE, *PQOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE; - -typedef struct _QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 6 - ULONG QosId; - UCHAR NewFlow; // 1: newly added flow; 0: existing flow - UCHAR StateChange; // 1: activated; 2: modified; 3: deleted; - // 4: suspended(delete); 5: enabled; 6: disabled -} QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT, *PQOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT; - -// QOS Flow - -typedef struct _QOS_EVENT_RPT_IND_TLV_FLOW -{ - UCHAR TLVType; // 0x10-TX flow; 0x11-RX flow - USHORT TLVLength; // var - // embedded TLV's -} QOS_EVENT_RPT_IND_TLV_TX_FLOW, *PQOS_EVENT_RPT_IND_TLV_TX_FLOW; - -#define QOS_FLOW_TLV_IP_FLOW_IDX_TYPE 0x10 -#define QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS_TYPE 0x11 -#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX_TYPE 0x12 -#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET_TYPE 0x13 -#define QOS_FLOW_TLV_IP_FLOW_LATENCY_TYPE 0x14 -#define QOS_FLOW_TLV_IP_FLOW_JITTER_TYPE 0x15 -#define QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE_TYPE 0x16 -#define QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE_TYPE 0x17 -#define QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE_TYPE 0x18 -#define QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE_TYPE 0x19 -#define QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY_TYPE 0x1A -#define QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID_TYPE 0x1B - -typedef struct _QOS_FLOW_TLV_IP_FLOW_IDX -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 1 - UCHAR IpFlowIndex; -} QOS_FLOW_TLV_IP_FLOW_IDX, *PQOS_FLOW_TLV_IP_FLOW_IDX; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS -{ - UCHAR TLVType; // 0x11 - USHORT TLVLength; // 1 - UCHAR TrafficClass; -} QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS, *PQOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 8 - ULONG DataRateMax; - ULONG GuaranteedRate; -} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET -{ - UCHAR TLVType; // 0x13 - USHORT TLVLength; // 12 - ULONG PeakRate; - ULONG TokenRate; - ULONG BucketSize; -} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_LATENCY -{ - UCHAR TLVType; // 0x14 - USHORT TLVLength; // 4 - ULONG IpFlowLatency; -} QOS_FLOW_TLV_IP_FLOW_LATENCY, *PQOS_FLOW_TLV_IP_FLOW_LATENCY; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_JITTER -{ - UCHAR TLVType; // 0x15 - USHORT TLVLength; // 4 - ULONG IpFlowJitter; -} QOS_FLOW_TLV_IP_FLOW_JITTER, *PQOS_FLOW_TLV_IP_FLOW_JITTER; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE -{ - UCHAR TLVType; // 0x16 - USHORT TLVLength; // 4 - USHORT ErrRateMultiplier; - USHORT ErrRateExponent; -} QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE -{ - UCHAR TLVType; // 0x17 - USHORT TLVLength; // 4 - ULONG MinPolicedPktSize; -} QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE -{ - UCHAR TLVType; // 0x18 - USHORT TLVLength; // 4 - ULONG MaxAllowedPktSize; -} QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE -{ - UCHAR TLVType; // 0x19 - USHORT TLVLength; // 1 - UCHAR ResidualBitErrorRate; -} QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY -{ - UCHAR TLVType; // 0x1A - USHORT TLVLength; // 1 - UCHAR TrafficHandlingPriority; -} QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY, *PQOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID -{ - UCHAR TLVType; // 0x1B - USHORT TLVLength; // 2 - USHORT ProfileId; -} QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID, *PQOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID; - -// QOS Filter - -#define QOS_FILTER_TLV_IP_FILTER_IDX_TYPE 0x10 -#define QOS_FILTER_TLV_IP_VERSION_TYPE 0x11 -#define QOS_FILTER_TLV_IPV4_SRC_ADDR_TYPE 0x12 -#define QOS_FILTER_TLV_IPV4_DEST_ADDR_TYPE 0x13 -#define QOS_FILTER_TLV_NEXT_HDR_PROTOCOL_TYPE 0x14 -#define QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE_TYPE 0x15 -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TCP_TYPE 0x1B -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TCP_TYPE 0x1C -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_UDP_TYPE 0x1D -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_UDP_TYPE 0x1E -#define QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE_TYPE 0x1F -#define QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE_TYPE 0x20 -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TYPE 0x24 -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TYPE 0x25 - -typedef struct _QOS_EVENT_RPT_IND_TLV_FILTER -{ - UCHAR TLVType; // 0x12-TX filter; 0x13-RX filter - USHORT TLVLength; // var - // embedded TLV's -} QOS_EVENT_RPT_IND_TLV_RX_FILTER, *PQOS_EVENT_RPT_IND_TLV_RX_FILTER; - -typedef struct _QOS_FILTER_TLV_IP_FILTER_IDX -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 1 - UCHAR IpFilterIndex; -} QOS_FILTER_TLV_IP_FILTER_IDX, *PQOS_FILTER_TLV_IP_FILTER_IDX; - -typedef struct _QOS_FILTER_TLV_IP_VERSION -{ - UCHAR TLVType; // 0x11 - USHORT TLVLength; // 1 - UCHAR IpVersion; -} QOS_FILTER_TLV_IP_VERSION, *PQOS_FILTER_TLV_IP_VERSION; - -typedef struct _QOS_FILTER_TLV_IPV4_SRC_ADDR -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 8 - ULONG IpSrcAddr; - ULONG IpSrcSubnetMask; -} QOS_FILTER_TLV_IPV4_SRC_ADDR, *PQOS_FILTER_TLV_IPV4_SRC_ADDR; - -typedef struct _QOS_FILTER_TLV_IPV4_DEST_ADDR -{ - UCHAR TLVType; // 0x13 - USHORT TLVLength; // 8 - ULONG IpDestAddr; - ULONG IpDestSubnetMask; -} QOS_FILTER_TLV_IPV4_DEST_ADDR, *PQOS_FILTER_TLV_IPV4_DEST_ADDR; - -typedef struct _QOS_FILTER_TLV_NEXT_HDR_PROTOCOL -{ - UCHAR TLVType; // 0x14 - USHORT TLVLength; // 1 - UCHAR NextHdrProtocol; -} QOS_FILTER_TLV_NEXT_HDR_PROTOCOL, *PQOS_FILTER_TLV_NEXT_HDR_PROTOCOL; - -typedef struct _QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE -{ - UCHAR TLVType; // 0x15 - USHORT TLVLength; // 2 - UCHAR Ipv4TypeOfService; - UCHAR Ipv4TypeOfServiceMask; -} QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE, *PQOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE; - -typedef struct _QOS_FILTER_TLV_TCP_UDP_PORT -{ - UCHAR TLVType; // source port: 0x1B-TCP; 0x1D-UDP - // dest port: 0x1C-TCP; 0x1E-UDP - USHORT TLVLength; // 4 - USHORT FilterPort; - USHORT FilterPortRange; -} QOS_FILTER_TLV_TCP_UDP_PORT, *PQOS_FILTER_TLV_TCP_UDP_PORT; - -typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE -{ - UCHAR TLVType; // 0x1F - USHORT TLVLength; // 1 - UCHAR IcmpFilterMsgType; -} QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE; - -typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE -{ - UCHAR TLVType; // 0x20 - USHORT TLVLength; // 1 - UCHAR IcmpFilterMsgCode; -} QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_CODE; - -#define QOS_FILTER_PRECEDENCE_INVALID 256 -#define QOS_FILTER_TLV_PRECEDENCE_TYPE 0x22 -#define QOS_FILTER_TLV_ID_TYPE 0x23 - -typedef struct _QOS_FILTER_TLV_PRECEDENCE -{ - UCHAR TLVType; // 0x22 - USHORT TLVLength; // 2 - USHORT Precedence; // precedence of the filter -} QOS_FILTER_TLV_PRECEDENCE, *PQOS_FILTER_TLV_PRECEDENCE; - -typedef struct _QOS_FILTER_TLV_ID -{ - UCHAR TLVType; // 0x23 - USHORT TLVLength; // 2 - USHORT FilterId; // filter ID -} QOS_FILTER_TLV_ID, *PQOS_FILTER_TLV_ID; - -#ifdef QCQOS_IPV6 - -#define QOS_FILTER_TLV_IPV6_SRC_ADDR_TYPE 0x16 -#define QOS_FILTER_TLV_IPV6_DEST_ADDR_TYPE 0x17 -#define QOS_FILTER_TLV_IPV6_NEXT_HDR_PROTOCOL_TYPE 0x14 // same as IPV4 -#define QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS_TYPE 0x19 -#define QOS_FILTER_TLV_IPV6_FLOW_LABEL_TYPE 0x1A - -typedef struct _QOS_FILTER_TLV_IPV6_SRC_ADDR -{ - UCHAR TLVType; // 0x16 - USHORT TLVLength; // 17 - UCHAR IpSrcAddr[16]; - UCHAR IpSrcAddrPrefixLen; // [0..128] -} QOS_FILTER_TLV_IPV6_SRC_ADDR, *PQOS_FILTER_TLV_IPV6_SRC_ADDR; - -typedef struct _QOS_FILTER_TLV_IPV6_DEST_ADDR -{ - UCHAR TLVType; // 0x17 - USHORT TLVLength; // 17 - UCHAR IpDestAddr[16]; - UCHAR IpDestAddrPrefixLen; // [0..128] -} QOS_FILTER_TLV_IPV6_DEST_ADDR, *PQOS_FILTER_TLV_IPV6_DEST_ADDR; - -#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_TCP 0x06 -#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_UDP 0x11 - -typedef struct _QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS -{ - UCHAR TLVType; // 0x19 - USHORT TLVLength; // 2 - UCHAR TrafficClass; - UCHAR TrafficClassMask; // compare the first 6 bits only -} QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS, *PQOS_FILTER_TLV_IPV6_TRAFFIC_CLASS; - -typedef struct _QOS_FILTER_TLV_IPV6_FLOW_LABEL -{ - UCHAR TLVType; // 0x1A - USHORT TLVLength; // 4 - ULONG FlowLabel; -} QOS_FILTER_TLV_IPV6_FLOW_LABEL, *PQOS_FILTER_TLV_IPV6_FLOW_LABEL; - -#endif // QCQOS_IPV6 -#endif - -// ======================= WMS ============================== -#define QMIWMS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIWMS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIWMS_EVENT_REPORT_IND 0x0001 -#define QMIWMS_RAW_SEND_REQ 0x0020 -#define QMIWMS_RAW_SEND_RESP 0x0020 -#define QMIWMS_RAW_WRITE_REQ 0x0021 -#define QMIWMS_RAW_WRITE_RESP 0x0021 -#define QMIWMS_RAW_READ_REQ 0x0022 -#define QMIWMS_RAW_READ_RESP 0x0022 -#define QMIWMS_MODIFY_TAG_REQ 0x0023 -#define QMIWMS_MODIFY_TAG_RESP 0x0023 -#define QMIWMS_DELETE_REQ 0x0024 -#define QMIWMS_DELETE_RESP 0x0024 -#define QMIWMS_GET_MESSAGE_PROTOCOL_REQ 0x0030 -#define QMIWMS_GET_MESSAGE_PROTOCOL_RESP 0x0030 -#define QMIWMS_LIST_MESSAGES_REQ 0x0031 -#define QMIWMS_LIST_MESSAGES_RESP 0x0031 -#define QMIWMS_GET_SMSC_ADDRESS_REQ 0x0034 -#define QMIWMS_GET_SMSC_ADDRESS_RESP 0x0034 -#define QMIWMS_SET_SMSC_ADDRESS_REQ 0x0035 -#define QMIWMS_SET_SMSC_ADDRESS_RESP 0x0035 -#define QMIWMS_GET_STORE_MAX_SIZE_REQ 0x0036 -#define QMIWMS_GET_STORE_MAX_SIZE_RESP 0x0036 - - -#define WMS_MESSAGE_PROTOCOL_CDMA 0x00 -#define WMS_MESSAGE_PROTOCOL_WCDMA 0x01 - -#if 0 -typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG; - -typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR MessageProtocol; -} QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG; - -typedef struct _QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_REQ_MSG; - -typedef struct _QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - ULONG MemStoreMaxSize; -} QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_RESP_MSG; - -typedef struct _REQUEST_TAG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TagType; -} REQUEST_TAG, *PREQUEST_TAG; - -typedef struct _QMIWMS_LIST_MESSAGES_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_LIST_MESSAGES_REQ_MSG, *PQMIWMS_LIST_MESSAGES_REQ_MSG; - -typedef struct _QMIWMS_MESSAGE -{ - ULONG MessageIndex; - UCHAR TagType; -} QMIWMS_MESSAGE, *PQMIWMS_MESSAGE; - -typedef struct _QMIWMS_LIST_MESSAGES_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - ULONG NumMessages; -} QMIWMS_LIST_MESSAGES_RESP_MSG, *PQMIWMS_LIST_MESSAGES_RESP_MSG; - -typedef struct _QMIWMS_RAW_READ_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG MemoryIndex; -} QMIWMS_RAW_READ_REQ_MSG, *PQMIWMS_RAW_READ_REQ_MSG; - -typedef struct _QMIWMS_RAW_READ_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR TagType; - UCHAR Format; - USHORT MessageLength; - UCHAR Message; -} QMIWMS_RAW_READ_RESP_MSG, *PQMIWMS_RAW_READ_RESP_MSG; - -typedef struct _QMIWMS_MODIFY_TAG_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG MemoryIndex; - UCHAR TagType; -} QMIWMS_MODIFY_TAG_REQ_MSG, *PQMIWMS_MODIFY_TAG_REQ_MSG; - -typedef struct _QMIWMS_MODIFY_TAG_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_MODIFY_TAG_RESP_MSG, *PQMIWMS_MODIFY_TAG_RESP_MSG; - -typedef struct _QMIWMS_RAW_SEND_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR SmsFormat; - USHORT SmsLength; - UCHAR SmsMessage; -} QMIWMS_RAW_SEND_REQ_MSG, *PQMIWMS_RAW_SEND_REQ_MSG; - -typedef struct _RAW_SEND_CAUSE_CODE -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CauseCode; -} RAW_SEND_CAUSE_CODE, *PRAW_SEND_CAUSE_CODE; - - -typedef struct _QMIWMS_RAW_SEND_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_RAW_SEND_RESP_MSG, *PQMIWMS_RAW_SEND_RESP_MSG; - - -typedef struct _WMS_DELETE_MESSAGE_INDEX -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG MemoryIndex; -} WMS_DELETE_MESSAGE_INDEX, *PWMS_DELETE_MESSAGE_INDEX; - -typedef struct _WMS_DELETE_MESSAGE_TAG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR MessageTag; -} WMS_DELETE_MESSAGE_TAG, *PWMS_DELETE_MESSAGE_TAG; - -typedef struct _QMIWMS_DELETE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_DELETE_REQ_MSG, *PQMIWMS_DELETE_REQ_MSG; - -typedef struct _QMIWMS_DELETE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_DELETE_RESP_MSG, *PQMIWMS_DELETE_RESP_MSG; - - -typedef struct _QMIWMS_GET_SMSC_ADDRESS_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMIWMS_GET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_GET_SMSC_ADDRESS_REQ_MSG; - -typedef struct _QMIWMS_SMSC_ADDRESS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SMSCAddressType[3]; - UCHAR SMSCAddressLength; - UCHAR SMSCAddressDigits; -} QMIWMS_SMSC_ADDRESS, *PQMIWMS_SMSC_ADDRESS; - - -typedef struct _QMIWMS_GET_SMSC_ADDRESS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR SMSCAddress; -} QMIWMS_GET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_GET_SMSC_ADDRESS_RESP_MSG; - -typedef struct _QMIWMS_SET_SMSC_ADDRESS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR SMSCAddress; -} QMIWMS_SET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_SET_SMSC_ADDRESS_REQ_MSG; - -typedef struct _QMIWMS_SET_SMSC_ADDRESS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_SET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_SET_SMSC_ADDRESS_RESP_MSG; - -typedef struct _QMIWMS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportNewMessage; -} QMIWMS_SET_EVENT_REPORT_REQ_MSG, *PQMIWMS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIWMS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_SET_EVENT_REPORT_RESP_MSG, *PQMIWMS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMIWMS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG StorageIndex; -} QMIWMS_EVENT_REPORT_IND_MSG, *PQMIWMS_EVENT_REPORT_IND_MSG; -#endif - -// ======================= End of WMS ============================== - - -// ======================= NAS ============================== -#define QMINAS_SET_EVENT_REPORT_REQ 0x0002 -#define QMINAS_SET_EVENT_REPORT_RESP 0x0002 -#define QMINAS_EVENT_REPORT_IND 0x0002 -#define QMINAS_GET_SIGNAL_STRENGTH_REQ 0x0020 -#define QMINAS_GET_SIGNAL_STRENGTH_RESP 0x0020 -#define QMINAS_PERFORM_NETWORK_SCAN_REQ 0x0021 -#define QMINAS_PERFORM_NETWORK_SCAN_RESP 0x0021 -#define QMINAS_INITIATE_NW_REGISTER_REQ 0x0022 -#define QMINAS_INITIATE_NW_REGISTER_RESP 0x0022 -#define QMINAS_INITIATE_ATTACH_REQ 0x0023 -#define QMINAS_INITIATE_ATTACH_RESP 0x0023 -#define QMINAS_GET_SERVING_SYSTEM_REQ 0x0024 -#define QMINAS_GET_SERVING_SYSTEM_RESP 0x0024 -#define QMINAS_SERVING_SYSTEM_IND 0x0024 -#define QMINAS_GET_HOME_NETWORK_REQ 0x0025 -#define QMINAS_GET_HOME_NETWORK_RESP 0x0025 -#define QMINAS_GET_PREFERRED_NETWORK_REQ 0x0026 -#define QMINAS_GET_PREFERRED_NETWORK_RESP 0x0026 -#define QMINAS_SET_PREFERRED_NETWORK_REQ 0x0027 -#define QMINAS_SET_PREFERRED_NETWORK_RESP 0x0027 -#define QMINAS_GET_FORBIDDEN_NETWORK_REQ 0x0028 -#define QMINAS_GET_FORBIDDEN_NETWORK_RESP 0x0028 -#define QMINAS_SET_FORBIDDEN_NETWORK_REQ 0x0029 -#define QMINAS_SET_FORBIDDEN_NETWORK_RESP 0x0029 -#define QMINAS_SET_TECHNOLOGY_PREF_REQ 0x002A -#define QMINAS_SET_TECHNOLOGY_PREF_RESP 0x002A -#define QMINAS_GET_RF_BAND_INFO_REQ 0x0031 -#define QMINAS_GET_RF_BAND_INFO_RESP 0x0031 -#define QMINAS_GET_CELL_LOCATION_INFO_REQ 0x0043 -#define QMINAS_GET_CELL_LOCATION_INFO_RESP 0x0043 -#define QMINAS_GET_PLMN_NAME_REQ 0x0044 -#define QMINAS_GET_PLMN_NAME_RESP 0x0044 -#define QUECTEL_PACKET_TRANSFER_START_IND 0X100 -#define QUECTEL_PACKET_TRANSFER_END_IND 0X101 -#define QMINAS_GET_SYS_INFO_REQ 0x004D -#define QMINAS_GET_SYS_INFO_RESP 0x004D -#define QMINAS_SYS_INFO_IND 0x004E -#define QMINAS_GET_SIG_INFO_REQ 0x004F -#define QMINAS_GET_SIG_INFO_RESP 0x004F - -typedef struct _QMINAS_GET_HOME_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} __attribute__ ((packed)) QMINAS_GET_HOME_NETWORK_REQ_MSG, *PQMINAS_GET_HOME_NETWORK_REQ_MSG; - -typedef struct _HOME_NETWORK_SYSTEMID -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT SystemID; - USHORT NetworkID; -} __attribute__ ((packed)) HOME_NETWORK_SYSTEMID, *PHOME_NETWORK_SYSTEMID; - -typedef struct _HOME_NETWORK -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} __attribute__ ((packed)) HOME_NETWORK, *PHOME_NETWORK; - -#if 0 -typedef struct _HOME_NETWORK_EXT -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDescDisp; - UCHAR NetworkDescEncoding; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} HOME_NETWORK_EXT, *PHOME_NETWORK_EXT; - -typedef struct _QMINAS_GET_HOME_NETWORK_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMINAS_GET_HOME_NETWORK_RESP_MSG, *PQMINAS_GET_HOME_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_PREFERRED_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_GET_PREFERRED_NETWORK_REQ_MSG; - - -typedef struct _PREFERRED_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - USHORT RadioAccess; -} PREFERRED_NETWORK, *PPREFERRED_NETWORK; - -typedef struct _QMINAS_GET_PREFERRED_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - USHORT NumPreferredNetwork; -} QMINAS_GET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_GET_PREFERRED_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG; - -typedef struct _FORBIDDEN_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; -} FORBIDDEN_NETWORK, *PFORBIDDEN_NETWORK; - -typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - USHORT NumForbiddenNetwork; -} QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_SERVING_SYSTEM_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_SERVING_SYSTEM_REQ_MSG, *PQMINAS_GET_SERVING_SYSTEM_REQ_MSG; - -typedef struct _QMINAS_ROAMING_INDICATOR_MSG -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - UCHAR RoamingIndicator; -} QMINAS_ROAMING_INDICATOR_MSG, *PQMINAS_ROAMING_INDICATOR_MSG; -#endif - -typedef struct _QMINAS_DATA_CAP -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - UCHAR DataCapListLen; - UCHAR DataCap; -} __attribute__ ((packed)) QMINAS_DATA_CAP, *PQMINAS_DATA_CAP; - -typedef struct _QMINAS_CURRENT_PLMN_MSG -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} __attribute__ ((packed)) QMINAS_CURRENT_PLMN_MSG, *PQMINAS_CURRENT_PLMN_MSG; - -typedef struct _QMINAS_GET_SERVING_SYSTEM_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMINAS_GET_SERVING_SYSTEM_RESP_MSG, *PQMINAS_GET_SERVING_SYSTEM_RESP_MSG; - -typedef struct _SERVING_SYSTEM -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR RegistrationState; - UCHAR CSAttachedState; - UCHAR PSAttachedState; - UCHAR RegistredNetwork; - UCHAR InUseRadioIF; - UCHAR RadioIF; -} __attribute__ ((packed)) SERVING_SYSTEM, *PSERVING_SYSTEM; - -typedef struct _QMINAS_GET_SYS_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMINAS_GET_SYS_INFO_RESP_MSG, *PQMINAS_GET_SYS_INFO_RESP_MSG; - -typedef struct _QMINAS_SYS_INFO_IND_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMINAS_SYS_INFO_IND_MSG, *PQMINAS_SYS_INFO_IND_MSG; - -typedef struct _SERVICE_STATUS_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvStatus; - UCHAR true_srv_status; - UCHAR IsPrefDataPath; -} __attribute__ ((packed)) SERVICE_STATUS_INFO, *PSERVICE_STATUS_INFO; - -typedef struct _CDMA_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR IsSysPrlMatchValid; - UCHAR IsSysPrlMatch; - UCHAR PRevInUseValid; - UCHAR PRevInUse; - UCHAR BSPRevValid; - UCHAR BSPRev; - UCHAR CCSSupportedValid; - UCHAR CCSSupported; - UCHAR CDMASysIdValid; - USHORT SID; - USHORT NID; - UCHAR BSInfoValid; - USHORT BaseID; - ULONG BaseLAT; - ULONG BaseLONG; - UCHAR PacketZoneValid; - USHORT PacketZone; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; -} __attribute__ ((packed)) CDMA_SYSTEM_INFO, *PCDMA_SYSTEM_INFO; - -typedef struct _HDR_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR IsSysPrlMatchValid; - UCHAR IsSysPrlMatch; - UCHAR HdrPersonalityValid; - UCHAR HdrPersonality; - UCHAR HdrActiveProtValid; - UCHAR HdrActiveProt; - UCHAR is856SysIdValid; - UCHAR is856SysId[16]; -} __attribute__ ((packed)) HDR_SYSTEM_INFO, *PHDR_SYSTEM_INFO; - -typedef struct _GSM_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR EgprsSuppValid; - UCHAR EgprsSupp; - UCHAR DtmSuppValid; - UCHAR DtmSupp; -} __attribute__ ((packed)) GSM_SYSTEM_INFO, *PGSM_SYSTEM_INFO; - -typedef struct _WCDMA_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR HsCallStatusValid; - UCHAR HsCallStatus; - UCHAR HsIndValid; - UCHAR HsInd; - UCHAR PscValid; - UCHAR Psc; -} __attribute__ ((packed)) WCDMA_SYSTEM_INFO, *PWCDMA_SYSTEM_INFO; - -typedef struct _LTE_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR TacValid; - USHORT Tac; -} __attribute__ ((packed)) LTE_SYSTEM_INFO, *PLTE_SYSTEM_INFO; - -typedef struct _TDSCDMA_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR HsCallStatusValid; - UCHAR HsCallStatus; - UCHAR HsIndValid; - UCHAR HsInd; - UCHAR CellParameterIdValid; - USHORT CellParameterId; - UCHAR CellBroadcastCapValid; - ULONG CellBroadcastCap; - UCHAR CsBarStatusValid; - ULONG CsBarStatus; - UCHAR PsBarStatusValid; - ULONG PsBarStatus; - UCHAR CipherDomainValid; - UCHAR CipherDomain; -} __attribute__ ((packed)) TDSCDMA_SYSTEM_INFO, *PTDSCDMA_SYSTEM_INFO; - -typedef enum { - NAS_SYS_SRV_STATUS_NO_SRV_V01 = 0, - NAS_SYS_SRV_STATUS_LIMITED_V01 = 1, - NAS_SYS_SRV_STATUS_SRV_V01 = 2, - NAS_SYS_SRV_STATUS_LIMITED_REGIONAL_V01 = 3, - NAS_SYS_SRV_STATUS_PWR_SAVE_V01 = 4, -}nas_service_status_enum_type_v01; - -typedef enum { - SYS_SRV_DOMAIN_NO_SRV_V01 = 0, - SYS_SRV_DOMAIN_CS_ONLY_V01 = 1, - SYS_SRV_DOMAIN_PS_ONLY_V01 = 2, - SYS_SRV_DOMAIN_CS_PS_V01 = 3, - SYS_SRV_DOMAIN_CAMPED_V01 = 4, -}nas_service_domain_enum_type_v01; - -typedef enum { - QMI_NAS_RADIO_INTERFACE_UNKNOWN = -1, - QMI_NAS_RADIO_INTERFACE_NONE = 0x00, - QMI_NAS_RADIO_INTERFACE_CDMA_1X = 0x01, - QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO = 0x02, - QMI_NAS_RADIO_INTERFACE_AMPS = 0x03, - QMI_NAS_RADIO_INTERFACE_GSM = 0x04, - QMI_NAS_RADIO_INTERFACE_UMTS = 0x05, - QMI_NAS_RADIO_INTERFACE_LTE = 0x08, - QMI_NAS_RADIO_INTERFACE_TD_SCDMA = 0x09, - QMI_NAS_RADIO_INTERFACE_5GNR = 0x0C, -} QMI_NAS_RADIO_INTERFACE_E; - -typedef enum { - QMI_NAS_ACTIVE_BAND_BC_0 = 0, - QMI_NAS_ACTIVE_BAND_BC_1 = 1, - QMI_NAS_ACTIVE_BAND_BC_2 = 2, - QMI_NAS_ACTIVE_BAND_BC_3 = 3, - QMI_NAS_ACTIVE_BAND_BC_4 = 4, - QMI_NAS_ACTIVE_BAND_BC_5 = 5, - QMI_NAS_ACTIVE_BAND_BC_6 = 6, - QMI_NAS_ACTIVE_BAND_BC_7 = 7, - QMI_NAS_ACTIVE_BAND_BC_8 = 8, - QMI_NAS_ACTIVE_BAND_BC_9 = 9, - QMI_NAS_ACTIVE_BAND_BC_10 = 10, - QMI_NAS_ACTIVE_BAND_BC_11 = 11, - QMI_NAS_ACTIVE_BAND_BC_12 = 12, - QMI_NAS_ACTIVE_BAND_BC_13 = 13, - QMI_NAS_ACTIVE_BAND_BC_14 = 14, - QMI_NAS_ACTIVE_BAND_BC_15 = 15, - QMI_NAS_ACTIVE_BAND_BC_16 = 16, - QMI_NAS_ACTIVE_BAND_BC_17 = 17, - QMI_NAS_ACTIVE_BAND_BC_18 = 18, - QMI_NAS_ACTIVE_BAND_BC_19 = 19, - QMI_NAS_ACTIVE_BAND_GSM_450 = 40, - QMI_NAS_ACTIVE_BAND_GSM_480 = 41, - QMI_NAS_ACTIVE_BAND_GSM_750 = 42, - QMI_NAS_ACTIVE_BAND_GSM_850 = 43, - QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED = 44, - QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY = 45, - QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS = 46, - QMI_NAS_ACTIVE_BAND_GSM_DCS_1800 = 47, - QMI_NAS_ACTIVE_BAND_GSM_PCS_1900 = 48, - QMI_NAS_ACTIVE_BAND_WCDMA_2100 = 80, - QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900 = 81, - QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800 = 82, - QMI_NAS_ACTIVE_BAND_WCDMA_1700_US = 83, - QMI_NAS_ACTIVE_BAND_WCDMA_850 = 84, - QMI_NAS_ACTIVE_BAND_WCDMA_800 = 85, - QMI_NAS_ACTIVE_BAND_WCDMA_2600 = 86, - QMI_NAS_ACTIVE_BAND_WCDMA_900 = 87, - QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN = 88, - QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN = 90, - QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN = 91, - QMI_NAS_ACTIVE_BAND_EUTRAN_1 = 120, - QMI_NAS_ACTIVE_BAND_EUTRAN_2 = 121, - QMI_NAS_ACTIVE_BAND_EUTRAN_3 = 122, - QMI_NAS_ACTIVE_BAND_EUTRAN_4 = 123, - QMI_NAS_ACTIVE_BAND_EUTRAN_5 = 124, - QMI_NAS_ACTIVE_BAND_EUTRAN_6 = 125, - QMI_NAS_ACTIVE_BAND_EUTRAN_7 = 126, - QMI_NAS_ACTIVE_BAND_EUTRAN_8 = 127, - QMI_NAS_ACTIVE_BAND_EUTRAN_9 = 128, - QMI_NAS_ACTIVE_BAND_EUTRAN_10 = 129, - QMI_NAS_ACTIVE_BAND_EUTRAN_11 = 130, - QMI_NAS_ACTIVE_BAND_EUTRAN_12 = 131, - QMI_NAS_ACTIVE_BAND_EUTRAN_13 = 132, - QMI_NAS_ACTIVE_BAND_EUTRAN_14 = 133, - QMI_NAS_ACTIVE_BAND_EUTRAN_17 = 134, - QMI_NAS_ACTIVE_BAND_EUTRAN_18 = 143, - QMI_NAS_ACTIVE_BAND_EUTRAN_19 = 144, - QMI_NAS_ACTIVE_BAND_EUTRAN_20 = 145, - QMI_NAS_ACTIVE_BAND_EUTRAN_21 = 146, - QMI_NAS_ACTIVE_BAND_EUTRAN_23 = 152, - QMI_NAS_ACTIVE_BAND_EUTRAN_24 = 147, - QMI_NAS_ACTIVE_BAND_EUTRAN_25 = 148, - QMI_NAS_ACTIVE_BAND_EUTRAN_26 = 153, - QMI_NAS_ACTIVE_BAND_EUTRAN_27 = 164, - QMI_NAS_ACTIVE_BAND_EUTRAN_28 = 158, - QMI_NAS_ACTIVE_BAND_EUTRAN_29 = 159, - QMI_NAS_ACTIVE_BAND_EUTRAN_30 = 160, - QMI_NAS_ACTIVE_BAND_EUTRAN_31 = 165, - QMI_NAS_ACTIVE_BAND_EUTRAN_32 = 154, - QMI_NAS_ACTIVE_BAND_EUTRAN_33 = 135, - QMI_NAS_ACTIVE_BAND_EUTRAN_34 = 136, - QMI_NAS_ACTIVE_BAND_EUTRAN_35 = 137, - QMI_NAS_ACTIVE_BAND_EUTRAN_36 = 138, - QMI_NAS_ACTIVE_BAND_EUTRAN_37 = 139, - QMI_NAS_ACTIVE_BAND_EUTRAN_38 = 140, - QMI_NAS_ACTIVE_BAND_EUTRAN_39 = 141, - QMI_NAS_ACTIVE_BAND_EUTRAN_40 = 142, - QMI_NAS_ACTIVE_BAND_EUTRAN_41 = 149, - QMI_NAS_ACTIVE_BAND_EUTRAN_42 = 150, - QMI_NAS_ACTIVE_BAND_EUTRAN_43 = 151, - QMI_NAS_ACTIVE_BAND_EUTRAN_46 = 163, - QMI_NAS_ACTIVE_BAND_EUTRAN_47 = 166, - QMI_NAS_ACTIVE_BAND_EUTRAN_48 = 167, - QMI_NAS_ACTIVE_BAND_EUTRAN_66 = 161, - QMI_NAS_ACTIVE_BAND_EUTRAN_71 = 168, - QMI_NAS_ACTIVE_BAND_EUTRAN_125 = 155, - QMI_NAS_ACTIVE_BAND_EUTRAN_126 = 156, - QMI_NAS_ACTIVE_BAND_EUTRAN_127 = 157, - QMI_NAS_ACTIVE_BAND_EUTRAN_250 = 162, - QMI_NAS_ACTIVE_BAND_TDSCDMA_A = 200, - QMI_NAS_ACTIVE_BAND_TDSCDMA_B = 201, - QMI_NAS_ACTIVE_BAND_TDSCDMA_C = 202, - QMI_NAS_ACTIVE_BAND_TDSCDMA_D = 203, - QMI_NAS_ACTIVE_BAND_TDSCDMA_E = 204, - QMI_NAS_ACTIVE_BAND_TDSCDMA_F = 205, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_1 = 250, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_2 = 251, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_3 = 252, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_5 = 253, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_7 = 254, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_8 = 255, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_20 = 256, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_28 = 257, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_38 = 258, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_41 = 259, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_50 = 260, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_51 = 261, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_66 = 262, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_70 = 263, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_71 = 264, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_74 = 265, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_75 = 266, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_76 = 267, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_77 = 268, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_78 = 269, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_79 = 270, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_80 = 271, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_81 = 272, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_82 = 273, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_83 = 274, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_84 = 275, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_85 = 276, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_257= 277, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_258= 278, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_259= 279, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_260= 280, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_261= 281, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_12 = 282, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_25 = 283, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_34 = 284, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_39 = 285, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_40 = 286, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_65 = 287, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_86 = 288, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_48 = 289, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_14 = 290 -} QMI_NAS_ACTIVE_BAND_E; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8_t srv_domain_valid; - uint8_t srv_domain; - uint8_t srv_capability_valid; - uint8_t srv_capability; - uint8_t roam_status_valid; - uint8_t roam_status; - uint8_t is_sys_forbidden_valid; - uint8_t is_sys_forbidden; - - uint8_t lac_valid; - uint16_t lac; - uint8_t cell_id_valid; - uint32_t cell_id; - uint8_t reg_reject_info_valid; - uint8_t reject_srv_domain; - uint8_t rej_cause; - uint8_t network_id_valid; - UCHAR MCC[3]; - UCHAR MNC[3]; - - uint8_t tac_valid; - uint16_t tac; -} __attribute__ ((packed)) NR5G_SYSTEM_INFO, *PNR5G_SYSTEM_INFO; - -#if 0 -typedef struct _QMINAS_SERVING_SYSTEM_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_SERVING_SYSTEM_IND_MSG, *PQMINAS_SERVING_SYSTEM_IND_MSG; - -typedef struct _QMINAS_SET_PREFERRED_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT NumPreferredNetwork; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - USHORT RadioAccess; -} QMINAS_SET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_SET_PREFERRED_NETWORK_REQ_MSG; - -typedef struct _QMINAS_SET_PREFERRED_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_SET_PREFERRED_NETWORK_RESP_MSG; - -typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT NumForbiddenNetwork; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; -} QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG; - -typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_REQ_MSG; - -typedef struct _VISIBLE_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkStatus; - UCHAR NetworkDesclen; -} VISIBLE_NETWORK, *PVISIBLE_NETWORK; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_RESP_MSG; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO -{ - UCHAR TLVType; // 0x010 - required parameter - USHORT TLVLength; // length - USHORT NumNetworkInstances; -} QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO -{ - UCHAR TLVType; // 0x011 - required parameter - USHORT TLVLength; // length - USHORT NumInst; -} QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_RAT_INFO; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT -{ - USHORT MCC; - USHORT MNC; - UCHAR RAT; -} QMINAS_PERFORM_NETWORK_SCAN_RAT, *PQMINAS_PERFORM_NETWORK_SCAN_RAT; - - -typedef struct _QMINAS_MANUAL_NW_REGISTER -{ - UCHAR TLV2Type; // 0x02 - result code - USHORT TLV2Length; // 4 - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR RadioAccess; -} QMINAS_MANUAL_NW_REGISTER, *PQMINAS_MANUAL_NW_REGISTER; - -typedef struct _QMINAS_INITIATE_NW_REGISTER_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR RegisterAction; -} QMINAS_INITIATE_NW_REGISTER_REQ_MSG, *PQMINAS_INITIATE_NW_REGISTER_REQ_MSG; - -typedef struct _QMINAS_INITIATE_NW_REGISTER_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_INITIATE_NW_REGISTER_RESP_MSG, *PQMINAS_INITIATE_NW_REGISTER_RESP_MSG; - -typedef struct _QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT TechPref; - UCHAR Duration; -} QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_REQ_MSG; - -typedef struct _QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_RESP_MSG; - -typedef struct _QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_REQ_MSG; - -typedef struct _QMINAS_SIGNAL_STRENGTH -{ - CHAR SigStrength; - UCHAR RadioIf; -} QMINAS_SIGNAL_STRENGTH, *PQMINAS_SIGNAL_STRENGTH; - -typedef struct _QMINAS_SIGNAL_STRENGTH_LIST -{ - UCHAR TLV3Type; - USHORT TLV3Length; - USHORT NumInstance; -} QMINAS_SIGNAL_STRENGTH_LIST, *PQMINAS_SIGNAL_STRENGTH_LIST; - - -typedef struct _QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - CHAR SignalStrength; - UCHAR RadioIf; -} QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_RESP_MSG; - - -typedef struct _QMINAS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportSigStrength; - UCHAR NumTresholds; - CHAR TresholdList[2]; -} QMINAS_SET_EVENT_REPORT_REQ_MSG, *PQMINAS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMINAS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_SET_EVENT_REPORT_RESP_MSG, *PQMINAS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMINAS_SIGNAL_STRENGTH_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - CHAR SigStrength; - UCHAR RadioIf; -} QMINAS_SIGNAL_STRENGTH_TLV, *PQMINAS_SIGNAL_STRENGTH_TLV; - -typedef struct _QMINAS_REJECT_CAUSE_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ServiceDomain; - USHORT RejectCause; -} QMINAS_REJECT_CAUSE_TLV, *PQMINAS_REJECT_CAUSE_TLV; - -typedef struct _QMINAS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_EVENT_REPORT_IND_MSG, *PQMINAS_EVENT_REPORT_IND_MSG; - -typedef struct _QMINAS_GET_RF_BAND_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_GET_RF_BAND_INFO_REQ_MSG, *PQMINAS_GET_RF_BAND_INFO_REQ_MSG; - -typedef struct _QMINASRF_BAND_INFO -{ - UCHAR RadioIf; - USHORT ActiveBand; - USHORT ActiveChannel; -} QMINASRF_BAND_INFO, *PQMINASRF_BAND_INFO; - -typedef struct _QMINAS_GET_RF_BAND_INFO_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR NumInstances; -} QMINAS_GET_RF_BAND_INFO_RESP_MSG, *PQMINAS_GET_RF_BAND_INFO_RESP_MSG; - - -typedef struct _QMINAS_GET_PLMN_NAME_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT MCC; - USHORT MNC; -} QMINAS_GET_PLMN_NAME_REQ_MSG, *PQMINAS_GET_PLMN_NAME_REQ_MSG; - -typedef struct _QMINAS_GET_PLMN_NAME_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_GET_PLMN_NAME_RESP_MSG, *PQMINAS_GET_PLMN_NAME_RESP_MSG; - -typedef struct _QMINAS_GET_PLMN_NAME_SPN -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SPN_Enc; - UCHAR SPN_Len; -} QMINAS_GET_PLMN_NAME_SPN, *PQMINAS_GET_PLMN_NAME_SPN; - -typedef struct _QMINAS_GET_PLMN_NAME_PLMN -{ - UCHAR PLMN_Enc; - UCHAR PLMN_Ci; - UCHAR PLMN_SpareBits; - UCHAR PLMN_Len; -} QMINAS_GET_PLMN_NAME_PLMN, *PQMINAS_GET_PLMN_NAME_PLMN; - -typedef struct _QMINAS_INITIATE_ATTACH_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR PsAttachAction; -} QMINAS_INITIATE_ATTACH_REQ_MSG, *PQMINAS_INITIATE_ATTACH_REQ_MSG; - -typedef struct _QMINAS_INITIATE_ATTACH_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} QMINAS_INITIATE_ATTACH_RESP_MSG, *PQMINAS_INITIATE_ATTACH_RESP_MSG; -#endif -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - SHORT ecio; -} __attribute__ ((packed)) QMINAS_SIG_INFO_CDMA_TLV_MSG, *PQMINAS_SIG_INFO_CDMA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - SHORT ecio; - CHAR sinr; - INT io; -} __attribute__ ((packed)) QMINAS_SIG_INFO_HDR_TLV_MSG, *PQMINAS_SIG_INFO_HDR_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; -} __attribute__ ((packed)) QMINAS_SIG_INFO_GSM_TLV_MSG, *PQMINAS_SIG_INFO_GSM_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - SHORT ecio; -} __attribute__ ((packed)) QMINAS_SIG_INFO_WCDMA_TLV_MSG, *PQMINAS_SIG_INFO_WCDMA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - CHAR rsrq; - SHORT rsrp; - SHORT snr; -} __attribute__ ((packed)) QMINAS_SIG_INFO_LTE_TLV_MSG, *PQMINAS_SIG_INFO_LTE_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rscp; -} __attribute__ ((packed)) QMINAS_SIG_INFO_TDSCDMA_TLV_MSG, *PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - SHORT rsrp; - SHORT snr; -} __attribute__ ((packed)) QMINAS_SIG_INFO_5G_NSA_TLV_MSG, *PQMINAS_SIG_INFO_5G_NSA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - SHORT nr5g_rsrq; -} __attribute__ ((packed)) QMINAS_SIG_INFO_5G_SA_TLV_MSG, *PQMINAS_SIG_INFO_5G_SA_TLV_MSG; - -typedef struct { - uint8 radio_if; - uint16 active_band; - uint16 active_channel; -} __attribute__ ((packed)) NasGetRfBandInfo; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfo bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoList; - -typedef struct { - uint8 radio_if; - uint16 dedicated_band; -} __attribute__ ((packed)) NasGetRfBandInfoDedicated; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfoDedicated bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoDedicatedList; - -typedef struct { - uint8 radio_if; - uint16 active_band; - uint32 active_channel; -} __attribute__ ((packed)) NasGetRfBandInfoExtended; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfoExtended bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoExtendedList; - -typedef struct { - uint8 radio_if; - uint32 bandwidth; -} __attribute__ ((packed)) NasGetRfBandInfoBandWidth; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfoBandWidth bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoBandWidthList; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 plmn[3]; - uint8 tac[3]; - uint64 global_cell_id; - uint16 physical_cell_id; - int16 rsrq; - int16 rsrp; - int16 snr; -} __attribute__ ((packed)) NasGetCellLocationNr5gServingCell; - -typedef struct { - uint16 physical_cell_id; - int16 rsrq; - int16 rsrp; - int16 rssi; - int16 cell_selection_rx_level; -} __attribute__ ((packed)) NasGetCellLocationLteInfoCell; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 ue_in_idle; - uint8 plmn[3]; - uint16 tracking_area_code; - uint32 global_cell_id; - uint16 absolute_rf_channel_number; - uint16 serving_cell_id; - uint8 cell_reselection_priority; - uint8 s_non_intra_search_threshold; - uint8 serving_cell_low_threshold; - uint8 s_intra_search_threshold; - uint8 cells_len; - NasGetCellLocationLteInfoCell cells_array[0]; -} __attribute__ ((packed)) NasGetCellLocationLteInfoIntrafrequency; - -typedef struct _QmiMessageNasGetCellLocationInfoOutputInterfrequencyLteInfoFrequencyElement { - uint16 eutra_absolute_rf_channel_number; - uint8 cell_selection_rx_level_low_threshold; - uint8 cell_selection_rx_level_high_threshold; - uint8 cell_reselection_priority; - uint8 cells_len; - NasGetCellLocationLteInfoCell cells_array[0]; -} __attribute__ ((packed)) NasGetCellLocationLteInfoInterfrequencyFrequencyElement; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 ue_in_idle; - uint8 freqs_len; - NasGetCellLocationLteInfoInterfrequencyFrequencyElement freqs[0]; -} __attribute__ ((packed)) NasGetCellLocationLteInfoInterfrequency; - -// ======================= End of NAS ============================== - -// ======================= UIM ============================== -#define QMIUIM_READ_TRANSPARENT_REQ 0x0020 -#define QMIUIM_READ_TRANSPARENT_RESP 0x0020 -#define QMIUIM_READ_TRANSPARENT_IND 0x0020 -#define QMIUIM_READ_RECORD_REQ 0x0021 -#define QMIUIM_READ_RECORD_RESP 0x0021 -#define QMIUIM_READ_RECORD_IND 0x0021 -#define QMIUIM_WRITE_TRANSPARENT_REQ 0x0022 -#define QMIUIM_WRITE_TRANSPARENT_RESP 0x0022 -#define QMIUIM_WRITE_TRANSPARENT_IND 0x0022 -#define QMIUIM_WRITE_RECORD_REQ 0x0023 -#define QMIUIM_WRITE_RECORD_RESP 0x0023 -#define QMIUIM_WRITE_RECORD_IND 0x0023 -#define QMIUIM_SET_PIN_PROTECTION_REQ 0x0025 -#define QMIUIM_SET_PIN_PROTECTION_RESP 0x0025 -#define QMIUIM_SET_PIN_PROTECTION_IND 0x0025 -#define QMIUIM_VERIFY_PIN_REQ 0x0026 -#define QMIUIM_VERIFY_PIN_RESP 0x0026 -#define QMIUIM_VERIFY_PIN_IND 0x0026 -#define QMIUIM_UNBLOCK_PIN_REQ 0x0027 -#define QMIUIM_UNBLOCK_PIN_RESP 0x0027 -#define QMIUIM_UNBLOCK_PIN_IND 0x0027 -#define QMIUIM_CHANGE_PIN_REQ 0x0028 -#define QMIUIM_CHANGE_PIN_RESP 0x0028 -#define QMIUIM_CHANGE_PIN_IND 0x0028 -#define QMIUIM_DEPERSONALIZATION_REQ 0x0029 -#define QMIUIM_DEPERSONALIZATION_RESP 0x0029 -#define QMIUIM_EVENT_REG_REQ 0x002E -#define QMIUIM_EVENT_REG_RESP 0x002E -#define QMIUIM_GET_CARD_STATUS_REQ 0x002F -#define QMIUIM_GET_CARD_STATUS_RESP 0x002F -#define QMIUIM_STATUS_CHANGE_IND 0x0032 -#define QMIUIM_POWER_DOWN 0x0030 -#define QMIUIM_POWER_UP 0x0031 - - -typedef struct _QMIUIM_GET_CARD_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIUIM_GET_CARD_STATUS_RESP_MSG, *PQMIUIM_GET_CARD_STATUS_RESP_MSG; - -#define UIM_CARD_STATE_ABSENT 0x00 -#define UIM_CARD_STATE_PRESENT 0x01 -#define UIM_CARD_STATE_ERROR 0x02 - -typedef struct _QMIUIM_CARD_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT IndexGWPri; - USHORT Index1XPri; - USHORT IndexGWSec; - USHORT Index1XSec; - UCHAR NumSlot; - UCHAR CardState; - UCHAR UPINState; - UCHAR UPINRetries; - UCHAR UPUKRetries; - UCHAR ErrorCode; - UCHAR NumApp; - UCHAR AppType; - UCHAR AppState; - UCHAR PersoState; - UCHAR PersoFeature; - UCHAR PersoRetries; - UCHAR PersoUnblockRetries; - UCHAR AIDLength; -} __attribute__ ((packed)) QMIUIM_CARD_STATUS, *PQMIUIM_CARD_STATUS; - -typedef struct _QMIUIM_PIN_STATE -{ - UCHAR UnivPIN; - UCHAR PIN1State; - UCHAR PIN1Retries; - UCHAR PUK1Retries; - UCHAR PIN2State; - UCHAR PIN2Retries; - UCHAR PUK2Retries; -} __attribute__ ((packed)) QMIUIM_PIN_STATE, *PQMIUIM_PIN_STATE; - -typedef struct _QMIUIM_VERIFY_PIN_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Session_Type; - UCHAR Aid_Len; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINID; - UCHAR PINLen; - UCHAR PINValue; -} __attribute__ ((packed)) QMIUIM_VERIFY_PIN_REQ_MSG, *PQMIUIM_VERIFY_PIN_REQ_MSG; - -typedef struct _QMIUIM_VERIFY_PIN_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__ ((packed)) QMIUIM_VERIFY_PIN_RESP_MSG, *PQMIUIM_VERIFY_PIN_RESP_MSG; - -typedef struct _QMIUIM_READ_TRANSPARENT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Session_Type; - UCHAR Aid_Len; - UCHAR TLV2Type; - USHORT TLV2Length; - USHORT file_id; - UCHAR path_len; - UCHAR path[]; -} __attribute__ ((packed)) QMIUIM_READ_TRANSPARENT_REQ_MSG, *PQMIUIM_READ_TRANSPARENT_REQ_MSG; - -typedef struct _READ_TRANSPARENT_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT Offset; - USHORT Length; -} __attribute__ ((packed)) READ_TRANSPARENT_TLV, *PREAD_TRANSPARENT_TLV; - -typedef struct _QMIUIM_CONTENT -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT content_len; - UCHAR content[]; -} __attribute__ ((packed)) QMIUIM_CONTENT, *PQMIUIM_CONTENT; - -typedef struct _QMIUIM_READ_TRANSPARENT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIUIM_READ_TRANSPARENT_RESP_MSG, *PQMIUIM_READ_TRANSPARENT_RESP_MSG; - -typedef struct _QMIUIM_SET_CARD_SLOT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR slot; -} __attribute__ ((packed)) QMIUIM_SET_CARD_SLOT_REQ_MSG, *PQMIUIM_SET_CARD_SLOT_REQ_MSG; - -// ======================= COEX ============================== -#define QMI_COEX_GET_WWAN_STATE_REQ 0x22 -#define QMI_COEX_GET_WWAN_STATE_RESP 0x22 - -typedef struct { - - uint32_t freq; - /**< Band center frequency in MHz. */ - - uint32_t bandwidth; - /**< Bandwidth in MHz. */ -}coex_band_type_v01; /* Type */ - -typedef struct _QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND -{ - UCHAR TLVType; - USHORT TLVLength; - coex_band_type_v01 ul_band; - coex_band_type_v01 dl_band; -} __attribute__ ((packed)) QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND, *PQMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND; - - -typedef struct _QMUX_MSG -{ - QCQMUX_HDR QMUXHdr; - union - { - // Message Header - QCQMUX_MSG_HDR QMUXMsgHdr; - QCQMUX_MSG_HDR_RESP QMUXMsgHdrResp; - - // QMIWDS Message -#if 0 - QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG PacketServiceStatusReq; - QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG PacketServiceStatusRsp; - QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG PacketServiceStatusInd; - QMIWDS_EVENT_REPORT_IND_MSG EventReportInd; - QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG GetCurrChannelRateReq; - QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG GetCurrChannelRateRsp; - QMIWDS_GET_PKT_STATISTICS_REQ_MSG GetPktStatsReq; - QMIWDS_GET_PKT_STATISTICS_RESP_MSG GetPktStatsRsp; - QMIWDS_SET_EVENT_REPORT_REQ_MSG EventReportReq; - QMIWDS_SET_EVENT_REPORT_RESP_MSG EventReportRsp; -#endif - //#ifdef QC_IP_MODE - QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG GetRuntimeSettingsReq; - QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG GetRuntimeSettingsRsp; - //#endif // QC_IP_MODE - QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG SetClientIpFamilyPrefReq; - QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG SetClientIpFamilyPrefResp; - QMIWDS_SET_AUTO_CONNECT_REQ_MSG SetAutoConnectReq; -#if 0 - QMIWDS_GET_MIP_MODE_REQ_MSG GetMipModeReq; - QMIWDS_GET_MIP_MODE_RESP_MSG GetMipModeResp; -#endif - QMIWDS_START_NETWORK_INTERFACE_REQ_MSG StartNwInterfaceReq; - QMIWDS_START_NETWORK_INTERFACE_RESP_MSG StartNwInterfaceResp; - QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG StopNwInterfaceReq; - QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG StopNwInterfaceResp; - QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG GetDefaultSettingsReq; - QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG GetDefaultSettingsResp; - QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG ModifyProfileSettingsReq; - QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG ModifyProfileSettingsResp; - QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG GetProfileSettingsReq; - QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG CreatetProfileSettingsReq; -#if 0 - QMIWDS_GET_DATA_BEARER_REQ_MSG GetDataBearerReq; - QMIWDS_GET_DATA_BEARER_RESP_MSG GetDataBearerResp; - QMIWDS_DUN_CALL_INFO_REQ_MSG DunCallInfoReq; - QMIWDS_DUN_CALL_INFO_RESP_MSG DunCallInfoResp; -#endif - QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG BindMuxDataPortReq; - - // QMIDMS Messages -#if 0 - QMIDMS_GET_DEVICE_MFR_REQ_MSG GetDeviceMfrReq; - QMIDMS_GET_DEVICE_MFR_RESP_MSG GetDeviceMfrRsp; - QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG GetDeviceModeIdReq; - QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG GetDeviceModeIdRsp; - QMIDMS_GET_DEVICE_REV_ID_REQ_MSG GetDeviceRevIdReq; - QMIDMS_GET_DEVICE_REV_ID_RESP_MSG GetDeviceRevIdRsp; - QMIDMS_GET_MSISDN_REQ_MSG GetMsisdnReq; - QMIDMS_GET_MSISDN_RESP_MSG GetMsisdnRsp; - QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG GetDeviceSerialNumReq; - QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG GetDeviceSerialNumRsp; - QMIDMS_GET_DEVICE_CAP_REQ_MSG GetDeviceCapReq; - QMIDMS_GET_DEVICE_CAP_RESP_MSG GetDeviceCapResp; - QMIDMS_GET_BAND_CAP_REQ_MSG GetBandCapReq; - QMIDMS_GET_BAND_CAP_RESP_MSG GetBandCapRsp; - QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG GetActivatedStatusReq; - QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG GetActivatedStatusResp; - QMIDMS_GET_OPERATING_MODE_REQ_MSG GetOperatingModeReq; - QMIDMS_GET_OPERATING_MODE_RESP_MSG GetOperatingModeResp; -#endif - QMIDMS_SET_OPERATING_MODE_REQ_MSG SetOperatingModeReq; - QMIDMS_SET_OPERATING_MODE_RESP_MSG SetOperatingModeResp; -#if 0 - QMIDMS_UIM_GET_ICCID_REQ_MSG GetICCIDReq; - QMIDMS_UIM_GET_ICCID_RESP_MSG GetICCIDResp; - QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG ActivateAutomaticReq; - QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG ActivateAutomaticResp; - QMIDMS_ACTIVATE_MANUAL_REQ_MSG ActivateManualReq; - QMIDMS_ACTIVATE_MANUAL_RESP_MSG ActivateManualResp; -#endif - QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG UIMGetPinStatusReq; - QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG UIMGetPinStatusResp; - QMIDMS_UIM_VERIFY_PIN_REQ_MSG UIMVerifyPinReq; - QMIDMS_UIM_VERIFY_PIN_RESP_MSG UIMVerifyPinResp; -#if 0 - QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG UIMSetPinProtectionReq; - QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG UIMSetPinProtectionResp; - QMIDMS_UIM_CHANGE_PIN_REQ_MSG UIMChangePinReq; - QMIDMS_UIM_CHANGE_PIN_RESP_MSG UIMChangePinResp; - QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG UIMUnblockPinReq; - QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG UIMUnblockPinResp; - QMIDMS_SET_EVENT_REPORT_REQ_MSG DmsSetEventReportReq; - QMIDMS_SET_EVENT_REPORT_RESP_MSG DmsSetEventReportResp; - QMIDMS_EVENT_REPORT_IND_MSG DmsEventReportInd; -#endif - QMIDMS_UIM_GET_STATE_REQ_MSG UIMGetStateReq; - QMIDMS_UIM_GET_STATE_RESP_MSG UIMGetStateResp; - QMIDMS_UIM_GET_IMSI_REQ_MSG UIMGetIMSIReq; - QMIDMS_UIM_GET_IMSI_RESP_MSG UIMGetIMSIResp; -#if 0 - QMIDMS_UIM_GET_CK_STATUS_REQ_MSG UIMGetCkStatusReq; - QMIDMS_UIM_GET_CK_STATUS_RESP_MSG UIMGetCkStatusResp; - QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG UIMSetCkProtectionReq; - QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG UIMSetCkProtectionResp; - QMIDMS_UIM_UNBLOCK_CK_REQ_MSG UIMUnblockCkReq; - QMIDMS_UIM_UNBLOCK_CK_RESP_MSG UIMUnblockCkResp; -#endif - - // QMIQOS Messages -#if 1 - QMI_QOS_SET_EVENT_REPORT_REQ_MSG QosSetEventReportReq; - QMI_QOS_SET_EVENT_REPORT_RESP_MSG QosSetEventReportRsp; - QMI_QOS_SET_EVENT_REPORT_IND_MSG QosSetEventReportInd; - QMI_QOS_BIND_DATA_PORT_REQ_MSG QosBindDataPortReq; - QMI_QOS_BIND_DATA_PORT_RESP_MSG QosBindDataPortRsp; - QMI_QOS_INDICATION_REGISTER_REQ_MSG QosIndRegReq; - QMI_QOS_INDICATION_REGISTER_RESP_MSG QosIndRegRsp; - QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG QosGlobalQosFlowInd; - QMI_QOS_GET_QOS_INFO_REQ_MSG QosGetQosInfoReq; - QMI_QOS_GET_QOS_INFO_RESP_MSG QosGetQosInfoRsp; -#endif - - // QMIWMS Messages -#if 0 - QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG GetMessageProtocolReq; - QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG GetMessageProtocolResp; - QMIWMS_GET_SMSC_ADDRESS_REQ_MSG GetSMSCAddressReq; - QMIWMS_GET_SMSC_ADDRESS_RESP_MSG GetSMSCAddressResp; - QMIWMS_SET_SMSC_ADDRESS_REQ_MSG SetSMSCAddressReq; - QMIWMS_SET_SMSC_ADDRESS_RESP_MSG SetSMSCAddressResp; - QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG GetStoreMaxSizeReq; - QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG GetStoreMaxSizeResp; - QMIWMS_LIST_MESSAGES_REQ_MSG ListMessagesReq; - QMIWMS_LIST_MESSAGES_RESP_MSG ListMessagesResp; - QMIWMS_RAW_READ_REQ_MSG RawReadMessagesReq; - QMIWMS_RAW_READ_RESP_MSG RawReadMessagesResp; - QMIWMS_SET_EVENT_REPORT_REQ_MSG WmsSetEventReportReq; - QMIWMS_SET_EVENT_REPORT_RESP_MSG WmsSetEventReportResp; - QMIWMS_EVENT_REPORT_IND_MSG WmsEventReportInd; - QMIWMS_DELETE_REQ_MSG WmsDeleteReq; - QMIWMS_DELETE_RESP_MSG WmsDeleteResp; - QMIWMS_RAW_SEND_REQ_MSG RawSendMessagesReq; - QMIWMS_RAW_SEND_RESP_MSG RawSendMessagesResp; - QMIWMS_MODIFY_TAG_REQ_MSG WmsModifyTagReq; - QMIWMS_MODIFY_TAG_RESP_MSG WmsModifyTagResp; -#endif - - // QMINAS Messages -#if 0 - QMINAS_GET_HOME_NETWORK_REQ_MSG GetHomeNetworkReq; - QMINAS_GET_HOME_NETWORK_RESP_MSG GetHomeNetworkResp; - QMINAS_GET_PREFERRED_NETWORK_REQ_MSG GetPreferredNetworkReq; - QMINAS_GET_PREFERRED_NETWORK_RESP_MSG GetPreferredNetworkResp; - QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG GetForbiddenNetworkReq; - QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG GetForbiddenNetworkResp; - QMINAS_GET_SERVING_SYSTEM_REQ_MSG GetServingSystemReq; -#endif - QMINAS_GET_SERVING_SYSTEM_RESP_MSG GetServingSystemResp; - QMINAS_GET_SYS_INFO_RESP_MSG GetSysInfoResp; - QMINAS_SYS_INFO_IND_MSG NasSysInfoInd; -#if 0 - QMINAS_SERVING_SYSTEM_IND_MSG NasServingSystemInd; - QMINAS_SET_PREFERRED_NETWORK_REQ_MSG SetPreferredNetworkReq; - QMINAS_SET_PREFERRED_NETWORK_RESP_MSG SetPreferredNetworkResp; - QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG SetForbiddenNetworkReq; - QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG SetForbiddenNetworkResp; - QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG PerformNetworkScanReq; - QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG PerformNetworkScanResp; - QMINAS_INITIATE_NW_REGISTER_REQ_MSG InitiateNwRegisterReq; - QMINAS_INITIATE_NW_REGISTER_RESP_MSG InitiateNwRegisterResp; - QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG SetTechnologyPrefReq; - QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG SetTechnologyPrefResp; - QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG GetSignalStrengthReq; - QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG GetSignalStrengthResp; - QMINAS_SET_EVENT_REPORT_REQ_MSG SetEventReportReq; - QMINAS_SET_EVENT_REPORT_RESP_MSG SetEventReportResp; - QMINAS_EVENT_REPORT_IND_MSG NasEventReportInd; - QMINAS_GET_RF_BAND_INFO_REQ_MSG GetRFBandInfoReq; - QMINAS_GET_RF_BAND_INFO_RESP_MSG GetRFBandInfoResp; - QMINAS_INITIATE_ATTACH_REQ_MSG InitiateAttachReq; - QMINAS_INITIATE_ATTACH_RESP_MSG InitiateAttachResp; - QMINAS_GET_PLMN_NAME_REQ_MSG GetPLMNNameReq; - QMINAS_GET_PLMN_NAME_RESP_MSG GetPLMNNameResp; -#endif - - // QMIUIM Messages - QMIUIM_GET_CARD_STATUS_RESP_MSG UIMGetCardStatus; - QMIUIM_VERIFY_PIN_REQ_MSG UIMUIMVerifyPinReq; - QMIUIM_VERIFY_PIN_RESP_MSG UIMUIMVerifyPinResp; -#if 0 - QMIUIM_SET_PIN_PROTECTION_REQ_MSG UIMUIMSetPinProtectionReq; - QMIUIM_SET_PIN_PROTECTION_RESP_MSG UIMUIMSetPinProtectionResp; - QMIUIM_CHANGE_PIN_REQ_MSG UIMUIMChangePinReq; - QMIUIM_CHANGE_PIN_RESP_MSG UIMUIMChangePinResp; - QMIUIM_UNBLOCK_PIN_REQ_MSG UIMUIMUnblockPinReq; - QMIUIM_UNBLOCK_PIN_RESP_MSG UIMUIMUnblockPinResp; -#endif - QMIUIM_READ_TRANSPARENT_REQ_MSG UIMUIMReadTransparentReq; - QMIUIM_READ_TRANSPARENT_RESP_MSG UIMUIMReadTransparentResp; - QMIUIM_SET_CARD_SLOT_REQ_MSG UIMSetCardSlotReq; - - QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG SetLoopBackReq; - QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd; - }; -} __attribute__ ((packed)) QMUX_MSG, *PQMUX_MSG; - -typedef struct _QCQMIMSG { - QCQMI_HDR QMIHdr; - union { - QMICTL_MSG CTLMsg; - QMUX_MSG MUXMsg; - }; -} __attribute__ ((packed)) QCQMIMSG, *PQCQMIMSG; - -#pragma pack(pop) - -#endif // MPQMUX_H - diff --git a/quectel_cm_5G/src/Makefile b/quectel_cm_5G/src/Makefile deleted file mode 100644 index d895de1..0000000 --- a/quectel_cm_5G/src/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -ifneq ($(CROSS_COMPILE),) -CROSS-COMPILE:=$(CROSS_COMPILE) -endif -#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_mips_malta_defconfig/output/host/usr/bin/mips-buildroot-linux-uclibc- -#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_arm_vexpress_defconfig/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi- -#CROSS-COMPILE:=/workspace/buildroot-git/qemu_mips64_malta/output/host/usr/bin/mips-gnu-linux- -ifeq ($(CC),cc) -CC:=$(CROSS-COMPILE)gcc -endif -LD:=$(CROSS-COMPILE)ld - -QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c -QL_CM_SRC+=atc.c atchannel.c at_tok.c -#QL_CM_SRC+=qrtr.c rmnetctl.c -ifeq (1,1) -QL_CM_DHCP=udhcpc.c -else -LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c -DHCP=libmnl/dhcp/dhcpclient.c libmnl/dhcp/dhcpmsg.c libmnl/dhcp/packet.c -QL_CM_DHCP=udhcpc_netlink.c -QL_CM_DHCP+=${LIBMNL} -endif - -LDFLAGS += -lpthread -ldl -lrt - -release: clean qmi-proxy mbim-proxy atc-proxy #qrtr-proxy - $(CC) ${CFLAGS} ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM ${LDFLAGS} - -debug: clean - $(CC) ${CFLAGS} -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM -lpthread -ldl -lrt - -qmi-proxy: - $(CC) ${CFLAGS} quectel-qmi-proxy.c -o quectel-qmi-proxy ${LDFLAGS} - -mbim-proxy: - $(CC) ${CFLAGS} quectel-mbim-proxy.c -o quectel-mbim-proxy ${LDFLAGS} - -qrtr-proxy: - $(CC) ${CFLAGS} quectel-qrtr-proxy.c -o quectel-qrtr-proxy ${LDFLAGS} - -atc-proxy: - $(CC) ${CFLAGS} quectel-atc-proxy.c atchannel.c at_tok.c util.c -o quectel-atc-proxy ${LDFLAGS} - -clean: - rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy diff --git a/quectel_cm_5G/src/Makefile.am b/quectel_cm_5G/src/Makefile.am deleted file mode 100644 index 87e5266..0000000 --- a/quectel_cm_5G/src/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -bin_PROGRAMS = quectel-CM -QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c -QL_CM_SRC+=atc.c atchannel.c at_tok.c -#QL_CM_SRC+=qrtr.c rmnetctl.c -QL_CM_DHCP=udhcpc.c -if USE_QRTR -quectel_CM_CFLAGS = -DCONFIG_QRTR -QL_CM_SRC += qrtr.c rmnetctl.c -if USE_MSM_IPC -quectel_CM_CFLAGS += -DUSE_LINUX_MSM_IPC -endif -endif - -quectel_CM_SOURCES = ${QL_CM_SRC} ${QL_CM_DHCP} - -bin_PROGRAMS += quectel-qmi-proxy -quectel_qmi_proxy_SOURCES = quectel-qmi-proxy.c - -bin_PROGRAMS += quectel-mbim-proxy -quectel_mbim_proxy_SOURCES = quectel-mbim-proxy.c -LIBS = -l pthread -CFLAGS = -Wall -Wextra -Werror -O1 diff --git a/quectel_cm_5G/src/NOTICE b/quectel_cm_5G/src/NOTICE deleted file mode 100644 index 898aac4..0000000 --- a/quectel_cm_5G/src/NOTICE +++ /dev/null @@ -1,7 +0,0 @@ -This program is totally open souce code, and public domain software for customers of Quectel company. - -The APIs of QMI WWAMN interfaces are defined by Qualcomm. And this program complies with Qualcomm QMI WWAN interfaces specification. - -Customers are free to modify the source codes and redistribute them. - -For those who is not Quectel's customer, all rights are closed, and any copying and commercial development over this progrma is not allowed. diff --git a/quectel_cm_5G/src/QMIThread.c b/quectel_cm_5G/src/QMIThread.c deleted file mode 100644 index 40ea8d2..0000000 --- a/quectel_cm_5G/src/QMIThread.c +++ /dev/null @@ -1,2993 +0,0 @@ -/****************************************************************************** - @file QMIThread.c - @brief QMI WWAN connectivity manager. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include "QMIThread.h" -#include - -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a): (b)) -#endif - -#define qmi_rsp_check_and_return() do { \ - if (err < 0 || pResponse == NULL) { \ - dbg_time("%s err = %d", __func__, err); \ - return err; \ - } \ - pMUXMsg = &pResponse->MUXMsg; \ - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { \ - USHORT QMUXError = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); \ - dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, \ - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), QMUXError); \ - free(pResponse); \ - return QMUXError; \ - } \ -} while(0) - -#define qmi_rsp_check() do { \ - if (err < 0 || pResponse == NULL) { \ - dbg_time("%s err = %d", __func__, err); \ - return err; \ - } \ - pMUXMsg = &pResponse->MUXMsg; \ - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { \ - USHORT QMUXError = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); \ - dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, \ - le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), QMUXError); \ - } \ -} while(0) - -static uint32_t WdsConnectionIPv4Handle = 0; -static uint32_t WdsConnectionIPv6Handle = 0; -static int s_is_cdma = 0; -static int s_5g_type = WWAN_DATA_CLASS_NONE; -static int s_hdr_personality = 0; // 0x01-HRPD, 0x02-eHRPD -static char *qstrcpy(char *to, const char *from) { //no __strcpy_chk - char *save = to; - for (; (*to = *from) != '\0'; ++from, ++to); - return(save); -} - -static void uchar2char(char *dst_ptr, size_t dst_len, const UCHAR *src_ptr, size_t src_len) { - size_t copy = MIN(dst_len-1, src_len); - - if (copy) - memcpy(dst_ptr, src_ptr, copy); - dst_ptr[copy] = 0; -} - -static int s_9x07 = 1; - -typedef USHORT (*CUSTOMQMUX)(PQMUX_MSG pMUXMsg, void *arg); - -// To retrieve the ith (Index) TLV -PQMI_TLV_HDR GetTLV (PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType) { - int TLVFind = 0; - USHORT Length = le16_to_cpu(pQMUXMsgHdr->Length); - PQMI_TLV_HDR pTLVHdr = (PQMI_TLV_HDR)(pQMUXMsgHdr + 1); - - while (Length >= sizeof(QMI_TLV_HDR)) { - TLVFind++; - if (TLVType > 0x1000) { - if ((TLVFind + 0x1000) == TLVType) - return pTLVHdr; - } else if (pTLVHdr->TLVType == TLVType) { - return pTLVHdr; - } - - Length -= (le16_to_cpu((pTLVHdr->TLVLength)) + sizeof(QMI_TLV_HDR)); - pTLVHdr = (PQMI_TLV_HDR)(((UCHAR *)pTLVHdr) + le16_to_cpu(pTLVHdr->TLVLength) + sizeof(QMI_TLV_HDR)); - } - - return NULL; -} - -static USHORT GetQMUXTransactionId(void) { - static int TransactionId = 0; - if (++TransactionId > 0xFFFF) - TransactionId = 1; - return TransactionId; -} - -static PQCQMIMSG ComposeQMUXMsg(UCHAR QMIType, USHORT Type, CUSTOMQMUX customQmuxMsgFunction, void *arg) { - UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE]; - PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf; - int Length; - - memset(QMIBuf, 0x00, sizeof(QMIBuf)); - pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRequest->QMIHdr.CtlFlags = 0x00; - pRequest->QMIHdr.QMIType = QMIType; - - pRequest->MUXMsg.QMUXHdr.CtlFlags = QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD; - pRequest->MUXMsg.QMUXHdr.TransactionId = cpu_to_le16(GetQMUXTransactionId()); - pRequest->MUXMsg.QMUXMsgHdr.Type = cpu_to_le16(Type); - if (customQmuxMsgFunction) - pRequest->MUXMsg.QMUXMsgHdr.Length = cpu_to_le16(customQmuxMsgFunction(&pRequest->MUXMsg, arg) - sizeof(QCQMUX_MSG_HDR)); - else - pRequest->MUXMsg.QMUXMsgHdr.Length = cpu_to_le16(0x0000); - - pRequest->QMIHdr.Length = cpu_to_le16(le16_to_cpu(pRequest->MUXMsg.QMUXMsgHdr.Length) + sizeof(QCQMUX_MSG_HDR) + sizeof(QCQMUX_HDR) - + sizeof(QCQMI_HDR) - 1); - Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - - pRequest = (PQCQMIMSG)malloc(Length); - if (pRequest == NULL) { - dbg_time("%s fail to malloc", __func__); - } else { - memcpy(pRequest, QMIBuf, Length); - } - - return pRequest; -} - -#if 0 -static USHORT NasSetEventReportReq(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->SetEventReportReq.TLVType = 0x10; - pMUXMsg->SetEventReportReq.TLVLength = 0x04; - pMUXMsg->SetEventReportReq.ReportSigStrength = 0x00; - pMUXMsg->SetEventReportReq.NumTresholds = 2; - pMUXMsg->SetEventReportReq.TresholdList[0] = -113; - pMUXMsg->SetEventReportReq.TresholdList[1] = -50; - return sizeof(QMINAS_SET_EVENT_REPORT_REQ_MSG); -} - -static USHORT WdsSetEventReportReq(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->EventReportReq.TLVType = 0x10; // 0x10 -- current channel rate indicator - pMUXMsg->EventReportReq.TLVLength = 0x0001; // 1 - pMUXMsg->EventReportReq.Mode = 0x00; // 0-do not report; 1-report when rate changes - - pMUXMsg->EventReportReq.TLV2Type = 0x11; // 0x11 - pMUXMsg->EventReportReq.TLV2Length = 0x0005; // 5 - pMUXMsg->EventReportReq.StatsPeriod = 0x00; // seconds between reports; 0-do not report - pMUXMsg->EventReportReq.StatsMask = 0x000000ff; // - - pMUXMsg->EventReportReq.TLV3Type = 0x12; // 0x12 -- current data bearer indicator - pMUXMsg->EventReportReq.TLV3Length = 0x0001; // 1 - pMUXMsg->EventReportReq.Mode3 = 0x01; // 0-do not report; 1-report when changes - - pMUXMsg->EventReportReq.TLV4Type = 0x13; // 0x13 -- dormancy status indicator - pMUXMsg->EventReportReq.TLV4Length = 0x0001; // 1 - pMUXMsg->EventReportReq.DormancyStatus = 0x00; // 0-do not report; 1-report when changes - return sizeof(QMIWDS_SET_EVENT_REPORT_REQ_MSG); -} - -static USHORT DmsSetEventReportReq(PQMUX_MSG pMUXMsg) { - PPIN_STATUS pPinState = (PPIN_STATUS)(&pMUXMsg->DmsSetEventReportReq + 1); - PUIM_STATE pUimState = (PUIM_STATE)(pPinState + 1); - // Pin State - pPinState->TLVType = 0x12; - pPinState->TLVLength = 0x01; - pPinState->ReportPinState = 0x01; - // UIM State - pUimState->TLVType = 0x15; - pUimState->TLVLength = 0x01; - pUimState->UIMState = 0x01; - return sizeof(QMIDMS_SET_EVENT_REPORT_REQ_MSG) + sizeof(PIN_STATUS) + sizeof(UIM_STATE); -} -#endif - -static USHORT WdsStartNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) { - PQMIWDS_TECHNOLOGY_PREFERECE pTechPref; - PQMIWDS_AUTH_PREFERENCE pAuthPref; - PQMIWDS_USERNAME pUserName; - PQMIWDS_PASSWD pPasswd; - PQMIWDS_APNNAME pApnName; - PQMIWDS_IP_FAMILY_TLV pIpFamily; - USHORT TLVLength = 0; - UCHAR *pTLV; - PROFILE_T *profile = (PROFILE_T *)arg; - const char *profile_user = profile->user; - const char *profile_password = profile->password; - int profile_auth = profile->auth; - - if (s_is_cdma && (profile_user == NULL || profile_user[0] == '\0') && (profile_password == NULL || profile_password[0] == '\0')) { - profile_user = "ctnet@mycdma.cn"; - profile_password = "vnet.mobi"; - profile_auth = 2; //chap - } - - pTLV = (UCHAR *)(&pMUXMsg->StartNwInterfaceReq + 1); - pMUXMsg->StartNwInterfaceReq.Length = 0; - - // Set technology Preferece - pTechPref = (PQMIWDS_TECHNOLOGY_PREFERECE)(pTLV + TLVLength); - pTechPref->TLVType = 0x30; - pTechPref->TLVLength = cpu_to_le16(0x01); - if (s_is_cdma == 0) - pTechPref->TechPreference = 0x01; - else - pTechPref->TechPreference = 0x02; - TLVLength +=(le16_to_cpu(pTechPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - // Set APN Name - if (profile->apn && !s_is_cdma) { //cdma no apn - pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength); - pApnName->TLVType = 0x14; - pApnName->TLVLength = cpu_to_le16(strlen(profile->apn)); - qstrcpy((char *)&pApnName->ApnName, profile->apn); - TLVLength +=(le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set User Name - if (profile_user) { - pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength); - pUserName->TLVType = 0x17; - pUserName->TLVLength = cpu_to_le16(strlen(profile_user)); - qstrcpy((char *)&pUserName->UserName, profile_user); - TLVLength += (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Password - if (profile_password) { - pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength); - pPasswd->TLVType = 0x18; - pPasswd->TLVLength = cpu_to_le16(strlen(profile_password)); - qstrcpy((char *)&pPasswd->Passwd, profile_password); - TLVLength += (le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Auth Protocol - if (profile_user && profile_password) { - pAuthPref = (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength); - pAuthPref->TLVType = 0x16; - pAuthPref->TLVLength = cpu_to_le16(0x01); - pAuthPref->AuthPreference = profile_auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2 - TLVLength += (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Add IP Family Preference - pIpFamily = (PQMIWDS_IP_FAMILY_TLV)(pTLV + TLVLength); - pIpFamily->TLVType = 0x19; - pIpFamily->TLVLength = cpu_to_le16(0x01); - pIpFamily->IpFamily = profile->curIpFamily; - TLVLength += (le16_to_cpu(pIpFamily->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - //Set Profile Index - if (profile->pdp && !s_is_cdma) { //cdma only support one pdp, so no need to set profile index - PQMIWDS_PROFILE_IDENTIFIER pProfileIndex = (PQMIWDS_PROFILE_IDENTIFIER)(pTLV + TLVLength); - pProfileIndex->TLVLength = cpu_to_le16(0x01); - pProfileIndex->TLVType = 0x31; - pProfileIndex->ProfileIndex = profile->pdp; - if (s_is_cdma && s_hdr_personality == 0x02) { - pProfileIndex->TLVType = 0x32; //profile_index_3gpp2 - pProfileIndex->ProfileIndex = 101; - } - TLVLength += (le16_to_cpu(pProfileIndex->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - return sizeof(QMIWDS_START_NETWORK_INTERFACE_REQ_MSG) + TLVLength; -} - -static USHORT WdsStopNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->StopNwInterfaceReq.TLVType = 0x01; - pMUXMsg->StopNwInterfaceReq.TLVLength = cpu_to_le16(0x04); - if (*((int *)arg) == IpFamilyV4) - pMUXMsg->StopNwInterfaceReq.Handle = cpu_to_le32(WdsConnectionIPv4Handle); - else - pMUXMsg->StopNwInterfaceReq.Handle = cpu_to_le32(WdsConnectionIPv6Handle); - return sizeof(QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG); -} - -static USHORT WdsSetClientIPFamilyPref(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->SetClientIpFamilyPrefReq.TLVType = 0x01; - pMUXMsg->SetClientIpFamilyPrefReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->SetClientIpFamilyPrefReq.IpPreference = *((UCHAR *)arg); - return sizeof(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG); -} - -static USHORT WdsSetAutoConnect(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->SetAutoConnectReq.TLVType = 0x01; - pMUXMsg->SetAutoConnectReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->SetAutoConnectReq.autoconnect_setting = *((UCHAR *)arg); - return sizeof(QMIWDS_SET_AUTO_CONNECT_REQ_MSG); -} - -enum peripheral_ep_type { - DATA_EP_TYPE_RESERVED = 0x0, - DATA_EP_TYPE_HSIC = 0x1, - DATA_EP_TYPE_HSUSB = 0x2, - DATA_EP_TYPE_PCIE = 0x3, - DATA_EP_TYPE_EMBEDDED = 0x4, - DATA_EP_TYPE_BAM_DMUX = 0x5, -}; - -static USHORT WdsSetQMUXBindMuxDataPort(PQMUX_MSG pMUXMsg, void *arg) { - QMAP_SETTING *qmap_settings = (QMAP_SETTING *)arg; - - pMUXMsg->BindMuxDataPortReq.TLVType = 0x10; - pMUXMsg->BindMuxDataPortReq.TLVLength = cpu_to_le16(0x08); - pMUXMsg->BindMuxDataPortReq.ep_type = cpu_to_le32(qmap_settings->ep_type); - pMUXMsg->BindMuxDataPortReq.iface_id = cpu_to_le32(qmap_settings->iface_id); - pMUXMsg->BindMuxDataPortReq.TLV2Type = 0x11; - pMUXMsg->BindMuxDataPortReq.TLV2Length = cpu_to_le16(0x01); - pMUXMsg->BindMuxDataPortReq.MuxId = qmap_settings->MuxId; - pMUXMsg->BindMuxDataPortReq.TLV3Type = 0x13; - pMUXMsg->BindMuxDataPortReq.TLV3Length = cpu_to_le16(0x04); - pMUXMsg->BindMuxDataPortReq.client_type = cpu_to_le32(1); //WDS_CLIENT_TYPE_TETHERED - - return sizeof(QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG); -} - -static int qmap_version = 0x05; -static USHORT WdaSetDataFormat(PQMUX_MSG pMUXMsg, void *arg) { - QMAP_SETTING *qmap_settings = (QMAP_SETTING *)arg; - - if (qmap_settings->rx_urb_size == 0) { - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS pWdsAdminQosTlv; - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV linkProto; - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV dlTlp; - - pWdsAdminQosTlv = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS)(&pMUXMsg->QMUXMsgHdr + 1); - pWdsAdminQosTlv->TLVType = 0x10; - pWdsAdminQosTlv->TLVLength = cpu_to_le16(0x0001); - pWdsAdminQosTlv->QOSSetting = 0; /* no-QOS header */ - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)(pWdsAdminQosTlv + 1); - linkProto->TLVType = 0x11; - linkProto->TLVLength = cpu_to_le16(4); - linkProto->Value = cpu_to_le32(0x01); /* Set Ethernet mode */ - - dlTlp = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)(linkProto + 1);; - dlTlp->TLVType = 0x13; - dlTlp->TLVLength = cpu_to_le16(4); - dlTlp->Value = cpu_to_le32(0x00); - - if (sizeof(*linkProto) != 7 ) - dbg_time("%s sizeof(*linkProto) = %zu, is not 7!", __func__, sizeof(*linkProto) ); - - return sizeof(QCQMUX_MSG_HDR) + sizeof(*pWdsAdminQosTlv) + sizeof(*linkProto) + sizeof(*dlTlp); - } - else { - //Indicates whether the Quality of Service(QOS) data format is used by the client. - pMUXMsg->SetDataFormatReq.QosDataFormatTlv.TLVType = 0x10; - pMUXMsg->SetDataFormatReq.QosDataFormatTlv.TLVLength = cpu_to_le16(0x0001); - pMUXMsg->SetDataFormatReq.QosDataFormatTlv.QOSSetting = 0; /* no-QOS header */ - - //Underlying Link Layer Protocol - pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVType = 0x11; - pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.Value = cpu_to_le32(0x02); /* Set IP mode */ - - //Uplink (UL) data aggregation protocol to be used for uplink data transfer. - pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVType = 0x12; - pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //UL QMAP is enabled - - //Downlink (DL) data aggregation protocol to be used for downlink data transfer - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVType = 0x13; - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //DL QMAP is enabled - - //Maximum number of datagrams in a single aggregated packet on downlink - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.TLVType = 0x15; - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(qmap_settings->rx_urb_size/512); - - //Maximum size in bytes of a single aggregated packet allowed on downlink - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVType = 0x16; - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(qmap_settings->rx_urb_size); - - //Peripheral End Point ID - pMUXMsg->SetDataFormatReq.epTlv.TLVType = 0x17; - pMUXMsg->SetDataFormatReq.epTlv.TLVLength = cpu_to_le16(8); - pMUXMsg->SetDataFormatReq.epTlv.ep_type = cpu_to_le32(qmap_settings->ep_type); - pMUXMsg->SetDataFormatReq.epTlv.iface_id = cpu_to_le32(qmap_settings->iface_id); - -#ifdef QUECTEL_UL_DATA_AGG - if (!qmap_settings->ul_data_aggregation_max_datagrams) { - return ((size_t)&((QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG *)0)->DlMinimumPassingTlv); - } - - //Maximum number of datagrams in a single aggregated packet on uplink - pMUXMsg->SetDataFormatReq.DlMinimumPassingTlv.TLVType = 0x19; - pMUXMsg->SetDataFormatReq.DlMinimumPassingTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.DlMinimumPassingTlv.Value = cpu_to_le32(qmap_settings->dl_minimum_padding); - - //Maximum number of datagrams in a single aggregated packet on uplink - pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxDatagramsTlv.TLVType = 0x1B; - pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(qmap_settings->ul_data_aggregation_max_datagrams); - - //Maximum size in bytes of a single aggregated packet allowed on downlink - pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxSizeTlv.TLVType = 0x1C; - pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(qmap_settings->ul_data_aggregation_max_size); -#endif - - return sizeof(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG); - } -} - -#ifdef CONFIG_SIM -static USHORT DmsUIMVerifyPinReqSend(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->UIMVerifyPinReq.TLVType = 0x01; - pMUXMsg->UIMVerifyPinReq.PINID = 0x01; //Pin1, not Puk - pMUXMsg->UIMVerifyPinReq.PINLen = strlen((const char *)arg); - qstrcpy((char *)&pMUXMsg->UIMVerifyPinReq.PINValue, ((const char *)arg)); - pMUXMsg->UIMVerifyPinReq.TLVLength = cpu_to_le16(2 + strlen((const char *)arg)); - return sizeof(QMIDMS_UIM_VERIFY_PIN_REQ_MSG) + (strlen((const char *)arg) - 1); -} - -static USHORT UimVerifyPinReqSend(PQMUX_MSG pMUXMsg, void *arg) -{ - pMUXMsg->UIMUIMVerifyPinReq.TLVType = 0x01; - pMUXMsg->UIMUIMVerifyPinReq.TLVLength = cpu_to_le16(0x02); - pMUXMsg->UIMUIMVerifyPinReq.Session_Type = 0x00; - pMUXMsg->UIMUIMVerifyPinReq.Aid_Len = 0x00; - pMUXMsg->UIMUIMVerifyPinReq.TLV2Type = 0x02; - pMUXMsg->UIMUIMVerifyPinReq.TLV2Length = cpu_to_le16(2 + strlen((const char *)arg)); - pMUXMsg->UIMUIMVerifyPinReq.PINID = 0x01; //Pin1, not Puk - pMUXMsg->UIMUIMVerifyPinReq.PINLen= strlen((const char *)arg); - qstrcpy((char *)&pMUXMsg->UIMUIMVerifyPinReq.PINValue, ((const char *)arg)); - return sizeof(QMIUIM_VERIFY_PIN_REQ_MSG) + (strlen((const char *)arg) - 1); -} - -#ifdef CONFIG_IMSI_ICCID -static USHORT UimReadTransparentIMSIReqSend(PQMUX_MSG pMUXMsg, void *arg) { - PREAD_TRANSPARENT_TLV pReadTransparent; - - pMUXMsg->UIMUIMReadTransparentReq.TLVType = 0x01; - pMUXMsg->UIMUIMReadTransparentReq.TLVLength = cpu_to_le16(0x02); - if (!strcmp((char *)arg, "EF_ICCID")) { - pMUXMsg->UIMUIMReadTransparentReq.Session_Type = 0x06; - pMUXMsg->UIMUIMReadTransparentReq.Aid_Len = 0x00; - - pMUXMsg->UIMUIMReadTransparentReq.TLV2Type = 0x02; - pMUXMsg->UIMUIMReadTransparentReq.file_id = cpu_to_le16(0x2FE2); - pMUXMsg->UIMUIMReadTransparentReq.path_len = 0x02; - pMUXMsg->UIMUIMReadTransparentReq.path[0] = 0x00; - pMUXMsg->UIMUIMReadTransparentReq.path[1] = 0x3F; - } - else if(!strcmp((char *)arg, "EF_IMSI")) { - pMUXMsg->UIMUIMReadTransparentReq.Session_Type = 0x00; - pMUXMsg->UIMUIMReadTransparentReq.Aid_Len = 0x00; - - pMUXMsg->UIMUIMReadTransparentReq.TLV2Type = 0x02; - pMUXMsg->UIMUIMReadTransparentReq.file_id = cpu_to_le16(0x6F07); - pMUXMsg->UIMUIMReadTransparentReq.path_len = 0x04; - pMUXMsg->UIMUIMReadTransparentReq.path[0] = 0x00; - pMUXMsg->UIMUIMReadTransparentReq.path[1] = 0x3F; - pMUXMsg->UIMUIMReadTransparentReq.path[2] = 0xFF; - pMUXMsg->UIMUIMReadTransparentReq.path[3] = 0x7F; - } - - pMUXMsg->UIMUIMReadTransparentReq.TLV2Length = cpu_to_le16(3 + pMUXMsg->UIMUIMReadTransparentReq.path_len); - - pReadTransparent = (PREAD_TRANSPARENT_TLV)(&pMUXMsg->UIMUIMReadTransparentReq.path[pMUXMsg->UIMUIMReadTransparentReq.path_len]); - pReadTransparent->TLVType = 0x03; - pReadTransparent->TLVLength = cpu_to_le16(0x04); - pReadTransparent->Offset = cpu_to_le16(0x00); - pReadTransparent->Length = cpu_to_le16(0x00); - - return (sizeof(QMIUIM_READ_TRANSPARENT_REQ_MSG) + pMUXMsg->UIMUIMReadTransparentReq.path_len + sizeof(READ_TRANSPARENT_TLV)); -} -#endif -#endif - -#ifdef CONFIG_APN -static USHORT WdsCreateProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) { - PROFILE_T *profile = (PROFILE_T *)arg; - pMUXMsg->CreatetProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG) - 4); - pMUXMsg->CreatetProfileSettingsReq.TLVType = 0x01; - pMUXMsg->CreatetProfileSettingsReq.TLVLength = cpu_to_le16(0x01); - pMUXMsg->CreatetProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 - pMUXMsg->CreatetProfileSettingsReq.TLV2Type = 0x25; - pMUXMsg->CreatetProfileSettingsReq.TLV2Length = cpu_to_le16(0x01); - pMUXMsg->CreatetProfileSettingsReq.pdp_context = profile->pdp; // 0 ~ 3GPP, 1 ~ 3GPP2 - return sizeof(QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG); -} - -static USHORT WdsGetProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) { - PROFILE_T *profile = (PROFILE_T *)arg; - pMUXMsg->GetProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG) - 4); - pMUXMsg->GetProfileSettingsReq.TLVType = 0x01; - pMUXMsg->GetProfileSettingsReq.TLVLength = cpu_to_le16(0x02); - pMUXMsg->GetProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 - pMUXMsg->GetProfileSettingsReq.ProfileIndex = profile->pdp; - return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG); -} - -static USHORT WdsModifyProfileSettingsReq(PQMUX_MSG pMUXMsg, void *arg) { - USHORT TLVLength = 0; - UCHAR *pTLV; - PROFILE_T *profile = (PROFILE_T *)arg; - PQMIWDS_PDPTYPE pPdpType; - - pMUXMsg->ModifyProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG) - 4); - pMUXMsg->ModifyProfileSettingsReq.TLVType = 0x01; - pMUXMsg->ModifyProfileSettingsReq.TLVLength = cpu_to_le16(0x02); - pMUXMsg->ModifyProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 - pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->pdp; - - pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1); - - pPdpType = (PQMIWDS_PDPTYPE)(pTLV + TLVLength); - pPdpType->TLVType = 0x11; - pPdpType->TLVLength = cpu_to_le16(0x01); - pPdpType->PdpType = profile->iptype; - TLVLength +=(le16_to_cpu(pPdpType->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - - // Set APN Name - if (profile->apn) { - PQMIWDS_APNNAME pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength); - pApnName->TLVType = 0x14; - pApnName->TLVLength = cpu_to_le16(strlen(profile->apn)); - qstrcpy((char *)&pApnName->ApnName, profile->apn); - TLVLength +=(le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set User Name - if (profile->user) { - PQMIWDS_USERNAME pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength); - pUserName->TLVType = 0x1B; - pUserName->TLVLength = cpu_to_le16(strlen(profile->user)); - qstrcpy((char *)&pUserName->UserName, profile->user); - TLVLength += (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Password - if (profile->password) { - PQMIWDS_PASSWD pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength); - pPasswd->TLVType = 0x1C; - pPasswd->TLVLength = cpu_to_le16(strlen(profile->password)); - qstrcpy((char *)&pPasswd->Passwd, profile->password); - TLVLength +=(le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - // Set Auth Protocol - if (profile->user && profile->password) { - PQMIWDS_AUTH_PREFERENCE pAuthPref = (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength); - pAuthPref->TLVType = 0x1D; - pAuthPref->TLVLength = cpu_to_le16(0x01); - pAuthPref->AuthPreference = profile->auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2 - TLVLength += (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); - } - - return sizeof(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG) + TLVLength; -} -#endif - -static USHORT WdsGetRuntimeSettingReq(PQMUX_MSG pMUXMsg, void *arg) -{ - (void)arg; - pMUXMsg->GetRuntimeSettingsReq.TLVType = 0x10; - pMUXMsg->GetRuntimeSettingsReq.TLVLength = cpu_to_le16(0x04); - // the following mask also applies to IPV6 - pMUXMsg->GetRuntimeSettingsReq.Mask = cpu_to_le32(QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR) | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_SV_ADDR | - QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_DOM_NAME; - - return sizeof(QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG); -} - -static PQCQMIMSG s_pRequest; -static PQCQMIMSG s_pResponse; - -static int is_response(const PQCQMIMSG pRequest, const PQCQMIMSG pResponse) { - if ((pRequest->QMIHdr.QMIType == pResponse->QMIHdr.QMIType) - && (pRequest->QMIHdr.ClientId == pResponse->QMIHdr.ClientId)) { - USHORT requestTID, responseTID; - if (pRequest->QMIHdr.QMIType == QMUX_TYPE_CTL) { - requestTID = pRequest->CTLMsg.QMICTLMsgHdr.TransactionId; - responseTID = pResponse->CTLMsg.QMICTLMsgHdr.TransactionId; - } else { - requestTID = le16_to_cpu(pRequest->MUXMsg.QMUXHdr.TransactionId); - responseTID = le16_to_cpu(pResponse->MUXMsg.QMUXHdr.TransactionId); - } - return (requestTID == responseTID); - } - return 0; -} - -int (*qmidev_send)(PQCQMIMSG pRequest); - -int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned msecs, const char *funcname) { - int ret; - - if (!pRequest) - return -EINVAL; - - pthread_mutex_lock(&cm_command_mutex); - - if (ppResponse) - *ppResponse = NULL; - - dump_qmi(pRequest, le16_to_cpu(pRequest->QMIHdr.Length) + 1); - - s_pRequest = pRequest; - s_pResponse = NULL; - - ret = qmidev_send(pRequest); - - if (ret == 0) { - ret = pthread_cond_timeout_np(&cm_command_cond, &cm_command_mutex, msecs); - if (!ret) { - if (s_pResponse && ppResponse) { - *ppResponse = s_pResponse; - } else { - if (s_pResponse) { - free(s_pResponse); - s_pResponse = NULL; - } - } - } else { - dbg_time("%s message timeout", funcname); - } - } - - pthread_mutex_unlock(&cm_command_mutex); - - return ret; -} - -void QmiThreadRecvQMI(PQCQMIMSG pResponse) { - pthread_mutex_lock(&cm_command_mutex); - if (pResponse == NULL) { - if (s_pRequest) { - free(s_pRequest); - s_pRequest = NULL; - s_pResponse = NULL; - pthread_cond_signal(&cm_command_cond); - } - pthread_mutex_unlock(&cm_command_mutex); - return; - } - dump_qmi(pResponse, le16_to_cpu(pResponse->QMIHdr.Length) + 1); - if (s_pRequest && is_response(s_pRequest, pResponse)) { - free(s_pRequest); - s_pRequest = NULL; - s_pResponse = malloc(le16_to_cpu(pResponse->QMIHdr.Length) + 1); - if (s_pResponse != NULL) { - memcpy(s_pResponse, pResponse, le16_to_cpu(pResponse->QMIHdr.Length) + 1); - } - pthread_cond_signal(&cm_command_cond); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_CTL) - && (le16_to_cpu(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMICTLType == QMICTL_REVOKE_CLIENT_ID_IND))) { - qmidevice_send_event_to_main(MODEM_REPORT_RESET_EVENT); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_NAS) - && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMINAS_SERVING_SYSTEM_IND)) { - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_WDS) - && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMIWDS_GET_PKT_SRVC_STATUS_IND)) { - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_NAS) - && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMINAS_SYS_INFO_IND)) { - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_WDS_ADMIN) - && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMI_WDA_SET_LOOPBACK_CONFIG_IND)) { - qmidevice_send_event_to_main_ext(RIL_UNSOL_LOOPBACK_CONFIG_IND, - &pResponse->MUXMsg.SetLoopBackInd, sizeof(pResponse->MUXMsg.SetLoopBackInd)); - } -#ifdef CONFIG_REG_QOS_IND - else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_QOS) - && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMI_QOS_GLOBAL_QOS_FLOW_IND)) { - UINT qos_id = 0; - UCHAR new_flow = ql_get_global_qos_flow_ind_qos_id(pResponse, &qos_id); - if (qos_id != 0 && new_flow == 1) - qmidevice_send_event_to_main_ext(RIL_UNSOL_GLOBAL_QOS_FLOW_IND_QOS_ID, &qos_id, sizeof(qos_id)); -#ifdef CONFIG_GET_QOS_DATA_RATE - if (new_flow) { - ULONG64 max_data_rate[2] = {0}; - if (ql_get_global_qos_flow_ind_data_rate(pResponse, (void *)max_data_rate) == 0){} - } -#endif - } -#endif - else { - if (debug_qmi) - dbg_time("nobody care this qmi msg!!"); - } - pthread_mutex_unlock(&cm_command_mutex); -} - -#ifdef CONFIG_COEX_WWAN_STATE -static int requestGetCoexWWANState(void) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PQMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND pLteBand; - static QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND oldLteBand = {-1, -1}; - int err; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_COEX, QMI_COEX_GET_WWAN_STATE_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - - if (err < 0 || pResponse == NULL) { - dbg_time("%s err = %d", __func__, err); - return err; - } - - pMUXMsg = &pResponse->MUXMsg; - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { - dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)); - err = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); - free(pResponse); - return err; - } - pLteBand = (PQMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - - if (pLteBand && memcmp(pLteBand, &oldLteBand, sizeof(oldLteBand))) { - oldLteBand = *pLteBand; - dbg_time("%s ul_freq %d ul_bandwidth %d", __func__, le32_to_cpu(pLteBand->ul_band.freq), le32_to_cpu(pLteBand->ul_band.bandwidth)); - dbg_time("%s dl_freq %d dl_bandwidth %d", __func__, le32_to_cpu(pLteBand->dl_band.freq), le32_to_cpu(pLteBand->dl_band.bandwidth)); - } - free(pResponse); - return 0; -} -#endif - -static int requestSetEthMode(PROFILE_T *profile) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse = NULL; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV linkProto; - UCHAR IpPreference; - UCHAR autoconnect_setting = 0; - QMAP_SETTING qmap_settings = {0}; - - qmap_settings.size = sizeof(qmap_settings); - - if (profile->qmap_mode) { - profile->rawIP = 1; - s_9x07 = profile->rawIP; - - qmap_settings.MuxId = profile->muxid; - - if (profile->hardware_interface == HARDWARE_PCIE) { //SDX20_PCIE - qmap_settings.rx_urb_size = profile->qmap_size; //SDX24&SDX55 support 32KB - qmap_settings.ep_type = DATA_EP_TYPE_PCIE; - qmap_settings.iface_id = 0x04; - } - else { // for MDM9x07&MDM9x40&SDX20 USB - qmap_settings.rx_urb_size = profile->qmap_size; //SDX24&SDX55 support 32KB - qmap_settings.ep_type = DATA_EP_TYPE_HSUSB; - qmap_settings.iface_id = 0x04; - } - - qmap_settings.ul_data_aggregation_max_datagrams = 11; //by test result, 11 can get best TPUT - qmap_settings.ul_data_aggregation_max_size = 8*1024; - qmap_settings.dl_minimum_padding = 0; //no effect when register to real netowrk - if(profile->qmap_version != 0x09) - profile->qmap_version = 0x05; - - qmap_version = profile->qmap_version; - if (profile->rmnet_info.size) { - qmap_settings.rx_urb_size = profile->rmnet_info.rx_urb_size; - qmap_settings.ep_type = profile->rmnet_info.ep_type; - qmap_settings.iface_id = profile->rmnet_info.iface_id; - qmap_settings.dl_minimum_padding = profile->rmnet_info.dl_minimum_padding; - qmap_version = profile->rmnet_info.qmap_version; - } - - if (!profile->wda_client) { - if (qmidev_is_gobinet(profile->qmichannel)) { - //when QMAP enabled, set data format in GobiNet driver - } - else if (profile->proxy[0]) { - /* the first running 'quectel-cm' had alloc wda client and set data format, - so we can ingore to set data format here. */ - } - goto skip_WdaSetDataFormat; - } - } - - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_ADMIN, QMIWDS_ADMIN_SET_DATA_FORMAT_REQ, WdaSetDataFormat, (void *)&qmap_settings); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (linkProto != NULL) { - profile->rawIP = (le32_to_cpu(linkProto->Value) == 2); - s_9x07 = profile->rawIP; //MDM90x7 only support RAW IP, do not support Eth - } - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x16); - if (linkProto != NULL && profile->qmap_mode) { - qmap_settings.rx_urb_size = le32_to_cpu(linkProto->Value); - dbg_time("qmap_settings.rx_urb_size = %u", qmap_settings.rx_urb_size); //must same as rx_urb_size defined in GobiNet&qmi_wwan driver - } - -#ifdef QUECTEL_UL_DATA_AGG - if (qmap_settings.ul_data_aggregation_max_datagrams) - { - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x17); - if (linkProto != NULL) { - qmap_settings.ul_data_aggregation_max_datagrams = MIN(qmap_settings.ul_data_aggregation_max_datagrams, le32_to_cpu(linkProto->Value)); - dbg_time("qmap_settings.ul_data_aggregation_max_datagrams = %u", qmap_settings.ul_data_aggregation_max_datagrams); - } - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x18); - if (linkProto != NULL) { - qmap_settings.ul_data_aggregation_max_size = MIN(qmap_settings.ul_data_aggregation_max_size, le32_to_cpu(linkProto->Value)); - dbg_time("qmap_settings.ul_data_aggregation_max_size = %u", qmap_settings.ul_data_aggregation_max_size); - } - - linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1A); - if (linkProto != NULL) { - qmap_settings.dl_minimum_padding = le32_to_cpu(linkProto->Value); - dbg_time("qmap_settings.dl_minimum_padding = %u", qmap_settings.dl_minimum_padding); - } - - if (qmap_settings.ul_data_aggregation_max_datagrams > 1) { - ql_set_driver_qmap_setting(profile, &qmap_settings); - } - } -#endif - - free(pResponse); - -skip_WdaSetDataFormat: - if (profile->enable_ipv4) { - if (profile->qmapnet_adapter[0]) { - // bind wds mux data port - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_BIND_MUX_DATA_PORT_REQ , WdsSetQMUXBindMuxDataPort, (void *)&qmap_settings); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) free(pResponse); - } - - // set ipv4 - IpPreference = IpFamilyV4; - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, WdsSetClientIPFamilyPref, (void *)&IpPreference); - err = QmiThreadSendQMI(pRequest, &pResponse); - if (pResponse) free(pResponse); - } - - if (profile->enable_ipv6) { - if (profile->qmapnet_adapter[0]) { - // bind wds ipv6 mux data port - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_IPV6, QMIWDS_BIND_MUX_DATA_PORT_REQ , WdsSetQMUXBindMuxDataPort, (void *)&qmap_settings); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) free(pResponse); - } - - // set ipv6 - IpPreference = IpFamilyV6; - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_IPV6, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, WdsSetClientIPFamilyPref, (void *)&IpPreference); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) free(pResponse); - } - - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_SET_AUTO_CONNECT_REQ , WdsSetAutoConnect, (void *)&autoconnect_setting); - QmiThreadSendQMI(pRequest, &pResponse); - if (pResponse) free(pResponse); - - return 0; -} - -#ifdef CONFIG_SIM -static int requestGetPINStatus(SIM_Status *pSIMStatus) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIDMS_UIM_PIN_STATUS pPin1Status = NULL; - //PQMIDMS_UIM_PIN_STATUS pPin2Status = NULL; - - if (s_9x07) - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_GET_CARD_STATUS_REQ, NULL, NULL); - else - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_GET_PIN_STATUS_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pPin1Status = (PQMIDMS_UIM_PIN_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - //pPin2Status = (PQMIDMS_UIM_PIN_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - - if (pPin1Status != NULL) { - if (pPin1Status->PINStatus == QMI_PIN_STATUS_NOT_VERIF) { - *pSIMStatus = SIM_PIN; - } else if (pPin1Status->PINStatus == QMI_PIN_STATUS_BLOCKED) { - *pSIMStatus = SIM_PUK; - } else if (pPin1Status->PINStatus == QMI_PIN_STATUS_PERM_BLOCKED) { - *pSIMStatus = SIM_BAD; - } - } - - free(pResponse); - return 0; -} - -static int requestGetSIMStatus(SIM_Status *pSIMStatus) { //RIL_REQUEST_GET_SIM_STATUS - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - const char * SIM_Status_String[] = { - "SIM_ABSENT", - "SIM_NOT_READY", - "SIM_READY", /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ - "SIM_PIN", - "SIM_PUK", - "SIM_NETWORK_PERSONALIZATION" - }; - - if (s_9x07) - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_GET_CARD_STATUS_REQ, NULL, NULL); - else - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_GET_STATE_REQ, NULL, NULL); - - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - *pSIMStatus = SIM_ABSENT; - if (s_9x07) - { - PQMIUIM_CARD_STATUS pCardStatus = NULL; - PQMIUIM_PIN_STATE pPINState = NULL; - UCHAR CardState = 0x01; - UCHAR PIN1State = QMI_PIN_STATUS_NOT_VERIF; - //UCHAR PIN1Retries; - //UCHAR PUK1Retries; - //UCHAR PIN2State; - //UCHAR PIN2Retries; - //UCHAR PUK2Retries; - - pCardStatus = (PQMIUIM_CARD_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if (pCardStatus != NULL) - { - pPINState = (PQMIUIM_PIN_STATE)((PUCHAR)pCardStatus + sizeof(QMIUIM_CARD_STATUS) + pCardStatus->AIDLength); - CardState = pCardStatus->CardState; - if (CardState == UIM_CARD_STATE_PRESENT) { - if (pPINState->UnivPIN == 1) - { - PIN1State = pCardStatus->UPINState; - //PIN1Retries = pCardStatus->UPINRetries; - //PUK1Retries = pCardStatus->UPUKRetries; - } - else - { - PIN1State = pPINState->PIN1State; - //PIN1Retries = pPINState->PIN1Retries; - //PUK1Retries = pPINState->PUK1Retries; - } - //PIN2State = pPINState->PIN2State; - //PIN2Retries = pPINState->PIN2Retries; - //PUK2Retries = pPINState->PUK2Retries; - } - } - - *pSIMStatus = SIM_ABSENT; - if ((CardState == 0x01) && ((PIN1State == QMI_PIN_STATUS_VERIFIED)|| (PIN1State == QMI_PIN_STATUS_DISABLED))) - { - *pSIMStatus = SIM_READY; - } - else if (CardState == 0x01) - { - if (PIN1State == QMI_PIN_STATUS_NOT_VERIF) - { - *pSIMStatus = SIM_PIN; - } - if ( PIN1State == QMI_PIN_STATUS_BLOCKED) - { - *pSIMStatus = SIM_PUK; - } - else if (PIN1State == QMI_PIN_STATUS_PERM_BLOCKED) - { - *pSIMStatus = SIM_BAD; - } - else if (PIN1State == QMI_PIN_STATUS_NOT_INIT || PIN1State == QMI_PIN_STATUS_VERIFIED || PIN1State == QMI_PIN_STATUS_DISABLED) - { - *pSIMStatus = SIM_READY; - } - } - else if (CardState == 0x00 || CardState == 0x02) - { - } - else - { - } - } - else - { - //UIM state. Values: - // 0x00 UIM initialization completed - // 0x01 UIM is locked or the UIM failed - // 0x02 UIM is not present - // 0x03 Reserved - // 0xFF UIM state is currently - //unavailable - if (pResponse->MUXMsg.UIMGetStateResp.UIMState == 0x00) { - *pSIMStatus = SIM_READY; - } else if (pResponse->MUXMsg.UIMGetStateResp.UIMState == 0x01) { - *pSIMStatus = SIM_ABSENT; - err = requestGetPINStatus(pSIMStatus); - } else if ((pResponse->MUXMsg.UIMGetStateResp.UIMState == 0x02) || (pResponse->MUXMsg.UIMGetStateResp.UIMState == 0xFF)) { - *pSIMStatus = SIM_ABSENT; - } else { - *pSIMStatus = SIM_ABSENT; - } - } - dbg_time("%s SIMStatus: %s", __func__, SIM_Status_String[*pSIMStatus]); - - free(pResponse); - - return 0; -} - -static int requestEnterSimPin(const char *pPinCode) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - if (s_9x07) - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_VERIFY_PIN_REQ, UimVerifyPinReqSend, (void *)pPinCode); - else - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_VERIFY_PIN_REQ, DmsUIMVerifyPinReqSend, (void *)pPinCode); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - free(pResponse); - return 0; -} -#endif - -#ifdef CONFIG_IMSI_ICCID -static int requestGetICCID(void) { //RIL_REQUEST_GET_IMSI - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PQMIUIM_CONTENT pUimContent; - int err; - - if (s_9x07) { - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_READ_TRANSPARENT_REQ, UimReadTransparentIMSIReqSend, (void *)"EF_ICCID"); - err = QmiThreadSendQMI(pRequest, &pResponse); - } else { - return 0; - } - qmi_rsp_check_and_return(); - - pUimContent = (PQMIUIM_CONTENT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pUimContent != NULL) { - static char DeviceICCID[32] = {'\0'}; - int i = 0, j = 0; - - for (i = 0, j = 0; i < le16_to_cpu(pUimContent->content_len); ++i) { - char charmaps[] = "0123456789ABCDEF"; - - DeviceICCID[j++] = charmaps[(pUimContent->content[i] & 0x0F)]; - DeviceICCID[j++] = charmaps[((pUimContent->content[i] & 0xF0) >> 0x04)]; - } - DeviceICCID[j] = '\0'; - - dbg_time("%s DeviceICCID: %s", __func__, DeviceICCID); - } - - free(pResponse); - return 0; -} - -static int requestGetIMSI(void) { //RIL_REQUEST_GET_IMSI - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PQMIUIM_CONTENT pUimContent; - int err; - - if (s_9x07) { - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_READ_TRANSPARENT_REQ, UimReadTransparentIMSIReqSend, (void *)"EF_IMSI"); - err = QmiThreadSendQMI(pRequest, &pResponse); - } else { - return 0; - } - qmi_rsp_check_and_return(); - - pUimContent = (PQMIUIM_CONTENT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pUimContent != NULL) { - static char DeviceIMSI[32] = {'\0'}; - int i = 0, j = 0; - - for (i = 0, j = 0; i < le16_to_cpu(pUimContent->content[0]); ++i) { - if (i != 0) - DeviceIMSI[j++] = (pUimContent->content[i+1] & 0x0F) + '0'; - DeviceIMSI[j++] = ((pUimContent->content[i+1] & 0xF0) >> 0x04) + '0'; - } - DeviceIMSI[j] = '\0'; - - dbg_time("%s DeviceIMSI: %s", __func__, DeviceIMSI); - } - - free(pResponse); - return 0; -} -#endif - -#if 1 -static void quectel_convert_cdma_mcc_2_ascii_mcc( USHORT *p_mcc, USHORT mcc ) -{ - unsigned int d1, d2, d3, buf = mcc + 111; - - if ( mcc == 0x3FF ) // wildcard - { - *p_mcc = 3; - } - else - { - d3 = buf % 10; - buf = ( d3 == 0 ) ? (buf-10)/10 : buf/10; - - d2 = buf % 10; - buf = ( d2 == 0 ) ? (buf-10)/10 : buf/10; - - d1 = ( buf == 10 ) ? 0 : buf; - -//dbg_time("d1:%d, d2:%d,d3:%d",d1,d2,d3); - if ( d1<10 && d2<10 && d3<10 ) - { - *p_mcc = d1*100+d2*10+d3; -#if 0 - *(p_mcc+0) = '0' + d1; - *(p_mcc+1) = '0' + d2; - *(p_mcc+2) = '0' + d3; -#endif - } - else - { - //dbg_time( "invalid digits %d %d %d", d1, d2, d3 ); - *p_mcc = 0; - } - } -} - -static void quectel_convert_cdma_mnc_2_ascii_mnc( USHORT *p_mnc, USHORT imsi_11_12) -{ - unsigned int d1, d2, buf = imsi_11_12 + 11; - - if ( imsi_11_12 == 0x7F ) // wildcard - { - *p_mnc = 7; - } - else - { - d2 = buf % 10; - buf = ( d2 == 0 ) ? (buf-10)/10 : buf/10; - - d1 = ( buf == 10 ) ? 0 : buf; - - if ( d1<10 && d2<10 ) - { - *p_mnc = d1*10 + d2; - } - else - { - //dbg_time( "invalid digits %d %d", d1, d2, 0 ); - *p_mnc = 0; - } - } -} - -static int requestGetHomeNetwork(USHORT *p_mcc, USHORT *p_mnc, USHORT *p_sid, USHORT *p_nid) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PHOME_NETWORK pHomeNetwork; - PHOME_NETWORK_SYSTEMID pHomeNetworkSystemID; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_HOME_NETWORK_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pHomeNetwork = (PHOME_NETWORK)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (pHomeNetwork && p_mcc && p_mnc ) { - *p_mcc = le16_to_cpu(pHomeNetwork->MobileCountryCode); - *p_mnc = le16_to_cpu(pHomeNetwork->MobileNetworkCode); - //dbg_time("%s MobileCountryCode: %d, MobileNetworkCode: %d", __func__, *pMobileCountryCode, *pMobileNetworkCode); - } - - pHomeNetworkSystemID = (PHOME_NETWORK_SYSTEMID)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if (pHomeNetworkSystemID && p_sid && p_nid) { - *p_sid = le16_to_cpu(pHomeNetworkSystemID->SystemID); //china-hefei: sid 14451 - *p_nid = le16_to_cpu(pHomeNetworkSystemID->NetworkID); - //dbg_time("%s SystemID: %d, NetworkID: %d", __func__, *pSystemID, *pNetworkID); - } - - free(pResponse); - - return 0; -} -#endif - -#if 0 -// Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length. -static const char * MCCMNC_CODES_HAVING_3DIGITS_MNC[] = { - "302370", "302720", "310260", - "405025", "405026", "405027", "405028", "405029", "405030", "405031", "405032", - "405033", "405034", "405035", "405036", "405037", "405038", "405039", "405040", - "405041", "405042", "405043", "405044", "405045", "405046", "405047", "405750", - "405751", "405752", "405753", "405754", "405755", "405756", "405799", "405800", - "405801", "405802", "405803", "405804", "405805", "405806", "405807", "405808", - "405809", "405810", "405811", "405812", "405813", "405814", "405815", "405816", - "405817", "405818", "405819", "405820", "405821", "405822", "405823", "405824", - "405825", "405826", "405827", "405828", "405829", "405830", "405831", "405832", - "405833", "405834", "405835", "405836", "405837", "405838", "405839", "405840", - "405841", "405842", "405843", "405844", "405845", "405846", "405847", "405848", - "405849", "405850", "405851", "405852", "405853", "405875", "405876", "405877", - "405878", "405879", "405880", "405881", "405882", "405883", "405884", "405885", - "405886", "405908", "405909", "405910", "405911", "405912", "405913", "405914", - "405915", "405916", "405917", "405918", "405919", "405920", "405921", "405922", - "405923", "405924", "405925", "405926", "405927", "405928", "405929", "405930", - "405931", "405932", "502142", "502143", "502145", "502146", "502147", "502148" -}; - -static const char * MCC_CODES_HAVING_3DIGITS_MNC[] = { - "302", //Canada - "310", //United States of America - "311", //United States of America - "312", //United States of America - "313", //United States of America - "314", //United States of America - "315", //United States of America - "316", //United States of America - "334", //Mexico - "338", //Jamaica - "342", //Barbados - "344", //Antigua and Barbuda - "346", //Cayman Islands - "348", //British Virgin Islands - "365", //Anguilla - "708", //Honduras (Republic of) - "722", //Argentine Republic - "732" //Colombia (Republic of) -}; - -int requestGetIMSI(const char **pp_imsi, USHORT *pMobileCountryCode, USHORT *pMobileNetworkCode) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - if (pp_imsi) *pp_imsi = NULL; - if (pMobileCountryCode) *pMobileCountryCode = 0; - if (pMobileNetworkCode) *pMobileNetworkCode = 0; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_GET_IMSI_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - if (pMUXMsg->UIMGetIMSIResp.TLV2Type == 0x01 && le16_to_cpu(pMUXMsg->UIMGetIMSIResp.TLV2Length) >= 5) { - int mnc_len = 2; - unsigned i; - char tmp[4]; - - if (pp_imsi) *pp_imsi = strndup((const char *)(&pMUXMsg->UIMGetIMSIResp.IMSI), le16_to_cpu(pMUXMsg->UIMGetIMSIResp.TLV2Length)); - - for (i = 0; i < sizeof(MCCMNC_CODES_HAVING_3DIGITS_MNC)/sizeof(MCCMNC_CODES_HAVING_3DIGITS_MNC[0]); i++) { - if (!strncmp((const char *)(&pMUXMsg->UIMGetIMSIResp.IMSI), MCCMNC_CODES_HAVING_3DIGITS_MNC[i], 6)) { - mnc_len = 3; - break; - } - } - if (mnc_len == 2) { - for (i = 0; i < sizeof(MCC_CODES_HAVING_3DIGITS_MNC)/sizeof(MCC_CODES_HAVING_3DIGITS_MNC[0]); i++) { - if (!strncmp((const char *)(&pMUXMsg->UIMGetIMSIResp.IMSI), MCC_CODES_HAVING_3DIGITS_MNC[i], 3)) { - mnc_len = 3; - break; - } - } - } - - tmp[0] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[0]; - tmp[1] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[1]; - tmp[2] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[2]; - tmp[3] = 0; - if (pMobileCountryCode) *pMobileCountryCode = atoi(tmp); - tmp[0] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[3]; - tmp[1] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[4]; - tmp[2] = 0; - if (mnc_len == 3) { - tmp[2] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[6]; - } - if (pMobileNetworkCode) *pMobileNetworkCode = atoi(tmp); - } - - free(pResponse); - - return 0; -} -#endif - -static struct wwan_data_class_str class2str[] = { - {WWAN_DATA_CLASS_NONE, "UNKNOWN"}, - {WWAN_DATA_CLASS_GPRS, "GPRS"}, - {WWAN_DATA_CLASS_EDGE, "EDGE"}, - {WWAN_DATA_CLASS_UMTS, "UMTS"}, - {WWAN_DATA_CLASS_HSDPA, "HSDPA"}, - {WWAN_DATA_CLASS_HSUPA, "HSUPA"}, - {WWAN_DATA_CLASS_LTE, "LTE"}, - {WWAN_DATA_CLASS_5G_NSA, "5G_NSA"}, - {WWAN_DATA_CLASS_5G_SA, "5G_SA"}, - {WWAN_DATA_CLASS_1XRTT, "1XRTT"}, - {WWAN_DATA_CLASS_1XEVDO, "1XEVDO"}, - {WWAN_DATA_CLASS_1XEVDO_REVA, "1XEVDO_REVA"}, - {WWAN_DATA_CLASS_1XEVDV, "1XEVDV"}, - {WWAN_DATA_CLASS_3XRTT, "3XRTT"}, - {WWAN_DATA_CLASS_1XEVDO_REVB, "1XEVDO_REVB"}, - {WWAN_DATA_CLASS_UMB, "UMB"}, - {WWAN_DATA_CLASS_CUSTOM, "CUSTOM"}, -}; - -static const char *wwan_data_class2str(ULONG class) -{ - unsigned int i = 0; - for (i = 0; i < sizeof(class2str)/sizeof(class2str[0]); i++) { - if (class2str[i].class == class) { - return class2str[i].str; - } - } - return "UNKNOWN"; -} - -static USHORT char2ushort(UCHAR str[3]) { - int i; - char temp[4]; - USHORT ret= 0; - - memcpy(temp, str, 3); - temp[3] = '\0'; - - for (i = 0; i < 4; i++) { - if ((UCHAR)temp[i] == 0xFF) { - temp[i] = '\0'; - } - } - ret = (USHORT)atoi(temp); - - return ret; -} - -static int requestRegistrationState2(UCHAR *pPSAttachedState) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - USHORT MobileCountryCode = 0; - USHORT MobileNetworkCode = 0; - const char *pDataCapStr = "UNKNOW"; - LONG remainingLen; - PSERVICE_STATUS_INFO pServiceStatusInfo; - int is_lte = 0; - PCDMA_SYSTEM_INFO pCdmaSystemInfo; - PHDR_SYSTEM_INFO pHdrSystemInfo; - PGSM_SYSTEM_INFO pGsmSystemInfo; - PWCDMA_SYSTEM_INFO pWcdmaSystemInfo; - PLTE_SYSTEM_INFO pLteSystemInfo; - PTDSCDMA_SYSTEM_INFO pTdscdmaSystemInfo; - PNR5G_SYSTEM_INFO pNr5gSystemInfo; - UCHAR DeviceClass = 0; - ULONG DataCapList = 0; - - /* Additional LTE System Info - Availability of Dual connectivity of E-UTRA with NR5G */ - uint8_t endc_available_valid = 0; /**< Must be set to true if endc_available is being passed */ - uint8_t endc_available = 0x00; - /**< - Upper layer indication in LTE SIB2. Values: \n - - 0x00 -- 5G Not available \n - - 0x01 -- 5G Available - - */ - /* Additional LTE System Info - DCNR restriction Info */ - uint8_t restrict_dcnr_valid = 0; /**< Must be set to true if restrict_dcnr is being passed */ - uint8_t restrict_dcnr = 0x01; - /**< - DCNR restriction in NAS attach/TAU accept. Values: \n - - 0x00 -- Not restricted \n - - 0x01 -- Restricted - */ - - *pPSAttachedState = 0; - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SYS_INFO_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pServiceStatusInfo = (PSERVICE_STATUS_INFO)(((PCHAR)&pMUXMsg->GetSysInfoResp) + QCQMUX_MSG_HDR_SIZE); - remainingLen = le16_to_cpu(pMUXMsg->GetSysInfoResp.Length); - - s_is_cdma = 0; - s_5g_type = WWAN_DATA_CLASS_NONE; - s_hdr_personality = 0; - while (remainingLen > 0) { - switch (pServiceStatusInfo->TLVType) { - case 0x10: // CDMA - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_1XRTT| - WWAN_DATA_CLASS_1XEVDO| - WWAN_DATA_CLASS_1XEVDO_REVA| - WWAN_DATA_CLASS_1XEVDV| - WWAN_DATA_CLASS_1XEVDO_REVB; - DeviceClass = DEVICE_CLASS_CDMA; - s_is_cdma = (0 == is_lte); - } - break; - case 0x11: // HDR - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_3XRTT| - WWAN_DATA_CLASS_UMB; - DeviceClass = DEVICE_CLASS_CDMA; - s_is_cdma = (0 == is_lte); - } - break; - case 0x12: // GSM - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_GPRS| - WWAN_DATA_CLASS_EDGE; - DeviceClass = DEVICE_CLASS_GSM; - } - break; - case 0x13: // WCDMA - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_UMTS; - DeviceClass = DEVICE_CLASS_GSM; - } - break; - case 0x14: // LTE - if (pServiceStatusInfo->SrvStatus == 0x02) { - DataCapList = WWAN_DATA_CLASS_LTE; - DeviceClass = DEVICE_CLASS_GSM; - is_lte = 1; - s_is_cdma = 0; - } - break; - case 0x4A: // NR5G Service Status Info - if (pServiceStatusInfo->SrvStatus == NAS_SYS_SRV_STATUS_SRV_V01) { - DataCapList |= WWAN_DATA_CLASS_5G_SA; - DeviceClass = DEVICE_CLASS_GSM; - is_lte = 1; - s_is_cdma = 0; - } - break; - case 0x4B: // NR5G System Info - pNr5gSystemInfo = (PNR5G_SYSTEM_INFO)pServiceStatusInfo; - if (pNr5gSystemInfo->srv_domain_valid == 0x01) { - if (pNr5gSystemInfo->srv_domain & SYS_SRV_DOMAIN_PS_ONLY_V01) { - *pPSAttachedState = 1; - } - } - - if (pNr5gSystemInfo->network_id_valid == 0x01) { - MobileCountryCode = (USHORT)char2ushort(pNr5gSystemInfo->MCC); - MobileNetworkCode = (USHORT)char2ushort(pNr5gSystemInfo->MNC); - } - break; - case 0x4E: //Additional LTE System Info - Availability of Dual Connectivity of E-UTRA with NR5G - endc_available_valid = 1; - endc_available = pServiceStatusInfo->SrvStatus; - break; - - case 0x4F: //Additional LTE System Info - DCNR restriction Info - restrict_dcnr_valid = 1; - restrict_dcnr = pServiceStatusInfo->SrvStatus; - break; - - case 0x24: // TDSCDMA - if (pServiceStatusInfo->SrvStatus == 0x02) { - pDataCapStr = "TD-SCDMA"; - } - break; - case 0x15: // CDMA - // CDMA_SYSTEM_INFO - pCdmaSystemInfo = (PCDMA_SYSTEM_INFO)pServiceStatusInfo; - if (pCdmaSystemInfo->SrvDomainValid == 0x01) { - if (pCdmaSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#if 0 - if (pCdmaSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pCdmaSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#endif - if (pCdmaSystemInfo->NetworkIdValid == 0x01) { - MobileCountryCode = (USHORT)char2ushort(pCdmaSystemInfo->MCC); - MobileNetworkCode = (USHORT)char2ushort(pCdmaSystemInfo->MNC); - } - break; - case 0x16: // HDR - // HDR_SYSTEM_INFO - pHdrSystemInfo = (PHDR_SYSTEM_INFO)pServiceStatusInfo; - if (pHdrSystemInfo->SrvDomainValid == 0x01) { - if (pHdrSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#if 0 - if (pHdrSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pHdrSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - s_is_cdma = (0 == is_lte); - } - } -#endif - if (*pPSAttachedState && pHdrSystemInfo->HdrPersonalityValid == 0x01) { - if (pHdrSystemInfo->HdrPersonality == 0x03) - s_hdr_personality = 0x02; - //else if (pHdrSystemInfo->HdrPersonality == 0x02) - // s_hdr_personality = 0x01; - } - USHORT cmda_mcc = 0, cdma_mnc = 0; - if(!requestGetHomeNetwork(&cmda_mcc, &cdma_mnc,NULL, NULL) && cmda_mcc) { - quectel_convert_cdma_mcc_2_ascii_mcc(&MobileCountryCode, cmda_mcc); - quectel_convert_cdma_mnc_2_ascii_mnc(&MobileNetworkCode, cdma_mnc); - } - break; - case 0x17: // GSM - // GSM_SYSTEM_INFO - pGsmSystemInfo = (PGSM_SYSTEM_INFO)pServiceStatusInfo; - if (pGsmSystemInfo->SrvDomainValid == 0x01) { - if (pGsmSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - } - } -#if 0 - if (pGsmSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pGsmSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - } - } -#endif - if (pGsmSystemInfo->NetworkIdValid == 0x01) { - MobileCountryCode = (USHORT)char2ushort(pGsmSystemInfo->MCC); - MobileNetworkCode = (USHORT)char2ushort(pGsmSystemInfo->MNC); - } - break; - case 0x18: // WCDMA - // WCDMA_SYSTEM_INFO - pWcdmaSystemInfo = (PWCDMA_SYSTEM_INFO)pServiceStatusInfo; - if (pWcdmaSystemInfo->SrvDomainValid == 0x01) { - if (pWcdmaSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - } - } -#if 0 - if (pWcdmaSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pWcdmaSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - } - } -#endif - if (pWcdmaSystemInfo->NetworkIdValid == 0x01) { - MobileCountryCode = (USHORT)char2ushort(pWcdmaSystemInfo->MCC); - MobileNetworkCode = (USHORT)char2ushort(pWcdmaSystemInfo->MNC); - } - break; - case 0x19: // LTE_SYSTEM_INFO - // LTE_SYSTEM_INFO - pLteSystemInfo = (PLTE_SYSTEM_INFO)pServiceStatusInfo; - if (pLteSystemInfo->SrvDomainValid == 0x01) { - if (pLteSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - is_lte = 1; - s_is_cdma = 0; - } - } -#if 0 - if (pLteSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pLteSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - is_lte = 1; - s_is_cdma = 0; - } - } -#endif - if (pLteSystemInfo->NetworkIdValid == 0x01) { - MobileCountryCode = (USHORT)char2ushort(pLteSystemInfo->MCC); - MobileNetworkCode = (USHORT)char2ushort(pLteSystemInfo->MNC); - } - break; - case 0x25: // TDSCDMA - // TDSCDMA_SYSTEM_INFO - pTdscdmaSystemInfo = (PTDSCDMA_SYSTEM_INFO)pServiceStatusInfo; - if (pTdscdmaSystemInfo->SrvDomainValid == 0x01) { - if (pTdscdmaSystemInfo->SrvDomain & 0x02) { - *pPSAttachedState = 1; - } - } -#if 0 - if (pTdscdmaSystemInfo->SrvCapabilityValid == 0x01) { - *pPSAttachedState = 0; - if (pTdscdmaSystemInfo->SrvCapability & 0x02) { - *pPSAttachedState = 1; - } - } -#endif - if (pTdscdmaSystemInfo->NetworkIdValid == 0x01) { - MobileCountryCode = (USHORT)char2ushort(pTdscdmaSystemInfo->MCC); - MobileNetworkCode = (USHORT)char2ushort(pTdscdmaSystemInfo->MNC); - } - break; - default: - break; - } /* switch (pServiceStatusInfo->TLYType) */ - - remainingLen -= (le16_to_cpu(pServiceStatusInfo->TLVLength) + 3); - pServiceStatusInfo = (PSERVICE_STATUS_INFO)((PCHAR)&pServiceStatusInfo->TLVLength + le16_to_cpu(pServiceStatusInfo->TLVLength) + sizeof(USHORT)); - } /* while (remainingLen > 0) */ - - if (DataCapList & WWAN_DATA_CLASS_LTE) { - if (endc_available_valid && restrict_dcnr_valid) { - if (endc_available && !restrict_dcnr) { - DataCapList |= WWAN_DATA_CLASS_5G_NSA; - } - } - } - - if (DeviceClass == DEVICE_CLASS_CDMA) { - if (s_hdr_personality == 2) { - pDataCapStr = s_hdr_personality == 2 ? "eHRPD" : "HRPD"; - } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO_REVB) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO_REVB); - } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO_REVA) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO_REVA); - } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO); - } else if (DataCapList & WWAN_DATA_CLASS_1XRTT) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XRTT); - } else if (DataCapList & WWAN_DATA_CLASS_3XRTT) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_3XRTT); - } else if (DataCapList & WWAN_DATA_CLASS_UMB) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_UMB); - } - } else { - if (DataCapList & WWAN_DATA_CLASS_5G_SA) { - s_5g_type = WWAN_DATA_CLASS_5G_SA; - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_5G_SA); - } else if (DataCapList & WWAN_DATA_CLASS_5G_NSA) { - s_5g_type = WWAN_DATA_CLASS_5G_NSA; - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_5G_NSA); - } else if (DataCapList & WWAN_DATA_CLASS_LTE) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_LTE); - } else if ((DataCapList & WWAN_DATA_CLASS_HSDPA) && (DataCapList & WWAN_DATA_CLASS_HSUPA)) { - pDataCapStr = "HSDPA_HSUPA"; - } else if (DataCapList & WWAN_DATA_CLASS_HSDPA) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_HSDPA); - } else if (DataCapList & WWAN_DATA_CLASS_HSUPA) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_HSUPA); - } else if (DataCapList & WWAN_DATA_CLASS_UMTS) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_UMTS); - } else if (DataCapList & WWAN_DATA_CLASS_EDGE) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_EDGE); - } else if (DataCapList & WWAN_DATA_CLASS_GPRS) { - pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_GPRS); - } - } - - dbg_time("%s MCC: %d, MNC: %d, PS: %s, DataCap: %s", __func__, - MobileCountryCode, MobileNetworkCode, (*pPSAttachedState == 1) ? "Attached" : "Detached" , pDataCapStr); - - free(pResponse); - - return 0; -} - -static int requestRegistrationState(UCHAR *pPSAttachedState) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMINAS_CURRENT_PLMN_MSG pCurrentPlmn; - PSERVING_SYSTEM pServingSystem; - PQMINAS_DATA_CAP pDataCap; - USHORT MobileCountryCode = 0; - USHORT MobileNetworkCode = 0; - const char *pDataCapStr = "UNKNOW"; - - if (s_9x07) { - return requestRegistrationState2(pPSAttachedState); - } - - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SERVING_SYSTEM_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pCurrentPlmn = (PQMINAS_CURRENT_PLMN_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - if (pCurrentPlmn) { - MobileCountryCode = le16_to_cpu(pCurrentPlmn->MobileCountryCode); - MobileNetworkCode = le16_to_cpu(pCurrentPlmn->MobileNetworkCode); - } - - *pPSAttachedState = 0; - pServingSystem = (PSERVING_SYSTEM)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (pServingSystem) { - //Packet-switched domain attach state of the mobile. - //0x00 PS_UNKNOWN ?Unknown or not applicable - //0x01 PS_ATTACHED ?Attached - //0x02 PS_DETACHED ?Detached - *pPSAttachedState = pServingSystem->RegistrationState; - if (pServingSystem->RegistrationState == 0x01) //0x01 ?C REGISTERED ?C Registered with a network - *pPSAttachedState = pServingSystem->PSAttachedState; - else { - //MobileCountryCode = MobileNetworkCode = 0; - *pPSAttachedState = 0x02; - } - } - - pDataCap = (PQMINAS_DATA_CAP)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pDataCap && pDataCap->DataCapListLen) { - UCHAR *DataCap = &pDataCap->DataCap; - if (pDataCap->DataCapListLen == 2) { - if ((DataCap[0] == 0x06) && ((DataCap[1] == 0x08) || (DataCap[1] == 0x0A))) - DataCap[0] = DataCap[1]; - } - switch (DataCap[0]) { - case 0x01: pDataCapStr = "GPRS"; break; - case 0x02: pDataCapStr = "EDGE"; break; - case 0x03: pDataCapStr = "HSDPA"; break; - case 0x04: pDataCapStr = "HSUPA"; break; - case 0x05: pDataCapStr = "UMTS"; break; - case 0x06: pDataCapStr = "1XRTT"; break; - case 0x07: pDataCapStr = "1XEVDO"; break; - case 0x08: pDataCapStr = "1XEVDO_REVA"; break; - case 0x09: pDataCapStr = "GPRS"; break; - case 0x0A: pDataCapStr = "1XEVDO_REVB"; break; - case 0x0B: pDataCapStr = "LTE"; break; - case 0x0C: pDataCapStr = "HSDPA"; break; - case 0x0D: pDataCapStr = "HSDPA"; break; - default: pDataCapStr = "UNKNOW"; break; - } - } - - if (pServingSystem && pServingSystem->RegistrationState == 0x01 && pServingSystem->InUseRadioIF && pServingSystem->RadioIF == 0x09) { - pDataCapStr = "TD-SCDMA"; - } - - s_is_cdma = 0; - if (pServingSystem && pServingSystem->RegistrationState == 0x01 && pServingSystem->InUseRadioIF && (pServingSystem->RadioIF == 0x01 || pServingSystem->RadioIF == 0x02)) { - USHORT cmda_mcc = 0, cdma_mnc = 0; - s_is_cdma = 1; - if(!requestGetHomeNetwork(&cmda_mcc, &cdma_mnc,NULL, NULL) && cmda_mcc) { - quectel_convert_cdma_mcc_2_ascii_mcc(&MobileCountryCode, cmda_mcc); - quectel_convert_cdma_mnc_2_ascii_mnc(&MobileNetworkCode, cdma_mnc); - } - if (1) { - PQCQMUX_TLV pTLV = (PQCQMUX_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x23); - if (pTLV) - s_hdr_personality = pTLV->Value; - else - s_hdr_personality = 0; - if (s_hdr_personality == 2) - pDataCapStr = "eHRPD"; - } - } - - dbg_time("%s MCC: %d, MNC: %d, PS: %s, DataCap: %s", __func__, - MobileCountryCode, MobileNetworkCode, (*pPSAttachedState == 1) ? "Attached" : "Detached" , pDataCapStr); - - free(pResponse); - - return 0; -} - -static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_PKT_SRVC_TLV pPktSrvc; - UCHAR oldConnectionStatus = *pConnectionStatus; - UCHAR QMIType = (curIpFamily == IpFamilyV4) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_GET_PKT_SRVC_STATUS_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - pPktSrvc = (PQMIWDS_PKT_SRVC_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (pPktSrvc) { - *pConnectionStatus = pPktSrvc->ConnectionStatus; - if ((le16_to_cpu(pPktSrvc->TLVLength) == 2) && (pPktSrvc->ReconfigReqd == 0x01)) - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - - if (*pConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) { - if (curIpFamily == IpFamilyV4) - WdsConnectionIPv4Handle = 0; - else - WdsConnectionIPv6Handle = 0; - } - - if (oldConnectionStatus != *pConnectionStatus || debug_qmi) { - dbg_time("%s %sConnectionStatus: %s", __func__, (curIpFamily == IpFamilyV4) ? "IPv4" : "IPv6", - (*pConnectionStatus == QWDS_PKT_DATA_CONNECTED) ? "CONNECTED" : "DISCONNECTED"); - } - - free(pResponse); - return 0; -} - -static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err = 0; - UCHAR QMIType = (curIpFamily == IpFamilyV4) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - -//DualIPSupported means can get ipv4 & ipv6 address at the same time, one wds for ipv4, the other wds for ipv6 - profile->curIpFamily = curIpFamily; - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_START_NETWORK_INTERFACE_REQ, WdsStartNwInterfaceReq, profile); - err = QmiThreadSendQMITimeout(pRequest, &pResponse, 120 * 1000, __func__); - qmi_rsp_check(); - - if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { - PQMI_TLV_HDR pTLVHdr; - - pTLVHdr = GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if (pTLVHdr) { - uint16_t *data16 = (uint16_t *)(pTLVHdr+1); - uint16_t call_end_reason = le16_to_cpu(data16[0]); - dbg_time("call_end_reason is %d", call_end_reason); - } - - pTLVHdr = GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (pTLVHdr) { - uint16_t *data16 = (uint16_t *)(pTLVHdr+1); - uint16_t call_end_reason_type = le16_to_cpu(data16[0]); - uint16_t verbose_call_end_reason = le16_to_cpu(data16[1]); - - dbg_time("call_end_reason_type is %d", call_end_reason_type); - dbg_time("call_end_reason_verbose is %d", verbose_call_end_reason); - } - - free(pResponse); - return le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); - } - - if (curIpFamily == IpFamilyV4) { - WdsConnectionIPv4Handle = le32_to_cpu(pResponse->MUXMsg.StartNwInterfaceResp.Handle); - dbg_time("%s WdsConnectionIPv4Handle: 0x%08x", __func__, WdsConnectionIPv4Handle); - } else { - WdsConnectionIPv6Handle = le32_to_cpu(pResponse->MUXMsg.StartNwInterfaceResp.Handle); - dbg_time("%s WdsConnectionIPv6Handle: 0x%08x", __func__, WdsConnectionIPv6Handle); - } - - free(pResponse); - - return 0; -} - -static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - UCHAR QMIType = (curIpFamily == 0x04) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - - (void)profile; - if (curIpFamily == IpFamilyV4 && WdsConnectionIPv4Handle == 0) - return 0; - if (curIpFamily == IpFamilyV6 && WdsConnectionIPv6Handle == 0) - return 0; - - dbg_time("%s WdsConnectionIPv%dHandle", __func__, curIpFamily == IpFamilyV4 ? 4 : 6); - - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_STOP_NETWORK_INTERFACE_REQ , WdsStopNwInterfaceReq, &curIpFamily); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - if (curIpFamily == IpFamilyV4) - WdsConnectionIPv4Handle = 0; - else - WdsConnectionIPv6Handle = 0; - free(pResponse); - return 0; -} - -static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR pIpv4Addr; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR pIpv6Addr = NULL; - PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU pMtu; - IPV4_T *pIpv4 = &profile->ipv4; - IPV6_T *pIpv6 = &profile->ipv6; - UCHAR QMIType = (curIpFamily == 0x04) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6; - PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR pPCSCFIpv6Addr; - PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR pPCSCFIpv4Addr; - - if (curIpFamily == IpFamilyV4) { - memset(pIpv4, 0x00, sizeof(IPV4_T)); - if (WdsConnectionIPv4Handle == 0) - return 0; - } else if (curIpFamily == IpFamilyV6) { - memset(pIpv6, 0x00, sizeof(IPV6_T)); - if (WdsConnectionIPv6Handle == 0) - return 0; - } - - pRequest = ComposeQMUXMsg(QMIType, QMIWDS_GET_RUNTIME_SETTINGS_REQ, WdsGetRuntimeSettingReq, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pPCSCFIpv6Addr = (PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x2e); // 0x2e - pcscf ipv6 address - if (pPCSCFIpv6Addr) { - if (pPCSCFIpv6Addr->PCSCFNumber == 1) { - UCHAR *PCSCFIpv6Addr1 = (UCHAR *)(pPCSCFIpv6Addr + 1); - memcpy(profile->PCSCFIpv6Addr1, PCSCFIpv6Addr1, 16); - }else if (pPCSCFIpv6Addr->PCSCFNumber == 2) { - UCHAR *PCSCFIpv6Addr1 = (UCHAR *)(pPCSCFIpv6Addr + 1); - UCHAR *PCSCFIpv6Addr2 = PCSCFIpv6Addr1 + 16; - memcpy(profile->PCSCFIpv6Addr1, PCSCFIpv6Addr1, 16); - memcpy(profile->PCSCFIpv6Addr2, PCSCFIpv6Addr2, 16); - } - } - - pPCSCFIpv4Addr = (PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x23); // 0x23 - pcscf ipv4 address - if (pPCSCFIpv4Addr) { - if (pPCSCFIpv4Addr->PCSCFNumber == 1) { - UCHAR *PCSCFIpv4Addr1 = (UCHAR *)(pPCSCFIpv4Addr + 1); - memcpy(&profile->PCSCFIpv4Addr1, PCSCFIpv4Addr1, 4); - }else if (pPCSCFIpv4Addr->PCSCFNumber == 2) { - UCHAR *PCSCFIpv4Addr1 = (UCHAR *)(pPCSCFIpv4Addr + 1); - UCHAR *PCSCFIpv4Addr2 = PCSCFIpv4Addr1 + 4; - memcpy(&profile->PCSCFIpv4Addr1, PCSCFIpv4Addr1, 4); - memcpy(&profile->PCSCFIpv4Addr2, PCSCFIpv4Addr2, 4); - } - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS); - if (pIpv4Addr) { - pIpv4->DnsPrimary = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS); - if (pIpv4Addr) { - pIpv4->DnsSecondary = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY); - if (pIpv4Addr) { - pIpv4->Gateway = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET); - if (pIpv4Addr) { - pIpv4->SubnetMask = pIpv4Addr->IPV4Address; - } - - pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4); - if (pIpv4Addr) { - pIpv4->Address = pIpv4Addr->IPV4Address; - } - - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS); - if (pIpv6Addr) { - memcpy(pIpv6->DnsPrimary, pIpv6Addr->IPV6Address, 16); - } - - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS); - if (pIpv6Addr) { - memcpy(pIpv6->DnsSecondary, pIpv6Addr->IPV6Address, 16); - } - - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY); - if (pIpv6Addr) { - memcpy(pIpv6->Gateway, pIpv6Addr->IPV6Address, 16); - pIpv6->PrefixLengthGateway = pIpv6Addr->PrefixLength; - } - - pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6); - if (pIpv6Addr) { - memcpy(pIpv6->Address, pIpv6Addr->IPV6Address, 16); - pIpv6->PrefixLengthIPAddr = pIpv6Addr->PrefixLength; - } - - pMtu = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU); - if (pMtu) { - if (curIpFamily == IpFamilyV4) - pIpv4->Mtu = le32_to_cpu(pMtu->Mtu); - else - pIpv6->Mtu = le32_to_cpu(pMtu->Mtu); - } - - free(pResponse); - return 0; -} - -#ifdef CONFIG_APN -static int requestSetProfile(PROFILE_T *profile) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - const char *new_apn = profile->apn ? profile->apn : ""; - const char *new_user = profile->user ? profile->user : ""; - const char *new_password = profile->password ? profile->password : ""; - const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"}; - - dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->apn, profile->user, profile->password, profile->auth,ipStr[profile->iptype]); - if (!profile->pdp) - return -1; - - if ( !strcmp(profile->old_apn, new_apn) && !strcmp(profile->old_user, new_user) - && !strcmp(profile->old_password, new_password) - && profile->old_iptype == profile->iptype - && profile->old_auth == profile->auth) - { - dbg_time("no need to set skip the rest"); - return 0; - } - - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_MODIFY_PROFILE_SETTINGS_REQ, WdsModifyProfileSettingsReq, profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - free(pResponse); - return 1; -} - -static int requestGetProfile(PROFILE_T *profile) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - PQMIWDS_APNNAME pApnName; - PQMIWDS_USERNAME pUserName; - PQMIWDS_PASSWD pPassWd; - PQMIWDS_AUTH_PREFERENCE pAuthPref; - PQMIWDS_IPTYPE pIpType; - const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"}; - - profile->old_apn[0] = profile->old_user[0] = profile->old_password[0] = '\0'; - profile->old_auth = 0; - profile->old_iptype = 0; - if (profile->enable_ipv4 && profile->enable_ipv6) - profile->iptype = 3; - else if (profile->enable_ipv6) - profile->iptype = 2; - else - profile->iptype = 0; - - if (!profile->pdp) - return 0; - -_re_check: - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_SETTINGS_REQ, WdsGetProfileSettingsReqSend, profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - if (err == 0 && pResponse && le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXResult) - && le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXError) == QMI_ERR_EXTENDED_INTERNAL) - { - free(pResponse); - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_CREATE_PROFILE_REQ, WdsCreateProfileSettingsReqSend, profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - free(pResponse); - goto _re_check; - } - qmi_rsp_check_and_return(); - - pApnName = (PQMIWDS_APNNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14); - pUserName = (PQMIWDS_USERNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1B); - pPassWd = (PQMIWDS_PASSWD)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1C); - pAuthPref = (PQMIWDS_AUTH_PREFERENCE)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1D); - pIpType = (PQMIWDS_IPTYPE)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - - if (pApnName/* && le16_to_cpu(pApnName->TLVLength)*/) - uchar2char(profile->old_apn, sizeof(profile->old_apn), &pApnName->ApnName, le16_to_cpu(pApnName->TLVLength)); - if (pUserName/* && pUserName->UserName*/) - uchar2char(profile->old_user, sizeof(profile->old_user), &pUserName->UserName, le16_to_cpu(pUserName->TLVLength)); - if (pPassWd/* && le16_to_cpu(pPassWd->TLVLength)*/) - uchar2char(profile->old_password, sizeof(profile->old_password), &pPassWd->Passwd, le16_to_cpu(pPassWd->TLVLength)); - if (pAuthPref/* && le16_to_cpu(pAuthPref->TLVLength)*/) { - profile->old_auth = pAuthPref->AuthPreference; - } - if (pIpType) { - profile->old_iptype = pIpType->IPType; - } - - dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->old_apn, profile->old_user, profile->old_password, profile->old_auth, ipStr[profile->old_iptype]); - - free(pResponse); - return 0; -} -#endif - -#ifdef CONFIG_SIGNALINFO -static int requestGetSignalInfo(void) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SIG_INFO_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - - // CDMA - { - PQMINAS_SIG_INFO_CDMA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_CDMA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s CDMA: RSSI %d dBm, ECIO %.1lf dBm", __func__, - ptlv->rssi, (-0.5) * (double)ptlv->ecio); - } - } - - // HDR - { - PQMINAS_SIG_INFO_HDR_TLV_MSG ptlv = (PQMINAS_SIG_INFO_HDR_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s HDR: RSSI %d dBm, ECIO %.1lf dBm, IO %d dBm", __func__, - ptlv->rssi, (-0.5) * (double)ptlv->ecio, ptlv->io); - } - } - - // GSM - { - PQMINAS_SIG_INFO_GSM_TLV_MSG ptlv = (PQMINAS_SIG_INFO_GSM_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s GSM: RSSI %d dBm", __func__, ptlv->rssi); - } - } - - // WCDMA - { - PQMINAS_SIG_INFO_WCDMA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_WCDMA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x13); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s WCDMA: RSSI %d dBm, ECIO %.1lf dBm", __func__, - ptlv->rssi, (-0.5) * (double)ptlv->ecio); - } - } - - // LTE - { - PQMINAS_SIG_INFO_LTE_TLV_MSG ptlv = (PQMINAS_SIG_INFO_LTE_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s LTE: RSSI %d dBm, RSRQ %d dB, RSRP %d dBm, SNR %.1lf dB", __func__, - ptlv->rssi, ptlv->rsrq, ptlv->rsrp, (0.1) * (double)ptlv->snr); - } - } - - // TDSCDMA - { - PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x15); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s LTE: RSCP %d dBm", __func__, ptlv->rscp); - } - } - - // 5G_NSA - if (s_5g_type == WWAN_DATA_CLASS_5G_NSA) - { - PQMINAS_SIG_INFO_5G_NSA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_5G_NSA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x17); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s 5G_NSA: RSRP %d dBm, SNR %.1lf dB", __func__, ptlv->rsrp, (0.1) * (double)ptlv->snr); - } - } - - // 5G_SA - if (s_5g_type == WWAN_DATA_CLASS_5G_SA) - { - PQMINAS_SIG_INFO_5G_SA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_5G_SA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x18); - if (ptlv && ptlv->TLVLength) - { - dbg_time("%s 5G_SA: NR5G_RSRQ %d dB", __func__, ptlv->nr5g_rsrq); - } - } - - free(pResponse); - return 0; -} -#endif - -#ifdef CONFIG_VERSION -static int requestBaseBandVersion(PROFILE_T *profile) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PDEVICE_REV_ID revId; - int err; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_GET_DEVICE_REV_ID_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - revId = (PDEVICE_REV_ID)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - - if (revId && le16_to_cpu(revId->TLVLength)) - { - uchar2char(profile->BaseBandVersion, sizeof(profile->BaseBandVersion), &revId->RevisionID, le16_to_cpu(revId->TLVLength)); - dbg_time("%s %s", __func__, profile->BaseBandVersion); - } - - free(pResponse); - return 0; -} -#endif - -static USHORT DmsSetOperatingModeReq(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->SetOperatingModeReq.TLVType = 0x01; - pMUXMsg->SetOperatingModeReq.TLVLength = cpu_to_le16(1); - pMUXMsg->SetOperatingModeReq.OperatingMode = *((UCHAR *)arg); - - return sizeof(QMIDMS_SET_OPERATING_MODE_REQ_MSG); -} - -static USHORT UimSetCardSlotReq(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->UIMSetCardSlotReq.TLVType = 0x01; - pMUXMsg->UIMSetCardSlotReq.TLVLength = cpu_to_le16(1); - pMUXMsg->UIMSetCardSlotReq.slot = *((UCHAR *)arg); - - return sizeof(QMIUIM_SET_CARD_SLOT_REQ_MSG); -} - -static int requestRadioPower(int state) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - UCHAR OperatingMode = (!!state) ? DMS_OP_MODE_ONLINE : DMS_OP_MODE_LOW_POWER; - USHORT SimOp = (!!state) ? QMIUIM_POWER_UP : QMIUIM_POWER_DOWN; - UCHAR cardSlot = 0x01; - - dbg_time("%s(%d)", __func__, state); - - pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_SET_OPERATING_MODE_REQ, DmsSetOperatingModeReq, &OperatingMode); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - free(pResponse); - - pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, SimOp, UimSetCardSlotReq, &cardSlot); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - free(pResponse); - - return 0; -} - -static USHORT WdaSetLoopBackReq(PQMUX_MSG pMUXMsg, void *arg) { - (void)arg; - pMUXMsg->SetLoopBackReq.loopback_state.TLVType = 0x01; - pMUXMsg->SetLoopBackReq.loopback_state.TLVLength = cpu_to_le16(1); - - pMUXMsg->SetLoopBackReq.replication_factor.TLVType = 0x10; - pMUXMsg->SetLoopBackReq.replication_factor.TLVLength = cpu_to_le16(4); - - return sizeof(QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG); -} - -static int requestSetLoopBackState(UCHAR loopback_state, ULONG replication_factor) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - - dbg_time("%s(loopback_state=%d, replication_factor=%u)", __func__, loopback_state, replication_factor); - - pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_ADMIN, QMI_WDA_SET_LOOPBACK_CONFIG_REQ, WdaSetLoopBackReq, NULL); - pRequest->MUXMsg.SetLoopBackReq.loopback_state.TLVVaule = loopback_state; - pRequest->MUXMsg.SetLoopBackReq.replication_factor.TLVVaule = cpu_to_le16(replication_factor); - - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - free(pResponse); - return 0; -} - -#ifdef CONFIG_ENABLE_QOS -static USHORT QosSetBindMuxDataPort(PQMUX_MSG pMUXMsg, void *arg) { - PROFILE_T *profile = (PROFILE_T *)arg; - pMUXMsg->QosBindDataPortReq.EpIdTlv.TLVType = 0x10; - pMUXMsg->QosBindDataPortReq.EpIdTlv.TLVLength = cpu_to_le16(8); - pMUXMsg->QosBindDataPortReq.EpIdTlv.ep_type = cpu_to_le32(profile->rmnet_info.ep_type); - pMUXMsg->QosBindDataPortReq.EpIdTlv.iface_id = cpu_to_le32(profile->rmnet_info.iface_id); - pMUXMsg->QosBindDataPortReq.MuxIdTlv.TLVType = 0x11; - pMUXMsg->QosBindDataPortReq.MuxIdTlv.TLVLength = cpu_to_le16(1); - pMUXMsg->QosBindDataPortReq.MuxIdTlv.mux_id = profile->muxid; - return sizeof(QMI_QOS_BIND_DATA_PORT_REQ_MSG); -} - -#ifdef CONFIG_REG_QOS_IND -static USHORT QosIndRegReq(PQMUX_MSG pMUXMsg, void *arg) { - pMUXMsg->QosIndRegReq.ReportGlobalQosFlowTlv.TLVType = 0x10; - pMUXMsg->QosIndRegReq.ReportGlobalQosFlowTlv.TLVLength = cpu_to_le16(1); - pMUXMsg->QosIndRegReq.ReportGlobalQosFlowTlv.report_global_qos_flows = 1; - return sizeof(QMI_QOS_INDICATION_REGISTER_REQ_MSG); -} -#endif - -static int requestRegisterQos(PROFILE_T *profile) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse = NULL; - PQMUX_MSG pMUXMsg; - int err; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_QOS, QMI_QOS_BIND_DATA_PORT_REQ , QosSetBindMuxDataPort, (void *)profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - dbg_time("%s QosSetBindMuxDataPort", __func__); - qmi_rsp_check_and_return(); - if (pResponse) free(pResponse); - -#ifdef CONFIG_REG_QOS_IND - pRequest = ComposeQMUXMsg(QMUX_TYPE_QOS, QMI_QOS_INDICATION_REGISTER_REQ , QosIndRegReq, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - dbg_time("%s QosIndRegReq", __func__); - qmi_rsp_check_and_return(); - if (pResponse) free(pResponse); -#endif - return 0; -} - -#ifdef CONFIG_GET_QOS_INFO -UCHAR ql_get_qos_info_data_rate(PQCQMIMSG pResponse, void *max_data_rate) -{ - PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW qos_tx_granted_flow = NULL; - PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW qos_rx_granted_flow = NULL; - qos_tx_granted_flow = (PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if(qos_tx_granted_flow != NULL) - { - *(ULONG64 *)(max_data_rate) = le64_to_cpu(qos_tx_granted_flow->data_rate_max); - dbg_time("GET_QOS_INFO: tx_data_rate_max=%llu", *(ULONG64 *)(max_data_rate+0)); - } - else - dbg_time("GET_QOS_INFO: No qos_tx_granted_flow"); - qos_rx_granted_flow = (PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - if(qos_rx_granted_flow != NULL) - { - *(ULONG64 *)(max_data_rate+sizeof(ULONG64)) = le64_to_cpu(qos_rx_granted_flow->data_rate_max); - dbg_time("GET_QOS_INFO: rx_data_rate_max=%llu", *(ULONG64 *)(max_data_rate+sizeof(ULONG64))); - } - else - dbg_time("GET_QOS_INFO: No qos_rx_granted_flow"); - if(qos_tx_granted_flow != NULL || qos_rx_granted_flow != NULL) - return 0; - else - return 1; -} - -static USHORT QosGetQosInfoReq(PQMUX_MSG pMUXMsg, void *arg) { - PROFILE_T *profile = (PROFILE_T *)arg; - pMUXMsg->QosGetQosInfoReq.QosIdTlv.TLVType = 0x01; - pMUXMsg->QosGetQosInfoReq.QosIdTlv.TLVLength = cpu_to_le16(4); - pMUXMsg->QosGetQosInfoReq.QosIdTlv.qos_id = cpu_to_le32(profile->qos_id); - return sizeof(QMI_QOS_GET_QOS_INFO_REQ_MSG); -} - -static int requestGetQosInfo(PROFILE_T *profile) { - PQCQMIMSG pRequest; - PQCQMIMSG pResponse = NULL; - PQMUX_MSG pMUXMsg; - int err; - - if(profile->qos_id == 0) - { - dbg_time("%s request not send: invalid qos_id", __func__); - return 0; - } - pRequest = ComposeQMUXMsg(QMUX_TYPE_QOS, QMI_QOS_GET_QOS_INFO_REQ , QosGetQosInfoReq, (void *)profile); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - if (pResponse) - { -#ifdef CONFIG_GET_QOS_DATA_RATE - ULONG64 max_data_rate[2] = {0}; - if(ql_get_qos_info_data_rate(pResponse, (void *)max_data_rate) == 0){} -#endif - free(pResponse); - } - return 0; -} -#endif //#ifdef CONFIG_GET_QOS_INFO - -#ifdef CONFIG_REG_QOS_IND -UCHAR ql_get_global_qos_flow_ind_qos_id(PQCQMIMSG pResponse, UINT *qos_id) -{ - PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE qos_flow_state = NULL; - qos_flow_state = (PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if(qos_flow_state != NULL) - { - if(le32_to_cpu(qos_flow_state->state_change) == QOS_IND_FLOW_STATE_ACTIVATED && qos_flow_state->new_flow == 1) - { - *qos_id = le32_to_cpu(qos_flow_state->qos_id); - dbg_time("QMI_QOS_GLOBAL_QOS_FLOW_IND: qos_id=%u state=QOS_IND_FLOW_STATE_ACTIVATED", *qos_id); - } - return (qos_flow_state->new_flow); - } - return (0); -} - -#ifdef CONFIG_GET_QOS_DATA_RATE -UCHAR ql_get_global_qos_flow_ind_data_rate(PQCQMIMSG pResponse, void *max_data_rate) -{ - PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED qos_tx_flow_granted = NULL; - PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED qos_rx_flow_granted = NULL; - qos_tx_flow_granted = (PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10); - if(qos_tx_flow_granted != NULL) - { - *(ULONG64 *)(max_data_rate) = le64_to_cpu(qos_tx_flow_granted->data_rate_max); - dbg_time("QMI_QOS_GLOBAL_QOS_FLOW_IND: tx_data_rate_max=%llu", *(ULONG64 *)(max_data_rate+0)); - } - else - dbg_time("QMI_QOS_GLOBAL_QOS_FLOW_IND: No qos_tx_flow_granted"); - qos_rx_flow_granted = (PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if(qos_rx_flow_granted != NULL) - { - *(ULONG64 *)(max_data_rate+sizeof(ULONG64)) = le64_to_cpu(qos_rx_flow_granted->data_rate_max); - dbg_time("QMI_QOS_GLOBAL_QOS_FLOW_IND: rx_data_rate_max=%llu", *(ULONG64 *)(max_data_rate+sizeof(ULONG64))); - } - else - dbg_time("QMI_QOS_GLOBAL_QOS_FLOW_IND: No qos_rx_flow_granted"); - if(qos_tx_flow_granted != NULL || qos_rx_flow_granted != NULL) - return 0; - else - return 1; -} -#endif -#endif //#ifdef CONFIG_REG_QOS_IND -#endif //#ifdef CONFIG_ENABLE_QOS - -#ifdef CONFIG_CELLINFO -/* - at+qeng="servingcell" and at+qeng="neighbourcell" - https://gitlab.freedesktop.org/mobile-broadband/libqmi/-/blob/master/src/qmicli/qmicli-nas.c -*/ -static int nas_get_cell_location_info(void); -static int nas_get_rf_band_information(void); - -static int requestGetCellInfoList(void) { - dbg_time("%s", __func__); - nas_get_cell_location_info(); - nas_get_rf_band_information(); - return 0; -} -#endif - -const struct request_ops qmi_request_ops = { -#ifdef CONFIG_VERSION - .requestBaseBandVersion = requestBaseBandVersion, -#endif - .requestSetEthMode = requestSetEthMode, -#ifdef CONFIG_SIM - .requestGetSIMStatus = requestGetSIMStatus, - .requestEnterSimPin = requestEnterSimPin, -#endif -#ifdef CONFIG_IMSI_ICCID - .requestGetICCID = requestGetICCID, - .requestGetIMSI = requestGetIMSI, -#endif -#ifdef CONFIG_APN - .requestSetProfile = requestSetProfile, - .requestGetProfile = requestGetProfile, -#endif - .requestRegistrationState = requestRegistrationState, - .requestSetupDataCall = requestSetupDataCall, - .requestQueryDataCall = requestQueryDataCall, - .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, - .requestGetIPAddress = requestGetIPAddress, -#ifdef CONFIG_SIGNALINFO - .requestGetSignalInfo = requestGetSignalInfo, -#endif -#ifdef CONFIG_CELLINFO - .requestGetCellInfoList = requestGetCellInfoList, -#endif - .requestSetLoopBackState = requestSetLoopBackState, - .requestRadioPower = requestRadioPower, -#ifdef CONFIG_ENABLE_QOS - .requestRegisterQos = requestRegisterQos, -#endif -#ifdef CONFIG_GET_QOS_INFO - .requestGetQosInfo = requestGetQosInfo, -#endif -#ifdef CONFIG_COEX_WWAN_STATE - .requestGetCoexWWANState = requestGetCoexWWANState, -#endif -}; - -#ifdef CONFIG_CELLINFO -static char *str_from_bcd_plmn (uint8 plmn[3]) -{ - const char bcd_chars[] = "0123456789*#abc\0\0"; - static char str[12]; - int i; - int j = 0; - - for (i = 0; i < 3; i++) { - str[j] = bcd_chars[plmn[i]&0xF]; - if (str[j]) j++; - str[j] = bcd_chars[plmn[i]>>4]; - if (str[j]) j++; - } - - str[j++] = 0; - - return str; -} - -typedef struct { - UINT type; - const char *name; -} ENUM_NAME_T; - -#define enum_name(type) {type, #type} -#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) - -static const ENUM_NAME_T QMI_NAS_ACTIVE_BAND_NAME[] = { - enum_name(QMI_NAS_ACTIVE_BAND_BC_0), - enum_name(QMI_NAS_ACTIVE_BAND_BC_1), - enum_name(QMI_NAS_ACTIVE_BAND_BC_2), - enum_name(QMI_NAS_ACTIVE_BAND_BC_3), - enum_name(QMI_NAS_ACTIVE_BAND_BC_4), - enum_name(QMI_NAS_ACTIVE_BAND_BC_5), - enum_name(QMI_NAS_ACTIVE_BAND_BC_6), - enum_name(QMI_NAS_ACTIVE_BAND_BC_7), - enum_name(QMI_NAS_ACTIVE_BAND_BC_8), - enum_name(QMI_NAS_ACTIVE_BAND_BC_9), - enum_name(QMI_NAS_ACTIVE_BAND_BC_10), - enum_name(QMI_NAS_ACTIVE_BAND_BC_11), - enum_name(QMI_NAS_ACTIVE_BAND_BC_12), - enum_name(QMI_NAS_ACTIVE_BAND_BC_13), - enum_name(QMI_NAS_ACTIVE_BAND_BC_14), - enum_name(QMI_NAS_ACTIVE_BAND_BC_15), - enum_name(QMI_NAS_ACTIVE_BAND_BC_16), - enum_name(QMI_NAS_ACTIVE_BAND_BC_17), - enum_name(QMI_NAS_ACTIVE_BAND_BC_18), - enum_name(QMI_NAS_ACTIVE_BAND_BC_19), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_450), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_480), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_750), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_850), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_DCS_1800), - enum_name(QMI_NAS_ACTIVE_BAND_GSM_PCS_1900), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_2100), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_1700_US), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_850), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_800), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_2600), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_900), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN), - enum_name(QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_1), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_2), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_3), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_4), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_5), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_6), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_7), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_8), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_9), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_10), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_11), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_12), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_13), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_14), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_17), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_18), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_19), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_20), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_21), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_23), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_24), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_25), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_26), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_27), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_28), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_29), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_30), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_31), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_32), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_33), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_34), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_35), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_36), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_37), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_38), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_39), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_40), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_41), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_42), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_43), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_46), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_47), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_48), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_66), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_71), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_125), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_126), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_127), - enum_name(QMI_NAS_ACTIVE_BAND_EUTRAN_250), - enum_name(QMI_NAS_ACTIVE_BAND_TDSCDMA_A), - enum_name(QMI_NAS_ACTIVE_BAND_TDSCDMA_B), - enum_name(QMI_NAS_ACTIVE_BAND_TDSCDMA_C), - enum_name(QMI_NAS_ACTIVE_BAND_TDSCDMA_D), - enum_name(QMI_NAS_ACTIVE_BAND_TDSCDMA_E), - enum_name(QMI_NAS_ACTIVE_BAND_TDSCDMA_F), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_1 ), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_2 ), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_3 ), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_5 ), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_7 ), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_8 ), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_20), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_28), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_38), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_41), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_50), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_51), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_66), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_70), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_71), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_74), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_75), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_76), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_77), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_78), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_79), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_80), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_81), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_82), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_83), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_84), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_85), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_257), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_258), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_259), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_260), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_261), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_12), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_25), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_34), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_39), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_40), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_65), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_86), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_48), - enum_name(QMI_NAS_ACTIVE_BAND_NR5G_BAND_14), -}; - -static const char *qmi_nas_radio_interface_get_string(uint8 radio_if) -{ - const char *str = NULL; - - switch (radio_if) { - case QMI_NAS_RADIO_INTERFACE_CDMA_1X: str = "cdma-1x"; break; - case QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO: str = "cdma-1xevdo"; break; - case QMI_NAS_RADIO_INTERFACE_AMPS: str = "amps"; break; - case QMI_NAS_RADIO_INTERFACE_GSM: str = "gsm"; break; - case QMI_NAS_RADIO_INTERFACE_UMTS: str = "umts"; break; - case QMI_NAS_RADIO_INTERFACE_LTE: str = "lte"; break; - case QMI_NAS_RADIO_INTERFACE_TD_SCDMA: str = "td-scdma"; break; - case QMI_NAS_RADIO_INTERFACE_5GNR: str = "5gnr"; break; - default: str = NULL; break; - } - - return str ? str : "unknown"; -} - -static const char *qmi_nas_active_band_get_string(uint32 active_band) -{ - size_t i; - - for (i = 0; i < N_ELEMENTS(QMI_NAS_ACTIVE_BAND_NAME); i++) { - if (active_band == QMI_NAS_ACTIVE_BAND_NAME[i].type) - return QMI_NAS_ACTIVE_BAND_NAME[i].name + strlen("QMI_NAS_ACTIVE_BAND_"); - } - - return "unknown"; -} - -typedef struct { - uint16 min; - uint16 max; - const char *name; -} EarfcnRange; - -/* http://niviuk.free.fr/lte_band.php */ -static const EarfcnRange earfcn_ranges[] = { - { 0, 599, "E-UTRA band 1: 2100" }, - { 600, 1199, "E-UTRA band 2: 1900 PCS" }, - { 1200, 1949, "E-UTRA band 3: 1800+" }, - { 1950, 2399, "E-UTRA band 4: AWS-1" }, - { 2400, 2649, "E-UTRA band 5: 850" }, - { 2650, 2749, "E-UTRA band 6: UMTS only" }, - { 2750, 3449, "E-UTRA band 7: 2600" }, - { 3450, 3799, "E-UTRA band 8: 900" }, - { 3800, 4149, "E-UTRA band 9: 1800" }, - { 4150, 4749, "E-UTRA band 10: AWS-1+" }, - { 4750, 4999, "E-UTRA band 11: 1500 Lower" }, - { 5000, 5179, "E-UTRA band 12: 700 a" }, - { 5180, 5279, "E-UTRA band 13: 700 c" }, - { 5280, 5379, "E-UTRA band 14: 700 PS" }, - { 5730, 5849, "E-UTRA band 17: 700 b" }, - { 5850, 5999, "E-UTRA band 18: 800 Lower" }, - { 6000, 6149, "E-UTRA band 19: 800 Upper" }, - { 6150, 6449, "E-UTRA band 20: 800 DD" }, - { 6450, 6599, "E-UTRA band 21: 1500 Upper" }, - { 6600, 7399, "E-UTRA band 22: 3500" }, - { 7500, 7699, "E-UTRA band 23: 2000 S-band" }, - { 7700, 8039, "E-UTRA band 24: 1600 L-band" }, - { 8040, 8689, "E-UTRA band 25: 1900+" }, - { 8690, 9039, "E-UTRA band 26: 850+" }, - { 9040, 9209, "E-UTRA band 27: 800 SMR" }, - { 9210, 9659, "E-UTRA band 28: 700 APT" }, - { 9660, 9769, "E-UTRA band 29: 700 d" }, - { 9770, 9869, "E-UTRA band 30: 2300 WCS" }, - { 9870, 9919, "E-UTRA band 31: 450" }, - { 9920, 10359, "E-UTRA band 32: 1500 L-band" }, - { 36000, 36199, "E-UTRA band 33: TD 1900" }, - { 36200, 36349, "E-UTRA band 34: TD 2000" }, - { 36350, 36949, "E-UTRA band 35: TD PCS Lower" }, - { 36950, 37549, "E-UTRA band 36: TD PCS Upper" }, - { 37550, 37749, "E-UTRA band 37: TD PCS Center" }, - { 37750, 38249, "E-UTRA band 38: TD 2600" }, - { 38250, 38649, "E-UTRA band 39: TD 1900+" }, - { 38650, 39649, "E-UTRA band 40: TD 2300" }, - { 39650, 41589, "E-UTRA band 41: TD 2500" }, - { 41590, 43589, "E-UTRA band 42: TD 3500" }, - { 43590, 45589, "E-UTRA band 43: TD 3700" }, - { 45590, 46589, "E-UTRA band 44: TD 700" }, -}; - -static const char * earfcn_to_eutra_band_string (uint16 earfcn) -{ - size_t i; - - for (i = 0; i < N_ELEMENTS (earfcn_ranges); i++) { - if (earfcn <= earfcn_ranges[i].max && earfcn >= earfcn_ranges[i].min) - return earfcn_ranges[i].name; - } - - return "unknown"; -} - -static int nas_get_cell_location_info(void) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - PQMI_TLV pV; - int err; - int i, j; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_CELL_LOCATION_INFO_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - pV = (PQMI_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x2E); - if (pV && pV->TLVLength) { - printf ("5GNR ARFCN: '%u'\n", pV->u32); - } - - { - NasGetCellLocationNr5gServingCell *ptlv = (NasGetCellLocationNr5gServingCell *)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x2F); - if (ptlv && ptlv->TLVLength) - { - printf ("5GNR cell information:\n" - "\tPLMN: '%s'\n" - "\tTracking Area Code: '%u'\n" - "\tGlobal Cell ID: '%" PRIu64 "'\n" - "\tPhysical Cell ID: '%u'\n" - "\tRSRQ: '%.1lf dB'\n" - "\tRSRP: '%.1lf dBm'\n" - "\tSNR: '%.1lf dB'\n", - str_from_bcd_plmn(ptlv->plmn), - ptlv->tac[0]<<16 | ptlv->tac[1]<<8 | ptlv->tac[2] , - ptlv->global_cell_id, - ptlv->physical_cell_id, - (0.1) * ((double)ptlv->rsrq), - (0.1) * ((double)ptlv->rsrp), - (0.1) * ((double)ptlv->snr)); - } - } - - { - NasGetCellLocationLteInfoIntrafrequency *ptlv = (NasGetCellLocationLteInfoIntrafrequency *)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x13); - if (ptlv && ptlv->TLVLength) - { - printf ("Intrafrequency LTE Info:\n" - "\tUE In Idle: '%s'\n" - "\tPLMN: '%s'\n" - "\tTracking Area Code: '%u'\n" - "\tGlobal Cell ID: '%u'\n" - "\tEUTRA Absolute RF Channel Number: '%u' (%s)\n" - "\tServing Cell ID: '%u'\n", - ptlv->ue_in_idle ? "yes" : "no", - str_from_bcd_plmn(ptlv->plmn), - ptlv->tracking_area_code, - ptlv->global_cell_id, - ptlv->absolute_rf_channel_number, earfcn_to_eutra_band_string(ptlv->absolute_rf_channel_number), - ptlv->serving_cell_id); - - if (ptlv->ue_in_idle) - printf ("\tCell Reselection Priority: '%u'\n" - "\tS Non Intra Search Threshold: '%u'\n" - "\tServing Cell Low Threshold: '%u'\n" - "\tS Intra Search Threshold: '%u'\n", - ptlv->cell_reselection_priority, - ptlv->s_non_intra_search_threshold, - ptlv->serving_cell_low_threshold, - ptlv->s_intra_search_threshold); - - - for (i = 0; i < ptlv->cells_len; i++) { - NasGetCellLocationLteInfoCell *cell = &ptlv->cells_array[i]; - - printf ("\tCell [%u]:\n" - "\t\tPhysical Cell ID: '%u'\n" - "\t\tRSRQ: '%.1lf' dB\n" - "\t\tRSRP: '%.1lf' dBm\n" - "\t\tRSSI: '%.1lf' dBm\n", - i, - cell->physical_cell_id, - (double) cell->rsrq * 0.1, - (double) cell->rsrp * 0.1, - (double) cell->rssi * 0.1); - - if (ptlv->ue_in_idle) - printf ("\t\tCell Selection RX Level: '%d'\n", - cell->cell_selection_rx_level); - } - } - } - - { - NasGetCellLocationLteInfoInterfrequency *ptlv = (NasGetCellLocationLteInfoInterfrequency *)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14); - if (ptlv && ptlv->TLVLength) - { - int off = offsetof(NasGetCellLocationLteInfoInterfrequency, freqs[0]); - printf ("Interfrequency LTE Info:\n" - "\tUE In Idle: '%s'\n", ptlv->ue_in_idle ? "yes" : "no"); - - for (i = 0; i < ptlv->freqs_len; i++) { - NasGetCellLocationLteInfoInterfrequencyFrequencyElement *freq = (((void *)ptlv) + off); - - off += sizeof(*freq); - printf ("\tFrequency [%u]:\n" - "\t\tEUTRA Absolute RF Channel Number: '%u' (%s)\n" - "\t\tSelection RX Level Low Threshold: '%u'\n" - "\t\tCell Selection RX Level High Threshold: '%u'\n", - i, - freq->eutra_absolute_rf_channel_number, earfcn_to_eutra_band_string(freq->eutra_absolute_rf_channel_number), - freq->cell_selection_rx_level_low_threshold, - freq->cell_selection_rx_level_high_threshold); - if (ptlv->ue_in_idle) - printf ("\t\tCell Reselection Priority: '%u'\n", - freq->cell_reselection_priority); - - - for (j = 0; j < freq->cells_len; j++) { - NasGetCellLocationLteInfoCell *cell = &freq->cells_array[j]; - - off += sizeof(*cell); - printf ("\t\tCell [%u]:\n" - "\t\t\tPhysical Cell ID: '%u'\n" - "\t\t\tRSRQ: '%.1lf' dB\n" - "\t\t\tRSRP: '%.1lf' dBm\n" - "\t\t\tRSSI: '%.1lf' dBm\n" - "\t\t\tCell Selection RX Level: '%u'\n", - j, - cell->physical_cell_id, - (double) cell->rsrq * 0.1, - (double) cell->rsrp * 0.1, - (double) cell->rssi * 0.1, - cell->cell_selection_rx_level); - } - } - } - } - - pV = (PQMI_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1E); - if (pV && pV->TLVLength) { - if (pV->u32 == 0xFFFFFFFF) - printf ("LTE Timing Advance: 'unavailable'\n"); - else - printf ("LTE Timing Advance: '%u'\n", pV->u32); - } - - free(pResponse); - return 0; -} - -static int nas_get_rf_band_information(void) -{ - PQCQMIMSG pRequest; - PQCQMIMSG pResponse; - PQMUX_MSG pMUXMsg; - int err; - int i; - - pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_RF_BAND_INFO_REQ, NULL, NULL); - err = QmiThreadSendQMI(pRequest, &pResponse); - qmi_rsp_check_and_return(); - - { - NasGetRfBandInfoList *ptlv = (NasGetRfBandInfoList *)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01); - if (ptlv && ptlv->TLVLength) - { - printf ("Band Information:\n"); - for (i = 0; i < ptlv->num_instances; i++) { - NasGetRfBandInfo *band = &ptlv->bands_array[i]; - - printf ("\tRadio Interface: '%s'\n" - "\tActive Band Class: '%s'\n" - "\tActive Channel: '%u'\n", - qmi_nas_radio_interface_get_string (band->radio_if), - qmi_nas_active_band_get_string (band->active_band), - band->active_channel); - } - } - } - - { - NasGetRfBandInfoExtendedList *ptlv = (NasGetRfBandInfoExtendedList *)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11); - if (ptlv && ptlv->TLVLength) - { - printf ("Band Information (Extended):\n"); - for (i = 0; i < ptlv->num_instances; i++) { - NasGetRfBandInfoExtended *band = &ptlv->bands_array[i]; - - printf ("\tRadio Interface: '%s'\n" - "\tActive Band Class: '%s'\n" - "\tActive Channel: '%u'\n", - qmi_nas_radio_interface_get_string (band->radio_if), - qmi_nas_active_band_get_string (band->active_band), - band->active_channel); - } - } - } - - { - NasGetRfBandInfoBandWidthList *ptlv = (NasGetRfBandInfoBandWidthList *)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12); - if (ptlv && ptlv->TLVLength) - { - printf ("Bandwidth:\n"); - for (i = 0; i < ptlv->num_instances; i++) { - NasGetRfBandInfoBandWidth *band = &ptlv->bands_array[i]; - - printf ("\tRadio Interface: '%s'\n" - "\tBandwidth: '%u'\n", - qmi_nas_radio_interface_get_string (band->radio_if), - (band->bandwidth)); - } - } - } - - free(pResponse); - return 0; -} -#endif diff --git a/quectel_cm_5G/src/QMIThread.h b/quectel_cm_5G/src/QMIThread.h deleted file mode 100644 index b5dfe1a..0000000 --- a/quectel_cm_5G/src/QMIThread.h +++ /dev/null @@ -1,420 +0,0 @@ -#ifndef __QMI_THREAD_H__ -#define __QMI_THREAD_H__ - -#define CONFIG_GOBINET -#define CONFIG_QMIWWAN -#define CONFIG_SIM -#define CONFIG_APN -#define CONFIG_VERSION -//#define CONFIG_SIGNALINFO -//#define CONFIG_CELLINFO -//#define CONFIG_COEX_WWAN_STATE -#define CONFIG_DEFAULT_PDP 1 -//#define CONFIG_IMSI_ICCID -#define QUECTEL_UL_DATA_AGG -//#define QUECTEL_QMI_MERGE -//#define REBOOT_SIM_CARD_WHEN_APN_CHANGE -//#define REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS 60 //unit is seconds -//#define CONFIG_QRTR -//#define CONFIG_ENABLE_QOS -//#define CONFIG_REG_QOS_IND -//#define CONFIG_GET_QOS_INFO -//#define CONFIG_GET_QOS_DATA_RATE - -#if (defined(CONFIG_REG_QOS_IND) || defined(CONFIG_GET_QOS_INFO) || defined(CONFIG_GET_QOS_DATA_RATE)) -#ifndef CONFIG_REG_QOS_IND -#define CONFIG_REG_QOS_IND -#endif -#ifndef CONFIG_ENABLE_QOS -#define CONFIG_ENABLE_QOS -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qendian.h" -#include "MPQMI.h" -#include "MPQCTL.h" -#include "MPQMUX.h" -#include "util.h" - -#define DEVICE_CLASS_UNKNOWN 0 -#define DEVICE_CLASS_CDMA 1 -#define DEVICE_CLASS_GSM 2 - -#define WWAN_DATA_CLASS_NONE 0x00000000 -#define WWAN_DATA_CLASS_GPRS 0x00000001 -#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */ -#define WWAN_DATA_CLASS_UMTS 0x00000004 -#define WWAN_DATA_CLASS_HSDPA 0x00000008 -#define WWAN_DATA_CLASS_HSUPA 0x00000010 -#define WWAN_DATA_CLASS_LTE 0x00000020 -#define WWAN_DATA_CLASS_5G_NSA 0x00000040 -#define WWAN_DATA_CLASS_5G_SA 0x00000080 -#define WWAN_DATA_CLASS_1XRTT 0x00010000 -#define WWAN_DATA_CLASS_1XEVDO 0x00020000 -#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000 -#define WWAN_DATA_CLASS_1XEVDV 0x00080000 -#define WWAN_DATA_CLASS_3XRTT 0x00100000 -#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */ -#define WWAN_DATA_CLASS_UMB 0x00400000 -#define WWAN_DATA_CLASS_CUSTOM 0x80000000 - -struct wwan_data_class_str { - ULONG class; - const char *str; -}; - -#pragma pack(push, 1) -typedef struct __IPV4 { - uint32_t Address; - uint32_t Gateway; - uint32_t SubnetMask; - uint32_t DnsPrimary; - uint32_t DnsSecondary; - uint32_t Mtu; -} IPV4_T; - -typedef struct __IPV6 { - UCHAR Address[16]; - UCHAR Gateway[16]; - UCHAR SubnetMask[16]; - UCHAR DnsPrimary[16]; - UCHAR DnsSecondary[16]; - UCHAR PrefixLengthIPAddr; - UCHAR PrefixLengthGateway; - ULONG Mtu; -} IPV6_T; - -typedef struct { - UINT size; - UINT rx_urb_size; - UINT ep_type; - UINT iface_id; - UINT MuxId; - UINT ul_data_aggregation_max_datagrams; //0x17 - UINT ul_data_aggregation_max_size ;//0x18 - UINT dl_minimum_padding; //0x1A -} QMAP_SETTING; - -//Configured downlink data aggregationprotocol -#define WDA_DL_DATA_AGG_DISABLED (0x00) //DL data aggregation is disabled (default) -#define WDA_DL_DATA_AGG_TLP_ENABLED (0x01) // DL TLP is enabled -#define WDA_DL_DATA_AGG_QC_NCM_ENABLED (0x02) // DL QC_NCM isenabled -#define WDA_DL_DATA_AGG_MBIM_ENABLED (0x03) // DL MBIM isenabled -#define WDA_DL_DATA_AGG_RNDIS_ENABLED (0x04) // DL RNDIS is enabled -#define WDA_DL_DATA_AGG_QMAP_ENABLED (0x05) // DL QMAP isenabled -#define WDA_DL_DATA_AGG_QMAP_V2_ENABLED (0x06) // DL QMAP V2 is enabled -#define WDA_DL_DATA_AGG_QMAP_V3_ENABLED (0x07) // DL QMAP V3 is enabled -#define WDA_DL_DATA_AGG_QMAP_V4_ENABLED (0x08) // DL QMAP V4 is enabled -#define WDA_DL_DATA_AGG_QMAP_V5_ENABLED (0x09) // DL QMAP V5 is enabled - -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int qmap_mode; - unsigned int qmap_version; - unsigned int dl_minimum_padding; - char ifname[8][16]; - unsigned char mux_id[8]; -} RMNET_INFO; - -#define IpFamilyV4 (0x04) -#define IpFamilyV6 (0x06) - -struct __PROFILE; -struct qmi_device_ops { - int (*init)(struct __PROFILE *profile); - int (*deinit)(void); - int (*send)(PQCQMIMSG pRequest); - void* (*read)(void *pData); -}; -#ifdef CONFIG_QRTR -extern const struct qmi_device_ops qrtr_qmidev_ops; -#endif -extern const struct qmi_device_ops gobi_qmidev_ops; -extern const struct qmi_device_ops qmiwwan_qmidev_ops; -extern const struct qmi_device_ops mbim_dev_ops; -extern const struct qmi_device_ops atc_dev_ops; -extern int (*qmidev_send)(PQCQMIMSG pRequest); - -struct usb_device_info { - int idVendor; - int idProduct; - int busnum; - int devnum; - int bNumInterfaces; -}; - -struct usb_interface_info { - int bNumEndpoints; - int bInterfaceClass; - int bInterfaceSubClass; - int bInterfaceProtocol; - char driver[32]; -}; - -#define LIBQMI_PROXY "qmi-proxy" //src/libqmi-glib/qmi-proxy.h -#define LIBMBIM_PROXY "mbim-proxy" -#define QUECTEL_QMI_PROXY "quectel-qmi-proxy" -#define QUECTEL_MBIM_PROXY "quectel-mbim-proxy" -#define QUECTEL_ATC_PROXY "quectel-atc-proxy" -#define QUECTEL_QRTR_PROXY "quectel-qrtr-proxy" - -#ifndef bool -#define bool uint8_t -#endif -struct request_ops; -typedef struct __PROFILE { - //user input start - const char *apn; - const char *user; - const char *password; - int auth; - int iptype; - const char *pincode; - char proxy[32]; - int pdp; - int enable_bridge; - bool enable_ipv4; - bool enable_ipv6; - const char *logfile; - const char *usblogfile; - char expect_adapter[32]; - int kill_pdp; - int replication_factor; - //user input end - - char qmichannel[32]; - char usbnet_adapter[32]; - char qmapnet_adapter[32]; - char driver_name[32]; - int qmap_mode; - int qmap_size; - int qmap_version; - int curIpFamily; - int rawIP; - int muxid; -#ifdef CONFIG_ENABLE_QOS - UINT qos_id; -#endif - int wda_client; - IPV4_T ipv4; - IPV6_T ipv6; - UINT PCSCFIpv4Addr1; - UINT PCSCFIpv4Addr2; - UCHAR PCSCFIpv6Addr1[16]; - UCHAR PCSCFIpv6Addr2[16]; - bool reattach_flag; - int hardware_interface; - int software_interface; - - struct usb_device_info usb_dev; - struct usb_interface_info usb_intf; - - int usbmon_fd; - FILE *usbmon_logfile_fp; - bool loopback_state; - - char BaseBandVersion[64]; - char old_apn[64]; - char old_user[64]; - char old_password[64]; - int old_auth; - int old_iptype; - - const struct qmi_device_ops *qmi_ops; - const struct request_ops *request_ops; - RMNET_INFO rmnet_info; -} PROFILE_T; - -#ifdef QUECTEL_QMI_MERGE -#define MERGE_PACKET_IDENTITY 0x2c7c -#define MERGE_PACKET_VERSION 0x0001 -#define MERGE_PACKET_MAX_PAYLOAD_SIZE 56 -typedef struct __QMI_MSG_HEADER { - uint16_t idenity; - uint16_t version; - uint16_t cur_len; - uint16_t total_len; -} QMI_MSG_HEADER; - -typedef struct __QMI_MSG_PACKET { - QMI_MSG_HEADER header; - uint16_t len; - char buf[4096]; -} QMI_MSG_PACKET; -#endif - -typedef enum { - SIM_ABSENT = 0, - SIM_NOT_READY = 1, - SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ - SIM_PIN = 3, - SIM_PUK = 4, - SIM_NETWORK_PERSONALIZATION = 5, - SIM_BAD = 6, -} SIM_Status; - -#pragma pack(pop) - -#define WDM_DEFAULT_BUFSIZE 256 -#define RIL_REQUEST_QUIT 0x1000 -#define RIL_INDICATE_DEVICE_CONNECTED 0x1002 -#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003 -#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004 -#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005 -#define MODEM_REPORT_RESET_EVENT 0x1006 -#define RIL_UNSOL_LOOPBACK_CONFIG_IND 0x1007 -#ifdef CONFIG_REG_QOS_IND -#define RIL_UNSOL_GLOBAL_QOS_FLOW_IND_QOS_ID 0x1008 -#endif - -extern pthread_mutex_t cm_command_mutex; -extern pthread_cond_t cm_command_cond; -extern unsigned int cm_recv_buf[1024]; -extern int cm_open_dev(const char *dev); -extern int cm_open_proxy(const char *name); -extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs); -extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned msecs, const char *funcname); -#define QmiThreadSendQMI(pRequest, ppResponse) QmiThreadSendQMITimeout(pRequest, ppResponse, 30 * 1000, __func__) -extern void QmiThreadRecvQMI(PQCQMIMSG pResponse); -extern void udhcpc_start(PROFILE_T *profile); -extern void udhcpc_stop(PROFILE_T *profile); -extern void ql_set_driver_link_state(PROFILE_T *profile, int link_state); -extern void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings); -extern void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info); -extern void dump_qmi(void *dataBuffer, int dataLen); -extern void qmidevice_send_event_to_main(int triger_event); -extern void qmidevice_send_event_to_main_ext(int triger_event, void *data, unsigned len); -extern uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType); -extern uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId); -#ifdef CONFIG_REG_QOS_IND -extern UCHAR ql_get_global_qos_flow_ind_qos_id(PQCQMIMSG pResponse, UINT *qos_id); -#endif -#ifdef CONFIG_GET_QOS_DATA_RATE -extern UCHAR ql_get_global_qos_flow_ind_data_rate(PQCQMIMSG pResponse, void *max_data_rate); -#endif - -struct request_ops { - int (*requestBaseBandVersion)(PROFILE_T *profile); - int (*requestSetEthMode)(PROFILE_T *profile); - int (*requestSetLoopBackState)(UCHAR loopback_state, ULONG replication_factor); - int (*requestGetSIMStatus)(SIM_Status *pSIMStatus); - int (*requestEnterSimPin)(const char *pPinCode); - int (*requestSetProfile)(PROFILE_T *profile); // 1 ~ success and apn change, 0 ~ success and no apn change, -1 ~ fail - int (*requestGetProfile)(PROFILE_T *profile); - int (*requestRegistrationState)(UCHAR *pPSAttachedState); - int (*requestSetupDataCall)(PROFILE_T *profile, int curIpFamily); - int (*requestQueryDataCall)(UCHAR *pConnectionStatus, int curIpFamily); - int (*requestDeactivateDefaultPDP)(PROFILE_T *profile, int curIpFamily); - int (*requestGetIPAddress)(PROFILE_T *profile, int curIpFamily); - int (*requestGetSignalInfo)(void); - int (*requestGetCellInfoList)(void); - int (*requestGetICCID)(void); - int (*requestGetIMSI)(void); - int (*requestRadioPower)(int state); - int (*requestRegisterQos)(PROFILE_T *profile); - int (*requestGetQosInfo)(PROFILE_T *profile); - int (*requestGetCoexWWANState)(void); -}; -extern const struct request_ops qmi_request_ops; -extern const struct request_ops mbim_request_ops; -extern const struct request_ops atc_request_ops; - -extern int get_driver_type(PROFILE_T *profile); -extern BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile); -int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile); -int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile); -extern int ql_bridge_mode_detect(PROFILE_T *profile); -extern int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile); -extern int ql_qmap_mode_detect(PROFILE_T *profile); -#ifdef CONFIG_QRTR -extern int rtrmnet_ctl_create_vnd(char *devname, char *vndname, uint8_t muxid, - uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size); -#endif - -#define qmidev_is_gobinet(_qmichannel) (strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0) -#define qmidev_is_qmiwwan(_qmichannel) (strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0) -#define qmidev_is_pciemhi(_qmichannel) (strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0) - -#define driver_is_qmi(_drv_name) (strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0) -#define driver_is_mbim(_drv_name) (strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0) - -extern FILE *logfilefp; -extern int debug_qmi; -extern int qmidevice_control_fd[2]; -extern int g_donot_exit_when_modem_hangup; -extern void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2); -void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix); -void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix); -int reattach_driver(PROFILE_T *profile); -extern void no_trunc_strncpy(char *dest, const char *src, size_t dest_size); - -enum -{ - DRV_INVALID, - SOFTWARE_QMI, - SOFTWARE_MBIM, - SOFTWARE_ECM_RNDIS_NCM, - SOFTWARE_QRTR, - HARDWARE_PCIE, - HARDWARE_USB, -}; - -enum -{ - SIG_EVENT_START, - SIG_EVENT_CHECK, - SIG_EVENT_STOP, -}; - -typedef enum -{ - DMS_OP_MODE_ONLINE, - DMS_OP_MODE_LOW_POWER, - DMS_OP_MODE_FACTORY_TEST_MODE, - DMS_OP_MODE_OFFLINE, - DMS_OP_MODE_RESETTING, - DMS_OP_MODE_SHUTTING_DOWN, - DMS_OP_MODE_PERSISTENT_LOW_POWER, - DMS_OP_MODE_MODE_ONLY_LOW_POWER, - DMS_OP_MODE_NET_TEST_GW, -}Device_operating_mode; - -#ifdef CM_DEBUG -#define dbg_time(fmt, args...) do { \ - fprintf(stdout, "[%15s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \ - fflush(stdout);\ - if (logfilefp) fprintf(logfilefp, "[%s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \ -} while(0) -#else -#define dbg_time(fmt, args...) do { \ - fprintf(stdout, "[%s] " fmt "\n", get_time(), ##args); \ - fflush(stdout);\ - if (logfilefp) fprintf(logfilefp, "[%s] " fmt "\n", get_time(), ##args); \ -} while(0) -#endif -#endif diff --git a/quectel_cm_5G/src/QmiWwanCM.c b/quectel_cm_5G/src/QmiWwanCM.c deleted file mode 100644 index ede5a07..0000000 --- a/quectel_cm_5G/src/QmiWwanCM.c +++ /dev/null @@ -1,459 +0,0 @@ -/****************************************************************************** - @file QmiWwanCM.c - @brief QMI WWAN connectivity manager. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - -#include -#include -#include -#include -#include -#include "QMIThread.h" - -#ifdef CONFIG_QMIWWAN -static int cdc_wdm_fd = -1; -static UCHAR qmiclientId[QMUX_TYPE_ALL]; - -static UCHAR GetQCTLTransactionId(void) { - static int TransactionId = 0; - if (++TransactionId > 0xFF) - TransactionId = 1; - return TransactionId; -} - -typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg); - -static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType, CUSTOMQCTL customQctlMsgFunction, void *arg) { - UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE]; - PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf; - int Length; - - pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRequest->QMIHdr.CtlFlags = 0x00; - pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL; - pRequest->QMIHdr.ClientId= 0x00; - - pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; - pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId(); - pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType); - if (customQctlMsgFunction) - pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) - sizeof(QCQMICTL_MSG_HDR)); - else - pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000); - - pRequest->QMIHdr.Length = cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1); - Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - - pRequest = (PQCQMIMSG)malloc(Length); - if (pRequest == NULL) { - dbg_time("%s fail to malloc", __func__); - } else { - memcpy(pRequest, QMIBuf, Length); - } - - return pRequest; -} - -static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - (void)arg; - QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001); - QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL; - return sizeof(QMICTL_GET_VERSION_REQ_MSG); -} - -static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) { - QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001); - QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0]; - return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG); -} - -static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) { - QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002); - QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0]; - QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1] ; - return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG); -} - -static USHORT CtlLibQmiProxyOpenReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - (void)arg; - const char *device_path = (const char *)(arg); - QCTLMsg->LibQmiProxyOpenReq.TLVType = 0x01; - QCTLMsg->LibQmiProxyOpenReq.TLVLength = cpu_to_le16(strlen(device_path)); - //strcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path); - //__builtin___strcpy_chk - memcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path, strlen(device_path)); - return sizeof(QMICTL_LIBQMI_PROXY_OPEN_MSG) + (strlen(device_path)); -} - -static int libqmi_proxy_open(const char *cdc_wdm) { - int ret; - PQCQMIMSG pResponse; - - ret = QmiThreadSendQMI(ComposeQCTLMsg(QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN, - CtlLibQmiProxyOpenReq, (void *)cdc_wdm), &pResponse); - if (!ret && pResponse - && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 - && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { - ret = 0; - } - else { - return -1; - } - - if (pResponse) - free(pResponse); - - return ret; -} - -static int QmiWwanSendQMI(PQCQMIMSG pRequest) { - struct pollfd pollfds[]= {{cdc_wdm_fd, POLLOUT, 0}}; - int ret; - - if (cdc_wdm_fd == -1) { - dbg_time("%s cdc_wdm_fd = -1", __func__); - return -ENODEV; - } - - if (pRequest->QMIHdr.QMIType != QMUX_TYPE_CTL) { - pRequest->QMIHdr.ClientId = qmiclientId[pRequest->QMIHdr.QMIType]; - if (pRequest->QMIHdr.ClientId == 0) { - dbg_time("QMIType %d has no clientID", pRequest->QMIHdr.QMIType); - return -ENODEV; - } - - if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6) - pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS; - } - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while ((ret < 0) && (errno == EINTR)); - - if (pollfds[0].revents & POLLOUT) { - ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - ret = write(cdc_wdm_fd, pRequest, nwrites); - if (ret == nwrites) { - ret = 0; - } else { - dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - } - } else { - dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret, pollfds[0].revents, errno, strerror(errno)); - } - - return ret; -} - -static UCHAR QmiWwanGetClientID(UCHAR QMIType) { - PQCQMIMSG pResponse; - - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType), &pResponse); - - if (pResponse) { - USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult); // QMI_RESULT_SUCCESS - USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError); // QMI_ERR_INVALID_ARG - //UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType; - UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId; - - if (!QMUXResult && !QMUXError && (QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) { - switch (QMIType) { - case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; - case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; - case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; - case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; - case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; - case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; - case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; - case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break; - case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); - break; - default: break; - } - return ClientId; - } - } - return 0; -} - -static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId) { - UCHAR argv[] = {QMIType, ClientId}; - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ, CtlReleaseClientIdReq, argv), NULL); - return 0; -} - -static int QmiWwanInit(PROFILE_T *profile) { - unsigned i; - int ret; - PQCQMIMSG pResponse; - - if (profile->proxy[0] && !strcmp(profile->proxy, LIBQMI_PROXY)) { - ret = libqmi_proxy_open(profile->qmichannel); - if (ret) - return ret; - } - - if (!profile->proxy[0]) { - for (i = 0; i < 10; i++) { - ret = QmiThreadSendQMITimeout(ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000, __func__); - if (!ret) - break; - sleep(1); - } - if (ret) - return ret; - } - - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL), &pResponse); - if (profile->qmap_mode) { - if (pResponse) { - if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { - uint8_t NumElements = 0; - - for (NumElements = 0; NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements; NumElements++) { -#if 0 - dbg_time("QMUXType = %02x Version = %d.%d", - pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType, - pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MajorVersion, - pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion); -#endif - if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType == QMUX_TYPE_WDS_ADMIN) - profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion > 16); - } - } - } - } - if (pResponse) free(pResponse); - qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS); - if (profile->enable_ipv6) - qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS); - qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS); - qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS); - qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM); - qmiclientId[QMUX_TYPE_WDS_ADMIN] = QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN); -#ifdef CONFIG_COEX_WWAN_STATE - qmiclientId[QMUX_TYPE_COEX] = QmiWwanGetClientID(QMUX_TYPE_COEX); -#endif -#ifdef CONFIG_ENABLE_QOS - qmiclientId[QMUX_TYPE_QOS] = QmiWwanGetClientID(QMUX_TYPE_QOS); -#endif - profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; - - return 0; -} - -static int QmiWwanDeInit(void) { - unsigned int i; - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - QmiWwanReleaseClientID(i, qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static ssize_t qmi_proxy_read (int fd, void *buf, size_t size) { - ssize_t nreads; - PQCQMI_HDR pHdr = (PQCQMI_HDR)buf; - - nreads = read(fd, pHdr, sizeof(QCQMI_HDR)); - if (nreads == sizeof(QCQMI_HDR) && le16_to_cpu(pHdr->Length) < size) { - nreads += read(fd, pHdr+1, le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR)); - } - - return nreads; -} - -#ifdef QUECTEL_QMI_MERGE -static int QmiWwanMergeQmiRsp(void *buf, ssize_t *src_size) { - static QMI_MSG_PACKET s_QMIPacket; - QMI_MSG_HEADER *header = NULL; - ssize_t size = *src_size; - - if((uint16_t)size < sizeof(QMI_MSG_HEADER)) - return -1; - - header = (QMI_MSG_HEADER *)buf; - if(le16_to_cpu(header->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(header->version) != MERGE_PACKET_VERSION || le16_to_cpu(header->cur_len) > le16_to_cpu(header->total_len)) - return -1; - - if(le16_to_cpu(header->cur_len) == le16_to_cpu(header->total_len)) { - *src_size = le16_to_cpu(header->total_len); - memcpy(buf, buf + sizeof(QMI_MSG_HEADER), *src_size); - s_QMIPacket.len = 0; - return 0; - } - - memcpy(s_QMIPacket.buf + s_QMIPacket.len, buf + sizeof(QMI_MSG_HEADER), le16_to_cpu(header->cur_len)); - s_QMIPacket.len += le16_to_cpu(header->cur_len); - - if (le16_to_cpu(header->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || s_QMIPacket.len >= le16_to_cpu(header->total_len)) { - memcpy(buf, s_QMIPacket.buf, s_QMIPacket.len); - *src_size = s_QMIPacket.len; - s_QMIPacket.len = 0; - return 0; - } - - return -1; -} -#endif - -static void * QmiWwanThread(void *pData) { - PROFILE_T *profile = (PROFILE_T *)pData; - const char *cdc_wdm = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - char num = cdc_wdm[strlen(cdc_wdm)-1]; - - if (profile->proxy[0]) { - if (!strncmp(profile->proxy, QUECTEL_QMI_PROXY, strlen(QUECTEL_QMI_PROXY))) { - snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num); - } - } - else if (!strncmp(cdc_wdm, "/dev/mhi_IPCR", strlen("/dev/mhi_IPCR"))) { - snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QRTR_PROXY, num); - } - else if (profile->qmap_mode > 1) { - snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num); - } - - if (profile->proxy[0]) - cdc_wdm_fd = cm_open_proxy(profile->proxy); - else - cdc_wdm_fd = cm_open_dev(cdc_wdm); - - if (cdc_wdm_fd == -1) { - dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm, errno, strerror(errno)); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - pthread_exit(NULL); - return NULL; - } - - dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd); - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - while (1) { - struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0}, {cdc_wdm_fd, POLLIN, 0}}; - int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]); - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI(NULL); - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - //dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events, pollfds[ne].revents); - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("poll fd = %d, events = 0x%04x", fd, revents); - if (fd == cdc_wdm_fd) { - } else { - } - if (revents & (POLLHUP | POLLNVAL)) //EC20 bug, Can get POLLERR - goto __QmiWwanThread_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __QmiWwanThread_quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - - if (fd == cdc_wdm_fd) { - ssize_t nreads; - PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; - - if (!profile->proxy[0]) - nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf)); - else - nreads = qmi_proxy_read(fd, cm_recv_buf, sizeof(cm_recv_buf)); - //dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - if (nreads <= 0) { - dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - break; - } -#ifdef QUECTEL_QMI_MERGE - if((profile->qmap_mode == 0 || profile->qmap_mode == 1) && QmiWwanMergeQmiRsp(cm_recv_buf, &nreads)) - continue; -#endif - if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) { - dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d", __func__, (int)nreads, le16_to_cpu(pResponse->QMIHdr.Length)); - continue; - } - - QmiThreadRecvQMI(pResponse); - } - } - } - -__QmiWwanThread_quit: - if (cdc_wdm_fd != -1) { close(cdc_wdm_fd); cdc_wdm_fd = -1; } - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -const struct qmi_device_ops qmiwwan_qmidev_ops = { - .init = QmiWwanInit, - .deinit = QmiWwanDeInit, - .send = QmiWwanSendQMI, - .read = QmiWwanThread, -}; - -uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType) { - return QmiWwanGetClientID(QMIType); -} - -uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId) { - return QmiWwanReleaseClientID(QMIType, ClientId); -} -#endif - diff --git a/quectel_cm_5G/src/ReleaseNote.txt b/quectel_cm_5G/src/ReleaseNote.txt deleted file mode 100644 index 430babe..0000000 --- a/quectel_cm_5G/src/ReleaseNote.txt +++ /dev/null @@ -1,325 +0,0 @@ -Release Notes - -[V1.6.4] -Date: 9/7/2022 -enhancement: - 1. set cflags as -Wall -Wextra -Werror -O1, and fix compile errors - 2. some code refactoring - 3. add quectel-qrtr-proxy -fix: - 1. netmask error when use ifconfig on little endian cpu - -[V1.6.2] -Date: 11/18/2021 -enhancement: - 1. support 'LTE && WiFi Coexistence Solution via QMI'. - If customer want use this feature, need enable CONFIG_COEX_WWAN_STATE in QMIThread.h - -[V1.6.1] -Date: 7/20/2021 -enhancement: - 1. add requestGetCellInfoList requestRadioPower - 2. add QMI OVER MBIM - 3. support qrtr and rmnet - 4. support RG500U PCIE - 5. add qos service && get qos flow data_rate_max func -fix: - 1. mbim: increase mbim open timeout to 3 seconds. some modem take long time for open cmd. - 2. support MsChapV2 - 3. mbim: invalid memory access when only get one DNS - 4. some bug fix for use AT Command to setup data call - -[V1.6.0.26] -Date: 4/22/2021 -enhancement: - 1. add lots of log file to show how to use this tool - 2. support pcie mhi multiple call - 3. at command: support EC200U/EC200T/EC200S/RG801H/RG500U/ -fix: - 1. mbim-proxy: fix errors on big endian cpu, ignore mbim open/close cmd from quectel-cm - -[V1.6.0.25] -Date: 4/8/2021 -enhancement: -fix: - 1. fix compile error when use gcc 9.3.0 - 2. fix yocto 'QA Issue: No GNU_HASH in the ELF binary' - -[V1.6.0.24] -Date: 3/9/2021 -enhancement: - 1. '-p [quectel-][qmi|mbim]-proxy', can connect to quectel/libqmi/libmbim's proxy, even only one data - 2. set variable s_9x07 as 1 (from 0), most of modems are base on MDM90x7 and later QCOM chip. -fix: - 1. define CHAR as signed char - 2. mofidy Makefile to generate more compile warnnings and fix them - -[V1.6.0.23] -Date: 2/26/2021 -enhancement: - 1. support 'AT+QNETDEVCTL' (not release) -fix: - 1. modify help/usage - 2. fix some memroy access error in mbim-cm.c - -[V1.6.0.22] -Date: 2/4/2021 -enhancement: - 1. support connect to libqmi's qmi-proxy - 2. only allow ' 0/1/2/none/pap/chap' for auth of '-s' - 3. '-m iface-idx' bind QMAP data call to wwan0_ -fix: - -[V1.6.0.21] -Date: 1/28/2021 -enhancement: - 1. print 5G signal -fix: - 1. fix compile errors: -Werror=format-truncation= - -[V1.6.0.20] -Date: 12/29/2020 -enhancement: - 1. Code refactoring - 2. support 'AT+QNETDEVCTL' (not release) -fix: - -[V1.6.0.19] -Date: 12/4/2020 -enhancement: - 1. if 'udhcpc's default.script' missed, directy set ip/dns/route by 'ip' co,mand -fix: - -[V1.6.0.18] -Date: 12/4/2020 -enhancement: - 1. Code refactoring -fix: - -[V1.6.0.17] -Date: 8/25/2020 -enhancement: - 1. support MBIM multi-call - 2. support unisoc RG500U mbim - 3. QUECTEL_QMI_MERGE: some SOC can not read more then 64 bytes (QMI)data via USB Endpoint 0 -fix: - -[V1.6.0.15] -Date: 7/24/2020 -enhancement: -fix: - 1. QMAP multi-call, AT+CFUN=4 then AT+CFUN=1, only one call can obtain IP by DHCP - -[V1.6.0.14] -Date: 6/10/2020 -enhancement: - 1. support X55's GobiNet LOOPBACK -fix: - 1. very old uclib do not support htole32 and pthread_condattr_setclock - 2. pthread_cond_wait tv_nsec >= 1000000000U is wrong - 3. do not close socket in udhcpc.c ifc_get_addr() - -[V1.6.0.13] -Date: 6/9/2020 -enhancement: - 1. add some example for openwrt, marco 'QL_OPENWER_NETWORK_SETUP' -fix: - -[V1.6.0.12] -Date: 5/29/2020 -enhancement: -fix: - 1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4) - -[V1.6.0.11] -Date: 5/28/2020 -enhancement: -fix: - 1. fix mbim debug on Big Endian CPU - -[V1.6.0.10] -Date: 5/25/2020 -enhancement: -fix: - 1. set QMAP .ul_data_aggregation_max_datagrams to 11 (from 16) - -[V1.6.0.9] -Date: 5/22/2020 -enhancement: -fix: - 1. dial fail when register to 5G-SA - -[V1.6.0.8] -Date: 4/30/2020 -enhancement: - 1. support '-b' to seletc brige mode -fix: - -[V1.6.0.7] -Date: 4/29/2020 -enhancement: - 1. support QMAP multi-call for qmi_wwan_q and pcie_mhi 's rmnet driver -fix: - -[V1.6.0.6] -Date: 4/20/2020 -enhancement: - 1. support '-k pdn_idx' to hangup call '-n pdn_idx' -fix: - 1. fix set dl_minimum_padding as 0, modems do not support this featrue - -[V1.6.0.5] -Date: 4/10/2020 -enhancement: - 1. support X55's QMAPV5 for PCIE -fix: - -[V1.6.0.3] -Date: 4/8/2020 -enhancement: - 1. support multi-modems all use multi-data-calls -fix: - -[V1.6.0.2] -Date: 4/7/2020 -enhancement: - 1. support X55's QMAPV5 for USB -fix: - -[V1.6.0.1] -Date: 4/1/2020 -enhancement: - 1. support QMAP UL AGG (multi data call) -fix: - 1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4) - -[V1.5.9] -Date: 3/4/2020 -enhancement: - 1. support pcie mhi multi-APN data call - 3. support QMAP UL AGG (single data call) -fix: - 1. set 4 bytes aligned for mbim parameters, or cause dial mbim call fail - -[V1.5.8] -Date: 2/18/2020 -enhancement: - 1. support '-l 14' X55's loopback function -fix: - -[V1.5.7] -Date: 2/6/2020 -enhancement: - 1. support '-u usbmon_log_file' to catch usbmon log -fix: - -[V1.5.6] -Date: 1/20/202 -enhancement: - 1. show driver name and version - 2. support PCSCF - 3. support bridge in mbim -fix: - -[V1.5.5] -Date: 12/31/2019 -enhancement: -fix: - 1. fix some memory access bug in mbim-cm.c - -[WCDMA<E_QConnectManager_Linux&Android_V1.5.4] -Date: 12/17/2019 -enhancement: - 1. Add copyright - 2. auto detect pcie mhi /dev/mhi* -fix: - -[WCDMA<E_QConnectManager_Linux&Android_V1.5.3] -Date: 2019/12/11 -enhancement: -1. support show SignalInfo, controlled by macro CONFIG_SIGNALINFO -2. support show 5G_NSA/5G_NA -3. support Microsoft Extend MBIM message -fix: -1. quectel-qmi-proxy bugs on Big-Endian CPU - -[WCDMA<E_QConnectManager_Linux&Android_V1.5.2] -Date: 12/2/2019 -enhancement: - 1. support requestGetSignalInfo() -fix: - -[WCDMA<E_QConnectManager_Linux&Android_V1.4.1] -Date: 10/23/2019 -enhancement: - 1. support QMI_CTL_REVOKE_CLIENT_ID_IND (Quectel define QMI) - 2. add copyright -fix: - 1. remove SIGUSR - -[WCDMA<E_QConnectManager_Linux&Android_V1.3.10] -Date: 10/14/2019 -enhancement: - 1. increase retry interval -fix: - -[WCDMA<E_QConnectManager_Linux&Android_V1.2.1] -Date: 2019/02/26 -enhancement: -1. Implement help message. - -root@ubuntu:# ./quectel-CM -h -[02-26_10:39:21:353] Usage: ./quectel-CM [options] -[02-26_10:39:21:353] -s [apn [user password auth]] Set apn/user/password/auth get from your network provider -[02-26_10:39:21:353] -p pincode Verify sim card pin if sim card is locked -[02-26_10:39:21:353] -f logfilename Save log message of this program to file -[02-26_10:39:21:353] -i interface Specify network interface(default auto-detect) -[02-26_10:39:21:353] -4 IPv4 protocol -[02-26_10:39:21:353] -6 IPv6 protocol -[02-26_10:39:21:353] -m muxID Specify muxid when set multi-pdn data connection. -[02-26_10:39:21:353] -n channelID Specify channelID when set multi-pdn data connection(default 1). -[02-26_10:39:21:353] [Examples] -[02-26_10:39:21:353] Example 1: ./quectel-CM -[02-26_10:39:21:353] Example 2: ./quectel-CM -s 3gnet -[02-26_10:39:21:353] Example 3: ./quectel-CM -s 3gnet carl 1234 0 -p 1234 -f gobinet_log.txt -root@ubuntu:# -2. Support bridge mode when set multi-pdn data connections. -3. Host device can access network in bridge mode. - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.46] -Date: 2019/02/18 -enhancement: -1. support only IPV6 data call. quectel-CM now support three dialing methods: IPV4 only, IPV6 only, IPV4V6. - ./quectel-CM -4(or no argument) only IPV4 - -6 only IPV6 - -4 -6 IPV4 && IPV6 - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.45] -Date: 2018/09/13 -enhancement: -1. support EG12 PCIE interface - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.44] -Date: 2018/09/10 -enhancement: -1. support setup IPV4&IPV6 data call. - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.43] -[WCDMA<E_QConnectManager_Linux&Android_V1.1.42] -Date: 2018/08/29 -enhancement: -1. support QMI_WWAN's QMAP fucntion and bridge mode, please contact Quectel FAE to get qmi_wwan.c patch. - when enable QMI_WWAN's QMAP IP Mux function, must run 'quectel-qmi-proxy -d /dev/cdc-wdmX' before quectel-CM - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.41] -Date: 2018/05/24 -enhancement: -1. fix a cdma data call error - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.40] -Date: 2018/05/12 -enhancement: -1. support GobiNet's QMAP fucntion and bridge mode. - 'Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.5' and later version is required to use QMAP and bridge mode. - for detail, please refer to GobiNet Driver - diff --git a/quectel_cm_5G/src/at_tok.c b/quectel_cm_5G/src/at_tok.c deleted file mode 100644 index 6736cc8..0000000 --- a/quectel_cm_5G/src/at_tok.c +++ /dev/null @@ -1,283 +0,0 @@ -/* //device/system/reference-ril/at_tok.c -** -** Copyright 2006, The Android Open Source Project -** -** 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. -*/ - -#include "at_tok.h" -#include -#include -#include -#include -#include - -/** - * Starts tokenizing an AT response string - * returns -1 if this is not a valid response string, 0 on success. - * updates *p_cur with current position - */ -int at_tok_start(char **p_cur) -{ - if (*p_cur == NULL) { - return -1; - } - - // skip prefix - // consume "^[^:]:" - - *p_cur = strchr(*p_cur, ':'); - - if (*p_cur == NULL) { - return -1; - } - - (*p_cur)++; - - return 0; -} - -static void skipWhiteSpace(char **p_cur) -{ - if (*p_cur == NULL) return; - - while (**p_cur != '\0' && isspace(**p_cur)) { - (*p_cur)++; - } -} - -static void skipNextComma(char **p_cur) -{ - if (*p_cur == NULL) return; - - while (**p_cur != '\0' && **p_cur != ',') { - (*p_cur)++; - } - - if (**p_cur == ',') { - (*p_cur)++; - } -} - -static char * nextTok(char **p_cur) -{ - char *ret = NULL; - - skipWhiteSpace(p_cur); - - if (*p_cur == NULL) { - ret = NULL; - } else if (**p_cur == '"') { - (*p_cur)++; - ret = strsep(p_cur, "\""); - skipNextComma(p_cur); - } else { - ret = strsep(p_cur, ","); - } - - return ret; -} - - -/** - * Parses the next integer in the AT response line and places it in *p_out - * returns 0 on success and -1 on fail - * updates *p_cur - * "base" is the same as the base param in strtol - */ - -static int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns) -{ - char *ret; - - if (*p_cur == NULL) { - return -1; - } - - ret = nextTok(p_cur); - - if (ret == NULL) { - return -1; - } else { - long l; - char *end; - - if (uns) - l = strtoul(ret, &end, base); - else - l = strtol(ret, &end, base); - - *p_out = (int)l; - - if (end == ret) { - return -1; - } - } - - return 0; -} - -/** - * Parses the next base 10 integer in the AT response line - * and places it in *p_out - * returns 0 on success and -1 on fail - * updates *p_cur - */ -int at_tok_nextint(char **p_cur, int *p_out) -{ - return at_tok_nextint_base(p_cur, p_out, 10, 0); -} - -/** - * Parses the next base 16 integer in the AT response line - * and places it in *p_out - * returns 0 on success and -1 on fail - * updates *p_cur - */ -int at_tok_nexthexint(char **p_cur, int *p_out) -{ - return at_tok_nextint_base(p_cur, p_out, 16, 1); -} - -int at_tok_nextbool(char **p_cur, char *p_out) -{ - int ret; - int result; - - ret = at_tok_nextint(p_cur, &result); - - if (ret < 0) { - return -1; - } - - // booleans should be 0 or 1 - if (!(result == 0 || result == 1)) { - return -1; - } - - if (p_out != NULL) { - *p_out = (char)result; - } - - return ret; -} - -int at_tok_nextstr(char **p_cur, char **p_out) -{ - if (*p_cur == NULL) { - return -1; - } - - *p_out = nextTok(p_cur); - - return 0; -} - -/** returns 1 on "has more tokens" and 0 if no */ -int at_tok_hasmore(char **p_cur) -{ - return ! (*p_cur == NULL || **p_cur == '\0'); -} - -int at_tok_count(const char *in_line) -{ - int commas = 0; - const char *p; - - if (!in_line) - return 0; - - for (p = in_line; *p != '\0' ; p++) { - if (*p == ',') commas++; - } - - return commas; -} - -//fmt: d ~ int, x ~ hexint, b ~ bool, s ~ str -int at_tok_scanf(const char *in_line, const char *fmt, ...) -{ - int n = 0; - int err; - va_list ap; - const char *p = fmt; - void *d; - void *dump; - static char s_line[1024]; - char *line = s_line; - - if (!in_line) - return 0; - - strncpy(s_line, in_line, sizeof(s_line) - 1); - - va_start(ap, fmt); - - err = at_tok_start(&line); - if (err < 0) goto error; - - for (; *p; p++) { - if (*p == ',' || *p == ' ') - continue; - - if (*p != '%') { - goto error; - } - p++; - - d = va_arg(ap, void *); - if (!d) - d = &dump; - - if (!at_tok_hasmore(&line)) - break; - - if (*line == '-' && *(line + 1) == ',') { - line += 2; - n++; - if (*p == 'd') - *(int *)d = -1; - continue; - } - - switch(*p) { - case 'd': - err = at_tok_nextint(&line, (int *)d); - if (err < 0) goto error; - break; - case 'x': - err = at_tok_nexthexint(&line, (int *)d); - if (err < 0) goto error; - break; - case 'b': - err = at_tok_nextbool(&line, (char *)d); - if (err < 0) goto error; - break; - case 's': - err = at_tok_nextstr(&line, (char **)d); //if strdup(line), here return free memory to caller - if (err < 0) goto error; - break; - default: - goto error; - break; - } - - n++; - } - - va_end(ap); - -error: - //free(line); - return n; -} diff --git a/quectel_cm_5G/src/at_tok.h b/quectel_cm_5G/src/at_tok.h deleted file mode 100644 index 2fcb683..0000000 --- a/quectel_cm_5G/src/at_tok.h +++ /dev/null @@ -1,33 +0,0 @@ -/* //device/system/reference-ril/at_tok.h -** -** Copyright 2006, The Android Open Source Project -** -** 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. -*/ - -#ifndef AT_TOK_H -#define AT_TOK_H 1 - -int at_tok_start(char **p_cur); -int at_tok_nextint(char **p_cur, int *p_out); -int at_tok_nexthexint(char **p_cur, int *p_out); - -int at_tok_nextbool(char **p_cur, char *p_out); -int at_tok_nextstr(char **p_cur, char **out); - -int at_tok_hasmore(char **p_cur); -int at_tok_count(const char *in_line); -int at_tok_scanf(const char *line, const char *fmt, ...); - -#endif /*AT_TOK_H */ - diff --git a/quectel_cm_5G/src/atc.c b/quectel_cm_5G/src/atc.c deleted file mode 100644 index d9fa61e..0000000 --- a/quectel_cm_5G/src/atc.c +++ /dev/null @@ -1,1054 +0,0 @@ -/****************************************************************************** - @file atc.c - @brief at command. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int asprintf(char **s, const char *fmt, ...); - -#include "QMIThread.h" - -#include "atchannel.h" -#include "at_tok.h" - -static int asr_style_atc = 0; -static int s_pdp; -#define safe_free(__x) do { if (__x) { free((void *)__x); __x = NULL;}} while(0) -#define safe_at_response_free(__x) { if (__x) { at_response_free(__x); __x = NULL;}} - -#define at_response_error(err, p_response) \ - (err \ - || p_response == NULL \ - || p_response->finalResponse == NULL \ - || p_response->success == 0) - -static int atc_init(PROFILE_T *profile) { - int err; - char *cmd; - ATResponse *p_response = NULL; - - if (profile->proxy[0]) { - s_pdp = profile->pdp; - err = at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); - if (at_response_error(err, p_response)) - asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support - safe_at_response_free(p_response); - - return err; - } - - err = at_handshake(); - if (err) { - dbg_time("handshake fail, TODO ... "); - goto exit; - } - - s_pdp = profile->pdp; - at_send_command_singleline("AT+QCFG=\"usbnet\"", "+QCFG:", NULL); - at_send_command_multiline("AT+QNETDEVCTL=?", "+QNETDEVCTL:", NULL); - at_send_command("AT+CGREG=2", NULL); //GPRS Network Registration Status - at_send_command("AT+CEREG=2", NULL); //EPS Network Registration Status - at_send_command("AT+C5GREG=2", NULL); //5GS Network Registration Status - - err = at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); - if (at_response_error(err, p_response)) - asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support - safe_at_response_free(p_response); - - err = at_send_command_singleline("AT+QCFG=\"NAT\"", "+QCFG:", &p_response); - if (!at_response_error(err, p_response)) { - int old_nat, new_nat = asr_style_atc ? 1 : 0; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s%d", NULL, &old_nat); - if (err == 2 && old_nat != new_nat) { - safe_at_response_free(p_response); - asprintf(&cmd, "AT+QCFG=\"NAT\",%d", new_nat); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (!at_response_error(err, p_response)) { - err = at_send_command("at+cfun=1,1",NULL); - if (!err) - g_donot_exit_when_modem_hangup = 1; - //reboot to take effect - } - safe_at_response_free(p_response); - } - err = 0; - } - safe_at_response_free(p_response); - -exit: - return err; -} - -static int atc_deinit(void) { - return 0; -} - -/** - * Called by atchannel when an unsolicited line appears - * This is called on atchannel's reader thread. AT commands may - * not be issued here - */ -static void onUnsolicited (const char *s, const char *sms_pdu) -{ - (void)sms_pdu; - - if (strStartsWith(s, "+QNETDEVSTATUS:")) { - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } - else if (strStartsWith(s, "+CGREG:") - || strStartsWith(s, "+CEREG:") - || strStartsWith(s, "+C5GREG:")) { - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } -} - -static void onTimeout(void) { - dbg_time("%s", __func__); - //TODO -} - -static void onClose(void) { - dbg_time("%s", __func__); -} - -static void * atc_read_thread(void *param) { - PROFILE_T *profile = (PROFILE_T *)param; - const char *cdc_wdm = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - int atc_fd; - - atc_fd = cm_open_dev(cdc_wdm); - if (atc_fd <= 0) { - dbg_time("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno)); - goto __quit; - } - - dbg_time("atc_fd = %d", atc_fd); - - if (at_open(atc_fd, onUnsolicited, 0)) - goto __quit; - - at_set_on_timeout(onTimeout); - at_set_on_reader_closed(onClose); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (atc_fd > 0) { - struct pollfd pollfds[] = {{atc_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}}; - int ne, ret, nevents = 2; - - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - - if (ret == 0 && wait_for_request_quit) { - break; - } - - if (ret < 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (atc_fd == fd) { - usleep(10*1000); //let atchannel.c read at response. - } - else if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //dbg_time("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - } - } - -__quit: - at_close(); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - dbg_time("%s exit", __func__); - - return NULL; -} - -const struct qmi_device_ops atc_dev_ops = { - .init = atc_init, - .deinit = atc_deinit, - .read = atc_read_thread, -}; - -static int requestBaseBandVersion(PROFILE_T *profile) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - - (void)profile; - - err = at_send_command_multiline("AT+CGMR", "\0", &p_response); - if (at_response_error(err, p_response)) - goto exit; - - if (p_response->p_intermediates && p_response->p_intermediates->line) { - strncpy(profile->BaseBandVersion, p_response->p_intermediates->line, sizeof(profile->BaseBandVersion) - 1); - retVal = 0; - } - -exit: - safe_at_response_free(p_response); - return retVal; -} - -static int requestGetSIMStatus(SIM_Status *pSIMStatus) -{ - int err; - ATResponse *p_response = NULL; - char *cpinLine; - char *cpinResult; - int ret = SIM_NOT_READY; - - err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response); - if (at_response_error(err, p_response)) - goto done; - - switch (at_get_cme_error(p_response)) - { - case CME_SUCCESS: - break; - - case CME_SIM_NOT_INSERTED: - case CME_OPERATION_NOT_ALLOWED: - case CME_FAILURE: - ret = SIM_ABSENT; - goto done; - - default: - ret = SIM_NOT_READY; - goto done; - } - - cpinLine = p_response->p_intermediates->line; - err = at_tok_start (&cpinLine); - - if (err < 0) - { - ret = SIM_NOT_READY; - goto done; - } - - err = at_tok_nextstr(&cpinLine, &cpinResult); - - if (err < 0) - { - ret = SIM_NOT_READY; - goto done; - } - - if (0 == strcmp (cpinResult, "SIM PIN")) - { - ret = SIM_PIN; - goto done; - } - else if (0 == strcmp (cpinResult, "SIM PUK")) - { - ret = SIM_PUK; - goto done; - } - else if (0 == strcmp (cpinResult, "PH-NET PIN")) - { - return SIM_NETWORK_PERSONALIZATION; - } - else if (0 != strcmp (cpinResult, "READY")) - { - /* we're treating unsupported lock types as "sim absent" */ - ret = SIM_ABSENT; - goto done; - } - - ret = SIM_READY; - -done: - safe_at_response_free(p_response); - *pSIMStatus = ret; - return err; -} - -static int requestEnterSimPin(const char *pPinCode) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - - asprintf(&cmd, "AT+CPIN=%s", pPinCode); - err = at_send_command(cmd, NULL); - safe_free(cmd); - - if (!at_response_error(err, p_response)) { - retVal = 0; - } - - safe_at_response_free(p_response); - return retVal; -} - -static int requestSetProfile(PROFILE_T *profile) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - const char *new_apn = profile->apn ? profile->apn : ""; - const char *new_user = profile->user ? profile->user : ""; - const char *new_password = profile->password ? profile->password : ""; - const char *ipStr[] = {"NULL", "IPV4", "IPV6", "IPV4V6"}; - - dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, - profile->pdp, profile->apn, profile->user, profile->password, - profile->auth,ipStr[profile->iptype]); - - if ( !strcmp(profile->old_apn, new_apn) && !strcmp(profile->old_user, new_user) - && !strcmp(profile->old_password, new_password) - && profile->old_iptype == profile->iptype - && profile->old_auth == profile->auth) - { - dbg_time("no need to set skip the rest"); - return 0; - } - - asprintf(&cmd, "AT+QICSGP=%d,%d,\"%s\",\"%s\",\"%s\",%d", - profile->pdp, profile->iptype, new_apn, new_user, new_password, profile->auth); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) { - safe_at_response_free(p_response); - asprintf(&cmd, "AT+CGDCONT=%d,\"%s\",\"%s\"", profile->pdp, ipStr[profile->iptype], new_apn); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - } - - safe_at_response_free(p_response); - return 1; -} - -static int requestGetProfile(PROFILE_T *profile) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - int pdp; - int old_iptype = 1; // 1 ~ IPV4, 2 ~ IPV6, 3 ~ IPV4V6 - char *old_apn = "", *old_user = "", *old_password = ""; - int old_auth = 0; - const char *ipStr[] = {"NULL", "IPV4", "IPV6", "IPV4V6"}; - - if (profile->enable_ipv4 && profile->enable_ipv6) - profile->iptype = 3; - else if (profile->enable_ipv6) - profile->iptype = 2; - else - profile->iptype = 1; - -_re_check: - asprintf(&cmd, "AT+QICSGP=%d", profile->pdp); - err = at_send_command_singleline(cmd, "+QICSGP:", &p_response); - safe_free(cmd); - if (err == AT_ERROR_INVALID_RESPONSE && p_response == NULL) { - //bug of RG801H - safe_at_response_free(p_response); - asprintf(&cmd, "AT+QICSGP=%d,%d,\"\",\"\",\"\",0", profile->pdp, profile->iptype); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (!at_response_error(err, p_response)) { - safe_at_response_free(p_response); - goto _re_check; - } - } - - if (!at_response_error(err, p_response)) { - err = at_tok_scanf(p_response->p_intermediates->line, - "%d%s%s%s%d", &old_iptype, &old_apn, &old_user, &old_password, &old_auth); - - if (err != 4 || pdp != profile->pdp) - goto _error; - } - else { - ATLine *atLine = NULL; - char *cgdcont_iptype = NULL; - - safe_at_response_free(p_response); - err = at_send_command_multiline("AT+CGDCONT?", "+CGDCONT:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - atLine = p_response->p_intermediates; - while (atLine) { - err = at_tok_scanf(atLine->line, "%d%s%s", &pdp, &cgdcont_iptype, &old_apn); - if (err == 3 && pdp == profile->pdp) { - if (!strcasecmp(cgdcont_iptype, ipStr[3])) - old_iptype = 3; - else if (!strcasecmp(cgdcont_iptype, ipStr[2])) - old_iptype = 2; - else - old_iptype = 1; - break; - } - old_apn = NULL; - atLine = atLine->p_next; - } - } - - retVal = 0; - -_error: - if (!old_apn) old_apn = ""; - if (!old_user) old_user = ""; - if (!old_password) old_password = ""; - - strncpy(profile->old_apn, old_apn, sizeof(profile->old_apn)); - strncpy(profile->old_user, old_user, sizeof(profile->old_user)); - strncpy(profile->old_password, old_password, sizeof(profile->old_password)); - profile->old_auth = old_auth; - profile->old_iptype = old_iptype; - - dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, - profile->pdp, profile->old_apn, profile->old_user, profile->old_password, - profile->old_auth, ipStr[profile->old_iptype]); - - safe_at_response_free(p_response); - - return retVal; -} - -static int requestRegistrationState(UCHAR *pPSAttachedState) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - ATLine *p_cur; - int i; - int cops_act = -1; - int state = 0, lac = 0, cid = 0, act = 0; - int commas; - char *line; - - *pPSAttachedState = 0; - - err = at_send_command_multiline( - "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", - "+COPS:", &p_response); - if (at_response_error(err, p_response)) - goto error; - -/* -AT< +COPS: 0,0,"CHINA MOBILE",13 -AT< +COPS: 0,1,"CMCC",13 -AT< +COPS: 0,2,"46000",13 -AT< OK -*/ - retVal = 0; - for (i = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { - err = at_tok_scanf(p_cur->line, "%d%d%s%d", NULL, NULL, NULL, &cops_act); - if (err != 4) goto error; - - break; - } - - safe_at_response_free(p_response); - switch (cops_act) { - case 2: //UTRAN - case 4: //UTRAN W/HSDPA - case 5: //UTRAN W/HSUPA - case 6: //UTRAN W/HSDPA and HSUPA - //AT+CGREG GPRS Network Registration Status - err = at_send_command_singleline("AT+CGREG?", "+CGREG:", &p_response); - break; - - case 7: //E-UTRAN - case 13: //E-UTRAN-NR dual connectivity - //AT+CEREG EPS Network Registration Status - err = at_send_command_singleline("AT+CEREG?", "+CEREG:", &p_response); - break; - - case 10: //E-UTRAN connected to a 5GCN - case 11: //NR connected to a 5GCN - case 12: //NG-RAN - //AT+C5GREG 5GS Network Registration Status - err = at_send_command_singleline("AT+C5GREG?", "+C5GREG:", &p_response); - break; - - default: - goto error; - break; - } - - if (at_response_error(err, p_response)) - goto error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto error; - - line = p_response->p_intermediates->line; - commas = at_tok_count(line); - switch (commas) { - case 0: /* +CREG: */ - err = at_tok_nextint(&line, &state); - if (err < 0) goto error; - break; - - case 1: /* +CREG: , */ - err = at_tok_scanf(line, "%d%d", NULL, &state); - if (err != 2) goto error; - break; - - case 2: /* +CREG: , , */ - err = at_tok_scanf(line, "%d%x%x", NULL, &state, &lac, &cid); - if (err != 3) goto error; - break; - - case 3: /* +CREG: , , , */ - err = at_tok_scanf(line, "%d%d%x%x", NULL, &state, &lac, &cid); - if (err != 4) goto error; - break; - - case 4: //, , , , */ - case 5: - case 6: - case 7: - err = at_tok_scanf(line, "%d%d%x%x%d", NULL, &state, &lac, &cid, &act); - if (err != 5) goto error; - break; - - default: - goto error; - } - - //dbg_time("state=%d", state); - - if (state == 1 || state == 5) { //Registered, home network / roaming - *pPSAttachedState = 1; - } - -error: - safe_at_response_free(p_response); - return retVal; -} - -static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - ATLine *p_cur = NULL; - int pdp = profile->pdp; - int state = 0; - - (void)curIpFamily; - - if (strStartsWith(profile->BaseBandVersion, "RG801H") || strStartsWith(profile->BaseBandVersion, "EC200H")) { - //RG801H will miss USB_CDC_NOTIFY_NETWORK_CONNECTION - asprintf(&cmd, "ifconfig %s up", profile->usbnet_adapter); - if (system(cmd)) {}; - safe_free(cmd); - } - - if (asr_style_atc) { - err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) { - int cid = 0; - state = 0; - - err = at_tok_scanf(p_cur->line, "%d%d", &cid, &state); - if (cid == pdp) - break; - else if(state) - state = 0; - } - safe_at_response_free(p_response); - - if (state == 0) { - asprintf(&cmd, "AT+CGACT=1,%d", pdp); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) - goto _error; - } - } - - if(asr_style_atc) - asprintf(&cmd, "AT+QNETDEVCTL=1,%d,%d", pdp, 1); - else - asprintf(&cmd, "AT+QNETDEVCTL=%d,1,%d", pdp, 1); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - - if (at_response_error(err, p_response)) - goto _error; - - if (!asr_style_atc) { //TODO some modems do not sync return setup call resule - int t = 0; - - while (t++ < 15) { - asprintf(&cmd, "AT+QNETDEVSTATUS=%d", pdp); - err = at_send_command_singleline(cmd, "+QNETDEVSTATUS", &p_response); - safe_free(cmd); - if (err) goto _error; - - if (!at_response_error(err, p_response)) { - break; - } - safe_at_response_free(p_response); - sleep(1); - } - } - - //some modem do not report URC - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - -_error: - safe_at_response_free(p_response); - //dbg_time("%s err=%d", __func__, err); - return err; -} - -static int at_netdevstatus(int pdp, unsigned int *pV4Addr) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - char *ipv4_address = NULL; - char *ipv4_gate = NULL; - char *ipv4_DHCP = NULL; - char *ipv4_pDNS = NULL; - char *ipv4_sDNS = NULL; - char *ipv6_address = NULL; - char *ipv6_gate = NULL; - char *ipv6_DHCP = NULL; - char *ipv6_pDNS = NULL; - char *ipv6_sDNS = NULL; - - *pV4Addr = 0; - - asprintf(&cmd, "AT+QNETDEVSTATUS=%d", pdp); - err = at_send_command_singleline(cmd, "+QNETDEVSTATUS", &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s%s%s%s%s%s%s%s%s%s", - &ipv4_address, &ipv4_gate, &ipv4_DHCP, &ipv4_pDNS, &ipv4_sDNS, - &ipv6_address, &ipv6_gate, &ipv6_DHCP, &ipv6_pDNS, &ipv6_sDNS); - if (err > 0) { -#if 0 - dbg_time("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", - ipv4_address, ipv4_gate, ipv4_DHCP, ipv4_pDNS, ipv4_sDNS, - ipv6_address, ipv6_gate, ipv6_DHCP, ipv6_pDNS, ipv6_sDNS); -#endif - - if (ipv4_address && ipv4_address[0]) { - int addr[4] = {0, 0, 0, 0}; - - if (strstr(ipv4_address, ".")) { - sscanf(ipv4_address, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]); - } - else { - sscanf(ipv4_address, "%02X%02X%02X%02X", &addr[3], &addr[2], &addr[1], &addr[0]); - } - *pV4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); - } - } - -_error: - safe_at_response_free(p_response); - return 0; -} - -static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { - int err; - ATResponse *p_response = NULL; - ATLine *p_cur = NULL; - int state = 0; - int bind = 0; - int cid; - int pdp = s_pdp; - unsigned int v4Addr = 0; - - (void)curIpFamily; - - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - - if (!asr_style_atc) { - err = at_netdevstatus(pdp, &v4Addr); - if (!err && v4Addr) { - *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; - //if (profile->ipv4.Address == v4Addr) {} //TODO - } - return err; - } - - err = at_send_command_multiline("AT+QNETDEVCTL?", "+QNETDEVCTL:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - { - //+QNETDECTL:,,, - err = at_tok_scanf(p_cur->line, "%d%d%d%d", &bind, &cid, NULL, &state); - if (err != 4 || cid != pdp) - continue; - if (bind != 1) - bind = 0; - } - safe_at_response_free(p_response); - - if (bind == 0 || state == 0) - goto _error; - - err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - { - state = 0; - err = at_tok_scanf(p_cur->line, "%d%d", &cid, &state); - if (cid == pdp) - break; - else if(state) - state = 0; - } - safe_at_response_free(p_response); - - if (bind && state) - *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; - -_error: - safe_at_response_free(p_response); - //dbg_time("%s err=%d, call_state=%d", __func__, err, *pConnectionStatus); - return 0; -} - -static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { - char *cmd = NULL; - int pdp = profile->pdp; - - (void)curIpFamily; - - if (asr_style_atc) - asprintf(&cmd, "AT+QNETDEVCTL=0,%d,%d", pdp, 0); - else - asprintf(&cmd, "AT+QNETDEVCTL=%d,0,%d", pdp, 0); - at_send_command(cmd, NULL); - safe_free(cmd); - - //dbg_time("%s err=%d", __func__, err); - return 0; -} - -static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - ATLine *p_cur = NULL; - int pdp = profile->pdp; - unsigned int v4Addr = 0; - - (void)curIpFamily; - - if (!asr_style_atc) { - err = at_netdevstatus(pdp, &v4Addr); - goto _error; - } - - asprintf(&cmd, "AT+CGPADDR=%d", profile->pdp); - err = at_send_command_singleline(cmd, "+CGPADDR:", &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) - goto _error; - - //+CGPADDR: 1,"10.201.80.91","2409:8930:4B3:41C7:F9B8:3D9B:A2F7:CA96" - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - { - char *ipv4 = NULL; - char *ipv6 = NULL; - - err = at_tok_scanf(p_cur->line, "%d%s%s", &pdp, &ipv4, &ipv6); - if (err < 2 || pdp != profile->pdp) - continue; - - if (ipv4) { - int addr[4] = {0, 0, 0, 0}; - - sscanf(ipv4, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]); - v4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); - break; - } - } - -_error: - if (v4Addr && profile->ipv4.Address != v4Addr) { - unsigned char *v4 = (unsigned char *)&v4Addr; - - profile->ipv4.Address = v4Addr; - dbg_time("%s %d.%d.%d.%d", __func__, v4[0], v4[1], v4[2], v4[3]); - } - - //dbg_time("%s err=%d", __func__, err); - return v4Addr ? 0 : -1; -} - -static int requestGetSignalInfo(void) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - int i; - ATLine *p_cur = NULL; - char *rat = NULL; - int cops_act = 0; - int is_nr5g_nsa = 0, nr5g_sa = 0; - int verbose = 0; - - err = at_send_command_singleline("at+cops?", "+COPS:", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - retVal = 0; - err = at_tok_scanf(p_response->p_intermediates->line, "%d%d%s%d", NULL, NULL, NULL, &cops_act); - if (err != 4) goto _error; - - nr5g_sa = (cops_act == 11); - - safe_at_response_free(p_response); - err = at_send_command_multiline("at+qeng=\"servingcell\"", "+QENG:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (i = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { - char *type, *state; - - err = at_tok_scanf(p_cur->line, "%s%s", &type, &state); - if (err != 2 || strcmp(type, "servingcell")) - continue; - - if (!strcmp(state, "SEARCH") || !strcmp(state, "LIMSRV")) - continue; - - if (!strcmp(state, "NOCONN") || !strcmp(state, "CONNECT")) { - err = at_tok_scanf(p_cur->line, "%s%s%s", &type, &state, &rat); - if (err != 3) - continue; - } - else { - rat = state; - } - - if (!strcmp(rat, "NR5G-SA")) - { - //+QENG: "servingcell",,"NR5G-SA",,,,,,,,,,,,,, - //+QENG: "servingcell","NOCONN","NR5G-SA","TDD", 454,12,0,21,4ED,636576,78,3,-85,-11,32,0,5184 - struct qeng_servingcell_nr5g_sa { - char *cell_type, *state, *rat, *is_tdd; - int MCC, MNC, cellID/*hex*/; - int PCID, TAC/*hex*/, ARFCN; - int band, NR_DL_bandwidth; - int RSRP, RSRQ, RSSI, SINR; - }; - struct qeng_servingcell_nr5g_sa nr5g_sa; - - memset(&nr5g_sa, 0, sizeof(nr5g_sa)); - err = at_tok_scanf(p_cur->line, "%s,%s,%s,%s,%d,%d,%x,%d,%x,%d,%d,%d,%d,%d,%d,%d", - &nr5g_sa.cell_type, &nr5g_sa.state, &nr5g_sa.rat, &nr5g_sa.is_tdd, - &nr5g_sa.MCC, &nr5g_sa.MNC, &nr5g_sa.cellID, &nr5g_sa.PCID, &nr5g_sa.TAC, - &nr5g_sa.ARFCN, &nr5g_sa.band, &nr5g_sa.NR_DL_bandwidth, - &nr5g_sa.RSRP, &nr5g_sa.RSRQ, &nr5g_sa.RSSI, &nr5g_sa.SINR); - - if (err >= 13 && verbose) { - dbg_time("%s,%s,%s,%s,%d,%d,%x,%d,%x,%d,%d,%d,%d,%d,%d,%d", - nr5g_sa.cell_type, nr5g_sa.state, nr5g_sa.rat, nr5g_sa.is_tdd, - nr5g_sa.MCC, nr5g_sa.MNC, nr5g_sa.cellID, nr5g_sa.PCID, nr5g_sa.TAC, - nr5g_sa.ARFCN, nr5g_sa.band, nr5g_sa.NR_DL_bandwidth, - nr5g_sa.RSRP, nr5g_sa.RSRQ, nr5g_sa.RSSI, nr5g_sa.SINR); - } - } - else if (!strcmp(rat, "NR5G-NSA")) - { - //+QENG: "NR5G-NSA",,,,,< SINR>,,, - struct qeng_servingcell_nr5g_nsa { - char *mcc, *mnc; - int pcid, rsrp, sinr, rsrq; - }; - struct qeng_servingcell_nr5g_nsa nr5g_nsa; - - memset(&nr5g_nsa, 0, sizeof(nr5g_nsa)); - err = at_tok_scanf(p_cur->line, "%s%s%s%s%d%d%d%dd", - NULL, NULL, &nr5g_nsa.mcc, &nr5g_nsa.mnc, &nr5g_nsa.pcid, &nr5g_nsa.rsrp, &nr5g_nsa.sinr, &nr5g_nsa.rsrq); - if (err == 8 && verbose) - { - dbg_time("mcc=%s, mnc=%s, pcid=%d, rsrp=%d, sinr=%d, rsrq=%d", - nr5g_nsa.mcc, nr5g_nsa.mnc, nr5g_nsa.pcid, nr5g_nsa.rsrp, nr5g_nsa.sinr, nr5g_nsa.rsrq); - } - - is_nr5g_nsa = 1; - } - else if (!strcmp(rat, "LTE")) - { - //+QENG: "LTE",,,,,,,,,,,,,,,,, - struct qeng_servingcell_lte { - char *is_tdd, *mcc, *mnc; - int cellID/*hex*/, pcid, earfcn, freq_band_ind, ul_bandwidth, dl_bandwidth; - int tac/*hex*/, rsrp, rsrq, rssi, sinr, cqi,tx_power,srxlev; - }; - struct qeng_servingcell_lte lte; - - memset(<e, 0, sizeof(lte)); - if (!strcmp(rat, state)) - err = at_tok_scanf(p_cur->line, "%s%s%s%s%s%x%d%d%d%d%d%x%d%d%d%d%d%d%d", - NULL, NULL, <e.is_tdd, <e.mcc, <e.mnc, - <e.cellID, <e.pcid, <e.earfcn, <e.freq_band_ind, <e.ul_bandwidth, <e.dl_bandwidth, - <e.tac, <e.rsrp, <e.rsrq, <e.rssi, <e.sinr, <e.cqi, <e.tx_power, <e.srxlev); - else - err = at_tok_scanf(p_cur->line, "%s%s%s%s%s%s%x%d%d%d%d%d%x%d%d%d%d%d%d%d", - NULL, NULL, NULL, <e.is_tdd, <e.mcc, <e.mnc, - <e.cellID, <e.pcid, <e.earfcn, <e.freq_band_ind, <e.ul_bandwidth, <e.dl_bandwidth, - <e.tac, <e.rsrp, <e.rsrq, <e.rssi, <e.sinr, <e.cqi, <e.tx_power, <e.srxlev); - - if (err >= 18 && verbose) - { - dbg_time("is_tdd=%s, mcc=%s, mnc=%s", lte.is_tdd, lte.mcc, lte.mnc); - dbg_time("cellID=%x, pcid=%d, earfcn=%d", lte.cellID, lte.pcid, lte.earfcn); - dbg_time("freq_band_ind=%d, ul_bandwidth=%d, dl_bandwidth=%d", lte.freq_band_ind, lte.ul_bandwidth, lte.dl_bandwidth); - dbg_time("tac=%x, rsrp=%d, rsrq=%d, rssi=%d, sinr=%d", lte.tac, lte.rsrp, lte.rsrq, lte.rssi, lte.sinr); - dbg_time("cqi=%d, tx_power=%d, earfcn=%d", lte.cqi, lte.tx_power, lte.srxlev); - } - } - } - - if (is_nr5g_nsa) { - int endc_avl, plmn_info_list_r15_avl, endc_rstr, nr5g_basic; - - is_nr5g_nsa = 0; - safe_at_response_free(p_response); - err = at_send_command_multiline("at+qendc", "+QENDC:", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - err = at_tok_scanf(p_response->p_intermediates->line, "%d%d%d%d", - &endc_avl, &plmn_info_list_r15_avl, &endc_rstr, &nr5g_basic); - if (err == 4 && nr5g_basic) { - is_nr5g_nsa = 1; - } - } - - if (verbose) - dbg_time("cops_act=%d, nr5g_nsa=%d, nr5g_sa=%d", cops_act, is_nr5g_nsa, nr5g_sa); - -_error: - safe_at_response_free(p_response); - return retVal; -} - -static int requestGetICCID(void) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *iccid; - - err = at_send_command_singleline("AT+QCCID", "+QCCID:", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s", &iccid); - if (err != 1) goto _error; - - if (iccid && iccid[0]) { - dbg_time("%s %s", __func__, iccid); - retVal = 0; - } - -_error: - safe_at_response_free(p_response); - return retVal; -} - -static int requestGetIMSI(void) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *imsi; - - err = at_send_command_numeric("AT+CIMI", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - imsi = p_response->p_intermediates->line; - if (imsi) { - dbg_time("%s %s", __func__, imsi); - retVal = 0; - } - -_error: - safe_at_response_free(p_response); - return retVal; -} - -const struct request_ops atc_request_ops = { - .requestBaseBandVersion = requestBaseBandVersion, - .requestGetSIMStatus = requestGetSIMStatus, - .requestEnterSimPin = requestEnterSimPin, - .requestSetProfile = requestSetProfile, - .requestGetProfile = requestGetProfile, - .requestRegistrationState = requestRegistrationState, - .requestSetupDataCall = requestSetupDataCall, - .requestQueryDataCall = requestQueryDataCall, - .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, - .requestGetIPAddress = requestGetIPAddress, - .requestGetSignalInfo = requestGetSignalInfo, - .requestGetICCID = requestGetICCID, - .requestGetIMSI = requestGetIMSI, -}; - diff --git a/quectel_cm_5G/src/atchannel.c b/quectel_cm_5G/src/atchannel.c deleted file mode 100644 index 90aa1c4..0000000 --- a/quectel_cm_5G/src/atchannel.c +++ /dev/null @@ -1,1037 +0,0 @@ -/* //device/system/reference-ril/atchannel.c -** -** Copyright 2006, The Android Open Source Project -** -** 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. -*/ - -#include "atchannel.h" -#include "at_tok.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "QMIThread.h" -#define LOGE dbg_time -#define LOGD dbg_time - -#define NUM_ELEMS(x) (sizeof(x)/sizeof(x[0])) - -#define MAX_AT_RESPONSE sizeof(cm_recv_buf) -#define HANDSHAKE_RETRY_COUNT 8 -#define HANDSHAKE_TIMEOUT_MSEC 1000 - -static pthread_t s_tid_reader; -static int s_fd = -1; /* fd of the AT channel */ -static ATUnsolHandler s_unsolHandler; -static int s_atc_proxy = 0; /* fd of the AT channel */ - -/* for input buffering */ - -static char *s_ATBuffer = (char *)cm_recv_buf; -static char *s_ATBufferCur = (char *)cm_recv_buf; - -static int s_readCount = 0; - -#if AT_DEBUG -void AT_DUMP(const char* prefix, const char* buff, int len) -{ - if (len < 0) - len = strlen(buff); - LOGD("%.*s", len, buff); -} -#endif - -/* - * for current pending command - * these are protected by s_commandmutex - */ -static ATCommandType s_type; -static const char *s_responsePrefix = NULL; -static const char *s_smsPDU = NULL; -static const char *s_raw_data = NULL; -static size_t s_raw_len; -static ATResponse *sp_response = NULL; - -static void (*s_onTimeout)(void) = NULL; -static void (*s_onReaderClosed)(void) = NULL; -static int s_readerClosed; - -static void onReaderClosed(); -static int writeCtrlZ (const char *s); -static int writeline (const char *s); -static int writeraw (const char *s, size_t len); - -static void sleepMsec(long long msec) -{ - struct timespec ts; - int err; - - ts.tv_sec = (msec / 1000); - ts.tv_nsec = (msec % 1000) * 1000 * 1000; - - do { - err = nanosleep (&ts, &ts); - } while (err < 0 && errno == EINTR); -} - -/** returns 1 if line starts with prefix, 0 if it does not */ -int strStartsWith(const char *line, const char *prefix) -{ - for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) { - if (*line != *prefix) { - return 0; - } - } - - return *prefix == '\0'; -} - -/** add an intermediate response to sp_response*/ -static void addIntermediate(const char *line) -{ - ATLine *p_new; - - p_new = (ATLine *) malloc(sizeof(ATLine)); - - p_new->line = strdup(line); - - /* note: this adds to the head of the list, so the list - will be in reverse order of lines received. the order is flipped - again before passing on to the command issuer */ - p_new->p_next = sp_response->p_intermediates; - sp_response->p_intermediates = p_new; -} - - -/** - * returns 1 if line is a final response indicating error - * See 27.007 annex B - * WARNING: NO CARRIER and others are sometimes unsolicited - */ -static const char * s_finalResponsesError[] = { - "ERROR", - "+CMS ERROR:", - "+CME ERROR:", - "NO CARRIER", /* sometimes! */ - "NO ANSWER", - "NO DIALTONE", - "COMMAND NOT SUPPORT", -}; -static int isFinalResponseError(const char *line) -{ - size_t i; - - for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) { - if (strStartsWith(line, s_finalResponsesError[i])) { - return 1; - } - } - - return 0; -} - -/** - * returns 1 if line is a final response indicating success - * See 27.007 annex B - * WARNING: NO CARRIER and others are sometimes unsolicited - */ -static const char * s_finalResponsesSuccess[] = { - "OK", - "+QIND: \"FOTA\",\"END\",0", - "CONNECT" /* some stacks start up data on another channel */ -}; - -static int isFinalResponseSuccess(const char *line) -{ - size_t i; - - for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) { - if (strStartsWith(line, s_finalResponsesSuccess[i])) { - return 1; - } - } - - return 0; -} - -#if 0 -/** - * returns 1 if line is a final response, either error or success - * See 27.007 annex B - * WARNING: NO CARRIER and others are sometimes unsolicited - */ -static int isFinalResponse(const char *line) -{ - return isFinalResponseSuccess(line) || isFinalResponseError(line); -} -#endif - -/** - * returns 1 if line is the first line in (what will be) a two-line - * SMS unsolicited response - */ -static const char * s_smsUnsoliciteds[] = { - "+CMT:", - "+CDS:", - "+CBM:", - "+CMTI:" -}; -static int isSMSUnsolicited(const char *line) -{ - size_t i; - - for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) { - if (strStartsWith(line, s_smsUnsoliciteds[i])) { - return 1; - } - } - - return 0; -} - - -/** assumes s_commandmutex is held */ -static void handleFinalResponse(const char *line) -{ - sp_response->finalResponse = strdup(line); - - pthread_cond_signal(&cm_command_cond); -} - -static void handleUnsolicited(const char *line) -{ - if (s_unsolHandler != NULL) { - s_unsolHandler(line, NULL); - } -} - -static void processLine(const char *line) -{ - pthread_mutex_lock(&cm_command_mutex); - - if (sp_response == NULL) { - /* no command pending */ - handleUnsolicited(line); - } else if (s_raw_data != NULL && 0 == strcmp(line, "CONNECT")) { - usleep(500*1000); //for EC20 - writeraw(s_raw_data, s_raw_len); - s_raw_data = NULL; - } else if (isFinalResponseSuccess(line)) { - if(s_atc_proxy) - handleUnsolicited(line); - sp_response->success = 1; - handleFinalResponse(line); - } else if (isFinalResponseError(line)) { - if(s_atc_proxy) - handleUnsolicited(line); - sp_response->success = 0; - handleFinalResponse(line); - } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) { - // See eg. TS 27.005 4.3 - // Commands like AT+CMGS have a "> " prompt - writeCtrlZ(s_smsPDU); - s_smsPDU = NULL; - } else switch (s_type) { - case NO_RESULT: - handleUnsolicited(line); - break; - case NUMERIC: - if (sp_response->p_intermediates == NULL - && isdigit(line[0]) - ) { - addIntermediate(line); - } else { - /* either we already have an intermediate response or - the line doesn't begin with a digit */ - handleUnsolicited(line); - } - break; - case SINGLELINE: - if (sp_response->p_intermediates == NULL - && strStartsWith (line, s_responsePrefix) - ) { - addIntermediate(line); - } else { - /* we already have an intermediate response */ - handleUnsolicited(line); - } - break; - case MULTILINE: - if (strStartsWith (line, s_responsePrefix)) { - addIntermediate(line); - } else { - handleUnsolicited(line); - } - break; - - default: /* this should never be reached */ - LOGE("Unsupported AT command type %d\n", s_type); - handleUnsolicited(line); - break; - } - - pthread_mutex_unlock(&cm_command_mutex); -} - - -/** - * Returns a pointer to the end of the next line - * special-cases the "> " SMS prompt - * - * returns NULL if there is no complete line - */ -static char * findNextEOL(char *cur) -{ - if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') { - /* SMS prompt character...not \r terminated */ - return cur+2; - } - - // Find next newline - while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++; - - return *cur == '\0' ? NULL : cur; -} - - -/** - * Reads a line from the AT channel, returns NULL on timeout. - * Assumes it has exclusive read access to the FD - * - * This line is valid only until the next call to readline - * - * This function exists because as of writing, android libc does not - * have buffered stdio. - */ - -static const char *readline() -{ - ssize_t count; - - char *p_read = NULL; - char *p_eol = NULL; - char *ret; - - /* this is a little odd. I use *s_ATBufferCur == 0 to - * mean "buffer consumed completely". If it points to a character, than - * the buffer continues until a \0 - */ - if (*s_ATBufferCur == '\0') { - /* empty buffer */ - s_ATBufferCur = s_ATBuffer; - *s_ATBufferCur = '\0'; - p_read = s_ATBuffer; - } else { /* *s_ATBufferCur != '\0' */ - /* there's data in the buffer from the last read */ - - // skip over leading newlines - while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') - s_ATBufferCur++; - - p_eol = findNextEOL(s_ATBufferCur); - - if (p_eol == NULL) { - /* a partial line. move it up and prepare to read more */ - size_t len; - - len = strlen(s_ATBufferCur); - - memmove(s_ATBuffer, s_ATBufferCur, len + 1); - p_read = s_ATBuffer + len; - s_ATBufferCur = s_ATBuffer; - } - /* Otherwise, (p_eol !- NULL) there is a complete line */ - /* that will be returned the while () loop below */ - } - - while (p_eol == NULL) { - if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) { - LOGE("ERROR: Input line exceeded buffer\n"); - /* ditch buffer and start over again */ - s_ATBufferCur = s_ATBuffer; - *s_ATBufferCur = '\0'; - p_read = s_ATBuffer; - } - - do { - while (s_fd > 0) { - struct pollfd pollfds[1] = {{s_fd, POLLIN, 0}}; - int ret; - - do { - ret = poll(pollfds, 1, -1); - } while ((ret < 0) && (errno == EINTR)); - - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - break; - } else if (pollfds[0].revents & (POLLIN)) { - break; - } - }; - - count = (s_fd == -1) ? 0 : read(s_fd, p_read, - MAX_AT_RESPONSE - (p_read - s_ATBuffer)); - } while (count < 0 && errno == EINTR); - - if (count > 0) { - AT_DUMP( "<< ", p_read, count ); - s_readCount += count; - - p_read[count] = '\0'; - - // skip over leading newlines - while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') - s_ATBufferCur++; - - p_eol = findNextEOL(s_ATBufferCur); - p_read += count; - } else if (count <= 0) { - /* read error encountered or EOF reached */ - if(count == 0) { - LOGD("atchannel: EOF reached"); - } else { - LOGD("atchannel: read error %s", strerror(errno)); - } - return NULL; - } - } - - /* a full line in the buffer. Place a \0 over the \r and return */ - - ret = s_ATBufferCur; - *p_eol = '\0'; - s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */ - /* and there will be a \0 at *p_read */ - - LOGD("AT< %s", ret); - return ret; -} - - -static void onReaderClosed() -{ - LOGE("%s", __func__); - if (s_onReaderClosed != NULL && s_readerClosed == 0) { - - pthread_mutex_lock(&cm_command_mutex); - - s_readerClosed = 1; - - pthread_cond_signal(&cm_command_cond); - - pthread_mutex_unlock(&cm_command_mutex); - - s_onReaderClosed(); - } -} - - -static void *readerLoop(void *arg) -{ - (void)arg; - - for (;;) { - const char * line; - - line = readline(); - - if (line == NULL) { - break; - } - - if(isSMSUnsolicited(line)) { - char *line1; - const char *line2; - - // The scope of string returned by 'readline()' is valid only - // till next call to 'readline()' hence making a copy of line - // before calling readline again. - line1 = strdup(line); - line2 = readline(); - - if (line2 == NULL) { - break; - } - - if (s_unsolHandler != NULL) { - s_unsolHandler (line1, line2); - } - free(line1); - } else { - processLine(line); - } - } - - onReaderClosed(); - - return NULL; -} - -/** - * Sends string s to the radio with a \r appended. - * Returns AT_ERROR_* on error, 0 on success - * - * This function exists because as of writing, android libc does not - * have buffered stdio. - */ -static int writeline (const char *s) -{ - size_t cur = 0; - size_t len = strlen(s); - ssize_t written; - static char at_command[64]; - - if (s_fd < 0 || s_readerClosed > 0) { - return AT_ERROR_CHANNEL_CLOSED; - } - - LOGD("AT> %s", s); - - AT_DUMP( ">> ", s, strlen(s) ); - -#if 1 //send '\r' maybe fail via USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller (rev 04) - if (len < (sizeof(at_command) - 1)) { - strcpy(at_command, s); - at_command[len++] = '\r'; - s = (const char *)at_command; - } -#endif - - /* the main string */ - while (cur < len) { - do { - written = write (s_fd, s + cur, len - cur); - } while (written < 0 && errno == EINTR); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - cur += written; - } - -#if 1 //Quectel send '\r' maybe fail via USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller (rev 04) - if (s == (const char *)at_command) { - return 0; - } -#endif - - /* the \r */ - - do { - written = write (s_fd, "\r" , 1); - } while ((written < 0 && errno == EINTR) || (written == 0)); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - return 0; -} -static int writeCtrlZ (const char *s) -{ - size_t cur = 0; - size_t len = strlen(s); - ssize_t written; - - if (s_fd < 0 || s_readerClosed > 0) { - return AT_ERROR_CHANNEL_CLOSED; - } - - LOGD("AT> %s^Z", s); - - AT_DUMP( ">* ", s, strlen(s) ); - - /* the main string */ - while (cur < len) { - do { - written = write (s_fd, s + cur, len - cur); - } while (written < 0 && errno == EINTR); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - cur += written; - } - - /* the ^Z */ - - do { - written = write (s_fd, "\032" , 1); - } while ((written < 0 && errno == EINTR) || (written == 0)); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - return 0; -} - -static int writeraw (const char *s, size_t len) { - size_t cur = 0; - ssize_t written; - - if (s_fd < 0 || s_readerClosed > 0) { - return AT_ERROR_CHANNEL_CLOSED; - } - - /* the main string */ - while (cur < len) { - struct pollfd pollfds[1] = {{s_fd, POLLOUT, 0}}; - int ret; - - ret = poll(pollfds, 1, -1); - if (ret <= 0) - break; - - do { - written = write (s_fd, s + cur, len - cur); - } while (written < 0 && errno == EINTR); - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - cur += written; - } - - if (written < 0) { - return AT_ERROR_GENERIC; - } - - return cur; -} - -static void clearPendingCommand() -{ - if (sp_response != NULL) { - at_response_free(sp_response); - } - - sp_response = NULL; - s_responsePrefix = NULL; - s_smsPDU = NULL; -} - - -/** - * Starts AT handler on stream "fd' - * returns 0 on success, -1 on error - */ -int at_open(int fd, ATUnsolHandler h, int proxy) -{ - int ret; - pthread_attr_t attr; - - s_fd = fd; - s_unsolHandler = h; - s_readerClosed = 0; - s_atc_proxy = proxy; - - s_responsePrefix = NULL; - s_smsPDU = NULL; - sp_response = NULL; - - pthread_attr_init (&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - ret = pthread_create(&s_tid_reader, &attr, readerLoop, NULL); - - if (ret < 0) { - LOGE("readerLoop create fail!"); - perror ("pthread_create\n"); - return -1; - } - - return 0; -} - -/* FIXME is it ok to call this from the reader and the command thread? */ -void at_close() -{ - dbg_time("at_close"); - if (s_fd >= 0) { - close(s_fd); - } - s_fd = -1; - - pthread_mutex_lock(&cm_command_mutex); - - s_readerClosed = 1; - - pthread_cond_signal(&cm_command_cond); - - pthread_mutex_unlock(&cm_command_mutex); - - /* the reader thread should eventually die */ -} - -static ATResponse * at_response_new() -{ - return (ATResponse *) calloc(1, sizeof(ATResponse)); -} - -void at_response_free(ATResponse *p_response) -{ - ATLine *p_line; - - if (p_response == NULL) return; - - p_line = p_response->p_intermediates; - - while (p_line != NULL) { - ATLine *p_toFree; - - p_toFree = p_line; - p_line = p_line->p_next; - - free(p_toFree->line); - free(p_toFree); - } - - free (p_response->finalResponse); - free (p_response); -} - -/** - * The line reader places the intermediate responses in reverse order - * here we flip them back - */ -static void reverseIntermediates(ATResponse *p_response) -{ - ATLine *pcur,*pnext; - - pcur = p_response->p_intermediates; - p_response->p_intermediates = NULL; - - while (pcur != NULL) { - pnext = pcur->p_next; - pcur->p_next = p_response->p_intermediates; - p_response->p_intermediates = pcur; - pcur = pnext; - } -} - -/** - * Internal send_command implementation - * Doesn't lock or call the timeout callback - * - * timeoutMsec == 0 means infinite timeout - */ -static int at_send_command_full_nolock (const char *command, ATCommandType type, - const char *responsePrefix, const char *smspdu, - long long timeoutMsec, ATResponse **pp_outResponse) -{ - int err = 0; - - if (!timeoutMsec) - timeoutMsec = 15000; - - if(sp_response != NULL) { - err = AT_ERROR_COMMAND_PENDING; - goto error; - } - - if (command != NULL) - err = writeline (command); - - if (err < 0) { - printf("%s errno: %d (%s)\n", __func__, errno, strerror(errno)); - goto error; - } - - s_type = type; - s_responsePrefix = responsePrefix; - s_smsPDU = smspdu; - sp_response = at_response_new(); - - while (sp_response->finalResponse == NULL && s_readerClosed == 0) { - err = pthread_cond_timeout_np(&cm_command_cond, &cm_command_mutex, timeoutMsec); - - if (err == ETIMEDOUT) { - err = AT_ERROR_TIMEOUT; - goto error; - } - } - - if (pp_outResponse == NULL) { - at_response_free(sp_response); - } else { - /* line reader stores intermediate responses in reverse order */ - reverseIntermediates(sp_response); - *pp_outResponse = sp_response; - } - - sp_response = NULL; - - if(s_readerClosed > 0) { - err = AT_ERROR_CHANNEL_CLOSED; - goto error; - } - - err = 0; -error: - clearPendingCommand(); - - return err; -} - -/** - * Internal send_command implementation - * - * timeoutMsec == 0 means infinite timeout - */ -static int at_send_command_full (const char *command, ATCommandType type, - const char *responsePrefix, const char *smspdu, - long long timeoutMsec, ATResponse **pp_outResponse) -{ - int err; - - if (0 != pthread_equal(s_tid_reader, pthread_self())) { - /* cannot be called from reader thread */ - return AT_ERROR_INVALID_THREAD; - } - - pthread_mutex_lock(&cm_command_mutex); - - err = at_send_command_full_nolock(command, type, - responsePrefix, smspdu, - timeoutMsec, pp_outResponse); - - pthread_mutex_unlock(&cm_command_mutex); - - if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) { - s_onTimeout(); - } - - return err; -} - - -/** - * Issue a single normal AT command with no intermediate response expected - * - * "command" should not include \r - * pp_outResponse can be NULL - * - * if non-NULL, the resulting ATResponse * must be eventually freed with - * at_response_free - */ -int at_send_command (const char *command, ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, NO_RESULT, NULL, - NULL, 0, pp_outResponse); - - return err; -} - - -int at_send_command_singleline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, SINGLELINE, responsePrefix, - NULL, 0, pp_outResponse); - - if (err == 0 && pp_outResponse != NULL - && (*pp_outResponse)->success > 0 - && (*pp_outResponse)->p_intermediates == NULL - ) { - /* successful command must have an intermediate response */ - at_response_free(*pp_outResponse); - *pp_outResponse = NULL; - return AT_ERROR_INVALID_RESPONSE; - } - - return err; -} - - -int at_send_command_numeric (const char *command, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, NUMERIC, NULL, - NULL, 0, pp_outResponse); - - if (err == 0 && pp_outResponse != NULL - && (*pp_outResponse)->success > 0 - && (*pp_outResponse)->p_intermediates == NULL - ) { - /* successful command must have an intermediate response */ - at_response_free(*pp_outResponse); - *pp_outResponse = NULL; - return AT_ERROR_INVALID_RESPONSE; - } - - return err; -} - - -int at_send_command_sms (const char *command, - const char *pdu, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, SINGLELINE, responsePrefix, - pdu, 0, pp_outResponse); - - if (err == 0 && pp_outResponse != NULL - && (*pp_outResponse)->success > 0 - && (*pp_outResponse)->p_intermediates == NULL - ) { - /* successful command must have an intermediate response */ - at_response_free(*pp_outResponse); - *pp_outResponse = NULL; - return AT_ERROR_INVALID_RESPONSE; - } - - return err; -} - -int at_send_command_multiline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - err = at_send_command_full (command, MULTILINE, responsePrefix, - NULL, 0, pp_outResponse); - - return err; -} - -int at_send_command_raw (const char *command, - const char *raw_data, unsigned int raw_len, - const char *responsePrefix, - ATResponse **pp_outResponse) -{ - int err; - - s_raw_data = raw_data; - s_raw_len = raw_len; - err = at_send_command_full (command, SINGLELINE, responsePrefix, - NULL, 0, pp_outResponse); - - return err; -} - -/** - * Periodically issue an AT command and wait for a response. - * Used to ensure channel has start up and is active - */ - -int at_handshake() -{ - int i; - int err = 0; - - if (0 != pthread_equal(s_tid_reader, pthread_self())) { - /* cannot be called from reader thread */ - return AT_ERROR_INVALID_THREAD; - } - - pthread_mutex_lock(&cm_command_mutex); - - for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) { - /* some stacks start with verbose off */ - err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT, - NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL); - - if (err == 0) { - break; - } - } - - pthread_mutex_unlock(&cm_command_mutex); - - if (err == 0) { - /* pause for a bit to let the input buffer drain any unmatched OK's - (they will appear as extraneous unsolicited responses) */ - - sleepMsec(HANDSHAKE_TIMEOUT_MSEC); - } - - return err; -} - -AT_CME_Error at_get_cme_error(const ATResponse *p_response) -{ - int ret; - int err; - char *p_cur; - - if (p_response == NULL) - return CME_ERROR_NON_CME; - - if (p_response->success > 0) { - return CME_SUCCESS; - } - - if (p_response->finalResponse == NULL - || !strStartsWith(p_response->finalResponse, "+CME ERROR:") - ) { - return CME_ERROR_NON_CME; - } - - p_cur = p_response->finalResponse; - err = at_tok_start(&p_cur); - - if (err < 0) { - return CME_ERROR_NON_CME; - } - - err = at_tok_nextint(&p_cur, &ret); - - if (err < 0) { - return CME_ERROR_NON_CME; - } - - return (AT_CME_Error) ret; -} - -/** This callback is invoked on the command thread */ -void at_set_on_timeout(void (*onTimeout)(void)) -{ - s_onTimeout = onTimeout; -} - -/** - * This callback is invoked on the reader thread (like ATUnsolHandler) - * when the input stream closes before you call at_close - * (not when you call at_close()) - * You should still call at_close() - */ -void at_set_on_reader_closed(void (*onClose)(void)) -{ - s_onReaderClosed = onClose; -} diff --git a/quectel_cm_5G/src/atchannel.h b/quectel_cm_5G/src/atchannel.h deleted file mode 100644 index cce28b1..0000000 --- a/quectel_cm_5G/src/atchannel.h +++ /dev/null @@ -1,152 +0,0 @@ -/* //device/system/reference-ril/atchannel.h -** -** Copyright 2006, The Android Open Source Project -** -** 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. -*/ - -#ifndef ATCHANNEL_H -#define ATCHANNEL_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* define AT_DEBUG to send AT traffic to /tmp/radio-at.log" */ -#define AT_DEBUG 0 - -#if AT_DEBUG -extern void AT_DUMP(const char* prefix, const char* buff, int len); -#else -#define AT_DUMP(prefix,buff,len) do{}while(0) -#endif - -#define AT_ERROR_GENERIC -1 -#define AT_ERROR_COMMAND_PENDING -2 -#define AT_ERROR_CHANNEL_CLOSED -3 -#define AT_ERROR_TIMEOUT -4 -#define AT_ERROR_INVALID_THREAD -5 /* AT commands may not be issued from - reader thread (or unsolicited response - callback */ -#define AT_ERROR_INVALID_RESPONSE -6 /* eg an at_send_command_singleline that - did not get back an intermediate - response */ - - -typedef enum { - NO_RESULT, /* no intermediate response expected */ - NUMERIC, /* a single intermediate response starting with a 0-9 */ - SINGLELINE, /* a single intermediate response starting with a prefix */ - MULTILINE /* multiple line intermediate response - starting with a prefix */ -} ATCommandType; - -/** a singly-lined list of intermediate responses */ -typedef struct ATLine { - struct ATLine *p_next; - char *line; -} ATLine; - -/** Free this with at_response_free() */ -typedef struct { - int success; /* true if final response indicates - success (eg "OK") */ - char *finalResponse; /* eg OK, ERROR */ - ATLine *p_intermediates; /* any intermediate responses */ -} ATResponse; - -/** - * a user-provided unsolicited response handler function - * this will be called from the reader thread, so do not block - * "s" is the line, and "sms_pdu" is either NULL or the PDU response - * for multi-line TS 27.005 SMS PDU responses (eg +CMT:) - */ -typedef void (*ATUnsolHandler)(const char *s, const char *sms_pdu); - -int at_open(int fd, ATUnsolHandler h, int proxy); -void at_close(); - -/* This callback is invoked on the command thread. - You should reset or handshake here to avoid getting out of sync */ -void at_set_on_timeout(void (*onTimeout)(void)); -/* This callback is invoked on the reader thread (like ATUnsolHandler) - when the input stream closes before you call at_close - (not when you call at_close()) - You should still call at_close() - It may also be invoked immediately from the current thread if the read - channel is already closed */ -void at_set_on_reader_closed(void (*onClose)(void)); - -int at_send_command_singleline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse); - -int at_send_command_numeric (const char *command, - ATResponse **pp_outResponse); - -int at_send_command_multiline (const char *command, - const char *responsePrefix, - ATResponse **pp_outResponse); - -int at_send_command_raw (const char *command, - const char *raw_data, unsigned int raw_len, - const char *responsePrefix, - ATResponse **pp_outResponse); - -int at_handshake(); - -int at_send_command (const char *command, ATResponse **pp_outResponse); - -int at_send_command_sms (const char *command, const char *pdu, - const char *responsePrefix, - ATResponse **pp_outResponse); - -void at_response_free(ATResponse *p_response); - -int strStartsWith(const char *line, const char *prefix); - -typedef enum { - CME_ERROR_NON_CME = -1, - CME_SUCCESS = 0, - - CME_OPERATION_NOT_ALLOWED = 3, - CME_OPERATION_NOT_SUPPORTED = 4, - CME_PH_SIM_PIN= 5, - CME_PH_FSIM_PIN = 6, - CME_PH_FSIM_PUK = 7, - CME_SIM_NOT_INSERTED =10, - CME_SIM_PIN_REQUIRED = 11, - CME_SIM_PUK_REQUIRED = 12, - CME_FAILURE = 13, - CME_SIM_BUSY = 14, - CME_SIM_WRONG = 15, - CME_INCORRECT_PASSWORD = 16, - CME_SIM_PIN2_REQUIRED = 17, - CME_SIM_PUK2_REQUIRED = 18, - CME_MEMORY_FULL = 20, - CME_INVALID_INDEX = 21, - CME_NOT_FOUND = 22, - CME_MEMORY_FAILURE = 23, - CME_STRING_TO_LONG = 24, - CME_INVALID_CHAR = 25, - CME_DIALSTR_TO_LONG = 26, - CME_INVALID_DIALCHAR = 27, -} AT_CME_Error; - -AT_CME_Error at_get_cme_error(const ATResponse *p_response); - -#ifdef __cplusplus -} -#endif - -#endif /*ATCHANNEL_H*/ diff --git a/quectel_cm_5G/src/configure.ac b/quectel_cm_5G/src/configure.ac deleted file mode 100644 index f4c60ea..0000000 --- a/quectel_cm_5G/src/configure.ac +++ /dev/null @@ -1,48 +0,0 @@ -# -*- Autoconf -*- -# Process this file with autoconf to produce a configure script. - -AC_PREREQ([2.61]) -AC_INIT([quectel-CM], [1.0], [fae-support@quectel.com]) -AC_CONFIG_HEADERS([config.h]) - -# Checks for programs. -AC_PROG_CC - -# Checks for libraries. - -# Checks for header files. - -# Checks for typedefs, structures, and compiler characteristics. -AC_ARG_WITH(sanitized-headers, - AS_HELP_STRING([--with-sanitized-headers=DIR], - [Specify the location of the sanitized Linux headers]), - [CPPFLAGS="$CPPFLAGS -idirafter $withval"]) - -AC_ARG_WITH([qrtr], - AC_HELP_STRING([--with-qrtr], - [enable qrtr, building which use qrtr])) - -if (test "x${with_qrtr}" = "xyes"); then - #AC_DEFINE(ENABLE_USEQTRT, 1, [Define if uses qrtr]) - AC_CHECK_HEADERS([linux/qrtr.h linux/rmnet_data.h]) -fi - -AM_CONDITIONAL(USE_QRTR, test "x${with_qrtr}" = "xyes") - -AC_ARG_WITH([msm-ipc], - AC_HELP_STRING([--with-msm-ipc], - [enable msm-ipc, building which use qrtr])) - -if (test "x${with_msm_ipc}" = "xyes"); then - #AC_DEFINE(ENABLE_USEQTRT, 1, [Define if uses qrtr]) - AC_CHECK_HEADERS([linux/msm_ipc.h linux/rmnet_data.h]) -fi - -AM_CONDITIONAL(USE_MSM_IPC, test "x${with_msm_ipc}" = "xyes") - -# Checks for library functions. - -# Does not strictly follow GNU Coding standards -AM_INIT_AUTOMAKE([foreign subdir-objects]) -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/quectel_cm_5G/src/default.script b/quectel_cm_5G/src/default.script deleted file mode 100644 index 26b95c1..0000000 --- a/quectel_cm_5G/src/default.script +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert. -# -# Based on the busybox example scripts and the old udhcp source -# package default.* scripts. - -RESOLV_CONF="/etc/resolv.conf" - -case $1 in - bound|renew) - [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" - [ -n "$subnet" ] && NETMASK="netmask $subnet" - - /sbin/ifconfig $interface $ip $BROADCAST $NETMASK - - if [ -n "$router" ]; then - echo "$0: Resetting default routes" - while /sbin/route del default gw 0.0.0.0 dev $interface; do :; done - - metric=0 - for i in $router; do - /sbin/route add default gw $i dev $interface metric $metric - metric=$(($metric + 1)) - done - fi - - # Update resolver configuration file - R="" - [ -n "$domain" ] && R="domain $domain -" - for i in $dns; do - echo "$0: Adding DNS $i" - R="${R}nameserver $i -" - done - - if [ -x /sbin/resolvconf ]; then - echo -n "$R" | resolvconf -a "${interface}.udhcpc" - else - echo -n "$R" > "$RESOLV_CONF" - fi - ;; - - deconfig) - if [ -x /sbin/resolvconf ]; then - resolvconf -d "${interface}.udhcpc" - fi - /sbin/ifconfig $interface 0.0.0.0 - ;; - - leasefail) - echo "$0: Lease failed: $message" - ;; - - nak) - echo "$0: Received a NAK: $message" - ;; - - *) - echo "$0: Unknown udhcpc command: $1"; - exit 1; - ;; -esac diff --git a/quectel_cm_5G/src/default.script_ip b/quectel_cm_5G/src/default.script_ip deleted file mode 100644 index 24f8e59..0000000 --- a/quectel_cm_5G/src/default.script_ip +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -# Busybox udhcpc dispatcher script. Copyright (C) 2009 by Axel Beckert. -# -# Based on the busybox example scripts and the old udhcp source -# package default.* scripts. - -RESOLV_CONF="/etc/resolv.conf" -IPCMD=`which ip` - -case $1 in - bound|renew) - $IPCMD address add broadcast $broadcast $ip/$subnet dev $interface - - if [ -n "$router" ]; then - echo "$0: Resetting default routes" - while $IPCMD route del default dev $interface; do :; done - - metric=0 - for i in $router; do - $IPCMD route add default dev $interface via $router metric $metric - metric=$(($metric + 1)) - done - fi - - # Update resolver configuration file - R="" - [ -n "$domain" ] && R="domain $domain -" - for i in $dns; do - echo "$0: Adding DNS $i" - R="${R}nameserver $i -" - done - - if [ -x /sbin/resolvconf ]; then - echo -n "$R" | resolvconf -a "${interface}.udhcpc" - else - echo -n "$R" > "$RESOLV_CONF" - fi - ;; - - deconfig) - if [ -x /sbin/resolvconf ]; then - resolvconf -d "${interface}.udhcpc" - fi - $IPCMD address flush dev $interface - ;; - - leasefail) - echo "$0: Lease failed: $message" - ;; - - nak) - echo "$0: Received a NAK: $message" - ;; - - *) - echo "$0: Unknown udhcpc command: $1"; - exit 1; - ;; -esac diff --git a/quectel_cm_5G/src/device.c b/quectel_cm_5G/src/device.c deleted file mode 100644 index 6e95405..0000000 --- a/quectel_cm_5G/src/device.c +++ /dev/null @@ -1,768 +0,0 @@ -/****************************************************************************** - @file device.c - @brief QMI device dirver. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "QMIThread.h" -#include "ethtool-copy.h" - -#define USB_CLASS_VENDOR_SPEC 0xff -#define USB_CLASS_COMM 2 -#define USB_CDC_SUBCLASS_ACM 0x02 -#define USB_CDC_SUBCLASS_ETHERNET 0x06 -#define USB_CDC_SUBCLASS_NCM 0x0d -#define USB_CDC_SUBCLASS_MBIM 0x0e -#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 - -#define CM_MAX_PATHLEN 256 - -#define CM_INVALID_VAL (~((int)0)) - -/* get first line from file 'fname' - * And convert the content into a hex number, then return this number */ -static int file_get_value(const char *fname, int base) { - FILE *fp = NULL; - long num; - char buff[32 + 1] = {'\0'}; - char *endptr = NULL; - - fp = fopen(fname, "r"); - if (!fp) goto error; - if (fgets(buff, sizeof(buff), fp) == NULL) - goto error; - fclose(fp); - - num = (int) strtol(buff, &endptr, base); - if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN)) - goto error; - /* if there is no digit in buff */ - if (endptr == buff) - goto error; - - if (debug_qmi) - dbg_time("(%s) = %lx", fname, num); - return (int) num; - - error: - if (fp) fclose(fp); - return CM_INVALID_VAL; -} - -/* - * This function will search the directory 'dirname' and return the first child. - * '.' and '..' is ignored by default - */ -static int dir_get_child(const char *dirname, char *buff, unsigned bufsize, const char *prefix) { - struct dirent *entptr = NULL; - DIR *dirptr; - - buff[0] = 0; - - dirptr = opendir(dirname); - if (!dirptr) - return -1; - - while ((entptr = readdir(dirptr))) { - if (entptr->d_name[0] == '.') - continue; - if (prefix && strlen(prefix) && strncmp(entptr->d_name, prefix, strlen(prefix))) - continue; - snprintf(buff, bufsize, "%.31s", entptr->d_name); - break; - } - closedir(dirptr); - - return 0; -} - -static int conf_get_val(const char *fname, const char *key) { - char buff[128] = {'\0'}; - FILE *fp = fopen(fname, "r"); - if (!fp) - return CM_INVALID_VAL; - - while (fgets(buff, sizeof(buff) - 1, fp)) { - char prefix[128] = {'\0'}; - char tail[128] = {'\0'}; - /* To eliminate cppcheck warnning: Assume string length is no more than 15 */ - sscanf(buff, "%15[^=]=%15s", prefix, tail); - if (!strncasecmp(prefix, key, strlen(key))) { - fclose(fp); - return atoi(tail); - } - } - - fclose(fp); - return CM_INVALID_VAL; -} - -static void query_usb_device_info(char *path, struct usb_device_info *p) { - size_t offset = strlen(path); - - memset(p, 0, sizeof(*p)); - - path[offset] = '\0'; - strcat(path, "/idVendor"); - p->idVendor = file_get_value(path, 16); - - if (p->idVendor == CM_INVALID_VAL) - return; - - path[offset] = '\0'; - strcat(path, "/idProduct"); - p->idProduct = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/busnum"); - p->busnum = file_get_value(path, 10); - - path[offset] = '\0'; - strcat(path, "/devnum"); - p->devnum = file_get_value(path, 10); - - path[offset] = '\0'; - strcat(path, "/bNumInterfaces"); - p->bNumInterfaces = file_get_value(path, 10); - - path[offset] = '\0'; -} - -static void query_usb_interface_info(char *path, struct usb_interface_info *p) { - char driver[128]; - size_t offset = strlen(path); - int n; - - memset(p, 0, sizeof(*p)); - - path[offset] = '\0'; - strcat(path, "/bNumEndpoints"); - p->bInterfaceClass = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/bInterfaceClass"); - p->bInterfaceClass = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/bInterfaceSubClass"); - p->bInterfaceSubClass = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/bInterfaceProtocol"); - p->bInterfaceProtocol = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/driver"); - n = readlink(path, driver, sizeof(driver)); - if (n > 0) { - driver[n] = 0; - if (debug_qmi) dbg_time("driver -> %s", driver); - n = strlen(driver); - while (n > 0) { - if (driver[n] == '/') - break; - n--; - } - strncpy(p->driver, &driver[n + 1], sizeof(p->driver) - 1); - } - - path[offset] = '\0'; -} - -static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsize) { - size_t offset = strlen(path); - char tmp[32]; - - devname[0] = 0; - - if (access(path, R_OK)) - return -1; - - path[offset] = '\0'; - strcat(path, "/GobiQMI"); - if (!access(path, R_OK)) - goto step_1; - - path[offset] = '\0'; - strcat(path, "/usbmisc"); - if (!access(path, R_OK)) - goto step_1; - - path[offset] = '\0'; - strcat(path, "/usb"); - if (!access(path, R_OK)) - goto step_1; - - return -1; - - step_1: - /* get device(qcqmiX|cdc-wdmX) */ - if (debug_qmi) dbg_time("%s", path); - dir_get_child(path, tmp, sizeof(tmp), NULL); - if (tmp[0] == '\0') - return -1; - - /* There is a chance that, no device(qcqmiX|cdc-wdmX) is generated. We should warn user about that! */ - snprintf(devname, bufsize, "/dev/%s", tmp); - if (access(devname, R_OK | F_OK) && errno == ENOENT) { - int major, minor; - - dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno)); - strcat(path, "/"); - strcat(path, tmp); - strcat(path, "/uevent"); - major = conf_get_val(path, "MAJOR"); - minor = conf_get_val(path, "MINOR"); - - if (major == CM_INVALID_VAL || minor == CM_INVALID_VAL) - dbg_time("get major and minor failed"); - else if (mknod(devname, S_IFCHR | 0666, (((major & 0xfff) << 8) | (minor & 0xff) | ((minor & 0xfff00) << 12)))) - dbg_time("please mknod %s c %d %d", devname, major, minor); - } - - return 0; -} - -/* To detect the device info of the modem. - * return: - * FALSE -> fail - * TRUE -> ok - */ -BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) { - struct dirent *ent = NULL; - DIR *pDir; - const char *rootdir = "/sys/bus/usb/devices"; - struct { - char path[255 * 2]; - } *pl; - pl = (typeof(pl)) malloc(sizeof(*pl)); - memset(pl, 0x00, sizeof(*pl)); - - pDir = opendir(rootdir); - if (!pDir) { - dbg_time("opendir %s failed: %s", rootdir, strerror(errno)); - goto error; - } - - while ((ent = readdir(pDir)) != NULL) { - char netcard[32 + 1] = {'\0'}; - char devname[32 + 5] = {'\0'}; //+strlen("/dev/") - int netIntf; - int driver_type; - - if (ent->d_name[0] == 'u') - continue; - - snprintf(pl->path, sizeof(pl->path), "%s/%s", rootdir, ent->d_name); - query_usb_device_info(pl->path, &profile->usb_dev); - if (profile->usb_dev.idVendor == CM_INVALID_VAL) - continue; - - if (profile->usb_dev.idVendor == 0x2c7c || profile->usb_dev.idVendor == 0x05c6) { - dbg_time("Find %s/%s idVendor=0x%x idProduct=0x%x, bus=0x%03x, dev=0x%03x", - rootdir, ent->d_name, profile->usb_dev.idVendor, profile->usb_dev.idProduct, - profile->usb_dev.busnum, profile->usb_dev.devnum); - } - - /* get network interface */ - /* NOTICE: there is a case that, bNumberInterface=6, but the net interface is 8 */ - /* toolchain-mips_24kc_gcc-5.4.0_musl donot support GLOB_BRACE */ - /* RG500U's MBIM is at inteface 0 */ - for (netIntf = 0; netIntf < (profile->usb_dev.bNumInterfaces + 8); netIntf++) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/net", rootdir, ent->d_name, netIntf); - dir_get_child(pl->path, netcard, sizeof(netcard), NULL); - if (netcard[0]) - break; - } - - if (netcard[0] == '\0') { //for centos 2.6.x - const char *n = "usb0"; - const char *c = "qcqmi0"; - - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/net:%s", rootdir, ent->d_name, n); - if (!access(pl->path, F_OK)) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/GobiQMI:%s", rootdir, ent->d_name, c); - if (!access(pl->path, F_OK)) { - snprintf(qmichannel, bufsize, "/dev/%s", c); - snprintf(usbnet_adapter, bufsize, "%s", n); - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4", rootdir, ent->d_name); - query_usb_interface_info(pl->path, &profile->usb_intf); - break; - } - } - } - - if (netcard[0] == '\0') - continue; - - /* not '-i iface' */ - if (usbnet_adapter[0] && strcmp(usbnet_adapter, netcard)) - continue; - - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, netIntf); - query_usb_interface_info(pl->path, &profile->usb_intf); - driver_type = get_driver_type(profile); - - if (driver_type == SOFTWARE_QMI || driver_type == SOFTWARE_MBIM) { - detect_path_cdc_wdm_or_qcqmi(pl->path, devname, sizeof(devname)); - } else if (driver_type == SOFTWARE_ECM_RNDIS_NCM) { - int atIntf = -1; - - if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel - switch (profile->usb_dev.idProduct) { //EC200U - case 0x0901: //EC200U - case 0x8101: //RG801H - atIntf = 2; - break; - case 0x0900: //RG500U - atIntf = 4; - break; - case 0x6026: //EC200T - case 0x6005: //EC200A - case 0x6002: //EC200S - case 0x6001: //EC100Y - atIntf = 3; - break; - default: - dbg_time("unknow at interface for USB idProduct:%04x\n", profile->usb_dev.idProduct); - break; - } - } - - if (atIntf != -1) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, atIntf); - dir_get_child(pl->path, devname, sizeof(devname), "tty"); - if (devname[0] && !strcmp(devname, "tty")) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/tty", rootdir, ent->d_name, atIntf); - dir_get_child(pl->path, devname, sizeof(devname), "tty"); - } - } - } - - if (netcard[0] && devname[0]) { - if (devname[0] == '/') - snprintf(qmichannel, bufsize, "%s", devname); - else - snprintf(qmichannel, bufsize, "/dev/%s", devname); - snprintf(usbnet_adapter, bufsize, "%s", netcard); - dbg_time("Auto find qmichannel = %s", qmichannel); - dbg_time("Auto find usbnet_adapter = %s", usbnet_adapter); - break; - } - } - closedir(pDir); - - if (qmichannel[0] == '\0' || usbnet_adapter[0] == '\0') { - dbg_time("network interface '%s' or qmidev '%s' is not exist", usbnet_adapter, qmichannel); - goto error; - } - free(pl); - return TRUE; - error: - free(pl); - return FALSE; -} - - -int isContain(const char *str1, const char *str2) { - if (strstr(str1, str2) != NULL) { - return 1; - } else { - return 0; - } -} - -void replaceStr(char *str, char *orig, char *rep) { - char buffer[1024]; - char *p; - while (p = strstr(str, orig)) { - memcpy(buffer, str, p - str); - buffer[p - str] = '\0'; - sprintf(buffer + strlen(buffer), "%s%s", rep, p + strlen(orig)); - strcpy(str, buffer); - } -} - -int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile) { - struct dirent *ent = NULL; - DIR *pDir; - const char *rootdir_mhi[] = {"/sys/bus/mhi_q/devices", "/sys/bus/mhi/devices", NULL}; - int i = 0; - char path[256]; - int find = 0; - while (rootdir_mhi[i]) { - const char *rootdir = rootdir_mhi[i++]; - dbg_time("rootdir : %s ", rootdir); - pDir = opendir(rootdir); - if (!pDir) { - if (errno != ENOENT) { - dbg_time("opendir %s failed: %s", rootdir, strerror(errno)); - } - continue; - } - while ((ent = readdir(pDir)) != NULL) { - char netcard[32] = {'\0'}; - char devname[32] = {'\0'}; - int software_interface = SOFTWARE_QMI; - char *pNode = NULL; - pNode = strstr(ent->d_name, "_IP_HW0"); //0306_00.01.00_IP_HW0 - if (!pNode) { - continue; - } - - char *d_name[32]; - strcpy(d_name, ent->d_name); - replaceStr(d_name, "_IP_HW0", ""); - dbg_time("while -> pcie_name = : %s ", d_name); - - snprintf(path, sizeof(path), "%s/%.32s/net", rootdir, ent->d_name); - dir_get_child(path, netcard, sizeof(netcard), NULL); - if (!netcard[0]) { - continue; - } - if (usbnet_adapter[0] && strcmp(netcard, usbnet_adapter)) { //not '-i x - continue; - } - if (!strcmp(rootdir, "/sys/bus/mhi/devices")) { - // snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); // 13 is sizeof(0306_00.01.00) - snprintf(path, sizeof(path), "%s/%s_IPCR", rootdir, d_name); - if (!access(path, F_OK)) { - /* we also need 'cat /dev/mhi_0306_00.01.00_pipe_14' to enable rmnet as like USB's DTR - or will get error 'requestSetEthMode QMUXResult = 0x1, QMUXError = 0x46' */ - sprintf(usbnet_adapter, "%s", netcard); - sprintf(qmichannel, "qrtr-%d", 3); // 3 is sdx modem's node id - profile->software_interface = SOFTWARE_QRTR; - find = 1; - break; - } - continue; - } - - //解决PCIE硬编码导致不兼容hv问题 - snprintf(path, sizeof(path), "%s/%s_IPCR", rootdir, d_name); - if (access(path, F_OK)) { - snprintf(path, sizeof(path), "%s/%s_QMI0", rootdir, d_name); - if (access(path, F_OK)) { - snprintf(path, sizeof(path), "%s/%s_MBIM", rootdir, d_name); - if (!access(path, F_OK)) { - software_interface = SOFTWARE_MBIM; - } - } - } - - //原 - // snprintf(path, sizeof(path), "%s/%.14s_IPCR", rootdir, ent->d_name); - // dbg_time("while -> path3 : %s ", path); - // if (access(path, F_OK)) { - // snprintf(path, sizeof(path), "%s/%.14s_QMI0", rootdir, ent->d_name); - // dbg_time("while -> path4 : %s ", path); - // if (access(path, F_OK)) { - // snprintf(path, sizeof(path), "%s/%.14s_MBIM", rootdir, ent->d_name); - // dbg_time("while -> path5 : %s ", path); - // if (!access(path, F_OK)) { - // software_interface = SOFTWARE_MBIM; - // } - // } - // } - - dbg_time("while -> path_final : %s ", path); - if (access(path, F_OK)) { - continue; - } - strncat(path, "/mhi_uci_q", sizeof(path) - 1); - dir_get_child(path, devname, sizeof(devname), NULL); - if (!devname[0]) { - continue; - } - dbg_time("while -> path_final_sub : %s ,dev_name: %s ", path, devname); - sprintf(usbnet_adapter, "%s", netcard); - sprintf(qmichannel, "/dev/%s", devname); - profile->software_interface = software_interface; - find = 1; - break; - } - closedir(pDir); - } - return find; -} - -int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) { - if (!access("/sys/class/net/sipa_dummy0", F_OK)) { - strcpy(usbnet_adapter, "sipa_dummy0"); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "%s%d", "pcie", profile->pdp - 1); - } else { - dbg_time("atdevice_detect failed"); - goto error; - } - - if (!access("/dev/stty_nr31", F_OK)) { - strcpy(atchannel, "/dev/stty_nr31"); - profile->software_interface = SOFTWARE_ECM_RNDIS_NCM; - } else { - goto error; - } - - return 1; - error: - return 0; -} - - -int get_driver_type(PROFILE_T *profile) { - /* QMI_WWAN */ - if (profile->usb_intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { - return SOFTWARE_QMI; - } else if (profile->usb_intf.bInterfaceClass == USB_CLASS_COMM) { - switch (profile->usb_intf.bInterfaceSubClass) { - case USB_CDC_SUBCLASS_MBIM: - return SOFTWARE_MBIM; - break; - case USB_CDC_SUBCLASS_ETHERNET: - case USB_CDC_SUBCLASS_NCM: - return SOFTWARE_ECM_RNDIS_NCM; - break; - default: - break; - } - } else if (profile->usb_intf.bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER) { - if (profile->usb_intf.bInterfaceSubClass == 1 && profile->usb_intf.bInterfaceProtocol == 3) - return SOFTWARE_ECM_RNDIS_NCM; - } - - dbg_time("%s unknow bInterfaceClass=%d, bInterfaceSubClass=%d", __func__, - profile->usb_intf.bInterfaceClass, profile->usb_intf.bInterfaceSubClass); - return DRV_INVALID; -} - -struct usbfs_getdriver { - unsigned int interface; - char driver[255 + 1]; -}; - -struct usbfs_ioctl { - int ifno; /* interface 0..N ; negative numbers reserved */ - int ioctl_code; /* MUST encode size + direction of data so the - * macros in give correct values */ - void *data; /* param buffer (in, or out) */ -}; - -#define IOCTL_USBFS_DISCONNECT _IO('U', 22) -#define IOCTL_USBFS_CONNECT _IO('U', 23) - -int usbfs_is_kernel_driver_alive(int fd, int ifnum) { - struct usbfs_getdriver getdrv; - getdrv.interface = ifnum; - if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) { - dbg_time("%s ioctl USBDEVFS_GETDRIVER failed, kernel driver may be inactive", __func__); - return 0; - } - dbg_time("%s find interface %d has match the driver %s", __func__, ifnum, getdrv.driver); - return 1; -} - -void usbfs_detach_kernel_driver(int fd, int ifnum) { - struct usbfs_ioctl operate; - operate.data = NULL; - operate.ifno = ifnum; - operate.ioctl_code = IOCTL_USBFS_DISCONNECT; - if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { - dbg_time("%s detach kernel driver failed", __func__); - } else { - dbg_time("%s detach kernel driver success", __func__); - } -} - -void usbfs_attach_kernel_driver(int fd, int ifnum) { - struct usbfs_ioctl operate; - operate.data = NULL; - operate.ifno = ifnum; - operate.ioctl_code = IOCTL_USBFS_CONNECT; - if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { - dbg_time("%s detach kernel driver failed", __func__); - } else { - dbg_time("%s detach kernel driver success", __func__); - } -} - -int reattach_driver(PROFILE_T *profile) { - int ifnum = 4; - int fd; - char devpath[128] = {'\0'}; - snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", profile->usb_dev.busnum, profile->usb_dev.devnum); - fd = open(devpath, O_RDWR | O_NOCTTY); - if (fd < 0) { - dbg_time("%s fail to open %s", __func__, devpath); - return -1; - } - usbfs_detach_kernel_driver(fd, ifnum); - usbfs_attach_kernel_driver(fd, ifnum); - close(fd); - return 0; -} - -#define SIOCETHTOOL 0x8946 - -int ql_get_netcard_driver_info(const char *devname) { - int fd = -1; - struct ethtool_drvinfo drvinfo; - struct ifreq ifr; /* ifreq suitable for ethtool ioctl */ - - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, devname); - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno)); - return -1; - } - - drvinfo.cmd = ETHTOOL_GDRVINFO; - ifr.ifr_data = (void *) &drvinfo; - - if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { - dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno)); - close(fd); - return -1; - } - - dbg_time("netcard driver = %s, driver version = %s", drvinfo.driver, drvinfo.version); - - close(fd); - - return 0; -} - -int ql_get_netcard_carrier_state(const char *devname) { - int fd = -1; - struct ethtool_value edata; - struct ifreq ifr; /* ifreq suitable for ethtool ioctl */ - - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, devname); - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno)); - return -1; - } - - edata.cmd = ETHTOOL_GLINK; - edata.data = 0; - ifr.ifr_data = (void *) &edata; - - if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { - dbg_time("ioctl('%s') error: errno(%d)(%s)", devname, errno, strerror(errno)); - return -1; - } - - if (!edata.data) - dbg_time("netcard carrier = %d", edata.data); - - close(fd); - - return edata.data; -} - -static void *catch_log(void *arg) { - PROFILE_T *profile = (PROFILE_T *) arg; - int nreads = 0; - char tbuff[256 + 32]; - char filter[32]; - size_t tsize = strlen(get_time()) + 1; - - snprintf(filter, sizeof(filter), ":%d:%03d:", profile->usb_dev.busnum, profile->usb_dev.devnum); - - while (1) { - nreads = read(profile->usbmon_fd, tbuff + tsize, sizeof(tbuff) - tsize - 1); - if (nreads <= 0) { - if (nreads == -1 && errno == EINTR) - continue; - break; - } - - tbuff[tsize + nreads] = '\0'; // printf("%s", buff); - - if (!strstr(tbuff + tsize, filter)) - continue; - - snprintf(tbuff, sizeof(tbuff), "%s", get_time()); - tbuff[tsize - 1] = ' '; - - fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp); - } - - return NULL; -} - -int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path) { - char usbmon_path[256]; - pthread_t pt; - pthread_attr_t attr; - - if (access("/sys/module/usbmon", F_OK)) { - dbg_time("usbmon is not load, please execute \"modprobe usbmon\" or \"insmod usbmon.ko\""); - return -1; - } - - if (access("/sys/kernel/debug/usb", F_OK)) { - dbg_time("debugfs is not mount, please execute \"mount -t debugfs none_debugs /sys/kernel/debug\""); - return -1; - } - - snprintf(usbmon_path, sizeof(usbmon_path), "/sys/kernel/debug/usb/usbmon/%du", profile->usb_dev.busnum); - profile->usbmon_fd = open(usbmon_path, O_RDONLY); - if (profile->usbmon_fd < 0) { - dbg_time("open %s error(%d) (%s)", usbmon_path, errno, strerror(errno)); - return -1; - } - - snprintf(usbmon_path, sizeof(usbmon_path), "cat /sys/kernel/debug/usb/devices >> %s", log_path); - if (system(usbmon_path) == -1) {}; - - profile->usbmon_logfile_fp = fopen(log_path, "wb"); - if (!profile->usbmon_logfile_fp) { - dbg_time("open %s error(%d) (%s)", log_path, errno, strerror(errno)); - close(profile->usbmon_fd); - profile->usbmon_fd = -1; - return -1; - } - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - pthread_create(&pt, &attr, catch_log, (void *) profile); - - return 0; -} - -void ql_stop_usbmon_log(PROFILE_T *profile) { - if (profile->usbmon_fd > 0) - close(profile->usbmon_fd); - if (profile->usbmon_logfile_fp) - fclose(profile->usbmon_logfile_fp); -} diff --git a/quectel_cm_5G/src/ethtool-copy.h b/quectel_cm_5G/src/ethtool-copy.h deleted file mode 100644 index b5515c2..0000000 --- a/quectel_cm_5G/src/ethtool-copy.h +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * ethtool.h: Defines for Linux ethtool. - * - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * Copyright 2001 Jeff Garzik - * Portions Copyright 2001 Sun Microsystems (thockin@sun.com) - * Portions Copyright 2002 Intel (eli.kupermann@intel.com, - * christopher.leech@intel.com, - * scott.feldman@intel.com) - * Portions Copyright (C) Sun Microsystems 2008 - */ - -#ifndef _LINUX_ETHTOOL_H -#define _LINUX_ETHTOOL_H - -#include -#include - -/* This should work for both 32 and 64 bit userland. */ -struct ethtool_cmd { - __u32 cmd; - __u32 supported; /* Features this interface supports */ - __u32 advertising; /* Features this interface advertises */ - __u16 speed; /* The forced speed (lower bits) in - * Mbps. Please use - * ethtool_cmd_speed()/_set() to - * access it */ - __u8 duplex; /* Duplex, half or full */ - __u8 port; /* Which connector port */ - __u8 phy_address; /* MDIO PHY address (PRTAD for clause 45). - * May be read-only or read-write - * depending on the driver. - */ - __u8 transceiver; /* Which transceiver to use */ - __u8 autoneg; /* Enable or disable autonegotiation */ - __u8 mdio_support; /* MDIO protocols supported. Read-only. - * Not set by all drivers. - */ - __u32 maxtxpkt; /* Tx pkts before generating tx int */ - __u32 maxrxpkt; /* Rx pkts before generating rx int */ - __u16 speed_hi; /* The forced speed (upper - * bits) in Mbps. Please use - * ethtool_cmd_speed()/_set() to - * access it */ - __u8 eth_tp_mdix; /* twisted pair MDI-X status */ - __u8 eth_tp_mdix_ctrl; /* twisted pair MDI-X control, when set, - * link should be renegotiated if necessary - */ - __u32 lp_advertising; /* Features the link partner advertises */ - __u32 reserved[2]; -}; - -static __inline__ void ethtool_cmd_speed_set(struct ethtool_cmd *ep, - __u32 speed) -{ - - ep->speed = (__u16)speed; - ep->speed_hi = (__u16)(speed >> 16); -} - -static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) -{ - return (ep->speed_hi << 16) | ep->speed; -} - -/* Device supports clause 22 register access to PHY or peripherals - * using the interface defined in . This should not be - * set if there are known to be no such peripherals present or if - * the driver only emulates clause 22 registers for compatibility. - */ -#define ETH_MDIO_SUPPORTS_C22 1 - -/* Device supports clause 45 register access to PHY or peripherals - * using the interface defined in and . - * This should not be set if there are known to be no such peripherals - * present. - */ -#define ETH_MDIO_SUPPORTS_C45 2 - -#define ETHTOOL_FWVERS_LEN 32 -#define ETHTOOL_BUSINFO_LEN 32 -/* these strings are set to whatever the driver author decides... */ -struct ethtool_drvinfo { - __u32 cmd; - char driver[32]; /* driver short name, "tulip", "eepro100" */ - char version[32]; /* driver version string */ - char fw_version[ETHTOOL_FWVERS_LEN]; /* firmware version string */ - char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ - /* For PCI devices, use pci_name(pci_dev). */ - char reserved1[32]; - char reserved2[12]; - /* - * Some struct members below are filled in - * using ops->get_sset_count(). Obtaining - * this info from ethtool_drvinfo is now - * deprecated; Use ETHTOOL_GSSET_INFO - * instead. - */ - __u32 n_priv_flags; /* number of flags valid in ETHTOOL_GPFLAGS */ - __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ - __u32 testinfo_len; - __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ - __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ -}; - -#define SOPASS_MAX 6 -/* wake-on-lan settings */ -struct ethtool_wolinfo { - __u32 cmd; - __u32 supported; - __u32 wolopts; - __u8 sopass[SOPASS_MAX]; /* SecureOn(tm) password */ -}; - -/* for passing single values */ -struct ethtool_value { - __u32 cmd; - __u32 data; -}; - -/* for passing big chunks of data */ -struct ethtool_regs { - __u32 cmd; - __u32 version; /* driver-specific, indicates different chips/revs */ - __u32 len; /* bytes */ - __u8 data[0]; -}; - -/* for passing EEPROM chunks */ -struct ethtool_eeprom { - __u32 cmd; - __u32 magic; - __u32 offset; /* in bytes */ - __u32 len; /* in bytes */ - __u8 data[0]; -}; - -/** - * struct ethtool_eee - Energy Efficient Ethernet information - * @cmd: ETHTOOL_{G,S}EEE - * @supported: Mask of %SUPPORTED_* flags for the speed/duplex combinations - * for which there is EEE support. - * @advertised: Mask of %ADVERTISED_* flags for the speed/duplex combinations - * advertised as eee capable. - * @lp_advertised: Mask of %ADVERTISED_* flags for the speed/duplex - * combinations advertised by the link partner as eee capable. - * @eee_active: Result of the eee auto negotiation. - * @eee_enabled: EEE configured mode (enabled/disabled). - * @tx_lpi_enabled: Whether the interface should assert its tx lpi, given - * that eee was negotiated. - * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting - * its tx lpi (after reaching 'idle' state). Effective only when eee - * was negotiated and tx_lpi_enabled was set. - */ -struct ethtool_eee { - __u32 cmd; - __u32 supported; - __u32 advertised; - __u32 lp_advertised; - __u32 eee_active; - __u32 eee_enabled; - __u32 tx_lpi_enabled; - __u32 tx_lpi_timer; - __u32 reserved[2]; -}; - -/** - * struct ethtool_modinfo - plugin module eeprom information - * @cmd: %ETHTOOL_GMODULEINFO - * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx - * @eeprom_len: Length of the eeprom - * - * This structure is used to return the information to - * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. - * The type code indicates the eeprom data format - */ -struct ethtool_modinfo { - __u32 cmd; - __u32 type; - __u32 eeprom_len; - __u32 reserved[8]; -}; - -/** - * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates - * @cmd: ETHTOOL_{G,S}COALESCE - * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after - * a packet arrives. - * @rx_max_coalesced_frames: Maximum number of packets to receive - * before an RX interrupt. - * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that - * this value applies while an IRQ is being serviced by the host. - * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames, - * except that this value applies while an IRQ is being serviced - * by the host. - * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after - * a packet is sent. - * @tx_max_coalesced_frames: Maximum number of packets to be sent - * before a TX interrupt. - * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that - * this value applies while an IRQ is being serviced by the host. - * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames, - * except that this value applies while an IRQ is being serviced - * by the host. - * @stats_block_coalesce_usecs: How many usecs to delay in-memory - * statistics block updates. Some drivers do not have an - * in-memory statistic block, and in such cases this value is - * ignored. This value must not be zero. - * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing. - * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing. - * @pkt_rate_low: Threshold for low packet rate (packets per second). - * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after - * a packet arrives, when the packet rate is below @pkt_rate_low. - * @rx_max_coalesced_frames_low: Maximum number of packets to be received - * before an RX interrupt, when the packet rate is below @pkt_rate_low. - * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after - * a packet is sent, when the packet rate is below @pkt_rate_low. - * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before - * a TX interrupt, when the packet rate is below @pkt_rate_low. - * @pkt_rate_high: Threshold for high packet rate (packets per second). - * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after - * a packet arrives, when the packet rate is above @pkt_rate_high. - * @rx_max_coalesced_frames_high: Maximum number of packets to be received - * before an RX interrupt, when the packet rate is above @pkt_rate_high. - * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after - * a packet is sent, when the packet rate is above @pkt_rate_high. - * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before - * a TX interrupt, when the packet rate is above @pkt_rate_high. - * @rate_sample_interval: How often to do adaptive coalescing packet rate - * sampling, measured in seconds. Must not be zero. - * - * Each pair of (usecs, max_frames) fields specifies this exit - * condition for interrupt coalescing: - * (usecs > 0 && time_since_first_completion >= usecs) || - * (max_frames > 0 && completed_frames >= max_frames) - * It is illegal to set both usecs and max_frames to zero as this - * would cause interrupts to never be generated. To disable - * coalescing, set usecs = 0 and max_frames = 1. - * - * Some implementations ignore the value of max_frames and use the - * condition: - * time_since_first_completion >= usecs - * This is deprecated. Drivers for hardware that does not support - * counting completions should validate that max_frames == !rx_usecs. - * - * Adaptive RX/TX coalescing is an algorithm implemented by some - * drivers to improve latency under low packet rates and improve - * throughput under high packet rates. Some drivers only implement - * one of RX or TX adaptive coalescing. Anything not implemented by - * the driver causes these values to be silently ignored. - * - * When the packet rate is below @pkt_rate_high but above - * @pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ -struct ethtool_coalesce { - __u32 cmd; - __u32 rx_coalesce_usecs; - __u32 rx_max_coalesced_frames; - __u32 rx_coalesce_usecs_irq; - __u32 rx_max_coalesced_frames_irq; - __u32 tx_coalesce_usecs; - __u32 tx_max_coalesced_frames; - __u32 tx_coalesce_usecs_irq; - __u32 tx_max_coalesced_frames_irq; - __u32 stats_block_coalesce_usecs; - __u32 use_adaptive_rx_coalesce; - __u32 use_adaptive_tx_coalesce; - __u32 pkt_rate_low; - __u32 rx_coalesce_usecs_low; - __u32 rx_max_coalesced_frames_low; - __u32 tx_coalesce_usecs_low; - __u32 tx_max_coalesced_frames_low; - __u32 pkt_rate_high; - __u32 rx_coalesce_usecs_high; - __u32 rx_max_coalesced_frames_high; - __u32 tx_coalesce_usecs_high; - __u32 tx_max_coalesced_frames_high; - __u32 rate_sample_interval; -}; - -/* for configuring RX/TX ring parameters */ -struct ethtool_ringparam { - __u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ - - /* Read only attributes. These indicate the maximum number - * of pending RX/TX ring entries the driver will allow the - * user to set. - */ - __u32 rx_max_pending; - __u32 rx_mini_max_pending; - __u32 rx_jumbo_max_pending; - __u32 tx_max_pending; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - __u32 rx_pending; - __u32 rx_mini_pending; - __u32 rx_jumbo_pending; - __u32 tx_pending; -}; - -/** - * struct ethtool_channels - configuring number of network channel - * @cmd: ETHTOOL_{G,S}CHANNELS - * @max_rx: Read only. Maximum number of receive channel the driver support. - * @max_tx: Read only. Maximum number of transmit channel the driver support. - * @max_other: Read only. Maximum number of other channel the driver support. - * @max_combined: Read only. Maximum number of combined channel the driver - * support. Set of queues RX, TX or other. - * @rx_count: Valid values are in the range 1 to the max_rx. - * @tx_count: Valid values are in the range 1 to the max_tx. - * @other_count: Valid values are in the range 1 to the max_other. - * @combined_count: Valid values are in the range 1 to the max_combined. - * - * This can be used to configure RX, TX and other channels. - */ - -struct ethtool_channels { - __u32 cmd; - __u32 max_rx; - __u32 max_tx; - __u32 max_other; - __u32 max_combined; - __u32 rx_count; - __u32 tx_count; - __u32 other_count; - __u32 combined_count; -}; - -/* for configuring link flow control parameters */ -struct ethtool_pauseparam { - __u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ - - /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autoneg' here non-zero to have the - * pause parameters be auto-negotiated too. In such a case, the - * {rx,tx}_pause values below determine what capabilities are - * advertised. - * - * If 'autoneg' is zero or the link is not being auto-negotiated, - * then {rx,tx}_pause force the driver to use/not-use pause - * flow control. - */ - __u32 autoneg; - __u32 rx_pause; - __u32 tx_pause; -}; - -#define ETH_GSTRING_LEN 32 -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, - ETH_SS_PRIV_FLAGS, - ETH_SS_NTUPLE_FILTERS, /* Do not use, GRXNTUPLE is now deprecated */ - ETH_SS_FEATURES, -}; - -/* for passing string sets for data tagging */ -struct ethtool_gstrings { - __u32 cmd; /* ETHTOOL_GSTRINGS */ - __u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - __u32 len; /* number of strings in the string set */ - __u8 data[0]; -}; - -struct ethtool_sset_info { - __u32 cmd; /* ETHTOOL_GSSET_INFO */ - __u32 reserved; - __u64 sset_mask; /* input: each bit selects an sset to query */ - /* output: each bit a returned sset */ - __u32 data[0]; /* ETH_SS_xxx count, in order, based on bits - in sset_mask. One bit implies one - __u32, two bits implies two - __u32's, etc. */ -}; - -/** - * enum ethtool_test_flags - flags definition of ethtool_test - * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise - * only online tests. - * @ETH_TEST_FL_FAILED: Driver set this flag if test fails. - * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback - * test. - * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test - */ - -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), - ETH_TEST_FL_EXTERNAL_LB = (1 << 2), - ETH_TEST_FL_EXTERNAL_LB_DONE = (1 << 3), -}; - -/* for requesting NIC test and getting results*/ -struct ethtool_test { - __u32 cmd; /* ETHTOOL_TEST */ - __u32 flags; /* ETH_TEST_FL_xxx */ - __u32 reserved; - __u32 len; /* result length, in number of u64 elements */ - __u64 data[0]; -}; - -/* for dumping NIC-specific statistics */ -struct ethtool_stats { - __u32 cmd; /* ETHTOOL_GSTATS */ - __u32 n_stats; /* number of u64's being returned */ - __u64 data[0]; -}; - -struct ethtool_perm_addr { - __u32 cmd; /* ETHTOOL_GPERMADDR */ - __u32 size; - __u8 data[0]; -}; - -/* boolean flags controlling per-interface behavior characteristics. - * When reading, the flag indicates whether or not a certain behavior - * is enabled/present. When writing, the flag indicates whether - * or not the driver should turn on (set) or off (clear) a behavior. - * - * Some behaviors may read-only (unconditionally absent or present). - * If such is the case, return EINVAL in the set-flags operation if the - * flag differs from the read-only value. - */ -enum ethtool_flags { - ETH_FLAG_TXVLAN = (1 << 7), /* TX VLAN offload enabled */ - ETH_FLAG_RXVLAN = (1 << 8), /* RX VLAN offload enabled */ - ETH_FLAG_LRO = (1 << 15), /* LRO is enabled */ - ETH_FLAG_NTUPLE = (1 << 27), /* N-tuple filters enabled */ - ETH_FLAG_RXHASH = (1 << 28), -}; - -/* The following structures are for supporting RX network flow - * classification and RX n-tuple configuration. Note, all multibyte - * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to - * be in network byte order. - */ - -/** - * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc. - * @ip4src: Source host - * @ip4dst: Destination host - * @psrc: Source port - * @pdst: Destination port - * @tos: Type-of-service - * - * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow. - */ -struct ethtool_tcpip4_spec { - __be32 ip4src; - __be32 ip4dst; - __be16 psrc; - __be16 pdst; - __u8 tos; -}; - -/** - * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4 - * @ip4src: Source host - * @ip4dst: Destination host - * @spi: Security parameters index - * @tos: Type-of-service - * - * This can be used to specify an IPsec transport or tunnel over IPv4. - */ -struct ethtool_ah_espip4_spec { - __be32 ip4src; - __be32 ip4dst; - __be32 spi; - __u8 tos; -}; - -#define ETH_RX_NFC_IP4 1 - -/** - * struct ethtool_usrip4_spec - general flow specification for IPv4 - * @ip4src: Source host - * @ip4dst: Destination host - * @l4_4_bytes: First 4 bytes of transport (layer 4) header - * @tos: Type-of-service - * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0 - * @proto: Transport protocol number; mask must be 0 - */ -struct ethtool_usrip4_spec { - __be32 ip4src; - __be32 ip4dst; - __be32 l4_4_bytes; - __u8 tos; - __u8 ip_ver; - __u8 proto; -}; - -union ethtool_flow_union { - struct ethtool_tcpip4_spec tcp_ip4_spec; - struct ethtool_tcpip4_spec udp_ip4_spec; - struct ethtool_tcpip4_spec sctp_ip4_spec; - struct ethtool_ah_espip4_spec ah_ip4_spec; - struct ethtool_ah_espip4_spec esp_ip4_spec; - struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; - __u8 hdata[52]; -}; - -/** - * struct ethtool_flow_ext - additional RX flow fields - * @h_dest: destination MAC address - * @vlan_etype: VLAN EtherType - * @vlan_tci: VLAN tag control information - * @data: user defined data - * - * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT - * is set in &struct ethtool_rx_flow_spec @flow_type. - * @h_dest is valid if %FLOW_MAC_EXT is set. - */ -struct ethtool_flow_ext { - __u8 padding[2]; - unsigned char h_dest[ETH_ALEN]; - __be16 vlan_etype; - __be16 vlan_tci; - __be32 data[2]; -}; - -/** - * struct ethtool_rx_flow_spec - classification rule for RX flows - * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW - * @h_u: Flow fields to match (dependent on @flow_type) - * @h_ext: Additional fields to match - * @m_u: Masks for flow field bits to be matched - * @m_ext: Masks for additional field bits to be matched - * Note, all additional fields must be ignored unless @flow_type - * includes the %FLOW_EXT or %FLOW_MAC_EXT flag - * (see &struct ethtool_flow_ext description). - * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC - * if packets should be discarded - * @location: Location of rule in the table. Locations must be - * numbered such that a flow matching multiple rules will be - * classified according to the first (lowest numbered) rule. - */ -struct ethtool_rx_flow_spec { - __u32 flow_type; - union ethtool_flow_union h_u; - struct ethtool_flow_ext h_ext; - union ethtool_flow_union m_u; - struct ethtool_flow_ext m_ext; - __u64 ring_cookie; - __u32 location; -}; - -/** - * struct ethtool_rxnfc - command to get or set RX flow classification rules - * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH, - * %ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE, - * %ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS - * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW - * @data: Command-dependent value - * @fs: Flow classification rule - * @rule_cnt: Number of rules to be affected - * @rule_locs: Array of used rule locations - * - * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating - * the fields included in the flow hash, e.g. %RXH_IP_SRC. The following - * structure fields must not be used. - * - * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues - * on return. - * - * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined - * rules on return. If @data is non-zero on return then it is the - * size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the - * driver supports any special location values. If that flag is not - * set in @data then special location values should not be used. - * - * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an - * existing rule on entry and @fs contains the rule on return. - * - * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the - * user buffer for @rule_locs on entry. On return, @data is the size - * of the rule table, @rule_cnt is the number of defined rules, and - * @rule_locs contains the locations of the defined rules. Drivers - * must use the second parameter to get_rxnfc() instead of @rule_locs. - * - * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update. - * @fs.@location either specifies the location to use or is a special - * location value with %RX_CLS_LOC_SPECIAL flag set. On return, - * @fs.@location is the actual rule location. - * - * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an - * existing rule on entry. - * - * A driver supporting the special location values for - * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused - * location, and may remove a rule at a later location (lower - * priority) that matches exactly the same set of flows. The special - * values are: %RX_CLS_LOC_ANY, selecting any location; - * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum - * priority); and %RX_CLS_LOC_LAST, selecting the last suitable - * location (minimum priority). Additional special values may be - * defined in future and drivers must return -%EINVAL for any - * unrecognised value. - */ -struct ethtool_rxnfc { - __u32 cmd; - __u32 flow_type; - __u64 data; - struct ethtool_rx_flow_spec fs; - __u32 rule_cnt; - __u32 rule_locs[0]; -}; - - -/** - * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection - * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR - * @size: On entry, the array size of the user buffer, which may be zero. - * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware - * indirection table. - * @ring_index: RX ring/queue index for each hash value - * - * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size - * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means - * the table should be reset to default values. This last feature - * is not supported by the original implementations. - */ -struct ethtool_rxfh_indir { - __u32 cmd; - __u32 size; - __u32 ring_index[0]; -}; - -/** - * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter - * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW - * @h_u: Flow field values to match (dependent on @flow_type) - * @m_u: Masks for flow field value bits to be ignored - * @vlan_tag: VLAN tag to match - * @vlan_tag_mask: Mask for VLAN tag bits to be ignored - * @data: Driver-dependent data to match - * @data_mask: Mask for driver-dependent data bits to be ignored - * @action: RX ring/queue index to deliver to (non-negative) or other action - * (negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP) - * - * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where - * a field value and mask are both zero this is treated as if all mask - * bits are set i.e. the field is ignored. - */ -struct ethtool_rx_ntuple_flow_spec { - __u32 flow_type; - union { - struct ethtool_tcpip4_spec tcp_ip4_spec; - struct ethtool_tcpip4_spec udp_ip4_spec; - struct ethtool_tcpip4_spec sctp_ip4_spec; - struct ethtool_ah_espip4_spec ah_ip4_spec; - struct ethtool_ah_espip4_spec esp_ip4_spec; - struct ethtool_usrip4_spec usr_ip4_spec; - struct ethhdr ether_spec; - __u8 hdata[72]; - } h_u, m_u; - - __u16 vlan_tag; - __u16 vlan_tag_mask; - __u64 data; - __u64 data_mask; - - __s32 action; -#define ETHTOOL_RXNTUPLE_ACTION_DROP (-1) /* drop packet */ -#define ETHTOOL_RXNTUPLE_ACTION_CLEAR (-2) /* clear filter */ -}; - -/** - * struct ethtool_rx_ntuple - command to set or clear RX flow filter - * @cmd: Command number - %ETHTOOL_SRXNTUPLE - * @fs: Flow filter specification - */ -struct ethtool_rx_ntuple { - __u32 cmd; - struct ethtool_rx_ntuple_flow_spec fs; -}; - -#define ETHTOOL_FLASH_MAX_FILENAME 128 -enum ethtool_flash_op_type { - ETHTOOL_FLASH_ALL_REGIONS = 0, -}; - -/* for passing firmware flashing related parameters */ -struct ethtool_flash { - __u32 cmd; - __u32 region; - char data[ETHTOOL_FLASH_MAX_FILENAME]; -}; - -/** - * struct ethtool_dump - used for retrieving, setting device dump - * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or - * %ETHTOOL_SET_DUMP - * @version: FW version of the dump, filled in by driver - * @flag: driver dependent flag for dump setting, filled in by driver during - * get and filled in by ethtool for set operation. - * flag must be initialized by macro ETH_FW_DUMP_DISABLE value when - * firmware dump is disabled. - * @len: length of dump data, used as the length of the user buffer on entry to - * %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver - * for %ETHTOOL_GET_DUMP_FLAG command - * @data: data collected for get dump data operation - */ - -#define ETH_FW_DUMP_DISABLE 0 - -struct ethtool_dump { - __u32 cmd; - __u32 version; - __u32 flag; - __u32 len; - __u8 data[0]; -}; - -/* for returning and changing feature sets */ - -/** - * struct ethtool_get_features_block - block with state of 32 features - * @available: mask of changeable features - * @requested: mask of features requested to be enabled if possible - * @active: mask of currently enabled features - * @never_changed: mask of features not changeable for any device - */ -struct ethtool_get_features_block { - __u32 available; - __u32 requested; - __u32 active; - __u32 never_changed; -}; - -/** - * struct ethtool_gfeatures - command to get state of device's features - * @cmd: command number = %ETHTOOL_GFEATURES - * @size: in: number of elements in the features[] array; - * out: number of elements in features[] needed to hold all features - * @features: state of features - */ -struct ethtool_gfeatures { - __u32 cmd; - __u32 size; - struct ethtool_get_features_block features[0]; -}; - -/** - * struct ethtool_set_features_block - block with request for 32 features - * @valid: mask of features to be changed - * @requested: values of features to be changed - */ -struct ethtool_set_features_block { - __u32 valid; - __u32 requested; -}; - -/** - * struct ethtool_sfeatures - command to request change in device's features - * @cmd: command number = %ETHTOOL_SFEATURES - * @size: array size of the features[] array - * @features: feature change masks - */ -struct ethtool_sfeatures { - __u32 cmd; - __u32 size; - struct ethtool_set_features_block features[0]; -}; - -/** - * struct ethtool_ts_info - holds a device's timestamping and PHC association - * @cmd: command number = %ETHTOOL_GET_TS_INFO - * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags - * @phc_index: device index of the associated PHC, or -1 if there is none - * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values - * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values - * - * The bits in the 'tx_types' and 'rx_filters' fields correspond to - * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, - * respectively. For example, if the device supports HWTSTAMP_TX_ON, - * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set. - */ -struct ethtool_ts_info { - __u32 cmd; - __u32 so_timestamping; - __s32 phc_index; - __u32 tx_types; - __u32 tx_reserved[3]; - __u32 rx_filters; - __u32 rx_reserved[3]; -}; - -/* - * %ETHTOOL_SFEATURES changes features present in features[].valid to the - * values of corresponding bits in features[].requested. Bits in .requested - * not set in .valid or not changeable are ignored. - * - * Returns %EINVAL when .valid contains undefined or never-changeable bits - * or size is not equal to required number of features words (32-bit blocks). - * Returns >= 0 if request was completed; bits set in the value mean: - * %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not - * changeable (not present in %ETHTOOL_GFEATURES' features[].available) - * those bits were ignored. - * %ETHTOOL_F_WISH - some or all changes requested were recorded but the - * resulting state of bits masked by .valid is not equal to .requested. - * Probably there are other device-specific constraints on some features - * in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered - * here as though ignored bits were cleared. - * %ETHTOOL_F_COMPAT - some or all changes requested were made by calling - * compatibility functions. Requested offload state cannot be properly - * managed by kernel. - * - * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of - * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands - * for ETH_SS_FEATURES string set. First entry in the table corresponds to least - * significant bit in features[0] fields. Empty strings mark undefined features. - */ -enum ethtool_sfeatures_retval_bits { - ETHTOOL_F_UNSUPPORTED__BIT, - ETHTOOL_F_WISH__BIT, - ETHTOOL_F_COMPAT__BIT, -}; - -#define ETHTOOL_F_UNSUPPORTED (1 << ETHTOOL_F_UNSUPPORTED__BIT) -#define ETHTOOL_F_WISH (1 << ETHTOOL_F_WISH__BIT) -#define ETHTOOL_F_COMPAT (1 << ETHTOOL_F_COMPAT__BIT) - - -/* CMDs currently supported */ -#define ETHTOOL_GSET 0x00000001 /* Get settings. */ -#define ETHTOOL_SSET 0x00000002 /* Set settings. */ -#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ -#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers. */ -#define ETHTOOL_GWOL 0x00000005 /* Get wake-on-lan options. */ -#define ETHTOOL_SWOL 0x00000006 /* Set wake-on-lan options. */ -#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level. */ -#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation. */ -/* Get link status for host, i.e. whether the interface *and* the - * physical port (if there is one) are up (ethtool_value). */ -#define ETHTOOL_GLINK 0x0000000a -#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */ -#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters. */ -#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable - * (ethtool_value) */ -#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable - * (ethtool_value). */ -#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test. */ -#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -#define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */ -#define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */ -#define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */ -#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */ -#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */ -#define ETHTOOL_GFLAGS 0x00000025 /* Get flags bitmap(ethtool_value) */ -#define ETHTOOL_SFLAGS 0x00000026 /* Set flags bitmap(ethtool_value) */ -#define ETHTOOL_GPFLAGS 0x00000027 /* Get driver-private flags bitmap */ -#define ETHTOOL_SPFLAGS 0x00000028 /* Set driver-private flags bitmap */ - -#define ETHTOOL_GRXFH 0x00000029 /* Get RX flow hash configuration */ -#define ETHTOOL_SRXFH 0x0000002a /* Set RX flow hash configuration */ -#define ETHTOOL_GGRO 0x0000002b /* Get GRO enable (ethtool_value) */ -#define ETHTOOL_SGRO 0x0000002c /* Set GRO enable (ethtool_value) */ -#define ETHTOOL_GRXRINGS 0x0000002d /* Get RX rings available for LB */ -#define ETHTOOL_GRXCLSRLCNT 0x0000002e /* Get RX class rule count */ -#define ETHTOOL_GRXCLSRULE 0x0000002f /* Get RX classification rule */ -#define ETHTOOL_GRXCLSRLALL 0x00000030 /* Get all RX classification rule */ -#define ETHTOOL_SRXCLSRLDEL 0x00000031 /* Delete RX classification rule */ -#define ETHTOOL_SRXCLSRLINS 0x00000032 /* Insert RX classification rule */ -#define ETHTOOL_FLASHDEV 0x00000033 /* Flash firmware to device */ -#define ETHTOOL_RESET 0x00000034 /* Reset hardware */ -#define ETHTOOL_SRXNTUPLE 0x00000035 /* Add an n-tuple filter to device */ -#define ETHTOOL_GRXNTUPLE 0x00000036 /* deprecated */ -#define ETHTOOL_GSSET_INFO 0x00000037 /* Get string set info */ -#define ETHTOOL_GRXFHINDIR 0x00000038 /* Get RX flow hash indir'n table */ -#define ETHTOOL_SRXFHINDIR 0x00000039 /* Set RX flow hash indir'n table */ - -#define ETHTOOL_GFEATURES 0x0000003a /* Get device offload settings */ -#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */ -#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */ -#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */ -#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */ -#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */ -#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */ -#define ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */ -#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ -#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ -#define ETHTOOL_GEEE 0x00000044 /* Get EEE settings */ -#define ETHTOOL_SEEE 0x00000045 /* Set EEE settings */ - -/* compatibility with older code */ -#define SPARC_ETH_GSET ETHTOOL_GSET -#define SPARC_ETH_SSET ETHTOOL_SSET - -/* Indicates what features are supported by the interface. */ -#define SUPPORTED_10baseT_Half (1 << 0) -#define SUPPORTED_10baseT_Full (1 << 1) -#define SUPPORTED_100baseT_Half (1 << 2) -#define SUPPORTED_100baseT_Full (1 << 3) -#define SUPPORTED_1000baseT_Half (1 << 4) -#define SUPPORTED_1000baseT_Full (1 << 5) -#define SUPPORTED_Autoneg (1 << 6) -#define SUPPORTED_TP (1 << 7) -#define SUPPORTED_AUI (1 << 8) -#define SUPPORTED_MII (1 << 9) -#define SUPPORTED_FIBRE (1 << 10) -#define SUPPORTED_BNC (1 << 11) -#define SUPPORTED_10000baseT_Full (1 << 12) -#define SUPPORTED_Pause (1 << 13) -#define SUPPORTED_Asym_Pause (1 << 14) -#define SUPPORTED_2500baseX_Full (1 << 15) -#define SUPPORTED_Backplane (1 << 16) -#define SUPPORTED_1000baseKX_Full (1 << 17) -#define SUPPORTED_10000baseKX4_Full (1 << 18) -#define SUPPORTED_10000baseKR_Full (1 << 19) -#define SUPPORTED_10000baseR_FEC (1 << 20) -#define SUPPORTED_20000baseMLD2_Full (1 << 21) -#define SUPPORTED_20000baseKR2_Full (1 << 22) -#define SUPPORTED_40000baseKR4_Full (1 << 23) -#define SUPPORTED_40000baseCR4_Full (1 << 24) -#define SUPPORTED_40000baseSR4_Full (1 << 25) -#define SUPPORTED_40000baseLR4_Full (1 << 26) - -/* Indicates what features are advertised by the interface. */ -#define ADVERTISED_10baseT_Half (1 << 0) -#define ADVERTISED_10baseT_Full (1 << 1) -#define ADVERTISED_100baseT_Half (1 << 2) -#define ADVERTISED_100baseT_Full (1 << 3) -#define ADVERTISED_1000baseT_Half (1 << 4) -#define ADVERTISED_1000baseT_Full (1 << 5) -#define ADVERTISED_Autoneg (1 << 6) -#define ADVERTISED_TP (1 << 7) -#define ADVERTISED_AUI (1 << 8) -#define ADVERTISED_MII (1 << 9) -#define ADVERTISED_FIBRE (1 << 10) -#define ADVERTISED_BNC (1 << 11) -#define ADVERTISED_10000baseT_Full (1 << 12) -#define ADVERTISED_Pause (1 << 13) -#define ADVERTISED_Asym_Pause (1 << 14) -#define ADVERTISED_2500baseX_Full (1 << 15) -#define ADVERTISED_Backplane (1 << 16) -#define ADVERTISED_1000baseKX_Full (1 << 17) -#define ADVERTISED_10000baseKX4_Full (1 << 18) -#define ADVERTISED_10000baseKR_Full (1 << 19) -#define ADVERTISED_10000baseR_FEC (1 << 20) -#define ADVERTISED_20000baseMLD2_Full (1 << 21) -#define ADVERTISED_20000baseKR2_Full (1 << 22) -#define ADVERTISED_40000baseKR4_Full (1 << 23) -#define ADVERTISED_40000baseCR4_Full (1 << 24) -#define ADVERTISED_40000baseSR4_Full (1 << 25) -#define ADVERTISED_40000baseLR4_Full (1 << 26) - -/* The following are all involved in forcing a particular link - * mode for the device for setting things. When getting the - * devices settings, these indicate the current mode and whether - * it was forced up into this mode or autonegotiated. - */ - -/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ -#define SPEED_10 10 -#define SPEED_100 100 -#define SPEED_1000 1000 -#define SPEED_2500 2500 -#define SPEED_10000 10000 -#define SPEED_UNKNOWN -1 - -/* Duplex, half or full. */ -#define DUPLEX_HALF 0x00 -#define DUPLEX_FULL 0x01 -#define DUPLEX_UNKNOWN 0xff - -/* Which connector port. */ -#define PORT_TP 0x00 -#define PORT_AUI 0x01 -#define PORT_MII 0x02 -#define PORT_FIBRE 0x03 -#define PORT_BNC 0x04 -#define PORT_DA 0x05 -#define PORT_NONE 0xef -#define PORT_OTHER 0xff - -/* Which transceiver to use. */ -#define XCVR_INTERNAL 0x00 -#define XCVR_EXTERNAL 0x01 -#define XCVR_DUMMY1 0x02 -#define XCVR_DUMMY2 0x03 -#define XCVR_DUMMY3 0x04 - -/* Enable or disable autonegotiation. If this is set to enable, - * the forced link modes above are completely ignored. - */ -#define AUTONEG_DISABLE 0x00 -#define AUTONEG_ENABLE 0x01 - -/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then - * the driver is required to renegotiate link - */ -#define ETH_TP_MDI_INVALID 0x00 /* status: unknown; control: unsupported */ -#define ETH_TP_MDI 0x01 /* status: MDI; control: force MDI */ -#define ETH_TP_MDI_X 0x02 /* status: MDI-X; control: force MDI-X */ -#define ETH_TP_MDI_AUTO 0x03 /* control: auto-select */ - -/* Wake-On-Lan options. */ -#define WAKE_PHY (1 << 0) -#define WAKE_UCAST (1 << 1) -#define WAKE_MCAST (1 << 2) -#define WAKE_BCAST (1 << 3) -#define WAKE_ARP (1 << 4) -#define WAKE_MAGIC (1 << 5) -#define WAKE_MAGICSECURE (1 << 6) /* only meaningful if WAKE_MAGIC */ - -/* L2-L4 network traffic flow types */ -#define TCP_V4_FLOW 0x01 /* hash or spec (tcp_ip4_spec) */ -#define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ -#define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ -#define AH_ESP_V4_FLOW 0x04 /* hash only */ -#define TCP_V6_FLOW 0x05 /* hash only */ -#define UDP_V6_FLOW 0x06 /* hash only */ -#define SCTP_V6_FLOW 0x07 /* hash only */ -#define AH_ESP_V6_FLOW 0x08 /* hash only */ -#define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ -#define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ -#define AH_V6_FLOW 0x0b /* hash only */ -#define ESP_V6_FLOW 0x0c /* hash only */ -#define IP_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ -#define IPV4_FLOW 0x10 /* hash only */ -#define IPV6_FLOW 0x11 /* hash only */ -#define ETHER_FLOW 0x12 /* spec only (ether_spec) */ -/* Flag to enable additional fields in struct ethtool_rx_flow_spec */ -#define FLOW_EXT 0x80000000 -#define FLOW_MAC_EXT 0x40000000 - -/* L3-L4 network traffic flow hash options */ -#define RXH_L2DA (1 << 1) -#define RXH_VLAN (1 << 2) -#define RXH_L3_PROTO (1 << 3) -#define RXH_IP_SRC (1 << 4) -#define RXH_IP_DST (1 << 5) -#define RXH_L4_B_0_1 (1 << 6) /* src port in case of TCP/UDP/SCTP */ -#define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ -#define RXH_DISCARD (1 << 31) - -#define RX_CLS_FLOW_DISC 0xffffffffffffffffULL - -/* Special RX classification rule insert location values */ -#define RX_CLS_LOC_SPECIAL 0x80000000 /* flag */ -#define RX_CLS_LOC_ANY 0xffffffff -#define RX_CLS_LOC_FIRST 0xfffffffe -#define RX_CLS_LOC_LAST 0xfffffffd - -/* EEPROM Standards for plug in modules */ -#define ETH_MODULE_SFF_8079 0x1 -#define ETH_MODULE_SFF_8079_LEN 256 -#define ETH_MODULE_SFF_8472 0x2 -#define ETH_MODULE_SFF_8472_LEN 512 - -/* Reset flags */ -/* The reset() operation must clear the flags for the components which - * were actually reset. On successful return, the flags indicate the - * components which were not reset, either because they do not exist - * in the hardware or because they cannot be reset independently. The - * driver must never reset any components that were not requested. - */ -enum ethtool_reset_flags { - /* These flags represent components dedicated to the interface - * the command is addressed to. Shift any flag left by - * ETH_RESET_SHARED_SHIFT to reset a shared component of the - * same type. - */ - ETH_RESET_MGMT = 1 << 0, /* Management processor */ - ETH_RESET_IRQ = 1 << 1, /* Interrupt requester */ - ETH_RESET_DMA = 1 << 2, /* DMA engine */ - ETH_RESET_FILTER = 1 << 3, /* Filtering/flow direction */ - ETH_RESET_OFFLOAD = 1 << 4, /* Protocol offload */ - ETH_RESET_MAC = 1 << 5, /* Media access controller */ - ETH_RESET_PHY = 1 << 6, /* Transceiver/PHY */ - ETH_RESET_RAM = 1 << 7, /* RAM shared between - * multiple components */ - - ETH_RESET_DEDICATED = 0x0000ffff, /* All components dedicated to - * this interface */ - ETH_RESET_ALL = 0xffffffff, /* All components used by this - * interface, even if shared */ -}; -#define ETH_RESET_SHARED_SHIFT 16 - -#endif /* _LINUX_ETHTOOL_H */ diff --git a/quectel_cm_5G/src/log/cdc_mbim.txt b/quectel_cm_5G/src/log/cdc_mbim.txt deleted file mode 100644 index 8acdfde..0000000 --- a/quectel_cm_5G/src/log/cdc_mbim.txt +++ /dev/null @@ -1,71 +0,0 @@ -root@ZhuoTK:/# dmesg -[ 788.920000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform -[ 789.160000] cdc_mbim 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 789.170000] cdc_mbim 1-1.3:1.4 wwan0: register 'cdc_mbim' at usb-101c0000.ehci-1.3, CDC MBIM, a2:58:dc:4d:dd:ca - -root@ZhuoTK:/# quectel-CM -s cmnet & -[04-13_05:24:38:767] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:24:38:769] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 -[04-13_05:24:38:771] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_05:24:38:771] Auto find usbnet_adapter = wwan0 -[04-13_05:24:38:771] netcard driver = cdc_mbim, driver version = 22-Aug-2005 -[04-13_05:24:38:771] Modem works in MBIM mode -[04-13_05:24:38:779] cdc_wdm_fd = 7 -[04-13_05:24:38:779] mbim_open_device() -[04-13_05:24:39:624] mbim_device_caps_query() -[04-13_05:24:39:656] DeviceId: 866758045439136 -[04-13_05:24:39:656] FirmwareInfo: EC25EFAR06A11M4G -[04-13_05:24:39:656] HardwareInfo: QUECTEL Mobile Broadband Modul -[04-13_05:24:39:657] mbim_device_services_query() -[04-13_05:24:39:688] mbim_set_radio_state( 1 ) -[04-13_05:24:39:721] HwRadioState: 1, SwRadioState: 1 -[04-13_05:24:39:721] mbim_subscriber_status_query() -[04-13_05:24:39:784] SubscriberId: 460028563800461 -[04-13_05:24:39:784] SimIccId: 89860015120716380461 -[04-13_05:24:39:785] SubscriberReadyState NotInitialized -> Initialized -[04-13_05:24:39:785] mbim_register_state_query() -[04-13_05:24:39:816] RegisterState Unknown -> Home -[04-13_05:24:39:816] mbim_packet_service_query() -[04-13_05:24:39:848] PacketServiceState Unknown -> Attached -[04-13_05:24:39:848] mbim_query_connect(sessionID=0) -[04-13_05:24:39:880] ActivationState Unknown -> Deactivated -[04-13_05:24:39:881] ifconfig wwan0 0.0.0.0 -[04-13_05:24:39:899] ifconfig wwan0 down -[04-13_05:24:39:913] mbim_set_connect(onoff=1, sessionID=0) -[04-13_05:24:39:976] ActivationState Deactivated -> Activated -[04-13_05:24:39:977] mbim_ip_config(sessionID=0) -[04-13_05:24:40:008] < SessionId = 0 -[04-13_05:24:40:008] < IPv4ConfigurationAvailable = 0xf -[04-13_05:24:40:008] < IPv6ConfigurationAvailable = 0x0 -[04-13_05:24:40:008] < IPv4AddressCount = 0x1 -[04-13_05:24:40:008] < IPv4AddressOffset = 0x3c -[04-13_05:24:40:009] < IPv6AddressCount = 0x0 -[04-13_05:24:40:009] < IPv6AddressOffset = 0x0 -[04-13_05:24:40:009] < IPv4 = 10.129.90.29/30 -[04-13_05:24:40:009] < gw = 10.129.90.30 -[04-13_05:24:40:009] < dns1 = 211.138.180.2 -[04-13_05:24:40:009 < dns2 = 211.138.180.3 -[04-13_05:24:40:009] < ipv4 mtu = 1500 -[04-13_05:24:40:041] ifconfig wwan0 up -[04-13_05:24:40:063] ip -4 address flush dev wwan0 -[04-13_05:24:40:073] ip -4 address add 10.129.90.29/30 dev wwan0 -[04-13_05:24:40:084] ip -4 route add default via 10.129.90.30 dev wwan0 - -root@ZhuoTK:/# ifconfig wwan0 -wwan0 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA - inet addr:10.129.90.29 Bcast:0.0.0.0 Mask:255.255.255.252 - inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link - UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1 - RX packets:0 errors:0 dropped:0 overruns:0 frame:0 - TX packets:5 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:0 (0.0 B) TX bytes:380 (380.0 B) - -root@ZhuoTK:/# ip ro show -default via 10.129.90.30 dev wwan0 -10.129.90.28/30 dev wwan0 proto kernel scope link src 10.129.90.29 -192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 - -root@ZhuoTK:/# ping www.qq.com -PING www.qq.com (183.194.238.117): 56 data bytes -64 bytes from 183.194.238.117: seq=0 ttl=53 time=58.674 ms \ No newline at end of file diff --git a/quectel_cm_5G/src/log/cdc_mbim_vlan.txt b/quectel_cm_5G/src/log/cdc_mbim_vlan.txt deleted file mode 100644 index 79e15a4..0000000 --- a/quectel_cm_5G/src/log/cdc_mbim_vlan.txt +++ /dev/null @@ -1,168 +0,0 @@ -root@ZhuoTK:/# dmesg -[ 788.920000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform -[ 789.160000] cdc_mbim 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 789.170000] cdc_mbim 1-1.3:1.4 wwan0: register 'cdc_mbim' at usb-101c0000.ehci-1.3, CDC MBIM, a2:58:dc:4d:dd:ca - -root@ZhuoTK:/# ip link add link wwan0 name wwan0.1 type vlan id 1 -root@ZhuoTK:/# ip link add link wwan0 name wwan0.2 type vlan id 2 -root@ZhuoTK:/# ifconfig wwan0.1 -wwan0.1 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA - BROADCAST NOARP MULTICAST MTU:1500 Metric:1 - RX packets:0 errors:0 dropped:0 overruns:0 frame:0 - TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) - -root@ZhuoTK:/# ifconfig wwan0.2 -wwan0.2 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA - BROADCAST NOARP MULTICAST MTU:1500 Metric:1 - RX packets:0 errors:0 dropped:0 overruns:0 frame:0 - TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) - -root@ZhuoTK:/# quectel-mbim-proxy & -root@ZhuoTK:/# [04-13_07:04:27:543] mbim_dev_fd=3 -[04-13_07:04:27:543] mbim_send_open_msg() -[04-13_07:04:28:321] receive MBIM_OPEN_DONE, status=0 -[04-13_07:04:28:321] mbim_server_fd=4 - -root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & -[04-13_07:04:34:256] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_07:04:34:259] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 -[04-13_07:04:34:260] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_07:04:34:260] Auto find usbnet_adapter = wwan0 -[04-13_07:04:34:260] netcard driver = cdc_mbim, driver version = 22-Aug-2005 -[04-13_07:04:34:261] mbim_qmap_mode = 4, vlan_id = 0x01, qmap_netcard = wwan0.1 -[04-13_07:04:34:261] Modem works in MBIM mode -[04-13_07:04:34:261] handle_client_connect client_fd=5, client_idx=1 -[04-13_07:04:34:262] connect to quectel-mbim-proxy sockfd = 7 -[04-13_07:04:34:262] cdc_wdm_fd = 7 -[04-13_07:04:34:262] mbim_open_device() -[04-13_07:04:35:106] mbim_device_caps_query() -[04-13_07:04:35:139] DeviceId: 866758045439136 -[04-13_07:04:35:139] FirmwareInfo: EC25EFAR06A11M4G -[04-13_07:04:35:139] HardwareInfo: QUECTEL Mobile Broadband Modul -[04-13_07:04:35:139] mbim_device_services_query() -[04-13_07:04:35:170] mbim_set_radio_state( 1 ) -[04-13_07:04:35:202] HwRadioState: 1, SwRadioState: 1 -[04-13_07:04:35:202] mbim_subscriber_status_query() -[04-13_07:04:35:267] SubscriberId: 460028563800461 -[04-13_07:04:35:267] SimIccId: 89860015120716380461 -[04-13_07:04:35:267] SubscriberReadyState NotInitialized -> Initialized -[04-13_07:04:35:267] mbim_register_state_query() -[04-13_07:04:35:297] RegisterState Unknown -> Home -[04-13_07:04:35:298] mbim_packet_service_query() -[04-13_07:04:35:329] PacketServiceState Unknown -> Attached -[04-13_07:04:35:330] mbim_query_connect(sessionID=1) -[04-13_07:04:35:361] ActivationState Unknown -> Deactivated -[04-13_07:04:35:362] ifconfig wwan0.1 0.0.0.0 -[04-13_07:04:35:373] ifconfig wwan0.1 down -[04-13_07:04:35:383] mbim_set_connect(onoff=1, sessionID=1) -[04-13_07:04:35:426] ActivationState Deactivated -> Activated -[04-13_07:04:35:426] mbim_ip_config(sessionID=1) -[04-13_07:04:35:457] < SessionId = 1 -[04-13_07:04:35:457] < IPv4ConfigurationAvailable = 0xf -[04-13_07:04:35:457] < IPv6ConfigurationAvailable = 0x0 -[04-13_07:04:35:457] < IPv4AddressCount = 0x1 -[04-13_07:04:35:458] < IPv4AddressOffset = 0x3c -[04-13_07:04:35:458] < IPv6AddressCount = 0x0 -[04-13_07:04:35:458] < IPv6AddressOffset = 0x0 -[04-13_07:04:35:458] < IPv4 = 10.129.90.29/30 -[04-13_07:04:35:458] < gw = 10.129.90.30 -[04-13_07:04:35:458] < dns1 = 211.138.180.2 -[04-13_07:04:35:458] < dns2 = 211.138.180.3 -[04-13_07:04:35:458] < ipv4 mtu = 1500 -[04-13_07:04:35:489] ifconfig wwan0 up -[04-13_07:04:35:509] ifconfig wwan0.1 down -[04-13_07:04:35:522] ifconfig wwan0.1 up -[04-13_07:04:35:535] ip -4 address flush dev wwan0.1 -[04-13_07:04:35:545] ip -4 address add 10.129.90.29/30 dev wwan0.1 -[04-13_07:04:35:556] ip -4 route add default via 10.129.90.30 dev wwan0.1 - -root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & -[04-13_07:04:45:150] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_07:04:45:152] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 -[04-13_07:04:45:154] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_07:04:45:154] Auto find usbnet_adapter = wwan0 -[04-13_07:04:45:154] netcard driver = cdc_mbim, driver version = 22-Aug-2005 -[04-13_07:04:45:155] mbim_qmap_mode = 4, vlan_id = 0x02, qmap_netcard = wwan0.2 -[04-13_07:04:45:155] Modem works in MBIM mode -[04-13_07:04:45:155] handle_client_connect client_fd=6, client_idx=2 -[04-13_07:04:45:156] connect to quectel-mbim-proxy sockfd = 7 -[04-13_07:04:45:156] cdc_wdm_fd = 7 -[04-13_07:04:45:156] mbim_open_device() -[04-13_07:04:46:025] mbim_device_caps_query() -[04-13_07:04:46:056] DeviceId: 866758045439136 -[04-13_07:04:46:056] FirmwareInfo: EC25EFAR06A11M4G -[04-13_07:04:46:056] HardwareInfo: QUECTEL Mobile Broadband Modul -[04-13_07:04:46:056] mbim_device_services_query() -[04-13_07:04:46:088] mbim_set_radio_state( 1 ) -[04-13_07:04:46:119] HwRadioState: 1, SwRadioState: 1 -[04-13_07:04:46:119] mbim_subscriber_status_query() -[04-13_07:04:46:183] SubscriberId: 460028563800461 -[04-13_07:04:46:184] SimIccId: 89860015120716380461 -[04-13_07:04:46:184] SubscriberReadyState NotInitialized -> Initialized -[04-13_07:04:46:184] mbim_register_state_query() -[04-13_07:04:46:216] RegisterState Unknown -> Home -[04-13_07:04:46:216] mbim_packet_service_query() -[04-13_07:04:46:248] PacketServiceState Unknown -> Attached -[04-13_07:04:46:248] mbim_query_connect(sessionID=2) -[04-13_07:04:46:280] ActivationState Unknown -> Deactivated -[04-13_07:04:46:280] ifconfig wwan0.2 0.0.0.0 -[04-13_07:04:46:291] ifconfig wwan0.2 down -[04-13_07:04:46:304] mbim_set_connect(onoff=1, sessionID=2) -[04-13_07:04:46:504] ActivationState Deactivated -> Activated -[04-13_07:04:46:505] mbim_ip_config(sessionID=2) -[04-13_07:04:46:537] < SessionId = 2 -[04-13_07:04:46:537] < IPv4ConfigurationAvailable = 0xf -[04-13_07:04:46:537] < IPv6ConfigurationAvailable = 0x0 -[04-13_07:04:46:538] < IPv4AddressCount = 0x1 -[04-13_07:04:46:538] < IPv4AddressOffset = 0x3c -[04-13_07:04:46:538] < IPv6AddressCount = 0x0 -[04-13_07:04:46:538] < IPv6AddressOffset = 0x0 -[04-13_07:04:46:538] < IPv4 = 10.129.37.205/30 -[04-13_07:04:46:538] < gw = 10.129.37.206 -[04-13_07:04:46:538] < dns1 = 211.138.180.2 -[04-13_07:04:46:538] < dns2 = 211.138.180.3 -[04-13_07:04:46:538] < ipv4 mtu = 1500 -[04-13_07:04:46:569] ifconfig wwan0 up -[04-13_07:04:46:579] ifconfig wwan0.2 up -[04-13_07:04:46:592] ip -4 address flush dev wwan0.2 -[04-13_07:04:46:602] ip -4 address add 10.129.37.205/30 dev wwan0.2 -[04-13_07:04:46:613] ip -4 route add default via 10.129.37.206 dev wwan0.2 - -root@ZhuoTK:/# ifconfig wwan0.1 -wwan0.1 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA - inet addr:10.129.90.29 Bcast:0.0.0.0 Mask:255.255.255.252 - inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link - UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1 - RX packets:4 errors:0 dropped:0 overruns:0 frame:0 - TX packets:13 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:304 (304.0 B) TX bytes:1170 (1.1 KiB) - -root@ZhuoTK:/# ifconfig wwan0.2 -wwan0.2 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA - inet addr:10.129.37.205 Bcast:0.0.0.0 Mask:255.255.255.252 - inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link - UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1 - RX packets:0 errors:0 dropped:0 overruns:0 frame:0 - TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:0 - RX bytes:0 (0.0 B) TX bytes:720 (720.0 B) - -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process -root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0.1 -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=98.584 ms - -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process -root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0.2 -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=111 time=101.770 ms \ No newline at end of file diff --git a/quectel_cm_5G/src/log/ecm_ncm_rndis.txt b/quectel_cm_5G/src/log/ecm_ncm_rndis.txt deleted file mode 100644 index 2ae7e6b..0000000 --- a/quectel_cm_5G/src/log/ecm_ncm_rndis.txt +++ /dev/null @@ -1,129 +0,0 @@ -# ./quectel-CM -s cmnet & -[04-21_17:35:14:362] Quectel_QConnectManager_Linux_V1.6.0.26 -[04-21_17:35:14:363] Find /sys/bus/usb/devices/2-4 idVendor=0x2c7c idProduct=0x8101, bus=0x002, dev=0x016 -[04-21_17:35:14:363] Auto find qmichannel = /dev/ttyUSB0 -[04-21_17:35:14:363] Auto find usbnet_adapter = usb0 -[04-21_17:35:14:363] netcard driver = cdc_ncm, driver version = 22-Aug-2005 -[04-21_17:35:14:363] Modem works in ECM_RNDIS_NCM mode -[04-21_17:35:14:371] atc_fd = 7 -[04-21_17:35:14:371] AT> ATE0Q0V1 -[04-21_17:35:14:372] AT< RDATE0Q0V1 -[04-21_17:35:14:372] AT< COMMAND NOT SUPPORT -[04-21_17:35:15:373] AT> AT+QCFG="usbnet" -[04-21_17:35:15:373] AT< +QCFG: "usbnet",5 -[04-21_17:35:15:373] AT< OK -[04-21_17:35:15:373] AT> AT+QNETDEVCTL=? -[04-21_17:35:15:374] AT< +QNETDEVCTL: (1-11),(0,1),(0,1) -[04-21_17:35:15:374] AT< OK -[04-21_17:35:15:374] AT> AT+CGREG=2 -[04-21_17:35:15:376] AT< OK -[04-21_17:35:15:376] AT> AT+CEREG=2 -[04-21_17:35:15:381] AT< OK -[04-21_17:35:15:381] AT> AT+C5GREG=2 -[04-21_17:35:15:384] AT< OK -[04-21_17:35:15:384] AT> AT+QNETDEVSTATUS=? -[04-21_17:35:15:385] AT< +QNETDEVSTATUS: (1-11) -[04-21_17:35:15:385] AT< OK -[04-21_17:35:15:385] AT> AT+QCFG="NAT" -[04-21_17:35:15:385] AT< +QCFG: "nat",0 -[04-21_17:35:15:385] AT< OK -[04-21_17:35:15:385] AT> AT+CGMR -[04-21_17:35:15:386] AT< RG801HEAAAR03A01M8G -[04-21_17:35:15:386] AT< OK -[04-21_17:35:15:386] AT> AT+CPIN? -[04-21_17:35:15:388] AT< +CPIN: READY -[04-21_17:35:15:388] AT< OK -[04-21_17:35:15:389] AT> AT+QCCID -[04-21_17:35:15:393] AT< +QCCID: 89860015120716380461 -[04-21_17:35:15:393] AT< OK -[04-21_17:35:15:393] requestGetICCID 89860015120716380461 -[04-21_17:35:15:393] AT> AT+CIMI -[04-21_17:35:15:409] AT< 460028563800461 -[04-21_17:35:15:409] AT< OK -[04-21_17:35:15:409] requestGetIMSI 460028563800461 -[04-21_17:35:15:409] AT> AT+QICSGP=1 -[04-21_17:35:15:411] AT< +QICSGP: 1,1,"cment","","",0,,0, -[04-21_17:35:15:411] AT< OK -[04-21_17:35:15:411] AT> AT+QICSGP=1 -[04-21_17:35:15:415] AT< +QICSGP: 1,1,"cment","","",0,,0, -[04-21_17:35:15:415] AT< OK -[04-21_17:35:15:415] AT> AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS? -[04-21_17:35:15:421] AT< +COPS: 0,0,"CHINA MOBILE",12 -[04-21_17:35:15:421] AT< +COPS: 0,1,"CMCC",12 -[04-21_17:35:15:421] AT< +COPS: 0,2,"46000",12 -[04-21_17:35:15:421] AT< OK -[04-21_17:35:15:421] AT> AT+C5GREG? -[04-21_17:35:15:424] AT< +C5GREG: 2,1,"46550B","0000000170C23000",11,1,"01" -[04-21_17:35:15:424] AT< OK -[04-21_17:35:15:424] AT> at+cops? -[04-21_17:35:15:427] AT< +COPS: 0,2,"46000",12 -[04-21_17:35:15:427] AT< OK -[04-21_17:35:15:427] AT> at+qeng="servingcell" -[04-21_17:35:15:441] AT< +QENG: "servingcell","NOCONN","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-54,-10,16,-,- -[04-21_17:35:15:441] AT< OK -[04-21_17:35:15:441] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:15:445] AT< ERROR -[04-21_17:35:15:445] ifconfig usb0 0.0.0.0 -[04-21_17:35:15:446] ifconfig usb0 down -[04-21_17:35:15:448] AT> AT+QNETDEVCTL=1,1,0 -[04-21_17:35:15:454] AT< OK -[04-21_17:35:15:456] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:15:458] AT< ERROR -[04-21_17:35:15:989] AT< +QNETDEVSTATUS:1,1,"IPV4" -[04-21_17:35:16:459] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:16:461] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 -[04-21_17:35:16:461] AT< OK -[04-21_17:35:16:461] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:16:462] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 -[04-21_17:35:16:462] AT< OK -[04-21_17:35:16:462] requestGetIPAddress 10.25.16.79 -[04-21_17:35:16:462] AT> at+cops? -[04-21_17:35:16:463] AT< +COPS: 0,2,"46000",12 -[04-21_17:35:16:463] AT< OK -[04-21_17:35:16:463] AT> at+qeng="servingcell" -[04-21_17:35:16:465] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-52,-11,15,-,- -[04-21_17:35:16:465] AT< OK -[04-21_17:35:16:465] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:16:466] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 -[04-21_17:35:16:466] AT< OK -[04-21_17:35:16:466] ifconfig usb0 up -[04-21_17:35:16:470] busybox udhcpc -f -n -q -t 5 -i usb0 -udhcpc: started, v1.30.1 -udhcpc: sending discover -udhcpc: sending select for 10.25.16.79 -udhcpc: lease of 10.25.16.79 obtained, lease time 518400 -[04-21_17:35:16:602] /etc/udhcpc/default.script: Resetting default routes -SIOCDELRT: No such process -SIOCADDRT: Network is unreachable -[04-21_17:35:16:606] /etc/udhcpc/default.script: Adding DNS 211.138.180.2 -[04-21_17:35:16:606] /etc/udhcpc/default.script: Adding DNS 211.138.180.3 -[04-21_17:35:16:655] AT> at+cops? -[04-21_17:35:16:656] AT< +COPS: 0,2,"46000",12 -[04-21_17:35:16:656] AT< OK -[04-21_17:35:16:656] AT> at+qeng="servingcell" -[04-21_17:35:16:657] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-50,-11,17,-,- -[04-21_17:35:16:658] AT< OK -err = 16 -[04-21_17:35:16:658] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:16:659] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 -[04-21_17:35:16:659] AT< OK - -root@carl-ThinkPad-X1-Carbon-7th:/home/carl/q/quectel-CM# ifconfig usb0 -usb0: flags=4163 mtu 1500 - inet 10.25.16.79 netmask 255.255.255.224 broadcast 10.25.16.95 - inet6 fe80::5c98:e9d4:c82d:5f prefixlen 64 scopeid 0x20 - ether 0c:5b:8f:27:9a:64 txqueuelen 1000 (Ethernet) - RX packets 7 bytes 1656 (1.6 KB) - RX errors 0 dropped 0 overruns 0 frame 0 - TX packets 32 bytes 5112 (5.1 KB) - TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 - -root@carl-ThinkPad-X1-Carbon-7th:/home/carl/q/quectel-CM# [04-21_17:35:31:670] AT> at+cops? -[04-21_17:35:31:671] AT< +COPS: 0,2,"46000",12 -[04-21_17:35:31:671] AT< OK -[04-21_17:35:31:671] AT> at+qeng="servingcell" -[04-21_17:35:31:673] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-48,-10,17,-,- -[04-21_17:35:31:673] AT< OK -[04-21_17:35:31:673] AT> AT+QNETDEVSTATUS=1 -[04-21_17:35:31:674] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 -[04-21_17:35:31:674] AT< OK diff --git a/quectel_cm_5G/src/log/gobinet.txt b/quectel_cm_5G/src/log/gobinet.txt deleted file mode 100644 index 2b286de..0000000 --- a/quectel_cm_5G/src/log/gobinet.txt +++ /dev/null @@ -1,62 +0,0 @@ -root@ZhuoTK:/# dmesg -[ 230.590000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 -[ 230.600000] creating qcqmi0 - -root@ZhuoTK:/# quectel-CM -s cmnet & -[04-13_03:24:58:213] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:24:58:216] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 -[04-13_03:24:58:218] Auto find qmichannel = /dev/qcqmi0 -[04-13_03:24:58:218] Auto find usbnet_adapter = usb0 -[04-13_03:24:58:218] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_03:24:58:219] Modem works in QMI mode -[04-13_03:24:58:260] Get clientWDS = 7 -[04-13_03:24:58:292] Get clientDMS = 8 -[04-13_03:24:58:324] Get clientNAS = 9 -[04-13_03:24:58:355] Get clientUIM = 10 -[04-13_03:24:58:388] Get clientWDA = 11 -[04-13_03:24:58:420] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:24:58:548] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:24:58:549] requestSetProfile[1] cmnet///0 -[04-13_03:24:58:613] requestGetProfile[1] cmnet///0 -[04-13_03:24:58:645] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:24:58:677] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_03:24:58:677] ifconfig usb0 0.0.0.0 -[04-13_03:24:58:696] ifconfig usb0 down -[04-13_03:24:59:028] requestSetupDataCall WdsConnectionIPv4Handle: 0x87245bd0 -[04-13_03:24:59:189] ifconfig usb0 up -[04-13_03:24:59:214] you are use OpenWrt? -[04-13_03:24:59:215] should not calling udhcpc manually? -[04-13_03:24:59:215] should modify /etc/config/network as below? -[04-13_03:24:59:215] config interface wan -[04-13_03:24:59:215] option ifname usb0 -[04-13_03:24:59:215] option proto dhcp -[04-13_03:24:59:215] should use "/sbin/ifstaus wan" to check usb0 's status? -[04-13_03:24:59:216] busybox udhcpc -f -n -q -t 5 -i usb0 -[04-13_03:24:59:226] udhcpc (v1.23.2) started -[04-13_03:24:59:238] Sending discover... -[04-13_03:24:59:248] Sending select for 10.198.78.154... -[04-13_03:24:59:251] Lease of 10.198.78.154 obtained, lease time 7200 -[04-13_03:24:59:257] udhcpc: ifconfig usb0 10.198.78.154 netmask 255.255.255.252 broadcast + -[04-13_03:24:59:266] udhcpc: setting default routers: 10.198.78.153 - -root@ZhuoTK:/# ifconfig usb0 -usb0 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.198.78.154 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:6 errors:0 dropped:0 overruns:0 frame:0 - TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:916 (916.0 B) TX bytes:960 (960.0 B) - -root@ZhuoTK:/# ip ro show -default via 10.198.78.153 dev usb0 -10.198.78.152/30 dev usb0 proto kernel scope link src 10.198.78.154 -192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 - -root@ZhuoTK:/# killall quectel-CM -[04-13_03:25:38:779] requestDeactivateDefaultPDP WdsConnectionIPv4Handle -[04-13_03:25:39:061] ifconfig usb0 0.0.0.0 -[04-13_03:25:39:072] ifconfig usb0 down -[04-13_03:25:39:284] GobiNetThread exit -[04-13_03:25:39:285] qmi_main exit diff --git a/quectel_cm_5G/src/log/gobinet_bridge.txt b/quectel_cm_5G/src/log/gobinet_bridge.txt deleted file mode 100644 index 7ed229e..0000000 --- a/quectel_cm_5G/src/log/gobinet_bridge.txt +++ /dev/null @@ -1,60 +0,0 @@ -root@ZhuoTK:/# insmod GobiNet.ko -[ 80.460000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 -[ 80.460000] usbcore: registered new interface driver GobiNet -[ 97.710000] usb 1-1.3: new high-speed USB device number 3 using ehci-platform -[ 97.930000] usb 1-1.3: GSM modem (1-port) converter now attached to ttyUSB103 -[ 97.950000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 -[ 97.960000] creating qcqmi0 - -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 -root@ZhuoTK:/# brctl addif br0 usb0 -root@ZhuoTK:/# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00ca019197b9 no eth0.1 - usb0 - -root@ZhuoTK:/# quectel-CM -s cment -b & -[04-13_05:13:18:213] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:13:18:216] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[ 122.270000] net usb0: bridge_mode change to 0x1 -[04-13_05:13:18:218] Auto find qmichannel = /dev/qcqmi0 -[04-13_05:13:18:218] Auto find usbnet_adapter = usb0 -[04-13_05:13:18:218] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_05:13:18:224] Modem works in QMI mode -[04-13_05:13:18:251] Get clientWDS = 7 -[04-13_05:13:18:282] Get clientDMS = 8 -[04-13_05:13:18:316] Get clientNAS = 9 -[04-13_05:13:18:347] Get clientUIM = 10 -[04-13_05:13:18:379] Get clientWDA = 11 -[04-13_05:13:18:411] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:13:18:539] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:13:18:540] requestSetProfile[1] cment///0 -[04-13_05:13:18:603] requestGetProfile[1] cment///0 -[04-13_05:13:18:637] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:13:18:666] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:13:18:667] ifconfig usb0 0.0.0.0 -[04-13_05:13:18:687] ifconfig usb0 down -[04-13_05:13:19:083] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d220 -[04-13_05:13:19:243] ifconfig usb0 up -[04-13_05:13:19:270] echo '0xa218480' > /sys/class/net/usb0/bridge_ipv4 - -root@ZhuoTK:/# ifconfig br0 up -[ 135.530000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 135.570000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 135.580000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 135.610000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 135.620000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 135.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128 -[ 136.000000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 136.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128 -[ 137.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128 -[ 138.740000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 138.910000] usb0 sip = 10.33.132.128, tip=10.33.132.128, ipv4=10.33.132.128 -[ 139.000000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 140.860000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 143.160000] br0: port 2(usb0) entered forwarding state -[ 143.160000] br0: port 1(eth0.1) entered forwarding state -[ 148.870000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 149.010000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 -[ 165.630000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 diff --git a/quectel_cm_5G/src/log/gobinet_qmap=1.txt b/quectel_cm_5G/src/log/gobinet_qmap=1.txt deleted file mode 100644 index 83cedd9..0000000 --- a/quectel_cm_5G/src/log/gobinet_qmap=1.txt +++ /dev/null @@ -1,45 +0,0 @@ -root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=1 -[ 798.480000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 -[ 798.490000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 -[ 798.510000] creating qcqmi0 -[ 798.510000] usbcore: registered new interface driver GobiNet -[ 799.620000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 -[ 799.630000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 - -root@ZhuoTK:/# quectel-CM -s cmnet & -[04-13_03:32:31:248] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:32:31:251] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x005 -[04-13_03:32:31:253] Auto find qmichannel = /dev/qcqmi0 -[04-13_03:32:31:253] Auto find usbnet_adapter = usb0 -[04-13_03:32:31:253] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_03:32:31:253] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0 -[04-13_03:32:31:254] Modem works in QMI mode -[04-13_03:32:31:289] Get clientWDS = 7 -[04-13_03:32:31:320] Get clientDMS = 8 -[04-13_03:32:31:353] Get clientNAS = 9 -[04-13_03:32:31:385] Get clientUIM = 10 -[04-13_03:32:31:417] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:32:31:545] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:32:31:545] requestSetProfile[1] cmnet///0 -[04-13_03:32:31:609] requestGetProfile[1] cmnet///0 -[04-13_03:32:31:641] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:32:31:673] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_03:32:31:674] ifconfig usb0 0.0.0.0 -[04-13_03:32:31:698] ifconfig usb0 down -[04-13_03:32:31:770] requestSetupDataCall WdsConnectionIPv4Handle: 0x872481a0 -[ 857.000000] net usb0: link_state 0x0 -> 0x1 -[04-13_03:32:31:902] ifconfig usb0 up -[04-13_03:32:31:928] you are use OpenWrt? -[04-13_03:32:31:928] should not calling udhcpc manually? -[04-13_03:32:31:928] should modify /etc/config/network as below? -[04-13_03:32:31:928] config interface wan -[04-13_03:32:31:928] option ifname usb0 -[04-13_03:32:31:929] option proto dhcp -[04-13_03:32:31:929] should use "/sbin/ifstaus wan" to check usb0 's status? -[04-13_03:32:31:929] busybox udhcpc -f -n -q -t 5 -i usb0 -[04-13_03:32:31:939] udhcpc (v1.23.2) started -[04-13_03:32:31:951] Sending discover... -[04-13_03:32:31:956] Sending select for 10.199.102.71... -[04-13_03:32:31:959] Lease of 10.199.102.71 obtained, lease time 7200 -[04-13_03:32:31:964] udhcpc: ifconfig usb0 10.199.102.71 netmask 255.255.255.240 broadcast + -[04-13_03:32:31:974] udhcpc: setting default routers: 10.199.102.72 diff --git a/quectel_cm_5G/src/log/gobinet_qmap=1_bridge.txt b/quectel_cm_5G/src/log/gobinet_qmap=1_bridge.txt deleted file mode 100644 index 64a8374..0000000 --- a/quectel_cm_5G/src/log/gobinet_qmap=1_bridge.txt +++ /dev/null @@ -1,62 +0,0 @@ -root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=1 -[ 41.540000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 -[ 41.550000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 -[ 41.570000] creating qcqmi0 -[ 41.570000] usbcore: registered new interface driver GobiNet -[ 42.700000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 -[ 42.710000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 - -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 -root@ZhuoTK:/# brctl addif br0 usb0 -root@ZhuoTK:/# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00ca019197b9 no eth0.1 - usb0 - -root@ZhuoTK:/# quectel-CM -s cmnet -b & -# [04-13_05:12:29:338] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:12:29:340] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[ 73.380000] net usb0: bridge_mode change to 0x1 -[04-13_05:12:29:342] Auto find qmichannel = /dev/qcqmi0 -[04-13_05:12:29:342] Auto find usbnet_adapter = usb0 -[04-13_05:12:29:342] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_05:12:29:343] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0 -[04-13_05:12:29:348] Modem works in QMI mode -[04-13_05:12:29:382] Get clientWDS = 7 -[04-13_05:12:29:414] Get clientDMS = 8 -[04-13_05:12:29:447] Get clientNAS = 9 -[04-13_05:12:29:479] Get clientUIM = 10 -[04-13_05:12:29:512] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:12:29:640] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:12:29:640] requestSetProfile[1] cmnet///0 -[04-13_05:12:29:704] requestGetProfile[1] cmnet///0 -[04-13_05:12:29:735] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:12:29:767] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:12:29:768] ifconfig usb0 0.0.0.0 -[04-13_05:12:29:792] ifconfig usb0 down -[04-13_05:12:29:863] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d820 -[ 74.030000] net usb0: link_state 0x0 -> 0x1 -[04-13_05:12:29:996] ifconfig usb0 up -[04-13_05:12:30:022] echo '0xa16b769' > /sys/class/net/usb0/bridge_ipv4 - -root@ZhuoTK:/# ifconfig br0 up -[ 82.210000] br0: port 2(usb0) entered forwarding state -[ 82.210000] br0: port 2(usb0) entered forwarding state -[ 82.220000] br0: port 1(eth0.1) entered forwarding state -[ 82.220000] br0: port 1(eth0.1) entered forwarding state -[ 88.830000] rt305x-esw 10110000.esw: link changed 0x01 -[ 89.010000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 89.040000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 89.050000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 89.120000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 -[ 89.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 -[ 89.400000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 -[ 89.520000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 -[ 90.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 -[ 91.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 -[ 92.350000] usb0 sip = 10.22.183.105, tip=10.22.183.105, ipv4=10.22.183.105 -[ 92.430000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 -[ 92.660000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 -[ 97.240000] br0: port 2(usb0) entered forwarding state -[ 97.240000] br0: port 1(eth0.1) entered forwarding state diff --git a/quectel_cm_5G/src/log/gobinet_qmap=4.txt b/quectel_cm_5G/src/log/gobinet_qmap=4.txt deleted file mode 100644 index 5ec02bf..0000000 --- a/quectel_cm_5G/src/log/gobinet_qmap=4.txt +++ /dev/null @@ -1,146 +0,0 @@ -root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=4 -[ 970.380000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 -[ 970.380000] usbcore: registered new interface driver GobiNet -[ 989.620000] usb 1-1.3: new high-speed USB device number 6 using ehci-platform -[ 989.860000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 -[ 989.870000] creating qcqmi0 -[ 989.880000] GobiNet::qmap_register_device usb0.1 -[ 989.880000] GobiNet::qmap_register_device usb0.2 -[ 989.890000] GobiNet::qmap_register_device usb0.3 -[ 989.890000] GobiNet::qmap_register_device usb0.4 -[ 994.820000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 -[ 994.830000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 - -root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & -[04-13_03:35:31:878] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:35:31:881] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x006 -[04-13_03:35:31:882] Auto find qmichannel = /dev/qcqmi0 -[04-13_03:35:31:882] Auto find usbnet_adapter = usb0 -[04-13_03:35:31:883] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_03:35:31:883] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0.1 -[04-13_03:35:31:883] Modem works in QMI mode -[04-13_03:35:31:896] Get clientWDS = 7 -[04-13_03:35:31:927] Get clientDMS = 8 -[04-13_03:35:31:959] Get clientNAS = 9 -[04-13_03:35:31:992] Get clientUIM = 10 -[04-13_03:35:32:024] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:35:32:152] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:35:32:152] requestSetProfile[1] cmnet///0 -[04-13_03:35:32:216] requestGetProfile[1] cmnet///0 -[04-13_03:35:32:248] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:35:32:279] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_03:35:32:280] ifconfig usb0 down -[04-13_03:35:32:290] ifconfig usb0.1 0.0.0.0 -[04-13_03:35:32:301] ifconfig usb0.1 down -[04-13_03:35:32:344] requestSetupDataCall WdsConnectionIPv4Handle: 0x8723eef0 -[ 1037.570000] net usb0: link_state 0x0 -> 0x1 -[04-13_03:35:32:477] ifconfig usb0 up -[04-13_03:35:32:496] ifconfig usb0.1 up -[04-13_03:35:32:508] you are use OpenWrt? -[04-13_03:35:32:509] should not calling udhcpc manually? -[04-13_03:35:32:509] should modify /etc/config/network as below? -[04-13_03:35:32:509] config interface wan -[04-13_03:35:32:509] option ifname usb0.1 -[04-13_03:35:32:509] option proto dhcp -[04-13_03:35:32:509] should use "/sbin/ifstaus wan" to check usb0.1 's status? -[04-13_03:35:32:510] busybox udhcpc -f -n -q -t 5 -i usb0.1 -[04-13_03:35:32:520] udhcpc (v1.23.2) started -[04-13_03:35:32:532] Sending discover... -[04-13_03:35:32:540] Sending select for 10.187.142.20... -[04-13_03:35:32:545] Lease of 10.187.142.20 obtained, lease time 7200 -[04-13_03:35:32:550] udhcpc: ifconfig usb0.1 10.187.142.20 netmask 255.255.255.248 broadcast + -[04-13_03:35:32:560] udhcpc: setting default routers: 10.187.142.21 - -root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & -[04-13_03:35:38:766] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:35:38:769] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x006 -[04-13_03:35:38:770] Auto find qmichannel = /dev/qcqmi0 -[04-13_03:35:38:770] Auto find usbnet_adapter = usb0 -[04-13_03:35:38:771] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_03:35:38:771] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = usb0.2 -[04-13_03:35:38:771] Modem works in QMI mode -[04-13_03:35:38:809] Get clientWDS = 7 -[04-13_03:35:38:841] Get clientDMS = 8 -[04-13_03:35:38:873] Get clientNAS = 9 -[04-13_03:35:38:905] Get clientUIM = 10 -[04-13_03:35:38:937] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:35:39:065] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:35:39:065] requestSetProfile[2] 4gnet///0 -[04-13_03:35:39:129] requestGetProfile[2] 4gnet///0 -[04-13_03:35:39:161] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:35:39:193] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_03:35:39:193] ifconfig usb0.2 0.0.0.0 -[04-13_03:35:39:206] ifconfig usb0.2 down -[04-13_03:35:39:417] requestSetupDataCall WdsConnectionIPv4Handle: 0x87252eb0 -[ 1044.650000] net usb0: link_state 0x1 -> 0x3 -[04-13_03:35:39:550] ifconfig usb0 up -[04-13_03:35:39:560] ifconfig usb0.2 up -[04-13_03:35:39:573] you are use OpenWrt? -[04-13_03:35:39:573] should not calling udhcpc manually? -[04-13_03:35:39:573] should modify /etc/config/network as below? -[04-13_03:35:39:573] config interface wan -[04-13_03:35:39:573] option ifname usb0.2 -[04-13_03:35:39:573] option proto dhcp -[04-13_03:35:39:573] should use "/sbin/ifstaus wan" to check usb0.2 's status? -[04-13_03:35:39:574] busybox udhcpc -f -n -q -t 5 -i usb0.2 -[04-13_03:35:39:585] udhcpc (v1.23.2) started -[04-13_03:35:39:597] Sending discover... -[04-13_03:35:39:601] Sending select for 10.197.125.183... -[04-13_03:35:39:606] Lease of 10.197.125.183 obtained, lease time 7200 -[04-13_03:35:39:611] udhcpc: ifconfig usb0.2 10.197.125.183 netmask 255.255.255.240 broadcast + -[04-13_03:35:39:621] udhcpc: setting default routers: 10.197.125.184 - -root@ZhuoTK:/# ifconfig usb0.1 -usb0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.187.142.20 Mask:255.255.255.248 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:4 errors:0 dropped:0 overruns:0 frame:0 - TX packets:10 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:764 (764.0 B) TX bytes:1824 (1.7 KiB) - -root@ZhuoTK:/# ifconfig usb0.2 -usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.197.125.183 Mask:255.255.255.240 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:3 errors:0 dropped:0 overruns:0 frame:0 - TX packets:9 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:688 (688.0 B) TX bytes:1224 (1.1 KiB) - -root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev usb0.1 -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=74.450 ms - -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process - -root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev usb0.2 -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=257.851 ms - -root@ZhuoTK:/# quectel-CM -k 2 -[04-13_03:39:16:986] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:39:16:988] /proc/2294/cmdline: quectel-CM -n 2 -s 4gnet -[04-13_03:39:16:988] send SIGINT to process 2294 -[04-13_03:39:16:989] requestDeactivateDefaultPDP WdsConnectionIPv4Handle -[ 1262.310000] net usb0: link_state 0x3 -> 0x1 -[04-13_03:39:17:216] ifconfig usb0.2 0.0.0.0 -[04-13_03:39:17:228] ifconfig usb0.2 down -[04-13_03:39:17:370] GobiNetThread exit -[04-13_03:39:17:371] qmi_main exit - -[2]+ Done quectel-CM -n 2 -s 4gnet - -root@ZhuoTK:/# ifconfig usb0.2 -usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - NOARP MTU:1500 Metric:1 - RX packets:30 errors:0 dropped:0 overruns:0 frame:0 - TX packets:35 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:2816 (2.7 KiB) TX bytes:3408 (3.3 KiB) diff --git a/quectel_cm_5G/src/log/gobinet_qmap=4_bridge.txt b/quectel_cm_5G/src/log/gobinet_qmap=4_bridge.txt deleted file mode 100644 index ebfd4fb..0000000 --- a/quectel_cm_5G/src/log/gobinet_qmap=4_bridge.txt +++ /dev/null @@ -1,114 +0,0 @@ -root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=4 -[ 42.120000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 -[ 42.130000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 -[ 42.140000] creating qcqmi0 -[ 42.150000] GobiNet::qmap_register_device usb0.1 -[ 42.150000] GobiNet::qmap_register_device usb0.2 -[ 42.160000] GobiNet::qmap_register_device usb0.3 -[ 42.160000] GobiNet::qmap_register_device usb0.4 -[ 42.170000] usbcore: registered new interface driver GobiNet -[ 43.270000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 -[ 43.280000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 - -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 -root@ZhuoTK:/# brctl addif br0 usb0.1 -root@ZhuoTK:/# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00ca019197b9 no eth0.1 - usb0.1 - -root@ZhuoTK:/# quectel-CM -n 1 -s cmnet -b & -[04-13_05:12:42:155] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:12:42:158] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[ 86.130000] net usb0.1: bridge_mode change to 0x1 -[04-13_05:12:42:159] Auto find qmichannel = /dev/qcqmi0 -[04-13_05:12:42:160] Auto find usbnet_adapter = usb0 -[04-13_05:12:42:160] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_05:12:42:160] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0.1 -[04-13_05:12:42:166] Modem works in QMI mode -[04-13_05:12:42:181] Get clientWDS = 7 -[04-13_05:12:42:213] Get clientDMS = 8 -[04-13_05:12:42:246] Get clientNAS = 9 -[04-13_05:12:42:278] Get clientUIM = 10 -[04-13_05:12:42:310] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:12:42:438] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:12:42:439] requestSetProfile[1] cmnet///0 -[04-13_05:12:42:502] requestGetProfile[1] cmnet///0 -[04-13_05:12:42:534] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:12:42:565] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:12:42:566] ifconfig usb0 down -[04-13_05:12:42:576] ifconfig usb0.1 0.0.0.0 -[04-13_05:12:42:587] ifconfig usb0.1 down -[04-13_05:12:42:629] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d740 -[ 86.730000] net usb0: link_state 0x0 -> 0x1 -[04-13_05:12:42:762] ifconfig usb0 up -[04-13_05:12:42:782] ifconfig usb0.1 up -[04-13_05:12:42:794] echo '0xa16b769' > /sys/class/net/usb0.1/bridge_ipv4 - -root@ZhuoTK:/# ifconfig br0 up -[ 98.270000] usb0.1 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 98.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 -[ 98.370000] usb0.1 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 -[ 99.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 -[ 100.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 -[ 100.500000] usb0.1 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 - -root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & -[04-13_05:13:05:715] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:13:05:717] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[04-13_05:13:05:719] Auto find qmichannel = /dev/qcqmi0 -[04-13_05:13:05:719] Auto find usbnet_adapter = usb0 -[04-13_05:13:05:719] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_05:13:05:719] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = usb0.2 -[04-13_05:13:05:720] Modem works in QMI mode -[04-13_05:13:05:734] Get clientWDS = 7 -[04-13_05:13:05:766] Get clientDMS = 8 -[04-13_05:13:05:798] Get clientNAS = 9 -[04-13_05:13:05:830] Get clientUIM = 10 -[04-13_05:13:05:861] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:13:05:990] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:13:05:991] requestSetProfile[2] 4gnet///0 -[04-13_05:13:06:054] requestGetProfile[2] 4gnet///0 -[04-13_05:13:06:086] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:13:06:118] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:13:06:119] ifconfig usb0.2 0.0.0.0 -[04-13_05:13:06:131] ifconfig usb0.2 down -[04-13_05:13:06:375] requestSetupDataCall WdsConnectionIPv4Handle: 0x872b8c50 -[ 110.470000] net usb0: link_state 0x1 -> 0x3 -[04-13_05:13:06:507] ifconfig usb0 up -[04-13_05:13:06:518] ifconfig usb0.2 up -[04-13_05:13:06:539] you are use OpenWrt? -[04-13_05:13:06:540] should not calling udhcpc manually? -[04-13_05:13:06:540] should modify /etc/config/network as below? -[04-13_05:13:06:540] config interface wan -[04-13_05:13:06:540] option ifname usb0.2 -[04-13_05:13:06:540] option proto dhcp -[04-13_05:13:06:540] should use "/sbin/ifstaus wan" to check usb0.2 's status? -[04-13_05:13:06:540] busybox udhcpc -f -n -q -t 5 -i usb0.2 -[04-13_05:13:06:554] udhcpc (v1.23.2) started -[04-13_05:13:06:614] Sending discover... -[04-13_05:13:06:619] Sending select for 10.22.58.141... -[04-13_05:13:06:623] Lease of 10.22.58.141 obtained, lease time 7200 -[04-13_05:13:06:629] udhcpc: ifconfig usb0.2 10.22.58.141 netmask 255.255.255.252 broadcast + -[04-13_05:13:06:638] udhcpc: setting default routers: 10.22.58.142 - -root@ZhuoTK:/# ifconfig usb0.2 -usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.22.58.141 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:612 (612.0 B) TX bytes:1064 (1.0 KiB) - -root@ZhuoTK:/# ip ro show -default via 10.22.58.142 dev usb0.2 -10.22.58.140/30 dev usb0.2 proto kernel scope link src 10.22.58.141 -192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 - -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=69.822 ms - diff --git a/quectel_cm_5G/src/log/pcie_mhi_mbim.txt b/quectel_cm_5G/src/log/pcie_mhi_mbim.txt deleted file mode 100644 index 7a988a9..0000000 --- a/quectel_cm_5G/src/log/pcie_mhi_mbim.txt +++ /dev/null @@ -1,80 +0,0 @@ -root@OpenWrt:/# lspci -00:00.0 Class 0604: 17cb:1001 -01:00.0 Class ff00: 17cb:0306 - -root@OpenWrt:/# insmod pcie_mhi.ko mhi_mbim_enabled=1 -[ 63.094154] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 -[ 63.094739] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 63.099373] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] -[ 63.108476] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 63.293451] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 63.324757] [I][mhi_netdev_enable_iface] Exited. -[ 63.326265] rmnet_vnd_register_device(rmnet_mhi0.1)=0 - -root@OpenWrt:/# quectel-CM -s cment & -[04-13_09:25:23:910] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_09:25:23:912] network interface '' or qmidev '' is not exist -[04-13_09:25:23:912] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-13_09:25:23:913] mbim_qmap_mode = 1, vlan_id = 0x00, qmap_netcard = rmnet_mhi0.1 -[04-13_09:25:23:913] Modem works in MBIM mode -[04-13_09:25:23:965] cdc_wdm_fd = 7 -[04-13_09:25:23:965] mbim_open_device() -[04-13_09:25:24:549] mbim_device_caps_query() -[04-13_09:25:24:575] DeviceId: 869710030002905 -[04-13_09:25:24:575] FirmwareInfo: RM500QGLABR10A03M4G_01.001.03 -[04-13_09:25:24:575] HardwareInfo: RM500QGL_VH -[04-13_09:25:24:576] mbim_device_services_query() -[04-13_09:25:24:585] mbim_set_radio_state( 1 ) -[04-13_09:25:24:588] HwRadioState: 1, SwRadioState: 1 -[04-13_09:25:24:588] mbim_subscriber_status_query() -[04-13_09:25:24:612] SubscriberId: 460028563800461 -[04-13_09:25:24:612] SimIccId: 89860015120716380461 -[04-13_09:25:24:613] SubscriberReadyState NotInitialized -> Initialized -[04-13_09:25:24:613] mbim_register_state_query() -[04-13_09:25:24:617] RegisterState Unknown -> Home -[04-13_09:25:24:617] mbim_packet_service_query() -[04-13_09:25:24:619] PacketServiceState Unknown -> Attached -[04-13_09:25:24:619] CurrentDataClass = 5G_NSA -[04-13_09:25:24:620] mbim_query_connect(sessionID=0) -[04-13_09:25:24:631] ActivationState Unknown -> Deactivated -[04-13_09:25:24:631] ifconfig rmnet_mhi0 down -[04-13_09:25:24:657] ifconfig rmnet_mhi0.1 0.0.0.0 -ifconfig: SIOCSIFFLAGS: Network is down -[04-13_09:25:24:681] ifconfig rmnet_mhi0.1 down -[04-13_09:25:24:705] mbim_register_state_query() -[04-13_09:25:24:709] mbim_packet_service_query() -[04-13_09:25:24:713] CurrentDataClass = 5G_NSA -[04-13_09:25:24:713] mbim_set_connect(onoff=1, sessionID=0) -[04-13_09:25:25:096] ActivationState Deactivated -> Activated -[04-13_09:25:25:097] mbim_ip_config(sessionID=0) -[04-13_09:25:25:100] < SessionId = 0 -[04-13_09:25:25:100] < IPv4ConfigurationAvailable = 0xf -[04-13_09:25:25:100] < IPv6ConfigurationAvailable = 0x0 -[04-13_09:25:25:101] < IPv4AddressCount = 0x1 -[04-13_09:25:25:101] < IPv4AddressOffset = 0x3c -[04-13_09:25:25:101] < IPv6AddressCount = 0x0 -[04-13_09:25:25:102] < IPv6AddressOffset = 0x0 -[04-13_09:25:25:102] < IPv4 = 10.190.166.229/30 -[04-13_09:25:25:103] < gw = 10.190.166.230 -[04-13_09:25:25:103] < dns1 = 211.138.180.2 -[04-13_09:25:25:103] < dns2 = 211.138.180.3 -[04-13_09:25:25:104] < ipv4 mtu = 1500 -[04-13_09:25:25:112] ifconfig rmnet_mhi0 up -[04-13_09:25:25:141] ifconfig rmnet_mhi0.1 up -[04-13_09:25:25:170] ip -4 address flush dev rmnet_mhi0.1 -[04-13_09:25:25:190] ip -4 address add 10.190.166.229/30 dev rmnet_mhi0.1 -[04-13_09:25:25:213] ip -4 route add default via 10.190.166.230 dev rmnet_mhi0.1 - -root@OpenWrt:/# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.190.166.229 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:19 errors:0 dropped:0 overruns:0 frame:0 - TX packets:29 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:2326 (2.2 KiB) TX bytes:2991 (2.9 KiB) - -root@OpenWrt:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=278.561 ms diff --git a/quectel_cm_5G/src/log/pcie_mhi_mbim_qmap=4.txt b/quectel_cm_5G/src/log/pcie_mhi_mbim_qmap=4.txt deleted file mode 100644 index 4d6cdf0..0000000 --- a/quectel_cm_5G/src/log/pcie_mhi_mbim_qmap=4.txt +++ /dev/null @@ -1,170 +0,0 @@ -root@OpenWrt:/# lspci -00:00.0 Class 0604: 17cb:1001 -01:00.0 Class ff00: 17cb:0304 -root@OpenWrt:/# insmod pcie_mhi.ko mhi_mbim_enabled=1 qmap_mode=4 -[ 76.596827] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 -[ 76.598596] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0304 -[ 76.602863] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] -[ 76.611323] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 76.760239] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 76.828699] [I][mhi_netdev_enable_iface] Exited. -[ 76.832727] rmnet_vnd_register_device(rmnet_mhi0.1)=0 -[ 76.836596] rmnet_vnd_register_device(rmnet_mhi0.2)=0 -[ 76.841170] rmnet_vnd_register_device(rmnet_mhi0.3)=0 -[ 76.846373] rmnet_vnd_register_device(rmnet_mhi0.4)=0 - -root@OpenWrt:~# quectel-mbim-proxy -d /dev/mhi_MBIM & -root@OpenWrt:~# [04-14_03:05:36:296] mbim_dev_fd=3 -[04-14_03:05:36:297] mbim_send_open_msg() -[04-14_03:05:36:669] receive MBIM_OPEN_DONE, status=0 -[04-14_03:05:36:670] mbim_server_fd=4 - -root@OpenWrt:~# quectel-CM -n 1 -s cmnet & -[04-14_03:05:45:955] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_03:05:45:956] network interface '' or qmidev '' is not exist -[04-14_03:05:45:957] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-14_03:05:45:957] mbim_qmap_mode = 4, vlan_id = 0x01, qmap_netcard = rmnet_mhi0.1 -[04-14_03:05:45:958] Modem works in MBIM mode -[04-14_03:05:45:959] connect to quectel-mbim-proxy sockfd = 7 -[04-14_03:05:45:959] handle_client_connect client_fd=5, client_idx=1 -[04-14_03:05:45:959] cdc_wdm_fd = 7 -[04-14_03:05:45:960] mbim_open_device() -[04-14_03:05:45:961] mbim_device_caps_query() -[04-14_03:05:45:967] DeviceId: 860459050041596 -[04-14_03:05:45:968] FirmwareInfo: EM120RGLAPR02A03M4G_01.001.07 - -[04-14_03:05:45:968] HardwareInfo: EM120R_GL -[04-14_03:05:45:968] mbim_device_services_query() -[04-14_03:05:45:972] mbim_set_radio_state( 1 ) -[04-14_03:05:45:976] HwRadioState: 1, SwRadioState: 1 -[04-14_03:05:45:976] mbim_subscriber_status_query() -[04-14_03:05:45:985] SubscriberId: 460028563800461 -[04-14_03:05:45:985] SimIccId: 89860015120716380461 -[04-14_03:05:45:986] SubscriberReadyState NotInitialized -> Initialized -[04-14_03:05:45:986] mbim_register_state_query() -[04-14_03:05:45:991] RegisterState Unknown -> Home -[04-14_03:05:45:991] mbim_packet_service_query() -[04-14_03:05:45:995] PacketServiceState Unknown -> Attached -[04-14_03:05:45:996] mbim_query_connect(sessionID=1) -[04-14_03:05:46:000] ActivationState Unknown -> Deactivated -[04-14_03:05:46:000] ifconfig rmnet_mhi0 down -[04-14_03:05:46:024] ifconfig rmnet_mhi0.1 0.0.0.0 -ifconfig: SIOCSIFFLAGS: Network is down -[04-14_03:05:46:049] ifconfig rmnet_mhi0.1 down -[04-14_03:05:46:072] mbim_set_connect(onoff=1, sessionID=1) -[04-14_03:05:46:099] ActivationState Deactivated -> Activated -[04-14_03:05:46:099] mbim_ip_config(sessionID=1) -[ 222.484298] net rmnet_mhi0: link_state 0x0 -> 0x1 -[04-14_03:05:46:103] < SessionId = 1 -[04-14_03:05:46:104] < IPv4ConfigurationAvailable = 0xf -[04-14_03:05:46:104] < IPv6ConfigurationAvailable = 0x0 -[04-14_03:05:46:104] < IPv4AddressCount = 0x1 -[04-14_03:05:46:105] < IPv4AddressOffset = 0x3c -[ 222.507775] [I][mhi_netdev_open] Opened net dev interface -[04-14_03:05:46:105] < IPv6AddressCount = 0x0 -[04-14_03:05:46:105] < IPv6AddressOffset = 0x0 -[04-14_03:05:46:106] < IPv4 = 10.38.21.158/30 -[04-14_03:05:46:106] < gw = 10.38.21.157 -[04-14_03:05:46:106] < dns1 = 211.138.180.2 -[04-14_03:05:46:107] < dns2 = 211.138.180.3 -[04-14_03:05:46:107] < ipv4 mtu = 1500 -[04-14_03:05:46:112] ifconfig rmnet_mhi0 up -[04-14_03:05:46:140] ifconfig rmnet_mhi0.1 up -[04-14_03:05:46:168] ip -4 address flush dev rmnet_mhi0.1 -[04-14_03:05:46:190] ip -4 address add 10.38.21.158/30 dev rmnet_mhi0.1 -[04-14_03:05:46:212] ip -4 route add default via 10.38.21.157 dev rmnet_mhi0.1 -[04-14_03:05:50:730] handle_client_connect client_fd=6, client_idx=2 -[ 227.558631] net rmnet_mhi0: link_state 0x1 -> 0x3 - -root@OpenWrt:~# quectel-CM -n 2 -s 4gnet -[04-14_03:05:50:725] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_03:05:50:726] network interface '' or qmidev '' is not exist -[04-14_03:05:50:727] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-14_03:05:50:728] mbim_qmap_mode = 4, vlan_id = 0x02, qmap_netcard = rmnet_mhi0.2 -[04-14_03:05:50:729] Modem works in MBIM mode -[04-14_03:05:50:730] connect to quectel-mbim-proxy sockfd = 8 -[04-14_03:05:50:730] cdc_wdm_fd = 8 -[04-14_03:05:50:731] mbim_open_device() -[04-14_03:05:50:732] mbim_device_caps_query() -[04-14_03:05:50:738] DeviceId: 860459050041596 -[04-14_03:05:50:739] FirmwareInfo: EM120RGLAPR02A03M4G_01.001.07 - -[04-14_03:05:50:739] HardwareInfo: EM120R_GL -[04-14_03:05:50:740] mbim_device_services_query() -[04-14_03:05:50:744] mbim_set_radio_state( 1 ) -[04-14_03:05:50:747] HwRadioState: 1, SwRadioState: 1 -[04-14_03:05:50:747] mbim_subscriber_status_query() -[04-14_03:05:50:757] SubscriberId: 460028563800461 -[04-14_03:05:50:758] SimIccId: 89860015120716380461 -[04-14_03:05:50:758] SubscriberReadyState NotInitialized -> Initialized -[04-14_03:05:50:759] mbim_register_state_query() -[04-14_03:05:50:763] RegisterState Unknown -> Home -[04-14_03:05:50:764] mbim_packet_service_query() -[04-14_03:05:50:768] PacketServiceState Unknown -> Attached -[04-14_03:05:50:769] mbim_query_connect(sessionID=2) -[04-14_03:05:50:772] ActivationState Unknown -> Deactivated -[04-14_03:05:50:773] ifconfig rmnet_mhi0.2 0.0.0.0 -[04-14_03:05:50:799] ifconfig rmnet_mhi0.2 down -[04-14_03:05:50:834] mbim_set_connect(onoff=1, sessionID=2) -[04-14_03:05:51:170] ActivationState Deactivated -> Activated -[04-14_03:05:51:171] mbim_ip_config(sessionID=2) -[04-14_03:05:51:174] < SessionId = 2 -[04-14_03:05:51:174] < IPv4ConfigurationAvailable = 0xf -[04-14_03:05:51:175] < IPv6ConfigurationAvailable = 0x0 -[04-14_03:05:51:175] < IPv4AddressCount = 0x1 -[04-14_03:05:51:175] < IPv4AddressOffset = 0x3c -[04-14_03:05:51:176] < IPv6AddressCount = 0x0 -[04-14_03:05:51:176] < IPv6AddressOffset = 0x0 -[04-14_03:05:51:176] < IPv4 = 10.36.109.217/30 -[04-14_03:05:51:177] < gw = 10.36.109.218 -[04-14_03:05:51:177] < dns1 = 211.138.180.2 -[04-14_03:05:51:178] < dns2 = 211.138.180.3 -[04-14_03:05:51:178] < ipv4 mtu = 1500 -[04-14_03:05:51:182] ifconfig rmnet_mhi0 up -[04-14_03:05:51:206] ifconfig rmnet_mhi0.2 up -[04-14_03:05:51:233] ip -4 address flush dev rmnet_mhi0.2 -[04-14_03:05:51:254] ip -4 address add 10.36.109.217/30 dev rmnet_mhi0.2 -[04-14_03:05:51:277] ip -4 route add default via 10.36.109.218 dev rmnet_mhi0.2 - -root@OpenWrt:~# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.38.21.158 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:37 errors:0 dropped:0 overruns:0 frame:0 - TX packets:29 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:9907 (9.6 KiB) TX bytes:2764 (2.6 KiB) - -root@OpenWrt:~# ifconfig rmnet_mhi0.2 -rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.36.109.217 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:5 errors:0 dropped:0 overruns:0 frame:0 - TX packets:18 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:344 (344.0 B) TX bytes:1152 (1.1 KiB) - -root@OpenWrt:~# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process -root@OpenWrt:~# ip ro add 8.8.8.8/32 dev rmnet_mhi0.1 -root@OpenWrt:~# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=73.248 ms - -root@OpenWrt:~# ip ro del 8.8.8.8/32 -root@OpenWrt:~# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process -root@OpenWrt:~# ip ro add 8.8.8.8/32 dev rmnet_mhi0.2 -root@OpenWrt:~# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=99.637 ms - -root@OpenWrt:~# quectel-CM -k 2 -[04-14_03:06:58:912] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_03:06:59:063] /proc/3565/cmdline: quectel-CM -n 2 -s 4gnet -[04-14_03:06:59:064] send SIGINT to process 3565 -[ 295.719442] net rmnet_mhi0: link_state 0x3 -> 0x1 -[04-14_03:06:59:407] proxy_loop poll fd = 6, revents = 0011 -[04-14_03:06:59:408] handle_client_disconnect client_fd=6, client_idx=2 diff --git a/quectel_cm_5G/src/log/pcie_mhi_qmap=1.txt b/quectel_cm_5G/src/log/pcie_mhi_qmap=1.txt deleted file mode 100644 index c93af7e..0000000 --- a/quectel_cm_5G/src/log/pcie_mhi_qmap=1.txt +++ /dev/null @@ -1,127 +0,0 @@ -root@OpenWrt:/# cat /sys/class/net/rmnet_mhi0/qmap_mode -1 -root@OpenWrt:/# cat /sys/module/pcie_mhi/parameters/mhi_mbim_enabled -0 -root@OpenWrt:/# dmesg | grep mhi -[ 18.442226] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 -[ 18.443032] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 18.447488] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] -[ 18.456563] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 18.464184] [I][mhi_init_pci_dev] msi_required = 5, msi_allocated = 5, msi_irq = 197 -[ 18.464215] [I][mhi_power_up] dev_state:RESET -[ 18.464225] [I][mhi_async_power_up] Requested to power on -[ 18.464432] [I][mhi_alloc_coherent] size = 114688, dma_handle = 8d400000 -[ 18.464445] [I][mhi_init_dev_ctxt] mhi_ctxt->ctrl_seg = d1766000 -[ 18.466003] [I][mhi_async_power_up] dev_state:RESET ee:AMSS -[ 18.466080] [I][mhi_pm_st_worker] Transition to state:READY -[ 18.466109] [I][mhi_pm_st_worker] INVALID_EE -> AMSS -[ 18.466135] [I][mhi_ready_state_transition] Waiting to enter READY state -[ 18.466224] [I][mhi_async_power_up] Power on setup success -[ 18.466265] [I][mhi_pci_probe] Return successful -[ 18.577299] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, pm_state:POR -[ 18.577312] [I][mhi_ready_state_transition] Device in READY State -[ 18.577325] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, INVALID_EE -[ 18.577329] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:POR -[ 18.577337] [I][mhi_init_mmio] Initializing MMIO -[ 18.577344] [I][mhi_init_mmio] CHDBOFF:0x300 -[ 18.577361] [I][mhi_init_mmio] ERDBOFF:0x700 -[ 18.577372] [I][mhi_init_mmio] Programming all MMIO values. -[ 18.690834] [I][mhi_dump_tre] carl_ev evt_state_change mhistate=2 -[ 18.690854] [I][mhi_process_ctrl_ev_ring] MHI state change event to state:M0 -[ 18.690866] [I][mhi_pm_m0_transition] Entered With State:READY PM_STATE:POR -[ 18.690879] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:M0 -[ 18.694229] [I][mhi_dump_tre] carl_ev evt_ee_state execenv=2 -[ 18.694241] [I][mhi_process_ctrl_ev_ring] MHI EE received event:AMSS -[ 18.694293] [I][mhi_pm_st_worker] Transition to state:MISSION MODE -[ 18.694310] [I][mhi_pm_st_worker] INVALID_EE -> AMSS -[ 18.694319] [I][mhi_pm_mission_mode_transition] Processing Mission Mode Transition -[ 18.694341] [I][mhi_init_timesync] No timesync capability found -[ 18.694350] [I][mhi_pm_mission_mode_transition] Adding new devices -[ 18.696365] [I][mhi_dtr_probe] Enter for DTR control channel -[ 18.696383] [I][__mhi_prepare_channel] Entered: preparing channel:18 -[ 18.703113] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 -[ 18.703164] [I][__mhi_prepare_channel] Chan:18 successfully moved to start state -[ 18.703174] [I][__mhi_prepare_channel] Entered: preparing channel:19 -[ 18.710681] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 -[ 18.710734] [I][__mhi_prepare_channel] Chan:19 successfully moved to start state -[ 18.710804] [I][mhi_dtr_probe] Exit with ret:0 -[ 18.711774] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 18.711811] [I][__mhi_prepare_channel] Entered: preparing channel:100 -[ 18.732097] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 -[ 18.732151] [I][__mhi_prepare_channel] Chan:100 successfully moved to start state -[ 18.732162] [I][__mhi_prepare_channel] Entered: preparing channel:101 -[ 18.744170] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 -[ 18.744219] [I][__mhi_prepare_channel] Chan:101 successfully moved to start state -[ 18.749132] [I][mhi_netdev_enable_iface] Exited. -[ 18.750306] rmnet_vnd_register_device(rmnet_mhi0.1)=0 -[ 18.752927] [I][mhi_pm_mission_mode_transition] Exit with ret:0 - -root@OpenWrt:/# busybox microcom /dev/mhi_DUN -at+cpin? -+CPIN: READY - -OK -at+cops? -+COPS: 0,0,"CHINA MOBILE",13 - -OK -at+csq -+csq: 23,99 - -OK - -root@OpenWrt:/# quectel-CM -s cmnet & -[04-13_09:26:58:077] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_09:26:58:078] network interface '' or qmidev '' is not exist -[04-13_09:26:58:079] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-13_09:26:58:080] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 -[04-13_09:26:58:080] Modem works in QMI mode -[04-13_09:26:58:131] cdc_wdm_fd = 7 -[04-13_09:26:59:132] QmiWwanInit message timeout -[04-13_09:27:00:140] Get clientWDS = 15 -[04-13_09:27:00:144] Get clientDMS = 1 -[04-13_09:27:00:147] Get clientNAS = 4 -[04-13_09:27:00:151] Get clientUIM = 1 -[04-13_09:27:00:155] Get clientWDA = 1 -[04-13_09:27:00:158] requestBaseBandVersion RM500QGLABR10A03M4G -[04-13_09:27:00:161] qmap_settings.rx_urb_size = 16384 -[04-13_09:27:00:162] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_09:27:00:162] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-13_09:27:00:163] qmap_settings.dl_minimum_padding = 0 -[04-13_09:27:00:176] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_09:27:00:177] requestSetProfile[1] cmnet///0 -[04-13_09:27:00:190] requestGetProfile[1] cmnet///0 -[04-13_09:27:00:193] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-13_09:27:00:197] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_09:27:00:198] ifconfig rmnet_mhi0 down -[04-13_09:27:00:222] ifconfig rmnet_mhi0.1 0.0.0.0 -[04-13_09:27:00:247] ifconfig rmnet_mhi0.1 down -[04-13_09:27:00:281] requestSetupDataCall WdsConnectionIPv4Handle: 0x1228bb20 -[ 245.284909] net rmnet_mhi0: link_state 0x0 -> 0x1 -[04-13_09:27:00:293] ifconfig rmnet_mhi0 up -[ 245.308696] [I][mhi_netdev_open] Opened net dev interface -[04-13_09:27:00:318] ifconfig rmnet_mhi0.1 up -[04-13_09:27:00:353] you are use OpenWrt? -[04-13_09:27:00:354] should not calling udhcpc manually? -[04-13_09:27:00:354] should modify /etc/config/network as below? -[04-13_09:27:00:355] config interface wan -[04-13_09:27:00:355] option ifname rmnet_mhi0.1 -[04-13_09:27:00:355] option proto dhcp -[04-13_09:27:00:356] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? -[04-13_09:27:00:356] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 -udhcpc: started, v1.28.3 -udhcpc: sending discover -udhcpc: sending select for 10.128.73.23 -udhcpc: lease of 10.128.73.23 obtained, lease time 7200 -[04-13_09:27:00:710] udhcpc: ifconfig rmnet_mhi0.1 10.128.73.23 netmask 255.255.255.240 broadcast + -[04-13_09:27:00:742] udhcpc: setting default routers: 10.128.73.24 - -root@OpenWrt:/# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.128.73.23 Mask:255.255.255.240 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:612 (612.0 B) TX bytes:684 (684.0 B) diff --git a/quectel_cm_5G/src/log/pcie_mhi_qmap=1_bridge.txt b/quectel_cm_5G/src/log/pcie_mhi_qmap=1_bridge.txt deleted file mode 100644 index 0ab6de7..0000000 --- a/quectel_cm_5G/src/log/pcie_mhi_qmap=1_bridge.txt +++ /dev/null @@ -1,76 +0,0 @@ -root@OpenWrt:/# lspci -00:00.0 Class 0604: 17cb:1001 -01:00.0 Class ff00: 17cb:0306 - -root@OpenWrt:~# insmod pcie_mhi.ko -[ 77.949271] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 -[ 77.950949] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 77.955331] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] -[ 77.963756] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 78.048911] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 78.092304] [I][mhi_netdev_enable_iface] Exited. -[ 78.096580] rmnet_vnd_register_device(rmnet_mhi0.1)=0 - -root@OpenWrt:~# brctl addbr br0 -root@OpenWrt:~# brctl addif br0 rmnet_mhi0.1 -root@OpenWrt:~# brctl addif br0 eth1 -[ 250.017213] device eth1 entered promiscuous mode -root@OpenWrt:~# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00001c353487 no eth1 - rmnet_mhi0.1 - -root@OpenWrt:~# quectel-CM -s cmnet -b & -[04-14_06:43:28:473] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_06:43:28:474] network interface '' or qmidev '' is not exist -[04-14_06:43:28:475] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-14_06:43:28:476] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 -[04-14_06:43:28:477] Modem works in QMI mode -[04-14_06:43:28:531] cdc_wdm_fd = 7 -[04-14_06:43:29:532] QmiWwanInit message timeout -[04-14_06:43:30:540] Get clientWDS = 15 -[04-14_06:43:30:543] Get clientDMS = 1 -[04-14_06:43:30:546] Get clientNAS = 4 -[04-14_06:43:30:550] Get clientUIM = 1 -[04-14_06:43:30:553] Get clientWDA = 1 -[04-14_06:43:30:557] requestBaseBandVersion RM500QGLABR10A03M4G -[04-14_06:43:30:560] qmap_settings.rx_urb_size = 16384 -[04-14_06:43:30:561] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-14_06:43:30:561] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-14_06:43:30:561] qmap_settings.dl_minimum_padding = 0 -[04-14_06:43:30:575] requestGetSIMStatus SIMStatus: SIM_READY -[04-14_06:43:30:575] requestSetProfile[1] cmnet///0 -[04-14_06:43:30:588] requestGetProfile[1] cmnet///0 -[04-14_06:43:30:591] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-14_06:43:30:595] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-14_06:43:30:595] ifconfig rmnet_mhi0 down -[04-14_06:43:30:620] ifconfig rmnet_mhi0.1 0.0.0.0 -ifconfig: SIOCSIFFLAGS: Network is down -[04-14_06:43:30:644] ifconfig rmnet_mhi0.1 down -[04-14_06:43:30:679] requestSetupDataCall WdsConnectionIPv4Handle: 0xb41f47d0 -[ 263.869899] net rmnet_mhi0: link_state 0x0 -> 0x1 -[04-14_06:43:30:693] ifconfig rmnet_mhi0 up -[ 263.892647] [I][mhi_netdev_open] Opened net dev interface -[04-14_06:43:30:718] ifconfig rmnet_mhi0.1 up -[04-14_06:43:30:746] echo '0xa59316b' > /sys/class/net/rmnet_mhi0.1/bridge_ipv4 - -root@OpenWrt:~# ifconfig br0 up -[ 268.800026] br0: port 2(eth1) entered forwarding state -[ 268.800336] br0: port 2(eth1) entered forwarding state -[ 268.804251] br0: port 1(rmnet_mhi0.1) entered forwarding state -[ 268.809465] br0: port 1(rmnet_mhi0.1) entered forwarding state -[ 283.845790] br0: port 2(eth1) entered forwarding state - -[ 296.512489] rmnet_mhi0.1 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 296.515756] rmnet_mhi0.1 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 296.586584] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 -[ 296.672356] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 -[ 296.792061] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 -[ 296.832822] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 -[ 296.941073] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107 -[ 297.941310] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107 -[ 298.941528] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107 -[ 299.941704] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.107, ipv4=10.89.49.107 -[ 300.024484] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 -[ 300.051995] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 -[ 303.915933] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 diff --git a/quectel_cm_5G/src/log/pcie_mhi_qmap=4.txt b/quectel_cm_5G/src/log/pcie_mhi_qmap=4.txt deleted file mode 100644 index 5f43a74..0000000 --- a/quectel_cm_5G/src/log/pcie_mhi_qmap=4.txt +++ /dev/null @@ -1,138 +0,0 @@ -root@OpenWrt:/# lspci -00:00.0 Class 0604: 17cb:1001 -01:00.0 Class ff00: 17cb:0306 - -root@OpenWrt:/# insmod pcie_mhi.ko qmap_mode=4 -[ 61.988878] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 -[ 61.989484] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 61.994039] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] -[ 62.003208] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -[ 62.191947] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 62.224065] [I][mhi_netdev_enable_iface] Exited. -[ 62.225619] rmnet_vnd_register_device(rmnet_mhi0.1)=0 -[ 62.229289] rmnet_vnd_register_device(rmnet_mhi0.2)=0 -[ 62.234378] rmnet_vnd_register_device(rmnet_mhi0.3)=0 -[ 62.240039] rmnet_vnd_register_device(rmnet_mhi0.4)=0 - -root@OpenWrt:/# quectel-qmi-proxy -d /dev/mhi_QMI0 & -[04-13_09:25:12:278] Will use cdc-wdm='/dev/mhi_QMI0', proxy='quectel-qmi-proxy0' -[04-13_09:25:12:297] qmi_proxy_init enter -[04-13_09:25:12:297] qmi_proxy_loop enter thread_id 0xb6e88d44 -[04-13_09:25:14:298] qmi_proxy_init succful -[04-13_09:25:14:299] local server: quectel-qmi-proxy0 sockfd = 4 -[04-13_09:25:14:299] qmi_proxy_server_fd = 4 - -root@OpenWrt:/# quectel-CM -n 1 -s cmnet & -[04-13_09:25:32:336] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_09:25:32:337] network interface '' or qmidev '' is not exist -[04-13_09:25:32:338] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-13_09:25:32:339] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 -[04-13_09:25:32:340] Modem works in QMI mode -[04-13_09:25:32:341] connect to quectel-qmi-proxy0 sockfd = 7 -[04-13_09:25:32:342] cdc_wdm_fd = 7 -[04-13_09:25:32:380] requestBaseBandVersion RM500QGLABR10A03M4G -[04-13_09:25:32:382] qmap_settings.rx_urb_size = 16384 -[04-13_09:25:32:383] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_09:25:32:383] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-13_09:25:32:384] qmap_settings.dl_minimum_padding = 0 -[04-13_09:25:32:394] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_09:25:32:395] requestSetProfile[1] cmnet///0 -[04-13_09:25:32:409] requestGetProfile[1] cmnet///0 -[04-13_09:25:32:414] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-13_09:25:32:418] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_09:25:32:419] ifconfig rmnet_mhi0 down -[04-13_09:25:32:448] ifconfig rmnet_mhi0.1 0.0.0.0 -[04-13_09:25:32:473] ifconfig rmnet_mhi0.1 down -[04-13_09:25:32:514] requestSetupDataCall WdsConnectionIPv4Handle: 0x2313a2a0 -[ 121.648172] net rmnet_mhi0: link_state 0x0 -> 0x1 -[04-13_09:25:32:525] ifconfig rmnet_mhi0 up -[ 121.671210] [I][mhi_netdev_open] Opened net dev interface -[04-13_09:25:32:551] ifconfig rmnet_mhi0.1 up -[04-13_09:25:32:586] you are use OpenWrt? -[04-13_09:25:32:587] should not calling udhcpc manually? -[04-13_09:25:32:587] should modify /etc/config/network as below? -[04-13_09:25:32:587] config interface wan -[04-13_09:25:32:588] option ifname rmnet_mhi0.1 -[04-13_09:25:32:588] option proto dhcp -[04-13_09:25:32:589] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? -[04-13_09:25:32:589] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 -udhcpc: started, v1.28.3 -udhcpc: sending discover -udhcpc: sending select for 10.174.91.70 -udhcpc: lease of 10.174.91.70 obtained, lease time 7200 -[04-13_09:25:32:980] udhcpc: ifconfig rmnet_mhi0.1 10.174.91.70 netmask 255.255.255.252 broadcast + -[04-13_09:25:33:007] udhcpc: setting default routers: 10.174.91.69 - -root@OpenWrt:/# quectel-CM -n 2 -s 4gnet & -[04-13_09:25:42:976] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_09:25:42:977] network interface '' or qmidev '' is not exist -[04-13_09:25:42:978] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-13_09:25:42:978] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x82, qmap_netcard = rmnet_mhi0.2 -[04-13_09:25:42:979] Modem works in QMI mode -[04-13_09:25:42:981] connect to quectel-qmi-proxy0 sockfd = 7 -[04-13_09:25:42:982] cdc_wdm_fd = 7 -[04-13_09:25:43:010] requestBaseBandVersion RM500QGLABR10A03M4G -[04-13_09:25:43:013] qmap_settings.rx_urb_size = 16384 -[04-13_09:25:43:014] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_09:25:43:014] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-13_09:25:43:015] qmap_settings.dl_minimum_padding = 0 -[04-13_09:25:43:030] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_09:25:43:030] requestSetProfile[2] 4gnet///0 -[04-13_09:25:43:046] requestGetProfile[2] 4gnet///0 -[04-13_09:25:43:050] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-13_09:25:43:054] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_09:25:43:055] ifconfig rmnet_mhi0.2 0.0.0.0 -[04-13_09:25:43:082] ifconfig rmnet_mhi0.2 down -[04-13_09:25:43:507] requestSetupDataCall WdsConnectionIPv4Handle: 0x2332a780 -[ 132.641313] net rmnet_mhi0: link_state 0x1 -> 0x3 -[04-13_09:25:43:519] ifconfig rmnet_mhi0 up -[04-13_09:25:43:543] ifconfig rmnet_mhi0.2 up -[04-13_09:25:43:570] you are use OpenWrt? -[04-13_09:25:43:570] should not calling udhcpc manually? -[04-13_09:25:43:571] should modify /etc/config/network as below? -[04-13_09:25:43:571] config interface wan -[04-13_09:25:43:571] option ifname rmnet_mhi0.2 -[04-13_09:25:43:572] option proto dhcp -[04-13_09:25:43:572] should use "/sbin/ifstaus wan" to check rmnet_mhi0.2 's status? -[04-13_09:25:43:573] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.2 -udhcpc: started, v1.28.3 -udhcpc: sending discover -udhcpc: sending select for 10.163.253.197 -udhcpc: lease of 10.163.253.197 obtained, lease time 7200 -[04-13_09:25:43:810] udhcpc: ifconfig rmnet_mhi0.2 10.163.253.197 netmask 255.255.255.252 broadcast + -[04-13_09:25:43:836] udhcpc: setting default routers: 10.163.253.198 - -root@OpenWrt:/# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.174.91.70 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:4 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:612 (612.0 B) TX bytes:1380 (1.3 KiB) - -root@OpenWrt:/# ifconfig rmnet_mhi0.2 -rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.163.253.197 Mask:255.255.255.252 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:612 (612.0 B) TX bytes:684 (684.0 B) - -root@OpenWrt:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process -root@OpenWrt:/# ip ro add 8.8.8.8/32 dev rmnet_mhi0.1 -root@OpenWrt:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=390.869 ms - -root@OpenWrt:/# ip ro del 8.8.8.8/32 -root@OpenWrt:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process -root@OpenWrt:/# ip ro add 8.8.8.8/32 dev rmnet_mhi0.2 -root@OpenWrt:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=111 time=314.395 ms \ No newline at end of file diff --git a/quectel_cm_5G/src/log/pcie_mhi_qmap=4_bridge.txt b/quectel_cm_5G/src/log/pcie_mhi_qmap=4_bridge.txt deleted file mode 100644 index 0af5ff0..0000000 --- a/quectel_cm_5G/src/log/pcie_mhi_qmap=4_bridge.txt +++ /dev/null @@ -1,147 +0,0 @@ -root@OpenWrt:~# lspci -00:00.0 Class 0604: 17cb:1001 -01:00.0 Class ff00: 17cb:0306 -root@OpenWrt:~# - -root@OpenWrt:~# insmod pcie_mhi.ko qmap_mode=4 -[ 200.906104] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 -[ 200.907913] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 -[ 200.912164] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] -[ 200.920593] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) -root@OpenWrt:~# [ 201.112214] [I][mhi_netdev_enable_iface] Prepare the channels for transfer -[ 201.154640] [I][mhi_netdev_enable_iface] Exited. -[ 201.159271] rmnet_vnd_register_device(rmnet_mhi0.1)=0 -[ 201.162953] rmnet_vnd_register_device(rmnet_mhi0.2)=0 -[ 201.167698] rmnet_vnd_register_device(rmnet_mhi0.3)=0 -[ 201.172178] rmnet_vnd_register_device(rmnet_mhi0.4)=0 - -root@OpenWrt:~# brctl addbr br0 -root@OpenWrt:~# brctl addif br0 eth1 -root@OpenWrt:~# brctl addif br0 rmnet_mhi0.2 -root@OpenWrt:~# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00001c353487 no eth1 - rmnet_mhi0.2 - -root@OpenWrt:~# quectel-qmi-proxy -d /dev/mhi_QMI0 & -[04-14_06:44:01:556] Will use cdc-wdm='/dev/mhi_QMI0', proxy='quectel-qmi-proxy0' -[04-14_06:44:01:573] qmi_proxy_init enter -[04-14_06:44:01:573] qmi_proxy_loop enter thread_id 0xb6f20d44 -[04-14_06:44:03:574] qmi_proxy_init succful -[04-14_06:44:03:574] local server: quectel-qmi-proxy0 sockfd = 4 -[04-14_06:44:03:575] qmi_proxy_server_fd = 4 - - -root@OpenWrt:~# quectel-CM -n 1 -s cmnet & -[04-14_06:47:53:303] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_06:47:53:314] network interface '' or qmidev '' is not exist -[04-14_06:47:53:315] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-14_06:47:53:316] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 -[04-14_06:47:53:316] Modem works in QMI mode -[04-14_06:47:53:318] connect to quectel-qmi-proxy0 sockfd = 7 -[04-14_06:47:53:318] cdc_wdm_fd = 7 -[04-14_06:47:53:326] Get clientWDS = 15 -[04-14_06:47:53:329] Get clientDMS = 2 -[04-14_06:47:53:334] Get clientNAS = 4 -[04-14_06:47:53:338] Get clientUIM = 1 -[04-14_06:47:53:343] Get clientWDA = 1 -[04-14_06:47:53:347] requestBaseBandVersion RM500QGLABR10A03M4G -[04-14_06:47:53:351] qmap_settings.rx_urb_size = 16384 -[04-14_06:47:53:352] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-14_06:47:53:352] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-14_06:47:53:352] qmap_settings.dl_minimum_padding = 0 -[04-14_06:47:53:369] requestGetSIMStatus SIMStatus: SIM_READY -[04-14_06:47:53:370] requestSetProfile[1] cmnet///0 -[04-14_06:47:53:402] requestGetProfile[1] cmnet///0 -[04-14_06:47:53:407] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:47:53:411] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-14_06:47:53:412] ifconfig rmnet_mhi0 down -[04-14_06:47:53:436] ifconfig rmnet_mhi0.1 0.0.0.0 -[04-14_06:47:53:460] ifconfig rmnet_mhi0.1 down -[04-14_06:48:26:399] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:26:405] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:26:411] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:26:970] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-14_06:48:26:992] requestSetupDataCall WdsConnectionIPv4Handle: 0x34176710 -[04-14_06:48:27:005] ifconfig rmnet_mhi0 up -[04-14_06:48:27:031] ifconfig rmnet_mhi0.1 up -[04-14_06:48:27:057] you are use OpenWrt? -[04-14_06:48:27:057] should not calling udhcpc manually? -[04-14_06:48:27:080] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? -[04-14_06:48:27:081] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 -[04-14_06:48:27:363] udhcpc: ifconfig rmnet_mhi0.1 10.245.22.3 netmask 255.255.255.248 broadcast + -[04-14_06:48:27:398] udhcpc: setting default routers: 10.245.22.4 -[04-14_06:48:27:491] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA - -root@OpenWrt:~# quectel-CM -n 2 -s 4gnet -b & -[04-14_06:48:06:842] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_06:48:06:853] network interface '' or qmidev '' is not exist -[04-14_06:48:06:854] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-14_06:48:06:855] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x82, qmap_netcard = rmnet_mhi0.2 -[04-14_06:48:06:855] Modem works in QMI mode -[04-14_06:48:06:857] connect to quectel-qmi-proxy0 sockfd = 7 -[04-14_06:48:06:858] cdc_wdm_fd = 7 -[04-14_06:48:06:864] Get clientWDS = 16 -[04-14_06:48:06:867] Get clientDMS = 3 -[04-14_06:48:06:871] Get clientNAS = 5 -[04-14_06:48:06:874] Get clientUIM = 2 -[04-14_06:48:06:879] Get clientWDA = 2 -[04-14_06:48:06:886] requestBaseBandVersion RM500QGLABR10A03M4G -[04-14_06:48:06:891] qmap_settings.rx_urb_size = 16384 -[04-14_06:48:06:891] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-14_06:48:06:892] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-14_06:48:06:892] qmap_settings.dl_minimum_padding = 0 -[04-14_06:48:06:909] requestGetSIMStatus SIMStatus: SIM_READY -[04-14_06:48:06:909] requestSetProfile[2] 4gnet///0 -[04-14_06:48:06:940] requestGetProfile[2] 4gnet///0 -[04-14_06:48:06:944] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:06:949] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-14_06:48:06:949] ifconfig rmnet_mhi0 down -[04-14_06:48:06:973] ifconfig rmnet_mhi0.2 0.0.0.0 -[04-14_06:48:06:998] ifconfig rmnet_mhi0.2 down -[04-14_06:48:26:400] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:26:405] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:26:411] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW -[04-14_06:48:26:970] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-14_06:48:27:220] requestSetupDataCall WdsConnectionIPv4Handle: 0x341450a0 -[04-14_06:48:27:228] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-14_06:48:27:238] ifconfig rmnet_mhi0 up -[04-14_06:48:27:263] ifconfig rmnet_mhi0.2 up -[04-14_06:48:27:313] echo '0xaf51be9' > /sys/class/net/rmnet_mhi0.2/bridge_ipv4 - -root@OpenWrt:~# ifconfig rmnet_mhi0.1 -rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.245.22.3 Mask:255.255.255.248 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:6 errors:0 dropped:0 overruns:0 frame:0 - TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:1836 (1.7 KiB) TX bytes:2052 (2.0 KiB) - -root@OpenWrt:~# ifconfig rmnet_mhi0.2 -rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:347 errors:0 dropped:0 overruns:0 frame:0 - TX packets:795 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:119871 (117.0 KiB) TX bytes:121254 (118.4 KiB) - -root@OpenWrt:~# ifconfig br0 up -[ 520.005476] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 520.025896] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 520.028002] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 520.144371] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 520.410052] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233 -[ 520.414504] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 520.847074] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 521.410241] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233 -[ 522.410455] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233 -[ 522.822594] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 523.410638] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.233, ipv4=10.245.27.233 -[ 523.510028] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 523.997961] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 543.799483] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 -[ 543.929301] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 - diff --git a/quectel_cm_5G/src/log/qmi_wwan_q.txt b/quectel_cm_5G/src/log/qmi_wwan_q.txt deleted file mode 100644 index 161dbbd..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_q.txt +++ /dev/null @@ -1,65 +0,0 @@ -root@ZhuoTK:/# dmesg -[ 15.840000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 15.860000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode -[ 15.860000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 1520 -[ 15.870000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, da:0b:ce:b2:db:21 - -root@ZhuoTK:/# quectel-CM -s cment & -[04-13_03:20:20:456] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:20:20:459] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[04-13_03:20:20:460] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_03:20:20:460] Auto find usbnet_adapter = wwan0 -[04-13_03:20:20:461] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_03:20:20:461] Modem works in QMI mode -[04-13_03:20:20:469] cdc_wdm_fd = 7 -[04-13_03:20:20:547] Get clientWDS = 4 -[04-13_03:20:20:579] Get clientDMS = 1 -[04-13_03:20:20:611] Get clientNAS = 4 -[04-13_03:20:20:643] Get clientUIM = 1 -[04-13_03:20:20:675] Get clientWDA = 1 -[04-13_03:20:20:707] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:20:20:836] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:20:20:836] requestSetProfile[1] cment///0 -[04-13_03:20:20:899] requestGetProfile[1] cment///0 -[04-13_03:20:20:931] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:20:20:963] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_03:20:20:963] ifconfig wwan0 0.0.0.0 -[04-13_03:20:20:976] ifconfig wwan0 down -[04-13_03:20:21:186] requestSetupDataCall WdsConnectionIPv4Handle: 0x8723e780 -[04-13_03:20:21:316] ifconfig wwan0 up -[04-13_03:20:21:329] you are use OpenWrt? -[04-13_03:20:21:330] should not calling udhcpc manually? -[04-13_03:20:21:330] should modify /etc/config/network as below? -[04-13_03:20:21:330] config interface wan -[04-13_03:20:21:330] option ifname wwan0 -[04-13_03:20:21:330] option proto dhcp -[04-13_03:20:21:330] should use "/sbin/ifstaus wan" to check wwan0 's status? -[04-13_03:20:21:331] busybox udhcpc -f -n -q -t 5 -i wwan0 -[04-13_03:20:21:341] udhcpc (v1.23.2) started -[04-13_03:20:21:353] Sending discover... -[04-13_03:20:21:362] Sending select for 10.90.1.113... -[04-13_03:20:21:365] Lease of 10.90.1.113 obtained, lease time 7200 -[04-13_03:20:21:370] udhcpc: ifconfig wwan0 10.90.1.113 netmask 255.255.255.252 broadcast + -[04-13_03:20:21:380] udhcpc: setting default routers: 10.90.1.114 - -root@ZhuoTK:/# ifconfig wwan0 -wwan0 Link encap:Ethernet HWaddr 00:CA:01:91:97:BA - inet addr:10.90.1.113 Mask:255.255.255.252 - inet6 addr: fe80::2ca:1ff:fe91:97ba/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:38 errors:0 dropped:0 overruns:0 frame:0 - TX packets:46 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:5244 (5.1 KiB) TX bytes:6964 (6.8 KiB) - -root@ZhuoTK:/# ip ro show -default via 10.90.1.114 dev wwan0 -10.90.1.112/30 dev wwan0 proto kernel scope link src 10.90.1.113 -192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 - -root@ZhuoTK:/# killall quectel-CM -[04-13_03:20:46:130] requestDeactivateDefaultPDP WdsConnectionIPv4Handle -[04-13_03:20:46:406] ifconfig wwan0 0.0.0.0 -[04-13_03:20:46:418] ifconfig wwan0 down -[04-13_03:20:46:600] QmiWwanThread exit -[04-13_03:20:46:600] qmi_main exit diff --git a/quectel_cm_5G/src/log/qmi_wwan_q_bridge.txt b/quectel_cm_5G/src/log/qmi_wwan_q_bridge.txt deleted file mode 100644 index b979af9..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_q_bridge.txt +++ /dev/null @@ -1,57 +0,0 @@ -root@ZhuoTK:/# insmod qmi_wwan_q.ko -[ 116.910000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 116.930000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode -[ 116.930000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 1520 -[ 116.940000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, 06:fb:51:a3:d6:c5 -[ 116.950000] usbcore: registered new interface driver qmi_wwan_q - -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 -root@ZhuoTK:/# brctl addif br0 wwan0 -root@ZhuoTK:/# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00ca019197b9 no eth0.1 - wwan0 - -root@ZhuoTK:/# quectel-CM -s cmnet -b & -root@ZhuoTK:/# [04-13_05:13:39:369] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:13:39:372] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[ 143.340000] net wwan0: bridge_mode change to 0x1 -[04-13_05:13:39:373] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_05:13:39:374] Auto find usbnet_adapter = wwan0 -[04-13_05:13:39:374] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_05:13:39:380] Modem works in QMI mode -[04-13_05:13:39:388] cdc_wdm_fd = 7 -[04-13_05:13:39:466] Get clientWDS = 5 -[04-13_05:13:39:496] Get clientDMS = 2 -[04-13_05:13:39:527] Get clientNAS = 4 -[04-13_05:13:39:559] Get clientUIM = 1 -[04-13_05:13:39:592] Get clientWDA = 1 -[04-13_05:13:39:626] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:13:39:752] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:13:39:752] requestSetProfile[1] cmnet///0 -[04-13_05:13:39:816] requestGetProfile[1] cmnet///0 -[04-13_05:13:39:848] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:13:39:879] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:13:39:880] ifconfig wwan0 0.0.0.0 -[04-13_05:13:39:893] ifconfig wwan0 down -[04-13_05:13:39:943] requestSetupDataCall WdsConnectionIPv4Handle: 0x872627c0 -[04-13_05:13:40:073] ifconfig wwan0 up -[04-13_05:13:40:085] echo '0xa8d9237' > /sys/class/net/wwan0/bridge_ipv4 - -root@ZhuoTK:/# ifconfig br0 up -[ 165.730000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 165.750000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 165.860000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 -[ 165.870000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 -[ 165.990000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 -[ 166.010000] wwan0 sip = 0.0.0.0, tip=10.141.146.55, ipv4=10.141.146.55 -[ 166.070000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 -[ 167.010000] wwan0 sip = 0.0.0.0, tip=10.141.146.55, ipv4=10.141.146.55 -[ 167.480000] br0: port 2(wwan0) entered forwarding state -[ 167.520000] br0: port 1(eth0.1) entered forwarding state -[ 168.020000] wwan0 sip = 0.0.0.0, tip=10.141.146.55, ipv4=10.141.146.55 -[ 169.010000] wwan0 sip = 10.141.146.55, tip=10.141.146.55, ipv4=10.141.146.55 -[ 169.120000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 -[ 169.130000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 -[ 176.620000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 diff --git a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=1.txt b/quectel_cm_5G/src/log/qmi_wwan_q_qmap=1.txt deleted file mode 100644 index 9f088e5..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=1.txt +++ /dev/null @@ -1,54 +0,0 @@ -root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=1 -[ 1367.200000] usbcore: registered new interface driver qmi_wwan_q -[ 1383.840000] usb 1-1.3: new high-speed USB device number 7 using ehci-platform -[ 1384.080000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 1384.080000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode -[ 1384.100000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 -[ 1384.100000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, da:0b:ce:b2:db:21 - -root@ZhuoTK:/# quectel-CM -s cmnet & -[04-13_03:41:28:144] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:41:28:146] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x007 -[04-13_03:41:28:148] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_03:41:28:148] Auto find usbnet_adapter = wwan0 -[04-13_03:41:28:148] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_03:41:28:149] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0 -[04-13_03:41:28:150] Modem works in QMI mode -[04-13_03:41:28:158] cdc_wdm_fd = 7 -[04-13_03:41:28:238] Get clientWDS = 4 -[04-13_03:41:28:271] Get clientDMS = 1 -[04-13_03:41:28:302] Get clientNAS = 4 -[04-13_03:41:28:334] Get clientUIM = 1 -[04-13_03:41:28:365] Get clientWDA = 1 -[04-13_03:41:28:397] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:41:28:430] qmap_settings.rx_urb_size = 4096 -[ 1393.530000] net wwan0: ul_data_aggregation_max_datagrams=11, ul_data_aggregation_max_size=4096, dl_minimum_padding=0 -[04-13_03:41:28:431] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_03:41:28:431] qmap_settings.ul_data_aggregation_max_size = 4096 -[04-13_03:41:28:431] qmap_settings.dl_minimum_padding = 0 -[04-13_03:41:28:557] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:41:28:558] requestSetProfile[1] cmnet///0 -[04-13_03:41:28:622] requestGetProfile[1] cmnet///0 -[04-13_03:41:28:654] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:41:28:685] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[ 1393.790000] net wwan0: link_state 0x1 -> 0x0 -[04-13_03:41:28:692] ifconfig wwan0 0.0.0.0 -[04-13_03:41:28:703] ifconfig wwan0 down -[04-13_03:41:28:751] requestSetupDataCall WdsConnectionIPv4Handle: 0x8729a6b0 -[ 1393.980000] net wwan0: link_state 0x0 -> 0x1 -[04-13_03:41:28:882] ifconfig wwan0 up -[04-13_03:41:28:895] you are use OpenWrt? -[04-13_03:41:28:895] should not calling udhcpc manually? -[04-13_03:41:28:895] should modify /etc/config/network as below? -[04-13_03:41:28:896] config interface wan -[04-13_03:41:28:896] option ifname wwan0 -[04-13_03:41:28:896] option proto dhcp -[04-13_03:41:28:896] should use "/sbin/ifstaus wan" to check wwan0 's status? -[04-13_03:41:28:896] busybox udhcpc -f -n -q -t 5 -i wwan0 -[04-13_03:41:28:907] udhcpc (v1.23.2) started -[04-13_03:41:28:919] Sending discover... -[04-13_03:41:28:925] Sending select for 10.129.198.20... -[04-13_03:41:28:929] Lease of 10.129.198.20 obtained, lease time 7200 -[04-13_03:41:28:934] udhcpc: ifconfig wwan0 10.129.198.20 netmask 255.255.255.248 broadcast + -[04-13_03:41:28:949] udhcpc: setting default routers: 10.129.198.21 - diff --git a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=1_bridge.txt b/quectel_cm_5G/src/log/qmi_wwan_q_qmap=1_bridge.txt deleted file mode 100644 index 05919d6..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=1_bridge.txt +++ /dev/null @@ -1,86 +0,0 @@ -root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=1 -[ 49.000000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 49.000000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode -[ 49.020000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 -[ 49.020000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, de:ae:5c:82:b5:b2 -[ 49.030000] usbcore: registered new interface driver qmi_wwan_q - -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 -root@ZhuoTK:/# brctl addif br0 wwan0 -root@ZhuoTK:/# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00ca019197b9 no eth0.1 - wwan0 - -root@ZhuoTK:/# quectel-CM -s cmnet -b & -[04-13_05:11:46:442] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:11:46:444] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[ 84.340000] net wwan0: bridge_mode change to 0x1 -[04-13_05:11:46:446] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_05:11:46:446] Auto find usbnet_adapter = wwan0 -[04-13_05:11:46:446] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_05:11:46:447] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0 -[04-13_05:11:46:454] Modem works in QMI mode -[04-13_05:11:46:462] cdc_wdm_fd = 7 -[04-13_05:11:46:537] Get clientWDS = 5 -[04-13_05:11:46:569] Get clientDMS = 1 -[04-13_05:11:46:601] Get clientNAS = 4 -[04-13_05:11:46:633] Get clientUIM = 1 -[04-13_05:11:46:666] Get clientWDA = 1 -[04-13_05:11:46:697] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:11:46:730] qmap_settings.rx_urb_size = 4096 -[ 84.620000] net wwan0: ul_data_aggregation_max_datagrams=11, ul_data_aggregation_max_size=4096, dl_minimum_padding=0 -[04-13_05:11:46:730] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_05:11:46:730] qmap_settings.ul_data_aggregation_max_size = 4096 -[04-13_05:11:46:730] qmap_settings.dl_minimum_padding = 0 -[04-13_05:11:46:859] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:11:46:859] requestSetProfile[1] cmnet///0 -[04-13_05:11:46:922] requestGetProfile[1] cmnet///0 -[04-13_05:11:46:954] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:11:46:986] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[ 84.880000] net wwan0: link_state 0x1 -> 0x0 -[04-13_05:11:46:992] ifconfig wwan0 0.0.0.0 -[04-13_05:11:47:005] ifconfig wwan0 down -[04-13_05:11:47:050] requestSetupDataCall WdsConnectionIPv4Handle: 0x872a5830 -[ 85.070000] net wwan0: link_state 0x0 -> 0x1 -[04-13_05:11:47:183] ifconfig wwan0 up -[04-13_05:11:47:195] echo '0xa54a78b' > /sys/class/net/wwan0/bridge_ipv4 - -root@ZhuoTK:/# ifconfig wwan0 -wwan0 Link encap:Ethernet HWaddr DE:AE:5C:82:B5:B2 - inet6 addr: fe80::dcae:5cff:fe82:b5b2/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:3792 errors:0 dropped:0 overruns:0 frame:0 - TX packets:3271 errors:0 dropped:36 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:2271762 (2.1 MiB) TX bytes:565184 (551.9 KiB) - -root@ZhuoTK:/# ifconfig br0 up -[ 89.530000] br0: port 2(wwan0) entered forwarding state -[ 89.530000] br0: port 2(wwan0) entered forwarding state -[ 89.540000] br0: port 1(eth0.1) entered forwarding state -[ 89.540000] br0: port 1(eth0.1) entered forwarding state - -root@ZhuoTK:/# -[ 93.720000] wwan0 sip = 192.168.1.153, tip=10.84.167.140, ipv4=10.84.167.139 -[ 104.560000] br0: port 2(wwan0) entered forwarding state -[ 104.560000] br0: port 1(eth0.1) entered forwarding state -[ 111.750000] rt305x-esw 10110000.esw: link changed 0x00 -[ 116.440000] rt305x-esw 10110000.esw: link changed 0x01 -[ 116.620000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 116.680000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 116.690000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 116.760000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 117.050000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 117.220000] wwan0 sip = 0.0.0.0, tip=10.84.167.139, ipv4=10.84.167.139 -[ 117.820000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 118.220000] wwan0 sip = 0.0.0.0, tip=10.84.167.139, ipv4=10.84.167.139 -[ 118.300000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 119.220000] wwan0 sip = 0.0.0.0, tip=10.84.167.139, ipv4=10.84.167.139 -[ 120.220000] wwan0 sip = 10.84.167.139, tip=10.84.167.139, ipv4=10.84.167.139 -[ 120.300000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 121.430000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 141.730000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 144.390000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 -[ 144.510000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 diff --git a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=4.txt b/quectel_cm_5G/src/log/qmi_wwan_q_qmap=4.txt deleted file mode 100644 index 6464f27..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=4.txt +++ /dev/null @@ -1,185 +0,0 @@ -root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=4 -[ 1515.180000] usbcore: registered new interface driver qmi_wwan_q -[ 1530.260000] usb 1-1.3: new high-speed USB device number 8 using ehci-platform -[ 1530.500000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 1530.500000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode -[ 1530.520000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 -[ 1530.520000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, RMNET/USB device, da:0b:ce:b2:db:21 -[ 1530.530000] net wwan0: qmap_register_device wwan0_1 -[ 1530.540000] net wwan0: qmap_register_device wwan0_2 -[ 1530.550000] net wwan0: qmap_register_device wwan0_3 -[ 1530.550000] net wwan0: qmap_register_device wwan0_4 - -root@ZhuoTK:~# quectel-qmi-proxy & -[04-13_03:44:53:958] Will use cdc-wdm='/dev/cdc-wdm0', proxy='quectel-qmi-proxy0' -[04-13_03:44:53:959] qmi_proxy_init enter -[04-13_03:44:53:960] qmi_proxy_loop enter thread_id 0x77c07530 -[04-13_03:44:54:960] qmi_proxy_init succful -[04-13_03:44:54:960] local server: quectel-qmi-proxy0 sockfd = 4 -[04-13_03:44:54:960] qmi_proxy_server_fd = 4 -[04-13_03:45:04:346] +++ ClientFd=5 -[04-13_03:45:04:410] +++ ClientFd=5 QMIType=1 ClientId=4 -[04-13_03:45:04:442] +++ ClientFd=5 QMIType=2 ClientId=1 -[04-13_03:45:04:474] +++ ClientFd=5 QMIType=3 ClientId=4 -[04-13_03:45:04:506] +++ ClientFd=5 QMIType=11 ClientId=1 -[04-13_03:45:04:539] +++ ClientFd=5 QMIType=26 ClientId=1 -[04-13_03:45:10:770] +++ ClientFd=6 -[04-13_03:45:10:811] +++ ClientFd=6 QMIType=1 ClientId=21 -[04-13_03:45:10:843] +++ ClientFd=6 QMIType=2 ClientId=2 -[04-13_03:45:10:875] +++ ClientFd=6 QMIType=3 ClientId=5 -[04-13_03:45:10:907] +++ ClientFd=6 QMIType=11 ClientId=2 -[04-13_03:46:31:419] --- ClientFd=6 QMIType=1 ClientId=21 -[04-13_03:46:31:451] --- ClientFd=6 QMIType=2 ClientId=2 -[04-13_03:46:31:484] --- ClientFd=6 QMIType=3 ClientId=5 -[04-13_03:46:31:517] --- ClientFd=6 QMIType=11 ClientId=2 -[04-13_03:46:31:518] qmi_proxy_loop poll fd = 6, revents = 0011 -[04-13_03:46:31:519] --- ClientFd=6 - -root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & -root@ZhuoTK:/# [04-13_03:45:04:340] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:45:04:343] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x008 -[04-13_03:45:04:344] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_03:45:04:344] Auto find usbnet_adapter = wwan0 -[04-13_03:45:04:345] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_03:45:04:345] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0_1 -[04-13_03:45:04:345] Modem works in QMI mode -[04-13_03:45:04:347] connect to quectel-qmi-proxy0 sockfd = 7 -[04-13_03:45:04:347] cdc_wdm_fd = 7 -[04-13_03:45:04:411] Get clientWDS = 4 -[04-13_03:45:04:443] Get clientDMS = 1 -[04-13_03:45:04:475] Get clientNAS = 4 -[04-13_03:45:04:507] Get clientUIM = 1 -[04-13_03:45:04:540] Get clientWDA = 1 -[04-13_03:45:04:571] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:45:04:602] qmap_settings.rx_urb_size = 4096 -[ 1609.700000] net wwan0: ul_data_aggregation_max_datagrams=11, ul_data_aggregation_max_size=4096, dl_minimum_padding=0 -[04-13_03:45:04:603] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_03:45:04:603] qmap_settings.ul_data_aggregation_max_size = 4096 -[04-13_03:45:04:603] qmap_settings.dl_minimum_padding = 0 -[04-13_03:45:04:731] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:45:04:731] requestSetProfile[1] cmnet///0 -[04-13_03:45:04:795] requestGetProfile[1] cmnet///0 -[04-13_03:45:04:827] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:45:04:858] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[ 1609.960000] net wwan0: link_state 0x1 -> 0x0 -[04-13_03:45:04:865] ifconfig wwan0 down -[04-13_03:45:04:879] ifconfig wwan0_1 0.0.0.0 -[04-13_03:45:04:889] ifconfig wwan0_1 down -[04-13_03:45:04:955] requestSetupDataCall WdsConnectionIPv4Handle: 0x87253410 -[ 1610.180000] net wwan0: link_state 0x0 -> 0x1 -[04-13_03:45:05:087] ifconfig wwan0 up -[ 1610.200000] IPv6: ADDRCONF(NETDEV_UP): wwan0: link is not ready -[04-13_03:45:05:105] ifconfig wwan0_1 up -[ 1610.220000] IPv6: ADDRCONF(NETDEV_CHANGE): wwan0: link becomes ready -[04-13_03:45:05:125] you are use OpenWrt? -[04-13_03:45:05:125] should not calling udhcpc manually? -[04-13_03:45:05:125] should modify /etc/config/network as below? -[04-13_03:45:05:125] config interface wan -[04-13_03:45:05:125] option ifname wwan0_1 -[04-13_03:45:05:125] option proto dhcp -[04-13_03:45:05:126] should use "/sbin/ifstaus wan" to check wwan0_1 's status? -[04-13_03:45:05:126] busybox udhcpc -f -n -q -t 5 -i wwan0_1 -[04-13_03:45:05:136] udhcpc (v1.23.2) started -[04-13_03:45:05:148] Sending discover... -[04-13_03:45:05:155] Sending select for 10.244.10.206... -[04-13_03:45:05:160] Lease of 10.244.10.206 obtained, lease time 7200 -[04-13_03:45:05:165] udhcpc: ifconfig wwan0_1 10.244.10.206 netmask 255.255.255.252 broadcast + -[04-13_03:45:05:174] udhcpc: setting default routers: 10.244.10.205 - -root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & -[04-13_03:45:10:764] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:45:10:767] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x008 -[04-13_03:45:10:768] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_03:45:10:768] Auto find usbnet_adapter = wwan0 -[04-13_03:45:10:768] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_03:45:10:769] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = wwan0_2 -[04-13_03:45:10:769] Modem works in QMI mode -[04-13_03:45:10:771] connect to quectel-qmi-proxy0 sockfd = 7 -[04-13_03:45:10:771] cdc_wdm_fd = 7 -[04-13_03:45:10:812] Get clientWDS = 21 -[04-13_03:45:10:844] Get clientDMS = 2 -[04-13_03:45:10:876] Get clientNAS = 5 -[04-13_03:45:10:908] Get clientUIM = 2 -[04-13_03:45:10:971] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_03:45:11:099] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_03:45:11:099] requestSetProfile[2] 4gnet///0 -[04-13_03:45:11:163] requestGetProfile[2] 4gnet///0 -[04-13_03:45:11:195] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_03:45:11:227] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_03:45:11:227] ifconfig wwan0_2 0.0.0.0 -[ 1616.340000] IPv6: ADDRCONF(NETDEV_UP): wwan0_2: link is not ready -[04-13_03:45:11:246] ifconfig wwan0_2 down -[04-13_03:45:11:642] requestSetupDataCall WdsConnectionIPv4Handle: 0x87254580 -[ 1616.870000] net wwan0: link_state 0x1 -> 0x3 -[04-13_03:45:11:775] ifconfig wwan0 up -[04-13_03:45:11:785] ifconfig wwan0_2 up -[04-13_03:45:11:798] you are use OpenWrt? -[04-13_03:45:11:798] should not calling udhcpc manually? -[04-13_03:45:11:798] should modify /etc/config/network as below? -[04-13_03:45:11:798] config interface wan -[04-13_03:45:11:798] option ifname wwan0_2 -[04-13_03:45:11:798] option proto dhcp -[04-13_03:45:11:798] should use "/sbin/ifstaus wan" to check wwan0_2 's status? -[04-13_03:45:11:799] busybox udhcpc -f -n -q -t 5 -i wwan0_2 -[04-13_03:45:11:809] udhcpc (v1.23.2) started -[04-13_03:45:11:821] Sending discover... -[04-13_03:45:11:830] Sending select for 10.245.78.212... -[04-13_03:45:11:836] Lease of 10.245.78.212 obtained, lease time 7200 -[04-13_03:45:11:842] udhcpc: ifconfig wwan0_2 10.245.78.212 netmask 255.255.255.248 broadcast + -[04-13_03:45:11:852] udhcpc: setting default routers: 10.245.78.213 - -root@ZhuoTK:/# ifconfig wwan0_1 -wwan0_1 Link encap:Ethernet HWaddr DA:0B:CE:B2:DB:21 - inet addr:10.244.10.206 Mask:255.255.255.252 - inet6 addr: fe80::d80b:ceff:feb2:db21/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:4 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:640 (640.0 B) TX bytes:1344 (1.3 KiB) - -root@ZhuoTK:/# ifconfig wwan0_2 -wwan0_2 Link encap:Ethernet HWaddr DA:0B:CE:B2:DB:21 - inet addr:10.245.78.212 Mask:255.255.255.248 - inet6 addr: fe80::d80b:ceff:feb2:db21/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:8 errors:0 dropped:0 overruns:0 frame:0 - TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:1193 (1.1 KiB) TX bytes:1028 (1.0 KiB) - -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process - -root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0_1 -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=113.508 ms - -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -root@ZhuoTK:/# ip ro del 8.8.8.8/32 -RTNETLINK answers: No such process - -root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0_2 -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=111 time=123.651 ms - -root@ZhuoTK:/# quectel-CM -k 2 -[04-13_03:46:30:808] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_03:46:30:811] /proc/2834/cmdline: quectel-CM -n 2 -s 4gnet -[04-13_03:46:30:811] send SIGINT to process 2834 -[04-13_03:46:30:811] requestDeactivateDefaultPDP WdsConnectionIPv4Handle -[ 1696.460000] net wwan0: link_state 0x3 -> 0x1 -[04-13_03:46:31:361] ifconfig wwan0_2 0.0.0.0 -[04-13_03:46:31:373] ifconfig wwan0_2 down -[04-13_03:46:31:516] QmiWwanThread exit -[04-13_03:46:31:516] qmi_main exit - -root@ZhuoTK:/# ifconfig wwan0_2 -wwan0_2 Link encap:Ethernet HWaddr DA:0B:CE:B2:DB:21 - NOARP MTU:1500 Metric:1 - RX packets:16 errors:0 dropped:0 overruns:0 frame:0 - TX packets:15 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:1865 (1.8 KiB) TX bytes:1620 (1.5 KiB) diff --git a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=4_bridge.txt b/quectel_cm_5G/src/log/qmi_wwan_q_qmap=4_bridge.txt deleted file mode 100644 index 504d11a..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_q_qmap=4_bridge.txt +++ /dev/null @@ -1,132 +0,0 @@ -root@ZhuoTK:/# brctl addbr br0 -brctl: bridge br0: File exists -root@ZhuoTK:/# brctl delbr br0 -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 - -root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=4 -[ 365.340000] usbcore: registered new interface driver qmi_wwan_q -[ 380.860000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform -[ 381.100000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device -[ 381.100000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode -[ 381.120000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 -[ 381.120000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, RMNET/USB device, fa:24:73:b5:39:a8 -[ 381.130000] net wwan0: qmap_register_device wwan0_1 -[ 381.140000] net wwan0: qmap_register_device wwan0_2 -[ 381.150000] net wwan0: qmap_register_device wwan0_3 -[ 381.150000] net wwan0: qmap_register_device wwan0_4 - -root@ZhuoTK:/# brctl addbr br0 -root@ZhuoTK:/# brctl addif br0 eth0.1 -root@ZhuoTK:/# brctl addif br0 wwan0_2 -root@ZhuoTK:/# brctl show -bridge name bridge id STP enabled interfaces -br0 8000.00ca019197b9 no eth0.1 - wwan0_2 - -root@ZhuoTK:/# quectel-qmi-proxy & -[04-13_05:18:10:832] Will use cdc-wdm='/dev/cdc-wdm0', proxy='quectel-qmi-proxy0' -[04-13_05:18:10:833] qmi_proxy_init enter -[04-13_05:18:10:833] qmi_proxy_loop enter thread_id 0x77995530 -[04-13_05:18:11:833] qmi_proxy_init succful -[04-13_05:18:11:833] local server: quectel-qmi-proxy0 sockfd = 4 -[04-13_05:18:11:833] qmi_proxy_server_fd = 4 - -root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet -b & -[04-13_05:18:20:144] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:18:20:146] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 -[04-13_05:18:20:147] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_05:18:20:148] Auto find usbnet_adapter = wwan0 -[04-13_05:18:20:148] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_05:18:20:148] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = wwan0_2 -[04-13_05:18:20:149] Modem works in QMI mode -[04-13_05:18:20:150] connect to quectel-qmi-proxy0 sockfd = 7 -[04-13_05:18:20:150] cdc_wdm_fd = 7 -[04-13_05:18:20:370] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:18:20:403] qmap_settings.rx_urb_size = 4096 -[04-13_05:18:20:404] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-13_05:18:20:404] qmap_settings.ul_data_aggregation_max_size = 4096 -[04-13_05:18:20:404] qmap_settings.dl_minimum_padding = 0 -[04-13_05:18:20:530] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:18:20:530] requestSetProfile[2] 4gnet///0 -[04-13_05:18:20:594] requestGetProfile[2] 4gnet///0 -[04-13_05:18:20:626] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:18:20:657] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:18:20:658] ifconfig wwan0_2 0.0.0.0 -[04-13_05:18:20:669] ifconfig wwan0_2 down -[04-13_05:18:21:010] requestSetupDataCall WdsConnectionIPv4Handle: 0x87249650 -[ 425.100000] net wwan0: link_state 0x1 -> 0x3 -[04-13_05:18:21:143] ifconfig wwan0 up -[04-13_05:18:21:156] ifconfig wwan0_2 up -[04-13_05:18:21:168] echo '0xa8ceec7' > /sys/class/net/wwan0_2/bridge_ipv4 - -root@ZhuoTK:/# ifconfig br0 up - -[ 450.520000] br0: port 2(wwan0_2) entered forwarding state -[ 450.520000] br0: port 1(eth0.1) entered forwarding state -[ 450.770000] wwan0_2 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 450.790000] wwan0_2 PC Mac Address: 00:0e:c6:a6:6c:f1 -[ 450.840000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 450.950000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 450.950000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 451.120000] wwan0_2 sip = 0.0.0.0, tip=10.140.238.199, ipv4=10.140.238.199 -[ 451.180000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 452.120000] wwan0_2 sip = 0.0.0.0, tip=10.140.238.199, ipv4=10.140.238.199 -[ 453.080000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 453.120000] wwan0_2 sip = 0.0.0.0, tip=10.140.238.199, ipv4=10.140.238.199 -[ 454.120000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.199, ipv4=10.140.238.199 -[ 454.220000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 456.200000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 458.120000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 -[ 459.240000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 - -root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & -[04-13_05:19:21:122] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:19:21:125] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 -[04-13_05:19:21:126] Auto find qmichannel = /dev/cdc-wdm0 -[04-13_05:19:21:126] Auto find usbnet_adapter = wwan0 -[04-13_05:19:21:127] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 -[04-13_05:19:21:127] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0_1 -[04-13_05:19:21:127] Modem works in QMI mode -[04-13_05:19:21:128] connect to quectel-qmi-proxy0 sockfd = 7 -[04-13_05:19:21:129] cdc_wdm_fd = 7 -[04-13_05:19:21:331] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:19:21:459] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:19:21:459] requestSetProfile[1] cmnet///0 -[04-13_05:19:21:522] requestGetProfile[1] cmnet///0 -[04-13_05:19:21:554] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:19:21:585] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[ 485.550000] net wwan0: link_state 0x3 -> 0x2 -[04-13_05:19:21:592] ifconfig wwan0_1 0.0.0.0 -[ 485.570000] IPv6: ADDRCONF(NETDEV_UP): wwan0_1: link is not ready -[04-13_05:19:21:610] ifconfig wwan0_1 down -[04-13_05:19:21:682] requestSetupDataCall WdsConnectionIPv4Handle: 0x8725ed70 -[ 485.780000] net wwan0: link_state 0x2 -> 0x3 -[04-13_05:19:21:815] ifconfig wwan0 up -[04-13_05:19:21:826] ifconfig wwan0_1 up -[04-13_05:19:21:845] you are use OpenWrt? -[04-13_05:19:21:845] should not calling udhcpc manually? -[04-13_05:19:21:845] should modify /etc/config/network as below? -[04-13_05:19:21:845] config interface wan -[04-13_05:19:21:845] option ifname wwan0_1 -[04-13_05:19:21:845] option proto dhcp -[04-13_05:19:21:845] should use "/sbin/ifstaus wan" to check wwan0_1 's status? -[04-13_05:19:21:846] busybox udhcpc -f -n -q -t 5 -i wwan0_1 -[04-13_05:19:21:863] udhcpc (v1.23.2) started -[04-13_05:19:21:923] Sending discover... -[04-13_05:19:21:927] Sending select for 10.141.146.55... -[04-13_05:19:21:932] Lease of 10.141.146.55 obtained, lease time 7200 -[04-13_05:19:21:938] udhcpc: ifconfig wwan0_1 10.141.146.55 netmask 255.255.255.240 broadcast + -[04-13_05:19:21:949] udhcpc: setting default routers: 10.141.146.56 - -root@ZhuoTK:/# ip ro show -default via 10.141.146.56 dev wwan0_1 -10.141.146.48/28 dev wwan0_1 proto kernel scope link src 10.141.146.55 -192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 - -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=111 time=86.006 ms -64 bytes from 8.8.8.8: seq=1 ttl=111 time=74.763 ms -64 bytes from 8.8.8.8: seq=2 ttl=111 time=85.501 ms -64 bytes from 8.8.8.8: seq=3 ttl=111 time=74.231 ms diff --git a/quectel_cm_5G/src/log/qmi_wwan_qmap=4.txt b/quectel_cm_5G/src/log/qmi_wwan_qmap=4.txt deleted file mode 100644 index c0067bf..0000000 --- a/quectel_cm_5G/src/log/qmi_wwan_qmap=4.txt +++ /dev/null @@ -1,55 +0,0 @@ -# dmesg -[ 1737.738025] usb 1-1.2: new high-speed USB device number 5 using xhci-hcd -[ 1737.838917] usb 1-1.2: New USB device found, idVendor=2c7c, idProduct=0512, bcdDevice= 3.18 -[ 1737.838948] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 -[ 1737.838963] usb 1-1.2: Product: EG12-EA -[ 1737.838975] usb 1-1.2: Manufacturer: Quectel -[ 1737.838986] usb 1-1.2: SerialNumber: 0123456789ABCDE -[ 1737.994955] option 1-1.2:1.0: GSM modem (1-port) converter detected -[ 1737.995430] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB0 -[ 1737.995978] option 1-1.2:1.1: GSM modem (1-port) converter detected -[ 1737.996409] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB1 -[ 1737.996963] option 1-1.2:1.2: GSM modem (1-port) converter detected -[ 1737.997351] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB2 -[ 1737.997909] option 1-1.2:1.3: GSM modem (1-port) converter detected -[ 1737.998976] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB3 -[ 1825.835796] qmi_wwan 1-1.2:1.4: cdc-wdm0: USB WDM device -[ 1825.839685] qmi_wwan 1-1.2:1.4 wwan0: register 'qmi_wwan' at usb-fe9c0000.xhci-1.2, WWAN/QMI device, 0e:80:14:b1:f6:b9 -[ 1825.840062] usbcore: registered new interface driver qmi_wwan - -# ifconfig wwan0 down -# echo Y > /sys/class/net/wwan0/qmi/raw_ip - -# echo 1 > /sys/class/net/wwan0/qmi/add_mux -# ifconfig qmimux0 -qmimux0: flags=4240 mtu 1500 - unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC) - RX packets 0 bytes 0 (0.0 B) - RX errors 0 dropped 0 overruns 0 frame 0 - TX packets 0 bytes 0 (0.0 B) - TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 - -# echo 2 > /sys/class/net/wwan0/qmi/add_mux -# echo 3 > /sys/class/net/wwan0/qmi/add_mux -# echo 4 > /sys/class/net/wwan0/qmi/add_mux -# ifconfig qmimux3 -qmimux3: flags=4240 mtu 1500 - unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC) - RX packets 0 bytes 0 (0.0 B) - RX errors 0 dropped 0 overruns 0 frame 0 - TX packets 0 bytes 0 (0.0 B) - TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 - -set wwan0's mtu to max qmap packet size, for usbnet.c:usbnet_change_mtu() do not accept -# ifconfig wwan0 mtu 16385 - -run qmi proxy programm, -# quectel-CM/quectel-qmi-proxy -d /dev/cdc-wdm0 -or libqmi's qmi-proxy, if use libqmi's qmi-proxy, you can use qmicli to setup data call. -# /usr/libexec/qmi-proxy --verbose --no-exit - -use quectel-CM to setup data call, if use libqmi's qmi-proxy, use '-p qmi-proxy' instead of '-p quectel-qmi-proxy' -# quectel-CM -p quectel-qmi-proxy -n 4 -s cmnet4 -# quectel-CM -p quectel-qmi-proxy -n 1 -s cmnet - -for how to use libqmi to setup data call, please refer to https://knowledge.quectel.com/display/SWSYSTLinuxAndroid/libqmi_How+to+using+QMAP+multiplexing \ No newline at end of file diff --git a/quectel_cm_5G/src/log/usage_of_argument/6.txt b/quectel_cm_5G/src/log/usage_of_argument/6.txt deleted file mode 100644 index 5ab9533..0000000 --- a/quectel_cm_5G/src/log/usage_of_argument/6.txt +++ /dev/null @@ -1,68 +0,0 @@ -root@OpenWrt:~# quectel-CM -s cmnet -4 -6 -[04-14_06:56:51:778] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-14_06:56:51:779] network interface '' or qmidev '' is not exist -[04-14_06:56:51:780] netcard driver = pcie_mhi, driver version = V1.3.0.17 -[04-14_06:56:51:781] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 -[04-14_06:56:51:782] Modem works in QMI mode -[04-14_06:56:51:783] connect to quectel-qmi-proxy0 sockfd = 7 -[04-14_06:56:51:783] cdc_wdm_fd = 7 -[04-14_06:56:51:789] Get clientWDS = 15 -[04-14_06:56:51:792] Get clientWDS = 16 -[04-14_06:56:51:794] Get clientDMS = 3 -[04-14_06:56:51:798] Get clientNAS = 4 -[04-14_06:56:51:801] Get clientUIM = 1 -[04-14_06:56:51:805] Get clientWDA = 1 -[04-14_06:56:51:809] requestBaseBandVersion RM500QGLABR10A03M4G -[04-14_06:56:51:813] qmap_settings.rx_urb_size = 16384 -[04-14_06:56:51:813] qmap_settings.ul_data_aggregation_max_datagrams = 11 -[04-14_06:56:51:814] qmap_settings.ul_data_aggregation_max_size = 8192 -[04-14_06:56:51:814] qmap_settings.dl_minimum_padding = 0 -[04-14_06:56:51:835] requestGetSIMStatus SIMStatus: SIM_READY -[04-14_06:56:51:836] requestSetProfile[1] cmnet///0 -[04-14_06:56:51:848] requestGetProfile[1] cmnet///0 -[04-14_06:56:51:852] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA -[04-14_06:56:51:857] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-14_06:56:51:860] requestQueryDataCall IPv6ConnectionStatus: DISCONNECTED -[04-14_06:56:51:861] ifconfig rmnet_mhi0 down -[04-14_06:56:51:885] ifconfig rmnet_mhi0.1 0.0.0.0 -ifconfig: SIOCSIFFLAGS: Network is down -[04-14_06:56:51:909] ifconfig rmnet_mhi0.1 down -[04-14_06:56:51:943] requestSetupDataCall WdsConnectionIPv4Handle: 0x341450a0 -[04-14_06:56:52:423] requestSetupDataCall WdsConnectionIPv6Handle: 0x341439f0 -[ 1001.561353] net rmnet_mhi0: link_state 0x0 -> 0x1 -[04-14_06:56:52:441] ifconfig rmnet_mhi0 up -[ 1001.584623] [I][mhi_netdev_open] Opened net dev interface -[04-14_06:56:52:467] ifconfig rmnet_mhi0.1 up -[04-14_06:56:52:495] you are use OpenWrt? -[04-14_06:56:52:496] should not calling udhcpc manually? -[04-14_06:56:52:496] should modify /etc/config/network as below? -[04-14_06:56:52:497] config interface wan -[04-14_06:56:52:497] option ifname rmnet_mhi0.1 -[04-14_06:56:52:497] option proto dhcp -[04-14_06:56:52:498] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? -[04-14_06:56:52:498] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 -udhcpc: started, v1.28.3 -udhcpc: sending discover -udhcpc: sending select for 10.245.22.3 -udhcpc: lease of 10.245.22.3 obtained, lease time 7200 -[04-14_06:56:52:713] udhcpc: ifconfig rmnet_mhi0.1 10.245.22.3 netmask 255.255.255.248 broadcast + -[04-14_06:56:52:754] udhcpc: setting default routers: 10.245.22.4 -[04-14_06:56:52:838] ip -6 address flush dev rmnet_mhi0.1 -[04-14_06:56:52:861] ip -6 address add 2409:8930:463:3daa:7c8e:429a:c902:c6cc/64 dev rmnet_mhi0.1 -[04-14_06:56:52:884] ip -6 route add default dev rmnet_mhi0.1 - -root@OpenWrt:~# cat /etc/resolv.conf -nameserver 2409:8030:2000:0:0:0:0:1 # IPV6 rmnet_mhi0.1 -nameserver 2409:8030:2000:0:0:0:0:2 # IPV6 rmnet_mhi0.1 -search lan -nameserver 127.0.0.1 - -root@OpenWrt:~# ip -6 ro show -2409:8930:463:96df::/64 dev rmnet_mhi0.1 proto kernel metric 256 -fe80::/64 dev br-lan proto kernel metric 256 -fe80::/64 dev br0 proto kernel metric 256 -default dev rmnet_mhi0.1 metric 1024 - -root@OpenWrt:~# ping6 www.qq.com -PING www.qq.com (2402:4e00:1430:1301::9227:79cc:76f2): 56 data bytes -64 bytes from 2402:4e00:1430:1301::9227:79cc:76f2: seq=0 ttl=51 time=97.230 ms diff --git a/quectel_cm_5G/src/log/usage_of_argument/m.txt b/quectel_cm_5G/src/log/usage_of_argument/m.txt deleted file mode 100644 index c4c46b8..0000000 --- a/quectel_cm_5G/src/log/usage_of_argument/m.txt +++ /dev/null @@ -1,58 +0,0 @@ -root@ZhuoTK:/# quectel-CM -n 1 -m 4 -s cmnet & -[04-13_05:12:07:455] Quectel_QConnectManager_Linux_V1.6.0.25 -[04-13_05:12:07:458] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 -[04-13_05:12:07:459] Auto find qmichannel = /dev/qcqmi0 -[04-13_05:12:07:459] Auto find usbnet_adapter = usb0 -[04-13_05:12:07:467] netcard driver = GobiNet, driver version = V1.6.2.13 -[04-13_05:12:07:467] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x84, qmap_netcard = usb0.4 -[04-13_05:12:07:467] Modem works in QMI mode -[04-13_05:12:07:495] Get clientWDS = 7 -[04-13_05:12:07:529] Get clientDMS = 8 -[04-13_05:12:07:561] Get clientNAS = 9 -[04-13_05:12:07:591] Get clientUIM = 10 -[04-13_05:12:07:623] requestBaseBandVersion EC25EFAR06A11M4G -[04-13_05:12:07:752] requestGetSIMStatus SIMStatus: SIM_READY -[04-13_05:12:07:752] requestSetProfile[1] cmnet///0 -[04-13_05:12:07:817] requestGetProfile[1] cmnet///0 -[04-13_05:12:07:849] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE -[04-13_05:12:07:881] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED -[04-13_05:12:07:881] ifconfig usb0 down -[04-13_05:12:07:892] ifconfig usb0.4 0.0.0.0 -[04-13_05:12:07:903] ifconfig usb0.4 down -[04-13_05:12:07:944] requestSetupDataCall WdsConnectionIPv4Handle: 0x87265c40 -[ 52.020000] net usb0: link_state 0x0 -> 0x8 -[04-13_05:12:08:077] ifconfig usb0 up -[04-13_05:12:08:096] ifconfig usb0.4 up -[04-13_05:12:08:116] you are use OpenWrt? -[04-13_05:12:08:116] should not calling udhcpc manually? -[04-13_05:12:08:116] should modify /etc/config/network as below? -[04-13_05:12:08:116] config interface wan -[04-13_05:12:08:116] option ifname usb0.4 -[04-13_05:12:08:116] option proto dhcp -[04-13_05:12:08:116] should use "/sbin/ifstaus wan" to check usb0.4 's status? -[04-13_05:12:08:117] busybox udhcpc -f -n -q -t 5 -i usb0.4 -[04-13_05:12:08:134] udhcpc (v1.23.2) started -[04-13_05:12:08:193] Sending discover... -[04-13_05:12:08:197] Sending select for 10.84.241.180... -[04-13_05:12:08:203] Lease of 10.84.241.180 obtained, lease time 7200 -[04-13_05:12:08:208] udhcpc: ifconfig usb0.4 10.84.241.180 netmask 255.255.255.248 broadcast + -[04-13_05:12:08:221] udhcpc: setting default routers: 10.84.241.181 - -root@ZhuoTK:/# ifconfig usb0.4 -usb0.4 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 - inet addr:10.84.241.180 Mask:255.255.255.248 - inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link - UP RUNNING NOARP MTU:1500 Metric:1 - RX packets:2 errors:0 dropped:0 overruns:0 frame:0 - TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 - collisions:0 txqueuelen:1000 - RX bytes:612 (612.0 B) TX bytes:984 (984.0 B) - -root@ZhuoTK:/# ip ro show -default via 10.84.241.181 dev usb0.4 -10.84.241.176/29 dev usb0.4 proto kernel scope link src 10.84.241.180 -192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 - -root@ZhuoTK:/# ping 8.8.8.8 -PING 8.8.8.8 (8.8.8.8): 56 data bytes -64 bytes from 8.8.8.8: seq=0 ttl=52 time=99.431 ms diff --git a/quectel_cm_5G/src/main.c b/quectel_cm_5G/src/main.c deleted file mode 100644 index e39a5f3..0000000 --- a/quectel_cm_5G/src/main.c +++ /dev/null @@ -1,934 +0,0 @@ -/****************************************************************************** - @file main.c - @brief The entry program. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 -2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - -#include "QMIThread.h" -#include -#include -#include -#include - -#include "util.h" -//#define CONFIG_PID_FILE_FORMAT "/var/run/quectel-CM-%s.pid" //for example /var/run/quectel-CM-wwan0.pid - -static PROFILE_T s_profile; -int debug_qmi = 0; -int qmidevice_control_fd[2]; -static int signal_control_fd[2]; -int g_donot_exit_when_modem_hangup = 0; -extern int ql_ifconfig(int argc, char *argv[]); -extern int ql_get_netcard_driver_info(const char*); -extern int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path); -extern void ql_stop_usbmon_log(PROFILE_T *profile); -//UINT ifc_get_addr(const char *ifname); -static int s_link = -1; -static void usbnet_link_change(int link, PROFILE_T *profile) { - if (s_link == link) - return; - - s_link = link; - - if (!(link & (1<ipv4, 0, sizeof(IPV4_T)); - - if (!(link & (1<ipv6, 0, sizeof(IPV6_T)); - - if (link) { - udhcpc_start(profile); - } else { - udhcpc_stop(profile); - } -} - -static int check_ipv4_address(PROFILE_T *profile) { - uint32_t oldAddress = profile->ipv4.Address; - - if (profile->request_ops == &mbim_request_ops) - return 1; //we will get a new ipv6 address per requestGetIPAddress() - if (profile->request_ops == &atc_request_ops) - return 1; //TODO - - if (profile->request_ops->requestGetIPAddress(profile, IpFamilyV4) == 0) { - if (profile->ipv4.Address != oldAddress || debug_qmi) { - unsigned char *l = (unsigned char *)&oldAddress; - unsigned char *r = (unsigned char *)&profile->ipv4.Address; - dbg_time("localIP: %d.%d.%d.%d VS remoteIP: %d.%d.%d.%d", - l[3], l[2], l[1], l[0], r[3], r[2], r[1], r[0]); - } - return (profile->ipv4.Address == oldAddress); - } - - return 0; -} - -static void main_send_event_to_qmidevice(int triger_event) { - if (write(qmidevice_control_fd[0], &triger_event, sizeof(triger_event)) == -1) {}; -} - -static void send_signo_to_main(int signo) { - if (write(signal_control_fd[0], &signo, sizeof(signo)) == -1) {}; -} - -void qmidevice_send_event_to_main(int triger_event) { - if (write(qmidevice_control_fd[1], &triger_event, sizeof(triger_event)) == -1) {}; -} - -void qmidevice_send_event_to_main_ext(int triger_event, void *data, unsigned len) { - if (write(qmidevice_control_fd[1], &triger_event, sizeof(triger_event)) == -1) {}; - if (write(qmidevice_control_fd[1], data, len) == -1) {}; -} - -#define MAX_PATH 256 - -static int ls_dir(const char *dir, int (*match)(const char *dir, const char *file, void *argv[]), void *argv[]) -{ - DIR *pDir; - struct dirent* ent = NULL; - int match_times = 0; - - pDir = opendir(dir); - if (pDir == NULL) { - dbg_time("Cannot open directory: %s, errno: %d (%s)", dir, errno, strerror(errno)); - return 0; - } - - while ((ent = readdir(pDir)) != NULL) { - match_times += match(dir, ent->d_name, argv); - } - closedir(pDir); - - return match_times; -} - -static int is_same_linkfile(const char *dir, const char *file, void *argv[]) -{ - const char *qmichannel = (const char *)argv[1]; - char linkname[MAX_PATH*2+6]; - char filename[MAX_PATH]; - int linksize; - - snprintf(linkname, sizeof(linkname), "%.256s/%s", dir, file); - linksize = readlink(linkname, filename, sizeof(filename)); - if (linksize <= 0) - return 0; - - filename[linksize] = 0; - if (strcmp(filename, qmichannel)) - return 0; - - dbg_time("%s -> %s", linkname, filename); - return 1; -} - -static int is_brother_process(const char *dir, const char *file, void *argv[]) -{ - //const char *myself = (const char *)argv[0]; - char linkname[MAX_PATH*2+6]; - char filename[MAX_PATH]; - int linksize; - int i = 0, kill_timeout = 15; - pid_t pid; - - //dbg_time("%s", file); - while (file[i]) { - if (!isdigit(file[i])) - break; - i++; - } - - if (file[i]) { - //dbg_time("%s not digit", file); - return 0; - } - - snprintf(linkname, sizeof(linkname), "%s/%s/exe", dir, file); - linksize = readlink(linkname, filename, sizeof(filename)); - if (linksize <= 0) - return 0; - - filename[linksize] = 0; - - pid = atoi(file); - if (pid >= getpid()) - return 0; - - snprintf(linkname, sizeof(linkname), "%s/%s/fd", dir, file); - if (!ls_dir(linkname, is_same_linkfile, argv)) - return 0; - - dbg_time("%s/%s/exe -> %s", dir, file, filename); - while (kill_timeout-- && !kill(pid, 0)) - { - kill(pid, SIGTERM); - sleep(1); - } - if (!kill(pid, 0)) - { - dbg_time("force kill %s/%s/exe -> %s", dir, file, filename); - kill(pid, SIGKILL); - sleep(1); - } - - return 1; -} - -static int kill_brothers(const char *qmichannel) -{ - char myself[MAX_PATH]; - int filenamesize; - void *argv[2] = {myself, (void *)qmichannel}; - - filenamesize = readlink("/proc/self/exe", myself, sizeof(myself)); - if (filenamesize <= 0) - return 0; - myself[filenamesize] = 0; - - if (ls_dir("/proc", is_brother_process, argv)) - sleep(1); - - return 0; -} - -static int kill_data_call_pdp(int pdp, char *self) { - int pid; - char *p = NULL; - - p = self; - while (*self) { - if (*self == '/') - p = self+1; - self++; - } - - pid = getpid_by_pdp(pdp, p); - if (pid > 0) { - dbg_time("send SIGINT to process %d", pid); - return kill(pid, SIGINT); - } - - return -1; -} - -static void ql_sigaction(int signo) { - if (SIGALRM == signo) - send_signo_to_main(SIG_EVENT_START); - else - { - g_donot_exit_when_modem_hangup = 0; - send_signo_to_main(SIG_EVENT_STOP); - main_send_event_to_qmidevice(SIG_EVENT_STOP); //main may be wating qmi response - } -} - -static int usage(const char *progname) { - dbg_time("Usage: %s [options]", progname); - dbg_time("-s [apn [user password auth]] Set apn/user/password/auth get from your network provider. auth: 1~pap, 2~chap, 3~MsChapV2"); - dbg_time("-p pincode Verify sim card pin if sim card is locked"); - dbg_time("-p [quectel-][qmi|mbim]-proxy Request to use proxy"); - dbg_time("-f logfilename Save log message of this program to file"); - dbg_time("-u usbmonlog filename Save usbmon log to file"); - dbg_time("-i interface Specify which network interface to setup data call when multi-modems exits"); - dbg_time("-4 Setup IPv4 data call (default)"); - dbg_time("-6 Setup IPv6 data call"); - dbg_time("-n pdn Specify which pdn to setup data call (default 1 for QMI, 0 for MBIM)"); - dbg_time("-k pdn Specify which pdn to hangup data call (by send SIGINT to 'quectel-CM -n pdn')"); - dbg_time("-m iface-idx Bind QMI data call to wwan0_ when QMAP used. E.g '-n 7 -m 1' bind pdn-7 data call to wwan0_1"); - dbg_time("-b Enable network interface bridge function (default 0)"); - dbg_time("-v Verbose log mode, for debug purpose."); - dbg_time("[Examples]"); - dbg_time("Example 1: %s ", progname); - dbg_time("Example 2: %s -s 3gnet ", progname); - dbg_time("Example 3: %s -s 3gnet carl 1234 1 -p 1234 -f gobinet_log.txt", progname); - return 0; -} - -static int qmi_main(PROFILE_T *profile) -{ - int triger_event = 0; - int signo; -#ifdef CONFIG_SIM - SIM_Status SIMStatus = SIM_ABSENT; -#endif - UCHAR PSAttachedState = 0; - UCHAR IPv4ConnectionStatus = QWDS_PKT_DATA_UNKNOW; - UCHAR IPv6ConnectionStatus = QWDS_PKT_DATA_UNKNOW; - unsigned SetupCallFail = 0; - unsigned long SetupCallAllowTime = clock_msec(); -#ifdef REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS - unsigned PsAttachFail = 0; - unsigned long PsAttachTime = clock_msec(); -#endif - int qmierr = 0; - const struct request_ops *request_ops = profile ->request_ops; - pthread_t gQmiThreadID = 0; - -//sudo apt-get install udhcpc -//sudo apt-get remove ModemManager - if (profile->reattach_flag) { - if (!reattach_driver(profile)) - sleep(2); - } - - /* try to recreate FDs*/ - if (socketpair( AF_LOCAL, SOCK_STREAM, 0, signal_control_fd) < 0 ) { - dbg_time("%s Faild to create main_control_fd: %d (%s)", __func__, errno, strerror(errno)); - return -1; - } - - if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, qmidevice_control_fd ) < 0 ) { - dbg_time("%s Failed to create thread control socket pair: %d (%s)", __func__, errno, strerror(errno)); - return 0; - } - - if ((profile->qmap_mode == 0 || profile->qmap_mode == 1) - && (!profile->proxy[0] || strstr(profile->qmichannel, "_IPCR"))) { - kill_brothers(profile->qmichannel); - } - - if (pthread_create( &gQmiThreadID, 0, profile->qmi_ops->read, (void *)profile) != 0) { - dbg_time("%s Failed to create QMIThread: %d (%s)", __func__, errno, strerror(errno)); - return 0; - } - - if ((read(qmidevice_control_fd[0], &triger_event, sizeof(triger_event)) != sizeof(triger_event)) - || (triger_event != RIL_INDICATE_DEVICE_CONNECTED)) { - dbg_time("%s Failed to init QMIThread: %d (%s)", __func__, errno, strerror(errno)); - return 0; - } - - if (profile->qmi_ops->init && profile->qmi_ops->init(profile)) { - dbg_time("%s Failed to qmi init: %d (%s)", __func__, errno, strerror(errno)); - return 0; - } - - if (request_ops->requestBaseBandVersion) - request_ops->requestBaseBandVersion(profile); - - if (request_ops->requestSetEthMode) - request_ops->requestSetEthMode(profile); - - if (request_ops->requestSetLoopBackState && profile->loopback_state) { - qmierr = request_ops->requestSetLoopBackState(profile->loopback_state, profile->replication_factor); - if (qmierr != QMI_ERR_INVALID_QMI_CMD) //X20 return this error - profile->loopback_state = 0; //wait for RIL_UNSOL_LOOPBACK_CONFIG_IND - } - - if (request_ops->requestGetSIMStatus) { - qmierr = request_ops->requestGetSIMStatus(&SIMStatus); - - while (qmierr == QMI_ERR_OP_DEVICE_UNSUPPORTED) { - sleep(1); - qmierr = request_ops->requestGetSIMStatus(&SIMStatus); - } - - if ((SIMStatus == SIM_PIN) && profile->pincode && request_ops->requestEnterSimPin) { - request_ops->requestEnterSimPin(profile->pincode); - } - } - - if (SIMStatus == SIM_READY) { - if (request_ops->requestGetICCID) - request_ops->requestGetICCID(); - - if (request_ops->requestGetIMSI) - request_ops->requestGetIMSI(); - } - - if (request_ops->requestGetProfile) - request_ops->requestGetProfile(profile); - - if (request_ops->requestSetProfile && (profile->apn || profile->user || profile->password)) { - if (request_ops->requestSetProfile(profile) == 1) { -#ifdef REBOOT_SIM_CARD_WHEN_APN_CHANGE //enable at only when customer asked - if (request_ops->requestRadioPower) { - request_ops->requestRadioPower(0); - request_ops->requestRadioPower(1); - } -#endif - } - } - - request_ops->requestRegistrationState(&PSAttachedState); - -#ifdef CONFIG_ENABLE_QOS - request_ops->requestRegisterQos(profile); -#endif - - send_signo_to_main(SIG_EVENT_CHECK); - - while (1) - { - struct pollfd pollfds[] = {{signal_control_fd[1], POLLIN, 0}, {qmidevice_control_fd[0], POLLIN, 0}}; - int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]); - - do { - ret = poll(pollfds, nevents, 15*1000); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0) - { - send_signo_to_main(SIG_EVENT_CHECK); - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - goto __main_quit; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - main_send_event_to_qmidevice(RIL_REQUEST_QUIT); - if (revents & POLLHUP) - goto __main_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == signal_control_fd[1]) - { - if (read(fd, &signo, sizeof(signo)) == sizeof(signo)) - { - alarm(0); - switch (signo) - { - case SIG_EVENT_START: - if (PSAttachedState != 1 && profile->loopback_state == 0) - break; - - if (SetupCallAllowTime > clock_msec()) { - alarm((SetupCallAllowTime - clock_msec()+999)/1000); - break; - } - - if (profile->enable_ipv4 && IPv4ConnectionStatus != QWDS_PKT_DATA_CONNECTED) { - qmierr = request_ops->requestSetupDataCall(profile, IpFamilyV4); - - if ((qmierr > 0) && profile->user && profile->user[0] && profile->password && profile->password[0]) { - int old_auto = profile->auth; - - //may be fail because wrong auth mode, try pap->chap, or chap->pap - profile->auth = (profile->auth == 1) ? 2 : 1; - qmierr = request_ops->requestSetupDataCall(profile, IpFamilyV4); - - if (qmierr) - profile->auth = old_auto; //still fail, restore old auth moe - } - - if (!qmierr) { - qmierr = request_ops->requestGetIPAddress(profile, IpFamilyV4); - if (!qmierr) - IPv4ConnectionStatus = QWDS_PKT_DATA_CONNECTED; - } - - } - - if (profile->enable_ipv6 && IPv6ConnectionStatus != QWDS_PKT_DATA_CONNECTED) { - if (profile->enable_ipv4 && profile->request_ops != &qmi_request_ops) { - IPv6ConnectionStatus = IPv4ConnectionStatus; - } - else { - qmierr = request_ops->requestSetupDataCall(profile, IpFamilyV6); - - if (!qmierr) { - qmierr = request_ops->requestGetIPAddress(profile, IpFamilyV6); - if (!qmierr) - IPv6ConnectionStatus = QWDS_PKT_DATA_CONNECTED; - } - } - } - - if ((profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) - || (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) { - const unsigned allow_time[] = {5, 10, 20, 40, 60}; - - if (SetupCallFail < (sizeof(allow_time)/sizeof(unsigned))) - SetupCallAllowTime = allow_time[SetupCallFail]; - else - SetupCallAllowTime = 60; - SetupCallFail++; - dbg_time("try to requestSetupDataCall %ld second later", SetupCallAllowTime); - alarm(SetupCallAllowTime); - SetupCallAllowTime = SetupCallAllowTime*1000 + clock_msec(); - } - else if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) { - SetupCallFail = 0; - SetupCallAllowTime = clock_msec(); - } - break; - - case SIG_EVENT_CHECK: - if (request_ops->requestGetSignalInfo) - request_ops->requestGetSignalInfo(); - - if (request_ops->requestGetCellInfoList) - request_ops->requestGetCellInfoList(); - - if (request_ops->requestGetCoexWWANState) - request_ops->requestGetCoexWWANState(); - - if (PSAttachedState != 1) - request_ops->requestRegistrationState(&PSAttachedState); - -#ifdef REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS - if (PSAttachedState) { - PsAttachTime = clock_msec(); - PsAttachFail = 0; - } - else { - unsigned long diff = (clock_msec() - PsAttachTime) / 1000; - unsigned long threshold = REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS << PsAttachFail; - - if (diff > threshold || diff > 960) { - //interval time is 60 -> 120 - > 240 - > 480 -> 960 - PsAttachTime = clock_msec(); - PsAttachFail++; - - if (request_ops->requestRadioPower) { - request_ops->requestRadioPower(0); - request_ops->requestRadioPower(1); - } - } - } -#endif - - if (profile->enable_ipv4 && IPv4ConnectionStatus != QWDS_PKT_DATA_DISCONNECTED - && !request_ops->requestQueryDataCall(&IPv4ConnectionStatus, IpFamilyV4)) - { - if (QWDS_PKT_DATA_CONNECTED == IPv4ConnectionStatus && profile->ipv4.Address == 0) { - //killall -9 quectel-CM for MBIM and ATC call - qmierr = request_ops->requestGetIPAddress(profile, IpFamilyV4); - if (qmierr) - IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - - //local ip is different with remote ip - if (QWDS_PKT_DATA_CONNECTED == IPv4ConnectionStatus && check_ipv4_address(profile) == 0) { - request_ops->requestDeactivateDefaultPDP(profile, IpFamilyV4); - IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - } - else { - IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - - if (profile->enable_ipv6 && IPv6ConnectionStatus != QWDS_PKT_DATA_DISCONNECTED) { - if (profile->enable_ipv4 && profile->request_ops != &qmi_request_ops) { - IPv6ConnectionStatus = IPv4ConnectionStatus; - } - else { - request_ops->requestQueryDataCall(&IPv6ConnectionStatus, IpFamilyV6); - } - } - else { - IPv6ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - } - - if (IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) { - usbnet_link_change(0, profile); - } - else if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) { - int link = 0; - if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED) - link |= (1<enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) - || (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) { - send_signo_to_main(SIG_EVENT_START); - } - break; - - case SIG_EVENT_STOP: - if (profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED) { - request_ops->requestDeactivateDefaultPDP(profile, IpFamilyV4); - } - if (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) { - if (profile->enable_ipv4 && profile->request_ops != &qmi_request_ops) { - - } - else { - request_ops->requestDeactivateDefaultPDP(profile, IpFamilyV6); - } - } - usbnet_link_change(0, profile); - if (profile->qmi_ops->deinit) - profile->qmi_ops->deinit(); - main_send_event_to_qmidevice(RIL_REQUEST_QUIT); - goto __main_quit; - break; - - default: - break; - } - } - } - - if (fd == qmidevice_control_fd[0]) { - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - switch (triger_event) { - case RIL_INDICATE_DEVICE_DISCONNECTED: - usbnet_link_change(0, profile); - goto __main_quit; - break; - - case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: - request_ops->requestRegistrationState(&PSAttachedState); - if (PSAttachedState == 1) { - if ((profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) - || (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) { - send_signo_to_main(SIG_EVENT_START); - } - } else { - SetupCallAllowTime = clock_msec(); - } - break; - - case RIL_UNSOL_DATA_CALL_LIST_CHANGED: - if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) { - SetupCallAllowTime = clock_msec() + 1000; //from connect -> disconnect, do not re-dail immediately, wait network stable - } - send_signo_to_main(SIG_EVENT_CHECK); - break; - - case MODEM_REPORT_RESET_EVENT: - { - dbg_time("main recv MODEM RESET SIGNAL"); - main_send_event_to_qmidevice(RIL_REQUEST_QUIT); - g_donot_exit_when_modem_hangup = 1; - goto __main_quit; - } - break; - - case RIL_UNSOL_LOOPBACK_CONFIG_IND: - { - QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd; - if (read(fd, &SetLoopBackInd, sizeof(SetLoopBackInd)) == sizeof(SetLoopBackInd)) { - profile->loopback_state = SetLoopBackInd.loopback_state.TLVVaule; - profile->replication_factor = le32_to_cpu(SetLoopBackInd.replication_factor.TLVVaule); - dbg_time("SetLoopBackInd: loopback_state=%d, replication_factor=%u", - profile->loopback_state, profile->replication_factor); - if (profile->loopback_state) - send_signo_to_main(SIG_EVENT_START); - } - } - break; -#ifdef CONFIG_REG_QOS_IND - case RIL_UNSOL_GLOBAL_QOS_FLOW_IND_QOS_ID: - { - UINT qos_id = 0; - if (read(fd, &qos_id, sizeof(qos_id)) == sizeof(qos_id)) { - profile->qos_id = qos_id; - } - } - break; -#endif - default: - break; - } - } - } - } - } - -__main_quit: - usbnet_link_change(0, profile); - if (gQmiThreadID && pthread_join(gQmiThreadID, NULL)) { - dbg_time("%s Error joining to listener thread (%s)", __func__, strerror(errno)); - } - - close(signal_control_fd[0]); - close(signal_control_fd[1]); - close(qmidevice_control_fd[0]); - close(qmidevice_control_fd[1]); - dbg_time("%s exit", __func__); - - return 0; -} - -static int quectel_CM(PROFILE_T *profile) -{ - int ret = 0; - char qmichannel[32] = {'\0'}; - char usbnet_adapter[32] = {'\0'}; - - if (profile->expect_adapter[0]) - strncpy(usbnet_adapter, profile->expect_adapter, sizeof(usbnet_adapter)); - - if (qmidevice_detect(qmichannel, usbnet_adapter, sizeof(qmichannel), profile)) { - profile->hardware_interface = HARDWARE_USB; - } - else if (mhidevice_detect(qmichannel, usbnet_adapter, profile)) { - profile->hardware_interface = HARDWARE_PCIE; - } - else if (atdevice_detect(qmichannel, usbnet_adapter, profile)) { - profile->hardware_interface = HARDWARE_PCIE; - } -#ifdef CONFIG_QRTR - else if (1) { - strcpy(qmichannel, "qrtr"); - strcpy(usbnet_adapter, "rmnet_mhi0"); - profile->hardware_interface = HARDWARE_PCIE; - profile->software_interface = SOFTWARE_QRTR; - } -#endif - else { - dbg_time("qmidevice_detect failed"); - goto error; - } - - strncpy(profile->qmichannel, qmichannel, sizeof(profile->qmichannel)); - strncpy(profile->usbnet_adapter, usbnet_adapter, sizeof(profile->usbnet_adapter)); - ql_get_netcard_driver_info(profile->usbnet_adapter); - - if ((profile->hardware_interface == HARDWARE_USB) && profile->usblogfile) - ql_capture_usbmon_log(profile, profile->usblogfile); - - if (profile->hardware_interface == HARDWARE_USB) { - profile->software_interface = get_driver_type(profile); - } - - ql_qmap_mode_detect(profile); - - if (profile->software_interface == SOFTWARE_MBIM) { - dbg_time("Modem works in MBIM mode"); - profile->request_ops = &mbim_request_ops; - profile->qmi_ops = &mbim_dev_ops; - ret = qmi_main(profile); - } - else if (profile->software_interface == SOFTWARE_QMI) { - dbg_time("Modem works in QMI mode"); - profile->request_ops = &qmi_request_ops; - if (qmidev_is_gobinet(profile->qmichannel)) - profile->qmi_ops = &gobi_qmidev_ops; - else - profile->qmi_ops = &qmiwwan_qmidev_ops; - qmidev_send = profile->qmi_ops->send; - ret = qmi_main(profile); - } - else if (profile->software_interface == SOFTWARE_ECM_RNDIS_NCM) { - dbg_time("Modem works in ECM_RNDIS_NCM mode"); - profile->request_ops = &atc_request_ops; - profile->qmi_ops = &atc_dev_ops; - ret = qmi_main(profile); - } -#ifdef CONFIG_QRTR - else if (profile->software_interface == SOFTWARE_QRTR) { - dbg_time("Modem works in QRTR mode"); - profile->request_ops = &qmi_request_ops; - profile->qmi_ops = &qrtr_qmidev_ops; - qmidev_send = profile->qmi_ops->send; - ret = qmi_main(profile); - } -#endif - else { - dbg_time("unsupport software_interface %d", profile->software_interface); - } - - ql_stop_usbmon_log(profile); - -error: - return ret; -} - -static int parse_user_input(int argc, char **argv, PROFILE_T *profile) { - int opt = 1; - - profile->pdp = CONFIG_DEFAULT_PDP; - - if (!strcmp(argv[argc-1], "&")) - argc--; - -#define has_more_argv() ((opt < argc) && (argv[opt][0] != '-')) - while (opt < argc) { - if (argv[opt][0] != '-') { - return usage(argv[0]); - } - - switch (argv[opt++][1]) - { - case 's': - profile->apn = profile->user = profile->password = ""; - if (has_more_argv()) { - profile->apn = argv[opt++]; - } - if (has_more_argv()) { - profile->user = argv[opt++]; - } - if (has_more_argv()) { - profile->password = argv[opt++]; - if (profile->password && profile->password[0]) - profile->auth = 2; //default chap, customers may miss auth - } - if (has_more_argv()) { - const char *auth = argv[opt++]; - - if (!strcmp(auth, "0") || !strcasecmp(auth, "none")) { - profile->auth = 0; - } - else if (!strcmp(auth, "1") || !strcasecmp(auth, "pap")) { - profile->auth = 1; - } - else if (!strcmp(auth, "2") || !strcasecmp(auth, "chap")) { - profile->auth = 2; - } - else if (!strcmp(auth, "3") || !strcasecmp(auth, "MsChapV2")) { - profile->auth = 3; - } - else { - dbg_time("unknow auth '%s'", auth); - return usage(argv[0]); - } - } - break; - - case 'p': - if (has_more_argv()) { - const char *arg = argv[opt++]; - - if (!strcmp(arg, QUECTEL_QMI_PROXY) || !strcmp(arg, QUECTEL_MBIM_PROXY) - || !strcmp(arg, LIBQMI_PROXY) || !strcmp(arg, LIBMBIM_PROXY) || !strcmp(arg, QUECTEL_ATC_PROXY)) { - strncpy(profile->proxy, arg, sizeof(profile->proxy) - 1); - } - else if ((999 < atoi(arg)) && (atoi(arg) < 10000)) { - profile->pincode = arg; - } - else { - dbg_time("unknow -p '%s'", arg); - return usage(argv[0]); - } - } - break; - - case 'm': - if (has_more_argv()) - profile->muxid = argv[opt++][0] - '0' + 0x80; - break; - - case 'n': - if (has_more_argv()) - profile->pdp = argv[opt++][0] - '0'; - break; - - case 'f': - if (has_more_argv()) { - profile->logfile = argv[opt++]; - } - break; - - case 'i': - if (has_more_argv()) { - strncpy(profile->expect_adapter, argv[opt++], sizeof(profile->expect_adapter) - 1); - } - break; - - case 'v': - debug_qmi = 1; - break; - - case 'l': - if (has_more_argv()) { - profile->replication_factor = atoi(argv[opt++]); - if (profile->replication_factor > 0) { - profile->loopback_state = 1; - } - } - break; - - case '4': - profile->enable_ipv4 = 1; - break; - - case '6': - profile->enable_ipv6 = 1; - break; - - case 'u': - if (has_more_argv()) { - profile->usblogfile = argv[opt++]; - } - break; - - case 'b': - profile->enable_bridge = 1; - break; - - case 'k': - if (has_more_argv()) { - profile->kill_pdp = argv[opt++][0] - '0'; - } - break; - - default: - return usage(argv[0]); - break; - } - } - - if (profile->enable_ipv4 != 1 && profile->enable_ipv6 != 1) { // default enable IPv4 - profile->enable_ipv4 = 1; - } - - return 1; -} - -int main(int argc, char *argv[]) -{ - int ret; - PROFILE_T *ctx = &s_profile; - - dbg_time("QConnectManager_Linux_V1.6.4"); - - ret = parse_user_input(argc, argv, ctx); - if (!ret) - return ret; - - if (ctx->kill_pdp) { - return kill_data_call_pdp(ctx->kill_pdp, argv[0]); - } - - if (ctx->logfile) { - logfilefp = fopen(ctx->logfile, "a+"); - if (!logfilefp) { - dbg_time("Fail to open %s, errno: %d(%s)", ctx->logfile, errno, strerror(errno)); - } - } - - signal(SIGINT, ql_sigaction); - signal(SIGTERM, ql_sigaction); - signal(SIGALRM, ql_sigaction); - - do { - ret = quectel_CM(ctx); - if (g_donot_exit_when_modem_hangup > 0) - sleep(3); - } while (g_donot_exit_when_modem_hangup > 0); - - if (logfilefp) { - fclose(logfilefp); - } - - return ret; -} diff --git a/quectel_cm_5G/src/mbim-cm.c b/quectel_cm_5G/src/mbim-cm.c deleted file mode 100644 index b96ff55..0000000 --- a/quectel_cm_5G/src/mbim-cm.c +++ /dev/null @@ -1,2426 +0,0 @@ -/****************************************************************************** - @file mbim-cm.c - @brief MIBIM drivers. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "QMIThread.h" - -#define mbim_debug dbg_time - -#define UUID_BASIC_CONNECT "a289cc33-bcbb-8b4f-b6b0-133ec2aae6df" -//https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-5g-data-class-support -#define UUID_BASIC_CONNECT_EXT "3d01dcc5-fef5-4d05-0d3a-bef7058e9aaf" -#define UUID_SMS "533fbeeb-14fe-4467-9f90-33a223e56c3f" -#define UUID_USSD "e550a0c8-5e82-479e-82f7-10abf4c3351f" -#define UUID_PHONEBOOK "4bf38476-1e6a-41db-b1d8-bed289c25bdb" -#define UUID_STK "d8f20131-fcb5-4e17-8602-d6ed3816164c" -#define UUID_AUTH "1d2b5ff7-0aa1-48b2-aa52-50f15767174e" -#define UUID_DSS "c08a26dd-7718-4382-8482-6e0d583c4d0e" -#define uuid_ext_qmux "d1a30bc2-f97a-6e43-bf65-c7e24fb0f0d3" -#define uuid_mshsd "883b7c26-985f-43fa-9804-27d7fb80959c" -#define uuid_qmbe "2d0c12c9-0e6a-495a-915c-8d174fe5d63c" -#define UUID_MSFWID "e9f7dea2-feaf-4009-93ce-90a3694103b6" -#define uuid_atds "5967bdcc-7fd2-49a2-9f5c-b2e70e527db3" -#define uuid_qdu "6427015f-579d-48f5-8c54-f43ed1e76f83" -#define UUID_MS_UICC_LOW_LEVEL "c2f6588e-f037-4bc9-8665-f4d44bd09367" -#define UUID_MS_SARControl "68223D04-9F6C-4E0F-822D-28441FB72340" -#define UUID_VOICEEXTENSIONS "8d8b9eba-37be-449b-8f1e-61cb034a702e" -#define UUID_LIBMBIM_PROXY "838cf7fb-8d0d-4d7f-871e-d71dbefbb39b" - -#define UUID_MBIMContextTypeInternet "7E5E2A7E-4E6F-7272-736B-656E7E5E2A7E" - -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned int UINT32; -typedef unsigned long long UINT64; - -#pragma pack(4) -typedef enum { - MBIM_CID_CMD_TYPE_QUERY = 0, - MBIM_CID_CMD_TYPE_SET = 1, -} MBIM_CID_CMD_TYPE_E; - -typedef enum { - MBIM_CID_DEVICE_CAPS = 1, - MBIM_CID_SUBSCRIBER_READY_STATUS = 2, - MBIM_CID_RADIO_STATE = 3, MBIM_CID_PIN = 4, - MBIM_CID_PIN_LIS = 5, - MBIM_CID_HOME_PROVIDER = 6, - MBIM_CID_PREFERRED_PROVIDERS = 7, - MBIM_CID_VISIBLE_PROVIDERS = 8, - MBIM_CID_REGISTER_STATE = 9, - MBIM_CID_PACKET_SERVICE = 10, - MBIM_CID_SIGNAL_STATE = 11, - MBIM_CID_CONNECT = 12, - MBIM_CID_PROVISIONED_CONTEXTS = 13, - MBIM_CID_SERVICE_ACTIVATION = 14, - MBIM_CID_IP_CONFIGURATION = 15, - MBIM_CID_DEVICE_SERVICES = 16, - MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST = 19, - MBIM_CID_PACKET_STATISTICS = 20, - MBIM_CID_NETWORK_IDLE_HINT = 21, - MBIM_CID_EMERGENCY_MODE = 22, - MBIM_CID_IP_PACKET_FILTERS = 23, - MBIM_CID_MULTICARRIER_PROVIDERS = 24, -} UUID_BASIC_CONNECT_CID_E; - -typedef enum{ - MBIM_CID_MS_PROVISIONED_CONTEXT_V2 = 1, - MBIM_CID_MS_NETWORK_BLACKLIST = 2, - MBIM_CID_MS_LTE_ATTACH_CONFIG = 3, - MBIM_CID_MS_LTE_ATTACH_STATUS = 4, - MBIM_CID_MS_SYS_CAPS = 5, - MBIM_CID_MS_DEVICE_CAPS_V2 = 6, - MBIM_CID_MS_DEVICE_SLOT_MAPPING = 7, - MBIM_CID_MS_SLOT_INFO_STATUS = 8, - MBIM_CID_MS_PCO = 9, - MBIM_CID_MS_DEVICE_RESET = 10, - MBIM_CID_MS_BASE_STATIONS_INFO = 11, - MBIM_CID_MS_LOCATION_INFO_STATUS = 12, - MBIM_CID_NOT_DEFINED = 13, - MBIM_CID_MS_PIN_EX = 14, - MBIM_CID_MS_VERSION = 15, -} UUID_BASIC_CONNECT_EXT_CID_E; - -typedef enum { - MBIM_CID_SMS_CONFIGURATION = 1, // Y Y Y - MBIM_CID_SMS_READ = 2, // N Y Y - MBIM_CID_SMS_SEND = 3, // Y N N - MBIM_CID_SMS_DELETE = 4, // Y N N - MBIM_CID_SMS_MESSAGE_STORE_STATUS = 5, // N Y Y -} UUID_SMS_CID_E; - -typedef enum { - MBIM_CID_DSS_CONNECT = 1, // Y N N -} UUID_DSS_CID_E; - -typedef enum{ - MBIM_OPEN_MSG = 1, - MBIM_CLOSE_MSG = 2, - MBIM_COMMAND_MSG = 3, - MBIM_HOST_ERROR_MSG = 4, - MBIM_OPEN_DONE = 0x80000001, - MBIM_CLOSE_DONE = 0x80000002, - MBIM_COMMAND_DONE = 0x80000003, - MBIM_FUNCTION_ERROR_MSG = 0x80000004, - MBIM_INDICATE_STATUS_MSG = 0x80000007, -} MBIM_MSG_Type_E; - -typedef enum { /*< since=1.10 >*/ - MBIM_CID_PROXY_CONTROL_UNKNOWN = 0, - MBIM_CID_PROXY_CONTROL_CONFIGURATION = 1 -} UUID_LIBMBIM_PROXY_CID_E; - -typedef enum { - MBIM_CID_MS_UICC_ATR = 1, - MBIM_CID_MS_UICC_OPEN_CHANNEL = 2, - MBIM_CID_MS_UICC_CLOSE_CHANNEL = 3, - MBIM_CID_MS_UICC_APDU = 4, - MBIM_CID_MS_UICC_TERMINAL_CAPABILITY = 5, - MBIM_CID_MS_UICC_RESET = 6, - MBIM_CID_MS_APP_LIST = 7, -} UUID_MS_UICC_CID_E; - -typedef enum { - MBIM_ERROR_TIMEOUT_FRAGMENT = 1, - MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE = 2, - MBIM_ERROR_LENGTH_MISMATCH = 3, - MBIM_ERROR_DUPLICATED_TID = 4, - MBIM_ERROR_NOT_OPENED = 5, - MBIM_ERROR_UNKNOWN = 6, - MBIM_ERROR_CANCEL = 7, - MBIM_ERROR_MAX_TRANSFER = 8, -} MBIM_ERROR_E; - -typedef enum { - MBIM_STATUS_SUCCESS = 0, - MBIM_STATUS_BUSY = 1, - MBIM_STATUS_FAILURE = 2, - MBIM_STATUS_SIM_NOT_INSERTED = 3, - MBIM_STATUS_BAD_SIM = 4, - MBIM_STATUS_PIN_REQUIRED = 5, - MBIM_STATUS_PIN_DISABLED = 6, - MBIM_STATUS_NOT_REGISTERED = 7, - MBIM_STATUS_PROVIDERS_NOT_FOUND = 8, - MBIM_STATUS_NO_DEVICE_SUPPORT = 9, - MBIM_STATUS_PROVIDER_NOT_VISIBLE = 10, - MBIM_STATUS_DATA_CLASS_NOT_AVAILABL = 11, - MBIM_STATUS_PACKET_SERVICE_DETACHED = 12, -} MBIM_STATUS_CODES_E; - -typedef enum { - MBIMPacketServiceActionAttach = 0, - MBIMPacketServiceActionDetach = 1, -} MBIM_PACKET_SERVICE_ACTION_E; - -typedef enum { - MBIMPacketServiceStateUnknown = 0, - MBIMPacketServiceStateAttaching = 1, - MBIMPacketServiceStateAttached = 2, - MBIMPacketServiceStateDetaching = 3, - MBIMPacketServiceStateDetached = 4, -} MBIM_PACKET_SERVICE_STATE_E; - -static const char *MBIMPacketServiceStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMPacketServiceStateUnknown, "Unknown"}, - {MBIMPacketServiceStateAttaching, "Attaching"}, - {MBIMPacketServiceStateAttached, "Attached"}, - {MBIMPacketServiceStateDetaching, "Detaching"}, - {MBIMPacketServiceStateDetached, "Detached"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef enum { - MBIMDataClassNone = 0x0, - MBIMDataClassGPRS = 0x1, - MBIMDataClassEDGE = 0x2, - MBIMDataClassUMTS = 0x4, - MBIMDataClassHSDPA = 0x8, - MBIMDataClassHSUPA = 0x10, - MBIMDataClassLTE = 0x20, - MBIMDataClass5G_NSA = 0x40, - MBIMDataClass5G_SA = 0x80, - MBIMDataClass1XRTT = 0x10000, - MBIMDataClass1XEVDO = 0x20000, - MBIMDataClass1XEVDORevA = 0x40000, - MBIMDataClass1XEVDV = 0x80000, - MBIMDataClass3XRTT = 0x100000, - MBIMDataClass1XEVDORevB = 0x200000, - MBIMDataClassUMB = 0x400000, - MBIMDataClassCustom = 0x80000000, -} MBIM_DATA_CLASS_E; - -static const char *MBIMDataClassStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMDataClassNone, "None"}, - {MBIMDataClassGPRS, "GPRS"}, - {MBIMDataClassEDGE, "EDGE"}, - {MBIMDataClassUMTS, "UMTS"}, - {MBIMDataClassHSDPA, "HSDPA"}, - {MBIMDataClassHSUPA, "HSUPA"}, - {MBIMDataClassLTE, "LTE"}, - {MBIMDataClass5G_NSA, "5G_NSA"}, - {MBIMDataClass5G_SA, "5G_SA"}, - {MBIMDataClass1XRTT, "1XRTT"}, - {MBIMDataClass1XEVDO, "1XEVDO"}, - {MBIMDataClass1XEVDORevA, "1XEVDORevA"}, - {MBIMDataClass1XEVDV, "1XEVDV"}, - {MBIMDataClass3XRTT, "3XRTT"}, - {MBIMDataClass1XEVDORevB, "1XEVDORevB"}, - {MBIMDataClassUMB, "UMB"}, - {MBIMDataClassCustom, "Custom"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Unknow"; -}; - -typedef struct { - UINT32 NwError; - UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E - UINT32 HighestAvailableDataClass; //MBIM_DATA_CLASS_E - UINT64 UplinkSpeed; - UINT64 DownlinkSpeed; -} MBIM_PACKET_SERVICE_INFO_T; - -typedef struct { - UINT32 NwError; - UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E - UINT32 CurrentDataClass; //MBIM_DATA_CLASS_E - UINT64 UplinkSpeed; - UINT64 DownlinkSpeed; - UINT32 FrequencyRange; -} MBIM_PACKET_SERVICE_INFO_V2_T; - -typedef enum { - MBIMSubscriberReadyStateNotInitialized = 0, - MBIMSubscriberReadyStateInitialized = 1, - MBIMSubscriberReadyStateSimNotInserted = 2, - MBIMSubscriberReadyStateBadSim = 3, - MBIMSubscriberReadyStateFailure = 4, - MBIMSubscriberReadyStateNotActivated = 5, - MBIMSubscriberReadyStateDeviceLocked = 6, -}MBIM_SUBSCRIBER_READY_STATE_E; - -static const char *MBIMSubscriberReadyStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMSubscriberReadyStateNotInitialized, "NotInitialized"}, - {MBIMSubscriberReadyStateInitialized, "Initialized"}, - {MBIMSubscriberReadyStateSimNotInserted, "NotInserted"}, - {MBIMSubscriberReadyStateBadSim, "BadSim"}, - {MBIMSubscriberReadyStateFailure, "Failure"}, - {MBIMSubscriberReadyStateNotActivated, "NotActivated"}, - {MBIMSubscriberReadyStateDeviceLocked, "DeviceLocked"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef struct { - UINT32 DeviceType; //MBIM_DEVICE_TYPE - UINT32 CellularClass; //MBIM_CELLULAR_CLASS - UINT32 VoiceClass; //MBIM_VOICE_CLASS - UINT32 SimClass; //MBIM_SIM_CLASS - UINT32 DataClass; //MBIM_DATA_CLASS - UINT32 SmsCaps; //MBIM_SMS_CAPS - UINT32 ControlCaps; //MBIM_CTRL_CAPS - UINT32 MaxSessions; - UINT32 CustomDataClassOffset; - UINT32 CustomDataClassSize; - UINT32 DeviceIdOffset; - UINT32 DeviceIdSize; - UINT32 FirmwareInfoOffset; - UINT32 FirmwareInfoSize; - UINT32 HardwareInfoOffset; - UINT32 HardwareInfoSize; - UINT8 DataBuffer[0]; //DeviceId FirmwareInfo HardwareInfo -} MBIM_DEVICE_CAPS_INFO_T; - -typedef enum { - MBIMRadioOff = 0, - MBIMRadioOn = 1, -} MBIM_RADIO_SWITCH_STATE_E; - -typedef struct { - MBIM_RADIO_SWITCH_STATE_E RadioState; -} MBIM_SET_RADIO_STATE_T; - -typedef struct { - MBIM_RADIO_SWITCH_STATE_E HwRadioState; - MBIM_RADIO_SWITCH_STATE_E SwRadioState; -} MBIM_RADIO_STATE_INFO_T; - -typedef enum { - MBIMReadyInfoFlagsNone, - MBIMReadyInfoFlagsProtectUniqueID, -}MBIM_UNIQUE_ID_FLAGS; - -typedef struct { - UINT32 ReadyState; - UINT32 SubscriberIdOffset; - UINT32 SubscriberIdSize; - UINT32 SimIccIdOffset; - UINT32 SimIccIdSize; - UINT32 ReadyInfo; - UINT32 ElementCount; - UINT8 *TelephoneNumbersRefList; - UINT8 *DataBuffer; -} MBIM_SUBSCRIBER_READY_STATUS_T; - -typedef enum { - MBIMRegisterActionAutomatic, - MBIMRegisterActionManual, -}MBIM_REGISTER_ACTION_E; - -typedef enum { - MBIMRegisterStateUnknown = 0, - MBIMRegisterStateDeregistered = 1, - MBIMRegisterStateSearching = 2, - MBIMRegisterStateHome = 3, - MBIMRegisterStateRoaming = 4, - MBIMRegisterStatePartner = 5, - MBIMRegisterStateDenied = 6, -}MBIM_REGISTER_STATE_E; - -typedef enum { - MBIMRegisterModeUnknown = 0, - MBIMRegisterModeAutomatic = 1, - MBIMRegisterModeManual = 2, -}MBIM_REGISTER_MODE_E; - -static const char *MBIMRegisterStateStr(int _val) { - struct { int val;char *name;} _enumstr[] ={ - {MBIMRegisterStateUnknown, "Unknown"}, - {MBIMRegisterStateDeregistered, "Deregistered"}, - {MBIMRegisterStateSearching, "Searching"}, - {MBIMRegisterStateHome, "Home"}, - {MBIMRegisterStateRoaming, "Roaming"}, - {MBIMRegisterStatePartner, "Partner"}, - {MBIMRegisterStateDenied, "Denied"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -static const char *MBIMRegisterModeStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMRegisterModeUnknown, "Unknown"}, - {MBIMRegisterModeAutomatic, "Automatic"}, - {MBIMRegisterModeManual, "Manual"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef enum { - MBIM_REGISTRATION_NONE, - MBIM_REGISTRATION_MANUAL_SELECTION_NOT_AVAILABLE, - MBIM_REGISTRATION_PACKET_SERVICE_AUTOMATIC_ATTACH, -}MBIM_REGISTRATION_FLAGS_E; - -typedef struct { - UINT32 NwError; - UINT32 RegisterState; //MBIM_REGISTER_STATE_E - UINT32 RegisterMode; - UINT32 AvailableDataClasses; - UINT32 CurrentCellularClass; - UINT32 ProviderIdOffset; - UINT32 ProviderIdSize; - UINT32 ProviderNameOffset; - UINT32 ProviderNameSize; - UINT32 RoamingTextOffset; - UINT32 RoamingTextSize; - UINT32 RegistrationFlag; - UINT8 *DataBuffer; -} MBIM_REGISTRATION_STATE_INFO_T; - -typedef struct { - UINT32 NwError; - UINT32 RegisterState; //MBIM_REGISTER_STATE_E - UINT32 RegisterMode; - UINT32 AvailableDataClasses; - UINT32 CurrentCellularClass; - UINT32 ProviderIdOffset; - UINT32 ProviderIdSize; - UINT32 ProviderNameOffset; - UINT32 ProviderNameSize; - UINT32 RoamingTextOffset; - UINT32 RoamingTextSize; - UINT32 RegistrationFlag; - UINT32 PreferredDataClass; - UINT8 *DataBuffer; -} MBIM_REGISTRATION_STATE_INFO_V2_T; - -typedef struct { - UINT32 MessageType; //Specifies the MBIM message type. - UINT32 MessageLength; //Specifies the total length of this MBIM message in bytes. - /* Specifies the MBIM message id value. This value is used to match host sent messages with function responses. - This value must be unique among all outstanding transactions. - For notifications, the TransactionId must be set to 0 by the function */ - UINT32 TransactionId; -} MBIM_MESSAGE_HEADER; - -typedef struct { - UINT32 TotalFragments; //this field indicates how many fragments there are intotal. - UINT32 CurrentFragment; //This field indicates which fragment this message is. Values are 0 to TotalFragments?\1 -} MBIM_FRAGMENT_HEADER; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 MaxControlTransfer; -} MBIM_OPEN_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 Status; //MBIM_STATUS_CODES_E -} MBIM_OPEN_DONE_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; -} MBIM_CLOSE_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 Status; -} MBIM_CLOSE_DONE_T; - -typedef struct { - UINT8 uuid[16]; -} UUID_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - MBIM_FRAGMENT_HEADER FragmentHeader; - UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. - UINT32 CID; //Specifies the CID that identifies the parameter being queried for - UINT32 CommandType; //0 for a query operation, 1 for a Set operation - UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. - UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID -} MBIM_COMMAND_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - MBIM_FRAGMENT_HEADER FragmentHeader; - UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. - UINT32 CID; //Specifies the CID that identifies the parameter being queried for - UINT32 Status; - UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. - UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID -} MBIM_COMMAND_DONE_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 ErrorStatusCode; -} MBIM_HOST_ERROR_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 ErrorStatusCode; -} MBIM_FUNCTION_ERROR_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - MBIM_FRAGMENT_HEADER FragmentHeader; - UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. - UINT32 CID; //Specifies the CID that identifies the parameter being queried for - UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. - UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID -} MBIM_INDICATE_STATUS_MSG_T; - -typedef struct { - UINT32 offset; - UINT32 size; -} OL_PAIR_LIST; - -typedef struct { - UUID_T DeviceServiceId; - UINT32 DssPayload; - UINT32 MaxDssInstances; - UINT32 CidCount; - UINT32 CidList[]; -} MBIM_DEVICE_SERVICE_ELEMENT_T; - -typedef struct { - UINT32 DeviceServicesCount; - UINT32 MaxDssSessions; - OL_PAIR_LIST DeviceServicesRefList[]; -} MBIM_DEVICE_SERVICES_INFO_T; - -typedef enum { - MBIMActivationCommandDeactivate = 0, - MBIMActivationCommandActivate = 1, -} MBIM_ACTIVATION_COMMAND_E; - -typedef enum { - MBIMCompressionNone = 0, - MBIMCompressionEnable = 1, -} MBIM_COMPRESSION_E; - -typedef enum { - MBIMAuthProtocolNone = 0, - MBIMAuthProtocolPap = 1, - MBIMAuthProtocolChap = 2, - MBIMAuthProtocolMsChapV2 = 3, -} MBIM_AUTH_PROTOCOL_E; - -typedef enum { - MBIMContextIPTypeDefault = 0, - MBIMContextIPTypeIPv4 = 1, - MBIMContextIPTypeIPv6 = 2, - MBIMContextIPTypeIPv4v6 = 3, - MBIMContextIPTypeIPv4AndIPv6 = 4, -} MBIM_CONTEXT_IP_TYPE_E; - -typedef enum { - MBIMActivationStateUnknown = 0, - MBIMActivationStateActivated = 1, - MBIMActivationStateActivating = 2, - MBIMActivationStateDeactivated = 3, - MBIMActivationStateDeactivating = 4, -} MBIM_ACTIVATION_STATE_E; - -typedef enum { - MBIMVoiceCallStateNone = 0, - MBIMVoiceCallStateInProgress = 1, - MBIMVoiceCallStateHangUp = 2, -} MBIM_VOICECALL_STATE_E; - -static const char *MBIMMSGTypeStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIM_OPEN_MSG, "MBIM_OPEN_MSG"}, - {MBIM_CLOSE_MSG, "MBIM_CLOSE_MSG"}, - {MBIM_COMMAND_MSG, "MBIM_COMMAND_MSG"}, - {MBIM_HOST_ERROR_MSG, "MBIM_HOST_ERROR_MSG"}, - {MBIM_OPEN_DONE, "MBIM_OPEN_DONE"}, - {MBIM_CLOSE_DONE, "MBIM_CLOSE_DONE"}, - {MBIM_COMMAND_DONE, "MBIM_COMMAND_DONE"}, - {MBIM_FUNCTION_ERROR_MSG, "MBIM_FUNCTION_ERROR_MSG"}, - {MBIM_INDICATE_STATUS_MSG, "MBIM_INDICATE_STATUS_MSG"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "MBIMMSGTypeUnknow"; -}; - -static const char *MBIMContextIPTypeStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMContextIPTypeDefault, "MBIMContextIPTypeDefault"}, - {MBIMContextIPTypeIPv4, "MBIMContextIPTypeIPv4"}, - {MBIMContextIPTypeIPv6, "MBIMContextIPTypeIPv6"}, - {MBIMContextIPTypeIPv4v6, "MBIMContextIPTypeIPv4v6"}, - {MBIMContextIPTypeIPv4AndIPv6, "MBIMContextIPTypeIPv4AndIPv6"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "MBIMContextIPTypeUnknow"; -} - -static const char *MBIMActivationStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMActivationStateUnknown, "Unknown"}, - {MBIMActivationStateActivated, "Activated"}, - {MBIMActivationStateActivating, "Activating"}, - {MBIMActivationStateDeactivated, "Deactivated"}, - {MBIMActivationStateDeactivating, "Deactivating"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -static const char *MBIMVoiceCallStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMVoiceCallStateNone, "None"}, - {MBIMVoiceCallStateInProgress, "InProgress"}, - {MBIMVoiceCallStateHangUp, "HangUp"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef struct { - const char *uuid; - UINT32 cid; - const char *name; -} UUID_CID_STR; - -static const UUID_CID_STR uuid_cid_string[] = { - {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_CAPS, "MBIM_CID_DEVICE_CAPS"}, - {UUID_BASIC_CONNECT, MBIM_CID_SUBSCRIBER_READY_STATUS, "MBIM_CID_SUBSCRIBER_READY_STATUS"}, - {UUID_BASIC_CONNECT, MBIM_CID_RADIO_STATE, "MBIM_CID_RADIO_STATE"}, - {UUID_BASIC_CONNECT, MBIM_CID_PIN, "MBIM_CID_PIN"}, - {UUID_BASIC_CONNECT, MBIM_CID_PIN_LIS, "MBIM_CID_PIN_LIS"}, - {UUID_BASIC_CONNECT, MBIM_CID_HOME_PROVIDER, "MBIM_CID_HOME_PROVIDER"}, - {UUID_BASIC_CONNECT, MBIM_CID_PREFERRED_PROVIDERS, "MBIM_CID_PREFERRED_PROVIDERS"}, - {UUID_BASIC_CONNECT, MBIM_CID_VISIBLE_PROVIDERS, "MBIM_CID_VISIBLE_PROVIDERS"}, - {UUID_BASIC_CONNECT, MBIM_CID_REGISTER_STATE, "MBIM_CID_REGISTER_STATE"}, - {UUID_BASIC_CONNECT, MBIM_CID_PACKET_SERVICE, "MBIM_CID_PACKET_SERVICE"}, - {UUID_BASIC_CONNECT, MBIM_CID_SIGNAL_STATE, "MBIM_CID_SIGNAL_STATE"}, - {UUID_BASIC_CONNECT, MBIM_CID_CONNECT, "MBIM_CID_CONNECT"}, - {UUID_BASIC_CONNECT, MBIM_CID_PROVISIONED_CONTEXTS, "MBIM_CID_PROVISIONED_CONTEXTS"}, - {UUID_BASIC_CONNECT, MBIM_CID_SERVICE_ACTIVATION, "MBIM_CID_SERVICE_ACTIVATION"}, - {UUID_BASIC_CONNECT, MBIM_CID_IP_CONFIGURATION, "MBIM_CID_IP_CONFIGURATION"}, - {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_SERVICES, "MBIM_CID_DEVICE_SERVICES"}, - {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST, "MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST"}, - {UUID_BASIC_CONNECT, MBIM_CID_PACKET_STATISTICS, "MBIM_CID_PACKET_STATISTICS"}, - {UUID_BASIC_CONNECT, MBIM_CID_NETWORK_IDLE_HINT, "MBIM_CID_NETWORK_IDLE_HINT"}, - {UUID_BASIC_CONNECT, MBIM_CID_EMERGENCY_MODE, "MBIM_CID_EMERGENCY_MODE"}, - {UUID_BASIC_CONNECT, MBIM_CID_IP_PACKET_FILTERS, "MBIM_CID_IP_PACKET_FILTERS"}, - {UUID_BASIC_CONNECT, MBIM_CID_MULTICARRIER_PROVIDERS, "MBIM_CID_MULTICARRIER_PROVIDERS"}, - - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PROVISIONED_CONTEXT_V2, "MBIM_CID_MS_PROVISIONED_CONTEXT_V2"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_NETWORK_BLACKLIST, "MBIM_CID_MS_NETWORK_BLACKLIST"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LTE_ATTACH_CONFIG, "MBIM_CID_MS_LTE_ATTACH_CONFIG"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LTE_ATTACH_STATUS, "MBIM_CID_MS_LTE_ATTACH_STATUS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_SYS_CAPS, "MBIM_CID_MS_SYS_CAPS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_CAPS_V2, "MBIM_CID_MS_DEVICE_CAPS_V2"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_SLOT_MAPPING, "MBIM_CID_MS_DEVICE_SLOT_MAPPING"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_SLOT_INFO_STATUS, "MBIM_CID_MS_SLOT_INFO_STATUS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PCO, "MBIM_CID_MS_PCO"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_RESET, "MBIM_CID_MS_DEVICE_RESET"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_BASE_STATIONS_INFO, "MBIM_CID_MS_BASE_STATIONS_INFO"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LOCATION_INFO_STATUS, "MBIM_CID_MS_LOCATION_INFO_STATUS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_NOT_DEFINED, "MBIM_CID_NOT_DEFINED"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PIN_EX, "MBIM_CID_MS_PIN_EX"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_VERSION, "MBIM_CID_MS_VERSION"}, - - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_ATR, "MBIM_CID_MS_UICC_ATR"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_OPEN_CHANNEL, "MBIM_CID_MS_UICC_OPEN_CHANNEL"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_CLOSE_CHANNEL, "MBIM_CID_MS_UICC_CLOSE_CHANNEL"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_APDU, "MBIM_CID_MS_UICC_APDU"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_TERMINAL_CAPABILITY, "MBIM_CID_MS_UICC_TERMINAL_CAPABILITY"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_RESET, "MBIM_CID_MS_UICC_RESET"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_APP_LIST, "MBIM_CID_MS_APP_LIST"}, -}; - -typedef struct { - UINT32 SessionId; - UINT32 ActivationCommand; //MBIM_ACTIVATION_COMMAND_E - UINT32 AccessStringOffset; - UINT32 AccessStringSize; - UINT32 UserNameOffset; - UINT32 UserNameSize; - UINT32 PasswordOffset; - UINT32 PasswordSize; - UINT32 Compression; //MBIM_COMPRESSION_E - UINT32 AuthProtocol; //MBIM_AUTH_PROTOCOL_E - UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E - UUID_T ContextType; - UINT8 DataBuffer[0]; /* apn, username, password */ -} MBIM_SET_CONNECT_T; - -typedef struct { - UINT32 SessionId; - UINT32 ActivationState; //MBIM_ACTIVATION_STATE_E - UINT32 VoiceCallState; - UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E - UUID_T ContextType; - UINT32 NwError; -} MBIM_CONNECT_T; - -typedef struct { - UINT32 OnLinkPrefixLength; - UINT8 IPv4Address[4]; -} MBIM_IPV4_ELEMENT_T; - -typedef struct { - UINT32 OnLinkPrefixLength; - UINT8 IPv6Address[16]; -} MBIM_IPV6_ELEMENT_T; - -typedef struct { - UINT32 SessionId; - UINT32 IPv4ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU - UINT32 IPv6ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU - UINT32 IPv4AddressCount; - UINT32 IPv4AddressOffset; - UINT32 IPv6AddressCount; - UINT32 IPv6AddressOffset; - UINT32 IPv4GatewayOffset; - UINT32 IPv6GatewayOffset; - UINT32 IPv4DnsServerCount; - UINT32 IPv4DnsServerOffset; - UINT32 IPv6DnsServerCount; - UINT32 IPv6DnsServerOffset; - UINT32 IPv4Mtu; - UINT32 IPv6Mtu; - UINT8 DataBuffer[]; -} MBIM_IP_CONFIGURATION_INFO_T; - -typedef struct { - UINT32 RSRP; - UINT32 SNR; - UINT32 RSRPThreshold; - UINT32 SNRThreshold; - UINT32 SystemType; -} MBIM_RSRP_SNR_INFO_T; - -typedef struct { - UINT32 Elementcount; - MBIM_RSRP_SNR_INFO_T RsrpSnr[0]; -} MBIM_RSRP_SNR_T; - -typedef struct { - UINT32 Rssi; - UINT32 ErrorRate; - UINT32 SignalStrengthInterval; - UINT32 RssiThreshold; - UINT32 ErrorRateThreshold; -} MBIM_SIGNAL_STATE_INFO_T; - -typedef struct { - UINT32 Rssi; - UINT32 ErrorRate; - UINT32 SignalStrengthInterval; - UINT32 RssiThreshold; - UINT32 ErrorRateThreshold; - UINT32 RsrpSnrOffset; - UINT32 RsrpSnrSize; - UINT8 DataBuffer[]; -} MBIM_SIGNAL_STATE_INFO_V2_T; - -typedef struct { - UINT32 SignalStrengthInterval; - UINT32 RssiThreshold; - UINT32 ErrorRateThreshold; -} MBIM_SET_SIGNAL_STATE_T; - -typedef struct { - UINT32 DevicePathOffset; - UINT32 DevicePathSize; - UINT32 Timeout; - UINT8 DataBuffer[]; -} MBIM_LIBQMI_PROXY_CONFIG_T; - -typedef struct { - UINT32 AtrSize; - UINT32 AtrOffset; - UINT8 DataBuffer[]; -} MBIM_MS_ATR_INFO_T; - -#pragma pack() - -static pthread_t s_tid_reader = 0; -static int mbim_verbose = 0; -static UINT32 TransactionId = 1; -static unsigned mbim_default_timeout = 30000; -static const char *mbim_apn = NULL; -static const char *mbim_user = NULL; -static const char *mbim_passwd = NULL; -static int mbim_iptype = MBIMContextIPTypeDefault; -static int mbim_auth = MBIMAuthProtocolNone; -static int mbim_sessionID = 0; -static int mbim_fd = -1; -static MBIM_MESSAGE_HEADER *mbim_pRequest; -static MBIM_MESSAGE_HEADER *mbim_pResponse; - -static unsigned int qmi_over_mbim_support = 0; -static int qmi_over_mbim_sk[2] = {-1, -1}; -static pthread_mutex_t mbim_command_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t mbim_command_cond = PTHREAD_COND_INITIALIZER; -static int mbim_ms_version = 1; -static uint8_t qmi_over_mbim_nas = 0; -int qmi_over_mbim_qmidev_send(PQCQMIMSG pQMI); - -static const UUID_T * str2uuid(const char *str) { - static UUID_T uuid; - UINT32 d[16]; - char tmp[16*2+4+1]; - unsigned i = 0; - - while (str[i]) { - tmp[i] = tolower(str[i]); - i++; - } - tmp[i] = '\0'; - - sscanf(tmp, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], - &d[8], &d[9], &d[10], &d[11], &d[12], &d[13], &d[14], &d[15]); - - for (i = 0; i < 16; i++) { - uuid.uuid[i] = d[i]&0xFF; - } - - return &uuid; -} - -static void wchar2char(const char *src, size_t src_size, char *dst, size_t dst_len) { - size_t i; - - for (i = 0; i < (dst_len-1) && i < (src_size/2); i++) - dst[i] = src[i*2]; - dst[i] = 0; -} - -static size_t char2wchar(const char *src, size_t src_len, uint8_t *dst, size_t dst_len) { - size_t i; - - if (src_len > (dst_len/2)) - src_len = (dst_len/2); - - for (i = 0; i < src_len; i++) { - *dst++ = *src++; - *dst++ = 0; - } - - return i*2; -} - -#define mbim_alloc( _size) malloc(_size) -#define mbim_free(_mem) do { if (_mem) { free(_mem); _mem = NULL;}} while(0) - -static int mbim_open_state = 0; -static MBIM_SUBSCRIBER_READY_STATE_E ReadyState = MBIMSubscriberReadyStateNotInitialized; -static MBIM_REGISTER_STATE_E RegisterState = MBIMRegisterStateUnknown; -static MBIM_PACKET_SERVICE_STATE_E PacketServiceState = MBIMPacketServiceStateUnknown; -static MBIM_ACTIVATION_STATE_E ActivationState = MBIMActivationStateUnknown; -static MBIM_SUBSCRIBER_READY_STATE_E oldReadyState = MBIMSubscriberReadyStateNotInitialized; -static MBIM_REGISTER_STATE_E oldRegisterState = MBIMRegisterStateUnknown; -static MBIM_PACKET_SERVICE_STATE_E oldPacketServiceState = MBIMPacketServiceStateUnknown; -static MBIM_ACTIVATION_STATE_E oldActivationState = MBIMActivationStateUnknown; -static int mbim_update_state(void); - -static __inline uint32_t mbim2qmi_ipv4addr(uint32_t addr) { - return (addr>>24) | (addr>>8&0xff00) | (addr<<8&0xff0000) | (addr<<24); -} - -static __inline void mbim2qmi_ipv6addr(const unsigned char *src, unsigned char *dst) { - int i; - - for (i = 0; i < 16 ; i++) { - dst[i] = src[i]; - } -} - -static MBIM_MESSAGE_HEADER *compose_open_command(UINT32 MaxControlTransfer) -{ - MBIM_OPEN_MSG_T *pRequest = (MBIM_OPEN_MSG_T *)mbim_alloc(sizeof(MBIM_OPEN_MSG_T)); - - if(!pRequest) - return NULL; - - pRequest->MessageHeader.MessageType = htole32(MBIM_OPEN_MSG); - pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_OPEN_MSG_T)); - pRequest->MessageHeader.TransactionId = htole32(TransactionId++); - pRequest->MaxControlTransfer = htole32(MaxControlTransfer); - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_close_command(void) -{ - MBIM_CLOSE_MSG_T *pRequest = (MBIM_CLOSE_MSG_T *)mbim_alloc(sizeof(MBIM_CLOSE_MSG_T)); - - if(!pRequest) - return NULL; - - pRequest->MessageHeader.MessageType = htole32(MBIM_CLOSE_MSG); - pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_CLOSE_MSG_T)); - pRequest->MessageHeader.TransactionId = htole32(TransactionId++); - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_basic_connect_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) -{ - MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)mbim_alloc(sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength); - - if (!pRequest) - return NULL; - - pRequest->MessageHeader.MessageType = htole32(MBIM_COMMAND_MSG); - pRequest->MessageHeader.MessageLength = htole32((sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength)); - pRequest->MessageHeader.TransactionId = htole32(TransactionId++); - - pRequest->FragmentHeader.TotalFragments = htole32(1); - pRequest->FragmentHeader.CurrentFragment= htole32(0); - - memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16); - - pRequest->CID = htole32(CID); - pRequest->CommandType = htole32(CommandType); - if (InformationBufferLength && pInformationBuffer) { - pRequest->InformationBufferLength = htole32(InformationBufferLength); - memcpy(pRequest->InformationBuffer, pInformationBuffer, InformationBufferLength); - } else { - pRequest->InformationBufferLength = htole32(0); - } - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_basic_connect_ext_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) -{ - MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength); - - if (!pRequest) - return NULL; - - memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16); - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_qmi_over_mbim_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) -{ - MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength); - - if (!pRequest) - return NULL; - - memcpy(pRequest->DeviceServiceId.uuid, str2uuid(uuid_ext_qmux), 16); - - return &pRequest->MessageHeader; -} - -static const char * uuid2str(const UUID_T *pUUID) { - static char str[16*2+4+1]; - const UINT8 *d = pUUID->uuid; - - snprintf(str, sizeof(str), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], - d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); - - return str; -} - -static const char *DeviceServiceId2str(const UUID_T *pUUID) { - const char *str = uuid2str(pUUID); - - struct { char *val;char *name;} _enumstr[] = { - {UUID_BASIC_CONNECT, "UUID_BASIC_CONNECT"}, - {UUID_BASIC_CONNECT_EXT, "UUID_BASIC_CONNECT_EXT"}, - {UUID_SMS, "UUID_SMS"}, - {UUID_USSD, "UUID_USSD"}, - {UUID_PHONEBOOK, "UUID_PHONEBOOK"}, - {UUID_STK, "UUID_STK"}, - {UUID_AUTH, "UUID_AUTH"}, - {UUID_DSS, "UUID_DSS"}, - {uuid_ext_qmux, "uuid_ext_qmux"}, - {uuid_mshsd, "uuid_mshsd"}, - {uuid_qmbe, "uuid_qmbe"}, - {UUID_MSFWID, "UUID_MSFWID"}, - {uuid_atds, "uuid_atds"}, - {uuid_qdu, "uuid_qdu"}, - {UUID_MS_UICC_LOW_LEVEL, "UUID_MS_UICC_LOW_LEVEL"}, - {UUID_MS_SARControl, "UUID_MS_SARControl"}, - {UUID_VOICEEXTENSIONS, "UUID_VOICEEXTENSIONS"}, - {UUID_LIBMBIM_PROXY, "UUID_LIBMBIM_PROXY"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (!strcasecmp(str, _enumstr[idx].val)) - return _enumstr[idx].name; - } - - return str; -} - -static const char *mbim_get_segment(void *_pMsg, UINT32 offset, UINT32 len) -{ - int idx; - static char buff[256] = {'\0'}; - UINT8 *pMsg = (UINT8*)_pMsg; - - for (idx = 0; idx < (int)(len/2); idx++) - buff[idx] = pMsg[offset+idx*2]; - buff[idx] = '\0'; - return buff; -} - -static void mbim_dump_header(MBIM_MESSAGE_HEADER *pMsg, const char *direction) { - mbim_debug("%s Header:", direction); - mbim_debug("%s MessageLength = %u", direction, le32toh(pMsg->MessageLength)); - mbim_debug("%s MessageType = %s (0x%08x)", direction, MBIMMSGTypeStr(le32toh(pMsg->MessageType)), le32toh(pMsg->MessageType)); - mbim_debug("%s TransactionId = %u", direction, le32toh(pMsg->TransactionId)); - mbim_debug("%s Contents:", direction); -} - -static void mbim_dump_uuid_cid(const UUID_T *pUUID, UINT32 CID, const char *direction) { - size_t idx; - const char *uuidStr = uuid2str(pUUID); - const char *cidStr = "unknow"; - - for (idx = 0; idx < (sizeof(uuid_cid_string)/sizeof(uuid_cid_string[0])); idx++) { - if (!strcmp(uuidStr, uuid_cid_string[idx].uuid) && uuid_cid_string[idx].cid == CID) { - cidStr = uuid_cid_string[idx].name; - } - } - - mbim_debug("%s DeviceServiceId = %s (%s)", direction, DeviceServiceId2str(pUUID), uuidStr); - mbim_debug("%s CID = %s (%u)", direction, cidStr, le32toh(CID)); -} - - -static void mbim_dump_command_msg(MBIM_COMMAND_MSG_T *pCmdMsg, const char *direction) { - mbim_dump_uuid_cid(&pCmdMsg->DeviceServiceId, le32toh(pCmdMsg->CID), direction); - mbim_debug("%s CommandType = %s (%u)", direction, le32toh(pCmdMsg->CommandType) ? "set" : "query", le32toh(pCmdMsg->CommandType)); - mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdMsg->InformationBufferLength)); -} - -static void mbim_dump_command_done(MBIM_COMMAND_DONE_T *pCmdDone, const char *direction) { - mbim_dump_uuid_cid(&pCmdDone->DeviceServiceId, le32toh(pCmdDone->CID), direction); - mbim_debug("%s Status = %u", direction, le32toh(pCmdDone->Status)); - mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdDone->InformationBufferLength)); -} - -static void mbim_dump_indicate_msg(MBIM_INDICATE_STATUS_MSG_T *pIndMsg, const char *direction) { - mbim_dump_uuid_cid(&pIndMsg->DeviceServiceId, le32toh(pIndMsg->CID), direction); - mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pIndMsg->InformationBufferLength)); -} - -static void mbim_dump_connect(MBIM_CONNECT_T *pInfo, const char *direction) { - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - mbim_debug("%s ActivationState = %s (%u)", direction, MBIMActivationStateStr(le32toh(pInfo->ActivationState)), le32toh(pInfo->ActivationState)); - mbim_debug("%s IPType = %s", direction, MBIMContextIPTypeStr(le32toh(pInfo->IPType))); - mbim_debug("%s VoiceCallState = %s", direction, MBIMVoiceCallStateStr(le32toh(pInfo->VoiceCallState))); - mbim_debug("%s ContextType = %s", direction, uuid2str(&pInfo->ContextType)); - mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); -} - -static void mbim_dump_signal_state(MBIM_SIGNAL_STATE_INFO_T *pInfo, const char *direction) -{ - mbim_debug("%s Rssi = %u", direction, le32toh(pInfo->Rssi)); - mbim_debug("%s ErrorRate = %u", direction, le32toh(pInfo->ErrorRate)); - mbim_debug("%s SignalStrengthInterval = %u", direction, le32toh(pInfo->SignalStrengthInterval)); - mbim_debug("%s RssiThreshold = %u", direction, le32toh(pInfo->RssiThreshold)); - mbim_debug("%s ErrorRateThreshold = %u", direction, le32toh(pInfo->ErrorRateThreshold)); -} - -static void mbim_dump_packet_service(MBIM_PACKET_SERVICE_INFO_T *pInfo, const char *direction) -{ - mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); - mbim_debug("%s PacketServiceState = %s", direction, MBIMPacketServiceStateStr(le32toh(pInfo->PacketServiceState))); - mbim_debug("%s HighestAvailableDataClass = %s", direction, MBIMDataClassStr(le32toh(pInfo->HighestAvailableDataClass))); - mbim_debug("%s UplinkSpeed = %ld", direction, (long)le64toh(pInfo->UplinkSpeed)); - mbim_debug("%s DownlinkSpeed = %ld", direction, (long)le64toh(pInfo->DownlinkSpeed)); -} - -static void mbim_dump_subscriber_status(MBIM_SUBSCRIBER_READY_STATUS_T *pInfo, const char *direction) -{ - mbim_debug("%s ReadyState = %s", direction, MBIMSubscriberReadyStateStr(le32toh(pInfo->ReadyState))); - mbim_debug("%s SIMICCID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize))); - mbim_debug("%s SubscriberID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize))); - /* maybe more than one number */ - uint32_t idx; - for (idx = 0; idx < le32toh(pInfo->ElementCount); idx++) { - UINT32 offset = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[0]; - UINT32 length = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[1]; - mbim_debug("%s Number = %s", direction, mbim_get_segment(pInfo, le32toh(offset), le32toh(length))); - } -} - -static void mbim_dump_regiester_status(MBIM_REGISTRATION_STATE_INFO_T *pInfo, const char *direction) -{ - mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); - mbim_debug("%s RegisterState = %s", direction, MBIMRegisterStateStr(le32toh(pInfo->RegisterState))); - mbim_debug("%s RegisterMode = %s", direction, MBIMRegisterModeStr(le32toh(pInfo->RegisterMode))); -} - -static void mbim_dump_ipconfig(MBIM_IP_CONFIGURATION_INFO_T *pInfo, const char *direction) -{ - UINT8 prefix = 0, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL; - - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - mbim_debug("%s IPv4ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv4ConfigurationAvailable)); - mbim_debug("%s IPv6ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv6ConfigurationAvailable)); - mbim_debug("%s IPv4AddressCount = 0x%x", direction, le32toh(pInfo->IPv4AddressCount)); - mbim_debug("%s IPv4AddressOffset = 0x%x", direction, le32toh(pInfo->IPv4AddressOffset)); - mbim_debug("%s IPv6AddressCount = 0x%x", direction, le32toh(pInfo->IPv6AddressCount)); - mbim_debug("%s IPv6AddressOffset = 0x%x", direction, le32toh(pInfo->IPv6AddressOffset)); - - /* IPv4 */ - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) { - MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv4 = pAddress->IPv4Address; - mbim_debug("%s IPv4 = %u.%u.%u.%u/%u", direction, ipv4[0], ipv4[1], ipv4[2], ipv4[3], prefix); - } - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) { - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s gw = %u.%u.%u.%u", direction, gw[0], gw[1], gw[2], gw[3]); - } - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x3) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset) -sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s dns1 = %u.%u.%u.%u", direction, dns1[0], dns1[1], dns1[2], dns1[3]); - if (le32toh(pInfo->IPv4DnsServerCount) == 2) { - dns2 = dns1 + 4; - mbim_debug("%s dns2 = %u.%u.%u.%u", direction, dns2[0], dns2[1], dns2[2], dns2[3]); - } - } - if (le32toh(pInfo->IPv4Mtu)) mbim_debug("%s ipv4 mtu = %u", direction, le32toh(pInfo->IPv4Mtu)); - - /* IPv6 */ - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) { - MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv6 = pAddress->IPv6Address; - mbim_debug("%s IPv6 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%d", \ - direction, ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7], \ - ipv6[8], ipv6[9], ipv6[10], ipv6[11], ipv6[12], ipv6[13], ipv6[14], ipv6[15], prefix); - } - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) { - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s gw = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ - direction, gw[0], gw[1], gw[2], gw[3], gw[4], gw[5], gw[6], gw[7], \ - gw[8], gw[9], gw[10], gw[11], gw[12], gw[13], gw[14], gw[15]); - } - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x3) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s dns1 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ - direction, dns1[0], dns1[1], dns1[2], dns1[3], dns1[4], dns1[5], dns1[6], dns1[7], \ - dns1[8], dns1[9], dns1[10], dns1[11], dns1[12], dns1[13], dns1[14], dns1[15]); - if (le32toh(pInfo->IPv6DnsServerCount) == 2) { - dns2 = dns1 + 16; - mbim_debug("%s dns2 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ - direction, dns2[0], dns2[1], dns2[2], dns2[3], dns1[4], dns1[5], dns1[6], dns1[7], - dns2[8], dns2[9], dns2[10], dns2[11], dns2[12], dns2[13], dns2[14], dns2[15]); - } - } - if (le32toh(pInfo->IPv6Mtu)) mbim_debug("%s ipv6 mtu = %u", direction, le32toh(pInfo->IPv6Mtu)); -} - -static void mbim_dump(MBIM_MESSAGE_HEADER *pMsg, int mbim_verbose) { - unsigned char *data = (unsigned char *)pMsg; - const char *direction = (le32toh(pMsg->MessageType) & 0x80000000) ? "<" : ">"; - - if (!mbim_verbose) - return; - - if (mbim_verbose) { - unsigned i; - static char *_tmp = NULL; - - if (!_tmp) - _tmp = (char *)malloc(4096); - - if (_tmp) { - _tmp[0] = (le32toh(pMsg->MessageType) & 0x80000000) ? '<' : '>'; - _tmp[1] = '\0'; - for (i = 0; i < le32toh(pMsg->MessageLength) && i < 4096; i++) - snprintf(_tmp + strlen(_tmp), 4096 - strlen(_tmp), "%02X:", data[i]); - mbim_debug("%s", _tmp); - } - } - - mbim_dump_header(pMsg, direction); - - switch (le32toh(pMsg->MessageType)) { - case MBIM_OPEN_MSG: { - MBIM_OPEN_MSG_T *pOpenMsg = (MBIM_OPEN_MSG_T *)pMsg; - mbim_debug("%s MaxControlTransfer = %u", direction, le32toh(pOpenMsg->MaxControlTransfer)); - } - break; - case MBIM_OPEN_DONE: { - MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsg; - mbim_debug("%s Status = %u", direction, le32toh(pOpenDone->Status)); - } - break; - case MBIM_CLOSE_MSG: { - - } - break; - case MBIM_CLOSE_DONE: { - MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsg; - mbim_debug("%s Status = %u", direction, le32toh(pCloseDone->Status)); - } - break; - case MBIM_COMMAND_MSG: { - MBIM_COMMAND_MSG_T *pCmdMsg = (MBIM_COMMAND_MSG_T *)pMsg; - - mbim_dump_command_msg(pCmdMsg, direction); - if (!memcmp(pCmdMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { - switch (le32toh(pCmdMsg->CID)) { - case MBIM_CID_CONNECT: { - MBIM_SET_CONNECT_T *pInfo = (MBIM_SET_CONNECT_T *)pCmdMsg->InformationBuffer; - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - } - break; - case MBIM_CID_IP_CONFIGURATION: { - MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdMsg->InformationBuffer; - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - } - break; - default: - break; - } - } - } - break; - case MBIM_COMMAND_DONE: { - MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsg; - - mbim_dump_command_done(pCmdDone, direction); - if (le32toh(pCmdDone->InformationBufferLength) == 0) - return; - - if (!memcmp(pCmdDone->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { - switch (le32toh(pCmdDone->CID)) { - case MBIM_CID_CONNECT: { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; - mbim_dump_connect(pInfo, direction); - } - break; - case MBIM_CID_IP_CONFIGURATION: { - //MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer; - //mbim_dump_ipconfig(pInfo, direction); - } - break; - case MBIM_CID_PACKET_SERVICE: { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; - mbim_dump_packet_service(pInfo, direction); - } - break; - case MBIM_CID_SUBSCRIBER_READY_STATUS: { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer; - mbim_dump_subscriber_status(pInfo, direction); - } - break; - case MBIM_CID_REGISTER_STATE: { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer; - mbim_dump_regiester_status(pInfo, direction); - } - break; - default: - break; - } - } - } - break; - case MBIM_INDICATE_STATUS_MSG: { - MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pMsg; - - mbim_dump_indicate_msg(pIndMsg, direction); - if (le32toh(pIndMsg->InformationBufferLength) == 0) - return; - - if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { - switch (le32toh(pIndMsg->CID)) { - case MBIM_CID_CONNECT: { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer; - mbim_dump_connect(pInfo, direction); - } - break; - case MBIM_CID_SIGNAL_STATE: { - MBIM_SIGNAL_STATE_INFO_T *pInfo = (MBIM_SIGNAL_STATE_INFO_T *)pIndMsg->InformationBuffer; - mbim_dump_signal_state(pInfo, direction); - } - break; - case MBIM_CID_SUBSCRIBER_READY_STATUS: { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer; - mbim_dump_subscriber_status(pInfo, direction); - } - break; - case MBIM_CID_REGISTER_STATE: { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer; - mbim_dump_regiester_status(pInfo, direction); - } - break; - case MBIM_CID_PACKET_SERVICE: { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer; - mbim_dump_packet_service(pInfo, direction); - } - break; - default: - break; - } - } - else if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16)) { - } - } - break; - case MBIM_FUNCTION_ERROR_MSG: { - MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T*)pMsg; - mbim_debug("%s ErrorStatusCode = %u", direction, le32toh(pErrMsg->ErrorStatusCode)); - } - break; - default: - break; - } -} - -static void mbim_recv_command(MBIM_MESSAGE_HEADER *pResponse, unsigned size) -{ - (void)size; - pthread_mutex_lock(&mbim_command_mutex); - - if (pResponse) - mbim_dump(pResponse, mbim_verbose); - - if (pResponse == NULL) { - pthread_cond_signal(&mbim_command_cond); - } - else if (mbim_pRequest && le32toh(mbim_pRequest->TransactionId) == le32toh(pResponse->TransactionId)) { - mbim_pResponse = mbim_alloc(le32toh(pResponse->MessageLength)); - if (mbim_pResponse) - memcpy(mbim_pResponse, pResponse, le32toh(pResponse->MessageLength)); - pthread_cond_signal(&mbim_command_cond); - } - else if (le32toh(pResponse->MessageType) == MBIM_INDICATE_STATUS_MSG) { - MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pResponse; - - if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) - { - switch (le32toh(pIndMsg->CID)) { - case MBIM_CID_SUBSCRIBER_READY_STATUS: { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer; - if (oldReadyState != le32toh(pInfo->ReadyState)) - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } - break; - case MBIM_CID_REGISTER_STATE: { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer; - if (oldRegisterState != le32toh(pInfo->RegisterState)) - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } - break; - case MBIM_CID_PACKET_SERVICE: { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer; - MBIM_PACKET_SERVICE_STATE_E state = le32toh(pInfo->PacketServiceState); - - if (oldPacketServiceState != state - && (1 || MBIMPacketServiceStateAttached == state || MBIMPacketServiceStateDetached == state)) - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } - break; - case MBIM_CID_CONNECT: { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer; - if (pInfo->SessionId == (uint32_t)mbim_sessionID) { - MBIM_ACTIVATION_STATE_E state = le32toh(pInfo->ActivationState); - - if (oldActivationState != state - && (1 || MBIMActivationStateActivated == state || MBIMActivationStateDeactivated == state)) - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } - } - break; - default: - break; - } - } - } - - pthread_mutex_unlock(&mbim_command_mutex); -} - -static int mbim_send_command(MBIM_MESSAGE_HEADER *pRequest, MBIM_COMMAND_DONE_T **ppCmdDone, unsigned msecs) { - int ret; - - if (ppCmdDone) - *ppCmdDone = NULL; - - if (mbim_fd <= 0) - return -ENODEV; - - if (s_tid_reader == 0) - return -EINVAL; - - if (!pRequest) - return -ENOMEM; - - pthread_mutex_lock(&mbim_command_mutex); - - if (pRequest) { - if (pRequest->TransactionId == (0xFFFFFF + 1)) { //quectel-mbim-proxy need 0xFF000000 to indicat client - TransactionId = 1; - pRequest->TransactionId = htole32(TransactionId++); - } - mbim_dump(pRequest, mbim_verbose); - } - - mbim_pRequest = pRequest; - mbim_pResponse = NULL; - - ret = write(mbim_fd, pRequest, le32toh(pRequest->MessageLength)); - - if (ret > 0 && (uint32_t)ret == le32toh(pRequest->MessageLength)) { - ret = pthread_cond_timeout_np(&mbim_command_cond, &mbim_command_mutex, msecs); - if (!ret) { - if (mbim_pResponse && ppCmdDone) { - *ppCmdDone = (MBIM_COMMAND_DONE_T *)mbim_pResponse; - } - } - } else { - mbim_debug("%s pthread_cond_timeout_np=%d", __func__, ret); - } - - mbim_pRequest = mbim_pResponse = NULL; - - pthread_mutex_unlock(&mbim_command_mutex); - - return ret; -} - -static ssize_t mbim_proxy_read (int fd, MBIM_MESSAGE_HEADER *pResponse, size_t size) { - ssize_t nreads; - - nreads = read(fd, pResponse, sizeof(MBIM_MESSAGE_HEADER)); - if (nreads == sizeof(MBIM_MESSAGE_HEADER) && le32toh(pResponse->MessageLength) <= size) { - nreads += read(fd, pResponse+1, le32toh(pResponse->MessageLength) - sizeof(MBIM_MESSAGE_HEADER)); - } - - return nreads; -} - -static void * mbim_read_thread(void *param) { - PROFILE_T *profile = (PROFILE_T *)param; - const char *cdc_wdm = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - - mbim_verbose = debug_qmi; - s_tid_reader = pthread_self(); - - if (profile->qmap_mode > 1 && profile->qmapnet_adapter[0]) { - if (!profile->proxy[0]) - sprintf(profile->proxy, "%s", QUECTEL_MBIM_PROXY); - mbim_sessionID = profile->pdp; - } - - if (profile->proxy[0]) { - mbim_fd = cm_open_proxy(profile->proxy); - } - else { - mbim_fd = cm_open_dev(cdc_wdm); - } - - if (mbim_fd <= 0) { - mbim_debug("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno)); - goto __quit; - } - - dbg_time("cdc_wdm_fd = %d", mbim_fd); - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (mbim_fd > 0) { - struct pollfd pollfds[] = {{mbim_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}, {qmi_over_mbim_sk[1], POLLIN, 0}}; - int ne, ret, nevents = 2; - - if (pollfds[nevents].fd != -1) - nevents++; - - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - - if (ret == 0 && wait_for_request_quit) { - break; - } - - if (ret < 0) { - mbim_debug("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - mbim_debug("%s poll err/hup/inval", __func__); - mbim_debug("epoll fd = %d, events = 0x%04x", fd, revents); - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (mbim_fd == fd) { - ssize_t nreads; - MBIM_MESSAGE_HEADER *pResponse = (MBIM_MESSAGE_HEADER *) cm_recv_buf; - - if (profile->proxy[0]) - nreads = mbim_proxy_read(fd, pResponse, sizeof(cm_recv_buf)); - else - nreads = read(fd, pResponse, sizeof(cm_recv_buf)); - - if (nreads <= 0) { - mbim_debug("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - break; - } - - mbim_recv_command(pResponse, nreads); - } - else if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //mbim_debug("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - else if (fd == qmi_over_mbim_sk[1]) { - ssize_t nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf)); - if (nreads > 0) - QmiThreadRecvQMI((PQCQMIMSG)cm_recv_buf); - } - } - } - -__quit: - if (mbim_fd != -1) { close(mbim_fd); mbim_fd = -1; } - mbim_recv_command(NULL, 0); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - mbim_debug("%s exit", __func__); - s_tid_reader = 0; - - return NULL; -} - -static int mbim_status_code(MBIM_MESSAGE_HEADER *pMsgHdr) { - int status = 0; - - if (!pMsgHdr) - return 0; - - switch (le32toh(pMsgHdr->MessageType)) { - case MBIM_OPEN_DONE: { - MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsgHdr; - status = le32toh(pOpenDone->Status); - } - break; - case MBIM_CLOSE_DONE: { - MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsgHdr; - status = le32toh(pCloseDone->Status); - } - break; - case MBIM_COMMAND_DONE: { - MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsgHdr; - status = le32toh(pCmdDone->Status); - } - break; - case MBIM_FUNCTION_ERROR_MSG: { - MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T *)pMsgHdr; - status = le32toh(pErrMsg->ErrorStatusCode); - if (status == MBIM_ERROR_NOT_OPENED) - mbim_open_state = 0; //EM06ELAR03A05M4G when suspend/resume, may get this error - } - break; - default: - break; - } - - return status; -} - -#define mbim_check_err(err, pRequest, pCmdDone) do { \ - int _status = mbim_status_code(pCmdDone ? &pCmdDone->MessageHeader : NULL); \ - if (err || _status || !pCmdDone) { \ - if (pCmdDone) { mbim_dump(&pCmdDone->MessageHeader, (mbim_verbose == 0)); } \ - mbim_free(pRequest); mbim_free(pCmdDone); \ - mbim_debug("%s:%d err=%d, Status=%d", __func__, __LINE__, err, _status); \ - if (err) return err; \ - if (_status) return _status; \ - return 8888; \ - } \ -} while(0) - -/* - * MBIM device can be open repeatly without error - * So, we can call the function, no matter it have been opened or not - */ -static int mbim_open_device(uint32_t MaxControlTransfer) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_OPEN_DONE_T *pOpenDone = NULL; - int err = 0; - - mbim_debug("%s()", __func__); - pRequest = compose_open_command(MaxControlTransfer); - err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pOpenDone, 3*1000); //EM06ELAR03A09M4G take about 2.5 seconds - mbim_check_err(err, pRequest, pOpenDone); - - err = le32toh(pOpenDone->Status); - mbim_free(pRequest); mbim_free(pOpenDone); - - return err; -} - -static int mbim_close_device(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_CLOSE_DONE_T *pCloseDone = NULL; - int err = 0; - - mbim_debug("%s()", __func__); - pRequest = compose_close_command(); - err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pCloseDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCloseDone); - - err = le32toh(pCloseDone->Status); - mbim_free(pRequest); mbim_free(pCloseDone); - - return err; -} - -static int mbim_query_connect(int sessionID) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_SET_CONNECT_T set_connect; - int err; - - if (ActivationState != MBIMActivationStateActivated || mbim_verbose) - mbim_debug("%s(sessionID=%d)", __func__, sessionID); //avoid two many log - set_connect.SessionId = htole32(sessionID); - pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_QUERY, &set_connect, sizeof(set_connect)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) - { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; - ActivationState = le32toh(pInfo->ActivationState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_ms_version_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - struct _bc_ext_version { - UINT8 ver_minor; - UINT8 ver_major; - UINT8 ext_ver_minor; - UINT8 ext_ver_major; - } __attribute__ ((packed)) bc_ext_version; - - bc_ext_version.ver_major = 1; - bc_ext_version.ver_minor = 0; - bc_ext_version.ext_ver_major = 2; - bc_ext_version.ext_ver_minor = 0; - - pRequest = compose_basic_connect_ext_command(MBIM_CID_MS_VERSION, MBIM_CID_CMD_TYPE_QUERY, &bc_ext_version, sizeof(bc_ext_version)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - struct _bc_ext_version *pInfo = (struct _bc_ext_version *)pCmdDone->InformationBuffer; - //mbim_debug("%s ext_rel_ver major=%d, minor=%d", __func__, pInfo->ext_ver_major, pInfo->ext_ver_minor); - mbim_ms_version = pInfo->ext_ver_major; - } - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_device_services_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - int mbim_v2_support = 0; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_SERVICES, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (pCmdDone->InformationBufferLength) { - MBIM_DEVICE_SERVICES_INFO_T *pInfo = (MBIM_DEVICE_SERVICES_INFO_T *)pCmdDone->InformationBuffer; - UINT32 i; - - for (i = 0; i < le32toh(pInfo->DeviceServicesCount) ; i++) { - //UINT32 size = pInfo->DeviceServicesRefList[i].size; - UINT32 offset = le32toh(pInfo->DeviceServicesRefList[i].offset); - MBIM_DEVICE_SERVICE_ELEMENT_T *pSrvEle = (MBIM_DEVICE_SERVICE_ELEMENT_T *)((void *)pInfo + offset); - - //mbim_debug("\t[%2d] %s (%s)", i, DeviceServiceId2str(&pSrvEle->DeviceServiceId), uuid2str(&pSrvEle->DeviceServiceId)); - if (!strcasecmp(UUID_BASIC_CONNECT_EXT, uuid2str(&pSrvEle->DeviceServiceId))) { - UINT32 cid = 0; - - for (cid = 0; cid < le32toh(pSrvEle->CidCount); cid++) { - if (MBIM_CID_MS_VERSION == le32toh(pSrvEle->CidList[cid])) { - mbim_v2_support = 1; - } - } - } - else if (!strcasecmp(uuid_ext_qmux, uuid2str(&pSrvEle->DeviceServiceId))) { - qmi_over_mbim_support = 1; - } - } - } - mbim_free(pRequest); mbim_free(pCmdDone); - - if (mbim_v2_support) { - mbim_ms_version_query(); - } - - return err; -} - -static int mbim_device_caps_query(PROFILE_T *profile) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_CAPS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_DEVICE_CAPS_INFO_T *pInfo = (MBIM_DEVICE_CAPS_INFO_T *)pCmdDone->InformationBuffer; - char tmp[32]; - - if (le32toh(pInfo->DeviceIdOffset) && le32toh(pInfo->DeviceIdSize)) { - wchar2char((const char *)pInfo + le32toh(pInfo->DeviceIdOffset), le32toh(pInfo->DeviceIdSize), tmp, sizeof(tmp)); - mbim_debug("DeviceId: %s", tmp); - } - if (le32toh(pInfo->FirmwareInfoOffset) && le32toh(pInfo->FirmwareInfoSize)) { - wchar2char((const char *)pInfo + le32toh(pInfo->FirmwareInfoOffset), le32toh(pInfo->FirmwareInfoSize), tmp, sizeof(tmp)); - strncpy(profile->BaseBandVersion, tmp, sizeof(profile->BaseBandVersion)); - mbim_debug("FirmwareInfo: %s", tmp); - } - if (le32toh(pInfo->HardwareInfoOffset) && le32toh(pInfo->HardwareInfoSize)) { - wchar2char((const char *)pInfo + le32toh(pInfo->HardwareInfoOffset), le32toh(pInfo->HardwareInfoSize), tmp, sizeof(tmp)); - mbim_debug("HardwareInfo: %s", tmp); - } - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -#if 0 -static int mbim_radio_state_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (pCmdDone->InformationBufferLength) { - MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer; - mbim_debug("HwRadioState: %d, SwRadioState: %d", pInfo->HwRadioState, pInfo->SwRadioState); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} -#endif - -static int mbim_set_radio_state(MBIM_RADIO_SWITCH_STATE_E RadioState) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - UINT32 value = htole32(RadioState); - int err; - - mbim_debug("%s( %d )", __func__, RadioState); - pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer; - mbim_debug("HwRadioState: %d, SwRadioState: %d", le32toh(pInfo->HwRadioState), le32toh(pInfo->SwRadioState)); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_subscriber_status_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer; - char tmp[32]; - - wchar2char((const char *)pInfo + le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize), tmp, sizeof(tmp)); - mbim_debug("SubscriberId: %s", tmp); - wchar2char((const char *)pInfo + le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize), tmp, sizeof(tmp)); - mbim_debug("SimIccId: %s", tmp); - ReadyState = le32toh(pInfo->ReadyState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_register_state_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_REGISTER_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer;; - RegisterState = le32toh(pInfo->RegisterState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_packet_service_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; - PacketServiceState = le32toh(pInfo->PacketServiceState); - mbim_update_state(); - - if (le32toh(pCmdDone->InformationBufferLength) == sizeof(MBIM_PACKET_SERVICE_INFO_V2_T)) { - MBIM_PACKET_SERVICE_INFO_V2_T *pInfo = (MBIM_PACKET_SERVICE_INFO_V2_T *)pCmdDone->InformationBuffer; - mbim_debug("CurrentDataClass = %s", MBIMDataClassStr(le32toh(pInfo->CurrentDataClass))); - } - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_packet_service_set(MBIM_PACKET_SERVICE_ACTION_E action) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - UINT32 value = htole32(action); - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; - PacketServiceState = le32toh(pInfo->PacketServiceState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -#define _align_32(len) {len += (len % 4) ? (4 - (len % 4)) : 0;} -static int mbim_populate_connect_data(MBIM_SET_CONNECT_T **connect_req_ptr) { - int offset; - int buflen = 0; - - if (mbim_apn && strlen(mbim_apn) > 0) buflen += 2*strlen(mbim_apn) ; - _align_32(buflen); - if (mbim_user && strlen(mbim_user) > 0) buflen += 2*strlen(mbim_user); - _align_32(buflen); - if (mbim_passwd && strlen(mbim_passwd) > 0) buflen += 2*strlen(mbim_passwd); - _align_32(buflen); - - *connect_req_ptr = (MBIM_SET_CONNECT_T*)malloc(sizeof(MBIM_SET_CONNECT_T) + buflen); - if (! *connect_req_ptr) { - mbim_debug("not enough memory\n"); - return -1; - } - memset(*connect_req_ptr, 0, sizeof(MBIM_SET_CONNECT_T) + buflen); - - offset = 0; - if (mbim_apn && strlen(mbim_apn) > 0) { - (*connect_req_ptr)->AccessStringSize = htole32(2*strlen(mbim_apn)); - (*connect_req_ptr)->AccessStringOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); - offset = char2wchar(mbim_apn, strlen(mbim_apn), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); - _align_32(offset); - } - - if (mbim_user && strlen(mbim_user) > 0) { - (*connect_req_ptr)->UserNameSize = htole32(2*strlen(mbim_user)); - (*connect_req_ptr)->UserNameOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); - offset = char2wchar(mbim_user, strlen(mbim_user), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); - _align_32(offset); - } - - if (mbim_passwd && strlen(mbim_passwd) > 0) { - (*connect_req_ptr)->PasswordSize = htole32(2*strlen(mbim_passwd)); - (*connect_req_ptr)->PasswordOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); - offset = char2wchar(mbim_passwd, strlen(mbim_passwd), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); - } - - return buflen; -} - -static int mbim_set_connect(int onoff, int sessionID) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_SET_CONNECT_T *set_connect = NULL; - int err; - - mbim_debug("%s(onoff=%d, sessionID=%d)", __func__, onoff, sessionID); - /* alloc memory then populate APN USERNAME PASSWORD */ - int buflen = mbim_populate_connect_data(&set_connect); - if (buflen < 0) { - return ENOMEM; - } - - set_connect->SessionId = htole32(sessionID); - if (onoff == 0) - set_connect->ActivationCommand = htole32(MBIMActivationCommandDeactivate); - else - set_connect->ActivationCommand = htole32(MBIMActivationCommandActivate); - - set_connect->Compression = htole32(MBIMCompressionNone); - set_connect->AuthProtocol = htole32(mbim_auth); - set_connect->IPType = htole32(mbim_iptype); - memcpy(set_connect->ContextType.uuid, str2uuid(UUID_MBIMContextTypeInternet), 16); - - pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_SET, set_connect, sizeof(MBIM_SET_CONNECT_T) + buflen); - mbim_free(set_connect); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout*10); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; - ActivationState = le32toh(pInfo->ActivationState); - mbim_update_state(); - } - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_ip_config(PROFILE_T *profile, int sessionID) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_IP_CONFIGURATION_INFO_T ip_info; - int err; - - if (profile->ipv4.Address == 0 || mbim_verbose) - mbim_debug("%s(sessionID=%d)", __func__, sessionID); - ip_info.SessionId = htole32(sessionID); - pRequest = compose_basic_connect_command(MBIM_CID_IP_CONFIGURATION, MBIM_CID_CMD_TYPE_QUERY, &ip_info, sizeof(ip_info)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - UINT8 prefix, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL; - UINT32 mtu = 1500; - MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer; - - /* IPv4 network configration */ - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) { - MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv4 = pAddress->IPv4Address; - - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x4) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - if (le32toh(pInfo->IPv4DnsServerCount) == 2) - dns2 = dns1 + 4; - } - - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x8) - mtu = le32toh(pInfo->IPv4Mtu); - - if (profile->ipv4.Address != mbim2qmi_ipv4addr(*(uint32_t *)ipv4) || mbim_verbose) { - mbim_dump_ipconfig(pInfo, "<"); - profile->ipv4.Address = mbim2qmi_ipv4addr(*(uint32_t *)ipv4); - } - - if(gw != NULL) - profile->ipv4.Gateway = mbim2qmi_ipv4addr(*(uint32_t *)gw); - profile->ipv4.SubnetMask = mbim2qmi_ipv4addr(0xFFFFFFFF>>(32-prefix)<<(32-prefix)); - if(dns1 != NULL) - profile->ipv4.DnsPrimary = mbim2qmi_ipv4addr(*(uint32_t *)dns1); - if(dns2 != NULL) - profile->ipv4.DnsSecondary = mbim2qmi_ipv4addr(*(uint32_t *)dns2); - profile->ipv4.Mtu = mbim2qmi_ipv4addr(mtu); - } - - /* IPv6 network configration */ - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) { - gw = NULL; dns1 = NULL; dns2 = NULL; - MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv6 = pAddress->IPv6Address; - - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x4) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - if (le32toh(pInfo->IPv6DnsServerCount) == 2) - dns2 = dns1 + 16; - } - - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x8) - mtu = le32toh(pInfo->IPv6Mtu); - - if(ipv6 != NULL) - mbim2qmi_ipv6addr(ipv6, profile->ipv6.Address); - if(gw != NULL) - mbim2qmi_ipv6addr(gw, profile->ipv6.Gateway); - if(dns1 != NULL) - mbim2qmi_ipv6addr(dns1, profile->ipv6.DnsPrimary); - if(dns2 != NULL) - mbim2qmi_ipv6addr(dns2, profile->ipv6.DnsSecondary); - profile->ipv6.PrefixLengthIPAddr = prefix; - profile->ipv6.PrefixLengthGateway = prefix; - profile->ipv6.Mtu = mbim2qmi_ipv4addr(mtu); - } - } - return err; -} - -int mbim_proxy_configure(const char *dev) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_LIBQMI_PROXY_CONFIG_T *cfg; - int err; - - pRequest = compose_basic_connect_command( - MBIM_CID_PROXY_CONTROL_CONFIGURATION, - MBIM_CID_CMD_TYPE_SET, - NULL, - sizeof(*cfg) + strlen(dev)*2); - if (pRequest) { - memcpy(((MBIM_COMMAND_MSG_T *)pRequest)->DeviceServiceId.uuid, str2uuid(UUID_LIBMBIM_PROXY), 16); - cfg = (MBIM_LIBQMI_PROXY_CONFIG_T *)((MBIM_COMMAND_MSG_T *)pRequest)->InformationBuffer; - - cfg->DevicePathOffset = sizeof(*cfg); - cfg->DevicePathSize = char2wchar(dev, strlen(dev), cfg->DataBuffer, strlen(dev)*2); - cfg->Timeout = 15; - } - - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_update_state(void) { - int chages = 0; - - if (oldReadyState != ReadyState) { - mbim_debug("SubscriberReadyState %s -> %s ", MBIMSubscriberReadyStateStr(oldReadyState), MBIMSubscriberReadyStateStr(ReadyState)); - oldReadyState = ReadyState; chages++; - } - if (oldRegisterState != RegisterState) { - mbim_debug("RegisterState %s -> %s ", MBIMRegisterStateStr(oldRegisterState), MBIMRegisterStateStr(RegisterState)); - oldRegisterState = RegisterState; chages++; - } - if (oldPacketServiceState != PacketServiceState) { - mbim_debug("PacketServiceState %s -> %s ", MBIMPacketServiceStateStr(oldPacketServiceState), MBIMPacketServiceStateStr(PacketServiceState)); - oldPacketServiceState = PacketServiceState; chages++; - } - if (oldActivationState != ActivationState) { - mbim_debug("ActivationState %s -> %s ", MBIMActivationStateStr(oldActivationState), MBIMActivationStateStr(ActivationState)); - oldActivationState = ActivationState; chages++; - } - - return chages; -} - -static int mbim_init(PROFILE_T *profile) { - int retval; - int t = 0; - - if (profile->proxy[0] && !strcmp(profile->proxy, LIBMBIM_PROXY)) { - retval = mbim_proxy_configure(profile->qmichannel); - if (retval) goto exit; - } - - while (t++ < 10) { - retval = mbim_open_device(4096); - if (retval != ETIMEDOUT) - break; - } - if (retval) goto exit; - retval = mbim_device_caps_query(profile); - if (retval) goto exit; - mbim_update_state(); - retval = mbim_device_services_query(); - if (retval) goto exit; - mbim_update_state(); - retval = mbim_set_radio_state(MBIMRadioOn); - if (retval) goto exit; - mbim_update_state(); - - if (qmi_over_mbim_support) { - if (!socketpair( AF_LOCAL, SOCK_STREAM, 0, qmi_over_mbim_sk)) { - qmidev_send = qmi_over_mbim_qmidev_send; -#ifdef CONFIG_CELLINFO //by now, only this function need QMI OVER MBIM - qmi_over_mbim_nas = qmi_over_mbim_get_client_id(QMUX_TYPE_NAS); -#endif - } - } - - return 0; - -exit: - return retval; -} - -static int mbim_deinit(void) { - if (qmi_over_mbim_nas) { - qmi_over_mbim_release_client_id(QMUX_TYPE_NAS, qmi_over_mbim_nas); - qmi_over_mbim_nas = 0; - } - - mbim_close_device(); - - if (qmi_over_mbim_sk[0] != -1) { - close(qmi_over_mbim_sk[0]); - close(qmi_over_mbim_sk[1]); - } - - return 0; -} - -const struct qmi_device_ops mbim_dev_ops = { - .init = mbim_init, - .deinit = mbim_deinit, - .read = mbim_read_thread, -}; - -static int requestBaseBandVersion(PROFILE_T *profile) { - (void)profile; - return 0; -} - -static int requestGetSIMStatus(SIM_Status *pSIMStatus) -{ - int retval; - - *pSIMStatus = SIM_ABSENT; - retval = mbim_subscriber_status_query(); - if (retval) - goto exit; - mbim_update_state(); - - switch(ReadyState) { - case MBIMSubscriberReadyStateNotInitialized: *pSIMStatus = SIM_NOT_READY; break; - case MBIMSubscriberReadyStateInitialized: *pSIMStatus = SIM_READY; break; - case MBIMSubscriberReadyStateSimNotInserted: *pSIMStatus = SIM_ABSENT; break; - case MBIMSubscriberReadyStateBadSim: *pSIMStatus = SIM_BAD; break; - case MBIMSubscriberReadyStateFailure: *pSIMStatus = SIM_ABSENT; break; - case MBIMSubscriberReadyStateNotActivated: *pSIMStatus = SIM_ABSENT; break; - case MBIMSubscriberReadyStateDeviceLocked: *pSIMStatus = SIM_PIN; break; - default: *pSIMStatus = SIM_ABSENT; break; - } - -exit: - return retval; -} - -static int requestRegistrationState(UCHAR *pPSAttachedState) { - int retval; - - *pPSAttachedState = 0; - retval = mbim_register_state_query(); - if (retval) - goto exit; - mbim_update_state(); - - switch (RegisterState) { - case MBIMRegisterStateUnknown: *pPSAttachedState = 0; break; - case MBIMRegisterStateDeregistered: *pPSAttachedState = 0; break; - case MBIMRegisterStateSearching: *pPSAttachedState = 0; break; - case MBIMRegisterStateHome: *pPSAttachedState = 1; break; - case MBIMRegisterStateRoaming: *pPSAttachedState = 1; break; - case MBIMRegisterStatePartner: *pPSAttachedState = 0; break; - case MBIMRegisterStateDenied: *pPSAttachedState = 0; break; - default: *pPSAttachedState = 0; break; - } - - if (*pPSAttachedState == 0) - goto exit; - - retval = mbim_packet_service_query(); - if (retval) - goto exit; - - switch (PacketServiceState) { - case MBIMPacketServiceStateUnknown: *pPSAttachedState = 0; break; - case MBIMPacketServiceStateAttaching: *pPSAttachedState = 0; break; - case MBIMPacketServiceStateAttached: *pPSAttachedState = 1; break; - case MBIMPacketServiceStateDetaching: *pPSAttachedState = 0; break; - case MBIMPacketServiceStateDetached: *pPSAttachedState = 0; break; - default: *pPSAttachedState = 0; break; - } - - if (*pPSAttachedState == 0) - mbim_packet_service_set(MBIMPacketServiceActionAttach); - -exit: - return retval; -} - -static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { - int retval; - - (void)curIpFamily; - - if (profile->apn) - mbim_apn = profile->apn; - if (profile->user) - mbim_user = profile->user; - if (profile->password) - mbim_passwd = profile->password; - if (profile->auth) - mbim_auth = profile->auth; - if (profile->enable_ipv4) - mbim_iptype = MBIMContextIPTypeIPv4; - if (profile->enable_ipv6) - mbim_iptype = MBIMContextIPTypeIPv6; - if (profile->enable_ipv4 && profile->enable_ipv6) - mbim_iptype = MBIMContextIPTypeIPv4AndIPv6; - - retval = mbim_set_connect(1, mbim_sessionID); - if (retval) - goto exit; - -exit: - return retval; -} - -static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { - int retval; - - (void)curIpFamily; - - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - - retval = mbim_query_connect(mbim_sessionID); - if (retval) - goto exit; - - switch(ActivationState) { - case MBIMActivationStateUnknown: *pConnectionStatus = QWDS_PKT_DATA_UNKNOW; break; - case MBIMActivationStateActivated: *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; break; - case MBIMActivationStateActivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - case MBIMActivationStateDeactivated: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - case MBIMActivationStateDeactivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - default: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - } - -exit: - return retval; -} - -static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { - int retval; - - (void)profile; - (void)curIpFamily; - - retval = mbim_set_connect(0, mbim_sessionID); - if (retval) - goto exit; - -exit: - return retval; -} - -static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { - int retval; - - (void)curIpFamily; - retval = mbim_ip_config(profile, mbim_sessionID); - if (retval) - goto exit; - -exit: - return retval; -} - -#ifdef CONFIG_CELLINFO -static int requestGetCellInfoList(void) { - if (qmi_over_mbim_nas) { - if (qmi_request_ops.requestGetCellInfoList) - return qmi_request_ops.requestGetCellInfoList(); - } - - return 0; -} -#endif - -const struct request_ops mbim_request_ops = { - .requestBaseBandVersion = requestBaseBandVersion, - .requestGetSIMStatus = requestGetSIMStatus, - .requestRegistrationState = requestRegistrationState, - .requestSetupDataCall = requestSetupDataCall, - .requestQueryDataCall = requestQueryDataCall, - .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, - .requestGetIPAddress = requestGetIPAddress, -#ifdef CONFIG_CELLINFO - .requestGetCellInfoList = requestGetCellInfoList, -#endif -}; - -int qmi_over_mbim_qmidev_send(PQCQMIMSG pQMI) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - size_t len = le16toh(pQMI->QMIHdr.Length) + 1; - - if (pQMI->QMIHdr.QMIType != QMUX_TYPE_CTL) { - if (pQMI->QMIHdr.QMIType == QMUX_TYPE_NAS) - pQMI->QMIHdr.ClientId = qmi_over_mbim_nas; - - if (pQMI->QMIHdr.ClientId == 0) { - dbg_time("QMIType %d has no clientID", pQMI->QMIHdr.QMIType); - return -ENODEV; - } - } - - pRequest = compose_qmi_over_mbim_command(1, MBIM_CID_CMD_TYPE_SET, pQMI, len); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - err = -1; - len = le32toh(pCmdDone->InformationBufferLength); - if (len) { - if (write(qmi_over_mbim_sk[0], pCmdDone->InformationBuffer, len) == (long)len) { - err = 0; - }; - } - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} diff --git a/quectel_cm_5G/src/qendian.h b/quectel_cm_5G/src/qendian.h deleted file mode 100644 index 5e99d5f..0000000 --- a/quectel_cm_5G/src/qendian.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __QUECTEL_ENDIAN_H__ -#define __QUECTEL_ENDIAN_H__ -#include - -#ifndef htole32 -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define htole16(x) (uint16_t)(x) -#define le16toh(x) (uint16_t)(x) -#define letoh16(x) (uint16_t)(x) -#define htole32(x) (uint32_t)(x) -#define le32toh(x) (uint32_t)(x) -#define letoh32(x) (uint32_t)(x) -#define htole64(x) (uint64_t)(x) -#define le64toh(x) (uint64_t)(x) -#define letoh64(x) (uint64_t)(x) -#else -static __inline uint16_t __bswap16(uint16_t __x) { - return (__x<<8) | (__x>>8); -} - -static __inline uint32_t __bswap32(uint32_t __x) { - return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); -} - -static __inline uint64_t __bswap64(uint64_t __x) { - return (__bswap32(__x)+0ULL<<32) | (__bswap32(__x>>32)); -} - -#define htole16(x) __bswap16(x) -#define le16toh(x) __bswap16(x) -#define letoh16(x) __bswap16(x) -#define htole32(x) __bswap32(x) -#define le32toh(x) __bswap32(x) -#define letoh32(x) __bswap32(x) -#define htole64(x) __bswap64(x) -#define le64toh(x) __bswap64(x) -#define letoh64(x) __bswap64(x) -#endif -#endif - -#define le16_to_cpu(x) le16toh((uint16_t)(x)) -#define le32_to_cpu(x) le32toh((uint32_t)(x)) -#define le64_to_cpu(x) le64toh((uint64_t)(x)) -#define cpu_to_le16(x) htole16((uint16_t)(x)) -#define cpu_to_le32(x) htole32((uint32_t)(x)) -#define cpu_to_le64(x) htole64((uint64_t)(x)) - -static __inline uint32_t ql_swap32(uint32_t __x) { - return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); -} -#endif //__QUECTEL_ENDIAN_H__ - diff --git a/quectel_cm_5G/src/qlist.h b/quectel_cm_5G/src/qlist.h deleted file mode 100644 index c7f95cf..0000000 --- a/quectel_cm_5G/src/qlist.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __QUECTEL_LIST_H__ -#define __QUECTEL_LIST_H__ -struct qlistnode -{ - struct qlistnode *next; - struct qlistnode *prev; -}; - -#define qnode_to_item(node, container, member) \ - (container *) (((char*) (node)) - offsetof(container, member)) - -#define qlist_for_each(node, list) \ - for (node = (list)->next; node != (list); node = node->next) - -#define qlist_empty(list) ((list) == (list)->next) -#define qlist_head(list) ((list)->next) -#define qlist_tail(list) ((list)->prev) - -static void qlist_init(struct qlistnode *node) -{ - node->next = node; - node->prev = node; -} - -static void qlist_add_tail(struct qlistnode *head, struct qlistnode *item) -{ - item->next = head; - item->prev = head->prev; - head->prev->next = item; - head->prev = item; -} - -static void qlist_remove(struct qlistnode *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; -} -#endif \ No newline at end of file diff --git a/quectel_cm_5G/src/qmap_bridge_mode.c b/quectel_cm_5G/src/qmap_bridge_mode.c deleted file mode 100644 index 0148b0f..0000000 --- a/quectel_cm_5G/src/qmap_bridge_mode.c +++ /dev/null @@ -1,402 +0,0 @@ -/****************************************************************************** - @file qmap_bridge_mode.c - @brief Connectivity bridge manager. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include "QMIThread.h" - -static size_t ql_fread(const char *filename, void *buf, size_t size) { - FILE *fp = fopen(filename , "r"); - size_t n = 0; - - memset(buf, 0x00, size); - - if (fp) { - n = fread(buf, 1, size, fp); - if (n <= 0 || n == size) { - dbg_time("warnning: fail to fread(%s), fread=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -static size_t ql_fwrite(const char *filename, const void *buf, size_t size) { - FILE *fp = fopen(filename , "w"); - size_t n = 0; - - if (fp) { - n = fwrite(buf, 1, size, fp); - if (n != size) { - dbg_time("warnning: fail to fwrite(%s), fwrite=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -int ql_bridge_mode_detect(PROFILE_T *profile) { - const char *ifname = profile->qmapnet_adapter[0] ? profile->qmapnet_adapter : profile->usbnet_adapter; - const char *driver; - char bridge_mode[128]; - char bridge_ipv4[128]; - char ipv4[128]; - char buf[64]; - size_t n; - int in_bridge = 0; - - driver = profile->driver_name; - snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode", ifname); - snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4", ifname); - - if (access(bridge_ipv4, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno)); - return 0; - } - - snprintf(bridge_mode, sizeof(bridge_mode), "/sys/module/%s/parameters/bridge_mode", driver); - snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/module/%s/parameters/bridge_ipv4", driver); - - if (access(bridge_mode, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno)); - } - return 0; - } - } - - n = ql_fread(bridge_mode, buf, sizeof(buf)); - if (n > 0) { - in_bridge = (buf[0] != '0'); - } - if (!in_bridge) - return 0; - - memset(ipv4, 0, sizeof(ipv4)); - - if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 || profile->qmap_mode == 1) { - snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address); - dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); - ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); - } - else { - snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address, profile->muxid); - dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); - ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); - } - - return in_bridge; -} - -int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile) { - char filename[256]; - char buf[4]; - size_t n; - FILE *fp; - - if (!qmidev_is_qmiwwan(profile->qmichannel)) - return 0; - - snprintf(filename, sizeof(filename), "/sys/class/net/%s/qmi/rawip", profile->usbnet_adapter); - n = ql_fread(filename, buf, sizeof(buf)); - - if (n == 0) - return 0; - - if (buf[0] == '1' || buf[0] == 'Y') - return 0; - - fp = fopen(filename , "w"); - if (fp == NULL) { - dbg_time("Fail to fopen(%s, \"w\"), errno: %d (%s)", filename, errno, strerror(errno)); - return 1; - } - - buf[0] = 'Y'; - n = fwrite(buf, 1, 1, fp); - if (n != 1) { - dbg_time("Fail to fwrite(%s), errno: %d (%s)", filename, errno, strerror(errno)); - fclose(fp); - return 1; - } - fclose(fp); - - return 0; -} - -int ql_driver_type_detect(PROFILE_T *profile) { - if (qmidev_is_gobinet(profile->qmichannel)) { - profile->qmi_ops = &gobi_qmidev_ops; - } - else { - profile->qmi_ops = &qmiwwan_qmidev_ops; - } - qmidev_send = profile->qmi_ops->send; - - return 0; -} - -void ql_set_driver_bridge_mode(PROFILE_T *profile) { - char enable[16]; - char filename[256]; - - if(profile->qmap_mode) - snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->qmapnet_adapter); - else - snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->usbnet_adapter); - snprintf(enable, sizeof(enable), "%02d\n", profile->enable_bridge); - ql_fwrite(filename, enable, sizeof(enable)); -} - -static int ql_qmi_qmap_mode_detect(PROFILE_T *profile) { - char buf[128]; - int n; - struct { - char filename[255 * 2]; - char linkname[255 * 2]; - } *pl; - - pl = (typeof(pl)) malloc(sizeof(*pl)); - - snprintf(pl->linkname, sizeof(pl->linkname), "/sys/class/net/%s/device/driver", profile->usbnet_adapter); - n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); - pl->filename[n] = '\0'; - while (pl->filename[n] != '/') - n--; - strncpy(profile->driver_name, &pl->filename[n+1], sizeof(profile->driver_name) - 1); - - ql_get_driver_rmnet_info(profile, &profile->rmnet_info); - if (profile->rmnet_info.size) { - profile->qmap_mode = profile->rmnet_info.qmap_mode; - if (profile->qmap_mode) { - int offset_id = (profile->muxid == 0)? profile->pdp - 1 : profile->muxid - 0x81; - - if (profile->qmap_mode == 1) - offset_id = 0; - profile->muxid = profile->rmnet_info.mux_id[offset_id]; - strncpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id], sizeof(profile->qmapnet_adapter) - 1); - profile->qmap_size = profile->rmnet_info.rx_urb_size; - profile->qmap_version = profile->rmnet_info.qmap_version; - } - - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode", profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/module/%s/parameters/qmap_mode", profile->driver_name); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/device/driver/module/parameters/qmap_mode", profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - goto _out; - } - } - } - } - - if (!access(pl->filename, R_OK)) { - n = ql_fread(pl->filename, buf, sizeof(buf)); - if (n > 0) { - profile->qmap_mode = atoi(buf); - - if (profile->qmap_mode > 1) { - if(!profile->muxid) - profile->muxid = profile->pdp + 0x80; //muxis is 0x8X for PDN-X - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), - "%.16s.%d", profile->usbnet_adapter, profile->muxid - 0x80); - } if (profile->qmap_mode == 1) { - profile->muxid = 0x81; - strncpy(profile->qmapnet_adapter, profile->usbnet_adapter, sizeof(profile->qmapnet_adapter)); - } - } - } - else if (qmidev_is_qmiwwan(profile->qmichannel)) { - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d", profile->pdp - 1); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - } - goto _out; - } - - //upstream Kernel Style QMAP qmi_wwan.c - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); - n = ql_fread(pl->filename, buf, sizeof(buf)); - if (n >= 5) { - dbg_time("If use QMAP by /sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); - #if 1 - dbg_time("Please set mtu of wwan0 >= max dl qmap packet size"); - #else - dbg_time("File:%s Line:%d Please make sure add next patch to qmi_wwan.c", __func__, __LINE__); - /* - diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c - index 74bebbd..db8a777 100644 - --- a/drivers/net/usb/qmi_wwan.c - +++ b/drivers/net/usb/qmi_wwan.c - @@ -379,6 +379,24 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c - if (!ret) { - info->flags |= QMI_WWAN_FLAG_MUX; - ret = len; - +#if 1 //Add by Quectel - + if (le16_to_cpu(dev->udev->descriptor.idVendor) == 0x2c7c) { - + int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct); - + - + if (idProduct == 0x0121 || idProduct == 0x0125 || idProduct == 0x0435) //MDM9x07 - + dev->rx_urb_size = 4*1024; - + else if (idProduct == 0x0306) //MDM9x40 - + dev->rx_urb_size = 16*1024; - + else if (idProduct == 0x0512) //SDX20 - + dev->rx_urb_size = 32*1024; - + else if (idProduct == 0x0620) //SDX24 - + dev->rx_urb_size = 32*1024; - + else if (idProduct == 0x0800) //SDX55 - + dev->rx_urb_size = 32*1024; - + else - + dev->rx_urb_size = 32*1024; - + } - +#endif - } - err: - rtnl_unlock(); - */ - #endif - profile->qmap_mode = n/5; //0x11\n0x22\n0x33\n - if (profile->qmap_mode > 1) { - //PDN-X map to qmimux-X - if(!profile->muxid) { - profile->muxid = (buf[5*(profile->pdp - 1) + 2] - '0')*16 + (buf[5*(profile->pdp - 1) + 3] - '0'); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->pdp - 1); - } else { - profile->muxid = (buf[5*(profile->muxid - 0x81) + 2] - '0')*16 + (buf[5*(profile->muxid - 0x81) + 3] - '0'); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->muxid - 0x81); - } - } else if (profile->qmap_mode == 1) { - profile->muxid = (buf[5*0 + 2] - '0')*16 + (buf[5*0 + 3] - '0'); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), - "qmimux%d", 0); - } - } - } - -_out: - if (profile->qmap_mode) { - if (profile->qmap_size == 0) { - profile->qmap_size = 16*1024; - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_size", profile->usbnet_adapter); - if (!access(pl->filename, R_OK)) { - size_t n; - char buf[32]; - n = ql_fread(pl->filename, buf, sizeof(buf)); - if (n > 0) { - profile->qmap_size = atoi(buf); - } - } - } - - if (profile->qmap_version == 0) { - profile->qmap_version = WDA_DL_DATA_AGG_QMAP_ENABLED; - } - - dbg_time("qmap_mode = %d, qmap_version = %d, qmap_size = %d, muxid = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->qmap_version, profile->qmap_size, profile->muxid, profile->qmapnet_adapter); - } - ql_set_driver_bridge_mode(profile); - free(pl); - - return 0; -} - -static int ql_mbim_usb_vlan_mode_detect(PROFILE_T *profile) { - char tmp[128]; - - snprintf(tmp, sizeof(tmp), "/sys/class/net/%s.%d", profile->usbnet_adapter, profile->pdp); - if (!access(tmp, F_OK)) { - profile->qmap_mode = 4; - profile->muxid = profile->pdp; - no_trunc_strncpy(profile->qmapnet_adapter, tmp + strlen("/sys/class/net/"), sizeof(profile->qmapnet_adapter) - 1); - - dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); - } - - return 0; -} - -static int ql_mbim_mhi_qmap_mode_detect(PROFILE_T *profile) { - ql_get_driver_rmnet_info(profile, &profile->rmnet_info); - if (profile->rmnet_info.size) { - profile->qmap_mode = profile->rmnet_info.qmap_mode; - if (profile->qmap_mode) { - int offset_id = profile->pdp - 1; - - if (profile->qmap_mode == 1) - offset_id = 0; - profile->muxid = profile->pdp; - strcpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id]); - profile->qmap_size = profile->rmnet_info.rx_urb_size; - profile->qmap_version = profile->rmnet_info.qmap_version; - - dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); - } - - goto _out; - } - -_out: - return 0; -} - -int ql_qmap_mode_detect(PROFILE_T *profile) { - if (profile->software_interface == SOFTWARE_MBIM) { - if (profile->hardware_interface == HARDWARE_USB) - return ql_mbim_usb_vlan_mode_detect(profile); - else if (profile->hardware_interface == HARDWARE_PCIE) - return ql_mbim_mhi_qmap_mode_detect(profile); - } else if (profile->software_interface == SOFTWARE_QMI) { - return ql_qmi_qmap_mode_detect(profile); - } -#ifdef CONFIG_QRTR - else if(profile->software_interface == SOFTWARE_QRTR) { - char tmp[128]; - - profile->qmap_mode = 4; - profile->qmap_version = WDA_DL_DATA_AGG_QMAP_V5_ENABLED; - profile->qmap_size = 31*1024; - profile->muxid = 0x80 | profile->pdp; - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "rmnet_data%d", profile->muxid&0xF); - - snprintf(tmp, sizeof(tmp), "/sys/class/net/%s", profile->qmapnet_adapter); - if (access(tmp, F_OK)) { - rtrmnet_ctl_create_vnd(profile->usbnet_adapter, profile->qmapnet_adapter, - profile->muxid, profile->qmap_version, 11, 4096); - } - } -#endif - return 0; -} diff --git a/quectel_cm_5G/src/qrtr.c b/quectel_cm_5G/src/qrtr.c deleted file mode 100644 index 2dc1853..0000000 --- a/quectel_cm_5G/src/qrtr.c +++ /dev/null @@ -1,657 +0,0 @@ -//https://github.com/andersson/qrtr -/****************************************************************************** - @file QrtrCM.c - @brief GobiNet driver. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include "QMIThread.h" - -typedef struct { - uint32_t service; - uint32_t version; - uint32_t instance; - uint32_t node; - uint32_t port; -} QrtrService; - -#define QRTR_MAX (QMUX_TYPE_WDS_ADMIN + 1) -static QrtrService service_list[QRTR_MAX]; -static int qmiclientId[QRTR_MAX]; -static int get_client(UCHAR QMIType); -static uint32_t node_modem = 3; //IPQ ~ 3, QCM ~ 0 - -#ifdef USE_LINUX_MSM_IPC -#include - -struct xport_ipc_router_server_addr { - uint32_t service; - uint32_t instance; - uint32_t node_id; - uint32_t port_id; -}; - -union ctl_msg { - uint32_t cmd; - struct { - uint32_t cmd; - uint32_t service; - uint32_t instance; - uint32_t node_id; - uint32_t port_id; - } srv; - struct { - uint32_t cmd; - uint32_t node_id; - uint32_t port_id; - } cli; - }; -#define CTL_CMD_NEW_SERVER 4 -#define CTL_CMD_REMOVE_SERVER 5 - -#define VERSION_MASK 0xff -#define GET_VERSION(x) (x & 0xff) -#define GET_XPORT_SVC_INSTANCE(x) GET_VERSION(x) -#define GET_INSTANCE(x) ((x & 0xff00) >> 8) - -static int msm_ipc_socket(const char *name) -{ - int sock; - int flags; - - sock = socket(AF_MSM_IPC, SOCK_DGRAM, 0); - if (sock < 0) { - dbg_time("%s(%s) errno: %d (%s)\n", __func__, name, errno, strerror(errno)); - return -1; - } - - fcntl(sock, F_SETFD, FD_CLOEXEC); - flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); - - return sock; -} - -static uint32_t xport_lookup -( - int lookup_sock_fd, - uint32_t service_id, - uint32_t version -) -{ - uint32_t num_servers_found = 0; - uint32_t num_entries_to_fill = 4; - struct server_lookup_args *lookup_arg; - int i; - - lookup_arg = (struct server_lookup_args *)malloc(sizeof(*lookup_arg) - + (num_entries_to_fill * sizeof(struct msm_ipc_server_info))); - if (!lookup_arg) - { - dbg_time("%s: Malloc failed\n", __func__); - return 0; - } - - lookup_arg->port_name.service = service_id; - lookup_arg->port_name.instance = GET_XPORT_SVC_INSTANCE(version); - lookup_arg->num_entries_in_array = num_entries_to_fill; - lookup_arg->lookup_mask = VERSION_MASK; - lookup_arg->num_entries_found = 0; - if (ioctl(lookup_sock_fd, IPC_ROUTER_IOCTL_LOOKUP_SERVER, lookup_arg) < 0) - { - dbg_time("%s: Lookup failed for %08x: %08x\n", __func__, service_id, version); - free(lookup_arg); - return 0; - } - - dbg_time("%s: num_entries_found %d for type=%d instance=%d", __func__, - lookup_arg->num_entries_found, service_id, version); - num_servers_found = 0; - for (i = 0; ((i < (int)num_entries_to_fill) && (i < lookup_arg->num_entries_found)); i++) - { - QrtrService service_info[1]; - - if (lookup_arg->srv_info[i].node_id != node_modem) - continue; - num_servers_found++; - - service_info[0].service = lookup_arg->srv_info[i].service; - service_info[0].version = GET_VERSION(lookup_arg->srv_info[i].instance); - service_info[0].instance = GET_INSTANCE(lookup_arg->srv_info[i].instance); - service_info[0].node = lookup_arg->srv_info[i].node_id; - service_info[0].port = lookup_arg->srv_info[i].port_id; - - service_list[service_id] = service_info[0]; - qmiclientId[service_id] = get_client(service_id); - } - - free(lookup_arg); - return num_servers_found; -} - -static int xport_send(int sock, uint32_t node, uint32_t port, const void *data, unsigned int sz) -{ - struct sockaddr_msm_ipc addr = {}; - int rc; - - addr.family = AF_MSM_IPC; - addr.address.addrtype = MSM_IPC_ADDR_ID; - addr.address.addr.port_addr.node_id = node; - addr.address.addr.port_addr.port_id = port; - - rc = sendto(sock, data, sz, MSG_DONTWAIT, (void *)&addr, sizeof(addr)); - if (rc < 0) { - dbg_time("xport_send errno: %d (%s)\n", errno, strerror(errno)); - return -1; - } - - return 0; -} - -static int xport_recv(int sock, void *data, unsigned int sz, uint32_t *node, uint32_t *port) -{ - struct sockaddr_msm_ipc addr = {}; - socklen_t addr_size = sizeof(struct sockaddr_msm_ipc); - int rc; - - rc = recvfrom(sock, data, sz, MSG_DONTWAIT, (void *)&addr, &addr_size); - if (rc < 0) { - dbg_time("xport_recv errno: %d (%s)\n", errno, strerror(errno)); - } - else if (addr.address.addrtype != MSM_IPC_ADDR_ID) { - dbg_time("xport_recv addrtype is NOT MSM_IPC_ADDR_ID\n"); - rc = -1; - } - - *node = addr.address.addr.port_addr.node_id; - *port = addr.address.addr.port_addr.port_id; - return rc; -} -#define qmi_recv xport_recv - -static int xport_ctrl_init(void) -{ - int ctrl_sock; - int rc; - uint32_t instance = 1; //modem - uint32_t version; - - ctrl_sock = msm_ipc_socket("ctrl_port"); - if (ctrl_sock == -1) - return -1; - - rc = ioctl(ctrl_sock, IPC_ROUTER_IOCTL_GET_VERSION, &version); - if (rc < 0) { - dbg_time("%s: failed to get ipc version\n", __func__); - goto init_close_ctrl_fd; - } - dbg_time("%s ipc_version = %d", __func__, version); - - rc = ioctl(ctrl_sock, IPC_ROUTER_IOCTL_BIND_CONTROL_PORT, NULL); - if (rc < 0) { - dbg_time("%s: failed to bind as control port\n", __func__); - goto init_close_ctrl_fd; - } - - //cat /sys/kernel/debug/msm_ipc_router/dump_servers - rc = 0; - rc += xport_lookup(ctrl_sock, QMUX_TYPE_WDS, instance); - if (service_list[QMUX_TYPE_WDS].port) { - qmiclientId[QMUX_TYPE_WDS_IPV6] = get_client(QMUX_TYPE_WDS); - } - rc += xport_lookup(ctrl_sock, QMUX_TYPE_NAS, instance); - rc += xport_lookup(ctrl_sock, QMUX_TYPE_UIM, instance); - rc += xport_lookup(ctrl_sock, QMUX_TYPE_DMS, instance); - rc += xport_lookup(ctrl_sock, QMUX_TYPE_WDS_ADMIN, instance); - - if (rc == 0) { - dbg_time("%s: failed to lookup qmi service\n", __func__); - goto init_close_ctrl_fd; - } - - return ctrl_sock; - -init_close_ctrl_fd: - close(ctrl_sock); - return -1; -} - -static void handle_ctrl_pkt(int sock) { - union ctl_msg pkt; - uint32_t type; - int rc; - - rc = recvfrom(sock, &pkt, sizeof(pkt), 0, NULL, NULL); - if (rc < 0) - return; - - type = le32toh(pkt.cmd); - if (CTL_CMD_NEW_SERVER == type || CTL_CMD_REMOVE_SERVER == type) { - QrtrService s; - - s.service = le32toh(pkt.srv.service); - s.version = le32toh(pkt.srv.instance) & 0xff; - s.instance = le32toh(pkt.srv.instance) >> 8; - s.node = le32toh(pkt.srv.node_id); - s.port = le32toh(pkt.srv.port_id); - - if (debug_qmi) - dbg_time ("[qrtr] %s server on %u:%u -> service %u, version %u, instance %u", - CTL_CMD_NEW_SERVER == type ? "add" : "remove", - s.node, s.port, s.service, s.version, s.instance); - - if (CTL_CMD_NEW_SERVER == type) { - if (s.service < QRTR_MAX) { - service_list[s.service] = s; - } - } - else if (CTL_CMD_REMOVE_SERVER == type) { - if (s.service < QRTR_MAX) { - memset(&service_list[s.service], 0, sizeof(QrtrService)); - } - } - } -} -#else -#include -#include "qrtr.h" -#endif - -static int qrtr_socket(void) -{ - struct sockaddr_qrtr sq; - socklen_t sl = sizeof(sq); - int sock; - int rc; - - sock = socket(AF_QIPCRTR, SOCK_DGRAM, 0); - if (sock < 0) { - dbg_time("qrtr_socket errno: %d (%s)\n", errno, strerror(errno)); - return -1; - } - - rc = getsockname(sock, (void *)&sq, &sl); - if (rc || sq.sq_family != AF_QIPCRTR || sl != sizeof(sq)) { - dbg_time("getsockname: %d (%s)\n", errno, strerror(errno)); - close(sock); - return -1; - } - - return sock; -} - -static int qrtr_send(int sock, uint32_t node, uint32_t port, const void *data, unsigned int sz) -{ - struct sockaddr_qrtr sq = {}; - int rc; - - sq.sq_family = AF_QIPCRTR; - sq.sq_node = node; - sq.sq_port = port; - - rc = sendto(sock, data, sz, MSG_DONTWAIT, (void *)&sq, sizeof(sq)); - if (rc < 0) { - dbg_time("sendto errno: %d (%s)\n", errno, strerror(errno)); - return -1; - } - - return 0; -} - -static int qrtr_recv(int sock, void *data, unsigned int sz, uint32_t *node, uint32_t *port) -{ - struct sockaddr_qrtr sq = {}; - socklen_t sl = sizeof(sq); - int rc; - - rc = recvfrom(sock, data, sz, MSG_DONTWAIT, (void *)&sq, &sl); - if (rc < 0) { - dbg_time("qrtr_recv errno: %d (%s)\n", errno, strerror(errno)); - } - - *node = sq.sq_node; - *port = sq.sq_port; - return rc; - } -#define qmi_recv qrtr_recv - -static int qrtr_ctrl_init(void) { - int sock; - int rc; - struct qrtr_ctrl_pkt pkt; - struct sockaddr_qrtr sq; - socklen_t sl = sizeof(sq); - - sock = qrtr_socket(); - if (sock == -1) - return -1; - - memset(&pkt, 0, sizeof(pkt)); - pkt.cmd = htole32(QRTR_TYPE_NEW_LOOKUP); - - getsockname(sock, (void *)&sq, &sl); - rc = qrtr_send(sock, sq.sq_node, QRTR_PORT_CTRL, &pkt, sizeof(pkt)); - if (rc == -1) { - dbg_time("qrtr_send errno: %d (%s)\n", errno, strerror(errno)); - close(sock); - return -1; - } - - return sock; -} - -static void handle_server_change(uint32_t type, struct qrtr_ctrl_pkt *ppkt) { - struct qrtr_ctrl_pkt pkt = *ppkt; - QrtrService s; - - s.service = le32toh(pkt.server.service); - s.version = le32toh(pkt.server.instance) & 0xff; - s.instance = le32toh(pkt.server.instance) >> 8; - s.node = le32toh(pkt.server.node); - s.port = le32toh(pkt.server.port); - - if (debug_qmi) - dbg_time ("[qrtr] %s server on %u:%u -> service %u, version %u, instance %u", - QRTR_TYPE_NEW_SERVER == type ? "add" : "remove", - s.node, s.port, s.service, s.version, s.instance); - - if (s.node != node_modem) - return; //we only care modem - - if (QRTR_TYPE_NEW_SERVER == type) { - if (s.service < QRTR_MAX) { - service_list[s.service] = s; - } - } - else if (QRTR_TYPE_DEL_SERVER == type) { - if (s.service < QRTR_MAX) { - memset(&service_list[s.service], 0, sizeof(QrtrService)); - } - } - } - -static void handle_ctrl_pkt(int sock) { - struct qrtr_ctrl_pkt pkt; - struct sockaddr_qrtr sq; - socklen_t sl = sizeof(sq); - uint32_t type; - int rc; - - rc = recvfrom(sock, &pkt, sizeof(pkt), 0, (void *)&sq, &sl); - if (rc < 0) - return; - - type = le32toh(pkt.cmd); - if (debug_qmi) - dbg_time("type %u, node %u, sq.port %x, len: %d", type, sq.sq_node, sq.sq_port, rc); - - if (sq.sq_port != QRTR_PORT_CTRL) - return; - - if (QRTR_TYPE_NEW_SERVER == type || QRTR_TYPE_DEL_SERVER == type) { - handle_server_change(type, &pkt); - } -} - -static int get_client(UCHAR QMIType) { - int ClientId; - QrtrService *s = &service_list[QMIType]; - - if (!s ->service) { - dbg_time("%s service: %d for QMIType: %d", __func__, s ->service, QMIType); - return -ENODEV; - } - -#ifdef USE_LINUX_MSM_IPC - ClientId = msm_ipc_socket("xport"); -#else - ClientId = qrtr_socket(); -#endif - if (ClientId == -1) { - return 0; - } - - switch (QMIType) { - case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; - case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; - case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; - case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; - case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; - case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; - case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; - case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); - break; - default: break; - } - - return ClientId; -} - -static void handle_alloc_client(PROFILE_T *profile) { - int srv_list[] = {QMUX_TYPE_WDS, QMUX_TYPE_NAS, QMUX_TYPE_UIM, QMUX_TYPE_DMS, QMUX_TYPE_WDS_ADMIN}; - size_t i = 0, srv_ready = 0; - static int report = -1; - - if (report != -1) - return; - - for(i = 0; i < sizeof(srv_list)/sizeof(srv_list[0]); i++) { - int srv = srv_list[i]; - - if (service_list[srv].service) - srv_ready++; - else - continue; - - if (qmiclientId[srv] == 0) { - qmiclientId[srv] = get_client(srv); - - if (qmiclientId[srv] != 0) { - if (srv == QMUX_TYPE_WDS) { - qmiclientId[QMUX_TYPE_WDS_IPV6] = get_client(QMUX_TYPE_WDS); - } - else if (srv == QMUX_TYPE_WDS_ADMIN) { - profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; - } - } - } - } - - if (srv_ready == sizeof(srv_list)/sizeof(srv_list[0])) { - if (qmiclientId[QMUX_TYPE_WDS]) { - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - } else { - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - } - report = 1; - } -} - -static int qmi_send(PQCQMIMSG pRequest) { - uint8_t QMIType = pRequest->QMIHdr.QMIType; - int sock; - QrtrService *s = &service_list[QMIType == QMUX_TYPE_WDS_IPV6 ? QMUX_TYPE_WDS: QMIType]; - sock = qmiclientId[QMIType]; - - pRequest->QMIHdr.ClientId = 0xaa; - if (!s ->service || !sock) { - dbg_time("%s service: %d, sock: %d for QMIType: %d", __func__, s ->service, sock, QMIType); - return -ENODEV; - } - -#ifdef USE_LINUX_MSM_IPC - return xport_send(sock, s->node, s->port, &pRequest->MUXMsg, - le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR)); -#else - return qrtr_send(sock, s->node, s->port, &pRequest->MUXMsg, - le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR)); -#endif -} - -static int qmi_deinit(void) { - unsigned int i; - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - close(qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static void * qmi_read(void *pData) { - PROFILE_T *profile = (PROFILE_T *)pData; - int ctrl_sock; - int wait_for_request_quit = 0; - -#ifdef USE_LINUX_MSM_IPC - ctrl_sock = xport_ctrl_init(); - if (ctrl_sock != -1) - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); -#else - ctrl_sock = qrtr_ctrl_init(); -#endif - - if (ctrl_sock == -1) - goto _quit; - - while (1) { - struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}, {ctrl_sock, POLLIN, 0}}; - int ne, ret, nevents = 2; - unsigned int i; - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - pollfds[nevents].fd = qmiclientId[i]; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents = 0; - nevents++; - } - } - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (fd == qmidevice_control_fd[1]) { - } else { - } - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto _quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto _quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - else if (fd == ctrl_sock) { - handle_ctrl_pkt(ctrl_sock); - handle_alloc_client(profile); - } - else - { - PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; - int rc; - uint32_t sq_node = 0; - uint32_t sq_port = 0; - - rc = qmi_recv(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR), &sq_node, &sq_port); - if (debug_qmi) - dbg_time("fd %d, node %u, port %x, len: %d", fd, sq_node, sq_port, rc); - - if (rc <= 0) - { - dbg_time("%s read=%d errno: %d (%s)", __func__, rc, errno, strerror(errno)); - break; - } - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] == fd) - { - pResponse->QMIHdr.QMIType = i; - - if (service_list[i].node != sq_node || service_list[i].port != sq_port) { - continue; - } - } - } - - pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pResponse->QMIHdr.Length = cpu_to_le16(rc + sizeof(QCQMI_HDR) - 1); - pResponse->QMIHdr.CtlFlags = 0x00; - pResponse->QMIHdr.ClientId = 0xaa; - - QmiThreadRecvQMI(pResponse); - } - } - } - -_quit: - qmi_deinit(); - close(ctrl_sock); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -const struct qmi_device_ops qrtr_qmidev_ops = { - .deinit = qmi_deinit, - .send = qmi_send, - .read = qmi_read, -}; - diff --git a/quectel_cm_5G/src/qrtr.h b/quectel_cm_5G/src/qrtr.h deleted file mode 100644 index d1727a8..0000000 --- a/quectel_cm_5G/src/qrtr.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _LINUX_QRTR_H -#define _LINUX_QRTR_H - -#include -#include - -#ifndef AF_QIPCRTR -#define AF_QIPCRTR 42 -#endif - -#define QRTR_NODE_BCAST 0xffffffffu -#define QRTR_PORT_CTRL 0xfffffffeu - -struct sockaddr_qrtr { - __kernel_sa_family_t sq_family; - __u32 sq_node; - __u32 sq_port; -}; - -enum qrtr_pkt_type { - QRTR_TYPE_DATA = 1, - QRTR_TYPE_HELLO = 2, - QRTR_TYPE_BYE = 3, - QRTR_TYPE_NEW_SERVER = 4, - QRTR_TYPE_DEL_SERVER = 5, - QRTR_TYPE_DEL_CLIENT = 6, - QRTR_TYPE_RESUME_TX = 7, - QRTR_TYPE_EXIT = 8, - QRTR_TYPE_PING = 9, - QRTR_TYPE_NEW_LOOKUP = 10, - QRTR_TYPE_DEL_LOOKUP = 11, -}; - -#define QRTR_TYPE_DEL_PROC 13 - -struct qrtr_ctrl_pkt { - __le32 cmd; - - union { - struct { - __le32 service; - __le32 instance; - __le32 node; - __le32 port; - } server; - - struct { - __le32 node; - __le32 port; - } client; - - struct { - __le32 rsvd; - __le32 node; - } proc; - - }; -} __attribute__ ((packed)); - -#define QRTR_PROTO_VER_1 1 - -struct qrtr_hdr_v1 { - __le32 version; - __le32 type; - __le32 src_node_id; - __le32 src_port_id; - __le32 confirm_rx; - __le32 size; - __le32 dst_node_id; - __le32 dst_port_id; -} __attribute__ ((packed)); - -#endif /* _LINUX_QRTR_H */ diff --git a/quectel_cm_5G/src/quectel-atc-proxy.c b/quectel_cm_5G/src/quectel-atc-proxy.c deleted file mode 100644 index dc929ad..0000000 --- a/quectel_cm_5G/src/quectel-atc-proxy.c +++ /dev/null @@ -1,506 +0,0 @@ -/****************************************************************************** - @file quectel-atc-proxy.c - @brief atc proxy. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qlist.h" -#include "QMIThread.h" -#include "atchannel.h" -#include "at_tok.h" - -#define dprintf(fmt, args...) do { fprintf(stdout, "%s " fmt, get_time(), ##args); } while(0); -#define SYSCHECK(c) do{if((c)<0) {dprintf("%s %d error: '%s' (code: %d)\n", __func__, __LINE__, strerror(errno), errno); return -1;}}while(0) -#define cfmakenoblock(fd) do{fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);}while(0) - -#define safe_free(__x) do { if (__x) { free((void *)__x); __x = NULL;}} while(0) -#define safe_at_response_free(__x) { if (__x) { at_response_free(__x); __x = NULL;}} - -#define at_response_error(err, p_response) \ - (err \ - || p_response == NULL \ - || p_response->finalResponse == NULL \ - || p_response->success == 0) - -typedef struct { - struct qlistnode qnode; - int ClientFd; - unsigned AccessTime; -} ATC_PROXY_CONNECTION; - -static int atc_proxy_quit = 0; -static pthread_t thread_id = 0; -static int atc_dev_fd = -1; -static int atc_proxy_server_fd = -1; -static struct qlistnode atc_proxy_connection; -static int verbose_debug = 0; -static int modem_reset_flag = 0; -static uint8_t atc_buf[4096]; -static int asr_style_atc = 0; -extern int asprintf(char **s, const char *fmt, ...); -static ATC_PROXY_CONNECTION *current_client_fd = NULL; - -static void dump_atc(uint8_t *pATC, int fd,int size, const char flag) -{ - if (verbose_debug) { - printf("%c %d:\n", flag, fd); - printf("%.*s\n", size, pATC); - } -} - -static int send_atc_to_client(int clientFd, uint8_t *pATC, int size) { - struct pollfd pollfds[]= {{clientFd, POLLOUT, 0}}; - ssize_t ret = 0; - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while (ret == -1 && errno == EINTR && atc_proxy_quit == 0); - - if (pollfds[0].revents & POLLOUT) { - ret = write(clientFd, pATC, size); - } - - return ret; -} - -static void onUnsolicited (const char *s, const char *sms_pdu) -{ - struct qlistnode *con_node; - int ret; - char buf[1024]; - - if(s) { - strcpy(buf, s); - strcat(buf, "\r\n"); - } - if(sms_pdu) { - strcat(buf, sms_pdu); - strcat(buf, "\r\n"); - } - - if(current_client_fd) { - ATC_PROXY_CONNECTION *atc_con = current_client_fd; - ret = send_atc_to_client(atc_con->ClientFd, (uint8_t *)buf, strlen(buf)); - if(ret < 0) { - close(atc_con->ClientFd); - qlist_remove(&atc_con->qnode); - free(atc_con); - } - return; - } - - qlist_for_each(con_node, &atc_proxy_connection) { - ATC_PROXY_CONNECTION *atc_con = qnode_to_item(con_node, ATC_PROXY_CONNECTION, qnode); - if(atc_con && atc_con->ClientFd > 0) { - ret = send_atc_to_client(atc_con->ClientFd, (uint8_t *)buf, strlen(buf)); - if(ret < 0) { - close(atc_con->ClientFd); - con_node = con_node->prev; - qlist_remove(&atc_con->qnode); - free(atc_con); - continue; - } - } - } -} - -static void onTimeout(void) { - dprintf("%s", __func__); - //TODO -} - -static void onClose(void) { - dprintf("%s", __func__); -} - -static int create_local_server(const char *name) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - SYSCHECK(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)); - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name) ); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - SYSCHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr))); - if(bind(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno)); - return -1; - } - - dprintf("local server: %s sockfd = %d\n", name, sockfd); - cfmakenoblock(sockfd); - listen(sockfd, 1); - - return sockfd; -} - -static void accept_atc_connection(int serverfd) { - int clientfd = -1; - unsigned char addr[128]; - socklen_t alen = sizeof(addr); - ATC_PROXY_CONNECTION *atc_con; - - clientfd = accept(serverfd, (struct sockaddr *)addr, &alen); - - atc_con = (ATC_PROXY_CONNECTION *)malloc(sizeof(ATC_PROXY_CONNECTION)); - if (atc_con) { - qlist_init(&atc_con->qnode); - atc_con->ClientFd= clientfd; - atc_con->AccessTime = 0; - dprintf("+++ ClientFd=%d\n", atc_con->ClientFd); - qlist_add_tail(&atc_proxy_connection, &atc_con->qnode); - } - - cfmakenoblock(clientfd); -} - -static void cleanup_atc_connection(int clientfd) { - struct qlistnode *con_node; - - qlist_for_each(con_node, &atc_proxy_connection) { - ATC_PROXY_CONNECTION *atc_con = qnode_to_item(con_node, ATC_PROXY_CONNECTION, qnode); - if (atc_con->ClientFd == clientfd) { - dprintf("--- ClientFd=%d\n", atc_con->ClientFd); - close(atc_con->ClientFd); - qlist_remove(&atc_con->qnode); - free(atc_con); - if (current_client_fd == atc_con) - current_client_fd = NULL; - break; - } - } -} - -static int atc_proxy_init(void) { - int err; - char *cmd; - ATResponse *p_response = NULL; - - err = at_handshake(); - if (err) { - dprintf("handshake fail, TODO ... "); - goto exit; - } - - at_send_command_singleline("AT+QCFG=\"usbnet\"", "+QCFG:", NULL); - at_send_command_multiline("AT+QNETDEVCTL=?", "+QNETDEVCTL:", NULL); - at_send_command("AT+CGREG=2", NULL); //GPRS Network Registration Status - at_send_command("AT+CEREG=2", NULL); //EPS Network Registration Status - at_send_command("AT+C5GREG=2", NULL); //5GS Network Registration Status - - at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); - if (at_response_error(err, p_response)) - asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support - - safe_at_response_free(p_response); - - err = at_send_command_singleline("AT+QCFG=\"NAT\"", "+QCFG:", &p_response); - if (!at_response_error(err, p_response)) { - int old_nat, new_nat = asr_style_atc ? 1 : 0; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s%d", NULL, &old_nat); - if (err == 2 && old_nat != new_nat) { - safe_at_response_free(p_response); - asprintf(&cmd, "AT+QCFG=\"NAT\",%d", new_nat); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (!at_response_error(err, p_response)) { - err = at_send_command("at+cfun=1,1",NULL); - } - safe_at_response_free(p_response); - } - err = 0; - } - safe_at_response_free(p_response); - -exit: - return err; -} - -static void atc_start_server(const char* servername) { - atc_proxy_server_fd = create_local_server(servername); - dprintf("atc_proxy_server_fd = %d\n", atc_proxy_server_fd); - if (atc_proxy_server_fd == -1) { - dprintf("Failed to create %s, errno: %d (%s)\n", servername, errno, strerror(errno)); - } -} - -static void atc_close_server(const char* servername) { - if (atc_proxy_server_fd != -1) { - dprintf("%s %s close server\n", __func__, servername); - close(atc_proxy_server_fd); - atc_proxy_server_fd = -1; - } -} - -static void *atc_proxy_loop(void *param) -{ - uint8_t *pATC = atc_buf; - struct qlistnode *con_node; - ATC_PROXY_CONNECTION *atc_con; - - (void)param; - dprintf("%s enter thread_id %p\n", __func__, (void *)pthread_self()); - - qlist_init(&atc_proxy_connection); - while (atc_dev_fd > 0 && atc_proxy_quit == 0) { - struct pollfd pollfds[2+64]; - int ne, ret, nevents = 0; - ssize_t nreads; - - pollfds[nevents].fd = atc_dev_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (atc_proxy_server_fd > 0) { - pollfds[nevents].fd = atc_proxy_server_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - } - - qlist_for_each(con_node, &atc_proxy_connection) { - atc_con = qnode_to_item(con_node, ATC_PROXY_CONNECTION, qnode); - - pollfds[nevents].fd = atc_con->ClientFd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (nevents == (sizeof(pollfds)/sizeof(pollfds[0]))) - break; - } - - do { - ret = poll(pollfds, nevents, (atc_proxy_server_fd > 0) ? -1 : 200); - } while (ret == -1 && errno == EINTR && atc_proxy_quit == 0); - - if (ret < 0) { - dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); - goto atc_proxy_loop_exit; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dprintf("%s poll fd = %d, revents = %04x\n", __func__, fd, revents); - if (fd == atc_dev_fd) { - goto atc_proxy_loop_exit; - } else if(fd == atc_proxy_server_fd) { - - } else { - cleanup_atc_connection(fd); - } - continue; - } - - if (!(pollfds[ne].revents & POLLIN)) { - continue; - } - - if (fd == atc_proxy_server_fd) { - accept_atc_connection(fd); - } - else if (fd == atc_dev_fd) { - usleep(10*1000); //let atchannel.c read at response. - if (modem_reset_flag) - goto atc_proxy_loop_exit; - } - else { - memset(atc_buf, 0x0, sizeof(atc_buf)); - nreads = read(fd, pATC, sizeof(atc_buf)); - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - cleanup_atc_connection(fd); - break; - } - - dump_atc(pATC, fd, nreads, 'r'); - qlist_for_each(con_node, &atc_proxy_connection) { - atc_con = qnode_to_item(con_node, ATC_PROXY_CONNECTION, qnode); - if (atc_con->ClientFd == pollfds[nevents].fd) { - current_client_fd = atc_con; - break; - } - } - at_send_command ((const char *)pATC, NULL); - current_client_fd = NULL; - } - } - } - -atc_proxy_loop_exit: - at_close(); - while (!qlist_empty(&atc_proxy_connection)) { - ATC_PROXY_CONNECTION *atc_con = qnode_to_item(qlist_head(&atc_proxy_connection), ATC_PROXY_CONNECTION, qnode); - cleanup_atc_connection(atc_con->ClientFd); - } - dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self()); - - return NULL; -} - -static void usage(void) { - dprintf(" -d A valid atc device\n" - " default /dev/ttyUSB2, but /dev/ttyUSB2 may be invalid\n" - " -i netcard name\n" - " -v Will show all details\n"); -} - -static void sig_action(int sig) { - if (atc_proxy_quit == 0) { - atc_proxy_quit = 1; - if (thread_id) - pthread_kill(thread_id, sig); - } -} - -int main(int argc, char *argv[]) { - int opt; - char atc_dev[32+1] = "/dev/ttyUSB2"; - int retry_times = 0; - char servername[64] = {0}; - - optind = 1; - signal(SIGINT, sig_action); - - while ( -1 != (opt = getopt(argc, argv, "d:i:vh"))) { - switch (opt) { - case 'd': - strcpy(atc_dev, optarg); - break; - case 'v': - verbose_debug = 1; - break; - default: - usage(); - return 0; - } - } - - if (access(atc_dev, R_OK | W_OK)) { - dprintf("Fail to access %s, errno: %d (%s). break\n", atc_dev, errno, strerror(errno)); - return -1; - } - - sprintf(servername, "quectel-atc-proxy%c", atc_dev[strlen(atc_dev) - 1]); - dprintf("Will use atc-dev='%s', proxy='%s'\n", atc_dev, servername); - - while (atc_proxy_quit == 0) { - if (access(atc_dev, R_OK | W_OK)) { - dprintf("Fail to access %s, errno: %d (%s). continue\n", atc_dev, errno, strerror(errno)); - // wait device - sleep(3); - continue; - } - - atc_dev_fd = open(atc_dev, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (atc_dev_fd == -1) { - dprintf("Failed to open %s, errno: %d (%s). break\n", atc_dev, errno, strerror(errno)); - return -1; - } - cfmakenoblock(atc_dev_fd); - if (at_open(atc_dev_fd, onUnsolicited, 1)) { - close(atc_dev_fd); - atc_dev_fd = -1; - } - at_set_on_timeout(onTimeout); - at_set_on_reader_closed(onClose); - - /* no atc_proxy_loop lives, create one */ - pthread_create(&thread_id, NULL, atc_proxy_loop, NULL); - /* try to redo init if failed, init function must be successfully */ - while (atc_proxy_init() != 0) { - if (retry_times < 5) { - dprintf("fail to init proxy, try again in 2 seconds.\n"); - sleep(2); - retry_times++; - } else { - dprintf("has failed too much times, restart the modem and have a try...\n"); - break; - } - /* break loop if modem is detached */ - if (access(atc_dev, F_OK|R_OK|W_OK)) - break; - } - retry_times = 0; - atc_start_server(servername); - if (atc_proxy_server_fd == -1) - pthread_cancel(thread_id); - pthread_join(thread_id, NULL); - - /* close local server at last */ - atc_close_server(servername); - close(atc_dev_fd); - /* DO RESTART IN 20s IF MODEM RESET ITSELF */ - if (modem_reset_flag) { - unsigned int time_to_wait = 20; - while (time_to_wait) { - time_to_wait = sleep(time_to_wait); - } - modem_reset_flag = 0; - } - } - - return 0; -} \ No newline at end of file diff --git a/quectel_cm_5G/src/quectel-mbim-proxy.c b/quectel_cm_5G/src/quectel-mbim-proxy.c deleted file mode 100644 index 5cf6f41..0000000 --- a/quectel_cm_5G/src/quectel-mbim-proxy.c +++ /dev/null @@ -1,453 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qendian.h" - -#define QUECTEL_MBIM_PROXY "quectel-mbim-proxy" -#define safe_close(_fd) do { if (_fd > 0) { close(_fd); _fd = -1; } } while(0) - -#define CM_MAX_CLIENT 32 -#define TID_MASK (0xFFFFFF) -#define TID_SHIFT (24) - -typedef enum { - MBIM_OPEN_MSG = 1, - MBIM_CLOSE_MSG = 2, - MBIM_OPEN_DONE = 0x80000001, - MBIM_CLOSE_DONE = 0x80000002, -} MBIM_MSG; - -typedef struct { - unsigned int MessageType; - unsigned int MessageLength; - unsigned int TransactionId; -} MBIM_MESSAGE_HEADER; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - unsigned int MaxControlTransfer; -} MBIM_OPEN_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - unsigned int Status; -} MBIM_OPEN_DONE_T; - -typedef struct { - int client_fd; - int client_idx; -} CM_CLIENT_T; - -static unsigned char cm_recv_buffer[4096]; -static CM_CLIENT_T cm_clients[CM_MAX_CLIENT]; -static int verbose = 0; - -const char * get_time(void) { - static char time_buf[128]; - struct timeval tv; - time_t time; - suseconds_t millitm; - struct tm *ti; - - gettimeofday (&tv, NULL); - - time= tv.tv_sec; - millitm = (tv.tv_usec + 500) / 1000; - - if (millitm == 1000) { - ++time; - millitm = 0; - } - - ti = localtime(&time); - sprintf(time_buf, "[%02d-%02d_%02d:%02d:%02d:%03d]", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); - return time_buf; -} - -#define mbim_debug(fmt, args...) do { fprintf(stdout, "%s " fmt, get_time(), ##args); } while(0); - -static int non_block_write(int fd, void *data, int len) -{ - int ret; - struct pollfd pollfd = {fd, POLLOUT, 0}; - ret = poll(&pollfd, 1, 3000); - - if (ret <= 0) { - mbim_debug("%s poll ret=%d, errno: %d(%s)\n", __func__, ret, errno, strerror(errno)); - } - - ret = write (fd, data, len); - if (ret != len) - mbim_debug("%s write ret=%d, errno: %d(%s)\n", __func__, ret, errno, strerror(errno)); - - return len; -} - -static int mbim_send_open_msg(int mbim_dev_fd, uint32_t MaxControlTransfer) { - MBIM_OPEN_MSG_T open_msg; - MBIM_OPEN_MSG_T *pRequest = &open_msg; - - pRequest->MessageHeader.MessageType = htole32(MBIM_OPEN_MSG); - pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_OPEN_MSG_T)); - pRequest->MessageHeader.TransactionId = htole32(1); - pRequest->MaxControlTransfer = htole32(MaxControlTransfer); - - mbim_debug("%s()\n", __func__); - return non_block_write(mbim_dev_fd, pRequest, sizeof(MBIM_OPEN_MSG_T)); -} - -/* - * parameter: proxy name - * return: local proxy server fd or -1 -*/ -static int proxy_make_server(const char *proxy_name) -{ - int len, flag; - struct sockaddr_un sockaddr; - int mbim_server_fd; - - mbim_server_fd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (mbim_server_fd < 0) { - mbim_debug("socket failed: %s\n", strerror(errno)); - return -1; - } - if (fcntl(mbim_server_fd, F_SETFL, fcntl(mbim_server_fd, F_GETFL) | O_NONBLOCK) < 0) - mbim_debug("fcntl set server(%d) NONBLOCK attribute failed: %s\n", mbim_server_fd, strerror(errno)); - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - snprintf(sockaddr.sun_path, UNIX_PATH_MAX, "0%s", proxy_name); - sockaddr.sun_path[0] = '\0'; // string starts with leading '\0' - flag = 1; - if (setsockopt(mbim_server_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) < 0) { - safe_close(mbim_server_fd); - mbim_debug("setsockopt failed\n"); - } - - len = strlen(proxy_name) + offsetof(struct sockaddr_un, sun_path) + 1; - if (bind(mbim_server_fd, (struct sockaddr*)&sockaddr, len) < 0) { - safe_close(mbim_server_fd); - mbim_debug("bind failed: %s\n", strerror(errno)); - return -1; - } - - listen(mbim_server_fd, 4); - return mbim_server_fd; -} - -static int handle_client_connect(int server_fd) -{ - int i, client_fd; - struct sockaddr_in cli_addr; - socklen_t len = sizeof(cli_addr); - - client_fd = accept(server_fd, (struct sockaddr *)&cli_addr, &len); - if (client_fd < 0) { - mbim_debug("proxy accept failed: %s\n", strerror(errno)); - return -1; - } - - if (fcntl(client_fd, F_SETFL, fcntl(client_fd, F_GETFL) | O_NONBLOCK) < 0) - mbim_debug("fcntl set client(%d) NONBLOCK attribute failed: %s\n", client_fd, strerror(errno)); - - for (i = 0; i < CM_MAX_CLIENT; i++) { - if (cm_clients[i].client_fd <= 0) { - cm_clients[i].client_fd = client_fd; - cm_clients[i].client_idx= i+1; - mbim_debug("%s client_fd=%d, client_idx=%d\n", __func__, cm_clients[i].client_fd, cm_clients[i].client_idx); - return 0; - } - } - - close(client_fd); - return -1; -} - -static void handle_client_disconnect(int client_fd) -{ - int i; - - for (i = 0; i < CM_MAX_CLIENT; i++) { - if (cm_clients[i].client_fd == client_fd) { - mbim_debug("%s client_fd=%d, client_idx=%d\n", __func__, cm_clients[i].client_fd, cm_clients[i].client_idx); - safe_close(cm_clients[i].client_fd); - return; - } - } -} - -static int handle_client_request(int mbim_dev_fd, int client_fd, void *pdata, int len) -{ - int i; - int client_idx = -1; - int ret; - MBIM_MESSAGE_HEADER *pRequest = (MBIM_MESSAGE_HEADER *)pdata; - unsigned int TransactionId = le32toh(pRequest->TransactionId); - - for (i = 0; i < CM_MAX_CLIENT; i++) { - if (cm_clients[i].client_fd == client_fd) { - client_idx = cm_clients[i].client_idx; - break; - } - } - - if (client_idx == -1) { - goto error; - } - - if (le32toh(pRequest->MessageType) == MBIM_OPEN_MSG - || le32toh(pRequest->MessageType) == MBIM_CLOSE_MSG) { - MBIM_OPEN_DONE_T OpenDone; - OpenDone.MessageHeader.MessageType = htole32(le32toh(pRequest->MessageType) | 0x80000000); - OpenDone.MessageHeader.MessageLength = htole32(sizeof(OpenDone)); - OpenDone.MessageHeader.TransactionId = htole32(TransactionId); - OpenDone.Status = htole32(0); - non_block_write (client_fd, &OpenDone, sizeof(OpenDone)); - return 0; - } - - /* transfer TransicationID to proxy transicationID and record in sender list */ - pRequest->TransactionId = htole32(TransactionId | (client_idx << TID_SHIFT)); - if (verbose) mbim_debug("REQ client_fd=%d, client_idx=%d, tid=%u\n", - cm_clients[client_idx].client_fd, cm_clients[client_idx].client_idx, TransactionId); - ret = non_block_write (mbim_dev_fd, pRequest, len); - if (ret == len) - return 0; - -error: - return -1; -} - -/* - * Will read message from device and transfer it to clients/client - * Notice: - * unsocial message will be send to all clients - */ -static int handle_device_response(void *pdata, int len) -{ - int i; - MBIM_MESSAGE_HEADER *pResponse = (MBIM_MESSAGE_HEADER *)pdata; - unsigned int TransactionId = le32toh(pResponse->TransactionId); - - /* unsocial/function error message */ - if (TransactionId == 0) { - for (i = 0; i < CM_MAX_CLIENT; i++) { - if (cm_clients[i].client_fd > 0) { - non_block_write(cm_clients[i].client_fd, pResponse, len); - } - } - } - else { - /* try to find the sender */ - int client_idx = (TransactionId >> TID_SHIFT); - - for (i = 0; i < CM_MAX_CLIENT; i++) { - if (cm_clients[i].client_idx == client_idx && cm_clients[i].client_fd > 0) { - TransactionId &= TID_MASK; - pResponse->TransactionId = htole32(TransactionId); - if (verbose) mbim_debug("RSP client_fd=%d, client_idx=%d, tid=%u\n", - cm_clients[i].client_fd, cm_clients[i].client_idx, TransactionId); - non_block_write(cm_clients[i].client_fd, pResponse, len); - break; - } - } - - if (i == CM_MAX_CLIENT) { - mbim_debug("%s nobody care tid=%u\n", __func__, TransactionId); - } - } - - return 0; -} - -static int proxy_loop(int mbim_dev_fd) -{ - int i; - int mbim_server_fd = -1; - - while (mbim_dev_fd > 0) { - struct pollfd pollfds[2+CM_MAX_CLIENT]; - int ne, ret, nevents = 0; - - pollfds[nevents].fd = mbim_dev_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (mbim_server_fd > 0) { - pollfds[nevents].fd = mbim_server_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - for (i = 0; i < CM_MAX_CLIENT; i++) { - if (cm_clients[i].client_fd > 0) { - pollfds[nevents].fd = cm_clients[i].client_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - } - } - } - - ret = poll(pollfds, nevents, (mbim_server_fd > 0) ? -1 : (10*1000)); - if (ret <= 0) { - goto error; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - mbim_debug("%s poll fd = %d, revents = %04x\n", __func__, fd, revents); - if (fd == mbim_dev_fd) { - goto error; - } else if(fd == mbim_server_fd) { - - } else { - handle_client_disconnect(fd); - } - continue; - } - - if (!(pollfds[ne].revents & POLLIN)) { - continue; - } - - if (fd == mbim_server_fd) { - handle_client_connect(fd); - } - else { - int len = read(fd, cm_recv_buffer, sizeof(cm_recv_buffer)); - - if (len <= 0) { - mbim_debug("%s read fd=%d, len=%d, errno: %d(%s)\n", __func__, fd, len, errno, strerror(errno)); - if (fd == mbim_dev_fd) - goto error; - else - handle_client_disconnect(fd); - - return len; - } - - if (fd == mbim_dev_fd) { - if (mbim_server_fd == -1) { - MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)cm_recv_buffer; - - if (le32toh(pOpenDone->MessageHeader.MessageType) == MBIM_OPEN_DONE) { - mbim_debug("receive MBIM_OPEN_DONE, status=%d\n", htole32(pOpenDone->Status)); - if (htole32(pOpenDone->Status)) - goto error; - mbim_server_fd = proxy_make_server(QUECTEL_MBIM_PROXY); - mbim_debug("mbim_server_fd=%d\n", mbim_server_fd); - } - } - else { - handle_device_response(cm_recv_buffer, len); - } - } - else { - handle_client_request(mbim_dev_fd, fd, cm_recv_buffer, len); - } - } - } - } - -error: - safe_close(mbim_server_fd); - for (i = 0; i < CM_MAX_CLIENT; i++) { - safe_close(cm_clients[i].client_fd); - } - - mbim_debug("%s exit\n", __func__); - return 0; -} - -/* - * How to use this proxy? - * 1. modprobe -a 8021q - * 2. Create network interface for channels: - * ip link add link wwan0 name wwan0.1 type vlan id 1 - * ip link add link wwan0 name wwan0.2 type vlan id 2 - * 3. Start './mbim-proxy' with -d 'device' - * 4. Start Clients: ./quectel-CM -n id1 - * 5. Start Clients: ./quectel-CM -n id2 - * ... - * Notice: - * mbim-proxy can work in backgroud as a daemon - * '-n' sessionID - * The modem may not support multi-PDN mode or how many PDN it supports is undefined. It depends!!! - * Besides, some modem also may not support some sessionID. For instance EC20 doesn't support SessionId 1... - */ -int main(int argc, char **argv) -{ - int optidx = 0; - int opt; - char *optstr = "d:vh"; - const char *device = "/dev/cdc-wdm0"; - - struct option options[] = { - {"verbose", no_argument, NULL, 'v'}, - {"device", required_argument, NULL, 'd'}, - {0, 0, 0, 0}, - }; - while ((opt = getopt_long(argc, argv, optstr, options, &optidx)) != -1) { - switch (opt) { - case 'v': - verbose = 1; - break; - case 'd': - device = optarg; - break; - case 'h': - mbim_debug("-h Show this message\n"); - mbim_debug("-v Verbose\n"); - mbim_debug("-d [device] MBIM device\n"); - return 0; - default: - mbim_debug("illegal argument\n"); - return -1; - } - } - - if (!device) { - mbim_debug("Missing parameter: device\n"); - return -1; - } - - while (1) { - int mbim_dev_fd = open(device, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (mbim_dev_fd < 0) { - mbim_debug("cannot open mbim_device %s: %s\n", device, strerror(errno)); - sleep(2); - continue; - } - mbim_debug ("mbim_dev_fd=%d\n", mbim_dev_fd); - - memset(cm_clients, 0, sizeof(cm_clients)); - mbim_send_open_msg(mbim_dev_fd, sizeof(cm_recv_buffer)); - proxy_loop(mbim_dev_fd); - safe_close(mbim_dev_fd); - } - - return -1; -} diff --git a/quectel_cm_5G/src/quectel-qmi-proxy.c b/quectel_cm_5G/src/quectel-qmi-proxy.c deleted file mode 100644 index e1d28bc..0000000 --- a/quectel_cm_5G/src/quectel-qmi-proxy.c +++ /dev/null @@ -1,694 +0,0 @@ -/****************************************************************************** - @file quectel-qmi-proxy.c - @brief The qmi proxy. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qendian.h" -#include "qlist.h" -#include "MPQMI.h" -#include "MPQCTL.h" -#include "MPQMUX.h" - -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a): (b)) -#endif - -const char * get_time(void) { - static char time_buf[128]; - struct timeval tv; - time_t time; - suseconds_t millitm; - struct tm *ti; - - gettimeofday (&tv, NULL); - - time= tv.tv_sec; - millitm = (tv.tv_usec + 500) / 1000; - - if (millitm == 1000) { - ++time; - millitm = 0; - } - - ti = localtime(&time); - sprintf(time_buf, "[%02d-%02d_%02d:%02d:%02d:%03d]", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); - return time_buf; -} - -#define dprintf(fmt, args...) do { fprintf(stdout, "%s " fmt, get_time(), ##args); } while(0); -#define SYSCHECK(c) do{if((c)<0) {dprintf("%s %d error: '%s' (code: %d)\n", __func__, __LINE__, strerror(errno), errno); return -1;}}while(0) -#define cfmakenoblock(fd) do{fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);}while(0) - -typedef struct { - struct qlistnode qnode; - int ClientFd; - QCQMIMSG qmi[0]; -} QMI_PROXY_MSG; - -typedef struct { - struct qlistnode qnode; - uint8_t QMIType; - uint8_t ClientId; - unsigned AccessTime; -} QMI_PROXY_CLINET; - -typedef struct { - struct qlistnode qnode; - struct qlistnode client_qnode; - int ClientFd; - unsigned AccessTime; -} QMI_PROXY_CONNECTION; - -#ifdef QUECTEL_QMI_MERGE -#define MERGE_PACKET_IDENTITY 0x2c7c -#define MERGE_PACKET_VERSION 0x0001 -#define MERGE_PACKET_MAX_PAYLOAD_SIZE 56 -typedef struct __QMI_MSG_HEADER { - uint16_t idenity; - uint16_t version; - uint16_t cur_len; - uint16_t total_len; -} QMI_MSG_HEADER; - -typedef struct __QMI_MSG_PACKET { - QMI_MSG_HEADER header; - uint16_t len; - char buf[4096]; -} QMI_MSG_PACKET; -#endif - -static int qmi_proxy_quit = 0; -static pthread_t thread_id = 0; -static int cdc_wdm_fd = -1; -static int qmi_proxy_server_fd = -1; -static struct qlistnode qmi_proxy_connection; -static struct qlistnode qmi_proxy_ctl_msg; -static int verbose_debug = 0; -static int modem_reset_flag = 0; -static int qmi_sync_done = 0; -static uint8_t qmi_buf[4096]; - -#ifdef QUECTEL_QMI_MERGE -static int merge_qmi_rsp_packet(void *buf, ssize_t *src_size) { - static QMI_MSG_PACKET s_QMIPacket; - QMI_MSG_HEADER *header = NULL; - ssize_t size = *src_size; - - if((uint16_t)size < sizeof(QMI_MSG_HEADER)) - return -1; - - header = (QMI_MSG_HEADER *)buf; - if(le16toh(header->idenity) != MERGE_PACKET_IDENTITY || le16toh(header->version) != MERGE_PACKET_VERSION || le16toh(header->cur_len) > le16toh(header->total_len)) - return -1; - - if(le16toh(header->cur_len) == le16toh(header->total_len)) { - *src_size = le16toh(header->total_len); - memcpy(buf, buf + sizeof(QMI_MSG_HEADER), *src_size); - s_QMIPacket.len = 0; - return 0; - } - - memcpy(s_QMIPacket.buf + s_QMIPacket.len, buf + sizeof(QMI_MSG_HEADER), le16toh(header->cur_len)); - s_QMIPacket.len += le16toh(header->cur_len); - - if (le16toh(header->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || s_QMIPacket.len >= le16toh(header->total_len)) { - memcpy(buf, s_QMIPacket.buf, s_QMIPacket.len); - *src_size = s_QMIPacket.len; - s_QMIPacket.len = 0; - return 0; - } - - return -1; -} -#endif - -static int create_local_server(const char *name) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - SYSCHECK(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)); - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name) ); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - SYSCHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr))); - if(bind(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno)); - return -1; - } - - dprintf("local server: %s sockfd = %d\n", name, sockfd); - cfmakenoblock(sockfd); - listen(sockfd, 1); - - return sockfd; -} - -static void accept_qmi_connection(int serverfd) { - int clientfd = -1; - unsigned char addr[128]; - socklen_t alen = sizeof(addr); - QMI_PROXY_CONNECTION *qmi_con; - - clientfd = accept(serverfd, (struct sockaddr *)addr, &alen); - - qmi_con = (QMI_PROXY_CONNECTION *)malloc(sizeof(QMI_PROXY_CONNECTION)); - if (qmi_con) { - qlist_init(&qmi_con->qnode); - qlist_init(&qmi_con->client_qnode); - qmi_con->ClientFd= clientfd; - qmi_con->AccessTime = 0; - dprintf("+++ ClientFd=%d\n", qmi_con->ClientFd); - qlist_add_tail(&qmi_proxy_connection, &qmi_con->qnode); - } - - cfmakenoblock(clientfd); -} - -static void cleanup_qmi_connection(int clientfd) { - struct qlistnode *con_node, *qmi_node; - - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - if (qmi_con->ClientFd == clientfd) { - while (!qlist_empty(&qmi_con->client_qnode)) { - QMI_PROXY_CLINET *qmi_client = qnode_to_item(qlist_head(&qmi_con->client_qnode), QMI_PROXY_CLINET, qnode); - - dprintf("xxx ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); - - qlist_remove(&qmi_client->qnode); - free(qmi_client); - } - - qlist_for_each(qmi_node, &qmi_proxy_ctl_msg) { - QMI_PROXY_MSG *qmi_msg = qnode_to_item(qmi_node, QMI_PROXY_MSG, qnode); - - if (qmi_msg->ClientFd == qmi_con->ClientFd) { - qlist_remove(&qmi_msg->qnode); - free(qmi_msg); - break; - } - } - - dprintf("--- ClientFd=%d\n", qmi_con->ClientFd); - close(qmi_con->ClientFd); - qlist_remove(&qmi_con->qnode); - free(qmi_con); - break; - } - } -} - -static void get_client_id(QMI_PROXY_CONNECTION *qmi_con, PQMICTL_GET_CLIENT_ID_RESP_MSG pClient) { - if (pClient->QMIResult == 0 && pClient->QMIError == 0) { - QMI_PROXY_CLINET *qmi_client = (QMI_PROXY_CLINET *)malloc(sizeof(QMI_PROXY_CLINET)); - - qlist_init(&qmi_client->qnode); - qmi_client->QMIType = pClient->QMIType; - qmi_client->ClientId = pClient->ClientId; - qmi_client->AccessTime = 0; - - dprintf("+++ ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); - qlist_add_tail(&qmi_con->client_qnode, &qmi_client->qnode); - } -} - -static void release_client_id(QMI_PROXY_CONNECTION *qmi_con, PQMICTL_RELEASE_CLIENT_ID_RESP_MSG pClient) { - struct qlistnode *client_node; - - if (pClient->QMIResult == 0 && pClient->QMIError == 0) { - qlist_for_each (client_node, &qmi_con->client_qnode) { - QMI_PROXY_CLINET *qmi_client = qnode_to_item(client_node, QMI_PROXY_CLINET, qnode); - - if (pClient->QMIType == qmi_client->QMIType && pClient->ClientId == qmi_client->ClientId) { - dprintf("--- ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); - qlist_remove(&qmi_client->qnode); - free(qmi_client); - break; - } - } - } -} - -static void dump_qmi(PQCQMIMSG pQMI, int fd, const char flag) -{ - if (verbose_debug) - { - unsigned i; - unsigned size = le16toh(pQMI->QMIHdr.Length) + 1; - printf("%c %d %u: ", flag, fd, size); - if (size > 16) - size = 16; - for (i = 0; i < size; i++) - printf("%02x ", ((uint8_t *)pQMI)[i]); - printf("\n"); - } -} - -static int send_qmi_to_cdc_wdm(PQCQMIMSG pQMI) { - struct pollfd pollfds[]= {{cdc_wdm_fd, POLLOUT, 0}}; - ssize_t ret = 0; - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while (ret == -1 && errno == EINTR && qmi_proxy_quit == 0); - - if (pollfds[0].revents & POLLOUT) { - ssize_t size = le16toh(pQMI->QMIHdr.Length) + 1; - ret = write(cdc_wdm_fd, pQMI, size); - dump_qmi(pQMI, cdc_wdm_fd, 'w'); - } - - return ret; -} - -static int send_qmi_to_client(PQCQMIMSG pQMI, int clientFd) { - struct pollfd pollfds[]= {{clientFd, POLLOUT, 0}}; - ssize_t ret = 0; - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while (ret == -1 && errno == EINTR && qmi_proxy_quit == 0); - - if (pollfds[0].revents & POLLOUT) { - ssize_t size = le16toh(pQMI->QMIHdr.Length) + 1; - ret = write(clientFd, pQMI, size); - dump_qmi(pQMI, clientFd, 'w'); - } - - return ret; -} - -static void recv_qmi_from_dev(PQCQMIMSG pQMI) { - struct qlistnode *con_node, *client_node; - - if (qmi_proxy_server_fd == -1) { - qmi_sync_done = 1; - } - else if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) { - if (pQMI->CTLMsg.QMICTLMsgHdr.CtlFlags == QMICTL_CTL_FLAG_RSP) { - if (!qlist_empty(&qmi_proxy_ctl_msg)) { - QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode); - - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - if (qmi_con->ClientFd == qmi_msg->ClientFd) { - send_qmi_to_client(pQMI, qmi_msg->ClientFd); - - if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_GET_CLIENT_ID_RESP) - get_client_id(qmi_con, &pQMI->CTLMsg.GetClientIdRsp); - else if ((le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_RESP) || - (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_REVOKE_CLIENT_ID_IND)) { - release_client_id(qmi_con, &pQMI->CTLMsg.ReleaseClientIdRsp); - if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_REVOKE_CLIENT_ID_IND) - modem_reset_flag = 1; - } - else { - } - } - } - - qlist_remove(&qmi_msg->qnode); - free(qmi_msg); - } - } - - if (!qlist_empty(&qmi_proxy_ctl_msg)) { - QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode); - - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - if (qmi_con->ClientFd == qmi_msg->ClientFd) { - send_qmi_to_cdc_wdm(qmi_msg->qmi); - } - } - } - } - else { - qlist_for_each(con_node, &qmi_proxy_connection) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - qlist_for_each(client_node, &qmi_con->client_qnode) { - QMI_PROXY_CLINET *qmi_client = qnode_to_item(client_node, QMI_PROXY_CLINET, qnode); - if (pQMI->QMIHdr.QMIType == qmi_client->QMIType) { - if (pQMI->QMIHdr.ClientId == 0 || pQMI->QMIHdr.ClientId == qmi_client->ClientId) { - send_qmi_to_client(pQMI, qmi_con->ClientFd); - } - } - } - } - } -} - -static int recv_qmi_from_client(PQCQMIMSG pQMI, unsigned size, int clientfd) { - if (qmi_proxy_server_fd <= 0) { - send_qmi_to_cdc_wdm(pQMI); - } - else if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) { - QMI_PROXY_MSG *qmi_msg; - - if (pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType == QMICTL_SYNC_REQ) { - dprintf("do not allow client send QMICTL_SYNC_REQ\n"); - return 0; - } - - if (qlist_empty(&qmi_proxy_ctl_msg)) - send_qmi_to_cdc_wdm(pQMI); - - qmi_msg = malloc(sizeof(QMI_PROXY_MSG) + size); - qlist_init(&qmi_msg->qnode); - qmi_msg->ClientFd = clientfd; - memcpy(qmi_msg->qmi, pQMI, size); - qlist_add_tail(&qmi_proxy_ctl_msg, &qmi_msg->qnode); - } - else { - send_qmi_to_cdc_wdm(pQMI); - } - - return 0; -} - -static int qmi_proxy_init(void) { - unsigned i; - QCQMIMSG _QMI; - PQCQMIMSG pQMI = &_QMI; - - dprintf("%s enter\n", __func__); - - pQMI->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pQMI->QMIHdr.CtlFlags = 0x00; - pQMI->QMIHdr.QMIType = QMUX_TYPE_CTL; - pQMI->QMIHdr.ClientId= 0x00; - - pQMI->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; - - qmi_sync_done = 0; - for (i = 0; i < 10; i++) { - pQMI->CTLMsg.SyncReq.TransactionId = i+1; - pQMI->CTLMsg.SyncReq.QMICTLType = QMICTL_SYNC_REQ; - pQMI->CTLMsg.SyncReq.Length = 0; - - pQMI->QMIHdr.Length = - htole16(le16toh(pQMI->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMI_HDR) + sizeof(QCQMICTL_MSG_HDR) - 1); - - if (send_qmi_to_cdc_wdm(pQMI) <= 0) - break; - - sleep(1); - if (qmi_sync_done) - break; - } - - dprintf("%s %s\n", __func__, qmi_sync_done ? "succful" : "fail"); - return qmi_sync_done ? 0 : -1; -} - -static void qmi_start_server(const char* servername) { - qmi_proxy_server_fd = create_local_server(servername); - dprintf("qmi_proxy_server_fd = %d\n", qmi_proxy_server_fd); - if (qmi_proxy_server_fd == -1) { - dprintf("Failed to create %s, errno: %d (%s)\n", servername, errno, strerror(errno)); - } -} - -static void qmi_close_server(const char* servername) { - if (qmi_proxy_server_fd != -1) { - dprintf("%s %s close server\n", __func__, servername); - close(qmi_proxy_server_fd); - qmi_proxy_server_fd = -1; - } -} - -static void *qmi_proxy_loop(void *param) -{ - PQCQMIMSG pQMI = (PQCQMIMSG)qmi_buf; - struct qlistnode *con_node; - QMI_PROXY_CONNECTION *qmi_con; - - (void)param; - dprintf("%s enter thread_id %p\n", __func__, (void *)pthread_self()); - - qlist_init(&qmi_proxy_connection); - qlist_init(&qmi_proxy_ctl_msg); - - while (cdc_wdm_fd > 0 && qmi_proxy_quit == 0) { - struct pollfd pollfds[2+64]; - int ne, ret, nevents = 0; - ssize_t nreads; - - pollfds[nevents].fd = cdc_wdm_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (qmi_proxy_server_fd > 0) { - pollfds[nevents].fd = qmi_proxy_server_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - } - - qlist_for_each(con_node, &qmi_proxy_connection) { - qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); - - pollfds[nevents].fd = qmi_con->ClientFd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (nevents == (sizeof(pollfds)/sizeof(pollfds[0]))) - break; - } - -#if 0 - dprintf("poll "); - for (ne = 0; ne < nevents; ne++) { - dprintf("%d ", pollfds[ne].fd); - } - dprintf("\n"); -#endif - - do { - //ret = poll(pollfds, nevents, -1); - ret = poll(pollfds, nevents, (qmi_proxy_server_fd > 0) ? -1 : 200); - } while (ret == -1 && errno == EINTR && qmi_proxy_quit == 0); - - if (ret < 0) { - dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); - goto qmi_proxy_loop_exit; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dprintf("%s poll fd = %d, revents = %04x\n", __func__, fd, revents); - if (fd == cdc_wdm_fd) { - goto qmi_proxy_loop_exit; - } else if(fd == qmi_proxy_server_fd) { - - } else { - cleanup_qmi_connection(fd); - } - - continue; - } - - if (!(pollfds[ne].revents & POLLIN)) { - continue; - } - - if (fd == qmi_proxy_server_fd) { - accept_qmi_connection(fd); - } - else if (fd == cdc_wdm_fd) { - nreads = read(fd, pQMI, sizeof(qmi_buf)); - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)\n", __func__, (int)nreads, errno, strerror(errno)); - goto qmi_proxy_loop_exit; - } -#ifdef QUECTEL_QMI_MERGE - if(merge_qmi_rsp_packet(pQMI, &nreads)) - continue; -#endif - if (nreads != (le16toh(pQMI->QMIHdr.Length) + 1)) { - dprintf("%s nreads=%d, pQCQMI->QMIHdr.Length = %d\n", __func__, (int)nreads, le16toh(pQMI->QMIHdr.Length)); - continue; - } - - dump_qmi(pQMI, fd, 'r'); - recv_qmi_from_dev(pQMI); - if (modem_reset_flag) - goto qmi_proxy_loop_exit; - } - else { - nreads = read(fd, pQMI, sizeof(qmi_buf)); - - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - cleanup_qmi_connection(fd); - break; - } - - if (nreads != (le16toh(pQMI->QMIHdr.Length) + 1)) { - dprintf("%s nreads=%d, pQCQMI->QMIHdr.Length = %d\n", __func__, (int)nreads, le16toh(pQMI->QMIHdr.Length)); - continue; - } - - dump_qmi(pQMI, fd, 'r'); - recv_qmi_from_client(pQMI, nreads, fd); - } - } - } - -qmi_proxy_loop_exit: - while (!qlist_empty(&qmi_proxy_connection)) { - QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(qlist_head(&qmi_proxy_connection), QMI_PROXY_CONNECTION, qnode); - - cleanup_qmi_connection(qmi_con->ClientFd); - } - - dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self()); - - return NULL; -} - -static void usage(void) { - dprintf(" -d A valid qmi device\n" - " default /dev/cdc-wdm0, but cdc-wdm0 may be invalid\n" - " -i netcard name\n" - " -v Will show all details\n"); -} - -static void sig_action(int sig) { - if (qmi_proxy_quit == 0) { - qmi_proxy_quit = 1; - if (thread_id) - pthread_kill(thread_id, sig); - } -} - -int main(int argc, char *argv[]) { - int opt; - char cdc_wdm[32+1] = "/dev/cdc-wdm0"; - int retry_times = 0; - char servername[64] = {0}; - - optind = 1; - - signal(SIGINT, sig_action); - - while ( -1 != (opt = getopt(argc, argv, "d:i:vh"))) { - switch (opt) { - case 'd': - strcpy(cdc_wdm, optarg); - break; - case 'v': - verbose_debug = 1; - break; - default: - usage(); - return 0; - } - } - - if (access(cdc_wdm, R_OK | W_OK)) { - dprintf("Fail to access %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno)); - return -1; - } - - sprintf(servername, "quectel-qmi-proxy%c", cdc_wdm[strlen(cdc_wdm)-1]); - dprintf("Will use cdc-wdm='%s', proxy='%s'\n", cdc_wdm, servername); - - while (qmi_proxy_quit == 0) { - if (access(cdc_wdm, R_OK | W_OK)) { - dprintf("Fail to access %s, errno: %d (%s). continue\n", cdc_wdm, errno, strerror(errno)); - // wait device - sleep(3); - continue; - } - - cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (cdc_wdm_fd == -1) { - dprintf("Failed to open %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno)); - return -1; - } - cfmakenoblock(cdc_wdm_fd); - - /* no qmi_proxy_loop lives, create one */ - pthread_create(&thread_id, NULL, qmi_proxy_loop, NULL); - /* try to redo init if failed, init function must be successfully */ - while (qmi_proxy_init() != 0) { - if (retry_times < 5) { - dprintf("fail to init proxy, try again in 2 seconds.\n"); - sleep(2); - retry_times++; - } else { - dprintf("has failed too much times, restart the modem and have a try...\n"); - break; - } - /* break loop if modem is detached */ - if (access(cdc_wdm, F_OK|R_OK|W_OK)) - break; - } - retry_times = 0; - qmi_start_server(servername); - if (qmi_proxy_server_fd == -1) - pthread_cancel(thread_id); - pthread_join(thread_id, NULL); - - /* close local server at last */ - qmi_close_server(servername); - close(cdc_wdm_fd); - /* DO RESTART IN 20s IF MODEM RESET ITSELF */ - if (modem_reset_flag) { - unsigned int time_to_wait = 20; - while (time_to_wait) { - time_to_wait = sleep(time_to_wait); - } - modem_reset_flag = 0; - } - } - - return 0; -} diff --git a/quectel_cm_5G/src/quectel-qrtr-proxy.c b/quectel_cm_5G/src/quectel-qrtr-proxy.c deleted file mode 100644 index 9404e96..0000000 --- a/quectel_cm_5G/src/quectel-qrtr-proxy.c +++ /dev/null @@ -1,894 +0,0 @@ -/****************************************************************************** - @file quectel-qrtr-proxy.c - @brief The qrtr proxy. - - DESCRIPTION - Connectivity Management Tool for USB/PCIE network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "qrtr.h" - -#include "qendian.h" -#include "qlist.h" -#include "MPQMI.h" -#include "MPQCTL.h" -#include "MPQMUX.h" - -static const char * get_time(void) { - static char time_buf[128]; - struct timeval tv; - time_t time; - suseconds_t millitm; - struct tm *ti; - - gettimeofday (&tv, NULL); - - time= tv.tv_sec; - millitm = (tv.tv_usec + 500) / 1000; - - if (millitm == 1000) { - ++time; - millitm = 0; - } - - ti = localtime(&time); - sprintf(time_buf, "[%02d-%02d_%02d:%02d:%02d:%03d]", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); - return time_buf; -} - -#define dprintf(fmt, args...) do { fprintf(stdout, "%s " fmt, get_time(), ##args); } while(0); -#define SYSCHECK(c) do{if((c)<0) {dprintf("%s %d error: '%s' (code: %d)\n", __func__, __LINE__, strerror(errno), errno); return -1;}}while(0) -#define cfmakenoblock(fd) do{fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);}while(0) -#define align_4(_len) (((_len) + 3) & ~3) - -typedef struct { - struct qlistnode qnode; - int ClientFd; - QCQMIMSG qrtr[0]; -} QRTR_PROXY_MSG; - -typedef struct { - struct qlistnode qnode; - uint8_t QMIType; - uint8_t ClientId; - uint32_t node_id; - uint32_t port_id; - unsigned AccessTime; -} QRTR_PROXY_CLINET; - -typedef struct { - struct qlistnode qnode; - struct qlistnode client_qnode; - int ClientFd; - unsigned AccessTime; -} QRTR_PROXY_CONNECTION; - -typedef struct { - struct qlistnode qnode; - uint32_t service; - uint32_t version; - uint32_t instance; - uint32_t node; - uint32_t port; - - __le32 src_node_id; - __le32 src_port_id; -} QRTR_SERVICE; - -static int qrtr_proxy_quit = 0; -static pthread_t thread_id = 0; -static int cdc_wdm_fd = -1; -static int qrtr_proxy_server_fd = -1; -static struct qlistnode qrtr_proxy_connection; -static struct qlistnode qrtr_server_list; -static int verbose_debug = 0; -static uint32_t node_modem = 3; //IPQ ~ 3, QCM ~ 0 -static uint32_t node_myself = 1; - -static QRTR_SERVICE *find_qrtr_service(uint8_t QMIType) -{ - struct qlistnode *node; - - qlist_for_each (node, &qrtr_server_list) { - QRTR_SERVICE *srv = qnode_to_item(node, QRTR_SERVICE, qnode); - if (srv->service == QMIType) - return srv; - } - - return NULL; -} - -static uint8_t client_bitmap[0xf0]; -static uint8_t port_bitmap[0xff0]; -static int alloc_client_id(void) { - int id = 1; - - for (id = 1; id < (int)sizeof(client_bitmap); id++) { - if (client_bitmap[id] == 0) { - client_bitmap[id] = id; - return id; - } - } - - dprintf("NOT find %s()\n", __func__); - return 0; -} - -static void free_client_id(int id) { - if (id < (int)sizeof(client_bitmap) && client_bitmap[id] == id) { - client_bitmap[id] = 0; - return; - } - dprintf("NOT find %s(id=%d)\n", __func__, id); -} - -static int alloc_port_id(void) { - int id = 1; - - for (id = 1; id < (int)sizeof(port_bitmap); id++) { - if (port_bitmap[id] == 0) { - port_bitmap[id] = id; - return id; - } - } - - dprintf("NOT find %s()\n", __func__); - return 0; -} - -static void free_port_id(int id) { - if (id < (int)sizeof(port_bitmap) && port_bitmap[id] == id) { - port_bitmap[id] = 0; - return; - } - dprintf("NOT find %s(id=%d)\n", __func__, id); -} - -static void dump_qrtr(void *buf, size_t len, char flag) -{ - size_t i; - static char printf_buf[1024]; - int cnt = 0, limit=1024; - unsigned char *d = (unsigned char *)buf; - struct qrtr_hdr_v1 *hdr = (struct qrtr_hdr_v1 *)buf; - const char *ctrl_pkt_strings[] = { - [QRTR_TYPE_DATA] = "data", - [QRTR_TYPE_HELLO] = "hello", - [QRTR_TYPE_BYE] = "bye", - [QRTR_TYPE_NEW_SERVER] = "new-server", - [QRTR_TYPE_DEL_SERVER] = "del-server", - [QRTR_TYPE_DEL_CLIENT] = "del-client", - [QRTR_TYPE_RESUME_TX] = "resume-tx", - [QRTR_TYPE_EXIT] = "exit", - [QRTR_TYPE_PING] = "ping", - [QRTR_TYPE_NEW_LOOKUP] = "new-lookup", - [QRTR_TYPE_DEL_LOOKUP] = "del-lookup", - }; - - for (i = 0; i < len && i < 64; i++) { - if (i%4 == 0) - cnt += snprintf(printf_buf+cnt, limit-cnt, " "); - cnt += snprintf(printf_buf+cnt, limit-cnt, "%02x", d[i]); - } - dprintf("%s\n", printf_buf); - - dprintf("%c ver=%d, type=%d(%s), %x,%x -> %x,%x, confirm_rx=%d, size=%u\n", - flag, - le32toh(hdr->version), le32toh(hdr->type), ctrl_pkt_strings[le32toh(hdr->type)], - le32toh(hdr->src_node_id), le32toh(hdr->src_port_id), le32toh(hdr->dst_node_id), le32toh(hdr->dst_port_id), - le32toh(hdr->confirm_rx), le32toh(hdr->size)); -} - -static int send_qmi_to_client(PQCQMIMSG pQMI, int fd) { - struct pollfd pollfds[]= {{fd, POLLOUT, 0}}; - ssize_t ret = 0; - ssize_t size = le16toh(pQMI->QMIHdr.Length) + 1; - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while (ret == -1 && errno == EINTR && qrtr_proxy_quit == 0); - - if (pollfds[0].revents & POLLOUT) { - ret = write(fd, pQMI, size); - } - - return ret == size ? 0 : -1; -} - -static int send_qrtr_to_dev(struct qrtr_hdr_v1 *hdr, int fd) { - struct pollfd pollfds[]= {{fd, POLLOUT, 0}}; - ssize_t ret = 0; - ssize_t size = align_4(le32toh(hdr->size) + sizeof(*hdr)); - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while (ret == -1 && errno == EINTR && qrtr_proxy_quit == 0); - - if (pollfds[0].revents & POLLOUT) { - ret = write(fd, hdr, size); - } - - return ret == size ? 0 : -1; -} - -static int qrtr_node_enqueue(const void *data, size_t len, - int type, struct sockaddr_qrtr *from, - struct sockaddr_qrtr *to, unsigned int confirm_rx) -{ - int rc = -1; - size_t size = sizeof(struct qrtr_hdr_v1) + len; - struct qrtr_hdr_v1 *hdr = (struct qrtr_hdr_v1 *)malloc(align_4(size)); - - if (hdr) { - hdr->version = htole32(QRTR_PROTO_VER_1); - hdr->type = htole32(type); - hdr->src_node_id = htole32(from->sq_node); - hdr->src_port_id = htole32(from->sq_port); - hdr->dst_node_id = htole32(to->sq_node); - hdr->dst_port_id = htole32(to->sq_port); - hdr->size = htole32(len); - hdr->confirm_rx = htole32(!!confirm_rx); - - memcpy(hdr + 1, data, len); - dump_qrtr(hdr, size, '>'); - send_qrtr_to_dev(hdr, cdc_wdm_fd); - free(hdr); - } - - return rc; -} - -static int send_ctrl_hello(__u32 sq_node, __u32 sq_port) -{ - struct qrtr_ctrl_pkt pkt; - int rc; - struct sockaddr_qrtr to = {AF_QIPCRTR, sq_node, sq_port}; - struct sockaddr_qrtr from = {AF_QIPCRTR, node_myself, QRTR_PORT_CTRL}; - - memset(&pkt, 0, sizeof(pkt)); - pkt.cmd = htole32(QRTR_TYPE_HELLO); - - rc = qrtr_node_enqueue(&pkt, sizeof(pkt), QRTR_TYPE_HELLO, &from, &to, 0); - if (rc < 0) - return rc; - - return 0; -} - -static int ctrl_cmd_del_client(__u32 sq_node, __u32 sq_port, uint8_t QMIType) -{ - struct qrtr_ctrl_pkt pkt; - int rc; - struct sockaddr_qrtr to = {AF_QIPCRTR, QRTR_NODE_BCAST, QRTR_PORT_CTRL}; - struct sockaddr_qrtr from = {AF_QIPCRTR, sq_node, sq_port}; - QRTR_SERVICE *srv = find_qrtr_service(QMIType); - - if (srv) { - to.sq_node = srv->src_node_id; - } - - memset(&pkt, 0, sizeof(pkt)); - pkt.cmd = htole32(QRTR_TYPE_DEL_CLIENT); - pkt.client.node = htole32(sq_node); - pkt.client.port = htole32(sq_port); - - rc = qrtr_node_enqueue(&pkt, sizeof(pkt), QRTR_TYPE_DATA, &from, &to, 0); - if (rc < 0) - return rc; - - return 0; -} - -static void handle_server_change(struct qrtr_hdr_v1 *hdr) { - struct qrtr_ctrl_pkt *pkt = (struct qrtr_ctrl_pkt *)(hdr + 1); - QRTR_SERVICE *s; - - dprintf ("[qrtr] %s server on %u:%u(%u:%u) -> service %u, instance %x\n", - QRTR_TYPE_NEW_SERVER == hdr->type ? "add" : "remove", - le32toh(pkt->server.node), le32toh(pkt->server.port), - le32toh(hdr->src_node_id), le32toh(hdr->src_port_id), - le32toh(pkt->server.service), le32toh(pkt->server.instance)); - - if (le32toh(pkt->server.node) != node_modem) { - return; //we only care modem - } - - s = (QRTR_SERVICE *)malloc(sizeof(QRTR_SERVICE)); - if (!s) - return; - - qlist_init(&s->qnode); - s->service = le32toh(pkt->server.service); - s->version = le32toh(pkt->server.instance) & 0xff; - s->instance = le32toh(pkt->server.instance) >> 8; - s->node = le32toh(pkt->server.node); - s->port = le32toh(pkt->server.port); - - s->src_node_id = le32toh(hdr->src_node_id); - s->src_port_id = le32toh(hdr->src_port_id); - - if (QRTR_TYPE_NEW_SERVER == hdr->type) { - qlist_add_tail(&qrtr_server_list, &s->qnode); - } - else if (QRTR_TYPE_DEL_SERVER == hdr->type) { - qlist_remove(&s->qnode); - } -} - -static int create_local_server(const char *name) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - SYSCHECK(sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)); - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name) ); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - SYSCHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr))); - if(bind(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno)); - return -1; - } - - dprintf("local server: %s sockfd = %d\n", name, sockfd); - cfmakenoblock(sockfd); - listen(sockfd, 1); - - return sockfd; -} - -static uint8_t alloc_qrtr_client_id(QRTR_PROXY_CONNECTION *qrtr_con, uint8_t QMIType) { - QRTR_PROXY_CLINET *qrtr_client = (QRTR_PROXY_CLINET *)malloc(sizeof(QRTR_PROXY_CLINET)); - - qlist_init(&qrtr_client->qnode); - qrtr_client->QMIType = QMIType; - qrtr_client->ClientId = alloc_client_id(); - qrtr_client->node_id = 1; - qrtr_client->port_id = alloc_port_id(); - qrtr_client->AccessTime = 0; - - dprintf("+++ ClientFd=%d QMIType=%d ClientId=%d, node_id=%d, port_id=%d\n", - qrtr_con->ClientFd, qrtr_client->QMIType, qrtr_client->ClientId, - qrtr_client->node_id, qrtr_client->port_id); - qlist_add_tail(&qrtr_con->client_qnode, &qrtr_client->qnode); - - return qrtr_client->ClientId; -} - -static void release_qrtr_client_id(QRTR_PROXY_CONNECTION *qrtr_con, uint8_t QMIType, uint8_t ClientId) { - struct qlistnode *client_node; - int find = 0; - - qlist_for_each (client_node, &qrtr_con->client_qnode) { - QRTR_PROXY_CLINET *qrtr_client = qnode_to_item(client_node, QRTR_PROXY_CLINET, qnode); - - if (QMIType == qrtr_client->QMIType && ClientId == qrtr_client->ClientId) { - dprintf("--- ClientFd=%d QMIType=%d ClientId=%d, node_id=%d, port_id=%d\n", - qrtr_con->ClientFd, qrtr_client->QMIType, qrtr_client->ClientId, - qrtr_client->node_id, qrtr_client->port_id); - ctrl_cmd_del_client(qrtr_client->node_id, qrtr_client->port_id, qrtr_client->QMIType); - free_client_id(qrtr_client->ClientId); - free_port_id(qrtr_client->port_id); - qlist_remove(&qrtr_client->qnode); - free(qrtr_client); - find++; - break; - } - } - - if (!find) { - dprintf("NOT find on %s(ClientFd=%d, QMIType=%d, ClientId=%d)\n", - __func__, qrtr_con->ClientFd, QMIType, ClientId); - } -} - -static void accept_qrtr_connection(int serverfd) { - int clientfd = -1; - unsigned char addr[128]; - socklen_t alen = sizeof(addr); - QRTR_PROXY_CONNECTION *qrtr_con; - - clientfd = accept(serverfd, (struct sockaddr *)addr, &alen); - - qrtr_con = (QRTR_PROXY_CONNECTION *)malloc(sizeof(QRTR_PROXY_CONNECTION)); - if (qrtr_con) { - qlist_init(&qrtr_con->qnode); - qlist_init(&qrtr_con->client_qnode); - qrtr_con->ClientFd= clientfd; - qrtr_con->AccessTime = 0; - dprintf("+++ ClientFd=%d\n", qrtr_con->ClientFd); - qlist_add_tail(&qrtr_proxy_connection, &qrtr_con->qnode); - } - - cfmakenoblock(clientfd); -} - -static void cleanup_qrtr_connection(int clientfd) { - struct qlistnode *con_node; - int find = 0; - - qlist_for_each(con_node, &qrtr_proxy_connection) { - QRTR_PROXY_CONNECTION *qrtr_con = qnode_to_item(con_node, QRTR_PROXY_CONNECTION, qnode); - - if (qrtr_con->ClientFd == clientfd) { - while (!qlist_empty(&qrtr_con->client_qnode)) { - QRTR_PROXY_CLINET *qrtr_client = qnode_to_item(qlist_head(&qrtr_con->client_qnode), QRTR_PROXY_CLINET, qnode); - - release_qrtr_client_id(qrtr_con, qrtr_client->QMIType, qrtr_client->ClientId); - } - - dprintf("--- ClientFd=%d\n", qrtr_con->ClientFd); - close(qrtr_con->ClientFd); - qlist_remove(&qrtr_con->qnode); - free(qrtr_con); - find = 1; - break; - } - } - - if (!find) { - dprintf("NOT find on %s(ClientFd=%d)\n", __func__, clientfd); - } -} - -static void recv_qrtr_from_dev(struct qrtr_hdr_v1 *hdr) { - int find = 0; - uint32_t type = le32toh(hdr->type); - - if (type == QRTR_TYPE_HELLO) { - send_ctrl_hello(le32toh(hdr->src_node_id), le32toh(hdr->src_port_id)); - find++; - } - else if (type == QRTR_TYPE_NEW_SERVER || type == QRTR_TYPE_DEL_SERVER) { - handle_server_change(hdr); - find++; - } - else if (type == QRTR_TYPE_DATA) { - struct qlistnode *con_node, *client_node; - - qlist_for_each(con_node, &qrtr_proxy_connection) { - QRTR_PROXY_CONNECTION *qrtr_con = qnode_to_item(con_node, QRTR_PROXY_CONNECTION, qnode); - - qlist_for_each(client_node, &qrtr_con->client_qnode) { - QRTR_PROXY_CLINET *qrtr_client = qnode_to_item(client_node, QRTR_PROXY_CLINET, qnode); - - if (qrtr_client->node_id == le32toh(hdr->dst_node_id) && qrtr_client->port_id == le32toh(hdr->dst_port_id)) { - PQCQMIMSG pQMI = (PQCQMIMSG)malloc(hdr->size + sizeof(QCQMI_HDR)); - - if (pQMI) { - pQMI->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pQMI->QMIHdr.Length = htole16(hdr->size + sizeof(QCQMI_HDR) - 1); - pQMI->QMIHdr.CtlFlags = 0x00; - pQMI->QMIHdr.QMIType = qrtr_client->QMIType; - pQMI->QMIHdr.ClientId = qrtr_client->ClientId; - memcpy(&pQMI->MUXMsg, hdr + 1, hdr->size); - send_qmi_to_client(pQMI, qrtr_con->ClientFd); - free(pQMI); - find++; - } - } - } - } - - if (hdr->confirm_rx) { - struct qrtr_ctrl_pkt pkt; - struct sockaddr_qrtr from = {AF_QIPCRTR, le32toh(hdr->dst_node_id), le32toh(hdr->dst_port_id)}; - struct sockaddr_qrtr to = {AF_QIPCRTR, le32toh(hdr->src_node_id), le32toh(hdr->src_port_id)}; - - memset(&pkt, 0, sizeof(pkt)); - pkt.cmd = htole32(QRTR_TYPE_RESUME_TX); - pkt.client.node = hdr->dst_node_id; - pkt.client.port = hdr->dst_port_id; - - qrtr_node_enqueue(&pkt, sizeof(pkt), QRTR_TYPE_RESUME_TX, &from, &to, 0); - } - } - else if (type == QRTR_TYPE_RESUME_TX) { - } - - if (!find) { - dprintf("NOT find on %s()\n", __func__); - } -} - -static int recv_qmi_from_client(PQCQMIMSG pQMI, int clientfd) { - QRTR_PROXY_CONNECTION *qrtr_con; - struct qlistnode *con_node, *client_node; - int find = 0; - - qlist_for_each(con_node, &qrtr_proxy_connection) { - qrtr_con = qnode_to_item(con_node, QRTR_PROXY_CONNECTION, qnode); - if (qrtr_con->ClientFd == clientfd) - break; - qrtr_con = NULL; - } - - if (!qrtr_con) { - return -1; - } - - if (le16toh(pQMI->QMIHdr.QMIType) == QMUX_TYPE_CTL) { - if (pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType == QMICTL_SYNC_REQ) { - dprintf("do not allow client send QMICTL_SYNC_REQ\n"); - return 0; - } - else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType) == QMICTL_GET_CLIENT_ID_REQ) { - uint8_t QMIType = pQMI->CTLMsg.GetClientIdReq.QMIType; - PQCQMIMSG pRsp = (PQCQMIMSG)malloc(256); - - if (pRsp) { - uint8_t ClientId = 0; - - if (find_qrtr_service(QMIType)) { - ClientId = alloc_qrtr_client_id(qrtr_con, QMIType); - } - - pRsp->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRsp->QMIHdr.Length = htole16(sizeof(pRsp->CTLMsg.GetClientIdRsp) + sizeof(pRsp->QMIHdr) - 1); - pRsp->QMIHdr.CtlFlags = 0x00; - pRsp->QMIHdr.QMIType = QMUX_TYPE_CTL; - pRsp->QMIHdr.ClientId = 0; - - pRsp->CTLMsg.QMICTLMsgHdrRsp.CtlFlags = QMICTL_FLAG_RESPONSE; - pRsp->CTLMsg.QMICTLMsgHdrRsp.TransactionId = pQMI->CTLMsg.QMICTLMsgHdr.TransactionId; - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMICTLType = pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType; - pRsp->CTLMsg.QMICTLMsgHdrRsp.Length = htole16(sizeof(pRsp->CTLMsg.GetClientIdRsp) - sizeof(pRsp->CTLMsg.QMICTLMsgHdr)); - pRsp->CTLMsg.QMICTLMsgHdrRsp.TLVType = QCTLV_TYPE_RESULT_CODE; - pRsp->CTLMsg.QMICTLMsgHdrRsp.TLVLength = htole16(4); - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult = htole16(ClientId ? 0 : QMI_RESULT_FAILURE); - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError = htole16(ClientId ? 0 : QMI_ERR_INTERNAL); - pRsp->CTLMsg.GetClientIdRsp.TLV2Type = QCTLV_TYPE_REQUIRED_PARAMETER; - pRsp->CTLMsg.GetClientIdRsp.TLV2Length = htole16(2); - pRsp->CTLMsg.GetClientIdRsp.QMIType = QMIType; - pRsp->CTLMsg.GetClientIdRsp.ClientId = ClientId; - - send_qmi_to_client(pRsp, clientfd); - free(pRsp); - find++; - } - } - else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_REQ) { - PQCQMIMSG pRsp = (PQCQMIMSG)malloc(256); - release_qrtr_client_id(qrtr_con, pQMI->CTLMsg.ReleaseClientIdReq.QMIType, pQMI->CTLMsg.ReleaseClientIdReq.ClientId); - - if (pRsp) { - pRsp->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRsp->QMIHdr.Length = htole16(sizeof(pRsp->CTLMsg.ReleaseClientIdRsp) + sizeof(pRsp->QMIHdr) - 1); - pRsp->QMIHdr.CtlFlags = 0x00; - pRsp->QMIHdr.QMIType = QMUX_TYPE_CTL; - pRsp->QMIHdr.ClientId = 0; - - pRsp->CTLMsg.QMICTLMsgHdrRsp.CtlFlags = QMICTL_FLAG_RESPONSE; - pRsp->CTLMsg.QMICTLMsgHdrRsp.TransactionId = pQMI->CTLMsg.QMICTLMsgHdr.TransactionId; - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMICTLType = pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType; - pRsp->CTLMsg.QMICTLMsgHdrRsp.Length = htole16(sizeof(pRsp->CTLMsg.ReleaseClientIdRsp) - sizeof(pRsp->CTLMsg.QMICTLMsgHdr)); - pRsp->CTLMsg.QMICTLMsgHdrRsp.TLVType = QCTLV_TYPE_RESULT_CODE; - pRsp->CTLMsg.QMICTLMsgHdrRsp.TLVLength = htole16(4); - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult = htole16(0); - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError = htole16(0); - pRsp->CTLMsg.ReleaseClientIdRsp.TLV2Type = QCTLV_TYPE_REQUIRED_PARAMETER; - pRsp->CTLMsg.ReleaseClientIdRsp.TLV2Length = htole16(2); - pRsp->CTLMsg.ReleaseClientIdRsp.QMIType = pQMI->CTLMsg.ReleaseClientIdReq.QMIType; - pRsp->CTLMsg.ReleaseClientIdRsp.ClientId = pQMI->CTLMsg.ReleaseClientIdReq.ClientId; - - send_qmi_to_client(pRsp, clientfd); - free(pRsp); - find++; - } - } - else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType) == QMICTL_GET_VERSION_REQ) { - PQCQMIMSG pRsp = (PQCQMIMSG)malloc(256); - - if (pRsp) { - pRsp->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRsp->QMIHdr.Length = htole16(sizeof(pRsp->CTLMsg.GetVersionRsp) + sizeof(pRsp->QMIHdr) - 1); - pRsp->QMIHdr.CtlFlags = 0x00; - pRsp->QMIHdr.QMIType = QMUX_TYPE_CTL; - pRsp->QMIHdr.ClientId = 0; - - pRsp->CTLMsg.QMICTLMsgHdrRsp.CtlFlags = QMICTL_FLAG_RESPONSE; - pRsp->CTLMsg.QMICTLMsgHdrRsp.TransactionId = pQMI->CTLMsg.QMICTLMsgHdr.TransactionId; - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMICTLType = pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType; - pRsp->CTLMsg.QMICTLMsgHdrRsp.Length = htole16(sizeof(pRsp->CTLMsg.GetVersionRsp) - sizeof(pRsp->CTLMsg.QMICTLMsgHdr)); - pRsp->CTLMsg.QMICTLMsgHdrRsp.TLVType = QCTLV_TYPE_RESULT_CODE; - pRsp->CTLMsg.QMICTLMsgHdrRsp.TLVLength = htole16(4); - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXResult = htole16(0); - pRsp->CTLMsg.QMICTLMsgHdrRsp.QMUXError = htole16(0); - pRsp->CTLMsg.GetVersionRsp.TLV2Type = QCTLV_TYPE_REQUIRED_PARAMETER; - pRsp->CTLMsg.GetVersionRsp.TLV2Length = htole16(1); - pRsp->CTLMsg.GetVersionRsp.NumElements = 0; - - send_qmi_to_client(pRsp, clientfd); - free(pRsp); - find++; - } - } - } - else { - qlist_for_each (client_node, &qrtr_con->client_qnode) { - QRTR_PROXY_CLINET *qrtr_client = qnode_to_item(client_node, QRTR_PROXY_CLINET, qnode); - - if (pQMI->QMIHdr.QMIType == qrtr_client->QMIType && pQMI->QMIHdr.ClientId == qrtr_client->ClientId) { - QRTR_SERVICE *srv = find_qrtr_service(pQMI->QMIHdr.QMIType); - - if (srv && srv->service) { - struct sockaddr_qrtr from = {AF_QIPCRTR, qrtr_client->node_id, qrtr_client->port_id}; - struct sockaddr_qrtr to = {AF_QIPCRTR, srv->node, srv->port}; - - qrtr_node_enqueue(&pQMI->MUXMsg, le16toh(pQMI->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR), - QRTR_TYPE_DATA, &from, &to, 0); - find++; - } - break; - } - } - } - - if (!find) { - dprintf("NOT find on %s()\n", __func__); - } - - return 0; -} - -static int qrtr_proxy_init(void) { - unsigned i; - int qrtr_sync_done = 0; - - dprintf("%s enter\n", __func__); - send_ctrl_hello(QRTR_NODE_BCAST, QRTR_PORT_CTRL); - - for (i = 0; i < 10; i++) { - sleep(1); - qrtr_sync_done = !qlist_empty(&qrtr_server_list); - if (qrtr_sync_done) - break; - } - - dprintf("%s %s\n", __func__, qrtr_sync_done ? "succful" : "fail"); - return qrtr_sync_done ? 0 : -1; -} - -static void qrtr_start_server(const char* servername) { - qrtr_proxy_server_fd = create_local_server(servername); - dprintf("qrtr_proxy_server_fd = %d\n", qrtr_proxy_server_fd); - if (qrtr_proxy_server_fd == -1) { - dprintf("Failed to create %s, errno: %d (%s)\n", servername, errno, strerror(errno)); - } -} - -static void qrtr_close_server(const char* servername) { - if (qrtr_proxy_server_fd != -1) { - dprintf("%s %s\n", __func__, servername); - close(qrtr_proxy_server_fd); - qrtr_proxy_server_fd = -1; - } -} - -static void *qrtr_proxy_loop(void *param) -{ - void *rx_buf; - struct qlistnode *con_node; - QRTR_PROXY_CONNECTION *qrtr_con; - - (void)param; - dprintf("%s enter thread_id %p\n", __func__, (void *)pthread_self()); - - rx_buf = malloc(8192); - if (!rx_buf) - return NULL; - - while (cdc_wdm_fd > 0 && qrtr_proxy_quit == 0) { - struct pollfd pollfds[32]; - int ne, ret, nevents = 0; - ssize_t nreads; - - pollfds[nevents].fd = cdc_wdm_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (qrtr_proxy_server_fd > 0) { - pollfds[nevents].fd = qrtr_proxy_server_fd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - } - - qlist_for_each(con_node, &qrtr_proxy_connection) { - qrtr_con = qnode_to_item(con_node, QRTR_PROXY_CONNECTION, qnode); - - pollfds[nevents].fd = qrtr_con->ClientFd; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents= 0; - nevents++; - - if (nevents == (sizeof(pollfds)/sizeof(pollfds[0]))) - break; - } - - do { - //ret = poll(pollfds, nevents, -1); - ret = poll(pollfds, nevents, (qrtr_proxy_server_fd > 0) ? -1 : 200); - } while (ret == -1 && errno == EINTR && qrtr_proxy_quit == 0); - - if (ret < 0) { - dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); - goto qrtr_proxy_loop_exit; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dprintf("%s poll fd = %d, revents = %04x\n", __func__, fd, revents); - if (fd == cdc_wdm_fd) { - goto qrtr_proxy_loop_exit; - } - else if (fd == qrtr_proxy_server_fd) { - - } - else { - cleanup_qrtr_connection(fd); - } - - continue; - } - - if (!(pollfds[ne].revents & POLLIN)) { - continue; - } - - if (fd == qrtr_proxy_server_fd) { - accept_qrtr_connection(fd); - } - else if (fd == cdc_wdm_fd) { - struct qrtr_hdr_v1 *hdr = (struct qrtr_hdr_v1 *)rx_buf; - - nreads = read(fd, rx_buf, 8192); - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)\n", __func__, (int)nreads, errno, strerror(errno)); - goto qrtr_proxy_loop_exit; - } - else if (nreads != (int)align_4(le32toh(hdr->size) + sizeof(*hdr))) { - dprintf("%s nreads=%d, hdr->size = %d\n", __func__, (int)nreads, le32toh(hdr->size)); - continue; - } - - dump_qrtr(hdr, nreads, '<'); - recv_qrtr_from_dev(hdr); - } - else { - PQCQMIMSG pQMI = (PQCQMIMSG)rx_buf; - - nreads = read(fd, rx_buf, 8192); - if (nreads <= 0) { - dprintf("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - cleanup_qrtr_connection(fd); - break; - } - else if (nreads != (le16toh(pQMI->QMIHdr.Length) + 1)) { - dprintf("%s nreads=%d, pQCQMI->QMIHdr.Length = %d\n", __func__, (int)nreads, le16toh(pQMI->QMIHdr.Length)); - continue; - } - - recv_qmi_from_client(pQMI, fd); - } - } - } - -qrtr_proxy_loop_exit: - while (!qlist_empty(&qrtr_proxy_connection)) { - QRTR_PROXY_CONNECTION *qrtr_con = qnode_to_item(qlist_head(&qrtr_proxy_connection), QRTR_PROXY_CONNECTION, qnode); - - cleanup_qrtr_connection(qrtr_con->ClientFd); - } - - dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self()); - free(rx_buf); - - return NULL; -} - -static void usage(void) { - dprintf(" -d A valid qrtr device\n" - " default /dev/mhi_IPCR, but mhi_IPCR may be invalid\n" - " -i netcard name\n" - " -v Will show all details\n"); -} - -static void sig_action(int sig) { - if (qrtr_proxy_quit == 0) { - qrtr_proxy_quit = 1; - if (thread_id) - pthread_kill(thread_id, sig); - } -} - -int main(int argc, char *argv[]) { - int opt; - char cdc_wdm[32+1] = "/dev/mhi_IPCR"; - char servername[64] = {0}; - - signal(SIGINT, sig_action); - signal(SIGTERM, sig_action); - - optind = 1; - while ( -1 != (opt = getopt(argc, argv, "d:i:vh"))) { - switch (opt) { - case 'd': - strcpy(cdc_wdm, optarg); - break; - case 'v': - verbose_debug = 1; - break; - default: - usage(); - return 0; - } - } - - sprintf(servername, "quectel-qrtr-proxy%c", cdc_wdm[strlen(cdc_wdm)-1]); - dprintf("Will use cdc-wdm='%s', proxy='%s'\n", cdc_wdm, servername); - - while (qrtr_proxy_quit == 0) { - cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (cdc_wdm_fd == -1) { - dprintf("Failed to open %s, errno: %d (%s)\n", cdc_wdm, errno, strerror(errno)); - sleep(5); - continue; - } - cfmakenoblock(cdc_wdm_fd); - qlist_init(&qrtr_proxy_connection); - qlist_init(&qrtr_server_list); - pthread_create(&thread_id, NULL, qrtr_proxy_loop, NULL); - - if (qrtr_proxy_init() == 0) { - qrtr_start_server(servername); - pthread_join(thread_id, NULL); - qrtr_close_server(servername); - } - else { - pthread_cancel(thread_id); - pthread_join(thread_id, NULL); - } - - close(cdc_wdm_fd); - } - - return 0; -} diff --git a/quectel_cm_5G/src/rmnetctl.c b/quectel_cm_5G/src/rmnetctl.c deleted file mode 100644 index 5b2fb0f..0000000 --- a/quectel_cm_5G/src/rmnetctl.c +++ /dev/null @@ -1,342 +0,0 @@ -//https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/dataservices/tree/rmnetctl -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RMNETCTL_SUCCESS 0 -#define RMNETCTL_LIB_ERR 1 -#define RMNETCTL_KERNEL_ERR 2 -#define RMNETCTL_INVALID_ARG 3 - -enum rmnetctl_error_codes_e { - RMNETCTL_API_SUCCESS = 0, - - RMNETCTL_API_FIRST_ERR = 1, - RMNETCTL_API_ERR_MESSAGE_SEND = 3, - RMNETCTL_API_ERR_MESSAGE_RECEIVE = 4, - - RMNETCTL_INIT_FIRST_ERR = 5, - RMNETCTL_INIT_ERR_PROCESS_ID = RMNETCTL_INIT_FIRST_ERR, - RMNETCTL_INIT_ERR_NETLINK_FD = 6, - RMNETCTL_INIT_ERR_BIND = 7, - - RMNETCTL_API_SECOND_ERR = 9, - RMNETCTL_API_ERR_HNDL_INVALID = RMNETCTL_API_SECOND_ERR, - RMNETCTL_API_ERR_RETURN_TYPE = 13, -}; - -struct rmnetctl_hndl_s { - uint32_t pid; - uint32_t transaction_id; - int netlink_fd; - struct sockaddr_nl src_addr, dest_addr; -}; -typedef struct rmnetctl_hndl_s rmnetctl_hndl_t; - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -struct nlmsg { - struct nlmsghdr nl_addr; - struct ifinfomsg ifmsg; - char data[500]; -}; - -#define MIN_VALID_PROCESS_ID 0 -#define MIN_VALID_SOCKET_FD 0 -#define KERNEL_PROCESS_ID 0 -#define UNICAST 0 - -enum { - IFLA_RMNET_UL_AGG_PARAMS = __IFLA_RMNET_MAX, - __IFLA_RMNET_EXT_MAX, -}; - -struct rmnet_egress_agg_params { - uint16_t agg_size; - uint16_t agg_count; - uint32_t agg_time; -}; - -static int rmnet_get_ack(rmnetctl_hndl_t *hndl, uint16_t *error_code) -{ - struct nlack { - struct nlmsghdr ackheader; - struct nlmsgerr ackdata; - char data[256]; - - } ack; - int i; - - if (!hndl || !error_code) - return RMNETCTL_INVALID_ARG; - - if ((i = recv(hndl->netlink_fd, &ack, sizeof(ack), 0)) < 0) { - *error_code = errno; - return RMNETCTL_API_ERR_MESSAGE_RECEIVE; - } - - /*Ack should always be NLMSG_ERROR type*/ - if (ack.ackheader.nlmsg_type == NLMSG_ERROR) { - if (ack.ackdata.error == 0) { - *error_code = RMNETCTL_API_SUCCESS; - return RMNETCTL_SUCCESS; - } else { - *error_code = -ack.ackdata.error; - return RMNETCTL_KERNEL_ERR; - } - } - - *error_code = RMNETCTL_API_ERR_RETURN_TYPE; - return RMNETCTL_API_FIRST_ERR; -} - -static int rtrmnet_ctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code) -{ - struct sockaddr_nl __attribute__((__may_alias__)) *saddr_ptr; - int netlink_fd = -1; - pid_t pid = 0; - - if (!hndl || !error_code) - return RMNETCTL_INVALID_ARG; - - *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t)); - if (!*hndl) { - *error_code = RMNETCTL_API_ERR_HNDL_INVALID; - return RMNETCTL_LIB_ERR; - } - - memset(*hndl, 0, sizeof(rmnetctl_hndl_t)); - - pid = getpid(); - if (pid < MIN_VALID_PROCESS_ID) { - free(*hndl); - *error_code = RMNETCTL_INIT_ERR_PROCESS_ID; - return RMNETCTL_LIB_ERR; - } - (*hndl)->pid = KERNEL_PROCESS_ID; - netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (netlink_fd < MIN_VALID_SOCKET_FD) { - free(*hndl); - *error_code = RMNETCTL_INIT_ERR_NETLINK_FD; - return RMNETCTL_LIB_ERR; - } - - (*hndl)->netlink_fd = netlink_fd; - - memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl)); - - (*hndl)->src_addr.nl_family = AF_NETLINK; - (*hndl)->src_addr.nl_pid = (*hndl)->pid; - - saddr_ptr = &(*hndl)->src_addr; - if (bind((*hndl)->netlink_fd, - (struct sockaddr *)saddr_ptr, - sizeof(struct sockaddr_nl)) < 0) { - close((*hndl)->netlink_fd); - free(*hndl); - *error_code = RMNETCTL_INIT_ERR_BIND; - return RMNETCTL_LIB_ERR; - } - - memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl)); - - (*hndl)->dest_addr.nl_family = AF_NETLINK; - (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID; - (*hndl)->dest_addr.nl_groups = UNICAST; - - return RMNETCTL_SUCCESS; -} - -static int rtrmnet_ctl_deinit(rmnetctl_hndl_t *hndl) -{ - if (!hndl) - return RMNETCTL_SUCCESS; - - close(hndl->netlink_fd); - free(hndl); - - return RMNETCTL_SUCCESS; -} - -static int rtrmnet_ctl_newvnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname, - uint16_t *error_code, uint8_t index, - uint32_t flagconfig, uint32_t ul_agg_cnt, uint32_t ul_agg_size) -{ - struct rtattr *attrinfo, *datainfo, *linkinfo; - struct ifla_vlan_flags flags; - int devindex = 0, val = 0; - char *kind = "rmnet"; - struct nlmsg req; - short id; - - if (!hndl || !devname || !vndname || !error_code) - return RMNETCTL_INVALID_ARG; - - memset(&req, 0, sizeof(req)); - req.nl_addr.nlmsg_type = RTM_NEWLINK; - req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | - NLM_F_ACK; - req.nl_addr.nlmsg_seq = hndl->transaction_id; - hndl->transaction_id++; - - /* Get index of devname*/ - devindex = if_nametoindex(devname); - if (devindex < 0) { - *error_code = errno; - return RMNETCTL_KERNEL_ERR; - } - - /* Setup link attr with devindex as data */ - val = devindex; - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_LINK; - attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val))); - memcpy(RTA_DATA(attrinfo), &val, sizeof(val)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(val))); - - /* Set up IFLA info kind RMNET that has linkinfo and type */ - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_IFNAME; - attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1)); - memcpy(RTA_DATA(attrinfo), vndname, strlen(vndname) + 1); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1)); - - linkinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - linkinfo->rta_type = IFLA_LINKINFO; - linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(0)); - - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_INFO_KIND; - attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind))); - memcpy(RTA_DATA(attrinfo), kind, strlen(kind)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(strlen(kind))); - - datainfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - datainfo->rta_type = IFLA_INFO_DATA; - datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(0)); - - id = index; - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_VLAN_ID; - attrinfo->rta_len = RTA_LENGTH(sizeof(id)); - memcpy(RTA_DATA(attrinfo), &id, sizeof(id)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(id))); - - if (flagconfig != 0) { - flags.mask = flagconfig; - flags.flags = flagconfig; - - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_VLAN_FLAGS; - attrinfo->rta_len = RTA_LENGTH(sizeof(flags)); - memcpy(RTA_DATA(attrinfo), &flags, sizeof(flags)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(flags))); - } - - if (ul_agg_cnt > 1) { - struct rmnet_egress_agg_params agg_params; - - agg_params.agg_size = ul_agg_size; - agg_params.agg_count = ul_agg_cnt; - agg_params.agg_time = 3000000; - - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_RMNET_UL_AGG_PARAMS; - attrinfo->rta_len = RTA_LENGTH(sizeof(agg_params)); - memcpy(RTA_DATA(attrinfo), &agg_params, sizeof(agg_params)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(agg_params))); - } - - datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo; - - linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo; - - if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) { - *error_code = RMNETCTL_API_ERR_MESSAGE_SEND; - return RMNETCTL_LIB_ERR; - } - - return rmnet_get_ack(hndl, error_code); -} - -int rtrmnet_ctl_create_vnd(char *devname, char *vndname, uint8_t muxid, - uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size) -{ - struct rmnetctl_hndl_s *handle; - uint16_t error_code; - int return_code; - uint32_t flagconfig = RMNET_FLAGS_INGRESS_DEAGGREGATION; - - printf("%s devname: %s, vndname: %s, muxid: %d, qmap_version: %d\n", - __func__, devname, vndname, muxid, qmap_version); - - ul_agg_cnt = 0; //TODO - - if (ul_agg_cnt > 1) - flagconfig |= RMNET_EGRESS_FORMAT_AGGREGATION; - - if (qmap_version == 9) { //QMAPV5 -#ifdef RMNET_FLAGS_INGRESS_MAP_CKSUMV5 - flagconfig |= RMNET_FLAGS_INGRESS_MAP_CKSUMV5; - flagconfig |= RMNET_FLAGS_EGRESS_MAP_CKSUMV5; -#else - return -1001; -#endif - } - else if (qmap_version == 8) { //QMAPV4 - flagconfig |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4; - flagconfig |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4; - } - else if (qmap_version == 5) { //QMAPV1 - } - else { - flagconfig = 0; - } - - return_code = rtrmnet_ctl_init(&handle, &error_code); - if (return_code) { - printf("rtrmnet_ctl_init error_code: %d, return_code: %d, errno: %d (%s)\n", - error_code, return_code, errno, strerror(errno)); - } - if (return_code == RMNETCTL_SUCCESS) { - return_code = rtrmnet_ctl_newvnd(handle, devname, vndname, &error_code, - muxid, flagconfig, ul_agg_cnt, ul_agg_size); - if (return_code) { - printf("rtrmnet_ctl_newvnd error_code: %d, return_code: %d, errno: %d (%s)\n", - error_code, return_code, errno, strerror(errno)); - } - rtrmnet_ctl_deinit(handle); - } - - return return_code; -} diff --git a/quectel_cm_5G/src/udhcpc.c b/quectel_cm_5G/src/udhcpc.c deleted file mode 100644 index 5601a6e..0000000 --- a/quectel_cm_5G/src/udhcpc.c +++ /dev/null @@ -1,733 +0,0 @@ -/****************************************************************************** - @file udhcpc.c - @brief call DHCP tools to obtain IP address. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "QMIThread.h" -extern int ql_get_netcard_carrier_state(const char *devname); - -static __inline in_addr_t qmi2addr(uint32_t __x) { - return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); -} - -static int ql_system(const char *shell_cmd) { - dbg_time("%s", shell_cmd); - return system(shell_cmd); -} - -static void ifc_init_ifr(const char *name, struct ifreq *ifr) -{ - memset(ifr, 0, sizeof(struct ifreq)); - no_trunc_strncpy(ifr->ifr_name, name, IFNAMSIZ); - ifr->ifr_name[IFNAMSIZ - 1] = 0; -} - -static void ql_set_mtu(const char *ifname, int ifru_mtu) { - int inet_sock; - struct ifreq ifr; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (inet_sock > 0) { - ifc_init_ifr(ifname, &ifr); - - if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) { - if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) { - dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu); - ifr.ifr_ifru.ifru_mtu = ifru_mtu; - ioctl(inet_sock, SIOCSIFMTU, &ifr); - } - } - - close(inet_sock); - } -} - -static int ifc_get_addr(const char *name, in_addr_t *addr) -{ - int inet_sock; - struct ifreq ifr; - int ret = 0; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - ifc_init_ifr(name, &ifr); - if (addr != NULL) { - ret = ioctl(inet_sock, SIOCGIFADDR, &ifr); - if (ret < 0) { - *addr = 0; - } else { - *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; - } - } - close(inet_sock); - return ret; -} - -static short ifc_get_flags(const char *ifname) -{ - int inet_sock; - struct ifreq ifr; - int ret = 0; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (inet_sock > 0) { - ifc_init_ifr(ifname, &ifr); - - if (!ioctl(inet_sock, SIOCGIFFLAGS, &ifr)) { - ret = ifr.ifr_ifru.ifru_flags; - } - - close(inet_sock); - } - - return ret; -} - -static int ql_netcard_ipv4_address_check(const char *ifname, in_addr_t ip) { - in_addr_t addr = 0; - - ifc_get_addr(ifname, &addr); - return addr == ip; -} - -static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) { - int fd; - char raw_ip[128]; - char shell_cmd[128]; - char mode[2] = "X"; - int mode_change = 0; - - if (ql_netcard_ipv4_address_check(ifname, qmi2addr(ip))) - return 0; - - snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); - if (access(raw_ip, F_OK)) - return 0; - - fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd < 0) { - dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); - return 0; - } - - if (read(fd, mode, 2) == -1) {}; - if (mode[0] == '0' || mode[0] == 'N') { - dbg_time("File:%s Line:%d udhcpc fail to get ip address, try next:", __func__, __LINE__); - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname); - ql_system(shell_cmd); - dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); - mode[0] = 'Y'; - if (write(fd, mode, 2) == -1) {}; - mode_change = 1; - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname); - ql_system(shell_cmd); - } - - close(fd); - return mode_change; -} - -static void* udhcpc_thread_function(void* arg) { - FILE * udhcpc_fp; - char *udhcpc_cmd = (char *)arg; - - if (udhcpc_cmd == NULL) - return NULL; - - dbg_time("%s", udhcpc_cmd); - udhcpc_fp = popen(udhcpc_cmd, "r"); - free(udhcpc_cmd); - if (udhcpc_fp) { - char buf[0xff]; - - buf[sizeof(buf)-1] = '\0'; - while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) { - if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n')) - buf[strlen(buf) - 1] = '\0'; - dbg_time("%s", buf); - } - - pclose(udhcpc_fp); - } - - return NULL; -} - -//#define USE_DHCLIENT -#ifdef USE_DHCLIENT -static int dhclient_alive = 0; -#endif -static int dibbler_client_alive = 0; - -void ql_set_driver_link_state(PROFILE_T *profile, int link_state) { - char link_file[128]; - int fd; - int new_state = 0; - - snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); - fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) { - if (errno != ENOENT) - dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); - return; - } - - if (profile->qmap_mode <= 1) - new_state = !!link_state; - else { - //0x80 means link off this pdp - new_state = (link_state ? 0x00 : 0x80) + (profile->muxid & 0x7F); - } - - snprintf(link_file, sizeof(link_file), "%d\n", new_state); - if (write(fd, link_file, sizeof(link_file)) == -1) {}; - - if (link_state == 0 && profile->qmapnet_adapter[0] - && strcmp(profile->qmapnet_adapter, profile->usbnet_adapter)) { - size_t rc; - - lseek(fd, 0, SEEK_SET); - rc = read(fd, link_file, sizeof(link_file)); - if (rc > 1 && (!strncasecmp(link_file, "0\n", 2) || !strncasecmp(link_file, "0x0\n", 4))) { - snprintf(link_file, sizeof(link_file), "ifconfig %s down", profile->usbnet_adapter); - ql_system(link_file); - } - } - - close(fd); -} - -static const char *ipv4Str(const uint32_t Address) { - static char str[] = {"255.225.255.255"}; - uint8_t *ip = (uint8_t *)&Address; - - snprintf(str, sizeof(str), "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]); - return str; -} - -static const char *ipv6Str(const UCHAR Address[16]) { - static char str[64]; - uint16_t ip[8]; - int i; - for (i = 0; i < 8; i++) { - ip[i] = (Address[i*2]<<8) + Address[i*2+1]; - } - - snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x:%x:%x", - ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]); - - return str; -} - -void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) -{ - char shell_cmd[128]; - - if (!ifname) - return; - - if (!access("/sbin/ip", X_OK)) { - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 4, ifname); - ql_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 4, ip, prefix, ifname); - ql_system(shell_cmd); - - //ping6 www.qq.com - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default via %s dev %s", 4, gw, ifname); - ql_system(shell_cmd); - } else { - unsigned n = (0xFFFFFFFF >> (32 - prefix)) << (32 - prefix); - // n = (n>>24) | (n>>8&0xff00) | (n<<8&0xff0000) | (n<<24); - - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s netmask %s", ifname, ip, ipv4Str(n)); - ql_system(shell_cmd); - - //Resetting default routes - snprintf(shell_cmd, sizeof(shell_cmd), "route del default dev %s", ifname); - while(!system(shell_cmd)); - - snprintf(shell_cmd, sizeof(shell_cmd), "route add default gw %s dev %s", gw, ifname); - ql_system(shell_cmd); - } -} - -void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) { - char shell_cmd[128]; - - (void)gw; - if (!access("/sbin/ip", X_OK)) { - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 6, ifname); - ql_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 6, ip, prefix, ifname); - ql_system(shell_cmd); - - //ping6 www.qq.com - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default dev %s", 6, ifname); - ql_system(shell_cmd); - } else { - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s/%d", ifname, ip, prefix); - ql_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default dev %s", ifname); - ql_system(shell_cmd); - } -} - -static void update_ip_address_by_qmi(const char *ifname, const IPV4_T *ipv4, const IPV6_T *ipv6) { - char *d1, *d2; - - if (ipv4 && ipv4->Address) { - d1 = strdup(ipv4Str(ipv4->Address)); - d2 = strdup(ipv4Str(ipv4->Gateway)); - unsigned prefix = 0; - unsigned n = 0; - - for (n = 0; n < 32; n++) { - if (ipv4->SubnetMask&((unsigned)1<DnsPrimary) { - d1 = strdup(ipv4Str(ipv4->DnsPrimary)); - d2 = strdup(ipv4Str(ipv4->DnsSecondary ? ipv4->DnsSecondary : ipv4->DnsPrimary)); - update_resolv_conf(4, ifname, d1, d2); - free(d1); free(d2); - } - } - - if (ipv6 && ipv6->Address[0] && ipv6->PrefixLengthIPAddr) { - d1 = strdup(ipv6Str(ipv6->Address)); - d2 = strdup(ipv6Str(ipv6->Gateway)); - - update_ipv6_address(ifname, d1, d2, ipv6->PrefixLengthIPAddr); - free(d1); free(d2); - - //Adding DNS - if (ipv6->DnsPrimary[0]) { - d1 = strdup(ipv6Str(ipv6->DnsPrimary)); - d2 = strdup(ipv6Str(ipv6->DnsSecondary[0] ? ipv6->DnsSecondary : ipv6->DnsPrimary)); - update_resolv_conf(6, ifname, d1, d2); - free(d1); free(d2); - } - } -} - -//#define QL_OPENWER_NETWORK_SETUP -#ifdef QL_OPENWER_NETWORK_SETUP -static const char *openwrt_lan = "br-lan"; -static const char *openwrt_wan = "wwan0"; - -static int ql_openwrt_system(const char *cmd) { - int i; - int ret = 1; - char shell_cmd[128]; - - snprintf(shell_cmd, sizeof(shell_cmd), "%s 2>1 > /dev/null", cmd); - - for (i = 0; i < 15; i++) { - dbg_time("%s", cmd); - ret = system(shell_cmd); - if (!ret) - break; - sleep(1); - } - - return ret; -} - -static int ql_openwrt_is_wan(const char *ifname) { - if (openwrt_lan == NULL) { - system("uci show network.wan.ifname"); - } - - if (strcmp(ifname, openwrt_wan)) - return 0; - - return 1; -} - -static void ql_openwrt_setup_wan(const char *ifname, const IPV4_T *ipv4) { - FILE *fp = NULL; - char config[64]; - - snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv4config", ifname); - - if (ipv4 == NULL) { - if (ql_openwrt_is_wan(ifname)) - ql_openwrt_system("ifdown wan"); - return; - } - - fp = fopen(config, "w"); - if (fp == NULL) - return; - - fprintf(fp, "IFNAME=\"%s\"\n", ifname); - fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv4Str(ipv4->Address)); - fprintf(fp, "NETMASK=\"%s\"\n", ipv4Str(ipv4->SubnetMask)); - fprintf(fp, "GATEWAY=\"%s\"\n", ipv4Str(ipv4->Gateway)); - fprintf(fp, "DNSSERVERS=\"%s", ipv4Str(ipv4->DnsPrimary)); - if (ipv4->DnsSecondary != 0) - fprintf(fp, " %s", ipv4Str(ipv4->DnsSecondary)); - fprintf(fp, "\"\n"); - - fclose(fp); - - if (!ql_openwrt_is_wan(ifname)) - return; - - ql_openwrt_system("ifup wan"); -} - -static void ql_openwrt_setup_wan6(const char *ifname, const IPV6_T *ipv6) { - FILE *fp = NULL; - char config[64]; - int first_ifup; - - snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv6config", ifname); - - if (ipv6 == NULL) { - if (ql_openwrt_is_wan(ifname)) - ql_openwrt_system("ifdown wan6"); - return; - } - - first_ifup = (access(config, F_OK) != 0); - - fp = fopen(config, "w"); - if (fp == NULL) - return; - - fprintf(fp, "IFNAME=\"%s\"\n", ifname); - fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv6Str(ipv6->Address)); - fprintf(fp, "NETMASK=\"%s\"\n", ipv6Str(ipv6->SubnetMask)); - fprintf(fp, "GATEWAY=\"%s\"\n", ipv6Str(ipv6->Gateway)); - fprintf(fp, "PrefixLength=\"%d\"\n", ipv6->PrefixLengthIPAddr); - fprintf(fp, "DNSSERVERS=\"%s", ipv6Str(ipv6->DnsPrimary)); - if (ipv6->DnsSecondary[0]) - fprintf(fp, " %s", ipv6Str(ipv6->DnsSecondary)); - fprintf(fp, "\"\n"); - - fclose(fp); - - if (!ql_openwrt_is_wan(ifname)) - return; - - if (first_ifup) - ql_openwrt_system("ifup wan6"); - else - ql_openwrt_system("/etc/init.d/network restart"); //make PC to release old IPV6 address, and RS new IPV6 address - -#if 1 //TODO? why need this? - if (openwrt_lan) { - int i; - char shell_cmd[128]; - UCHAR Address[16] = {0}; - - ql_openwrt_system(("ifstatus lan")); - - for (i = 0; i < (ipv6->PrefixLengthIPAddr/8); i++) - Address[i] = ipv6->Address[i]; - - snprintf(shell_cmd, sizeof(shell_cmd), "ip route del %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, ifname); - ql_openwrt_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "ip route add %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, openwrt_lan); - ql_system(shell_cmd); - } -#endif -} -#endif - -void udhcpc_start(PROFILE_T *profile) { - char *ifname = profile->usbnet_adapter; - char shell_cmd[128]; - - ql_set_driver_link_state(profile, 1); - - if (profile->qmapnet_adapter[0]) { - ifname = profile->qmapnet_adapter; - } - - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) { - ql_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - if (strcmp(ifname, profile->usbnet_adapter)) { - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", profile->usbnet_adapter); - ql_system(shell_cmd); - if (ifc_get_flags(ifname)&IFF_UP) { - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname); - ql_system(shell_cmd); - } - } - - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname); - ql_system(shell_cmd); - - if (profile->ipv4.Address) { - if (profile->PCSCFIpv4Addr1) - dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1)); - if (profile->PCSCFIpv4Addr2) - dbg_time("pcscf2: %s", ipv4Str(profile->PCSCFIpv4Addr2)); - } - - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { - if (profile->PCSCFIpv6Addr1[0]) - dbg_time("pcscf1: %s", ipv6Str(profile->PCSCFIpv6Addr1)); - if (profile->PCSCFIpv6Addr2[0]) - dbg_time("pcscf2: %s", ipv6Str(profile->PCSCFIpv6Addr2)); - } - -#if 1 //for bridge mode, only one public IP, so do udhcpc manually - if (ql_bridge_mode_detect(profile)) { - return; - } -#endif - -//because must use udhcpc to obtain IP when working on ETH mode, -//so it is better also use udhcpc to obtain IP when working on IP mode. -//use the same policy for all modules -#if 0 - if (profile->rawIP != 0) //mdm9x07/ec25,ec20 R2.0 - { - update_ip_address_by_qmi(ifname, &profile->ipv4, &profile->ipv6); - return; - } -#endif - - if (profile->ipv4.Address == 0) - goto set_ipv6; - - if (profile->request_ops == &mbim_request_ops) { //lots of mbim modem do not support DHCP - update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); - } - else -/* Do DHCP using busybox tools */ - { - char udhcpc_cmd[128]; - pthread_attr_t udhcpc_thread_attr; - pthread_t udhcpc_thread_id; - - pthread_attr_init(&udhcpc_thread_attr); - pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED); - -#ifdef USE_DHCLIENT - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -4 -d --no-pid %s", ifname); - dhclient_alive++; -#else - if (access("/usr/share/udhcpc/default.script", X_OK) - && access("/etc//udhcpc/default.script", X_OK)) { - dbg_time("No default.script found, it should be in '/usr/share/udhcpc/' or '/etc//udhcpc' depend on your udhcpc version!"); - } - - //-f,--foreground Run in foreground - //-b,--background Background if lease is not obtained - //-n,--now Exit if lease is not obtained - //-q,--quit Exit after obtaining lease - //-t,--retries N Send up to N discover packets (default 3) - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "busybox udhcpc -f -n -q -t 5 -i %s", ifname); -#endif - -#if 1 //for OpenWrt - if (!access("/lib/netifd/dhcp.script", X_OK) && !access("/sbin/ifup", X_OK) && !access("/sbin/ifstatus", X_OK)) { -#if 0 //20210415 do not promot these message - dbg_time("you are use OpenWrt?"); - dbg_time("should not calling udhcpc manually?"); - dbg_time("should modify /etc/config/network as below?"); - dbg_time("config interface wan"); - dbg_time("\toption ifname %s", ifname); - dbg_time("\toption proto dhcp"); - dbg_time("should use \"/sbin/ifstaus wan\" to check %s 's status?", ifname); -#endif - } -#endif - -#ifdef USE_DHCLIENT - pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); - sleep(1); -#else - pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); - pthread_join(udhcpc_thread_id, NULL); - - if (profile->request_ops == &atc_request_ops - && !ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) { - ql_get_netcard_carrier_state(ifname); - } - - if (profile->request_ops != &qmi_request_ops) { //only QMI modem support next fixup! - goto set_ipv6; - } - - if (ql_raw_ip_mode_check(ifname, profile->ipv4.Address)) { - pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); - pthread_join(udhcpc_thread_id, NULL); - } - - if (!ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) { - //no udhcpc's default.script exist, directly set ip and dns - update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); - } - //Add by Demon. check default route - FILE *rt_fp = NULL; - char rt_cmd[128] = {0}; - - //Check if there is a default route. - snprintf(rt_cmd, sizeof(rt_cmd), "route -n | grep %s | awk '{print $1}' | grep 0.0.0.0", ifname); - rt_fp = popen((const char *)rt_cmd, "r"); - if (rt_fp != NULL) { - char buf[20] = {0}; - int found_default_rt = 0; - - if (fgets(buf, sizeof(buf), rt_fp) != NULL) { - //Find the specified interface - found_default_rt = 1; - } - - if (1 == found_default_rt) { - //dbg_time("Route items found for %s", ifname); - } - else { - dbg_time("Warning: No route items found for %s", ifname); - } - - pclose(rt_fp); - } - //End by Demon. -#endif - } - -#ifdef QL_OPENWER_NETWORK_SETUP - ql_openwrt_setup_wan(ifname, &profile->ipv4); -#endif - -set_ipv6: - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { -#if 1 - //module do not support DHCPv6, only support 'Router Solicit' - //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) { - char forward_state[2]; - if (read(forward_fd, forward_state, 2) == -1) {}; - if (forward_state[0] == '1') { - //dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); - } - close(forward_fd); - } - - update_ip_address_by_qmi(ifname, NULL, &profile->ipv6); - - if (profile->ipv6.DnsPrimary[0] || profile->ipv6.DnsSecondary[0]) { - char dns1str[64], dns2str[64]; - - if (profile->ipv6.DnsPrimary[0]) { - strcpy(dns1str, ipv6Str(profile->ipv6.DnsPrimary)); - } - - if (profile->ipv6.DnsSecondary[0]) { - strcpy(dns2str, ipv6Str(profile->ipv6.DnsSecondary)); - } - - update_resolv_conf(6, ifname, profile->ipv6.DnsPrimary[0] ? dns1str : NULL, - profile->ipv6.DnsSecondary[0] != '\0' ? dns2str : NULL); - } - -#ifdef QL_OPENWER_NETWORK_SETUP - ql_openwrt_setup_wan6(ifname, &profile->ipv6); -#endif -#else -#ifdef USE_DHCLIENT - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -6 -d --no-pid %s", ifname); - dhclient_alive++; -#else - /* - DHCPv6: Dibbler - a portable DHCPv6 - 1. download from http://klub.com.pl/dhcpv6/ - 2. cross-compile - 2.1 ./configure --host=arm-linux-gnueabihf - 2.2 copy dibbler-client to your board - 3. mkdir -p /var/log/dibbler/ /var/lib/ on your board - 4. create /etc/dibbler/client.conf on your board, the content is - log-mode short - log-level 7 - iface wwan0 { - ia - option dns-server - } - 5. run "dibbler-client start" to get ipV6 address - 6. run "route -A inet6 add default dev wwan0" to add default route - */ - snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default %s", ifname); - ql_system(shell_cmd); - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dibbler-client run"); - dibbler_client_alive++; -#endif - - pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); -#endif - } -} - -void udhcpc_stop(PROFILE_T *profile) { - char *ifname = profile->usbnet_adapter; - char shell_cmd[128]; - - ql_set_driver_link_state(profile, 0); - - if (profile->qmapnet_adapter[0]) { - ifname = profile->qmapnet_adapter; - } - -#ifdef USE_DHCLIENT - if (dhclient_alive) { - system("killall dhclient"); - dhclient_alive = 0; - } -#endif - if (dibbler_client_alive) { - if (system("killall dibbler-client")) {}; - dibbler_client_alive = 0; - } - -//it seems when call netif_carrier_on(), and netcard 's IP is "0.0.0.0", will cause netif_queue_stopped() - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s 0.0.0.0", ifname); - ql_system(shell_cmd); - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname); - ql_system(shell_cmd); - -#ifdef QL_OPENWER_NETWORK_SETUP - ql_openwrt_setup_wan(ifname, NULL); - ql_openwrt_setup_wan6(ifname, NULL); -#endif -} diff --git a/quectel_cm_5G/src/udhcpc_netlink.c b/quectel_cm_5G/src/udhcpc_netlink.c deleted file mode 100644 index 56209f8..0000000 --- a/quectel_cm_5G/src/udhcpc_netlink.c +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmnl/ifutils.h" -#include "libmnl/dhcp/dhcp.h" -#include "util.h" -#include "QMIThread.h" - -static int ql_raw_ip_mode_check(const char *ifname) -{ - int fd; - char raw_ip[128]; - char mode[2] = "X"; - int mode_change = 0; - - snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); - if (access(raw_ip, F_OK)) - return 0; - - fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd < 0) - { - dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); - return 0; - } - - read(fd, mode, 2); - if (mode[0] == '0' || mode[0] == 'N') - { - if_link_down(ifname); - dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); - mode[0] = 'Y'; - write(fd, mode, 2); - mode_change = 1; - if_link_up(ifname); - } - - close(fd); - return mode_change; -} - -void ql_set_driver_link_state(PROFILE_T *profile, int link_state) -{ - char link_file[128]; - int fd; - int new_state = 0; - - snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); - fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) - { - if (errno != ENOENT) - dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); - return; - } - - if (profile->qmap_mode <= 1) - new_state = !!link_state; - else - { - //0x80 means link off this pdp - new_state = (link_state ? 0x00 : 0x80) + profile->pdp; - } - - snprintf(link_file, sizeof(link_file), "%d\n", new_state); - write(fd, link_file, sizeof(link_file)); - - if (link_state == 0 && profile->qmap_mode > 1) - { - size_t rc; - - lseek(fd, 0, SEEK_SET); - rc = read(fd, link_file, sizeof(link_file)); - if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n"))) - { - if_link_down(profile->usbnet_adapter); - } - } - - close(fd); -} - -void udhcpc_start(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - - ql_set_driver_link_state(profile, 1); - ql_raw_ip_mode_check(ifname); - - if (profile->qmapnet_adapter) - { - ifname = profile->qmapnet_adapter; - } - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) - { - if_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - if (strcmp(ifname, profile->usbnet_adapter)) - { - if_link_up(profile->usbnet_adapter); - } - - if_link_up(ifname); - -#if 1 //for bridge mode, only one public IP, so do udhcpc manually - if (ql_bridge_mode_detect(profile)) - { - return; - } -#endif - // if use DHCP(should make with ${DHCP} src files) - // do_dhcp(ifname); - // return 0; - /* IPv4 Addr Info */ - if (profile->ipv4.Address) - { - dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu); - dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address))); - dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask))); - dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway))); - dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary))); - dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary))); - if_set_network_v4(ifname, ntohl(profile->ipv4.Address), - mask_to_prefix_v4(profile->ipv4.SubnetMask), - ntohl(profile->ipv4.Gateway), - ntohl(profile->ipv4.DnsPrimary), - ntohl(profile->ipv4.DnsSecondary)); - } - - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) - { - //module do not support DHCPv6, only support 'Router Solicit' - //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) - { - char forward_state[2]; - read(forward_fd, forward_state, 2); - if (forward_state[0] == '1') - { - dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); - } - close(forward_fd); - } - - dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu); - dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address)); - dbg_time("IPv6 Netmask: %d", profile->ipv6.PrefixLengthIPAddr); - dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway)); - dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary)); - dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary)); - if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr, - profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary); - } -} - -void udhcpc_stop(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - - ql_set_driver_link_state(profile, 0); - - if (profile->qmapnet_adapter) - { - ifname = profile->qmapnet_adapter; - } - - if_link_down(ifname); - if_flush_v4_addr(ifname); - if_flush_v6_addr(ifname); -} diff --git a/quectel_cm_5G/src/udhcpc_script.c b/quectel_cm_5G/src/udhcpc_script.c deleted file mode 100644 index 5e32ae3..0000000 --- a/quectel_cm_5G/src/udhcpc_script.c +++ /dev/null @@ -1,132 +0,0 @@ -/****************************************************************************** - @file udhcpc.c - @brief call DHCP tools to obtain IP address. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "QMIThread.h" - -#define IFDOWN_SCRIPT "/etc/quectel/ifdown.sh" -#define IFUP_SCRIPT "/etc/quectel/ifup.sh" - -static int ql_system(const char *shell_cmd) -{ - dbg_time("%s", shell_cmd); - return system(shell_cmd); -} - -uint32_t mask_to_prefix_v4(uint32_t mask) -{ - uint32_t prefix = 0; - while (mask) - { - mask = mask & (mask - 1); - prefix++; - } - return prefix; -} - -uint32_t mask_from_prefix_v4(uint32_t prefix) -{ - return ~((1 << (32 - prefix)) - 1); -} - -/* mask in int */ -uint32_t broadcast_from_mask(uint32_t ip, uint32_t mask) -{ - return (ip & mask) | (~mask); -} - -const char *ipaddr_to_string_v4(in_addr_t ipaddr, char *buf, size_t size) -{ - // static char buf[INET6_ADDRSTRLEN] = {'\0'}; - buf[0] = '\0'; - uint32_t addr = ipaddr; - return inet_ntop(AF_INET, &addr, buf, size); -} - -const char *ipaddr_to_string_v6(uint8_t *ipaddr, char *buf, size_t size) -{ - buf[0] = '\0'; - return inet_ntop(AF_INET6, ipaddr, buf, size); -} - -/** - * For more details see default.script - * - * The main aim of this function is offload ip management to script, CM has not interest in manage IP address. - * just tell script all the info about ip, mask, router, dns... - */ -void udhcpc_start(PROFILE_T *profile) -{ - char shell_cmd[1024]; - char ip[128]; - char subnet[128]; - char broadcast[128]; - char router[128]; - char domain1[128]; - char domain2[128]; - - if (NULL == getenv(IFUP_SCRIPT)) - return; - - // manage IPv4??? - // check rawip ??? - snprintf(shell_cmd, sizeof(shell_cmd), - " netiface=%s interface=%s mtu=%u ip=%s subnet=%s broadcast=%s router=%s" - " domain=\"%s %s\" %s", - profile->usbnet_adapter, - profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter, - profile->ipv4.Mtu, - ipaddr_to_string_v4(ntohl(profile->ipv4.Address), ip, sizeof(ip)), - ipaddr_to_string_v4(ntohl(profile->ipv4.SubnetMask), subnet, sizeof(subnet)), - ipaddr_to_string_v4(ntohl(broadcast_from_mask(profile->ipv4.Address, profile->ipv4.SubnetMask)), - broadcast, sizeof(broadcast)), - ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway), router, sizeof(router)), - ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary), domain1, sizeof(domain1)), - ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary), domain2, sizeof(domain2)), - getenv(IFUP_SCRIPT)); - ql_system(shell_cmd); - - // manage IPv6??? -} - -/** - * For more details see default.script - * - * The main aim of this function is offload ip management to script, CM has not interest in manage IP address. - * just tell script all the info about ip, mask, router, dns... - */ -void udhcpc_stop(PROFILE_T *profile) -{ - char shell_cmd[1024]; - - if (NULL == getenv(IFDOWN_SCRIPT)) - return; - - snprintf(shell_cmd, sizeof(shell_cmd), - "netiface=%s interface=%s %s", - profile->usbnet_adapter, - profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter, - getenv(IFDOWN_SCRIPT)); - ql_system(shell_cmd); -} diff --git a/quectel_cm_5G/src/util.c b/quectel_cm_5G/src/util.c deleted file mode 100644 index dbf2162..0000000 --- a/quectel_cm_5G/src/util.c +++ /dev/null @@ -1,361 +0,0 @@ -/****************************************************************************** - @file util.c - @brief some utils for this QCM tool. - - DESCRIPTION - Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - -#include -#include -typedef unsigned short sa_family_t; -#include - -#if defined(__STDC__) -#include -#define __V(x) x -#else -#include -#define __V(x) (va_alist) va_dcl -#define const -#define volatile -#endif - -#include - -#include "QMIThread.h" - -pthread_mutex_t cm_command_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cm_command_cond = PTHREAD_COND_INITIALIZER; -unsigned int cm_recv_buf[1024]; - -int cm_open_dev(const char *dev) { - int fd; - - fd = open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd != -1) { - fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); - fcntl(fd, F_SETFD, FD_CLOEXEC); - - if (!strncmp(dev, "/dev/tty", strlen("/dev/tty"))) - { - //disable echo on serial ports - struct termios ios; - - memset(&ios, 0, sizeof(ios)); - tcgetattr( fd, &ios ); - cfmakeraw(&ios); - cfsetispeed(&ios, B115200); - cfsetospeed(&ios, B115200); - tcsetattr( fd, TCSANOW, &ios ); - tcflush(fd, TCIOFLUSH); - } - } else { - dbg_time("Failed to open %s, errno: %d (%s)", dev, errno, strerror(errno)); - } - - return fd; -} - -int cm_open_proxy(const char *name) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (sockfd < 0) - return sockfd; - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name) ); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - if(connect(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dbg_time("connect %s errno: %d (%s)", name, errno, strerror(errno)); - return -1; - } - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); - fcntl(sockfd, F_SETFL, fcntl(sockfd,F_GETFL) | O_NONBLOCK); - fcntl(sockfd, F_SETFD, FD_CLOEXEC); - - dbg_time("connect to %s sockfd = %d", name, sockfd); - - return sockfd; -} - -static void setTimespecRelative(struct timespec *p_ts, long long msec) -{ - struct timeval tv; - - gettimeofday(&tv, (struct timezone *) NULL); - - /* what's really funny about this is that I know - pthread_cond_timedwait just turns around and makes this - a relative time again */ - p_ts->tv_sec = tv.tv_sec + (msec / 1000); - p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; - if ((unsigned long)p_ts->tv_nsec >= 1000000000UL) { - p_ts->tv_sec += 1; - p_ts->tv_nsec -= 1000000000UL; - } -} - -int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs) { - if (msecs != 0) { - unsigned i; - unsigned t = msecs/4; - int ret = 0; - - if (t == 0) - t = 1; - - for (i = 0; i < msecs; i += t) { - struct timespec ts; - setTimespecRelative(&ts, t); -//very old uclibc do not support pthread_condattr_setclock(CLOCK_MONOTONIC) - ret = pthread_cond_timedwait(cond, mutex, &ts); //to advoid system time change - if (ret != ETIMEDOUT) { - if(ret) dbg_time("ret=%d, msecs=%u, t=%u", ret, msecs, t); - break; - } - } - - return ret; - } else { - return pthread_cond_wait(cond, mutex); - } -} - -const char * get_time(void) { - static char time_buf[128]; - struct timeval tv; - time_t time; - suseconds_t millitm; - struct tm *ti; - - gettimeofday (&tv, NULL); - - time= tv.tv_sec; - millitm = (tv.tv_usec + 500) / 1000; - - if (millitm == 1000) { - ++time; - millitm = 0; - } - - ti = localtime(&time); - sprintf(time_buf, "%02d-%02d_%02d:%02d:%02d:%03d", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); - return time_buf; -} - -unsigned long clock_msec(void) -{ - struct timespec tm; - clock_gettime( CLOCK_MONOTONIC, &tm); - return (unsigned long)(tm.tv_sec*1000 + (tm.tv_nsec/1000000)); -} - -FILE *logfilefp = NULL; - -void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2) { - const char *dns_file = "/etc/resolv.conf"; - FILE *dns_fp; - char dns_line[256]; - #define MAX_DNS 16 - char *dns_info[MAX_DNS]; - char dns_tag[64]; - int dns_match = 0; - int i; - - snprintf(dns_tag, sizeof(dns_tag), "# IPV%d %s", iptype, ifname); - - for (i = 0; i < MAX_DNS; i++) - dns_info[i] = NULL; - - dns_fp = fopen(dns_file, "r"); - if (dns_fp) { - i = 0; - dns_line[sizeof(dns_line)-1] = '\0'; - - while((fgets(dns_line, sizeof(dns_line)-1, dns_fp)) != NULL) { - if ((strlen(dns_line) > 1) && (dns_line[strlen(dns_line) - 1] == '\n')) - dns_line[strlen(dns_line) - 1] = '\0'; - //dbg_time("%s", dns_line); - if (strstr(dns_line, dns_tag)) { - dns_match++; - continue; - } - dns_info[i++] = strdup(dns_line); - if (i == MAX_DNS) - break; - } - - fclose(dns_fp); - } - else if (errno != ENOENT) { - dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); - return; - } - - if (dns1 == NULL && dns_match == 0) - return; - - dns_fp = fopen(dns_file, "w"); - if (dns_fp) { - if (dns1) - fprintf(dns_fp, "nameserver %s %s\n", dns1, dns_tag); - if (dns2) - fprintf(dns_fp, "nameserver %s %s\n", dns2, dns_tag); - - for (i = 0; i < MAX_DNS && dns_info[i]; i++) - fprintf(dns_fp, "%s\n", dns_info[i]); - fclose(dns_fp); - } - else { - dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); - } - - for (i = 0; i < MAX_DNS && dns_info[i]; i++) - free(dns_info[i]); -} - -pid_t getpid_by_pdp(int pdp, const char* program_name) -{ - glob_t gt; - int ret; - char filter[16]; - pid_t pid; - - snprintf(filter, sizeof(filter), "-n %d", pdp); - ret = glob("/proc/*/cmdline", GLOB_NOSORT, NULL, >); - if (ret != 0) { - dbg_time("glob error, errno = %d(%s)", errno, strerror(errno)); - return -1; - } else { - int i = 0, fd = -1; - ssize_t nreads; - char cmdline[512] = {0}; - - for (i = 0; i < (int)gt.gl_pathc; i++) { - fd = open(gt.gl_pathv[i], O_RDONLY); - if (fd == -1) { - dbg_time("open %s failed, errno = %d(%s)", gt.gl_pathv[i], errno, strerror(errno)); - globfree(>); - return -1; - } - - nreads = read(fd, cmdline, sizeof(cmdline)); - if (nreads > 0) { - int pos = 0; - while (pos < nreads-1) { - if (cmdline[pos] == '\0') - cmdline[pos] = ' '; // space - pos++; - } - // printf("%s\n", cmdline); - } - - if (strstr(cmdline, program_name) && strstr(cmdline, filter)) { - char path[64] = {0}; - char pidstr[64] = {0}; - char *p; - - dbg_time("%s: %s", gt.gl_pathv[i], cmdline); - strcpy(path, gt.gl_pathv[i]); - p = strstr(gt.gl_pathv[i], "/cmdline"); - *p = '\0'; - while (*(--p) != '/') ; - - strcpy(pidstr, p+1); - pid = atoi(pidstr); - globfree(>); - - return pid; - } - } - } - - globfree(>); - return -1; -} - -void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info) { - int ifc_ctl_sock; - struct ifreq ifr; - int rc; - int request = 0x89F3; - unsigned char data[512]; - - memset(rmnet_info, 0x00, sizeof(*rmnet_info)); - - ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ifc_ctl_sock <= 0) { - dbg_time("socket() failed: %s\n", strerror(errno)); - return; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ - 1] = 0; - ifr.ifr_ifru.ifru_data = (void *)data; - - rc = ioctl(ifc_ctl_sock, request, &ifr); - if (rc < 0) { - if (errno != ENOTSUP) - dbg_time("ioctl(0x%x, qmap_settings) errno:%d (%s), rc=%d", request, errno, strerror(errno), rc); - } - else { - memcpy(rmnet_info, data, sizeof(*rmnet_info)); - } - - close(ifc_ctl_sock); -} - -void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings) { - int ifc_ctl_sock; - struct ifreq ifr; - int rc; - int request = 0x89F2; - - ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ifc_ctl_sock <= 0) { - dbg_time("socket() failed: %s\n", strerror(errno)); - return; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ - 1] = 0; - ifr.ifr_ifru.ifru_data = (void *)qmap_settings; - - rc = ioctl(ifc_ctl_sock, request, &ifr); - if (rc < 0) { - dbg_time("ioctl(0x%x, qmap_settings) failed: %s, rc=%d", request, strerror(errno), rc); - } - - close(ifc_ctl_sock); -} - -void no_trunc_strncpy(char *dest, const char *src, size_t dest_size) -{ - size_t i = 0; - - for (i = 0; i < dest_size && *src; i++) { - *dest++ = *src++; - } - - *dest = 0; -} diff --git a/quectel_cm_5G/src/util.h b/quectel_cm_5G/src/util.h deleted file mode 100644 index 4354bbc..0000000 --- a/quectel_cm_5G/src/util.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - @file - util.h - - @brief - This file provides the definitions, and declares some common APIs for list-algorithm. - - */ - -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include -#include - -struct listnode -{ - struct listnode *next; - struct listnode *prev; -}; - -#define node_to_item(node, container, member) \ - (container *) (((char*) (node)) - offsetof(container, member)) - -#define list_declare(name) \ - struct listnode name = { \ - .next = &name, \ - .prev = &name, \ - } - -#define list_for_each(node, list) \ - for (node = (list)->next; node != (list); node = node->next) - -#define list_for_each_reverse(node, list) \ - for (node = (list)->prev; node != (list); node = node->prev) - -void list_init(struct listnode *list); -void list_add_tail(struct listnode *list, struct listnode *item); -void list_add_head(struct listnode *head, struct listnode *item); -void list_remove(struct listnode *item); - -#define list_empty(list) ((list) == (list)->next) -#define list_head(list) ((list)->next) -#define list_tail(list) ((list)->prev) - -int epoll_register(int epoll_fd, int fd, unsigned int events); -int epoll_deregister(int epoll_fd, int fd); -const char * get_time(void); -unsigned long clock_msec(void); -pid_t getpid_by_pdp(int, const char*); - -#endif diff --git a/rooter/0basicapps/ext-command/Makefile b/rooter/0basicapps/ext-command/Makefile deleted file mode 100644 index 828e77a..0000000 --- a/rooter/0basicapps/ext-command/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-command -PKG_VERSION:=4.500 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-command - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Applications - TITLE:=support for Command - PKGARCH:=all -endef - -define Package/ext-command/description - Helper scripts to enable command -endef - - -define Build/Compile -endef - -define Package/ext-command/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,ext-command)) diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua deleted file mode 100644 index a9f0640..0000000 --- a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/controller/commands.lua +++ /dev/null @@ -1,296 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2012 Jo-Philipp Wich - -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 - -]]-- - -module("luci.controller.commands", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - entry({"admin", "system", "commands"}, firstchild(), _(translate("Custom Commands")), 80) - entry({"admin", "system", "commands", "dashboard"}, template("commands"), _(translate("Dashboard")), 1) - entry({"admin", "system", "commands", "config"}, cbi("commands"), _(translate("Configure")), 2) - entry({"admin", "system", "commands", "script"}, template("cmdedit"), _(translate("Scripts")), 3) - entry({"admin", "system", "commands", "run"}, call("action_run"), nil, 3).leaf = true - entry({"admin", "system", "commands", "download"}, call("action_download"), nil, 3).leaf = true - end - - entry({"admin", "system", "load_script"}, call("action_load_script")) - entry({"admin", "system", "save_script"}, call("action_save_script")) - entry({"admin", "system", "del_script"}, call("action_del_script")) - - entry({"command"}, call("action_public"), nil, 1).leaf = true -end - ---- Decode a given string into arguments following shell quoting rules ---- [[abc \def "foo\"bar" abc'def']] -> [[abc def]] [[foo"bar]] [[abcdef]] -local function parse_args(str) - local args = { } - - local function isspace(c) - if c == 9 or c == 10 or c == 11 or c == 12 or c == 13 or c == 32 then - return c - end - end - - local function isquote(c) - if c == 34 or c == 39 or c == 96 then - return c - end - end - - local function isescape(c) - if c == 92 then - return c - end - end - - local function ismeta(c) - if c == 36 or c == 92 or c == 96 then - return c - end - end - - --- Convert given table of byte values into a Lua string and append it to - --- the "args" table. Segment byte value sequence into chunks of 256 values - --- to not trip over the parameter limit for string.char() - local function putstr(bytes) - local chunks = { } - local csz = 256 - local upk = unpack - local chr = string.char - local min = math.min - local len = #bytes - local off - - for off = 1, len, csz do - chunks[#chunks+1] = chr(upk(bytes, off, min(off + csz - 1, len))) - end - - args[#args+1] = table.concat(chunks) - end - - --- Scan substring defined by the indexes [s, e] of the string "str", - --- perform unquoting and de-escaping on the fly and store the result in - --- a table of byte values which is passed to putstr() - local function unquote(s, e) - local off, esc, quote - local res = { } - - for off = s, e do - local byte = str:byte(off) - local q = isquote(byte) - local e = isescape(byte) - local m = ismeta(byte) - - if e then - esc = true - elseif esc then - if m then res[#res+1] = 92 end - res[#res+1] = byte - esc = false - elseif q and quote and q == quote then - quote = nil - elseif q and not quote then - quote = q - else - if m then res[#res+1] = 92 end - res[#res+1] = byte - end - end - - putstr(res) - end - - --- Find substring boundaries in "str". Ignore escaped or quoted - --- whitespace, pass found start- and end-index for each substring - --- to unquote() - local off, esc, start, quote - for off = 1, #str + 1 do - local byte = str:byte(off) - local q = isquote(byte) - local s = isspace(byte) or (off > #str) - local e = isescape(byte) - - if esc then - esc = false - elseif e then - esc = true - elseif q and quote and q == quote then - quote = nil - elseif q and not quote then - start = start or off - quote = q - elseif s and not quote then - if start then - unquote(start, off - 1) - start = nil - end - else - start = start or off - end - end - - --- If the "quote" is still set we encountered an unfinished string - if quote then - unquote(start, #str) - end - - return args -end - -local function parse_cmdline(cmdid, args) - local uci = require "luci.model.uci".cursor() - if uci:get("luci", cmdid) == "command" then - local cmd = uci:get_all("luci", cmdid) - local argv = parse_args(cmd.command) - local i, v - - if cmd.param == "1" and args then - for i, v in ipairs(parse_args(luci.http.urldecode(args))) do - argv[#argv+1] = v - end - end - - for i, v in ipairs(argv) do - if v:match("[^%w%.%-i/]") then - argv[i] = '"%s"' % v:gsub('"', '\\"') - end - end - - return argv - end -end - -function action_run(...) - local fs = require "nixio.fs" - local argv = parse_cmdline(...) - if argv then - local outfile = os.tmpname() - local errfile = os.tmpname() - - local rv = os.execute(table.concat(argv, " ") .. " >%s 2>%s" %{ outfile, errfile }) - local stdout = fs.readfile(outfile, 1024 * 512) or "" - local stderr = fs.readfile(errfile, 1024 * 512) or "" - - fs.unlink(outfile) - fs.unlink(errfile) - - local binary = not not (stdout:match("[%z\1-\8\14-\31]")) - - luci.http.prepare_content("application/json") - luci.http.write_json({ - command = table.concat(argv, " "), - stdout = not binary and stdout, - stderr = stderr, - exitcode = rv, - binary = binary - }) - else - luci.http.status(404, translate("No such command")) - end -end - -function action_download(...) - local fs = require "nixio.fs" - local argv = parse_cmdline(...) - if argv then - local fd = io.popen(table.concat(argv, " ") .. " 2>/dev/null") - if fd then - local chunk = fd:read(4096) or "" - local name - if chunk:match("[%z\1-\8\14-\31]") then - luci.http.header("Content-Disposition", "attachment; filename=%s" - % fs.basename(argv[1]):gsub("%W+", ".") .. ".bin") - luci.http.prepare_content("application/octet-stream") - else - luci.http.header("Content-Disposition", "attachment; filename=%s" - % fs.basename(argv[1]):gsub("%W+", ".") .. ".txt") - luci.http.prepare_content("text/plain") - end - - while chunk do - luci.http.write(chunk) - chunk = fd:read(4096) - end - - fd:close() - else - luci.http.status(500, translate("Failed to execute command")) - end - else - luci.http.status(404, "No such command") - end -end - -function action_public(cmdid, args) - local uci = require "luci.model.uci".cursor() - if cmdid and - uci:get("luci", cmdid) == "command" and - uci:get("luci", cmdid, "public") == "1" - then - action_download(cmdid, args) - else - luci.http.status(403, translate("Access to command denied")) - end -end - -function action_load_script() - local set = luci.http.formvalue("set") - local rv ={} - local file - - file = io.open(set, "r") - if file ~= nil then - local tmp = file:read("*all") - rv["text"] = tmp - file:close() - else - rv["text"] = translate("No file found") - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_save_script() - local line = luci.http.formvalue("set") - local rv ={} - local file - - s, e = line:find("|") - name = line:sub(1,s-1) - text = line:sub(e+1) - - file = io.open(name, "w") - file:write(text) - file:close() - os.execute("chmod 777 " .. name) - - rv["name"] = name - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_del_script() - local name = luci.http.formvalue("set") - local rv ={} - os.remove(name) - - rv["name"] = name - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end \ No newline at end of file diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua deleted file mode 100644 index 1359eb2..0000000 --- a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/model/cbi/commands.lua +++ /dev/null @@ -1,37 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2012 Jo-Philipp Wich - -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 - -]]-- - -local m, s - -m = Map("luci", translate("Custom Commands"), - translate("This page allows you to configure custom shell commands which can be easily invoked from the web interface.")) - -s = m:section(TypedSection, "command", "") -s.template = "cbi/tblsection" -s.anonymous = true -s.addremove = true - - -s:option(Value, "name", translate("Description"), - translate("A short textual description of the configured command")) - -s:option(Value, "command", translate("Command"), - translate("Command line to execute")) - -s:option(Flag, "param", translate("Custom arguments"), - translate("Allow the user to provide additional command line arguments")) - -s:option(Flag, "public", translate("Public access"), - translate("Allow executing the command and downloading its output without prior authentication")) - -return m diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm deleted file mode 100644 index cfd8a53..0000000 --- a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/cmdedit.htm +++ /dev/null @@ -1,186 +0,0 @@ -<%+header%> - - - - -
      -
      -

      <%:Script Editing%>

      -
      <%:Create, Edit and Save Scripts%>
      -
      - - - - - - -
      <%:Script Name :%>
       
      - - - - - - -
      <%:Path to Script :%>
       
      - - - - - -
      - -
      - - - - - - - - - -
       
      - -
      - -
      -
      -<%+footer%> \ No newline at end of file diff --git a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm b/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm deleted file mode 100644 index 83792a9..0000000 --- a/rooter/0basicapps/ext-command/files/usr/lib/lua/luci/view/commands.htm +++ /dev/null @@ -1,176 +0,0 @@ -<%# -LuCI - Lua Configuration Interface -Copyright 2012 Jo-Philipp Wich - -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 - --%> - -<% css = [[ - -.commandbox { - height: 12em; - width: 30%; - float: left; - height: 12em; - margin: 5px; - position: relative; -} - -.commandbox h3 { - font-size: 1.5em !important; - line-height: 2em !important; - margin: 0 !important; -} - -.commandbox input[type="text"] { - width: 50% !important; -} - -.commandbox div { - position: absolute; - left: 0; - bottom: 1.5em; -} - -]] -%> - -<%+header%> - - - - -<% - local uci = require "luci.model.uci".cursor() - local commands = { } - - uci:foreach("luci", "command", function(s) commands[#commands+1] = s end) -%> - -
      "> -
      -

      <%:Custom Commands%>

      - -
      - <% local _, command; for _, command in ipairs(commands) do %> -
      -

      <%=pcdata(command.name)%>

      -

      <%:Command:%> <%=pcdata(command.command)%>

      - <% if command.param == "1" then %> -

      <%:Arguments:%>

      - <% end %> -
      - - - <% if command.public == "1" then %> - - <% end %> -
      -
      - <% end %> - -

      - -
      -
      - - -
      - -<%+footer%> diff --git a/rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy b/rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy deleted file mode 100644 index c227083..0000000 --- a/rooter/0basicapps/ext-command/files/usr/lib/scripts/dummy +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/rooter/0basicapps/ext-extra/Makefile b/rooter/0basicapps/ext-extra/Makefile deleted file mode 100644 index 07a6c59..0000000 --- a/rooter/0basicapps/ext-extra/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-extra -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-extra - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Applications - TITLE:=Add Scheduled Reboot - PKGARCH:=all -endef - -define Package/ext-extra/description - Helper scripts to install Scheduled Reboot -endef - - -define Build/Compile -endef - -define Package/ext-extra/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-extra)) diff --git a/rooter/0basicapps/ext-extra/files/etc/config/schedule b/rooter/0basicapps/ext-extra/files/etc/config/schedule deleted file mode 100644 index 95c1155..0000000 --- a/rooter/0basicapps/ext-extra/files/etc/config/schedule +++ /dev/null @@ -1,7 +0,0 @@ - -config reboot 'reboot' - option enable '0' - -config timezone 'timezone' - option zonename 'UTC' - diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua deleted file mode 100644 index 8c1bda3..0000000 --- a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/controller/schedule.lua +++ /dev/null @@ -1,9 +0,0 @@ --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.schedule", package.seeall) - -function index() - local page - page = entry({"admin", "services", "schedule"}, cbi("schedule"), _("Scheduled Reboot"), 61) - page.dependent = true -end diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua deleted file mode 100644 index 0de690c..0000000 --- a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Copyright 2008 Steven Barth --- Copyright 2008-2013 Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - -local fs = require "nixio.fs" -local cronfile = "/etc/cronuser" - -f = SimpleForm("crontab", translate("Scheduled Tasks"), translate("This is the system crontab in which scheduled tasks can be defined.")) - -t = f:field(TextValue, "crons") -t.rmempty = true -t.rows = 10 -function t.cfgvalue() - return fs.readfile(cronfile) or "" -end - -function f.handle(self, state, data) - if state == FORM_VALID then - if data.crons then - fs.writefile(cronfile, data.crons:gsub("\r\n", "\n")) - else - fs.writefile(cronfile, "") - end - luci.sys.call("/usr/lib/rooter/luci/croncat.sh") - end - return true -end - -return f diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua b/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua deleted file mode 100644 index e6cbf29..0000000 --- a/rooter/0basicapps/ext-extra/files/usr/lib/lua/luci/model/cbi/schedule.lua +++ /dev/null @@ -1,133 +0,0 @@ -local utl = require "luci.util" - -local sys = require "luci.sys" -local zones = require "luci.sys.zoneinfo" -local fs = require "nixio.fs" -local conf = require "luci.config" - -os.execute("/usr/lib/rooter/luci/reboot.sh 0") - -m = Map("schedule", translate("Scheduled Reboot"), translate("Schedule a Router Reboot at a Specified Time")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/rooter/luci/reboot.sh 1 &") -end - -d1 = m:section(TypedSection, "timezone", " ") - ---o1 = d1:option(DummyValue, "_systime", translate("Local Time : ")) ---o1.template = "admin_system/clock_status" - -o = d1:option(DummyValue, "zonename", translate("Timezone : "), translate("Be sure to set your Timezone correctly in System->System")) - -d = m:section(TypedSection, "reboot", " ") - -c1 = d:option(ListValue, "enable", " "); -c1:value("0", "Disabled") -c1:value("1", "Enabled") -c1.default=0 - -sdhour = d:option(ListValue, "sdhour", translate("Reboot Time :")) -sdhour.rmempty = true -sdhour:value("0", "12:00 AM") -sdhour:value("1", "12:15 AM") -sdhour:value("2", "12:30 AM") -sdhour:value("3", "12:45 AM") -sdhour:value("4", "01:00 AM") -sdhour:value("5", "01:15 AM") -sdhour:value("6", "01:30 AM") -sdhour:value("7", "01:45 AM") -sdhour:value("8", "02:00 AM") -sdhour:value("9", "02:15 AM") -sdhour:value("10", "02:30 AM") -sdhour:value("11", "02:45 AM") -sdhour:value("12", "03:00 AM") -sdhour:value("13", "03:15 AM") -sdhour:value("14", "03:30 AM") -sdhour:value("15", "03:45 AM") -sdhour:value("16", "04:00 AM") -sdhour:value("17", "04:15 AM") -sdhour:value("18", "04:30 AM") -sdhour:value("19", "04:45 AM") -sdhour:value("20", "05:00 AM") -sdhour:value("21", "05:15 AM") -sdhour:value("22", "05:30 AM") -sdhour:value("23", "05:45 AM") -sdhour:value("24", "06:00 AM") -sdhour:value("25", "06:15 AM") -sdhour:value("26", "06:30 AM") -sdhour:value("27", "06:45 AM") -sdhour:value("28", "07:00 AM") -sdhour:value("29", "07:15 AM") -sdhour:value("30", "07:30 AM") -sdhour:value("31", "07:45 AM") -sdhour:value("32", "08:00 AM") -sdhour:value("33", "08:15 AM") -sdhour:value("34", "08:30 AM") -sdhour:value("35", "08:45 AM") -sdhour:value("36", "09:00 AM") -sdhour:value("37", "09:15 AM") -sdhour:value("38", "09:30 AM") -sdhour:value("39", "09:45 AM") -sdhour:value("40", "10:00 AM") -sdhour:value("41", "10:15 AM") -sdhour:value("42", "10:30 AM") -sdhour:value("43", "10:45 AM") -sdhour:value("44", "11:00 AM") -sdhour:value("45", "11:15 AM") -sdhour:value("46", "11:30 AM") -sdhour:value("47", "11:45 AM") -sdhour:value("48", "12:00 PM") -sdhour:value("49", "12:15 PM") -sdhour:value("50", "12:30 PM") -sdhour:value("51", "12:45 PM") -sdhour:value("52", "01:00 PM") -sdhour:value("53", "01:15 PM") -sdhour:value("54", "01:30 PM") -sdhour:value("55", "01:45 PM") -sdhour:value("56", "02:00 PM") -sdhour:value("57", "02:15 PM") -sdhour:value("58", "02:30 PM") -sdhour:value("59", "02:45 PM") -sdhour:value("60", "03:00 PM") -sdhour:value("61", "03:15 PM") -sdhour:value("62", "03:30 PM") -sdhour:value("63", "03:45 PM") -sdhour:value("64", "04:00 PM") -sdhour:value("65", "04:15 PM") -sdhour:value("66", "04:30 PM") -sdhour:value("67", "04:45 PM") -sdhour:value("68", "05:00 PM") -sdhour:value("69", "05:15 PM") -sdhour:value("70", "05:30 PM") -sdhour:value("71", "05:45 PM") -sdhour:value("72", "06:00 PM") -sdhour:value("73", "06:15 PM") -sdhour:value("74", "06:30 PM") -sdhour:value("75", "06:45 PM") -sdhour:value("76", "07:00 PM") -sdhour:value("77", "07:15 PM") -sdhour:value("78", "07:30 PM") -sdhour:value("79", "07:45 PM") -sdhour:value("80", "08:00 PM") -sdhour:value("81", "08:15 PM") -sdhour:value("82", "08:30 PM") -sdhour:value("83", "08:45 PM") -sdhour:value("84", "09:00 PM") -sdhour:value("85", "09:15 PM") -sdhour:value("86", "09:30 PM") -sdhour:value("87", "09:45 PM") -sdhour:value("88", "10:00 PM") -sdhour:value("89", "10:15 PM") -sdhour:value("90", "10:30 PM") -sdhour:value("91", "10:45 PM") -sdhour:value("92", "11:00 PM") -sdhour:value("93", "11:15 PM") -sdhour:value("94", "11:30 PM") -sdhour:value("95", "11:45 PM") - -sdhour:depends("enable", "1") -sdhour.default = "0" - -return m - diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh b/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh deleted file mode 100644 index 842f648..0000000 --- a/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/croncat.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Croncat" "$@" -} - -> /tmp/crontmp -if [ -e /etc/crontabs/root ]; then - while read -r line; do - if [ -n "$line" ]; then - if [ ${line: -1} == ";" ]; then - echo "$line" >> /tmp/crontmp - fi - fi - done < /etc/crontabs/root -fi - -if [ -f /etc/cronuser ]; then - if [ -f /etc/cronbase ]; then - cat /etc/cronbase /etc/cronuser > /etc/crontabs/root - else - cp /etc/cronuser /etc/crontabs/root - fi -else - if [ -f /etc/cronbase ]; then - cp /etc/cronbase /etc/crontabs/root - else - > /etc/crontabs/root - fi -fi -cat /tmp/crontmp /etc/crontabs/root > /tmp/cronroot -cp /tmp/cronroot /etc/crontabs/root -rm /tmp/crontmp -rm /tmp/cronroot - -/etc/init.d/cron restart diff --git a/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh b/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh deleted file mode 100644 index eac8962..0000000 --- a/rooter/0basicapps/ext-extra/files/usr/lib/rooter/luci/reboot.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Schedule Reboot" "$@" -} - -PARM=$1 - -if [ $PARM = "0" ]; then - HO=$(uci get system.@system[-1].zonename) - if [ -z $HO ]; then - HO="UTC" - fi - uci set schedule.timezone.zonename="$HO" - uci commit schedule -fi - -if [ $PARM = "1" ]; then - sleep 5 - EN=$(uci get schedule.reboot.enable) - if [ $EN = "1" ]; then - SDHOUR=$(uci get schedule.reboot.sdhour) - HOUR=`expr $SDHOUR / 4` - let "TH = $HOUR * 4" - let "TMP1 = $SDHOUR - $TH" - let "MIN = $TMP1 * 15" - echo "$MIN $HOUR * * * sleep 70 && touch /etc/banner && reboot -f" > /etc/cronbase - else - rm -f /etc/cronbase - fi - /usr/lib/rooter/luci/croncat.sh -fi diff --git a/rooter/0basicapps/ext-p910nd/Makefile b/rooter/0basicapps/ext-p910nd/Makefile deleted file mode 100644 index 9f7dc57..0000000 --- a/rooter/0basicapps/ext-p910nd/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-p910nd -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-p910nd - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Applications - DEPENDS:=+p910nd +kmod-usb-printer +kmod-usb-ohci - TITLE:=Install Print Server - PKGARCH:=all -endef - -define Package/ext-p910nd/description - Helper scripts to install print Server -endef - - -define Build/Compile -endef - -define Package/ext-p910nd/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-p910nd)) diff --git a/rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx b/rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx deleted file mode 100644 index 80f6d62..0000000 --- a/rooter/0basicapps/ext-p910nd/files/etc/uci-defaults/40_luci-p910ndx +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@p910nd[-1] - add ucitrack p910nd - set ucitrack.@p910nd[-1].init=p910nd - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua b/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua deleted file mode 100644 index 2fc941f..0000000 --- a/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/controller/p910ndx.lua +++ /dev/null @@ -1,15 +0,0 @@ --- Copyright 2008 Yanira --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.p910ndx", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/p910nd") then - return - end - - local page - - page = entry({"admin", "services", "p910ndx"}, cbi("p910ndx"), _("Print Server"), 60) - page.dependent = true -end diff --git a/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua b/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua deleted file mode 100644 index 12c4a58..0000000 --- a/rooter/0basicapps/ext-p910nd/files/usr/lib/lua/luci/model/cbi/p910ndx.lua +++ /dev/null @@ -1,59 +0,0 @@ ---[[ - -LuCI p910nd -(c) 2008 Yanira -(c) 2012 Jo-Philipp Wich - -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 - -]]-- - -local uci = luci.model.uci.cursor_state() -local net = require "luci.model.network" -local m, s, p, b - -m = Map("p910nd", translate("Print Server"), - translatef("Support for USB Printers.")) - -net = net.init(m.uci) - -s = m:section(TypedSection, "p910nd", translate("Settings")) -s.addremove = true -s.anonymous = true - -s:option(Flag, "enabled", translate("enable")) - -s:option(Value, "device", translate("Device")).rmempty = true - -b = s:option(Value, "bind", translate("Interface"), translate("Specifies the interface to listen on.")) -b.template = "cbi/network_netlist" -b.nocreate = true -b.unspecified = true - -function b.cfgvalue(...) - local v = Value.cfgvalue(...) - if v then - return (net:get_status_by_address(v)) - end -end - -function b.write(self, section, value) - local n = net:get_network(value) - if n and n:ipaddr() then - Value.write(self, section, n:ipaddr()) - end -end - -p = s:option(ListValue, "port", translate("Port"), translate("TCP listener port.")) -p.rmempty = true -for i=0,9 do - p:value(i, 9100+i) -end - -s:option(Flag, "bidirectional", translate("Bidirectional mode")) - -return m diff --git a/rooter/0basicapps/usb-storage/Makefile b/rooter/0basicapps/usb-storage/Makefile deleted file mode 100644 index e2b95c2..0000000 --- a/rooter/0basicapps/usb-storage/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=usb-storage -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/usb-storage - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Applications - DEPENDS:= +ntfs-3g +fdisk +kmod-usb-storage \ - +kmod-fs-ext4 +kmod-fs-vfat +kmod-nls-cp437 +kmod-nls-iso8859-1 +kmod-nls-utf8 \ - +block-mount +kmod-fs-exfat +kmod-fs-hfs +hd-idle - TITLE:=Install USB Storage - PKGARCH:=all -endef - -define Package/usb-storage/description - Helper scripts to install USB Storage -endef - - -define Build/Compile -endef - -define Package/usb-storage/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,usb-storage)) diff --git a/rooter/0basicapps/usb-storage/files/etc/config/umount b/rooter/0basicapps/usb-storage/files/etc/config/umount deleted file mode 100644 index ca8f428..0000000 --- a/rooter/0basicapps/usb-storage/files/etc/config/umount +++ /dev/null @@ -1,2 +0,0 @@ -config umount 'umount' - option drive '' diff --git a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount deleted file mode 100644 index 961a219..0000000 --- a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/20-mount +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh /etc/rc.common -. /lib/functions.sh - -log() { - logger -t "20-mount" "$@" -} - -blkdev=`dirname $DEVPATH` -if [ `basename $blkdev` != "block" ]; then - device=`basename $DEVPATH` - if echo $device | grep -q "mtdblock"; then - exit 0 - fi - if [ -e /etc/sda_drop ]; then - source /etc/sda_drop - if echo $device | grep -q "$SDA"; then - exit 0 - fi - fi - if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then - /usr/lib/sdcard/sdcard.sh detect - source /tmp/detect.file - if [ $detect = "1" ]; then - if echo $device | grep -q "mmcblk"; then - exit 0 - fi - fi - fi - if echo $device | grep -q "mmcblk"; then - device1="SDCard"${device:8:2} - else - device1=$device - fi - - case "$ACTION" in - add) - mkdir -p /mnt/$device1 - # vfat & ntfs-3g check - if [ `which fdisk` ]; then - isntfs=`fdisk -l | grep $device | grep NTFS` - isvfat=`fdisk -l | grep $device | grep FAT` - isfuse=`lsmod | grep fuse` - isntfs3g=`which ntfs-3g` - else - isntfs="" - isvfat="" - fi - # mount with ntfs-3g if possible, else with default mount - if [ "$isntfs" -a "$isfuse" -a "$isntfs3g" ]; then - ntfs-3g -o nls=utf8 /dev/$device /mnt/$device1 - log "Mount /mnt/$device as NTFS" - elif [ "$isvfat" ]; then - mount -o rw,sync,umask=002,codepage=437,iocharset=iso8859-1 /dev/$device /mnt/$device1 - log "Mount /mnt/$device as FAT" - else - mount -o rw,sync /dev/$device /mnt/$device1 - log "Mount /mnt/$device as other" - fi - - chmod 777 /mnt/$device1 - chown nobody /mnt/$device1 - - if [ -e /usr/lib/sdcard/sdcard.sh ]; then - /usr/lib/sdcard/sdcard.sh add - fi - ;; - esac -fi \ No newline at end of file diff --git a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount deleted file mode 100644 index 7a1f933..0000000 --- a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/30-mount +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh /etc/rc.common -. /lib/functions.sh -# Copyright (C) 2011 OpenWrt.org - -log() { - logger -t "30-mount" "$@" -} - -sanitize() { - sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@" -} - -blkdev=`dirname $DEVPATH` -if [ `basename $blkdev` != "block" ]; then - device=`basename $DEVPATH` - if echo $device | grep -q "mtdblock"; then - exit 0 - fi - if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then - /usr/lib/sdcard/sdcard.sh detect - source /tmp/detect.file - if [ $detect = "1" ]; then - if echo $device | grep -q "mmcblk"; then - exit 0 - fi - fi - fi - if echo $device | grep -q "mmcblk"; then - device1="SDCard"${device:8:2} - else - device1=$device - fi - - if [ -e /etc/sda_drop ]; then - source /etc/sda_drop - if echo $device | grep -q "$SDA"; then - exit 0 - fi - fi - - case "$ACTION" in - add) - MT=$(cat /proc/mounts | grep "$device") - if [ -z $MT ]; then - exit 0 - fi - DEVN=${DEVNAME:0:3} - MODEL=$(sanitize "/sys/block/$DEVN/device/model") - if [ -d /etc/ksmbd ]; then - uci delete ksmbd.$device1 - uci set ksmbd.$device1=share - uci set ksmbd.$device1.name=$device1 - uci set ksmbd.$device1.path=/mnt/$device1 - uci set ksmbd.$device1.read_only=no - uci set ksmbd.$device1.guest_ok=yes - uci set ksmbd.$device1.create_mask='0666' - uci set ksmbd.$device1.dir_mask='0777' - uci commit ksmbd - /etc/init.d/ksmbd restart - log "/mnt/$device1 shared as $device1" - else - if [ -d /etc/samba ]; then - uci delete samba.$device1 - uci set samba.$device1=sambashare - uci set samba.$device1.name=$device1 - uci set samba.$device1.path=/mnt/$device1 - uci set samba.$device1.read_only=no - uci set samba.$device1.guest_ok=yes - uci commit samba - /etc/init.d/samba restart - log "/mnt/$device1 shared as $device1" - fi - fi - ;; - remove) - log "remove /mnt/$device1" - if [ -d /etc/ksmbd ]; then - uci delete ksmbd.$device1 - uci commit ksmbd - else - if [ -d /etc/samba ]; then - uci delete samba.$device1 - uci commit samba - fi - fi - ;; - esac -fi diff --git a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount b/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount deleted file mode 100644 index 5594607..0000000 --- a/rooter/0basicapps/usb-storage/files/etc/hotplug.d/block/99-mount +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh /etc/rc.common -. /lib/functions.sh - -log() { - logger -t "99-mount" "$@" -} - - -blkdev=`dirname $DEVPATH` -if [ `basename $blkdev` != "block" ]; then - device=`basename $DEVPATH` - if echo $device | grep -q "mtdblock"; then - exit 0 - fi - - if [ ! -e /usr/lib/sdcard/sdcard.sh ]; then - /usr/lib/sdcard/sdcard.sh detect - source /tmp/detect.file - if [ $detect = "1" ]; then - if echo $device | grep -q "mmcblk"; then - exit 0 - fi - fi - fi - if echo $device | grep -q "mmcblk"; then - device1="SDCard"${device:8:2} - else - device1=$device - fi - - case "$ACTION" in - remove) - log "remove /mnt/$device1" - umount -l /mnt/$device1 - rm -rf /mnt/$device1 - if [ -e /usr/lib/sdcard/sdcard.sh ]; then - /usr/lib/sdcard/sdcard.sh remove - fi - ;; - esac -fi \ No newline at end of file diff --git a/rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle b/rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle deleted file mode 100644 index 92f4356..0000000 --- a/rooter/0basicapps/usb-storage/files/etc/uci-defaults/40_luci-hd_idle +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@hd-idle[-1] - add ucitrack hd-idle - set ucitrack.@hd-idle[-1].init=hd-idle - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/rooter/0basicapps/usb-storage/files/etc/umount b/rooter/0basicapps/usb-storage/files/etc/umount deleted file mode 100644 index 8292a0f..0000000 --- a/rooter/0basicapps/usb-storage/files/etc/umount +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Umount" "$@" -} - -sleep 5 -DRV=$(uci get umount.umount.drive) -if [ -z $DRV ]; then - exit 0 -fi - -umount -l /mnt/$DRV - -rm -rf /mnt/$DRV - -uci set umount.umount.drive='' -uci commit umount diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua deleted file mode 100644 index 3e99da2..0000000 --- a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/hd_idle.lua +++ /dev/null @@ -1,15 +0,0 @@ --- Copyright 2008 Yanira --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.hd_idle", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/hd-idle") then - return - end - - local page - - page = entry({"admin", "services", "hd_idle"}, cbi("hd_idle"), _("Hard Drive Idle"), 60) - page.dependent = true -end diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua deleted file mode 100644 index dbc085c..0000000 --- a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/controller/umount.lua +++ /dev/null @@ -1,8 +0,0 @@ -module("luci.controller.umount", package.seeall) - -function index() - local page - - page = entry({"admin", "services", "umount"}, cbi("umount", {hidesavebtn=true, hideresetbtn=true}), "Safely Eject Drive", 25) - page.dependent = true -end diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua deleted file mode 100644 index 272e926..0000000 --- a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/hd_idle.lua +++ /dev/null @@ -1,29 +0,0 @@ --- Copyright 2008 Yanira --- Licensed to the public under the Apache License 2.0. - -require("nixio.fs") - -m = Map("hd-idle", "Hard Drive Idle", - translate("This is a utility program for spinning-down external " .. - "disks after a period of idle time.")) - -s = m:section(TypedSection, "hd-idle", translate("Settings")) -s.anonymous = true - -s:option(Flag, "enabled", translate("Enable")) - -disk = s:option(Value, "disk", translate("Disk")) -disk.rmempty = true -for dev in nixio.fs.glob("/dev/[sh]d[a-z]") do - disk:value(nixio.fs.basename(dev)) -end - -s:option(Value, "idle_time_interval", translate("Idle-time")).default = 10 -s.rmempty = true -unit = s:option(ListValue, "idle_time_unit", translate("Idle-time unit")) -unit.default = "minutes" -unit:value("minutes", translate("min")) -unit:value("hours", translate("h")) -unit.rmempty = true - -return m diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua b/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua deleted file mode 100644 index 334fe7f..0000000 --- a/rooter/0basicapps/usb-storage/files/usr/lib/lua/luci/model/cbi/umount.lua +++ /dev/null @@ -1,20 +0,0 @@ -require("nixio.fs") - -m = Map("umount", "Safely Eject a Drive", - translate("Safely eject a drive from the router")) - -m.on_after_save = function(self) - luci.sys.call("/etc/umount &") -end - -drv = m:section(TypedSection, "umount", translate("Currently Mounted Drives")) -drv.anonymous = true - -disk = drv:option(Value, "drive", translate(" "), translate("Click Save and Apply to eject drive")) -disk.rmempty = true -for dev in nixio.fs.glob("/mnt/[sh]d[a-z][1-9]") do - dv = nixio.fs.basename(dev) - disk:value(nixio.fs.basename(dev)) -end - -return m \ No newline at end of file diff --git a/rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh b/rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh deleted file mode 100644 index 257d915..0000000 --- a/rooter/0basicapps/usb-storage/files/usr/lib/sdcard/sdcard.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/bin/sh - -log() { - logger -t "sdcard" "$@" -} - -h721() { - if [ $1 = "add" ]; then - echo "17" > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio17/direction - echo 0 > /sys/class/gpio/gpio17/value - else - echo "17" > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio17/direction - echo 1 > /sys/class/gpio/gpio17/value -fi -} - -wg1608() { - if [ $1 = "add" ]; then - echo timer > /sys/class/leds/zbt-wg3526:green:signal/trigger - echo 1000 > /sys/class/leds/zbt-wg3526:green:signal/delay_on - echo 0 > /sys/class/leds/zbt-wg3526:green:signal/delay_off - else - echo timer > /sys/class/leds/zbt-wg3526:green:signal/trigger - echo 0 > /sys/class/leds/zbt-wg3526:green:signal/delay_on - echo 1000 > /sys/class/leds/zbt-wg3526:green:signal/delay_off - fi -} - -ws7915() { - if [ $1 = "add" ]; then - echo timer > /sys/class/leds/sys/trigger - echo 1000 > /sys/class/leds/sys/delay_on - echo 0 > /sys/class/leds/sys/delay_off - else - echo timer > /sys/class/leds/sys/trigger - echo 0 > /sys/class/leds/sys/delay_on - echo 1000 > /sys/class/leds/sys/delay_off - fi -} - -ws1688() { - if [ $1 = "add" ]; then - echo timer > /sys/class/leds/usb/trigger - echo 1000 > /sys/class/leds/usb/delay_on - echo 0 > /sys/class/leds/usb/delay_off - else - echo timer > /sys/class/leds/usb/trigger - echo 0 > /sys/class/leds/usb/delay_on - echo 1000 > /sys/class/leds/usb/delay_off - fi -} - -ACTION=$1 -model=$(cat /tmp/sysinfo/model) - -case $ACTION in - "add"|"remove" ) - mod=$(echo $model | grep "H721") - if [ $mod ]; then - h721 $ACTION - fi - mod=$(echo $model | grep "WG1608") - if [ $mod ]; then - wg1608 $ACTION - fi - mod=$(echo $model | grep "WS7915") - if [ $mod ]; then - ws7915 $ACTION - fi - - mod=$(echo $model | grep "WS1688") - if [ $mod ]; then - ws1688 $ACTION - fi - ;; - "detect" ) - mod=$(echo $model | grep "Raspberry") - if [ $mod ]; then - echo 'detect="'"1"'"' > /tmp/detect.file - else - echo 'detect="'"0"'"' > /tmp/detect.file - fi - ;; -esac - - diff --git a/rooter/0basicsupport/ext-buttons/Makefile b/rooter/0basicsupport/ext-buttons/Makefile deleted file mode 100644 index d4ae835..0000000 --- a/rooter/0basicsupport/ext-buttons/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-buttons -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-buttons - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Support - TITLE:=Install button support - PKGARCH:=all -endef - -define Package/ext-buttons/description - Helper scripts to install button support -endef - - -define Build/Compile -endef - -define Package/ext-buttons/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-buttons)) diff --git a/rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh b/rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh deleted file mode 100644 index 82a4e4e..0000000 --- a/rooter/0basicsupport/ext-buttons/files/etc/btnaction.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh - -FUNC=$1 - -reset_short() { - passwd -d root - reboot -f -} - -reset_long() { - mtd -r erase rootfs_data -} - -wifi() { - STATEFILE="/tmp/wifionoff.state" - - if [ $# -eq 1 ]; then - case $1 in - "up"|"on") - STATE=off - ;; - "down"|"off") - STATE=on - ;; - esac - else - if [ ! -e ${STATEFILE} ]; then - STATE=on - else - . ${STATEFILE} - fi - fi - if [ -z ${STATE} ]; then - STATE=on - fi - - if [ ${STATE} == "on" ]; then - /sbin/wifi down - STATE=off - else - /sbin/wifi up - STATE=on - fi - - echo "STATE=${STATE}" > ${STATEFILE} -} - -if [ $FUNC = "reset_short" ]; then - reset_short -fi -if [ $FUNC = "reset_long" ]; then - reset_long -fi -if [ $FUNC = "wifi" ]; then - wifi $2 -fi diff --git a/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button b/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button deleted file mode 100644 index 0efab99..0000000 --- a/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/00-button +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -do_button () { - local button - local action - local handler - local min - local max - - config_get button $1 button - config_get action $1 action - config_get handler $1 handler - config_get min $1 min - config_get max $1 max - - [ "$ACTION" = "$action" -a "$BUTTON" = "$button" -a -n "$handler" ] && { - [ -z "$min" -o -z "$max" ] && eval $handler - [ -n "$min" -a -n "$max" ] && { - [ $min -le $SEEN -a $max -ge $SEEN ] && eval $handler - } - } -} - -config_load system -config_foreach do_button button \ No newline at end of file diff --git a/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk b/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk deleted file mode 100644 index ea4f499..0000000 --- a/rooter/0basicsupport/ext-buttons/files/etc/hotplug.d/button/10-buttonchk +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Button Checker " "$@" -} - -log "Button Name : $BUTTON Action : $ACTION" - -log "$ACTION $SEEN" - diff --git a/rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons b/rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons deleted file mode 100644 index 1901e61..0000000 --- a/rooter/0basicsupport/ext-buttons/files/etc/init.d/buttons +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -log() { - logger -t "Buttons" "$@" -} - -START=98 - -start() { - local BTN=$(uci -q get system.@button[-1].button) -} - -stop() { - log "Stopping Buttons" -} diff --git a/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua b/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua deleted file mode 100644 index 70fa838..0000000 --- a/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/controller/buttons.lua +++ /dev/null @@ -1,14 +0,0 @@ -module("luci.controller.buttons", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - page = entry({"admin", "system", "buttons"}, cbi("buttons/buttons"), _(translate("Buttons")), 65) - page.dependent = true - end -end diff --git a/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua b/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua deleted file mode 100644 index 4f37569..0000000 --- a/rooter/0basicsupport/ext-buttons/files/usr/lib/lua/luci/model/cbi/buttons/buttons.lua +++ /dev/null @@ -1,44 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2008 Steven Barth - -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 - -$Id$ -]]-- - -m = Map("system", translate("Buttons"), - translate("This page allows the configuration of custom button actions")) - -s = m:section(TypedSection, "button", "") -s.anonymous = true -s.addremove = true - -s:option(Value, "button", translate("Name")) - -act = s:option(ListValue, "action", - translate("Action"), - translate("Specifies the button state to handle")) - -act:value("released") -act:value("pressed") -act.default = "released" - -s:option(Value, "handler", - translate("Handler"), - translate("Path to executable which handles the button event")) - -min = s:option(Value, "min", translate("Minimum hold time")) -min.rmempty = true -min:depends("action", "released") - -max = s:option(Value, "max", translate("Maximum hold time")) -max.rmempty = true -max:depends("action", "released") - -return m \ No newline at end of file diff --git a/rooter/0basicsupport/ext-sms/Makefile b/rooter/0basicsupport/ext-sms/Makefile deleted file mode 100644 index 3315be2..0000000 --- a/rooter/0basicsupport/ext-sms/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-sms -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-sms - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Support - TITLE:=Install SMS support - PKGARCH:=all -endef - -define Package/ext-sms/description - Helper scripts to install SMS on ROOter -endef - - -define Build/Compile -endef - -define Package/ext-sms/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-sms)) diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua deleted file mode 100644 index e17e2ee..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/controller/sms.lua +++ /dev/null @@ -1,162 +0,0 @@ -module("luci.controller.sms", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local fs = require "nixio.fs" - if not fs.stat("/etc/nosms") then - local page - page = entry({"admin", "modem", "sms"}, template("rooter/sms"), translate("短信功能"), 35) - page.dependent = true - - end - - - entry({"admin", "modem", "check_read"}, call("action_check_read")) - entry({"admin", "modem", "del_sms"}, call("action_del_sms")) - entry({"admin", "modem", "send_sms"}, call("action_send_sms")) - entry({"admin", "modem", "change_sms"}, call("action_change_sms")) - entry({"admin", "modem", "change_smsdn"}, call("action_change_smsdn")) - entry({"admin", "modem", "change_smsflag"}, call("action_change_smsflag")) - entry({"admin", "modem", "delall_sms"}, call("action_delall_sms")) -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function action_send_sms() - if package.path:find(";/usr/lib/sms/?.lua") == nil then - package.path = package.path .. ";/usr/lib/sms/?.lua" - end - smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") - local set = luci.http.formvalue("set") - local number = trim(string.sub(set, 1, 20)) - local txt = string.sub(set, 21) - local utf8togsm = require "utf8togsm" - utf8togsm.chktxt(txt) - local msg = utf8togsm["msg"] - local dcs = utf8togsm["dcs"] - txt = utf8togsm["txt"] - local rv = {} - local file = nil - local k = 1 - local status - local rfname = "/tmp/smssendstatus0000" - if msg == nil then - os.execute("if [ -e " .. rfname .. " ]; then rm " ..rfname .. "; fi") - os.execute("lua /usr/lib/sms/sendsms.lua " .. smsnum .. " " .. number .. " " .. dcs .. " " .. txt .. " 0000") - os.execute("sleep 3") - repeat - file = io.open(rfname, "r") - if file == nil then - os.execute("sleep 1") - end - k = k + 1 - until k > 25 or file ~=nil - if file == nil then - status = translate('Sending attempt timed out (fail)') - else - status = file:read("*line") - file:close() - os.remove (rfname) - end - else - status = msg - end - rv["status"] = status - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_delall_sms() - smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") - os.execute("/usr/lib/sms/delall.sh " .. smsnum) -end - -function action_del_sms() - local set = luci.http.formvalue("set") - if set ~= nil then - smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") - os.execute("/usr/lib/sms/delsms.sh " .. smsnum .. " " .. set) - os.execute("touch /tmp/smswakeup" .. smsnum) - end -end - -function action_check_read() - local rv ={} - local file - local line - smsnum = luci.model.uci.cursor():get("modem", "general", "smsnum") - conn = "Modem #" .. smsnum - rv["conntype"] = conn - support = luci.model.uci.cursor():get("modem", "modem" .. smsnum, "sms") - rv["ready"] = "0" - rv["menable"] = "0" - rv["mslots"] = "0" - if support == "1" then - rv["ready"] = "1" - result = "/tmp/smsresult" .. smsnum .. ".at" - file = io.open(result, "r") - if file ~= nil then - file:close() - file = io.open("/tmp/smstext" .. smsnum, "r") - if file == nil then - rv["ready"] = "3" - else - rv["menable"] = luci.model.uci.cursor():get("modem", "sms", "menable") - rv["mslots"] = luci.model.uci.cursor():get("modem", "sms", "slots") - rv["ready"] = "2" - local tmp = file:read("*line") - rv["used"] = tmp - tmp = file:read("*line") - rv["max"] = tmp - full = nil - - repeat - for j = 1, 4 do - line = file:read("*line") - if line ~= nil then - if j == 3 then - full = full .. string.char(29) - local i = tonumber(line) - for k = 1, i do - line = file:read("*line") - full = full .. line - if k < i then - full = full .. '\n' - end - end - else - if full == nil then - full = line - else - full = full .. string.char(29) .. line - end - end - end - end - until line == nil - file:close() - rv["line"] = full - end - end - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_change_sms() - os.execute("/usr/lib/rooter/luci/modemchge.sh sms 1") -end - -function action_change_smsdn() - os.execute("/usr/lib/rooter/luci/modemchge.sh sms 0") -end - -function action_change_smsflag() - local set = tonumber(luci.http.formvalue("set")) - os.execute("/usr/lib/sms/toggle.sh " .. set) -end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm b/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm deleted file mode 100644 index 6b4c787..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/lua/luci/view/rooter/sms.htm +++ /dev/null @@ -1,556 +0,0 @@ -<%+header%> - - - - -
      -
      -

      <%:短信收发页面%>

      -
      <%:通过模块发送和接收文本消息%>
      -
      - <%:通信模块信息%> - - - - - - - -
        - - - -
        - <%:收到的短信%> - - - - - - - - - - - - -
        <%:SIM可存放的短信空间 (条)%>
        <%:已使用的SIM短信空间 (条)%>
         
             
            - - - - - - - - - - - - - - - - -
             
            <%:启用模块到SIM卡的短信传输%>
            - -
            <%:模块上的未读信息数量%>
             
               
               
              - - - - - - - -
                
              - - - - - - - - - - - -
              <%:已读状态%>
              <%:发件人%>
              <%:Date%>
              <%:时间%>
              <%:短信%>
              - - - - - -
              - -
              - - - - - - - - -
              <%:短信内容 :%>
              - -  
              - - - - - - - - -
               
              - - <%:短信会话%> - - - - - - - -
              <%:收件人 :%>
               
              - - - - - -
              - -
              - - - - - - - -
                
              - - - - - - - -
              <%:短信发送状态 :%>
                 
                - -
                - -
                -
                -<%+footer%> diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delall.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delall.sh deleted file mode 100644 index aa0c50b..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delall.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Delete SMS" "$@" -} - -CURRMODEM=$1 -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc) - -LOCKDIR="/tmp/smslock$CURRMODEM" -PIDFILE="${LOCKDIR}/PID" - -while [ 1 -lt 6 ]; do - if mkdir "${LOCKDIR}" &>/dev/null; then - echo "$$" > "${PIDFILE}" - ATCMDD="AT+CPMS=\"$SMSLOC\";+CMGD=1,4" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log "$OX" - uci set modem.modem$CURRMODEM.smsnum=999 - uci commit modem - break - else - OTHERPID="$(cat "${PIDFILE}")" - if [ $? = 0 ]; then - if ! kill -0 $OTHERPID &>/dev/null; then - rm -rf "${LOCKDIR}" - fi - fi - sleep 1 - fi -done -rm -rf "${LOCKDIR}" \ No newline at end of file diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh deleted file mode 100644 index a8ccfc8..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/delsms.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Delete SMS" "$@" -} - -CURRMODEM=$1 -shift 1 -SLOTS="$@" -log "$SLOTS" - -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc) - -LOCKDIR="/tmp/smslock$CURRMODEM" -PIDFILE="${LOCKDIR}/PID" - -while [ true ]; do - if mkdir "${LOCKDIR}" &>/dev/null; then - echo "$$" > "${PIDFILE}" - for SLOT in $SLOTS - do - ATCMDD="AT+CPMS=\"$SMSLOC\";+CMGD=$SLOT" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log "$OX" - done - uci set modem.modem$CURRMODEM.smsnum=999 - uci commit modem - break - else - OTHERPID="$(cat "${PIDFILE}")" - if [ $? = 0 ]; then - if ! kill -0 $OTHERPID &>/dev/null; then - rm -rf "${LOCKDIR}" - fi - fi - sleep 1 - fi -done -rm -rf "${LOCKDIR}" diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/merge.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/merge.lua deleted file mode 100644 index 4a7442c..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/merge.lua +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/lua - -function ltrim(s) - return s:match'^%s*(.*)' -end - -file=arg[1] -filet=arg[1] - -overall = {} - -cntr = 1 -filein = io.open(file, "r") -maxslot = -1 -repeat - message = {} - local line = filein:read("*line") - if line == nil then - break - end - if cntr < 2 then - maxused = line - line = filein:read("*line") - maxslots = line - cntr=2 - else - message['slot'] = line - message['phone'] = filein:read("*line") - nline = filein:read("*line") - message['nline'] = nline - ncntr = 1 - msg="" - message['msgnum'] = "xxx" - message['msgord'] = "xxx" - message['msgmax'] = "xxx" - lines = filein:read("*line") - s, e = lines:find("Msg# ") - if s ~= nil then - bs, be = lines:find(",", e+1) - msgnum = lines:sub(e+1, be-1) - message['msgnum'] = msgnum - s, e = lines:find("/", be+1) - msgord = lines:sub(be+1, e-1) - message['msgord'] = msgord - message['msgmax'] = lines:sub(e+1) - lines = filein:read("*line") - end - msg = lines - nc = tonumber(nline) - if nc > 2 then - for i=1,nc-2,1 - do - lines = filein:read("*line") - if lines ~= "" then - msg = msg .. "\n" .. lines - else - if i == nc-2 then - if msgord == message['msgmax'] then - msg = msg .. "\n\n" - else - msg = msg .. "\n\n" - end - else - msg = msg .. "\n" - - end - end - end - --print(nln, msg) - --msg = msg .. "\n" - end - message['msg'] = msg - message['numlines'] = nc - 1 - sht = filein:read("*line") - s, e = sht:find("Msg#") - if s ~= nil then - shtt = sht:sub(1, s-1) - bs, be = sht:find("/", e) - sht = shtt .. sht:sub(be+2) - end - message['short'] = sht - overall[message['slot']] = message - if maxslot < tonumber(message['slot']) then - maxslot = tonumber(message['slot']) - end - end -until 1==0 -filein:close() - -fileout = io.open(filet, "w") -fileout:write(maxused, "\n") -fileout:write(maxslots, "\n") - -for i=0,maxslot,1 -do - msgbuild = {} - shortmsg = {} - if overall[tostring(i)] ~= nil then - --print(i, overall[tostring(i)]['msgnum']) - if overall[tostring(i)]['msgnum'] == "xxx" then - fileout:write(overall[tostring(i)]['slot'], "\n") - fileout:write(overall[tostring(i)]['phone'], "\n") - fileout:write(overall[tostring(i)]['nline'], "\n") - fileout:write(overall[tostring(i)]['msg'], "\n") - fileout:write(overall[tostring(i)]['short'], "\n") - else - msgnum = overall[tostring(i)]['msgnum'] - msgtmp = overall[tostring(i)]['slot'] - msgord = overall[tostring(i)]['msgord'] - msgmax = tonumber(overall[tostring(i)]['msgmax']) - msg = overall[tostring(i)]['msg'] - numlines = overall[tostring(i)]['numlines'] - --print(numlines) - msgbuild[overall[tostring(i)]['msgord']] = overall[tostring(i)]['msg'] - shortmsg[overall[tostring(i)]['msgord']] = overall[tostring(i)]['short'] - for j=i+1,maxslot,1 - do - if overall[tostring(j)] ~= nil then - if overall[tostring(j)]['msgnum'] == msgnum then - numlines = numlines + (overall[tostring(j)]['numlines']) - --print(overall[tostring(j)]['numlines']) - msgtmp = msgtmp .. " " .. overall[tostring(j)]['slot'] - msgbuild[overall[tostring(j)]['msgord']] = overall[tostring(j)]['msg'] - shortmsg[overall[tostring(j)]['msgord']] = overall[tostring(j)]['short'] - overall[tostring(j)] = nil - end - end - end - msg="" - mflg = 0 - short = nil - for j=1,msgmax,1 - do - if msgbuild[tostring(j)] ~= nil then - msg = msg .. msgbuild[tostring(j)] - if short == nil then - short = shortmsg[tostring(j)] - end - else - mflg = 1 - end - end - fileout:write(msgtmp, "\n") - fileout:write(overall[tostring(i)]['phone'], "\n") - - if mflg ~= 0 then - msg = "Partial Message : " .. msg - t = short:gsub("%s+", " ") - short = "Partial Message " .. t - end - endc = string.sub(msg, -2) - if endc == "\n\n" then - mlen = msg:len() - 2 - msg = string.sub(msg,1,mlen) - end - local _,n = msg:gsub("\n","") - fileout:write(tostring(n+1), "\n") - fileout:write(msg, "\n") - fileout:write(short, "\n") - end - end -end -fileout:close() - - diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua deleted file mode 100644 index bbd5661..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/pack7bit.lua +++ /dev/null @@ -1,79 +0,0 @@ -local pack7bit = {} - -function hasbit(x, p) - return x % (p + p) >= p -end - -function bitand(x, y) - local p = 1; local z = 0; local limit = x > y and x or y - while p <= limit do - if hasbit(x, p) and hasbit(y, p) then - z = z + p - end - p = p + p - end - return z -end - -function bitor(x, y) - local p = 1; local z = 0; local limit = x > y and x or y - while p <= limit do - if hasbit(x, p) or hasbit(y, p) then - z = z + p - end - p = p + p - end - return z -end - -function bitright(x, y) - return math.floor(x / 2 ^ y) -end - -function bitleft(x, y) - return x * 2 ^ y -end - -function pack7bit.pack(udl, txt) - maxb = math.ceil((tonumber(udl, 16) / 8) * 7) - udtab = {} - ii = 1 - jj = 1 - kk = 0 - repeat - ch = tonumber(txt:sub(jj, jj + 1), 16) - if ii == 1 then - udtab[kk + 1] = ch - elseif ii == 2 then - udtab[kk] = bitor(bitleft(bitand(ch, 1), 7), udtab[kk]) - udtab[kk + 1] = bitright(bitand(ch, 126), 1) - elseif ii == 3 then - udtab[kk] = bitor(bitleft(bitand(ch, 3), 6), udtab[kk]) - udtab[kk + 1] = bitright(bitand(ch, 124), 2) - elseif ii == 4 then - udtab[kk] = bitor(bitleft(bitand(ch, 7), 5), udtab[kk]) - udtab[kk + 1] = bitright(bitand(ch, 120), 3) - elseif ii == 5 then - udtab[kk] = bitor(bitleft((bitand(ch, 15)), 4), udtab[kk]) - udtab[kk + 1] = bitright(bitand(ch, 112), 4) - elseif ii == 6 then - udtab[kk] = bitor(bitleft(bitand(ch, 31), 3), udtab[kk]) - udtab[kk + 1] = bitright(bitand(ch, 96), 5) - elseif ii == 7 then - udtab[kk] = bitor(bitleft(bitand(ch, 63), 2), udtab[kk]) - udtab[kk + 1] = bitright(bitand(ch, 64), 6) - else - udtab[kk] = bitor(bitleft(ch, 1), udtab[kk]) - ii = 0 - kk = kk - 1 - end - ii = ii + 1 - jj = jj + 2 - kk = kk + 1 - until jj > #txt - for jj = 1, maxb do - udtab[jj] = string.format("%02X", udtab[jj]) - end - pack7bit["pdu"] = table.concat(udtab) -end -return pack7bit diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms deleted file mode 100644 index 8826bb2..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/processsms +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "sms process" "$@" -} - -CURRMODEM=$1 - -log "SMS Supported Modem$CURRMODEM" - -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -LOCKDIR="/tmp/smslock$CURRMODEM" -PIDFILE="${LOCKDIR}/PID" -rm -rf "${LOCKDIR}" - -idV=$(uci -q get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) -MODEMID="$idV${idP:0:3}" - -ATCMDD="AT+CMGF=0" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -sleep 1 -ATCMDD="AT+CPMS=\"SM\",\"SM\",\"SM\"" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -MAXED=$(echo "$OX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}") -if [ "$MAXED" == "0" -a "$MODEMID" != "119968a" ]; then - ATCMDD="AT+CPMS=\"ME\",\"ME\",\"ME\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - uci set modem.modem$CURRMODEM.smsloc="ME" - SMSLOC="ME" - MEM3="ME" -else - uci set modem.modem$CURRMODEM.smsloc="SM" - SMSLOC="SM" - MEM3="SM" -fi -sleep 1 -uci set modem.modem$CURRMODEM.smsnum=999 -uci commit modem -ATCMDD="AT+CPMS=\"ME\"" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -MESC=$(echo "$OX" | grep -o "+CPMS:.*" | awk -F, '{print $1}' | grep -o "[0-9]\{1,3\}") -METC=$(echo "$OX" | grep -o "+CPMS:.*" | awk -F, '{print $2}' | grep -o "[0-9]\{1,3\}") -MESLOT="0" -MESCc="" -if [ "x$MESC" = "x" ]; then - MESC="0" -fi -if [ "x$METC" = "x" ]; then - METC="0" - MESC="0" - SMSLOC="SM" -fi -uci set modem.sms.slots=$MESC -uci commit modem -sleep 1 - -rm -f /tmp/smsresult$CURRMODEM".at" -> /tmp/smsslots$CURRMODEM -HH=$(date +%H) - -while true; do - SLEEP="20" - while true; do - if mkdir "${LOCKDIR}" &>/dev/null; then - echo "$$" > "${PIDFILE}" - if [ "$METC" != "0" ]; then - ATCMDD="AT+CPMS=\"ME\",\"$SMSLOC\",\"$MEM3\"" - SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - USED=$(echo "$SX" | cut -d, -f1 | grep -o "[0-9]\{1,3\}") - MESCc="$USED" - MAXED=$(echo "$SX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}") - fi - if [ $SMSLOC == "SM" ]; then - ATCMDD="AT+CPMS=\"SM\",\"$SMSLOC\",\"$MEM3\"" - SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - USED=$(echo "$SX" | cut -d, -f1 | grep -o "[0-9]\{1,3\}") - MAXED=$(echo "$SX" | cut -d, -f2 | grep -o "[0-9]\{1,3\}") - if [ -n "$MESCc" -a "$MESCc" != "$MESC" ]; then - MESC=$MESCc - uci set modem.sms.slots=$MESC - uci commit modem - fi - if [ $USED == $MAXED -a $MEM3 == "SM" ]; then - ATCMDD="AT+CPMS=\"SM\",\"SM\",\"ME\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - MEM3="ME" - else - if [ $USED != $MAXED -a $MEM3 == "ME" ]; then - ATCMDD="AT+CPMS=\"SM\",\"SM\",\"SM\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - MEM3="SM" - fi - fi - fi - if [ $MAXED -eq 0 ]; then - SLEEP="900" - fi - if [ $USED -eq $(uci get modem.modem$CURRMODEM.smsnum) ] && [ $HH -eq $(date +%H) ]; then - if [ $MEM3 == "SM" -a $USED -lt $MAXED -a $MESC -gt 0 -a $(uci -q get modem.sms.menable) == 1 ]; then - ATCMDD="AT+CPMS=\"ME\";+CMGR=$MESLOT;+CPMS=\"SM\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - Rstat=$(echo "$OX" | grep -o "+CMGR:[^,]\+" | grep -o "[0-3]") - PDU=$(echo "$OX" | grep -o "[0-9A-F]\{30,\}") - PDUL=$(echo "$OX" | grep -o "+CMGR:.*" | grep -o ",[0-9]\{1,\}" | grep -o "[0-9]\{1,3\}") - if [ -n "$PDU" -a -n "$PDUL" -a -n "$Rstat" ]; then - if [ ${#PDUL} -eq 2 ]; then - PDUL="0$PDUL" - fi - ATCMDD="$PDUL,SM,$Rstat,$PDU" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "smswrite.gcom" "$CURRMODEM" "$ATCMDD") - MREF=$(echo "$OX" | grep -o "[0-9]\{1,3\}") - if [ ${#MREF} -gt 0 ]; then - echo "$MREF" >> /tmp/smsslots$CURRMODEM - ATCMDD="AT+CPMS=\"ME\";+CMGD=$MESLOT;+CPMS=\"SM\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - MESC=$(($MESC - 1)) - uci set modem.sms.slots=$MESC - uci commit modem - SLEEP="5" - fi - MESLOT=$(($MESLOT + 1)) - if [ $MESLOT -gt $METC -o $MESC == "0" ]; then - MESLOT="0" - fi - fi - else - log "Reread SMS Messages on Modem $CURRMODEM" - echo "$SX" > /tmp/smstemp$CURRMODEM - ATCMDD="AT+CMGL=4" - SX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - SX=$(echo "$SX" | sed -e "s/+CMGL:/+CMGL: /g") - echo "$SX" >> /tmp/smstemp$CURRMODEM - uci set modem.modem$CURRMODEM.smsnum=$USED - uci commit modem - mv /tmp/smstemp$CURRMODEM /tmp/smsresult$CURRMODEM.at - lua /usr/lib/sms/smsread.lua $CURRMODEM - HH=$(date +%H) - SLEEP="5" - fi - break - else - OTHERPID="$(cat "${PIDFILE}")" - if [ $? = 0 ]; then - if ! kill -0 $OTHERPID &>/dev/null; then - rm -rf "${LOCKDIR}" - fi - fi - sleep 1 - fi - done - rm -rf "${LOCKDIR}" - n=1 - until [ $n -ge $SLEEP ] - do - sleep 1 - if [ -e /tmp/smswakeup$CURRMODEM ]; then - rm /tmp/smswakeup$CURRMODEM - n=$(( $n + $SLEEP )) - else - n=$(( $n + 1 )) - fi - done -done diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua deleted file mode 100644 index baee895..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.lua +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/lua - -modem = arg[1] -addr = arg[2] -dcs = arg[3] -txt = arg[4] -suffix = arg[5] - -if package.path:find(";/usr/lib/sms/?.lua") == nil then - package.path = package.path .. ";/usr/lib/sms/?.lua" -end - -local pack7bit = require "pack7bit" - -udl = string.format("%02X", math.floor(#txt / 2)) -da = "81" -if addr:sub(1, 1) == "+" then - da = "91" - addr = addr:sub(2) -elseif addr:sub(1, 1) == "-" then - addr = addr:sub(2) -end -da = string.format("%02X", #addr) .. da -if (#addr % 2) > 0 then - addr = addr .. "F" -end -k = #addr -j = 1 -repeat - da = da .. addr:sub(j + 1, j + 1) .. addr:sub(j, j) - j = j + 2 -until j > k -if dcs == "00" then - pack7bit.pack(udl, txt) - ud = pack7bit["pdu"] -else - ud = txt -end -pdu = "001100" .. da .. "00" .. dcs .. "AD" .. udl .. ud -pdul = string.format("%03d", (math.floor(#pdu / 2) - 1)) -os.execute("/usr/lib/sms/sendsms.sh " .. modem .. " " .. pdul .. "," .. suffix .. "," .. pdu .. " &") diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh deleted file mode 100644 index fad0e9c..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sendsms.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -CURRMODEM=$1 -ATCMDD=$2 - -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "sendsms-at.gcom" "$CURRMODEM" "$ATCMDD") diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua deleted file mode 100644 index 3237ca5..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.lua +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/lua - -local modem = arg[1] -local dest = arg[2] -local txt = arg[3] -local pid = arg[4] -local rfname = "/tmp/smssendstatus" .. pid - -if package.path:find(";/usr/lib/sms/?.lua") == nil then - package.path = package.path .. ";/usr/lib/sms/?.lua" -end - -local utf8togsm = require "utf8togsm" -utf8togsm.chktxt(txt) -local msg = utf8togsm["msg"] -local dcs = utf8togsm["dcs"] -txt = utf8togsm["txt"] - -if msg == nil then - os.execute("if [ -e " .. rfname .. " ]; then rm " ..rfname .. "; fi") - os.execute("lua /usr/lib/sms/sendsms.lua " .. modem .. " " .. dest .. " " .. dcs .. " " .. txt .. " " .. pid) -else - os.execute('echo "SMS sending failed - text is too long" > ' .. rfname) -end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh deleted file mode 100644 index 2c28887..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsout.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "sms process" "$@" -} - -CURRMODEM=$(uci get modem.general.smsnum) - -DEST="$1" -shift 1 -TXT="$@" -MYPID=$(printf "%05d" $$) -MYPID=$(printf "${MYPID:1:4}") -RESFILE="/tmp/smssendstatus"$MYPID - -lua /usr/lib/sms/smsout.lua $CURRMODEM $DEST "$TXT" $MYPID -sleep 5 -COUNT=0 -XSTATUS=1 -RES="SMS sending failed, timeout reading result" -while [ $COUNT -lt 15 ]; do - if [ -e $RESFILE ]; then - read RES < $RESFILE - if [ "${RES:0:9}" = "SMS sent," ]; then - XSTATUS=0 - fi - COUNT=999 - rm $RESFILE - else - sleep 2 - fi - COUNT=$(($COUNT + 1)) -done -log "$RES" -echo "$RES" -exit $XSTATUS diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua deleted file mode 100644 index 65903a4..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/smsread.lua +++ /dev/null @@ -1,863 +0,0 @@ -#!/usr/bin/lua - -senders2delete = {} -deletebinaries = false - -modemn = arg[1] - -local smsresult = "/tmp/smsresult" .. modemn .. ".at" -local smsslots = "/tmp/smsslots" .. modemn -local smstime = "/tmp/smstime" .. modemn -local t = {} -local tptr -local m_pdu_ptr -local m_pdu -local m_smsc -local m_with_udh -local m_report -local m_number -local m_replace -local m_alphabet -local m_dcs -local m_flash -local m_date -local m_time -local m_text -local m_concat -local m_read -local m_index -local g_table1 = {} -local g_table2 = {} - -local max_smsc = 64 -local max_number = 64 -local max_udh_data = 512 -surrogate = 0 - -function reset() - m_smsc = nil - m_with_udh = 0 - m_report = 0 - m_number = nil - m_replace = 0 - m_alphabet = -1 - m_flash = 0 - m_date = nil - m_time = nil - m_text = nil - m_concat = nil -end - -function hasbit(x, p) - return x % (p + p) >= p -end - -function bitor(x, y) - local p = 1; local z = 0; local limit = x > y and x or y - while p <= limit do - if hasbit(x, p) or hasbit(y, p) then - z = z + p - end - p = p + p - end - return z -end - -function bitand(x, y) - local p = 1; local z = 0; local limit = x > y and x or y - while p <= limit do - if hasbit(x, p) and hasbit(y, p) then - z = z + p - end - p = p + p - end - return z -end - -function bitright(x, y) - return math.floor(x / 2 ^ y) -end - -function bitleft(x, y) - return x * 2 ^ y -end - -function ocount(x, y) - local j = 0 - local i = x:find(y, 0) - while i ~= nil do - i = x:find(y, i + 1) - j = j + 1 - end - return j -end - -printf = function(s,...) - if echo == 0 then - io.write(s:format(...)) - else - ss = s:format(...) - os.execute("/usr/lib/rooter/logprint.sh " .. ss) - end -end - -function isxdigit(digit) - if digit == nil then - return 0 - end - if digit >= 48 and digit <= 57 then - return 1 - end - if digit >= 97 and digit <= 102 then - return 1 - end - if digit >= 65 and digit <= 70 then - return 1 - end - return 0 -end - -function isdigit(digit) - if digit >= 48 and digit <= 57 then - return 1 - end - return 0 -end - -function octet2bin(octet) - result = 0 - if octet:byte(1) > 57 then - result = result + octet:byte(1) - 55 - else - result = result + octet:byte(1) - 48 - end - result = result * 16 - if octet:byte(2) > 57 then - result = result + octet:byte(2) - 55 - else - result = result + octet:byte(2) - 48 - end - return result -end - -function octet2bin_check(octet) - if octet:byte(1) == 0 then - return -1 - end - if octet:byte(2) == 0 then - return -2 - end - if isxdigit(octet:byte(1)) == 0 then - return -3 - end - if isxdigit(octet:byte(2)) == 0 then - return -4 - end - return octet2bin(octet) -end - -function swapchars(sstring) - local length = sstring:len() - local xstring = nil - local i = 1 - while i < length do - c1 = sstring:sub(i, i) - c2 = sstring:sub(i+1, i+1) - if xstring == nil then - xstring = c2 .. c1 - else - xstring = xstring .. c2 .. c1 - end - i = i + 2 - end - return xstring -end - -function parseSMSC() - m_pdu_ptr = m_pdu - local length = octet2bin_check(m_pdu_ptr) - if length < 0 then - return -1 - end - if length == 0 then - m_smsc = "" - m_pdu_ptr = m_pdu_ptr:sub(3) - return 1 - end - if length < 2 or length > max_smsc then - return -1 - end - length = (length * 2) - 2 - local mlen = m_pdu:len() - if mlen < (length + 4) then - return -1 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - local addr_type = octet2bin_check(m_pdu_ptr) - if addr_type < 0 then - return -1 - end - if addr_type < 0x80 then - return -1 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - m_smsc = m_pdu_ptr:sub(0, length) - m_smsc = swapchars(m_smsc) - if addr_type < 0x90 then - for j=1, length do - if isxdigit(m_smsc:byte(j)) == 0 then - return -1 - end - end - else - if m_smsc:byte(length) == 70 then - m_smsc = m_smsc:sub(1, length-1) - end - local leng = m_smsc:len() - for j=1,leng do - if isdigit(m_smsc:byte(j)) == 0 then - return -1 - end - end - end - m_pdu_ptr = m_pdu_ptr:sub(length + 1) - return 1 -end - -function explainAddressType(octet_char, octet_int) - local result - if octet_char ~= nil then - result = octet2bin_check(octet_char) - else - result = octet_int - end - return result -end - -function concatinfo(x) - while #x > 9 do - if x:sub(1, 4) == '0003' then - if x:sub(7, 10) ~= '0101' then - m_concat = 'Msg# ' .. tonumber(x:sub(5, 6), 16) - m_concat = m_concat .. ',' .. tonumber(x:sub(9, 10), 16) - m_concat = m_concat .. '/' .. tonumber(x:sub(7, 8), 16) - end - x = "" - elseif x:sub(1, 4) == '0804' then - if x:sub(9, 12) ~= '0101' then - m_concat = 'Msg# ' .. tonumber(x:sub(5, 8), 16) - m_concat = m_concat .. ',' .. tonumber(x:sub(11, 12), 16) - m_concat = m_concat .. '/' .. tonumber(x:sub(9, 10), 16) - end - x = "" - else - local iel = tonumber(x:sub(3, 4), 16) - x = x:sub(5 + iel * 2) - end - end -end - -function pdu2binary(pdu, with_udh) - local skip_octets = 0 - local octetcounter - m_text = '' - local octets = octet2bin_check(pdu) - local last_i = 0 - if octets < 0 then - return -1 - end - if with_udh > 0 then - local pdu2 = pdu:sub(3) - local udhl = tonumber(pdu2:sub(1, 2), 16) - concatinfo(pdu2:sub(3, (udhl + 1) * 2)) - local udhsize = octet2bin_check(pdu2) - if udhsize < 0 then - return -1 - end - skip_octets = udhsize + 1 - end - for octetcounter = 0, (octets - skip_octets - 1) do - local pdu2 = pdu:sub((octetcounter * 2) + 3 + (skip_octets * 2)) - local i = octet2bin_check(pdu2) - if i < 0 then - return -1 - end - if m_alphabet == 2 then - if (2 + octetcounter) % 2 == 0 then - last_i = i - else - m_text = word2utf8(bitor(bitleft(last_i, 8), i), m_text) - end - else - if i < 32 or i > 127 then - i = 0x25A1 - end - m_text = word2utf8(i, m_text) - end - end - return (octets - skip_octets) -end - -function pdu2text(pdu, with_udh) - local result - local octetcounter - local skip_characters = 0 - local binary = 0 - m_text = '' - local septets = octet2bin_check(pdu) - if septets < 0 then - return -1 - end - if with_udh > 0 then - local pdu2 = pdu:sub(3) - local udhl = tonumber(pdu2:sub(1, 2), 16) - concatinfo(pdu2:sub(3, (udhl + 1) * 2)) - local udhsize = octet2bin_check(pdu2) - skip_characters = math.floor((((udhsize+1)*8)+6)/7) - end - local octets = math.floor((septets * 7 + 7) / 8) - local bitposition = 0 - local byteposition - local byteoffset - local i - local g_table_nbr = 1 - octetcounter = 0 - for charcounter=0,septets-1 do - local c = 0 - for bitcounter=0,6 do - byteposition = math.floor(bitposition / 8) - byteoffset = bitposition % 8 - while (byteposition >= octetcounter) and (octetcounter < octets) do - local pdu2 = pdu:sub((octetcounter * 2) + 3) - i = octet2bin_check(pdu2) - if i < 0 then - return -2 - end - binary = i - octetcounter = octetcounter + 1 - end - if bitand(binary, (2^byteoffset)) > 0 then - c = bitor(c, 128) - end - bitposition = bitposition + 1 - c = bitand(math.floor(c / 2), 127) - end - c = gsm2byte(c) - if charcounter >= skip_characters and c ~= 27 then - m_text = word2utf8(c, m_text) - end - end - return 1 -end - -function gsm2byte(ch) - if g_table_nbr == 2 then - if g_table2[ch] == nil then - ch = 63 - else - ch = g_table2[ch] - end - g_table_nbr = 1 - else - if ch == 27 then - g_table_nbr = 2 - else - if g_table1[ch] ~= nil then - ch = g_table1[ch] - end - end - end - return ch -end - -function word2utf8(i, txt) - if surrogate > 0 then - if i >= 0xDC00 and i <= 0xDFFF then - local ii = 0x10000 + bitand(i, 0x3FF) + bitleft(bitand(surrogate, 0x3FF), 10) - txt = txt .. string.char(bitor(0xF0, bitright(bitand(ii, 0x1C0000), 18))) - txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0x3F000), 12))) - txt = txt .. string.char(bitor(0x80, bitright(bitand(ii, 0xFC0), 6))) - txt = txt .. string.char(bitor(0x80, bitand(ii, 0x3F))) - else - txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1) - end - surrogate = 0 - elseif i >= 0xD800 and i <= 0xDBFF then - surrogate = i - elseif i >= 0xDC00 and i <= 0xDFFF then - txt = txt .. string.char(0xe2) .. string.char(0x96) .. string.char(0xa1) - elseif i < 0x80 then - txt = txt .. string.char(i) - elseif i < 0x800 then - txt = txt .. string.char(bitor(0xC0, bitright(bitand(i, 0x7C0), 6))) - txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F))) - else - if i == 0x2029 then - txt = txt .. string.char(10) - else - txt = txt .. string.char(bitor(0xE0, bitright(bitand(i, 0xF000), 12))) - txt = txt .. string.char(bitor(0x80, bitright(bitand(i, 0xFC0), 6))) - txt = txt .. string.char(bitor(0x80, bitand(i, 0x3F))) - end - end - return txt -end - -function parseDeliver() - if m_pdu_ptr:len() < 4 then - return 0 - end - local padding = 0 - local length = octet2bin_check(m_pdu_ptr) - local timezone - if length < 0 or length > max_number then - return 0 - end --- Sender Address - if length == 0 then - m_pdu_ptr = m_pdu_ptr:sub(5) - else - padding = length % 2 - m_pdu_ptr = m_pdu_ptr:sub(3) - local addr_type = explainAddressType(m_pdu_ptr, 0) - if addr_type < 0 then - return 0 - end - if addr_type < 0x80 then - return 0 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - if bitand(addr_type, 112) == 80 then - if m_pdu_ptr:len() < (length + padding) then - return 0 - end - local htmp = string.format("%x", math.floor((length * 4) / 7)) - if htmp:len() < 2 then - htmp = "0" .. htmp - end - htmp = htmp:upper() - local tpdu = htmp .. m_pdu_ptr - local res = pdu2text(tpdu, 0) - if res < 0 then - return 0 - end - m_number = string.gsub(m_text, "\n", " ") - m_text = nil - else - m_number = m_pdu_ptr:sub(1, length + padding + 1) - m_number = swapchars(m_number) - if m_number:byte(length + padding) == 70 then - m_number = m_number:sub(1, length + padding - 1) - end - if addr_type == 145 then - m_number = "+" .. m_number - end - end - end - m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1) - if m_pdu_ptr:len() < 20 then - return 0 - end --- PID - local byte_buf = octet2bin_check(m_pdu_ptr) - if byte_buf < 0 then - return 0 - end - if bitand(byte_buf, 0xF8) == 0x40 then - m_replace = bitand(byte_buf, 0x07) - end - m_pdu_ptr = m_pdu_ptr:sub(3) --- Alphabet - byte_buf = octet2bin_check(m_pdu_ptr) - if byte_buf < 0 then - return 0 - end - m_alphabet = math.floor(bitand(byte_buf, 0x0C) / 4) - if m_alphabet == 3 then - return 0 - end - if m_alphabet == 0 then - m_alphabet = -1 - end --- DCS, Flash Msg - m_dcs = byte_buf - if bitand(byte_buf, 0x10) > 0 then - if bitand(byte_buf, 0x01) > 0 then - m_flash = 1 - end - end - m_pdu_ptr = m_pdu_ptr:sub(3) --- Date - local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) - if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then - return 0 - end - m_date = str_buf - m_pdu_ptr = m_pdu_ptr:sub(7) --- Time - str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) - if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then - return 0 - end - if tonumber(m_pdu_ptr:sub(8,8), 16) > 7 then - timezone = '-' .. ((tonumber(m_pdu_ptr:sub(8, 8), 16) - 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4 - else - timezone = '+' .. (m_pdu_ptr:sub(8, 8) .. tonumber(m_pdu_ptr:sub(7, 7), 16)) / 4 - end - if timezone:sub(-2, -1) == '.0' then - timezone = timezone:sub(1, -3) - end - m_time = str_buf .. ' ' .. timezone .. 'h' - m_pdu_ptr = m_pdu_ptr:sub(7) - if octet2bin_check(m_pdu_ptr) < 0 then - return 0 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - --- Text - local result = 0 - local bin_udh = 1 - if m_alphabet <= 0 then - result = pdu2text(m_pdu_ptr, m_with_udh) - return result - else - result = pdu2binary(m_pdu_ptr, m_with_udh) - return result - end - return 1 -end - -function parseStatusReport() - if m_pdu_ptr:len() < 6 then - return 0 - end - local messageid = octet2bin_check(m_pdu_ptr) - if messageid < 0 then - return 0 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - local length = octet2bin_check(m_pdu_ptr) - if length < 1 or length > max_number then - return 0 - end - local padding = length % 2 - m_pdu_ptr = m_pdu_ptr:sub(3) - local addr_type = explainAddressType(m_pdu_ptr, 0) - if addr_type < 0x80 then - return 0 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - if bitand(addr_type, 112) == 80 then - if m_pdu_ptr:len() < (length + padding) then - return 0 - end - local htmp = string.format("%x", math.floor((length * 4) / 7)) - if htmp:len() < 2 then - htmp = "0" .. htmp - end - local tpdu = htmp .. m_pdu_ptr - local res = pdu2text(tpdu, 0) - if res < 0 then - return 0 - end - m_number = m_text - m_text = nil - else - m_number = m_pdu_ptr:sub(1, length + padding + 1) - m_number = swapchars(m_number) - if m_number:byte(length + padding) == 70 then - m_number = m_number:sub(1, length + padding - 1) - end - end - m_pdu_ptr = m_pdu_ptr:sub(length + padding + 1) - if m_pdu_ptr:len() < 14 then - return 0 - end --- Date - local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) - if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then - return 0 - end - m_date = str_buf - m_pdu_ptr = m_pdu_ptr:sub(7) --- Time - str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) - if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then - return 0 - end - m_time = str_buf - m_pdu_ptr = m_pdu_ptr:sub(7) - if octet2bin_check(m_pdu_ptr) < 0 then - return 0 - end - m_pdu_ptr = m_pdu_ptr:sub(3) --- Discharge Date - local str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. "-" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. "-" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) - if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then - return 0 - end - local d_date = str_buf - m_pdu_ptr = m_pdu_ptr:sub(7) --- Time - str_buf = m_pdu_ptr:sub(2,2) .. m_pdu_ptr:sub(1,1) .. ":" .. m_pdu_ptr:sub(4,4) .. m_pdu_ptr:sub(3,3) .. ":" .. m_pdu_ptr:sub(6,6) .. m_pdu_ptr:sub(5,5) - if (not isdigit(m_pdu_ptr:byte(1))) or (not isdigit(m_pdu_ptr:byte(2))) or (not isdigit(m_pdu_ptr:byte(3))) or (not isdigit(m_pdu_ptr:byte(4))) or (not isdigit(m_pdu_ptr:byte(5))) or (not isdigit(m_pdu_ptr:byte(6))) then - return 0 - end - local d_time = str_buf - m_pdu_ptr = m_pdu_ptr:sub(7) - if octet2bin_check(m_pdu_ptr) < 0 then - return 0 - end - m_pdu_ptr = m_pdu_ptr:sub(3) - local status = octet2bin_check(m_pdu_ptr) - if status < 0 then - return 0 - end - m_text = string.format("Discharge Timestamp: %s %s Message ID: %d Status: %d", d_date, d_time, messageid, status) - return 1 -end - -function parse() - local flag = parseSMSC() - if flag ~= 1 then - return 0 - end - local tmp = octet2bin_check(m_pdu_ptr) - if tmp < 0 then - return 0 - end - if bitand(tmp, 0x40) > 0 then - m_with_udh = 1 - end - if bitand(tmp, 0x20) > 0 then - m_report = 1 - end - local type = bitand(tmp, 3) - if type == 0 then - m_pdu_ptr = m_pdu_ptr:sub(3) - local result = parseDeliver() - if result < 1 then - return 0 - end - else - if type == 2 then - m_pdu_ptr = m_pdu_ptr:sub(3) - local result = parseStatusReport() - return result - else - return 0 - end - end - return 1 -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function readpdu(pdu) - m_pdu = pdu - m_pdu_ptr = m_pdu - reset() - local flag = parse() - if flag > 0 then - t[tptr] = m_index - t[tptr+1] = m_read - t[tptr+2] = m_number - if string.find(delsend, gschar .. m_number .. gschar, 1, true) then - delslots = delslots .. m_index .. " " - else - if m_dcs == 245 and deletebinaries then - delslots = delslots .. m_index .. " " - end - end - t[tptr+3] = m_date - t[tptr+4] = m_time - if m_concat ~= nil then - m_text = m_concat .. '\n' .. m_text - end - t[tptr+5] = m_text - tptr = tptr + 6 - end -end - -local max_msg = "0" -local used_msg = "0" -gschar = string.char(29) -delsend = gschar .. table.concat(senders2delete, gschar) .. gschar -delslots = "" -tptr = 3 -t[1] = used_msg -t[2] = max_msg -g_table1 = {163, 36, 165, 232, 233, 249, 236, 242, 199, 10, 216, 248, 13, 197, 229, 0x394, 95, 0x3A6, 0x393, 0x39B, 0x3A9, 0x3A0, 0x3A8, 0x3A3, 0x398, 0x39E} -g_table1[0] = 64 -g_table1[28] = 198 -g_table1[29] = 230 -g_table1[30] = 223 -g_table1[31] = 201 -g_table1[36] = 164 -g_table1[64] = 161 -g_table1[91] = 196 -g_table1[92] = 214 -g_table1[93] = 209 -g_table1[94] = 220 -g_table1[95] = 167 -g_table1[96] = 191 -g_table1[123] = 228 -g_table1[124] = 246 -g_table1[125] = 241 -g_table1[126] = 252 -g_table1[127] = 224 -g_table2[10] = 10 -g_table2[20] = 94 -g_table2[40] = 123 -g_table2[41] = 125 -g_table2[47] = 92 -g_table2[60] = 91 -g_table2[61] = 126 -g_table2[62] = 93 -g_table2[64] = 124 -g_table2[101] = 0x20AC --- -os.execute("touch " .. smsslots) -local slottab = {} -local file = io.open(smsslots, "r") -for k in file:lines() do - slottab[k] = true -end -file:close() -local file = io.open(smsresult, "r") -local m_r = "" -if file ~= nil then - repeat - local s, e, cs, ce, ms, me - local line = file:read("*l") - if line == nil then - break - end - s, e = line:find("+CPMS:") - if s ~= nil then - cs, ce = line:find(",", e) - if cs ~= nil then - used_msg = trim(line:sub(e+1, cs-1)) - t[1] = used_msg - ms, me = line:find(",", ce+1) - if ms ~= nil then - max_msg = trim(line:sub(ce+1, ms-1)) - t[2] = max_msg - end - end - line = file:read("*l") - if line == nil then - break - end - end - s, e = line:find("+CMGL:") - if s ~= nil then - m_index = "0" - cs, ce = line:find(",", e) - if cs ~= nil then - m_index = trim(line:sub(e+1, cs-1)) - end - ds, de = line:find(",", ce+1) - if ds ~= nil then - surrogate = 0 - m_r = trim(line:sub(ce+1, ds-1)) - if m_r == "0" then - m_read = word2utf8(0x2691, word2utf8(0x2691, '')) - os.execute("date +%s > " .. smstime) - if not slottab[m_index] then - os.execute("echo " .. m_index .. " >> " .. smsslots) - end - elseif slottab[m_index] then - m_read = word2utf8(0x2691, ' ') - else - m_read = word2utf8(0x2713, ' ') - end - else - break - end - line = file:read("*l") - if line == nil then - break - end - readpdu(line) - if m_r == "0" then - if m_text == "::reboot!!" then - os.execute("(sleep 60; reboot -f) &") - elseif m_text == "::pwrtoggle!!" then - os.execute("(sleep 60; /usr/lib/rooter/pwrtoggle.sh 3) &") - elseif m_text:sub(1, 3) == "GPS" then - cmd_hand = io.popen("uci -q get modem.general.pin") - gpspin = cmd_hand:read() - cmd_hand:close() - if (m_text == "GPS" and gpspin == nil) or (m_text == "GPS " .. gpspin) then - if tonumber(m_number) ~= nil then - os.execute("/usr/lib/gps/smsreply.sh " .. modemn .. " " .. m_number .. "&") - delslots = delslots .. m_index .. " " - end - end - end - end - end - until 1==0 - file:close() -end - -local tfname = "/tmp/smstemptext" .. math.random(99) -local tfile = io.open(tfname, "w") -tfile:write(t[1] .. "\n") -tfile:write(t[2] .. "\n") -if tonumber(used_msg) == 0 then - tfile:close() -else - i = 3 - while t[i] ~= nil do - local mtxt = t[i + 5] - tfile:write(t[i] .. "\n") - tfile:write(t[i + 2] .. "\n") - tfile:write((ocount(mtxt, '\n') + 1) .. '\n') - tfile:write(mtxt .. "\n") - local mn = t[i + 2] .. " " - mn = mn:sub(1,20) - local stxt = '' - local j = 0 - local k = 1 - local ch = '' - while j < 20 do - ch = string.byte(mtxt:sub(k, k)) - if ch == nil then - j = 20 - elseif ch == 10 or ch == 13 then - stxt = stxt .. ' ' - k = k + 1 - elseif ch < 127 then - stxt = stxt .. string.char(ch) - k = k + 1 - elseif ch < 0xE0 then - stxt = stxt .. mtxt:sub(k, k + 1) - k = k + 2 - elseif ch < 0xF0 then - stxt = stxt .. mtxt:sub(k, k + 2) - k = k + 3 - else - stxt = stxt .. mtxt:sub(k, k + 3) - k = k + 4 - end - j = j + 1 - end - if mtxt ~= stxt then - stxt = stxt .. " ..." - end - local msg = t[i + 1] .. " " .. mn .. t[i + 3] .. " " .. t[i + 4] .. " " .. stxt - tfile:write(msg .. "\n") - i = i + 6 - end - tfile:close() -end -os.execute("/usr/lib/sms/merge.lua " .. tfname) -os.execute("mv " .. tfname .. " /tmp/smstext" .. modemn) - -if #delslots > 0 then - os.execute("/usr/lib/sms/delsms.sh " .. modemn .. " " .. delslots .. " &") -end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua deleted file mode 100644 index 78189a3..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.lua +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/lua - -local oaddr = arg[1] -local txt = arg[2] -local pid = arg[3] - -if package.path:find(";/usr/lib/sms/?.lua") == nil then - package.path = package.path .. ";/usr/lib/sms/?.lua" -end - -local utf8togsm = require "utf8togsm" -local pack7bit = require "pack7bit" - -local isok = true - -if #oaddr > 11 then - txt = oaddr .. " " .. txt - oaddr = "ROOter" -end - -if #txt == 0 then - txt = "Usage: /usr/lib/sms/sys2sms.sh 'from' 'text to write here'" -end - -utf8togsm.chktxt(txt) -local msg = utf8togsm["msg"] -local dcs = utf8togsm["dcs"] -local ud = utf8togsm["txt"] - -local udl = string.format("%02X", math.floor(#ud / 2)) - -if msg ~= nil then - isok = false -end - -if isok and dcs == "00" then - pack7bit.pack(udl, ud) - ud = pack7bit["pdu"] -end -if #oaddr == 0 or oaddr == ' ' then - oaddr = "ROOter" -end -if oaddr:sub(-1) == ' ' then - oaddr = oaddr:sub(1, -2) -end -local oaddrl = #oaddr * 2 -if oaddrl > 14 then - oaddrl = oaddrl - 2 -elseif oaddrl > 6 then - oaddrl = oaddrl - 1 -end -oaddrl = string.format("%02X", oaddrl) - -utf8togsm.chktxt(oaddr) -oaddr = utf8togsm["txt"] - -if utf8togsm["dcs"] == "08" then - isok = false -end - -pack7bit.pack(string.format("%02X", math.floor(#oaddr / 2)), oaddr) -oaddr = pack7bit["pdu"] - -dtg = os.date("%y%m%d%H%M%S%z", os.time()) -sign = dtg:sub(13, 13) -tz = dtg:sub(-4) -dtgif = '' -for j = 1, 11, 2 do - dtgif = dtgif .. dtg:sub(j + 1, j + 1) .. dtg:sub(j, j) -end -tz = string.format("%02d", math.floor((tonumber(tz:sub(1, 2) * 4)) + tonumber(tz:sub(3, 4) / 15))) -tz = tz:sub(2, 2) .. tz:sub(1, 1) -if sign == "-" then - tz = tz:sub(1, 1) .. string.format("%X", (tonumber(tz:sub(2, 2)) + 8)) -end - -pdu = "0004" .. oaddrl .. "D0" .. oaddr .. "00" .. dcs .. dtgif .. tz .. udl .. ud - -if isok then - pdul = string.format("%03d", (math.floor(#pdu / 2) - 1)) - os.execute("echo " .. pdul .. " " .. pdu .. " > /tmp/pdu" .. pid) -end diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh deleted file mode 100644 index d98b19d..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/sys2sms.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "sms process" "$@" -} - -ADDR="$1" -shift 1 -TXT="$@" -MYPID=$(printf "%05d" $$) -RESFILE="/tmp/pdu"$MYPID - -CURRMODEM=$(uci get modem.general.smsnum) -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -RES="" -XSTATUS=0 - -lua /usr/lib/sms/sys2sms.lua "$ADDR" "$TXT" $MYPID - -if [ -e $RESFILE ]; then - read PDUL PDU < $RESFILE - rm $RESFILE -else - RES="Failed to write SMS - is text too long?" - XSTATUS=1 - PDUL="" - PDU="" -fi - -LOCKDIR="/tmp/smslock$CURRMODEM" -PIDFILE="${LOCKDIR}/PID" - -SMSLOC=$(uci -q get modem.modem$CURRMODEM.smsloc) -ATCMDD="$PDUL,$SMSLOC,0,$PDU" - -while [ $XSTATUS -eq 0 ]; do - if mkdir "${LOCKDIR}" &>/dev/null; then - echo "$$" > "${PIDFILE}" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "smswrite.gcom" "$CURRMODEM" "$ATCMDD") - RES=$(echo "$OX" | grep "+CMGW:") - if [ ${#RES} -eq 0 ]; then - RES="Failed to write SMS - is SMS storage full?" - XSTATUS=1 - else - RES="New SMS written successfully" - fi - rm -rf "${LOCKDIR}" - break - else - OTHERPID="$(cat "${PIDFILE}")" - if [ $? = 0 ]; then - if ! kill -0 $OTHERPID &>/dev/null; then - rm -rf "${LOCKDIR}" - fi - fi - sleep 1 - fi -done - -log "$RES" -echo "$RES" -exit $XSTATUS diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh deleted file mode 100644 index 4c32f74..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/toggle.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -SET=$1 - -uci set modem.sms.menable=$SET -uci commit modem - diff --git a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua b/rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua deleted file mode 100644 index 8b1bdbe..0000000 --- a/rooter/0basicsupport/ext-sms/files/usr/lib/sms/utf8togsm.lua +++ /dev/null @@ -1,167 +0,0 @@ -local utf8togsm = {} - -function hasbit(x, p) - return x % (p + p) >= p -end - -function bitand(x, y) - local p = 1; local z = 0; local limit = x > y and x or y - while p <= limit do - if hasbit(x, p) and hasbit(y, p) then - z = z + p - end - p = p + p - end - return z -end - -function bitor(x, y) - local p = 1; local z = 0; local limit = x > y and x or y - while p <= limit do - if hasbit(x, p) or hasbit(y, p) then - z = z + p - end - p = p + p - end - return z -end - -function bitleft(x, y) - return x * 2 ^ y -end - -function bitright(x, y) - return math.floor(x / 2 ^ y) -end - -function utf8togsm.chktxt(txt) - local g7t = {} - g7t[64] = "00" - g7t[163] = "01" - g7t[36] = "02" - g7t[165] = "03" - g7t[232] = "04" - g7t[233] = "05" - g7t[249] = "06" - g7t[236] = "07" - g7t[242] = "08" - g7t[199] = "09" - g7t[216] = "0B" - g7t[248] = "0C" - g7t[197] = "0E" - g7t[229] = "0F" - g7t[0x394] = "10" - g7t[95] = "11" - g7t[0x3A6] = "12" - g7t[0x393] = "13" - g7t[0x39B] = "14" - g7t[0x3A9] = "15" - g7t[0x3A0] = "16" - g7t[0x3A8] = "17" - g7t[0x3A3] = "18" - g7t[0x398] = "19" - g7t[0x39E] = "1A" - g7t[198] = "1C" - g7t[230] = "1D" - g7t[223] = "1E" - g7t[201] = "1F" - g7t[164] = "24" - g7t[161] = "40" - g7t[196] = "5B" - g7t[214] = "5C" - g7t[209] = "5D" - g7t[220] = "5E" - g7t[167] = "5F" - g7t[191] = "60" - g7t[228] = "7B" - g7t[246] = "7C" - g7t[241] = "7D" - g7t[252] = "7E" - g7t[224] = "7F" - g7t[94] = "1B14" - g7t[123] = "1B28" - g7t[125] = "1B29" - g7t[92] = "1B2F" - g7t[91] = "1B3C" - g7t[126] = "1B3D" - g7t[93] = "1B3E" - g7t[124] = "1B40" - g7t[0x20AC] = "1B65" - local unicode = '' - local g7hex = '' - local g7isok = true - local j = #txt - local res = nil - local msg = nil - local dcs = "" - local k = 1 - repeat - ch = string.byte(txt, k, k) - if ch >= 0xF0 then - ch = bitleft(bitand(ch, 7), 18) - ch = bitor(bitleft(bitand(string.byte(txt, k + 1, k + 1), 0x3F), 12), ch) - ch = bitor(bitleft(bitand(string.byte(txt, k + 2, k + 2), 0x3F), 6), ch) - ch = bitor(bitand(string.byte(txt, k + 3, k + 3), 0x3F), ch) - 0x10000 - local w1 = bitor(0xD800, bitright(bitand(ch, 0xFFC00), 10)) - local w2 = bitor(0xDC00, bitand(ch, 0x3FF)) - unicode = unicode .. string.format("%04X", w1) .. string.format("%04X", w2) - g7isok = false - k = k + 3 - elseif ch >= 0xE0 then - ch = bitleft(bitand(ch, 0xF), 12) - ch = bitor(bitleft(bitand(string.byte(txt, k + 1, k + 1), 0x3F), 6), ch) - ch = bitor(bitand(string.byte(txt, k + 2, k + 2), 0x3F), ch) - res = g7t[ch] - if res == nil then - g7isok = false - else - g7hex = g7hex .. res - end - unicode = unicode .. string.format("%04X", ch) - k = k + 2 - elseif ch >= 0xC0 then - ch = bitleft(bitand(ch, 0x3F), 6) - ch = bitor(bitand(string.byte(txt, k + 1, k + 1), 0x3F), ch) - res = g7t[ch] - if res == nil then - g7isok = false - else - g7hex = g7hex .. res - end - unicode = unicode .. string.format("%04X", ch) - k = k + 1 - elseif ch == 0x60 then - unicode = unicode .. '0060' - g7isok = false - elseif ch <= 0x7F then - res = g7t[ch] - if res == nil then - g7hex = g7hex .. string.format("%02X", ch) - else - g7hex = g7hex .. res - end - unicode = unicode .. string.format("%04X", ch) - else - g7hex = g7hex .. '3F' - unicode = unicode .. '003F' - end - k = k + 1 - until k > j - if g7isok and #g7hex <= 320 then - dcs = "00" - txt = g7hex - elseif g7isok then - msg = 'Processed text length = ' .. math.floor(#g7hex / 2) .. ' 7-bit characters.\n' - msg = msg .. 'Currently ROOter supports 160 maximum per message.' - elseif #unicode <= 280 then - dcs = "08" - txt = unicode - else - msg = 'Processed text length = ' .. math.floor(#unicode / 4) .. ' 16-bit Unicode characters.\n' - msg = msg .. 'Currently ROOter supports 70 maximum per message.' - end - utf8togsm["msg"] = msg - utf8togsm["dcs"] = dcs - utf8togsm["txt"] = txt -end -return utf8togsm diff --git a/rooter/0basicsupport/luci-app-guestwifi/Makefile b/rooter/0basicsupport/luci-app-guestwifi/Makefile deleted file mode 100644 index 71340c7..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-guestwifi -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/luci-app-guestwifi - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Applications - TITLE:=support for Guest Wifi - PKGARCH:=all -endef - -define Package/luci-app-guestwifi/description - Helper scripts to enable Guest Wifi -endef - - -define Build/Compile -endef - -define Package/luci-app-guestwifi/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,luci-app-guestwifi)) diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi b/rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi deleted file mode 100644 index 5a314d4..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/etc/config/guestwifi +++ /dev/null @@ -1,4 +0,0 @@ - -config guest 'guestw' - option 5g '1' - diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh deleted file mode 100644 index fc044ff..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/create.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Guest Wifi" "$@" -} - -do_radio24() { - local config=$1 - local channel - - config_get channel $1 channel - if [ $channel -gt 15 ]; then - uci set guestwifi.$NAME.radio5g="1" - fi -} - -NAME=$1 - -uci set guestwifi.$NAME=guestwifi -uci set guestwifi.$NAME.ssid="Guest" -uci set guestwifi.$NAME.freq="0" -uci set guestwifi.$NAME.enabled="0" -uci set guestwifi.$NAME.encrypted="" -uci set guestwifi.$NAME.password="" -uci set guestwifi.$NAME.qos="0" -uci set guestwifi.$NAME.ul="" -uci set guestwifi.$NAME.dl="" -uci set guestwifi.$NAME.radio5g="0" -config_load wireless -config_foreach do_radio24 wifi-device -uci commit guestwifi \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh deleted file mode 100644 index 1929c5f..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/remove.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Guest Wifi" "$@" -} - -NAME=$1 diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh deleted file mode 100644 index e5b7646..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/start.sh +++ /dev/null @@ -1,200 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Guest Wifi" "$@" -} - -do_radio() { - local config=$1 - local freq=$2 - local channel - - config_get channel $1 channel - if [ $freq = "0" ]; then - if [ $channel -lt 15 ]; then - RADIO=$config - fi - else - if [ $channel -gt 15 ]; then - RADIO=$config - fi - fi -} - -do_check() { - local config=$1 - local wfreq=$2 - local enabled - local freq - - config_get enabled $1 enabled - if [ $enabled = "1" ]; then - config_get freq $1 freq - if [ $freq = $wfreq ]; then - CHECK=1 - fi - fi -} - -NAME=$1 -RAD=$(uci -q get guestwifi.$NAME.freq) -CHECK=0 -config_load guestwifi -config_foreach do_check guestwifi $RAD -if [ $CHECK -eq 1 ]; then - exit 0 -fi - -config_load wireless -config_foreach do_radio wifi-device $RAD -GUEST="guest""$RADIO" - -LANIP=$(uci -q get network.lan.ipaddr) -L1=$(echo $LANIP | cut -d. -f1) -L2=$(echo $LANIP | cut -d. -f2) -L3=$(echo $LANIP | cut -d. -f3) -L4=$(echo $LANIP | cut -d. -f4) -NL3="254" -if [ $RAD = "0" ]; then - NL3="253" -fi -if [ $L3 = "254" ]; then - NL3="1" -fi -if [ $L3 = "253" ]; then - NL3="2" -fi -IP="$L1"."$L2"."$NL3"."$L4" - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -WW=$(uci get -q network.$GUEST) -if [ -z $WW ]; then -# Configure guest network - uci delete network.${GUEST}_dev - uci set network.${GUEST}_dev=device - uci set network.${GUEST}_dev.type=bridge - uci set network.${GUEST}_dev.name="br-"$GUEST - - uci delete network.$GUEST - uci set network.$GUEST=interface - uci set network.$GUEST.proto=static - uci set network.$GUEST.ipaddr=$IP - uci set network.$GUEST.$ifname1=br-${GUEST} - uci set network.$GUEST.netmask=255.255.255.0 - -# Configure DHCP for guest network - uci delete dhcp.$GUEST - uci set dhcp.$GUEST=dhcp - uci set dhcp.$GUEST.interface=$GUEST - uci set dhcp.$GUEST.start=50 - uci set dhcp.$GUEST.limit=200 - uci set dhcp.$GUEST.leasetime=1h - -# Configure firewall for guest network - ## Configure guest zone - uci delete firewall.$GUEST"_zone" - uci set firewall.$GUEST"_zone"=zone - uci set firewall.$GUEST"_zone".name=$GUEST - uci set firewall.$GUEST"_zone".network=$GUEST - uci set firewall.$GUEST"_zone".input=REJECT - uci set firewall.$GUEST"_zone".forward=REJECT - uci set firewall.$GUEST"_zone".output=ACCEPT - ## Allow Guest -> Internet - uci delete firewall.$GUEST"_forwarding" - uci set firewall.$GUEST"_forwarding"=forwarding - uci set firewall.$GUEST"_forwarding".src=$GUEST - uci set firewall.$GUEST"_forwarding".dest=wan - ## Allow DNS Guest -> Router - uci delete firewall.$GUEST"_rule_dns" - uci set firewall.$GUEST"_rule_dns"=rule - uci set firewall.$GUEST"_rule_dns".name="Allow "$GUEST" DNS Queries" - uci set firewall.$GUEST"_rule_dns".src=$GUEST - uci set firewall.$GUEST"_rule_dns".dest_port=53 - uci set firewall.$GUEST"_rule_dns".proto=tcpudp - uci set firewall.$GUEST"_rule_dns".target=ACCEPT - ## Allow DHCP Guest -> Router - uci delete firewall.$GUEST"_rule_dhcp" - uci set firewall.$GUEST"_rule_dhcp"=rule - uci set firewall.$GUEST"_rule_dhcp".name="Allow "$GUEST" DHCP request" - uci set firewall.$GUEST"_rule_dhcp".src=$GUEST - uci set firewall.$GUEST"_rule_dhcp".src_port=68 - uci set firewall.$GUEST"_rule_dhcp".dest_port=67 - uci set firewall.$GUEST"_rule_dhcp".proto=udp - uci set firewall.$GUEST"_rule_dhcp".target=ACCEPT - - uci commit -fi - -# Configure guest Wi-Fi -SSID=$(uci -q get guestwifi.$NAME.ssid) -ENCR=$(uci -q get guestwifi.$NAME.encrypted) - -uci delete wireless.$NAME -uci set wireless.$NAME=wifi-iface -uci set wireless.$NAME.device=$RADIO -uci set wireless.$NAME.mode=ap -uci set wireless.$NAME.network=$GUEST -uci set wireless.$NAME.ssid=$SSID -case $ENCR in - "0" ) - uci set wireless.$NAME.encryption="none" - uci set wireless.$NAME.key="" - ;; - "1" ) - uci set wireless.$NAME.encryption="psk" - uci set wireless.$NAME.key=$(uci get guestwifi.$NAME.password) - ;; - "2" ) - uci set wireless.$NAME.encryption="psk2" - uci set wireless.$NAME.key=$(uci get guestwifi.$NAME.password) - ;; -esac -uci commit wireless - -QOS=$(uci -q get guestwifi.$NAME.qos) - -if [ $QOS = "1" ]; then - DL=$(uci -q get guestwifi.$NAME.dl) - let "DL=$DL * 1000" - UL=$(uci -q get guestwifi.$NAME.ul) - let "UL=$UL * 1000" - IFACE="$(iwinfo | grep "ESSID" | grep $SSID)" - WI=${IFACE% *} - WI=${WI% *} - uci delete sqm.$NAME - uci set sqm.$NAME=queue - uci set sqm.$NAME.interface=$WI - uci set sqm.$NAME.enabled='1' - uci set sqm.$NAME.upload=$DL - uci set sqm.$NAME.download=$UL - uci set sqm.$NAME.qdisc='cake' - uci set sqm.$NAME.script='piece_of_cake.qos' - uci set sqm.$NAME.qdisc_advanced='1' - uci set sqm.$NAME.linklayer='none' - uci set sqm.$NAME.ingress_ecn='ECN' - uci set sqm.$NAME.egress_ecn='ECN' - uci set sqm.$NAME.debug_logging='0' - uci set sqm.$NAME.verbosity='5' - uci set sqm.$NAME.squash_dscp='1' - uci set sqm.$NAME.squash_ingress ='1' - uci commit sqm - /etc/init.d/sqm start - /etc/init.d/sqm enable -fi - - -if [ -z $WW ]; then - /etc/init.d/dnsmasq restart - /etc/init.d/firewall restart - /etc/init.d/network restart -fi - - - -uci set guestwifi.$NAME.enabled="1" -uci commit guestwifi \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh deleted file mode 100644 index 3313ed0..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/guestwifi/stop.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Guest Wifi" "$@" -} - -NAME=$1 - -uci delete wireless.$NAME -uci commit wireless -QOS=$(uci get guestwifi.$NAME.qos) -if [ $QOS = "1" ]; then - uci delete sqm.$NAME - uci commit sqm - /etc/init.d/sqm start - /etc/init.d/sqm enable -fi -uci set guestwifi.$NAME.enabled="0" -uci commit guestwifi \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua deleted file mode 100644 index a4cabce..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/controller/guestwifi.lua +++ /dev/null @@ -1,19 +0,0 @@ -module("luci.controller.guestwifi", package.seeall) - -function index() - local page - if not nixio.fs.access("/etc/config/wireless") then - return - end - - page = entry({"admin", "network", "guestwifi"}, cbi("guestwifi", {hidesavebtn=true, hideresetbtn=true}), "Guest Wifi", 22) - page.dependent = true - entry( {"admin", "network", "guestwifi", "edit"}, cbi("guestwifi-edit"), nil ).leaf = true - - entry({"admin", "network", "createwifi"}, call("action_createwifi")) -end - -function action_createwifi() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/guestwifi/create.sh " .. set) -end \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua deleted file mode 100644 index 982ee85..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi-edit.lua +++ /dev/null @@ -1,72 +0,0 @@ -require("luci.ip") -local uci = require "luci.model.uci".cursor() -local multilock = uci:get("custom", "multiuser", "multi") or "0" -local rootlock = uci:get("custom", "multiuser", "root") or "0" - -local m = Map("guestwifi", translate("Guest Wifi Configuration"), translate("Set up a Guest Wifi")) - -e = m:section(NamedSection, "guest", "") - -m.on_init = function(self) - --luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) -end - -btn = e:option(Button, "_btn", translate(" ")) -btn.inputtitle = translate("Back to Main Page") -btn.inputstyle = "apply" -btn.redirect = luci.dispatcher.build_url( - "admin", "network", "guestwifi" -) -function btn.write(self, section, value) - luci.http.redirect( self.redirect ) -end - -local s = m:section( NamedSection, arg[1], "guestwifi", translate("Instance Name : " .. arg[1]) ) - -ssid = s:option(Value, "ssid", translate("SSID :")); -ssid.rmempty = true; -ssid.optional=false; -ssid.default="Guest"; - -bl = s:option(ListValue, "freq", translate("Frequency :")); -bl:value("0", "2.4Ghz") -bl.rmempty = true; -bl.optional=false; -wifi5g = uci:get("guestwifi", arg[1], "radio5g") -if wifi5g == "1" then - bl:value("1", "5.0Ghz") -end - -el = s:option(ListValue, "encrypted", translate("Encryption :")); -el:value("0", translate("None")) -el:value("1", translate("WPA-PSK (Medium Security)")) -el:value("2", translate("WPA2-PSK (Strong Security)")) -el.default=0 - -pass = s:option(Value, "password", translate("Password :")); -pass.rmempty = true; -pass.optional=false; -pass.default=""; -pass.datatype="wpakey"; -pass.password = true - -if (multilock == "0") then - ql = s:option(ListValue, "qos", translate("Bandwidth Limited :")); - ql:value("0", "Disabled") - ql:value("1", "Enabled") - ql.default=0 - - dl = s:option(Value, "dl", translate("Download Speed (Mbit/s) :")); - dl.optional=false; - dl.rmempty = true; - dl.datatype = "and(uinteger,min(1))" - dl.default=10 - - ul = s:option(Value, "ul", translate("Upload Speed (Mbit/s) :")); - ul.optional=false; - ul.rmempty = true; - ul.datatype = "and(uinteger,min(1))" - ul.default=2 -end - -return m \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua deleted file mode 100644 index 6ec09c2..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/model/cbi/guestwifi.lua +++ /dev/null @@ -1,128 +0,0 @@ -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() -local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have -local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid - -local m = Map("guestwifi", translate("Guest Wifi"), translate("Set up a Guest Wifi on your Router")) - -local s = m:section( TypedSection, "guestwifi", translate("Instances"), translate("Below is a list of Guest Wifi Instances and their current state") ) -s.template = "cbi/tblsection" -s.template_addremove = "guestwifi/cbi-select-input-add" -s.addremove = true -s.add_select_options = { } - -s.extedit = luci.dispatcher.build_url("admin", "network", "guestwifi", "edit", "%s") - -function s.parse(self, section) - local recipe = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".select" - ) - - if recipe and not s.add_select_options[recipe] then - self.invalid_cts = true - else - TypedSection.parse( self, section ) - end -end - -function s.create(self, name) - local recipe = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".select" - ) - local name = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".text" - ) - return 0 -end - -function s.remove(self, name) - sys.call("/usr/lib/guestwifi/stop.sh %s" % name) - uci:delete("guestwifi", name) - uci:save("guestwifi") - uci:commit("guestwifi") -end - - - -local updown = s:option( Button, "_updown", translate("Start/Stop") ) -updown._state = false -updown.redirect = luci.dispatcher.build_url( - "admin", "network", "guestwifi" -) -function updown.cbid(self, section) - local file_cfg = self.map:get(section, "enabled") - if file_cfg == "1" then - pid = 1 - else - pid = nil - end - self._state = pid ~= nil - self.option = self._state and "stop" or "start" - return AbstractValue.cbid(self, section) -end -function updown.cfgvalue(self, section) - self.title = self._state and "stop" or "start" - self.inputstyle = self._state and "reset" or "reload" -end -function updown.write(self, section, value) - if self.option == "stop" then - sys.call("/usr/lib/guestwifi/stop.sh %s" % section) - else - sys.call("/usr/lib/guestwifi/start.sh %s" % section) - end - luci.http.redirect( self.redirect ) -end - -local port = s:option( DummyValue, "ssid", translate("SSID") ) - -local freq = s:option( DummyValue, "freq", translate("Frequency") ) -function freq.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = "0" - end - if val == "1" then - return "5.0Ghz" - else - return "2.4Ghz" - end -end - -local auto = s:option( DummyValue, "encrypted", translate("Encryption") ) -function auto.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = 0 - end - if val == "1" then - return "WPA-PSK (Medium Security)" - else - if val == "2" then - return "WPA2-PSK (Strong Security)" - else - return "None" - end - end -end - -local qos = s:option( DummyValue, "qos", translate("Bandwidth Limiting") ) -function qos.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = 0 - end - if val == "1" then - dl_cfg = self.map:get(section, "dl") - ul_cfg = self.map:get(section, "ul") - return "Download : " .. dl_cfg .. " Mbit/s / Upload : " .. ul_cfg .. " Mbit/s" - else - return "Disabled" - end -end - - -return m \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm deleted file mode 100644 index a99adf8..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/cbi-select-input-add.htm +++ /dev/null @@ -1,60 +0,0 @@ - - - - -<%+guestwifi/ovpn_css%> - -
                -
                -
                - - - - -
                 
                -

                <%:New Guest Wifi%>

                - - - - - - -
                -
                -
                -
                \ No newline at end of file diff --git a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm b/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm deleted file mode 100644 index 55c0a54..0000000 --- a/rooter/0basicsupport/luci-app-guestwifi/files/usr/lib/lua/luci/view/guestwifi/ovpn_css.htm +++ /dev/null @@ -1,38 +0,0 @@ - diff --git a/rooter/0drivers/rmbim/.svn/entries b/rooter/0drivers/rmbim/.svn/entries deleted file mode 100644 index 358eda1..0000000 --- a/rooter/0drivers/rmbim/.svn/entries +++ /dev/null @@ -1,65 +0,0 @@ -10 - -dir -42347 -svn://svn.openwrt.org/openwrt/trunk/package/network/utils/umbim -svn://svn.openwrt.org/openwrt - - - -2014-08-26T09:36:59.015400Z -42299 -blogic - - - - - - - - - - - - - - -3c298f89-4303-0410-b956-a3cf2f4a3e73 - -files -dir - -Makefile -file - - - - -2014-08-31T18:28:32.000000Z -47329758b279f0cfd6073b11ec66d486 -2014-08-26T09:36:59.015400Z -42299 -blogic - - - - - - - - - - - - - - - - - - - - - -1141 - diff --git a/rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base b/rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base deleted file mode 100644 index f0868ce..0000000 --- a/rooter/0drivers/rmbim/.svn/text-base/Makefile.svn-base +++ /dev/null @@ -1,45 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=umbim -PKG_VERSION:=2014-08-26 -PKG_RELEASE=$(PKG_SOURCE_VERSION) - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=git://git.openwrt.org/project/umbim.git -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_VERSION:=7741d88cdfd36f0c4380f660a9ad7109df76b432 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -PKG_MAINTAINER:=John Crispin - -PKG_LICENSE:=GPLv2 -PKG_LICENSE_FILES:= - -PKG_BUILD_PARALLEL:=1 - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -define Package/umbim - SECTION:=net - CATEGORY:=Network - DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim - TITLE:=Control utility for mobile broadband modems -endef - -define Package/umbim/description - umbim is a command line tool for controlling mobile broadband modems using - the MBIM-protocol. -endef - -TARGET_CFLAGS += \ - -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections - -TARGET_LDFLAGS += -Wl,--gc-sections - -define Package/umbim/install - $(INSTALL_DIR) $(1)/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/ - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,umbim)) diff --git a/rooter/0drivers/rmbim/Makefile b/rooter/0drivers/rmbim/Makefile deleted file mode 100644 index e35f0b2..0000000 --- a/rooter/0drivers/rmbim/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=umbim -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL=$(PROJECT_GIT)/project/umbim.git -PKG_SOURCE_DATE:=2021-08-18 -PKG_SOURCE_VERSION:=de5623104baee6e0c13c92f05c15bf4b4145c0b1 -PKG_MIRROR_HASH:=2d4a75d2b53c8413521a2fd138895e327bff3f4b4d29a540342b2d2e1e009852 -PKG_MAINTAINER:=John Crispin - -PKG_LICENSE:=GPL-2.0 -PKG_LICENSE_FILES:= - -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -define Package/rmbim - SECTION:=net - CATEGORY:=ROOter - SUBMENU:=Drivers - DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim +luci-proto-mbim - TITLE:=Control utility for mobile broadband modems -endef - -define Package/rmbim/description - rmbim is a command line tool for controlling mobile broadband modems using - the MBIM-protocol. -endef - -TARGET_CFLAGS += \ - -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections - -TARGET_LDFLAGS += -Wl,--gc-sections - -define Package/rmbim/install - $(INSTALL_DIR) $(1)/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/ - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,rmbim)) diff --git a/rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh b/rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh deleted file mode 100644 index 67e48fd..0000000 --- a/rooter/0drivers/rmbim/files/lib/netifd/proto/mbim.sh +++ /dev/null @@ -1,627 +0,0 @@ -#!/bin/sh - -[ -n "$INCLUDE_ONLY" ] || { - . /lib/functions.sh - . ../netifd-proto.sh - init_proto "$@" -} -# DBG=-v - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "MBIM Connect $CURRMODEM" "$@" -} - -enb=$(uci -q get custom.connect.ipv6) -if [ -z $enb ]; then - enb="1" -fi - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -get_connect() { - NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) - NAPN2=$(uci -q get modem.modeminfo$CURRMODEM.apn2) - NUSER=$(uci -q get modem.modeminfo$CURRMODEM.user) - NPASS=$(uci -q get modem.modeminfo$CURRMODEM.passw) - NAUTH=$(uci -q get modem.modeminfo$CURRMODEM.auth) - PINC=$(uci -q get modem.modeminfo$CURRMODEM.pincode) - PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) - isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist) - - apn=$NAPN - apn2=$NAPN2 - username="$NUSER" - password="$NPASS" - auth=$NAUTH - pincode=$PINC - - if [ "$PDPT" = 0 ]; then - ipt="" - else - IPVAR=$(uci -q get modem.modem$CURRMODEM.pdptype) - case "$IPVAR" in - "IP" ) - ipt="ipv4:" - ;; - "IPV6" ) - ipt="ipv6:" - ;; - "IPV4V6" ) - ipt="ipv4v6:" - ;; - esac - fi -} - -get_sub() { - log "Checking subscriber" - tid=$((tid + 1)) - SUB=$(umbim $DBG -n -t $tid -d $device subscriber) - retq=$? - if [ $retq -ne 0 ]; then - log "Subscriber init failed" - proto_notify_error "$interface" NO_SUBSCRIBER - return 1 - fi - CNUM=$(echo "$SUB" | awk '/number:/ {print $2}') - IMSI=$(echo "$SUB" | awk '/subscriberid:/ {print $2}') - uci set modem.modem$CURRMODEM.imsi=$IMSI - ICCID=$(echo "$SUB" | awk '/simiccid:/ {print $2}') - uci set modem.modem$CURRMODEM.iccid=$ICCID - uci commit modem -} - -proto_mbim_init_config() { - available=1 - no_device=1 - proto_config_add_string "device:device" - proto_config_add_string apn - proto_config_add_string apn2 - proto_config_add_string pincode - proto_config_add_string delay - proto_config_add_string auth - proto_config_add_string username - proto_config_add_string password -} - -_proto_mbim_setup() { - local interface="$1" - local tid=2 - local ret v6cap pdns v4dns v6dns - - if [ ! -f /tmp/bootend.file ]; then - return 0 - fi - - CURRMODEM=$(uci -q get network.$interface.currmodem) - uci set modem.modem$CURRMODEM.connected=0 - uci commit modem - rm -f $ROOTER_LINK/reconnect$CURRMODEM - jkillall getsignal$CURRMODEM - rm -f $ROOTER_LINK/getsignal$CURRMODEM - jkillall con_monitor$CURRMODEM - rm -f $ROOTER_LINK/con_monitor$CURRMODEM - jkillall mbim_monitor$CURRMODEM - rm -f $ROOTER_LINK/mbim_monitor$CURRMODEM - - local device apn pincode delay - json_get_vars device apn apn2 pincode delay auth username password - - case $auth in - "0" ) - auth= - ;; - "1" ) - auth="pap" - ;; - "2" ) - auth="chap" - ;; - "*" ) - auth= - ;; - esac - - IMEI="Unknown" - IMSI="Unknown" - ICCID="Unknown" - CNUM="*" - CNUMx="*" - - [ -n "$ctl_device" ] && device=$ctl_device - - [ -n "$device" ] || { - log "No control device specified" - proto_notify_error "$interface" NO_DEVICE - proto_set_available "$interface" 0 - return 1 - } - [ -c "$device" ] || { - log "The specified control device does not exist" - proto_notify_error "$interface" NO_DEVICE - proto_set_available "$interface" 0 - return 1 - } - - devname="$(basename "$device")" - devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" - ifname="$( ls "$devpath"/net )" - - [ -n "$ifname" ] || { - log "Failed to find matching interface" - proto_notify_error "$interface" NO_IFNAME - proto_set_available "$interface" 0 - return 1 - } - - [ -n "$delay" ] && sleep "$delay" - - log "Query radio state" - umbim $DBG -n -d $device radio | grep "off" - STATUS=$? - - [ "$STATUS" -ne 0 ] || { - sleep 1 - log "Setting FCC Auth" - uqmi $DBG -s -m -d $device --fcc-auth - sleep 1 - } - - log "Reading capabilities" - tid=$((tid + 1)) - DCAPS=$(umbim $DBG -n -t $tid -d $device caps) - retq=$? - if [ $retq -ne 0 ]; then - - log "Failed to read modem caps" - tid=$((tid + 1)) - umbim $DBG -t $tid -d "$device" disconnect - proto_notify_error "$interface" PIN_FAILED - return 1 - fi - CUSTOM=$(echo "$DCAPS" | awk '/customdataclass:/ {print $2}') - IMEI=$(echo "$DCAPS" | awk '/deviceid:/ {print $2}') - uci set modem.modem$CURRMODEM.imei=$IMEI - echo 'CUSTOM="'"$CUSTOM"'"' > /tmp/mbimcustom$CURRMODEM - - get_sub - - if [ ! -f /tmp/profile$CURRMODEM ]; then - $ROOTER/connect/get_profile.sh $CURRMODEM - fi - - get_connect - - log "Checking PIN state" - tid=$((tid + 1)) - umbim $DBG -n -t $tid -d $device pinstate - retq=$? - if [ $retq -eq 2 ]; then - log "PIN is required" - if [ ! -z $pincode ]; then - log "Sending PIN" - tid=$((tid + 1)) - umbim $DBG -n -t $tid -d $device unlock "$pincode" 2>/dev/null - retq=$? - if [ $retq -ne 0 ]; then - log "PIN unlock failed" - exit 1 - else - log "PIN unlocked" - sleep 3 - CHKPORT=$(uci get modem.modem$CURRMODEM.commport) - if [ ! -z $CHKPORT ]; then - $ROOTER/common/gettype.sh $CURRMODEM - else - get_sub - fi - fi - else - log "PIN is missing in the profile" - exit 1 - fi - else - log "PIN is not required" - fi - - log "Register with network" - for i in $(seq 30); do - tid=$((tid + 1)) - REG=$(umbim $DBG -n -t $tid -d $device registration) - retq=$? - [ $retq -ne 2 ] && break - sleep 2 - done - if [ $retq != 0 ]; then - if [ $retq != 4 ]; then - log "Subscriber registration failed" - proto_notify_error "$interface" NO_REGISTRATION - return 1 - fi - fi - MCCMNC=$(echo "$REG" | awk '/provider_id:/ {print $2}') - PROV=$(echo "$REG" | awk '/provider_name:/ {print $2}') - MCC=${MCCMNC:0:3} - MNC=${MCCMNC:3} - - tid=$((tid + 1)) - - log "Attach to network" - ATTACH=$(umbim $DBG -n -t $tid -d $device attach) - retq=$? - if [ $retq != 0 ]; then - log "Failed to attach to network" - proto_notify_error "$interface" ATTACH_FAILED - return 1 - fi - UP=$(echo "$ATTACH" | awk '/uplinkspeed:/ {print $2}') - DOWN=$(echo "$ATTACH" | awk '/downlinkspeed:/ {print $2}') - - tid=$((tid + 1)) - - for isp in $isplist - do - NAPN=$(echo $isp | cut -d, -f2) - NPASS=$(echo $isp | cut -d, -f4) - CID=$(echo $isp | cut -d, -f5) - NUSER=$(echo $isp | cut -d, -f6) - NAUTH=$(echo $isp | cut -d, -f7) - if [ "$NPASS" = "nil" ]; then - NPASS="NIL" - fi - if [ "$NUSER" = "nil" ]; then - NUSER="NIL" - fi - if [ "$NAUTH" = "nil" ]; then - NAUTH="0" - fi - apn=$NAPN - username="$NUSER" - password="$NPASS" - auth=$NAUTH - case $auth in - "0" ) - auth="none" - ;; - "1" ) - auth="pap" - ;; - "2" ) - auth="chap" - ;; - "*" ) - auth="none" - ;; - esac - - if [ ! -e /etc/config/isp ]; then - log "Connect to network using $apn" - else - log "Connect to network" - fi - - if [ ! -e /etc/config/isp ]; then - log "$ipt $apn $auth $username $password" - fi - - tidd=0 - tcnt=4 - while ! umbim $DBG -n -t $tid -d $device connect "$ipt""$apn" "$auth" "$username" "$password"; do - tid=$((tid + 1)) - sleep 1; - tidd=$((tidd + 1)) - if [ $tidd -gt $tcnt ]; then - break; - fi - done - if [ $tidd -le $tcnt ]; then - break - fi - done - if [ $tidd -gt $tcnt ]; then - log "Failed to connect to network" - return 1 - fi - log "Save Connect Data" - uci set modem.modem$CURRMODEM.mdevice=$device - uci set modem.modem$CURRMODEM.mapn=$apn - uci set modem.modem$CURRMODEM.mipt=$itp - uci set modem.modem$CURRMODEM.mauth=$auth - uci set modem.modem$CURRMODEM.musername=$username - uci set modem.modem$CURRMODEM.mpassword=$password - uci commit modem - - tid=$((tid + 1)) - - log "Get IP config" - CONFIG=$(umbim $DBG -n -t $tid -d $device config) || { - log "config failed" - return 1 - } - - IP=$(echo -e "$CONFIG"|grep "ipv4address"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") - GATE=$(echo -e "$CONFIG"|grep "ipv4gateway"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") - DNS1=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 1p) - DNS2=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 2p) - if [ $enb = "1" ]; then - IP6=$(echo "$CONFIG" | awk '/ipv6address:/ {print $2}' | cut -d / -f 1) - DNS3=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 1p) - DNS4=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 2p) - fi - echo "$GATE" > /tmp/mbimgateway - - [ -n "$IP" ] && echo "IP: $IP" - [ -n "$DNS1" ] && echo "DNS1: $DNS1" - [ -n "$DNS2" ] && echo "DNS2: $DNS2" - if [ $enb = "1" ]; then - [ -n "$IP6" ] && echo "IPv6: $IP6" - [ -n "$DNS3" ] && echo "DNS3: $DNS3" - [ -n "$DNS4" ] && echo "DNS4: $DNS4" - fi - - log "Connected, setting IP" - - if [ $enb = "1" ]; then - if [ -n "$IP6" -a -z "$IP" ]; then - log "Running IPv6-only mode" - nat46=1 - fi - - if [[ $(echo "$IP6" | grep -o "^[23]") ]]; then - # Global unicast IP acquired - v6cap=1 - elif - [[ $(echo "$IP6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then - # non-routable address - v6cap=2 - else - v6cap=0 - fi - fi - - INTER=$(uci get modem.modem$CURRMODEM.inter) - if [ -e /tmp/v4dns$INTER -o -e /tmp/v6dns$INTER ]; then - pdns=1 - if [ -e /tmp/v4dns$INTER ]; then - v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null) - fi - if [ $enb = "1" ]; then - if [ -e /tmp/v6dns$INTER ]; then - v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null) - fi - fi - else - v4dns="$DNS1 $DNS2" - if [ $enb = "1" ]; then - v6dns="$DNS3 $DNS4" - fi - fi - - proto_init_update "$ifname" 1 - - if [ -n "$IP" ]; then - proto_add_ipv4_address $IP "255.255.255.255" - proto_add_ipv4_route "0.0.0.0" 0 - fi - - for DNSV in $(echo "$v4dns"); do - proto_add_dns_server "$DNSV" - done - - if [ $enb = "1" ]; then - if [ "$v6cap" -gt 0 ]; then - # RFC 7278: Extend an IPv6 /64 Prefix to LAN - proto_add_ipv6_address $IP6 128 - if [ "$v6cap" = 1 ]; then - proto_add_ipv6_prefix $IP6/64 - proto_add_ipv6_route "::0" 0 "" "" "" $IP6/64 - for DNSV in $(echo "$v6dns"); do - proto_add_dns_server "$DNSV" - done - fi - fi - fi - - proto_add_data - json_add_string zone wan - proto_close_data - - proto_send_update "$interface" - - if [ $enb = "1" ]; then - if [ "$v6cap" -gt 0 ]; then - local zone="$(fw3 -q network "$interface" 2>/dev/null)" - fi - if [ "$v6cap" = 2 ]; then - log "Adding IPv6 dynamic interface" - json_init - json_add_string name "${interface}_6" - json_add_string ${ifname1} "@$interface" - json_add_string proto "dhcpv6" - json_add_string extendprefix 1 - [ -n "$zone" ] && json_add_string zone "$zone" - [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 - json_add_boolean peerdns 0 - json_add_array dns - for DNSV in $(echo "$v6dns"); do - json_add_string "" "$DNSV" - done - json_close_array - proto_add_dynamic_defaults - json_close_object - ubus call network add_dynamic "$(json_dump)" - elif - [ "$v6cap" = 1 -a "$nat46" = 1 ]; then - log "Adding 464XLAT (CLAT) dynamic interface" - json_init - json_add_string name "CLAT$INTER" - json_add_string proto "464xlat" - json_add_string tunlink "${interface}" - [ -n "$zone" ] && json_add_string zone "$zone" - proto_add_dynamic_defaults - json_close_object - ubus call network add_dynamic "$(json_dump)" - fi - fi - - tid=$((tid + 1)) - uci_set_state network $interface tid "$tid" -# SIGNAL=$(umbim $DBG -n -t $tid -d $device signal) -# CSQ=$(echo "$SIGNAL" | awk '/rssi:/ {print $2}') - - if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 3 - fi - - $ROOTER/log/logger "Modem #$CURRMODEM Connected" - log "Modem $CURRMODEM Connected" - - IDP=$(uci get modem.modem$CURRMODEM.idP) - IDV=$(uci get modem.modem$CURRMODEM.idV) - - if [ ! -s /tmp/msimdata$CURRMODEM ]; then - echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM - echo "$IMEI" >> /tmp/msimdatax$CURRMODEM - echo "$IMSI" >> /tmp/msimdatax$CURRMODEM - echo "$ICCID" >> /tmp/msimdatax$CURRMODEM - echo "1" >> /tmp/msimdatax$CURRMODEM - mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM - fi - - if [ ! -s /tmp/msimnum$CURRMODEM ]; then - echo "$CNUM" > /tmp/msimnumx$CURRMODEM - echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM - mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM - fi - - uci set modem.modem$CURRMODEM.custom=$CUSTOM - uci set modem.modem$CURRMODEM.provider=$PROV - uci set modem.modem$CURRMODEM.down=$DOWN" kbps Down | " - uci set modem.modem$CURRMODEM.up=$UP" kbps Up" - uci set modem.modem$CURRMODEM.mcc=$MCC - uci set modem.modem$CURRMODEM.mnc=" "$MNC - uci set modem.modem$CURRMODEM.sig="--" - uci set modem.modem$CURRMODEM.sms=0 - uci commit modem - - COMMPORT=$(uci get modem.modem$CURRMODEM.commport) - if [ -z $COMMPORT ]; then - ln -s $ROOTER/mbim/mbimdata.sh $ROOTER_LINK/getsignal$CURRMODEM - else - $ROOTER/sms/check_sms.sh $CURRMODEM & - ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM - # send custom AT startup command - if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then - ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) - if [ ! -z "${ATCMDD}" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - log "Error sending custom AT command: $ATCMDD with result: $OX" - else - log "Sent custom AT command: $ATCMDD with result: $OX" - fi - fi - fi - fi - ln -s $ROOTER/connect/reconnect.sh $ROOTER_LINK/reconnect$CURRMODEM - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM - $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & - #ln -s $ROOTER/mbim/monitor.sh $ROOTER_LINK/mbim_monitor$CURRMODEM - #$ROOTER_LINK/mbim_monitor$CURRMODEM $CURRMODEM $device & - - uci set modem.modem$CURRMODEM.connected=1 - uci commit modem - - if [ -e $ROOTER/connect/postconnect.sh ]; then - $ROOTER/connect/postconnect.sh $CURRMODEM - fi - - if [ -e $ROOTER/timezone.sh ]; then - TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) - if [ "$TZ" = "1" ]; then - $ROOTER/timezone.sh & - fi - fi - #CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) - CLB=1 - if [ -e /etc/config/mwan3 ]; then - INTER=$(uci get modem.modeminfo$CURRMODEM.inter) - if [ -z $INTER ]; then - INTER=0 - else - if [ $INTER = 0 ]; then - INTER=$CURRMODEM - fi - fi - ENB=$(uci -q get mwan3.wan$CURRMODEM.enabled) - if [ ! -z $ENB ]; then - if [ $CLB = "1" ]; then - uci set mwan3.wan$INTER.enabled=1 - else - uci set mwan3.wan$INTER.enabled=0 - fi - uci commit mwan3 - /usr/sbin/mwan3 restart - fi - fi - rm -f /tmp/usbwait - - return 0 -} - -proto_mbim_setup() { - - local ret - _proto_mbim_setup $@ - ret=$? - - [ "$ret" = 0 ] || { - log "MBIM bringup failed, retry in 5s" - CPORT=$(uci get modem.modem$CURRMODEM.commport) - ATCMDD="AT+COPS=0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - #log "Restart Modem" - #/usr/lib/rooter/luci/restart.sh $CURRMODEM - sleep 5 - } - - exit 0 - return $ret -} - -proto_mbim_teardown() { - local interface="$1" - - local device - json_get_vars device - local tid=$(uci_get_state network $interface tid) - - [ -n "$ctl_device" ] && device=$ctl_device - - if [ -n "$device" ]; then - log "Stopping network" - if [ -n "$tid" ]; then - tid=$((tid + 1)) - umbim $DBG -t $tid -d "$device" disconnect - uci_revert_state network $interface tid - else - umbim $DBG -d "$device" disconnect - fi - fi - - proto_init_update "*" 0 - proto_send_update "$interface" - -} - -[ -n "$INCLUDE_ONLY" ] || add_protocol mbim diff --git a/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh b/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh deleted file mode 100644 index 41f6f10..0000000 --- a/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/mbimdata.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK=$ROOTER"/links" - -log() { - logger -t "MBIM Data" "$@" -} - -STARTIMEX=$(date +%s) -MONSTAT= -rm -f /tmp/monstat$CURRMODEM - -build_status() { - CSQ=$signal - if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then - CSQ_PER=$(($CSQ * 100/31)) - CSQ_RSSI=$((2 * CSQ - 113)) - CSQX=$CSQ_RSSI - [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI - [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI - CSQ_PER=$CSQ_PER"%" - CSQ_RSSI=$CSQ_RSSI" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi - echo "-" > /tmp/status$CURRMODEM.file - echo "$CSQ" >> /tmp/status$CURRMODEM.file - echo "$CSQ_PER" >> /tmp/status$CURRMODEM.file - echo "$CSQ_RSSI" >> /tmp/status$CURRMODEM.file - echo "$manuf" >> /tmp/status$CURRMODEM.file - echo "$provider" >> /tmp/status$CURRMODEM.file - echo "$cellmode" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$mcc" >> /tmp/status$CURRMODEM.file - echo "$mnc" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$down" >> /tmp/status$CURRMODEM.file - echo "$up" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo "$MONSTAT" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$conn" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "MBIM" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file -} - -CURRMODEM=$1 - -conn="Modem #"$CURRMODEM -custom=$(uci get modem.modem$CURRMODEM.custom) -port=$(uci get modem.modem$CURRMODEM.wdm) -netd=$(uci get modem.modem$CURRMODEM.wwan) -manuf=$(uci get modem.modem$CURRMODEM.manuf) -model=$(uci get modem.modem$CURRMODEM.model) -mcc=$(uci get modem.modem$CURRMODEM.mcc) -mnc=$(uci get modem.modem$CURRMODEM.mnc) -up=$(uci get modem.modem$CURRMODEM.up) -down=$(uci get modem.modem$CURRMODEM.down) -provider=$(uci get modem.modem$CURRMODEM.provider) -cellmode=$(uci get modem.modem$CURRMODEM.mode) -if [ $cellmode = "CUSTOM" ]; then - cellmode=$custom -fi -signal=$(uci get modem.modem$CURRMODEM.sig) - -device="/dev/cdc-wdm"$port -netdev="wwan"$netd -manuf=$manuf" "$model - -tid=2 -while [ 1 -eq 1 ]; do - tid=2 - #SIGNAL=$(umbim -n -t $tid -d $device signal) - tid=$((tid + 1)) - #SIGNAL=$(umbim -n -t $tid -d $device signal) - signal=0 - if [ -e /tmp/monstat$CURRMODEM ]; then - source /tmp/monstat$CURRMODEM - fi - if [ -z $MONSTAT ]; then - MONSTAT="Unknown" - fi - build_status - if [ -e /etc/netspeed ]; then - NETSPEED=60 - else - NETSPEED=10 - fi - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - while [ $ELAPSE -lt $NETSPEED ]; do - sleep 2 - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - done - STARTIMEX=$CURRTIME -done diff --git a/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh b/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh deleted file mode 100644 index 0e84aec..0000000 --- a/rooter/0drivers/rmbim/files/usr/lib/rooter/mbim/monitor.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -ROOTER_LINK="/tmp/links" - -log() { - logger -t "MBIM Monitor" "$@" -} - -CURRMODEM=$1 -DEVICE=$2 - -while :; do - tid=$(uci_get_state network wan$CURRMODEM tid) - tid=$((tid + 1)) - umbim -d $DEVICE -n -t $tid status >/dev/null - retq=$? - uci_toggle_state network wan$CURRMODEM tid $tid - [ $retq -ne 0 ] && break - sleep 10 -done - -case $retq in -2) - error="activation state: activating" - ;; -3) - error="activation state: deactivated" - ;; -4) - error="activation state: deactivating" - ;; -255) - error="MBIM message not long enough" - ;; -esac - -log "Modem $CURRMODEM Connection is Down ($error)" -if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then - $ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM & -fi - -# wait to be killed by mbim.sh -sleep 60 diff --git a/rooter/0drivers/rqmi/Makefile b/rooter/0drivers/rqmi/Makefile deleted file mode 100644 index a69b892..0000000 --- a/rooter/0drivers/rqmi/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=uqmi -PKG_RELEASE:=$(AUTORELEASE) - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git -PKG_SOURCE_DATE:=2021-11-06 -PKG_SOURCE_VERSION:=6f956265167945267d676c99f123a8c822f0a77b -PKG_MIRROR_HASH:=1dbe14a28ec59b364dbde5dea9e10ed1c5c3eda274b6c7690c793a06643acf3e -PKG_MAINTAINER:=Matti Laakso - -PKG_LICENSE:=GPL-2.0 -PKG_LICENSE_FILES:= - -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/cmake.mk - -define Package/rqmi - SECTION:=net - CATEGORY:=ROOter - SUBMENU:=Drivers - DEPENDS:=+libubox +libblobmsg-json +kmod-usb-net +kmod-usb-net-qmi-wwan +wwan - TITLE:=Control utility for mobile broadband modems -endef - -define Package/rqmi/description - uqmi is a command line tool for controlling mobile broadband modems using - the QMI-protocol. -endef - -TARGET_CFLAGS += \ - -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections - -TARGET_LDFLAGS += -Wl,--gc-sections - -CMAKE_OPTIONS += \ - -DDEBUG=1 - -define Package/rqmi/install - $(INSTALL_DIR) $(1)/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/uqmi $(1)/sbin/ - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,rqmi)) diff --git a/rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh b/rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh deleted file mode 100644 index e3c4cbf..0000000 --- a/rooter/0drivers/rqmi/files/usr/lib/rooter/qmi/connectqmi.sh +++ /dev/null @@ -1,301 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "QMI Connect $CURRMODEM" "$@" -} - - . /lib/functions.sh - . /lib/netifd/netifd-proto.sh - -CURRMODEM=$1 -devname=$2 -device=/dev/$2 -auth=$3 -NAPN=$4 -username=$5 -password=$6 -RAW=$7 -DHCP=$8 -pincode=$9 - -enb=$(uci -q get custom.connect.ipv6) -if [ -z $enb ]; then - enb="1" -fi - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -INTER=$(uci -q get modem.modem$CURRMODEM.inter) -interface="wan"$INTER - -case $auth in - "0" ) - auth="none" - ;; - "1" ) - auth="pap" - ;; - "2" ) - auth="chap" - ;; - *) - auth="none" - ;; -esac - -if [ $username = NIL ]; then - username= -fi -if [ $password = NIL ]; then - password= -fi - -ifname="$(ls /sys/class/usbmisc/$devname/device/net/)" - -#while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do -# sleep 1; -#done - -[ -n "$pincode" ] && { - uqmi -s -d "$device" --verify-pin1 "$pincode" || { - log "Unable to verify PIN" - ret=1 - } -} - -uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 5 ; kill -9 $! -uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1 & sleep 5 ; kill -9 $! - -if [ $RAW -eq 1 ]; then - DATAFORM='"raw-ip"' -else - if [ $idV = 1199 -a $idP = 9055 ]; then - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" - DATAFORM='"802.3"' - uqmi -s -d "$device" --set-data-format 802.3 - uqmi -s -d "$device" --wda-set-data-format 802.3 - else - log "getting data format" - DATAFORM=$(uqmi -s -d "$device" --wda-get-data-format) - fi -fi - -log "WDA-GET-DATA-FORMAT is $DATAFORM" -if [ "$DATAFORM" = '"raw-ip"' ]; then - [ -f /sys/class/net/$ifname/qmi/raw_ip ] || { - log "Device only supports raw-ip mode but is missing this required driver attribute: /sys/class/net/$ifname/qmi/raw_ip" - ret=1 - } - echo "Y" > /sys/class/net/$ifname/qmi/raw_ip -fi - -log "Query radio state" -uqmi -s -d "$device" --get-signal-info | grep -q "Information unavailable" & sleep 5 ; kill -9 $! -STATUS=$? - -[ "$STATUS" -ne 0 ] || { - sleep 1 - log "Setting FCC Auth" - uqmi -s -d "$device" --fcc-auth & sleep 5 ; kill -9 $! - sleep 1 - } - -uqmi -s -d "$device" --sync > /dev/null 2>&1 & sleep 5 ; kill -9 $! - -#uqmi -s -d "$device" --network-register > /dev/null 2>&1 - -log "Waiting for network registration" -td=0 -while uqmi -s -d "$device" --get-serving-system | grep '"searching"' > /dev/null; do - sleep 5; - tid=$((tid + 1)) - if [ $tid -gt 2 ]; then - uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 10 ; kill -9 $! - exit 1 - fi -done - -cid=`uqmi -s -d "$device" --get-client-id wds` -[ $? -ne 0 ] && { - log "Unable to obtain client ID" - ret=1 -} - -uqmi -s -d "$device" --set-client-id wds,"$cid" --set-ip-family ipv4 > /dev/null - -isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist) -apn2=$(uci -q get modem.modeminfo$CURRMODEM.apn2) -for isp in $isplist - do - NAPN=$(echo $isp | cut -d, -f2) - NPASS=$(echo $isp | cut -d, -f4) - CID=$(echo $isp | cut -d, -f5) - NUSER=$(echo $isp | cut -d, -f6) - NAUTH=$(echo $isp | cut -d, -f7) - if [ "$NPASS" = "nil" ]; then - NPASS="NIL" - fi - if [ "$NUSER" = "nil" ]; then - NUSER="NIL" - fi - if [ "$NAUTH" = "nil" ]; then - NAUTH="0" - fi - username="$NUSER" - password="$NPASS" - auth=$NAUTH - case $auth in - "0" ) - auth="none" - ;; - "1" ) - auth="pap" - ;; - "2" ) - auth="chap" - ;; - "*" ) - auth="none" - ;; - esac - - if [ ! -e /etc/config/isp ]; then - log "Connect to network using $NAPN" - else - log "Connect to network" - fi - - if [ ! -e /etc/config/isp ]; then - log "$NAPN $auth $username $password" - fi - - conn=0 - tidd=0 - tcnt=4 - while true; do - ST=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --start-network ${NAPN:+--apn $NAPN} ${auth:+--auth-type $auth} \ - ${username:+--username $username} ${password:+--password $password}) - log "Connection returned : $ST" - CONN=$(uqmi -s -d "$device" --get-data-status) - log "Status is $CONN" - if [[ $(echo "$CONN" | grep -o "disconnected") ]]; then - sleep 1 - tidd=$((tidd + 1)) - if [ $tidd -gt $tcnt ]; then - break - fi - else - conn=1 - break - fi - done - if [ $conn -eq 1 ]; then - break; - fi - done - -if [[ -z $(echo "$CONN" | grep -o "disconnected") ]]; then - ret=0 - - uci set modem.modem$CURRMODEM.mdevice=$device - uci set modem.modem$CURRMODEM.mcid=$cid - uci set modem.modem$CURRMODEM.mapn=$NAPN - uci set modem.modem$CURRMODEM.mauth=$auth - uci set modem.modem$CURRMODEM.musername=$username - uci set modem.modem$CURRMODEM.mpassword=$password - uci commit modem - - CONN4=$(uqmi -s -d "$device" --set-client-id wds,"$cid" --get-current-settings) - log "GET-CURRENT-SETTINGS is $CONN4" - - if [ $enb = "1" ]; then - cid6=`uqmi -s -d "$device" --get-client-id wds` - [ $? -ne 0 ] && { - log "Unable to obtain client ID" - ret=1 - } - - uqmi -s -d "$device" --set-client-id wds,"$cid6" --set-ip-family ipv6 > /dev/null - ST6=$(uqmi -s -d "$device" --set-client-id wds,"$cid6" --start-network ${NAPN:+--apn $NAPN} ${auth:+--auth-type $auth} \ - ${username:+--username $username} ${password:+--password $password}) - log "IPv6 Connection returned : $ST6" - CONN6=$(uqmi -s -d "$device" --set-client-id wds,"$cid6" --get-current-settings) - CONF6=$(jsonfilter -s $CONN6 -e '@.ipv6') - if [ -n "$CONF6" ];then - log "IPv6 settings are $CONF6" - touch /tmp/ipv6supp$INTER - else - rm -f /tmp/ipv6supp$INTER - fi - fi - - if [ $DATAFORM = '"raw-ip"' ]; then - log "Handle raw-ip" - json_load "$CONN4" - json_select ipv4 - json_get_vars ip subnet gateway dns1 dns2 - if [ $enb = "1" ]; then - if [ -n "$CONF6" ]; then - json_load "$CONN6" - json_select ipv6 - json_get_var ip_6 ip - json_get_var gateway_6 gateway - json_get_var dns1_6 dns1 - json_get_var dns2_6 dns2 - json_get_var ip_prefix_length ip-prefix-length - fi - fi - - if [ -s /tmp/v4dns$INTER -o -s /tmp/v6dns$INTER ]; then - pdns=1 - if [ -s /tmp/v4dns$INTER ]; then - v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null) - fi - if [ $enb = "1" ]; then - if [ -s /tmp/v6dns$INTER ]; then - v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null) - fi - fi - else - v4dns="$dns1 $dns2" - if [ $enb = "1" ]; then - v6dns="$dns1_6 $dns2_6" - echo "$v6dns" > /tmp/v6dns$INTER - fi - fi - - if [ $DHCP -eq 0 ]; then - log Applying IP settings to wan$INTER - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=static - uci set network.wan$INTER.${ifname1}=$ifname - uci set network.wan$INTER.metric=$INTER"0" - uci set network.wan$INTER.ipaddr=$ip/$subnet - uci set network.wan$INTER.gateway='0.0.0.0' - uci set network.wan$INTER.dns="$v4dns" - uci commit network - uci set modem.modem$CURRMODEM.interface=$ifname - uci commit modem - else - proto_init_update "$ifname" 1 - proto_set_keep 1 - proto_add_ipv4_address "$ip" "$subnet" - proto_add_ipv4_route "0.0.0.0" 0 - for DNSV in $(echo "$v4dns"); do - proto_add_dns_server "$DNSV" - done - proto_send_update "$interface" - fi - fi -else - uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 10 ; kill -9 $! - ret=1 -fi - -exit $ret diff --git a/rooter/0optionalapps/bwallocate/Makefile b/rooter/0optionalapps/bwallocate/Makefile deleted file mode 100644 index 183c85d..0000000 --- a/rooter/0optionalapps/bwallocate/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=bwallocate -PKG_VERSION:=4.500 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/bwallocate - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - DEPENDS:=+ext-throttle +msmtp - TITLE:=Install scripts for Bandwidth Allocation - PKGARCH:=all -endef - -define Package/bwallocate/description - Install scripts for Bandwidth Allocation -endef - - -define Build/Compile -endef - -define Package/bwallocate/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,bwallocate)) diff --git a/rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint b/rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint deleted file mode 100644 index b74e85a..0000000 --- a/rooter/0optionalapps/bwallocate/files/etc/init.d/textbwint +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=88 - -log() { - logger -t "TEXTING" "$@" -} - -start() -{ - uci set bwmon.general.enabled="1" - uci commit bwmon - /usr/lib/bwmon/textbw.sh & -} diff --git a/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua b/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua deleted file mode 100644 index a26d6fd..0000000 --- a/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/controller/bwallocate.lua +++ /dev/null @@ -1,22 +0,0 @@ -module("luci.controller.bwallocate", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local lock = luci.model.uci.cursor():get("custom", "menu", "full") - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - if lock == "1" then - local lock1 = luci.model.uci.cursor():get("custom", "bwallocate", "lock") - if lock1 == "1" then - if (multilock == "1" and rootlock == "1") then - entry({"admin", "adminmenu", "bwmenu"}, cbi("fullmenu/bwmenu"), translate("Bandwidth Allocation"), 6) - else - entry({"admin", "adminmenu", "bwmenu"}, cbi("fullmenu/bwmenu"), translate("---Bandwidth Allocation"), 6) - end - end - end - end -end \ No newline at end of file diff --git a/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua b/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua deleted file mode 100644 index 9fcc8d9..0000000 --- a/rooter/0optionalapps/bwallocate/files/usr/lib/lua/luci/model/cbi/fullmenu/bwmenu.lua +++ /dev/null @@ -1,267 +0,0 @@ -local utl = require "luci.util" - -m = Map("custom", translate("Bandwidth Allocation"), translate("Set Maximum Bandwidth Usage before Internet blockage")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/bwmon/allocate.sh 0 &") -end - -s = m:section(TypedSection, "bwallocate", translate("Allocation Settings")) -s.anonymous = true -s.addremove = false - -s:option(Flag, "enabled", translate("Allocation Enabled : ")) - -maxim = s:option(Value, "allocate", translate("Maximum Bandwidth in GB : "), translate("Maximum amount of bandwidth that can be used before Internet is affected")); -maxim.rmempty = true; -maxim.optional=false; -maxim.default="1000"; -maxim.datatype = "and(uinteger,min(1))" - -rollover = s:option(ListValue, "rollover", translate("Rollover Day : "), translate("Day of the month when bandwidth usage resets")) -rollover.rmempty = true -rollover:value("1", "1st") -rollover:value("2", "2nd") -rollover:value("3", "3rd") -rollover:value("4", "4th") -rollover:value("5", "5th") -rollover:value("6", "6th") -rollover:value("7", "7th") -rollover:value("8", "8th") -rollover:value("9", "9th") -rollover:value("10", "10th") -rollover:value("11", "11th") -rollover:value("12", "12th") -rollover:value("13", "13th") -rollover:value("14", "14th") -rollover:value("15", "15th") -rollover:value("16", "16th") -rollover:value("17", "17th") -rollover:value("18", "18th") -rollover:value("19", "19th") -rollover:value("20", "20th") -rollover:value("21", "21th") -rollover:value("22", "22th") -rollover:value("23", "23th") -rollover:value("24", "24th") -rollover:value("25", "25th") -rollover:value("26", "26th") -rollover:value("27", "27th") -rollover:value("28", "28th") -rollover.default = "1" - -act = s:option(ListValue, "action", translate("Internet Action : "), translate("Action taken when allocation is exceeded")) -act.rmempty = true -act:value("0", "Internet Blocked") -act:value("1", "Internet Throttled") -act.default = "0" - -down = s:option(Value, "down", translate("Download Speed in Mbps :")); -down.optional=false; -down.rmempty = true; -down.datatype = "and(uinteger,min(1),max(999))" -down:depends("action", "1") -down.default = "5" - -up = s:option(Value, "up", translate("Upload Speed in Mbps :")); -up.optional=false; -up.rmempty = true; -up.datatype = "and(uinteger,min(1),max(999))" -up:depends("action", "1") -up.default = "2" - -s = m:section(TypedSection, "texting", translate("Text/Email Settings")) -s.anonymous = true -s.addremove = false - -aact = s:option(ListValue, "text", translate("Enable : "), translate("Enable Sending Text or Email Information")) -aact.rmempty = true -aact:value("0", "No") -aact:value("1", "Yes") -aact.default = "0" - - -pph = s:option(Value, "ident", translate("Identifier :")); -pph.optional=false; -pph.rmempty = true; -pph:depends("text", "1") -pph.default = "xxx" - - - -ct = s:option(ListValue, "method", translate("Criteria : "), translate("Criteria used to determine when to send information")) -ct.rmempty = true -ct:value("0", translate("By Specified Time Interval")) -ct:value("1", translate("By Amount Used")) -ct:value("2", translate("By Percentage Used")) -ct.default = "0" -ct:depends("text", "1") - -sdhour = s:option(ListValue, "time", translate("Sending Time :"), translate("Time to send information")) -sdhour.rmempty = true -sdhour:value("0", "12:00 AM") -sdhour:value("1", "12:15 AM") -sdhour:value("2", "12:30 AM") -sdhour:value("3", "12:45 AM") -sdhour:value("4", "01:00 AM") -sdhour:value("5", "01:15 AM") -sdhour:value("6", "01:30 AM") -sdhour:value("7", "01:45 AM") -sdhour:value("8", "02:00 AM") -sdhour:value("9", "02:15 AM") -sdhour:value("10", "02:30 AM") -sdhour:value("11", "02:45 AM") -sdhour:value("12", "03:00 AM") -sdhour:value("13", "03:15 AM") -sdhour:value("14", "03:30 AM") -sdhour:value("15", "03:45 AM") -sdhour:value("16", "04:00 AM") -sdhour:value("17", "04:15 AM") -sdhour:value("18", "04:30 AM") -sdhour:value("19", "04:45 AM") -sdhour:value("20", "05:00 AM") -sdhour:value("21", "05:15 AM") -sdhour:value("22", "05:30 AM") -sdhour:value("23", "05:45 AM") -sdhour:value("24", "06:00 AM") -sdhour:value("25", "06:15 AM") -sdhour:value("26", "06:30 AM") -sdhour:value("27", "06:45 AM") -sdhour:value("28", "07:00 AM") -sdhour:value("29", "07:15 AM") -sdhour:value("30", "07:30 AM") -sdhour:value("31", "07:45 AM") -sdhour:value("32", "08:00 AM") -sdhour:value("33", "08:15 AM") -sdhour:value("34", "08:30 AM") -sdhour:value("35", "08:45 AM") -sdhour:value("36", "09:00 AM") -sdhour:value("37", "09:15 AM") -sdhour:value("38", "09:30 AM") -sdhour:value("39", "09:45 AM") -sdhour:value("40", "10:00 AM") -sdhour:value("41", "10:15 AM") -sdhour:value("42", "10:30 AM") -sdhour:value("43", "10:45 AM") -sdhour:value("44", "11:00 AM") -sdhour:value("45", "11:15 AM") -sdhour:value("46", "11:30 AM") -sdhour:value("47", "11:45 AM") -sdhour:value("48", "12:00 PM") -sdhour:value("49", "12:15 PM") -sdhour:value("50", "12:30 PM") -sdhour:value("51", "12:45 PM") -sdhour:value("52", "01:00 PM") -sdhour:value("53", "01:15 PM") -sdhour:value("54", "01:30 PM") -sdhour:value("55", "01:45 PM") -sdhour:value("56", "02:00 PM") -sdhour:value("57", "02:15 PM") -sdhour:value("58", "02:30 PM") -sdhour:value("59", "02:45 PM") -sdhour:value("60", "03:00 PM") -sdhour:value("61", "03:15 PM") -sdhour:value("62", "03:30 PM") -sdhour:value("63", "03:45 PM") -sdhour:value("64", "04:00 PM") -sdhour:value("65", "04:15 PM") -sdhour:value("66", "04:30 PM") -sdhour:value("67", "04:45 PM") -sdhour:value("68", "05:00 PM") -sdhour:value("69", "05:15 PM") -sdhour:value("70", "05:30 PM") -sdhour:value("71", "05:45 PM") -sdhour:value("72", "06:00 PM") -sdhour:value("73", "06:15 PM") -sdhour:value("74", "06:30 PM") -sdhour:value("75", "06:45 PM") -sdhour:value("76", "07:00 PM") -sdhour:value("77", "07:15 PM") -sdhour:value("78", "07:30 PM") -sdhour:value("79", "07:45 PM") -sdhour:value("80", "08:00 PM") -sdhour:value("81", "08:15 PM") -sdhour:value("82", "08:30 PM") -sdhour:value("83", "08:45 PM") -sdhour:value("84", "09:00 PM") -sdhour:value("85", "09:15 PM") -sdhour:value("86", "09:30 PM") -sdhour:value("87", "09:45 PM") -sdhour:value("88", "10:00 PM") -sdhour:value("89", "10:15 PM") -sdhour:value("90", "10:30 PM") -sdhour:value("91", "10:45 PM") -sdhour:value("92", "11:00 PM") -sdhour:value("93", "11:15 PM") -sdhour:value("94", "11:30 PM") -sdhour:value("95", "11:45 PM") -sdhour:depends("text", "1") -sdhour.default = "48" - -xct = s:option(ListValue, "days", translate("Interval : "), translate("Number of days between sending information")) -xct.rmempty = true -xct:value("1", translate("Every Day")) -xct:value("2", translate("Every 2 Days")) -xct:value("5", translate("Every 5 Days")) -xct:value("10", translate("Every 10 Days")) -xct:value("15", translate("Every 15 Days")) -xct.default = "5" -xct:depends("method", "0") - -xxct = s:option(ListValue, "increment", translate("Increment : "), translate("Amount Used between sending information")) -xxct.rmempty = true -xxct:value("50", translate("Every 50 GB")) -xxct:value("75", translate("Every 75 GB")) -xxct:value("100", translate("Every 100 GB")) -xxct.default = "50" -xxct:depends("method", "1") - -ph1 = s:option(ListValue, "percent", translate("Percentage Used :")); -ph1.optional=false; -ph1.rmempty = true; -ph1:value("10", translate("10%")) -ph1:value("20", translate("20%")) -ph1:value("30", translate("30%")) -ph1:value("40", translate("40%")) -ph1:value("50", translate("50%")) -ph1:value("60", translate("60%")) -ph1:value("70", translate("70%")) -ph1:value("80", translate("80%")) -ph1:value("90", translate("90%")) -ph1:depends("method", "2") -ph1.default = "90" - ---b3 = s:option(DummyValue, "blank", " "); - -btn = s:option(Button, "_btn", translate(" ")) -btn.inputtitle = translate("Send Test of Text or Email") -btn.inputstyle = "apply" -btn:depends("text", "1") -function btn.write() - luci.sys.call("/usr/lib/bwmon/dotext.sh &") -end - -b4 = s:option(DummyValue, "blank", " "); - -ct = s:option(ListValue, "tore", translate("Sending Method : "), translate("Method used to send information")) -ct.rmempty = true -ct:value("0", translate("By Text")) -ct:value("1", translate("By Email")) -ct.default = "0" -ct:depends("text", "1") - -ph = s:option(Value, "phone", translate("Phone Number :")); -ph.optional=false; -ph.rmempty = true; -ph.datatype = "phonedigit" -ph:depends("tore", "0") -ph.default = "12223334444" - -ph1 = s:option(Value, "email", translate("Email Address :")); -ph1.optional=false; -ph1.rmempty = true; -ph1:depends("tore", "1") -ph1.default = "jdoe@domain.com" - - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/Makefile b/rooter/0optionalapps/bwmon/Makefile deleted file mode 100644 index c413b2f..0000000 --- a/rooter/0optionalapps/bwmon/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=bwmon -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/bwmon - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Install Bandwidth Monitor - PKGARCH:=all -endef - -define Package/bwmon/description - Helper scripts to install Bandwidth Monitor on ROOter -endef - - -define Build/Compile -endef - -define Package/bwmon/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,bwmon)) diff --git a/rooter/0optionalapps/bwmon/files/etc/config/bwmon b/rooter/0optionalapps/bwmon/files/etc/config/bwmon deleted file mode 100644 index 9d45a80..0000000 --- a/rooter/0optionalapps/bwmon/files/etc/config/bwmon +++ /dev/null @@ -1,9 +0,0 @@ - -config general 'general' - option external '0' - option backup '30' - option enabled '1' - - -config bwwan 'bwwan' - option wan '0' \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/etc/init.d/bwmon b/rooter/0optionalapps/bwmon/files/etc/init.d/bwmon deleted file mode 100644 index 0dc2498..0000000 --- a/rooter/0optionalapps/bwmon/files/etc/init.d/bwmon +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=60 - -start() { - WX=$(uci -q get custom.bwallocate.lock) - if [ "$WX" = "1" ]; then - uci set bwmon.general.enabled=1 - uci commit bwmon - fi - /usr/lib/bwmon/wrtbwmon.sh & - /usr/lib/bwmon/create.sh & -} - -stop() { - rmdir -f /tmp/WRTbmon -} \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon b/rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon deleted file mode 100644 index c664559..0000000 --- a/rooter/0optionalapps/bwmon/files/lib/upgrade/keep.d/bwmon +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/bwmon/data/ diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh deleted file mode 100644 index 58b4c22..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/allocate.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -log() { - logger -t "allocate" "$@" -} - -amount=$1 - -if [ $amount != "0" ]; then - uci set custom.bwallocate.allocate=$amount - uci commit custom -else - sleep 3 -fi -result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` -while [ $result -ge 1 ]; do - sleep 2 - result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` -done - -lua /usr/lib/bwmon/create_data.lua diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua deleted file mode 100644 index f2f8a17..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/amtleft.lua +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/lua - -function ltrim(s) - return s:match'^%s*(.*)' -end - -function calc(total) - if total < 1000 then - tstr = string.format("%.2f", total) - tfm = " K" - else - if total < 1000000 then - tstr = string.format("%.2f", total/1000) - tfm = " MB" - else - tstr = string.format("%.2f", total/1000000) - tfm = " GB" - end - end - str = tstr .. tfm - return ltrim(str) -end - -aamt = arg[1] -uamt = arg[2] -if uamt > aamt then - amt = uamt - aamt - amts = calc(amt) - amts = "-" .. amts -else - amt = aamt - uamt - amts = calc(math.abs(amt)) -end -tfile = io.open("/tmp/amtleft", "w") -tfile:write(amts, "\n") -tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua deleted file mode 100644 index c9f579e..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-daily.lua +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/lua - -dailyUsageDB = arg[1] - -bw = {} -maclist = {} - -file = io.open(dailyUsageDB, "r") -i = 0 -repeat - line = file:read("*line") - if line == nil then - break - end - s, e = line:find("\"mac\":\"") - bs, be = line:find("\"", e+1) - mac = line:sub(e+1, bs-1) - if bw[mac] == nil then - maclist[i] = mac - i = i + 1 - bw[mac] = {} - bw[mac]['down'] = 0 - bw[mac]['offdown'] = 0 - bw[mac]['up'] = 0 - bw[mac]['offup'] = 0 - end - s, e = line:find("\"down\":\"") - bs, be = line:find("\"", e+1) - down = tonumber(line:sub(e+1, bs-1)) - bw[mac]['down'] = bw[mac]['down'] + down - s, e = line:find("\"up\":\"") - bs, be = line:find("\"", e+1) - up = tonumber(line:sub(e+1, bs-1)) - bw[mac]['up'] = bw[mac]['up'] + up - s, e = line:find("\"offdown\":\"") - bs, be = line:find("\"", e+1) - offdown = tonumber(line:sub(e+1, bs-1)) - bw[mac]['offdown'] = bw[mac]['offdown'] + offdown - s, e = line:find("\"offup\":\"") - bs, be = line:find("\"", e+1) - offup = tonumber(line:sub(e+1, bs-1)) - bw[mac]['offup'] = bw[mac]['offup'] + offup - s, e = line:find("\"ip\":\"") - bs, be = line:find("\"", e+1) - bw[mac]['ip'] = line:sub(e+1, bs-1) - s, e = line:find("\"name\":\"") - bs, be = line:find("\"", e+1) - bw[mac]['name'] = line:sub(e+1, bs-1) -until 1==0 -file:close() - -j=0 -file = io.open(dailyUsageDB .. ".bk", "w") -while maclist[j] ~= nil do - mac = maclist[j] - dline = "\"mac\":\"" .. mac .. "\",\"down\":\"" .. bw[mac]['down'] .. "\",\"up\":\"" .. bw[mac]['up'] .. "\",\"offdown\":\"0\",\"offup\":\"0\",\"ip\":\"" .. bw[mac]['ip'] .. "\",\"name\":\"" .. bw[mac]['name'] .. "\"" - file:write(dline, "\n") - j = j + 1 -end -file:close() - diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua deleted file mode 100644 index 5d8e883..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup-mon.lua +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/lua - -monthUsageDB = arg[1] - -tfile = io.open(monthUsageDB .. ".bk", "w") -tfile:close() - -file = io.open(monthUsageDB, "r") - -repeat - line = file:read("*line") - if line == nil then - break - end - s, e = line:find("start day") - if s ~= nil then - maclist = {} - bw = {} - i = 0 - startday = line - repeat - line = file:read("*line") - if line == nil then - break - end - s, e = line:find("end day") - if s ~= nil then - endday = line - break - end - s, e = line:find("\"mac\":\"") - bs, be = line:find("\"", e+1) - mac = line:sub(e+1, bs-1) - if bw[mac] == nil then - maclist[i] = mac - i = i + 1 - bw[mac] = {} - bw[mac]['down'] = 0 - bw[mac]['offdown'] = 0 - bw[mac]['up'] = 0 - bw[mac]['offup'] = 0 - end - s, e = line:find("\"down\":\"") - bs, be = line:find("\"", e+1) - down = tonumber(line:sub(e+1, bs-1)) - bw[mac]['down'] = bw[mac]['down'] + down - s, e = line:find("\"up\":\"") - bs, be = line:find("\"", e+1) - up = tonumber(line:sub(e+1, bs-1)) - bw[mac]['up'] = bw[mac]['up'] + up - s, e = line:find("\"offdown\":\"") - bs, be = line:find("\"", e+1) - offdown = tonumber(line:sub(e+1, bs-1)) - bw[mac]['offdown'] = bw[mac]['offdown'] + offdown - s, e = line:find("\"offup\":\"") - bs, be = line:find("\"", e+1) - offup = tonumber(line:sub(e+1, bs-1)) - bw[mac]['offup'] = bw[mac]['offup'] + offup - s, e = line:find("\"ip\":\"") - bs, be = line:find("\"", e+1) - bw[mac]['ip'] = line:sub(e+1, bs-1) - s, e = line:find("\"name\":\"") - bs, be = line:find("\"", e+1) - bw[mac]['name'] = line:sub(e+1, bs-1) - until 1==0 - -- day data - j=0 - tfile = io.open(monthUsageDB .. ".bk", "a") - tfile:write(startday, "\n") - while maclist[j] ~= nil do - mac = maclist[j] - dline = "\"mac\":\"" .. mac .. "\",\"down\":\"" .. bw[mac]['down'] .. "\",\"up\":\"" .. bw[mac]['up'] .. "\",\"offdown\":\"0\",\"offup\":\"0\",\"ip\":\"" .. bw[mac]['ip'] .. "\",\"name\":\"" .. bw[mac]['name'] .. "\"" - tfile:write(dline, "\n") - j = j + 1 - end - tfile:write(endday, "\n") - tfile:close() - end - -until 1==0 -file:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh deleted file mode 100644 index dba2368..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/backup.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh - -log() { - logger -t "wrtbwmon" "$@" -} - -# parameters -# -btype=$1 -cDay=$2 -monthlyUsageDB=$3 -dailyUsageDB=$4 -monthlyUsageBack=$5 -dailyUsageBack=$6 -pDay=$7 - -/usr/lib/bwmon/backup-daily.lua $dailyUsageDB -/usr/lib/bwmon/backup-mon.lua $monthlyUsageDB -cp -f $monthlyUsageDB".bk" $monthlyUsageDB -cp -f $dailyUsageDB".bk" $dailyUsageDB - -echo "start day $cDay" >> $monthlyUsageDB".bk" -cat $dailyUsageDB".bk" >> $monthlyUsageDB".bk" -echo "end day $cDay" >> $monthlyUsageDB".bk" - -enb=$(uci -q get bwmon.general.enabled) - -if [ $btype = "backup" ]; then - if [ "$enb" = "1" ]; then - cp -f $monthlyUsageDB".bk" $monthlyUsageBack - cp -f $dailyUsageDB".bk" $dailyUsageBack - fi -else - if [ $btype = "daily" ]; then - cp -f $monthlyUsageDB".bk" $monthlyUsageDB - if [ "$enb" = "1" ]; then - cp -f $monthlyUsageDB".bk" $monthlyUsageBack - fi - fi -fi - -rm -f $dailyUsageDB".bk" - -bwday=$(uci -q get modem.modeminfo1.bwday) -if [ ! -z "$bwday" ]; then - if [ $bwday = $pDay -a $bwday != "0" ]; then - if [ -e /usr/lib/bwmon/sendsms ]; then - /usr/lib/bwmon/sendsms.sh - fi - fi -fi \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block deleted file mode 100644 index ba7fb02..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/block +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -internet_block() -{ - enable=$1 - iptables -w -S ACCOUNTING_BLOCK > /tmp/iptables.block.$$ - if [ "$enable" = 1 ] - then - # insert the block rule - check=$(cat /tmp/iptables.block.$$ | grep -e "-m comment --comment internet_block -j DROP") - if [ -z "$check" ] - then - iptables -w -I ACCOUNTING_BLOCK -m comment --comment internet_block -j DROP 2>/dev/null - fi - else - # remove the block rule - count=$(cat /tmp/iptables.block.$$ | grep -e "-m comment --comment internet_block -j DROP" | wc -l) - for i in $(seq 1 $count) - do - iptables -w -D ACCOUNTING_BLOCK -m comment --comment internet_block -j DROP 2>/dev/null - done - fi - - rm -rf /tmp/iptables.block.$$ -} - -internet_block $1 - diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh deleted file mode 100644 index 003fec7..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/change.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -log() { - logger -t "wrtbwmon" "$@" -} - -enable=$1 - -WX=$(uci -q get custom.bwallocate.lock) -if [ "$WX" = "1" ]; then - enable="1" -fi -uci set bwmon.general.enabled=$enable -uci commit bwmon diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh deleted file mode 100644 index 20b3376..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/chksms.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -CURRMODEM=1 - -rm -f /tmp/texting -CPORT=$(uci -q get modem.modem$CURRMODEM.commport) -if [ -z $CPORT ]; then - return -fi -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "smschk.gcom" "$CURRMODEM") -ERROR="ERROR" -if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` -then - return -fi -echo "0" > /tmp/texting -uci set modem.general.smsnum='1' -uci commit modem \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua deleted file mode 100644 index 2c5d764..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/cleanup.lua +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/lua - -filepost = "-mac_data.js" -dirname = '/usr/lib/bwmon/data' - -function clean() - nummon = 0 - months = {} - f = io.popen('/bin/ls ' .. dirname) - for name in f:lines() do - s, e = name:find(filepost) - if s ~= nil then - nummon = nummon + 1 - months[nummon] = dirname .. "/" .. name - end - end - f:close() - - count = 1 - if nummon > 0 then - for i=nummon,1,-1 do - if count > 3 then - os.execute("rm -f " .. months[i]) - end - count = count + 1 - end - end -end - -clean() -dirname = '/tmp/bwmon/data' -clean() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh deleted file mode 100644 index 348d873..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -log() { - logger -t "createdata" "$@" -} - -lua /usr/lib/bwmon/create_data.lua -sleep 60 -while [ true ] -do - result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` - if [ $result -lt 1 ]; then - lua /usr/lib/bwmon/create_data.lua - fi - sleep 60 -done \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua deleted file mode 100644 index fc3fba8..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/create_data.lua +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/lua - -dirname = '/tmp/bwmon/data' -filepost = "-mac_data.js.bk" -bw = {} -maclist = {} -devices = {} -totaldevices = 0 -totaldown = 0 -totalup = 0 -total = 0 - -printf = function(s,...) - local ss = s:format(...) - os.execute("/usr/lib/rooter/logprint.sh " .. ss) -end - -function ltrim(s) - return s:match'^%s*(.*)' -end - -function calc(total) - if total < 1000 then - tstr = string.format("%.2f", total) - tfm = " K" - else - if total < 1000000 then - tstr = string.format("%.2f", total/1000) - tfm = " MB" - else - tstr = string.format("%.2f", total/1000000) - tfm = " GB" - end - end - str = tstr .. tfm - return ltrim(str) -end - -function monthly(datafile) - file = io.open(datafile, "r") - i = 0 - dayx = 0 - repeat - line = file:read("*line") - if line == nil then - break - end - s, e = line:find("start day") - if s ~= nil then - dayx = dayx + 1 - repeat - line = file:read("*line") - s, e = line:find("end day") - if s ~= nil then - break - end - s, e = line:find("\"mac\":\"") - bs, be = line:find("\"", e+1) - mac = line:sub(e+1, bs-1) - if bw[mac] == nil then - maclist[i] = mac - i = i + 1 - bw[mac] = {} - bw[mac]['down'] = 0 - bw[mac]['offdown'] = 0 - bw[mac]['up'] = 0 - bw[mac]['offup'] = 0 - end - s, e = line:find("\"down\":\"") - bs, be = line:find("\"", e+1) - down = tonumber(line:sub(e+1, bs-1)) - bw[mac]['down'] = bw[mac]['down'] + down - s, e = line:find("\"up\":\"") - bs, be = line:find("\"", e+1) - up = tonumber(line:sub(e+1, bs-1)) - bw[mac]['up'] = bw[mac]['up'] + up - s, e = line:find("\"offdown\":\"") - bs, be = line:find("\"", e+1) - offdown = tonumber(line:sub(e+1, bs-1)) - bw[mac]['offdown'] = bw[mac]['offdown'] + offdown - s, e = line:find("\"offup\":\"") - bs, be = line:find("\"", e+1) - offup = tonumber(line:sub(e+1, bs-1)) - bw[mac]['offup'] = bw[mac]['offup'] + offup - s, e = line:find("\"ip\":\"") - bs, be = line:find("\"", e+1) - bw[mac]['ip'] = line:sub(e+1, bs-1) - s, e = line:find("\"name\":\"") - bs, be = line:find("\"", e+1) - bw[mac]['name'] = line:sub(e+1, bs-1) - until 1==0 - end - until 1==0 - file:close() - return dayx -end - -function totals(bw, maclist, dayz) - totaldown = 0 - totalup = 0 - utotaldown = 0 - utotalup = 0 - j=0 - while maclist[j] ~= nil do - totaldown = totaldown + bw[maclist[j]]['down'] - totalup = totalup + bw[maclist[j]]['up'] - utotaldown = utotaldown + bw[maclist[j]]['offdown'] - utotalup = utotalup + bw[maclist[j]]['offup'] - j = j + 1 - end - total = totalup + totaldown - ptotal = (total / dayz) * 30 -end - -function showdevices(bw, maclist) - k = 0 - while maclist[k] ~= nil do - k = k + 1 - end - if k > 0 then - j = 0 - while maclist[j] ~= nil do - dtot = bw[maclist[j]]['down'] + bw[maclist[j]]['up'] - devices[j] = bw[maclist[j]]['ip'] .."|" .. maclist[j] - devices[j] = devices[j] .. "|" .. calc(bw[maclist[j]]['down']) .. "|" .. calc(bw[maclist[j]]['up']) - devices[j] = devices[j] .. "|" .. calc(dtot) .. "|" .. bw[maclist[j]]['name'] - j = j + 1 - end - end - totaldevices = j -end - -os.execute("echo 0 > /tmp/lockbw") -dataname = nil -f = io.popen('/bin/ls ' .. dirname) -for name in f:lines() do - s, e = name:find(filepost) - if s ~= nil then - dataname = dirname .. "/" .. name - end -end -f:close() - -if dataname ~= nil then - days = monthly(dataname) - totals(bw, maclist, days) - tfile = io.open("/tmp/bwdata", "w") - tfile:write(days, "\n") - tfile:write(tostring(total), "\n") - tfile:write(calc(total), "\n") - tfile:write(tostring(totaldown), "\n") - tfile:write(calc(totaldown), "\n") - tfile:write(tostring(totalup), "\n") - tfile:write(calc(totalup), "\n") - tfile:write(tostring(ptotal), "\n") - tfile:write(calc(ptotal), "\n") - -- - -- allocated bandwidth in K - -- - bwallo='rm -f /tmp/bwallo; x=$(uci -q get custom.bwallocate.allocate); echo $x >> /tmp/bwallo; x=$(uci -q get custom.bwallocate.password); echo $x >> /tmp/bwallo' - os.execute(bwallo) - file = io.open("/tmp/bwallo", "r") - if file == nil then - allo = 1000000000 - passw = "password" - else - allos = file:read("*line") - allo = tonumber(allos) * 1000000 - passw = file:read("*line") - file:close() - end - tfile:write(tostring(allo), "\n") - tfile:write(calc(allo), "\n") - tfile:write(passw, "\n") - - showdevices(bw, maclist) - tfile:write(tostring(totaldevices), "\n") - if totaldevices > 0 then - for i=0, totaldevices-1 do - tfile:write(devices[i], "\n") - end - end - tfile:close() -else - tfile = io.open("/tmp/bwdata", "w") - tfile:write("0\n") - tfile:write("0\n") - tfile:close() -end -os.execute("rm -f /tmp/lockbw") -os.execute("/usr/lib/bwmon/excede.sh " .. tostring(total) .. " " .. tostring(allo) .. " " .. tostring(ptotal)) -os.execute("/usr/lib/bwmon/savetot.sh \"" .. calc(total) .. "\"") -os.execute("/usr/lib/bwmon/perday.lua") diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder deleted file mode 100644 index c227083..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/data/placeholder +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua deleted file mode 100644 index 6ef57c4..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/datainc.lua +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/lua - -prev = arg[1] -- previous increment in GB -incr = arg[2] -- fixed increment in GB -used = arg[3] -- amt used in Kb - -used = used / 1000000 -- used in GB -current = prev + incr -running = "0" -if used >= current then - while used >= (current + incr) do - current = current + incr - end - prev = current - running = "1" -end - -tfile = io.open("/tmp/bwinc", "w") -tfile:write("prev=\"", prev, "\"\n") -tfile:write("runn=\"", running, "\"") -tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua deleted file mode 100644 index a287094..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dataper.lua +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/lua - -alloc = arg[1] -- allocate increment in GB -per = arg[2] -- fixed percentage in GB -used = arg[3] -- amt used in Kb - ---used = used / 10000 -- used in GB -percent = (used / alloc) * 100 - -running = "0" -if percent >= tonumber(per) then - running = "1" -end - -tfile = io.open("/tmp/bwper", "w") -tfile:write("runn=\"", running, "\"") -tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh deleted file mode 100644 index 651c410..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/dotext.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "TEXTING" "$@" -} - -getbw() { - alloc=$(uci -q get custom.bwallocate.allocate)"000000" - if [ -e /tmp/bwdata ]; then - while IFS= read -r line; do - days=$line - if [ $days = '0' ]; then - used="0" - return - fi - read -r line - used=$line - read -r line - useda=$line - return - done < /tmp/bwdata - else - used="0" - useda="0.00 K" - fi -} - -sendmsg() { - getbw - /usr/lib/bwmon/amtleft.lua $alloc $used - bwleft=$(cat /tmp/amtleft) - - #ident=$(uci -q get custom.texting.ident) - ident=$(uci -q get modem.modem1.iccid) - if [ -z "$ident" ]; then - ident="Unknown User" - fi - message="$ident has used $useda bandwidth and has $bwleft of bandwidth left" - - tore=$(uci -q get custom.texting.tore) - if [ $tore = '0' ]; then - phone=$(uci -q get custom.texting.phone) - /usr/lib/bwmon/chksms.sh - if [ -e /tmp/texting ]; then - /usr/lib/sms/smsout.sh "$phone" "$message" - log "$phone $message" - else - log "$message not sent. No SMS." - fi - else - email=$(uci -q get custom.texting.email) - - host=$(uci -q get custom.texting.smtp) - user=$(uci -q get custom.texting.euser) - pass=$(uci -q get custom.texting.epass) - - STEMP="/tmp/eemail" - MSG="/usr/lib/bwmon/msmtprc" - DST="/etc/msmtprc" - rm -f $STEMP - cp $MSG $STEMP - sed -i -e "s!#HOST#!$host!g" $STEMP - sed -i -e "s!#USER#!$user!g" $STEMP - sed -i -e "s!#PASS#!$pass!g" $STEMP - mv $STEMP $DST - - STEMP="/tmp/emailmsg" - MSG="/usr/lib/bwmon/message" - rm -f $STEMP - cp $MSG $STEMP - sed -i -e "s!#EMAIL#!$email!g" $STEMP - sed -i -e "s!#MESSAGE#!$message!g" $STEMP - sed -i -e "s!#IDENT#!$ident!g" $STEMP - mess=$(cat /tmp/emailmsg) - echo -e "$mess" | msmtp --read-envelope-from --read-recipients - log "$email $message" - fi - -} - -sendmsg \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh deleted file mode 100644 index 61c4ec3..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/editemail.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -log() { - logger -t "edit email" "$@" -} - -host=$(uci -q get custom.texting.smtp) -if [ -z $host ]; then - exit 0 -fi -user=$(uci -q get custom.texting.euser) -if [ -z $user ]; then - exit 0 -fi -pass=$(uci -q get custom.texting.epass) -if [ -z $pass ]; then - exit 0 -fi - -STEMP="/tmp/eemail" -MSG="/usr/lib/bwmon/msmtprc" -DST="/etc/msmtprc" -rm -f $STEMP -cp $MSG $STEMP -sed -i -e "s!#HOST#!$host!g" $STEMP -sed -i -e "s!#USER#!$user!g" $STEMP -sed -i -e "s!#PASS#!$pass!g" $STEMP -mv $STEMP $DST - \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh deleted file mode 100644 index 5c9af09..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/excede.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "excede BW " "$@" -} - -do_throttle() { - local config=$1 - local limit - - config_get name $1 name - config_get limit $1 limit - config_get throttle $1 throttle - let kamt=limit*1000000 - if [ $amt -gt $kamt ]; then - if [ $limit -gt $baselimit ]; then - speed=$throttle - level=$name - baselimit=$limit - fi - fi -} - -lock=$(uci -q get custom.bwallocate.lock) -if [ $lock = "1" ]; then - enb=$(uci -q get custom.bwallocate.enabled) - if [ $enb = '1' ]; then - allocate=$2 - total=$1 - /usr/lib/bwmon/block 0 - action=$(uci -q get custom.bwallocate.action) - if [ -z $action ]; then - action=0 - fi - if [ ! -e /usr/lib/throttle/throttle.sh ]; then - action=0 - fi - if [ $action != "2" ]; then - if [ $total -gt $allocate ]; then - if [ $action = "0" ]; then - if [ -e /etc/nodogsplash/control ]; then - /etc/nodogsplash/control block - else - /usr/lib/bwmon/block 1 - fi - else - down=$(uci -q get custom.bwallocate.down) - if [ -z $down ]; then - down=5 - fi - up=$(uci -q get custom.bwallocate.up) - if [ -z $up ]; then - up=2 - fi - /usr/lib/throttle/throttle.sh start $down $up - fi - else - if [ -e /usr/lib/throttle/throttle.sh ]; then - /usr/lib/throttle/throttle.sh stop - fi - if [ -e /etc/nodogsplash/control ]; then - /etc/nodogsplash/control unblock - fi - /usr/lib/bwmon/block 0 - fi - else - meth=$(uci -q get custom.bwallocate.meth) - if [ -z $meth ]; then - meth="0" - fi - if [ $meth = "0" ]; then - amt=$total - else - amt=$3 - fi - speed="0" - baselimit="0" - config_load custom - config_foreach do_throttle throttle - if [ $speed != "0" ]; then - /usr/lib/bwmon/float.lua "$speed" - source /tmp/float - /usr/lib/throttle/throttle.sh start $SPEED $SPEED 1 - log "Throttled to $speed Mbps" - else - if [ -e /usr/lib/throttle/throttle.sh ]; then - /usr/lib/throttle/throttle.sh stop - fi - fi - - fi - fi -fi \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh deleted file mode 100644 index 9b11296..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/external.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -log() { - logger -t "wrtbwmon" "$@" -} - -external=$1 - -ext=$(uci -q get bwmon.general.external) - -if [ "$ext" = "$external" ]; then - exit 0 -else - uci set bwmon.general.external=$external - uci commit bwmon - PID=$(ps |grep "wrtbwmon.sh" | grep -v grep |head -n 1 | awk '{print $1}') - PID1=$(ps |grep "create.sh" | grep -v grep |head -n 1 | awk '{print $1}') - if [ ! -z "$PID" ]; then - kill -9 $PID - kill -9 $PID1 - fi - /usr/lib/bwmon/wrtbwmon.sh & - /usr/lib/bwmon/create.sh & -fi \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua deleted file mode 100644 index 4c40f3e..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/float.lua +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/lua - -val = arg[1] - -retval = val * 1000 - -local tfile = io.open("/tmp/float", "w") -tfile:write("SPEED=\"", retval, "\"") -tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message deleted file mode 100644 index 509a0e4..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/message +++ /dev/null @@ -1,4 +0,0 @@ -From: Broadband Usage -To: #EMAIL# -Subject: Broadband Usage -#MESSAGE# diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc deleted file mode 100644 index 4b8a3f8..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/msmtprc +++ /dev/null @@ -1,12 +0,0 @@ -account default -host #HOST# -port 587 -auto_from off -from #USER# -aliases /etc/aliases -tls on -tls_starttls on -tls_trust_file /etc/ssl/certs/ca-certificates.crt -auth on -user #USER# -password #PASS# \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua deleted file mode 100644 index 1f133ef..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/perday.lua +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/lua - -function ltrim(s) - return s:match'^%s*(.*)' -end - -function calc(total) - if total < 1000 then - tstr = string.format("%.2f", total) - tfm = " K" - else - if total < 1000000 then - tstr = string.format("%.2f", total/1000) - tfm = " MB" - else - tstr = string.format("%.2f", total/1000000) - tfm = " GB" - end - end - str = tstr .. tfm - return ltrim(str) -end - -local function bubblesort(a) - repeat - local swapped = false - for i = 1, table.getn(a) do - if a[i - 1] < a[i] then - a[i], a[i - 1] = a[i - 1], a[i] - swapped = true - end -- if - end -- for - until swapped == false -end - -function ConBytes(line) - local s, e, bs, be - s, e = line:find(" ") - bs, be = line:find("K", e+1) - if bs == nil then - bs, be = line:find("MB", e+1) - if bs == nil then - val = tonumber(line:sub(1, e-1)) * 1000000 - else - val = tonumber(line:sub(1, e-1)) * 1000 - end - else - val = tonumber(line:sub(1, e-1)) - end - return val -end - -dirname = '/usr/lib/bwmon/data' -filepost = "-mac_data.js" -monthly = dirname .. "/monthly.data" -daylist = {} -dayline = {} -monlist = {} -monline = {} - -dataname = nil -f = io.popen('/bin/ls ' .. dirname) -for name in f:lines() do - s, e = name:find(filepost) - if s ~= nil then - dataname = name - end -end -f:close() - -if dataname ~= nil then - yearmon = dataname:sub(1, 7) - datafile = dirname .. "/" .. dataname - file = io.open(datafile, "r") - i = 0 - repeat - line = file:read("*line") - if line == nil then - break - end - s, e = line:find("start day") - if s ~= nil then - day = line:sub(e+1) - nday = tonumber(day) - day= tostring(nday) - if nday < 10 then - day = "0" .. day - end - yearmonday = yearmon .. "-" .. day - - daydwn = 0 - dayup = 0 - repeat - line = file:read("*line") - s, e = line:find("end day") - if s ~= nil then - dayt = dayup + daydwn - if dayt > 0 then - daylist[i] = yearmonday - i = i + 1 - dayline[yearmonday] = {} - dayline[yearmonday]['down'] = daydwn - dayline[yearmonday]['up'] = dayup - dayline[yearmonday]['total'] = dayup + daydwn - end - break - end - s, e = line:find("\"down\":\"") - bs, be = line:find("\"", e+1) - daydwn = daydwn + tonumber(line:sub(e+1, bs-1)) - s, e = line:find("\"up\":\"") - bs, be = line:find("\"", e+1) - dayup = dayup + tonumber(line:sub(e+1, bs-1)) - until 1==0 - end - until 1==0 - - if i > 0 then - tfile = io.open(monthly, "r") - if tfile == nil then - for j = 0,i-1 - do - lin = daylist[j] - monlist[j] = lin - monline[lin] = {} - dwn = calc(dayline[lin]['down']) - up = calc(dayline[lin]['up']) - total = calc(dayline[lin]['total']) - dataline = lin .. "|" .. dwn .. "|" .. up .. "|" .. total - monline[lin]['data'] = dataline - end - k = i - else - k = 0 - ksize = tfile:read("*line") - kdwn = tfile:read("*line") - kup = tfile:read("*line") - ktotal = tfile:read("*line") - repeat - line = tfile:read("*line") - if line == nil then - break - end - ymd = line:sub(1,10) - monlist[k] = ymd - k = k + 1 - monline[ymd] = {} - monline[ymd]['data'] = line - until 1==0 - tfile:close() - - for j = 0,i-1 - do - lin = daylist[j] - if monline[lin] == nil then - monlist[k] = lin - k = k + 1 - monline[lin] = {} - end - dwn = calc(dayline[lin]['down']) - up = calc(dayline[lin]['up']) - total = calc(dayline[lin]['total']) - dataline = lin .. "|" .. dwn .. "|" .. up .. "|" .. total - monline[lin]['data'] = dataline - end - end - - bubblesort(monlist) - - tfile = io.open(monthly, "w") - if k > 30 then - k = 30 - end - tfile:write(tostring(k), "\n") - fdown = 0 - fup = 0 - ftotal = 0 - for j = 0,k-1 - do - lin = monlist[j] - dataline = monline[lin]['data'] - s, e = dataline:find("|") - if s ~= nil then - bs, be = dataline:find("|", e+1) - fdown = ConBytes(dataline:sub(e+1, be-1)) + fdown - s, e = dataline:find("|", be+1) - fup = ConBytes(dataline:sub(be+1, e-1)) + fup - ftotal = ConBytes(dataline:sub(e+1)) + ftotal - end - end - tfile:write(calc(fdown), "\n") - tfile:write(calc(fup), "\n") - tfile:write(calc(ftotal), "\n") - for j = 0,k-1 - do - lin = monlist[j] - dataline = monline[lin]['data'] - tfile:write(dataline, "\n") - end - tfile:close() - end - - file:close() -end \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh deleted file mode 100644 index 42e38b6..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/process.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -log() { - logger -t "BWmon Process" "$@" -} - -running=0 -if [ -e "/tmp/WRTbmon" ]; then - running=1 -fi - -sleep 5 - -if [ $running = 0 ]; then - log "Enable BandWidthMonitor" - /usr/lib/bwmon/wrtbwmon.sh & -fi - - - diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh deleted file mode 100644 index 648b9d6..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/rollover.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Rollover" "$@" -} - -amount=$1 - -uci set custom.bwallocate.rollover=$amount -uci set custom.bwallocate.persent="0" -uci commit custom diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh deleted file mode 100644 index 1a780ba..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/savetot.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -log() { - logger -t "save total" "$@" -} - -total=$1 - -uci set custom.bwday.bwday="$total" -uci commit custom \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh deleted file mode 100644 index 3fc4ff4..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/sendsms.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -log() { - logger -t "sendsms" "$@" -} - -chksms() { - CURRMODEM=1 - rm -f /tmp/texting - CPORT=$(uci -q get modem.modem$CURRMODEM.commport) - if [ -z $CPORT ]; then - return - fi - SMS_OK=$(uci -q get modem.modem$CURRMODEM.sms) - if [ "$SMS_OK" != "1" ]; then - return - fi - echo "0" > /tmp/texting -} - -delay=$(uci -q get modem.modeminfo$CURRMODEM.delay) -if [ "$delay" -gt 0 ]; then - cnt=1 - while true; do - sleep 3600 - let cnt=cnt+1 - if [ $cnt -gt $delay ]; then - break - fi - done -fi -total=$(uci -q get.custom.bwday.bwday) -chksms -phone=$(uci -q get modem.modeminfo$CURRMODEM.bwphone) -if [ (! -z "$phone") -o ("$phone" != "0") ]; then - if [ -e /tmp/texting ]; then - /usr/lib/sms/smsout.sh "$phone" "$total" - fi -fi diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh deleted file mode 100644 index ed85caa..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/textbw.sh +++ /dev/null @@ -1,153 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - modlog "TEXTING" "$@" -} - -checktime() { - SHOUR=$(uci -q get custom.texting.time) - EHOUR=`expr $SHOUR + 1` - if [ $EHOUR -gt 95 ]; then - EHOUR=0 - fi - HOUR=`expr $SHOUR / 4` - let "TH = $HOUR * 4" - let "TMP1 = $SHOUR - $TH" - let "MIN = $TMP1 * 15" - shour=$HOUR - smin=$MIN - - HOUR=`expr $EHOUR / 4` - let "TH = $HOUR * 4" - let "TMP1 = $EHOUR - $TH" - let "MIN = $TMP1 * 15" - ehour=$HOUR - emin=$MIN - - chour=$(date +%H) - cmin=$(date +%M) - if [ $shour -gt $chour ]; then - flag="0" - else - if [ $shour -eq $chour ]; then - if [ $smin -le $cmin ]; then - flag="1" - else - flag="0" - fi - else - flag="1" - fi - fi - - if [ $flag = "1" ]; then - if [ $ehour -lt $chour ]; then - flag="0" - else - if [ $ehour -eq $chour ]; then - if [ $emin -lt $cmin ]; then - flag="0" - else - flag="1" - fi - else - flag="1" - fi - fi - fi - echo $flag -} - -getbw() { - alloc=$(uci -q get custom.bwallocate.allocate)"000000" - if [ -e /tmp/bwdata ]; then - while IFS= read -r line; do - days=$line - if [ $days = '0' ]; then - used="0" - return - fi - read -r line - used=$line - return - done < /tmp/bwdata - else - used="0" - fi -} - -checkamt() { - istime=$(checktime) - if [ $istime = '1' ]; then - incr=$(uci -q get custom.texting.increment) - getbw - /usr/lib/bwmon/datainc.lua $prev $incr $used - source /tmp/bwinc - uci set custom.texting.used=$prev - uci commit custom - echo $runn - else - echo "0" - fi -} - -checkper() { - istime=$(checktime) - if [ $istime = '1' ]; then - prev=$(uci -q get custom.texting.used) - per=$(uci -q get custom.texting.percent) - persent=$(uci -q get custom.bwallocate.persent) - if [ "$persent" != "1" ]; then - getbw - /usr/lib/bwmon/dataper.lua $alloc $per $used - source /tmp/bwper - if [ $runn = "1" ]; then - uci set custom.bwallocate.persent="1" - uci commit custom - fi - echo $runn - else - echo "0" - fi - else - echo "0" - fi -} - -delay=900 -while true -do - EN=$(uci -q get custom.bwallocate.enabled) - if [ $EN = "1" ]; then - MT=$(uci -q get custom.texting.method) - if [ $MT = '0' ]; then - days=$(uci -q get custom.texting.days) - daysdate=$( date +%d ) - daysdate="${daysdate#"${daysdate%%[!0]*}"}" - remain=$((daysdate % days)) - if [ $remain -eq 0 ]; then - running=$(checktime) - else - running="0" - fi - else - if [ $MT = '1' ]; then - running=$(checkamt) - else - running=$(checkper) - fi - fi - if [ $running = "1" ]; then - EN=$(uci -q get custom.texting.text) - if [ $EN = "1" ]; then - /usr/lib/bwmon/dotext.sh & - sleep $delay - fi - else - sleep $delay - fi - else - sleep $delay - fi -done \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh b/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh deleted file mode 100644 index 55e3924..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/bwmon/wrtbwmon.sh +++ /dev/null @@ -1,508 +0,0 @@ -#!/bin/sh - -setbackup() { - extn=$(uci -q get bwmon.general.external) - if [ "$extn" = "0" ]; then - backPath=/usr/lib/bwmon/data/ - else - if [ -e "$extn""/" ]; then - backPath=$extn"/data/" - else - backPath=/usr/lib/bwmon/data/ - uci set bwmon.general.external="0" - uci commit bwmon - fi - fi - if [ ! -e "$backpath" ]; then - mkdir -p $backPath - fi -} - -LAN_TYPE=$(uci get network.lan.ipaddr | awk -F. ' { print $1"."$2 }') -LEASES_FILE=/tmp/dhcp.leases -lockDir=/tmp/WRTbmon - -ifname="ifname" -source /etc/openwrt_release -twone=$(echo "$DISTRIB_RELEASE" | grep "21.02") -if [ ! -z "$twone" ]; then - ifname="device" -fi - - -[ ! -d "$lockDir" ] && mkdir "$lockDir" -basePath="/tmp/bwmon/" -mkdir -p $basePath"data" -dataPath=$basePath"data/" -setbackup -lockDir1=/tmp/wrtbwmon1.lock -lockDir=/tmp/wrtbwmon.lock -mkdir -p "$lockDir" -pidFile=$lockDir/pid -STARTIMEX=$(date +%s) -STARTIMEY=$(date +%s) -STARTIMEZ=$(date +%s) -cYear=$(date +%Y) -cDay=$(date +%d) -cMonth=$(date +%m) -setup_time=60 -update_time=60 -bs=$(uci -q get bwmon.general.backup) -let "bs=$bs*60" -backup_time=$bs -pause=30 -unlimited="peak" - -networkFuncs=/lib/functions/network.sh -uci=`which uci 2>/dev/null` -nslookup=`which nslookup 2>/dev/null` -nvram=`which nvram 2>/dev/null` -binDir=/usr/sbin -chains='INPUT OUTPUT FORWARD' -DEBUG= -interfaces='eth0' # in addition to detected WAN -DB="/tmp/usage.db" -mode= - -log() { - logger -t "wrtbwmon" "$@" -} - -header="#mac,ip,iface,in,out,total,first_date,last_date" - -createDbIfMissing() -{ - [ ! -f "$DB" ] && rm -f $DB;echo $header > "$DB" -} - -checkWAN() -{ - [ -z "$wan" ] && return -} - -lookup() -{ - MAC=$1 - IP=$2 - userDB=$3 - for USERSFILE in $userDB /tmp/dhcp.leases /tmp/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do - [ -e "$USERSFILE" ] || continue - case $USERSFILE in - /tmp/dhcp.leases ) - USER=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ') - ;; - /etc/hosts ) - USER=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ') - ;; - * ) - USER=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,) - ;; - esac - [ "$USER" = "*" ] && USER= - [ -n "$USER" ] && break - done - if [ -n "$DO_RDNS" -a -z "$USER" -a "$IP" != "NA" -a -n "$nslookup" ]; then - USER=`$nslookup $IP $DNS | awk '!/server can/{if($4){print $4; exit}}' | sed -re 's/[.]$//'` - fi - [ -z "$USER" ] && USER=${MAC} - echo $USER -} - -detectIF() -{ - if [ -f "$networkFuncs" ]; then - IF=`. $networkFuncs; network_get_device netdev $1; echo $netdev` - [ -n "$IF" ] && echo $IF && return - fi - - if [ -n "$uci" -a -x "$uci" ]; then - IF=`$uci get network.${1}.$ifname 2>/dev/null` - [ $? -eq 0 -a -n "$IF" ] && echo $IF && return - fi - - if [ -n "$nvram" -a -x "$nvram" ]; then - IF=`$nvram get ${1}_$ifname 2>/dev/null` - [ $? -eq 0 -a -n "$IF" ] && echo $IF && return - fi -} - -detectLAN() -{ - [ -e /sys/class/net/br-lan ] && echo br-lan && return - lan=$(detectIF lan) - [ -n "$lan" ] && echo $lan && return -} - -detectWAN() -{ - [ -n "$WAN_IF" ] && echo $WAN_IF && return - wan=$(detectIF wan) - [ -n "$wan" ] && echo $wan && return - wan=$(ip route show 2>/dev/null | grep default | sed -re '/^default/ s/default.*dev +([^ ]+).*/\1/') - [ -n "$wan" ] && echo $wan && return - [ -f "$networkFuncs" ] && wan=$(. $networkFuncs; network_find_wan wan; echo $wan) - [ -n "$wan" ] && echo $wan && return -} - -lock() -{ - attempts=0 - while [ $attempts -lt 10 ]; do - mkdir $lockDir1 2>/dev/null && break - attempts=$((attempts+1)) - pid=`cat $pidFile 2>/dev/null` - if [ -n "$pid" ]; then - if [ -d "/proc/$pid" ]; then - [ -n "$DEBUG" ] && echo "WARNING: Lockfile detected but process $(cat $pidFile) does not exist !" - rm -rf $lockDir1 - else - sleep 1 - fi - fi - done - mkdir $lockDir1 2>/dev/null - echo $$ > $pidFile - [ -n "$DEBUG" ] && echo $$ "got lock after $attempts attempts" - trap '' INT -} - -unlock() -{ - rm -rf $lockDir1 - [ -n "$DEBUG" ] && echo $$ "released lock" - trap "rm -f /tmp/*_$$.tmp; kill $$" INT -} - -# chain -newChain() -{ - chain=$1 - # Create the RRDIPT_$chain chain (it doesn't matter if it already exists). - iptables -t mangle -N RRDIPT_$chain 2> /dev/null - - # Add the RRDIPT_$chain CHAIN to the $chain chain if not present - iptables -t mangle -C $chain -j RRDIPT_$chain 2>/dev/null - if [ $? -ne 0 ]; then - [ -n "$DEBUG" ] && echo "DEBUG: iptables chain misplaced, recreating it..." - iptables -t mangle -I $chain -j RRDIPT_$chain - fi -} - -# chain tun -newRuleIF() -{ - chain=$1 - IF=$2 - - #!@todo test - if [ "$chain" = "OUTPUT" ]; then - cmd="iptables -t mangle -o $IF -j RETURN" - eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain" - elif [ "$chain" = "INPUT" ]; then - cmd="iptables -t mangle -i $IF -j RETURN" - eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain" - fi -} - -accounting(){ - LAN_IFACE="br-lan" - WAN_IFACE=$1 - LAN_IP=$(uci -q get network.lan.ipaddr) - SERVER_IP=$(echo $LAN_IP | cut -d . -f 1,2,3).0 - INTERNAL_NETMASK="$SERVER_IP/24" - - # create the ACCOUNTING chains - iptables -w -N ACCOUNTING_BLOCK 2> /dev/null - iptables -w -N ACCOUNTING_IN 2> /dev/null - iptables -w -N ACCOUNTING_OUT 2> /dev/null - check=0 - # check if accounting rule for ethernet wan not exist, add it - checks=$(iptables -w -L FORWARD -v -n | grep "ACCOUNTING" | grep "$WAN_IFACE") - [ -z "$checks" ] && check=1 - - # check if jumps to the ACCOUNTING chains are still at the start of the FORWARD chain - iptables -w -L FORWARD --line-numbers -n | grep "ACCOUNTING" | grep "^1 " - if [ $? -ne 0 -o "$check" = "1" ]; then - # remove old jump rules - iptables -w -D FORWARD $(iptables -w -L FORWARD --line-numbers | grep ACCOUNTING | grep -m 1 -o "[0-9]*") - while [ $? -eq 0 ]; do - iptables -w -D FORWARD $(iptables -w -L FORWARD --line-numbers | grep ACCOUNTING | grep -m 1 -o "[0-9]*") - done - # insert new jump rules at start of FORWARD chain - if [ -n "$WAN_IFACE" ] - then - iptables -w -I FORWARD -i ${WAN_IFACE} -j ACCOUNTING_IN - iptables -w -I FORWARD -o ${WAN_IFACE} -j ACCOUNTING_OUT - fi - iptables -w -I FORWARD -j ACCOUNTING_BLOCK - fi - - #For each host in the ARP table - grep ${LAN_IFACE} /proc/net/arp | while read IP TYPE FLAGS MAC MASK IFACE - do - #Add iptables rules (if non existing). - iptables -w -nL ACCOUNTING_IN | grep "${IP} " > /dev/null - if [ $? -ne 0 ]; then - iptables -w -I ACCOUNTING_IN -d ${IP} -s ${INTERNAL_NETMASK} -j RETURN - iptables -w -I ACCOUNTING_IN -d ${IP} ! -s ${INTERNAL_NETMASK} -j RETURN - fi - - iptables -w -nL ACCOUNTING_OUT | grep "${IP} " > /dev/null - if [ $? -ne 0 ]; then - iptables -w -I ACCOUNTING_OUT -s ${IP} -d ${INTERNAL_NETMASK} -j RETURN - iptables -w -I ACCOUNTING_OUT -s ${IP} ! -d ${INTERNAL_NETMASK} -j RETURN - fi - done -} - -setup() -{ - for chain in $chains; do - newChain $chain - done - - wan=$(detectWAN) - checkWAN - wan1=$(detectIF wan1) - wan2=$(detectIF wan2) - C1=$(uci -q get modem.modem1.connected) - C2=$(uci -q get modem.modem2.connected)$C1 - if [ ! -z $C2 ]; then - interfaces="$wan1 $wan2" - WW=$(uci -q get bwmon.bwwan.wan) - if [ "$WW" = "1" ]; then - interfaces=$interfaces $wan" wwan" - fi - else - WW=$(uci -q get bwmon.bwwan.wan) - if [ "$WW" = "1" ]; then - interfaces="$wan wwan" - else - return - fi - fi - - # track local data - for chain in INPUT OUTPUT; do - for interface in $interfaces; do - [ -n "$interface" ] && [ -e "/sys/class/net/$interface" ] && newRuleIF $chain $interface - #if [ -e /etc/bwlock ]; then - accounting $interface - #fi - done - done - - # this will add rules for hosts in arp table - update $dailyUsageDB - - rm -f /tmp/*_$$.tmp -} - -update() -{ - createDbIfMissing - checkWAN - PERTOTAL=0 - - > /tmp/iptables_$$.tmp - lock - # only zero our own chains - for chain in $chains; do - iptables -nvxL RRDIPT_$chain -t mangle -Z >> /tmp/iptables_$$.tmp - done - # the iptables and readDB commands have to be separate. Otherwise, - # they will fight over iptables locks - awk -v mode="$mode" -v interfaces=\""$interfaces"\" -f $binDir/readDB.awk \ - $DB \ - /proc/net/arp \ - /tmp/iptables_$$.tmp - - while read L1 - do - MAC=$(echo ${L1} | cut -f1 -d, ) - if [ $MAC != "#mac" ]; then - MAC=$(echo ${L1} | cut -f1 -d, ) - IP=$(echo ${L1} | cut -f2 -d, ) - IN=$(echo ${L1} | cut -f4 -d, ) - IN=$((${IN}/1000)) - OUT=$(echo ${L1} | cut -f5 -d, ) - OUT=$((${OUT}/1000)) - TOTAL=$(echo ${L1} | cut -f6 -d, ) - TOTAL=$((${TOTAL}/1000)) - let PERTOTAL=PERTOTAL+TOTAL - if [ $TOTAL -gt 0 -a $IP != "NA" ]; then - for USERSFILE in /tmp/dhcp.leases /tmp/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do - [ -e "$USERSFILE" ] || continue - case $USERSFILE in - /tmp/dhcp.leases ) - NAME=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ') - ;; - /etc/hosts ) - NAME=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ') - ;; - * ) - NAME=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,) - ;; - esac - [ "$NAME" = "*" ] && NAME= - [ -n "$NAME" ] && break - done - if [ -z $NAME ]; then - NAME="*" - fi - - echo "\"mac\":\""${MAC}"\"","\"down\":\""${IN}"\"","\"up\":\""${OUT}"\"","\"offdown\":\""0"\"","\"offup\":\""0"\"","\"ip\":\""${IP}"\"","\"name\":\""${NAME}"\"" >> ${1} - fi - fi - done < $DB - if [ -e /usr/lib/bwmon/period.sh ]; then - /usr/lib/bwmon/period.sh "$PERTOTAL" - fi - unlock -} - - -createFiles() -{ - while [ -e /tmp/lockbw ]; do - sleep 1 - done - echo "0" > /tmp/lockbw - while [ ! -e $backPath*"mac_data.js" ]; do - valid=$(cat /var/state/dnsmasqsec) - st=$(echo "$valid" | grep "ntpd says time is valid") - if [ ! -z "$st" ]; then - break - fi - sleep 10 - done - dailyUsageDB="$dataPath$cYear-$cMonth-$cDay-daily_data.js" - dailyUsageBack="$backPath$cYear-$cMonth-$cDay-daily_data.js" - if [ ! -f $dailyUsageBack ]; then - rm -f $backPath*"daily_data.js" - touch $dailyUsageDB - touch $dailyUsageBack - else - cp -f $dailyUsageBack $dailyUsageDB - fi - monthlyUsageDB="$dataPath$cYear-$cMonth-mac_data.js" - monthlyUsageBack="$backPath$cYear-$cMonth-mac_data.js" - if [ -f $monthlyUsageBack ]; then - cp -f $monthlyUsageBack $monthlyUsageDB".bk" - sed "/start day $cDay/,/end day $cDay/d" $monthlyUsageDB".bk" > $monthlyUsageDB - cp -f $monthlyUsageBack $monthlyUsageDB".bk" - else - rm -f $backPath*"mac_data.js" - touch $monthlyUsageDB - touch $monthlyUsageBack - /usr/lib/bwmon/backup.sh "backup" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack - fi - rm -f /tmp/lockbw -} - -shutDown() -{ - while [ -e /tmplockbw ]; do - sleep 1 - done - echo "0" > /tmp/lockbw - /usr/lib/bwmon/backup.sh "backup" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack - lua /usr/lib/bwmon/cleanup.lua - rm -f /tmp/lockbw -} - -checkSetup() -{ - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - if [ $ELAPSE -gt $setup_time ]; then - STARTIMEX=$CURRTIME - setup - /usr/lib/bwmon/backup.sh "setup" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack - fi -} - -checkUpdate() -{ - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEY - if [ $ELAPSE -gt $update_time ]; then - STARTIMEY=$CURRTIME - update $dailyUsageDB $unlimited - fi -} - -checkBackup() -{ - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEZ - bs=$(uci -q get bwmon.general.backup) - let "bs=$bs*60" - backup_time=$bs - if [ $ELAPSE -gt $backup_time ]; then - STARTIMEZ=$CURRTIME - shutDown - fi -} - -checkTime() -{ - while [ -e /tmplockbw ]; do - sleep 1 - done - echo "0" > /tmp/lockbw - pDay=$(date +%d) - pYear=$(date +%Y) - pMonth=$(date +%m) - if [ "$cDay" -ne "$pDay" ]; then - /usr/lib/bwmon/backup.sh "daily" $cDay $monthlyUsageDB $dailyUsageDB $monthlyUsageBack $dailyUsageBack - - cDay=$pDay - cMonth=$pMonth - cYear=$pYear - monthlyUsageBack="$backPath$cYear-$cMonth-mac_data.js" - if [ ! -e $monthlyUsageBack ]; then - rm -f $backPath*"mac_data.js" - fi - rm -f $dataPath[[:digit:]][[:digit:]][[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]-daily_data.js - rm -f $backPath[[:digit:]][[:digit:]][[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]"-"[[:digit:]][[:digit:]]-daily_data.js - roll=$(uci -q get custom.bwallocate.rollover) - [ -z $roll ] && roll=1 - if [ "$roll" -eq "$pDay" ]; then - rm -f $monthlyUsageDB - rm -f $backPath*"mac_data.js" - monthlyUsageDB="$dataPath$cYear-$cMonth-mac_data.js" - monthlyUsageBack="$backPath$cYear-$cMonth-mac_data.js" - touch $monthlyUsageDB - uci set custom.texting.used='0' - uci commit custom - if [ -e /usr/lib/bwmon/periodreset.sh ]; then - /usr/lib/bwmon/periodreset.sh - fi - fi - rm -f $dailyUsageDB - rm -f $backPath*"daily_data.js" - dailyUsageDB="$dataPath$cYear-$cMonth-$cDay-daily_data.js" - touch $dailyUsageDB - dailyUsageBack="$backPath$cYear-$cMonth-$cDay-daily_data.js" - fi - rm -f /tmp/lockbw -} - -createFiles -setup -while [ -d $lockDir ]; do - checkSetup - checkTime - checkBackup - n=0 - while [ true ] ; do - n=$(($n + 1)) - if [ ! -d "$lockDir" ]; then - shutDown - exit 0 - fi - [ "$n" -gt "$pause" ] && break; - sleep 1 - done -done diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua b/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua deleted file mode 100644 index ac269e8..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/controller/bwmon.lua +++ /dev/null @@ -1,119 +0,0 @@ -module("luci.controller.bwmon", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - entry({"admin", "nlbw"}, firstchild(), translate("Bandwidth Monitor"), 80).dependent=false - page = entry({"admin", "nlbw", "bwmon"}, template("bwmon/bwmon"), translate("ROOter Bandwidth Monitor"), 70) - page.dependent = true - - entry({"admin", "nlbw", "check_bw"}, call("action_check_bw")) - entry({"admin", "nlbw", "change_bw"}, call("action_change_bw")) - entry({"admin", "nlbw", "change_roll"}, call("action_change_roll")) - entry({"admin", "nlbw", "change_enable"}, call("action_change_enable")) - entry({"admin", "nlbw", "change_bwenable"}, call("action_change_bwenable")) - entry({"admin", "nlbw", "change_backup"}, call("action_change_backup")) - entry({"admin", "nlbw", "change_external"}, call("action_change_external")) - entry({"admin", "nlbw", "change_bwwan"}, call("action_change_bwwan")) -end - -function action_check_bw() - local rv = {} - local maclist = {} - - file = io.open("/tmp/bwdata", "r") - if file ~= nil then - rv['days'] = file:read("*line") - if rv['days'] ~= "0" then - rv['total'] = file:read("*line") - rv['ctotal'] = file:read("*line") - rv['totaldown'] = file:read("*line") - rv['ctotaldown'] = file:read("*line") - rv['totalup'] = file:read("*line") - rv['ctotalup'] = file:read("*line") - rv['ptotal'] = file:read("*line") - rv['cptotal'] = file:read("*line") - rv['atotal'] = file:read("*line") - rv['catotal'] = file:read("*line") - rv['password'] = file:read("*line") - j = file:read("*line") - if j == nil then - j = 0 - end - rv['macsize'] = j - if j ~=0 then - for i=0, j-1 do - maclist[i] = file:read("*line") - end - rv['maclist'] = maclist - end - end - file:close() - else - rv['days'] = 0 - end - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if multilock == "0" then - rv['lock'] = luci.model.uci.cursor():get("custom", "bwallocate", "lock") - else - if rootlock == "0" then - rv['lock'] = "1" - else - rv['lock'] = "0" - end - end - rv['rollover'] = luci.model.uci.cursor():get("custom", "bwallocate", "rollover") - rv['enabled'] = luci.model.uci.cursor():get("custom", "bwallocate", "enabled") - rv['bwenabled'] = luci.model.uci.cursor():get("bwmon", "general", "enabled") - rv['backup'] = luci.model.uci.cursor():get("bwmon", "general", "backup") - rv['external'] = luci.model.uci.cursor():get("bwmon", "general", "external") - rv['bwwan'] = luci.model.uci.cursor():get("bwmon", "bwwan", "wan") - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_change_bw() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/bwmon/allocate.sh " .. set) - -end - -function action_change_roll() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/bwmon/rollover.sh " .. set) - -end - -function action_change_enable() - local set = luci.http.formvalue("set") - os.execute("uci set custom.bwallocate.enabled=" .. set .. "; uci commit custom") - -end - -function action_change_bwenable() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/bwmon/change.sh " .. set) - -end - -function action_change_backup() - local set = luci.http.formvalue("set") - os.execute("uci set bwmon.general.backup=" .. set .. "; uci commit bwmon") - -end - -function action_change_external() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/bwmon/external.sh " .. set) - -end - -function action_change_bwwan() - local set = luci.http.formvalue("set") - os.execute("uci set bwmon.bwwan.wan=" .. set .. "; uci commit bwmon") - -end \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm b/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm deleted file mode 100644 index 2664efd..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/lib/lua/luci/view/bwmon/bwmon.htm +++ /dev/null @@ -1,610 +0,0 @@ -<%+header%> -<% -local sys = require "luci.sys" -local utl = require "luci.util" -local fs = require "nixio.fs" - -function showicon(lck) - if lck == 0 then - return resource .. "/icons/unlock1.png" - else - return resource .. "/icons/lock1.png" - end -end - --%> - - - - -
                -
                -

                <%:Bandwidth Monitor%>

                -
                -

                <%:Note : Bandwidth Monitor will not turn on until there is Internet Available%>

                - - - -
                - <%:Extra Internet Sources%> - - - - - - - - -
                <%:Include WAN and Hotspot%>
                -
                - -
                - <%:Data Backup Configuration%> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                <%:Enable Data Backup%>
                <%:Backup Interval in Minutes%>
                -
                <%:Backup Storage Location%>
                - -
                - -
                - <%:Total Bandwidth%> - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                <%:Total Amount of Bandwidth used this Month : %>
                <%:Estimated Bandwidth to be used this Month : %>
                <%:Rollover Day : %>
                -
                - - - - - -
                - -
                - <%:Report%> - - - - - - - - - - - - - - - - - -
                <%:Number of Days in Reporting Period : %>
                <%:Total Amount of Download Bandwidth : %>
                <%:Total Amount of Upload Bandwidth : %>
                - - - - - - -
                - -
                - - - - - - - - - -
                <%:IP Address%>
                <%:Name%>
                <%:MAC Address%>
                <%:Bandwidth Down%>
                <%:Bandwidth Up%>
                <%:Bandwidth Total%>
                - - - -
                -
                - -
                -
                -<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk b/rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk deleted file mode 100644 index cb57377..0000000 --- a/rooter/0optionalapps/bwmon/files/usr/sbin/readDB.awk +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/awk - -function inInterfaces(host){ - return(interfaces ~ "(^| )"host"($| )") -} - -function newRule(arp_ip, - ipt_cmd){ - # checking for existing rules shouldn't be necessary if newRule is - # always called after db is read, arp table is read, and existing - # iptables rules are read. - ipt_cmd="iptables -t mangle -j RETURN -s " arp_ip - system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD") - ipt_cmd="iptables -t mangle -j RETURN -d " arp_ip - system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD") -} - -function total(i){ - return(bw[i "/in"] + bw[i "/out"]) -} - -function date( cmd, d){ - cmd="date +%d-%m-%Y_%H:%M:%S" - cmd | getline d - close(cmd) - #!@todo could start a process with "while true; do date ...; done" - return(d) -} - -BEGIN { - od="" - fid=1 - debug=0 - rrd=0 -} - -/^#/ { # get DB filename - FS="," - dbFile=FILENAME - next -} - -# data from database; first file -FNR==NR { #!@todo this doesn't help if the DB file is empty. - if($2 == "NA") - #!@todo could get interface IP here - n=$1 - else - n=$2 - - hosts[n] = "" # add this host/interface to hosts - mac[n] = $1 - ip[n] = $2 - inter[n] = $3 - bw[n "/in"] = $4 - bw[n "/out"] = $5 - firstDate[n] = $7 - lastDate[n] = $8 - next -} - -# not triggered on the first file -FNR==1 { - FS=" " - fid++ #!@todo use fid for all files; may be problematic for empty files - next -} - -# arp: ip hw flags hw_addr mask device -fid==2 { - #!@todo regex match IPs and MACs for sanity - arp_ip = $1 - arp_flags = $3 - arp_mac = $4 - arp_dev = $6 - if(arp_flags != "0x0" && !(arp_ip in ip)){ - if(debug) - print "new host:", arp_ip, arp_flags > "/dev/stderr" - hosts[arp_ip] = "" - mac[arp_ip] = arp_mac - ip[arp_ip] = arp_ip - inter[arp_ip] = arp_dev - bw[arp_ip "/in"] = bw[arp_ip "/out"] = 0 - firstDate[arp_ip] = lastDate[arp_ip] = date() - } - next -} - -#!@todo could use mangle chain totals or tailing "unnact" rules to -# account for data for new hosts from their first presence on the -# network to rule creation. The "unnact" rules would have to be -# maintained at the end of the list, and new rules would be inserted -# at the top. - -# skip line -# read the chain name and deal with the data accordingly -fid==3 && $1 == "Chain"{ - rrd=$2 ~ /RRDIPT_.*/ - next -} - -fid==3 && rrd && (NF < 9 || $1=="pkts"){ next } - -fid==3 && rrd { # iptables input - if($6 != "*"){ - m=$6 - n=m "/out" - } else if($7 != "*"){ - m=$7 - n=m "/in" - } else if($8 != "0.0.0.0/0"){ - m=$8 - n=m "/out" - } else { # $9 != "0.0.0.0/0" - m=$9 - n=m "/in" - } - - # remove host from array; any hosts left in array at END get new - # iptables rules - - #!@todo this deletes a host if any rule exists; if only one - # directional rule is removed, this will not remedy the situation - delete hosts[m] - - if($2 > 0){ # counted some bytes - if(mode == "diff" || mode == "noUpdate") - print n, $2 - if(mode!="noUpdate"){ - if(inInterfaces(m)){ # if label is an interface - if(!(m in mac)){ # if label was not in db (also not in - # arp table, but interfaces won't be - # there anyway) - firstDate[m] = date() - mac[m] = inter[m] = m - ip[m] = "NA" - bw[m "/in"]=bw[m "/out"]= 0 - } - } - bw[n]+=$2 - lastDate[m] = date() - } - } -} - -END { - if(mode=="noUpdate") exit - close(dbFile) - system("rm -f " dbFile) - print "#mac,ip,iface,in,out,total,first_date,last_date" > dbFile - OFS="," - for(i in mac) - print mac[i], ip[i], inter[i], bw[i "/in"], bw[i "/out"], total(i), firstDate[i], lastDate[i] > dbFile - close(dbFile) - # for hosts without rules - for(host in hosts) if(!inInterfaces(host)) newRule(host) -} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-autoapn/Makefile b/rooter/0optionalapps/ext-autoapn/Makefile deleted file mode 100644 index ef5fbc4..0000000 --- a/rooter/0optionalapps/ext-autoapn/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-autoapn -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-autoapn - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=support for Automatic APN - PKGARCH:=all -endef - -define Package/ext-autoapn/description - Helper scripts to enable Automatic APN -endef - - -define Build/Compile -endef - -define Package/ext-autoapn/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,ext-autoapn)) diff --git a/rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data b/rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data deleted file mode 100644 index 88afe61..0000000 --- a/rooter/0optionalapps/ext-autoapn/files/usr/lib/autoapn/apn.data +++ /dev/null @@ -1,2198 +0,0 @@ -00101,phone,AT&TPHONETESTSIM,nil,1,nil,nil -001010,VZWINTERNET,TestInternet,nil,1,nil,nil -20201,internet,CosmoteWirelessInternet,nil,1,nil,nil -20205,internet.vodafone.gr,VfMobileInternet,nil,1,nil,nil -20209,myq,QInternet,nil,1,nil,nil -20210,gint.b-online.gr,WindInternet,nil,1,nil,nil -20402,internet.tele2.nl,Tele2GPRS,nil,1,nil,nil -20403,internet.mvno.mobi,MVNONL,mvno,1,mvno,1 -20404,mobiledata,JumpRoam,nil,1,nil,0 -20404,iot.truphone.com,Truphone,nil,1,nil,nil -20404,live.vodafone.com,VodafoneNL,vodafone,1,vodafone,1 -20404,VZWINTERNET,EHRPD-VZWRoamingInternet,nil,3,nil,nil -20408,iot.truphone.com,Truphone,nil,1,nil,nil -20404,internet.cs4glte.com,CSpireinternational,cs3g,1,Uniroam@inet.cs.com,3 -20404,admin.cs4glte.com,CSpireinternational,nil,1,nil,nil -20404,tethering.cs4glte.com,CSpireinternational,nil,1,nil,nil -20408,KPN4G.nl,KPN/Hi4GLTEMobielinternet,nil,1,nil,nil -20408,portalmmm.nl,KPN/HiMobielInternet,nil,1,nil,nil -20408,internet.mvno.mobi,MVNONL,mvno,1,mvno,1 -20408,rabo,RaboMobielInt.,nil,1,nil,nil -20404,net.hotm,HOTmobileInternet,nil,1,nil,nil -20412,internet,TelfortInternet,nil,1,nil,nil -20416,internet,T-MobileInternet,nil,1,nil,1 -20416,internet.ben,BenInternetAbonnee,nil,1,nil,nil -20416,basic.internet.ben.data,BenInternetPrePaid,nil,1,nil,nil -20420,internet,T-MobileInternet,nil,1,nil,1 -20433,iot.truphone.com,Truphone,nil,1,nil,nil -20601,INTERNET.PROXIMUS.BE,PxInternet,nil,1,nil,nil -20601,telenetwap.be,TelenetInternet,nil,1,nil,nil -20601,iijmio.jp,IIJmio(TypeI/Roaming),iij,1,mio@iij,3 -20601,vmobile.jp,vmobile.jp(Roaming),vmobile,1,vmobile@jp,3 -20605,telenetwap.be,TelenetInternet,nil,1,nil,nil -20610,mworld.be,MobistarInternet,nil,1,nil,nil -20610,netgprs.com,netgprs.com,tsl,1,tsl,nil -20620,gprs.base.be,BASEWAP,base,1,base,1 -20628,bicsapn,BICSInternet,nil,1,nil,nil -20801,orange,OrangeWorld,orange,1,orange,1 -20801,orange-mib,OrangeEntreprise,orange,1,orange,2 -20801,orange.fr,OrangeInternet,orange,1,orange,0 -20801,ofnew.fr,CarrefourWAP,orange,1,orange,1 -20801,coriolis,Coriolis,nil,1,nil,nil -20809,sl2sfr,SFRwebphone,nil,1,nil,nil -20809,websfr,SFRoptionmodem,nil,1,nil,nil -20809,pda.newcomobile.com,BeAliv,nil,1,nil,nil -20809,iot.truphone.com,Truphone,nil,1,nil,nil -20809,coriolis,Coriolis,nil,1,nil,nil -20810,sl2sfr,SFRwebphone,nil,1,nil,nil -20810,websfr,SFRoptionModem,nil,1,nil,0 -20810,fnetnrj,NRJWEB,nil,1,nil,nil -20810,internetnrj,INTERNETNRJ,nil,1,nil,0 -20810,wap65,AuchanWAP,nil,1,nil,nil -20810,wap66,WAPLeclercMobile,nil,1,nil,nil -20810,fnetcoriolis,CoriolisWAP,nil,1,nil,nil -20810,internetcoriolis,CoriolisWEB,nil,1,nil,0 -20810,wapdebitel,WEBLaPosteMobile,nil,1,nil,nil -20810,wap68,DartySurf&Mails,nil,1,nil,nil -20810,internet68,KeyyoMobileInternet,nil,1,nil,0 -20810,wap68,KeyyoMobileWap,nil,1,nil,0 -20810,wap66,WAPRegloMobile,nil,1,nil,0 -20812,iot.truphone.com,Truphone,nil,1,nil,nil -20815,free,Free,nil,1,nil,nil -20815,free.re,FreeReInt,nil,1,nil,nil -20815,iliad,IliadInt,nil,1,nil,nil -20817,bornsip,Legos,nil,1,nil,nil -20820,mmsbouygtel.com,BouyguesTelecom,nil,1,nil,nil -20822,mobiledata,mobiledata,nil,1,nil,nil -20822,netgprs.com,netgprs.com,tsl,1,tsl,nil -20823,virgin-mobile.fr,Virginmobile,nil,1,nil,nil -20826,fnetnrj,NRJWEB,nil,1,nil,nil -20827,coriolis,Coriolis,nil,1,nil,nil -21401,airtelwap.es,Internetmóvil,wap125,1,wap@wap,1 -21401,airtelnet.es,INTERNET,vodafone,1,vodafone,1 -21402,altecom.net,ALTECOM,nil,1,nil,nil -21402,fibracat.cat,FIBRACAT,nil,1,nil,nil -21403,orangeworld,OrangeInternetMóvil,orange,1,orange,1 -21403,internet,OrangeInternetPC,orange,1,orange,0 -21403,internet.euskaltel.mobi,EuskaltelInternet,EUSKALTEL,1,CLIENTE,1 -21403,CARREFOURINTERNET,Carrefour,nil,1,nil,1 -21403,internettph,HappyInternet,nil,1,nil,nil -21403,internet.racc.net,RACCINTERNET,RACC,1,CLIENTERACC,nil -21403,internetmas,MASMovilInternet,nil,1,nil,nil -21403,ibercominternet,IbercomInternet,nil,1,nil,nil -21403,jazzinternet,jazzinternet,nil,1,nil,nil -21404,internet,YoigoInternet,nil,1,nil,nil -21405,tuenti.com,Tuenti,tuenti,1,tuenti,1 -21405,inet.es,INETRoaming,nil,1,nil,nil -21406,airtelnet.es,INTERNETGPRS,vodafone,1,vodafone,nil -21406,internet.euskaltel.mobi,EuskaltelInternet,EUSKALTEL,1,CLIENTE,1 -21406,internet.mundo-r.com,InternetR,nil,1,nil,1 -21406,internet.telecable.es,TeleCableInternet,telecable,1,telecable,1 -21406,gprs.eroskimovil.es,EroskiMovilGPRS,wap125,1,wap@wap,1 -21406,gprs.pepephone.com,DUN,nil,1,nil,0 -21406,gprsmov.pepephone.com,Internet,nil,1,nil,0 -21407,telefonica.es,Movistar,telefonica,1,telefonica,1 -21407,jazzinternet,JazztelInternet,nil,1,nil,nil -21407,movistar.es,Conexióompartida,MOVISTAR,1,MOVISTAR,1 -21407,internet.t-2.net,T-2,nil,1,nil,nil -21408,internet.euskaltel.mobi,EuskaltelInternet,EUSKALTEL,1,CLIENTE,1 -21416,internet.telecable.es,TeleCableInternet,telecable,1,telecable,nil -21418,internet.ono.com,ONOInternet,nil,1,nil,nil -21419,orangeworld,internetsimyo,orange,1,orange,1 -21421,jazzinternet,jazzinternet,nil,1,nil,nil -21427,iot.truphone.com,Truphone,nil,1,nil,nil -21432,tuenti.com,Tuenti,tuenti,1,tuenti,3 -21434,inet.es,INETInternet,nil,1,nil,nil -21601,online,TelenorOnline,nil,1,nil,nil -21601,net,DjuiceNET,nil,1,nil,0 -21601,wap,DjuiceWAP,nil,1,nil,0 -21630,internet.telekom,T-MobileH,nil,1,nil,1 -21670,internet.vodafone.net,VodafoneInternet,nil,1,nil,0 -21670,wap.vodafone.net,VodafoneLive!,vodawap,1,vodawap,1 -21670,vitamax.internet.vodafone.net,VodafoneInternetVitaMAX,nil,1,nil,nil -21670,vitamax.wap.vodafone.net,VodafoneLive!VitaMAX,vodawap,1,vodawap,1 -21803,wap.eronet.ba,HTEronetWAP,nil,1,nil,nil -21803,gprs.eronet.ba,HTEronetGPRS,nil,1,nil,nil -21805,3g1,m,nil,1,nil,nil -21890,active.bhmobile.ba,BHMobileInternet,nil,1,nil,nil -21901,internet.ht.hr,T-MobileInternet,nil,1,nil,1 -21901,web.htgprs,bonbonInternet,nil,1,nil,1 -21902,internet.tele2.hr,Tele2,nil,1,nil,nil -21910,data.vip.hr,Broadband,38591,1,38591,1 -22001,internet,Telenorinternet,gprs,1,telenor,1 -22002,internet,TelenorMNEinternet,gprs,1,gprs,nil -22003,gprswap,mt,064,1,mts,1 -22003,gprsinternet,MTSInternetRS,064,1,mts,0 -22004,tmcg-wnw,T-MobileInternet,38267,1,38267,nil -20404,pda.stm.sk.ca,SaskTel,nil,1,nil,nil -20465,agms,agms,nil,1,nil,nil -22005,vipmobile,VipGPRS,vipmobile,1,vipmobile,1 -22201,wap.tim.it,TIMWAP,nil,1,nil,nil -22201,ibox.tim.it,TIMDUN(IT),nil,1,nil,0 -22201,internet.windmobile.ca,Internet,nil,1,nil,nil -22201,modem.iusacellgsm.mx,Modem,iusacellgsm,1,iusacellgsm,0 -22201,web.iusacellgsm.mx,Internet,iusacellgsm,1,iusacellgsm,0 -22201,web.noverca.it,NOVERCAWEB,nil,1,nil,0 -22210,mobile.vodafone.it,Acc.Internetdacell,nil,1,nil,nil -22210,web.omnitel.it,TetheringInternet,nil,1,nil,0 -22210,wap.postemobile.it,PosteMobile,nil,1,nil,0 -22210,internet.postemobile.it,PosteMobile(DUN),nil,1,nil,0 -22210,mobile.erg.it,ErgMobileWAP,nil,1,nil,0 -22250,iliad,Iliad,nil,1,nil,nil -22254,data.plintron.it,Plintron,nil,1,nil,1 -22288,internet.wind,WINDWEB,nil,1,nil,nil -22288,internet.windmobile.ca,Internet,nil,1,nil,nil -22299,tre.it,3,nil,1,nil,nil -22299,apn.fastweb.it,FastwebWEB,nil,1,nil,nil -22601,live.vodafone.com,Vodafonelive!,vodafone,1,live,1 -22601,live.pre.vodafone.com,Vodafonelive!PRE,vodafone,1,live,0 -22603,broadband,CosmoteConnectMobile,nil,1,nil,nil -22603,wnw,web'n'walk,wnw,1,wnw,1 -22605,internet,Digi.Mobil,nil,1,nil,1 -22606,broadband,CosmoteConnectMobile,nil,1,nil,nil -22606,wnw,web'n'walk,wnw,1,wnw,nil -22610,net,OrangeInternet,nil,1,nil,nil -22801,gprs.swisscom.ch,SwisscomServices,nil,1,nil,nil -22802,internet,Sunriselive,nil,1,nil,nil -22803,internet,OrangeInternet,nil,1,nil,nil -22803,netgprs.com,netgprs.com,tsl,1,tsl,nil -23001,internet.t-mobile.cz,T-MobileCZ,wap,1,wap,1 -23002,internet,O2internet,nil,1,nil,nil -23003,internet,Internet,nil,1,nil,nil -23101,internet,OrangeSK,nil,1,nil,nil -23101,orangewap,OrangeWorld,wap,1,wap,1 -23102,internet,T-Mobileinternet,nil,1,nil,1 -23106,o2internet,O2internet,nil,1,nil,nil -23201,a1.net,live!,ppp,1,ppp@a1plus.at,1 -23203,internet.t-mobile.at,T-MobileLTE,tm,1,t-mobile,1 -23205,drei.at,Planet3,nil,1,nil,nil -23207,web,tele.ringweb,web,1,web@telering.at,1 -23210,drei.at,Planet3,nil,1,nil,nil -23211,bob.at,data.bob,ppp,1,data@bob.at,1 -23212,web.yesss.at,yesss!,nil,1,nil,nil -23222,data.plintron.at,Plintron,nil,1,nil,1 -23401,internet,UBIQUISYS,nil,1,nil,nil -23402,mobile.o2.co.uk,O2MOBILEWEB,O2web,1,O2web,nil -23408,internet.btonephone.com,BTOnePhoneInternet,nil,1,nil,nil -23410,mobile.o2.co.uk,O2MobileWeb,password,1,o2web,nil -23410,payandgo.o2.co.uk,O2Pay&Go,password,1,payandgo,nil -23410,prepay.tesco-mobile.com,TESCO,password,1,tescowap,1 -23410,giffgaff.com,giffgaff,password,1,giffgaff,1 -23410,mobiledata,JumpUK,nil,1,nil,0 -23411,mobile.o2.co.uk,O2MOBILEWEB,O2web,1,O2web,nil -23415,wap.vodafone.co.uk,VodafoneUK,wap,1,wap,1 -23415,pp.vodafone.co.uk,VodafoneUKPrepay,wap,1,wap,1 -23415,asdamobiles.co.uk,ASDAWAP,wap,1,wap,1 -23415,payg.talkmobile.co.uk,TalkmobPAYGWAP,wap,1,wap,1 -23415,talkmobile.co.uk,TalkmobWAP,wap,1,wap,1 -23415,mobile.talktalk.co.uk,TalkTalkWAP,nil,1,nil,nil -23415,payg.mobilebysainsburys.co.uk,Sainsbury'sPAYG,nil,1,nil,1 -23415,uk.lebara.mobi,LebaraInternet,wap,1,wap,1 -23420,three.co.uk,3,nil,1,nil,nil -23420,3hotspot,3Hotspot,nil,1,nil,0 -23426,data.lycamobile.co.uk,Lycamobile,plus,1,lmuk,1 -23430,goto.virginmobile.uk,VirginMediaMobileInternet,nil,1,user,1 -23430,everywhere,EEInternet,secure,1,eesecure,1 -23430,internet.btonephone.com,BTOnePhoneInternet,nil,1,nil,nil -23433,tslpaygnet,Internet,nil,1,nil,0 -23433,everywhere,EEInternet,secure,1,eesecure,1 -23425,iot.truphone.com,Truphone,nil,1,nil,nil -23439,Jump,Jump,nil,1,nil,nil -23439,gamma.co.uk,GammaData,nil,1,nil,nil -23450,pepper,pepperWEB(Jersey),nil,1,nil,nil -23455,internet,C&WGuernseyInternet,nil,1,nil,nil -23458,3gpronto,3GHSDPA,nil,1,nil,nil -23458,web.manxpronto.net,ManxTelecomContractWEB,gprs,1,gprs,nil -23486,everywhere,EEInternet,secure,1,eesecure,1 -23594,3hotspot,3hotspot,nil,1,nil,0 -23594,three.co.uk,3,nil,1,nil,nil -23801,internet,DKTDC,nil,1,nil,0 -23801,internet,TDCInternet,nil,1,nil,nil -23801,wap,TELMOREWAP,nil,1,nil,0 -23802,Internet,TelenorInternet,nil,1,nil,nil -23806,data.tre.dk,3,nil,1,nil,nil -23820,www.internet.mtelia.dk,TeliaSurfPort,nil,1,nil,nil -23820,webSP,CallmeInternet,nil,1,nil,nil -23830,web.orange.dk,OrangeDE,nil,1,nil,nil -23877,Internet,TelenorInternet,nil,1,nil,nil -24001,online.telia.se,Telia,nil,1,nil,nil -24001,halebop.telia.se,HalebopInternet,nil,1,nil,nil -24002,data.tre.se,3,nil,1,nil,nil -24004,data.tre.se,3,nil,1,nil,nil -24005,4g.tele2.se,Tele2Internet,nil,1,nil,nil -24005,internet.tele2.se,Tele2Internet3G,nil,1,nil,nil -24005,online.telia.se,Telia,nil,1,nil,nil -24005,halebop.telia.se,HalebopInternet,nil,1,nil,nil -24006,internet,Internet,nil,1,nil,nil -24007,4g.tele2.se,Tele2Internet,nil,1,nil,nil -24007,internet.tele2.se,Tele2Internet3G,nil,1,nil,nil -24007,internet.tele2.no,Tele2Internet,wap,1,wap,1 -24007,Jump,Jump,nil,1,nil,nil -24007,gamma.co.uk,GammaData,nil,1,nil,nil -24008,internet.telenor.se,TelenorSE,nil,1,nil,nil -24009,com4,Com4,nil,1,nil,nil -24010,data.springmobil.se,Springdata,nil,1,nil,nil -240017,halebop.telia.se,HalebopInternet,nil,1,nil,nil -24024,4g.tele2.se,Tele2Internet,nil,1,nil,nil -24024,internet.tele2.se,Tele2Internet3G,nil,1,nil,nil -24201,internet.ventelo.no,VenteloInternett,nil,1,nil,nil -24201,telenor,Telenor,nil,1,nil,nil -24202,netcom,NetCom,nil,1,nil,nil -24204,internet.tele2.no,Tele2Internet,nil,1,nil,nil -24205,internet,NwNInternet,nil,1,nil,nil -24209,com4,Com4,nil,1,nil,nil -24403,internet,DNAInternet,nil,1,nil,nil -24404,internet,DNAInternet,nil,1,nil,nil -24405,internet,ElisaInternet,nil,1,nil,nil -24405,internet.saunalahti,SaunalahtiInternet,nil,1,nil,nil -24410,internet.song.fi,TDCInternet,songnet,1,song@internet,nil -24412,internet,DNAInternet,nil,1,nil,nil -24412,dnapro.fi,DNAProInternet,nil,1,nil,1 -24412,inet.tdc.fi,TDCInternetFinland,nil,1,nil,1 -24413,internet,DNAInternet,nil,1,nil,nil -24421,internet.saunalahti,SaunalahtiInternet,nil,1,nil,nil -24491,internet,SONERAInternet,nil,1,nil,nil -24601,omnitel,OmnitelInternet,omni,1,omni,1 -24602,wap,BiteInternet,nil,1,nil,nil -24608,mezon,Mezon,nil,1,nil,nil -24603,internet.tele2.lt,Tele2InternetLT,nil,1,nil,nil -246081,VZW800,Test800,nil,3,nil,nil -246081,VZWINTERNET,TestInternet,nil,3,nil,3 -246081,VZWINTERNET,TestInternet,nil,3,nil,nil -24681,VZW800,Test800,nil,3,nil,nil -24681,VZWINTERNET,TestInternet,nil,3,nil,3 -24681,VZWINTERNET,TestInternet,nil,3,nil,nil -24701,internet.lmt.lv,LMTInternet,nil,1,nil,nil -24702,internet.tele2.lv,Tele2LVInternet,nil,1,nil,nil -24705,internet,BiteLVInternet,nil,1,nil,nil -24705,wap,BiteLVWAP,nil,1,nil,nil -24801,internet.emt.ee,EMTInternet,nil,1,nil,nil -24801,wap.emt.ee,EMTWAP,nil,1,nil,nil -24801,send.ee,Send,nil,1,nil,nil -24802,internet,ElisaInternet,nil,1,nil,nil -24802,wap,ElisaWAP,nil,1,nil,nil -24803,internet.tele2.ee,Tele2Internet,nil,1,nil,nil -25001,internet.mts.ru,MTSInternet,mts,1,mts,1 -25002,internet,MegafonInternet,nil,1,nil,nil -25011,yota.ru,YOTAInternet,nil,1,nil,nil -25020,internet.tele2.ru,TELE2Internet,nil,1,nil,nil -25028,vodalte.ru,VODAinternet,nil,1,nil,nil -25062,m.tinkoff,TinkoffMobile,nil,1,nil,nil -25099,internet.beeline.ru,BeelineInternet,beeline,1,beeline,1 -25501,internet,MTS-internet,nil,1,nil,nil -25502,internet.beeline.ua,Beeline-internet,nil,1,nil,nil -25503,www.kyivstar.net,KyivstarInternet,internet,1,igprs,1 -25503,www.djuice.com.ua,DjuiceInternet,nil,1,nil,nil -25506,internet,Life,nil,1,nil,nil -25507,3g.utel.ua,UtelInternet,nil,1,nil,nil -25701,web.velcom.by,VelcomInternet,nil,1,nil,1 -25702,mts,MTSInternet,mts,1,mts,1 -25704,internet.life.com.by,life,nil,1,nil,1 -25901,wap.orange.md,Orange_Internet_GPRS,nil,1,nil,nil -25902,internet,MoldcellInternet,nil,1,nil,nil -25905,internet3g.unite.md,UniteInternetPrePay,nil,1,nil,nil -25905,internet.unite.md,UniteInternetPostPay,nil,1,nil,nil -26001,plus,PlusInternet,nil,1,nil,nil -26002,internet,T-mobile.pl,nil,1,nil,nil -26002,heyah.pl,heyahinternet,nil,1,nil,nil -26003,Internet,OrangeInternet,internet,1,internet,1 -26006,internet,PlayInternet,nil,1,nil,nil -26033,iot.truphone.com,Truphone,nil,1,nil,nil -26044,rebtel,Rebtel,nil,1,nil,nil -26201,internet.telekom,TelekomInternet,telekom,1,telekom,1 -26202,web.vodafone.de,VodafoneDE,nil,1,nil,nil -26202,home.vodafone.de,VodafoneDE,nil,1,nil,nil -26203,internet.eplus.de,E-PlusInternet,internet,1,eplus,1 -26207,internet,o2Internet,nil,1,nil,nil -26207,pinternet.interkom.de,o2InternetPrepaid,nil,1,nil,nil -26207,webmobil1,TchiboInternet,nil,1,nil,nil -26242,iot.truphone.com,Truphone,nil,1,nil,nil -26801,net2.vodafone.pt,VodafoneNet2,vodafone,1,vodafone,1 -26801,internet.vodafone.pt,vodafonePdun,nil,1,nil,0 -26803,umts,PortalOptimus,nil,1,nil,nil -26803,modem,OptimusHotSpot,nil,1,nil,nil -26806,internet,tmninternet,nil,1,nil,nil -27001,wap.pt.lu,LUXGSMWAP,wap,1,wap,nil -27002,internet,MTXC,nil,1,nil,nil -27077,internet,TangoWAP,tango,1,tango,nil -27077,netgprs.com,netgprs.com,tsl,1,tsl,nil -27099,orange.lu,Orange,nil,1,nil,nil -27201,live.vodafone.com,VodafoneIE,nil,1,nil,nil -27201,hs.vodafone.ie,VodafoneMISP,vodafone,1,vodafone,0 -27202,3iot.com,3Ireland,nil,1,nil,nil -27202,internet,3Ireland,nil,1,nil,0 -27203,data.mymeteor.ie,MeteorData,wap,1,my,1 -27205,3ireland.ie,3Ireland,nil,1,nil,nil -27211,tescomobile.liffeytelecom.com,Tesco,nil,1,nil,nil -27401,internet,SiminnInternet,nil,1,nil,nil -27402,gprs.is,VodafoneInternet,nil,1,nil,nil -27403,gprs.is,VodafoneInternet,nil,1,nil,0 -27411,net.nova.is,NetNova,nil,1,nil,nil -27801,internet,VodafoneMT,internet,1,internet,nil -28001,cytamobile,CYTA,nil,1,nil,nil -28010,internet,MTNInternet,nil,1,nil,nil -28020,ip.primetel,PrimeTel,nil,1,nil,nil -28401,inet-gprs.mtel.bg,MTel,nil,1,nil,nil -28403,internet.vivacom.bg,VIVACOMInternet,vivacom,1,vivacom,1 -28405,telenorbg,TelenorInternet,nil,1,nil,0 -28411,bulsat.com,bulsatcom,nil,1,nil,nil -28413,apn.maxtelecom.bg,MAXTELECOM,nil,1,nil,nil -28601,internet,TURKCELLINTERNET,nil,1,nil,nil -28602,internet,Vodafoneinternet,nil,1,nil,1 -28603,internet,AVEAINTERNET,nil,1,nil,1 -29001,internet,TeleInternet,nil,1,nil,nil -29340,internet.simobil.si,Si.mobilGPRS,internet,1,simobil,1 -29341,internet,MobilniInternet,internet,1,mobitel,1 -29364,internet.t-2.net,T2,nil,1,nil,nil -29370,internet.tusmobil.si,TusmobilInternet,internet,1,tusmobil,1 -29370,telemach.net,TelemachInternet,nil,1,nil,nil -29401,internet,T-MobileMKInternet,t-mobile,1,internet,nil -29402,Internet,Cosmofon,Internet,1,Internet,nil -29403,vipoperator,Internet,vipoperator,1,vipoperator,nil -29505,em,EMnify,nil,1,nil,nil -29509,em,EMnify,nil,1,nil,nil -29509,bicsapn,BICS,nil,1,nil,nil -29702,tmcg-wnw,T-MobileInternet,38267,1,38267,nil -302220,sp.telus.com,TELUS,nil,1,nil,nil -302220,isp.telus.com,TELUSTether,nil,1,nil,nil -302220,sp.koodo.com,Koodo,nil,1,nil,nil -302220,sp.mb.com,MobileInternet,nil,1,nil,nil -302220,isp.mb.com,TetheredMobileInternet,nil,1,nil,nil -302221,isp.telus.com,TELUSISP,nil,1,nil,nil -302221,sp.koodo.com,Koodo,nil,1,nil,nil -302221,isp.mb.com,TetheredPCMobile,nil,1,nil,nil -302320,wap.davewireless.com,MOWAP,nil,1,nil,nil -302270,wisp.mobi.eastlink.ca,Internet,nil,1,nil,nil -302370,ltedata.apn,FidoTethering,nil,1,nil,nil -302370,ltemobile.apn,FidoInternet,nil,1,nil,nil -302370,sp.mts,MTS,nil,1,nil,nil -302370,internet.mts,MTSTetheringS,nil,1,nil,nil -302490,internet.windmobile.ca,Internet,nil,1,nil,nil -302500,media.ng,Media,nil,1,nil,nil -302510,media.ng,Media,nil,1,nil,nil -302520,media.ng,Media,nil,1,nil,nil -302610,pda.bell.ca,BellMobility,nil,1,nil,nil -302610,ota.bell.ca,BellMobility,nil,1,nil,nil -302660,sp.mts,MTS,nil,1,nil,nil -302660,internet.mts,MTSTethering,nil,1,nil,nil -302720,ltemobile.apn,RogersLTE,nil,1,nil,nil -302720,chatrweb.apn,chatr,nil,1,nil,nil -302720,chatrisp.apn,ChatrTethering,nil,1,nil,nil -302720,ltedata.apn,TbaytelTethering,nil,1,nil,nil -302780,pda.stm.sk.ca,SaskTel,nil,1,nil,nil -310000,VZWINTERNET,Bluewire,nil,3,nil,nil -310020,union.wap.com,UnionWirelessData,nil,1,nil,nil -310004,internet,Verizon,nil,3,nil,3 -310028,VZWINTERNET,ALUTest-SIMInternet,nil,3,nil,nil -310030,private.centennialwireless.com,Internet,priv,1,privuser,nil -310032,VZWINTERNET,Itewire,nil,3,nil,nil -310035,VZWINTERNET,Etex,nil,3,nil,nil -310040,VZWINTERNET,Mta,nil,3,nil,nil -310050,VZWINTERNET,Alaskacomm,nil,3,nil,nil -310066,internet,U.S.Cellular,*,1,*,nil -310080,corrgprs,CorrWap,nil,1,nil,nil -310090,isp,Internet,nil,1,nil,nil -310100,isp.plateau,PLATWEB,nil,1,nil,nil -310120,sprint,Sprint,nil,1,nil,nil -310120,otasn,OTA,nil,1,nil,nil -310120,cinet.spcs,SPCSGlobal,nil,1,nil,nil -310130,VZWINTERNET,Carolinawest,nil,3,nil,nil -310150,ndo,internet,nil,1,nil,nil -310160,fast.t-mobile.com,T-MobileUS160,nil,1,nil,nil -310160,pcweb.tmobile.com,T-MobileUS160DUN,none,1,none,nil -310160,fast.metropcs.com,MetroPCS160,nil,1,nil,nil -310170,isp.cingular,DataConnect,nil,1,nil,nil -310180,internet.wcc.net,WCW-INTERNET,mmsc,1,13257630000,nil -310200,fast.t-mobile.com,T-MobileUS200,nil,1,nil,nil -310200,pcweb.tmobile.com,T-MobileUS200DUN,none,1,none,nil -310200,fast.metropcs.com,MetroPCS200,nil,1,nil,nil -310210,fast.t-mobile.com,T-MobileUS210,nil,1,nil,nil -310210,pcweb.tmobile.com,T-MobileUS210DUN,none,1,none,nil -310210,fast.metropcs.com,MetroPCS210,nil,1,nil,nil -310220,fast.t-mobile.com,T-MobileUS220,nil,1,nil,nil -310220,pcweb.tmobile.com,T-MobileUS220DUN,none,1,none,nil -310220,fast.metropcs.com,MetroPCS220,nil,1,nil,nil -310230,fast.t-mobile.com,T-MobileUS230,nil,1,nil,nil -310230,pcweb.tmobile.com,T-MobileUS230DUN,none,1,none,nil -310230,fast.metropcs.com,MetroPCS230,nil,1,nil,nil -310240,fast.t-mobile.com,T-MobileUS240,nil,1,nil,nil -310240,pcweb.tmobile.com,T-MobileUS240DUN,none,1,none,nil -310240,fast.metropcs.com,MetroPCS240,nil,1,nil,nil -310250,fast.t-mobile.com,T-MobileUS250,nil,1,nil,nil -310250,pcweb.tmobile.com,T-MobileUS250DUN,none,1,none,nil -310250,fast.metropcs.com,MetroPCS250,nil,1,nil,nil -310260,fast.t-mobile.com,T-MobileGPRS,nil,1,nil,nil -310260,h2g2,ProjectFi-T,none,1,none,nil -310260,fast.metropcs.com,MetroPCS260,nil,1,nil,nil -310260,simple,SIMPLE,nil,1,nil,nil -310260,wap.tracfone,TFWAP,nil,1,nil,nil -310260,wholesale,ConsumerCellular,nil,1,nil,nil -310270,fast.t-mobile.com,T-MobileUS270,nil,1,nil,nil -310270,pcweb.tmobile.com,T-MobileUS270DUN,none,1,none,nil -310270,fast.metropcs.com,MetroPCS270,nil,1,nil,nil -310280,agms,agms,nil,1,nil,nil -310300,fast.t-mobile.com,T-MobileUS300,nil,1,nil,nil -310300,pcweb.tmobile.com,T-MobileUS300DUN,none,1,none,nil -310300,fast.metropcs.com,MetroPCS300,nil,1,nil,nil -310310,fast.t-mobile.com,T-MobileUS310,nil,1,nil,nil -310310,pcweb.tmobile.com,T-MobileUS310DUN,none,1,none,nil -310310,fast.metropcs.com,MetroPCS310,nil,1,nil,nil -310320,isp.cellularoneaz.net,CellularOneNEAZISP,nil,1,nil,nil -310330,VZWINTERNET,Alltel2,nil,3,nil,nil -310360,VZWINTERNET,Pioneer,nil,3,nil,nil -310380,proxy,Cingular380ATT,nil,1,nil,nil -310380,agms.nl.gmm,AGMSGlobal,nil,1,nil,nil -310410,broadband,ATTNextgenphone,nil,1,nil,nil -310410,phone,ATTPhone,nil,1,nil,nil -310410,wap.cingular,ATTWAP,nil,1,nil,nil -310410,PRODATA,DefenseMobile,nil,1,nil,nil -310410,tfdata,TFDATA,nil,1,nil,nil -310420,wap.gocbw.com,CBWData,nil,1,nil,nil -310430,VZWINTERNET,Gci,nil,3,nil,nil -310450,internet.vedge.com,ViaeroConnect,nil,1,nil,nil -310470,isp.cingular,DataConnect,nil,1,nil,nil -310470,wap.cingular,MediaNet,CINGULAR1,1,WAP@CINGULARGPRS.COM,nil -310470,admin.4g.ntelos.com,nTelosOta,nil,1,nil,nil -310470,internet.4g.ntelos.com,nTelosWireless,nil,1,nil,nil -310470,tethering.4g.ntelos.com,nTelosTether,nil,1,nil,nil -310480,isp.cingular,DataConnect,nil,1,nil,nil -310480,wap.cingular,MediaNet,CINGULAR1,1,WAP@CINGULARGPRS.COM,nil -310490,fast.t-mobile.com,T-MobileUS490,nil,1,nil,nil -310490,pcweb.tmobile.com,T-MobileUS490DUN,none,1,none,nil -310490,fast.metropcs.com,MetroPCS490,nil,1,nil,nil -310530,fast.t-mobile.com,T-MobileUS530,nil,1,nil,nil -310530,pcweb.tmobile.com,T-MobileUS530DUN,none,1,none,nil -310530,fast.metropcs.com,MetroPCS530,nil,1,nil,nil -310560,nxtgenphone,ATTNextgenphone,nil,1,nil,nil -310570,internet,CellularOneSmartphone,nil,1,nil,nil -310580,VZWINTERNET,Inland,nil,3,nil,nil -310590,fast.t-mobile.com,T-MobileUS590,nil,1,nil,nil -310590,pcweb.tmobile.com,T-MobileUS590DUN,none,1,none,nil -310590,fast.metropcs.com,MetroPCS590,nil,1,nil,nil -310600,VZWINTERNET,Cellcom,nil,3,nil,nil -310610,internet.epictouch,EpicINT,nil,1,nil,nil -310640,fast.t-mobile.com,T-MobileUS640,nil,1,nil,nil -310640,pcweb.tmobile.com,T-MobileUS640DUN,none,1,none,nil -310640,fast.metropcs.com,MetroPCS640,nil,1,nil,nil -310660,fast.t-mobile.com,T-MobileUS660,nil,1,nil,nil -310660,pcweb.tmobile.com,T-MobileUS660DUN,none,1,none,nil -310660,fast.metropcs.com,MetroPCS660,nil,1,nil,nil -31069,iot.truphone.com,Truphone,nil,1,nil,nil -310720,internet.com,RogersInternet,nil,1,nil,nil -310750,VZWINTERNET,Appalachian,nil,3,nil,nil -310770,i2.iwireless.com,Web2,nil,1,nil,nil -310770,wap1.iwireless.com,Web1,nil,1,nil,nil -310800,fast.t-mobile.com,T-MobileUS800,nil,1,nil,nil -310800,pcweb.tmobile.com,T-MobileUS800DUN,none,1,none,nil -310800,fast.metropcs.com,MetroPCS800,nil,1,nil,nil -310840,isp,Internet,nil,1,nil,nil -310880,wapdtcw.com,DTCdtcwap,nil,1,nil,nil -310900,VZWINTERNET,Midrivers,nil,3,nil,nil -310910,wap.firstcellular.com,WOW_WAP,nil,1,nil,nil -310920,VZWINTERNET,Jamesvalley,nil,3,nil,nil -310930,VZWINTERNET,CopperValley,nil,3,nil,nil -310960,VZWINTERNET,Nntcwire,nil,3,nil,nil -311050,VZWINTERNET,Thumbcellular,nil,3,nil,nil -311070,VZWINTERNET,Elementmobile,nil,3,nil,nil -311080,PINE,PINEWAP,nil,1,nil,nil -311140,VZWINTERNET,Sprocket,nil,3,nil,nil -311190,isp.cellular1.net,ISP,nil,1,nil,nil -311190,broadband.cellular1.net,Tether,nil,1,nil,nil -311210,internet.farmerswireless.com,FarmersGPRS,nil,1,nil,nil -311220,usccinternet,U.S.Cellular,nil,1,nil,nil -311221,usccinternet,U.S.Cellular,nil,1,nil,nil -311222,usccinternet,U.S.Cellular,nil,1,nil,nil -311223,usccinternet,U.S.Cellular,nil,1,nil,nil -311224,usccinternet,U.S.Cellular,nil,1,nil,nil -311225,usccinternet,U.S.Cellular,nil,1,nil,nil -311226,usccinternet,U.S.Cellular,nil,1,nil,nil -311227,usccinternet,U.S.Cellular,nil,1,nil,nil -311228,usccinternet,U.S.Cellular,nil,1,nil,nil -311229,usccinternet,U.S.Cellular,nil,1,nil,nil -311230,admin.cs4glte.com,CSpireota,nil,1,nil,nil -311230,internet.cs4glte.com,CSpireinternet,nil,1,nil,nil -311230,tethering.cs4glte.com,CSpiretether,nil,1,nil,nil -311310,VZWINTERNET,Leaco,nil,3,nil,nil -311340,VZWINTERNET,Illinoisvalley,nil,3,nil,nil -311350,VZWINTERNET,Nemont,nil,3,nil,nil -311370,web.gci,GCIWEB,nil,1,nil,nil -311370,web.acs,ACSWEB,nil,1,nil,nil -311410,VZWINTERNET,Chatmobrsa2,nil,3,nil,nil -311420,VZWINTERNET,Northwestcell,nil,3,nil,nil -311430,VZWINTERNET,Chatmobrsa1,nil,3,nil,nil -311440,VZWINTERNET,Bluegrass,nil,3,nil,nil -311450,VZWINTERNET,Ptci,nil,3,nil,nil -311500,wap,24-7WAP,nil,1,nil,nil -311530,mms.mymobiletxt.com,Blaze,nil,1,nil,nil -311530,wap.mymobiletxt.com,DuetInternet,nil,1,nil,nil -311580,usccinternet,U.S.Cellular,nil,1,nil,nil -311581,usccinternet,U.S.Cellular,nil,1,nil,nil -311582,usccinternet,U.S.Cellular,nil,1,nil,nil -311583,usccinternet,U.S.Cellular,nil,1,nil,nil -311584,usccinternet,U.S.Cellular,nil,1,nil,nil -311585,usccinternet,U.S.Cellular,nil,1,nil,nil -311586,usccinternet,U.S.Cellular,nil,1,nil,nil -311587,usccinternet,U.S.Cellular,nil,1,nil,nil -311588,usccinternet,U.S.Cellular,nil,1,nil,nil -311589,usccinternet,U.S.Cellular,nil,1,nil,nil -311600,VZWINTERNET,Cox,nil,3,nil,nil -311610,VZWINTERNET,Srtcomm,nil,3,nil,nil -311650,VZWINTERNET,Unitedwireless,nil,3,nil,nil -311670,VZWINTERNET,Pinebelt,nil,3,nil,nil -311740,akcell.mobi,TelAlaskaCellular,nil,1,nil,nil -311750,CdmaNai,Cleartalk,nil,1,nil,3 -311750,home.netamerica.com,ClearTalkLTE,nil,1,nil,nil -311910,mymn4g.net,MobileNation,nil,1,nil,nil -311920,VZWINTERNET,Charitonvalley,nil,3,nil,nil -311930,internet.syringawireless.com,SyringaWireless,nil,1,nil,nil -312420,admin.lte.ntwls.com,NexTechOta,nil,1,nil,nil -312420,internet.lte.ntwls.com,NexTechWireless,nil,1,nil,nil -312420,modem.lte.ntwls.com,NexTechTether,nil,1,nil,nil -312570,BlueHotspot,BlueWireless,wirelessblue,1,%M@dun.bluehandset.com,nil -330000,VZWINTERNET,Openmobile,nil,3,nil,nil -330110,lte.claropr.com,PuertoRico,nil,1,nil,1 -334020,internet.itelcel.com,Internet,webgprs2002,1,webgprs,1 -33403,internet.movistar.mx,MovistarINTERNET,movistar,1,movistar,1 -334030,internet.movistar.mx,MovistarINTERNET,movistar,1,movistar,1 -334050,web.iusacellgsm.mx,IusacellInternet,iusacellgsm,1,iusacellgsm,nil -33450,modem.iusacellgsm.mx,Modem,iusacellgsm,1,iusacellgsm,1 -334090,location.nexteldata.com.mx,Localización,nil,1,nil,0 -334090,modem.nexteldata.com.mx,Internet,nil,1,nil,0 -334090,wap.nexteldata.com.mx,Navegación,nil,1,nil,0 -33805,web,INTERNETDigicel,nil,1,nil,nil -338050,web,INTERNETDigicel,nil,1,nil,nil -33818,internet,LimeInternetPostpaid,nil,1,nil,nil -33818,ppinternet,LimeInternetPrepaid,nil,1,nil,nil -338180,internet,LimeInternetPostpaid,nil,1,nil,nil -338180,ppinternet,LimeInternetPrepaid,nil,1,nil,nil -338070,internet.ideasclaro.com.jm,ClaroWeb,nil,1,nil,1 -338180,internet,LimeInternetPostpaid,nil,1,nil,1 -34001,orangeweb,OrangeWorldCaraïbe,orange,1,orange,nil -34001,orangeweb,Orangeweb,orange,1,orange,1 -34020,web.digicelfr.com,DigicelWeb,nil,1,nil,nil -34260,internet,LimeInternetPostpaid,nil,1,nil,nil -342600,internet,Barbado,nil,1,nil,1 -34492,internet,LimeInternetPostpaid,nil,1,nil,nil -344920,internet,Antigua,nil,1,nil,1 -34614,internet,LimeInternetPostpaid,nil,1,nil,nil -346140,internet,CaymanIslands,nil,1,nil,1 -34817,internet,LimeInternetPostpaid,nil,1,nil,nil -34877,wap.digicelbvi.com,Bvi,nil,1,nil,1 -34877,wap.digicelbvi.com,Bvi,wapbvi,1,wapbvi,1 -348170,internet,Bvi,nil,1,nil,1 -35211,internet,LimeInternetPostpaid,nil,1,nil,nil -352110,internet,Grenada,nil,1,nil,1 -35486,internet,LimeInternetPostpaid,nil,1,nil,nil -354860,internet,Monserrat,nil,1,nil,1 -35611,internet,LimeInternetPostpaid,nil,1,nil,nil -356110,internet,StKittsAndNevis,nil,1,nil,1 -35811,internet,LimeInternetPostpaid,nil,1,nil,nil -36011,internet,LimeInternetPostpaid,nil,1,nil,nil -358110,internet,StLucia,nil,1,nil,1 -360110,internet,StVincent,nil,1,nil,1 -36269,web.digicelcuracao.com,Curacao,nil,1,nil,1 -36269,wap,Curacao,nil,1,nil,1 -36302,web.digicelaruba.com,INTERNETAruba,nil,1,nil,1 -363020,web.digicelaruba.com,INTERNETAruba,nil,1,nil,1 -36449,pda.newcomobile.com,BeAliv,nil,1,nil,nil -36584,internet,LimeInternetPostpaid,nil,1,nil,nil -365840,internet,Anguilla,nil,1,nil,1 -36611,internet,LimeInternetPostpaid,nil,1,nil,nil -366110,internet,Dominica,nil,1,nil,1 -36801,internet,Internet,nil,1,nil,nil -37001,orangeinternet,OrangeInternet(LTE),nil,1,nil,nil -37001,orangenet.com.do,Orangenet(3G),nil,1,nil,nil -37002,internet.ideasclaro.com.do,InternetMóvilClaro,nil,1,nil,nil -370020,internet.ideasclaro.com.do,InternetMóvilClaro,nil,1,nil,nil -37004,edge.viva.net.do,VivaEdge(GSM),viva,1,viva,1 -37202,wap.digicelha.com,Haiti,nil,1,nil,1 -37202,wap.digicelha.com,Haiti,wap01ha,1,wapha,1 -37203,natcom,NATCOMINTERNET,nil,1,nil,nil -37412,internet,Bmobileinternet,nil,1,nil,1 -374120,internet,Bmobileinternet,nil,1,nil,1 -374121,internet,Bmobileinternet,nil,1,nil,1 -374122,internet,Bmobileinternet,nil,1,nil,1 -374123,internet,Bmobileinternet,nil,1,nil,1 -374124,internet,Bmobileinternet,nil,1,nil,1 -374125,internet,Bmobileinternet,nil,1,nil,1 -374126,internet,Bmobileinternet,nil,1,nil,1 -374127,internet,Bmobileinternet,nil,1,nil,1 -374128,internet,Bmobileinternet,nil,1,nil,1 -374129,internet,Bmobileinternet,nil,1,nil,1 -37413,web.digiceltt.com,INTERNETTrinidad,nil,1,nil,1 -374130,web.digiceltt.com,INTERNETTrinidad,nil,1,nil,1 -37635,internet,LimeInternetPostpaid,nil,1,nil,nil -376350,internet,TurksAndCaicos,nil,1,nil,1 -40001,default,Azercell,nil,1,nil,nil -40002,default,Bakcell,nil,1,nil,nil -40003,default,FONEX,nil,1,nil,nil -40004,default,NarMobile,nil,1,nil,nil -40101,internet.beeline.kz,BeelineInternet,beeline,1,@internet.beeline,1 -40101,internet.dos.kz,DOSInternet,nil,1,nil,nil -40102,internet,KcellInternet,nil,1,nil,nil -40107,internet,ALTELINTERNET,nil,1,nil,nil -40177,internet,Tele2Internet,nil,1,nil,nil -40211,default,B-Mobile,nil,1,nil,nil -40277,ticlnet,TashiCell,nil,1,nil,nil -40401,portalnmms,Vodafonelive,nil,1,nil,nil -40401,www,Vodafonemobileconnect,nil,1,nil,nil -40402,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40402,airtelgprs.com,MobileOffice,nil,1,nil,nil -40403,airtelgprs.com,MobileOffice,nil,1,nil,nil -40403,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40404,internet,Idea_Internet,nil,1,nil,nil -40404,imis,IDEAGPRS,nil,1,nil,nil -40405,www,Vodafonemobileconnect,nil,1,nil,nil -40405,portalnmms,Vodafonelive,nil,1,nil,nil -40407,internet,Idea_Internet,nil,1,nil,nil -40407,imis,IDEAGPRS,nil,1,nil,nil -40409,smartnet,RelianceNet,nil,1,nil,nil -40409,smartwap,RelianceWAP,nil,1,nil,1 -40410,airtelgprs.com,MobileOffice,nil,1,nil,nil -40410,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40411,www,Vodafonemobileconnect,nil,1,nil,nil -40411,portalnmms,Vodafonelive,nil,1,nil,nil -40412,internet,Idea_Internet,nil,1,nil,nil -40412,imis,IDEAGPRS,nil,1,nil,nil -40413,www,Vodafonemobileconnect,nil,1,nil,nil -40413,portalnmms,Vodafonelive,nil,1,nil,nil -40414,internet,Idea_Internet,nil,1,nil,nil -40414,imis,IDEAGPRS,nil,1,nil,nil -40415,www,Vodafonemobileconnect,nil,1,nil,nil -40415,portalnmms,Vodafonelive,nil,1,nil,nil -40416,airtelgprs.com,MobileOffice,nil,1,nil,nil -40416,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40417,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40417,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil -40417,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil -40417,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40417,aircelgprs,AircelInternet(40417),nil,1,nil,nil -40418,smartnet,RelianceNet,nil,1,nil,nil -40418,smartwap,RelianceWAP,nil,1,nil,1 -40418,rcomnet,RelianceInternet(40418),nil,1,nil,nil -40419,internet,Idea_Internet,nil,1,nil,nil -40419,imis,IDEAGPRS,nil,1,nil,nil -40420,www,Vodafonemobileconnect,nil,1,nil,nil -40420,portalnmms,Vodafonelive,nil,1,nil,nil -40421,www,LoopMobile,nil,1,nil,nil -40422,internet,Idea_Internet,nil,1,nil,nil -40422,imis,IDEAGPRS,nil,1,nil,nil -40424,internet,Idea_Internet,nil,1,nil,nil -40424,imis,IDEAGPRS,nil,1,nil,nil -40425,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40425,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil -40425,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil -40425,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40425,aircelgprs,AircelInternet(40425),nil,1,nil,nil -40427,www,Vodafonemobileconnect,nil,1,nil,nil -40427,portalnmms,Vodafonelive,nil,1,nil,nil -40428,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40428,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil -40428,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil -40428,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40428,aircelgprs,AircelInternet(40428),nil,1,nil,nil -40429,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40429,myaircelpost,PocketInternet-Postpaid,nil,1,nil,nil -40429,myaircel,PocketInternet-Prepaid,nil,1,nil,nil -40429,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40429,aircelgprs,AircelInternet(40429),nil,1,nil,nil -40429,aircelwap,AircelWAP(40429),nil,1,nil,nil -40430,www,Vodafonemobileconnect,nil,1,nil,nil -40430,portalnmms,Vodafonelive,nil,1,nil,nil -40431,airtelgprs.com,MobileOffice,nil,1,nil,nil -40431,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40433,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40433,myaircelpost,PocketInternet-Postpaid,nil,1,nil,nil -40433,myaircel,PocketInternet-Prepaid,nil,1,nil,nil -40433,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40433,aircelgprs,AircelInternet(40433),nil,1,nil,nil -40433,aircelwap,AircelWAP(40433),nil,1,nil,nil -40434,bsnlnet,bsnlnet,nil,1,nil,1 -40434,bsnllive,bsnllive,nil,1,nil,nil -40435,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40435,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil -40435,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil -40435,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40435,aircelgprs,AircelInternet(40435),nil,1,nil,nil -40436,smartnet,RelianceNet,nil,1,nil,nil -40436,smartwap,RelianceWAP,nil,1,nil,1 -40436,rcomnet,RelianceInternet(40436),nil,1,nil,nil -40437,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40437,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil -40437,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil -40437,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40437,aircelgprs,AircelInternet(40437),nil,1,nil,nil -40438,bsnlnet,bsnlnet,nil,1,nil,nil -40438,bsnllive,bsnllive,nil,1,nil,nil -40440,airtelgprs.com,MobileOffice,nil,1,nil,nil -40440,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40441,aircelgprs.po,Aircel-GPRS-Postpaid,nil,1,nil,nil -40441,aircelgprs.pr,Aircel-GPRS-Prepaid,nil,1,nil,nil -40441,aircelwap.po,PocketInternet-Postpaid,nil,1,nil,nil -40441,aircelwap.pr,PocketInternet-Prepaid,nil,1,nil,nil -40441,aircelgprs,AircelInternet(40441),nil,1,nil,nil -40441,aircelwap,AircelWAP(40441),nil,1,nil,nil -40442,aircelgprs.po,Aircel-GPRS-Postpaid,nil,1,nil,nil -40442,aircelgprs.pr,Aircel-GPRS-Prepaid,nil,1,nil,nil -40442,aircelwap.po,PocketInternet-Postpaid,nil,1,nil,nil -40442,aircelwap.pr,PocketInternet-Prepaid,nil,1,nil,nil -40442,aircelgprs,AircelInternet(40442),nil,1,nil,nil -40443,www,Vodafonemobileconnect,nil,1,nil,nil -40443,portalnmms,Vodafonelive,nil,1,nil,nil -40444,internet,Idea_Internet,nil,1,nil,nil -40444,imis,IDEAGPRS,nil,1,nil,nil -40445,airtelgprs.com,MobileOffice,nil,1,nil,nil -40445,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40446,www,Vodafonemobileconnect,nil,1,nil,nil -40446,portalnmms,Vodafonelive,nil,1,nil,nil -40449,airtelgprs.com,MobileOffice,nil,1,nil,nil -40449,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40450,smartnet,RelianceNet,nil,1,nil,nil -40450,smartwap,RelianceWAP,nil,1,nil,1 -40451,bsnlnet,bsnlnet,nil,1,nil,nil -40451,bsnllive,bsnllive,nil,1,nil,nil -40452,smartnet,RelianceNet,nil,1,nil,nil -40452,smartwap,RelianceWAP,nil,1,nil,1 -40453,bsnlnet,bsnlnet,nil,1,nil,nil -40453,bsnllive,bsnllive,nil,1,nil,nil -40454,bsnlnet,bsnlnet,nil,1,nil,nil -40454,bsnllive,bsnllive,nil,1,nil,nil -40455,bsnlnet,bsnlnet,nil,1,nil,nil -40455,bsnllive,bsnllive,nil,1,nil,nil -40456,internet,Idea_Internet,nil,1,nil,nil -40456,imis,IDEAGPRS,nil,1,nil,nil -40457,bsnlnet,bsnlnet,nil,1,nil,nil -40457,bsnllive,bsnllive,nil,1,nil,nil -40458,bsnlnet,bsnlnet,nil,1,nil,nil -40458,bsnllive,bsnllive,nil,1,nil,nil -40459,bsnlnet,bsnlnet,nil,1,nil,nil -40459,bsnllive,bsnllive,nil,1,nil,nil -40460,www,Vodafonemobileconnect,nil,1,nil,nil -40460,portalnmms,Vodafonelive,nil,1,nil,nil -40462,bsnlnet,bsnlnet,nil,1,nil,nil -40462,bsnllive,bsnllive,nil,1,nil,nil -40464,bsnlnet,bsnlnet,nil,1,nil,nil -40464,bsnllive,bsnllive,nil,1,nil,nil -40466,bsnlnet,bsnlnet,nil,1,nil,nil -40466,bsnllive,bsnllive,nil,1,nil,nil -40467,smartnet,RelianceNet,nil,1,nil,nil -40467,smartwap,RelianceWAP,nil,1,nil,1 -40468,mtnl.net,MTNL,mtnl123,1,mtnl,0 -40469,mtnl.net,MTNL,mtnl123,1,mtnl,0 -40470,airtelgprs.com,MobileOffice,nil,1,nil,nil -40470,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40471,bsnlnet,bsnlnet,nil,1,nil,nil -40471,bsnllive,bsnllive,nil,1,nil,nil -40472,bsnlnet,bsnlnet,nil,1,nil,nil -40472,bsnllive,bsnllive,nil,1,nil,nil -40473,bsnlnet,bsnlnet,nil,1,nil,nil -40473,bsnllive,bsnllive,nil,1,nil,nil -40474,bsnlnet,bsnlnet,nil,1,nil,nil -40474,bsnllive,bsnllive,nil,1,nil,nil -40475,bsnlnet,bsnlnet,nil,1,nil,nil -40475,bsnllive,bsnllive,nil,1,nil,nil -40476,bsnlnet,bsnlnet,nil,1,nil,nil -40476,bsnllive,bsnllive,nil,1,nil,nil -40477,bsnlnet,bsnlnet,nil,1,nil,nil -40477,bsnllive,bsnllive,nil,1,nil,nil -40478,internet,Idea_Internet,nil,1,nil,nil -40478,imis,IDEAGPRS,nil,1,nil,nil -40479,bsnlnet,bsnlnet,nil,1,nil,nil -40479,bsnllive,bsnllive,nil,1,nil,nil -40480,bsnlnet,bsnlnet,nil,1,nil,nil -40480,bsnllive,bsnllive,nil,1,nil,nil -40481,bsnlnet,bsnlnet,nil,1,nil,nil -40481,bsnllive,bsnllive,nil,1,nil,nil -40482,internet,Idea_Internet,nil,1,nil,nil -40482,imis,IDEAGPRS,nil,1,nil,nil -40483,smartnet,RelianceNet,nil,1,nil,nil -40483,smartwap,RelianceWAP,nil,1,nil,1 -40484,www,Vodafonemobileconnect,nil,1,nil,nil -40484,portalnmms,Vodafonelive,nil,1,nil,nil -40485,smartnet,RelianceNet,nil,1,nil,nil -40485,smartwap,RelianceWAP,nil,1,nil,1 -40486,www,Vodafonemobileconnect,nil,1,nil,nil -40486,portalnmms,Vodafonelive,nil,1,nil,nil -40487,internet,Idea_Internet,nil,1,nil,nil -40487,imis,IDEAGPRS,nil,1,nil,nil -40488,www,Vodafonemobileconnect,nil,1,nil,nil -40488,portalnmms,Vodafonelive,nil,1,nil,nil -40489,internet,Idea_Internet,nil,1,nil,nil -40489,imis,IDEAGPRS,nil,1,nil,nil -40490,airtelgprs.com,MobileOffice,nil,1,nil,nil -40490,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40491,aircelwebpost,Aircel-GPRS-Postpaid,nil,1,nil,nil -40491,aircelwappost,PocketInternet-Postpaid,nil,1,nil,nil -40491,aircelwap,PocketInternet-Prepaid,nil,1,nil,nil -40491,aircelweb,Aircel-GPRS-Prepaid,nil,1,nil,nil -40492,airtelgprs.com,MobileOffice,nil,1,nil,nil -40492,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40493,airtelgprs.com,MobileOffice,nil,1,nil,nil -40493,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40494,airtelgprs.com,MobileOffice,nil,1,nil,nil -40494,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40495,airtelgprs.com,MobileOffice,nil,1,nil,nil -40495,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40496,airtelgprs.com,MobileOffice,nil,1,nil,nil -40496,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40497,airtelgprs.com,MobileOffice,nil,1,nil,nil -40497,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40498,airtelgprs.com,MobileOffice,nil,1,nil,nil -40498,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40501,rcomnet,Netconnect,nil,1,nil,nil -40501,rcomwap,RelianceMbWorld,nil,1,nil,nil -40503,rcomnet,Netconnect,nil,1,nil,nil -40503,rcomwap,RelianceMbWorld,nil,1,nil,nil -40504,rcomnet,Netconnect,nil,1,nil,nil -40504,rcomwap,RelianceMbWorld,nil,1,nil,nil -40505,rcomnet,Netconnect,nil,1,nil,nil -40505,rcomwap,RelianceMbWorld,nil,1,nil,nil -40506,rcomnet,Netconnect,nil,1,nil,nil -40506,rcomwap,RelianceMbWorld,nil,1,nil,nil -40507,rcomnet,Netconnect,nil,1,nil,nil -40507,rcomwap,RelianceMbWorld,nil,1,nil,nil -40508,rcomnet,Netconnect,nil,1,nil,nil -40508,rcomwap,RelianceMbWorld,nil,1,nil,nil -40509,rcomnet,Netconnect,nil,1,nil,nil -40509,rcomwap,RelianceMbWorld,nil,1,nil,nil -40510,rcomnet,Netconnect,nil,1,nil,nil -40510,rcomwap,RelianceMbWorld,nil,1,nil,nil -40511,rcomnet,Netconnect,nil,1,nil,nil -40511,rcomwap,RelianceMbWorld,nil,1,nil,nil -40512,rcomnet,Netconnect,nil,1,nil,nil -40512,rcomwap,RelianceMbWorld,nil,1,nil,nil -40513,rcomnet,Netconnect,nil,1,nil,nil -40513,rcomwap,RelianceMbWorld,nil,1,nil,nil -40514,rcomnet,Netconnect,nil,1,nil,nil -40514,rcomwap,RelianceMbWorld,nil,1,nil,nil -40515,rcomnet,Netconnect,nil,1,nil,nil -40515,rcomwap,RelianceMbWorld,nil,1,nil,nil -40517,rcomnet,Netconnect,nil,1,nil,nil -40517,rcomwap,RelianceMbWorld,nil,1,nil,nil -40518,rcomnet,Netconnect,nil,1,nil,nil -40518,rcomwap,RelianceMbWorld,nil,1,nil,nil -40519,rcomnet,Netconnect,nil,1,nil,nil -40519,rcomwap,RelianceMbWorld,nil,1,nil,nil -40520,rcomnet,Netconnect,nil,1,nil,nil -40520,rcomwap,RelianceMbWorld,nil,1,nil,nil -40521,rcomnet,Netconnect,nil,1,nil,nil -40521,rcomwap,RelianceMbWorld,nil,1,nil,nil -40522,rcomnet,Netconnect,nil,1,nil,nil -40522,rcomwap,RelianceMbWorld,nil,1,nil,nil -40523,rcomnet,Netconnect,nil,1,nil,nil -40523,rcomwap,RelianceMbWorld,nil,1,nil,nil -405025,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405025,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405026,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405026,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405027,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405027,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405028,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405028,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405029,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405029,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405030,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405030,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405031,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405031,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405032,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405032,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405033,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405033,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405034,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405034,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405035,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405035,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405036,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405036,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405037,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405037,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405038,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405038,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405039,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405039,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405040,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405040,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405041,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405041,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405042,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405042,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405043,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405043,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405044,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405044,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405045,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405045,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405046,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405046,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -405047,TATA.DOCOMO.INTERNET,TATADOCOMOINTERNET,nil,1,nil,nil -405047,TATA.DOCOMO.DIVE.IN,TATADOCOMODIVE-IN,nil,1,nil,nil -40551,airtelgprs.com,MobileOffice,nil,1,nil,nil -40551,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40552,airtelgprs.com,MobileOffice,nil,1,nil,nil -40552,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40553,airtelgprs.com,MobileOffice,nil,1,nil,nil -40553,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40554,airtelgprs.com,MobileOffice,nil,1,nil,nil -40554,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40555,airtelgprs.com,MobileOffice,nil,1,nil,nil -40555,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40556,airtelgprs.com,MobileOffice,nil,1,nil,nil -40556,airtelfun.com,AIRTELLIVE,nil,1,nil,nil -40566,www,Vodafonemobileconnect,nil,1,nil,nil -40566,portalnmms,Vodafonelive,nil,1,nil,nil -40567,www,Vodafonemobileconnect,nil,1,nil,nil -40567,portalnmms,Vodafonelive,nil,1,nil,nil -40570,internet,Idea_Internet,nil,1,nil,nil -40570,imis,IDEAGPRS,nil,1,nil,nil -405750,www,Vodafonemobileconnect,nil,1,nil,nil -405750,portalnmms,Vodafonelive,nil,1,nil,nil -405751,www,Vodafonemobileconnect,nil,1,nil,nil -405751,portalnmms,Vodafonelive,nil,1,nil,nil -405752,www,Vodafonemobileconnect,nil,1,nil,nil -405752,portalnmms,Vodafonelive,nil,1,nil,nil -405753,www,Vodafonemobileconnect,nil,1,nil,nil -405753,portalnmms,Vodafonelive,nil,1,nil,nil -405754,www,Vodafonemobileconnect,nil,1,nil,nil -405754,portalnmms,Vodafonelive,nil,1,nil,nil -405755,www,Vodafonemobileconnect,nil,1,nil,nil -405755,portalnmms,Vodafonelive,nil,1,nil,nil -405756,www,Vodafonemobileconnect,nil,1,nil,nil -405756,portalnmms,Vodafonelive,nil,1,nil,nil -405799,internet,Idea_Internet,nil,1,nil,nil -405799,imis,IDEAGPRS,nil,1,nil,nil -405800,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405800,aircelwap,PocketInternet,nil,1,nil,nil -405801,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405801,aircelwap,PocketInternet,nil,1,nil,nil -405802,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405802,aircelwap,PocketInternet,nil,1,nil,nil -405803,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405803,aircelwap,PocketInternet,nil,1,nil,nil -405804,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405804,aircelwap,PocketInternet,nil,1,nil,nil -405805,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405805,aircelwap,PocketInternet,nil,1,nil,nil -405806,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405806,aircelwap,PocketInternet,nil,1,nil,nil -405807,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405807,aircelwap,PocketInternet,nil,1,nil,nil -405808,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405808,aircelwap,PocketInternet,nil,1,nil,nil -405809,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405809,aircelwap,PocketInternet,nil,1,nil,nil -405810,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405810,aircelwap,PocketInternet,nil,1,nil,nil -405811,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405811,aircelwap,PocketInternet,nil,1,nil,nil -405812,aircelgprs,Aircel-GPRS,nil,1,nil,nil -405812,aircelwap,PocketInternet,nil,1,nil,nil -405813,uninor,UninorInternet,nil,1,nil,1 -405813,uninor,UninorWap,nil,1,nil,nil -405814,uninor,UninorInternet,nil,1,nil,1 -405814,uninor,UninorWap,nil,1,nil,nil -405815,uninor,UninorInternet,nil,1,nil,1 -405815,uninor,UninorWap,nil,1,nil,nil -405816,uninor,UninorInternet,nil,1,nil,1 -405816,uninor,UninorWap,nil,1,nil,nil -405817,uninor,UninorInternet,nil,1,nil,1 -405817,uninor,UninorWap,nil,1,nil,nil -405818,uninor,UninorInternet,nil,1,nil,1 -405818,uninor,UninorWap,nil,1,nil,nil -405819,uninor,UninorInternet,nil,1,nil,1 -405819,uninor,UninorWap,nil,1,nil,nil -405820,uninor,UninorInternet,nil,1,nil,1 -405820,uninor,UninorWap,nil,1,nil,nil -405821,uninor,UninorInternet,nil,1,nil,1 -405821,uninor,UninorWap,nil,1,nil,nil -405822,uninor,UninorInternet,nil,1,nil,1 -405822,uninor,UninorWap,nil,1,nil,nil -405823,vinternet.com,Videocon,nil,1,nil,nil -405824,vinternet.com,Videocon,nil,1,nil,nil -405825,vinternet.com,Videocon,nil,1,nil,nil -405826,vinternet.com,Videocon,nil,1,nil,nil -405827,vinternet.com,Videocon,nil,1,nil,nil -405828,vinternet.com,Videocon,nil,1,nil,nil -405829,vinternet.com,Videocon,nil,1,nil,nil -405830,vinternet.com,Videocon,nil,1,nil,nil -405831,vinternet.com,Videocon,nil,1,nil,nil -405832,vinternet.com,Videocon,nil,1,nil,nil -405833,vinternet.com,Videocon,nil,1,nil,nil -405834,vinternet.com,Videocon,nil,1,nil,nil -405835,vinternet.com,Videocon,nil,1,nil,nil -405836,vinternet.com,Videocon,nil,1,nil,nil -405837,vinternet.com,Videocon,nil,1,nil,nil -405838,vinternet.com,Videocon,nil,1,nil,nil -405839,vinternet.com,Videocon,nil,1,nil,nil -405840,vinternet.com,Videocon,nil,1,nil,nil -405841,vinternet.com,Videocon,nil,1,nil,nil -405842,vinternet.com,Videocon,nil,1,nil,nil -405843,vinternet.com,Videocon,nil,1,nil,nil -405844,uninor,UninorInternet,nil,1,nil,1 -405844,uninor,UninorWap,nil,1,nil,nil -405845,internet,Idea_Internet,nil,1,nil,nil -405845,imis,IDEAGPRS,nil,1,nil,nil -405846,internet,Idea_Internet,nil,1,nil,nil -405846,imis,IDEAGPRS,nil,1,nil,nil -405847,internet,Idea_Internet,nil,1,nil,nil -405847,imis,IDEAGPRS,nil,1,nil,nil -405848,internet,Idea_Internet,nil,1,nil,nil -405848,imis,IDEAGPRS,nil,1,nil,nil -405849,internet,Idea_Internet,nil,1,nil,nil -405849,imis,IDEAGPRS,nil,1,nil,nil -405850,internet,Idea_Internet,nil,1,nil,nil -405850,imis,IDEAGPRS,nil,1,nil,nil -405851,internet,Idea_Internet,nil,1,nil,nil -405851,imis,IDEAGPRS,nil,1,nil,nil -405852,internet,Idea_Internet,nil,1,nil,nil -405852,imis,IDEAGPRS,nil,1,nil,nil -405853,internet,Idea_Internet,nil,1,nil,nil -405853,imis,IDEAGPRS,nil,1,nil,nil -405854,www,LoopInternet(405854),nil,1,nil,nil -405855,www,LoopInternet(405855),nil,1,nil,nil -405856,www,LoopInternet(405856),nil,1,nil,nil -405857,www,LoopInternet(405857),nil,1,nil,nil -405858,www,LoopInternet(405858),nil,1,nil,nil -405859,www,LoopInternet(405859),nil,1,nil,nil -405860,www,LoopInternet(405860),nil,1,nil,nil -405861,www,LoopInternet(405861),nil,1,nil,nil -405862,www,LoopInternet(405862),nil,1,nil,nil -405863,www,LoopInternet(405863),nil,1,nil,nil -405864,www,LoopInternet(405864),nil,1,nil,nil -405865,www,LoopInternet(405865),nil,1,nil,nil -405866,www,LoopInternet(405866),nil,1,nil,nil -405867,www,LoopInternet(405867),nil,1,nil,nil -405868,www,LoopInternet(405868),nil,1,nil,nil -405869,www,LoopInternet(405869),nil,1,nil,nil -405870,www,LoopInternet(405870),nil,1,nil,nil -405871,www,LoopInternet(405871),nil,1,nil,nil -405872,www,LoopInternet(405872),nil,1,nil,nil -405873,www,LoopInternet(405873),nil,1,nil,nil -405874,www,LoopInternet(405874),nil,1,nil,nil -405875,uninor,UninorInternet,nil,1,nil,1 -405875,uninor,UninorWap,nil,1,nil,nil -405876,uninor,UninorInternet,nil,1,nil,1 -405876,uninor,UninorWap,nil,1,nil,nil -405877,uninor,UninorInternet,nil,1,nil,1 -405877,uninor,UninorWap,nil,1,nil,nil -405878,uninor,UninorInternet,nil,1,nil,1 -405878,uninor,UninorWap,nil,1,nil,nil -405879,uninor,UninorInternet,nil,1,nil,1 -405879,uninor,UninorWap,nil,1,nil,nil -405880,uninor,UninorInternet,nil,1,nil,1 -405880,uninor,UninorWap,nil,1,nil,nil -405881,gprs.stel.in,STEL,nil,1,nil,nil -405882,gprs.stel.in,STEL,nil,1,nil,nil -405883,gprs.stel.in,STEL,nil,1,nil,nil -405884,gprs.stel.in,STEL,nil,1,nil,nil -405885,gprs.stel.in,STEL,nil,1,nil,nil -405886,gprs.stel.in,STEL,nil,1,nil,nil -405908,internet,IDEA,nil,1,nil,nil -405909,internet,IDEA,nil,1,nil,nil -405910,internet,IDEA,nil,1,nil,nil -405911,internet,IDEA,nil,1,nil,nil -405912,internet,Cheers,nil,1,nil,nil -405913,internet,Cheers,nil,1,nil,nil -405914,internet,Cheers,nil,1,nil,nil -405915,internet,Cheers,nil,1,nil,nil -405916,internet,Cheers,nil,1,nil,nil -405917,internet,Cheers,nil,1,nil,nil -405918,internet,Cheers,nil,1,nil,nil -405919,internet,Cheers,nil,1,nil,nil -405920,internet,Cheers,nil,1,nil,nil -405921,internet,Cheers,nil,1,nil,nil -405922,internet,Cheers,nil,1,nil,nil -405923,internet,Cheers,nil,1,nil,nil -405924,internet,Cheers,nil,1,nil,nil -405925,uninor,UninorInternet,nil,1,nil,1 -405925,uninor,UninorWap,nil,1,nil,nil -405926,uninor,UninorInternet,nil,1,nil,1 -405926,uninor,UninorWap,nil,1,nil,nil -405927,uninor,UninorInternet,nil,1,nil,1 -405927,uninor,UninorWap,nil,1,nil,nil -405928,uninor,UninorInternet,nil,1,nil,1 -405928,uninor,UninorWap,nil,1,nil,nil -405929,uninor,UninorInternet,nil,1,nil,1 -405929,uninor,UninorWap,nil,1,nil,nil -405930,internet,Cheers,nil,1,nil,nil -405931,internet,Cheers,nil,1,nil,nil -405932,vinternet.com,Videocon,nil,1,nil,nil -41001,connect.mobilinkworld.com,MobilinkWAPGPRS,Mobilink,1,Mobilink,nil -41003,Ufone.internet,UfoneWAP,nil,1,nil,nil -41004,zonginternet,ZONGWAP,nil,1,nil,nil -41006,internet,TelenorWAP,nil,1,nil,nil -41007,Wap.warid,WaridWAP,nil,1,nil,nil -410310,att.mvno,ConsumerCellular,nil,1,nil,nil -41201,default,AWCC,nil,1,nil,nil -41220,default,Roshan,nil,1,nil,nil -41240,default,MTN,nil,1,nil,nil -41250,default,Etisalat,nil,1,nil,nil -41301,default,Mobitel,nil,1,nil,nil -41302,default,Dialog,nil,1,nil,nil -41303,default,Etisalat,nil,1,nil,nil -41305,default,Airtel,nil,1,nil,nil -41308,default,Hutch,nil,1,nil,nil -41401,default,MPT,nil,1,nil,nil -41405,Internet,OoredooInternet,nil,1,nil,nil -41501,internet.mic1.com.lb,AlfaInternet,mic1,1,mic1,nil -41501,wap.mic1.com.lb,Alfawap,mic1,1,mic1,nil -41503,touch,touch,nil,1,nil,nil -41503,wap,touch_WAP,nil,1,nil,nil -41601,zain,ZainJOInternet,zain,1,zain,1 -41601,Zain,ZainJOStreaming,zain,1,zain,1 -41603,net,Umniahinternet,nil,1,nil,nil -41603,wap,UmniahWAP,nil,1,nil,nil -416770,net.orange.jo,OrangeInternet,net,1,net,1 -416770,wap.orange.jo,OrangeWAP,wap,1,wap,1 -41677,net.orange.jo,OrangeInternet,net,1,net,1 -41677,wap.orange.jo,OrangeWAP,wap,1,wap,1 -41701,net.syriatel.com,SyriatelNet,nil,1,nil,nil -41702,internet,MTNWAP,nil,1,nil,nil -41805,net.asiacell.com,AsiacellInternet,nil,1,nil,nil -41808,default,SanaTel,nil,1,nil,nil -41820,internet,ZAIN-GPRS,atheer,1,atheer,1 -41830,internet,ZAIN-GPRS,atheer,1,atheer,1 -41840,internet.korek.com,Korek9595,nil,1,nil,nil -41840,net.korek.com,Korek9191,korek,1,korek,nil -41845,default,Mobitel,nil,1,nil,nil -41862,default,Itisaluna,nil,1,nil,nil -41892,default,Omnnea,nil,1,nil,nil -41902,pps,MI,pps,1,pps,nil -41902,pps,ZainWAP,pps,1,pps,3 -41903,action.ooredoo.com,OoredooAction,nil,1,nil,1 -41903,mms.ooredoo.com,OoredooMMS,nil,1,nil,1 -41904,viva,VIVA-KW,nil,1,nil,0 -42001,jawalnet.com.sa,STC-GPRS,nil,1,nil,nil -42003,web1,MobilyWEB,nil,1,nil,nil -42003,wap2,Mobilyprepaid-GPRS,nil,1,nil,nil -42003,wap1,Mobilypostpaid-GPRS,nil,1,nil,nil -42003,web2,MobilyWEB2,nil,1,nil,nil -42004,zain,zain-InternetWap,nil,1,nil,0 -42101,default,SabaFon,nil,1,nil,nil -42102,default,MTN,nil,1,nil,nil -42103,default,YemenMobile,nil,1,nil,nil -42104,default,HiTS-UNITEL,nil,1,nil,nil -42202,taif,OmanMobileInternet,taif,1,taif,1 -42203,isp.nawras.com.om,NawrasInternet,test,1,test,1 -42402,etisalat.ae,EtisalatDataPackage,nil,1,nil,1 -42402,etisalat,WeyakWap,nil,1,nil,1 -42403,du,duInternet,nil,1,nil,nil -42501,uwap.orange.co.il,3GPortal,nil,1,nil,nil -42502,sphone,CellcomInternet,nil,1,nil,nil -42503,sphone.pelephone.net.il,SphonePelephone,pcl,1,pcl@3g,2 -42505,wap,JawwalWAP,nil,1,nil,nil -42506,internet,Internet,nil,1,nil,nil -42507,net.hotm,InternetHOTmobile,nil,1,nil,nil -42507,pc.hotm,PCHOTmobile,nil,1,nil,0 -42508,internet.golantelecom.net.il,GolanTelecomInternet,nil,1,nil,nil -42510,uwap.orange.co.il,3GPortal,nil,1,nil,nil -42514,data.youphone.co.il,YouPhone,nil,1,nil,nil -42515,hcminternet,HomeCellularInternet,nil,1,nil,nil -42516,internet.rl,RamiLevi3G,nil,1,nil,nil -42601,internet.batelco.com,BatelcoInternet,nil,1,nil,nil -42601,wap.batelco.com,BatelcoWAP,wap,1,wap,0 -42602,internet,ZainBHInternet,internet,1,internet,0 -42602,wap,ZainBHWAP,wap,1,wap,0 -42604,viva.bh,VIVAGPRS,nil,1,nil,nil -42604,vivawap.bh,VIVAWAP,nil,1,nil,nil -42701,data,Internet,nil,1,nil,1 -42702,web.vodafone.com.qa,Vodainternet,nil,1,nil,nil -42888,default,Unitel,nil,1,nil,nil -42891,default,Skytel,nil,1,nil,nil -42898,default,G.Mobile,nil,1,nil,nil -42899,default,MobiCom,nil,1,nil,nil -42901,default,Namaste/NTMobile,nil,1,nil,nil -42902,default,Ncell,nil,1,nil,nil -42903,default,Sky/C-Phone,nil,1,nil,nil -42904,default,SmartCell,nil,1,nil,nil -43211,mcinet,MCI-GPRS,nil,1,nil,nil -43214,mcinet,MCI-GPRS,nil,1,nil,nil -43219,mcinet,MCI-GPRS,nil,1,nil,nil -43220,rightel,rightel,nil,1,nil,nil -43235,mtnirancell,Irancell-GPRS,nil,1,nil,nil -43270,mcinet,MCI-GPRS,nil,1,nil,nil -43293,mcinet,MCI-GPRS,nil,1,nil,nil -43404,internet.beeline.uz,Beeline-UZBInternet,beeline,1,beeline,1 -43405,internet,UCELLInternet,nil,1,nil,nil -43406,default,PerfectumMobile,nil,1,nil,nil -43407,net.mts.uz,MTS-UZBInternet,mts,1,mts,1 -43601,default,Tcell,nil,1,nil,nil -43602,default,Tcell,nil,1,nil,nil -43603,default,Megafon,nil,1,nil,nil -43604,default,Babilon-M,nil,1,nil,nil -43605,default,Tacom,nil,1,nil,nil -43612,default,Tcell,nil,1,nil,nil -43701,default,Beeline,nil,1,nil,nil -43703,default,Fonex,nil,1,nil,nil -43705,default,MegaCom,nil,1,nil,nil -43709,default,O!,nil,1,nil,nil -43801,default,MTS(BARASHCommunication),nil,1,nil,nil -43802,default,TM-Cell,nil,1,nil,nil -44003,iijmio.jp,IIJmio(TypeI),iij,1,mio@iij,3 -44003,vmobile.jp,vmobile.jp,vmobile,1,vmobile@jp,3 -44010,spmode.ne.jp,sp-mode,nil,1,nil,nil -44010,mopera.net,moperaU,nil,1,nil,nil -44010,bmobile.ne.jp,b-mobileforNexus,bmobile,1,bmobile@nx,3 -44010,iijmio.jp,IIJmio,iij,1,mio@iij,3 -44010,3g-d-2.ocn.ne.jp,OCNモバイルONE(3G),mobile,1,mobileid@ocn,2 -44010,lte-d.ocn.ne.jp,OCNモバイルONE(LTE),mobile,1,mobileid@ocn,2 -44010,ratel.com,RATEL,ratel,1,ratel@ratel.com,3 -44020,plus.acs.jp,Application,ym,1,ym,2 -44020,ratel.com,RATEL,ratel,1,ratel@ratel.com,3 -44051,ratel.com,RATEL,ratel,1,ratel@ratel.com,3 -44051,a.rmobile.jp,Rakuten,0000,1,rakuten@vdm,3 -45005,lte.sktelecom.com,SKTLTEINTERNET,nil,1,nil,nil -45005,web.sktelecom.com,SKT3GINTERNET,nil,1,nil,nil -45005,lte-roaming.sktelecom.com,SKTLTERoaming,nil,1,nil,nil -45005,roaming.sktelecom.com,SKT3GRoaming,nil,1,nil,nil -45011,web.sktelecom.com,SKT3GINTERNET,nil,1,nil,nil -45011,lte-roaming.sktelecom.com,SKTLTERoaming,nil,1,nil,nil -45011,roaming.sktelecom.com,SKT3GRoaming,nil,1,nil,nil -45006,internet.lguplus.co.kr,LGuplus,nil,1,nil,nil -45006,lte-roaming.lguplus.co.kr,LGuplusLTERoaming,nil,1,nil,0 -45006,wroaming.lguplus.co.kr,LGuplusRoaming,nil,1,nil,0 -45008,lte.ktfwing.com,KT,nil,1,nil,nil -45201,m-wap,Mobi-wap-gprs2,mms,1,mms,1 -45202,m3-world,Vina-wap-gprs,mms,1,mms,1 -45204,v-internet,Viettel-wap-gprs1,nil,1,nil,nil -45204,v-wap,Viettel-wap-gprs2,nil,1,nil,nil -45205,internet,Vietnamobile_GPRS3,nil,1,nil,nil -45205,wap,Vietnamobile_GPRS1,nil,1,nil,nil -45207,internet,Gmobile-wap-gprs2,nil,1,nil,nil -45208,e-internet,e-internet,nil,1,nil,nil -45208,e-wap,e-wap,nil,1,nil,nil -45400,mobile,1O1O,nil,1,nil,3 -45400,NWMOBILE,NWMOBILE,nil,1,nil,3 -45402,mobile,1O1O,nil,1,nil,3 -45402,NWMOBILE,NWMOBILE,nil,1,nil,3 -45403,mobile.lte.three.com.hk,3LTE,nil,1,nil,1 -45403,mobile.three.com.hk,3,nil,1,nil,1 -45404,web-g.three.com.hk,3(2G)GPRS,nil,1,nil,nil -45406,SmarTone,SmarTone,nil,1,nil,3 -45408,iot.truphone.com,Truphone,nil,1,nil,nil -45410,hkcsl,one2free,nil,1,nil,3 -45412,cmhk,CMHKData,nil,1,nil,nil -45413,cmhk,CMHKData,nil,1,nil,nil -45415,SmarTone,SmarTone,nil,1,nil,3 -45416,pccw,PCCW-HKT,nil,1,nil,1 -45417,SmarTone,SmarTone,nil,1,nil,3 -45418,mobile,1O1O,nil,1,nil,3 -45418,NWMOBILE,NWMOBILE,nil,1,nil,3 -45419,pccw,PCCW-HKT,nil,1,nil,1 -45500,smartgprs,SmarToneMacau,nil,1,nil,3 -45501,ctm-mobile,CTMData,nil,1,nil,nil -45501,ctmprepaid,CTM(Prepaid),nil,1,nil,nil -45503,mobile.three.com.mo,3Macau,nil,1,nil,1 -45504,ctm-mobile,CTMData,nil,1,nil,nil -45504,ctmprepaid,CTM(Prepaid),nil,1,nil,nil -45505,mobile.three.com.mo,3Macau,nil,1,nil,1 -45601,default,Cellcard,nil,1,nil,nil -45602,default,Smart,nil,1,nil,nil -45604,default,qb,nil,1,nil,nil -45605,default,Star-Cell,nil,1,nil,nil -45606,default,Smart,nil,1,nil,nil -45608,default,Metfone,nil,1,nil,nil -45609,default,Beeline,nil,1,nil,nil -45611,default,Excell,nil,1,nil,nil -45618,default,Cellcard,nil,1,nil,nil -45701,default,LTC,nil,1,nil,nil -45702,default,ETL,nil,1,nil,nil -45703,default,Unitel,nil,1,nil,nil -45708,default,Beeline,nil,1,nil,nil -46000,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil -46000,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil -46001,3gnet,沃3G连接互联网(ChinaUnicom),nil,1,nil,nil -46001,3gwap,沃3G手机上网(ChinaUnicom),nil,1,nil,nil -46001,uninet,联通2GNET上网(ChinaUnicom),nil,1,nil,nil -46002,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil -46002,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil -46007,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil -46008,cmnet,中国移动(ChinaMobile)GPRS,nil,1,nil,nil -46007,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil -46008,cmwap,中国移动(ChinaMobile)WAP,nil,1,nil,nil -46009,3gnet,ChinaUnicom3G,nil,1,nil,nil -46009,3gwap,ChinaUnicomwap,nil,1,nil,nil -46011,ctlte,ctlte,nil,1,nil,0 -46003,ctnet,CTNET,vnet.mobi,1,ctnet@mycdma.cn,3 -46003,ctwap,CTWAP,vnet.mobi,1,ctwap@mycdma.cn,3 -20404,ctnet,CTNET,nil,1,nil,0 -46601,internet,遠傳電信(FarEasTone)(Internet),nil,1,nil,nil -46688,internet,和信電訊(KGT-Online)(Internet),nil,1,nil,nil -46689,vibo,VIBO-vibo,nil,1,nil,nil -46689,internet,TStar-internet,nil,1,nil,nil -46689,viboone,VIBOONE,nil,1,nil,nil -46692,internet,中華電信(Chunghwa)(Internet),nil,1,nil,nil -46693,Internet,台灣大哥大(TWMobile)(Internet),nil,1,nil,nil -46697,Internet,台灣大哥大(TWMobile)(Internet),nil,1,nil,nil -46699,Internet,台灣大哥大(TWMobile)(Internet),nil,1,nil,nil -47001,gpinternet,GP-INTERNET,nil,1,nil,0 -47201,default,Dhiraagu,nil,1,nil,nil -47202,OoredooData,OoredooData,nil,1,nil,nil -50210,diginet,DiGiInternet,nil,1,nil,nil -50212,max4g,MaxisInternet,wap,1,maxis,1 -50213,celcom4g,CelcomInternet,nil,1,nil,nil -502143,diginet,DiGiInternet,nil,1,nil,nil -502145,celcom4g,CelcomInternet,nil,1,nil,nil -502146,diginet,DiGiInternet,nil,1,nil,nil -502148,celcom4g,CelcomInternet,nil,1,nil,nil -50216,diginet,DiGiInternet,nil,1,nil,nil -50217,max4g,MaxisInternet,wap,1,maxis,1 -50218,my3g,UMobileInternet,nil,1,nil,nil -50219,celcom4g,CelcomInternet,nil,1,nil,nil -50501,telstra.wap,TelstraInternet,nil,1,nil,nil -50501,telstra.internet,TelstraTethering,nil,1,nil,nil -50502,yesinternet,OptusYesInternet,nil,1,nil,nil -50503,live.vodafone.com,Vodafonelive!,nil,1,nil,nil -50506,3services,Planet3,nil,1,nil,0 -50507,vfinternet.au,VFInternet,nil,1,nil,nil -50511,Telstra.wap,TelstraInternet,nil,1,nil,nil -50512,3netaccess,3Internet,nil,1,nil,nil -50512,3services,3,nil,1,nil,nil -50538,iot.truphone.com,Truphone,nil,1,nil,nil -50571,Telstra.wap,TelstraInternet,nil,1,nil,nil -50572,Telstra.wap,TelstraInternet,nil,1,nil,nil -50588,vfinternet.au,VFInternet,nil,1,nil,nil -50590,internet,OptusInternet,nil,1,nil,nil -50599,live.vodafone.com,VodafoneLive!,nil,1,nil,nil -51001,indosatgprs,indosatgprs,nil,1,nil,1 -51008,AXIS,AXIS-SNS,nil,1,nil,1 -51008,AXIS,AXISwap,123456,1,axis,1 -51010,internet,internet,nil,1,nil,nil -51010,telkomsel,TSEL-WAP,wap123,1,wap,1 -51011,internet,Internet,nil,1,nil,1 -51021,indosatgprs,Indosat-SNS,nil,1,nil,1 -51021,indosatgprs,IndosatGPRS,indosat,1,indosat,1 -51089,3gprs,3-SNS,nil,1,nil,1 -51089,3gprs,3GPRS,3gprs,1,3gprs,1 -51401,default,Telin,nil,1,nil,nil -51402,default,TimorTelecom,nil,1,nil,nil -51403,default,ViettelTimor-Leste,nil,1,nil,nil -51502,internet.globe.com.ph,myGlobeInternet,nil,1,nil,nil -51502,http.globe.com.ph,myGlobeINET,nil,1,nil,nil -51502,www.globe.com.ph,myGlobeConnect,nil,1,nil,nil -51503,smartlte,SMARTLTE,nil,1,nil,nil -51503,internet,SMARTINTERNET,nil,1,nil,nil -51503,Smart1,SmartGPRS,nil,1,nil,nil -51505,minternet,SunInternet,nil,1,nil,nil -51505,wap,SUNWAPGPRS,nil,1,nil,nil -51505,fbband,SunSBW,nil,1,nil,nil -51518,redinternet,Redinternet,nil,1,nil,nil -52000,internet,CAT3GINTERNET,nil,1,nil,nil -52000,internet,TRUE-HINTERNET,true,1,true,1 -52001,internet,AISInternet,nil,1,nil,0 -52003,internet,AISInternet,nil,1,nil,0 -52004,internet,TRUE-HINTERNET,true,1,true,1 -52005,www.dtac.co.th,dtacInternet,nil,1,nil,nil -52015,internet,TOT3GInternet,nil,1,nil,nil -52018,www.dtac.co.th,dtacInternet,nil,1,nil,nil -52099,internet,TRUEINTERNET,true,1,true,1 -52501,e-ideas,SingTel(PostPaid),nil,1,nil,nil -52501,hicard,SingTel(PrePaid),nil,1,nil,nil -52502,e-ideas,SingTel(PostPaid),nil,1,nil,nil -52502,hicard,SingTel(PrePaid),nil,1,nil,nil -52503,sunsurf,SunsurfMobile,nil,1,nil,nil -52504,sunsurf,SunsurfMobile,nil,1,nil,nil -52505,shwap,SHDataPostpaid,nil,1,nil,nil -52802,default,B-Mobile,nil,1,nil,nil -52811,default,DSTCom,nil,1,nil,nil -53001,vodafone,VFNZInternet,nil,1,nil,nil -53005,Internet,Data,nil,1,nil,nil -53005,wapaccess.co.nz,Default,nil,1,nil,nil -53024,internet,2DegreesInternet,nil,1,nil,nil -53602,default,Digicel,nil,1,nil,nil -53701,default,BeMobile,nil,1,nil,nil -53703,wap.digicelpng.com,PNGWAP,nil,1,nil,nil -53703,internet.digicelpng.com,PNGWEB,nil,1,nil,nil -53703,wap.digicel.com.pg,PapuaNewGuinea,nil,1,nil,1 -53703,em,EMnify,nil,1,nil,nil -53901,default,U-Call,nil,1,nil,nil -53943,default,ShorelineCommunication,nil,1,nil,nil -53988,default,Digicel,nil,1,nil,nil -53988,wap,Tonga,nil,1,nil,1 -54001,default,BREEZE,nil,1,nil,nil -54002,default,BeMobile,nil,1,nil,nil -54100,default,AIL,nil,1,nil,nil -54101,default,SMILE,nil,1,nil,nil -54105,default,Digicel,nil,1,nil,nil -54105,wap,Vanatu,nil,1,nil,1 -54201,default,Vodafone,nil,1,nil,nil -54202,default,Digicel,nil,1,nil,nil -54202,wap,Fiji,nil,1,nil,1 -54411,default,Bluesky,nil,1,nil,nil -54501,default,Kiribati-TSKL,nil,1,nil,nil -54509,default,Kiribati-FrigateNet,nil,1,nil,nil -54601,default,Mobilis,nil,1,nil,nil -54720,default,Vini,nil,1,nil,nil -54801,default,TelecomCook,nil,1,nil,nil -54901,default,Digicel,nil,1,nil,nil -54927,default,Bluesky,nil,1,nil,nil -55001,default,FSMTC,nil,1,nil,nil -55101,default,MINTA,nil,1,nil,nil -55201,default,PNCC,nil,1,nil,nil -55280,default,PalauMobile,nil,1,nil,nil -60201,mobinilweb,MobinilWeb,nil,1,nil,nil -60201,mobinilwap,MobinilWAP,nil,1,nil,nil -60202,internet.vodafone.net,vodafoneinternet,internet,1,internet,3 -60202,wap.vodafone.com.eg,VodafoneWAP,wap,1,wap,3 -60203,etisalat,EtisalatWAP,nil,1,nil,nil -60301,wap,mobiliswap,wap,1,wap,1 -60301,internet,Mobilisinternet,internet,1,internet,1 -60302,djezzy.internet,djezzy.internet,nil,1,nil,nil -60303,internet,Ooredoointernet,nil,1,nil,1 -60400,internet.orange.ma,Internet,nil,1,nil,1 -60400,wap.meditel.ma,Imedia,MEDIWAP,1,MEDIWAP,1 -60401,wap.iamgprs.ma,MobileZone,nil,1,nil,nil -60401,www.iamgprs1.ma,InternetMobile,nil,1,nil,nil -60402,www.wana.ma,WEB,nil,1,nil,nil -60501,weborange,weborange,nil,1,nil,nil -60502,internet.tn,Internet,nil,1,nil,nil -60502,gprs.tn,InternetPortail,gprs,1,gprs,1 -60503,internet.ooredoo.tn,OoredooTNInternet,nil,1,nil,nil -60600,default,Libyana,nil,1,nil,nil -60601,default,Madar,nil,1,nil,nil -60602,default,Al-JeelPhone,nil,1,nil,nil -60603,default,LibyaPhone,nil,1,nil,nil -60606,default,HatefLibya,nil,1,nil,nil -60701,default,Gamcel,nil,1,nil,nil -60702,default,Africel,nil,1,nil,nil -60703,default,Comium,nil,1,nil,nil -60704,default,QCell,nil,1,nil,nil -60801,wap,OrangeWapSN,wap,1,wap,nil -60801,internet,OrangeWebSN,internet,1,internet,nil -60802,web.sentel.com,TigoInternetSN,nil,1,nil,nil -60803,expresso,ExpressoInternetSN,wap,1,wap,nil -60901,default,Mattel,nil,1,nil,nil -60902,default,Chinguitel,nil,1,nil,nil -60910,default,Mauritel,nil,1,nil,nil -61002,internet,Orange3G/4G,internet,1,internet,1 -61002,wap,OrangeWapML,wap,1,wap,nil -61101,default,OrangeS.A.,nil,1,nil,nil -61102,default,Sotelgui,nil,1,nil,nil -61103,default,TelecelGuinee,nil,1,nil,nil -61104,default,MTN,nil,1,nil,nil -61105,default,Cellcom,nil,1,nil,nil -61202,moov,MoovInternetCI,web,1,web,nil -61203,orangeciweb,Oweb,web,1,web,1 -61203,orangeciwap,OWORLDCI,wap,1,wap,nil -61204,gprs.koz.ci,KozInternetCI,web,1,web,nil -61205,web.mtn.ci,MTNInternetCI,vide,1,vide,nil -61301,default,Telmob,nil,1,nil,nil -61302,default,Airtel,nil,1,nil,nil -61303,default,TelecelFaso,nil,1,nil,nil -61404,orange.ne,OrangeInternet,nil,1,nil,nil -61501,default,TogoCell,nil,1,nil,nil -61503,default,Moov,nil,1,nil,nil -61601,default,Libercom,nil,1,nil,nil -61602,default,Moov,nil,1,nil,nil -61603,default,MTN,nil,1,nil,nil -61604,default,BBCOM,nil,1,nil,nil -61605,default,Glo,nil,1,nil,nil -61701,orange,OrangeInternet,nil,1,nil,nil -61801,default,LonestarCell,nil,1,nil,nil -61802,default,Libercell,nil,1,nil,nil -61804,default,Comium,nil,1,nil,nil -61807,Orange,Orange,nil,1,nil,nil -61820,default,LIBTELCO,nil,1,nil,nil -61901,default,Airtel,nil,1,nil,nil -61902,default,Tigo,nil,1,nil,nil -61903,default,Africell,nil,1,nil,nil -61904,default,Comium,nil,1,nil,nil -61905,default,Africell,nil,1,nil,nil -61925,default,Mobitel,nil,1,nil,nil -6200,glowap,Glo,nil,1,nil,0 -62001,internet,MTNInternetGH,nil,1,nil,nil -62002,browse,VodafoneInternetGH,nil,1,nil,nil -62003,web.tigo.com.gh,TigoInternetGH,nil,1,nil,nil -62006,wap,AirtelInternetGH,nil,1,nil,nil -62007,glowap,GloInternetGH,glo,1,glo,1 -62120,internet.ng.zain.com,AirtelInternet,internet,1,internet,1 -62120,wap.ng.zain.com,AirtelWAP,wap,1,wap,1 -62130,web.gprs.mtnnigeria.net,MTNWAP,web,1,web,1 -62150,glosecure,GloDirect,gprs,1,gprs,1 -62160,etisalat,etisalatWAP,nil,1,nil,nil -62201,default,Airtel,nil,1,nil,nil -62202,default,Tawali,nil,1,nil,nil -62203,default,Tigo,nil,1,nil,nil -62204,default,Salam,nil,1,nil,nil -62301,default,CTP,nil,1,nil,nil -62302,default,TC,nil,1,nil,nil -62303,orangeca3g,Internetbrowsing,nil,1,nil,nil -62304,default,Nationlink,nil,1,nil,nil -62501,default,CVMOVEL,nil,1,nil,nil -62502,default,T+,nil,1,nil,nil -62601,default,CSTmovel,nil,1,nil,nil -62701,default,OrangeGQ,nil,1,nil,nil -62703,default,HitsGQ,nil,1,nil,nil -62801,default,Libertis,nil,1,nil,nil -62802,default,Moov,nil,1,nil,nil -62803,default,Airtel,nil,1,nil,nil -62804,default,Azur,nil,1,nil,nil -62901,default,Airtel,nil,1,nil,nil -62910,default,LibertisTelecom,nil,1,nil,nil -63001,vodanet,VodacomInternetCD,nil,1,nil,nil -63089,tigo.web,TigoInternetCD,nil,1,nil,nil -63102,default,UNITEL,nil,1,nil,nil -63104,default,MOVICEL,nil,1,nil,nil -63202,default,Areeba,nil,1,nil,nil -63203,4Gogb,OrangeBissau,nil,1,nil,nil -63207,default,Guinetel,nil,1,nil,nil -63301,default,Cable&Wireless,nil,1,nil,nil -63302,default,MediatechInternational,nil,1,nil,nil -63310,default,Airtel,nil,1,nil,nil -63401,default,ZainSD,nil,1,nil,nil -63402,default,MTN,nil,1,nil,nil -63407,default,SudaniOne,nil,1,nil,nil -63409,default,PrivetNetwork,nil,1,nil,nil -63510,default,MTN,nil,1,nil,nil -63512,default,Rwandatel,nil,1,nil,nil -63513,default,Tigo,nil,1,nil,nil -63514,default,Airtel,nil,1,nil,nil -63601,default,ETH-MTN,nil,1,nil,nil -63701,default,Telesom,nil,1,nil,nil -63704,default,Somafone,nil,1,nil,nil -63710,default,Nationlink,nil,1,nil,nil -63725,default,Hormuud,nil,1,nil,nil -63730,default,Golis,nil,1,nil,nil -63757,default,Unittel,nil,1,nil,nil -63760,default,NationlinkTelecom,nil,1,nil,nil -63771,default,Somtel,nil,1,nil,nil -63782,default,Telcom,nil,1,nil,nil -63801,default,Evatis,nil,1,nil,nil -63902,safaricom,safaricomGPRS,data,1,saf,1 -63903,internet,AirtelInternet,nil,1,nil,nil -63903,ke.celtel.com,Airtel,nil,1,nil,nil -63905,Internet,YuInternet,nil,1,nil,nil -63905,Yuinternet,YuWAP,nil,1,nil,nil -63907,bew.orange.co.ke,OrangeInternet,nil,1,nil,nil -64004,Wap,VodacomWAP,nil,1,nil,nil -64101,internet,AirtelInternetUG,nil,1,nil,nil -64110,yellopix.mtn.co.ug,MTNInternetUG,nil,1,nil,nil -64111,utweb,UTLInternetUG,nil,1,nil,nil -64114,orange.ug,OrangeInternetUG,nil,1,nil,nil -64122,web.waridtel.co.ug,WaridTelecomInternetUG,nil,1,nil,nil -64201,default,Spacetel,nil,1,nil,nil -64202,default,Tempo,nil,1,nil,nil -64203,default,Onatel,nil,1,nil,nil -64207,default,SmartMobile,nil,1,nil,nil -64208,default,HiTsTelecom,nil,1,nil,nil -64282,default,Leo,nil,1,nil,nil -64301,default,mCel,nil,1,nil,nil -64303,default,Movitel,nil,1,nil,nil -64304,default,Vodacom,nil,1,nil,nil -64501,default,Airtel,nil,1,nil,nil -64502,default,MTN,nil,1,nil,nil -64503,default,ZAMTEL,nil,1,nil,nil -64602,orangenet,OrangeMGInternet,nil,1,nil,0 -64700,orangerun,OrangeWorldre,orange,1,orange,nil -64702,onlywap,OnlyWap,only,1,only,1 -64703,free.re,FreeRe,nil,1,nil,nil -64710,sl2sfr,FullInternetSRR,nil,1,nil,nil -64710,wapsfr,GPRSSRR,wap,1,wap,nil -64710,fnetcoriolis,CoriolisWAP,nil,1,nil,nil -64803,default,Telecel,nil,1,nil,nil -64804,default,Econet,nil,1,nil,nil -64901,default,MTC,nil,1,nil,nil -64902,default,switch,nil,1,nil,nil -64903,default,Leo,nil,1,nil,nil -65001,default,TNM,nil,1,nil,nil -65010,default,Airtel,nil,1,nil,nil -65101,internet,VCLInternetGPRS,nil,1,nil,nil -65310,default,SwaziMTN,nil,1,nil,nil -65401,default,HURI-SNPT,nil,1,nil,nil -65501,lte.vodacom.za,LTE.Vodacom,nil,1,nil,nil -65501,internet,Smart.Vodacom,nil,1,nil,nil -65502,internet,TelkomMobileInternet,nil,1,nil,nil -65507,internet,CellCGPRS,nil,1,nil,nil -65507,vdata,VIRGIN_INTERNET_1,nil,1,nil,nil -65510,myMTN,MTNGPRS,mtnwap,1,mtnwap,1 -65701,default,Eritel,nil,1,nil,nil -70267,default,DigiCell,nil,1,nil,nil -70299,default,Smart,nil,1,nil,nil -70401,internet.ideasclaro,InternetCLARO,nil,1,nil,nil -70402,broadband.tigo.gt,BroadbandTIGO,nil,1,nil,nil -70403,internet.movistar.gt,MovistarINTERNET,movistargt,1,movistargt,1 -704030,internet.movistar.gt,MovistarINTERNET,movistargt,1,movistargt,1 -70601,internet.ideasclaro,InternetCLARO,nil,1,nil,nil -70602,web.digicelsv.com,DigicelInternet,nil,1,nil,nil -70603,internet.tigo.sv,InternetTigo,nil,1,nil,nil -70604,internet.movistar.sv,MovistarINTERNET,movistarsv,1,movistarsv,1 -706040,internet.movistar.sv,MovistarINTERNET,movistarsv,1,movistarsv,1 -708001,internet.ideasclaro,InternetClaro,nil,1,nil,nil -70802,internet.tigo.hn,INTERNETTIGO,nil,1,nil,nil -70804,web.digicelhn.com,Honduras,nil,1,nil,1 -70804,wap.digicelhn.com,Honduras,nil,1,nil,1 -708020,internet.tigo.hn,INTERNETTIGO,nil,1,nil,nil -708040,web.digicelhn.com,Honduras,nil,1,nil,1 -71021,internet.ideasalo.ni,EnitelWEB,internet,1,internet,1 -71030,internet.movistar.ni,MovistarINTERNET,movistarni,1,movistarni,1 -710300,internet.movistar.ni,MovistarINTERNET,movistarni,1,movistarni,1 -71073,internet.ideasalo.ni,EnitelWEB,internet,1,internet,1 -710730,internet.ideasalo.ni,EnitelWEB,internet,1,internet,1 -71201,kolbi3g,KOLBI3G,nil,1,nil,nil -71201,kolbi,CostarRica,nil,1,nil,1 -71202,kolbi3g,KOLBI3G,nil,1,nil,nil -71203,internet.ideasclaro,InternetCLAROCR,nil,1,nil,nil -71204,internet.movistar.cr,MovistarINTERNET,movistarcr,1,movistarcr,1 -712019,tm7datos,InternetTuyo,nil,1,nil,nil -712190,tm7datos,InternetTuyo,nil,1,nil,nil -71220,datos.fullmovil.cr,InternetFullmovil,nil,1,nil,nil -71401,apn01.cwpanama.com.pa,Internet,nil,1,nil,nil -71402,internet.movistar.pa,MovistarINTERNET,movistarpa,1,movistarpa,1 -714020,internet.movistar.pa,MovistarINTERNET,movistarpa,1,movistarpa,1 -71403,web.claro.com.pa,WEBClaro,CLAROWEB,1,CLAROWEB,1 -71404,web.digicelpanama.com,DigicelInternet,nil,1,nil,nil -714040,web.digicelpanama.com,Panama,nil,1,nil,1 -71606,movistar.pe,MovistarINTERNET,movistar,1,movistar@datos,1 -71610,claro.pe,CLARODATOS,claro,1,claro,1 -71615,bitel,Bitel-Internet,nil,1,nil,1 -71617,entel.pe,EntelPE,nil,1,nil,0 -71617,location.entel.pe,EntelLocation,nil,1,nil,0 -72201,internet.movil,Quam_WEB,internet,1,internet,1 -72207,wap.gprs.unifon.com.ar,MovistarWAP,wap,1,wap,1 -72207,internet.gprs.unifon.com.ar,Argentina,internet,1,internet,1 -72231,igprs.claro.com.ar,ClaroAR,nil,1,nil,nil -722310,igprs.claro.com.ar,ClaroAR,nil,1,nil,nil -72234,datos.personal.com,PersonalDatos,datos,1,datos,1 -72234,internet.personal.com,Argentina,internet,1,internet,0 -72236,gprs.nuestro.com.ar,Argentina,nil,1,gprs,0 -722340,datos.personal.com,Argentina,adgj,1,gprs,0 -722340,internet.personal.com,Argentina,internet,1,internet,0 -722341,datos.personal.com,PersonalDatos,datos,1,datos,1 -722341,internet.personal.com,Argentina,internet,1,internet,0 -72402,timbrasil.br,TIMConnect,tim,1,tim,1 -72403,timbrasil.br,TIMConnect,tim,1,tim,1 -72404,timbrasil.br,TIMConnect,tim,1,tim,1 -72405,java.claro.com.br,JavaSession,claro,1,claro,nil -72406,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 -72407,sercomtel.com.br,SCTLGPRS,sercomtel,1,sercomtel,nil -72410,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 -72411,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 -72415,sercomtel.com.br,Sercomtel,sercomtel,1,sercomtel,1 -72416,gprs.oi.com.br,OiGPRSInternet,nil,1,nil,nil -72417,internet.br,Surf,nil,1,nil,1 -72419,gprs.telemigcelular.com.br,TelemigCGPRS,celular,1,celular,nil -72423,zap.vivo.com.br,VivoInternet,vivo,1,vivo,1 -72424,gprs.oi.com.br,OI,oi,1,oi,1 -72431,gprs.oi.com.br,OiGPRSInternet,nil,1,nil,nil -72432,ctbc.br,CTBC,1212,1,CTBC,1 -72433,ctbc.br,CTBC,1212,1,CTBC,1 -72434,ctbc.br,CTBC,1212,1,CTBC,1 -72439,wap.nextel3g.net.br,NextelWAP,nil,1,nil,0 -72454,portoconecta.br,PortoSeguroConecta,nil,1,nil,0 -73001,bam.entelpcs.cl,InternetMovil,entelpcs,1,entelpcs,1 -73009,wap.nextelmovil.cl,InternetNextel,nil,1,nil,0 -73010,bam.entelpcs.cl,InternetMovil,entelpcs,1,entelpcs,1 -73002,wap.tmovil.cl,MovistarAPLICACIONES,wap,1,wap,1 -73003,bam.clarochile.cl,BandaAnchaMovil,clarochile,1,clarochile,1 -73007,web.gtdmovil.cl,web,webgtd,1,webgtd,1 -73008,movil.vtr.com,Internet,vtrmovil,1,vtrmovil,2 -73008,wap.vtr.com,Wap,nil,1,nil,0 -73212,internet.movistar.com.co,MovistarINTERNET,movistar,1,movistar,1 -732101,internet.comcel.com.co,COMCEL,COMCELWEB,1,COMCELWEB,1 -732103,web.colombiamovil.com.co,TIGOWEB,nil,1,nil,1 -732103,moviletb.net.co,InternetETB,etb,1,etb,0 -732103,movilexito.net.co,InternetÉxito,nil,1,nil,1 -732103,www.une.net.co,UNE,une,1,une,0 -732111,web.colombiamovil.com.co,TIGOWEB,nil,1,nil,1 -732111,moviletb.net.co,InternetETB,etb,1,etb,0 -732111,movilexito.net.co,InternetÉxito,nil,1,nil,1 -732111,www.une.net.co,UNE,une,1,une,0 -732123,internet.movistar.com.co,MovistarINTERNET,movistar,1,movistar,1 -732123,web.vmc.net.co,VirginMobile,nil,1,nil,1 -732130,lte.avantel.com.co,Avantel,nil,1,nil,0 -732187,internetmovil.etb.net.co,ETB4G,nil,1,nil,0 -73401,internet.digitel.ve,Digitel412,nil,1,nil,nil -73401,gprsweb.digitel.ve,Venezuela,nil,1,nil,1 -73402,internet.digitel.ve,Digitel412,nil,1,nil,nil -73402,gprsweb.digitel.ve,Venezuela,nil,1,nil,1 -73403,internet.digitel.ve,Digitel412,nil,1,nil,nil -73403,gprsweb.digitel.ve,Venezuela,nil,1,nil,1 -73404,internet.movistar.ve,MovistarINTERNET,nil,1,nil,nil -73404,wap.movistar.ve,MovistarWAP,nil,1,nil,nil -73406,int.movilnet.com.ve,MODEM,nil,1,nil,nil -73601,internet.nuevatel.com,VIVA3G,nil,1,nil,1 -73602,wap.movil.com.bo,ENTELWAPGPRS,nil,1,nil,1 -73603,wap.tigo.bo,WAPTIGO,nil,1,nil,1 -73801,default,Digicel,nil,1,nil,nil -73801,wap.digicelgy.com,Guyana,wap,1,wap,1 -73802,default,GT&TCellinkPlus,nil,1,nil,nil -74000,internet.movistar.com.ec,MovistarINTERNET,movistar,1,movistar,1 -74001,internet.claro.com.ec,InternetClaro,nil,1,nil,nil -740010,internet.claro.com.ec,InternetClaro,nil,1,nil,nil -74002,internet3gsp.alegro.net.ec,CNT3G,nil,1,nil,nil -74401,vox.internet,VOXINTERNET,nil,1,nil,1 -74401,vox.wap,Paraguay,nil,1,nil,1 -74402,igprs.claro.com.py,ClaroPY,ctigprs999,1,ctigprs,1 -74404,internet.tigo.py,TIGOPY,nil,1,nil,1 -74405,internet,PersonalDatosPy,personal,1,personal,1 -74602,default,Telesur,nil,1,nil,nil -74603,web.digicelsr.com,Suriname,nil,1,nil,1 -74603,wap.digicelsr.com,Suriname,wap,1,wap,1 -74801,wap,wapANCEL,nil,1,nil,1 -74801,gprs.ancel,gprsANCEL,nil,1,nil,1 -74807,webapn.movistar.com.uy,MovistarINTERNET,movistar,1,movistar,1 -74810,igprs.claro.com.uy,ClaroUY,ctigprs999,1,ctigprs,1 -28310,Internet,OrangeArmeniaInternet,nil,1,nil,1 -65202,internet.orange.co.bw,OrangeWAPBW,nil,1,nil,nil -62402,orangecmgprs,OrangeCM,orange,1,orange,nil -64602,orangeworld,OrangeWorldMG,orange,1,world,nil -90128,ciot.vodafone.com,CIOTVodafone,vodafone,1,vodafone,nil -90137,mobiledata,mobiledata,nil,1,nil,nil -90143,em,EMnify,nil,1,nil,nil -90158,bicsapn,BICSInternet,nil,1,nil,nil -25050,internet.sberbank-tele.com,Sberbank-TelecomInternet,nil,1,nil,nil -20630,web.be,Unleashed,nil,1,nil,nil -22207,web.kenamobile.it,KenaMobileWeb,nil,1,nil,nil -50519,data.lycamobile.com.au,Lycamobile,nil,1,nil,1 -24223,data.lyca-mobile.no,Lycamobile,nil,1,nil,1 -22854,data.lycamobile.ch,Lycamobile,nil,1,nil,1 -23208,data.lycamobile.at,Lycamobile,nil,1,nil,1 -20606,data.lycamobile.be,Lycamobile,nil,1,nil,1 -26243,data.lycamobile.de,Lycamobile,nil,1,nil,1 -23812,data.lycamobile.dk,Lycamobile,nil,1,nil,1 -21425,data.lycamobile.es,Lycamobile,nil,1,nil,1 -20825,data.lycamobile.fr,Lycamobile,nil,1,nil,1 -27213,data.lycamobile.ie,Lycamobile,nil,1,nil,1 -20409,data.lycamobile.nl,Lycamobile,nil,1,nil,1 -26009,data.lycamobile.pl,Lycamobile,nil,1,nil,1 -26804,data.lycamobile.pt,Lycamobile,nil,1,nil,1 -22616,data.lycamobile.ro,Lycamobile,nil,1,nil,1 -24012,data.lycamobile.se,Lycamobile,nil,1,nil,1 -22235,data.lycamobile.it,Lycamobile,nil,1,nil,1 -311960,data.lycamobile.com,Lycamobile,nil,1,nil,1 -64126,data.lycamobile.ug,Lycamobile,nil,1,nil,1 -29404,data.lycamobile.mk,Lycamobile,nil,1,nil,1 -65553,data.lycamobile.co.za,Lycamobile,nil,1,nil,1 -23457,mobile.sky,Internet,nil,1,nil,0 -29701,flat,Internet,nil,1,nil,3 -29701,internet,Internet,nil,1,nil,3 -29702,tmcg-4g,TelekomInternet,38267,1,38267,1 -29703,mtelinternet,mTelInternet,068,1,internet,2 -40421,jionet,Jio,nil,1,nil,3 -404854,jionet,Jio,nil,1,nil,3 -404855,jionet,Jio,nil,1,nil,3 -404856,jionet,Jio,nil,1,nil,3 -404857,jionet,Jio,nil,1,nil,3 -404858,jionet,Jio,nil,1,nil,3 -404859,jionet,Jio,nil,1,nil,3 -404860,jionet,Jio,nil,1,nil,3 -404861,jionet,Jio,nil,1,nil,3 -404862,jionet,Jio,nil,1,nil,3 -404863,jionet,Jio,nil,1,nil,3 -404864,jionet,Jio,nil,1,nil,3 -404865,jionet,Jio,nil,1,nil,3 -404866,jionet,Jio,nil,1,nil,3 -404867,jionet,Jio,nil,1,nil,3 -404868,jionet,Jio,nil,1,nil,3 -404869,jionet,Jio,nil,1,nil,3 -404870,jionet,Jio,nil,1,nil,3 -404871,jionet,Jio,nil,1,nil,3 -404872,jionet,Jio,nil,1,nil,3 -404873,jionet,Jio,nil,1,nil,3 -404874,jionet,Jio,nil,1,nil,3 -22801,shared.m2m.ch,SwisscomM2M,nil,1,nil,0 -27202,Open.internet,3Ireland,nil,1,nil,nil -24008,services.telenor.se,TelenorMobilsurf,nil,1,nil,nil -310410,accessrgn.net,AT&T,nil,1,nil,nil -24603,static.tele2.lt,Tele2,nil,1,nil,nil -24602,bangapro,Bite,nil,1,nil,nil -24601,gprs.fix-ip.omnitel1.net,Telia,nil,1,nil,nil -20404,truphone.com,Truphone,nil,1,nil,nil -20433,truphone.com,Truphone,nil,1,nil,nil -20809,truphone.com,Truphone,nil,1,nil,nil -20812,truphone.com,Truphone,nil,1,nil,nil -21427,truphone.com,Truphone,nil,1,nil,nil -23425,truphone.com,Truphone,nil,1,nil,nil -26033,truphone.com,Truphone,nil,1,nil,nil -26242,truphone.com,Truphone,nil,1,nil,nil -31030,truphone.com,Truphone,nil,1,nil,nil -310300,truphone.com,Truphone,nil,1,nil,nil -45408,truphone.com,Truphone,nil,1,nil,nil -50538,truphone.com,Truphone,nil,1,nil,nil -50502,truphone.com,Truphone,nil,1,nil,nil -20828,datapro,AIF,nil,1,nil,nil -90140,iot.1nce.net,1NCE,nil,1,nil,nil -00101,internet,Amarisoft,nil,1,nil,nil -00101,default,Amarisoft,nil,1,nil,nil -40001,internet,Azercell,nil,1,nil,nil -310004,VZWINTERNET,Verizon,nil,3,nil,nil -310010,VZWINTERNET,Verizon,nil,3,nil,nil -310012,VZWINTERNET,Verizon,nil,3,nil,nil -310013,VZWINTERNET,Verizon,nil,3,nil,nil -310350,VZWINTERNET,Verizon,nil,3,nil,nil -310590,VZWINTERNET,Verizon,nil,3,nil,nil -310591,VZWINTERNET,Verizon,nil,3,nil,nil -310592,VZWINTERNET,Verizon,nil,3,nil,nil -310593,VZWINTERNET,Verizon,nil,3,nil,nil -310594,VZWINTERNET,Verizon,nil,3,nil,nil -310595,VZWINTERNET,Verizon,nil,3,nil,nil -310596,VZWINTERNET,Verizon,nil,3,nil,nil -310597,VZWINTERNET,Verizon,nil,3,nil,nil -310598,VZWINTERNET,Verizon,nil,3,nil,nil -310599,VZWINTERNET,Verizon,nil,3,nil,nil -310820,VZWINTERNET,Verizon,nil,3,nil,nil -310890,VZWINTERNET,Verizon,nil,3,nil,nil -310891,VZWINTERNET,Verizon,nil,3,nil,nil -310892,VZWINTERNET,Verizon,nil,3,nil,nil -310893,VZWINTERNET,Verizon,nil,3,nil,nil -310894,VZWINTERNET,Verizon,nil,3,nil,nil -310895,VZWINTERNET,Verizon,nil,3,nil,nil -310896,VZWINTERNET,Verizon,nil,3,nil,nil -310897,VZWINTERNET,Verizon,nil,3,nil,nil -310898,VZWINTERNET,Verizon,nil,3,nil,nil -310899,VZWINTERNET,Verizon,nil,3,nil,nil -310910,VZWINTERNET,Verizon,nil,3,nil,nil -311110,VZWINTERNET,Verizon,nil,3,nil,nil -311270,VZWINTERNET,Verizon,nil,3,nil,nil -311271,VZWINTERNET,Verizon,nil,3,nil,nil -311272,VZWINTERNET,Verizon,nil,3,nil,nil -311273,VZWINTERNET,Verizon,nil,3,nil,nil -311274,VZWINTERNET,Verizon,nil,3,nil,nil -311275,VZWINTERNET,Verizon,nil,3,nil,nil -311276,VZWINTERNET,Verizon,nil,3,nil,nil -311277,VZWINTERNET,Verizon,nil,3,nil,nil -311278,VZWINTERNET,Verizon,nil,3,nil,nil -311279,VZWINTERNET,Verizon,nil,3,nil,nil -311280,VZWINTERNET,Verizon,nil,3,nil,nil -311281,VZWINTERNET,Verizon,nil,3,nil,nil -311282,VZWINTERNET,Verizon,nil,3,nil,nil -311283,VZWINTERNET,Verizon,nil,3,nil,nil -311284,VZWINTERNET,Verizon,nil,3,nil,nil -311285,VZWINTERNET,Verizon,nil,3,nil,nil -311286,VZWINTERNET,Verizon,nil,3,nil,nil -311287,VZWINTERNET,Verizon,nil,3,nil,nil -311288,VZWINTERNET,Verizon,nil,3,nil,nil -311289,VZWINTERNET,Verizon,nil,3,nil,nil -311390,VZWINTERNET,Verizon,nil,3,nil,nil -311480,VZWINTERNET,Verizon,nil,3,nil,nil -311481,VZWINTERNET,Verizon,nil,3,nil,nil -311482,VZWINTERNET,Verizon,nil,3,nil,nil -311483,VZWINTERNET,Verizon,nil,3,nil,nil -311484,VZWINTERNET,Verizon,nil,3,nil,nil -311485,VZWINTERNET,Verizon,nil,3,nil,nil -311486,VZWINTERNET,Verizon,nil,3,nil,nil -311487,VZWINTERNET,Verizon,nil,3,nil,nil -311488,VZWINTERNET,Verizon,nil,3,nil,nil -311489,VZWINTERNET,Verizon,nil,3,nil,nil -311590,VZWINTERNET,Verizon,nil,3,nil,nil -312040,VZWINTERNET,Verizon,nil,3,nil,nil -312160,VZWINTERNET,Verizon,nil,3,nil,nil -312770,VZWINTERNET,Verizon,nil,3,nil,nil -310010,VZWINTERNET,Verizon,nil,3,nil,nil -310012,VZWINTERNET,Verizon,nil,3,nil,nil -310004,ne01.vzwstatic,Verizon,nil,3,nil,nil -310010,ne01.vzwstatic,Verizon,nil,3,nil,nil -310012,ne01.vzwstatic,Verizon,nil,3,nil,nil -310013,ne01.vzwstatic,Verizon,nil,3,nil,nil -310350,ne01.vzwstatic,Verizon,nil,3,nil,nil -310590,ne01.vzwstatic,Verizon,nil,3,nil,nil -310591,ne01.vzwstatic,Verizon,nil,3,nil,nil -310592,ne01.vzwstatic,Verizon,nil,3,nil,nil -310593,ne01.vzwstatic,Verizon,nil,3,nil,nil -310594,ne01.vzwstatic,Verizon,nil,3,nil,nil -310595,ne01.vzwstatic,Verizon,nil,3,nil,nil -310596,ne01.vzwstatic,Verizon,nil,3,nil,nil -310597,ne01.vzwstatic,Verizon,nil,3,nil,nil -310598,ne01.vzwstatic,Verizon,nil,3,nil,nil -310599,ne01.vzwstatic,Verizon,nil,3,nil,nil -310820,ne01.vzwstatic,Verizon,nil,3,nil,nil -310890,ne01.vzwstatic,Verizon,nil,3,nil,nil -310891,ne01.vzwstatic,Verizon,nil,3,nil,nil -310892,ne01.vzwstatic,Verizon,nil,3,nil,nil -310893,ne01.vzwstatic,Verizon,nil,3,nil,nil -310894,ne01.vzwstatic,Verizon,nil,3,nil,nil -310895,ne01.vzwstatic,Verizon,nil,3,nil,nil -310896,ne01.vzwstatic,Verizon,nil,3,nil,nil -310897,ne01.vzwstatic,Verizon,nil,3,nil,nil -310898,ne01.vzwstatic,Verizon,nil,3,nil,nil -310899,ne01.vzwstatic,Verizon,nil,3,nil,nil -310910,ne01.vzwstatic,Verizon,nil,3,nil,nil -311110,ne01.vzwstatic,Verizon,nil,3,nil,nil -311270,ne01.vzwstatic,Verizon,nil,3,nil,nil -311271,ne01.vzwstatic,Verizon,nil,3,nil,nil -311272,ne01.vzwstatic,Verizon,nil,3,nil,nil -311273,ne01.vzwstatic,Verizon,nil,3,nil,nil -311274,ne01.vzwstatic,Verizon,nil,3,nil,nil -311275,ne01.vzwstatic,Verizon,nil,3,nil,nil -311276,ne01.vzwstatic,Verizon,nil,3,nil,nil -311277,ne01.vzwstatic,Verizon,nil,3,nil,nil -311278,ne01.vzwstatic,Verizon,nil,3,nil,nil -311279,ne01.vzwstatic,Verizon,nil,3,nil,nil -311280,ne01.vzwstatic,Verizon,nil,3,nil,nil -311281,ne01.vzwstatic,Verizon,nil,3,nil,nil -311282,ne01.vzwstatic,Verizon,nil,3,nil,nil -311283,ne01.vzwstatic,Verizon,nil,3,nil,nil -311284,ne01.vzwstatic,Verizon,nil,3,nil,nil -311285,ne01.vzwstatic,Verizon,nil,3,nil,nil -311286,ne01.vzwstatic,Verizon,nil,3,nil,nil -311287,ne01.vzwstatic,Verizon,nil,3,nil,nil -311288,ne01.vzwstatic,Verizon,nil,3,nil,nil -311289,ne01.vzwstatic,Verizon,nil,3,nil,nil -311390,ne01.vzwstatic,Verizon,nil,3,nil,nil -311480,ne01.vzwstatic,Verizon,nil,3,nil,nil -311481,ne01.vzwstatic,Verizon,nil,3,nil,nil -311482,ne01.vzwstatic,Verizon,nil,3,nil,nil -311483,ne01.vzwstatic,Verizon,nil,3,nil,nil -311484,ne01.vzwstatic,Verizon,nil,3,nil,nil -311485,ne01.vzwstatic,Verizon,nil,3,nil,nil -311486,ne01.vzwstatic,Verizon,nil,3,nil,nil -311487,ne01.vzwstatic,Verizon,nil,3,nil,nil -311488,ne01.vzwstatic,Verizon,nil,3,nil,nil -311489,ne01.vzwstatic,Verizon,nil,3,nil,nil -311590,ne01.vzwstatic,Verizon,nil,3,nil,nil -312040,ne01.vzwstatic,Verizon,nil,3,nil,nil -312160,ne01.vzwstatic,Verizon,nil,3,nil,nil -312770,ne01.vzwstatic,Verizon,nil,3,nil,nil -310004,nw01.vzwstatic,Verizon,nil,3,nil,nil -310010,nw01.vzwstatic,Verizon,nil,3,nil,nil -310012,nw01.vzwstatic,Verizon,nil,3,nil,nil -310013,nw01.vzwstatic,Verizon,nil,3,nil,nil -310350,nw01.vzwstatic,Verizon,nil,3,nil,nil -310590,nw01.vzwstatic,Verizon,nil,3,nil,nil -310591,nw01.vzwstatic,Verizon,nil,3,nil,nil -310592,nw01.vzwstatic,Verizon,nil,3,nil,nil -310593,nw01.vzwstatic,Verizon,nil,3,nil,nil -310594,nw01.vzwstatic,Verizon,nil,3,nil,nil -310595,nw01.vzwstatic,Verizon,nil,3,nil,nil -310596,nw01.vzwstatic,Verizon,nil,3,nil,nil -310597,nw01.vzwstatic,Verizon,nil,3,nil,nil -310598,nw01.vzwstatic,Verizon,nil,3,nil,nil -310599,nw01.vzwstatic,Verizon,nil,3,nil,nil -310820,nw01.vzwstatic,Verizon,nil,3,nil,nil -310890,nw01.vzwstatic,Verizon,nil,3,nil,nil -310891,nw01.vzwstatic,Verizon,nil,3,nil,nil -310892,nw01.vzwstatic,Verizon,nil,3,nil,nil -310893,nw01.vzwstatic,Verizon,nil,3,nil,nil -310894,nw01.vzwstatic,Verizon,nil,3,nil,nil -310895,nw01.vzwstatic,Verizon,nil,3,nil,nil -310896,nw01.vzwstatic,Verizon,nil,3,nil,nil -310897,nw01.vzwstatic,Verizon,nil,3,nil,nil -310898,nw01.vzwstatic,Verizon,nil,3,nil,nil -310899,nw01.vzwstatic,Verizon,nil,3,nil,nil -310910,nw01.vzwstatic,Verizon,nil,3,nil,nil -311110,nw01.vzwstatic,Verizon,nil,3,nil,nil -311270,nw01.vzwstatic,Verizon,nil,3,nil,nil -311271,nw01.vzwstatic,Verizon,nil,3,nil,nil -311272,nw01.vzwstatic,Verizon,nil,3,nil,nil -311273,nw01.vzwstatic,Verizon,nil,3,nil,nil -311274,nw01.vzwstatic,Verizon,nil,3,nil,nil -311275,nw01.vzwstatic,Verizon,nil,3,nil,nil -311276,nw01.vzwstatic,Verizon,nil,3,nil,nil -311277,nw01.vzwstatic,Verizon,nil,3,nil,nil -311278,nw01.vzwstatic,Verizon,nil,3,nil,nil -311279,nw01.vzwstatic,Verizon,nil,3,nil,nil -311280,nw01.vzwstatic,Verizon,nil,3,nil,nil -311281,nw01.vzwstatic,Verizon,nil,3,nil,nil -311282,nw01.vzwstatic,Verizon,nil,3,nil,nil -311283,nw01.vzwstatic,Verizon,nil,3,nil,nil -311284,nw01.vzwstatic,Verizon,nil,3,nil,nil -311285,nw01.vzwstatic,Verizon,nil,3,nil,nil -311286,nw01.vzwstatic,Verizon,nil,3,nil,nil -311287,nw01.vzwstatic,Verizon,nil,3,nil,nil -311288,nw01.vzwstatic,Verizon,nil,3,nil,nil -311289,nw01.vzwstatic,Verizon,nil,3,nil,nil -311390,nw01.vzwstatic,Verizon,nil,3,nil,nil -311480,nw01.vzwstatic,Verizon,nil,3,nil,nil -311481,nw01.vzwstatic,Verizon,nil,3,nil,nil -311482,nw01.vzwstatic,Verizon,nil,3,nil,nil -311483,nw01.vzwstatic,Verizon,nil,3,nil,nil -311484,nw01.vzwstatic,Verizon,nil,3,nil,nil -311485,nw01.vzwstatic,Verizon,nil,3,nil,nil -311486,nw01.vzwstatic,Verizon,nil,3,nil,nil -311487,nw01.vzwstatic,Verizon,nil,3,nil,nil -311488,nw01.vzwstatic,Verizon,nil,3,nil,nil -311489,nw01.vzwstatic,Verizon,nil,3,nil,nil -311590,nw01.vzwstatic,Verizon,nil,3,nil,nil -312040,nw01.vzwstatic,Verizon,nil,3,nil,nil -312160,nw01.vzwstatic,Verizon,nil,3,nil,nil -312770,nw01.vzwstatic,Verizon,nil,3,nil,nil -310004,so01.vzwstatic,Verizon,nil,3,nil,nil -310010,so01.vzwstatic,Verizon,nil,3,nil,nil -310012,so01.vzwstatic,Verizon,nil,3,nil,nil -310013,so01.vzwstatic,Verizon,nil,3,nil,nil -310350,so01.vzwstatic,Verizon,nil,3,nil,nil -310590,so01.vzwstatic,Verizon,nil,3,nil,nil -310591,so01.vzwstatic,Verizon,nil,3,nil,nil -310592,so01.vzwstatic,Verizon,nil,3,nil,nil -310593,so01.vzwstatic,Verizon,nil,3,nil,nil -310594,so01.vzwstatic,Verizon,nil,3,nil,nil -310595,so01.vzwstatic,Verizon,nil,3,nil,nil -310596,so01.vzwstatic,Verizon,nil,3,nil,nil -310597,so01.vzwstatic,Verizon,nil,3,nil,nil -310598,so01.vzwstatic,Verizon,nil,3,nil,nil -310599,so01.vzwstatic,Verizon,nil,3,nil,nil -310820,so01.vzwstatic,Verizon,nil,3,nil,nil -310890,so01.vzwstatic,Verizon,nil,3,nil,nil -310891,so01.vzwstatic,Verizon,nil,3,nil,nil -310892,so01.vzwstatic,Verizon,nil,3,nil,nil -310893,so01.vzwstatic,Verizon,nil,3,nil,nil -310894,so01.vzwstatic,Verizon,nil,3,nil,nil -310895,so01.vzwstatic,Verizon,nil,3,nil,nil -310896,so01.vzwstatic,Verizon,nil,3,nil,nil -310897,so01.vzwstatic,Verizon,nil,3,nil,nil -310898,so01.vzwstatic,Verizon,nil,3,nil,nil -310899,so01.vzwstatic,Verizon,nil,3,nil,nil -310910,so01.vzwstatic,Verizon,nil,3,nil,nil -311110,so01.vzwstatic,Verizon,nil,3,nil,nil -311270,so01.vzwstatic,Verizon,nil,3,nil,nil -311271,so01.vzwstatic,Verizon,nil,3,nil,nil -311272,so01.vzwstatic,Verizon,nil,3,nil,nil -311273,so01.vzwstatic,Verizon,nil,3,nil,nil -311274,so01.vzwstatic,Verizon,nil,3,nil,nil -311275,so01.vzwstatic,Verizon,nil,3,nil,nil -311276,so01.vzwstatic,Verizon,nil,3,nil,nil -311277,so01.vzwstatic,Verizon,nil,3,nil,nil -311278,so01.vzwstatic,Verizon,nil,3,nil,nil -311279,so01.vzwstatic,Verizon,nil,3,nil,nil -311280,so01.vzwstatic,Verizon,nil,3,nil,nil -311281,so01.vzwstatic,Verizon,nil,3,nil,nil -311282,so01.vzwstatic,Verizon,nil,3,nil,nil -311283,so01.vzwstatic,Verizon,nil,3,nil,nil -311284,so01.vzwstatic,Verizon,nil,3,nil,nil -311285,so01.vzwstatic,Verizon,nil,3,nil,nil -311286,so01.vzwstatic,Verizon,nil,3,nil,nil -311287,so01.vzwstatic,Verizon,nil,3,nil,nil -311288,so01.vzwstatic,Verizon,nil,3,nil,nil -311289,so01.vzwstatic,Verizon,nil,3,nil,nil -311390,so01.vzwstatic,Verizon,nil,3,nil,nil -311480,so01.vzwstatic,Verizon,nil,3,nil,nil -311481,so01.vzwstatic,Verizon,nil,3,nil,nil -311482,so01.vzwstatic,Verizon,nil,3,nil,nil -311483,so01.vzwstatic,Verizon,nil,3,nil,nil -311484,so01.vzwstatic,Verizon,nil,3,nil,nil -311485,so01.vzwstatic,Verizon,nil,3,nil,nil -311486,so01.vzwstatic,Verizon,nil,3,nil,nil -311487,so01.vzwstatic,Verizon,nil,3,nil,nil -311488,so01.vzwstatic,Verizon,nil,3,nil,nil -311489,so01.vzwstatic,Verizon,nil,3,nil,nil -311590,so01.vzwstatic,Verizon,nil,3,nil,nil -312040,so01.vzwstatic,Verizon,nil,3,nil,nil -312160,so01.vzwstatic,Verizon,nil,3,nil,nil -312770,so01.vzwstatic,Verizon,nil,3,nil,nil -310004,mw01.vzwstatic,Verizon,nil,3,nil,nil -310010,mw01.vzwstatic,Verizon,nil,3,nil,nil -310012,mw01.vzwstatic,Verizon,nil,3,nil,nil -310013,mw01.vzwstatic,Verizon,nil,3,nil,nil -310350,mw01.vzwstatic,Verizon,nil,3,nil,nil -310590,mw01.vzwstatic,Verizon,nil,3,nil,nil -310591,mw01.vzwstatic,Verizon,nil,3,nil,nil -310592,mw01.vzwstatic,Verizon,nil,3,nil,nil -310593,mw01.vzwstatic,Verizon,nil,3,nil,nil -310594,mw01.vzwstatic,Verizon,nil,3,nil,nil -310595,mw01.vzwstatic,Verizon,nil,3,nil,nil -310596,mw01.vzwstatic,Verizon,nil,3,nil,nil -310597,mw01.vzwstatic,Verizon,nil,3,nil,nil -310598,mw01.vzwstatic,Verizon,nil,3,nil,nil -310599,mw01.vzwstatic,Verizon,nil,3,nil,nil -310820,mw01.vzwstatic,Verizon,nil,3,nil,nil -310890,mw01.vzwstatic,Verizon,nil,3,nil,nil -310891,mw01.vzwstatic,Verizon,nil,3,nil,nil -310892,mw01.vzwstatic,Verizon,nil,3,nil,nil -310893,mw01.vzwstatic,Verizon,nil,3,nil,nil -310894,mw01.vzwstatic,Verizon,nil,3,nil,nil -310895,mw01.vzwstatic,Verizon,nil,3,nil,nil -310896,mw01.vzwstatic,Verizon,nil,3,nil,nil -310897,mw01.vzwstatic,Verizon,nil,3,nil,nil -310898,mw01.vzwstatic,Verizon,nil,3,nil,nil -310899,mw01.vzwstatic,Verizon,nil,3,nil,nil -310910,mw01.vzwstatic,Verizon,nil,3,nil,nil -311110,mw01.vzwstatic,Verizon,nil,3,nil,nil -311270,mw01.vzwstatic,Verizon,nil,3,nil,nil -311271,mw01.vzwstatic,Verizon,nil,3,nil,nil -311272,mw01.vzwstatic,Verizon,nil,3,nil,nil -311273,mw01.vzwstatic,Verizon,nil,3,nil,nil -311274,mw01.vzwstatic,Verizon,nil,3,nil,nil -311275,mw01.vzwstatic,Verizon,nil,3,nil,nil -311276,mw01.vzwstatic,Verizon,nil,3,nil,nil -311277,mw01.vzwstatic,Verizon,nil,3,nil,nil -311278,mw01.vzwstatic,Verizon,nil,3,nil,nil -311279,mw01.vzwstatic,Verizon,nil,3,nil,nil -311280,mw01.vzwstatic,Verizon,nil,3,nil,nil -311281,mw01.vzwstatic,Verizon,nil,3,nil,nil -311282,mw01.vzwstatic,Verizon,nil,3,nil,nil -311283,mw01.vzwstatic,Verizon,nil,3,nil,nil -311284,mw01.vzwstatic,Verizon,nil,3,nil,nil -311285,mw01.vzwstatic,Verizon,nil,3,nil,nil -311286,mw01.vzwstatic,Verizon,nil,3,nil,nil -311287,mw01.vzwstatic,Verizon,nil,3,nil,nil -311288,mw01.vzwstatic,Verizon,nil,3,nil,nil -311289,mw01.vzwstatic,Verizon,nil,3,nil,nil -311390,mw01.vzwstatic,Verizon,nil,3,nil,nil -311480,mw01.vzwstatic,Verizon,nil,3,nil,nil -311481,mw01.vzwstatic,Verizon,nil,3,nil,nil -311482,mw01.vzwstatic,Verizon,nil,3,nil,nil -311483,mw01.vzwstatic,Verizon,nil,3,nil,nil -311484,mw01.vzwstatic,Verizon,nil,3,nil,nil -311485,mw01.vzwstatic,Verizon,nil,3,nil,nil -311486,mw01.vzwstatic,Verizon,nil,3,nil,nil -311487,mw01.vzwstatic,Verizon,nil,3,nil,nil -311488,mw01.vzwstatic,Verizon,nil,3,nil,nil -311489,mw01.vzwstatic,Verizon,nil,3,nil,nil -311590,mw01.vzwstatic,Verizon,nil,3,nil,nil -312040,mw01.vzwstatic,Verizon,nil,3,nil,nil -312160,mw01.vzwstatic,Verizon,nil,3,nil,nil -312770,mw01.vzwstatic,Verizon,nil,3,nil,nil -310004,we01.vzwstatic,Verizon,nil,3,nil,nil -310010,we01.vzwstatic,Verizon,nil,3,nil,nil -310012,we01.vzwstatic,Verizon,nil,3,nil,nil -310013,we01.vzwstatic,Verizon,nil,3,nil,nil -310350,we01.vzwstatic,Verizon,nil,3,nil,nil -310590,we01.vzwstatic,Verizon,nil,3,nil,nil -310591,we01.vzwstatic,Verizon,nil,3,nil,nil -310592,we01.vzwstatic,Verizon,nil,3,nil,nil -310593,we01.vzwstatic,Verizon,nil,3,nil,nil -310594,we01.vzwstatic,Verizon,nil,3,nil,nil -310595,we01.vzwstatic,Verizon,nil,3,nil,nil -310596,we01.vzwstatic,Verizon,nil,3,nil,nil -310597,we01.vzwstatic,Verizon,nil,3,nil,nil -310598,we01.vzwstatic,Verizon,nil,3,nil,nil -310599,we01.vzwstatic,Verizon,nil,3,nil,nil -310820,we01.vzwstatic,Verizon,nil,3,nil,nil -310890,we01.vzwstatic,Verizon,nil,3,nil,nil -310891,we01.vzwstatic,Verizon,nil,3,nil,nil -310892,we01.vzwstatic,Verizon,nil,3,nil,nil -310893,we01.vzwstatic,Verizon,nil,3,nil,nil -310894,we01.vzwstatic,Verizon,nil,3,nil,nil -310895,we01.vzwstatic,Verizon,nil,3,nil,nil -310896,we01.vzwstatic,Verizon,nil,3,nil,nil -310897,we01.vzwstatic,Verizon,nil,3,nil,nil -310898,we01.vzwstatic,Verizon,nil,3,nil,nil -310899,we01.vzwstatic,Verizon,nil,3,nil,nil -310910,we01.vzwstatic,Verizon,nil,3,nil,nil -311110,we01.vzwstatic,Verizon,nil,3,nil,nil -311270,we01.vzwstatic,Verizon,nil,3,nil,nil -311271,we01.vzwstatic,Verizon,nil,3,nil,nil -311272,we01.vzwstatic,Verizon,nil,3,nil,nil -311273,we01.vzwstatic,Verizon,nil,3,nil,nil -311274,we01.vzwstatic,Verizon,nil,3,nil,nil -311275,we01.vzwstatic,Verizon,nil,3,nil,nil -311276,we01.vzwstatic,Verizon,nil,3,nil,nil -311277,we01.vzwstatic,Verizon,nil,3,nil,nil -311278,we01.vzwstatic,Verizon,nil,3,nil,nil -311279,we01.vzwstatic,Verizon,nil,3,nil,nil -311280,we01.vzwstatic,Verizon,nil,3,nil,nil -311281,we01.vzwstatic,Verizon,nil,3,nil,nil -311282,we01.vzwstatic,Verizon,nil,3,nil,nil -311283,we01.vzwstatic,Verizon,nil,3,nil,nil -311284,we01.vzwstatic,Verizon,nil,3,nil,nil -311285,we01.vzwstatic,Verizon,nil,3,nil,nil -311286,we01.vzwstatic,Verizon,nil,3,nil,nil -311287,we01.vzwstatic,Verizon,nil,3,nil,nil -311288,we01.vzwstatic,Verizon,nil,3,nil,nil -311289,we01.vzwstatic,Verizon,nil,3,nil,nil -311390,we01.vzwstatic,Verizon,nil,3,nil,nil -311480,we01.vzwstatic,Verizon,nil,3,nil,nil -311481,we01.vzwstatic,Verizon,nil,3,nil,nil -311482,we01.vzwstatic,Verizon,nil,3,nil,nil -311483,we01.vzwstatic,Verizon,nil,3,nil,nil -311484,we01.vzwstatic,Verizon,nil,3,nil,nil -311485,we01.vzwstatic,Verizon,nil,3,nil,nil -311486,we01.vzwstatic,Verizon,nil,3,nil,nil -311487,we01.vzwstatic,Verizon,nil,3,nil,nil -311488,we01.vzwstatic,Verizon,nil,3,nil,nil -311489,we01.vzwstatic,Verizon,nil,3,nil,nil -311590,we01.vzwstatic,Verizon,nil,3,nil,nil -312040,we01.vzwstatic,Verizon,nil,3,nil,nil -312160,we01.vzwstatic,Verizon,nil,3,nil,nil -312770,we01.vzwstatic,Verizon,nil,3,nil,nil -302490,internet.freedommobile.ca,FreedomMobile,nil,1,nil,nil \ No newline at end of file diff --git a/rooter/0optionalapps/ext-blacklist/Makefile b/rooter/0optionalapps/ext-blacklist/Makefile deleted file mode 100644 index 0c156e8..0000000 --- a/rooter/0optionalapps/ext-blacklist/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-blacklist -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-blacklist - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Install Mac Blacklisting - PKGARCH:=all -endef - -define Package/ext-blacklistdescription - Helper scripts to install Mac Blacklisting -endef - - -define Build/Compile -endef - -define Package/ext-blacklist/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-blacklist)) diff --git a/rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist b/rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist deleted file mode 100644 index 00fb552..0000000 --- a/rooter/0optionalapps/ext-blacklist/files/etc/config/blacklist +++ /dev/null @@ -1,4 +0,0 @@ - -config blacklist 'blacklist' - - diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh b/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh deleted file mode 100644 index 6775a95..0000000 --- a/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/blacklist.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Blacklist" "$@" -} - -getmac() { - local config=$1 - config_get src_mac $1 src_mac - if [ ! -z $src_mac ]; then - if [ $create = "0" ]; then - uci set firewall.blacklist=rule - uci set firewall.blacklist.src='lan' - uci set firewall.blacklist.target='REJECT' - uci set firewall.blacklist.dest='wan' - uci set firewall.blacklist.name='Blacklist' - create=1 - fi - uci add_list firewall.blacklist.src_mac=$src_mac - fi -} - -sleep 8 -create="0" -uci -q delete firewall.blacklist -config_load blacklist -config_foreach getmac devices -uci commit firewall -/etc/init.d/firewall restart - -exit 0 diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh b/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh deleted file mode 100644 index 4b13613..0000000 --- a/rooter/0optionalapps/ext-blacklist/files/usr/lib/blacklist/chkblack.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Blacklist" "$@" -} - - -result=`ps | grep -i "blacklist.sh" | grep -v "grep" | wc -l` -if [ $result -eq 0 ]; then - /usr/lib/blacklist/blacklist.sh & -fi \ No newline at end of file diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua b/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua deleted file mode 100644 index 5797a2d..0000000 --- a/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/controller/blacklist.lua +++ /dev/null @@ -1,10 +0,0 @@ -module("luci.controller.blacklist", package.seeall) - -function index() - local page - local lock = luci.model.uci.cursor():get("custom", "menu", "full") - if lock == "1" then - page = entry({"admin", "adminmenu", "blacklist"}, cbi("blacklist"), "---Blacklist by Mac", 10) - page.dependent = true - end -end diff --git a/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua b/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua deleted file mode 100644 index 91fa4e7..0000000 --- a/rooter/0optionalapps/ext-blacklist/files/usr/lib/lua/luci/model/cbi/blacklist.lua +++ /dev/null @@ -1,21 +0,0 @@ -require("nixio.fs") - -m = Map("blacklist", translate("Blacklist Devices by Mac Address")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/blacklist/chkblack.sh &") -end - -s = m:section(TypedSection, "devices", translate("Blacklisted Devices"), translate("Block these devices from using the Internet")) -s.anonymous = true -s.addremove = true - -o = s:option(Value, "src_mac", translate("Device MAC address")) - o.datatype = "list(macaddr)" - o.placeholder = translate("any") - - luci.sys.net.mac_hints(function(mac, name) - o:value(mac, "%s (%s)" %{ mac, name }) - end) - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-blockport/Makefile b/rooter/0optionalapps/ext-blockport/Makefile deleted file mode 100644 index 103fa98..0000000 --- a/rooter/0optionalapps/ext-blockport/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-blockport -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-blockport - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Install Port Blocking - PKGARCH:=all -endef - -define Package/ext-blockport/description - Helper scripts to install Port Blocking -endef - - -define Build/Compile -endef - -define Package/ext-blockport/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-blockport)) diff --git a/rooter/0optionalapps/ext-blockport/files/etc/config/blockport b/rooter/0optionalapps/ext-blockport/files/etc/config/blockport deleted file mode 100644 index 8e69716..0000000 --- a/rooter/0optionalapps/ext-blockport/files/etc/config/blockport +++ /dev/null @@ -1,4 +0,0 @@ - -config port 'port' - - diff --git a/rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.sh b/rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.sh deleted file mode 100644 index 6965bc0..0000000 --- a/rooter/0optionalapps/ext-blockport/files/usr/lib/blockport/blockport.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -config="firewall" - -do_block_remove() { - config_get name $1 name - if [ "$name" = "Block_src" ]; then - uci delete $config".""$1" - fi -} - -handle_port() { - echo $1 - uci add $config rule - uci set $config.@rule[-1].src='lan' - uci set $config.@rule[-1].family='ipv4' - uci set $config.@rule[-1].dest='wan' - uci set $config.@rule[-1].target='DROP' - uci set $config.@rule[-1].proto='tcp' - uci set $config.@rule[-1].src_port="$1" - uci set $config.@rule[-1].name='Block_src' -} - -do_port() { - config_list_foreach "$1" block handle_port -} - -sleep 8 -config_load $config -config_foreach do_block_remove rule - -config_load blockport -config_foreach do_port port -uci commit $config -/etc/init.d/firewall restart 2>/dev/null - diff --git a/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua b/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua deleted file mode 100644 index 57bd9ff..0000000 --- a/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/controller/blockport.lua +++ /dev/null @@ -1,15 +0,0 @@ --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.blockport", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local lock = luci.model.uci.cursor():get("custom", "menu", "full") - --if lock == "1" then - local page - page = entry({"admin", "adminmenu", "blockport"}, cbi("portblk"), _(translate("Port Blocking")), 11) - page.dependent = true - --end -end diff --git a/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua b/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua deleted file mode 100644 index 73cd1ea..0000000 --- a/rooter/0optionalapps/ext-blockport/files/usr/lib/lua/luci/model/cbi/portblk.lua +++ /dev/null @@ -1,21 +0,0 @@ -local utl = require "luci.util" - -local sys = require "luci.sys" -local zones = require "luci.sys.zoneinfo" -local fs = require "nixio.fs" -local conf = require "luci.config" - -m = Map("blockport", translate("Port Blocking"), translate("Block traffic using specific ports")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/blockport/blockport.sh &") -end - -s = m:section(TypedSection, "port", translate("Block Port List")) -s.anonymous = true -s.addremove = false - -s:option(DynamicList, "block", translate("Ports")) - - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-domain/Makefile b/rooter/0optionalapps/ext-domain/Makefile deleted file mode 100644 index 103fa98..0000000 --- a/rooter/0optionalapps/ext-domain/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-blockport -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-blockport - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Install Port Blocking - PKGARCH:=all -endef - -define Package/ext-blockport/description - Helper scripts to install Port Blocking -endef - - -define Build/Compile -endef - -define Package/ext-blockport/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-blockport)) diff --git a/rooter/0optionalapps/ext-domain/files/etc/config/blockport b/rooter/0optionalapps/ext-domain/files/etc/config/blockport deleted file mode 100644 index 8e69716..0000000 --- a/rooter/0optionalapps/ext-domain/files/etc/config/blockport +++ /dev/null @@ -1,4 +0,0 @@ - -config port 'port' - - diff --git a/rooter/0optionalapps/ext-domain/files/usr/lib/blockport/blockport.sh b/rooter/0optionalapps/ext-domain/files/usr/lib/blockport/blockport.sh deleted file mode 100644 index 6965bc0..0000000 --- a/rooter/0optionalapps/ext-domain/files/usr/lib/blockport/blockport.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -config="firewall" - -do_block_remove() { - config_get name $1 name - if [ "$name" = "Block_src" ]; then - uci delete $config".""$1" - fi -} - -handle_port() { - echo $1 - uci add $config rule - uci set $config.@rule[-1].src='lan' - uci set $config.@rule[-1].family='ipv4' - uci set $config.@rule[-1].dest='wan' - uci set $config.@rule[-1].target='DROP' - uci set $config.@rule[-1].proto='tcp' - uci set $config.@rule[-1].src_port="$1" - uci set $config.@rule[-1].name='Block_src' -} - -do_port() { - config_list_foreach "$1" block handle_port -} - -sleep 8 -config_load $config -config_foreach do_block_remove rule - -config_load blockport -config_foreach do_port port -uci commit $config -/etc/init.d/firewall restart 2>/dev/null - diff --git a/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/blockport.lua b/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/blockport.lua deleted file mode 100644 index fca343d..0000000 --- a/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/controller/blockport.lua +++ /dev/null @@ -1,12 +0,0 @@ --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.blockport", package.seeall) - -function index() - local lock = luci.model.uci.cursor():get("custom", "menu", "full") - if lock == "1" then - local page - page = entry({"admin", "adminmenu", "blockport"}, cbi("portblk"), _("---Port Blocking"), 10) - page.dependent = true - end -end diff --git a/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/portblk.lua b/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/portblk.lua deleted file mode 100644 index 73cd1ea..0000000 --- a/rooter/0optionalapps/ext-domain/files/usr/lib/lua/luci/model/cbi/portblk.lua +++ /dev/null @@ -1,21 +0,0 @@ -local utl = require "luci.util" - -local sys = require "luci.sys" -local zones = require "luci.sys.zoneinfo" -local fs = require "nixio.fs" -local conf = require "luci.config" - -m = Map("blockport", translate("Port Blocking"), translate("Block traffic using specific ports")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/blockport/blockport.sh &") -end - -s = m:section(TypedSection, "port", translate("Block Port List")) -s.anonymous = true -s.addremove = false - -s:option(DynamicList, "block", translate("Ports")) - - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-rspeedtest/Makefile b/rooter/0optionalapps/ext-rspeedtest/Makefile deleted file mode 100644 index 5dee477..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-rspeedtest -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-rspeedtest - SECTION:=utils - CATEGORY:=ROOter - DEPENDS:=+httping +curl +coreutils +coreutils-date +speedtestpp - SUBMENU:=Optional Applications - TITLE:=support for ROOter SpeedTest - PKGARCH:=all -endef - -define Package/ext-rspeedtest/description - Helper scripts to enable ROOter SpeedTest -endef - - -define Build/Compile -endef - -define Package/ext-rspeedtest/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,ext-rspeedtest)) diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua deleted file mode 100644 index 6ac5628..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/controller/rspeedtest.lua +++ /dev/null @@ -1,79 +0,0 @@ -module("luci.controller.rspeedtest", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - page = entry({"admin", "speed", "rspeedtest"}, template("speedtest/rspeedtest"), translate("SpeedTest by Ookla"), 72) - page.dependent = true - - entry({"admin", "speed", "closeserver"}, call("action_closeserver")) - entry({"admin", "speed", "stoptest"}, call("action_stoptest")) - entry({"admin", "speed", "getspeed"}, call("action_getspeed")) - entry({"admin", "speed", "getspeeddata"}, call("action_getspeeddata")) -end - -function action_closeserver() - local rv = {} - - os.execute("/usr/lib/speedtest/info.sh") - result = "/tmp/sinfo" - file = io.open(result, "r") - if file ~= nil then - rv["status"] = file:read("*line") - if rv["status"] ~= "0" then - rv["ip"] = file:read("*line") - rv["isp"] = file:read("*line") - rv["city"] = file:read("*line") - rv["prov"] = file:read("*line") - end - file:close() - else - rv["status"] = "0" - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_stoptest() - os.execute("/usr/lib/speedtest/stop.sh") -end - -function action_getspeed() - local rv = {} - - os.execute("/usr/lib/speedtest/getspeed.sh ") - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_getspeeddata() - local rv = {} - - result = "/tmp/getspeed" - file = io.open(result, "r") - if file ~= nil then - rv["dlsize"] = file:read("*line") - rv["dlelapse"] = file:read("*line") - rv["ulsize"] = file:read("*line") - rv["ulelapse"] = file:read("*line") - file:close() - else - rv["dlsize"] = "0" - rv["ulsize"] = "0" - end - result = "/tmp/spworking" - file = io.open(result, "r") - if file ~= nil then - rv["working"] = file:read("*line") - file:close() - else - rv["working"] = "0" - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm deleted file mode 100644 index a35eaa4..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/lua/luci/view/speedtest/rspeedtest.htm +++ /dev/null @@ -1,259 +0,0 @@ -<%+header%> -<% - user_icon = resource .. "/img/user.png" - prov_icon = resource .. "/img/prov.png" - load_icon = resource .. "/icons/loading.gif" -%> - - - - -
                - -
                -

                <%:Speed Test by Ookla%>

                -
                <%:An Internet speed test that runs from the router%>
                - - - -
                - - - - - - -
                <%:***Finding Optimal Server***%>
                 
                - - - - - - - - - - -
                 
                 
                - - - - - - - - -
                 
                 
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                 
                - - - - - - - - - - - - - - - - - - -
                - -
                - -<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua deleted file mode 100644 index 5544048..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/closest.lua +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/lua - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -ulat = arg[1] -ulon = arg[2] - -url = {} -slat = {} -slon = {} -city = {} -dist = {} -prov = {} - -radius = 6371 - -cnt = 0 -clos = 99999999.99 -index = 0 -file = io.open("/tmp/slist", "r") -if file ~= nil then - repeat - line = file:read("*line") - if line == nil then - break - end - cnt = cnt + 1 - s, e = line:find(" ") - if s ~= nil then - url[cnt] = trim(line:sub(0, s-1)) - cs, ce = line:find(" ", e+1) - slat[cnt] = trim(line:sub(e, cs-1)) - s, e = line:find(" ", ce+1) - slon[cnt] = trim(line:sub(ce, s-1)) - cs, ce = line:find("\"", e+1) - s, e = line:find("\"", ce+1) - city[cnt] = trim(line:sub(ce+1, s-1)) - prov[cnt] = trim(line:sub(e+1)) - - dlat = math.rad(slat[cnt] - ulat) - dlon = math.rad(slon[cnt] - ulon) - a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.rad(ulat)) * math.cos(math.rad(slat[cnt])) * math.sin(dlon / 2) * math.sin(dlon / 2)) - c = 2 * math.atan(math.sqrt(a), math.sqrt(1 - a)) - dist[cnt] = radius * c - - if dist[cnt] < clos then - clos = dist[cnt] - index = cnt - end - end - until 1==0 - file:close() - tfile = io.open("/tmp/close", "w") - tfile:write("CURL=\"", url[index], "\"\n") - tfile:write("CITY=\"", city[index], "\"\n") - tfile:write("PROV=\"", prov[index], "\"") - tfile:close() -end - - diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh deleted file mode 100644 index 7583f5b..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/getspeed.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Getspeed " "$@" -} - -fixspeed() { - sed 's/\(PROVIDER=[[:blank:]]*\)\(.*\)/\1'\''\2'\''/' /tmp/speed > /tmp/tspeed -} - -echo "0" > /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "1" > /tmp/spworking - -JITTER="" -LATENCY="" -DOWNLOAD_SPEED="" -UPLOAD_SPEED="" - -while IFS= read -r line -do - read -r line - read -r line - read -r line - read -r line - read -r line - break -done < /tmp/sinfo -url=${line:7:100} -url=$(echo $url" " | tr "/" ",") -url=$(echo "$url" | cut -d, -f1) -rm -f /tmp/speed -speedtest --test-server $url --output text > /tmp/speed & -while [ -z "$JITTER" ] -do - if [ -e /tmp/speed ]; then - fixspeed - if [ -e /tmp/tspeed ]; then - source /tmp/tspeed - fi - fi - sleep 1 -done -echo "$LATENCY" > /tmp/getspeed -echo "$JITTER" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "2" > /tmp/spworking - -while [ -z "$DOWNLOAD_SPEED" ] -do - if [ -e /tmp/speed ]; then - fixspeed - if [ -e /tmp/tspeed ]; then - source /tmp/tspeed - fi - fi - sleep 1 -done -echo "$LATENCY" > /tmp/getspeed -echo "$JITTER" >> /tmp/getspeed -echo "$DOWNLOAD_SPEED" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "3" > /tmp/spworking - -while [ -z "$UPLOAD_SPEED" ] -do - if [ -e /tmp/speed ]; then - fixspeed - if [ -e /tmp/tspeed ]; then - source /tmp/tspeed - fi - fi - sleep 1 -done -echo "$LATENCY" > /tmp/getspeed -echo "$JITTER" >> /tmp/getspeed -echo "$DOWNLOAD_SPEED" >> /tmp/getspeed -echo "$UPLOAD_SPEED" >> /tmp/getspeed -echo "0" > /tmp/spworking - diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh deleted file mode 100644 index 1232246..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/info.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh - -killprocess() { - proc=$1 - PID=$(ps |grep "$proc" | grep -v grep |head -n 1 | awk '{print $1}') - if [ ! -z $PID ]; then - kill -9 $PID - fi -} - -killprocess "speedtest --test-server" -killprocess "/speedtest/closest.lua" -killprocess "/speedtest/getspeed.sh" -killprocess "/speedtest/servers.lua" - -rm -f /tmp/speed -rm -f /tmp/sinfo -rm -f /tmp/close -rm -f /tmp/getspeed -rm -f /tmp/jpg -rm -f /tmp/pinfo -rm -f /tmp/sinfo -rm -f /tmp/slist -echo "0" > /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" > /tmp/spworking -wget -q -O /tmp/client http://speedtest.net/speedtest-config.php -if [ $? = "0" ]; then - RAW=$(cat /tmp/client) - clid=$(echo $RAW" " | grep -o " " | tr -d '"' | tr " " "," | tr "/" "," | tr "=" ",") - ip=$(echo $clid | cut -d, -f3) - ulat=$(echo $clid | cut -d, -f5) - ulon=$(echo $clid | cut -d, -f7) - isp=$(echo $clid | cut -d, -f9) - rm -f /tmp/client - echo "1" > /tmp/sinfo - echo "$ip" >> /tmp/sinfo - echo "$isp" >> /tmp/sinfo - - wget -q -O /tmp/servers http://www.speedtest.net/speedtest-servers-static.php - if [ $? != "0" ]; then - wget -q -O /tmp/servers http://c.speedtest.net/speedtest-servers.php - if [ $? != "0" ]; then - echo "0" > /tmp/sinfo - exit 0 - fi - fi - rm -f /tmp/slist - while IFS= read -r line - do - read -r line - /usr/lib/speedtest/servers.lua "$line" - if [ -e /tmp/server ]; then - source /tmp/server - echo "$URL $LAT $LON "\""$NAME"\"" $SPONSOR" >> /tmp/slist - rm -f /tmp/server - fi - done < /tmp/servers - rm -f /tmp/servers - - /usr/lib/speedtest/closest.lua $ulat $ulon - source /tmp/close - echo "$CITY" >> /tmp/sinfo - echo "$PROV" >> /tmp/sinfo - echo "$CURL" >> /tmp/sinfo - rm -f /tmp/slist - rm -f /tmp/close -else - echo "0" > /tmp/sinfo - exit 0 -fi - diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh deleted file mode 100644 index 7ec502c..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/ping.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -rm -f /tmp/pinfo - -echo "0" > /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "1" > /tmp/spworking -while IFS= read -r line -do - read -r line - read -r line - read -r line - read -r line - read -r line - break -done < /tmp/sinfo - -hp=$(httping -c 3 $line) -pingg=$(echo $hp" " | grep -o "round-trip .\+ ms " | tr " " "," | tr "/" ",") -latency=$(echo $pingg | cut -d, -f7) - -echo "$latency" > /tmp/pinfo -echo "2" > /tmp/spworking - diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua deleted file mode 100644 index abc3962..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/servers.lua +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/lua - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -line = arg[1] -if line == nil then - return -end - -s, e = line:find("url=\"") -if s ~= nil then - cs, ce = line:find("\"", e+1) - url = trim(line:sub(e+1, cs-1)) -else - return -end -s, e = line:find("lat=\"") -if s ~= nil then - cs, ce = line:find("\"", e+1) - lat = trim(line:sub(e+1, cs-1)) -end -s, e = line:find("lon=\"") -if s ~= nil then - cs, ce = line:find("\"", e+1) - lon = trim(line:sub(e+1, cs-1)) -end -s, e = line:find("name=\"") -if s ~= nil then - cs, ce = line:find("\"", e+1) - name = trim(line:sub(e+1, cs-1)) -end -s, e = line:find("sponsor=\"") -if s ~= nil then - cs, ce = line:find("\"", e+1) - sponsor = trim(line:sub(e+1, cs-1)) -end - -tfile = io.open("/tmp/server", "w") -tfile:write("URL=\"", url, "\"\n") -tfile:write("LAT=\"", lat, "\"\n") -tfile:write("LON=\"", lon, "\"\n") -tfile:write("NAME=\"", name, "\"\n") -tfile:write("SPONSOR=\"", sponsor, "\"") -tfile:close() \ No newline at end of file diff --git a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh b/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh deleted file mode 100644 index c95dec0..0000000 --- a/rooter/0optionalapps/ext-rspeedtest/files/usr/lib/speedtest/stop.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -killprocess() { - proc=$1 - PID=$(pgrep -f "$proc") - if [ ! -z $PID ]; then - kill -9 $PID - fi -} - -killprocess "speedtest --test-server" -killprocess "/speedtest/closest.lua" -killprocess "/speedtest/getspeed.sh" -killprocess "/speedtest/servers.lua" - -flist="/tmp/speed /tmp/sinfo /tmp/close /tmp/getspeed /tmp/jpg /tmp/pinfo /tmp/sinfo /tmp/slist" - -for val in $flist; do - rm -f $val -done - -echo "0" > /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" >> /tmp/getspeed -echo "0" > /tmp/spworking - diff --git a/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/prov.png b/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/prov.png deleted file mode 100644 index 715618c41900d9ebd5be760daa41acadfc2cd01f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23789 zcmV($K;yrOP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3^glH@p+W&gQ~S^@zQ({eD7BE5rNexC!Hdw4`- zl}NX=TV}YMnJSe8-f-`ma6JF}f4#?l{nvkm+(JC=RBCQHpZvMo-D2k-_5A*Pe~0tl z|J{G$uiu5g|NQv_0!h{=O8)nSWl8|FK3tKM(02Kfiu| zO#Is&g}*-eZ@+lkeg5swA8Yr%tG@5^Jzc*uE0vF*hx+v>`(M0pu$0$+Tjs0q|HQw` z{%U+x9&xf`i`^W2%_AU{to9r3utE=Sc=q2jOm6XxPb~Z$<75x~S-nbZab9l0?N@kX zVH?(QRd!;sYZpI`zwagN&u#njW~hAf3cNA~E*5ylzrK$D^uzy`uiqDXUqv^Bv;JNy z?kg(O+=e^ne|Z&q5Z<3PO?!R!*YStkoPTWW#SW&u%#{c1=lCu$Qus@@uD#C}uS@5B zoZl{ovVJbW67kuIn+X>?aApKMRnUKwbWW$?Jc$o6P8+T9+_kPox-}2VCz5VyD z{p{-BcP;#5=l;8Z2+~L;!?A*Wi z?LX|=>f57SdxO+M*Yvzz4BInDN51Pj+8pJKt%On9be@vcwpuJiro`)d8Z>$(TV@(kYjsjs_Cex7c&oXag%2_HKPoBpQoJ}Y5h%Y|WG*GR1Uk=T@*O|DNb zbHGtQs6vj>GcKp=8R z7bXzGnLTx>3T`pk5)Tu&Oa`uAF; z%^_bZn$5ip)Tv~l2FIYk9rrbEUejUeZA1pFC6N zNiQ7b^W1EFSO>!PjDq;RCwq_Jrtu;z@0u5eqp*7;VFa#~dchlJeIWOp(-V>4{TVHc zh8dZeb;o2p3(!#sh>vuK;%EzfFKrfFXz#A*Zq15rbrL!X8IaZ1zw;?Rj z86eRtm42(EA`49zNEF`vJ=>W1;q6zC<$dmjzVN!4R;tJVzQ5GTTFfyQz=G@Ik$6J9 zkiv<^-jg+Vcg`CX3fF@{D5-}v*F>)ZXaNs)%s1Zq#<>Ew{9bh?-oFah1hOndFV!|{ zc*-Ybxvx{t6}gB8rlp0|!}vdGJ_R9ReOSu$jMN9()!Dqk&gK@+$zB4YuSabfZ0q%e zp2yYu{VaAS%~g*$OUzgo7KaxHRHI@vFi!Kyys5;CkGxnOaPqv^klC=rdEKGS_Qo{% z^!J(TD0kultIUh1c`_zBok~+ynp!(ccq;}eu9DvKD)Uy`kwXo8=4S8_n3n54TEi+{ z$~T53W8Eu@g5#PPy37?(+<0eKada$V))%OO3MAN=`?%T|?Kv)%;?!s4H}QRY^XPr? zI2a7{b>KoUldgEdZq+{UL3IFkGFLeBn1h?;!4E{Nwh&x?>>{QLapA$Pq#U4)56{f1 z-wQ$C25RIhjK0QtGD3{Yc#+6AAACf|2jT)ybcC{Dk>2X2)@NWSuzM%=paPS58r� zq9IEd4;~l$)Nn54ehxkjZz2S}=XGNOaG-e90IAVx$E&3KM$8N1c!Cioj*q=#_i=#u zG3-PiNaoS62ZMCJQ>2QlVG+*<2Z+;lzbjIDA?sCvPBW%n5e`I8H=Fo1Le2U;=Ydz@ ze_`D3i3P$^hLZ7uVZU>>fX7=ipggtV7Ejz%#M&a65#2@za5^Dk!Vm1te1Xf?=uF?sz2)^>q+Ls-m30k1s(>^bh=6t8M?8kzM+nz=CIDkJ;UThAP0Pt=@ukqqj&Yj*p$0H%j}m76C)_;u23hEGx1wl4Z;b z)B!3H-X2&BFez(&J+KN~CtL@CLiu@+geF5RpQtK;|5#zUb!Pyx8E-q`#o10YhBmTQQ|&9UDykp zpZ*w$Wg{>~1Jj-#Y+67R3b%ga^4@W+y{+*{uaCBn`v-Q!g8~wPEamQ+4%P_oi!)$R zQQU$L${lkx=eocwA|5mo>xuRPVD7gF7BYYxT(!`oc>&Y#h3Lxl)GOmn!u4ioR*S4S z2=8?PkcGLBfv_sh?(EnOEZAEQkfrj3q-IPA_${BWs=<nF%eM1-pak{sDyUKc1S`W8k&mT$!~(rNIZ!gZmz_ z9vHEJ8Okinz_nu4l4z}5n2{#?L4}&?$U2_)cEUZC96|D2fxIooTIRDE(B&DNRA;@i4M%t1i($m+3YFbRnNR39j^Mq0I+I&aZPN> zHBVVw-dq8*rq%+uMd-)&S={p@Qa8ME3N?^eUOTvGNCmA3zuF!b3ZnU zTUSH?{eHEc>Ojljv@VMGgfS74k9i{WFL-v|Z)Xi*FeCF{Bpk`cFk*O(^R#nf`vI`J zlQaRjAZwNv4;vr&&&?gN_Aj!`Qh&e{b~=_QydEqmMq}@7pXg&t`z4?znct^bMM(Al z0??h>PSQ+dfQXC_=?$Hv0O1cy{zdDVAD_TLa z1>^?ALs4ot79W7c6Gaq0MIgvh0{x1li2YczfR!NiSaq&kHI^sH9%P%*_x`dBt00hN z;!V$cU|o6KqV>ZE;U>!6fTTPrN`=+F#V@)api2hGt}8=Cu%f5|wC-pfON6?ghGjBv z5S)Rt2i5RgtGkhvulH`(1dfAhpB+-dAHy@icHu>A-*z;0ApytrgrGpS_?hshtMai8 zlOu?p2}X)71x&s{3&XZxzc9f$)?2fc4@3?QjDJWyHZb88+hmooiTGEayKrZBgX7-N znLcnOVETwvS{r*RZ1}3@z?Xuj&<)fFuMV7mTHtUYEj>rc!0brAA;^*-BQPVtD#}u~ z{df@Ogy$*;z`x7~SGZ8n(jqhw)PZPJ`4%LSZA<7sOzf1E;=IsjP}6*|mv}(k7cA|7 z$c6>-!7^SQUWlDRh5+7e!qc>`k|0gk$;MvjE)Rm$M(>78gh#@8Bamz}5F7rrw!1>` z!`&Y17ifEEkWa)}WS06*X!REWQVWezqG{PQZ^S$mv# zAs_{Za2NC#?0lAqfn>d5N4`G1Fm&lUa1w4GlyC6}ZWucUExlsrA=R*3LDY-AG7GqMA z#3O)@`oy7Q=n?D(ckx^ke|+I808t2I!4#l9>^V?Ssu_`Vp(L;n z5$_AznAgOKWqlZSL>Snya`#vue`8+wI3QyOExw@F1x~>E4A%LCG@mz?yMirnw}|Hb z;IJ^-6R?UwHO5k4Ajd#Y?|E0@@~www)J)z~LV;bqht3I zi;D9?Wk8FVcdT14NI2rta3=VXo-vGXTs2`w2BNTTOr>P1Al^{61DI?G51xvhGHNpK zxi;2d6|UTh>;Gt42ap+wVT%Juc*=CpQx&a%eU2TlV&NVP2x`YpfhFO-+%Qjcqd{nV zL@M;%5Ky+72a8AsuBqYq5<3Bpz>8#{M})3aOr&ut7_N~lWOHC!WDZ*@Cs*lt-YDQ1 zLDF~%@cm`HhFk9k?)EyJWyi|6k1sONS!-_?+Q5hQe;htfVo{HrN zbsjLThPs%fK*V6M7*FsJka$2d;rRh(f*-iS+XYAgoWU{j`0#6lWWj4DHwuM#;drCK zNE@b`bpng^A&SOoH2^2H5@lcDf7a_w*d%s*f?6W-e5D57$Fq;)1eIU7981RxIq zYQcLVyo0xa{K^iw0$R#7@!0SuJQCmnihx;SDUmuTM87tKncNRDt#_2*v4dEB_Nf5X z1BM+n#=VU#jo9}Gj??P-p^|63$J-5KJmuN1LUwgJ^JIg{>!-e~x~5oBtRQ5tt&P40Yo)m5uvf|xem7W zOmc|V3*}cV68B!QIslrg1Ba*LrQsuN=iV=1IXDFN7t%_(zE1>aM^GJNhLg&W5qNOj zo+@JJ8t!+ypF8SO@GkXn)B2l$7u@5+?oC72<9IN}Z~Hzf$Wrmf$?zXSkni)2_?`qI z&83`%rr5!R(Zq0qS3)V3Pk1r92hRmM>Cea+;g~Y~%r)Q*@Yx^31Tf()=h?6cxO@N_ zI--_b1{e^WTH*a^0sMjR7nY&m>_A;Wp@|_9M?;)2q#)r3g?Lm)l$np^86eWHGy|c7 zz8&aE!FpmlaH1V|BPRsG1BPzUQpftBrW^fpKMi0Sa}l|~r*VyEh{YsvK_D~Fi~cTT z8YG31y_g%ASjBN(*z)xvCeJYcgT{$LHP z`Oy82AUZgPVKN}+<_YED)wo7M1*-{xsh~|*4pO^g2CNipyXm@264ZixM__iI2QUXe zwBbE`9)!~jc|h*Q&A)H`)OAiYF+7#EOW0Se+H0PGpEe%NP~Bqt({1qcW~K1IMsZYB zK1n}_)!XcZeF#`#2R1n0G32mqWeb=o))^Lgvzl=nX!c-NVCp*-+__@U$jB!Bj|Kt;hu?+GXjmkD6 zSI9P$8AWy5+X2{Q4{?7mv>ti;4d>om3B8qLLn1VNfQ^a=-XDkl@)sy(a}^vT5_wb{ z=;K|O(!u<*Fj{^zH$j1~96`}Y;q$P^DMN!Gka7F7syWRrcL&NG;28KR*a83giWG+yT1LaBVMFnbKbvH(*atEk4So-2kF37}G#N5hGC5!|Tu3w0N~A%MhyhxpR-2Em-~FjbEkda*7@8AgD|Tp(8XOJC;! zX+@P0AfuTH&V>g70^`|%jI3(!7|o}iSyT8J$&@{a8?ZMh5^tJ5chp66OhIL zX#tK|=?w%7ZTlppV#t>vKp^1tS*i<{iiU*?pn1R&uXA8+uo77I{vc%lCiH(m)VbY- zzeLp=Xlt0A&@OJ2{?RGy!jr&aup>j5JTayLH5c~Xnx|_!XvDEXyI;fyx1$OREBIxG za>&~;&oOCBAT>ontg6L~WiuzV9}kobe)+3-#d~ek(6*Hf$VV)8b9qBgXX%ukLAJUvY(oG0q>blMT)ByJn(b?d%p# zfbBIMC2Bg*V8Kp+7hf197`ULPbhc$9B8;QIjUUT@)?c8=%m9c8Re*Q^w9qmr#%nxf z=M@0a1F;0wfuGKpMMo0M0ZPgG73}YMK_ijy9e>4ifJ+W&J3R0KQ$P~H)F5J6J)Gq- zk|C0TYVlb>F?Rk;d%G|m0qET)lmyuT6(1=B&3~d;Y(A2Q(vKmM#7%-UbHYxg5?EbB z**gO)m$WKm0Z?8kBB&OegFA~Xi}}=LNa!)5v*Vk>27^8zcQ(S^C|z3kG=o1_5JZf7 zSS;bODHG%!h=B+h=zTK;zG17*U%|$6C!B=O7zW%A>gPJ?P0oe+U^Ux;JG`I+U=}Rg z1MB@Fi5QK=g7Sg5(+W^Q0T45wNm*beb8BqCG%oRGZx9M$Z~*dz&fT~rIHDo?`C!&j z>#JP?N|xoqgrO>?BUq~^NCUND_qQr|5e(LNcrpw$CLMr|d<+a~W(itC!6t73?4YiE zIKqgLPcI*kcoCz5i`(cye9k21?d0q5FixuU?M*_;*(55Nk?)& z@hoSOVxJqV+!7hA^BeF8ID>${eod6$R;HlS;9hPtnw?TRD)7c&IXGIaQ{8;OO znMU{<9B>%5;*pF;no}%TRFf_zkKHE%1ARFUfxey`^K8aRajrnIYJJCm0X+&r>D@OC z91$P}Jkf#`SPkh4MvUOOkYfyzNgxFsBQpAzNV$I!DFd`3?k*-$8X_PY`;|vAr2u`y zb>XtHD%yEO@4W*62lrs$2;cB-PQ6|rCaQ`hvg#u1kwJ-YYM}0$&I{0jTpr++8&w0O zpowrH@CR;^o9W3SvW7rZL-0We{dh67n+-B|zF2Bh4U3De0TrvUM|>)q2m+{VD2z;5 z40`Tv4Z>w;2`h#50JsL^eHyoWHA)+xZA#0LlP8*e@sxy@w=- ztitAdEY(q7;9w7UvWMSinK_ojVmo9I@bbcpVdT&Nz#jYn-g#=WfFf06k7MFHFI3rJ zm{Z=lKr=JluwFon<>uIw`>vuaZl8O@BLcXs;CZje_FG|uq3H-@L=MGnqA47c_IyJ7 zFRdhxTS1jOZe0vGjx$2rA>F1B;Kw@?oAFuK0T&(?B-PFF=Ew0YMEMuTGl>bSgLZR^ z6+QP&<7TDO^)zhuxu9!7CFxhky7;9X&$!pj_rqWl3U%)M1GciC3Rkl_0=c-F>EHXn zd~??WBr+cSMKxZH(10S_iW$Uz>#eZcCQM$~4t@hXnzC`2TXO=2niIgz3PkJIo&?P_ zgEl{Ai|k+zEk)`;HuyHOpY*@bp(2|zvIaN90;1CW!0NMAc(AOsfUqv(<~aY!2kI$M zEqn!rbYPkgS1ZYua0~!>-@?BPdbp1JO}hLKT44b-(1>iVO+E*r!gBy-v1ZRtxWnik zUIZMJ@i*cL_8Ap{&7u^u^!VtF@S$8YUSpRnWj7oVV|B0RtbAmIMsGNQBxA=g1Yi$|t1JqXQ%R1y5&(Q+MI1yGG7>8?L%Zh2Nne$GB;iX?AGus&>6I-6%YHr%9n4hvMmd>jcBL#Ju z^2xijg^#&`{6IW-K!8C4+FpQ@f4Dhh@%>UXJ0&1REtes8+{*okE@jyW94M-cQY=pa z6rWd7U%y&5?gr`%HNaKlbz!asF))+}zmy6Cc%7+7B->I{jc*6rVe2s+qBFu(2gw!r5g=7k^2d3V#C=8d~nrcY?x52ZU6-} zwjY<-t%sh=s?}hc22Ci2P>|wh+${92e3}3UTFadcgarIX27c zN!St6+08vzVF&10Z0f?2oN}#VaU5EC;qU=sDWJ<>Ud^MWMxvU**4)W#7L23m$N}5A zU)*kfk-R>Ud;?Jdy8-6P;XEsgl;BcY*`$vITF*Jy6&UhS+F5_fLr#lKPdtri57Fjf zZVQd#T$l0Cl+%PKB;Nc6fim;}+VOfv_YtjXVdK8oJ$@V;UvaS#y*w_{3?TMht?=w( zh4)uk$^7!+i>ubOtcQf`fxQy=5Mr6{jOLY<)jG387br7Gzmf9+250~rJO(x!3vX46 zb&6656f~h9)o=(R@$9r(*;WW+h{?eK%Uuu(gaAi%<3mR_-eq8P6S*2-*{08)2k?b& zRU-H>)_+PR_QhV4ZheQKLJsRSe2o5F- z7Z*(^^})L?NYBpS80Tf6@YtLRI$tD>Qzw^1*1uEQ~CdP@*6n}tz!#b>K z_!PK}k4RUGSf0K+pdHgGaAmOUF$S;MlYk|8ZIM&4ayNHAa3~9OI zghv%9#C7?Y&t=(W*@5n9VgJB)KVcYFFeGF>6YT4E1A@RVZYkD*6(1`iAZw4)nc28 zQWZSqSVrkBV!&mA=`dZR!m>@dSy0VR-J<%}%#E^u4YQL0AdYp5n4Eaq@ME>bxGWH0 z*WgVuZfO3IL{SeOUZ%-?>|{4z!5oHhSWpar$iNNqf-&B!w0O zHn@XrzA+8ROoH!8*#<(5)Jl+A10V9xn2?rkXx23A8F?~fzUQS?gHk>qT5G#HDwwSe zGaidx&z(_N@KO}2qgRNdl^^#ptyK=jv9MjpwLMeD#BWhdzyL^?dS~I5^-#AVb%-hm zbEDsnF>xvQn)GXJ1dp05WTqxW5u<4w*;X#M9M!vcFP7D!aOe_?)Nops=|Ve0wjj>r z6asCdhXK8h&a*QBVM|{uP8bL^Ke_=7^EMX{WjaIigf%ef?Cp!gb5W9`Zdg2 zviWtF>ax;dtf7~k3(5gUW$(UnL91xaJ3R;98<+lAEv-o6V;1gcu|ixJ71t*jr)0x+ zy%^^IvUKbEsjX|s*TB~yNB9Xn8{PwQz@u0drf0+2$F{3!uyrLHbF6w$^zD+%mx2UZ z(Zq&;*j{sHr`-1ft3S)3(1T1DqBg)bfF}%ZJg4 z8iOm0$GTB#JS1A1BfcxjHGmQYsBfAT>u+g2PgtNCs0{979HwVZJo0Oki1foS#I>v7 z6VC~~=`0`8_rCCtXrsXmF~v9Opv<;ZZrR8vF#H^r8VQF7e&7X``zyR8017D`JcA)1 zo~wY4EjceXBw==NInm;g_Kgj z`>2S7Jz$u(P0OFE33)V?fLGX!bslc9b$|_waT}MbmFEkV=$*M~4pXwU6*I`wWvjE$ zPw?Wf7>6fD%JrD0fZvTk{*gvFz&61WkayrRDla@?4rTzxPX^$zGJYbb@oRm-DE^1K ziGNbh__j~XcBC`ficvYip@)5oF5hZ`3t;6g)m2{A?1&Ywa1ErB*J!FR3}x@;l68YhSvu2d z2TOkLu-U{M-V1DQa|9Fyr-yw^4GJb`D_bO38{?ptHtWSS&hs@2#ReU6iIpQyY*9={ zI$70j;eW7~&$t1W8B7d8+8bf38xl9gzvUG=Dev*nQm{DO{bL*V08_& z-!@ZS=n?nb=FA7T*O!h6fW%INYwhsCb;-wYG&&G)4l4YL_Ye@!LU7XI;;y4&=2 zF*K|1E6kbjJ4j8kK($8U5_@hT6IiZnZ2`SwesJHFJ+Oldvh#Bx;K9ExR21mfipA?S zAdNd`HQ>v)RXA)Q*dOc71G4=+S~Y=a>zOr*tgYpq2kcY4YMVqivs6HCqF{qU&3Ft% zNlKN<;F`!#d=!QO{<$g=b8X(xfqtcNhtqnsv*A8)S*T|=v-v~_h>4NikyLFfAyV>eV0guN46iZ)ZF6u1l0u>V=0Xr5`Q-2V!*=Z6AVs`zAE(Yrl(e>5i{q}vLVsE9d91n0%lg+5B7Auw;@FzTV%oZDx%a$`bD}BX-I|iOrc_H* z@sap70J+K5$HEEZ1J!!$8^@`>7F@j3CZaEni8BVV&$p*2!mArIBz!Zwd6=5~*V5hB zXT>m6Z#%!*gWroDve!E|5Dkzk1pG1%32VArF1X?>W4!cR|+RDs(FscxfG(W%g z>w@4F%iQdz1-)D8YuU#DP?F3@`y-V={cLD`mL>Y_~-`)`?l*!Dibm zXNx+E6ZXnlT2-8Y@(2sO7VBVUjg3O3G}vF-2_vrZ8m|O7H3!fPn`@Ua75)pXJN|T> ztn~@OzOjD#SyLlla;2ud8qo^Soh!=Lqc)8oceecP;jf=xzaH4lz`a^=*d6JiO`PHi zORweQDr$Ux6!kK>+!_cTmkq|qHZ>Xj34^V^FlLDRSAQYDGFLDl{>U;&9Z!5C0&V@^ zOpCd!m^zGAS=eV&y9Gmb8=WJW4zhX(dN>n23fr0U?>cRqWK%si^DgEjUbG+2|C$Kg zb2lJ)1?pyH2ruAsSve80X`K3goT52WV}NMkO849anc+PI^wrw%c%|JtUw%}#K`V^- z%_#U{y>*;>IlslkpIAceqT(>xQLUnqp6~(KzHQ3TfPY-_17dq0aqs_lhP|@~j@xSY zX&k{^)4d(Vy?$-@UpvZbZ%X3SgDn(5j!{f2h+&ShV+V7<)aJE|9pHDet+P)>Q9;bl zy#8J^WtGM%-B!DE7ggK`RBBaFn-$TSua|9YCe_U!6%#h6|LaQim)A<|^Ts9pxd4Z0 zHq&aSrJQiqe-&BT1`uv@7hXp1H};Od)?$3#PX#*OZ!Ld5=W~DGTF%e??bVz{Go7uZ zFC3Q2fRB;)_E==L@8}PKza6(wjm+`^KK>EPNar?#UQ|!-Zh>GATXeb zbo_aX-r;zSX~F{*+`^n5OO(_7Y)_`~c};j@96|Wv3GF+uW(*AbY3bWr#T@ZsMPBVh ze_jj4EeS~6nt6wcj)Q6`y#pjk9sH#k|59d&e5z_~Xra8d53>_{82O&GZkMhx}OO1MmNH zjmj@O$Ty(Rr&-%+8u2NgN?HoKQu(LMBfr-%o{KADHJ)9#3WchVf!mPdHLdH}9e_4F zy_d;3``pn;q@Dlmuq!uK&-;)vv$J0?{%XaF3m~-}GWq45+!DZC2836!@}t<#VlEu! z1RDi*sJZK~wL0%1R=+%%DZN^<15}_)R-c^MPu@@_-lu=k{nbx`r7SC`hFIa-%{gAl zkTKTEnzC-8O*TB85iYZOcB)&g4g!1Yxe&@bhaDWOrdW~Q14bwXn%#nUi1A~!r)A;R zh;kL%(Q_$|#X&X=108iEB-R3(GsQExe9k|nGyW*Lw%hM06^ri?7>ZO^r z03ZX!O2lM@oy#ggX0UeC<6|EZ@Z;dscyzI~wjBTk?1=p|Y4!31@GF)GN0VO+AWpJ! zmCK}DfLq-8bbbR1o{xElWxze{P*^^l0JaGk@31%MpYbh>Z!@F6t8Hu8)wXsrAAiQl z*nzE`JEiikI@<8n(eC&-rug13`Tc@pzarP442U@lW$y-b)cytRitRJ4?_q(4(~9+6 z_I=jftd~S~_3+8=xHalmP(+`DDcvUr;!(5J!Ci zkCo8V@e}%4pleU*+AQN&GIIy8QidI}&jM=0Gw|z`1zNqS1r;Ti>RFeCb}cAM=QOsZO)oxrIO`XV{$nTooz6q~Sam z9uKzO%n(41curFU0u?}YZ-=oPxFzqkDG*xXtfUG~z2cC%Sg+cgJ2Lk2nV>tp6NMiz zHtjsWfMEx~=dpph?&!L)iW|#ccF#!~cx7B%(p=gVnvoC7dAF50MFY(i={KkAD50Fg z#Y7jDEm&WXX>!~KUKOL^9Er=MIOe$lkPK~BGZ@WSog;60ghB+TKVA1u4rI%%*c`Y9 zHgMg6>$VpJ{NB=~G)zX^E$a2tX7AWUoQdWHcx*jB8~dJ)hkAk$Hv!Xx>jDJ6k(KYR zXa1wejm6~sGsrk>ULD6J>iT-FeS4qSa+U=OicUWjwU=K5nx0^BF&v`qDG+CprP}oV z)hr&tgcX+Gkna5zwb)*5zml1=mk(U_0>lANfiR%fPDuk9Pb-cVaQ)Pt9v5PoQQs@s zr+V2f%I?&iwNB0Q;R}v>?&e9;za!)LBKu&^9kSYF)EEh%A3Ja_3$-9?{bz<69La%* zj;Co_3lMO~sxTXQC&S4%u*I6kS2M|49Me*4ys>C?jdaOfpK$Lo)pJ*VvELS17F&NR zW_Y#%Gzp48^itoJoJIW?wgM1%<2V|lAh)AZB{%by^2IKZc0?f7CFKusLYjKRtbnwTCHTEMLnPM3iDB zd9_!efBi;QKZ7QVL02&DRc$+ik1E-Qpu6K8AZSR@qv~Iv-yhX)zf`{oMIIa%);Jq% zF}lrz>!@%0vaLq5pZ71zo+CcYtP7utAF0UkIoeJgB6PR`3w-VXPKoW3FW_mcJvLQi zUV9HR8e+#-pgh<|`?s9+`0h?g>`;B#+Ytiv4V2=PJ84T`84pXq@agk4Mf(7Ff&<`o z5$y=oR#vF;Wj?&Y3>+l_xpf9s0f;+H^K#I4l(l}>nXn5ub?ZTFbGV~5V~&Q5rsJ9|e?8!FqO$|B{JQ|v zt{OyYb-boSAHdnuMr=5DfTflTXLGLI6^po3R0Y0hB{a~$aWfVOUS@y*p?qHaU4>|x zUbNI6oYhZLOSMDYD#YF$mGr9&rGoo4aQB#3Q}jy*DA{h~lEnjvYy;(Rkn&IUnI0L< zJnN9na61lR1ju!6^QWoB^k8e|r8A_&Ni1mp?@3~C&g8h%Wx?SP0uJXO+hA*1sB`7g zl9$?poc8EN$E{q>Aeu+U^w}7;$7Jn5I}3oH0gu@ujNJh4-PZG1y4|$sZFeoQL{ zZtTH}@U-fGXnX2fHn2Ul?lASLpJypWgWL_6#7^yDn{d? zY>q`5p*oH8cj-!Y`kL`?ES}yTi!}Byu&?;WnXl{k`XO1LWvSBubWM8qMTl zYC9g>I36E{#&R2|v@*yVL+t@r{k3(%a9(z5X6oQQ9M1(xf+Jc2QWB8rIg#vYEkJ3k z(vv%K_O|lmmVa6S>@bExK5-SSZRBY{yr9j?Y8T`>hCSqU+AIh;n3gMAfsHnlA*p-q zY6xwZBq=yo;a24%($ z85pI2h+oc@lQNrSKT7|Z7kZn70RxRa0w{M&HOIL}bUd#Whj`ZCquruxqMk!CmM;8! zJy`3C{hGe&2}I4@mx=iot$amTG9_wW@7ebe$}5x$J`k_Bu25MM`!x zx*bdp&vbJqQQ4lu7ONCt6nT&CjN@zMYl6$*_>XWNemDFf&i|G6Ot7%fd^wTtH-Q^D2#|q?<&+S{ZL@q>Bw2ZEwnHdU!+V8H}Wv(n2 zH2m%H1}vk1Bb|ndCZ59Bwd3=wRqQ?`6c5ai+)04k5sfkd^n!uTyL|B%EMW$_=o_J< zmV(<6y+dv1IKv|nEDlHB8G~$f$zf6zx@Yjb?)gOAhvTkaXRWr-oHS|J!z!UY8_}kb zJz)hiJP3~Uxt@7Gy zM@HDIjYjMk_3k9QSb&6pgrivilXeR*RuvTDWIpF1mI|}8huLB(5S6^?r>4KymWFO) z9drGezjM6fOuNl5vT)!mi<(u$ss*z*IXHhg*{>c>$cK}|ft6r)@$0?k&O$WiVbkQ- zm27hA(&z(+aF4cuvUWg$VxgKvX1mF8H)`acCPyw8P1nrxNa?bjy4X%_)o6hvIlFRK z&fW=80%S$oU7O>G6VhMojcn%*%w65=2fX%}PF&_C79oOX@c5DnhaKSD-~?Rff-kjn zH#MMGx3U(T_l)rA3-PnmEwlq~XxPjNsS-UN&j5!#8x7W{!QCz9x0K3$SiIipn2|bC zO4eoBpPJuY$_XD;l9@%$qZn} z{5HpMS*CgpMb!}wdv;-Wf|o-atg}LoBZvqg01avcfuyWPTglLBxeo!p!*p(I>RaDP zv0z`Vk73#2K`8Z}Z*Vzj^%+jq+95fBH@*@9nC`k4SS_XuBm zLG4qM&53fu%}kw9t(+6F+l5U%cBZUei3cWoDR*VneO{CUyMGpR#e~RY&G#?hsbj}jqY{; z$FCX8KLa@8E+Hy_HAmk%m(MA!mXztDxQ*l7qk|me0iEqe5qAqFNMXPbP5}9-V%yhygz_MR7iJVvIDuj|VTL5+DB6r-;Q{h;o8h+>tYSq#=oh8} zq*a46U4v=*+Z~kmy&G#Q|9N+YGCq&}lR=p5Xay(P#y!;<>vuS6(}WmiaoPpwaNK;gl@S?h zy?1O%hI&_{W)Gre{+7UfcU|eu@`6aR!y8;-Pj~s!7`t?8?hNowTED-FTGuh+&kHPB zy>}&-$vQLP)eQe-)!|o-@fAcFD1o9w0V8{JXEaLGcz~L2$4YU-IDAX-tygQ8T#9Wk z&JuAl4;o&=+QUAaXMQ&$N8J`gL}u9FjpH{Uc+MzzOU^~!BklP#xWT2i7-E->EC{WB))I$=Zn!zq@y)xS*% z!_nZB53G^d!;Njg2j`l5KEX5Vt>3~FiZu*|O$*cBZ#bCS2bYp?3=?g|sh&WZd^;N~ z3~PL{f!Y&j$!)$Ci8{Js8PIKKu9!7m8{kkQ?J-8}wVF6tIDq*I4oY&I|3*)?M%kC< zOeEOP)B-v55&+GjrEdU;Lvn*0C^%#bmklpx&)DkXIBYoMUS}`)LJr~w4G>s zM$!X5TxX2-+1|GZF6?|1L8$Kqv{0=T)|gDUDJDpK}<-X2ZjWFetxxa3QCk$@Mvo!i#hgwQ+g z&Vh1Ht!!oe>3J!*Tf(3p?1qf&PLtyLrt6DlU&z zY&uQBMKoDv-ecY8p6}(TgLyv3C3>@MWyjsd&xkKS-3AE%pd~FvOGWPUz8&&)0>s6= zZCCr_d^^1VYB0TM+up-YaNp4hivb#tI^-VAkwUVh!jK#i9UVtEUdQiVIFQRBK`7HY zz)kkBce|AV|0mDykW%j!aQI%H8{r7IzJ10Pac6{>7Pi^b=(JgqdhB`97C1X%(D7Af zl+M?Q=;q0>K6kRh=fqvsT>;lI^2?44f%ssfOwWa*O4l7E=Op*bv5z>(=}|DDFJ~`Q zpSkRDU|2J&xG-Rr%yn6+2lwbc%CW-kv;d@9!&A?F7=&2FU>HUuS*z2BaXE(z+ZI2H zirk!LW;Mjq>?k@e+jq+@p}U=o5Wm6ykoY|mq}kfj9q!t!r4MG0>@)8>9^)KRyMiMW z!iHVvDvs!39M>Kl_c*=Bng%R2Zvn~d6x6%Nz?QU6O>tsOwYbySYtWPfmzveTJE>etbN!gsQelccG~r(uWLV3#;o|xe*m2MI_M$&H1~wV zhBzMQc8cL2y`9DZZ6Pqc7xv&P9%4h0Q2K6MM`uwjTV(HnJRO+3vtp3qo{(*i7E*hQ zvit7+Y(T-dXQaGf*E%joBbH%f70z4Jyd1##9H#}^$j7^zgKQ*}n6`~RqGM*hR`lgD zP-lqRNCy{NW4cr07^Ixo&qFhYJm)waZ@yNHf45_Xd#q~H6G*BqE5ST1#{hLJ=lB`E zf5=tlU(@%;c%rEdhb?Lg4fCN|mKE*MFLoV1H*Dos|H5cnUK$RP-`&F;k1_$=dT=?z z@z_qOyqx3RHB^*5E0_fRKm z2%I1WBsM1Du~-LoVZ~in_&Q->2*Ki|7kNGSU`Lks6yn*(Q2_-7yW;FuP?#WW3a z2sm4+?Dy7QkB7TGw9C?_cV}hdYR)^xavSA&_o)$8&xrXOR%9b-XFA}#Cw}CFRb>YX z;4Oe5>?_#)49+&kvWlraN(rkXFiiL=o6>`MU5{QiKExMg_GOL zo;>E+0A-(^0M|UdVs)8koAyw#TG#TpF;ry9(X1-Qvsleh4h) z@iFqm%cFz1H9FV3%!AInk0~;Dd2M%7Jr@V^@w^^Oa5`uO45u^8D`OptGmNY?+6|TY zJ3k=Ut{bhLzC%W#k^ub!2*aXIXN~Hq&0bkX*0QHGScSfvuy{CV1m$?m8#p|P7v+FX z&H+?}aPRTw->`7tg)tQ?{GiF+@`2#kms{KEyJUDw`XHnLlj;Hf(fNW1qW#f}y5 z;4#}B9T9nW6rNSEz%8dI^<9_$IJ^sSue+V8e}`oaM?JluBL@J0P0+bLzyj3(2_2w8 z&+e=HoR8))B5*6jwY;7gq{VplL`W`YItRpU%0psXzSBhFd)0I;=Z!c_qc@X84oS8P zWV7|hv%cQ%$Q^&#_KuRDp#d#ri4;+TcJzUVLF;JF=k=+5Bz2{SzdvPkT zM~3m)z~?=OhYbMCJlL#)mA6K#rz5TCq|;(}P%;bmj>++e4rrc6b*&OOg9CTID5sHe z{zL@S9($8=_dSo>F8j1IzJkp*?(Fz#!)=zu8iMfHGs~5;W4X2qcfjL!PEC8)53B+5 zI(OadFBbXL$4=9>FZ}G6PCz@!*q(Oe1UuKs9l=uEQPGF>+)jmB=KuA?RPAQu@ zjNf4bHa(q3685F!QBA}2fqkmU!;_rg8NhTGKW>OTm#ppw781`N_r{-^!s<|i=U~rK zzj8&VX{l|XrJ5Ye$m;((A42k;zkrYxlf{|HSm@J3dFs1+{f>Q#(l7%tb_YlIBrJTD z)tDF^a2^1z+uZtktn!Jgu_bZir=i1jz>$Lj%sU%`#e-Yfm9GD<7I;b{QsrRgVVaJ=Ys#7ScqZUbvYIs zA!W*GbXu8}8IO~OwAdhbXmH<0Q0zm`fH6@UybnDyz6iNK9y^fBE*agH-$HWR!Ma@} zI5(bRey)mD!wLdTPN)>#(phKS@vWX6l#g$ko2T5B9pA6eOT4Aju-GW-iWn^N(6a30 zHT{w2mtifwbK{U^T=QWe1hgzHg~nvwWq@y&}Fj78+n@0ZimjaPxQPmc#!4*7~U z$END6>C3JqM`J?s1i+`$Z*y}_%dnLI-rvUv2AY zUIL3yj&^y%@f{=(mIfk}0hneKYkD|(bd2H*QBoRr7|9&w?XHz4p#>^-BCGZe>Bm8M;&IwRm*E+ZhsUDEd^$78fqor=z0Xd- zc01(m^iUSbQnb(%Mr=x28bg=_&Y3(jzPnX<;&{!$R z=5d6rsoe&u)n(b1We2FX0J-t>HjJdR!Lswon$i01kvuc(E`rDMhPDf&?&W!0yM57< znFqq{IA2rmeV^ZZI@r)SS={Ho;4cMN#ftgs+{nqZqJTm-&gboi6X-?ZMg@V}#&#{q zKq05+$w{>L0f@iP7&Om}Ssl)b1HJ*vur2dFoKfWDG_ADF7++73zz(*ce~3S8&&pKlmxw0j9sv(GHXULHRMFcXnT zlJciVa~k${10#SC)qI*gE5@-JmI0B&5#ib{`*3%N#S`IbDnFlM*h;va?3LM{^7A1c zSm%My9x&+0it+rk=s1{t?0fZqQjz21=xqmmVcso->6SryQoxtlezeZEc8m*u=P^?b zvBkPvM#zj!NNT<@sDiM^e13ePW?%smoMPoUs7olU}_fRvg$`qTa7+}v&j?Z!X%eGFD(Pl>ja)L9%B z!(!%w$;r#fisn{qGjU`T&hpHY&n@3Wa$Fc34~xT~0}8BQo2G9r zM_Tj=%19p3Yskpst)Y$FqrxNzZ~b@-!B{=-A@Dxx)o#AB5dL-pyz~UO4@avYD2K;Ru(kHT;{&i$hAy19(RU-C z2R<%S${5LR>JoPVNCD~pALnR}IS88P9smFU24YJ`L;w%~5C9OEGN0)H000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2jv177ds!#<6F4^01?hfL_t(o!&R7hlvU-K?tkC6 zhcgyX6q5{E%z~nfB8Wu6qzS=poa2~iYqB)P8|~I^uSstDn%k?#bvx;FOlxkUpbSL; zihvpu5!w`jAafN36!TO?4X36v?X&lD|2PFJ{jIgvKI`ngzWwayeV%u}?`u#5VMxqz zDX4@o4lafuTfj@k5KzkYkV^XW4{{95v@^1^8^6Bkxij1T>t`1m4v;y0irmF!$Yrs) z60x{P)re7~MvY+5^r?6g$20i0+ip7(k8i!ye*hhc6rFhBdV~Po0V7f#g#xszh)Md8 z3rWTu3}K11b?E8MkxnHj2tpI#U~vJrSY(Lr<8-uUGd??SG?oCOP6IAbc4 ztFLD4$dNdT@FXO0{PZafpFPXwonP?Tw$H%x;NH8bUVNvCj~hq3b?Nmy++>2HfSw}O zTD+7?rVvmW^XSM1kd!dR60~+PM513HDkMCGIGGkEw6}7@u08O*7scReO?c?LTD9x2 zS|wfVk#_Gqq|Bu*MWJ-5vqSrv8q`thRY9S)eet<^BB@={>svn8s7JpmMvfQH{6Mq! zH!!0kL$aflqymx>v9Lr+f=m|#5h)3qjRJhnp{jocQ2_`cpXp>!P++R>)4YDerTu?# zmnOEgaA@y-8kYTv#PQQSwe&HryJ{rA_{V>xfBy=ee(GsH{dfxv`|G*qFYY3r>*Yj! zBjW}S-D?q=CuG zL+3f-L4lM+OoBoPz63!5o6S)flo(MgFyZ)dc;qh?zvIuf`}jE>Z#t@*=iVq|P|~1* z$+$+07^Sn#t@_X3EK{mqmB7`8weM;DiZ$x*#+7z_-8$!H_2zo?;{SX}_^xoR!0NX7 z3w5gDgc{GcEB@8R;?c)6z3C7W@*NB+<}tllD3r<|$rbS>5)vcB0@pP(!oyFKlF7sV}K z)yYDn_dfVQI4G7taf4hCE_(LIFX%!(qfwK_3y{UgI94_5)@#|C8sS*sd%`ILeQWuf zI(h1t23DpO^NnJ$GRSz$>f?_;*13F1-24^s+zYzl;yFet!uDkQ7>q=f#MS4|Qnh^f zXNj|58_t9i|FnG{lK%+^~`AYHimGKX_gaC<%&#JcCx%uF>-K zYen2EgEUqij;dlQU8p~%%`0oYZ(MI?~vnWDMQ+z+&yH|3aO)Zf)7{u^#=id$nctW}Vr8 zOfit(2QCgWpm%Ck=&jmSWpLJ$!Bq^afhM6l=PXd+V!M9v&;OzwJGQH!KpQ{Ztflua zl8K@Elc)9bKYS)`n5G$xjSTH-C#gK7RA5|d3+DTOqnS@VtCld(?F(;K%tJ9yf5*|H zTfeF;8$VNTOCV*W16%j##sBeFnm>P@l9fr}BNI1zr)Gs#)vQ)Bo>0n5Xn5ri-ML_~ zUj5sj=<`qNq)<{QEqimhCQX_ot8&!As zycm47W*s}okhUhw?A~T}y!ubNp{2y$H~x(&W5#jfbQ4(@5X4I`$gd)ZTuxlN$OGSh zlJ{$uffJD!*qOBp&b?14-y4a6{YA=_uRF*~C4{xY^YrHG75eR}<-#qe7%ygJK>bs3Ih0vi zym+yKu%xQ1h6>kJER|Lw7FWE_a35{>NE`MY5K|`T?)on#TJ5RdNWRGY>67`7*MCJU zIRJSv5YQVC0wE!P{?Jlt-dhdXPKd{eR~ZD2i}h7s((%SfV~AQ|W%}*|UeC zLx<8YT>+6WMmRBxvETp=yT4>c^;p^(k6^vtJfnvXr}69wLdPW}ghBzr62@9eim0A2 zj<%K-ip2tg{SN~IExs5E$%Gguz{miU znKNLF!Eu}`|6K;ipBTjRyemKfjAIFXm&kJ|5fOP%458>6u)+ciPxaHGeS7s+|N9k@ zc7!d<#&JA(UQE{U^zg%vs-vY{zVDaItr$us$0Io@#4rRa;vt&-2PvjhPM!gYm@=*?69jjarz8$W7vU{C$RU_NoGyI8A{+7D3u~G zfQdlj^oi3Tm^pPuIajEh!Xo-IN}n+^E!Xb+K|m}PW8uPuY}&L53`7bD!U6!Pc#1m~Eus_HzGoNdIWwEAJAK+< zh7D!?)-PDNXbCYtO>b`wESQ*s?|76{qIT_CZn=hRO)XkYp2G8?&=%I(m=ku&tvj*c?NI2kv^&C3#IUaoa8CLyq2c%8fGXG9WKq?kOBl9IJFJrPd2=`sph_k>6LDRHS2?H*c=)zyE%{^2#gP zyLYel?c1jx{_uyo=bn3X(@i%i7K?%b)at}bP>SsgfVK%JePy1e%8-K*DLdrhyt`l`CSyESIa7$p)3 zIkpTe?OLU z1={$B->bDJt3cAOy?gY7XTPVpGiRz_x1D_5$frbfwRQi()DLxv2|(xprF z;~)Q6b#--;q(Y&fl`B_j!h{Jjpp;Xt1OIHsd^L9jy6)K*#7i$~QtMd;WSfCvp5fUn zv+Iw*%(?pIy5H&Gj(r+c(N7QEwM4u3f1#WL)qJ#3cRuo<{$K5CHC;Tb{;8z=zLwK* z$}F#5y;`eQt-6w=jWJh3``BZTsjI6?FTeb^E%yq=VDbju1+01t~J|s zifcydrepi5>NrDMSwIn$L6OPlFHrgO*Tm?_I@y+0dvk|WDr&{*Wx96yB#}T=_#*A< zVt1SVVsr>Km2Kv{4kY;PwMRbuY>^YH9niK!G?7@)!3kvV^on&3J<-tZlzY$u8{%7tt$ii(cizS)C!jwZaY~Ua@9;(-d&6}>wYgW8ptJSMksK4VW z1^WKuPf3!#ao1h)lPMXj2FEM4_|~uK@V>*UZ*J4TyYCkF-K853?4r8uJXcFlESABA z0w-4<9JvxU%tFt3CaJ)*BZuJIe<>zT(|>-jO*u(#zr9Z5$6YUo31Yfw_B{3U=JeBl z`Ug=F*RNME)4F%p$_0J<-uo4GW%ZL+{+GZNcp5$WI{o^M)yhly?WRw~lcaH39F7Dw6iy`EQ20TKWLO~8)6STDhB@uc40`zJ85<`|c_&dSIzeojGN~F8uQ3^#fYm_^~P(O-f@v(`3wW2BINVsfl*P!B`68}NH~EYAJJdsaL0;y zDxw?%yIPpidVzTd58*ubw_?y3-SpIpTK4%NHA=b=N&7$Br_9l_%H;|=-f~`bNA{^X z>`|{meX@I}GLh6AN-MVS)y(g|Bt}gTFTAMP_4^rn{y3>jb9wArD1geWxqTqLP?%V+ zs7OLFou!%SkMLa}EFR7r15#0r@=`GN;ZP%r??K=nc z9H^)D*bz)2pwQV4p-2x*<5X7CZ`^2{3Ds0Dy#1Ur>DrMUl>_NWR?wYH(^eAJP2*xI oWJ}njivhv_;vN*cp&|kQA9d-_CoL3KaR2}S07*qoM6N<$f>3pOBLDyZ diff --git a/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/user.png b/rooter/0optionalapps/ext-rspeedtest/files/www/luci-static/resources/img/user.png deleted file mode 100644 index a557423916997d8147307314222fb64bfd32da97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15663 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 z z!C>^kobW3Ye&N+fL_!3}Sw@KZU>RL!+J#SfBK%dtAv(bS^@trULRbQ)IK$`k-ty%# zV0n)=ME=TIgoJ~f1RHdS>>QGS=r2N?x0Q?t0d9b5LS}g&99RPDLDT+Wk1vo9x$+#f zGm#tsM!uQ=gA_VtsFK|Ddn;3w*|MCOV7hK0eSg(W-k-3Coz zgOfW9l4lJCm*HVHNHkBTSp|upf}tLUSG3IxppF`g!QL&oBoQ~*eUh2%|;L_x~gJqN{x)FA#zCa4I9L+E?7La5x- zDzB;1F^N6dh7A=@Ise;mufmXt7C^_~X%VT1K;niUmO{X(6IUcL68|9n!CE*2hW0kK zTWIjat9sc&{Sg%&@^w5jVL|!={&09DE?+c{_g2V-tO9Vr_{RE72`i`(7#JWnF$)dC z@H0ACP9(qj&(uGLB`pHdJfPF+AOP!8eV{;|m~t@JtJFZSsZh3VaCw3BH=au( zLrW)Ir~xT)Ug@$wzbJ78_mvBtkBqagC=~P|1`cR4K;}}C9Hl0Vc|B_ zW^W>uH&hAl8fcQaID-aiNgM=L=kKNT#2|_U*DLE{ZBVwjG+qHV@skQMS(i=n6Ac{% zn<~Q8gM~oEiFSz;lq_^t;bMg5nptlksFsA5S9u#;V7wj=fFlNQ2reeFEMNkt#gMBk z#7kLVI;Fe-F+!wC_)eT+9v~Kr4OwUG*Hb+RDQ0ORaIyX;xy2x1OoFfwXbAuS2a!=3 zN)213rHt>G@b~lo1bKXQE@`i10F>c&QbI%G0tP=?0pxi2x_rb2`?U$Y^ z5&Fa)k&VLJAeJ^^3d_%WvV>A9S-XuM`4C_)i3T9Z_38*O)foS_MgTQ%! z))6w`5u^z`^Up_Bs~(cFM|DXeP+Rc$)~C%?3k&K%kR1V^%7-q94$`X+hge}b)Fg2Q z@OUqheP|16*axnB&WLRm4&IGLRefOa1o4TL6GqB@$0q>v>BGpnSsv=faO zYi($@vo>6`&XHV$50th;grp8Geq9-4^QbSPBND7J|JZ$+$`J5wQj^Z|Qr@a?W6Y zdQ!BC25r@PmhXs=BR~V1(C|m9YNAF+9yBIO53S4;WQ-V;%o1S;0H`9x-86A%JTw4U zgsesGYS(h^<}aE?B>4^Qw*OOztO=GfNoFfk{(=9$BUx6U6o88S%<}u7W@Sf|vArLi^Xv{hAA@*C-+m zhKSU5fW6Y#(!MAJp1aR5JrRaNnN7$F#;qwSBT0|L#%x+}Yoi*xu!(Gi7F2!HMjfjb z^DES5C=%Dj9QdzZKSz^R#RTXSCVq-@s6!5F$vbE>X5fP*+ zsQ^fUV!+@+p2DgJOAY*FMr4GKb|02XODMgEB>}lXAPiJG7D**O1cV0zRLVPYnB+17 zo$2!0(A~4Rtx78!<(R_ot<3Jc!$Y^s)sV9 zvz#!5W!M17*#^$!4qXu^xFb{&cC)I|82jegu?yPX*@QFEgOUcCL6IoZPfQvKM{bjz z_}gvR%*qtF#j_!FF?~#Cyaat^D0}(62(GK9vfZCG0-)C)Wjf()K&IozhqBwMQ%Rkb zWOmDvB#4O+&p6O;8!o7j84$C=6`Tyf8(z^jGk;#MR8q{McTduH-Hl1)_2{*gy0D>$ zp`;Q%Mnbht)zkoT)on;lWRIb~+HH?0b8w*?SntsLYdw+3pHiQV>G)`g)+M5OL1rD3T}F zsOAEos2gGdp9D+%v}Ef~nHfM`a7G5$bgaDVh3F$u4M9#5AXgaPY<%o#~GnON3N z+{ED$**6^iyiFQcMusp4@#3o{bit~DSem9h)efch%^L}FAzXrXsfr}&O2|1@hy~LdP~fWhA@MYl`gsOD zhpOgLWq<7DlQR%CBZm&VHW*o7?1+oRaAS#U?qzVz$i#Fx0L(ag+K@3Aoz6Q3c#gr& zw;yeZVl53S=tcK{`d+TD=V zd38WitYL~Suv!w)VBAI}*m1CpWcE}S4v7mtwXCE`JY;BY`Z6W+l@Z0SJT@f~L>)kc_A7{8d3umEd;TX-Mp3P)M{Nsa z)Gh%DE`iLO+#UIK)2dj-dVmD^Q*&N@AS2C!mGDdLS<(b!A_1jBg+^+K%R{TmI73=l z1ZwIr8N#}!m*6B421~`gGH7;yK2;1Kdd3rK;JGg@yFFZNf5AmQ7qnTe%kH`omyJJ{ z-K_yKsH><>xQ6nPPDL#_ueP(PdyThmtuD^3y%M!DY(NYVFJG@F049X=Q!5S`N}S+_ zRM)~Ch2y^ZPg8M|MF>%SWp+u+cvRlYqh~cNsw~um#%9`wElF(4TPA^nMF47XKFSoF3rNFF#94iMHcwj}v+BiI}PHu7L=^K*6WlDAl4>!yML^LbK-<%4WqU(xkn^hXZM~CeAr;AAW@5ai1*Y+0YRD7FUYl}V zNqnNWE|CQ6;Cd;PQYxIq@}8@ z+r4j8;im&jEZj0RKvV^r$p@w~-!?;VgAw2TPzL0P4Ql{4#|Ve=H~;pG*HZUf;Rk>& zIf8b}NyVH>5(CV90P1b!{Qn@G^!FO5DIb{k$P(@xe(*|mn z462S*S69p+w~iPidi8gKRahFN?@glLE4G4_-tO$~m}Phn4@HK+TtoYLE`cdx$4xSR zdmW~L>E*l*8ttb{85-+=dRA{;6ds+cZ4lVW%L}3@T}M-p+S>D8;2AzGKL8P*BGHJ< z=ccpWr);3yrCzveID1BP4L{Xx&u@+lN{3P<27nL46!74zp!S48&}D%foZ7uFWvP#w z6kJ3;e$-ALuxmX|Z6Ar5TiOq5Qf?jF4ic-A54=;K>^(_kz(uYgHq^v~j#oF=Mr&lR z&4}z^JNe+nDk4Q$ZfyWyAIS=$7tr79Rg)p$#Rc>IQL!WhSd)n0b~>gO3lZYF;v{g7 z#U44vjBbA|qe*Q)zz0z_pyHLLy3X*p2#cua0k!Vr#V7xO2E{I!Spcd(!)M_msP(j!McpZ=*R@(gIRF?qqT_uhA6-g1JC;-&b zl>Cos<=#9Mz}&G6C}l)QBGL|!z7$+N)mQp~=Cr5mv;h@~e|#2Bed`(nXzFSEuktLL z%i19JlW-o;h2%*@BbP{Ab>krq%t>rc6sm#haOl`Tm0jzE8t(Y1iUzX~A3SLEg665zQb`OI_=8O;3}ThV2PXhi^aZIvdI>C8^s;T5PMvc0TAy)xrS z?TyGaz=DW~Tp!Vru-M~h`?07-fC$>^R|S;u&8{F{aKFetgjyt5tF|Dt&6)?QYpadS zLS`CO&kQJ@vlQAWhNzv%0osu@$;rJ{v=VfSHwDf3>~AsCybM*>Ucpy)i7G&2@w0Rf z(IJBf=BQ;DcHG*G*BDiI4GFQO9wEqFeWDUq#H)@$2&k?d#oMeGYF%Lyz;V}fo!Ufh zRWlj?ZM`uAdx-S{_m$2Z0bdbPQFkM@ZX&}Y39HtIb_)K#G!^sv{6TZkfOl2c(Ft7hl~r_w@naTIjPAX z<+Ywx7yhQFYyfn|HBFhs}93Y0^_WVOk;_gvPp zwpN}`24NW<Jq5KSLL&HDX^8$dK?K71B00Ta}8t2GGdBef`26~ka&^?V8miOCvaFR*w;bqa4J&)1Nm z10l?ck-2zT9xSxfdAAers4oIaC%p1)onIiz)O}c)`14wm za_>wH4ni&1rN`^RQY1EdD@s+$C#xY2FbeW=^HI8vx@G=z{^t+GOq}LlC-=}+v4VT( zb>hOd=83E!v1G={KOL6SIV}D;UzD3`YT{rOk~XJ{4Ivy9iH{l*(b@umJ1`Jj;~gYg zr2M@25S=F>JjAx(j|*FkOG$mq(kV+=E`Q4?cPDowTGVmmA${b8eKV;}?<(QRM2;;% z53i9Hhebxn?^hg8R)oA=(xDrJQeaRTv8cp&-AC)02c?| zUE71aLpur{l`&rTF-D_zl3A^9XHo+6VyF4RFT z-=#_cS%7#(oNB-;Hg_wJp(ZZ!@A+(07R%KxZm;T?1CLlgxX^)wRkbb8GxBiSlPK6M z1ZNo`cyd|mg zyS_e49#bg@KuV~CX;K<0ix=b|H#=2_8TLruX6LAC&-ZGKV>F%%K%r`A8`|kUa9Rh= z@H;xLiKm01pVtk_60As8D;L(TdLr2AY!^~Vbu}KPKV;h4SY@$EIAjo}tD1IA;bfIo zi6jee?^S$Jje+56T+ksDwQ~|3IF$HKy!H(5s8>f|In_O*v%frxqMy&JAdxP?cvY!w zs@$lF`E{QPHVoU%XOR2qJi^j&1>`%Do?${>5dj2dfJ|33zCVSeo`^jhC<Wd{9yH0jge#H~Upe-4KvN!~FS3*i#0aTI_Z%>ABDfW^F zC6yo26m7!(D0LkyKl(Su0V+@RX!XP832$xl4(1f_+dqPCpDj-djMTSCG)dD%n%PKP&5ST=bKf|F} zKw2$~dTd_5B7;SPpqF8;7}c`QM+ETb7z{9UEB~CWHBg~$_#7f~Y1Mc5au(85;F6{` zyhqbsH*Cl*VNmApfM9mWdxxX zPK|{l;_*pAw@hDJKrWOk5GzTC^swhLX}~)RpKDe(*id^1j!Wmhe0=>JO-CbDH7)75 zrc-P|Ym52ruX9KT-wC#(0~;+#o|%g7I{%9O1s1x;%PqKaVJf1$YuOHuEW@H6S{-NA z!B@4a0svQK46+i!2Aeu6Lba=1k--a>Q>8aRQ*s(=o9Y-ppqxw)8I`rxo8$n&kTO%} zT%=}IKl6bh803A`JpoSud~I!T${IW!oXd?5suS}?Eb3i#2cRu>W- zNMS_DSyr}g<-2^eSKll|jhyQ>@OUR6?U|R2zSikg0uDepbNy_)oTOt*CBw8!=h-s+ zwzHSWn(Fj?eJ1MdQWqow2Gi{ckr%R4{eOtvRa6c1D%a-XlFngG^>%0ryuV66ii$wb zMQw08f;82vy+xWj#wWhi_fte2RGdX!R#7c68L_DY2TUVIafm}xxNqwZE&8>HsI9c@ zw;TTP#&dH^>PxL<4gK!alLFumwU6Uj($p#Hf!e>wLlv)C2pKmPTgNn-$}>nX9XV0q zhMSV8s|}|ts#Psy+Lq|@QLw-ENsPqE<@Rr%Jqc^2jI@nhs``ICT=3U|W+C(&Vidm4 z#2J|ncHlKkH5G&^831Puj4W_;bP6=S;mx$vT>lW=MeXek(zcJ7)R(HA)uGKtOzVp1 zqJja@`4*k@Vkt)?wTQjblO?RumI^aUbFa8QxsZzlW;n6Zr_nD z6aaGzxq{1GC6r@$!(r9!cXXL>Br;knaUy<)dMknjEM(Q;VZ!Ha?MAOdouF64+!VF) zR&{A};TW7Kbo4&8H3Kkd$$`Rn#}IcUbq*2eI-p2gVu^@F(9%@dM%-=Rq$Ju}ZmSB1 zD8rm8qTm)}DQJ(xd`BsP-qN5huWF7?x|FE%>2bYXZt_>f(5~-^z|u@pj|-OI!1~HK z9qGbBtIc0qhD+brL1ct?GF9icl>A-74s8oXJe^I5LOVjh1G=jb^r|;xuYFC2xiD4X zwdE}x9>*hj9RQnKmtn?72SnRm?m$5Ad_#=W>pTsPCBDN8Iu0idpbj>aunt=!=B23q ztn=Z}xw=FY9lI_2|g1`u)yx z|6CWGjY^6d*I*%-4@i9J6fiTbZu_v&ps1iD8|J)U4trWKpy$ak&9T zpV`&%7Z`{X*5Qv_s=C2neO?AxWgl*>uLHoItDfl7+a3Ysc|kR9yhqd*NoYG30RY)) zYZR0qqN3VQA&c9KV~L~{!NaRu zk)Uh=5u$cU?bU$hnng8YL{-$GA0dhivtpcy(=K9d=GWpzBpwJF3@~?KP)n~7CJZ&u z8X2tbpsb;m@WH_3UmgvgUDqlNJXw>ETO&vqrQH} zsV=j(udAa?v-%`WrCzeFPRJ+*kpNd`BUt=>SqDq{c5G{z&9$H}B^q0uO;>#o*h`q7 zc>LBFVUp%WTu8K~^C}`o!Z^RScx_DOUT*vP;gq0N{#569 zwMC>NlD>n7<)1JbDz~nWNdU#E4twGac5Ox5b3G$TA7IJjsiFl&NMgS4s*oA$?nFs^ zonRri&A$zw;>CG*V-X1kXTjO%z@%p4*Gr|-&q)WaG072A4oy0_+?rk$KV9v5@vbQv zUZyr}(-&2|Q|CH!+sWjjFG;Dp>%65`FI!X#aKzIBiaPbWB$xBzqd^uz$KR(82OCsp z>XYSJNLJ);8BcDhS!iLbx_YG>`bfkn{?lF}7Qk+Nn^r0t==(GgBI=T^5fue}55+K|zQsjf&_*=< z48k!A2_8sHZ4NwV-}*|AdBVQH5_(U!y5;9_-gTy^uWWt2M)qcsCg#R`=cGXbZ7`;x zQyrk3zNVAa$8|jOr2z?%@O)!Wj(6^0* zS6tQ}Ne@Bgaspo4ffyO5Zc@Z3udDfT>3dhIj!u!uel8LTl}EOyPO2{jz!<$IbRHr$ zJWYRo39;ue_j6X*HElB58$lekJ&(wE`}u0OygK2GoNKDc=(sE7;`OB*>m80!Icz%O zPL!i<0}_$000JJOGiWi5C9MW5STKb z=>Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^Rg0vH!E5@L{?O#lE7bxA})R9M4} zn0c(7M|sA7Gv9K~x#!%~_VpIqapE`$2_Zm9$i5)aPzZq*T9qn*5EN2Gp&+%DkWfKI zs1<1_bWy`50%QR~3QdFEEF>0Shp-qzAWodzc)hW&?|PPRo0+G7e8+}XNMWSW(f6Hs zzj@}Jcb@lo#}I@uAPFR_u>=Gd8U|7il`B!h(+EAb^apJ3=2vZ;Iri|{`DMoY1I8?j zjl#`sGK;`?=e5op}Tnl2i8np_jCNtr8U!J%?Y}tCr;Z4@TF%Yj!+elJZYMs zQdnzz!X1x3$xpjWr$;Y3Yu%HkdURpk8lDfHG)gJ6oT$|#0rG`D z?Ws1#NXQ40V2N!#M^qJzxPob4&^&m6-wW~F`_8y<^_cy5Fob~-KmpwVdyB_=1kM2FXtR+dAq(TE_T2`qgsajU3dRkOp5B_A2 zwr@LIqj5_HtF+OQNm5}Dpk^b{`~T`M)h)ZqROv*qq`vD*sw7v+WtEmC-M{Gc=evIT zi|d{|z_xw?D+8JmR03Ox*i}rb;H>8la^s%8H-Bfgt0hT2@06=hu4NTklGK&LKvJ$- zzy2lBjuhKSZ-4Wj>cO4=qq(_x^@~!^&K}jr|LJC}+qzj;bjg*MYGG+kQYnQ(3Yp{w zl1i09>Ph|w1)S||r9RH{-Y zDVK^u$_vSP?Rww=C9&1Scw3L$f4>Iv3zGMe4;qw}a@CVQpY`q~hhEeEMz@A);CU#$k{-ml%IvcDpQN(x@ym8uj}=+satNLRk}QcYs@y}Q0G zWnR_tiYiqaXrQ33q=8gPhbrjjs+750PF`UMN<|%NDy3ij_?K#@9bI(oXugwEVki$bb2eiq}6%LE7y$E2qh67=X27NbgUr> zTexTEcOZ><$4xg82n_N9k0Fi{bTTbbj|HIgoO9v1ocD^C@%WH_ zGd6RC3s*exw&lUaNl~4>aRgL=v9_l1DAXP>kmniAPKyFq?4JO{`qk4lFbfD2Ah8KV z1`jxSB4g6DUhunzGiw878jsmEsY*<ttf|C@uJhW#_bc!ud=I-&2!P3bwqW7f`$cw z3w6*{We$;{%vOjaam^){f*0Ss^Ba&fY9k9#Qm48Ah(K&(EEWUg{Q-~e-ow*y>jVJEWzTSwcphvz`UZCz!WjD$dvq+kL`s{uy* z;cKraF)^RK=2;tP^RaGg3pig|_ z6N=+lqobqRy?eLvJl9|_IJF30li_fl8bGB=#SrSZ{_8 nC%Sgs&XCckkx0#~uT~IahPFwVZqIxhyU&lBOvk1gy1` zWl6Kyr0@=+m;j_hj*qC-ZNMPoh^w*$32$oZj|H)6y;K3g)|M`Fw9*y;@B6^}`QjHp zj~fh_7@y>Z>tD}#=bgv)?b~TI8qChlGBY#7jvYIA?6JqV@x~kZ*vCG`ZMWUV#TQ>p znx>}~;7_`=uG}yNVrnieTm@gd{i~{cslL22d8u;4Ae8btOKK$q$w|kbdtTeNZC5`efqQirmXnw2jpao?c29cZ+g?4WUUpT&wS=Hr~Y@R^yV-QT`BqE)S<7ub51*U z>`=4WR1`(J<(6Ai6ota@+to>cRaN&O4HWdbJMR=9z2_VH$;y&eBn?V0Ims>e>+vTU zz)P22aH%@Bt#`fiCiRP4L0*GFPcPJ*bEjx!@7}#yy?V6(?cBLjl2lf;0_v^wYkDiC z!bu0al|FUHJ>mmDd_-S5bU=$kATF!9Ci7JdZV>djTmD01@u*&X&2`F);Rn0RLml{n z7?ow&DUaTF-+fBcR9m-h)$!xUr63hqJ_K81SoYG+19SSj`yN)b;lm%?@%-%E)T>Y1 zd~VBu5`(jKm4+*cmNMS>n%7aJmir!lkoH6e3pAnxyayZcn=0$KwJ3_P*5aIF+qP|F zS;oEh-pj<;I9FVLIaYxxjtRrEw{PLAzj~VEtH*!L%jWlU)epbV&$4Pz?Tq5LZsp!zKEp}`xre5$$=e{leCJp21a5lodk8~8VH*j=G2}VFOEbpQ zcR$0ndGltjyz)vG78d!zo*#e-#2E4bUEqPIo?&U@6wi!W?0lTk9qq8Uw|v7BE09Fc zP(%zYo;c3;_ddp^GtOk)x^-BfU*%XLkf7OoL2xHY+ZaQy*E{um;DQTqK|FWtaDB;>dknDi$;VlkZr|3AL=f1-v=~G! z7FSL3Xm@dP*UTKGfFc@=7Exlk^oq*}!4VW_M)iFQu>n^NH@&{F(@<>w|DHA)WX0gr z*f@rbr>$knmJO^KTZQ)#z8Uf8+#-8c7R=m4o4na3_c2h4MlQ|{;^LWuy!E?3_}A|( zXX;A|WhI4D@^x)osML}Q^-q>-u8>@z;0rl<6~pY4)rF)6lDeT(Auo5TAk9_Na8L3* zX;4Z*+MRp7ao58yxnOpN_3AU?E8^g>5w$Qr(9b!sdKL38+VgKtG{~iDAccW^-aDlg2SrdJ zuR>L=;Cv-jUaG>WG}K$^|61~$6vJN9pim}hS61my9(wSt*B?7FvFYe@O!|UUf>KzC zsQl1}m>zAhIOtJEhStag&-WIX7#o{^`sw|P4U@cPdTN}OO~4t9ZGs@LAZZwoAvT@} zi!o-X=_~|6Fr;Y$xiHpX3}haB480`c;n_L9u>Z+-AKA3-3(q8R?$)knMKMLMWK}C> z(Dj&x97R>oOh(Adf{`epH# zuMUStA;l60e*I!t3-?+uFNWUH#~B5tiv)9akIm6w_;>8VbF)T4W^-h zSHJ@u6VY8*V%5|H6$NdVv!x7-9X!hV1IIuA$~EiXarK4gFf{}+1+=P~l8A&NPi`S# zh9#55Cr7bd-F&Vd5T%2R9)uL4utW6>&2R&Mc4sp73hhMdM%f^e=Y-GJ666c4>JJh!s z5fsKSAfgBSc;Og3XZ9c27s6@T=8de3jj|j>p0=3p6*MPTQ&Lx=)_|#?9YH9-bV^YH z6%{s#a5y3izVeJDO$NRqi4q)r8vPTzsNd(@EdR**+2bD_J93Q8QHRyCOqm9)Bt}Lo zt7IWKj@iIWm64yef#d6^-?l%EZkuVO6l1G!G$^WyMlwcG)upbDYvODGCWD57{{^sx V3%W2@5)=Rc002ovPDHLkV1jlVc&h*a diff --git a/rooter/0optionalapps/ext-speedtest/Makefile b/rooter/0optionalapps/ext-speedtest/Makefile deleted file mode 100644 index 68a6e47..0000000 --- a/rooter/0optionalapps/ext-speedtest/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-speedtest -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-speedtest - SECTION:=utils - CATEGORY:=ROOter - DEPENDS:=+ext-rspeedtest - SUBMENU:=Optional Applications - TITLE:=support for OpenSpeedTest - PKGARCH:=all -endef - -define Package/ext-speedtest/description - Helper scripts to enable OpenSpeedTest -endef - - -define Build/Compile -endef - -define Package/ext-speedtest/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,ext-speedtest)) diff --git a/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua b/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua deleted file mode 100644 index 0a70363..0000000 --- a/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/controller/speedtest.lua +++ /dev/null @@ -1,7 +0,0 @@ -module("luci.controller.speedtest", package.seeall) -function index() - local page - entry({"admin", "speed"}, firstchild(), "Speed Test", 81).dependent=false - page = entry({"admin", "speed", "speedtest"}, template("speedtest/speedtest"), "OpenSpeedTest", 71) - page.dependent = true -end diff --git a/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm b/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm deleted file mode 100644 index 53317d1..0000000 --- a/rooter/0optionalapps/ext-speedtest/files/usr/lib/lua/luci/view/speedtest/speedtest.htm +++ /dev/null @@ -1,45 +0,0 @@ -<%+header%> - - - -
                -
                -

                Browser Speed Test

                -
                A Speed Test using OpenSpeedTest that runs in the browser
                - - - - - - - - - -
                - -
                - - - - - -
                - - - -
                -
                -<%+footer%> diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css deleted file mode 100644 index 5254b92..0000000 --- a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/iconmoon_splash.css +++ /dev/null @@ -1,69 +0,0 @@ -@font-face { - font-family: 'icomoon_splash'; - src: url('../fonts/icomoon_splash.eot?vja16g'); - src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), - url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), - url('../fonts/icomoon_splash.woff?vja16g') format('woff'), - url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"], [class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'icomoon_splash' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - - -.icon-power-off:before { - content: "\f011"; -} -.icon-signal:before { - content: "\f012"; -} -.icon-cog:before { - content: "\f013"; -} -.icon-gear:before { - content: "\f013"; -} -.icon-home:before { - content: "\f015"; -} -.icon-exclamation-triangle:before { - content: "\f071"; -} -.icon-warning:before { - content: "\f071"; -} -.icon-comments:before { - content: "\f086"; -} -.icon-hdd-o:before { - content: "\f0a0"; -} -.icon-plug:before { - content: "\f1e6"; -} -.icon-wifi:before { - content: "\f1eb"; -} -.icon-connection:before { - content: "\e91b"; -} -.icon-podcast:before { - content: "\e91c"; -} -.icon-earth:before { - content: "\e9ca"; -} diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css deleted file mode 100644 index 85af002..0000000 --- a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/css/splash.css +++ /dev/null @@ -1,341 +0,0 @@ -/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ - -/* - CSS for ROOter splash pages - Copyright Francois Dechery - https://github.com/soif -*/ - -/* @group Splash Pages ---------------------------------------------------*/ - -.rooterSplash{ - padding: 0; - background: #F0F0F0; -} -.rooterPageHead{ - background: #55F; - padding: 10px 5px; - background: rgb(140,140,255); - background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); - background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); - border-bottom: 1px solid rgba(0,0,0,0.7); - -} -.rooterPageContent{ - border-top: 1px solid rgba(255,255,255,0.8); - border-bottom: 1px solid rgba(0,0,0, 0.1); - padding: 25px 10px; - max-width: 1200px; - margin: auto; -} - -.rooterPageContentBut{ - border-top: 1px solid rgba(255,255,255,0.8); - border-bottom: 1px solid rgba(0,0,0, 0.1); - padding: 25px 10px; - max-width: 600px; - margin: auto; -} - -.rooterHeadTitle{ - color: #fff; - text-align: center; - font-family: Georgia, "Times New Roman", Times, serif; - font-size: 32px; - line-height: 120%; - text-shadow: -1px -1px 2px rgba(0,0,0,0.5); -} -.rooterPageFoot{ - border-top: 1px solid rgba(255,255,255,0.8); - margin-top: 20px; - padding: 10px 10px; - max-width: 950px; - margin: auto; - font-size: 16px; -} -.rooterFootMenu{ - float: left; - margin-bottom: 10px; -} -.rooterFootMenu A{ - text-decoration: none; -} -.rooterFootMenu A:hover{ - color: #000; -} -.rooterFootMenu UL{ - padding: 0; - margin: 0; - overflow: hidden; - display: inline-block; -} -.rooterFootMenu LI{ - float: left; - padding: 0; - margin: 0; - list-style: none; -} -.rooterFootMenu LI A{ - padding: 0 10px; - color: #555; -} -.rooterFootMenu LI:first-child A{ - padding-left: 0; -} -.rooterFootCredits{ - float: right; - padding: 0; - margin: 0; - color: #999; - text-align: right; -} -.rooterFootCredits A{ - color: #777; -} -/* @end */ - - - - -/* @group Page: Home ---------------------------------------------------*/ - - -/* @group Logo -++++++++++++++++++ */ -.rooterHeadBox{ - font-size: 50px; - font-family: Georgia, "Times New Roman", Times, serif; - color: #fff; - line-height: 100%; - overflow: hidden; - width: 700px; - margin: auto; - padding-top: 10px; - opacity: 0; -} -.rooterLogo{ - background: url("../img/kangaroo_800.png") no-repeat; - background-size: 100%; - float: left; - height: 110px; - width: 250px; - opacity: 0.4; -} -.rooterTagline{ - margin-left: 100px; - padding-left: 10px; - text-shadow: 2px 2px 3px rgba(0,0,0,0.3); -} - -/* @end */ - -@media only screen and (max-width: 600px) { - .rooterHeadBox{ - text-align: center; - width: auto; - } - .rooterLogo{ - display: inline-block; - float: none; - } - .rooterTagline { - display: none; - } - .rooterFootCredits, - .rooterFootMenu{ - float: none; - text-align: center; - } -} - -#rooterItems{ - clear: both; - max-width: 600px ; - margin: auto; -} - -#rooterItemss{ - clear: both; - max-width: 350px ; - margin: auto; -} -.rooterItem{ - overflow: hidden; - border: 5px solid #00; - border-color: #00 #DDD #DDD #00; - padding: 20px 15px; - margin-bottom: 20px; - border-radius: 8px; - background-color: #AFAFAF; -} -.rooterItem:hover{ - background-color: #CFCFCF; - border-color: #AAA; -} -.rooterItemTitle{ - float: left; - font-size: 18px; - font-weight: bold; - padding-right: 10px; - color: #000; - line-height: 2em; -} -.rooterItemTitle .icon{ - color: #55F; - margin-right: 8px; - font-size: 2em; - vertical-align: middle; -} - -.rooterItemsp{ - overflow: hidden; - border: 5px solid #00; - border-color: #00 #DDD #DDD #00; - padding: 5px 15px; - margin-bottom: 5px; - border-radius: 8px; - background-color: #AFAFAF; -} -.rooterItemsp:hover{ - background-color: #CFCFCF; - border-color: #AAA; -} - -#rooterItems A{ - text-decoration: none; -} -.rooterItemDesc{ - font-size: 18px; - color: #777; - margin-left: 220px; - margin-top: 0.7em; -} -/* @end */ - - - -/* @group Page: Status ---------------------------------------------------*/ - -.modemStatusBlock{ - margin-bottom: 30px; -} -#rooterSplashStatus h3{ - clear:both; - font-size: 18px; - color: #55F; -} -#rooterSplashStatus h3 .icon{ - margin-right: 3px; -} -#rooterSplashStatus h3 .msCell{ - color: #666; -} -.modemStatusRow{ - clear:both; - padding-bottom: 20px; - overflow: hidden; -} -.modemStatusRow .msTitle{ - border-radius: 2px 2px 0 0; - padding: 5px 5px ; - background: #484848; - color: #fff; - background: rgb(99,99,99); - background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); - background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); -} -.modemStatusRow .msCell{ - border-radius: 10px; - display: inline-block; - margin-top: 10px; - float:left; - border: 1px solid #ccc; - padding-bottom: 5px; - background: #fff; - -} -.modemStatusRow1 .msCell{ - width: 176px; - margin: 10px 5px 0 5px; - text-align: center; -} -.modemStatusRow1 SPAN B{ - font-weight: bold; - font-size: 35px; - line-height: 110%; - text-shadow: 1px 1px 1px rgba(0,0,0,0.4); -} -.modemStatusRow1 .msDesc{ - color: #000; - font-size: 12px; -} -.modemStatusRow2 .msCell{ - margin: 10px 5px; - text-align: center; -} -.modemStatusRow2 SPAN{ - display: inline-block; - padding: 5px 5px ; - font-size: 14px; -} -#counter_div{ - color: #000; - font-weight: normal; - font-size: 14px; -} -#counter_val{ - color: #F00; - font-size: 32px; - font-weight: bold; - text-shadow: 1px 1px 1px rgba(0,0,0,0.1); -} -#msCell_per{} -#msCell_csq{} -#msCell_rssi{} -#msCell_rscp{} -#msCell_ecio{} - -#rooterSplashStatus .level_0{ - color: #0F0; // green -} -#rooterSplashStatus .level_1{ - color: #0CB; // green blue -} -#rooterSplashStatus .level_2{ - color: #00F; // blue -} -#rooterSplashStatus .level_3{ - color: #F0F; // violet -} -#rooterSplashStatus .level_4{ - color: #F80; // orange -} -#rooterSplashStatus .level_5{ - color: #F00; // red -} -#rooterSplashStatus .level_6{ - color: #FF0; // yellow -} - -/* @end */ - - -/* Easy Color changer ------------- */ - -.rooterPageHead{ - /*background: #55F;*/ -} -.rooterItemTitle .icon, -#rooterSplashStatus h3{ - color: #55F; -} - - - diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.eot b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.eot deleted file mode 100644 index 29cd4d1f36a419b4822d210be985dbde03d1d3ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 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 Gn*ReFo8=Jz diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg deleted file mode 100644 index dc2127b..0000000 --- a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.ttf b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.ttf deleted file mode 100644 index 4e27645c4f897ba62acace85a644aff591860682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4516 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 E0b}jXx&QzG diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.woff b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/fonts/icomoon_splash.woff deleted file mode 100644 index 63f541307f5f723c6eed5ef792b2fbce8e4ea0f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4592 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 Vg5RoPjlsG#(%?z@pM}q8{|Cw&)JOmT diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/favicon.gif b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/favicon.gif deleted file mode 100644 index bfbe292825c753540fdd42af7823e167398874e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2441 zcmeH|`8yMi1ILGvYixGm<15Ef&K%XGWGY8nBu7{bHJZ6{Bq|yscV0Es=-6N-A(-ME%9Np_=t!2*uVA^pYRf&^oF*( z!kS&-EpG5uH*l{TxRV6!^#p$+f%{32esA!AJ7mBc^4SMD;Dwm+ z27mR1ehY+82SVo_AZCK0^C8fMhtQw*U`zLPrpg^~%uvH4| zR~USY0^6d(w<)k~Dq=SrwjF`kjeze(!gizJ`%%b)NW{S-BsU7a7me79g>z!yoLB@m z8qSS@AH>4BaR_d_>~^fmdYtMGUF{$RKa+-^Prtszyu;22{FEKml}G8$3+pfZFU$YO z{}=)J9UuHTLD06{K*D3&R(~8_?#haa^F?N!o zlsMu-tc*~Fu@K71ve@CNwg^8j>SkxAJ@sOYs-55BSd6OxPnr%@m}yrPk)mpvtnxqj0ew6D_ujjAtxs9Bikc{4)t`0#pbMT~G)cdhPSVxAf6tlIkb>#o#LkpANO z;*El?g2y5AzgOIAzHw*8vYrPu&2+urXN7WtTbHZ$vY6*WO*c1xHrYBD7#QszaOw^d z>-k?yKIn&&oQ(h)c6}6<@_hD1kok~BBm&DXe_Lv#M&9c`gl(6H@=6gdF#^nJ1w$3q zF^f2j*81G|V|}KX5S#M+Z&*1Q;?3Je^O(1f)qK|s!wi010}AN{OwS}+=n3)Nx%9mj zCD!EF!keOq9hyk7_l_Yxfrjs7q@ANLWIrvxrrz?4nF=Hb1PTZ#U53oQz)4~-1p@N; zl-%RmD#L{+P3~F-*dPZ_E5=pqCNeErR6IPYv&hQNy~w*#g~dC19;I!M+<*AU-NT-L z*(IE@SkUvhVIhdg`&_NOn}GX~+1vMJnJ~$Mzbpk#7c*F|l^AccH-v>Fqy-9apI?1& zD_*V`Gd@DhSLNKsNbi{MmAsmsh%Ie$_l}!rKqS#FzzM{cYwrlhd;vUy$b28${n!kz zcEA-GxR4@dZB&eplBroUgQrx%@n-`Q9Bew!&-S0UuNuCs>?&B_p0{s(0hOWAe)8jP-l7 zm9g(i8~0aBK~87;bLP}PPGEnJ?@yK#v$U6*MXv164IM7y7>pgA4H@d06Xo>GST&{o zp7-HwZzdi0(OV?q?EA#D_17J*JgnbKU&(skIL{sIrR=ng9t?dkpubtZpE7DSEQosZ z%jV|;!6HXnZ}h8Lds^@+pA)McjrsQ&sD~KNytq2d&PiG*aAS&t2?9f|MMiY!On=l! zYZcWXQz47l9CmmUSlTCoP0jpezTLFV;~g5_H7(KD*DiZ*E$ZsbBrGbrwclRrft>>r zAwS=~VdxvOe4%r%`$g;BijSUHVjgl_&{+2xE#Bs3-rx$m^S7uIr(ODA>bOQRd!76+^)JBhkVD(k)@2uP$fz8W(i z=w7z%1g8o!W>-kVjc05963awysKuSabrsQ1jkO=qnyl|42lg_Wtlc!97MYNKT}=x;&gqW3TbnA}QSS95oj9!b!RS?JE&sX zfbY3Z56Hsl7oD^se@eN*D7{-YPSQFF9%R>M7)=@9+TG+iloJO0ao-8aJR%1;^ACjV#SQ=f diff --git a/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/kangaroo_800.png b/rooter/0optionalapps/ext-speedtest/files/www/luci-static/speed/img/kangaroo_800.png deleted file mode 100644 index 478fa6d62f4ce758358142fefd480c564773ce36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5836 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 Wk|dU(LN#0f0000/dev/null 2>&1` -then - return -fi -echo "0" > /tmp/texting -uci set modem.general.smsnum='1' -uci commit modem \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh deleted file mode 100644 index 5767c1f..0000000 --- a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/dotext.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "TEXTING" "$@" -} - -handle_numbers() { - let "NUMBERS = $NUMBERS + 1" - if [ $NUMBERS -eq $nindex ]; then - numch=$1 - fi -} - -do_numbers() { - local config=$1 - config_list_foreach "$config" number handle_numbers -} - -handle_messages() { - let "NUMBERS = $NUMBERS + 1" - if [ $NUMBERS -eq $nindex ]; then - numch=$1 - fi -} - -do_messages() { - local config=$1 - config_list_foreach "$config" message handle_messages -} - -sendmsg() { - nnum=$(uci -q get texting.texting.numbers) - mnum=$(uci -q get texting.texting.messages) - delay=$(uci -q get texting.texting.interval) - NUMBERS=0 - RANDOM=$(date +%s%N | cut -b10-19) - RAN=$RANDOM - RAN1=${RAN:0:1} - if [ $RAN1 = "0" ]; then - RAN="1"$RAN - rlen=${#RAN} - if [ $rlen -gt 9 ]; then - RAN=${RAN:0:8} - fi - fi - nindex=$(( $RAN % $nnum + 1 )) - config_load texting - config_foreach do_numbers numbers - Phone=$numch - NUMBERS=0 - RANDOM=$(date +%s%N | cut -b10-19) - RAN=$RANDOM - RAN1=${RAN:0:1} - if [ $RAN1 = "0" ]; then - RAN="1"$RAN - rlen=${#RAN} - if [ $rlen -gt 9 ]; then - RAN=${RAN:0:8} - fi - fi - nindex=$(( $RAN % $mnum + 1 )) - config_foreach do_messages messages - Message=$numch - /usr/lib/fullmenu/chksms.sh - if [ -e /tmp/texting ]; then - /usr/lib/sms/smsout.sh "$Phone" "$Message" - fi -} - -checktime() { - shour=$(uci -q get texting.texting.starthour) - smin=$(uci -q get texting.texting.startmin) - ehour=$(uci -q get texting.texting.endhour) - emin=$(uci -q get texting.texting.endmin) - chour=$(date +%H) - cmin=$(date +%M) - if [ $shour -gt $chour ]; then - flag="0" - else - if [ $shour -eq $chour ]; then - if [ $smin -le $cmin ]; then - flag="1" - else - flag="0" - fi - else - flag="1" - fi - fi - - if [ $flag = "1" ]; then - if [ $ehour -lt $chour ]; then - flag="0" - else - if [ $ehour -eq $chour ]; then - if [ $emin -lt $cmin ]; then - flag="0" - else - flag="1" - fi - else - flag="1" - fi - fi - fi - - echo $flag -} - -while true -do - running=$(checktime) - if [ $running = "1" ]; then - EN=$(uci -q get texting.setting.enabled) - if [ $EN = "1" ]; then - sendmsg - sleep $delay - fi - else - sleep 900 - fi -done \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh b/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh deleted file mode 100644 index 5d57226..0000000 --- a/rooter/0optionalapps/ext-texting/files/usr/lib/fullmenu/text-setup.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "TEXTING" "$@" -} - -sleep 3 - -handle_numbers() { - let "NUMBERS = $NUMBERS + 1" -} - -do_numbers() { - local config=$1 - config_list_foreach "$config" number handle_numbers -} - -handle_messages() { - let "NUMBERS = $NUMBERS + 1" -} - -do_messages() { - local config=$1 - config_list_foreach "$config" message handle_numbers -} - -SHOUR=$(uci -q get texting.setting.start) -HOUR=`expr $SHOUR / 4` -let "TH = $HOUR * 4" -let "TMP1 = $SHOUR - $TH" -let "MIN = $TMP1 * 15" -uci set texting.texting.starthour=$HOUR -uci set texting.texting.startmin=$MIN -EHOUR=$(uci -q get texting.setting.end) -HOUR=`expr $EHOUR / 4` -let "TH = $HOUR * 4" -let "TMP1 = $EHOUR - $TH" -let "MIN = $TMP1 * 15" -uci set texting.texting.endhour=$HOUR -uci set texting.texting.endmin=$MIN - -NUMBERS=0 -config_load texting -config_foreach do_numbers numbers -uci set texting.texting.numbers=$NUMBERS -NUMBERS=0 -config_foreach do_messages messages -uci set texting.texting.messages=$NUMBERS - -TIMES=$(uci -q get texting.setting.times) -let "TH = $EHOUR - $SHOUR" -let "TMIN = $TH * 15" -let "INTERVAL = $TMIN / $TIMES" -let "INTERVAL = $INTERVAL * 60" -uci set texting.texting.interval=$INTERVAL -uci commit texting - -result=`ps | grep -i "dotext.sh" | grep -v "grep" | wc -l` -if [ $result -lt 1 ]; then - /usr/lib/fullmenu/dotext.sh & -fi - diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua deleted file mode 100644 index c0c5585..0000000 --- a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/controller/texting.lua +++ /dev/null @@ -1,24 +0,0 @@ -module("luci.controller.texting", package.seeall) -function index() - local lock = luci.model.uci.cursor():get("custom", "menu", "full") - if lock == "1" then - entry({"admin", "adminmenu", "texting"}, cbi("fullmenu/texting"), "---Random Texting", 8) - end - - entry({"admin", "services", "chksms"}, call("action_chksms")) -end - -function action_chksms() - local rv = {} - os.execute("/usr/lib/fullmenu/chksms.sh") - file = io.open("/tmp/texting", "r") - if file ~= nil then - rv["sms"] = "1" - file:close() - else - rv["sms"] = "0" - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua deleted file mode 100644 index d689c0b..0000000 --- a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/model/cbi/fullmenu/texting.lua +++ /dev/null @@ -1,254 +0,0 @@ -local utl = require "luci.util" - -m = Map("texting", translate("Random Texting"), translate("Send random message to number at random times")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/fullmenu/text-setup.sh &") -end - -s = m:section(TypedSection, "setting", "Global Settings") -s.anonymous = true -s.addremove = false - -s:option(Flag, "enabled", translate("Enabled : ")) - -sdhour = s:option(ListValue, "start", translate("Starting Time :")) -sdhour.rmempty = true -sdhour:value("0", "12:00 AM") -sdhour:value("1", "12:15 AM") -sdhour:value("2", "12:30 AM") -sdhour:value("3", "12:45 AM") -sdhour:value("4", "01:00 AM") -sdhour:value("5", "01:15 AM") -sdhour:value("6", "01:30 AM") -sdhour:value("7", "01:45 AM") -sdhour:value("8", "02:00 AM") -sdhour:value("9", "02:15 AM") -sdhour:value("10", "02:30 AM") -sdhour:value("11", "02:45 AM") -sdhour:value("12", "03:00 AM") -sdhour:value("13", "03:15 AM") -sdhour:value("14", "03:30 AM") -sdhour:value("15", "03:45 AM") -sdhour:value("16", "04:00 AM") -sdhour:value("17", "04:15 AM") -sdhour:value("18", "04:30 AM") -sdhour:value("19", "04:45 AM") -sdhour:value("20", "05:00 AM") -sdhour:value("21", "05:15 AM") -sdhour:value("22", "05:30 AM") -sdhour:value("23", "05:45 AM") -sdhour:value("24", "06:00 AM") -sdhour:value("25", "06:15 AM") -sdhour:value("26", "06:30 AM") -sdhour:value("27", "06:45 AM") -sdhour:value("28", "07:00 AM") -sdhour:value("29", "07:15 AM") -sdhour:value("30", "07:30 AM") -sdhour:value("31", "07:45 AM") -sdhour:value("32", "08:00 AM") -sdhour:value("33", "08:15 AM") -sdhour:value("34", "08:30 AM") -sdhour:value("35", "08:45 AM") -sdhour:value("36", "09:00 AM") -sdhour:value("37", "09:15 AM") -sdhour:value("38", "09:30 AM") -sdhour:value("39", "09:45 AM") -sdhour:value("40", "10:00 AM") -sdhour:value("41", "10:15 AM") -sdhour:value("42", "10:30 AM") -sdhour:value("43", "10:45 AM") -sdhour:value("44", "11:00 AM") -sdhour:value("45", "11:15 AM") -sdhour:value("46", "11:30 AM") -sdhour:value("47", "11:45 AM") -sdhour:value("48", "12:00 PM") -sdhour:value("49", "12:15 PM") -sdhour:value("50", "12:30 PM") -sdhour:value("51", "12:45 PM") -sdhour:value("52", "01:00 PM") -sdhour:value("53", "01:15 PM") -sdhour:value("54", "01:30 PM") -sdhour:value("55", "01:45 PM") -sdhour:value("56", "02:00 PM") -sdhour:value("57", "02:15 PM") -sdhour:value("58", "02:30 PM") -sdhour:value("59", "02:45 PM") -sdhour:value("60", "03:00 PM") -sdhour:value("61", "03:15 PM") -sdhour:value("62", "03:30 PM") -sdhour:value("63", "03:45 PM") -sdhour:value("64", "04:00 PM") -sdhour:value("65", "04:15 PM") -sdhour:value("66", "04:30 PM") -sdhour:value("67", "04:45 PM") -sdhour:value("68", "05:00 PM") -sdhour:value("69", "05:15 PM") -sdhour:value("70", "05:30 PM") -sdhour:value("71", "05:45 PM") -sdhour:value("72", "06:00 PM") -sdhour:value("73", "06:15 PM") -sdhour:value("74", "06:30 PM") -sdhour:value("75", "06:45 PM") -sdhour:value("76", "07:00 PM") -sdhour:value("77", "07:15 PM") -sdhour:value("78", "07:30 PM") -sdhour:value("79", "07:45 PM") -sdhour:value("80", "08:00 PM") -sdhour:value("81", "08:15 PM") -sdhour:value("82", "08:30 PM") -sdhour:value("83", "08:45 PM") -sdhour:value("84", "09:00 PM") -sdhour:value("85", "09:15 PM") -sdhour:value("86", "09:30 PM") -sdhour:value("87", "09:45 PM") -sdhour:value("88", "10:00 PM") -sdhour:value("89", "10:15 PM") -sdhour:value("90", "10:30 PM") -sdhour:value("91", "10:45 PM") -sdhour:value("92", "11:00 PM") -sdhour:value("93", "11:15 PM") -sdhour:value("94", "11:30 PM") -sdhour:value("95", "11:45 PM") -sdhour.default = "32" - -sdhour = s:option(ListValue, "end", translate("Ending Time :")) -sdhour.rmempty = true -sdhour:value("0", "12:00 AM") -sdhour:value("1", "12:15 AM") -sdhour:value("2", "12:30 AM") -sdhour:value("3", "12:45 AM") -sdhour:value("4", "01:00 AM") -sdhour:value("5", "01:15 AM") -sdhour:value("6", "01:30 AM") -sdhour:value("7", "01:45 AM") -sdhour:value("8", "02:00 AM") -sdhour:value("9", "02:15 AM") -sdhour:value("10", "02:30 AM") -sdhour:value("11", "02:45 AM") -sdhour:value("12", "03:00 AM") -sdhour:value("13", "03:15 AM") -sdhour:value("14", "03:30 AM") -sdhour:value("15", "03:45 AM") -sdhour:value("16", "04:00 AM") -sdhour:value("17", "04:15 AM") -sdhour:value("18", "04:30 AM") -sdhour:value("19", "04:45 AM") -sdhour:value("20", "05:00 AM") -sdhour:value("21", "05:15 AM") -sdhour:value("22", "05:30 AM") -sdhour:value("23", "05:45 AM") -sdhour:value("24", "06:00 AM") -sdhour:value("25", "06:15 AM") -sdhour:value("26", "06:30 AM") -sdhour:value("27", "06:45 AM") -sdhour:value("28", "07:00 AM") -sdhour:value("29", "07:15 AM") -sdhour:value("30", "07:30 AM") -sdhour:value("31", "07:45 AM") -sdhour:value("32", "08:00 AM") -sdhour:value("33", "08:15 AM") -sdhour:value("34", "08:30 AM") -sdhour:value("35", "08:45 AM") -sdhour:value("36", "09:00 AM") -sdhour:value("37", "09:15 AM") -sdhour:value("38", "09:30 AM") -sdhour:value("39", "09:45 AM") -sdhour:value("40", "10:00 AM") -sdhour:value("41", "10:15 AM") -sdhour:value("42", "10:30 AM") -sdhour:value("43", "10:45 AM") -sdhour:value("44", "11:00 AM") -sdhour:value("45", "11:15 AM") -sdhour:value("46", "11:30 AM") -sdhour:value("47", "11:45 AM") -sdhour:value("48", "12:00 PM") -sdhour:value("49", "12:15 PM") -sdhour:value("50", "12:30 PM") -sdhour:value("51", "12:45 PM") -sdhour:value("52", "01:00 PM") -sdhour:value("53", "01:15 PM") -sdhour:value("54", "01:30 PM") -sdhour:value("55", "01:45 PM") -sdhour:value("56", "02:00 PM") -sdhour:value("57", "02:15 PM") -sdhour:value("58", "02:30 PM") -sdhour:value("59", "02:45 PM") -sdhour:value("60", "03:00 PM") -sdhour:value("61", "03:15 PM") -sdhour:value("62", "03:30 PM") -sdhour:value("63", "03:45 PM") -sdhour:value("64", "04:00 PM") -sdhour:value("65", "04:15 PM") -sdhour:value("66", "04:30 PM") -sdhour:value("67", "04:45 PM") -sdhour:value("68", "05:00 PM") -sdhour:value("69", "05:15 PM") -sdhour:value("70", "05:30 PM") -sdhour:value("71", "05:45 PM") -sdhour:value("72", "06:00 PM") -sdhour:value("73", "06:15 PM") -sdhour:value("74", "06:30 PM") -sdhour:value("75", "06:45 PM") -sdhour:value("76", "07:00 PM") -sdhour:value("77", "07:15 PM") -sdhour:value("78", "07:30 PM") -sdhour:value("79", "07:45 PM") -sdhour:value("80", "08:00 PM") -sdhour:value("81", "08:15 PM") -sdhour:value("82", "08:30 PM") -sdhour:value("83", "08:45 PM") -sdhour:value("84", "09:00 PM") -sdhour:value("85", "09:15 PM") -sdhour:value("86", "09:30 PM") -sdhour:value("87", "09:45 PM") -sdhour:value("88", "10:00 PM") -sdhour:value("89", "10:15 PM") -sdhour:value("90", "10:30 PM") -sdhour:value("91", "10:45 PM") -sdhour:value("92", "11:00 PM") -sdhour:value("93", "11:15 PM") -sdhour:value("94", "11:30 PM") -sdhour:value("95", "11:45 PM") -sdhour.default = "68" - -sdhour = s:option(ListValue, "times", translate("Times per Day :")) -sdhour.rmempty = true -sdhour:value("2", "2") -sdhour:value("4", "4") -sdhour:value("6", "6") -sdhour:value("8", "8") -sdhour:value("10", "10") -sdhour:value("12", "12") -sdhour:value("14", "14") -sdhour:value("16", "16") -sdhour:value("18", "18") -sdhour:value("20", "20") -sdhour:value("22", "22") -sdhour:value("24", "24") -sdhour:value("26", "26") -sdhour:value("28", "28") -sdhour:value("30", "30") -sdhour:value("32", "32") -sdhour:value("34", "34") -sdhour:value("36", "36") -sdhour:value("38", "38") -sdhour:value("40", "40") -sdhour.default = "10" - - -s = m:section(TypedSection, "numbers", "Phone Numbers") -s.anonymous = true -s.addremove = false - -o = s:option(DynamicList, "number", translate("List of Phone Numbers : ")) - -s = m:section(TypedSection, "messages", "Messages") -s.anonymous = true -s.addremove = false - -o = s:option(DynamicList, "message", translate("List of Messages : ")) - -m:section(SimpleSection).template = "fullmenu/textarea" - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm b/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm deleted file mode 100644 index fd7c69f..0000000 --- a/rooter/0optionalapps/ext-texting/files/usr/lib/lua/luci/view/fullmenu/textarea.htm +++ /dev/null @@ -1,103 +0,0 @@ -<% - load_icon = resource .. "/icons/loading.gif" -%> - - - - -
                - <%:Manual Texting%> - - - - - - - - - -
                Phone Number :
                Message :
                 
                - - - - - - - - - -
                diff --git a/rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh b/rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh deleted file mode 100644 index 6178cdb..0000000 --- a/rooter/0optionalapps/ext-throttle/files/usr/lib/throttle/throttle.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -stop_interface() { - INTER=$1 - DEVICE=$(uci -q get sqm.$INTER.interface) - uci set sqm.$INTER.enabled='0' - uci commit sqm - if [ $DEVICE != "0" ]; then - /usr/lib/sqm/run.sh stop ${DEVICE} - fi -} - -start_interface() { - INTER=$1 - sdown=$2 - sup=$3 - uci set sqm.$INTER.enabled='1' - uci set sqm.$INTER.download=$sdown - uci set sqm.$INTER.upload=$sup - uci commit sqm - DEVICE=$(uci -q get sqm.$INTER.interface) - if [ $DEVICE != "0" ]; then - /usr/lib/sqm/run.sh stop ${DEVICE} - /usr/lib/sqm/run.sh start ${DEVICE} - fi -} - -cmd=$1 -if [ $cmd = 'start' ]; then - mult=$4 - if [ -z $mult ]; then - down=$2"000" - up=$3"000" - else - down=$2 - up=$3 - fi - /etc/init.d/sqm enabled - start_interface wan $down $up - start_interface wan1 $down $up - start_interface wan2 $down $up -else - stop_interface wan - stop_interface wan1 - stop_interface wan2 -fi \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/Makefile b/rooter/0optionalapps/ext-wireguard/Makefile deleted file mode 100644 index e46e0df..0000000 --- a/rooter/0optionalapps/ext-wireguard/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-wireguard -PKG_VERSION:=4.500 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-wireguard - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - DEPENDS:=+wireguard-tools +kmod-wireguard \ - +luci-proto-wireguard +udp-tunnel +eoip - TITLE:=Install scripts for Wireguard - PKGARCH:=all -endef - -define Package/ext-wireguard/description - Install scripts for Wireguard -endef - - -define Build/Compile -endef - -define Package/ext-wireguard/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,ext-wireguard)) diff --git a/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard b/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard deleted file mode 100644 index 77908d4..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard +++ /dev/null @@ -1,5 +0,0 @@ - -config settings 'settings' - option enabled '0' - option client '0' - option server '0' diff --git a/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes b/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes deleted file mode 100644 index 52a6b2b..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/etc/config/wireguard_recipes +++ /dev/null @@ -1,36 +0,0 @@ -config wireguard_recipe b_client - option _description "Wireguard Client" - option _role "client" - option client "1" - option port "51280" - option auto '0' - option addresses '' - option dns '' - option privatekey '' - option name '' - option keepalive '25' - option publickey '' - option presharedkey '' - option ips '' - option ra_ips '1' - option endpoint_host '' - option sport '51280' - option active '0' - option udptunnel '0' - option mtu '1280' - -config wireguard_recipe b_server - option _description "Wireguard Server" - option _role "server" - option client "0" - option port "51280" - option auto '0' - option addresses '' - option publickey '' - option privatekey '' - option usepre '0' - option presharedkey '' - option active '0' - option udptunnel '0' - option udpport '54321' - option mtu '1280' \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard b/rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard deleted file mode 100644 index 16a34ce..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/etc/init.d/wireguard +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh /etc/rc.common -. /lib/functions.sh -# Copyright (C) 2006 OpenWrt.org - -START=99 - -log() { - logger -t "WireGuard Init.d : " "$@" -} - -chk_zone() { - local config=$1 - - config_get src $config src - config_get dest $config dest - if [ $src = "lan" -a $dest = "wg" ]; then - uci set firewall."$config".dest="wan" - uci commit firewall - fi -} - -check_config () { - log "Check Client Interfaces" - uci delete network.wg0 - uci delete network.wg1 - uci commit network - uci set network.wg0=interface - uci set network.wg0.proto="wireguard" - uci set network.wg0.auto="0" - uci set network.wg0.private_key="" - uci set network.wg0.listen_port="" - uci add_list network.wg0.addresses="" - uci set network.wg1=interface - uci set network.wg1.proto="wireguard" - uci set network.wg1.auto="0" - uci set network.wg1.private_key="" - uci set network.wg1.listen_port="" - uci add_list network.wg1.addresses="" - uci commit network - - uci delete firewall.wgzone - uci delete firewall.wgwforward - uci delete firewall.wwgforward - uci delete firewall.lwgforward - uci delete firewall.wglforward - uci commit firewall - uci set firewall.wgzone=zone - uci set firewall.wgzone.name="wg" - uci set firewall.wgzone.forward="ACCEPT" - uci set firewall.wgzone.output="ACCEPT" - uci set firewall.wgzone.network="wg0 wg1" - uci set firewall.wgzone.input="ACCEPT" - uci set firewall.wgzone.masq="1" - uci set firewall.wgzone.mtu_fix="1" - uci commit firewall - - config_load firewall - config_foreach chk_zone forwarding - - /etc/init.d/firewall restart -} - -chk_start() { - local config=$1 - - config_get auto $config auto - uci set wireguard."$config".active="0" - uci commit wireguard - if [ $auto = '1' ]; then - /usr/lib/wireguard/startvpn.sh $config - else - /usr/lib/wireguard/stopvpn.sh $config - fi -} - -start() { - uci set wireguard.settings.client="0" - uci set wireguard.settings.server="0" - uci commit wireguard - if [ ! -e /etc/openvpn ]; then - mkdir /etc/openvpn - fi - check_config - - config_load wireguard - config_foreach chk_start wireguard - if [ -e /etc/crontabs/root ]; then - sed -i '/wireguard_watchdog/d' /etc/crontabs/root - fi - echo '* * * * * /usr/bin/wireguard_watchdog' >> /etc/crontabs/root - /etc/init.d/cron restart -} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua deleted file mode 100644 index 48ea3c3..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/controller/wireguard.lua +++ /dev/null @@ -1,111 +0,0 @@ --- Copyright 2016-2017 Dan Luedtke --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.wireguard", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - entry({"admin", "vpn", "wireguard"}, cbi("wireguard"), _("Wireguard"), 63) - entry( {"admin", "vpn", "wireguard", "client"}, cbi("wireguard-client"), nil ).leaf = true - entry( {"admin", "vpn", "wireguard", "server"}, cbi("wireguard-server"), nil ).leaf = true - end - - entry( {"admin", "vpn", "wireguard", "wupload"}, call("conf_upload")) - entry( {"admin", "vpn", "generateconf"}, call("conf_gen")) - entry( {"admin", "vpn", "textconf"}, call("text_gen")) - entry( {"admin", "vpn", "wirestatus"}, call("wirestatus")) -end - -function conf_upload() - local fs = require("nixio.fs") - local http = require("luci.http") - local util = require("luci.util") - local uci = require("luci.model.uci").cursor() - local upload = http.formvalue("ovpn_file") - local name = http.formvalue("instance_name2") - local file = "/etc/openvpn/" ..name.. ".conf" - - if name and upload then - local fp - - http.setfilehandler( - function(meta, chunk, eof) - local data = util.trim(chunk:gsub("\r\n", "\n")) .. "\n" - data = util.trim(data:gsub("[\128-\255]", "")) - - if not fp and meta and meta.name == "ovpn_file" then - fp = io.open(file, "w") - end - if fp and data then - fp:write(data) - end - if fp and eof then - fp:close() - end - end - ) - - if fs.access(file) then - os.execute("/usr/lib/wireguard/conf.sh " .. name .. " " .. file) - end - end - http.redirect(luci.dispatcher.build_url('admin/vpn/wireguard')) -end - -function conf_gen() - os.execute("/usr/lib/wireguard/create.sh") -end - -function text_gen() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/wireguard/text.sh " .. "\"" .. set .. "\"") -end - -function wirestatus() - local data = { } - local last_device = "" - - local wg_dump = io.popen("wg show all dump") - if wg_dump then - local line - for line in wg_dump:lines() do - local line = string.split(line, "\t") - if not (last_device == line[1]) then - last_device = line[1] - data[line[1]] = { - name = line[1], - public_key = line[3], - listen_port = line[4], - fwmark = line[5], - peers = { } - } - else - local peer = { - public_key = line[2], - endpoint = line[4], - allowed_ips = { }, - latest_handshake = line[6], - transfer_rx = line[7], - transfer_tx = line[8], - persistent_keepalive = line[9] - } - if not (line[4] == '(none)') then - for ipkey, ipvalue in pairs(string.split(line[5], ",")) do - if #ipvalue > 0 then - table.insert(peer['allowed_ips'], ipvalue) - end - end - end - table.insert(data[line[1]].peers, peer) - end - end - end - - luci.http.prepare_content("application/json") - luci.http.write_json(data) -end \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua deleted file mode 100644 index 45e2216..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-client.lua +++ /dev/null @@ -1,104 +0,0 @@ -require("luci.ip") -require("luci.model.uci") - ---luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) - -local m = Map("wireguard", translate("Wireguard Client"), translate("Set up a Wireguard Client")) - -e = m:section(NamedSection, "settings", "") - -m.on_init = function(self) - --luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) -end - -btn = e:option(Button, "_btn", translate(" ")) -btn.inputtitle = translate("Back to Main Page") -btn.inputstyle = "apply" -btn.redirect = luci.dispatcher.build_url( - "admin", "vpn", "wireguard" -) -function btn.write(self, section, value) - luci.http.redirect( self.redirect ) -end - - -local s = m:section( NamedSection, arg[1], "wireguard", translate("Client") ) - -ip = s:option(Value, "addresses", translate("IP Addresses :"), translate("Comma separated list of IP Addresses that server will accept from this client")); -ip.rmempty = true; -ip.optional=false; -ip.default="10.14.0.2/24"; - -port = s:option(Value, "port", translate("Listen Port :"), translate("Client Listen Port")); -port.rmempty = true; -port.optional=false; -port.default="51820"; - -ul = s:option(ListValue, "udptunnel", translate("Enable UDP over TCP :")); -ul:value("0", translate("No")) -ul:value("1", translate("Yes")) -ul.default=0 - -dns = s:option(Value, "dns", translate("DNS Servers :"), translate("Comma separated list of DNS Servers.")); -dns.rmempty = true; -dns.optional=false; - -mtu = s:option(Value, "mtu", translate("MTU :"), translate("Maximum MTU")); -mtu.rmempty = true; -mtu.optional=false; -mtu.datatype = 'range(1280,1420)'; -mtu.default="1280"; - -pka = s:option(Value, "persistent_keepalive", translate("Persistent Keep Alive :"), translate("Seconds between keep alive messages")); -pka.rmempty = true; -pka.optional=false; -pka.datatype = 'range(1,100)'; -pka.default="25"; - -pkey = s:option(Value, "privatekey", translate("Private Key :"), translate("Private Key supplied by the Server")); -pkey.rmempty = true; -pkey.optional=false; - -il = s:option(ListValue, "wginter", translate("Interface to Use :")); -il:value("0", translate("WG0")) -il:value("1", translate("WG1")) -il.default="0" - -bl = s:option(ListValue, "auto", translate("Start on Boot :")); -bl:value("0", translate("No")) -bl:value("1", translate("Yes")) -bl.default="0" - -xbl = s:option(ListValue, "forward", translate("All Traffic Through Tunnel :")); -xbl:value("0", translate("No")) -xbl:value("1", translate("Yes")) -xbl.default="1" - -s = m:section( NamedSection, arg[1], "wireguard", translate("Server") ) - -name = s:option( Value, "name", translate("Server Name :"), translate("Optional Server name")) - -pukey = s:option(Value, "publickey", translate("Public Key :"), translate("Public Key of the Server")); -pukey.rmempty = true; -pukey.optional=false; - -prkey = s:option(Value, "presharedkey", translate("Presharedkey :"), translate("PreShared Key from the Server")); -prkey.rmempty = true; -prkey.optional=false; - -host = s:option(Value, "endpoint_host", translate("Server Address :"), translate("URL or IP Address of Server")); -host.rmempty = true; -host.optional=false; -host.default=""; - -sport = s:option(Value, "sport", translate("Listen Port :"), translate("Server Listen Port")); -sport.rmempty = true; -sport.optional=false; -sport.default="51820"; - -sip = s:option(Value, "ips", translate("Allowed IP Addresses :"), translate("Comma separated list of IP Addresses that server will accept")); -sip.rmempty = true; -sip.optional=false; -sip.default="10.14.0.0/24"; - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua deleted file mode 100644 index 5fb15ee..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard-server.lua +++ /dev/null @@ -1,130 +0,0 @@ -require("luci.ip") -require("luci.model.uci") - ---luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) - -local m = Map("wireguard", translate("Wireguard Server"), translate("Set up a Wireguard Server")) - -e = m:section(NamedSection, "settings", "") - -m.on_init = function(self) - luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1]) -end - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/wireguard/keygen.sh " .. arg[1] .. "&") -end - -btn = e:option(Button, "_btn", translate(" ")) -btn.inputtitle = translate("Back to Main Page") -btn.inputstyle = "apply" -btn.redirect = luci.dispatcher.build_url( - "admin", "vpn", "wireguard" -) -function btn.write(self, section, value) - luci.http.redirect( self.redirect ) -end - - -local s = m:section( NamedSection, arg[1], "wireguard", translate("Server") ) - -ip = s:option(Value, "addresses", translate("Internal IP Address :")); -ip.rmempty = true; -ip.optional=false; -ip.default="10.14.0.1/32"; -ip.datatype = "ipaddr" - -host = s:option(Value, "endpoint_host", translate("Server Address :"), translate("URL or IP Address of Server")); -host.rmempty = true; -host.optional=false; -host.default="example.wireguard.org"; - -port = s:option(Value, "port", translate("Port :"), translate("Server Listen Port. Default is 51280")); -port.rmempty = true; -port.optional=false; -port.default="51280"; - -ul = s:option(ListValue, "udptunnel", "Enable UDP over TCP :"); -ul:value("0", translate("No")) -ul:value("1", translate("Yes")) -ul.default=0 - -uport = s:option(Value, "udpport", translate("UDP over TCP Port :"), translate("Server Local TCP Port. Default is 54321")); -uport.rmempty = true; -uport.optional=false; -uport.default="54321"; -uport:depends("udptunnel", "1") - -pkey = s:option(DummyValue, "privatekey", translate("Private Key :")); -pkey.optional=false; - -pukey = s:option(DummyValue, "publickey", translate("Public Key :"), translate("Server Public key sent to Clients")); -pukey.optional=false; - -pl = s:option(ListValue, "usepre", "Use PreSharedKey :"); -pl:value("0", translate("No")) -pl:value("1", translate("Yes")) -pl.default=0 - -prkey = s:option(DummyValue, "presharedkey", translate("PreShared Key :"), translate("PreShared Key sent to Client")); -prkey.optional=false; -prkey:depends("usepre", "1") - -bl = s:option(ListValue, "auto", translate("Start on Boot :")); -bl:value("0", translate("No")) -bl:value("1", translate("Yes")) -bl.default="0" - -xbl = s:option(ListValue, "forward", translate("All Traffic Through Tunnel :")); -xbl:value("0", translate("No")) -xbl:value("1", translate("Yes")) -xbl.default="1" - - -b3 = s:option(DummyValue, "blank", " "); - -sx = s:option(Value, "_dmy1", translate(" ")) -sx.template = "wireguard/conf" - -ss = m:section(TypedSection, "custom" .. arg[1], translate("Clients"), translate("Clients of this server")) -ss.anonymous = true -ss.addremove = true - -name = ss:option(Value, "name", translate("Client Name")) -name.optional=false; - -cport = ss:option(Value, "endpoint_port", translate("Listen Port :"), translate("Port sent to Client. Default is 51280")); -cport.rmempty = true; -cport.optional=false; -cport.default=""; - -aip = ss:option(Value, "address", translate("Assigned IP Address :"), translate("IP Address assigned to Client")); -aip.rmempty = true; -aip.optional=false; -aip.default="10.14.0.2/32"; - -dns = ss:option(Value, "dns", translate("DNS Servers :"), translate("Comma separated list of DNS Servers sent to Client")); -dns.rmempty = true; -dns.optional=false; -dns.default=""; - -mtu = ss:option(Value, "mtu", translate("MTU :"), translate("Maximum MTU")); -mtu.rmempty = true; -mtu.optional=false; -mtu.datatype = 'range(1280,1420)'; -mtu.default="1280"; - -aip = ss:option(Value, "allowed_ips", translate("Allowed IP Address :"), translate("Comma separated list of IP Addresses allowed from Client")); -aip.rmempty = true; -aip.optional=false; -aip.default="0.0.0.0/0,::/0"; - -pukey = ss:option(DummyValue, "publickey", translate("Public Key :"), translate("Client Public Key")); -pukey.optional=false; - -pikey = ss:option(DummyValue, "privatekey", translate("Private Key :"), translate("Private Key sent to Client")); -pikey.optional=false; - -b3 = ss:option(DummyValue, "blank", " "); - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua deleted file mode 100644 index 0aab305..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/model/cbi/wireguard.lua +++ /dev/null @@ -1,182 +0,0 @@ -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() -local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have -local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid - -local m = Map("wireguard", translate("Wireguard"), translate("Set up a Wireguard VPN Tunnel on your Router")) - -local s = m:section( TypedSection, "wireguard", translate("Instances"), translate("Below is a list of configured Wireguard Instances and their current state") ) -s.template = "cbi/tblsection" -s.template_addremove = "wireguard/cbi-select-input-add" -s.addremove = true -s.add_select_options = { } - -local cfg = s:option(DummyValue, "config") -function cfg.cfgvalue(self, section) - local file_cfg = self.map:get(section, "client") - if file_cfg == "1" then - s.extedit = luci.dispatcher.build_url("admin", "vpn", "wireguard", "client", "%s") - else - s.extedit = luci.dispatcher.build_url("admin", "vpn", "wireguard", "server", "%s") - end -end - -uci:load("wireguard_recipes") -uci:foreach( "wireguard_recipes", "wireguard_recipe", - function(section) - s.add_select_options[section['.name']] = - section['_description'] or section['.name'] - end -) - -function s.parse(self, section) - local recipe = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".select" - ) - - if recipe and not s.add_select_options[recipe] then - self.invalid_cts = true - else - TypedSection.parse( self, section ) - end -end - -function s.create(self, name) - local recipe = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".select" - ) - local name = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".text" - ) - if #name > 3 and not name:match("[^a-zA-Z0-9_]") then - local s = uci:section("wireguard", "wireguard", name) - if s then - local options = uci:get_all("wireguard_recipes", recipe) - for k, v in pairs(options) do - if k ~= "_role" and k ~= "_description" then - if type(v) == "boolean" then - v = v and "1" or "0" - end - uci:set("wireguard", name, k, v) - end - end - uci:save("wireguard") - uci:commit("wireguard") - if extedit then - luci.http.redirect( self.extedit:format(name) ) - end - end - elseif #name > 0 then - self.invalid_cts = true - end - return 0 -end - -function s.remove(self, name) - local cfg_file = "/etc/openvpn/" ..name.. ".conf" - local auth_file = "/etc/openvpn/" ..name.. ".auth" - if fs.access(cfg_file) then - fs.unlink(cfg_file) - end - if fs.access(auth_file) then - fs.unlink(auth_file) - end - uci:delete("wireguard", name) - uci:save("wireguard") - uci:commit("wireguard") -end - -local port = s:option( DummyValue, "client", translate("Type") ) -function port.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = 0 - end - if val == "1" then - return "Client" - else - return "Server" - end -end - -local addr = s:option( DummyValue, "addresses", translate("IP Addresses") ) -function addr.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - return val or "----" -end - -local auto = s:option( DummyValue, "udptunnel", translate("UDP over TCP") ) -function auto.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = 0 - end - if val == "1" then - return "Yes" - else - return "No" - end -end - -local auto = s:option( DummyValue, "auto", translate("Start on Boot") ) -function auto.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = 0 - end - if val == "1" then - return "Yes" - else - return "No" - end -end - -local active = s:option( DummyValue, "active", translate("Started") ) -function active.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if val == nil then - val = 0 - end - if val == "1" then - return "Yes" - else - return "No" - end -end - -local updown = s:option( Button, "_updown", translate("Start/Stop") ) -updown._state = false -updown.redirect = luci.dispatcher.build_url( - "admin", "vpn", "wireguard" -) -function updown.cbid(self, section) - local file_cfg = self.map:get(section, "active") - if file_cfg == "1" then - pid = 1 - else - pid = nil - end - self._state = pid ~= nil - self.option = self._state and "stop" or "start" - return AbstractValue.cbid(self, section) -end -function updown.cfgvalue(self, section) - self.title = self._state and "stop" or "start" - self.inputstyle = self._state and "reset" or "reload" -end -function updown.write(self, section, value) - if self.option == "stop" then - sys.call("/usr/lib/wireguard/stopvpn.sh %s" % section) - else - sys.call("/usr/lib/wireguard/startvpn.sh %s" % section) - end - luci.http.redirect( self.redirect ) -end - -m:section(SimpleSection).template = "wireguard/wireguard" - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm deleted file mode 100644 index c6cb8ac..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/cbi-select-input-add.htm +++ /dev/null @@ -1,111 +0,0 @@ - - - -<%+wireguard/ovpn_css%> - -
                -
                -

                <%:Template based configuration%>

                -
                -
                - -
                -
                - -
                -
                -
                -
                -
                -

                <%:Conf configuration file upload%>

                -
                -
                - -
                -
                - -
                -
                - -
                -
                -
                -
                - -
                -
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm deleted file mode 100644 index e75e88f..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/conf.htm +++ /dev/null @@ -1,27 +0,0 @@ - - - -
                - - - - - - - -
                   
                -
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm deleted file mode 100644 index 55c0a54..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/ovpn_css.htm +++ /dev/null @@ -1,38 +0,0 @@ - diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm deleted file mode 100644 index 47056fa..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/pageswitch.htm +++ /dev/null @@ -1,30 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<%+openvpn/ovpn_css%> - -
                -

                - <%:Overview%> » - <%=luci.i18n.translatef("Instance \"%s\"", self.instance)%> -

                - <% if self.mode == "basic" then %> - "><%:Switch to advanced configuration%> »

                -


                - <% elseif self.mode == "advanced" then %> - <%:Switch to basic configuration%> »

                -


                - <%:Configuration category%>: - <% for i, c in ipairs(self.categories) do %> - <% if c == self.category then %> - <%=translate(c)%> - <% else %> - "><%=translate(c)%> - <% end %> - <% if next(self.categories, i) then %>|<% end %> - <% end %> - <% end %> -
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm deleted file mode 100644 index 2a1a4b5..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/text_conf.htm +++ /dev/null @@ -1,61 +0,0 @@ -<% - -%> - - - -
                - <%:Paste Configuration File Here%> - - - - -
                - -
                - - - - - - - - - - -
                <%:Instance Name : %>
                <%:Start on Boot : %>
                - -  
                -
                diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm b/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm deleted file mode 100644 index cf7544e..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/lua/luci/view/wireguard/wireguard.htm +++ /dev/null @@ -1,228 +0,0 @@ -<%# - Copyright 2016-2017 Dan Luedtke - Licensed to the public under the Apache License 2.0. --%> - -<% - --%> - - - -

                <%:WireGuard Status%>

                - -
                - -
                - - - - - - -
                -
                <%:Interface %>
                -
                  
                - - - - - - - - - - - - - - - -
                  -
                <%:Configuration%>
                -
                   -
                - <%:Collecting data...%> -
                -
                  -
                <%:Peer%>
                -
                   -
                - <%:Collecting data...%> -
                -
                - - - - - - - -
                -
                <%:Interface %>
                -
                  
                - - - - - - - - - - - - - - - -
                  -
                <%:Configuration%>
                -
                   -
                - <%:Collecting data...%> -
                -
                  -
                <%:Peer%>
                -
                   -
                - <%:Collecting data...%> -
                -
                - -
                - -
                - diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh deleted file mode 100644 index 5c36ca2..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/conf.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/sh - -log() { - modlog "Wireguard Conf" "$@" -} - -name=$1 -file=$2 -auto=$3 -if [ -z $auto ]; then - auto="0" -fi - -extract() { - line=$1 - PD=$(echo "$line" | grep "#") - if [ ! -z "$PD" ]; then - return - fi - PRK=$(echo "$line" | grep "PrivateKey" | tr " " ",") - if [ ! -z "$PRK" ]; then - PrivateKey=$(echo $PRK | cut -d, -f3) - fi - PRK=$(echo "$line" | grep "PublicKey" | tr " " ",") - if [ ! -z "$PRK" ]; then - PublicKey=$(echo $PRK | cut -d, -f3) - fi - PRK=$(echo "$line" | grep "PresharedKey" | tr " " ",") - if [ ! -z "$PRK" ]; then - PreSharedKey=$(echo $PRK | cut -d, -f3) - fi - INTER=$(echo "$line" | grep "WGinterface" | tr " " ",") - if [ ! -z "$INTER" ]; then - wginter=$(echo $INTER | cut -d, -f3) - if [ "$wginter" -gt 1 ]; then - wginter="1" - fi - fi - PRK=$(echo "$line" | grep "Address" | tr " " "#") - if [ ! -z "$PRK" ]; then - if [ -z $Address ]; then - Address=$(echo $PRK | cut -d# -f3) - else - Address=$Address","$(echo $PRK | cut -d# -f3) - fi - fi - PRK=$(echo "$line" | grep "dns" | tr " " "#") - if [ ! -z "$PRK" ]; then - dns=$(echo $PRK | cut -d# -f3) - fi - PRK=$(echo "$line" | grep "DNS" | tr " " "#") - if [ ! -z "$PRK" ]; then - dns=$(echo $PRK | cut -d# -f3) - fi - PRK=$(echo "$line" | grep "ListenPort" | tr " " ",") - if [ ! -z "$PRK" ]; then - listenport=$(echo $PRK | cut -d, -f3) - fi - PRK=$(echo "$line" | grep "AllowedIPs" | tr " " "#") - if [ ! -z "$PRK" ]; then - if [ -z $allowedips ]; then - allowedips=$(echo $PRK | cut -d# -f3) - else - allowedips=$allowedips","$(echo $PRK | cut -d# -f3) - fi - fi - PRK=$(echo "$line" | grep "Endpoint" | tr " " ",") - if [ ! -z "$PRK" ]; then - endpoint=$(echo $PRK | cut -d, -f3) - fi - MTU=$(echo "$line" | grep "MTU" | tr " " ",") - if [ ! -z "$MTU" ]; then - mtu=$(echo $MTU | cut -d, -f3) - fi -} - -listenport="51280" -dns="" -sed -i -e "s!PrivateKey= !PrivateKey=!g" $file -sed -i -e "s!PrivateKey=!PrivateKey = !g" $file -sed -i -e "s!PublicKey= !PublicKey=!g" $file -sed -i -e "s!PublicKey=!PublicKey = !g" $file -sed -i -e "s!PresharedKey= !PresharedKey=!g" $file -sed -i -e "s!PresharedKey=!PresharedKey = !g" $file -sed -i -e "s!Address= !Address=!g" $file -sed -i -e "s!Address=!Address = !g" $file -sed -i -e "s!WGinterface=!WGinterface = !g" $file -sed -i -e "s!WGinterface= !WGinterface = !g" $file -sed -i -e "s!dns= !dns=!g" $file -sed -i -e "s!dns=!dns = !g" $file -sed -i -e "s!DNS= !DNS=!g" $file -sed -i -e "s!DNS=!DNS = !g" $file -sed -i -e "s!ListenPort= !ListenPort=!g" $file -sed -i -e "s!ListenPort=!ListenPort = !g" $file -sed -i -e "s!AllowedIPs= !AllowedIPs=!g" $file -sed -i -e "s!AllowedIPs=!AllowedIPs = !g" $file -sed -i -e "s!Endpoint= !Endpoint=!g" $file -sed -i -e "s!Endpoint=!Endpoint = !g" $file -sed -i -e "s!MTU= !MTU=!g" $file -sed -i -e "s!MTU=!MTU = !g" $file - -while IFS= read -r linex -do - extract "$linex" -done < $file -extract "$linex" -PRK=$(echo "$endpoint" | tr ":" ",") -endpoint=$(echo $PRK | cut -d, -f1) -sport=$(echo $PRK | cut -d, -f2) -if [ -z "$wginter" ]; then - wginter="0" -fi -uci delete wireguard.$name -uci set wireguard.$name=wireguard -uci set wireguard.$name.auto=$auto -uci set wireguard.$name.client="1" -uci set wireguard.$name.active="0" -uci set wireguard.$name.privatekey="$PrivateKey" -uci set wireguard.$name.presharedkey="$PreSharedKey" -uci set wireguard.$name.port="$listenport" -uci set wireguard.$name.addresses="$Address" -uci set wireguard.$name.dns="$dns" -uci set wireguard.$name.wginter="$wginter" -uci set wireguard.$name.publickey="$PublicKey" -uci set wireguard.$name.endpoint_host="$endpoint" -uci set wireguard.$name.ips="$allowedips" -uci set wireguard.$name.name="$name" -uci set wireguard.$name.sport="$sport" -uci set wireguard.$name.mtu="$mtu" -uci set wireguard.$name.persistent_keepalive='25' -uci commit wireguard - -rm -f $file - \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh deleted file mode 100644 index 143abe6..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/create.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Wireguard Conf" "$@" -} - -WG=$(cat /tmp/wginst) - -do_create() { - local config=$1 - - config_get name $config name - if [ -z $name ]; then - name=$config - fi - - echo "----Start Conf File for "$name" ----" >> ${PKI_DIR}/package/wg.conf - echo "[Interface]" >> ${PKI_DIR}/package/wg.conf - config_get privatekey $config privatekey - echo "PrivateKey = "$privatekey >> ${PKI_DIR}/package/wg.conf - config_get address $config address - echo "Address = "$address >> ${PKI_DIR}/package/wg.conf - config_get endpoint_port $config endpoint_port - if [ ! -z $endpoint_port ]; then - echo "ListenPort = "$endpoint_port >> ${PKI_DIR}/package/wg.conf - fi - config_get dns $config dns - if [ ! -z $dns ]; then - echo "DNS = "$dns >> ${PKI_DIR}/package/wg.conf - fi - config_get mtu $config mtu - if [ ! -z $mtu ]; then - echo "MTU = "$mtu >> ${PKI_DIR}/package/wg.conf - fi - config_get wginter $config wginter - if [ -z"$wginter"]; then - wginter=0 - fi - echo "PrivateKey = "$wginter >> ${PKI_DIR}/package/wg.conf - echo " " >> ${PKI_DIR}/package/wg.conf - echo "[Peer]" >> ${PKI_DIR}/package/wg.conf - PUB=$(uci get wireguard."$WG".publickey) - echo "PublicKey = "$PUB >> ${PKI_DIR}/package/wg.conf - USE=$(uci get wireguard."$WG".usepre) - if [ $USE = "1" ]; then - PRE=$(uci get wireguard."$WG".presharedkey) - echo "PresharedKey = "$PRE >> ${PKI_DIR}/package/wg.conf - fi - HOST=$(uci get wireguard."$WG".endpoint_host) - PORT=$(uci get wireguard."$WG".port) - if [ ! -z $PORT ]; then - HOST=$HOST":"$PORT - fi - echo "Endpoint = "$HOST >> ${PKI_DIR}/package/wg.conf - config_get allowed_ips $config allowed_ips - echo "AllowedIPs = "$allowed_ips >> ${PKI_DIR}/package/wg.conf - echo "----EndConf File for "$name" ----" >> ${PKI_DIR}/package/wg.conf - echo " " >> ${PKI_DIR}/package/wg.conf -} - -#PKI_DIR="/tmp/wireguard" -PKI_DIR="/www" -#rm -rfv "$PKI_DIR" -#mkdir -p ${PKI_DIR} -#chmod -R 0777 ${PKI_DIR} -cd ${PKI_DIR} -mkdir -p package -cd .. -chmod -R 0777 ${PKI_DIR}/package -#rm -rfv "/www/package" -#ln -s ${PKI_DIR}/package /www/package - - -rm -f ${PKI_DIR}/package/wg.conf -config_load wireguard -config_foreach do_create custom$WG - -cd ${PKI_DIR}/package - -tar -czf wgconf.tar.gz wg.conf diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh deleted file mode 100644 index 3b30f61..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/keygen.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Wireguard KeyGen" "$@" -} - -WG=$1 -echo "$WG" > /tmp/wginst - -sleep 5 - -EXST=$(uci get wireguard."$WG") -if [ -z $EXST ]; then - uci set wireguard."$WG"="wireguard" - uci commit wireguard -fi - -PRIV=$(uci get wireguard."$WG".privatekey) -if [ -z $PRIV ]; then - umask u=rw,g=,o= - wg genkey | tee /tmp/wgserver.key | wg pubkey > /tmp/wgclient.pub - wg genpsk > /tmp/wg.psk - - WG_KEY="$(cat /tmp/wgserver.key)" # private key - WG_PSK="$(cat /tmp/wg.psk)" # shared key - WG_PUB="$(cat /tmp/wgclient.pub)" # public key to be used on other end - rm -f /tmp/wgserver.key - rm -f /tmp/wg.psk - rm -f /tmp/wgclient.pub - uci set wireguard."$WG".privatekey=$WG_KEY - uci set wireguard."$WG".publickey=$WG_PUB - uci set wireguard."$WG".presharedkey=$WG_PSK - uci commit wireguard -fi - -do_custom() { - local config=$1 - - config_get privatekey $config privatekey - if [ -z "$privatekey" ]; then - umask u=rw,g=,o= - wg genkey | tee /tmp/wgserver.key | wg pubkey > /tmp/wgclient.pub - wg genpsk > /tmp/wg.psk - - WG_KEY="$(cat /tmp/wgserver.key)" # private key - WG_PSK="$(cat /tmp/wg.psk)" # shared key - WG_PUB="$(cat /tmp/wgclient.pub)" # public key to be used on other end - rm -f /tmp/wgserver.key - rm -f /tmp/wg.psk - rm -f /tmp/wgclient.pub - log "$WG_KEY" - uci set wireguard."$config".privatekey=$WG_KEY - uci set wireguard."$config".publickey=$WG_PUB - uci set wireguard."$config".presharedkey=$WG_PSK - uci set wireguard."$config".persistent_keepalive='25' - uci set wireguard."$config".route_allowed_ips='1' - fi -} - -config_load wireguard -config_foreach do_custom custom$WG -uci commit wireguard \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh deleted file mode 100644 index 3e00972..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/startvpn.sh +++ /dev/null @@ -1,323 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Wireguard Start" "$@" -} - -WG=$1 - -chk_zone() { - local config=$1 - - config_get src $config src - config_get dest $config dest - if [ $src = "lan" -a $dest = "wan" ]; then - uci set firewall."$config".dest="wg" - uci commit firewall - fi -} - -do_dns() { - cdns=$1 - local ifce=$2 - ldns=$(uci -q get network.wg$ifce.dns) - ex=$(echo "$ldns" | grep "$cdns") - if [ -z $ex ]; then - log "Add DNS $cdns to WG$ifce" - uci add_list network.wg$ifce.dns="$cdns" - uci commit network - /etc/init.d/network reload - fi -} - -do_port() { - PORT=$1 - udp=$2 - # look for rule for this port - INB="inbound"$PORT$udp - RULE=$(uci -q get firewall.$INB) - if [ -z $RULE ]; then - uci set firewall.$INB=rule - uci set firewall.$INB.name=$INB - uci set firewall.$INB.target=ACCEPT - uci set firewall.$INB.src=* - uci set firewall.$INB.proto=$udp - uci set firewall.$INB.dest_port=$PORT - uci commit firewall - /etc/init.d/firewall reload - fi -} - -do_delete() { - local config=$1 - - uci delete network.$1 -} - -create_speer() { - local config=$1 - - uci set network.$config="wireguard_wg1" - - config_get persistent_keepalive $config persistent_keepalive - uci set network.$config.persistent_keepalive="$persistent_keepalive" - config_get route_allowed_ips $config route_allowed_ips - uci set network.$config.route_allowed_ips="$route_allowed_ips" - config_get publickey $config publickey - uci set network.$config.public_key="$publickey" - usepre=$(uci -q get wireguard.$WG.usepre) - log "$usepre" - if [ $usepre = "1" ]; then - presharedkey=$(uci -q get wireguard.$WG.presharedkey) - log "$presharedkey" - uci set network.$config.preshared_key="$presharedkey" - fi - config_get allowed_ips $config allowed_ips - allowed_ips=$allowed_ips"," - ips=$(echo $allowed_ips | cut -d, -f1) - i=1 - while [ ! -z $ips ] - do - uci add_list network.$config.allowed_ips="$ips" - i=$((i+1)) - ips=$(echo $allowed_ips | cut -d, -f$i) - done - -} - -create_cpeer() { - local config=$1 - local ifce=$2 - - uci set network.$config="wireguard_wg$ifce" - - publickey=$(uci -q get wireguard."$config".publickey) - uci set network.$config.public_key="$publickey" - presharedkey=$(uci -q get wireguard."$WG".presharedkey) - if [ ! -z $presharedkey ]; then - uci set network.$config.preshared_key="$presharedkey" - fi - persistent_keepalive=$(uci -q get wireguard."$config".persistent_keepalive) - if [ -z $persistent_keepalive ]; then - persistent_keepalive=25 - fi - uci set network.$config.persistent_keepalive="$persistent_keepalive" - route_allowed_ips=1 - uci set network.$config.route_allowed_ips="$route_allowed_ips" - - if [ $UDP = 1 ]; then - endpoint_host="127.0.0.1" - uci set network.$config.endpoint_host="$endpoint_host" - sport=$(uci -q get wireguard."$config".port) - if [ -z $sport ]; then - sport="54321" - fi - uci set network.$config.endpoint_port="$sport" - else - endpoint_host=$(uci -q get wireguard."$config".endpoint_host) - uci set network.$config.endpoint_host="$endpoint_host" - sport=$(uci -q get wireguard."$config".sport) - if [ -z $sport ]; then - sport="51280" - fi - uci set network.$config.endpoint_port="$sport" - fi - - ips=$(uci -q get wireguard."$config".ips)"," - cips=$(echo $ips | cut -d, -f1) - i=1 - while [ ! -z $cips ] - do - uci add_list network.$config.allowed_ips="$cips" - i=$((i+1)) - cips=$(echo $ips | cut -d, -f$i) - done -} - -handle_server() { - config_foreach do_delete wireguard_wg1 - - uci delete network.wg1 - uci set network.wg1="interface" - uci set network.wg1.proto="wireguard" - - auto=$(uci -q get wireguard."$WG".auto) - if [ -z $auto ]; then - auto="0" - fi - uci set network.wg1.auto="$auto" - - port=$(uci -q get wireguard."$WG".port) - if [ -z $port ]; then - port="51280" - fi - uci set network.wg1.listen_port="$port" - do_port $port udp - - privatekey=$(uci -q get wireguard."$WG".privatekey) - uci set network.wg1.private_key="$privatekey" - - ips=$(uci -q get wireguard."$WG".addresses)"," - cips=$(echo $ips | cut -d, -f1) - i=1 - while [ ! -z $cips ] - do - uci add_list network.wg1.addresses="$cips" - i=$((i+1)) - cips=$(echo $ips | cut -d, -f"$i") - if [ -z $cips ]; then - break - fi - done - - config_load wireguard - config_foreach create_speer custom$WG - - uci commit network -} - -handle_client() { - ifce=$1 - config_foreach do_delete wireguard_wg$ifce - - uci delete network.wg$ifce - uci set network.wg$ifce="interface" - uci set network.wg$ifce.proto="wireguard" - - auto=$(uci -q get wireguard."$WG".auto) - if [ -z $auto ]; then - auto="0" - fi - uci set network.wg$ifce.auto="$auto" - mtu=$(uci -q get wireguard."$WG".mtu) - if [ ! -z $mtu ]; then - uci set network.wg$ifce.mtu="$mtu" - fi - dns=$(uci -q get wireguard."$WG".dns) - if [ ! -z $dns ]; then - do_dns $dns $ifce - fi - port=$(uci -q get wireguard."$WG".port) - if [ -z $port ]; then - port="51280" - fi - uci set network.wg$ifce.listen_port="$port" - do_port $port udp - - privatekey=$(uci -q get wireguard."$WG".privatekey) - uci set network.wg$ifce.private_key="$privatekey" - - ips=$(uci -q get wireguard."$WG".addresses)"," - cips=$(echo $ips | cut -d, -f1) - i=1 - while [ ! -z "$cips" ] - do - uci add_list network.wg$ifce.addresses="$cips" - i=$((i+1)) - cips=$(echo "$ips" | cut -d, -f"$i") - if [ -z "$cips" ]; then - break - fi - done - uci add_list network.wg$ifce.addresses="::/0" - - create_cpeer $WG $ifce - - uci commit network -} - -udp_server() { - local config=$1 - udpport=$(uci -q get wireguard."$WG".udpport) - if [ -z $udpport ]; then - udpport="54321" - fi - port=$(uci -q get wireguard."$WG".port) - if [ -z $port ]; then - port="54321" - fi - do_port $udpport tcp - udptunnel -s -v "0.0.0.0:"$udpport "127.0.0.1:"$port & - #log "udptunnel -s -v 0.0.0.0:$udpport 127.0.0.1:$port" -} - -udp_client() { - local config=$1 - port=$(uci -q get wireguard."$WG".port) - if [ -z $port ]; then - port="54321" - fi - endpoint_host=$(uci -q get wireguard.$WG.endpoint_host) - sport=$(uci -q get wireguard.$WG.sport) - if [ -z $sport ]; then - sport="51280" - fi - - udptunnel "127.0.0.1:"$port $endpoint_host":"$sport & - #log "udptunnel 127.0.0.1:$port $endpoint_host:$sport" -} - -forward=$(uci -q get wireguard."$WG".forward) -if [ "$forward" != "0" ]; then - config_load firewall - config_foreach chk_zone forwarding -else - uci set firewall.wgwforward=forwarding - uci set firewall.wgwforward.dest="wan" - uci set firewall.wgwforward.src="wg" - - uci set firewall.wwgforward=forwarding - uci set firewall.wwgforward.dest="wg" - uci set firewall.wwgforward.src="wan" - - uci set firewall.lwgforward=forwarding - uci set firewall.lwgforward.dest="wg" - uci set firewall.lwgforward.src="lan" - - uci set firewall.wglforward=forwarding - uci set firewall.wglforward.dest="lan" - uci set firewall.wglforward.src="wg" - uci commit firewall -fi -etc/init.d/firewall restart - -config_load network -SERVE=$(uci -q get wireguard."$WG".client) -if [ $SERVE = "0" ]; then - running=$(uci -q get wireguard.settings.server) - if [ $running = 1 ]; then - exit 0 - fi - UDP=$(uci -q get wireguard."$WG".udptunnel) - if [ $UDP = 1 ]; then - udp_server $WG - fi - handle_server - uci commit network - ifup wg1 - sleep 2 - uci set wireguard.settings.server="1" -else - running=$(uci -q get wireguard.settings.client) - log "Client running $running" - - INTER=$(uci -q get wireguard."$WG".wginter) - if [ -z "$INTER" ]; then - INTER=0 - fi - UDP=$(uci -q get wireguard."$WG".udptunnel) - if [ $UDP = 1 ]; then - udp_client $WG - fi - handle_client $INTER - uci commit network - log "Start Interface" - ifup wg$INTER - sleep 2 - uci set wireguard.settings.client="1" -fi - -uci set wireguard."$WG".active="1" -uci commit wireguard - diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh deleted file mode 100644 index 9e56adf..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/stopvpn.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Wireguard Stop" "$@" -} - -chk_zone() { - local config=$1 - - config_get src $config src - config_get dest $config dest - if [ $src = "lan" -a $dest = "wg" ]; then - uci set firewall."$config".dest="wan" - uci commit firewall - fi -} - -WG=$1 - -forward=$(uci -q get wireguard."$WG".forward) -if [ "$forward" != "0" ]; then - config_load firewall - config_foreach chk_zone forwarding -else - uci delete firewall.wgwforward - uci delete firewall.wwgforward - uci delete firewall.lwgforward - uci delete firewall.wglforward - uci commit firewall -fi -/etc/init.d/firewall restart - -SERVE=$(uci get wireguard."$WG".client) -if [ $SERVE = "0" ]; then - ifdown wg1 - uci set wireguard.settings.server="0" - uci delete network.wg1 - uci set network.wg1=interface - uci set network.wg1.proto="wireguard" - uci set network.wg1.auto="0" - uci set network.wg1.private_key="" - uci set network.wg1.listen_port="" - uci add_list network.wg1.addresses="" - uci commit network -else - INTER=$(uci -q get wireguard."$WG".wginter) - if [ -z "$INTER" ]; then - INTER=0 - fi - ifdown wg$INTER - uci set wireguard.settings.client="0" - uci delete network.wg$INTER - uci set network.wg$INTER=interface - uci set network.wg$INTER.proto="wireguard" - uci set network.wg$INTER.auto="0" - uci set network.wg$INTER.private_key="" - uci set network.wg$INTER.listen_port="" - uci add_list network.wg$INTER.addresses="" - uci commit network -fi -UDP=$(uci get wireguard."$WG".udptunnel) -if [ $UDP = 1 ]; then - PID=$(ps |grep "udptunnel" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID -fi - -uci set wireguard."$WG".active="0" -uci commit wireguard - -/etc/init.d/wireguard stop \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh b/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh deleted file mode 100644 index 2f5a622..0000000 --- a/rooter/0optionalapps/ext-wireguard/files/usr/lib/wireguard/text.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Wireguard TextConf" "$@" -} - -conf1=$1 -conf=$(echo $conf1) -conf=$(echo "$conf" | tr "?" "~") - -boot=$(echo "$conf" | cut -d~ -f1) -iname=$(echo "$conf" | cut -d~ -f2) -conf=$(echo "$conf1" | tr "?" "~") -confile=$(echo "$conf" | cut -d~ -f3) - -echo "$confile" > /tmp/confile - -/usr/lib/wireguard/conf.sh $iname /tmp/confile $boot \ No newline at end of file diff --git a/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard.png b/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard.png deleted file mode 100644 index 34f85d8486f4499a7ed215d5a20057f4048a9024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22762 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 YsyNG(0Rzr1YRU?j7+M$<>$@KPADp!95dZ)H diff --git a/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard_disabled.png b/rooter/0optionalapps/ext-wireguard/files/www/luci-static/resources/icons/wireguard_disabled.png deleted file mode 100644 index ccfb7aece3b8a4219681262fe78d78f2c477c6bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23205 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 diff --git a/rooter/0optionalapps/ext-zerotier/Makefile b/rooter/0optionalapps/ext-zerotier/Makefile deleted file mode 100644 index b7cfa94..0000000 --- a/rooter/0optionalapps/ext-zerotier/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-zerotier -PKG_VERSION:=4.500 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-zerotier - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - DEPENDS:=+zerotier - TITLE:=Install scripts for Zerotier - PKGARCH:=all -endef - -define Package/ext-zerotier/description - Install scripts for Zerotier -endef - - -define Build/Compile -endef - -define Package/ext-zerotier/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,ext-zerotier)) diff --git a/rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire b/rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire deleted file mode 100644 index 05b8693..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/etc/init.d/zerofire +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh /etc/rc.common -. /lib/functions.sh -# Copyright (C) 2006 OpenWrt.org - -START=91 - -log() { - logger -t "ZeroTier Init.d : " "$@" -} - -check_config () { - WW=$(uci get firewall.zerozone) - if [ -z $WW ]; then - uci set firewall.zerozone=zone - uci set firewall.zerozone.name="zerotier" - uci set firewall.zerozone.forward="REJECT" - uci set firewall.zerozone.output="ACCEPT" - uci set firewall.zerozone.input="ACCEPT" - uci set firewall.zerozone.device="zt+" - uci set firewall.zerozone.masq="1" - uci set firewall.zerozone.mtu_fix="1" - - uci set firewall.zlzforward=forwarding - uci set firewall.zlzforward.dest="zerotier" - uci set firewall.zlzforward.src="lan" - - uci set firewall.zzlforward=forwarding - uci set firewall.zzlforward.dest="lan" - uci set firewall.zzlforward.src="zerotier" - uci commit firewall - /etc/init.d/firewall restart - fi -} - -start() { - check_config -} \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier b/rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier deleted file mode 100644 index eee1ac9..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/etc/uci-defaults/64-zerotier +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh /etc/rc.common - -id=$(uci -q get custom.zerotier.networkid) -uci delete zerotier.zerotier.join -uci add_list zerotier.zerotier.join=$id -uci commit zerotier -/etc/init.d/zerotier restart diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua deleted file mode 100644 index 74c997b..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/controller/zerotier.lua +++ /dev/null @@ -1,62 +0,0 @@ -module("luci.controller.zerotier", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local fs = require "nixio.fs" - local lock = luci.model.uci.cursor():get("custom", "menu", "full") - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - if lock == "1" then - if fs.stat("/etc/config/zerotier") then - local page - if (multilock == "1" and rootlock == "1") then - page = entry({"admin", "adminmenu", "zerotier"}, template("zerotier/zerotier"), translate("Zerotier"), 7) - page.dependent = true - else - page = entry({"admin", "adminmenu", "zerotier"}, template("zerotier/zerotier"), translate("---Router ID"), 7) - page.dependent = true - end - end - end - end - - entry({"admin", "services", "getid"}, call("action_getid")) - entry({"admin", "services", "sendid"}, call("action_sendid")) - entry({"admin", "services", "get_ids"}, call("action_get_ids")) -end - -function action_getid() - local rv = {} - id = luci.model.uci.cursor():get("zerotier", "zerotier", "join") - rv["netid"] = id - secret = luci.model.uci.cursor():get("zerotier", "zerotier", "secret") - if secret == nil then - secret = "xxxxxxxxxx" - end - rv["routerid"] = string.sub(secret,1,10) - rv["password"] = luci.model.uci.cursor():get("custom", "zerotier", "password") - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_sendid() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/zerotier/netid.sh 1 " .. set) -end - -function action_get_ids() - local rv = {} - id = luci.model.uci.cursor():get("zerotier", "zerotier", "join") - rv["netid"] = id - secret = luci.model.uci.cursor():get("zerotier", "zerotier", "secret") - if secret ~= nil then - rv["routerid"] = string.sub(secret,1,10) - else - rv["routerid"] = "xxxxxxxxxx" - end - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm deleted file mode 100644 index 47fd4b2..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/admin_status/index/zero.htm +++ /dev/null @@ -1 +0,0 @@ -<%+zerotier/zerotier1%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm deleted file mode 100644 index 2e7e15b..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier.htm +++ /dev/null @@ -1,182 +0,0 @@ -<%+header%> -<% -local sys = require "luci.sys" -local utl = require "luci.util" -local fs = require "nixio.fs" - -function showicon(lck) - if lck == 0 then - return resource .. "/icons/unlock1.png" - else - return resource .. "/icons/lock1.png" - end -end - --%> - - - -
                -
                -

                <%:Router ID (Zerotier)%>

                -
                - - - - -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                - -
                -
                -<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm b/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm deleted file mode 100644 index dfb07b6..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/usr/lib/lua/luci/view/zerotier/zerotier1.htm +++ /dev/null @@ -1,22 +0,0 @@ - - -
                - <%:Router Info%> - - - -
                <%:Network ID%><%:Loading%> Collecting data...
                <%:Router ID%>
                -
                - diff --git a/rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh b/rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh deleted file mode 100644 index 8993552..0000000 --- a/rooter/0optionalapps/ext-zerotier/files/usr/lib/zerotier/netid.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "NetID" "$@" -} - -ID=$2 - -log "$ID" - -if [ $ID = "xxxxxxxxxxxxxxxx" ]; then - uci set zerotier.zerotier.enabled='0' -else - uci set zerotier.zerotier.enabled='1' -fi - -uci delete zerotier.zerotier.join -uci add_list zerotier.zerotier.join=$ID -uci commit zerotier -/etc/init.d/zerotier restart diff --git a/rooter/0optionalapps/extramenu/Makefile b/rooter/0optionalapps/extramenu/Makefile deleted file mode 100644 index 8896ae0..0000000 --- a/rooter/0optionalapps/extramenu/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=extramenu -PKG_VERSION:=4.500 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/extramenu - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Install scripts for Extra menus - PKGARCH:=all -endef - -define Package/extramenu/description - Install scripts for Extra menus -endef - - -define Build/Compile -endef - -define Package/extramenu/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,extramenu)) diff --git a/rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu b/rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu deleted file mode 100644 index d4b7188..0000000 --- a/rooter/0optionalapps/extramenu/files/etc/init.d/fullmenu +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=88 - -log() { - logger -t "FULL MENU" "$@" -} - -start() -{ - df=$(uci -q get custom.menu.default) - if [ -z $df ]; then - df=0 - fi - uci set custom.menu.full=$df - uci set custom.menu.enabled='1' - uci commit custom -} diff --git a/rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh b/rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh deleted file mode 100644 index d5963e8..0000000 --- a/rooter/0optionalapps/extramenu/files/usr/lib/fullmenu/setmenu.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Menu Change" "$@" -} - -full=$1 -source /etc/openwrt_release -twone=$(echo "$DISTRIB_RELEASE" | grep "21.02") - -if [ $full = "0" ]; then - fv="1" -else - fv="0" -fi -uci set custom.menu.full=$fv -uci commit custom \ No newline at end of file diff --git a/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua b/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua deleted file mode 100644 index 67488c4..0000000 --- a/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/controller/fullmenu.lua +++ /dev/null @@ -1,39 +0,0 @@ -module("luci.controller.fullmenu", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - entry({"admin", "adminmenu"}, firstchild(), translate("Administration"), 24).dependent=false - local df = luci.model.uci.cursor():get("custom", "menu", "default") - if df == '0' then - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - page = entry({"admin", "adminmenu", "fullmenu"}, template("fullmenu/fullmenu"), translate("Unlock / Lock Menus"), 5) - page.dependent = true - end - end - - entry({"admin", "menu", "getmenu"}, call("action_getmenu")) - entry({"admin", "menu", "setmenu"}, call("action_setmenu")) - -end - -function action_getmenu() - local rv = {} - id = luci.model.uci.cursor():get("custom", "menu", "full") - rv["full"] = id - password = luci.model.uci.cursor():get("custom", "menu", "password") - rv["password"] = password - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_setmenu() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/fullmenu/setmenu.sh " .. set) - -end \ No newline at end of file diff --git a/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm b/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm deleted file mode 100644 index 9511a60..0000000 --- a/rooter/0optionalapps/extramenu/files/usr/lib/lua/luci/view/fullmenu/fullmenu.htm +++ /dev/null @@ -1,181 +0,0 @@ -<%+header%> -<% -local sys = require "luci.sys" -local utl = require "luci.util" -local fs = require "nixio.fs" - -function showicon(lck) - if lck == 0 then - return resource .. "/icons/unlock1.png" - else - return resource .. "/icons/lock1.png" - end -end - --%> - - - -
                -
                -

                <%:Unlock or Lock Administrative Menus%>

                -
                - - - - -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                - -
                -
                -<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile b/rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile deleted file mode 100644 index e6383bd..0000000 --- a/rooter/0optionalapps/luci-app-dnsmasq-ipset/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-dnsmasq-ipset -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/luci-app-dnsmasq-ipset - SECTION:=luci - CATEGORY:=LuCI - DEPENDS:=+dnsmasq-full - SUBMENU:=3. Applications - TITLE:=support for IP Set settings - PKGARCH:=all -endef - -define Package/luci-app-dnsmasq-ipset/description - Helper scripts for IP Set settings -endef - - -define Build/Compile -endef - -define Package/luci-app-dnsmasq-ipset/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,luci-app-dnsmasq-ipset)) diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset deleted file mode 100644 index 83ec840..0000000 --- a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/config/dnsmasq-ipset +++ /dev/null @@ -1,5 +0,0 @@ -config ipsets - option ipset_name 'netflix' - option enabled '0' - list managed_domain 'netflix.com' - list managed_domain 'netflix.ca' \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset deleted file mode 100644 index a993efd..0000000 --- a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/etc/init.d/dnsmasq-ipset +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh /etc/rc.common -# Author Qier LU - -START=55 - -DNSMASQ="/etc/dnsmasq.conf" - -gen_config_file() { - local section="${1}" - config_get ipset_name "${section}" "ipset_name" - sname="#$ipset_name-1" - ename="#$ipset_name-2" - sed -i "/$sname/,/$ename/d" "$DNSMASQ" - config_get enabled "${section}" "enabled" - if [ -z $enabled ]; then - enabled=0 - fi - if [ ${enabled} -eq 0 ] - then - return - fi - - handle_domain() { - local domain="${1}" - ipline=$ipline"${domain}/" - } - - ipline="ipset=/" - echo "#$ipset_name-1" >> "$DNSMASQ" - config_list_foreach "${section}" "managed_domain" handle_domain - echo "$ipline${ipset_name}" >> "$DNSMASQ" - echo "#$ipset_name-2" >> "$DNSMASQ" - ipset -N -exist "$ipset_name" iphash - /etc/init.d/dnsmasq reload -} - -gen_config_files() { - config_load 'dnsmasq-ipset' - config_foreach gen_config_file 'ipsets' -} - -start() { - gen_config_files -} - -reload() { - sleep 5 - gen_config_files -} diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua deleted file mode 100644 index d0a49b0..0000000 --- a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/controller/dnsmasq-ipset.lua +++ /dev/null @@ -1,12 +0,0 @@ - --- Auther Qier LU - -module("luci.controller.dnsmasq-ipset", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/dnsmasq-ipset") then - return - end - - entry({"admin", "network", "dnsmasq-ipset"}, cbi("dnsmasq-ipset"), _("DNSmasq IP-Set"), 60).dependent = true -end diff --git a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua b/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua deleted file mode 100644 index fe6fff5..0000000 --- a/rooter/0optionalapps/luci-app-dnsmasq-ipset/files/usr/lib/lua/luci/model/cbi/dnsmasq-ipset.lua +++ /dev/null @@ -1,24 +0,0 @@ --- Auther Qier LU - -local m, s, o, p - -m = Map("dnsmasq-ipset", translate("DNSmasq IPSet"), translate("IPSet lists for DNSMasq-full")) - -m.on_after_save = function(self) - luci.sys.call("/etc/init.d/dnsmasq-ipset reload &") -end - -s = m:section(TypedSection, "ipsets", translate("IPSet Lists")) -s.anonymous = true -s.addremove = true - -o = s:option(Value, "ipset_name", translate("IPSet Name")) -o.placeholder = "target ipset" -o.default = "rooter" -o.rmempty = false - -o = s:option(Flag, "enabled", translate("Enabled")) - -o = s:option(DynamicList, "managed_domain", translate("Managed Domain List")) - -return m diff --git a/rooter/0optionalapps/luci-app-hotspot/Makefile b/rooter/0optionalapps/luci-app-hotspot/Makefile deleted file mode 100644 index eedaaf3..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-hotspot -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/luci-app-hotspot - SECTION:=luci - CATEGORY:=LuCI - DEPENDS:=+iw +iwinfo - SUBMENU:=3. Applications - TITLE:=support for Wifi Hotspot Manager - PKGARCH:=all -endef - -define Package/luci-app-hotspot/description - Helper scripts to enable Wifi Hotspot Manager -endef - - -define Build/Compile -endef - -define Package/luci-app-hotspot/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,luci-app-hotspot)) diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate b/rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate deleted file mode 100644 index 23b3751..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/etc/config/travelmate +++ /dev/null @@ -1,17 +0,0 @@ - -config travelmate 'global' - option trm_debug '1' - option trm_maxwait '20' - option trm_maxretry '3' - option trm_iw '1' - option trm_auto '1' - option radio0 '2.4 Ghz' - option radio1 '5.8 Ghz' - option radcnt '2' - option reconn '1' - option connecting '0' - option ssid '5' - option trm_enabled '0' - option lost '0' - option delay '15' - diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface b/rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface deleted file mode 100644 index c075669..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/etc/hotplug.d/iface/99-travelmate-iface +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -wif=$(uci -q get travelmate.global.freq) -if [ "$ACTION" = ifup -a "$INTERFACE" = "wwan$wif" ]; then - exit 1 -fi - -if [ "$ACTION" = ifdown -a "$INTERFACE" = "wwan$wif" ]; then - wifilog "HOTSPOT" "hotplug (iface): action='$ACTION' interface='$INTERFACE'" - conn=$(uci -q get travelmate.global.connecting) - if [ "$conn" != "1" ]; then - uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" - uci -q set wireless.wwan$wif.encryption="none" - uci -q set wireless.wwan$wif.key= - uci -q set wireless.wwan$wif.disabled=1 - uci -q commit wireless - wifilog "HOTSPOT" "Lost Connection" - ubus call network reload - disa=$(uci -q get travelmate.global.ssid) - # check for disconnect or lost connection - if [ "$disa" != "7" ]; then - uci set travelmate.global.ssid="9" # lost connection - reconn=$(uci -q get travelmate.global.reconn) - if [ "$reconn" != "0" ]; then - lost=$(uci -q get travelmate.global.lost) - if [ $reconn -eq 99 ]; then - lost="1" - fi - if [ $lost -le $reconn ]; then - let lost=$lost+1 - uci set travelmate.global.lost=$lost - uci set travelmate.global.delay="30" - uci commit travelmate - sleep 10 - /usr/lib/hotspot/travelmate.sh & - exit 0 - fi - fi - fi - uci set travelmate.global.trm_enabled="0" - uci commit travelmate - fi - - debug="$(uci -q get travelmate.global.trm_debug)" - if [ $debug = "1" ]; then - wifilog "HOTSPOT" "hotplug (iface): action='$ACTION' interface='$INTERFACE'" - fi -fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate b/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate deleted file mode 100644 index 565844b..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/travelmate +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh /etc/rc.common - -. /lib/functions.sh - -START=98 - -log() { - wifilog "Hotspot Initialize" "$@" -} - -do_zone() { - local config=$1 - local name - local network - - config_get name $1 name - config_get network $1 network - newnet="$network" - if [ $name = wan ]; then - WWAN=$(echo "$network" | grep "wwan2") - if [ -z "$WWAN" ]; then - newnet="$newnet wwan2 wwan5" - uci_set firewall "$config" network "$newnet" - uci_commit firewall - /etc/init.d/firewall restart - fi - fi -} - -do_radio() { - local config=$1 - local channel - local hwmode - - config_get channel $1 channel - config_get hwmode $1 hwmode - if [ $hwmode = "11g" ]; then - w2=$(uci -q get wireless.wwan2.device) - if [ -z $w2 ]; then - uci set wireless.wwan2=wifi-iface - uci set wireless.wwan2.device=$config - uci set wireless.wwan2.network="wwan2" - uci set wireless.wwan2.mode="sta" - uci set wireless.wwan2.ssid="Hotspot Manager Interface" - uci set wireless.wwan2.encryption="none" - uci set wireless.wwan2.disabled="1" - uci commit wireless - fi - else - w2=$(uci -q get wireless.wwan5.device) - if [ -z $w2 ]; then - uci set wireless.wwan5=wifi-iface - uci set wireless.wwan5.device=$config - uci set wireless.wwan5.network="wwan5" - uci set wireless.wwan5.mode="sta" - uci set wireless.wwan5.ssid="Hotspot Manager Interface" - uci set wireless.wwan5.encryption="none" - uci set wireless.wwan5.disabled="1" - uci commit wireless - fi - fi -} - -start() -{ -log "Hotspot Firewall" - - PRO=$(uci get network.wwan2.proto) - if [ -z $PRO ]; then - uci set network.wwan2=interface - uci set network.wwan2.proto=dhcp - uci set network.wwan2.metric='2' - uci set network.wwan26=interface - uci set network.wwan26.proto=dhcpv6 - uci set network.wwan26.metric='2' - uci set network.wwan5=interface - uci set network.wwan5.proto=dhcp - uci set network.wwan5.metric='2' - uci set network.wwan56=interface - uci set network.wwan56.proto=dhcpv6 - uci set network.wwan56.metric='2' - uci commit network - fi - config_load firewall - config_foreach do_zone zone - config_load wireless - config_foreach do_radio wifi-device - uci set travelmate.global.lost="0" - uci set travelmate.global.delay="30" - uci set travelmate.global.state='0' - uci commit travelmate -} - - diff --git a/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot b/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot deleted file mode 100644 index f610bee..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/etc/init.d/zhot +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh /etc/rc.common - -. /lib/functions.sh - -START=99 - -log() { - wifilog "Z-Hotspot " "$@" -} - -start() -{ - uci set travelmate.global.lost="0" - uci set travelmate.global.delay="30" - uci commit travelmate - /usr/lib/hotspot/travelmate.sh & -} diff --git a/rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot b/rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot deleted file mode 100644 index 5ed46ef..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/lib/upgrade/keep.d/hotspot +++ /dev/null @@ -1 +0,0 @@ -/etc/hotspot diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall b/rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall deleted file mode 100644 index 3802082..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/bin/hkillall +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -LOOKFOR=$1 -KILLLIST=$(ps | grep $LOOKFOR) -echo "$KILLLIST" | while read line; do - if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then - PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") - kill $PIDV - fi -done \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh deleted file mode 100644 index a214c8a..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/band.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -BAND=$1 -if [ $BAND = "1" ]; then - BAND=2 -else - BAND=5 -fi - -/usr/lib/hotspot/enable.sh 0 - -uci set travelmate.global.freq=$BAND -uci set travelmate.global.ssid="6" -uci commit travelmate - -result=`ps | grep -i "travelmate.sh" | grep -v "grep" | wc -l` -if [ $result -ge 1 ] -then - wifilog "Band Change" "Travelmate already running" -else - /usr/lib/hotspot/travelmate.sh & -fi -uci set travelmate.global.ssid="Hotspot Manager Interface" -uci commit travelmate -exit 0 \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh deleted file mode 100644 index 83d87ef..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/copyhot.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -if [ -f "/tmp/hot" ]; then - rm -f /etc/hotspot - while IFS='|' read -r ssid encrypt key flag - do - echo $ssid"|"$encrypt"|"$key >> /etc/hotspot - done <"/tmp/hot" -fi diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh deleted file mode 100644 index 93e2f67..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/dis_hot.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -wif=$(uci -q get travelmate.global.freq) -rm -f /tmp/hotman -uci set travelmate.global.ssid="7" -uci set travelmate.global.state='' -uci set travelmate.global.bssid="" -uci set travelmate.global.key='' -uci commit travelmate -uci -q set wireless.wwan$wif.disabled=1 -uci set wireless.wwan$wif.ssid="Hotspot Manager Interface" -uci -q commit wireless -/etc/init.d/network reload - diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh deleted file mode 100644 index e2b645f..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/enable.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -SET=$1 - -uci set travelmate.global.trm_enabled=$SET -uci commit travelmate - -wif=$(uci -q get travelmate.global.freq) - -if [ $SET = "1" ]; then - wifilog "Enable" "Connect Hotspot" - AU=$(uci get travelmate.global.trm_auto) - hkillall travelmate.sh - if [ $AU = "1" ]; then - uci set travelmate.global.ssid="8" - uci set travelmate.global.bssid="" - uci set travelmate.global.state='' - uci set travelmate.global.key='' - uci commit travelmate - uci -q set wireless.wwan$wif.encryption="none" - uci -q set wireless.wwan$wif.key= - uci set wireless.wwan$wif.ssid="Hotspot Manager Interface" - uci -q commit wireless - /usr/lib/hotspot/travelmate.sh & - fi -else - wifilog "Enable" "Disconnect Hotspot" - hkillall travelmate.sh - rm -f /tmp/hotman - uci set travelmate.global.ssid="7" - uci set travelmate.global.state="0" - uci set travelmate.global.key='' - uci set travelmate.global.bssid="" - uci set travelmate.global.trm_enabled="0" - uci commit travelmate - uci -q set wireless.wwan$wif.disabled=1 - uci set wireless.wwan$wif.ssid="Hotspot Manager Interface" - uci -q commit wireless - ubus call network.interface.wwan down - ubus call network reload -fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh deleted file mode 100644 index c42fb01..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/getssid.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -wif=$(uci -q get travelmate.global.freq) -RADIO=$(uci get wireless.wwan$wif.device) -ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" -if [ -z $ap_list ]; then - wifi up - ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" -fi - -rm -f /tmp/ssidlist -for ap in ${ap_list} -do - iwinfo "${ap}" scan >> /tmp/ssidlist -done diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh deleted file mode 100644 index 77df595..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/inrange.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -. "/lib/functions.sh" - -log() { - wifilog "In Range" "$@" -} - -rm -f /tmp/hot1 -cnt=0 -trm_ifstatus="false" -while [ ${cnt} -lt 20 ] -do - trm_ifstatus="$(ubus -S call network.wireless status | jsonfilter -l1 -e '@.*.up')" - if [ "${trm_ifstatus}" = "true" ] - then - break - fi - cnt=$((cnt+1)) - sleep 1 -done - -wif=$(uci -q get travelmate.global.freq) -RADIO=$(uci get wireless.wwan$wif.device) -ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" - -trm_scanner="$(which iw)" -for ap in ${ap_list} -do - ssid_list="$(${trm_scanner} dev "${ap}" scan 2>/dev/null > /tmp/scan - cat /tmp/scan | awk '/SSID: /{if(!seen[$0]++){printf "\"";for(i=2; i<=NF; i++)if(i==2)printf $i;else printf " "$i;printf "\" "}}')" - - if [ -n "${ssid_list}" ] - then - if [ -f "/etc/hotspot" ]; then - while IFS='|' read -r ssid encrypt key - do - ssidq="\"$ssid\"" - if [ -n "$(printf "${ssid_list}" | grep -Fo "${ssidq}")" ] - then - echo $ssid"|"$encrypt"|"$key"|1" >> /tmp/hot1 - else - echo $ssid"|"$encrypt"|"$key"|0" >> /tmp/hot1 - fi - done <"/etc/hotspot" - fi - else - if [ -f "/etc/hotspot" ]; then - while IFS='|' read -r ssid encrypt key - do - echo $ssid"|"$encrypt"|"$key"|0" >> /tmp/hot1 - done <"/etc/hotspot" - fi - fi -done -if [ -f "/tmp/hot1" ]; then - mv -f /tmp/hot1 /tmp/hot -fi - - diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh deleted file mode 100644 index 63323d4..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/manual.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -MAN="$1" - -hkillall travelmate.sh - -/usr/lib/hotspot/dis_hot.sh -echo "$MAN" > /tmp/hotman -/usr/lib/hotspot/travelmate.sh & - diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh deleted file mode 100644 index cbc9571..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/mode.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -SET=$1 - -rm -f /tmp/hotman -uci set travelmate.global.trm_auto=$SET -uci commit travelmate - -if [ $SET = "1" ]; then - result=`ps | grep -i "travelmate.sh" | grep -v "grep" | wc -l` - if [ $result -ge 1 ] - then - wifilog "HOTSPOT" "Travelmate already running" - else - /usr/lib/hotspot/travelmate.sh & - fi -else - hkillall travelmate.sh -fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh deleted file mode 100644 index cef0a60..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/reconn.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Reconnect" "$@" -} - -reconn=$1 -log "$reconn" -uci set travelmate.global.reconn=$reconn -uci commit travelmate \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh deleted file mode 100644 index 81574d7..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/hotspot/travelmate.sh +++ /dev/null @@ -1,429 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -# travelmate, a wlan connection manager for travel router -# written by Dirk Brenken (dev@brenken.org) - -# This is free software, licensed under the GNU General Public License v3. -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# prepare environment -# -LC_ALL=C -PATH="/usr/sbin:/usr/bin:/sbin:/bin" -trm_ver="0.3.0" -trm_enabled=1 -trm_debug=0 -trm_maxwait=20 -trm_maxretry=1 -trm_iw=1 -trm_auto=$(uci -q get travelmate.global.trm_auto) - -check_wwan() { - uci set travelmate.global.ssid="8" - wif=$(uci -q get travelmate.global.freq) - if [ -z "$wif" ]; then - uci set travelmate.global.freq="2" - fi - uci commit travelmate - while [ ! -e /etc/config/wireless ] - do - sleep 1 - done - sleep 3 - f_check "ap" - cntx=0 - while [ "${trm_ifstatus}" != "true" ]; do - sleep 1 - f_check "ap" - let cntx=cntx+1 - if [ $cntx -ge 20 ]; then - break - fi - done - f_log "info" "AP Status ::: $trm_ifstatus" -} - -count_radio() { - local config=$1 - local channel - - config_get channel $1 channel - if [ $channel -gt 15 ]; then - uci set travelmate.global.radio5="5.8 Ghz" - else - uci set travelmate.global.radio2="2.4 Ghz" - fi - let radcnt=radcnt+1 -} - -check_radio() { - radcnt=0 - config_load wireless - config_foreach count_radio wifi-device - uci set travelmate.global.radcnt=$radcnt - uci commit travelmate -} - -f_envload() -{ - # source required system libraries - # - if [ -r "/lib/functions.sh" ] - then - . "/lib/functions.sh" - else - f_log "error" "required system library not found" - fi - - # load uci config and check 'enabled' option - # - option_cb() - { - local option="${1}" - local value="${2}" - eval "${option}=\"${value}\"" - } - config_load travelmate - - if [ ${trm_enabled} -ne 1 ] - then - f_log "info " "status ::: Hotspot Manager is currently disabled" - exit 0 - fi - - # check for preferred wireless tool - # - if [ ${trm_iw} -eq 1 ] - then - trm_scanner="$(which iw)" - else - trm_scanner="$(which iwinfo)" - fi - if [ -z "${trm_scanner}" ] - then - f_log "error" "status ::: no wireless tool for wlan scanning found, please install 'iw' or 'iwinfo'" - fi -} - -# function to bring down all STA interfaces -# -f_prepare() -{ - local config="${1}" - local mode="$(uci -q get wireless."${config}".mode)" - local network="$(uci -q get wireless."${config}".network)" - local disabled="$(uci -q get wireless."${config}".disabled)" - - if [ "${mode}" = "sta" ] && [ -n "${network}" ] - then - trm_stalist="${trm_stalist} ${config}_${network}" - if [ -z "${disabled}" ] || [ "${disabled}" = "0" ] - then - uci -q set wireless."${config}".disabled=1 - f_log "debug" "prepare ::: config: ${config}, interface: ${network}" - fi - fi -} - -f_check() -{ - local ifname cnt=0 mode="${1}" - trm_ifstatus="false" - - while [ ${cnt} -lt ${trm_maxwait} ] - do - wif=$(uci -q get travelmate.global.freq) - RADIO=$(uci get wireless.wwan$wif.device) - ifname="$(ubus -S call network.wireless status | jsonfilter -l 1 -e "@.$RADIO.interfaces[@.config.mode=\"${mode}\"].ifname")" - if [ -z $ifname ]; then - break - fi - if [ "${mode}" = "sta" ] - then - trm_ifstatus="$(ubus -S call network.interface dump | jsonfilter -e "@.interface[@.device=\"${ifname}\"].up")" - else - trm_ifstatus="$(ubus -S call network.wireless status | jsonfilter -l1 -e '@.*.up')" - fi - if [ "${trm_ifstatus}" = "true" ] - then - break - fi - cnt=$((cnt+1)) - sleep 1 - done - f_log "debug" "check ::: ${mode} name: ${ifname}, status: ${trm_ifstatus}, count: ${cnt}" -} - -# function to write to syslog -# -f_log() -{ - local class="${1}" - local log_msg="${2}" - - if [ -n "${log_msg}" ] && ([ "${class}" != "debug" ] || [ ${trm_debug} -eq 1 ]) - then - wifilog "HOTSPOT-[${trm_ver}] ${class}" "${log_msg}" - if [ "${class}" = "error" ] - then - wif=$(uci -q get travelmate.global.freq) - uci set travelmate.global.ssid="1" - uci commit travelmate - uci -q set wireless.wwan@wif.ssid="Hotspot Manager Interface" - uci -q set wireless.wwan$wif.encryption="none" - uci -q set wireless.wwan$wif.key= - uci -q commit wireless - #exit 255 - fi - fi -} - -ssid_list="" -ap_list="" -trm_stalist="" - -f_working_ap() { - f_check "ap" - wif=$(uci -q get travelmate.global.freq) - RADIO=$(uci get wireless.wwan$wif.device) - ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" - f_log "debug" "main ::: ap-list: ${ap_list}, sta-list: ${trm_stalist}" - if [ -z "${ap_list}" ] || [ -z "${trm_stalist}" ] - then - sleep 3 - f_check "ap" - ap_list="$(ubus -S call network.wireless status | jsonfilter -e "@.$RADIO.interfaces[@.config.mode=\"ap\"].ifname")" - f_log "debug" "main ::: ap-list: ${ap_list}, sta-list: ${trm_stalist}" - fi -} - -f_scan_ap() { - wif=$(uci -q get travelmate.global.freq) - radio=$(uci get wireless.wwan$wif.device) - # scan using AP radio - trm_iwinfo="$(command -v iwinfo)" - trm_maxscan="10" - scan_dev="$(ubus -S call network.wireless status 2>/dev/null | jsonfilter -q -l1 -e "@.${radio}.interfaces[0].ifname")" - ssid_list="$("${trm_iwinfo}" "${scan_dev:-${radio}}" scan 2>/dev/null | - awk 'BEGIN{FS="[[:space:]]"}/Address:/{var1=$NF}/ESSID:/{var2="";for(i=12;i<=NF;i++)if(var2==""){var2=$i}else{var2=var2" "$i}} - /Quality:/{split($NF,var0,"/")}/Encryption:/{if($NF=="none"){var3="+"}else{var3="-"}; - printf "%i %s %s %s\n",(var0[1]*100/var0[2]),var3,var1,var2}' | sort -rn | head -qn "${trm_maxscan}")" -} - -f_main() -{ - local config network ssid cnt=0 - wif=$(uci -q get travelmate.global.freq) - - trm_stalist="" - # check if wwan is connected - f_check "sta" - if [ "${trm_ifstatus}" == "true" ]; then - wifi down $(uci -q get wireless.wwan$wif.device) - f_check "sta" - f_log "info" "STA ${trm_ifstatus}" - while [ "${trm_ifstatus}" == "true" ]; do - sleep 1 - f_check "sta" - done - fi - if [ "${trm_ifstatus}" != "true" ] # not connected - then - uci set travelmate.global.state='1' - uci commit travelmate - f_check "ap" - f_log "info" "AP ${trm_ifstatus}" - if [ "${trm_ifstatus}" != "true" ]; then - wifi up $(uci -q get wireless.wwan$wif.device) - f_check "ap" - while [ "${trm_ifstatus}" != "true" ]; do - sleep 1 - f_check "ap" - done - fi - uci set travelmate.global.bssid="" - uci set travelmate.global.ssid="2" - uci commit travelmate - uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" - uci -q set wireless.wwan$wif.encryption="none" - uci -q set wireless.wwan$wif.key= - uci -q commit wireless - ubus call network.interface.wwan$wif up - ubus call network reload - wifi up $(uci -q get wireless.wwan$wif.device) - sleep 5 - - # set disabled for wwan iface - config_load wireless - config_foreach f_prepare wifi-iface - if [ -n "$(uci -q changes wireless)" ] - then - uci -q commit wireless - ubus call network reload - fi - # check if AP working - f_working_ap - # AP or STA not working - if [ -z "${ap_list}" ] || [ -z "${trm_stalist}" ] - then - f_log "error" "main ::: no usable AP/STA configuration found" - - else - # single AP in list - for ap in ${ap_list} - do - #f_scan_ap - # repeat scan and connection - cnt=0 - delay=10 - reconn=$(uci -q get travelmate.global.reconn) - while [ ${cnt} -lt $reconn ] - do - f_log "info" " Retry Count ${cnt}" - if [ $reconn -eq 99 ]; then - cnt=0 - fi - f_scan_ap - f_log "info" " SSID List ${ssid_list}" - # get list of Hotspots present - if [ -n "${ssid_list}" ]; then - if [ "$trm_auto" = "1" ]; then - FILE="/etc/hotspot" - else - FILE="/tmp/hotman" - fi - if [ -f "${FILE}" ]; then - # read list of selected Hotspots - while IFS='|' read -r ssid encrypt key - do - ssidq="\"$ssid\"" - # see if in scan list - if [ -n "$(printf "${ssid_list}" | grep -Fo "${ssidq}")" ]; then - # connect to Hotspot - uci set travelmate.global.bssid="$ssid" - uci set travelmate.global.ssid=">>> $ssid" - uci set travelmate.global.connecting="1" - uci commit travelmate - uci -q set wireless.wwan$wif.ssid="$ssid" - uci -q set wireless.wwan$wif.encryption=$encrypt - uci -q set wireless.wwan$wif.key=$key - uci -q set wireless.wwan$wif.disabled=0 - uci -q commit wireless - wifi up $(uci -q get wireless.wwan$wif.device) - ubus call network.interface.wwan$wif up - ubus call network reload - f_log "info " "main ::: wwan interface connected to uplink ${ssid}" - sleep 5 - # wait and check for good connection - f_check "ap" - f_log "info" "AP Status ::: $trm_ifstatus" - cntx=0 - while [ "${trm_ifstatus}" != "true" ]; do - sleep 1 - f_check "ap" - let cntx=cntx+1 - if [ $cntx -ge $delay ]; then - break - fi - f_log "info" "AP Status ::: $trm_ifstatus" - done - cntx=0 - #delay=$(uci -q get travelmate.global.delay) - f_check "sta" - f_log "info" "STA Status ${trm_ifstatus}" - while [ "${trm_ifstatus}" != "true" ]; do - sleep 1 - f_check "sta" - let cntx=cntx+1 - if [ $cntx -ge $delay ]; then - break - fi - f_log "info" "STA Status ${trm_ifstatus}" - done - - if [ "${trm_ifstatus}" = "true" ]; then - uci set travelmate.global.ssid="$ssid" - uci set travelmate.global.connecting="0" - uci set travelmate.global.lost="0" - uci set travelmate.global.state='2' - uci set travelmate.global.key=$key - uci set travelmate.global.trm_auto="1" - uci commit travelmate - # connection good - f_log "info" "Connected $ssid" - exit 0 - fi - # bad connection try next Hotspot in list - uci set travelmate.global.bssid="" - uci set travelmate.global.ssid="3" - uci commit travelmate - uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" - uci -q set wireless.wwan$wif.encryption="none" - uci -q set wireless.wwan$wif.key= - uci -q set wireless.wwan$wif.disabled=1 - uci -q commit wireless - ubus call network.interface.wwan$wif down - ubus call network reload - f_log "info" "Try next in list" - fi - done <"${FILE}" - wifi up $(uci -q get wireless.wwan$wif.device) - f_check "ap" - while [ "${trm_ifstatus}" != "true" ]; do - f_check "ap" - sleep 1 - done - fi - fi - # No connection to any in list - cnt=$((cnt+1)) - if [ $reconn -gt 0 ]; then - if [ ${cnt} -lt $reconn ]; then - f_log "info " "Sleep before retrying" - sleep 30 - fi - fi - # repeat scan and connect - done - done - fi - # unable to connect - if [ "$trm_auto" = "1" ]; then - uci set travelmate.global.ssid="4" - else - uci set travelmate.global.ssid="5" - fi - reconn=$(uci -q get travelmate.global.reconn) - lost=$(uci -q get travelmate.global.lost) - if [ $reconn -eq 99 ]; then - lost="1" - fi - if [ $lost -gt $reconn ]; then - uci set travelmate.global.ssid="5" - fi - uci set travelmate.global.trm_enabled="0" - uci set travelmate.global.connecting="0" - uci set travelmate.global.lost="0" - uci set travelmate.global.state='0' - uci set travelmate.global.bssid="" - uci set travelmate.global.trm_auto="1" - uci commit travelmate - uci -q set wireless.wwan$wif.ssid="Hotspot Manager Interface" - uci -q set wireless.wwan$wif.encryption="none" - uci -q set wireless.wwan$wif.key= - uci -q commit wireless - f_log "info " "main ::: no wwan uplink found" - fi - # already connected - exit 0 -} - -check_wwan -check_radio -f_envload -f_main - -exit 0 \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua deleted file mode 100644 index 75ceb27..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/hotspot.lua +++ /dev/null @@ -1,307 +0,0 @@ -module("luci.controller.hotspot", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - entry({"admin", "hotspot"}, firstchild(), translate("Wifi Hotspot"), 29).dependent=false - page = entry({"admin", "hotspot", "hotspot"}, template("hotspot/hotspot"), _(translate("Hotspot Manager")), 5) - page.dependent = true - end - - entry({"admin", "services", "check_spot"}, call("action_check_spot")) - entry({"admin", "services", "set_mode"}, call("action_set_mode")) - entry({"admin", "services", "set_enabled"}, call("action_set_enabled")) - entry({"admin", "services", "disconnect"}, call("action_disconnect")) - entry({"admin", "services", "refreshlist"}, call("action_refresh")) - entry({"admin", "services", "moveup"}, call("action_moveup")) - entry({"admin", "services", "movedown"}, call("action_movedown")) - entry({"admin", "services", "addtolist"}, call("action_addtolist")) - entry({"admin", "services", "dellist"}, call("action_dellist")) - entry({"admin", "services", "editlist"}, call("action_editlist")) - entry({"admin", "services", "mancon"}, call("action_mancon")) - entry({"admin", "services", "bandchange"}, call("action_bandchange")) - entry({"admin", "services", "reconn"}, call("action_reconn")) -end - -function readhot() - line = nil - file = io.open("/tmp/hot", "r") - if file ~= nil then - repeat - tmp = file:read("*line") - if tmp ~= nil then - if line == nil then - line = tmp - else - line = line .. "|" .. tmp - end - end - until tmp == nil - file:close() - end - return line -end - -function action_check_spot() - local rv = {} - local freq = {} - local set = luci.http.formvalue("set") - auto = luci.model.uci.cursor():get("travelmate", "global", "trm_auto") - rv["auto"] = auto - rv["enabled"] = luci.model.uci.cursor():get("travelmate", "global", "trm_enabled") - rv["reconn"] = luci.model.uci.cursor():get("travelmate", "global", "reconn") - if rv["reconn"] == nil then - rv["reconn"] = "0" - end - - rv["ssid"] = luci.model.uci.cursor():get("travelmate", "global", "ssid") - if rv["ssid"] == nil then - rv["ssid"] = "No Connection" - end - fre = luci.model.uci.cursor():get("travelmate", "global", "freq") - encr = luci.model.uci.cursor():get("wireless", "wwan" .. fre, "encryption") - if encr == "none" then - rv["encryp"] = translate("Open") - else - rv["encryp"] = translate("Encrypted") - end - rv["disable"] = luci.model.uci.cursor():get("wireless", "wwan" .. fre, "disabled") - - dual = luci.model.uci.cursor():get("travelmate", "global", "radcnt") - rv["dual"] = dual - nrad = tonumber(dual) - for k = 0, nrad do - freq[k] = luci.model.uci.cursor():get("travelmate", "global", "radio" .. tostring(k)) - end - rv['freq'] = freq - - device = luci.model.uci.cursor():get("wireless", "wwan" .. fre, "device") - device = string.sub(device, 6, 7) - if fre == "2" then - fre="0" - else - fre="1" - end - rv["band"] = fre - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_set_mode() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/hotspot/enable.sh " .. set) -end - -function action_set_enabled() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/hotspot/enable.sh " .. set) -end - -function action_disconnect() - os.execute("/usr/lib/hotspot/dis_hot.sh") -end - -function action_refresh() - local rv = {} - os.execute("/usr/lib/hotspot/inrange.sh") - hotline = readhot() - if hotline == nil then - rv["empty"] = "1" - else - rv["empty"] = "0" - rv["hotline"] = hotline - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function movelist(direc, set, key) - local temp = {} - local rv = {} - local index = 0 - file = io.open("/tmp/hot", "r") - if file ~= nil then - repeat - tmp = file:read("*line") - if tmp ~= nil then - temp[index] = tmp - index = index + 1 - end - until tmp == nil - file:close() - if direc == 0 then - line2 = temp[set-1] - temp[set-1] = temp[set] - temp[set] = line2 - elseif direc == 1 then - line2 = temp[set+1] - temp[set+1] = temp[set] - temp[set] = line2 - elseif direc == 2 then - if index > 0 then - for i=set, index-2 do - temp[i] = temp[i+1] - end - end - index = index - 1 - elseif direc == 3 then - s, e = temp[set]:find("|") - name = temp[set]:sub(1, s-1) - cs, ce = temp[set]:find("|", e+1) - enc = temp[set]:sub(e+1, cs-1) - bs, be = temp[set]:find("|", ce+1) - ko = temp[set]:sub(ce+1, bs-1) - fl = temp[set]:sub(be+1) - temp[set] = name .. "|" .. enc .. "|" .. key .. "|" .. fl - end - if index < 0 then - --os.execute("rm -f /tmp/hot1; rm -f /etc/hotspot") - else - file = io.open("/tmp/hot", "w") - for i=0, index-1 do - file:write(temp[i], "\n") - end - file:close() - os.execute("/usr/lib/hotspot/copyhot.sh") - end - end -end - -function action_moveup() - local set = tonumber(luci.http.formvalue("set")) - local rv = {} - movelist(0, set) - hotline = readhot() - if hotline == nil then - rv["empty"] = "1" - else - rv["empty"] = "0" - rv["hotline"] = hotline - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_movedown() - local set = tonumber(luci.http.formvalue("set")) - local rv = {} - movelist(1, set) - hotline = readhot() - if hotline == nil then - rv["empty"] = "1" - else - rv["empty"] = "0" - rv["hotline"] = hotline - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_dellist() - local set = tonumber(luci.http.formvalue("set")) - local rv = {} - movelist(2, set) - hotline = readhot() - if hotline == nil then - rv["empty"] = "1" - else - rv["empty"] = "0" - rv["hotline"] = hotline - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_addtolist() - local set = luci.http.formvalue("set") - local rv = {} - - s, e = set:find("|") - ssid = set:sub(1, e-1) - - file = io.open("/etc/hotspot", "r") - if file ~= nil then - i = 0 - repeat - line = file:read("*line") - if line == nil then - break - else - s, e = line:find(ssid) - if s ~= nil then - i = 1 - break - end - end - until 1==0 - if i == 0 then - file = io.open("/etc/hotspot", "a") - file:write(set) - file:write("\n") - file:close() - end - else - file = io.open("/etc/hotspot", "w") - file:write(set) - file:write("\n") - file:close() - end - os.execute("/usr/lib/hotspot/inrange.sh") - hotline = readhot() - if hotline == nil then - rv["empty"] = "1" - else - rv["empty"] = "0" - rv["hotline"] = hotline - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_editlist() - local set = luci.http.formvalue("set") - local rv = {} - s, e = set:find("|") - sel = set:sub(1, s-1) - idx = tonumber(sel) - key = set:sub(e+1) - movelist(3, idx, key) - hotline = readhot() - if hotline == nil then - rv["empty"] = "1" - else - rv["empty"] = "0" - rv["hotline"] = hotline - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_mancon() - local set = luci.http.formvalue("set") - local rv = {} - os.execute("/usr/lib/hotspot/manual.sh \"" .. set .. "\"") -end - -function action_bandchange() - local set = luci.http.formvalue("set") - local rv = {} - os.execute("/usr/lib/hotspot/band.sh \"" .. set .. "\"") -end - -function action_reconn() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/hotspot/reconn.sh \"" .. set .. "\"") -end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua deleted file mode 100644 index b192569..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/controller/wifilog.lua +++ /dev/null @@ -1,33 +0,0 @@ -module("luci.controller.wifilog", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - local page - page = entry({"admin", "hotspot", "wifilog"}, template("wifilog/wifilog"), _(translate("Hotspot Logging")), 61) - page.dependent = true - end - - entry({"admin", "status", "wifilog"}, call("action_wifilog")) -end - -function action_wifilog() - local file - local rv ={} - - file = io.open("/tmp/wifilog.log", "r") - if file ~= nil then - local tmp = file:read("*all") - rv["log"] = tmp - file:close() - else - rv["log"] = translate("No entries in log file") - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm deleted file mode 100644 index fae6a6b..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/hotspot/hotspot.htm +++ /dev/null @@ -1,1139 +0,0 @@ -<%- - -local sys = require "luci.sys" -local utl = require "luci.util" - -wifi = {} -scan = {} -numnet = 0 - -printf = function(s,...) - io.write(s:format(...)) - local ss = s:format(...) -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function showicon() - return resource .. "/icons/encryption.png" -end - -function guess_wifi_signal(info) - local scale = scan[info]["quality"] - local icon - if scale < 15 then - icon = resource .. "/icons/signal-0.png" - elseif scale < 35 then - icon = resource .. "/icons/signal-0-25.png" - elseif scale < 55 then - icon = resource .. "/icons/signal-25-50.png" - elseif scale < 75 then - icon = resource .. "/icons/signal-50-75.png" - else - icon = resource .. "/icons/signal-75-100.png" - end - - return icon -end - -function scan_open(rrx, rry) - rony = 1 - if rry["encrypt"] == "Open" then - rony = 0 - end - ronx = 1 - if rrx["encrypt"] == "Open" then - ronx = 0 - end - if ronx < rony then - return true - end - if ronx > rony then - return false - end - ronx = rrx["quality"] - rony = rry["quality"] - if ronx > rony then - return true - end - return false -end - -function partition(arr, left, right) - local i = left - local j = right - local pivot = math.floor((left + right) / 2) - local tmp - while i <= j do - while scan_open(arr[i], arr[pivot]) do - i = i + 1 - end - while scan_open(arr[pivot], arr[j]) do - j = j - 1 - end - if i <= j then - tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp - i = i + 1 - j = j - 1 - end - end - return i, arr -end - -function quicksort(arr, left, right) - index, arr = partition(arr, left, right) - if left < (index - 1) then - quicksort(arr, left, index-1) - end - if index < right then - quicksort(arr, index, right) - end - return arr -end - -function build_scan(j, k) - scan[k]["channel"] = wifi[j]["channel"] - scan[k]["essid"] = wifi[j]["essid"] - scan[k]["signal"] = tonumber(wifi[j]["signal"]) - qc = tonumber(wifi[j]["quality"]) - qm = tonumber(wifi[j]["quality_max"]) - scan[k]["quality"] = math.floor((100 / qm) * qc) - scan[k]["ekey"] = wifi[j]["ekey"] - if wifi[j]["ekey"] == "none" then - scan[k]["encrypt"] = "Open" - scan[k]["encryption"] = wifi[j]["encryption"] - else - scan[k]["encrypt"] = wifi[j]["ekey"] - scan[k]["encryption"] = wifi[j]["encryption"] - end -end - -function get_networks() - luci.util.exec("/usr/lib/hotspot/getssid.sh") - file = io.open("/tmp/ssidlist", "r") - if file == nil then - numnet = 0 - return - end - i = 0 - cont = 2 - line = file:read("*line") - repeat - if line == nil then - cont = 0 - else - s, e = line:find("Cell ") - if s ~= nil then - cont = 1 - essid=nil - i = i + 1 - wifi[i] = {} - encryption = "none" - repeat - line = file:read("*line") - if line == nil then - cont = 0 - break - else - s, e = line:find("Cell ") - if s ~= nil then - break - else - s, e = line:find("ESSID:") - if s ~= nil then - ee = line:len() - essid = trim(line:sub(e+3, ee-1)) - end - s, e = line:find("Mode:") - if s ~= nil then - line1 = trim(line:sub(e+1)) - bs, be = line1:find(" ", 1) - mode = trim(line1:sub(1, bs)) - cs, ce = line1:find(" ") - line2 = trim(line1:sub(ce+1)) - s, e = line2:find("Channel:") - channel = trim(line2:sub(e+2)) - end - s, e = line:find("Signal:") - if s ~= nil then - line1 = trim(line:sub(e+1)) - bs, be = line1:find(" ", 1) - signal = trim(line1:sub(1, bs)) - cs, ce = line1:find(" ") - line2 = trim(line1:sub(ce+1)) - s, e = line2:find("Quality:") - cs, ce = line2:find("/", e) - quality = trim(line2:sub(e+1, ce-1)) - quality_max = trim(line2:sub(ce+1)) - end - s, e = line:find("Encryption:") - if s ~= nil then - cs, ce = line:find("WEP") - if cs == nil then - encrypt = trim(line:sub(e+2)) - s, e = encrypt:find("none") - if s ~= nil then - encryption = "none" - else - s, e = encrypt:find("mixed") - if s ~= nil then - encryption = "psk-mixed" - else - s, e = encrypt:find("WPA2") - if s ~= nil then - encryption = "psk2" - else - encryption = "psk" - end - end - end - else - cont = 2 - i = i - 1 - break - end - end - end - end - until 1==0 - else - line = file:read("*line") - end - end - if cont < 2 then - if i > 0 then - if essid ~= nil and mode == "Master" then - wifi[i]["essid"] = essid - wifi[i]["channel"] = channel - wifi[i]["signal"] = signal - wifi[i]["quality"] = quality - wifi[i]["quality_max"] = quality_max - wifi[i]["ekey"] = encrypt - wifi[i]["encryption"] = encryption - end - end - end - if cont == 0 then - break - end - cont = 2 - until 1==0 - file:close() - - k = 0 - if i > 0 then - for j=1, i do - if wifi[j]["essid"] ~= nil and tonumber(wifi[j]["quality"]) > 0 then - if k < 1 then - k = k+1 - scan[k] = {} - build_scan(j, k) - else - flag = 0 - for l=1, k do - if wifi[j]["essid"] == scan[l]["essid"] and wifi[j]["channel"] == scan[l]["channel"] and wifi[j]["ekey"] == scan[l]["ekey"] then - qc = tonumber(wifi[j]["quality"]) - qm = tonumber(wifi[j]["quality_max"]) - qual = math.floor((100 / qm) * qc) - if qual > scan[l]["quality"] then - build_scan(j, l) - end - flag = 1 - break - end - end - if flag == 0 then - k = k+1 - scan[k] = {} - build_scan(j, k) - end - end - end - end - scan = quicksort(scan, 1, k) - end - numnet = k -end - --%> -<%+header%> - - - - -
                - -
                -

                <%:Wifi Hotspot Management%>

                -
                <%:Manage Your Wifi Hotspot Connections%>
                - - - -
                - - - - - - -
                  -  
                - - - - - -
                 
                - - - - - - - -
                <%:Reconnection Attempts on Dropped Connection%> - - -  
                - - - - - - - - - - - -
                 
                - - - - - - - -
                <%:Wifi Radio Frequency :%>
                - -  
                - - - - - -
                 
                - - - - - - - -
                <%:Current Wifi Hotspot : %>
                  - - - - - - - -
                  <%:Encryption : %>
                     
                    - - - - - -
                     
                    - - - - - - - - - -
                    <%:In Range%>
                    <%:Wifi Hotspot Networks%>
                     
                    - -
                      -
                    - -
                      -
                    •  
                    • -
                    • <%:No Wifi Hotspot Networks Selected%>
                    • -
                    •  
                    • -
                    - - - - - -
                     
                    - - - - - - - -
                    <%:Hotspot Name :%>
                       
                      - - - - - - - -
                      <%:Encrypted :%>
                         
                        - - - - - - - - -
                        <%:Key :%>
                           
                          - - - - - -
                           
                          - - - - - - - - - -
                           
                          - - - - - -
                           
                          - - <% get_networks() %> - - - - - -
                          <%:Available Networks : %><%=numnet%>
                          - <% if numnet > 0 then - for m=1, numnet do - data = scan[m]["essid"] .. "|" .. scan[m]["encryption"] - %> - - - - - - -
                          - -
                          - <%=scan[m]["quality"]%>% -
                          -
                          - <%=scan[m]["essid"]%>
                          - Channel: <%=scan[m]["channel"]%> | - Encryption: <%=scan[m]["encrypt"]%> -
                          - -
                          - <% end - end %> -
                          - -
                          -
                          - - - -
                          - - -<%+footer%> diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm deleted file mode 100644 index 48bdb5f..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/lua/luci/view/wifilog/wifilog.htm +++ /dev/null @@ -1,32 +0,0 @@ -<%+header%> - - - - -
                          -

                          <%:Hotspot Logging%>

                          -
                          -
                          - <%:Log%> - - - - -
                          - -
                          - -
                          - -
                          - -<%+footer%> \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh b/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh deleted file mode 100644 index c9b7bc2..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/lib/rooter/log/wifilogger.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -TEXT=$1 -DATE=$(date +%c) - -modlog="/tmp/wifilog.log" -tmplog="/tmp/twifilog" - -echo "$DATE : $TEXT" >> $modlog -lua $ROOTER/log/mrotate.lua $modlog $tmplog -mv $tmplog $modlog - diff --git a/rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog b/rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog deleted file mode 100644 index 962b1ce..0000000 --- a/rooter/0optionalapps/luci-app-hotspot/files/usr/sbin/wifilog +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -name=$1 -text=$2 - -logger -t "$name" "$text" -/usr/lib/rooter/log/wifilogger.sh "$name $text" \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-hotspot/files/www/luci-static/resources/icons/encryption.png b/rooter/0optionalapps/luci-app-hotspot/files/www/luci-static/resources/icons/encryption.png deleted file mode 100644 index b45e2856202b579ca9ed66da9f3c5113ce654ee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 620 zcmV-y0+aoTP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0s%=xK~zXf#g#cu z96=a`Cj?oD#Y8|vV&DcCj6mE0La7Y(A2y2Oca zf^{(~K8X*3p5Sc=w>uV{qNYfGCFpQ2h6EZA+u}~JM4O^tpkZ+#=tEy}WQt|+$ajU; zc2L|4kJR9O7N||o2merHE*EP~14h$~5yZ&xm&HfX9?E#k#Ns8M$vj3ZD*p;9zhFdS zN$@+8C>6_qM_sHDfzRQnI9(h!D&i4Y_)x7p-!q;}q9D#R=1da3PMj`stt3&-SKyJetbYQtDTz`McZVnZ5o2OJlGK9ot)r0iBeIvZ>(>ExMGvP3e2q}O65*Y;26bTbzSB$ z!FO^h{L`n5$5DLIPydZnDm?;rd)~P-Mu8Rp0000 --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.nft-qos", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/nft-qos") then - return - end - - entry({"admin", "status", "realtime", "rate"}, - template("nft-qos/rate"), _("Rate"), 5).leaf = true - entry({"admin", "status", "realtime", "rate_status"}, - call("action_rate")).leaf = true - entry({"admin", "services", "nft-qos"}, cbi("nft-qos/nft-qos"), - _("Qos over Nftables"), 60) -end - -function _action_rate(rv, n) - local c = nixio.fs.access("/proc/net/ipv6_route") and - io.popen("nft list chain inet nft-qos-monitor " .. n .. " 2>/dev/null") or - io.popen("nft list chain ip nft-qos-monitor " .. n .. " 2>/dev/null") - - if c then - for l in c:lines() do - local _, i, p, b = l:match( - '^%s+ip ([^%s]+) ([^%s]+) counter packets (%d+) bytes (%d+)' - ) - if i and p and b then - -- handle expression - rv[#rv + 1] = { - rule = { - family = "inet", - table = "nft-qos-monitor", - chain = n, - handle = 0, - expr = { - { match = { right = i } }, - { counter = { packets = p, bytes = b } } - } - } - } - end - end - c:close() - end -end - -function action_rate() - luci.http.prepare_content("application/json") - local data = { nftables = {} } - _action_rate(data.nftables, "upload") - _action_rate(data.nftables, "download") - luci.http.write_json(data) -end diff --git a/rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/model/cbi/nft-qos/nft-qos.lua b/rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/model/cbi/nft-qos/nft-qos.lua deleted file mode 100644 index 61a6d76..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/model/cbi/nft-qos/nft-qos.lua +++ /dev/null @@ -1,229 +0,0 @@ --- Copyright 2018 Rosy Song --- Licensed to the public under the Apache License 2.0. - -local uci = require("luci.model.uci").cursor() -local wa = require("luci.tools.webadmin") -local fs = require("nixio.fs") -local ipc = require("luci.ip") - -local def_rate_dl = uci:get("nft-qos", "default", "static_rate_dl") -local def_rate_ul = uci:get("nft-qos", "default", "static_rate_ul") -local def_unit_dl = uci:get("nft-qos", "default", "static_unit_dl") -local def_unit_ul = uci:get("nft-qos", "default", "static_unit_ul") - -local def_up = uci:get("nft-qos", "default", "dynamic_bw_up") -local def_down = uci:get("nft-qos", "default", "dynamic_bw_down") - -local limit_enable = uci:get("nft-qos", "default", "limit_enable") -local limit_type = uci:get("nft-qos", "default", "limit_type") -local enable_priority = uci:get("nft-qos", "default", "priority_enable") - -local has_ipv6 = fs.access("/proc/net/ipv6_route") - -m = Map("nft-qos", translate("Qos over Nftables")) - --- --- Taboptions --- -s = m:section(TypedSection, "default", translate("NFT-QoS Settings")) -s.addremove = false -s.anonymous = true - -s:tab("limit", "Limit Rate") -s:tab("priority", "Traffic Priority") - --- --- Static --- -o = s:taboption("limit", Flag, "limit_enable", translate("Limit Enable"), translate("Enable Limit Rate Feature")) -o.default = limit_enable or o.enabled -o.rmempty = false - -o = s:taboption("limit", ListValue, "limit_type", translate("Limit Type"), translate("Type of Limit Rate")) -o.default = limit_static or "static" -o:depends("limit_enable","1") -o:value("static", "Static") -o:value("dynamic", "Dynamic") - -o = s:taboption("limit", Value, "static_rate_dl", translate("Default Download Rate"), translate("Default value for download rate")) -o.datatype = "uinteger" -o.default = def_rate_dl or '50' -o:depends("limit_type","static") - -o = s:taboption("limit", ListValue, "static_unit_dl", translate("Default Download Unit"), translate("Default unit for download rate")) -o.default = def_unit_dl or "kbytes" -o:depends("limit_type","static") -o:value("bytes", "Bytes/s") -o:value("kbytes", "KBytes/s") -o:value("mbytes", "MBytes/s") - -o = s:taboption("limit", Value, "static_rate_ul", translate("Default Upload Rate"), translate("Default value for upload rate")) -o.datatype = "uinteger" -o.default = def_rate_ul or '50' -o:depends("limit_type","static") - -o = s:taboption("limit", ListValue, "static_unit_ul", translate("Default Upload Unit"), translate("Default unit for upload rate")) -o.default = def_unit_ul or "kbytes" -o:depends("limit_type","static") -o:value("bytes", "Bytes/s") -o:value("kbytes", "KBytes/s") -o:value("mbytes", "MBytes/s") - --- --- Dynamic --- -o = s:taboption("limit", Value, "dynamic_bw_down", translate("Download Bandwidth (Mbps)"), translate("Default value for download bandwidth")) -o.default = def_up or '100' -o.datatype = "uinteger" -o:depends("limit_type","dynamic") - -o = s:taboption("limit", Value, "dynamic_bw_up", translate("Upload Bandwidth (Mbps)"), translate("Default value for upload bandwidth")) -o.default = def_down or '100' -o.datatype = "uinteger" -o:depends("limit_type","dynamic") - -o = s:taboption("limit", Value, "dynamic_cidr", translate("Target Network (IPv4/MASK)"), translate("Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc")) -o.datatype = "cidr4" -ipc.routes({ family = 4, type = 1 }, function(rt) o.default = rt.dest end) -o:depends("limit_type","dynamic") - -if has_ipv6 then - o = s:taboption("limit", Value, "dynamic_cidr6", translate("Target Network6 (IPv6/MASK)"), translate("Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc")) - o.datatype = "cidr6" - o:depends("limit_type","dynamic") -end - -o = s:taboption("limit", DynamicList, "limit_whitelist", translate("White List for Limit Rate")) -o.datatype = "ipaddr" -o:depends("limit_enable","1") - --- --- Priority --- -o = s:taboption("priority", Flag, "priority_enable", translate("Enable Traffic Priority"), translate("Enable this feature")) -o.default = enable_priority or o.enabled -o.rmempty = false - -o = s:taboption("priority", ListValue, "priority_netdev", translate("Default Network Interface"), translate("Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc")) -o:depends("priority_enable", "1") -wa.cbi_add_networks(o) - --- --- Static Limit Rate - Download Rate --- -if limit_enable == "1" and limit_type == "static" then - -x = m:section(TypedSection, "download", translate("Static QoS-Download Rate")) -x.anonymous = true -x.addremove = true -x.template = "cbi/tblsection" - -o = x:option(Value, "hostname", translate("Hostname")) -o.datatype = "hostname" -o.default = 'undefined' - -if has_ipv6 then - o = x:option(Value, "ipaddr", translate("IP Address(V4 / V6)")) -else - o = x:option(Value, "ipaddr", translate("IP Address(V4 Only)")) -end -o.datatype = "ipaddr" -if nixio.fs.access("/tmp/dhcp.leases") or nixio.fs.access("/var/dhcp6.leases") then - o.titleref = luci.dispatcher.build_url("admin", "status", "overview") -end - -o = x:option(Value, "macaddr", translate("MAC (optional)")) -o.rmempty = true -o.datatype = "macaddr" - -o = x:option(Value, "rate", translate("Rate")) -o.default = def_rate_dl or '50' -o.size = 4 -o.datatype = "uinteger" - -o = x:option(ListValue, "unit", translate("Unit")) -o.default = def_unit_dl or "kbytes" -o:value("bytes", "Bytes/s") -o:value("kbytes", "KBytes/s") -o:value("mbytes", "MBytes/s") - --- --- Static Limit Rate - Upload Rate --- -y = m:section(TypedSection, "upload", translate("Static QoS-Upload Rate")) -y.anonymous = true -y.addremove = true -y.template = "cbi/tblsection" - -o = y:option(Value, "hostname", translate("Hostname")) -o.datatype = "hostname" -o.default = 'undefined' - -if has_ipv6 then - o = y:option(Value, "ipaddr", translate("IP Address(V4 / V6)")) -else - o = y:option(Value, "ipaddr", translate("IP Address(V4 Only)")) -end -o.datatype = "ipaddr" -if nixio.fs.access("/tmp/dhcp.leases") or nixio.fs.access("/var/dhcp6.leases") then - o.titleref = luci.dispatcher.build_url("admin", "status", "overview") -end - -o = y:option(Value, "macaddr", translate("MAC (optional)")) -o.rmempty = true -o.datatype = "macaddr" - -o = y:option(Value, "rate", translate("Rate")) -o.default = def_rate_ul or '50' -o.size = 4 -o.datatype = "uinteger" - -o = y:option(ListValue, "unit", translate("Unit")) -o.default = def_unit_ul or "kbytes" -o:value("bytes", "Bytes/s") -o:value("kbytes", "KBytes/s") -o:value("mbytes", "MBytes/s") - -end - --- --- Traffic Priority Settings --- -if enable_priority == "1" then - -s = m:section(TypedSection, "priority", translate("Traffic Priority Settings")) -s.anonymous = true -s.addremove = true -s.template = "cbi/tblsection" - -o = s:option(ListValue, "protocol", translate("Protocol")) -o.default = "tcp" -o:value("tcp", "TCP") -o:value("udp", "UDP") -o:value("udplite", "UDP-Lite") -o:value("sctp", "SCTP") -o:value("dccp", "DCCP") - -o = s:option(ListValue, "priority", translate("Priority")) -o.default = "1" -o:value("-400", "1") -o:value("-300", "2") -o:value("-225", "3") -o:value("-200", "4") -o:value("-150", "5") -o:value("-100", "6") -o:value("0", "7") -o:value("50", "8") -o:value("100", "9") -o:value("225", "10") -o:value("300", "11") - -o = s:option(Value, "service", translate("Service"), translate("e.g. https, 23, (separator is comma)")) -o.default = '?' - -o = s:option(Value, "comment", translate("Comment")) -o.default = '?' - -end - -return m diff --git a/rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/view/nft-qos/rate.htm b/rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/view/nft-qos/rate.htm deleted file mode 100644 index 5f9cb57..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/files/usr/lib/lua/luci/view/nft-qos/rate.htm +++ /dev/null @@ -1,167 +0,0 @@ -<%# - Copyright 2018 Rosy Song - Licensed to the public under the Apache License 2.0. --%> - -<%+header%> - - - -

                          <%:Realtime Rate%>

                          - -
                          <%:This page gives an overview over currently download/upload rate.%>
                          - -
                          - <%:Realtime Download Rate%> -
                          -
                          -
                          -
                          <%:IP Address%>
                          -
                          <%:Download Rate%>
                          -
                          <%:Bytes Total%>
                          -
                          <%:Packets Total%>
                          -
                          -
                          -
                          - <%:Collecting data...%> -
                          -
                          -
                          -
                          -
                          - -
                          - <%:Realtime Upload Rate%> -
                          -
                          -
                          -
                          <%:IP Address%>
                          -
                          <%:Upload Rate%>
                          -
                          <%:Bytes Total%>
                          -
                          <%:Packets Total%>
                          -
                          -
                          -
                          - <%:Collecting data...%> -
                          -
                          -
                          -
                          -
                          - -<%+footer%> diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/bg/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/bg/nft-qos.po deleted file mode 100644 index 6bfdc6b..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/bg/nft-qos.po +++ /dev/null @@ -1,233 +0,0 @@ -msgid "" -msgstr "" -"Language: bg\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/ca/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/ca/nft-qos.po deleted file mode 100644 index c2eef3c..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/ca/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-01-10 12:23+0000\n" -"Last-Translator: Adolfo Jayme Barrientos \n" -"Language-Team: Catalan \n" -"Language: ca\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.10.1\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "S’estan recollint dades…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Nom de l’amfitrió" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Unitat" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/cs/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/cs/nft-qos.po deleted file mode 100644 index acc9a0f..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/cs/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-02-04 05:03+0000\n" -"Last-Translator: Pavel Borecki \n" -"Language-Team: Czech \n" -"Language: cs\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 3.11-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Shromažďování údajů…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Komentář" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Název počítače" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP adresa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Údaje nejsou k dispozici" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokol" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/de/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/de/nft-qos.po deleted file mode 100644 index 2c14fe3..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/de/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-07-11 21:29+0000\n" -"Last-Translator: ssantos \n" -"Language-Team: German \n" -"Language: de\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.2-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Bytes Gesamt" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Sammle Daten..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Kommentar" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Standard-Downloadrate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Standard-Download-Einheit" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Standard-Netzwerkschnittstelle" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Standard-Uploadrate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Standard-Upload-Einheit" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "Standardeinheit für Downloadrate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Standardeinheit für Upload-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "Standardwert für Download-Bandbreite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "Standardwert für Downloadrate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Standardwert für Upload-Bandbreite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Standardwert für Upload-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "Download-Bandbreite (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Download-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Aktiviere die Limit-Rate-Funktion" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Aktiviere Traffic-Priorisierung" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "Diese Funktion aktivieren" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Hostname" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP-Adresse" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "Limit aktivieren" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Limit-Typ" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (optional)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "NFT-QoS-Einstellungen" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Keine Informationen verfügbar" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Pakete Gesamt" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Priorität" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokoll" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "Rate" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Echtzeit-Downloadrate" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "Echtzeit-Rate" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Echtzeit-Uploadrate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Service" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "Statische QoS-Download-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "Statische QoS-Upload-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "Zielnetzwerk (IPv4/MASK)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "Zielnetzwerk6 (IPv6/MASK)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" -"Diese Seite gibt einen Überblick über die aktuelle Download-/Uploadrate." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "Einstellungen für Traffic-Priorität" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "Typ der Limit-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Einheit" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "Upload-Bandbreite (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "Uploadrate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "Whitelist für die Limit-Rate" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "z.B. https, 23, (Trennzeichen ist Komma)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/el/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/el/nft-qos.po deleted file mode 100644 index 57aa172..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/el/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-12-01 16:16+0000\n" -"Last-Translator: Marios Koutsoukis \n" -"Language-Team: Greek \n" -"Language: el\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.4-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Συλλογή δεδομένων..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Όνομα κεντρικού υπολογιστή" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/en/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/en/nft-qos.po deleted file mode 100644 index f3e6b42..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/en/nft-qos.po +++ /dev/null @@ -1,233 +0,0 @@ -msgid "" -msgstr "" -"Language: en\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/es/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/es/nft-qos.po deleted file mode 100644 index f12d261..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/es/nft-qos.po +++ /dev/null @@ -1,246 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: 2020-09-18 18:36+0000\n" -"Last-Translator: Franco Castillo \n" -"Language-Team: Spanish \n" -"Language: es\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.3-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Total de bytes" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Recolectando datos…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Comentario" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Velocidad de descarga predeterminada" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Unidad de descarga predeterminada" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Interfaz de red predeterminada" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Velocidad de carga predeterminada" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Unidad de carga predeterminada" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "Unidad predeterminada para la velocidad de descarga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Unidad predeterminada para la velocidad de carga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "Valor predeterminado para el ancho de banda de descarga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "Valor predeterminado para la velocidad de descarga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Valor predeterminado para el ancho de banda de carga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Valor predeterminado para la velocidad de carga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "Ancho de banda de descarga (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Velocidad de descarga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Activar función de límite de velocidad" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Activar prioridad de tráfico" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "Activar esta característica" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Nombre del host" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "Dirección IP" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "Dirección IP (v4/v6)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "Dirección IP (sólo v4)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "Activar límite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Tipo de límite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (opcional)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "Configuración de NFT-QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" -"Interfaz de red para configuración de tráfico, por ejemplo, br-lan, eth0.1, " -"eth0, etc." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "Red a aplicar, por ejemplo. 192.168.1.0/24, 10.2.0.0/16, etc." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "Red a aplicar, por ejemplo. AAAA::BBBB/64, CCCC::1/128, etc." - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "No hay información disponible" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Paquetes totales" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Prioridad" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protocolo" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "Qos sobre Nftables" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "Velocidad" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Velocidad de descarga en tiempo real" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "Velocidad en tiempo real" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Velocidad de carga en tiempo real" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Servicio" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "Velocidad de descarga de QoS estática" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "Velocidad de carga de QoS estática" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "Red de destino (IPv4 / MASK)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "Red de destino 6 (IPv6/MÁSCARA)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" -"Esta página ofrece una vista general sobre la velocidad de descarga/carga " -"actual." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "Ajustes de prioridad de tráfico" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "Tipo de límite de velocidad" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Unidad" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "Ancho de banda de carga (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "Velocidad de carga" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "Lista blanca para el límite de velocidad" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "p.ej. https, 23, (el separador es una coma)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/fr/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/fr/nft-qos.po deleted file mode 100644 index 391c427..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/fr/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-10-24 08:56+0000\n" -"Last-Translator: ButterflyOfFire \n" -"Language-Team: French \n" -"Language: fr\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.3.1\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Total octets" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Récupération des données…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Commentaire" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Nom d'hôte" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "Adresse IP" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Information indisponible" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protocole" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Service" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/he/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/he/nft-qos.po deleted file mode 100644 index b182668..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/he/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-10-17 15:26+0000\n" -"Last-Translator: Yaron Shahrabani \n" -"Language-Team: Hebrew \n" -"Language: he\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && " -"n % 10 == 0) ? 2 : 3));\n" -"X-Generator: Weblate 4.3.1-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "נאספים נתונים…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/hi/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/hi/nft-qos.po deleted file mode 100644 index 29961a2..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/hi/nft-qos.po +++ /dev/null @@ -1,233 +0,0 @@ -msgid "" -msgstr "" -"Language: hi\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/hu/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/hu/nft-qos.po deleted file mode 100644 index 1027fc6..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/hu/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-01-08 19:28+0000\n" -"Last-Translator: Balázs Úr \n" -"Language-Team: Hungarian \n" -"Language: hu\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.10.1-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Bájt összesen" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Adatok összegyűjtése…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Megjegyzés" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Alapértelmezett letöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Alapértelmezett letöltési mértékegység" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Alapértelmezett hálózati csatoló" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Alapértelmezett feltöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Alapértelmezett feltöltési mértékegység" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "Alapértelmezett mértékegység a letöltési aránynál" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Alapértelmezett mértékegység a feltöltési aránynál" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "Alapértelmezett érték a letöltési sávszélességnél" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "Alapértelmezett érték a letöltési aránynál" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Alapértelmezett érték a feltöltési sávszélességnél" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Alapértelmezett érték a feltöltési aránynál" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "Letöltési sávszélesség (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Letöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Arány korlátozása funkció engedélyezése" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Forgalomprioritás engedélyezése" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "A funkció engedélyezése" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Gépnév" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP-cím" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "Korlátozás engedélyezése" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Korlát típusa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (elhagyható)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "NFT-QoS beállítások" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Nincs elérhető információ" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Csomagok összesen" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Prioritás" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokoll" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "Arány" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Valós idejű letöltési arány" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "Valós idejű arány" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Valós idejű feltöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Szolgáltatás" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "Statikus QoS-letöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "Statikus QoS feltöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "Célhálózat (IPv4/MASZK)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "Célhálózat 6 (IPv6/MASZK)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" -"Ez az oldal áttekintést ad a jelenlegi letöltési és feltöltési arányról." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "Forgalomprioritás beállításai" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "Arány korlátozásának típusa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Mértékegység" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "Feltöltési sávszélesség (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "Feltöltési arány" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "Fehérlista az arány korlátázásához" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "például https, 23, (vesszővel elválasztva)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/it/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/it/nft-qos.po deleted file mode 100644 index 0635c24..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/it/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-03-04 04:29+0000\n" -"Last-Translator: TuxAlex0 \n" -"Language-Team: Italian \n" -"Language: it\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.0-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Raccolta dati..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Commento" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Hostname" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Nessuna informazione disponibile" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protocollo" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/ja/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/ja/nft-qos.po deleted file mode 100644 index 186ecb0..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/ja/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-10-10 13:26+0000\n" -"Last-Translator: RyotaGamer <21ryotagamer@gmail.com>\n" -"Language-Team: Japanese \n" -"Language: ja\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.3-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "データを収集中..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "コメント" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "ホスト名" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP アドレス" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "NFT-QoS 設定" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "情報なし" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "プロトコル" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "サービス" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "アップロード帯域幅 (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/ko/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/ko/nft-qos.po deleted file mode 100644 index 5a3f704..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/ko/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-07-28 17:55+0000\n" -"Last-Translator: TheNoFace \n" -"Language-Team: Korean \n" -"Language: ko\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.2-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "데이터 수집 중..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/mr/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/mr/nft-qos.po deleted file mode 100644 index 86c0604..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/mr/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-02-07 09:18+0000\n" -"Last-Translator: Prachi Joshi \n" -"Language-Team: Marathi \n" -"Language: mr\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 3.11-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "डेटा संकलित करीत आहे ..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "टिप्पणी" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "होस्टनाव" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "प्रोटोकॉल" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "युनिट" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/ms/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/ms/nft-qos.po deleted file mode 100644 index 08bfab1..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/ms/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2019-12-16 23:25+0000\n" -"Last-Translator: Pusak Hitam \n" -"Language-Team: Malay \n" -"Language: ms\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.10-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Mengumpul data..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/nb_NO/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/nb_NO/nft-qos.po deleted file mode 100644 index 5ecf971..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/nb_NO/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2019-10-30 03:21+0000\n" -"Last-Translator: Allan Nordhøy \n" -"Language-Team: Norwegian Bokmål \n" -"Language: nb_NO\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.9.1\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Samler inn data…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/pl/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/pl/nft-qos.po deleted file mode 100644 index 7342882..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/pl/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-09-19 18:03+0000\n" -"Last-Translator: Marcin Net \n" -"Language-Team: Polish \n" -"Language: pl\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.3-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Bajty ogółem" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Trwa zbieranie danych..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Komentarz" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Domyślna szybkość pobierania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Domyślna jednostka pobierania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Domyślny interfejs sieciowy" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Domyślna szybkość przesyłania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Domyślna jednostka przesyłania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "Domyślna jednostka dla szybkości pobierania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Domyślna jednostka szybkości wysyłania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "Wartość domyślna dla przepustowości pobierania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "Wartość domyślna dla szybkości pobierania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Wartość domyślna dla przepustowości wysyłania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Wartość domyślna szybkości wysyłania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "Przepustowość pobierania (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Szybkość pobierania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Włącz funkcję limitu prędkości" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Włącz priorytet ruchu" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "Włącz tę funkcję" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Nazwa hosta" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "Adres IP" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "Włącz limit" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Typ limitu" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (opcjonalnie)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "Ustawienia NFT-QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Brak dostępnych informacji" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Suma pakietów" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Priorytet" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokół" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "Tempo" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Szybkość pobierania w czasie rzeczywistym" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "Szybkość w czasie rzeczywistym" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Szybkość wysyłania w czasie rzeczywistym" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Usługa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "Statyczna prędkość pobierania QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "Statyczna prędkość wysyłania QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "Sieć docelowa (IPv4/Maska)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "Sieć docelowa (IPv6/Maska)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "Ta strona zawiera przegląd aktualnej prędkości pobierania/wysyłania." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "Ustawienia priorytetu ruchu sieciowego" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "Typ limitu prędkości" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Jednostka" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "Przepustowość przesyłania (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "Szybkość wysyłania" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "Biała lista dla limitu prędkości" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "np. https, 23, (separator to przecinek)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/pt/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/pt/nft-qos.po deleted file mode 100644 index 8c6b36e..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/pt/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-09-18 18:36+0000\n" -"Last-Translator: ssantos \n" -"Language-Team: Portuguese \n" -"Language: pt\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.3-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Total de Bytes" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "A recolher dados..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Comentário" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Taxa de Descarregamento Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Unidade de Descarregamento Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Interface de Rede Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Taxa de Envio Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Unidade de Envio Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "Unidade padrão para taxa de descarregamento" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Unidade padrão para taxa de envio" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "Valor padrão para largura de banda de descarregamento" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "Valor padrão para taxa de descarregamento" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Valor padrão para a largura de banda de envio" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Valor padrão para a taxa de envio" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "Largura de Banda de Descarregamento (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Taxa de Descarregamento" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Ativar Recurso de Limite de Taxa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Ativar Prioridade de Tráfego" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "Ativar este recurso" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Nome do Host" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "Endereço IP" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "Limitar Ativação" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Tipo de Limite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (opcional)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "Configurações NFT-QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Sem informação disponível" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Total de Pacotes" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Prioridade" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protocolo" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "Taxa" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Taxa de Descarregamento em Tempo Real" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "Taxa em Tempo Real" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Taxa de Envio em Tempo Real" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Serviço" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "Taxa Estática de Descarregamanto de QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "Taxa Estática de Envio QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "Rede de Destino (IPv4/MASK)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "Rede6 de Destino (IPv6/MASK)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" -"Esta página dá uma visão geral sobre a taxa de descarregamento/envio atual." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "Configurações de Prioridade de Tráfego" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "Tipo de Taxa Limite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Unidade" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "Largura de Banda de Envio (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "Taxa de Envio" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "Lista Branca para a Taxa Limite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "por exemplo https, 23, (o separador é vírgula)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/pt_BR/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/pt_BR/nft-qos.po deleted file mode 100644 index 40f436d..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/pt_BR/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-09-17 16:34+0000\n" -"Last-Translator: Wellington Terumi Uemura \n" -"Language-Team: Portuguese (Brazil) \n" -"Language: pt_BR\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.3-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Total de Bytes" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Coletando dados..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Comentário" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Taxa de Download Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Unidade de Download Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Interface de Rede Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Taxa de Upload Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Unidade de Upload Padrão" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "Unidade padrão para taxa de download" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Unidade padrão para taxa de upload" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "Valor padrão para a largura de banda para download" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "Valor padrão para a taxa de download" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Valor padrão para a largura de banda de upload" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Valor padrão para a taxa de upload" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "Largura de Banda de Download (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Taxa de Download" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Ativar o Recurso de Limitação de Taxa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Ativar a Prioridade de Tráfego" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "Ativar este recurso" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Nome do equipamento" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "Endereço IP" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "Ativar Limite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Tipo de Limite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (opcional)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "Configurações NFT-QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Nenhuma informação disponível" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Total de Pacotes" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Prioridade" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protocolo" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "Taxa" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Taxa de Download em Tempo Real" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "Taxa em Tempo Real" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Taxa de Upload em Tempo Real" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Serviço" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "QoS estático - Taxa de download" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "QoS-Estático - Taxa de Upload" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "Rede de Destino (IPv4/MASK)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "Rede de Destino (IPV6/MASK)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "Esta página dá uma visão geral sobre a taxa atual de download/upload." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "Configuração da Prioridade do Tráfego" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "Tipo de Taxa Limite" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "Unidade" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "Largura de Banda de Upload (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "Taxa de Upload" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "Lista Branca para a Limitação da Taxa" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "por exemplo, https, 23, (separado por vírgulas)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/ro/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/ro/nft-qos.po deleted file mode 100644 index bc97a06..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/ro/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-03-29 21:22+0000\n" -"Last-Translator: Cristian Ionescu \n" -"Language-Team: Romanian \n" -"Language: ro\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " -"20)) ? 1 : 2;\n" -"X-Generator: Weblate 4.0-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Colectare date..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Numele gazdei ( hostname )" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/ru/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/ru/nft-qos.po deleted file mode 100644 index 638701b..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/ru/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-10-09 00:10+0000\n" -"Last-Translator: Artem \n" -"Language-Team: Russian \n" -"Language: ru\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 4.3-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Всего байт" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Сбор данных..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Комментарий" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Скорость загрузки по умолчанию" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Единица загрузки по умолчанию" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Сетевой интерфейс по умолчанию" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Скорость отправки по умолчанию" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "Скорость загрузки" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "Включить функцию ограничения скорости" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "Включить приоритет трафика" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "Включить эту функцию" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Имя хоста" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP адрес" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "Тип лимита" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "MAC (необязательно)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "МБ" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "Настройки NFT-QoS" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Нет доступной информации" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "Всего пакетов" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "Приоритет" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Протокол" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "Скорость загрузки в реальном времени" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "Скорость отправки в реальном времени" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "Служба" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "узел" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/sk/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/sk/nft-qos.po deleted file mode 100644 index 7c4afad..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/sk/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-04-04 17:35+0000\n" -"Last-Translator: Dušan Kazik \n" -"Language-Team: Slovak \n" -"Language: sk\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 4.0-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Zbieram dáta..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Komentár" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Názov hostiteľa" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Nie sú dostupné žiadne informácie" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokol" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/sv/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/sv/nft-qos.po deleted file mode 100644 index da1b53a..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/sv/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-11-22 15:35+0000\n" -"Last-Translator: PontusÖsterlindh \n" -"Language-Team: Swedish \n" -"Language: sv\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.4-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Bytes Totalt" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Samlar in data..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Kommentera" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Värdnamn" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP-adress" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Ingen information tillgänglig" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokoll" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/templates/nft-qos.pot b/rooter/0optionalapps/luci-app-nft-qos/po/templates/nft-qos.pot deleted file mode 100644 index 8fecfa0..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/templates/nft-qos.pot +++ /dev/null @@ -1,230 +0,0 @@ -msgid "" -msgstr "Content-Type: text/plain; charset=UTF-8" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/tr/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/tr/nft-qos.po deleted file mode 100644 index fd53746..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/tr/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-11-28 20:18+0000\n" -"Last-Translator: Oğuz Ersen \n" -"Language-Team: Turkish \n" -"Language: tr\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.4-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "Bayt Toplamı" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Veri alınıyor..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Açıklama" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "Varsayılan İndirme Hızı" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "Varsayılan İndirme Birimi" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "Varsayılan Ağ Arayüzü" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "Varsayılan Yükleme Hızı" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "Varsayılan Yükleme Birimi" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "İndirme hızı için varsayılan birim" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "Yükleme hızı için varsayılan birim" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "İndirme bant genişliği için varsayılan değer" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "İndirme hızı için varsayılan değer" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "Yükleme band genişliği için varsayılan değer" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "Yükleme hızı için varsayılan değer" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "İndirme Band Genişliği (Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "İndirme Hızı" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Sunucu adı" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Bilgi bulunmamaktadır" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Protokol" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/uk/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/uk/nft-qos.po deleted file mode 100644 index 748da14..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/uk/nft-qos.po +++ /dev/null @@ -1,240 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2020-02-17 11:51+0000\n" -"Last-Translator: Olexandr Nesterenko \n" -"Language-Team: Ukrainian \n" -"Language: uk\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 3.11-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Збирання даних..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Примітка" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "Назва (ім'я) вузла" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP-адреса" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "Інформація відсутня" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Протокол" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/vi/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/vi/nft-qos.po deleted file mode 100644 index dcbba21..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/vi/nft-qos.po +++ /dev/null @@ -1,239 +0,0 @@ -msgid "" -msgstr "" -"PO-Revision-Date: 2019-11-13 13:07+0000\n" -"Last-Translator: Le Van Uoc \n" -"Language-Team: Vietnamese \n" -"Language: vi\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 3.10-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "Đang lấy dữ liệu..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "Bình luận" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "Giao thức" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/zh_Hans/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/zh_Hans/nft-qos.po deleted file mode 100644 index 02a59da..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/zh_Hans/nft-qos.po +++ /dev/null @@ -1,245 +0,0 @@ -# -# Yangfl , 2019. -# -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: 2020-11-22 15:35+0000\n" -"Last-Translator: Eric \n" -"Language-Team: Chinese (Simplified) \n" -"Language: zh_Hans\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.4-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "字节总数" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "正在收集数据…" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "注解" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "默认下载速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "默认下载速率单位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "默认网络接口" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "默认上传速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "默认上传速率单位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "默认的下载速率单位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "默认的上传速率单位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "下载带宽的默认值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "下载速率的默认值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "上传带宽的默认值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "上传速率的默认值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "下载带宽(Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "下载速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "开启速率限制功能" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "开启流量优先级" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "开启这个功能" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "主机名" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP 地址" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "IP 地址(V4 / V6)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "IP 地址(仅 V4)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "限速开启" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "限速类型" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "物理地址(可选)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "NFT-QoS 设置" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "流量整形的目标网络接口,例如br-lan、eth0.1、eth0等" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "将要应用规则的网络,例如192.168.1.0/24、10.2.0.0/16等" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "将要应用规则的网络,例如AAAA::BBBB/64、CCCC::1/128等" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "无可用信息" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "数据包总数" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "优先级" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "协议" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "QoS Nftables 版" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "速率" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "实时下载速率" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "实时速率显示" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "实时上传速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "服务" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "静态 QoS-下载速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "静态 QoS-上传速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "目标网络(IPv4 地址/掩码)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "目标网络 v6(IPv6 地址/掩码)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "该页面提供了当前上传和下载速率的一个总览。" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "流量优先级设置" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "限速的类型" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "单元" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "上传带宽(Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "上传速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "限速白名单" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "例如https, 23(用逗号分隔)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/po/zh_Hant/nft-qos.po b/rooter/0optionalapps/luci-app-nft-qos/po/zh_Hant/nft-qos.po deleted file mode 100644 index e2fa5f4..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/po/zh_Hant/nft-qos.po +++ /dev/null @@ -1,245 +0,0 @@ -# -# Yangfl , 2019. -# -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: 2020-06-30 13:41+0000\n" -"Last-Translator: Hulen \n" -"Language-Team: Chinese (Traditional) \n" -"Language: zh_Hant\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 4.2-dev\n" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:136 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:155 -msgid "Bytes Total" -msgstr "位元組總數" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:141 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:160 -msgid "Collecting data..." -msgstr "收集資料中..." - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:224 -msgid "Comment" -msgstr "註解" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default Download Rate" -msgstr "預設下載速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default Download Unit" -msgstr "預設下載速率單位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Default Network Interface" -msgstr "預設網路介面" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default Upload Rate" -msgstr "預設上傳速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default Upload Unit" -msgstr "預設上傳速率單位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:53 -msgid "Default unit for download rate" -msgstr "預設的下載速率單位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:65 -msgid "Default unit for upload rate" -msgstr "預設的上傳速率單位" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Default value for download bandwidth" -msgstr "下載頻寬的預設值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:48 -msgid "Default value for download rate" -msgstr "下載速率的預設值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Default value for upload bandwidth" -msgstr "上傳頻寬的預設值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:60 -msgid "Default value for upload rate" -msgstr "上傳速率的預設值" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:75 -msgid "Download Bandwidth (Mbps)" -msgstr "下載頻寬(Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:135 -msgid "Download Rate" -msgstr "下載速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Enable Limit Rate Feature" -msgstr "開啟速率限制功能" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable Traffic Priority" -msgstr "開啟流量優先順序" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:103 -msgid "Enable this feature" -msgstr "開啟這個功能" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:121 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:158 -msgid "Hostname" -msgstr "主機名稱" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:134 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:153 -msgid "IP Address" -msgstr "IP 位址" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:126 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:163 -msgid "IP Address(V4 / V6)" -msgstr "IP 位址(V4 / V6)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:128 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:165 -msgid "IP Address(V4 Only)" -msgstr "IP 位址(僅 V4)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:38 -msgid "Limit Enable" -msgstr "限速開啟" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Limit Type" -msgstr "限速型別" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:135 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:172 -msgid "MAC (optional)" -msgstr "實體位址(可選)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:48 -msgid "MB" -msgstr "MB" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:28 -msgid "NFT-QoS Settings" -msgstr "NFT-QoS 設定" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:107 -msgid "Network Interface for Traffic Shaping, e.g. br-lan, eth0.1, eth0, etc" -msgstr "流量整形的目標網路介面,例如br-lan、eth0.1、eth0等" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Network to be apply, e.g. 192.168.1.0/24, 10.2.0.0/16, etc" -msgstr "將要應用規則的網路,例如192.168.1.0/24、10.2.0.0/16等" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Network to be apply, e.g. AAAA::BBBB/64, CCCC::1/128, etc" -msgstr "將要應用規則的網路,例如AAAA::BBBB/64、CCCC::1/128等" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:65 -msgid "No information available" -msgstr "無可用資訊" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:137 -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:156 -msgid "Packets Total" -msgstr "資料包總數" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:207 -msgid "Priority" -msgstr "優先順序" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:199 -msgid "Protocol" -msgstr "協定" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:16 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:23 -msgid "Qos over Nftables" -msgstr "QoS Nftables 版" - -#: applications/luci-app-nft-qos/luasrc/controller/nft-qos.lua:12 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:139 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:176 -msgid "Rate" -msgstr "速率" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:130 -msgid "Realtime Download Rate" -msgstr "實時下載速率" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:125 -msgid "Realtime Rate" -msgstr "實時速率顯示" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:149 -msgid "Realtime Upload Rate" -msgstr "實時上傳速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "Service" -msgstr "服務" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:116 -msgid "Static QoS-Download Rate" -msgstr "靜態 QoS-下載速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:153 -msgid "Static QoS-Upload Rate" -msgstr "靜態 QoS-上傳速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:85 -msgid "Target Network (IPv4/MASK)" -msgstr "目標網路(IPv4 位址/掩碼)" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:91 -msgid "Target Network6 (IPv6/MASK)" -msgstr "目標網路 v6(IPv6 位址/掩碼)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:127 -msgid "This page gives an overview over currently download/upload rate." -msgstr "該頁面提供了當前上傳和下載速率的一個總覽。" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:194 -msgid "Traffic Priority Settings" -msgstr "流量優先順序設定" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:42 -msgid "Type of Limit Rate" -msgstr "限速的型別" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:144 -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:181 -msgid "Unit" -msgstr "單元" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:80 -msgid "Upload Bandwidth (Mbps)" -msgstr "上傳頻寬(Mbps)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:154 -msgid "Upload Rate" -msgstr "上傳速率" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:96 -msgid "White List for Limit Rate" -msgstr "限速白名單" - -#: applications/luci-app-nft-qos/luasrc/model/cbi/nft-qos/nft-qos.lua:221 -msgid "e.g. https, 23, (separator is comma)" -msgstr "例如https, 23(用逗號分隔)" - -#: applications/luci-app-nft-qos/luasrc/view/nft-qos/rate.htm:44 -msgid "kB" -msgstr "kB" diff --git a/rooter/0optionalapps/luci-app-nft-qos/root/usr/share/rpcd/acl.d/luci-app-nft-qos.json b/rooter/0optionalapps/luci-app-nft-qos/root/usr/share/rpcd/acl.d/luci-app-nft-qos.json deleted file mode 100644 index b2de626..0000000 --- a/rooter/0optionalapps/luci-app-nft-qos/root/usr/share/rpcd/acl.d/luci-app-nft-qos.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-nft-qos": { - "description": "Grant UCI access for luci-app-nft-qos", - "read": { - "uci": [ "nft-qos" ] - }, - "write": { - "uci": [ "nft-qos" ] - } - } -} diff --git a/rooter/0optionalapps/luci-app-rooterddns/Makefile b/rooter/0optionalapps/luci-app-rooterddns/Makefile deleted file mode 100644 index 4ed1d3b..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-rooterddns -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/luci-app-rooterddns - SECTION:=luci - CATEGORY:=LuCI - DEPENDS:=+ddns-scripts +ddns-scripts_no-ip_com - SUBMENU:=3. Applications - TITLE:=LuCI Support for Dynamic DNS Client - PKGARCH:=all -endef - -define Package/luci-app-rooterddns/description - LuCI Support for Dynamic DNS Client -endef - - -define Build/Compile -endef - -define Package/luci-app-rooterddns/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,luci-app-rooterddns)) diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/etc/uci-defaults/40_luci-ddns b/rooter/0optionalapps/luci-app-rooterddns/files/etc/uci-defaults/40_luci-ddns deleted file mode 100644 index a82c1f9..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/etc/uci-defaults/40_luci-ddns +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# no longer needed for "Save and Apply" to restart ddns -uci -q batch <<-EOF >/dev/null - delete ucitrack.@ddns[-1] - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -return 0 diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/controller/ddns.lua b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/controller/ddns.lua deleted file mode 100644 index 89da567..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/controller/ddns.lua +++ /dev/null @@ -1,308 +0,0 @@ --- Copyright 2008 Steven Barth --- Copyright 2008 Jo-Philipp Wich --- Copyright 2013 Manuel Munz --- Copyright 2014-2016 Christian Schoenebeck --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.ddns", package.seeall) - -local NX = require "nixio" -local NXFS = require "nixio.fs" -local DISP = require "luci.dispatcher" -local HTTP = require "luci.http" -local I18N = require "luci.i18n" -- not globally avalible here -local IPKG = require "luci.model.ipkg" -local SYS = require "luci.sys" -local UCI = require "luci.model.uci" -local UTIL = require "luci.util" -local DDNS = require "luci.tools.ddns" -- ddns multiused functions - -luci_helper = "/usr/lib/ddns/dynamic_dns_lucihelper.sh" - -local srv_name = "ddns-scripts" -local srv_ver_min = "2.7.6" -- minimum version of service required -local srv_ver_cmd = luci_helper .. [[ -V | awk {'print $2'}]] -local app_name = "luci-app-ddns" -local app_title = "Dynamic DNS" -local app_version = "2.4.8-1" - -function index() - local nxfs = require "nixio.fs" -- global definitions not available - local sys = require "luci.sys" -- in function index() - local ddns = require "luci.tools.ddns" -- ddns multiused functions - local muci = require "luci.model.uci" - - -- no config create an empty one - if not nxfs.access("/etc/config/ddns") then - nxfs.writefile("/etc/config/ddns", "") - end - - -- preset new option "lookup_host" if not already defined - local uci = muci.cursor() - local commit = false - uci:foreach("ddns", "service", function (s) - if not s["lookup_host"] and s["domain"] then - uci:set("ddns", s[".name"], "lookup_host", s["domain"]) - commit = true - end - end) - if commit then uci:commit("ddns") end - uci:unload("ddns") - - entry( {"admin", "services", "ddns"}, cbi("ddns/overview"), _("Dynamic DNS"), 59) - entry( {"admin", "services", "ddns", "detail"}, cbi("ddns/detail"), nil ).leaf = true - entry( {"admin", "services", "ddns", "hints"}, cbi("ddns/hints", - {hideapplybtn=true, hidesavebtn=true, hideresetbtn=true}), nil ).leaf = true - entry( {"admin", "services", "ddns", "global"}, cbi("ddns/global"), nil ).leaf = true - entry( {"admin", "services", "ddns", "logview"}, call("logread") ).leaf = true - entry( {"admin", "services", "ddns", "startstop"}, post("startstop") ).leaf = true - entry( {"admin", "services", "ddns", "status"}, call("status") ).leaf = true -end - --- Application specific information functions -function app_description() - return I18N.translate("Dynamic DNS allows your router to be reached with " .. - "a fixed hostname while having a dynamically changing IP address.") -end -function app_title_back() - return [[]] - .. I18N.translate(app_title) - .. [[]] -end - --- Standardized application/service functions -function app_title_main() - return [[]] - .. I18N.translate(app_title) - .. [[]] -end -function service_version() - local ver = nil - - ver = UTIL.exec(srv_ver_cmd) - if #ver > 0 then return ver end - - IPKG.list_installed(srv_name, function(n, v, d) - if v and (#v > 0) then ver = v end - end - ) - return ver -end -function service_ok() - return IPKG.compare_versions((service_version() or "0"), ">=", srv_ver_min) -end - --- internal function to read all sections status and return data array -local function _get_status() - local uci = UCI.cursor() - local service = SYS.init.enabled("ddns") and 1 or 0 - local url_start = DISP.build_url("admin", "system", "startup") - local data = {} -- Array to transfer data to javascript - - data[#data+1] = { - enabled = service, -- service enabled - url_up = url_start, -- link to enable DDS (System-Startup) - } - - uci:foreach("ddns", "service", function (s) - - -- Get section we are looking at - -- and enabled state - local section = s[".name"] - local enabled = tonumber(s["enabled"]) or 0 - local datelast = "_empty_" -- formatted date of last update - local datenext = "_empty_" -- formatted date of next update - - -- get force seconds - local force_seconds = DDNS.calc_seconds( - tonumber(s["force_interval"]) or 72 , - s["force_unit"] or "hours" ) - -- get/validate pid and last update - local pid = DDNS.get_pid(section) - local uptime = SYS.uptime() - local lasttime = DDNS.get_lastupd(section) - if lasttime > uptime then -- /var might not be linked to /tmp - lasttime = 0 -- and/or not cleared on reboot - end - - -- no last update happen - if lasttime == 0 then - datelast = "_never_" - - -- we read last update - else - -- calc last update - -- sys.epoch - sys uptime + lastupdate(uptime) - local epoch = os.time() - uptime + lasttime - -- use linux date to convert epoch - datelast = DDNS.epoch2date(epoch) - -- calc and fill next update - datenext = DDNS.epoch2date(epoch + force_seconds) - end - - -- process running but update needs to happen - -- problems if force_seconds > uptime - force_seconds = (force_seconds > uptime) and uptime or force_seconds - if pid > 0 and ( lasttime + force_seconds - uptime ) <= 0 then - datenext = "_verify_" - - -- run once - elseif force_seconds == 0 then - datenext = "_runonce_" - - -- no process running and NOT enabled - elseif pid == 0 and enabled == 0 then - datenext = "_disabled_" - - -- no process running and enabled - elseif pid == 0 and enabled ~= 0 then - datenext = "_stopped_" - end - - -- get/set monitored interface and IP version - local iface = s["interface"] or "_nonet_" - local use_ipv6 = tonumber(s["use_ipv6"]) or 0 - if iface ~= "_nonet_" then - local ipv = (use_ipv6 == 1) and "IPv6" or "IPv4" - iface = ipv .. " / " .. iface - end - - -- try to get registered IP - local lookup_host = s["lookup_host"] or "_nolookup_" - local dnsserver = s["dns_server"] or "" - local force_ipversion = tonumber(s["force_ipversion"] or 0) - local force_dnstcp = tonumber(s["force_dnstcp"] or 0) - local is_glue = tonumber(s["is_glue"] or 0) - local command = luci_helper .. [[ -]] - if (use_ipv6 == 1) then command = command .. [[6]] end - if (force_ipversion == 1) then command = command .. [[f]] end - if (force_dnstcp == 1) then command = command .. [[t]] end - if (is_glue == 1) then command = command .. [[g]] end - command = command .. [[l ]] .. lookup_host - if (#dnsserver > 0) then command = command .. [[ -d ]] .. dnsserver end - command = command .. [[ -- get_registered_ip]] - local reg_ip = SYS.exec(command) - if reg_ip == "" then - reg_ip = "_nodata_" - end - - -- fill transfer array - data[#data+1] = { - section = section, - enabled = enabled, - iface = iface, - lookup = lookup_host, - reg_ip = reg_ip, - pid = pid, - datelast = datelast, - datenext = datenext - } - end) - - uci:unload("ddns") - return data -end - --- called by XHR.get from detail_logview.htm -function logread(section) - -- read application settings - local uci = UCI.cursor() - local ldir = uci:get("ddns", "global", "ddns_logdir") or "/var/log/ddns" - local lfile = ldir .. "/" .. section .. ".log" - local ldata = NXFS.readfile(lfile) - - if not ldata or #ldata == 0 then - ldata="_nodata_" - end - uci:unload("ddns") - HTTP.write(ldata) -end - --- called by XHR.get from overview_status.htm -function startstop(section, enabled) - local uci = UCI.cursor() - local pid = DDNS.get_pid(section) - local data = {} -- Array to transfer data to javascript - - -- if process running we want to stop and return - if pid > 0 then - local tmp = NX.kill(pid, 15) -- terminate - NX.nanosleep(2) -- 2 second "show time" - -- status changed so return full status - data = _get_status() - HTTP.prepare_content("application/json") - HTTP.write_json(data) - return - end - - -- read uncommitted changes - -- we don't save and commit data from other section or other options - -- only enabled will be done - local exec = true - local changed = uci:changes("ddns") - for k_config, v_section in pairs(changed) do - -- security check because uci.changes only gets our config - if k_config ~= "ddns" then - exec = false - break - end - for k_section, v_option in pairs(v_section) do - -- check if only section of button was changed - if k_section ~= section then - exec = false - break - end - for k_option, v_value in pairs(v_option) do - -- check if only enabled was changed - if k_option ~= "enabled" then - exec = false - break - end - end - end - end - - -- we can not execute because other - -- uncommitted changes pending, so exit here - if not exec then - HTTP.write("_uncommitted_") - return - end - - -- save enable state - uci:set("ddns", section, "enabled", ( (enabled == "true") and "1" or "0") ) - uci:save("ddns") - uci:commit("ddns") - uci:unload("ddns") - - -- start ddns-updater for section - local command = luci_helper .. [[ -S ]] .. section .. [[ -- start]] - os.execute(command) - NX.nanosleep(3) -- 3 seconds "show time" - - -- status changed so return full status - data = _get_status() - HTTP.prepare_content("application/json") - HTTP.write_json(data) -end - --- called by XHR.poll from overview_status.htm -function status() - local data = _get_status() - HTTP.prepare_content("application/json") - HTTP.write_json(data) -end - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/detail.lua b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/detail.lua deleted file mode 100644 index d283c54..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/detail.lua +++ /dev/null @@ -1,1479 +0,0 @@ --- Copyright 2008 Steven Barth --- Copyright 2008 Jo-Philipp Wich --- Copyright 2013 Manuel Munz --- Copyright 2014-2016 Christian Schoenebeck --- Licensed to the public under the Apache License 2.0. - -local NX = require "nixio" -local NXFS = require "nixio.fs" -local SYS = require "luci.sys" -local UTIL = require "luci.util" -local HTTP = require "luci.http" -local DISP = require "luci.dispatcher" -local WADM = require "luci.tools.webadmin" -local DTYP = require "luci.cbi.datatypes" -local CTRL = require "luci.controller.ddns" -- this application's controller -local DDNS = require "luci.tools.ddns" -- ddns multiused functions - --- takeover arguments -- ####################################################### -local section = arg[1] - --- html constants -- ########################################################### -local font_red = "" -local font_off = "" -local bold_on = "" -local bold_off = "" - --- error text constants -- ##################################################### -local err_ipv6_plain = translate("IPv6 not supported") .. " - " .. - translate("please select 'IPv4' address version") -local err_ipv6_basic = bold_on .. - font_red .. - translate("IPv6 not supported") .. - font_off .. - "
                          " .. translate("please select 'IPv4' address version") .. - bold_off -local err_ipv6_other = bold_on .. - font_red .. - translate("IPv6 not supported") .. - font_off .. - "
                          " .. translate("please select 'IPv4' address version in") .. " " .. - [[]] .. - translate("Basic Settings") .. - [[]] .. - bold_off - -function err_tab_basic(self) - return translate("Basic Settings") .. " - " .. self.title .. ": " -end -function err_tab_adv(self) - return translate("Advanced Settings") .. " - " .. self.title .. ": " -end -function err_tab_timer(self) - return translate("Timer Settings") .. " - " .. self.title .. ": " -end - --- read services/services_ipv6 files -- ######################################## -local services4 = { } -- IPv4 -- -local fd4 = io.open("/etc/ddns/services", "r") -if fd4 then - local ln, s, t - repeat - ln = fd4:read("*l") - s = ln and ln:match('^%s*".*') -- only handle lines beginning with " - s = s and s:gsub('"','') -- remove " - t = s and UTIL.split(s,"(%s+)",nil,true) -- split on whitespaces - if t then services4[t[1]]=t[2] end - until not ln - fd4:close() -end - -local services6 = { } -- IPv6 -- -local fd6 = io.open("/etc/ddns/services_ipv6", "r") -if fd6 then - local ln, s, t - repeat - ln = fd6:read("*l") - s = ln and ln:match('^%s*".*') -- only handle lines beginning with " - s = s and s:gsub('"','') -- remove " - t = s and UTIL.split(s,"(%s+)",nil,true) -- split on whitespaces - if t then services6[t[1]]=t[2] end - until not ln - fd6:close() -end - --- multi-used functions -- #################################################### --- function to verify settings around ip_source --- will use dynamic_dns_lucihelper to check if --- local IP can be read -local function _verify_ip_source() - -- section is globally defined here be calling agrument (see above) - local _arg - - local _ipv6 = usev6:formvalue(section) - local _source = (_ipv6 == "1") - and src6:formvalue(section) - or src4:formvalue(section) - - local command = CTRL.luci_helper .. [[ -]] - if (_ipv6 == "1") then command = command .. [[6]] end - - if _source == "network" then - _arg = (_ipv6 == "1") - and ipn6:formvalue(section) - or ipn4:formvalue(section) - command = command .. [[n ]] .. _arg - elseif _source == "web" then - _arg = (_ipv6 == "1") - and iurl6:formvalue(section) - or iurl4:formvalue(section) - command = command .. [[u ]] .. _arg - - -- proxy only needed for checking url - _arg = (pxy) and pxy:formvalue(section) or "" - if (_arg and #_arg > 0) then - command = command .. [[ -p ]] .. _arg - end - elseif _source == "interface" then - command = command .. [[i ]] .. ipi:formvalue(section) - elseif _source == "script" then - command = command .. [[s ]] .. ips:formvalue(section) - end - command = command .. [[ -- get_local_ip]] - return (SYS.call(command) == 0) -end - --- function to check if option is used inside url or script --- return -1 on error, 0 NOT required, 1 required -local function _option_used(option, urlscript) - local surl -- search string for url - local ssh -- search string for script - local required -- option used inside url or script - - if option == "domain" then surl, ssh = '%[DOMAIN%]', '%$domain' - elseif option == "username" then surl, ssh = '%[USERNAME%]', '%$username' - elseif option == "password" then surl, ssh = '%[PASSWORD%]', '%$password' - elseif option == "param_enc" then surl, ssh = '%[PARAMENC%]', '%$param_enc' - elseif option == "param_opt" then surl, ssh = '%[PARAMOPT%]', '%$param_opt' - else - error("undefined option") - return -1 -- return on error - end - - local required = false - -- handle url - if urlscript:find('http') then - required = ( urlscript:find(surl) ) - -- handle script - else - if not urlscript:find("/") then - -- might be inside ddns-scripts directory - urlscript = "/usr/lib/ddns/" .. urlscript - end - -- problem with script exit here - if not NXFS.access(urlscript) then return -1 end - - local f = io.input(urlscript) - -- still problem with script exit here - if not f then return -1 end - for l in f:lines() do - repeat - if l:find('^#') then break end -- continue on comment lines - required = ( l:find(surl) or l:find(ssh) ) - until true - if required then break end - end - f:close() - end - return (required and 1 or 0) -end - --- function to verify if option is valid -local function _option_validate(self, value) - -- section is globally defined here be calling agrument (see above) - local fusev6 = usev6:formvalue(section) or "0" - local fsvc4 = svc4:formvalue(section) or "-" - local fsvc6 = svc6:formvalue(section) or "-" - local urlsh, used - - -- IP-Version dependent custom service selected - if (fusev6 == "0" and fsvc4 == "-") or - (fusev6 == "1" and fsvc6 == "-") then - -- read custom url - urlsh = uurl:formvalue(section) or "" - -- no url then read custom script - if (#urlsh == 0) then - urlsh = ush:formvalue(section) or "" - end - -- IPv4 read from services4 table - elseif (fusev6 == "0") then - urlsh = services4[fsvc4] or "" - -- IPv6 read from services6 table - else - urlsh = services6[fsvc6] or "" - end - -- problem with url or script exit here - -- error handled somewhere else - if (#urlsh == 0) then return "" end - - used = _option_used(self.option, urlsh) - -- on error or not used return empty sting - if used < 1 then return "" end - -- needed but no data then return error - if not value or (#value == 0) then - return nil, err_tab_basic(self) .. translate("missing / required") - end - return value -end - --- cbi-map definition -- ####################################################### -local m = Map("ddns") -m.title = CTRL.app_title_back() -m.description = CTRL.app_description() -m.redirect = DISP.build_url("admin", "services", "ddns") - -m.on_after_commit = function(self) - if self.changed then -- changes ? - local pid = DDNS.get_pid(section) - if pid > 0 then -- running ? - local tmp = NX.kill(pid, 1) -- send SIGHUP - end - end -end - --- provider switch was requested, save and reload page -if m:formvalue("cbid.ddns.%s._switch" % section) then -- section == arg[1] - local fsvc - local fusev6 = m:formvalue("cbid.ddns.%s.use_ipv6" % section) or "0" - if fusev6 == "1" then - fsvc = m:formvalue("cbid.ddns.%s.ipv6_service_name" % section) or "" - else - fsvc = m:formvalue("cbid.ddns.%s.ipv4_service_name" % section) or "" - end - - if fusev6 ~= (m:get(section, "use_ipv6") or "0") then -- IPv6 was changed - m:set(section, "use_ipv6", fusev6) -- save it - end - - if fsvc ~= "-" then -- NOT "custom" - m:set(section, "service_name", fsvc) -- save it - else -- else - m:del(section, "service_name") -- delete it - end - m.uci:save(m.config) - - -- reload page - HTTP.redirect( DISP.build_url("admin", "services", "ddns", "detail", section) ) - return -end - --- read application settings -- ################################################ --- log directory -local logdir = m.uci:get(m.config, "global", "ddns_logdir") or "/var/log/ddns" - --- cbi-section definition -- ################################################### -local ns = m:section( NamedSection, section, "service", - translate("Details for") .. ([[: %s]] % section), - translate("Configure here the details for selected Dynamic DNS service.") ) -ns.instance = section -- arg [1] -ns:tab("basic", translate("Basic Settings"), nil ) -ns:tab("advanced", translate("Advanced Settings"), nil ) -ns:tab("timer", translate("Timer Settings"), nil ) -ns:tab("logview", translate("Log File Viewer"), nil ) - --- TAB: Basic ##################################################################################### --- enabled -- ################################################################# -en = ns:taboption("basic", Flag, "enabled", - translate("Enabled"), - translate("Enable service") ) -en.orientation = "horizontal" - --- IPv4/IPv6 - lookup_host -- ################################################# -luh = ns:taboption("basic", Value, "lookup_host", - translate("Lookup Hostname"), - translate("Hostname/FQDN to validate, if an IP update happens or is necessary") ) -luh.rmempty = false -luh.placeholder = "myhost.example.com" -function luh.validate(self, value) - if not value - or not (#value > 0) - or not DTYP.hostname(value) then - return nil, err_tab_basic(self) .. translate("invalid FQDN / required - Sample") .. ": 'myhost.example.com'" - else - return UTIL.trim(value) - end -end -function luh.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- use_ipv6 -- ################################################################ -usev6 = ns:taboption("basic", ListValue, "use_ipv6", - translate("IP address version"), - translate("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider") ) -usev6.widget = "radio" -usev6.default = "0" -usev6:value("0", translate("IPv4-Address") ) -function usev6.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) or "0" - if DDNS.has_ipv6 or (value == "1" and not DDNS.has_ipv6) then - self:value("1", translate("IPv6-Address") ) - end - if value == "1" and not DDNS.has_ipv6 then - self.description = err_ipv6_basic - end - return value -end -function usev6.validate(self, value) - if (value == "1" and DDNS.has_ipv6) or value == "0" then - return value - end - return nil, err_tab_basic(self) .. err_ipv6_plain -end -function usev6.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4 - service_name -- ##################################################### -svc4 = ns:taboption("basic", ListValue, "ipv4_service_name", - translate("DDNS Service provider") .. " [IPv4]" ) -svc4.default = "-" -svc4:depends("use_ipv6", "0") -- only show on IPv4 -function svc4.cfgvalue(self, section) - local v = DDNS.read_value(self, section, "service_name") - if v and (#v > 0) then - for s, u in UTIL.kspairs(services4) do - if v == s then return v end - end - end - return "-" -end -function svc4.validate(self, value) - if usev6:formvalue(section) ~= "1" then -- do only on IPv4 - return value - else - return "" -- suppress validate error - end -end -function svc4.write(self, section, value) - if usev6:formvalue(section) ~= "1" then -- do only IPv4 here - self.map:del(section, self.option) -- to be shure - if value ~= "-" then -- and write "service_name - self.map:del(section, "update_url") -- delete update_url - self.map:del(section, "update_script") -- delete update_script - return self.map:set(section, "service_name", value) - else - return self.map:del(section, "service_name") - end - end -end -function svc4.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv6 - service_name -- ##################################################### -svc6 = ns:taboption("basic", ListValue, "ipv6_service_name", - translate("DDNS Service provider") .. " [IPv6]" ) -svc6.default = "-" -svc6:depends("use_ipv6", "1") -- only show on IPv6 -if not DDNS.has_ipv6 then - svc6.description = err_ipv6_basic -end -function svc6.cfgvalue(self, section) - local v = DDNS.read_value(self, section, "service_name") - if v and (#v > 0) then - for s, u in UTIL.kspairs(services4) do - if v == s then return v end - end - end - return "-" -end -function svc6.validate(self, value) - if usev6:formvalue(section) == "1" then -- do only on IPv6 - if DDNS.has_ipv6 then return value end - return nil, err_tab_basic(self) .. err_ipv6_plain - else - return "" -- suppress validate error - end -end -function svc6.write(self, section, value) - if usev6:formvalue(section) == "1" then -- do only when IPv6 - self.map:del(section, self.option) -- delete "ipv6_service_name" helper - if value ~= "-" then -- and write "service_name - self.map:del(section, "update_url") -- delete update_url - self.map:del(section, "update_script") -- delete update_script - return self.map:set(section, "service_name", value) - else - return self.map:del(section, "service_name") - end - end -end -function svc6.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - change Provider -- ############################################# -svs = ns:taboption("basic", Button, "_switch") -svs.title = translate("Really change DDNS provider?") -svs.inputtitle = translate("Change provider") -svs.inputstyle = "apply" - --- IPv4/IPv6 - update_url -- ################################################## -uurl = ns:taboption("basic", Value, "update_url", - translate("Custom update-URL"), - translate("Update URL to be used for updating your DDNS Provider." .. "
                          " .. - "Follow instructions you will find on their WEB page.") ) -function uurl.validate(self, value) - local fush = ush:formvalue(section) - local fusev6 = usev6:formvalue(section) - - if (fusev6 ~= "1" and svc4:formvalue(section) ~= "-") or - (fusev6 == "1" and svc6:formvalue(section) ~= "-") then - return "" -- suppress validate error - elseif not value or (#value == 0) then - if not fush or (#fush == 0) then - return nil, err_tab_basic(self) .. translate("missing / required") - else - return "" -- suppress validate error / update_script is given - end - elseif (#fush > 0) then - return nil, err_tab_basic(self) .. translate("either url or script could be set") - end - - local url = DDNS.parse_url(value) - if not url.scheme == "http" then - return nil, err_tab_basic(self) .. translate("must start with 'http://'") - elseif not url.query then - return nil, err_tab_basic(self) .. " " .. translate("missing / required") - elseif not url.host then - return nil, err_tab_basic(self) .. " " .. translate("missing / required") - elseif SYS.call([[nslookup ]] .. url.host .. [[ >/dev/null 2>&1]]) ~= 0 then - return nil, err_tab_basic(self) .. translate("can not resolve host: ") .. url.host - end - - return value -end -function uurl.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - update_script -- ############################################### -ush = ns:taboption("basic", Value, "update_script", - translate("Custom update-script"), - translate("Custom update script to be used for updating your DDNS Provider.") ) -function ush.validate(self, value) - local fuurl = uurl:formvalue(section) - local fusev6 = usev6:formvalue(section) - - if (fusev6 ~= "1" and svc4:formvalue(section) ~= "-") or - (fusev6 == "1" and svc6:formvalue(section) ~= "-") then - return "" -- suppress validate error - elseif not value or (#value == 0) then - if not fuurl or (#fuurl == 0) then - return nil, err_tab_basic(self) .. translate("missing / required") - else - return "" -- suppress validate error / update_url is given - end - elseif (#fuurl > 0) then - return nil, err_tab_basic(self) .. translate("either url or script could be set") - elseif not NXFS.access(value) then - return nil, err_tab_basic(self) .. translate("File not found") - end - return value -end -function ush.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - domain -- ###################################################### -dom = ns:taboption("basic", Value, "domain", - translate("Domain"), - translate("Replaces [DOMAIN] in Update-URL") ) -dom.placeholder = "myhost.example.com" -function dom.validate(self, value) - return _option_validate(self, value) -end -function dom.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - username -- #################################################### -user = ns:taboption("basic", Value, "username", - translate("Username"), - translate("Replaces [USERNAME] in Update-URL (URL-encoded)") ) -function user.validate(self, value) - return _option_validate(self, value) -end -function user.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - password -- #################################################### -pw = ns:taboption("basic", Value, "password", - translate("Password"), - translate("Replaces [PASSWORD] in Update-URL (URL-encoded)") ) -pw.password = true -function pw.validate(self, value) - return _option_validate(self, value) -end -function pw.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - param_enc -- ################################################### -pe = ns:taboption("basic", Value, "param_enc", - translate("Optional Encoded Parameter"), - translate("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)") ) -function pe.validate(self, value) - return _option_validate(self, value) -end -function pe.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - param_enc -- ################################################### -po = ns:taboption("basic", Value, "param_opt", - translate("Optional Parameter"), - translate("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)") ) -function po.validate(self, value) - return _option_validate(self, value) -end -function po.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- handled service dependent show/display -- ################################## --- IPv4 -- -local cv4 = svc4:cfgvalue(section) -if cv4 ~= "-" then - svs:depends ("ipv4_service_name", "-" ) -- show only if "-" - ush:depends ("ipv4_service_name", "?") - uurl:depends("ipv4_service_name", "?") -else - uurl:depends("ipv4_service_name", "-") - ush:depends ("ipv4_service_name", "-") - dom:depends("ipv4_service_name", "-" ) - user:depends("ipv4_service_name", "-" ) - pw:depends("ipv4_service_name", "-" ) - pe:depends("ipv4_service_name", "-" ) - po:depends("ipv4_service_name", "-" ) -end -for s, u in UTIL.kspairs(services4) do - svc4:value(s) -- fill DropDown-List - if cv4 ~= s then - svs:depends("ipv4_service_name", s ) - else - dom:depends ("ipv4_service_name", ((_option_used(dom.option, u) == 1) and s or "?") ) - user:depends("ipv4_service_name", ((_option_used(user.option, u) == 1) and s or "?") ) - pw:depends ("ipv4_service_name", ((_option_used(pw.option, u) == 1) and s or "?") ) - pe:depends ("ipv4_service_name", ((_option_used(pe.option, u) == 1) and s or "?") ) - po:depends ("ipv4_service_name", ((_option_used(po.option, u) == 1) and s or "?") ) - end -end -svc4:value("-", translate("-- custom --") ) - --- IPv6 -- -local cv6 = svc6:cfgvalue(section) -if cv6 ~= "-" then - svs:depends ("ipv6_service_name", "-" ) - uurl:depends("ipv6_service_name", "?") - ush:depends ("ipv6_service_name", "?") -else - uurl:depends("ipv6_service_name", "-") - ush:depends ("ipv6_service_name", "-") - dom:depends("ipv6_service_name", "-" ) - user:depends("ipv6_service_name", "-" ) - pw:depends("ipv6_service_name", "-" ) - pe:depends("ipv6_service_name", "-" ) - po:depends("ipv6_service_name", "-" ) -end -for s, u in UTIL.kspairs(services6) do - svc6:value(s) -- fill DropDown-List - if cv6 ~= s then - svs:depends("ipv6_service_name", s ) - else - dom:depends ("ipv6_service_name", ((_option_used(dom.option, u) == 1) and s or "?") ) - user:depends("ipv6_service_name", ((_option_used(user.option, u) == 1) and s or "?") ) - pw:depends ("ipv6_service_name", ((_option_used(pw.option, u) == 1) and s or "?") ) - pe:depends ("ipv6_service_name", ((_option_used(pe.option, u) == 1) and s or "?") ) - po:depends ("ipv6_service_name", ((_option_used(po.option, u) == 1) and s or "?") ) - end -end -svc6:value("-", translate("-- custom --") ) - --- IPv4/IPv6 - use_https -- ################################################### -if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then - https = ns:taboption("basic", Flag, "use_https", - translate("Use HTTP Secure") ) - https.orientation = "horizontal" - function https.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) - if not DDNS.has_ssl and value == "1" then - self.description = bold_on .. font_red .. - translate("HTTPS not supported") .. font_off .. "
                          " .. - translate("please disable") .. " !" .. bold_off - else - self.description = translate("Enable secure communication with DDNS provider") - end - return value - end - function https.validate(self, value) - if (value == "1" and DDNS.has_ssl ) or value == "0" then return value end - return nil, err_tab_basic(self) .. translate("HTTPS not supported") .. " !" - end - function https.write(self, section, value) - if value == "1" then - return self.map:set(section, self.option, value) - else - self.map:del(section, "cacert") - return self.map:del(section, self.option) - end - end -end - --- IPv4/IPv6 - cacert -- ###################################################### -if DDNS.has_ssl then - cert = ns:taboption("basic", Value, "cacert", - translate("Path to CA-Certificate"), - translate("directory or path/file") .. "
                          " .. - translate("or") .. bold_on .. " IGNORE " .. bold_off .. - translate("to run HTTPS without verification of server certificates (insecure)") ) - cert:depends("use_https", "1") - cert.placeholder = "/etc/ssl/certs" - cert.forcewrite = true - function cert.validate(self, value) - if https:formvalue(section) ~= "1" then - return "" -- suppress validate error if NOT https - end - if value then -- otherwise errors in datatype check - if DTYP.directory(value) - or DTYP.file(value) - or (value == "IGNORE") - or (#value == 0) then - return value - end - end - return nil, err_tab_basic(self) .. - translate("file or directory not found or not 'IGNORE'") .. " !" - end - function cert.parse(self, section, novld) - DDNS.value_parse(self, section, novld) - end -end - --- TAB: Advanced ################################################################################# --- IPv4 - ip_source -- ######################################################## -src4 = ns:taboption("advanced", ListValue, "ipv4_source", - translate("IP address source") .. " [IPv4]", - translate("Defines the source to read systems IPv4-Address from, that will be send to the DDNS provider") ) -src4:depends("use_ipv6", "0") -- IPv4 selected -src4.default = "network" -src4:value("network", translate("Network")) -src4:value("web", translate("URL")) -src4:value("interface", translate("Interface")) -src4:value("script", translate("Script")) -function src4.cfgvalue(self, section) - return DDNS.read_value(self, section, "ip_source") -end -function src4.validate(self, value) - if usev6:formvalue(section) == "1" then - return "" -- ignore on IPv6 selected - elseif not _verify_ip_source() then - return nil, err_tab_adv(self) .. - translate("can not detect local IP. Please select a different Source combination") - else - return value - end -end -function src4.write(self, section, value) - if usev6:formvalue(section) == "1" then - return true -- ignore on IPv6 selected - elseif value == "network" then - self.map:del(section, "ip_url") -- delete not need parameters - self.map:del(section, "ip_interface") - self.map:del(section, "ip_script") - elseif value == "web" then - self.map:del(section, "ip_network") -- delete not need parameters - self.map:del(section, "ip_interface") - self.map:del(section, "ip_script") - elseif value == "interface" then - self.map:del(section, "ip_network") -- delete not need parameters - self.map:del(section, "ip_url") - self.map:del(section, "ip_script") - elseif value == "script" then - self.map:del(section, "ip_network") - self.map:del(section, "ip_url") -- delete not need parameters - self.map:del(section, "ip_interface") - end - self.map:del(section, self.option) -- delete "ipv4_source" helper - return self.map:set(section, "ip_source", value) -- and write "ip_source -end -function src4.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv6 - ip_source -- ######################################################## -src6 = ns:taboption("advanced", ListValue, "ipv6_source", - translate("IP address source") .. " [IPv6]", - translate("Defines the source to read systems IPv6-Address from, that will be send to the DDNS provider") ) -src6:depends("use_ipv6", 1) -- IPv6 selected -src6.default = "network" -src6:value("network", translate("Network")) -src6:value("web", translate("URL")) -src6:value("interface", translate("Interface")) -src6:value("script", translate("Script")) -if not DDNS.has_ipv6 then - src6.description = err_ipv6_other -end -function src6.cfgvalue(self, section) - return DDNS.read_value(self, section, "ip_source") -end -function src6.validate(self, value) - if usev6:formvalue(section) ~= "1" then - return "" -- ignore on IPv4 selected - elseif not DDNS.has_ipv6 then - return nil, err_tab_adv(self) .. err_ipv6_plain - elseif not _verify_ip_source() then - return nil, err_tab_adv(self) .. - translate("can not detect local IP. Please select a different Source combination") - else - return value - end -end -function src6.write(self, section, value) - if usev6:formvalue(section) ~= "1" then - return true -- ignore on IPv4 selected - elseif value == "network" then - self.map:del(section, "ip_url") -- delete not need parameters - self.map:del(section, "ip_interface") - self.map:del(section, "ip_script") - elseif value == "web" then - self.map:del(section, "ip_network") -- delete not need parameters - self.map:del(section, "ip_interface") - self.map:del(section, "ip_script") - elseif value == "interface" then - self.map:del(section, "ip_network") -- delete not need parameters - self.map:del(section, "ip_url") - self.map:del(section, "ip_script") - elseif value == "script" then - self.map:del(section, "ip_network") - self.map:del(section, "ip_url") -- delete not need parameters - self.map:del(section, "ip_interface") - end - self.map:del(section, self.option) -- delete "ipv4_source" helper - return self.map:set(section, "ip_source", value) -- and write "ip_source -end -function src6.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4 - ip_network (default "wan") -- ####################################### -ipn4 = ns:taboption("advanced", ListValue, "ipv4_network", - translate("Network") .. " [IPv4]", - translate("Defines the network to read systems IPv4-Address from") ) -ipn4:depends("ipv4_source", "network") -ipn4.default = "wan" -WADM.cbi_add_networks(ipn4) -function ipn4.cfgvalue(self, section) - return DDNS.read_value(self, section, "ip_network") -end -function ipn4.validate(self, value) - if usev6:formvalue(section) == "1" - or src4:formvalue(section) ~= "network" then - -- ignore if IPv6 selected OR - -- ignore everything except "network" - return "" - else - return value - end -end -function ipn4.write(self, section, value) - if usev6:formvalue(section) == "1" - or src4:formvalue(section) ~= "network" then - -- ignore if IPv6 selected OR - -- ignore everything except "network" - return true - else - -- set also as "interface" for monitoring events changes/hot-plug - self.map:set(section, "interface", value) - self.map:del(section, self.option) -- delete "ipv4_network" helper - return self.map:set(section, "ip_network", value) -- and write "ip_network" - end -end -function ipn4.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv6 - ip_network (default "wan6") -- ###################################### -ipn6 = ns:taboption("advanced", ListValue, "ipv6_network", - translate("Network") .. " [IPv6]" ) -ipn6:depends("ipv6_source", "network") -ipn6.default = "wan6" -WADM.cbi_add_networks(ipn6) -if DDNS.has_ipv6 then - ipn6.description = translate("Defines the network to read systems IPv6-Address from") -else - ipn6.description = err_ipv6_other -end -function ipn6.cfgvalue(self, section) - return DDNS.read_value(self, section, "ip_network") -end -function ipn6.validate(self, value) - if usev6:formvalue(section) ~= "1" - or src6:formvalue(section) ~= "network" then - -- ignore if IPv4 selected OR - -- ignore everything except "network" - return "" - elseif DDNS.has_ipv6 then - return value - else - return nil, err_tab_adv(self) .. err_ipv6_plain - end -end -function ipn6.write(self, section, value) - if usev6:formvalue(section) ~= "1" - or src6:formvalue(section) ~= "network" then - -- ignore if IPv4 selected OR - -- ignore everything except "network" - return true - else - -- set also as "interface" for monitoring events changes/hotplug - self.map:set(section, "interface", value) - self.map:del(section, self.option) -- delete "ipv6_network" helper - return self.map:set(section, "ip_network", value) -- and write "ip_network" - end -end -function ipn6.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4 - ip_url (default "checkip.dyndns.com") -- ############################ -iurl4 = ns:taboption("advanced", Value, "ipv4_url", - translate("URL to detect") .. " [IPv4]", - translate("Defines the Web page to read systems IPv4-Address from") ) -iurl4:depends("ipv4_source", "web") -iurl4.default = "http://checkip.dyndns.com" -function iurl4.cfgvalue(self, section) - return DDNS.read_value(self, section, "ip_url") -end -function iurl4.validate(self, value) - if usev6:formvalue(section) == "1" - or src4:formvalue(section) ~= "web" then - -- ignore if IPv6 selected OR - -- ignore everything except "web" - return "" - elseif not value or #value == 0 then - return nil, err_tab_adv(self) .. translate("missing / required") - end - - local url = DDNS.parse_url(value) - if not (url.scheme == "http" or url.scheme == "https") then - return nil, err_tab_adv(self) .. translate("must start with 'http://'") - elseif not url.host then - return nil, err_tab_adv(self) .. " " .. translate("missing / required") - elseif SYS.call([[nslookup ]] .. url.host .. [[>/dev/null 2>&1]]) ~= 0 then - return nil, err_tab_adv(self) .. translate("can not resolve host: ") .. url.host - else - return value - end -end -function iurl4.write(self, section, value) - if usev6:formvalue(section) == "1" - or src4:formvalue(section) ~= "web" then - -- ignore if IPv6 selected OR - -- ignore everything except "web" - return true - else - self.map:del(section, self.option) -- delete "ipv4_url" helper - return self.map:set(section, "ip_url", value) -- and write "ip_url" - end -end -function iurl4.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv6 - ip_url (default "checkipv6.dyndns.com") -- ########################## -iurl6 = ns:taboption("advanced", Value, "ipv6_url", - translate("URL to detect") .. " [IPv6]" ) -iurl6:depends("ipv6_source", "web") -iurl6.default = "http://checkipv6.dyndns.com" -if DDNS.has_ipv6 then - iurl6.description = translate("Defines the Web page to read systems IPv6-Address from") -else - iurl6.description = err_ipv6_other -end -function iurl6.cfgvalue(self, section) - return DDNS.read_value(self, section, "ip_url") -end -function iurl6.validate(self, value) - if usev6:formvalue(section) ~= "1" - or src6:formvalue(section) ~= "web" then - -- ignore if IPv4 selected OR - -- ignore everything except "web" - return "" - elseif not DDNS.has_ipv6 then - return nil, err_tab_adv(self) .. err_ipv6_plain - elseif not value or #value == 0 then - return nil, err_tab_adv(self) .. translate("missing / required") - end - - local url = DDNS.parse_url(value) - if not (url.scheme == "http" or url.scheme == "https") then - return nil, err_tab_adv(self) .. translate("must start with 'http://'") - elseif not url.host then - return nil, err_tab_adv(self) .. " " .. translate("missing / required") - elseif SYS.call([[nslookup ]] .. url.host .. [[>/dev/null 2>&1]]) ~= 0 then - return nil, err_tab_adv(self) .. translate("can not resolve host: ") .. url.host - else - return value - end -end -function iurl6.write(self, section, value) - if usev6:formvalue(section) ~= "1" - or src6:formvalue(section) ~= "web" then - -- ignore if IPv4 selected OR - -- ignore everything except "web" - return true - else - self.map:del(section, self.option) -- delete "ipv6_url" helper - return self.map:set(section, "ip_url", value) -- and write "ip_url" - end -end -function iurl6.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4 + IPv6 - ip_interface -- ############################################## -ipi = ns:taboption("advanced", ListValue, "ip_interface", - translate("Interface"), - translate("Defines the interface to read systems IP-Address from") ) -ipi:depends("ipv4_source", "interface") -- IPv4 -ipi:depends("ipv6_source", "interface") -- or IPv6 -for _, v in pairs(SYS.net.devices()) do - -- show only interface set to a network - -- and ignore loopback - net = WADM.iface_get_network(v) - if net and net ~= "loopback" then - ipi:value(v) - end -end -function ipi.validate(self, value) - local fusev6 = usev6:formvalue(section) - if (fusev6 ~= "1" and src4:formvalue(section) ~= "interface") - or (fusev6 == "1" and src6:formvalue(section) ~= "interface") then - return "" - else - return value - end -end -function ipi.write(self, section, value) - local fusev6 = usev6:formvalue(section) - if (fusev6 ~= "1" and src4:formvalue(section) ~= "interface") - or (fusev6 == "1" and src6:formvalue(section) ~= "interface") then - return true - else - -- get network from device to - -- set also as "interface" for monitoring events changes/hotplug - local net = WADM.iface_get_network(value) - self.map:set(section, "interface", net) - return self.map:set(section, self.option, value) - end -end -function ipi.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4 + IPv6 - ip_script -- ################################################# -ips = ns:taboption("advanced", Value, "ip_script", - translate("Script"), - translate("User defined script to read systems IP-Address") ) -ips:depends("ipv4_source", "script") -- IPv4 -ips:depends("ipv6_source", "script") -- or IPv6 -ips.placeholder = "/path/to/script.sh" -function ips.validate(self, value) - local fusev6 = usev6:formvalue(section) - local split - if value then split = UTIL.split(value, " ") end - - if (fusev6 ~= "1" and src4:formvalue(section) ~= "script") - or (fusev6 == "1" and src6:formvalue(section) ~= "script") then - return "" - elseif not value or not (#value > 0) or not NXFS.access(split[1], "x") then - return nil, err_tab_adv(self) .. - translate("not found or not executable - Sample: '/path/to/script.sh'") - else - return value - end -end -function ips.write(self, section, value) - local fusev6 = usev6:formvalue(section) - if (fusev6 ~= "1" and src4:formvalue(section) ~= "script") - or (fusev6 == "1" and src6:formvalue(section) ~= "script") then - return true - else - return self.map:set(section, self.option, value) - end -end -function ips.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4 - interface - default "wan" -- ######################################## --- event network to monitor changes/hotplug/dynamic_dns_updater.sh --- only needs to be set if "ip_source"="web" or "script" --- if "ip_source"="network" or "interface" we use their network -eif4 = ns:taboption("advanced", ListValue, "ipv4_interface", - translate("Event Network") .. " [IPv4]", - translate("Network on which the ddns-updater scripts will be started") ) -eif4:depends("ipv4_source", "web") -eif4:depends("ipv4_source", "script") -eif4.default = "wan" -WADM.cbi_add_networks(eif4) -function eif4.cfgvalue(self, section) - return DDNS.read_value(self, section, "interface") -end -function eif4.validate(self, value) - local fsrc4 = src4:formvalue(section) or "" - if usev6:formvalue(section) == "1" - or fsrc4 == "network" - or fsrc4 == "interface" then - return "" -- ignore IPv6, network, interface - else - return value - end -end -function eif4.write(self, section, value) - local fsrc4 = src4:formvalue(section) or "" - if usev6:formvalue(section) == "1" - or fsrc4 == "network" - or fsrc4 == "interface" then - return true -- ignore IPv6, network, interface - else - self.map:del(section, self.option) -- delete "ipv4_interface" helper - return self.map:set(section, "interface", value) -- and write "interface" - end -end -function eif4.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv6 - interface - default "wan6" -- ####################################### --- event network to monitor changes/hotplug --- only needs to be set if "ip_source"="web" or "script" --- if "ip_source"="network" or "interface" we use their network -eif6 = ns:taboption("advanced", ListValue, "ipv6_interface", - translate("Event Network") .. " [IPv6]" ) -eif6:depends("ipv6_source", "web") -eif6:depends("ipv6_source", "script") -eif6.default = "wan6" -WADM.cbi_add_networks(eif6) -if not DDNS.has_ipv6 then - eif6.description = err_ipv6_other -else - eif6.description = translate("Network on which the ddns-updater scripts will be started") -end -function eif6.cfgvalue(self, section) - return DDNS.read_value(self, section, "interface") -end -function eif6.validate(self, value) - local fsrc6 = src6:formvalue(section) or "" - if usev6:formvalue(section) ~= "1" - or fsrc6 == "network" - or fsrc6 == "interface" then - return "" -- ignore IPv4, network, interface - elseif not DDNS.has_ipv6 then - return nil, err_tab_adv(self) .. err_ipv6_plain - else - return value - end -end -function eif6.write(self, section, value) - local fsrc6 = src6:formvalue(section) or "" - if usev6:formvalue(section) ~= "1" - or fsrc6 == "network" - or fsrc6 == "interface" then - return true -- ignore IPv4, network, interface - else - self.map:del(section, self.option) -- delete "ipv6_interface" helper - return self.map:set(section, "interface", value) -- and write "interface" - end -end -function eif6.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- IPv4/IPv6 - bind_network -- ################################################ -if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then - bnet = ns:taboption("advanced", ListValue, "bind_network", - translate("Bind Network") ) - bnet:depends("ipv4_source", "web") - bnet:depends("ipv6_source", "web") - bnet.default = "" - bnet:value("", translate("-- default --")) - WADM.cbi_add_networks(bnet) - function bnet.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) - if not DDNS.has_bindnet and value ~= "" then - self.description = bold_on .. font_red .. - translate("Binding to a specific network not supported") .. font_off .. "
                          " .. - translate("please set to 'default'") .. " !" .. bold_off - else - self.description = translate("OPTIONAL: Network to use for communication") .. - "
                          " .. translate("Casual users should not change this setting") - end - return value - end - function bnet.validate(self, value) - if ( (value ~= "") and DDNS.has_bindnet ) or (value == "") then return value end - return nil, err_tab_adv(self) .. translate("Binding to a specific network not supported") .. " !" - end - function bnet.parse(self, section, novld) - DDNS.value_parse(self, section, novld) - end -end - --- IPv4 + IPv6 - force_ipversion -- ########################################### --- optional to force wget/curl and host to use only selected IP version --- command parameter "-4" or "-6" -if DDNS.has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then - fipv = ns:taboption("advanced", Flag, "force_ipversion", - translate("Force IP Version") ) - fipv.orientation = "horizontal" - function fipv.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) - if not DDNS.has_forceip and value ~= "0" then - self.description = bold_on .. font_red .. - translate("Force IP Version not supported") .. font_off .. "
                          " .. - translate("please disable") .. " !" .. bold_off - else - self.description = translate("OPTIONAL: Force the usage of pure IPv4/IPv6 only communication.") - end - return value - end - function fipv.validate(self, value) - if (value == "1" and DDNS.has_forceip) or value == "0" then return value end - return nil, err_tab_adv(self) .. translate("Force IP Version not supported") - end -end - --- IPv4 + IPv6 - dns_server -- ################################################ --- optional DNS Server to use resolving my IP -if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then - dns = ns:taboption("advanced", Value, "dns_server", - translate("DNS-Server"), - translate("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") .. "
                          " .. - translate("Format: IP or FQDN")) - dns.placeholder = "mydns.lan" - function dns.validate(self, value) - -- if .datatype is set, then it is checked before calling this function - if not value or (#value == 0) then - return "" -- ignore on empty - elseif not DDNS.has_dnsserver then - return nil, err_tab_adv(self) .. translate("Specifying a DNS-Server is not supported") - elseif not DTYP.host(value) then - return nil, err_tab_adv(self) .. translate("use hostname, FQDN, IPv4- or IPv6-Address") - else - local ipv6 = usev6:formvalue(section) or "0" - local force = fipv:formvalue(section) or "0" - local command = CTRL.luci_helper .. [[ -]] - if (ipv6 == 1) then command = command .. [[6]] end - if (force == 1) then command = command .. [[f]] end - command = command .. [[d ]] .. value .. [[ -- verify_dns]] - - local ret = SYS.call(command) - if ret == 0 then return value -- everything OK - elseif ret == 2 then return nil, err_tab_adv(self) .. translate("nslookup can not resolve host") - elseif ret == 3 then return nil, err_tab_adv(self) .. translate("nc (netcat) can not connect") - elseif ret == 4 then return nil, err_tab_adv(self) .. translate("Forced IP Version don't matched") - else return nil, err_tab_adv(self) .. translate("unspecific error") - end - end - end - function dns.parse(self, section, novld) - DDNS.value_parse(self, section, novld) - end -end - --- IPv4 + IPv6 - force_dnstcp -- ############################################## -if DDNS.has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then - tcp = ns:taboption("advanced", Flag, "force_dnstcp", - translate("Force TCP on DNS") ) - tcp.orientation = "horizontal" - function tcp.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) - if not DDNS.has_bindhost and value ~= "0" then - self.description = bold_on .. font_red .. - translate("DNS requests via TCP not supported") .. font_off .. "
                          " .. - translate("please disable") .. " !" .. bold_off - else - self.description = translate("OPTIONAL: Force the use of TCP instead of default UDP on DNS requests.") - end - return value - end - function tcp.validate(self, value) - if (value == "1" and DDNS.has_bindhost ) or value == "0" then - return value - end - return nil, err_tab_adv(self) .. translate("DNS requests via TCP not supported") - end -end - --- IPv4 + IPv6 - proxy -- ##################################################### --- optional Proxy to use for http/https requests [user:password@]proxyhost[:port] -if DDNS.has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then - pxy = ns:taboption("advanced", Value, "proxy", - translate("PROXY-Server") ) - pxy.placeholder="user:password@myproxy.lan:8080" - function pxy.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) - if not DDNS.has_proxy and value ~= "" then - self.description = bold_on .. font_red .. - translate("PROXY-Server not supported") .. font_off .. "
                          " .. - translate("please remove entry") .. "!" .. bold_off - else - self.description = translate("OPTIONAL: Proxy-Server for detection and updates.") .. "
                          " .. - translate("Format") .. ": " .. bold_on .. "[user:password@]proxyhost:port" .. bold_off .. "
                          " .. - translate("IPv6 address must be given in square brackets") .. ": " .. - bold_on .. " [2001:db8::1]:8080" .. bold_off - end - return value - end - function pxy.validate(self, value) - -- if .datatype is set, then it is checked before calling this function - if not value or (#value == 0) then - return "" -- ignore on empty - elseif DDNS.has_proxy then - local ipv6 = usev6:formvalue(section) or "0" - local force = fipv:formvalue(section) or "0" - local command = CRTL.luci_helper .. [[ -]] - if (ipv6 == 1) then command = command .. [[6]] end - if (force == 1) then command = command .. [[f]] end - command = command .. [[p ]] .. value .. [[ -- verify_proxy]] - local ret = SYS.call(command) - if ret == 0 then return value - elseif ret == 2 then return nil, err_tab_adv(self) .. translate("nslookup can not resolve host") - elseif ret == 3 then return nil, err_tab_adv(self) .. translate("nc (netcat) can not connect") - elseif ret == 4 then return nil, err_tab_adv(self) .. translate("Forced IP Version don't matched") - elseif ret == 5 then return nil, err_tab_adv(self) .. translate("proxy port missing") - else return nil, err_tab_adv(self) .. translate("unspecific error") - end - else - return nil, err_tab_adv(self) .. translate("PROXY-Server not supported") - end - end - function pxy.parse(self, section, novld) - DDNS.value_parse(self, section, novld) - end -end - --- use_syslog -- ############################################################## -slog = ns:taboption("advanced", ListValue, "use_syslog", - translate("Log to syslog"), - translate("Writes log messages to syslog. Critical Errors will always be written to syslog.") ) -slog.default = "2" -slog:value("0", translate("No logging")) -slog:value("1", translate("Info")) -slog:value("2", translate("Notice")) -slog:value("3", translate("Warning")) -slog:value("4", translate("Error")) -function slog.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- use_logfile -- ############################################################# -logf = ns:taboption("advanced", Flag, "use_logfile", - translate("Log to file"), - translate("Writes detailed messages to log file. File will be truncated automatically.") .. "
                          " .. - translate("File") .. [[: "]] .. logdir .. [[/]] .. section .. [[.log"]] ) -logf.orientation = "horizontal" -logf.default = "1" -- if not defined write to log by default - --- TAB: Timer #################################################################################### --- check_interval -- ########################################################## -ci = ns:taboption("timer", Value, "check_interval", - translate("Check Interval") ) -ci.template = "ddns/detail_value" -ci.default = "10" -function ci.validate(self, value) - if not DTYP.uinteger(value) - or tonumber(value) < 1 then - return nil, err_tab_timer(self) .. translate("minimum value 5 minutes == 300 seconds") - end - - local secs = DDNS.calc_seconds(value, cu:formvalue(section)) - if secs >= 300 then - return value - else - return nil, err_tab_timer(self) .. translate("minimum value 5 minutes == 300 seconds") - end -end -function ci.write(self, section, value) - -- remove when default - local secs = DDNS.calc_seconds(value, cu:formvalue(section)) - if secs ~= 600 then --default 10 minutes - return self.map:set(section, self.option, value) - else - self.map:del(section, "check_unit") - return self.map:del(section, self.option) - end -end -function ci.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- check_unit -- ############################################################## -cu = ns:taboption("timer", ListValue, "check_unit", "not displayed, but needed otherwise error", - translate("Interval to check for changed IP" .. "
                          " .. - "Values below 5 minutes == 300 seconds are not supported") ) -cu.template = "ddns/detail_lvalue" -cu.default = "minutes" -cu:value("seconds", translate("seconds")) -cu:value("minutes", translate("minutes")) -cu:value("hours", translate("hours")) ---cu:value("days", translate("days")) -function cu.write(self, section, value) - -- remove when default - local secs = DDNS.calc_seconds(ci:formvalue(section), value) - if secs ~= 600 then --default 10 minutes - return self.map:set(section, self.option, value) - else - return true - end -end -function cu.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- force_interval (modified) -- ############################################### -fi = ns:taboption("timer", Value, "force_interval", - translate("Force Interval") ) -fi.template = "ddns/detail_value" -fi.default = "72" -- see dynamic_dns_updater.sh script ---fi.rmempty = false -- validate ourselves for translatable error messages -function fi.validate(self, value) - if not DTYP.uinteger(value) - or tonumber(value) < 0 then - return nil, err_tab_timer(self) .. translate("minimum value '0'") - end - - local force_s = DDNS.calc_seconds(value, fu:formvalue(section)) - if force_s == 0 then - return value - end - - local ci_value = ci:formvalue(section) - if not DTYP.uinteger(ci_value) then - return "" -- ignore because error in check_interval above - end - - local check_s = DDNS.calc_seconds(ci_value, cu:formvalue(section)) - if force_s >= check_s then - return value - end - - return nil, err_tab_timer(self) .. translate("must be greater or equal 'Check Interval'") -end -function fi.write(self, section, value) - -- simulate rmempty=true remove default - local secs = DDNS.calc_seconds(value, fu:formvalue(section)) - if secs ~= 259200 then --default 72 hours == 3 days - return self.map:set(section, self.option, value) - else - self.map:del(section, "force_unit") - return self.map:del(section, self.option) - end -end -function fi.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- force_unit -- ############################################################## -fu = ns:taboption("timer", ListValue, "force_unit", "not displayed, but needed otherwise error", - translate("Interval to force updates send to DDNS Provider" .. "
                          " .. - "Setting this parameter to 0 will force the script to only run once" .. "
                          " .. - "Values lower 'Check Interval' except '0' are not supported") ) -fu.template = "ddns/detail_lvalue" -fu.default = "hours" ---fu.rmempty = false -- want to control write process ---fu:value("seconds", translate("seconds")) -fu:value("minutes", translate("minutes")) -fu:value("hours", translate("hours")) -fu:value("days", translate("days")) -function fu.write(self, section, value) - -- simulate rmempty=true remove default - local secs = DDNS.calc_seconds(fi:formvalue(section), value) - if secs ~= 259200 and secs ~= 0 then --default 72 hours == 3 days - return self.map:set(section, self.option, value) - else - return true - end -end -function fu.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- retry_count -- ############################################################# -rc = ns:taboption("timer", Value, "retry_count") -rc.title = translate("Error Retry Counter") -rc.description = translate("On Error the script will stop execution after given number of retrys") - .. "
                          " - .. translate("The default setting of '0' will retry infinite.") -rc.default = "0" -function rc.validate(self, value) - if not DTYP.uinteger(value) then - return nil, err_tab_timer(self) .. translate("minimum value '0'") - else - return value - end -end -function rc.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- retry_interval -- ########################################################## -ri = ns:taboption("timer", Value, "retry_interval", - translate("Error Retry Interval") ) -ri.template = "ddns/detail_value" -ri.default = "60" -function ri.validate(self, value) - if not DTYP.uinteger(value) - or tonumber(value) < 1 then - return nil, err_tab_timer(self) .. translate("minimum value '1'") - else - return value - end -end -function ri.write(self, section, value) - -- simulate rmempty=true remove default - local secs = DDNS.calc_seconds(value, ru:formvalue(section)) - if secs ~= 60 then --default 60seconds - return self.map:set(section, self.option, value) - else - self.map:del(section, "retry_unit") - return self.map:del(section, self.option) - end -end -function ri.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- retry_unit -- ############################################################## -ru = ns:taboption("timer", ListValue, "retry_unit", "not displayed, but needed otherwise error", - translate("On Error the script will retry the failed action after given time") ) -ru.template = "ddns/detail_lvalue" -ru.default = "seconds" ---ru.rmempty = false -- want to control write process -ru:value("seconds", translate("seconds")) -ru:value("minutes", translate("minutes")) ---ru:value("hours", translate("hours")) ---ru:value("days", translate("days")) -function ru.write(self, section, value) - -- simulate rmempty=true remove default - local secs = DDNS.calc_seconds(ri:formvalue(section), value) - if secs ~= 60 then --default 60seconds - return self.map:set(section, self.option, value) - else - return true -- will be deleted by retry_interval - end -end -function ru.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- TAB: LogView ################################################################################## -lv = ns:taboption("logview", DummyValue, "_logview") -lv.template = "ddns/detail_logview" -lv.inputtitle = translate("Read / Reread log file") -lv.rows = 50 -function lv.cfgvalue(self, section) - local lfile=logdir .. "/" .. section .. ".log" - if NXFS.access(lfile) then - return lfile .. "\n" .. translate("Please press [Read] button") - end - return lfile .. "\n" .. translate("File not found or empty") -end - -return m diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/global.lua b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/global.lua deleted file mode 100644 index 9dc0857..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/global.lua +++ /dev/null @@ -1,121 +0,0 @@ --- Copyright 2014 Christian Schoenebeck --- Licensed to the public under the Apache License 2.0. - -local NX = require "nixio" -local NXFS = require "nixio.fs" -local DISP = require "luci.dispatcher" -local SYS = require "luci.sys" -local CTRL = require "luci.controller.ddns" -- this application's controller -local DDNS = require "luci.tools.ddns" -- ddns multiused functions - --- cbi-map definition -- ####################################################### -local m = Map("ddns") -m.title = CTRL.app_title_back() -m.description = CTRL.app_description() -m.redirect = DISP.build_url("admin", "services", "ddns") - -function m.commit_handler(self) - if self.changed then -- changes ? - local command = CTRL.luci_helper .. " -- reload" - os.execute(command) -- reload configuration - end -end - --- cbi-section definition -- ################################################### -local ns = m:section( NamedSection, "global", "ddns", - translate("Global Settings"), - translate("Configure here the details for all Dynamic DNS services including this LuCI application.") - .. [[
                          ]] - .. translate("It is NOT recommended for casual users to change settings on this page.") - .. [[
                          ]] - .. [[]] - .. translate("For detailed information about parameter settings look here.") - .. [[]] - ) - --- section might not exist -function ns.cfgvalue(self, section) - if not self.map:get(section) then - self.map:set(section, nil, self.sectiontype) - end - return self.map:get(section) -end - --- upd_privateip -- ########################################################### -local ali = ns:option(Flag, "upd_privateip") -ali.title = translate("Allow non-public IP's") -ali.description = translate("Non-public and by default blocked IP's") .. ":" - .. [[
                          IPv4: ]] - .. "0/8, 10/8, 100.64/10, 127/8, 169.254/16, 172.16/12, 192.168/16" - .. [[
                          IPv6: ]] - .. "::/32, f000::/4" -ali.default = "0" - --- ddns_dateformat -- ######################################################### -local df = ns:option(Value, "ddns_dateformat") -df.title = translate("Date format") -df.description = [[]] - .. translate("For supported codes look here") - .. [[]] -df.template = "ddns/global_value" -df.default = "%F %R" -df.date_string = "" -function df.cfgvalue(self, section) - local value = AbstractValue.cfgvalue(self, section) or self.default - local epoch = os.time() - self.date_string = DDNS.epoch2date(epoch, value) - return value -end -function df.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- ddns_rundir -- ############################################################# -local rd = ns:option(Value, "ddns_rundir") -rd.title = translate("Status directory") -rd.description = translate("Directory contains PID and other status information for each running section") -rd.default = "/var/run/ddns" --- no need to validate. if empty default is used everything else created by dns-scripts -function rd.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- ddns_logdir -- ############################################################# -local ld = ns:option(Value, "ddns_logdir") -ld.title = translate("Log directory") -ld.description = translate("Directory contains Log files for each running section") -ld.default = "/var/log/ddns" --- no need to validate. if empty default is used everything else created by dns-scripts -function ld.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- ddns_loglines -- ########################################################### -local ll = ns:option(Value, "ddns_loglines") -ll.title = translate("Log length") -ll.description = translate("Number of last lines stored in log files") -ll.default = "250" -function ll.validate(self, value) - local n = tonumber(value) - if not n or math.floor(n) ~= n or n < 1 then - return nil, self.title .. ": " .. translate("minimum value '1'") - end - return value -end -function ll.parse(self, section, novld) - DDNS.value_parse(self, section, novld) -end - --- use_curl -- ################################################################ -if (SYS.call([[ grep -i "\+ssl" /usr/bin/wget >/dev/null 2>&1 ]]) == 0) -and NXFS.access("/usr/bin/curl") then - local pc = ns:option(Flag, "use_curl") - pc.title = translate("Use cURL") - pc.description = translate("If both cURL and GNU Wget are installed, Wget is used by default.") - .. [[
                          ]] - .. translate("To use cURL activate this option.") - pc.orientation = "horizontal" - pc.default = "0" -end - -return m diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/hints.lua b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/hints.lua deleted file mode 100644 index df39a3a..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/hints.lua +++ /dev/null @@ -1,166 +0,0 @@ --- Copyright 2014-2016 Christian Schoenebeck --- Licensed to the public under the Apache License 2.0. - -local DISP = require "luci.dispatcher" -local SYS = require "luci.sys" -local CTRL = require "luci.controller.ddns" -- this application's controller -local DDNS = require "luci.tools.ddns" -- ddns multiused functions - --- html constants -font_red = [[]] -font_off = [[]] -bold_on = [[]] -bold_off = [[]] - --- cbi-map definition -- ####################################################### -m = Map("ddns") -m.title = CTRL.app_title_back() -m.description = CTRL.app_description() -m.redirect = DISP.build_url("admin", "services", "ddns") - --- SimpleSection definition -- ################################################# --- show Hints to optimize installation and script usage -s = m:section( SimpleSection, - translate("Hints"), - translate("Below a list of configuration tips for your system to run Dynamic DNS updates without limitations") ) - --- ddns-scripts needs to be updated for full functionality -if not CTRL.service_ok() then - local so = s:option(DummyValue, "_update_needed") - so.titleref = DISP.build_url("admin", "system", "packages") - so.rawhtml = true - so.title = font_red .. bold_on .. - translate("Software update required") .. bold_off .. font_off - so.value = translate("The currently installed 'ddns-scripts' package did not support all available settings.") .. - "
                          " .. - translate("Please update to the current version!") -end - --- DDNS Service disabled -if not SYS.init.enabled("ddns") then - local se = s:option(DummyValue, "_not_enabled") - se.titleref = DISP.build_url("admin", "system", "startup") - se.rawhtml = true - se.title = bold_on .. - translate("DDNS Autostart disabled") .. bold_off - se.value = translate("Currently DDNS updates are not started at boot or on interface events." .. "
                          " .. - "This is the default if you run DDNS scripts by yourself (i.e. via cron with force_interval set to '0')" ) -end - --- No IPv6 support -if not DDNS.has_ipv6 then - local v6 = s:option(DummyValue, "_no_ipv6") - v6.titleref = 'http://www.openwrt.org" target="_blank' - v6.rawhtml = true - v6.title = bold_on .. - translate("IPv6 not supported") .. bold_off - v6.value = translate("IPv6 is currently not (fully) supported by this system" .. "
                          " .. - "Please follow the instructions on OpenWrt's homepage to enable IPv6 support" .. "
                          " .. - "or update your system to the latest OpenWrt Release") -end - --- No HTTPS support -if not DDNS.has_ssl then - local sl = s:option(DummyValue, "_no_https") - sl.titleref = DISP.build_url("admin", "system", "packages") - sl.rawhtml = true - sl.title = bold_on .. - translate("HTTPS not supported") .. bold_off - sl.value = translate("Neither GNU Wget with SSL nor cURL installed to support secure updates via HTTPS protocol.") .. - "
                          - " .. - translate("You should install 'wget' or 'curl' or 'uclient-fetch' with 'libustream-*ssl' package.") .. - "
                          - " .. - translate("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.") -end - --- No bind_network -if not DDNS.has_bindnet then - local bn = s:option(DummyValue, "_no_bind_network") - bn.titleref = DISP.build_url("admin", "system", "packages") - bn.rawhtml = true - bn.title = bold_on .. - translate("Binding to a specific network not supported") .. bold_off - bn.value = translate("Neither GNU Wget with SSL nor cURL installed to select a network to use for communication.") .. - "
                          - " .. - translate("You should install 'wget' or 'curl' package.") .. - "
                          - " .. - translate("GNU Wget will use the IP of given network, cURL will use the physical interface.") .. - "
                          - " .. - translate("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.") -end - --- currently only cURL possibly without proxy support -if not DDNS.has_proxy then - local px = s:option(DummyValue, "_no_proxy") - px.titleref = DISP.build_url("admin", "system", "packages") - px.rawhtml = true - px.title = bold_on .. - translate("cURL without Proxy Support") .. bold_off - px.value = translate("cURL is installed, but libcurl was compiled without proxy support.") .. - "
                          - " .. - translate("You should install 'wget' or 'uclient-fetch' package or replace libcurl.") .. - "
                          - " .. - translate("In some versions cURL/libcurl in OpenWrt is compiled without proxy support.") -end - --- "Force IP Version not supported" -if not DDNS.has_forceip then - local fi = s:option(DummyValue, "_no_force_ip") - fi.titleref = DISP.build_url("admin", "system", "packages") - fi.rawhtml = true - fi.title = bold_on .. - translate("Force IP Version not supported") .. bold_off - local value = translate("BusyBox's nslookup and Wget do not support to specify " .. - "the IP version to use for communication with DDNS Provider!") - if not (DDNS.has_wgetssl or DDNS.has_curl or DDNS.has_fetch) then - value = value .. "
                          - " .. - translate("You should install 'wget' or 'curl' or 'uclient-fetch' package.") - end - if not DDNS.has_bindhost then - value = value .. "
                          - " .. - translate("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.") - end - fi.value = value -end - --- "DNS requests via TCP not supported" -if not DDNS.has_bindhost then - local dt = s:option(DummyValue, "_no_dnstcp") - dt.titleref = DISP.build_url("admin", "system", "packages") - dt.rawhtml = true - dt.title = bold_on .. - translate("DNS requests via TCP not supported") .. bold_off - dt.value = translate("BusyBox's nslookup and hostip do not support to specify to use TCP " .. - "instead of default UDP when requesting DNS server!") .. - "
                          - " .. - translate("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.") -end - --- nslookup compiled with musl produce problems when using -if not DDNS.has_dnsserver then - local ds = s:option(DummyValue, "_no_dnsserver") - ds.titleref = DISP.build_url("admin", "system", "packages") - ds.rawhtml = true - ds.title = bold_on .. - translate("Using specific DNS Server not supported") .. bold_off - ds.value = translate("BusyBox's nslookup in the current compiled version " .. - "does not handle given DNS Servers correctly!") .. - "
                          - " .. - translate("You should install 'bind-host' or 'knot-host' or 'drill' or 'hostip' package, " .. - "if you need to specify a DNS server to detect your registered IP.") -end - --- certificates installed -if DDNS.has_ssl and not DDNS.has_cacerts then - local ca = s:option(DummyValue, "_no_certs") - ca.titleref = DISP.build_url("admin", "system", "packages") - ca.rawhtml = true - ca.title = bold_on .. - translate("No certificates found") .. bold_off - ca.value = translate("If using secure communication you should verify server certificates!") .. - "
                          - " .. - translate("Install 'ca-certificates' package or needed certificates " .. - "by hand into /etc/ssl/certs default directory") -end - -return m diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/overview.lua b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/overview.lua deleted file mode 100644 index 337c6e7..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/model/cbi/ddns/overview.lua +++ /dev/null @@ -1,219 +0,0 @@ --- Copyright 2014-2016 Christian Schoenebeck --- Licensed to the public under the Apache License 2.0. - -local NXFS = require "nixio.fs" -local DISP = require "luci.dispatcher" -local HTTP = require "luci.http" -local SYS = require "luci.sys" -local CTRL = require "luci.controller.ddns" -- this application's controller -local DDNS = require "luci.tools.ddns" -- ddns multiused functions - -local show_hints = not (DDNS.has_ipv6 -- IPv6 support - and DDNS.has_ssl -- HTTPS support - and DDNS.has_proxy -- Proxy support - and DDNS.has_bindhost -- DNS TCP support - and DDNS.has_forceip -- Force IP version - and DDNS.has_dnsserver -- DNS server support - and DDNS.has_bindnet -- Bind to network/interface - and DDNS.has_cacerts -- certificates installed at /etc/ssl/certs - ) -local not_enabled = not SYS.init.enabled("ddns") -local need_update = not CTRL.service_ok() - --- html constants -font_red = [[]] -font_off = [[]] -bold_on = [[]] -bold_off = [[]] - --- cbi-map definition -- ####################################################### -m = Map("ddns") -m.title = CTRL.app_title_main() -m.description = CTRL.app_description() - -m.on_after_commit = function(self) - if self.changed then -- changes ? - local command = CTRL.luci_helper - if SYS.init.enabled("ddns") then -- ddns service enabled, restart all - command = command .. " -- restart" - os.execute(command) - else -- ddns service disabled, send SIGHUP to running - command = command .. " -- reload" - os.execute(command) - end - end -end - --- SimpleSection definition -- ################################################## --- with all the JavaScripts we need for "a good Show" -a = m:section( SimpleSection ) -a.template = "ddns/overview_status" - --- SimpleSection definition -- ################################################# --- show Hints to optimize installation and script usage -if not_enabled then - - s = m:section( SimpleSection, translate("Hints") ) - - -- DDNS Service disabled - if not_enabled then - local dv = s:option(DummyValue, "_not_enabled") - dv.titleref = DISP.build_url("admin", "system", "startup") - dv.rawhtml = true - dv.title = bold_on .. - translate("DDNS Autostart disabled") .. bold_off - dv.value = translate("Currently DDNS updates are not started at boot or on interface events." .. "
                          " .. - "You can start/stop each configuration here. It will run until next reboot.") - end - -end - -local_web="

                           

                           

                          " - --- TableSection definition -- ################################################## -ts = m:section( TypedSection, "service", - translate("Overview"), - translate("Below is a list of DDNS configurations and their current state.") - .. "
                          " - .. "
                          " .. local_web ) -ts.sectionhead = translate("Configuration") -ts.template = "cbi/tblsection" -ts.addremove = true -ts.extedit = DISP.build_url("admin", "services", "ddns", "detail", "%s") -function ts.create(self, name) - AbstractSection.create(self, name) - HTTP.redirect( self.extedit:format(name) ) -end - --- Lookup_Host and registered IP -- ################################################# -dom = ts:option(DummyValue, "_lookupIP", - translate("Lookup Hostname") .. "
                          " .. translate("Registered IP") ) -dom.template = "ddns/overview_doubleline" -function dom.set_one(self, section) - local lookup = self.map:get(section, "lookup_host") or "" - if lookup ~= "" then - return lookup - else - return [[]] .. translate("config error") .. [[]] - end -end -function dom.set_two(self, section) - local lookup_host = self.map:get(section, "lookup_host") or "" - if lookup_host == "" then return "" end - local dnsserver = self.map:get(section, "dnsserver") or "" - local use_ipv6 = tonumber(self.map:get(section, "use_ipv6") or 0) - local force_ipversion = tonumber(self.map:get(section, "force_ipversion") or 0) - local force_dnstcp = tonumber(self.map:get(section, "force_dnstcp") or 0) - local is_glue = tonumber(self.map:get(section, "is_glue") or 0) - local command = CTRL.luci_helper .. [[ -]] - if (use_ipv6 == 1) then command = command .. [[6]] end - if (force_ipversion == 1) then command = command .. [[f]] end - if (force_dnstcp == 1) then command = command .. [[t]] end - if (is_glue == 1) then command = command .. [[g]] end - command = command .. [[l ]] .. lookup_host - if (#dnsserver > 0) then command = command .. [[ -d ]] .. dnsserver end - command = command .. [[ -- get_registered_ip]] - local ip = SYS.exec(command) - if ip == "" then ip = translate("no data") end - return ip -end - --- enabled -ena = ts:option( Flag, "enabled", - translate("Enabled")) -ena.template = "ddns/overview_enabled" -ena.rmempty = false - --- show PID and next update -upd = ts:option( DummyValue, "_update", - translate("Last Update") .. "
                          " .. translate("Next Update")) -upd.template = "ddns/overview_doubleline" -function upd.set_one(self, section) -- fill Last Update - -- get/validate last update - local uptime = SYS.uptime() - local lasttime = DDNS.get_lastupd(section) - if lasttime > uptime then -- /var might not be linked to /tmp and cleared on reboot - lasttime = 0 - end - - -- no last update happen - if lasttime == 0 then - return translate("never") - - -- we read last update - else - -- calc last update - -- os.epoch - sys.uptime + lastupdate(uptime) - local epoch = os.time() - uptime + lasttime - -- use linux date to convert epoch - return DDNS.epoch2date(epoch) - end -end -function upd.set_two(self, section) -- fill Next Update - -- get enabled state - local enabled = tonumber(self.map:get(section, "enabled") or 0) - local datenext = translate("unknown error") -- formatted date of next update - - -- get force seconds - local force_interval = tonumber(self.map:get(section, "force_interval") or 72) - local force_unit = self.map:get(section, "force_unit") or "hours" - local force_seconds = DDNS.calc_seconds(force_interval, force_unit) - - -- get last update and get/validate PID - local uptime = SYS.uptime() - local lasttime = DDNS.get_lastupd(section) - if lasttime > uptime then -- /var might not be linked to /tmp and cleared on reboot - lasttime = 0 - end - local pid = DDNS.get_pid(section) - - -- calc next update - if lasttime > 0 then - local epoch = os.time() - uptime + lasttime + force_seconds - -- use linux date to convert epoch - datelast = DDNS.epoch2date(epoch) - end - - -- process running but update needs to happen - if pid > 0 and ( lasttime + force_seconds - uptime ) < 0 then - datenext = translate("Verify") - - -- run once - elseif force_seconds == 0 then - datenext = translate("Run once") - - -- no process running and NOT enabled - elseif pid == 0 and enabled == 0 then - datenext = translate("Disabled") - - -- no process running and NOT - elseif pid == 0 and enabled ~= 0 then - datenext = translate("Stopped") - end - - return datenext -end - --- start/stop button -btn = ts:option( Button, "_startstop", - translate("Process ID") .. "
                          " .. translate("Start / Stop") ) -btn.template = "ddns/overview_startstop" -function btn.cfgvalue(self, section) - local pid = DDNS.get_pid(section) - if pid > 0 then - btn.inputtitle = "PID: " .. pid - btn.inputstyle = "reset" - btn.disabled = false - elseif (self.map:get(section, "enabled") or "0") ~= "0" then - btn.inputtitle = translate("Start") - btn.inputstyle = "apply" - btn.disabled = false - else - btn.inputtitle = "----------" - btn.inputstyle = "button" - btn.disabled = true - end - return true -end - -return m diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/tools/ddns.lua b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/tools/ddns.lua deleted file mode 100644 index 209d9c3..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/tools/ddns.lua +++ /dev/null @@ -1,315 +0,0 @@ --- Copyright 2014-2016 Christian Schoenebeck --- Licensed to the public under the Apache License 2.0. - -module("luci.tools.ddns", package.seeall) - -local NX = require "nixio" -local NXFS = require "nixio.fs" -local OPKG = require "luci.model.ipkg" -local UCI = require "luci.model.uci" -local SYS = require "luci.sys" -local UTIL = require "luci.util" - -local function _check_certs() - local _, v = NXFS.glob("/etc/ssl/certs/*.crt") - if ( v == 0 ) then _, v = NXFS.glob("/etc/ssl/certs/*.pem") end - return (v > 0) -end - -has_wgetssl = (SYS.call( [[which wget-ssl >/dev/null 2>&1]] ) == 0) -- and true or nil -has_curl = (SYS.call( [[which curl >/dev/null 2>&1]] ) == 0) -has_curlssl = (SYS.call( [[$(which curl) -V 2>&1 | grep "Protocols:" | grep -qF "https"]] ) ~= 0) -has_curlpxy = (SYS.call( [[grep -i "all_proxy" /usr/lib/libcurl.so* >/dev/null 2>&1]] ) == 0) -has_fetch = (SYS.call( [[which uclient-fetch >/dev/null 2>&1]] ) == 0) -has_fetchssl = NXFS.access("/lib/libustream-ssl.so") -has_bbwget = (SYS.call( [[$(which wget) -V 2>&1 | grep -iqF "busybox"]] ) == 0) -has_bindhost = (SYS.call( [[which host >/dev/null 2>&1]] ) == 0) - or (SYS.call( [[which khost >/dev/null 2>&1]] ) == 0) - or (SYS.call( [[which drill >/dev/null 2>&1]] ) == 0) -has_hostip = (SYS.call( [[which hostip >/dev/null 2>&1]] ) == 0) -has_nslookup = (SYS.call( [[$(which nslookup) localhost 2>&1 | grep -qF "(null)"]] ) ~= 0) -has_ipv6 = (NXFS.access("/proc/net/ipv6_route") and NXFS.access("/usr/sbin/ip6tables")) -has_ssl = (has_wgetssl or has_curlssl or (has_fetch and has_fetchssl)) -has_proxy = (has_wgetssl or has_curlpxy or has_fetch or has_bbwget) -has_forceip = (has_wgetssl or has_curl or has_fetch) -- only really needed for transfer -has_dnsserver = (has_bindhost or has_hostip or has_nslookup) -has_bindnet = (has_wgetssl or has_curl) -has_cacerts = _check_certs() - --- function to calculate seconds from given interval and unit -function calc_seconds(interval, unit) - if not tonumber(interval) then - return nil - elseif unit == "days" then - return (tonumber(interval) * 86400) -- 60 sec * 60 min * 24 h - elseif unit == "hours" then - return (tonumber(interval) * 3600) -- 60 sec * 60 min - elseif unit == "minutes" then - return (tonumber(interval) * 60) -- 60 sec - elseif unit == "seconds" then - return tonumber(interval) - else - return nil - end -end - --- convert epoch date to given format -function epoch2date(epoch, format) - if not format or #format < 2 then - local uci = UCI.cursor() - format = uci:get("ddns", "global", "ddns_dateformat") or "%F %R" - uci:unload("ddns") - end - format = format:gsub("%%n", "
                          ") -- replace newline - format = format:gsub("%%t", " ") -- replace tab - return os.date(format, epoch) -end - --- read lastupdate from [section].update file -function get_lastupd(section) - local uci = UCI.cursor() - local rdir = uci:get("ddns", "global", "ddns_rundir") or "/var/run/ddns" - local etime = tonumber(NXFS.readfile("%s/%s.update" % { rdir, section } ) or 0 ) - uci:unload("ddns") - return etime -end - --- read PID from run file and verify if still running -function get_pid(section) - local uci = UCI.cursor() - local rdir = uci:get("ddns", "global", "ddns_rundir") or "/var/run/ddns" - local pid = tonumber(NXFS.readfile("%s/%s.pid" % { rdir, section } ) or 0 ) - if pid > 0 and not NX.kill(pid, 0) then - pid = 0 - end - uci:unload("ddns") - return pid -end - --- replacement of build-in read of UCI option --- modified AbstractValue.cfgvalue(self, section) from cbi.lua --- needed to read from other option then current value definition -function read_value(self, section, option) - local value - if self.tag_error[section] then - value = self:formvalue(section) - else - value = self.map:get(section, option) - end - - if not value then - return nil - elseif not self.cast or self.cast == type(value) then - return value - elseif self.cast == "string" then - if type(value) == "table" then - return value[1] - end - elseif self.cast == "table" then - return { value } - end -end - --- replacement of build-in parse of "Value" --- modified AbstractValue.parse(self, section, novld) from cbi.lua --- validate is called if rmempty/optional true or false --- before write check if forcewrite, value eq default, and more -function value_parse(self, section, novld) - local fvalue = self:formvalue(section) - local fexist = ( fvalue and (#fvalue > 0) ) -- not "nil" and "not empty" - local cvalue = self:cfgvalue(section) - local rm_opt = ( self.rmempty or self.optional ) - local eq_cfg -- flag: equal cfgvalue - - -- If favlue and cvalue are both tables and have the same content - -- make them identical - if type(fvalue) == "table" and type(cvalue) == "table" then - eq_cfg = (#fvalue == #cvalue) - if eq_cfg then - for i=1, #fvalue do - if cvalue[i] ~= fvalue[i] then - eq_cfg = false - end - end - end - if eq_cfg then - fvalue = cvalue - end - end - - -- removed parameter "section" from function call because used/accepted nowhere - -- also removed call to function "transfer" - local vvalue, errtxt = self:validate(fvalue) - - -- error handling; validate return "nil" - if not vvalue then - if novld then -- and "novld" set - return -- then exit without raising an error - end - - if fexist then -- and there is a formvalue - self:add_error(section, "invalid", errtxt or self.title .. ": invalid") - return -- so data are invalid - elseif not rm_opt then -- and empty formvalue but NOT (rmempty or optional) set - self:add_error(section, "missing", errtxt or self.title .. ": missing") - return -- so data is missing - elseif errtxt then - self:add_error(section, "invalid", errtxt) - return - end --- error ("\n option: " .. self.option .. --- "\n fvalue: " .. tostring(fvalue) .. --- "\n fexist: " .. tostring(fexist) .. --- "\n cvalue: " .. tostring(cvalue) .. --- "\n vvalue: " .. tostring(vvalue) .. --- "\n vexist: " .. tostring(vexist) .. --- "\n rm_opt: " .. tostring(rm_opt) .. --- "\n eq_cfg: " .. tostring(eq_cfg) .. --- "\n eq_def: " .. tostring(eq_def) .. --- "\n novld : " .. tostring(novld) .. --- "\n errtxt: " .. tostring(errtxt) ) - end - - -- lets continue with value returned from validate - eq_cfg = ( vvalue == cvalue ) -- update equal_config flag - local vexist = ( vvalue and (#vvalue > 0) ) and true or false -- not "nil" and "not empty" - local eq_def = ( vvalue == self.default ) -- equal_default flag - - -- (rmempty or optional) and (no data or equal_default) - if rm_opt and (not vexist or eq_def) then - if self:remove(section) then -- remove data from UCI - self.section.changed = true -- and push events - end - return - end - - -- not forcewrite and no changes, so nothing to write - if not self.forcewrite and eq_cfg then - return - end - - -- we should have a valid value here - assert (vvalue, "\n option: " .. self.option .. - "\n fvalue: " .. tostring(fvalue) .. - "\n fexist: " .. tostring(fexist) .. - "\n cvalue: " .. tostring(cvalue) .. - "\n vvalue: " .. tostring(vvalue) .. - "\n vexist: " .. tostring(vexist) .. - "\n rm_opt: " .. tostring(rm_opt) .. - "\n eq_cfg: " .. tostring(eq_cfg) .. - "\n eq_def: " .. tostring(eq_def) .. - "\n errtxt: " .. tostring(errtxt) ) - - -- write data to UCI; raise event only on changes - if self:write(section, vvalue) and not eq_cfg then - self.section.changed = true - end -end - ------------------------------------------------------------------------------ --- copied from https://svn.nmap.org/nmap/nselib/url.lua --- @author Diego Nehab --- @author Eddie Bell ---[[ - URI parsing, composition and relative URL resolution - LuaSocket toolkit. - Author: Diego Nehab - RCS ID: $Id: url.lua,v 1.37 2005/11/22 08:33:29 diego Exp $ - parse_query and build_query added For nmap (Eddie Bell ) -]]-- ---- --- Parses a URL and returns a table with all its parts according to RFC 2396. --- --- The following grammar describes the names given to the URL parts. --- --- ::= :///;?# --- ::= @: --- ::= [:] --- :: = {/} --- --- --- The leading / in / is considered part of --- . --- @param url URL of request. --- @param default Table with default values for each field. --- @return A table with the following fields, where RFC naming conventions have --- been preserved: --- scheme, authority, userinfo, --- user, password, host, --- port, path, params, --- query, and fragment. ------------------------------------------------------------------------------ -function parse_url(url) --, default) - -- initialize default parameters - local parsed = {} --- for i,v in base.pairs(default or parsed) do --- parsed[i] = v --- end - - -- remove whitespace --- url = string.gsub(url, "%s", "") - -- get fragment - url = string.gsub(url, "#(.*)$", - function(f) - parsed.fragment = f - return "" - end) - -- get scheme. Lower-case according to RFC 3986 section 3.1. - url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", - function(s) - parsed.scheme = string.lower(s); - return "" - end) - -- get authority - url = string.gsub(url, "^//([^/]*)", - function(n) - parsed.authority = n - return "" - end) - -- get query stringing - url = string.gsub(url, "%?(.*)", - function(q) - parsed.query = q - return "" - end) - -- get params - url = string.gsub(url, "%;(.*)", - function(p) - parsed.params = p - return "" - end) - -- path is whatever was left - parsed.path = url - - local authority = parsed.authority - if not authority then - return parsed - end - authority = string.gsub(authority,"^([^@]*)@", - function(u) - parsed.userinfo = u; - return "" - end) - authority = string.gsub(authority, ":([0-9]*)$", - function(p) - if p ~= "" then - parsed.port = p - end; - return "" - end) - if authority ~= "" then - parsed.host = authority - end - - local userinfo = parsed.userinfo - if not userinfo then - return parsed - end - userinfo = string.gsub(userinfo, ":([^:]*)$", - function(p) - parsed.password = p; - return "" - end) - parsed.user = userinfo - return parsed -end diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/admin_status/index/ddns.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/admin_status/index/ddns.htm deleted file mode 100644 index 9791065..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/admin_status/index/ddns.htm +++ /dev/null @@ -1 +0,0 @@ -<%+ddns/system_status%> diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_logview.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_logview.htm deleted file mode 100644 index fd1d5be..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_logview.htm +++ /dev/null @@ -1,56 +0,0 @@ - - - - -<%+cbi/valueheader%> - -
                          - -<% --- one button on top, one at the buttom -%> - /> - -

                          - -<% --- set a readable style taken from openwrt theme for textarea#syslog --- in openwrt theme there are problems with a width of 100 so we check for theme and set to lower value -%> - -

                          - -<% --- one button on top, one at the buttom -%> - /> - -<%+cbi/valuefooter%> - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_lvalue.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_lvalue.htm deleted file mode 100644 index b69d780..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_lvalue.htm +++ /dev/null @@ -1,23 +0,0 @@ - - - -  -<% if self.widget == "select" then %> - -<% elseif self.widget == "radio" then - local c = 0 - for i, key in pairs(self.keylist) do - c = c + 1 -%> - /> - > - ><%=self.vallist[i]%> -<% if c == self.size then c = 0 %><% if self.orientation == "horizontal" then %> <% else %>
                          <% end %> -<% end end %> -<% end %> -<%+cbi/valuefooter%> - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_value.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_value.htm deleted file mode 100644 index cbe76ab..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/detail_value.htm +++ /dev/null @@ -1,9 +0,0 @@ - - -<%+cbi/valueheader%> - /> - - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/global_value.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/global_value.htm deleted file mode 100644 index 23ec059..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/global_value.htm +++ /dev/null @@ -1,34 +0,0 @@ - - -<%+cbi/valueheader%> - - - -/> -
                          -
                          - <%:help%><%=self.description%> -
                          - <%:Current setting%>: <%=self.date_string%> -
                          -
                          - - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_doubleline.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_doubleline.htm deleted file mode 100644 index 1d1b4be..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_doubleline.htm +++ /dev/null @@ -1,10 +0,0 @@ - - -<%+cbi/valueheader%> - -<%=self:set_one(section)%> -
                          -<%=self:set_two(section)%> - -<%+cbi/valuefooter%> - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_enabled.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_enabled.htm deleted file mode 100644 index 2efc125..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_enabled.htm +++ /dev/null @@ -1,16 +0,0 @@ - - -<%+cbi/valueheader%> - - /> - - /> -> - -<%+cbi/valuefooter%> - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_startstop.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_startstop.htm deleted file mode 100644 index 327028c..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_startstop.htm +++ /dev/null @@ -1,17 +0,0 @@ - - -<%+cbi/valueheader%> - -<% if self:cfgvalue(section) ~= false then --- We need to garantie that function cfgvalue run first to set missing parameters -%> - - - " style="font-size: 100%;" type="button" onclick="onclick_startstop(this.id)" - <%= - attr("name", section) .. attr("id", cbid) .. attr("value", self.inputtitle) .. ifattr(self.disabled, "disabled") - %> /> -<% end %> - -<%+cbi/valuefooter%> - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_status.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_status.htm deleted file mode 100644 index b409ed0..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/overview_status.htm +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - diff --git a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/system_status.htm b/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/system_status.htm deleted file mode 100644 index 5bdcb03..0000000 --- a/rooter/0optionalapps/luci-app-rooterddns/files/usr/lib/lua/luci/view/ddns/system_status.htm +++ /dev/null @@ -1,144 +0,0 @@ - - - - -
                          - <%:Dynamic DNS%> - - - - - - - - - - - - -
                          <%:Configuration%><%:Next Update%><%:Lookup Hostname%><%:Registered IP%><%:Network%>

                          <%:Collecting data...%>
                          -
                          - diff --git a/rooter/0optionalapps/luci-app-rootervpn/Makefile b/rooter/0optionalapps/luci-app-rootervpn/Makefile deleted file mode 100644 index 46f6d81..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-rootervpn -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/luci-app-rootervpn - SECTION:=luci - CATEGORY:=LuCI - DEPENDS:=+openvpn-easy-rsa +openvpn-openssl +eoip - SUBMENU:=3. Applications - TITLE:=support for modified OpenVPN - PKGARCH:=all -endef - -define Package/luci-app-rootervpn/description - Helper scripts to enable OpenVPN support -endef - - -define Build/Compile -endef - -define Package/luci-app-rootervpn/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,luci-app-rootervpn)) diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes b/rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes deleted file mode 100644 index 68b6274..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/config/openvpn_recipes +++ /dev/null @@ -1,293 +0,0 @@ -# -# Routed point-to-point server -# -config openvpn_recipe b_server_tun_ptp - option _description "Basic point-to-point TUN VPN Server" - option _role "server" - option dev "tun-server" - option ifconfig "10.0.0.1 10.0.0.2" - option secret "shared-secret.key" - option keepalive "10 60" - option comp_lzo "yes" - option verb "3" - option mssfix "1420" - option topology "p2p" - -# -# Routed point-to-point client -# -config openvpn_recipe b_client_tun_ptp - option _description "Basic point-to-point TUN VPN Client" - option _role "client" - option client "1" - option dev "tun0" - list remote "vpnserver.example.org" - option ifconfig "10.0.0.2 10.0.0.1" - option secret "shared-secret.key" - option nobind "1" - option comp_lzo "yes" - option verb "3" - -# -# Routed multi-client server -# -config openvpn_recipe a_server_tun - option _description "Basic TUN VPN Server" - option _role "server" - option dev "tun-server" - option topology "subnet" - option port "1194" - option proto "udp" - option server "10.0.100.0 255.255.255.0" - option ca "/etc/openvpn/placeholder/placeholder.file" - option cert "/etc/openvpn/placeholder/placeholder.file" - option key "/etc/openvpn/placeholder/placeholder.file" - option dh "/etc/openvpn/placeholder/placeholder.file" - option keepalive "10 60" - option comp_lzo "yes" - option verb "3" - option mssfix "1420" - -# -# Routed client -# -config openvpn_recipe a_client_tun - option _description "Basic TUN VPN Client" - option _role "client" - option client "1" - option dev "tun0" - option proto "udp" - list remote "vpnserver.example.org" - option remote_cert_tls "server" - option comp_lzo "yes" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option verb "3" - option reneg_sec "0" - option float "1" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option ca "/etc/openvpn/placeholder/placeholder.file" - option cert "/etc/openvpn/placeholder/placeholder.file" - option key "/etc/openvpn/placeholder/placeholder.file" - -# -# Multi-client ethernet bridge server -# -config openvpn_recipe c_server_tap_bridge - option _description "Basic Server-Bridge TAP VPN Server" - option _role "server" - option dev "tap-server" - option port "1194" - option server_bridge "192.168.100.1 255.255.255.0 192.168.100.128 192.168.100.254" - option ca "/etc/openvpn/placeholder/placeholder.file" - option cert "/etc/openvpn/placeholder/placeholder.file" - option key "/etc/openvpn/placeholder/placeholder.file" - option dh "/etc/openvpn/placeholder/placeholder.file" - option keepalive "10 60" - option comp_lzo "yes" - option verb "3" - option mssfix "1420" - -# -# Ethernet bridge client -# -config openvpn_recipe c_client_tap_bridge - option _description "Basic Server-Bridge TAP VPN Client" - option _role "client" - option client "1" - option dev "tap0" - list remote "vpnserver.example.org" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option ca "/etc/openvpn/placeholder/placeholder.file" - option cert "/etc/openvpn/placeholder/placeholder.file" - option key "/etc/openvpn/placeholder/placeholder.file" - option remote_cert_tls "server" - option comp_lzo "yes" - option nobind "1" - option persist_key "1" - option verb "3" - option reneg_sec "0" - option float "1" - -# -# OVPN Client -# -config openvpn_recipe d_ovpn_client - option _description "Client using OVPN File" - option _role "client" - option config "/etc/openvpn/placeholder/placeholder.file" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - -# -# NordVpn -# -config openvpn_recipe e_nordvpn_client_tun - option _description "Predefined Client for NordVPN" - option _role "client" - option config "/etc/openvpn/placeholder/placeholder.file" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - -# -# Private Internet Access Client -# -config openvpn_recipe e_pia_client_tun - option _description "Predefined Client for Private Internet Access" - option _role "client" - option client "1" - option dev "tun0" - option proto "udp" - list remote "us-example.privateinternetaccess.com" - option port "1198" - option resolv_retry "infinite" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option cipher "aes-128-cbc" - option auth "sha1" - option tls_client "1" - option remote_cert_tls "server" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option comp_lzo "yes" - option verb "1" - option reneg_sec "0" - option crl_verify "/etc/openvpn/pia/crl.rsa.2048.pem" - option ca "/etc/openvpn/pia/ca.rsa.2048.crt" - option disable_occ "1" - -# -# Windscribe -# -config openvpn_recipe e_windscribe_client_tun - option _description "Predefined Client for Windscribe" - option _role "client" - option client "1" - option dev "tun0" - option proto "udp" - list remote "example.windscribe.com" - option port "443" - option resolv_retry "infinite" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option cipher "aes-256-cbc" - option auth "sha512" - option tls_client "1" - option remote_cert_tls "server" - option key_direction "1" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option comp_lzo "yes" - option verb "2" - option reneg_sec "432000" - option tls_auth "/etc/openvpn/windscribe/ta.key" - option ca "/etc/openvpn/windscribe/ca.crt" - option redirect_gateway "def1" - -# -# ProtonVPN -# -config openvpn_recipe e_proton_client_tun - option _description "Predefined Client for ProtonVPN" - option _role "client" - option client "1" - option dev "tun0" - option proto "udp" - list remote "example.protonvpn.com" - option port "1194" - option resolv_retry "infinite" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option cipher "aes-256-cbc" - option auth "sha512" - option tls_client "1" - option remote_cert_tls "server" - option key_direction "1" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option comp_lzo "yes" - option verb "3" - option reneg_sec "0" - option tls_auth "/etc/openvpn/placeholder/placeholder.file" - option ca "/etc/openvpn/placeholder/placeholder.file" - option redirect_gateway "def1" - -# -# Mullvad -# -config openvpn_recipe e_mullvad_client_tun - option _description "Predefined Client for Mullvad" - option _role "client" - option client "1" - option dev "tun0" - option proto "udp" - list remote "example.mullvad.net" - option port "1194" - option resolv_retry "infinite" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option cipher "aes-256-cbc" - option tls_client "1" - option remote_cert_tls "server" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option comp_lzo "yes" - option verb "3" - option ca "/etc/openvpn/mullvad/mullvad_ca.crt" - option crl_verify "/etc/openvpn/mullvad/mullvad_crl.pem" - option redirect_gateway "def1" - -# -# AirVPN -# -config openvpn_recipe e_airvpn_client_tun - option _description "Predefined Client for AirVPN" - option _role "client" - option client "1" - option dev "tun0" - option proto "udp" - list remote "example.vpn.airdns.org" - option port "443" - option resolv_retry "infinite" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option cipher "aes-256-cbc" - option route_delay "5" - option explicit_exit_notify "5" - option tls_client "1" - option remote_cert_tls "server" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option comp_lzo "no" - option verb "3" - option key_direction "1" - option ca "/etc/openvpn/airvpn/ca.crt" - option cert "/etc/openvpn/airvpn/client.crt" - option key "/etc/openvpn/airvpn/client.key" - option tls_auth "/etc/openvpn/airvpn/ta.key" - -# -# Tunnelbear -# -config openvpn_recipe e_tunnelbear_client_tun - option _description "Predefined Client for Tunnelbear" - option _role "client" - option dev "tun0" - option proto "udp" - option port "443" - option client "1" - option nobind "1" - option persist_key "1" - option persist_tun "1" - option remote_cert_tls "server" - option reneg_sec "0" - option verb "1" - option comp_lzo "yes" - option auth_user_pass "/etc/openvpn/placeholder/placeholder.file" - option ca "/etc/openvpn/placeholder/placeholder.file" - option cert "/etc/openvpn/placeholder/placeholder.file" - option key "/etc/openvpn/placeholder/placeholder.file" - option remote "example.tunnelbear-ios.com" - option auth "SHA256" - option keysize "256" - option keep_alive "10 30" - option redirect_gateway "def1" diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn b/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn deleted file mode 100644 index 543cdf1..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/openvpn +++ /dev/null @@ -1,194 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2008-2013 OpenWrt.org -# Copyright (C) 2008 Jo-Philipp Wich -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. - -START=90 -STOP=10 - -USE_PROCD=1 -PROG=/usr/sbin/openvpn - -LIST_SEP=" -" -log() { - logger -t "OpenVpn init.d" "$@" -} - -if [ -e /tmp/openvpnboot ]; then - if [ -z "$1" ]; then - return - fi -fi - -UCI_STARTED= -UCI_DISABLED= - -append_param() { - local s="$1" - local v="$2" - case "$v" in - *_*_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;; - *_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;; - *_*) v=${v%%_*}-${v#*_} ;; - esac - echo -n "$v" >> "/var/etc/openvpn-$s.conf" - return 0 -} - -append_bools() { - local p; local v; local s="$1"; shift - for p in $*; do - config_get_bool v "$s" "$p" - [ "$v" = 1 ] && append_param "$s" "$p" && echo >> "/var/etc/openvpn-$s.conf" - done -} - -append_params() { - local p; local v; local s="$1"; shift - for p in $*; do - config_get v "$s" "$p" - IFS="$LIST_SEP" - for v in $v; do - [ -n "$v" ] && [ "$p" != "push" ] && append_param "$s" "$p" && echo " $v" >> "/var/etc/openvpn-$s.conf" - [ -n "$v" ] && [ "$p" == "push" ] && append_param "$s" "$p" && echo " \"$v\"" >> "/var/etc/openvpn-$s.conf" - done - unset IFS - done -} - -append_list() { - local p; local v; local s="$1"; shift - - list_cb_append() { - v="${v}:$1" - } - - for p in $*; do - unset v - config_list_foreach "$s" "$p" list_cb_append - [ -n "$v" ] && append_param "$s" "$p" && echo " ${v:1}" >> "/var/etc/openvpn-$s.conf" - done -} - -section_enabled() { - config_get_bool enable "$1" 'enable' 0 - config_get_bool enabled "$1" 'enabled' 0 - [ $enable -gt 0 ] || [ $enabled -gt 0 ] -} - -openvpn_add_instance() { - local name="$1" - local dir="$2" - local conf="$3" - - uci set openvpn.$1.laststart="$(date +%s)" - uci commit openvpn - - procd_open_instance "$name" - procd_set_param command "$PROG" \ - --syslog "openvpn($name)" \ - --status "/var/run/openvpn.$name.status" \ - --cd "$dir" \ - --config "$conf" - procd_set_param file "$dir/$conf" - procd_set_param term_timeout 15 - procd_set_param respawn - procd_append_param respawn 3600 - procd_append_param respawn 5 - procd_append_param respawn -1 - procd_close_instance -} - -start_instance() { - local s="$1" - - config_get config "$s" config - config="${config:+$(readlink -f "$config")}" - - log "start instance $s" - if [ ! -e /tmp/openvpnboot ]; then - config_get_bool bootstart "$s" 'bootstart' 0 - if [ $bootstart -eq 0 ]; then - append UCI_DISABLED "$config" "$LIST_SEP" - return 1 - fi - fi - - section_enabled "$s" || { - append UCI_DISABLED "$config" "$LIST_SEP" - return 1 - } - - [ ! -d "/var/run" ] && mkdir -p "/var/run" - - if [ ! -z "$config" ]; then - append UCI_STARTED "$config" "$LIST_SEP" - openvpn_add_instance "$s" "${config%/*}" "$config" - return - fi - - [ ! -d "/var/etc" ] && mkdir -p "/var/etc" - [ -f "/var/etc/openvpn-$s.conf" ] && rm "/var/etc/openvpn-$s.conf" - - append_bools "$s" $OPENVPN_BOOLS - append_params "$s" $OPENVPN_PARAMS - append_list "$s" $OPENVPN_LIST - - openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" - sleep 5 -} - -start_service() { - local instance="$1" - local instance_found=0 - - /etc/init.d/rootervpn start - - config_cb() { - local type="$1" - local name="$2" - if [ "$type" = "openvpn" ]; then - if [ -n "$instance" -a "$instance" = "$name" ]; then - instance_found=1 - fi - fi - } - - . /usr/share/openvpn/openvpn.options - config_load 'openvpn' - - if [ -n "$instance" ]; then - [ "$instance_found" -gt 0 ] || return - start_instance "$instance" - else - config_foreach start_instance 'openvpn' $1 - - - local path name - for path in /etc/openvpn/*.conf; do - if [ -f "$path" ]; then - name="${path##*/}"; name="${name%.conf}" - - # don't start configs again that are already started by uci - if echo "$UCI_STARTED" | grep -qxF "$path"; then - continue - - # don't start configs which are set to disabled in uci - elif echo "$UCI_DISABLED" | grep -qxF "$path"; then - logger -t openvpn "$name.conf is disabled in /etc/config/openvpn" - continue - fi - - openvpn_add_instance "$name" "${path%/*}" "$path" - - fi - done - fi - echo "0" > /tmp/openvpnboot -} - -service_triggers() { - procd_add_reload_trigger openvpn -} diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn b/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn deleted file mode 100644 index eb83a60..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/init.d/rootervpn +++ /dev/null @@ -1,183 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=60 - -log() { - logger -t "OpenVPN : " "$@" -} - -check_config () { - log "Check Client Interfaces" - CHANGE="0" - WW=$(uci get network.VPN) - if [ -z $WW ]; then - uci set network.VPN=interface - uci set network.VPN.proto="none" - uci set network.VPN.ifname="tun0" - uci set network.VPN.auto="0" - CHANGE="1" - fi - WW=$(uci get network.VPNS) - if [ -z $WW ]; then - uci set network.VPNS=interface - uci set network.VPNS.proto="none" - uci set network.VPNS.ifname="tun-server" - uci set network.VPNS.auto="0" - CHANGE="1" - fi - WW=$(uci get network.TAP) - if [ -z $WW ]; then - uci set network.TAP=interface - uci set network.TAP.proto="none" - uci set network.TAP.ifname="tap0" - uci set network.TAP.auto="1" - LANIF=$(uci get network.lan.ifname) - TAP0=$(echo $LANIF | grep "tap0") - if [ -z "$TAP0" ]; then - uci set network.lan.ifname="$(uci get network.lan.ifname) tap0" - fi - CHANGE="1" - fi - WW=$(uci get network.TAPS) - if [ -z $WW ]; then - uci set network.TAPS=interface - uci set network.TAPS.proto="none" - uci set network.TAPS.ifname="tap-server" - uci set network.TAPS.auto="0" - LANIF=$(uci get network.lan.ifname) - TAP1=$(echo $LANIF | grep "tap-server") - if [ -z "$TAP1" ]; then - uci set network.lan.ifname="$(uci get network.lan.ifname) tap-server" - fi - CHANGE="1" - fi - if [ $CHANGE = "1" ]; then - uci commit network - /etc/init.d/network restart - fi - - CHANGE="0" - WW=$(uci get firewall.vpnzone) - if [ -z $WW ]; then - uci set firewall.vpnzone=zone - uci set firewall.vpnzone.name="VPN" - uci set firewall.vpnzone.forward="REJECT" - uci set firewall.vpnzone.output="ACCEPT" - uci set firewall.vpnzone.network="VPN" - uci set firewall.vpnzone.input="REJECT" - uci set firewall.vpnzone.masq="1" - uci set firewall.vpnzone.mtu_fix="1" - uci set firewall.vpnforward=forwarding - uci set firewall.vpnforward.dest="VPN" - uci set firewall.vpnforward.src="lan" - CHANGE="1" - fi - WW=$(uci get firewall.vpnzones) - if [ -z $WW ]; then - uci set firewall.vpnzones=zone - uci set firewall.vpnzones.name="VPNS" - uci set firewall.vpnzones.forward="REJECT" - uci set firewall.vpnzones.output="ACCEPT" - uci set firewall.vpnzones.network="VPNS" - uci set firewall.vpnzones.input="ACCEPT" - uci set firewall.vpnzones.masq="1" - uci set firewall.vpnzones.mtu_fix="1" - uci set firewall.vpnforwards=forwarding - uci set firewall.vpnforwards.dest="VPNS" - uci set firewall.vpnforwards.src="lan" - CHANGE="1" - fi - if [ $CHANGE = "1" ]; then - uci commit firewall - /etc/init.d/firewall restart - fi - WW=$(uci get openvpn.settings) - if [ -z $WW ]; then - uci set openvpn.settings=settings - uci set openvpn.settings.vpn2lan="0" - uci set openvpn.settings.vpns2lan="0" - uci set openvpn.settings.vpn2wan="0" - uci set openvpn.settings.country="CA" - uci set openvpn.settings.city="Abbotsford" - uci set openvpn.settings.organ="ROOter" - uci set openvpn.settings.days="3650" - uci set openvpn.settings.nclient='1' - uci commit openvpn - fi -} - -checkserver() { - log "Check Server Interfaces" - local s=$1 - if [ -z $s ]; then - return - fi - local SERVER="0" - local config=$(uci get openvpn.$s.config) - if [ ! -z $config ]; then - return - fi - local client=$(uci get openvpn.$s.client) - if [ -z $client ]; then - SERVER="1" - else - if [ $client = "0" ]; then - SERVER="1" - fi - fi - - if [ $SERVER = "1" ]; then - port=$(uci get openvpn.$s.port) - if [ -z $port ]; then - PORT="1194" - else - PORT=$port - fi - # look for rule for this port - INB="inbound"$PORT - RULE=$(uci get firewall.$INB) - if [ -z $RULE ]; then - uci set firewall.$INB=rule - uci set firewall.$INB.name=$INB - uci set firewall.$INB.target=ACCEPT - uci set firewall.$INB.src=* - uci set firewall.$INB.proto=udp - uci set firewall.$INB.dest_port=$PORT - uci commit firewall - /etc/init.d/firewall reload - fi - DEV=$(uci get openvpn.$s.dev) - if [ $DEV = "tun0" ]; then - uci set openvpn.$s.dev="tun1" - uci commit openvpn - else - - if [ $DEV = "tap0" ]; then - uci set openvpn.$s.dev="tap1" - uci commit openvpn - fi - fi - else - DEV=$(uci get openvpn.$s.dev) - if [ $DEV = "tun1" ]; then - uci set openvpn.$s.dev="tun0" - uci commit openvpn - else - if [ $DEV = "tap1" ]; then - uci set openvpn.$s.dev="tap0" - uci commit openvpn - fi - fi - fi -} - -start() { - check_config - checkserver - - if [ -d /etc/luci-uploads ]; then - rm -rfv /etc/luci-uploads - fi - ln -s /etc/openvpn /etc/luci-uploads -} \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt deleted file mode 100644 index cc37250..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ca.crt +++ /dev/null @@ -1,36 +0,0 @@ ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt deleted file mode 100644 index 7c8e434..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.crt +++ /dev/null @@ -1,38 +0,0 @@ ------BEGIN CERTIFICATE----- -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 -qAZoGjCdOJq/IrQCq/95Cpw= ------END CERTIFICATE----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key deleted file mode 100644 index 9f34129..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/client.key +++ /dev/null @@ -1,52 +0,0 @@ ------BEGIN PRIVATE KEY----- -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 -59PFiE0grG3JNZa3g34RjxOtsoNrz3bH ------END PRIVATE KEY----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key deleted file mode 100644 index 7d53ac5..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/airvpn/ta.key +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN OpenVPN Static key V1----- -7bb7a23a0f5f28d01e792df68f1764ab -f2688719288808bf58e8a2d4f9354ecf -132625dfb895fc3f6330ae1e868e4dfa -c164c0931593d7f9a7da9595cf353433 -8896e1d0a987a0d19838944af8fea4e5 -215a3a0c76f4c67d5a4aee6a53be66a4 -c88b84f850030840fb30f8550ed8068f -35c1ef34ee8f40a0ea5862dfb6f8d3c5 -7ab5e27ac2799cf93e8765ff63cd8cd8 -6b391b813925cd373bb202796f64d16f -003d042ca828d1b07f18ba1d0cb0323d -df3ee9287e9e084e655699efb3cffa92 -3626946fa372e7beee245e7a95b4c1d8 -7d16cae685218d4b8afc019b22e41083 -476ee9883fe666d236301e55b2062551 -4d91c8a69467a758293994df1e6fa7ae ------END OpenVPN Static key V1----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt deleted file mode 100644 index b795d91..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_ca.crt +++ /dev/null @@ -1,109 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 3 (0x3) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=NA, ST=None, L=None, O=Mullvad, CN=Mullvad CA/emailAddress=info@mullvad.net - Validity - Not Before: Mar 24 16:19:48 2009 GMT - Not After : Mar 22 16:19:48 2019 GMT - Subject: C=NA, ST=None, L=None, O=Mullvad, CN=master.mullvad.net/emailAddress=info@mullvad.net - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:c5:00:39:5d:fe:9b:0c:b7:ff:76:a4:93:bf:26: - 1b:d6:c8:4a:e5:3c:ce:1c:2c:16:80:a2:61:a6:e9: - 63:4b:70:a1:80:6f:0e:0c:bb:a9:b6:d1:bd:f5:a0: - 78:82:09:4d:94:22:aa:77:7c:09:36:42:cd:a5:a6: - 90:73:27:42:00:31:e4:d4:8b:49:36:65:a3:25:82: - b8:26:d7:d1:f5:b5:a9:be:57:93:9d:7c:d6:1c:df: - 9a:87:81:53:0b:17:81:d1:0d:ca:dc:4d:19:13:fa: - 11:e6:da:68:eb:81:05:39:e3:1e:3a:3f:fc:e2:64: - 3c:98:3c:89:a9:42:b3:30:70:57:56:a1:f5:08:b2: - 75:12:a0:36:93:9d:69:e9:7e:11:71:d9:1c:e8:7d: - ec:03:21:11:7a:0a:7a:03:35:ba:b8:b2:0c:3a:6f: - 57:88:62:45:3d:0c:6c:18:ff:21:49:37:ae:40:78: - 6d:45:52:29:ac:21:ad:4a:01:61:67:0b:01:c4:ac: - b0:88:97:52:ff:cb:3a:21:f0:14:2b:c1:79:8d:79: - 35:14:fc:9c:3f:6c:c9:62:fc:8c:c7:a8:51:34:75: - 1c:23:d5:db:b9:44:08:1c:0c:17:2c:21:2a:b4:29: - db:15:59:e7:a9:1c:d6:19:19:ef:e4:6b:ea:78:6d: - 76:8d - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 75:8A:14:92:0D:F3:6E:B7:36:4F:8B:4F:15:6C:3F:18:15:90:64:DE - X509v3 Authority Key Identifier: - keyid:E1:63:B4:3E:55:A3:D2:37:5F:DE:3A:91:48:51:4B:20:1A:F2:9B:C5 - DirName:/C=NA/ST=None/L=None/O=Mullvad/CN=Mullvad CA/emailAddress=info@mullvad.net - serial:84:68:2E:A0:51:2A:BB:D4 - - X509v3 Basic Constraints: - CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - a4:b4:62:3d:cb:7e:57:b3:bd:2a:41:e0:3b:94:d0:4c:08:69: - 8a:b1:73:15:13:20:c9:d7:b0:b6:5d:65:4a:4d:1d:27:cc:ca: - 11:0e:86:fa:65:61:26:39:c2:54:8e:da:eb:78:21:37:0e:c7: - a4:d2:17:8a:4b:ad:17:84:25:5e:24:0e:9a:81:ff:d1:1b:0e: - 32:9b:f4:81:e0:07:e9:8f:9d:c1:43:7f:40:30:01:07:7c:02: - c7:c4:9c:05:48:4c:bf:41:69:57:c1:d3:bb:a3:5a:01:17:96: - b0:c9:00:22:57:2f:84:da:45:33:6e:6c:2b:13:c5:af:75:a7: - b2:6b:71:6e:13:2c:97:0e:d9:93:da:6d:d9:34:c6:06:7d:0e: - e2:b8:d2:78:13:79:0f:ac:ac:a8:68:a9:72:73:7a:d8:ab:7b: - 0a:b0:54:b5:f3:ce:29:0d:47:82:0c:b4:d9:20:64:ff:ef:17: - 46:92:de:65:e8:67:ce:3a:92:de:e4:3e:99:73:9f:7a:7c:00: - 72:07:39:78:77:37:62:89:a2:db:24:fd:60:2a:e0:82:57:f6: - 55:94:f6:79:47:19:c9:13:3b:5d:b7:6b:66:14:d4:7d:3c:76: - 75:e9:a3:55:ba:b4:92:30:3b:ad:66:72:0c:39:4b:cc:95:a9: - bc:06:ef:2b ------BEGIN CERTIFICATE----- -MIIEQjCCAyqgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBzMQswCQYDVQQGEwJOQTEN -MAsGA1UECBMETm9uZTENMAsGA1UEBxMETm9uZTEQMA4GA1UEChMHTXVsbHZhZDET -MBEGA1UEAxMKTXVsbHZhZCBDQTEfMB0GCSqGSIb3DQEJARYQaW5mb0BtdWxsdmFk -Lm5ldDAeFw0wOTAzMjQxNjE5NDhaFw0xOTAzMjIxNjE5NDhaMHsxCzAJBgNVBAYT -Ak5BMQ0wCwYDVQQIEwROb25lMQ0wCwYDVQQHEwROb25lMRAwDgYDVQQKEwdNdWxs -dmFkMRswGQYDVQQDExJtYXN0ZXIubXVsbHZhZC5uZXQxHzAdBgkqhkiG9w0BCQEW -EGluZm9AbXVsbHZhZC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQDFADld/psMt/92pJO/JhvWyErlPM4cLBaAomGm6WNLcKGAbw4Mu6m20b31oHiC -CU2UIqp3fAk2Qs2lppBzJ0IAMeTUi0k2ZaMlgrgm19H1tam+V5OdfNYc35qHgVML -F4HRDcrcTRkT+hHm2mjrgQU54x46P/ziZDyYPImpQrMwcFdWofUIsnUSoDaTnWnp -fhFx2RzofewDIRF6CnoDNbq4sgw6b1eIYkU9DGwY/yFJN65AeG1FUimsIa1KAWFn -CwHErLCIl1L/yzoh8BQrwXmNeTUU/Jw/bMli/IzHqFE0dRwj1du5RAgcDBcsISq0 -KdsVWeepHNYZGe/ka+p4bXaNAgMBAAGjgdgwgdUwHQYDVR0OBBYEFHWKFJIN8263 -Nk+LTxVsPxgVkGTeMIGlBgNVHSMEgZ0wgZqAFOFjtD5Vo9I3X946kUhRSyAa8pvF -oXekdTBzMQswCQYDVQQGEwJOQTENMAsGA1UECBMETm9uZTENMAsGA1UEBxMETm9u -ZTEQMA4GA1UEChMHTXVsbHZhZDETMBEGA1UEAxMKTXVsbHZhZCBDQTEfMB0GCSqG -SIb3DQEJARYQaW5mb0BtdWxsdmFkLm5ldIIJAIRoLqBRKrvUMAwGA1UdEwQFMAMB -Af8wDQYJKoZIhvcNAQEFBQADggEBAKS0Yj3LflezvSpB4DuU0EwIaYqxcxUTIMnX -sLZdZUpNHSfMyhEOhvplYSY5wlSO2ut4ITcOx6TSF4pLrReEJV4kDpqB/9EbDjKb -9IHgB+mPncFDf0AwAQd8AsfEnAVITL9BaVfB07ujWgEXlrDJACJXL4TaRTNubCsT -xa91p7JrcW4TLJcO2ZPabdk0xgZ9DuK40ngTeQ+srKhoqXJzetirewqwVLXzzikN -R4IMtNkgZP/vF0aS3mXoZ846kt7kPplzn3p8AHIHOXh3N2KJotsk/WAq4IJX9lWU -9nlHGckTO123a2YU1H08dnXpo1W6tJIwO61mcgw5S8yVqbwG7ys= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEQjCCAyqgAwIBAgIJAIRoLqBRKrvUMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNV -BAYTAk5BMQ0wCwYDVQQIEwROb25lMQ0wCwYDVQQHEwROb25lMRAwDgYDVQQKEwdN -dWxsdmFkMRMwEQYDVQQDEwpNdWxsdmFkIENBMR8wHQYJKoZIhvcNAQkBFhBpbmZv -QG11bGx2YWQubmV0MB4XDTA5MDMyNDA2NDcyNVoXDTE5MDMyMjA2NDcyNVowczEL -MAkGA1UEBhMCTkExDTALBgNVBAgTBE5vbmUxDTALBgNVBAcTBE5vbmUxEDAOBgNV -BAoTB011bGx2YWQxEzARBgNVBAMTCk11bGx2YWQgQ0ExHzAdBgkqhkiG9w0BCQEW -EGluZm9AbXVsbHZhZC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQDNNzZOrq+gMaA6wfyWdNFmxlM2OB1czwFgtPiDd9f6F8m6CGYBQog3Q2Wx3yAv -hxt/uchFBCKtYz6Yh59BCxXKfNAQT2uaMC6KAvKFgz0wppi4S8YbWg2KDelNO/Zv -Rb1QT4CBWMbtYzCQZvlJpHr2ZwuXG2OiT477oMyX5Hmf+iT0drmqi+wylRr7CRBs -LBu+fxLZ2LFD5g6MATuL3ql5JLIoVjlSqIgbld74pD4WUnM61HRwFsKoCEjq409Y -QNP1xO7BeaJu3uQvg/HJhXnGZxTatXhqvdCuAPQRppQ4UnkUzxdSTrfgM3hqMony -vX1vy0dX1S8iTQCIeyzAYNObAgMBAAGjgdgwgdUwHQYDVR0OBBYEFOFjtD5Vo9I3 -X946kUhRSyAa8pvFMIGlBgNVHSMEgZ0wgZqAFOFjtD5Vo9I3X946kUhRSyAa8pvF -oXekdTBzMQswCQYDVQQGEwJOQTENMAsGA1UECBMETm9uZTENMAsGA1UEBxMETm9u -ZTEQMA4GA1UEChMHTXVsbHZhZDETMBEGA1UEAxMKTXVsbHZhZCBDQTEfMB0GCSqG -SIb3DQEJARYQaW5mb0BtdWxsdmFkLm5ldIIJAIRoLqBRKrvUMAwGA1UdEwQFMAMB -Af8wDQYJKoZIhvcNAQEFBQADggEBAMjMAFPDeFOrQsvMXD/x+CuARwegS2PDZuB5 -f1Svw3YDF6cB1jlc0F12nh9SZxaYRwKIlpYoolLCOLoUCLwQJ0gsokxLV7G4gVb8 -dzETnNq4HG/QOPwPisjoOCaEmcd0tx1EkyNY0KLqFZTS0VdmDHCn89dDFA/6yuYI -5u04uJs7c/K4qaW7X6ajOOdneqjbtPeVOvx9DWXHxA0xz4Y+/w4laX/OTRD7jySq -K9fLfRliE5zsxzpUr5EWxAnqiABoWL71SiItk5fG8k3MJJ9SVr+YnTHmE7S4KNqu -4wTksvkb0Tmjae1lRSlMd6u2AulAxVcVKAod2QVffhj+hdkYM94= ------END CERTIFICATE----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem deleted file mode 100644 index 10e26dd..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/mullvad/mullvad_crl.pem +++ /dev/null @@ -1,36 +0,0 @@ ------BEGIN X509 CRL----- -MIIGMTCCBRkwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCTkExDTALBgNVBAgT -BE5vbmUxDTALBgNVBAcTBE5vbmUxEDAOBgNVBAoTB011bGx2YWQxGzAZBgNVBAMT -Em1hc3Rlci5tdWxsdmFkLm5ldDEfMB0GCSqGSIb3DQEJARYQaW5mb0BtdWxsdmFk -Lm5ldBcNMTcwNjIyMTQzMzEyWhcNMjcwNjIwMTQzMzEyWjCCBGswEgIBARcNMTcw -NjIyMTQzMzExWjASAgEDFw0xNzA2MjIxNDMzMTFaMBICASkXDTE3MDYyMjE0MzMx -MVowEwICDasXDTE3MDYyMjE0MzMxMVowEwICDawXDTE3MDYyMjE0MzMxMVowEwIC -Da0XDTE3MDYyMjE0MzMxMVowEwICDx4XDTE3MDYyMjE0MzMxMVowEwICGxsXDTE3 -MDYyMjE0MzMxMVowEwICPf4XDTE3MDYyMjE0MzMxMVowEwICSrUXDTE3MDYyMjE0 -MzMxMVowFAIDAbbXFw0xNzA2MjIxNDMzMTFaMBQCAwaeUBcNMTcwNjIyMTQzMzEx -WjAUAgMGnlUXDTE3MDYyMjE0MzMxMVowFAIDCheTFw0xNzA2MjIxNDMzMTFaMBQC -AwpvDBcNMTcwNjIyMTQzMzExWjAUAgML2jcXDTE3MDYyMjE0MzMxMVowFAIDDCfI -Fw0xNzA2MjIxNDMzMTFaMBQCAwwrKhcNMTcwNjIyMTQzMzExWjAUAgMMNWEXDTE3 -MDYyMjE0MzMxMVowFAIDDDViFw0xNzA2MjIxNDMzMTFaMBQCAwyXhRcNMTcwNjIy -MTQzMzExWjAUAgMM99UXDTE3MDYyMjE0MzMxMVowFAIDDPfWFw0xNzA2MjIxNDMz -MTFaMBQCAwz31xcNMTcwNjIyMTQzMzExWjAUAgMM9+MXDTE3MDYyMjE0MzMxMVow -FAIDDPfkFw0xNzA2MjIxNDMzMTFaMBQCAwz35RcNMTcwNjIyMTQzMzExWjAUAgMN -FHEXDTE3MDYyMjE0MzMxMVowFAIDDRSLFw0xNzA2MjIxNDMzMTFaMBQCAw1FfBcN -MTcwNjIyMTQzMzExWjAUAgMNUWcXDTE3MDYyMjE0MzMxMVowFAIDDVFoFw0xNzA2 -MjIxNDMzMTFaMBQCAw1RbBcNMTcwNjIyMTQzMzExWjAUAgMN2AoXDTE3MDYyMjE0 -MzMxMVowFAIDDdgLFw0xNzA2MjIxNDMzMTFaMBQCAw6G3xcNMTcwNjIyMTQzMzEx -WjAUAgMOkpwXDTE3MDYyMjE0MzMxMVowFAIDDpKdFw0xNzA2MjIxNDMzMTFaMBQC -Aw7DWhcNMTcwNjIyMTQzMzExWjAUAgMPFEEXDTE3MDYyMjE0MzMxMVowFAIDDyaP -Fw0xNzA2MjIxNDMzMTFaMBQCAw9D1xcNMTcwNjIyMTQzMzExWjAUAgMPzJQXDTE3 -MDYyMjE0MzMxMVowFAIDE3pTFw0xNzA2MjIxNDMzMTFaMBQCAxN6VBcNMTcwNjIy -MTQzMzExWjAUAgMTjroXDTE3MDYyMjE0MzMxMVowFAIDFIUDFw0xNzA2MjIxNDMz -MTFaMBQCAx7XBxcNMTcwNjIyMTQzMzExWjAUAgMgFScXDTE3MDYyMjE0MzMxMVow -FAIDImufFw0xNzA2MjIxNDMzMTFaMBQCAyPpNRcNMTcwNjIyMTQzMzExWjAUAgMk -eEgXDTE3MDYyMjE0MzMxMVowDQYJKoZIhvcNAQELBQADggEBAEdGuk5OitTepMQL -O2ugSjKl9le9ttuwiNkXCowYZwMpvOvk98RuhcgqwetDtxdMIi7koMIlbILfbIwA -VYvaV7HzpOzkL9D4RpE8GN3r1xjc+pjz5RN08Q+l/pRI9VeS2Bz6sstujqDMu0kT -LEzxtyiWGgdyYL0ykirahStLxmjc0JLLSsZXHuVJGmdJsphoEw/zgTRR02N7Q0gP -AmL6+i4mXY8OMaUMFWwKikliT+VAT23H1VPPUpS/5n3p+j15Hn5bI+rHyLmO2Ca7 -0UlcBbTVhoNMO25/6js5icRktebiaI0hq3Zofd5U80tGJnH+udIUEAq6CD/wUNqq -VcdW4oc= ------END X509 CRL----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt deleted file mode 100644 index 6deea60..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/ca.rsa.2048.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFqzCCBJOgAwIBAgIJAKZ7D5Yv87qDMA0GCSqGSIb3DQEBDQUAMIHoMQswCQYD -VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNV -BAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIElu -dGVybmV0IEFjY2VzczEgMB4GA1UEAxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3Mx -IDAeBgNVBCkTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkB -FiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbTAeFw0xNDA0MTcxNzM1 -MThaFw0zNDA0MTIxNzM1MThaMIHoMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex -EzARBgNVBAcTCkxvc0FuZ2VsZXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQg -QWNjZXNzMSAwHgYDVQQLExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UE -AxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBCkTF1ByaXZhdGUgSW50 -ZXJuZXQgQWNjZXNzMS8wLQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVy -bmV0YWNjZXNzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPXD -L1L9tX6DGf36liA7UBTy5I869z0UVo3lImfOs/GSiFKPtInlesP65577nd7UNzzX -lH/P/CnFPdBWlLp5ze3HRBCc/Avgr5CdMRkEsySL5GHBZsx6w2cayQ2EcRhVTwWp -cdldeNO+pPr9rIgPrtXqT4SWViTQRBeGM8CDxAyTopTsobjSiYZCF9Ta1gunl0G/ -8Vfp+SXfYCC+ZzWvP+L1pFhPRqzQQ8k+wMZIovObK1s+nlwPaLyayzw9a8sUnvWB -/5rGPdIYnQWPgoNlLN9HpSmsAcw2z8DXI9pIxbr74cb3/HSfuYGOLkRqrOk6h4RC -OfuWoTrZup1uEOn+fw8CAwEAAaOCAVQwggFQMB0GA1UdDgQWBBQv63nQ/pJAt5tL -y8VJcbHe22ZOsjCCAR8GA1UdIwSCARYwggESgBQv63nQ/pJAt5tLy8VJcbHe22ZO -sqGB7qSB6zCB6DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpM -b3NBbmdlbGVzMSAwHgYDVQQKExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4G -A1UECxMXUHJpdmF0ZSBJbnRlcm5ldCBBY2Nlc3MxIDAeBgNVBAMTF1ByaXZhdGUg -SW50ZXJuZXQgQWNjZXNzMSAwHgYDVQQpExdQcml2YXRlIEludGVybmV0IEFjY2Vz -czEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j -b22CCQCmew+WL/O6gzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQAn -a5PgrtxfwTumD4+3/SYvwoD66cB8IcK//h1mCzAduU8KgUXocLx7QgJWo9lnZ8xU -ryXvWab2usg4fqk7FPi00bED4f4qVQFVfGfPZIH9QQ7/48bPM9RyfzImZWUCenK3 -7pdw4Bvgoys2rHLHbGen7f28knT2j/cbMxd78tQc20TIObGjo8+ISTRclSTRBtyC -GohseKYpTS9himFERpUgNtefvYHbn70mIOzfOJFTVqfrptf9jXa9N8Mpy3ayfodz -1wiqdteqFXkTYoSDctgKMiZ6GdocK9nMroQipIQtpnwd4yBDWIyC6Bvlkrq5TQUt -YDQ8z9v+DMO6iwyIDRiU ------END CERTIFICATE----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem deleted file mode 100644 index a58ef56..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/pia/crl.rsa.2048.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN X509 CRL----- -MIICWDCCAUAwDQYJKoZIhvcNAQENBQAwgegxCzAJBgNVBAYTAlVTMQswCQYDVQQI -EwJDQTETMBEGA1UEBxMKTG9zQW5nZWxlczEgMB4GA1UEChMXUHJpdmF0ZSBJbnRl -cm5ldCBBY2Nlc3MxIDAeBgNVBAsTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSAw -HgYDVQQDExdQcml2YXRlIEludGVybmV0IEFjY2VzczEgMB4GA1UEKRMXUHJpdmF0 -ZSBJbnRlcm5ldCBBY2Nlc3MxLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRl -aW50ZXJuZXRhY2Nlc3MuY29tFw0xNjA3MDgxOTAwNDZaFw0zNjA3MDMxOTAwNDZa -MCYwEQIBARcMMTYwNzA4MTkwMDQ2MBECAQYXDDE2MDcwODE5MDA0NjANBgkqhkiG -9w0BAQ0FAAOCAQEAQZo9X97ci8EcPYu/uK2HB152OZbeZCINmYyluLDOdcSvg6B5 -jI+ffKN3laDvczsG6CxmY3jNyc79XVpEYUnq4rT3FfveW1+Ralf+Vf38HdpwB8EW -B4hZlQ205+21CALLvZvR8HcPxC9KEnev1mU46wkTiov0EKc+EdRxkj5yMgv0V2Re -ze7AP+NQ9ykvDScH4eYCsmufNpIjBLhpLE2cuZZXBLcPhuRzVoU3l7A9lvzG9mjA -5YijHJGHNjlWFqyrn1CfYS6koa4TGEPngBoAziWRbDGdhEgJABHrpoaFYaL61zqy -MR6jC0K2ps9qyZAN74LEBedEfK7tBOzWMwr58A== ------END X509 CRL----- diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file deleted file mode 100644 index e88efe6..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/placeholder/placeholder.file +++ /dev/null @@ -1,2 +0,0 @@ -placeholder file -placeholder \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt deleted file mode 100644 index 7edc133..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ca.crt +++ /dev/null @@ -1,34 +0,0 @@ ------BEGIN CERTIFICATE----- -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 -ZYGQgrLt+ot8MbLhJlkp4Q== ------END CERTIFICATE----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key b/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key deleted file mode 100644 index dd556ac..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/etc/openvpn/windscribe/ta.key +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN OpenVPN Static key V1----- -5801926a57ac2ce27e3dfd1dd6ef8204 -2d82bd4f3f0021296f57734f6f1ea714 -a6623845541c4b0c3dea0a050fe6746c -b66dfab14cda27e5ae09d7c155aa554f -399fa4a863f0e8c1af787e5c602a801d -3a2ec41e395a978d56729457fe6102d7 -d9e9119aa83643210b33c678f9d4109e -3154ac9c759e490cb309b319cf708cae -83ddadc3060a7a26564d1a24411cd552 -fe6620ea16b755697a4fc5e6e9d0cfc0 -c5c4a1874685429046a424c026db672e -4c2c492898052ba59128d46200b40f88 -0027a8b6610a4d559bdc9346d33a0a6b -08e75c7fd43192b162bfd0aef0c716b3 -1584827693f676f9a5047123466f0654 -eade34972586b31c6ce7e395f4b478cb ------END OpenVPN Static key V1----- \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn b/rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn deleted file mode 100644 index 30f20da..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/lib/upgrade/keep.d/rootervpn +++ /dev/null @@ -1 +0,0 @@ -/etc/openvpn/* diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass b/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass deleted file mode 100644 index 615c85c..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/ovpn-userpass +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -log() { - logger -t "UserPass : " "$@" -} - -conf="/etc/openvpn/ovpnauth.conf" - -userpass=`cat $1` -username=`echo $userpass | awk '{print $1}'` -password=`echo $userpass | awk '{print $2}'` - -log "$username $password" - - -exit 0 \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall b/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall deleted file mode 100644 index 3802082..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/bin/rkillall +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -LOOKFOR=$1 -KILLLIST=$(ps | grep $LOOKFOR) -echo "$KILLLIST" | while read line; do - if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then - PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") - kill $PIDV - fi -done \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh deleted file mode 100644 index b461228..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/dns.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Firewall Settings : " "$@" -} - -sleep 5 -LANOPENDNS=$(uci get openvpn.settings.lanopendns) -if [ -z $LANOPENDNS ]; then - LANOPENDNS="0" -fi -LANGOOGLE=$(uci get openvpn.settings.langoogle) -if [ -z $LANGOOGLE ]; then - LANGOOGLE="0" -fi -WANOPENDNS=$(uci get openvpn.settings.wanopendns) -if [ -z $WANOPENDNS ]; then - WANOPENDNS="0" -fi -WANGOOGLE=$(uci get openvpn.settings.wangoogle) -if [ -z $WANGOOGLE ]; then - WANGOOGLE="0" -fi - -if [ $LANOPENDNS = "1" -a $LANGOOGLE = "0" ]; then - uci del dhcp.lan.dhcp_option - uci add_list dhcp.lan.dhcp_option='6,208.67.222.222,208.67.220.220' -fi -if [ $LANOPENDNS = "0" -a $LANGOOGLE = "1" ]; then - uci del dhcp.lan.dhcp_option - uci add_list dhcp.lan.dhcp_option='6,8.8.8.8,8.8.4.4' -fi -if [ $LANOPENDNS = "1" -a $LANGOOGLE = "1" ]; then - uci del dhcp.lan.dhcp_option - uci add_list dhcp.lan.dhcp_option='6,8.8.8.8,8.8.4.4' - uci add_list dhcp.lan.dhcp_option='6,208.67.222.222,208.67.220.220' -fi -if [ $LANOPENDNS = "0" -a $LANGOOGLE = "0" ]; then - uci del dhcp.lan.dhcp_option -fi - -if [ $WANOPENDNS = "1" -a $WANGOOGLE = "0" ]; then - uci set network.wan.peerdns='0' - uci del network.wan.dns - uci add_list network.wan.dns='208.67.222.222' - uci add_list network.wan.dns='208.67.220.220' -fi -if [ $WANOPENDNS = "0" -a $WANGOOGLE = "1" ]; then - uci set network.wan.peerdns='0' - uci del network.wan.dns - uci add_list network.wan.dns='8.8.8.8' - uci add_list network.wan.dns='8.8.4.4' -fi -if [ $WANOPENDNS = "1" -a $WANGOOGLE = "1" ]; then - uci set network.wan.peerdns='0' - uci del network.wan.dns - uci add_list network.wan.dns='8.8.8.8' - uci add_list network.wan.dns='8.8.4.4' - uci add_list network.wan.dns='208.67.222.222' - uci add_list network.wan.dns='208.67.220.220' -fi -if [ $WANOPENDNS = "0" -a $WANGOOGLE = "0" ]; then - uci set network.wan.peerdns='1' - uci del network.wan.dns -fi -uci commit -/etc/init.d/network restart \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh deleted file mode 100644 index 3ae0752..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/firewall.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Firewall Settings : " "$@" -} - -sleep 5 -VPN2LAN=$(uci get openvpn.settings.vpn2lan) -if [ -z $VPN2LAN ]; then - VPN2LAN="0" -fi -VPNS2LAN=$(uci get openvpn.settings.vpns2lan) -if [ -z $VPNS2LAN ]; then - VPNS2LAN="0" -fi -VPN2WAN=$(uci get openvpn.settings.vpn2wan) -if [ -z $VPN2WAN ]; then - VPN2WAN="0" -fi - -CHANGE="0" -if [ $VPN2LAN = "1" ]; then - WW=$(uci get firewall.vpnforward1) - if [ -z $WW ]; then - uci set firewall.vpnforward1=forwarding - uci set firewall.vpnforward1.dest="lan" - uci set firewall.vpnforward1.src="VPN" - CHANGE="1" - fi -else - WW=$(uci get firewall.vpnforward1) - if [ ! -z $WW ]; then - uci delete firewall.vpnforward1 - CHANGE="1" - fi -fi - -if [ $VPNS2LAN = "1" ]; then - WW=$(uci get firewall.vpnforwards1) - if [ -z $WW ]; then - uci set firewall.vpnforwards1=forwarding - uci set firewall.vpnforwards1.dest="lan" - uci set firewall.vpnforwards1.src="VPNS" - CHANGE="1" - fi -else - WW=$(uci get firewall.vpnforwards1) - if [ ! -z $WW ]; then - uci delete firewall.vpnforwards1 - CHANGE="1" - fi -fi - -if [ $VPN2WAN = "1" ]; then - WW=$(uci get firewall.vpnforward2) - if [ -z $WW ]; then - uci set firewall.vpnforward2=forwarding - uci set firewall.vpnforward2.dest="wan" - uci set firewall.vpnforward2.src="VPNS" - CHANGE="1" - fi -else - WW=$(uci get firewall.vpnforward2) - if [ ! -z $WW ]; then - uci delete firewall.vpnforward2 - CHANGE="1" - fi -fi - -if [ $CHANGE = "1" ]; then - uci commit firewall - /etc/init.d/firewall restart -fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh deleted file mode 100644 index 17e1704..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/generate.sh +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/sh - - rm -f /tmp/easyrsa -### Step 1: Create the PKI directory tree - PKI_DIR="/tmp/openvpn" - -# if [ -d "$PKI_DIR" ]; then - rm -rfv "$PKI_DIR" -# fi - mkdir -p ${PKI_DIR} - chmod -R 0777 ${PKI_DIR} - mkdir -p ${PKI_DIR}/client - chmod -R 0777 ${PKI_DIR}/client - mkdir -p ${PKI_DIR}/server - chmod -R 0777 ${PKI_DIR}/server - mkdir -p ${PKI_DIR}/package - chmod -R 0777 ${PKI_DIR}/package - if [ -d "/www/package" ]; then - rm -rfv "/www/package" - fi - ln -s ${PKI_DIR}/package /www/package - cd ${PKI_DIR} - - touch index.txt - echo 1000 > serial - mkdir newcerts - - -### Step 2: Start with a clean configuration, and establish the basic variables - cp /etc/ssl/openssl.cnf ${PKI_DIR} - PKI_CNF=${PKI_DIR}/openssl.cnf - - CNT=$(uci get openvpn.settings.country) - CTY=$(uci get openvpn.settings.city) - ORG=$(uci get openvpn.settings.organ) - DAYS=$(uci get openvpn.settings.days) - CNAME=$(uci get openvpn.settings.comm) - EMAIL=$(uci get openvpn.settings.email) - UNIT=$(uci get openvpn.settings.unit) - UNSTRUC=$(uci get openvpn.settings.unstruc) - NCLIENT=$(uci get openvpn.settings.nclient) - if [ -z $NCLIENT ]; then - NCLIENT=1 - fi - - sed -i "/^dir/ s:=.*:= ${PKI_DIR}/:" ${PKI_CNF} - sed -i '/.*Name/ s:= match:= optional:' ${PKI_CNF} - - sed -i "/organizationName_default/ s:= .*:= $ORG:" ${PKI_CNF} - sed -i "/stateOrProvinceName_default/ s:= .*:= $CTY:" ${PKI_CNF} - sed -i "/countryName_default/ s:= .*:= $CNT:" ${PKI_CNF} - if [ ! -z $CNAME ]; then - sed -i -e "s/commonName = Common Name (e.g. server FQDN or YOUR name)/commonName = $CNAME/g" ${PKI_CNF} - fi - if [ ! -z $EMAIL ]; then - sed -i -e "s/emailAddress = Email Address/emailAddress = $EMAIL/g" ${PKI_CNF} - fi - if [ ! -z $UNIT ]; then - sed -i -e "s/organizationalUnitName = Organizational Unit Name (eg, section)/organizationalUnitName = $UNIT/g" ${PKI_CNF} - fi - if [ ! -z $UNSTRUC ]; then - sed -i -e "s/unstructuredName = An optional company name/unstructuredName = $UNSTRUC/g" ${PKI_CNF} - fi - - sed -i "/default_days/ s:=.*:= $DAYS:" ${PKI_CNF} - sed -i "/default_bits/ s:=.*:= 2048:" ${PKI_CNF} - - -cat >> ${PKI_CNF} <<"EOF" -############################################################################### -### Check via: openssl x509 -text -noout -in *.crt | grep 509 -A 1 -[ my-server ] -# X509v3 Key Usage: Digital Signature, Key Encipherment -# X509v3 Extended Key Usage: TLS Web Server Authentication - keyUsage = digitalSignature, keyEncipherment - extendedKeyUsage = serverAuth - -[ my-client ] -# X509v3 Key Usage: Digital Signature -# X509v3 Extended Key Usage: TLS Web Client Authentication - keyUsage = digitalSignature - extendedKeyUsage = clientAuth - -EOF - - echo "1" > /tmp/easyrsa - -### Step 3a: Create the CA, Server, and Client certificates (*without* using easy-rsa): -# pkitool --initca ## equivalent to the 'build-ca' script - openssl req -batch -nodes -new -keyout "ca.key" -out "ca.crt" -x509 -days $DAYS -config ${PKI_CNF} 2> /dev/null ## x509 (self-signed) for the CA - - echo "2" > /tmp/easyrsa -# pkitool --server my-server ## equivalent to the 'build-key-server' script - openssl req -batch -nodes -new -keyout "$ORG-server.key" -out "$ORG-server.csr" -subj "/CN=$ORG-server" -config ${PKI_CNF} 2> /dev/null - openssl ca -batch -keyfile "ca.key" -cert "ca.crt" -in "$ORG-server.csr" -out "$ORG-server.crt" -config ${PKI_CNF} -extensions my-server 2> /dev/null - - echo "3" > /tmp/easyrsa -# pkitool my-client ## equivalent to the 'build-key' script - COUNTER=$NCLIENT - while [ $COUNTER -gt 0 ]; do - openssl req -batch -nodes -new -keyout "$ORG-client$COUNTER.key" -out "$ORG-client$COUNTER.csr" -subj "/CN=$ORG-client$COUNTER" -config ${PKI_CNF} 2> /dev/null - openssl ca -batch -keyfile "ca.key" -cert "ca.crt" -in "$ORG-client$COUNTER.csr" -out "$ORG-client$COUNTER.crt" -config ${PKI_CNF} -extensions my-client 2> /dev/null - let COUNTER=COUNTER-1 - done - - chmod 0600 "ca.key" - chmod 0600 "$ORG-server.key" - COUNTER=$NCLIENT - while [ $COUNTER -gt 0 ]; do - chmod 0600 "$ORG-client$COUNTER.key" - cp "$ORG-client$COUNTER.crt" ${PKI_DIR}/client - cp "$ORG-client$COUNTER.key" ${PKI_DIR}/client - let COUNTER=COUNTER-1 - done - - cp "ca.crt" ${PKI_DIR}/client - cp "ca.crt" ${PKI_DIR}/server - cp "$ORG-server.key" ${PKI_DIR}/server - cp "$ORG-server.crt" ${PKI_DIR}/server - - echo "4" > /tmp/easyrsa -### Step 4: Create the Diffie-Hellman parameters - openssl dhparam -out dh2048.pem 2048 2> /dev/null - cp "dh2048.pem" ${PKI_DIR}/server - - echo "5" > /tmp/easyrsa - - - tar -czf ${PKI_DIR}/package/certificates.tar.gz ./client ./server - sleep 7 - echo "6" > /tmp/easyrsa \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh deleted file mode 100644 index e9088c9..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/stop.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -result=`ps | grep -i "generate.sh" | grep -v "grep" | wc -l` -if [ $result -ge 1 ]; then - rkillall generate.sh - rm -f /tmp/easyrsa - PKI_DIR="/etc/openvpn/ssl" - if [ -d "$PKI_DIR" ]; then - rm -rfv "$PKI_DIR" - fi -fi \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh deleted file mode 100644 index e99b9b9..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpn.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -log() { - logger -t "OpenVpn Vpn" "$@" -} - -/etc/init.d/openvpn stop $1 -sleep 5 - diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh deleted file mode 100644 index 8b34078..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/easyrsa/vpng.sh +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -convert() { - secs=$1 - csec=$(printf "%02d:%02d:%02d" $(($secs/3600)) $(($secs%3600/60)) $(($secs%60))) -} - -clist() { - SDIR="/tmp/run" - - STAT=$SDIR"/openvpn."$1".status" - - COUNT=0 - RT=0 - TT="Virtual Address Common Name Real Address" - while read -r line; do - name="$line" - RTT=$(echo "$name" | grep "Virtual Address") - if [ ! -z "$RTT" ]; then - RT=1 - fi - RTT=$(echo "$name" | grep "GLOBAL STATS") - if [ ! -z "$RTT" ]; then - RT=0 - fi - if [ $RT = 1 ]; then - if [ $COUNT -gt 0 ]; then - vip=$(echo "$name" | cut -d, -f1) - com=$(echo "$name" | cut -d, -f2) - rel=$(echo "$name" | cut -d, -f3) - TT="$TT $vip $com $rel" - fi - let COUNT=COUNT+1 - fi - done < "$STAT" - if [ $COUNT -le 1 ]; then - TT="No clients" - COUNT=0 - else - let COUNT=COUNT-1 - fi -} - -rm -f /tmp/vpn - -vpn_instance() { - local s="$1" - echo "$s " >> /tmp/vpn - config_get config "$s" config - if [ -z $config ]; then - config_get_bool client "$s" client 0 - else - client=1 - fi - echo "$client" >> /tmp/vpn - config_get_bool enabled "$s" 'enabled' 0 - echo "$enabled" >> /tmp/vpn - - result=`ps | grep -i "/usr/sbin/openvpn --syslog openvpn($s)" | grep -v "grep" | wc -l` - if [ $result -ge 1 ] - then - echo "1" >> /tmp/vpn - else - echo "0" >> /tmp/vpn - fi - - if [ -z $config ]; then - config_get port "$s" port - if [ -z $port ]; then - echo "1194" >> /tmp/vpn - else - echo "$port" >> /tmp/vpn - fi - config_get proto "$s" proto - if [ -z $proto ]; then - echo "udp" >> /tmp/vpn - else - echo "$proto" >> /tmp/vpn - fi - else - prott=$(cat "$config" | grep -i "proto " | tr " " ",") - prot=$(echo "$prott" | cut -d, -f2) - remtt=$(cat "$config" | grep -i -m 1 "remote " | tr " " ",") - remt=$(echo "$remtt" | cut -d, -f3) - echo "$remt" >> /tmp/vpn - echo "$prot" >> /tmp/vpn - fi - if [ $client = "0" ]; then - echo "---" >> /tmp/vpn - if [ $result -ge 1 ]; then - clist $s - echo "$COUNT" >> /tmp/vpn - echo "$TT" >> /tmp/vpn - else - echo "0" >> /tmp/vpn - echo "Not running" >> /tmp/vpn - fi - else - if [ -z $config ]; then - config_get remote "$s" remote - echo "$remote" >> /tmp/vpn - else - remtt=$(cat "$config" | grep -i -m 1 "remote " | tr " " ",") - remt=$(echo "$remtt" | cut -d, -f2) - echo "$remt" >> /tmp/vpn - fi - echo "---" >> /tmp/vpn - echo "not server" >> /tmp/vpn - fi - if [ $result -ge 1 ] - then - config_get laststart "$s" laststart - CURRTIME=$(date +%s) - let upt=CURRTIME-laststart - convert $upt - upt=$csec - else - upt="---" - fi - echo "$upt" >> /tmp/vpn -} - -config_load 'openvpn' -config_foreach vpn_instance 'openvpn' - -exit 0 - diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua deleted file mode 100644 index 80dbf89..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/controller/openvpn.lua +++ /dev/null @@ -1,135 +0,0 @@ --- Copyright 2008 Steven Barth --- Copyright 2008 Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.openvpn", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - entry({"admin", "vpn"}, firstchild(), translate("VPN"), 30).dependent=false - entry( {"admin", "vpn", "openvpn"}, cbi("openvpn"), _(translate("OpenVPN")), 1 ) - entry( {"admin", "vpn", "openvpn-server"}, cbi("openvpn-server"), _(translate("--OpenVPN Extras")), 2 ) - - entry( {"admin", "vpn", "openvpn", "basic"}, cbi("openvpn-basic"), nil ).leaf = true - entry( {"admin", "vpn", "openvpn", "advanced"}, cbi("openvpn-advanced"), nil ).leaf = true - entry( {"admin", "vpn", "openvpn", "file"}, form("openvpn-file"), nil ).leaf = true - entry( {"admin", "vpn", "openvpn", "upload"}, call("ovpn_upload")) - end - - entry({"admin", "vpn", "vpnstatus"}, call("action_vpnstatus")) - entry({"admin", "vpn", "rsastatus"}, call("action_status")) - entry({"admin", "vpn", "rsagenerate"}, call("action_generate")) - entry({"admin", "vpn", "rsastop"}, call("action_stop")) -end - -function ovpn_upload() - local fs = require("nixio.fs") - local http = require("luci.http") - local util = require("luci.util") - local uci = require("luci.model.uci").cursor() - local upload = http.formvalue("ovpn_file") - local name = http.formvalue("instance_name2") - local file = "/etc/openvpn/" ..name.. ".ovpn" - - if name and upload then - local fp - - http.setfilehandler( - function(meta, chunk, eof) - local data = util.trim(chunk:gsub("\r\n", "\n")) .. "\n" - data = util.trim(data:gsub("[\128-\255]", "")) - - if not fp and meta and meta.name == "ovpn_file" then - fp = io.open(file, "w") - end - if fp and data then - fp:write(data) - end - if fp and eof then - fp:close() - end - end - ) - - if fs.access(file) then - if not uci:get_first("openvpn", name) then - uci:set("openvpn", name, "openvpn") - uci:set("openvpn", name, "config", file) - uci:save("openvpn") - uci:commit("openvpn") - end - end - end - http.redirect(luci.dispatcher.build_url('admin/vpn/openvpn')) -end - -function action_status() - local rv = {} - - file = io.open("/tmp/easyrsa", "r") - if file ~= nil then - rv["status"] = file:read("*line") - file:close() - else - rv["status"] = "0" - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_generate() - os.execute("/usr/lib/easyrsa/generate.sh &") -end - -function action_stop() - os.execute("/usr/lib/easyrsa/stop.sh") -end - -function action_vpnstatus() - local rv ={} - - os.execute("/usr/lib/easyrsa/vpng.sh") - local file = io.open("/tmp/vpn", "r") - if file ~= nil then - i = 0 - name = file:read("*line") - while name ~= nil do - vpntype = file:read("*line") - enabled = file:read("*line") - started = file:read("*line") - port = file:read("*line") - proto = file:read("*line") - remote = file:read("*line") - clients = file:read("*line") - tooltip = file:read("*line") - laststart = file:read("*line") - rv[#rv+1] = { - name = name, - vpntype = vpntype, - enabled = enabled, - started = started, - port = port, - proto = proto, - remote = remote, - clients = clients, - tooltip = tooltip, - laststart = laststart - } - name = file:read("*line") - end - file:close() - else - rv[#rv+1] = { - enabled = "-1", - } - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua deleted file mode 100644 index a79288d..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-advanced.lua +++ /dev/null @@ -1,902 +0,0 @@ --- Copyright 2008 Steven Barth --- Licensed to the public under the Apache License 2.0. - -local fs = require("nixio.fs") - -local knownParams = { - -- - --Widget - -- Name - -- Default(s) - -- Description - -- Option(s) - - { "Service", { - -- initialisation and daemon options - { ListValue, - "verb", - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, - translate("Set output verbosity") }, - { Flag, - "mlock", - 0, - translate("Disable Paging") }, - { Flag, - "disable_occ", - 0, - translate("Disable options consistency check") }, - -- { Value, - -- "user", - -- "root", - -- translate("Set UID to user") }, - -- { Value, - -- "group", - -- "root", - -- translate("Set GID to group") }, - { Value, - "cd", - "/etc/openvpn", - translate("Change to directory before initialization") }, - { Value, - "chroot", - "/var/run", - translate("Chroot to directory after initialization") }, - -- { Value, - -- "daemon", - -- "Instance-Name", - -- translate("Daemonize after initialization") }, - -- { Value, - -- "syslog", - -- "Instance-Name", - -- translate("Output to syslog and do not daemonize") }, - { Flag, - "passtos", - 0, - translate("TOS passthrough (applies to IPv4 only)") }, - -- { Value, - -- "inetd", - -- "nowait Instance-Name", - -- translate("Run as an inetd or xinetd server") }, - { Value, - "log", - "/var/log/openvpn.log", - translate("Write log to file") }, - { Value, - "log_append", - "/var/log/openvpn.log", - translate("Append log to file") }, - { Flag, - "suppress_timestamps", - 0, - translate("Don't log timestamps") }, - -- { Value, - -- "writepid", - -- "/var/run/openvpn.pid", - -- translate("Write process ID to file") }, - { Value, - "nice", - 0, - translate("Change process priority") }, - { Flag, - "fast_io", - 0, - translate("Optimize TUN/TAP/UDP writes") }, - { Value, - "echo", - "some params echoed to log", - translate("Echo parameters to log") }, - { ListValue, - "remap_usr1", - { "SIGHUP", "SIGTERM" }, - translate("Remap SIGUSR1 signals") }, - { Value, - "status", - "/var/run/openvpn.status 5", - translate("Write status to file every n seconds") }, - { Value, - "status_version", - { 1, 2 }, - translate("Status file format version") }, -- status - { Value, - "mute", - 5, - translate("Limit repeated log messages") }, - { Value, - "up", - "/usr/bin/ovpn-up", - translate("Shell cmd to execute after tun device open") }, - { Value, - "up_delay", - 5, - translate("Delay tun/tap open and up script execution") }, - { Value, - "down", - "/usr/bin/ovpn-down", - translate("Shell cmd to run after tun device close") }, - { Flag, - "down_pre", - 0, - translate("Call down cmd/script before TUN/TAP close") }, - { Flag, - "up_restart", - 0, - translate("Run up/down scripts for all restarts") }, - { Value, - "route_up", - "/usr/bin/ovpn-routeup", - translate("Execute shell cmd after routes are added") }, - { Value, - "ipchange", - "/usr/bin/ovpn-ipchange", - translate("Execute shell command on remote ip change"), - { mode="p2p" } }, - { DynamicList, - "setenv", - { "VAR1 value1", "VAR2 value2" }, - translate("Pass environment variables to script") }, - { Value, - "tls_verify", - "/usr/bin/ovpn-tlsverify", - translate("Shell command to verify X509 name") }, - { Value, - "client_connect", - "/usr/bin/ovpn-clientconnect", - translate("Run script cmd on client connection") }, - { Value, - "client_disconnect", - "/usr/bin/ovpn-clientdisconnect", - translate("Run script cmd on client disconnection") }, - { Value, - "learn_address", - "/usr/bin/ovpn-learnaddress", - translate("Executed in server mode whenever an IPv4 address/route or MAC address is added to OpenVPN's internal routing table") }, - { Value, - "auth_user_pass_verify", - "/usr/bin/ovpn-userpass via-env", - translate("Executed in server mode on new client connections, when the client is still untrusted") }, - { ListValue, - "script_security", - { 0, 1, 2, 3 }, - translate("Policy level over usage of external programs and scripts") }, - { ListValue, - "compress", - { "lzo", "lz4" }, - translate("Enable a compression algorithm") }, - } }, - - { "Networking", { - -- socket config - { ListValue, - "mode", - { "p2p", "server" }, - translate("Major mode") }, - { Value, - "local", - "0.0.0.0", - translate("Local host name or ip address") }, - { Value, - "port", - 1194, - translate("TCP/UDP port # for both local and remote") }, - { Value, - "lport", - 1194, - translate("TCP/UDP port # for local (default=1194)") }, - { Value, - "rport", - 1194, - translate("TCP/UDP port # for remote (default=1194)") }, - { Flag, - "float", - 0, - translate("Allow remote to change its IP or port") }, - { Flag, - "nobind", - 0, - translate("Do not bind to local address and port") }, - { Value, - "dev", - "tun0", - translate("tun/tap device") }, - { ListValue, - "dev_type", - { "tun", "tap" }, - translate("Type of used device") }, - { Value, - "dev_node", - "/dev/net/tun", - translate("Use tun/tap device node") }, - { Value, - "ifconfig", - "10.200.200.3 10.200.200.1", - translate("Set tun/tap adapter parameters") }, - { Flag, - "ifconfig_noexec", - 0, - translate("Don't actually execute ifconfig") }, - { Flag, - "ifconfig_nowarn", - 0, - translate("Don't warn on ifconfig inconsistencies") }, - { DynamicList, - "route", - "10.123.0.0 255.255.0.0", - translate("Add route after establishing connection") }, - { Value, - "route_gateway", - "10.234.1.1", - translate("Specify a default gateway for routes") }, - { Value, - "route_delay", - 0, - translate("Delay n seconds after connection") }, - { Flag, - "route_noexec", - 0, - translate("Don't add routes automatically") }, - { Flag, - "route_nopull", - 0, - translate("Don't pull routes automatically") }, - { Flag, - "allow_recursive_routing", - 0, - translate("Don't drop incoming tun packets with same destination as host") }, - { ListValue, - "mtu_disc", - { "yes", "maybe", "no" }, - translate("Enable Path MTU discovery") }, - { Flag, - "mtu_test", - 0, - translate("Empirically measure MTU") }, - { ListValue, - "comp_lzo", - { "yes", "no", "adaptive" }, - translate("Use fast LZO compression") }, - { Flag, - "comp_noadapt", - 0, - translate("Don't use adaptive lzo compression"), - { comp_lzo=1 } }, - { Value, - "link_mtu", - 1500, - translate("Set TCP/UDP MTU") }, - { Value, - "tun_mtu", - 1500, - translate("Set tun/tap device MTU") }, - { Value, - "tun_mtu_extra", - 1500, - translate("Set tun/tap device overhead") }, - { Value, - "fragment", - 1500, - translate("Enable internal datagram fragmentation"), - { proto="udp" } }, - { Value, - "mssfix", - 1500, - translate("Set upper bound on TCP MSS"), - { proto="udp" } }, - { Value, - "sndbuf", - 65536, - translate("Set the TCP/UDP send buffer size") }, - { Value, - "rcvbuf", - 65536, - translate("Set the TCP/UDP receive buffer size") }, - { Value, - "txqueuelen", - 100, - translate("Set tun/tap TX queue length") }, - { Value, - "shaper", - 10240, - translate("Shaping for peer bandwidth") }, - { Value, - "inactive", - 240, - translate("tun/tap inactivity timeout") }, - { Value, - "keepalive", - "10 60", - translate("Helper directive to simplify the expression of --ping and --ping-restart in server mode configurations") }, - { Value, - "ping", - 30, - translate("Ping remote every n seconds over TCP/UDP port") }, - { Value, - "ping_exit", - 120, - translate("Remote ping timeout") }, - { Value, - "ping_restart", - 60, - translate("Restart after remote ping timeout") }, - { Flag, - "ping_timer_rem", - 0, - translate("Only process ping timeouts if routes exist") }, - { Flag, - "persist_tun", - 0, - translate("Keep tun/tap device open on restart") }, - { Flag, - "persist_key", - 0, - translate("Don't re-read key on restart") }, - { Flag, - "persist_local_ip", - 0, - translate("Keep local IP address on restart") }, - { Flag, - "persist_remote_ip", - 0, - translate("Keep remote IP address on restart") }, - -- management channel - { Value, - "management", - "127.0.0.1 31194 /etc/openvpn/mngmt-pwds", - translate("Enable management interface on IP port") }, - -- management - { Flag, - "management_query_passwords", - 0, - translate("Query management channel for private key") }, - -- management - { Flag, - "management_hold", - 0, - translate("Start OpenVPN in a hibernating state") }, - -- management - { Value, - "management_log_cache", - 100, - translate("Number of lines for log file history") }, - { ListValue, - "topology", - { "net30", "p2p", "subnet" }, - translate("'net30', 'p2p', or 'subnet'"), - {dev_type="tun" } }, - } }, - - { "VPN", { - { Value, - "server", - "10.200.200.0 255.255.255.0", - translate("Configure server mode"), - { client="0" }, { client="" } }, - { Value, - "server_bridge", - "10.200.200.1 255.255.255.0 10.200.200.200 10.200.200.250", - translate("Configure server bridge"), - { client="0" }, { client="" } }, - { DynamicList, - "push", - { "redirect-gateway", "comp-lzo" }, - translate("Push options to peer"), - { client="0" }, { client="" } }, - { Flag, - "push_reset", - 0, - translate("Don't inherit global push options"), - { client="0" }, { client="" } }, - { Flag, - "disable", - 0, - translate("Client is disabled"), - { client="0" }, { client="" } }, - { Value, - "ifconfig_pool", - "10.200.200.100 10.200.200.150 255.255.255.0", - translate("Set aside a pool of subnets"), - { client="0" }, { client="" } }, - { Value, - "ifconfig_pool_persist", - "/etc/openvpn/ipp.txt 600", - translate("Persist/unpersist ifconfig-pool"), - { client="0" }, { client="" } }, - { Value, - "ifconfig_push", - "10.200.200.1 255.255.255.255", - translate("Push an ifconfig option to remote"), - { client="0" }, { client="" } }, - { Value, - "iroute", - "10.200.200.0 255.255.255.0", - translate("Route subnet to client"), - { client="0" }, { client="" } }, - { Flag, - "client_to_client", - 0, - translate("Allow client-to-client traffic"), - { client="0" }, { client="" } }, - { Flag, - "duplicate_cn", - 0, - translate("Allow multiple clients with same certificate"), - { client="0" }, { client="" } }, - { Value, - "client_config_dir", - "/etc/openvpn/ccd", - translate("Directory for custom client config files"), - { client="0" }, { client="" } }, - { Flag, - "ccd_exclusive", - 0, - translate("Refuse connection if no custom client config"), - { client="0" }, { client="" } }, - { Value, - "tmp_dir", - "/var/run/openvpn", - translate("Temporary directory for client-connect return file"), - { client="0" }, { client="" } }, - { Value, - "hash_size", - "256 256", - translate("Set size of real and virtual address hash tables"), - { client="0" }, { client="" } }, - { Value, - "bcast_buffers", - 256, - translate("Number of allocated broadcast buffers"), - { client="0" }, { client="" } }, - { Value, - "tcp_queue_limit", - 64, - translate("Maximum number of queued TCP output packets"), - { client="0" }, { client="" } }, - { Value, - "max_clients", - 10, - translate("Allowed maximum of connected clients"), - { client="0" }, { client="" } }, - { Value, - "max_routes_per_client", - 256, - translate("Allowed maximum of internal"), - { client="0" }, { client="" } }, - { Value, - "connect_freq", - "3 10", - translate("Allowed maximum of new connections"), - { client="0" }, { client="" } }, - { Flag, - "username_as_common_name", - 0, - translate("Use username as common name"), - { client="0" }, { client="" } }, - { Flag, - "client", - 0, - translate("Configure client mode") }, - { Flag, - "pull", - 0, - translate("Accept options pushed from server"), - { client="1" } }, - { FileUpload, - "auth_user_pass", - "/etc/openvpn/userpass.txt", - translate("Authenticate using username/password"), - { client="1" } }, - { ListValue, - "auth_retry", - { "none", "nointeract", "interact" }, - translate("Handling of authentication failures"), - { client="1" } }, - { Value, - "explicit_exit_notify", - 1, - translate("Send notification to peer on disconnect"), - { client="1" } }, - { DynamicList, - "remote", - "1.2.3.4", - translate("Remote host name or ip address") }, - { Flag, - "remote_random", - 0, - translate("Randomly choose remote server"), - { client="1" } }, - { ListValue, - "proto", - { "udp", "tcp-client", "tcp-server" }, - translate("Use protocol"), - { client="1" } }, - { Value, - "connect_retry", - 5, - translate("Connection retry interval"), - { proto="tcp-client" }, { client="1" } }, - { Value, - "http_proxy", - "192.168.1.100 8080", - translate("Connect to remote host through an HTTP proxy"), - { client="1" } }, - { Flag, - "http_proxy_retry", - 0, - translate("Retry indefinitely on HTTP proxy errors"), - { client="1" } }, - { Value, - "http_proxy_timeout", - 5, - translate("Proxy timeout in seconds"), - { client="1" } }, - { DynamicList, - "http_proxy_option", - { "VERSION 1.0", "AGENT OpenVPN/2.0.9" }, - translate("Set extended HTTP proxy options"), - { client="1" } }, - { Value, - "socks_proxy", - "192.168.1.200 1080", - translate("Connect through Socks5 proxy"), - { client="1" } }, - -- client && socks_proxy - { Value, - "socks_proxy_retry", - 5, - translate("Retry indefinitely on Socks proxy errors"), - { client="1" } }, - { Value, - "resolv_retry", - "infinite", - translate("If hostname resolve fails, retry"), - { client="1" } }, - { ListValue, - "redirect_gateway", - { "", "local", "def1", "local def1" }, - translate("Automatically redirect default route"), - { client="1" } }, - { Value, - "verify_client_cert", - { "none", "optional", "require" }, - translate("Specify whether the client is required to supply a valid certificate") }, - } }, - - { "Cryptography", { - { FileUpload, - "secret", - "/etc/openvpn/secret.key", - translate("Enable Static Key encryption mode (non-TLS)") }, - -- parse - { Value, - "auth", - "SHA1", - translate("HMAC authentication for packets") }, - -- parse - { Value, - "cipher", - { - "AES-128-CBC", - "AES-128-CFB", - "AES-128-CFB1", - "AES-128-CFB8", - "AES-128-GCM", - "AES-128-OFB", - "AES-192-CBC", - "AES-192-CFB", - "AES-192-CFB1", - "AES-192-CFB8", - "AES-192-GCM", - "AES-192-OFB", - "AES-256-CBC", - "AES-256-CFB", - "AES-256-CFB1", - "AES-256-CFB8", - "AES-256-GCM", - "AES-256-OFB", - "BF-CBC", - "BF-CFB", - "BF-OFB", - "CAST5-CBC", - "CAST5-CFB", - "CAST5-OFB", - "DES-CBC", - "DES-CFB", - "DES-CFB1", - "DES-CFB8", - "DES-EDE-CBC", - "DES-EDE-CFB", - "DES-EDE-OFB", - "DES-EDE3-CBC", - "DES-EDE3-CFB", - "DES-EDE3-CFB1", - "DES-EDE3-CFB8", - "DES-EDE3-OFB", - "DES-OFB", - "DESX-CBC", - "RC2-40-CBC", - "RC2-64-CBC", - "RC2-CBC", - "RC2-CFB", - "RC2-OFB" - }, - translate("Encryption cipher for packets") }, - -- parse - { Value, - "keysize", - 1024, - translate("Size of cipher key") }, - -- parse - { Value, - "engine", - "dynamic", - translate("Enable OpenSSL hardware crypto engines") }, - { Value, - "replay_window", - "64 15", - translate("Replay protection sliding window size") }, - { Flag, - "mute_replay_warnings", - 0, - translate("Silence the output of replay warnings") }, - { Value, - "replay_persist", - "/var/run/openvpn-replay-state", - translate("Persist replay-protection state") }, - { Flag, - "tls_server", - 0, - translate("Enable TLS and assume server role"), - { tls_client="" }, { tls_client="0" } }, - { Flag, - "tls_client", - 0, - translate("Enable TLS and assume client role"), - { tls_server="" }, { tls_server="0" } }, - { FileUpload, - "ca", - "/etc/easy-rsa/keys/ca.crt", - translate("Certificate authority") }, - { FileUpload, - "dh", - "/etc/easy-rsa/keys/dh1024.pem", - translate("Diffie Hellman parameters") }, - { FileUpload, - "cert", - "/etc/easy-rsa/keys/some-client.crt", - translate("Local certificate") }, - { FileUpload, - "key", - "/etc/easy-rsa/keys/some-client.key", - translate("Local private key") }, - { FileUpload, - "pkcs12", - "/etc/easy-rsa/keys/some-client.pk12", - translate("PKCS#12 file containing keys") }, - { ListValue, - "key_method", - { 1, 2 }, - translate("Enable TLS and assume client role") }, - { DynamicList, - "tls_cipher", - { - "DHE-RSA-AES256-SHA", - "DHE-DSS-AES256-SHA", - "AES256-SHA", - "EDH-RSA-DES-CBC3-SHA", - "EDH-DSS-DES-CBC3-SHA", - "DES-CBC3-SHA", - "DHE-RSA-AES128-SHA", - "DHE-DSS-AES128-SHA", - "AES128-SHA", - "RC4-SHA", - "RC4-MD5", - "EDH-RSA-DES-CBC-SHA", - "EDH-DSS-DES-CBC-SHA", - "DES-CBC-SHA", - "EXP-EDH-RSA-DES-CBC-SHA", - "EXP-EDH-DSS-DES-CBC-SHA", - "EXP-DES-CBC-SHA", - "EXP-RC2-CBC-MD5", - "EXP-RC4-MD5" - }, - translate("TLS cipher") }, - { DynamicList, - "tls_ciphersuites", - { - "TLS_AES_256_GCM_SHA384", - "TLS_AES_128_GCM_SHA256", - "TLS_CHACHA20_POLY1305_SHA256" - }, - translate("TLS 1.3 or newer cipher") }, - { Value, - "tls_timeout", - 2, - translate("Retransmit timeout on TLS control channel") }, - { Value, - "reneg_bytes", - 1024, - translate("Renegotiate data chan. key after bytes") }, - { Value, - "reneg_pkts", - 100, - translate("Renegotiate data chan. key after packets") }, - { Value, - "reneg_sec", - 3600, - translate("Renegotiate data chan. key after seconds") }, - { Value, - "hand_window", - 60, - translate("Timeframe for key exchange") }, - { Value, - "tran_window", - 3600, - translate("Key transition window") }, - { Flag, - "single_session", - 0, - translate("Allow only one session") }, - { Flag, - "tls_exit", - 0, - translate("Exit on TLS negotiation failure") }, - { Value, - "tls_auth", - "/etc/openvpn/tlsauth.key", - translate("Additional authentication over TLS") }, - { Value, - "tls_crypt", - "/etc/openvpn/tlscrypt.key", - translate("Encrypt and authenticate all control channel packets with the key") }, - -- { Value, - -- "askpass", - -- "[file]", - -- translate("Get PEM password from controlling tty before we daemonize") }, - { Flag, - "auth_nocache", - 0, - translate("Don't cache --askpass or --auth-user-pass passwords") }, - { Value, - "tls_remote", - "remote_x509_name", - translate("Only accept connections from given X509 name") }, - { ListValue, - "ns_cert_type", - { "client", "server" }, - translate("Require explicit designation on certificate") }, - { ListValue, - "remote_cert_tls", - { "client", "server" }, - translate("Require explicit key usage on certificate") }, - { Value, - "crl_verify", - "/etc/easy-rsa/keys/crl.pem", - translate("Check peer certificate against a CRL") }, - { Value, - "tls_version_min", - "1.0", - translate("The lowest supported TLS version") }, - { Value, - "tls_version_max", - "1.2", - translate("The highest supported TLS version") }, - { ListValue, - "key_direction", - { 0, 1 }, - translate("The key direction for 'tls-auth' and 'secret' options") }, - { Flag, - "ncp_disable", - 0, - translate("This completely disables cipher negotiation") }, - { Value, - "ncp_ciphers", - "AES-256-GCM:AES-128-GCM", - translate("Restrict the allowed ciphers to be negotiated") }, - } } -} - - -local cts = { } -local params = { } - -local m = Map("openvpn") -m.redirect = luci.dispatcher.build_url("admin", "vpn", "openvpn") -m.apply_on_parse = true - -local p = m:section( SimpleSection ) -p.template = "openvpn/pageswitch" -p.mode = "advanced" -p.instance = arg[1] -p.category = arg[2] or "Service" - -for _, c in ipairs(knownParams) do - cts[#cts+1] = c[1] - if c[1] == p.category then params = c[2] end -end - -p.categories = cts - - -local s = m:section( - NamedSection, arg[1], "openvpn", - translate("%s" % arg[2]) -) - -s.title = translate("%s" % arg[2]) -s.addremove = false -s.anonymous = true - - -for _, option in ipairs(params) do - local o = s:option( - option[1], option[2], - option[2], option[4] - ) - - o.optional = true - - if option[1] == DummyValue then - o.value = option[3] - elseif option[1] == FileUpload then - - o.initial_directory = "/etc/openvpn" - - function o.cfgvalue(self, section) - local cfg_val = AbstractValue.cfgvalue(self, section) - - if cfg_val then - return cfg_val - end - end - - function o.formvalue(self, section) - local sel_val = AbstractValue.formvalue(self, section) - local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") - - if sel_val and sel_val ~= "" then - return sel_val - end - - if txt_val and txt_val ~= "" then - return txt_val - end - end - - function o.remove(self, section) - local cfg_val = AbstractValue.cfgvalue(self, section) - local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") - - if cfg_val and fs.access(cfg_val) and txt_val == "" then - fs.unlink(cfg_val) - end - return AbstractValue.remove(self, section) - end - elseif option[1] == Flag then - o.default = nil - else - if option[1] == DynamicList then - function o.cfgvalue(...) - local val = AbstractValue.cfgvalue(...) - return ( val and type(val) ~= "table" ) and { val } or val - end - end - - if type(option[3]) == "table" then - if o.optional then o:value("", "-- remove --") end - for _, v in ipairs(option[3]) do - v = tostring(v) - o:value(v) - end - o.default = tostring(option[3][1]) - else - o.default = tostring(option[3]) - end - end - - for i=5,#option do - if type(option[i]) == "table" then - o:depends(option[i]) - end - end -end - -return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua deleted file mode 100644 index dbab780..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-basic.lua +++ /dev/null @@ -1,196 +0,0 @@ --- Copyright 2008 Steven Barth --- Licensed to the public under the Apache License 2.0. - -local fs = require("nixio.fs") - -local basicParams = { - -- - -- Widget, Name, Default(s), Description - -- - { ListValue, - "verb", - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, - translate("Set output verbosity") }, - { Value, - "nice", - 0, - translate("Change process priority") }, - { Value, - "port", - 1194, - translate("TCP/UDP port # for both local and remote") }, - { ListValue, - "dev_type", - { "tun", "tap" }, - translate("Type of used device") }, - { Value, - "ifconfig", - "10.200.200.3 10.200.200.1", - translate("Set tun/tap adapter parameters") }, - { Value, - "server", - "10.200.200.0 255.255.255.0", - translate("Configure server mode") }, - { Value, - "server_bridge", - "192.168.1.1 255.255.255.0 192.168.1.128 192.168.1.254", - translate("Configure server bridge") }, - { Flag, - "nobind", - 0, - translate("Do not bind to local address and port") }, - { ListValue, - "comp_lzo", - {"yes","no","adaptive"}, - translate("Use fast LZO compression") }, - { Value, - "keepalive", - "10 60", - translate("Helper directive to simplify the expression of --ping and --ping-restart in server mode configurations") }, - { Flag, - "client", - 0, - translate("Configure client mode") }, - { Flag, - "client_to_client", - 0, - translate("Allow client-to-client traffic") }, - { DynamicList, - "remote", - "vpnserver.example.org", - translate("Remote host name or ip address") }, - { FileUpload, - "secret", - "/etc/openvpn/secret.key", - translate("Enable Static Key encryption mode (non-TLS)") }, - { ListValue, - "key_direction", - { 0, 1 }, - translate("The key direction for 'tls-auth' and 'secret' options") }, - { FileUpload, - "pkcs12", - "/etc/easy-rsa/keys/some-client.pk12", - translate("PKCS#12 file containing keys") }, - { FileUpload, - "ca", - "/etc/easy-rsa/keys/ca.crt", - translate("Certificate authority") }, - { FileUpload, - "dh", - "/etc/easy-rsa/keys/dh1024.pem", - translate("Diffie Hellman parameters") }, - { FileUpload, - "cert", - "/etc/easy-rsa/keys/some-client.crt", - translate("Local certificate") }, - { FileUpload, - "key", - "/etc/easy-rsa/keys/some-client.key", - translate("Local private key") }, - { FileUpload, - "auth_user_pass", - "/etc/easy-rsa/keys/some-client.pass", - translate("Password file") }, -} - -local has_ipv6 = fs.access("/proc/net/ipv6_route") -if has_ipv6 then - table.insert( basicParams, { ListValue, - "proto", - { "udp", "tcp-client", "tcp-server", "udp4", "tcp4-client", "tcp4-server","udp6", "tcp6-client", "tcp6-server" }, - translate("Use protocol") - }) -else - table.insert( basicParams, { ListValue, - "proto", - { "udp", "tcp-client", "tcp-server" }, - translate("Use protocol") - }) -end - -local m = Map("openvpn") -m.redirect = luci.dispatcher.build_url("admin", "vpn", "openvpn") -m.apply_on_parse = true - -local p = m:section( SimpleSection ) -p.template = "openvpn/pageswitch" -p.mode = "basic" -p.instance = arg[1] - - -local s = m:section( NamedSection, arg[1], "openvpn" ) - -for _, option in ipairs(basicParams) do - local o = s:option( - option[1], option[2], - option[2], option[4] - ) - - o.optional = true - - if option[1] == DummyValue then - o.value = option[3] - elseif option[1] == FileUpload then - - o.initial_directory = "/etc/openvpn" - - function o.cfgvalue(self, section) - local cfg_val = AbstractValue.cfgvalue(self, section) - - if cfg_val then - return cfg_val - end - end - - function o.formvalue(self, section) - local sel_val = AbstractValue.formvalue(self, section) - local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") - - if sel_val and sel_val ~= "" then - return sel_val - end - - if txt_val and txt_val ~= "" then - return txt_val - end - end - - function o.remove(self, section) - local cfg_val = AbstractValue.cfgvalue(self, section) - local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox") - - if cfg_val and fs.access(cfg_val) and txt_val == "" then - fs.unlink(cfg_val) - end - return AbstractValue.remove(self, section) - end - elseif option[1] == Flag then - o.default = nil - else - if option[1] == DynamicList then - function o.cfgvalue(...) - local val = AbstractValue.cfgvalue(...) - return ( val and type(val) ~= "table" ) and { val } or val - end - end - - if type(option[3]) == "table" then - if o.optional then o:value("", "-- remove --") end - for _, v in ipairs(option[3]) do - v = tostring(v) - o:value(v) - end - o.default = tostring(option[3][1]) - else - o.default = tostring(option[3]) - end - end - - for i=5,#option do - if type(option[i]) == "table" then - o:depends(option[i]) - end - end -end - -return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua deleted file mode 100644 index 9d50601..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-file.lua +++ /dev/null @@ -1,82 +0,0 @@ --- Licensed to the public under the Apache License 2.0. - -local ip = require("luci.ip") -local fs = require("nixio.fs") -local util = require("luci.util") -local uci = require("luci.model.uci").cursor() -local cfg_file = uci:get("openvpn", arg[1], "config") -local auth_file = cfg_file:match("(.+)%..+").. ".auth" - -local m = Map("openvpn") - -local p = m:section( SimpleSection ) -p.template = "openvpn/pageswitch" -p.mode = "file" -p.instance = arg[1] - -if not cfg_file or not fs.access(cfg_file) then - local f = SimpleForm("error", nil, translatef("The OVPN config file (%s) could not be found, please check your configuration.", cfg_file or "n/a")) - f:append(Template("openvpn/ovpn_css")) - f.reset = false - f.submit = false - return m, f -end - -if fs.stat(cfg_file).size >= 102400 then - f = SimpleForm("error", nil, - translatef("The size of the OVPN config file (%s) is too large for online editing in LuCI (≥ 100 KB). ", cfg_file) - .. translate("Please edit this file directly in a terminal session.")) - f:append(Template("openvpn/ovpn_css")) - f.reset = false - f.submit = false - return m, f -end - -f = SimpleForm("cfg", nil) -f:append(Template("openvpn/ovpn_css")) -f.submit = translate("Save") -f.reset = false - -s = f:section(SimpleSection, nil, translatef("Section to modify the OVPN config file (%s)", cfg_file)) -file = s:option(TextValue, "data1") -file.datatype = "string" -file.rows = 20 - -function file.cfgvalue() - return fs.readfile(cfg_file) or "" -end - -function file.write(self, section, data1) - return fs.writefile(cfg_file, "\n" .. util.trim(data1:gsub("\r\n", "\n")) .. "\n") -end - -function file.remove(self, section, value) - return fs.writefile(cfg_file, "") -end - -function s.handle(self, state, data1) - return true -end - -s = f:section(SimpleSection, nil, translatef("Section to add an optional 'auth-user-pass' file with your credentials (%s)", auth_file)) -file = s:option(TextValue, "data2") -file.datatype = "string" -file.rows = 5 - -function file.cfgvalue() - return fs.readfile(auth_file) or "" -end - -function file.write(self, section, data2) - return fs.writefile(auth_file, util.trim(data2:gsub("\r\n", "\n")) .. "\n") -end - -function file.remove(self, section, value) - return fs.writefile(auth_file, "") -end - -function s.handle(self, state, data2) - return true -end - -return m, f diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua deleted file mode 100644 index 88c8888..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn-server.lua +++ /dev/null @@ -1,86 +0,0 @@ --- Copyright 2008 Steven Barth --- Licensed to the public under the Apache License 2.0. - -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() - -local m = Map("openvpn", translate("OpenVPN Extras"), translate("Extra Settings for an OpenVPN Client or Server")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/easyrsa/firewall.sh &") - luci.sys.call("/usr/lib/easyrsa/dns.sh &") -end - -gw = m:section(TypedSection, "settings", translate("Advanced Extras")) -gw.anonymous = true -gw:tab("default", translate("Custom Firewall Settings")) -gw:tab("dns", translate("Custom DNS Settings")) -gw:tab("key", translate("Key and Certificate Generation")) - -this_tab = "default" - -gw:taboption(this_tab, Flag, "vpn2lan", translate("Forward Client VPN to LAN"), translate("(Client) Allow clients behind the VPN server to connect to computers within your LAN") ) -gw:taboption(this_tab, Flag, "vpns2lan", translate("Forward Server VPN to LAN"), translate("(Server) Allow clients behind the VPN server to connect to computers within your LAN") ) -gw:taboption(this_tab, Flag, "vpn2wan", translate("Forward Server VPN to WAN"), translate("(Server) Allow clients to connect to the internet (WAN) through the tunnel") ) - -this_tab = "dns" - -gw:taboption(this_tab, Flag, "lanopendns", translate("LAN DNS using OpenDNS"), translate("Fixed DNS on LAN interface using OpenDNS") ) -gw:taboption(this_tab, Flag, "langoogle", translate("LAN DNS using Google"), translate("Fixed DNS on LAN interface using Google") ) -gw:taboption(this_tab, Flag, "wanopendns", translate("WAN DNS using OpenDNS"), translate("Fixed DNS on WAN interface using OpenDNS") ) -gw:taboption(this_tab, Flag, "wangoogle", translate("WAN DNS using Google"), translate("Fixed DNS on WAN interface using Google") ) - -this_tab = "key" - -country = gw:taboption(this_tab, Value, "country", translate("Country Name :"), translate("2 letter country abbreviation")); -country.optional=false; -country.rmempty = true; -country.default="CA" -country.datatype = "rangelength(2, 2)" - -city = gw:taboption(this_tab, Value, "city", translate("City Name :")); -city.optional=false; -city.rmempty = true; -city.default="Abbotsford" -city.datatype = "minlength(2)" - -organ = gw:taboption(this_tab, Value, "organ", translate("Organization Name :"), translate("name will appear on certs and keys")); -organ.optional=false; -organ.rmempty = true; -organ.default="ROOter" -organ.datatype = "minlength(2)" - -comm = gw:taboption(this_tab, Value, "comm", translate("Common Name :"), translate("(Optional) Common Name of Organization")); -comm.optional=true; -comm.rmempty = true; - -unit = gw:taboption(this_tab, Value, "unit", translate("Section Name :"), translate("(Optional) Name of Section")); -unit.optional=true; -unit.rmempty = true; - -unstruc = gw:taboption(this_tab, Value, "unstruc", translate("Optional Organization Name :"), translate("(Optional) Another Name for Organization")); -unstruc.optional=true; -unstruc.rmempty = true; - -email = gw:taboption(this_tab, Value, "email", translate("Email Address :"), translate("(Optional) Email Address")); -unit.optional=true; -unit.rmempty = true; - -days = gw:taboption(this_tab, Value, "days", translate("Days to certify for :"), translate("number of days certs and keys are valid")); -days.optional=false; -days.rmempty = true; -days.default="3650" -days.datatype = "min(1)" - -clnt = gw:taboption(this_tab, Value, "nclient", translate("Number of Clients :"), translate("number of clients to generate certs and keys for")); -clnt.optional=false; -clnt.rmempty = true; -clnt.default="1" -clnt.datatype = "min(1)" - -sx = gw:taboption(this_tab, Value, "_dmy1", translate(" ")) -sx.template = "easyrsa/easyrsa" - - -return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua deleted file mode 100644 index b79df8b..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/model/cbi/openvpn.lua +++ /dev/null @@ -1,179 +0,0 @@ --- Copyright 2008 Steven Barth --- Licensed to the public under the Apache License 2.0. - -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() -local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have -local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid - -local m = Map("openvpn", translate("OpenVPN")) -local s = m:section( TypedSection, "openvpn", translate("OpenVPN instances"), translate("Below is a list of configured OpenVPN instances and their current state") ) -s.template = "cbi/tblsection" -s.template_addremove = "openvpn/cbi-select-input-add" -s.addremove = true -s.add_select_options = { } - -local cfg = s:option(DummyValue, "config") -function cfg.cfgvalue(self, section) - local file_cfg = self.map:get(section, "config") - if file_cfg then - s.extedit = luci.dispatcher.build_url("admin", "vpn", "openvpn", "file", "%s") - else - s.extedit = luci.dispatcher.build_url("admin", "vpn", "openvpn", "basic", "%s") - end -end - -uci:load("openvpn_recipes") -uci:foreach( "openvpn_recipes", "openvpn_recipe", - function(section) - s.add_select_options[section['.name']] = - section['_description'] or section['.name'] - end -) - -function s.getPID(section) -- Universal function which returns valid pid # or nil - local pid = sys.exec("%s | grep -w '[o]penvpn(%s)'" % { psstring, section }) - if pid and #pid > 0 then - return tonumber(pid:match("^%s*(%d+)")) - else - return nil - end -end - -function s.parse(self, section) - local recipe = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".select" - ) - - if recipe and not s.add_select_options[recipe] then - self.invalid_cts = true - else - TypedSection.parse( self, section ) - end -end - -function s.create(self, name) - local recipe = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".select" - ) - local name = luci.http.formvalue( - luci.cbi.CREATE_PREFIX .. self.config .. "." .. - self.sectiontype .. ".text" - ) - if #name > 3 and not name:match("[^a-zA-Z0-9_]") then - local s = uci:section("openvpn", "openvpn", name) - if s then - local options = uci:get_all("openvpn_recipes", recipe) - for k, v in pairs(options) do - if k ~= "_role" and k ~= "_description" then - if type(v) == "boolean" then - v = v and "1" or "0" - end - uci:set("openvpn", name, k, v) - end - end - uci:save("openvpn") - uci:commit("openvpn") - if extedit then - luci.http.redirect( self.extedit:format(name) ) - end - end - elseif #name > 0 then - self.invalid_cts = true - end - return 0 -end - -function s.remove(self, name) - local cfg_file = "/etc/openvpn/" ..name.. ".ovpn" - local auth_file = "/etc/openvpn/" ..name.. ".auth" - if fs.access(cfg_file) then - fs.unlink(cfg_file) - end - if fs.access(auth_file) then - fs.unlink(auth_file) - end - uci:delete("openvpn", name) - uci:save("openvpn") - uci:commit("openvpn") -end - -s:option( Flag, "enabled", translate("Enabled") ) -s:option( Flag, "bootstart", translate("Start on Bootup") ) - -local active = s:option( DummyValue, "_active", translate("Started") ) -function active.cfgvalue(self, section) - local pid = s.getPID(section) - if pid ~= nil then - return (sys.process.signal(pid, 0)) - and translatef("yes (%i)", pid) - or translate("no") - end - return translate("no") -end - -local updown = s:option( Button, "_updown", translate("Start/Stop") ) -updown._state = false -updown.redirect = luci.dispatcher.build_url( - "admin", "vpn", "openvpn" -) -function updown.cbid(self, section) - local pid = s.getPID(section) - self._state = pid ~= nil and sys.process.signal(pid, 0) - self.option = self._state and "stop" or "start" - return AbstractValue.cbid(self, section) -end -function updown.cfgvalue(self, section) - self.title = self._state and "stop" or "start" - self.inputstyle = self._state and "reset" or "reload" -end -function updown.write(self, section, value) - if self.option == "stop" then - --sys.call("/etc/init.d/openvpn stop %s" % section) - sys.call("/usr/lib/easyrsa/vpn.sh %s" % section) - else - sys.call("/etc/init.d/openvpn start %s" % section) - end - luci.http.redirect( self.redirect ) -end - -local port = s:option( DummyValue, "port", translate("Port") ) -function port.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if not val then - local file_cfg = self.map:get(section, "config") - if file_cfg and fs.access(file_cfg) then - val = sys.exec("awk '{if(match(tolower($1),/^port$/)&&match($2,/[0-9]+/)){cnt++;printf $2;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) - if val == "-" then - val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match($3,/[0-9]+/)){cnt++;printf $3;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) - end - end - end - return val or "-" -end - -local proto = s:option( DummyValue, "proto", translate("Protocol") ) -function proto.cfgvalue(self, section) - local val = AbstractValue.cfgvalue(self, section) - if not val then - local file_cfg = self.map:get(section, "config") - if file_cfg and fs.access(file_cfg) then - val = sys.exec("awk '{if(match(tolower($1),/^proto$/)&&match(tolower($2),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf tolower($2);exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) - if val == "-" then - val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match(tolower($4),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf $4;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg) - end - end - end - return val or "-" -end - -function m.on_after_apply(self,map) - --sys.call('/etc/init.d/openvpn reload') -end - -m:section(SimpleSection).template = "openvpn/vpn1" - -return m diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm deleted file mode 100644 index fab323d..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/admin_status/index/vpn.htm +++ /dev/null @@ -1 +0,0 @@ -<%+openvpn/vpn1%> \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm deleted file mode 100644 index 25fe654..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/easyrsa/easyrsa.htm +++ /dev/null @@ -1,172 +0,0 @@ - - - -
                          - - - - - - - -
                             
                          -

                           

                          - - - - - - - -
                           <%:Key Generation will take 60 minutes or more so be patient.%>  
                          -

                           

                          -

                          <%:Status of Key Generation%>

                          -

                           

                          - - - - -
                          - -
                          - -

                           

                          - - - - - - - - -
                             
                          - -
                          diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm deleted file mode 100644 index 9ca1e87..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/cbi-select-input-add.htm +++ /dev/null @@ -1,111 +0,0 @@ - - - -<%+openvpn/ovpn_css%> - -
                          -
                          -

                          <%:Template based configuration%>

                          -
                          -
                          - -
                          -
                          - -
                          -
                          -
                          -
                          -
                          -

                          <%:OVPN configuration file upload%>

                          -
                          -
                          - -
                          -
                          - -
                          -
                          - -
                          -
                          -
                          -
                          - -
                          -
                          diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm deleted file mode 100644 index 55c0a54..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/ovpn_css.htm +++ /dev/null @@ -1,38 +0,0 @@ - diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm deleted file mode 100644 index 7d88b84..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/pageswitch.htm +++ /dev/null @@ -1,30 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<%+openvpn/ovpn_css%> - -
                          -

                          - <%:Overview%> » - <%=luci.i18n.translatef("Instance \"%s\"", self.instance)%> -

                          - <% if self.mode == "basic" then %> - "><%:Switch to advanced configuration%> »

                          -


                          - <% elseif self.mode == "advanced" then %> - <%:Switch to basic configuration%> »

                          -


                          - <%:Configuration category%>: - <% for i, c in ipairs(self.categories) do %> - <% if c == self.category then %> - <%=translate(c)%> - <% else %> - "><%=translate(c)%> - <% end %> - <% if next(self.categories, i) then %>|<% end %> - <% end %> - <% end %> -
                          diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm b/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm deleted file mode 100644 index 1c70818..0000000 --- a/rooter/0optionalapps/luci-app-rootervpn/files/usr/lib/lua/luci/view/openvpn/vpn1.htm +++ /dev/null @@ -1,120 +0,0 @@ - - -
                          -

                          <%:OpenVPN Status%>

                          - - - - - - - - - - - - - - -
                          <%:Name%><%:Type%><%:Status%><%:Uptime%><%:Remote IP%><%:Clients%><%:Port%>

                          <%:Collecting data...%>
                          -
                          \ No newline at end of file diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-disabled.png b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-disabled.png deleted file mode 100644 index ccb0f561cf02501aa12fdf40394a522a176f2b97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1014 zcmVWdH}`0SOZhI*)>{(*OVf2XskIMF-;n3IYrgQc>V?00009a7bBm000XT z000XT0n*)m`~Uz0bV)=(RCwB@Ra+>mQ50VD`x(Zqlu;-qGs8JT=Shn5;I8Bn-joMP z;YE3n&VwS&$RqP2WlHBoo=9?iphVG>%Z%HMOdWJaF6B1na=z`K`De_Ka=!ki*?WEK z+iR`8_TG}0mzU+`<-NVV`}=$P5+o8ye0+RiVWCo~3@Iom*xcNN=-0FaAQYp~n39a4 z>gge~nH&xp7@(}I_qBF*7;SEj_V=Mdb#pM)2{K%yQjx~_cw=KME@%OEJ6pV|i8%*oVG35Yerz zQF}W}P0X>ajZMNN0A#qp@g2GJbXKpTBH}ooB9cNnC_Fy=Sz7XGfmU41T;TXl?T9Yr z@&uiZr6YzQWPN+f{;#jIdWl;3`N75I{09jM38tqf((9?L%$GGJR#(|4YQY48UVj%C z7qCxUz&Il#<8NdnX|+^ZN<2@&z$8psts^-(CMG7(7|cgYKSf7}4-KmW&3@(8B% z^!JtuicUaycsP9tOwKLznm^DJU0tm9!N4R;V)wj4RA3?7?e>k04Y^z{OerK1U*87< zlio99c~ybdj#r(>ZH4i|!h$gV)!6u^QH0u~UgXy(-ZP`n>-#4r{MQPpudjc6eDr8l zS5s#vt*pH1d-TNcFjZBt^Mpg@bPDN_)k=qlKRY_2l}hZM)oRVj$>DH)dbAoEKI;4a z$w_=4otYmpnaN~|jg3{QR3SQ@E+r*}=XurOAkEH_cr6QkKRWt*YwP;@S|*eIaXP=Z zw9xi8i%Y0IB1On&XAf0Xm6eqd5fQAA9!yWW)oM3NiB!VE+!YmW3u^7Yyu9q|>l+^* z_s}p269}Mz3>P?h5z^b+>j_7##;r;Q1M6PYOQSKmTsE8S;^M+=Hiw3WMny$oXmdE? zkur*ixRgp(ftng|E7-Q4pP%2{+z8`uCnxOw(r8$*J_ai^nyI^cm*K3?Cfk$vH?6KZZH@g k9v(gtf^$+*lHebJf3u{^p>{)!s{jB107*qoM6N<$f{3uxE&u=k diff --git a/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-started.png b/rooter/0optionalapps/luci-app-rootervpn/files/www/luci-static/resources/icons/vpn-started.png deleted file mode 100644 index 3f58ff147e996eedcdac630b5022c47905f34635..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 858 zcmV-g1Eu_lP)R#Hqb*tC^|3IO_!oogkT7Zt(*w}tvym(QM0pt@#M#g`aFJIOH z*-TAbP*BhhvaGhYwu$NG%a`JOe0-mDbabvTP#Kt-nw|#HZ{EBSVWPI-xWM4B=-9Di zRt^ph2k@yme*Czlx3~A!j~_qslV#C@1q%|KoSgREzI|Ku*|TR-@87={M3(>g^Cvq< z?CH~|(%ZIe^Rlq8H~~_N&$9pg{QMtaDdo?fKg>l%MZFAIk}A-5`$1|z$(5Cr^%uIl zprGKp-Me?Yz|2~@bZHbwJTo(M8itRqT)Cpt-``(|%|&nDz7+=1pFVx!`~CYjE4n<$ zhoz;Z-9!bQzP|p&HEY&{@bK__0r7zu?w7H#@mWw(4Gaui4-!*SQo85i;jsfGuCA_r z6QKj7r_Do0w1PMotnL9(V{pG4vrs0CkAR_3?Kdd`nqaJ)4N11OMpIN1O+FI&&b5Y^cUG?T7ayqtZ7VYYHGJ=VfgIXvs25< z%R51AVCuaCjxbPt#6aZ=518*x0X=aOls(?Pdnd>UN*xCe9<*P!Y*`d~d4>)^1?R3^ zyWB)XMBX?$I_}4(7U=l@pv;_?mp2Kdo}}b@>Cz=#kZWyhYz~u})LC%32vn8Z^Xi$y0diCm1m^d&&{WCN)JP#_GaQYBr+nFdHILPV$ROadw~VQM}}X&ezAgDD%4I4FbryCfrAcMul#OrZ?C+0 z^QJno3qh6HlP6DPi1iT&fNEN4Y3ZlPK8lNrTLcd}Y~aCz2MTlN&P{&x>XjHF3qWyX kX=!;JSb{GGr8aD80O!b@B@^pQ?EnA(07*qoM6N<$f(~MzeE@Mn=ZJqN1YLoSd90R8&;9G49&6tMBB=lZDi>039$hGyh6YPd8<`a^*@C zkpCaZ(F3~R3Np@}y0s{Axm6dmZ#D#^0Z^HBf z`Denz!~KW~IuOv%&{zjDVD;+N8-Q`amYkeyf-KL=%lj-cGSU;oe*E~c&BBEX59{jc zF822JPGezV`9ZWrAOOt3SCf*G%ub&^ox^|!aBy&Z@bK`+HZd`ohEE*}0Yl!~+S)eb zQv)hdh$&UTaRf?fgcOnkfab!}0N6*re*NMBC1)`)u}f66gz@s_%W-gvfc3^dkj=Yy z@9w3AuVD5v2?+_^qJ_!86qssdWz`8{^YQWBVS+~Xe`;HF{`~p08#itQ^7HdQQdL!5 zzz7UBhKCOy+5@ZdC}7SP#HSflaNfIj&y9kY6t+K*2yFiQS|@}jA!=_HVPP^1x! zU%q^)+uYpzf5CzUhe^=~!Z`C0s4RQ*=#ed~d;@`xA3w^0=x^V?iCn*aJrv3H|A0l; zc|k$JdpLavvhDfv=O!OMd{9J|ICt(`8nCW+AvR7xtsZA*=L%q)JVX`)mgIYZO@)t) zz_N_Bv$OLHs7#}Ff&c+?bMt;zSJxsICMKrez_wQH;|eEc>n+a diff --git a/rooter/0optionalapps/nft-qos/Makefile b/rooter/0optionalapps/nft-qos/Makefile deleted file mode 100644 index 78e0ec2..0000000 --- a/rooter/0optionalapps/nft-qos/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright (C) 2018 rosysong@rosinson.com -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=nft-qos -PKG_VERSION:=1.0.6 -PKG_RELEASE:=1 -PKG_LICENSE:=GPL-2.0 - -PKG_MAINTAINER:=Rosy Song - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/nft-qos - SECTION:=utils - CATEGORY:=Base system - DEPENDS:=+nftables +kmod-nft-netdev +kmod-nft-bridge - TITLE:=QoS scripts over nftables - PKGARCH:=all -endef - -define Package/nft-qos/description - This package provides implementation for qos over nftables. - Currently, static/dynamic qos and traffic shaping are supported. -endef - -define Package/nft-qos/conffiles -/etc/config/nft-qos -endef - -define Build/Prepare -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/nft-qos/install - $(INSTALL_DIR) $(1)/lib/nft-qos - $(INSTALL_DATA) ./files/lib/* $(1)/lib/nft-qos/ - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_CONF) ./files/nft-qos.config $(1)/etc/config/nft-qos - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_BIN) ./files/nft-qos.init $(1)/etc/init.d/nft-qos - $(INSTALL_DIR) $(1)/etc/hotplug.d/dhcp - $(INSTALL_BIN) ./files/nft-qos-monitor.hotplug $(1)/etc/hotplug.d/dhcp/00-nft-qos-monitor - $(INSTALL_BIN) ./files/nft-qos-dynamic.hotplug $(1)/etc/hotplug.d/dhcp/01-nft-qos-dynamic -endef - -$(eval $(call BuildPackage,nft-qos)) diff --git a/rooter/0optionalapps/nft-qos/files/lib/core.sh b/rooter/0optionalapps/nft-qos/files/lib/core.sh deleted file mode 100644 index d3c9d64..0000000 --- a/rooter/0optionalapps/nft-qos/files/lib/core.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2018 rosysong@rosinson.com -# - -# for uci_validate_section() -. /lib/functions/procd.sh - -NFT_QOS_HAS_BRIDGE= -NFT_QOS_INET_FAMILY=ip -NFT_QOS_SCRIPT_TEXT= -NFT_QOS_SCRIPT_FILE=/tmp/qos.nft - -qosdef_appendx() { # - NFT_QOS_SCRIPT_TEXT="$NFT_QOS_SCRIPT_TEXT""$1" -} - -qosdef_append_chain_def() { # - qosdef_appendx "\t\ttype $1 hook $2 priority $3; policy $4;\n" -} - -qosdef_append_chain_ingress() { # - qosdef_appendx "\t\ttype $1 hook ingress device $2 priority $3; policy $4;\n" -} - -# qosdef_append_rule_{MATCH}_{STATEMENT} -qosdef_append_rule_ip_limit() { # - local ipaddr=$1 - local operator=$2 - local unit=$3 - local rate=$4 - - qosdef_appendx \ - "\t\tip $operator $ipaddr limit rate over $rate $unit/second drop\n" -} - -# qosdef_append_rule_{MATCH}_{POLICY} -qosdef_append_rule_ip_policy() { # - qosdef_appendx "\t\tip $1 $2 $3\n" -} - -_handle_limit_whitelist() { # - local ipaddr=$1 - local operator - - [ -z "$ipaddr" ] && return - - case "$2" in - download) operator="daddr";; - upload) operator="saddr";; - esac - - qosdef_append_rule_ip_policy $operator $ipaddr accept -} - -qosdef_append_rule_limit_whitelist() { # - config_list_foreach default limit_whitelist _handle_limit_whitelist $1 -} - -qosdef_flush_table() { # - nft flush table $1 $2 2>/dev/null -} - -qosdef_remove_table() { #
                          - nft delete table $1 $2 2>/dev/null -} - -qosdef_init_header() { # add header for nft script - qosdef_appendx "#!/usr/sbin/nft -f\n" - qosdef_appendx "# Copyright (C) 2018 rosysong@rosinson.com\n" - qosdef_appendx "#\n\n" -} - -qosdef_init_env() { - # check interface type of lan - local lt="$(uci_get "network.lan.type")" - [ "$lt" = "bridge" ] && export NFT_QOS_HAS_BRIDGE="y" - - # check if ipv6 support - [ -e /proc/sys/net/ipv6 ] && export NFT_QOS_INET_FAMILY="inet" -} - -qosdef_clean_cache() { - rm -f $NFT_QOS_SCRIPT_FILE -} - -qosdef_init_done() { - echo -e $NFT_QOS_SCRIPT_TEXT > $NFT_QOS_SCRIPT_FILE 2>/dev/null -} - -qosdef_start() { - nft -f $NFT_QOS_SCRIPT_FILE 2>/dev/null -} diff --git a/rooter/0optionalapps/nft-qos/files/lib/dynamic.sh b/rooter/0optionalapps/nft-qos/files/lib/dynamic.sh deleted file mode 100644 index 207daca..0000000 --- a/rooter/0optionalapps/nft-qos/files/lib/dynamic.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2018 rosysong@rosinson.com -# - -. /lib/nft-qos/core.sh - -qosdef_validate_dynamic() { - uci_load_validate nft-qos default "$1" "$2" \ - 'limit_enable:bool:0' \ - 'limit_type:maxlength(8)' \ - 'dynamic_bw_up:uinteger:100' \ - 'dynamic_bw_down:uinteger:100' -} - -# return average rate for dhcp leases -qosdef_dynamic_rate() { # - local c=0 c6=0 - - [ ! -e /tmp/dhcp.leases -a \ - ! -e /var/dhcp6.leases ] && return - - [ -e /tmp/dhcp.leases ] && \ - c=$(wc -l < /tmp/dhcp.leases 2>/dev/null) - [ -e /var/dhcp6.leases ] && \ - c6=$(wc -l < /var/dhcp6.leases 2>/dev/null) - [ $c -eq 0 -a $c6 -eq 0 ] && \ - { echo 12500; return; } - - echo $(($1 / ($c + $c6))) -} - -qosdef_append_chain_dym() { # - local cidr cidr6 - local operator rate - local hook=$1 name=$2 bandwidth=$3 - - config_get cidr default 'dynamic_cidr' - config_get cidr6 default 'dynamic_cidr6' - - [ -z "$cidr" -a -z "$cidr6" ] && return - - case "$2" in - download) operator=daddr;; - upload) operator=saddr;; - esac - - rate=$(qosdef_dynamic_rate $bandwidth) - - qosdef_appendx "\tchain $name {\n" - qosdef_append_chain_def filter $hook 0 accept - qosdef_append_rule_limit_whitelist $name - [ -n "$cidr" ] && \ - qosdef_append_rule_ip_limit $cidr $operator kbytes $rate - [ -n "$cidr6" ] && \ - qosdef_append_rule_ip_limit $cidr6 $operator kbytes $rate - qosdef_appendx "\t}\n" -} - -qosdef_flush_dynamic() { - qosdef_flush_table "$NFT_QOS_INET_FAMILY" nft-qos-dynamic -} - -# init dynamic qos -qosdef_init_dynamic() { - local hook_ul="prerouting" hook_dl="postrouting" - - [ "$2" = 0 ] || { - logger -t nft-qos-dynamic "validation failed" - return 1 - } - - [ $limit_enable -eq 0 -o \ - "$limit_type" = "static" ] && return 1 - - # Transfer mbits/s to mbytes/s - # e.g. 100,000 kbits == 12,500 kbytes - dynamic_bw_up=$(($dynamic_bw_up * 1000 / 8)) - dynamic_bw_down=$(($dynamic_bw_down * 1000 / 8)) - - [ -z "$NFT_QOS_HAS_BRIDGE" ] && { - hook_ul="postrouting" - hook_dl="prerouting" - } - - qosdef_appendx "table $NFT_QOS_INET_FAMILY nft-qos-dynamic {\n" - qosdef_append_chain_dym $hook_ul upload $dynamic_bw_up - qosdef_append_chain_dym $hook_dl download $dynamic_bw_down - qosdef_appendx "}\n" -} diff --git a/rooter/0optionalapps/nft-qos/files/lib/monitor.sh b/rooter/0optionalapps/nft-qos/files/lib/monitor.sh deleted file mode 100644 index 54de88e..0000000 --- a/rooter/0optionalapps/nft-qos/files/lib/monitor.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2018 rosysong@rosinson.com -# - -. /lib/nft-qos/core.sh - -qosdef_monitor_get_ip_handle() { # - echo $(nft list chain $1 nft-qos-monitor $2 -a 2>/dev/null | grep $3 | awk '{print $11}') -} - -qosdef_monitor_add() { # - handle_dl=$(qosdef_monitor_get_ip_handle $NFT_QOS_INET_FAMILY download $2) - [ -z "$handle_dl" ] && nft add rule $NFT_QOS_INET_FAMILY nft-qos-monitor download ip daddr $2 counter - handle_ul=$(qosdef_monitor_get_ip_handle $NFT_QOS_INET_FAMILY upload $2) - [ -z "$handle_ul" ] && nft add rule $NFT_QOS_INET_FAMILY nft-qos-monitor upload ip saddr $2 counter -} - -qosdef_monitor_del() { # - local handle_dl handle_ul - handle_dl=$(qosdef_monitor_get_ip_handle $NFT_QOS_INET_FAMILY download $2) - handle_ul=$(qosdef_monitor_get_ip_handle $NFT_QOS_INET_FAMILY upload $2) - [ -n "$handle_dl" ] && nft delete handle $handle_dl - [ -n "$handle_ul" ] && nft delete handle $handle_ul -} - -# init qos monitor -qosdef_init_monitor() { - local hook_ul="prerouting" hook_dl="postrouting" - - [ -z "$NFT_QOS_HAS_BRIDGE" ] && { - hook_ul="postrouting" - hook_dl="prerouting" - } - - nft add table $NFT_QOS_INET_FAMILY nft-qos-monitor - nft add chain $NFT_QOS_INET_FAMILY nft-qos-monitor upload { type filter hook $hook_ul priority 0\; } - nft add chain $NFT_QOS_INET_FAMILY nft-qos-monitor download { type filter hook $hook_dl priority 0\; } -} diff --git a/rooter/0optionalapps/nft-qos/files/lib/priority.sh b/rooter/0optionalapps/nft-qos/files/lib/priority.sh deleted file mode 100644 index 081b13f..0000000 --- a/rooter/0optionalapps/nft-qos/files/lib/priority.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2018 rosysong@rosinson.com -# - -. /lib/functions/network.sh -. /lib/nft-qos/core.sh - -P1=""; P2=""; P3=""; P4=""; P5=""; P6=""; -P7=""; P8=""; P9=""; P10=""; P11=""; - -qosdef_validate_priority() { - uci_load_validate nft-qos default "$1" "$2" \ - 'priority_enable:bool:0' \ - 'priority_netdev:maxlength(8)' -} - -_qosdef_handle_protox() { # - case "$1" in - -400) P1="$P1""$2";; - -300) P2="$P2""$2";; - -225) P3="$P3""$2";; - -200) P4="$P4""$2";; - -150) P5="$P5""$2";; - -100) P6="$P6""$2";; - 0) P7="$P7""$2";; - 50) P8="$P8""$2";; - 100) P9="$P9""$2";; - 225) P10="$P10""$2";; - 300) P11="$P11""$2";; - esac -} - -qosdef_handle_protox() { #
                          - local proto prio srv - - config_get proto $1 'protocol' - config_get prio $1 'priority' - config_get srv $1 'service' - - [ -z "$proto" -o \ - -z "$prio" -o \ - -z "$srv" ] && return - - _qosdef_handle_protox $prio \ - "\t\t$proto dport { $srv } accept\n" -} - -qosdef_append_rule_protox() { #
                          - config_foreach qosdef_handle_protox $1 - qosdef_appendx \ - "${P1}${P2}${P3}${P4}${P5}${P6}${P7}${P8}${P9}${P10}${P11}" -} - -qosdef_append_chain_priority() { #
                          - local name=$1 device=$3 - - qosdef_appendx "\tchain $name {\n" - qosdef_append_chain_ingress filter $device 0 accept - qosdef_append_rule_protox $2 - qosdef_appendx "\t}\n" -} - -qosdef_remove_priority() { - qosdef_remove_table netdev nft-qos-priority -} - -# init traffic priority -qosdef_init_priority() { - local ifname="br-lan" - - [ "$2" = 0 ] || { - logger -t nft-qos-priority "validation failed" - return 1 - } - - [ $priority_enable -eq 0 ] && return 1 - - case "$priority_netdev" in - lan) [ "$(uci_get network.lan.type)" != "bridge" ] && { - network_get_device ifname "$priority_netdev" || \ - ifname="$(uci_get network.lan.ifname)" - } - ;; - wan*) network_get_device ifname "$priority_netdev" || \ - ifname="$(uci_get network.$priority_netdev.ifname)" - ;; - esac - - qosdef_appendx "table netdev nft-qos-priority {\n" - qosdef_append_chain_priority filter priority $ifname - qosdef_appendx "}\n" -} diff --git a/rooter/0optionalapps/nft-qos/files/lib/static.sh b/rooter/0optionalapps/nft-qos/files/lib/static.sh deleted file mode 100644 index 051c0ba..0000000 --- a/rooter/0optionalapps/nft-qos/files/lib/static.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2018 rosysong@rosinson.com -# - -. /lib/nft-qos/core.sh - -qosdef_validate_static() { - uci_load_validate nft-qos default "$1" "$2" \ - 'limit_enable:bool:0' \ - 'limit_type:maxlength(8)' \ - 'static_unit_dl:string:kbytes' \ - 'static_unit_ul:string:kbytes' \ - 'static_rate_dl:uinteger:50' \ - 'static_rate_ul:uinteger:50' -} - -# append rule for static qos -qosdef_append_rule_sta() { #
                          - local ipaddr unit rate - local operator=$2 - - config_get ipaddr $1 ipaddr - config_get unit $1 unit $3 - config_get rate $1 rate $4 - - [ -z "$ipaddr" ] && return - - qosdef_append_rule_ip_limit $ipaddr $operator $unit $rate -} - -# append chain for static qos -qosdef_append_chain_sta() { #
                          - local hook=$1 name=$2 - local config=$3 operator - - case "$name" in - download) operator="daddr";; - upload) operator="saddr";; - esac - - qosdef_appendx "\tchain $name {\n" - qosdef_append_chain_def filter $hook 0 accept - qosdef_append_rule_limit_whitelist $name - config_foreach qosdef_append_rule_sta $config $operator $4 $5 - qosdef_appendx "\t}\n" -} - -qosdef_flush_static() { - qosdef_flush_table "$NFT_QOS_INET_FAMILY" nft-qos-static -} - -# static limit rate init -qosdef_init_static() { - local hook_ul="prerouting" hook_dl="postrouting" - - [ "$2" = 0 ] || { - logger -t nft-qos-static "validation failed" - return 1 - } - - [ $limit_enable -eq 0 -o \ - $limit_type = "dynamic" ] && return 1 - - [ -z "$NFT_QOS_HAS_BRIDGE" ] && { - hook_ul="postrouting" - hook_dl="prerouting" - } - - qosdef_appendx "table $NFT_QOS_INET_FAMILY nft-qos-static {\n" - qosdef_append_chain_sta $hook_ul upload upload $static_unit_ul $static_rate_ul - qosdef_append_chain_sta $hook_dl download download $static_unit_dl $static_rate_dl - qosdef_appendx "}\n" -} diff --git a/rooter/0optionalapps/nft-qos/files/nft-qos-dynamic.hotplug b/rooter/0optionalapps/nft-qos/files/nft-qos-dynamic.hotplug deleted file mode 100644 index b81fa94..0000000 --- a/rooter/0optionalapps/nft-qos/files/nft-qos-dynamic.hotplug +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# Copyright 2018 rosysong@rosinson.com -# - -export initscript="nft-qos-dynamic" - -. /lib/functions.sh -. /lib/nft-qos/core.sh -. /lib/nft-qos/dynamic.sh - -NFT_QOS_DYNAMIC_ON= - -qosdef_check_if_dynamic() { - [ $limit_enable -eq 1 -a \ - "$limit_type" = "dynamic" ] && \ - NFT_QOS_DYNAMIC_ON="y" -} - - -logger -t nft-qos-dynamic "ACTION=$ACTION, MACADDR=$MACADDR, IPADDR=$IPADDR, HOSTNAME=$HOSTNAME" - -case "$ACTION" in - add | update | remove) - qosdef_validate_dynamic default qosdef_check_if_dynamic - [ -z "$NFT_QOS_DYNAMIC_ON" ] && return - - qosdef_init_env - qosdef_flush_dynamic - - qosdef_init_header - qosdef_validate_dynamic default qosdef_init_dynamic - qosdef_init_done - qosdef_start - ;; -esac diff --git a/rooter/0optionalapps/nft-qos/files/nft-qos-monitor.hotplug b/rooter/0optionalapps/nft-qos/files/nft-qos-monitor.hotplug deleted file mode 100644 index 5868bb1..0000000 --- a/rooter/0optionalapps/nft-qos/files/nft-qos-monitor.hotplug +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -# -# Copyright 2018 rosysong@rosinson.com -# - -export initscript="nft-qos-monitor" - -. /lib/nft-qos/monitor.sh - -logger -t nft-qos-monitor "ACTION=$ACTION, MACADDR=$MACADDR, IPADDR=$IPADDR, HOSTNAME=$HOSTNAME" - -case "$ACTION" in - add | update) - qosdef_init_env - qosdef_init_monitor - qosdef_monitor_add $MACADDR $IPADDR $HOSTNAME - ;; - remove) - qosdef_init_env - qosdef_init_monitor - qosdef_monitor_del $MACADDR $IPADDR $HOSTNAME - ;; -esac diff --git a/rooter/0optionalapps/nft-qos/files/nft-qos.config b/rooter/0optionalapps/nft-qos/files/nft-qos.config deleted file mode 100644 index 82e3b39..0000000 --- a/rooter/0optionalapps/nft-qos/files/nft-qos.config +++ /dev/null @@ -1,107 +0,0 @@ -# -# Copyright (C) 2018 rosysong@rosinson.com -# -# This is the sample for nft-qos configuration file, -# which will generate a nftables script in /tmp/qos.nft -# - -# Getting Started -# Official site : -# https://netfilter.org/projects/nftables/index.html -# What is nftables : -# https://wiki.nftables.org/wiki-nftables/index.php/Main_Page -# - -# Basic Operations -# Configuring Tables : -# https://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables -# Configuring Chains : -# https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains -# Configuring Rules : -# https://wiki.nftables.org/wiki-nftables/index.php/Simple_rule_management -# Quick Reference (recommended) : -# https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes -# https://netfilter.org/projects/nftables/manpage.html -# - -config default default - # Enable Flag for limit rate - option limit_enable '1' - - # Options for enable Static QoS (rate limit) - option limit_type 'static' - # Options for Static QoS (rate limit) - option static_unit_dl 'kbytes' - option static_unit_ul 'kbytes' - option static_rate_dl '50' - option static_rate_ul '50' - - # Options for enable Dynamic QoS - # This option can not compatible with Static QoS - # option limit_type 'dynamic' - - # For Dynamic QoS Samples (unit of bandwidth is Mbps): - option dynamic_cidr '192.168.1.0/24' - option dynamic_cidr6 'AAAA:BBBB::1/64' - option dynamic_bw_up '100' - option dynamic_bw_down '100' - - # White list for static/dynamic limit - # list limit_whitelist '192.168.1.225' - # list limit_whitelist '192.168.1.0/24' - # list limit_whitelist 'ABCD:CDEF::1/64' - - # Options for Traffic Priority - option priority_enable '0' - option priority_netdev 'lan' - - -# -# For Static QoS Rate Limit Samples : -# -# For Download : -#config download -# option hostname 'My PC' -# option unit 'kbytes' -# option ipaddr '192.168.1.224' -# option rate '128' -# -# For Upload : -#config upload -# option hostname 'office-pc' -# option unit 'mbytes' -# option ipaddr 'ABCD:FFED::1/64' -# option rate '1024' -# -# -# Traffic Priority Samples : -# -# protocol : tcp, udp, udplite, sctp, dccp, tcp is default -# priority : integer between 1-11, 1 is default and the highest -# service : you can input a integer or service name, -# e.g. '22', '11-22', 'telnet', 'ssh, http, ftp', etc -# -#config priority -# option protocol 'tcp' -# option priority '-400' -# option service '23' -# option comment '?' -# -#config priority -# option protocol 'udp' -# option priority '-400' -# option service 'https' -# option comment '?' -# -#config priority -# option protocol 'dccp' -# option priority '0' -# option service '22-35' -# option comment '?' -# -#config priority -# option protocol 'dccp' -# option priority '300' -# option service 'ftp,ssh,http' -# option comment '?' -# diff --git a/rooter/0optionalapps/nft-qos/files/nft-qos.init b/rooter/0optionalapps/nft-qos/files/nft-qos.init deleted file mode 100644 index 7a56ec7..0000000 --- a/rooter/0optionalapps/nft-qos/files/nft-qos.init +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (C) 2018 rosysong@rosinson.com -# - -. /lib/nft-qos/core.sh -. /lib/nft-qos/monitor.sh -. /lib/nft-qos/dynamic.sh -. /lib/nft-qos/static.sh -. /lib/nft-qos/priority.sh - -START=99 -USE_PROCD=1 - -service_triggers() { - procd_add_reload_trigger nft-qos - - procd_open_validate - qosdef_validate_dynamic - qosdef_validate_static - qosdef_validate_priority - procd_close_validate -} - -start_service() { - config_load nft-qos - - qosdef_init_env - qosdef_flush_static - qosdef_flush_dynamic - qosdef_remove_priority - - qosdef_init_header - qosdef_init_monitor - qosdef_validate_dynamic default qosdef_init_dynamic - qosdef_validate_static default qosdef_init_static - qosdef_validate_priority default qosdef_init_priority - qosdef_init_done - qosdef_start -} - -stop_service() { - qosdef_flush_dynamic - qosdef_flush_static - qosdef_remove_priority - qosdef_clean_cache -} diff --git a/rooter/0optionalapps/pingtest/Makefile b/rooter/0optionalapps/pingtest/Makefile deleted file mode 100644 index 0393fd7..0000000 --- a/rooter/0optionalapps/pingtest/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=pingtest -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/pingtest - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - DEPENDS:=+httping +curl - TITLE:=Added scripts for custom ping test - PKGARCH:=all -endef - -define Package/pingtest/description - Added scripts for custom ping test -endef - - -define Build/Compile -endef - -define Package/pingtest/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,pingtest)) diff --git a/rooter/0optionalapps/pingtest/files/etc/config/ping b/rooter/0optionalapps/pingtest/files/etc/config/ping deleted file mode 100644 index 6fa2bfc..0000000 --- a/rooter/0optionalapps/pingtest/files/etc/config/ping +++ /dev/null @@ -1,6 +0,0 @@ -config ping 'ping' - option enable '0' - option delay '40' - option conn '1' - option interval '20' - option type '1' \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/etc/init.d/pingtest b/rooter/0optionalapps/pingtest/files/etc/init.d/pingtest deleted file mode 100644 index 32cc726..0000000 --- a/rooter/0optionalapps/pingtest/files/etc/init.d/pingtest +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2013 OpenWrt.org - -START=99 -USE_PROCD=1 - -log() { - logger -t "pingtest" "$@" -} - -start_service() -{ - /usr/lib/custom/test_ping.sh & -} diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh b/rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh deleted file mode 100644 index 32af6cb..0000000 --- a/rooter/0optionalapps/pingtest/files/usr/lib/custom/johns_ping.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { -logger -t "Custom Ping Test " "$@" -} - -tping() { - hp=$(httping $2 -c 3 -s $1) - pingg=$(echo $hp" " | grep -o "round-trip .\+ ms ") - if [ -z "$pingg" ]; then - tmp=0 - else - tmp=200 - fi -} - -uci set ping.ping.conn="4" -uci commit ping - -CURRMODEM=1 -CPORT=$(uci -q get modem.modem$CURRMODEM.commport) -DELAY=$(uci get ping.ping.delay) - -TYPE=$(uci get ping.ping.type) -if [ $TYPE = "1" ]; then -log "Curl" - RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/) - RETURN_CODE_2=$(curl --ipv6 -m 10 -s -o /dev/null -w "%{http_code}" http://www.example.org/) - RETURN_CODE_3=$(curl -m 10 -s -o /dev/null -w "%{http_code}" https://github.com) -else -log "Ping" - tping "http://www.google.com/"; RETURN_CODE_1=$tmp - tping "http://www.example.org/" "-6"; RETURN_CODE_2=$tmp - tping "https://github.com"; RETURN_CODE_3=$tmp -fi - -if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then - log "Bad Ping Test" - if [ $TYPE = "1" ]; then - tping "http://www.google.com/"; RETURN_CODE_1=$tmp - tping "http://www.example.org/" "-6"; RETURN_CODE_2=$tmp - tping "https://github.com"; RETURN_CODE_3=$tmp - else - RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/) - RETURN_CODE_2=$(curl --ipv6 -m 10 -s -o /dev/null -w "%{http_code}" http://www.example.org/) - RETURN_CODE_3=$(curl -m 10 -s -o /dev/null -w "%{http_code}" https://github.com) - fi - if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then - log "Second Bad Ping Test" - uci set ping.ping.conn="3" - uci commit ping - ATCMDD="AT+CFUN=1,1" - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" - sleep $DELAY - tries=0 - while [ $tries -lt 9 ] - do - CONN=$(uci -q get modem.modem$CURRMODEM.connected) - if [ $CONN = "1" ]; then - uci set ping.ping.conn="4" - uci commit ping - if [ $TYPE = "1" ]; then - log "Curl" - RETURN_CODE_1=$(curl -m 10 -s -o /dev/null -w "%{http_code}" http://www.google.com/) - RETURN_CODE_2=$(curl --ipv6 -m 10 -s -o /dev/null -w "%{http_code}" http://www.example.org/) - RETURN_CODE_3=$(curl -m 10 -s -o /dev/null -w "%{http_code}" https://github.com) - else - log "Ping" - tping "http://www.google.com/"; RETURN_CODE_1=$tmp - tping "http://www.example.org/" "-6"; RETURN_CODE_2=$tmp - tping "https://github.com"; RETURN_CODE_3=$tmp - fi - if [[ "$RETURN_CODE_1" != "200" && "$RETURN_CODE_2" != "200" && "$RETURN_CODE_3" != "200" ]]; then - uci set ping.ping.conn="1" - uci commit ping - reboot -f - fi - log "Second Ping Test Good" - uci set ping.ping.conn="2" - uci commit ping - exit 0 - else - sleep 20 - tries=$((tries+1)) - fi - done - reboot -f - fi -else - log "Good Ping" - uci set ping.ping.conn="2" - uci commit ping -fi -exit 0 diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh b/rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh deleted file mode 100644 index ab3c5a3..0000000 --- a/rooter/0optionalapps/pingtest/files/usr/lib/custom/test_ping.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { -logger -t "Custom Ping Test " "$@" -} - -sleep 20 -CURRMODEM=1 -uci set ping.ping.conn="1" -uci commit ping -while [ true ] -do - INTER=$(uci get ping.ping.interval) - ENB=$(uci get ping.ping.enable) - if [ $ENB = 0 ]; then - sleep $INTER - else - CONN=$(uci -q get modem.modem$CURRMODEM.connected) - if [ $CONN = "1" ]; then - result=`ps | grep -i "johns_ping.sh" | grep -v "grep" | wc -l` - if [ $result -lt 1 ]; then - /usr/lib/custom/johns_ping.sh & - fi - else - uci set ping.ping.conn="1" - uci commit ping - fi - sleep $INTER - fi -done \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua deleted file mode 100644 index 025d16b..0000000 --- a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/controller/ping.lua +++ /dev/null @@ -1,16 +0,0 @@ --- Licensed to the public under the Apache License 2.0. - -module("luci.controller.ping", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - page = entry({"admin", "modem", "ping"}, cbi("ping"), _(translate("Custom Ping Test")), 45) - page.dependent = true - end -end diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua deleted file mode 100644 index caa3bf6..0000000 --- a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/model/cbi/ping.lua +++ /dev/null @@ -1,42 +0,0 @@ -local utl = require "luci.util" - -local sys = require "luci.sys" -local zones = require "luci.sys.zoneinfo" -local fs = require "nixio.fs" -local conf = require "luci.config" - -m = Map("ping", translate("Custom Ping Test"), translate("Enable/Disable Custom Ping Test")) - -d = m:section(TypedSection, "ping", " ") -d.anonymous = true - -c1 = d:option(ListValue, "enable", "Ping Test Status : ", "Ping every 20 seconds and, if it fails, restart modem or reboot router"); -c1:value("0", "Disabled") -c1:value("1", "Enabled") -c1.default=0 - -interval = d:option(Value, "interval", translate("Test Interval :"), translate("Number of seconds between testing the connection. Range is 20 to 120 secs.")); -interval.rmempty = true; -interval.optional=false; -interval.datatype = 'range(20,120)'; -interval.default="20"; - -type = d:option(ListValue, "type", "Test Type :", "Type of test - Page Retrieval or Ping"); -type:value("0", "Ping") -type:value("1", "Page Retrieval") -type.default=1 - -d1 = d:option(ListValue, "delay", "Reconnection Delay","Delay in seconds after restarting modem before checking for connection"); -d1:value("40", "40 seconds") -d1:value("45", "45 seconds") -d1:value("50", "50 seconds") -d1:value("55", "55 seconds") -d1:value("60", "60 seconds") -d1:value("70", "70 seconds") -d1:value("80", "80 seconds") -d1:value("90", "90 seconds") -d1:value("100", "100 seconds") -d1:value("120", "120 seconds") -d1.default=40 - -return m \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm deleted file mode 100644 index ed0c240..0000000 --- a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/admin_status/index/extping.htm +++ /dev/null @@ -1 +0,0 @@ -<%+pingtest/extping%> \ No newline at end of file diff --git a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm b/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm deleted file mode 100644 index daba06c..0000000 --- a/rooter/0optionalapps/pingtest/files/usr/lib/lua/luci/view/pingtest/extping.htm +++ /dev/null @@ -1,26 +0,0 @@ - - -
                          - <%:Custom Ping Test Status%> -
                          - -
                          <%:Ping Status%><%:Loading%> Collecting data...
                          - - diff --git a/rooter/0optionalapps/qfirehose/Makefile b/rooter/0optionalapps/qfirehose/Makefile deleted file mode 100644 index 6ceb348..0000000 --- a/rooter/0optionalapps/qfirehose/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (C) 2011-2014 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=qfirehose -PKG_RELEASE:=1 - -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk - -define Package/qfirehose - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Quectel FireHose - MAINTAINER:=Dairyman -endef - -define Package/qfirehose/description - Quectel FireHose -endef - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) \ - CC="$(TARGET_CC)" \ - CFLAGS="$(TARGET_CFLAGS) -Wall" -endef - -define Package/qfirehose/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/qfirehose $(1)/usr/bin/QFirehose -endef - -$(eval $(call BuildPackage,qfirehose)) diff --git a/rooter/0optionalapps/qfirehose/src/Makefile b/rooter/0optionalapps/qfirehose/src/Makefile deleted file mode 100644 index 44864b7..0000000 --- a/rooter/0optionalapps/qfirehose/src/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: qfirehose - -qfirehose: - $(CC) $(CFLAGS) -Wall firehose_protocol.c qfirehose.c sahara_protocol.c usb_linux.c stream_download_protocol.c md5.c usb2tcp.c -o $@ $^ - -clean: - rm -rf firehose obj libs diff --git a/rooter/0optionalapps/qfirehose/src/firehose_protocol.c b/rooter/0optionalapps/qfirehose/src/firehose_protocol.c deleted file mode 100644 index 7116cde..0000000 --- a/rooter/0optionalapps/qfirehose/src/firehose_protocol.c +++ /dev/null @@ -1,970 +0,0 @@ -/****************************************************************************** - @file firehose_protocol.c - @brief firehose protocol. - - DESCRIPTION - QFirehoe Tool for USB and PCIE of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include "usb_linux.h" -#include -#include -#include - -#define error_return() do {dbg_time("%s %s %d fail\n", __FILE__, __func__, __LINE__); return __LINE__; } while(0) -int recv_sc600y_configure_num = 1; -extern const char *q_device_type; -static int fh_recv_cmd_sk[2]; - -extern unsigned q_erase_all_before_download; -extern int update_transfer_bytes(long long bytes_cur); -extern int show_progress(); - -struct fh_configure_cmd { - const char *type; - const char *MemoryName; - uint32_t Verbose; - uint32_t AlwaysValidate; - uint32_t MaxDigestTableSizeInBytes; - uint32_t MaxPayloadSizeToTargetInBytes; - uint32_t MaxPayloadSizeFromTargetInBytes ; //2048 - uint32_t MaxPayloadSizeToTargetInByteSupported; //16k - uint32_t ZlpAwareHost; - uint32_t SkipStorageInit; -}; - -struct fh_erase_cmd { - const char *type; - //uint32_t PAGES_PER_BLOCK; - //uint32_t SECTOR_SIZE_IN_BYTES; - //char label[32]; - uint32_t last_sector; - uint32_t num_partition_sectors; - //uint32_t physical_partition_number; - uint32_t start_sector; -}; - -struct fh_program_cmd { - const char *type; - char *filename; - uint32_t filesz; - //uint32_t PAGES_PER_BLOCK; - uint32_t SECTOR_SIZE_IN_BYTES; - //char label[32]; - //uint32_t last_sector; - uint32_t num_partition_sectors; - //uint32_t physical_partition_number; - uint32_t start_sector; -}; - -struct fh_response_cmd { - const char *type; - const char *value; - uint32_t rawmode; - uint32_t MaxPayloadSizeToTargetInBytes; -}; - -struct fh_log_cmd { - const char *type; -}; - -struct fh_patch_cmd { - const char *type; - char *filename; - uint32_t filesz; - uint32_t SECTOR_SIZE_IN_BYTES; - uint32_t num_partition_sectors; -}; - -struct fh_cmd_header { - const char *type; -}; - -struct fh_vendor_defines { - const char *type; // "vendor" -}; - -struct fh_cmd { - union { - struct fh_cmd_header cmd; - struct fh_configure_cmd cfg; - struct fh_erase_cmd erase; - struct fh_program_cmd program; - struct fh_response_cmd response; - struct fh_log_cmd log; - struct fh_patch_cmd patch; - struct fh_vendor_defines vdef; - }; - int part_upgrade; - char xml_original_data[512]; -}; - -struct fh_data { - const char *firehose_dir; - const void *usb_handle; - unsigned MaxPayloadSizeToTargetInBytes; - unsigned fh_cmd_count; - unsigned fh_patch_count; - unsigned ZlpAwareHost; - struct fh_cmd fh_cmd_table[256]; //AG525 have more than 64 partition - - unsigned xml_tx_size; - unsigned xml_rx_size; - char xml_tx_buf[1024]; - char xml_rx_buf[1024]; -}; - -static const char * fh_xml_find_value(const char *xml_line, const char *key, char **ppend) { - char *pchar = strstr(xml_line, key); - char *pend; - - if (!pchar) { - dbg_time("%s: no key %s in %s\n", __func__, key, xml_line); - return NULL; - } - - pchar += strlen(key); - if (pchar[0] != '=' && pchar[1] != '"') { - dbg_time("%s: no start %s in %s\n", __func__, "=\"", xml_line); - return NULL; - } - - pchar += strlen("=\""); - pend = strstr(pchar, "\""); - if (!pend) { - dbg_time("%s: no end %s in %s\n", __func__, "\"", xml_line); - return NULL; - } - - *ppend = pend; - return pchar; -} - -static const char * fh_xml_get_value(const char *xml_line, const char *key) { - static char value[64]; - char *pend; - const char *pchar = fh_xml_find_value(xml_line, key, &pend); - - if (!pchar) { - return NULL; - } - - strncpy(value, pchar, pend - pchar); - value[pend - pchar] = '\0'; - - return value; -} - -static void fh_xml_set_value(char *xml_line, const char *key, unsigned value) { - char *pend; - const char *pchar = fh_xml_find_value(xml_line, key, &pend); - char *tmp_line = strdup(xml_line); - char value_str[32]; - - if (!pchar || !tmp_line) { - return; - } - - snprintf(value_str, sizeof(value_str), "%u", value); - tmp_line[pchar - xml_line] = '\0'; - strcat(tmp_line, value_str); - strcat(tmp_line, pend); - - strcpy(xml_line, tmp_line); - free(tmp_line); -} - -static int fh_parse_xml_line(const char *xml_line, struct fh_cmd *fh_cmd) { - const char *pchar = NULL; - size_t len = strlen(xml_line); - - memset(fh_cmd, 0, sizeof( struct fh_cmd)); - strcpy(fh_cmd->xml_original_data, xml_line); - if (fh_cmd->xml_original_data[len - 1] == '\n') - fh_cmd->xml_original_data[len - 1] = '\0'; - - if (strstr(xml_line, "vendor=\"quectel\"")) { - fh_cmd->vdef.type = "vendor"; - return 0; - } - else if (!strncmp(xml_line, "erase.type = "erase"; - if (strstr(xml_line, "last_sector")) { - if ((pchar = fh_xml_get_value(xml_line, "last_sector"))) - fh_cmd->erase.last_sector = atoi(pchar); - } - if ((pchar = fh_xml_get_value(xml_line, "start_sector"))) - fh_cmd->erase.start_sector = atoi(pchar); - if ((pchar = fh_xml_get_value(xml_line, "num_partition_sectors"))) - fh_cmd->erase.num_partition_sectors = atoi(pchar); - - return 0; - } - else if (!strncmp(xml_line, "program.type = "program"; - if ((pchar = fh_xml_get_value(xml_line, "filename"))) - { - fh_cmd->program.filename = strdup(pchar); - if(fh_cmd->program.filename[0] == '\0') - {//some fw version have blank program line, ignore it. - return -1; - } - } - if ((pchar = fh_xml_get_value(xml_line, "start_sector"))) - fh_cmd->program.start_sector = atoi(pchar); - if ((pchar = fh_xml_get_value(xml_line, "num_partition_sectors"))) - fh_cmd->program.num_partition_sectors = atoi(pchar); - if ((pchar = fh_xml_get_value(xml_line, "SECTOR_SIZE_IN_BYTES"))) - fh_cmd->program.SECTOR_SIZE_IN_BYTES = atoi(pchar); - - return 0; - } - else if (!strncmp(xml_line, "patch.type = "patch"; - pchar = fh_xml_get_value(xml_line, "filename"); - if (pchar && strcmp(pchar, "DISK")) - return -1; - return 0; - } - else if (!strncmp(xml_line, "response.type = "response"; - pchar = fh_xml_get_value(xml_line, "value"); - if (pchar) { - if (!strcmp(pchar, "ACK")) - fh_cmd->response.value = "ACK"; - else if(!strcmp(pchar, "NAK")) - fh_cmd->response.value = "NAK"; - else - fh_cmd->response.value = "OTHER"; - } - if (strstr(xml_line, "rawmode")) { - pchar = fh_xml_get_value(xml_line, "rawmode"); - if (pchar) { - fh_cmd->response.rawmode = !strcmp(pchar, "true"); - } - } - else if (strstr(xml_line, "MaxPayloadSizeToTargetInBytes")) { - pchar = fh_xml_get_value(xml_line, "MaxPayloadSizeToTargetInBytes"); - if (pchar) { - fh_cmd->response.MaxPayloadSizeToTargetInBytes = atoi(pchar); - } - } - return 0; - } - else if (!strncmp(xml_line, "program.type = "log"; - return 0; - } - - error_return(); -} - -static int fh_parse_xml_file(struct fh_data *fh_data, const char *xml_file) { - FILE *fp = fopen(xml_file, "rb"); - - if (fp == NULL) { - dbg_time("%s fail to fopen(%s), errno: %d (%s)\n", __func__, xml_file, errno, strerror(errno)); - error_return(); - } - - while (fgets(fh_data->xml_tx_buf, fh_data->xml_tx_size, fp)) { - char *xml_line = strstr(fh_data->xml_tx_buf, "<"); - char *c_start = NULL; - - if (!xml_line) - continue; - - c_start = strstr(xml_line, ""); - - if (c_end) { - /* - - - - */ - char *tmp = strstr(xml_line, "/>"); - if (tmp && (tmp < c_start || tmp > c_end)) { - memset(c_start, ' ', c_end - c_start + strlen("-->")); - goto __fh_parse_xml_line; - } - - continue; - } - else { - /* - - --> - */ - do { - if (fgets(fh_data->xml_tx_buf, fh_data->xml_tx_size, fp) == NULL) { break; }; - xml_line = fh_data->xml_tx_buf; - } while (!strstr(xml_line, "-->") && strstr(xml_line, " SAHARA_RESET"); - if (0 == sahara_tx_data (usb_handle, tx_buffer, sizeof(sahara_packet_reset))) { - dbg(LOG_ERROR, "Sending RESET packet failed"); - return 0; - } - - return 1; -#endif -} - -static int send_done_packet (void *usb_handle, void *tx_buffer) { - sahara_packet_done *sahara_done = (sahara_packet_done *)tx_buffer; - - sahara_done->header.command = le_uint32(SAHARA_DONE_ID); - sahara_done->header.length = le_uint32(sizeof(sahara_packet_done)); - // Send the image data - dbg(LOG_EVENT, "SENDING --> SAHARA_DONE"); - if (0 == sahara_tx_data (usb_handle, tx_buffer, sizeof(sahara_packet_done))) { - dbg(LOG_ERROR, "Sending DONE packet failed"); - return 0; - } - return 1; -} - -static int start_image_transfer(void *usb_handle, void *tx_buffer, const sahara_packet_read_data *sahara_read_data, FILE *file_handle) -{ - int retval = 0; - uint32_t bytes_read = 0, bytes_to_read_next; - uint32_t DataOffset = le_uint32(sahara_read_data->data_offset); - uint32_t DataLength = le_uint32(sahara_read_data->data_length); - - dbg(LOG_INFO, "0x%08x 0x%08x 0x%08x", le_uint32(sahara_read_data->image_id), DataOffset, DataLength); - - if (fseek(file_handle, (long)DataOffset, SEEK_SET)) { - dbg(LOG_INFO, "%d errno: %d (%s)", __LINE__, errno, strerror(errno)); - return 0; - } - - while (bytes_read < DataLength) { - bytes_to_read_next = MIN((uint32_t)DataLength - bytes_read, SAHARA_RAW_BUFFER_SIZE); - retval = fread(tx_buffer, 1, bytes_to_read_next, file_handle); - - if (retval < 0) { - dbg(LOG_ERROR, "file read failed: %s", strerror(errno)); - return 0; - } - - if ((uint32_t) retval != bytes_to_read_next) { - dbg(LOG_ERROR, "Read %d bytes, but was asked for 0x%08x bytes", retval, DataLength); - return 0; - } - - /*send the image data*/ - if (0 == sahara_tx_data (usb_handle, tx_buffer, bytes_to_read_next)) { - dbg(LOG_ERROR, "Tx Sahara Image Failed"); - return 0; - } - - bytes_read += bytes_to_read_next; - } - - return 1; -} - -static int start_image_transfer_64bit(void *usb_handle, void *tx_buffer, const sahara_packet_read_data_64bit *sahara_read_data_64bit, FILE *file_handle) -{ - sahara_packet_read_data sahara_read_data; - - sahara_read_data.header = sahara_read_data_64bit->header; - sahara_read_data.image_id = sahara_read_data_64bit->image_id; - sahara_read_data.data_offset = sahara_read_data_64bit->data_offset; - sahara_read_data.data_length = sahara_read_data_64bit->data_length; - - return start_image_transfer(usb_handle, tx_buffer, &sahara_read_data, file_handle); -} - -static int sahara_start(void *usb_handle, void *tx_buffer, void *rx_buffer, FILE *file_handle) { - uint32_t image_id = 0; - sahara_packet_header* sahara_cmd = (sahara_packet_header *)rx_buffer; - sahara_packet_hello *sahara_hello = (sahara_packet_hello *)rx_buffer; - sahara_packet_read_data *sahara_read_data = (sahara_packet_read_data *)rx_buffer; - sahara_packet_read_data_64bit *sahara_read_data_64bit = (sahara_packet_read_data_64bit *)rx_buffer; - sahara_packet_done_resp *sahara_done_resp = (sahara_packet_done_resp *)rx_buffer; - sahara_packet_end_image_tx *sahara_end_image_tx = (sahara_packet_end_image_tx *)rx_buffer; - - sahara_packet_hello_resp *sahara_hello_resp = (sahara_packet_hello_resp *)tx_buffer; - - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_HELLO"); - if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) { -#if 0 - unsigned char edl_cmd[] = {0x4b, 0x65, 0x01, 0x00, 0x54, 0x0f, 0x7e}; - sahara_tx_data(usb_handle, edl_cmd, sizeof(edl_cmd)); -#else - sahara_tx_data(usb_handle, tx_buffer, 1); -#endif - if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) - return 0; - } - - //Check if the received command is a hello command - if (le_uint32(sahara_cmd->command) != SAHARA_HELLO_ID) { - dbg(LOG_ERROR, "Received a different command: %x while waiting for hello packet", sahara_hello->header.command); - send_reset_command(usb_handle, rx_buffer); - return 0; - } - - // Recieved hello, send the hello response - //Create a Hello request - sahara_hello_resp->header.command = le_uint32(SAHARA_HELLO_RESP_ID); - sahara_hello_resp->header.length = le_uint32(sizeof(sahara_packet_hello_resp)); - sahara_hello_resp->version = sahara_hello->version; //SAHARA_VERSION; - sahara_hello_resp->version_supported = sahara_hello->version_supported; //SAHARA_VERSION_SUPPORTED; - sahara_hello_resp->status = le_uint32(SAHARA_STATUS_SUCCESS); - sahara_hello_resp->mode = sahara_hello->mode; - sahara_hello_resp->reserved0 = le_uint32(1); - sahara_hello_resp->reserved1 = le_uint32(2); - sahara_hello_resp->reserved2 = le_uint32(3); - sahara_hello_resp->reserved3 = le_uint32(4); - sahara_hello_resp->reserved4 = le_uint32(5); - sahara_hello_resp->reserved5 = le_uint32(6); - - switch (le_uint32(sahara_hello->mode)) { - case SAHARA_MODE_IMAGE_TX_PENDING: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_PENDING"); - break; - case SAHARA_MODE_IMAGE_TX_COMPLETE: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_COMPLETE"); - break; - case SAHARA_MODE_MEMORY_DEBUG: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_MEMORY_DEBUG"); - break; - case SAHARA_MODE_COMMAND: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_COMMAND"); - break; - default: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_0x%x", le_uint32(sahara_hello->mode)); - break; - } - - if (le_uint32(sahara_hello->mode) != SAHARA_MODE_IMAGE_TX_PENDING) { - dbg(LOG_ERROR, "ERROR NOT SAHARA_MODE_IMAGE_TX_PENDING"); - sahara_hello_resp->mode = SAHARA_MODE_IMAGE_TX_PENDING; - } - - /*Send the Hello Resonse Request*/ - dbg(LOG_EVENT, "SENDING --> SAHARA_HELLO_RESPONSE"); - if (0 == sahara_tx_data (usb_handle, tx_buffer, sizeof(sahara_packet_hello_resp))) { - dbg(LOG_ERROR, "Tx Sahara Data Failed "); - return 0; - } - - while (1) { - dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_COMMAND"); - if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) - return 0; - - if (le_uint32(sahara_cmd->command) == SAHARA_READ_DATA_ID) { - start_image_transfer(usb_handle, tx_buffer, sahara_read_data, file_handle); - } - else if (le_uint32(sahara_cmd->command) == SAHARA_64_BITS_READ_DATA_ID) { - start_image_transfer_64bit(usb_handle, tx_buffer, sahara_read_data_64bit, file_handle); - } - else if (le_uint32(sahara_cmd->command) == SAHARA_END_IMAGE_TX_ID) { - dbg(LOG_EVENT, "image_id = %d, status = %d", le_uint32(sahara_end_image_tx->image_id), le_uint32(sahara_end_image_tx->status)); - if (le_uint32(sahara_end_image_tx->status) == SAHARA_STATUS_SUCCESS) { - image_id = le_uint32(sahara_end_image_tx->image_id); - send_done_packet (usb_handle, tx_buffer); - break; - } else { - return 0; - } - } - else if (le_uint32(sahara_cmd->command) == SAHARA_HELLO_ID) { - continue; - } - else { - dbg(LOG_ERROR, "Received an unknown command: %d ", le_uint32(sahara_cmd->command)); - send_reset_command (usb_handle, tx_buffer); - return 0; - } - } - - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_DONE_RESP"); - if (0 == sahara_rx_data(usb_handle, rx_buffer, 0)) - return 0; - - dbg(LOG_INFO, "image_tx_status = %d", le_uint32(sahara_done_resp->image_tx_status)); - - if (SAHARA_MODE_IMAGE_TX_PENDING == le_uint32(sahara_done_resp->image_tx_status)) { - if (image_id == 13) //prog_nand_firehose_9x07.mbn - return 1; - if (image_id == 7) //NPRG9x55.mbn - return 1; - if (image_id == 21) //sbl1.mbn, October 22 2020 2:12 PM, AG35CEVAR05A07T4G - return 1; - } - else if (SAHARA_MODE_IMAGE_TX_COMPLETE == le_uint32(sahara_done_resp->image_tx_status)) { - dbg(LOG_EVENT,"Successfully uploaded all images"); - return 1; - } - else { - dbg(LOG_ERROR, "Received unrecognized status %d at SAHARA_WAIT_DONE_RESP state", - le_uint32(sahara_done_resp->image_tx_status)); - return 0; - } - - return 0; -} - -int sahara_main(const char *firehose_dir, const char *firehose_mbn, void *usb_handle, int edl_mode_05c69008) { - int retval = 0; - char full_path[512]; - FILE *file_handle; - void *tx_buffer; - void *rx_buffer; - - if (edl_mode_05c69008) { - snprintf(full_path, sizeof(full_path), "%.255s/%.240s", firehose_dir, firehose_mbn); - } - else { - char *prog_nand_firehose_filename = NULL; - - snprintf(full_path, sizeof(full_path), "%.255s/..", firehose_dir); - if (!qfile_find_file(full_path, "NPRG9x", ".mbn", &prog_nand_firehose_filename) - && !qfile_find_file(full_path, "NPRG9x", ".mbn", &prog_nand_firehose_filename)) { - dbg(LOG_ERROR, "retrieve NPRG MBN failed."); - return ENOENT; - } - dbg(LOG_INFO, "prog_nand_firehose_filename = %s", prog_nand_firehose_filename); - - snprintf(full_path, sizeof(full_path), "%.255s/../%.240s", firehose_dir, prog_nand_firehose_filename); - free(prog_nand_firehose_filename); - } - - file_handle = fopen(full_path, "rb"); - if (file_handle == NULL) { - dbg(LOG_INFO, "%s %d %s errno: %d (%s)", __func__, __LINE__, full_path, errno, strerror(errno)); - return ENOENT; - } - - rx_buffer = malloc (SAHARA_RAW_BUFFER_SIZE); - tx_buffer = malloc (SAHARA_RAW_BUFFER_SIZE); - - if (NULL == rx_buffer || NULL == tx_buffer) { - dbg(LOG_ERROR, "Failed to allocate sahara buffers"); - return ENOMEM; - } - - retval = sahara_start(usb_handle, tx_buffer, rx_buffer, file_handle); - if (0 == retval) { - dbg(LOG_ERROR, "Sahara protocol error"); - } - else { - dbg(LOG_STATUS, "Sahara protocol completed"); - } - - free(rx_buffer); - free(tx_buffer); - fclose(file_handle); - - if (retval) - return 0; - - return __LINE__; -} diff --git a/rooter/0optionalapps/qfirehose/src/sahara_protocol.h b/rooter/0optionalapps/qfirehose/src/sahara_protocol.h deleted file mode 100644 index bb88a2c..0000000 --- a/rooter/0optionalapps/qfirehose/src/sahara_protocol.h +++ /dev/null @@ -1,385 +0,0 @@ -/*=========================================================================== - * FILE: - * sahara_packet.h - * - * DESCRIPTION: - * Sahara protocol states and structure declaration. - * - * Copyright (C) 2012 Qualcomm Technologies, Inc. All rights reserved. - * Qualcomm Technologies Proprietary/GTDR - * - * All data and information contained in or disclosed by this document is - * confidential and proprietary information of Qualcomm Technologies, Inc. and all - * rights therein are expressly reserved. By accepting this material the - * recipient agrees that this material and the information contained therein - * is held in confidence and in trust and will not be used, copied, reproduced - * in whole or in part, nor its contents revealed in any manner to others - * without the express written permission of Qualcomm Technologies, Inc. - * =========================================================================== - * - * sahara_packet.h : Sahara protocol states and structure declaration. - * ========================================================================================== - * $Header: //components/rel/boot.bf/3.1.4/boot_images/core/storage/tools/QSaharaServer/src/sahara_protocol.h#1 $ - * $DateTime: 2017/02/21 04:58:32 $ - * $Author: pwbldsvc $ - * - * Edit History: - * YYYY-MM-DD who why - * ----------------------------------------------------------------------------- - * 2010-09-28 ng Added command mode support - * 2010-10-18 ab Added memory debug mode support - * - * Copyright 2012 by Qualcomm Technologies, Inc. All Rights Reserved. - * - *========================================================================================== - */ - -#ifndef SAHARA_PROTOCOL_H -#define SAHARA_PROTOCOL_H - -/*=========================================================================== - * - * INCLUDE FILES - * - * ===========================================================================*/ - -/*=========================================================================== - * - * PUBLIC DATA DECLARATIONS - * - * ===========================================================================*/ -// Sahara Protocol Version -#define SAHARA_VERSION 2 -#define SAHARA_VERSION_SUPPORTED 4 - -/*Maximum 1 megabyte tx buffer size*/ - -#define SAHARA_RAW_BUFFER_SIZE (4*1024) - -// Sahara command IDs -typedef enum -{ - SAHARA_NO_CMD_ID = 0x00, - SAHARA_HELLO_ID = 0x01, // sent from target to host - SAHARA_HELLO_RESP_ID = 0x02, // sent from host to target - SAHARA_READ_DATA_ID = 0x03, // sent from target to host - SAHARA_END_IMAGE_TX_ID = 0x04, // sent from target to host - SAHARA_DONE_ID = 0x05, // sent from host to target - SAHARA_DONE_RESP_ID = 0x06, // sent from target to host - SAHARA_RESET_ID = 0x07, // sent from host to target - SAHARA_RESET_RESP_ID = 0x08, // sent from target to host - SAHARA_MEMORY_DEBUG_ID = 0x09, // sent from target to host - SAHARA_MEMORY_READ_ID = 0x0A, // sent from host to target - SAHARA_CMD_READY_ID = 0x0B, // sent from target to host - SAHARA_CMD_SWITCH_MODE_ID = 0x0C, // sent from host to target - SAHARA_CMD_EXEC_ID = 0x0D, // sent from host to target - SAHARA_CMD_EXEC_RESP_ID = 0x0E, // sent from target to host - SAHARA_CMD_EXEC_DATA_ID = 0x0F, // sent from host to target - SAHARA_64_BITS_MEMORY_DEBUG_ID = 0x10, // sent from target to host - SAHARA_64_BITS_MEMORY_READ_ID = 0x11, // sent from host to target - SAHARA_64_BITS_READ_DATA_ID = 0x12, - // place all new commands above this - SAHARA_LAST_CMD_ID, - SAHARA_MAX_CMD_ID = 0x7FFFFFFF // To ensure 32-bits wide -} boot_sahara_cmd_id; - -typedef enum { - SAHARA_IMAGE_TYPE_BINARY = 0, /* Binary format */ - SAHARA_IMAGE_TYPE_ELF, /* ELF format */ - SAHARA_IMAGE_UNKNOWN = 0x7FFFFFFF /* To ensure 32-bits wide */ -} boot_sahara_image; - -// Status codes for Sahara -typedef enum -{ - // Success - SAHARA_STATUS_SUCCESS = 0x00, - - // Invalid command received in current state - SAHARA_NAK_INVALID_CMD = 0x01, - - // Protocol mismatch between host and target - SAHARA_NAK_PROTOCOL_MISMATCH = 0x02, - - // Invalid target protocol version - SAHARA_NAK_INVALID_TARGET_PROTOCOL = 0x03, - - // Invalid host protocol version - SAHARA_NAK_INVALID_HOST_PROTOCOL = 0x04, - - // Invalid packet size received - SAHARA_NAK_INVALID_PACKET_SIZE = 0x05, - - // Unexpected image ID received - SAHARA_NAK_UNEXPECTED_IMAGE_ID = 0x06, - - // Invalid image header size received - SAHARA_NAK_INVALID_HEADER_SIZE = 0x07, - - // Invalid image data size received - SAHARA_NAK_INVALID_DATA_SIZE = 0x08, - - // Invalid image type received - SAHARA_NAK_INVALID_IMAGE_TYPE = 0x09, - - // Invalid tranmission length - SAHARA_NAK_INVALID_TX_LENGTH = 0x0A, - - // Invalid reception length - SAHARA_NAK_INVALID_RX_LENGTH = 0x0B, - - // General transmission or reception error - SAHARA_NAK_GENERAL_TX_RX_ERROR = 0x0C, - - // Error while transmitting READ_DATA packet - SAHARA_NAK_READ_DATA_ERROR = 0x0D, - - // Cannot receive specified number of program headers - SAHARA_NAK_UNSUPPORTED_NUM_PHDRS = 0x0E, - - // Invalid data length received for program headers - SAHARA_NAK_INVALID_PDHR_SIZE = 0x0F, - - // Multiple shared segments found in ELF image - SAHARA_NAK_MULTIPLE_SHARED_SEG = 0x10, - - // Uninitialized program header location - SAHARA_NAK_UNINIT_PHDR_LOC = 0x11, - - // Invalid destination address - SAHARA_NAK_INVALID_DEST_ADDR = 0x12, - - // Invalid data size receieved in image header - SAHARA_NAK_INVALID_IMG_HDR_DATA_SIZE = 0x13, - - // Invalid ELF header received - SAHARA_NAK_INVALID_ELF_HDR = 0x14, - - // Unknown host error received in HELLO_RESP - SAHARA_NAK_UNKNOWN_HOST_ERROR = 0x15, - - // Timeout while receiving data - SAHARA_NAK_TIMEOUT_RX = 0x16, - - // Timeout while transmitting data - SAHARA_NAK_TIMEOUT_TX = 0x17, - - // Invalid mode received from host - SAHARA_NAK_INVALID_HOST_MODE = 0x18, - - // Invalid memory read access - SAHARA_NAK_INVALID_MEMORY_READ = 0x19, - - // Host cannot handle read data size requested - SAHARA_NAK_INVALID_DATA_SIZE_REQUEST = 0x1A, - - // Memory debug not supported - SAHARA_NAK_MEMORY_DEBUG_NOT_SUPPORTED = 0x1B, - - // Invalid mode switch - SAHARA_NAK_INVALID_MODE_SWITCH = 0x1C, - - // Failed to execute command - SAHARA_NAK_CMD_EXEC_FAILURE = 0x1D, - - // Invalid parameter passed to command execution - SAHARA_NAK_EXEC_CMD_INVALID_PARAM = 0x1E, - - // Unsupported client command received - SAHARA_NAK_EXEC_CMD_UNSUPPORTED = 0x1F, - - // Invalid client command received for data response - SAHARA_NAK_EXEC_DATA_INVALID_CLIENT_CMD = 0x20, - - // Failed to authenticate hash table - SAHARA_NAK_HASH_TABLE_AUTH_FAILURE = 0x21, - - // Failed to verify hash for a given segment of ELF image - SAHARA_NAK_HASH_VERIFICATION_FAILURE = 0x22, - - // Failed to find hash table in ELF image - SAHARA_NAK_HASH_TABLE_NOT_FOUND = 0x23, - - // Place all new error codes above this - SAHARA_NAK_LAST_CODE, - - SAHARA_NAK_MAX_CODE = 0x7FFFFFFF // To ensure 32-bits wide -} boot_sahara_status; - -// Status of all image transfers -typedef enum -{ - SAHARA_MODE_IMAGE_TX_PENDING = 0x0, - SAHARA_MODE_IMAGE_TX_COMPLETE = 0x1, - SAHARA_MODE_MEMORY_DEBUG = 0x2, - SAHARA_MODE_COMMAND = 0x3, - - // place all new commands above this - SAHARA_MODE_LAST, - SAHARA_MODE_MAX = 0x7FFFFFFF -} boot_sahara_mode; - -// Executable commands when target is in command mode -typedef enum -{ - SAHARA_EXEC_CMD_NOP = 0x00, - SAHARA_EXEC_CMD_SERIAL_NUM_READ = 0x01, - SAHARA_EXEC_CMD_MSM_HW_ID_READ = 0x02, - SAHARA_EXEC_CMD_OEM_PK_HASH_READ = 0x03, - SAHARA_EXEC_CMD_SWITCH_DMSS = 0x04, - SAHARA_EXEC_CMD_SWITCH_STREAMING = 0x05, - SAHARA_EXEC_CMD_READ_DEBUG_DATA = 0x06, - - // place all new commands above this - SAHARA_EXEC_CMD_LAST, - SAHARA_EXEC_CMD_MAX = 0x7FFFFFFF -} boot_sahara_exec_cmd_id; - -/* Sahara Protocol states */ -typedef enum { - SAHARA_WAIT_HELLO, - SAHARA_WAIT_COMMAND, - SAHARA_WAIT_RESET_RESP, - SAHARA_WAIT_DONE_RESP, - SAHARA_WAIT_MEMORY_READ, - SAHARA_WAIT_CMD_EXEC_RESP, - SAHARA_WAIT_MEMORY_TABLE, - SAHARA_WAIT_MEMORY_REGION, -} boot_sahara_state; - -/* ============================================================================= */ -/* Sahara protocol packet defintions */ -/* ============================================================================= */ - -typedef struct -{ - uint32_t command; // command ID - uint32_t length; // packet length incl command and length -} sahara_packet_header; - -// HELLO command packet type - sent from target to host -// indicates start of protocol on target side -typedef struct -{ - sahara_packet_header header; - uint32_t version; // target protocol version number - uint32_t version_supported; // minimum protocol version number supported - // on target - uint32_t cmd_packet_length; // maximum packet size supported for command - // packets - uint32_t mode; // expected mode of target operation - uint32_t reserved0; // reserved field - uint32_t reserved1; // reserved field - uint32_t reserved2; // reserved field - uint32_t reserved3; // reserved field - uint32_t reserved4; // reserved field - uint32_t reserved5; // reserved field -} sahara_packet_hello; - -// HELLO_RESP command packet type - sent from host to target -// response to hello, protocol version running on host and status sent -typedef struct -{ - sahara_packet_header header; - uint32_t version; // host protocol version number - uint32_t version_supported; // minimum protocol version number supported - // on host - uint32_t status; // OK or error condition - uint32_t mode; // mode of operation for target to execute - uint32_t reserved0; // reserved field - uint32_t reserved1; // reserved field - uint32_t reserved2; // reserved field - uint32_t reserved3; // reserved field - uint32_t reserved4; // reserved field - uint32_t reserved5; // reserved field -} sahara_packet_hello_resp; - -// READ_DATA command packet type - sent from target to host -// sends data segment offset and length to be read from current host -// image file -typedef struct -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint32_t data_offset; // offset into image file to read data from - uint32_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data; - -// READ_DATA_64 command packet type - sent from target to host -// sends data segment offset and length to be read from current host -// image file -/* -#ifdef WINDOWSPC -#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) -PACK( -typedef struct // note for gcc use __attribute__((__packed__)) -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint64_t data_offset; // offset into image file to read data from - uint32_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data_64bit; -); -#else -typedef __attribute__((__packed__)) struct -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint64_t data_offset; // offset into image file to read data from - uint32_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data_64bit; -#endif -*/ -typedef struct -{ - sahara_packet_header header; - uint64_t image_id; // ID of image to be transferred - uint64_t data_offset; // offset into image file to read data from - uint64_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data_64bit; - -// END_IMAGE_TX command packet type - sent from target to host -// indicates end of a single image transfer and status of transfer -typedef struct -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint32_t status; // OK or error condition -} sahara_packet_end_image_tx; - -// DONE packet type - sent from host to target -// indicates end of single image transfer -typedef struct -{ - sahara_packet_header header; -} sahara_packet_done; - -// DONE_RESP packet type - sent from target to host -// indicates end of all image transfers -typedef struct -{ - sahara_packet_header header; - uint32_t image_tx_status; // indicates if all images have been - // transferred; - // 0 = IMAGE_TX_PENDING - // 1 = IMAGE_TX_COMPLETE -} sahara_packet_done_resp; - -// RESET packet type - sent from host to target -// indicates to target to reset -typedef struct -{ - sahara_packet_header header; -} sahara_packet_reset; - -// RESET_RESP packet type - sent from target to host -// indicates to host that target has reset -typedef struct -{ - sahara_packet_header header; -} sahara_packet_reset_resp; -#endif /* SAHARA_PACKET_H */ diff --git a/rooter/0optionalapps/qfirehose/src/stream_download_protocol.c b/rooter/0optionalapps/qfirehose/src/stream_download_protocol.c deleted file mode 100644 index 1033565..0000000 --- a/rooter/0optionalapps/qfirehose/src/stream_download_protocol.c +++ /dev/null @@ -1,766 +0,0 @@ -/****************************************************************************** - @file stream_download_protocol.c - @brief stream protocol. - - DESCRIPTION - QFirehoe Tool for USB and PCIE of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - -#include "usb_linux.h" -#include "hostdl_packet.h" - -#define true (1==1) -#define false (1!=1) - -#define MAX_SEND_BUFFER_SIZE 1280 -#define MAX_RECEIVE_BUFFER_SIZE 1280 -unsigned char g_Transmit_Buffer[MAX_SEND_BUFFER_SIZE]; -int g_Transmit_Length; - -unsigned char g_Receive_Buffer[MAX_RECEIVE_BUFFER_SIZE]; -int g_Receive_Bytes; - -static void *stream_usb_handle; - -static void dump_buffer(unsigned char * buff, int len) -{ - int i = 0; - - dbg_time("dump buffer: %d bytes\n", len); - for(i = 0; i < len; i++) - { - dbg_time("%02x ", buff[i]); - } - dbg_time("\nend\n"); - -} - -#define CRC_16_L_SEED 0xFFFF -#define CRC_TAB_SIZE 256 /* 2^CRC_TAB_BITS */ -#define CRC_16_L_POLYNOMIAL 0x8408 - -static const uint16_t crc_16_l_table[ CRC_TAB_SIZE ] = { - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -unsigned short crc_16_l_calc(unsigned char *buf_ptr, int len) { - int data, crc_16; - for (crc_16 = CRC_16_L_SEED; len >= 8; len -= 8, buf_ptr++) { - crc_16 = crc_16_l_table[(crc_16 ^ *buf_ptr) & 0x00ff] ^ (crc_16 >> 8); - } - if (len != 0) { - - data = ((int) (*buf_ptr)) << (16 - 8); - - while (len-- != 0) { - if (((crc_16 ^ data) & 0x01) != 0) { - - crc_16 >>= 1; - crc_16 ^= CRC_16_L_POLYNOMIAL; - - } else { - - crc_16 >>= 1; - - } - - data >>= 1; - } - } - return (~crc_16); -} - -void compute_reply_crc () -{ - unsigned short crc = crc_16_l_calc (g_Transmit_Buffer, g_Transmit_Length * 8); - g_Transmit_Buffer[g_Transmit_Length] = crc & 0xFF; - g_Transmit_Buffer[g_Transmit_Length + 1] = crc >> 8; - g_Transmit_Length += 2; -} - -static void compose_packet(unsigned char cmd, unsigned char *parameter, uint32_t parameter_len, unsigned char *data, uint32_t data_len) { - uint32_t i; - - g_Transmit_Buffer[0] = cmd; - if (parameter == NULL) parameter_len = 0; - if (data == NULL) data_len = 0; - for (i = 0; i < parameter_len; i++) { - g_Transmit_Buffer[1 + i] = parameter[i]; - } - for (i = 0; i < data_len; i++) { - g_Transmit_Buffer[1 + parameter_len + i] = data[i]; - } - g_Transmit_Length = 1 + parameter_len + data_len; - g_Transmit_Buffer[g_Transmit_Length] = 0; -} - -static unsigned char stream_tx_buf[1280]; -#define CHECK_FOR_DATA() do {} while(0) -#define TRANSMIT_BYTE(_byte) do { stream_tx_buf[j++] = _byte; } while(0) - -static int send_packet(int flag) { - int i; - int ch; - int j; - - j = 0; - - - CHECK_FOR_DATA (); - - /* Since we don't know how long it's been. */ - if (!!flag) { - TRANSMIT_BYTE (0x7E); - } - - for (i = 0; i < g_Transmit_Length; i++) - { - /* we only need to check once every 31 characters, since RX and TX - * run at about the same speed, and our RX FIFO is 64 characters - */ - if ((i & 31) == 31) - CHECK_FOR_DATA (); - - ch = g_Transmit_Buffer[i]; - - if (ch == 0x7E || ch == 0x7D) - { - TRANSMIT_BYTE (0x7D); - TRANSMIT_BYTE (0x20 ^ ch); /*lint !e734 */ - } - else - { - TRANSMIT_BYTE (ch); /*lint !e734 */ - } - } - - CHECK_FOR_DATA (); - TRANSMIT_BYTE (0x7E); - -#if 0 - /* Hack for USB protocol. If we have an exact multiple of the USB frame - * size, then the last frame will not be sent out. The USB standard says - * that a "short packet" needs to be sent to flush the data. Two flag - * characters can serve as the short packet. Doing it this way, we only - * perform this test once on every entire packet from the target, so the - * over head is not too much. - */ - if ((j%512) == 0) - { - TRANSMIT_BYTE (0x7E); - TRANSMIT_BYTE (0x7E); - } - #endif - - return (qusb_noblock_write(stream_usb_handle, stream_tx_buf, j, j, 3000, 1) == j) ? 0 : -1; -} - -static int remove_escape_hdlc_flag(unsigned char* buffer, int len) -{ - int i = 0; - int index = 0; - int escape = 0; - //dump_buffer(buffer, len); - if(len == 0) return 0; - //ignore the first HDLC FLAG bytes - while(buffer[i] == 0x7e) - { - i++; - } - //all bytes is HDLC FLAG - if(i == len) - return 0; - for(; i < len; i++) - { - if(buffer[i] == 0x7D) - { - escape = 1; - continue; - } - if(escape == 1) - { - escape = 0; - buffer[i] ^= 0x20; - } - buffer[index++] = buffer[i]; - } - buffer[index] = 0; - //dump_buffer(buffer, index); - return index; -} - -static int receive_packet(void) -{ - int bytesread = 0; - unsigned char *buff = g_Receive_Buffer; - int idx = 0; - do - { - bytesread = qusb_noblock_read(stream_usb_handle, &buff[idx], MAX_RECEIVE_BUFFER_SIZE, 0, 3000); - if(bytesread == 0) - { - //timeout may be error - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - //dump_buffer(&buff[idx], bytesread); - idx += bytesread; - if(buff[idx - 1] == 0x7e) - { - //check the packet whether valid. - g_Receive_Bytes = remove_escape_hdlc_flag(buff, idx); - if(g_Receive_Bytes == 0) - { - continue; - }else{ - return 1; - } - } - }while(1); - - return 0; -} - -static int handle_hello(void) -{ - static const char host_header[] = "QCOM fast download protocol host"; - //static const char target_header[] = "QCOM fast download protocol targ"; - //char string1[64]; - //int size; - int err; - dbg_time("%s\n", __func__); - - memset(&g_Transmit_Buffer[0],0,sizeof(g_Transmit_Buffer)); - g_Transmit_Buffer[HELLO_CMD_OFFSET] = HELLO_REQ; - memcpy(&g_Transmit_Buffer[HELLO_MAGIC_NUM_OFFSET],host_header,32); - g_Transmit_Buffer[HELLO_MAX_VER_OFFSET] = STREAM_DLOAD_MAX_VER; - g_Transmit_Buffer[HELLO_MIN_VER_OFFSET] = STREAM_DLOAD_MIN_VER; - g_Transmit_Buffer[HELLO_MAX_DATA_SZ_1_OFFSET] = 0; - g_Transmit_Length = 36; - - compute_reply_crc(); - send_packet(1); - - int timeout = 5; - do{ - err = receive_packet(); - if(err == 1){ - switch(g_Receive_Buffer[0]) - { - case 0x02: - return 1; - case 0x0d: - continue; - default: - //dump_buffer(g_Receive_Buffer, 64); - return 0; - } - } - else if(err == -1){ - dbg_time("error = %d, strerr = %s\n", errno, strerror(errno)); - return 0; - } - timeout--; - }while(timeout); - - return 0; -} - -static int handle_security_mode(unsigned char trusted) { - dbg_time("%s trusted = %d\n", __func__, trusted); - compose_packet(0x17, &trusted, 1, NULL, 0); - compute_reply_crc(); - send_packet(1); - int timeout = 5; - do{ - if(receive_packet() == 1){ - switch(g_Receive_Buffer[0]) - { - case 0x18: - return 1; - default: - return 0; - } - }else - { - timeout--; - if(timeout==0) - { - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - } - }while(1); - return 0; -} -/* -set download flag in module, quectel custom command, -if flag : reboot, module will enter DM -if not flag: reboot normal -*/ -static int handle_quectel_download_flag(unsigned char mode) { - //byte mode = 1; - compose_packet(0x60, &mode, 1, NULL, 0); - compute_reply_crc(); - send_packet(1); - int timeout = 5; - do{ - if(receive_packet() == 1) - { - switch(g_Receive_Buffer[0]) - { - case 0x61: - switch( g_Receive_Buffer[1] ) - { - case 0x00: - return 1; - default: - return 0; - } - break; - case 0x0E: - dbg_time("Invalid command"); - return 2; - default: - dump_buffer(g_Receive_Buffer, 64); - return 0; - } - } - else - { - timeout--; - if(timeout==0) - { - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - } - }while(1); -} - -static const char *stream_firehose_dir; -static int stread_fread(const char *filename, void **pp_filebuf) { - int filesize = 0; - FILE *fp; - char fullpath[MAX_PATH*2]; - - snprintf(fullpath, sizeof(fullpath), "%.240s/../%.240s", stream_firehose_dir, filename); - fp = fopen(fullpath, "rb"); - if (fp == NULL) { - dbg_time("fail to fope %s, errno: %d (%s)\n", fullpath, errno, strerror(errno)); - return 0; - } - - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - - *pp_filebuf = malloc(filesize); - fseek(fp, 0, SEEK_SET); - filesize = fread(*pp_filebuf, 1, filesize, fp); - fclose(fp); - - dbg_time("%s filename=%s, filesize=%d\n", __func__, filename, filesize); - return filesize; -} - -static int handle_parti_tbl(unsigned char override) { - int timeout = 5; - int filesize; - void *filebuf; - const char *partition_path= "partition.mbn"; - dbg_time("%s override = %d\n", __func__, override); - - filesize = stread_fread(partition_path, &filebuf); - if (filesize <= 0) - return 0; - - compose_packet(0x19, &override, 1, filebuf, filesize); - compute_reply_crc(); - send_packet(1); - free(filebuf); - - do{ - if(receive_packet() == 1){ - dbg_time("handle_parti_tbl command = %02x, status = %02x\n", g_Receive_Buffer[0], g_Receive_Buffer[1]); - switch(g_Receive_Buffer[0]) - { - case 0x1a: - switch( g_Receive_Buffer[1] ){ - case 0x00: - return 1; - case 0x01: //0x1 this means that the original partition is different from the current partition,try to send partition - return 0; - case 0x02: //0x2 Partition table format not recognized, does not accept override - return 0; - case 0x03: //0x3 Erase operation failed - return 0; - break; - default: - return 0; - } - default: - return 0; - } - }else - { - timeout--; - if(timeout == 0) - { - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - } - }while(1); -} - -static int handle_reset(void) { - dbg_time("%s\n", __func__); - compose_packet(0x0b, NULL, 0, NULL, 0); - compute_reply_crc(); - send_packet(1); -#if 1 - return 1; -#else - int timeout = 5; - do{ - if(receive_packet() == 1){ - switch(g_Receive_Buffer[0]) - { - case 0x0c: - return 1; - case 0x0d: - continue; - default: - dump_buffer(g_Receive_Buffer, 64); - return 0; - } - } - else - { - - timeout--; - if(timeout == 0) - { - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - } - }while(1); -#endif -} - -/******pkt_open_multi_image*******/ - -static void pkt_open_multi_image (unsigned char mode, unsigned char *data, uint32_t size) { - compose_packet(0x1b, &mode, 1, data, size); - compute_reply_crc(); -} - -static int handle_openmulti(uint32_t size,unsigned char* data) -{ - int timeout = 5; - unsigned char mode=0x0e; - - pkt_open_multi_image(mode, data, size); - send_packet(1); - do { - if (receive_packet() == 1) { - switch (g_Receive_Buffer[0]) { - case 0x1c: - return 1; - case 0x0d: - continue; - default: - return 0; - } - }else - { - - timeout--; - if(timeout == 0) - { - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - } - } while (1); - return 1; -} - -/******pkt_write_multi_image*******/ -static void pkt_write_multi_image(uint32_t addr, unsigned char*data, uint16_t size) { - unsigned char parameter[4] = {(unsigned char)(addr)&0xff, (unsigned char)(addr>>8)&0xff, (unsigned char)(addr>>16)&0xff, (unsigned char)(addr>>24)&0xff}; - compose_packet(0x07, parameter, 4, data, size); - compute_reply_crc(); -} - -static int handle_write(unsigned char *data, uint32_t size) -{ - //uint32_t total_size; - uint32_t addr = 0; - uint32_t writesize; - uint32_t buffer_size = 1024; - //int loop = 1; - int retry_cnt = 3; //if send failed,send again - int ret; - - //total_size = size; - while(size) - { - writesize = (size < buffer_size) ? size : buffer_size; - - pkt_write_multi_image(addr, data, writesize); -start_send_packet: - ret = send_packet(1); - if(0 != ret) - { - dbg_time("io read/write failed\n"); - return 0; - } - if(receive_packet() == 1){ - switch(g_Receive_Buffer[0]) - { - case 0x08: - size -= writesize; - addr += writesize; - //retry_cnt=5; - break; - default: - goto retry_send_packet; - return 0; - } - } - else - { - -retry_send_packet: - retry_cnt--; - if(retry_cnt > 0) - { - goto start_send_packet; - } - else - { - dbg_time( "value is [0x%02x]",g_Receive_Buffer[0]); - return 0; - } - } - - } - - return 1; -} -/******PARTITION*******/ -static int handle_close(void) { - int timeout = 5; - compose_packet(0x15, NULL, 0, NULL, 0); - compute_reply_crc(); - send_packet(1); - - do{ - if(receive_packet() == 1){ - switch(g_Receive_Buffer[0]) - { - case 0x16: - return 1; - default: - return 0; - } - }else - { - - timeout--; - if(timeout == 0) - { - dbg_time("%s timeout\n", __FUNCTION__); - return 0; - } - } - }while(1); - return 0; -} - -static int do_flash_mbn(const char *partion, const char *filepath) { - int result = false; - void *filebuf = NULL; - int filesize = 0; - - dbg_time("%s %s\n", __func__, partion); - - if (filepath) { - filesize = stread_fread(filepath, &filebuf); - if (filesize <= 0) - return 0; - } - else { - filesize = 4*1024; - filebuf = (unsigned char *)malloc(filesize); - memset(filebuf, 0x00, filesize); - } - - result = handle_openmulti(strlen(partion) + 1, (unsigned char *)partion); - if (result == false) { - dbg_time("%s open failed\n", partion); - goto __fail; - } - - dbg_time("sending '%s' (%dKB)\n", partion, (int)(filesize/1024)); - - result = handle_write(filebuf, filesize); - if (result == false) { - dbg_time("%s download failed\n", partion); - goto __fail; - } - - result = handle_close(); - if (result == false) { - dbg_time("%s close failed.\n", partion); - goto __fail; - } - - dbg_time("OKAY\n"); - -__fail: - free(filebuf); - - return result; -} - -int stream_download(const char *firehose_dir, void *usb_handle, unsigned qusb_zlp_mode) -{ - (void)qusb_zlp_mode; - stream_usb_handle = usb_handle; - stream_firehose_dir = firehose_dir; - - if (handle_hello() == false) { - dbg_time("Send hello command fail\n"); - return false; - } - - /* - hello packet will set dload flag in module, when upgrade interrup, restart module,module will enter dm(quectel sbl) - */ - if (handle_security_mode(1) == false) { - dbg_time("Send trust command fail\n"); - return false; - } - - if (handle_parti_tbl(0) == false) { - dbg_time("----------------------------------\n"); - dbg_time("Detect partition mismatch.\n"); - dbg_time("Download parition with override.\n"); - dbg_time("----------------------------------\n"); - - if(handle_parti_tbl(1) == false) { - dbg_time("override failed. \n"); - return false; - } - - /* - partition is not match, the download flag will be clear, so set it again, reset will clear it - */ - if(handle_quectel_download_flag(1) == false) { - dbg_time("Set Quectel download flag failed\n"); - } - else { - dbg_time("Set Quectel download flag successfully\n"); - } - } - -#if 1 - if (do_flash_mbn("0:SBL", "sbl1.mbn") == false) { - return false; - } -#endif - - if (handle_reset() == false) { - dbg_time("Send reset command failed\n"); - return false; - } - - dbg_time("%s successful\n", __func__); - - return true; -} - -//hunter.lv add -//retrieve module soft revision - -typedef struct -{ - unsigned char cmd_code; - unsigned char version; - unsigned char reserved[2]; - unsigned char msm[4]; - unsigned char mobile_modle_number[4]; - unsigned char mobile_software_revision[1]; -}__attribute__ ((packed))extended_build_id_response_t; - -int retrieve_soft_revision(void *usb_handle, uint8_t *mobile_software_revision, unsigned length) -{ -/* -80-v1294-1_yyd_serial_interface_control_document_(icd)_for_cdma_dual-mode_subscriber_station_data 3.4.122 Extended Build ID -*/ - uint8_t req1[] = {0x7E,0x7C, 0x93,0x49, 0x7E}; - int ret; - uint8_t *rx_buff = malloc(2048); - - memset(mobile_software_revision, 0x00, length); - - if (rx_buff == NULL) - return 0; - - ret = qusb_noblock_write(usb_handle, req1, sizeof(req1), sizeof(req1), 1000, 0); - if(ret > 0) { - ret = qusb_noblock_read(usb_handle, rx_buff , 2048, 1, 3000); - if (ret > 0) { - if (rx_buff[0] == 0x7C && rx_buff[ret - 1] == 0x7E) { - extended_build_id_response_t *rsp = (extended_build_id_response_t *)rx_buff; - (void)length; - memcpy(mobile_software_revision, rsp->mobile_software_revision, strlen((const char *)rsp->mobile_software_revision)); - } - } - } - - free(rx_buff); - return (mobile_software_revision[0] != '\0'); -} diff --git a/rooter/0optionalapps/qfirehose/src/usb2tcp.c b/rooter/0optionalapps/qfirehose/src/usb2tcp.c deleted file mode 100644 index 0d8e4d3..0000000 --- a/rooter/0optionalapps/qfirehose/src/usb2tcp.c +++ /dev/null @@ -1,338 +0,0 @@ -/****************************************************************************** - @file tty2tcp.c - @brief switch data between tcp socket and ttyUSB port. - - DESCRIPTION - QLog Tool for USB and PCIE of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) -#include -#else -#include -#endif -//#include -#include "usb_linux.h" -#include //for __BYTE_ORDER -char *inet_ntoa(struct in_addr in); - -#define dprintf dbg_time - -#define MIN(a,b) ((a) < (b)? (a) : (b)) - -#define MAX_USBFS_BULK_IN_SIZE (4 * 1024) -#define MAX_USBFS_BULK_OUT_SIZE (16 * 1024) - -static uint32_t cpu_to_le32 (uint32_t v32) { - uint32_t tmp = v32; -#if __BYTE_ORDER == __LITTLE_ENDIAN -#else - unsigned char *s = (unsigned char *)(&v32); - unsigned char *d = (unsigned char *)(&tmp); - d[0] = s[3]; - d[1] = s[2]; - d[2] = s[1]; - d[3] = s[0]; -#endif - return tmp; -} -#define le32_to_cpu(_v32) cpu_to_le32(_v32) - -static int qusb_control[2]; - -static int noblock_full_read(int fd, void *pbuf, ssize_t size) { - ssize_t cur = 0; - - while (cur < size) { - ssize_t ret = read(fd, (char *)pbuf+cur, size-cur); - - if (ret > 0) - cur += ret; - else if (ret < 0 && errno == EAGAIN) { - struct pollfd pollfds[] = {{fd, POLLIN, 0}}; - poll(pollfds, 1, -1); - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) - break; - } else { - dprintf("fd=%d read=%zd, errno: %d (%s)\n", fd, ret, errno, strerror(errno)); - break; - } - } - - if (cur != size) { - dprintf("%s fd=%d cur=%zd, size=%zd\n", __func__, fd, cur, size); - } - - return cur; -} - -static ssize_t noblock_full_write(int fd, const void *pbuf, ssize_t size) { - ssize_t cur = 0; - - while (cur < size) { - ssize_t ret = write(fd, (char *)pbuf+cur, size-cur); - if (ret > 0) - cur += ret; - else if (ret <= 0 && errno == EAGAIN) { - struct pollfd pollfds[] = {{fd, POLLOUT, 0}}; - poll(pollfds, 1, -1); - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) - break; - } else { - dprintf("fd=%d write=%zd, errno: %d (%s)\n", fd, ret, errno, strerror(errno)); - break; - } - } - - if (cur != size) { - dprintf("%s fd=%d cur=%zd, size=%zd\n", __func__, fd, cur, size); - } - - return cur; -} - -static void* usb_bulk_read_thread(void* arg) { - const void *usb_handle = arg; - void *buf = malloc(MAX_USBFS_BULK_IN_SIZE); - int fd = qusb_control[1]; - - if (buf == NULL) - return NULL; - - while(usb_handle) { - int count = qusb_noblock_read(usb_handle, buf, MAX_USBFS_BULK_IN_SIZE, 1, 30000); - - if (count > 0) { - count = write(fd, buf, count); - count = read(fd, buf, 32); //wait usb2tcp_main read - if (count <= 0) { - dprintf("read=%d\n", count); - break; - } - } else if (count <= 0) { - break; - } - } - - close(fd); - free(buf); - return NULL; -} - -static int qusb_open(const void *usb_handle) { - int fd = -1; - pthread_t thread_id; - - pthread_attr_t usb_thread_attr; - pthread_attr_init(&usb_thread_attr); - pthread_attr_setdetachstate(&usb_thread_attr, PTHREAD_CREATE_DETACHED); - - socketpair(AF_LOCAL, SOCK_STREAM, 0, qusb_control); - pthread_create(&thread_id, &usb_thread_attr, usb_bulk_read_thread, (void*)usb_handle); - - fd = qusb_control[0]; - - return fd; -} - -static ssize_t qusb_read(int fd, void* pbuf, size_t size) { - return read(fd, pbuf, size); -} - -static int create_tcp_server(int socket_port) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_in sockaddr; - - dprintf("%s tcp_port=%d\n", __func__, socket_port); - /*Create server socket*/ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd <= 0) - return sockfd; - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); - sockaddr.sin_port = htons(socket_port); - - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); - if (bind(sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) { - close(sockfd); - dprintf("%s bind %d errno: %d (%s)\n", __func__, socket_port, errno, strerror(errno)); - return -1; - } - - return sockfd; -} - -static int wait_client_connect(int server_fd) { - int client_fd = -1; - unsigned char addr[128]; - socklen_t alen = sizeof(addr); - - dprintf("%s\n", __func__); - listen(server_fd, 1); - client_fd = accept(server_fd, (struct sockaddr *)addr, &alen); - if (client_fd <= 0) - return client_fd; - - if (client_fd > 0) { - struct sockaddr_in *addr_in = (struct sockaddr_in *)addr; - dprintf("clientfd = %d %s:%d connect\n", client_fd, inet_ntoa(addr_in->sin_addr), addr_in->sin_port); - } - - return client_fd; -} - -int usb2tcp_main(const void *usb_handle, int tcp_port, unsigned qusb_zlp_mode) { - void *pbuf = malloc(MAX_USBFS_BULK_OUT_SIZE); - int server_fd = -1, client_fd = -1, usb_fd = -1, size = -1; - TLV_USB tlv_usb; - - if (pbuf == NULL) - return -1; - - server_fd = create_tcp_server(tcp_port); - dprintf("server_fd=%d\n", server_fd); - if (server_fd <= 0) { - dprintf("Fail create_tcp_server\n"); - goto _out; - } - - if (client_fd <= 0) { - client_fd = wait_client_connect(server_fd); - if (client_fd < 0) { - dprintf("Fail wait_client_connect\n"); - goto _out; - } - } - - usb_fd = qusb_open(usb_handle); - dprintf("usb_fd = %d\n", usb_fd); - - tlv_usb.tag = cpu_to_le32(Q_USB2TCP_VERSION); - tlv_usb.length = cpu_to_le32(12); - tlv_usb.idVendor = cpu_to_le32(0x05c6); - tlv_usb.idProduct = cpu_to_le32(0x9008); - tlv_usb.interfaceNum = cpu_to_le32(1); - if (write(client_fd, &tlv_usb, sizeof(tlv_usb)) == -1) {}; - - fcntl(usb_fd, F_SETFL, fcntl(usb_fd,F_GETFL) | O_NONBLOCK); - fcntl(client_fd, F_SETFL, fcntl(client_fd,F_GETFL) | O_NONBLOCK); - - while (usb_fd > 0 && client_fd > 0) { - struct pollfd pollfds[] = {{usb_fd, POLLIN, 0}, {client_fd, POLLIN, 0}}; - int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]); - - do { - ret = poll(pollfds, nevents, -1); - } while (ret < 0 && errno == EINTR); - - - if (ret <= 0) { - dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); - goto _hangup; - } - - - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - dprintf("%s poll usb_fd = %d, revents = %04x\n", __func__, usb_fd, pollfds[0].revents); - goto _hangup; - } - - - if (pollfds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { - dprintf("%s poll client_fd = %d, revents = %04x\n", __func__, client_fd, pollfds[1].revents); - goto _hangup; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - TLV tlv = {Q_USB2TCP_VERSION, 0}; - - if ((pollfds[ne].revents & POLLIN) == 0) - continue; - - if (fd == usb_fd) { - size = qusb_read(usb_fd, pbuf, MAX_USBFS_BULK_IN_SIZE); - if (size <= 0) { - dprintf("usb_fd=%d read=%d, errno: %d (%s)\n", fd, size, errno, strerror(errno)); - goto _hangup;; - } - if (write(usb_fd, pbuf, 1) == -1) {}; //wakeup usb_bulk_read_thread - - tlv.tag = cpu_to_le32(Q_USB2TCP_VERSION); - tlv.length = cpu_to_le32(size); - if (sizeof(tlv) != noblock_full_write(client_fd, &tlv, sizeof(tlv))) { - goto _hangup; - break; - } - - if (size != noblock_full_write(client_fd, pbuf, size)) { - goto _hangup; - break; - } - } - else if (fd == client_fd) { - size = noblock_full_read(client_fd, &tlv, sizeof(tlv)); - if (size != sizeof(tlv)) { - dprintf("client_fd=%d read=%d, errno: %d (%s)\n", fd, size, errno, strerror(errno)); - goto _hangup; - } - - if (le32_to_cpu(tlv.tag) != Q_USB2TCP_VERSION) { - break; - } - - size = le32_to_cpu(tlv.length); - if (size != noblock_full_read(client_fd, pbuf, size)) { - goto _hangup; - break; - } - qusb_noblock_write(usb_handle, pbuf, size, size, 3000, qusb_zlp_mode); - } - } - } - -_hangup: - if (usb_fd > 0) { - close(usb_fd); - usb_fd = -1; - } - if (client_fd > 0) { - close(client_fd); - client_fd = -1; - } - -_out: - free(pbuf); - return 0; -} diff --git a/rooter/0optionalapps/qfirehose/src/usb_linux.c b/rooter/0optionalapps/qfirehose/src/usb_linux.c deleted file mode 100644 index 89e7917..0000000 --- a/rooter/0optionalapps/qfirehose/src/usb_linux.c +++ /dev/null @@ -1,1197 +0,0 @@ -/****************************************************************************** - @file usb_linux.c - @brief read and write usb devices. - - DESCRIPTION - QFirehoe Tool for USB and PCIE of Quectel wireless cellular modules. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) -#include -#else -#include -#endif -#include -#include -#include -#include "usb_linux.h" - -int edl_pcie_mhifd = -1; -int switch_to_edl_mode(void *usb_handle); - -extern uint32_t inet_addr(const char *); - -#define MAX_USBFS_BULK_IN_SIZE (4 * 1024) -#define EC20_MAX_INF 4 -#define MKDEV(__ma, __mi) (((__ma & 0xfff) << 8) | (__mi & 0xff) | ((__mi & 0xfff00) << 12)) - -struct quectel_usb_device { - char devname[64]; - int desc; - int ttyfd; - int idVendor; - int idProduct; - uint8_t bNumInterfaces; - uint8_t intr_ep[EC20_MAX_INF]; - uint8_t bulk_ep_in[EC20_MAX_INF]; - uint8_t bulk_ep_out[EC20_MAX_INF]; - int wMaxPacketSize[EC20_MAX_INF]; - int control[EC20_MAX_INF][2]; -}; - -static struct quectel_usb_device quectel_9x07; -static int tcp_socket_fd = -1; -static int usb_dm_interface = 0; - -static int strStartsWith(const char *line, const char *prefix) -{ - if (!prefix || prefix[0] == '\0') - return 1; - - for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) { - if (*line != *prefix) { - return 0; - } - } - - return *prefix == '\0'; -} - -static int strEndsWith(const char *line, const char *suffix) -{ - size_t a, b; - - if (!suffix || suffix[0] == '\0') - return 1; - - a = strlen(line); - b = strlen(suffix); - return (a >= b) && (strcmp(line + (a -b), suffix) == 0); -} - -static int quectel_get_sysinfo_by_uevent(const char *uevent, MODULE_SYS_INFO *pSysInfo) { - FILE *fp; - char line[MAX_PATH]; - - memset(pSysInfo, 0x00, sizeof(MODULE_SYS_INFO)); - - fp = fopen(uevent, "r"); - if (fp == NULL) { - dbg_time("fail to fopen %s, errno: %d (%s)\n", uevent, errno, strerror(errno)); - return 0; - } - - //dbg_time("%s\n", uevent); - while (fgets(line, sizeof(line), fp)) { - if (line[strlen(line) - 1] == '\n' || line[strlen(line) - 1] == '\r') { - line[strlen(line) - 1] = '\0'; - } - - //dbg_time("%s\n", line); - if (strStartsWith(line, "MAJOR=")) { - pSysInfo->MAJOR = atoi(&line[strlen("MAJOR=")]); - } - else if (strStartsWith(line, "MINOR=")) { - pSysInfo->MINOR = atoi(&line[strlen("MINOR=")]); - } - else if (strStartsWith(line, "DEVNAME=")) { - if(pSysInfo) - strncpy(pSysInfo->DEVNAME, &line[strlen("DEVNAME=")], sizeof(pSysInfo->DEVNAME)); - } - else if (strStartsWith(line, "DEVTYPE=")) { - strncpy(pSysInfo->DEVTYPE, &line[strlen("DEVTYPE=")], sizeof(pSysInfo->DEVTYPE)); - } - else if (strStartsWith(line, "PRODUCT=")) { - strncpy(pSysInfo->PRODUCT, &line[strlen("PRODUCT=")], sizeof(pSysInfo->PRODUCT)); - } - } - - fclose(fp); - - return 1; -} - -// the return value is the number of quectel modules -int auto_find_quectel_modules(char *module_sys_path, unsigned size) -{ - const char *base = "/sys/bus/usb/devices"; - DIR *busdir = NULL; - struct dirent *de = NULL; - int count = 0; - - busdir = opendir(base); - if (busdir == NULL) - return -1; - - while ((de = readdir(busdir))) { - static char uevent[MAX_PATH]; - static MODULE_SYS_INFO sysinfo; - - if (!isdigit(de->d_name[0])) continue; - - snprintf(uevent, sizeof(uevent), "%.24s/%.16s/uevent", base, de->d_name); - if (!quectel_get_sysinfo_by_uevent(uevent, &sysinfo)) - continue; - - if (sysinfo.MAJOR != 189) - continue; - - //dbg_time("MAJOR=%d, MINOR=%d, DEVNAME=%s, DEVTYPE=%s, PRODUCT=%s\n", - // sysinfo.MAJOR, sysinfo.MINOR, sysinfo.DEVNAME, sysinfo.DEVTYPE, sysinfo.PRODUCT); - - if (sysinfo.DEVTYPE[0] == '\0' || strStartsWith(sysinfo.DEVTYPE, "usb_device") == 0) - continue; - - if (sysinfo.PRODUCT[0] == '\0') { - continue; - } - - if (!(strStartsWith(sysinfo.PRODUCT, "2c7c/") - || strStartsWith(sysinfo.PRODUCT, "5c6/9008") - || strStartsWith(sysinfo.PRODUCT, "5c6/901f") - || strStartsWith(sysinfo.PRODUCT, "5c6/9091") - || strStartsWith(sysinfo.PRODUCT, "3763/3c93/318"))) { - continue; - } - - if ((strStartsWith(sysinfo.PRODUCT, "2c7c/6") || strStartsWith(sysinfo.PRODUCT, "2c7c/8")) - && (sysinfo.PRODUCT[strlen("2c7c/6000")] == '/')) //skip ASR&HISI modules - continue; - - snprintf(module_sys_path, size, "%.24s/%s", base, de->d_name); - count++; - dbg_time("[%d] %s %s\n", count, module_sys_path, sysinfo.PRODUCT); - } - - closedir(busdir); - - return count; -} - -void quectel_get_ttyport_by_syspath(const char *module_sys_path, char *module_port_name, unsigned size) { - char infname[256]; - DIR *infdir = NULL; - struct dirent *de = NULL; - - module_port_name[0] = '\0'; - - sprintf(infname, "%s:1.%d", module_sys_path, usb_dm_interface); - infdir = opendir(infname); - if (infdir == NULL) - return; - - while ((de = readdir(infdir))) { - if (strStartsWith(de->d_name, "ttyUSB")) { - snprintf(module_port_name, size, "/dev/%s", de->d_name); - break; - } - else if (!strncmp(de->d_name, "tty", strlen("tty"))) { - sprintf(infname, "%s:1.%d/tty", module_sys_path, usb_dm_interface); - closedir(infdir); - infdir = opendir(infname); - if (infdir == NULL) - break; - } - } - - if (infdir) closedir(infdir); -} - -static void quectel_fixup_sysport(const char *module_port_name, char *sysport, unsigned size) { - char syspath[MAX_PATH+16]; - const char *sys_base = "/sys/class/tty"; - DIR *sys_dir = NULL; - struct dirent *dev = NULL; - - sysport[0] = '\0'; - sys_dir = opendir(sys_base); - if (!sys_dir) { - dbg_time("fail to opendir('%s'), errno: %d (%s)\n", sys_base, errno, strerror(errno)); - return; - } - - while (NULL != (dev = readdir(sys_dir))) - { - if (!strncasecmp("ttyUSB", dev->d_name, strlen("ttyUSB"))) { - MODULE_SYS_INFO sysinfo; - - snprintf(syspath, sizeof(syspath), "%.24s/%.16s/uevent", sys_base, dev->d_name); - if (quectel_get_sysinfo_by_uevent(syspath, &sysinfo)) { - struct stat buf; - dev_t devt; - - devt = makedev(sysinfo.MAJOR, sysinfo.MINOR); - if(!stat(module_port_name, &buf) && buf.st_rdev == devt) { - snprintf(sysport, size, "/sys/class/tty/%.16s", dev->d_name); - break; - } - } - } - } - closedir(sys_dir); -} - - -void quectel_get_syspath_name_by_ttyport(const char *module_port_name, char *module_sys_path, unsigned size) { - char syspath[MAX_PATH]; - char sysport[64]; - int count; - char *pchar = NULL; - char dm_tty[24]; - - snprintf(dm_tty, sizeof(dm_tty), ":1.%d/tty", usb_dm_interface); - module_sys_path[0] = '\0'; - - snprintf(sysport, sizeof(sysport), "/sys/class/tty/%.48s", &module_port_name[strlen("/dev/")]); - if(access(sysport, F_OK) && errno == ENOENT) { - quectel_fixup_sysport(module_port_name, sysport, sizeof(sysport));//query real name - } - if(access(sysport, F_OK) && errno == ENOENT) - return; - count = readlink(sysport, syspath, sizeof(syspath) - 1); - if (count < (int)strlen(dm_tty)) - return; - -//ttyUSB0 -> ../../devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0 - pchar = strstr(syspath, dm_tty); - if (pchar == NULL) - return; - - *pchar = '\0'; - while (*pchar != '/') - pchar--; - - snprintf(module_sys_path, size, "/sys/bus/usb/devices/%.232s", pchar + 1); -} - -static void quectel_get_usb_device_info(const char *module_sys_path, struct quectel_usb_device *udev) { - static unsigned char devdesc[1024]; - size_t desclength, len; - char devname[MAX_PATH]; - int desc_fd; - __u8 bInterfaceNumber = 0; - int dev_mknod_and_delete_after_use = 0; - - MODULE_SYS_INFO sysinfo; - snprintf(devname, sizeof(devname), "%.248s/%s", module_sys_path, "uevent"); - if (!quectel_get_sysinfo_by_uevent(devname, &sysinfo)) - return; - - snprintf(devname, sizeof(devname), "/dev/%s", sysinfo.DEVNAME); - if (access(devname, R_OK) && errno_nodev()) { - //maybe Linux have create /sys/ device, but not ready to create /dev/ device. - usleep(100*1000); - } - - if (access(devname, R_OK) && errno_nodev()) - { - char *p = strstr(devname+strlen("/dev/"), "/"); - - while (p) { - p[0] = '_'; - p = strstr(p, "/"); - } - - if (mknod(devname, S_IFCHR|0666, MKDEV(sysinfo.MAJOR, sysinfo.MINOR))) { - devname[1] = 't'; - devname[2] = 'm'; - devname[3] = 'p'; - - if (mknod(devname, S_IFCHR|0666, MKDEV(sysinfo.MAJOR, sysinfo.MINOR))) { - dbg_time("Fail to mknod %s, errno : %d (%s)\n", devname, errno, strerror(errno)); - return; - } - } - - dev_mknod_and_delete_after_use = 1; - } - - desc_fd = open(devname, O_RDWR | O_NOCTTY); - - if (dev_mknod_and_delete_after_use) { - remove(devname); - } - - if (desc_fd <= 0) { - dbg_time("fail to open %s, errno: %d (%s)\n", devname, errno, strerror(errno)); - return; - } - - desclength = read(desc_fd, devdesc, sizeof(devdesc)); - len = 0; - while (len < desclength) { - struct usb_descriptor_header *h = (struct usb_descriptor_header *)(&devdesc[len]); - - if (h->bLength == sizeof(struct usb_device_descriptor) && h->bDescriptorType == USB_DT_DEVICE) { - struct usb_device_descriptor *device = (struct usb_device_descriptor *)h; - - udev->idVendor = device->idVendor; - udev->idProduct = device->idProduct; - dbg_time("P: %s idVendor=%04x idProduct=%04x\n", devname, device->idVendor, device->idProduct); - } - else if (h->bLength == sizeof(struct usb_config_descriptor) && h->bDescriptorType == USB_DT_CONFIG) { - struct usb_config_descriptor *config = (struct usb_config_descriptor *)h; - - dbg_time("C: %s bNumInterfaces: %d\n", devname, config->bNumInterfaces); - udev->bNumInterfaces = config->bNumInterfaces; - } - else if (h->bLength == sizeof(struct usb_interface_descriptor) && h->bDescriptorType == USB_DT_INTERFACE) { - struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)h; - - dbg_time("I: If#= %d Alt= %d #EPs= %d Cls=%02x Sub=%02x Prot=%02x\n", - interface->bInterfaceNumber, interface->bAlternateSetting, interface->bNumEndpoints, - interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bInterfaceProtocol); - bInterfaceNumber = interface->bInterfaceNumber; - } - else if (h->bLength == USB_DT_ENDPOINT_SIZE && h->bDescriptorType == USB_DT_ENDPOINT) { - if (bInterfaceNumber < EC20_MAX_INF) { - struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)h; - - dbg_time("E: Ad=%02x Atr=%02x MxPS= %d Ivl=%dms\n", - endpoint->bEndpointAddress, endpoint->bmAttributes, endpoint->wMaxPacketSize, endpoint->bInterval); - - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { - if (endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - udev->bulk_ep_in[bInterfaceNumber] = endpoint->bEndpointAddress; - else - udev->bulk_ep_out[bInterfaceNumber] = endpoint->bEndpointAddress; - udev->wMaxPacketSize[bInterfaceNumber] = endpoint->wMaxPacketSize; - } else if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT){ - udev->intr_ep[bInterfaceNumber] = endpoint->bEndpointAddress; - } - } - } else { - } - - len += h->bLength; - } - - if (len == desclength) { - strcpy(udev->devname, devname); - udev->desc = desc_fd; - } - - usb_dm_interface = 0; - if ((udev->bulk_ep_in[usb_dm_interface] == 0 && udev->bulk_ep_in[usb_dm_interface] == 0) - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0127) //EM05CEFC-LNV Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0514) //EG060K-EA - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0310) //EM05-CN Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x030a) //EM05-G Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0309) //EM05E-EDU Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x030d)) //EM05G-FCCL Laptop - { - - if ((udev->idVendor == 0x2c7c && udev->idProduct == 0x0127) //EM05CEFC-LNV Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0310) //EM05-CN Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x030a) //EM05-G Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x0309) //EM05E-EDU Laptop - || (udev->idVendor == 0x2c7c && udev->idProduct == 0x030d)) //EM05G-FCCL Laptop - usb_dm_interface = 3; - - if (udev->idVendor == 0x2c7c && udev->idProduct == 0x0514) //EG060K-EA - usb_dm_interface = 2; - } -} - -static int usbfs_bulk_write(struct quectel_usb_device *udev, const void *data, int len, int timeout_msec, int need_zlp) { - struct usbdevfs_urb bulk; - struct usbdevfs_urb *urb = &bulk; - int n = -1; - int bInterfaceNumber = usb_dm_interface; - - (void)timeout_msec; - //if (urb->type == 0) - { - memset(urb, 0, sizeof(struct usbdevfs_urb)); - urb->type = USBDEVFS_URB_TYPE_BULK; - urb->endpoint = udev->bulk_ep_out[bInterfaceNumber]; - } - - urb->status = -1; - urb->buffer = (void *)data; - urb->buffer_length = len; - urb->usercontext = urb; - - if (need_zlp && (len%udev->wMaxPacketSize[bInterfaceNumber]) == 0) { - //dbg_time("USBDEVFS_URB_ZERO_PACKET\n"); -#ifndef USBDEVFS_URB_ZERO_PACKET -#define USBDEVFS_URB_ZERO_PACKET 0x40 -#endif - urb->flags = USBDEVFS_URB_ZERO_PACKET; - } else { - urb->flags = 0; - } - - do { - n = ioctl(udev->desc, USBDEVFS_SUBMITURB, urb); - } while((n < 0) && (errno == EINTR)); - - if (n != 0) { - dbg_time("inf[%d] USBDEVFS_SUBMITURB %d/%d, errno = %d (%s)\n", bInterfaceNumber, n, urb->buffer_length, errno, strerror(errno)); - return -1; - } - - do { - urb = NULL; - n = ioctl(udev->desc, USBDEVFS_REAPURB, &urb); - } while((n < 0) && (errno == EINTR)); - - if (n != 0) { - dbg_time("inf[%d] ep_out %d/%d, errno = %d (%s)\n", bInterfaceNumber, n, urb->buffer_length, errno, strerror(errno)); - } - - //dbg_time("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length); - - if (urb && urb->status == 0 && urb->actual_length) - return urb->actual_length; - - return -1; -} - -static int poll_wait(int poll_fd, short events, int timeout_msec) { - struct pollfd pollfds[] = {{poll_fd, events, 0}}; - int ret; - - do { - ret = poll(pollfds, 1, timeout_msec); - } while(ret == -1 && errno == EINTR); - - if (ret == 1 && (pollfds[0].revents & (events))) - return 0; - else if (ret == 0) {//timeout - dbg_time("poll_wait events=%s msec=%d timeout\n", - (events & POLLIN) ? "POLLIN" : "POLLOUT", timeout_msec); - return ETIMEDOUT; - } - - return EIO; -} - -static int usbfs_bulk_read(struct quectel_usb_device *udev, void *pbuf, int len, int timeout) { - struct usbdevfs_bulktransfer bulk; - int n = -1; - int bInterfaceNumber = usb_dm_interface; - - if (len < 512) { - dbg_time("%s len=%d is too short\n", __func__, len); - return 0; - } - - bulk.ep = udev->bulk_ep_in[bInterfaceNumber]; - bulk.len = (len > MAX_USBFS_BULK_IN_SIZE) ? MAX_USBFS_BULK_IN_SIZE : len; - bulk.data = (void *)pbuf; - bulk.timeout = timeout; - - n = ioctl(udev->desc, USBDEVFS_BULK, &bulk); - if( n <= 0 ) { - if (errno == ETIMEDOUT) { - dbg_time("inf[%d] ep_in %d/%d, errno = %d (%s), timeout=%d\n", bInterfaceNumber, n, bulk.len, errno, strerror(errno), timeout); - n = 0; - } - else - dbg_time("inf[%d] ep_in %d/%d, errno = %d (%s)\n", bInterfaceNumber, n, bulk.len, errno, strerror(errno)); - } - - return n ; -} - -static int qtcp_connect(const char *port_name, int *idVendor, int *idProduct, int *interfaceNum) { - int fd = -1; - char *tcp_host = strdup(port_name); - char *tcp_port = strchr(tcp_host, ':'); - struct sockaddr_in sockaddr; - TLV_USB tlv_usb; - - dbg_time("%s port_name = %s\n", __func__, port_name); - - if (tcp_port == NULL) - return -1; - - *tcp_port++ = '\0'; - if (atoi(tcp_port) < 1 || atoi(tcp_port) > 0xFFFF) - return -1; - - fd = socket(AF_INET, SOCK_STREAM, 0); - - if (fd <= 0) { - dbg_time("Device could not be socket: Linux System Errno: %s\n", strerror (errno)); - return -1; - } - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sin_family = AF_INET; - sockaddr.sin_addr.s_addr = inet_addr(tcp_host); - sockaddr.sin_port = htons(atoi(tcp_port)); - - free(tcp_host); - if (connect(fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) < 0) { - close(fd); - dbg_time("Device could not be connect: Linux System Errno: %s\n", strerror (errno)); - return -1; - } - - //block read, untill usb2tcp tell me the usb device information - memset(&tlv_usb, 0x00, sizeof(tlv_usb)); - if (read(fd, &tlv_usb, sizeof(tlv_usb)) == -1) { }; - *idVendor = tlv_usb.idVendor; - *idProduct = tlv_usb.idProduct; - *interfaceNum = tlv_usb.interfaceNum; - - dbg_time("idVendor=%04x, idProduct=%04x, interfaceNum=%d\n", *idVendor, *idProduct, *interfaceNum); - - return fd; -} - -static int qtcp_read(int fd, void *pbuf, int size, int timeout_msec) { - static TLV tlv = {Q_USB2TCP_VERSION, 0}; - int cur = 0; - int len; - - if (tlv.length == 0) { - len = read(fd, &tlv, sizeof(tlv)); - if (len != sizeof(tlv)) { - dbg_time("%s read=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); - return 0; - } - - if (tlv.tag != Q_USB2TCP_VERSION) { - dbg_time("%s tlv->tag=0x%x\n", __func__, tlv.tag); - return 0; - } - } - - if (size > tlv.length) - size = tlv.length; - tlv.length -= size; - - while (cur < size) { - if (poll_wait(fd, POLLIN, timeout_msec)) - break; - - len = read(fd, (uint8_t *)pbuf+cur, size-cur); - if (len > 0) { - cur += len; - } - else { - dbg_time("%s read=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); - break; - } - } - - if (cur != size) { - dbg_time("%s cur=%d, size=%d\n", __func__, cur, size); - } - - return cur; -} - -static int qtcp_write(int fd, void*pbuf, int size, int timeout_msec) { - TLV tlv = {Q_USB2TCP_VERSION, size}; - int cur = 0; - int len; - - len = write(fd, &tlv, sizeof(tlv)); - if (len != sizeof(tlv)) { - dbg_time("%s write=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); - return 0; - } - - while (cur < size) { - if (poll_wait(fd, POLLOUT, timeout_msec)) - break; - - len = write(fd, (uint8_t *)pbuf+cur, size-cur); - if (len > 0) { - cur += len; - } - else { - dbg_time("%s write=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); - break; - } - } - - if (cur != size) { - dbg_time("%s cur=%d, size=%d\n", __func__, cur, size); - } - - return cur; -} - -struct usbfs_getdriver -{ - unsigned int interface; - char driver[255 + 1]; -}; - -struct usbfs_ioctl -{ - int ifno; /* interface 0..N ; negative numbers reserved */ - int ioctl_code; /* MUST encode size + direction of data so the - * macros in give correct values */ - void *data; /* param buffer (in, or out) */ -}; - -#define IOCTL_USBFS_DISCONNECT _IO('U', 22) -#define IOCTL_USBFS_CONNECT _IO('U', 23) - -int usbfs_is_kernel_driver_alive(int fd, int ifnum) -{ - struct usbfs_getdriver getdrv; - getdrv.interface = ifnum; - if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) { - if (errno != ENODATA) - dbg_time("%s ioctl USBDEVFS_GETDRIVER failed, errno: %d (%s)\n", __func__, errno, strerror(errno)); - return 0; - } - dbg_time("%s find interface %d has match the driver %s\n", __func__, ifnum, getdrv.driver); - return 1; -} - -void usbfs_detach_kernel_driver(int fd, int ifnum) -{ - struct usbfs_ioctl operate; - operate.data = NULL; - operate.ifno = ifnum; - operate.ioctl_code = IOCTL_USBFS_DISCONNECT; - if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { - dbg_time("%s detach kernel driver failed\n", __func__); - } else { - dbg_time("%s detach kernel driver success\n", __func__); - } -} - -#define KVERSION(j,n,p) ((j)*1000000 + (n)*1000 + (p)) -static struct utsname utsname; /* for the kernel version */ -static int ql_get_kernel_version(void) -{ - int osmaj, osmin, ospatch; - int kernel_version; - - uname(&utsname); - osmaj = osmin = ospatch = 0; - sscanf(utsname.release, "%d.%d.%d", &osmaj, &osmin, &ospatch); - kernel_version = KVERSION(osmaj, osmin, ospatch); - - return kernel_version; -} - -static int detect_xhci_usb_zero_packet_bug_not_fix(const char *module_sys_path) { - char buf[256]; - int tmp; - char *driver; - - tmp = snprintf(buf, sizeof(buf), "/sys/bus/usb/devices/usb%c/../driver", module_sys_path[strlen("/sys/bus/usb/devices/")]); - driver = buf + (++tmp); - *driver = '\0'; - - tmp = readlink(buf, driver, sizeof(buf) - tmp); - dbg_time("tmp=%s, driver=%s\n", buf, driver); - if (tmp <= 0) - return 0; - - if (!strstr(driver, "xhci")) - return 0; - - tmp = ql_get_kernel_version(); - if (tmp >= KVERSION(4,3,0)) - return 0; - - dbg_time("WARNNING ON File:%s Function:%s Line:%d\n", __FILE__, __func__, __LINE__); - dbg_time("The module attach to XHCI controller, but your kernel verison less than V4.3.0\n"); - dbg_time("Please make sure your kernel had apply patch 'usb: xhci: Add support for URB_ZERO_PACKET to bulk/sg transfers'\n"); - dbg_time("https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/drivers/usb/host/xhci-ring.c?id=4758dcd19a7d9ba9610b38fecb93f65f56f86346\n"); - sleep(2); //sleep 2 seconds, make sure FAE/customers can notice this warnning. - - return 1; -} - -void *qusb_noblock_open(const char *module_sys_path, int *idVendor, int *idProduct, int *interfaceNum) { - struct termios ios; - int retval; - int fd = -1; - struct quectel_usb_device *udev = &quectel_9x07; - - *idVendor = *idProduct = *interfaceNum = 0; - tcp_socket_fd = -1; - - if (module_sys_path && module_sys_path[0] == '/') { - char port_name[64]; - - memset(udev, 0, sizeof(struct quectel_usb_device)); - quectel_get_usb_device_info(module_sys_path, udev); - if (udev->desc <= 0) - return NULL; - quectel_get_ttyport_by_syspath(module_sys_path, port_name, sizeof(port_name)); - detect_xhci_usb_zero_packet_bug_not_fix(module_sys_path); - - *idVendor = udev->idVendor; - *idProduct = udev->idProduct; - *interfaceNum = udev->bNumInterfaces; - - if (port_name[0] == '\0' || (port_name[0] != '\0' && access(port_name, R_OK)) || (udev->idVendor == 0x05c6 && udev->idProduct == 0x9008)) { - int bInterfaceNumber = usb_dm_interface; - - if (usbfs_is_kernel_driver_alive(udev->desc, bInterfaceNumber)) { - usbfs_detach_kernel_driver(udev->desc, bInterfaceNumber); - } - retval = ioctl(udev->desc, USBDEVFS_CLAIMINTERFACE, &bInterfaceNumber); - if(retval != 0) { - dbg_time("Fail to claim interface %d, errno: %d (%s)\n", bInterfaceNumber, errno, strerror(errno)); - if (udev->idVendor == 0x05c6) { - int n; - struct { - char infname[255 * 2]; - char driver[255 * 2]; - } *pl; - const char *driver = NULL; - - pl = (typeof(pl)) malloc(sizeof(*pl)); - - snprintf(pl->infname, sizeof(pl->infname), "%.255s:1.%d/driver", module_sys_path, usb_dm_interface); - n = readlink(pl->infname, pl->driver, sizeof(pl->driver)); - if (n > 0) { - pl->driver[n] = '\0'; - while (pl->driver[n] != '/') - n--; - driver = (&pl->driver[n+1]); - } - - dbg_time("Error: when module in 'Emergency download mode', should not register any usb driver\n"); - if (driver) - dbg_time("Error: it register to usb driver ' %s ' now, should delete 05c6&9008 from the source file of this driver\n", driver); - if (driver && !strcmp(driver, "qcserial")) - dbg_time("Delete 05c6&9008 from 'drivers/usb/serial/qcserial.c' or disable qcserial from kernel config\n"); - qusb_noblock_close(udev); - free(pl); - } - return NULL; - } - - udev->ttyfd = -1; - return udev; - } - else if (!access(port_name, R_OK)) { - dbg_time("%s port_name = %s\n", __func__, port_name); - - fd = open (port_name, O_RDWR | O_SYNC); - - if (fd <= 0) { - dbg_time("Device %s could not be open: Linux System Errno: %s", port_name, strerror (errno)); - return NULL; - } - - retval = tcgetattr (fd, &ios); - if (-1 == retval) { - dbg_time("ermio settings could not be fetched Linux System Error:%s", strerror (errno)); - return NULL; - } - - cfmakeraw (&ios); - cfsetispeed(&ios, B115200); - cfsetospeed(&ios, B115200); - - retval = tcsetattr (fd, TCSANOW, &ios); - if (-1 == retval) { - dbg_time("Device could not be configured: Linux System Errno: %s", strerror (errno)); - } - udev->ttyfd = fd; - fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); - - return udev; - } - else { - dbg_time("fail to access %s errno: %d (%s)\n", port_name, errno, strerror(errno)); - } - } - else { - fd = qtcp_connect(module_sys_path, idVendor, idProduct, interfaceNum); - if (fd > 0) { - tcp_socket_fd = fd; - fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); - return &tcp_socket_fd; - } - } - - return NULL; -} - -int qusb_noblock_close(void *handle) { - struct quectel_usb_device *udev = &quectel_9x07; - - if (handle == &tcp_socket_fd) { - close(tcp_socket_fd); - tcp_socket_fd = -1; - } if (handle == udev && udev->ttyfd > 0) { - close(udev->ttyfd); - close(udev->desc); - } - else if (handle == udev && udev->desc > 0) { - int bInterfaceNumber = usb_dm_interface; - ioctl(udev->desc, USBDEVFS_RELEASEINTERFACE, &bInterfaceNumber); - close(udev->desc); - } - else if (handle == &edl_pcie_mhifd && edl_pcie_mhifd > 0) { - close(edl_pcie_mhifd); edl_pcie_mhifd = -1; - } - memset(udev, 0, sizeof(*udev)); - - return 0; -} - -int qusb_use_usbfs_interface(const void *handle) { - struct quectel_usb_device *udev = &quectel_9x07; - - return (handle == udev && udev->ttyfd <= 0 && udev->desc > 0); -} - -int qusb_noblock_read(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec) { - struct quectel_usb_device *udev = &quectel_9x07; - int cur = 0; - int poll_ret = 0; - - if (min_size == 0) - min_size = 1; - if (timeout_msec == 0) - timeout_msec = 3000; - -#if 0 //depend on your worst net speed - if (handle == &tcp_socket_fd) { - if (timeout_msec > 1000) //before sahala&firebose, we allow read timeout occurs - timeout_msec = 120*1000; - } -#endif - - while (cur < min_size) { - int len = 0; - - if (handle == &tcp_socket_fd) { - if ((poll_ret = poll_wait(tcp_socket_fd, POLLIN, timeout_msec))) - break; - len = qtcp_read(tcp_socket_fd, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec); - } - else if (handle == udev && udev->ttyfd > 0) { - if ((poll_ret = poll_wait(udev->ttyfd, POLLIN, timeout_msec))) - break; - len = read(udev->ttyfd, (uint8_t *)pbuf+cur, max_size-cur); - } - else if (handle == udev && udev->desc > 0) { - len = usbfs_bulk_read(udev, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec); - } - else if (handle == &edl_pcie_mhifd && edl_pcie_mhifd > 0) { - if ((poll_ret = poll_wait(edl_pcie_mhifd, POLLIN, timeout_msec))) - break; - len = read(edl_pcie_mhifd, (uint8_t *)pbuf+cur, max_size-cur); - } - else { - break; - } - - if (len > 0) { - cur += len; - } else { - dbg_time("%s read=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); - break; - } - } - - if (poll_ret == EIO) - return -1; - else if (poll_ret == ETIMEDOUT) - return cur; - - if (cur < min_size) { - dbg_time("%s cur=%d, min_size=%d\n", __func__, cur, min_size); - } - - return cur; -} - -int qusb_noblock_write(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec, int need_zlp) { - struct quectel_usb_device *udev = &quectel_9x07; - int cur = 0; - - if (min_size == 0) - min_size = 1; - if (timeout_msec == 0) - timeout_msec = 3000; - -#if 0 //depend on your worst net speed - if (handle == &tcp_socket_fd) { - timeout_msec = 120*1000; - } -#endif - - while (cur < min_size) { - int len = 0; - - if (handle == &tcp_socket_fd) { - if (poll_wait(tcp_socket_fd, POLLOUT, timeout_msec)) - break; - len = qtcp_write(tcp_socket_fd, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec); - } - else if (handle == udev && udev->ttyfd > 0) { - if (poll_wait(udev->ttyfd, POLLOUT, timeout_msec)) - break; - len = write(udev->ttyfd, (uint8_t *)pbuf+cur, max_size-cur); - } else if (handle == udev && udev->desc > 0) { - len = usbfs_bulk_write(udev, (uint8_t *)pbuf+cur, max_size-cur, timeout_msec, need_zlp); - } - else if (handle == &edl_pcie_mhifd && edl_pcie_mhifd > 0) { - if (poll_wait(edl_pcie_mhifd, POLLOUT, timeout_msec)) - break; - len = write(edl_pcie_mhifd, (uint8_t *)pbuf+cur, max_size-cur); - } - else { - break; - } - - if (len > 0) { - cur += len; - } else { - dbg_time("%s write=%d, errno: %d (%s)\n", __func__, len, errno, strerror(errno)); - break; - } - } - - if (cur < min_size) { - dbg_time("%s cur=%d, min_size=%d\n", __func__, cur, min_size); - } - - return cur; -} - -int qfile_find_file(const char *dir, const char *prefix, const char *suffix, char** filename) { - DIR *pdir; - struct dirent* ent = NULL; - pdir = opendir(dir); - - *filename = NULL; - if(pdir) - { - while((ent = readdir(pdir)) != NULL) - { - if (strStartsWith(ent->d_name, prefix) && strEndsWith(ent->d_name, suffix)) - { - dbg_time("find '%s'\n", ent->d_name); - *filename = strdup(ent->d_name); - break; - } - } - } - - closedir(pdir); - return *filename != NULL; -} - -const char * firehose_get_time(void) { - static char time_buf[50]; - struct timeval tv; - static int s_start_msec = -1; - int now_msec, cost_msec; - - gettimeofday (&tv, NULL); - now_msec = tv.tv_sec * 1000; - now_msec += (tv.tv_usec + 500) / 1000; - - if (s_start_msec == -1) { - s_start_msec = now_msec; - } - - cost_msec = now_msec - s_start_msec; - - sprintf(time_buf, "[%03d.%03d]", cost_msec/1000, cost_msec%1000); - return time_buf; -} - -// void dbg_time (const char *fmt, ...) { -// va_list args; -// va_start(args, fmt); -// static char line[2048]; -// snprintf(line, sizeof(line), "%s ", firehose_get_time()); -// vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, args); -// fprintf(stdout, "%s", line); -// fflush(stdout); -// } - -int qpcie_open(const char *firehose_dir, const char *firehose_mbn) { - int bhifd, edlfd, diagfd; - long ret; - FILE *fp; - BHI_INFO_TYPE *bhi_info = malloc(sizeof(BHI_INFO_TYPE)); - char prog_firehose_sdx24[256+32]; - size_t filesize; - void *filebuf; - - snprintf(prog_firehose_sdx24, sizeof(prog_firehose_sdx24), "%.255s/%s", firehose_dir, firehose_mbn); - fp = fopen(prog_firehose_sdx24, "rb"); - if (fp ==NULL) { - dbg_time("fail to fopen %s, errno: %d (%s)\n", prog_firehose_sdx24, errno, strerror(errno)); - error_return(); - } - - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fseek(fp, 0, SEEK_SET); - - filebuf = malloc(sizeof(filesize)+filesize); - memcpy(filebuf, &filesize, sizeof(filesize)); - if (fread((uint8_t *)filebuf+sizeof(filesize), 1, filesize, fp) == (size_t)0) { }; - fclose(fp); - - diagfd = open("/dev/mhi_DIAG", O_RDWR | O_NOCTTY); - if (diagfd > 0) - { - int edl_retry = 30; //SDX55 require long time by now 20190412 - void *usb_handle = &edl_pcie_mhifd; - edl_pcie_mhifd = diagfd; - - while (access("/dev/mhi_DIAG", R_OK) == 0 && edl_retry-- > 0) { - dbg_time("switch_to_edl_mode\n"); - switch_to_edl_mode(usb_handle); - sleep(1); - } - - close(diagfd); - edl_pcie_mhifd = -1; - } - - sleep(1); //see https://ticket.quectel.com/browse/FAE-39737 - bhifd = open("/dev/mhi_BHI", O_RDWR | O_NOCTTY); - if (bhifd <= 0) { - dbg_time("fail to open %s, errno: %d (%s)\n", "/dev/mhi_BHI", errno, strerror(errno)); - error_return(); - } - - ret = ioctl(bhifd, IOCTL_BHI_GETDEVINFO, bhi_info); - if (ret) { - dbg_time("fail to ioctl IOCTL_BHI_GETDEVINFO, errno: %d (%s)\n", errno, strerror(errno)); - error_return(); - } - - dbg_time("bhi_ee = %d\n", bhi_info->bhi_ee); - if (bhi_info->bhi_ee != MHI_EE_EDL) { - dbg_time("bhi_ee is not MHI_EE_EDL\n"); - close(bhifd); - free(filebuf); - error_return(); - } - free(bhi_info); - - ret = ioctl(bhifd, IOCTL_BHI_WRITEIMAGE, filebuf); - if (ret) { - dbg_time("fail to ioctl IOCTL_BHI_GETDEVINFO, errno: %d (%s)\n", errno, strerror(errno)); - error_return(); - } - - close(bhifd); - free(filebuf); - - sleep(1); - edlfd = open("/dev/mhi_EDL", O_RDWR | O_NOCTTY); - if (edlfd <= 0) { - dbg_time("fail to access %s, errno: %d (%s)\n", "/dev/mhi_EDL", errno, strerror(errno)); - error_return(); - } - - edl_pcie_mhifd = edlfd; - - return 0; -} - -int usbmon_fd = -1; -int usbmon_logfile_fd = -1; - -void *catch_log(void *arg) -{ - int nreads = 0; - char tbuff[256]; - size_t off = strlen("[999.999] "); - - (void)arg; - tbuff[off - 1] = ' '; - while(1) { - nreads = read(usbmon_fd, tbuff + off, sizeof(tbuff) - off); - if (nreads == -1 && errno == EINTR) - continue; - if (nreads <= 0) - break; - - tbuff[off + nreads] = '\0'; - memcpy(tbuff, firehose_get_time(), off - 1); - - if (write(usbmon_logfile_fd, tbuff, strlen(tbuff)) == -1) { }; - } - - return NULL; -} - -int ql_capture_usbmon_log(const char* usbmon_logfile) -{ - const char *usbmon_path = "/sys/kernel/debug/usb/usbmon/0u"; - pthread_t pt; - pthread_attr_t attr; - - if (access("/sys/kernel/debug/usb", F_OK)) { - dbg_time("debugfs is not mount, please execute \"mount -t debugfs none_debugs /sys/kernel/debug\"\n"); - return -1; - } - if (access("/sys/kernel/debug/usb/usbmon", F_OK)) { - dbg_time("usbmon is not load, please execute \"modprobe usbmon\" or \"insmod usbmon.ko\"\n"); - return -1; - } - - usbmon_fd = open(usbmon_path, O_RDONLY); - if (usbmon_fd < 0) { - dbg_time("open %s error(%d) (%s)\n", usbmon_path, errno, strerror(errno)); - return -1; - } - - usbmon_logfile_fd = open(usbmon_logfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (usbmon_logfile_fd < 0) { - dbg_time("open %s error(%d) (%s)\n", usbmon_logfile, errno, strerror(errno)); - close(usbmon_fd); - return -1; - } - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&pt, &attr, catch_log, NULL); - - return 0; -} - -void ql_stop_usbmon_log() -{ - if (usbmon_logfile_fd > 0) - close(usbmon_logfile_fd); - if (usbmon_fd > 0) - close(usbmon_fd); -} diff --git a/rooter/0optionalapps/qfirehose/src/usb_linux.h b/rooter/0optionalapps/qfirehose/src/usb_linux.h deleted file mode 100644 index 881e49c..0000000 --- a/rooter/0optionalapps/qfirehose/src/usb_linux.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef __QFIREHOSE_USB_LINUX_H__ -#define __QFIREHOSE_USB_LINUX_H__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_PATH 256 -#define MIN(a,b) ((a) < (b)? (a) : (b)) - -typedef struct module_sys_info { -/* -MAJOR=189 -MINOR=1 -DEVNAME=bus/usb/001/002 -DEVTYPE=usb_device -DRIVER=usb -PRODUCT=2c7c/415/318 -TYPE=239/2/1 -BUSNUM=001 -*/ - //char sys_path[MAX_PATH]; - int MAJOR; - int MINOR; - char DEVNAME[64]; - char DEVTYPE[64]; - char PRODUCT[64]; -}MODULE_SYS_INFO; - -void * qusb_noblock_open(const char *module_sys_path, int *idVendor, int *idProduct, int *interfaceNum); -int qusb_noblock_close(void *handle); -int qusb_noblock_write(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec, int need_zlp); -int qusb_noblock_read(const void *handle, void *pbuf, int max_size, int min_size, int timeout_msec); -int qfile_find_file(const char *dir, const char *prefix, const char *suffix, char** filename); -#define errno_nodev() (errno == ENOENT || errno == ENODEV) -// void dbg_time (const char *fmt, ...); -const char * firehose_get_time(void); -extern FILE *loghandler; -#ifdef FH_DEBUG -#define dbg_time(fmt, args...) \ - do \ - { \ - fprintf(stdout, "[%15s-%04d]%s: " fmt, __FILE__, __LINE__, firehose_get_time(), ##args); \ - fflush(stdout); \ - if (loghandler) \ - fprintf(loghandler, "[%15s-%04d]%s: " fmt, __FILE__, __LINE__, firehose_get_time(), ##args); \ - } while (0); -#else -#define dbg_time(fmt, args...) \ - do \ - { \ - fprintf(stdout, "%s: " fmt, firehose_get_time(), ##args); \ - fflush(stdout); \ - if (loghandler) \ - fprintf(loghandler, "%s: " fmt, firehose_get_time(), ##args); \ - } while (0); -#endif -double get_now(); -void get_duration(double start); -int update_transfer_bytes(long long bytes_cur); -void set_transfer_allbytes(long long bytes); -int auto_find_quectel_modules(char *module_sys_path, unsigned size); -void quectel_get_syspath_name_by_ttyport(const char *module_port_name, char *module_sys_path, unsigned size); -void quectel_get_ttyport_by_syspath(const char *module_sys_path, char *module_port_name, unsigned size); -#define error_return() do {dbg_time("%s %s %d fail\n", __FILE__, __func__, __LINE__); return __LINE__; } while(0) - -extern int edl_pcie_mhifd; - -#define IOCTL_BHI_GETDEVINFO 0x8BE0 + 1 -#define IOCTL_BHI_WRITEIMAGE 0x8BE0 + 2 - -typedef unsigned int ULONG; - -typedef struct _bhi_info_type -{ - ULONG bhi_ver_minor; - ULONG bhi_ver_major; - ULONG bhi_image_address_low; - ULONG bhi_image_address_high; - ULONG bhi_image_size; - ULONG bhi_rsvd1; - ULONG bhi_imgtxdb; - ULONG bhi_rsvd2; - ULONG bhi_msivec; - ULONG bhi_rsvd3; - ULONG bhi_ee; - ULONG bhi_status; - ULONG bhi_errorcode; - ULONG bhi_errdbg1; - ULONG bhi_errdbg2; - ULONG bhi_errdbg3; - ULONG bhi_sernum; - ULONG bhi_sblantirollbackver; - ULONG bhi_numsegs; - ULONG bhi_msmhwid[6]; - ULONG bhi_oempkhash[48]; - ULONG bhi_rsvd5; -}BHI_INFO_TYPE, *PBHI_INFO_TYPE; - -enum MHI_EE { - MHI_EE_PBL = 0x0, /* Primary Boot Loader */ - MHI_EE_SBL = 0x1, /* Secondary Boot Loader */ - MHI_EE_AMSS = 0x2, /* AMSS Firmware */ - MHI_EE_RDDM = 0x3, /* WIFI Ram Dump Debug Module */ - MHI_EE_WFW = 0x4, /* WIFI (WLAN) Firmware */ - MHI_EE_PT = 0x5, /* PassThrough, Non PCIe BOOT (PCIe is BIOS locked, not used for boot */ - MHI_EE_EDL = 0x6, /* PCIe enabled in PBL for emergency download (Non PCIe BOOT) */ - MHI_EE_FP = 0x7, /* FlashProg, Flash Programmer Environment */ - MHI_EE_BHIE = MHI_EE_FP, - MHI_EE_UEFI = 0x8, /* UEFI */ - - MHI_EE_DISABLE_TRANSITION = 0x9, - MHI_EE_MAX -}; -int qpcie_open(const char *firehose_dir, const char *firehose_mbn); - -#define Q_USB2TCP_VERSION 0x12345678 -typedef struct { - int tag; - int length; - int value[]; -} TLV; - -typedef struct { - int tag; - int length; - int idVendor; - int idProduct; - int interfaceNum; -} TLV_USB; -#endif diff --git a/rooter/0optionalapps/qlog/Makefile b/rooter/0optionalapps/qlog/Makefile deleted file mode 100644 index cef8271..0000000 --- a/rooter/0optionalapps/qlog/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (C) 2011-2014 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=qlog -PKG_RELEASE:=1 - -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk - -define Package/qlog - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Quectel Qlog - MAINTAINER:=Dairyman -endef - -define Package/qlog/description - Quectel Qlog -endef - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) \ - CC="$(TARGET_CC)" \ - CFLAGS="$(TARGET_CFLAGS) -Wall" -endef - -define Package/qlog/install - $(INSTALL_DIR) $(1)/usr/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/QLog $(1)/usr/bin/QLog - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,qlog)) diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T1.LinuxData-OTA-DataService-AP_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T1.LinuxData-OTA-DataService-AP_V01.cfg deleted file mode 100644 index f66248605d6bcf956dd5140a7b95d7359a1d5104..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2012 zcmb1@v94pN_)zC<#Ky48x2|TgXPwMctvVhNtGeW;3+uf385nja)Om9pvutE-J=WdMT`M<5$$1qjFh@y$*UpOpb5 zEf2)!mV@~04D3+;`!68A7K0X)4|F|{ufw1N<+p`^_>K&YP(GU}h#$ca0p%-(g7{Gk zQBXbu8;IW_yh0daAIQ#u#NMqS_pB0L1$EESKXt`GCxO7NMlh2Z$Yca!V_-CW05KR2 z06D-IWH=z4zyOj3fdgO}2pdicz*!&$8w!s&&hP*K|J$P|l|bR);D9Z507_zW6%IW_ z3I7143wCEQc*uZ~k^!-{G{^+OHG&dcD=$%&GB7kSK$9$X^$sNX6E#k-n>Xx48}R#x zr0}z9fyW^zF<5isHycS7ZyX}28)ae-0hVu1;6V=x^>=sz6qF@-46vI+4^fc)ECw?^ q!W|6C>Q4yR%<-bKE`dQPt1f|Yc6D77P<0+2FA^|}7Samer0M{1B6I=( diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T2.RegServ-CotextAct_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T2.RegServ-CotextAct_V01.cfg deleted file mode 100644 index 8645a8a5d3c2e76fe9e28ae30754b735ac060f44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2260 zcmds2T}TvB6h5=R+Lj}$h{f8jgdvf#Xd!8^NiWIPgM}zbWD14#pkhRs%@`8)ScLUZ zSP}FiJ@h0}Q4(Yjlob`#gR4m?S~(H1h3lTqnVs1kCs*txr~{XCzVmm_d^7h>j;Bn5 z!-^Cva=`6vQu~<-$Q*bQzCdk-k{ zZ=5mAJ&X%Y{#AvX-|rf9#qtnkkPS6xu#J7pc25)cxg_=yN#+;|dT#-c20(J?a}4{r z?qtUGjNj|bef|axp5S?UGkUdo9!3~@@>b_*^ASNZaT1`#nrA|dd)3CTv2P@o>s?irMd%pZBR}#%u{eSl!dY~2NI~n9PBx5^2Ff|a zK*Hrnm;eJZz(GX-7? zNcPqDapL&&`WHJyhi7}dkk7a~4S?C#rTGE|BHur4CW#lL)FCAjUD>R~Y_I?P%0{;wS*LUo)SL5Uq MR&+~s;NCC&0_5W$wg3PC diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T3.SimpleData-(TCPUDP)_V01.cfg deleted file mode 100644 index 6289c58433222df1cc878ef6fd4c05bf5b949289..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2144 zcmds2TSydP6h5<8Wo<`RA1qef7eOLwyJ2auN-xP2VG%xrWCaDiq}YSke>NoSF$n9S z=t2*r^w3Kp79~Okfo(*A^x!H|l6D!0*uZs9=giLRjFTHd5Y$=z`ObaLoc}-nmWOKv zbZA1^;)BusqUTbB2oJ0mMWr?3#JgKUkpUjI2&E9<_^?n403LrNkl^Gup?Cnw8wg~0 z^PD`(K)ODtqsx1ha065=2qm-=7P|>{!67d}H7v~%)WVUy1lvJ*MNk8MjRa7z_Oj@0 z_JU4l>xrjVFjdehy~nZ_*v#^aJ1omU73y-=eU>8-G33T!mS6f``?GeAv9IRdW_FnJ zPZo!2O|u-XtgHkm<6a=DDq)NkBiDp(t9JJ38045hm0U$O za$q0(x;Q7=NyYT`oX%1LpeDgM9X(BoPaIR9MPREugP6o+3~VNohVIEe_5s*o`~ZTW zT|tcLTKy5USb#Ayyhk-Nox(GVya}t*60S%=PW%y`IG4VHIsl@ULSuVf+N~FEssEh& zPDcZ1#XDU_vN}fn!Hh;nj4O=$ponFITn*K^Uh*VG^M0@yVPHIbFc--47NREdhM3fP z4P)t4oA)RyxHgkCY~p#$l08C8QA@uj5Ir;Vh~+f3#im;xY<1`*$;#|7{S%_S8+!lR zB-q21JNierjY0MZ>fb!35-Rm?PS*QpdgViBeGVT3i`7&5~{8B+9 zy;}dV+PC1(enMJ{SP_taxNJ@U=6PPB{O<%jVw6~`m!J*VIN{?v@5+NQ$$7h5Rw%X)I*9rXsdTNB<#H` zs3@zK@(&0xF%c>VV*4<#9$H08(mnFcQ$R5#iu~~!$szq^GgE;p7mQWRd2W>)K190@dP>TS@J`qT8{JT&+02R#y z3cP+w%yN)!+%wSSy+&9ARr5j(Zi9t5!FD*{C8&qR8G=SQw2Pn))RzPe(6^5Oiq>5g zy{%p_?yMhOrFW&*e!u*KhGG zZ0&7j!jwE^5|Tl-hyBC;+{BlzvOVG-C0jEm;ow)N*gvQYQjIvlVVUjQ$`IMs;3(yE zBn45XMrh8X#hHJh^lqumx8nW=s^>YMq0%8UpGQXFLXk)WAjIoN)HK26zs*imQ|=+s{01Wp6|$0n6KShDyOe1%e4WUb>Wcd_;Rv37eH^#1t-}eg6~w6FH9i4b1sJD}52$6|rSbFvZ$M#L#AQPei8s-cpd+(fx&UfzkIwzE zjN3@ucK^BdgN_AIOLV);!D5WYhZWsCW(gk@vu%p2xjtV@zAd$@F4&4NF%jCI59BKs zq$2W$SkitSqnUJv_b@v+H%oMEp;Sz9M(AlO>9-`JXL=5?0uuQJRKGb)CpD_ytYXy9Vy%Y!7CJ?eTs@HARi3nkrpk8q zk2_g~b^IEp>s+Y*Snr#cb4$qRm5%7uFPDP^V4de>&i~H96F$%mZpl}l_xOwX|79)q zCT({%ko80XA+>>?(abb;oeh4Rl*6eRR}o?|oBlkypq2Eec26jQHS{oAqILi7&9)+b xjXavCc5ghN@LF;-k(Vwp;vGuSz4S1JX^EbF>d8HehGq~@lhzN2HVB>+KLG)M5y=1m diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T5.COMMON-T1T4_V01.cfg deleted file mode 100644 index 57d1346c1f017cebaf587a8e647a1cbe6f51d251..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4226 zcmeHJe`u6-7=PaTZ8vw`%`xY0+{Vxyk#aU;=0=xNGC&vQ-pSR2LIRMXoBFB9I z$FC8S;Dz7ixC@}Ng;)T7{F*EmfYke;;12gY#2Y71Lus;a?Q0x&K9pI+T;^t7IV`f! zF@`>L0#dWX({P0SYhj7zZ@?-RnPGVs>~1qDIQiR4S^1mvhsA^%!JT=T z?Jhg7IVVp%+pYMR_1B#@NRLg_hOqCWxh(tMJM6XgL6f{jVENR4%Ad7IR0<{tE$|yL z>iynrocBv5 zDmGM1&T-%h>jo-LTj-|BH++nJtHRaceB8C-{A-Rhle6$|W1HpGYpU}$Q^lQa{rVM* zAzBlwDa4TE`$D_;c`fUC?-Lhkc+p~dF$ftc6>SYOXBoNW>=7qKzpI+_4A-8o&Fh5! z6l*h7!G8W|AWCt`!R+(;1=cr48%fW)*kvAXjlQCd&G!G~_;4xbJ`_DV3%U19$UEqB zn10$Lx>Qu4#{itAr>QC>PCcWXu7bM2C}I-tpnn;uRCIp3mu=|Y*M0!SpuUBC_3Kou zcbE^7;u0#EkrZwl=S$d{Zeu|RGFm{*mEb9%40)nQPK-wh5lUsfl5q;)EFP}oe~o{8^a;+`4B()Fq#`{r7-7N#MeW3iSnmO6y(3pmdTT?> z_LGHE{x1=JGUvz-_7EY{atou5cd;p*+U|auM~qG<63BuV+mM)`lGZ>)x>-*yQeW$>o@(YsS4qX*S*3{yi2)$c+;)K9mvpc2mf5>1`|=Wc5=sjX K%Iy%^EdL2@L%Z|< diff --git a/rooter/0optionalapps/qlog/files/usr/lib/conf/T6.FullMessage.SimpleLogPacket(AT)_V01.cfg b/rooter/0optionalapps/qlog/files/usr/lib/conf/T6.FullMessage.SimpleLogPacket(AT)_V01.cfg deleted file mode 100644 index 19499f09c185247ea6f928c1d5eca898a1cdd7c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4191 zcmeHJeMnPL6hAhnD>d7u=-9+$m?J7y7MV(}|B?|=LKz~AiXagaicr(HNlHZoffYrd z_FtLw@lQmFETRtzDuO_Yl*-UbOz8v3=yuNay}kMNo}11JsypsGpTBd?&b{xxn_(*u zpk_pHuZV*i8-)6nV!?KDv5=UOFYI`GPH-m!-1G?Uxd7X*32p;G_Yjg8*!4wl#{y&& zBT0s55709mVp=b7I!AvN=@M|f7u=>b@ZkWGLMYKASq&hWON7sX zr6OJ}KVc7jC%;_SsF5c)KE?1V{20sBtRWby#qTbq{9B3+)c=F4;O7>yh zN3^pdoR3-C#U#=_iSLP5$1sK7&TF}za5rJXpE2*G1!5}o2iGX^t$QeMdvXW9W0Fpy z(#B!PFf4#mv5sCR;Z7J|8bfgs{y&}E8zWz{KI1@yJ$v+mdOT)~$I~a;UUtS(ti$H> z=ICQZTMOac%~Vf^xkIey4nK_QQ;((s6rnwuSa=b=U4v_-cZA{w>(qGinXRc7 zpLE^`>d?aeE`93&t&u2(#TG7K z&lSQhv}M`kxF!7jb7i^^%<<*qvodQ_mh2NQ?rht)P@W22m}%c49zIj?hM8^?#)nycz&aX%sg4Dd+#!}rBZx4n=kNL_!BIp#{G?BC3^5P)Obc#Aqla4#3*L4njwd>y*6?`Ky$puNAfAPI^dN384@@n|{RBEbiXl(H6 zAxfpVHmP5@)JVJ@;f_o{9e!!MI?F1dk3){gPS6BzlmYrU4<;<06hn!l0&jjZ(h?39 zy>WiVLD%GsIU*>|Q(1@XA0F4H_C>#Ca{ZgQZ*p2zXrvETNY^nT z3f>%_3^bWO2+rVli>VnHtmg+KO&R*(`xO^P3e>q=hG=q!UzeQRFc+tp-U%-7&xeu| zHb+=Rm|fhGbr%sbJ_pPNM=@Z@6BqK(YLJ?{;MXjd`6gf3Rr^seO+4JT2AdmjS`NrX zM2%mBdyHnQk OzmmD03yw%5ln zgc%G=7Czzg;V0IVzPcti_oi)rTJ!`+#QfniF8ke!mL!>d9%`IEUHOIUGF%{JUjPV#Mt9LKjlca1y}dwI5vY z{lM{=BQXyF3UD91Bbu0?KkDXaA!5AhJjUfbdMvCNba5_PV(duu=n2Z$``dsE<`m2^b9MCqXXoYR$+_fu zZ+VoHF5_kh7%`qwMP(tP_TSLUk?-U!h?O4Q8g{|{Tz(tdC!6uV^?$Hk+sY|{zTaVp zoV>9|;#`LjwU?;;Q&@wQ!zb4_4?D1Zycei%Cj_Fq<&PAF%F`oiW^|RI=SO-%FnGC@ z#HBzaCd5180M1Ke5b*6`Aw)&?Y_hm!vLw2pq;@ktM17VnHrR3NPuMG)0e&mt$bi8)+}ispAf7EOB+YBaIhCy||JK1+?p>mC-yG^^FyxwP!YV zQZ)$+m5$}~-|6|IViXBwaanR!aKYDdi5Ueg9qZdSFO4aD+JaC&2?~ib3Gr$k5$8qs z@N!=og@01SO;;PQiEy!{(#U2>)!vvg&tGn=LFRt-{H-19jl$=}r5>Mx`E%9&l3X72 zUdwlK>hg>gf^TWQT?1)2|3;H2vJa@{TE-&Y6e~W`u7h0H;dA4=i0AnbK71@W`#kX! z;t8@Rk9wjFtn0V-^G)xgvvb)$hD~0UU;Tj1T@%I{h#$W^*HT*(Af@r%@Y@B+XxJ9T z9PNcS*yl(ton_fl&dS5wC}^C@h%Smm_beMJ^F3M}xu4eRl+Grtl?@MPz;Qgn?K3fT z@x{or`y$?NTzV{FwbHkH#XZrAD?UyWALAp_#Xg&9S`#vR)nvW z6nt3d0@@Sk%M=#Qc)+;i!aNJXzqs$>UtMO&tDb+Aygv<%)%1e qOeYVMMZbK-sW<6GbNLLrHtDzR;h9$sTFv{`PD3iKplGgltM)ggN57;1 diff --git a/rooter/0optionalapps/qlog/src/Makefile b/rooter/0optionalapps/qlog/src/Makefile deleted file mode 100644 index b5b7daa..0000000 --- a/rooter/0optionalapps/qlog/src/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -SOURCES = main.c asr.c mdm.c tty2tcp.c sahara.c - -linux: clean - ${CC} $(SOURCES) $(CFLAGS) -Wall -o QLog -lpthread -ldl - -clean: - rm -rf QLog *.exe *.dSYM *.obj *.exp .*o *.lib *~ libs out - diff --git a/rooter/0optionalapps/qlog/src/asr.c b/rooter/0optionalapps/qlog/src/asr.c deleted file mode 100644 index af54c56..0000000 --- a/rooter/0optionalapps/qlog/src/asr.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "qlog.h" - -struct CSDLFileHeader -{ - uint32_t dwHeaderVersion;//0x0 - uint32_t dwDataFormat;//0x1 - uint32_t dwAPVersion; - uint32_t dwCPVersion; - uint32_t dwSequenceNum;//ļţ0ʼ - uint32_t dwTime;//Total seconds from 1970.1.1 0:0:0 - uint32_t dwCheckSum;//0x0 -}; - -int g_is_asr_chip = 0; - -ssize_t asr_send_cmd(int ttyfd, const unsigned char *buf, size_t size) { - ssize_t wc = 0; - - while (wc < size) { - uint32_t *cmd_data = (uint32_t *)(buf+wc); - unsigned cmd_len = qlog_le32(cmd_data[0]); - //unsigned i; - - if (cmd_len > (size - wc)) - break; - - //qlog_dbg("Send CMD to UE: "); - //for(i=0; i ../../devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1:1.0/ttyUSB0/tty/ttyUSB0 - pchar = strstr(syspath, ":1.0/tty"); //MDM - if (pchar == NULL) { - pchar = strstr(syspath, ":1.2/tty"); //ASR - g_is_asr_chip = (pchar != NULL); - } - if (pchar == NULL) { - qlog_dbg("%s is not a usb-to-serial device?\n", ttyport); - return; - } - - *pchar = '\0'; - while (*pchar != '/') - pchar--; - - strcpy(sysport, pchar + 1); - - snprintf(syspath, sizeof(syspath), "/sys/bus/usb/devices/%s/idVendor", sysport); - fd = open(syspath, O_RDONLY); - if (fd <= 0) { - qlog_dbg("Fail to open %s, errno: %d (%s)\n", syspath, errno, strerror(errno)); - return; - } - read(fd, idVendor, 4); - close(fd); - - snprintf(syspath, sizeof(syspath), "/sys/bus/usb/devices/%s/idProduct", sysport); - fd = open(syspath, O_RDONLY); - if (fd <= 0) { - qlog_dbg("Fail to open %s, errno: %d (%s)\n", syspath, errno, strerror(errno)); - return; - } - read(fd, idProduct, 4); - close(fd); - - snprintf(syspath, sizeof(syspath), "/sys/bus/usb/devices/%s/bNumInterfaces", sysport); - fd = open(syspath, O_RDONLY); - if (fd <= 0) { - qlog_dbg("Fail to open %s, errno: %d (%s)\n", syspath, errno, strerror(errno)); - return; - } - read(fd, bNumInterfaces, 4); - close(fd); - - qlog_dbg("%s idVendor=%s, idProduct=%s, bNumInterfaces=%d\n", __func__, idVendor, idProduct, atoi(bNumInterfaces)); -} - -static unsigned long get_now_msec() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec*1000 + tv.tv_usec / 1000; -} - -static size_t ql_tty_read(int fd, void *buf, size_t size) -{ - size_t rc; - - rc = read(fd,buf,size); - - if (rc > 0) { - static size_t total_read = 0; - static unsigned long now_msec = 0; - unsigned long n = get_now_msec(); - - if (now_msec == 0) - now_msec = get_now_msec(); - total_read += rc; - - if ((total_read >= (4*1024*1024)) || (n >= (now_msec + 5000))) { - qlog_dbg("recv: %zdM %zdK %zdB in %ld msec\n", total_read/(1024*1024), - total_read/1024%1024,total_read%1024, n-now_msec); - now_msec = n; - total_read = 0; - } - } - - return rc; -} - -ssize_t qlog_poll_write(int fd, const void *buf, size_t size, unsigned timeout_msec) { - ssize_t wc = 0; - ssize_t nbytes; - - nbytes = write(fd, buf+wc, size-wc); - - if (nbytes <= 0) { - if (errno != EAGAIN) { - qlog_dbg("Fail to write fd = %d, errno : %d (%s)\n", fd, errno, strerror(errno)); - goto out; - } - else { - nbytes = 0; - } - } - - wc += nbytes; - - while (wc < size) { - int ret; - struct pollfd pollfds[] = {{fd, POLLOUT, 0}}; - - ret = poll(pollfds, 1, timeout_msec); - - if (ret <= 0) { - qlog_dbg("Fail to poll fd = %d, errno : %d (%s)\n", fd, errno, strerror(errno)); - break; - } - - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - qlog_dbg("Fail to poll fd = %d, revents = %04x\n", fd, pollfds[0].revents); - break; - } - - if (pollfds[0].revents & (POLLOUT)) { - nbytes = write(fd, buf+wc, size-wc); - - if (nbytes <= 0) { - qlog_dbg("Fail to write fd = %d, errno : %d (%s)\n", fd, errno, strerror(errno)); - break; - } - wc += nbytes; - } - } - -out: - if (wc != size) { - qlog_dbg("%s fd=%d, size=%zd, timeout=%d, wc=%zd\n", __func__, fd, size, timeout_msec, wc); - } - - return (wc); -} - -static int qlog_logfile_create(const char *logfile_dir, const char *logfile_suffix, unsigned logfile_seq) { - int logfd; - time_t ltime; - char shortname[32]; - char filename[255+1]; - struct tm *currtime; - - //delete old logfile - if (s_logfile_num && s_logfile_List[logfile_seq%s_logfile_num][0]) { - sprintf(filename, "%s/%s.%s", logfile_dir, s_logfile_List[logfile_seq%s_logfile_num], logfile_suffix); - if (access(filename, R_OK) == 0) { - remove(filename); - } - } - - time(<ime); - currtime = localtime(<ime); - snprintf(shortname, sizeof(shortname), "%04d%02d%02d_%02d%02d%02d_%04d", - (currtime->tm_year+1900), (currtime->tm_mon+1), currtime->tm_mday, - currtime->tm_hour, currtime->tm_min, currtime->tm_sec, logfile_seq); - sprintf(filename, "%s/%s.%s", logfile_dir, shortname, logfile_suffix); - - logfd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0444); - if (logfd <= 0) { - qlog_dbg("Fail to create new logfile! errno : %d (%s)\n", errno, strerror(errno)); - } - - qlog_dbg("%s %s logfd=%d\n", __func__, filename, logfd); - - if (s_logfile_num) { - strcpy(s_logfile_List[logfile_seq%s_logfile_num], shortname); - } - - return logfd; -} - -static size_t qlog_logfile_save(int logfd, const void *buf, size_t size) { - return qlog_poll_write(logfd, buf, size, 1000); -} - -static int qlog_logfile_close(int logfd) { - return close(logfd); -} - -static void* qlog_logfile_init_filter_thread(void* arg) { - void **thread_args = (void **)arg; - qlog_ops_t *qlog_ops = (qlog_ops_t *)thread_args[0]; - int *ttyfd = (int *)thread_args[1]; - const char *filter_cfg = ( const char *)thread_args[2]; - - if (qlog_ops->init_filter) - qlog_ops->init_filter(*ttyfd, filter_cfg); - - return NULL; -} - -static int qlog_handle(int ttyfd, const char *logfile_dir, size_t logfile_size, unsigned logfile_num, const char *filter_cfg) { - ssize_t savelog_size = 0; - void *rbuf; - const size_t rbuf_size = (16*1024); - static int logfd = -1; - unsigned logfile_seq = 0; - const char *logfile_suffix = g_is_asr_chip ? "sdl" : "qmdl"; - static qlog_ops_t qlog_ops; - pthread_t thread_id; - pthread_attr_t thread_attr; - const void *thread_args[3]; - - if (logfile_dir[0] == '9' && atoi(logfile_dir) >= 9000) { - filter_cfg = logfile_dir; - qlog_ops = tty2tcp_qlog_ops; - } - else { - qlog_ops = g_is_asr_chip ? asr_qlog_ops : mdm_qlog_ops; - if (access(logfile_dir, F_OK) && errno == ENOENT) - mkdir(logfile_dir, 0755); - } - - if (!qlog_ops.logfile_create) - qlog_ops.logfile_create = qlog_logfile_create; - if (!qlog_ops.logfile_save) - qlog_ops.logfile_save = qlog_logfile_save; - if (!qlog_ops.logfile_close) - qlog_ops.logfile_close = qlog_logfile_close; - - rbuf = malloc(rbuf_size); - if (rbuf == NULL) { - qlog_dbg("Fail to malloc rbuf_size=%zd, errno: %d (%s)\n", rbuf_size, errno, strerror(errno)); - return -1; - } - - thread_args[0] = &qlog_ops; - thread_args[1] = &ttyfd; - thread_args[2] = filter_cfg; - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - pthread_create(&thread_id, &thread_attr, qlog_logfile_init_filter_thread, (void*)thread_args); - - while(1) { - ssize_t rc, wc; - int ret; - struct pollfd pollfds[] = {{ttyfd, POLLIN, 0}}; - - ret = poll(pollfds, 1, -1); - - if (ret <= 0) { - qlog_dbg("poll(ttyfd) =%d, errno: %d (%s)\n", ret, errno, strerror(errno)); - break; - } - - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - qlog_dbg("ttyfd revents = %04x\n", pollfds[0].revents); - break; - } - - if (pollfds[0].revents & (POLLIN)) { - rc = ql_tty_read(ttyfd, rbuf, rbuf_size); - - if(rc > 0) { - if (logfd == -1) { - logfd = qlog_ops.logfile_create(logfile_dir, logfile_suffix, logfile_seq); - if (logfd <= 0) { - break; - } - if (qlog_ops.logfile_init) - qlog_ops.logfile_init(logfd, logfile_seq); - logfile_seq++; - } - - wc = qlog_ops.logfile_save(logfd, rbuf, rc); - - if (wc != rc) { - qlog_dbg("savelog fail %zd/%zd, break\n", wc, rc); - break; - } - - savelog_size += wc; - - if (savelog_size >= logfile_size) { - savelog_size = 0; - qlog_ops.logfile_close(logfd); - logfd = -1; - } - } - else - { - qlog_dbg("ttyfd recv %zd Bytes. break\n", rc); - break; - } - } - } - - if (logfd > 0) - qlog_ops.logfile_close(logfd); - free(rbuf); - - return 0; -} - -static void ql_sigaction(int signal_num) { - qlog_dbg("recv signal %d\n", signal_num); -} - -static void qlog_usage(const char *self, const char *dev) { - qlog_dbg("Usage: %s -p -s -f filter_cfg -n -b \n", self); - qlog_dbg("Default: %s -p %s -s %s -n %d -b %d to save log to local disk\n", - self, dev, ".", LOGFILE_NUM, LOGFILE_SIZE_DEFAULT/1024/1024); - qlog_dbg(" -p ttyport to catch log, default is '/dev/ttyUSB0'\n"); - qlog_dbg(" -s where to save log, default is '.' \n"); - qlog_dbg(" if set as '9000', QLog will run as TCP Server Mode, and let 'QPST/QWinLog/CATStudio' to connect!\n"); - qlog_dbg(" -f filter cfg for catch log, can be found in directory 'conf'. if not set this arg, will use default filter conf\n"); - qlog_dbg(" and UC200T&EC200T do not need filter cfg.\n"); - qlog_dbg(" -n max num of log file to save, range is '0~512'. default is 0. 0 means no limit.\n"); - qlog_dbg(" or QLog will auto delete oldtest log file if exceed max num\n"); - qlog_dbg(" -m max size of single log file, unit is MBytes, range is '2~512', default is 128\n"); - - qlog_dbg("\nFor example: %s -p /dev/ttyUSB0 -w .\n", self); -} - -int main(int argc, char **argv) -{ - int opt; - char ttyname[32] = "/dev/ttyUSB0"; - int ttyfd = -1; - const char *logfile_dir = "./"; - const char *filter_cfg = NULL; - size_t logfile_size = LOGFILE_SIZE_DEFAULT; - unsigned logfile_num = LOGFILE_NUM; - char idVendor[5] = "0000"; - char idProduct[5] = "0000"; - char bNumInterfaces[5] = "0"; - - qlog_dbg("QLog Version: Quectel_QLog_Linux&Android_V1.3\n"); //when release, rename to V1.X - - optind = 1; //call by popen(), optind mayby is not 1 - while ( -1 != (opt = getopt(argc, argv, "d:p:s:w:n:m:b:f:c:h"))) { - switch (opt) { - case 'p': - if (optarg[0] == 't') //ttyUSB0 - snprintf(ttyname, sizeof(ttyname), "/dev/%s", optarg); - else if (optarg[0] == 'U') //USB0 - snprintf(ttyname, sizeof(ttyname), "/dev/tty%s", optarg); - else if (optarg[0] == '/') - snprintf(ttyname, sizeof(ttyname), "%s", optarg); - else { - qlog_dbg("unknow dev %s\n", optarg); - } - break; - case 's': - logfile_dir = optarg; - break; - case 'n': - logfile_num = atoi(optarg); - if (logfile_num < 0) - logfile_num = 0; - else if (logfile_num > LOGFILE_NUM) - logfile_num = LOGFILE_NUM; - s_logfile_num = logfile_num; - break; - case 'm': - logfile_size = atoi(optarg)*1024*1024; - if (logfile_size < LOGFILE_SIZE_MIN) - logfile_size = LOGFILE_SIZE_MIN; - else if (logfile_size > LOGFILE_SIZE_MAX) - logfile_size = LOGFILE_SIZE_MAX; - break; - case 'f': - filter_cfg = optarg; - break; - case 'b': - case 'c': //unused - break; - default: - qlog_usage(argv[0], ttyname); - return 0; - break; - } - } - - signal(SIGTERM, ql_sigaction); - signal(SIGHUP, ql_sigaction); - signal(SIGINT, ql_sigaction); - - ttyfd = open (ttyname, O_RDWR | O_NDELAY | O_NOCTTY); - - if (ttyfd <= 0) { - qlog_dbg("Fail to open %s, errno : %d (%s)\n", ttyname, errno, strerror(errno)); - return -1; - } - - qlog_dbg("open %s ttyfd = %d\n", ttyname, ttyfd); - - if ( ttyfd > 0 ) { - struct termios ios; - - memset(&ios, 0, sizeof(ios)); - tcgetattr( ttyfd, &ios ); - cfmakeraw(&ios); - cfsetispeed(&ios, B115200); - cfsetospeed(&ios, B115200); - tcsetattr( ttyfd, TCSANOW, &ios ); - } - - if (strncmp(ttyname, "/dev/mhi", strlen("/dev/mhi"))) { - qlog_get_vidpid_by_ttyport(ttyname, idVendor, idProduct, bNumInterfaces); - } - else { - if (!strcmp(ttyname, "/dev/mhi_DIAG")) { - strcpy(idVendor, "2c7c"); - strcpy(bNumInterfaces, "5"); //log mode - } - else if (!strcmp(ttyname, "/dev/mhi_SAHARA")) { - strcpy(idVendor, "2c7c"); - strcpy(bNumInterfaces, "1"); //dump mode - } - } - - qlog_dbg("Press CTRL+C to stop catch log.\n"); - - if (g_is_asr_chip == 0 && atoi(bNumInterfaces) == 1) { - if (access(logfile_dir, F_OK) && errno == ENOENT) - mkdir(logfile_dir, 0755); - sahara_catch_dump(ttyfd, logfile_dir, 1); - } - else if (atoi(bNumInterfaces) > 1) { - qlog_handle(ttyfd, logfile_dir, logfile_size, logfile_num, filter_cfg); - } - else { - qlog_dbg("unknow state! quit!\n"); - } - - close(ttyfd); - - return 0; -} diff --git a/rooter/0optionalapps/qlog/src/mdm.c b/rooter/0optionalapps/qlog/src/mdm.c deleted file mode 100644 index 42d1adf..0000000 --- a/rooter/0optionalapps/qlog/src/mdm.c +++ /dev/null @@ -1,203 +0,0 @@ -#include "qlog.h" - -static unsigned char qlog_mdm_default_cfg[] = { -0x1d,0x1c,0x3b,0x7e,0x00,0x78,0xf0,0x7e,0x4b,0x32,0x06,0x00,0xba,0x4d,0x7e,0x7c,0x93,0x49,0x7e,0x1c,0x95,0x2a,0x7e,0x0c,0x14,0x3a,0x7e,0x63,0xe5,0xa1,0x7e,0x4b, -0x0f,0x00,0x00,0xbb,0x60,0x7e,0x4b,0x09,0x00,0x00,0x62,0xb6,0x7e,0x4b,0x08,0x00,0x00,0xbe,0xec,0x7e,0x4b,0x08,0x01,0x00,0x66,0xf5,0x7e,0x4b,0x04,0x00,0x00,0x1d, -0x49,0x7e,0x4b,0x04,0x0f,0x00,0xd5,0xca,0x7e,0x4b,0x0f,0x18,0x00,0x01,0x9e,0xa9,0x7e,0x4b,0x0f,0x18,0x00,0x02,0x05,0x9b,0x7e,0x4b,0x0f,0x2c,0x00,0x28,0xea,0x7e, -0x4b,0x12,0x39,0x00,0xeb,0x7b,0x7e,0x4b,0x12,0x3c,0x00,0x53,0x05,0x7e,0x4b,0x12,0x37,0x00,0xfb,0xe1,0x7e,0x4b,0x12,0x3b,0x00,0x5b,0x48,0x7e,0x4b,0x12,0x35,0x00, -0x4b,0xd2,0x7e,0x4b,0x12,0x3a,0x00,0x83,0x51,0x7e,0x4b,0x12,0x00,0x08,0x19,0x96,0x7e,0x7d,0x5d,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x41,0x7e,0x7d,0x5d,0x04, -0x00,0x00,0x02,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x4c,0x06,0x7e,0x7d,0x5d,0x04,0x05,0x00,0x05,0x00,0x00,0x00,0x1f,0x00, -0x00,0x00,0xce,0xa7,0x7e,0x7d,0x5d,0x04,0x07,0x00,0x08,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xd0,0x71,0x7e,0x7d,0x5d,0x04,0x0b,0x00,0x0c,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x7c,0x68,0x7e,0x7d,0x5d,0x04,0x0e,0x00,0x12,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xb5,0x3a,0x7e,0x7d,0x5d,0x04,0x14,0x00,0x15,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x2e,0xbb, -0x7e,0x7d,0x5d,0x04,0x19,0x00,0x19,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x88,0xd0,0x7e,0x7d,0x5d,0x04,0x20,0x00,0x20,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xea,0xaa, -0x7e,0x7d,0x5d,0x04,0x27,0x00,0x28,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xfe,0x01,0x00,0x00,0x89,0x11,0x7e,0x7d,0x5d,0x04,0x2a,0x00,0x2b,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x01,0x1a,0x7e,0x7d,0x5d,0x04,0x33,0x00,0x33,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0xc2,0xc1,0x7e,0x7d,0x5d,0x04,0x36,0x00,0x36,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0xa3,0xd6,0x7e,0x7d,0x5d,0x04,0x39,0x00,0x3a,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x65,0xdf,0x7e,0x7d,0x5d,0x04, -0x3f,0x00,0x41,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0xfe,0xff,0x1f,0x00,0x1f,0x00,0x00,0x00,0xc9,0x67,0x7e,0x7d,0x5d,0x04,0x44,0x00,0x45,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x2e,0x6c,0x7e,0x7d,0x5d,0x04,0x48,0x00,0x4a,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x4f,0xf2, -0x7e,0x7d,0x5d,0x04,0x4c,0x00,0x4c,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xf2,0x66,0x7e,0x7d,0x5d,0x04,0x4e,0x00,0x4e,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x11,0x0f, -0x7e,0x7d,0x5d,0x04,0x58,0x00,0x58,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x9a,0x49,0x7e,0x7d,0x5d,0x04,0x5a,0x00,0x5b,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x0e,0x43,0x7e,0x7d,0x5d,0x04,0x63,0x00,0x63,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xd9,0x60,0x7e,0x7d,0x5d,0x04,0x70,0x00,0x70,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x4a,0x17,0x7e,0x7d,0x5d,0x04,0x75,0x00,0x75,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc8,0x6d,0x7e,0x7d,0x5d,0x04,0xea,0x03,0xea,0x03,0x00,0x00,0x1e,0x00, -0x00,0x00,0xa9,0x9e,0x7e,0x7d,0x5d,0x04,0xee,0x03,0xef,0x03,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x9b,0x20,0x7e,0x7d,0x5d,0x04,0xd0,0x07,0xd7,0x07, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0xdc,0x10,0x7e,0x7d,0x5d,0x04,0xb8,0x0b,0xc5,0x0b,0x00,0x00,0x1f,0x00,0x00,0x00,0xfe,0xff,0x7f,0x00,0x7f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1f,0x00, -0x00,0x00,0xff,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1c,0x00,0x00,0x00,0xa9,0x36,0x7e,0x7d,0x5d,0x04,0xa0,0x0f,0xaa,0x0f,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0xfe,0x01,0x00,0x00,0x1e,0x00,0x00,0x00,0xfe,0xff,0x01,0x00,0xfe,0xff,0x07,0x00,0xfe,0xff,0x01,0x00,0xfe,0x07,0x00,0x00,0x1e,0x00,0x00,0x00,0xc3,0xb9, -0x7e,0x7d,0x5d,0x04,0x05,0x12,0x05,0x12,0x00,0x00,0x1f,0x00,0x00,0x00,0xd2,0x41,0x7e,0x7d,0x5d,0x04,0x07,0x12,0x07,0x12,0x00,0x00,0x1f,0x00,0x00,0x00,0xf3,0x12, -0x7e,0x7d,0x5d,0x04,0x88,0x13,0xa8,0x13,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xf4,0x4c,0x7e,0x7d,0x5d,0x04,0x72,0x17,0x72,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0xcc,0x20, -0x7e,0x7d,0x5d,0x04,0x74,0x17,0x74,0x17,0x00,0x00,0x3f,0x00,0x00,0x00,0x47,0x46,0x7e,0x7d,0x5d,0x04,0x93,0x17,0x93,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0x8f,0xca, -0x7e,0x7d,0x5d,0x04,0x97,0x17,0x97,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0xcd,0x6c,0x7e,0x7d,0x5d,0x04,0xa4,0x17,0xb7,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00, -0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x8d,0xd1,0x7e,0x7d,0x5d,0x04,0xc0,0x17,0xc0,0x17,0x00,0x00,0x1e,0x00,0x00,0x00,0x96,0x89,0x7e,0x7d,0x5d,0x04, -0x34,0x21,0x34,0x21,0x00,0x00,0x1e,0x00,0x00,0x00,0x10,0xc3,0x7e,0x7d,0x5d,0x04,0x1c,0x25,0x25,0x25,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0xff,0x1f,0x00,0x7d,0x5e, -0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x7d,0x5e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0xfe,0x03,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x3e,0xd0,0x00,0x00, -0x90,0xed,0x7e,0x7d,0x5d,0x04,0x0b,0x28,0x0f,0x28,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x1c,0x00,0x00,0x00, -0x71,0x86,0x7e,0x7d,0x5d,0x04,0x6e,0x28,0x89,0x28,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, -0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, -0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00, -0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x52,0x90,0x7e,0x73, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xda,0x81,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xfe,0x0f,0x00,0x00,0xf0,0x07,0xc8,0x00,0x00,0x40, -0xc4,0x00,0x00,0x00,0x00,0xc0,0x49,0xf3,0xc7,0x5b,0x7c,0xf3,0x0b,0x01,0x00,0x00,0x00,0x20,0xec,0x00,0xcc,0x83,0x01,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00, -0x38,0x00,0x38,0x00,0x00,0x01,0x01,0x00,0x40,0x08,0xf0,0x07,0x0c,0xf8,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x00,0xff,0xf7,0x7f,0xf0,0xfc,0xff,0xff,0xad,0xe0,0x7f,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, -0xe0,0xff,0xff,0xff,0x48,0x1c,0x1e,0x00,0x03,0x10,0x18,0xff,0xff,0xff,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x90,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x80,0x1b,0x80,0xff,0x5f,0x06,0x00,0x00,0x41,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xc0,0x07,0x01,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x10,0x00,0x80,0x00,0x00,0x7f,0xce,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00, -0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xf8,0x07,0x00,0x00,0x00, -0x07,0x00,0x00,0xc0,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x30,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xb7,0xb2,0x7e,0x73,0x00,0x00, -0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x09,0x08,0x00,0x00,0x31,0x00,0x09,0x80,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xef,0x20,0xf0,0x90,0x3c,0x1d,0x60,0x04,0x00,0x00,0x4f,0x03,0xfe,0x07,0x43,0x0b,0x02, -0x01,0x00,0x00,0x07,0xf4,0x45,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x86,0x8a,0x45,0xf8,0x25,0x10,0x00,0xcc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xc3,0x1e,0x00,0x7d,0x5e,0x00,0x4e,0x00,0xff,0x03,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x32,0x3e,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x5d, -0x0c,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x90,0x6f,0x3b,0xfc,0x01,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0xff,0xd7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0xf0,0xff,0xe7,0xff,0xbf,0xf3,0x43,0x3f,0x02,0x00,0xe0,0xe3,0x01,0xff,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x90,0x6f,0x1f,0xfc,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0xff,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0xe0,0xe7,0xff,0xf7,0xc3,0x3f,0x01,0x00,0xe0,0xe3,0x01,0x10,0x5d,0xe6,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x57,0x0b, -0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x01,0x00,0x7f,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0xff,0x37,0x06,0xea,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0xfc,0xf0,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x01,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x77,0x00,0x00,0x7f,0x9f,0xaa,0x7e,0x73,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0xd0,0x01,0x00,0x00, -0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0xce,0x04,0xce,0x00,0x3f,0x00,0x3f,0x00,0xdf,0x24,0x00,0x00,0x7f,0xfc,0x3c,0x00, -0x00,0x00,0x3e,0x28,0x4e,0x50,0x05,0x12,0x51,0xe0,0x00,0x00,0xff,0xff,0xff,0xe2,0xcf,0xe1,0x7d,0x5d,0x51,0x7f,0x00,0x01,0x74,0x42,0xe0,0xac,0x34,0x7e,0x73,0x00, -0x00,0x00,0x03,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x39,0x01,0x00,0x00,0x79,0xa6,0xff,0xff,0xff,0xa1,0x1f,0x00,0xdf,0x01,0x00,0x00,0x03,0x40,0x00,0x00,0x00,0x9f, -0x00,0x00,0x00,0x00,0xc0,0x06,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0xff,0x37,0xff,0xbf,0x1b,0x05,0x00,0x01,0x2b,0x17,0x7e,0x60,0x00,0x12,0x6a,0x7e,0x60,0x01, -0x9b,0x7b,0x7e,0x82,0x00,0x00,0x00,0x55,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xb7,0x0f,0x00,0x00,0x00,0x00,0x00,0x88,0xf4,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x04,0x00,0xd8,0x8f,0xff,0x3d,0xf8,0x48,0xfa,0x3f,0x06,0x00,0x00,0x19,0x00,0x00,0x00,0x0a,0xe0,0x0f,0x22,0x00,0x00,0x00,0xf8,0x84,0x2f,0x40,0x00,0x00, -0x0a,0x80,0xff,0xef,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0xe0,0x01,0xff,0x3f,0x82,0x00,0x01, -0x7d,0x5e,0x00,0x00,0x80,0xff,0x00,0x00,0x00,0x00,0xbe,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x0f,0xfe,0x7f,0x00,0x18,0x00,0x00,0x00,0xe0,0x01,0x00,0x00, -0xc0,0xfd,0xbf,0x95,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xc0,0x3f,0x12,0x8c,0x04,0x00,0x60,0xc8, -0x2f,0xf8,0xe7,0xf9,0xff,0x7f,0xff,0xff,0x07,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,0xfc,0x6f,0x00,0xc7,0x9f,0x00,0x03,0x80,0xf9,0xfa,0x0f,0x80, -0x7b,0x80,0x37,0x24,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x23,0x8c, -0x0d,0x00,0x00,0x01,0x98,0x04,0x00,0x30,0x00,0x00,0x00,0x00,0x06,0x00,0xf2,0x07,0x00,0x44,0x00,0xf8,0x1f,0x20,0x73,0x7e -}; - -extern int tty2tcp_sockfd; -ssize_t mdm_send_cmd(int ttyfd, const unsigned char *buf, size_t size) { - size_t wc = 0; - - while (wc < size) { - size_t flag = wc; - const unsigned char *cur = buf + wc; - unsigned short len = cur[2] + (((unsigned short)cur[3]) << 8) + 5; - - if (cur[0] == 0x7e && cur[1] == 0x01 && (wc + len) <= size && cur[len - 1] == 0x7e) { - flag += (len - 1); - } - else { - if (flag == 0 && buf[flag] == 0x7E) - flag++; - - while (buf[flag] != 0x7E && flag < size) - flag++; - } - - if (buf[flag] == 0x7E || flag == size) - qlog_poll_write(ttyfd, buf + wc, flag - wc + 1, 1000); - - if (tty2tcp_sockfd > 0 && (flag + 1) < size) { - size_t i = 0; - qlog_dbg("size=%zd, cur=%zd\n", size, flag - wc + 1); - for (i = 0; i < 16; i++) - printf("%02x", buf[i+wc]); - printf("\n"); - } - - wc = flag + 1; - } - - return size; -} - -static int mdm_init_filter(int ttyfd, const char *cfg) { - unsigned char *rbuf; - const size_t rbuf_size = (16*1024); - size_t cfg_size = 0; - -#if 0 - if (cfg == NULL) { - const unsigned char mdm_enter_dump1[] = { - 0x4b, 0x12, 0x18, 0x02, 0x01, 0x00, 0xd2, 0x7e - }; - const unsigned char mdm_enter_dump2[] = { - 0x7e, 0x01, 0x04, 0x00, 0x4b, 0x25, 0x03, 0x00, 0x7e - }; - qlog_dbg("send mdm dump command\n"); - mdm_send_cmd(ttyfd, mdm_enter_dump1, sizeof(mdm_enter_dump1)); - usleep(100*1000); - mdm_send_cmd(ttyfd, mdm_enter_dump2, sizeof(mdm_enter_dump2)); - return 0; - } -#endif - - rbuf = (unsigned char *)malloc(rbuf_size); - if (rbuf == NULL) { - qlog_dbg("Fail to malloc rbuf_size=%zd, errno: %d (%s)\n", rbuf_size, errno, strerror(errno)); - return -1; - } - - if (cfg) { - int cfgfd = open(cfg, O_RDONLY); - if (cfgfd < 0) { - qlog_dbg("Fail to open %s, errno : %d (%s)\n", cfg, errno, strerror(errno)); - } - - cfg_size = read(cfgfd, rbuf, rbuf_size); - close(cfgfd); - } - - if (cfg_size <= 0) { - cfg_size = sizeof(qlog_mdm_default_cfg); - memcpy(rbuf, qlog_mdm_default_cfg, cfg_size); - } - - mdm_send_cmd(ttyfd, rbuf, cfg_size); - - free(rbuf); - - return 0; -} - -qlog_ops_t mdm_qlog_ops = { - .init_filter = mdm_init_filter, -}; diff --git a/rooter/0optionalapps/qlog/src/qlog.h b/rooter/0optionalapps/qlog/src/qlog.h deleted file mode 100644 index 6ff8266..0000000 --- a/rooter/0optionalapps/qlog/src/qlog.h +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include -#ifndef __QUECTEL_QLOG_H -#define __QUECTEL_QLOG_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef unsigned int uint32_t; - -typedef struct { - int (*init_filter)(int ttyfd, const char *conf); - int (*logfile_create)(const char *logfile_dir, const char *logfile_suffix, unsigned logfile_seq); - int (*logfile_init)(int logfd, unsigned logfile_seq); - size_t (*logfile_save)(int logfd, const void *buf, size_t size); - int (*logfile_close)(int logfd); -} qlog_ops_t; - -extern qlog_ops_t mdm_qlog_ops; -extern qlog_ops_t asr_qlog_ops; -extern qlog_ops_t tty2tcp_qlog_ops; -extern int g_is_asr_chip; -extern ssize_t asr_send_cmd(int ttyfd, const unsigned char *buf, size_t size); -extern ssize_t mdm_send_cmd(int ttyfd, const unsigned char *buf, size_t size); - -extern uint32_t qlog_le32 (uint32_t v32); -extern uint64_t qlog_le64 (uint64_t v64); -extern ssize_t qlog_poll_write(int fd, const void *buf, size_t size, unsigned timeout_mesc); - -extern unsigned qlog_msecs(void); -#define qlog_dbg(fmt, arg... ) do { unsigned msec = qlog_msecs(); printf("[%03d.%03d]" fmt, msec/1000, msec%1000, ## arg); } while (0) - int sahara_catch_dump(int port_fd, const char *path_to_save_files, int do_reset); -#endif diff --git a/rooter/0optionalapps/qlog/src/sahara.c b/rooter/0optionalapps/qlog/src/sahara.c deleted file mode 100644 index 347f3df..0000000 --- a/rooter/0optionalapps/qlog/src/sahara.c +++ /dev/null @@ -1,660 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -unsigned int inet_addr(const char *cp); - -/* modify macro MIN -* usually we difine it as: (a) < (b) ? (a) : (b) -* but it will cause some problems, here is a case: -* MIN(i++, j++), when calling the macro above, i++ will be run two times, which is wrong. -* so we can modify it as following. -* (void)(&_a == &_b); is use to check wether the type of 'a' and 'b' is same or not. -* (void) is used to eliminated warnning. -*/ -#define MIN(a, b) ({ \ - typeof(a) _a = a; \ - typeof(b) _b = b; \ - (void)(&_a == &_b); \ - _a < _b ? _a : _b; \ - }) - -#include "sahara_protocol.h" -#include "qlog.h" - -sahara_data_t sahara_data = { - NULL, // rx_buffer - NULL, // tx_buffer - NULL, // misc_buffer - SAHARA_WAIT_HELLO, // state - 0, // timed_data_size - -1, // fd - -1, // ram_dump_image - 5, // max_ram_dump_retries - SAHARA_RAW_BUFFER_SIZE, // max_ram_dump_read - SAHARA_MODE_LAST, // mode - SAHARA_MODE_LAST, // prev_mode - 0, // command - false // ram_dump_64bit -}; - -typedef struct { - char *port_name; - int port_fd; - int rx_timeout; - size_t MAX_TO_READ; - size_t MAX_TO_WRITE; -} com_port_t; - -static com_port_t com_port = { - "/dev/ttyUSB0", // port_name - -1, // port_fd - 5, // rx_timeout - 1024 * 64, - 1024 * 64, -}; - -typedef struct { - const char *path_to_save_files; - int verbose; - int do_reset; -} kickstart_options_t; - -static kickstart_options_t kickstart_options = { - NULL, // path_to_save_files - 1, // verbose - 1, -}; - -enum LOG_LEVEL { -LOG_DEBUG = 1, -LOG_EVENT, -LOG_INFO, -LOG_STATUS, -LOG_WARN, -LOG_ERROR -}; - -extern unsigned qlog_msecs(void); -#define dbg( log_level, fmt, arg... ) do {if (kickstart_options.verbose || LOG_ERROR == log_level) { unsigned msec = qlog_msecs(); printf("[%03d.%03d]" fmt "\n", msec/1000, msec%1000, ## arg);}} while (0) - -static bool port_tx_data (void *buffer, size_t bytes_to_send) { - int temp_bytes_sent; - size_t bytes_sent = 0; - - while (bytes_sent < bytes_to_send) { - do { - temp_bytes_sent = write (com_port.port_fd, buffer + bytes_sent, MIN(bytes_to_send - bytes_sent, com_port.MAX_TO_WRITE)); - if (-1 == temp_bytes_sent && (errno == EINTR || errno == EAGAIN)) { - sleep(1); - } else { - break; - } - } while(1); - - if (temp_bytes_sent <= 0) { - dbg(LOG_ERROR, "Write returned failure %d, errno %d, System error code: %s", temp_bytes_sent, errno, strerror (errno)); - return false; - } - else { - bytes_sent += temp_bytes_sent; - } - } - - return true; -} - -static bool port_rx_data(void *buffer, size_t bytes_to_read, size_t *bytes_read) { - fd_set rfds; - struct timeval tv; - int retval; - - // Init read file descriptor - FD_ZERO (&rfds); - FD_SET (com_port.port_fd, &rfds); - - // time out initializtion. - tv.tv_sec = com_port.rx_timeout >= 0 ? com_port.rx_timeout : 0; - tv.tv_usec = 0; - - retval = select (com_port.port_fd + 1, &rfds, NULL, NULL, ((com_port.rx_timeout >= 0) ? (&tv) : (NULL))); - if (retval <= 0) { - dbg(LOG_ERROR, "select returned error: %s", strerror (errno)); - return false; - } - - retval = read (com_port.port_fd, buffer, MIN(bytes_to_read, com_port.MAX_TO_READ)); - if (retval <= 0) { - dbg(LOG_ERROR, "Read/Write File descriptor returned error: %s, error code %d", strerror (errno), retval); - return false; - } - - if (NULL != bytes_read) - *bytes_read = retval; - - return true; -} - -static bool sahara_tx_data (size_t bytes_to_send) { - return port_tx_data(sahara_data.tx_buffer, bytes_to_send); -} - -static bool sahara_rx_data(size_t bytes_to_read) { - sahara_packet_header* command_packet_header = NULL; - size_t temp_bytes_read = 0, bytes_read = 0; - - const char *boot_sahara_cmd_id_str[SAHARA_LAST_CMD_ID] = { - "SAHARA_NO_CMD_ID", // = 0x00, - " SAHARA_HELLO_ID", // = 0x01, // sent from target to host - "SAHARA_HELLO_RESP_ID", // = 0x02, // sent from host to target - "SAHARA_READ_DATA_ID", // = 0x03, // sent from target to host - "SAHARA_END_IMAGE_TX_ID", // = 0x04, // sent from target to host - "SAHARA_DONE_ID", // = 0x05, // sent from host to target - "SAHARA_DONE_RESP_ID", // = 0x06, // sent from target to host - "SAHARA_RESET_ID", // = 0x07, // sent from host to target - "SAHARA_RESET_RESP_ID", // = 0x08, // sent from target to host - "SAHARA_MEMORY_DEBUG_ID", // = 0x09, // sent from target to host - "SAHARA_MEMORY_READ_ID", // = 0x0A, // sent from host to target - "SAHARA_CMD_READY_ID", // = 0x0B, // sent from target to host - "SAHARA_CMD_SWITCH_MODE_ID", // = 0x0C, // sent from host to target - "SAHARA_CMD_EXEC_ID", // = 0x0D, // sent from host to target - "SAHARA_CMD_EXEC_RESP_ID", // = 0x0E, // sent from target to host - "SAHARA_CMD_EXEC_DATA_ID", // = 0x0F, // sent from host to target - "SAHARA_64_BITS_MEMORY_DEBUG_ID", // = 0x10, // sent from target to host - "SAHARA_64_BITS_MEMORY_READ_ID", // = 0x11, // sent from host to target - "SAHARA_64_BITS_READ_DATA_ID", // = 0x12, - }; - - if (0 == bytes_to_read) { - command_packet_header = (sahara_packet_header *) sahara_data.rx_buffer; - memset(command_packet_header, 0x00, sizeof(sahara_packet_header)); - - if (false == port_rx_data(sahara_data.rx_buffer, sizeof(sahara_packet_header), &temp_bytes_read)) - return false; - - dbg(LOG_INFO, "Read %zd bytes, command %d and packet length %d bytes", temp_bytes_read, qlog_le32(command_packet_header->command), qlog_le32(command_packet_header->length)); - if (temp_bytes_read != sizeof(sahara_packet_header)) - return false; - - if (qlog_le32(command_packet_header->command) < SAHARA_LAST_CMD_ID) { - dbg(LOG_EVENT, "RECEIVED <-- %s", boot_sahara_cmd_id_str[qlog_le32(command_packet_header->command)]); - if (false == port_rx_data(sahara_data.rx_buffer + sizeof(sahara_packet_header), qlog_le32(command_packet_header->length) - sizeof(sahara_packet_header), &temp_bytes_read)) - return false; - if (temp_bytes_read != (qlog_le32(command_packet_header->length) - sizeof(sahara_packet_header))) { - dbg(LOG_INFO, "Read %zd bytes", temp_bytes_read + sizeof(sahara_packet_header)); - return false; - } - } else { - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_CMD_UNKONOW_%d", qlog_le32(command_packet_header->command)); - return false; - } - } - else { - while (bytes_read < bytes_to_read) { - if (false == port_rx_data(sahara_data.rx_buffer + bytes_read, bytes_to_read - bytes_read, &temp_bytes_read)) { - dbg(LOG_ERROR, "bytes_read = %zd, bytes_to_read = %zd", bytes_read, bytes_to_read); - return false; - } else - bytes_read += temp_bytes_read; - } - } - - return true; -} - -static int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y) { - // Perform the carry for the later subtraction by updating y. - if (x->tv_usec < y->tv_usec) { - int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } - if (x->tv_usec - y->tv_usec > 1000000) { - int nsec = (x->tv_usec - y->tv_usec) / 1000000; - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } - - // Compute the time remaining to wait. tv_usec is certainly positive. */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; - - // Return 1 if result is negative. - return x->tv_sec < y->tv_sec; -} - -static void time_throughput_calculate(struct timeval *start_time, struct timeval *end_time, size_t size_bytes) -{ - struct timeval result; - double TP = 0.0; - - if (size_bytes == 0) { - dbg(LOG_INFO, "Cannot calculate throughput, size is 0"); - return; - } - timeval_subtract(&result, end_time, start_time); - - TP = (double)result.tv_usec/1000000.0; - TP += (double)result.tv_sec; - - if(TP>0.0) - { - TP = (double)((double)size_bytes/TP)/(1024.0*1024.0); - dbg(LOG_STATUS, "%zd bytes transferred in %ld.%06ld seconds (%.4fMBps)", size_bytes, result.tv_sec, result.tv_usec,TP); - } - else - dbg(LOG_STATUS, "%zd bytes transferred in %ld.%06ld seconds", size_bytes, result.tv_sec, result.tv_usec); -} - -static bool send_reset_command () -{ - sahara_packet_reset *sahara_reset = (sahara_packet_reset *)sahara_data.tx_buffer; - sahara_reset->header.command = qlog_le32(SAHARA_RESET_ID); - sahara_reset->header.length = qlog_le32(sizeof(sahara_packet_reset)); - - /* Send the Reset Request */ - dbg(LOG_EVENT, "SENDING --> SAHARA_RESET"); - if (false == sahara_tx_data (sizeof(sahara_packet_reset))) { - dbg(LOG_ERROR, "Sending RESET packet failed"); - return false; - } - - return true; -} - -static bool send_memory_read_packet (uint64_t memory_table_address, uint64_t memory_table_length) { - sahara_packet_memory_read *sahara_memory_read = (sahara_packet_memory_read *)sahara_data.tx_buffer; - sahara_packet_memory_read_64bit *sahara_memory_read_64bit = (sahara_packet_memory_read_64bit *)sahara_data.tx_buffer; - - dbg(LOG_EVENT, "SENDING --> SAHARA_MEMORY_READ, address 0x%08"PRIX64", length 0x%08"PRIX64, memory_table_address, memory_table_length); - - if (true == sahara_data.ram_dump_64bit) { - sahara_memory_read_64bit->header.command = qlog_le32(SAHARA_64_BITS_MEMORY_READ_ID); - sahara_memory_read_64bit->header.length = qlog_le32(sizeof(sahara_packet_memory_read_64bit)); - sahara_memory_read_64bit->memory_addr = qlog_le64(memory_table_address); - sahara_memory_read_64bit->memory_length = qlog_le64(memory_table_length); - - /* Send the Memory Read packet */ - if (false == sahara_tx_data (sizeof(sahara_packet_memory_read_64bit))) { - dbg(LOG_ERROR, "Sending MEMORY_READ packet failed"); - return false; - } - } else { - sahara_memory_read->header.command = qlog_le32(SAHARA_MEMORY_READ_ID); - sahara_memory_read->header.length = qlog_le32(sizeof(sahara_packet_memory_read)); - sahara_memory_read->memory_addr = qlog_le32((uint32_t)memory_table_address); - sahara_memory_read->memory_length = qlog_le32((uint32_t)memory_table_length); - - /* Send the Memory Read packet */ - if (false == sahara_tx_data (sizeof(sahara_packet_memory_read))) { - dbg(LOG_ERROR, "Sending MEMORY_READ packet failed"); - return false; - } - } - - return true; -} - -static bool is_valid_memory_table(uint64_t memory_table_size) -{ - if (true == sahara_data.ram_dump_64bit && memory_table_size % sizeof(dload_debug_type_64bit) == 0) { - return true; - } - else if (false == sahara_data.ram_dump_64bit && memory_table_size % sizeof(dload_debug_type) == 0) { - return true; - } - else { - return false; - } -} - -static bool sahara_start(void) { - int retval = 0; - int num_debug_entries = -1; - int i = 0; - uint64_t memory_table_addr = 0; - uint64_t memory_table_length = 0; - - struct timeval time_start, time_end; - - sahara_packet_hello *sahara_hello = (sahara_packet_hello *)sahara_data.rx_buffer; - sahara_packet_hello_resp *sahara_hello_resp = (sahara_packet_hello_resp *)sahara_data.tx_buffer; - sahara_packet_memory_debug *sahara_memory_debug = (sahara_packet_memory_debug *)sahara_data.rx_buffer; - sahara_packet_memory_debug_64bit *sahara_memory_debug_64bit = (sahara_packet_memory_debug_64bit *)sahara_data.rx_buffer; - dload_debug_type *sahara_memory_table_rx = (dload_debug_type *)sahara_data.rx_buffer; - dload_debug_type_64bit *sahara_memory_table = (dload_debug_type_64bit *)sahara_data.misc_buffer; - sahara_packet_reset_resp *sahara_reset_resp = (sahara_packet_reset_resp *)sahara_data.rx_buffer; - - sahara_data.state = SAHARA_WAIT_HELLO; - kickstart_options.verbose = 1; - - while (1) - { - switch (sahara_data.state) - { - case SAHARA_WAIT_HELLO: - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_HELLO"); - if (false == sahara_rx_data(0)) // size 0 means we don't know what to expect. So we'll just try to read the 8 byte header - { - sahara_tx_data(1); - if (false == sahara_rx_data(0)) - return false; - } - - //Check if the received command is a hello command - if (SAHARA_HELLO_ID != qlog_le32(sahara_hello->header.command)) { - dbg(LOG_ERROR, "Received a different command: %x while waiting for hello packet", qlog_le32(sahara_hello->header.command)); - if (false == send_reset_command ()) { - return false; - } - // set the state to SAHARA_WAIT_RESET_RESP - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_RESET_RESP\n"); - sahara_data.state = SAHARA_WAIT_RESET_RESP; - } - else { - // Recieved hello, send the hello response - // Create a Hello request - sahara_hello_resp->header.command = qlog_le32(SAHARA_HELLO_RESP_ID); - sahara_hello_resp->header.length = qlog_le32(sizeof(sahara_packet_hello_resp)); - sahara_hello_resp->version = sahara_hello->version; //SAHARA_VERSION; - sahara_hello_resp->version_supported = sahara_hello->version_supported; //SAHARA_VERSION_SUPPORTED; - sahara_hello_resp->status = qlog_le32(SAHARA_STATUS_SUCCESS); - sahara_hello_resp->mode = sahara_hello->mode; - sahara_hello_resp->reserved0 = qlog_le32(1); - sahara_hello_resp->reserved1 = qlog_le32(2); - sahara_hello_resp->reserved2 = qlog_le32(3); - sahara_hello_resp->reserved3 = qlog_le32(4); - sahara_hello_resp->reserved4 = qlog_le32(5); - sahara_hello_resp->reserved5 = qlog_le32(6); - - switch (qlog_le32(sahara_hello->mode)) { - case SAHARA_MODE_IMAGE_TX_PENDING: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_PENDING"); - break; - case SAHARA_MODE_IMAGE_TX_COMPLETE: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_IMAGE_TX_COMPLETE"); - break; - case SAHARA_MODE_MEMORY_DEBUG: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_MEMORY_DEBUG"); - break; - case SAHARA_MODE_COMMAND: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_COMMAND"); - break; - default: - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MODE_0x%x", qlog_le32(sahara_hello->mode)); - break; - } - - if (qlog_le32(sahara_hello->mode) != sahara_data.mode) { - dbg(LOG_ERROR, "Not expect module state "); - return false; - } - - /*Send the Hello Resonse Request*/ - dbg(LOG_EVENT, "SENDING --> SAHARA_HELLO_RESPONSE"); - if (false == sahara_tx_data (sizeof(sahara_packet_hello_resp))) - { - dbg(LOG_ERROR, "Tx Sahara Data Failed "); - return false; - } - sahara_data.state = SAHARA_WAIT_COMMAND; - } - break; - - case SAHARA_WAIT_COMMAND: - dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_COMMAND"); - if (false == sahara_rx_data(0)) - return false; - - // Check if it is an end of image Tx - if (SAHARA_MEMORY_DEBUG_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command) - || SAHARA_64_BITS_MEMORY_DEBUG_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)) { - dbg(LOG_EVENT, "RECEIVED <-- SAHARA_MEMORY_DEBUG"); - - if (SAHARA_64_BITS_MEMORY_DEBUG_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)) { - sahara_data.ram_dump_64bit = true; - dbg(LOG_EVENT, "Using 64 bit RAM dump mode"); - memory_table_addr = qlog_le64(sahara_memory_debug_64bit->memory_table_addr); - memory_table_length = qlog_le64(sahara_memory_debug_64bit->memory_table_length); - } - else { - sahara_data.ram_dump_64bit = false; - memory_table_addr = qlog_le32(sahara_memory_debug->memory_table_addr); - memory_table_length = qlog_le32(sahara_memory_debug->memory_table_length); - } - - dbg(LOG_INFO, "Memory Table Address: 0x%08"PRIX64", Memory Table Length: 0x%08"PRIX64, memory_table_addr, memory_table_length); - - if (false == is_valid_memory_table(memory_table_length)) { - dbg(LOG_ERROR, "Invalid memory table received"); - if (false == send_reset_command ()) { - return false; - } - sahara_data.state = SAHARA_WAIT_RESET_RESP; - break; - } - - if (memory_table_length > 0) { - if (false == send_memory_read_packet(memory_table_addr, memory_table_length)) { - return false; - } - - if (memory_table_length > SAHARA_RAW_BUFFER_SIZE) { - dbg(LOG_ERROR, "Memory table length is greater than size of intermediate buffer"); - return false; - } - } - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_MEMORY_TABLE"); - sahara_data.state = SAHARA_WAIT_MEMORY_TABLE; - } - else { - dbg(LOG_ERROR, "Received an unknown command: %d ", qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)); - if (SAHARA_HELLO_ID == qlog_le32(((sahara_packet_header *)sahara_data.rx_buffer)->command)) - continue; - if (false == send_reset_command ()) { - return false; - } - // set the state to SAHARA_WAIT_RESET_RESP - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_RESET_RESP"); - sahara_data.state = SAHARA_WAIT_RESET_RESP; - } - break; - - case SAHARA_WAIT_MEMORY_TABLE: - dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_MEMORY_TABLE"); - num_debug_entries = 0; - if (memory_table_length > 0) { - if (false == sahara_rx_data((size_t)memory_table_length)) { - return false; - } - dbg(LOG_INFO, "Memory Debug table received"); - - if (true == sahara_data.ram_dump_64bit) { - memcpy (sahara_data.misc_buffer, sahara_data.rx_buffer, (size_t)memory_table_length); - num_debug_entries = (int)(memory_table_length/sizeof(dload_debug_type_64bit)); - } - else { - num_debug_entries = (int)(memory_table_length/sizeof(dload_debug_type)); - if (num_debug_entries * sizeof(dload_debug_type_64bit) > SAHARA_RAW_BUFFER_SIZE) { - dbg(LOG_ERROR, "Length of memory table converted to 64-bit entries is greater than size of intermediate buffer"); - return false; - } - - for (i = 0; i < num_debug_entries; ++i) { - sahara_memory_table[i].save_pref = (uint64_t) qlog_le32(sahara_memory_table_rx[i].save_pref); - sahara_memory_table[i].mem_base = (uint64_t) qlog_le32(sahara_memory_table_rx[i].mem_base); - sahara_memory_table[i].length = (uint64_t) qlog_le32(sahara_memory_table_rx[i].length); - strncpy(sahara_memory_table[i].filename, sahara_memory_table_rx[i].filename, DLOAD_DEBUG_STRLEN_BYTES); - strncpy(sahara_memory_table[i].desc, sahara_memory_table_rx[i].desc, DLOAD_DEBUG_STRLEN_BYTES); - } // end for (i = 0; i < num_debug_entries; ++i) - } - } - - for(i = 0; i < num_debug_entries; i++) { - dbg(LOG_EVENT, "Base 0x%08"PRIX64" Len 0x%08"PRIX64", '%s', '%s'", sahara_memory_table[i].mem_base, sahara_memory_table[i].length, sahara_memory_table[i].filename, sahara_memory_table[i].desc); - } - sahara_data.state = SAHARA_WAIT_MEMORY_REGION; - break; - - case SAHARA_WAIT_MEMORY_REGION: - dbg(LOG_INFO, "STATE <-- SAHARA_WAIT_MEMORY_REGION"); - for(i = 0; i < num_debug_entries; i++) { - uint64_t cur = 0; - int fd = -1; - char full_filename[255] = {0}; - if (kickstart_options.path_to_save_files) { - strcpy(full_filename, kickstart_options.path_to_save_files); - strcat(full_filename, "/"); - } - strcat(full_filename, sahara_memory_table[i].filename); - - fd = open(full_filename, O_CREAT | O_WRONLY | O_TRUNC, 0444); - if (fd==-1) { - dbg(LOG_ERROR, "ERROR: Your file '%s' does not exist or cannot be created\n\n",sahara_memory_table[num_debug_entries].filename); - exit(0); - } - gettimeofday(&time_start, NULL); - - while (cur < sahara_memory_table[i].length) { - uint64_t len = MIN((uint32_t)(sahara_memory_table[i].length - cur), sahara_data.max_ram_dump_read); - - if (len < sahara_data.max_ram_dump_read || cur == 0 || (cur%(16*1024*1024)) == 0) - kickstart_options.verbose = 1; - else - kickstart_options.verbose = 0; - - retval = send_memory_read_packet(sahara_memory_table[i].mem_base + cur, len); - if (false == retval) { - return false; - } - - retval = sahara_rx_data((size_t)len); - if (false == retval) { - system("fuser /dev/ttyUSB0"); - if ( sahara_data.max_ram_dump_read > (16*1024)) { - sahara_data.max_ram_dump_read = sahara_data.max_ram_dump_read / 2; - continue; - } - return false; - } - - cur += len; - - retval = write(fd, sahara_data.rx_buffer, (unsigned int)len); - if (retval < 0) { - dbg(LOG_ERROR, "file write failed: %s", strerror(errno)); - return false; - } - if ((uint32_t) retval != len) { - dbg(LOG_WARN, "Wrote only %d of 0x%08"PRIX64" bytes", retval, memory_table_length); - } - } - - - kickstart_options.verbose = 1; - dbg(LOG_STATUS, "Received file '%s'", sahara_memory_table[i].filename); - close(fd); - gettimeofday(&time_end, NULL); - time_throughput_calculate(&time_start, &time_end, sahara_memory_table[i].length); - } - - if ( kickstart_options.do_reset) { - if (false == send_reset_command ()) { - return false; - } - sahara_data.state = SAHARA_WAIT_RESET_RESP; - } else { - return true; - } - break; - - case SAHARA_WAIT_DONE_RESP: - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_DONE_RESP"); - return false; - break; - - case SAHARA_WAIT_RESET_RESP: - dbg(LOG_EVENT, "STATE <-- SAHARA_WAIT_RESET_RESP"); - if (true == sahara_rx_data(0)) { - if (SAHARA_RESET_RESP_ID != qlog_le32(sahara_reset_resp->header.command)) { - dbg(LOG_INFO,"Waiting for reset response code %i, received %i instead.", SAHARA_RESET_RESP_ID, qlog_le32(sahara_reset_resp->header.command)); - continue; - } - } else { - if (SAHARA_RESET_RESP_ID == qlog_le32(sahara_reset_resp->header.command)) { - dbg(LOG_INFO,"Get reset response code %i", sahara_reset_resp->header.command); - return true; - } else { - dbg(LOG_ERROR, "read failed: Linux system error: %s", strerror(errno)); - return false; - } - } - - return true; - break; - - default: - dbg(LOG_ERROR, "Unrecognized state %d", sahara_data.state); - return false; - } /* end switch */ - } /* end while (1) */ -} - - int sahara_catch_dump(int port_fd, const char *path_to_save_files, int do_reset) { - int retval; - - sahara_data.mode = SAHARA_MODE_MEMORY_DEBUG; - com_port.port_fd = port_fd; - kickstart_options.path_to_save_files = path_to_save_files; - kickstart_options.do_reset = do_reset; - - sahara_data.rx_buffer = malloc (SAHARA_RAW_BUFFER_SIZE); - sahara_data.tx_buffer = malloc (2048); - sahara_data.misc_buffer = malloc (2048); - - if (NULL == sahara_data.rx_buffer || NULL == sahara_data.tx_buffer || NULL == sahara_data.misc_buffer) { - dbg(LOG_ERROR, "Failed to allocate sahara buffers"); - return false; - } - - retval = sahara_start(); - if (false == retval) { - dbg(LOG_ERROR, "Sahara protocol error"); - } - else { - dbg(LOG_ERROR, "Sahara protocol completed"); - } - - free(sahara_data.rx_buffer); - free(sahara_data.tx_buffer); - free(sahara_data.misc_buffer); - - sahara_data.rx_buffer = sahara_data.tx_buffer = sahara_data.misc_buffer = NULL; - - if (retval == false) - dbg(LOG_INFO, "Catch DUMP using Sahara protocol failed\n\n"); - else - dbg(LOG_INFO, "Catch DUMP using Sahara protocol successful\n\n"); - - return retval; -} diff --git a/rooter/0optionalapps/qlog/src/sahara_protocol.h b/rooter/0optionalapps/qlog/src/sahara_protocol.h deleted file mode 100644 index 0db7989..0000000 --- a/rooter/0optionalapps/qlog/src/sahara_protocol.h +++ /dev/null @@ -1,510 +0,0 @@ -/*=========================================================================== - * FILE: - * sahara_packet.h - * - * DESCRIPTION: - * Sahara protocol states and structure declaration. - * - * Copyright (C) 2012 Qualcomm Technologies, Inc. All rights reserved. - * Qualcomm Technologies Proprietary/GTDR - * - * All data and information contained in or disclosed by this document is - * confidential and proprietary information of Qualcomm Technologies, Inc. and all - * rights therein are expressly reserved. By accepting this material the - * recipient agrees that this material and the information contained therein - * is held in confidence and in trust and will not be used, copied, reproduced - * in whole or in part, nor its contents revealed in any manner to others - * without the express written permission of Qualcomm Technologies, Inc. - * =========================================================================== - * - * sahara_packet.h : Sahara protocol states and structure declaration. - * ========================================================================================== - * $Header: //components/rel/boot.bf/3.1.4/boot_images/core/storage/tools/QSaharaServer/src/sahara_protocol.h#1 $ - * $DateTime: 2017/02/21 04:58:32 $ - * $Author: pwbldsvc $ - * - * Edit History: - * YYYY-MM-DD who why - * ----------------------------------------------------------------------------- - * 2010-09-28 ng Added command mode support - * 2010-10-18 ab Added memory debug mode support - * - * Copyright 2012 by Qualcomm Technologies, Inc. All Rights Reserved. - * - *========================================================================================== - */ - -#ifndef SAHARA_PROTOCOL_H -#define SAHARA_PROTOCOL_H - -/*=========================================================================== - * - * INCLUDE FILES - * - * ===========================================================================*/ - -/*=========================================================================== - * - * PUBLIC DATA DECLARATIONS - * - * ===========================================================================*/ -// Sahara Protocol Version -#define SAHARA_VERSION 2 -#define SAHARA_VERSION_SUPPORTED 4 - -/*Maximum 1 megabyte tx buffer size*/ -#define SAHARA_RAW_BUFFER_SIZE (64*1024) - -// Sahara command IDs -typedef enum -{ - SAHARA_NO_CMD_ID = 0x00, - SAHARA_HELLO_ID = 0x01, // sent from target to host - SAHARA_HELLO_RESP_ID = 0x02, // sent from host to target - SAHARA_READ_DATA_ID = 0x03, // sent from target to host - SAHARA_END_IMAGE_TX_ID = 0x04, // sent from target to host - SAHARA_DONE_ID = 0x05, // sent from host to target - SAHARA_DONE_RESP_ID = 0x06, // sent from target to host - SAHARA_RESET_ID = 0x07, // sent from host to target - SAHARA_RESET_RESP_ID = 0x08, // sent from target to host - SAHARA_MEMORY_DEBUG_ID = 0x09, // sent from target to host - SAHARA_MEMORY_READ_ID = 0x0A, // sent from host to target - SAHARA_CMD_READY_ID = 0x0B, // sent from target to host - SAHARA_CMD_SWITCH_MODE_ID = 0x0C, // sent from host to target - SAHARA_CMD_EXEC_ID = 0x0D, // sent from host to target - SAHARA_CMD_EXEC_RESP_ID = 0x0E, // sent from target to host - SAHARA_CMD_EXEC_DATA_ID = 0x0F, // sent from host to target - SAHARA_64_BITS_MEMORY_DEBUG_ID = 0x10, // sent from target to host - SAHARA_64_BITS_MEMORY_READ_ID = 0x11, // sent from host to target - SAHARA_64_BITS_READ_DATA_ID = 0x12, - // place all new commands above this - SAHARA_LAST_CMD_ID, - SAHARA_MAX_CMD_ID = 0x7FFFFFFF // To ensure 32-bits wide -} boot_sahara_cmd_id; - -typedef enum { - SAHARA_IMAGE_TYPE_BINARY = 0, /* Binary format */ - SAHARA_IMAGE_TYPE_ELF, /* ELF format */ - SAHARA_IMAGE_UNKNOWN = 0x7FFFFFFF /* To ensure 32-bits wide */ -} boot_sahara_image; - -// Status codes for Sahara -typedef enum -{ - // Success - SAHARA_STATUS_SUCCESS = 0x00, - - // Invalid command received in current state - SAHARA_NAK_INVALID_CMD = 0x01, - - // Protocol mismatch between host and target - SAHARA_NAK_PROTOCOL_MISMATCH = 0x02, - - // Invalid target protocol version - SAHARA_NAK_INVALID_TARGET_PROTOCOL = 0x03, - - // Invalid host protocol version - SAHARA_NAK_INVALID_HOST_PROTOCOL = 0x04, - - // Invalid packet size received - SAHARA_NAK_INVALID_PACKET_SIZE = 0x05, - - // Unexpected image ID received - SAHARA_NAK_UNEXPECTED_IMAGE_ID = 0x06, - - // Invalid image header size received - SAHARA_NAK_INVALID_HEADER_SIZE = 0x07, - - // Invalid image data size received - SAHARA_NAK_INVALID_DATA_SIZE = 0x08, - - // Invalid image type received - SAHARA_NAK_INVALID_IMAGE_TYPE = 0x09, - - // Invalid tranmission length - SAHARA_NAK_INVALID_TX_LENGTH = 0x0A, - - // Invalid reception length - SAHARA_NAK_INVALID_RX_LENGTH = 0x0B, - - // General transmission or reception error - SAHARA_NAK_GENERAL_TX_RX_ERROR = 0x0C, - - // Error while transmitting READ_DATA packet - SAHARA_NAK_READ_DATA_ERROR = 0x0D, - - // Cannot receive specified number of program headers - SAHARA_NAK_UNSUPPORTED_NUM_PHDRS = 0x0E, - - // Invalid data length received for program headers - SAHARA_NAK_INVALID_PDHR_SIZE = 0x0F, - - // Multiple shared segments found in ELF image - SAHARA_NAK_MULTIPLE_SHARED_SEG = 0x10, - - // Uninitialized program header location - SAHARA_NAK_UNINIT_PHDR_LOC = 0x11, - - // Invalid destination address - SAHARA_NAK_INVALID_DEST_ADDR = 0x12, - - // Invalid data size receieved in image header - SAHARA_NAK_INVALID_IMG_HDR_DATA_SIZE = 0x13, - - // Invalid ELF header received - SAHARA_NAK_INVALID_ELF_HDR = 0x14, - - // Unknown host error received in HELLO_RESP - SAHARA_NAK_UNKNOWN_HOST_ERROR = 0x15, - - // Timeout while receiving data - SAHARA_NAK_TIMEOUT_RX = 0x16, - - // Timeout while transmitting data - SAHARA_NAK_TIMEOUT_TX = 0x17, - - // Invalid mode received from host - SAHARA_NAK_INVALID_HOST_MODE = 0x18, - - // Invalid memory read access - SAHARA_NAK_INVALID_MEMORY_READ = 0x19, - - // Host cannot handle read data size requested - SAHARA_NAK_INVALID_DATA_SIZE_REQUEST = 0x1A, - - // Memory debug not supported - SAHARA_NAK_MEMORY_DEBUG_NOT_SUPPORTED = 0x1B, - - // Invalid mode switch - SAHARA_NAK_INVALID_MODE_SWITCH = 0x1C, - - // Failed to execute command - SAHARA_NAK_CMD_EXEC_FAILURE = 0x1D, - - // Invalid parameter passed to command execution - SAHARA_NAK_EXEC_CMD_INVALID_PARAM = 0x1E, - - // Unsupported client command received - SAHARA_NAK_EXEC_CMD_UNSUPPORTED = 0x1F, - - // Invalid client command received for data response - SAHARA_NAK_EXEC_DATA_INVALID_CLIENT_CMD = 0x20, - - // Failed to authenticate hash table - SAHARA_NAK_HASH_TABLE_AUTH_FAILURE = 0x21, - - // Failed to verify hash for a given segment of ELF image - SAHARA_NAK_HASH_VERIFICATION_FAILURE = 0x22, - - // Failed to find hash table in ELF image - SAHARA_NAK_HASH_TABLE_NOT_FOUND = 0x23, - - // Place all new error codes above this - SAHARA_NAK_LAST_CODE, - - SAHARA_NAK_MAX_CODE = 0x7FFFFFFF // To ensure 32-bits wide -} boot_sahara_status; - -// Status of all image transfers -typedef enum -{ - SAHARA_MODE_IMAGE_TX_PENDING = 0x0, - SAHARA_MODE_IMAGE_TX_COMPLETE = 0x1, - SAHARA_MODE_MEMORY_DEBUG = 0x2, - SAHARA_MODE_COMMAND = 0x3, - - // place all new commands above this - SAHARA_MODE_LAST, - SAHARA_MODE_MAX = 0x7FFFFFFF -} boot_sahara_mode; - -// Executable commands when target is in command mode -typedef enum -{ - SAHARA_EXEC_CMD_NOP = 0x00, - SAHARA_EXEC_CMD_SERIAL_NUM_READ = 0x01, - SAHARA_EXEC_CMD_MSM_HW_ID_READ = 0x02, - SAHARA_EXEC_CMD_OEM_PK_HASH_READ = 0x03, - SAHARA_EXEC_CMD_SWITCH_DMSS = 0x04, - SAHARA_EXEC_CMD_SWITCH_STREAMING = 0x05, - SAHARA_EXEC_CMD_READ_DEBUG_DATA = 0x06, - - // place all new commands above this - SAHARA_EXEC_CMD_LAST, - SAHARA_EXEC_CMD_MAX = 0x7FFFFFFF -} boot_sahara_exec_cmd_id; - -/* Sahara Protocol states */ -typedef enum { - SAHARA_WAIT_HELLO, - SAHARA_WAIT_COMMAND, - SAHARA_WAIT_RESET_RESP, - SAHARA_WAIT_DONE_RESP, - SAHARA_WAIT_MEMORY_READ, - SAHARA_WAIT_CMD_EXEC_RESP, - SAHARA_WAIT_MEMORY_TABLE, - SAHARA_WAIT_MEMORY_REGION, -} boot_sahara_state; - -/* ============================================================================= */ -/* Sahara protocol packet defintions */ -/* ============================================================================= */ - -typedef struct -{ - uint32_t command; // command ID - uint32_t length; // packet length incl command and length -} sahara_packet_header; - -// HELLO command packet type - sent from target to host -// indicates start of protocol on target side -typedef struct -{ - sahara_packet_header header; - uint32_t version; // target protocol version number - uint32_t version_supported; // minimum protocol version number supported - // on target - uint32_t cmd_packet_length; // maximum packet size supported for command - // packets - uint32_t mode; // expected mode of target operation - uint32_t reserved0; // reserved field - uint32_t reserved1; // reserved field - uint32_t reserved2; // reserved field - uint32_t reserved3; // reserved field - uint32_t reserved4; // reserved field - uint32_t reserved5; // reserved field -} sahara_packet_hello; - -// HELLO_RESP command packet type - sent from host to target -// response to hello, protocol version running on host and status sent -typedef struct -{ - sahara_packet_header header; - uint32_t version; // host protocol version number - uint32_t version_supported; // minimum protocol version number supported - // on host - uint32_t status; // OK or error condition - uint32_t mode; // mode of operation for target to execute - uint32_t reserved0; // reserved field - uint32_t reserved1; // reserved field - uint32_t reserved2; // reserved field - uint32_t reserved3; // reserved field - uint32_t reserved4; // reserved field - uint32_t reserved5; // reserved field -} sahara_packet_hello_resp; - -// READ_DATA command packet type - sent from target to host -// sends data segment offset and length to be read from current host -// image file -typedef struct -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint32_t data_offset; // offset into image file to read data from - uint32_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data; - -// READ_DATA_64 command packet type - sent from target to host -// sends data segment offset and length to be read from current host -// image file -/* -#ifdef WINDOWSPC -#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) -PACK( -typedef struct // note for gcc use __attribute__((__packed__)) -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint64_t data_offset; // offset into image file to read data from - uint32_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data_64bit; -); -#else -typedef __attribute__((__packed__)) struct -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint64_t data_offset; // offset into image file to read data from - uint32_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data_64bit; -#endif -*/ -typedef struct -{ - sahara_packet_header header; - uint64_t image_id; // ID of image to be transferred - uint64_t data_offset; // offset into image file to read data from - uint64_t data_length; // length of data segment to be retreived - // from image file -} sahara_packet_read_data_64bit; - -// END_IMAGE_TX command packet type - sent from target to host -// indicates end of a single image transfer and status of transfer -typedef struct -{ - sahara_packet_header header; - uint32_t image_id; // ID of image to be transferred - uint32_t status; // OK or error condition -} sahara_packet_end_image_tx; - -// DONE packet type - sent from host to target -// indicates end of single image transfer -typedef struct -{ - sahara_packet_header header; -} sahara_packet_done; - -// DONE_RESP packet type - sent from target to host -// indicates end of all image transfers -typedef struct -{ - sahara_packet_header header; - uint32_t image_tx_status; // indicates if all images have been - // transferred; - // 0 = IMAGE_TX_PENDING - // 1 = IMAGE_TX_COMPLETE -} sahara_packet_done_resp; - -// RESET packet type - sent from host to target -// indicates to target to reset -typedef struct -{ - sahara_packet_header header; -} sahara_packet_reset; - -// RESET_RESP packet type - sent from target to host -// indicates to host that target has reset -typedef struct -{ - sahara_packet_header header; -} sahara_packet_reset_resp; - -// MEMORY_DEBUG packet type - sent from target to host -// sends host the location and length of memory region table -typedef struct -{ - sahara_packet_header header; - uint32_t memory_table_addr; // location of memory region table - uint32_t memory_table_length; // length of memory table -} sahara_packet_memory_debug; -typedef struct -{ - sahara_packet_header header; - uint64_t memory_table_addr; // location of memory region table - uint64_t memory_table_length; // length of memory table -} sahara_packet_memory_debug_64bit; - -// MEMORY_READ packet type - sent from host to target -// sends memory address and length to read from target memory -typedef struct -{ - sahara_packet_header header; - uint32_t memory_addr; // memory location to read from - uint32_t memory_length; // length of data to send -} sahara_packet_memory_read; -typedef struct -{ - sahara_packet_header header; - uint64_t memory_addr; // memory location to read from - uint64_t memory_length; // length of data to send -} sahara_packet_memory_read_64bit; - -// CMD_READY packet type - sent from target to host -// indicates to host that target is ready to accept commands -typedef struct -{ - sahara_packet_header header; -} sahara_packet_cmd_ready; - -// CMD_SWITCH_MODE packet type - sent from host to target -// indicates to target to switch modes -typedef struct -{ - sahara_packet_header header; - uint32_t mode; // mode of operation for target to execute -} sahara_packet_cmd_switch_mode; - -// CMD_EXEC packet type - sent from host to target -// indicates to target to execute given client_command -typedef struct -{ - sahara_packet_header header; - uint32_t client_command; // command ID for target Sahara client to - // execute -} sahara_packet_cmd_exec; - -// CMD_EXEC_RESP packet type - sent from host to target -// indicates to host that target has successfully executed command -// and length of data response -typedef struct -{ - sahara_packet_header header; - uint32_t client_command; // command ID for target Sahara client to - // execute - uint32_t resp_length; // length of response returned from command - // execution -} sahara_packet_cmd_exec_resp; - -// CMD_EXEC_DATA packet type - sent from target to host -// indicates that host is ready to receive data after command execution -typedef struct -{ - sahara_packet_header header; - uint32_t client_command; // command ID for target Sahara client to - // execute -} sahara_packet_cmd_exec_data; - -#define DLOAD_DEBUG_STRLEN_BYTES 20 -typedef struct -{ - uint32_t save_pref; - uint32_t mem_base; - uint32_t length; - char desc[DLOAD_DEBUG_STRLEN_BYTES]; - char filename[DLOAD_DEBUG_STRLEN_BYTES]; -} dload_debug_type; - -typedef struct -{ - uint64_t save_pref; //force 8 bytes alignment - uint64_t mem_base; - uint64_t length; - char desc[DLOAD_DEBUG_STRLEN_BYTES]; - char filename[DLOAD_DEBUG_STRLEN_BYTES]; -} dload_debug_type_64bit; - -typedef struct { - /* buffer for sahara rx */ - void* rx_buffer; - - /* buffer for sahara tx */ - void* tx_buffer; - - /* buffer for memory table */ - void* misc_buffer; - - /* Sahara state */ - boot_sahara_state state; - - size_t timed_data_size; - - // handle to input image - int fd; - - int ram_dump_image; - - int max_ram_dump_retries; - - uint32_t max_ram_dump_read; - - boot_sahara_mode mode; - boot_sahara_mode prev_mode; - - unsigned int command; - bool ram_dump_64bit; - -} sahara_data_t; -#endif /* SAHARA_PACKET_H */ diff --git a/rooter/0optionalapps/qlog/src/tty2tcp.c b/rooter/0optionalapps/qlog/src/tty2tcp.c deleted file mode 100644 index 9d3b6e4..0000000 --- a/rooter/0optionalapps/qlog/src/tty2tcp.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "qlog.h" - -unsigned int inet_addr(const char *cp); -char *inet_ntoa(struct in_addr in); - -static int wait_tcp_client_connect(int tcp_port) { - int sockfd, n, connfd; - struct sockaddr_in serveraddr; - struct sockaddr_in clientaddr; - int reuse_addr = 1; - size_t sin_size; - - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) - { - qlog_dbg("Create socket fail!\n"); - return 0; - } - - memset(&serveraddr, 0, sizeof(serveraddr)); - serveraddr.sin_family = AF_INET; - serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); - serveraddr.sin_port = htons(tcp_port); - - qlog_dbg("Starting the TCP server(%d)...\n", tcp_port); - - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); - - n = bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); - if (n == -1) - { - qlog_dbg("bind fail! errno: %d\n", errno); - close(sockfd); - return 0; - } - qlog_dbg("bind OK!\n"); - - n = listen(sockfd, 1); - if (n == -1) - { - qlog_dbg("listen fail! errno: %d\n", errno); - close(sockfd); - return 0; - } - qlog_dbg("listen OK!\nWaiting the TCP Client...\n"); - - sin_size = sizeof(struct sockaddr_in); - connfd = accept(sockfd, (struct sockaddr *)&clientaddr, (socklen_t *)&sin_size); - close(sockfd); - if (connfd == -1) - { - qlog_dbg("accept fail! errno: %d\n", errno); - return -1; - } - - qlog_dbg("TCP Client %s:%d connect\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port); - - return connfd; -} - -int tty2tcp_sockfd = -1; -static int tty2tcp_ttyfd = -1; -static int tty2tcp_tcpport = 9000; - -static void *tcp_sock_read_Loop(void *arg) { - int sockfd = tty2tcp_sockfd; - int ttyfd = tty2tcp_ttyfd; - void *rbuf; - const size_t rbuf_size = (4*1024); - - rbuf = malloc(rbuf_size); - if (rbuf == NULL) { - qlog_dbg("Fail to malloc rbuf_size=%zd, errno: %d (%s)\n", rbuf_size, errno, strerror(errno)); - return NULL; - } - - while (sockfd > 0) { - ssize_t rc, wc; - int ret; - struct pollfd pollfds[] = {{sockfd, POLLIN, 0}}; - - ret = poll(pollfds, 1, -1); - - if (ret <= 0) { - qlog_dbg("poll(ttyfd) =%d, errno: %d (%s)\n", ret, errno, strerror(errno)); - break; - } - - if (pollfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - tty2tcp_sockfd = -1; - close(sockfd); - qlog_dbg("ttyfd revents = %04x\n", pollfds[0].revents); - sockfd = tty2tcp_sockfd = wait_tcp_client_connect(tty2tcp_tcpport); - } - - if (pollfds[0].revents & (POLLIN)) { - rc = read(sockfd, rbuf, rbuf_size); - - if(rc > 0) { - if (g_is_asr_chip) - wc = asr_send_cmd(ttyfd, rbuf, rc); - else - wc = mdm_send_cmd(ttyfd, rbuf, rc); - - if (wc != rc) { - //qlog_dbg("ttyfd write fail %zd/%zd, break\n", wc, rc); - //break; - } - } - else - { - tty2tcp_sockfd = -1; - close(sockfd); - qlog_dbg("sockfd recv %zd Bytes. maybe terminae by peer!\n", rc); - sockfd = tty2tcp_sockfd = wait_tcp_client_connect(tty2tcp_tcpport); - } - } - } - - free(rbuf); - close(ttyfd); - tty2tcp_sockfd = -1; - qlog_dbg("%s exit\n", __func__); - - return NULL; -} - -static int tty2tcp_init_filter(int ttyfd, const char *cfg) { - int tcp_port = 9000; - int sockfd = -1; - pthread_t tid; - pthread_attr_t attr; - - if (cfg) - tcp_port = atoi(cfg); - - tty2tcp_tcpport = tcp_port; - sockfd = wait_tcp_client_connect(tcp_port); - - if (sockfd <= 0) - return -1; - - fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); - - pthread_attr_init (&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - tty2tcp_sockfd = sockfd; - tty2tcp_ttyfd = ttyfd; - pthread_create(&tid, &attr, tcp_sock_read_Loop, &attr); - - return 0; -} - -static int tty2tcp_logfile_create(const char *logfile_dir, const char *logfile_suffix, unsigned logfile_seq) { - return 1; -} - -static size_t tty2tcp_logfile_save(int logfd, const void *buf, size_t size) { - if (tty2tcp_sockfd > 0) - return qlog_poll_write(tty2tcp_sockfd, buf, size, 200); - return size; -} - -static int tty2tcp_logfile_close(int logfd) { - return 0; -} - -qlog_ops_t tty2tcp_qlog_ops = { - .init_filter = tty2tcp_init_filter, - .logfile_create = tty2tcp_logfile_create, - .logfile_save = tty2tcp_logfile_save, - .logfile_close = tty2tcp_logfile_close, -}; diff --git a/rooter/0optionalapps/udp-tunnel/Makefile b/rooter/0optionalapps/udp-tunnel/Makefile deleted file mode 100644 index 4d568b5..0000000 --- a/rooter/0optionalapps/udp-tunnel/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (C) 2011-2014 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=udp-tunnel -PKG_RELEASE:=1 - -PKG_FLAGS:=nonshared - -include $(INCLUDE_DIR)/package.mk - -define Package/udp-tunnel - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=UDPTunnel - MAINTAINER:=Dairyman -endef - -define Package/udp-tunnel/description - UDPTunnel -endef - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR) \ - CC="$(TARGET_CC)" \ - CFLAGS="$(TARGET_CFLAGS) -Wall" -endef - -define Package/udp-tunnel/install - $(INSTALL_DIR) $(1)/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/udptunnel $(1)/sbin/udptunnel -endef - -$(eval $(call BuildPackage,udp-tunnel)) diff --git a/rooter/0optionalapps/udp-tunnel/src/Makefile b/rooter/0optionalapps/udp-tunnel/src/Makefile deleted file mode 100644 index 0a70e29..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -prefix = /usr/local - -CFLAGS ?= -g -O2 - -INSTALL ?= install -PKG_CONFIG ?= pkg-config - -ifeq ($(shell $(PKG_CONFIG) --exists libsystemd || echo NO),) -DEFS += -DHAVE_SYSTEMD_SD_DAEMON_H $(shell $(PKG_CONFIG) --cflags libsystemd) -LDADD += $(shell $(PKG_CONFIG) --libs libsystemd) -endif - -CPPFLAGS += $(DEFS) $(INCLUDES) - -OBJECTS := log.o network.o utils.o udptunnel.o - -all: depend udptunnel - -install: - $(INSTALL) -d $(BASEDIR)$(prefix)/sbin/ - $(INSTALL) -m 0755 udptunnel $(BASEDIR)$(prefix)/sbin/ - -clean: - rm -f Makefile.depend $(OBJECTS) udptunnel - -%.o: %.c - $(CC) $(CPPFLAGS) $(CFLAGS) -c $< - -udptunnel: $(OBJECTS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDADD) $(LIBS) - -depend: Makefile.depend -Makefile.depend: - $(CC) $(CPPFLAGS) $(CFLAGS) -MM -MG *.c > $@ - --include Makefile.depend diff --git a/rooter/0optionalapps/udp-tunnel/src/log.c b/rooter/0optionalapps/udp-tunnel/src/log.c deleted file mode 100644 index 91bb04d..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/log.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * Inspired by log.c from the cowdancer package by James Clarke. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include - -#include "log.h" -#include "utils.h" - -static log_level filter_level = log_info; - -/* - * Return the appropriate file handle (stdout vs. stderr) for the log level. - */ -static FILE *file_for_level(log_level level) -{ - if (level & log_stderr || filter_level & log_stderr) - return stderr; - - if ((level & LOG_LEVEL_MASK) > log_warning) - return stdout; - else - return stderr; -} - -static void log_doit(log_level level, const char *format, va_list args) -{ - static int syslog_initialized; - - if ((level & LOG_LEVEL_MASK) > (filter_level & LOG_LEVEL_MASK)) - return; - - if (level & log_syslog || filter_level & log_syslog) { - if (!syslog_initialized) { - openlog(NULL, LOG_PID, LOG_DAEMON); - syslog_initialized = 1; - } - - if (level & log_strerror) { - int len = strlen(format); - char *format2; - - format2 = NOFAIL(malloc(len + 4 + 1)); - strcpy(format2, format); - strcpy(format2 + len, ": %m"); - vsyslog(level & LOG_LEVEL_MASK, format2, args); - free(format2); - } else { - vsyslog(level & LOG_LEVEL_MASK, format, args); - } - return; - } - - vfprintf(file_for_level(level), format, args); - if (level & log_strerror) - fprintf(file_for_level(level), ": %s", strerror(errno)); - fprintf(file_for_level(level), "\n"); -} - -log_level log_get_filter_level(void) -{ - return filter_level; -} - -void log_set_options(log_level filter_level_new) -{ - filter_level = filter_level_new; -} - -void log_printf(log_level level, const char *format, ...) -{ - va_list args; - - va_start(args, format); - log_doit(level, format, args); - va_end(args); -} - -void log_printf_exit(int status, log_level level, const char *format, ...) -{ - va_list args; - - va_start(args, format); - log_doit(level, format, args); - va_end(args); - - exit(status); -} - -void log_printf_err(log_level level, const char *format, ...) -{ - va_list args; - - va_start(args, format); - log_doit(level | log_strerror, format, args); - va_end(args); -} - -void log_printf_err_exit(int status, log_level level, const char *format, ...) -{ - va_list args; - - va_start(args, format); - log_doit(level | log_strerror, format, args); - va_end(args); - - exit(status); -} - diff --git a/rooter/0optionalapps/udp-tunnel/src/log.h b/rooter/0optionalapps/udp-tunnel/src/log.h deleted file mode 100644 index e42665d..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/log.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * Inspired by log.c from the cowdancer package by James Clarke. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __LOG_H__ -#define __LOG_H__ - -#include - -#include "utils.h" - -typedef enum log_level { - /* the value of the first 3 bits matches the syslog(3) levels */ - log_emerg = 0, - log_alert = 1, - log_crit = 2, - log_err = 3, - log_warning = 4, - log_notice = 5, - log_info = 6, - log_debug = 7, - log_nothing = 8, - - /* the following entries are bit flags to be OR'ed with the level */ - log_stderr = 0x10, - log_syslog = 0x20, - log_strerror = 0x40, -} log_level; - -/* remove the flags from log_level */ -#define LOG_LEVEL_MASK 0xf - -log_level log_get_filter_level(void); - -void log_set_options(log_level filter_level_new); - -__attribute__ ((format(printf, 2, 3))) -void log_printf(log_level level, const char *format, ...); - -__attribute__ ((format(printf, 3, 4), noreturn)) -void log_printf_exit(int status, log_level level, const char *format, ...); - -__attribute__ ((format(printf, 2, 3))) -void log_printf_err(log_level level, const char *format, ...); - -__attribute__ ((format(printf, 3, 4), noreturn)) -void log_printf_err_exit(int status, log_level level, const char *format, ...); - -#define err_sys(...) log_printf_err_exit(1, log_err, __VA_ARGS__) - -#endif /* !__LOG_H__ */ diff --git a/rooter/0optionalapps/udp-tunnel/src/network.c b/rooter/0optionalapps/udp-tunnel/src/network.c deleted file mode 100644 index 2c0f2c1..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/network.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* for getaddrinfo... */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "network.h" -#include "utils.h" -#include "log.h" - -char *print_addr_port(const struct sockaddr *addr, socklen_t addrlen) -{ - static char buf[1100], address[1025], port[32]; - int err; - - err = getnameinfo(addr, addrlen, address, sizeof(address), - port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); - if (err == EAI_SYSTEM) - err_sys("getnameinfo"); - else if (err) - log_printf_exit(1, log_err, "getnameinfo: %s", gai_strerror(err)); - - if (addr->sa_family == AF_INET6) - snprintf(buf, sizeof(buf) - 1, "[%s]:%s", address, port); - else - snprintf(buf, sizeof(buf) - 1, "%s:%s", address, port); - - return buf; -} - -static char *ai_print_addr_port(struct addrinfo *ai) -{ - return print_addr_port((struct sockaddr *) ai->ai_addr, ai->ai_addrlen); -} - -/* - * Try to parse anything that looks like: - * - an IPv4 or IPv6 address or a domain, with an optional port number - * - a port number - * - * address and/or port will be NULL if not found in the input. - * If address and port are not NULL then they must be freed by the caller. - */ -static void parse_address_port(const char *input, char **address, char **port) -{ - const char *p; - - *address = NULL; - *port = NULL; - - if (*input == '\0') { - return; - } else if (*input == '[' && (p = strchr(input, ']'))) { /* IPv6 */ - char *s; - int len = p - input - 1; - - *address = s = NOFAIL(malloc(len + 1)); - memcpy(s, input + 1, len); - *(s + len) = '\0'; - - p = strchr(p, ':'); - if (p && *(p + 1) != '\0') - *port = NOFAIL(strdup(p + 1)); /* IPv6 + port */ - } else if ((p = strchr(input, ':')) && /* IPv6, no port */ - strchr(p + 1, ':')) { /* and no brackets */ - *address = NOFAIL(strdup(input)); - } else if ((p = strchr(input, ':'))) { /* IPv4 + port */ - char *s; - int len = p - input; - - if (len) { - *address = s = NOFAIL(malloc(len + 1)); - memcpy(s, input, len); - *(s + len) = '\0'; - } - - p++; - if (*p != '\0') - *port = NOFAIL(strdup(p)); - } else { - for (p = input; *p; p++) - if (!isdigit(p[0])) - break; - if (*p) - *address = NOFAIL(strdup(input)); /* IPv4, no port */ - else - *port = NOFAIL(strdup(input)); /* just the port */ - } -} - -int udp_listener(const char *s) -{ - char *address, *port; - struct addrinfo hints, *res, *ai; - int err, fd; - - parse_address_port(s, &address, &port); - - if (!port) - log_printf_exit(2, log_err, "Missing port in '%s'!", s); - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_IDN; - - err = getaddrinfo(address, port, &hints, &res); - if (err == EAI_SYSTEM) - err_sys("getaddrinfo(%s:%s)", address, port); - else if (err) - log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", - address, port, gai_strerror(err)); - - if (address) - free(address); - if (port) - free(port); - - for (ai = res; ai; ai = ai->ai_next) { - if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) - continue; /* ignore */ - if (bind(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) == 0) - break; /* success */ - close(fd); - } - - if (!ai) - err_sys("Cannot bind to %s", s); - - log_printf(log_info, "Listening for UDP connections on %s", - ai_print_addr_port(ai)); - - freeaddrinfo(res); - - return fd; -} - -int *tcp_listener(const char *s) -{ - char *address, *port; - struct addrinfo hints, *res, *ai; - int err, fd, opt; - int fd_num = 0; - int *fd_list = NULL; - size_t allocated_fds = 0; - - parse_address_port(s, &address, &port); - - if (!port) - log_printf_exit(2, log_err, "Missing port in '%s'!", s); - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_IDN; - - err = getaddrinfo(address, port, &hints, &res); - if (err == EAI_SYSTEM) - err_sys("getaddrinfo(%s:%s)", address, port); - else if (err) - log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", - address, port, gai_strerror(err)); - - if (address) - free(address); - if (port) - free(port); - - /* add to fd_list all the sockets which match ai_flags */ - for (ai = res; ai; ai = ai->ai_next) { - if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) - continue; /* ignore */ - opt = 1; - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) - err_sys("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); - if (bind(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) - err_sys("Cannot bind to %s", s); - - /* success */ - if (listen(fd, 128) < 0) - err_sys("listen"); - - if (allocated_fds < fd_num + 1 + 1) { - allocated_fds += 8; - fd_list = realloc(fd_list, allocated_fds * sizeof(int)); - } - fd_list[fd_num++] = fd; - - log_printf(log_info, "Listening for TCP connections on %s", - ai_print_addr_port(ai)); - } - - /* and then add -1 as the list terminator */ - if (allocated_fds < fd_num + 1 + 1) - fd_list = realloc(fd_list, ++allocated_fds * sizeof(int)); - fd_list[fd_num] = -1; - - if (!fd_list) - err_sys("socket"); - - freeaddrinfo(res); - - return fd_list; -} - -/* - * Accept new connections and return after forking for each one. - */ -int accept_connections(int listening_sockets[]) -{ - while (1) { - int max = 0; - int i, fd; - fd_set readfds; - pid_t pid; - - FD_ZERO(&readfds); - for (i = 0; listening_sockets[i] != -1; i++) { - int flags; - - if ((flags = fcntl(listening_sockets[i], F_GETFL, 0)) < 0) - err_sys("fcntl(F_GETFL)"); - if (fcntl(listening_sockets[i], F_SETFL, flags | O_NONBLOCK) < 0) - err_sys("fcntl(F_SETFL, O_NONBLOCK)"); - - FD_SET(listening_sockets[i], &readfds); - SET_MAX(listening_sockets[i]); - } - - if (select(max, &readfds, NULL, NULL, NULL) < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - err_sys("select"); - } - - for (i = 0; listening_sockets[i] != -1; i++) { - int listen_sock; - struct sockaddr_storage client_addr; - socklen_t addrlen = sizeof(client_addr); - - if (!FD_ISSET(listening_sockets[i], &readfds)) - continue; - listen_sock = listening_sockets[i]; - - fd = accept(listen_sock, (struct sockaddr *) &client_addr, &addrlen); - if (fd < 0) { - if (errno == EAGAIN) - continue; - err_sys("accept"); - } - - log_printf(log_notice, "Received a TCP connection from %s", - print_addr_port((struct sockaddr *) &client_addr, addrlen)); - -#if 0 - /* do not fork, for testing */ - pid = 0; -#else - pid = fork(); -#endif - - if (pid < 0) - err_sys("fork"); - - if (pid > 0) { - close(fd); - } else { - for (i = 0; listening_sockets[i] != -1; i++) - close(listening_sockets[i]); - return fd; - } - } - } -} - -int udp_client(const char *s, struct sockaddr_storage *remote_udpaddr) -{ - char *address, *port; - struct addrinfo hints, *res, *ai; - int err, fd; - - parse_address_port(s, &address, &port); - - if (!address || !port) - log_printf_exit(2, log_err, "Missing address or port in '%s'!", s); - - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_ADDRCONFIG | AI_IDN; - - err = getaddrinfo(address, port, &hints, &res); - if (err == EAI_SYSTEM) - err_sys("getaddrinfo(%s:%s)", address, port); - else if (err) - log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", - address, port, gai_strerror(err)); - - if (address) - free(address); - if (port) - free(port); - - /* continue with the first socket which matches ai_flags */ - for (ai = res; ai; ai = ai->ai_next) { - if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) - continue; /* ignore */ - break; /* success */ - } - - if (!ai) - err_sys("socket"); - - log_printf(log_debug, "The UDP destination is %s", ai_print_addr_port(ai)); - - /* - * Return to the caller the resolved address, to be able to use it as the - * destination address of the next UDP packet. - */ - if (remote_udpaddr) - memcpy(remote_udpaddr, ai->ai_addr, ai->ai_addrlen); - - freeaddrinfo(res); - - return fd; -} - -int tcp_client(const char *s) -{ - char *address, *port; - struct addrinfo hints, *res, *ai; - int err, fd; - - parse_address_port(s, &address, &port); - - if (!address || !port) - log_printf_exit(2, log_err, "Missing address or port in '%s'!", s); - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_ADDRCONFIG | AI_IDN; - - err = getaddrinfo(address, port, &hints, &res); - if (err == EAI_SYSTEM) - err_sys("getaddrinfo(%s:%s)", address, port); - else if (err) - log_printf_exit(1, log_err, "Cannot resolve %s:%s: %s", - address, port, gai_strerror(err)); - - if (address) - free(address); - if (port) - free(port); - - for (ai = res; ai; ai = ai->ai_next) { - if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) - continue; /* ignore */ - if (connect(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) == 0) - break; /* success */ - close(fd); - } - - if (!ai) - err_sys("Cannot connect to %s", s); - - log_printf(log_info, "TCP connection opened to %s", - ai_print_addr_port(ai)); - - freeaddrinfo(res); - - return fd; -} - diff --git a/rooter/0optionalapps/udp-tunnel/src/network.h b/rooter/0optionalapps/udp-tunnel/src/network.h deleted file mode 100644 index 2fafdc1..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/network.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __NETWORK_H__ -#define __NETWORK_H__ - -#define SET_MAX(fd) do { if (max < (fd) + 1) { max = (fd) + 1; } } while (0) - -char *print_addr_port(const struct sockaddr *addr, socklen_t addrlen); - -int udp_listener(const char *s); - -int *tcp_listener(const char *s); - -int udp_listener_sa(const int num); - -int *tcp_listener_sa(const int num); - -int udp_client(const char *s, struct sockaddr_storage *remote_udpaddr); - -int tcp_client(const char *s); - -int accept_connections(int listening_sockets[]); - -#endif diff --git a/rooter/0optionalapps/udp-tunnel/src/udptunnel.c b/rooter/0optionalapps/udp-tunnel/src/udptunnel.c deleted file mode 100644 index 8dd9c17..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/udptunnel.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * Parts of this program are derived from udptunnel.c by Jonathan Lennox. - * This is the license of the original code: - * - * Copyright 1999, 2001 by Columbia University. All rights reserved. - * - * 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 the University 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 HOLDERS 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. - */ - -/* for sigaction... */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYSTEMD_SD_DAEMON_H -#include -#endif - -#include "utils.h" -#include "log.h" -#include "network.h" - -#ifdef HAVE_GETOPT_LONG -#include -#endif - -#define TCPBUFFERSIZE 65536 -#define UDPBUFFERSIZE (TCPBUFFERSIZE - 2) /* TCP packet - length */ - -struct out_packet { - uint16_t length; - char buf[UDPBUFFERSIZE]; -}; - -struct opts { - const char *udpaddr, *tcpaddr; - - int is_server; - int use_inetd; - char *handshake; - int timeout; -}; - -struct relay { - struct sockaddr_storage remote_udpaddr; - - int udp_sock, tcp_sock; - - int expect_handshake; - char handshake[32]; - int udp_timeout, tcp_timeout; - char buf[TCPBUFFERSIZE]; - char *buf_ptr, *packet_start; - int packet_length; - enum { - uninitialized = 0, - reading_handshake, - reading_length, - reading_packet, - } state; -}; - -static void usage(int status) -{ - FILE *fp = status == 0 ? stdout : stderr; - - fprintf(fp, "Usage: udptunnel [OPTION]... [[SOURCE:]PORT] DESTINATION:PORT\n\n"); - fprintf(fp, "-s --server listen for TCP connections\n"); - fprintf(fp, "-i --inetd expect to be started by inetd\n"); - fprintf(fp, "-T N --timeout N close the source connection after N seconds\n"); - fprintf(fp, " where no data was received\n"); - fprintf(fp, "-S --syslog log to syslog instead of standard error\n"); - fprintf(fp, "-v --verbose explain what is being done\n"); - fprintf(fp, "-h --help display this help and exit\n"); - fprintf(fp, "\nSOURCE:PORT must not be specified when using inetd or socket activation.\n\n"); - fprintf(fp, "If the -s option is used then the program will listen on SOURCE:PORT for TCP\n"); - fprintf(fp, "connections and relay the encapsulated packets with UDP to DESTINATION:PORT.\n"); - fprintf(fp, "Otherwise it will listen on SOURCE:PORT for UDP packets and encapsulate\n"); - fprintf(fp, "them in a TCP connection to DESTINATION:PORT.\n"); - - exit(status); -} - -static void parse_args(int argc, char *argv[], struct opts *opts) -{ -#ifdef HAVE_GETOPT_LONG - const struct option longopts[] = { - {"inetd", no_argument, NULL, 'i' }, - {"server", no_argument, NULL, 's' }, - {"syslog", no_argument, NULL, 'S' }, - {"timeout", required_argument, NULL, 'T' }, - {"help", no_argument, NULL, 'h' }, - {"verbose", no_argument, NULL, 'v' }, - {NULL, 0, NULL, 0 }, - }; - int longindex; -#endif - int c; - int expected_args; - int verbose = 0; - int use_syslog = 0; - - /* defaults */ - opts->handshake = NOFAIL(malloc(32)); - memcpy(opts->handshake, "udptunnel by md.\0\0\0\x01\x03\x06\x10\x15\x21\x28\x36\x45\x55\x66\x78\x91", 32); - - while ((c = GETOPT_LONGISH(argc, argv, "ihsvST:", - longopts, &longindex)) > 0) { - switch (c) { - case 'i': - opts->use_inetd = 1; - break; - case 's': - opts->is_server = 1; - break; - case 'S': - use_syslog = 1; - break; - case 'T': - opts->timeout = atol(optarg); - break; - case 'v': - verbose++; - break; - case 'h': - usage(0); - break; - default: - usage(2); - break; - } - } - - /* - * Look for 2 command line arguments (source and destination) - * if used in standalone mode or only 1 argument (destination) - * if used in inetd or socket activated modes. - */ - expected_args = (sd_listen_fds(0) || opts->use_inetd) ? 1 : 2; - - if (argc - optind == 0) - usage(2); - if (argc - optind != expected_args) { - fprintf(stderr, "Expected %d argument(s)!\n\n", expected_args); - usage(2); - } - - /* the source and destination addresses */ - if (opts->is_server) { - if (expected_args == 2) - opts->tcpaddr = NOFAIL(strdup(argv[optind++])); - opts->udpaddr = NOFAIL(strdup(argv[optind++])); - } else { - if (expected_args == 2) - opts->udpaddr = NOFAIL(strdup(argv[optind++])); - opts->tcpaddr = NOFAIL(strdup(argv[optind++])); - } - - if (!verbose) - log_set_options(log_warning); - else if (verbose == 1) - log_set_options(log_notice); - else if (verbose == 2) - log_set_options(log_info); - else - log_set_options(log_debug); - - if (use_syslog) - log_set_options(log_get_filter_level() | log_syslog); -} - -int udp_listener_sa(const int num) -{ - int fd = SD_LISTEN_FDS_START; - - if (num != 1) - log_printf_exit(2, log_err, - "UDP socket activation supports a single socket."); - - if (sd_is_socket(fd, AF_UNSPEC, SOCK_DGRAM, -1) <= 0) - log_printf_exit(2, log_err, - "UDP socket activation fd %d is not valid.", fd); - - return fd; -} - -int *tcp_listener_sa(const int num) -{ - int fd; - int *fds; - int fd_num = 0; - - fds = NOFAIL(malloc((num + 1) * sizeof(int))); - - for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + num; fd++) { - if (sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1) <= 0) - log_printf_exit(2, log_err, - "TCP socket activation fd %d is not valid.", fd); - fds[fd_num++] = fd; - } - - fds[fd_num] = -1; - - return fds; -} - -static void udp_to_tcp(struct relay *relay) -{ - struct out_packet p; - int buflen; - struct sockaddr_storage remote_udpaddr; - socklen_t addrlen = sizeof(remote_udpaddr); - - buflen = recvfrom(relay->udp_sock, p.buf, UDPBUFFERSIZE, 0, - (struct sockaddr *) &remote_udpaddr, &addrlen); - if (buflen < 0) - err_sys("recvfrom(udp)"); - if (buflen == 0) - return; /* ignore empty packets */ - - /* - * Store the source address of the received UDP packet, to be able to use - * it in send_udp_packet as the destination address of the next UDP reply. - */ - memcpy(&(relay->remote_udpaddr), &remote_udpaddr, addrlen); - -#ifdef DEBUG - log_printf(log_debug, "Received a %d bytes UDP packet from %s", buflen, - print_addr_port((struct sockaddr *) &remote_udpaddr, addrlen)); -#endif - - p.length = htons(buflen); - if (send(relay->tcp_sock, &p, buflen + sizeof(p.length), 0) < 0) - err_sys("send(tcp)"); -} - -static void send_udp_packet(struct relay *relay) -{ - int opt = 0; - socklen_t len = sizeof(opt); - - if (relay->remote_udpaddr.ss_family == 0) { - log_printf(log_info, - "Ignoring a packet for a still unknown UDP destination!"); - return; - } - - if (sendto(relay->udp_sock, relay->packet_start, relay->packet_length, 0, - (struct sockaddr *) &relay->remote_udpaddr, - sizeof(relay->remote_udpaddr)) >= 0) - return; - - /* this is the error path */ - if (errno != ECONNREFUSED) - err_sys("sendto(udp)"); - - /* clear the error if there is no UDP listener yet on the other end */ - log_printf(log_info, "sendto(udp) returned ECONNREFUSED: ignored"); - if (getsockopt(relay->udp_sock, SOL_SOCKET, SO_ERROR, &opt, &len) < 0) - err_sys("getsockopt(udp, SOL_SOCKET, SO_ERROR)"); - - return; -} - -static void tcp_to_udp(struct relay *relay) -{ - int read_len; - - if (relay->state == uninitialized) { - if (relay->expect_handshake) { - relay->state = reading_handshake; - relay->packet_length = sizeof(relay->handshake); - } else { - relay->state = reading_length; - relay->packet_length = sizeof(uint16_t); - } - relay->buf_ptr = relay->buf; - relay->packet_start = relay->buf; - } - - read_len = read(relay->tcp_sock, relay->buf_ptr, - (relay->buf + TCPBUFFERSIZE - relay->buf_ptr)); - if (read_len < 0) - err_sys("read(tcp)"); - - if (read_len == 0) - log_printf_exit(0, log_notice, "Remote closed the connection"); - - relay->buf_ptr += read_len; - - while (relay->buf_ptr - relay->packet_start >= relay->packet_length) { - if (relay->state == reading_handshake) { - /* check the handshake string */ - if (memcmp(relay->packet_start, &(relay->handshake), - sizeof(relay->handshake)) != 0) - log_printf_exit(0, log_info, - "Received a bad handshake, exiting"); - log_printf(log_debug, "Received a good handshake"); - relay->packet_start += sizeof(relay->handshake); - relay->state = reading_length; - relay->packet_length = sizeof(uint16_t); - } else if (relay->state == reading_length) { - /* read the lenght of the next packet */ - relay->packet_length = ntohs(*(uint16_t *) relay->packet_start); - relay->packet_start += sizeof(uint16_t); - relay->state = reading_packet; - } else if (relay->state == reading_packet) { - /* read an encapsulated packet and send it as UDP */ -#ifdef DEBUG - log_printf(log_debug, "Received a %u bytes TCP packet", - relay->packet_length); -#endif - - send_udp_packet(relay); - - memmove(relay->buf, relay->packet_start + relay->packet_length, - relay->buf_ptr - - (relay->packet_start + relay->packet_length)); - relay->buf_ptr -= - relay->packet_length + (relay->packet_start - relay->buf); - relay->packet_start = relay->buf; - relay->state = reading_length; - relay->packet_length = sizeof(uint16_t); - } - } -} - -static void send_handshake(struct relay *relay) -{ - if (sendto(relay->tcp_sock, relay->handshake, sizeof(relay->handshake), 0, - (struct sockaddr *) &relay->remote_udpaddr, - sizeof(relay->remote_udpaddr)) < 0) - err_sys("sendto(tcp, handshake)"); -} - -static void wait_for_child(int sig) -{ - while (waitpid(-1, NULL, WNOHANG) > 0); -} - -static void main_loop(struct relay *relay) -{ - time_t last_udp_input, last_tcp_input; - - last_udp_input = relay->udp_timeout ? time(NULL) : 0; - last_tcp_input = relay->tcp_timeout ? time(NULL) : 0; - - while (1) { - int ready_fds; - int max = 0; - fd_set readfds; - struct timeval tv, *ptv; - - FD_ZERO(&readfds); - FD_SET(relay->tcp_sock, &readfds); - SET_MAX(relay->tcp_sock); - FD_SET(relay->udp_sock, &readfds); - SET_MAX(relay->udp_sock); - - /* - * If a data timeout was configured then set a 10s timeout for - * select. - */ - if (last_udp_input || last_tcp_input) { - tv.tv_usec = 0; - tv.tv_sec = 10; - ptv = &tv; - } else { - ptv = NULL; - } - - ready_fds = select(max, &readfds, NULL, NULL, ptv); - if (ready_fds < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - err_sys("select"); - } - - /* check the timeout if one was configured and select(2) timed out */ - if (last_udp_input && !ready_fds) { /* timeout */ - if (time(NULL) - last_udp_input > relay->udp_timeout) - log_printf_exit(0, log_notice, - "Exiting after a %ds timeout for UDP input", - relay->udp_timeout); - } - if (last_tcp_input && !ready_fds) { /* timeout */ - if (time(NULL) - last_tcp_input > relay->tcp_timeout) - log_printf_exit(0, log_notice, - "Exiting after a %ds timeout for TCP input", - relay->tcp_timeout); - } - - if (FD_ISSET(relay->tcp_sock, &readfds)) { - tcp_to_udp(relay); - if (last_tcp_input) - last_tcp_input = time(NULL); - } - if (FD_ISSET(relay->udp_sock, &readfds)) { - udp_to_tcp(relay); - if (last_udp_input) - last_udp_input = time(NULL); - } - } -} - -int main(int argc, char *argv[]) -{ - struct opts opts; - struct relay relay; - - memset(&relay, 0, sizeof(relay)); - relay.tcp_sock = -1; - - memset(&opts, 0, sizeof(opts)); - parse_args(argc, argv, &opts); - if (opts.handshake) - memcpy(relay.handshake, opts.handshake, sizeof(relay.handshake)); - - sd_notify(0, "READY=1"); - - if (opts.is_server) { - struct sigaction sa; - - sa.sa_handler = wait_for_child; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction(SIGCHLD, &sa, NULL) == -1) - err_sys("sigaction"); - - if (opts.timeout) - relay.tcp_timeout = opts.timeout; - relay.expect_handshake = 1; - - if (opts.use_inetd) { - relay.tcp_sock = 0; - log_set_options(log_get_filter_level() | log_syslog); - } else { - int socket_activation_fds = sd_listen_fds(0); - int *listening_sockets; - - if (socket_activation_fds) - listening_sockets = tcp_listener_sa(socket_activation_fds); - else - listening_sockets = tcp_listener(opts.tcpaddr); - relay.tcp_sock = accept_connections(listening_sockets); - } - relay.udp_sock = udp_client(opts.udpaddr, &relay.remote_udpaddr); - } else { - if (opts.timeout) - relay.udp_timeout = opts.timeout; - - if (opts.use_inetd) { - relay.udp_sock = 0; - log_set_options(log_get_filter_level() | log_syslog); - } else { - int socket_activation_fds = sd_listen_fds(0); - - if (socket_activation_fds) - relay.udp_sock = udp_listener_sa(socket_activation_fds); - else - relay.udp_sock = udp_listener(opts.udpaddr); - } - relay.tcp_sock = tcp_client(opts.tcpaddr); - - send_handshake(&relay); - } - - main_loop(&relay); - exit(0); -} - diff --git a/rooter/0optionalapps/udp-tunnel/src/utils.c b/rooter/0optionalapps/udp-tunnel/src/utils.c deleted file mode 100644 index 088ffe8..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/utils.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include - -#include "utils.h" - -void *do_nofail(void *ptr, const char *file, const int line) -{ - if (ptr) - return ptr; - - fprintf(stderr, "Memory allocation failure at %s:%d.", file, line); - exit(1); -} - diff --git a/rooter/0optionalapps/udp-tunnel/src/utils.h b/rooter/0optionalapps/udp-tunnel/src/utils.h deleted file mode 100644 index be91197..0000000 --- a/rooter/0optionalapps/udp-tunnel/src/utils.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2018 Marco d'Itri - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __UTILS_H__ -#define __UTILS_H__ - -#if !defined __GNUC__ && !defined __attribute__ -#define __attribute__(x) /*NOTHING*/ -#endif - -#ifndef AI_IDN -#define AI_IDN 0 -#endif - -#ifndef AI_ADDRCONFIG -#define AI_ADDRCONFIG 0 -#endif - -#ifndef SD_LISTEN_FDS_START -#define SD_LISTEN_FDS_START 0 -#define sd_listen_fds(a) 0 -#define sd_notify(a, b) -#define sd_is_socket(a, b, c, d) -1 -#endif - -#if defined __GLIBC__ || (defined __APPLE__ && defined __MACH__) -#define HAVE_GETOPT_LONG -#endif - -#ifdef HAVE_GETOPT_LONG -#define GETOPT_LONGISH(c, v, o, l, i) getopt_long(c, v, o, l, i) -#else -#define GETOPT_LONGISH(c, v, o, l, i) getopt(c, v, o) -#endif - -#define NOFAIL(ptr) do_nofail((ptr), __FILE__, __LINE__) - -void *do_nofail(void *ptr, const char *file, const int line); - -#endif diff --git a/rooter/0optionalapps/webconsole/Makefile b/rooter/0optionalapps/webconsole/Makefile deleted file mode 100644 index eb8cc4b..0000000 --- a/rooter/0optionalapps/webconsole/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=webconsole -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/webconsole - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Optional Applications - TITLE:=Install scripts for Web Console - PKGARCH:=all -endef - -define Package/webconsole/description - Helper scripts to install scripts for Web Console -endef - - -define Build/Compile -endef - -define Package/webconsole/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,webconsole)) diff --git a/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua b/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua deleted file mode 100644 index d65745a..0000000 --- a/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/controller/webconsole.lua +++ /dev/null @@ -1,31 +0,0 @@ --- A simple web console in case you don't have access to the shell --- --- Hua Shao - -module("luci.controller.webconsole", package.seeall) -local http = require("luci.http") - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" - local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - if (multilock == "0") or (multilock == "1" and rootlock == "1") then - entry({"admin", "system", "console"}, template("web/web_console"), _(translate("Web Console")), 66) - end - entry({"admin", "system", "webcmd"}, call("action_webcmd")) -end - -function action_webcmd() - local cmd = http.formvalue("cmd") - if cmd then - local fp = io.popen(tostring(cmd).." 2>&1") - local result = fp:read("*a") - fp:close() - result = result:gsub("<", "<") - http.write(tostring(result)) - else - http.write_json(http.formvalue()) - end -end diff --git a/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm b/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm deleted file mode 100644 index 682dcad..0000000 --- a/rooter/0optionalapps/webconsole/files/usr/lib/lua/luci/view/web/web_console.htm +++ /dev/null @@ -1,51 +0,0 @@ -<%+header%> - -

                          <%:Web Console%>

                          -
                          -
                          - <%:Execute shell commands or scripts as root.%><%:Be Careful%>. -

                          <%:Press%> Enter <%:to execute. Press%> Shift+Enter <%:to start a new line.%>

                          -

                          -

                          - - - - - - - -

                          
                          -    
                          -
                          - - - -<%+footer%> - diff --git a/rooter/0protocols/luci-proto-3x/Makefile b/rooter/0protocols/luci-proto-3x/Makefile deleted file mode 100644 index a28fb4e..0000000 --- a/rooter/0protocols/luci-proto-3x/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright (C) 2007-2013 OpenWrt.org -# Copyright (C) 2010 Vertical Communications -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-proto-3x -PKG_VERSION:=1.0 -PKG_RELEASE:=1 -PKG_MAINTAINER:=Dairyman -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE) - -include $(INCLUDE_DIR)/package.mk - -define Package/luci-proto-3x/Default - VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) - URL:=http://openwrt.org/ - MAINTAINER:=Dairyman -endef - -define Package/luci-proto-3x -$(call Package/luci-proto-3x/Default) - SECTION:=net - CATEGORY:=ROOter - SUBMENU:=Protocols - TITLE:=Support for 3x -endef - -define Package/luci-proto-3x/description - This package contains LuCI support for 3x -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile/Default -endef - -Build/Compile = $(Build/Compile/Default) - -define Package/luci-proto-3x/install - $(INSTALL_DIR) $(1)/usr - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/lib/lua - $(INSTALL_DIR) $(1)/usr/lib/lua/luci - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/network - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/admin_network - $(INSTALL_DATA) ./files/usr/lib/lua/luci/model/network/proto_3x.lua $(1)/usr/lib/lua/luci/model/network/ - $(INSTALL_DATA) ./files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua $(1)/usr/lib/lua/luci/model/cbi/admin_network/ -endef - -$(eval $(call BuildPackage,luci-proto-3x)) diff --git a/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua b/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua deleted file mode 100644 index 59bf2f6..0000000 --- a/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/cbi/admin_network/proto_3x.lua +++ /dev/null @@ -1,146 +0,0 @@ --- Copyright 2011 Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - -local map, section, net = ... - -local device, apn, service, pincode, username, password, dialnumber -local ipv6, maxwait, defaultroute, metric, peerdns, dns, - keepalive_failure, keepalive_interval, demand - - -device = section:taboption("general", Value, "device", translate("Modem device")) -device.rmempty = false - -local device_suggestions = nixio.fs.glob("/dev/tty[A-Z]*") - or nixio.fs.glob("/dev/tts/*") - -if device_suggestions then - local node - for node in device_suggestions do - device:value(node) - end -end - - -service = section:taboption("general", Value, "service", translate("Service Type")) -service:value("", translate("-- Please choose --")) -service:value("umts", "UMTS/GPRS") -service:value("umts_only", translate("UMTS only")) -service:value("gprs_only", translate("GPRS only")) -service:value("evdo", "CDMA/EV-DO") - - -apn = section:taboption("general", Value, "apn", translate("APN")) - - -pincode = section:taboption("general", Value, "pincode", translate("PIN")) - - -username = section:taboption("general", Value, "username", translate("PAP/CHAP username")) - - -password = section:taboption("general", Value, "password", translate("PAP/CHAP password")) -password.password = true - -dialnumber = section:taboption("general", Value, "dialnumber", translate("Dial number")) -dialnumber.placeholder = "*99***1#" - -if luci.model.network:has_ipv6() then - - ipv6 = section:taboption("advanced", Flag, "ipv6", - translate("Enable IPv6 negotiation on the PPP link")) - - ipv6.default = ipv6.disabled - -end - - -maxwait = section:taboption("advanced", Value, "maxwait", - translate("Modem init timeout"), - translate("Maximum amount of seconds to wait for the modem to become ready")) - -maxwait.placeholder = "20" -maxwait.datatype = "min(1)" - - -defaultroute = section:taboption("advanced", Flag, "defaultroute", - translate("Use default gateway"), - translate("If unchecked, no default route is configured")) - -defaultroute.default = defaultroute.enabled - - -metric = section:taboption("advanced", Value, "metric", - translate("Use gateway metric")) - -metric.placeholder = "0" -metric.datatype = "uinteger" -metric:depends("defaultroute", defaultroute.enabled) - - -peerdns = section:taboption("advanced", Flag, "peerdns", - translate("Use DNS servers advertised by peer"), - translate("If unchecked, the advertised DNS server addresses are ignored")) - -peerdns.default = peerdns.enabled - - -dns = section:taboption("advanced", DynamicList, "dns", - translate("Use custom DNS servers")) - -dns:depends("peerdns", "") -dns.datatype = "ipaddr" -dns.cast = "string" - - -keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure", - translate("LCP echo failure threshold"), - translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures")) - -function keepalive_failure.cfgvalue(self, section) - local v = m:get(section, "keepalive") - if v and #v > 0 then - return tonumber(v:match("^(%d+)[ ,]+%d+") or v) - end -end - -function keepalive_failure.write() end -function keepalive_failure.remove() end - -keepalive_failure.placeholder = "0" -keepalive_failure.datatype = "uinteger" - - -keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval", - translate("LCP echo interval"), - translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold")) - -function keepalive_interval.cfgvalue(self, section) - local v = m:get(section, "keepalive") - if v and #v > 0 then - return tonumber(v:match("^%d+[ ,]+(%d+)")) - end -end - -function keepalive_interval.write(self, section, value) - local f = tonumber(keepalive_failure:formvalue(section)) or 0 - local i = tonumber(value) or 5 - if i < 1 then i = 1 end - if f > 0 then - m:set(section, "keepalive", "%d %d" %{ f, i }) - else - m:del(section, "keepalive") - end -end - -keepalive_interval.remove = keepalive_interval.write -keepalive_interval.placeholder = "5" -keepalive_interval.datatype = "min(1)" - - -demand = section:taboption("advanced", Value, "demand", - translate("Inactivity timeout"), - translate("Close inactive connection after the given amount of seconds, use 0 to persist connection")) - -demand.placeholder = "0" -demand.datatype = "uinteger" diff --git a/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua b/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua deleted file mode 100644 index 9795a7c..0000000 --- a/rooter/0protocols/luci-proto-3x/files/usr/lib/lua/luci/model/network/proto_3x.lua +++ /dev/null @@ -1,68 +0,0 @@ ---[[ -LuCI - Network model - 3G, PPP, PPtP, PPPoE and PPPoA protocol extension - -Copyright 2011 Jo-Philipp Wich - -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. - -]]-- - -local netmod = luci.model.network - -local _, p -for _, p in ipairs({"3x"}) do - - local proto = netmod:register_protocol(p) - - function proto.get_i18n(self) - return luci.i18n.translate("UMTS/GPRS/EV-DO") - end - - function proto.ifname(self) - return p .. "-" .. self.sid - end - - function proto.opkg_package(self) - return "comgt" - end - - function proto.is_installed(self) - return nixio.fs.access("/lib/netifd/proto/3x.sh") - end - - function proto.is_floating(self) - return (p ~= "pppoe") - end - - function proto.is_virtual(self) - return true - end - - function proto.get_interfaces(self) - if self:is_floating() then - return nil - else - return netmod.protocol.get_interfaces(self) - end - end - - function proto.contains_interface(self, ifc) - if self:is_floating() then - return (netmod:ifnameof(ifc) == self:ifname()) - else - return netmod.protocol.contains_interface(self, ifc) - end - end - - netmod:register_pattern_virtual("^%s-%%w" % p) -end \ No newline at end of file diff --git a/rooter/0protocols/luci-proto-mbim/Makefile b/rooter/0protocols/luci-proto-mbim/Makefile deleted file mode 100644 index ca3441c..0000000 --- a/rooter/0protocols/luci-proto-mbim/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright (C) 2007-2013 OpenWrt.org -# Copyright (C) 2010 Vertical Communications -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-proto-mbim -PKG_VERSION:=1.0 -PKG_RELEASE:=1 -PKG_MAINTAINER:=Dairyman -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE) - -include $(INCLUDE_DIR)/package.mk - -define Package/luci-proto-mbim/Default - VERSION:=$(PKG_VERSION)-$(PKG_RELEASE) - URL:=http://openwrt.org/ - MAINTAINER:=Dairyman -endef - -define Package/luci-proto-mbim -$(call Package/luci-proto-mbim/Default) - SECTION:=net - CATEGORY:=ROOter - SUBMENU:=Protocols - TITLE:=Support for mbim -endef - -define Package/luci-proto-mbim/description - This package contains LuCI support for mbim -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile/Default -endef - -Build/Compile = $(Build/Compile/Default) - -define Package/luci-proto-mbim/install - $(INSTALL_DIR) $(1)/usr - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/lib/lua - $(INSTALL_DIR) $(1)/usr/lib/lua/luci - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/network - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi/admin_network - $(INSTALL_DATA) ./files/usr/lib/lua/luci/model/network/proto_mbim.lua $(1)/usr/lib/lua/luci/model/network/ - $(INSTALL_DATA) ./files/usr/lib/lua/luci/model/cbi/admin_network/proto_mbim.lua $(1)/usr/lib/lua/luci/model/cbi/admin_network/ -endef - -$(eval $(call BuildPackage,luci-proto-mbim)) diff --git a/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/cbi/admin_network/proto_mbim.lua b/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/cbi/admin_network/proto_mbim.lua deleted file mode 100644 index 380f471..0000000 --- a/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/cbi/admin_network/proto_mbim.lua +++ /dev/null @@ -1,45 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -local map, section, net = ... - -local device, apn, pincode, username, password -local auth, ipv6 - - -device = section:taboption("general", Value, "device", translate("Modem device")) -device.rmempty = false - -local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*") - -if device_suggestions then - local node - for node in device_suggestions do - device:value(node) - end -end - - -apn = section:taboption("general", Value, "apn", translate("APN")) - - -pincode = section:taboption("general", Value, "pincode", translate("PIN")) - - -username = section:taboption("general", Value, "username", translate("PAP/CHAP username")) - - -password = section:taboption("general", Value, "password", translate("PAP/CHAP password")) -password.password = true - -auth = section:taboption("general", Value, "auth", translate("Authentication Type")) -auth:value("", translate("-- Please choose --")) -auth:value("both", "PAP/CHAP (both)") -auth:value("pap", "PAP") -auth:value("chap", "CHAP") -auth:value("none", "NONE") - -if luci.model.network:has_ipv6() then - ipv6 = section:taboption("advanced", Flag, "ipv6", translate("Enable IPv6 negotiation")) - ipv6.default = ipv6.disabled -end \ No newline at end of file diff --git a/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua b/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua deleted file mode 100644 index 2cc525a..0000000 --- a/rooter/0protocols/luci-proto-mbim/files/usr/lib/lua/luci/model/network/proto_mbim.lua +++ /dev/null @@ -1,51 +0,0 @@ --- Copyright 2016 David Thornley --- Licensed to the public under the Apache License 2.0. - -local netmod = luci.model.network -local interface = luci.model.network.interface -local proto = netmod:register_protocol("mbim") - -function proto.get_i18n(self) - return luci.i18n.translate("MBIM") -end - -function proto.ifname(self) - local base = netmod._M.protocol - local ifname = base.ifname(self) -- call base class "protocol.ifname(self)" - - -- Note: ifname might be nil if the adapter could not be determined through ubus (default name to qmi-wan in this case) - if ifname == nil then - ifname = "mbim-" .. self.sid - end - return ifname -end - -function proto.get_interface(self) - return interface(self:ifname(), self) -end - -function proto.opkg_package(self) - return "rmbim" -end - -function proto.is_installed(self) - return nixio.fs.access("/lib/netifd/proto/mbim.sh") -end - -function proto.is_floating(self) - return true -end - -function proto.is_virtual(self) - return true -end - -function proto.get_interfaces(self) - return nil -end - -function proto.contains_interface(self, ifc) - return (netmod:ifnameof(ifc) == self:ifname()) -end - -netmod:register_pattern_virtual("^mbim-%w") \ No newline at end of file diff --git a/rooter/0routerspecfic/rd05a1/Makefile b/rooter/0routerspecfic/rd05a1/Makefile deleted file mode 100644 index c303d11..0000000 --- a/rooter/0routerspecfic/rd05a1/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=rd05a1 -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/rd05a1 - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Router Specific - DEPENDS:=+ath9k-htc-firmware +kmod-ath10k \ - +kmod-ath9k-htc - TITLE:=Install scripts for RD05A1 - PKGARCH:=all -endef - -define Package/rd05a1/description - Helper scripts to install scripts for RD05A1 -endef - - -define Build/Compile -endef - -define Package/rd05a1/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,rd05a1)) diff --git a/rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr b/rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr deleted file mode 100644 index f77fa81..0000000 --- a/rooter/0routerspecfic/rd05a1/files/etc/init.d/pciepwr +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2013 OpenWrt.org - -START=87 -USE_PROCD=1 - -log() { - logger -t "RD05A1 PCie Power" "$@" -} - -start_service() -{ - gpio=13 - echo $gpio > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio${gpio}/direction - echo 1 > /sys/class/gpio/gpio${gpio}/value - log "Turn on PCie Power" -} diff --git a/rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/QCA9887/hw1.0/board.bin b/rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/QCA9887/hw1.0/board.bin deleted file mode 100644 index 9ef7e7bbf7f17646a7dd246b1b3a5d03673a3951..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmcJNK}+LM5XUF#$%U#xYb{AgAH7!GWmkK27xb_M$*D-2O7aXP$9H+Kc&S$*h|o(x zD$=6_z2u;Wu^F(;HBKz<-qd;U&+k8z%uGUH4xo9XxHFK4atNRR%=XpK zty~oaYfrcQb2)A(U@id=aUMj!Ni-S&>i{4A!c3`DTDTWU(dRfXzO7ErKkq*EZZrW_ z0p|Zq=4+Wqzt?=L<^Kq;?ou`yzxu^2Q!A^1lvqkCMeYtS#4=6OFe>H6eS`oZM2Ha* zgcM=YO}4elGE}v+j}Rb)2r)u}kRlX)SY5=e6ebp{o=AzL2rGwbGL?f!=fE@>)oSGg zAwqz~a%D+fS>4|K`fX=pv-$DUmo2$2ScZMz(13*GjK(CP*0SviM=xni6E`*Y)>>YV zoYD(=O@6w+T~_D4aXk~CFF<{gFSe72e?fcnw_!N0q)m@P{jy`QEnMPCIB9zGHWs zPS8Qm41N$9w?^S>+>46t88E`>kYF_fi^$!@=HwSmMc&fwZlH(Wr5AgNm)7?5R=200 odKcdHqzf~-8=23~Go5!MeadUxiNxQH=Sb^217|pu!OH)ykMBIwwEzGB diff --git a/rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/QCA9887/hw1.0/firmware-5.bin b/rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/QCA9887/hw1.0/firmware-5.bin deleted file mode 100644 index 2109698c778ab8721111a8ea45780372b2e289c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 236104 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 A52+c*i}PWP{AQCH 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μ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 diff --git a/rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/cal-pci-0000_00_00.0.bin b/rooter/0routerspecfic/rd05a1/files/lib/firmware/ath10k/cal-pci-0000_00_00.0.bin deleted file mode 100644 index 4588a060625ee5c5dc7c2d7bf857c83653aab65a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2116 zcmZ?a&~RX3Jn?QB*Aztt26={1PbLnR91aEs22mgu1Y!`VU|>i9QV~u@CdRr3h6W%p zC`f=Ys7doP3NQ*VC@C>92!J62g90^;r;1tp44y2U3^QkPQpGf?7{bWN$RH{z${;Ev z1U8S0i;Dq-DF9~~7##k0{>N%UWePT7Qbe)o$1YZ|rl4;P0}RW+fs~Yt3h9%ZXk=<`Wy8QwP&#)J3|G}po&jP*=rubEN|&zz;i`I& z8U&3^+@{9Hh8h@q7-5P^$;c^?f*BZmA~Ghd*n9LW3&#Y8SqwsA9Sk#I#{Q~hVBwg| zFc&O36E0fKz|7tSR3$7vkzpQOv<4{J2^O8eFb7GLg`<_B4`@O+lDRbuY+M}-y+F}s zh6zY&*|~cdCIQXuVVI62%E8mYFa;>u0hEJ+U)3-c*>prqM$dx1n52f9iV`*~B_;Ll zT$kILj3ZrcgM@u%O@>OB+oB8=pnJ$>3y4WbO3OO9d3bvJ8kkvFTH6BCL`*`@mK}S~ z!f3y^w7zxQ_8$*QnzU%sVT3$P+y@kl6Epfpo@c4LJ))ose69@8ZKnf5vOf^UaruiT /sys/class/gpio/export -echo out > /sys/class/gpio/gpio$wd_gpio/direction - -while [ 1 ] -do - echo 1 >/sys/class/gpio/gpio$wd_gpio/value - sleep 1 - echo 0 >/sys/class/gpio/gpio$wd_gpio/value - sleep 1 - - echo 1 >/sys/class/gpio/gpio$wd_gpio/value - sleep 1 - echo 0 >/sys/class/gpio/gpio$wd_gpio/value - sleep 1 - - echo 1 >/sys/class/gpio/gpio$wd_gpio/value - sleep 1 - echo 0 >/sys/class/gpio/gpio$wd_gpio/value - sleep 1 -done diff --git a/rooter/0routerspecfic/we826q/files/usr/lib/rooter/changedevice.sh b/rooter/0routerspecfic/we826q/files/usr/lib/rooter/changedevice.sh deleted file mode 100644 index 507c479..0000000 --- a/rooter/0routerspecfic/we826q/files/usr/lib/rooter/changedevice.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Change Device" "$@" -} - -uci set system.led_wan.dev=$1 -uci commit system -/etc/init.d/led restart \ No newline at end of file diff --git a/rooter/0splash/ext-splash/Makefile b/rooter/0splash/ext-splash/Makefile deleted file mode 100644 index 8372994..0000000 --- a/rooter/0splash/ext-splash/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-splash -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-splash - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Splash Screens - TITLE:=Added scripts for Login display - PKGARCH:=all -endef - -define Package/ext-splash/description - Added scripts for Login display -endef - - -define Build/Compile -endef - -define Package/ext-splash/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-splash)) diff --git a/rooter/0splash/ext-splash/files/etc/config/iframe b/rooter/0splash/ext-splash/files/etc/config/iframe deleted file mode 100644 index a97bc1d..0000000 --- a/rooter/0splash/ext-splash/files/etc/config/iframe +++ /dev/null @@ -1,17 +0,0 @@ - -config iframe 'iframe' - option splashpage '0' - option splashtitle 'ROOter' - option url 'www.ofmodemsandmen.com' - option dual '0' - option speed '0' - option band '0' - -config login 'login' - option logframe '0' - option logtype '3' - option logimage 'open.png' - option logimageheight '300' - option logimagewidth '300' - option logimagepos 'absmiddle' - diff --git a/rooter/0splash/ext-splash/files/etc/init.d/iframeint b/rooter/0splash/ext-splash/files/etc/init.d/iframeint deleted file mode 100644 index 79f6de6..0000000 --- a/rooter/0splash/ext-splash/files/etc/init.d/iframeint +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2013 OpenWrt.org - -START=60 -USE_PROCD=1 - -log() { - logger -t "iframe" "$@" -} - -start_service() -{ - if [ ! -d /tmp/www ]; then - mkdir -p /tmp/www - fi - /usr/lib/iframe/create.sh & - /usr/lib/iframe/status.sh & -} diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/band.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/band.html deleted file mode 100644 index 9db882d..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/band.html +++ /dev/null @@ -1 +0,0 @@ -

                          Bandwidth Usage
                          \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh deleted file mode 100644 index 1c5a776..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/bwdays.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -genline() { - MONLIST=$MONLIST"" - t1="
                          $START
                          " - t2="
                          $updata
                          " - t3="
                          $downdata
                          " - t4="
                          $totaldata
                          " - MONLIST=$MONLIST$t1$t2$t3$t4"" -} - -bwdata() { - START="-" - END="-" - header=0 - while IFS= read -r line; do - if [ $header -eq 0 ]; then - days=$line - read -r line - DOWN=$line - read -r line - UP=$line - read -r line - TOTAL=$line - read -r line - line=$(echo $line" " | tr "|" ",") - END=$(echo $line | cut -d, -f1) - START=$END - updata=$(echo $line | cut -d, -f2) - downdata=$(echo $line | cut -d, -f3) - totaldata=$(echo $line | cut -d, -f4) - genline - read -r line - header=1 - if [ -z "$line" ]; then - break - fi - fi - line=$(echo $line" " | tr "|" ",") - START=$(echo $line | cut -d, -f1) - updata=$(echo $line | cut -d, -f2) - downdata=$(echo $line | cut -d, -f3) - totaldata=$(echo $line | cut -d, -f4) - genline - - done < /usr/lib/bwmon/data/monthly.data -} - -currdata() { - while IFS= read -r line; do - if [ $line = '0' ]; then - break - else - cdays=$line - read -r line - read -r line - ctused=$line - read -r line - read -r line - ctdwn=$line - read -r line - read -r line - ctup=$line - read -r line - read -r line - cproject=$line - break - fi - done < /tmp/bwdata -} - - STEMP="/tmp/www/dtemp.html" - STATUS="/usr/lib/iframe/bwtemplate.html" - IFSTATUS="/tmp/www/daylist.html" - - MONLIST="" - - rm -f $STEMP - cp $STATUS $STEMP - if [ -e /usr/lib/bwmon/data/monthly.data ]; then - #MONLIST="" - bwdata - MONLIST=$MONLIST"
                          " - else - START="-" - END="-" - TOTAL="-" - DOWN="-" - UP="-" - fi - - currdata - - sed -i -e "s!#START#!$START!g" $STEMP - sed -i -e "s!#END#!$END!g" $STEMP - sed -i -e "s!#TOTAL#!$TOTAL!g" $STEMP - sed -i -e "s!#DOWN#!$DOWN!g" $STEMP - sed -i -e "s!#UP#!$UP!g" $STEMP - sed -i -e "s!#MONLIST#!$MONLIST!g" $STEMP - - sed -i -e "s!#CDAYS#!$cdays!g" $STEMP - sed -i -e "s!#CTOTAL#!$ctused!g" $STEMP - sed -i -e "s!#CDOWN#!$ctdwn!g" $STEMP - sed -i -e "s!#CUP#!$ctup!g" $STEMP - sed -i -e "s!#PROJECT#!$cproject!g" $STEMP - - mv $STEMP $IFSTATUS - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html deleted file mode 100644 index 81b6ec9..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/bwtemplate.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - -

                          Current Month's Bandwidth Usage

                          -
                          -
                          -
                          -
                          Days
                          - #CDAYS# -
                          -
                          -
                          Total Amount Used
                          - #CTOTAL# -
                          -
                          -
                          -
                          -
                          Downloaded
                          - #CDOWN# -
                          -
                          -
                          Uploaded
                          - #CUP# -
                          -
                          -
                          Projected Amount
                          - #PROJECT# -
                          -
                          -
                          - -

                          Last 30 Day Bandwidth Usage

                          - - -
                          -
                          -
                          -
                          Starting Date
                          - #START# -
                          -
                          -
                          Ending Date
                          - #END# -
                          -
                          -
                          -
                          -
                          Total
                          - #TOTAL# -
                          -
                          -
                          Download
                          - #DOWN# -
                          -
                          -
                          Upload
                          - #UP# -
                          -
                          -
                          - -
                          - - - - - - - - - #MONLIST# - - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh deleted file mode 100644 index 5a292e5..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/create.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -bwdata() { - result=`ps | grep -i "create_data.lua" | grep -v "grep" | wc -l` - if [ $result -lt 1 ]; then - lua /usr/lib/bwmon/create_data.lua - fi - while [ true ] - do - if [ -e /tmp/bwdata ]; then - break - fi - sleep 1 - done -} - -bwdata -/usr/lib/iframe/update.sh -logtype=$(uci -q get iframe.login.logtype) -if [ $logtype = "1" ]; then - sleep 300 - while [ true ] - do - result=`ps | grep -i "update.sh" | grep -v "grep" | wc -l` - if [ $result -lt 1 ]; then - /usr/lib/iframe/update.sh - fi - sleep 300 - done -fi \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html deleted file mode 100644 index ba5170d..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/daylist.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - -

                          Current Month's Bandwidth Usage

                          -
                          -
                          -
                          -
                          Days
                          - 10 -
                          -
                          -
                          Total Amount Used
                          - 451.39 MB -
                          -
                          -
                          -
                          -
                          Downloaded
                          - 409.57 MB -
                          -
                          -
                          Uploaded
                          - 41.82 MB -
                          -
                          -
                          Projected Amount
                          - 1.35 GB -
                          -
                          -
                          - -

                          Last 30 Day Bandwidth Usage

                          - - -
                          -
                          -
                          -
                          Starting Date
                          - 2022-01-03 -
                          -
                          -
                          Ending Date
                          - 2022-01-15 -
                          -
                          -
                          -
                          -
                          Total
                          - 360.05 MB -
                          -
                          -
                          Download
                          - 322.79 MB -
                          -
                          -
                          Upload
                          - 37.25 MB -
                          -
                          -
                          - -
                          -
                          DATE
                          DOWN
                          UP
                          TOTAL
                          - - - - - - - -
                          DATE
                          DOWN
                          UP
                          TOTAL
                          2022-01-15
                          0.00 K
                          0.00 K
                          0.00 K
                          2022-01-14
                          0.00 K
                          0.00 K
                          0.00 K
                          2022-01-13
                          41.87 MB
                          1.71 MB
                          43.58 MB
                          2022-01-12
                          0.00 K
                          0.00 K
                          0.00 K
                          2022-01-07
                          18.56 MB
                          5.24 MB
                          23.80 MB
                          2022-01-06
                          175.59 MB
                          25.72 MB
                          201.32 MB
                          2022-01-04
                          56.19 MB
                          3.59 MB
                          59.78 MB
                          2022-01-03
                          30.58 MB
                          986.00 K
                          31.57 MB
                          -
                          - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html deleted file mode 100644 index aa47d93..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/iframe.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - -

                          #TITLE#

                          - -
                          -
                          -
                          -
                          Reporting Period (Days)
                          - #DAYS# -
                          -
                          -
                          -
                          -
                          Total Bandwidth Used
                          - #TOTAL# -
                          -
                          -
                          Projected Use
                          - #PROJ# -
                          -
                          -
                          -
                          -
                          Total Downloaded
                          - #DOWN# -
                          -
                          -
                          Total Uploaded
                          - #UP# -
                          -
                          -
                          - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/image.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/image.html deleted file mode 100644 index a7b9893..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/image.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - -

                           

                          -

                          - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/mframe.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/mframe.html deleted file mode 100644 index 589c857..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/mframe.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - -
                          -

                          Modem 1

                          -
                          -
                          -
                          Strength (%)
                          - #PER# -
                          -
                          -
                          CSQ
                          - #CSQ# -
                          -
                          -
                          RSSI (dBm)
                          - #RSSI# -
                          -
                          -
                          RSCP (dBm) RSRP
                          - #RSCP# -
                          -
                          -
                          ECIO (dB) RSRQ
                          - #RSRQ# -
                          -
                          -
                          SINR (dB)
                          - #SINR# -
                          -
                          - -
                          -

                          Network

                          - -
                          -
                          -
                          Mode
                          - #MODE# -
                          -
                          -
                          MCC
                          - #MCC# -
                          -
                          -
                          MNC
                          - #MNC# -
                          -
                          -
                          RNC/eNB ID
                          - #RNC# #RNCN# -
                          - -
                          -
                          LAC
                          - #LAC# #LACN# -
                          -
                          -
                          Channel (EARFCN)
                          - #CHAN# -
                          -
                          -
                          PCI
                          - #CELLID# -
                          -
                          -
                          Bands
                          - #BAND# -
                          -
                          -
                          -
                          -

                          Device

                          - -
                          -
                          -
                          Router
                          - #ROUTER# -
                          -
                          -
                          Modem
                          - #MODEM# -
                          -
                          -
                          Provider
                          - #PROVIDER# -
                          -
                          -
                          Protocol
                          - #PROTO# -
                          -
                          -
                          Port
                          - #PORT# -
                          -
                          -
                          Temperature
                          - #TEMP# -
                          -
                          -
                          -
                          - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html deleted file mode 100644 index 5957a8b..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/modem2.html +++ /dev/null @@ -1 +0,0 @@ -

                          Modem 2

                          Strength (%)
                          #PER#
                          CSQ
                          #CSQ#
                          RSSI (dBm)
                          #RSSI#
                          RSCP (dBm) RSRP
                          #RSCP#
                          ECIO (dB) RSRQ
                          #RSRQ#
                          SINR (dB)
                          #SINR#

                          Network

                          Mode
                          #MODE#
                          MCC
                          #MCC#
                          MNC
                          #MNC#
                          RNC/eNB ID
                          #RNC# #RNCN#
                          LAC
                          #LAC# #LACN#
                          Channel (EARFCN)
                          #CHAN#
                          PCI
                          #CELLID#
                          Bands
                          #BAND#

                          Device

                          Modem
                          #MODEM#
                          Provider
                          #MODEMN#
                          Protocol
                          #PROTO#
                          Port
                          #PORT#
                          Temperature
                          #TEMP#
                          \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/open.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/open.html deleted file mode 100644 index fa7d40d..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/open.html +++ /dev/null @@ -1 +0,0 @@ -
                          OpenSpeedTest
                          \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html deleted file mode 100644 index 0338c71..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/speed.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

                          OpenSpeedTest

                          - -
                          - -
                          - -
                          - - - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/status.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/status.html deleted file mode 100644 index 7c7c33d..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/status.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - #TITLEBAR# - #BUTTON# -
                          -

                          Modem 1

                          -
                          -
                          -
                          Strength (%)
                          - #PER# -
                          -
                          -
                          CSQ
                          - #CSQ# -
                          -
                          -
                          RSSI (dBm)
                          - #RSSI# -
                          -
                          -
                          RSCP (dBm) RSRP
                          - #RSCP# -
                          -
                          -
                          ECIO (dB) RSRQ
                          - #RSRQ# -
                          -
                          -
                          SINR (dB)
                          - #SINR# -
                          -
                          - -
                          -

                          Network

                          - -
                          -
                          -
                          Mode
                          - #MODE# -
                          -
                          -
                          MCC
                          - #MCC# -
                          -
                          -
                          MNC
                          - #MNC# -
                          -
                          -
                          RNC/eNB ID
                          - #RNC# #RNCN# -
                          - -
                          -
                          LAC
                          - #LAC# #LACN# -
                          -
                          -
                          Channel (EARFCN)
                          - #CHAN# -
                          -
                          -
                          PCI
                          - #CELLID# -
                          -
                          -
                          Bands
                          - #BAND# -
                          -
                          -
                          -
                          -

                          Device

                          - -
                          -
                          -
                          Router
                          - #ROUTER# -
                          -
                          -
                          Modem
                          - #MODEM# -
                          -
                          -
                          Provider
                          - #PROVIDER# -
                          -
                          -
                          Protocol
                          - #PROTO# -
                          -
                          -
                          Port
                          - #PORT# -
                          -
                          -
                          Temperature
                          - #TEMP# -
                          -
                          -
                          External IP
                          - #EXTERNAL# -
                          -
                          -
                          - #MODEM2# -
                          - - - #OPEN# - - #BWMON# - - - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh deleted file mode 100644 index ed0881b..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/status.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -/usr/lib/rooter/signal/status.sh 1 "No Modem Present" - -while [ true ] -do - result=`ps | grep -i "stupdate.sh" | grep -v "grep" | wc -l` - if [ $result -lt 1 ]; then - /usr/lib/iframe/stupdate.sh - /usr/lib/iframe/bwdays.sh - fi - splash=$(uci -q get iframe.iframe.splashpage) - if [ $splash = "1" ]; then - mv /www/splash_files/check1.gif /www/splash_files/check.gif - ln -s /tmp/www/splash.html /www/splash.html - else - mv /www/splash_files/check.gif /www/splash_files/check1.gif - rm -f /www/splash.html - fi - sleep 10 -done \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh deleted file mode 100644 index 656a8f2..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/stupdate.sh +++ /dev/null @@ -1,404 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Status Update" "$@" -} - -levelsper="101,85,70,55,40,25,0" -namesper="Perfect,Excellent,Good,Medium,Low,Bad,Dead" -levelsrssi="1,70,90,100,119,113,0" -namesrssi="Perfect,High,Medium,Poor,Bad,None" -levelsrscp="50,70,90,100,112,136,140,0" -namesrscp='High (3G) :High (4G),Medium (3G) : High (4G),Poor (3G) : Good (4G),Weak (3G) : Medium (4G),None (3G) : Poor (4G)' - -level2txt() { - tmp="$1" - key=$2 - front="" - tmp1="$tmp"" " - if [ "$tmp" = "-" ]; then - namev="""--""" - return - fi - if [ $key = "per" ]; then - tmp=$(echo "$tmp" | sed -e "s/%//g") - level=$levelsper - namev=$namesper - namez=$namev - cindex=1 - nindex=0 - namev="-" - while [ true ] - do - levelv=$(echo "$level" | cut -d, -f$cindex) - if [ $levelv = "0" ]; then - namev="-" - break - fi - if [ "$tmp" -ge "$levelv" ]; then - nind=$((${nindex}+1)) - namev=$(echo "$namez" | cut -d, -f$nind) - break - fi - cindex=$((${cindex}+1)) - nindex=$((${nindex}+1)) - done - css="level_"$nindex - desc="
                          "$namev"
                          " - namev="""$front$tmp1"""$desc - return - fi - if [ $key = "rssi" ]; then - front="-" - tmp=$(echo "$tmp" | sed -e "s/-//g") - tmp=$(echo "$tmp" | sed -e "s/dBm//g") - tmp1="$tmp"" " - level=$levelsrssi - namev=$namesrssi - namez=$namev - cindex=1 - nindex=0 - namev="-" - while [ true ] - do - levelv=$(echo "$level" | cut -d, -f$cindex) - if [ $levelv = "0" ]; then - namev="-" - break - fi - if [ "$tmp" -le "$levelv" ]; then - nindex=$((${nindex}+1)) - namev=$(echo "$namez" | cut -d, -f$nindex) - break - fi - cindex=$((${cindex}+1)) - nindex=$((${nindex}+1)) - done - css="level_"$nindex - desc="
                          "$namev"
                          " - namev="""$front$tmp1"""$desc - return - fi - if [ $key = "rscp" ]; then - front="" - tmp=$(echo "$tmp" | sed -e "s/dBm//g") - tmp=$(echo "$tmp" | sed -e "s/([^)]*)//g") - tmp1="$tmp"" " - tmp=$(echo "$tmp" | sed -e "s/-//g") - tmp=$(echo "$tmp" | tr " " "," | cut -d, -f1 ) - tmp=$(printf %.0f "$tmp") - level=$levelsrscp - namev=$namesrscp - namez=$namev - cindex=1 - nindex=0 - namev="-" - while [ true ] - do - levelv=$(echo "$level" | cut -d, -f$cindex) - if [ $levelv = "0" ]; then - namev="-" - break - fi - if [ "$tmp" -le "$levelv" ]; then - namev=$(echo "$namez" | cut -d, -f$nindex) - nindex=$((${nindex}-1)) - break - fi - cindex=$((${cindex}+1)) - nindex=$((${nindex}+1)) - done - css="level_"$nindex - desc="
                          "$namev"
                          " - namev="""$front$tmp1"""$desc - return - fi - - if [ $key = "single" ]; then - desc="" - tmp=$(echo "$tmp" | sed -e "s/dBm//g") - tmp=$(echo "$tmp" | sed -e "s/dB//g") - if [ $3 != "1" ];then - tmp=$(echo "$tmp" | sed -e "s/-//g") - fi - if [ $3 = "1" -o $3 = "0" ];then - desc="
                          "."
                          " - fi - namev="""$tmp"""$desc - return - fi -} - -readstatus() { -modd=$1 - while IFS= read -r line; do - port="$line" - read -r line - csq="$line" - read -r line - per="$line" - read -r line - rssi="$line" - read -r line - modem="$line" - read -r line - cops="$line" - read -r line - mode="$line" - read -r line - lac="$line" - read -r line - lacn="$line" - read -r line - cid="$line" - - read -r line - cidn="$line" - read -r line - mcc="$line" - read -r line - mnc="$line" - read -r line - rnc="$line" - read -r line - rncn="$line" - read -r line - down="$line" - read -r line - up="$line" - read -r line - ecio="$line" - read -r line - rscp="$line" - read -r line - ecio1="$line" - - read -r line - rscp1="$line" - read -r line - netmode="$line" - read -r line - cell="$line" - read -r line - modtype="$line" - read -r line - conntype="$line" - read -r line - channel="$line" - read -r line - phone="$line" - read -r line - read -r line - lband="$line" - read -r line - tempur="$line" - - read -r line - proto="$line" - read -r line - pci="$line" - read -r line - sinr="$line" - break - done < /tmp/status$modd.file -} - -bwdata() { - while IFS= read -r line; do - if [ $line = '0' ]; then - nodata="1" - break - else - nodata="0" - days=$line - read -r line - read -r line - tused=$line - read -r line - read -r line - tdwn=$line - read -r line - read -r line - tup=$line - read -r line - read -r line - project=$line - break - fi - done < /tmp/bwdata -} - -splash=$(uci -q get iframe.iframe.splashpage) - -if [ $splash = "1" ]; then - STEMP="/tmp/www/stemp.html" - STATUS="/usr/lib/iframe/status.html" - SPSTATUS="/tmp/www/splash.html" - rm -f $STEMP - cp $STATUS $STEMP - button="" - sed -i -e "s!#BUTTON#!$button!g" $STEMP - sed -i -e "s!#LUCIS#!luci-static/!g" $STEMP - titlebar="" - url=$(uci -q get iframe.iframe.url) - if [ -z $url ]; then - url="www.ofmodemsandmen.com" - fi - titlebar=$(echo "$titlebar" | sed -e "s!#URL#!$url!g") - sed -i -e "s!#TITLEBAR#!$titlebar!g" $STEMP - title=$(uci -q get iframe.iframe.splashtitle) - sed -i -e "s!#TITLE#!$title!g" $STEMP - - readstatus 1 - level2txt "$csq" "single" 0 - sed -i -e "s!#CSQ#!$namev!g" $STEMP - level2txt "$per" "per" - sed -i -e "s!#PER#!$namev!g" $STEMP - level2txt "$rssi" "rssi" - sed -i -e "s!#RSSI#!$namev!g" $STEMP - level2txt "$rscp" "rscp" - sed -i -e "s!#RSCP#!$namev!g" $STEMP - level2txt "$ecio" "single" 1 - sed -i -e "s!#RSRQ#!$namev!g" $STEMP - level2txt "$sinr" "single" 1 - sed -i -e "s!#SINR#!$namev!g" $STEMP - - level2txt "$mode" "single" - sed -i -e "s!#MODE#!$namev!g" $STEMP - level2txt "$mcc" "single" - sed -i -e "s!#MCC#!$namev!g" $STEMP - level2txt "$mnc" "single" - sed -i -e "s!#MNC#!$namev!g" $STEMP - level2txt "$rnc" "single" - sed -i -e "s!#RNC#!$namev!g" $STEMP - level2txt "$rncn" "single" - sed -i -e "s!#RNCN#!$namev!g" $STEMP - level2txt "$lac" "single" - sed -i -e "s!#LAC#!$namev!g" $STEMP - level2txt "$lacn" "single" - sed -i -e "s!#LACN#!$namev!g" $STEMP - level2txt "$pci" "single" - sed -i -e "s!#CELLID#!$namev!g" $STEMP - level2txt "$channel" "single" - sed -i -e "s!#CHAN#!$namev!g" $STEMP - level2txt "$lband" "single" - sed -i -e "s!#BAND#!$namev!g" $STEMP - - if [ -e /etc/custom ]; then - mod="/etc/custom" - else - mod="/tmp/sysinfo/model" - fi - while IFS= read -r line; do - ROUTER=$line - break - done < $mod - level2txt "$ROUTER" "single" - sed -i -e "s!#ROUTER#!$namev!g" $STEMP - level2txt "$modem" "single" - sed -i -e "s!#MODEM#!$namev!g" $STEMP - level2txt "$cops" "single" - namev=$(echo "$namev" | tr -d '&') - sed -i -e "s~#PROVIDER#~$namev~g" $STEMP - level2txt "$proto" "single" - sed -i -e "s!#PROTO#!$namev!g" $STEMP - level2txt "$port" "single" - sed -i -e "s!#PORT#!$namev!g" $STEMP - level2txt "$tempur" "single" - sed -i -e "s!#TEMP#!$namev!g" $STEMP - rm -f /tmp/spip; wget -O /tmp/spip http://ipecho.net/plain > /dev/null 2>&1 - extr=$(cat /tmp/spip) - if [ -z "$extr" ]; then - extr="-" - fi - level2txt "$extr" "single" - sed -i -e "s!#EXTERNAL#!$namev!g" $STEMP - - dual=$(uci -q get iframe.iframe.dual) - if [ $dual = "1" ]; then - STEMP2="/tmp/www/stemp2.html" - STATUS2="/usr/lib/iframe/modem2.html" - rm -f $STEMP2 - cp $STATUS2 $STEMP2 - - readstatus 2 - level2txt "$csq" "single" 0 - sed -i -e "s!#CSQ#!$namev!g" $STEMP2 - level2txt "$per" "per" - sed -i -e "s!#PER#!$namev!g" $STEMP2 - level2txt "$rssi" "rssi" - sed -i -e "s!#RSSI#!$namev!g" $STEMP2 - level2txt "$rscp" "rscp" - sed -i -e "s!#RSCP#!$namev!g" $STEMP2 - level2txt "$ecio" "single" 1 - sed -i -e "s!#RSRQ#!$namev!g" $STEMP2 - level2txt "$sinr" "single" 1 - sed -i -e "s!#SINR#!$namev!g" $STEMP2 - - level2txt "$mode" "single" - sed -i -e "s!#MODE#!$namev!g" $STEMP2 - level2txt "$mcc" "single" - sed -i -e "s!#MCC#!$namev!g" $STEMP2 - level2txt "$mnc" "single" - sed -i -e "s!#MNC#!$namev!g" $STEMP2 - level2txt "$rnc" "single" - sed -i -e "s!#RNC#!$namev!g" $STEMP2 - level2txt "$rncn" "single" - sed -i -e "s!#RNCN#!$namev!g" $STEMP2 - level2txt "$lac" "single" - sed -i -e "s!#LAC#!$namev!g" $STEMP2 - level2txt "$lacn" "single" - sed -i -e "s!#LACN#!$namev!g" $STEMP2 - level2txt "$pci" "single" - sed -i -e "s!#CELLID#!$namev!g" $STEMP2 - level2txt "$channel" "single" - sed -i -e "s!#CHAN#!$namev!g" $STEMP2 - level2txt "$lband" "single" - sed -i -e "s!#BAND#!$namev!g" $STEMP2 - - level2txt "$modem" "single" - sed -i -e "s!#MODEM#!$namev!g" $STEMP2 - level2txt "$cops" "single" - namev=$(echo "$namev" | tr -d '&') - sed -i -e "s!#MODEMN#!$namev!g" $STEMP2 - level2txt "$proto" "single" - sed -i -e "s!#PROTO#!$namev!g" $STEMP2 - level2txt "$port" "single" - sed -i -e "s!#PORT#!$namev!g" $STEMP2 - level2txt "$tempur" "single" - sed -i -e "s!#TEMP#!$namev!g" $STEMP2 - - MODEM2=$(cat $STEMP2) - sed -i -e "s!#MODEM2#!$MODEM2!g" $STEMP - else - sed -i -e "s!#MODEM2#!!g" $STEMP - fi - - open=$(uci -q get iframe.iframe.speed) - if [ $open = "1" ]; then - STEMP2="/tmp/www/stemp2.html" - STATUS2="/usr/lib/iframe/open.html" - rm -f $STEMP2 - cp $STATUS2 $STEMP2 - MODEM2=$(cat $STEMP2) - sed -i -e "s!#OPEN#!$MODEM2!g" $STEMP - else - sed -i -e "s!#OPEN#!!g" $STEMP - fi - - band=$(uci -q get iframe.iframe.band) - if [ $band = "1" ]; then - STEMP2="/tmp/www/stemp2.html" - STATUS2="/usr/lib/iframe/band.html" - rm -f $STEMP2 - cp $STATUS2 $STEMP2 - MODEM2=$(cat $STEMP2) - sed -i -e "s!#BWMON#!$MODEM2!g" $STEMP - else - sed -i -e "s!#BWMON#!!g" $STEMP - fi - - mv $STEMP $SPSTATUS -fi - diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh b/rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh deleted file mode 100644 index e6cb8df..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/update.sh +++ /dev/null @@ -1,301 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Status Update" "$@" -} - -levelsper="101,85,70,55,40,25,10,1,0" -namesper="Perfect,Excellent,Good,Medium,Low,Bad,Dead" -levelsrssi="113,119,100,90,70,1,0" -namesrssi="None,Bad,Poor,Medium,High,Perfect" -levelsrscp="140,136,112,100,90,70,50,1,0" -namesrscp='None,None (3G) : Poor (4G),Weak (3G) : Medium (4G),Poor (3G) : Good (4G),Medium (3G) : High (4G),High (3G) :High (4G)' - -level2txt() { - tmp="$1" - key=$2 - front="" - tmp1="$tmp"" " - if [ "$tmp" = "-" ]; then - namev="""--""" - return - fi - if [ $key = "per" ]; then - tmp=$(echo "$tmp" | sed -e "s/%//g") - level=$levelsper - namev=$namesper - fi - if [ $key = "rssi" ]; then - front="-" - tmp=$(echo "$tmp" | sed -e "s/-//g") - tmp=$(echo "$tmp" | sed -e "s/dBm//g") - tmp1="$tmp"" " - level=$levelsrssi - namev=$namesrssi - fi - if [ $key = "rscp" ]; then - front="" - tmp=$(echo "$tmp" | sed -e "s/dBm//g") - tmp=$(echo "$tmp" | sed -e "s/([^)]*)//g") - tmp1="$tmp"" " - tmp=$(echo "$tmp" | sed -e "s/-//g") - tmp=$(echo "$tmp" | tr " " "," | cut -d, -f1 ) - tmp=$(printf %.0f "$tmp") - level=$levelsrscp - namev=$namesrscp - fi - - if [ $key = "single" ]; then - desc="" - tmp=$(echo "$tmp" | sed -e "s/dBm//g") - tmp=$(echo "$tmp" | sed -e "s/dB//g") - if [ $3 != "1" ];then - tmp=$(echo "$tmp" | sed -e "s/-//g") - fi - if [ $3 = "1" -o $3 = "0" ];then - desc="
                          "."
                          " - fi - namev="""$tmp"""$desc - return - fi - - namez=$namev - cindex=1 - nindex=0 - namev="-" - - while [ true ] - do - levelv=$(echo "$level" | cut -d, -f$cindex) - if [ $levelv = "0" ]; then - namev="-" - break - fi - if [ "$tmp" -ge "$levelv" ]; then - namev=$(echo "$namez" | cut -d, -f$nindex) - break - fi - cindex=$((${cindex}+1)) - nindex=$((${nindex}+1)) - done - - css="level_"$nindex - desc="
                          "$namev"
                          " - namev="""$front$tmp1"""$desc -} - -readstatus() { -modd=$1 - while IFS= read -r line; do - port="$line" - read -r line - csq="$line" - read -r line - per="$line" - read -r line - rssi="$line" - read -r line - modem="$line" - read -r line - cops="$line" - read -r line - mode="$line" - read -r line - lac="$line" - read -r line - lacn="$line" - read -r line - cid="$line" - - read -r line - cidn="$line" - read -r line - mcc="$line" - read -r line - mnc="$line" - read -r line - rnc="$line" - read -r line - rncn="$line" - read -r line - down="$line" - read -r line - up="$line" - read -r line - ecio="$line" - read -r line - rscp="$line" - read -r line - ecio1="$line" - - read -r line - rscp1="$line" - read -r line - netmode="$line" - read -r line - cell="$line" - read -r line - modtype="$line" - read -r line - conntype="$line" - read -r line - channel="$line" - read -r line - phone="$line" - read -r line - read -r line - lband="$line" - read -r line - tempur="$line" - - read -r line - proto="$line" - read -r line - pci="$line" - read -r line - sinr="$line" - break - done < /tmp/status$modd.file -} -bwdata() { - while IFS= read -r line; do - if [ $line = '0' ]; then - nodata="1" - break - else - nodata="0" - days=$line - read -r line - read -r line - tused=$line - read -r line - read -r line - tdwn=$line - read -r line - read -r line - tup=$line - read -r line - read -r line - project=$line - break - fi - done < /tmp/bwdata -} - -logtype=$(uci -q get iframe.login.logtype) -if [ $logtype = "1" ]; then - STEMP="/tmp/www/itemp.html" - STATUS="/usr/lib/iframe/mframe.html" - IFSTATUS="/tmp/www/display.html" - - rm -f $STEMP - cp $STATUS $STEMP - readstatus 1 - level2txt "$csq" "single" 0 - sed -i -e "s!#CSQ#!$namev!g" $STEMP - level2txt "$per" "per" - sed -i -e "s!#PER#!$namev!g" $STEMP - level2txt "$rssi" "rssi" - sed -i -e "s!#RSSI#!$namev!g" $STEMP - level2txt "$rscp" "rscp" - sed -i -e "s!#RSCP#!$namev!g" $STEMP - level2txt "$ecio" "single" 1 - sed -i -e "s!#RSRQ#!$namev!g" $STEMP - level2txt "$sinr" "single" 1 - sed -i -e "s!#SINR#!$namev!g" $STEMP - - level2txt "$mode" "single" - sed -i -e "s!#MODE#!$namev!g" $STEMP - level2txt "$mcc" "single" - sed -i -e "s!#MCC#!$namev!g" $STEMP - level2txt "$mnc" "single" - sed -i -e "s!#MNC#!$namev!g" $STEMP - level2txt "$rnc" "single" - sed -i -e "s!#RNC#!$namev!g" $STEMP - level2txt "$rncn" "single" - sed -i -e "s!#RNCN#!$namev!g" $STEMP - level2txt "$lac" "single" - sed -i -e "s!#LAC#!$namev!g" $STEMP - level2txt "$lacn" "single" - sed -i -e "s!#LACN#!$namev!g" $STEMP - level2txt "$pci" "single" - sed -i -e "s!#CELLID#!$namev!g" $STEMP - level2txt "$channel" "single" - sed -i -e "s!#CHAN#!$namev!g" $STEMP - level2txt "$lband" "single" - sed -i -e "s!#BAND#!$namev!g" $STEMP - - if [ -e /etc/custom ]; then - mod="/etc/custom" - else - mod="/tmp/sysinfo/model" - fi - while IFS= read -r line; do - ROUTER=$line - break - done < $mod - level2txt "$ROUTER" "single" - sed -i -e "s!#ROUTER#!$namev!g" $STEMP - level2txt "$modem" "single" - sed -i -e "s!#MODEM#!$namev!g" $STEMP - level2txt "$cops" "single" - namev=$(echo "$namev" | tr -d '&') - sed -i -e "s!#PROVIDER#!$namev!g" $STEMP - level2txt "$proto" "single" - sed -i -e "s!#PROTO#!$namev!g" $STEMP - level2txt "$port" "single" - sed -i -e "s!#PORT#!$namev!g" $STEMP - level2txt "$tempur" "single" - sed -i -e "s!#TEMP#!$namev!g" $STEMP - - mv $STEMP $IFSTATUS -fi - -if [ $logtype = "2" ]; then - STEMP="/tmp/www/itemp.html" - STATUS="/usr/lib/iframe/image.html" - IFSTATUS="/tmp/www/display.html" - - rm -f $STEMP - cp $STATUS $STEMP - logimage=$(uci -q get iframe.login.logimage) - sed -i -e "s!#IMAGE#!$logimage!g" $STEMP - logimagewidth=$(uci -q get iframe.login.logimagewidth) - sed -i -e "s!#WIDTH#!$logimagewidth!g" $STEMP - - mv $STEMP $IFSTATUS -fi - -if [ $logtype = "4" ]; then - STEMP="/tmp/www/itemp.html" - STATUS="/usr/lib/iframe/speed.html" - IFSTATUS="/tmp/www/display.html" - - rm -f $STEMP - cp $STATUS $STEMP - - mv $STEMP $IFSTATUS -fi - -if [ $logtype = "3" ]; then - STEMP="/tmp/www/itemp.html" - STATUS="/usr/lib/iframe/zerotier.html" - IFSTATUS="/tmp/www/display.html" - - rm -f $STEMP - cp $STATUS $STEMP - - ID=$(uci -q get zerotier.zerotier.secret) - if [ -z $ID ]; then - ID="xxxxxxxxxx" - else - ID=${ID:0:10} - fi - - sed -i -e "s!#ID#!$ID!g" $STEMP - source /etc/codename - sed -i -e "s!#VER#!$CODENAME!g" $STEMP - - mv $STEMP $IFSTATUS -fi \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html b/rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html deleted file mode 100644 index aaba6a5..0000000 --- a/rooter/0splash/ext-splash/files/usr/lib/iframe/zerotier.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - -

                          Router ID : #ID#

                          -
                          Powered by : #VER#
                          - - - diff --git a/rooter/0splash/ext-splash/files/www/luci-static/display.html b/rooter/0splash/ext-splash/files/www/luci-static/display.html deleted file mode 100644 index acc2f86..0000000 --- a/rooter/0splash/ext-splash/files/www/luci-static/display.html +++ /dev/null @@ -1 +0,0 @@ -/tmp/www/display.html \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/iframe.html b/rooter/0splash/ext-splash/files/www/luci-static/iframe.html deleted file mode 100644 index 444edca..0000000 --- a/rooter/0splash/ext-splash/files/www/luci-static/iframe.html +++ /dev/null @@ -1 +0,0 @@ -/tmp/www/daylist.html \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html b/rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html deleted file mode 100644 index 1155573..0000000 --- a/rooter/0splash/ext-splash/files/www/luci-static/ifstatus.html +++ /dev/null @@ -1 +0,0 @@ -/tmp/www/ifstatus.html \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css b/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css deleted file mode 100644 index 5254b92..0000000 --- a/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/iconmoon_splash.css +++ /dev/null @@ -1,69 +0,0 @@ -@font-face { - font-family: 'icomoon_splash'; - src: url('../fonts/icomoon_splash.eot?vja16g'); - src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), - url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), - url('../fonts/icomoon_splash.woff?vja16g') format('woff'), - url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"], [class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'icomoon_splash' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - - -.icon-power-off:before { - content: "\f011"; -} -.icon-signal:before { - content: "\f012"; -} -.icon-cog:before { - content: "\f013"; -} -.icon-gear:before { - content: "\f013"; -} -.icon-home:before { - content: "\f015"; -} -.icon-exclamation-triangle:before { - content: "\f071"; -} -.icon-warning:before { - content: "\f071"; -} -.icon-comments:before { - content: "\f086"; -} -.icon-hdd-o:before { - content: "\f0a0"; -} -.icon-plug:before { - content: "\f1e6"; -} -.icon-wifi:before { - content: "\f1eb"; -} -.icon-connection:before { - content: "\e91b"; -} -.icon-podcast:before { - content: "\e91c"; -} -.icon-earth:before { - content: "\e9ca"; -} diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css b/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css deleted file mode 100644 index 05040a4..0000000 --- a/rooter/0splash/ext-splash/files/www/luci-static/rooter/css/splash.css +++ /dev/null @@ -1,342 +0,0 @@ -/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ - -/* - CSS for ROOter splash pages - Copyright Francois Dechery - https://github.com/soif -*/ - -/* @group Splash Pages ---------------------------------------------------*/ - -.rooterSplash{ - padding: 0; - background: #F0F0F0; -} -.rooterPageHead{ - background: #55F; - padding: 20px 5px; - background: rgb(140,140,255); - background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); - background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); - border-bottom: 1px solid rgba(0,0,0,0.7); - -} -.rooterPageContent{ - border-top: 1px solid rgba(255,255,255,0.8); - border-bottom: 1px solid rgba(0,0,0, 0.1); - padding: 0px 0px; - max-width: 1200px; - margin: auto; -} - -.rooterPageContentBW{ - border-top: 1px solid rgba(255,255,255,0.8); - border-bottom: 1px solid rgba(0,0,0, 0.1); - padding: 10px 0px; - max-width: 600px; - margin: auto; -} - -.rooterHeadTitle{ - color: #fff; - text-align: center; - font-family: Georgia, "Times New Roman", Times, serif; - font-size: 32px; - line-height: 120%; - text-shadow: -1px -1px 2px rgba(0,0,0,0.5); -} -.rooterPageFoot{ - border-top: 1px solid rgba(255,255,255,0.8); - margin-top: 20px; - padding: 10px 10px; - max-width: 950px; - margin: auto; - font-size: 16px; -} -.rooterFootMenu{ - float: left; - margin-bottom: 10px; -} -.rooterFootMenu A{ - text-decoration: none; -} -.rooterFootMenu A:hover{ - color: #000; -} -.rooterFootMenu UL{ - padding: 0; - margin: 0; - overflow: hidden; - display: inline-block; -} -.rooterFootMenu LI{ - float: left; - padding: 0; - margin: 0; - list-style: none; -} -.rooterFootMenu LI A{ - padding: 0 10px; - color: #555; -} -.rooterFootMenu LI:first-child A{ - padding-left: 0; -} -.rooterFootCredits{ - float: right; - padding: 0; - margin: 0; - color: #999; - text-align: right; -} -.rooterFootCredits A{ - color: #777; -} -/* @end */ - - - - -/* @group Page: Home ---------------------------------------------------*/ - - -/* @group Logo -++++++++++++++++++ */ -.rooterHeadBox{ - font-size: 50px; - font-family: Georgia, "Times New Roman", Times, serif; - color: #fff; - line-height: 100%; - overflow: hidden; - width: 700px; - margin: auto; - padding-top: 10px; - opacity: 0; -} -.rooterLogo{ - background: url("../img/kangaroo_800.png") no-repeat; - background-size: 100%; - float: left; - height: 110px; - width: 250px; - opacity: 0.4; -} -.rooterTagline{ - margin-left: 100px; - padding-left: 10px; - text-shadow: 2px 2px 3px rgba(0,0,0,0.3); -} - -/* @end */ - -@media only screen and (max-width: 600px) { - .rooterHeadBox{ - text-align: center; - width: auto; - } - .rooterLogo{ - display: inline-block; - float: none; - } - .rooterTagline { - display: none; - } - .rooterFootCredits, - .rooterFootMenu{ - float: none; - text-align: center; - } -} - -#rooterItems{ - clear: both; - max-width: 600px ; - margin: auto; -} - -#rooterItemss{ - clear: both; - max-width: 300px ; - margin: auto; -} -.rooterItem{ - overflow: hidden; - border: 5px solid #00; - border-color: #00 #DDD #DDD #00; - padding: 20px 15px; - margin-bottom: 20px; - border-radius: 8px; - background-color: #AFAFAF; -} -.rooterItem:hover{ - background-color: #CFCFCF; - border-color: #AAA; -} -.rooterItemTitle{ - float: left; - font-size: 18px; - font-weight: bold; - padding-right: 10px; - color: #000; - line-height: 2em; -} -.rooterItemTitle .icon{ - color: #55F; - margin-right: 8px; - font-size: 2em; - vertical-align: middle; -} - -.rooterItemsp{ - overflow: hidden; - border: 5px solid #00; - border-color: #00 #DDD #DDD #00; - padding: 5px 15px; - margin-bottom: 5px; - border-radius: 8px; - background-color: #AFAFAF; - max-width: 300px ; -} -.rooterItemsp:hover{ - background-color: #CFCFCF; - border-color: #AAA; -} - -#rooterItems A{ - text-decoration: none; -} -.rooterItemDesc{ - font-size: 18px; - color: #777; - margin-left: 220px; - margin-top: 0.7em; -} -/* @end */ - - - -/* @group Page: Status ---------------------------------------------------*/ - -.modemStatusBlock{ - margin-bottom: 30px; -} -#rooterSplashStatus h3{ - clear:both; - font-size: 18px; - color: #55F; -} -#rooterSplashStatus h3 .icon{ - margin-right: 3px; -} -#rooterSplashStatus h3 .msCell{ - color: #666; -} -.modemStatusRow{ - clear:both; - padding-bottom: 20px; - overflow: hidden; -} -.modemStatusRow .msTitle{ - border-radius: 2px 2px 0 0; - padding: 5px 5px ; - background: #484848; - color: #fff; - background: rgb(99,99,99); - background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); - background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); -} -.modemStatusRow .msCell{ - border-radius: 10px; - display: inline-block; - margin-top: 10px; - float:left; - border: 1px solid #ccc; - padding-bottom: 5px; - background: #fff; - -} -.modemStatusRow1 .msCell{ - width: 176px; - margin: 10px 5px 0 5px; - text-align: center; -} -.modemStatusRow1 SPAN B{ - font-weight: bold; - font-size: 35px; - line-height: 110%; - text-shadow: 1px 1px 1px rgba(0,0,0,0.4); -} -.modemStatusRow1 .msDesc{ - color: #000; - font-size: 12px; -} -.modemStatusRow2 .msCell{ - margin: 10px 5px; - text-align: center; -} -.modemStatusRow2 SPAN{ - display: inline-block; - padding: 5px 5px ; - font-size: 14px; -} -#counter_div{ - color: #000; - font-weight: normal; - font-size: 14px; -} -#counter_val{ - color: #F00; - font-size: 32px; - font-weight: bold; - text-shadow: 1px 1px 1px rgba(0,0,0,0.1); -} -#msCell_per{} -#msCell_csq{} -#msCell_rssi{} -#msCell_rscp{} -#msCell_ecio{} - -#rooterSplashStatus .level_0{ - color: #0F0; // green -} -#rooterSplashStatus .level_1{ - color: #0CB; // green blue -} -#rooterSplashStatus .level_2{ - color: #00F; // blue -} -#rooterSplashStatus .level_3{ - color: #F0F; // violet -} -#rooterSplashStatus .level_4{ - color: #F80; // orange -} -#rooterSplashStatus .level_5{ - color: #F00; // red -} -#rooterSplashStatus .level_6{ - color: #FF0; // yellow -} - -/* @end */ - - -/* Easy Color changer ------------- */ - -.rooterPageHead{ - /*background: #55F;*/ -} -.rooterItemTitle .icon, -#rooterSplashStatus h3{ - color: #55F; -} - - - diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot deleted file mode 100644 index 29cd4d1f36a419b4822d210be985dbde03d1d3ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 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 Gn*ReFo8=Jz diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg deleted file mode 100644 index dc2127b..0000000 --- a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf deleted file mode 100644 index 4e27645c4f897ba62acace85a644aff591860682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4516 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 E0b}jXx&QzG diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff b/rooter/0splash/ext-splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff deleted file mode 100644 index 63f541307f5f723c6eed5ef792b2fbce8e4ea0f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4592 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 Vg5RoPjlsG#(%?z@pM}q8{|Cw&)JOmT diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/favicon.gif b/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/favicon.gif deleted file mode 100644 index bfbe292825c753540fdd42af7823e167398874e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2441 zcmeH|`8yMi1ILGvYixGm<15Ef&K%XGWGY8nBu7{bHJZ6{Bq|yscV0Es=-6N-A(-ME%9Np_=t!2*uVA^pYRf&^oF*( z!kS&-EpG5uH*l{TxRV6!^#p$+f%{32esA!AJ7mBc^4SMD;Dwm+ z27mR1ehY+82SVo_AZCK0^C8fMhtQw*U`zLPrpg^~%uvH4| zR~USY0^6d(w<)k~Dq=SrwjF`kjeze(!gizJ`%%b)NW{S-BsU7a7me79g>z!yoLB@m z8qSS@AH>4BaR_d_>~^fmdYtMGUF{$RKa+-^Prtszyu;22{FEKml}G8$3+pfZFU$YO z{}=)J9UuHTLD06{K*D3&R(~8_?#haa^F?N!o zlsMu-tc*~Fu@K71ve@CNwg^8j>SkxAJ@sOYs-55BSd6OxPnr%@m}yrPk)mpvtnxqj0ew6D_ujjAtxs9Bikc{4)t`0#pbMT~G)cdhPSVxAf6tlIkb>#o#LkpANO z;*El?g2y5AzgOIAzHw*8vYrPu&2+urXN7WtTbHZ$vY6*WO*c1xHrYBD7#QszaOw^d z>-k?yKIn&&oQ(h)c6}6<@_hD1kok~BBm&DXe_Lv#M&9c`gl(6H@=6gdF#^nJ1w$3q zF^f2j*81G|V|}KX5S#M+Z&*1Q;?3Je^O(1f)qK|s!wi010}AN{OwS}+=n3)Nx%9mj zCD!EF!keOq9hyk7_l_Yxfrjs7q@ANLWIrvxrrz?4nF=Hb1PTZ#U53oQz)4~-1p@N; zl-%RmD#L{+P3~F-*dPZ_E5=pqCNeErR6IPYv&hQNy~w*#g~dC19;I!M+<*AU-NT-L z*(IE@SkUvhVIhdg`&_NOn}GX~+1vMJnJ~$Mzbpk#7c*F|l^AccH-v>Fqy-9apI?1& zD_*V`Gd@DhSLNKsNbi{MmAsmsh%Ie$_l}!rKqS#FzzM{cYwrlhd;vUy$b28${n!kz zcEA-GxR4@dZB&eplBroUgQrx%@n-`Q9Bew!&-S0UuNuCs>?&B_p0{s(0hOWAe)8jP-l7 zm9g(i8~0aBK~87;bLP}PPGEnJ?@yK#v$U6*MXv164IM7y7>pgA4H@d06Xo>GST&{o zp7-HwZzdi0(OV?q?EA#D_17J*JgnbKU&(skIL{sIrR=ng9t?dkpubtZpE7DSEQosZ z%jV|;!6HXnZ}h8Lds^@+pA)McjrsQ&sD~KNytq2d&PiG*aAS&t2?9f|MMiY!On=l! zYZcWXQz47l9CmmUSlTCoP0jpezTLFV;~g5_H7(KD*DiZ*E$ZsbBrGbrwclRrft>>r zAwS=~VdxvOe4%r%`$g;BijSUHVjgl_&{+2xE#Bs3-rx$m^S7uIr(ODA>bOQRd!76+^)JBhkVD(k)@2uP$fz8W(i z=w7z%1g8o!W>-kVjc05963awysKuSabrsQ1jkO=qnyl|42lg_Wtlc!97MYNKT}=x;&gqW3TbnA}QSS95oj9!b!RS?JE&sX zfbY3Z56Hsl7oD^se@eN*D7{-YPSQFF9%R>M7)=@9+TG+iloJO0ao-8aJR%1;^ACjV#SQ=f diff --git a/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/kangaroo_800.png b/rooter/0splash/ext-splash/files/www/luci-static/rooter/img/kangaroo_800.png deleted file mode 100644 index 478fa6d62f4ce758358142fefd480c564773ce36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5836 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 Wk|dU(LN#0f0000DzfNY>Fh|Ltj$Y2csQN9XW diff --git a/rooter/0splash/ext-splashconfig/Makefile b/rooter/0splash/ext-splashconfig/Makefile deleted file mode 100644 index c986ca8..0000000 --- a/rooter/0splash/ext-splashconfig/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-splashconfig -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/ext-splashconfig - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Splash Screens - DEPENDS:=+ext-splash - TITLE:=Added scripts for Login display - PKGARCH:=all -endef - -define Package/ext-splashconfig/description - Added scripts for Login display -endef - - -define Build/Compile -endef - -define Package/ext-splashconfig/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-splashconfig)) diff --git a/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua b/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua deleted file mode 100644 index 40b8960..0000000 --- a/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/controller/splash.lua +++ /dev/null @@ -1,10 +0,0 @@ ---[[ -ext-theme -]]-- - -module("luci.controller.splash", package.seeall) - -function index() - entry({"admin", "splash"}, firstchild(), "Splash Screen", 82).dependent=false - entry({"admin", "splash", "splash"}, cbi("splashm"), _("Configuration"), 20) -end diff --git a/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua b/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua deleted file mode 100644 index 0073acb..0000000 --- a/rooter/0splash/ext-splashconfig/files/usr/lib/lua/luci/model/cbi/splashm.lua +++ /dev/null @@ -1,44 +0,0 @@ - - -local sys = require "luci.sys" -local zones = require "luci.sys.zoneinfo" -local fs = require "nixio.fs" -local conf = require "luci.config" - -m = Map("iframe", "Splash Screen Configuration",translate("Change the configuration of the Splash and Login screen.")) -m:chain("luci") - -s = m:section(TypedSection, "iframe", "Status Page Configuration") -s.anonymous = true -s.addremove = false - -c1 = s:option(ListValue, "splashpage", "Enable Network Status Page Before Login :"); -c1:value("0", "Disabled") -c1:value("1", "Enabled") -c1.default=0 - -a1 = s:option(Value, "splashtitle", "Network Status Title :"); -a1.optional=false; -a1.default = "ROOter Status" -a1:depends("splashpage", "1") - -dc1 = s:option(ListValue, "dual", "Enable Modem 2 Status :"); -dc1:value("0", "Disabled") -dc1:value("1", "Enabled") -dc1.default=0 -dc1:depends("splashpage", "1") - -cc1 = s:option(ListValue, "speed", "Enable OpenSpeedTest :"); -cc1:value("0", "Disabled") -cc1:value("1", "Enabled") -cc1.default=0 -cc1:depends("splashpage", "1") - -ec1 = s:option(ListValue, "band", "Enable Bandwidth Summary :"); -ec1:value("0", "Disabled") -ec1:value("1", "Enabled") -ec1.default=0 -ec1:depends("splashpage", "1") - - -return m \ No newline at end of file diff --git a/rooter/0splash/splash/Makefile b/rooter/0splash/splash/Makefile deleted file mode 100644 index 2941b94..0000000 --- a/rooter/0splash/splash/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=splash -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/splash - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Splash Screens - TITLE:=Added scripts for Splash screen - PKGARCH:=all -endef - -define Package/splash/description - Added scripts for Splash screen -endef - - -define Build/Compile -endef - -define Package/splash/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,splash)) diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css b/rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css deleted file mode 100644 index 5254b92..0000000 --- a/rooter/0splash/splash/files/www/luci-static/rooter/css/iconmoon_splash.css +++ /dev/null @@ -1,69 +0,0 @@ -@font-face { - font-family: 'icomoon_splash'; - src: url('../fonts/icomoon_splash.eot?vja16g'); - src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), - url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), - url('../fonts/icomoon_splash.woff?vja16g') format('woff'), - url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"], [class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'icomoon_splash' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - - -.icon-power-off:before { - content: "\f011"; -} -.icon-signal:before { - content: "\f012"; -} -.icon-cog:before { - content: "\f013"; -} -.icon-gear:before { - content: "\f013"; -} -.icon-home:before { - content: "\f015"; -} -.icon-exclamation-triangle:before { - content: "\f071"; -} -.icon-warning:before { - content: "\f071"; -} -.icon-comments:before { - content: "\f086"; -} -.icon-hdd-o:before { - content: "\f0a0"; -} -.icon-plug:before { - content: "\f1e6"; -} -.icon-wifi:before { - content: "\f1eb"; -} -.icon-connection:before { - content: "\e91b"; -} -.icon-podcast:before { - content: "\e91c"; -} -.icon-earth:before { - content: "\e9ca"; -} diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css b/rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css deleted file mode 100644 index 76957ea..0000000 --- a/rooter/0splash/splash/files/www/luci-static/rooter/css/splash.css +++ /dev/null @@ -1,311 +0,0 @@ -/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ - -/* - CSS for ROOter splash pages - Copyright Francois Dechery - https://github.com/soif -*/ - -/* @group Splash Pages ---------------------------------------------------*/ - -.rooterSplash{ - padding: 0; - background: #F0F0F0; -} -.rooterPageHead{ - background: #55F; - padding: 10px 5px; - background: rgb(140,140,255); - background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); - background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); - border-bottom: 1px solid rgba(0,0,0,0.7); - -} -.rooterPageContent{ - border-top: 1px solid rgba(255,255,255,0.8); - border-bottom: 1px solid rgba(0,0,0, 0.1); - padding: 25px 10px; - max-width: 950px; - margin: auto; -} -.rooterHeadTitle{ - color: #fff; - text-align: center; - font-family: Georgia, "Times New Roman", Times, serif; - font-size: 32px; - line-height: 120%; - text-shadow: -1px -1px 2px rgba(0,0,0,0.5); -} -.rooterPageFoot{ - border-top: 1px solid rgba(255,255,255,0.8); - margin-top: 20px; - padding: 10px 10px; - max-width: 950px; - margin: auto; - font-size: 11px; -} -.rooterFootMenu{ - float: left; - margin-bottom: 10px; -} -.rooterFootMenu A{ - text-decoration: none; -} -.rooterFootMenu A:hover{ - color: #000; -} -.rooterFootMenu UL{ - padding: 0; - margin: 0; - overflow: hidden; - display: inline-block; -} -.rooterFootMenu LI{ - float: left; - padding: 0; - margin: 0; - list-style: none; -} -.rooterFootMenu LI A{ - padding: 0 10px; - color: #555; -} -.rooterFootMenu LI:first-child A{ - padding-left: 0; -} -.rooterFootCredits{ - float: right; - padding: 0; - margin: 0; - color: #999; - text-align: right; -} -.rooterFootCredits A{ - color: #777; -} -/* @end */ - - - - -/* @group Page: Home ---------------------------------------------------*/ - - -/* @group Logo -++++++++++++++++++ */ -.rooterHeadBox{ - font-size: 50px; - font-family: Georgia, "Times New Roman", Times, serif; - color: #fff; - line-height: 100%; - overflow: hidden; - width: 700px; - margin: auto; - padding-top: 10px; - opacity: 0; -} -.rooterLogo{ - background: url("../img/kangaroo_800.png") no-repeat; - background-size: 100%; - float: left; - height: 110px; - width: 250px; - opacity: 0.4; -} -.rooterTagline{ - margin-left: 100px; - padding-left: 10px; - text-shadow: 2px 2px 3px rgba(0,0,0,0.3); -} - -/* @end */ - -@media only screen and (max-width: 600px) { - .rooterHeadBox{ - text-align: center; - width: auto; - } - .rooterLogo{ - display: inline-block; - float: none; - } - .rooterTagline { - display: none; - } - .rooterFootCredits, - .rooterFootMenu{ - float: none; - text-align: center; - } -} - -#rooterItems{ - clear: both; - max-width: 800px ; - margin: auto; -} -.rooterItem{ - overflow: hidden; - border: 1px solid #EEE; - border-color: #EEE #DDD #DDD #EEE; - padding: 20px 15px; - margin-bottom: 20px; - border-radius: 8px; - background-color: #fff; -} -.rooterItem:hover{ - background-color: #F3F3FF; - border-color: #AAA; -} -.rooterItemTitle{ - float: left; - font-size: 18px; - font-weight: bold; - padding-right: 10px; - color: #000; - line-height: 2em; -} -.rooterItemTitle .icon{ - color: #55F; - margin-right: 8px; - font-size: 2em; - vertical-align: middle; -} -#rooterItems A{ - text-decoration: none; -} -.rooterItemDesc{ - font-size: 14px; - color: #777; - margin-left: 220px; - margin-top: 0.7em; -} -/* @end */ - - - -/* @group Page: Status ---------------------------------------------------*/ - -.modemStatusBlock{ - margin-bottom: 30px; -} -#rooterSplashStatus h3{ - clear:both; - font-size: 18px; - color: #55F; -} -#rooterSplashStatus h3 .icon{ - margin-right: 3px; -} -#rooterSplashStatus h3 .msCell{ - color: #666; -} -.modemStatusRow{ - clear:both; - padding-bottom: 20px; - overflow: hidden; -} -.modemStatusRow .msTitle{ - border-radius: 2px 2px 0 0; - padding: 5px 5px ; - background: #484848; - color: #fff; - background: rgb(99,99,99); - background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); - background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); -} -.modemStatusRow .msCell{ - border-radius: 10px; - display: inline-block; - margin-top: 10px; - float:left; - border: 1px solid #ccc; - padding-bottom: 5px; - background: #fff; - -} -.modemStatusRow1 .msCell{ - width: 176px; - margin: 10px 5px 0 5px; - text-align: center; -} -.modemStatusRow1 SPAN B{ - font-weight: bold; - font-size: 70px; - line-height: 110%; - text-shadow: 1px 1px 1px rgba(0,0,0,0.4); -} -.modemStatusRow1 .msDesc{ - color: #000; - font-size: 12px; -} -.modemStatusRow2 .msCell{ - margin: 10px 5px; - text-align: center; -} -.modemStatusRow2 SPAN{ - display: inline-block; - padding: 5px 5px ; - font-size: 14px; -} -#counter_div{ - color: #000; - font-weight: normal; - font-size: 14px; -} -#counter_val{ - color: #F00; - font-size: 32px; - font-weight: bold; - text-shadow: 1px 1px 1px rgba(0,0,0,0.1); -} -#msCell_per{} -#msCell_csq{} -#msCell_rssi{} -#msCell_rscp{} -#msCell_ecio{} - -#rooterSplashStatus .level_0{ - color: #0F0; // green -} -#rooterSplashStatus .level_1{ - color: #0CB; // green blue -} -#rooterSplashStatus .level_2{ - color: #00F; // blue -} -#rooterSplashStatus .level_3{ - color: #F0F; // violet -} -#rooterSplashStatus .level_4{ - color: #F80; // orange -} -#rooterSplashStatus .level_5{ - color: #F00; // red -} -#rooterSplashStatus .level_6{ - color: #FF0; // yellow -} - -/* @end */ - - -/* Easy Color changer ------------- */ - -.rooterPageHead{ - /*background: #55F;*/ -} -.rooterItemTitle .icon, -#rooterSplashStatus h3{ - color: #55F; -} - - - diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.eot deleted file mode 100644 index 29cd4d1f36a419b4822d210be985dbde03d1d3ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 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 Gn*ReFo8=Jz diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg deleted file mode 100644 index dc2127b..0000000 --- a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.ttf deleted file mode 100644 index 4e27645c4f897ba62acace85a644aff591860682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4516 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 E0b}jXx&QzG diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff b/rooter/0splash/splash/files/www/luci-static/rooter/fonts/icomoon_splash.woff deleted file mode 100644 index 63f541307f5f723c6eed5ef792b2fbce8e4ea0f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4592 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 Vg5RoPjlsG#(%?z@pM}q8{|Cw&)JOmT diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/img/favicon.gif b/rooter/0splash/splash/files/www/luci-static/rooter/img/favicon.gif deleted file mode 100644 index bfbe292825c753540fdd42af7823e167398874e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2441 zcmeH|`8yMi1ILGvYixGm<15Ef&K%XGWGY8nBu7{bHJZ6{Bq|yscV0Es=-6N-A(-ME%9Np_=t!2*uVA^pYRf&^oF*( z!kS&-EpG5uH*l{TxRV6!^#p$+f%{32esA!AJ7mBc^4SMD;Dwm+ z27mR1ehY+82SVo_AZCK0^C8fMhtQw*U`zLPrpg^~%uvH4| zR~USY0^6d(w<)k~Dq=SrwjF`kjeze(!gizJ`%%b)NW{S-BsU7a7me79g>z!yoLB@m z8qSS@AH>4BaR_d_>~^fmdYtMGUF{$RKa+-^Prtszyu;22{FEKml}G8$3+pfZFU$YO z{}=)J9UuHTLD06{K*D3&R(~8_?#haa^F?N!o zlsMu-tc*~Fu@K71ve@CNwg^8j>SkxAJ@sOYs-55BSd6OxPnr%@m}yrPk)mpvtnxqj0ew6D_ujjAtxs9Bikc{4)t`0#pbMT~G)cdhPSVxAf6tlIkb>#o#LkpANO z;*El?g2y5AzgOIAzHw*8vYrPu&2+urXN7WtTbHZ$vY6*WO*c1xHrYBD7#QszaOw^d z>-k?yKIn&&oQ(h)c6}6<@_hD1kok~BBm&DXe_Lv#M&9c`gl(6H@=6gdF#^nJ1w$3q zF^f2j*81G|V|}KX5S#M+Z&*1Q;?3Je^O(1f)qK|s!wi010}AN{OwS}+=n3)Nx%9mj zCD!EF!keOq9hyk7_l_Yxfrjs7q@ANLWIrvxrrz?4nF=Hb1PTZ#U53oQz)4~-1p@N; zl-%RmD#L{+P3~F-*dPZ_E5=pqCNeErR6IPYv&hQNy~w*#g~dC19;I!M+<*AU-NT-L z*(IE@SkUvhVIhdg`&_NOn}GX~+1vMJnJ~$Mzbpk#7c*F|l^AccH-v>Fqy-9apI?1& zD_*V`Gd@DhSLNKsNbi{MmAsmsh%Ie$_l}!rKqS#FzzM{cYwrlhd;vUy$b28${n!kz zcEA-GxR4@dZB&eplBroUgQrx%@n-`Q9Bew!&-S0UuNuCs>?&B_p0{s(0hOWAe)8jP-l7 zm9g(i8~0aBK~87;bLP}PPGEnJ?@yK#v$U6*MXv164IM7y7>pgA4H@d06Xo>GST&{o zp7-HwZzdi0(OV?q?EA#D_17J*JgnbKU&(skIL{sIrR=ng9t?dkpubtZpE7DSEQosZ z%jV|;!6HXnZ}h8Lds^@+pA)McjrsQ&sD~KNytq2d&PiG*aAS&t2?9f|MMiY!On=l! zYZcWXQz47l9CmmUSlTCoP0jpezTLFV;~g5_H7(KD*DiZ*E$ZsbBrGbrwclRrft>>r zAwS=~VdxvOe4%r%`$g;BijSUHVjgl_&{+2xE#Bs3-rx$m^S7uIr(ODA>bOQRd!76+^)JBhkVD(k)@2uP$fz8W(i z=w7z%1g8o!W>-kVjc05963awysKuSabrsQ1jkO=qnyl|42lg_Wtlc!97MYNKT}=x;&gqW3TbnA}QSS95oj9!b!RS?JE&sX zfbY3Z56Hsl7oD^se@eN*D7{-YPSQFF9%R>M7)=@9+TG+iloJO0ao-8aJR%1;^ACjV#SQ=f diff --git a/rooter/0splash/splash/files/www/luci-static/rooter/img/kangaroo_800.png b/rooter/0splash/splash/files/www/luci-static/rooter/img/kangaroo_800.png deleted file mode 100644 index 478fa6d62f4ce758358142fefd480c564773ce36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5836 zcmV;-7BlIIP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3&wmK-Y%ME|pjSpoutU^#rAGdq~&&sA1+``K>$ zdES{WcV%@}CJ9m~B80>F&%bZ@7eBeC7>Zh}z1GN2>7}Q^hZbKyucO5BygxtnyuXw0 z&xiDJQ{q(Sn7_Y42IuwL4OZUg=lAD>t@k+XJ<$7$j{&nkIq~6rU3(9d)9bvv{|^0q z-za}s&imKu=Q3Wi`Qh(k1Y;}XZK0c=JzlbM(%;~4t-Mibp=e4>~ zDv_$;y{L~6KA*U763YDCR(Tn}%4d6ComXRti;QiuIeD!hT@um0Qe?}JE9W^bSxm8{ zlZ<0ZiyZj5mM!(PNPu|YbCH{jWbBX|`B-Evb2@#_MV{yO=XpySPu{|nNf=DHf}FpeGYW5Ls!IuN$Ta5;N+NQ8lE|S=PD8+_Z?Gx;`_Y9XO_PGcw#dd)F;f11&%mh zLrj%#*ve0yGuLS>A-+mOY`+H}L_AxWjASwpt7Mfb(NZ!I;@HT~VCE^8G|7OdrY+%; zn+%~?q8fNM_n17_CQYx?Pz#CBT(glH%7tW=qTt6$14BczmY}LtO`CQdHP=$L)@s!` zYFM^nYSqk|bsH_W(zMlPt+n1pPd!6n+H1GaTkm}g9y%C$aQEPfF=m>1mZ`H&n{D8i_CTYZh4cHWf#uG_+HyYF%20Hsroo_g%G)6ckI?dDsq-g@n}+wb_y+B>V? zXH9;{-0!m{@2q*o%5$B4%NnQ6K86sd6ZM>tu~dYNn`Zz(C(l`IQcCj7dCp>YqS8dx zL_IlMJY!_A97%fRGk4!I_uIS$E&o&A(yuZXJazw%%mq)~J99th?Tf7K@hD1u6696r zF^%~`Y+N)_8!m9aJeFFO2%obk2&cs4xfyl!L|CPp!AB~)oHUQ++h9-`-L$lduFM_F zUPa{`ne|qgoyg45+oICy;p@1jjhkl;E#}>)4hHGROZRwgWX#>yOrEWp7`3KqR5RSW zsKztzka6PG$XaEtT*8QHk3B2DQ~HMg$jZ4e&MljH*3r+Y#x!J<+4?B_t4Z7BGHtAJ z^wmcTgDD;II4>F92~_l+WNRB2Jd^Z$Sra`*L&CR@YiHTdsIP>#mj z$Mz{lyOJjH1X!(G+5LpfdJp)_i%0IsJ*!jVT@xi6Zz8srf7*D~1tptx4JGVb(me{q zPNkf7fKaI-$~vAc_Y@CuLFo3Cepj~R5Rl0w<<6w1bPsx3=3uPx9H7pGTVTT7XFAR% zgm)Ick4!QSiVD23>Nbh+gbk>U3p7gchcup(rZIa;vG-87`gC%lHsK&@G}e?)1){pQ zWKf|yS83fDqD@u6lpUnC@oZ|%$Xm_f+A z;UJgwOJioI?*nXiU{+Eqz@;j|36D7t6P^?Lr1G&14%jg}wSbak;DmbJy2l)a!RFS% z#8&9XI@1}aaW4_DBk&8}FDZ2~t5G0lF6z|G!#o&iU-;^Fe*jUN=;J+sWVB3m+fxD% zePxPFd6jN6w&(1CjrVS6?vW3rK*+{`#CC6UHZgNlkAdtWsgpl3|Bg0skD7koQp&UuP)N&|In~+CA(x6@e zZ4qj2=mH3-wkzrX9WnmuNCYA@xv=YMWD}_h%arg%AOjaNLowZsHiK3yZdWBh59S3y;a$vGYStE(l z$aW@|>2&KgEfnNsfV}dqL#tCk33wy~eccOqsZ&s=00y#--BzX?oi`3cudN4va%xGa zhY58}9W#Eb3mOe*kw{Ar%_f1_6#>Mv*c%BiMLKh@*3plJl2@;rnCaCn=~3rq@3VLd zA0Phs7!g5wJE$3LQ&juvGSP5l;(W*}f_~eY)a}g}2u(z2F%|5MbFDgIunsH=vq$!* zhHTtw&e;XYMnTk7e_hOI!cx>*x|9Wjci5iTE*!|Xu@3Ju9h6@k!$@=P8;`A&E<8pK z3srrOy9+^FYJ{yQWGe}d0#@`jLp=NV0MR`!YH=j2&59DWOtn*=H~>SdG0!)7hmr;n zU6~Ra$4Fy`36}9RJrpeW+1*C1&cH$#kBA_>vYWZyD3W_2@5zTkLUR+K-;-8vu8?%% zL`frg&Ia2W@d^>_V1Gm^Ttk#joE_pDb6I3c0v3;EOo6*xha_`@%{>@Rt;`!ItI-OL zSix1+jQ@+~WDzGky-Pn=CtW^`71SE{9I!`9?I2*56eKu~eK8Lx!k^XES4XTJREk6= zOwysJ-MC(eEm2*{q{-jxFbH+Gs@p{G{%}?`CE|_NA@btPGf91!RmkqN8g?SKjmp`I zryy$xWR4^z&GwQSExWSH>Fg~L0!atg+7^#gNTltBebIn%M!@~ew>|Py??e%&fu%-7 zIAG(cVV{C{yo=?9tKO0O9F}1c9qq=@}!c7_zlpgE}Kh?uxp4r#2|a|pL% z9f)aglSz?a#=!u-1)XC+XJ&(qke3Tyy0`173*9?{Yt$^fjX^4q_QGhyj?v15&BTX* z_3%1VQ5m;C7gx4mh_+9}&Md=WBC}jrCIHqF-^NJ48a?ng*6-v_h za!u}msS>#2!j6hBsaQj3*>D60ug+2zG*aC;ZZ6YJ718Y$zrO7mG3lVGnQxQe0s8Z3 zeDAFK8M81Ma}o86Tl36y3OA-ZJV zn>bgXFwsoXNiy+3N&#A<8EXw2k1iA;7nh0vPB(43kdvqTs7NtKrhxy(Y~7{7T?&?- zHWf`H#D>n8(-5EqZ?Fi{4K{0x@x7F5n3hneo8~bGHVL zj1DNfmm$yCrl&y=C-#;ge6`2|#hZ#uheC{~ASm#l_8V5KxXevK<8m0;4S3_*39T*s z65z+)RS%@@(P;__Hk**Q64vx)2s=l84kjDvc5tDL2kC&)=?mKE8%*Qs%Z{iO zbU zhKrEzsi1rCq|nM7G=#n<`JT$nsZ+jCE%<}I;;Rwv?n7}xXUHKT6_)mPkh!JlBn>t2 zS?T*((W%~tZh{JeXxHzohz{%yM?v#q3FkvtoDU;wM2_gQ=`Ltu&?YMt8pNWU#syA4 z&6}bf)ZJ$_0WrSGi2e5M2iy=iQSr&5yBP9p!w5RTW5nYdT6F7$rcKgVW98u6mu_sm zU%@Flm*ZRMPh)`)PcCKWRK5Moumh4t_4{6Q_ARmPT|QbFmjwJufgl+wp|41K8bHIx z-DHMN0;t#SWPXMhB{3mjomt^3aQ6kk(O*bN3`ehX$ucAV12TCZ!#}+-Qj!fT?>hqY z88P^t6u2Xx$@g*b!h>YYgUB@6^hO02a_b)cmzmyCfMYQ zdNi~dhd?$jZdj|Me3pU2;Jp*(!WD~p==d&g*PCnb@U9@q^}g;|r;*l;NMMIjqEp9u zPuQ{f21ApW&?J-=XJG0N2sD(<*NB2polt2kv~a8*g&NQT%O2xB7f-d79jnq=Fm2!M z+TM5Xa|5ln?_g{^xYErY`kryz%;RHtBwC4sL>*ZO7;^(up(Orv=eG_;;%4rmYsZUy z`4(Djq++e;Jpz5i@c)8Z@SktJ7{Q|Ghr1%o@4~*t>2A@DN(2J|y4pP1tvrQIz_+(! z(CqTo0MEu85$yuza}k^=O}B5InrX&EHUtub;!VwI<{PhQak54Kar9<~)A3GjKAU$& zHPQ$nwwF>meWHPAQS?fXek)YC!XJ2iV!C_yFVNvyuvPbL9RL6T24YJ`L;w%~5C9OE zGN0)H000SaNLh0L04^8+04^8-Dyk;N1TjNRyBF)gusE|#0nD7eCW}8qFBq8DECinKAr9)|=h#@3_ zGxPnE+>Q7ZF zRiZyW7eo*Q@WqDXI53;dU~FtG!)P>yVi-oD(P*}ah=_^U*w{fDjRs&Ceq%qat*s>| zPoDg2Y;2585CpXFe-er06bgls^78V=f`Wn$CX=a~nVA6!g(81?dOA2IC8eLuW{)gJ zmp7YFfpa>YpsTBEyGSJZ(UT`nwhs*rad8}nT}?Kd%^u6l%Uo zNF5d@iqVc5A8z2V{E6T5fs{-Ud^>wDgwvlWM?*Xtwp z?AddFDHG>P$Ye6MbLY;7QmM4S;c&cBzr|t!6%`c?@1m1Vr(3jIEo;?)>+9=FiI0yT z^Axm&t56^i$T~VYwmY3pm-|I`z+S=MrUbo5v3S57Ge{y(u_{4HR zn=dd7J4;GRS~@#B^VMoKcVJ*3Nh}r@oj!f~*BlOKcqx5SsZ{j9fdhA>QfYxgp-A^O zv=swqFc=tYHhXlrp?N|`B$5L`klB!skg2S!Ecw~9XKP-*e92qsPmI?UIvfsATwMIX zAD{sMi00kQI4CPC6Zs1?KA-;_!!WSw!L_!w?wubi^kt#b=@x}Tk?zZ}O0OuHoSZ~r zVq(7b2WS)u#eVD7tsnY&kl8CH^61f{*ZpOsH8nMT=nvU}WmoX{@#F6=H5TYCfglLa z$jIn@@#4i6e@W{sYv)FzkrEddr}0%_Fbq5SeE##s#>S6O6!oio+_IX;W5@_QsBEFTKRPm#tQ{R4 z+g4=2M zWP;Pu(!N?OyrQBaac5^|KAX)R&B(~;EiW(slTxYN94JTY-`aG^Q>j$cU@$N+3C&Y$XU?3tB$LSmlarIk+=Jpc z4qm-_1$ujXGwSQ>s{{gp%vBf*hGA!EX=$@wua8*n0n21EL1<{`j)9d&hemuU)%V1p=`J${X0;-u~V~Ymu0ksIuGb z0lDHxH8nK>@d73!B#c@tmLQo-wsr0|qtO@^5)xv`&CTszks7wuQrP&eZG3z@j>qGv z<`*tP5JZ%hmp2|ie!PCmmMwor5ahoVuU4xSSS*&PnVA{-?Ck716h#q-!$GD{C|Fon z*d&X^8h2MLxn?RoTp;^pbve4y28Hv#|vgTXLGMn>wR zqocoJFc>BZg@Rcumi2nQK2oF6#19P(aR&znlg7u#<6IT^&$WhzhC>w<6@T=FXCw!r zr<|RgEzi!*mcQ+NX0sXe_4VZ_mCCe%fq`VTTAirV>0)d)8!aj->R;*U>0kNEGyVr2 Wk|dU(LN#0f0000 - - - Home - ROOter - - - - - - - - - - - - - - - - - - - -
                          - -
                          - -
                          The ROOter Project
                          -
                          -
                          - - - -
                          -
                          - -
                          -
                          - ROOter Splash Page by Soif and Dairyman -
                          -
                          - - - - diff --git a/rooter/0splash/splash/files/www/splash_files/cellular.png b/rooter/0splash/splash/files/www/splash_files/cellular.png deleted file mode 100644 index 953bf0897143d03cca60de20b753e2159dbf6927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8344 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 diff --git a/rooter/0splash/splash/files/www/splash_files/check.jpg b/rooter/0splash/splash/files/www/splash_files/check.jpg deleted file mode 100644 index f1fb739832977ab446c5bbb382278c8ee4c9c12b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 631 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>=}ORb!jZ%|9=wzK$gba diff --git a/rooter/0splash/splash/files/www/splash_files/forum.png b/rooter/0splash/splash/files/www/splash_files/forum.png deleted file mode 100644 index 9e8b8c222e46c082eb0bed1621b309f7144d12fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3845 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 diff --git a/rooter/0splash/splash/files/www/splash_files/home.png b/rooter/0splash/splash/files/www/splash_files/home.png deleted file mode 100644 index 38687c71991b5ed5e17625142388a46dde396ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1262 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 diff --git a/rooter/0splash/splash/files/www/splash_files/rooter.png b/rooter/0splash/splash/files/www/splash_files/rooter.png deleted file mode 100644 index be8099f6b2dd0206a37ee4a6313f3ada97a08528..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 311293 zcmZU)Q;;Q0(>1!=*llat#`Uq_e71B{JN;%*X7wfQhN8^CQ=(@=8w|38Cf2OwU$Bl-W}ZDta}|Nm0{XTeVG zH{kGpIF)>x96<>G$E&patP~*Ne>gjmcdB&&wALvb36#l0;nf z59KQSk?4eQ{$+XKsA62=GW*Hl+(Q#WUokDa#8d5>-zz7ET=6(BxXk7M91iEsU-FXe-ui7hbBnvS4eQtgD zaIwNG{e1CCdbwaxjKQYACz)MIaczNPVO%g@|p+NJtwWb+!3vcaRM z(*@*8B};`3+vTdj5~ehauz6hjMtU3^tgw&Uk*A;8_>LN zQonPbzGu&n7@j`Nt;jNP>S|wf33y_5_@jMq+63Qw{Q4^Hj^aMI>FYQL z*U!Xv3W&M2@mjyAt1CZ+gRtb=HULA~y&H|69mMonYTYlszLZBFw;z$VHfxYT%jugJ z_`19J4q(Cq3z@L zm729lE&63{Z7XiGR-OL9p{Jnu+ha37$2>XB>B7qV>hjR1xToVe9o46Z`W<0M8tCYC zW8JJz^0iP*@~$Jp1E0c!A*6iPPI?uT?xj_$-rTOWDZfh62hRZFzOT5>ZB=Y+K}8Tut62?TF5$xcWXO0hKZtuF&M%-#Q`(%4mMJm(D9!P&RVW3J(pZR>y@s15pTi7&0ik%8 z$sE4A+M$V?B_1BNpX{;2iWhFTA1Cq66YFjMl^^Lm0@E273d%pdzv>#-LjU^MdBw*) zYR;{67$2O_aH@3r`g&AcyjRtx-M6sh*Lgf*qmFq1{j;A&*79i1-tT-i{T=UENsHHb ze>4`}K029JRrGqt4`8*YKa8Y~C!8xcs3)$U+~ zdo-DoPaGf0WYBRVQ;5TZTEU0&biGHHk6-e1NIGwwXU>NBa|4m_cV11m#E+-|faUsTh^!4%GGqtb3?lj4dRiOU} zf*Vlq0k_S!c9eLz5&6)EUux4xJx7ty;nMw6*r=fyk=*y}i1MxK6Cj!f)*8cKK%k|& ziP7Gt!Jki|ynR)T?$Q%`XqO1ODf*NZf0yg%G0yMaxqO8-KnDdv{P1ck%?w_p=Jo8T zZswxL4avg_Wg_?+2t&BxB^mpC@B;Ve9v^wi+V?-^T0e&Z?+T0G{*25_0)}VY6PckW zq#+66_y7VL{?9s?x;x!(4CVAyCgn?0kf^q_MIXa~n*Ew%B(1O_DWZ5`f5Y;0%nv_L+3k8R_nxCr%XB zo5w#^{vx#BkbpWo#_z)|YP}(VeLEck8$`AW*ZnIez*v;1Np_SsjuLs3QQYZz2aYgr zEMyu8UFChVivvOmsxqHd%Sc!Vdh|-kl3=`3gzNE}hHOz1cN`hOuiUTwzyoXc&q5?V zx<&|45^j{4YV9H$(>M#!TsF;Fcd!CbX2@f=gN-nVgf%~K^scU4!a&MFUCZS`#^od1dh|(@Kc40`^X*eFS*$|%Uld#t_%&7Q7@6RN^AXKiTEIS zsW}~VZ@k{w9QfhiT7ZnJJK86L?n*~F=@Wsr^dAKCpQyv$o&ZKQBWEY-iUM{}&9f_h zI#zG=^L*XJMs6Fw_mUcXy17Hu1oF5#9{`tlBM~pBb1g&d_ql=PxHdb||C^@w=KK*Q=C2aVa zGHWtMDh%X8G9MkBW8d+X*VfxIW;+q(gJTIf@)m=z+oY$x&0ex^23^5STZ*keO_m9E zqR$D66@rpFh!E@WdL>GG$zI63!InnG%C;;$()5_UxjD@E_)-f#=-hrVSicy&S#AU^ zVGEu!K_~Qw)enatWZH$^ECqNB&=LX&t>7n)UPAe+qR3cjhmrUW*wWl4Wj3<2bxr6L zvH*L08G7`qSyCJH=}1YmusKbk*V)mTn-n*jr3*@q`|x;i_H-p<51jpGvC5g|?>DtcTWbvY6xD&{H% zG^i0DOeG_G6lOmn_&u3k0*KR-vpleNiRp!yV_z2sBT@M9`8WUz2Ln=QmJnUQZgj`A znVsShE2%|vhfYB&+QqvnR6nP?NE%p`)-kW;+gOcD5*R@;!$kiA2RW=iDEC>}s46*C z#cG31E6{H#vQVRS_jtLBjwYq;)V1$}Df;^bJbLD>3G`*lc7(X`h|OQr;-wK;K?p!q zP#16(OKoueWc9R503f>#R=9JCmm#V)ZzuXMn5%a_nEN-m*2{@u=!rGFDj3l@>(5T<2+WsZ@%p0w_kBjVOhE^{&c8EFTWF_HX^Hi%_c&+r86?~d2F_`n^{|k~&;j+ic}w~7 zz4}@-O^j47@9$JV=v7|D{aklnSYIYy{C6oyd3}=zE7QIP*P@?K!=A9UyjFp1>On|G z(dFilr}ll4CuSCwGTQX`q8D1QWCgYd{NBz^jDO}Iw-Rf1c4tHKekz$(Dt_jawR(E3 zMwFC}tT?y$&sB7ReolbFK*wp#bocGpkc3W7Gw3v-&jSuiOO zLJHGx&fyA5;iY=z%H^0K{2~QLF!ke4S^y*sPm%U%Rl=~+{Au+~txr^q_S&9i@o?@1 zJSgiawJfA+It5Gs@UcVvstVdj$b8QYR{rxkh12R5_x5kbfFods5KT z*<&zGdMut`w+$Hy!oP^JAh|;n{Oko(=J^&Iy@)i0LTsH!P@Kf-y_T&z99T*N=2{d780?`!~YvLCpAN9c5`GHC`>DaHVBw@m=mf-cQ1SEPCiws zPn^M|Xs ztw4g~gokTemzGB1x%Zq;aou&&(@MnF$W|Dr1;M02_?i>aN=6v>5&dD?XF7o2kMmW2 zj942q%c>D`yG=X~^*AO(iw0PJ<#m#Vpxpe;O6+pP^NbY^7#DdNoat7al3M40BlLm{ zonJLG+Z%LOvQ`;bv;Tm^UxVkTNsg3$!|z6OddlsP#c$8SFNq8O#uVVBwV^A2>&oGw zX6I7w32GDw2&ZOnrW@!ELkGW**1ajt%MnGhW}T>i*W$0x7b~+_a*_EcC}D=IQ^T+8 z*P|8Y!N1k{1pJ{HVK{#Wv2kOGf@;$@1C-n84!`kH&eZ&)YDbNVkNzhX%cuG9r-(iVKDSIlQFvmpxCV&D9mb)%%9(?qjcmnP0T{c9r~Hc4r){fn<=U z4q)wTjyB)%`Zb*`i^07OEV2UTz4K-C*;CU~Or@4cG%|M8PGaaD*3467(b=bP{<$vf zOXoSr^YPnPL^8+X#}^3HVxW1 zAESy5T+Y(!(xV~O6(16rVX9(=UeN$S+ijW693b)Y<+Z$V*A;tWsD&76vu8m&Q}T6+ z)o(%7BHqid!7u)`H6yK=~YaDjO5|__(*i_PD1lWz_%Zr;zC0~?jmcWD1#pl@`>XzQlCpF=roz%eo zXe^S6K?mUVuUdY*$oqE~|NO%jSdFcnsi9{_SJBax_P6bhs9GV1MMm*IOGvY>p^5ko zC$VxTm;a)Ck{yWH{>+~4d!DSGbiBtm6k1;q zGFur17z|<&D}2gQR5%mks84&*0<9vY43d}A$O$wBVhEWDiQh9+2`J_W$9S3nk}cLTmBeShmV-jG_h;zE=131I^bdyr~bw~pIfA5sy{<%46Su6grF#p~(0XBCASJS${OG&g zOS)dvoqK2vmiN7!xF4{P^56;RA{pY&e73YI7hi1yeaP`&I{f#?CMkssATc)i=A&<$ zFfM2!xgq1@HX*ZmG$i&zHugXEpILV9afqcwZ>22Zq_kl&*z@2}LmdpSO?Vw(;tP}jzZ*;YE0w3R!C#|XOoLf< zaUJWjmWa$+e4pU9r?%X)`{>Y;=b>io{l2ow!C zs~~O*5@Z_DTa3~Y*_s9rGWJy6o-^>i#9U3j%tAZ#lX=@NUF>w2U;^R z2JIEK<^kWC;15w9));oHbs>|$b{~Oll^v&@uOqRm%DVnbS97f4m4-YsM%rl}=tLMK zM0f!#9Pr-B*3=0P1+{0;7w4Y*$axNU(;~=NS|h-=lPphgajG_CcNRbe{S=V|(5D^R??N6WEuoJWWEDD=^J4S>rny~v_0zxQ}te&8fq)mysTd47Cz|D(Yt@GA&> zIq)IjlIiT|4bT?(WW`(l5d)Bh*M%)6YanFOTXbzHbJCx^KlfN@9;>T2Z{3(ERqyl^ z{VIp;HDlC#60v*$GLmwe&8Z-GYd7=3{eirN(o`*Fy?uuz1qf2m&CLcdiKYtZg(mcmzFv+FIv1`fgZ+4aOV*SQ)&{EbqktCom>#ZYmddEAQp2OorP8WxYdY;EvbS*Z-8w~0K5vgK+yb}EZ zy)ezRA*z6C5n$i|b0JR+;G22X^QxVyMlwiZ+1Idu#kR(YKv;hjp#z_pgK+UgTr^Sq z^f76-|J9#LtwA_FnVs6y@$R;{snqmO@%d5YLtcKFhnWyW)cRrY3j`$-mPoD|=aX*$ zhE>*EK0XiPDlrr(J9GwHtGV>Hz@M2#bw3TnFQGF7MqmaD4t10xcK=V#S$Z5&p@uEu*<$8xYYL5`jn$A{#%y`;sFIkyv^c-ICXIXtO6^tobnx=sk~ z8MPe4S0`iAkYei)2`xWN0skuiw+((d5B-}F$3M0)FMj)x0ys9`%bg)lM4;~)vt?D3 zIzDdNGL(jq%OZk@i2SM#X|Tatfvp(WYMV<}A;m@p`veDxaTomD}OVQ>sZ! zFV&R2!g=LNtD?4DGMIX}c>wB*aB0EgKKb0FtTfk2sy{x{n#p2%rf* zCU<6j{jpb0If|BQoA=l}?V$lM{23IaQuN}u3FAGI-G0ZK#sE6p&tY0?RkJVi@GV?l z$3DN*OLd2r&ZxF1wCy5=c|{m|+zSi*&_GFo(JjNm8U!p!$QEOes8eY`1N3nls$ong z*Fc4m_f=q90636*p=iFP8;N3BSuo%Jnv&-n*%afmo zqyf%YJE8&4-+XN|l!~je-XC$NPIQjdA$c&ZpIQsv$ZoK2CUSuXZ0w zo0yZrJF~#1Qllr^Erio+tXD@1sb~4YQDKE8by^9)Q}9XoO`a2=2^Vi+qDnsbi1Rjy72Du+mFw#B&Vb~_-^+BEyCFa-s}EMaO}GSiibKF^F}#0_7Z|?~{FR&|3QB zIIR*+eSD=PZnW!1VNt%Co6zKx1Wh6T2Bphk-QZH996S#(>y9@2Ta_-A`VIrdi%+kf3K$eXRd_w3cJ22NHU zSQSZ~4Kj?|IAg``1pgAi6}RGFeX_{LtF#KATq%(xO=Byq#)lFc;K+i`fok}#2ynio zaD_(n2^8TN-E2^@(0vWaZ2dO(k53WmxF6AJ8RR5BFxmIMmSp`!1Vc>K8J+GteNVz# z*^|+pHqxs_?jk)GMG4la--PG} z+#nBxL-;A^if~_sI3yFZAC-WtT#?MEsXvCj@XyceN9JDRpXvWR$v11)9p>0>*J&Ue z?KJhcj`Cn?$#>)~&}JMU;DPJi;Jpb-2lz=r|`P%mGjWF?cY*z!I|O=rsR|Zva~=)cPVj72UVMAqw5q zUpb~{ytXimWJDAo3{if~QL-+lulBSFh+9K7{Bcdrjh(fZ8M3>G8NE>=NXeC# z09t%DJ2_!-2E?X)2$v}CNEJSIw0K|_*BoD1(bskPiR4b(b!IoOTu_e4ldl6mKt`3SFwMD2de6$z$( z4B>i^9~k-G5iCgroadkR5ySzh&i{H|+Jul&8@YB9^Ee!28i;iGC;SA6@$*zo6kqiS zmKjtQW4E6~gcd1WRQ+K&i_Z?$mJJR_i!8F>TtcSQ zrmfJg?Y$ml%eWSY4~eewZbC@|IL&n|-d9^+zh=^;*B$wZi1vIxn4HsbiAD=RsqnQ} zW?lL@Q3=}@W8^LmUjhPSB{(HYXY?Z0je}emkl%y;O&rsS0~4tF1qWNHRV9T&g#?go zDny~ImMOp{aM1ft&G1Lgm|L5HA|67;gium3{&5}9y!-CgT<2KVB%ER*3jT!2RV!sN zW(iewVx@1q`FA0G;sb;3VEKV3p$4U&7Ft>qUvLzb^M8{U3o}>IWaWi9+0L7cmSYUo zkulUCjZvv*e3fAVo>vf}m{?Zh8nl;zdY&N$5W*b{X$~Ab@`2^$!n?rGL>UPZhKKNt+v@D%%a_8~OdtF|MRKuoh!QY0wEnh7 zvQQ>(wU@waN$&%{OF9Q3AWY!3wCects`bUb+rHf{HI||db$=S9B(;9ZiDhl}53rk> zkI^w-KD;JKQLnJE3r2+8(Y?4)|2LV(jntWimatw!!ai858Vve;7l)!>Odx+Ln`6NG zgL}dup(38hR~Ej)Tm`Mno#QV?hUj>u_0lT{G+K=^m$%Gej<*el{L!O%s&%n$U*TUe z7kFs4j$3ub3giOimI)#sa$5#Xss}8HX2EKk-y*<=U*Ie*)@o%7PREz&97JR zd>QK&^6`&C#@jcqgJ%pBt!+J_AeVD;T zHo8><)k;5vgy|rp={Uk}wqL}U~1u#yc+L#jjw88WOMo;-jApiv%A& zHtn5#R1hss1&p2vxmnwFZgs8#8Y%)#+T7P|_N|_3V&9k~QtCTne;DS*REm%d_~qb> znDfdU*ZB`lRVOMj2Pdo%D9tD+IrF&t^j^NsUO2=9yxwmEw!dz{d|of~D@=A9vguF1 zPY67IdRHa#KlvWsQWg!}@>k3$OY@}1@VW(%~eCDg*_rX z?BuzvoRL{#JjJe3EEI7f?r;K|Lcv50fdZ6)^xPqHAyG5V7;F*2cEnS*nV=)#496!rcvK z?a?CcMOHyY$|spHKw>g~za4Mflv6sb^YzU8eWmd$`TPh#^!<3d3d<`L9nmN!St{`^ zlj+lvfslY=^@kaa5gNQSD*Hv`8%Vr!&r(@46`*lC{M=RUA)eF1M}eSV?R!HXHMj43 z=_~5e4o5Tw_Q3+@^DkIb#kz2^{oHL?oBxSrs>+dEYiCiA@7VFBV~ZNJq7KW3_0 zd720Ct+0(h&PRk$>Hkz``d_D<(0cRnC-E>dDif9hn9q5Uk-(Oz+u95utdReRD8#MD z$pw@EaM>~E0qbcZ$%1|nJ8CuwH8>#Ji6_GSeOg@E^IeXri?^S2Q5^t8MIJ&Nyjo0# z62Nd9ZYFzGiF&RN?pKKwuf#gKvIX0_Ppb8AcnyY;K^gP%%izSI| zUiJnYXUH%?afOzYMS{FFv$9AQo1(rH76%9Z0A0@q8b+rVZE%Hw!Gz|=`p5$B`cv-@ z;hH5UH-dX)Av4eWWiv$aGei!kz}J{OXMr(79`%X0LMNr(P)<$Jyz@eXQWuq~+KIlA z69Je-l3~6V{Sh61s@|f-ErdA+Eqk+t3urqilJ^eYgfKGX$4l_88Hd8yH8Den; z;02FBG^B3UynOM-!-iUja|;YyRde)=GnsK-ouUh9QtS9WkLsGeKhz3ixB0yjEvm7n zVB=omg!(|6KpO8JN-?b8vj?CSfwyY%aD1oV-+bHuDO_aeH(G!atIIHCXxd;e=xu=6 z+ZLi9(#*;6UBqfz8zh5-kN|9t1O^Z54Xv8=`sUWc{tWkwLx3!UoQ>WUfh$k7{7$gz z>(K?D+#B!k$$(>Qa|a(SL9nw49)iEaa&S?N9rgrSr3w?UAA5yZMG{L;gdi}ae1;i` z1=}!s^h0KMh?dGodnUwpM2W_)Zdds9zqo4>kQrXx5F#C-wu3^`{JZe1C4yx3n6}>o zV>$%58 z)e9kmLDiz_0T#I1)$J_IY_K}v{S@RIpz4Hm)Q8hhutXx(V!3!y3%-Sm;wTIV$A$et7>2Y4UB@=`#g-W6jYIZb zE9@@#<2wU5lxn|18fC#!6=Uuz#rDI$Z~2snjaZjcGRP3PlJ8yQy~Z=K6&P zd&D@d#XB%C3L-xoM|_x#`yt0#x9&4tH`BVt#38v_#3G$i12+Fl{~-@nl0em9XDsB% zIYhy*xeipIMJXq0{*dws8wt!WA1~G=jxSfF42nY#4SKl2MK($G1OMv%CIu>z?bVv< zGSCz)&lOgS0CnNRoUsRJKZ8Jn?|!dJbvIPSq#~ZY<-m>;b+~9Ba?LAb3jHA)f7}L_ zUBv=--+zOQoyR|>5fvMX#8@dsJw9LU=stQ)IxZFrAd~*|sGJW)$Gl<>f_+s+*IXRV zQV>tA5|<1VqF4g2Q1mggx;kmzH|!>boo9f%O!s8eUFWIf)erc-L7!VFu8}WkITnn6 z%CQU2x+RM6AxMIuIA4{imR=rch@oVC@y6eAKrjj;|cG}_Ms z@*}fK4Nvm%_Jp&NsI}huxOQ>vHr?^QBDcyr`EioGrXjSb!x=9vuGl$h(P$TeA9|PL zJ8HcV9y>8s*YhnA0QSB=gX_6>;MjtqKQm%PcbSJhrPlIhbFJa}^BuM`b>l|xL;X>I zi|Afwek&+1FYnN!=f?)^;ewB(Iaz2cma-s4bh{!Mv^}Si^O`3I^^OK>ZR{~t5Yh9( z^Wm)}T-VFv&E1>_B5Od2de!i!$jY0UWWPA!ib8K-;s1* z_}RidV`=6+0E85Fce-sMnnldZ5Z6n^#-(BZC8Nn+CA_uS(sALLm@CcxF~&Es(E>AH zSFj7ga7?CG@E)vOjPn<=CKWTCC3-6{4|!P`ERnX;NGd`0%o>~)k%=%zDi5-E7ewC679yPc4l|{OVlW9y(H$Z##&6ACpFnxWM7rylOmG>@ zBsJdfXZ$N*bn=)Ci=#b8t(#!ZmEjXI9TAv~UU}7+{%LFV>382ZGw=7q&kQJATvmI+ zIpFZsb2gBpP5(O;WRi8^7C0oS^Zz7)QIQx0@duk$=#5B3L+sZHwg=>R zmZ|+h&4lo0ctt>A6eyB`!Fq9;zz!S^ZJCj!S1Z!0#vA@xHJ~k|Z{3Xjz_gtbPc#YA zlr8PXyZ}N#zB&~2XQvK&AdVu6Z6n_kydF{@KQcuil`IQ!ZrOpFjj;)~yydi2xZXVmFH-ktrdUHtQ{IvN-Et#AD4DT-A|5b7NW~cbPdB z$PF!gejTA3=KmxGceCpkPg?yV5Cy-n6`e}~gDTg-d+>5MH$LA#Dj#`824sFQtNS}R zZk?Q!nRXxD3%w7P-m%p}XYU-dbBk<4Xj)wtU9nQjRSJ)Ty|c??N1$&s&rQ78`mPc%XBFw%Dph zSMERh_pPny|JrK_N}iM)9d2efrbdreV8Q>;0SIt0WG0!42z-ACG!$SmCw&>@LV=Q5 zI|sYItrd%RBYVpyFkZ!!-ea}AV_nhM6)4(VBD^qJ5{!;nWwQ!R?_C!`%v-6Ac5!Bv3Dl(p%3lRb&OaQy7h0UJ{4 zIL^+Mj;Z40eKM(CJ%-@ z$b;%A>~=;Qt70@6IM`Dj4C33%J&hQwM>re>dC7nQi;s^RTg#ECy$5uShi+akh>si}Zjm467&;w2uH5+= zz4Z5V$wsX4{!Cd~{lX^xA;sY)zCa`e5Cj~_P^@9iT;y1>B)XjWszC2Lx$h$@Gl!p; zRI(iyY&n5xBh^e^pszZu0$m4x8Z&ZxLS0E}xPqLIDpDne0fb~_eDH6J&zs*Sfk}LN z;P~>==;;ZP+7>KGJTGwg?YwMRHU3C()uMo#3`o23Jq4R@h*^|f5Qa@Be!hEF=&i0! zEvFydqyqxKzWmqph3h5pNclP9-PI0dKb%_9&(X+D7fusz2}^b7*#qVxfnc`#q1k=*z?U8hUQq7;wCK~q;t#&V9fDRZo8j= zWaUa9^|h+7eiduU27V#uuy&!UloZx4ufU52zWf=M?rg0PB{brO-d8q@&;-Mo!Ah~E zbe89yJdrw5ZM%`Of|3);bVZ;P6Xf4@9JFFE3rLd0$!>s;3gN0=Agsiyd){ih0UtUq zf)AE;L)e7_rb$JgUf04uhkOeerOER#5t0{m2 zCjA}Oe1;V!yJ8;|EK&ygemm0fthXmqHN&yeDflM_&m;cXpJ@b_qy#1C4?z@}b7Xwl zT|t_B_{xPI#MKDpjOHE!t!2okAJC{_XU>IQNdeAtVHQ~BO|dblu|PQxjkR}A7f_Ox zWR97>m7}bApYol*S2|qlzx6>kW8=o0OfQ#xaX32F|7yvt9cZ8oti459{3np^yP46d z=CiPRpv`oBJh>(8;9s-DHOh#=@V~d)1UMUZ&7EY$8?kA?WKj zBl1`c^dJOsbMg1Bd}anERzl0Z-cAr%^z|DUP(^QTvOG;@W5tndBex}3SX^W?fxspd=L%%?%Jt=m&pVIvr9%OV=1%EHV!}B7l}Mf$0-KEKo)5x(E}T_oqCOgc+&lC?a!5W!lHd> zG$80Vl&Au+VPW_s=R77`B(lbmK4_$^yeUzbG6mp@Z)iHaqzIT)RkgdJZXip%329TeHAhd-yT?Y^SV86( z&bxYAtL(=Oi~GJHZmT*RrTkL91LY15@4bb%oQ6+qa)s}5%Poh+3Z9fP?ik}v$`Anj z9@1w-=tr}rPSUMMdf<=P)pN%Ut2-3C3gFdMf8k*g`(|$Z3SAQPjpyeR_}?h^f5~X> zbFIX_EadVNVbC5VOb=sovV#mZ+maODUQiUezPg~tkPu;IRtV%n zhNUL)AJ3A^R(?IeeK);O#a(#2P%}ZlD?R}wgY=ZMF)q>cz-2+jwjd>5<)RMfv{a2S z^$j8jDEs_+<J(^S5{uXd*s-+~GX%4Pci@{5r3>b^^2OD<*X+Xmu zmsShcOwS0F(vXOGry?>R|1$tEaUj8-JZWTSkxH?aV$_E8XD>ijh5L)mGYxFeswhU`%q!P$+<1r$-BS8v)A|N@zeNiR{g9HU$x<87hJcso&LeDDls?vn=uh z86&}{^o>IbW+s|#JcTXIlGm+UkQl4K(ZTV%TIaT7XI{3W)aWTTm(REOYwMShxAwCu zK*U7(-@lPO#WnMl-6t4rfP{ zT{^+Vd3Nxu8>7=CQUcPc4}8jog_Lm>0fNw{rgEXEyLJlaqp%3(*HpN-m0$Xz4q}D8 zvr0d|mkbP9oR&c8#qtW@#ma$nAwv$NL0N9i7cZ9~I2$>$PG0+t28rh)jIIXqk)V7j zuU4s#qo*B2*8Fot^i(OL*kX{E4+FBOm3<{YUHE_h?~J9Vb_PKmuivOqOC+qr#Ba*{ z6&LUkbJ-RCKsue<9*%Vl0&*u&!RWrBhtJ!q$pBLPuxdLmdn>(IN^q1p;BaL>_*%d8 zzy!z{RqM+4uaoP2qit7KOextB;wJ8$b>uGJT`Cdu=oG+c45ZQ+Vyn6I()LZP@x8{@ zyz>^NALn*@yX(t2(^&lwTf=H#)YsPFB%ZH|$E*#e#vBt&>!66tL7=lmqco{fHq-@` zn)$bOmM-5@BOS>>2m8@-n(=-ADvV_sOx`oZ%c(* zPC;+Idv_;({3S26LTBYAG+iI3om!V!J}1OE%pm0>r^d4$uCg#7O1G4@tG-(V#yCQZ zJs44`A&GRs%AJX1a`*E%AAK<`s11T>ep+N7>-!&YWoM4;W&hMZFXWmQiGg>FTF{!n zK&Ya|q8cQ`8#K-15m#1JaUW^p>MgZgMY{>aLOYm%=7bGk$avUocNaW4%Dwb`hFt$Q z%-VGl+IUa*#?DjkRz8(@e}t~v=OuoD?oHzQxb!8C@8wsR_x;tU(ETGhINF&eF8Qw^ zuYp08YyJDIPk~K;(fckn_j%l^XOWH3K7eh}pJ+SyPwa>p`{M z2^fhCC>jO~FAOw1e?D6;g)UdlR?vpf^D}&k_F_4aNhyFolZ1mv`q*%L72MD3`FqM2 z@9DApkv4Z95$lh3wfYDtuyaZkbV^5a5|$S8_DO`85IZ`8T2=S*#yj|sbZ<7-}I`4kOeti`7!G#dulkKBgH z6S9+e0_#A^nx67wL<1t~BOFD65CYFjUmBf>Kg-QB;WZR)iX7*ShL;2%Nj56OcC?Nr zDwR=ZlSV7r+J^A2PW)z+ZYDrg9NpD20(zR4@W3i4t2#u8VscFsU!^UN(T#*(9cwa^ zUJ#0wegd@4sWPO6{p9+3OaMv(z#yVj44-|BVR~nBewyOYkKwOFsV^|agQHR?;?eI1 z*7JdId8|Q(e}*IVp9=ZfUk8Tm*uQ<>%tI%|2w5_F)RFcw8+$_0N?F>IK-bGlBD(pW zmE^EqQvz+OnEm#eOxsB*`nO_S4eEJ1QR7hoK1ERrhd!`kHIa91YQ9cc*gnI$bS&t>!18x2tSR}E{p$23k9-@jQqkBBYIJ_c;2>*-w9jp;#is+`zq68fTh*7aX&7)rp%r!!8rtth|g$T~JrPhraR zCcdQ1czhJ)Zn;qZPeiZX-QNk~c>DHS`uXP{sVtnyiws&ACoGEBSJj08gsRpR_}vF+5iY!&}z9RSk!R;`@3iQ z>%aa{vvZf%V&Q>yI_ELBzW$!B-n^5$KklCB=YRhr(Gw5!e5X$2k}00+QNw|FCju&E z*F=v`RR7_h5S&*09ztfxn^FQhyj#rD?nu5?9;YVkQYUdaPjW+$WL1YBL&()vV*~5M z@7^l_W1)I|v*yXha{^j?28h{=CoH$s_G(G*zI#iXxfdF`EIk6)bknUe6&^u%LZqq^ z;06B9x#nxhCG>8sA#{xrC@Kc8){uE z`yi3I5>N!i$AwY=Nl|A4M1-1Ul&vii8rF>fk&MC1EML+rEEwN4w0(Y|{RYvvcC>lq z`!moi7^Dg4<`)Jln!sh7@rqJ`uv}N``fb7PrtmA_$|s-;g*T!I?cWAn|*$_|9o^kZKBh zehY|D24KtQBPto_jrgvy$W|ng&&*2djH)SC2U}k)fnd_aA2L#W%g=AAsvgnTyoR85 z>Tgq<&rW~+mg{O;8`U_ZG`L0`(z)juTt4$N>wyz&ca!w@_}E)dn|NG67)P9$-a+VV zimqLUoal2L>vk{cD_%bLNGJ4Mervt4xt zQJh>GMfebam|%W_vLolc27u7(`}K3nF(>0xrku#T5ZYw^8AJJ}PXlcFQ)b*((KeO@ zYFkj>Ic9hMAH6n@Dl>?>Gc<#FJJx_7%;}?=4ktE zU+4WOnc(=fMm`~K6f`31$vWp6YC5#AJE&h@VbcdiQ!E>ICJ4jWLVoajJake&@CD&9 zd~(Mk^H<7-pM-9#@) z8*d8tILUuJcx2M_JDsF0PVs~1OSbqtZ=Kxt$iD#oJOl&L22ZzN0swIMMmSgq=lBT_ zD1~}esP>ao3m?VtylO-)@&-Ut!q!~wS!v#{j(0ObYGK{jWk zSd&N^dliaU$WldOhwA&9mzEUjPds z=l+{TTDTR>`Tlzrlwk#duS-puLqf)4?rAa0gv}L&(x&THWI?|%KLdpD#dXp0fnazb zP=wM7y@rDgw!y(;%y(fLQ)=+F6r zLCe0Puw`NNc|-dr7EZbD=4lyPKKJ=iXhQU|m9fq7rHpZ;an^ajp-WH0wp;^@Q=?6m4bKz{SK5ApJKY4p;E*=a%htmXX7 z225uK&7lT0wwmMiNylm+eGywt=$A#oqS)to_v_qhbcPKvW(T+v^`q7xK78LnJD%Z) zzfw>S?frUMbJwe1PpjUi1G!@$GX;(~!l_R!m}RGZfR07M`r8D>3LWF&m?du#VRk(J zafs=DorSjCOT?LiO!WOEqNoMZnCd`BXL0P_zY}a@tB^aSu)Bc_^lO)?cOS?RM-lp% z!gwTFYFckjSZWQ^-0IW`uhXCw9WL zJE!s2UueDXH!)P80hat7qO`9i0#uaHxCL+EmiwY-E^jl1dZkx+0UmStiDtoQ@SRt) zi6&X|ZB!9U8K4PvZDYad>6OO^$`r{F;Hx?Mi%M9zXmXuC6UwuU^~>>%hx72@~>DhPa;Y7t@%3R4t*Jb+pemA8C#d&9zUL*=?4N$UK> zeaFJ$_T!Fr56^Ue|G)w|3xh9vnGf0r+y={%w%lJ=zx$4=tfOGbrjleHNcmT}hT;+j z@=O42BbqM>pei&yv2HN%+4Gnxb7u@+)odYA8z^M3qB!IL$uzkVH1>EGIN7(3dOr5 zT-1QRTt8SMu>obWZooeaV_M^vm102@OAZE+L~&CG{j|oVdrH>w{u&wkYp1vLjlQFe z;)%X&Hz5c+poTV~Nqjc#W6P_N>`Ky7MJ8c~-8{(qt0G6|RU26_`O(?)f;!0@tl{JJ z{hW{A;QOgWUVSI;FOW3PX<&!nzy4mI`|R=aCw~uT?tjJseN53AJ7>F-naI2LZNLe_tTpg^eDBHJV_}kUl(1gt!KZu{xALh z=(k({m<>C1RN5$E<9S)yb1bz^2Kx>z6N zv_Tqr0K|>kW}q+#bZ&L)kG}%|A~LQiT!kXmy=OW{_Q*|w#60&f=hAP_!I_1bBZ-!{%;lIH3UMyC! zAa0*`BFM-yCF*2fbKppmd<_@W0}2=^{UBJB9py;p;z)`RxCogmQIL>Z0rB&pPxlP$ zAjqevD_$MEWj$(wZSfHL_*&1x3_%-O2>2jaK_uTnPGpghp#98LAFBh&nU+$bUU9$8 zN&%6oQQe6~7}OI@c(~SVypW0|f5Mst$~E72#e!yL5qoyL4n6btJ4u`+0t^d62;em% zb!MN<7GhYaxc=pG!M6+aeD^cWzj;gF{qUV=sQ>)OztZlm66%W2R^(=DdGzY$E&Z^1 zOEYe(k1reg`Qs->)-1ej(YIXp?|-2D-I@nGKXcDQKdSo8cSOJcPqh2VNu*-GSWx-) zma^OTRPjV01`hOQE*o_HvLz3vix)UE)DlvbwhxlXaDxpTV+bDQS1T%4YyOod7$y$27S%zXu|+}Z*&1y zMe(=!#C`M3&%v5gyyN}=FYW3R?SB41^zcM(S4;a92C@(e*yT}jQxHG~f&w@dmmLf2 zIikA(bODIs^^qH;Q9l{v;1J&@M540UjCL0*2z+TE_}7}99P3bK)Uj9x39}2J3wc^B zDmnK(t!?RHa3#*UYPA%93R8+`GQmnfHP$AEZZyktg-ckk8d%&clRVa69y9y>P9xK~ znSkI@0@%ZZxdGTo8&K#++39EL<%iCAj6fNK{4ZX>T$evY09DkeR*6gO zOxOWL%K694Im2~xxL{PP5MH=StVBmf!R|G0cLL0a1*|eH_OyobbnzPO;RFqBO6cx8rn>{<%a|*EnqoA?YwtI6 zk&VKL`tJ9>aGjYy2*ym)6N1zLobuc>tzhnBQm^@8dnZ2=OZb@e^DOiPtd{zns6%ZO zw=;B}@mM+I!{m=f=}KXklgu#`=xw$o1Nc!O-2sKfIB0qpVI1VZqH853qXPK+w&=yCny?Wv7>Nxrpv^^8&4n=CE86tnb#1BBG>S^ zpihDF1RxV?i~b?nOAA#i8>l8@l4;^BZoOB5Rx+Ju3l(C-_hTleX-)2E7LSmTM*q>( zqs_bGQ^YH^^e8B?Oxh9|Nkixos40lpBTl-dIP9`C&vhw`a@c;zqg5?eEfRX z&}w-_VONQ-$ea=J{il0ICK>(H|MtI2-9Fvl)7_8v)NG(xy&@INR+3fx{qKK|{Nxm# zD+%rV$4?(AAaW85Hs$(;!Qu`1)qbH{2drD_|=l%-^pvfJVr+K741H~ z$e<7>XoQ(-K;PrOUB01kUDGmS&{I26pHb01Q?1N13&RBx0%mZwjuN9zL#{Sz zx#IJxIgbbypaTTn+^fJQ-Kt|yH07{x!D+k{JZZdWr!p1>V5VrP$-3E+#xmIkPPuKo zIs7*~gDfY>{y?c}0|wxNppiW^^r~;KgD@ZMcS#n=?@wv$RjTqTZtt;U(9%{%<10zJDlX?@aDjZS&|8LuDE_nd9ma=FKAnQq~`99 z_V7J}@-#0bI-k<&G^=_h7QR}O0>bwQLNxLf1^q$fCd>h3*mkrLOGpAy!8S@*O`=7l zlUdqm(mwbcd43Nk?^CH!kSq&%W2=s2Nyj|^DhhFM$GpodRA$T1jv8?fmKL;Ma2k=W zmM~nfa9Z>&QBu?bT$QuU=L7`-l7!Hi@QMg({fJQQdYLxTPAl0HNd!b85JfDNau&>| zrd9N$IsqSQ;5!B5E23ZZG~LeVvr1j-!XS^2&Si)9IY#B0@HOcy z_|xB?&W-VG6cfrdB)VSV{w9I+_nA83c_SX&(uje2Nx>u0Q=8gU1K z5)MkshkFIZ?{vGxlN$VvBGW0Yk6XyP4-@b>1fLzC>_@8%oz*D?u{rl%7T_ef(*U7g zr^zP#0w0mXatbtljy3B@)kh${?<3K!wQl-ZkJH&Yy^$f@`V1?bgxzoW;We-f7fDEIL#Qimat@UGg6il8WFlMfjHkbR9UKLdA5 zw1rS!T&-^oM-yq#O%~=vOBZW^_UpWl5!FJa5eRBWYoROL#Q4&mDlLWcD1yY9>k{^OU}V92vP- zSzx*n{|(c;BwAOi^@(XqS8cOuhcd~KEXn>#%_SjWcKLTNj^L$+WhLFjm2X>{#mGX= z2BTZRi5ZUe@ISFcc#TB*YIIYE$FexFWoG%fp`y4E@F5Yk90XGqwg5i7X}Sgc$nX-) z9o`uhg8h~S!sVI;#)h_=Cn|1l==R;M&|@}t5A^cm1I4GB%3{re)r=p#qT=S30quKQ z7AvYAHuTevAL+w~4-_i~A4?WcZ{N}F&3mrXoOaR=dwCW?LoCs!JYB#0p0-@i!tWTF zds@FO7;rFt8u-_PKj zzhv;0i?!oH07gUmmo08v*5 zh@Iy*HkZ{uCp2kZ2Wj_AfYnwkhXD@e`>oQ?#FIT*6dE)D*CX;kqa~3kC#0Rl$-3eN zd81%H(G^U>4^hJu%alx-E6}gto5iS7@)SW3%@y=$aD>JHh&Xcf)>YrGd8vd64Q;n6 z=^7X-0G?7Qr`(PRuc+&hrxcD)#O}~J6YH=aMEHBB9G-$w(*0->A`kk3Sm9A{!4(4i3Z@tl+Yn07rl z22m!oQLYC4lupz49=v0)evmn*nZO5iY-0u=yv^bJx6zFb>n@|~Y#xnp=DTB-wM4$` z=6b7ZaAS|#&R1oS-^TUFZ~NioyNsJ+nwT{D-klPD6DT~>JSXpwf&hJ8Ad2bh4{3WE z6)VY?Bk(?+27}x#y=S!ZrHfxXc*7Rlqz$V(UssT(cfDG{ySnz<-xQAie5MUus+xhk z+s?Z*Uqcvto~}cL+{ZuvnTqQxmY1HW&NKSv+uza0pZ-F-eMO5>!*o~GZW4qHYKO&Q zX0$83H*y}#S+HD`GvQEUv3S{87G&Ne0Z8&uxUFLvm17wv&o|BxIi9_0GNOP+iGqU+ z94AxAT^$QapFHGQCVp$u;J6+V?bS{#944e{u7P~uSSEs^h*-!p9QB{%vyTBIOY06 zC|7xYEi{rS#0q5ThP7iWAz~q1bdfu}*$!2Mg2-AG63^}VI<7Z_#oztz_bhBZ5Hdu|8* zY`f+5Z5Y(OfIh|(gC_}^q2f(vA5`lPVIQeNXx8XNFy9*dF53M$tOqmEvd_L<@sR;Y znNbD76d`s?7UDo{y5$?c$;3J#$+I)nKO^4?gn3y?V6Dj+gqY8aB!`nQ%#8@+y1pu> zK53;JTZF_91mS@TlVi*sE3Y+?VFoATp!bo@-o_hT2`YUf@&LOI**_d;(1g$q`Qr~Qs*^HMCb`MVoh^LT#danbzzk*Y@?Ta^<)Cc<;B z<5KkS=);`_n1C;v7@!J`nv9$;L9G${?aq>f=Gx9=-#InAgTfKhIv~;O8jZqclt%>s zc-I%Tnus6AT=FC6+R%tlj+`XeZEJy!5adg>e0Wt3kR_WW`%|^|46aKHp`8^15Noqg zVB_-UZ|2(sW=UycJ{!F?rmvA7(BEM~hq}r)RF?3eDFhfdp>DwknWmW%UD7&ob{v02UDGvWp3dYpFLA`VP9Ps}2P45^~6YNG* zlD?2U5K`Qb(gfi*Xjtl2*o;Z&?134Ys8`Zp`(W2J)~KUnU*1XdBxg#bwDXNP@Lhe) zignBq(2m*DeRMP#n(KDJ1FG0q@a^AYaKFrGP8!Bu0YNjm7Y#y@4np#_;G^f%Z0`dg zq6&%D#lF|}7JV)Wi2cNqX+FOu5v3ag%6{>bGNO;$DDB6cM%uR#!88|=?^(Lid>vcp z5_4sAU)P&( z@kzc1mO$C@9zHK;lh1Df2!`qmKm)vF(1Q56ph`SFKTBxSVzHvDt804M?pcTc-};$m zS62rdz1HH<>#!-aVY^wHiM-9oc(9lyBklA+j4hIOok=zJva!mB*bKt$YT~V``+L;F zU5E6Z+d3t=-hu_ka;FLJkW@$nvRpujUc&+h3+D|S_Q6pH?ZQRlgDdC>ZHGG5e0$B& z5hcN3DZVxlejtbnV%;T?wxWhWj23l7okan(at*nQe@; zU2)s21$=-$*2TrHdOw=!Sef0a9aM|%ExBI3)A8_!fA~k*J=gTdKmJ)9zO%X%%Si=} z{OX#PD+U+W--tEi=Rf~K+kgF;gaJHX)9TF)74L5-U(UI{fi}Axy@2YH%_K2hv)@Wo zCs>^%ksJg(7V<$eyqzuRKmFr1{h$BK@8~~#gVb|8M7g>C+GO;f9~YFvr38ukHU*U9 zv~2*USvb%43Id=nk5Onn3%-AGo3Wt2pzu-)1r9+A0Jb2+7HERfQ8h;tq*7=xd!94f z?M}c!lS6A>@xPpQj65o*R69u}jWD>SSs9%6pZJa7riBwNzVP~mXR4GHC^5uB0+XlE zSQMbZ{0*?=#HbV0XM@xd;A^D?<>q{j0aMAQkjtisd?X}oX~2#&!!*G{g7Czd(I?tH zm+Od-%EtZ8Nd-1x@X`~@j6m(p6H|3_~O~R zpcMZMN&Q{>XX&8d+9p z_I6l#U_DKd*+{dY%kMo9odPnX98O;xb!Q+PPYFV&C`Dc;R{Q%A3dK<>4(91j0~HM9 zU%O%5 zzq}j^WH4lCPFCnBI5!GpuP=s|A6nUl(XTq1-_Xx$NDquLeKwAOI0igNs%d=_43H*E zNUBeoN3Gpuh zt?;t(h;qK9_4O^y7D(#065;CMr=KK8!_Dn2eY(3FAf&;o_a}&-Uf{ZT)YBc1?vVga zI5HB``rZMLz7L4k$Sjo5Tofl%B*#jbf8A(6j2F6Q94EP-5C_^8Ss^lgPgowHLG-4v zhqLg$(ovjf6T{kf@9H$ubA-Q!SNc^HzRg1ThZozSkt@*y1a&^fNQ^P?cLD-b1V&ST>0=9ZrB zKGDaY9;y0NG3s5?Yz{~BoM!9yboKUIZlXCoK5Xgk$B$I~^-eT^h%0^b{w?3*iiP@| zHjGZ7>D|LGV3iA03Fv5fzL4A;&5EDD*wfW|LErsuCE(+KDiCZ{bj}iF z>g9^)N2KxCY0{+z$^8mYhIZoQE86l*EmwJ_T7{hdF1ZhyWn+Ds3urKQl4fFHVfN+E zcOvkDb{EQqau%ZD_+1wbgP0{{H-!KW_&FnXfHQiPDC_yUiUmqoG4gpP{vGhMK>aY$ zkyRUx*<#HqbCs36(juICKg*aA;2{8~Q42+c_dx`fu)QJb0^?LjCJV7DdsCx+2>p2c zDtwcgO1v|wT@;`a#ot1QB0fhR(prYN3F5f|E%>e=ks%z=cd!s~jY@9Aa#@;nZYOy` z9zWcP@69@1(fn#gO9Tbu1#1`K6ur|tEIeoT3|NFhwm_hOD=OdD;s(7(EQQTpa>0NL z2EUeEq+HA;79f@xj}z|aeXZGAgGTp~l%UZ<>MH+9EEC?GW&wc34+8)=DwP8BO65^$ zIN4as6!lG(u141z2;!I@vCwfU%lFQ*o>$sVt~6)tT)+gv@3xMyjYVN;)LH@?2j-YK z%tK&<1uzDA*TN-mKqB}!mzgFwIT#K#Y>BsgU}`sqYK(JOLV`HO*RA5lkEpRJ@}0!S zf^QI%IvLiCojC48Bj(Z=6wR_de-tID@2~PDAVk6xcXv2*_LT2LMneJQGaQfwsLlp{ zEaSF58fG?~d&U9&Gyq7}kK+`rq`_`;AstY=hW-)y(B7~9bep;`+?P(3p`*Cg%Vk3+ z{^^X(gU=U${%Xn*L6C!n)9@>GSTL`u?xE^?47} zo;`-%{W3bJi_O<@KeSXfe^{4(sOzCGh%t}u6p8oOd z8+P|3QeVF_>u^6eNs5}ff{Vt-kCIvf3Chbn(>a)TBcU`pR=>0WWVfqm$>5_l?L4Sg zo86v2LsGDxXokEW-+n{S56|>zx1$*{B#JY7FM0QTOW<4L+Zqe09J-xb7<*(DYPqz zB@!DEvXKoP=L%T^(y*KJc~|n|7=#FA1wexV2Yf!Fan*x>8V$kg%-KveB$;xGBEqKD z!sWkx^NyZhHuU3v{fXDn6@!uQX|oM9U%wGFJmVw6i$30O=;NRGockvMSIckS(Spa? z>}n-ctCu~rua!7#BeQmSvtU57qjC*rZ3YC}7x6QYfKE=W8pZ#|+M6xOjwD%PY6ig9 z*zTH{x3a2wm67Rrq40tK&nJrTi9!lnhSS}(WaXZDm)Ly4Vn#ixY6b(`BW`u~L`jtA z_3#BS7|isjo^$kiL+hJ?E;xW)du8F@1O{EMmg>t5zYfn+J&H z;sn@KNk_wD*esWH`0z<|1%#|Ogy?9fhz|4{%p-oy*Do3DENO)b4PS5R`NBg3@Z>M~ zwO9P#JoV64A~(~FHcP#9U7?BtKEIHdR2``-VS-9lg(?y(Pg4~H;G~XnT@XZ6OYMsx zcEZRf^EIzQr6diSd#mtuV$Z9+eB>(zEy&1cqPmeb4xi8kX@=En2rL_**!cFEbH(w2 z4%hNI95n!y6KkM@f%$=g`vDpLE>hcx3WXL7e&O1+K&4?Bq;CqUJ@>Z{3=#(Eyb1JKZIzIYc9(bZ@ks=yz(jjB#yr4Up;!UW-K-JyoFH8TQ)z&ze?h1+o`v7c^Iu zWfDh=Mu|W)^B#-MA~TBO1eA!zq|$4Sxq^zG^dV`2IAWy)Q0f4j?aEVd!)t+7MS`pw zqH{^wF$!jIFmljC91}#N^<%MQ|2sj*FcFb|PD64EK%|$_Gd7x&?Bm%(^OmKaQHUs2 zcpRNnKFZ_y&r(n(bg$D#WpugxXajGLQL2OU6DtE8_oT~{j^PmgN)hstho98_ujzyz&YOVs3v-xLqwnT*~Xh%-0_RG(k0iaN1um4@=b)I_u^v@IX&-UGu zX=48_H6UfBXB@lp6vSNF8~SM${^W)B$xqxLqu%U4AOd$|V&dta&&;pCvI6(?`=5$G z({Vjd&pLnfBPcp)q?xBfx^JfyjqwBBna?baC&$PBf#b6E^|izS`;YI5wi}82_K&yn&By(b*6ULmmH?2$;SgcPnB+)| zMTCFf4lM_fEnU2QtL@kC?&#v`h4}yCV3zCk2|^sjE7QSv(!F6`(V9JfD&jh=A!z>( z%B>e;%FhWn^V*S_1AGk{V*cD@i&=hbj7cmxT|ivkutqHeh$wKpauW2XhJz}42l(ib zo|TXVOZiyL*=jH@j6@Viu0BI!fgqWC%{L_a!S^FF1WORs`$K;Y-KbDn4yoh zNqD1=ET!UsN(mgV)YNpaz~P`276cC=?OyXq>~-28rO%7Un#cBwm#^u#Yw4G7z85_% zZ7OkqTD^Epmv6qJ_3DP&{Xp-(`#|>}?ui)0a->O@Uw%a|U%wInbcDW$!BQJq4%RtH zUhp|=IFNqrXusp2`i3NfzW)?tf=YLC4uD$@GSQ%K`C>)umlFTVW+c~|RO2AQ`9i5d z3`^*UAiFw}+aRmm2z?019n}wM?IsOe(1C%+V5bge-e@)p28JsL%@Mit7)lc~H%X&l_`0&ym))G(c5ACUiuOc7vFA zsr9o@G#XjBoK|P#+G)c?e8+mR;c@90IHH+hkRCWSf^AT}_34Kx{d9~7&nqM?<(`%>obgi7IU$CLKdQU|L z%)_wv7=b> zqH5%W(u1U5NgVs9SjvCY{rDq;rDP8R8AUl305O?$h0C`UTk)Do$$bSxiJeSE=4by*Kg#OGo z%;L|JIrZcP{%b2UZt^+L*@mA3wZgV}CW-O6giZn)r;Wo;-+%7!LaXKda=Bg8p78+~ zQ_JfY5}UNV=eNiKg2oAyWzTE{WO(bt)QEHtdV)53<`3t#^nm7i;+) z{8H>koe0{sveFHSa+AJaDI?ARjkiXN=$zctjZ{Cxr@3wE*dF+KeAY@9qBww>#jjgj zF!J3<_752rR}CVbMwS?kHbZJqgwPZsBT%C_z~i|?o8^`sZ}(6i(eM7|cl74fg8uj~ z|4etE_5x^7aX?x;Y&KNCe!-LLf)0-z?Y_UI`|p00h-dlc4Q;=EOV!neK7cyoqs+e! z`UnOS+Y1JCH=tMX%hw%UTrcSHa8JXM1JA#`q5g*l4mKa93FZo~-SB%kzPsbk;BTN; zJc6rcEBR=~;`A*a?jIQR++l;-C~#O_H6jG>A@q+*Me3wSN+nKFwbv@Z`puQZu3l`1 zUDA2ep|jhCU%PwY^Xrg3=FoEA3UvoT_;KISVpvhb$KSiX(5nO#Fe-sYM}S5(h>ClN zOF5nZOWsQP@=_teSO#sB2dWmC$T*rE>H@SN^l9YhUhy3Hfq2iS;%Pg4-Z<}fw;tX zQn`Z{xCrs18r!0m5c&qWhM(J`f5^adb5Mf>6ZbE!*3|H^_lKi&UfuoD(xSbf^@}B4 ztuca{?vsvJKiE(M%!`HyeM{P%1olVE zR^Y!Y1DNRKz84EE#il+Alje%Yi>7l};xMXmauu(iP|&&?X)Dc(I0oJO^jJS`!S(DI^M5>1_iWgXO5! zdj*eIdnl9{?X)&ytw_#IuC|^;RW+{7K`V};2Z4|tpe!cC0=~xh^=R%oNQDO)m4M_6 z9I*gkjE1Ede_5eTXzxZ2Z5gJZQd;@i^c^ZMHNuxfLj5D8c}I> zJZ0d||CHj}+4CjsB-**8x9t4*xeoL89$))OK%6xQQ>TN;F^}Ih2Vybw^xV(q8!-d|H3@pxd)9*`_tvvrvj@wu`QTHVz zy6g2?_I)ogM3DXB?b|Qu z5wu;%*?m^JK*`?=4(HUS_lbc`8JJmxWez}M5{xP?gm@JjA%iyrudD5f>MaN4TOPyZ z5iBk8OEit+b3#844)*(71b7>I@sb1LOI^fn50QS@Ir^hfnE*rpK>oC6=D(pO9>?wUEg$a>{NEo%GZKKkq)4Sqz+ntnGtQb$#g_ouGI`kLFkVkd1il7Cemr2ym$MAp-xx)P^jU;QKZ9zjYbPQ4+ zcTz>XxY=qYYRMp)!312Z26&4{V812ZJ+`#wNpkV}YpT1N9vC9FKmQ`vc)3BR^IjSV zrVTxKz6VxKj!`Rdxry3bP?|GFN;bTbBtX?r0{zrcn2bKzN<+|W$!pgm!hm24OvM6<-mLUp^0%XWK1A1mycVQo7o5U89cB`T?6lG3=GR%4{6 zP#8=DQh*Svwv7RzbvDo0f0thuQpa)sVkGGvXNfe;Ll|kpR#c+J2a2llFww|&oERb8Pvk%>U6B0s<&sH6ts*)Pb_LKrTzjx!=&!0c{wE4pm-=FAy zDGB40rX_k=L_Pf6?cITHu2$4A_;`5O(Z$6kzg_O0$K9helfyE(Sfg*jRu;Yo2+f!4 z%nP&cvv1XbOcmItN=MP`J}Et>Mf8UcREsCLUh;ivEa zOnVN%;h+;aa(0UqZC<{m*I#@^4Wod&@88oee_`-~_6W@d2Z?WK{pOW)c&~?60-4Sq zM7RuHK*OI|alk(;dg@m#RTn+a%Ym-0mOP;s1oO4KOZ4NoqUK{GqVD5;qeG|qE{HERw=6!a#5E;u{rZ7E{#mdA4GR5~PogoxftU`=MZibpiMi$*zv+ZTF- z00D)gAXe(pT^xgs{w&K{64v37@1Olq8dBn_f^N0g^7$`oRY2_c9!B##1{VkP0@-YN zo~-HWH(RlGZikxsyHC=m!W~;$NTt8yImhP?z~88O#*-)cOsoIDjzyiQwqclsQRr39ZL{Qa>MX`v#4Y$f= zvCKFqT20eZ>LHHLgs@$z!j)#WH6T?Z0nI3DurJ11G*)ILa7*iA;bx`%J~Trv0kZSv zK31LDaz|Ys#F48~Fri78LDq@X0lli!0WJhyS7NIi9$8yL7Sc|*(~0x<#Dwj{2JPT5y0jpDYAjxQ!ZbLy04<@gJ zhN4$$-NYKUIDeli?K$x^W;S&khsiNNWp{r*Q1Yt5oPo8{4eIoLvjD0;&453ZtW0A* zIX*GSu(0&Zql@tw0-ZJ=EyeXG8lPta#Bf4E%9WYo_)4%eAKOS%0Q(EQN}mcu!g<=F#mitvZIZ zr)g}NDjlaLB`NZs1E^8cC*K!rOrugAyRM^a1|JU(M+P3t3HZQI-S=$-_`uJn+Xr#{ z5n*Ms(CkeXxn$_^>;*pI$d%=x=dw}%!JjOknID(*!q9#gpbjCs8N-={`mdPt$(C0) zjUuDqOr%{|HV(QEG*bgFe9#JrR^63jpY$IBd=P0N`z-)uMFR&q0wmBq9a%@2_k#oi zQKJX5N=x5sm5;{kLj|z3BAi9_1;K*!4FUHY{BjPMe6xuX8S-xF(k`}zy%9{&FQ_w@6R-_X);`Lh}U6<4oc)9bhIXvIO^`)_}u zpa1PAqFbKuufC$|-@c)XFW&H>Ea=d+YE2BP%9fAuqN2@qD;1CfN z!~NZt7jnKo-tMUx801_zdi-Nx0Q4)-Jp-6)+&pV30q!|y`@{W_mZ)Z|2KvM|*n7VI zAJFq5Ihq8uD@L$YFB%nd2Sww!??B-b)c|N=($o$@XdbI0k2fr8g$AO5TIYN1nb4Vw zP;c6z+Wd<;FV0If!b)=#5jN3a-2B>$?R67tt&#;5*Viel7Y$@a?V+GL1a&)cVr$xo zY3rJU!fQT+*Zi+92sAVv8vZ@<>(DCnis#Y-fCkhb36^W42a*BL+#*lFseojmsCY_P zEhh^REH@Zmb+xFZnPtp;-d^i+a@?s>hYd{{V*->&%u|cdx@Uk0Di$*4688FKrUl2t zK!=A%X*d|syprd{@&Xz9Ep_)hp}WDJdcW_a7t3Z*(Z#!WLS4H1_8V${eJ{bfw0Z+T z#Pxxug@5;OhdZiETm_mNv?Bd6XH+Ed04FDul%+~l+r5X2&0w>dhNcO81AmVKP z%3p_K^Rjzk%sid0x%R>$JEzZt;KqO~zpkLl#4=cOXFhMNR1B@H(-Y42ISmS(0UA+U zg0huqOy5s>;o_Lhru_W$v$SfZf6n)}G7|-M<^ViuSO9K7k-zF}{)zjt__-_aObrfW zae-6bFa0|fJw`M}@s`0qrRDv#qT(!Af5N8K%OtjQodYnb-06NAl55xOFgfL>3~&coeMyefo-I*2g`W; zxnGEuNEJvHv`iXT`1}~p9{V_k^Xse0&+)#?6}ox*yr>qP= z{hiY)@|nn(C?z4}XVwqolx=y|$l~AobH4hKzF=C>nMf$26$oYpg{QP(cDe~sXSaYkq<#YU=#No4V$7vNXWVWC^3Z-DXdhx22iW-AN$YD8MzwBilz z)1SYmPyfQ;<2?tv%NIlk1{KF0E%WpUi^$RUfp_2? zC_PcL#`qq|G$R|0?7R1wQX9ZT1<&(6+M!~IuYo%qA78_NSgf?)ieCk#@W}scDfu7=^&2qPu|cYnJvxk|g&~5@Ui$&1{u~ga zt3F2QSSc8@4nw2Qen^{%&JdqD$Abld&bafs-uWIQtHv4-#Sc*3m|bzw&q-All{^7J zgSx8WdvLtCt{8I@pOcB?bN`RDu0PwU{qvi0Nl7~WAb&z(nv2t=0(l}fKbKKI|Gdip zWO}@1wPw=6`h?=3K*i3&z+TLTFrDERZxwz`M47p#tWnzRaSFN;!aM~YSv-*=pla%* zGz&;S2S`HxOi!tQgq%h0b5UjSdmi^VisJQtd>X(!`}ov#&p-ZzQhj1VkjJ3_6!|*M zum5<~`Fx7^Oa$`JR-VocWEsGhfXE8<#yXKWCmGog<%Fg_8UP7eA$J8+BmZGGj^`=x zi5O*-a*9TwFYb>Ni^L)TFTW>`Pm!=q{Y6a6moLXS=zrZudc9RW;uiPl7Lt zv(pSo7(8bw?cYe$!lsF17&H~ez5*8Z@i@?GIok2opzDD4g9e14DS6&B51;Pn>Z^Ag zG^&ftSem8DB$18kDQeU?VO8;by09aU^@)Y#NrWk%Vp%3v0F{v=jLoxy9-=SH)+r-n z7x^4;J@-WJlxycL;A1H+L4lI%RIj2;7qi|j4Vln>NVArbJ%^YSPGbTHv?>wA7BrPj z<<&O6`gsV9)%w>ua*H^$CN8xP&k zgzmusNGCzIr?+3cq!%x?^wW>u(uZGv;MX3dFhG}I(#;oN%iqDi`IW)P_y7Dyq7OaY zY~Kjrx#juP)<4qYc1tVwfqA9GvzNK){cf6B^xa zk3e-#U>Yr&jr1MqE9KgEaB(7anF|q}!5JiSH1DO5($f)krl8az`wWpM7LjJ;g-PIt z8+>rm91#~0feI*BclHazJ22mN_SlC?lKVj#5h9$eMYogsaB0CJnz4>Lw~elHgHri| zikLCCgpmYIM`M<~l8glWan+7OxeoUf7xJB1e^%!u?(n>5`tjfBpV_^0M zT5$c>QmqTaR+9vD5dD>kqjj9f#vc?#=|$pGN<2uFwX=Y>5@U^EYfq=i52KVM;du@W z5=YlGAY%hpqoiVe3c5)N{j(cP$F|5Dm}HatVO*2(-9D|ugHQ$~cP+h8)QWiMOjnl2 z_FO0usi?y z6YAWPpL_oKk$Pow#*hC!pXXwzat6RX71z(dHLVZx!h$nE0{eY{kjv{=^mzN8mdn(} zLY5AfDya7ndvg`00E4^}{#(_aiMA zwFITxcfS#3>{kTi1Z46rBukB^iU;!R1zo(jqyzsOnQDNC_AbyJzi?>+ z^4Rj6mcY{sW!^CokH<=lo3!{Kw2%t)mw}8o?}{~1jRKI#7updt8rHa4m^%0XoZbfp z8n+DOk)1y9P1mOG@f`YJBDlSzVHKrAdKAD2eaMo(lV8UmtLGr71r>|0MPF;s2?4KM za?qUMP=zT~li9-t0bN)m77bt1(9i>q;d?&%zxbn6Vs81^Avpihen0YcJW3xBo3laV zRjJ~LI6DaN5D;Rto>{Rf^|pZNM8sRHoW^Y^qhEyIS#zSU-c$o?ZkU)VxwQn?bHh6_uf zMgmxXGM6%c+9a?QN4uoCzz^Lsc9Kw77~ zx;r^kf4pY39nZ}kYmB*uscT*oDw)ucf;p9uQaaIf9+jV%XkmUBGp3SLT#RNxP+GJ3aZ%0tEKCDnZOBUWq>Zoz9MOQ~{B_b7 zrpRnhGRJaVoF$^vPFFM0MlX_YZfwg+?s&R;rN;z-N+6Q6q<)~&PU=sHWY1|};>eCj zl%JDIOg2R@nx_E|Eki4z%F_t=PBQef&fW9JkZ5gZv*3OfaGdV-aWdfOzCcmk}?Xf5LO zekum0IFB>mo6o;^|9^yb^qIGO)=BK-wdW{?W5Q{Ao}S!Om5F)Zj=%PFPUc%4spsE# z#^6JrFTnIf|6yyv>|?V%drW8X{PE`sdk$~Ye`vC4xm?oz{u5o_Tq`re67$Cc$9C%# z$7ZpY#cg+NWh1N63=i}N4qOlWy=Bcw3GsO!8en(Y|9)N@at?1D7~A}5w}x!7D@ zv|>P>9C$^YVo58d)k3 zu&m9&N;C{LC0+n?#@|NbYU2cB4)8;-3i+U;8EA9<5m zU2-tmQTx+RG`zZ^uU`C~jvRmea>S7yXuU)ez}l?&f@G_yU+^%k=$l_jY<4$mqHoaZ zVb90DScp5-BLki0V!?o8NgW4baMbE{y?hp$*)zPskAqOp*UK@$7>+8Q?jf-FaHPkdKN0{c zy_Uv>b;Ivl1hF|qRzm0d90<97bTd+ zT7n?H-Y$5d+ERc20MA%D?shx}w;UXL+FtQuwu2p~Hu=Mb+YV|syx45$`rSZ}e4iZo zy3`MkJoWd|+z%yYxNbG;OTHHy8EXW~&P)K(Ju41Su_9HdEW~zKDg+i(fx-qLh(KL0 ziqat#6#$5KIY(juB6pc49_TmC7ZKSXOnAW{Z=3)fbzN&n5c7bR)8UduQ%VQK~piQ(5ntR$Z>3ppr^* z&trX5i}0YP0JzU&jjS}lg*~~B$q3HWp)gfZK2KH26j&3Ur|W~0>W5=KxpSYPeK5+; z8uu8VsuJefbIxrEiGZiwn7o){gk%&FO9ci^s8i+NwSuUDSsC$k#7qF{U?~!UW&9KkG$tj>acjd}{TeGV<``7b<)#oToGUszf z`HW-W8Hcs;%cCWV!o*okf5%Mp>3EbCnqCux!L&KivcW;)huT-gd~qjizvud%Jay>h zF{S&cbT0FBZrq*-ByFfhDVFZRDkBMI!jPa6X{G!DD}fJI&Ur_d%B#If-F%U1P5|Yw2t?5rvnfMAJe@-9nX*N-@Zys?w)E zdf+U3Ori>QIN1b@mHGS21cs$LxB^7e{SwLF0)CJY{GqbIS?Yxhi;9WD2|lF&-5P^j1K|l7lMW zuSAysN|p2gMBfNueh;>!z`1HA$FA8hCzih*XeWbO=xVtdKxWNB-D^J1H~jpiEhp0M zkDuqyty;Z~!XNKAK<3~b&D;1qSA5M6yCC+KFW+tZLC;3LC>*$t)`rRT5^$)hJ;7DEYF|1lgJ08;i<37^=&A};(aXTKDpSl(84tr`jSgT&w zv}B-kxCfX2pf?n8V9N7%J@9)tzB}@<>>dxa-|w|*foOLClw9$7tF{K$w;d`Gi#vgt z03IB~^7HkP$L)dt{)xfD`yN(WR1f?LzUIjAqv9c5_b&9hYyl#mo8o{QT9$ZS(c+o| z=$9+%YrbB{AR}lOC<%MoMjXIa+gdD#QBkN&Cm?qVpF64q=piDF453a39ZM3Td`w5p zT=OB)_dK8O_&)eEGT*`is_A1mNI#HA25l_>Ob6a2NqIpuC)hZpxut=OB3KpnP^V6m zSZDj79VfuGgO#kW5qJh^gr}Rg9+SwRnkYR2q{li2zEhKiREZXgTg+*tz{?O;S3GZ8 zSnc*=w~P6(kRaI8@^UQ|+QTPC8+Qk4`J~*{6~zq$7zQB=o^Ox0JH93dsc7tYUbGB; zU%q@z8wRL*{{D~mf1tzuj;9#EW^v%LJJ2Os)uY0ps8fJXC2NHCfX2N^=^Yvo`NM`V1Us@F+EtI*AJXQhMlZ?aM%j`Jssv2#3=N{%6JuHF0>Ix+dTXHK0-{|&<)hLI2X`t|NaB!sxr}R>^A>OUp{O``sfyx{ zLg&)uRP{VY%Q?U(0{!8!E>*nF9FJ<>%FgWd8^w^#yA@tjov1<20cAT%+#fFgMmMf{MR`K8m%wE5zZGM*y*C zHtSSS7WI7cZsJBQq_bc_cL*=WA!*Olip4BpXLgo-9D}PwtHJ8!d3-hC%sFct2MYn_ zREk1pAOJh*hB8l_aw1A!Rla|uqsYD{*E7=G9$4R}&r8o38bKsc;TlN>%FfW0&H>Dp2=O_RmM!0m1sgOWu~iq{j2F`%JD_ni*&vx zx3`$*#yGwTaDAq1CH)5~`No2Yc4H)MPSOgL3Fso-?hWWv^%x(f;8%N5&4ATY%@Si( zTyG1qQ}2;;u3z(r-dxmjrET__;;uUX^(Pv%XDY5IRXU}tPG~lB%~hP;SLHq6be+oP z0O>m>_pzIP_XL1=r7u`w(2cJiL7a;tE2gOMXU$@6%$>d?eV?w&vc~kSHtDX^tfiKh zVclsEN>q8W;7u-Y@Xmp*EIcs@yLEALxlCAIAj^=NFvnY#zbu!>Xc+c$H)$mue5#*I7%O{j6t`z~%X61p8757Hy%3 z&bZl)H1(@Qk+4t!ZwCul9z)P?f@UX$y?{k2)52^b##C>B&psN@HNu(Krdo(R7kpZa zoGpPv6*6VLI3{iRBXDgtV(SXG<9j~k8w6S$R5cZCF18Fb zY5|Rp9|G-ar*2CdZ2*YVKJa)!#{hM=lMMSHf`X=B%N)aoi*XscMnthkbmQ!T74UQ? z0MLTiS;-TX(4x{l1CZLIe*qs8s%Jd|A>yF;$bn@GT9h=>Fgg*Y3)*~M^D%OOe8Jal z<<$_N^}QI7b!&dn>d0f<@HuKME1YXS7U&kxc+odOguXSbTlp7Sk)E#soXT+i&{>F! zuXkoJ;55*5+7bI8G)d3E(9s>R368DO#K8a^R8(gw4fboTaO4VQunN$)@p-F$gkXIn z(4Ql>P$zS8a&kSSVPooVL+UG!9xE=Sz|o1|MgUYF&2`J0xN?vH+i9FGduW7C20S+a zuMP!|dogH014IBCDcp(HAxKr@$oIs8uR&FJa=qbfg(|@wnhdy$Eul4Huo+%Zf6Eu( z(*t$=y@-ld>xzNSgH`}Ui-EoyM+u}m(Xj-fj>+aUXs2`UmO5v6;{`SmR|ObIz`;&P ztxf=$&>}IIupzEgO9x?4nH0TdYE7y^duobWli7h=qo{EMttD>2Mgj`nke5dbNFAzG zeBQDbpen`3z-z|gagdJZ6{U?(jV42O=j*hwD=UEj(X0%{ZQuQ?(%TDF#N=HKAElrYTI8 z!09B7y->~e+hnJgekwQV5jOdX7;|7f{gC2#CHPGlT34j<>-2@Q_ZDL)i=0u=%JSCf z1sfBdKWH8NqzSs!Lgi6{jIo%HF1*FoNmvIz+PvkM=pXK*vIl6_egf zALTxa)<0EY)d>$DlcV^ zDT}EcCHKVEZjVL`iPqMTu+9e{uix?;&_j78fe>gsp>RiX(^|fP04)P2Ek#JB%ZYYR zZ<>^0O`>sUoyb$UW`dy71xOsroB?PQ7&znJ2A9#YrG1m9igqn zk~Cu6(TuPM2+?MR=wl%wA>sM1M5ruWbSdi}#OW8VMu-FfJY%(pNIInmtE;taX z)zjNswnZAn)iUmp1HFcW=G}*$R?8a!SP%D(F0S9w&8ye6-yi7Xj}N5Xo8L;;=FQvR z(d#dMCm(hA?jzlQcT3CTg4)Fk23~OV;-Kl8LDSZTsP#pVH)9~2y^;q%xb%X||KWdQ6 z^JB*g^kTE1B?{BHQ`#>*Wz7(2U7_{MP6}A736ch*L<_FWO zOC^)9M_g7izMbR_7E%`Ra$PHP3gf^#I_VIO&k$OsP|Lgkkbw`n<$>Gx0M~q9a3J6K zd)hQD-<}M{_j}RKG#<$g1MDy?7$CS;>YGny8;d$8c!ZKSXipB&yvdkGrKUwPidxj3 z95x9-r4sFrBqTH_%~ULT9|xJ}lOsKC200&S-Qa8z+P!E{h!Ta#Hk{=C=g5GvkvJrV zvTX8aH_0gw8NtVNLmyIKrze`}J;}i@_koFf(Uh_c`FWdquj_oa zc%Ps9cy3cl$Ovx4G0WM$=Uh>-QJ|;5Fctts0b=^MBp@7}0zNw)(J|31aa#NXE`6wo zNtLtE;-ufYYEIslt2ItR(b>y018`@rzZ=Eb5(i{As3f08-gW{ z#(o-bX2jgBOe+MvVoXh&3JOhXIGT<}S>p-B40(QORgm`*?1#}#IN02jbFdnoSGuPH z9&2D5jWR5^&1l7|`)agAmFiYq9CBCmvbvTrX4XuVKP9cHyg$y&qZ5~>`8`+{Rhx0{ zxu+^Fvt!8dWnm{CGayJBtaCq>3YfTyji2qt51SryC;@>PSbR<&QhZJ^aPyHYUOGNo zGVC(_Fn?B}@|T*pG?qr?t6-e5Bp6?HNB!2-Vv~~xbprna+TnPDz!(8GX%C4>C&=O4 z#cL*uLauyFaKwmwMp(B>_o520coj ziO?OCo|O)R#?oNst`;C9CN!J>O>(0RmL7KwP5jn84hvl9)@`){UFAUWfX`S;Uy+w@z7~$&zxD%w=!=Hbqi*6--LJ$H!_UN?D=eJ%_!)T)CYxULdf5#x> zl7sjKbqv%%K@yz-79$1E#k{ z0WP9Cx5_;a#{a@g94?vqrq|vbRd4eVAadpC9z69mn)Ye(Xpl{h)Up)9YyKnw4A~(l zNah%N0q6`oBcys+2}Mb>(>eyC%`l<1Hj&dJsxD8u@gQK9o*Rk6m|K~vqnZSlu!9ax zt#A`<1Hp5!+#8Rf2G6?4Ah7mc`*~n0b>0GVO6C26wm^EGxv+>iJLqDaj5$P5@3pT1 z%mV5`Md_6oArwhJr=L~d@LXYZ3p`z=>N~Cjs8KxME_mK+9}6#ZDcnY4oqKHP<~P5m z-_`#>f4^?%cV0~mP%V;vG-BY;OZSQepU=WuBfhA(9pDsW2Ezc*4ltKGr|x6HEAU9% zS5b(8!i7r(JxY~=BrmVUlKpUq^x<)!|NiF>{289EFCG2%%Nu%oUCBHGkQLyS*f9nw z@KH?_1%Tu8rJ^QW2;GFWo4OarHkl$eh7~0OO&B+P%z<7n&QRzx66IAANib>f8n9s? z00N@$OE)XKl*$9yyzBguUo`pIk3?}7I- zr4&{69ND8LeTJx>W)hpr7>4|)4R009NSHrpGDy~Ad%izf@}`J6Y;SmMzv#E0?R@EVr@R@aXS5(`$-IFZeVvbkLu z$WLc+dSZIN=K%bP09z^uTBj}OTqRxV)CJ0&e9yU`nK1zQlY2{n%-9F#-0_Xoulf37 z$1qD`q_z$jggns*b#CHNR>DeS2?1L3F)b-*VeFgaD9pZlP})pU!5YUVYNfvIga)~6 zbU((v|Hv`aW~Jb!&bdh0;H;uyRShy>^vR-4sgj@>94anub~K#LoXpEh6GOgO7k@7t z=&I;qFlOK+tg`Z@HqBK4lDMhKRRfg*1g3)9QH|)0>M_i?dG1u4G!?p!*0hoh%&K~| z%k=;uurvk5q6=DqkP1+xXnvMO!}B4#|7cbgVpgZ^(Ih&OrBpojhjE_DUg_lc>*Z2h zeE?jr(CMOS-v5JH5iw{KkV0DpFR{^uEF3i>i69RdU0iic9pPK4@z z^LKwQqUgVT`v?B)mIL?=2TdG^U%#fSm+$x(7<_!Vr~R*=Xw7TSb#qPqUgXk3+X5rG zMFn8{lHPvt1vM|O=qRR0f%dRnG&)ZZae)WqAxKh$Q@=-(nqDH!N`mg1mKRH5sfg~u zYaa<|05`Jm1Pn^QKxqJP%4)tY5dI>dm067pFwe8DGk^%X4L)O`rD%BJFVJ6wzY{^f zTdlM!H<_V9XH!5DOgkRJy&N+r&eD{c--j$ber03h8?)tiH@MSaRoiHW5)Mite)dL7 z=_vQE3Fa0g5^w(d5rHs-Hw)S4bosVez+94bo?BtZS;IH!3F7olw!6u+F8Uf|EWI%T z6p+PyKluVYNJxY#NH84->4GL2iKwsbDBYK~3`xPStZ*ps($CV{KsQMPEI}7RR1l=c z3VsLu4lB~A^Ot>gO-4Pj-~B;#EJz+;-d2^~_o8~LM3y8KrRBPo?BI_FzAEh__4SH= z&mjAn4{ix6BmzmP&h)1B&?;LD3hoea_eQVm<@|bO@Fr$O7&AxWuWl8nN_10c%?tdQ zm4FCTewI9OFJCR`cHap_4);g|_{BJ3;YO7+Xi}%P@lh3BkY!9Pz=dL?S!ktvdUfc7 zCdKQ`;gZvmJ?0!y)N6vrrq~1}nPZvU1xn>2MnwiogF#eamVB?*ydI&yj87EPtlJv{ zUU7t@aXzHAxD0_aKmCjjB+;65kD5NO^R-yJg%V;DBWh-14L6D>8=xf@r>XFJJgzf8 zGawQoJqtk2iHpnc4+U)@@11d0kE9)|$NCyNO1dKKSpong_}1TOmGZG8wg!2qprfkP zXV9y5?CMNdPk=}M^?GL|ileqE)%6$&j6)6TtRAygI_=j0NFNi0B?z?@rZot>T|Vu}QS$X@S4(qvGsuqL1Zs_7-~|9(*V zrR-Zsj@o3F3y+V6OJc3x*GX0}I(Mw;iy#Vgu9yr)+$|2O*f&;KV~ zT#m<3mu4hzNOG=A@>tzS%ThH}l=Td9lEXNTbpA0PuABb{6(^87u4_3gX}-s7+6W4S zGZ@F?N);Dy#H-rMj1XnRgQtlj2RNTcH9d}epk-+_0U&48(n`cyHH5Vl7O!5*&hf~v z*rOk|ew+zTbb_Y^GEKf-GWOz1Q+MWuIr1At%qJ7Ucr9{Qrp;vy>8fn>aPW!41OI!c z4l7vZK?@VR%$58`>0pm=20ZwKWxbtoL^WWkq2d7o^1Qc@g(Lk6}PCt6k~gaJ7#Biw6q)*^$Q*<&wdg8;RSJ ztO1EmW0@xedjM%Xmpgv_?hfv1{H?1LuIAIG>3Q&Z=v& zaY~7O$YRov79i3_d}O_W!eHEf$ujcH>9nb!1mCqTx}kLSF@zxCAy+@mWWv^IbqBT0 z2pc#8Xy_~;?(dyAe_>;->(PMQavqfAJV+m|8}w#zQh6gSe8_b~neI&cVX;*tR zr94KuWpH}Wf&PI%dwI}K?(lYk(^Vx}oL;Jn65LDQi$;3%B*8R(YjL5AYRM}`6XX6P z^;xf&xiO$7TDPc~VK{}Y8L+Rah3;k8noh*}0uF1(ekb5(Si*NgMm^7rHbz>-9jQM~Yj>J5b6uxV~x zosBgrul;ZU>Z`mrd)w#oY@-d@*H3nWdrxnm9Mftczn?0`GTb*oIXE!z~06~66PtJUi%5SFZypwErE6e-`%^1vSN@>i- zp!@W@f;F8BLTh%C81a@_uiYr3*XN`3vXS%mlzSgZa6&1OFuHlchIk^6Fn1?u@!{1N zLFk`3+d8d=g088QA_EWJsDj>ZXp}BvWdX7uA1&kFwyllF41lBxkyE;=Bp#g}dF{!l zZAy_zu2ceoB&c^%fgdDFh|0ns%7(hq=gFGsMH?4!zN@qmXYz0etR(ww{s+JZQH*e!RjNmDcvrEUW=P1{3(6zR252|@HXHPIzw9SD5 z+~^I^s71FVLrv(ePKl;Vb*TbYfM6Ws#0I6=fA zp3WQs23-w(qETr^0OgDGnjd%iNK1aWC%)2jN^)N&mO&hfBmw5YkxoHW@on?(pCoJ$ zAL9LeQ5BiLd^#S}WW6swugIL|n0?@VjQ85R4+KI<+wEz4spoTdPXrH{3_!F#zt0P% zHa=>{g@TMiltti)CS@)H=>TUZaN?~!J5Qg5Fy_c2pIZpg?K?)Al-}XaL}tzwbPoX1 zGy*vK_$W6^UDf2~9Md^xH;fDB$SB+V z!}K^&gM!VmeU3N?m<^gYWG;(Wm8b#W>Rj;St=K^#C>sL4ZzsrAEGC?`}g$vx3B5?i#2`s{eP$X_kSV3;KjM+ zV`yH}>Sjx;HJ|CHAL-*C{|6m@{E?ai2Xk@50Wxn=>lJCSt2CasMmR(2f{Rav_O#7c`&7i8f-ILqF8kT_=n(iR$Q>l+~hl&p(U=6PQ}uvll{&)T&eee>ZD^uK?6PyUDRXpQ;DK#@m^ zK_!Dr>uI6c#3;7ppiTv^4tGL1vqykeJTH|+lT`{&7naDNxFHy54<>fiic&BqoUUGr zc8U*?!Er0DYbyp4OAl+?J3d`ar09OVWRR;1zK5U>qIsS#9VjlO9%gW|YP_B|EPHXC zWR^vxOUR~gwzHM3^q^pYFRnpDFTn)fUlrNkq}dZqf!QugZxf#HO&_VWQcZI(t>2j< zRbeH04Kd|Zov z;~ofSIRY2@jVOIGm0a&7bQF@&L3pm(G z^0fdqp#Xs;#cwdadZrMeZVug}IbzK_peMj&w-J@@PU(4}Hig;v#F&q%9M7Z+8G+cK zI>$8A7 zb)TOc!Tfv9{iL1I&trZYxAghr-YT!o6fA?R`D@M}Z@H?C7ShFYZhk&-_Wmc)5#{*! z+!z@M@yNop_hO6xc>7ECil|rWzFDVKl+w$O`d5gNBrvY?wex8KNP;<=(8%VevQTtm zhN-xkMY&urZpyeNv1F=(So3yD`8Vy<9VVNaGy0V`f{D&`P-oE0uaTf}i0J>!3um>Q zOr)s@y_hs9s7(mg*}zK%jleD9&tGXHGBoo;=W(D%9A?^Zs}|Nbr64xT9XsQ4np& z_GU#(^lspx`t?@^Nx$4_x|rwM;qf3rHe98IUV;E#XkEhcgSG3}bvOzZf zp{4z|KhuXl{xi|{JPr&-Xm=DR8gBx-I*GRt93n`=yudjvOuIBF)lQ=6O0`2|dJg5% z@-M*3=2`^&kN@p|C4cpr{LL#0O9mxyB>`vxkbpRy&m*FNWU6l2%|BRHt8I=#Ra0tN zB@2OXG>C(i!ELQvU|BoKcp&iZ&7lqz5Qy#3C=uCA9Nqo=s1>PpPX`Xlj~83IzT$CgFX?!HM-Tt{6XW~${N7KzQ0`>xq>##U z8^ISqzTCrdf9tp@64T#`fg&S+85>C|2pvPax;qKzI{_e=A9bY-48d!c&#K|nfZifE zaPsy0PIX8 zodV*rl93YT(YVejQBwxEaR}q0oSrNIh&~mk;&xZ%{HUCY1vc?qzYnQMPOA-N-;vQp z>nS1Zl!Bbr|L0t=#{EdCJ<+8;PUmPLzWA;}yJP#PQl04Jy;&T4avan1=+j5K=K_s$ ze;-A(+MB2dOf$bdQto7)X(Pt1%paT_m#Q(CnXn|v@0q_KC#EW?>TyPwhvv-?@jxX!PHFFrdtFco5RbHP%l zL36?KmXWvqIne;HxDA>O?ew@44TLnAXLLpxgE-DDrQ{yQ!AovU#W++}@sGnO6jye+ z_BRs%UYvK?#a&M`ou z*k^XU4=p*y*d2c5*l&?5I;$1TVh-4AQ=bVh^c&%W8B$M8s`LxX498djal(P?M-I51 zL_Ur=KbFS%DYs|3&_OE!u3)a~Yn0!d7G0q*2@k_rH|K%Y9H_0<3n|xj!=9>zmic15 zm&SQdO-Q*di>kJ|g6MXD8K+V78tiI^%U~`4FXB$Ka`HHsae~HAngEwmpbtEjSMgh_l_61Hp=x>uXwb zupgj17>s&Vp-RFar0%3q88W$>iyMv^TA|e3yu75x`y=h|@9Dq(FaJb8{`wRB^3x9# zjsO##1Up}R{WV>^z2Y_Mk$(BppQ-=LA85(*0Q8aLo`FSN^7&kFtj2)|2X?Q2`vtAv zyr!^P(1DNpvF(I^@4%;DuW5bBf&WTlrrnOu1$DU1MmbLC=G?VnfUrOVH*tdMv_T(u zP?gR_sUGx7VM2CB67A?aA=zpt0dXVODbRkWJtK~7pylNaZMT<<1C}Bz$4A~i>^N?# zggFQ6-*7~>x)a{&g3oKUVqnNfse+a7uea2`e^2gL22B6gA2?9Em8|))QSWz3yhm~N za8eahU)fIEt{?qqDWUELx^Q@{B53mrt+r9Sgc_gY&p=ndBe8z&yCvU z(^V@pa0G_c3c8tvOkn^vR8!mn1VM%Ys6g>`9hQ77dMmGm8HVVS$|k|`4ATF~pG zzRdC=YO(2jlE~|sS{5$3u4rb~$$S^#tOcFo0_DemPOAf|EAjl<3kJG~Wh-cQV6l8O z;RYO{s#VS$N+uF9KR&bTg+@?ykuKt;unen5N4K9k?Wwb4Ao#MT?FC=!%O&j|9*HkC z-#?Xfs~^x*aseR11NZI&p^iDgE*j3VKgdYAT9q6{5FeCji*P z!n}6o^sf=Fue8!7iIjl>P20=4FGQH=q;l6o$uGV1q5^3L7rSd2zrbt8aM)=e&p-u9 z7p(v)C5&e^uXkPEM*-;2{1DA#2L`3RhedCz+BBr`CW4jbf;=XuoWeTWp??qs6PX&{-nfwx z``>AHkqT{O5!g*CB1M2b>BwwglGI2)1<(2O%<1gZg=-8Dq=#17MSk+SSp<9%2}y z3u>3|t(h@RgV0iJAM_li*AoBVtAT~WH8d(ta{7$A+3@QV*m_0G-Yw z1KY}Iz$3Lv!Lu(w-v$WLWT9p+Y~<3Gkfjy3PUucLLPsKi(HL*1I=Nqdr^SL7TfUl@rN7TFtY>myBfTyvN z=xEG|dRtzmk2bHM!70XnK2AtMB3Xq#ZivnGifYwq!TV)BE)t|cPzoNzy4BkPH%DdKVkN4BxPu|vSfL+>G$fF!3+P@0Y2z=rX8A^i z+B(5`GxnXj-1tszOpHe#4zyS`ve54jpM=l7S~m3X_(>L?cmL%dsf|av`}7wE5+78J zv)<5R`^l8ylk!M69^7gGIzTh)O>-XpT# zOQpuaIjGqv_(1ai;TFNzBOl{ZS8_N#ZP(;Bm2^Mw_oS2e+CDIYcW#r(j{E7N#Z_at~tOg(1?IahF&5I{#^xW*jFzavG0XR zLc`;XiU@Qm;OT-ob=dR!SLoEv%M*I4U>-GIiZ#f@0}ROVgX>SlrfJmxpBBBK&Tc8Q zsg}OFs%XZoNz0mT+Lh_cG`k{lC{ai*isEs%8Y=JEM9S9)vOgg@t08>D$ zzX3tI2S=)~d`1p7r*33p536&*mp)fpMbs6%cZt8E0>jKUi^X`jG2oBZ#7|3AN--=c zEO44UjUMb80c2Hf0@%{1SXxByucWz&nP9H_htmLQ4BUz)i57%AZzK^ir;mL0UiN*L zl_TX(F^(B2m=jUb&ZY#ek6C=LYeq_N^y-3ml6h9`&IqtW)&~j4!CRHjDxNM|756q* zhCG}~(Mtfci0fRmAyvUSVjLe55R6$s9>pYl)Evz&fn)l?}1TLIE#5U zzH>ZIabfZrAD#Z_^&Pbhrv?_OJwnp1o%_l3$4Ql?_?9Y6Ka;GAYjJJX5ZV1&zD^RC zKICLTd7fjzFmvDXV|K#>Mb2DaomHUc>r2cO)xj#nYJ{MDz;RD#tAP^kjk$-I^YLWb zL6tw)7a-AZ5|gO3cZ45bZX-`#%PP~pn}!Jr$nQ!)Z-zF`-5pxoS|-C zSODjN91o@{jwuYI=tn1uf*l0HvdmhLsexvYn^!i%A_b7_ES1J(g96?(XjTyShuTKh z^dH8_PGvyx*OrWf69H($6a3H}gx@ZcIwTs5HmsL*r~&Ffkdz(Ig^5P`fjRtxHi z(SSbF@1^TDCVv0$NEffZpqFpn(Z`>^rHA+53DwItFKBxK$E&}m&Ehrf-~UASfA|v( zzueQs;)=(3Oa0*F#_MIQD|+<>f6luvDQq|Nz(MbkPjSy6NHiM^EY|CWHtHZuM-CXf z$Gv8+))m^DP{qOE;&LIjwc-baSPwGx@|u;3oTZlz1eObRIr8H2rbmvAuJd|- zeWF5e{i&2a`i(%9kpU5_k4t% z?UCoxL8x%cpq;}H4CIdc1Kl$KzW(BZTE2z>+9H14@s8(StJTZ}kNb;5|UY+-(E4S16I9Tu{y>YyCu@@>@FW`V| zgLmQ^w-dX@Dph}F1FMCC>1vHyds)0Y&GhSNlR{BB2z9*aJDpYHJ~F7#mX8Y+$^lhM zSPe@c)C(m7Nfb1}jOH?^PH|DeM+!0^$oG|PJW)A2PMd%>e7=XlT(F{cbM{%_9_*S~ zPQ`+6XW2H`JIXzq;uAXe<40w{St?3$EK2|O1)b_##xoQFPRLU6X!BLp>*x(ocuSxu zpd6`QMu|vUh>4vOy2xOO+{yF4q<&>KnN?Y2KT}K8L}JoPf6VWz{AeDa6qd+a!BGK- ze2KcRX;Q$N&CW{(^ASnO)*Q0Te##8>$rUhXHKJTAN=XtIUEW7SOckh<2n?o02^Ko^ z`4cDCim0$CQlvd3Ec2)h1=OlfjtUgDValJ($gkKCL0N!Uts=cyg4~Rilr?1{xm0LV8U~`V zrdmk$Qds?oIsp^d;FtA6yvT*Ng{(L% zaa(le-q73EZ|Kv<_w@5m-{DDGtZM$fq8BfILl;+XIk;}={U829)xA1A)m=qLMht@p z+M%%tbou4qa*+3qLBs{^kkRKa=o>@3$oO+mzP*-ad;_xsMx?}cf)@~ zbGJH>7Kc=?g6rKK?52z8L7~BIx^}6EhAbH7Vc&K9`hz5S;3BkGaM1q9-vO2i2ao%E zFRn@p_|L;hgsyK2Zm17zb@m9ER4SF&L0l=i{w5TiWnJz5Mb^`r)Uw zIHLW-Km8-EmxE-3kxbmUrzGavSGME-P9g`h7O3q z(H0e;26#%c^}xYBe^2|7=Lwpe?D?419Q3Z7Qo1BJuoM@kT0%2u}&7L`NQMT@}KPQ~83G3`GzP>tr#xg#E;Pj2d(%Z=~VIh)Nt_ALJ%J{^i=TSEE`U$4*>qNcn5BDN1?iv6qVl3D2{A^NB>FgL2KkErr-3jB_0 zDSHwOCXI}Xd989erf^p9(&wZrj~jB}9ZX9!28&}xS{pk0+-zAjeZF{23NDKvE?1#a z!(^Y|t7Fq;XT)@Fu8e;yU_Ms~L1F;Cq=K1x1hdZ$G*&7k#>libO^~`oLz6UJr`Ker zO(`2VhgbydMK;&v`CG*Ch2FP(-kDz4r3!ea=$SSl7X5p&4edPO9ie&p_q=b&e7?q% zxt|?ho=0&WwYo9UUNpLN8Hgt_zpfgwG?$ouid{cHUQZgYvA(9#3g=jFrIdh5wT#?H zBsBweMsJnlR1IamW`nI`Hu&Dop|X3!nd6;LlrY;1GB~#jR#s55HZLb^65}bYnreFB zQXCOY8@aIGtznLI#v5Lw+tNz;{{52XDBohdGqjjkkTgXZIMiuAYalsx|}6r zlt<`gkil*D5^yi&f_S5HbnQ+9G(+-&p`13O!}}M_(p)$O3&gzKbUtxE!*~;`Jfq+u zlOjZK2N&$PB)cwsCu#u!sad6fjX~cd$00+dM5@si&}bW#j)OlZ%`Esh8?pS9 z$&)&x%EU?;6%KUkjQ|#mHQcXYD=b}*F;6p9 zeEhIoM0H@hU5TwOj{DtLU(=f5=Z}B-Gj$9?T)m~LxnQvHj&5FjB>~@$fBKg0|MD|! zLoL_1YthNPmQLk}?Z5VI~1rHPmrnxxd><0D66SMK}D1MbBe#f1v&CK|n^>spTp1(2e-V_te58{o;y2 z%|HkAmf>SR@_S$W<}C+ye@8d|Beg&O3$?c&==T1e?jP=yde!jQK=chmV;-| zik5YwT6y&Scnoy>v=e}g3^e*tYy`xSR58{(KD&-VAA?W&%MTnRzoPZ^hPKNEwG5O| z8LW;T(}h0V_jGx2LpNXXdct%54o}|x!r;scU`K$Ps6>>44pJcE^T`ZSy&7b*sI}9i ztT(l6aM++Edo2rzx>QN<>s50X-9a|8A*f3l)&TSg(zXV@Rf;j^J8@al1$`;O#saqB zmF6;`kLr2;RY9v&5!E-T)*j3%d@zb)wDm5E)+QxDQlqJKnX(&UsH@b`z$u zMXow~%g{NOxL{)yO7^nkeVyK4&r>UjDbRFK|H5!rROJ~MU;scr}Df-2+gd=a3B6vU0dB=>QE8H_WxJ}WO}y=XN0qpahdxd<7c$bG%k zH7-a`kP(2Wuss>vC{0wy%~><>qJgn<*;z~8dqyuHpeoJBipID}{-IX>(HI@s@F9)> zq73ZKZCC#;#|byOrl59`R$eXc(c@3%K_eZ=YMGL;jt*>uuDD>DQmWqvP%O!i#cOFF6Lirp5M^h>$;i_YM8>hkv2!v6XD> z@qk8Y9DsxB1;oRzyZ+7J({TNYcFl^q3eHxJj(9VJh1GgZ*Efwc>bt)?aL@>6G6qJQ zMmlIiD^g!D2xvOdFZhLusv!$Ol6Bt>3;>S82LgS{uf0@nKs)P$qIm!-XadAps*h4( zx@5$&_7xho0wH zLz~rtUM{z^fjbcgT@U=>zkKumkpK8^w4s9_b?F%*sI(W6Z@cScp~yWy3RjgR3Jeae zM;suAmg-@lfyn`uxeN%~dy4lTdEQ(IP-vW56Z2q61q6G`cYpkYipWu+;d5W|wOGU9 zYpV-ox971xwmgRp6z&)xaunZg`27q*Dh44N24t@Dq7~^eCHH*nizpPVx*xm6Tk=)I z$=U!nPNyqM)5)>UD3Dlq#H}kTy(iI+)y7(b2f2^Lxy38r6!X9W1rd6~<;pLVY6L3W zEuYKBJq4bZu%*RvP&X>f#{EhEKV@&$V_9~khpl~vJKu=N%*dhUVzEhf(=DqF0X78v z06*D)U-af5>3%U_8#dGsEJ$d(sg^ku$zm0&va)iFjOmVN*k0ea*52ntR*_N%k<7}> zh-4@;DW4WI(VbkxKxbOgYTizf+VNy~hs5OpVV?2yD z`Y63T*mMP6GM%jzl6u301q>vqJ0?(w!$<2Gk~-(k%6NY$x#{~i`>pQ5o(7g=$svXX zSGIDe&W?v!pA&~HeO@HeYI=?XUYRgCu|%-%Y-)pvi{*M1ufKEiHWLd=9o%s@IQ?FX z{@bQSr@pH{By zVyaq+=TuY1m;M`KvZv7#3npQmjL7r7%jKp&2bUQg6>71#Q-J;O*N`x=fGX1DMlyjv zD;JHvQt^=zwe)vcnX+(s?$Bi)ky6541i|QcyQj8(hVE%?1p}IZovqQt7fUi0MK0tD zYsB=Ps5yU!#PjS45^`d05T0^ao6(GCStEF%C-mrQGm4`0Zln3A_L8L666Dd~UmWY+ znU+W#3R25SONSGVinD0l8Ou`#12;2A984oq7u=+n2az4)&KwLaV4KAt@EPAHS%ob% z1j6WdLe$Y<#Cg&=q=!tf=y1=D#hv;744wKub*$OaI(WmWb|Bw)ct!=&URf=DRiZS@-5EFYxAm#5b(t5M& z4tL@~Dwc;y()e>lS7pmFnYTL`b-wet--$DK{%oUbf9|Om40%iRVOT&0{W9~~9}=Oc z0*zd3gvx3h5{_v!&MwWk04ca3`_Te`nMrgOd9kkBO|7>EM25;LS}-yL7A? z3XtBa1r0{M5on@0k&=JG&Z*r<{P6&e#PMhwCA#9q2sZXTW{&^Pk!s&K?8-hD^|FhJ zxsGc>*c^?BN@>=nF;YBEWRgU!+AKz!#NwMRB&rO+W)uWtjRY+N9u7L{<=R#WE;EpT zc{Cu4?8Z0kPCx36zSouz4O=jksk~@m6S`X39h9%&dvc|Tj}|G_jz7z8EDI@3gw|_; z(#`JnAWQx4d#kD3zI`RHzWIZc?ImG5)8!*A2p(&)xsqq!d@XN2|1~fwni#LOs6Y;b zq6nWGr1LYGeDI-!`;X*yI@g4!CS<88ZGB8M0Y)KE>9_ARQEWH2v|RzzfFPHpiB#Z1 zXBq2kcMYQZt<2hMT|zkccKYWVgASnUUe|)&_7R0BI(d5S0p2tuBHIBw*PmNL$w}AY z;SlvRZ1wwYB_4FoXkoY8>if;7{3Y|6OU9OXBdvaasfoN`64E(AcIpj=(o~WlL0o3( zNIOJbCxE}|A`yv)gc3zw)g}9;FqmLP(}*u?D@4f!nd$yI6k0rM(tgoM_ja#KP)lzu zu4|W2jfWr`dhxi?r>@gVAJ3AmgcI3bYJwifJf{?K)PlULbX}GP;{-(UsF85BoJ+ia zPoBS-Nw;}LI2}~}81(6j((<_k6!@)iDT-hi*uI^Z^C4BK7WDdI0n)frFRrgMs1%Jb zyPhUo95Z9@H<1&NvY*pNEI39zRxVFkSh9oS7>lK7N>h4+4-py=d%ZW9dTG&)M~1zK zADc}oR||}UOAz+LV#vCqU2n-pbgz|sNEazN_T-QXY?V2U>pkz>e}`+8wN>D?F*(Z5 za}0lYC!x-Uvv(m8?;hA=I7&A73W;PLN6C?QStW@c4DT}>e9=3IVe~zTJXtw3w=@zx z{*3L3X=5037-c`ZM*!%n%{@=-X(q)WUC^#3$5Cr1Mcc1T^9ib+!(I;tsaXu)n z2ThV-N>4-bk{~28r%RBpZha!kxK@_A!O6WnR#T#KRV9hx!kG%8tM+q9yf6V|0Q2{p zOs7_e^x_WVrleU?{vKD*GH%C2q))EdsgP?8eu%YC1cH~IHl@J*IhsK(a1Fl1&7?SH z(@quzg%wuD@$d!?`B?h%(InhWTqWcVv?Yn7k~W`}p@KRWYB2 zq(UJ1u>6pZh`q+}%*Macb@rXT{!pl;>E{UkIldOZFBCmM+`}{DFx7Z{Hr?vK_cM27 zjl=MaaxCcf?-T~(Y0|suWaHn{gn0CmL1ch$8sE+oGmoZ_NywfIHh+<}1zuGb(Xp*A z;nurW{OAA)X>?$7FCSyKKF0Ego7D|cY25fvC&QL5zd6G=HS9}U*r}?sJ7k7v>|zK5 zEER+xQ;CEW&?w?ZTgQ~Tetib3+coC(8=Su~ns6H-vv;+GkfByWr*J@JqL@rEl8ytD zc)Nqq@Xe{R^8jg|Gm&m=gCRIks6(t6;-LYfy_kxnG}522C^2c-V3U#_WaFK+k7II3 z2SjV7f#*yE%R&zQ!M-nOV%lqxB}R}(QD>w8Gb<}5fpCobCns`mxs)$||D_fNSDLgR zrJkP1$>~FxoIIAfUfUm^J{5WTwM-WGB%t=uWM@*$G~sXf+Vy)+ucO+BU2 zAUjha+m}YfhV8}fS`(z(t-&<#7tTE>m*5&`G7J}1Ej$9?KDDik_Gr?MTv~wRK^B+Y zTjM6MVcSJw{~Ij`DlLHEwhYHj3WVLXa?rw}zX9g!AdjXCY4sXr%|>>YH}d9>Ur{>s z{{079B(3GTfNS}L-RJdcCac8*y{3|rsY8o`<3?)zT+Pi}I<*(gjhyPeEY42lkJBlq zRj4s>uyuX%Ht@6xDsB5M*F;JFPGuc1!jVcn+X4%SqOOVMY!7>m{ISjanysyQQ7xU2f|Y7dMVSHey;gK z8mOCXE4e*vO+r?$qPf1-zn@Ee+RGG<@0d^_`9}e=*8}^YyL1s~)(99*=~&iSn~QTP z1H932?MW5Ojzbhx7V%sVVbmGo9;^pI4ONI)lo^ris-j zujJ&(M{<4jN?%h8?fn%YUCCXZBl{w^n2oc8E<6*C)(C;RM=J6nEE#Kvb2UXL#G@{l zS4P*j9;6cnHady0^@&Ne*9%&};#X%xnIihc?^rYBwp5{Nt)OOTffb=b|~?P9_T~df~HnbTtkcT51YMqq)7j zlT2`M*=MF|S_z5IkUK@L(ltOBTsVb^MwP$UiVsVQQ%p{Y-jMkEefNWwkT*Z{i)fR{ z5}YsR{k8qL$Jpneg)$in7vM!>dLPGx_r4E$E8>c1@RGt0_K-Wa_?ue9r!D4RGQd?N zbwlqYM0a66mK#_iXU}Vx8n7)>R(axK30UiAQOM8^D$@BRER#rGR@oAYG1**3zbC@} zn0Hc}f*oLlp&lkcNc17$jNgM9Vww@}l!bX9R0`{L%E@F*J{v5@?LI+~icl(7_~Lb= zA;7|^wipm055M>13+sDnTM5R&Anfy5;C?R&`|dOW8=Sw#Nu=`!Ak7^i3NvAm5gamO z&`ixfaQ5QvL%k#U93j?qZ7x9Yvn)t)KLD8u;^%*7!VtYBw8`W-j3GCjk(38rHW%gK z=kL8CFch9OmIJS>{mkmR-8Ns{iS+%O-xPu%<- z1z#WHQ^D~X88Xw(pwrQs%RB@73D<{ls0!N?!OU;RJgvL@iZtEy30cZN0U?V6e9H`pJRoN7vZeIfR@L#jhmpj5R?lMs)e}3^LGTlT6>&Xm)xLp1;B< z*6># zJ*Rjrij~$6D||ndTB7+f&F;hwj4~QeqY}eMw~YoGn0j@C+i6Lc za#OM4L*{tQaJP6ZzD}hGb= z55Yl`%3^X~U-wj+ur_E^ywvMJ5YYl8-m;ry?c<3hFq+K6m@%~AB~0YwCm+aHU;IHf z&!5U#3y2Ox_VT`*o@!#IiS>8C{;Waw&oVzdkwTNm0QgFaA|cAv zvn#0%Q6AI_ndzFEX#sQn`h{G*c_kgp=Dz+$uJ;~D zeReMEd+*D9{YbjWsq8dp;4?s>=w{!`1}@u>=G9-b^|?$>qwMxKa;t^eL=ylsK^k3i z?GBumnHDuOLi9jeYP5i8wns|chEshm=d~4@;AeD4x`bON+wj{l!54ZX>P_m>{1sbE zoEhIrgInP+>l)MHO=fK1neZM?ov=>t$i^E(m=v@u&Sv_)@QAtAJrWj$K{Bagg#^Ci zzd?oV2pC8`;qy6QZ9!peRqFad&8`6uz9ZdCcKX>briGlGe<;htLAF;r>0atv>UB?a z&29S)4f{^?wc2AZ+vdn5-{9+3L?G!Xv0wYr4t@C9L?dtag(dI>if|CVdrJgU=g*2X zecs(09`;Zon^gDozt=2qx^SgGccp*6q5 zNnGi*Om+E99X<#(ksX_5Jvj#@3xG1L^cEf2WFxV+Ur1e_XzU5}y@E;*JN?y~XBzlz z2p-dV&gVJ{M{=LwXMh}fv;U4c0k5&t?~(hue<#uuH`2i43VbUj;tyo1u`<>-Ou$+; zEh5*`@v!B3o-P(Vzso|Ok=_@qSv;qso(V7puJrtx6gFvG%u;Op4QVP z*AN6mY)wKszoe?=?d=7jzkp27rYrrmSyRS3PO|c-7cUsCp zn&XCX9#C!+v{1oB;f_XG+wA#$2=Zk$tbKe|8qs3nt2t6vYv(oGRPffj&%TInnh;S8naum^Z~(eV*V9 z$9;yv+GnYTBDJu4g6lRRu zI>I5BsA1%yVxuvFDZSeEG3Q<0jNHYA-2n?q;)nDWT6q{!l_3O|P31?)-y597Vq`O` zsHj_v_wB4h!h_0IB=Lg@rUBRUp5yVFSnWcS#I7izY;HFXB`?w87PM5}?PR@gJ7Nkml{x^Rk&%S&nFP}b> zf^O#e-IE7${@zdIY`&JKUwtiazkVtKBzQn9@Uj{pZ#O&LmJ^wty(i1_kEEO5lOs&d z0Pz5bPlHUQ2gb?CLW6dY+g+5K?Z%37z@sJ=`5i*#CFIe1ZFAy7*c9^IG_MN~<^kzI zg5KU9HR)S05M8{ul2$kH>T72hkWO^KPPrRV6DeUb@R`xq9`D z6q~owe)pAJ{o%JFuV2xdW2Jlh?U(e{_i_U>MGb_vT3GD0;NpR%_jXnHvY6^2 zqlZb{d?$yCujT2*Q)w=rYXR~?+MDn60P+c6v;y|736VWpVVB&yTZtTqe`WIKeiFf; zStM)WgHd05!%iR+(dslF@68uP8eLm^J&@l{WLK}`da~9;{9Gm{@9Q)ASQF__Ej97hLJO|-yPf90dpT_NK-sUPSk1M-*Fy&osJbQ+ zp}mD1tp?vli}SS>wDSe|J2X7Ry7R%Kakkwf!5e)MFVNc#kx`T}VTB>iM2Bz%tK;}u z6J0;ua;Dd)!Cu!fct3<%VE2^PC4|2T8U`g5!U}Sc4v^cO>t3GEC~VMa@&aYDljW&Q z=Ou~U+l?Nsa8%bdcca0-hxz3CzAPTRFWZ|N>328QP$&&X(K{x)aQ~fTw8w69G~-1U zm{rT4F+U=QQzb$w4!+WxKD`k@krb9pFgqGt*1d5@+NLs|1w$#t$zYLGB=Bq%_V&rD1DF4o$Tf)RE;O%pt6 zD3c0|IH5Os@eyl}<^8}lU`(v@I?q#g!p{zzIuy}VVK{Xu3U^))EcncS#8d_$8=cjH zqD9}HUP^_j*2hYcQk(enn+BhKZbCX#W;n0R-DH@8L{BnsEzuatKG~`6z%8QlwRiyg zxkx{w!ikyqyv-Ok=I2j3JNkiKnjstP`kIJ?>HnAJK?ANLz8Ab46d|}De(v%7p{#O> zIi=l~XcGoZPSNP<`simS*2u*5Zz?KI6{CB>IOi}ki78{Ktkd5E`ZU)h$|e_BU>%FU zf~rqk3&oVbtSh|ZXXqm!MKdkr3!5agCSnoLF-IW)xGxf#V!_{(pj)G^{B7PvIRTa(A5Q92B{17X-9?_|9!R4H@Eon)>kx49y z8&fu{sp3s!2B5+P_?rirYEg$Iw(IP*ILoLiduG*KUw13X#e?tTi5a;u;Ak-SsrXvG zlk4$%5TZe27VpD(hTbzyL-2G;H;BW1N5ZT3q}BHaKL=eU{Cm%-%)!nj7Lya3obwqZ zzD_ciZL{D`>}&EcQ%ov@!O8&N7nhPYR92M<`Z;txtJxZW`r` zC!Z5ZFoHjwW*6^#4K|J$Zk2F!ar|;W{N>&i`JF=!&Gvin^G*iw34?3chwYOZ6b@vN z`6Oij4-%F*qVR)0q-0&JHG^so9Zoh6Ve~h1IZqoektj~CMqz)36lxkxhv-F;9iSl- zF>O2;ohU|$zs_BllZ%w3&uoTV`B4WeFzjL4$P=#Al=Cghyxs3_N zk;FmS(mbq}Br1$fR#~p~drtJVfms5f6p8AV$tpJ-Cn$D;(!30(Xo6?k(=g z7r**@X|A+5m==2PD!F(6LwWGzQwcYFx%}df5?@?MwY*2)4OYh>glmu&P0CiE{7C9Y zA8YQrX2%-cOF-?gR~L)9tWRt1v$x=102TxMdD%%dp9mUQgvry{y^zUtrU|Ykp?f_9 z(D^|TNMj@0rGzXua+-k7b&-oCtU3z`-a3j;Wlj~Q% zlgrC5WPkC6#I3#ter;aBfsw%-J{9O<7^X8}Z!MWK?C*g4<(ih>agl|6$kIrVNuRzS zNiX87jlECL1_hXw-Oqyh^V8x~3x*s0yI1-a-^yX~m9)=)D~GcWq+C6e^}|nPdGb(- z<$c*{u-!CTY;1ZVGHNlCMhmQ3pU+eS>~6E=eQ36Nn5-Aloh>w()`NEe=v=AmNZsbgoVJ(z}4c?4Z( zOiaz$QIc>x`6caDkqmvvQayIRZVPBr|f*(A8_G16pL57dA-(#+06b22Ps_ z)+feUvF`{Kq=^eAD7@8KI^2=;dF-Azd+#tdd^z4x_wn`GSxekRFX%fG#kGPt892Dn z982!PAPr2Ek+c(blipi07cN83S)lltfX;q~64~EVflX|B))#&5$lK3avDf#5k`Vhz zPBPC8sS)9x$7+!d&EBVSonzLMx|NamO^3fQzFtgNXHVKfpD>9wz3@{bt0@NmtS&*> z`DIX4Xj9XkF<>KjZMT5dZ| zL3tclx0$l}!On90qM!xNRCJet;wT|^uQ3jSEDnXi8pgDqXG?@s_muY!O&CrnDWHS* z>Ue#~J4~sqbqQ8nI>a*?o}?`d4_t)|8}#on>3Zki`QHnr>&)TkOM;o<`!;ME`t_O&T>N zhQ@?7u@XmWQ2n#l`96;;{J?)_Zj9WO&>sKnKxpqRMoFJV%tD5E-Oc%3vtgt*HsS|` z(Pwsk%s3t0w6nY?}MH zby5%D7ayj^K=M*y0R$VdY3&V+^oH-6AYAC?Xt{Yq-4XIcvQ*b*d}ile=#X4L z*_o>t%(=1IfdCX|?~pAw+{wDe!y(SkjZSBhKE!L3rgYUiA>By#(GNe#uoc?{6$3_9 zM5=B zKFtFX$};)}*H@bG(t;ufEU%E*Et&**_tbH|eV>ZT&cp?R zcdVV{Nf?J4G!<_2gRyVI^%9L(nQdJ>yw!J_%M8;t5ND5<(p)^3-Q}11d{(l1{-Mkt zd@QR+KbG0O5A?p@BZO^#b(EW{URo_07weU*<||ofF|&(%lJUEngKRX}mQ&qVEvABV zP7`3lC>yx8>(%R}*Z2s_-ipa!1qji&9lW&PqMZ&*oZW9BJU%={g0kW?tHO`q*mm1Uwn!Vb^+3Rx_EN)mXloTTOMx%%#@_ zde8zCN@z0{B2&4J^zUZEu+!qJn=JHR-Iv9a_vGgKxyZ$>ZmR>IA7rdcheI?lsmYSc zg+uWSA1rQ+T2`K%dU3(-b7fMtXo?hm0-#tyVS$l4RLe{p56}Hnl6r~s`a$6PBk4Uu z?n+0D+0i*CPX1^IJ&K^@SyT!;yiMc6lVMP<84fTjj>W||n5>2}H;=}=#B{hd(O|0) zyf(m-(xFy(q9dhGiOq}^&6A><(x;{Y#Ea`%B>QayYvQD#Snwph_cdeq^}&n5nusH1 zD_3A+G2uqHOq~6*jcR*;U$MhKomJxJllUPWTvAt(GrYK-zT@7#wHFi5gfCjYb9VO5 zjV!2=$GuS4S|D*hD-=2Od2GBho|=b5%5`{ix;`ZENYs$T2P@2t%Wg$Q=&bml-$jD` zCH1LvPm&@~;nR-jYLKr9MDc>G(U*56fN%tU4ZZq8J9mT*q`%c2>b;tgCk|)!WxzVF*%$&I-xFGMm zu8d;T-R9Ik5;NIq;+EixGAcz08h7$Y{r)JK5zKy`C% z_5|fJ&1+i_fHMFhg`aIPW_I&HE3$oq6e$wgzlGYR-P{lkV_p6p$<8pmIyOFFO~B!U zk5U-MEvaB7a!!$HTqE8KH+khJW@&^jOm3(UW5GB2VVndj7)E`=kz9}D9B`htbgZOL zGWfu;nHKteEBby!cA2jAns12Fw1YB@J3E6VAed@kLO0^k|W46@<`sG`FuWOl4=dzm2WR5dYi|buSbO>L&)=8zY9cRQel9OxKGz~@Ew|sT zUz?7vCiH;0)g{K^M<-R+bhr+Mi3xNu0W(YihWK@=jyTB<3u3Dk>kENDl^$;0>%xN5-lI#cRFfj{F^aiPzCA+3I<>ldHvJ^7U^ zAOBSDeehq&+5JzXuTJDjpWjsR5%IRz+*SA`P!MDZn-(Zfz7q4z;%XA28SZL+_iWj%$U>J;SY7Gp3dWyC*!W& z<4Qj;-Gt0B?oXtQZfEk+XpS7*;k&c$wqfPHvZZ9{ibH za#C$@5g407y(>*UQljaos9_SqYb#7`F{UCvU0YJ6GIgoaRjWcee?q)dY?*wwLm)#s zGtwF8i31ZrYkIl*K*p!1_Y>#a^nM8E{|>2eN%yc%y||P;W%$Af=|wqRBTc7HrYHC5 zpbwU`_i1*+#4TEK%Ma0Em za!%s05z};v@|AY>@qJ3~Do5*IBRxZwL#Aqx)0BuwN5 zdWv6WC@6k!t(ah3EX)wMa6cDZGdU5#R7?%F*t1|BlH2~B#5mF;gW;rd4q2ZJ`%2@_ zy6}T}XEerBip?l*ZT))+fA09V#tXRUThY)mR8_b6VNS3!XSo>Ue%avWp0xL(utZj& z9TyPdd$=8nfaLcvO5#l|u#+SYJ~jXyRH%w~u4()%d@A#9ULKR@)EFB3j+}KECcP<_ zx5;;Ee%R+vQkgl0Jx#t*;VtKpFaId`S9bv)MQ5!t{2a=dbncX1`!>J&{Xg7_JFCwJy||_UuKUUOS@dqB##Xj z4cx_4liia_CM)ZB-);|b+#P9jSI?%JoF1iE7M!BA6AidC4Q_Mm9GOR2%Z@LCOeN;& zKod3a4UpV!G>CwdHJ{1ZY9$L8`@MZD7vDXT{pA%#E%KLt`PWh(qW<|p-hTUyTz&VI z?7sPf$g8jPXJ6}uUCZMS&g9|wL|^ktzWMT7xw*Zh^kJdb)nENiHqVz*T~6iIvv1@U zg$WYQ?WNw!t;}iy2TY}d2PiV(B}cQnO~+)4AvzhDCAAYV7(xNuGCIG76((jdVXb2w2Pv^?jL~Ka|~DT}N+T!|2ARHG%7a$&pLgX0gB&GYJDV&W|v0 zu*8;sE}R^Rr>gr8lE^5&xpztCwk9T_IALva7-7om>mbF9NeSe+*+H}kE0bDqAy8=a zwNEQrD*&DQfI}V6prw3Z>e%^(8@47NFG)_kAF^k|QYZYJyRoB?h;_kuL6WBbd&LG! zVS*+_^jH|U7g|mNOoRi!vvV(PCY4(DT;y)w_$#|)yNqp&N%1H6y|7q5r~r9uEDW8> zJB3bu{kvV>1Vy`hoW;>=_*5cVGVNl!*?pLO?=<=kDZ!G_dkkIJloSQq6dAtq?zwCT zfW#*nx~MVwbiXjQy;wSFG+IH+)(B!r5%US0lI%Oq+L)YkZyAD)MrjmF@K_|~Un1^% zk_s_)x+_cif_K%SOau`G7D>Sk_jJ!f9Hw`bN}TN-)g?_J09rt$zrcvatrrb;9)gq6 zbVj~qG96s$(v1b{%A!k!SkBg(k%5u;Qs^%lypmii|JmS30h;^jwbymc0+2pqP3sN7 zmeX7NH|wet+6|)?O9$WSKW?A#zc%o%tg&6KDnlOy9wN1r3$U>4YkRWR=_|Tb}Q>qWGG277h ztSGAt0VKSxH<{L?{>LOdO~2SDYI1QG+-$W-3WuTa!X)N3K5U&~YLJs-m+#HWY-MCF zWIREOKc+TS=kKr4M+6j6Tyi z|F-y&3XdUa9mC@8$do%oYxwyzW%UX3$a2EgK)mzb|J0hH%5R?7)zN?VE=|0fK7a2k zNFrrh)sr02LkgjBxDmt8*oQ$Ep&T7JLqN74w4%lFb4j;ZY?CqV>67ktT5Mss-lFtz zqIVvX|41+e9wOGEG!QE9S_Z1clpq(tUj*c|c93HWE{_+SgkwZWaUJ*4I*QQ>j|zr@ zVrp2n0o;8(Iq{|iRanOa1q)*wFw{ue2uSq;1SBbNKk5^j(*bMWf=CCIgLq^&2F(sk zLRfK&jXArhpF=aYk3alKy8TgJe)pCBc`Lj9PO7s{!-h#7hn7*lEP!N zlV*D@WrHB2$!z&RrcZt<%g0Y7&K7c@YD!OBa8IZ6nXJwVEod~?zis5uG?YaJW}oJG z(^3l${Y+YX&{cb3T~WYlyM6S;vGTpBg$&hq^uXC_K>`1e9Z1AWDveAK@V9%}J=5aj z%P%!i+{xpGRzAP}jRotsFA2HYy?!ck{T(V5k!35NeE3+C=_s37kd7tEF6^uc?qWu_Q^umW1R$IH46En1poE6fio0|I6NC41oRN zI*vYqw=Un|_=>7&(-JCBy|mw5%H@kMw+GGF{)(=c#2@qsjZGp-2Eag(V<9Fq0J5wlBT^6I@}= zD~&Y0C8xRrl&`aWP!3(1=$%~hIZ`pw+3S$21^3I&lC=^%mi1iMT`Uq3m^p#PYqV79qIXb2)&>j!vDP{9D}vkR)C_d|#K+g*4Bf>-xCmy@s48 zV4YJf!Vl4>uPFu=34S4#6zYAc98N;AYVY4jWxa#+dwng8k{Wy7Wg2}m9HR5Ov-Q(0 z3}&J0Ekcp2D26x95S^0F;CWT9Os>6aEl=U?L#K!Q-iE)eas*8xflAx z6EvCT0cY*!TknZa=`fk}XFo5^FCiux$?z-_WFtgBXA?Hwy4vX;Bm%h=VZ9M`OD{J1 zRQLo}rSs&@VHn2!i1~g|#HHx{>~)#oJjr#LS2}2V_t~3>M%1-)+aOI_=_#0UkYtP( z>9180MpH167DDnms92F$ZOI-R10OwJ#8 z(ca$2d?OD0-mX2cSfha6(R!jSq1qjr1LP(K-E){Kde<7o2UPvoz@kzSjFgQZ!LE9V zB!9#AJM3FdEHG#R|IyIg-jUa9E8Ge|9HC)oq2!R%&~FM;#!eG)aApY6(m2(z5ZBLC z9C%%A?;IQKN6NA8Db#`cSAaZU41P7%^fAd~@kTH1Cl#qAAukL<8v4ORwf89+P$Gnq z;rT#ui3xe)2(?Dwj?S(1qA|gfvX@GNzHud{SY@^fl3;}TJ3hCCpMtN;pM?N`SZqla z2U(WdbF0KhNnQFoIHII9$IWu|-?1)_e!cej@$3PMrwSGe=g1;BQc10KsG2Eb*(Awc z(_njrae`z#)#yE+O=gP@jf|=I8jwecW6=}+5L{I<2Q)Oo z_-DsrO*wfVy?*Dj@}Xhz?)&B6liJlg1ycS1{`I{H$ekDYFZc@Xz&c3qN~&Fk3s2*6 z|Ng|_XV`a62M=iRf+Vr(z1o+gEZ~z(8_D$~X3`uiSBZmZlgT!hz7P#-n?AdJuT|02 z%se1?cvlrWpRuz*0a%J8Zc1Siz+*{fs;?wMc^vLr8b8K#NG9UCOS0OC*$bM|@3p(m zcfE}YCFvk`2p(tTe{kayr@6P$XX&2}odEv*!60rl)vCEUK6v!L{NXphppVIZ55Wcb8`*S^NMlh&;Y|9osc(W z@I&XVWb%f|hX&r8EhSgi_m^@q*Vo(J%IhzFC%dn|k>znO=bEgZ9JliOfB)~~!O4;` zvd0T8Joc~j2Ha{Q+RKy2OPNj^`RdEhW%K$wDse5AGcCe4Jh)cNd$NH++xC)OoucZj zbEgS+Q8rB08gE9{gutw{7@6wNAVryLQh!RKaOv9jgxtBwB$7n{{J88w<*GX&ug})^ zf~mDt&PN*75R<9`a|vwJ`N1TtAYw!^ra^ne)AKRwZRQLb#%h{xfAF2ji5md-pNbNeSPa z&F1XqQ^8@)GmFcKXCj_x1G0!F3?llxTsc=4D$0Ic(E=cM@O8+-_Y z8>v!1uQOUZix)JNqD}e}v^n!KdV@mQL_)lYVZ0ktwu%|X$w^9rWJMcw@U!%WKuBUb zpCydC zwEk?^m_oy#H8C0ToJu2uQ+y%1XH?sY-TICbU=q2Zngy9sz=Wbf94RcKWm#|)-8)~xG{%lmUL5DiF-9^SjD$R$>if;?K@{fDeB3+fsx^IOd?-juLd&~IMTV2H3WrnWX-#R1ukEax z1VcL`%i3ZJ-_$26ecj-)i!3D_v;@JCGs<6y%_Z zA-bpY<(XV<>>z#o-utq>ypYY?3v>Af-)8ziKKS&fOo-mT`c9Mj|5p>Tz3jGMQLu47 z(SiZImjasVuVlJ?A(Q>ba;k|&tN**DF85T{i=`|VP@rmM59Ya;QV9;z=|ThBiO3Dc zz#4?7YkkhE(h845Z)S^{xORsqJH2;{#gxw2nh#2I-D)9m#fS9h{2_TC)5AgDJpEdB zPrsDu?WKHr@04WofBe7ytsX9WdHVc{Wa3HK>+^acr;nEM(I@A6z}(31KmVn!6HVl5 zllMJ#k;)ecKL_|@1S=j0U4XG0)kI9fub$Rc5D~>N*Fe73`?6v}Sm|?_&d#Mc%=C3@ z>wY1jE6j9?5EB$7jCZyUf*;tulOR)(YT6!>Cv~aIYaLS$$Sf`)1=ujyaoOl0SK@$V zak6KJ5rq3L-soDn71Q27P#vkL(e>V#j|AJ`=%!yt|LR&U-hM0F7k`lZpZ+shJp4?y z-HEOTEpGIC+IA|-Qy3neP(W;l%0$;`b9uuAdfw{4t!naiK;S-hJE`^l)oT>a-Xk&Cel6g*%8Nrntfzo;PqPdyw<-`6jb00MhwbzYM`) zRtB}L;U&=dy+O&IJfGYJJ7fr0!cseS*|qko(x7DpeSa1cEnNRC+*1Xv(XE2Sq9F8AzEsfq#yR@k7CVhMX`MwD5hr!;tI z6o=3l2WdK~ZIU0wIg7PVTuhx3&?AkiR`_vJ;RU9Pwcr_+?g@~13*0M|&z}nP7N*lB z%|Is_Z>L(+W8!eTyV3ui@H%kTWAevBQs%cbbx?nnExR??12u{EgNbD_ zwY2GCi!-z==}81=)O5C#+uJ?kk@0)Ppjw!5SH$n}nXnm-pL5xC>_aH!p?Cqj4spA# z>TCuHIJPD6okQmXi!-ju()`&{ya_JPguIN`RYV!=B_& zPfT29*^A%c9!i-TGvZ~$cljh4H6XdbNdJa4YcW23X2bZB>my}WdCe1)Ff<|(M9WZE ziQ^L8L^QY$(@@Bi5^|wp_d|y1!w(f8wgD^ObRKMd;c-EfrTob+?}AtnVh}20Z&<*w zBBV%1hD+nPR=AYjy)hr!J`5ei=rE*rs{8fZ3J6lfq_Y5;)JJ76!*zWl9h!RvVYLVoi86Di)llK$$rzvp z95>^H(u}>*dxc5QL|^uBxRw3W*YfP-3o!Jh#x^zj);&6JkY4*;DR1A-HyaX(rY zJhgL#+?0;^alQ1J9;-8(vczd%jn(d;h$SrE0na321hK30ri70zDgSA4&hf zaqX~6u`gJHK&eSe20QG^mAs61;}W0X#NiMwEFr;!k4bKFE)Uj$H`c4Y9}_iT(5Zl4 zy0h_ccrxY(FUa))gZNtzF4_}^&i6&~5KE_}1Xo;Y_<7l~hm@*w|JpR*@Pfu*xfx9+ z$wfN)gu*;h{2#gQJh9K5k5qglQ@4pvxS}MLD@!2E;arMz@=5l(O48~4?>sR|lkS<#_n322u1D zF+U|j0Ae!0W+FKZEacbpLTYQ*d~Z!M77#+H=|MyS1ofb?9ma}ALa!}`^hlgbrXOf- zOskS-YTqSwyhgU08zLB1r}y>m78+~xy7U*!@3`NQO9YtsU31^S>#3a1IkZk*KHw15 z`gfBV8IoM%Q`wSLc%#hDe_J=ad(Ui1F6RL}A_PN4@r_%+)luz1*Pw_-rviLgW%l4=t`7>cXsJe(j@I{ zd?aguSfkhkjT&nLFfjYfk%)!L_E59}wM??#STB82xEdpd-sMiDwn@6?@V#7>gnq>N zlovy+AQpaRwC-c#enX=}G&%<)c4OK?%5meJzZlE`ewL#IQOyRVo1 zLcTu%c{kVob6*vTk8~qyO;VHNX6n#}@TUuqAa||xEVza{!L>+6R2ik@qjcPKUx0kL zeq#oem4t;JCK#1Z3=%1;ORk$g2sHCA7b?y#J1RhMZEd<9kT==QGHJ^$SaDKK7DfU_ z_qliCI*o@MyylImX%9~BRX1hnbsP> zsuf`;B#;$``-Fl<&qAj$bqo!z+}K^}Srq{vg$%&i* zhO@bni*LS^{R{mJZ=cIgKX@qp#dG=X-~T&VPa%1X~< zHdoJOuf>aLCZ*?Z-Ninng7?6Qfq@5RG!zj6Y{X+H{6;5jx>^j@x2bQW0xiK^ydjV`elSdWG*ik%;+)eJ zI+~L@lC%Kx%AKz5t$xdm7FXc4K*`G_n@f6UbjB6Y?7f&a`sX<(9ddCgw_0>UuK48R zpKDU^p&T?I-t0PhWUTK!khAr<-qD5L-&^T#v}`>zay(9DuJ@@tnMh5;ydzzKgWj8J zHO&V?>nI2gMc}Z$Ke{rEGx#WltDpSXWzr>uB*Z#4l(5xewyLc%p+Bgu9l)+I{XkKK zA_U#=!fHDU=Fy~CnQE|;k6c8blHSMeRC=ITYClHH4F;u{EyW;X_Q{puz|DY5l$BfggC?xuK)U9!Rk$ zD$B4ls1T>g6I%m>b{J%{C@P09m8M+eMFC@#zIOvcd}oc1rVqZ(Dw0SsMa8{HJ{&@S zh6$S~G=1~D(G%SNS*;o8%3c?nE}Vq{!~!7=n~^9PcXBq%e@qQbQ|rJd0RF1aX<~f-xmG zGI?JH#T-ui6C_0J^Y!^X-i2`ZA}#D*TAyyhsRE}5gaVdMylq$%lhDN?2Farm|SpGL0>#mfLMd7~OPclF)6JyhL!` zR~Bz{ZvD@qW+)9`(INc+}vh$)g zmYn9`K5&4kXAR&?Fgcu*D?URAYf!+0>vL*wMK)4e7FSk|^KYQ>n87JgPT*5eI zon+*VC+}s7Tb_r8B3U+cK0z7^fgC5iDBwBTCb( z1V6>4M4St8c&6#v()ow4PR26Tslg#b6Yia_Dyb51pwJBmMSj7qlRx)W-Fan8u(Aet zuuUsYev9syN)tQWd?YJfZwXj3Zixdflzrb|MDnt9eE|^H0E;0}OdPK8rwWk5F{6Wa zeBs;;vPxWe%4Fz*B}Zu90nX7HWCI6P8O;3@9YEwS+;n}CbgZae!-)rqmd=Bf_@Z}r z(%!_lJwvTBL!cYp=yW4Ik5sR<+VooI&81A)fh?)r{CR9z+TcKSHdhQ0c zYQ58()G?C$Uy(brDTw8QCUd7uj?)g^LUw)XE}OCty+^Qi^jFXXU^-dp_nqhgc&XoY zDU*1s*R;{)yeDb%c7LPK`=H792@{mv&6jffySK94ypgj{|G7-yA5xvkjefqXS9%BU zm$II(q|keDadjz%m~3UQ`*&IC{a#`*XyLZE%|!nR_k4jx2VhZsO7=*`FLH3Az;$b+ z#SYTc2?CHv=x{eKEyo}SyAn756C>-;pfHh}E5fa!E9$lG(LpE>lG_rl@R~#b=5at$ zvX!|OAd|HgQOAiE#U1zVZgZ3y-P4eJo<4XeVX>BY`x^5I9$YO=yNoDkDy%8!rzx`I zP-03cD;M5~lpL-Lg8{(h9K{nRBE!>fD2fsI0gqfe_$Wf_lJcEM43gOxJF=MMRt8l|4W{hp6y5uQ!!09bx4|ag zl+DEZQhmr&3d=s^f_j*MxMCC4bG%^ZE0`BkNfkLU0zDbmNzS>lM54EUZ=B~8^Es3b z@O0Grd6tx@BuerMu@;)c!yTsWPADd*Lau;!nEaVC5iAl^D>Am(bRiWyz87UUc)Rr4 zd2J-fgde_1SuB@9-iY#s-T;koL_$c(miT03+*x(GV##l11q}yY?w=78d^!wznQoHH z+ml6TZ2i)+Bu$E(17#+^VsLFS?q1gipZz2mSK|o*9@D1uCKx##NiCsjX#7<*#UWl_ zywUGCm#dp=zVCdwk|TsM^bA@q%>U~8@(rgL%Qaxh_Z*(xkr0gp);J8VjHzpCud(^K zZCuF1VW0XRGu>B<)mkntUdZtXo<-mUzx3u<@5vmBftIkQif5BSrmfkE`!Ss^_^hBx zc1a zPL!&S0vhDJb!h@vu_?e*CUXcf8OwPbozL_8+`zVEy7#pc2}uJyjPSYA^TR&Lal0p2 zS-87=)8OuDS=zYwbx=KUw6--aQvdkkg=$A}D ziXv@{;)kvIFOQtmOE~+&#OH-tIuKm@n6bnzNCs) z(Bk7*YXF|K48Y}NLWQgrcJ-W)eW)t9zS7M|EsURq>n?P@5`=eSvxP()iZz> z?XBSL{otaDEQ5?DdRk~;+A%@l2je|0#EvwJyVZk9lXSfgv9``G1q?KJ-)_GnHnp63 zViYSMKkH}h28Y)~@-h-?YY7O+zhzdIxZC9zIP4MCSCFdfsV3q2>~`Q+z19Nba4YlejXe1Dzmb#E6S+P{ z+26b+1hUdSbN~FFT<>qm?P)KsWdlrdIMFp$68lPTmmA(%L(Uv}l0i`f!aD+dgy1!~ zWTIf8_<(q_KrAz0kdu%-7zj5rM>GjD*Y9l#XP-yHDL^JA;ktEm!|2Boifta=y7Ozj z!n0H9uWqE>+{%8rl!fl+>B*AGMBE<uA9+uY1B>HcFAS}wVCj07WZESa@X0*Pzo|%v zXKHRqPF#p#_Nhd4ZX#o8uta81t8rFF=-v6fa~b8HmQPl2r1QrKuHGzYGJ!Ul&&D`e zD2!_{Bo4)}kNX7Wlc8gpl3xQe*?E&BGBeP6pz#k-u0-ICgRH!FmJM?s^EwG3LA&yz z_GfP7cb;jb>-6=eh?rd9O$jnVL^>A79UBw|Go;im6cjnVxBU&c-qrq6zyF}g`dnt^ zf=wI1tv1aqJ);^eOb#dxN(6)>-NtVZZzS#--K+PxA0SWN5q{c}ht~k=1h;R*YrvKJ zqsAQF+tV3df`!f1=8}7}>w72Y$DD^mZ<2MMXs3xY^97eb#`8L8{KJ%Rt_99wxzOV2 zlCf*Hn#%raBYWA$^B7_BP!q>Wv?-*t0qjiL5?>v8H6+}x$oR} z$d*_zs8a#qVN8B{^BuzkW76|A_uZaTik?jyThrW=9tW&}nm)$>A7TN~xwJaZ7hjK_ zBu7`Hvc$Q}-T%CAlf-loPvRX08`9q65R;u zQoA}7FD)nQHm$ImUFIU@2y&^lC@i?76aC#!Nr0{^ZuPziv5A7K!~5b4euF`df=OZ9 zngknuV7fY$G?q(_&Y4gzke|KQV4~?mJ!4WvB^Ye-uJDORg3_eTP!jUcxE!9z|G@$I zR{y+Zd$(tGy%2Qek&Cs}frfK}5i{jYdmo)cM_dEWt^VBX5izC*z5dUB^oe}_AOEei zActd&Sj=Sp(T}7)JtaKmt1o_~N&lrD`de~1dUkmxHX5xo`PKxyL=uasSkuelpas%m zC67LQERQt!KmEh+mj3dUoUG@v(!=Z*|M2%BZ=TEYd@0vgFDd;v znOE}g>^{l!-#z_Cj<24JOiLcBTfHYBDMD(Pa1JrIYcmb(nd~uHhtEQo%VNIPB>REP zXKRi%Z>~48+g<7%IgsGr&~;^OGK3XBV~2XJ*RWcjas6yIH?rNgHrfu!4LWTJlXv8r zC~Tc~{m}2u%hs||3s7{pEe#q6sEkaF2Ox&k?Ms7<&SZ(l1qqTTw-|{{jnw|c-BCfceF3Dw)7hBnF0dW(#{|OG&$8yl?-fVTe;T7*p4-T;~XP?;%L8w_T{12JL(VFc#h17$2msv90~ z35$U8+7$H#x~9o>*TY!FGhLz6XLQy&-B*^Nkx$aorpl5>pRkstK``g@xjr-9 zTY8;0n`^B{A8-u;|9#xTKcwc~-|I&>S)a)2{GnWas|EMwtsVU7=_a)xKIb?(KSI7% z!gOLkaN*F^bPh24S?)$zB-JJS&U&-sqyS9{qZ8@6>zBGTTEbtX@CmM@Y_&1|1vTt@ zy127w)%#s9mTa~hdJ| zCYsty7!Gt_+ePa3#{@rhcto&R!P^*fFI}>CgHIsRA4Fypdln>Z0>rw@dVAbUb+VB2NB8CY{E2+| zn+wKBylyc)$ga7RlMnC9qbCokC{?Xn#@Oy~kcplJZM*Xcl%J2TK-83`TG{LClyh*I z%xjDC<(+k|i{*sMQ{Yat=ww$8Gjy*a#3gVR3JP{iNS4k?G~zSX%)};$z$f&r793hM zJ^J{OOcxsOK3vJg#f8YuBzb{UK;!Zd8k<1Wdd<_0mQkSkO=gH)FywXl)ZWw&p)ALr z$GwK0ePJ=Q0TgOwViQ=`t?v8VqjO>E1M?8vYBZdviilzu#Cj0*OG7MR3TqDRJts(v zIc1p(S5tE;o&OS@D^#-)R#1>&H=5u{=As!?t1<#KO?RuDW8&W_l!2)a6eQ97=n_mR z_=K!CcZ3*+Tv8-A1bU|km}*rwTEo%fh2+9J{k_GiR9xFWp%Eo7JV}82PV)rc1S19? z6Pu2tUzS70@z1;?+(b%47@r64emV3i)Vb-DIHC6UCEsiOHE=w_ogu-WQo_2+0U4#q zxu~&8M|KoX1)2;>X8Cn;s0u$^VdU2xk=W%=PeH1-9bTs_2V5%E7hF>I&wa(r@kr9T z;%=wI!JDIUX_EtRB`|dmZ0I<3GeMIrvxCKNXfUF7ODKo`j0Bf+jO>n%>*Mi5O}`gj zfQT0$F8tzHHz8IUILE?mM4@EVbIMS$+C3ax8`=YUs#r5C2fiU7pQA%lyXOPCKCN{; zyUr4zXi_g37Y=eRh|R!qM>p&Np`22sP+TgYes$v0sD|C2)(;8XuR7Q$5Sa2KPIOFD znkeh_QudlK!>F&)e?LsMfI533>&H*@dkT5^%~x7{yp)+`*WC zzcs;W3nt>_s6L@oM^!4Aq(uDR_&a|kh4?FqCU;KmAFeTFO z+1}pDWHr|!bSICWyf4-9Aa9?&ggleX7Z2FYZ=eh{UoepFOk35~A>FBciiBjRnA2mW zsKFgsunP>yT9`rB<&D(yyHDARVL6p8 z4n|G(my@NOhK203c--T_Jm@{%9!>p259j0VU`+yDd$Sb?l@oJePR&(s+>#UIBxbB< z6diS4xlFa!?uB8Ht>JCYgBWK@L+iE9TV0TFN%OaV^SxybYI$&7sa%~Rj zdgATlQI@l*ESFk@AM~|=L)Ra;Mq>hrRjv1bzLc)kJvzmN&@k2F29PGHn_{DwENFVp zPGHTH7bL@Npq4$z&YeTK=qUp!ZN#~_x8yItjee)sIJ0M;U_QY*(S1t5S{!rQ6G^rU4mV9EcpVO-v?*8W6vw>39cbY2 zV_P2skvy5$+O$2SLp_-J-=KO^xKU|k3Q^vXPI8(guDaNZHQL;}h{{S+k3Z(4K_k_X zlsu;u1=h~an*ovBe{=t~WZg^=8!Gb^^q+D#D~p>w>+EV$ORA)T!zdGCCQ?nZmVfcz z{xkVk|LSk#^{cn?FaPDa{2%}OzmYc=ujQbLbx|MXU;oelgRD*-%I0<_mp5I_xVw=Ji~hpPDQ%V_=mzNr6q6gOSo%EZDk44mh9JY!kpGs8Y7Y+7%HRS?Z{0M;L)IEM zHMHRHE8dQrJf#km-KAhRmjScpVLQPAUM+~Xk9p+g4{cO{MDh|WX@_D8{)MJ!`rW;eAn=5X_ir7g_Xyar3_n&I;J(nYr-+ISR zcaK7WA+$63JGzi!>YxEf&Sbam-6QC4N^?s}&qRTE!yU}E9ub*T7P;Rs+JAeGXEZ1l9{F_(O z!sYGkBdOOOqggtS~TXdR@Hr+(hs{i#f*Co-QzdTz}0AUMB2lOKQj zSU&pTzI^th59G5?KarpQ_%CF6dMe_o7zwD4_z9!%@19-CuYdD9`PDCfFTeiPZ{_pP ze<$C3{jFTnJ7Ne7rgoOb)4KM!UHVK??Z@2?NUWk@z#id20mvc_o*6On82ztd09Tj+ zT~+Fy3M=x4KwhMgMOjkW?1Sdi02x^y3{D$9@qX4bh-2f21kvg}aL2Aqte z9lOVXk(umf=j8p0g$DNs4Ne+KhGD_g0STRS`QRk~IV26EoF)AKq`hafY-xEW_Uur( z>YO_H=FoJa=|s~sG#Lblrhx%Ok`N0tvOyY29((K`URulca$3u4jsMs)9?gs;5E9ao z1QJ06H90qQgwEmSd`~`gDp&2j{XXyeeY@&(L8Z-3t#pZ9qta1MCk zF9)x(06d=3k@DTdP+14*V`B9Sp4v0jK-+%Ts;-_efW!wn*XQ(9d=fJD)ydH7LwSGd ze(no>gh;v~9z4t?!_>7;!CT;vF`EAjG&SA3ZUA9A&Szw;Avl`jVfCe@ibh1#$*|V~CQZ?y_O^IC3 zi(<`7IqIQNFXP+a{3@P$;#s`!-jCtf;bojY^@QBt7)$$RbQa-n|L)KA>3!(Kzk&CC zX|D@$8LO-7c=*xBaQeAZ@_hOza~A^@&Dn^N&DGHUY0@-m>udEjS*Dc5Og8yC)x;3H z!Pmw?MF;bVCMn1nJa_&y9(m{yoPO%0(Ok3B<8*A4G(rnLlGKcPx`+6CV|{i7HxI!C ztc{XtV~w?YtzFr~;D<@*bSUD~Rp^b*mG7g0dN|hZY3dRzV^RxDu-1tFoUO57mvfXE zOx4{(>Wv93n{u+hWvm@7b{D>q4 zV(_2;#S_?l{wd4`T|B$9BgQO|&pwS>sU*gxA@4IQpS>)9R?+X;TtrC>b7OV^%L@lo z`0d#z&I3zF5S8{x@>E4RtLPkfZ`c=eEdlUOXmo*fNkZ5rmjp49dn~AM9S`aV!<`m_ zmKZllm{#T%Q0z%8hf(=Q%&z^c5tEZnuowG4=P*0y;Q_S$S*BwEp zw}HnVeF7!1?9>9$LrG)F_B6(MSB~9)gaLd)Mys+0F3QrvAU&kfE}$m9J8p)m0zN3V z#aZ;RxC|UCH?h;*MrHP9)uABmaJdYF&Ph-mmyKH_;Cx6$Ty=L#VRYGeSL{L?b2AC* zr9f$ZTdfwly`eoLvM&)XM1^+-SH5!Ssx%g`nzH$5kZ5qC?PwifW>+K9b6T# zIyhz$NWS}GT^v#a{Q(gZHSMxlkYxpc#3w?U?4}q>avP}naHe8XQDEYCp~5I+58l>%BeC!T17Op`juA$4y-HfbDy{UVg>{wwjLRIdsFNq9iyh6o#7qKnt zTW&W{-)A<26q-?`q{`h0-8GSaoiU$0=aJ4NImE5!9e2VkCKYE)SX8T5-4DhE-4P|w z6-JqktVj?}K}kc$FRv`qaux?g>!_5tPqy0_wpJ1DUqq==z;Gzf?8Jfgz8)k z*B;+5$>s%}Ra#%Wqycy_4mFw4u~c^UhT{Cj=1iGz`#@OTk!!ysO5-X4JTHXR&D0c+ z$I2ErG<{trN2FradFy;A>yTD6M{f4ai2-_+ zJ|AppLSUUYUnNy|pZb+tIL0L(){)g>N!-^iKtVf;?A}xRs4Uk|lWQp|Ny|Vxhw`~a z4ryCwVn{zne<^$K&98keZomFc#JeRNo?XV}=gtA$0S_fQt%2H*SH1EMY;3Nf-YDW5 z-~OH?&}83}H5pY=BsNc4YmUs`-V2B=Ic%kd2EzToO|Ti@mTfzuT4X z0h)_V3}inx=4NosHP_*mTV93-fAT1vdg>YMZug85IC1Q5@>~YPj*{z`E`y1Ldc;YP znJ8YO0)#_j=Hh;)-b-LJcA0|{7s=e08YMW{uy~H&^ya(qTOa!X{^HO75?gCMw69A1 zP#UWy5NQKhs4A3V2iY4bL@OOjvQw(lD`41e=@A$*FdlamodHK86v*`q2OSNbV&QsZUhk*sj*9vCCb>btR`cUnm>TG1L+5j7zV!?7VU%k<2Pu8+03-YRxKwj|+^H!Iunq`jekJTWU zQfE>$y#!8!4M+YKgFOk2XEF(tJ32PeE(hIFTw&(yb~>wp8;$f3g0msmlHZghMK)7BHfNhrsarN7BQMh1 zrV=b&d;L+YUOJCnZ&w1>U5q6VYaD&41f-Hs?Dka5FKTV0GuqH0ykWPi^o2tS;q}Y+G^}J;btqqLx?!xrv~i zpvpkJU;#Qc847X$!tPM=&MpdMCJ|>5CoS!aY)XK>e({3X`CTl`&0@T{g)2|~OtG&6 zIjn=$hJ0X(V+W4P{kCvHoJW7_l8Q5iycnmNstih=#6Z@4OpaDo2Lmr)#EIy-JU{ZH zSH-|p<^3h`D@!ma&t`6}h~`{|BgYQo(9uIUuyQ~Wu%;M!Nm9$MoE}?nNTV?%%UHtB zNs9ToDmp7oY;De=-D;o|%bKsZP%S|zuFKt!NHJMcQ}?B#81;9d{;d#dlFb(QbiiC9 zj7eEqMtYW_VpZ#!wB4jyjDngv@u6gaWZfDK$k}AM!P*yT3aUd;V95VnJw-f?QSeVbX}ZRO;R06!U@kJgv!35m9xxI6f5j- zoVn_-Yu)Dz9X6B2Seb7#Br{uos0>^|V!@QE(@*Ko(Ab8l6<4^#gMNgXJclY_OR{EN zNz8jgv4yor0+3DYo_ZdVbpbn@$a-D0%OPgURcu_kq>hTBoukMBqB0XrONXkADA&Ni z%#R=VK~UG#QPDctb8Z+kbCo{Ypse3>A}OgVz3U)|>{W&NMPt?RAi;vhi>jL<@6oqF z!gMc;o8KH&q9hmmW`#8<^ieJj9e#VPdI5?dA3LaQU^J7NW9$oj2RY}a&!csC!|xLi zJ_zdOl&e+sA1Z$82TM}Nzw8Ga^nDUH+vyS%mUUVDQRQsp$@p|a5jg&P-;rQ~6~eRD z1bGKyI%(Qd6m!GlN+GJTf58f14z5RbA+^)`XQ)LXg_Sv~?L91t+J#OOMx}6D7(`6f z0UVlP8l%mb3CT?cR)dlrS=uKyWhZYeM@a@QG(@RcdT=2N)5<%NYU@l$RO$(wT|ulr|vuRO5F~-8APrqAupHr zq-_F)i6y|s!a+T2m#& z!b}-&L=OM2GcTz_xw!Ka8U?Qs0|lmElsU$>Q1w+x`3$d7G}{b=!aS$+Ks1W+$27Fz z@5BeTp;4rVa$bgF*r^Mq#RK_;z9fYKwPQvJ%CmKe0k%+_ugO*t8(k?$%rwR|*IkR( zzy9@@pI^Y^zjz!EJ@7ELuWo3fR;q|^l)W;_hB_M=>OQu$_46Xx6kLn2=UnAUgKO8J z^n6W$W5XiLCK>%4%u(kyN&mvmS!mSBnd|mzM<%ng>vi_DgAy1;yLQRlIoCNgC*BD! z66xcEAaKljK|ToYB?j^s-QA6LiZIpbonqRYp40FU*=%~I`UPKmSg~I8Plm#u+Dqn*h^A)5&OxXw&-5xWOBJCN<-WRD^ONZaAJT? zjdS|TKTMzXrH*MPaREgXMmc0Sb@!Gg6Xp=5lGBT^EVWQH!9t~EV`Y9ADH9RJ_v+#AeS)G7xKEQYZ|y^3$A~$G!t~Z0%gei8GrzKS1V_ zsyLJSe27lzyx7)Em0CGOUJ}RB-P}ad-$7xxD>i{}oRI{fsRm>j*@GBVrB>A|_bMuO zmF>3Clt0U{1ZC|lB&~HU)P`u3V-21L@&UDaN&MGHg8Iwou3nJCooRq(j1GpS)@P8q z4WE(usiG>W%8P7mT>IoiYmlkIDZ!Hofa-$yolBHEu~HD z4k_^EDx;j~@B&Wk5IKHz|HUc}hcAaZTy3;`{FB50WS=r>MPfBehGZoLB$Z)x50Po5 zBkx<5ptAkIYL342S>bE zR8V?sW%)8;!PK2~1YW!oIj2LCnyNYj*TfN6=s6i%%U{o;3+B|gCpL${AM?yLscJ%4 zmz<%U%@(?+ub?aYYWBc98nvRNVPzd2Wq?*DT(UjD(fx|@bxw3xsq0KrFi~fX%K97$zvJLFU!y$!Wcz`!=Hwjo zf#Kq5|5Sn5Ck>euWX6P1M7D@!vH#=9e&&_91BZDw9WNJ5WMR(Mw)ZP_ioTf^RX96T z3XIJqER@{mr%t8XiIsVWmxd-(Nr(ZfsDV$?{G^p!$;b~_x{f<+=sIw)j8NyKLWi67 z%yB{fr}5lJQ;ARN9IPu+ja;gdIu877LL4UiW7ti*Cz+tx?Mm>$3$e{23gz5tn))y39hsf7;V@)(dC$MX;OAU6YRq(QsdZck( z@`5V5tzBTQhG2OKmBlh<7iSSyi(&^ev^O`vt3SH6xSsp1PWVmrjPQ9MxI zZRWsrc=C~_<@<37;EQMxPoAJnFKgUDAd{`2XcjETDZo-q# zK8pURkJrBOE(wlDIxANYKfl`^YSmp;%jGfjM;+}*MR3|^jxCY1W9*8?u?<>#N>zm| z1@4)07Gr3H8B7AzpO$8^y}gZgXAM97=}+Z;ckt1VeiYyR*8TYL_aD&UyV-1DLlUfN zrHWq5P$||qxBq5wV;J|WVjYlW%O@GB(x&rup-L!B^n?t4X$i=L{x;FMJA)G0UX7xX z1?xK4UQq;z1?Q&0kvS^*KnpF*DXNG|5q2e}xb|f?;nlBtEl!<1hlTkixlc(FXXeoE zZitWC(&9`Zs^g}cZow}l@wo4wzKf51_@lUdaZ~&dXLtJO_1FofI@pXWLVBB!DQt_? z`ZV+LEzeH@#!MK)=$_%>K!&LCvsADyqxxKAZbp;qQM0+D%oyv~EmU?<${t8^sbkH0 zKFj)gn*m8oP}9wasNG7O22_~2ZjDQp(h0kmc0p1r{;MXLx+OzRg!v3lVx7vsi-u;p z?#6o)zzcMH7Cz4+_Nx*PKaMbgXZhlfhYKaPzJX66rr@#Kn8+}R&f&0$Zn%sWz`yGd z_Eg?7$rSt_S)OdPNG~9m9&97ZZMw!)?$(vg?Xn6s1i*s1pT*IidftuX&a45zxwE=M*PKF%}iR;5}E?j`UqL}9-516L_3I#!iT62PEPP|W@DV~23v zwS@QG4o5PG^JmWE@`cOz#V>w=C!c%@7cO1GmDQ`tdEf01b?}-n4T^4AHxek7O4@2> zm!eqY9FDP$u=~*K4K#o*vvZedp&dPWA0}fA_Qs=u?qPP*Sj{TN4NY`Mai37h9;}=n=&Vock^~TvWbAt>P;Fj=z9gI5 zS4Su{S5U7uw20B|babX7QpM@Os(JFe6rQAFFB6nXUGAf51wll4O(UO|DKPJ+V6lY90FT+_bdEddn#0)bhs;XgFXq^*1`aEc2cVc$sMw#w8+Bp@@+wQQ$ ziN37wq2(0}m-nMbts)7eI0(8edvoE?B5JcU5?t-L3U^||mOhD;y)o7qy2#)#4o9o^ zv?qoSm9CnDo@wGE?4ngg=}g4%mrF%;9$J{7k}+w!T{VrJB4zsu9H%MVkiM^06ZTUq zsLfFJAyq|lqH?O&!OqdZ2qDHMhv}8Ob82A^9n0;ax24|YSkXokLAehy6h@j(vr2l7uMiNd+3c zmdDf#h`WbEWZj2+=sSyDh0q`mnag&4N|brM1Lpt@(vaoB0%veS$G$j${aF{zoN=a! zy%7`{ZMIi151gJ!mJh!=q7*kb6a`^kO*FI|+I6c%pP9`J?)3m~#>Yn;D z%JiejjZ^4h5S1EbxYENT$)BN*C#*)0DFiHY9Uv`OhDNE(%Nz0kEjCfxH-pB38mfyG z>^r)ILcN6EAi%sFt`gp|A+~LIh(Tuu`(#26QG$}5XBP=iN$J_3Cmzbd;zW2Q! z;QZ5P@$WzVr7J3qps_y0m|UZp8XRkez(c28khJrX=f za?Myfk#(Dudt7a;iC+|7P$Yave5=@x=KP%4ud-@jg<24bK{=B`v8oaT!!f%XO@|r@ z-TYJFl91HqdpH;1I&In1oRZO?#$uaU3?y4-+bFgZLW(Ome$6Xz!;RPA%U}8u)>b$1 z(GPzLM-E?uFMj^-u)W#BzJrIw=Z(?p7Sx}lI#U=c+&5O(a-swT<#I{Ij>oDMmZ{xP zcyQ*K=^{%&7;I|-V(g1v$S!g-TA?e@FzMiRCt5s?)!y-Qz3zq%Z0npysGY(@d|RVZ z!@+BgFL`Y22lSHFhsjI(CGouP7#aN*@qwhJ8 zgfET?iVjfK_soa{;0Pd8?A0ah9>y480__aE;HRS|_CybvV~*1KQ(YTJ6cd)M=;aFf znpMH+HRYVxFuR{Q8eYfhW%YO)g3R1=H;d;!N6+ODW=TBR#Z(8Fg^V!D@54}>k)HF& z(QVT{PuolV&N58cud*C@pq*+sk@B4U$#s-{ktcHrh#Nq+rh4o&i(D5xKyKe+KQocJ zTjL8y<8iL&sw$QFAW7bX&;J(q3Z-*fHfv!QV)=*7cxWYt)NLv{WCOHXoScGjc?Oo8 zQ(bcfui$D`%go_A^FD{4(4R^^(!k?~UFzXplQS3v4tEV)##J;kmt18& zgY$`%I-G*BdC`c6ekI(lQvHrts|C7A;-YGes9>C&p=cYp0Fta=^{w|%T{Q)93z$hzbgsS*^^IVb7xb6Wh%c`#o5gxP79bR68oM= z@^k^atqbT$K;06D5%oFC0K3?zp)n&#k_1t;T3IPi<8noZ{v!#p*5wAb;_mJab~`<#60{+IQ`lzCJQ~?L zMWopcC5d7eBw+Vrj&(Iq4})L*-i{qA*)*f1kCV?|5+k>&xc~2ecNq-{Xm7ajC0G<^ za`4artn6EqXIN4UERzs@{+T6K7ejgE=wTd`XS1@h4@V9i!PCz^i4!NE z!Iibkih)uoi7d1jd4ctT0 zEE7)AyNtBo##&-rXdNZtT8KU@?1tF9|#7@)vu$IvNtp8099n4 zRgE5hlo|4X4l8oS8f7p_4F{hl4sa4q269s`q{e?!b5PKVVJ7E+ipLTGX~L^jZCABc z78VHzMzTrBa@CQ9gOEpR3xu-Xs7r((4tlWFMvp9Ci~BI_$~w#5rcEOpaAVlV;_)Lm z@zfJ2i*wWJy~EKmm>#E2*_$1vz!6%eo~|*kPFMlP+dJNe`j^ZYo-|;!;!Ki-&dGTa z+SE~~W^OpKkQZ;X+@U_fL7CJqIOYS}lseCp7&t=p{50Hm-ILT;+KGG8sT_jjGXz;}0)MaK_&GN7{{flpeWGjZNw;0kepNfG&Hqt7AE zJ)g07c?K`nJyB?xaam`9*#=8CT+&l;A%-u6ne4nvj!1J|&~6-ufK@eI$uC0F>j^lB zCca3np)ym(wJ)8+-EX-AjkyxGS{*#{(-F@6a)h;V5kvG*lCu{MVszR=^hRA-uaeF{ zu==~R){|thhHrlD2YCCt-+@nk;^mSMwD5PI`@H1qa*jG(;>qD>d%{{(i*zGW)Jwoz zqW|Pf-DrSfy?~ovc{^VB`nO_qYX{%B@2fa*_5}XvYhT7Me)$kyd*>^0&%5uzZMVG~ z58nR>&R$r~EiW0o6lID&WH`&RtU?|fX6j(^0TedgceLm&7kKJu{-;UB;Bb?j_*RYY7m5-Qd2(sG@{7V`X|8!VBMp`7!hzx+w~H>RJ({l2|9FPz>F)Uctc$3u@EZ z*(9uuYoW78KC_K%2s<%lY?LIC?29e`_y>MN=O{n@XP?v9vD+S5EG4gP%*NQ+I_2~y zOStyBoALHveD^Ucs)|`AVgVVs%c}dL(`@R6CnELC)L?Oge_CQ7s3U zws{lil8-wz_H%uYG-t1~qB{#wX=(|L&UX4Dg3kC9oG`B0FFykUS48rfb@pvZClNIU z5{pcvF*8G=Vy?~(dKzip^>o#$+@7g9aVVNRdB}Z}i;=S_hQs{6U5p?2HL~CF41h)) zF#Q^5HeCX<2iD~hk-P)KO~rsGaO%O_Kw90KhJw9dqJ4VUI&_JL6^I;`Pw(BFW2#Ov zR*Z05FkD>X*sUh2wQkV@>|tI}Y&?H547H-AIS6csCURI_$3e5_`t&ENx}G_s&5Eui z9)vxSmNIl0ywoYaD>mD|Q<`~=M8nX!#A7lnA8Vz9??>jIEb!rh(;6XNZfFlj|C`+k zPT2C_#Mq1iQ)4$(_L0t#lyvB=tn63HauC_9K$$ZcnPI$D8J?|DImjbNPMr>V7Z1zC3k^J1h1j7zAn+Ae6jmK}j0T$J-b`d$~*F(Bq} zy9BRcIl}J7CB&6^EQ|3yut-d-{5(B{!TKiFTfdaw*-|Zz71^{0R+>1z{|F8(E#mmW z{Svr0wTi-ueps}wN2Ybqia z*VfiBJ3ouf&2_n+fhIBxc32S}4Fj>okp$n=QfX?!!9*lOO`c;-uD4>MgYvwJsZkvB zG4+NF@ON-^bq(jwJtK)xgq4L^+;ZzpIC6MD?zrQ2$?5La7Bm^zbdPr_j8&GPb|4Na zcFDNyE2iCCZ=y_=m-eCj@*=Kz$zg2oyaMf>v147jyrYSvH|*?wR4OH{Y7w(aeHpHY zVd@9i+~9mg8&|Kcig7)O-k^_5SFR|_5!vB79pd|k1~Ve$tyHif-N?iU$xuU_IFlZ# z=WbJVn9wVQe-)IDnfP}q|B_;`9P%0#l9D(pPo63`S#r_JZfpvYzft(iE;B!Ea1wn!RilIV>{Nh!~?R$WBp zNPsnVLL^BZ(BRASpjcrrC+8%QWThtiPZn?AkwYj;5?LIKG|5UGBqmaPZ&`&MSsgY^ zuS-rcA7~=4OhE}TLhY7Jh&D!Y@5WA5P%$1?_09-cko_CfIQLtv16nGZV-CSRds;AbD@DN_I}yCUXsIy=u8R2 z;QokX6KE||hi?AHJ)d9-bIkWmj10k`O(VtW^Fe9amZiC}{2tEw7j!w`f`$nsz!#&U zDfSufyX^1Yp7WE85Fp5BKolMVn*k}tvBOYXP^}4N=#n?CH4{Eoc(c&WlDJvF%)Ce( zS|wKtyRlI&>kNovWrWUNSOwTau;9WG-Q!HglqGFaH`4@1Rkz)+eryBlnPYiOGxIk( zGdc1d44-tQMvmY+IhjHB$d;u;MTrY)X**;;6^q7T#DQZ)2bjXEs@;3Ptv10WM(nVr zv@vN}>9ng0b<7`b;Lr_oxbe=I>OM*fPGDjO2i~`KpX5<~J zV%OTbPX}V(>h&hNogJ*KEaTjXOZeN*{R77GCOhqp&TZ-S_hRkvrCw|@GaV0%E2zd| z_xmHIpsiMBuzK|>?!WJ6xO`I0p+_IUlfQfffB(gQzypi-<85#J zHT?GP{5GCBaR!e)`#dg*zw3{zTNfurkDJCrWkveTXFrDnM-QUi>7dgcVgK=Kv9+;@ zW^GnG0}Sp}QJs}&PD}>|mx+?0o-7U8c|H~PS1@+Z)Sxz*o9Rj%BExh!O1eKd$gUOq z*anQN>!wq?013ZG{2E)LxcQ|1Vi96M?Lzs#wJ`v%W{;wx|z zzl5u0sdXDOFCwXPA)eLC+o{xzEV#Lo6uG_fT?>U8=eV6b*tCMT3*5a@x?RImXFAI! z$$~@ic;-b@h)pJw+(9}?BL9(66!CUC4L$B28(gr^OrK-d*F(2=wcv!{?dnhP9D`_cNjaRx%I_N=P ztC>+?l{BT9n})6BLV|7;D5z6xShvAtrXyFWQ=uXe#mqft!)&LjXkbGxc57Nb*_&zY6yFem%Xn7-1Kou0ZH`Bb|D za=%Gm0&-*jp)lQ`-;rQ{hzn;<;o_z9iktn#W52}1k358>r8&$=^0UyKQwP&*HWha~ zFZayhM-`+D9G8wu@e9==7E4RmcUWE%T&v6?nxsET+g#k0>o zi)WuZp@|5c&i2kGR##Uwk?Z${=!(;&1Lt6LGA0#kQ917`<+{>2GH{t6%X62YV@SrR zj6?8}j06m}msBUDAc;pYmc#?QvQE2lJzY6BV?DQhd1hOz^!Lxo{mfy0|2)d_o;wUG zD+Sc*MeKwOaK$)Fz)&QtO!iUKjAY*ujU_)H$a$|Iud3-?r#?7^!WUHMf>6!GL1_xH z(Owq=H!2Z2p8G%(5LHi>z=V}bt^X!E7Ndff8~}|+G~{+>Yfaf7vPXxNScfjFhgM`g z#HooR?#r25Szf`61W{Y8c1qHi6bIS`3g?;aBGptPi8DGVPNfTGS_5|iq`Y1 zYegBp3TAM@G&1ULR;pv4fJhLY4%w|Di=5dV&I%-2iL5BYPzs}$rsj-Ms}f2x(petD z=a_^t>r&ccorOs(k(GO6Vs8mZtjR)u&+mK1wP)+7O$resw3jpMU7=s~PA zFtN_51WIc@t>o*AL4ku|X;;lD5UVpEkBnwBwIWbanZR7fD|dcV-H6B+tRhV4Z-e}t zOs>^+ErM*%8Dj#Q;#VagKA~{K>MjAXA#|63$U0M>D9NlhlVmo$PM7J2(pgZMBnp!R z#PmZ#)1V0A$=P=BjywTzwDm5@&+AuOf$IyHdh&2SHL&)-wg zUU|nA{O7;-G5qw$58x+1Y@>5|4eenIGiEH*?vfa0Ad6Y4Mm8I!#apLorh5njdbkDLHx6K-HRXm;QP3E{=CsZ zQ^|hVMMaWT#&GS{B^1Ti3^&)c)g9NGxN!QMJd-*$*Urg;)+LFpqfH1p8NDQCv!uv; zjoD)>Y$U1SW>PPN>gLw81L>WUD{2^hZ{MvBzswH%H=fLKrMfTd%$fF*F-<0#xN9_& zIpIe)3?Dds4R5njH&5Xqsr<>fYgz}k> z3C3wJCAdr6_GB>A|DC#GkAuDjFUWM*0g0w$2K$zcj zIO%!2;Xn_eqWUI-vzk)mshUM%mFLtaERL4YGgj z@-d;|P4gtglqhZPL?0_zfQZ8^S|whuRh%#roFK8_N@)(0)U`qYcR2 z;Ehp8ERssI9>&y$D0Yxk=CShfI}t4J$EnAkmCr8W@N$*G^&W$tO|k zUBPBKw!Cy+saMDSqSEt~%fyp*(HpHHE{)NctD;)3inEB(+P#1) zm)2yRHnB7dyyDiIas7cqSe9Vy`0- z$Spw$lrm0P&vbu4hY$maCOdQ*l87!WFQdr$0`Xq^_8-Lh`YNuy?ijYVB=BBamxM&t zZMTos&H!86eM0%Mv$iSkORCY11Vc<{$`asFk+!12Svn+Laa*1d1N04qbz{>C9M3uT z9O)V_UygA3%0)c%&;yvAol&*<`T2QCwD#l3(c`jCb9h-r5|ZUv$NphoUcypylFSdo zhI(IG`EfCI@S@^?;k3gX*9qlRXJWzb$il)LuD$jeEG{o$|A7^`S9xZ=jwEQCT6w3V z?b2a$T}dt^4zSlt(C^AOAxM3>H`yl5cqfv8Nb(Vo z?JSZ+gvkhXD;Q$cDj1zPiJkRL%=P4nExZ)%P=bjvyD>9j_-D|OWUjm0fkgHa7&K5R zNMg%^C7rA|f`T}6QuhX#bwNfhKIBYBs^`SPBOQc@LSjrfnB2A5#h^3KA~zW9l9|Nx zg0>}51IU89hA?V>Wjr4kr02q3Rdy19)FN$8?-ghnmG>TU}o*>A`= zOVh`0UxKD`5v%7epvVd$TS^oH%j{1kAgttbUMM%vsfjJJDqc`~C;=a7B~x?gfn)kh zH3;u3Wi>03$}r>PB!7fPEI&Gop2&73z2OITfg8{76lDGnlM#IK(I8GE+pf)rz zfwjJ@lO|{0E11}U!|Y5|zos|o6qA*=a~4FHz!>4C+F|Jpkh2BkZxc*dQXKAG6BDl6 z*mXgC!0cM^6EUr5PlwznCxaZPJ?SJ&SXd^GGjmnHi6czi(58n#c}A+etXk7f(_e=< zV13T{l6X4ZNd=N?k+|-96dP{ZD^F{p5m(?vMJ>K@hyvHaU@>8uhBtIW%KpoAW@7i8 zLigA__IpCEVp;@A-u;L}U#xQwK&Ni)yD_G7lBh4B28#+429tGGf)DxoU_5f2GZSVE zbw-KFNfkrx^LhbuhZ;D1<2-J=`+6LI*~>Jz?8~yPZ%NSGoW-$gj^g6ur_oc*)ml|-6~$&NNIG4NOPQTNU01gsGDC38%{O(1o0C+f zQWKqV59^y(ICv>Z(TXHBEo^Re#jZbrpZ)wHyymVu@oR5+C*Jm&x8Pe}{R$p=^dbEG zfuG>PCm%*f{3h3zMN!gclZu@J$p#Y|C=Gv9h&4voymVP%O|$h`>mDe)v?Kw211$Qs z#WpkXCk-#z6^WEc)5+Y`c-WJBZ0l?v_l+{&A<7AS$gspUk0e>|N%B!BTBW;GXeuQ6 z_S>(=hd=T`+;`tM@P#k@4eom78}M7d{SkcgTVKWZfAnoxgBIR(@B6fS^5D-N#?D4p z62_h;QX~XnVTkbEAhWLDIIsebcA}FkA6AYW>Vt743!iZiI{(K#8teIBLSi}_nReA^ zI~cdIBSq#$6%0&G%fojQV(r?8c+;ESAkSxAp27VJF{{nZYiEtKFJt-}S({q9DK>0f z6Afz1vHL}RAHucO_Jv zqsT15v>6w(`-bRZj59Pnswi-XOrxz0T%y81qtG$nY0)ilvstF|!3f9-j}BG}H{-_w zQ|crrveZo&I3kp(_}dHjs!wz%3!9U3%!OGnbx%H#aJ*T5zB@10Ob?oSM5=Sxdyr9n zJi{eUsnZiuJD$AoZ4iv)Q*|bDoT5$)v=?&9jLqeRtWeVv@y`Fi5BPbpr^z6UwH%Fg zin9_WZG{=sqi8rZpCzS1o`7VIPn}C%<~1?fQwTxd98(mz8J=;@lb&}!JmXE^IZ@Kw zc_~4q8<3YsR_P+GRhVi5qV$<#r>Ysb2j^f2nX9}desG9RR^B73%~*1k!^o_KXhTDA zKwK8NjQW(4I48KBUU*OV4fDIL_nWEgEDp;BtPE3fUNOvVUSM<y+D&Mp zc*C8Tx#^XdSv-L8h9m};SCNTPC)av;|GW;wU3mNn;Ot4@>Pb0}>vCOdMjMnh1;x=UsT?tKWh$pDBm& zW813ZAe|&0Q}aS@JW~x>zGppUer8A$zvU-Gu9H8f(U<feZ{CdnSEaA|RgDA=RFEp(hO0-eT zstJexW5dkSkcaUL0vxxCCPF_itmICAIn1TUlDo4M;>`TqU5yw=9E&#mM9rJk%!Q+{h!j#<_4x{|y_vN^@2${Agg_|-%U14)uuZKpAh z>I?E5W`L#Zv3%z{5zk+T^?q4mlvyIT$49ZOU`qmf-1WB6T36VF#spSP0B_{zKyoQL;S$iX0 zaC^nAe`-a(AgrnoYFe1pc?X_{@c1ICOOZmcuDkg-_8nZpSvgq4C$OS}LX}D- zy`BOETIJ7*oNdzS_T^qiv|EH8EY4$PWkriM?S5OIZF2RJGHAW-w%c*fTi>W8B|rZ8 zkMNzJ`~bU~tMYFp+na>{P^5C?_8i+8W$S$FGxN_)ouUz==z3`262e*ti6I0u=CE@E zWr~XQ*^UQo`z!{qsSOJ&?u);h7=Z=PdPw^vzKXV`SX~kuPDoM@D+d?x$xr=roOu2e zzV`KRVQy{??|t9BstErVfA)FtVGVrZ;~y8_RK)2gP#7BWe*NCYEY?DgD8&5h=k$dV^s$>2Vx8ew_+QX^`wN z!Qm7(V!}f{ZN5D_0P@PxWIzwbun^e%2M;VOKCBF6&fv0omn&a7k*UlHGx5UM%2WrZ zVp;=(IHN%}bh>vHIP@C;A*gi>N0>aKkfw~Twa0Qy3CGP#Tk`g3p7kqom zCm=d3uGPxG)Xz&|Xys2G;+tBL%zj`; zZC^v_Rv-J(kAbyS%px>5*F9x167aS~4M-q^ihnN>5 zaQ^aXImm5!4pkgJvLA;ev3c*i-;SGaI*M1{b(aRJaC13{jgRC5{7%-!^SS6wi98j* z&oI2-4f5vYixQCO+sYw&*Qo0PT{e~p23yX9jvalF&I;8 zB|>X=fbABm@?D(+=yh8tmI7Uuh-&KnZH@qF^^dsHNdjVDiC40wb_a3J^`^wOvshR@ zf+NRo#DT+yB{?a}b*y1&z9R22#5G3`;rekz^8RQ20nYRjHhZ!G)`6 zZ*5>vocQwLCAp6dwk0^pu3SMyUelKZC#yU9r7&c+yEC(+1=1^r)!{E z3jwuT6oxfcG6LeeE%wb!=x{htVhd7tRwbBX>?dL+QyK3YjVSXlpJqgIv;dA$y51l$Tp1^5w@IEGAPNg{TPT8GPN5?yzfY=$H zh+x`xHU*>d2R+t-QoX+*${|kP+IjyPMvh@EG#t4yk0ptAGW6%p&)6WpvDkR^b^U#> zjpXTEePM{tNGt1+u@YtRWX%XMkEwaCy@ksh`OBhSc2mk z*87`SI5LAyx`Ua;s@TdHyX`)z;ydsAn=fJg#0C8RZ~kZa+@E{~>u1-nvV1^?xpmk& ziZt2E7*tctR+5so>dVN9S(wL|T2}J!Rdzu`Xg80Lx2#~Zr&^t+I(QHoWi~NjP1*NL z4eUR55Os+ID&j9Uc6P8M-`kfi1KT^~$Hk!o`|y%$4&nAYZpHG^1K8>B>dYMjYj!}= zvCTGk0=v-7vwGO2CVL}Ch~PSFDt8cAfzl99i54%oU*pgUzOh545N4$D4rz83ejVtH z)kv8%S<|Jxa@_^_0p|e2u&!~&sWVUFXAk}m^^+v z(|@S}@!Njw9oWBc7+?R&cX9f;^BAnRQI?pZ-`d8^OjBX$ZLx9OJ(bFg?yV$=6pA|> zt!c13Rx&2CL00r0$i~RzG>Sg*=jsn`i3#5|DqC6)bu z@h^X0VPp?I^bmTjp7`XN3iz@^&*B(^{F20zyK)WHqQos!c4s0aiB4ahQ&EyoCYOG{ zhXF+$cQxjuej9}d$&jTTWXRrNp)GQOd*&GFQth4P9Z3f587%M*_2iaZ@||cBlICzI z)BcD_!<*R|v#x=WIq*JH)eRZjdn+kU?0%Qxf_<2-h#zn$P5J&&o?x)+WV$dV2f?%? zNm(m3k#g_PgeWzpwOG4QQwazrLddzDbkHep>wk3tG~JVc=^8T6e@~? zgrjNn_{J9|Aa-D(VpirL2d0Rryz_zKthE|l$Q@tm*r9v^!UZ7xt2g*Q0U-n{E)G#- z@Fd1!B*u*gh6@$BmR9J7^*rVgQ+)G$A3CO>D8{c;c0-JQoh;PmJ!_%WRj1gRwaP}K z35W``v9L*&q5*@WrX(P&oNl3?^&|mV6+_ihZH3e)AjDM5r+4M>mSp4A$lo5bDkP4m zovJ`xP!|KgG>2ich@H(b=8xVWKU+qyx{2M@Q|NDOBkLJ;EoV^5MdF={;!k?$k9Xwn zV^r#_gm2-}#Z$5mdYGvf@wzwOjyJve4OpC=#cN*m3M|ddS{uF)=iCNvN9cb~u!_!= zdNP?`5p2T~V89a&`?Mv4=X1!b`l;Xe6ZST(g1euyWl1I}YI2ms(cO02%XHZA%(=_z z^iDi~8c#oSLY{vg+p@m>E@u>WB-xOa9S^knKIUK_1H>THidyO@5EZr(7|cPTH9Z4+ z_ryrWgCZ`iKaWdmJ>0NE@x<`M@Q|+8`b~%D&J78+LteyZJiQ>Wesh_y)9h@5AbM zo>6ubLP6L$qLXD39L213@ho;^y~T)QQ^yI2Ff|WEYVM>Gt_}WtlVvD zuVf0$hqK5*xKdG+G#-}LR(%p-0fkP5I6bUthOe(KnY#Km?Vka>`M|aK{SaC!epRx zMdNYb7*euH0>Yw0f&A?p%x_e*`;x+jh)uOt-kZNq5{SeS5EI!o_!t@7GSXLOvR-M= z1SY|mqK-J(jwT@5<|ov~553dYsM0z+B_j=@O2vXCmSr0X9i{55Q>O2GIu^^jHGooUZ3D z4t)X?89XGL`Zrjhms3wp4bj{0WK)O5AQ6cZMVkcs;Z!nV$bjiNl4(bsMaa9_djt@D zGKA0qpd5DgVhEV&W<^dgkiSuIFk{m|JKJuScv`TLdA#>1}aO{F6pE!lqrE$R$llM?XV7>Y}DO}5Pge&613St{m6vY=M zPxVo57F73QcCLw**y7jUbvKF)%xtO34=zC*(;8*sR(x&Q)cs8ne?$Nb&wA_Pt~g^Nj-b z?O(+DMgwO_q$Gh`TW+m?<}xmvzJ#miuj1nQO*Ho{DPas}h7?LYWD+n|IE?c1g*LOJ z^tp+vT+9CvTE(GfRixMWBeOU{q1l-Rp&AgAA(Os^1prszqW$2##YHPzY8g~#XKh}D zk_o-emTE56*aeZ-^g5x=Bp$hD1s{I@Z{csh@K^ZUXa5>+c+;=pkN^0O@!7xnQ~dd7 zKaKaj@1yv`Kl&8@^gsSPeC_LBz-wRiCcO6p@4zEJdkhc$M8Qbla1 z_yg{_QYq5Fo(W62R>HgAeJ?h*H}K;h{RCORi%^me-XBo|CECl8&1uk{&sP?)+rOYi zq7YS$#h6sGdsc`d&l#obtpPuUIF)=R%^RS0x(#}5@kpS1JmI`xh#b<$Yd7}6%&{xF zu9lvW!c>9Y7$vEDqQ!Ao0%HOHPz%}l+=n|`foITTXVuYQvruFmkV!0_>qaTd*2u-X z4&v?vZ4m%pK%l=EyP#7Qv5|t**zgipq~yMhR1k3jzna*`Y%=4MC3|9xywed(3P96& zK;}_G3d{7J6^qAHg_ZkH;W&k#fygY_XC=+ITIoQN#J}-$=VM}&C;x5+KHT$aYcZ$V zniXSKkP9kgCVHk~G%(DxQX+<~b?4_Mto>b5y@N^R&Ze}Rc7By#IF^4gb;Em#XQL6f~y6FwSY1g9( zNNDpc>W~xT<7Y*ZRadP{lAT5lCdOn9X=t@1ibrZ>hom|cgUNwdR(}!|v5|wDX_*zn zs47pYs54P533%hqPy~^n6z`l)JZ@&dM+-7CXcM~*E(H@N)jfqg63FWx-M(NrX47PwALZ1d1! z{ksGv_jWi?fMkBZ8V$0xtgo)(^vPe~$f0@JAGe`gDmgZ`%n>f&|KrOmlX~jVU$Kb4 zV*X1jE{^&$by#Rs9gSUr55v%Np{VxDTiLfLd!$UQkzH(U?AZEJun`444|--*tZ<|i zEu;hemK;SjOyY5%%x$0^i0rdUUDm#O0Er|oy%uMfN^(|Yod&yd);gN>XX1cTYRRx8 zM|jEN5XJd96L}0wq)r_zTiLGp%40*40_qzmo>=xP$;2%ZBcp@dd(k?MMSVsit#xqj zWx!T@kL~(Q6A%p!i^e)t4NXgk1kyTS>&crY<38V8>%zD`hCB$Mg zBOW_v9#Hg{I!ntnU2}YRR5BN%%QU#CfUJ1cs z#XGTt8QC-h%O4!;6e$~zufC-gH24I<=4r-Lzv!S?(;W~`H|Zf;xk7MgaJkUUz61d< zU21WVC=*VaB8Zs&eO_0wIQ3bs#~XOMci)kj{@j9Hk56dyC8jfFgRGuSEwk$xk0$St zn}w-)9seA2au`h3)62Ez71r26!n_yfdz(GX*UVol_o2_Z_}nrF-_!kBCJ(OdQT|>< zerK>DYca;#e*43iot;IeGQh*%{VDFc>6K_m68!zIeH)!tN4uEqY!~-_;Gbbx0@v-< zHopDMZ{f=MOA56iQ`Uf+s#v!5FPlz6;Fw_b^0{`g&6Kj3NBdBs=qY_;O@iI!66%NQ zm_OFQ+uwK_4z5JFx(@vOrxiKJo9J#5P9^@hOC&@U=T2_mve^XcX#DI`-$pp z3`e_K#Lyy3!Pbolx5BKsH)M|&{zs|UkZbK}d{Zn}oOo!eT2dixapoD_Sl}2c)w7KNSRk&2k1%ry$fWC+=10ka z%JaF**nFyS{ zcW&V|i@a}7RsMlpj?8snb>_nz`7rcdTVLqh+u4Tugv=E;{M?a8V0h^aGrPXC8cjOU zns}Jq3d1zNe`R&ejAB^J%Y>h$uEIl+xJI?62ZdkBINJlini&7-iqM4rD#wKFG53K| zjFKyxEw`{pCEu#j)}~5xm?+P*YWl(2^{LPFLSy10&R!2R2d6od6FB^>X9EeMy$o1W zGa!nDa+Ceq7F1ZS4K|0$f>lua$xNB^B|7{RS@%PgW^*=y$W<>KuqZMXEe=DcWKrS6 zak?jgZ=<;cM7txUiE&~C#d#ABND=Ne;%1N_Bpxq`p=!!&LuI)tOCU5>dPL$$<)CnF zBCTUghYxN>@B5u|Z({5fAxGIKK zbvZQ1qe=SQTVHmq1dNHYMLoRC_HuyJr%%iGS+uscb&!29h_zy??-z&4Ql>&{?lUyN zahfiCzSY?#R`ws3&naPMRt)N33+K<6__6Yv} zf4yM2J;PYe{q3MA)486X3{gdAwyPy(edwV_aO&jqAbson{H$WRNmopzUF$m9K(cDs zFu1^iR@`H8@D-(t=IM;lCpJ9Y#CZD*8nPD);yfu8P_0^LswXyJ`^puh@}0;TnwNEp zvl4cB9w;I;Ta?!`aImhn65OPYRfy~-y`c(Z>BXyHU!afuI!icY!&6oKBdv-eyCQ< zs5YypE{QFvmvmNQTh4Yx0{n)oM>HO2BEqU3lXiB4d>15^=TcB2f&vm!H&Zl}f>oZu zNFS2?u4*9IFnW~v>T|)twJ7*S`s8KV!?8lINTd+OHm9Y9BtmooW%*ED7q*Q?k{FR) zN2}Z1+tr$$F;0r<)lK%U}{%fjemS*|< zhQY2p^updR@j58(ba^2|53P#DCR@ke&&{|Q5HB96>`cB(l)zH}=cmzEOg(+D3L#p+ znK`OZ3m_~B38oS#g;ix9ZaL{tc?7l=_#DlA;DUur{+m(1`)bCg!N1kJapA%P=m}8XK*=5I?#ny6aq#22_h88W@3k`C% z+ge2`K0fWqnUZ^MF73mxIK=9OEBNX^d{Z?(KKj9rylj zL~L|_hzeOM#}Y@S*7@Mf6wd<}oI~-o*)m@DhBxBNU;77?Dly*n>u=YDoU;{tU3;e| z=|oAp8I^j?_Nx5u-FM%GAN=HpSlir2z!_VjR2aOG`nbfntE6)DWSIbI3vBWIQsLjD!=eO~>hNq&QRIS>7=<-KxNG{#xQ=uM8amO_I0p6|1c6uF!%u2|{Qnsb?_`Ejdw< zm<+k|V+Vv4^n`|@T-0i=w#{i&ST-J+>i3WjA(NnVv>?keCwqOMa~?4jtm)tsPnVjI zT)?2PfoSd!mJeQoa&r#7A*l!lD)6VwGo_j?3B{{9?=V}NL)0B(x0fouK1ycMD9)l@ zUPQIDgQZ0Yv^!0-H`-XgcnVu%?LQJBpd%;)Z0+*SG zrXAon@FW-xtu6a2_D6_pYNw=o5|ll!%^m;L3-TXXSHKuHe9N>r=>nvNJ1@ElB!%fn zbGk4)gV&3JiPMsh#+HzlE``E6a}ZX!6G-$HUF9G#-sns2cO21PdtaO-S=ZW z^2jsTZF9DXVp)B8t|gQipfaFRrQEWd89JC*9o7rbk~6U?iL(T>N!u{z@?o8%gRpxM z)!~XbtU7vx8uYrd@8w!{*3m!rEc#d1wM#Nns7a!-Bxfnrs#@4jRp3j7&kb>@g~YT! zmc)*gN7J_eVF?o4RmxQqY7yc_K?|=VC!99S>}AUM%^!#Z3@ee&h9-%1N3D7uI*LiM zf+eaQGGs#ED4}s^34?~LN283{{WEA3X3$$)LfVzULaT6ziYV4=%gDqb2Xc?qZVz<{ zJmOJT&aPp7hZ1a%EI}(incJy!R+5PJxvwb7DZxjYEAR%EaIj)0?-OaOJXIUx+xf)n zr;>mqa-L~7jV&!!T2gAZFrZ|6oP(Mg7-hyBn2dVL3a2<>@vj4%=L5UkkEFn9_`rM=815G<}2%U>MOOemO|3{@ux z&Iaz;`JvGQN9>~I(8DliY4QW)gzZfES9pB0{zm55YWxs+PIDdR35dZiUz~vW-$|2j z;&feiz>9J59!Vu`AD-s3h*~0WcsxJ2>N_3=J@zw@ks~6DjV))2vC^n-Gb7m1ZoPTL zF!V$EfzkB31o#5I`K7g65M8(Uzo$r#=6=vrQVnG zedhcbEFE4(eSQYVt~-wGIMrF`=c?!rDX5v?aQT3qv64y$7%2&h3M6>ox+%T11g}g` zdJ^n+iCkE$VpbBI14l}_3Y=>uP9iHt5^UE|sWp++Tvu=)dvp|`(;aG8nKKm;h4fOh zBQZs36Pt6=nTJB;bUzaH@#RLt!Mqb4nvaW2jtW{()T*}Od5yX{DcJtyoGHbi$2P;K zqJuEBi51ui3I(E7Zr0{yEl3zs(GEp>tFM1n#K*VA)_(DGUzDWcGT!#icc4Dgz=OZ| zA^z9@@qfcde(Mvs?Uvi|@BXiUjsN+7`d{#`{;U5MM-IOP-}w4>@W20`{~8~9|A+8L z|LPC%SAYH&Sif>rNh<2)2DY{~5RS{*{aBaxr%#ndG*o;OJT9-o$4_cr%G>gK?X{()bt`G24AQ*1$ zO5^He0(RF#qL>S-t4&E=utZc5lZn*TbJb{C!B+p5P64_-hX<_Vp$)evoWNMa%+1M# z3g?;#>w4cX&82Ve&%&06)2m=(9>+MFnJNobqSN;r`1aV>%sHQ&fMhE9cyS<lPL`$^+MQXh;3M$fyY>fiA?cXAu`z%Hd#M; zDgkk(od29CBaL0xSayq20hen|4ACCwV9?c;KU=9xaCB;4MYRIeD$z~I1SGLplSrI4 z6OfeEyVwGPFbkbSb5Jraws?mzp(W*_gR><%&q0_&=$JBwyW0{=?UQifCi%=6F{;}b z#XCq#R7oAl0ZonXn?v%fN{7pc_Fs?vx7~?sW)@pn58c)Pg>h4>PUXc0X|Az;RUG*G z28yH#q`*;V6`XWjR*|7nwu@pG^FL{4EfhkpJjo_y*#JpT9-sx`7I0rJ+)whlxS z?!)d^MEtKfwt^&i)XOQ#pEEP_DwcTp%2`Q3dOG{DFyFxS*BrRu$O`HK$Ot`Fxa@%f- zgMUtbz9EV2wj}SV(oOf%5=O;Ch!?KIjjw(yHU}wIx2}jo?PFGcfBVcCB$uutoH>H> z@z-Pa`rDC6kiR8?Okv*w;w1@6BIBed?Qq5*vhS1xY4{5gHkQR1RYR2K#a7g1m(?Y? zC>i0^*a@`-3;@Ow%ydbsJHlYCgVDNd+Ah~j&Vks1vD&#%yLe-EKxPU`Zc~=UtB4Kg z@9dy0iRJQ**C3%NXQz+B)-Foq_3!SYJRf0hM(+926>L5IB(NpxFlftn2Ng1_jXPR} z8)^q6F|*6+9i4{Qgb^zql0?OYs&$1E3-A??CD+v5-PFJ?a+(jUsHN~ukyXQkI`9~T zZKX%fBq>y?;B2Ipk<2HP1Oz(V&g7U*kk6B}+Zv?0Sq+Mz`2kvfp3ZLM0)LJ^H=HCQ zna*lhWju8(SQZEyMQ};&_rQ^ExY`AL7scCD^BMmSdv6wH*;$fgl*IND15B=D0-CbQ}uX1CXGL{RBEkFVZ%>oGx zfDl4+N}0-3W-5o6Bkp{L-rwH)Klf&WS9QO*yKTo>NurF1d(S=R|M$O#Z>YFROhi)X zsIQ!?N*O=$ac+Qdr$1F=t;xwpRXfB1vpoqB9#6E#`=C6JC^nsZue1d+y3U}l^&xwMZeZ?kRsFcNk!doU}b<60eFp7~EAjav? zW?Af<%2JgkM3;PAT=KtIY^OaZvDeEY#6C~1uo*g8+j$#0JC%|H!l#mQN*rfqlFL7t zoy8HSq)F3?%Nn0kU$O81=HLAHk{EX-e$L{a@86GSAAd?42^CHOqyVTjWqsF1`1o&r z06g`8!#GIyGSW2>S8FQit8ptyv9Wei*H(*?zs0nD?n+-doz(`X zgc85@?#72c`T==#U3~j{-$K1PgX^zeee9gxi;ffsNu7<|k$Id{teZcO&r~EMOi3(#&-L%Z zYc9D!{yW9bpL`NOdh{{%b>UdLE;(2#v7Jo{`l50FaT3x!c?zxFrcTym{OI9q+tco<|)&{mIYd>|V#P+m(W^ZpEQO-PlyyG@cpZtEwhg z_j7ch76&S2&grl^lu6!}O!>6AS{CJmHW76~FOk78sO)73($%(465j{aQd-;i9hpMw zmCUX|Bhf-VhMRz^l=R5exY9B%#oAmA1&9&I*`cFxvCjSqBdM#4d}JzUG^jNay89ck zfX$5zt_oT#;0lzYAmizpDw>p=f}WA(Gv&qV zDdEMAzMA6atK)I4@~5Z_l}%`=hl~c}uI%^?&q^=@5TtN&a6;*^%<#prF{lbB#e_;K ziUahZP|QUV1@*b1lBEkOPetb zyfHE9I_Au^3#d1c)gQen67#W8+$FEmIRS(l(OolF{pV1CSmn$lJ#%%Dh$J{xwj*;R zj!6b4#E17o0$eIVVyc=b#AzVGA|rmgnp)vRjsuk%^s~w$lMPvE&!9d%kD+X?{?d{f zGL10JWvS2;eOx1}f@#P^a_DemWL-!yIN(G@5|(PZiAr`t4uog1bo_bw`7SPd!|U+= z_rD+SeAiXjvv+4GsZo<4VFwP$+VVcc*jF6(>$v2xQP`OOVLkbv-VoqclMQBR@P)O!k=g~!iE_CmdVmZdf&Bslow~hz=(Pq4AuXE|FO7jJKlcf6}a%ii*f$> z=i}(nV^WAbtr*$Ua(}7UKGJniMUBN|Vp4X69NwpnAJ(L5VWuVbYri_C?>%Q1-gN2f zu_!0oYcG5)_DK-e+8{USU*4&H)>GrJB(6;CoykvEDY2$!`1ch4Swb!USnbLBJbFkwFAcdr zJ0wXyJz7Gx9;18YCCu*FF9qbhe6%5kts1ihr0i_-9;h?+&;qwSFG3?~O+p}{122P6 z#flW60&h-p$%+%?2+@&(C*=f24k->Exvw;^v+>A8O`dB;KOn*eeVG zsFdTA1i}de&Nm|zAk94Kb&_H3UMQ-BR8gKt#Ke);8HLVuuI-#$#WZZHq9oSBFwSb| z$iGQuuC>be$ZOPuoxC#-#bcwZtfUfzVMOG-H{0KVh@D$PpPLMDwH_<^Jv(CS zzB?AUO79gGiwa{+EqOS*%4N{vQmoK3^yHkh<4_%*f4od17MhpuC?uWhN`)l7KdR1;)Pxo;-NuOON_ey{sbgT zjdSgNxjqXIs4Dk6;V)p&ZIuvp@QCZQ4Y6 z9fzNLL0+O|FeQZ@jnI{(mWp{df9>noxo;=723;&4Jg5RTy`!gOZ_XiZ%*iFmp3Nkd zb}~&O3wgablY2cPoJOv3;05u>7A+MJbHYTKD9bsRRJX7;yNO%=;(om5wfk}UWEU^| z;t0CSLq$bVX1CFtHNbFQs3C4|t0PJEv~oX2ot`Q~k!v>6Vj`vEJQs}y8;zrnW?u#@i#_@jgne{teDGauu+uOjXJH)ny zsunQo8(SLBx~EQ}y<-=aPi^7WZ+#!vec)<*;d8%(+rImKeC=z0g^%2L9e($BzJzal z^A_B4+jsEpYp%lwKk{KbaNqs-)_1>+_q^+B^$(e8P2r*Y9>KQhT?&QW=&eZ%uBb-| zA9>aH3Ma7iRAS;ur}8`RxC<{FI7egdfv28yDPnncT38Ge05IrwU$f7CY|T*WY4%`q6!XgcY2x%J7kF?j4XDJ z{hh`fYAaqc<&hFuRMP1@3|9)TkP=td2)NZa4&z@}Lpi(q>dBr#7!v;wrUqc6cxU1x zTwJWmD$pPvo75N+GPw45ZXID=8+y}6n)owlktdQd04q_^l#a~VF%TLH7b~3TR$+Wo z!gyMhjN)qfnN%@H0tJ--xW6MRQ*k53?tnYY^#8|sc!x+;D5}J`689K!VN~>E$2QQi z?rRhRdaUF$D$Q`BGN7VRp6R$cFS?3JS2#;DWAhtTagb`iGDKP(>SnG#w~UH+|wG_^mH~L7z!EF7xMU&#clgK=6=-15+UalTAwS)w9N_@F_H0+xk=?s@;vMh25|>_j2`;(h5*_)M*AY&9 zHI1_kTZ^sZk@<{BO_jLoeG zYg-A9pB~}h@eRCmbP2~#oWSy{4Xk%|;q=iBY)bN9Ye}FRY-)Z`r|WduwazHV0Gx90 zI%6qJXrQOCu1wE#b}jku@o+}g*Sr=AYD`Gep;$`cNYeB}vLe{e>WKH(j($fd= z?q9nGkDPo-4w)^ay%luiI(E-rifwXWo?Kr>F;kZ!TMFJ9c^(0mZU&@;c(D;NicAM# z#6z84mP5M@#z!yQTEX~AmJh%^u>3zywJGv-fDI~gMh8{zXQWAS7+EHZc% zg)aufo$wp;qXVC-}tLt7LC#JLC-Bcw`Nx+!JItXT@Vs5!>$J z$iGqv{EI-|jwe1xt_Nc^HW-8z3btYO1W77xabe9gJwU!jwi`adNyjjUY z$^P5WMk4fFSH5wd1yq7YOJYc^hExKZ#(H`0J_Q(hL-k_Hqdr!PWo*t$OnUYio&xBe z-on-^OGr;{=-$ZWdTQJoc~w0qVslNF>&&bN-ss>b*$>qJF z|4<_~9Dk$BQ1&%7vPGD|L+7CX85 zEcCXP6v8^+Zs?g6V+QG_tnqdWt0z17-nZ|=wb#EJH{9@1{QRlMaqqqN;`tY!!)Jc; zvv}Z#58(CIzlH7*F%g8o1BzDE(Z&`vUI$(Vckd<>#>P zq8<3m7e1=Zjm@=9IjdV5Gs(x}u|`1S>i>s9 zpVSY?IDHj|$La6Dc%#ax%1sf$e40Gpj5583jPFtOe9~f*l0x=F9vtEGkrp62r4De; ztY(uqjgwp-Te^noam)F~u>nLgH$x=9+Vg++^o0{6snhKmjKxt(_aT`vwHG~ufiLchwlsCX!ywcGoRa#<^ z$1dP!jk0|NUX5K1!>!gM9X*eIJyd>-NxWi$D`QfuSA?pMoSST~cHz9s7P>B`eI6;C zDN?s%`%r<7Lo9GyoOx}bA}gIff1T{FvYw;A5l*u1d5qL7==JJ4i#rf2V|8F!Q4yH5YCD7E^$AR+T8Rv#HYm#KKE#Ds%E0{{x5O)rvyYVbm4?l)v zbOKkr`EB^r$3KF%y!kD94>BLWjZb~+c%GHwpYio~AhCYM5B)!9U;p2F?O*Xr#ozI* zF_gnTBgfeR@6N|Xm+=pM=mU81#TRk%GUREc=;3#99+fGlOsv!>o~Ph;Pl22y#d{`_aa%CLu1&MVkNO7MmnY49Ot44;djjn4~WvRKh+j64@9XP8+d96ZS$!#5~~o@=?ujkOyQ`60~!hw;%Cy>UO1N#mqE3ZK{ib}mWe&sK|6 zSGy|woaKIqU8bH{dhR0mw$!RdC?(97&=P%3)9K^25z-Wq~gs@iN6&lnge;MErs}2IQ6ZV%qlz7QI%?VeQXSPUJ&j{fp6ob zMZ(&i&{hh4NKZW5ke z^~uTl`i2%wmBdW@=(WK$y?VNfJ8%C1u2{JYZ+q8Uu)cH*2M@o1|MVaK7@zy%=T##4 z+u!_#{M;#g_S2uj{8STP`_n&1Z*vQuzUeb~yTqFx{P0m!W}Db#6DIGY*{n(Y?r6hy zp}ij)oek{0a1T~DPibK^SUQb{oHDU`0RYL8RRZ59r6{n6WFq-Y&I2MBj#V~4R;{d!_& zJsE#j^9C9|!cAl|4-IKN4rtz^Oeu7zQ5d|tl;H*LSXy)$jmfxnP_;r>jM`wZmqk)lh%~&M!59H(*C9Bj-_ExIixYBUrsmNFXOz+3hUTtIK?C*9@|t2V+1YJxn^j%zE!kMz zQ)@^DB(}BCC;MFPVZA8_$mS6&L@S6-Kab(@pCVs*66fz};d7t+9De`zf4@w^^_~~* z77mX|Z zxP=j03tz**ppm@{BB^_-v0?^%=@t#MbF9dLbCM3{r#JBO@hu!W-oweY7{^v5l;tgX zorb<|ElJU!#B6s3y;IMl^Zebw=3z<7S5T9HSCfE}6-^A|ZSp${vJc1ynL$0OYcOZ$ zlf};{shPBPdQ$$JmYa4$u4+jxeH}FK$P)7uU;uA&-wy`rL`-posvHdS`!2$fW3nzc z=78-NVET$TqjBCj=q^kHJLeED%%Zx@5=m929A>4LMB%DMISVlw9MvNA{otfSBC`B@ zS~{fjAYhP8sOL^jBaL=DhQuQ0pi78nY-4VXFMNF->@_pvt89*t%ArXtd7B~vi*;oIMBaz@@Qvc$oke>84y# z$K+diKvrf@t2E7nfKulJGXabz63)rBoOvs1Qk=vZJcUy&T@Kb`FqMtCZ#o;B`nd>e zV=Ompu^VkBap@bxFNIu@w4X|nMmJ+7bbjC~sgsjKpK4bzCdupGJ>xux9Kta9PYzG= zrV%@Vp<$H=$C_2n(Up>{Q2fR}tb~>8h--Ms=0fY^t-W z`oZw`8LZgEPH%vl2EU4IMP*Q!Xpj z{Wt*_Y$!Km-+7Dp;^#kxZf^}=`Rbpm7{6ZQr>C$B(^&fAM=?#_sJq@E`vD zA7db&^@AV$7|uEGBK+mozlkF+JTLdBWA}_IPEzbF?mZu$|Ke|&V2%9KUw`v!ICS7? zk6|R?Pb1x=EVsFH6AD$6&(!4pYf2fgBSz!G?Kt->ufqke*@fTz^cC1CsnLqW?ZZcb zTW@Ds`hZ@mcnF4~0`4<5jcH+%voUR{!ctbqsay$1&l zJY_IdDgd&hm$>Y-JQv$bL*-`Z^U&%evh}Ble+?z(A`1J*_gWq>MVX)7-dG9d+nE~x z>;5(VhyE#s<9MMlXKX}h`(WIT)E@RAim)P|%oMAnbLCO|93wgDS-hrvvO( zIY%T8HuQN>j?>i5oTF1#s=BMIE7E*oSzH<{qRIn)lb80qvJs^^`Dne#6}+Sr4YO-VTV zc9>PBV@%K1b(^d&ts+}bC7Gnld7*N7bXBhBtEg?gjLO;poP6S5bPqm;^UrPK#t&YD zn{K)ZS6_X#J>5K*Q2yii;#%h)b8C%%slb}NAK~Zpi5J0(W_+)Rzb&U~UbOJ*4D+^9 zYkRz-lF;M~cz0K~>M^O5;Qq?`DxN=f5(iIh;6x`wKazunW`45923=VnPC@0R6oRy!l3T}?@-R!`&f^G{*0bQ~=?WGWI@ zT7=8#1VCa9g)Y)upEc8GwdJVD8X*at>UAvsRiMKSU6~-0o5nv92VHN^xOG}m&`r4I z9G#{Y0CG|%geGjM9B47Jq&6YEL;X)WCdHdsS3HT@@(f!xT34gOktSA(4W96I(zQP^ z1<}qrJ7QJql;uU}@&~^pX#B6q1F1(h)zej z9->j^gv?6S3lQj(>&yZqo{&SaYiQK%e9B8mQy^P<(x8^oe(prpWGdXqun5Xl044yH zc3(XA2=w^Scq{jL5QE5*5(;d;n@_l*pDlH7g-4L0=kMx-9Y(ItCq5Va(^iyF>M)Cm zCRpJG4TToMXDDM9QpbB2dPWtl`eSEswTw{|1SmZD2r!L6&Nsy`Ip65#rJp}c`1s!q z<%gN*Nv2Z)l4=#+k~yh6s_E}0F3-u%aPEp=g(v*lXi!*}#8jQi@?OjSAooLJ91Hmd zC$Ca~(D08CQck~&gOe!ya_G;O#Ry-E+(m_mQ022$$9g|EseC5Pu}u(au^XQj2AQ?% zNwoOQeNdeiPRvzt90JLk&ixETW5&QtuParEc~jSxhnj@KXOtFwpJ^abL6Bf2KmhO5iWb{TX4bouf?~&bsIi#{fDt*al3LZI^7NR z=+ZfbydDjK(|$OM4Ys7uB;>c88fIoN6O{#sP5gpOc|MGMKW7Ge@_aU!X;T$!ENxxr zB)sqfqwt1+smcYYF>Es66B2ENYrX3ViMrWFx;}J5lKVumum*>^x+`?mVoVl1q>zuN z6mX6Q*8|d$dZBNfM`iwNF6LROxM#m_Q=Z6GVtFPPPPYiJsrw?RnvF)f$NRmGoG}@G z{>1&(_sDE*S1|EKxQ~sGP!=G86`vWiru;A_Cnmqs-SnVt7n*qIF`-PK78zBQ@{6^I zOf|4%anMC7G#IGscw~;@E)S%g_u8nYke7f>3qiLe$^Vn~3g zNl+NNt~S*hx;?W7(g$nfOZ}Wq_A6Y&IXJr0D6q=IJ4sEo%MD&Ei2B{3@|6}KRR1zZ zR$}CNpeF8;oDDm&A((IUFo?HQNrJ{@{bWj?Dsl~@p1f9{CTLYPTh z^g}x&60C@;<;3IZlS{bosUvuCDaBegjjUS1x@6~hlIqw#-;g!2-q%CFF|&w#c206r zIf$j0$Txaw#8>5-9z|xMK_$25A{O>vj-ebngYGK&`AJ#Zed@DFu#f~H+tTr~n#tu9 zNH7CXJrG7!O#)S(SCWmSXeo)kP)^Fw0xhKm<#$)N)(uNrk+n<{tNNV${4Cn%?Ztd! zC)O!r*=l36U;#BkXC&*E`)SnF28*8mE@7?Dq%hc}5~k~gc8Rh|YKCC!kXP--5-LVM zo5IIA05%j8Bw=i!nT|^t}?3(`b=^-h0C+C zY6&45NmrgpM_!%xzip)CxFdf{Os>cu5bsX8$%=vpDq4_r)M1?kk-kTzt5A(vVq{{9 zGw|;uAFokemioW0uoPmeCQ<`Gm_pMlvSiJ@EUFT#8nvdHbuxx)@t*l}$t}UPrtsKj zL<=uf!jk)~ou#ydU}=|LC(_0NEFoB)yj$X6*J#P!dU?PWlbyj*iE7LZDT3a99HtLe z0E{&(f@ZPJ_GZ$mU5Dyf_U;z@v z(`c%~(YmVZar!|R6~!XLRGQaC34At?him|Hy+n5IGbyOm8qR5f@i5dNEi3(1ct6M$ z;LjA1O~kT5!iCK->i$fkw5ElMhHk=m@~-kYs#<6#o?zNEN}bacj?%?c#g)kzKTEmY zVaZ8I)4ua~O!+EOSZ8iZNr}YiW(B90Pht1YJ-F`1Yq96NJ-Fk$_o_HUf4Qe(HNDND zP9hnLhdtGH(nP#IHI1VOU&1#}-+~)H{!x7KvtPu$4?cju{OVugy}y19KJ>v4;@jWu z;sN=$PQQbX-}F&D_}EWz|HJpvI;@sOj8P^3wG|s6Y~6C zv-fk@B!7)r4bZI?oKX`oG=cDs!&PK#v`kdxV%p2EV;9s2yKWVx}vjPB}L7MltQHeUU zWCn?vFcPfPtN__qU!Oby#}kv#JD%{Mh@#0Ujk`i>C(BPq5(aBS#h(?bU?qnw6*{8S zZ`ime9eK~pooei}#P(UL#3?324RG178WbdncQb418KRd>2-%36WncveJq@TC+8(L{ zHwi_#EGlj;9Yxa%M5^y$x~3ZzB%s&ZG?SIMlVf##Qx!lI{#7B#ucija-K`FKR1)du zQnZ)`c4vJBozpMLVYh^6<9V#S`~;@rO}zWcH{c7O`wZUmo@>+tCUpAwH@hlKrvD)q z9{ie|e1y$8IklLCP6cRIsf!JqQJhTPKa&6*PfPx;`{?TZ?u7u93Rg}(qmtUX{K$c0 zT|9AU3omc9B!QpC%(inekVB+8P31O8*aw?9HC)mzKkN9}-3`>Y1I^7EhAd_VTk3-o zt9e>W*E5%Xv$+@3doPp1^)&KVRT&6{?slX(3G4a!OUxfH0=hHs-W5!{&mH z63{ic5t9gFoQhSK5gcJ=eqQmxkm95^+eXr!Lv!ba$l80bZQrF>UY0^!4qO^r6%v0c z4We;l6;N1TFEBmdvgD3Q2n!6loX5t!Qat>W?C)x!Ta(oSCofrKr36jADo*LmLl;6D zBqLXD<2s*o$}W`WqHT7%N3oJ)89?bGo;DLDRSzY0qyv+X>`H;KE^&+aef^YOQb1BS(fr<$YsgDL7C!u)1U0Pn_ohp5JXn2C=UgLo=w4- ze9{3vTw5L>P@X_IucJH{gZ4GNpa|~aC43{Z$1lW@Crg&~vVoS(}vWFr`DwA5F$(D`2=oGks zN{b>8oBF%tK{Dl2#Vt-EKf|O?Fu5u$h+|H-$||`p%?7hde5=TV9|s zV^XTI`?Eyhc_((?11zs-n9`LNK75^Z$~#GXYJ=v1^hIF-q40AOc6r@&1Rt#V8k=&$ zGL&-%<+3=;M!zrLqm_YNhr!8426>Z0r#dr*XP$iuFCBUjpZe5iv3=(*eDy0gqqf*a zZ$)BpbxNm4kt8cSw(rzjWa;#2#IwdBU0GVexBm8ayzfI9-u||$(3S-LM-M-M&CVun z`t)b;%=1s<)?07ItE(&c4f*ftbQ_O7{seCQ-mSRyZCB#=zWfLH>u=nGrKMFo^ur%w z=i(wh`LT~{GX9fCeuAs6z7n0z7Vf(DUMw%ItE>6iN=M^e#(PUn81FepA+z#lPaBKN z`*8f#IlSqjeQ4DS96Nae$4~Te(d%D_Z3`FRnTLLiXYcr-6dQ}!ICTp9&)tDfTz>=R zchBOE`|iZ-;$D2J-*+Cln<{4kZekSwJJE2M%_IUW+{8z-R0KZ~EQuTWp zO~gn2%Ns+fIsmKC2=7mt+iN!Hy_b)y0Aa37_+opyr3WhfeM_|{pj0^tZxXsOc?q4G z#E98w(E6n{U2rto(gK8C1XT<%0dwSYOOye6_cA@-0nl#AL zv9goSLjj_cy25aw^lqRQw{|xqV^3@Kasr~2pO2P!D2CcG3kFkhRn;hJa;WkDbHuAY zR1=UIeQHWZwN4s+BkZgqoT4u4Q-U!6u1LYaYFvUtBEhMyn?T-Q3Xh^8*U&Is?TReS zq(+YexexQ(Fg3e?Mzf7-cZgBT@x^o*H1(H}fX1~N?qB#h zg`1o;Rhj&~QnWy6p%u&Pim;axBSK1|$6RrFt%4{d4%RG@bt!*pIbj!d^QRymp|YVx$WRX9`Gpxd zY!)!H^I~j&&AZTTo`co;PHaYPS=X{gtFn)%_!7z9YRKB2u3$4uw5zFdwpC;5)A5`# zmsCySc)lL%f@Q+~hFYN4yiP*qK|2C|o@rPyffUPQmMOFNS_a$el`Wh60fkea@K zRi0UsXCR>#az6jJgVwX^gd_O-{&+9$Mto^f_szqi?e+1!r9g0!p6qPZVT9ixAr^E|eS# zLJT;`VTU?5;;|*Y6~!s5j=snAsn)dAV(tav({)Z<_;)4on2lg~73+WJiqn_EOFnzm zAprV}@=%*s_3Wk$u{m-3!=Lb}P!hcxfsJ8AHhtg}%wTR6mz_8MNHkG^D10xeOcW1( z#!SS-l6-!K!}{3BFhUTvsEiwA4s9AMQdt3_%2Mut&ik$t5QSbj={t6)MQnwULBMjq zhOxA7a5J{gU%LlpHAmBHNvxIB0ZZ-hMW`9s-YQl@={S)7~j7s@gy5;$a@ZDuldYV z*HUio)|`YA!%vxC*d)W)QFcE~&eRi5iG7LY2NnH{!_g*2X-|D{Y;C&HBli%YhlF9v zpK1k8BA)Vf3sX}fL0ytiPK*==mRGcZF?CW)9u+x4P@0@Qo12?hUR}b?H-8Q9yY71Y z{=fWPeBs7Zo;P_**2a7Tv)guJuHDA1w>^se7f8`0F}^d1ar(q5oI1RM*S+>abPv6X!;c-r zjN~t$`qZcJ;7{(wv7a8pXTJDZeCyUbG3X!A{kOPlH!iyH0`*l|TV2*TQyA?y2Hix>L=OqOps+6RcJjDPavBOs798EK~OHU$A zVq2{#{cjo*ntpXMA;TNK#vUA#xm8eR}SZR@%bfeu1K0W zw^M@Nj1CxjeL2LEO{}h+()HC?+^&x78NC;nXg5-H(?06+k`_pzyD33(Ff{4FYTDG` zu_;TkHoXJWyDmkxwS=|aD$FNR9nwrCU$7BKGS)Xf?Xl@OLsL83s z0;ERn7zgySf7laYvQorm_{NS&?p*EMpAEm*l$_1dY)z9hV;*+7rj@n#*hc7*oAJhJWc@^f@cOKSr84R7^%wvZiZGc zwW=&Hp*X0U;M8cBLxDQ=J_0 zlktAA7?QPHB{n~xb2Uje)6Iw+K|b$%T!1KC0{(Yl&cfA(PoPT)+|=O1kzZ|L5JUCy zh-|W^>Q#gaYg`D2cj3Gk|KoL-DXmSOM`3FlB+NMBi95qP+%p~*48iEp3bxp}i6((> zuq!V>qEK1Kr2ve+Pmq5rc`cyQ$qHFu8L(n#y;`vZf~Qu}-S!wl1+C9_k-+wy%^bnU>gOnlM#Zh~-t~E|j?i zm8B{}EkFkJ6;WP|oP#{a<1JYyQluuv0il274CYFE4#TdNJ0!SrJxrQ3r6iD4?LDe^@I7KxpRS&gfRXOL?LW`PQuG{#u9H>yy zE3$%Kl?ww8V5lM)oDi3Wb%d`*eU<8;YBkLuGz~Dkki@16cdtls#A(LGuX&AJQ;u(b z^Befr^6&i??!NPWJpABKd^YQh+{u}(!fBsYa+BNUS zAN&vh8n=G^oA~ovZpPa$e+Pc|U;iHd_&@$J4j*_?&l@6-7+($_dj-qutGNDyH{hM` z_%(_5sY2Uo?P+u(^ZjYj6`glO68k>Y$7J7DB5J-z?k|+JylF7hf|12=$Y<@}O~%*aQB-m;0#qq9 zU912}N{)vX>gpGgt2Y#(v_UymjSwld9t~CA+Kfb_vbYHnxEh~^gEMlpIOHjL;T({G zUrSUXJnZwk4^V16J(c8znZ@e9XJM=Y9!}A~7}lk6+~1!Z5h|6XJ%eC|FRCY2bt)(2 zH9r8S@s@N3Ia1ff4~9g3;+&CiI@UJ!!l0Z11ZKYkmsBdZnjEYVvC%9@v@_w!dxElJ zV)wwNz=e{}c_8xR5K=UG^Axum3K8$fl(J#PSvcI-Nc5Sypi6+0fYp)&h_ZQf6;;B{ za6)Eql4S3k66?6dYU&bGL5r$Z)u!Q)*_|GC^*Sy1+E|*zK6N}*$yB?pp^k#*bXZ$(<4#mZ_= zHjl{@PA@L#{o*y8KE6uZa$qaRlmw(k?<89NBZ!utz|miPAJwhHxbh7b;9vjVm++3a zy&b#H-G@;9PP+d7V9^JOy3!=nE(svpB?xbq?=1c+^cCouxFuxl|#>A{owN`4!$78&Hy#~3{grmGJXpSkVN*a79bJJv%->Z zDP{=6B8xs(sZL9TB9$Sf^KxJRP6}_=bF!1yFrptqWjpFI8wquZX%a)SH8}>>C5H92 zO4Gzy6Jd6G)#XnoI+XC#A?AW@2N$lodd3b+w z5Z7+ApAA8&D@+~&q=>nDC3kn>BJo1iIe)n|u9CP`CJn(wd_3_dNFtqRzS*9(X@@1G zc~+FgSQ%0$CLpDtMLy=PSW+Ho2X*X65bnF>FTF1iJadgpbvXP%q~dm8EvB1-&E0qMzexOy{eNyE0}ZTqtqms z=6%fMUX6T8gg8v@ENQg~MNQUrqH!o4b>%v{24iMwEqj&4jLMdB{TJl3ZOT&EQfOkm zD!D+Tt6^$4ze-+OT3YcIsz_uQi@Y>L685gqo{z9GTt>ZJ$2sR*gm+y2Aw(UC*Gnhyy>H%vd@DwGu!Ud0;VN8m z#l=|9)@6-!@x)WlVfXI+c=3fpIQGg>YAnlhj6DxabuvMJB^D=za~XoS$G9P20zl*D zcIH#OzD+u~H`As!Em8!BbCqHC{a?7Fx)rhGeHi#>+ECGMT3vr${b1sePf~_D%}}mh z9-0q4=SIo_$?4vX00WFBXb6s=npEV<6K{f#kW^5T164{;YK7`cBaCQHGL)u z{EQOhD|*02RPNwtkBKIEAaY;TnRCR%r_dxoJ?e5f`17uu-6L)HnF5FfK*j9wza`nr zDB>%dbu<|16a`gN65|pvd|lPB-Ljc#>>&1*Q0u*l;o2ej`xN#r&fuL_yaiWYaV2)2 zvmcmfa!!uw{^{%Q;j3`GH@~>=R0g`DF1KVaY<4?1bm#Ql zfF4u5^@UoB)y@{8sVWxafNst;usZ5U4Vt4pH;eV|ItGN2a9ShZCuy4N&@>&`Am}T8 zxyNyHK97a{Z^cS~9esJtx+Y}w1{hl6pajx^cI_iAEULIb zRBP;X)G+97a@2xT$B$#@;$@Ol*z0687o#L1xdar#-yCAJkt!4eED)xm5@EymkS2lb zY%~Q`y9SKs;m+J47ACqM2FvlTYJC!}1q_Ps{^==7BscE9P#j zP$8Oyv70?8R8fk=)1f3!)Wy%U0JBS_AW3x`t$eSvP!qsZp)>{?ilYGSh&4Hmqs+(Z z457LH8L4b(AOvShSk2@a7OF9v`}1_A7B#T5xEg7bC%C|8O4il!8k()-V7tf)@vh*q<#|NRVG>W zob+cxVyDFq;WnHW=c(hf-DN#a+^IWAO}b0@8HBvt6XIxms7Cp?c^}!tTMBAwJvBLI4X%kv&mu0ou5%~ zs?o@F^QQ6{2lT<3pTashSR0bCNYT(Hv6^N;a&|@%Q}WdfRNEEI&1}Q5!$(xC;+%c^ zu(rNpQ?AI&mFdGVq#shJE6cu)bYrB`6jhRwdp_(I7;FvbYU}Dlds%S#n>(dNau5YGcW~59)GZycZ&b9cPaauFVwJ4{rNLsh) zW2Wkxa&4*cQuMwsrq*hTj!0AHMRKPrv3!;RW+dh>9XW!`K>SGg8k>=Pygg*`F!k3chz5LwlyQyA~9TwG={M$DG129uQXdIS`lvl z!Na(!`7T`diJS1_ryj-Kk3NXCdVvr9=1q9!si$!NeRtu6@V@XTmA+YU-Cw!O&s{ev#2LcjghUmivDUBwfchQK{0tC5_kq% z8yHIAM($XBzJ;~5Rn+AS=pH+T7oJ-}a*Sw^7B){D#oDP=d8Sj?v3m#ZyytE_ckF5O zqAuokY{zxiz8_CNa{wRy;D_+oBR|43Pd=gXbo;^_I-61)%JZ3?nb90A7oVr8}O4n2fIa zffQr!J|m^ud765TpOu{K5C=WH5OynPK($Fqg(KjnXyhmwCs#7DHJaLS% z`4-UUBvgWSE*6#_P%cmwUp=lV$0Q1PaA(zps*WaMTReu z$T~74p{u62e6J=4M>AW+)aWz@CttwkvF9+~Eby+ky%E>{`mbY;6d!t~Cm2_)|5Skd z{eLmhOCrZc<|a8=q>_uLc=^a7+)11>T*vaFs;OK#uku2;- zV>^lDJ5iaP!jKSys(F4;p}9z=l}C|FAZ@g(sLacOqdX)}?5M6pN7{^?$ToIfa0R++ z$5rBx$pxikS%gHYk8V2Ybl*1P=c;+-M0M1hXbH@y8Q8Fp;GTEnv#ctFhFx{k<ss4#5ku7_YP$2HPoFx50 zf|;sNyaVA2Y@Dbl~Bbf{x-IR*$u7=P7LJ!b4nA9BI{}??3D?eOSuQ=GLg+khXR$+vG9y_g zkq!Kj1=v8~oHZO>V8<1 z#f&aL<+I8G>z%`5#&yg4$Tb}^pc{5NpNCh{M?Oh3ts}55W_T1d?2xAY7VFhm!$|yxHf}3 z7DbRDHqNDMeyrb$%8} zYYJ04r?LHVN6N?Hbx3N%dHS*o}&4u`_XVJDnFZo5Y1TcRZWVL z`I#v#a+~c%DI|t?@vElf>tDD0itrzh5upUl()P9F_S@?_GR7x2$R^F?lCJs zQq2=p^dQPgHNv2hW-&H%C-i|gS0XK7tN~Fd1d9_gHkspmoLgFxC@rTP%1@OuHP-b# zE>OlII++?YDjD73VP)~*1&YElBdZ$pwTo;*`N|AF&HV5zaVRf>EXQWUe~5m6gL)@^ z8hGv+Mz5Sm*wiBsV+;$LrlHg1MoRiY!ptN0>K>(|t96DVci)Y)tA`04^1Sr%2(G|} z4Oc9FWCwkzN|Y79grN`JzmgmoxE>Cfic5u-FeCBzi6-#7(HLf=Qx3S!Vl+`GIA}bH zU7k@%k2N(hOkCkgN6>E06$hvC!bpt7r?NXjMXP*r>=unjX*?u{!&IF&Ig+J&vHEgV zEP1f^wMh~?m5Dq((&vVw%tQkC{Yqh66L#B%US6g>Ol6y>_fMlSIDz9wevZzuXK~J@ z`*7(cufzWR=h?H!3m5e`OT+%3zW#o`6B<;XLD93EL?4pV!sz>e3v2EFMitnql00+xr@)+Y7eYc|R&l(K zritbtFG}UOOkp~%{*xOghJP#Pp}T?Z>S@&K+ayWvqc8v6kVAwpr<7BZfrRhg0F7;O zE#zqoWUb3JCs}NYN$fbg*i!6j#Tp;sgj_1%q%B9%#2xiZ`05k!Y#8I47GD=+mAVELE8$(;T#B@EH=xNz`US!#F|; z3JnxBW~HGJNVPQ+X;;W5w~-s3#cEzvl$x!=GX|ocBoCj zhswVbJ7|=PQbnCHxR&X8WOB!ngjH<16&$*4@@wrX!lD|ra-`r?Z@SPc?OhLXPMNdJ zI1_nfP@$9uX_#8%maLjfus5lcU7e|Pc@Q@-=xweA?^wQ4j`nKPrU433a{HOn>eLko^$sh>T1<3E}WIY_&qC{9LIdiBH+G62cpK0bu?g zXZn=DiydpMCDv$D!`|`F6doJ2;g*=6mY%7}cp--~Ez`u!iq8`Jt$c=Lyh%`am(vw^ zRPo0eSSDYb`6N6F^jQS;E1TMkCR&6J0d%+cP(8A+)BWT>nJR|9aAmDjvGXY5YEk+5 z*ofrwj{JKpR?^&_nQiP2`m%l~khAaNZP<1GB094FHYKslmWSxJWDQDeJbmI-OfNKa zBDr$AHat{@d?}_g~N#_U)1=%KIqAvs%qZYko(c)edVVthMEkI z;!PC_A^E<)zJb}rX}OIfEY8f~@Y0GVyiF-uc|Tb|EX&U{rleSs-)-&OiJqL1$Bw*$ z8$R+$yn5^u&O3J>o_qQ!`3%pXv$clVY2!E#`h_--`fN;~a1#2^?tNU8Q$F(ni6#i( zSy^cCD;oufmNf$kq~nH$qJU}&lMB;fgIpA0)u?6L1wTt677;&ti@lX z2Ct^l&_*A##X1_jV;C;Kgk*Rc=bpa{H-6-UxcZuRV_G&dZ%I-a9~i&t>mLHi{Qrwz zW4K_1`jmHAbtF&1R;*+Gmk%Gq!w>xk&prEdNywKqZ&-f*1eRZ!Rw!PvDaFB#*P;G~ zHzC`z5B=#mq|$y=^=nzUktD3SjWjU?E~0Z?Pv(2mgQXV~26AYsRS5UDaDn$uVr zcF^2$K3dD?p}TxUJAvA3SLeP>uhR#byd`m43YsY=bu$sGX&R7&|6saFyCm>0H+Z6sI#rTE%cjH87#j+7gjf)_t_nG+j{GC-SmmBOW=afa zVm8!55GbWpBXf#o@-m>SEJZD}8x=rj*4(ioCf9qXom`T0Lp)a%NQsS!Bshr~^O5jt zNo=k@1g3rE$#qg{{pnQ28dT6ES{>^%mtS`|RUY!%YqSc;*yN#!rO&|=^C-BAhrcqE zGLWGu6^yV7gDUWRQW23Ta=!_mXu0APPXo${voKRvi^4?=3WFsueo}~}2$qk`>=4SeZKzpLG7 z@G&Se�$6Fa*?Ro&;ozxP$*s2vB9{D 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�!$5oK1*okxLp=Cj1|cI(jc%`*jn;VPZzn^BB|qX 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 diff --git a/rooter/0splash/splash/files/www/status.html b/rooter/0splash/splash/files/www/status.html deleted file mode 100644 index 930709f..0000000 --- a/rooter/0splash/splash/files/www/status.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - Live Network Status - - - - - - - - - - - - - - - -

                          -
                          ROOter Live Network Status
                          -
                          - -
                          - - - - - - - -
                          Enter your credentials :
                          - -
                          -

                          0 sec
                          - Signal

                          - -
                          -
                          -
                          Strength (%)
                          - - -
                          -
                          -
                          CSQ
                          - - -
                          -
                          -
                          RSSI (dBm)
                          - - -
                          -
                          -
                          RSCP (dBm) RSRP
                          - - -
                          -
                          -
                          ECIO (dB) RSRQ
                          - - -
                          -
                          -
                          - -
                          -

                          Network -

                          - -
                          -
                          -
                          Mode
                          - - -
                          -
                          -
                          MCC
                          - - -
                          -
                          -
                          MNC
                          - - -
                          -
                          -
                          RNC/eNB ID
                          - - - -
                          - -
                          -
                          LAC
                          - - - -
                          -
                          -
                          Cell ID
                          - - -
                          -
                          -
                          Channel
                          - - -
                          -
                          -
                          Bands
                          - - -
                          -
                          -
                          - -
                          -

                          Device -

                          - -
                          -
                          -
                          Modem
                          - - -
                          -
                          -
                          Protocol
                          - - -
                          -
                          -
                          Port
                          - - -
                          -
                          -
                          Temperature
                          - - -
                          -
                          -
                          - -
                          - -
                          - -
                          -
                          M2M Wireless -- Your Wireless Connection
                          -
                          -
                          - - - diff --git a/rooter/0splash/status/Makefile b/rooter/0splash/status/Makefile deleted file mode 100644 index 7bb30c0..0000000 --- a/rooter/0splash/status/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=status -PKG_VERSION:=1.000 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -define Package/status - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Splash Screens - TITLE:=Added scripts for Status Splash screen - PKGARCH:=all -endef - -define Package/status/description - Added scripts for Status Splash screen -endef - - -define Build/Compile -endef - -define Package/status/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,status)) diff --git a/rooter/0splash/status/files/etc/config/splash b/rooter/0splash/status/files/etc/config/splash deleted file mode 100644 index 1d6102f..0000000 --- a/rooter/0splash/status/files/etc/config/splash +++ /dev/null @@ -1,4 +0,0 @@ -config settings 'settings' - option enabled '1' - option full '1' - \ No newline at end of file diff --git a/rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua b/rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua deleted file mode 100644 index 7500383..0000000 --- a/rooter/0splash/status/files/usr/lib/lua/luci/controller/splashset.lua +++ /dev/null @@ -1,11 +0,0 @@ ---[[ -luci-app-argon-config -]]-- - -module("luci.controller.splashset", package.seeall) - -function index() - if nixio.fs.access("/etc/config/splash") then - entry({"admin", "theme", "splashset"}, cbi("splash"), _("Splash Screen"), 71) - end -end diff --git a/rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua b/rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua deleted file mode 100644 index b36dc8b..0000000 --- a/rooter/0splash/status/files/usr/lib/lua/luci/model/cbi/splash.lua +++ /dev/null @@ -1,22 +0,0 @@ -local fs = require "nixio.fs" -local sys = require "luci.sys" -local uci = require "luci.model.uci".cursor() -require("luci.util") -require("luci.model.ipkg") - -local m = Map("splash", translate("Splash Screen"), translate("Enable/disable Splash Screen")) - -m.on_after_save = function(self) - luci.sys.call("/usr/lib/splash/splash.sh &") -end - -gwx = m:section(TypedSection, "settings", translate("Management")) -gwx.anonymous = true - - -bl = gwx:option(ListValue, "enabled", "Enable Splash Screen :"); -bl:value("0", "Disabled") -bl:value("1", "Enabled") -bl.default=0 - -return m \ No newline at end of file diff --git a/rooter/0splash/status/files/usr/lib/splash/check.gif b/rooter/0splash/status/files/usr/lib/splash/check.gif deleted file mode 100644 index 75b945d2553848b8b6f41fe5e24599c0687b8472..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmZ?wbhEHbWMp7unE0RJ|Ns9C3=9Vj8~~DvKUo+V7?>DzfNY>Fh|Ltj$Y2csQN9XW diff --git a/rooter/0splash/status/files/usr/lib/splash/full.gif b/rooter/0splash/status/files/usr/lib/splash/full.gif deleted file mode 100644 index 75b945d2553848b8b6f41fe5e24599c0687b8472..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmZ?wbhEHbWMp7unE0RJ|Ns9C3=9Vj8~~DvKUo+V7?>DzfNY>Fh|Ltj$Y2csQN9XW diff --git a/rooter/0splash/status/files/usr/lib/splash/splash.sh b/rooter/0splash/status/files/usr/lib/splash/splash.sh deleted file mode 100644 index 6b1cca7..0000000 --- a/rooter/0splash/status/files/usr/lib/splash/splash.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -log() { - logger -t "Splash Screen : " "$@" -} - -sleep 5 - -ENB=$(uci get splash.settings.enabled) -FULL=$(uci get splash.settings.full) - -if [ $ENB = "0" ]; then - rm -f /www/splash_files/check.gif - rm -f /www/splash_files/full.gif -else - cp /usr/lib/splash/check.gif /www/splash_files - rm -f /www/splash_files/full.gif - if [ $FULL = "1" ]; then - cp /usr/lib/splash/full.gif /www/splash_files - fi -fi \ No newline at end of file diff --git a/rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css b/rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css deleted file mode 100644 index 5254b92..0000000 --- a/rooter/0splash/status/files/www/luci-static/rooter/css/iconmoon_splash.css +++ /dev/null @@ -1,69 +0,0 @@ -@font-face { - font-family: 'icomoon_splash'; - src: url('../fonts/icomoon_splash.eot?vja16g'); - src: url('../fonts/icomoon_splash.eot?vja16g#iefix') format('embedded-opentype'), - url('../fonts/icomoon_splash.ttf?vja16g') format('truetype'), - url('../fonts/icomoon_splash.woff?vja16g') format('woff'), - url('../fonts/icomoon_splash.svg?vja16g#icomoon_splash') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"], [class*=" icon-"] { - /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'icomoon_splash' !important; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - - /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - - -.icon-power-off:before { - content: "\f011"; -} -.icon-signal:before { - content: "\f012"; -} -.icon-cog:before { - content: "\f013"; -} -.icon-gear:before { - content: "\f013"; -} -.icon-home:before { - content: "\f015"; -} -.icon-exclamation-triangle:before { - content: "\f071"; -} -.icon-warning:before { - content: "\f071"; -} -.icon-comments:before { - content: "\f086"; -} -.icon-hdd-o:before { - content: "\f0a0"; -} -.icon-plug:before { - content: "\f1e6"; -} -.icon-wifi:before { - content: "\f1eb"; -} -.icon-connection:before { - content: "\e91b"; -} -.icon-podcast:before { - content: "\e91c"; -} -.icon-earth:before { - content: "\e9ca"; -} diff --git a/rooter/0splash/status/files/www/luci-static/rooter/css/splash.css b/rooter/0splash/status/files/www/luci-static/rooter/css/splash.css deleted file mode 100644 index bafcc6c..0000000 --- a/rooter/0splash/status/files/www/luci-static/rooter/css/splash.css +++ /dev/null @@ -1,311 +0,0 @@ -/* @override http://src.dev.lo.lo/ROOter/www/luci-static/rooter/css/splash.css */ - -/* - CSS for ROOter splash pages - Copyright Francois Dechery - https://github.com/soif -*/ - -/* @group Splash Pages ---------------------------------------------------*/ - -.rooterSplash{ - padding: 0; - background: #F0F0F0; -} -.rooterPageHead{ - background: #55F; - padding: 10px 5px; - background: rgb(140,140,255); - background: -moz-linear-gradient(top, rgba(140,140,255,1) 0%, rgba(85,85,255,1) 100%); - background: -webkit-linear-gradient(top, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - background: linear-gradient(to bottom, rgba(140,140,255,1) 0%,rgba(85,85,255,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#8c8cff', endColorstr='#5555ff',GradientType=0 ); - border-bottom: 1px solid rgba(0,0,0,0.7); - -} -.rooterPageContent{ - border-top: 1px solid rgba(255,255,255,0.8); - border-bottom: 1px solid rgba(0,0,0, 0.1); - padding: 25px 10px; - max-width: 1200px; - margin: auto; -} -.rooterHeadTitle{ - color: #fff; - text-align: center; - font-family: Georgia, "Times New Roman", Times, serif; - font-size: 32px; - line-height: 120%; - text-shadow: -1px -1px 2px rgba(0,0,0,0.5); -} -.rooterPageFoot{ - border-top: 1px solid rgba(255,255,255,0.8); - margin-top: 20px; - padding: 10px 10px; - max-width: 950px; - margin: auto; - font-size: 16px; -} -.rooterFootMenu{ - float: left; - margin-bottom: 10px; -} -.rooterFootMenu A{ - text-decoration: none; -} -.rooterFootMenu A:hover{ - color: #000; -} -.rooterFootMenu UL{ - padding: 0; - margin: 0; - overflow: hidden; - display: inline-block; -} -.rooterFootMenu LI{ - float: left; - padding: 0; - margin: 0; - list-style: none; -} -.rooterFootMenu LI A{ - padding: 0 10px; - color: #555; -} -.rooterFootMenu LI:first-child A{ - padding-left: 0; -} -.rooterFootCredits{ - float: right; - padding: 0; - margin: 0; - color: #999; - text-align: right; -} -.rooterFootCredits A{ - color: #777; -} -/* @end */ - - - - -/* @group Page: Home ---------------------------------------------------*/ - - -/* @group Logo -++++++++++++++++++ */ -.rooterHeadBox{ - font-size: 50px; - font-family: Georgia, "Times New Roman", Times, serif; - color: #fff; - line-height: 100%; - overflow: hidden; - width: 700px; - margin: auto; - padding-top: 10px; - opacity: 0; -} -.rooterLogo{ - background: url("../img/kangaroo_800.png") no-repeat; - background-size: 100%; - float: left; - height: 110px; - width: 250px; - opacity: 0.4; -} -.rooterTagline{ - margin-left: 100px; - padding-left: 10px; - text-shadow: 2px 2px 3px rgba(0,0,0,0.3); -} - -/* @end */ - -@media only screen and (max-width: 600px) { - .rooterHeadBox{ - text-align: center; - width: auto; - } - .rooterLogo{ - display: inline-block; - float: none; - } - .rooterTagline { - display: none; - } - .rooterFootCredits, - .rooterFootMenu{ - float: none; - text-align: center; - } -} - -#rooterItems{ - clear: both; - max-width: 800px ; - margin: auto; -} -.rooterItem{ - overflow: hidden; - border: 1px solid #EEE; - border-color: #EEE #DDD #DDD #EEE; - padding: 20px 15px; - margin-bottom: 20px; - border-radius: 8px; - background-color: #fff; -} -.rooterItem:hover{ - background-color: #F3F3FF; - border-color: #AAA; -} -.rooterItemTitle{ - float: left; - font-size: 18px; - font-weight: bold; - padding-right: 10px; - color: #000; - line-height: 2em; -} -.rooterItemTitle .icon{ - color: #55F; - margin-right: 8px; - font-size: 2em; - vertical-align: middle; -} -#rooterItems A{ - text-decoration: none; -} -.rooterItemDesc{ - font-size: 14px; - color: #777; - margin-left: 220px; - margin-top: 0.7em; -} -/* @end */ - - - -/* @group Page: Status ---------------------------------------------------*/ - -.modemStatusBlock{ - margin-bottom: 30px; -} -#rooterSplashStatus h3{ - clear:both; - font-size: 18px; - color: #55F; -} -#rooterSplashStatus h3 .icon{ - margin-right: 3px; -} -#rooterSplashStatus h3 .msCell{ - color: #666; -} -.modemStatusRow{ - clear:both; - padding-bottom: 20px; - overflow: hidden; -} -.modemStatusRow .msTitle{ - border-radius: 2px 2px 0 0; - padding: 5px 5px ; - background: #484848; - color: #fff; - background: rgb(99,99,99); - background: -moz-linear-gradient(top, rgba(99,99,99,1) 0%, rgba(72,72,72,1) 100%); - background: -webkit-linear-gradient(top, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - background: linear-gradient(to bottom, rgba(99,99,99,1) 0%,rgba(72,72,72,1) 100%); - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#636363', endColorstr='#484848',GradientType=0 ); -} -.modemStatusRow .msCell{ - border-radius: 10px; - display: inline-block; - margin-top: 10px; - float:left; - border: 1px solid #ccc; - padding-bottom: 5px; - background: #fff; - -} -.modemStatusRow1 .msCell{ - width: 176px; - margin: 10px 5px 0 5px; - text-align: center; -} -.modemStatusRow1 SPAN B{ - font-weight: bold; - font-size: 70px; - line-height: 110%; - text-shadow: 1px 1px 1px rgba(0,0,0,0.4); -} -.modemStatusRow1 .msDesc{ - color: #000; - font-size: 12px; -} -.modemStatusRow2 .msCell{ - margin: 10px 5px; - text-align: center; -} -.modemStatusRow2 SPAN{ - display: inline-block; - padding: 5px 5px ; - font-size: 14px; -} -#counter_div{ - color: #000; - font-weight: normal; - font-size: 14px; -} -#counter_val{ - color: #F00; - font-size: 32px; - font-weight: bold; - text-shadow: 1px 1px 1px rgba(0,0,0,0.1); -} -#msCell_per{} -#msCell_csq{} -#msCell_rssi{} -#msCell_rscp{} -#msCell_ecio{} - -#rooterSplashStatus .level_0{ - color: #0F0; // green -} -#rooterSplashStatus .level_1{ - color: #0CB; // green blue -} -#rooterSplashStatus .level_2{ - color: #00F; // blue -} -#rooterSplashStatus .level_3{ - color: #F0F; // violet -} -#rooterSplashStatus .level_4{ - color: #F80; // orange -} -#rooterSplashStatus .level_5{ - color: #F00; // red -} -#rooterSplashStatus .level_6{ - color: #FF0; // yellow -} - -/* @end */ - - -/* Easy Color changer ------------- */ - -.rooterPageHead{ - /*background: #55F;*/ -} -.rooterItemTitle .icon, -#rooterSplashStatus h3{ - color: #55F; -} - - - diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.eot b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.eot deleted file mode 100644 index 29cd4d1f36a419b4822d210be985dbde03d1d3ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 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 Gn*ReFo8=Jz diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg deleted file mode 100644 index dc2127b..0000000 --- a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.ttf b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.ttf deleted file mode 100644 index 4e27645c4f897ba62acace85a644aff591860682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4516 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 E0b}jXx&QzG diff --git a/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.woff b/rooter/0splash/status/files/www/luci-static/rooter/fonts/icomoon_splash.woff deleted file mode 100644 index 63f541307f5f723c6eed5ef792b2fbce8e4ea0f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4592 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 Vg5RoPjlsG#(%?z@pM}q8{|Cw&)JOmT diff --git a/rooter/0splash/status/files/www/luci-static/rooter/img/favicon.gif b/rooter/0splash/status/files/www/luci-static/rooter/img/favicon.gif deleted file mode 100644 index bfbe292825c753540fdd42af7823e167398874e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2441 zcmeH|`8yMi1ILGvYixGm<15Ef&K%XGWGY8nBu7{bHJZ6{Bq|yscV0Es=-6N-A(-ME%9Np_=t!2*uVA^pYRf&^oF*( z!kS&-EpG5uH*l{TxRV6!^#p$+f%{32esA!AJ7mBc^4SMD;Dwm+ z27mR1ehY+82SVo_AZCK0^C8fMhtQw*U`zLPrpg^~%uvH4| zR~USY0^6d(w<)k~Dq=SrwjF`kjeze(!gizJ`%%b)NW{S-BsU7a7me79g>z!yoLB@m z8qSS@AH>4BaR_d_>~^fmdYtMGUF{$RKa+-^Prtszyu;22{FEKml}G8$3+pfZFU$YO z{}=)J9UuHTLD06{K*D3&R(~8_?#haa^F?N!o zlsMu-tc*~Fu@K71ve@CNwg^8j>SkxAJ@sOYs-55BSd6OxPnr%@m}yrPk)mpvtnxqj0ew6D_ujjAtxs9Bikc{4)t`0#pbMT~G)cdhPSVxAf6tlIkb>#o#LkpANO z;*El?g2y5AzgOIAzHw*8vYrPu&2+urXN7WtTbHZ$vY6*WO*c1xHrYBD7#QszaOw^d z>-k?yKIn&&oQ(h)c6}6<@_hD1kok~BBm&DXe_Lv#M&9c`gl(6H@=6gdF#^nJ1w$3q zF^f2j*81G|V|}KX5S#M+Z&*1Q;?3Je^O(1f)qK|s!wi010}AN{OwS}+=n3)Nx%9mj zCD!EF!keOq9hyk7_l_Yxfrjs7q@ANLWIrvxrrz?4nF=Hb1PTZ#U53oQz)4~-1p@N; zl-%RmD#L{+P3~F-*dPZ_E5=pqCNeErR6IPYv&hQNy~w*#g~dC19;I!M+<*AU-NT-L z*(IE@SkUvhVIhdg`&_NOn}GX~+1vMJnJ~$Mzbpk#7c*F|l^AccH-v>Fqy-9apI?1& zD_*V`Gd@DhSLNKsNbi{MmAsmsh%Ie$_l}!rKqS#FzzM{cYwrlhd;vUy$b28${n!kz zcEA-GxR4@dZB&eplBroUgQrx%@n-`Q9Bew!&-S0UuNuCs>?&B_p0{s(0hOWAe)8jP-l7 zm9g(i8~0aBK~87;bLP}PPGEnJ?@yK#v$U6*MXv164IM7y7>pgA4H@d06Xo>GST&{o zp7-HwZzdi0(OV?q?EA#D_17J*JgnbKU&(skIL{sIrR=ng9t?dkpubtZpE7DSEQosZ z%jV|;!6HXnZ}h8Lds^@+pA)McjrsQ&sD~KNytq2d&PiG*aAS&t2?9f|MMiY!On=l! zYZcWXQz47l9CmmUSlTCoP0jpezTLFV;~g5_H7(KD*DiZ*E$ZsbBrGbrwclRrft>>r zAwS=~VdxvOe4%r%`$g;BijSUHVjgl_&{+2xE#Bs3-rx$m^S7uIr(ODA>bOQRd!76+^)JBhkVD(k)@2uP$fz8W(i z=w7z%1g8o!W>-kVjc05963awysKuSabrsQ1jkO=qnyl|42lg_Wtlc!97MYNKT}=x;&gqW3TbnA}QSS95oj9!b!RS?JE&sX zfbY3Z56Hsl7oD^se@eN*D7{-YPSQFF9%R>M7)=@9+TG+iloJO0ao-8aJR%1;^ACjV#SQ=f diff --git a/rooter/0splash/status/files/www/luci-static/rooter/img/kangaroo_800.png b/rooter/0splash/status/files/www/luci-static/rooter/img/kangaroo_800.png deleted file mode 100644 index 478fa6d62f4ce758358142fefd480c564773ce36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5836 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 Wk|dU(LN#0f0000 - - - Live Network Status - - - - - - - - - - - - - - - -
                          -
                          ROOter Live Network Status
                          -
                          - -
                          - - - - - - - -
                          Enter your password :
                          - - - -
                          -

                          0 sec
                          - Signal

                          - -
                          -
                          -
                          Strength (%)
                          - - -
                          -
                          -
                          CSQ
                          - - -
                          -
                          -
                          RSSI (dBm)
                          - - -
                          -
                          -
                          RSCP (dBm) RSRP
                          - - -
                          -
                          -
                          ECIO (dB) RSRQ
                          - - -
                          -
                          -
                          SINR (dB)
                          - - -
                          -
                          -
                          - -
                          -

                          Network -

                          - -
                          -
                          -
                          Mode
                          - - -
                          -
                          -
                          MCC
                          - - -
                          -
                          -
                          MNC
                          - - -
                          -
                          -
                          RNC/eNB ID
                          - - - -
                          - -
                          -
                          LAC
                          - - - -
                          -
                          -
                          Cell ID
                          - - -
                          -
                          -
                          Channel
                          - - -
                          -
                          -
                          Bands
                          - - -
                          -
                          -
                          - -
                          -

                          Device -

                          - -
                          -
                          -
                          Modem
                          - - -
                          -
                          -
                          Protocol
                          - - -
                          -
                          -
                          Port
                          - - -
                          -
                          -
                          Temperature
                          - - -
                          -
                          -
                          - -
                          - -
                          -
                          - ROOter Splash Page by Soif and Dairyman -
                          -
                          - - - diff --git a/rooter/0splash/status/files/www/splash_files/cellular.png b/rooter/0splash/status/files/www/splash_files/cellular.png deleted file mode 100644 index 953bf0897143d03cca60de20b753e2159dbf6927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8344 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 diff --git a/rooter/0splash/status/files/www/splash_files/check.jpg b/rooter/0splash/status/files/www/splash_files/check.jpg deleted file mode 100644 index f1fb739832977ab446c5bbb382278c8ee4c9c12b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 631 zcmex=9X@jO*zpr5PhGlvPb?HxGHT=yahkYr<3UbkKb$@|Xn~>=}ORb!jZ%|9=wzK$gba diff --git a/rooter/0splash/status/files/www/splash_files/forum.png b/rooter/0splash/status/files/www/splash_files/forum.png deleted file mode 100644 index 9e8b8c222e46c082eb0bed1621b309f7144d12fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3845 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 diff --git a/rooter/0splash/status/files/www/splash_files/full.gif b/rooter/0splash/status/files/www/splash_files/full.gif deleted file mode 100644 index 75b945d2553848b8b6f41fe5e24599c0687b8472..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmZ?wbhEHbWMp7unE0RJ|Ns9C3=9Vj8~~DvKUo+V7?>DzfNY>Fh|Ltj$Y2csQN9XW diff --git a/rooter/0splash/status/files/www/splash_files/home.png b/rooter/0splash/status/files/www/splash_files/home.png deleted file mode 100644 index 38687c71991b5ed5e17625142388a46dde396ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1262 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 diff --git a/rooter/0splash/status/files/www/splash_files/rooter.png b/rooter/0splash/status/files/www/splash_files/rooter.png deleted file mode 100644 index be8099f6b2dd0206a37ee4a6313f3ada97a08528..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 311293 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�$6Fa*?Ro&;ozxP$*s2vB9{D z)TNhw0+mUuQ@{d)b!A{q=D9hZ+S5xFIz!w%5+f0-AVT7NFO_iR>oeZ6c-fNo9y!7y zQBGH)a?Fx|N{p%3Thuy4z1hYV&jYX^8ew+FJmw@Wf8|eZ#=Eb(8vpj+{yW@r@4fie zEw|vA=byuG|MM^7g4gWFUANtZ<(Cel-kwKeL6Uer$3~3id>flJN_0zpvbYV~_RZng zsYBR&;3Pi!;p=eY``?Yne)s?$xbr)B=T*Ok_g!}le)01s@#CL8g127w7Tow7H{yv$ zpTMp6-hnq=cp3irzxqQwbo&qRz<2KkI+9v%4V5c1kZhEqN4;SmX)=_LIMRDp$QelE zYC5BT{`Y2)HL#!tx@aj5Q9i8beZDMm9eUGW`V4^sVrFX$8Z`|@6?WW+Yu1rkDvRF?kE}vX)NqY~ znT3NUBQ=xz9dQ&!XsZOd!G;8qG{IDBmn^e+DJpVH6ew@nN>CwrokKd}LACg+qPnmR z&AB-Y>vf53QkypozZ^FsowP8yW75KA`mEfywiF=g#u1!4_yp?c;>~Y-13rAi4S3s| z->#%v#oJe7pJV;g*WcII8NMO~N}B~Hc(rOx69TG;+;jg!`0lrF$C0DQWG~1*lV?0g zO^2LyCgv8g{gTVDc=_9~*4~9p*(amEB)5&k;6+tyerlgp5e1PR{(SaaFVz`YV^Xlx zHX|20NKl)q%X`!?H@6crJ1#)?*z@|kHFT9KpwqV45)qO`tJO9^CMvmEjAj*1K*!=d znURFH&<;{FZeXyrjOoULgw;7r)wWB4G{Af_K`Pg<%8|V6k?EzPh$Ko3+)T5yjS4~K=Dfv9x z)E!!<(iP%vH?3%-X{t_G`S(Z*5l%LSgB*P+rV<7WMl<>BH74-%H<5%b%0~KciB4v6 zoq|Nj&x)}y+0)3Kx~WvgxUU_*x^{erX<-c&`5y7YO1ccjfYgJBshwpy*%{-9b$UZ? z%c!eLSe3{oMEpEq+^+=pN>VCm>Hdnx`^!XBd?Mk-i1`G5k7`$hXej|cFUCrTaZ-A4 z1pK$XR%!)sk*T4b0+~soj!?>X2JT64QYKF*DrcK;@~QigU?LYNrzVyF2MJ?S=dz|? z7EBkz1VrZynX+fbjUs;^g?|ut-SAvw+`U%|uGqbbQZtR5RGKUTvE1RH+Nt%Qp?kS0 z1ewh7nA|_|WG6AgZPe1gOAKP{} zF}DNQzbnDU;g_&=EXK5at~XyWg_WQ8uuTY z_3N+4``-6PY`)`sy*FFyTdJNkEBTHp`~*oe&L<)>6RkC7lziUp=DHS`yBJaM}HwwlpVElFY6xkGD6RyIRAozCfA9NCnWFfH|ysOUtr!lp~oR}y-) zVqAl4Xj3!FWz)Zm624r!+-sd)ie_ULKYRQMyzs(7tRFpz`r;hYVFmZ!_b`qfKY@>a z;s$(fx{bT<~Ux~ElIwo#u|h}=ld znLqu;H?VVI7cPIp)p7GcwFvCc9>m`+Oh9c*efiixh1tB&88yIRPnE zx2zFvwSg;NO*oRX!4hKjB*ZE}%BmHg=oDv7NOJof3e`kqOm*&Cn3EQn=C=Af#rWUs zV93ixpbCi4S8Lc&RY`J~8Q-}-DpBap=pk;p<#vHk;#NqQ&L$a#zo{}2bk@f~&|12x zbwPPNe!wJG2|L1tbO=@0lz{kUs!=6LYDEr}A_xgcD~jJVqT)n-5am8@@(D=kBpaP^ zqs#7}lDEw{SG#zlq5gY+Fw&b)$bw9MsQ?K+?Zi}9z3G@)p;8!TPkSKp8Hc&cfEGSh z&JD7axFQD+dG#CV%li;lKBN*uUy2dp$48o|jS9z=#v>=bj@!JpvtaS6s-3`DlpDFI9KZ5mQd&76x- zG>fz*2?mp7j;uR0ZL6X^KaEi>Mvn=m9FP=>sA;B9*G?qgbJ%L5x}6y4j!M$9i0@}o zB+H>TklH0D{>!+xutI9UBDGfo_ZQ>+Jc!Nz{ZKhaPie1l?4Gg{^A(iYGC$7L0SxoQMX#%|gfOr^VJvy(anHJHrGzA9l{tBH{|`zpC&`q&Z%ftzRs9le*u?5~ zZjG6I0-vl0f06p(Y|t|02WSyEGUHZlPz|*ETb27(O~#JDSw6s^--Wpo8#dY0Y_jq_ zsx@~QroV*j8@j&hxt1rYY7`aIDw>cv)|!o_IPwC7%R%LH<5CeaC{8J^ny*2J_lW{z z4D)pe$0T71g&*c=DdRf{y(-lkohzW+hP*?;=iroh{Xv_WnR1Drl?;!oXIB~y=rv7a*!@RbEdi7|hpVL!9 z1S9h~Qe**@*?cXS405aqVXYx?Z3#HJvW%&0J7%V0tgfzT(thZrCDbJupPkykOfAFO z(#u$w>ErzUdnLfVjP;cW=j_h$>d_zRb@cmvZE6tW%KdZlc&^PD#wYrQkWd`cft}t) z(Uh!zdTY(e_0YqtZp85@9z!_gnv-b5iqgE|;sFNJ$y6z6WFkH+M5C6ze&z_+Uw?5;SXG!os2o@~)Hn{02z2f5GkFs%Yg{d0 z`R6~z61~s9p+W4W5ViEq%V-bp!08kBqcl2#Kl^|F3Mk|;*foG^z9!0t`BFvhOOuDu zDHn@*1eU9o7(vF_9Mw-?vrrQiESWH0GtrYCk%&`=g*Kh)rVOI81OGI8QGe<13 z!Sf6)%tz=&!oQbu=fDc}1JR*Jd4U$Vtd32DnF$HDSxwM7t)$qnuEik*Os=)% z4Q0_0d?5TD%T$KAwZvVVI0ay?ShrMJgA+l!O^dzI6y0yn&qxic z!HC+)OWW3JsRS|e0a>G3fN$Ivhhmo!g9@Q(=6&*g;YH?V;?hAAzvXI{0zwwS#x+!z zE@1uod)PIa!6T#x6yH{N@n_Twg^v4{);H+)VK6QWpR^$cTddt_0?_Ma)ktTp_*O(Zx)CGivv3Emlh$Q1|1R&zetC62@^XGqFk<0q8gxBsmS0vEIM51Yq06Fu|)q+ zq1W4_gp_`tL%+)|Vr}7;X#JOahw1&XnN|!HI+S?uoMS;gZXxcbm0HB^=MD9@5d|Lx z4Loe`stbHrLlIhpD0YPF8KNY^Nqw6E5hv=bR>MGvk^tT}4UR8?c4dt`i5wj4mm(w= zOKP36pS>m}S$y#G!B(MbC}e@`4OFk6MPcDODz`2p8@G{8*vMoOs8Dj>rlg*Q>gsKk z`{g*=px3NAO^F^gp~q^>;UQTS%5c?H+0wZf_V|g#(-eE?`P2Td(zY$uJQN8)H5ioG zJwlJ8Q(BTf8D7L1y^-=(OcM~%6nckisS2RS(#K6&V{}TV6LF-Iap`*4bRqSK6${o!E*bK9#CRpIo4#d&Qu{jjC#kZ{mH( zLvFV9rdy$^KsagM6rMZSQQGk3W6~*0ioy>cW^9sIE$8Uju+%TD@FacG``|xWQeI5< z=yjWv;4~@Lc?8nxepPM-7ltZy53`#U@lNtt`%{8#OuHqa(>Jf55SWVeno(u6^-O^u zCi~u25lh~R893hV5HBD87G=T?+i~H1NT?2F=yie7n&#_q%sfX(^^%NX8|}eRk>$E% zw#U#p1i)-}K@aI-+uh}j$A}enYRr0(?gUI{!(5vmQbLS4fD_VDTIMywduOO8@?l(} zLzn45#Si4gWuCIFv=k`>@<4Y?D+H8i9he!#f&BwmUOA8VU%iG}DNDe91H=8p6e}os zZKb6H!1F>WnUSnx;np(N*VvGkRsNb-n5X!YOh{FhW&K%tHD-L8n32H+43^oA(Agf1 zWoZ4nC>Gn40JkamCV&#_rQ6ygb5#f_XY!1V3Z)FTL(YA$Qk4w&SH(P3a|3RnCZuqr zUIQ(?A0l7@rPnakN1nGQhN(i)Y8G`5_-4qBl58s;7ujBxmDNYZCK@T)6FoS8`2&3J z`7dI0ViaHh`ZtkGQw&<)l>Kz${3U!PpTj3U@eDrm+-LFDTW{g3U;P>$fA&c{^2`H> z5BK8yjd@sIw69_{#4;K69ij`Indrmb$u0~fDHdj%SiW)#SKhdQ+|4-(?Rf$fdAf8J z(_zEap@~V6O@I66-@}1}r|=*C!@t8{{>8WO_G_=nu%XRT$eU&9-l%8-bluQ;>Khss zuaLgJ0aRAj@cx+(@bt5vk|NpnfAj(YtA@;RxU`Q;m72`h^1A=oPhP~y`w!#zi9-ZT zuj6Mg{7h7>WXy*4DbE^mp@J#T4fa){c;F;^>ArRuN^i}q(WVhu(9U4shdv%#UOK*j zc+>Up8wLy*H9Ff^cKb#xg*#gvl`KA!s=C&#uy7w0cY9k*d~IcP1qR%7W`-@f4jcOW z?GET^>Ii_PmfsyCLO!!h$5Xw{wgG~`GvXH(w){j|o&3bwR^*qR#&XFzyKx0(V#VsTeyK*a6C(9T^`xEE#=n>Gpen!Y12j++5KJe<6hs6&+? zq*~;4l7Bnoyz(F_dwb9#a}qI8kCJ%B!%bo+6@b+)91#bxgv!EgK8@`fc*6%6I{SKo z%6r0&ivpF!&c&v}t3#|&2H#_D$X@#wJnQj4NYIk8u9_H7uOvm@PwdM8xtX$-K|qy7b(H&WVJmQYff0XD zfen`aZu0ktpNW|ZXlsJ!m_hP(M4i{U*ywRA>Wa%Soz*BJO-V*0w~Uob?;+95;?(h7 z80ksVp4%Z^S00#*MCo{{(LvGVP6zFOmgZ$+wOCyMQvuo1zu;~6>zp;u9iV-W6e8t#Mt7bY;t+;j~;x$o}i4af#aX^m0;2}-H$IZ?T6E0i_|jX7)oWTA-#Ra%aT ztj!;dCPm$?+0;%8OE$tQQ?eN#NncCFSW%0T7g|@PO}frf8N*z0-FX1xLKtE zl>{S2=NS7hh;%CF&~%+80=LCdRjTVXdat<+THEy+3dItZmUAeScun-7T8kpnGfE)O zm&Tw_XxZb2?|ekWIYnuW^K-7`+g7L^=F#utA>xLZgE2@7#Z*|yu*qF3`jgK#e%+QI z&Ue@yp_LGmaXs8+T92rsSq5(y4z|Oyg<*x0DV1tSCnv9^%3VRHgJX#~B_qg=KS(E7 z`9ewY+ch)#6x9m8BwL~LyDybtG2COWgrQ$@0Z*i7*`++9a}3%YQ4toARQ5C(5}^j^ zYPBQ@kz~aHZcbPOO3Fpd#i^Li3%j7lWj-uMzxVL*Nz7k=1DDRdL+>?@sbNZnM`tkH z+bbQWMmr+3Kih_(Q)wZhN$W5{V3h#~Uq??@m)vJQKN)QEo?|o2X1gIBkaDRZodovo zT3ySEba}DtBVT4EwthOR$0+`$Xbm%&%opDcpM4*^n)=jO%JyKoH+SJ0v<7(JCMov` zP2TKI7b(ztAslZOvq;D@k}e$d-uqr%I+QVHj`05Hvx6zq5v9V3k6NH|)vWf#Y>V5s zuHnD@xBrMQec`w9x!-;YKltAFX^peONDYxLIx7|m_^SMkL!eF@Kh^tZ$h97UtjrTCpzsmd!v}CfRSZQEESGRaT5@BA)D4ifYZL zc-Kuh#TJ!9rDoc~QfYCwM7g`hfYOn74ql^nb=zn=V9(7wFF<~$mRYRI;(a%H7}1a z$QK$R#ra6*M$FCp|qql054oS0knl&lBiyL^}Wk;cSQ!o|GoxcR07AhC>Hw zgbj8~3)2pPjTod@A|u9BCSPRdB9b^nDM&Lgsn;sXONRF$0HPZH>J%+y>PJgbp+Gq_d%e7xz_@&j2Ra5 z!8w3(``9xQdYt&UZc+~*`dYafla`tQkW`!5C$#zdY2gjf>&MWdsF>jU9cdxO?L;;` zZ0V5xdZU6iB^b%>E~F@tbiIVQqB>09;tFt73nnQFhN-lL#6}jC(gHG(I(AQt;rUNI zi(^NRBGr?T`_@twP@$CA_;ttQAN}$7+^WA1yM+gThr*#_+H#nb%LNL4lx$bZc>Aq0 z`1y;!#Ls{EDpuFCx(3}D3RAm-HW$q(##*yhBz}hBLab717avir;eCg_0c7_i59?>p$ ztX?{>8xjxL(6HtWz)5A$ONVnMlR=dZ;0ysOpDP1g@sGt&r#%skQw(u+a9QWnTnTh- zQ#7$mvADyq4>)C4Zn|Ts;#A!UdFhVkZ`>{9gMvE+T+og+gs_K44%xVF!viW99gAb+}GQUNdi$HdF&J(J9#%AzW+4+Oo9%)I_>?UB--#O zZg_O4Gy?HM@?&L@ezcoRt%@O$rh_OIH$oun=&X@i!hgVOBR-Z^ma&v8;MPJGFTV6H z=9UW>pu?!a5}sa~?#+nYU#53iiEfI`1s&MtqG~`%7fU8n!W6Y@LLIT1T&!3?J)c8) za}yN;5PTT!IXHu(hY#V2k3NAtGgBBC9>QQ>FU3xVfPQCAze&I*O39C;suXuOH?xv7 zt*>w3mDk_HrK<~ATquHzovEI20;Y7I-KbCx9Z?A6vyYNK+c>9#6NaeF__Uj4isw~I z3|8oQHF10HA~si7(5jZ?zW0w0;L(R4!h!vVaW~!bLq}%m0FS7fv3Pcd=uuIl4iCk zYs)+WXMO74t{6*WEK`PL324_A zX12w4bQj`GwX(VKAE)y&DSji>8v8={((Edg%eZjm5^gRo;l1-$Xg|@IjWC&k~QiaSQBFPwAoOvlXHmfXqTMQIO`m~wn-(*10ic~{3( zB|N5hwYXZ(AcxKl2E$yyl0L7Yelw`yKf8E_j(*>N`Op6a|MCC)-|)H5ejdN~Z@!3c ze*IgxbpA4$D>=A*Lv+0<{P~x^jtj@<@ta@#6b7ey@Xf#Z2CgsO#OMF$_tCX?0!4Z@ z3?L}4M}`G9He9T{`66Eb&R^m7d+%auXaqAu!xR^G;q;?Nuy@Zs>>N6XzVrZ{SCkV` zENjrZnWK&WwI98MSI@jn@qPr4KmMo;H9O1#DbZO)d!RvkB+i|yb|Co~n^3>;)_eHi z@&_0l8$(ZbMr6Mmc?u#mUd!C6>d~3FrqY2$u&AkPG!S+T1bpxkM!>XQEzmP@k&2~J<=GTFtuYh|q-B3OmQe955enk9AD6C%ZPcJ- z4qfEEIWSf!Zl)zZNX!(fT@x|dH!*sz8D=gdnC%mloPZ6oE7hvZ1UZy*GL2a+e2n)- zIA9K=$`=Gix*HuP3;&yK)L9*)fTil*R%b3f6b13LSt0kuGV2$i5R;j&RBhR9)$1@N z3iSW%aIR~c_=~=1pg=I3li6PEH7~`?0vIrjjg58M1in(G0@EW2WpMAzvO0s{MrR*J zO=BAX5m{OawoW1~!;=yxT~~jZr+0xDmn7~Y!|Q6NB9`a?5N&yX7=XY45dFPQ2Y}ed z;K>i?Lm2rPXJKx!N@s!{*%{q6>Hzc$?}eW{uSWkLxbi_6=C;hTKC+|Q|`Ji2V*83m6yA8 z=@P#4o$pdo`Ab~9a7E3Ecz8FWfmNz_oH@(GtHUqnu(C9VG9?S$dkK(I63hOTQ8uZn zZy>)qCyAw3E2D306sceqZvQv}E-twJLhoZGah~Dm5;ffkaf%-sn7_WM+V&0wWNQt6 zZGmpmG99XAt=c(R`k7Urhu&jm5Y?e6lz3=4SrNdnS+0u9YY_2}FQh1Qb=7c?x#F%; zA6gMDe8~1}!Z=!+0x@sGh^rJyDS`xw&;u3pU|S2OgxU>C{%Zl+qPV5*yW-;AQbvdj zCR2jgWMJZ1(!gM2K_1>_9<4`7UYru@c>fqu)BADH>?odn{#hK~vs2bYi$F(%lJV|L zx2_YG>NH|0(w%p^p-?TMj3ll?@w`c(GPJG{T@j{^x|U&ZpdZ5{lh`xO32_EjZm;2I zZ@rJpw{C)&7Hw~Z4&@O_^!ZIL(u?K|1;iB-G>hV$O9y2t)}o}oLWw{T)$B3~^x5Cj zi_yV8%eI9FgBZYt++;&wi!*RYNA@JI0VFcWiDrMU<}Qc zgPz_|yyl&Sx11+%vV!ZkSLylIr3tUz(r;`vu|UDrwf1n2Z(9--N#>q)j*-nu*AU8VV!RJ6IFJ6WPx&iBO=! zU3zi#VxvMa#0*3c%MP^T;u`M?SETOMh*PCHThdKZA0YxDo;p!`c2R(Nz?2nE==``) zOdfn-A0B_?NqR=T*fG|HkA3`e*tct3Is^PX`bVd?V)C};w8;QO$i;Qs59{C=u`#Ce zM8tzBhGaq=;|B(5k5SBAU0W9copYBKkk75)tv9b=ZmEP)gA1B5xvy?41GnwU+L8p- zF^^8v;hG{r%`|cbm_n_zoX(jbGhZ?rWu%rJdyCy6#izD7NQ>GN(@>$3*ZeyC^9)ub zd32)kC-2dxo_Y$u_xpc@mwx_peD$l}#G?;w;JN3X$4`?l;@!8;$V^0orF!FOT)%M( zfAS~)2maL`d*=y9M;5BG}y%#~2p^=)Adk=`6+u zQWPVm@Yoa2h->;oPoBokkzFj}Eo?Nk@@WZeHJ(Y~nFmhLk!9njubju%-o1d$Y>u9L z9A42A<3pCYZu@F%%0u-N6FYGF{`>Lo|Cj$&&dqOr^RLk;SCmQ^kBE3kk?sou3ppwf2lYf^*L4QFJgX$k7GDcMOyy?~-|#kN*|&r?M|qV~r+k%wP^?DB zhRUFei8h}nlB4o{ubaVb$ZVU+x2dzdc)Wyjiz0x;eo-Es2SquoBC&?3B*qf~#Wx#; z!XklB&KctrHzzRe_8_}nLanL==tiwB3>+ba*~T^@9C-IzMorM52lFX=Rk~@u5yUgF zzO6g9K-dy0%J7ANriX>1cnoA zaG@ZhGcx6UaE+q1>6iXLU+-RN|Kh^MZ(3JeGhkHZWtgpSGHpbRuWeRCn2o zr|ksF{f#nZD(@3k)2A zXLmS9w>va|Uw{15d~63F(h7Cd%qpyMigc(sl$eHf@zMu);m1G5FJ68bi;K%HL3ffsNR8cw2}tB_p}0JU6a~~?0-k$@cVTqA z2W9&21#ate0zijV)l+%dmZfTRtn$>P0GvriaAfxs9z1*yr|&s|eFyf+{7JkkNdPBB z3H6}TvpogATnS~)f1US|d^p1Gm5wO4=X~xsMwP}GI$AqC5KRd%C7GON)Me(iC7lmD z=7>?LeE4R+igAV|pxlz$g>Ndbwpu*Vf5uE8wJdcy;sf3i$5mC_+a4p-BgB=;wuDPx zP4|4`MyPcD(1q5LYPD8_lwQKW-{axI80~Ye`VCGZ(l~n9=w-S$&mhG39<@To zZRZ*^{3*q=X(UZWEWli!Q22dQm9o{KOKl%DTyqEK(ClvPJ2Z>*KsSEy1o$d}$lYOw-dMu*MODhH6)7Rv#OC5nB*C|2Bw z%MieGqb8@c)OFpQM6!Rv4@6+KOS>2JUD<;C-1?5eX|5WHYs6z5tT{{^=6)~ zOYOqgFGuHRJoV~v)ZXn^h!vHYFXC!GD{QlX@vH^FRDPX1F>$HG)*vDAsc| z0=%?8E4~2bmPss>BMu`|4>28-CTa|9c&*oN2VpYeqyxN~*=OmI9TOw?n>t1V4M}6=d^c=*`3sOZKBsZp$Uq>I7Bd zTENk6fTzVwU-vY7?r@xqMO5XjR-+gekD1X&pVl|6k6276MICcrJx_piG8Vu&RL=S zv}IH?q0hwAn9lQQwrdha59*1;6%#(YjTtd}EqS({1p-1i0Zu4eg}?uM-~K*UmsatK zk9~~R_6WZJo$q6LaS6|T{CVt~*^jRgC@B?cNT-sN_-+EZGQRTveFcwy@^Sp;Z+sEo zee>tIR>>p3nS-5*qi3)eDKa6#x30#&TC9AiFd z3E<`xz|!<_!nm0p-rH4r@0%!;sv@*k*c&B-lOloP?F zz%Y-DafAHbeBXzUS3L`)SrGb=03qt%?)S|fE>|ripQS@;aA*J#R)pXILny^*%e2JA zpHMH{$kfW9x(QgeQJRvUg+5%57GX4z7M>=z8AD|)uB1t;(N?OLNbec*vPdi;yw+N^ ztQ++2pJIRsAGRiQ zo(doEe=}uZV`B}kzxf7!_%}bqx$_rs<=RyVUJ*{hc|J*N9wKvX$JHpUC2ie0eUB|# z@*X|=Nbv@&noZAsm6E3{+Vt5+iS+{~j^o7LcVXv&gXoz#j9Y#ZKmK5m_EeMoOHn6K zQLb6ECn+hVwcbquzP+5r#NK^4IXi?;JpLdhXLlRfY|UvJtQOLa(E4LVE>C?pIC12J zkwDE5#gEBK5AE@c4CmRP`kLyDeAzt zYxL^r>j`@Qe$z3o2;yIOAICcX) z;CYZ&kwD8lliqF@k3V`B?yUjWZ>^!HH-igT<|&D!SjfD0H?C`n_C{RPiF}#yV0E-c zIg7>HS8?&&IYj9heeCHc@VU=EkIz!_!<`37?7UEDM0c9&Xy>a^FN^<2#C6d_&q)WV zRSAX^CB3VUAv8I*UnO`FVMeNFg%dL0}q_W2})vj5fJO{o51FVhu7Y?hLl%pnvRh$ArI3wAome`45(p|Jl#q#4wDIq);1|mp8D!p2tSMBuPH2NKNkYt|MKLaP;g{BlRJt^i{Msdy#?;m$y{LlqmtLUvD ztS-w_)y}QIWeykOKuJAd03*c_F*4;DF)k+f#%zx6alIJ`(27zrp4(W(pMT}cSh#f) zU-{rO+xN!mN7 z?|U34`s1i3>3S(7r|6cBMm?lAmvO7Gj3=IY3Mc3ueBlefMOPNlIVM|+K@sDps)1I; zp|b=mmg#<U&m_L^`@b)$P>l-3PdW!$6?SrT5vRPYRzFJ8fw%jf8TBcRD0CyIeF`W^LR1$Hv7-89~dp3z`nx}mS#z`)n!UG_(--SN6n z8Ff$Q!Q!bXy1NK4C0IQwPv`D3t?6}I6HVN8@(A|K?8CjM9>(3rA0lALdGYtLnXhB1 zU66*WW$Y<*4+g6GXWYj%XSK{w`POKJN&h?DPEG%}4WOI9%l8GLF>N4H>6$$ouRF6Y zZNn>KA0RQ_HpZ+9vP}16n_{j^Glhi*^GxLT-O(&?8F+-ofwgjl65mQkh*qSy?&v^t z07yu5vds`)pjyPrt<%nd=)wyHt1JLSHlr2JZYTiZP45|}?+}2v0u&U0u+IBGI0GVn z2O0p?h|pK$#v8QF!$C2jPI1+Yx4p{RDFurM#ku_ya#lMskuZExx$BN7U-5vN!#*Hz zI`>8&o+3WE(1&inRMzm*>#alfa4nQ#iD5 zHy*qH6!ssOMQUga(a~M#ty(yHV+BjaGTL^Uk9KwYW@+ar0rb8B1Q`Mk)-WZnBZzhN zOM)myd3JcXN2C)jfAe(+RcE?D$#a$xtSoZt+zDaz79K*UKfM*Y7nDHQ8w7SJ6Q%vr z2oeMsC_#=65D1w?nLCu+mZrU4s?xu=)%2^nxk&(`TZ%kh)b0oksTW=#27opNaYu$+ zO@-U^7F-$Nb<|bc);TtA88g*NhJZ~aI4(_BP5x{-WPCYjY>{S!47jtzW=qvm1w3+F zpS}9(F>bM^=>1S4U7%Me7hzY*7^Ose_l{u<^d^)V5N60>VLDJ&Ez`MHvuk+&{8ha3 z_E{`1t;+E7zTG?NTaKZ>ca{#XM0lcfOp&z`Pav|zGKdLG4yLd&+DAZk3AyYdDjp?% z@l7;Z6jQh|%hh2zSW}cG*z|8pw=bfyaZ~um`;OdC2j3AK+_#6;6vZB{_;2fohT=-B zD8$K*%rqo4_DXF`L>APLE=&T&2i+K9^Ur4JEzC?0;lSQWRw zv@ky}x;{_N3=c`V2g$f49S@JhT0P-s~{pBj-catq9&R;a4in=ez>?S zr9l}$B98W!o{^zvL8#c{aiU0>X21Z;G+t$f(^kbaK2KF2!%&mOvE5u-pcHGCGWKP* zBXp5&ZIdC6$+<7|F7}DxYvtJqrgU*PS7tL4Ivnd4<=nLpSIJryrJ&bKchmEVHBl)n z;mFJm%TIHV&LySx!Q5MVsTA zyUo91n|!+D)3!?WinoWa_b{CAi!k^NqByYUFrIz(;}{z5$ICzaJ|f8;p}y6NS!8;~ zP-Uep&y{_rZ`d~A!<_%nnG0W#g39dre7f4|wbM_4E*kOa46jq%TE}|!1_9m{4jh=o z^vnbv`N$&}9iPC=?!(x*bDYjlV0fgD);z`AMp>`fc+6R*^BK-#Nul4!0>hj%+TjS5 z^}G-PnC_eTniZOO`yJX8j0t#1qVmJwZDzfE(+TknE!f|}JDsC#d(LBp{NeCE84AFi z*^;ZgIUTw#m&;NmSL&2`!|gkM#J=+-wlv4}nnNWAm7`@opxyE%*am`_-7s^Lp*o$R z2$ZL5Yh_C~-^|gY!?5aw?vnWM%t>bkM5j;{ptQFf(v6~)p4J|kl<+g}UPjst0O5tk zDhFH97vW@$xvP$mi6hVw31lE$_#WZ(E4C#C;`qkdQH;K)Es6+E%he7G54s3Ro6X|e-~KLMfBkj5^WNJiluDw`rb=o$sL(P7oSYnSwYI^n zYFnu{4kf)j9B6Zh_Zlb_8x*87m>M6!L-*f{Pk-V`9G%^ZoooaZkBi?!lYVZT&Xv(b z4D$qZ+wC01G+(s(#oUgm3oae_J)>A#FX2+w!>bn;(c3eOsT~90wbE=gr6b^&{VOJa zoWPhk)nrN3S^?E^K{WK)PonLV>3!sAztQibbsG4rzQB^KX)zxwmvWS_S5S_1$#n!x zN)lVfeU+2TMpO0<(+=8g9?Fdf2w*=AS2Xr%AH?fYRdv~8hkn-eG(qEHgB76!i79Xq zR=MK;rUZbJy_Rq%1Nj{duO<7eY546eK3Lf`-q$K~J7QFA=&*8{p3HVoW{)aeTRg@B z8yV#Ns3<Mlj_}E7thCEeH>U?t$7&1B!QI^Ve+*nw_t8cxBmtK4m z8yk5_Y$KH1tYcs(gS|6TXjTds>hCjy#Sq!rKtiiUi4nh812Ypt^tCkJdiN$J_Dz%u zMXt%yzm?_waU4iGbiWc5a~tdMsvDS^9LB?^@5OU;`0m@iM*ywHWB^9d&o_njrL_vK zUB8K2i%Zg3=sG!@8gkyE({JF zLMk1{>e3>XmX@%1b5(pzbS9%Mz%QPpI85NFMu3hxRLyz`iKs>QbO;}P`~iIYV^3k% z^bYLVJ!1k1C0=wE)T(qo1vLU6bC|o%w6drq^xUQQ>`=be$N(ELg)jk7c}mZCM728} zH62H0sNV#PCyN|NGLI4I(0?=;+2*P)bjh?i&-^WJd7yHn^52e;?v}w)f9X1Q?Hs24a)aVl9s^H5DajD4CF!gUlL>rL9AkRw=wO_H@D5zQGLM_LZe!_M zfv%r|YR$~%iD4=~l7`SA15vJO8ChOeM0linBO((!Mkss z!TsY_Nfyzb&>74|88Zl(OJTfz5*rYf+ zJ2e5n(nPd3gEJq@WB;z*pxZ*L#8$Ipx_nkzBwT@|%>pjnzKu8N8F}#mOdULl_1ZPO z^UAxxMoBw<3%5~A_tN!uW4(A)QC>Zd)jH2gR0ROB1o6hzy7+vk+>&K-M8nhcO;suU znq}nFr5J2vaswlU91cbYW?%5yr0-w8zJ|@CS)9E07$%0h@q_RGcNBA*Nc9cU*-G)4 z&L%F@ar~A%)emV*mN5f0)qY#|sIYM8Ga6%o28+&SphD+di@P{>4Fml#96ovwpZxeo zarpQwPMtojimK3#avv?J;emei_ogXkDV;Geofhf5$S`{78>IVExA%6XSkHVyeU?mv zLB=B_X))bk!#}jP&39PFmDb#q_l`Eu9wHTtaM%Nefn#Kmx7WvFeXVq(&nG zghWEm4C@63e5qr*Dj%>^A5*xPaO|0p6~QBx)?WB`$^zwqPw9fhMTMo!vW(5DP_Vd? zQ7;mJXho552F2H*%E}jRQ`)jlq=__F<>*k1vtkZibD0kASlzKjw9ju&5iQIxETg|dKsPU`rOi6&B%h=($=Ksv7c;&!Vp z0Hli!ngo4vt21BRq+nme$jCU39XW{I(^L59V~^mG2Tvlwn)k*FMMdy95DDy-zJ?I%4$NKsbZf-R3>e+epXEKP>{^(9e#3kJpIwFK;?U>Fe zSMiw=mZHQt&B0!O;^%5h~WY~Jfkw)tzbuTm<35K&jF|kpQNf?7~>8Ph!|g zwt&~)ewUti6sL|IG9-0diyW>oL!{)TMf;zV@f~A>=oz$e@U=bItdtSkBv2OVq1eVU zt(25`YEEi5H&9qxM$B$w&(3jLFAvi}_z6?#Y6^E<3<>4XaAaQN*3t&vJ9h~eC}G>! zEXlfMr{c*`O78dX!s&bVA)VYqvBZU$HQsuU^c*7zSNQNu>z$z_W;cDZ(HLv*U%a-2 ze2e{((x??TWIly~(wVn^iCS(Er%#>0lTSQ`r$6$9s%0F9GTsZ*_j!AUM*-{GiIv> z58eOC(O!&<4xv_eF*>@4%lp_OpkMbkcReU>bJ2x6#wyJln7KU_K4JkqXHV$p zoLg4tXVxf(D;X(M^#J0i!P2}kCuPN;_sp0QA_tBb1lau|(%qnf4V|=&M0VB*!;4o2b-T zy10ewvbYuViDFVI6@W^BL;iDgU6hk8eP!XlD;GpbZ z3RCFmj-bCMsoLg(?M(-zLBO9Q}|69$3i zx_UNw9gmT)L()-ev#gHCNazO=exI^$t&V(n2ts&9%`&ZX&d(*@7#w{k@5a58Dk5B0 zF);yfCPpkt5qH0qlNbJ27qXQ4U7S;wxOB(Cy9yebgo|jG$kxi6P(qp z(hQ)QWQ&0ZD`_y85U&zOp(60%NR`@Q0A`1}-o8;ih>MQDR-^R&@%1nrB1ovBR+JrA zDJZk5MZ>D1?X)T2`3jO)QzA&nqKvxCQ}01ENrB7K4V8$rk!Uv%t8SpRHjf~`f($M8 zdk*cxr=EQZ`*u%lsi|;Phm~cd;AzTnXpxQ?jQWv zZsrxLJE&2RYG~W0GN5fy{(GB}6Q1ulckUeCc;hVrAZu%DC>DzXI+PlrYneM=;u;*W zO+mnD)YEHqr@D~oN{C_)CxF?_9Ic5Ijvn2QBgaqSsi!}V@u3lnjSkb&>N1&G#3=Wu z&rO1tLw*VN%4OuQ-9#&z7VnuLLqE6o1Y&NB)*@H(x=^Gf=Y#nL^f(v5BZeoB?8QiW zME0O#_}#tkI7kuTp}+S}??HtCh&8$c%}g(nMXDTEM^zrN`CrOcr z@)p~^dV&ZSmS+`&Bi^KIu1Vt9Vrj-`3hhW*fE9aAtZ(G$Ipt+{`9?a?3cIUj4aTEU z)ay-@>9fvNPD;3HjW%N3wW0Mezp#k8TemU2W1ODr1ii18m=o$ix+R0U>@}oZgqESZ z@PK5yBl*m6kqa$8dzRP@R7-1Ex_K3Qr$}d$e&@fridaP?Dtk%*D=$ zA?(>ThTDr-lw0~MGii!%^*kNcE0W0VrWkhmzI*WC>HE>!)h*ru9E)uyoI`;4IPtc; zb$bODKe&!_7p`G*vtkb25;l74^m-*Z;CWA-K6OanC#{u6tpu0nLxRqhHiC~WN)B7t zG2V}Z2d0o)%VS|7C-$FO^54<3E^K|J)pgV?!q5`zOwCt;ke z!UZa#q6TAakK(*vqUXGhjlxa3hwOO~MJ&;aM0A*5za?`$O-eF&zt?IFiP_?u>{rAW zCFZtiUu>X6$tKS(uu4+3Rz_EMzxW04`t9x-p!diXURG>m@skuCopB`62`O5z-$GLq zt7y+#HIvLX1b}gu(iP7hS}&ENbQIVSm%DSZcnbXkBeYai5mG21O;0MDtyYQdX+a#i zWhR04aaY%ffCMMfOY4cwAU8#iF_0mCH%9BfQ5U*clw*ph3I#F`VmaEO;_h#gVo{CR z3OrCu=W2-(*tnxow0x$rsa!-P<^63G9PJ(n4Vx?Tw0Ej(F3QGtT+vSTq7ZCIQrTR~ zp*PW{XS|>QME0V!r5MUx*n}m9e1&=g6T`iDt?>a`jS>OWB#PBFnL%N{CiYYbT6MJR zRmp>@Rh>m*Akp1Fh!i~+L{j4A!vKqw-cVjac5zM;!{I$2ReDf?u zMk2k0_h1?MVyQ)Ix=FFGf&!tdIz5A`=LiM=t=C`1{H0}#^i2?ep*35s z5RfY%!G_B$C_q2&H+e3VfLM#yd0yngmlhWhqvxKZXKY)VpEc-xvxGN$yl`@E$NMP` zaKWhysnj6K^jdrdvRO0B>iR8LJYNEt+w#$@)@4308BdA2*u8h}!1}s{ix66PEshyeoJZh4T{@^VxHn>3h@LzCn;c*(cKe6cW;vRWR8CR zHY(LT_Ra3Xo~cRv#%G?x2+v7QjG(V;koINLO0 z+Ms9Boko7MhV@(lUCAL@dsXqv*_PC7bsx0xEROH$z2k+l6s9Aj4GfuGvUMJb0kdc3 zi^3TiFKj9RMp-Mw3Zk(kGa-%@HWl;_*R;VynO;Z^!slkqh{$*y`mC#JRZ0oi*ev`l z3RZCE)W|k;Bu!baW(7uz+|%iNKQ!;-3yW3-{c}e^=JA7$V6hyY4l6=&kd@YrBOL}l zXgDacdpPc-V1;cqaU8d{+H2-dX&#xNFP)4?tTRL&p@qu;ggYO+;9DYNW=SyQPti^n zuB%Mf8!oO=!uWM~21JJh9rXwajpb||4ANnG`aKaIq^ldlpoUhkjbnPVObel{hF+G{ z6nE-+P=yyO%AxJZoC;kJq3$*%WvwXvl!XulsPL;ZLI=V3+< zW&iM=>g~!1pPhfMNCA(FKVu_9IC|nZPCxh%9{$L)nB9L^Dy+P@UGtuVk87$Uyw#Hw zJcgoe^tLvT+?+?A13m@SiJ4S&`l5s4#X6XlOR?as+2bn9~?k& zjSlnp7`--u0%q$5DO6i@#dJ8a`(IGwDh_>xVv|#=fM65s>>_GcucC6}Dzb0ACXU02 zbXxXelFd}D2-hJxYGKvczc0 zb0yhrNL5um4AlRD{$xpHN($Q)_*sg#TuY+Hbk15`ekRWD>D3yFeo#U{ zQDDM<p

                          AqOdlHfu1z(K6Vg~JoFIu?AhC)vdS=V;E4)KgNr_N z*enl%EykJ!2X#j?J&0tU79Q7?Ur;M z#3asd2!(HIa+E;O4qUuEkM}Q~r?s*!;u)i(Jv^c+3RT?I`}}Wy4toiRB)c-$K5PzC z7%Nq(lmJ!n@~dy++u!*i&b)sKOl9CMmro$kp-nMB$v`fDGU#f(KDEn!okM+2J(fR483OPa&}Di<0xO_Z+rpAj-9}s z>D^MjzLVtKHnS;G*Q3O?Z=efZJyA-cngV9nL7L^Zs}&n7IZEIP0rIPqghjjb1*%2* z&lvi9xx-XKof2NJ&1WhsWpOi(N$ zote%2s!)&m`}@(;%@md_T}L;n^$0d7i7hv5@q!TwlCN}AQE9Msep3!wR+5m8jU#&4 zdp8c^`OkeCD@)6`a%~=mjvj;4%H#5Ti(=4c8y^D0^w<{o4U5CDExY>$as1S2T)CCS zEAPCE_uf7$iTj|pf=FW(mp-_HBl~C3olHw{M}6IV=DiZ2p#4aPb9bVTlE(zrR~PW= zOK-|NW-QedN?wc$NUfU8F%>tnf?-%1m*3{V&=Nh2b0AuMydor>iKo) z#`X60BAMtxioj$xcMHqeGS)We8L`waca#V)+x(g=&Qnv>rlA3fscu_@5xAk}wP>Gj zEF-tlz}(e0(bLl{8^-mMC}f*bv1cGtZm#3T)dG4;D|q^`!#H>K7Ot&PZb9p^RL;St zxS2?Gqgf#UNYAI>66kR9v@$A)Q4X>)e-rtYMJ(R9g3VlxKuv-2M*{x@KCGSrbPtap zlJ3Ujo`YDU>%DpTJzUy+8=$yG$XZ?AUCSsL1q7g7iVamntqLvqRhgOfTQvcv>114$ zBnh~7b$5%gV6mceCndUH6b2|scW8}K+|IK;crQJ4S1E6DtSZHwr4l*BM=2h$myi{d zFftGoU|*!YU7|IgTZKsW@(2I}%v36ETx}}SePF++Xe2@Fo6ed{49g2OTHkd3BrO3i zj!VF4;VG)6dnVakDi_<#m z#_DR17^wF4#>EgemFhyiHzB!3v)&dD8a<2c4oHw;dCL?+S!&-l9bd_9w+u#gi`Y_3 zb3B#d4UBr8sBS`WfhvGOskE@R^&hklX%Nbmbhji`W@z3xu*1-q!w<)HLewSdv+_b* zSmGhsAP8Bq27EYoP_V)T&J3Y9+orlKtxu;jVCjpBmMiX#VCs?;Gec|;fM6R=7+;*s zf^f3Vy6f!X8;J?2uqiegO=&fXiH{v@0gzAy3p$i#nGVQ@0f;NQ|64Plb|)bXKbfM! zlrNELMyUVH;YxPcO(pvw!-v(;%=~-x$}z$ zak{f@dM%bJ<$J=E6Q)P8WMs@2pkp)NoGVx?yxEn8m!^$CXr3twbxOu!K@pKMZT_og z(719Q{X6|x`LSKmZA%;9;O4MlgitZb(TeCDz$N5E zYe8GN!Z9QFStyin@xmp%@S`8&?Ah~jK+nz13GJ#%iRo5lK|zgUW}xKSpcT9D3S}Ug z`R?(EnoqTTNmvi;-G}Kt(|Gu?hjIS{4`FD0lFvw;#4?F(U_hss=@|gesvjr!?nJD4 z0*5Ji+H5qmc)%65?lcyfah$tZhDGblY6Q{|C~a;ax3&zA`T1@L*xItM!aE}Doi@bv zJkHgzXiW^*8UTwxbia)fy3!sF9@vFP9=VqSbVQQvo}MwZ+EJ{pSK+5daiLJhVq-;G z&yLeefICUaw=MKd&J3gMsX)QG-6+B-E}&f?@NxYd*4};--r^!AGhLY8y$93#_ac@_ zA(D*BOiY{(8SWldswJ!yDk#wN+^Cnac=H;p8q23raz4nOKuM7dEr_+VE3*|`upl%d zhn4TJ0t-`U)a}(}5YmiD6)qapl1H0WQxZu^BMT`ZmQg3-Bh#{UzCwhH z*e{^jl4zNT5y(imLM5%0YoK2tv;$T~>nM#|%Bpmu3NA%akYzvV^(y?B`4FQRp6sG^ z=GBFBoaXh(b4ZmOHdYoevTq#w_U^$xuJ)Qa4-J=&sKT%}iA_L}Uv8sF_pMYHQ@&_| zDP1Y4m~oedtMbKK6LYs#@Y5GxmWtuNy;HhF`0dJqG}Kvf3bte(iLad%#in!U_sxL)@uiKU;Z1_YFS3@&YAeUsLG%NAh5qAazNkG|1CHom6B zwL;g;$@3~DPkEU)o7%fW)X5mAin$;?yq&vdq_TYd#vIOHx_~u$UWLM{>@z3Y!o-eY z+;!p}OifMG9&k{u1fsTgbD@YEx7I0XkD}UQqE?iW-MG?CSqh30Xp1|NEFNJi9lA{b zWOZ{LfARIN(lvHrq`L>ZhDUMz%neDbxYNKCwGW?YA3oRk-nZysEM=Fmnq8rLLSU5k zX3y9Nx}r_EE4Pu~*udh#g3RYd1}Qnsq>RD>OAj`M^5@d?V9=0`GfzK3V0!|~t1EQR zZHjA)^gan3*2>s5Ifk7>JJ3&wfB!(Q0Ocu)Pd)vEbngSa^Zo^7H;PzY%c0sXV6`w$ zuNT9yqq8`C@DM%wG$pi@NCz>xPZ6BCd<#pt3f)7BLs4Z!IQ`uOcnGXp4J7F`8s$97 z1Y&CR`-g`6aPqDL7#``z&|sgOEDW}JZ9A~dTk@p)${kmS?)|OHzrc~%V@QwC8oW*G zYsU!MJ(TpbIUnbk`78mUHEdRH)A_LumlF2nrCZosT!KfymTe;^DdrxWptFefOo~84 zf{l;e7&3!Nl!tq8W4?x)Rv9JQcJ(CF!EGd>6sIV8j}wqeB`JGqaW{^@Kz)spcV25F z=Hv&3k)h4INg-2dP)jP2-_Ika8^&xsU)(_}yWy@DUV@EXpYos%61|dKuo71 z*kWl&G0CX6=%2ok#uj#n(2QW2y|e6?QwqY(}~z zj(VR7HM1>hd!6@hX|uu=7g0%uETpJW@$1s{^( zt^2MFf-wN`q$&~e$}HnpYY6~h6_5~sFd$%1(Q4KOfT+o!8vVdf!x(^g*y5zwzIt(V zs{8VNmQZN*aFz8I}_07ybEgBO3R%`+fPX@j+@T=^j|VG~-mlk%S9^uI>bky$+s77kbO z=zI8qmFT_o_4OhXr{7yIAng?qZ*HKTyN=fS9Cl4l;-e4Ui~H|8jlsTt%}`8I%SkJD zRKfzRgAj|^Tf5+&`A6uv5z0}9>pA2#^9^Ym^d2<`e;ZTgSAHnqR+Y2{9riJb(oCE9 z6lN8ujS8^y9*RW&9 z5biyB3Lk&=VLbEfN03P+g^m!5_0m4EF*lz>uIl0S>+^W=y=z$5pu;Cd!LmDvD!r#X zC5BN-L?bPq4%#Bx`6V=0&SQQ4JiOaikSeTT&(0y7ICvOOJn;k`eC%-~`+MaUBxA-g zLy~Zt4%-IulvmCb%J}{}=kb0vhnu%=!D-U|b_Nl|`{5IcYXqt~EKbw5a%z2cPUZrF z5Ao0Nquj}9%Dyr=taNI4jd8NpWKR_<*ybvv^;xNz*y;+aYsi*Z)kiURa(F<7#d$rf zXIHVgTB7&TkI~@~QGxMAJH1{X z=26WDn4tGPxns;IH}U#yig~6T6GeR(@g0=QMcGF^z5O^wNv{t!5bG6=JyXwkpubvP zqwri78qZsAzC-IUiV;fECMHMZy}MCc=e#Kh*v4tCudLQd&VO?qOZMRhtStQgakeRzQMHI`&Zw1A7A@M6>q|^%vM&TNelT41v=R5yCrVRwKk~iDm=cpNJ&mM~_k5 zJQfoPaPH`3=Rd&NAD*YPR!tPy{Iw|q-dk!4vL8$?&}=E~bYgrAv-?^o6&7&m+#47g z>cY&}dkcltn*`c&*tcs8 zN008s=bryGo_X?V0+lJ5y_%=zww$YD=FC+zC^3jJ4Lg=Voz^^8>vJnh$Sz#L*;n49 zHCV<#PYV46R*#=Jg3|y_nY{LPCm;nMAE z=)&ZV$Cr_Tlj)7qup4~6P zHzUJi;ysq=QZ>&T1nek3$C-2MSjz=ScI}i7SGk!-&?JDocAMVERb0OO4i;|RrWndI zRZ*O}=Q!Puk78ze21kz^CxDXFA{ZyoUc*pPeJtdbv9OxMRa#%K^<6>BqhvifNuLw+ z{L?Zw!L-&`l#4yt|5h*hJ9Yq4nl=-Pm{F z5bl5QQS6?XmUZ9ub*{;BO$Eiw2FT??9cE+lbyZT6?8s8P-oT_l0cAcG1Q&Ii3v8HEVga8+l5MQj{d!g-?F+X*~A$ z{q!CZaz(M2{>h#@yLa{f|J=P6n5Fcbg+D3AbKWVfgu zR*UXsEiX%6T7Iy+?7!f5`^nOh)@s{&Pj$~hwbIu;W{e9TM$wGz)^(aVelTptuq1uR`T2bt91}klE zmtp&BsLWqM>DI@<^G6sROkp26*VoRU!|#9ZA7Xmf3^JJ^3Gx~aI<+8Em`*&=PU)ir z9WfKTo-W}la;B@~#2;B?V+P4dMbl) z@}MmxQ}qNIWCQAqpDvdWu2p3)foU2IFEG+(XJ5&TMKByGlad}*7Ut>ei3~lm1K8YH zlg`tr!?QSg@BsP}NtuI_h7j)|PB^`=1XhL~Ggw?N;Nvf^3$*0v3NtDtD3HohK$l0- zZ(=y+ppjk1$WR7{5ADP0)2GEo@%}P9=R#er%YmSte`8j}Pe1z{3(pHeoy?>essrZB zAT*Nz48?sRtcg-E`EYIylT&Aelt5`9xUe}=kmUaXoN#q0c7sYGC+6)I=H};d<;oQbZWmCgb1N`S>lYPHe(n&2 ztu~qG0wzaODCSp$TJ(*J7cez7hCuU^Uy@ng*oRo6`fdq{0^gIqR9b?cWITa`2M*xU zyYJw=OYc)~5|RKR98v<3Tu~Os%Zzr6b9Q}!N|=_0L2D8#D{#JgU$g~E#xSQahK2?( z_vAhU@LQ}dOc?aN$bVl;u_i7{G(3|tEQE}XxB zrAIcl7MTzsrx}nG)q|n~?)7y_&%-hu>0a@CL9I?_juNH^bI-8+=pKp`c#lz1nxr*m z=oK@iF;%mnRjmy@6wYBzn4xlIVCmUBZrr$xdsjZe$XFWZPaMVp+8h0SeYi*gEGMRH zOYKldv~w)oJ1A!?WHq3iZjPflRX~9-d$7lIwMNYhc~^zEz zBL^@$JB#mr_q&pKjEszsp9-N#F)M#}HA9|2o5*mbGbyC|QWzc@!Ss&3n3{e{`M@p`nlR!(4goR=nf+R1iG?dgRpDSHa9u)|M6sDTr zz0Soc*31jr*s&{(fssK<;v;A=i4Ci_GxL_)?LKrl+r5rmM;VMXaj>^J47~ zPdRPjKX#R zy*vf!V@DDT%X5uZ1!3B3Zf*rDw?3n&<0cO8p1|&%)7ZUd zpH#tu!D>m$06pmQA1UPr>}LO!&7pr?46v8!E8xTr2B2I$a40LMlW@xn4u~c%_^mg1 z@t?d8zWCxx{QT#?pycB+1yWfFU}RWOxXIf(0MT6fa61W!p)2G3@PYuahvAw3gV~f? zaYyjM4D;ctN3-Q3#&8{J3zKo>c?ovjJeA9EFf!Ooc;Ilgi-IH`q)RXiQa3Uf3f^E* zEBfy^?XL#C-zMe1+cgh0%^Jh7rx3G9`L2A)g99p|3U#D%%T+@OAPfiTbd;_!hIDE_ zjvhOVOPAip$y3KD00>J5A{u3SO{=pm!dcgJF+qXXE5~ZLhw6zqdao(=oC$I!nIx@aB}>6k3GFJ2*rjp&FthUP$6%&k z27v<_R$kDfdxXFfpzNgpLn zQ3=4Ly=Zh5$;Ctlt$un8_oqbv$Z3{oA2nr&li?$=WJCpk(q-=nKmu(ACiS3XfpPW> zx#fE+jPWfk7UTE=wP_kvdMC1*eu9FWES@}hLczfi^%^?iHv&kOBvzV6ULQ=h73p+Z zI+*+wjmEH@uhPBA2$6uNU1T&8?p6==ydp!A1B5|HYtisS(lgyrnGY$*8N$17pT!^j;U7>ku|twQ+l(;xfYcNCrD}Bu1*jeJCE<=l zcpgf@{>Db)w4Zii9|gu~3bI=iMc;o&XR27l7zOwYFPz;yjrZSs6MyoD-w}Fm_P=4< zR-G*NTb8XDecixdwS@VOAuDH39LMn^r*QK4NsJGVcXWe9^o<#V={`+O_9K%C)A_2P zTq=^k?W5OE$czEsYi4T`7CX-n3VWZ$LhTmL9z28D{d=+aY#oE+Q~2<2Kcu9$g|(Gs z9NasCZW#pHr}a8C8Iz@bt^&}(bQp=0Ny$hS?eZ$hxdoK6>o_=0c4TIT0>?3Br`Y!M z41z#OpoZEtRJXL<7TV^B?IJZ8$JsMS@z4J0e}@AUkTdL0L}xu#LT`x17>gYWj^0-~ zISI1c6T|&Df95#7-zZ)>aR__p9tsqf52UGQV(7DQva_3#$2h}68%0ETn7Y}-%Hj$t zg$**tEu1|25-z>>7T$Q{4e=4;CwM9zs{7COBIt~DY;TVblwvSl@3-E%h@V-3 zzvSW9cb}oQ{tU^eE#jr++P0KK-#q^^{_!7v53@77C1#3KqLogkFh15NKE{B7ZY7US z9^0N$K?EU1aFPX0=`&bZSI)F34bAvByK`L8fmR@Vh? zJv1~d@!R~<=NQNw)-25`A#Al;ihYmPpv^SQt|Cq1q)mq7liheFDA+LBNN`I_RfvMR zCz@PL*raBhtw4lOYs839Hv6Ce6WXD1?#{QWVF{z>dBM1%E3;LqcxUU^bG6W*+YOfZ z5$ZBL`g*=aSn0%4JJL}!G+K)HA^TUJc~g8=19%46Gi$JTzI)Hp_ki^U>==vVy|>Qb zoA19bLN>wRvZzxE>x$d6z5c7qGycxU?-B@9iKi<@fZNYy3fQXTT)9)wAP>$Ep;SCB zj%aWoBLPl#*gOcFb>yHQb8{>B#VE|c+O#LY80=(dKSAV2@Qsu z6+K~F<{Fqm+!MAnr53QbRKe0l0gIajl(@>xuU}@$))XF<4a{xUDH%yh6}m3N#$-}B z$P#ue#SWz&t`sPOc5j%1o+F3$(C7UoGJOnFIfTQ94W?{TqI#%iUB$17RPFFr?;f&s5Wj)B(U&C@6F3ME4vSTX86k&5Etg=0wV+KJYq zEmRk?*dS+^iX-STU2I zP+jXihoBpy_oQB1u8zm)2Jp~of`XKE+z_pbzUiGfNx|H=zj=v*x&s2+R0DHuC26GL zUA3~0a?8Z$Hy+^ngD1$AY8aiE#^BT*at8 z40#Y?Tuq5-D@qsy9o7f;7m&>tDTyfy!y40Tia;H`>67_q0zI3Y8p2m!e1d0W>-QX( z#_zrV7C!jqySVt;%jBnNZ5>l3X7sZ69+hMUW{HyXYB@_kXOTwW@S(kU`<*w0T!xu) zPQA2O0=NVFc8jk(^U^V4FUnDX<~h^Yzkes*eDfkEC&$(Js?$;w`>yKtONOu5PbCn~ zWYT!`;;T6S$~oFoqZCw6t63Tyqo_<=717ATQm`Ju>DNypz2hLZ@)WeS({#=fqH`sQ zJd295z^A8XWjFzGtQMlQAO6+9`PV3~ZsULY7ymPE(0$rm-Jqk~(p^TgW0CzppUdc~ zH?t@2qhvNozIAPVnUeH6itB5rWalZEFJR}?1SO;=$bKEBKw7a9$rWpMAPxAFLFbM2 zCf3$AFgiR$YrYTZJ|8Df9l>iC&r>oQ>nS(r`B>H}^7Wh%Cjqo*vwLzJOM!liG$jokSOXx3A}dUb^P8x_yFH{ z^9@YxnAUzqUje;bu~5bO`nnKe@T}_i__&;ZDKvWu62sRwKD|eRx=R;MmAVQ7lCI=5rC2_cOTBol?SJqNKKS50JzMMvRXWF$3#)l- zZfukPTE@oa3MCG(L#aC->ry|MZV3v42M!K{cP?>ifra7N&Tv*U5gg>Xf+0F*q_zaa&Xs zF1dI}pM88Hjokxe{yWUq=%O(jyv zokUllOG0!@Nh`!Bt}M4iWOFOGiEZw#$HFpy#ac3@GWp$560g%bL}UH5Ct4Dd_I5XX zT?`ZbF7hvi)_n_fJ_14>@keft_;yfeR1>M4j)+2SIO^|M!a@i|bP{7K1$6bgO6XAu zJ}P!RE{ZTy9}`+Qts25H4UZIC>!~7D(7o9%7Sx9@Gy_&A)97*n2M?ihH57F&KdgW% zSG!vdZaAUf;YA)s@}(7{o*5({qT!(jU082J48O2QMdSlJf?bDrgJ8;E+T)hOWy0(- z92o)KDzti*X$S<169P^|cvgk06a2oMfN)i?&4ay6XGzfp>x6iL(yO$Y)Xa)aiAS5c z;%#yh5k*faL+)l>;8o23%$(-D@Unas&#|!auB*h5vfLI^%W(+U<{1!A=-*<@=WkUZ z+G@-jPL3ne1-M+p-Jn@n23b0EIr<+ns6N@^p} zy-eI)T*JeKZQOmjfud`ZA$O&M?^Ck8>BW#Q*>p|HAo%p2aaKupd4DQ;Ps3ETae-SZ z_6qgNbRG{KIfj|pV@Rh4B?#3;IMoH{4Egiigo!2(kFr9yFus|H8bXI59PnHrWkxMd z%KNMeS{wJUdFwOS+bh_8_9dJ>aTNOx?4tx-S98SNnAmRA@o;q&_g6QuR>;9E*HBnm zM4E;8n5HypV|sF!oIy%758`xK4owc=%}^ZA$qyc4j62&Du#p34GGkGqb3v}BQF(?I4fJ&t3#zLfruA80evYMQYr;&%L+Gxr zG_+eSrTLIyxRq0;wPR7!Hto}#I4NP`<*t&c6rZ7sTr%tLsK7iy0X);TR>;Y2=QmL) z6)`+8LCFXYTqb1rQ`PQ_4wIPbXnGn#sEP^2d=3kX3&`aiRBC*kDWNjw^$3|wig8(mfVnzg70fRIH)rpqi8 z1A8XWmx)u-G_8e5p(}ztzL2k!jtMKtv+Dhwdynzx!2*huFo$DFx?WmS3aG2qG6g(E zNhF>dBnv2pE$P1S5dLSMe<{$dVri4!wl4ZH95}uD z+6Bag3fa*XI|9n<(3i6CtX;&N+qc9Sj8FI(UEk1XkzP!#*%M?NsK#7bZ>!h&HA|qqDmZD8% z<}|yFi|@UHk6+Vv;6dUGDNN}1vb z9u6KB+T6BQmuGvxU0;b*C<sTl%cb{4`~mQKiDxy`}*uIT)BQjI&#l9){sn6Oy)(gYtJ$4KX?ol z?7Vs~;-{tQ*RkZPlija(krZ$3vp_mw2+9wju7?p#J+)WD7%V|eNK zVeHvMi4ZfELLq5{na<-P-x7ZF=~uXN?W#ZtS@5z=LG3H&&*0^g7ck3EO>Q8$HPxx3 z|Ha}C`62^9{>hKT7BpzR?%lbLFxi81=Z@m!=~Fmx;E;yMSy1AhrWD-S=ZdYO=RKTX z7214GxQ~X?lzc`dLGFgpWcTQKgZ-3Hk{@oi@8ZVoCuECCWY>zc-YKL~A)%>1dU$WA z6V;}GJS36}W@irv=3`-b1Hbz9m$-NTAqtELh$ZMAHpn;h3(a`7+N9U7P$I`OBcT_F zaaCbc!^Q%=4nrMGvooCT3c(cr&Sq+1hO@dF8XgD_23)>6ap@?idww@j(FuyD1x^DR zZI0cglg>p-nf-93*u~=t%xW##+X6>3rQjfo%&);lOHqUd35cZ>%KuX{1D584)R-@x z(~x{#+D8_>p&_~#U=Hr!xuT%zc2r&sQ@6Q9gpe!8hH7I{P@(Lfs};_@4pmqXe5ho= z&|LdLJIQ|m#v-4Vj6yXM7Cvc5z^pC;N?^t+Tj7=@H9R0ILp*^R5%>RSNh1;J#f2)8*vWD8q8me>mkoLB5=)i8gckx|ZeEZun=bIrZI}a@N}(#<#H2`vU$|#9&K)Kp;&9<`C3zk zmCb4qjpc{fMO$^4=LKFm-u)P-)j` zi;oMdgs)Bh2gxDWS4{zQ%3x1_kk}?uaZ;eN6gWEV;<3un4$Y;U4|?*>x!GL9TQf%iZ7 z4o*-K;F38WU#qt+oT|Fb9o7?>uVUGKyi-NDAFH8j3Y35 z1_ONh=-ID~M6tAY5aq|~SaeIUlB__R>Yzxha*L8N-HPT}fqD&IyT;T~s5zE&bsXkt z_o_1V?HP_5I;W)0V5T1g$+4&S(KYJ<&lru4WH3COq4T^8-+TWJ3Lx{M6raotQvjjP zqO{gos4^56+v3m}W%1>W%}soH>k6(vS;ku3M$@8TuEFKjtUA243brY5X|l@cS$ zywfpy-6Gq)kQ{8oYAL-4Ko7cyR0oxVCR&sJcuEHEE4dXE8w%lP#M1EF+IG_3EV`_D z(7=w72)5SOu{8e#?#W}a)-wMgMXGLq$USL=q}72Jccbb2F(HX`_EH&27GkpJ4fN33 z`rX)`9X3}{GkpWtIn_pgI*oRvi1pPCO87b4jH%Dah9RsIq_~gKfheNn2i7;T2&l#Q zeS>hq?v?s6wGFg*sB}zZ`flHUin;kkv0eR{BqdJ;3Jf-I`rI*SJz7b!)j3o}5Jz+^ zLPA`!v0cFBoA>bXFR$Ri<7GH4Te32PGIqaC{=}(ac6ykS#{vd38N7VzIR43>{S&DWbdG~4wh4T{nvUOz3Ot$V zR8GUD4b*7W5eX|%MK%{3&$qF;n#1zbWi+Z`MK8;di6_G)+8HEe*2w3;D&%0h{4>1q z?yFJ&{N&S*@XiNs!>?}P%CEQJ(^+v8N?j+6UI+H5e3&7hd64!=W1xAp^Xw_z%AJ%hxt>ZO>AL#V;z;PJoe4Z;G37;#rMDerx+OMlMSnMGE_*#*Sk&0?O*@& z*I3)EBA%GS)w{RQG_FV$f9Kc$;%qxb!;BG<5n(C{ClqNr<*)e0xr10+eu{hKEY|6s zr4ngG{4g%xUBK~|PGU3@<=9&f0SbO!I$e5)unevIxZ*Grwt;+hlM;Yy0$yn6luCPsJC zKGww@LveDm-CtVSkiz*VpIyT*KmGzX+1|l^+C%ji?U&=?i|sJ)*_zA(1Fx z%r9@^^Xrc(L8u}T4=~Ez9+u^u9-A6 zF-PZp3{A_}q4o`~&DCFu;g+enIhkj_ZRxpK-rJmr+G1KoIu&zOyH()}l zXbuIU3}a)H$89!dCKAZEPnk6jzmu^FRdZN+coW6PcQ89Sg10Wbj1$LBsC(8Ej;lnV zXLCSR%jBMMCDK9+y>jg5Ugr|C6c)S`dpjY5^j>=y>?}Z zoZcG3(HwT{h~muYJvb{>{xO-?;sIqIboK*$sjtEgo}1{48%U;N6f8z5KWiXD_b;1W z!@f)c7hic3Z@hI0dk#$t{6;8N^;VYi(sWSG<+1qW39@Tj@HPslEUhBV4w31yqhX4g>yiz4s!=BOc6ndzoL!|o+D<(WbLhYx+kI zfXvM>oU6M`QXWuqgU}r!$gu9<@DK$iTc}scbbU$m_YaCtShL)2y@Z#~oK-Ms-B}k(Z_T8`T45AdlAUA)Yg4*AB2I0X((&bBE*y@~b;orNR^3*H zf{hN0;{3@p{r!L>8fsswj-tWA7!q_J6v6l*mrYK zE*eLIkinPGfX*RJ@WSa9K;i z{rFmG4=k^5p+M{U7eD+tPM$i4>DeQ=arXv>e;&cbv&V4i_%V4eL43JNdd1L8rU?p@ z4$n^Ft@EeRmm0y^R-G;;B6BZK7FO|tpZt`5KaFGi_94@s*2gBGo7TQd{IV@~B2IDF zj;Tq!e(_~GGfj$t3V1%ZKpze`efk*AoI8!7k--;^A72;WV@^Z{GjZ&hnWP+*>{yG= z8q+m%H=2BeK$>RJ}R`s^b-UCLr+&q;jr(XT09%cERsP%@jufxRR2-H@W3yod+ci!R;7 zowEmV>bx(4fxg$o=K5_EC>beiZ>xDR8NTiTa<@dxNnou3118U3?wH*RBSx`_!?3`p zcr8aaJ~XzWTSTyVky*U)J-hx@pi+ zOZRl|Mx#!+K&`&JozVzJQdpu}LiRVJy8oswX!CrT9WZoAi$n%Wt?q!54&;LGh8`gA zT)1Svri6S#b!w<_9nsJbde4xwhz!ntEK7Kc0~%gaxBCNa1o%qakCOyuqTnkH`L@o! zf(@;&!!ytu*!Jpr_@>|anTnGvMFPnKbs~Cbt15*qMDvh24+Y7vm}~%BGhKyx?uGeV zOj3c4glnqn_r-vjYDib~9Ry{qnlEMuN~6T+RPiifprKq{hK1NgD(os(?}hf0yi1rp zOrwhJ%|(>fmIYgW=J;{E{`%{f+_h7xhZY%eTbJq$%~Yf&6BXx$TA!|Ol?JDXMmE(c zm+Mu^v4&nh_-c+u4R>nRF)`(#fZks!q&kj!0q3r|9Niv_)dTGcTI9h@)Ne%<|CtX% zU4kC^gjCWbuoV`c5FJq)k2kCM^uaoQeR~6o6%#A;jHH=Bn1YmeiyS8FbKOVeO{R*;W;Zx8p$tW)Cpm#Wn+$l zg!QM-Wwxb{4BLU-GdM^A$Igi<3?y0TE-YvP@l}3EbzZ^=3`OIJlqg_y1u%m)x8a#Q z%u$<*hsGUO(ejG7rU1#XgPAyWhPcwrEPgUmCORQzClu;5+JjE5rHDAh7@LYYiEnF5 z@3n}f^vG3($>=y`LrGR(Xdr``sWB|($|#X>Z#k^WYg6#hM@fn=0e%EAB*!LT7A>@k zSyXxMjctnFW|2s|bB+wHrw}x0_$}j!u;AiTsW=)gL)0RYfcR!qAhkR*#nieXBaN8p zq1?<-Fr#cnci^#G3rNxhXxVLR%jXerITE)xuT1~YSdh5wwRHNjTWtWsa&UoWlh8sSvy9~Nv|E!H$qGt z+Xo?;@x&K!!o>TZgNv;VO4j2>msBG7T;^{ZHYSW<7Pw?AA&goM&pX7DVo2Fp^ZZ04 z7D0`JD@wcvhX*k>K1xYaM%_CP9lsoO=Xky&Nr8BZUT>wbfUV6H>74GN;OfA>T_WHn zSbtMPJselMC%k_q#?u%X$sm&|((9BcXe)|XYB9Hnp>!0ly?kEoH_tDafx?EN%TBa+ zYm|7cZ{$!Z*X8i;oSwqqAP)v7I>z4DH2Hi+suljI^cg9^9v);iwWQc+Kf=XI3aDIL zX5MTjQQ&z|n<=s_v}{KPjD1OV)99mQ@L83qXcv*09ad1CU@Q57pAIU-I`F6a%hmP$ z2lruOYFsFb`EMBF7E43~?iH+?#41qpZefvy}A|$C&&J^+0EdUS6;)1 zKmPGiA-}mHjH0`DP2k}EN%RjyJ4Q?KGnxp7*c8D-LLfl(S`A6E zU3+#it@gBh_GZOFBx#FxY&IOSCngf{+u-)yI}GFy*0RqBeP$fj06yDtKgfp zNLB#H>OOh`@qicDQk=tm6JV0h6vz7pIsG&I7BNpM-LH0Z!Hs|SmLsh|>u;-pr0)|LCh z5TTGB)KcsN>P0OL2knHt9?cr zCs(ZC+0q6D*=2#$Navm$3>y(aJ~s_C8EVvSX>Z&{Hx<-tCUaB)rqa~Nc5SdF=u#Rk zt{9Z2#$USv@lu#dRdKa~yK96y!Bem%lKgO$UMiLqQ3!8)4Qv%xfbDg=!1hN_Np@lUY#{4)*=$Of5o?ww|Z&Itv0eF^M4d=RJ3o`yz82sT<+ zO1Kwps@C*GI*l`X_aRIRurD)&5bfDC8PC0YcH#JmW7si0shG*w!?;GbEbl`Cn}Jk~ z&RSV?hnNGtO|Q$vlO{(_o+(UVCIuYL3ag&CrE0}2H8OKmsv}-)2&J)0fpg4twf$5{ zh1Ch|^$9Q)#Vey*$qr+?T*dRXbyO%p;PW{(Ifi{xL$sfoS_{M0wpWV>)4y1m{=|`k zQb9NE4J_rWGOStkW0Wk=UgFu8W*M<&0ZEU()81rWAFi%3RK^oFEeipQVJC1yx5LSm zd1g7feg6sWJ($N@t|}N_nGohclb_q7`xACBK1ji0IfqQlK%rO`h*^W~6A$PIb?NSr zH9KPxj1hk}zl6Cbb0Ug8JTxG1ux7iZ9G+=(jl~P!Oi?uEJIc!2+of&XxN!ru27BrSJb3sR;i!fFkrCCEGQNI|FTz(D2mbi+9IjlsDff-3 zf*Z9e!V?2xvn?y|i@nCl6m@m>k=)7T#At?B=Q@i-!*#z=;#b z6$FW^?lN;@ihY-k1{0sqYw)}h7f}|M))9}<{S?2$F-YJ@PmK<5w72SM$eBc zOe;gPxdY6&R!>i^^I*Cp_#ye-@XQzvA3Xru3*p-3>ljX1c=NT_aq|l8wPZxa9eRVA zUABkLc~iJ{#ro8jp@4T_Kt4;I6TmQsvULV@3X5CBj>~0ilWpfjeQ9kI*Y7;S&AZR= z@uznwapk#?v~;^&j!pbBrqV4`@=t01>_=hyW$7kz@Epw5@>($)mXz?wXfG_U)4h0v z#f7ZUlkVT!kI~T-B?!A|Pwk-OCWUITCXhNFg8uVA|97}?^%}Nw+v1NdymAiT|8M>T z{h7EXkI>yV{gGLdivPK^w1Ce(`wYiVzDJ*V2R{G&W8A*`2r)a4r9Ie z!W_hJ{QTj5ij@w{Vs2pr^G_ero_&raC2KL-BN5~&Br0P6>}OUI50@}%Tb+R@#SruysCM$$;p14J$r=qwuKE! zu2`Rgbuvz!I)lmSp^isYlq9C0S$NqSEeI=I%P9+bX6KG6N?Hy`awSYxNjt!WDzRU% zm@x3<$qELCX7Ki<@8Y9hUdHB+e~D8kk0Cucj^BKBlU{F|64^eodHv+O_;ZH9dH6@4 z-olT5{4-p>d`D)acr+zS_lvs-EFh_%`lj4()&^s;80m2H8*`CSqc#e{R8Xi{DaWgB+j-9S@a3sa~T}Mpso;-U$4~Kev0Tx&r$! zen&4PX{5p~Yi13fB_0A(j0>VGeEOc0FIguSAvFRPYPNs9E|; zRo6YKczUK9h%`-w;q(JMo@HukwU8Rb;mswLa7C4<*lZN9w5KOc4e6w~oBL_ItTH`a%$k(M{F*%YWm$?+um>FHIp z!$}nC4HQcisj?{2Wmk_}dkU}Ut14=tW}w<;!OR#!Op?H?Z)8w}DMA9KkW{sN860&5 zQYQ#oc9`7#5{$Yl6+D6daoxaIgYF!)%Dj-w=h&*vDjffiee3i432e@M!S1L9F(kh3 z!sxn-k)VKVXvYrt6fABROjHd{*`wCwNab%J}5^11xSg<)SR6&Lx|Yp!*kUGA* z!z1Fmxa;6CY%^e!L66_}eJ$$cX?1m_-@*rzEi*gczBG4|Qc9JaXI~ON1uQMJ>SYSF zV%WKJ3X@ag0!Ng&E4`;gpGadAmcg-OVH|sD0O_=i<<&LZ zzyA=c&zJFNE>HKN4{=JIGyQ#(FsISiA4j{T;6`@H?3k4Rn#b&LJP#D3L;06~`B(UZ z?|mO{zx_Ub{5SuX%&;v}63k+ns6Jilc z9_e=+MM6OzX!q`EDau@U`7A1A8+czc3CqARB_Ea}F_bIumFj>5h#syTPf+sG-^Wal z4CgfD%t)Zkg$a(o#LpUf=v>)>{B{jjZZ6>PvGaK6(gYK;(xfK8YtcF6xK)I_RW_myA7cvH z@NlK@#m>izHR>0V5zFk*ewm$s#}JGocRjDjyjh#fN3Esk*K z&6go`?tp~k=iJ5d?Xb*%7{+jC2E-+YCIejIh74~hwh%P~!k?Qfr<~MCMS5+k|P!zpE&UFmm{np!f{rqXE5UK?> z6x;`@UFP)+=LarTf@Uc0OCIAd(XCvsdf2Emv0iCV5M4#B-H?h~CK|ygrR)>wIEIrE zWXzZZdcFYXOlfZNhH*San<%Qmoq*i$8BFTp$-SP8!}4F8cj}Cm;P3lT!~QDw(E^t; zk7QzDeg#{33T8ZR^(QH~j0%>O(Pw;F;h2q9D2z~oK3%O0Cze9pG z=qj9P)5B)If-Q17W?~X%cm!^}M8ETe-9aE{w61L{BzxIqXaN}tGw2Soqt!#W(m>_; z61iu}N%@8%WbnAkEV?+V8qNDiav5JKEC;;b5)u1W*AaAXsMB!-B7Q{MH8VDi@dHsL z%zi}4XcnforRpDNioDV`Dqcw>)T1efoP1pdg1PTy`#n_>J!Rv3eHDxdB?*IMG&6F( zB8eo@nG)*F$5>rm#b$O(Rr94{r$B?j5P9$jTTu}%ikd39=Ri4qO3JAfU$8}7t0LzoP=qoL57rn*47_`wNGNYaQLj$z#=7`MJ8il zZgq0rHr+ReqGyI3@&96;8qDSywGbIoRCv=*4Bp)cA< z1?C#nIy12qaOcqiu02@6cCAi(qb78P2S)pF=Hx-uCXqQdRfv(G+i8o)UW|hFi)T*Z zv}0hi>0oel1eYH!VKK{i+d*=I9>V18D;v+y$hwq3G%2_*%DXd!DS%5V3f|rcY)5{V zB73lJ?<`&|)sfwrq6psMxH2`_bc2nW2r=KbI>?zqw@e z!q(X1+{B*#8aH14Omvis{4`KKZ(DUiua` zD0ywv7qPK=7wao`5s$@mcgz)5s31NFv<&zWp?e+A_LzX)um)h;4R=ahphv%^k+Zt`L1AX8=^)y!wL?qF>zk9yq|yUHC9Gt4txim;|! zXbMpXD_w79%hI8l7~6~KnKOvQhG@%CvPkDlx~OzM!Vwp>;&aSh`#GYt_n9_Y39XuP z?wnQ|A+jR|YhOsQ#8!-di41n^I)Y@MP4;p?<|?YSyc9#9KBYu3>d`f@_QMQjW~OM* zox}XoJNWe{KP11kEq;i}YxrCRae$P2HTxBJ+!)QVZ~q>=`KE=H^-u7x{^h^M*>fjx z_WUcjdik#fiphiUVNC(c37Q(#>OvJ9kIp*zFct-T>&@43=0rly^V-TST>IijLho8E zZ~qPl9uy+gzj*&MZ0;P{scA|e8+3o?pWH^4UWb|P7+%b_!lm~P{DCAw0W639o0$QV zNlKUp$5e7*+a0YlSEg#X2pV}|w$#z_My=VRb2lVKiWDo7i!ste=R6-4vBU;3VF1tm z&|AshS8I3h=l}P=#rq%p5&r2v`{(%4kA8?xeti{{>MXtgEH-l<+3gLULnv9hr# z1VyjB_6A;ioqQH&vJTny>p#WTdR`S9MRe0p{71gm={gI8s%&G1X##uq?!{YgnRw|q z#g-w4U`C}78EA!hT+H+}+{tr#g8uHTMh7$!bZCBQ{QLhTyE8qXHX=*(yOATcRWP+?zF1x8;(AVnd zUdNby{lNjAl5h`(D!tC2wU|_24FNMHq7ddYu2VWHMh6$FMEz97m%(qoPCytxEeS}g zrVWXsD!_gh5@!4kYT!U*Cs6APVq2T~#y% zZl;Fv6i>b|ld&)r8Tf3YjeG0cxV=`vT*<{s-9oav4i`TDSNtjQA7ZtT4DS&W{Ft~`@pn#zkCuba+M1|=``)1%*N;0S(u2nEdNkg>0gjjnMt<6Vh z*G*wQ;Q{QRFdmSY1)VKkzG~G$K377q&_F3)6Lzaeqk>v}i=I!Jwex>cTqil`Gh$B()KZO4o|*AH%7qA59C~h@_KQaWtxNC6%tvfT+0jS`qyq`*7VtTVsyCZhUEjcy zr^|S_l*M+F&OZ+$SBm&J<{%SxF*Y)a)JRN{Cr<~W0_QVAo$waDW50vfP~2d8?_AXd{AN;sbj}f zpLAO?1O4JFr0Zbz_+Wky=HsXPP$qv;C@HbGh^?y4tfpKjl;n$peAeAzU&Dj&jCNqU zUxt)@_{%H!;_?dFttj220=*ZD+ZDP3tcKBnO7MdR;k_0QJsa3q-@@Yj68`$b8z|Ql z8=UDW>^fJ=x%0^X&5$#O;x&XqElm43LB5xV^P?*G@spNlCQ0hn^##2J7!5DvZuEL~8%xhOu&}g&&3qMW>jmk`@FPNJ zhoQ6WhA%4bl}c4e3W{a2B@Gu1Hzai1hSjI$Lg{6Tlqe@z635-b_+T5kwWmm@4kJ*4 z<~a@{D9G6gg2}s|ixtlnR`JVE?&HSw4N8DRWG~3?TOQJxFb0PEW&L<<3Y7HLs$AG= zV00*iO1XwzJBBbjF+u0Hp{Yv^VNm0)A-iFQlyQPOJUoa>Baij96U?GS=@3i(RH~M4HTePSiscKTOT%%qW>U*@Dfj zBJJCT1mb+1%#>Os+f!?83)>p)a@rSBfx>fVJ(u66{l86T_6k;37i2b#$%bT(N@C84 zKBH~qHfL~j&VHn(jq0bpIEX`M}vpfm{_&sfI)AGQrC_gI& zRd#w!k#M9N6`_ER6&wZMX($zFnMrXKj+H;Nt6*Y$*QEf)2gPYC6ouYkjvgd(0%y!j zV6wmsT8t(lUPCAu4OVB~-o)WE7jfv|ZtOX@M;TSwFp62km8sOAb=H%J1&N`d5&=q; z@OV3qua-9P)p`w!?I_COAv7W>GFYw{KxXqYJUYmY77}y~L-ZNO=%BXpWgLqpv6pO3 zOlXoVZKL$yyJ2?rN`N2_CQwvNtjD2)3G|Mg`g?(|Uihr4!(%A;AnjAu6WCZQWA5I4 zR0<3#iz7mxr%HP%%=?OLPKegsY+I;tkQwEQdknF`378X8D45&A`okS&hLT8rpl@%H z9Mw{mg1oYUW_Seg(SxX!DXH|=X#cc@@0$a9?i_e+Lse#=^k&qcUGVXJRgKj5&zCNr zPAU;_VRV7wmLV1diJUqOX_T;;*s z{v<-_6g&zLSU1BhQLx^OAyT8jh=Sl`jJq{vXRZr|f(!=N*U2F*tCJ{k;?^Kzlc95O zhdr5*3Wqal>+;Z@siFj??+n>0@Z~C{sN7P5QmgaqfKLe%Lwv$0u%I9m6PThzrX3wt zGX!m4Q7wyFZnKU>asbaL8Ca%0Tnd@=Srv{r!Gopcx@bXg*TIQcC{h3yNfu$c5j@Bi zuxZ8NWctyx={sc{2Ayw%Rkb;&VhD_{@;le_^?xhuxy|cBXWXK7x42!+up2|+s5=6* zMtA?4X22@QIDAJ6AyvBnWeQNY$}ObAKGO9z9z0pVj==;joPU`TkO@6Zt6JN3&>0A* z*>nXoP4^{3d)cM{rCjl)y6)F&v=i%yr7W>q*=!zlrVWlnx{KI}+Z;|^kCoLe6pA(4x|Vj*z7|gN<$9F%lP-1|iY|R@ID^CccTs?Fg93ysn(dm52yvH& z{RoBMXoTYwoKwO?(Id~-w7E0gQz&`CHW`XRiQ$%88#z3EvWO*06!ZClkbxwb(Zw@# z$HNF*yt*dVRQVdcxO6XgAeRe%tr`Wod5T9Wep;n}8t~TYqS#%<| zY5l@>Ns5=vR$VTF?G(>enHD1g+6cwdQuS93oPE4v4P+p^1T{QcO27K)Uw??RXI`Z< zmBe5C<_EOr+LV;1MUYMCjp3^2$$NNG9P7F13W`ey;rU7y_Z}`vPL|uGDJffg-QX~l( zs*}UjY1T8d*tSR2u(!Y#$tTn2C>L5{yZB&ds|C!j<)xS@$$+bfdAQ&biIZKWz&%r? zvqfj3MQ1R~=hstf!?BK{H|2Z6#l#RL*$MGQbMyD{{s-U0)vK3r?fNIu1<2=fiis4# z`3eRHb=yEf6h{PTIku};YsgcOU84kq=ZH9ob!Cp$=^`J{b9Q>p62tlUZ+WJO=US@d zS2=m-t{~5UwHmB{<5Ti&kPUB1*O)8jTwrm1r9ri_R>Y^DUB#nE3nJ^l0e*<}j5uyY zjef@SI|{Dlxwed5Zczf4&*!m~eJ=V+w(X1Pbd<5YQt&nv5l>k8)R6YiEczS`x9GaE zc=O^(r23xX=It*~$Zz0#-}?iM4kz%lAO8?{x1Q3yX^7H0?>k|GIDRm1 zp$wx4#A!AlUsG~PV!{}47X337=e>{vA(&|}H0IOnBpSiAe{c;j3{6k0er|;#((#bx zU`(c^I|lq5F1ND7blbxA!K8SeuNec>q>yw+xDz6bSW?bV6vM85ji{x#^94sKb1_|M zJ_%UN0Hf*2EQUoJ+;wVnKU%celTtCOQox)E`G`~CA8wQ|f9pD;sN#(`Ud12(!FTcY zH{MWKbYBOelAtlIp`{(Yy4MVSU@m=T({PQDKu3veMDB`SY zt?id7Cfb1p5ver`f}8;FsAqXRKS)=s4h|dW;t);q?@myp<*b*=)j#07U!@>;Vg4y{ zn;TeLcahmQgN<4hQP#6)Qy{WkqL_&sXI8Y_;)}3CI0*G zen-}nvC=#!&Gu!vP{3lLj0y$wWqRMC-KPbPRCr9r!YROxkppd4WRAg=xe;Cabyf1g z6+c6BVS7?m&_;z>vUCSSI!vbOBSC1eDi z8ApUs$Q76uzYYI}X?D|zFtV)*1>>e*F?kk+l|(zd zJ;iSY`})n@&QLoqt>H9ig10*QX#mMvlm5RdTw#Lfyw=v4PtZxX#h_ z6N_MZy)$Og96 z{0*CoDmeyTSx#yMrpK*tIx7htu%lqBRj(qFuq22Jpf6(cd}YwtY1<(^ljZutWK^d! zTCTSQ))|iT5P1RD?>s{J_p?wgLXh%=8ZIp3dX`@EQdR zRa9E6@*RUiK~jZ+#Vk3tx%ub#!4LihubnxCT{~vfakSNE4Pce+c1yZD!Kq{svzLw? zMmAT*Pk#0ZN_79Y8_H}oCIv(NX(uf=r3bcKJ8MdW^6{p|TmB^Y@@q1>DOjFzFF0&c?tyqNT zpknYSK#dt`8OUY&Usp&TxI=4`&57yf&^0r`4IT8bm7wIFd&;)>RGvTJKvFcZgo;-< z@uaBKEPD9$Pk$x4Iy`IWF*{l)K>>J5gxEOvc35}GQi+y^qKRR+4Tk` zV!qJI-nw3v;#c6WL}b_Ko`K#+i0oD(ox&Mqd@+YlMjAy zQO(e#CtS#iGvl1eFe-*A#}SGR!)LM_j+;z{lHtZ@t-1L_oXWdiC6bi;}@#h$#TCHn_I~8+x;a33! zOV1uTN+3+d;$DYbDu79GCsD<(UZ+E%ey;=t19mLmeQ~yfA(Ik=!0&WD0tl9RZ*8|& zn3L`gchdM=1rKg)u$ZdNE#6=#JP6u@K+yAgv)kWpu?5X~m7n;XfBQP4^4Td16u}j( z043I^Gbhi}Nknj9eLWPVab^ZOJi~rR>fP^D6Af(%&0yf%fARVxWig=NFMx^l91g#S z9l%pxhM})Jzz8u-83#OM__*3?F!YKm)mjeQ@|9qqT(z$&d~|?ZQ%!uc@SIJXrL7?j z3{CL4ed;x3^%f{Jo1(t%Oy|#xuD*#_6s14fNr_!~~|JNet@*gR2!GLkaCD-uITkENw4n zANcYHY7pL&FruWsU{gC`{c;TV!(%N2UfZ3=1&bYIF0(CV9j zJ+g-^<`Pii0DxzF3?UPU1oW4ZoQA|P^58EE6iOQGDSegzsAkF>m5u^gD2~3xq7i9* zyAt{{K|`4CVO)_QM0Qv!ERPuHI;nQLc($Cp&bm zqzn8|3IJ-3qqD-k!j`t^MQWTJh%#-M5|j-5sDb#8k_ z(qQPq`qmcmWbmqe3Dj6=md-?-j6XvvLgdsUbxIPdB{7tteUT$-Qv%v{gZ8)~ z^B!)aE#w$%H^k=piY8lz23hT$=d~(znC&wBN*2v>j*fPf64{tgWY_By_{Q{^)JNcj zy{)TBf@zlayGO^Gf-X*e$TnDbe$Jtg(MOHihP$<2n8mKyJ^wFf@BJpnb!3U2%*yh%eFNPMpkWDs0AWZ_ zBqdQJFO5bsyEC)k7a(V7SA;As)}ElRtfGo=&&P-+fL%v!s1iQW246 zQmKG6YP;~eEffnGl=3-4|BRV|vnm=OjmDaQP@{w0y&mq|U(|k&Mr)wrA99`Tu9^MX z>v2D{0u*y*FH2Ix4DWI@V=ab69Gg%~(=@HzA{M|r@#)XO4kggz2$x&5H zfJEHNYB~oJDB1|>h}w0MXH}FAxs4g57HMbGsUo`F6za_igMvDy507Y%M7tAc({#jp zl)yG2_FWXz_}<-)P#8oaxQ}wVjJ1s|blU`tZK-ldRYe3>eB_JLKusT9-XWM2U);g= zPD=$NWKw-R>1adxpx?wGBnW08;kZ#Y)KYT714?AkK6H#P7SNbX3P4F{bw!c`G67sD z*F#xcWiD8CqtMVclzBm06A!bdIwrXVO_@1b`Gk^RX+7gorEaOsj(LGrP?V`5O6g+% zBnXVzzEiEp$MyXpVu{%8D$jkp+sAjl`(p<9Gq`#C88$ZV(5I*1(I18)Oe2}-P_p%P z8G&lfxg*1Y)AXz3{P>KaRw<^ba2En$M;qUvV(Ose80Eq+Z z5(UvwMNd@X-uc>P{Exr*NBqrS|2KU5+t*ZxVP|ItJDYpzYg)Z71M{@0vJGIqlpUO~ z68dqh@QmKNMcXEo;c%VT(9`6JKZvr=5l*zU_ybT(Dj)K-#(?KbKKEurhTC!<@N=g} zd!qCBY&xurV+SFIst*GgGha@w4t@acK>mUZ^%$_Ifg%z2Ey`&b7hkmf~dt3TIf+u#0P}ss?)>q=3E5 zpb~tmlw9eT6vf2ICMFEd@my;ROu%l+=SJ83pY~XM_0PdE^3in-by}qP)ip{_8kuW< z1@<%Bc7BHGt`BW`$8f<-^R}bBR~=U7?swihDr4rTyr`K|VU>BJ2V@OTq{|-BkX)-` z<=KW#p`-?aG6KU-iL~5h14!07a7|OXW>qvJZSF%Sjw%PkQ;9gb#X z9+C^|(YobgiQ(r#t1`YR?MVdM4>XG@MX{&5zz6)l-#+hQp+ACFaT0AF_AWQRTw^d` zMA~huroZU1yHd2E;4$jzQY-m9bjjIUU)@fmV&Cz1%-Jq0I{>CmuN)v^ZK zKrMf(gZC{06ac0U-|%W233x^6jB6yrk)&x=Kw`5S!(`?#VyOTv8V7BpwF4r0(omK% z)e@H5hFlsEFw#X(r-z|p7$Itp)hv=omNt-pK-U1pi@D!xsBrdG;$+J zxM^4EkG^d%6zYjODo1JE$Ym0$wH{9f1S5`KXDTg#(dRica}AfiYTm+`BQL2aFxqtFp|$8 zmyRjuR5@4f&$gS!7K7xia@|zI>^KmU>5X{#F*}joyr(EL$#meE@e-C6cHs0{dIr0K zuL;-%x33dW-@Nw>bBAVe;kC=!=MfERH5~kXPOu~(#K{Wx{S1M9Ay*`D+fZlnVrhfH zc28%uv|42XxRb7g`)PLUVm;$-blvY;DJP%TF zOd7U;V|^U=u4Ez&5OXaL+9a}iG9x9KHeety6uCSN{oL#n4o{c3XPZhVYd3co5S28` zxmS@YKulG5o-J-LINQ};C}9vJlol1*N}8GBBKx9PN}x3AA)7ZW1}~G+O1?@1#~C>F zchMWvP_J-bj!dAGEh=Dg2&}8sJ^^1%m7H9ssbD0VNpjsi)1xUBRK*9jQy?@nEKO** zj+t}g@;$<~2IoR_GZhq(+@$^UU8^N#XjXmY-Vf{Nn36dN zo+t{nwepZkI;v_W!M9XeOs||xy2y;Am>ImNIZYc^9-5lKv18J_zJuR=cn|;U7oYP7 zSrkW)p}N~9CSV{E6FOvtwxw+8U;`5@dqsYYA(0x>0Hoika;+K!fNchrn*^FG8VY2x zX?-SP)EH;?QDAY^kf=Q9qPDw<#iviOwJjB>v`*TFRtJ5x!HGo1BnsN-1Sw;Ow16Jb#cgE@mTVyQK!#|>2l(E1-o)Me_wdO_ze0!mEmi<>C@FiL!#>7;=8yCsNKfF( z+A2Q%{7ba>yfeiDMsh-1bFsM0z+rGr_p9b75M{|dMF+aixaQqn9qSuQ*xnO?iDzF7SNs;=K<(pdIlUEETwX3=WpJ_%aVAq3pKu$c&6ABVcWHmFvks zzuHmS{`iQ;Af(N6m}cN)2FXT=ENumdI74O@p~?r#cP7V+3?aRwf?Z$l8$5>4B(wJW-wsf*0y}FVx=2kX ze1)pzyafEQ-@tAu1A*D|PQoOmwWGrk^;RR8;E92Z1|0deT5)g?;a4jQU;Q)8J|nQ# z5`_e|+93d4jD%w-SYNGx3~c{`t0f$J2I9T~e5oo7d>fWKp`~AiR+GpXHpT|nuh#4j zB(#r18@7!)Rp3RGHp6c88&*EL%uu)ibONk0~mzsJ%0+i2YMhfq(6fPR#I4 z);t=1mLDI-Q97c_S9fu9sfLyEIyd}bRaxpveOo4=GkB`+)pe3{v$@56!TZeTRk|=n zAXn-1@pNg80C3kPM#aIpC==Y)WFMp@Ggjh%i;7waiSQIMewRT3f42Dyb*`}+wDgRd z{b&MVQ*4U}>;u!QB+te7Y~yQ8OTpR~<%CLM(mgAbIbMIFP(ptCECzIf?dGPIe(jhN z9jF<)Mi#qo!9rA1j}f?)ybiL>HFTfdKx1Q<;3S5r*;f>ZWw=N77);UQVQ1qJdW{Y4 zrzuPv9#=J&1FdS79%{Ut$PG$RF0z#VprQ8?<9SJ@C4J&Q3HtsENU~=M+c~)^(o0`)?uN29~SPw-y)e|$L zctVHvd|?@T+bbx`V9g?(&gLfeu73$UU(yfC(Rm)5nZ-#4I*m+@dxC+JA0V2Y6Pl{E zUb6}VSkA7ln`>x=0fCp$b%U(*%4; z-cOu?QX(|`Q~K4jl`zv{u25`_FLh?nAu&wO0+5Sdoi)&nCgUtdlfYI*tKP!uvluSH#uV zUO~0I1HawCvuDqFjtInPN2ZU?;@r7;eEU1!!kIIt6wpf*K_+4w)vct~@DhnQcB=tC zzxfcq`QTHmZ9%LDDuleNTDI(kwmDuTXnBJRLfg!B@Pn^`W*=+AflSjM>AJn3yPHY3T_n zmAYo1i}?{uOwOQGVQ|oq`}YYB+XSdJY2h+H*#?GE{c&X`mG)c#Xw34Y9IbL8Ig1$gwlrKS{+e?qCHQOPfkP^drNK{jB#( z#A(M&2+w3Pe2?RJ=Nk;TTb|16_8Z%LUNxN)qchDc5Q}TISNvXA&rpZJeQIh1uU~#e zlL?D2w&>ej?TL`}=vH>{`2KC=$0Qif@H&CBXQi@xn8AnyQVl8n^IY$0aI?CxsjCq; z6B3Nwv&l3OMlcyJUlZUL&Ye=VuST|9|Erpo2j+Y1 zt7}>6@v!MUG#KBBC|i*L5r%A|1kiGq+bnpR4EI#2^}hB>+DYocO2`0rNnKTr!+YzNL1!XoD~(i9 zBd7L=9BAk?hTc``irl3>;Hc@-HLsO}9XR_Hj_7>^Bn@06Ice--G)>)9KEmi8w8_gk z@N>tiZ`cKu!FNgn3r#Xx@nkrx=F5ijVy1^h7DKr3aUNt*@<{V$y-ox5Rc^A~Rm{&$ z;3q%$1N@tR^G7&7e^h~*m@Nqo;#Rsej0VAZumOmtDiNX_CY6=@YrxMxe~J$m_OQ@R zVMP?bvL;ilR4W4GAa0Z&q}N7@VG5Rsm^&_rZlQ0#zX!~fqu zrbw$o1)-thNH0#dki!fQ@wGSmxbffxDxWXGC9s{Cn!|=PMT)@@6|`!TCaH?Fw@aXw z#dxdBK&qpYtUG*I+uIu`m$%JybsO#0=#{F{R3||&0dnd15j5!heRl+-vu_|DD`B%= zfWN!UAXQ5BEi2t*GY>&DE2VGBmhpk59H!_1JrfuU*IDjMG6i{plDa(HJf=>*j>5zY z;*&)*yBh?f2~;}+!>9C8!zML#dCtoj5pl3*j~ymZIfX3Or7<(kvy;R4(X*I8cN#nO zINtmHC)la1ptW@$rFajcV>ui?I>%rlt=Ty(WGd|u!>)XxkV!Q)n-=Nm0S#hDDKF`? zk9M!Z{Vz&uNtLM7N{3a`(6^9t#9%%!MNR_QI-egwvru{n44g!P`)(YI^;LZOY=dW_ zso8zOi!!md6*e_M=94l$Z!)w5u5GtzxkH z40{Xr(64S{jDYO?nd6ut&=iN|+GbiY7|uaiS;ti=Q5o1aO2=79@Okm|JyA~+6}{XD z+rtK-7@#}3UNW1;ChN@D5*d)uIJ2TWet_uw-h27%GtowXbuT}##kwh zTE)DsD~;A75+n1jV!rNkonkJ(rTw|CQjz0c208BERqcbzQ zj`B>R08OyDnU~_3M3XQecwN(DdCbyA%uc1zZ3Mg)Nz_PkF@;nzBcxL9pOoIiK*Sy7 zle&D~Iz%~x8r{ir2E<2^!^okM>ETcnv4ow!XtJzQ9he*|;K=M4o;i4eRqF$+Z8g#EConpFj3B#+R(%hxN==h=f)NLuD0A)t zU(FLn&p{H%^cA^65p(k=(eLK8irKA|5YUJ9WePc;v*+4DywXEu*(!p-60|iZj~+rc z@eTp`C~d+$JbAu^Flv>GcbE_2O%oJ#v=kWt{iDi_Og@8m&6I zy)9mAS*52tA`~OVE!kW;F2XYA%+MxYBQZcKjxh!pr%oQnfBFyqPLHGOBGjw)est&M6Bq1n5zdO4J+jF9#p{m!$a04lIdOu+(A1{9zTr zs6^~H!$c}rf$La)xvi4GHsCrD$h6I_j_Eatl$Ug_hEP0)_pl#;Xp$vnq)x-YJ|N!& zJ43!$BtIF1|NMPgwJiB^qsj0#EAQGNf~L@68}g&;unJMG>d>3gn^bsYBP8VGr5PRE zm^20(kM3f?DE{an1|L8AHvave{t3=sesxGmld0t)4u~Eo6%6Ki5`;-`lFTNs&1nDD zLKT1c+uOLk+QM2;Ks}K{S1*j4L=v(|4A(#`zy7;#DqvpH8_rINl*OW%f+m_Z9BBbE zv20qXzIs0aQAN<{>2&v$n?Sx8N2=LHbA1n68#~zIH7%^x@#xVSCcHi_y)uKD$s9^k zdF_W08A0QmoZ%Y&f1zO+7ZVNx@qy9?Jl%cs^M~-$@4kg@%fao1U7)?mb6;d6KEmhf zD`&q`xeLGdg3%Ejdt(mXSO(c{Qy-l`dX*n zN1GtF#NVGiH;VSwL+q~J2kI;Qt(K{Ng?8MdV?mj!ceS(<)SsLnbymk31 z()^r!VFdkn4x@+0vB1D}>)8!_ytITt`8j4U9>?pKFX7DTvjir5W^UZl!A)gmIDJ<@ zW+;=nConlRg7vjE1{=N_wtlyP+-Q1 zAHV;O@8hR}xU1!^ zWy1CBY!0VR9Knevj}dNEutJ9=gVy725-mTDXUl82|9AlxP99Z}fe?<>nlf2WwKbAm z_lyLmG)NyF&td*>344_?%Fnm8oasAR^cmdv?LI*afoGo}j{C0DDC5m57xA6%d|iV8 z&vopa9|Oc;&!#ve2||v{OwmD3;N7pkp^92Bczwd-J~BVWeUh{aU7ikn6I<2cevHKp zZRg>$WjuJijGzDNWBmTpJJ^_RXP$ZGBnk}J-ue199nLj2T2T5`wlIeGfA^e#V+~K9yui+O0}mfA@_X0u z{qMX^(394Rn>BaPmX_%FTVJKd%lJugYt2Lm~$7- z;Cny#5kYK8*XG{+O{}kMFml( zmbUsOp^##bwDgSzU$%=}jzGy_pww7IqrQRTCuZ^5#dDaRm>w!)D%Dk$phUIKP*9}Z zH=A;~cP4P|)KToLx3RwZi0{Fml)h}Bh4VnK$JN26W+syf@;x2HBWF!}S^FKGa}#pE zHCoGPw^lJVS;EyTSMd7lS1^5O5@vRSne`xNNF}3{E@Zm%CKw1Enl}q@zlXM{&uw%N+-@TCk8!+l`3QdWhu>7Oh_7IN^Do~2 zcqxzXeEV$%4*TSMm}3Ah*e@AR!ltFsY&4L~<+Q(3sA7_=y?ggLZr%I> z_aCmS`c&w*FjDN%cDWh=KYg}9Ofrv=(G+|e)(b^h6aG5E-CV~>`h$t_JX&ABf)$~4 ziGQ6w%Cme3!j%2woCT!&@=k(869 ztQQl-mxRfz8mY2@X?gf<0 zk%U-v+U^^VHt`ql-Nj#hL?BZ-j^xxNuO^9%@ag%QqHic%ZC{nu;F!Ev|BN3&rjdcGs>WUC3f~)X|cBm4|-s@e>5)Dq6L& zK77}W+fU2ra0j8SfqS~n!<88;@-w)is9+{q0eRH|Ly}b6%FJ|_rtK8+JHf_P}8+mK~OsX5{u`!I#oIZ>0=7G?{i}_$Q2GDFFVIG{YcvO(61un))BVWQOtxmcj71= z)m1yG*4iw`2q8#6h)uNd7L2n!a%4`2!L6^gRQ0OYXAnn6^%}4H%9X1)as1T&n27^M zF`9kl(7BB<@ObUS6jrtaY;DHTpzSD2!)f6#`sog~_~@F#Z?}vWhe2=ADcZpr7&4Qx z$sEqi9fQ;EU~a?=?i7`~k&!VRJ$V*EHif?3B`OC|-%*_9F`6X`ua zru#mrvZ!>NuIQH!v@y2VEc2O_ab%)|?|U5JCQYZebi!4H1;4F;m`^30Fh=jaTvilG69 z(bJ<1&Ev%B40alIjB;NtE|=kca33!SUK3qDvsgj<)>Mc?CAdYMFRpU+oX}pK zZeION7;l;$GrlGk7U=Rzh;dWqWL<+UpW8Ot4GEO0xO8bAfAmK`;kEt&jvhIp?0`r& z#%Pj9(-!+`8?xz`-p7S=Cy-7|Fvuw4=8YwSyPE#o%JbB)UoW!KQC zWSX_~xW(h5>ej^6bQW)2dksJR$sghC-?*l-(MA&0we!(1tSaiv4nDsL2At>5(m&Jx zZoeMlx3`|*=A(6NZ}*j^(C!-fS$VIxpV43w40_Seq7#%+rXPO1xrf6o`giReF)B(! z1RdJN@+3i(K%TFeVF2=nKYW*f{WLPfcSojn%CN6j*(V^|>(~b3Yc=RyR_?NshpRHg@p>t+(T+?g|e$Q1~(_>H|G^yXd zFXwv>*Is`GX>nq{>F;t>iPbaX!4sxZbL`LvdS{QKnDlvGk0GBM)tNb?V_8gwpbV(=4eOsDExnCt z+t;%{6jl0RRA|E$1l(sp8qyAIC}m4*fDG^ynq<2p1Nf5sc^6NfEuv5;FaViR@GaG$ zH0_JZA@6gX6-O6~Ijxo)njSUEfo@uVEY&cX=srF%0xko(^c6zceHkz9_v5G)c7m6% z)v)1QGx9wR2#o5Vvwsn`30;-xBAe<&7R}&qS1N5<#CiFB&CkuXxR%Og3vGmDC`p(`{J=SMvb&C2k|?SD=&(cgU>{hrNBc)U+V#!dmYmPQ$$Fw0;8m0qrByOI^e1z9e!x+me z^~I54GcMmt1_w&{Se}_14I1+_@DNp{j3~EAcB5S*_~q5}FxC0FBlpmhfn|k9Ii9 z4LYG}47ntY7B^T|>@{{N2es}}r?M-!#7tbA2>X$(d zCd2Mqxl+fC4BG)|!N4?9%BG90W2#HRQvI)zpc&K~6Jx zGOs}R$G&LL>yV8++RXvhWG=!i_tHojgA{{GkrSk&eYUxRUw`@l)p8GSzV-?f(}afR zAkEww9oosGQkfJ=j80Sbb?7-(_JGBebv(Rt54+W>0;<mUd74zvu50cZ%5E5 zU$n1$ZO!U=rej6k?)0f6s8)MeUD?9c&KmZ3TZxW?L$il)?%Y|-5jYyV7Fc?UZ5|Cw z#$Dd$==2oEGkI*ZGkEc^g{@2xjjV&hXc~>i3Z8U!@X^8w&b>N;EH`XU1O*1p{ydCm z@;J|Qj==cJl}osC`4Xb?q|ZadZK`?JJ>styj0Znh+{N9cO>~k%8A&7FcND;g14=SF zlZ?40KIGiVIC;KrCNK6$Gb>*9n~eo3nLihR#B1RXZ*cEql~TcGCsI*7bB$tieuy2Gorpw0)Z$a z9oVXxbWV$0_OZj5JwA(T66>bN2ynKrvBxtJORFZm>+lRT*5UOlXm*>bPBZhtO|4?R za&iWq?J4rCy^(bnFkq&2g$xdQhCaY+7$u-;x7&I^Ma4xjW(%A^oh?w9y_C@+Q@Kn`IYCH)I{+eji*ZAnl`11Navj%Tn!>N-1G(QzW_nqjp4GSOF~39PSI74UuY zTi?Nx$G4HrIb4%Vc;njJJg@Wmx&Z;E{H||B8AAA0A;)-!G=unTA&&3;;2pIijKOg3 z!hI|)H+emi^tIExc4#xY4kou%1}8Sqth=aLxq(m}lcqu#XCRM`1|Tl7aQ(CvO2Y0g z{mmM7w{PS6=l_6qJ&7Ov=nwGk{`^msQio_DvgPv!>a{K7LFiR-`H8Gzi+A3-fQuI- z>pzNC^S7wgpP}C9DT_jSGKK0TN=#;Yrla`8AIRXvE_w{uBpD=P2ttALJOcZ}<9Orh zHGJ)jYXp@esL8Zve9^2Gv!^&(Er9!0>VIr{pm`0V~N>NO9= z!ZE%sr2;w9(x^cx?WHKZsoZRBkNapB<=y94-)`di{UuyGcXXI^4XxlsD8doqI_RHT zoifgxJj!QvNHI}D6BTjvDk2UMH@02bCUNXA__+6Q1M6FTuH`pz;mtpRNBbc(NlB*G zc9yWUavfiMP}7QKV4ZQq{D?*+*yut37Ga!;(Fwf8XLSBN*EL4_m>ETicBH(!icaGN zc6SzW^Y${|Gl_4!Gq1f;(yXk*34Oz!(cz1d&`r8HfAOq->F4xgLmH)EWi_b;Vz+ND z5WFA5pZ}RqOvh9JBV-`ks4g>5c*=d+!e`f?;p*!rOlR4^w>@3voCx-mghh(M$iUi| z9v3F`1Fdw*cn9NbTs)&sdbYBoy;pzo)1NXh$U)`~9-10MgTBAnpzq&V#+P3{*4G@F zpV6Q!8M9?kW!Ko=W=T$pp>vEPp~{RC545zB4BWc;f`Q2x-hTUSBr~*4PEr-YhV&~- zy^1On%1?^qcf-NH1g|Q~4vaLejtKb56m=`b8!5vE!TtnwQ~3yNA;GG^2Ej}39c>D! zNG56XI-M%l$6)zH%u|W*xMws!hYjw+aa&*CFabz3$uPEG;u``#*BLgyAEeG0#2QT^ zHvx#5cADYC%PNYN!Be5CWyIB>_qnlj5F(sm21tx_EN&_oon{MWHbOX@RU$k=Snc+} zjj~JT0mUqLIl3QC@;`6v!n%N#dF-) zWBfgS5!g$~+;_TsZ;?B!@_SvqS1HZ=u4koHO=Fj29Q=kT^VCp?^-*7^(c4}|(A>kZ zGqd=~kAIAx{`g09I+tJ(I3sn>P%F&b8U{ghMm)#{3`6@5q55XjuGkL_+o=}XBU}dwmKl7yehyxdflT@pOwV-S z_B*ttO`YO8;GXb;7V-=dJDY3RS$@P1XuwJMh94~v2thFsEh<~dTm-vmlF0~ z-hBHFyz%B0zLICAD^1jvVkQmxT1kl8JdI3PNFXyA#}9rukB_%*V3X@mank6?(8cUw ztnkdXUu>fG47o1o@*cb?+u<40W2 zH1}Fp<+;7Ok1v+C@aDTom96f#>kN!s<8eb<7L`)EMBL&~WKIm9rU)lpJpU@*`|!Wx zlaFrmr5U6$X$>Mpk~S7{KXNZlj}@`HGr-ZgDZG02BrcvisZ|k?wT)(9sYrzt?NHSo zP3@Zunq;>$RiJCBlQ*!uT*KN{1^4bf!&7n4&)0DG-V^Lp8Y+(|!zM*iI;8P2zJ&HU zi0RxKPX~$-un(Gij&1b1dngg?-u&z?9^870*RNhA_&ba@xv!%BZ!rPFlaGeXN(Cfg z=W%#8gRQdG$wV~e6B0Llag*2gbQP=X>jb!8GDv!cO0|J%y^FE&83rucg0E|6D8sU+ zdP*^j#kzE+UFB+vkK5ec!yo_T2inN(YhY#O^1#kDGELoqnqALJ8nFo8_j@0HfiJ#z zqyXi?<5jJG^oZ)SQr6%aonlb9xkFGHpThi+34InCASWW{9S#-gh6x&R?p{(U50WEU zejyFKJNV?2Tlj~6_zgCm*oxDDO{3u?1?Hb;C=et9yVAR&FXI~fyh~@y8bfYB4 zbO&?WNs;347|&I81)qHQ5$@dI;QHn@AtMu~m5Jc=6zoV(XK1I|yG~Mlga93%!KNhD z48_>f3cJvj-9XM!6Gi$mNfcf<`vxvu{yI*dIc2%@CeT$HxC}Z?Ml>;r_EMV26TmI| zLt?=~3HbUq&f>lIKUTjj%7elH5i*#oY=*uDOWN0Cg;8Xdf>CkHsz5_7H=@;mi{~%n zwR6`nF*zw3Un-~Dg{4gM`b8O1L<>Y-*wtaHCQU0oJeD@g_WH#F{_bZ_@Qa^c$L2 z$)I5u!9+oaOZ!6^{J`E_-)y#Ko!_}%Ys?Ojk`|5~nZo1en+!y@aQf5?P8>f%Kp$b@Q1?M3oS>iFH*-p~XGyS+P)GUW zm8~}Z```Q?pM80Uc4PzFJF>s?8i2@59DVA33u7a3oR}X+o_puvg9W^L;V8`1ca!P$ zEY4OD0B2wMp|8DaN!rhCwGq<)@!kiYpj@t^GZ5+Gv`LPBm8ld-^A36k61FCo*q6&S zNr5O>G3v9>a}>$-8oPN=Ue_l1eG_ab8z}TO=^F*38b4^ST%f^+uVN7$26N6ZnHd)b zQQ*Hkg5ls0ILCS(8I<+XAJegP;6C>|><>o6VN|Y_n-C+Sou+cpp5D|zHdf46C+d5? zY5LXx+LTQtu+Tn^VHwzZjlkE^l^d8&i-9_X{oqKeB;f%?CF!`Ahc&R2BB@MhwZt^3 z2YoSqI+?<7L1Tu~r%4dkq!eU~JYhQzA{}CoF~bO>k@f?j9Y~Xr38D-x_7%x1k2>KZ zBL>KCpuM+_>XX~5%5d@YJl_50*YRKf%m2>9aKxy7bvs7Q!b=S2qX_5`%bALs4XNOU z|14Jrxbb)szkbriaxaHgs(`M+a(r%a%dLqS04noJl*10?^cuRFu@N$3K&2B8D6$2b zoifTTJ(K zlp6Tr-m*ICR{so6p1WlD)3UXM6UpmIOIFnPhXdduB_LZIC^`NZ_dD4L6VD09u@{C8)sg{&Hyfhx&V_&=n1knn#m7UZf3pCVj=?Gtc1mWmB`g|_cu#eKz4C0x*$~3lO z9jpc0NR|T}-)tgNO49r#80;pEgNd2}RmvGd5Fvw$=?n0i&zA7z{Z+KLyC~84XN5x- z%VEGLCh>5D)d0Y{l=Q6OF#?W4)GcYoz z5_|8`$8T5L=!$(5+D{_Qa~Mah=VGlD!(z3M=R0j=XVOaV(f~_Ru^L>thF7ngUmaIz zf@OXQpcWMmJ&of>4huU&)tuDkh6j9* zxkPihkr0#37H=^)TG=S$fBoVkd~xRy78eb@708|R>a$1yMS+e{j`F9y}yXg7=-(hw>J3}m<&j>}6`G@3P&T^E^SnK|N$)cio{rG~;M zQp7SyF^+ULukX9JTT$xJ9-r0x$zxbqYZKu1Av5OU#kjH_B3&q<*2JokVdR3LJD(h{6)`W^7`2DD7u&-6kXyR@y$#d4NV{^HV`c@M`y@|`0 zj^X0DtDuQgU!`+%XlFe4AQi{TfX8fW4NL&uYK2(cXyeiIGC}kU{QmPN=nZ5|5@uji zZHER{_IraEq>Z2`Oo)ME0G+83oinRVy04044xX5pPOHn{w1ztOM{SR`JESG{suo9z z!VihsC4t@#wEP_jfkcn@f5%Q)n~Lh zw>0>u)fj~Jbrmp_kR3?Izk@12Z?9HYiq!V@DZFy-h*m*GmS4q-0yED*_L1aXVkRCn z0exJmkicg*9^&)c3;5-Sck%4mGS=31;8(a`6Ld;`3hfNnQ6&C4#06Di3~oS4z#Tht z1T)7Dqm)mp2Xt){zZp&p6a2=E`k~m0ZC?Iw-oJ%k|N0Z$eefKM3(GcmfCh%S%5s9cTDuzeKRD-6^d}gfKBTk?gHuxb!Bk+%$r%O^9Ud4*6j%gMFlt|+^St|T3BUOG0bUG7;Ft2q zmBzGhrnOE3%1A^aX(?g$+<~y>5tpG)7T2mCwQKU(0!*cGTO6KhzsLC<&sRt0YM|w7 z;1(A>c+VY1$>M-jsY29oU^2uaiR$!2!w8XTil}SN973$xM2aUj#b-IFY!Upn@qC*O z_5L=N3AkIaaa=rq1Q*ZFt6G!c((syH!yDAN&SvH;<+ z0bozc! z%40x%mh0H!wsCOx=5zdV>Qe=1O@g`6={Y);5PkL1H15f)$}7f&a>NG~CUbba)!;Mt zQ02WPiWBIh$Iwg4#PS)mY0Q?Iyw|l3YT+*K^BzW$G32u;WO&|EqCyl4tus`uH*^Rt z{{oEYb-s@(is?qclH18K%|drQ!*-Go2V6m&l3s6PiU9wG^>Q0~%2;mqn?> z*K=#Mx&GP1ClTzWvDV+g$B!%6-g}P2`6Nn-9?x4-Vo@`gEi7UnT-}7tDs_!|Su&f$ z76bCF)&LLJcCk00tsI$E+G<9cIQgsX@)jPh*74u|@gv+hI)(9^htso%b)c6~EY$Fh z>&swTvb6&l9_llAW8kvBMSxkv>2v3le-GE3-$Adf8B&jcN9<}QMLW*DQsvi2x9(wK zeI0k7KgXeo5gl-vCdy9|#jL&30bv8B6iGruQns~b11k)+me#hgUFS71 zz&-xz1RKfvPB zDcy@Rho@9-a;Q)fnlsZOC@J$9ZC7eo+pS`!-pAa@bC^AGnR_jdOm@tuf=OC~{weMS z1dF>^+9F{3=u7N2>d13*NM&PsVp2hi=NQl;pQV)8&Oj%HudHozeG+*1Xax-hMJHZ; z1INz4MNm!K(XG)RwN;U^(M{s#zx)hGXJ)n6K`LzdY{E`c56loV*ECe?3w?Tf@`^+uWRXRc3ZPziY+bSN@MrnV8_{a@V2le>%9e9_0zxx+X- zHG)zxqig1=B3oSL&I9Sy<8u}|m8@5pXSH0b;pyr!p7JbAOdrL?x4(t6U;9IqoUXTg z{au;v?s$YyAJQl9OXiw0R6B~w8uTYF{2X%zzh z=S!Pt(3Zb)ySuws+2onznJ-Ko$6H6vD|Q|99QBhek)`Gy&u5CN zsudGPLLhs%iknZ?QR{txOa^%6^l{r8oYnW%WD7A%yVuY*fz1sDZOs6;pREAI9T%=0 z!kH^yQ_&HzYcIDR*h)o2gHqb8txSZG^mR1l+$xA7I540v91b3gDDL{q^*zG_-^Xw` zp-4r${G5TU#14}`Llvw*Y2OZgQ?FA;D)mx0VG@PIMzbIo&gzH)kZ!j>e6bqR;eVKZ z59RORs}&H(9B6H>73VFyTWOx{>cm@Z3YScvHi?^oYr`^<1TCH!7$~K}4#RXa5j|9X zUd%>pu5FSWh`~7!)wx#U)3MhfjrH=rQbd;dA_Jc4U|`fa`mGMy(qyd7l`<^FQ_iY1 zZ%Y6o8CwBuP9n?S4fVRTQ9WU3C<8I7{Cvl0YPneQjww3Sq%`*Mfp>!z68!hh(+4QO zc#fk-r}6GPZ{f$^{|>(Yy>Dag*t|Wb;ep`IKHiuq{+Z`v3gCMLa5tZ<;NkKPKE3-K zyFnH;8jD0|rpG2kx1ZP7tI8DS4o1fFTG?=QsL_B2A#N)(1P;>6AzXK9a2wc$o^byn zBuEi{zB+NwOiWkpY}rix{bv0A84j)v_L0F}Qr!}D8I|{?F>E(G1j#+6X!LWF1ld)z zx_j6jjG~x2fe-HQp}|dj;+5kVNu>E6UCll?$)pCK+SF=?Jh?+PA*(BI)10nlphl)I z+N*BD653&?T%zB8WG07K=0|Y1vxj=cM~Q$hH#x&=J!a`MagF?mSEV3YYcE_ zuZabu(UkxrGsd7LR3k4s;XP4E;r(U_{&QnFI2lv6W$eX&i>oHEA&ByXVy8rt(5&sC zrSygjL6o1*i<}k>t^~?CI&kj0m`v);!Yds@Hl0y*l$JDb3dKhoB=f5IA23jFF1N9< zwuVt@cI3Wy)dA)RvK<}V*Q9gYMFNywo7aay}FJ6=x z^cUcyOPD`<1udSfFp(4Qq(ToZo}rNYqsDs}@Se5>G%)aJ3)PX&L54ocx_Egyqs%<9 zNFFQIP1JVUcv9a&j=&}>(ufR1vQly6nv24aPz3n#8YpfPkW~gQ_89q82hzV&f-_DK z)=Ba?#Z_RzS4YjW!C*inCRN?pG!|(kxGy2QZ>l6cp2d2*uhOHgS5&(bZ1=IS_#9rd zf*k4$AbKb+{xp-Pfwe`waG9L)v=bUAMI6Zn&IE8cCfg*%eA5Pi-J)zJ>y@GoZfYO%k zm1}4aIP_^x%G~%q?N&=VB_*Jc%9%}+>F>%M0hj>9^b&d+gv4!?KvJg?fFu(ly(*yw z19x6mQr6ZpMB7Hai%)s|(quYPEFxFT>vhU>;+&|Y5ws|G-`~ATJ;veRTIrx zgO0tA%_^S**Iu51^a}PPkU`)qgU8mpRSoina`l#9ZPGVJ^-*R-$XSy+dcL@hd-oPl z$Ru%W{;1OJc%EbSp!cVK1V*E;94XIhznY2m35IGNAYcSzJHbP+2B1(kApn_?Jcem&ww;F%T(of zLi%gU49qIpUy#r4;_lrQ9GhEH5F(S~;|U1{`wHAdau~L9EWPiqe!;xP&6BDQr7M-U+PgV$4<-4UJiQQN?HR=OU3D zb6XmWJ!AkO($N|Iyg(!;eDY4GrFg)#vigFF+O0n7^glj>+s&Q2(%ZIns@UBja1t7B zEUWAcv7!AzU;Uz1C_FjW47g?BqY%Y1Ihrd0|5cP3aHI=yED-$e-rdICjcrU2WXn3c zeplyVjpb5ExFTsSKANweEMawbN5=xRc_ua&c952!XkiW8o1$r0;(8Z#hD4iyRY0Gs z{w1SQxhe{-)M!tsSwa;TA0U;*7BNz*a~s9{Q;gEzj*XWHo>TN|McqGf=~v*{s`0va z%MDEw)awnUSXFtp9zB1G(%3FeoM|JG9nqd|fql{s*yUMCFevD?w|H;642CMo8j&?j z#H}Pyfc@c|LjYmq$Gg1WrrL%oLH;%>bs=eO>(uZrZEQyTf{OKs%2-4D(`0tZlc!5O z!!hl_C=@abs){;KL}#K6Bv|PZLv(p|>Utj)p5ro~MStKaGv{!Ly~?m$MhWq zgO2WN5o_tSYdCxIC?@ISKK}eRZr^*ZLCD;ZU6kp=#J=ToMU0G$Y5@B5$#X2PtZJW` z*skT3O?0`}8w3iOoKXbpau3O#*J?lD^j|V`*^(4`?HVK6?F&$F#3W zo^j%dWLA?0GQX!>-Q~JAu*SXRx;gq-+CQDNo>6-ygN*zAE<8KbGwK1+FA-D-OmCp{ zz!~~fXaf^}_&QB-OAm(~{4GIBB(Lk(LE)i)pl`$`^^D4_nVRM4=kzqWqm$Sz1uIg) zQgXGP>z-Dg%xFMg6V0v_Q8ECXhNM!d7zsFACw7K4_m?XmdJ(SS@B{<=Gp}*2l&fbV zV^3tbOml6hnR3e=*C@g_;nHxDqY5;05j{29UFiX_WhCWss^Zqb%p8#b#E+U@qQ)BY zccio{z`;azj#fZoTy@EE$y|f5-8F*&g+I;BA?Zff%_x6bdB4$cyCfH1QeFJHR6Jt+ zm{QDoAiDG!z<3=sJRXCwWIWJ}f!i*l-Pob=E5oIspPMS+&;IcH`0)?Ek4u*>VpNny zh8cr>t^Fv1^aqB1rOGY5g!>Dt`0&nCynlm%M?a103k1Ccp8`_dT?Rl|;e~rKC_1KM+qF7J!wFs;~Sk-;~DGJAT{G^ViG$9I@|SUIC^3Z z-@0@Hqgn?wAE-gt!K6yG0f!14u>(AdVdBM>p`%|M*dSRNcM~{wd_sp7bqThvKS*FF z%wVye!<|hAzQotPrhuEKQcd-5~lA#jHL6d7(X%p~PfvL$U6ekX$ zoe%}H05Z8m3gD$;g5b4_CIM^M4GAJfwF_!h8eQ(cu%%7)z2+wGx6JM1E9dj>tp{2*c2Wd~)AKmlND^!lpzuM54B`ShVVR>N znUcCFlci`B1?Y|yQRY3!8abmWeU?2wo+dqAoPkU{8`li(4!@jU10I1!veh=jFyo$5 zjsl?@CUdCLK{RDph{s@!d$2`YC(I66B&Q!&r7#g%5Ls2f>!ZhDvsdrwtQhH&>2(K| zA~HaS=fBfVp%-=tBp58n90djsPI^)sPPev}vGZsHgWW|Qqqc$&QA2TqwCR`922ts! z$SaK@h__H72ncwcZl2EH&GP)wCbn&)t=V7N0fG^cd)?lt!KD*@vRcz-YpGgmR-VRP zf{Jdl#x<@GV3ie|bmTroVM=BU2<=H4)g^hvb<-}{bOF6W4;3M35xhymZOGTSyx%7> z2(#DGET~WN6CO>ci)T{(j+vQ4Qk98-cuJ;ui)xNYJ@)%L z5U<;2fXe_xk|9CV8zjOcbm*e!qsUtL6-wPpni8%k-L-tH01{EKtiOt=Rg$Gh82Mf8 ztLwFKJ4=wjYtN=r7%df%E#%dg)te0hrJ4dFnf)MQ2|B-_CE@{TOGmPwEmaqpaUoPW zr9HQKT?1{#y)S)KVOM)1$0o*A>Qwr*BuOMP+_eVnZL_2McA(S3Wxw}^ynI8#=I0O? zOJYL1`(;_Uh8}}Bsk%r-Oaf2wDe@e>_`ZNlw;yN)OQhF3jjm=|Wo|-~_Qe<4ubwp# zo?$SeN(2&wwqT54q)VMpPNL~k8CVS9soIhB8z~J%=#w&?TGFPnZ?%7n@6oAhzmtGI zN#;lpE)_2UWRi`Q%zZRtNc_KEZ$DK3BUK^oWNYxfBzBLt&DoD}Ux-AoyuYX)5wirb zwyGa?X$z`@s^PNb9L!xkj{o?d|1E*%4nF$)Lp*r8h&u}v6jNMNu5nneBg;LO;Tld( z%wo6EK-+zS+;|>mUOSC(+H@yu;&1-vU-5Z04FnNsS`jbcevB0)@g`Lz0=o`>uGAy( z4T3m~PmXgSH1ytPBPS8Qx1S91n7#^EMghIiRYDnP5Y=fI?2Pzx6FR7Sl?@7%3 z?Pq5gHKp`R8p=DuCrzZZ`k{V7c;EpeZFzV>gAY|2y`&T$Q;Jip-$YQ| zL2YLR&D}N3PL1Kxm9sc|<~08OzyDLbe(g=u&}p%;WNl zG)A$sW1eMFhCL?DOc99(lQEUw4dSM6LV7Wz0us0;I|V1|FLPA20or`z8g(VpYC@yU z@5Noax^Z4>kv=>`q7z4+K|@*&W35JTT{TKBIU@9Q4lC80`0HQaK&!lmcQ2p8+~hd_ z-9Tm}XZN&iFn68(iLYUNKPWjsfs9n#g_qjn$(80sq4OmrVCB!w9UH|demz}0ju(v* zp00IpdyT;S*N^bKni1XRz z2sDy8Pwi{Zw&6&Nmvl+1JxZFsU7?ty^?Alsq)PP$5~6TKM=FhF3~UMN9%&1_SMmubh3M!U@kl+4ZdMd|ZPipKFrH zjEiowRu1AiFl>bP$g{#{D3fPPT)!r5NJuAAWKa^`_tzX0X)|HMazPMi-q# z9;rN^?|1=So`-I*4Y!a|sq>Z&+~YgS-)X{*e2LDIL2hh>KBc9V$dt4QbB&vJ+N(|h zkP3?ge4$8!7Kq{G`SsA=6=k{xk^MHgGtmF8In0i{xo z4iP$REl$wq%anKmd7sx52q@3{vlVvfT(#eh4qO`!rP0L6Bau&_ znCv6(dumXGjw$L@lAw{GsMo4$K;9*w|>- z%svv@91m1+bQYy?PjQP>ROCx2Ye}xTWb1^+&}A?gmHt&zpH5o;9U3}Clq514vrzl) zWbT53U-`bUq+B(FRY-}~P8-2huaq`&ptb6UsDesWL~L2A&%sd0t`l)MO*p{)TwhpIZNlt^5g zjfAi-4(sW4MAR^uFzF+a3z!LY&$iVbbh}3M0!%%g0fJDh`HVA^HhYAc=1>zR{Cfj| zohEA-*q=^DOhAow(Pr%mpKd^xuvuF76W86~GXoP>>EfxdKl*HHde(Gp@Z2dp2)!ec zVfX;LvoC^alifuM)}`#?V1G|%5n~t7-M5+@GOeKlfq4)N&%==7{*lusq%bc`_!H(f zwQe_{ftc3MNUv)nCOdQ02u~KYQd5sFW1#Qw>JJ zG>7g(t!5Z{gRV^(Ok?OBRMmhNL63!J!NhLZaq4wT^~VYK8e%fU01ccqU7I3FxbMf4 znJLS|XX^X58=AZiuj_$WkybjCVtie$UA``3O|s&mTnK7!4Q>ON0wgw_-jbX=bw=%Q zM~SYc*y%%$WIEYnSGSffR3Ft&K&>3FueYH^qd!NSnpBr8jYWas8k&rg%HPzCApbFv)b z8Immxoo7IOfqF<%M!qwRNdRpu%8~B(jP+BnzEKBE4_!wcUbC^z!Vb?X0wlMP?2N+dB#;ek0Dyn$h?c^d$R!AJf-z$c!prRfv4y{*FyBBnGlJeku z2MAUWC=S1lajd9Bp|!h45)4#+!Sec zGo!#|99r5CVpPF&gjusu#@TEFH#-kx#0qpf>M#&Q^|B7iMpk6&gkb?5f`M!>4HOQ_ zB&T`JAZ7@{S{#HMYW%4WqCC)pc|%6KH}$tivU*}g-v8jwQrzk2@e^|D&T}%;1BtdI z#1~O~O3{Z4&j3sgsKx=@TQk_nlb5#Tk*6-n4=?V^ez_zgHSB=obk~k)fKakh3S%B~ zSSu#QBT3;k5g2IzU0-dns798KuCC8YN(PPzW_=pWGs289ll3AoJZ|ZhB}v8UQVSdI zHk~mJ4jXLFpiZPxh68Wrte8b;-$M`&!Bw)Z35fnT#%aa~&YPN)KqsV-eGRsc^iF6n zy(iCHx-8x1b@I?3KejIILtUGVq4~*~{1Iryq0n1rlR|K^NSQ!|(75iyrxrkElLOsb z9S)bFkvh{oFwnz4)r9le&6>QhF*enDehjKnO}RcENW7)jfB29FM;#e&>3wMYdZdGa z<~=F;L&BVLI@=m)F{2uev<6UhZ$*+7!h$R&%^?v_QWhNw(urvBJ5vXw!R2H)W9RBX zgRt3NEcLY}MJ%Jp;2)#CA*b+`vlZ#7Qv-~ne{&y{XPPOjQn@!PHrbBfyY!S?dHx47 zy!0G9T+x}c(!Tv(Ika+w!Sl7NFUj8JAL!!UWU_==h*3iwjwS?gYeiR4?>jxL&R|vl zgm7BZs-gNkG;NTjZbyGMWAz7m4&e81#2pHs9USaYJ7ZRZvhSW;z4oHC4#kr8mg!vU zsETOdl}#Ixs#A%&8rZL{NFOsrH=)nPy<9ets5hPcF4Fz4=dl5n4SmL0+pE;E z!S({1CI;S-_w!ioQ(Kcu2reQpgsWg;0(%HYjv%xZ z8_hAC$Rr~HM+{N{KyWnJW>s6St=a9#N_tG%sU<;#cIi4(-)O21H$s_a@+-cQUfzV zP7MxtDz&4;5`j=iMWBbOe{hhv9@wc29T*DA#umspZ6s|wWCB!rebi_6T zLb#CH1Km;dRS1M|Z_~*{8W6KYS35u(B5&@e)=}W!i_#%nH6}ZS?^oc~Ynl|)!mLbT zeEX4Ov;j@SkTVK&fHx7cM98cV5{0z^>;~Tm!uI=p!-~fxp`w8B;F)mHHMeRd?giQg zcqW*q5GGnV_d@A3vZkJ#a&9An2&-OH8^5FbZiI8h`>Qix0&Ot@FoVs2;&$Rg=EmFx z5xyu&JRs41My;%rVv_iM%!*=7hNFqzLz`>4yu8f7EhbA96^SUGhd)aniZy77a~Gjo z3KAL=CJGCN0kLDES~qCQMAxIxLja2z$+5yDIhRMkm6t^07K2_)uBkO1T4 zp=ypK5BG+G@?d}9^DP9ioANo49W}<0wFq`}#>BVNTVXN>;Z_LumD!&9p=)X@280QN zG~?1s`rEuQ!z{1Gl)C%K5}EaoR0fE z>r>rFomNU(WF%5iVfF$EWJZ3Xn%NnkX`oSt**vmx<__Hph4Q?*4(xXZScqA=U$8Jo=vF@&?lBpghL zb={Zwz--RciUky{j!c^eb372l#g+yX&+J3NhAam8DU1o*P!`oav&ci(loflZt0Jby zB9ysUq~i58b6D1`fxaaqnDGnA2G5muRBWbg#(2CeXO4)mLPcP~!h6D=0Pcq5KEteB zd!7NCfRUQ(y z`KFCIhcGkxGgJ!8(lhWHTQwsPm*;M{#H8JsJq2aH*js+#5}fTM@f76v@#9RY=orz8 zF3sQ}(?_N}I2dp?+7kMwj=d?16}>(bx7 zB$L4bRdN#u(RG{hmbbo9-uC97mY@I72Pnjb4h-frsFRdL5{P7Z^F71vJAByv+D^sOJSN%RN!V)CrAoJcHqGP#%et)Nw&d?)GC1`@wx>QKXDN+ z92|BXIKxv?XfHC75y{%7qCQjS2y?_LwHSGSq|c#6VYpRdlE3%tO?7&YlOgLZ_nej% zX+vzaqQKhV-0xva{_|g`29cXoW@?yGU2AY(+fR=zx202VN`ngT>Of|wbT=tJhD4== znz6nI25HA?EXP+gnC@nB6>Z*Z+w#)=D3&PxD z--DrBNVloZs<89X(o->mmP%^SwpIchfbRc&NxL;!YBgnJccgn@D(gp2$aHuhH4Un3 zn$i<$b6k_Cy+YB(sMFOzSe?l*m7P&vl0y*Y zI*>Y8S>mzola>bKiLR+S6AZA|8Wg@n%PA`AbUxG4=oyV6NcY*$4;ZL6G43?dV5mPP zWGk9EbCf>kVla_@V${G$v{_L~V(JhP{*x4R-Wj?*n)JgiA@CAF7&Mv6^=$9$?8x>j z=S5!8dmL|)Ri|LFBPV=e{0i0+dHtI-lljH86Sykc-H zcs9Vzc6Lc&YLq$UT!bsI%B6v2C6X$#&KyD$Vh_+#;r=k>uHOY%hscAR+jXIGgKLax zbEdVz>ZZJ3KpAER-xSvb0`(;uAqc=U!Ojt_r50FA(CA$>43&_gw?{)oFo=hcT_|&C zL}tP#k#|^Q*U&+=roxHk&eNH>*d1QqGHjqT6;ah)&tHn!B|NjlSz=;`NO0XeP{TT+ z%nz~)K#c-4D))+xd02-;_!{9FLsgSPAi3)xcu?ts?)LkUeLk*(P~O~FfUuv#o&-h| zFf!2I_Lg*Sk4P__G16^do!F!q6tXe->de6DXM1+tUe3t1_&^dqm26i@K}h% zQM9jrU=&&ij+uxR2E(5A?b#64*YK9LCiacC73Q!X54Yv~=9}fW|F{1rt!^o&Z|jk+ zI&OC5;w!oQBZB;CD&retncmFgKofvN-L9;3m*rr4SKj`ZfB&E4;fEiVCm#Q?^aoRU$2)#j{)c~kr+oeE zUzgAR?(fPBhb?dW+In>yzBC_`+=oFHpLfdwGR{>mD3p5~ z6Y2gU<1DblfMNpv&!W7ag$f!~%%Q3k)owYrfwy4QUG2PdcvXm}c|AVFp3eu_D>zqB zfi1&#R+*|QxXO+4mlbR>x=rZ2@fcuINNrpe2ElU1N_IeyfH3nZtQu5rG#2uYXrbEV zm4<}~u1|&V|VD8fE96^u}$XT2pvV|mk_E8-4+^mJjTaHc9 zGp@&kVxcQikm^%R{4cK*h)k3Y)hkK^WX_J06KI=zi)AZo=?I+EYA=s$Lm2pG$7+L~N=p@u^MPY9Xna3c; zP-(Q!H4Hr?Kw!JqgbTYca5rC&FwhXcVk#IJ3O@Zk|z>1+YQW5mr-3MNzQgNs zxOS&pdh{WE2&+;%bVBOON7PAcvfNr{_il{e2mZX7($QkD7E%8X!vkRaXvu`&P5;)b0ibv&SEE;ZqR z!hHz_z@|YySwUjETK7mjvBAG2aR^h>MLW$uz`UYM!_JxuzM_lD>VN9GMEFDu4a2afN!gl@CX`az#Gf_WQflHRyUD#0ry*7wKGTN&^N)b7|x;VzYETalS zz(3JtuSXSAV(wLVGTsFislrJ(@L5sad=mPikzJLofmw6F0)wz-l$!RFwaL^jwVSSw z6?>du%#CGKIV@J?IctewQST@h!9%b)5rkMnmni3^j#$~N6OQ2#H{T~BOry524#Gr} z0-`J=39lbRrvi8v^qzoD5MwlqYCX%1QuvKJ>BYmf(hruYud|)OvZFyGY)Vl&)GFqh zp<<6}wcWpoSdw&uTL;(Qu(ekE7CV$W=XgkBFl?u;u82ienoQ_xD;9 z$a9ZBr#7~&X1^`>E+3Ykx$h)tzE5`bZ0;PA8_&M1cDf-qlc}JNw7YdvI?Hu=`p4gs zXI}Zf967ft{n?KE{DgZ`X+&wFgKJu81^%-I49?&4r2G>$6@)m?rBB^Q` z>I1Qv+6fehs8_On!sDKTad6r`GHmza3 zvl@#>Bq+#CQ?7)~!}B4;SJ!%}ZSh=eoxRYhE4jBkK}8XiH*Fms4F)Lo%Kv8da~=#r zlPf_o$?jHEbwICPz9fI~=bw|GedpWclb`yyeC_LBmcM)W8?v!+Q{MBQ_eghXS-$a= zugbM+H{>JGZ2QHJ$~V684Y_{(I-!2!VV|8Sk}5@}V#pa{*nfy>MwU26rp`@RviD`x z_GCVefEmHICoDppw}j_DtGc%yWa(`;2z@3=0}DV2_ilh-8KG0=qX@Y}l!~fDA;m3J zM_#uHan%Bf$;o}nGL?DpX~Eu?R@`YMKBzAK{(c(E!q2FFx0jX(!7>txaCCDMMV?OW zA;W(lNN?0zY!jO!D;X#)CKsy{iw zh$<{EFsYy=BYO(~E>SV3+4J`*qxtnzm_+}Nd^+Rr-Ff>N^{cDIyYBCUWnfRP-MA?S z8c?Qg@hk}DeQ z+szUXi9*h37(T;E%X~wIcq1;oC}m7FrK^T|f#0i*CZBAK2$)mxR@*dTqKqLq6#0^J zNrokCMnSj>bS+j-+#}K)=t^GPO4 z8l)Aw1L?MFa{ZMTrMP}slGA53pr6S0#wsZttn1iY% z44kokz@kEshfHN-4OVM*f2_cxz|%x!yP==gkX9?^z-V9dgq<5?rIb!>S%Y1D5B!cE z@OGL@FP=($u&v3*OR{(V$5QUTpuzt&O+fecdqU=kX=ZfM$p~`*Lt^BaU_&spY;!oh zh%{k~duo7BkSzw3lc3-&qXv_7Jd0QkIH(TJNF*nPtTAayqL~+bO9n7ABoLZB?Hr7x z**z-t)-ev|Mx!Z%j%>Os<6Yg0+g&+!>NdGH9LU=7Rmn6!%{5@ieU>k8>N`@H!XIPU zd*!^C#JaQxe32LDIV#jJ*`as|bB+eJf@hn}QsyW15@eh;CYmWBauKx!piz|RnL(n` zUFk}98BLy+CI(%j%haH%t4?-F?MgXnNmG;1MsiXPrAMjeoq@FlT}8DY(3nW3aLirZ z!z+Zf)SBy3Z&;TVja}i6x3r5uc4XTpameZ*VAK zK7vOg%PqD=GJ`HC7+R3jPje>AaRIUh>wu^6qCGD-W5ECNYFO-nVC1Za!I*IUA`60Z z!}C^VnF6=5!I4rQLyVkJigyQXsC-Bm7T^jNuSXtKdzBx;fGCKhGuoM|^8cD7glftX zAP0U8o_ru!OCpEp>GrKJXoThraSr z>>gX7zyu^ptGUaPbmNixLiZVoeg2|N3u_pLKy6>d7T7Zp@#_iNB`(~`1Ob6!WSUn@ zBI1t!o;`1pegsVbq=2z?yNasT6cP|i5THy=crOAgRzf2Nh;h`h_b;u|8YNT0M>&-c z*-Qgh9tD8d5{Hn0AkmMR2p0Uaj4VMQ+hG({_;P$%E*oYMqN?$g_`EKf95sr^6@(0d zozaTCI6L)uDC140lpVOJnkxhVWR#oW_RT>i?e&z!do*}X9}{`g8H@2S?{`E^=HWH9 z1>J^R+`T|8qrt`vIljIkJNugyJZv?(^7Io=%N;*`hOBIV{`xSc7t+y$W{gg75)zPvHMrah(`ep==&LN}1@>~`JDIyfmuL=gnQf0Ou?ZhS zfJ4|+0MZ0R2god5k{6$QRQ5K`%bOp#T^@YrTjl3gN)SAgn8+c( zD_iO>&z!wee*M$0liuKTu?P)(KE>8lmRxCd!lN01{-0_P6khcMq5?j=KW#M zWj?FmiAZF#z}UlSWaKjz^~TjcVdGmDVQ(;$Kl;JbAD zRJX2@-Y4d7LJ zp@FH~l|TH#vrYcpIdZK+0jHVKkz-z@;Kf^oD6Kba^Qp7UrqE89u>-33jx*`F`|i8t{`>Ej+i$;J`u)CUwAbVx9(znKUArj*J>>o2hD^ZXF*CLh z(0Cd?H6zv*P#&-mfRYrr)}`f^^fW*^zP2KF-F{B)yz@?Z<4?aygOn9tD4gS*%p^P< zfHgU9Gye@IK=1k5wM{vHV@v+=m8!__Yq|xhXz`HE{Q9)Mt@le>c%E% z4-KO@<;=?n9NUvzRyu9b&{KBzcgg;7;iae5@LiJkJaA6#J9|dnaL>JjD`6JG>n=2& z9H>vd+DkGUgOSz9hE(|yPYA@iDm>U6Nu)e@0PfWcLaKUD(2?vytH7RaQpwTjxfu7AeI$m*I*9tY3l(Pq$#euXnabD5n zq+aaHbn}AjUVTBfEY8$24hB}K(#y7>xIzJl&hGK5(c834ZTJT znWwB4PhbGkJ}Dt#^sK7WVC66=w{?#{se9q3Zi9hF6 ztm}Jf6cY7YWSJVO0|JM61D#@hO<&h(=fd-{|J+mhnrpI!?V{H;a%{3;b9F!Fns{jz zl*<-m0X4bVlv-CfbC8vmfW$safiGaYrC7k|+G0xRXkhjXRESaTY$Ko|oeT|TMY={K zZwQbwb_8I< zHWi>^XxlV+uT~+ScaFlf&hNRX0zd1tctDir9stfN%6K3MP{hD%V9!dT6vp;Gg~R2F zhWnMN?Wx?7FV6RH4z*<0g5)ON9pkc;HJ=?x4AIAVMf-UOpp1~f_Be}}wV0TH*s_p- z1bSKuG8Tr;FtUT(;m}Fdfdf1g6Vf>6!*VR0wYI$VU2l;W+oiOB<_&WCY=fPOo0{xg zy}rrVsnKc3!N#86>O`*Gydd>fQ`+4X-6|b9baY8}x5skg#GUf~U;VUn8a?^$51y8X z|N7hNZ!!(mu!koynf5vVL^@Q^%Zlj|Ax4AWMrQ{CiWX0nKk>~3*4a$i-Kww`7TdA& zo^3Ip6;FyOUdZ5e#M#zXBbVh)B=_EZr@ZxncgvgJ@J2a(e9d5M+#gmz03;OlrKWM) zShvIF%e(T_vlrxZfA%#we_>m0Y^q%92BG*L} zPOBkQe1GFvCEU|9XFv4>-=87p)|^C%b7rP8(I&QxGiDExsoH4_uX1efo>x|0g_6`$-6icJkfFpOnX+KQBLc;i^1;V^3zSb=jKLSuM|qYb+_QG=|;@ zsa`FQ(9J7<}wsJgCOTzk%+-I9eQk426RC%R2z}jQw`Nf4=Iu$K>bEz z!e;h&cdgP>Th%1%sEi3&+mkPU>w9wP{LAw0H{PdfzAop^oHSUg2S9W}V(Xkcq^wrM zP+>X`oGKu&;rNcD9PIIHFRvcI_}>G?wfV#jXp4vlYC)nJYpF0IS2-ovnnQXo!TQ5H*2N$0b z*}tS80*1F84fGE5c?@L?+-p&DC`a9hA2J_?M^XXeg%ZgJARBGA3o>GZbwf=fgAAF} zqh2HM)cY7SB)f%S@2urekm%W((UEtaW|~0P0p)^Xw0`#RK+jbTJo9Rdp%v8Ab#Jug z@&&!_rJf9S4@8EV)HN{(=kr8m;jkkMGD#!tq!<|kI+jf&h`wURBbk<#t?0d@s|g4a z_6@XZ>R{c$`~;FY=yCxQq{_bRF zM`ZV=l=~a9jk2gF0Z1(JDqwG_LGI8Hm+_dva|Q_8%%BBqt)l~z1SoAmwi$7DKijtf zp2LcR?oR~ldcCMbO(#-l0#ZyyoWUV^MEG=jT8`jKV2?coE!<8Jg&#UIk~qT~K5wK64F=h9-aSHesz;eqe^*R){xe{tQ3!&@R30EUeu$%h zUw7O$!7mPO4M|8DUK7pfb3-7_c?@rXI%Lm++pxY4cc8;h2qh^)<*f9Xp{o4hvmM?w zsh|m!{|j02f^!Vl67D(o1jeQ_eJx|dPUH7yv*3Jh#c-Fl_icULps`Ad*Er5!91=!b z9s=gZ`~s9-%t)nEE0$A+(`7;0pct(7L3&*%hZ9IQ9mAE-jjTn0Tb)Zn$K+A~1( zzzx2zV%15^P~+z~kT@GFdQbI2PTlxWo$Tsw6_KKYs7AdCxyx(|Kz>vH<`b-CH!mM?wvn`*Oxood;dW1<~x z?#L;l(PD|Li*9TKGs9IBETyXi+>{DuVu9GIzNvU8YiFc*Vs$$ zrTN%2bO*(dx!?HmUy8WMQmAB2PGq z`LhYSBI3T46|G?M!tXmofirIU+#tJ<6nva8`_RC`Kz@qpd}9a^IePRcae8=Ag;!su z)7J`ug;ipU2gYy+Ri`ePJ|bOA1*S+C`|`#eVgKV-$81U}``I#Ay0vMzI&_ zO66P-Wj^&0E@Dmt7hZ#}3$I?0XP$k5os9Rs_r20v?#P1=zEg^-B5s)=D=eHyv400u z+FWGEGH**3XJ*GHF<~`QRI^P6+l6gxL_CoA_tB(~gTYXC_Kc%{V`D=$_lNS>voFb| z-GS_6ngy>MC+%vln^?k9+O`9|CRwp58Xprn|WqE3cp70dldI3*UKOp^* zHm#g#psYzpZEzrm#5!@9S8DEUk@vf)L3JzYN}@q81|0WqyecVt7p(J)_tI#nYZ*&_1G!~Cm0wzP@QkY%NjUqqTA5#`ik1{ zmKlFBAy5i}IxF3Dyu{&q#+@8CH6t5?&mBx3G5FS}(rolJ7)|8%JAX>9-Q1Itr|*=R z1|f~sVc8#+a^#LTNbl6`va4s|@a^ZMJhUc5R&Q(0ycQcREpb%hf@TrBNUR*^h7+cr zC6f}8ZKIh?O2gJ-&UaSW>l2Uise6=K2!=t`WTwB{F4;Yc8i@>wf#mf}I_jL3R#V1< zU=Ez38>-jV(eLF}i`|fHr6t2NN2Qf@q+42bJ<4471=N}XKK>(C@j}W3oq?4u={z}9 zjV>@*)T}GPs?^Ej?3~(pEvxxCtCr__j%I4t)i$Er3dj=Jwlp|_m}lt@gSENHs=5@I z^@JBtFF1#S)YhJyp(CyDU5~B*QB(ohJdiKk9wBiARq=PG)V<(8)}vAcLMy3)pg8OfjT%CpfF%trWI7E=9u!b z;>6F~M+8F5PcGZQs)73M|C(1_dupddCF5B{5wLhkq6XC7)k z$7+FJwcis9?oo6^mkY(v{mFo|@W)Rdm;d_T{%`3ncjY(#_5Z9v>ksAn_O7n2`ZLWN zZoIlDlbd~DdfA~Ico*{n?|zRw`plE^$Ui(H?|S#!<(EG7X}PxfoHTZ~eVs5oT~y>jHp>-prjp%o z#)<{~J!X*ROk4)#3Nye&o&Z^M>!g5n0E&oEs&9VlZ{>v-o{^7y^h5H${)hi0fARUx z$^ZK&e@fcjPk-iL%HuzLTpsz(Bl?;b<<~y-Yw|n4^S@{ew;>k7yVOA$=()Wpiv*i! zfw~o%Bpjd=c;k@(wHOOYlPB(RP#_X&BLS-VR;*nw?cFbZMl*Qa}H~ zD-vapZ8RGMb;;c){T`l4`twDOcfq5S~oo zy`legar;1Cc=@8dc=1(v_390|v9T>X{fTTHOk`J+6KDWrwI&&UIJP@A+R2iJGBLOU zR8)sUO=@yk8uq2OriWL9QR~^`nnqe>{-Y5@AX6qu2H`_B+4%R_or=vd6<#G} z@y!*k<4`CGMKRyR3^ZIdlPz)wlu{4Gt706wiXAo+v@QT4)9aZ)IB{Q{R;I}*;6#`` z(EovY76NmiW!)Q~!o4I%&b>p<@Au`$=bw(Pk=2~E2ak9@QIn7>4)~U_ z6IsL@B&_9X5XaaPaBx!^M(|msF}fZDLc7X%N1ejZg1@-*#0o|YbdYMEp(`-8f!a>z zuDppX(JKT ztg2qk~7qA-H#9#(?EPS);*tvbYMalWLgdgZNp3j&OuyP z$HeTZL8WR6se#fJZL~mv=zQ-CRK4{L?tel%H35mBTAQvfZa6GT7V=--t8N!Ir4+K2TrcwD?=P3l@ zg=uggfOY&ahoC(H5f)TTlcDBJNAB8ue$eRMQ}*m!mA5o{cW6uS&(ff3Wnl@Jxun7d zT_c;aAbq>*VU!+R7oI#|0J)57?);;QvX`?HNNPP9h>KgCg(V;hA)a}Pq#|p%g(ev1 zztLji846n=00;@lV)8*97GLiG#VX41n%I(37aELQhl@l0u@#u2fU|dsT|5H>rcvn? zW`CdXSq1MiXP^)V#CmByHFC%p0(C;DqTCCR3FkYIfFQ{jkL&G(Ymztk-$nK6E<5jIk2Kn@|tdfu0MlvfnbOt#CQabPo2q#SnoXS?>u zeHS3!21Se+e^?-eJH>nmh#UYAC*8H~Nigr#HjGiT7D42-E0@)eKmOc#5>HMKa%qn0 zvXnLD>ZaP_-GSW?goBn+*;600c5Y1?7ix0k%n`Y8<$_$k{GxPw9eMWEr>Rqf?)D03 zdE2S%@7_?KX4hMi(zRg;NMS12fRhDZC&9Nx4poW`f;ZH7AqFu3C}o?6Z`!Us>!5zx46r^5}OTk^kqv{jS{m`g>$;WmQJ%D=>STMK&8nrzyL9CH?9gGRx!x z9d#5l%b>9rlf{uUu8hql`f3wqv;@#JdUGEat==^TLhIrIeohEW+G4E9em6kbv0pvV94*NW`$C$mh>w4uJ9r zUa1V<-rk-CsFf0WBs*K%x5oE@(yI#aZ%qJf2BerTcsU=hHdT~D~BmYJD8Yyn?fA13xYA zf6vd!+Gok1TIl@oSVkgXG@|cg$D0aV11fhw&9U{pkinU!@{$Sl0lgz z5>{o6iOrNbJ#Qh-f>n7{tEh1XqptdLIJ}q8C(}&U8Iwd*Us6 zHD1$g23>#|LCF^#hp`6XV-0@CYUro&X*KT8$}=}#)Fk1GTzI}FFF*MNJ9b#(J8o{u z>+il(4j)=I_4eGEjle(zld|@qBa%}fXe8a*Ncw|anLWQHoBKP` zJF_V(hwsyWN6T|hW;d?N{wt4&?7ynsW{7 zi6EHoOXooUeOJxOU`sAsyeV5(^*Z*?>%HLT`W@}*T@DRL>w}7UX1FiT;lw7+n6cg3 zBppqUt)hw~E{Vgq9t_~*xcXWPg<2=41Ecl32zYU40exvBR$^aQ=e*BAqbCMdE` zV_PSsB`RR0oIH1%yztC<3JUj%HDnjCy*_kX(I5w7oK(zX)r?S}HmoR#{T^;92S=eDJcmwH)##bGwSy33 zIX@d=7HJYXWDXZ$z|}Aa7WP=9;XmVn@b_|<7+#Bi!XAk0w`?U27-H|X6S6wS=qktl zTo9~{L8m)3^=bOC5XfY;@gsTtUFT%2c3iTJnLPZthh(@lkVbz>2B-{BrLms%^;n+0 z{;a(5?A`M3{`cRKA3gE|*}igB?mcscYVzOwhwn?)*K3=EEObJ+7sOKSO!%G$oh~7Y zV~=apcN1HL(JU(Qvm7<5W1raOzOXUeor&@W9qST9v?5X>c>ARt|eGFBZ<8 z!!eB4-p_s@L#qC7;cPDuC6#_&Q$Gu_1>CEvN6B{eZ-4uD|r}BkA|AO52({Get z{MaYt)d#M~U;gD6Wpm@p^3Hd>Q$GBWUy`qX^=tCw`K8xgyW$^z^#6wux7 z6b>oPrwi*9pp^?1=W4ijwqSpP9hK^A%x&L%yu$2TP2)NBp991VbDfwmx+0B*84&E{ z7FG4)d8=N3&<4owmM_aVLrb|R=EEy?z4q@RDX>3_dDSNhor}^35A7yMACAgRYz$m{ zzWVPS4YHAd%w`MOld~Nd)FQs+^Mh>Nw1D+1Ef5%A*)&N5x@J zzqbI%(F1sG>p(`jarP#WYz{Kn9w#zPmL==huu?gzaT>bWX-S%tob_l!(USvoH4|mh zgF0i59kXJ|bylZ7+25C1Z`s@0Mqg|}ijW(;-s@;QGB)fZRmu~qKEzqY3{k5YoWm$T zZSe}92jNQ!qqAd@7>l#fn4=1n2irrzNR-xHsbHKDAt<#XqVjpt?Wqw$La7_G)N51+ zythA;7Khhz(jKoabxBz}*fKut+wOUXT$paj=!yp5x_-rMPtISsE?YYT8UEQ{%F$ED z@d%dxnl!kqyrhowor3}~YhYc0scDJL?{*c^U>B`pTfu7+Z*GYC? zk%NQ2EZsMithFjfS9wF)gNf8eBTYUcS<;`cXmYfqYxBx%s0qjo zwf~xM>}Jxx)?h{NU~^vs>5;~0*E9eJOz=Q`OW%V|2x_)i;X|^4xe3A@UCFrMuyb4e zMUTRYgiT;zA9GGgPhX>svsl(=uF0*mt*RDJS+AhagAf>Ij;Q@$ZRWJ7n}AYe6&n*; zoaq@_lF=lQW5-`7jqbX%hPoD-4Bz#}`=xv4h?J*#a_n_?$x9b+NH@(0`)VIKCi@Vp zgF@fkb!eIgL1h#cTm%U4Jt5MnFwUe zNt?(8?@CQ{BB*hr;^iF>>LsBf=hf+mqHGB}Hzumu(0Hb6ouGVX-E6e{gSb@@s(Hbh zS|O&I>zf;W+J!O-=gO+Y=q{L;)x>Dj!J-={3swDu!|AlssM|W7FlJidIMD$~VyCVw zi@6AHY>61wZ$(g0IHtiR${7TFH(e}<4GY}tJank>L6z2ll|_}hfo6@ zaA|b0QQ7q_M`S@6aPR1h#^JgfgsET%9K+!CBqbri6tMt0#&z`@dbXO&4Qa15HBYXS zx)lO;ldLAY`x?Y-tG(XZl$Kssjj=;%aJ@26C0q9iXBKA!^Ib_;EB|-9r_$o4BBLf* z>G}l_P{yn!{8J5@IdNp&kx48s|Km$CC_dFk47^74%zOHb|dJ05(ieCO+bC-uB3zxi+ejeP5`AEn07 zlEz%IUQ7RAn}UQw7CrH9j?r2}RFt&QU|FJgWk?>SDpKH2+%wN32u8}NQo6=EBx%MX zk`=6)`aISC$6Z2!tZRUQ@DZuvBMpdQD}hFVU}*y)nHsBLAiC88&9Mz&!zD0|(DfUQ zXQU8rb=n?ZOz1nNGxb}#KApD4LDM?-K^cPEsHm#!Bu7CJkwftzhp_G*N#5~U<(!m( zgY?y`lKqK&5k&X+tm9w}>}zvtU%v71-^q=Q>+*?Dd_tbO^Q?UJYY)k*7tYHse*6>i zTfg}~$;0|{Q161o2(NkOsehCgUwBSqfEDSFGK+Ja39d>&#ERoqm@`cNyz^;ii`|FV z=2l~NORSr1z49@ki$xg-Hky2|@cS4IFqSVTArR|iMWGAhi2^9x*|C+#1)1j*#6kQa z@@n5|wtbO?2G)&VfO)MOl+gN8S& z*dj35Z!;jyM-B&@EDSlx{NdTXm@z7&pLj`y!h*vI_}!`vw7@kSFTB>>gtz!@4yDy< z^IE`SF{9FS?m>>VeT>G?89d6l!4AC0RJ;rfFwvR?-jTs|uHM*{jT?QnE0;9U$fc`6 z#`^jZSwDPC4y~SG@YK}yuPuZhT> z1|5TOCPOu@6Wv%dN{+WEeuVieh`NDJ7_$xtRKx{+sM6b8BJ&nWiCCRh1KsM%XqIzm zJE^xdP*+2Fph5d#efV89q%$Z=ceug!^c>rimjr0mf0Du6Jgro+qxpk!$;(d+AxM}2?is+_#*t+JbH&~-zf z$M}YvI40^CZpxL-8**)TOB1(@P^p$0(AV92R*biG%&t;OziM5NEC=kM$s%i46N`0y zzAN1t@wBKWG#b_s$R>MwdsDgg<1fkaW4FmweUr(KCK=@>)mKa6iwAmMp!PY?8`+Yg ze^q4rybNzVDY+(ph3=o$;X7p9I4mcd4@zFgvyI4z(pXYsKHihAUQdf%M|IBGwlsz# zX^b@8)aN_Wgm!l2Ia!MO(l7M=hufx%tox(|CKNz#pqMHXR>*M=rYf!LpV!DVfs)np{qpgO5*LQ-4SZ+_p~eAHb0w_6(L(t#Cyg;PEA7%$)r&9*xrtrDtVluISQf*c} zw^$8h4l{2+7`3j^93v^Ip%bHa5CzIe9m$d=0F6$yzrw0I7-= zSgo+vs`Yg!l+pes4h5St*D(3<#HUhNFS06eVsPPbt^`m%FwbRk_=Q9PuH&;KPIn(U zHExy2l|j=ZXM$bnEckla8r!U7Csq@m)FsI=K+$5PY35mP_NhUq1bH)w< zOdYS$wH@m|2cKTn)!)~1*I16Ey`=uDHdep9qIWlL0pZ>VqcKkQw zbD#SY`ODA!p}hC~ACh1FxnplkC5Uc)ka-OM&22pULci z%C8%vP15`p&Ok9l$ATU4m`pvOb4}FoL1h+Dv+Mu?b<8&O@cgry>D(pPqIIbqoyoA> zAx*L@Pfa~_qKRyOApOhF$>jWVP_2^sK$Ek+eoukpAE__e)8~O!d7sb}@_lDchC(I! zjF?e4#iTGAWGes_WCKG59L}9OaD~rE!Em69fFXDN#|-6T~B2O! z3Obf|R!9pl2n>Rc_1dPH6G|1fjWG(oo5*yhFQtCRBTdHP3~GrC8v23;AdemEhU>E( z?Cp^uiz{0o3Bi8dmi^7k(pTFl8(VTfg>`)EdQCJLEBXdQ$XB>`px06YCY5av)+ehD z^@6QHbt1K)LPDVcADs-0PFI3s^LBoKAi!W`u6mva=u~DfreZdS%!I+@z_!GqNMfq% z_=4R>2LzuRXeI*8U_q$rR@jkOnrSm?GG|kY2z#kFYns#yt<9f1{3Ub&N{7A_0m@{Q z%`B1SMj-nWcU zr((f!sLoHY%q*^vvw>B<^Pl&j6_laEi6{Pi9b!h|RB;$dfJTMC7uN2JO7A?#LgMAh z;??>FgB@Da6+FRTAD&&haBnk*zs=_B$YIzT&#}GlbPk>27k(cwoVLA=5bdc!u%hW4 zu2F{f==k#<7$Xk?&Yt?XlP5%ut;pfqm*vho*W@ktpCS@rthV>^&Fk{S^XhMJOl0^E zPq2H;_>a$MNSjRPCP+|fJ!*W-vJr==0Zp;aO;fjMOHG&A6zoyh4a^>~s}tD}dI=#d z4sh3PW=Kp!C58`G!}RvIzD0iKXWuS&|IS%bnLqmUccecYu<)8;NPev=hmJ4H;nTkD-_Hr;FZ=_sI9f~t{hPv?crc|)P3PLzBwk^h6uCGCnlfcF_GBx(JobL(P zGW?v7Aw18q?GXwJIX!lm%Z-ZpxtmuW=8*%F)4K0(hwpeN!`^#lOjB`y5IF=disz8Q z%_p|3iN9V;`2^ z{Pw^aXkO<@5612R|T(4Z*(YCpQBs6+Dw?GuWc0 z!%b~A&ghG0zHY_BnF&zO5U)&}xz5)lughF<8=o`ub@c{8fS8ufa97T}f*j6eF}IhM zO`6$xBO1dYQ$af@{5cEkbq?=}0%KWVGz>n)uPu6wy&*(+%JY>%34IDi>xczL#0n{$ zGZ?1g)U(3{IzH}~*TSpj3578(#{WMFNc5WDzqJFBEN04!a~$3Q$z?vc&MKy7vNnha z%k0#uIVIO#0Q%&&a8}_Wuh>xlib); z!hI!99hvjFCiA%z{-aTHW|N8Z`}@)ukHI9sC~bzPi%Msf)8~_cu-jqvG1I^VF%=Bs zRE>Wk23^2&$8dN(GFV699N7Vi8Jp}p&y6v#8N{m6gYm6Q2BO0BKcYB1+sKrp$)bh! zx_(YebN#ipi~zCVgDp9rjVzhhHX0L7Qh+18t3gb=tM4@-3sn2?akZDnWir%2cz>+V z?y#=!CRw{c=lk*t&&%JoI?`;`C44&V}CXo7YI0{of2!E6Ff z>6Qfu^`p`T{jeq$5Sb#rch~4c5yU3?uqK*3$;Fp+FK+1b8B#&3M%rR^MqrppV6di@ zjzU6)naC*h1C)`KMX9Kf@sOru(a`_ZEij9smcgoGO|H`w{YjgYyQ%(r86#+Dan`}0 zE*j96eYNL(eciS`uPxmN+xq$g4rtp)#8!DzXEj6efwsRs*x7&wM{d9Sb#iFsq`a_s zUK-uH=35=<>cXJ|kZIDhudl*4b#HXTjr5wwxwY8(qp7U)>J9-m09{gAfR;EcCWF`? zk`+`kG5dr{&q&v6WbNe9{*Vtm3PlR9f)mb!>eSc_4_nYd3j!79q~PBhx|h)1ATNe9 zfl#*~nCD2Gw>GOCm)Xb>PITNI&H>J{(U`2E2?L^|@k#^jw{4%fPv>rObF z7w^N_kIWKCBwa;dmZ@ZFD>!ZVg3#=onJKNIAXl69)dpgdm~S5r%fHQ&O+s zRT+{Bz(`_WKi-G#tqfK4TDAAs)x*GYY3C{_8?-aIp5s)5+AiiOH87j#Vvd_?d+Qij z&gAHNN6wto1myMSugw5L? zC_E0s`J0Bho-EK4m!xyIq}>BsJ?nXFRHH^XV_gOO_oLtZfo$H~m6esA>}>AKD=%D= zc6~|x^8x24md>`N9gk$CnadmRSeFN0hqq~w!uIheo|VmwD{@V3|K;bN=@tS}2_oce&dp7%7j=N&iTbM(1qww|29O^mps1PKTN0Wy;{X^+G6CD8zg zF6!oAn2QEJQXlBg-RC0#F->KkA#oTyXK`VBaZU>>(AhSdRc8;gv3aHGQOpb5rHzVn zqOVvG+VmLH2A&JTVN37$1&VA|=nJz9fN(Q*gtnN|j+3DdHWGe6F#bi>nJp!B^9rIf zUOoSUeDTXu`I)ypARqbIN93;``l5X4ul`EL8ee_zgFi2~oxVf<=HYM3Ll1pTe&Hh@ zmQQ^0lk&BPzAUZgF}ZT(n)-*f@9|kx6u0|Jtq>^AQWbKj*viWVi@upZr<4q8gkOe& z3fIX67Mc6iE1PRW=GG~RB?v%QV)PkHw zt<~fEurnC+kI0^t+o+UxV8U$o;<$x5XkC*eqOYyhj7%VBEy;eKVuOJG6kjJ!oY4O^ z`outeb}IyHq4^z>iAst5pZ|*f83PO}5E78Z79b|{1II|prJV*80f)!9lHkxaaHoJ5-CHd-+ z{HLVl15_nSmNgLQs(FA?b}BBeq5rNM3)cp`Xyi_rbbcl-2IGrs#{B?p(9u93A5YnZ z;eo9=Tq3eYFK4jy5W-Mq&JRCD;-UdgqtoVGMSH2I0dGc{U!jt0%2h>xoUblxqB0<@ zA=U$IQ3)Y$xzCIwtdb{DJRdLe0$DLBrJ34Zz&{$+&l2@eObxS}l#X&NIBgpP)5we& zXb>^SQx=3`p~%}#mt_P{;BqO;X-C@Vstji`*glYKG}F!6s`m)?PsRn1lju4F1=GK;c`+JXQVpzx>Z@5Rg7PC&-k1-Q6b856+8A+_g!H;_DL;u_!JB#pq59NM7P`PtkOhKMAo0h7(`^? ziWdDq4Q-2`7yH~*#K3Wtfr%N`7S-M}C|AQksl5R9x6Ep?)LWN3&fY1Pu3eWShmJ{Y zX;sshI@jyOZFkAWPA(hI6f#+=$H!ip9!W>9Q}a|!ln9X`#8I>xPaC;8#&%+AQb-W)t04Gkq_>2_VQ8lyu2-6cHAJXALq#469>)12Yq> zyG4PdqnOVTlm^?1*k!G8{)00$r8~pSzA58nS z>Ks^sOx^UH>8msnl2G_GDBWVPQB(=ZBJ3={(1PGv8Q8R51HpbyloB$i3K%V5`&uLHpm?VN;D}M zq=7Pa#{D<5xe&EmHT^C$P|LD_(@!ZZ$Br=ypwuft$HC^@7%-E)6A+Su_ZO@0dhziW zss9v_MX=-W??UQp9X;o%bb6^QuQX+K&2}Z8_^R5Qb9de@>7l#i(yROO?*IIA5*?JX zcWF!3+ACziG>yxG$q(4_%E+{daCYL{^rKif2ZLW$_h8%o1%)A}^cf~%*RFiE{oI2< zl9yyA4lK_4<_vpzF($MK2}x?bd|}2(FIShKO8sVHAaKzv}HqJ*g@SWz|mVbr%%Li)&D_Y(<-342D7 zDUn;^msa-_A zBZ&>bfo8Cb?cfv2f_;-&GD0dmA0lOS0hRV_stG}Z!=@N2V`V#ytSb^3T&4zrAK<-_ zDI*yKe=-6cec#FMo^;ptrKyQXnSio1Cx$Pdmh8kqsE}|{Y)lPMCPM@VO(q31`m2&W z>(s+=Vu->AK?|m-1+kLIU}0e3I58NQ!ztBlAlVBku0(4TzqWNu=^fpG7*Mjh&Au4- zcSJ~2O%uTJ#z;o2qzLi(NZt_WkH-hnKNw4Ad4|DDk zThW#z`3_a=IpnI(`{v$;2D6czzUOv%@V)P{Iit9~fK1H{p27-e!o>TIJMNGxm#@nH z{!nK6UZ|YG&@$-&P9DRwnjoOXN)DQ9KwHyAos0&Y zvuR?;7`h5E{Du;YT-u^Wss@EE6GL~P~bF`s9+t%*`4Nx7k z@4*U(aP@eMH3?)FUbD;DG?L}|A?dV^$wK0>S@}O{>(;fIjM#qeriU029AE+8wnth2*k?7kj1FXfP!|4xrvgM!(4-o za%@3y8aF(!gbgt#iXm_&i@K%wxOmfL>g#hD=-N+o{};3? z)apUPjq{4`5$plrP-?Ub@coyWRT+JdG7N%~5*5%9aO#6G3mA6^fyErpo_m!sN=#)M zHiXQ2c#itnSr7|^Q^^f49J0H5lFoHMd{4hN0U-k!D_dR&!XQ6HWc7?sD57b_m0Ijt z6QxH$W$bf&4%5Irz9s=lE797b3gSaL!ISJd5}^YS0*=rD3Eho3i&S94GN>r*vnfR{ zCKC4hcpg#)Mn)gD#`%tINI#0pxlpb{nF2knB^t4J?gCsca$PZ-Lz)kZ+Im`mS#wo$ ze=nyS4P}!6!73PV<<;1U&2hx@BqBiJ#0+~-H?L?l-9Lt)GU%q*?-oALZMb?HtPQtd zK`LfAlE{YW1Dz+mEFnJXV*tU5yqGDLfaL09N!dyCS88)l4SlWJ*w$3fM42-^nDyFH zoH`=S04hlzB?c zFW5WKqi2Mi=DvJ*J`E-yn1h;?C~S^76A_nI44e|eD1=0!pqBzV%DD%lFy<+YAXA{v zt5$MAn;j_qJV1)!{{g|gv9ES&FOk;Zs9f0>=^nErM9qjifBCxn=<%y^@uh9qys#c3vW3>lk7SYoGkF_^{ zwk*5K#MVB;9p9Lll{J@2DwRqSZD!~Ox9FAx7%<(24hi^$Fl`8jiFWs2;|LRNBJ2P| z0}ZsJ!I)VHB%uLGtqBcPDyfF7%K1%qKEw9d(W`XUehmfT165(5@s~;Y@%VFB80!{9#!i(G9Sa5$Vzf< zI2LJAmy3{YL^FU)@!-Xa8V|Ia?TTa}1{;iXYA5@o0>q~c!PRk` z5!B((c9mn*i2HMgzyJiN-W)h3k6I@5gm%?FV$`H;2ckH908rWIMtX{_?2?b5Pp&~5 zMk)G-CA zEr7PC_oSU`aszTKNJq7~nP9Q3*Ey3|8+kwicT0sQ5WVpp2yFG%`cz$`(@lz5$f0X= zQS&^^*fTO0I-Vyb*4?y`Et6z)-C!m*v81@FYj(*I+aXqk%6@&a((|ch zf2_e`UdrlhsmEm!kf$iJ_U2lM9m?H{+cI9&a;3Z`lk3mO`u;tA?Ws&iXaq+HZsZUJ zSj&yqUzHDiSrw{LZFUT`*eOzwbcuHP=7sSRlvaxl2qpi85B_A_~0%RI+XPGABjZEX2Y^%tw;wS)00Hvgr z?CC`qRSTJF5p@c8Q(5S`TXUL*$qOJ@MjSR{7HbYzaawazFB}I~xUy-+O+7eHyROa6 zH$rlkU6wt44M^r!h#Ow6spVz?DEd?b{~gYBy@RK4pWF{22W7*qTTbcg8DV@`W@bs- z#$EnES}pdOP}h3gU;64R61327HU;HnwOSUr`nY`M=IavI7t%gFlfBu2tT3gTHiX}i zInMPdHfjbo+ocUTUPhs6B4UK@m2gUT*le>w*C%@Li5+~n_3kh6-%h(IkObX3r2!DF5yTHnOZ;w2_ezzzh212eZ59{AAt?Qgio|k0eKwzN3}#D zWZkI(&k#C#@K0$k^lvRPs5Y3n3TZ`!80@_$1`LWMG^GTLG&J6UOq+9bsV^;RjRRtG zyQURbUzSJg5>a;(#smbTpWFjKIVt`-gW>}hZZkAL3jSUp{kLO|Gap;Gj!_?t^;$ZI z0UQu_-frB#!#=08d)MpcPVXotYHtqI9pb3p=PDW@bW8nWv+Yb zz3Yc^uJLfKg~QWtepV)rAIs5=iG2FzC#71ogz&DmOH(j|5}s08@6m(Qd;I;4B}O)WV7(`R3j`Q*C1_XoaHPTq1)KJkH%$qRq= zDUFq8#=AYa1E_%A7OO}kNlgQSOXZ`@ZF>e=T(gNk-*}!@1|LJqnd@+3JdbWF_lDxrs_jQ(Jv|S<7 ztd{+loa}7orcOddzDGq%e=hO<*+hCt+RE}9tk*g{*Mq&FOIf2A(oU++t#S6}_wLGj z-uqs8?%B8M{r^$zxcWv%&rmA4uw>H3n=SN;2I;zL?lP(>?#mwZ8Rx6`91D zL3!F&+RL9+r+ZqK>;!} zQ+n`=qr_Beh4uj$7Ok*kJepfoA58HCJPlNltTmt}fUY_q70wxvrpG9!2?%2X)Emk% zB{=DD>dI8v?9iqQ(I8%gK454&0=#L;hgSybe|SgJ9H=l+qjr?-ocj#_!vYSajOZPiD&~x3u zY5Z&}Wi!_OGEkjpeTwd}O{^w*pXU2>S<(0k-TPV|f5)+0)y@3uOJf=DZs{AMPy@%} zwqCV~)8Q2(dg3|BlLD?bx9$OoPjt$H!Csh?WG3}zYE88!$ZIKsT`-biM(lLRCtMSzFp><&OjQGB zYUoI1`Aq-dIXcv9cg6meBbRti4#p+Bww7S6O)gV|OPy~B-!m1CivAY`#`(>Ju%Jn~ z)ZC>4Jzf^T18cCpcKnF!=Ldq=b@bzCz>qM3Nk!0W)^7A#tXs+~qMVP^BB;48DX)oVq|K;C zlVE}5W?<6;7YgtIeeI+?mN+#AxO|_r*jSSTDCyk)&6#Pd7f^mgqd7ma@A6Q>?}Uw@pCIB+4Wh6L~XpG3uO2A0$n2ov`Os zUTg!Nn7faUNnM74LZQJzhXIPsg8RGPhXQ};piA(ziP>MksR^`ASJ1DhE+4@e%VZ|DE*oWk76+C}E# zA5Fr-7sNMHD&4smoFrt?dHgm-sH>L!+Ti>|Q(-H5Sa4?6f%f?WK8pLHWK2YANo07N zpp>R|!sEXv}B=T1@xkgMa-YdFhic%P+p`r{&8Z_<~%l*1Fdg zvaF-$K2d*9Vl{W-G73xNH*1X<5RCwoc8rOJsQ`(?_7AkNxNm%Z<0ZgPcsjvS;&=?lI@q9L$okP{w^MXMEUdQn#`OSu^D|CHISp zlnYAQ+vGgA=99y6c~64*$zWPSgGPP7q8OVbw8M9Bzpy77{CMk-s@x#^bxw7zSXfbs z=cJW1G4%D<8f2E&&U0a|@7APVaR_CNLeV?>V$Z%6KQ*7RF{bow?S_1T=g6r^lXb#8 zRB}VkSU29I2)stoIdDvnG0k)M6V8Y5G+l4Scuzj}h0n{^zxpM4&%56xKl3v`BY*G* ze<1(YAO4{{`|La97k>V~m*4+C|43eW^;P-xU;hpHq4&N^zWv+YDPRBEmnkiKwyJH0 z*+H;UMr^qY5Dc82wh4M~(xE?dQ)^HH%k5>| zRzH8fHzH?Yy~!!<33)$y;5d9L$FVf@#j^sPf;COYQ!&TO!qmV3)e@^cTEFEjrFO0H z#)qGUW90>GYYBjuViX`5aFuS86KgP$pL`Ywn>jsS$R4~w4n{nl^*t@#^jhCLzbm7M zuG6Ch#n0)?z0?S=LRc4@i!`51R)xB zI&0JT)H=gEC^l_w$;Hjj%VG;T=Y3g2GEh&DzB`&s!^u~gyK+3!^)fot|K2w^p)TOf zy5jxcY9YI>R|btk!aySNjQ$d~L7DbHiVl+w^{?nh>1 zIJjn4kn07uG%WRZ?(4cf(cF6>CX8v%p*dum6EvQSC17P#H!uj=SPPJ&gJZpUnY?`S zHNCe_$o+OEv&Y^cN6&tn><-3quEk=r*7x4mA&Q5ULI`)~iF^CW4t!dz6dmq#l)6X>rYG-}DUXXNqxfdXvzf)!fh)Mif0b=<6oZSsxMsZ>!KFkZk_^iIzn}JBYSLvza1Kz#=b|D-_6$sBf? zHO|crJbxrcbc6Tlzd6O@kTdTvMuYJ>4<~kJfWq#2-&nLRVnz{z!uW?V1!x&`3N3~v z`ErkX>DvaOA=bVZO)>JF`B0<;!#o1qp93XQUJ_ayk_U)8xc5y!M>qtF9c=1lDe*9G zowP3}m@|DSr0L?4OHuQf7n_B4s#*Jo)fTU{qJFMI(5 z#WS*T(aHq5avoG`Zs~}9OtN^j4U%U5Wf^%mjMpI6=Efy! z7LgkkOpGPBe8xiUBlJ+Ep`ae_}|>S!W2#*@sN7p>j1=z9>kwR+F0bxUXwl4e|!j1tfGo;7lpviA64-diz@JmL1- zFH}w-kLFjyCYnLhiJnKp#bvmocghJTW>V71YE?Uj!~_s>3go=RYIA``iCP{;MB)xBS8{{DS<4-~B!L zQow?89S4rltkS2Ug<`idSDAffG`n|Wya z#$a1_dq?mI8rE%|@>xjAQ!ck+Gdm>GH}7BF!AXY&NRg#sL+doR*b&5|v<~@iOrO!;)`G5D0rHiwzBq zqIU?|YQ;__ZggE)phi*1!Ue%0bJ#+G&gqKh+qw%a;Z^77a(|S|;aHD#e#D1ry;z&F z7L;hJk&(nP!P#tOQ5)Q5l+PgUC7T6sdAXqmGJ|}OpVGSQWy|{43Jh0-tZ~oAy3x-K z`M@Epn~(F-55{?&h(Tz3XdLyeg$iM~=TrCv?4cXAlT*D1b8@I7HO{NE6i|G4O&xq^>iuwdLGBu-X_(p+p;`8ljZWR9?Y5Ex`kXjD&>B&mDl#>a^uCXNdB&W z%;Um_jD!fVmQk7OJwNA^VKyn{>8Br&_x;pAljpzuvh45A<>Md!l$@U}@uQOAV&QOm?g29G@vWvzXGg!1Zc^-!vMS z0LepFjLG%VjNS5$-lHv{2O+|B_d@T;iC&*mJs%CC6C}6`o00=Fhbe=;=cv%n*zDNB zMG}G_0+-%vPanzcmtK_{U%4qVeatqfgCi;SpOCZhHLBd;9?u?rO!khoSk&igvE13( z(EBfX-LXg4t?dXXijXAMq3K7|$hDVxB{c9CT3D}lwJwpRNe1dYDUSDLer=y(|dCN)f*CT-;ne51tAI8M+>N0;rRhd4=QN8jf_VJY-lXExAi1(U1~l*O!~?L zPFpiquj5p-PEa9iL&23{Tmlrq7s(Mc_%$iWk)ZFic-*e_{I=ZaF##bN*A2WRxIY8} z_-LYgmq9fUV0O!M=_Fp8B-zQ-+8^7{@h%dnxdT^YH=xgm#S6w(T_fdWX5BZyuUM(L zJh1rtQmi78$6Lqj>wQKMT6qW5iSY0m5Kqt(hP;bNOrDdw?hw9|cZBpfkoh%5%Op|h zP_t|RVQ?{nr06A1w(e!=+m7rRoqL!_>Ph?Gf?AT&wd1nblfIh4^)q;D<{~L=a!*cj z!n}7qp1#8qir)hUk)6lF1Qm0#YB2Sm7SAgnuelw+6$TDJ%{_|ql=5CKlrh@6&@G<* z(67e?O+#mw?_br9f3K)QWJ+(~O&sX6Ft&n@fafJ<61_^0H%W?oO0!g};DwMD>}7%Q zR>Ytkr;DRKs5h=vz6e%4c%5pQ2Qa#$_{V6(reFph zC8_<$I6Xgcde|yqTjmfgxvWG8?4J0Fx6 zKK%veG1%KT=eqww7-yW>JxlKGt#!nSwv&a#4X~$Ez3c~?FO8X?SJk<}=NSC)yhDX= zLNONoAQ&kE)xAb)E?3M} zLWiCY4DlQ6QRat&OlED<1;l4Gu5|zX^d~O& zlk%xge^&nZPybS0{Mt)YzxuhK`#JfY-}!a<_@Dim#zj4k)yC8fIh9Nh{PbKp3^Gim zSH^SMa>A=zy{<9%o526q>Z`{5)7U+`GKmClNMX+2AHzYh=Hz^*aZ`I?OHuHxE|;5 zfB^7IH-r`Nlr=h2QF32ky8ie=%Zj}pSp9c^Z^`CM>08_ zYNA*(h(cnx(lt=bCVDQ1ymw2ebZJui*xUb+yaWRA*ZzjSE4XavsE_tXq~VN`Hf`(v z519JEsa2EK>1Zyga)&$TlTSP@SFb!o6|Cbc2lB!TFUrl=ugbmC6B4#J+XclC*d5Rf z4+fB!&Xr-zfDA=6bY#lhxIQJNO-F<~5k^-Aj-=r^W1I5GpeX3Dk^m5>tO18$h(loV zvDqzQ<0DtDA5l5v<*9*%(>yN-}tP z8Vi8Ld9LS^xE`l^OejRw-dLvKp;3HCC5xN9ElNS4E!?95N@4ICskit$;}kE) zbI-}l#_-H}O7_JH10Tmd7_2PTFIhs@cU3^3EpCx&b;9flVBFsx{ z?YE3OF1L&X*r7_9&j?Z|$`TPhnk|w2hm%_!x@GMx54Q6eg)U&m^dZ4i zyLcZ$3aG))ci_sNULXA)I!vPDOL`I(vVH=QCiv;+{8_YOPh36FI@Z$3%Jbf}J)Fv7 zb=yU@(1di7U8BdswL$4J=YwP+bo@TVDo&@wKil23&8#t9licG~=sqi>$(l{zxUSfh zPv`^lA;Q`RUyOI19qz)r(n;0JBxR>ylA+1v)-Q$bALZB+MtuO6kXhF672C+J_f89< zPv85bJpZAuvthScpHhN-qDA~Cs z90T$UltGTy?9lcw>HggIYWyDL%t5?vJ#oau0c&rr$v9ND2wyCx8pbAsf!C1V#u?X< zT#{nx6QF7<`DRC$RjmcUAN|H3$VlTHjAIuk@cbE5JSL+<{2pOyBlvl_bTmlVW^R{} z|JKwH@7U@-G1jA)!@kuNE-^vYW5HB7hv$hFggHD{#=ak*=+J$Cz1dP&q|n#qm=qNT zn~P;dSM9o4GUkB9k7;J9g<(;T?HDSHwzx`k3UH|3x$oqfdee$u7eN2AsSASK0@P~g?e*WkGrTp=qd_aEd zSAIp__1^c&```b5`P`@9B42&}3mPNFY*Hl^EQ2BT`6kuq#N~67*=cmsP6`#ZC}0$S#*d)}{Xn1BY_&WjU73l~Y0@Ejx#RKXauJP7d?|*Cb*@4nf0C1^{tD zj=yCP^-LN*&@5D1iyACmQzwARB?dQ0gknG}P^Bj~dX9p3rYJ&*Nfw(1 zK8@bh3VDi`-W6G#Np*H1^Vu=sH#pAPulG)qq`4;SNT_zY7&aHRY!_SI3jq%Tj^3af zJ1suK(M-zOn95KrvUp5|!9p|uR3kkmEfh-UK+*|xBwg@kpvjZlultv{LRP1&6AgAi z$ceum$yGkp7arK?oV^4T4thV)C0}EduAB2(3oWSjyhpoIpn!vg0K$8fC40J zIP2bmjhv>oLh@pHDy#LG+&{lXmAdC&ctvKDo#<`S`?}WSTFG_`$J-gXNmZr6q2A*& z(Xbmd@(s=d7gekplSj_Cdby##cBab<#m8;EPx^N_*Vk-KEv+iZg^F-iuZ=5#$}`sr z7JR0rp37uwv~(X6TQc| ztyyU3N9!u@^!Fr&_P3z^7uB~WlL-f_JG?h>mp0Ku*K(pavAQ^u^INY; zJh>;OCKMxg>_*dp&kAAvC6#tCu>-sqtN&Xml6HOyYxZhb;E{APi)dtf^iYYdgri(Zm1!=z>?1`yglXi3`HHS2Q zPft-aD23G^fsgM6DWqa$IH9pvA#pHa zZ_}EI9i+*Wq#7>{T0j0IUmG|LOp@(g%!uwd9<6C)ULFae<$Cyu5AN@0DCFQ$r@?zf z{e&hYthB?GyY-#Am6D{1jX%eqwZ_vB=P;%F68*XmDkjc3^Lrk>ScrarIiXeJg;~0k zxk=TgI3*6B4Fj@$Yn@eI11qb#eKWYuU*noDNb*c}*b5e}_{^X}fOrQ>m}7#(ISCy{ zzX>)eCZ7pW1CtBDf5C&mM6t92C}{kdWfM!?PIq#5b;@Bty;|6NPK+Z8PE*sGfJqjD z!*wc(KCnZbnUpmq85?x);nG|*CLp3e-_=_dC*&`2&(2s#P$JrSK#80SJ|RSMz}aaC ztF8&J3{XqdLaDBn^umErZPY{_DwNyif*s+8@Wh&l_yr6Hb$_0W_cZ40S&p+=TVnwp zWv!dVVfAaANd~NhbIZn{r&U8plKCz)CeunIKd5!;k?#sN7wHE?H6+>hvie(ughP5^uzMnjhE!RzWrO|AH4G? zH6K`0<%&&X6bw#6xBSOl;hVghN*a7~+Z7|*WS!aoTB6ib_NIDwN=y_3U@ zXn4@03l!kBnRUK$PR)YzCOlcEOk3lzHS>j)jI#{W3?+-|>{PPjhh?>I#r2CuKL5oR z>w8-&QfhD;aRPGr3&;2H!`I}IN3MOtdLfD3$@Wz=+*xpa@?chX-II|X><5>gTVYwE z*80>e$&ChgJWUCQcPO?R&|Z4=75URY{;+)g>v!a(7fU2b-x@<0Pq zshi4(9U>-Q-jg(*TXz6TV#var)&yU-<~K{4Ld1pmIi2ElM`9b7$@2z4r%Q(kg1 zo5{i6M0T4qS!zKf)PR}GqmMo#b1lTa@Wn6cy$Et}^*Py$o|1!SzE}1he?~T1e5{IA z_j#-_O*;3+(rWPmVJz~A3KLgh*N(A0G9V$Tu3Iaj05gj|nGS#q?$~0dQ7)egas`6S zriZd8GimPYGjV^zN!AAP+T%u#{g9K&u&T94+0p2;Y>gDlWT4c0q31V)cZ`1S>S9OP zUFITsaAOd&bx*iBy(jBiuZlqK8Mxw5IS(Smf|5{#obrlz=2vt?2h1%Q{e{e$9Z7*F z8K?=R6Ftcf*8gwWacH`=iDIDc3J~eltCA0oCyc@I{iX~U%^cf#9VRm6!U^bi#0Vm!SpO$q$Ht!Qymt!VoR{efDah$K!{^x&AV#;xsb1)E8!183&3 z!3Z3lRCuC43{gh@>7O4@)+H4SnV);tj1X^(NMD4d$wq6_jo_PEaDGF`Jx03Z^-#Lf zp0~D(L4LtH;i)!pbKGn#CGGC)>l6IU3y;u2yb^N2)`?A(L&&=8VD~yruTvu^bn1%I z5pr$X)TSaM`Aa0Ih~E=u>RpQSov=}KXh-hcMsGSr_hI3C(VWgm{4u?ce_t$8QY|iz z*4w6{l$f+HCcaf0I}=7Ul_*<~kI0JvZnfRB<_{9~&1y?g6{sf$dIedMLxQzS7E{%W za3dr7BG%ST<9qRz?&g4KHLW8Jf+=GnRnLnarV^c4i*;;#QENUlUVw6%0?E>e!-}XB zRp~jb*!9JGkvjv0tc#tiiow)$si#%(`GnX`19&eQnmbcOvUOftZc*zs9hvwDA@nXD z5xwv?2&2AcVty^;$kF^aK?fZo-kSOySv`46xp>0U+bxTeg2jv%2>1ha!m4#5dD`zx z2x2E~uck*sL~-Ln@A$H@oExv0Bxd-SWVSW5?WG0*XX3&AI@;Fr2otp+{E+8#h9+GOERQeFPT!uFUN7$6!RZGTcv4>z0 zxbAx`A&3qu3&u?~m{!$K9|50pcqD%}t}Pf2Rj#@RwCyIfhN~Z_-z7-Zr3tN{LWq}t zU;Ny63O z9R?7ibP^AIwVmOVX=lf7%xiA1;8Jh{PqO8#axIyocLOSZ5-3ZKaIxfe(eTYwLu`{v zXX?IW{qbc32v$hrYTM+=J_xpOTBt~btr6OD>l`yulq!>*{BG8nVd1kQ>1Z6c?)vDbgcCI|xR#Zp@R zQ_QZ(Y%-N~l#ZmeTP*3=Ine@SGMmf#>_i_ty?&z!hR3qq*|E|UdSYbv=tTsjUXjSu zkn9C1L6a>QGD1P3uuf*X!_Sg*V6WNN;NkA)85B6-lBiR{5cwzV|nK3H%t8kQBJ;PBVT>~ zj(qurSLE*fQ~BTrKPfj}T9NmGq9Non(*dH-N5h21&do^X;{M|iI3_Bkoavf6(bp~X zZ<7gxL01zskuR?3dmf6+ugSGHJuQzt{*auUye=2de^wLx`|{+Qo|EzZReAoUmt@l% z>46@}x&Hmgv)?V_r`{$(H|fnw>r?F^;| z7#dWf&Eae2X+cK zCucI(hkSp2pnG`30tKBQ2$szE_e7T!JB%QB0?dqOaI9+vP(Dc3ZZ7WY^9GXXhVT=R zFmWCmAAlUCax;FFV7Ovq|F4-I*1JoJ6pbURyWY7}I8g+76(+2*!;q zSa7w9lt?D^k^$rhun?|^)V)s1Rs&Cn-~{lL90uQOE(f*YxVWDd1c!pQZS44f8I|Is z>wt9;WH5QmV!s^%K49p`2VzM`gzo_~Aa&iMzf<4R|0ZAkAm`x(fdY4htCEt z{A|9ENZ@IDYc3LuJ6&y{ z!jrV_zP3J9Hfnf(ydh0Ja_>+MA=Z{Gps)_<-e+!@7QL_(zn>9_=$dx@d>hvr*mCU)Qxgmg_P&Xc=hGGIa_ry+Ru zSb&N{^y&n=F&+S5HT0=Y2C+=QN9o~Z65NzgHn~sRwopWzvw>7Kme7?GjnkvKKHn2r zt?t_-gp&bNXQM);^8%kYG(T7)wCZ z|Mq{8@BRMolYjo>KPDges}Iow%5K!?RftZOj5+Z%CLy7Q!4C`f9hACr&&$h(N0>O}CWHYE51MM>H| z80ZZf#gT9J>49<_Hl-EYZZt+?7D}3ycC1v+N*<}g^9IhIrbn)G&qZRGHEDBq`=sGj zO%<4SwUM1V)3H4K%s-TS z8niB6|D3#Z|BjrjUz0!mtB*>l#qJOO(|;n@uN_GzP8RIAyouz;X2*`?cMM0$w4z(% z$mV9r!J(1KUiQD2`F?CeH%y%w8!G^IUU0}ZBkv;zEKk>KTrJJhLO&jpKlBp8LEWu%ZB<$b zG$R>lB2wzTTxwuBhyTdE6PfMp$>C#<$y@^tx`L%%e{{m8`=)BNS(-d87BbFps)a7i zBv)rz&|^wuUNC@6H6+)e|Azo%q(d|rP{qI~48%tmgMr}6djpI&OxlW(O*g#L4wwhI zW$ct&(Civc+@o7|_Q=7hOf8F@KHzkl){|e`%af{};gfy8O{RG%K%|C7OucUF#`pd1 zOfD54gRe|d@*kYH*MEjdo*G;#sowluU)|_FI`lP|>1l`q?g?Jw&?G`W#GqwCE{mLW z0d@Ewck#zM?>(-o{f1*1PJ9enl66U&U88*9Ivl&-NnLSC9E#u*o-B=l`p@emF(nxS zx=K!#60E$NteE;(ltgB?&r2}6N|H2ZBDz|ayoY|K*LDR?G@U*jiCg=>SH7o zkC=!=#^@|2@#Lc8+;Hka_>0Be;4aYS_2C6~aA;s~ShbkPO7fqoy(qHO%%1bh=MTTgb|mxkEE`Z`*<#U#-3IXtAf)AMj_lwInnPHgSzI@_XZX31GtTC@M@1 ziOsGAPK*i8v-U|<+d(6gBzRr zQ{7e`Z(EC*nHi(v+$Hm3ANC49O`y?WFj!odM|zQ*Wwy2wWGG88#jZeU9ex+N4h(JB zN&@BE`v|Xpq4%p^we%80!|v?fDUTy>C-RXG{Uv|*2jBZ{dG*FE`PEu3Fi?ObmMAlmM*?5T#t zXsrt%&rCl*bJ$DgAZg5M;8)>!}#QKWbi5H;8PFh-&(9sv6GG}PGe6KbeIxTDv7q4yCtL<TAWOt(i48Oyy?6D ziO6G*%IRv@3BWAr}JpqI06G(`h)wUE=BHzj`cRgu#ZS?f3N zot#Mh>@%{^`xCE@_5K{lNblWpx0MCep;~rZk&sMA8Ltu4ud1{AAf5;%cN^o>w0YzG zgJ{hY2GGcEZj0h0tMs0goE`!Tk7+A>MOtFZJy5VQ(f0lrso?OAI8(*eeF=QJ+2L)S z%$%OHgyZFgpIP8eYKN2>Z3bQ4FwINLwK{$cax*0iV?iON}pasvCvF%Te24#?lA>< z9#*7OJL5*szd_#*!XlxVQ@$1*XuP(>F`&q<*X+8__GXO#JAFMokf1lsIQG zIMG;rpx0(!);PZ1N}okdF7?@;OsomnwC4MgmzH3IU|(e}A@1>W1cU(g5WthSmRy%% zrpG_k=Xj>?Vg55YjE+J@2q+%SLIY}%&yBCpnr#BOd}x3y7w0yta%)s!$hUJk203sqD5%z#TOqXF zEgcP+3R_c8qsNS-Lf?IGm@~R6oS0`%=0&oRp1m2Di5Ds(Io!J{rx)jPw0|ti^=-ax zI-ko1^750BeB>h^lFxtXi}E8s`s4Dx_x%g`_(wh_zw}GLBoi1?=Q*2{_GM~t#=$ei zM)IDz!r>bW5craq9Bt+zF}Wx2Xh3e5+hrXb)82>Wr57Mv|G9Zgr9J!-A1=9~b7i@s ze5{>>ZvSoXKb(BTzBrNQ(&Qsepj#J9;c+8}9~2->H>I{e6U00Hezjg`d>s*?R~89^ zRrL_8M3^0Rjnc;IXC#-toM_bjeBfw4j9AdF&YX##)L7DclfcFRlzBz(8+4Eqh3w*_ z#GT2y8DhnR?n=~A9#+#pNz*RfybBr=!E*%$ zs&TFh43$AST445zF6xR6E zu0a+C%~&P@V+Se@FzvorQLCaeM&sZXaKXrb@9ILHeBu##+p|y0SH5yv78+10NEvD% z1z{h!R9zh;B{t2uuD`qb2Xfn|ga@I(Y&006VadjNT`-ZD=MR5zZ-+zXIy(%qU$kaT+R zeNpkvT1(yczX=-Ge%}iO--9j4Umlis`)_dQS4b`1<`O(3`mq!qxb5}kgYk_snQU+j z`Cy9RgmpizkTw=^VtUNFj{Goi#laN9AV`MsCtNPG&uFOy?J8n2grs>Kb@)V5?CN9a z(0x8uC7O3k+;Zphx$I^)5lgbYE=?aK zHN|WkZLqB{D0Cf?k^5m~!6`q^hhgEJWKu`gj1vQA#MFukxy!e$5dl1nz z0of~qIgcq)!00G=7esb9WHPzRYPyDc70iDoQ?98BtpCDBuGUR8MG%90SrUK_D!UGa z5#4Rl(y+UNE-w^4%HRa=#tpj=Je$gSvyw2=EqBJURpS*c8jbTp zCF7Ct7HXR&0VkVqerTCfJAjS~QI_In<)$_-HOyjt}LbtA}#s=vZcR{n

                          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�!$5oK1*okxLp=Cj1|cI(jc%`*jn;VPZzn^BB|qX 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 diff --git a/rooter/0splash/status/files/www/splashfull.html b/rooter/0splash/status/files/www/splashfull.html deleted file mode 100644 index 1624809..0000000 --- a/rooter/0splash/status/files/www/splashfull.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - Home - ROOter - - - - - - - - - - - - - - - - - - - -

                          - -
                          - -
                          The ROOter Project
                          -
                          -
                          - -
                          - -
                          -
                          - -
                          -
                          - ROOter Splash Page by Soif and Dairyman -
                          -
                          - - - - diff --git a/rooter/0splash/status/files/www/statusfull.html b/rooter/0splash/status/files/www/statusfull.html deleted file mode 100644 index 6e37899..0000000 --- a/rooter/0splash/status/files/www/statusfull.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - Live Network Status - - - - - - - - - - - - - - - -
                          -
                          ROOter Live Network Status
                          -
                          - -
                          - - - - - - - -
                          Enter your password :
                          - - - -
                          -

                          0 sec
                          - Signal

                          - -
                          -
                          -
                          Strength (%)
                          - - -
                          -
                          -
                          CSQ
                          - - -
                          -
                          -
                          RSSI (dBm)
                          - - -
                          -
                          -
                          RSCP (dBm) RSRP
                          - - -
                          -
                          -
                          ECIO (dB) RSRQ
                          - - -
                          -
                          -
                          SINR (dB)
                          - - -
                          -
                          -
                          - -
                          -

                          Network -

                          - -
                          -
                          -
                          Mode
                          - - -
                          -
                          -
                          MCC
                          - - -
                          -
                          -
                          MNC
                          - - -
                          -
                          -
                          RNC/eNB ID
                          - - - -
                          - -
                          -
                          LAC
                          - - - -
                          -
                          -
                          Cell ID
                          - - -
                          -
                          -
                          Channel
                          - - -
                          -
                          -
                          Bands
                          - - -
                          -
                          -
                          - -
                          -

                          Device -

                          - -
                          -
                          -
                          Modem
                          - - -
                          -
                          -
                          Protocol
                          - - -
                          -
                          -
                          Port
                          - - -
                          -
                          -
                          Temperature
                          - - -
                          -
                          -
                          - -
                          - -
                          -
                          - -
                          -
                          - ROOter Splash Page by Soif and Dairyman -
                          -
                          - - - diff --git a/rooter/ext-rooter-basic/Makefile b/rooter/ext-rooter-basic/Makefile deleted file mode 100644 index fe3e528..0000000 --- a/rooter/ext-rooter-basic/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -#Owned by DairyMan@Whirlpool -# -#Copyright GNU act. -include $(TOPDIR)/rules.mk - -PKG_NAME:=ext-rooter-basic -PKG_VERSION:=4.500 -PKG_RELEASE:=1 - -PKG_MAINTAINER:=Created by DM/makefile by Cobia@whirlpool -include $(INCLUDE_DIR)/package.mk - -# +kmod-rt2800-usb - -define Package/ext-rooter-basic - SECTION:=utils - CATEGORY:=ROOter - SUBMENU:=Basic Support - DEPENDS:=+luci-compat +kmod-usb-net +kmod-usb-net-huawei-cdc-ncm +kmod-usb-net-cdc-ether +kmod-usb-acm \ - +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis +kmod-usb-serial-qualcomm \ - +kmod-usb-net-sierrawireless +kmod-usb-ohci +kmod-usb-serial +kmod-nls-utf8 \ - +kmod-usb-serial-option +kmod-usb-serial-sierrawireless +luci-proto-3x \ - +kmod-usb-uhci +kmod-usb2 +luci-proto-3g +luci-theme-bootstrap \ - +usb-modeswitch +wireless-tools +rmbim +rqmi +ext-sms +ext-buttons - TITLE:=ROOter support for usbmodems - PKGARCH:=all -endef - -define Package/ext-rooter-basic/description - Helper scripts to enable ROOter to manage usb modem interfaces -endef - - -define Build/Compile -endef - -define Package/ext-rooter-basic/install - $(CP) ./files/* $(1)/ - - -endef - -$(eval $(call BuildPackage,ext-rooter-basic)) diff --git a/rooter/ext-rooter-basic/files/etc/codename b/rooter/ext-rooter-basic/files/etc/codename deleted file mode 100644 index 252dcda..0000000 --- a/rooter/ext-rooter-basic/files/etc/codename +++ /dev/null @@ -1 +0,0 @@ -CODENAME="GoldenOrb-Version-1" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/config/custom b/rooter/ext-rooter-basic/files/etc/config/custom deleted file mode 100644 index 67d0a8e..0000000 --- a/rooter/ext-rooter-basic/files/etc/config/custom +++ /dev/null @@ -1,64 +0,0 @@ - -config bwallocate 'bwallocate' - option rollover '1' - option allocate '1000' - option password '1234' - option lock '0' - option enabled '0' - -config texting 'texting' - option text '0' - option phone '1222333444' - option time '72' - option ident 'John Doe' - option method '0' - option days '1' - option increment '50' - option used '0' - option tore '0' - -config menu 'menu' - option password '1234' - option full '0' - option enabled '0' - option default '0' - -config atcmd 'atcmd' - option lock '0' - option enabled '1' - option password '1234' - option sierra '/etc/sierracmd' - option quectel '/etc/quectelcmd' - option generic '/etc/genericcmd' - -config bandlock 'bandlock' - option enabled '1' - option cenable1 '0' - option earfcn1 '0' - option pci1 '0' - -config zerotier 'zerotier' - option password '1234' - option lock '0' - option networkid 'xxxxxxxxxxxxxxxx' - -config logo 'logo' - option size 'large' - -config connect 'connect' - option ipv6 '1' - -config profile 'profile' - option save '0' - -config multi 'multiuser' - option multi '0' - option root '0' - -config bwday 'bwday' - option bwday '0' - option phone '0' - option delay '8' - -config simpin 'simpin' - option pin '' \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/config/modem b/rooter/ext-rooter-basic/files/etc/config/modem deleted file mode 100644 index 617a570..0000000 --- a/rooter/ext-rooter-basic/files/etc/config/modem +++ /dev/null @@ -1,18 +0,0 @@ - -config info 'general' - option modemnum '1' - option max '6' - -config new 'customize' - -config modem 'modem1' - option empty '1' - -config minfo1 'modeminfo1' - -config modem 'modem2' - option empty '1' - -config minfo2 'modeminfo2' - - diff --git a/rooter/ext-rooter-basic/files/etc/config/profile b/rooter/ext-rooter-basic/files/etc/config/profile deleted file mode 100644 index 42bafa1..0000000 --- a/rooter/ext-rooter-basic/files/etc/config/profile +++ /dev/null @@ -1,19 +0,0 @@ - -config default 'default' - option auth '0' - option ppp '0' - option lock '0' - option log '0' - option lb '1' - option alive '0' - option delay '5' - option at '0' - option apn 'internet' - option tzone '0' - option nodhcp '0' - option pdptype '0' - -config disable 'disable' - option enabled '0' - -config simpin 'simpin' \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/config/ttl b/rooter/ext-rooter-basic/files/etc/config/ttl deleted file mode 100644 index e7e7367..0000000 --- a/rooter/ext-rooter-basic/files/etc/config/ttl +++ /dev/null @@ -1,11 +0,0 @@ - -config ttl 'ttl' - option enabled '0' - option value '65' - -config hotspot 'hotspot' - option enable '0' - option oldenable '0' - option amt '10000' - option total '0' - diff --git a/rooter/ext-rooter-basic/files/etc/genericcmd b/rooter/ext-rooter-basic/files/etc/genericcmd deleted file mode 100644 index b6b15bc..0000000 --- a/rooter/ext-rooter-basic/files/etc/genericcmd +++ /dev/null @@ -1,4 +0,0 @@ -AT+CRSM=176,12258,0,0,10 -ICCID -at+csq -Signal Information diff --git a/rooter/ext-rooter-basic/files/etc/header_msg b/rooter/ext-rooter-basic/files/etc/header_msg deleted file mode 100644 index e3f2398..0000000 --- a/rooter/ext-rooter-basic/files/etc/header_msg +++ /dev/null @@ -1,4 +0,0 @@ - -/img/header.png -/img/rosy.png -/img/tomato.png \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan b/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan deleted file mode 100644 index 3512e42..0000000 --- a/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/10-lan +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -logger -t URL-DEBUG "hotplug (iface): action='$ACTION' interface='$INTERFACE'" - -if [ "$ACTION" = ifup -a "$INTERFACE" = "lan" ]; then - IP=$(uci get network.lan.ipaddr) - ipaddr=$(cat /etc/dnsmasq.conf | grep "address=/rooter.local/") - if [ ! -z $ipaddr ]; then - ipaddr=$(echo "$ipaddr" | sed -e "s!address=/rooter.local/!!g") - if [ $ipaddr != $IP ]; then - cp -f /etc/dnsmasq.conf /etc/dnsmasq.conf.bk - sed /"#StartURL"/,/"#EndURL"/d /etc/dnsmasq.conf.bk > /etc/dnsmasq.conf - rm -f /etc/dnsmasq.conf.bk - echo "#StartURL" >> /etc/dnsmasq.conf - echo "address=/rooter.local/$IP" >> /etc/dnsmasq.conf - echo "address=/www.rooter.local/$IP" >> /etc/dnsmasq.conf - echo "#EndURL" >> /etc/dnsmasq.conf - /etc/init.d/dnsmasq restart - fi - else - echo "#StartURL" >> /etc/dnsmasq.conf - echo "address=/rooter.local/$IP" >> /etc/dnsmasq.conf - echo "address=/www.rooter.local/$IP" >> /etc/dnsmasq.conf - echo "#EndURL" >> /etc/dnsmasq.conf - /etc/init.d/dnsmasq restart - fi -fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter b/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter deleted file mode 100644 index e0ecea9..0000000 --- a/rooter/ext-rooter-basic/files/etc/hotplug.d/iface/19-rooter +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh -# -# /etc/hotplug.d/iface/19-rooter -# - -log() { - logger -t "19-ROOTER" "$@" -} - -for I in `seq 1 $(uci get modem.general.modemnum)` -do - IFACE="wan"$I - - [ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0 - if [ ${INTERFACE} = "$IFACE" ]; then - if [ ${ACTION} = "ifup" ]; then - # TTL fix - if [ 1 = 0 ]; then - ttl=$(uci -q get modem.modeminfo$I.ttl) - if [ -z $ttl ]; then - ttl=0 - fi - if [ $ttl -eq 0 ]; then - ENB=$(uci get ttl.ttl.enabled) - if [ ! -z "$ENB" ]; then - #exst=$(cat /etc/firewall.user | grep " mangle .* $DEVICE " | wc -l) - #[ "$exst" -eq 4 ] || /usr/lib/custom/ttlx.sh - /usr/lib/custom/ttlx.sh - fi - fi - fi - MTU=$(uci get modem.modeminfo$I.mtu) - if [ -z $MTU ]; then - MTU=1500 - fi - if [ -n "$MTU" ]; then - ip link set mtu $MTU dev $DEVICE - logger -t "Custom MTU" $DEVICE set to $MTU - fi - fi - fi -done diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x b/rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x deleted file mode 100644 index 664d4ae..0000000 --- a/rooter/ext-rooter-basic/files/etc/hotplug.d/tty/30-3x +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -. /lib/functions.sh -. /lib/netifd/netifd-proto.sh - -find_3g_iface() { - local cfg="$1" - local tty="$2" - local proto - config_get proto "$cfg" proto - [ "$proto" = 3x ] || return 0 - - # bypass state vars here because 00-netstate could clobber .device - local dev=$(uci_get network "$cfg" device) - if [ "${dev##*/}" = "${tty##*/}" ]; then - if [ "$ACTION" = add ]; then - available=1 - else - available=0 - fi - proto_set_available "$cfg" $available - fi -} - -case "$DEVICENAME" in - tty*) - [ -e "/dev/$DEVICENAME" ] || [ "$ACTION" = remove ] || exit 0 - config_load network - config_foreach find_3g_iface interface "/dev/$DEVICENAME" - ;; -esac - diff --git a/rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode b/rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode deleted file mode 100644 index aef0620..0000000 --- a/rooter/ext-rooter-basic/files/etc/hotplug.d/usb/20-usb_mode +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -/usr/lib/rooter/modeswitch.sh & \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/init.d/clear b/rooter/ext-rooter-basic/files/etc/init.d/clear deleted file mode 100644 index a924aaa..0000000 --- a/rooter/ext-rooter-basic/files/etc/init.d/clear +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=19 - -start() { - COUNTER=1 - while [ $COUNTER -le 5 ]; do - INEX=$(uci -q get network.wan$COUNTER) - if [ -z $INEX ]; then - break - else - uci delete network.wan$COUNTER - uci commit network - fi - let COUNTER=COUNTER+1 - done - uci delete network.wg0 - uci delete network.wg1 - uci commit network -} diff --git a/rooter/ext-rooter-basic/files/etc/init.d/iphone b/rooter/ext-rooter-basic/files/etc/init.d/iphone deleted file mode 100644 index 625b1e0..0000000 --- a/rooter/ext-rooter-basic/files/etc/init.d/iphone +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=95 - -start() { - if [ ! -d "/var/lib/lockdown" ];then - mkdir -p /var/lib/lockdown - fi - bkp_files=`ls /etc/lockdown/locks` - for file in $bkp_files; - do - if [ ! -f "/var/lib/lockdown/$file" ];then - cp /etc/lockdown/locks/$file /var/lib/lockdown/ - fi - done - proc_usbmuxd=`ps | grep usbmuxd` - nb_usbmuxd=`echo "$proc_usbmuxd" | grep /usr/sbin/usbmuxd | wc -l` - if [ ! "$nb_usbmuxd" -eq 1 ];then - [ -x /usr/sbin/usbmuxd ] && usbmuxd -v - fi -} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/init.d/rooter b/rooter/ext-rooter-basic/files/etc/init.d/rooter deleted file mode 100644 index 1199b98..0000000 --- a/rooter/ext-rooter-basic/files/etc/init.d/rooter +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006 OpenWrt.org - -START=99 - -start() { - /usr/lib/rooter/initialize.sh -} - diff --git a/rooter/ext-rooter-basic/files/etc/init.d/usbmode b/rooter/ext-rooter-basic/files/etc/init.d/usbmode deleted file mode 100644 index 441b70a..0000000 --- a/rooter/ext-rooter-basic/files/etc/init.d/usbmode +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2013 OpenWrt.org - -START=88 -USE_PROCD=1 - -log() { - logger -t "usb-modeswitch" "$@" -} - -start_service() -{ - log "Remove early Modeswitch" -} diff --git a/rooter/ext-rooter-basic/files/etc/lockdown/locks/0000000000000000000000000000000000000000.plist b/rooter/ext-rooter-basic/files/etc/lockdown/locks/0000000000000000000000000000000000000000.plist deleted file mode 100644 index e69de29..0000000 diff --git a/rooter/ext-rooter-basic/files/etc/netspeed b/rooter/ext-rooter-basic/files/etc/netspeed deleted file mode 100644 index c227083..0000000 --- a/rooter/ext-rooter-basic/files/etc/netspeed +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/etc/quectelcmd b/rooter/ext-rooter-basic/files/etc/quectelcmd deleted file mode 100644 index a87e3b5..0000000 --- a/rooter/ext-rooter-basic/files/etc/quectelcmd +++ /dev/null @@ -1,6 +0,0 @@ -AT+CRSM=176,12258,0,0,10 -ICCID -AT+QMBNCFG="AutoSel",0 -APNFIX#1 -AT+QMBNCFG="Deactivate" -APNFIX#2 diff --git a/rooter/ext-rooter-basic/files/etc/sierracmd b/rooter/ext-rooter-basic/files/etc/sierracmd deleted file mode 100644 index d62aaa1..0000000 --- a/rooter/ext-rooter-basic/files/etc/sierracmd +++ /dev/null @@ -1,4 +0,0 @@ -AT+CRSM=176,12258,0,0,10 -ICCID -at+csq -Signal Strength diff --git a/rooter/ext-rooter-basic/files/etc/ttl.user b/rooter/ext-rooter-basic/files/etc/ttl.user deleted file mode 100644 index 98707a2..0000000 --- a/rooter/ext-rooter-basic/files/etc/ttl.user +++ /dev/null @@ -1,4 +0,0 @@ -# -# TTL Setting -# - diff --git a/rooter/ext-rooter-basic/files/etc/usb-mode.json b/rooter/ext-rooter-basic/files/etc/usb-mode.json deleted file mode 100644 index 90a68be..0000000 --- a/rooter/ext-rooter-basic/files/etc/usb-mode.json +++ /dev/null @@ -1,3180 +0,0 @@ -{ - "messages" : [ - "555342431234567800000000000006d0000000000000000000000000000000", - "55534243123456780002000000000a2a000000003300000100000000000000", - "5553424312345678000000000000061b004600000000000000000000000000", - "0f00010142", - "55534243f0298d8124000000800006bc626563240000000000000000000000", - "0902200001010080fa0904000002080650000705010200020007058102000200", - "55534243785634120100000080000601000000000000000000000000000000", - "55534243123456780000000000000616000000000000000000000000000000", - "55534243123456782400000080000612000024000000000000000000000000", - "5553424312345678000000000000061b000000ff0000000000000000000000", - "5553424368032c882400000080000612000000240000000000000000000000", - "5553424308306384c000000080000671030000000000000000000000000000", - "5553424312345678c00000008000069f140000000000000000000000000000", - "01b0000000000000000000000000000000000000000000000000000000000000", - "555342431234567800000000000006bd000000020000000000000000000000", - "1b5a01", - "5553424312345678c000000080010606f50402527000000000000000000000", - "55534243123456788000000080000606f50402527000000000000000000000", - "555342431234567800000000000006f0010300000000000000000000000000", - "55534243123456780000000000000aff554d53434847000000000000000000", - "555342431234567803000000800006f1010100000000000000000000000000", - "555342431234567800000000000005f1010100000000000000000000000000", - "555342431234567824000000800008ff024445564348470000000000000000", - "555342431234567824000000800008ff020000000000000000000000000000", - "55534243b82e238c24000000800008ff020000000000000000000000000000", - "55534243123456780600000080000601000000000000000000000000000000", - "55534243123456780600000080010a11060000000000000000000000000000", - "55534243123456780000000000000601000000000000000000000000000000", - "555342431234567824000000800008ff524445564348470000000000000000", - "555342431234567824000000800008ff524445564348473100000000000000", - "55534243123456782400000080000dfe524445564348473d4e444953000000", - "55534243d85dd88524000000800008ff524445564348470000000000000000", - "55534243123456702000000080000c85010101180101010101000000000000", - "55534243123456782400000080000685000000240000000000000000000000", - "55534243d8a523862400000080000685000000240000000000000000000000", - "5553424348c4758600000000000010ff000000000000000000000000000000", - "555342431234567824000000800006bc626563240000000000000000000000", - "5553424330f4cf8124000000800108df200000000000000000000000000000", - "5553424312345678c00000008000069f030000000000000000000000000000", - "555342431234567824000000800008FF05B112AEE102000000000000000000", - "55534243123456780000000000000606f50402527000000000000000000000", - "55534243123456780000000080000606f50402527000000000000000000000", - "555342431234567800000000000001ff000000000000000000000000000000", - "55534243123456781200000080000603000000020000000000000000000000", - "55534243123456780000000000000cff020000000000000000000000000000", - "5553424312345678800000008000060619181a207000000000000000000000", - "555342431234567800000000000010ff000000000000000000000000000000", - "555342431234567800000000000008ff000000000000030000000000000000", - "555342431234567824000000800108df200000000000000000000000000000", - "55534243f8d2e6838000000080000606f50402527000000000000000000000", - "555342431234567800000000000003f0010100000000000000000000000000", - "55534243123456780000000000000600000000000000000000000000000000", - "5553424312345679c000000080000671030000000000000000000000000000", - "555342430820298900000000000003f0010100000000000000000000000000", - "55534243123456700000000000000616aa0000000000000000000000000000", - "5553424312345678c000000080000671010000000000000000000000000000", - "5553424340799288C000000080010A16000000C00000000000000000000000", - "555342431234567800000000000006161f6d62706b00000000000000000000", - "5553424398e2c4812400000080000bff524445564348473d43440000000000" - ], - - "devices" : { - "03f0:002a": { - "*": { - "t_class": 7, - "msg": [ 0 ] - } - }, - "03f0:032a": { - "*": { - "t_class": 7, - "msg": [ 0 ] - } - }, - "03f0:371d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:4b1d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:4e1d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:521d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:531d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:541d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:581d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:631d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:641d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:681d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:911d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:931d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:9a1d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:9d1d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "03f0:a31d": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "0408:1000": { - "*": { - "t_vendor": 1032, - "t_product": [ 59906 ], - "msg": [ 1 ] - } - }, - "0408:ea17": { - "*": { - "t_vendor": 1032, - "t_product": [ 59926 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0408:ea43": { - "*": { - "t_vendor": 1032, - "t_product": [ 59975, 59977, 59981 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0408:f000": { - ":uMa=Yota": { - "t_vendor": 1032, - "t_product": [ 53257 ], - "msg": [ 2 ] - } - }, - "0421:060c": { - "*": { - "t_vendor": 1057, - "t_product": [ 1550 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:0610": { - "*": { - "t_vendor": 1057, - "t_product": [ 1554 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:0618": { - "*": { - "t_vendor": 1057, - "t_product": [ 1561 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:061d": { - "*": { - "t_vendor": 1057, - "t_product": [ 1566 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:0622": { - "*": { - "t_vendor": 1057, - "t_product": [ 1571 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:0627": { - "*": { - "t_vendor": 1057, - "t_product": [ 1554, 1577 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:062c": { - "*": { - "t_vendor": 1057, - "t_product": [ 1581, 1583 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:0632": { - "*": { - "t_vendor": 1057, - "t_product": [ 1586 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0421:0637": { - "*": { - "t_vendor": 1057, - "t_product": [ 1592 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "046d:c261": { - "*": { - "t_class": 3, - "msg_endpoint": 1, - "msg": [ 3 ], - "response_endpoint": 1 - } - }, - "0471:1210": { - ":uMa=Philips": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=Wisue": { - "t_vendor": 7612, - "t_product": [ 5 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0471:1237": { - "*": { - "t_vendor": 1137, - "t_product": [ 4614, 4660 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0482:024d": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "04bb:bccd": { - "*": { - "t_vendor": 1211, - "t_product": [ 2377 ], - "msg": [ 4 ] - } - }, - "04cc:2251": { - "*": { - "t_vendor": 1228, - "t_product": [ 8793, 8814 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "04cc:225c": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "04cc:226e": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "04cc:226f": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "04e8:680c": { - "*": { - "t_vendor": 1256, - "t_product": [ 26514 ], - "msg": [ 5 ] - } - }, - "04e8:689a": { - "*": { - "t_vendor": 1256, - "t_product": [ 26761 ], - "msg": [ 6 ] - } - }, - "04e8:f000": { - ":sMo=U209": { - "t_vendor": 1256, - "t_product": [ 26113 ], - "msg": [ 7 ] - } - }, - "04fc:2140": { - "*": { - "t_vendor": 1276, - "t_product": [ 1557, 4672 ], - "msg": [ 8 ] - } - }, - "057c:62ff": { - "*": { - "t_vendor": 1404, - "t_product": [ 34049, 34050 ], - "msg": [ 9 ] - } - }, - "057c:84ff": { - "*": { - "t_vendor": 1404, - "t_product": [ 33793 ], - "msg": [ 9 ] - } - }, - "0586:2030": { - "*": { - "t_vendor": 1414, - "t_product": [ 13379, 13380 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "05c6:0010": { - "*": { - "t_vendor": 1478, - "t_product": [ 160 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "05c6:1000": { - ":uMa=AnyDATA": { - "t_vendor": 5845, - "t_product": [ 25858 ], - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=CELOT": { - "t_vendor": 8479, - "t_product": [ 26625, 26626 ], - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=Co.,Ltd": { - "t_vendor": 7433, - "t_product": [ 17158 ], - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=DGT": { - "t_vendor": 8479, - "t_product": [ 26626 ], - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=SAMSUNG": { - "t_vendor": 1256, - "t_product": [ 26113 ], - "msg": [ 7 ] - }, - ":uMa=SSE": { - "t_vendor": 1478, - "t_product": [ 24576 ], - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=StrongRising": { - "t_vendor": 650, - "t_product": [ 4102 ], - "mode": "StandardEject", - "msg": [ ] - }, - ":uMa=Vertex": { - "t_vendor": 8167, - "t_product": [ 256 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "05c6:2000": { - "*": { - "t_vendor": 1478, - "t_product": [ 21, 22, 24, 52759 ], - "msg": [ 10 ], - "response": true, - "check": true - } - }, - "05c6:2001": { - "*": { - "t_vendor": 7694, - "t_product": [ 52758, 52759, 52990 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "05c6:6503": { - "*": { - "t_vendor": 5845, - "t_product": [ 25858 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "05c6:9024": { - "*": { - "t_vendor": 1478, - "t_product": [ 36901 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "05c6:98ff": { - "*": { - "t_vendor": 1478, - "t_product": [ 24577 ], - "mode": "Sierra", - "msg": [ ] - } - }, - "05c6:f000": { - "*": { - "t_vendor": 1478, - "t_product": [ 22, 24576, 36864 ], - "mode": "StandardEject", - "msg": [ 11 ] - } - }, - "05c7:1000": { - "*": { - "t_vendor": 1479, - "t_product": [ 24576 ], - "msg": [ 12 ] - } - }, - "0685:2000": { - "*": { - "t_vendor": 7326, - "t_product": [ 38403 ], - "msg": [ 10 ], - "response": true - } - }, - "072f:100d": { - "*": { - "t_vendor": 1839, - "t_product": [ 37068 ], - "msg_endpoint": 2, - "msg": [ 13 ] - } - }, - "07d1:a800": { - "*": { - "t_vendor": 2001, - "t_product": [ 15873, 15874, 32268 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "07d1:a804": { - "*": { - "t_vendor": 2001, - "t_product": [ 32273 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "07d1:f000": { - "*": { - "t_vendor": 2001, - "t_product": [ 32263 ], - "msg": [ 14 ] - } - }, - "0846:0fff": { - "*": { - "t_vendor": 2118, - "t_product": [ 26835 ], - "mode": "Sierra", - "msg": [ ] - } - }, - "0922:1001": { - "*": { - "t_vendor": 2338, - "t_product": [ 4098 ], - "msg_endpoint": 1, - "msg": [ 15 ], - "response_endpoint": 1 - } - }, - "0922:1003": { - "*": { - "t_vendor": 2338, - "t_product": [ 4100 ], - "msg_endpoint": 1, - "msg": [ 15 ], - "response_endpoint": 1 - } - }, - "0922:1007": { - "*": { - "t_vendor": 2338, - "t_product": [ 4104 ], - "msg_endpoint": 1, - "msg": [ 15 ], - "response_endpoint": 1 - } - }, - "0930:0d46": { - "*": { - "t_vendor": 2352, - "t_product": [ 3397 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0ace:2011": { - "*": { - "mode": "StandardEject", - "msg": [ ] - } - }, - "0ace:20ff": { - "*": { - "mode": "StandardEject", - "msg": [ ] - } - }, - "0af0:4007": { - "*": { - "t_vendor": 2800, - "t_product": [ 16389 ], - "mode": "Sierra", - "msg": [ ] - } - }, - "0b3c:c700": { - "*": { - "t_vendor": 2876, - "t_product": [ 49152, 49153, 49154 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0b3c:f000": { - "*": { - "t_vendor": 2876, - "t_product": [ 49155, 49156 ], - "msg": [ 16 ], - "response": true - } - }, - "0b3c:f00c": { - "*": { - "t_vendor": 2876, - "t_product": [ 49162 ], - "msg": [ 17 ] - } - }, - "0b3c:f017": { - "*": { - "t_vendor": 2876, - "t_product": [ 49163 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0bdb:190d": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "0bdb:1910": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "0cf3:20ff": { - "*": { - "t_vendor": 3315, - "t_product": [ 28688 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0d46:45a1": { - "*": { - "t_vendor": 3398, - "t_product": [ 17833 ], - "mode": "Kobil", - "msg": [ ] - } - }, - "0d46:45a5": { - "*": { - "t_vendor": 3398, - "t_product": [ 17837 ], - "mode": "Kobil", - "msg": [ ] - } - }, - "0df7:0800": { - "*": { - "t_class": 255, - "mode": "MobileAction", - "msg": [ ] - } - }, - "0e8d:0002": { - ":uPr=MT": { - "t_vendor": 3725, - "t_product": [ 161, 162, 165 ], - "msg": [ 18 ] - }, - ":uPr=Product": { - "t_vendor": 3725, - "t_product": [ 161, 162, 165 ], - "msg": [ 18 ] - } - }, - "0e8d:7109": { - "*": { - "t_vendor": 3725, - "t_product": [ 28949, 28952 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "0fce:d0cf": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "0fce:d0df": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "0fce:d0e1": { - "*": { - "t_class": 2, - "mode": "Sony", - "msg": [ ], - "config": 2 - } - }, - "0fce:d103": { - "*": { - "t_class": 2, - "mode": "Sony", - "msg": [ ], - "config": 2 - } - }, - "0fd1:1000": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "1004:1000": { - "*": { - "t_class": 255, - "msg": [ 19 ] - } - }, - "1004:607f": { - "*": { - "t_vendor": 4100, - "t_product": [ 24576, 24852 ], - "msg": [ 20 ], - "response": true - } - }, - "1004:610c": { - "*": { - "t_vendor": 4100, - "t_product": [ 24841 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:613a": { - "*": { - "t_vendor": 4100, - "t_product": [ 24868 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:613f": { - "*": { - "t_vendor": 4100, - "t_product": [ 24897 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:614e": { - "*": { - "t_vendor": 4100, - "t_product": [ 24885 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:6156": { - "*": { - "t_vendor": 4100, - "t_product": [ 24919 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:6190": { - "*": { - "t_vendor": 4100, - "t_product": [ 24963, 24999 ], - "mode": "StandardEject", - "msg": [ ], - "wait": 10 - } - }, - "1004:61dd": { - "*": { - "t_vendor": 4100, - "t_product": [ 24975 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:61e7": { - "*": { - "t_vendor": 4100, - "t_product": [ 25062 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:61eb": { - "*": { - "t_vendor": 4100, - "t_product": [ 25066 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1004:6327": { - "*": { - "t_vendor": 4100, - "t_product": [ 25382 ], - "msg": [ 21 ] - } - }, - "106c:3b03": { - "*": { - "t_vendor": 4204, - "t_product": [ 14101 ], - "msg": [ 22 ] - } - }, - "106c:3b05": { - "*": { - "t_vendor": 4204, - "t_product": [ 14102 ], - "msg": [ 23 ] - } - }, - "106c:3b06": { - "*": { - "t_vendor": 4204, - "t_product": [ 14103 ], - "msg": [ 24 ] - } - }, - "106c:3b11": { - "*": { - "t_vendor": 4204, - "t_product": [ 14104 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "106c:3b14": { - "*": { - "t_vendor": 4204, - "t_product": [ 14113 ], - "msg": [ 22 ] - } - }, - "1076:7f40": { - "*": { - "t_vendor": 4214, - "t_product": [ 32512 ], - "mode": "GCT", - "msg": [ ] - } - }, - "109b:f009": { - "*": { - "t_vendor": 4251, - "t_product": [ 37140 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1199:0fff": { - "*": { - "t_vendor": 4505, - "t_product": [ 23, 24, 25, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 274, 288, 536, 544, 548, 769, 26626, 26627, 26628, 26629, 26632, 26633, 26642, 26643, 26645, 26646, 26656, 26657, 26658, 26674, 26675, 26676, 26677, 26680, 26681, 26682, 26683, 26684, 26685, 26686, 26704, 26705, 26706, 26707, 26709, 26710, 26713, 26714, 26752, 26768, 26769, 26770, 26771, 26786, 26787, 26794, 36881, 36882, 36945 ], - "mode": "Sierra", - "msg": [ ] - } - }, - "1199:9011": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:9013": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:9017": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:901b": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:901c": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:901f": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:9041": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:9051": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:9053": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1199:9063": { - "*": { - "msg": [ ], - "config": 1 - } - }, - "1266:1000": { - "*": { - "t_vendor": 4710, - "t_product": [ 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4113, 4114 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "12d1:1001": { - "*": { - "t_class": 255, - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:1003": { - "*": { - "t_class": 255, - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:1009": { - "*": { - "t_class": 255, - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:1010": { - "*": { - "t_class": 255, - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:101e": { - "*": { - "t_class": 255, - "msg": [ 25 ] - } - }, - "12d1:1030": { - "*": { - "t_vendor": 4817, - "t_product": [ 4148 ], - "msg": [ 26 ] - } - }, - "12d1:1031": { - "*": { - "t_vendor": 4817, - "t_product": [ 4149 ], - "msg": [ 26 ] - } - }, - "12d1:1413": { - "*": { - "t_class": 255, - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:1414": { - "*": { - "t_class": 255, - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:1446": { - "*": { - "t_vendor": 4817, - "t_product": [ 4097, 5124, 5126, 5131, 5132, 5138, 5143, 5147, 5161, 5170, 5171, 5174, 5292, 5382, 5388, 5393 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1449": { - "*": { - "t_vendor": 4817, - "t_product": [ 5188 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14ad": { - "*": { - "t_vendor": 4817, - "t_product": [ 5294 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14b5": { - "*": { - "t_vendor": 4817, - "t_product": [ 5288, 5290 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14b7": { - "*": { - "t_vendor": 4817, - "t_product": [ 5324 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14ba": { - "*": { - "t_vendor": 4817, - "t_product": [ 5330 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14c1": { - "*": { - "t_vendor": 4817, - "t_product": [ 5318 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14c3": { - "*": { - "t_vendor": 4817, - "t_product": [ 5320 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14c4": { - "*": { - "t_vendor": 4817, - "t_product": [ 5322 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14c5": { - "*": { - "t_vendor": 4817, - "t_product": [ 5323 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14d1": { - "*": { - "t_vendor": 4817, - "t_product": [ 5321 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:14fe": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382, 5391, 5405, 7198 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1505": { - "*": { - "t_vendor": 4817, - "t_product": [ 5131, 5132, 5382, 5391, 5386 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:151a": { - "*": { - "t_vendor": 4817, - "t_product": [ 5403, 5405, 5406 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1520": { - "*": { - "t_vendor": 4817, - "t_product": [ 5221 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1521": { - "*": { - "t_vendor": 4817, - "t_product": [ 5220 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1523": { - "*": { - "t_vendor": 4817, - "t_product": [ 5265 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1526": { - "*": { - "t_vendor": 4817, - "t_product": [ 5327 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1527": { - "*": { - "t_vendor": 4817, - "t_product": [ 5524 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1553": { - "*": { - "t_vendor": 4817, - "t_product": [ 4097 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1557": { - "*": { - "t_vendor": 4817, - "t_product": [ 5285 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:155a": { - "*": { - "t_vendor": 4817, - "t_product": [ 5325 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:155b": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:156a": { - "*": { - "t_vendor": 4817, - "t_product": [ 5483, 5484 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1570": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:1571": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:1572": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:1573": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:157c": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:157d": { - "*": { - "t_vendor": 4817, - "t_product": [ 5339, 5340 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1580": { - "*": { - "t_vendor": 4817, - "t_product": [ 5509 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1581": { - "*": { - "t_vendor": 4817, - "t_product": [ 5511 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1582": { - "*": { - "t_vendor": 4817, - "t_product": [ 5512 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1583": { - "*": { - "t_vendor": 4817, - "t_product": [ 5513 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1597": { - "*": { - "t_vendor": 4817, - "t_product": [ 5528 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15bb": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:15c0": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:15c1": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:15ca": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15cd": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15ce": { - "*": { - "t_vendor": 4817, - "t_product": [ 5553, 5555 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15cf": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15d0": { - "*": { - "t_vendor": 4817, - "t_product": [ 5585 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15d2": { - "*": { - "t_vendor": 4817, - "t_product": [ 5587 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15e7": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15ec": { - "*": { - "t_vendor": 4817, - "t_product": [ 7206 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:15f0": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:1805": { - "*": { - "t_class": 255, - "msg": [ 25 ] - } - }, - "12d1:1c0b": { - "*": { - "t_vendor": 4817, - "t_product": [ 7173, 7174, 7175, 7176, 7184 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1c1b": { - "*": { - "t_vendor": 4817, - "t_product": [ 5382 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1c24": { - "*": { - "t_vendor": 4817, - "t_product": [ 7186, 7203 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1c25": { - "*": { - "msg": [ ], - "config": 0 - } - }, - "12d1:1d50": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "12d1:1da1": { - "*": { - "t_vendor": 4817, - "t_product": [ 7433 ], - "mode": "Huawei", - "msg": [ ] - } - }, - "12d1:1f01": { - "*": { - "t_vendor": 4817, - "t_product": [ 5339, 5340 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f02": { - "*": { - "t_vendor": 4817, - "t_product": [ 5340 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f03": { - "*": { - "t_vendor": 4817, - "t_product": [ 5339 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f04": { - "*": { - "t_vendor": 4817, - "t_product": [ 5564 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f05": { - "*": { - "t_vendor": 4817, - "t_product": [ 5565 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f06": { - "*": { - "t_vendor": 4817, - "t_product": [ 5575 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f07": { - "*": { - "t_vendor": 4817, - "t_product": [ 5567 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f09": { - "*": { - "t_vendor": 4817, - "t_product": [ 7248 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f11": { - "*": { - "t_vendor": 4817, - "t_product": [ 5308 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f15": { - "*": { - "t_vendor": 4817, - "t_product": [ 5120, 5367 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f16": { - "*": { - "mode": "MBIM", - "msg": [ ] - } - }, - "12d1:1f17": { - "*": { - "t_vendor": 4817, - "t_product": [ 5494 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f18": { - "*": { - "t_vendor": 4817, - "t_product": [ 5495 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f19": { - "*": { - "t_vendor": 4817, - "t_product": [ 5370, 5493, 5496 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f1b": { - "*": { - "t_vendor": 4817, - "t_product": [ 5497 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f1c": { - "*": { - "t_vendor": 4817, - "t_product": [ 5498, 5520 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f1d": { - "*": { - "t_vendor": 4817, - "t_product": [ 5499, 5521 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:1f1e": { - "*": { - "t_vendor": 4817, - "t_product": [ 5503, 5522 ], - "mode": "HuaweiNew", - "msg": [ ] - } - }, - "12d1:380b": { - "*": { - "t_class": 2, - "mode": "StandardEject", - "msg": [ ] - } - }, - "1307:1169": { - "*": { - "t_vendor": 5041, - "t_product": [ 49 ], - "mode": "Cisco", - "msg": [ ] - } - }, - "1410:5010": { - "*": { - "t_vendor": 5136, - "t_product": [ 16640, 17408, 28720 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5020": { - "*": { - "t_vendor": 5136, - "t_product": [ 24576, 28673 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5023": { - "*": { - "t_vendor": 5136, - "t_product": [ 28720 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5030": { - "*": { - "t_vendor": 5136, - "t_product": [ 24576 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5031": { - "*": { - "t_vendor": 5136, - "t_product": [ 24578 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5041": { - "*": { - "t_vendor": 5136, - "t_product": [ 28673, 28675 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5055": { - "*": { - "t_vendor": 5136, - "t_product": [ 24626 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:5059": { - "*": { - "t_vendor": 5136, - "t_product": [ 28721, 28738 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:7001": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "1410:9020": { - "*": { - "msg": [ ], - "config": 4 - } - }, - "148e:a000": { - "*": { - "t_class": 2, - "mode": "Sequans", - "msg": [ ] - } - }, - "148f:2578": { - "*": { - "t_vendor": 5263, - "t_product": [ 36897 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "148f:2878": { - "*": { - "t_vendor": 5263, - "t_product": [ 30209 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "15eb:7153": { - "*": { - "t_vendor": 5611, - "t_product": [ 29010 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1614:0800": { - "*": { - "t_class": 255, - "msg": [ 27 ] - } - }, - "1614:0802": { - "*": { - "t_class": 255, - "msg": [ 27 ] - } - }, - "16d5:f000": { - "*": { - "t_vendor": 5845, - "t_product": [ 26115 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "16d8:6281": { - "*": { - "t_class": 255, - "msg": [ 28 ] - } - }, - "16d8:6803": { - "*": { - "t_class": 2, - "msg": [ 29 ] - } - }, - "16d8:6804": { - "*": { - "t_class": 255, - "msg": [ 28 ] - } - }, - "16d8:700a": { - "*": { - "t_class": 255, - "msg": [ 30 ] - } - }, - "16d8:700b": { - "*": { - "t_class": 255, - "msg": [ 30 ] - } - }, - "16d8:f000": { - "*": { - "t_vendor": 5848, - "t_product": [ 24582 ], - "msg": [ 31 ] - } - }, - "1726:1900": { - "*": { - "t_vendor": 5926, - "t_product": [ 4096 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1726:f00e": { - "*": { - "t_vendor": 5926, - "t_product": [ 40960 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1782:0003": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "1782:0023": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "198a:0003": { - "*": { - "t_vendor": 6538, - "t_product": [ 2 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "198f:bccd": { - "*": { - "t_vendor": 6543, - "t_product": [ 544 ], - "msg": [ 4 ] - } - }, - "19d2:0003": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0026": { - "*": { - "t_vendor": 6610, - "t_product": [ 115, 148, 338 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0033": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0040": { - "*": { - "t_vendor": 6610, - "t_product": [ 34 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0053": { - "*": { - "t_vendor": 6610, - "t_product": [ 49 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0083": { - ":uPr=WCDMA": { - "t_vendor": 6610, - "t_product": [ 292 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0090": { - "*": { - "t_vendor": 6610, - "t_product": [ 52 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0101": { - "*": { - "t_vendor": 6610, - "t_product": [ 260 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0103": { - "*": { - "t_vendor": 6610, - "t_product": [ 49 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0110": { - "*": { - "t_vendor": 6610, - "t_product": [ 289 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0115": { - "*": { - "t_vendor": 6610, - "t_product": [ 278 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0120": { - "*": { - "t_vendor": 6610, - "t_product": [ 121 ], - "detach_storage": false, - "mode": "StandardEject", - "msg": [ ], - "response": false, - "interface": 0 - } - }, - "19d2:0146": { - "*": { - "t_vendor": 6610, - "t_product": [ 322, 323 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0149": { - "*": { - "t_vendor": 6610, - "t_product": [ 292 ], - "mode": "StandardEject", - "msg": [ 32 ] - } - }, - "19d2:0150": { - "*": { - "t_vendor": 6610, - "t_product": [ 292 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0154": { - "*": { - "t_vendor": 6610, - "t_product": [ 23, 279, 8195 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0166": { - "*": { - "t_vendor": 6610, - "t_product": [ 359 ], - "msg": [ 33 ] - } - }, - "19d2:0169": { - "*": { - "t_vendor": 6610, - "t_product": [ 368 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0198": { - "*": { - "t_vendor": 6610, - "t_product": [ 409 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0266": { - "*": { - "t_vendor": 6610, - "t_product": [ 613 ], - "mode": "StandardEject", - "msg": [ 34 ] - } - }, - "19d2:0304": { - "*": { - "t_vendor": 6610, - "t_product": [ 841 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0318": { - "*": { - "t_vendor": 6610, - "t_product": [ 791, 816 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0325": { - "*": { - "t_vendor": 6610, - "t_product": [ 806 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:0388": { - "*": { - "t_vendor": 6610, - "t_product": [ 1095 ], - "msg": [ 33 ] - } - }, - "19d2:0413": { - "*": { - "t_vendor": 6610, - "t_product": [ 1042 ], - "msg": [ 34 ] - } - }, - "19d2:1001": { - "*": { - "t_vendor": 6610, - "t_product": [ 4098, 4099 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1007": { - "*": { - "t_vendor": 6610, - "t_product": [ 4104 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1009": { - "*": { - "t_vendor": 6610, - "t_product": [ 4112 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1013": { - "*": { - "t_vendor": 6610, - "t_product": [ 4117 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1017": { - "*": { - "t_vendor": 6610, - "t_product": [ 4120 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1019": { - "*": { - "t_vendor": 6610, - "t_product": [ 4129 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1020": { - "*": { - "t_vendor": 6610, - "t_product": [ 4129 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1022": { - "*": { - "t_vendor": 6610, - "t_product": [ 4131, 4132 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1026": { - "*": { - "t_vendor": 6610, - "t_product": [ 4135, 4136, 4137 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1030": { - "*": { - "t_vendor": 6610, - "t_product": [ 4145, 4146 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1034": { - "*": { - "t_vendor": 6610, - "t_product": [ 4149, 4150, 4151 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1038": { - "*": { - "t_vendor": 6610, - "t_product": [ 4153, 4160 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1042": { - "*": { - "t_vendor": 6610, - "t_product": [ 4163 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1046": { - "*": { - "t_vendor": 6610, - "t_product": [ 4167 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1171": { - "*": { - "t_vendor": 6610, - "t_product": [ 4467 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1175": { - "*": { - "t_vendor": 6610, - "t_product": [ 4471 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1179": { - "*": { - "t_vendor": 6610, - "t_product": [ 4481 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1201": { - "*": { - "t_vendor": 6610, - "t_product": [ 4611 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1207": { - "*": { - "t_vendor": 6610, - "t_product": [ 4616 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1210": { - "*": { - "t_vendor": 6610, - "t_product": [ 4625 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1216": { - "*": { - "t_vendor": 6610, - "t_product": [ 4631 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1219": { - "*": { - "t_vendor": 6610, - "t_product": [ 4640, 4642 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1224": { - "*": { - "t_vendor": 6610, - "t_product": [ 130 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1225": { - "*": { - "t_vendor": 6610, - "t_product": [ 5125 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1227": { - "*": { - "t_vendor": 6610, - "t_product": [ 4690 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1232": { - "*": { - "t_vendor": 6610, - "t_product": [ 4712, 8195 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1233": { - "*": { - "t_vendor": 6610, - "t_product": [ 4720 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1237": { - "*": { - "t_vendor": 6610, - "t_product": [ 23 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1238": { - "*": { - "t_vendor": 6610, - "t_product": [ 23 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1420": { - "*": { - "t_vendor": 6610, - "t_product": [ 5125 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1511": { - "*": { - "t_vendor": 6610, - "t_product": [ 5394 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1514": { - "*": { - "t_vendor": 6610, - "t_product": [ 5397 ], - "msg": [ 35 ] - } - }, - "19d2:1517": { - "*": { - "t_vendor": 6610, - "t_product": [ 5401 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1520": { - "*": { - "t_vendor": 6610, - "t_product": [ 322 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1523": { - "*": { - "t_vendor": 6610, - "t_product": [ 5413 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1528": { - "*": { - "t_vendor": 6610, - "t_product": [ 5415 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1536": { - "*": { - "t_vendor": 6610, - "t_product": [ 5431, 5432 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1542": { - "*": { - "t_vendor": 6610, - "t_product": [ 5444 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1580": { - "*": { - "t_vendor": 6610, - "t_product": [ 5506 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:1588": { - "*": { - "t_vendor": 6610, - "t_product": [ 5513, 5521, 5522 ], - "mode": "StandardEject", - "msg": [ 32 ] - } - }, - "19d2:1595": { - "*": { - "t_vendor": 6610, - "t_product": [ 5428, 5522, 5526, 5632 ], - "mode": "StandardEject", - "msg": [ 32 ] - } - }, - "19d2:2000": { - "*": { - "t_vendor": 6610, - "t_product": [ 1, 2, 21, 22, 23, 25, 36, 49, 51, 55, 66, 82, 85, 97, 99, 100, 102, 145, 264, 279, 296, 337, 343, 375, 5122, 8194, 8195 ], - "mode": "StandardEject", - "msg": [ 32 ] - } - }, - "19d2:2004": { - "*": { - "t_vendor": 6610, - "t_product": [ 5122 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:bccd": { - "*": { - "t_vendor": 6610, - "t_product": [ 370 ], - "msg": [ 36 ] - } - }, - "19d2:ffde": { - "*": { - "t_vendor": 6610, - "t_product": [ 65501 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "19d2:ffe6": { - "*": { - "t_vendor": 6610, - "t_product": [ 65509 ], - "msg": [ 37 ] - } - }, - "19d2:fff5": { - "*": { - "t_vendor": 6610, - "t_product": [ 65508, 65513, 65521, 65534, 65535 ], - "msg": [ 38 ] - } - }, - "19d2:fff6": { - "*": { - "t_vendor": 6610, - "t_product": [ 65521 ], - "msg": [ 38 ] - } - }, - "1a8d:1000": { - "*": { - "t_vendor": 6797, - "t_product": [ 4098, 4103, 4105, 4109, 8198 ], - "mode": "StandardEject", - "msg": [ ], - "release_delay": 4000, - "response": true - } - }, - "1a8d:2000": { - "*": { - "t_vendor": 6797, - "t_product": [ 8198 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1ab7:5700": { - "*": { - "t_vendor": 6839, - "t_product": [ 8192, 22321 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1b7d:0700": { - "*": { - "t_vendor": 7037, - "t_product": [ 1 ], - "msg": [ 39 ] - } - }, - "1bbb:000f": { - "*": { - "t_vendor": 7099, - "t_product": [ 15 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1bbb:00ca": { - "*": { - "t_class": 255, - "msg": [ 17 ] - } - }, - "1bbb:011f": { - "*": { - "t_vendor": 7099, - "t_product": [ 262 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1bbb:022c": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "1bbb:025e": { - "*": { - "t_vendor": 7099, - "t_product": [ 405 ], - "msg": [ 17 ] - } - }, - "1bbb:f000": { - "*": { - "t_vendor": 7099, - "t_product": [ 0, 23, 183, 286, 401, 405 ], - "msg": [ 17 ] - } - }, - "1bbb:f017": { - "*": { - "t_vendor": 7099, - "t_product": [ 23, 286, 515 ], - "msg": [ 17 ] - } - }, - "1bbb:f052": { - "*": { - "t_vendor": 7099, - "t_product": [ 82 ], - "msg": [ 17 ] - } - }, - "1c9e:1001": { - "*": { - "t_vendor": 7326, - "t_product": [ 24672, 24673 ], - "msg": [ 40 ] - } - }, - "1c9e:6000": { - "*": { - "t_class": 255, - "msg": [ 27 ] - } - }, - "1c9e:6061": { - ":uPr=Storage": { - "t_class": 255, - "msg": [ 40 ] - } - }, - "1c9e:9101": { - "*": { - "t_vendor": 7326, - "t_product": [ 37124 ], - "msg": [ 40 ] - } - }, - "1c9e:9200": { - "*": { - "t_vendor": 7326, - "t_product": [ 37378 ], - "msg": [ 40 ] - } - }, - "1c9e:9401": { - "*": { - "t_vendor": 7326, - "t_product": [ 37892 ], - "msg": [ 40 ] - } - }, - "1c9e:9800": { - "*": { - "t_class": 255, - "msg": [ 17 ] - } - }, - "1c9e:98ff": { - "*": { - "t_vendor": 7326, - "t_product": [ 26625, 38913, 38915 ], - "msg": [ 41 ] - } - }, - "1c9e:9bfe": { - "*": { - "t_vendor": 7326, - "t_product": [ 39681 ], - "msg": [ 40 ] - } - }, - "1c9e:9d00": { - "*": { - "t_class": 255, - "msg": [ 40 ] - } - }, - "1c9e:9e00": { - "*": { - "t_class": 255, - "msg": [ 40 ] - } - }, - "1c9e:9e08": { - "*": { - "t_vendor": 7326, - "t_product": [ 40472 ], - "mode": "Sierra", - "msg": [ ] - } - }, - "1c9e:f000": { - "*": { - "t_vendor": 7326, - "t_product": [ 36864, 38403, 38405, 38407, 39168 ], - "msg": [ 42 ], - "wait": 1 - }, - ":uMa=USB_Modem": { - "t_vendor": 7326, - "t_product": [ 36864, 38403, 38405, 38407, 39168, 39424 ], - "msg": [ 17 ], - "wait": 1 - } - }, - "1c9e:f010": { - "*": { - "t_vendor": 7326, - "t_product": [ 61697 ], - "msg": [ 40 ] - } - }, - "1d09:1000": { - "*": { - "t_vendor": 7433, - "t_product": [ 4112 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1d09:1021": { - "*": { - "t_vendor": 7433, - "t_product": [ 4112 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1d09:1025": { - "*": { - "t_vendor": 7433, - "t_product": [ 4134 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "1da5:f000": { - "*": { - "t_vendor": 7589, - "t_product": [ 17682 ], - "mode": "Qisda", - "msg": [ ] - } - }, - "1dbc:0669": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "1dd6:1000": { - "*": { - "t_vendor": 7638, - "t_product": [ 4098 ], - "msg": [ 43 ], - "response": true - } - }, - "1de1:1101": { - "*": { - "t_vendor": 8679, - "t_product": [ 14 ], - "msg": [ 44 ] - } - }, - "1e0e:f000": { - "*": { - "t_vendor": 7694, - "t_product": [ 36864, 37120, 37376 ], - "msg": [ 14 ], - "response": true - } - }, - "1e89:f000": { - "*": { - "t_vendor": 7817, - "t_product": [ 6688 ], - "msg": [ 45 ] - } - }, - "1edf:6003": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "1ee8:0003": { - "*": { - "t_vendor": 7912, - "t_product": [ 4 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0007": { - "*": { - "t_vendor": 7912, - "t_product": [ 11 ], - "msg": [ 46 ] - } - }, - "1ee8:0009": { - "*": { - "t_vendor": 7912, - "t_product": [ 11 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0013": { - "*": { - "t_vendor": 7912, - "t_product": [ 17, 18, 20 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0018": { - "*": { - "t_vendor": 7912, - "t_product": [ 23 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0040": { - "*": { - "t_vendor": 7912, - "t_product": [ 62, 63 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0045": { - "*": { - "t_vendor": 7912, - "t_product": [ 68 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0048": { - "*": { - "t_vendor": 7912, - "t_product": [ 73 ], - "msg": [ 46 ] - } - }, - "1ee8:004a": { - "*": { - "t_vendor": 7912, - "t_product": [ 73 ], - "msg": [ 46 ] - } - }, - "1ee8:004f": { - "*": { - "t_vendor": 7912, - "t_product": [ 78 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0054": { - "*": { - "t_vendor": 7912, - "t_product": [ 83 ], - "msg": [ 46 ], - "response": true - } - }, - "1ee8:0060": { - "*": { - "t_vendor": 7912, - "t_product": [ 95 ], - "msg": [ 47 ] - } - }, - "1ee8:0063": { - "*": { - "t_vendor": 7912, - "t_product": [ 100, 101 ], - "msg": [ 47 ] - } - }, - "1ee8:0068": { - "*": { - "t_vendor": 7912, - "t_product": [ 105 ], - "msg": [ 47 ] - } - }, - "1f28:0021": { - "*": { - "t_vendor": 7976, - "t_product": [ 32 ], - "msg": [ 48 ] - } - }, - "1fac:0032": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "1fac:0130": { - "*": { - "t_vendor": 8108, - "t_product": [ 305 ], - "msg": [ 48 ] - } - }, - "1fac:0150": { - "*": { - "t_vendor": 8108, - "t_product": [ 337 ], - "msg": [ 48 ] - } - }, - "1fac:0151": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "2001:00a6": { - "*": { - "t_vendor": 8193, - "t_product": [ 32002 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:00a7": { - "*": { - "t_vendor": 8193, - "t_product": [ 32014 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:7600": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "2001:98ff": { - "*": { - "t_vendor": 8193, - "t_product": [ 32278 ], - "msg": [ 49 ], - "response": true - } - }, - "2001:a401": { - "*": { - "t_vendor": 8193, - "t_product": [ 32281 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a403": { - "*": { - "t_vendor": 8193, - "t_product": [ 32011, 32012 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a405": { - "*": { - "t_vendor": 8193, - "t_product": [ 32013 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a406": { - "*": { - "t_vendor": 8193, - "t_product": [ 32281 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a407": { - "*": { - "t_vendor": 8193, - "t_product": [ 32014 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a40a": { - "*": { - "t_vendor": 8193, - "t_product": [ 32016 ], - "msg": [ 50 ] - } - }, - "2001:a40d": { - "*": { - "t_vendor": 8193, - "t_product": [ 32312 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a706": { - "*": { - "t_vendor": 8193, - "t_product": [ 32001 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a707": { - "*": { - "t_vendor": 8193, - "t_product": [ 32002 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a708": { - "*": { - "t_vendor": 8193, - "t_product": [ 32003 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a805": { - "*": { - "t_vendor": 8193, - "t_product": [ 32274 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a809": { - "*": { - "t_vendor": 8193, - "t_product": [ 30976 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:a80b": { - "*": { - "t_vendor": 8193, - "t_product": [ 32000 ], - "msg": [ 50 ], - "response": true - } - }, - "2001:ab00": { - "*": { - "t_vendor": 8193, - "t_product": [ 32309 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2001:ac01": { - "*": { - "t_vendor": 8193, - "t_product": [ 32317 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2015:0001": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "201e:1023": { - "*": { - "t_vendor": 8222, - "t_product": [ 4130 ], - "msg": [ 51, 52 ], - "response": true - } - }, - "201e:2009": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "2020:0002": { - "*": { - "t_vendor": 8224, - "t_product": [ 8192, 16384, 16400 ], - "msg": [ 53 ] - } - }, - "2020:f00e": { - "*": { - "t_vendor": 8224, - "t_product": [ 4101, 4104 ], - "mode": "StandardEject", - "msg": [ ], - "wait": 2 - } - }, - "2020:f00f": { - "*": { - "t_vendor": 8224, - "t_product": [ 4101 ], - "mode": "StandardEject", - "msg": [ ], - "wait": 2 - } - }, - "2077:1000": { - "*": { - "t_vendor": 8311, - "t_product": [ 28673, 28688, 28689 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2077:f000": { - "*": { - "t_vendor": 8311, - "t_product": [ 36864, 36962, 40960, 40963 ], - "mode": "StandardEject", - "msg": [ 54 ] - } - }, - "20a6:f00a": { - "*": { - "t_vendor": 8358, - "t_product": [ 4096 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "20a6:f00e": { - "*": { - "t_vendor": 8358, - "t_product": [ 4357 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "20b9:1682": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "21f5:1000": { - "*": { - "t_vendor": 8693, - "t_product": [ 8200 ], - "msg": [ 55 ] - } - }, - "21f5:3010": { - "*": { - "t_vendor": 8693, - "t_product": [ 4353 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2262:0001": { - "*": { - "t_vendor": 8802, - "t_product": [ 2 ], - "msg": [ 56 ] - } - }, - "22de:6801": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "22de:6802": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "22de:6803": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "22f4:0021": { - "*": { - "t_class": 255, - "mode": "StandardEject", - "msg": [ ] - } - }, - "230d:0001": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "230d:0003": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "230d:0007": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "230d:000b": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "230d:000c": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "230d:000d": { - "*": { - "msg": [ ], - "config": 3 - } - }, - "230d:0101": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "230d:0103": { - "*": { - "msg": [ ], - "config": 2 - } - }, - "2357:0200": { - "*": { - "t_vendor": 9047, - "t_product": [ 513 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "2357:f000": { - "*": { - "t_vendor": 9047, - "t_product": [ 36864 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "23a2:1010": { - "*": { - "t_vendor": 9122, - "t_product": [ 4660 ], - "msg": [ 57 ] - } - }, - "257a:a000": { - "*": { - "t_vendor": 9594, - "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "257a:b000": { - "*": { - "t_vendor": 9594, - "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "257a:c000": { - "*": { - "t_vendor": 9594, - "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "257a:d000": { - "*": { - "t_vendor": 9594, - "t_product": [ 5633, 5663, 5679, 9759, 9775, 13855, 13871 ], - "mode": "StandardEject", - "msg": [ ] - } - }, - "6000:1000": { - "*": { - "t_vendor": 1478, - "t_product": [ 24576 ], - "msg": [ 55 ] - } - }, - "8888:6500": { - "*": { - "t_vendor": 5848, - "t_product": [ 25907 ], - "msg": [ 58 ] - } - }, - "ed09:1021": { - "*": { - "t_vendor": 60681, - "t_product": [ 4112 ], - "mode": "StandardEject", - "msg": [ ] - } - } - } -} diff --git a/rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh b/rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh deleted file mode 100644 index 4356489..0000000 --- a/rooter/ext-rooter-basic/files/lib/netifd/proto/3x.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/sh -INCLUDE_ONLY=1 - -. ../netifd-proto.sh -. ./ppp.sh -init_proto "$@" - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - logger -t "Create PPP Connection" "$@" -} - -chcklog() { - OOX=$1 - CLOG=$(uci get modem.modeminfo$CURRMODEM.log) - if [ $CLOG = "1" ]; then - log "$OOX" - fi -} - -proto_3x_init_config() { - no_device=1 - available=1 - ppp_generic_init_config - proto_config_add_string "device" - proto_config_add_string "apn" - proto_config_add_string "service" - proto_config_add_string "pincode" - proto_config_add_string "dialnumber" -} - -proto_3x_setup() { - local interface="$1" - local chat - - if [ ! -f /tmp/bootend.file ]; then - return 0 - fi - - json_get_var device device - json_get_var apn apn - json_get_var service service - json_get_var pincode pincode - - CURRMODEM=$(uci get network.$interface.currmodem) - - uci set modem.modem$CURRMODEM.connected=0 - uci commit modem - jkillall getsignal$CURRMODEM - rm -f $ROOTER_LINK/getsignal$CURRMODEM - jkillall con_monitor$CURRMODEM - rm -f $ROOTER_LINK/con_monitor$CURRMODEM - - - - [ -e "$device" ] || { - proto_set_available "$interface" 0 - return 1 - } - - if [ $service = "umts" ]; then - idV=$(uci get modem.modem$CURRMODEM.idV) - if [ $idV = 12d1 ]; then - $ROOTER/gcom/gcom-locked "$device" "curc.gcom" "$CURRMODEM" - log "Unsolicited Responses Disabled" - fi - chat="/etc/chatscripts/3g.chat" - if [ -n "$pincode" ]; then - OX=$($ROOTER/gcom/gcom-locked "$device" "setpin.gcom" "$CURRMODEM") - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - log "Modem $CURRMODEM Failed to Unlock SIM Pin" - chcklog "$OX" - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Pin Locked" - proto_notify_error "$interface" PIN_FAILED - proto_block_restart "$interface" - return 1 - fi - fi - export SETUSER=$(uci get modem.modeminfo$CURRMODEM.user) - export SETPASS=$(uci get modem.modeminfo$CURRMODEM.pass) - export SETAUTH=$(uci get modem.modeminfo$CURRMODEM.auth) - OX=$($ROOTER/gcom/gcom-locked "$device" "connect-ppp.gcom" "$CURRMODEM") - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - log "Error for Modem $CURRMODEM on Authorization" - chcklog "$OX" - fi - - if [ -z "$dialnumber" ]; then - dialnumber="*99***1#" - fi - else - chat="/etc/chatscripts/evdo.chat" - fi - - connect="${apn:+USE_APN=$apn }DIALNUMBER=$dialnumber /usr/sbin/chat -t5 -v -E -f $chat" - - ppp_generic_setup "$interface" \ - noaccomp \ - nopcomp \ - novj \ - nobsdcomp \ - noauth \ - lock \ - crtscts \ - 115200 "$device" - - sleep 20 - MAN=$(uci get modem.modem$CURRMODEM.manuf) - MOD=$(uci get modem.modem$CURRMODEM.model) - $ROOTER/log/logger "Modem #$CURRMODEM Connected ($MAN $MOD)" - PROT=$(uci get modem.modem$CURRMODEM.proto) - if [ $service = "umts" ]; then - ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - fi - ln -s $ROOTER/connect/reconnect-ppp.sh $ROOTER_LINK/reconnect$CURRMODEM - ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM - $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & - uci set modem.modem$CURRMODEM.connected=1 - uci set modem.modem$CURRMODEM.interface="3x-"$interface - uci commit modem - CLB=$(uci get modem.modeminfo$CURRMODEM.lb) - if [ -e /etc/config/mwan3 ]; then - INTER=$(uci get modem.modeminfo$CURRMODEM.inter) - if [ -z $INTER ]; then - INTER=0 - else - if [ $INTER = 0 ]; then - INTER=$CURRMODEM - fi - fi - if [ -e $ROOTER/timezone.sh ]; then - TZ=$(uci get modem.modeminfo$CURRMODEM.tzone) - if [ $TZ = "1" ]; then - log "Set TimeZone" - $ROOTER/timezone.sh & - fi - fi - ENB=$(uci get mwan3.wan$CURRMODEM.enabled) - if [ ! -z $ENB ]; then - if [ $CLB = "1" ]; then - uci set mwan3.wan$INTER.enabled=1 - else - uci set mwan3.wan$INTER.enabled=0 - fi - uci commit mwan3 - /usr/sbin/mwan3 restart - fi - fi - rm -f /tmp/usbwait - return 0 -} - -proto_3x_teardown() { - proto_kill_command "$interface" -} - -add_protocol 3x diff --git a/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles b/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles deleted file mode 100644 index 16cdff4..0000000 --- a/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/cronfiles +++ /dev/null @@ -1,2 +0,0 @@ -/etc/cronuser -/etc/cronbase diff --git a/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local b/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local deleted file mode 100644 index b68cb69..0000000 --- a/rooter/ext-rooter-basic/files/lib/upgrade/keep.d/rc-local +++ /dev/null @@ -1,3 +0,0 @@ -/overlay/upper/etc/rc.local -/etc/rc.local -/usr/lib/scripts diff --git a/rooter/ext-rooter-basic/files/usr/bin/bmask128 b/rooter/ext-rooter-basic/files/usr/bin/bmask128 deleted file mode 100644 index bfd5bde..0000000 --- a/rooter/ext-rooter-basic/files/usr/bin/bmask128 +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# -printf "Band 128-bit bandmask\n" -LBAND=1 -BBAND=1 -while [ $LBAND -le 48 ] -do - printf "%-6s%016X%016X\n" "$LBAND" "0" "$BBAND" - LBAND=$(( $LBAND + 1 )) - BBAND=$(( $BBAND * 2 )) -done -LBAND=65 -BBAND=1 -while [ $LBAND -le 85 ] -do - printf "%-6s%016X%016X\n" "$LBAND" "$BBAND" "0" - LBAND=$(( $LBAND + 1 )) - BBAND=$(( $BBAND * 2 )) -done diff --git a/rooter/ext-rooter-basic/files/usr/bin/chan2band.sh b/rooter/ext-rooter-basic/files/usr/bin/chan2band.sh deleted file mode 100644 index 5b5bff0..0000000 --- a/rooter/ext-rooter-basic/files/usr/bin/chan2band.sh +++ /dev/null @@ -1,317 +0,0 @@ -#!/bin/sh -CHAN=$1 -CHAN=$(echo "$CHAN" | grep -o "[0-9]*") - -decode_lte() { - if [ $CHAN -lt 600 ]; then - BAND="B1" - elif [ $CHAN -lt 1200 ]; then - BAND="B2" - elif [ $CHAN -lt 1950 ]; then - BAND="B3" - elif [ $CHAN -lt 2400 ]; then - BAND="B4" - elif [ $CHAN -lt 2650 ]; then - BAND="B5" - elif [ $CHAN -lt 2750 ]; then - BAND="B6" - elif [ $CHAN -lt 3450 ]; then - BAND="B7" - elif [ $CHAN -lt 3800 ]; then - BAND="B8" - elif [ $CHAN -lt 4150 ]; then - BAND="B9" - elif [ $CHAN -lt 4750 ]; then - BAND="B10" - elif [ $CHAN -lt 4950 ]; then - BAND="B11" - elif [ $CHAN -lt 5010 ]; then - BAND="-" - elif [ $CHAN -lt 5180 ]; then - BAND="B12" - elif [ $CHAN -lt 5280 ]; then - BAND="B13" - elif [ $CHAN -lt 5380 ]; then - BAND="B14" - elif [ $CHAN -lt 5730 ]; then - BAND="-" - elif [ $CHAN -lt 5850 ]; then - BAND="B17" - elif [ $CHAN -lt 6000 ]; then - BAND="B18" - elif [ $CHAN -lt 6150 ]; then - BAND="B19" - elif [ $CHAN -lt 6450 ]; then - BAND="B20" - elif [ $CHAN -lt 6600 ]; then - BAND="B21" - elif [ $CHAN -lt 7400 ]; then - BAND="B22" - elif [ $CHAN -lt 7500 ]; then - BAND="-" - elif [ $CHAN -lt 7700 ]; then - BAND="B23" - elif [ $CHAN -lt 8040 ]; then - BAND="B24" - elif [ $CHAN -lt 8690 ]; then - BAND="B25" - elif [ $CHAN -lt 9040 ]; then - BAND="B26" - elif [ $CHAN -lt 9210 ]; then - BAND="B27" - elif [ $CHAN -lt 9660 ]; then - BAND="B28" - elif [ $CHAN -lt 9770 ]; then - BAND="B29" - elif [ $CHAN -lt 9870 ]; then - BAND="B30" - elif [ $CHAN -lt 9920 ]; then - BAND="B31" - elif [ $CHAN -lt 10400 ]; then - BAND="B32" - elif [ $CHAN -lt 36000 ]; then - BAND="-" - elif [ $CHAN -lt 36200 ]; then - BAND="B33" - elif [ $CHAN -lt 36350 ]; then - BAND="B34" - elif [ $CHAN -lt 36950 ]; then - BAND="B35" - elif [ $CHAN -lt 37550 ]; then - BAND="B36" - elif [ $CHAN -lt 37750 ]; then - BAND="B37" - elif [ $CHAN -lt 38250 ]; then - BAND="B38" - elif [ $CHAN -lt 38650 ]; then - BAND="B39" - elif [ $CHAN -lt 39650 ]; then - BAND="B40" - elif [ $CHAN -lt 41590 ]; then - BAND="B41" - elif [ $CHAN -lt 43590 ]; then - BAND="B42" - elif [ $CHAN -lt 45590 ]; then - BAND="B43" - elif [ $CHAN -lt 46590 ]; then - BAND="B44" - elif [ $CHAN -lt 46790 ]; then - BAND="B45" - elif [ $CHAN -lt 54540 ]; then - BAND="B46" - elif [ $CHAN -lt 55240 ]; then - BAND="B47" - elif [ $CHAN -lt 56740 ]; then - BAND="B48" - elif [ $CHAN -lt 58240 ]; then - BAND="B49" - elif [ $CHAN -lt 59090 ]; then - BAND="B50" - elif [ $CHAN -lt 59140 ]; then - BAND="B51" - elif [ $CHAN -lt 60140 ]; then - BAND="B52" - elif [ $CHAN -lt 60255 ]; then - BAND="B53" - elif [ $CHAN -lt 65536 ]; then - BAND="-" - elif [ $CHAN -lt 66436 ]; then - BAND="B65" - elif [ $CHAN -lt 67336 ]; then - BAND="B66" - elif [ $CHAN -lt 67536 ]; then - BAND="B67" - elif [ $CHAN -lt 67836 ]; then - BAND="B68" - elif [ $CHAN -lt 68336 ]; then - BAND="B69" - elif [ $CHAN -lt 68586 ]; then - BAND="B70" - elif [ $CHAN -lt 68936 ]; then - BAND="B71" - elif [ $CHAN -lt 68986 ]; then - BAND="B72" - elif [ $CHAN -lt 69036 ]; then - BAND="B73" - elif [ $CHAN -lt 69466 ]; then - BAND="B74" - elif [ $CHAN -lt 70316 ]; then - BAND="B75" - elif [ $CHAN -lt 70366 ]; then - BAND="B76" - elif [ $CHAN -lt 70546 ]; then - BAND="B85" - elif [ $CHAN -lt 70596 ]; then - BAND="B87" - elif [ $CHAN -lt 70646 ]; then - BAND="B88" - else - BAND="-" - fi -} - -decode_nr5g() { - if [ $CHAN -lt 123400 ]; then - BAND="-" - elif [ $CHAN -le 130400 ]; then - BAND="n71" - elif [ $CHAN -lt 143400 ]; then - BAND="-" - elif [ $CHAN -lt 145600 ]; then - BAND="n29" - elif [ $CHAN -eq 145600 ]; then - BAND="n29|n85" - elif [ $CHAN -lt 145800 ]; then - BAND="n85" - elif [ $CHAN -eq 145800 ]; then - BAND="n12|n85" - elif [ $CHAN -lt 147600 ]; then - BAND="n12|n85" - elif [ $CHAN -lt 149200 ]; then - BAND="n12|n67|n85" - elif [ $CHAN -eq 149200 ]; then - BAND="n12|n13|n67|n85" - elif [ $CHAN -le 151200 ]; then - BAND="n13|n67" - elif [ $CHAN -lt 151600 ]; then - BAND="n67" - elif [ $CHAN -eq 151600 ]; then - BAND="n14|n28|n67" - elif [ $CHAN -le 153600 ]; then - BAND="n14|n28" - elif [ $CHAN -lt 158200 ]; then - BAND="n28" - elif [ $CHAN -eq 158200 ]; then - BAND="n14|n20|n28" - elif [ $CHAN -le 160600 ]; then - BAND="n20|n28" - elif [ $CHAN -le 164200 ]; then - BAND="n20" - elif [ $CHAN -lt 171800 ]; then - BAND="-" - elif [ $CHAN -lt 172000 ]; then - BAND="n26" - elif [ $CHAN -lt 173800 ]; then - BAND="n18|n26" - elif [ $CHAN -le 175000 ]; then - BAND="n5|n18|n26" - elif [ $CHAN -le 178800 ]; then - BAND="n5|n26" - elif [ $CHAN -lt 185000 ]; then - BAND="-" - elif [ $CHAN -le 192000 ]; then - BAND="n8" - elif [ $CHAN -lt 285400 ]; then - BAND="-" - elif [ $CHAN -lt 286400 ]; then - BAND="n51|n76|n91|n93" - elif [ $CHAN -eq 286400 ]; then - BAND="n50|n51|n75|n76|n91|92|n93|94" - elif [ $CHAN -lt 295000 ]; then - BAND="n50|n75|n92|n94" - elif [ $CHAN -eq 295000 ]; then - BAND="n50|n74|n75|n92|n94" - elif [ $CHAN -le 303400 ]; then - BAND="n50|n74|n75|n92|n94" - elif [ $CHAN -le 303600 ]; then - BAND="n74" - elif [ $CHAN -lt 305000 ]; then - BAND="-" - elif [ $CHAN -le 311800 ]; then - BAND="n24" - elif [ $CHAN -lt 361000 ]; then - BAND="-" - elif [ $CHAN -lt 376000 ]; then - BAND="n3" - elif [ $CHAN -eq 376000 ]; then - BAND="n3|n39" - elif [ $CHAN -le 384000 ]; then - BAND="n39" - elif [ $CHAN -lt 386000 ]; then - BAND="-" - elif [ $CHAN -le 398000 ]; then - BAND="n2|n25" - elif [ $CHAN -lt 399000 ]; then - BAND="n25" - elif [ $CHAN -eq 399000 ]; then - BAND="n25|n70" - elif [ $CHAN -lt 402000 ]; then - BAND="n70" - elif [ $CHAN -eq 402000 ]; then - BAND="n34|n70" - elif [ $CHAN -le 404000 ]; then - BAND="n34|n70" - elif [ $CHAN -le 405000 ]; then - BAND="n34" - elif [ $CHAN -lt 422000 ]; then - BAND="-" - elif [ $CHAN -le 434000 ]; then - BAND="n1|n65|n66" - elif [ $CHAN -le 440000 ]; then - BAND="n65|n66" - elif [ $CHAN -lt 460000 ]; then - BAND="-" - elif [ $CHAN -lt 470000 ]; then - BAND="n40" - elif [ $CHAN -eq 470000 ]; then - BAND="n30|n40" - elif [ $CHAN -le 472000 ]; then - BAND="n30|n40" - elif [ $CHAN -le 480000 ]; then - BAND="n40" - elif [ $CHAN -lt 496700 ]; then - BAND="-" - elif [ $CHAN -le 499000 ]; then - BAND="n53" - elif [ $CHAN -lt 499200 ]; then - BAND="-" - elif [ $CHAN -lt 514000 ]; then - BAND="n41|n90" - elif [ $CHAN -eq 514000 ]; then - BAND="n38|n41|n90" - elif [ $CHAN -lt 524000 ]; then - BAND="n38|n41|n90" - elif [ $CHAN -eq 524000 ]; then - BAND="n7|n38|n41|n90" - elif [ $CHAN -lt 538000 ]; then - BAND="n7|n41|n90" - elif [ $CHAN -eq 538000 ]; then - BAND="n7|n90" - elif [ $CHAN -lt 620000 ]; then - BAND="-" - elif [ $CHAN -lt 636667 ]; then - BAND="n77|n78" - elif [ $CHAN -le 646666 ]; then - BAND="n48|n77|n78" - elif [ $CHAN -le 653333 ]; then - BAND="n77|n78" - elif [ $CHAN -le 680000 ]; then - BAND="n77" - elif [ $CHAN -lt 693334 ]; then - BAND="-" - elif [ $CHAN -le 733333 ]; then - BAND="n79" - elif [ $CHAN -lt 743333 ]; then - BAND="-" - elif [ $CHAN -lt 795000 ]; then - BAND="n46" - elif [ $CHAN -eq 795000 ]; then - BAND="n46|n96" - elif [ $CHAN -le 875000 ]; then - BAND="n96" - else - BAND="-" - fi -} - -if [ -z "$CHAN" ]; then - BAND="-" -elif [ "$CHAN" -lt 123400 ]; then - decode_lte -elif [ "$CHAN" -le 875000 ]; then - decode_nr5g -else - BAND="-" -fi -echo $BAND -exit diff --git a/rooter/ext-rooter-basic/files/usr/bin/encodemask b/rooter/ext-rooter-basic/files/usr/bin/encodemask deleted file mode 100644 index 6b3ed14..0000000 --- a/rooter/ext-rooter-basic/files/usr/bin/encodemask +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/lua - -mtab = {} -vtab = {1, 2, 4, 8} - -for i = 1, 32 do - mtab[i] = 0 -end - -numarg = #arg -for argval = 1, numarg do - band = arg[argval] - if tonumber(band) <= 128 then - idx = math.floor((band - 1) / 4) + 1 - idxr = 33 - idx - val = vtab[(band - ((idx - 1) * 4 ))] - mtab[idxr] = mtab[idxr] + val - end -end -for i = 1, 32 do - mtab[i] = string.format("%X", mtab[i]) -end - -print(table.concat(mtab)) diff --git a/rooter/ext-rooter-basic/files/usr/bin/jkillall b/rooter/ext-rooter-basic/files/usr/bin/jkillall deleted file mode 100644 index 3802082..0000000 --- a/rooter/ext-rooter-basic/files/usr/bin/jkillall +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -LOOKFOR=$1 -KILLLIST=$(ps | grep $LOOKFOR) -echo "$KILLLIST" | while read line; do - if `echo "$line" | grep "/$LOOKFOR" > /dev/null` ; then - PIDV=$(echo $line | grep -o "^[0-9]\{1,5\}" | grep -o "[0-9]\{1,5\}") - kill $PIDV - fi -done \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi b/rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi deleted file mode 100644 index 06ad5b6..0000000 --- a/rooter/ext-rooter-basic/files/usr/bin/rsrp2rssi +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/lua - -rsrp = tonumber(arg[1]) -bw = tonumber(arg[2]) -if bw == 1.4 then - n = 6 -else - n = bw * 5 -end - -if tonumber(string.match(_VERSION, "%d+%.%d")) > 5.1 then - rssi = rsrp + (10 * math.log(n * 12, 10)) -else - rssi = rsrp + (10 * math.log10(n * 12)) -end -if rssi < -113 then - rssi = -113 -elseif rssi > -51 then - rssi = -51 -end -print(math.floor(rssi)) diff --git a/rooter/ext-rooter-basic/files/usr/bin/set_gpio b/rooter/ext-rooter-basic/files/usr/bin/set_gpio deleted file mode 100644 index 5fddfa7..0000000 --- a/rooter/ext-rooter-basic/files/usr/bin/set_gpio +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -PIN=$1 -VALUE=$2 - -PIN_FILE=/sys/class/gpio/gpio$PIN - -if [ -z "$PIN" -o -z "$VALUE" ]; then - exit 1 -fi - -echo $PIN >/sys/class/gpio/export - -if [ $(cat $PIN_FILE/direction) = "out" ]; then - echo $VALUE >$PIN_FILE/value -fi - -echo $PIN >/sys/class/gpio/unexport \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh b/rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh deleted file mode 100644 index e0dc4f9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/custom/locktype.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -CURRMODEM=$1 - -uVid=$(uci get modem.modem$CURRMODEM.uVid) -uPid=$(uci get modem.modem$CURRMODEM.uPid) - -if [ $uVid == "2c7c" ]; then - qc=$(uci get custom.atcmd.quectel) - echo "$qc" > /tmp/modemlock - echo " " >> /tmp/modemlock -else - if [ $uVid == "1199" ]; then - qc=$(uci get custom.atcmd.sierra) - echo "$qc" > /tmp/modemlock - echo " " >> /tmp/modemlock - else - qc=$(uci get custom.atcmd.generic) - echo "$qc" > /tmp/modemlock - echo " " >> /tmp/modemlock - fi -fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh b/rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh deleted file mode 100644 index 79e52bd..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/custom/ttlx.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -log() { - logger -t "TTL Hack" "$@" -} - -cp -f /etc/firewall.user /etc/firewall.user.bk -sed /"#startTTL"/,/"#endTTL"/d /etc/firewall.user.bk > /etc/firewall.user -rm -f /etc/firewall.user.bk -/etc/init.d/firewall restart 2> /dev/null - diff --git a/rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh b/rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh deleted file mode 100644 index 9ca9af7..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/gps/smsreply.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "GPS" "$@" -} - -CURRMODEM=$1 -SMSdest=$2 -MODTYPE=$(uci -q get modem.modem$CURRMODEM.modemtype) -if [ "$MODTYPE" == "2" -o "$MODTYPE" == "6" ]; then - COMMPORT="/dev/ttyUSB"$(uci -q get modem.modem$CURRMODEM.commport) -else - log "SMS position request from $SMSdest failed, modem $CURRMODEM is neither a Sierra nor Quectel" - exit -fi -GPSon=$(uci -q get gps.configuration.enabled) -if [ "$GPSon" != "1" -o $CURRMODEM == "2" ]; then - GPSon="0" - if [ $MODTYPE == "2" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT!CUSTOM?") - GPSsel=$(echo $OX | grep "GPSSEL") - GPSenable=$(echo $OX | grep "GPSENABLE") - if [ -z "$GPSsel" -o -z "$GPSenable" ]; then - ATCMDD="AT!ENTERCND=\"A710\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if [ -z "$GPSsel" ]; then - ATCMDD="at!custom=\"GPSSEL\",1" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - if [ -z "$GPSenable" ]; then - ATCMDD="at!custom=\"GPSENABLE\",1" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD="AT+CFUN=0;+CFUN=1,1" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - sleep 30 - fi - ATCMDD="AT!ENTERCND=\"AWRONG\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT!GPSTRACK=1,240,30,1000,5") - GPSendcmd="AT!GPSEND=0" - else - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+QGPS?") - err=$(echo "$OX" | grep "+QGPS: 1") - if [ -z "$err" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+QGPS=1") - fi - ATCMDD="AT+QCFG=\"gpsdrx\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - err=$(echo "$OX" | grep "0") - if [ -n "$err" ]; then - ATCMDD="AT+QCFG=\"gpsdrx\",1" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - GPSendcmd="AT+QGPSEND" - fi -fi -SMStime=$(($(date +%s) + 120)) -LAT="" -LON="" -while true; do - if [ $MODTYPE == "2" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT!GPSLOC?") - LATx=$(echo $OX | grep -o "Lat:[^(]\+([^)]\+" | grep -o "0x.\+") - LONx=$(echo $OX | grep -o "Lon:[^(]\+([^)]\+" | grep -o "0x.\+") - if [ -n "$LATx" -a -n "$LONx" ]; then - if [ $(printf "%d" $LATx) -gt $(printf "%d" 0x7FFFFFFF) ]; then - LATx=$(( ($LATx ^ 0xFFFFFFFF) + 1 )) - LAT="-"$(lua -e "print(string.format(\"%.5f\", $LATx * (180 / 2^25)))") - else - LAT=$(lua -e "print(string.format(\"%.5f\", $LATx * (180 / 2^25)))") - fi - if [ $(printf "%d" $LONx) -gt $(printf "%d" 0x7FFFFFFF) ]; then - LONx=$(( ($LONx ^ 0xFFFFFFFF) + 1 )) - LON="-"$(lua -e "print(string.format(\"%.5f\", $LONx * (180 / 2^25)))") - else - LON=$(lua -e "print(string.format(\"%.5f\", $LONx * (180 / 2^25)))") - fi - fi - else - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+QGPSLOC=2") - LAT=$(echo $OX | grep -o "+QGPSLOC:[ .0-9]\+,.\+" | cut -d, -f2) - LON=$(echo $OX | grep -o "+QGPSLOC:[ .0-9]\+,.\+" | cut -d, -f3) - fi - if [ -n "$LAT" -a -n "$LON" ]; then - SMSMODEM=$(uci -q get modem.general.smsnum) - if [ "$CURRMODEM" != "$SMSMODEM" ]; then - uci set modem.general.smsnum=$CURRMODEM - uci commit modem.general.smsnum - fi - OY=$(/usr/lib/sms/smsout.sh "$SMSdest" "$LAT $LON") - OYsent=$(echo $OY | grep -o "SMS sent") - if [ -n "$OYsent" ]; then - /usr/lib/sms/sys2sms.sh "ROOter" "GPS coordinates sent to $SMSdest" - log "GPS coordinates sent to $SMSdest" - else - log "Failed to send GPS coordinates sent to $SMSdest" - fi - if [ "$CURRMODEM" != "$SMSMODEM" ]; then - uci set modem.general.smsnum=$SMSMODEM - uci commit modem.general.smsnum - fi - break - fi - if [ $(date +%s) -gt $SMStime ]; then - log "Failed request from $SMSdest by SMS for LAT/LON, position not available" - break - fi - sleep 8 -done -if [ "$GPSon" != "1" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$GPSendcmd") -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua deleted file mode 100644 index 9c0d896..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/admin/modem.lua +++ /dev/null @@ -1,664 +0,0 @@ -module("luci.controller.admin.modem", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - entry({"admin", "modem"}, firstchild(), translate("移动数据"), 25).dependent=false - entry({"admin", "modem", "prof"}, cbi("rooter/profiles"), translate("DNS / APN / 监控配置"), 2) - entry({"admin", "modem", "nets"}, template("rooter/net_status"), translate("信号状态 / 模块状态"), 30) - entry({"admin", "modem", "debug"}, template("rooter/debug"), translate("后台AT调试信息"), 50) - entry({"admin", "modem", "cust"}, cbi("rooter/customize"), translate("自定义模块端口配置"), 55) - entry({"admin", "modem", "log"}, template("rooter/log"), translate("连接日志"), 60) - entry({"admin", "modem", "misc"}, template("rooter/misc"), translate("锁频段 / 锁PCI / 切协议"), 40) - - entry({"admin", "modem", "block"}, - template("rooter/bandlock")) - - - entry({"admin", "modem", "get_csq"}, call("action_get_csq")) - entry({"admin", "modem", "change_port"}, call("action_change_port")) - entry({"admin", "modem", "change_mode"}, call("action_change_mode")) - entry({"admin", "modem", "change_modem"}, call("action_change_modem")) - entry({"admin", "modem", "change_modemdn"}, call("action_change_modemdn")) - entry({"admin", "modem", "change_misc"}, call("action_change_misc")) - entry({"admin", "modem", "change_miscdn"}, call("action_change_miscdn")) - entry({"admin", "modem", "get_log"}, call("action_get_log")) - entry({"admin", "modem", "check_misc"}, call("action_check_misc")) - entry({"admin", "modem", "pwrtoggle"}, call("action_pwrtoggle")) - entry({"admin", "modem", "disconnect"}, call("action_disconnect")) - entry({"admin", "modem", "connect"}, call("action_connect")) - entry({"admin", "modem", "get_atlog"}, call("action_get_atlog")) - entry({"admin", "modem", "send_atcmd"}, call("action_send_atcmd")) - entry({"admin", "modem", "change_rate"}, call("action_change_rate")) - entry({"admin", "modem", "change_phone"}, call("action_change_phone")) - entry({"admin", "modem", "clear_log"}, call("action_clear_log")) - entry({"admin", "modem", "externalip"}, call("action_externalip")) - entry({"admin", "modem", "send_scancmd"}, call("action_send_scancmd")) - entry({"admin", "modem", "send_lockcmd"}, call("action_send_lockcmd")) - entry({"admin", "modem", "extping"}, call("action_extping")) - entry({"admin", "modem", "change_cell"}, call("action_change_cell")) - entry({"admin", "modem", "change_proto"}, call("action_change_proto")) - entry({"admin", "modem", "setpin"}, call("action_setpin")) -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function action_get_atlog() - local file - local rv ={} - - file = io.open("/tmp/atlog", "r") - if file ~= nil then - local tmp = file:read("*all") - rv["log"] = tmp - file:close() - else - rv["log"] = "No entries in log file" - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_get_log() - local file - local rv ={} - - file = io.open("/usr/lib/rooter/log/connect.log", "r") - if file ~= nil then - local tmp = file:read("*all") - rv["log"] = tmp - file:close() - else - rv["log"] = translate("No entries in log file") - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_disconnect() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/rooter/connect/disconnect.sh") -end - -function action_connect() - local set = luci.http.formvalue("set") - miscnum = luci.model.uci.cursor():get("modem", "general", "miscnum") - os.execute("/tmp/links/reconnect" .. miscnum .. " " .. miscnum) -end - -function action_pwrtoggle() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/rooter/pwrtoggle.sh " .. set) -end - -function action_send_atcmd() - local rv ={} - modnum = luci.model.uci.cursor():get("modem", "general", "miscnum") - local file - local set = luci.http.formvalue("set") - fixed = string.gsub(set, "\"", "~") - os.execute("/usr/lib/rooter/luci/atcmd.sh \'" .. fixed .. "\'") - - result = "/tmp/result" .. modnum .. ".at" - file = io.open(result, "r") - if file ~= nil then - rv["result"] = file:read("*all") - file:close() - os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/result" .. modnum .. ".at") - else - rv["result"] = " " - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_check_misc() - local rv ={} - local bnd1 = {} - local bnd2 = {} - local bnd31 = {} - local bnd32 = {} - local bnd33 = {} - local at1 = {} - local at2 = {} - local file - local file1 - local active - local connect - - miscnum = luci.model.uci.cursor():get("modem", "general", "miscnum") - conn = "Modem #" .. miscnum - rv["conntype"] = conn - empty = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "empty") - if empty == "1" then - active = "0" - rv["netmode"] = "-" - else - active = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "active") - if active == "1" then - connect = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "connected") - if connect == "0" then - active = "1" - else - active = "2" - end - uVid = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "uVid") - rv["uVid"] = uVid - uPid = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "uPid") - rv["uPid"] = uPid - file = io.open("/etc/fake", "r") - if file == nil then - rv["fake"] = "0" - else - rv["fake"] = "1" - file:close() - end - - rv["cenable"] = luci.model.uci.cursor():get("custom", "bandlock", "cenable" .. miscnum) - if rv["cenable"] == nil then - rv["cenable"] = "0" - end - rv["earfcn"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn" .. miscnum) - if rv["earfcn"] == nil then - rv["earfcn"] = "0" - end - rv["pci"] = luci.model.uci.cursor():get("custom", "bandlock", "pci" .. miscnum) - if rv["pci"] == nil then - rv["pci"] = "0" - end - - rv["earfcn1"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn1" .. miscnum) - if rv["earfcn1"] == nil then - rv["earfcn1"] = "0" - end - rv["pci1"] = luci.model.uci.cursor():get("custom", "bandlock", "pci1" .. miscnum) - if rv["pci1"] == nil then - rv["pci1"] = "0" - end - - rv["earfcn2"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn2" .. miscnum) - if rv["earfcn2"] == nil then - rv["earfcn2"] = "0" - end - rv["pci2"] = luci.model.uci.cursor():get("custom", "bandlock", "pci2" .. miscnum) - if rv["pci2"] == nil then - rv["pci2"] = "0" - end - - rv["earfcn3"] = luci.model.uci.cursor():get("custom", "bandlock", "earfcn3" .. miscnum) - if rv["earfcn3"] == nil then - rv["earfcn3"] = "0" - end - rv["pci3"] = luci.model.uci.cursor():get("custom", "bandlock", "pci3" .. miscnum) - if rv["pci3"] == nil then - rv["pci3"] = "0" - end - - file = io.open("/tmp/bmask", "r") - if file == nil then - rv["bndstr"] = "0" - rv["bndsup"] = "0" - else - line = file:read("*line") - rv["bndstr"] = line - line = file:read("*line") - rv["bndstr5g"] = line - line = file:read("*line") - rv["bndstr5gsa"] = line - line = file:read("*line") - rv["bndsup"] = line - line = file:read("*line") - rv["bndsup5g"] = line - line = file:read("*line") - rv["bndsup5gsa"] = line - line = file:read("*line") - ca = line - if ca ~= nil then - line = file:read("*line") - ca3 = line - end - file:close() - - indx = 0 - if ca ~= nil then - file = io.open("/usr/lib/rooter/luci/" .. ca, "r") - if file ~= nil then - line = file:read("*line") - repeat - s, e = line:find(" ") - b1 = trim(line:sub(1, s-1)) - bnd1[indx] = b1 - b2 = trim(line:sub(s+1)) - bnd2[indx] = b2 - indx = indx +1 - line = file:read("*line") - until line == nil - file:close() - end - end - rv['b1'] = bnd1 - rv['b2'] = bnd2 - rv['indx'] = tostring(indx) - - indx3 = 0 - if ca3 ~= nil then - file = io.open("/usr/lib/rooter/luci/" .. ca3, "r") - if file ~= nil then - line = file:read("*line") - repeat - s, e = line:find(" ") - b1 = trim(line:sub(1, s-1)) - bnd31[indx3] = b1 - cs, ce = line:find(" ", s+1) - b2 = trim(line:sub(s+1, cs-1)) - bnd32[indx3] = b2 - b3 = trim(line:sub(cs+1)) - bnd33[indx3] = b3 - indx3 = indx3 +1 - line = file:read("*line") - until line == nil - file:close() - end - end - rv['b31'] = bnd31 - rv['b32'] = bnd32 - rv['b33'] = bnd33 - rv['indx3'] = tostring(indx3) - - end - end - netmode = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "netmode") - rv["netmode"] = netmode - end - rv["pin"] = luci.model.uci.cursor():get("modem", "general", "pin") - rv["plock"] = luci.model.uci.cursor():get("custom", "atcmd", "lock") - if rv["plock"] == "1" then - rv["atlock"] = luci.model.uci.cursor():get("custom", "menu", "full") - generic = luci.model.uci.cursor():get("custom", "atcmd", "generic") - aindx = 0 - if active == "0" then - file = io.open(generic, "r") - else - os.execute("/usr/lib/custom/locktype.sh " .. miscnum ) - file1 = io.open("/tmp/modemlock", "r") - if file1 ~= nil then - linex = file1:read("*line") - file1:close() - file = io.open(linex, "r") - else - file = io.open(generic, "r") - end - end - if file ~= nil then - line = file:read("*line") - repeat - at1[aindx] = line - line = file:read("*line") - at2[aindx] = line - aindx = aindx +1 - line = file:read("*line") - until line == nil - file:close() - rv['at1'] = at1 - rv['at2'] = at2 - rv['aindx'] = tostring(aindx) - end - end - rv["active"] = active - file = io.open("/tmp/gpiopin", "r") - if file == nil then - rv.gpio = "0" - else - rv.gpio = "1" - line = file:read("*line") - line = file:read("*line") - if line ~= nil then - rv.gpio = "2" - end - file:close() - end - file = io.open("/sys/bus/usb/drivers/usb/usb1", "r") - if file == nil then - rv["usb"] = "0" - else - io.close(file) - rv["usb"] = "1" - end - file = io.open("/sys/bus/usb/drivers/usb/usb2", "r") - if file ~= nill then - io.close(file) - rv["usb"] = "2" - end - proto = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "proto") - rv["proto"] = proto - - model = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "model") - rv["model"] = model - - celltype = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "celltype") - rv["celltype"] = celltype - cmode = luci.model.uci.cursor():get("modem", "modem" .. miscnum, "cmode") - if cmode == "0" then - rv["netmode"] = "10" - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function lshift(x, by) - return x * 2 ^ by -end - -function rshift(x, by) - return math.floor(x / 2 ^ by) -end - -function action_change_mode() - local set = tonumber(luci.http.formvalue("set")) - local modemtype = rshift(set, 4) - local temp = lshift(modemtype, 4) - local netmode = set - temp - os.execute("/usr/lib/rooter/luci/modechge.sh " .. modemtype .. " " .. netmode) -end - -function action_change_port() - local set = tonumber(luci.http.formvalue("set")) - if set ~= nil and set > 0 then - if set == 1 then - os.execute("/usr/lib/rooter/luci/portchge.sh dwn") - else - os.execute("/usr/lib/rooter/luci/portchge.sh up") - end - end -end - -function action_change_misc() - os.execute("/usr/lib/rooter/luci/modemchge.sh misc 1") -end - -function action_change_miscdn() - os.execute("/usr/lib/rooter/luci/modemchge.sh misc 0") -end - -function action_change_modem() - os.execute("/usr/lib/rooter/luci/modemchge.sh modem 1") -end - -function action_change_modemdn() - os.execute("/usr/lib/rooter/luci/modemchge.sh modem 0") -end - -function action_get_csq() - modnum = luci.model.uci.cursor():get("modem", "general", "modemnum") - local file - stat = "/tmp/status" .. modnum .. ".file" - file = io.open(stat, "r") - - local rv ={} - - rv["port"] = file:read("*line") - rv["csq"] = file:read("*line") - rv["per"] = file:read("*line") - rv["rssi"] = file:read("*line") - rv["modem"] = file:read("*line") - rv["cops"] = file:read("*line") - rv["mode"] = file:read("*line") - rv["lac"] = file:read("*line") - rv["lacn"] = file:read("*line") - rv["cid"] = file:read("*line") - rv["cidn"] = file:read("*line") - rv["mcc"] = file:read("*line") - rv["mnc"] = file:read("*line") - rv["rnc"] = file:read("*line") - rv["rncn"] = file:read("*line") - rv["down"] = file:read("*line") - rv["up"] = file:read("*line") - rv["ecio"] = file:read("*line") - rv["rscp"] = file:read("*line") - rv["ecio1"] = file:read("*line") - rv["rscp1"] = file:read("*line") - rv["netmode"] = file:read("*line") - rv["cell"] = file:read("*line") - rv["modtype"] = file:read("*line") - rv["conntype"] = file:read("*line") - rv["channel"] = file:read("*line") - rv["phone"] = file:read("*line") - file:read("*line") - rv["lband"] = file:read("*line") - rv["tempur"] = file:read("*line") - rv["proto"] = file:read("*line") - rv["pci"] = file:read("*line") - rv["sinr"] = file:read("*line") - --rv["lat"] = file:read("*line") - --rv["long"] = file:read("*line") - - file:close() - - cmode = luci.model.uci.cursor():get("modem", "modem" .. modnum, "cmode") - if cmode == "0" then - rv["netmode"] = "10" - end - - rssi = rv["rssi"] - ecio = rv["ecio"] - rscp = rv["rscp"] - ecio1 = rv["ecio1"] - rscp1 = rv["rscp1"] - - if ecio == nil then - ecio = "-" - end - if ecio1 == nil then - ecio1 = "-" - end - if rscp == nil then - rscp = "-" - end - if rscp1 == nil then - rscp1 = "-" - end - - if ecio ~= "-" then - rv["ecio"] = ecio .. " dB" - end - if rscp ~= "-" then - rv["rscp"] = rscp .. " dBm" - end - if ecio1 ~= " " then - rv["ecio1"] = " (" .. ecio1 .. " dB)" - end - if rscp1 ~= " " then - rv["rscp1"] = " (" .. rscp1 .. " dBm)" - end - - if not nixio.fs.access("/etc/netspeed") then - rv["crate"] = translate("快速(每10秒更新一次)") - else - rv["crate"] = translate("缓慢(每60秒更新一次)") - end - - stat = "/tmp/msimdata" .. modnum - file = io.open(stat, "r") - if file == nil then - rv["modid"] = " " - rv["imei"] = " " - rv["imsi"] = " " - rv["iccid"] = " " - rv["host"] = "0" - else - rv["modid"] = file:read("*line") - rv["imei"] = file:read("*line") - rv["imsi"] = file:read("*line") - rv["iccid"] = file:read("*line") - rv["host"] = file:read("*line") - file:close() - end - - gpsdata = "/tmp/gpsdata1" - file = io.open(gpsdata, "r") - if file == nil then - rv["lat"] = "-" - rv["long"] = "-" - else - rv["lat"] = file:read("*line") - rv["long"] = file:read("*line") - file:close() - end - - stat = "/tmp/msimnum" .. modnum - file = io.open(stat, "r") - if file == nil then - rv["phone"] = "-" - rv["phonen"] = " " - else - rv["phone"] = file:read("*line") - rv["phonen"] = file:read("*line") - file:close() - end - - stat = "/tmp/simpin" .. modnum - file = io.open(stat, "r") - if file == nil then - rv["simerr"] = "0" - else - typ = file:read("*line") - if typ == "0" then - rv["simerr"] = "1" - else - if typ == "1" then - rv["simerr"] = "2" - else - if typ == "2" then - rv["simerr"] = "3" - else - rv["simerr"] = "4" - end - end - end - file:close() - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_change_rate() - local set = luci.http.formvalue("set") - if set == "1" then - os.execute("rm -f /etc/netspeed") - else - os.execute("echo \"0\" > /etc/netspeed") - end -end - -function action_change_phone() - local set = luci.http.formvalue("set") - s, e = string.find(set, "|") - pno = string.sub(set, 1, s-1) - pnon = string.sub(set, e+1) - modnum = luci.model.uci.cursor():get("modem", "general", "modemnum") - os.execute("/usr/lib/rooter/common/phone.sh " .. modnum .. " " .. pno .. " \"" .. pnon .. "\"") -end - -function action_clear_log() - local file - file = io.open("/usr/lib/rooter/log/connect.log", "w") - file:close() - os.execute("/usr/lib/rooter/log/logger 'Connection Log Cleared by User'") -end - -function action_externalip() - local rv ={} - - os.execute("rm -f /tmp/ipip; wget -O /tmp/ipip http://ipecho.net/plain > /dev/null 2>&1") - file = io.open("/tmp/ipip", "r") - if file == nil then - rv["extip"] = translate("Not Available") - else - rv["extip"] = file:read("*line") - if rv["extip"] == nil then - rv["extip"] = translate("Not Available") - end - file:close() - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_send_scancmd() - local rv ={} - local file - os.execute("/usr/lib/rooter/luci/scancmd.sh") - - result = "/tmp/scan" - file = io.open(result, "r") - if file ~= nil then - rv["result"] = file:read("*all") - file:close() - os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/scan") - else - rv["result"] = " " - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_send_lockcmd() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/rooter/luci/lock.sh " .. set) -end - -function action_extping() - local rv ={} - - enable = luci.model.uci.cursor():get("ping", "ping", "enable") - if enable == "0" then - rv["extping"] = translate("Not Enabled") - else - conn = luci.model.uci.cursor():get("ping", "ping", "conn") - if conn == "1" then - rv["extping"] = translate("Enabled, Waiting for Modem to Connect") - else - if conn == "2" then - rv["extping"] = translate("Enabled, Ping Test was Good") - else - if conn == "3" then - rv["extping"] = translate("Enabled, Ping Test Failed, Restarting Modem, Waiting for Reconnection") - else - if conn == "4" then - rv["extping"] = translate("Enabled, Connected, Waiting for Ping Test") - else - rv["extping"] = translate("Enabled, Unknown State") - end - end - end - end - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end - -function action_change_cell() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/rooter/luci/setcell.sh " .. "\"" .. set .. "\"") -end - -function action_change_proto() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/rooter/luci/protochnge.sh " ..set) -end - -function action_setpin() - local set = luci.http.formvalue("set") - os.execute("uci set modem.general.pin=" .. set .. "; uci commit modem") -end diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua deleted file mode 100644 index b37f797..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/modlog.lua +++ /dev/null @@ -1,29 +0,0 @@ -module("luci.controller.modlog", package.seeall) - -I18N = require "luci.i18n" -translate = I18N.translate - -function index() - local page - page = entry({"admin", "modem", "modlog"}, template("modlog/modlog"), _(translate("模块连接日志信息")), 61) - page.dependent = true - - entry({"admin", "status", "modlog"}, call("action_modlog")) -end - -function action_modlog() - local file - local rv ={} - - file = io.open("/tmp/modlog.log", "r") - if file ~= nil then - local tmp = file:read("*all") - rv["log"] = tmp - file:close() - else - rv["log"] = translate("No entries in log file") - end - - luci.http.prepare_content("application/json") - luci.http.write_json(rv) -end diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua deleted file mode 100644 index 77531f7..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/poweroff.lua +++ /dev/null @@ -1,13 +0,0 @@ -module("luci.controller.poweroff", package.seeall) - -function index() - local page - page = entry({"admin", "system", "poweroff"}, template("admin_system/poweroff"), _("System Stop"), 95) - entry({"admin", "system", "do_poweroff"}, call("action_poweroff")) - page.dependent = true -end - -function action_poweroff() - local set = luci.http.formvalue("set") - os.execute("/usr/lib/rooter/shutall.sh") -end diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua deleted file mode 100644 index fce9b46..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/controller/profile.lua +++ /dev/null @@ -1,40 +0,0 @@ -module("luci.controller.profile", package.seeall) -function index() - entry({"admin", "profile", "savecfg"}, call("action_savecfg")) - entry({"admin", "profile", "loadcfg"}, call("action_loadcfg")) - entry({"admin", "profile", "loadcfg1"}, call("action_loadcfg1")) - entry({"admin", "profile", "loadcfg2"}, call("action_loadcfg2")) -end - -function action_savecfg() - os.execute('/usr/lib/profile/savecfg.sh') -end - -function action_loadcfg() - local set = luci.http.formvalue("set") - local set1 = luci.http.formvalue("set1") - local tfile = io.open("/tmp/profilename", "w") - tfile:write(set, "\n") - if set1 ~= "~~" then - tfile:write(set1, "\n") - end - tfile:close() - os.execute("/usr/lib/profile/loadcfg.sh") -end - -function action_loadcfg1() - local set = luci.http.formvalue("set") - local tfile = io.open("/tmp/profilename", "w") - tfile:write(set) - tfile:close() -end - -function action_loadcfg2() - local set1 = luci.http.formvalue("set1") - if set1 ~= "~~" then - local tfile = io.open("/tmp/profilename", "a") - tfile:write(set1) - tfile:close() - end - os.execute("/usr/lib/profile/loadcfg.sh") -end \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua deleted file mode 100644 index b6001f0..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/firewall/ttlx.lua +++ /dev/null @@ -1,30 +0,0 @@ -local utl = require "luci.util" -local uci = require "luci.model.uci".cursor() - -m = Map("ttl", "Firewall - Custom TTL Settings", - translate("Enable and use a custom TTL value with modems")) - -m.on_after_save = function(self) - --luci.sys.call("/usr/lib/custom/ttlx.sh &") -end - -gw = m:section(TypedSection, "ttl", translate("Settings")) -gw.anonymous = true - -en = gw:option(Flag, "enabled", translate("Enabled :"), translate("Enable the use of custom TTL value")); -en.default="0" -en.rmempty = false; -en.optional=false; - -val = gw:option(ListValue, "value", translate("TTL Value :"), translate("Custom TTL value to be used on modems")); -val.default="65" -val:depends("enabled", "1") -val:value("63", "63") -val:value("64", "64") -val:value("65", "65") -val:value("66", "66") -val:value("67", "67") -val:value("117", "117") -val:value("0", "TTL-INC 1") - -return m \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua deleted file mode 100644 index acc7eb5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/customize.lua +++ /dev/null @@ -1,156 +0,0 @@ -local utl = require "luci.util" - -local modemfile = "/etc/config/modem.data" -local modemdata = {} -local count -local tabdata = {} - -function process_line(xline, cnt) - local data = {} - local pline = xline - local start = 1 - for i=1,3 do - s, e = string.find(pline, " ") - data[i] = string.sub(pline, start, s-1) - pline = string.sub(pline, e+1) - end - data[4] = pline - modemdata[cnt] = data -end - -function read_modem() - count = 0 - local file = io.open(modemfile, "r") - if file == nil then - return - end - repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) < 5 then - break - end - count = count + 1 - process_line(line, count) - until 1==0 - file:close() -end - -function insert_modem() - local location = count + 1 - - if count > 0 then - for j=1,count do - local mdata = modemdata[j] - if mdata[1] == tabdata[1] and mdata[2] == tabdata[2] then - location = j - end - end - end - - if count == 0 then - count = 1 - else - if location > count then - count = count + 1 - end - end - modemdata[location] = tabdata -end - -function write_modem() - os.remove(modemfile) - local file = io.open(modemfile, "w") - for k=1,count do - local mdata = modemdata[k] - for l=1,3 do - file:write(mdata[l], " ") - end - file:write(mdata[4], "\n") - end - file:close() -end - -function process_tabdata() - if tabdata[1] ~= "nil" and tabdata[2] ~= "nil" then - read_modem() - insert_modem() - write_modem() - end -end - -m = Map("modem", translate("自定义4G/5G 模块支持"), translate(" 修改某个模块使用的通信端口")) - -m.on_after_commit = function(self) - -- all written config names are in self.parsechain - local sobj - for _, sobj in ipairs(self.children) do - local sids - if utl.instanceof(sobj, NamedSection) then - sids = { sobj.section } - elseif utl.instanceof(sobj, TypedSection) then - sids = sobj:cfgsections() - end - local sid, fld, fln - - if not utl.instanceof(sobj, SimpleSection) then - for _, sid in ipairs(sids) do - for fln, fld in ipairs(sobj.children) do - local val = fld:formvalue(sid) - if val == nil or string.len(val) == 0 then - val = "nil" - end - tabdata[fln] = val - end - end - end - end - process_tabdata() -end - --- --- Vid Pid Dataport Commport --- - -e = m:section(TypedSection, "new", translate("模块端口 :")) - -a1 = e:option(Value, "vid", translate("模块 VID:")); -a1.optional=false; - -b1 = e:option(Value, "pid", translate("模块 ID :")); -b1.optional=false; - -p3 = e:option(ListValue, "port", translate("PPP 拨号端口 :")) -p3:value("tty", "default") -p3:value("tty0", "/dev/ttyUSB0") -p3:value("tty1", "/dev/ttyUSB1") -p3:value("tty2", "/dev/ttyUSB2") -p3:value("tty3", "/dev/ttyUSB3") -p3:value("tty4", "/dev/ttyUSB4") -p3:value("tty5", "/dev/ttyUSB5") -p3.default = "tty" - -p4 = e:option(ListValue, "comm", translate("通讯端口 :")) -p4:value("tty", "default") -p4:value("tty0", "/dev/ttyUSB0") -p4:value("tty1", "/dev/ttyUSB1") -p4:value("tty2", "/dev/ttyUSB2") -p4:value("tty3", "/dev/ttyUSB3") -p4:value("tty4", "/dev/ttyUSB4") -p4:value("tty5", "/dev/ttyUSB5") -p4.default = "tty" - -b3 = e:option(DummyValue, "blank", " "); - -btn = e:option(Button, "_btn", translate(" ")) -btn.inputtitle = translate("删除模块端口配置") -btn.inputstyle = "apply" -function btn.write() - luci.sys.call("/usr/lib/rooter/luci/luaops.sh delete /etc/config/modem.data") -end - -m:section(SimpleSection).template = "rooter/custom" - -return m diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua deleted file mode 100644 index 89789eb..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/model/cbi/rooter/profiles.lua +++ /dev/null @@ -1,828 +0,0 @@ -local utl = require "luci.util" -local uci = require "luci.model.uci".cursor() -local sys = require "luci.sys" -local fs = require "nixio.fs" - -local maxmodem = luci.model.uci.cursor():get("modem", "general", "max") -local profsave = luci.model.uci.cursor():get("custom", "profile", "save") -if profsave == nil then - profsave ="0" -end -local multilock = luci.model.uci.cursor():get("custom", "multiuser", "multi") or "0" -local rootlock = luci.model.uci.cursor():get("custom", "multiuser", "root") or "0" - -m = Map("profile", translate("模块DNS / APN 配置"),translate("")) - -m.on_after_commit = function(self) - if profsave == "1" then - luci.sys.call("/usr/lib/profile/restart.sh &") - end -end - -if profsave == "1" then - m:section(SimpleSection).template = "rooter/profile" - ds = m:section(TypedSection, "simpin", translate("SIM卡Pin码 :"), translate("如果配置文件钟没有SIM PIN码则使用")) - ds.anonymous = true - - ms = ds:option(Value, "pin", translate("PIN :")); - ms.rmempty = true; - ms.default = "" -end - - --- --- Default profile --- - -di = m:section(TypedSection, "default", translate("默认"), translate("一般只需要填写您运营商的APN即可,一般已经自动加载识别了,奇葩虚拟运营商你也可以继续填 Tips:模块下次重连后生效,如果你要现在生效,请保存后重启模块)## 华为天际通5G SA APN:5gscuiot ##")) -di.anonymous = true -di:tab("default", translate("通用")) -di:tab("advance", translate("高级")) -di:tab("connect", translate("连接状态监控")) -if (multilock == "0") or (multilock == "1" and rootlock == "1") then - di:tab("bwidth", translate("Bandwidth Reporting频宽报告")) -end - -this_tab = "default" - -ma = di:taboption(this_tab, Value, "apn", "APN :"); -ma.rmempty = true; -ma.default = "broadband" - -tt = di:taboption(this_tab, ListValue, "ttl", translate("设定TTL值 :")) -tt:value("0", translate("使用当前值")) -tt:value("1", translate("不配置TTL值")) -tt:value("63", "TTL 63") -tt:value("64", "TTL 64") -tt:value("65", "TTL 65") -tt:value("66", "TTL 66") -tt:value("67", "TTL 67") -tt:value("117", "TTL 117") -tt:value("TTL-INC 1", "TTL-INC 1") -tt.default = "0" - -ynl = di:taboption(this_tab, ListValue, "hostless", translate("设定通信模块TTL")); -ynl:value("0", "否") -ynl:value("1", translate("是")) -ynl.default=0 - -pt = di:taboption(this_tab, ListValue, "pdptype", translate("IP协议类型 :")) -pt:value("IP", "IPv4") -pt:value("IPV6", "IPv6") -pt:value("IPV4V6", "IPv4+IPv6") -pt:value("0", "默认") -pt.default = "0" - -cmcc = di:taboption(this_tab, Value, "context", translate("PDP Context for APN :")); -cmcc.optional=false; -cmcc.rmempty = true; -cmcc.datatype = "and(uinteger,min(1),max(10))" -cmcc.default = "1" - -mu = di:taboption(this_tab, Value, "user", translate("用户名 :")); -mu.optional=false; -mu.rmempty = true; - -mp = di:taboption(this_tab, Value, "passw", translate("密码 :")); -mp.optional=false; -mp.rmempty = true; -mp.password = true - -mpi = di:taboption(this_tab, Value, "pincode", translate("PIN码 :")); -mpi.optional=false; -mpi.rmempty = true; - -mau = di:taboption(this_tab, ListValue, "auth", translate("身份验证类型 :")) -mau:value("0", "None") -mau:value("1", "PAP") -mau:value("2", "CHAP") -mau.default = "0" - -mtz = di:taboption(this_tab, ListValue, "tzone", translate("自动设置时区"), translate("Tips:就是模块通网后会自动设置时区")); -mtz:value("0", "窝不要") -mtz:value("1", translate("窝要")) -mtz.default=1 - -ml = di:taboption(this_tab, ListValue, "lock", translate("阻止国际漫游选项并锁定特定运营商 :")); -ml:value("0", translate("否")) -ml:value("1", translate("强硬")) -ml:value("2", translate("软弱")) -ml.default=0 - -mcc = di:taboption(this_tab, Value, "mcc", translate("MCC :")); -mcc.optional=false; -mcc.rmempty = true; -mcc.datatype = "and(uinteger,min(1),max(999))" -mcc:depends("lock", "1") -mcc:depends("lock", "2") - -mnc = di:taboption(this_tab, Value, "mnc", translate("MNC :")); -mnc.optional=false; -mnc.rmempty = true; -mnc.datatype = "and(uinteger,min(1),max(999))" -mnc:depends("lock", "1") -mnc:depends("lock", "2") - -this_taba = "advance" - -mf = di:taboption(this_taba, ListValue, "ppp", translate("不使用常规协议,强制使用PPP拨号协议 :")); -mf:value("0", translate("启用")) -mf:value("1", translate("禁用")) -mf.default=0 - -md = di:taboption(this_taba, Value, "delay", translate("连接延时(秒为单位) :")); -md.optional=false; -md.rmempty = false; -md.default = 5 -md.datatype = "and(uinteger,min(5))" - -nl = di:taboption(this_taba, ListValue, "nodhcp", translate("强制QMI协议不使用模块的DHCP,从其他位置获取 :")); -nl:value("0", translate("禁用")) -nl:value("1", translate("启用")) -nl.default=0 - -mdns1 = di:taboption(this_taba, Value, "dns1", translate("自定义DNS 1 :")); -mdns1.rmempty = true; -mdns1.optional=false; -mdns1.datatype = "ipaddr" - -mdns2 = di:taboption(this_taba, Value, "dns2", translate("自定义DNS 2 :")); -mdns2.rmempty = true; -mdns2.optional=false; -mdns2.datatype = "ipaddr" - -mdns3 = di:taboption(this_taba, Value, "dns3", translate("自定义DNS 3 :")); -mdns3.rmempty = true; -mdns3.optional=false; -mdns3.datatype = "ipaddr" - -mdns4 = di:taboption(this_taba, Value, "dns4", translate("自定义DNS 4 :")); -mdns4.rmempty = true; -mdns4.optional=false; -mdns4.datatype = "ipaddr" - - -mlog = di:taboption(this_taba, ListValue, "log", translate("启用AT连接日志 :")); -mlog:value("0", translate("禁用")) -mlog:value("1", translate("是")) -mlog.default=0 - -if nixio.fs.access("/etc/config/mwan3") then - mlb = di:taboption(this_taba, ListValue, "lb", translate("在多个5G模块中开启流量负载均衡 :")); - mlb:value("0", translate("禁用")) - mlb:value("1", translate("启用")) - mlb.default=0 -end - -mtu = di:taboption(this_taba, Value, "mtu", translate("自定义MTU值 :"), - translate("不建议乱整,只能自定义1420到1500的范围的值")); -mtu.optional=true -mtu.rmempty = true -mtu.default = "1500" -mtu.datatype = "range(1420, 1500)" - -mat = di:taboption(this_taba, ListValue, "at", translate("连接时发送自定义AT命令 :")); -mat:value("0", translate("禁用")) -mat:value("1", translate("启用")) -mat.default=0 - -matc = di:taboption(this_taba, Value, "atc", translate("要执行的AT命令 :")); -matc.optional=false; -matc.rmempty = true; - --- --- Default Connection Monitoring --- - -this_tab = "connect" - -alive = di:taboption(this_tab, ListValue, "alive", translate("连接状态监控 :")); -alive.rmempty = true; -alive:value("0", translate("禁用")) -alive:value("1", translate("启用掉线写入系统日志")) -alive:value("2", translate("启用 5G模块掉线 则 路由自动重启")) -alive:value("3", translate("启用 5G模块掉线 则 自动重拨")) -alive:value("4", translate("启用 5G模块掉线 则 重新上电模块,需要路由GPIO支持,否则将使用其他方式重连")) -alive.default=0 - -reliability = di:taboption(this_tab, Value, "reliability", translate("监测网络稳定性 :"), - translate("范围: 1-100,必须Ping通这些IP地址,这条通信链路才会被视为联网状态")) -reliability.datatype = "range(1, 100)" -reliability.default = "1" -reliability:depends("alive", "1") -reliability:depends("alive", "2") -reliability:depends("alive", "3") -reliability:depends("alive", "4") - -count = di:taboption(this_tab, ListValue, "count", translate("监测次数(Ping) :")) -count.default = "1" -count:value("1") -count:value("2") -count:value("3") -count:value("4") -count:value("5") -count:depends("alive", "1") -count:depends("alive", "2") -count:depends("alive", "3") -count:depends("alive", "4") - -interval = di:taboption(this_tab, ListValue, "pingtime", translate("监测时间间隔 (Ping) :"), - translate("监测Ping之间间隔时间的值")) -interval.default = "10" -interval:value("5", translate("5 秒/次")) -interval:value("10", translate("10 秒/次")) -interval:value("20", translate("20 秒/次 推荐")) -interval:value("30", translate("30 秒次")) -interval:value("60", translate("1 分钟/次 ")) -interval:value("300", translate("5 分钟/次")) -interval:value("600", translate("10 分钟/次")) -interval:value("900", translate("15 分钟/次")) -interval:value("1800", translate("30 分钟/次")) -interval:value("3600", translate("1 小时/次")) -interval:depends("alive", "1") -interval:depends("alive", "2") -interval:depends("alive", "3") -interval:depends("alive", "4") - -timeout = di:taboption(this_tab, ListValue, "pingwait", translate("Ping 超时 :")) -timeout.default = "2" -timeout:value("1", translate("1 秒")) -timeout:value("2", translate("2 秒")) -timeout:value("3", translate("3 秒")) -timeout:value("4", translate("4 秒")) -timeout:value("5", translate("5 秒")) -timeout:value("6", translate("6 秒")) -timeout:value("7", translate("7 秒")) -timeout:value("8", translate("8 秒")) -timeout:value("9", translate("9 秒")) -timeout:value("10", translate("10 秒")) -timeout:depends("alive", "1") -timeout:depends("alive", "2") -timeout:depends("alive", "3") -timeout:depends("alive", "4") - -packetsize = di:taboption(this_tab, Value, "packetsize", translate("Ping报文大小(字节为单位) :"), - translate("范围值 :4-56,ping报文发送的数据字节数,可以要根据运营商进行调整")) - packetsize.datatype = "range(4, 56)" - packetsize.default = "56" - packetsize:depends("alive", "1") - packetsize:depends("alive", "2") - packetsize:depends("alive", "3") - packetsize:depends("alive", "4") - -down = di:taboption(this_tab, ListValue, "down", translate("链路状态 异常判定次数 :"), - translate("如果达到设定值次数,Ping依旧失败后,接口就会被当做异常不在线")) -down.default = "3" -down:value("1") -down:value("2") -down:value("3") -down:value("4") -down:value("5") -down:value("6") -down:value("7") -down:value("8") -down:value("9") -down:value("10") -down:depends("alive", "1") -down:depends("alive", "2") -down:depends("alive", "3") -down:depends("alive", "4") - -up = di:taboption(this_tab, ListValue, "up", translate("链路状态 正常判定次数 :"), - translate("Tips:当达到设定值次数Ping监测后,网络都能Ping设定地址后,则链路状态会被视为正常啦~~")) -up.default = "3" -up:value("1") -up:value("2") -up:value("3") -up:value("4") -up:value("5") -up:value("6") -up:value("7") -up:value("8") -up:value("9") -up:value("10") -up:depends("alive", "1") -up:depends("alive", "2") -up:depends("alive", "3") -up:depends("alive", "4") - -cb2 = di:taboption(this_tab, DynamicList, "trackip", translate("追踪 IP :"), - translate("这个IP将被拿来做链路状态检测用,简单说就是Ping它,能通那么就算链路正常,不通那就以你刚配合的方法处理")) -cb2.datatype = "ipaddr" -cb2:depends("alive", "1") -cb2:depends("alive", "2") -cb2:depends("alive", "3") -cb2:depends("alive", "4") -cb2.optional=false; -cb2.default="114.114.114.114" - -if (multilock == "0") or (multilock == "1" and rootlock == "1") then - this_tab = "bwidth" - bwday = di:taboption(this_tab, ListValue, "bwday", translate("发送监测信息的日期 :"), - translate("每月发送监测报告文件的日期,请选择在每个月的第几日发送,不需要请选择禁用")) - bwday.default = "0" - bwday:value("0", translate("禁用")) - bwday:value("1", translate("1日")) - bwday:value("2", translate("2日")) - bwday:value("3", translate("3日")) - bwday:value("4", translate("4日")) - bwday:value("5", translate("5日")) - bwday:value("6", translate("6日")) - bwday:value("7", translate("7日")) - bwday:value("8", translate("8日")) - bwday:value("9", translate("9日")) - bwday:value("10", translate("10日")) - bwday:value("11", translate("11日")) - bwday:value("12", translate("12日")) - bwday:value("13", translate("13日")) - bwday:value("14", translate("14日")) - bwday:value("15", translate("15日")) - bwday:value("16", translate("16日")) - bwday:value("17", translate("17日")) - bwday:value("18", translate("18日")) - bwday:value("19", translate("19日")) - bwday:value("20", translate("20日")) - bwday:value("21", translate("21日")) - bwday:value("22", translate("22日")) - bwday:value("23", translate("23日")) - bwday:value("24", translate("24日")) - bwday:value("25", translate("25日")) - bwday:value("26", translate("26日")) - bwday:value("27", translate("27日")) - bwday:value("28", translate("28日")) - - phone = di:taboption(this_tab, Value, "phone", translate("手机号码 :"), translate("我们将会通过这个手机号码给你发送监测日志报告,物联卡就爬吧发不了的,短信费用按你套餐资费扣,介意就别踏马用了")) - phone.default = "填入接收监测报告的手机号码,我们将会以短信方式给你发送" - - bwdelay = di:taboption(this_tab, ListValue, "bwdelay", translate("发送前延迟 :"), - translate("凌晨后几个小时发送短信给你")) - bwdelay:value("0", translate("不延迟")) - bwdelay:value("1", translate("1 小时")) - bwdelay:value("2", translate("2 小时")) - bwdelay:value("3", translate("3 小时")) - bwdelay:value("4", translate("4 小时")) - bwdelay:value("5", translate("5 小时")) - bwdelay:value("6", translate("6 小时")) - bwdelay:value("7", translate("7 小时")) - bwdelay:value("8", translate("8 小时")) - bwdelay:value("9", translate("9 小时")) - bwdelay:value("10", translate("10 小时")) - bwdelay:value("11", translate("11 小时")) - bwdelay:value("12", translate("12 小时")) -end - -if fs.stat("/usr/lib/autoapn/apn.data") then - dda = m:section(TypedSection, "disable", translate("Use Automatic APN"), translate("Enable the use of the Automatic APN selection. This disables Custom Profiles.")) - dda.anonymous = true - aenabled = dda:option(Flag, "autoapn", translate("Enabled")) - aenabled.default="0" - aenabled.optional=false; -end - -dd = m:section(TypedSection, "disable", translate("禁用自动APN :"), translate("禁用自动APN后,所有4G/5G通信模块将会使用默认配置文件,不勾选就是默认启用")) -dd.anonymous = true - -enabled = dd:option(Flag, "enabled", translate("禁用")) -enabled.default="0" -enabled.optional=false; - --- --- Custom profile --- - -s = m:section(TypedSection, "custom", translate("定制特定组合配置 :"), translate("可将某个特定配置应用在你所选中的4G/5G模块与SIM卡组合中")) -s.anonymous = true -s.addremove = true -s:tab("custom", translate("简要")) -s:tab("cadvanced", translate("高级")) -s:tab("cconnect", translate("网络异常自动处理")) -if (multilock == "0") or (multilock == "1" and rootlock == "1") then - s:tab("cbwidth", translate("通信模块频宽日志")) -end - -this_ctab = "custom" - -name = s:taboption(this_ctab, Value, "name", translate("配置名称 :")) - -enabled = s:taboption(this_ctab, Flag, "enabled", translate("启用")) -enabled.default="1" -enabled.optional=false; - -select = s:taboption(this_ctab, ListValue, "select", translate("选择对象 :")); -select:value("0", translate("模块 ID")) -select:value("1", translate("模块 IMEI")) -select:value("2", translate("模块名称")) -select:value("3", translate("SIM卡IMSI")) -select:value("4", translate("SIM卡ICCID")) -select.default=0 - -idV = s:taboption(this_ctab, Value, "vid", translate("USB VID :")); -idV.optional=false; -idV:depends("select", "0") -idV.default="xxxx" - -idP = s:taboption(this_ctab, Value, "pid", translate("USB PID :")); -idP.optional=false; -idP:depends("select", "0") -idP.default="xxxx" - -imei = s:taboption(this_ctab, Value, "imei", translate("通信模块IMEI :")); -imei.optional=false; -imei:depends("select", "1") -imei.datatype = "uinteger" -imei.default="1234567" - -model = s:taboption(this_ctab, Value, "model", translate("模块名称包含 :")); -model.optional=false; -model:depends("select", "2") -model.default="xxxx" - -imsi = s:taboption(this_ctab, Value, "imsi", translate("SIM卡IMSI :")); -imsi.optional=false; -imsi:depends("select", "3") -imsi.datatype = "uinteger" -imsi.default="1234567" - -iccid = s:taboption(this_ctab, Value, "iccid", translate("SIM卡ICCID :")); -iccid.optional=false; -iccid:depends("select", "4") -iccid.datatype = "uinteger" -iccid.default="1234567" - -select1 = s:taboption(this_ctab, ListValue, "select1", translate("选择组合对象 :")); -select1:value("0", "模块 ID") -select1:value("1", "模块 IMEI") -select1:value("2", "型号名称") -select1:value("3", "SIM卡IMSI") -select1:value("4", "SIM卡ICCID") -select1:value("10", "None") -select1.default=10 - -idV1 = s:taboption(this_ctab, Value, "vid1", translate("USB VID :")); -idV1.optional=false; -idV1:depends("select1", "0") -idV1.default="xxxx" - -idP1 = s:taboption(this_ctab, Value, "pid1", translate("USB PID :")); -idP1.optional=false; -idP1:depends("select1", "0") -idP1.default="xxxx" - -imei1 = s:taboption(this_ctab, Value, "imei1", translate("模块 IMEI :")); -imei1.optional=false; -imei1:depends("select1", "1") -imei1.datatype = "uinteger" -imei1.default="1234567" - -model1 = s:taboption(this_ctab, Value, "model1", translate("模块 名称包含 :")); -model1.optional=false; -model1:depends("select1", "2") -model1.default="xxxx" - -imsi1 = s:taboption(this_ctab, Value, "imsi1", translate("SIM卡IMSI :")); -imsi1.optional=false; -imsi1:depends("select1", "3") -imsi1.datatype = "uinteger" -imsi1.default="1234567" - -iccid1 = s:taboption(this_ctab, Value, "iccid1", translate("SIM卡ICCID :")); -iccid1.optional=false; -iccid1:depends("select1", "4") -iccid1.datatype = "uinteger" -iccid1.default="1234567" - -cma = s:taboption(this_ctab, Value, "apn", "APN :"); -cma.rmempty = true; - -tt = s:taboption(this_ctab, ListValue, "ttl", translate("自定义TTL值 :")) -tt:value("0", translate("Use Current Value")) -tt:value("1", translate("No TTL Value")) -tt:value("63", "TTL 63") -tt:value("64", "TTL 64") -tt:value("65", "TTL 65") -tt:value("66", "TTL 66") -tt:value("67", "TTL 67") -tt:value("117", "TTL 117") -tt:value("TTL-INC 1", "TTL-INC 1") -tt.default = "0" - -nl = s:taboption(this_ctab, ListValue, "hostless", translate("调整无主机(无主控)模块的TTL值 :")); -nl:value("0", translate("No")) -nl:value("1", translate("是")) -nl.default=0 - -pt = s:taboption(this_ctab, ListValue, "pdptype", translate("IP协议类型 :")) -pt:value("IP", "IPv4") -pt:value("IPv6", "IPv6") -pt:value("IPV4V6", "IPv4+IPv6") -pt:value("0", "Default") -pt.default = "0" - -cmcc = s:taboption(this_ctab, Value, "context", translate("PDP Context for APN :")); -cmcc.optional=false; -cmcc.rmempty = true; -cmcc.datatype = "and(uinteger,min(1),max(10))" -cmcc.default = "1" - -cmu = s:taboption(this_ctab, Value, "user", translate("用户名 :")); -cmu.optional=false; -cmu.rmempty = true; - -cmp = s:taboption(this_ctab, Value, "passw", translate("密码 :")); -cmp.optional=false; -cmp.rmempty = true; -cmp.password = true - -cmpi = s:taboption(this_ctab, Value, "pincode", "PIN码 :"); -cmpi.optional=false; -cmpi.rmempty = true; - -cmau = s:taboption(this_ctab, ListValue, "auth", translate("身份验证类型 :")) -cmau:value("0", "无") -cmau:value("1", "PAP") -cmau:value("2", "CHAP") -cmau.default = "0" - -cmtz = s:taboption(this_ctab, ListValue, "tzone", translate("自动设置时区"), translate("模块通网后自动设置时区")); -cmtz:value("0", translate("禁用")) -cmtz:value("1", translate("启用")) -cmtz.default=1 - -cml = s:taboption(this_ctab, ListValue, "lock", translate("是否锁定国际漫游运营商选项(国内不用管) :")); -cml:value("0", translate("否")) -cml:value("1", translate("强硬的")) -cml:value("2", translate("柔弱的")) -cml.default=0 - -cmcc = s:taboption(this_ctab, Value, "mcc", translate("MCC :")); -cmcc.optional=false; -cmcc.rmempty = true; -cmcc.datatype = "and(uinteger,min(1),max(999))" -cmcc:depends("lock", "1") -cmcc:depends("lock", "2") - -cmnc = s:taboption(this_ctab, Value, "mnc", translate("MNC :")); -cmnc.optional=false; -cmnc.rmempty = true; -cmnc.datatype = "and(uinteger,min(1),max(999))" -cmnc:depends("lock", "1") -cmnc:depends("lock", "2") - -this_ctaba = "cadvanced" - -cmf = s:taboption(this_ctaba, ListValue, "ppp", translate("强制使用3G PP协议拨号 :")); -cmf:value("0", translate("否")) -cmf:value("1", translate("是")) -cmf.default=0 - -cmw = s:taboption(this_ctaba, ListValue, "inter", translate("模块WAN口分配 :")); -cmw:value("0", "自动") -cmw:value("1", "WAN1") -cmw:value("2", "WAN2") -cmw:value("3", "关闭") -cmw.default=0 - -cmd = s:taboption(this_ctaba, Value, "delay", translate("连接延迟(以秒为单位) :")); -cmd.optional=false; -cmd.rmempty = false; -cmd.default = 5 -cmd.datatype = "and(uinteger,min(5))" - -cnl = s:taboption(this_ctaba, ListValue, "nodhcp", translate("强制QMI协议不使用模块的DHCP,从其他位置获取 :")); -cnl:value("0", translate("禁用")) -cnl:value("1", translate("启用")) -cnl.default=0 - -cmdns1 = s:taboption(this_ctaba, Value, "dns1", translate("自定义1 :")); -cmdns1.rmempty = true; -cmdns1.optional=false; -cmdns1.datatype = "ipaddr" - -cmdns2 = s:taboption(this_ctaba, Value, "dns2", translate("自定义2 :")); -cmdns2.rmempty = true; -cmdns2.optional=false; -cmdns2.datatype = "ipaddr" - -cmdns3 = s:taboption(this_ctaba, Value, "dns3", translate("自定义3 :")); -cmdns3.rmempty = true; -cmdns3.optional=false; -cmdns3.datatype = "ipaddr" - -cmdns4 = s:taboption(this_ctaba, Value, "dns4", translate("自定义4 :")); -cmdns4.rmempty = true; -cmdns4.optional=false; -cmdns4.datatype = "ipaddr" - -cmlog = s:taboption(this_ctaba, ListValue, "log", translate("启用连接日志 :")); -cmlog:value("0", translate("禁用")) -cmlog:value("1", translate("启用")) -cmlog.default=0 - -if nixio.fs.access("/etc/config/mwan3") then - cmlb = s:taboption(this_ctaba, ListValue, "lb", translate("在多个5G模块中开启流量负载均衡 :")); - cmlb:value("0", translate("禁用")) - cmlb:value("1", translate("启用")) - cmlb.default=0 -end - -mtu = s:taboption(this_ctaba, Value, "mtu", translate("自定义MTU值 :"), - translate("歪歪歪 米乱整窝,纸能自定义1420到1500的蜗 根据不同运营商进行调整的歪,理不鸡丢就不要瞎搞了蛙,等夏列个网炸嘿掉了鳖嘿来找我蜗~~")); -mtu.optional=true -mtu.rmempty = true -mtu.default = "1500" -mtu.datatype = "range(1420, 1500)" - -cmat = s:taboption(this_ctaba, ListValue, "at", translate("在连接模块时发送自定义AT命令 :")); -cmat:value("0", translate("禁用")) -cmat:value("1", translate("启用")) -cmat.default=0 - -cmatc = s:taboption(this_ctaba, Value, "atc", translate("自定义AT命令 :")); -cmatc.optional=false; -cmatc.rmempty = true; - --- --- Custom Connection Monitoring --- - -this_ctab = "cconnect" - -calive = s:taboption(this_ctab, ListValue, "alive", translate("连接状态监控 :")); -calive.rmempty = true; -calive:value("0", translate("禁用")) -calive:value("1", translate("启用掉线写入系统日志")) -calive:value("2", translate("启用 5G模块掉线 则 路由自动重启")) -calive:value("3", translate("启用 5G模块掉线 则 自动重拨")) -calive:value("4", translate("启用 5G模块掉线 则 重新上电模块,需要路由GPIO支持,否则将使用其他方式重连")) -calive.default=0 - -reliability = s:taboption(this_ctab, Value, "reliability", translate("监测网络稳定性 :"), - translate("Acceptable values: 范围: 1-100,必须Ping通这些IP地址,这条通信链路才会被视为联网状态")) -reliability.datatype = "range(1, 100)" -reliability.default = "1" -reliability:depends("alive", "1") -reliability:depends("alive", "2") -reliability:depends("alive", "3") -reliability:depends("alive", "4") - -count = s:taboption(this_ctab, ListValue, "count", translate("监测次数(Ping):")) -count.default = "1" -count:value("1") -count:value("2") -count:value("3") -count:value("4") -count:value("5") -count:depends("alive", "1") -count:depends("alive", "2") -count:depends("alive", "3") -count:depends("alive", "4") - -interval = s:taboption(this_ctab, ListValue, "pingtime", translate("监测时间间隔 (Ping) :"), - translate("监测Ping之间间隔时间的值")) -interval.default = "10" -interval:value("5", translate("5 秒")) -interval:value("10", translate("10 秒")) -interval:value("20", translate("20 秒")) -interval:value("30", translate("30 秒")) -interval:value("60", translate("1 分钟")) -interval:value("300", translate("5 分钟")) -interval:value("600", translate("10 分钟")) -interval:value("900", translate("15 分钟")) -interval:value("1800", translate("30 分钟")) -interval:value("3600", translate("1 小时")) -interval:depends("alive", "1") -interval:depends("alive", "2") -interval:depends("alive", "3") -interval:depends("alive", "4") - -timeout = s:taboption(this_ctab, ListValue, "pingwait", translate("Ping 超时 :")) -timeout.default = "2" -timeout:value("1", translate("1 秒")) -timeout:value("2", translate("2 秒")) -timeout:value("3", translate("3 秒")) -timeout:value("4", translate("4 秒")) -timeout:value("5", translate("5 秒")) -timeout:value("6", translate("6 秒")) -timeout:value("7", translate("7 秒")) -timeout:value("8", translate("8 秒")) -timeout:value("9", translate("9 秒")) -timeout:value("10", translate("10 秒")) -timeout:depends("alive", "1") -timeout:depends("alive", "2") -timeout:depends("alive", "3") -timeout:depends("alive", "4") - -packetsize = s:taboption(this_ctab, Value, "packetsize", translate("Ping报文大小(字节为单位) :"), - translate("范围值 :4-56,ping报文发送的数据字节数,可以要根据运营商进行调整")) - packetsize.datatype = "range(4, 56)" - packetsize.default = "56" - packetsize:depends("alive", "1") - packetsize:depends("alive", "2") - packetsize:depends("alive", "3") - packetsize:depends("alive", "4") - -down = s:taboption(this_ctab, ListValue, "down", translate("链路状态 异常判定次数 :"), - translate("如果达到设定值次数,Ping依旧失败后,接口就会被当做异常不在线")) -down.default = "3" -down:value("1") -down:value("2") -down:value("3") -down:value("4") -down:value("5") -down:value("6") -down:value("7") -down:value("8") -down:value("9") -down:value("10") -down:depends("alive", "1") -down:depends("alive", "2") -down:depends("alive", "3") -down:depends("alive", "4") - -up = s:taboption(this_ctab, ListValue, "up", translate("链路状态 正常判定次数"), - translate("当达到设定值次数Ping监测后,网络都能Ping设定地址后,则链路状态会被视为正常啦~~")) -up.default = "3" -up:value("1") -up:value("2") -up:value("3") -up:value("4") -up:value("5") -up:value("6") -up:value("7") -up:value("8") -up:value("9") -up:value("10") -up:depends("alive", "1") -up:depends("alive", "2") -up:depends("alive", "3") -up:depends("alive", "4") - -cb2 = s:taboption(this_ctab, DynamicList, "trackip", translate("追踪 IP :"), - translate("这个IP将被拿来做链路状态检测用,简单说就是Ping它,能通那么就算链路正常,不通那就以你刚配合的方法处理")) -cb2.datatype = "ipaddr" -cb2:depends("alive", "1") -cb2:depends("alive", "2") -cb2:depends("alive", "3") -cb2:depends("alive", "4") -cb2.optional=false; -cb2.default="114.114.114.114" - -if (multilock == "0") or (multilock == "1" and rootlock == "1") then - this_ctab = "cbwidth" - bwday = s:taboption(this_ctab, ListValue, "bwday", translate("每个月发送网络稳定日志的日期"), - translate("每月发送监测报告文件的日期,请选择在每个月的第几日发送,不需要请选择禁用")) - bwday.default = "0" - bwday:value("0", translate("禁用")) - bwday:value("1", translate("1日")) - bwday:value("2", translate("2日")) - bwday:value("3", translate("3日")) - bwday:value("4", translate("4日")) - bwday:value("5", translate("5日")) - bwday:value("6", translate("6日")) - bwday:value("7", translate("7日")) - bwday:value("8", translate("8日")) - bwday:value("9", translate("9日")) - bwday:value("10", translate("10日")) - bwday:value("11", translate("11日")) - bwday:value("12", translate("12日")) - bwday:value("13", translate("13日")) - bwday:value("14", translate("14日")) - bwday:value("15", translate("15日")) - bwday:value("16", translate("16日")) - bwday:value("17", translate("17日")) - bwday:value("18", translate("18日")) - bwday:value("19", translate("19日")) - bwday:value("20", translate("20日")) - bwday:value("21", translate("21日")) - bwday:value("22", translate("22日")) - bwday:value("23", translate("23日")) - bwday:value("24", translate("24日")) - bwday:value("25", translate("25日")) - bwday:value("26", translate("26日")) - bwday:value("27", translate("27日")) - bwday:value("28", translate("28日")) - - phone = s:taboption(this_ctab, Value, "phone", translate("手机号码 :"), translate("我们将会通过这个手机号码给你发送监测日志报告,物联卡就爬吧发不了的,短信费用按你套餐资费扣,介意就不要用了")) - phone.default = "12223334444" - - bwdelay = s:taboption(this_ctab, ListValue, "bwdelay", translate("发送前延迟 :"), - translate("凌晨后几个小时发送短信给你")) - bwdelay:value("0", translate("No Delay")) - bwdelay:value("1", translate("1 小时")) - bwdelay:value("2", translate("2 小时")) - bwdelay:value("3", translate("3 小时")) - bwdelay:value("4", translate("4 小时")) - bwdelay:value("5", translate("5 小时")) - bwdelay:value("6", translate("6 小时")) - bwdelay:value("7", translate("7 小时")) - bwdelay:value("8", translate("8 小时")) - bwdelay:value("9", translate("9 小时")) - bwdelay:value("10", translate("10 小时")) - bwdelay:value("11", translate("11 小时")) - bwdelay:value("12", translate("12 小时")) -end - -return m - - - diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm deleted file mode 100644 index 9aa6023..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_status/index/external.htm +++ /dev/null @@ -1 +0,0 @@ -<%+rooter/external%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm deleted file mode 100644 index 30d9333..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/admin_system/poweroff.htm +++ /dev/null @@ -1,34 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<%+header%> - - - - -

                          <%:System%>

                          -

                          <%:System Stop%>

                          -

                          <%:Graceful system stop. De-power then re-power to restart.%>

                          -

                          -
                            -<%+footer%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm deleted file mode 100644 index 990dc5c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/modlog/modlog.htm +++ /dev/null @@ -1,32 +0,0 @@ -<%+header%> - - - - -
                            -

                            <%:模块连接日志%>

                            -
                            -
                            - <%:Log%> - - - - -
                            - -
                            - -
                            - -
                            - -<%+footer%> diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm deleted file mode 100644 index e23d1e8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/custom.htm +++ /dev/null @@ -1,126 +0,0 @@ -<% -local modemfile = "/etc/config/modem.data" -local modemdata = {} -local count - -function process_line(xline, cnt) - local data = {} - local pline = xline - local start = 1 - for i=1,3 do - s, e = string.find(pline, " ") - data[i] = string.sub(pline, start, s-1) - pline = string.sub(pline, e+1) - end - data[4] = pline - modemdata[cnt] = data -end - -function read_modem() - count = 0 - local file = io.open(modemfile, "r") - if file == nil then - return - end - repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) < 5 then - break - end - count = count + 1 - process_line(line, count) - until 1==0 - file:close() -end - -function process_family(index) - local t = { } - if count == 0 then - return t - end - local mdata = modemdata[index] - if mdata[1] ~= "nil" and mdata[2] ~= "nil" then - t[1] = mdata[1] .. ":" .. mdata[2] - if mdata[3] == "tty" then - t[2] = "default" - end - if mdata[3] == "tty0" then - t[2] = "ttyUSB0" - end - if mdata[3] == "tty1" then - t[2] = "ttyUSB1" - end - if mdata[3] == "tty2" then - t[2] = "ttyUSB2" - end - if mdata[3] == "tty3" then - t[2] = "ttyUSB3" - end - if mdata[3] == "tty4" then - t[2] = "ttyUSB4" - end - if mdata[3] == "tty5" then - t[2] = "ttyUSB5" - end - - if mdata[4] == "tty" then - t[3] = "default" - end - if mdata[4] == "tty0" then - t[3] = "ttyUSB0" - end - if mdata[4] == "tty1" then - t[3] = "ttyUSB1" - end - if mdata[4] == "tty2" then - t[3] = "ttyUSB2" - end - if mdata[4] == "tty3" then - t[3] = "ttyUSB3" - end - if mdata[4] == "tty4" then - t[3] = "ttyUSB4" - end - if mdata[4] == "tty5" then - t[3] = "ttyUSB5" - end - - end - return t -end - -read_modem() - -%> - -
                            - <%:自定义模块端口数据库%> - - - - - - - <% - if count > 0 then - for i=1,count do - t = process_family(i) %> - - - - - - <% - end - else %> - - - - <% - end %> -
                            <%:模块名称%><%:数据端口%><%:通信端口%>
                            <%=t[1]%><%=t[2]%><%=t[3]%>
                            <%:暂无数据%>  
                            -
                            - diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm deleted file mode 100644 index e9f0d9c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/debug.htm +++ /dev/null @@ -1,87 +0,0 @@ -<%+header%> - -<% -local cnt = 0 -local tt = {} - -os.execute("cat /sys/kernel/debug/usb/devices > /tmp/modstat 2>&1") -local file = io.open("/tmp/modstat", "r") -repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) < 3 then - line = "********************************************************************************************************" - end - tt[cnt] = line - cnt = cnt + 1 -until 1 == 0 -cnt = cnt - 1 -file:close() -os.execute("/usr/lib/rooter/luci/luaops.sh delete /tmp/modstat") -%> - - - - -
                            -

                            <%:通信模块调试信息%>

                            -
                            -
                            - <%:自动化AT指令调试日志%> - - - - -
                            - -
                            - -
                            - -
                            - <%:设备信息%> - - - - - - - <% - for i=1,cnt do - s, e = string.find(tt[i], "供应商") - s1, e = string.find(tt[i], "品牌") - s2, e = string.find(tt[i], "模块型号") - if s ~= nil or s1 ~= nil or s2 ~= nil then - %> - - - - - - <% else - %> - - - - - - <% end - end %> -
                            <%=tt[i]%>
                            <%=tt[i]%>
                            -
                            -

                            -
                            - -<%+footer%> - diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm deleted file mode 100644 index 526e7bc..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/external.htm +++ /dev/null @@ -1,26 +0,0 @@ - - -
                            -

                            <%:公网 Internet IP 地址%>

                            - - -
                            <%:IP Address%><%:Loading%> Collecting data...
                            -
                            - diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm deleted file mode 100644 index 842ae8c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/log.htm +++ /dev/null @@ -1,53 +0,0 @@ -<%+header%> - - - - -
                            -
                            -

                            <%:Connection Log%>

                            -
                            - -
                            - - - - - - - -
                            - -
                            - -
                            - -
                            - -
                            -
                            -<%+footer%> \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm deleted file mode 100644 index 05a087e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/misc.htm +++ /dev/null @@ -1,2387 +0,0 @@ -<%+header%> -<% -local sys = require "luci.sys" -local utl = require "luci.util" -local fs = require "nixio.fs" -local uci = require "luci.model.uci".cursor() -local s = uci:get("custom", "bandlock", "enabled") -local a = uci:get("custom", "atcmd", "enabled") - -local multilock = uci:get("custom", "multiuser", "multi") or "0" -local rootlock = uci:get("custom", "multiuser", "root") or "0" -nomulti=1 -if (multilock == "0") or (multilock == "1" and rootlock == "1") then - nosms = 1 - if a == "1" then - nosms = 0 - end -else - nosms = 1 - nomulti = 0 -end -block = 1 -if s == "1" then - block = 0 -end - -function showicon(lck) - if lck == 0 then - return resource .. "/icons/unlock1.png" - else - return resource .. "/icons/lock1.png" - end -end - --%> - - - -
                            -
                            -

                            <%:锁频段/锁PCI/切换协议/AT命令%>

                            -
                            <%:锁频段/锁PCI/切换协议/AT命令%>
                            - - - -
                            - <%:当前模块%> - - - - - - - -
                              - - - -
                              -
                              -
                              - <%:模块 连接/断开控制%> - - - - - - - -
                              - - - - - - - -
                              -
                              - -<% if nosms == 0 then %> -
                              - <%:AT命令终端%> - - - - - - - - - - - - - - - -
                              <%:AT命令 : %>
                              - - - -  
                              -
                              - - - - - - - - - - - - - - - - - -
                              <%:AT命令 : %>
                               
                              - - - - - -
                              - -
                              - -
                              -<% end %> - -<% if nomulti == 1 then %> -<% if block == 0 then %> -
                              - <%:4G/5G频段锁定%> - - - - - -
                               
                              - - - - - - -
                              <%:没有模块/模块未适配本插件%> 
                              - - - - - - - -
                               
                              <%:4G LTE频段%>
                               
                              - - - - -
                              - - - - - - - -
                               
                              <%:5G NSA频段%>
                               
                              - - - - -
                              - - - - - - - -
                               
                              <%:5G SA 频段%>
                               
                              - - - - -
                              - - - - - - - -
                                
                              - - - - - -
                               
                              - - - - - - -
                               
                              - - - - - -
                              <%:2 x 载波聚合%>
                              - - - - -
                              - - - - - -
                              <%:3 x 载波聚合%>
                              - - - - -
                              - - - - - -
                               
                              - - - - - - - - - -
                               
                              <%:扫描可用的频段%>
                               
                              - - - - - -
                              - -
                              - - - - - - - - - - -
                                
                              <%:锁定基站%>
                               
                              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                              <%:功能状态 : %>
                                 
                              <%:EARFCN 1 : %>
                              <%:PCI 1 : %>
                               
                              <%:EARFCN 2 : %>
                              <%:PCI 2 : %>
                               
                              <%:EARFCN 3 : %>
                              <%:PCI 3 : %>
                               
                              <%:EARFCN 4 : %>
                              <%:PCI 4 : %>
                               
                              - - - - - - -
                               
                              - -
                              -<% end %> - -
                              - <%:模块连接协议切换%> - - - - - - - - - - - - - -
                               
                              <%:当前模块连接协议 :%>
                               
                               
                              <%:更改蜂窝模式 :%>
                              - - -
                              -
                              - -
                              - <%:网络类型选择%> - - - - - - - - - - - - - -
                              <%:当前网络类型 :%>
                               
                              <%:更改网络类型 :%>
                              - - - - -  
                              -
                              -<% end %> - -
                              - <%:GPS Message Pin%> - - - - - - - - -
                               
                              <%:Message Pin :%>
                               
                              -
                              - -
                              -
                              -<%+footer%> diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm deleted file mode 100644 index bcab6fa..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/net_status.htm +++ /dev/null @@ -1,564 +0,0 @@ -<%+header%> -<% -local fs = require "nixio.fs" -nosms = 1 -if not fs.stat("/etc/nosim") then - nosms = 0 -end -havegps = 0 -if fs.stat("/etc/havegps") then - havegps = 1 -end --%> - - - - -
                              -
                              -

                              <%:信号状态/模块信息%>

                              -
                              请注意该插件所有功能并无适配所有5G模块,不用妄想冷门模块插上就能用(有能力者自行适配) -
                              - - - -
                              - <%:综合信息%> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                              <%:模块 :%>
                                - - - -
                                <%:ID : %>
                                    
                                  <%:运营商 : %>
                                      
                                    <%:端口 :%>
                                      - - - -
                                      <%:温度 : %>
                                          
                                        <%:协议 : %>
                                            
                                          -
                                          - -<% if nosms == 0 then %> -
                                          - <%:通信模块/SIM卡信息%> - - - - - - - - - - - - - - - - - - - - - - -
                                          - -    
                                          <%:IMEI:%>
                                              
                                            <%:IMSI:%>
                                              <%:ICCID:%>
                                                - - - - - - - - - - - - -
                                                <%:SIM卡号码 : %>
                                                - -   
                                                <%:SIM卡名称 : %>
                                                -
                                                -<% end %> - -
                                                - <%:信号状态%> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                <%:蜂窝网络类型 :%>
                                                   
                                                  <%:CSQ : %>
                                                     
                                                    <%:信号强度 : %>
                                                       
                                                      <%:信号接收强度 RSSI : %>
                                                         
                                                        <%:参考信号接收质量 RSRQ :%>
                                                         
                                                        <%:参考信号接收功率 RSRP :%>
                                                         
                                                        <%:信噪比 SINR : %>
                                                           
                                                          <%:连接状态监控 : %>
                                                             
                                                            -
                                                            - -
                                                            - <%:基站信息%> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                                            <%:MCC / MNC :%>
                                                             
                                                            <%:eNB ID :%>
                                                             
                                                            <%:TAC :%>
                                                             
                                                            <%:Cell ID : %>
                                                             
                                                            <%:频段 Band : %>
                                                               
                                                              <%:频点 Channel : %>
                                                                 
                                                                <%:物理小区标识 PCI : %>
                                                                   
                                                                  <%:最大Qos级别 Maximum Qos : %>
                                                                   
                                                                  -
                                                                  - -<% if havegps == 1 then %> -
                                                                  - <%:GPS 定位%> - - - - - - - - - - - -
                                                                  <%:纬度 :%>
                                                                     
                                                                    <%:经度 :%>
                                                                       
                                                                      -
                                                                      -<% end %> -
                                                                      - <%:刷新频率%> - - - - - - - - - - - - - -
                                                                      <%:当前刷新率 :%>
                                                                       
                                                                      <%:修改刷新时间 :%>
                                                                      - -  
                                                                      -
                                                                      - -
                                                                      -
                                                                      -<%+footer%> - diff --git a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm b/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm deleted file mode 100644 index 64efa21..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/lua/luci/view/rooter/profile.htm +++ /dev/null @@ -1,75 +0,0 @@ -<% - -%> - - - -
                                                                      - <%:Import/Export the Profile Data%> - - - - - - - - - - - - - - - - -
                                                                       
                                                                      <%:Export Profile Data to Computer%>
                                                                       
                                                                      <%:Import Profile Data from Computer%>
                                                                        
                                                                      <%:Page will automatically refresh after file is loaded%>
                                                                      - -
                                                                      diff --git a/rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh b/rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh deleted file mode 100644 index 4c3a531..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/modlog/modlogger.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -TEXT=$1 -DATE=$(date +%c) - -modlog="/tmp/modlog.log" -tmplog="/tmp/tmodlog" - -wc -l $modlog > /tmp/linecnt -read lcnt fle < /tmp/linecnt -rm -f /tmp/linecnt -if [ $lcnt -ge 200 ]; then - start=$((lcnt-1)) - tail +$start modlog > $tmplog - mv $tmplog $modlog -fi - -echo "$DATE : $TEXT" >> $modlog diff --git a/rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh b/rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh deleted file mode 100644 index 09648f2..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/profile/loadcfg.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Load" "$@" -} - -profile=$(cat /tmp/profilename) -valid=$(echo "$profile" | grep "**Profile**") -if [ ! -z "$valid" ]; then - echo "$profile" > /tmp/profile - sed -i '1d' /tmp/profile - cp /tmp/profile /etc/config/profile -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh b/rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh deleted file mode 100644 index 3f632d1..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/profile/restart.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Restart" "$@" -} - -sleep 3 - -CURRMODEM=1 -CPORT=$(uci -q get modem.modem$CURRMODEM.commport) - -$ROOTER/luci/restart.sh $CURRMODEM 11 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh b/rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh deleted file mode 100644 index ab8c026..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/profile/savecfg.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -log() { - logger -t "Save" "$@" -} - -PKI_DIR="/www" -cd ${PKI_DIR} -mkdir -p package -cd .. -chmod -R 0777 ${PKI_DIR}/package - -echo "***Profile***" > ${PKI_DIR}/package/profilecfg.profile -state=$(cat /etc/config/profile) -echo "$state" >> ${PKI_DIR}/package/profilecfg.profile \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh deleted file mode 100644 index c461f46..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/autoapn.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "SimLock " "$@" -} diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua deleted file mode 100644 index b1f9922..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/cdmafind.lua +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/lua - -drv = {} -idV = arg[1] -idP = arg[2] - -retval = 0 - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - --- MAIN - -local i=0 -local file = io.open("/tmp/cdma", "r") -repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("Vendor=") - if s ~= nil then - cs, ce = line:find(" ", e) - m_idV = trim(line:sub(e+1, cs-1)) - s, e = line:find("ProdID=") - cs, ce = line:find(" ", e) - m_idP = trim(line:sub(e+1, cs-1)) - if m_idV == idV and m_idP == idP then - repeat - line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("Product=") - if s ~= nil then - s, e = line:find(" CDMA") - if s ~= nil then - retval = 1 - break - end - end - end - until 1==0 - break - end - end - end -until 1==0 -file:close() - - -os.exit(retval) \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh deleted file mode 100644 index 99b1ce3..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/chan2band.sh +++ /dev/null @@ -1,273 +0,0 @@ -#!/bin/sh -CHAN=$1 -CHAN=$(echo "$CHAN" | grep -o "[0-9]*") - -decode_lte() { - if [ $CHAN -lt 600 ]; then - BAND="B1" - elif [ $CHAN -lt 1200 ]; then - BAND="B2" - elif [ $CHAN -lt 1950 ]; then - BAND="B3" - elif [ $CHAN -lt 2400 ]; then - BAND="B4" - elif [ $CHAN -lt 2650 ]; then - BAND="B5" - elif [ $CHAN -lt 2750 ]; then - BAND="B6" - elif [ $CHAN -lt 3450 ]; then - BAND="B7" - elif [ $CHAN -lt 3800 ]; then - BAND="B8" - elif [ $CHAN -lt 4150 ]; then - BAND="B9" - elif [ $CHAN -lt 4750 ]; then - BAND="B10" - elif [ $CHAN -lt 4950 ]; then - BAND="B11" - elif [ $CHAN -lt 5010 ]; then - BAND="-" - elif [ $CHAN -lt 5180 ]; then - BAND="B12" - elif [ $CHAN -lt 5280 ]; then - BAND="B13" - elif [ $CHAN -lt 5380 ]; then - BAND="B14" - elif [ $CHAN -lt 5730 ]; then - BAND="-" - elif [ $CHAN -lt 5850 ]; then - BAND="B17" - elif [ $CHAN -lt 6000 ]; then - BAND="B18" - elif [ $CHAN -lt 6150 ]; then - BAND="B19" - elif [ $CHAN -lt 6450 ]; then - BAND="B20" - elif [ $CHAN -lt 6600 ]; then - BAND="B21" - elif [ $CHAN -lt 7400 ]; then - BAND="B22" - elif [ $CHAN -lt 7500 ]; then - BAND="-" - elif [ $CHAN -lt 7700 ]; then - BAND="B23" - elif [ $CHAN -lt 8040 ]; then - BAND="B24" - elif [ $CHAN -lt 8690 ]; then - BAND="B25" - elif [ $CHAN -lt 9040 ]; then - BAND="B26" - elif [ $CHAN -lt 9210 ]; then - BAND="B27" - elif [ $CHAN -lt 9660 ]; then - BAND="B28" - elif [ $CHAN -lt 9770 ]; then - BAND="B29" - elif [ $CHAN -lt 9870 ]; then - BAND="B30" - elif [ $CHAN -lt 9920 ]; then - BAND="B31" - elif [ $CHAN -lt 10400 ]; then - BAND="B32" - elif [ $CHAN -lt 36000 ]; then - BAND="-" - elif [ $CHAN -lt 36200 ]; then - BAND="B33" - elif [ $CHAN -lt 36350 ]; then - BAND="B34" - elif [ $CHAN -lt 36950 ]; then - BAND="B35" - elif [ $CHAN -lt 37550 ]; then - BAND="B36" - elif [ $CHAN -lt 37750 ]; then - BAND="B37" - elif [ $CHAN -lt 38250 ]; then - BAND="B38" - elif [ $CHAN -lt 38650 ]; then - BAND="B39" - elif [ $CHAN -lt 39650 ]; then - BAND="B40" - elif [ $CHAN -lt 41590 ]; then - BAND="B41" - elif [ $CHAN -lt 43590 ]; then - BAND="B42" - elif [ $CHAN -lt 45590 ]; then - BAND="B43" - elif [ $CHAN -lt 46590 ]; then - BAND="B44" - elif [ $CHAN -lt 46790 ]; then - BAND="B45" - elif [ $CHAN -lt 54540 ]; then - BAND="B46" - elif [ $CHAN -lt 55240 ]; then - BAND="B47" - elif [ $CHAN -lt 56740 ]; then - BAND="B48" - elif [ $CHAN -lt 58240 ]; then - BAND="B49" - elif [ $CHAN -lt 59090 ]; then - BAND="B50" - elif [ $CHAN -lt 59140 ]; then - BAND="B51" - elif [ $CHAN -lt 60140 ]; then - BAND="B52" - elif [ $CHAN -lt 60255 ]; then - BAND="B53" - elif [ $CHAN -lt 65536 ]; then - BAND="-" - elif [ $CHAN -lt 66436 ]; then - BAND="B65" - elif [ $CHAN -lt 67336 ]; then - BAND="B66" - elif [ $CHAN -lt 67536 ]; then - BAND="B67" - elif [ $CHAN -lt 67836 ]; then - BAND="B68" - elif [ $CHAN -lt 68336 ]; then - BAND="B69" - elif [ $CHAN -lt 68586 ]; then - BAND="B70" - elif [ $CHAN -lt 68936 ]; then - BAND="B71" - elif [ $CHAN -lt 68986 ]; then - BAND="B72" - elif [ $CHAN -lt 69036 ]; then - BAND="B73" - elif [ $CHAN -lt 69466 ]; then - BAND="B74" - elif [ $CHAN -lt 70316 ]; then - BAND="B75" - elif [ $CHAN -lt 70366 ]; then - BAND="B76" - elif [ $CHAN -lt 70546 ]; then - BAND="B85" - elif [ $CHAN -lt 70596 ]; then - BAND="B87" - elif [ $CHAN -lt 70646 ]; then - BAND="B88" - else - BAND="-" - fi -} - -decode_nr5g() { - if [ $CHAN -le 123400 ]; then - BAND="-" - elif [ $CHAN -le 130400 ]; then - BAND="n71" - elif [ $CHAN -le 143400 ]; then - BAND="-" - elif [ $CHAN -le 145600 ]; then - BAND="n29" - elif [ $CHAN -le 145800 ]; then - BAND="-" - elif [ $CHAN -le 149200 ]; then - BAND="n12" - elif [ $CHAN -le 151600 ]; then - BAND="-" - elif [ $CHAN -le 153600 ]; then - BAND="n14|n28" - elif [ $CHAN -le 158200 ]; then - BAND="n28" - elif [ $CHAN -le 160600 ]; then - BAND="n20|n28" - elif [ $CHAN -le 164200 ]; then - BAND="n20" - elif [ $CHAN -le 171800 ]; then - BAND="-" - elif [ $CHAN -le 172000 ]; then - BAND="n26" - elif [ $CHAN -le 173800 ]; then - BAND="n18|n26" - elif [ $CHAN -le 175000 ]; then - BAND="n5|n18|n26" - elif [ $CHAN -le 178800 ]; then - BAND="n5|n26" - elif [ $CHAN -le 185000 ]; then - BAND="-" - elif [ $CHAN -le 192000 ]; then - BAND="n8" - elif [ $CHAN -le 285400 ]; then - BAND="-" - elif [ $CHAN -le 286400 ]; then - BAND="n51|n76|n91|n93" - elif [ $CHAN -le 295000 ]; then - BAND="n50|n75|n92|n94" - elif [ $CHAN -le 303400 ]; then - BAND="n50|n74|n75|n92|n94" - elif [ $CHAN -le 303600 ]; then - BAND="n74" - elif [ $CHAN -le 361000 ]; then - BAND="-" - elif [ $CHAN -le 376000 ]; then - BAND="n3" - elif [ $CHAN -le 384000 ]; then - BAND="n39" - elif [ $CHAN -le 386000 ]; then - BAND="-" - elif [ $CHAN -le 398000 ]; then - BAND="n2|n25" - elif [ $CHAN -le 399000 ]; then - BAND="n25" - elif [ $CHAN -le 402000 ]; then - BAND="n70" - elif [ $CHAN -le 404000 ]; then - BAND="n34|n70" - elif [ $CHAN -le 405000 ]; then - BAND="n34" - elif [ $CHAN -le 422000 ]; then - BAND="-" - elif [ $CHAN -le 434000 ]; then - BAND="n1|n65|n66" - elif [ $CHAN -le 440000 ]; then - BAND="n65|n66" - elif [ $CHAN -le 460000 ]; then - BAND="-" - elif [ $CHAN -le 470000 ]; then - BAND="n40" - elif [ $CHAN -le 472000 ]; then - BAND="n30|n40" - elif [ $CHAN -le 480000 ]; then - BAND="n40" - elif [ $CHAN -le 496700 ]; then - BAND="-" - elif [ $CHAN -le 499000 ]; then - BAND="n53" - elif [ $CHAN -le 499200 ]; then - BAND="-" - elif [ $CHAN -le 514000 ]; then - BAND="n41|n90" - elif [ $CHAN -le 524000 ]; then - BAND="n38|n41|n90" - elif [ $CHAN -le 538000 ]; then - BAND="n7|n90" - elif [ $CHAN -le 620000 ]; then - BAND="-" - elif [ $CHAN -le 636667 ]; then - BAND="n77|n78" - elif [ $CHAN -le 646666 ]; then - BAND="n48|n77|n78" - elif [ $CHAN -le 653333 ]; then - BAND="n77|n78" - elif [ $CHAN -le 680000 ]; then - BAND="n77" - elif [ $CHAN -le 693334 ]; then - BAND="-" - elif [ $CHAN -le 733333 ]; then - BAND="n79" - else - BAND="-" - fi -} - -if [ -z "$CHAN" ]; then - BAND="-" -elif [ "$CHAN" -lt 123400 ]; then - decode_lte -elif [ "$CHAN" -lt 733333 ]; then - decode_nr5g -else - BAND="-" -fi -echo $BAND -exit diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh deleted file mode 100644 index 8e4ef40..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/fibocomdata.sh +++ /dev/null @@ -1,476 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Fibocom Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -decode_signal() { - if [ "$CRAT" -eq 4 ]; then - RSCPs=$(($RSRP - 141)) - if [ -n "$RSCP" ]; then - RSCP=$RSCP" dBm
                                                                      "$RSCPs - else - RSCP=$RSCPs - fi - if [ -n "$ECIO" ]; then - ECIO=$ECIO" dB
                                                                      "$((($RSRQ / 2) - 20)) - else - ECIO=$((($RSRQ / 2) - 20)) - fi - elif [ "$CRAT" -eq 9 ]; then - RSCPs=$(($RSRP - 157)) - if [ -n "$RSCP" ]; then - RSCP=$RSCP" dBm
                                                                      "$RSCPs - else - RSCP=$RSCPs - fi - if [ -n "$ECIO" ]; then - ECIO=$ECIO" dB
                                                                      "$((($RSRQ / 2) - 43)) - else - ECIO=$((($RSRQ / 2) - 43)) - fi - fi -} -decode_bw() { - case $BW in - "0") - BW="1.4" ;; - "1") - BW="3" ;; - "2") - BW="5" ;; - "3") - BW="10" ;; - "4") - BW="15" ;; - "5") - BW="20" ;; - *) - BW="-";; - esac -} - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "fibocominfo.gcom" "$CURRMODEM") - -OX=$(echo $OX | tr 'a-z' 'A-Z') - -SERVING=$(echo $OX | grep -o "+GTCCINFO:.\+COPN:") -if [ -z "$SERVING" ]; then - SERVING=$(echo $OX | grep -o "+GTCCINFO:.\+GTRAT") -fi - -REGXa="[12],[249],[0-9]\{3\},[0-9]\{2,3\},[0-9A-F]\{0,5\},[0-9A-F]\{0,10\},[0-9A-F]\{1,8\},[0-9A-F]\{1,8\},[15][0-9]\{1,4\},[0-9]\{1,3\},[-0-9]\{1,5\},[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}" - -REGXb="+GTCAINFO: 1,[0-9]\{1,2\},[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},[0-9]\{3,9\},[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\},[-0-9]\{1,4\},[0-9]\{1,6\},[0-9]\{1,6\},[0-9]\{1,3\},[0-9]\{1,3\}" - -REGXc="+GTCAINFO: [2-9],[0-9]\{1,2\},[0-9]\{1,5\},[0-9]\{1,3\},[0-9]\{1,3\},[-0-9]\{1,4\},[0-9]\{1,5\},[0-9]\{1,5\},[0-9]\{1,3\},[0-9]\{1,3\}" - -REGXd="+XMCI: 2,[0-9]\{3\},[0-9]\{2,3\},[^,]\+,[^,]\+,[^,]\+,\"0X[0-9A-F]\{8\}\",[^,]\+,[^,]\+,[0-9]\{1,2\},[0-9]\{1,2\},[0-9]\{1,2\}" - -REGXe="+XMCI: 4,[0-9]\{3\},[0-9]\{2,3\},[^,]\+,[^,]\+,\"0X[0-9A-F]\{4\}\",\"0X[0-9A-F]\{8\}\",[^,]\+,[^,]\+,[0-9]\{1,2\},[0-9]\{1,2\},[-0-9]\{1,5\}" - -REGXf="SCC[0-9]: 1,0,[0-9]\{1,3\},1[0-9]\{2\},[0-9]\{1,6\},[0-9]\{1,3\}" - -REGXg="2,4,,,,,[0-9A-F]\{1,5\},[0-9A-F]\{1,3\},,[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}" -REGXh="2,9,,,,,[0-9A-F]\{5\},[0-9A-F]\{1,3\},,[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}" -REGXy="1,4,[0-9]\{3\},[0-9]\{2,3\},[0-9A-F]\{0,5\},[0-9A-F]\{0,10\},[0-9]\{1,8\}, ,[0-9]\{1,2\},[0-5], ," - -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -NETMODE="-" -LBAND="-" -PCI="-" -CTEMP="-" -SINR="" -COPS_MCC="" - -CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ "$CSQ" = "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -if [ -n "$SERVING" ]; then - MODE=$(echo $SERVING | grep -o "+GTCCINFO: .\+ SERVICE CELL:") - LENM=${#MODE} - if [ $LENM -gt 25 ]; then - MODE=${MODE:11:$LENM-25} - else - MODE="-" - fi - GTCCDATA=$(echo $SERVING | grep -o "$REGXa") - GTCCDATAy=$(echo $SERVING | grep -o "$REGXy") - LTENEIGH=$(echo $SERVING | grep -o "$REGXg") - NRNEIGH=$(echo $SERVING | grep -o "$REGXh") - echo "" > /tmp/scan$CURRMODEM - for NVAL in $(echo "$LTENEIGH"); do - CHAN=$(echo $NVAL | cut -d, -f7) - CHAN=$(printf "%d" 0x$CHAN) - BAND=$(/usr/lib/rooter/chan2band.sh $CHAN) - PCIx=$(echo $NVAL | cut -d, -f8) - PCIx=$(printf "%d" 0x$PCIx) - RSSI=$(echo $NVAL | cut -d, -f11) - RSSI=$(($RSSI - 141)) - echo -e "Band : $BAND\tPCI : $PCIx\tSignal : $RSSI (dBm)" >> /tmp/scan$CURRMODEM - done - for NVAL in $(echo "$NRNEIGH"); do - CHAN=$(echo $NVAL | cut -d, -f7) - CHAN=$(printf "%d" 0x$CHAN) - BAND=$(/usr/lib/rooter/chan2band.sh $CHAN) - PCIx=$(echo $NVAL | cut -d, -f8) - PCIx=$(printf "%d" 0x$PCIx) - RSSI=$(echo $NVAL | cut -d, -f11) - RSSI=$(($RSSI - 157)) - echo -e "Band : $BAND\tPCI : $PCIx\tSignal : $RSSI (dBm)" >> /tmp/scan$CURRMODEM - done - CADATA1="" - CADATA2="" - XUDATA="" - XLDATA="" -else - GTCCDATA="" - CADATA1=$(echo $OX | grep -o "$REGXb") - CADATA2=$(echo $OX | grep -o "$REGXc") - if [ -n "$CADATA2" ]; then - if [ "$(echo $CADATA2 | cut -d, -f7)" = "65535" ]; then - CADATA2="" - fi - fi - XUDATA=$(echo $OX | grep -o "$REGXd") - XLDATA=$(echo $OX | grep -o "$REGXe") -fi -CADATA3=$(echo $OX | grep -o "$REGXf") -if [ -n "$GTCCDATA" ]; then - COPS_MCC=$(echo $GTCCDATA | cut -d, -f3) - COPS_MNC=$(echo $GTCCDATA | cut -d, -f4) - COPX="" - COPN=$(echo $OX" " | grep -o "+COPN: .\+ OK " | tr " " "," | tr -d '"' ) - if [ -n "$COPN" ]; then - COPP=$(echo $COPN" " | sed "s/.*\($COPS_MCC$COPS_MNC,.*\)\,/\1/") - if [ -n "$COPP" ]; then - COPX=$(echo $COPP | cut -d, -f2) - fi - fi - - LBAND="" - CHANNEL="" - RSCP="" - ECIO="" - PCI="" - XUDATA="" - for CCVAL in $(echo "$GTCCDATA"); do - CELLTYPE=$(echo $CCVAL | cut -d, -f1) - CRAT=$(echo $CCVAL | cut -d, -f2) - BAND=$(echo $CCVAL | cut -d, -f9) - CHAN=$(echo $CCVAL | cut -d, -f7) - CHAN=$(printf "%d" 0x$CHAN) - PCID=$(echo $CCVAL | cut -d, -f8) - PCID=$(printf "%d" 0x$PCID) - BW=$(echo $CCVAL | cut -d, -f10) - if [ "$CRAT" -eq 4 ]; then - SSINR=$(echo $CCVAL | cut -d, -f11 | grep -o "[-0-9]\{1,4\}") - if [ -n "$SSINR" ] && [ "$SSINR" != "255" ]; then - SSINR=$(($SSINR / 2))" dB" - else - SSINR="-" - fi - if [ -n "$SINR" ]; then - SINR=$SINR"
                                                                      "$SSINR - else - SINR=$SSINR - fi - if [ $BW -gt 14 ]; then - BW=$(($(echo $BW) / 5)) - else - BW="1.4" - fi - BAND=${BAND:1} - if [ "$CELLTYPE" -eq 1 ]; then - BAND="B"$(($BAND + 0))" (Bandwidth: "$BW" MHz)" - else - BAND="B"$(($BAND + 0))" (CA, Bandwidth: "$BW" MHz)" - fi - fi - if [ "$CRAT" -eq 9 ]; then - SSINR=$(echo $CCVAL | cut -d, -f11 | grep -o "[0-9]\{1,3\}") - if [ -n "$SSINR" ] && [ "$SSINR" != "255" ]; then - SSINR=$((($SSINR - 47) / 2))" dB" - else - SSINR="-" - fi - if [ -n "$SINR" ]; then - SINR=$SINR"
                                                                      "$SSINR - else - SINR=$SSINR - fi - if [ "$CELLTYPE" -eq 1 ]; then - BAND="n"${BAND:2}" (Bandwidth: "$BW" MHz)" - else - BAND="n"${BAND:2}" (CA, Bandwidth: "$BW" MHz)" - fi - fi - if [ -n "$LBAND" ]; then - LBAND=$LBAND"
                                                                      "$BAND - else - LBAND=$BAND - fi - if [ -n "$CHANNEL" ]; then - CHANNEL=$CHANNEL","$CHAN - else - CHANNEL=$CHAN - fi - if [ -n "$PCI" ]; then - PCI=$PCI","$PCID - else - PCI=$PCID - fi - if [ "$CELLTYPE" -eq 1 ]; then - RSRP=$(echo $CCVAL | cut -d, -f13) - RSRQ=$(echo $CCVAL | cut -d, -f14) - if [ "$RSRP" -ne 255 ] && [ "$RSRQ" -ne 255 ]; then - decode_signal - RSSI=$(rsrp2rssi $RSCPs $BW) - CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" - CSQ=$((($RSSI + 113) / 2)) - CSQ_RSSI=$RSSI" dBm" - fi - fi - done -fi - -if [ -n "$GTCCDATAy" ]; then - CHANNEL=$(echo $GTCCDATAy | cut -d, -f7) - BW=$(echo $GTCCDATAy | cut -d, -f10) - decode_bw - LBAND="B"$(echo $GTCCDATAy | cut -d, -f9)" (Bandwidth: "$BW" MHz)" - XUDATA="" -fi - -if [ -n "$XLDATA" ]; then - XLDATA=$(echo "${XLDATA//[\" ]/}") - XLEC=$(echo $OX | grep -o "+XLEC: [01],[0-9]\+,[0-5],.*BAND_LTE_[0-9]\{1,2\},[^ ]\+") - MODE="LTE" - PCI=$(echo $XLDATA | cut -d, -f6) - PCI=$(printf "%d" $PCI) - CHANNEL=$(echo $XLDATA | cut -d, -f7) - CHANNEL=$(printf "%d" $CHANNEL) - LBAND=$($ROOTER/chan2band.sh "$CHANNEL") - if [ -n "$XLEC" ]; then - BW=$(echo $XLEC | cut -d, -f3) - RAWLIST=$(echo $XLEC | grep -o "BAND_LTE_[0-9]\{1,2\}.\+" | grep -o "[,0-9]*" | tr ',' ' ') - BANDLIST="" - for BAND in $(echo "$RAWLIST"); do - if [ -n "$BAND" -a "$BAND" != "0" ]; then - if [ -n "$BANDLIST" ]; then - BANDLIST="$BANDLIST,$BAND" - else - BANDLIST="$BAND" - fi - fi - done - BAND="B"$(echo $BANDLIST | cut -d, -f1) - if [ "$BAND" = "$LBAND" ]; then - decode_bw - LBAND=$LBAND" (Bandwidth $BW MHz)" - NUMBR=$(echo $XLEC | cut -d, -f2) - for JJ in $(seq 2 $NUMBR); do - BAND=$(echo $BANDLIST | cut -d, -f$JJ) - if [ -n "$BAND" -a "$BAND" != "0" ]; then - KK=$(($JJ + 2)) - BW=$(echo $XLEC | cut -d, -f$KK) - decode_bw - if [ $BW != "-" ]; then - LBAND=$LBAND"
                                                                      B$BAND (CA, Bandwidth $BW MHz)" - fi - fi - done - fi - else - XLEC=$(echo $OX | grep -o "+XLEC: 0,[1-9],[0-5]") - if [ -n "$XLEC" ]; then - BW=$(echo $XLEC | cut -d, -f3) - decode_bw - LBAND=$LBAND" (Bandwidth $BW MHz)" - fi - fi - RSRP=$(echo $XLDATA | cut -d, -f10) - if [ $RSRP == 0 ]; then - RSRP=1 - fi - RSCP=$(($RSRP - 141)) - ECIO=$(echo $XLDATA | cut -d, -f11) - ECIO=$((($ECIO / 2) - 20)) - SINR=$(echo $XLDATA | cut -d, -f12 | grep -o "[-0-9]\{1,4\}") - if [ -n "$SINR" ] && [ "$SINR" != "255" ]; then - SINR=$(($SINR / 2))" dB" - fi - RSSI=$(rsrp2rssi $RSCP $BW) - CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" - CSQ=$((($RSSI + 113) / 2)) - CSQ_RSSI=$RSSI" dBm" -fi -if [ -n "$XUDATA" ]; then - MODE="UMTS" - CHANNEL=$(echo $XUDATA | cut -d, -f7) - CHANNEL=${CHANNEL:1:10} - CHANNEL=$(printf "%d" $CHANNEL) - RSCP=$(echo $XUDATA | cut -d, -f11) - RSCP=$(($RSCP - 121)) - ECIO=$(echo $XUDATA | cut -d, -f12) - ECIO=$((($ECIO / 2) - 24)) -fi -if [ -n "$CADATA1" ]; then - RSCP="" - ECIO="" - BW=$(echo $CADATA1 | cut -d, -f13) - decode_bw - BWD=$BW - BW=$(echo $CADATA1 | cut -d, -f14) - decode_bw - BWU=$BW - LBAND="B"$(echo $CADATA1 | cut -d, -f2)" (Bandwidth $BWD MHz Down | $BWU MHz Up)" - CHANNEL=$(echo $CADATA1 | cut -d, -f11) - MODE="LTE" - CRAT="4" - RSRP=$(echo $CADATA1 | cut -d, -f8) - RSRQ=$(echo $CADATA1 | cut -d, -f9) - if [ "$RSRP" -ne 255 ] && [ "$RSRQ" -ne 255 ]; then - decode_signal - RSSI=$(rsrp2rssi $RSCPs $BWD) - CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" - CSQ=$((($RSSI + 113) / 2)) - CSQ_RSSI=$RSSI" dBm" - else - RSRP="-" - RSRQ="-" - fi - PCI=$(echo $CADATA1 | cut -d, -f7) -fi -if [ -n "$CADATA2" ]; then - CADATA2=$(echo "${CADATA2//[ ]/}") - for CAVAL in $(echo "$CADATA2"); do - BW=$(echo $CAVAL | cut -d, -f9) - decode_bw - BWD=$BW - BW=$(echo $CAVAL | cut -d, -f10) - decode_bw - BWU=$BW - LBAND=$LBAND"
                                                                      B"$(echo $CAVAL | cut -d, -f2) - if [ $BWU = "-" ]; then - LBAND=$LBAND" (CA, Bandwidth: "$BWD" MHz)" - else - LBAND=$LBAND" (CA, Bandwidth $BWD MHz Down | $BWU MHz Up)" - fi - CHAN=$(echo $CAVAL | cut -d, -f7) - CHANNEL=$(echo "$CHANNEL", "$CHAN") - PCIX=$(echo $CAVAL | cut -d, -f3) - PCI=$(echo "$PCI", "$PCIX") - done -fi -if [ -n "$CADATA3" ]; then - CADATA3=$(echo "${CADATA3//[ ]/}") - for CAVAL in $(echo "$CADATA3"); do - BAND=$(echo $CAVAL | cut -d, -f3) - BAND=${BAND:1} - PCIX=$(echo $CAVAL | cut -d, -f4) - PCI=$(echo "$PCI", "$PCIX") - CHAN=$(echo $CAVAL | cut -d, -f5) - CHANNEL=$(echo "$CHANNEL", "$CHAN") - BW=$(echo $CAVAL | cut -d, -f6) - if [ $BW -gt 14 ]; then - BW=$(($(echo $BW) / 5)) - else - BW="1.4" - fi - LBAND=$LBAND"
                                                                      B"$(($BAND + 0))" (CA, Bandwidth: "$BW" MHz)" - done -fi - -MTEMP=$(echo $OX | grep -o "+MTSM: [0-9.]\{1,5\}") -if [ -n "$MTEMP" ]; then - CTEMP=$(echo $MTEMP | grep -o "[0-9.]\{1,5\}")$(printf "\xc2\xb0")"C" -fi - -MODTYPE="9" -MRAT=$(echo $OX | grep -o "+GTRAT: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ -n "$MRAT" ]; then -# If user inserted different SIM card, the Rat order will recover to default value (AT Commands manual) - case $MRAT in - "2" ) - NETMODE="5" ;; - "3" ) - NETMODE="7" ;; - "14" ) - NETMODE="9" ;; - "17"|"20" ) - NETMODE="8" ;; - * ) - NETMODE="1" ;; - esac -fi -XACT=$(echo $OX | grep -o "+XACT: [0-9]" | grep -o "[0-9]") -if [ -n "$XACT" ]; then - PREF=$(echo $OX | grep -o "+XACT: [0-9],[0-9]" | grep -o ",[0-9]") - case $XACT in - "1" ) - NETMODE="5" ;; - "2" ) - NETMODE="7" ;; - "4" ) - if [ "$PREF" = ",1" ]; then - NETMODE="4" - else - NETMODE="6" - fi ;; - * ) - NETMODE="6" ;; - esac -fi -CMODE=$(uci -q get modem.modem$CURRMODEM.cmode) -if [ "$CMODE" = 0 ]; then - NETMODE="10" -fi -if [ -z "$SINR" ]; then - SINR="-" -fi - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$CTEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file -if [ -n "$COPS_MCC" ]; then - echo 'COPS_MCC="'"$COPS_MCC"'"' >> /tmp/signal$CURRMODEM.file - echo 'COPS_MNC="'"$COPS_MNC"'"' >> /tmp/signal$CURRMODEM.file -fi -if [ -n "$COPX" ]; then - echo 'COPS="'"$COPX"'"' >> /tmp/signal$CURRMODEM.file -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh deleted file mode 100644 index 6ac00c2..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/gettype.sh +++ /dev/null @@ -1,254 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Get ICCID $CURRMODEM" "$@" -} - -echo "0" > /tmp/block - -decode_crsm() { - i=0 - while [ $i -lt $length ]; do - c1=${sstring:$i:1} - let 'j=i+1' - c2=${sstring:$j:1} - xstring=$xstring$c2$c1 - let 'i=i+2' - done -} - -CURRMODEM=$1 -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "gettype.gcom" "$CURRMODEM") -OX=$($ROOTER/common/processat.sh "$OX") - -MANUF=$(echo "$OX" | awk -F[:] '/Manufacturer:/ { print $2}') - -if [ -z "$MANUF" ]; then - ATCMDD="AT+CGMI" - MANUF=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - MANUF=$(echo $MANUF) - MANUF=$(echo "${MANUF//[\"]/}") - MANUF=${MANUF::-3} - MPREFIX=${MANUF::8} - if [ "$MPREFIX" = "AT+CGMI " ]; then - MANUF=$(echo $MANUF | cut -c 9-) - fi - MPREFIX=${MANUF::7} - if [ "$MPREFIX" = "+CGMI: " ]; then - MANUF=$(echo $MANUF | cut -c 8-) - fi -fi -if [ -z "$MANUF" ]; then - MANUF=$(uci get modem.modem$CURRMODEM.manuf) -fi - -MODEL=$(echo "$OX" | awk -F[,\ ] '/^\+MODEL:/ {print $2}') - -if [ -z "$MODEL" ]; then - ATCMDD="AT+CGMM" - MODEL=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - MODEL=$(echo $MODEL) - MODEL=$(echo "${MODEL//[\"]/}") - MODEL=${MODEL::-3} - MPREFIX=${MODEL::8} - if [ "$MPREFIX" = "AT+CGMM " ]; then - MODEL=$(echo $MODEL | cut -c 9-) - fi - MPREFIX=${MODEL::7} - if [ "$MPREFIX" = "+CGMM: " ]; then - MODEL=$(echo $MODEL | cut -c 8-) - fi - MODEL=$(echo $MODEL | cut -d, -f1) -fi -if [ -z "$MODEL" ]; then - MODEL=$(uci get modem.modem$CURRMODEM.model) -fi - -uci set modem.modem$CURRMODEM.manuf="$MANUF" -uci set modem.modem$CURRMODEM.model="$MODEL" -uci commit modem - -$ROOTER/signal/status.sh $CURRMODEM "$MANUF $MODEL" "Connecting" - -IMEI=$(echo "$OX" | awk -F[,\ ] '/^\IMEI:/ {print $2}') - -if [ -z "$IMEI" ]; then - ATCMDD="AT+CGSN" - IMEI=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - IMEI=$(echo $IMEI | grep -o "[0-9]\{15\}") -fi - -if [ -z "$IMEI" ]; then - ATCMDD="ATI5" - IMEI=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - IMEI=$(echo $IMEI | grep -o "[0-9]\{15\}") -fi - -if [ -n "$IMEI" ]; then - IMEI=$(echo "$IMEI" | sed -e 's/"//g') - IMEI=${IMEI:0:15} -else - IMEI="Unknown" -fi -uci set modem.modem$CURRMODEM.imei=$IMEI - -IDP=$(uci get modem.modem$CURRMODEM.idP) -IDV=$(uci get modem.modem$CURRMODEM.idV) - -echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM -echo "$IMEI" >> /tmp/msimdatax$CURRMODEM - -lua $ROOTER/signal/celltype.lua "$MODEL" $CURRMODEM -source /tmp/celltype$CURRMODEM -rm -f /tmp/celltype$CURRMODEM - -uci set modem.modem$CURRMODEM.celltype=$CELL -uci commit modem - -$ROOTER/luci/celltype.sh $CURRMODEM - -M2=$(echo "$OX" | grep -o "+CNUM:[^,]*,[^,]*,[0-9]\{3\}")"," -M2=${M2:6} -CNUMx=$(echo "$M2" | cut -d, -f1 | cut -d\" -f2) -CNUMx=$(echo $CNUMx) -CNUM=$(echo "$M2" | cut -d, -f2 | cut -d\" -f2) -CNUMtype=$(echo "$M2" | cut -d, -f3) -if [ "${CNUM:0:1}" != "+" -a "$CNUMtype" == "145" ]; then - CNUM="+"$CNUM -fi -if [ -z "$CNUM" ]; then - CNUM="*" -fi -if [ -z "$CNUMx" ]; then - CNUMx="*" -fi - -NLEN=$(echo "$OX" | awk -F[,\ ] '/^\+CPBR:/ {print $4}') -if [ "x$NLEN" != "x" ]; then - NLEN=$(echo "$NLEN" | sed -e 's/"//g') -else - NLEN="14" -fi -echo 'NLEN="'"$NLEN"'"' > /tmp/namelen$CURRMODEM - -ATCMDD="ATE1" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -ATCMDD="AT+CTZU=1" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -ATCMDD="AT\$QCPBMPREF?" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -PBzero=$(echo "$OX" | grep "0") -if [ -n "$PBzero" ]; then - ATCMDD="AT\$QCPBMPREF=1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -fi -ATCMDD="AT+CGDCONT?" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -ATCMDD="AT\$QCPDPIMSCFGE?" -OX=$OX$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -OX=$(echo $OX | tr 'a-z' 'A-Z') -OX=$(echo "${OX//[ ]/}") -imsAPN=$(echo $OX | grep -o "+CGDCONT:2,[^,]\+,\"IMS\"") -ims_on=$(echo $OX | grep -o "\$QCPDPIMSCFGE:2,1,") -if [ -n "$imsAPN" -a -z "$ims_on" ]; then - ATCMDD="AT\$QCPDPIMSCFGE=2,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -fi -if [ "$IDV" == "2c7c" ]; then - ATCMDD="AT+QLWCFG=\"startup\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - LWon=$(echo "$OX" | grep "1") - if [ -n "$LWon" ]; then - ATCMDD="AT+QLWCFG=\"startup\",0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ATCMDD="AT+QCFG=\"ims\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - IMSon=$(echo "$OX" | grep "1") - if [ -z "$IMSon" ]; then - ATCMDD="AT+QCFG=\"ims\",1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi -fi -ATCMDD="AT+CIMI" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -OX=$($ROOTER/common/processat.sh "$OX") -ERROR="ERROR" -if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` -then - ATCMDD="AT+CRSM=176,28423,0,0,9" - sstring=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" | grep -o "[0-9F]\{18\}") - if [ -n "$sstring" ]; then - length=${#sstring} - decode_crsm - IMSI=${xstring:3} - else - IMSI="Unknown" - fi -else - OX=${OX//[!0-9]/} - IMSIL=${#OX} - IMSI=${OX:0:$IMSIL} -fi -echo "$IMSI" >> /tmp/msimdatax$CURRMODEM -uci set modem.modem$CURRMODEM.imsi=$IMSI - -idV=$(uci -q get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) -if [ $idV = 0e8d ]; then - ATCMDD="AT+CCID" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - ICCID="Unknown" - else - ICCID=$(echo "$OX" | awk -F[,\ ] '/^\+CCID:/ {print $2}') - if [ "x$ICCID" != "x" ]; then - sstring=$(echo "$ICCID" | sed -e 's/"//g') - ICCID=$sstring - else - ICCID="Unknown" - fi - fi -else - ATCMDD="AT+CRSM=176,12258,0,0,10" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - ICCID="Unknown" - else - ICCID=$(echo "$OX" | awk -F[,\ ] '/^\+CRSM:/ {print $4}') - if [ "x$ICCID" != "x" ]; then - sstring=$(echo "$ICCID" | sed -e 's/"//g') - length=${#sstring} - xstring="" - decode_crsm - ICCID=$xstring - else - ICCID="Unknown" - fi - fi -fi -uci set modem.modem$CURRMODEM.iccid=$ICCID -uci commit modem -if [ -e /etc/config/modeinfo ]; then - uci set modeinfo.global.iccid$CURRMODEM=$ICCID - uci commit modeinfo -fi -echo "$ICCID" >> /tmp/msimdatax$CURRMODEM -echo "0" >> /tmp/msimdatax$CURRMODEM -echo "$CNUM" > /tmp/msimnumx$CURRMODEM -echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM - -mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM -mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM - -rm -f /tmp/block diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh deleted file mode 100644 index 8134784..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/huaweidata.sh +++ /dev/null @@ -1,299 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Huawei Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -fix_data() { - O=$($ROOTER/common/processat.sh "$OY") -} - -process_csq() { - CSQ=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $2}') - [ "x$CSQ" = "x" ] && CSQ=-1 - if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then - CSQ_PER=$(($CSQ * 100/31)) - CSQ_RSSI=$((2 * CSQ - 113)) - CSQX=$CSQ_RSSI - [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI - [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI - CSQ_PER=$CSQ_PER"%" - CSQ_RSSI=$CSQ_RSSI" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi -} - -process_huawei() { - CSNR=$(echo "$O" | awk -F[,\ ] '/^\^CSNR:/ {print $2}') - if [ "x$CSNR" != "x" ]; then - RSCP=$CSNR - CSNR=$(echo "$O" | awk -F[,\ ] '/^\^CSNR:/ {print $3}') - if [ "x$CSNR" != "x" ]; then - ECIO=$CSNR - else - ECIO=`expr $RSCP - $CSQX` - fi - else - EC=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $4}') - if [ "x$EC" != "x" ]; then - ECIO=$EC - EX=$(printf %.0f $ECIO) - RSCP=`expr $CSQX + $EX` - fi - fi - - HCSQ=$(echo "$O" | grep -o "\^HCSQ:[ ]*\"LTE\",[^,]*,[^,]*,[0-9]\{1,3\}") - if [ -n "$HCSQ" ]; then - SINR=$(echo $HCSQ | cut -d, -f4) - if [ $SINR -lt 255 ]; then - SINR=$((($SINR / 5) - 20)) - else - SINR="-" - fi - fi - - LTERSRP=$(echo "$O" | awk -F[,\ ] '/^\^LTERSRP:/ {print $2}') - if [ "x$LTERSRP" != "x" ]; then - RSCP=$LTERSRP - LTERSRP=$(echo "$O" | awk -F[,\ ] '/^\^LTERSRP:/ {print $3}') - if [ "x$LTERSRP" != "x" ]; then - ECIO=$LTERSRP - else - ECIO=`expr $RSCP - $CSQX` - fi - fi - LBANDS=$(echo $O | grep -o "\^HFREQINFO:[0-9,]\+") - LBAND="" - CHANNEL="" - printf '%s\n' "$LBANDS" | while read LBANDL; do - CHANN=$(echo $LBANDL | cut -d, -f4 | grep -o "[0-9]\{2,6\}") - if [ -z "$CHANN" ]; then - LBAND="" - CHANNEL="" - else - BWU=$(($(echo $LBANDL | cut -d, -f9) / 1000)) - BWD=$(($(echo $LBANDL | cut -d, -f6) / 1000)) - LBANDL=$(echo $LBANDL | cut -d, -f3) - if [ -z "$LBANDL" ]; then - LBAND="" - else - if [ -n "$LBAND" ]; then - LBAND=$LBAND" aggregated with:
                                                                      " - fi - LBAND=$LBAND"B"$LBANDL" (Bandwidth $BWD MHz Down | $BWU MHz Up)" - fi - if [ -n "$CHANN" ]; then - if [ -n "$CHANNEL" ]; then - CHANNEL=$CHANNEL", "$CHANN - else - CHANNEL=$CHANN - fi - fi - - fi - { - echo "$LBAND" - echo "$CHANNEL" - } > /tmp/lbandvar$CURRMODEM - done - if [ -e /tmp/lbandvar$CURRMODEM ]; then - { - read LBAND - read CHANNEL - } < /tmp/lbandvar$CURRMODEM - rm /tmp/lbandvar$CURRMODEM - fi - if [ -z "$LBAND" ]; then - LBAND="-" - fi - if [ -z "$CHANNEL" ]; then - CHANNEL="-" - fi - - NETMODE="0" - SYSCFG=$(echo "$O" | awk -F[,\"] '/^\^SYSCFGEX:/ {print $2}') - if [ "x$SYSCFG" != "x" ]; then - MODTYPE="3" - case $SYSCFG in - "00" ) - NETMODE="1" - ;; - "01" ) - NETMODE="3" - ;; - "02" ) - NETMODE="5" - ;; - "03" ) - NETMODE="7" - ;; - * ) - ACQ=${SYSCFG:0:2} - case $ACQ in - "01" ) - NETMODE="2" - ;; - "02" ) - NETMODE="4" - ;; - "03" ) - NETMODE="6" - ;; - esac - ;; - esac - else - SYSCFG=$(echo "$O" | awk -F[,\ ] '/^\^SYSCFG:/ {print $2}') - if [ "x$SYSCFG" != "x" ]; then - MODTYPE="4" - case $SYSCFG in - "7" ) - NETMODE="1" - ;; - "13" ) - NETMODE="3" - ;; - "14" ) - NETMODE="5" - ;; - * ) - SYSCFG=$(echo "$O" | awk -F[,\ ] '/^\^SYSCFG:/ {print $3}') - case $SYSCFG in - "0" ) - NETMODE="1" - ;; - "1" ) - NETMODE="2" - ;; - "2" ) - NETMODE="4" - ;; - esac - ;; - esac - fi - fi - - NETMODEx=$(uci get modem.modem$CURRMODEM.netmode) - if [ "$NETMODE" != "$NETMODEx" ]; then - uci set modem.modem$CURRMODEM.netmode="$NETMODE" - uci commit modem - fi - - MODE="-" - TECH=$(echo "$O" | awk -F[,] '/^\^SYSINFOEX:/ {print $9}' | sed 's/"//g') - if [ "x$TECH" != "x" ]; then - MODE="$TECH" - fi - - if [ "x$MODE" = "x-" ]; then - TECH=$(echo "$O" | awk -F[,\ ] '/^\^SYSINFO:/ {print $8}') - if [ "x$TECH" != "x" ]; then - case $TECH in - 17*) MODE="HSPA+ (64QAM)";; - 18*) MODE="HSPA+ (MIMO)";; - 1*) MODE="GSM";; - 2*) MODE="GPRS";; - 3*) MODE="EDGE";; - 4*) MODE="WCDMA";; - 5*) MODE="HSDPA";; - 6*) MODE="HSUPA";; - 7*) MODE="HSPA";; - 9*) MODE="HSPA+";; - *) MODE=$TECH;; - esac - fi - fi - - TEMP=$(echo "$O" | awk -F[,] '/^\^CHIPTEMP:/ {print $2}') - if [ "x$TEMP" != "x" ]; then - TEMP=$((TEMP / 10))$(printf "\xc2\xb0")"C" - else - TEMP="unknown" - fi - - CMODE=$(uci get modem.modem$CURRMODEM.cmode) - if [ $CMODE = 0 ]; then - NETMODE="10" - fi -} - -CSQ="-" -CSQ_PER="-" -CSQ_RSSI="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -CHANNEL="-" -LBAND="-" -MODETYPE="-" -NETMODE="-" -TEMP="-" -PCI="-" -SINR="-" - -OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "huaweiinfo.gcom" "$CURRMODEM") - -fix_data -process_csq -process_huawei - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -if [ $CSQ = "-" ]; then - log "$OY" -fi - -ENB="0" -if [ -e /etc/config/failover ]; then - ENB=$(uci get failover.enabled.enabled) -fi -if [ $ENB = "1" ]; then - exit 0 -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh deleted file mode 100644 index 5d096ad..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/lockchk.sh +++ /dev/null @@ -1,104 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Lock Provider" "$@" -} - -setautocops() { - if [ "$MODTYPE" = "2" -o "$MODTYPE" = "6" -o "$MODTYPE" = "8" -o "$MODTYPE" = "11" ]; then - NETMODE=$(uci get modem.modem$CURRMODEM.netmode) - case $NETMODE in - "3") - ATCMDD="AT+COPS=0,,,0" ;; - "5") - ATCMDD="AT+COPS=0,,,2" ;; - "7") - ATCMDD="AT+COPS=0,,,7" ;; - "8") - ATCMDD="AT+COPS=0,,,13" ;; - "9") - ATCMDD="AT+COPS=0,,,12" ;; - *) - ATCMDD="AT+COPS=0" ;; - esac - else - ATCMDD="AT+COPS=0" - fi - OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - CLOG=$(uci get modem.modeminfo$CURRMODEM.log) - if [ $CLOG = "1" ]; then - log "$OX" - fi - exit 0 -} - -CURRMODEM=$1 -if [ -e /usr/lib/netroam/lock.sh ]; then - if [ -e /tmp/rlock ]; then - /usr/lib/netroam/lock.sh $CURRMODEM - exit 0 - fi -fi -CPORT=/dev/ttyUSB$(uci get modem.modem$CURRMODEM.commport) -MODTYPE=$(uci get modem.modem$CURRMODEM.modemtype) -LOCK=$(uci get modem.modeminfo$CURRMODEM.lock) -if [ "$LOCK" = "2" ]; then - LOCK="4" -fi -ATCMDD="AT+COPS=3,2;+COPS?" -OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -COPSMODE=$(echo $OX | grep -o "+COPS:[ ]\?[014]" | grep -o "[014]") -COPSPLMN=$(echo $OX | grep -o "[0-9]\{5,6\}") - -if [ -z "$LOCK" -o "$LOCK" = "0" ]; then - if [ "$COPSMODE" = "0" ]; then - exit 0 - fi - setautocops -fi -MCC=$(uci -q get modem.modeminfo$CURRMODEM.mcc) -LMCC=${#MCC} -if [ $LMCC -ne 3 ]; then - setautocops -fi -MNC=$(uci -q get modem.modeminfo$CURRMODEM.mnc) -if [ -z $MNC ]; then - setautocops -fi -LMNC=${#MNC} -if [ $LMNC -eq 1 ]; then - MNC=0$MNC -fi -if [ "$COPSMODE$COPSPLMN" = "$LOCK$MCC$MNC" ]; then - exit 0 -fi -if [ "$MODTYPE" = "2" -o "$MODTYPE" = "6" -o "$MODTYPE" = "8" -o "$MODTYPE" = "11" ]; then - NETMODE=$(uci get modem.modem$CURRMODEM.netmode) - case $NETMODE in - "3") - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",0" ;; - "5") - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",2" ;; - "7") - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",7" ;; - "8") - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",13" ;; - "9") - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\",12" ;; - *) - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\"" ;; - esac -else - ATCMDD="AT+COPS=$LOCK,2,\"$MCC$MNC\"" -fi - -OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -CLOG=$(uci get modem.modeminfo$CURRMODEM.log) -if [ $CLOG = "1" ]; then - log "Error While Locking to Provider" - log "$OX" -else - log "Locked to Provider $MCC $MNC" -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh deleted file mode 100644 index c552b0a..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/mdm9215data.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "MDM9215 Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "mdm9215info.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') -O=$($ROOTER/common/processat.sh "$OX") -O=$(echo $O) - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -TEMP="-" -PCI="-" -SINR="-" - -Oup=$(echo $O | tr 'a-z' 'A-Z') - -CSQ=$(echo $O | grep -o "CSQ: [0-9]\+" | grep -o "[0-9]\+") -[ "x$CSQ" = "x" ] && CSQ=-1 - -if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then - CSQ_PER=$(($CSQ * 100/31)) - CSQ_RSSI=$((2 * CSQ - 113)) - CSQX=$CSQ_RSSI - [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI - [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI - CSQ_PER=$CSQ_PER"%" - CSQ_RSSI=$CSQ_RSSI" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -MODE="-" -WS46=$(echo $O" " | grep -o "+COPS: .\+ OK " | tr " " ",") -TECH=$(echo $WS46 | cut -d, -f5) - -if [ ! -z "$TECH" ]; then - MODE=$TECH - SGCELL=$(echo $O" " | grep -o "\$QCSQ .\+ OK " | tr " " "," | tr ",:" ",") - - WS46=$(echo $O" " | grep -o "AT\$QCSYSMODE? .\+ OK ") - WS46=$(echo "$WS46" | sed -e "s/AT\$QCSYSMODE? //g") - WS46=$(echo "$WS46" | sed -e "s/ OK//g") - - case $MODE in - *) - RSCP=$(echo $SGCELL | cut -d, -f8) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - ECIO=$(echo $SGCELL| cut -d, -f5) - ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") - RSSI=$(echo $SGCELL | cut -d, -f4) - CSQ_RSSI="-"$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" - ;; - "7") - RSSI=$(echo $SGCELL | cut -d, -f4) - CSQ_RSSI=$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" - RSCP=$(echo $SGCELL | cut -d, -f8) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - ECIO=$(echo $SGCELL| cut -d, -f4) - ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") - ;; - esac - - MODE=$WS46 -fi - -NETMODE="1" -MODTYPE="8" - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -if [ "$CSQ" = "-" ]; then - log "$OX" -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh deleted file mode 100644 index 360a708..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/meigdata.sh +++ /dev/null @@ -1,281 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Meig Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "meiginfo.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') - -O=$($ROOTER/common/processat.sh "$OX") -O=$(echo $O) -OX=$(echo $OX) - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -TEMP="-" -PCI="-" -SINR="-" - -CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ "$CSQ" = "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -MODE="-" -PSRAT=$(echo $O" " | grep -o "+PSRAT: .\+ OK " | tr " " ",") -TECH=$(echo $PSRAT | cut -d, -f2) -if [ -n "$TECH" ]; then - MODE=$TECH -fi - -ATECH=$(echo $OX | grep -o "+SGCELLINFOEX:[^,]\{2,6\}," | grep -o ":[ ]\?[-A-Z5]\{2,6\}" | grep -o "[-A-Z5]\{2,6\}") -if [ -n "$ATECH" ]; then - MODE=$ATECH -fi - -SGCELL=$(echo $O" " | grep -o "+SGCELLINFO: .\+ OK " | tr " " ",") - -MODEx=$MODE -case $MODEx in - "TD-LTE"|"FDD-LTE"|"FDD" ) - RSSI=$(echo $SGCELL | cut -d, -f5) - CSQ_RSSI="-"$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" - RSCP=$(echo $SGCELL | cut -d, -f6) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - ECIO=$(echo $SGCELL| cut -d, -f7) - ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") - SSINR=$(echo $SGCELL | cut -d, -f8 | grep -o "[0-9]\{1,3\}") - if [ -n "$SSINR" -a "$SSINR" -le "250" ]; then - SINR=$((($SSINR / 5) - 20))" dB" - fi - LBAND=$(echo $SGCELL | cut -d, -f9) - LBAND=$(echo $LBAND | grep -o "[0-9]\{1,5\}") - let LBAND=LBAND-119 - LBAND="B"$LBAND - CHANNEL=$(echo $SGCELL | cut -d, -f10) - CHANNEL=$(echo $CHANNEL | grep -o "[0-9]\{1,5\}") - ICELL=$(echo $O" " | grep -o "+CELLINFO: .\+ OK " | tr " " ",") - PCI=$(echo $ICELL | cut -d, -f18) - PCI=$(echo $PCI | grep -o "[0-9]\{1,5\}") - if [ $MODE = "FDD" ]; then - MODE="FDD LTE" - fi - ;; - "LTE"|"EN-DC" ) - SGC=$(echo $OX | grep -o "+SGCELLINFOEX:[ ]\?[-CDELNTE]\{3,5\},.\+AT+CELLINFO") - MODE=$(echo $SGC | cut -d, -f2) - PCI=$(echo $SGC | cut -d, -f6) - LBAND="B"$(echo $SGC | cut -d, -f10) - BW=$(echo $SGC | cut -d, -f11 | grep -o "[0-9]\{1,3\}") - if [ $BW -gt 14 ]; then - let BW=BW/5 - else - BW="1.4" - fi - LBAND=$LBAND" (Bandwidth $BW Mhz)" - CHANNEL=$(echo $SGC | cut -d, -f12) - RSSI=$(echo $SGC | cut -d, -f14) - CSQ_RSSI=$(echo $RSSI | grep -o "[-0-9]\{1,3\}")" dBm" - RSCP=$(echo $SGC | cut -d, -f15) - ECIO=$(echo $SGC| cut -d, -f16) - SINR=$(echo $SGC | cut -d, -f18)" dB" - if [ $MODEx == "EN-DC" ]; then - NRSINR=$(echo $SGC | cut -d, -f31 | grep -o "[-0-9]\{1,4\}") - NRBAND=$(echo $SGC | cut -d, -f32 | grep -o "[0-9]\{1,3\}") - NRCHAN=$(echo $SGC | cut -d, -f33 | grep -o "[0-9]\{6,7\}") - NRBW=$(echo $SGC | cut -d, -f34 | grep -o "[0-9]\{1,3\}") - if [ -n "$NRBAND" -a -n "$NRCHAN" -a -n "$NRBW" -a -n $NRSINR ]; then - NRRSRP=$(echo $SGC | cut -d, -f29 | grep -o "[-0-9]\{2,4\}") - NRRSRQ=$(echo $SGC | cut -d, -f30 | grep -o "[-0-9]\{2,4\}") - NRPCI=$(echo $SGC | cut -d, -f35 | grep -o "[0-9]\{1,3\}") - let NRBW=NRBW/5 - LBAND=$LBAND"
                                                                      n"$NRBAND" (Bandwidth "$NRBW" MHz)" - RSCP=$RSCP" dBm
                                                                      "$NRRSRP - ECIO=$ECIO" dBm
                                                                      "$NRRSRQ - SINR=$SINR"
                                                                      "$((($NRSINR / 5) - 20))" dB" - CHANNEL=$CHANNEL","$NRCHAN - PCI=$PCI","$NRPCI - fi - fi - ;; - "5G" ) - SGC=$(echo $OX | grep -o "+SGCELLINFOEX:[ ]\?5G,.\+AT+CELLINFO") - MODE=$(echo $SGC | cut -d, -f2) - PCI=$(echo $SGC | cut -d, -f6) - LBAND="n"$(echo $SGC | cut -d, -f8) - BW=$(echo $SGC | cut -d, -f9 | grep -o "[0-9]\{1,3\}") - let BW=BW/5 - LBAND=$LBAND" (Bandwidth $BW Mhz)" - CHANNEL=$(echo $SGC | cut -d, -f12) - RSCP=$(echo $SGC | cut -d, -f15) - ECIO=$(echo $SGC| cut -d, -f16) - SINR=$(echo $SGC | cut -d, -f17) - SINR=$((($SINR / 5) - 20))" dB" - ;; - "HSPA+"|"HSUPA"|"HSDPA"|"WCDMA" ) - if [ -n "$ATECH" ]; then - SGC=$(echo $OX | grep -o "WCDMA,[0-9]\{3\},.\+AT+CELLINFO" | tr ' ' ',') - CHANNEL=$(echo $SGC | cut -d, -f11) - ECIO=$(echo $SGC | cut -d, -f14) - RSCP=$(echo $SGC | cut -d, -f16) - else - RSCP=$(echo $SGCELL | cut -d, -f11) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - ECIO=$(echo $SGCELL| cut -d, -f12) - ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") - CHANNEL=$(echo $SGCELL | cut -d, -f8) - CHANNEL=$(echo $CHANNEL | grep -o "[0-9]\{1,4\}") - RSSI=$(echo $SGCELL | cut -d, -f10) - CSQ_RSSI=$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" - fi - ;; - *) - RSCP=$(echo $SGCELL | cut -d, -f10) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - CHANNEL=$(echo $SGCELL | cut -d, -f8) - CHANNEL=$(echo $CHANNEL | grep -o "[0-9]\{1,4\}") - RSSI=$(echo $SGCELL | cut -d, -f9) - CSQ_RSSI=$(echo $RSSI | grep -o "[0-9]\{1,3\}")" dBm" - ;; -esac - -CALIST=$(echo "${OX//[ ]/}" | grep -o "+CELLINFO:\"SCC\",[0-9],2,[0-9],[0-9]\{1,6\},[0-9]\{1,4\},[0-9]\{1,3\},[0-9]\{1,3\},[-0-9]\{1,4\},[-0-9]\{1,4\},[-0-9]\{1,4\},[-0-9]\{1,4\}") - -for CAVAL in $(echo "$CALIST"); do - if [ "$(echo $CAVAL | cut -d, -f2)" == "1" ]; then - CATYPE="CA"$(printf "\xe2\x86\x91") - else - CATYPE="CA" - fi - CHANv=$(echo $CAVAL | cut -d, -f5) - BWv=$(echo $CAVAL | cut -d, -f6) - if [ $BWv -gt 14 ]; then - let BWv=BWv/5 - else - BWv="1.4" - fi - if [ $CHANv -ge 123400 ]; then - BANDv="n"$(echo $CAVAL | cut -d, -f7) - else - BANDv="B"$(echo $CAVAL | cut -d, -f7) - fi - LBAND=$LBAND"
                                                                      "$BANDv" ($CATYPE, Bandwidth "$BWv" MHz)" - PCI=$PCI","$(echo $CAVAL | cut -d, -f8) - ECIO=$ECIO" dBm
                                                                      "$(echo $CAVAL | cut -d, -f9) - RSCP=$RSCP" dBm
                                                                      "$(echo $CAVAL | cut -d, -f10) - SINRv=$(echo $CAVAL | cut -d, -f12) - SINRv=$((($SINRv / 5) - 20))" dB" - CHANNEL=$CHANNEL","$CHANv - SINR=$SINR"
                                                                      "$SINRv -done - -NETMODE="-" -NMODE=$(echo $O" " | grep -o "+MODODR: .\+ OK " | tr " " ",") -TECH=$(echo $NMODE | cut -d, -f2) -if [ -n "$TECH" ]; then - MODTYPE="7" - case $TECH in - "2" ) - NETMODE="1" # Auto - ;; - "1" ) - NETMODE="5" # 3G only - ;; - "4" ) - NETMODE="4" # 3G preferred - ;; - "3" ) - NETMODE="3" # 2G only - ;; - "5" ) - NETMODE="7" # LTE only - ;; - * ) - NETMODE="1" - ;; - esac -fi -RATs=$(echo "$OX" | grep -o "\^SYSCFGEX: \"[0-9]\{2,6\}\"" | grep -o "[0-9]\{2,6\}") -if [ -n "$RATs" ]; then - MODTYPE="7" - case $RATs in - "02" ) - NETMODE="5" ;; - "03" ) - NETMODE="7" ;; - "04" ) - NETMODE="9" ;; - "0203" | "0204" | "020304" | "020403" ) - NETMODE="4" ;; - "0304" | "0302" | "030402" | "030204" ) - NETMODE="6" ;; - "0403" ) - NETMODE="8" ;; - * ) - NETMODE="1" ;; - esac -fi - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'PCI="'"$PCI"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ "$CONNECT" == "0" ]; then - exit 0 -fi - -if [ "$CSQ" = "-" ]; then - log "$OX" -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! "$OPER" ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua deleted file mode 100644 index 4598cd8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/modemchk.lua +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/lua - -local uvid = arg[1] -local upid = arg[2] -local dport = arg[3] -local cport = arg[4] - -local modemfile = "/etc/config/modem.data" -local modemdata = {} -local count -local retval -local cretval - -function process_line(xline, cnt) - local data = {} - local pline = xline - local start = 1 - for i=1,3 do - s, e = string.find(pline, " ") - data[i] = string.sub(pline, start, s-1) - pline = string.sub(pline, e+1) - end - data[4] = pline - modemdata[cnt] = data -end - -function read_modem() - count = 0 - local file = io.open(modemfile, "r") - if file == nil then - return - end - repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) < 5 then - break - end - count = count + 1 - process_line(line, count) - until 1==0 - file:close() -end - -function process_port() - for l=1,count do - local mdata = modemdata[l] - if mdata[1] == uvid and mdata[2] == upid then - retval = 0 - if mdata[3] == "tty0" then - retval = 1 - end - if mdata[3] == "tty1" then - retval = 2 - end - if mdata[3] == "tty2" then - retval = 3 - end - if mdata[3] == "tty3" then - retval = 4 - end - if mdata[3] == "tty4" then - retval = 5 - end - if mdata[3] == "tty5" then - retval = 6 - end - - cretval = 0 - if mdata[4] == "tty0" then - cretval = 1 - end - if mdata[4] == "tty1" then - cretval = 2 - end - if mdata[4] == "tty2" then - cretval = 3 - end - if mdata[4] == "tty3" then - cretval = 4 - end - if mdata[4] == "tty4" then - cretval = 5 - end - if mdata[4] == "tty5" then - cretval = 6 - end - - break - end - end -end - -read_modem() -retval = 0 -cretval = 0 -if count > 0 then - process_port() -end -if retval > 0 then - retval = retval - 1 -else - retval = tonumber(dport) -end -if cretval > 0 then - cretval = cretval - 1 -else - cretval = tonumber(cport) -end - -dret = string.format("%d", retval) -cret = string.format("%d", cretval) -local file = io.open("/tmp/parmpass", "w") -file:write("DPORT=\"" .. dret .. "\"\n") -file:write("CPORT=\"" .. cret .. "\"\n") -file:close() - -os.exit(retval) diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh deleted file mode 100644 index 0b189ef..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/novateldata.sh +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Novatel Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -fix_data() { - OY=$(echo $OY | tr 'a-z' 'A-Z') - O=$($ROOTER/common/processat.sh "$OY") - O=$(echo $O" ") - O=$(echo "${O//[\"]/}") -} - -process_csq() { -CSQ=$(echo $OY | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") - if [ "$CSQ" = "99" ]; then - CSQ="" - fi - if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi -} - -CSQ="-" -CSQ_PER="-" -CSQ_RSSI="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -CHANNEL="-" -TEMP="-" -PCI="-" -SINR="-" - -OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "novatelinfo.gcom" "$CURRMODEM") - -fix_data -process_csq - -DEG=$(echo $O" " | grep -o "+NWDEGC: .\+ OK " | tr " " ",") -TMP=$(echo $DEG | cut -d, -f2) -if [ -n "$TMP" ]; then - TEMP=$TMP$(printf "\xc2\xb0")"C" -fi - -MODE="-" -PSRAT=$(echo $O" " | grep -o "\$NWRAT: .\+ OK " | tr " " ",") -TECH=$(echo $PSRAT | cut -d, -f4) -if [ -n "$TECH" ]; then - case "$TECH" in - "1"|"2"|"3") - MODE="UMTS" - ;; - "4"|"5"|"6") - MODE="GSM" - ;; - "7"|"8"|"9") - MODE="LTE" - VZWRSRP=$(echo "$O" | grep -o "VZWRSRP: [0-9]\{1,3\},[0-9]\{1,7\},[-.0-9]\{1,7\}" | tr " " ",") - PCI=$(echo "$VZWRSRP" | cut -d, -f2) - CHANNEL=$(echo "$VZWRSRP" | cut -d, -f3) - LBAND=$("$ROOTER/chan2band.sh" "$CHANNEL") - TMP=$(echo "$VZWRSRP" | cut -d, -f4) - if [ -n "$TMP" ]; then - RSCP=$TMP - fi - VZWRSRQ=$(echo "$O" | grep -o "VZWRSRQ: [0-9]\{1,3\},[0-9]\{1,7\},[-.0-9]\{1,7\}" | tr " " ",") - TMP=$(echo "$VZWRSRQ" | cut -d, -f4) - if [ -n "$TMP" ]; then - ECIO=$TMP - fi - ;; - *) - MODE="CDMA/HDR" - ;; - esac -fi - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'PCI="'"$PCI"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -ENB="0" -if [ -e /etc/config/failover ]; then - ENB=$(uci get failover.enabled.enabled) -fi -if [ $ENB = "1" ]; then - exit 0 -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh deleted file mode 100644 index af68b66..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/otherdata.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Other Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -fix_data() { - O=$($ROOTER/common/processat.sh "$OY") -} - -process_csq() { - CSQ=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $2}') - [ "x$CSQ" = "x" ] && CSQ=-1 - if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then - CSQ_PER=$(($CSQ * 100/31)) - CSQ_RSSI=$((2 * CSQ - 113)) - CSQX=$CSQ_RSSI - [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI - [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI - CSQ_PER=$CSQ_PER"%" - CSQ_RSSI=$CSQ_RSSI" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi -} - -CSQ="-" -CSQ_PER="-" -CSQ_RSSI="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODETYPE="-" -NETMODE="-" -LBAND="-" -TEMP="-" -PCI="-" -SINR="-" - -OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "otherinfo.gcom" "$CURRMODEM") - -fix_data -process_csq - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'PCI="'"$PCI"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -ENB="0" -if [ -e /etc/config/failover ]; then - ENB=$(uci get failover.enabled.enabled) -fi -if [ $ENB = "1" ]; then - exit 0 -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh deleted file mode 100644 index cf0a8b9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/phone.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Phone Change" "$@" -} - -CURRMODEM=$1 -PHONE=$2 -NAME=$3 - -CPORT=$(uci get modem.modem$CURRMODEM.commport) -PHONE=$(echo "$PHONE" | sed -e 's/ //g') - -log "Change Modem $CURRMODEM SIM phone number to $PHONE, name to $NAME" - -INTER=${PHONE:0:1} -if [ $INTER = "+" ]; then - TON="145" - PHONE=${PHONE:1} -else - TON="129" -fi - -ATCMDD="AT+CPBS=\"ON\";+CPBS?" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -OX=$($ROOTER/common/processat.sh "$OX") - -ON=$(echo "$OX" | awk -F[,\ ] '/^\+CPBS:/ {print $2}') -if [ "$ON" = "\"ON\"" ]; then - ATCMDD="AT+CPBW=1,\"$PHONE\",$TON,\"$NAME\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD="AT+CNUM" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - M2=$(echo "$OX" | grep -o "+CNUM:[^,]*,[^,]*,[0-9]\{3\}")"," - M2=${M2:6} - CNUMx=$(echo "$M2" | cut -d, -f1 | cut -d\" -f2) - CNUMx=$(echo $CNUMx) - CNUM=$(echo "$M2" | cut -d, -f2 | cut -d\" -f2) - CNUMtype=$(echo "$M2" | cut -d, -f3) - if [ "${CNUM:0:1}" != "+" -a "$CNUMtype" == "145" ]; then - CNUM="+"$CNUM - fi - if [ -z "$CNUM" ]; then - CNUM="*" - fi - if [ -z "$CNUMx" ]; then - CNUMx="*" - fi - echo "$CNUM" > /tmp/msimnumx$CURRMODEM - echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM - mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh deleted file mode 100644 index 16cba63..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/processat.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -OX=$1 - -M6=$(echo "$OX" | sed -e "s/ / /g") -M5=$(echo "$M6" | sed -e "s/ / /g") -M4=$(echo "$M5" | sed -e "s/ / /g") -M3=$(echo "$M4" | sed -e "s/ / /g") -M2=$(echo "$M3" | sed -e "s/ / /g") -M2=$(echo "$M2" | sed -e "s/TAC:/ /;s/Tx Power:/ /;s/SINR/ /;s!SYSINFOEX:!SYSINFOEX: !;s!CNTI:!CNTI: !;s!SELRAT:!SELRAT: !;s!ZSNT:!ZSNT: !") -M1=$(echo "$M2" | sed -e "s!Car0 Tot Ec/Io!+ECIOx!;s!Car1 Tot Ec/Io!+ECIO1x!;s!Car0 RSCP!+RSCPx!;s!+CGMM: !!") -M2=$(echo "$M1" | sed -e "s!Car1 RSCP!+RSCP1x!;s!CSNR:!CSNR: !;s!RSSI (dBm):!RSSI4: !;s!AirCard !AirCard!;s!USB !USB!") -M3=$(echo "$M2" | sed -e "s!RSRP (dBm):!RSRP4: !;s!RSRQ (dB):!RSRQ4: !;s!LTERSRP:!LTERSRP: !;s!Model:!+MODEL: !;s!SYSCFGEX:!SYSCFGEX: !") -M7=$(echo "$M3" | sed -e "s!RX level Carrier 0 (dBm):!RSSI3: !;s!RX level Carrier 1 (dBm):!RSSI13: !;s!SYSCFG:!SYSCFG: !;s! ! !g") -OX=$(echo "$M7" | sed -e "s!WCDMA channel:!UMTS:!;s!SYSINFO:!SYSINFO: !;s!+PSRAT:!+PSRAT: !;s!+MODODR:!+MODODR: !") -echo "$OX" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh deleted file mode 100644 index 729ef12..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quantadata.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Quanta Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "quantainfo.gcom" "$CURRMODEM") - -OX=$(echo $OX | tr 'a-z' 'A-Z') - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -LBAND="-" -PCI="-" -SINR="-" -TEMP="-" - -CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ "$CSQ" = "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -REGX='*QRFINFO: \"LTE\",[0-9]\{1,2\},[0-9]\{1,5\},[.012345]\{1,3\},[0-9]\{1,3\},-[0-9]\{1,3\},[-0-9]\{1,3\},[.0-9]\{1,4\}' -LTE=$(echo $OX | grep -o "$REGX") -if [ -n "$LTE" ]; then - MODE="LTE" - BW=$(echo $LTE | cut -d, -f4) - LBAND="B"$(echo $LTE | cut -d, -f2)"(Bandwidth "$BW" MHz)" - RSCP=$(echo $LTE | cut -d, -f6) - ECIO=$(echo $LTE | cut -d, -f7) - CHANNEL=$(echo $LTE | cut -d, -f3) - PCI=$(echo $LTE | cut -d, -f5) - SINR=$(echo $LTE | cut -d, -f8)" dB" -else - REGX='*QRFINFO: \"WCDMA\",[0-9]\{1,2\},[0-9]\{1,5\},[^,],[0-9]\{1,3\},-[0-9]\{1,3\},[-0-9]\{1,3\}' - UMTS=$(echo $OX | grep -o "$REGX") - if [ -n "$UMTS" ]; then - MODE="WCDMA" - LBAND="B"$(echo $UMTS | cut -d, -f2) - RSCP=$(echo $UMTS | cut -d, -f6) - ECIO=$(echo $UMTS | cut -d, -f7) - CHANNEL=$(echo $UMTS | cut -d, -f3) - PCI=$(echo $UMTS | cut -d, -f5) - fi -fi - -TECH=$(echo $OX | grep -o "\^QCNCFG: \"[0123]\{2\}\"" | grep -o "[0123]\{2\}") -case $TECH in - "02") - NETMODE="5" - ;; - "03") - NETMODE="7" - ;; - *) - NETMODE="1" - ;; -esac - -MODTYPE="11" - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -if [ "$CSQ" = "-" ]; then - log "$OX" -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh deleted file mode 100644 index aa1b1b8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh +++ /dev/null @@ -1,376 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -CURRMODEM=$1 -COMMPORT=$2 - -lte_bw() { - BW=$(echo $BW | grep -o "[0-5]\{1\}") - case $BW in - "0") - BW="1.4" ;; - "1") - BW="3" ;; - "2"|"3"|"4"|"5") - BW=$((($(echo $BW) - 1) * 5)) ;; - esac -} - -nr_bw() { - BW=$(echo $BW | grep -o "[0-9]\{1,2\}") - case $BW in - "0"|"1"|"2"|"3"|"4"|"5") - BW=$((($(echo $BW) + 1) * 5)) ;; - "6"|"7"|"8"|"9"|"10"|"11"|"12") - BW=$((($(echo $BW) - 2) * 10)) ;; - "13") - BW="200" ;; - "14") - BW="400" ;; - esac -} - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "quectelinfo.gcom" "$CURRMODEM") - -OX=$(echo $OX | tr 'a-z' 'A-Z') - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -PCI="-" -CTEMP="-" -SINR="-" -CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ "$CSQ" = "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi -NR_NSA=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",") -NR_SA=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",") -if [ -n "$NR_NSA" ]; then - QENG=",,"$(echo $OX" " | grep -o "+QENG: \"LTE\".\+\"NR5G-NSA\"," | tr " " ",") - QENG5=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,5\},[-0-9]\{1,3\},-[0-9]\{2,3\},[0-9]\{1,7\},[0-9]\{1,3\}.\{1,6\}") - if [ -z "$QENG5" ]; then - QENG5=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,3\},[-0-9]\{1,3\},-[0-9]\{2,3\}") - if [ -n "$QENG5" ]; then - QENG5=$QENG5",," - fi - fi -elif [ -n "$NR_SA" ]; then - QENG=$(echo $NR_SA | tr " " ",") - QENG5=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",[ 0-9]\{3,4\},[0-9]\{2,3\},[0-9A-F]\{1,10\},[0-9]\{1,5\},[0-9A-F]\{2,6\},[0-9]\{6,7\},[0-9]\{1,3\},[0-9]\{1,2\},-[0-9]\{2,5\},-[0-9]\{2,3\},[-0-9]\{1,3\}") -else - QENG=$(echo $OX" " | grep -o "+QENG: [^ ]\+ " | tr " " ",") -fi -QCA=$(echo $OX" " | grep -o "+QCAINFO: \"S[CS]\{2\}\".\+NWSCANMODE" | tr " " ",") -QNSM=$(echo $OX | grep -o "+QCFG: \"NWSCANMODE\",[0-9]") -QNWP=$(echo $OX | grep -o "+QNWPREFCFG: \"MODE_PREF\",[A-Z5:]\+" | cut -d, -f2) -QTEMP=$(echo $OX | grep -o "+QTEMP: [0-9]\{1,3\}") -if [ -z "$QTEMP" ]; then - QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"XO[_-]THERM[_-][^,]\+,[\"]\?[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") -fi -if [ -z "$QTEMP" ]; then - QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDM-CORE-USR.\+[0-9]\{1,3\}\"" | cut -d\" -f4) -fi -if [ -z "$QTEMP" ]; then - QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDMSS.\+[0-9]\{1,3\}\"" | cut -d\" -f4) -fi -if [ -n "$QTEMP" ]; then - CTEMP=$(echo $QTEMP | grep -o "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C" -fi -RAT=$(echo $QENG | cut -d, -f4 | grep -o "[-A-Z5]\{3,7\}") -rm -f /tmp/modnetwork -case $RAT in - "GSM") - MODE="GSM" - ;; - "WCDMA") - MODE="WCDMA" - CHANNEL=$(echo $QENG | cut -d, -f9) - RSCP=$(echo $QENG | cut -d, -f12) - RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}") - ECIO=$(echo $QENG | cut -d, -f13) - ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}") - ;; - "LTE"|"CAT-M"|"CAT-NB") - MODE=$(echo $QENG | cut -d, -f5 | grep -o "[DFT]\{3\}") - if [ -n "$MODE" ]; then - MODE="$RAT $MODE" - else - MODE="$RAT" - fi - PCI=$(echo $QENG | cut -d, -f9) - CHANNEL=$(echo $QENG | cut -d, -f10) - LBAND=$(echo $QENG | cut -d, -f11 | grep -o "[0-9]\{1,3\}") - BW=$(echo $QENG | cut -d, -f12) - lte_bw - BWU=$BW - BW=$(echo $QENG | cut -d, -f13) - lte_bw - BWD=$BW - if [ -z "$BWD" ]; then - BWD="unknown" - fi - if [ -z "$BWU" ]; then - BWU="unknown" - fi - if [ -n "$LBAND" ]; then - LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" - fi - RSRP=$(echo $QENG | cut -d, -f15 | grep -o "[0-9]\{1,3\}") - if [ -n "$RSRP" ]; then - RSCP="-"$RSRP - RSRPLTE=$RSCP - fi - RSRQ=$(echo $QENG | cut -d, -f16 | grep -o "[0-9]\{1,3\}") - if [ -n "$RSRQ" ]; then - ECIO="-"$RSRQ - fi - RSSI=$(echo $QENG | cut -d, -f17 | grep -o "\-[0-9]\{1,3\}") - if [ -n "$RSSI" ]; then - CSQ_RSSI=$RSSI" dBm" - fi - SINRR=$(echo $QENG | cut -d, -f18 | grep -o "[0-9]\{1,3\}") - if [ -n "$SINRR" ]; then - if [ $SINRR -le 25 ]; then - SINR=$((($(echo $SINRR) * 2) -20))" dB" - fi - fi - - if [ -n "$NR_NSA" ]; then - MODE="LTE/NR EN-DC" - echo "0" > /tmp/modnetwork - if [ -n "$QENG5" ] && [ -n "$LBAND" ] && [ "$RSCP" != "-" ] && [ "$ECIO" != "-" ]; then - PCI="$PCI, "$(echo $QENG5 | cut -d, -f4) - SCHV=$(echo $QENG5 | cut -d, -f8) - SLBV=$(echo $QENG5 | cut -d, -f9) - BW=$(echo $QENG5 | cut -d, -f10 | grep -o "[0-9]\{1,3\}") - if [ -n "$SLBV" ]; then - LBAND=$LBAND"
                                                                      n"$SLBV - if [ -n "$BW" ]; then - nr_bw - LBAND=$LBAND" (Bandwidth $BW MHz)" - fi - if [ "$SCHV" -ge 123400 ]; then - CHANNEL=$CHANNEL", "$SCHV - else - CHANNEL=$CHANNEL", -" - fi - else - LBAND=$LBAND"
                                                                      nxx (unknown NR5G band)" - CHANNEL=$CHANNEL", -" - fi - RSCP=$RSCP" dBm
                                                                      "$(echo $QENG5 | cut -d, -f5) - SINRR=$(echo $QENG5 | cut -d, -f6 | grep -o "[0-9]\{1,3\}") - if [ -n "$SINRR" ]; then - if [ $SINRR -le 30 ]; then - SINR=$SINR"
                                                                      "$((($(echo $SINRR) * 2) -20))" dB" - fi - fi - ECIO=$ECIO" (4G) dB
                                                                      "$(echo $QENG5 | cut -d, -f7)" (5G) " - fi - fi - if [ -z "$LBAND" ]; then - LBAND="-" - else - if [ -n "$QCA" ]; then - QCA=$(echo $QCA | grep -o "\"S[CS]\{2\}\"[-0-9A-Z,\"]\+") - for QCAL in $(echo "$QCA"); do - if [ $(echo "$QCAL" | cut -d, -f7) = "2" ]; then - SCHV=$(echo $QCAL | cut -d, -f2 | grep -o "[0-9]\+") - SRATP="B" - if [ -n "$SCHV" ]; then - CHANNEL="$CHANNEL, $SCHV" - if [ "$SCHV" -gt 123400 ]; then - SRATP="n" - fi - fi - SLBV=$(echo $QCAL | cut -d, -f6 | grep -o "[0-9]\{1,2\}") - if [ -n "$SLBV" ]; then - LBAND=$LBAND"
                                                                      "$SRATP$SLBV - BWD=$(echo $QCAL | cut -d, -f3 | grep -o "[0-9]\{1,3\}") - if [ -n "$BWD" ]; then - UPDOWN=$(echo $QCAL | cut -d, -f13) - case "$UPDOWN" in - "UL" ) - CATYPE="CA"$(printf "\xe2\x86\x91") ;; - "DL" ) - CATYPE="CA"$(printf "\xe2\x86\x93") ;; - * ) - CATYPE="CA" ;; - esac - if [ $BWD -gt 14 ]; then - LBAND=$LBAND" ("$CATYPE", Bandwidth "$(($(echo $BWD) / 5))" MHz)" - else - LBAND=$LBAND" ("$CATYPE", Bandwidth 1.4 MHz)" - fi - fi - LBAND=$LBAND - fi - PCI="$PCI, "$(echo $QCAL | cut -d, -f8) - fi - done - fi - fi - if [ $RAT = "CAT-M" ] || [ $RAT = "CAT-NB" ]; then - LBAND="B$(echo $QENG | cut -d, -f11) ($RAT)" - fi - ;; - "NR5G-SA") - MODE="NR5G-SA" - echo "0" > /tmp/modnetwork - if [ -n "$QENG5" ]; then - MODE="$RAT $(echo $QENG5 | cut -d, -f4)" - PCI=$(echo $QENG5 | cut -d, -f8) - CHANNEL=$(echo $QENG5 | cut -d, -f10) - LBAND=$(echo $QENG5 | cut -d, -f11) - BW=$(echo $QENG5 | cut -d, -f12) - nr_bw - LBAND="n"$LBAND" (Bandwidth $BW MHz)" - RSCP=$(echo $QENG5 | cut -d, -f13) - ECIO=$(echo $QENG5 | cut -d, -f14) - if [ "$CSQ_PER" = "-" ]; then - RSSI=$(rsrp2rssi $RSCP $BW) - CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%" - CSQ=$((($RSSI + 113) / 2)) - CSQ_RSSI=$RSSI" dBm" - fi - SINRR=$(echo $QENG5 | cut -d, -f15 | grep -o "[0-9]\{1,3\}") - if [ -n "$SINRR" ]; then - if [ $SINRR -le 30 ]; then - SINR=$((($(echo $SINRR) * 2) -20))" dB" - fi - fi - fi - ;; -esac - -QRSRP=$(echo "$OX" | grep -o "+QRSRP:[^,]\+,-[0-9]\{1,5\},-[0-9]\{1,5\},-[0-9]\{1,5\}[^ ]*") -if [ -n "$QRSRP" ] && [ "$RAT" != "WCDMA" ]; then - QRSRP1=$(echo $QRSRP | cut -d, -f1 | grep -o "[-0-9]\+") - QRSRP2=$(echo $QRSRP | cut -d, -f2) - QRSRP3=$(echo $QRSRP | cut -d, -f3) - QRSRP4=$(echo $QRSRP | cut -d, -f4) - QRSRPtype=$(echo $QRSRP | cut -d, -f5) - if [ "$QRSRPtype" == "NR5G" ]; then - if [ -n "$NR_SA" ]; then - RSCP=$QRSRP1 - if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then - RSCP1="RxD "$QRSRP2 - fi - if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" -a "$QRSRP3" != "-44" ]; then - RSCP=$RSCP" dBm
                                                                      "$QRSRP3 - fi - if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" -a "$QRSRP4" != "-44" ]; then - RSCP1="RxD "$QRSRP4 - fi - else - RSCP=$RSRPLTE - if [ -n "$QRSRP1" -a "$QRSRP1" != "-32768" ]; then - RSCP=$RSCP" (4G) dBm
                                                                      "$QRSRP1 - if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then - RSCP="$RSCP,$QRSRP2" - if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" ]; then - RSCP="$RSCP,$QRSRP3" - if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" ]; then - RSCP="$RSCP,$QRSRP4" - fi - fi - RSCP=$RSCP" (5G) " - fi - fi - fi - elif [ "$QRSRP2$QRSRP3$QRSRP4" != "-44-44-44" -a -z "$QENG5" ]; then - RSCP=$QRSRP1 - if [ "$QRSRP3$QRSRP4" == "-140-140" -o "$QRSRP3$QRSRP4" == "-44-44" -o "$QRSRP3$QRSRP4" == "-32768-32768" ]; then - RSCP1="RxD "$(echo $QRSRP | cut -d, -f2) - else - RSCP=$RSCP" dBm (RxD "$QRSRP2" dBm)
                                                                      "$QRSRP3 - RSCP1="RxD "$QRSRP4 - fi - fi -fi - -QNSM=$(echo "$QNSM" | grep -o "[0-9]") -if [ -n "$QNSM" ]; then - MODTYPE="6" - case $QNSM in - "0" ) - NETMODE="1" ;; - "1" ) - NETMODE="3" ;; - "2"|"5" ) - NETMODE="5" ;; - "3" ) - NETMODE="7" ;; - esac -fi -if [ -n "$QNWP" ]; then - MODTYPE="6" - case $QNWP in - "AUTO" ) - NETMODE="1" ;; - "WCDMA" ) - NETMODE="5" ;; - "LTE" ) - NETMODE="7" ;; - "LTE:NR5G" ) - NETMODE="8" ;; - "NR5G" ) - NETMODE="9" ;; - esac -fi - -CMODE=$(uci -q get modem.modem$CURRMODEM.cmode) -if [ "$CMODE" = 0 ]; then - NETMODE="10" -fi - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$CTEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh deleted file mode 100644 index 11f1e99..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/sierradata.sh +++ /dev/null @@ -1,258 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "Sierra Data" "$@" -} - -read_ssc() { - SLBAND=$(echo $OX | grep -o "LTE "$SSCx" BAND: B[0-9]\+ LTE "$SSCx" BW :") - SLBAND=$(echo $SLBAND | grep -o " BAND: B[0-9]\+ ") - if [ -n "$SLBAND" ]; then - SLBAND=$(echo $SLBAND | grep -o "[0-9]\+") - SLBAND=$(printf "
                                                                      B%d" $SLBAND) - BWD=$(echo $OX | grep -o " LTE "$SSCx" BW : [.012345]\+ [ML]") - BWD=$(echo $BWD | grep -o " BW : [.012345]\+" | grep -o "[.012345]\+") - if [ -n "$BWD" ]; then - SLBAND=$SLBAND$(printf " (CA, Bandwidth %s MHz)" $BWD) - else - SLBAND=$SLBAND$(printf " (CA, Bandwidth unknown)") - fi - LBAND=$LBAND$SLBAND - XTRACHAN=$(echo $OX | grep -o " LTE "$SSCx" CHAN: [0-9]\+") - XTRACHAN=$(echo "$XTRACHAN" | grep -o "[0-9]\{2,6\}") - if [ -n "$XTRACHAN" ]; then - CHANNEL=$(echo "$CHANNEL", "$XTRACHAN") - fi - fi -} - -CURRMODEM=$1 -COMMPORT=$2 - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "sierrainfo.gcom" "$CURRMODEM") - -OX=$(echo $OX | tr 'a-z' 'A-Z') - -CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ -z "$CSQ" ] || [ "$CSQ" = "99" ]; then - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -else - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -fi - -MODTYPE="-" -NETMODE="-" -LBAND="-" -PCI="-" - -LTEINFO=$(echo $OX | grep -o "!LTEINFO: .\+ INTRAFREQ:" | tr " " ",") -LTEINFO=$(echo "$LTEINFO" | grep -o "[0-9]\{1,6\}\,[0-9]\{3\}\,.\+") -if [ -n "$LTEINFO" ]; then - PCI=$(echo $LTEINFO | cut -d, -f10 | grep -o "[0-9]\{1,3\}") - if [ -z "$PCI" ]; then - PCI="-" - fi -fi - -SINR=$(echo $OX | grep -o "SINR (.B): [-.0-9]\{1,5\}" | tr '\n' ' ' | cut -d' ' -f3) -if [ -n "$SINR" ]; then - SINR5=$(echo $OX | grep -o "NR5G SINR (.B): [-]*[.0-9]\{1,5\}" | cut -d' ' -f4) - if [ -n "$SINR5" ]; then - SINR=$SINR" dB, "$SINR5 - fi - SINR=$SINR" dB" -else - SINR="-" -fi -TEMP=$(echo $OX | grep -o "TEMPERATURE: [-.0-9]\+ " | grep -o "[-.0-9]\+" | tr '\n' ' ') -if [ -n "$TEMP" ]; then - TEMP=$(printf "$(echo $TEMP | cut -d' ' -f2)\xc2\xb0C") -else - TEMP="unknown" -fi - -RAT=$(echo $OX | grep -o "SYSTEM MODE: [^ ]\{3,10\}" | cut -d' ' -f3) - -MODE=$RAT -case $RAT in - "WCDMA") - MODE=$(echo $OX | grep -o " \*CNTI: 0,[^ ]\+" | cut -d, -f2) - if [ -z "$MODE" ] || [ "$MODE" = "NONE" ]; then - MODE=$RAT - fi - CHANNEL=$(echo $OX | grep -o "WCDMA CHANNEL: [0-9]\{3,5\}" | cut -d' ' -f3) - if [ -n "$CHANNEL" ]; then - LOCKCHAN=$(echo $OX | grep -o "!UMTSCHAN? ENABLE: 01 CHANNEL: [0-9]\{3,5\}") - if [ -n "$LOCKCHAN" ]; then - LOCKCHAN=$(echo $LOCKCHAN | grep -o "CHANNEL: [0-9]\+" | grep -o "[0-9]\+") - CHANNEL=$CHANNEL" (Soft locked to $LOCKCHAN)" - fi - else - CHANNEL="-" - fi - ECIO=$(echo $OX | grep -o "EC/IO: [+-]\?[.0-9]\+") - ECIO=$(echo "$ECIO") - ECIO1=$(echo "$ECIO" | cut -d' ' -f4) - ECIO=$(echo "$ECIO" | cut -d' ' -f2) - RSCP=$(echo $OX | grep -o "RSCP: -[.0-9]\+") - RSCP=$(echo "$RSCP") - RSCP1=$(echo "$RSCP" | cut -d' ' -f4) - RSCP=$(echo "$RSCP" | cut -d' ' -f2) - ;; - "LTE") - LBAND=$(echo $OX | grep -o "LTE BAND: B[0-9]\+ LTE BW: [.012345]\+ MHZ" | grep -o "[.0-9]\+") - LBAND=$(printf "B%d (Bandwidth %s MHz)" $LBAND) - CHANNEL=$(echo $OX | grep -o "LTE RX CHAN: [0-9]\{1,6\}" | grep -o "[0-9]\+") - SLBAND=$(echo $OX | grep -o " ACTIVE LTE SCELL BAND:[ ]*B[0-9]\+ LTE SCELL BW:[ ]*[.012345]\+ MHZ") - if [ -n "$SLBAND" ]; then - SLBAND=$(echo $SLBAND | grep -o "[.0-9]\+") - SLBAND=$(printf "
                                                                      B%d (CA, Bandwidth %s MHz)" $SLBAND) - LBAND=$LBAND$SLBAND - XTRACHAN=$(echo $OX | grep -o " LTE SCELL CHAN:[0-9]\+" | grep -o "[0-9]\{2,6\}") - CHANNEL=$CHANNEL", "$XTRACHAN - fi - SSCLIST=$(echo $OX | grep -o "LTE S[CS]C[0-9] STATE:[ ]\?ACTIVE" | grep -o "[0-9]") - for SSCVAL in $(echo "$SSCLIST"); do - SSCx="S[CS]C"$SSCVAL - read_ssc - done - if [ -n "$LTEINFO" ]; then - RSCP=$(echo $LTEINFO | cut -d, -f12 | grep -o "[-][.0-9]\{2,5\}") - ECIO=$(echo $LTEINFO | cut -d, -f11 | grep -o "[-.0-9]\{1,5\}") - fi - if [ -z "$RSCP" ]; then - RSCP=$(echo $OX | grep -o "PCC RXM RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) - fi - if [ -n "$RSCP" ]; then - RSCP1=$(echo $OX | grep -o "PCC RXD RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) - if [ -z "$RSCP1" ]; then - RSCP1=$(echo $OX | grep -o "PCC RXD RSSI: -[0-9]\+ RSRP (DBM): -[0-9]\{2,3\} " | cut -d' ' -f7) - fi - else - RSCP=$(echo $OX | grep -o "RSRP (DBM): -[0-9]\{2,3\} " | tr '\n' ' ' | cut -d' ' -f3) - fi - if [ -z "$ECIO" ]; then - ECIO=$(echo $OX | grep -o "RSRQ (DB): [-.0-9]\{1,5\} " | cut -d' ' -f3) - fi - ;; - "ENDC") - MODE="LTE/NR EN-DC" - LBAND=$(echo $OX | grep -o "LTE BAND: B[0-9]\+ LTE BW: [.012345]\+ MHZ" | grep -o "[.0-9]\+") - LBAND=$(printf "B%d (Bandwidth %s MHz)" $LBAND) - CHANNEL=$(echo $OX | grep -o "LTE RX CHAN: [0-9]\{1,6\}" | grep -o "[0-9]\+") - NBAND=$(echo $OX | grep -o "NR5G BAND: N[0-9]\+ NR5G BW: [0-9]\+ MHZ") - NBAND=$(echo "$NBAND" | cut -d' ' -f3)" "$(echo "$NBAND" | cut -d' ' -f6) - if [ "$NBAND" != " " ]; then - NBAND=$(echo $NBAND | grep -o "[.0-9]\+") - NBAND=$(printf "
                                                                      n%d (Bandwidth %s MHz)" $NBAND) - LBAND=$LBAND$NBAND - NCHAN=$(echo $OX | grep -o "NR5G RX CHAN: [0-9]\{6\}" | cut -d' ' -f4) - CHANNEL=$CHANNEL", "$NCHAN - fi - SSCLIST=$(echo $OX | grep -o "LTE S[CS]C[0-9] STATE:[ ]\?ACTIVE" | grep -o "[0-9]") - for SSCVAL in $(echo "$SSCLIST"); do - SSCx="S[CS]C"$SSCVAL - read_ssc - done - RSCP=$(echo $OX | grep -o "PCC RXM RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) - RSCP1=$(echo $OX | grep -o "NR5G RSRP (DBM): -[0-9]\{2,3\} " | cut -d' ' -f4) - ECIO=$(echo $OX | grep -o "RSRQ (DB): [-.0-9]\{1,5\} " | tr '\n' ' ' | cut -d' ' -f3) - ECIO1=$(echo $OX | grep -o "NR5G RSRQ (DB): [-.0-9]\{1,5\} " | cut -d' ' -f4) - ;; - "NR5G") - MODE="NR5G-SA" - NBAND=$(echo $OX | grep -o "NR5G BAND: N[0-9]\+ NR5G BW: [0-9]\+ MHZ") - NBAND=$(echo "$NBAND" | cut -d' ' -f3)" "$(echo "$NBAND" | cut -d' ' -f6) - CHANNEL=$(echo $OX | grep -o "NR5G RX CHAN: [0-9]\{1,6\}" | grep -o "[0-9]\+") - RSCP=$(echo $OX | grep -o "PCC RXM RSRP: -[0-9]\{2,3\} " | cut -d' ' -f4) - ECIO=$(echo $OX | grep -o "RSRQ (DB): [-.0-9]\{1,5\} " | cut -d' ' -f3) - ;; -esac - -SELRAT=$(echo $OX | grep -o "!SELRAT:[^0-9]\+[0-9]\{2\}" | grep -o "[0-9]\{2\}") -if [ -n "$SELRAT" ]; then - MODTYPE="2" - case $SELRAT in - "01" ) - NETMODE="5" - ;; - "02" ) - NETMODE="3" - ;; - "06" ) - NETMODE="7" - ;; - * ) - NETMODE="1" - ;; - esac -fi - -CMODE=$(uci -q get modem.modem$CURRMODEM.cmode) - -if [ "$CMODE" = 0 ]; then - NETMODE="10" -fi -if [ -z "$RSCP1" ]; then - RSCP1=" " -fi -if [ -z "$ECIO1" ]; then - ECIO1=" " -fi - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci -q get modem.modem$CURRMODEM.connected) - -if [ "$CONNECT" -eq 0 ]; then - exit 0 -fi - -if [ $CSQ = "-" ]; then - log "$OX" -fi - -ENB="0" -if [ -e /etc/config/failover ]; then - ENB=$(uci get failover.enabled.enabled) -fi - -if [ $ENB = "1" ]; then - exit 0 -fi - -WWANX=$(uci -q get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh deleted file mode 100644 index e48fdaf..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/simcomdata.sh +++ /dev/null @@ -1,172 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -CURRMODEM=$1 -COMMPORT=$2 - -decode_bw() { - BW=$(echo $BW | grep -o "[0-5]\{1\}") - case $BW in - "0") - BW="1.4" ;; - "1") - BW="3" ;; - "2") - BW="5" ;; - "3") - BW="10" ;; - "4") - BW="15" ;; - "5") - BW="20" ;; - esac -} - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "simcominfo.gcom" "$CURRMODEM") - -OX=$(echo $OX | tr 'a-z' 'A-Z') - -REGXa="+CPSI:[ ]*LTE,ONLINE,[0-9]\{3\}-[0-9]\{2,3\},0X[0-9A-F]\{1,5\},[0-9]\{3,9\},[0-9]\{1,3\},[-A-Z0-9]\+,[0-9]\{1,6\},[0-5],[0-5],-[0-9]\{1,3\},-[0-9]\{1,4\},[-0-9]\{1,5\},[0-9]\{1,2\}" - -REGXb="+CPSI:[ ]*NR5G[_ANS]*,[0-9]\{1,3\},[0-9]\{6\},-[0-9]\{1,4\},-[0-9]\{1,4\},[-0-9]\{1,4\}" - -REGXc="+CPSI:[ ]*NR5G_SA,ONLINE,[0-9]\{3\}-[0-9]\{2,3\},0X[0-9A-F]\{1,6\},[0-9]\{3,13\},[0-9]\{1,3\},[^,]\+,[0-9]\{6,7\},-[0-9]\{1,4\},-[0-9]\{1,4\},[-0-9]\{1,4\}" - -REGXz="+CMGRMI: CA_SCELL,[0-9]\{2,6\},[^,]\+,[0-9]\{1,3\},[0-5],[^,]\+,[0-9]\{1,3\},[^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,1" - -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -NETMODE="-" -LBAND="-" -PCI="-" -CTEMP="-" -MODE="" -SINR="-" - -CSQ=$(echo "$OX" | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ $CSQ = "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -CPSIa=$(echo "$OX" | grep -o "$REGXa") -if [ -n "$CPSIa" ]; then - CPSIb=$(echo "$OX" | grep -o "$REGXb") - PCI=$(echo $CPSIa | cut -d, -f6) - LBAND=$(echo $CPSIa | cut -d, -f7 | grep -o "[0-9]\{1,3\}") - CHANNEL=$(echo $CPSIa | cut -d, -f8) - BW=$(echo $CPSIa | cut -d, -f9) - decode_bw - BWD=$BW - BW=$(echo $CPSIa | cut -d, -f10) - decode_bw - BWU=$BW - LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" - ECIO=$(($(echo $CPSIa | cut -d, -f11) / 10)) - RSCP=$(($(echo $CPSIa | cut -d, -f12) / 10)) - SINR=$((($(echo $CPSIa | cut -d, -f14) * 2) - 20))" dB" - if [ -n "$CPSIb" ]; then - MODE="LTE/NR EN-DC" - PCI=$PCI", "$(echo $CPSIb | cut -d, -f2) - NCHAN=$(echo $CPSIb | cut -d, -f3) - CHANNEL="$CHANNEL, $NCHAN" - NBAND=$("$ROOTER/chan2band.sh" "$NCHAN") - if [ "$NBAND" = "-" ]; then - LBAND=$LBAND"
                                                                      nxx (unknown NR5G band)" - else - LBAND=$LBAND"
                                                                      "$NBAND - fi - RSCP=$RSCP" dBm
                                                                      "$(($(echo $CPSIb | cut -d, -f4) / 10)) - ECIO=$ECIO" dB
                                                                      "$(($(echo $CPSIb | cut -d, -f5) / 10)) - SSINR=$(echo $CPSIb | cut -d, -f6) - if [ $SSINR -lt 255 ]; then - SINR=$SINR"
                                                                      "$((($SSINR / 5) - 20))" dB" - fi - else - MODE="LTE" - fi - CPSIc="" -else - CPSIc=$(echo "$OX" | grep -o "$REGXc") - if [ -n "$CPSIc" ]; then - MODE="NR5G" - PCI=$(echo $CPSIc | cut -d, -f6) - LBAND="n"$(echo $CPSIc | cut -d, -f7 | grep -o "BAND[0-9]\{1,3\}" | grep -o "[0-9]\+") - CHANNEL=$(echo $CPSIc | cut -d, -f8) - RSCP=$(($(echo $CPSIc | cut -d, -f9) / 10)) - ECIO=$(($(echo $CPSIc | cut -d, -f10) / 10)) - if [ "$CSQ_PER" = "-" ]; then - CSQ_PER=$((100 - (($RSCP + 31) * 100/-125)))"%" - fi - SINR=$(($(echo $CPSIc | cut -d, -f11) / 10))" dB" - fi - CPSIb="" -fi - -CAINFO=$(echo "$OX" | grep -o "$REGXz" | tr ' ' ':') -if [ -n "$CAINFO" ]; then - for CASV in $(echo "$CAINFO"); do - LBAND=$LBAND"
                                                                      B"$(echo "$CASV" | cut -d, -f4) - BW=$(echo "$CASV" | cut -d, -f5) - decode_bw - LBAND=$LBAND" (CA, Bandwidth $BW MHz)" - CHANNEL="$CHANNEL, "$(echo "$CASV" | cut -d, -f2) - PCI="$PCI, "$(echo "$CASV" | cut -d, -f7) - done -fi - -CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") -TEMP=$(echo "$OX" | grep -o "+CPMUTEMP:[ ]*[-0-9]\+" | grep -o "[-0-9]\{1,4\}") - -if [ -n "$CNMP" ]; then - case $CNMP in - "2"|"55" ) - NETMODE="1" ;; - "13" ) - NETMODE="3" ;; - "14" ) - NETMODE="5" ;; - "38" ) - NETMODE="7" ;; - "71" ) - NETMODE="9" ;; - "109" ) - NETMODE="8" ;; - * ) - NETMODE="0" ;; - esac -fi -if [ -n "$TEMP" ]; then - TEMP=$(echo $TEMP)$(printf "\xc2\xb0")"C" -fi -MODTYPE="10" - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh deleted file mode 100644 index 5c7ad2e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/t77data.sh +++ /dev/null @@ -1,236 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "T77 Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "t77info.gcom" "$CURRMODEM") - -OX=$(echo $OX | tr 'a-z' 'A-Z') -O=$($ROOTER/common/processat.sh "$OX") -O=$(echo $O) - -REGXca="BAND:[0-9]\{1,3\} BW:[0-9.]\+MHZ EARFCN:[0-9]\+ PCI:[0-9]\+ RSRP:[^R]\+RSRQ:[^R]\+RSSI:[^S]\+SNR[^D]\+" -REGXrxd="RX_DIVERSITY:[^(]\+([^)]\+" - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -PCI="-" -SINR="-" - -CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ "$CSQ" = "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -TEMP=$(echo $OX | grep -o "TSENS_TZ_SENSOR[0-9]:[0-9]\{1,3\}") -if [ -n "$TEMP" ]; then - TEMP=${TEMP:17:3} -fi -if [ -z "$TEMP" ]; then - TEMP=$(echo $OX | grep -o "XO_THERM_BUF:[0-9]\{1,3\}") - if [ -n "$TEMP" ]; then - TEMP=${TEMP:13:3} - fi -fi -if [ -z "$TEMP" ]; then - TEMP=$(echo $OX | grep -o "TSENS: [0-9]\{1,3\}C") -fi -if [ -n "$TEMP" ]; then - TEMP=$(echo $TEMP | grep -o "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C" -else - TEMP="-" -fi -TECH=$(echo $O" " | grep -o "+COPS: .,.,[^,]\+,[027]") -TECH="${TECH: -1}" - -if [ -n "$TECH" ]; then - RSSI=$(echo $O | grep -o " RSSI: [^D]\+D" | grep -o "[-0-9\.]\+") - if [ -n "$RSSI" ]; then - CSQ_RSSI=$(echo $RSSI)" dBm" - fi - case $TECH in - "7") - MODE="LTE" - ECIO=$(echo $O | grep -o " RSRQ: [^D]\+D" | grep -o "[-0-9\.]\+") - SINR=$(echo $OX | grep -o "RS-S[I]*NR: [^D]\+D") - SINR=${SINR:8} - SINR=$(echo "$SINR" | grep -o "[-0-9.]\{1,3\}")" dB" - LBAND="B"$(echo $O | grep -o " BAND: [0-9]\+" | grep -o "[0-9]\+") - DEBUGv1=$(echo $O | grep -o "EARFCN(DL/UL):") - DEBUGv2=$(echo $O | grep -o "LTE ENGINEERING") - if [ -n "$DEBUGv1" ]; then - RSCP=$(echo $O | grep -o "[^G] RSRP: [^D]\+D" | grep -o "[-0-9\.]\+") - RSRPlist=$(echo $OX | grep -o "$REGXrxd" | grep -o "\-[.0-9]\{4,5\}" | tr "\n" ",") - if [ -n "$RSRPlist" ]; then - RSCP=$(echo $RSRPlist | cut -d, -f1) - MIMO=$(echo $OX | grep -o "$REGXrxd" | cut -d" " -f2) - if [ "$MIMO" == "3" ]; then - RSCP="(2xMIMO) $RSCP" - fi - for IDX in 2 3 4; do - RSCPval=$(echo $RSRPlist | cut -d, -f$IDX) - if [ -n "$RSCPval" -a "$RSCPval" != "-256.0" ]; then - RSCP="$RSCP dBm, $RSCPval" - fi - done - fi - CHANNEL=$(echo $O | grep -o " EARFCN(DL/UL): [0-9]\+" | grep -o "[0-9]\+") - BWD=$(echo $O | grep -o " BW: [0-9\.]\+ MHZ" | grep -o "[0-9\.]\+") - if [ "$BWD" != "1.4" ]; then - BWD=${BWD/.*} - fi - LBAND=$LBAND" (Bandwidth $BWD MHz)" - PCI=$(echo $OX | grep -o " ENB ID(PCI): [^(]\+([0-9]\{1,3\})" | grep -o "([0-9]\+)" | grep -o "[0-9]\+") - fi - if [ -n "$DEBUGv2" ]; then - RSCP=$(echo $O | grep -o "RSRP: [^D]\+D" | grep -o "[-0-9\.]\+") - CHANNEL=$(echo $O | grep -o " DL CHANNEL: [0-9]\+" | grep -o "[0-9]\+") - PCI=$(echo $OX | grep -o " PCI: [0-9]\{1,3\}" | grep -o "[0-9]\+") - fi - SCC=$(echo $OX | grep -o " SCELL[1-9]:") - if [ -n "$SCC" ]; then - SCCn=$(echo $SCC | grep -o [0-9]) - for SCCx in $(echo "$SCCn"); do - SCCv=$(echo $OX | grep -o "SCELL$SCCx: $REGXca" | tr ' ' ',') - if [ -n "$SCCv" ]; then - SLBV=B$(echo $SCCv | cut -d, -f2 | grep -o "[0-9]\{1,3\}") - SBWV=$(echo $SCCv | cut -d, -f3 | grep -o "[0-9][^M]\+") - if [ "$SBWV" != "1.4" ]; then - SBWV=${SBWV%.*} - fi - LBAND=$LBAND"
                                                                      "$SLBV" (CA, Bandwidth "$SBWV" MHz)" - CHANNEL=$CHANNEL", "$(echo $SCCv | cut -d, -f4 | grep -o "[0-9]\+") - PCI=$PCI", "$(echo $SCCv | cut -d, -f5 | grep -o "[0-9]\+") - RSCP=$RSCP" dBm, "$(echo $SCCv | cut -d, -f6 | grep -o "[-0-9.]\+") - ECIO=$ECIO" dB, "$(echo $SCCv | cut -d, -f7 | grep -o "[-0-9.]\+") - CSQ_RSSI=$CSQ_RSSI", "$(echo $SCCv | cut -d, -f8 | grep -o "[-0-9.]\+")" dBm" - SINR=$SINR", "$(echo $SCCv | cut -d, -f9 | grep -o "[-0-9.]\+")" dB" - fi - done - else - SCC=$(echo $O | grep -o " SCC[1-9][^M]\+MHZ") - if [ -n "$SCC" ]; then - printf '%s\n' "$SCC" | while read SCCX; do - SCCX=$(echo $SCCX | tr " " ",") - SLBV=$(echo $SCCX | cut -d, -f5 | grep -o "B[0-9]\{1,3\}") - SBWV=$(echo $SCCX | cut -d, -f9) - if [ "$SBWV" != "1.4" ]; then - SBWV=${SBWV/.*} - fi - LBAND=$LBAND"
                                                                      "$SLBV" (CA, Bandwidth "$SBWV" MHz)" - echo "$LBAND" > /tmp/lbandvar$CURRMODEM - done - if [ -e /tmp/lbandvar$CURRMODEM ]; then - read LBAND < /tmp/lbandvar$CURRMODEM - rm /tmp/lbandvar$CURRMODEM - fi - fi - fi - ;; - "2") - MODE="WCDMA" - DEBUGv1=$(echo $O | grep -o "RAT:WCDMA") - if [ -n "$DEBUGv1" ]; then - RSCP=$(echo $O | grep -o "RSCP:[^)]\+" | grep -o "[-0-9\.]\+DBM," | grep -o "[^DBM,]\+") - ECIO=$(echo $O | grep -o " ECIO:[^D]\+D" | grep -o "[-0-9\.]\+") - ECIO=$(echo $ECIO) - CHANNEL=$(echo $O | grep -o " CHANNEL (DL): [0-9]\+" | grep -o "[0-9]\+") - LBAND="B"$(echo $O | grep -o " BAND: [0-9]\+" | grep -o "[0-9]\+") - BW=$(echo $O | grep -o " BW: [0-9\.]\+ MHZ" | grep -o "[0-9\.]\+") - BW=$(printf "%.0f" $BW ) - LBAND=$LBAND" (Bandwidth $BW MHz)" - PCI=$(echo $OX | grep -o "PSC:.\?[0-9]\{1,3\}" | grep -o "[0-9]\+") - else - QCSQ=$(echo $O | grep -o "\$QCSQ: -[0-9]\{2,3\},[-0-9]\{1,3\},[-0-9]\{1,3\},") - if [ -n "$QCSQ" ]; then - RSCP=$(echo $QCSQ | cut -d, -f1 | grep -o "[-0-9]*") - ECIO=$(echo $QCSQ | cut -d, -f2) - fi - fi - ;; - *) - MODE="GSM" - ;; - esac -fi - -SCFG=$(echo $OX | grep -o "\^SYSCONFIG: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") -if [ -n "$SCFG" ]; then - case $SCFG in - "13" ) - NETMODE="3" ;; - "14" ) - NETMODE="5" ;; - "17" ) - NETMODE="7" ;; - * ) - NETMODE="1" ;; - esac -fi - -MODTYPE="8" - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -if [ "$CSQ" = "-" ]; then - log "$OX" -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh deleted file mode 100644 index 8b677f5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/telitdata.sh +++ /dev/null @@ -1,241 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -CURRMODEM=$1 -COMMPORT=$2 - -log() { - logger -t "Telit Data" "$@" -} -decode_bw() { - case $BW in - "0") - BW="1.4" - ;; - "1") - BW="3" - ;; - "2") - BW="5" - ;; - "3") - BW="10" - ;; - "4") - BW="15" - ;; - "5") - BW="20" - ;; - *) - BW="" - ;; - esac -} -decode_band() { - if [ "$SLBV" -lt 134 ]; then - SLBV=$(($SLBV - 119)) - elif [ "$SLBV" -eq 134 ]; then - SLBV="17" - elif [ "$SLBV" -lt 143 ]; then - SLBV=$(($SLBV - 102)) - elif [ "$SLBV" -lt 147 ]; then - SLBV=$(($SLBV - 125)) - elif [ "$SLBV" -lt 149 ]; then - SLBV=$(($SLBV - 123)) - elif [ "$SLBV" -lt 152 ]; then - SLBV=$(($SLBV - 108)) - elif [ "$SLBV" -eq 152 ]; then - SLBV="23" - elif [ "$SLBV" -eq 153 ]; then - SLBV="26" - elif [ "$SLBV" -eq 154 ]; then - SLBV="32" - elif [ "$SLBV" -lt 158 ]; then - SLBV=$(($SLBV - 30)) - elif [ "$SLBV" -lt 161 ]; then - SLBV=$(($SLBV - 130)) - elif [ "$SLBV" -eq 161 ]; then - SLBV="66" - elif [ "$SLBV" -eq 162 ]; then - SLBV="250" - elif [ "$SLBV" -eq 163 ]; then - SLBV="46" - elif [ "$SLBV" -eq 166 ]; then - SLBV="71" - else - SLBV="??" - fi - -} - -idV=$(uci get modem.modem$CURRMODEM.idV) -idP=$(uci get modem.modem$CURRMODEM.idP) - -if [ $idP = 1040 -o $idP = 1041 ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "telitinfo.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') -else - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "telitinfoln.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') -fi - -O=$($ROOTER/common/processat.sh "$OX") -O=$(echo $O) - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -TEMP="-" -PCI="-" -SINR="-" - -CSQ=$(echo $O | grep -o "CSQ: [0-9]\+" | grep -o "[0-9]\+") -[ "x$CSQ" = "x" ] && CSQ=-1 - -if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then - CSQ_PER=$(($CSQ * 100/31)) - CSQ_RSSI=$((2 * CSQ - 113)) - CSQX=$CSQ_RSSI - [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI - [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI - CSQ_PER=$CSQ_PER"%" - CSQ_RSSI=$CSQ_RSSI" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -TMP=$(echo $O" " | grep -o "#TEMPSENS: .\+ OK " | tr " " ",") -if [ -n "$TMP" ]; then - TEMP=$(echo $TMP | cut -d, -f3)$(printf "\xc2\xb0")"C" -fi - -MODE="-" -WS46=$(echo $O | grep -o "+COPS:.\+AT#RFSTS" | grep -o "+COPS: [0-3],[0-3],\"[^\"].\+\",[027]") -TECH=$(echo $WS46 | cut -d, -f4) -if [ -n "$TECH" ]; then - MODE=$TECH - case $MODE in - "7") - MODE="LTE" - CAINFO=$(echo $OX | grep -o "#CAINFO: 1.\+OK") - SGCELL=$(echo $OX | grep -o "[#^]RFSTS: \"[ 0-9]\{5,7\}\",[0-9]\{1,5\},.\+,\"[0-9]\{15\}\",\"[^\"]*\",[0-3],[0-9]\{1,2\}[,0-9]\{0,4\}") - if [ -n "$SGCELL" ]; then - RSCP=$(echo $SGCELL | cut -d, -f3) - ECIO=$(echo $SGCELL | cut -d, -f5) - RSSI=$(echo $SGCELL | cut -d, -f4) - CSQ_RSSI=$(echo "$RSSI dBm") - CHANNEL=$(echo $SGCELL | cut -d, -f2) - if [ $(echo ${SGCELL:0:1}) = "#" ]; then - LBAND="B"$(echo $SGCELL | cut -d, -f16 | grep -o "[0-9]\{1,2\}") - else - LBAND="B"$(echo $SGCELL | cut -d, -f15) - SSINR=$(echo $SGCELL | cut -d, -f16) - if [ -n "$SSINR" ]; then - SINR=$((($(echo $SSINR) / 5) - 20))" dB" - fi - fi - BW=$(echo $CAINFO | cut -d, -f3) - decode_bw - if [ -n "$BW" ];then - LBAND=$LBAND" (Bandwidth $BW MHz)" - fi - if [ -n "$CAINFO" ]; then - SCCLIST=$(echo $CAINFO | grep -o "1[2-6][0-9],[0-9]\{1,5\},[0-5],[0-9]\{1,3\},-[0-9]\+,-[0-9]\+,-[0-9]\+,[0-9]\{1,3\},2,[0-5],") - if [ -n "$SCCLIST" ]; then - SSINR=$(echo $CAINFO | grep -o "#CAINFO: [^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,[^,]\+,[0-9]\{1,3\},") - SINR=$((($(echo $SSINR | cut -d, -f8) / 5) - 20))" dB" - printf '%s\n' "$SCCLIST" | while read SCCVAL; do - PCI=$(echo $SCCVAL | cut -d, -f4) - SLBV=$(echo $SCCVAL | cut -d, -f1) - decode_band - LBAND=$LBAND"
                                                                      B"$SLBV - BW=$(echo $SCCVAL | cut -d, -f3) - decode_bw - LBAND=$LBAND" (CA, Bandwidth $BW MHz)" - SCHV=$(echo $SCCVAL | cut -d, -f2) - CHANNEL=$(echo "$CHANNEL", "$SCHV") - { - echo "$LBAND" - echo "$CHANNEL" - } > /tmp/lbandvar$CURRMODEM - done - fi - fi - if [ -e /tmp/lbandvar$CURRMODEM ]; then - { - read LBAND - read CHANNEL - } < /tmp/lbandvar$CURRMODEM - rm /tmp/lbandvar$CURRMODEM - fi - fi - ;; - 2) - MODE="UMTS" - SGCELL=$(echo $O | grep -o "[#^]RFSTS: \"[ 0-9]\{5,7\}\",[0-9]\{1,5\},.\+,\"[0-9]\{15\}\",") - if [ -n "$SGCELL" ]; then - RSSI=$(echo $SGCELL | cut -d, -f6) - CSQ_RSSI=$(echo "$RSSI dBm") - RSCP=$(echo $SGCELL | cut -d, -f5) - ECIO=$(echo $SGCELL| cut -d, -f4) - CHANNEL=$(echo $SGCELL | cut -d, -f2) - fi - ;; - esac -fi - -NETMODE="1" -MODTYPE="8" - -{ - echo 'CSQ="'"$CSQ"'"' - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'PCI="'"$PCI"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) - -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -if [ "$CSQ" = "-" ]; then - log "$OX" -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh deleted file mode 100644 index 6f9a4ec..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ubloxdata.sh +++ /dev/null @@ -1,250 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "ublox Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -get_ublox() { - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "ubloxinfo.gcom" "$CURRMODEM" | tr 'a-z' 'A-Z') -} - -get_ublox - -UCGED=$(echo $OX | grep -o "+UCGED: 2") -if [ -z "$UCGED" ]; then - ATCMDD="AT+UCGED=2" - UCGED=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - get_ublox -fi -OX=$(echo $OX) - -RSRP="" -RSRQ="" -CHANNEL="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODTYPE="-" -NETMODE="-" -LBAND="-" -TEMP="-" -PCI="-" -SINR="-" - -CSQ=$(echo $OX | grep -o "+CSQ: .\+ +CESQ" | tr " " ",") -CESQ=$(echo $OX | grep -o "+CESQ: .\+ +URAT" | tr " " ",") -URAT=$(echo $OX | grep -o "+URAT: .\+ +UCGED" | tr " " ",") -UCGED=$(echo $OX" " | grep -o "+UCGED: .\+ OK " | tr " " ",") - -CSQ=$(echo $CSQ | cut -d, -f2) -CSQ=$(echo $CSQ | grep -o "[0-9]\{1,2\}") - -if [ "$CSQ" -eq "99" ]; then - CSQ="" -fi -if [ -n "$CSQ" ]; then - CSQ_PER=$(($CSQ * 100/31))"%" - CSQ_RSSI=$((2 * CSQ - 113))" dBm" -else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" -fi - -RAT=$(echo $UCGED | cut -d, -f3) -case "$RAT" in - "2") - MODE="GSM" - LAC=$(echo $UCGED | cut -d, -f11) - LAC=$(echo $LAC | grep -o "[0-9A-F]\{4\}") - CID=$(echo $UCGED | cut -d, -f9) - CID=$(echo $CID | grep -o "[0-9A-F]\{4\}") - ;; - "3") - MODE="UMTS" - CHANNEL=$(echo $UCGED | cut -d, -f7) - LAC=$(echo $UCGED | cut -d, -f10) - LAC=$(echo $LAC | grep -o "[0-9A-F]\{4\}") - CID=$(echo $UCGED | cut -d, -f9) - CID=$(echo $CID | grep -o "[0-9A-F]\{5,8\}") - RSCP=$(echo $CESQ | cut -d, -f4) - RSCP=$(echo $RSCP | grep -o "[0-9]\{1,3\}") - if [ "$RSCP" -eq "255" ]; then - RSCP="" - fi - if [ -n "$RSCP" ]; then - RSCP=$(($RSCP - 121)) - fi - ECIO=$(echo $CESQ | cut -d, -f5) - ECIO=$(echo $ECIO | grep -o "[0-9]\{1,3\}") - if [ "$ECIO" -eq "255" ]; then - ECIO="" - fi - if [ -n "$ECIO" ]; then - ECIO=$((($ECIO / 2) - 24)) - fi - ;; - "4") - MODE="LTE" - LBAND=$(echo $UCGED | cut -d, -f8) - if [ "$LBAND" -eq "255" ]; then - LBAND="" - fi - BWU=$(echo $UCGED | cut -d, -f9) - BWU=$(echo $BWU | grep -o "[0-9]\{1,3\}") - BWD=$(echo $UCGED | cut -d, -f10) - BWD=$(echo $BWD | grep -o "[0-9]\{1,3\}") - if [ -z "$BWD" ]; then - LBAND="" - fi - if [ -z "$BWU" ]; then - LBAND="" - fi - if [ -z "$LBAND" ]; then - LBAND="-" - else - if [ "$BWU" = "6" ]; then - BWU="1.4" - else - BWU=$(($(echo $BWU) / 5)) - fi - if [ "$BWD" = "6" ]; then - BWD="1.4" - else - BWD=$(($(echo $BWD) / 5)) - fi - LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)" - fi - LAC=$(echo $UCGED | cut -d, -f11) - LAC=$(echo $LAC | grep -o "[0-9A-F]\{4\}") - CID=$(echo $UCGED | cut -d, -f12) - CID=$(echo $CID | grep -o "[0-9A-F]\{5,8\}") - RSRP=$(echo $CESQ | cut -d, -f7) - RSRP=$(echo $RSRP | grep -o "[0-9]\{1,3\}") - if [ "$RSRP" -eq "255" ]; then - RSRP="" - fi - if [ -n "$RSRP" ]; then - RSRP=$(($RSRP - 141)) - RSCP=$RSRP - fi - RSRQ=$(echo $CESQ | cut -d, -f6) - RSRQ=$(echo $RSRQ | grep -o "[0-9]\{1,3\}") - if [ "$RSRQ" -eq "255" ]; then - RSRQ="" - fi - if [ -n "$RSRQ" ]; then - RSRQ=$((($RSRQ / 2) - 19)) - ECIO=$RSRQ - fi - ;; -esac - -if [ $RAT -eq "2" ]; then - if [ -n "$CID" ]; then - CID_NUM=$(printf "%d" 0x$CID) - CID=$CID" ("$CID_NUM")" - fi -else - CID=$(echo $CID | grep -o "[0-9A-F]\{5,8\}") - if [ -n "$CID" ]; then - LCID=$(printf "%08X" 0x$CID) - LCID_NUM=$(printf "%d" 0x$LCID) - if [ "$RAT" -eq "4" ]; then - RNC=$(printf "${LCID:1:5}") - CID=$(printf "${LCID:6:2}") - else - RNC=$(printf "${LCID:1:3}") - CID=$(printf "${LCID:4:4}") - fi - CID_NUM=$(printf "%d" 0x$CID) - CID=$CID" ("$CID_NUM")" - RNC_NUM=" ("$(printf "%d" 0x$RNC)")" - fi -fi - -if [ -n "$LAC" ]; then - LAC_NUM=$(printf "%d" 0x$LAC) - LAC=$LAC" ("$LAC_NUM")" -else - LAC="-" - LAC_NUM="-" -fi - -URAT1=$(echo $URAT | cut -d, -f2) -URAT2=$(echo $URAT | cut -d, -f3) -if [ -n "$URAT1" ]; then - MODTYPE="5" - case $URAT1 in - "0" ) - NETMODE="3" - ;; - "2" ) - NETMODE="5" - ;; - "3" ) - NETMODE="7" - ;; - * ) - case $URAT2 in - "0" ) - NETMODE="2" - ;; - "2" ) - NETMODE="4" - ;; - "3" ) - NETMODE="1" - ;; - esac - ;; - esac -fi - -echo 'CSQ="'"$CSQ"'"' > /tmp/signal$CURRMODEM.file -echo 'CSQ_PER="'"$CSQ_PER"'"' >> /tmp/signal$CURRMODEM.file -echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' >> /tmp/signal$CURRMODEM.file -echo 'ECIO="'"$ECIO"'"' >> /tmp/signal$CURRMODEM.file -echo 'RSCP="'"$RSCP"'"' >> /tmp/signal$CURRMODEM.file -echo 'ECIO1="'"$ECIO1"'"' >> /tmp/signal$CURRMODEM.file -echo 'RSCP1="'"$RSCP1"'"' >> /tmp/signal$CURRMODEM.file -echo 'MODE="'"$MODE"'"' >> /tmp/signal$CURRMODEM.file -echo 'MODTYPE="'"$MODTYPE"'"' >> /tmp/signal$CURRMODEM.file -echo 'NETMODE="'"$NETMODE"'"' >> /tmp/signal$CURRMODEM.file -echo 'CHANNEL="'"$CHANNEL"'"' >> /tmp/signal$CURRMODEM.file -echo 'LBAND="'"$LBAND"'"' >> /tmp/signal$CURRMODEM.file -echo 'LAC="'"$LAC"'"' >> /tmp/signal$CURRMODEM.file -echo 'LAC_NUM="'""'"' >> /tmp/signal$CURRMODEM.file -echo 'CID="'"$CID"'"' >> /tmp/signal$CURRMODEM.file -echo 'CID_NUM="'""'"' >> /tmp/signal$CURRMODEM.file -echo 'RNC="'"$RNC"'"' >> /tmp/signal$CURRMODEM.file -echo 'RNC_NUM="'"$RNC_NUM"'"' >> /tmp/signal$CURRMODEM.file -echo 'TEMP="'"$TEMP"'"' >> /tmp/signal$CURRMODEM.file -echo 'PCI="'"$PCI"'"' >> /tmp/signal$CURRMODEM.file -echo 'SINR="'"$SINR"'"' >> /tmp/signal$CURRMODEM.file - -if [ "$CSQ" = "-" ]; then - log "$OX" -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh deleted file mode 100644 index 2800901..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/common/ztedata.sh +++ /dev/null @@ -1,193 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "ZTE Data" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -fix_data() { - O=$($ROOTER/common/processat.sh "$OY") -} - -process_csq() { - CSQ=$(echo "$O" | awk -F[,\ ] '/^\+CSQ:/ {print $2}') - [ "x$CSQ" = "x" ] && CSQ=-1 - if [ $CSQ -ge 0 -a $CSQ -le 31 ]; then - CSQ_PER=$(($CSQ * 100/31)) - CSQ_RSSI=$((2 * CSQ - 113)) - CSQX=$CSQ_RSSI - [ $CSQ -eq 0 ] && CSQ_RSSI="<= "$CSQ_RSSI - [ $CSQ -eq 31 ] && CSQ_RSSI=">= "$CSQ_RSSI - CSQ_PER=$CSQ_PER"%" - CSQ_RSSI=$CSQ_RSSI" dBm" - else - CSQ="-" - CSQ_PER="-" - CSQ_RSSI="-" - fi -} - -process_zte() { - ZRSSI=$(echo "$O" | awk -F[,\ ] '/^\+ZRSSI:/ {print $2}') - if [ "x$ZRSSI" != "x" ]; then - TMP_RSSI=$CSQ_RSSI - CSQ_RSSI="-"$ZRSSI" dBm" - ECI=$(echo "$O" | awk -F[,\ ] '/^\+ZRSSI:/ {print $3}') - if [ "x$ECI" != "x" ]; then - ECIO=`expr $ECI / 2` - ECIO="-"$ECIO - RSCP=$(echo "$O" | awk -F[,\ ] '/^\+ZRSSI:/ {print $4}') - if [ "x$RSCP" != "x" ]; then - RSCP=`expr $RSCP / 2` - RSCP="-"$RSCP - else - CSQ_RSSI=$TMP_RSSI - RSCP=$ZRSSI - ECIO=$ECI - fi - else - RSCP=$ZRSSI - CSQ_RSSI=$TMP_RSSI - ECIO=`expr $RSCP - $CSQX` - fi - fi - - MODE="-" - TECH=$(echo "$O" | awk -F[,\ ] '/^\+ZPAS:/ {print $2}' | sed 's/"//g') - if [ "x$TECH" != "x" -a "x$TECH" != "xNo" ]; then - MODE="$TECH" - fi - - ZSNT=$(echo "$O" | awk -F[,\ ] '/^\+ZSNT:/ {print $2}') - if [ "x$ZSNT" != "x" ]; then - MODTYPE="1" - if [ $ZSNT = "0" ]; then - ZSNTX=$(echo "$O" | awk -F[,\ ] '/^\+ZSNT:/ {print $4}') - case $ZSNTX in - "0" ) - NETMODE="1" - ;; - "1" ) - NETMODE="2" - ;; - "2" ) - NETMODE="4" - ;; - "6" ) - NETMODE="6" - ;; - esac - else - case $ZSNT in - "1" ) - NETMODE="3" - ;; - "2" ) - NETMODE="5" - ;; - "6" ) - NETMODE="7" - ;; - esac - fi - fi - - ZCELLINFO=$(echo $O | grep -o "+ZCELLINFO: .\+ OK") - if [ -n "$ZCELLINFO" ]; then - LBAND=$(echo $ZCELLINFO | cut -d, -f3 | grep -o "LTE B[0-9]\{1,2\}") - CHANNEL=$(echo $ZCELLINFO | cut -d, -f4 | grep -o "[0-9]\+") - if [ -n "$LBAND" ]; then - LBAND="B"$(echo $LBAND | grep -o "[0-9]\+") - else - LBAND="-" - CHANNEL="-" - fi - fi - - ZSINR=$(echo $OY | grep -o "+ZSINR: [-0-9]\{1,3\},[0-9],") - if [ -n "$ZSINR" ]; then - ZSINR=${ZSINR:8} - SINR=$(echo $ZSINR | cut -d, -f1)"."$(echo $ZSINR | cut -d, -f2)" dB" - fi - - CMODE=$(uci get modem.modem$CURRMODEM.cmode) - if [ $CMODE = 0 ]; then - NETMODE="10" - fi -} - -CSQ="-" -CSQ_PER="-" -CSQ_RSSI="-" -ECIO="-" -RSCP="-" -ECIO1=" " -RSCP1=" " -MODE="-" -MODETYPE="-" -NETMODE="-" -LBAND="-" -CHANNEL="-" -TEMP="-" -PCI="-" -SINR="-" - -OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "zteinfo.gcom" "$CURRMODEM") - -fix_data -process_csq -process_zte - -{ - echo 'CSQ="'"$CSQ"'"' > /tmp/signal$CURRMODEM.file - echo 'CSQ_PER="'"$CSQ_PER"'"' - echo 'CSQ_RSSI="'"$CSQ_RSSI"'"' - echo 'ECIO="'"$ECIO"'"' - echo 'RSCP="'"$RSCP"'"' - echo 'ECIO1="'"$ECIO1"'"' - echo 'RSCP1="'"$RSCP1"'"' - echo 'MODE="'"$MODE"'"' - echo 'MODTYPE="'"$MODTYPE"'"' - echo 'NETMODE="'"$NETMODE"'"' - echo 'LBAND="'"$LBAND"'"' - echo 'CHANNEL="'"$CHANNEL"'"' - echo 'TEMP="'"$TEMP"'"' - echo 'PCI="'"$PCI"'"' - echo 'SINR="'"$SINR"'"' -} > /tmp/signal$CURRMODEM.file - -CONNECT=$(uci get modem.modem$CURRMODEM.connected) -if [ $CONNECT -eq 0 ]; then - exit 0 -fi - -if [ $CSQ = "-" ]; then - log "$OY" -fi - -ENB="0" -if [ -e /etc/config/failover ]; then - ENB=$(uci get failover.enabled.enabled) -fi -if [ $ENB = "1" ]; then - exit 0 -fi - -WWANX=$(uci get modem.modem$CURRMODEM.interface) -OPER=$(cat /sys/class/net/$WWANX/operstate 2>/dev/null) -rm -f "/tmp/connstat"$CURRMODEM - -if [ ! $OPER ]; then - exit 0 -fi -if echo $OPER | grep -q "unknown"; then - exit 0 -fi - -if echo $OPER | grep -q "down"; then - echo "1" > "/tmp/connstat"$CURRMODEM -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask deleted file mode 100644 index 8051d05..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/bandmask +++ /dev/null @@ -1,483 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Band Mask $CURRMODEM" "$@" -} - -CURRMODEM=$1 -MODTYPE=$2 - -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -sierrabandmask() { - enb=$(uci -q get custom.bandlock.enabled) - ATCMDD='AT!ENTERCND="A710";!BAND?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if [ $enb == "1" ]; then - log " " - log "Sierra Response : $OX" - log " " - fi - OX=$(echo $OX | tr " " '\x0a') - line=$OX - Unk=$(echo $line | grep "Unknown") - if [ "$Unk" ]; then - BND=$(echo $line | cut -d, -f6 | tr " " ",") - if [ $enb == "1" ]; then - log "Unknw : $BND" - fi - L1=$(echo $BND | cut -d, -f11) - GW=$(echo $BND | cut -d, -f10) - L2=$(echo $BND | cut -d, -f13) - else - all=$(echo $line | grep "L Band Mask 2") - if [ "$all" ]; then - BND=$(echo $line | cut -d, -f4 | tr " " ",") - if [ $enb == "1" ]; then - log "EM7511 : $BND" - fi - OK=8 - EOK=$(echo $BND | cut -d, -f$OK) - while [ $EOK != "OK" ]; do - OK=$(( OK + 1 )) - EOK=$(echo $BND | cut -d, -f$OK) - done - if [ $enb == "1" ]; then - log "$OK" - fi - ex1=$(( OK - 5 )) - ex2=$(( OK - 6 )) - ex3=$(( OK - 3 )) - L1=$(echo $BND | cut -d, -f$ex1) - GW=$(echo $BND | cut -d, -f$ex2) - L2=$(echo $BND | cut -d, -f$ex3) - else - BND=$(echo $line | cut -d, -f5 | tr " " ",") - if [ $enb == "1" ]; then - log "$BND" - fi - L1=$(echo $BND | cut -d, -f3) - GW=$(echo $BND | cut -d, -f2) - L2=$(echo $BND | cut -d, -f5) - fi - fi - if [ ! $L2 ]; then - L2="0000000000000000" - fi - if [ $L2 = "OK" ]; then - L2="0000000000000000" - fi - if [ $enb == "1" ]; then - log " " - log "LTE Band Mask : $L2$L1" - log " " - fi - uci set modem.modem$CURRMODEM.GW="$GW" - uci set modem.modem$CURRMODEM.L1="0x$L2$L1" - uci set modem.modem$CURRMODEM.L1X="$L1" - uci set modem.modem$CURRMODEM.L2="$L2" - uci commit modem - ATCMDD='AT!ENTERCND="AWRONG"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -} - -quebandmask() { - enb=$(uci -q get custom.bandlock.enabled) - idP=$(uci get modem.modem$CURRMODEM.idP) - CPORT=$(uci get modem.modem$CURRMODEM.commport) - ATCMDD="AT+CGMM" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - model=$(echo "$OX" | tr '\n' ' ' | cut -d' ' -f2) - uci set modem.modem$CURRMODEM.model=$model - ATCMDD='AT+QCFG="band"' - EM160=0 - if [ $enb == "1" ]; then - log " " - log "Modem PID : $idP" - log "Modem Model : $model" - log " " - fi - if [ $idP = "0620" -o $idP = "0800" -o $idP = "030b" -o $idP = "0900" -o $idP = "0801" ]; then - EM20=$(echo $model | grep "EM20") - if [ -z "$EM20" ]; then - EM160=1 - ATCMDD='AT+QNWPREFCFG="lte_band"' - fi - fi - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if [ $enb == "1" ]; then - log " " - log "Quectel Response : $OX" - log " " - fi - L5="" - L6="" - EMT=0 - - if [ $EM160 = $EMT ]; then - qm=$(echo $OX" " | grep "+QCFG:" | tr -d '"' | tr " " ",") - if [ $enb == "1" ]; then - log "$qm" - log " " - fi - L1=$(echo $qm | cut -d, -f5) - GW=$(echo $qm | cut -d, -f4) - L2="0" - else - qm=$(echo $OX" " | grep "+QNWPREFCFG:" | tr -d '"' | tr " " ":" | tr "," ":") - if [ $enb == "1" ]; then - log "$qm" - log " " - fi - bd=5 - msk="" - L1=$(echo $qm | cut -d: -f"$bd") - while [ $L1 != "OK" ] - do - msk=$msk$L1" " - bd=$((bd+1)) - L1=$(echo $qm | cut -d: -f"$bd") - done - L1=$(encodemask $msk) - if [ -z "$L1" ]; then - L1="0" - fi - L2="0" - GW="0" - EMT=0800 - - if [ $idP = $EMT -o $idP = 0900 -o $idP = "0801" ]; then - ATCMDD='AT+QNWPREFCFG="nsa_nr5g_band"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - qm=$(echo $OX" " | grep "+QNWPREFCFG:" | tr -d '"' | tr " " ":" | tr "," ":") - if [ $enb == "1" ]; then - log "EM160/RM500 $qm" - fi - bd=5 - msk="" - L5=$(echo $qm | cut -d: -f"$bd") - - while [ $L5 != "OK" ] - do - msk=$msk$L5" " - bd=$((bd+1)) - L5=$(echo $qm | cut -d: -f"$bd") - done - if [ -z "$msk" -o $msk = "0" ]; then - L5="0" - else - L5=$(encodemask $msk) - fi - - ATCMDD='AT+QNWPREFCFG="nr5g_band"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - qm=$(echo $OX" " | grep "+QNWPREFCFG:" | tr -d '"' | tr " " ":" | tr "," ":") - if [ $enb == "1" ]; then - log "EM160/RM500 $qm" - fi - bd=5 - msk="" - L6=$(echo $qm | cut -d: -f"$bd") - - while [ $L6 != "OK" ] - do - msk=$msk$L6" " - bd=$((bd+1)) - L6=$(echo $qm | cut -d: -f"$bd") - done - if [ -z "$msk" -o $msk = "0" ]; then - L6="0" - else - L6=$(encodemask $msk) - fi - $ROOTER/luci/celltype.sh $CURRMODEM - netmode=$(uci -q get modem.modem$CURRMODEM.netmode) - NET="0" - if [ -e /etc/qfake ]; then - if [ $netmode = "7" ]; then - NET=8 - fi - else - if [ $netmode = "8" ]; then - NET=8 - fi - if [ $netmode = "9" ]; then - NET=9 - fi - fi - uci set modem.modem$CURRMODEM.NET="$NET" - if [ $NET = "8" -a $L1 = "0" ]; then - if [ $enb == "1" ]; then - log "NSA no LTE" - fi - fi - fi - fi - if [ $enb == "1" ]; then - log " " - log "LTE Band Mask : $L1" - log "5G NSA Band Mask : $L5" - log "5G NA Band Mask : $L6" - log " " - fi - uci set modem.modem$CURRMODEM.GW="$GW" - uci set modem.modem$CURRMODEM.L1="$L1" - uci set modem.modem$CURRMODEM.L2="$L2" - uci set modem.modem$CURRMODEM.L5="$L5" - uci set modem.modem$CURRMODEM.L6="$L6" - uci commit modem -} - -fibomask() { - enb=$(uci -q get custom.bandlock.enabled) - CPORT=$(uci get modem.modem$CURRMODEM.commport) - msk="" - NRsupport=false - ATCMDD='AT+GTACT=?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$(echo $OX | grep -o "+GTACT:[^)]\+") - if [ -n "$OX" ]; then - RATlist=$(echo $OX | grep -o "[0-9]\{2\}") - for RATval in $(echo "$RATlist"); do - if [ $RATval == "14" -o $RATval == "16" -o $RATval == "17" -o $RATval == "20" ]; then - NRsupport=true - fi - done - ATCMDD='AT+GTACT?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$(echo $OX" " | grep "+GTACT:" | tr -d '"' | tr " " ",") - else - ATCMDD='AT+XACT?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$(echo $OX" " | grep "+XACT:" | tr -d '"' | tr " " ",") - if [ -z "$OX" ]; then - ATCMDD="" - OX="No AT command found to read bands" - fi - fi - LTEbands=$(echo "$OX" | grep -o "1[0-9]\{2\}") - NRbands=$(echo "$OX" | grep -o "50[0-9]\{1,3\}") - for bandval in $(echo "$LTEbands"); do - msk=$msk$((bandval-100))" " - done - if [ -n "$msk" ]; then - L1=$(encodemask $msk) - else - L1="0" - fi - msk="" - for bandval in $(echo "$NRbands"); do - msk=$msk${bandval:2}" " - done - if [ $enb == "1" ]; then - log " " - log "Get Current Bands : $ATCMDD" - log "Current Bands : $OX" - log " " - fi - if [ -z "$msk" ]; then - if $NRsupport; then - L5="0x0" - else - L5="" - fi - else - L5="0x"$(encodemask $msk) - fi - if [ -n "$L1$L5" ]; then - if [ $enb == "1" ]; then - log " " - log "LTE Band Mask : $L1" - log "5G Band Mask : $L5" - log " " - fi - uci set modem.modem$CURRMODEM.L1="0x$L1" - uci set modem.modem$CURRMODEM.L5="$L5" - uci commit modem - fi -} - -t77mask() { - enb=$(uci -q get custom.bandlock.enabled) - ATCMDD='AT^SLBAND?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if [ $enb == "1" ]; then - log " " - log "T77 Response : $OX" - log " " - fi - lte=$(echo $OX" " | tr "," ":" | tr " " ",") - if [ $enb == "1" ]; then - log " " - log "T77 Response : $lte" - log " " - fi - qm=$(echo $lte | cut -d, -f5) - log "$qm" - bd=3 - msk="" - L1=$(echo $qm | cut -d: -f"$bd") - while [ $L1 != "OK" ] - do - msk=$msk$L1" " - bd=$((bd+1)) - L1=$(echo $qm | cut -d: -f"$bd") - done - L1=$(encodemask $msk) - if [ -z "$L1" ]; then - L1="0" - fi - if [ $enb == "1" ]; then - log " " - log "LTE Band Mask : $L1" - log " " - fi - uci set modem.modem$CURRMODEM.L1="0x$L1" - uci commit modem -} - -reversebit() { - LX=$1 - length=${#LX} - jx="${LX:2:length-2}" - length=${#jx} - str="" - i=$((length-1)) - while [ $i -ge 0 ] - do - dgt="0x"${jx:$i:1} - DecNum=`printf "%d" $dgt` - Binary= - Number=$DecNum - while [ $DecNum -ne 0 ] - do - Bit=$(expr $DecNum % 2) - Binary=$Bit$Binary - DecNum=$(expr $DecNum / 2) - done - if [ -z $Binary ]; then - Binary="0000" - fi - len=${#Binary} - while [ $len -lt 4 ] - do - Binary="0"$Binary - len=${#Binary} - done - revstr="" - length=${#Binary} - ii=$((length-1)) - while [ $ii -ge 0 ] - do - revstr=$revstr${Binary:$ii:1} - ii=$((ii-1)) - done - str=$str$revstr - i=$((i-1)) - done - revstr=$str"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -} - -reverse() { - REV="" - BNDD=$1 - strlen=${#BNDD} - i=$((strlen-1)) - while [ $i -ge 0 ] - do - REV=$REV${BNDD:$i:1} - i=$((i-1)) - done -} - -telitbandmask() { - enb=$(uci -q get custom.bandlock.enabled) - ATCMDD='AT#BND?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if [ $enb == "1" ]; then - log " " - log "Telit Response : $OX" - log " " - fi - OX=$(echo $OX | tr " " '\x0a') - line=$OX - bnd=$(echo $line | grep "BND: ") - if [ ! -z "$bnd" ]; then - line=$(echo $bnd | tr " " ',') - if [ $enb == "1" ]; then - log "$line" - fi - BND=$(echo $line | cut -d, -f5) - ext=$(echo $line | cut -d, -f6) - reverse $BND - revs=$REV"0000000000000000" - revs=${revs:0:16} - reverse $revs - EXT="" - if [ "$ext" != "OK" -a "$ext" != "0" ]; then - EXT=$ext - fi - revs=$EXT$REV - if [ $enb == "1" ]; then - log " " - log "LTE Band Mask : $revs" - log " " - fi - ATCMDD='AT#BND=?' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$(echo $OX | tr " " '\x0a') - OX=$(echo ${OX//),(/!}) - BND=$(echo $OX"!!" | cut -d! -f3) - extt=$(echo $OX"!!" | cut -d! -f4) - if [ ! -z "$extt" ]; then - extt=$(echo $extt | tr "(" ',') - extt=$(echo $extt | tr ")" ',') - extt=$(echo $extt",," | cut -d, -f1) - fi - BND=$(echo $BND | tr "(" ',') - BND=$(echo $BND | tr ")" ',') - BND=$(echo $BND",," | cut -d, -f1) - reverse $BND - revx=$REV"0000000000000000" - revx=${revx:0:16} - reverse $revx - revx=$extt$REV - revx=${revx:0:18} - reversebit "0x"$revx - revstr=${revstr:0:72} - if [ $enb == "1" ]; then - log " " - log "LTE Bit Mask : $revstr" - log " " - fi - - uci set modem.modem$CURRMODEM.GW="0" - uci set modem.modem$CURRMODEM.L1="0x$revs" - uci set modem.modem$CURRMODEM.L1X="$revstr" - uci set modem.modem$CURRMODEM.LEXT="$extt" - uci set modem.modem$CURRMODEM.L2="0" - uci commit modem - fi -} - -case $MODTYPE in - "0" ) - sierrabandmask - ;; - "1" ) - quebandmask - ;; - "2" ) - fibomask - ;; - "3" ) - t77mask - ;; - "4" ) - telitbandmask - ;; -esac - -$ROOTER/luci/mask.sh diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh deleted file mode 100644 index fece3af..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/conmon.sh +++ /dev/null @@ -1,188 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Connection Monitor $CURRMODEM" "$@" -} - -CURRMODEM=$1 - -power_toggle() { - if [ -f "/tmp/gpiopin" ]; then - source /tmp/gpiopin - echo "$GPIOPIN" > /sys/class/gpio/export - if [ $? -eq 0 ]; then - $ROOTER/pwrtoggle.sh 3 - else - $ROOTER/pwrtoggle.sh $CURRMODEM - fi - else - if [ $ACTIVE = 4 ]; then -# GPIO power-toggle not supported so re-bind USB driver, but only if power toggle is configured in connection monitoring - if [ $(uci -q get modem.pinginfo$CURRMODEM.alive) = 4 ]; then - $ROOTER/pwrtoggle.sh $CURRMODEM - fi -# if [ -L /sys/bus/usb/drivers/usb/usb1 ]; then -# if [ $(uci get modem.pinginfo1.alive) = 4 ]; then -# $ROOTER/pwrtoggle.sh 1 -# fi -# fi -# if [ -L /sys/bus/usb/drivers/usb/usb2 ]; then -# if [ $(uci get modem.pinginfo2.alive) = 4 ]; then -# $ROOTER/pwrtoggle.sh 2 -# fi -# fi - fi - fi -} - -do_down() { - echo 'MONSTAT="'"DOWN$1"'"' > /tmp/monstat$CURRMODEM - case $ACTIVE in - "1" ) - log "Modem $CURRMODEM Connection is Down$1" - ;; - "2" ) - log "Modem $CURRMODEM Connection is Down$1" - reboot -f - ;; - "3" ) - log "Modem $CURRMODEM Connection is Down$1" - PROT=$(uci get modem.modem$CURRMODEM.proto) - if [ $PROT -eq "30" ]; then - CPORT=$(uci get modem.modem$CURRMODEM.commport) - ATCMDD="AT+CFUN=4;+CFUN=1,1" - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" - echo "1" > /tmp/modgone - log "Setting Modem Removal flag" - sleep 60 - else - if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then - $ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM & - fi - fi - ;; - "4" ) - log "Modem $CURRMODEM Connection is Down$1" - power_toggle - ;; - esac -} - -CURSOR="-" - -log "Start Connection Monitor for Modem $CURRMODEM" - -sleep 30 - -while [ 1 = 1 ]; do - CP=$(uci -q get ping.ping.enable) - if [ $CP = "1" ]; then - echo 'MONSTAT="'"Custom Ping Test"'"' > /tmp/monstat$CURRMODEM - sleep 60 - else - ACTIVE=$(uci get modem.pinginfo$CURRMODEM.alive) - if [ $ACTIVE = "0" ]; then - echo 'MONSTAT="'"Disabled"'"' > /tmp/monstat$CURRMODEM - sleep 60 - else - track_ips= - IFNAME=$(uci get modem.modem$CURRMODEM.interface) - TIMEOUT=$(uci get modem.pinginfo$CURRMODEM.pingwait) - INTERVAL=$(uci get modem.pinginfo$CURRMODEM.pingtime) - RELIAB=$(uci get modem.pinginfo$CURRMODEM.reliability) - DOWN=$(uci get modem.pinginfo$CURRMODEM.down) - UP=$(uci get modem.pinginfo$CURRMODEM.up) - COUNT=$(uci get modem.pinginfo$CURRMODEM.count) - PACKETSIZE=$(uci get modem.pinginfo$CURRMODEM.packetsize) - INTERF=$(uci get modem.modeminfo$CURRMODEM.inter) - - list_track_ips() { - track_ips="$1 $track_ips" - } - - config_load modem - config_list_foreach "pinginfo$CURRMODEM" "trackip" list_track_ips - - if [ -f "/tmp/connstat$CURRMODEM" ]; then - do_down " from Modem" - rm -f /tmp/connstat$CURRMODEM - sleep 20 - else - ENB="0" - if [ -e /etc/config/failover ]; then - ENB=$(uci get failover.enabled.enabled) - fi - if [ $ENB = "1" ]; then - if [ -e /tmp/mdown$CURRMODEM ]; then - do_down " (using Failover)" - else - echo 'MONSTAT="'"Up ($CURSOR) (using Failover)"'"' > /tmp/monstat$CURRMODEM - fi - sleep 20 - else - # check to see if modem iface has an IP address, if not try a reconnect/power toggle - OX=$(ip address show $IFNAME 2>&1) - ip4=$(echo "$OX" | grep 'inet ' | cut -d' ' -f6) - ip6=$(echo "$OX" | grep 'inet6' | grep global | cut -d' ' -f6) - if [ -z "$ip4" -a -z "$ip6" ]; then - do_down " (no IP address)" - fi - - UPDWN="0" - host_up_count=0 - score_up=$UP - score_dwn=$DOWN - lost=0 - while true; do - if [ ! -z "$track_ips" ]; then - for track_ip in $track_ips; do - ping -I $IFNAME -c $COUNT -W $TIMEOUT -s $PACKETSIZE -q $track_ip &> /dev/null - if [ $? -eq 0 ]; then - let host_up_count++ - else - let lost++ - fi - done - if [ $host_up_count -lt $RELIAB ]; then - let score_dwn-- - score_up=$UP - if [ $score_dwn -eq 0 ]; then - UPDWN="1" - break - fi - else - let score_up-- - score_dwn=$DOWN - if [ $score_up -eq 0 ]; then - UPDWN="0" - break - fi - fi - else - UPDWN="0" - exit - fi - host_up_count=0 - sleep $INTERVAL - done - if [ $UPDWN = "1" ]; then - do_down " (using Ping Test)" - else - echo 'MONSTAT="'"UP ($CURSOR) (using Ping Test)"'"' > /tmp/monstat$CURRMODEM - fi - sleep $INTERVAL - - fi - fi - if [ $CURSOR = "-" ]; then - CURSOR="+" - else - CURSOR="-" - fi - fi - fi -done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh deleted file mode 100644 index 263fab6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_connect.sh +++ /dev/null @@ -1,1367 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Create Connection $CURRMODEM" "$@" -} - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -handle_timeout(){ - local wget_pid="$1" - local count=0 - TIMEOUT=70 - res=1 - if [ -d /proc/${wget_pid} ]; then - res=0 - fi - while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do - sleep 1 - count=$((count+1)) - res=1 - if [ -d /proc/${wget_pid} ]; then - res=0 - fi - done - - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill "$wget_pid" 2> /dev/null - res=1 - if [ -d /proc/${wget_pid} ]; then - res=0 - fi - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill -9 $wget_pid 2> /dev/null - fi - fi -} - -set_dns() { - local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) - local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) - local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) - local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) - - local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" - local bDNS="" - - echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null - if [ $? = 0 ]; then - log "Using DNS settings from the Connection Profile" - pdns=1 - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - - bDNS=$(echo $bDNS) - if [ $DHCP = 1 ]; then - uci set network.wan$INTER.peerdns=0 - uci set network.wan$INTER.dns="$bDNS" - fi - echo "$bDNS" > /tmp/v4dns$INTER - - bDNS="" - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - echo "$bDNS" > /tmp/v6dns$INTER - else - log "Using Provider assigned DNS" - pdns=0 - rm -f /tmp/v[46]dns$INTER - fi -} - -set_dns2() { - local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) - local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) - local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) - local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) - - local _DNS1 _DNS2 _DNS3 _DNS4 aDNS bDNS - - echo "$pDNS1 $pDNS2 $pDNS3 $pDNS4" | grep -o "[[:graph:]]" &>/dev/null - if [ $? = 0 ]; then - log "Using DNS settings from the Connection Profile" - pdns=1 - _DNS1=$pDNS1 - _DNS2=$pDNS2 - _DNS3=$pDNS3 - _DNS4=$pDNS4 - else - log "Using Provider assigned DNS" - pdns=0 - _DNS1=$DNS1 - _DNS2=$DNS2 - _DNS3=$DNS3 - _DNS4=$DNS4 - fi - - aDNS="$_DNS1 $_DNS2 $_DNS3 $_DNS4" - - bDNS="" - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0.0.0.0" ] && [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -n "$(echo "$DNSV" | grep -o ":")" ] && [ -z "$ip6" ] && continue - bDNS="$bDNS $DNSV" - fi - done - - bDNS=$(echo $bDNS) - uci set network.wan$INTER.dns="$bDNS" -} - -check_apn() { - IPVAR="IP" - local COMMPORT="/dev/ttyUSB"$CPORT - if [ -e /etc/nocops ]; then - echo "0" > /tmp/block - fi - ATCMDD="AT+CGDCONT=?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - - [ "$PDPT" = "0" ] && PDPT="" - for PDP in "$PDPT" IPV4V6; do - if [[ "$(echo $OX | grep -o "$PDP")" ]]; then - IPVAR="$PDP" - break - fi - done - - uci set modem.modem$CURRMODEM.pdptype=$IPVAR - uci commit modem - - log "PDP Type selected in the Connection Profile: \"$PDPT\", active: \"$IPVAR\"" - - if [ "$idV" = "12d1" ]; then - CFUNOFF="0" - else - CFUNOFF="4" - fi - - ATCMDD="AT+CGDCONT?;+CFUN?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - CGDCONT2=$(echo $OX | grep "+CGDCONT: 2,") - if [ -z "$CGDCONT2" ]; then - ATCMDD="AT+CGDCONT=2,\"$IPVAR\",\"ims\"" - OXy=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - if `echo $OX | grep "+CGDCONT: $CID,\"$IPVAR\",\"$NAPN\"," 1>/dev/null 2>&1` - then - if [ -z "$(echo $OX | grep -o "+CFUN: 1")" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") - fi - else - ATCMDD="AT+CGDCONT=$CID,\"$IPVAR\",\"$NAPN\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=$CFUNOFF") - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") - sleep 5 - fi - if [ -e /etc/nocops ]; then - rm -f /tmp/block - fi -} - -save_variables() { - echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file - echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file - echo 'USBN="'"$USBN"'"' >> /tmp/variable.file - echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file - echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file - echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file -} - -chcklog() { - OOX=$1 - CLOG=$(uci -q get modem.modeminfo$CURRMODEM.log) - if [ $CLOG = "1" ]; then - log "$OOX" - fi -} - -get_connect() { - NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) - NUSER=$(uci -q get modem.modeminfo$CURRMODEM.user) - NPASS=$(uci -q get modem.modeminfo$CURRMODEM.passw) - NAUTH=$(uci -q get modem.modeminfo$CURRMODEM.auth) - spin=$(uci -q get custom.simpin.pin) # SIM Pin - if [ -z "$spin" ]; then - spin=$(uci -q get modem.modeminfo$CURRMODEM.pincode) # Profile Pin - if [ -z "$spin" ]; then - spin=$(uci -q get profile.simpin.pin) # Default profile Pin - fi - fi - PINC=$spin - uci set modem.modeminfo$CURRMODEM.pincode=$PINC - uci commit modem - PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) -# -# QMI and MBIM can't handle nil -# - case $PROT in - "2"|"3"|"30"|"88" ) - if [ -z "$NUSER" ]; then - NUSER="NIL" - fi - if [ -z "$NPASS" ]; then - NPASS="NIL" - fi - ;; - esac - - uci set modem.modem$CURRMODEM.apn=$NAPN - uci set modem.modem$CURRMODEM.user=$NUSER - uci set modem.modem$CURRMODEM.passw=$NPASS - uci set modem.modem$CURRMODEM.auth=$NAUTH - uci set modem.modem$CURRMODEM.pin=$PINC - uci commit modem -} - -chksierra() { - SIERRAID=0 - if [ $idV = 1199 ]; then - case $idP in - "68aa"|"68a2"|"68a3"|"68a9"|"68b0"|"68b1" ) - SIERRAID=1 - ;; - "68c0"|"9040"|"9041"|"9051"|"9054"|"9056"|"90d3" ) - SIERRAID=1 - ;; - "9070"|"907b"|"9071"|"9079"|"901c"|"9091"|"901f"|"90b1" ) - SIERRAID=1 - ;; - esac - elif [ $idV = 114f -a $idP = 68a2 ]; then - SIERRAID=1 - elif [ $idV = 413c -a $idP = 81a8 ]; then - SIERRAID=1 - elif [ $idV = 413c -a $idP = 81b6 ]; then - SIERRAID=1 - fi -} - -chktelitmbim() { - TELITMBIM=0 - if [ $idV = 1bc7 -a $idP = 0032 ]; then - TELITMBIM=1 - fi -} - -chkT77() { - T77=0 - if [ $idV = 413c -a $idP = 81d7 ]; then - T77=1 - elif [ $idV = 413c -a $idP = 81d8 ]; then - T77=1 - elif [ $idV = 0489 -a $idP = e0b4 ]; then - T77=1 - elif [ $idV = 0489 -a $idP = e0b5 ]; then - T77=1 - elif [ $idV = 1bc7 -a $idP = 1910 ]; then - T77=1 - fi - if [ $T77 = 1 ]; then - [ -n "$TTYDEVS" ] || T77=0 - fi -} - -chkraw() { - RAW=0 - if [ $idV = 03f0 -a $idP = 0857 ]; then - RAW=1 - elif [ $idV = 1bc7 -a $idP = 1900 ]; then - RAW=1 - elif [ $idV = 1bc7 -a $idP = 1910 ]; then - RAW=1 - elif [ $idV = 19d2 -a $idP = 1432 ]; then - RAW=1 - elif [ $idV = 1e0e -a $idP = 9001 ]; then - RAW=1 - elif [ $idV = 2c7c ]; then - RAW=1 - elif [ $idV = 05c6 -a $idP = 9025 ]; then - [ $MAN = "Telit" ] || RAW=1 - elif [ $idV = 05c6 -a $idP = 90db ]; then - RAW=1 - elif [ $idV = 05c6 -a $idP = f601 ]; then - RAW=1 - elif [ $idV = 2cb7 -a $idP = 0104 ]; then - RAW=1 - elif [ $idV = 413c -a $idP = 81d7 ]; then - RAW=1 - elif [ $idV = 413c -a $idP = 81e0 ]; then - RAW=1 - elif [ $idV = 12d1 -a $idP = 1506 ]; then - RAW=1 - fi -} - -chkreg() { - local OX REGV REGST REGCMD - local COMMPORT="/dev/ttyUSB"$CPORT - ATCMDD="AT+CEREG?;+CREG?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - for REGCMD in +CEREG +CREG; do - REGV=$(echo "$OX" | grep -o "$REGCMD: [0-3],[0-9]") - if [ -n "$REGV" ]; then - REGST=$(echo "$REGV" | cut -d, -f2) - case $REGST in - "0" ) - continue - ;; - "1"|"5"|"6"|"7" ) - REGOK=1 - break - ;; - * ) - REGOK=0 - ;; - esac - fi - done -} - -addv6() { - . /lib/functions.sh - . /lib/netifd/netifd-proto.sh - local interface=wan$INTER - local zone="$(fw3 -q network "$interface" 2>/dev/null)" - - log "Adding IPv6 dynamic interface" - json_init - json_add_string name "${interface}_6" - json_add_string ${ifname1} "@$interface" - json_add_string proto "dhcpv6" - json_add_string extendprefix 1 - [ -n "$zone" ] && json_add_string zone "$zone" - [ "$pdns" = 1 ] && json_add_boolean peerdns 0 - [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 - proto_add_dynamic_defaults - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -get_tty() { -# $1 is bInterfaceNumber value - local IFNUM OX - IFNUM=$1 - for TTYD in $(echo "$TTYDEVS"); do - if [ ! "$ACM" = 1 ]; then - OX=$(cat /sys/class/tty/$TTYD/../../../bInterfaceNumber | grep "$IFNUM") - else - OX=$(cat /sys/class/tty/$TTYD/../../bInterfaceNumber | grep "$IFNUM") - fi - if [ $? = 0 ]; then - CPORT=$(echo $TTYD | grep -o "[[:digit:]]\+") - break - else - CPORT="" - fi - done -} - -get_tty_fix() { -# $1 is fixed ttyUSB or ttyACM port number - local POS - POS=`expr 1 + $1` - CPORT=$(echo "$TTYDEVS" | cut -d' ' -f"$POS" | grep -o "[[:digit:]]\+") -} - -get_tty_ncm() { - local IFPROT OX - PROTS="12 62 02 2" # PC UI interface bInterfaceProtocol value - for IFPROT in $PROTS; do - for TTYD in $(echo "$TTYDEVS"); do - OX=$(cat /sys/class/tty/$TTYD/../../../bInterfaceProtocol | grep -w "$IFPROT") - if [ $? = 0 ]; then - CPORT=$(echo $TTYD | grep -o "[[:digit:]]\+") - break 2 - else - CPORT="" - fi - done - done -} - -mbimcport() { - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - uci set modem.modem$CURRMODEM.commport=$CPORT - uci set modem.modem$CURRMODEM.proto="30" - log "MBIM Comm Port : /dev/ttyUSB$CPORT" -} - -CURRMODEM=$1 -RECON=$2 -SIERRAID=0 - -MAN=$(uci -q get modem.modem$CURRMODEM.manuf) -MOD=$(uci -q get modem.modem$CURRMODEM.model) -PROT=$(uci -q get modem.modem$CURRMODEM.proto) -idV=$(uci -q get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) - -if [ ! -z "$RECON" ]; then - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "ReConnecting" - uci set modem.modem$CURRMODEM.active=1 - uci set modem.modem$CURRMODEM.connected=0 - uci commit modem - INTER=$(uci -q get modem.modeminfo$CURRMODEM.inter) - jkillall getsignal$CURRMODEM - rm -f $ROOTER_LINK/getsignal$CURRMODEM - jkillall con_monitor$CURRMODEM - rm -f $ROOTER_LINK/con_monitor$CURRMODEM - jkillall mbim_monitor$CURRMODEM - rm -f $ROOTER_LINK/mbim_monitor$CURRMODEM - ifdown wan$INTER - CPORT=$(uci -q get modem.modem$CURRMODEM.commport) - WWANX=$(uci -q get modem.modem$CURRMODEM.wwan) - WDMNX=$(uci -q get modem.modem$CURRMODEM.wdm) - if [ "$RECON" = "1" ]; then - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" - fi -else - - DELAY=$(uci -q get modem.modem$CURRMODEM.delay) - if [ -z "$DELAY" ]; then - DELAY=5 - fi - -rm -f /tmp/usbwait - -MATCH="$(uci get modem.modem$CURRMODEM.maxcontrol | cut -d/ -f3- | xargs dirname)" - -case $PROT in - # Sierra Direct-IP data interface - - "1" ) - OX="$(for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH")" - ifname=$(basename $OX) - WWANX=$(echo $ifname | grep -o "[[:digit:]]") - log "Modem $CURRMODEM Sierra Direct-IP Device : $ifname" - - uci set modem.modem$CURRMODEM.wwan=$WWANX - uci set modem.modem$CURRMODEM.interface=$ifname - uci commit modem - ;; - - # QMI, NCM and MBIM use cdc-wdm - - "2"|"3"|"30"|"4"|"6"|"7" ) - OX="$(for a in /sys/class/usbmisc/*; do readlink $a; done | grep "$MATCH")" - devname=$(basename $OX) - log "Modem $CURRMODEM WDM Device : $devname" - WDMNX=$(echo $devname | grep -o "[[:digit:]]") - ifname="$(ls /sys/class/usbmisc/$devname/device/net/)" - WWANX=$(echo $ifname | grep -o "[[:digit:]]") - - uci set modem.modem$CURRMODEM.wdm=$WDMNX - uci set modem.modem$CURRMODEM.wwan=$WWANX - uci set modem.modem$CURRMODEM.interface=$ifname - uci commit modem - ;; -esac - -OX=$(for a in /sys/class/tty/*; do readlink $a; done | grep "$MATCH" | tr '\n' ' ' | xargs -r -n1 basename) -TTYDEVS=$(echo "$OX" | grep -o ttyUSB[0-9]) -if [ $? -ne 0 ]; then - TTYDEVS=$(echo "$OX" | grep -o ttyACM[0-9]) - [ $? -eq 0 ] && ACM=1 -fi -TTYDEVS=$(echo "$TTYDEVS" | tr '\n' ' ') -TTYDEVS=$(echo $TTYDEVS) -if [ -n "$TTYDEVS" ]; then - log Modem $CURRMODEM is a parent of $TTYDEVS -else - log "No Comm Ports" -fi - -get_tty_fix 0 -if [ -n "$CPORT" ]; then - uci set modem.modem$CURRMODEM.baseport=$CPORT -else - uci set modem.modem$CURRMODEM.baseport="" -fi -uci commit modem.modem$CURRMODEM - - case $PROT in -# -# Sierra Direct-IP modem comm port -# - "1" ) - log "Start Direct-IP Connection" - get_tty 03 - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - log "Sierra Comm Port : /dev/ttyUSB$CPORT" - ;; -# -# QMI modem comm port -# - "2"|"88" ) - log "Start QMI (RMNET) Connection" - sleep $DELAY - - chksierra - if [ $SIERRAID -eq 1 ]; then - get_tty 03 - elif [ $idV = 1bc7 ]; then - get_tty 03 - else - if [ $idV = 2c7c ]; then - QUEIF2="0121 0125 0306 0296 0512 0620 0800 030b 0801 0900" - if [[ $(echo "$QUEIF2" | grep -o -i "$idP") ]]; then - TPORT=2 - fi - elif [ $idV = 05c6 -a $idP = 9025 ]; then - [ $MAN = "Telit" ] || TPORT=2 - elif [ $idV = 1e0e -a $idP = 9001 ]; then - TPORT=2 - else - TPORT=1 - fi - get_tty_fix $TPORT - fi - - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - - log "Modem $CURRMODEM QMI (RMNET) Comm Port : /dev/ttyUSB$CPORT" - chkraw - ;; - "3"|"30" ) - log "Start MBIM Connection" - sleep $DELAY - - chksierra - if [ $SIERRAID -eq 1 ]; then - SIERRAIF2='1199:90b1' - if [[ $(echo $SIERRAIF2 | grep -o -i "$idV:$idP") ]]; then - IFNUM=02 - else - IFNUM=03 - fi - get_tty $IFNUM - if [ -z "$CPORT" ]; then - if [ $idP = "90d3" ]; then - get_tty_fix 0 - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - uci set modem.modem$CURRMODEM.commport=$CPORT - if [ -n "$CPORT" ]; then - uci set modem.modem$CURRMODEM.proto="30" - fi - log "Modem $CURRMODEM MBIM Comm Port : /dev/ttyUSB$CPORT" - else - uci set modem.modem$CURRMODEM.commport="" - uci set modem.modem$CURRMODEM.proto="3" - log "No MBIM Comm Port" - fi - else - mbimcport - fi - else - chktelitmbim - if [ $TELITMBIM -eq 1 ]; then - get_tty 00 - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - ACMPORT=$CPORT - CPORT=9$ACMPORT - ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT - uci set modem.modem$CURRMODEM.commport=$CPORT - if [ -n "$CPORT" ]; then - uci set modem.modem$CURRMODEM.proto="30" - fi - log "Modem $CURRMODEM MBIM Comm Port : /dev/ttyUSB$CPORT" - else - chkT77 - if [ $T77 -eq 1 ]; then - get_tty 02 - mbimcport - else - case $idV in - "2c7c"|"05c6" ) - get_tty_fix 2 - mbimcport - ;; - "03f0" ) - get_tty 02 - mbimcport - ;; - "1bc7" ) - if [ "$idP" = "1041" ]; then - get_tty 07 - else - get_tty 02 - fi - mbimcport - ;; - "2cb7" ) - get_tty_fix 0 - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - ACMPORT=$CPORT - CPORT="8$ACMPORT" - ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT - - uci set modem.modem$CURRMODEM.commport=$CPORT - uci set modem.modem$CURRMODEM.proto="30" - log "Modem $CURRMODEM MBIM Comm Port : /dev/ttyUSB$CPORT" - ;; - * ) - uci set modem.modem$CURRMODEM.commport="" - log "No MBIM Comm Port" - ;; - esac - fi - fi - fi - uci commit modem - ;; -# -# Huawei NCM -# - "4"|"6"|"7"|"24"|"26"|"27" ) - if [ "$idV" = "2c7c" -a "$idP" = "0900" ]; then - ATCMDD='AT+QCFG="usbnet",2' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB2" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD='AT+CFUN=1,1' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB2" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - reboot -f - fi - log "Start NCM Connection" - sleep $DELAY - - get_tty_ncm - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - - log "NCM Comm Port : /dev/ttyUSB$CPORT" - ;; - "28" ) - log "Start Fibocom NCM Connection" - get_tty_fix 2 - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - ACMPORT=$CPORT - CPORT="8$ACMPORT" - ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT - log "Modem $CURRMODEM Fibocom NCM Comm Port : /dev/ttyUSB$CPORT" - ;; - esac - - uci set modem.modem$CURRMODEM.commport=$CPORT - uci commit modem - -fi -if [ $PROT = "3" ]; then -# May have got changed to 30 above - PROT=$(uci -q get modem.modem$CURRMODEM.proto) -fi -if [ -z "$idV" ]; then - idV=$(uci -q get modem.modem$CURRMODEM.idV) -fi -QUECTEL=false -if [ "$idV" = "2c7c" ]; then - QUECTEL=true -elif [ "$idV" = "05c6" ]; then - QUELST="9090,9003,9215" - if [[ $(echo "$QUELST" | grep -o "$idP") ]]; then - QUECTEL=true - fi -fi - -if [ -e $ROOTER/connect/preconnect.sh ]; then - if [ "$RECON" != "2"|"88" ]; then - $ROOTER/connect/preconnect.sh $CURRMODEM - fi -fi - -if $QUECTEL; then - if [ "$RECON" != "2"|"88" ]; then - ATCMDD="AT+CNMI?" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo $OX | grep -o "+CNMI: [0-3],2," >/dev/null 2>&1`; then - ATCMDD="AT+CNMI=0,0,0,0,0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ATCMDD="AT+QINDCFG=\"smsincoming\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then - ATCMDD="AT+QINDCFG=\"smsincoming\",0,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ATCMDD="AT+QINDCFG=\"all\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then - ATCMDD="AT+QINDCFG=\"all\",0,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - log "Quectel Unsolicited Responses Disabled" - fi - $ROOTER/connect/bandmask $CURRMODEM 1 - clck=$(uci -q get custom.bandlock.cenable$CURRMODEM) - if [ $clck = "1" ]; then - ear=$(uci -q get custom.bandlock.earfcn$CURRMODEM) - pc=$(uci -q get custom.bandlock.pci$CURRMODEM) - ear1=$(uci -q get custom.bandlock.earfcn1$CURRMODEM) - pc1=$(uci -q get custom.bandlock.pci1$CURRMODEM) - ear2=$(uci -q get custom.bandlock.earfcn2$CURRMODEM) - pc2=$(uci -q get custom.bandlock.pci2$CURRMODEM) - ear3=$(uci -q get custom.bandlock.earfcn3$CURRMODEM) - pc3=$(uci -q get custom.bandlock.pci3$CURRMODEM) - cnt=1 - earcnt=$ear","$pc - if [ $ear1 != "0" -a $pc1 != "0" ]; then - earcnt=$earcnt","$ear1","$pc1 - let cnt=cnt+1 - fi - if [ $ear2 != "0" -a $pc2 != "0" ]; then - earcnt=$earcnt","$ear2","$pc2 - let cnt=cnt+1 - fi - if [ $ear3 != "0" -a $pc3 != "0" ]; then - earcnt=$earcnt","$ear3","$pc3 - let cnt=cnt+1 - fi - earcnt=$cnt","$earcnt - ATCMDD="at+qnwlock=\"common/4g\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log "$OX" - if `echo $OX | grep "ERROR" 1>/dev/null 2>&1` - then - ATCMDD="at+qnwlock=\"common/lte\",2,$ear,$pc" - else - ATCMDD=$ATCMDD","$earcnt - fi - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log "Cell Lock $OX" - sleep 10 - fi -fi -$ROOTER/luci/celltype.sh $CURRMODEM -if [ $SIERRAID -eq 1 ]; then - $ROOTER/connect/bandmask $CURRMODEM 0 - $ROOTER/luci/celltype.sh $CURRMODEM -fi -if [ $idV = "2dee" ]; then - ATC="AT^MODE=0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATC") -fi -if [ $idV = "2cb7" -o $idV = "8087" ]; then - $ROOTER/connect/bandmask $CURRMODEM 2 -fi - -chkT77 -if [ $T77 -eq 1 ]; then - $ROOTER/connect/bandmask $CURRMODEM 3 -fi - -if [ $idV = "1bc7" ]; then - if [ $idP = "1040" -o $idP = "1041" ]; then - $ROOTER/connect/bandmask $CURRMODEM 4 - fi -fi - -CHKPORT=$(uci -q get modem.modem$CURRMODEM.commport) -if [ -n "$CHKPORT" ]; then - $ROOTER/common/gettype.sh $CURRMODEM - $ROOTER/connect/get_profile.sh $CURRMODEM - if [ -e $ROOTER/simlock.sh ]; then - $ROOTER/simlock.sh $CURRMODEM - fi - - if [ -e /tmp/simpin$CURRMODEM ]; then - log " SIM Error" - exit 0 - fi - if [ -e /usr/lib/gps/gps.sh ]; then - /usr/lib/gps/gps.sh $CURRMODEM & - fi - INTER=$(uci -q get modem.modeminfo$CURRMODEM.inter) - [ $INTER = 3 ] && log "Modem $CURRMODEM disabled in Connection Profile" && exit 1 - $ROOTER/sms/check_sms.sh $CURRMODEM & - get_connect - if [ -z "$INTER" ]; then - INTER=$CURRMODEM - else - if [ $INTER = 0 ]; then - INTER=$CURRMODEM - fi - fi - log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" - OTHER=1 - if [ $CURRMODEM = 1 ]; then - OTHER=2 - fi - EMPTY=$(uci -q get modem.modem$OTHER.empty) - if [ $EMPTY = 0 ]; then - OINTER=$(uci -q get modem.modem$OTHER.inter) - if [ ! -z "$OINTER" ]; then - if [ $INTER = $OINTER ]; then - INTER=1 - if [ $OINTER = 1 ]; then - INTER=2 - fi - log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" - fi - fi - fi - uci set modem.modem$CURRMODEM.inter=$INTER - uci commit modem - log "Modem $CURRMODEM is using WAN$INTER" - - CID=$(uci -q get modem.modeminfo$CURRMODEM.context) - [ -z "$CID" ] && CID=1 - - DHCP=1 - if [ $PROT = 28 ]; then - DHCP=0 - elif [ $PROT = 2 -a $idV = 05c6 -a $idP = 9025 ]; then - [ $MAN = "Telit" ] || DHCP=0 - fi - NODHCP=$(uci -q get modem.modeminfo$CURRMODEM.nodhcp) - if [ $idV = "2c7c" -a $idP = "0801" ]; then - NODHCP="1" - fi - if [ "$NODHCP" = "1" ]; then - DHCP=0 - log "Using QMI without DHCP" - fi - - if [ $DHCP = 1 ]; then - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=dhcp - uci set network.wan$INTER.${ifname1}=$ifname - uci set network.wan$INTER._orig_bridge=false - uci set network.wan$INTER.metric=$INTER"0" - set_dns - uci commit network - else - set_dns - fi - - ttl=$(uci -q get modem.modeminfo$CURRMODEM.ttl) - if [ -z "$ttl" ]; then - ttl="0" - fi - $ROOTER/connect/handlettl.sh $CURRMODEM "$ttl" & - - if [ -e $ROOTER/changedevice.sh ]; then - $ROOTER/changedevice.sh $ifname - fi - - autoapn=$(uci -q get profile.disable.autoapn) - imsi=$(uci -q get modem.modem$CURRMODEM.imsi) - mcc6=${imsi:0:6} - mcc5=${imsi:0:5} - apd=0 - if [ -e /usr/lib/autoapn/apn.data ]; then - apd=1 - fi - if [ "$autoapn" = "1" -a $apd -eq 1 ]; then - isplist=$(grep -F "$mcc6" '/usr/lib/autoapn/apn.data') - if [ -z "$isplist" ]; then - isplist=$(grep -F "$mcc5" '/usr/lib/autoapn/apn.data') - if [ -z "$isplist" ]; then - isplist="000000,$NAPN,Default,$NPASS,$CID,$NUSER,$NAUTH" - fi - fi - else - isplist="000000,$NAPN,Default,$NPASS,$CID,$NUSER,$NAUTH" - fi - - uci set modem.modeminfo$CURRMODEM.isplist="$isplist" - uci commit modem - - if [ $idV = 12d1 ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "curc.gcom" "$CURRMODEM") - log "Huawei Unsolicited Responses Disabled" - ATCMDD="AT^USSDMODE=0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - FORCE=$(uci -q get modem.modeminfo$CURRMODEM.ppp) - if [ -n "$FORCE" ]; then - if [ $FORCE = 1 ]; then - log "Forcing PPP mode" - case $idV in - "12d1" ) - retval=10 - ;; - * ) - retval=11 - ;; - esac - uci set modem.modem$CURRMODEM.proto=$retval - rm -f $ROOTER_LINK/create_proto$CURRMODEM - log "Forced Protcol Value : $retval" - log "Connecting a PPP Modem" - ln -fs $ROOTER/ppp/create_ppp.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - exit 0 - fi - fi -fi - -if $QUECTEL; then - ATCMDD="AT+QINDCFG=\"all\",1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -fi - -modis=$(uci -q get basic.basic.modem) -if [ ! -z $modis ]; then - if [ $modis = "0" ]; then - log "Modem Disabled" - exit 0 - fi -fi - -for isp in $isplist -do - NAPN=$(echo $isp | cut -d, -f2) - NPASS=$(echo $isp | cut -d, -f4) - CID=$(echo $isp | cut -d, -f5) - NUSER=$(echo $isp | cut -d, -f6) - NAUTH=$(echo $isp | cut -d, -f7) - if [ "$NPASS" = "nil" ]; then - NPASS="NIL" - fi - if [ "$NUSER" = "nil" ]; then - NUSER="NIL" - fi - if [ "$NAUTH" = "nil" ]; then - NAUTH="0" - fi - export SETAPN=$NAPN - export SETUSER=$NUSER - export SETPASS=$NPASS - export SETAUTH=$NAUTH - export PINCODE=$PINC - - uci set modem.modem$CURRMODEM.apn=$NAPN - uci set modem.modem$CURRMODEM.user=$NUSER - uci set modem.modem$CURRMODEM.passw=$NPASS - uci set modem.modem$CURRMODEM.auth=$NAUTH - uci set modem.modem$CURRMODEM.pin=$PINC - uci commit modem - - concount=1 - while [ "$concount" -lt 3 ]; do - case $PROT in - "1" ) - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "auto.gcom" "$CURRMODEM") - chcklog "$OX" - M7=$(echo "$OX" | sed -e "s/SCPROF:/SCPROF: /;s! ! !g") - AU=$(echo "$M7" | awk -F[,\ ] '/^\!SCPROF:/ {print $4}') - if [ $AU = "1" ]; then - AUTO="1" - log "Autoconnect is Enabled" - else - AUTO="0" - log "Autoconnect is not Enabled" - fi - ;; - esac - uci set modem.modem$CURRMODEM.auto=$AUTO - uci commit modem - - case $PROT in - # - # Check provider Lock - # - "1"|"2"|"4"|"6"|"7"|"24"|"26"|"27"|"30"|"28"|"88" ) - $ROOTER/common/lockchk.sh $CURRMODEM - ;; - * ) - log "No Provider Lock Done" - ;; - esac - - case $PROT in - # - # Sierra and NCM uses separate Pincode setting - # - "1"|"4"|"6"|"7"|"24"|"26"|"27"|"28" ) - if [ -n "$PINC" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "setpin.gcom" "$CURRMODEM") - chcklog "$OX" - ERROR="ERROR" - if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` - then - log "Modem $CURRMODEM Failed to Unlock SIM Pin" - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Pin Locked" - exit 0 - fi - fi - ;; - * ) - log "Pincode in script" - ;; - esac - $ROOTER/log/logger "Attempting to Connect Modem #$CURRMODEM" - log "Attempting to Connect Modem $CURRMODEM" - - if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 2 - fi - - BRK=0 - case $PROT in - # - # Sierra connect script - # - "1" ) - if [ $AUTO = "0" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-directip.gcom" "$CURRMODEM") - chcklog "$OX" - ERROR="ERROR" - if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` - then - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - fi - M7=$(echo "$OX" | sed -e "s/SCACT:/SCACT: /;s! ! !g") - SCACT="!SCACT: 1,1" - if `echo ${M7} | grep "$SCACT" 1>/dev/null 2>&1` - then - BRK=0 - ifup wan$INTER - sleep 20 - else - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - fi - else - ifup wan$INTER - sleep 20 - fi - ;; - # - # QMI connect script - # - "2" ) - check_apn - $ROOTER/qmi/connectqmi.sh $CURRMODEM cdc-wdm$WDMNX $NAUTH $NAPN $NUSER $NPASS $RAW $DHCP $PINC - if [ $? = 0 ]; then - ifup wan$INTER - [ -f /tmp/ipv6supp$INTER ] && addv6 - else - #log "Restart Modem" - #/usr/lib/rooter/luci/restart.sh $CURRMODEM - exit 0 - fi - ;; - # - # NCM connect script - # - "4"|"6"|"7"|"24"|"26"|"27" ) - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "ati") - E5372=$(echo $OX | grep "E5372") - R215=$(echo $OX | grep "R215") - E5787=$(echo $OX | grep "E5787") - check_apn - if [ -n "$E5372" -o -n "$R215" -o -n "$E5787" ]; then - ifup wan$INTER - BRK=0 - else - OX=$($ROOTER/gcom/gcom-locked "/dev/cdc-wdm$WDMNX" "connect-ncm.gcom" "$CURRMODEM") - chcklog "$OX" - ERROR="ERROR" - if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` - then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-ncm.gcom" "$CURRMODEM") - chcklog "$OX" - fi - ERROR="ERROR" - if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` - then - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - else - ifup wan$INTER - sleep 25 - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "cgpaddr.gcom" "$CURRMODEM") - chcklog "$OX" - OX=$($ROOTER/common/processat.sh "$OX") - STATUS=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFOEX:/ {print $2}' | sed 's/"//g') - DOMAIN=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFOEX:/ {print $3}' | sed 's/"//g') - if [ "x$STATUS" = "x" ]; then - STATUS=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFO:/ {print $2}') - DOMAIN=$(echo "$OX" | awk -F[,\ ] '/^\^SYSINFO:/ {print $3}') - fi - CGPADDR="+CGPADDR:" - if `echo $OX | grep "$CGPADDR" 1>/dev/null 2>&1` - then - if [ $STATUS = "2" ]; then - if [ $DOMAIN = "1" ]; then - BRK=0 - else - if [ $DOMAIN = "2" ]; then - BRK=0 - else - if [ $DOMAIN = "3" ]; then - BRK=0 - else - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Network Error : Retrying" - fi - fi - fi - else - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Network Error : Retrying" - fi - else - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "No IP Address : Retrying" - fi - fi - fi - [ $BRK = 0 ] && addv6 - ;; - # - # Fibocom NCM connect - # - "28" ) - OX="$(for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH" | grep ".6/net/")" - ifname=$(basename $OX) - log "Modem $CURRMODEM Fibocom NCM Data Port : $ifname" - COMMPORT="/dev/ttyUSB"$CPORT - ATCMDD="AT+CGACT=0,$CID" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - check_apn - ATCMDD="AT+CGPIAF=1,0,0,0;+XDNS=$CID,1;+XDNS=$CID,2" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD="AT+CGACT=1,$CID" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ERROR="ERROR" - if [ -e /tmp/simerr$CURRMODEM ]; then - SIMFAIL=1 - log "SIM card error" - else - chkreg - [ "$REGOK" != 1 ] && log "Subscriber registration failed" - fi - if [ "$SIMFAIL" = 1 -o "$REGOK" != 1 ]; then - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - elif `echo "$OX" | grep -q "$ERROR"`; then - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - else - ATCMDD="AT+CGCONTRDP=$CID" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo "$OX" | grep -q "$ERROR"`; then - log "Failed to get IP information for context $CID" - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to get IP information : Retrying" - else - OX=$(echo "${OX//[\" ]/}") - ip=$(echo $OX | cut -d, -f4 | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}") - ip=$(echo $ip | cut -d' ' -f1) - DNS1=$(echo $OX | cut -d, -f6) - DNS2=$(echo $OX | cut -d, -f7) - OX6=$(echo $OX | grep -o "+CGCONTRDP:$CID,[0-9]\+,[^,]\+,[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}.\+") - ip6=$(echo $OX6 | grep -o "[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}:[0-9A-F]\{1,4\}") - ip6=$(echo $ip6 | cut -d' ' -f1) - DNS3=$(echo "$OX6" | cut -d, -f6) - DNS4=$(echo "$OX6" | cut -d, -f7) - - log "IP address(es): $ip $ip6" - log "DNS servers 1&2: $DNS1 $DNS2" - log "DNS servers 3&4: $DNS3 $DNS4" - - if [[ $(echo "$ip6" | grep -o "^[23]") ]]; then - # Global unicast IP acquired - v6cap=1 - elif [[ $(echo "$ip6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then - # non-routable address - v6cap=2 - else - v6cap=0 - fi - - if [ -n "$ip6" -a -z "$ip" ]; then - log "Running IPv6-only mode" - nat46=1 - fi - - ATCMDD="AT+XDATACHANNEL=1,1,\"/USBCDC/2\",\"/USBHS/NCM/0\",2,$CID" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - RDNS=$(uci -q get network.wan$INTER.dns) - - log "Applying IP settings to wan$INTER" - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=static - uci set network.wan$INTER.${ifname1}=$ifname - uci set network.wan$INTER.metric=$INTER"0" - if [ -n "$ip" ]; then - uci set network.wan$INTER.ipaddr=$ip/32 - uci set network.wan$INTER.gateway='0.0.0.0' - fi - if [ "$v6cap" -gt 0 ]; then - uci set network.wan$INTER.ip6addr=$ip6/128 - fi - - if [ -n "$RDNS" ]; then - uci set network.wan$INTER.dns="$RDNS" - else - set_dns2 - fi - - uci commit network - uci set modem.modem$CURRMODEM.interface=$ifname - uci commit modem - ip link set dev $ifname arp off - ATCMDD="AT+CGDATA=\"M-RAW_IP\",$CID" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "raw-ip.gcom" "$CURRMODEM" "$ATCMDD") - RESP=$(echo $OX | sed "s/AT+CGDATA=\"M-RAW_IP\",$CID //") - log "Final Modem $CURRMODEM result code is \"$RESP\"" - if [ "$RESP" = "OK CONNECT" ]; then - ifup wan$INTER - if [ -e /sys/class/net/$ifname/cdc_ncm/tx_timer_usecs ]; then - echo "0" > /sys/class/net/$ifname/cdc_ncm/tx_timer_usecs - fi - [ $v6cap = 2 ] && addv6 - sleep 2 - BRK=0 - else - BRK=1 - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - fi - fi - fi - ;; - # - # MBIM connect script - # - "3"|"30" ) - if [ -n "$CPORT" ]; then - check_apn - fi - log "Using Netifd Method" - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=mbim - uci set network.wan$INTER.device=/dev/cdc-wdm$WDMNX - uci set network.wan$INTER.metric=$INTER"0" - uci set network.wan$INTER.currmodem=$CURRMODEM - uci -q commit network - rm -f /tmp/usbwait - ifup wan$INTER - MIFACE=$(uci -q get modem.modem$CURRMODEM.interface) - if [ -e /sys/class/net/$MIFACE/cdc_ncm/tx_timer_usecs ]; then - echo "0" > /sys/class/net/$MIFACE/cdc_ncm/tx_timer_usecs - fi - exit 0 - ;; - esac - - if [ $BRK = 1 ]; then - ATCMDD="AT+COPS=0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - $ROOTER/log/logger "Retry Connection with Modem #$CURRMODEM" - log "Retry Connection" - sleep 10 - concount=$((concount+1)) - else - $ROOTER/log/logger "Modem #$CURRMODEM Connected" - log "Modem $CURRMODEM Connected" - break - fi - done - if [ $BRK = 0 ]; then - break - fi -done - -if [ $BRK = 1 ]; then - exit 0 -fi - -if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 3 -fi - -case $PROT in -# -# Sierra, NCM and QMI use modemsignal.sh and reconnect.sh -# - "1"|"2"|"4"|"6"|"7"|"24"|"26"|"27"|"28"|"88" ) - ln -fs $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM - ln -fs $ROOTER/connect/reconnect.sh $ROOTER_LINK/reconnect$CURRMODEM - # send custom AT startup command - if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then - ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) - if [ ! -z "$ATCMDD" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - ERROR="ERROR" - if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` - then - log "Error sending custom AT command: $ATCMDD with result: $OX" - else - log "Sent custom AT command: $ATCMDD with result: $OX" - fi - fi - fi - ;; -esac - - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - ln -fs $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM - $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & - uci set modem.modem$CURRMODEM.connected=1 - uci commit modem - - if [ -e $ROOTER/connect/postconnect.sh ]; then - $ROOTER/connect/postconnect.sh $CURRMODEM - fi - - if [ -e /etc/bandlock ]; then - M1='AT+COPS=?' - export TIMEOUT="120" - #OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") - export TIMEOUT="5" - fi - - if [ -e $ROOTER/timezone.sh ]; then - TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) - if [ "$TZ" = "1" ]; then - log "Set TimeZone" - $ROOTER/timezone.sh & - fi - fi - - CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) - CLB=1 - if [ -e /etc/config/mwan3 ]; then - ENB=$(uci -q get mwan3.wan$INTER.enabled) - if [ ! -z "$ENB" ]; then - if [ $CLB = "1" ]; then - uci set mwan3.wan$INTER.enabled=1 - else - uci set mwan3.wan$INTER.enabled=0 - fi - uci commit mwan3 - /usr/sbin/mwan3 restart - fi - fi - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh deleted file mode 100644 index 18d10c3..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_hostless.sh +++ /dev/null @@ -1,713 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Create Hostless Connection $CURRMODEM" "$@" -} - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -handle_timeout(){ - local wget_pid="$1" - local count=0 - ps | grep -v grep | grep $wget_pid - res="$?" - while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do - sleep 1 - count=$((count+1)) - ps | grep -v grep | grep $wget_pid - res="$?" - done - - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill "$wget_pid" 2> /dev/null - ps | grep -v grep | grep $wget_pid - res="$?" - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill -9 $wget_pid 2> /dev/null - fi - fi -} - -check_apn() { - IPVAR="IP" - local COMMPORT="/dev/ttyUSB"$CPORT - if [ -e /etc/nocops ]; then - echo "0" > /tmp/block - fi - ATCMDD="AT+CGDCONT=?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - - [ "$PDPT" = "0" ] && PDPT="" - for PDP in "$PDPT" IPV4V6; do - if [[ "$(echo $OX | grep -o "$PDP")" ]]; then - IPVAR="$PDP" - break - fi - done - - uci set modem.modem$CURRMODEM.pdptype=$IPVAR - uci commit modem - - log "PDP Type selected in the Connection Profile: \"$PDPT\", active: \"$IPVAR\"" - - if [ "$idV" = "12d1" ]; then - CFUNOFF="0" - else - CFUNOFF="4" - fi - ATCMDD="AT+CGDCONT?;+CFUN?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - CGDCONT2=$(echo $OX | grep "+CGDCONT: 2,") - if [ -z "$CGDCONT2" ]; then - ATCMDD="AT+CGDCONT=2,\"$IPVAR\",\"ims\"" - OXy=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - CGDCONT=$(echo $OX | grep -o "$CID,[^,]\+,[^,]\+,[^,]\+,0,0,1") - IPCG=$(echo $CGDCONT | cut -d, -f4) - if [ "$CGDCONT" == "$CID,\"$IPVAR\",\"$NAPN\",$IPCG,0,0,1" ]; then - if [ -z "$(echo $OX | grep -o "+CFUN: 1")" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") - fi - else - ATCMDD="AT+CGDCONT=$CID,\"$IPVAR\",\"$NAPN\",,0,0,1" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=$CFUNOFF") - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=1") - sleep 5 - fi -} - -set_dns() { - local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) - local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) - local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) - local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) - - local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" - local bDNS="" - - echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null - if [ $? = 0 ]; then - log "Using DNS settings from the Connection Profile" - pdns=1 - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - - bDNS=$(echo $bDNS) - uci set network.wan$INTER.peerdns=0 - uci set network.wan$INTER.dns="$bDNS" - echo "$bDNS" > /tmp/v4dns$INTER - - bDNS="" - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - echo "$bDNS" > /tmp/v6dns$INTER - else - log "Using Hostless Modem as a DNS relay" - pdns=0 - rm -f /tmp/v[46]dns$INTER - fi -} - -set_network() { - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=dhcp - uci set network.wan$INTER.${ifname1}=$1 - uci set network.wan$INTER.metric=$INTER"0" - set_dns - uci commit network - sleep 5 -} - -save_variables() { - echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file - echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file - echo 'USBN="'"$USBN"'"' >> /tmp/variable.file - echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file - echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file - echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file -} - -chcklog() { - OOX=$1 - CLOG=$(uci -q get modem.modeminfo$CURRMODEM.log) - if [ $CLOG = "1" ]; then - log "$OOX" - fi -} - -get_connect() { - NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) - PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) - uci set modem.modem$CURRMODEM.apn="$NAPN" - uci commit modem -} - -get_tty_fix() { -# $1 is fixed ttyUSB or ttyACM port number - local POS - POS=`expr 1 + $1` - CPORT=$(echo "$TTYDEVS" | cut -d' ' -f"$POS" | grep -o "[[:digit:]]\+") -} - -get_ip() { - ATCMDD="AT+CGPIAF=1,1,1,0;+CGPADDR" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$(echo "$OX" | grep "^+CGPADDR: $CID," | cut -d'"' -f2) - ip4=$(echo $OX | cut -d, -f1 | grep "\.") - ip6=$(echo $OX | cut -d, -f2 | grep ":") - log "IP address(es) obtained: $ip4 $ip6" -} - -check_ip() { - if [[ $(echo "$ip6" | grep -o "^[23]") ]]; then - # Global unicast IP acquired - v6cap=1 - elif [[ $(echo "$ip6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then - # non-routable address - v6cap=2 - else - v6cap=0 - fi - - if [ -n "$ip6" -a -z "$ip4" ]; then - log "Running IPv6-only mode" - nat46=1 - fi -} - -addv6() { - . /lib/functions.sh - . /lib/netifd/netifd-proto.sh - local interface=wan$INTER - local zone="$(fw3 -q network "$interface" 2>/dev/null)" - - log "Adding IPv6 dynamic interface" - json_init - json_add_string name "${interface}_6" - json_add_string ${ifname1} "@$interface" - json_add_string proto "dhcpv6" - json_add_string extendprefix 1 - [ -n "$zone" ] && json_add_string zone "$zone" - [ "$pdns" = 1 ] && json_add_boolean peerdns 0 - [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 - proto_add_dynamic_defaults - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -CURRMODEM=$1 - -MAN=$(uci -q get modem.modem$CURRMODEM.manuf) -MOD=$(uci -q get modem.modem$CURRMODEM.model) -$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Connecting" -$ROOTER/log/logger "Attempting to Connect Modem #$CURRMODEM ($MAN $MOD)" - -BASEP=$(uci -q get modem.modem$CURRMODEM.baseport) -idV=$(uci -q get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) -log " " -log "Hostless ID $idV:$idP" -log " " - -MATCH="$(uci -q get modem.modem$CURRMODEM.maxcontrol | cut -d/ -f3- | xargs dirname)" -OX=$(for a in /sys/class/tty/*; do readlink $a; done | grep "$MATCH" | tr '\n' ' ' | xargs -r -n1 basename) -TTYDEVS=$(echo "$OX" | grep -o ttyUSB[0-9]) -if [ $? -ne 0 ]; then - TTYDEVS=$(echo "$OX" | grep -o ttyACM[0-9]) - [ $? -eq 0 ] && ACM=1 -fi -TTYDEVS=$(echo "$TTYDEVS" | tr '\n' ' ') -TTYDEVS=$(echo $TTYDEVS) -if [ -n "$TTYDEVS" ]; then - log Modem $CURRMODEM is a parent of $TTYDEVS -else - log "No ECM Comm Port" -fi - -if [ $idV = 1546 -a $idP = 1146 ]; then - SP=1 -elif [ $idV = 19d2 -a $idP = 1476 ]; then - SP=2 -elif [ $idV = 1410 -a $idP = 9022 ]; then - SP=3 -elif [ $idV = 1410 -a $idP = 9032 ]; then - SP=3 -elif [ $idV = 2cb7 -o $idV = 1508 ]; then - sleep 5 - log "Fibocom ECM" - SP=4 -elif [ $idV = 2c7c ]; then - SP=5 -elif [ $idV = 12d1 -a $idP = 15c1 ]; then - SP=6 -elif [ $idV = 2cd2 ]; then - log "MikroTik R11e ECM" - SP=7 -elif [ $idV = 0e8d -a $idP = 7127 ]; then - log "RM350 ECM" - SP=8 -elif [ $idV = 0e8d -a $idP = 7126 ]; then - log "RM350 ECM" - SP=9 -else - SP=0 -fi - -log " " -log "Modem Type $SP" -log " " -if [ $SP -gt 0 ]; then - if [ $SP -eq 3 ]; then - PORTN=0 - elif [ $SP -eq 4 ]; then - PORTN=2 - elif [ $SP -eq 5 ]; then - [ $idP = 6026 ] && PORTN=1 || PORTN=2 - elif [ $SP -eq 6 ]; then - PORTN=2 - elif [ $SP -eq 7 ]; then - PORTN=0 - elif [ $SP -eq 8 ]; then - PORTN=3 - elif [ $SP -eq 9 ]; then - PORTN=1 - else - PORTN=1 - fi - get_tty_fix $PORTN - lua $ROOTER/common/modemchk.lua "$idV" "$idP" "$CPORT" "$CPORT" - source /tmp/parmpass - - if [ "$ACM" = 1 ]; then - ACMPORT=$CPORT - CPORT="7$ACMPORT" - ln -fs /dev/ttyACM$ACMPORT /dev/ttyUSB$CPORT - fi - - log "Modem $CURRMODEM ECM Comm Port : /dev/ttyUSB$CPORT" - uci set modem.modem$CURRMODEM.commport=$CPORT - uci commit modem - - $ROOTER/sms/check_sms.sh $CURRMODEM & - - if [ -e $ROOTER/connect/preconnect.sh ]; then - $ROOTER/connect/preconnect.sh $CURRMODEM - fi - - if [ $SP = 5 ]; then - clck=$(uci -q get custom.bandlock.cenable$CURRMODEM) - if [ "$clck" = "1" ]; then - ear=$(uci -q get custom.bandlock.earfcn$CURRMODEM) - pc=$(uci -q get custom.bandlock.pci$CURRMODEM) - ear1=$(uci -q get custom.bandlock.earfcn1$CURRMODEM) - pc1=$(uci -q get custom.bandlock.pci1$CURRMODEM) - ear2=$(uci -q get custom.bandlock.earfcn2$CURRMODEM) - pc2=$(uci -q get custom.bandlock.pci2$CURRMODEM) - ear3=$(uci -q get custom.bandlock.earfcn3$CURRMODEM) - pc3=$(uci -q get custom.bandlock.pci3$CURRMODEM) - cnt=1 - earcnt=$ear","$pc - if [ "$ear1" != "0" -a $pc1 != "0" ]; then - earcnt=$earcnt","$ear1","$pc1 - let cnt=cnt+1 - fi - if [ "$ear2" != "0" -a $pc2 != "0" ]; then - earcnt=$earcnt","$ear2","$pc2 - let cnt=cnt+1 - fi - if [ "$ear3" != "0" -a $pc3 != "0" ]; then - earcnt=$earcnt","$ear3","$pc3 - let cnt=cnt+1 - fi - earcnt=$cnt","$earcnt - ATCMDD="at+qnwlock=\"common/4g\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log "$OX" - if `echo $OX | grep "ERROR" 1>/dev/null 2>&1` - then - ATCMDD="at+qnwlock=\"common/lte\",2,$ear,$pc" - else - ATCMDD=$ATCMDD","$earcnt - fi - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log "Cell Lock $OX" - sleep 10 - fi - $ROOTER/connect/bandmask $CURRMODEM 1 - uci commit modem - fi - - - if [ $SP = 4 ]; then - if [ -e /etc/interwave ]; then - idP=$(uci -q get modem.modem$CURRMODEM.idP) - idPP=${idP:1:1} - if [ "$idPP" = "1" ]; then - ATC="AT+GTRAT=17" - else - ATC="AT+XACT=4,2" - fi - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATC") - fi - $ROOTER/connect/bandmask $CURRMODEM 2 - uci commit modem - fi -fi - -if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 2 -fi - -$ROOTER/common/gettype.sh $CURRMODEM -$ROOTER/connect/get_profile.sh $CURRMODEM -if [ $SP -gt 0 ]; then - if [ -e $ROOTER/simlock.sh ]; then - $ROOTER/simlock.sh $CURRMODEM - fi - - if [ -e /tmp/simpin$CURRMODEM ]; then - log " SIM Error" - #exit 0 - fi - if [ -e /usr/lib/gps/gps.sh ]; then - /usr/lib/gps/gps.sh $CURRMODEM & - fi -fi - -INTER=$(uci -q get modem.modeminfo$CURRMODEM.inter) -if [ -z "$INTER" ]; then - INTER=$CURRMODEM -else - if [ "$INTER" = 0 ]; then - INTER=$CURRMODEM - fi -fi -log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" -OTHER=1 -if [ $CURRMODEM = 1 ]; then - OTHER=2 -fi -EMPTY=$(uci -q get modem.modem$OTHER.empty) -if [ "$EMPTY" = 0 ]; then - OINTER=$(uci -q get modem.modem$OTHER.inter) - if [ ! -z "$OINTER" ]; then - if [ $INTER = $OINTER ]; then - INTER=1 - if [ "$OINTER" = 1 ]; then - INTER=2 - fi - log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" - fi - fi -fi -uci set modem.modem$CURRMODEM.inter=$INTER -uci commit modem -log "Modem $CURRMODEM is using WAN$INTER" - -CID=$(uci -q get modem.modeminfo$CURRMODEM.context) -[ -z "$CID" ] && CID=1 - -log "Checking Network Interface" -ifname="$(if [ "$MATCH" ]; then for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH"; fi | xargs -r basename)" - -if [ "$ifname" ]; then - log "Modem $CURRMODEM ECM Data Port : $ifname" - set_network "$ifname" - uci set modem.modem$CURRMODEM.interface=$ifname - if [ -e $ROOTER/changedevice.sh ]; then - $ROOTER/changedevice.sh $ifname - fi -else - log "Modem $CURRMODEM - No ECM Data Port found" -fi -uci commit modem - -ttl=$(uci -q get modem.modeminfo$CURRMODEM.ttl) -if [ -z "$ttl" ]; then - ttl="0" -fi -hostless=$(uci -q get modem.modeminfo$CURRMODEM.hostless) -if [ "$ttl" != "0" -a "$ttl" != "1" -a "$ttl" != "TTL-INC 1" -a "$hostless" = "1" ]; then - let "ttl=$ttl+1" -fi -$ROOTER/connect/handlettl.sh $CURRMODEM "$ttl" - -if [ $SP -eq 2 ]; then - get_connect - export SETAPN=$NAPN - BRK=1 - - while [ $BRK -eq 1 ]; do - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-zecm.gcom" "$CURRMODEM") - chcklog "$OX" - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - else - BRK=0 - fi - done -fi - -if [ $SP -eq 4 ]; then - get_connect - export SETAPN=$NAPN - BRK=1 - - while [ $BRK -eq 1 ]; do - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-fecm.gcom" "$CURRMODEM") - chcklog "$OX" - log " " - log "Fibocom Connect : $OX" - log " " - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - else - BRK=0 - get_ip - fi - done -fi - -if [ $SP = 8 -o $SP = 9 ]; then - log "FM350 Connection Command" - $ROOTER/connect/bandmask $CURRMODEM 2 - uci commit modem - get_connect - export SETAPN=$NAPN - BRK=1 - - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-fecm.gcom" "$CURRMODEM") - chcklog "$OX" - log " " - log "Fibocom Connect : $OX" - log " " - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - log "Failed to Connect" - else - BRK=0 - get_ip - check_ip - fi -fi - -if [ $SP = 5 ]; then - get_connect - if [ -n "$NAPN" ]; then - $ROOTER/common/lockchk.sh $CURRMODEM - if [ $idP = 6026 ]; then - IPN=1 - case "$PDPT" in - "IPV6" ) - IPN=2 - ;; - "IPV4V6" ) - IPN=3 - ;; - esac - ATCMDD="AT+QICSGP=$CID,$IPN,\"$NAPN\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD="AT+QNETDEVCTL=2,$CID,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - else - check_apn - fi - fi - ATCMDD="AT+CNMI?" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo $OX | grep -o "+CNMI: [0-3],2," >/dev/null 2>&1`; then - ATCMDD="AT+CNMI=0,0,0,0,0" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ATCMDD="AT+QINDCFG=\"smsincoming\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then - ATCMDD="AT+QINDCFG=\"smsincoming\",0,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ATCMDD="AT+QINDCFG=\"all\"" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo $OX | grep -o ",1" >/dev/null 2>&1`; then - ATCMDD="AT+QINDCFG=\"all\",0,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - log "Quectel Unsolicited Responses Disabled" - $ROOTER/luci/celltype.sh $CURRMODEM - ATCMDD="AT+QINDCFG=\"all\",1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - - get_ip - if [ -n "$ip6" ]; then - check_ip - if [ "$v6cap" -gt 0 ]; then - addv6 - fi - fi -fi - -if [ $SP -eq 6 ]; then - get_connect - export SETAPN=$NAPN - BRK=1 - - while [ $BRK -eq 1 ]; do - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "connect-ncm.gcom" "$CURRMODEM") - chcklog "$OX" - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - else - BRK=0 - fi - done -fi - -if [ $SP -eq 7 ]; then - get_connect - export SETAPN=$NAPN - BRK=1 - - if [ -n "$NAPN" ]; then - check_apn - fi - - while [ $BRK -eq 1 ]; do - ATCMDD="AT\$ECMCALL=1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - chcklog "$OX" - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Connect : Retrying" - else - BRK=0 - get_ip - if [ -n "$ip6" ]; then - check_ip - if [ "$v6cap" -gt 0 ]; then - addv6 - fi - fi - fi - done -fi - -rm -f /tmp/usbwait - -ifup wan$INTER -while `ifstatus wan$INTER | grep -q '"up": false\|"pending": true'`; do - sleep 1 -done -wan_ip=$(expr "`ifstatus wan$INTER | grep '"nexthop":'`" : '.*"nexthop": "\(.*\)"') -if [ $? -ne 0 ] ; then - wan_ip=192.168.0.1 -fi -uci set modem.modem$CURRMODEM.ip=$wan_ip -uci commit modem - -if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 3 -fi - -$ROOTER/log/logger "HostlessModem #$CURRMODEM Connected with IP $wan_ip" - -PROT=5 - -if [ $SP -gt 1 ]; then - ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & -else - VENDOR=$(uci -q get modem.modem$CURRMODEM.idV) - case $VENDOR in - "19d2" ) - TIMEOUT=3 - wget -O /tmp/connect.file http://$wan_ip/goform/goform_set_cmd_process?goformId=CONNECT_NETWORK & - handle_timeout "$!" - ln -s $ROOTER/signal/ztehostless.sh $ROOTER_LINK/getsignal$CURRMODEM - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - ;; - "12d1" ) - log "Huawei Hostless" - ln -s $ROOTER/signal/huaweihostless.sh $ROOTER_LINK/getsignal$CURRMODEM - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - ;; - * ) - log "Other Hostless" - ln -s $ROOTER/signal/otherhostless.sh $ROOTER_LINK/getsignal$CURRMODEM - $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - ;; -esac -fi - -ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM -$ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & -uci set modem.modem$CURRMODEM.connected=1 -uci commit modem - -if [ $SP -gt 0 ]; then - if [ -e $ROOTER/connect/postconnect.sh ]; then - $ROOTER/connect/postconnect.sh $CURRMODEM - fi - if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then - ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) - if [ -n "$ATCMDD" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - ERROR="ERROR" - if `echo $OX | grep "$ERROR" 1>/dev/null 2>&1` - then - log "Error sending custom AT command: $ATCMDD with result: $OX" - else - log "Sent custom AT command: $ATCMDD with result: $OX" - fi - fi - fi - - if [ -e $ROOTER/timezone.sh ]; then - TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) - if [ "$TZ" = "1" ]; then - log "Set TimeZone" - $ROOTER/timezone.sh & - fi - fi -fi - -#CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) -CLB=1 -if [ -e /etc/config/mwan3 ]; then - ENB=$(uci -q get mwan3.wan$INTER.enabled) - if [ ! -z "$ENB" ]; then - if [ "$CLB" = "1" ]; then - uci set mwan3.wan$INTER.enabled=1 - else - uci set mwan3.wan$INTER.enabled=0 - fi - uci commit mwan3 - /usr/sbin/mwan3 restart - fi -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh deleted file mode 100644 index c9fda31..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/create_iphone.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Create iPhone Connection $CURRMODEM" "$@" -} - - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -handle_timeout(){ - local wget_pid="$1" - local count=0 - ps | grep -v grep | grep $wget_pid - res="$?" - while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do - sleep 1 - count=$((count+1)) - ps | grep -v grep | grep $wget_pid - res="$?" - done - - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill "$wget_pid" 2> /dev/null - ps | grep -v grep | grep $wget_pid - res="$?" - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill -9 $wget_pid 2> /dev/null - fi - fi -} - -set_dns() { - local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) - local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) - local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) - local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) - - local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" - local bDNS="" - - echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null - if [ $? = 0 ]; then - log "Using DNS settings from the Connection Profile" - pdns=1 - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - - bDNS=$(echo $bDNS) - uci set network.wan$INTER.peerdns=0 - uci set network.wan$INTER.dns="$bDNS" - echo "$bDNS" > /tmp/v4dns$INTER - - bDNS="" - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - echo "$bDNS" > /tmp/v6dns$INTER - else - log "Using Hostless Modem as a DNS" - pdns=0 - rm -f /tmp/v[46]dns$INTER - fi -} - -set_network() { - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=dhcp - uci set network.wan$INTER.${ifname1}=$1 - uci set network.wan$INTER.metric=$INTER"0" - set_dns - uci commit network - sleep 5 -} - -save_variables() { - echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file - echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file - echo 'USBN="'"$USBN"'"' >> /tmp/variable.file - echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file - echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file - echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file -} - -chcklog() { - OOX=$1 - CLOG=$(uci -q get modem.modeminfo$CURRMODEM.log) - if [ $CLOG = "1" ]; then - log "$OOX" - fi -} - - -CURRMODEM=$1 - -MAN=$(uci get modem.modem$CURRMODEM.manuf) -MOD=$(uci get modem.modem$CURRMODEM.model) -$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Connecting" -$ROOTER/log/logger "Attempting to Connect Modem #$CURRMODEM ($MAN $MOD)" - -BASEP=$(uci -q get modem.modem$CURRMODEM.baseport) -idV=$(uci get modem.modem$CURRMODEM.idV) -idP=$(uci get modem.modem$CURRMODEM.idP) - -$ROOTER/connect/get_profile.sh $CURRMODEM - -INTER=$(uci get modem.modeminfo$CURRMODEM.inter) -if [ -z $INTER ]; then - INTER=$CURRMODEM -else - if [ $INTER = 0 ]; then - INTER=$CURRMODEM - fi -fi -log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" -OTHER=1 -if [ $CURRMODEM = 1 ]; then - OTHER=2 -fi -EMPTY=$(uci get modem.modem$OTHER.empty) -if [ $EMPTY = 0 ]; then - OINTER=$(uci get modem.modem$OTHER.inter) - if [ ! -z $OINTER ]; then - if [ $INTER = $OINTER ]; then - INTER=1 - if [ $OINTER = 1 ]; then - INTER=2 - fi - log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" - fi - fi -fi -uci set modem.modem$CURRMODEM.inter=$INTER -uci commit modem -log "Modem $CURRMODEM is using WAN$INTER" - -log "Checking Network Interface" -MATCH="$(uci get modem.modem$CURRMODEM.maxcontrol | cut -d/ -f3- | xargs dirname)" -ifname="$(if [ "$MATCH" ]; then for a in /sys/class/net/*; do readlink $a; done | grep "$MATCH"; fi | xargs -r basename)" - -if [ "$ifname" ]; then - log "Modem $CURRMODEM - iPhone - Data Port : $ifname" - set_network "$ifname" - uci set modem.modem$CURRMODEM.interface=$ifname -else - log "Modem $CURRMODEM - No iPhone Data Port found" -fi -uci commit modem - -rm -f /tmp/usbwait - -ifup wan$INTER -while `ifstatus wan$INTER | grep -q '"up": false\|"pending": true'`; do - sleep 1 -done -wan_ip=$(expr "`ifstatus wan$INTER | grep '"nexthop":'`" : '.*"nexthop": "\(.*\)"') -if [ $? -ne 0 ] ; then - wan_ip=192.168.0.1 -fi -uci set modem.modem$CURRMODEM.ip=$wan_ip -uci commit modem - -log "saving Trusted locks" -for file in `ls /var/lib/lockdown | grep -v SystemConfiguration.plist`; -do - if [ ! -f "/etc/lockdown/locks/$file" ];then - cp /var/lib/lockdown/$file /etc/lockdown/locks/ - else - new_md5=`md5sum /var/lib/lockdown/$file | awk -F" " '{print $1}'` - old_md5=`md5sum /etc/lockdown/locks/$file | awk -F" " '{print $1}'` - if [ "$new_md5" != "$old_md5" ];then - cp /var/lib/lockdown/$file /etc/lockdown/locks/ - fi - fi -done - -$ROOTER/log/logger "iPhone #$CURRMODEM Connected with IP $wan_ip" - -ln -s $ROOTER/signal/otherhostless.sh $ROOTER_LINK/getsignal$CURRMODEM -$ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & - -ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM -$ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & -uci set modem.modem$CURRMODEM.connected=1 -uci commit modem - -if [ -e $ROOTER/timezone.sh ]; then - TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) - if [ "$TZ" = "1" ]; then - log "Set TimeZone" - $ROOTER/timezone.sh & - fi -fi - -#CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) -CLB=1 -if [ -e /etc/config/mwan3 ]; then - ENB=$(uci -q get mwan3.wan$INTER.enabled) - if [ ! -z $ENB ]; then - if [ $CLB = "1" ]; then - uci set mwan3.wan$INTER.enabled=1 - else - uci set mwan3.wan$INTER.enabled=0 - fi - uci commit mwan3 - /usr/sbin/mwan3 restart - fi -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh deleted file mode 100644 index 9cef8b9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disablemw3.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -CURRMODEM=$1 - -if [ -e /etc/config/mwan3 ]; then - INTER=$(uci get modem.modeminfo$CURRMODEM.inter) - ENB=$(uci get mwan3.wan$INTER.enabled) - if [ ! -z $ENB ]; then - uci set mwan3.wan$INTER.enabled=0 - uci commit mwan3 - fi -fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh deleted file mode 100644 index bde1749..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/disconnect.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" -TIMEOUT=10 - -log() { - modlog "Disconnect Modem $CURRMODEM" "$@" -} - -handle_timeout(){ - local wget_pid="$1" - local count=0 - res=1 - if [ -d /proc/${wget_pid} ]; then - res=0 - fi - while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do - sleep 1 - count=$((count+1)) - res=1 - if [ -d /proc/${wget_pid} ]; then - res=0 - fi - done - - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill "$wget_pid" 2> /dev/null - res=1 - if [ -d /proc/${wget_pid} ]; then - res=0 - fi - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill -9 $wget_pid 2> /dev/null - fi - fi -} - -CURRMODEM=$(uci get modem.general.miscnum) -uci set modem.modem$CURRMODEM.connected=0 -uci commit modem -INTER=$(uci get modem.modeminfo$CURRMODEM.inter) - -jkillall getsignal$CURRMODEM -rm -f $ROOTER_LINK/getsignal$CURRMODEM -jkillall con_monitor$CURRMODEM -rm -f $ROOTER_LINK/con_monitor$CURRMODEM -ifdown wan$INTER - -MAN=$(uci get modem.modem$CURRMODEM.manuf) -MOD=$(uci get modem.modem$CURRMODEM.model) -$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Disconnected" - -PROT=$(uci get modem.modem$CURRMODEM.proto) -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -case $PROT in -"30" ) - ATCMDD="AT+CFUN=0" - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD" - ;; -"3" ) - WDMNX=$(uci get modem.modem$CURRMODEM.wdm) - umbim -n -t 3 -d /dev/cdc-wdm$WDMNX disconnect - ;; -* ) - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" - ;; -esac - -$ROOTER/log/logger "Modem #$CURRMODEM was Manually Disconnected" diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh deleted file mode 100644 index 89c5194..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/get_profile.sh +++ /dev/null @@ -1,423 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Get Profile $CURRMODEM" "$@" -} - -CURRMODEM=$1 - -MODEL=$(uci get modem.modem$CURRMODEM.model) -MANUF=$(uci get modem.modem$CURRMODEM.manuf) -idV=$(uci get modem.modem$CURRMODEM.idV) -idP=$(uci get modem.modem$CURRMODEM.idP) -IMEI=$(uci get modem.modem$CURRMODEM.imei) -IMSI=$(uci -q get modem.modem$CURRMODEM.imsi) -ICCID=$(uci get modem.modem$CURRMODEM.iccid) - -log "Modem $CURRMODEM is $MANUF $MODEL" - -rm -f /tmp/profile$CURRMODEM - -if [ "$IMSI" = "Unknown" ]; then - log "Warning: IMSI cannot be read - SIM card missing or locked?" - touch /tmp/simerr$CURRMODEM -else - rm -f /tmp/simerr$CURRMODEM -fi - -MATCH=0 - -do_custom() { - local config=$1 - local select name enabled select1 - local model - local imsi - local vid - local pid - - if [ $MATCH -eq 0 ]; then - config_get select $1 select - config_get name $1 name - config_get enabled $1 enabled - if [ -z "$enabled" ]; then - enabled=1 - fi - if [ -z "$name" ]; then - name="Not Named" - fi - if [ $enabled -eq 1 ]; then - case $select in - "0" ) - config_get vid $1 vid - config_get pid $1 pid - if [ $idV = $vid -a $idP = $pid ]; then - MATCH=1 - log "Modem ID Profile - "$name"" - fi - ;; - "1" ) - config_get imei $1 imei - case $IMEI in - "$imei"*) - MATCH=1 - log "SIM IMEI Profile - "$name"" - ;; - esac - ;; - "2" ) - config_get model $1 model - if [ "$MODEL" == "$model" ]; then - MATCH=1 - log "Modem Model Profile - "$name"" - fi - ;; - "3" ) - config_get imsi $1 imsi - case $IMSI in - "$imsi"*) - MATCH=1 - log "SIM IMSI Profile - "$name"" - ;; - esac - ;; - "4" ) - config_get iccid $1 iccid - case $ICCID in - "$iccid"*) - MATCH=1 - log "SIM ICCID Profile - "$name"" - ;; - esac - ;; - esac - if [ $MATCH = 1 ]; then - config_get select1 $1 select1 - if [ $select1 -ne 10 ]; then - MATCH=0 - case $select1 in - "0" ) - config_get vid1 $1 vid1 - config_get pid1 $1 pid1 - if [ $idV = $vid1 -a $idP = $pid1 ]; then - MATCH=1 - log "Modem ID Profile - "$name"" - fi - ;; - "1" ) - config_get imei1 $1 imei1 - case $IMEI in - "$imei"*) - MATCH=1 - log "SIM IMEI Profile - "$name"" - ;; - esac - ;; - "2" ) - config_get model1 $1 model1 - if [ "$MODEL" == "$model1" ]; then - MATCH=1 - log "Modem Model Profile - "$name"" - fi - ;; - "3" ) - config_get imsi1 $1 imsi1 - case $IMSI in - "$imsi1"*) - MATCH=1 - log "SIM IMSI Profile - "$name"" - ;; - esac - ;; - "4" ) - config_get iccid1 $1 iccid1 - case $ICCID in - "$iccid1"*) - MATCH=1 - log "SIM ICCID Profile - "$name"" - ;; - esac - ;; - esac - fi - if [ $MATCH = 1 ]; then - local apn user passw pincode auth ppp delay lock mcc mnc - local dns1 dns2 dns3 dns4 log lb at atc - config_get apn $1 apn - dapn=$(echo "$apn" | grep "|") - if [ -z $dapn ]; then - apn2="" - else - fapn=$apn"|" - fapn=$(echo $fapn" " | tr "|" ",") - apn=$(echo $fapn | cut -d, -f1) - apn2=$(echo $fapn | cut -d, -f2) - fi - uci set modem.modeminfo$CURRMODEM.apn=$apn - uci set modem.modeminfo$CURRMODEM.apn2=$apn2 - config_get mtu $1 mtu - uci set modem.modeminfo$CURRMODEM.mtu=$mtu - config_get context $1 context - uci set modem.modeminfo$CURRMODEM.context=$context - config_get user $1 user - uci set modem.modeminfo$CURRMODEM.user=$user - config_get passw $1 passw - uci set modem.modeminfo$CURRMODEM.passw=$passw - config_get pincode $1 pincode - uci set modem.modeminfo$CURRMODEM.pincode=$pincode - config_get auth $1 auth - uci set modem.modeminfo$CURRMODEM.auth=$auth - config_get ppp $1 ppp - uci set modem.modeminfo$CURRMODEM.ppp=$ppp - config_get inter $1 inter - uci set modem.modeminfo$CURRMODEM.inter=$inter - config_get delay $1 delay - uci set modem.modeminfo$CURRMODEM.delay=$delay - config_get lock $1 lock - uci set modem.modeminfo$CURRMODEM.lock=$lock - config_get mcc $1 mcc - uci set modem.modeminfo$CURRMODEM.mcc=$mcc - config_get mnc $1 mnc - uci set modem.modeminfo$CURRMODEM.mnc=$mnc - config_get dns1 $1 dns1 - uci set modem.modeminfo$CURRMODEM.dns1=$dns1 - config_get dns2 $1 dns2 - uci set modem.modeminfo$CURRMODEM.dns2=$dns2 - config_get dns3 $1 dns3 - uci set modem.modeminfo$CURRMODEM.dns3=$dns3 - config_get dns4 $1 dns4 - uci set modem.modeminfo$CURRMODEM.dns4=$dns4 - config_get log $1 log - uci set modem.modeminfo$CURRMODEM.log=$log - config_get lb $1 lb - uci set modem.modeminfo$CURRMODEM.lb=$lb - config_get at $1 at - uci set modem.modeminfo$CURRMODEM.at=$at - config_get atc $1 atc - uci set modem.modeminfo$CURRMODEM.atc=$atc - config_get tzone $1 tzone - uci set modem.modeminfo$CURRMODEM.tzone=$tzone - config_get nodhcp $1 nodhcp - uci set modem.modeminfo$CURRMODEM.nodhcp=$nodhcp - config_get pdptype $1 pdptype - if [ $pdptype = "0" ]; then - pdptype="" - fi - uci set modem.modeminfo$CURRMODEM.pdptype=$pdptype - config_get ttl $1 ttl - if [ -z "$ttl" ]; then - ttl="0" - fi - uci set modem.modeminfo$CURRMODEM.ttl="$ttl" - config_get hostless $1 hostless - if [ -z "$hostless" ]; then - hostless="0" - fi - uci set modem.modeminfo$CURRMODEM.hostless="$hostless" - config_get bwday $1 bwday - if [ -z $bwday ]; then - bwday="0" - fi - uci set modem.modeminfo$CURRMODEM.bwday=$bwday - config_get phone $1 phone - if [ -z $phone ]; then - phone="0" - fi - uci set modem.modeminfo$CURRMODEM.bwphone=$phone - config_get bwdelay $1 bwdelay - if [ -z $bwdelay ]; then - bwdelay="0" - fi - uci set modem.modeminfo$CURRMODEM.bwdelay=$bwdelay - - [ -n "$apn" ] || log "This profile has no APN configured !!!" - - config_get alive $1 alive - uci delete modem.pinginfo$CURRMODEM - uci set modem.pinginfo$CURRMODEM=pinfo$CURRMODEM - uci set modem.pinginfo$CURRMODEM.alive=$alive - if [ $alive -ne 0 ]; then - local reliability count pingtime pingwait packetsize down up - - handle_trackip() { - local value="$1" - uci add_list modem.pinginfo$CURRMODEM.trackip=$value - } - config_list_foreach "$config" trackip handle_trackip - TIP=$(uci get modem.pinginfo$CURRMODEM.trackip) - if [ -z "$TIP" ]; then - uci add_list modem.pinginfo$CURRMODEM.trackip="1.1.1.1" - fi - config_get reliability $1 reliability - uci set modem.pinginfo$CURRMODEM.reliability=$reliability - config_get count $1 count - uci set modem.pinginfo$CURRMODEM.count=$count - config_get pingtime $1 pingtime - uci set modem.pinginfo$CURRMODEM.pingtime=$pingtime - config_get pingwait $1 pingwait - uci set modem.pinginfo$CURRMODEM.pingwait=$pingwait - config_get packetsize $1 packetsize - uci set modem.pinginfo$CURRMODEM.packetsize=$packetsize - config_get down $1 down - uci set modem.pinginfo$CURRMODEM.down=$down - config_get up $1 up - uci set modem.pinginfo$CURRMODEM.up=$up - fi - - uci commit modem - fi - fi - fi - fi -} - -autoapn=$(uci -q get profile.disable.autoapn) -apd=0 -if [ -e /usr/lib/autoapn/apn.data ]; then - apd=1 -fi - -if [ $autoapn = "1" -a $apd -eq 1 ]; then - MATCH=0 -else - autod=$(uci -q get profile.disable.enabled) - if [ $autod = "1" ]; then - MATCH=0 - else - config_load profile - config_foreach do_custom custom - fi -fi - -if [ $MATCH = 0 ]; then - if [ $autod = "1" ]; then - if [ -e /etc/config/isp ]; then - MATCH=1 - fi - fi - if [ $MATCH = 1 ]; then - isp=$(uci -q get isp.general.current) - apn=$(uci -q get isp.$isp.apn) - apn2="" - else - apn=$(uci -q get profile.default.apn) - dapn=$(echo "$apn" | grep "|") - if [ -z $dapn ]; then - apn2="" - else - fapn=$apn"|" - fapn=$(echo $fapn" " | tr "|" ",") - apn=$(echo $fapn | cut -d, -f1) - apn2=$(echo $fapn | cut -d, -f2) - fi - fi - uci set modem.modeminfo$CURRMODEM.apn=$apn - uci set modem.modeminfo$CURRMODEM.apn2=$apn2 - if [ -n "$ICCID" ]; then - iccid="891490" - case $ICCID in - "$iccid"*) - uci set modem.modeminfo$CURRMODEM.apn2="" - uci set modem.modeminfo$CURRMODEM.apn="internet.freedommobile.ca" - ;; - esac - fi - - uci set modem.modeminfo$CURRMODEM.user=$(uci -q get profile.default.user) - uci set modem.modeminfo$CURRMODEM.passw=$(uci -q get profile.default.passw) - uci set modem.modeminfo$CURRMODEM.pincode=$(uci -q get profile.default.pincode) - uci set modem.modeminfo$CURRMODEM.context=$(uci -q get profile.default.context) - uci set modem.modeminfo$CURRMODEM.auth=$(uci get profile.default.auth) - uci set modem.modeminfo$CURRMODEM.ppp=$(uci get profile.default.ppp) - uci set modem.modeminfo$CURRMODEM.inter=0 - uci set modem.modeminfo$CURRMODEM.delay=$(uci get profile.default.delay) - uci set modem.modeminfo$CURRMODEM.lock=$(uci get profile.default.lock) - uci set modem.modeminfo$CURRMODEM.mcc=$(uci -q get profile.default.mcc) - uci set modem.modeminfo$CURRMODEM.mnc=$(uci -q get profile.default.mnc) - uci set modem.modeminfo$CURRMODEM.dns1=$(uci -q get profile.default.dns1) - uci set modem.modeminfo$CURRMODEM.dns2=$(uci -q get profile.default.dns2) - uci set modem.modeminfo$CURRMODEM.dns3=$(uci -q get profile.default.dns3) - uci set modem.modeminfo$CURRMODEM.dns4=$(uci -q get profile.default.dns4) - uci set modem.modeminfo$CURRMODEM.log=$(uci get profile.default.log) - uci set modem.modeminfo$CURRMODEM.lb=$(uci get profile.default.lb) - uci set modem.modeminfo$CURRMODEM.at=$(uci -q get profile.default.at) - uci set modem.modeminfo$CURRMODEM.atc=$(uci -q get profile.default.atc) - uci set modem.modeminfo$CURRMODEM.tzone=$(uci -q get profile.default.tzone) - uci set modem.modeminfo$CURRMODEM.mtu=$(uci -q get profile.default.mtu) - uci set modem.modeminfo$CURRMODEM.nodhcp=$(uci -q get profile.default.nodhcp) - pdp=$(uci -q get profile.default.pdptype) - if [ $pdp = "0" ]; then - pdp="" - fi - uci set modem.modeminfo$CURRMODEM.pdptype=$pdp - ttl=$(uci -q get profile.default.ttl) - if [ -z "$ttl" ]; then - ttl="0" - fi - uci set modem.modeminfo$CURRMODEM.ttl="$ttl" - hostless=$(uci -q get profile.default.hostless) - if [ -z "$hostless" ]; then - hostless="0" - fi - uci set modem.modeminfo$CURRMODEM.hostless="$hostless" - bwday=$(uci -q get profile.default.bwday) - if [ -z $bwday ]; then - bwday="0" - fi - uci set modem.modeminfo$CURRMODEM.bwday=$bwday - phone=$(uci -q get profile.default.phone) - if [ -z $phone ]; then - phone="0" - fi - uci set modem.modeminfo$CURRMODEM.bwphone=$phone - bwdelay=$(uci -q get profile.default.bwdelay) - if [ -z $bwdelay ]; then - bwdelay="0" - fi - uci set modem.modeminfo$CURRMODEM.bwdelay=$bwdelay - - alive=$(uci get profile.default.alive) - uci delete modem.pinginfo$CURRMODEM - uci set modem.pinginfo$CURRMODEM=pinfo$CURRMODEM - uci set modem.pinginfo$CURRMODEM.alive=$alive - if [ $alive -ne 0 ]; then - - handle_trackip1() { - local value="$1" - uci add_list modem.pinginfo$CURRMODEM.trackip=$value - } - config_list_foreach "default" trackip handle_trackip1 - TIP=$(uci get modem.pinginfo$CURRMODEM.trackip) - if [ -z "$TIP" ]; then - uci add_list modem.pinginfo$CURRMODEM.trackip="1.1.1.1" - fi - uci set modem.pinginfo$CURRMODEM.reliability=$(uci get profile.default.reliability) - uci set modem.pinginfo$CURRMODEM.count=$(uci get profile.default.count) - uci set modem.pinginfo$CURRMODEM.pingtime=$(uci get profile.default.pingtime) - uci set modem.pinginfo$CURRMODEM.pingwait=$(uci get profile.default.pingwait) - uci set modem.pinginfo$CURRMODEM.packetsize=$(uci get profile.default.packetsize) - uci set modem.pinginfo$CURRMODEM.down=$(uci get profile.default.down) - uci set modem.pinginfo$CURRMODEM.up=$(uci get profile.default.up) - fi - - uci commit modem - if [ "$autoapn" = "1" -a $apd -eq 1 ]; then - log "Automatic APN Used" - else - log "Default Profile Used" - [ -n "$(uci -q get profile.default.apn)" ] || log "Default profile has no APN configured" - fi -fi - -if [ ! -e /etc/config/isp ]; then - if [ "$autoapn" != "1" -a $apd -eq 1 ]; then - APN=$(uci -q get modem.modeminfo$CURRMODEM.apn) - log "APN of profile used is $APN" - fi -fi - -touch /tmp/profile$CURRMODEM diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh deleted file mode 100644 index fe216c6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/handlettl.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/sh - -log() { - modlog "TTL Settings $CURRMODEM" "$@" -} - -delTTL() { - FLG="0" - exst=$(cat /etc/ttl.user | grep "#startTTL$CURRMODEM") - if [ ! -z "$exst" ]; then - cp /etc/ttl.user /etc/ttl.user.bk - sed -i -e "s!iptables -t mangle -I POSTROUTING -o $IFACE!iptables -t mangle -D POSTROUTING -o $IFACE!g" /etc/ttl.user.bk - sed -i -e "s!iptables -t mangle -I PREROUTING -i $IFACE!iptables -t mangle -D PREROUTING -i $IFACE!g" /etc/ttl.user.bk - sed -i -e "s!ip6tables -t mangle -I POSTROUTING -o $IFACE!iptables -t mangle -D POSTROUTING -o $IFACE!g" /etc/ttl.user.bk - sed -i -e "s!ip6tables -t mangle -I PREROUTING -i $IFACE!iptables -t mangle -D PREROUTING -i $IFACE!g" /etc/ttl.user.bk - - rm -f /tmp/ttl.user - run=0 - while IFS= read -r line; do - if [ $run = "0" ]; then - sttl=$line - stx=$(echo "$sttl" | grep "#startTTL$CURRMODEM") - if [ ! -z $stx ]; then - run=1 - fi - else - sttl=$line - stx=$(echo "$sttl" | grep "#endTTL$CURRMODEM") - if [ ! -z $stx ]; then - chmod 777 /tmp/ttl.user - /tmp/ttl.user - break - fi - echo "$sttl" >> /tmp/ttl.user - fi - done < /etc/ttl.user.bk - cp /etc/ttl.user /etc/ttl.user.bk - - sed /"#startTTL$CURRMODEM"/,/"#endTTL$CURRMODEM"/d /etc/ttl.user.bk > /etc/ttl.user - FLG="1" - fi -} - -CURRMODEM=$1 -TTL="$2" -if [ $CURRMODEM = "0" ]; then - IFACE="wan" -else - IFACE=$(uci -q get modem.modem$CURRMODEM.interface) -fi - -if [ "$TTL" = "0" ]; then - ENB=$(uci -q get ttl.ttl.enabled) - if [ $ENB = "1" ]; then - TTL=$(uci -q get ttl.ttl.value) - if [ -z "$TTL" ]; then - TTL=65 - fi - else - delTTL - log "Deleting TTL on interface $IFACE" - exit 0 - fi -fi - -if [ "$TTL" = "1" ]; then - delTTL - log "Deleting TTL on interface $IFACE" - exit 0 -fi - -delTTL -VALUE="$TTL" -echo "#startTTL$CURRMODEM" >> /etc/ttl.user -log "Setting TTL $VALUE on interface $IFACE" -if [ "$TTL" = "TTL-INC 1" ]; then - TTL="0" -fi - -if [ $VALUE = "0" ]; then - echo "iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-inc 1" >> /etc/ttl.user - echo "iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-inc 1" >> /etc/ttl.user - iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-inc 1 - iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-inc 1 - if [ -e /usr/sbin/ip6tables ]; then - echo "ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-inc 1" >> /etc/ttl.user - echo "ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-inc 1" >> /etc/ttl.user - ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-inc 1 - ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-inc 1 - fi -else - echo "iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-set $VALUE" >> /etc/ttl.user - echo "iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-set $VALUE" >> /etc/ttl.user - iptables -t mangle -I POSTROUTING -o $IFACE -j TTL --ttl-set $VALUE - iptables -t mangle -I PREROUTING -i $IFACE -j TTL --ttl-set $VALUE - if [ -e /usr/sbin/ip6tables ]; then - echo "ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-set $VALUE" >> /etc/ttl.user - echo "ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-set $VALUE" >> /etc/ttl.user - ip6tables -t mangle -I POSTROUTING -o $IFACE -j HL --hl-set $VALUE - ip6tables -t mangle -I PREROUTING -i $IFACE -j HL --hl-set $VALUE - fi -fi -echo "#endTTL$CURRMODEM" >> /etc/ttl.user - - - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh deleted file mode 100644 index 12ec93e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/postconnect.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "PostConnect $CURRMODEM" "$@" -} - -CURRMODEM=$1 -idV=$(uci -q get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -log "Running PostConnect script" - -if [ -e /usr/lib/scan/emailchk.sh ]; then - /usr/lib/scan/emailchk.sh & -fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh deleted file mode 100644 index 92bef6f..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/preconnect.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "PreConnect $CURRMODEM" "$@" -} - -CURRMODEM=$1 -idV=$(uci -q get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -log "Running PreConnect script" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh deleted file mode 100644 index 26e6ccf..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect-ppp.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - logger -t "Reconnect Modem" "$@" -} - -CURRMODEM=$1 -uci set modem.modem$CURRMODEM.connected=0 -uci commit modem - -INTER=$(uci get modem.modeminfo$CURRMODEM.inter) - -jkillall getsignal$CURRMODEM -rm -f $ROOTER_LINK/getsignal$CURRMODEM -jkillall con_monitor$CURRMODEM -rm -f $ROOTER_LINK/con_monitor$CURRMODEM -ifdown wan$INTER -MAN=$(uci get modem.modem$CURRMODEM.manuf) -MOD=$(uci get modem.modem$CURRMODEM.model) -$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Reconnecting" -PROT=$(uci get modem.modem$CURRMODEM.proto) - -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -SEVR=$(uci get modem.modem$CURRMODEM.service) - -if [ $SEVR = 0 ]; then - COUNTER=1 - while [ $COUNTER -lt 6 ]; do - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM") - ERROR="ERROR" - if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` - then - log "Retry Reset" - sleep 3 - let COUNTER=COUNTER+1 - else - log "Modem Reset" - sleep 3 - $ROOTER/common/lockchk.sh $CURRMODEM - break - fi - done - if [ $COUNTER -lt 6 ]; then - ifup wan$INTER - else - log "Reset Failed for Modem $CURRMODEM" - $ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Failed to Reset" - fi -else - ifup wan$INTER -fi - - - - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh deleted file mode 100644 index 98ba291..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/connect/reconnect.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -ROOTER_LINK="/tmp/links" - -log() { - modlog "Reconnect Modem $CURRMODEM" "$@" -} - -CURRMODEM=$1 -log "Re-starting Connection for Modem $CURRMODEM" -$ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM 1 - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua deleted file mode 100644 index 464217d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/customname.lua +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/lua - -mfile = "/tmp/sysinfo/model" -nfile="/etc/custom" -local file = io.open(nfile, "r") -if file == nil then - return -end -linex = file:read("*line") -file:close() -file = io.open(mfile, "w") -if file == nil then - return -end - -file:write(linex,"\n") -file:close() \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom deleted file mode 100644 index 73544d9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/auto.gcom +++ /dev/null @@ -1,31 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT!SCPROF?1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s -:continue -exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - print $s - return diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom deleted file mode 100644 index 84149d6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/baseinfo.gcom +++ /dev/null @@ -1,33 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 1 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "ATI^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CGEQNEG=1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom deleted file mode 100644 index 6ced05d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo.gcom +++ /dev/null @@ -1,50 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CREG=2;+CREG?;+CREG=0^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CEREG=2;+CEREG?;+CEREG=0^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+C5GREG=2;+C5GREG?;+C5GREG=0^m" -let t=time()+f -gosub noerror -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - -:noerror -get 1 "^m" $s -if $mid($s,0,6)="^jERROR" return -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto noerror diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom deleted file mode 100644 index 4a72dd0..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cellinfo0.gcom +++ /dev/null @@ -1,45 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+COPS=3,0;+COPS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+COPS=3,2;+COPS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - -:noerror -get 1 "^m" $s -if $mid($s,0,6)="^jERROR" return -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto noerror diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom deleted file mode 100644 index 126aef6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/cgpaddr.gcom +++ /dev/null @@ -1,46 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CGPADDR=1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSINFOEX^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSINFO^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^NDISSTATQRY?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom deleted file mode 100644 index 00bc9e4..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-directip.gcom +++ /dev/null @@ -1,64 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT!SCACT=0,1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!SCDFTPROF=1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -let $x=$env("SETAPN") -let $y=$env("SETUSER") -let $z=$env("SETPASS") -let $a=$env("SETAUTH") -send "AT+CGDCONT=1,\"IP\",\"" -send $x -send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$QCPDPP=1," -send $a -if $a="0" send "^m" -else send ",\"" send $z send "\",\"" send $y send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!SCACT=1,1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!SCACT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom deleted file mode 100644 index 653f601..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-fecm.gcom +++ /dev/null @@ -1,45 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+GTRNDIS=0,1" -send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -let $x=$env("SETAPN") -send "AT+CGDCONT=1,\"IP\",\"" -send $x -send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+GTRNDIS=1,1" -send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom deleted file mode 100644 index 1fd4893..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ncm.gcom +++ /dev/null @@ -1,48 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT^^NDISDUP=1,0^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -let $x=$env("SETAPN") -let $y=$env("SETUSER") -let $z=$env("SETPASS") -let $a=$env("SETAUTH") -send "AT^^NDISDUP=1,1,\"" -send $x -if $a="0" send "\"^m" -else send "\",\"" send $y send "\",\"" send $z send "\"," send $a send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^NDISSTATQRY?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom deleted file mode 100644 index fadf2d8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-ppp.gcom +++ /dev/null @@ -1,36 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -let $y=$env("SETUSER") -let $z=$env("SETPASS") -let $a=$env("SETAUTH") -send "AT$QCPDPP=1," -send $a -if $a="0" send "^m" -else send ",\"" send $z send "\",\"" send $y send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom deleted file mode 100644 index fd14d94..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/connect-zecm.gcom +++ /dev/null @@ -1,45 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+ZECMCALL=0" -send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -let $x=$env("SETAPN") -send "AT+CGDCONT=1,\"IP\",\"" -send $x -send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZECMCALL=1" -send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom deleted file mode 100644 index 59f79da..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/curc.gcom +++ /dev/null @@ -1,31 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT\^CURC=0^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom deleted file mode 100644 index 72126b5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/fibocominfo.gcom +++ /dev/null @@ -1,65 +0,0 @@ -opengt -set com 115200n81 -set comecho off -set senddelay 0.02 -waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+GTCCINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s -if $s="^jERROR" goto gtrat - -send "AT+COPN^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:gtrat -send "AT+GTRAT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+GTCAINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+XACT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+XMCI=1;+XLEC?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+MTSM=1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked deleted file mode 100644 index ff816e2..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gcom-locked +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -log() { - logger -t "gcom-locked " "$@" -} - -ROOTER_GCOM="/usr/lib/rooter/gcom/" - - -PORT=$1 -GCOM=$2 -CURRMODEM=$3 -ATC=$4 - -LOCKDIR="/tmp/lockgcom$CURRMODEM" -PIDFILE="${LOCKDIR}/PID" - -while [ 1 -lt 6 ]; do - if mkdir "${LOCKDIR}" &>/dev/null; then - echo "$$" > "${PIDFILE}" - if [ ! -z "$ATC" ]; then - export ATCMD="$ATC" - fi - OX=$(gcom -d $PORT -s $ROOTER_GCOM$GCOM 2>/dev/null) - if [ ! -e /tmp/block ]; then - /usr/lib/rooter/log/at-logger "$PORT $OX" - fi - break - else - OTHERPID="$(cat "${PIDFILE}" 2>/dev/null)" - if [ $? = 0 ]; then - if ! kill -0 $OTHERPID &>/dev/null; then - rm -rf "${LOCKDIR}" - fi - fi - sleep 1 - fi -done - -rm -rf "${LOCKDIR}" -echo "$OX" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom deleted file mode 100644 index 77d733b..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/gettype.gcom +++ /dev/null @@ -1,43 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CFUN=1^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "ATI^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CNUM^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CPBR=?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom deleted file mode 100644 index cd9a091..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/huaweiinfo.gcom +++ /dev/null @@ -1,74 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^CSNR?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^HCSQ?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSINFOEX^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSCFGEX?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSCFG?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSINFO^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^HFREQINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^LTERSRP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^CHIPTEMP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom deleted file mode 100644 index 332890a..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/lock-prov.gcom +++ /dev/null @@ -1,38 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+COPS=0^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -let $x=$env("MCCMNC") -send "AT+COPS=1,2,\"" -send $x -send "\",2^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom deleted file mode 100644 index a647dac..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/mdm9215info.gcom +++ /dev/null @@ -1,43 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+COPS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$QCSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$QCSYSMODE?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom deleted file mode 100644 index 556874f..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/meiginfo.gcom +++ /dev/null @@ -1,69 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+PSRAT^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -if $s="^jERROR" goto newmodel - -send "AT+MODODR?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CELLINFO^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+SGCELLINFO^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -exit 0 - -:newmodel - -send "AT\^SYSCFGEX?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+SGCELLINFOEX^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CELLINFO=3^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom deleted file mode 100644 index e1a58e8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/novatelinfo.gcom +++ /dev/null @@ -1,48 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$NWRAT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$NWDEGC^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+VZWRSRP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+VZWRSRQ?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom deleted file mode 100644 index 6f851cd..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/otherinfo.gcom +++ /dev/null @@ -1,28 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom deleted file mode 100644 index 2ae0303..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quantainfo.gcom +++ /dev/null @@ -1,38 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT*QRFINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^QCNCFG?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom deleted file mode 100644 index 286acb9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/quectelinfo.gcom +++ /dev/null @@ -1,76 +0,0 @@ -opengt -set com 115200n81 -set comecho off -set senddelay 0.02 -waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+QENG=\"servingcell\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+QRSRP^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+QCAINFO^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+QCFG=\"nwscanmode\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s -if $s="^jERROR" goto qnwpref -goto temp - -:qnwpref -send "AT+QNWPREFCFG=\"mode_pref\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:temp -send "AT+QTEMP^m" -let t=time()+1 -gosub gettemp - -send "AT+QENG=\"neighbourcell\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - -:gettemp -get 1 "^m" $s -let x=len($s) -if x>0 print $s -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto gettemp diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom deleted file mode 100644 index cbdbf3e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/raw-ip.gcom +++ /dev/null @@ -1,31 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -let $x=$env("ATCMD") -send $x -send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jCONNECT" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom deleted file mode 100644 index 09e46f5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/reset.gcom +++ /dev/null @@ -1,25 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -//send "ate0^m" -//waitquiet 1 0.2 -send "AT+COPS=2;+CFUN=4^m" -waitfor 5 "OK" -sleep 5 -send "AT+CFUN?^m" -waitfor 5 "+CME ERROR:","+CFUN:" -if % = 0 goto cme_err -get 2 " " $s -if $left($s,1) = "1" goto end -sleep 5 -send "AT+CFUN=1^m" -waitquiet 1 0.2 -exit 0 - -:cme_err -print "+CME ERROR" -:end -exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom deleted file mode 100644 index b40dd6e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/run-at.gcom +++ /dev/null @@ -1,31 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g="" let f=25 -else let f=val($g) - -let $x=$env("ATCMD") -send $x -send "^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s -:continue -exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom deleted file mode 100644 index 7203af5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sendsms-at.gcom +++ /dev/null @@ -1,45 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start - -let $x=$env("ATCMD") -let $j=$left($x,1) -if $j = "0" let $j=$mid($x,1,2) -else let $j=$left($x,3) -let $r=$mid($x,4,4) -let k=len($x)-9 -let $p=$right($x,k) -send "AT+CMGF=0^m" -waitfor 2 "OK" -send "AT+CMGS=" -send $j -send "^m" -waitfor 3 ">" -send $p -send "^z" -waitfor 20 "+CMGS:" - -if % = 0 gosub sentsub -else gosub failsub - -get 1 "" $s - -:continue - exit 0 - -:sentsub -get 2 "^m^j" $s -let $c=$s -print "SMS sent, reference: "+$c -let $c='echo "SMS sent, reference: "'+$c+' > /tmp/smssendstatus'+$r -system $c -return - -:failsub -system 'echo "SMS sending failed" > /tmp/smssendstatus'+$r -print "SMS sending failed" -return diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom deleted file mode 100644 index 9b29c50..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setapn.gcom +++ /dev/null @@ -1,45 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -let $x=$env("SETAPN") -let $y=$env("SETUSER") -let $z=$env("SETPASS") -let $a=$env("SETAUTH") -send "AT+CGDCONT=1,\"IP\",\"" -send $x -send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$QCPDPP=1," -send $a -if $a="0" send "^m" -else send ",\"" send $z send "\",\"" send $y send "\"^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom deleted file mode 100644 index 9084557..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/setpin.gcom +++ /dev/null @@ -1,53 +0,0 @@ -# set pin code from evnironment "$PINCODE" -opengt - set com 115200n81 - set senddelay 0.05 - waitquiet 3 0.5 - flash 0.1 - - let c=0 -:start - send "AT+CPIN?^m" - waitfor 15 "SIM PUK","SIM PIN","READY","ERROR","ERR" - if % = -1 goto timeout - if % = 0 goto ready - if % = 1 goto setpin - if % = 2 goto ready - if % = 3 goto checkrepeat - if % = 4 goto checkrepeat - -:checkrepeat - inc c - if c>3 goto pinerror - waitquiet 12 0.5 - goto start - -:timeout - print "ERROR" - exit 1 - -:ready - goto continue - exit 0 - -:setpin - # check if output was "SIM PIN2", that's ok. - waitfor 1 "2" - if % = 0 goto ready - - send "AT+CPIN=\"" - send $env("PINCODE") - send "\"^m" - - waitfor 20 "OK","ERR" - if % = -1 goto pinerror - if % = 0 goto continue - if % = 1 goto pinerror - -:pinerror - print "ERROR" - exit 1 - -:continue - print "OK" - exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom deleted file mode 100644 index e24780c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/sierrainfo.gcom +++ /dev/null @@ -1,68 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ;+CESQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT*CNTI=0^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!SELRAT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ECIO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+RSCP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!UMTSCHAN?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!LTEINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!GSTATUS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT!PCTEMP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom deleted file mode 100644 index 50e45c9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/simcominfo.gcom +++ /dev/null @@ -1,48 +0,0 @@ -opengt -set com 115200n81 -set comecho off -set senddelay 0.02 -waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CPSI?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CNMP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CMGRMI=4^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CPMUTEMP^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom deleted file mode 100644 index f5d9e82..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smschk.gcom +++ /dev/null @@ -1,36 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CMGS=?;+CMGL=?;+CMGR=?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send 'AT+CPMS="SM","SM","SM"^m' -waitfor 5 "OK" - -send 'AT+CGSMS=2^m' -waitfor 5 "OK" - -:continue - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom deleted file mode 100644 index a65bb3c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/smswrite.gcom +++ /dev/null @@ -1,39 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 - -:start - -let $x=$env("ATCMD") -let $j=$left($x,1) -if $j = "0" let $j=$mid($x,1,2) -else let $j=$left($x,3) -let $d=$mid($x,4,2) -let $t=$mid($x,7,1) -let k=len($x)-9 -let $p=$right($x,k) -send "AT+CMGF=0^m" -waitfor 2 "OK" -send 'AT+CPMS="SM"' -send ',"' -send $d -send '"^m' -waitfor 2 "OK" -send "AT+CMGW=" -send $j -send "," -send $t -send "^m" -waitfor 3 ">" -send $p -send "^z" -waitfor 25 "+CMGW:" -if % = 0 print "+CMGW:" -else print "AT+CMGW - TIMEOUT" -get 1 "" $s -print $s - -:continue - exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom deleted file mode 100644 index f47d378..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/t77info.gcom +++ /dev/null @@ -1,70 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+COPS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^CA_INFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^DEBUG?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$DEBUG?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT\^SYSCONFIG?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT$QCSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+TEMP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -if $s!="^jERROR" exit 0 - -send "AT\^TEMP?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom deleted file mode 100644 index 5eaff94..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfo.gcom +++ /dev/null @@ -1,48 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT#TEMPSENS=2^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+COPS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT#RFSTS^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT#CAINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom deleted file mode 100644 index eb9bcbd..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/telitinfoln.gcom +++ /dev/null @@ -1,43 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+COPS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT^RFSTS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT#CAINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom deleted file mode 100644 index 9ebe9dc..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ubloxinfo.gcom +++ /dev/null @@ -1,43 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+CESQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+URAT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+UCGED?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom deleted file mode 100644 index 254da89..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/ussd.gcom +++ /dev/null @@ -1,29 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.05 - waitquiet 1 0.2 -:start -let f=20 -let $x=$env("ATCMD") -send $x+"^m" -waitfor 2 "OK" -let t=time()+f -let $s="" -gosub getresult -let x=len($s) -if x<2 let $s="^mUSSD TIMEOUT ERROR" -print $s -:continue -exit 0 -:getresult -get 1 "^m" $u -let x=len($u) -let $v=$s -if x>0 let $s=$v+$u -if $right(" "+$s,4) = '",15' return -if $right(" "+$s,4) = '",72' return -if $right(" "+$s,4) = '",68' return -if $mid($s,0,30)="^j+CME ERROR:" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom b/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom deleted file mode 100644 index 013447c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gcom/zteinfo.gcom +++ /dev/null @@ -1,58 +0,0 @@ -opengt - set com 115200n81 - set comecho off - set senddelay 0.02 - waitquiet 0.2 0.2 - -let $g=$env("TIMEOUT") -if $g = "" let f=25 -else let f = val($g) - -send "AT+CSQ^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZPAS?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZRSSI^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZRSSI?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZSINR^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZSNT?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - -send "AT+ZCELLINFO?^m" -let t=time()+f -gosub getresult -if $s="^mTIMEOUT ERROR" print $s - - exit 0 - -:getresult -get 1 "^m" $s -let x=len($s) -if x=0 let $s="^mTIMEOUT ERROR" -else print $s -if $s="^jOK" return -if $mid($s,0,6)="^jERROR" return -if $mid($s,0,8)="^jCOMMAND" return -if $mid($s,0,11)="^j+CME ERROR" return -if time()>t return -goto getresult diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh deleted file mode 100644 index 9ec628e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gpio-set.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -GPIO=$1 # name or number (without "gpio" prefix) -VAL=$2 # 0 or 1 -WAIT=$3 # delay in seconds, optional - -log() { - modlog "GPIO Set" "$@" -} - - -[ -n "$WAIT" ] && sleep $WAIT - -if `echo "$GPIO" | grep -q "^[0-9]*$"`; then - GPIO=gpio$GPIO -fi - -if [ -w /sys/class/gpio/$GPIO/value ]; then - echo "$VAL" > /sys/class/gpio/$GPIO/value - log "GPIO $GPIO has been set to $VAL" -else - log "GPIO $GPIO is not writable" -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua deleted file mode 100644 index fe63096..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/gpiomodel.lua +++ /dev/null @@ -1,221 +0,0 @@ -#!/usr/bin/lua - -mfile = "/tmp/sysinfo/model" -echo = 1 -model = {} -gpio = {} -gpio2 = {} -gpio3 = {} -gpio4 = {} -gpioname = {} -gpioname2 = {} -gpioname3 = {} -gpioname4 = {} - -pin = nil -pin2 = nil - -model[1] = "10u" -gpio[1] = 18 -model[2] = "11u" -gpio[2] = 8 -model[3] = "13u" -gpio[3] = 18 -model[4] = "mr3020" -gpio[4] = 8 -model[5] = "3040" -gpio[5] = 18 -model[6] = "3220" -gpio[6] = 6 -model[7] = "3420" -gpio[7] = 6 -model[8] = "wdr3500" -gpio[8] = 12 -gpioname[8] = "tp-link:power:usb" -model[9] = "wdr3600" -gpio[9] = 22 -gpioname[9] = "tp-link:power:usb1" -gpio2[9] = 21 -gpioname2[9] = "tp-link:power:usb2" -model[10] = "wdr4300" -gpio[10] = 22 -gpioname[10] = "tp-link:power:usb1" -gpio2[10] = 21 -gpioname2[10] = "tp-link:power:usb2" -model[11] = "wdr4310" -gpio[11] = 22 -gpioname2[11] = "tp-link:power:usb2" -gpioname[11] = "tp-link:power:usb1" -gpio2[11] = 21 -model[12] = "wdr4900" -gpio[12] = 10 -model[13] = "703n" -gpio[13] = 8 -model[14] = "710n" -gpio[14] = 8 -model[15] = "720" -gpio[15] = 8 -model[16] = "842" -gpio[16] = 6 -gpioname[16] = "tp-link:power:usb" -model[17] = "1043" -gpio[17] = 21 -gpioname[17] = "tp-link:power:usb" -model[18] = "4530" -gpio[18] = 22 -model[19] = "archer" -gpio[19] = 22 -gpio2[19] = 21 -gpioname2[19] = "tp-link:power:usb2" -gpioname[19] = "tp-link:power:usb1" -model[20] = "ar150" -gpio[20] = 6 -model[21] = "domino" -gpio[21] = 6 -model[22] = "300a" -gpio[22] = 0 -model[23] = "mt300n" -gpio[23] = 0 -model[24] = "ar750s" -gpio[24] = 7 -model[25] = "oolite" -gpio[25] = 18 -model[26] = "7800" -gpio[26] = 15 -gpio2[26] = 16 -model[27] = "m11g" -gpio[27] = 9 -gpioname[27] = "gpio9" -model[28] = "m33g" -gpio[28] = 9 -gpio2[28] = 10 -gpio3[28] = 11 -gpio4[28] = 12 -gpioname[28] = "pcie0_power" -gpioname2[28] = "pcie1_power" -gpioname3[28] = "pcie2_power" -gpioname4[28] = "usb_power" -model[29] = "rbsxtr" -gpio[29] = 13 -model[30] = "ap147" -gpio[30] = 13 -model[31] = "gigamod" -gpio[31] = 16 -gpioname[31] = "power_usb" -model[32] = "turbomod" -gpio[32] = 17 -gpioname[32] = "power_usb" -model[33] = "mk01" -gpio[33] = 6 - -numodel = 33 - -local file = io.open(mfile, "r") -if file == nil then - return -end - -name = nil -name2 = nil -line = file:read("*line") -file:close() -line = line:lower() - -for i=1,numodel do - start, ends = line:find(model[i]) - if start ~= nil then - if model[i] == "3420" then - start, ends = line:find("v1") - if start ~= nil then - pin = gpio[i] - pin2 = nil - else - pin = 4 - pin2 = nil - end - elseif model[i] == "3220" then - start, ends = line:find("v1") - if start ~= nil then - pin = gpio[i] - pin2 = nil - else - pin = 8 - pin2 = nil - end - elseif model[i] == "1043" then - start, ends = line:find("v2") - if start ~= nil then - pin = gpio[i] - pin2 = nil - name = gpioname[i] - name2 = nil - end - elseif model[i] == "842" then - start, ends = line:find("v3") - if start == nil then - start, ends = line:find("v2") - if start == nil then - pin = gpio[i] - pin2 = gpio2[i] - name = gpioname[i] - name2 = gpioname2[i] - else - pin = 4 - pin2 = nil - name = gpioname[i] - name2 = nil - end - end - elseif model[i] == "archer" then - start, ends = line:find("c20") - if start == nil then - pin = gpio[i] - pin2 = gpio2[i] - name = gpioname[i] - name2 = gpioname2[i] - end - elseif model[i] == "mt300n" then - start, ends = line:find("v2") - if start ~= nil then - pin = 11 - pin2 = nil - name = "usb" - name2 = nil - else - pin = gpio[i] - pin2 = nil - name = gpioname[i] - name2 = nil - end - else - pin = gpio[i] - pin2 = gpio2[i] - name = gpioname[i] - name2 = gpioname2[i] - end - break - end -end - -if pin ~= nil then - local tfile = io.open("/tmp/gpiopin", "w") - if pin2 ~= nil then - tfile:write("GPIOPIN=\"", pin, "\"\n") - tfile:write("GPIOPIN2=\"", pin2, "\"") - else - tfile:write("GPIOPIN=\"", pin, "\"") - end - tfile:close() -end -if name ~= nil then - local tfile = io.open("/tmp/gpioname", "w") - if name2 ~= nil then - tfile:write("GPIONAME=\"", name, "\"\n") - tfile:write("GPIONAME2=\"", name2, "\"") - else - tfile:write("GPIONAME=\"", name, "\"") - end - tfile:close() -else - os.remove("/tmp/gpioname") -end diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua deleted file mode 100644 index cda3061..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/idown.lua +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/lua - -cmd = arg[1] -interface = arg[2] - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -if interface ~= "wan" and interface ~= "wwan" then - s, e = interface:find("wan") - if s ~= nil then - mnum = trim(interface:sub(e+1)) - if cmd == "1" then - os.execute("/usr/lib/rooter/connect/disablemw3.sh " .. mnum) - line = "echo \"0\" > /tmp/mdown" .. mnum - else - line = "rm -f /tmp/mdown" .. mnum - end - os.execute(line) - end -end \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh deleted file mode 100644 index ff26398..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/initialize.sh +++ /dev/null @@ -1,295 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -CODENAME="ROOter " -if [ -f "/etc/codename" ]; then - source /etc/codename -fi - -# -# Set the maximum number of modems supported -# -MAX_MODEMS=2 -MODCNT=$MAX_MODEMS - -log() { - modlog "ROOter Initialize" "$@" -} - -do_zone() { - local config=$1 - local name - local network - - config_get name $1 name - config_get network $1 network - newnet=$network - if [ $name = wan ]; then - WAN1=$(echo $network | grep "wan1") - if [ -z $WAN1 ]; then - COUNTER=1 - while [ $COUNTER -le $MODCNT ]; do - newnet="$newnet wan$COUNTER" - let COUNTER=COUNTER+1 - done - uci_set firewall "$config" network "$newnet" - uci_commit firewall - /etc/init.d/firewall restart - fi - fi -} - -firstboot() { - HO=$(uci get system.@system[-1].hostname) - if [ $HO = "OpenWrt" ]; then - uci set system.@system[-1].hostname="OpenWrt" - echo "OpenWrt" > /proc/sys/kernel/hostname - fi - if [ $HO = "LEDE" ]; then - uci set system.@system[-1].hostname="LEDE" - echo "LEDE" > /proc/sys/kernel/hostname - fi - uci set system.@system[-1].cronloglevel="9" - uci commit system - - AP=$(uci -q get profile.default.apn) - if [ -z "$AP" ]; then - uci set profile.default.apn="internet" - uci commit profile - fi - - log "ROOter First Boot finalized" - - config_load firewall - config_foreach do_zone zone - - source /etc/openwrt_release - if [ $DISTRIB_RELEASE = "SNAPSHOT" ]; then - DISTRIB_RELEASE="master" - fi - tone=$(echo "$DISTRIB_RELEASE" | grep "master") -} - -if [ -e /tmp/installing ]; then - exit 0 -fi - - -log " Initializing Rooter" - -sed -i -e 's|/etc/savevar|#removed line|g' /etc/rc.local - -[ -f "/etc/firstboot" ] || { - firstboot -} - -mkdir -p $ROOTER_LINK - -uci delete modem.Version -uci set modem.Version=version -uci set modem.Version.ver=$CODENAME -uci commit modem - -source /etc/openwrt_release -rm -f /etc/openwrt_release -if [ $DISTRIB_RELEASE = "SNAPSHOT" ]; then - DISTRIB_RELEASE="master" -fi -if [ -e /etc/custom ]; then - lua $ROOTER/customname.lua - DISTRIB_DESCRIPTION=$(uci get modem.Version.ver) - DISTRIB_REVISION=" " -else - DISTRIB_DESCRIPTION=$(uci get modem.Version.ver)" ( "$DISTRIB_ID" "$DISTRIB_RELEASE" )" - DISTRIB_REVISION=" " -fi -echo "$(uci get modem.Version.ver)" > /etc/revision -echo 'DISTRIB_ID="'"$DISTRIB_ID"'"' >> /etc/openwrt_release -echo 'DISTRIB_RELEASE="'"$DISTRIB_RELEASE"'"' >> /etc/openwrt_release -echo 'DISTRIB_REVISION="'"$DISTRIB_REVISION"'"' >> /etc/openwrt_release -echo 'DISTRIB_CODENAME="'"$DISTRIB_CODENAME"'"' >> /etc/openwrt_release -echo 'DISTRIB_TARGET="'"$DISTRIB_TARGET"'"' >> /etc/openwrt_release -echo 'DISTRIB_DESCRIPTION="'"$DISTRIB_DESCRIPTION"'"' >> /etc/openwrt_release - -MODSTART=1 -WWAN=0 -USBN=0 -ETHN=1 -BASEPORT=0 -WDMN=0 -if - ifconfig eth1 &>/dev/null -then - if [ -e "/sys/class/net/eth1/device/bInterfaceProtocol" ]; then - ETHN=1 - else - ETHN=2 - fi -fi - -echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file -echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file -echo 'USBN="'"$USBN"'"' >> /tmp/variable.file -echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file -echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file -echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file - -echo 'MODCNTX="'"$MODCNT"'"' > /tmp/modcnt -uci set modem.general.max=$MODCNT -uci set modem.general.modemnum=1 -uci set modem.general.smsnum=1 -uci set modem.general.miscnum=1 - -OPING=$(uci -q get modem.ping.alive) -if [ ! -z $OPING ]; then - uci delete modem.ping -fi - -ifname1="ifname" -if [ -n "$tone" -o -e /etc/newstyle ]; then - ifname1="device" -fi - -COUNTER=1 -while [ $COUNTER -le $MODCNT ]; do - uci delete modem.modem$COUNTER - uci set modem.modem$COUNTER=modem - uci set modem.modem$COUNTER.empty=1 - - IPEX=$(uci get modem.pinginfo$COUNTER.alive) - if [ -z $IPEX ]; then - uci set modem.pinginfo$COUNTER=pinfo$COUNTER - uci set modem.pinginfo$COUNTER.alive="0" - fi - - INEX=$(uci get modem.modeminfo$COUNTER) - if [ -z $INEX ]; then - uci set modem.modeminfo$COUNTER=minfo$COUNTER - fi - - rm -f $ROOTER_LINK/getsignal$COUNTER - rm -f $ROOTER_LINK/reconnect$COUNTER - rm -f $ROOTER_LINK/create_proto$COUNTER - $ROOTER/signal/status.sh $COUNTER "No Modem Present" - - uci -q delete network.wan$COUNTER - uci set network.wan$COUNTER=interface - uci set network.wan$COUNTER.proto=dhcp - uci set network.wan$COUNTER.metric=$COUNTER"0" - uci set network.wan$COUNTER.${ifname1}="wan"$COUNTER - - if [ -e /etc/config/mwan3 ]; then - ENB=$(uci -q get mwan3.wan$COUNTER.enabled) - if [ ! -z $ENB ]; then - uci set mwan3.wan$COUNTER.enabled=0 - fi - fi - - if [ -e /etc/config/failover ]; then - uci delete failover.Modem$COUNTER - uci set failover.Modem$COUNTER=member - fi - - let COUNTER=COUNTER+1 -done - -if [ -e /etc/config/failover ]; then - uci delete failover.Wan - EXX=$(uci get network.wan) - if [ ! -z $EXX ]; then - uci set failover.Wan=member - fi - uci delete failover.Hotspot - uci set failover.Hotspot=member - uci commit failover - ENB=$(uci get failover.enabled.enabled) - if [ $ENB = "1" ]; then - if [ -e $ROOTER/connect/failover.sh ]; then - log "Starting Failover System" - $ROOTER/connect/failover.sh & - fi - fi -fi - -PRO=$(uci -q get network.wan.proto) -if [ ! -z $PRO ]; then - uci set network.wan.metric="1" -fi - -SM=$(uci get modem.sms) -if [ -z $SM ]; then - uci set modem.sms="sms" - uci set modem.sms.menable="0" - uci set modem.sms.slots="0" -fi - -uci commit modem -uci commit network -if [ -e /etc/config/mwan3 ]; then - uci commit mwan3 -fi - -if [ -e $ROOTER/removeipv6.sh ]; then - $ROOTER/removeipv6.sh -fi - -if [ -e /etc/hotplug.d/10-motion ]; then - rm -f /etc/hotplug.d/10-motion -fi -if [ -e /etc/hotplug.d/20-mjpg-streamer ]; then - rm -f /etc/hotplug.d/20-mjpg-streamer -fi -if [ -e /etc/hotplug.d/50-printer ]; then - rm -f /etc/hotplug.d/50-printer -fi -if [ -e $ROOTER/special.sh ]; then - $ROOTER/special.sh -fi - -lua $ROOTER/gpiomodel.lua - -HO=$(uci get system.@system[-1].hostname) -if [ $HO = "OpenWrt" ]; then - uci set system.@system[-1].hostname="OpenWrt" - uci commit system -fi - -if [ -e /usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua ]; then - mv -f /usr/lib/lua/luci/model/cbi/admin_system/cronnew.lua /usr/lib/lua/luci/model/cbi/admin_system/crontab.lua -fi - - -if [ -f "/etc/firstboot" ]; then - echo 'FIRSTBOOT="'"1"'"' > /etc/firstboot -else - echo 'FIRSTBOOT="'"0"'"' > /etc/firstboot - echo 'BOOTTIME="'"$(date +%s)"'"' > /tmp/boottime -fi - -# -# Added modems to various drivers -# -#source /etc/flash -#if [ "$FLASH" = "4" ]; then -#fi -#echo "413c 81b6" > /sys/bus/usb-serial/drivers/option1/new_id -echo "1546 1146" > /sys/bus/usb-serial/drivers/option1/new_id -echo "106c 3718" > /sys/bus/usb-serial/drivers/option1/new_id -#echo "1199 9091" > /sys/bus/usb-serial/drivers/option1/new_id - -# end of bootup -echo "0" > /tmp/bootend.file - -/etc/init.d/dnsmasq restart - -chown -R root:root /etc/dropbear/ -chmod 700 /etc/dropbear/ -chmod 644 /etc/dropbear/authorized_keys 2>/dev/null - -if [ ! -z $tone ]; then - [ -e /etc/newstyle ] || touch /etc/newstyle - #reboot -f -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger deleted file mode 100644 index ca7d6e6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/at-logger +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -TEXT=$1 -DATE=$(date +%c) - -echo " " >> /tmp/atlog -echo "$DATE : $TEXT" >> /tmp/atlog -lua $ROOTER/log/rotate.lua /tmp/atlog /tmp/attlog -mv /tmp/attlog /tmp/atlog - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger deleted file mode 100644 index e78b574..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/logger +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -TEXT=$1 -DATE=$(date +%c) - -wc -l $ROOTER/log/connect.log > /tmp/linecnt -read lcnt fle < /tmp/linecnt -rm -f /tmp/linecnt -if [ $lcnt -ge 20 ]; then - start=$((lcnt-1)) - tail +$start $ROOTER/log/connect.log > /tmp/connect.log - mv /tmp/connect.log $ROOTER/log/connect.log -fi - -echo "$DATE : $TEXT" >> $ROOTER/log/connect.log diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh deleted file mode 100644 index fde69f7..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/modlogger.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -TEXT=$1 -DATE=$(date +%c) - -modlog="/tmp/modlog.log" -tmplog="/tmp/tmodlog" - -echo "$DATE : $TEXT" >> $modlog -lua $ROOTER/log/mrotate.lua $modlog $tmplog -mv $tmplog $modlog - -exit 0 - -wc -l $modlog > /tmp/linecnt -read lcnt fle < /tmp/linecnt -rm -f /tmp/linecnt -if [ $lcnt -ge 200 ]; then - start=$((lcnt-1)) - tail +$start modlog > $tmplog - mv $tmplog $modlog -fi - -echo "$DATE : $TEXT" >> $modlog diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua deleted file mode 100644 index 0a5317d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/mrotate.lua +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/lua - -local uci = require "luci.model.uci".cursor() - -logfile = {} -infile = arg[1] -outfile = arg[2] - -i=0 -ifile = io.open(infile, "r") -if ifile == nil then - return -end -repeat - local line = ifile:read("*line") - if line == nil then - break - end - if string.len(line) > 1 then - i = i + 1 - logfile[i] = line - end -until 1==0 -ifile:close() - -maxs = 195 - -if i < maxs then - j = 1 -else - j = i - maxs - 1 -end -ofile = io.open(outfile, "w") -for k=j,i do - if logfile[k] ~= nil then - ofile:write(logfile[k] .. "\n") - end -end -ofile:close() \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua deleted file mode 100644 index f866446..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/log/rotate.lua +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/lua - -local uci = require "luci.model.uci".cursor() - -logfile = {} -infile = arg[1] -outfile = arg[2] - -i=0 -ifile = io.open(infile, "r") -if ifile == nil then - return -end -repeat - local line = ifile:read("*line") - if line == nil then - break - end - if string.len(line) > 1 then - i = i + 1 - logfile[i] = line - end -until 1==0 -ifile:close() - -bff = uci:get("variable", "info", "buffersize") -if bff == nil then - maxs = 50 -else - maxs = tonumber(bff) -end -if i < maxs then - j = 1 -else - j = i - maxs - 1 -end -ofile = io.open(outfile, "w") -for k=j,i do - if logfile[k] ~= nil then - ofile:write(logfile[k] .. "\n") - end -end -ofile:close() \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh deleted file mode 100644 index 779337f..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/logprint.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -# - -modlog "Log Print " "$1 $2 $3 $4 $5 $6" -exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh deleted file mode 100644 index efda95d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/atcmd.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ATCMDD=$1 - -CURRMODEM=$(uci get modem.general.miscnum) -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -M2=$(echo "$ATCMDD" | sed -e "s#~#\"#g") -COPS="+cops=?" -QOPS="+qops?" -M3=$(echo "$M2" | awk '{print tolower($0)}') -if `echo ${M3} | grep "${COPS}" 1>/dev/null 2>&1`; then - export TIMEOUT="120" -elif `echo ${M3} | grep "${QOPS}" 1>/dev/null 2>&1`; then - export TIMEOUT="120" -else - export TIMEOUT="5" -fi -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") -echo "$OX" > /tmp/result$CURRMODEM.at diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh deleted file mode 100644 index d1b3fb1..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/celltype.sh +++ /dev/null @@ -1,495 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Cell type $CURRMODEM" "$@" -} - -zte_type() { - ATCMDD="AT+ZSNT?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - ZSNT=$(echo "$OX" | awk -F[,\ ] '/^\+ZSNT:/ {print $2}') - if [ "x$ZSNT" != "x" ]; then - NETMODE="-" - if [ $ZSNT = "0" ]; then - ZSNTX=$(echo "$OX" | awk -F[,\ ] '/^\+ZSNT:/ {print $4}') - case $ZSNTX in - "0" ) - NETMODE="1" - ;; - "1" ) - NETMODE="2" - ;; - "2" ) - NETMODE="4" - ;; - "6" ) - NETMODE="6" - ;; - esac - else - case $ZSNT in - "1" ) - NETMODE="3" - ;; - "2" ) - NETMODE="5" - ;; - "6" ) - NETMODE="7" - ;; - esac - fi - fi - uci set modem.modem$CURRMODEM.modemtype="1" - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -sierra_type() { - ATCMDD="AT!SELRAT?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - SELRAT=$(echo $OX | grep -o "!SELRAT:[^0-9]\+[0-9]\{2\}" | grep -o "[0-9]\{2\}") - if [ -n "$SELRAT" ]; then - case $SELRAT in - "01" ) - NETMODE="5" - ;; - "02" ) - NETMODE="3" - ;; - "06" ) - NETMODE="7" - ;; - * ) - NETMODE="1" - ;; - esac - fi - uci set modem.modem$CURRMODEM.modemtype="2" - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -huawei_type() { - ATCMDD="AT^SYSCFGEX?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - SYSCFG=$(echo "$OX" | awk -F[,\"] '/^\^SYSCFGEX:/ {print $2}') - if [ "x$SYSCFG" != "x" ]; then - NETMODE="-" - case $SYSCFG in - "00" ) - NETMODE="1" - ;; - "01" ) - NETMODE="3" - ;; - "02" ) - NETMODE="5" - ;; - "03" ) - NETMODE="7" - ;; - * ) - ACQ=${SYSCFG:0:2} - case $ACQ in - "01" ) - NETMODE="2" - ;; - "02" ) - NETMODE="4" - ;; - "03" ) - NETMODE="6" - ;; - esac - ;; - esac - uci set modem.modem$CURRMODEM.modemtype="3" - else - ATCMDD="AT^SYSCFG?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - OX=$($ROOTER/common/processat.sh "$OX") - SYSCFG=$(echo "$OX" | awk -F[,\ ] '/^\^SYSCFG:/ {print $2}') - if [ "x$SYSCFG" != "x" ]; then - NETMODE="-" - case $SYSCFG in - "7" ) - NETMODE="1" - ;; - "13" ) - NETMODE="3" - ;; - "14" ) - NETMODE="5" - ;; - * ) - SYSCFG=$(echo "$OX" | awk -F[,\ ] '/^\^SYSCFG:/ {print $3}') - case $SYSCFG in - "0" ) - NETMODE="1" - ;; - "1" ) - NETMODE="2" - ;; - "2" ) - NETMODE="4" - ;; - esac - ;; - esac - uci set modem.modem$CURRMODEM.modemtype="4" - fi - fi - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -ublox_type() { - ATCMDD="AT+URAT?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - URAT=$(echo $OX" " | grep -o "+URAT: .\+ OK " | tr " " ",") - URAT1=$(echo $URAT | cut -d, -f2) - URAT2=$(echo $URAT | cut -d, -f3) - if [ -n "$URAT1" ]; then - NETMODE="-" - case $URAT1 in - "0" ) - NETMODE="3" - ;; - "2" ) - NETMODE="5" - ;; - "3" ) - NETMODE="7" - ;; - * ) - case $URAT2 in - "0" ) - NETMODE="2" - ;; - "2" ) - NETMODE="4" - ;; - "3" ) - NETMODE="1" - ;; - esac - ;; - esac - uci set modem.modem$CURRMODEM.modemtype="5" - fi - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -quectel_type() { - idVidP=$idV":"$idP - ATCMDD="AT+CGMM" - model=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - EM20=$(echo "$model" | grep "EM20") - if [ $EM20 ]; then - idVidP=$idV":"$idP"0" - fi - if [ "$idVidP" == "2c7c:0800" -o "$idVidP" == "2c7c:0620" -o "$idVidP" == "2c7c:030b" -o "$idVidP" == "2c7c:0801" -o "$idVidP" == "2c7c:0900" ]; then - ATCMDD="AT+QNWPREFCFG=\"mode_pref\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - QNSM=$(echo $OX | grep -o ",[AUTOLENR5GWCDM:]\+" | tr ',' ' ') - QNSM=$(echo $QNSM) - if [ -n "$QNSM" ]; then - case $QNSM in - "AUTO" ) - NETMODE="1" - ;; - "LTE" ) - NETMODE="7" - ;; - "LTE:NR5G" ) - NETMODE="8" - ;; - "NR5G" ) - NETMODE="9" - ;; - "WCDMA" ) - NETMODE="5" - ;; - esac - uci set modem.modem$CURRMODEM.modemtype="6" - fi - else - ATCMDD="AT+QCFG=\"nwscanmode\"" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - QNSM=$(echo $OX | grep -o "+QCFG: \"nwscanmode\",[0-9]" | grep -o "[0-9]") - if [ -n "$QNSM" ]; then - case $QNSM in - "0" ) - NETMODE="1" - ;; - "1" ) - NETMODE="3" - ;; - "2"|"5" ) - NETMODE="5" - ;; - "3" ) - NETMODE="7" - ;; - esac - uci set modem.modem$CURRMODEM.modemtype="6" - fi - fi - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -meig_type() { - if [ $idV == "2dee" ]; then - ATCMDD="AT^SYSCFGEX?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - RATs=$(echo "$OX" | grep -o "\^SYSCFGEX: \"[0-9]\{2,6\}\"" | grep -o "[0-9]\{2,6\}") - if [ -n "$RATs" ]; then - case $RATs in - "02" ) - NETMODE="5" ;; - "03" ) - NETMODE="7" ;; - "04" ) - NETMODE="9" ;; - "0203" | "0204" | "020304" | "020403" ) - NETMODE="4" ;; - "0304" | "0302" | "030402" | "030204" ) - NETMODE="6" ;; - "0403" ) - NETMODE="8" ;; - * ) - NETMODE="1" ;; - esac - fi - else - ATCMDD="AT+MODODR?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - MODODR=$(echo $OX | grep -o "[0-9]") - if [ -n "$MODODR" ]; then - case $MODODR in - "1"|"8" ) - NETMODE="5" ;; - "2" ) - NETMODE="1" ;; - "3" ) - NETMODE="3" ;; - "5" ) - NETMODE="7" ;; - esac - fi - fi - uci set modem.modem$CURRMODEM.modemtype="7" - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -telit_type() { - ATCMDD="AT^SYSCONFIG?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - SCFG=$(echo $OX | grep -o "\^SYSCONFIG: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") - if [ -n "$SCFG" ]; then - PREF=$(echo $OX | grep -o "\^SYSCONFIG: 2,[0-9]" | grep -o ",[0-9]") - case $SCFG in - "13" ) - NETMODE="3" ;; - "14" ) - NETMODE="5" ;; - "17" ) - NETMODE="7" ;; - * ) - NETMODE="1" ;; - esac - uci set modem.modem$CURRMODEM.modemtype="8" - fi - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -fibocom_type() { - NETMODE="" - idPP=${idP:1:1} - if [ "$idPP" = "1" ]; then - ATCMDD="AT+GTRAT?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - MRAT=$(echo $OX | grep -o "+GTRAT: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}") - if [ -n "$MRAT" ]; then - case $MRAT in - "2" ) - NETMODE="5" ;; - "3" ) - NETMODE="7" ;; - "14" ) - NETMODE="9" ;; - "17" ) - NETMODE="8" ;; - * ) - NETMODE="1" ;; - esac - fi - else - ATCMDD="AT+XACT?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - XACT=$(echo $OX | grep -o "+XACT: [0-9]" | grep -o "[0-9]") - if [ -n "$XACT" ]; then - PREF=$(echo $OX | grep -o "+XACT: [0-9],[0-9]" | grep -o ",[0-9]") - case $XACT in - "1" ) - NETMODE="5" ;; - "2" ) - NETMODE="7" ;; - "4" ) - if [ "$PREF" = ",1" ]; then - NETMODE="4" - else - NETMODE="6" - fi ;; - * ) - NETMODE="6" ;; - esac - - fi - fi - uci set modem.modem$CURRMODEM.modemtype="9" - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -simcom_type() { - ATCMDD="AT+CNMP?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - CNMP=$(echo "$OX" | grep -o "+CNMP:[ ]*[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}") - if [ -n "$CNMP" ]; then - case $CNMP in - "2"|"55" ) - NETMODE="1" ;; - "13" ) - NETMODE="3" ;; - "14" ) - NETMODE="5" ;; - "38" ) - NETMODE="7" ;; - "71" ) - NETMODE="9" ;; - "109" ) - NETMODE="8" ;; - * ) - NETMODE="0" ;; - esac - fi - uci set modem.modem$CURRMODEM.modemtype="10" - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -quanta_type() { - ATCMDD="AT^QCNCFG?" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - TECH=$(echo $OX | grep -o "\^QCNCFG: \"[0123]\{2\}\"" | grep -o "[0123]\{2\}") - case $TECH in - "02") - NETMODE="5" - ;; - "03") - NETMODE="7" - ;; - *) - NETMODE="1" - ;; - esac - uci set modem.modem$CURRMODEM.modemtype="11" - uci set modem.modem$CURRMODEM.netmode=$NETMODE - uci commit modem -} - -CURRMODEM=$1 -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -idV=$(uci get modem.modem$CURRMODEM.idV) -idP=$(uci -q get modem.modem$CURRMODEM.idP) -NETMODE="-" - -# This case statement should be kept in sync with: $ROOTER/signal/modemsignal.sh -case $idV in -"1199"|"0f3d" ) - sierra_type - ;; -"19d2" ) - if [ $idP = 1432 ]; then - telit_type - else - zte_type - fi - ;; -"12d1" ) - huawei_type - ;; -"2c7c" ) - quectel_type - ;; -"2cb7"|"1508"|"8087" ) - fibocom_type - ;; -"2dee" ) - meig_type - ;; -"05c6" ) - case $idP in - "f601" ) - meig_type - ;; - "5042" ) - telit_type - ;; - "9090"|"9003"|"9215" ) - quectel_type - ;; - "90db" ) - simcom_type - ;; - * ) - : - ;; - esac - ;; -"1bc7" ) - telit_type - ;; -"1410" ) - : - ;; -"413c" ) - case $idP in - "81d7"|"81d8" ) - telit_type - ;; - * ) - sierra_type - ;; - esac - ;; -"0489" |"03f0" ) - telit_type - ;; -"1e0e" ) - simcom_type - ;; -"8087" ) - if [ $idP = "095a" ]; then - fibocom_type - fi - ;; -"0408" ) - quanta_type - ;; -* ) - : - ;; -esac -exit diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands deleted file mode 100644 index aa600ca..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em060-2xbands +++ /dev/null @@ -1,29 +0,0 @@ -2 2 -2 5 -2 12 -2 13 -2 39 -4 4 -4 5 -4 12 -4 13 -4 29 -5 5 -5 7 -5 25 -5 30 -5 66 -7 7 -7 12 -7 26 -12 12 -12 25 -12 30 -12 66 -13 66 -25 25 -25 26 -30 29 -66 29 -66 66 -41 41 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands deleted file mode 100644 index 307919e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-2xbands +++ /dev/null @@ -1,46 +0,0 @@ -1 3 -1 5 -1 18 -1 19 -1 20 -1 26 -2 2 -2 4 -2 5 -2 12 -2 13 -2 17 -2 29 -2 30 -2 66 -3 3 -3 5 -2 7 -3 8 -3 19 -3 20 -3 28 -4 4 -4 5 -4 12 -4 13 -4 17 -4 19 -4 30 -5 7 -5 30 -5 66 -7 7 -7 20 -7 28 -12 30 -13 66 -19 21 -20 32 -29 30 -38 38 -39 39 -39 41 -40 40 -41 41 -66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands deleted file mode 100644 index 43f7600..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em12-3xbands +++ /dev/null @@ -1,43 +0,0 @@ -1 3 5 -1 3 7 -1 3 8 -1 3 19 -1 3 20 -1 3 28 -1 7 20 -2 4 5 -2 4 13 -2 5 30 -2 12 30 -2 29 30 -3 7 20 -3 7 28 -3 7 8 -4 5 30 -4 12 30 -4 29 30 -5 66 2 -13 66 2 -66 12 30 -66 29 30 -66 5 30 -2 14 66 -2 2 5 -2 2 13 -3 3 7 -3 7 7 -3 3 20 -3 3 28 -3 3 1 -4 4 5 -4 4 13 -7 7 28 -5 66 66 -13 66 66 -66 66 2 -14 66 66 -39 39 41 -39 41 41 -40 40 40 -41 41 41 -66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands deleted file mode 100644 index 74a2677..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-2xbands +++ /dev/null @@ -1,50 +0,0 @@ -1 3 -1 5 -1 18 -1 19 -1 20 -1 26 -2 2 -2 4 -2 5 -2 12 -2 13 -2 14 -2 17 -2 29 -2 30 -2 66 -3 3 -3 5 -2 7 -3 8 -3 19 -3 20 -3 28 -4 4 -4 5 -4 12 -4 13 -4 17 -4 19 -4 30 -5 7 -5 30 -5 66 -7 7 -7 20 -7 28 -12 30 -13 66 -14 30 -14 66 -29 30 -38 38 -39 39 -39 41 -40 40 -41 41 -66 5 -66 12 -66 29 -66 30 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands deleted file mode 100644 index 701af64..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-3xbands +++ /dev/null @@ -1,41 +0,0 @@ -1 3 5 -1 3 7 -1 3 19 -1 3 20 -1 3 28 -1 7 20 -2 4 5 -2 4 13 -2 5 30 -2 12 30 -2 29 30 -3 7 20 -3 7 28 -3 7 8 -4 5 30 -4 12 30 -4 29 30 -5 66 2 -13 66 2 -66 12 30 -66 29 30 -66 5 30 -2 14 66 -2 2 5 -2 2 13 -3 3 7 -3 7 7 -3 3 20 -3 3 28 -4 4 5 -4 4 13 -7 7 28 -5 66 66 -13 66 66 -39 39 41 -39 41 41 -40 40 40 -41 41 41 -66 66 2 -14 66 66 -66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands deleted file mode 100644 index 5489ad5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em20-4xbands +++ /dev/null @@ -1,8 +0,0 @@ -1 1 3 28 0 -1 3 40 40 0 -1 3 7 7 0 -1 3 3 7 7 -1 3 3 40 40 -1 3 7 7 28 -2 13 66 66 0 -3 3 7 7 28 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands deleted file mode 100644 index 4667685..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-2xbands +++ /dev/null @@ -1,29 +0,0 @@ -2 2 -2 5 -2 7 -2 12 -2 13 -2 14 -2 71 -4 4 -4 5 -4 7 -4 12 -4 13 -4 71 -5 5 -5 66 -7 7 -7 12 -12 66 -13 66 -14 66 -25 25 -25 26 -26 41 -41 41 -42 42 -43 43 -48 48 -66 66 -66 71 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands deleted file mode 100644 index a50f0f9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7411-3xbands +++ /dev/null @@ -1,8 +0,0 @@ -2 2 2 -7 7 7 -12 12 12 -41 41 41 -42 42 42 -43 43 43 -48 48 48 -66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands deleted file mode 100644 index ea770ac..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-2xbands +++ /dev/null @@ -1,60 +0,0 @@ -1 3 -1 5 -1 7 -1 8 -1 18 -1 19 -1 20 -1 26 -1 41 -1 42 -2 2 -2 4 -2 5 -2 12 -2 13 -2 28 -2 29 -2 30 -2 46 -2 66 -3 3 -3 5 -3 7 -3 8 -3 19 -3 20 -3 28 -3 41 -3 42 -4 4 -4 5 -4 7 -4 12 -4 13 -4 28 -4 29 -4 30 -4 46 -5 5 -5 7 -5 30 -5 46 -5 66 -7 7 -7 20 -7 28 -12 30 -12 66 -13 46 -13 66 -19 42 -20 32 -28 42 -29 30 -29 66 -30 66 -41 41 -41 42 -42 42 -48 48 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands deleted file mode 100644 index f64b670..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7511-3xbands +++ /dev/null @@ -1,55 +0,0 @@ -1 3 5 -1 3 7 -1 3 8 -1 3 19 -1 3 20 -1 3 28 -1 5 7 -1 7 20 -1 7 7 -1 42 42 -2 2 5 -2 2 12 -2 2 13 -2 4 5 -2 4 7 -2 4 12 -2 4 13 -2 4 29 -2 5 30 -2 5 66 -2 7 7 -2 7 12 -2 12 30 -2 13 66 -2 29 30 -2 66 66 -3 3 5 -3 3 7 -3 7 7 -3 7 20 -3 7 28 -3 41 42 -3 41 41 -3 42 42 -4 4 5 -4 4 12 -4 4 13 -4 4 30 -4 5 30 -4 7 7 -4 7 12 -4 12 30 -4 29 30 -5 30 66 -5 66 66 -7 7 28 -12 30 66 -13 66 66 -19 42 42 -29 30 66 -41 42 42 -41 41 42 -41 41 41 -48 48 48 -66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands deleted file mode 100644 index 3ff2f85..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-2xbands +++ /dev/null @@ -1,14 +0,0 @@ -1 18 -1 26 -1 41 -2 2 -2 28 -2 46 -4 28 -4 46 -5 5 -5 46 -20 32 -41 41 -42 42 -48 48 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands deleted file mode 100644 index 61b39c8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/em7565-3xbands +++ /dev/null @@ -1,51 +0,0 @@ -1 3 5 -1 3 7 -1 3 8 -1 3 19 -1 3 20 -1 3 28 -1 42 42 -2 2 5 -2 2 12 -2 2 13 -2 4 5 -2 4 7 -2 4 12 -2 4 13 -2 4 29 -2 5 30 -2 5 66 -2 7 7 -2 7 12 -2 12 30 -2 13 66 -2 29 30 -2 66 66 -3 3 5 -3 3 7 -3 3 20 -3 3 28 -3 7 7 -3 7 20 -3 7 28 -3 41 42 -3 41 41 -3 42 42 -4 4 5 -4 4 12 -4 4 13 -4 4 30 -4 7 7 -4 7 12 -4 12 30 -4 29 30 -5 30 66 -5 66 66 -7 7 28 -12 30 66 -13 66 66 -29 30 66 -41 42 41 -41 41 42 -48 48 48 -66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands deleted file mode 100644 index e9565cd..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06a-bands +++ /dev/null @@ -1,27 +0,0 @@ -2 2 -5 5 -2 12 -2 13 -2 29 -4 4 -4 5 -4 12 -4 13 -4 29 -7 5 -7 7 -7 12 -7 26 -25 5 -25 12 -25 25 -25 26 -30 5 -30 12 -30 29 -41 41 -66 5 -66 12 -66 13 -66 29 -66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands deleted file mode 100644 index 0937585..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/ep06e-bands +++ /dev/null @@ -1,32 +0,0 @@ -1 5 -1 8 -1 20 -1 28 -1 1 -3 5 -3 7 -3 8 -3 20 -3 28 -3 3 -5 38 -5 40 -5 41 -7 5 -7 8 -7 20 -7 28 -7 7 -8 38 -8 40 -8 41 -20 32 -20 38 -20 40 -20 41 -28 38 -28 40 -28 41 -38 38 -40 40 -41 41 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands deleted file mode 100644 index 540bd0a..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-2xbands +++ /dev/null @@ -1,35 +0,0 @@ -1 3 -1 5 -1 18 -1 19 -1 20 -1 21 -1 26 -2 4 -2 5 -2 12 -2 13 -2 17 -2 29 -2 30 -2 66 -3 5 -3 7 -3 8 -3 19 -3 20 -3 28 -4 5 -4 12 -4 13 -4 17 -4 29 -4 30 -5 7 -5 30 -5 66 -7 20 -7 28 -12 30 -13 66 -29 30 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands deleted file mode 100644 index 29632c3..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/l850-3xbands +++ /dev/null @@ -1,27 +0,0 @@ -1 3 7 -1 3 19 -1 3 20 -1 19 21 -2 4 5 -2 4 13 -2 5 30 -2 12 30 -2 29 30 -3 7 20 -3 7 28 -4 5 30 -4 12 30 -4 29 30 -5 66 2 -13 66 2 -2 2 5 -2 2 13 -3 3 7 -3 7 7 -3 3 20 -4 4 5 -4 4 13 -5 66 66 -13 66 66 -66 66 2 -66 66 66 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh deleted file mode 100644 index 236576c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/lock.sh +++ /dev/null @@ -1,395 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Lock Band $CURRMODEM" "$@" -} - -RESTART="1" - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -fibdecode() { - j=$1 - tdec=$2 - mod=$3 - length=${#j} - jx=$j - length=${#jx} - - str="" - i=$((length-1)) - while [ $i -ge 0 ] - do - dgt="0x"${jx:$i:1} - DecNum=`printf "%d" $dgt` - Binary= - Number=$DecNum - while [ $DecNum -ne 0 ] - do - Bit=$(expr $DecNum % 2) - Binary=$Bit$Binary - DecNum=$(expr $DecNum / 2) - done - if [ -z $Binary ]; then - Binary="0000" - fi - len=${#Binary} - while [ $len -lt 4 ] - do - Binary="0"$Binary - len=${#Binary} - done - revstr="" - length=${#Binary} - ii=$((length-1)) - while [ $ii -ge 0 ] - do - revstr=$revstr${Binary:$ii:1} - ii=$((ii-1)) - done - str=$str$revstr - i=$((i-1)) - done - - len=${#str} - ii=0 - lst="" - sep="," - hun=101 - if [ $mod = "1" ]; then - sep=":" - hun=1 - fi - if [ $mod = "2" ]; then - sep="," - hun=1 - fi - while [ $ii -lt $len ] - do - bnd=${str:$ii:1} - if [ $bnd -eq 1 ]; then - if [ $tdec -eq 1 ]; then - jj=$((ii+hun)) - else - if [ $ii -lt 9 ]; then - jj=$((ii+501)) - else - jj=$((ii+5001)) - fi - fi - if [ -z "$lst" ]; then - lst=$jj - else - lst=$lst$sep$jj - fi - fi - ii=$((ii+1)) - done - if [ -z $lst ]; then - lst="0" - fi -} - -encode() { - maskz=$1 - length=${#maskz} - i=0 - ii=1 - lst="" - ij=$((length-1)) - while [ $i -le $ij ] - do - dgt=${maskz:$i:1} - if [ $dgt == "1" ]; then - lst=$lst$ii" " - fi - i=$((i+1)) - ii=$((ii+1)) - done - maskz=$(encodemask $lst) - maskz=$(echo $maskz | sed 's/^0*//') -} - -maskx=$1 -mask64=$(echo "$maskx""," | cut -c1-64 | cut -d, -f1) -maskl2=$(echo ${maskx:64}"," | cut -d, -f1) -maskc=$(echo "$maskx" | grep ",") -if [ ! -z "$maskc" ]; then - mask=$(echo $maskx"," | cut -d, -f1) - mask5g=$(echo $maskx"," | cut -d, -f2) - mask5gsa=$(echo $maskx"," | cut -d, -f3) -else - mask=$maskx - mask5g="" - mask5gsa="" -fi - -#log "$mask" -#log "$mask5g" -#log "$mask5gsa" - -encode $mask -mask=$maskz -encode $mask5g -mask5g=$maskz -encode $mask5gsa -mask5gsa=$maskz -encode $mask64 -mask64=$maskz -encode $maskl2 -if [ -z $maskz ]; then - maskl2="0" -else - maskl2=$maskz -fi -if [ -z $mask64 ]; then - mask64="0" -fi - -if [ -z "$2" ]; then - CURRMODEM=$(uci get modem.general.miscnum) -else - CURRMODEM=1 -fi -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -CPORT=$(uci -q get modem.modem$CURRMODEM.commport) -model=$(uci get modem.modem$CURRMODEM.model) -uVid=$(uci get modem.modem$CURRMODEM.uVid) -uPid=$(uci get modem.modem$CURRMODEM.uPid) -GW=$(uci -q get modem.modem$CURRMODEM.GW) - -export TIMEOUT="5" -case $uVid in - "2c7c" ) - MODT="1" - if [ -z "$2" ]; then - RESTART="1" - fi - M5="" - M2='AT+QCFG="band",0,'$mask',0,1' - if [ $uPid = 0620 ]; then - EM20=$(echo $model | grep "EM20") - if [ -z "$EM20" ]; then #EM160 - if [ ! -z $mask ]; then - fibdecode $mask 1 1 - else - lst="0" - fi - M2='AT+QNWPREFCFG="lte_band",'$lst - else # Fake EM160 RM500 - if [ -e /etc/qfake ]; then - if [ ! -z $mask ]; then - fibdecode $mask 1 1 - else - lst="0" - fi - M2F='AT+QNWPREFCFG="lte_band",'$lst - if [ ! -z $mask5g ]; then - fibdecode $mask5g 1 1 - else - lst="0" - fi - M5F='AT+QNWPREFCFG="nsa_nr5g_band",'$lst - NET=$(uci -q get modem.modem$CURRMODEM.netmode) - if [ $NET = "9" ]; then - M5F='AT+QNWPREFCFG="nr5g_band",'$lst - fi - log " " - log "Fake LTE Locking Cmd : $M2F" - log "Fake 5G Locking Cmd : $M5F" - log " " - #rm -f /tmp/bmask - exit 0 - fi - fi - fi - if [ $uPid = 030b ]; then - if [ ! -z $mask ]; then - fibdecode $mask 1 1 - else - lst="0" - fi - M2='AT+QNWPREFCFG="lte_band",'$lst - fi - if [ $uPid = 0306 ]; then - RESTART="1" - fi - if [ $uPid = 0800 -o $uPid = 0900 -o $uPid = 0801 ]; then - if [ ! -z "$mask" ]; then - fibdecode $mask 1 1 - else - lst="0" - fi - M2='AT+QNWPREFCFG="lte_band",'$lst - if [ ! -z "$mask5g" ]; then - fibdecode $mask5g 1 1 - else - lst="0" - fi - M5='AT+QNWPREFCFG="nsa_nr5g_band",'$lst - if [ ! -z "$mask5gsa" ]; then - fibdecode $mask5gsa 1 1 - else - lst="0" - fi - M6='AT+QNWPREFCFG="nr5g_band",'$lst - fi - log " " - log "Locking Cmd : $M2" - log "Locking Cmd : $M5" - log "Locking Cmd : $M6" - log " " - - ATCMDD="AT" - NOCFUN=$uVid - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - if [ ! -z "$M5" ]; then - OX5=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M5") - fi - if [ ! -z "$M6" ]; then - OX6=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M6") - fi - log "Locking Cmd Response : $OX" - log "Locking Cmd Response : $OX5" - log "Locking Cmd Response : $OX6" - log " " - if [ $RESTART = "1" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - sleep 10 - fi - ;; - "1199" ) - MODT="0" - M1='AT!ENTERCND="A710"' - if [ -z $mask64 ]; then - mask64="0" - fi - case $uPid in - - "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 - M2='AT!BAND=11,"Test",0,'$mask64,0 - ;; - "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 - M2='AT!BAND=11,"Test",0,'$mask64,0 - if [ -e /etc/fake ]; then - M2='AT!BAND=11,"Test",0,'$mask64','$maskl2',0,0,0' - fi - ;; - "9090"|"9091"|"90b1" ) - M2='AT!BAND=11,"Test",0,'$mask64','$maskl2',0,0,0' - ;; - esac - log "$M2" - if [ -e /etc/fake ]; then - exit 0 - fi - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M1") - log "$OX" - ATCMDD="AT+CFUN=1,1" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - log "$OX" - M2='AT!BAND=00;!BAND=11' - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - log "$OX" - if [ $RESTART = "1" ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD='AT!ENTERCND="AWRONG"' - fi - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ;; - "8087"|"2cb7" ) - MODT="2" - FM150="" - if [ $uVid = 2cb7 ]; then - FM150=$(echo $model | grep "FM150") - if [ -z $FM150 ]; then - COMM="XACT" - else - COMM="GTACT" - fi - else - COMM="XACT" - fi - ATCMDD='AT+'$COMM'?' - log " " - log " Get Current Bands : $ATCMDD" - log " " - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log " " - log " Get Current Bands Response : $OX" - log " " - - lte="" - if [ ! -z $mask ]; then - fibdecode $mask 1 0 - lte=","$lst - fi - L1="4,2,1" - lst="" - if [ ! -z $FM150 ]; then - L1="17,6," - if [ ! -z $mask5g ]; then - fibdecode $mask5g 5 0 - lst=","$lst - else - L1="4,3," - fi - fi - ATCMDD="AT+""$COMM"="$L1$lte$lst" - log " " - log "Lock Command : $ATCMDD" - log " " - - #exit 0 - - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log " " - log "Lock Response : $OX" - log " " - if [ $RESTART = "1" ]; then - ATCMDD="AT+CFUN=1,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ;; - "413c" ) - MODT="3" - case $uPid in - - "81d7"|"81d8"|"e0b4" |"e0b5"|"1910") - if [ ! -z $mask ]; then - fibdecode $mask 1 2 - ATCMDD="AT^SLBAND=LTE,2,""$lst" - log "$ATCMDD" - else - exit 0 - fi - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - log " " - log "Lock Response : $OX" - log " " - if [ $RESTART = "1" ]; then - ATCMDD="AT+CFUN=1,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - ;; - esac - ;; - * ) - exit 0 - ;; -esac - -if [ $RESTART = "0" ]; then - /usr/lib/rooter/connect/bandmask $CURRMODEM $MODT - exit 0 -fi -rm -f /tmp/bmask -/usr/lib/rooter/luci/restart.sh $CURRMODEM -/usr/lib/rooter/connect/bandmask $CURRMODEM $MODT -exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh deleted file mode 100644 index b05855f..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/luaops.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -COMMAND=$1 -FILE=$2 - -if [ $COMMAND = delete ]; then - rm -f $FILE -fi \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh deleted file mode 100644 index 40a868d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mask.sh +++ /dev/null @@ -1,332 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "BandMasking $CURRMODEM" "$@" -} - -# -# remove for band locking -# -enb=$(uci -q get custom.bandlock.enabled) -if [ $enb == "0" ]; then - exit 0 -fi - -reverse() { - LX=$1 - length=${#LX} - jx="${LX:2:length-2}" - length=${#jx} - str="" - i=$((length-1)) - while [ $i -ge 0 ] - do - dgt="0x"${jx:$i:1} - DecNum=`printf "%d" $dgt` - Binary= - Number=$DecNum - while [ $DecNum -ne 0 ] - do - Bit=$(expr $DecNum % 2) - Binary=$Bit$Binary - DecNum=$(expr $DecNum / 2) - done - if [ -z $Binary ]; then - Binary="0000" - fi - len=${#Binary} - while [ $len -lt 4 ] - do - Binary="0"$Binary - len=${#Binary} - done - revstr="" - length=${#Binary} - ii=$((length-1)) - while [ $ii -ge 0 ] - do - revstr=$revstr${Binary:$ii:1} - ii=$((ii-1)) - done - str=$str$revstr - i=$((i-1)) - done - revstr=$str"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -} - -rm -f /tmp/bmask -CURRMODEM=$(uci get modem.general.miscnum) -CPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -uVid=$(uci get modem.modem$CURRMODEM.uVid) -uPid=$(uci get modem.modem$CURRMODEM.uPid) -ATCMDD="AT+CGMM" -model=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -L1=$(uci -q get modem.modem$CURRMODEM.L1) -L5=$(uci -q get modem.modem$CURRMODEM.L5) -L6=$(uci -q get modem.modem$CURRMODEM.L6) - -if [ ! $L1 ]; then - exit 0 -fi - -CA3="" -M5="x" -M6="x" -case $uVid in - "2c7c" ) - case $uPid in - "0125" ) # EC25 - #EUX EC25EUXGAR B1/B3/B7/B8/B20/B28A/B38/B40/B41 - #EU EC25EUGAR B1/B3/B7/B8/B20/B28A/B38/B40/B41 - #EC EC25ECGAR - #E EC25EFAR B1/B3/B5/B7/B8/B20/B38/B40/B41 - #AU EC25AUGCR - #AF-FD EC25AFFDR B2/B4/B5/B12/B13/B14/B66/B71 - #AF EC25AFFAR B2/B4/B5/B12/B13/B14/B66/B71 - #A EC25AFAR - CA="" - M1='ATI' - OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") - REV=$(echo $OX" " | grep -o "Revision: .\+ OK " | tr " " ",") - MODL=$(echo $REV | cut -d, -f2) - EC25AF=$(echo $MODL | grep "EC25AFF") - if [ ! -z "$EC25AF" ]; then # EC25-AF - M2='01011000000111000000000000000000000000000000000000000000000000000100001' - else - EC25AF=$(echo $MODL | grep "EC25E") - if [ ! -z "$EC25AF" ]; then # EC25-E - M2='1010101100000000000100000000000000000101100' - else - EC25AF=$(echo $MODL | grep "EC25AU") - if [ ! -z "$EC25AF" ]; then # EC25-AU - M2='111110110000000000000000000100000000000100' - else # EC25-A - M2='01010000000100' - fi - fi - fi - ;; - "0306" ) # EP06-A - M1='AT+GMR' - OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") - EP06E=$(echo $OX | grep "EP06E") - if [ ! -z "$EP06E" ]; then # EP06E - M2='101010110000000000010000000100010000010110' - CA="ep06e-bands" - else # EP06A - M2='010110100001100010000000110011000000000010000000000000000000000001' - CA="ep06a-bands" - fi - ;; - "030b" ) # EM060 - M2='111110110001110001110000110111000100011111100101000000000000000001000010' - CA="em060-2xbands" - CA3="" - ;; - "0512" ) # EM12-G - EM12=$(echo $model | grep "EG18") - if [ -z "$EM12" ]; then - M2='111110111001110011111000110111010000011110000000000000000000000001' - CA="em12-2xbands" - CA3="em12-3xbands" - else # EG18 - EM12=$(echo $model | grep "EA") - if [ -z "$EM12" ]; then # NA - M2='01011001000111001000000011001100000000001000000000000000000000000000001000010' - else # EA - M2='101010110000000000010000000100000000010110' - fi - CA="" - CA3="" - fi - ;; - "0620" ) # EM20-G - EM20=$(echo $model | grep "EM20") - if [ ! -z "$EM20" ]; then - M2='111110110001110011110000110111000000011111100101000000000000000001' - CA="em20-2xbands" - CA3="em20-3xbands" - CA4="em20-4xbands" - if [ -e /etc/qfake ]; then - M2='1111101100011100011100001101110101000111111000010000000000000000010000100' - M5='0000000000000000000000000000000000000100100000000000000000000000000000000000111' - M6='1110101100010000000100001001000000000101100000010000000000000000010000100000111' - $ROOTER/luci/celltype.sh $CURRMODEM - NET=$(uci -q get modem.modem$CURRMODEM.netmode) - if [ $NET != "7" ]; then - M5=$M6 # SA mode - L5=$L6 - fi - CA="" - CA3="" - CA4="" - fi - - else - M2='111110110001110011110000110111010000011111100101000000000000000001' - CA="em20-2xbands" - CA3="em20-3xbands" - CA4="em20-4xbands" - fi - ;; - "0801" ) #RM520 - GL=$(echo $model | grep "GL") - if [ ! -z "$GL" ]; then #RM520N-GL - M2='1111101100011100111100001101110101000111111001010000000000000000010000100' - M5='11101011000111000101000011011100000001011000000100000000000000000100011000111110' - M6=$M5 - CA="" - CA3="" - else #RM520N-EU - M2='1010101100000000000100000001000100000101111001000000000000000000000000100' - M5='101010110000000000010000000100000000010110000000000000000000000000000010001111' - M6=$M5 - CA="" - CA3="" - fi - ;; - "0900" ) - M2='111010110000000000010000000100000100011110' - M5='1000000000000000000000000001000000000000100000000000000000000000000000000000111' - M6=$M5 - CA="" - CA3="" - ;; - "0800") # RM500 - f2=$(echo $model | grep "500") - if [ -z "$f2" ]; then #RM502/505/510 - M2='1111101100011100111100001101110101000111111001010000000000000000010000100' - M5='1110101100010100000100001001000000000101100000010000000000000000010000100000111' - M6=$M5 - else - GL=$(echo $model | grep "GL") - if [ ! -z "$GL" ]; then #RM500-GL - M2='1111101100011100111100001101110101000111111001010000000000000000010000100' - M5='0000000000000000000000000000000000000000100000000000000000000000000000000000111' - M6='1110101100010000000100001001000000000101100000010000000000000000010000100000111' - else # RM500-AE - M2='1111101100011100111100001101110101000111111001010000000000000000010000100' - M5='11101011000100000001000010010000000001011000000100000000000000000100001000001110' - M6=$M5 - fi - fi - CA="" - CA3="" - ;; - esac - ;; - "1199" ) - case $uPid in - "68a2" ) # MC7700 - M2='1001000000000000100000000' - CA="" - ;; - "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 - M2='0101100000001000100000001' - CA="" - ;; - "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 - M2='11111011000110000001000011000100000000001' - if [ -e /etc/fake ]; then - M2='1111101100011100011100000100110100000000110001010000000000000000010' - fi - CA="mc7455-bands" - ;; - "9090"|"9091"|"90b1" ) - EM7565=$(echo "$model" | grep "7565") - if [ ! -z "$EM7565" ]; then # EM7565 - M2='111110111001100001110000010111010000000011100101000000000000000001' - CA="em7565-2xbands" - CA3="em7565-3xbands" - else - EM7511=$(echo "$model" | grep "7511") - if [ ! -z "$EM7511" ]; then # EM7511 - M2='1111101100011100011100000100110100000000110001010000000000000000010' - CA="em7511-2xbands" - CA3="em7511-3xbands" - else # EM7411 - M2='0101101000011100000000001100000000000000111000010000000000000000010000100' - CA="em7411-2xbands" - CA3="em7411-3xbands" - fi - fi - ;; - esac - ;; - "8087" ) - M2='111110110001100011110000010111000000011110000000000000000000000001' - CA="l850-2xbands" - CA3="l850-3xbands" - ;; - "2cb7" ) - FM150=$(echo "$model" | grep "FM150") - if [ -z "$FM150" ]; then - M2='111110110001100011110000010111000000011110000000000000000000000001' - CA="l850-2xbands" - CA3="l850-3xbands" - else - M2='01011000000100000000000010001100000000000000000000000000000000000100001' - M5='00001000000100000000000000000000000000001000000000000000000000000100001' - CA="" - CA3="" - fi - ;; - "413c" ) - case $uPid in - - "81d7"|"81d8"|"e0b4" |"e0b5"|"1910") - M2='11111011000111001111000011011101000001111110010100000000000000000100' - CA="" - CA3="" - ;; - esac - ;; - "1bc7" ) - case $uPid in - - "1040"|"1041") - L1X=$(uci -q get modem.modem$CURRMODEM.L1X) - M2=$L1X - CA="" - CA3="" - ;; - esac - ;; - * ) - exit 0 - ;; -esac - -reverse $L1 -echo $revstr > /tmp/bmask1 -if [ ! -z $L5 ]; then - reverse $L5 -else - revstr="x" -fi -echo $revstr >> /tmp/bmask1 -if [ ! -z $L6 ]; then - reverse $L6 -else - revstr="x" -fi -echo $revstr >> /tmp/bmask1 -echo $M2 >> /tmp/bmask1 -echo $M5 >> /tmp/bmask1 -if [ -z "$M6" ]; then - M6="x" -fi -echo $M6 >> /tmp/bmask1 -if [ $CA ]; then - echo $CA >> /tmp/bmask1 - if [ $CA3 ]; then - echo $CA3 >> /tmp/bmask1 - if [ $CA4 ]; then - echo $CA4 >> /tmp/bmask1 - fi - fi -fi -mv /tmp/bmask1 /tmp/bmask - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands deleted file mode 100644 index 3114071..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/mc7455-bands +++ /dev/null @@ -1,14 +0,0 @@ -1 8 -2 2 -2 5 -2 12 -2 13 -3 7 -3 20 -4 4 -4 5 -4 12 -4 13 -7 7 -7 20 -41 41 \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh deleted file mode 100644 index 7a8bf5e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modechge.sh +++ /dev/null @@ -1,276 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -MODEMTYPE=$1 -NETMODE=$2 - -# log() { - modlog "ModeChange $CURRMODEM" "$@" -# } - -CURRMODEM=$(uci get modem.general.miscnum) -uci set modem.modem$CURRMODEM.cmode="0" -uci set modem.modem$CURRMODEM.netmode="10" -uci commit modem - -MODEMTYPE=$(uci get modem.modem$CURRMODEM.modemtype) -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - -# ZTE -if [ $MODEMTYPE -eq 1 ]; then - case $NETMODE in - 1*) - ATC="AT+ZSNT=0,0,0" ;; - 2*) - ATC="AT+ZSNT=0,0,1" ;; - 3*) - ATC="AT+ZSNT=1,0,0" ;; - 4*) - ATC="AT+ZSNT=0,0,2" ;; - 5*) - ATC="AT+ZSNT=2,0,0" ;; - 6*) - ATC="AT+ZSNT=0,0,6" ;; - 7*) - ATC="AT+ZSNT=6,0,0" ;; - esac - ATC=$ATC";+ZBANDI=0" -fi - -# Sierra -if [ $MODEMTYPE -eq 2 ]; then - case $NETMODE in - "3" ) - ATC="AT!SELRAT=2" ;; - "5" ) - ATC="AT!SELRAT=1" ;; - "7" ) - ATC="AT!SELRAT=6" ;; - * ) - ATC="AT!SELRAT=0" ;; - esac -fi - -# Huawei LTE -if [ $MODEMTYPE -eq 3 ]; then - case $NETMODE in - 1*) - ATC="AT^SYSCFGEX=\"00\",40000000,2,4,40000000,," ;; - 2*) - ATC="AT^SYSCFGEX=\"010203\",40000000,2,4,40000000,," ;; - 3*) - ATC="AT^SYSCFGEX=\"01\",40000000,2,4,40000000,," ;; - 4*) - ATC="AT^SYSCFGEX=\"020301\",40000000,2,4,40000000,," ;; - 5*) - ATC="AT^SYSCFGEX=\"02\",40000000,2,4,40000000,," ;; - 6*) - ATC="AT^SYSCFGEX=\"030201\",40000000,2,4,40000000,," ;; - 7*) - ATC="AT^SYSCFGEX=\"03\",40000000,2,4,40000000,," ;; - esac -fi - -# Huawei legacy -if [ $MODEMTYPE -eq 4 ]; then - case $NETMODE in - 1*) - ATC="AT^SYSCFG=2,0,40000000,2,4" ;; - 2*) - ATC="AT^SYSCFG=2,1,40000000,2,4" ;; - 3*) - ATC="AT^SYSCFG=13,1,40000000,2,4" ;; - 4*) - ATC="AT^SYSCFG=2,2,40000000,2,4" ;; - 5*) - ATC="AT^SYSCFG=14,2,40000000,2,4" ;; - esac -fi - -# ublox -if [ $MODEMTYPE -eq 5 ]; then - case $NETMODE in - 1*) - ATC="AT+CFUN=4;+URAT=4,3;+CFUN=1,1" ;; - 2*) - ATC="AT+CFUN=4;+URAT=4,0;+CFUN=1,1" ;; - 3*) - ATC="AT+CFUN=4;+URAT=0;+CFUN=1,1" ;; - 4*) - ATC="AT+CFUN=4;+URAT=4,2;+CFUN=1,1" ;; - 5*) - ATC="AT+CFUN=4;+URAT=2;+CFUN=1,1" ;; - 6*) - ATC="AT+CFUN=4;+URAT=4,3;+CFUN=1,1" ;; - 7*) - ATC="AT+CFUN=4;+URAT=4,3;+CFUN=1,1" ;; - esac -fi - -# Quectel -if [ $MODEMTYPE -eq 6 ]; then - CURRMODEM=$(uci -q get modem.general.modemnum) - idV=$(uci -q get modem.modem$CURRMODEM.idV) - idP=$(uci -q get modem.modem$CURRMODEM.idP) - ATCMDD="AT+CGMM" - model=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - EM20=$(echo "$model" | grep "EM20") - if [ $EM20 ]; then - idP="0" - fi - NEWFMT=false - if [ "$idV" = "2c7c" ]; then - if [ "$idP" = "0800" -o "$idP" = "0620" -o "$idP" = "030b" -o "$idP" = "0801" -o "$idP" = "0900" ]; then - NEWFMT=true - fi - fi - case $NETMODE in - "3") - ATC="AT+QCFG=\"nwscanmode\",1" ;; - "5") - if $NEWFMT; then - ATC="AT+QNWPREFCFG=\"mode_pref\",WCDMA" - else - ATC="AT+QCFG=\"nwscanmode\",2" - fi - ;; - "7") - if $NEWFMT; then - ATC="AT+QNWPREFCFG=\"mode_pref\",LTE" - else - ATC="AT+QCFG=\"nwscanmode\",3" - fi - ;; - "8") - ATC="AT+QNWPREFCFG=\"mode_pref\",LTE:NR5G" ;; - "9") - ATC="AT+QNWPREFCFG=\"mode_pref\",NR5G" ;; - *) - if $NEWFMT; then - ATC="AT+QNWPREFCFG=\"mode_pref\",AUTO" - else - ATC="AT+QCFG=\"nwscanmode\",0" - fi - ;; - esac -fi - -# MEIG -if [ $MODEMTYPE -eq 7 ]; then - CURRMODEM=$(uci -q get modem.general.modemnum) - idV=$(uci -q get modem.modem$CURRMODEM.idV) - if [ $idV == "2dee" ]; then - case $NETMODE in - "4") - ATC="AT^SYSCFGEX=\"020304\"" ;; - "5") - ATC="AT^SYSCFGEX=\"02\"" ;; - "6") - ATC="AT^SYSCFGEX=\"030402\"" ;; - "7") - ATC="AT^SYSCFGEX=\"03\"" ;; - "8") - ATC="AT^SYSCFGEX=\"0403\"" ;; - "9") - ATC="AT^SYSCFGEX=\"04\"" ;; - *) - ATC="AT^SYSCFGEX=\"00\"" ;; - esac - else - case $NETMODE in - "3") - ATC="AT+MODODR=3" ;; - "5") - ATC="AT+MODODR=1" ;; - "7") - ATC="AT+MODODR=5" ;; - *) - ATC="AT+MODODR=2" ;; - esac - fi -fi - -# Telit, Foxconn, etc. -if [ $MODEMTYPE -eq 8 ]; then - case $NETMODE in - "3" ) - ATC="AT\$QCNSP=1,0,0" ;; - "5" ) - ATC="AT\$QCNSP=2,0,0" ;; - "7" ) - ATC="AT\$QCNSP=6,0,0" ;; - * ) - ATC="AT\$QCNSP=0,0,0" ;; - esac -fi - -# Fibocom -if [ $MODEMTYPE -eq 9 ]; then - CURRMODEM=$(uci -q get modem.general.modemnum) - idV=$(uci -q get modem.modem$CURRMODEM.idV) - idP=$(uci -q get modem.modem$CURRMODEM.idP) - idPP=${idP:1:1} - if [ "$idPP" = "1" ]; then - case $NETMODE in - "7") - ATC="AT+GTRAT=3" ;; - "8") - ATC="AT+GTRAT=17" ;; - "9") - ATC="AT+GTRAT=14" ;; - *) - ATC="AT+GTRAT=10" ;; - esac - else - case $NETMODE in - "4") - ATC="AT+XACT=4,1" ;; - "5") - ATC="AT+XACT=1" ;; - "7") - ATC="AT+XACT=2" ;; - *) - ATC="AT+XACT=4,2" ;; - esac - fi -fi - -# SIMCom -if [ $MODEMTYPE -eq 10 ]; then - case $NETMODE in - "3") - ATC="AT+CNMP=13" ;; - "5") - ATC="AT+CNMP=14" ;; - "7") - ATC="AT+CNMP=38" ;; - "8") - ATC="AT+CNMP=109" ;; - "9") - ATC="AT+CNMP=71" ;; - *) - ATC="AT+CNMP=2" ;; - esac -fi - -# Quanta, Megafon -if [ $MODEMTYPE -eq 11 ]; then - case $NETMODE in - "5") - ATC="AT^QCNCFG=02" ;; - "7") - ATC="AT^QCNCFG=03" ;; - *) - ATC="AT^QCNCFG=00" ;; - esac -fi - -ATCMDD="$ATC" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - -$ROOTER/luci/celltype.sh $CURRMODEM -uci set modem.modem$CURRMODEM.cmode="1" -uci commit modem - -$ROOTER/luci/restart.sh $CURRMODEM 11 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh deleted file mode 100644 index a0fd3e9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/modemchge.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -TYPE=$1 -DIREC=$2 -source /tmp/modcnt -MODCNT=$MODCNTX - -case $TYPE in -"modem" ) - MODENUM=$(uci get modem.general.modemnum) - ;; -"sms" ) - MODENUM=$(uci get modem.general.smsnum) - ;; -"misc" ) - MODENUM=$(uci get modem.general.miscnum) - ;; -esac - -if [ $DIREC -eq 1 ]; then - let MODENUM=MODENUM+1 - if [ $MODENUM -gt $MODCNT ]; then - MODENUM=1 - fi -else - if [ $MODENUM -eq 1 ]; then - MODENUM=$MODCNT - else - let MODENUM=MODENUM-1 - fi -fi -case $TYPE in -"modem" ) - uci set modem.general.modemnum=$MODENUM - ;; -"sms" ) - uci set modem.general.smsnum=$MODENUM - ;; -"misc" ) - uci set modem.general.miscnum=$MODENUM - uci commit modem - /usr/lib/rooter/luci/mask.sh - ;; -esac -uci commit modem - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh deleted file mode 100644 index 928b60d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/portchge.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -DIR=$1 - -log() { - modlog "Port change $CURRMODEM" "$@" -} - - -CURRMODEM=$(uci get modem.general.modemnum) -BASEP=$(uci get modem.modem$CURRMODEM.baseport) -MAXP=$(uci get modem.modem$CURRMODEM.maxport) -PORT=$(uci get modem.modem$CURRMODEM.commport) - -log "$DIR" - -if [ $DIR = "up" ]; then - if [ $PORT -lt $MAXP ]; then - PORT=`expr $PORT + 1` - echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file - fi -else - if [ $PORT -gt $BASEP ]; then - PORT=`expr $PORT - 1` - echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file - fi -fi - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh deleted file mode 100644 index f831521..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/protochnge.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -NEWMOD=$1 - - log() { - modlog "ProtoChange $CURRMODEM" "$@" - } - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - - change_bconf() { - local devname=$1 - local conf=$2 - local mode=$3 - local unconf=0 - log "Switching Modem at $devname to $mode by selecting Cfg# $conf" - echo $unconf >/sys/bus/usb/devices/$devname/bConfigurationValue - sleep 1 - echo $conf >/sys/bus/usb/devices/$devname/bConfigurationValue -} - - chkT77() { - T77=0 - if [ $idV = 413c -a $idP = 81d7 ]; then - T77=1 - elif [ $idV = 413c -a $idP = 81d8 ]; then - T77=1 - elif [ $idV = 0489 -a $idP = e0b4 ]; then - T77=1 - elif [ $idV = 0489 -a $idP = e0b5 ]; then - T77=1 - elif [ $idV = 1bc7 -a $idP = 1910 ]; then - T77=1 - fi -} - - chksierra() { - SIERRAID=0 - if [ $idV = 1199 ]; then - case $idP in - "68aa"|"68a2"|"68a3"|"68a9"|"68b0"|"68b1" ) - SIERRAID=1 - ;; - "68c0"|"9040"|"9041"|"9051"|"9054"|"9056"|"90d3" ) - SIERRAID=1 - ;; - "9070"|"907b"|"9071"|"9079"|"901c"|"9091"|"901f"|"90b1" ) - SIERRAID=1 - ;; - esac - elif [ $idV = 114f -a $idP = 68a2 ]; then - SIERRAID=1 - elif [ $idV = 413c -a $idP = 81a8 ]; then - SIERRAID=1 - elif [ $idV = 413c -a $idP = 81b6 ]; then - SIERRAID=1 - fi -} - -chkquectel() { - QUECTEL=false - if [ "$idV" = "2c7c" ]; then - QUECTEL=true - elif [ "$idV" = "05c6" ]; then - QUELST="9090,9003,9215" - if [[ $(echo "$QUELST" | grep -o "$idP") ]]; then - QUECTEL=true - fi - fi -} - -log "Protocol Change to $NEWMOD" - -CURRMODEM=$(uci get modem.general.modemnum) -CPORT=$(uci get modem.modem$CURRMODEM.commport) -idV=$(uci get modem.modem$CURRMODEM.uVid) -idP=$(uci get modem.modem$CURRMODEM.uPid) - -chkquectel -if $QUECTEL; then - case $NEWMOD in - "1" ) - ATCMDD='AT+QCFG="usbnet",0' - ;; - "2" ) - ATCMDD='AT+QCFG="usbnet",2' - ;; - "3" ) - ATCMDD='AT+QCFG="usbnet",1' - ;; - esac - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -fi - - chksierra - if [ $SIERRAID -eq 1 ]; then - ATCMDD='AT!ENTERCND="A710"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - - case $idP in - "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 - case $NEWMOD in - "1" ) - ATCMDD='at!UDUSBCOMP=6' - ;; - "2" ) - ATCMDD='at!UDUSBCOMP=8' - ;; - esac - ;; - "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 - case $NEWMOD in - "1" ) - ATCMDD='at!usbcomp=1,1,10d' - ;; - "2" ) - ATCMDD='at!usbcomp=1,1,1009' - ;; - esac - ;; - "9090"|"9091"|"90b1" ) # EM7565 - case $NEWMOD in - "1" ) - ATCMDD='at!usbcomp=1,3,10d' - ;; - "2" ) - ATCMDD='AT!USBCOMP=1,3,1009' - ;; - esac - ;; - esac - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ATCMDD='AT!ENTERCND="AWRONG"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - - chkT77 - if [ $T77 = "1" ]; then - DEVICE=$(uci get modem.modem$CURRMODEM.device) - if [ $NEWMOD = "1" ]; then - change_bconf $DEVICE 1 QMI - else - change_bconf $DEVICE 2 MBIM - fi - log "T77 $NEWMOD $DEVICE" - fi -sleep 5 - -/usr/lib/rooter/luci/restart.sh $CURRMODEM "9" - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh deleted file mode 100644 index 60482da..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/restart.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Modem Restart/Diisconnect $CURRMODEM" "$@" -} - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -CURRMODEM=$1 -CPORT=$(uci -q get modem.modem$CURRMODEM.commport) -INTER=$(uci get modem.modeminfo$CURRMODEM.inter) - -if [ "$2" != "9" -a "$2" != "11" ]; then - PROTO=$(uci get modem.modem$CURRMODEM.proto) - if [ "$PROTO" = "3" -o "$PROTO" = "30" ]; then - mdevice=$(uci -q get modem.modem$CURRMODEM.mdevice) - mapn=$(uci -q get modem.modem$CURRMODEM.mapn) - mipt=$(uci -q get modem.modem$CURRMODEM.mipt) - nauth=$(uci -q get modem.modem$CURRMODEM.mauth) - nusername=$(uci -q get modem.modem$CURRMODEM.musername) - mpassword=$(uci -q get modem.modem$CURRMODEM.mpassword) - log "Disconnect Network" - umbim -t 1 -d "$mdevice" disconnect - sleep 1 - exit 0 - fi - - if [ "$PROTO" = "2" ]; then - mdevice=$(uci -q get modem.modem$CURRMODEM.mdevice) - mapn=$(uci -q get modem.modem$CURRMODEM.mapn) - mcid=$(uci -q get modem.modem$CURRMODEM.mcid) - nauth=$(uci -q get modem.modem$CURRMODEM.mauth) - nusername=$(uci -q get modem.modem$CURRMODEM.musername) - mpassword=$(uci -q get modem.modem$CURRMODEM.mpassword) - uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null & sleep 1 ; kill -9 $! - exit 0 - fi - if [ "$2" = "10" ]; then - exit 0 - fi -fi - -if [ "$2" != "9" -a "$2" != "11" ]; then # disconnect - uci set modem.modem$CURRMODEM.connected=0 - uci commit modem - jkillall getsignal$CURRMODEM - rm -f $ROOTER_LINK/getsignal$CURRMODEM - jkillall con_monitor$CURRMODEM - rm -f $ROOTER_LINK/con_monitor$CURRMODEM - ifdown wan$INTER - $ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "reset.gcom" "$CURRMODEM" -else # restart - uVid=$(uci get modem.modem$CURRMODEM.uVid) - uPid=$(uci get modem.modem$CURRMODEM.uPid) - #if [ $uVid != "2c7c" ]; then - if [ ! -z "$CPORT" ]; then - ATCMDD="AT+CFUN=1,1" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - fi - log "Hard modem reset done" - #fi - ifdown wan$INTER - uci delete network.wan$CURRMODEM - uci set network.wan$CURRMODEM=interface - uci set network.wan$CURRMODEM.proto=dhcp - uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM - uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" - uci commit network - /etc/init.d/network reload - echo "1" > /tmp/modgone - log "Hard USB reset done" - - PORT="usb$CURRMODEM" - echo $PORT > /sys/bus/usb/drivers/usb/unbind - sleep 35 - echo $PORT > /sys/bus/usb/drivers/usb/bind -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh deleted file mode 100644 index dc6e96d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/scancmd.sh +++ /dev/null @@ -1,412 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Scan Command $CURRMODEM" "$@" -} - -fibdecode() { - j=$1 - tdec=$2 - mod=$3 - length=${#j} - jx=$j - length=${#jx} - - str="" - i=$((length-1)) - while [ $i -ge 0 ] - do - dgt="0x"${jx:$i:1} - DecNum=`printf "%d" $dgt` - Binary= - Number=$DecNum - while [ $DecNum -ne 0 ] - do - Bit=$(expr $DecNum % 2) - Binary=$Bit$Binary - DecNum=$(expr $DecNum / 2) - done - if [ -z $Binary ]; then - Binary="0000" - fi - len=${#Binary} - while [ $len -lt 4 ] - do - Binary="0"$Binary - len=${#Binary} - done - revstr="" - length=${#Binary} - ii=$((length-1)) - while [ $ii -ge 0 ] - do - revstr=$revstr${Binary:$ii:1} - ii=$((ii-1)) - done - str=$str$revstr - i=$((i-1)) - done - len=${#str} - ii=0 - lst="" - sep="," - hun=101 - if [ $mod = "1" ]; then - sep=":" - hun=1 - fi - while [ $ii -lt $len ] - do - bnd=${str:$ii:1} - if [ $bnd -eq 1 ]; then - if [ $tdec -eq 1 ]; then - jj=$((ii+hun)) - else - if [ $ii -lt 9 ]; then - jj=$((ii+501)) - else - jj=$((ii+5001)) - fi - fi - if [ -z $lst ]; then - lst=$jj - else - lst=$lst$sep$jj - fi - fi - ii=$((ii+1)) - done -} - -CURRMODEM=$(uci get modem.general.miscnum) -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -uVid=$(uci get modem.modem$CURRMODEM.uVid) -uPid=$(uci get modem.modem$CURRMODEM.uPid) -model=$(uci get modem.modem$CURRMODEM.model) -ACTIVE=$(uci get modem.pinginfo$CURRMODEM.alive) -uci set modem.pinginfo$CURRMODEM.alive='0' -uci commit modem -L1=$(uci get modem.modem$CURRMODEM.L1) -length=${#L1} -L1="${L1:2:length-2}" -L1=$(echo $L1 | sed 's/^0*//') -L2=$(uci get modem.modem$CURRMODEM.L2) -L1X=$(uci get modem.modem$CURRMODEM.L1X) -if [ -z $L1X ]; then - L1X="0" -fi - -case $uVid in - "2c7c" ) - M2='AT+QENG="neighbourcell"' - M5="" - case $uPid in - "0125" ) # EC25-A - EC25=$(echo $model | grep "EC25-AF") - if [ ! -z $EC25 ]; then - MX='400000000000003818' - else - MX='81a' - fi - M4='AT+QCFG="band",0,'$MX',0' - ;; - "0306" ) - M1='AT+GMR' - OX=$($ROOTER/gcom/gcom-locked "$CPORT" "run-at.gcom" "$CURRMODEM" "$M1") - EP06E=$(echo $OX | grep "EP06E") - if [ ! -z $EP06E ]; then # EP06E - M3='1a080800d5' - else # EP06-A - M3="2000001003300185A" - fi - M4='AT+QCFG="band",0,'$M3',0' - ;; - "030b" ) # EM060 - M3="420000A7E23B0E38DF" - M4='AT+QCFG="band",0,'$M3',0' - ;; - "0512" ) # EM12-G - EM12=$(echo $model | grep "EG18") - if [ -z "$EM12" ]; then - M3="2000001E0BB1F39DF" - else # EG18 - EM12=$(echo $model | grep "EA") - if [ -z "$EM12" ]; then # NA - M3="4200000100330138A" - else # EA - M3="1A0080800C5" - fi - fi - M4='AT+QCFG="band",0,'$M3',0' - ;; - "0620" ) # EM20-G - EM20=$(echo $model | grep "EM20") - if [ ! -z $EM20 ]; then # EM20 - M3="20000A7E03B0F38DF" - M4='AT+QCFG="band",0,'$M3',0' - if [ -e /etc/qfake ]; then - mask="42000087E2BB0F38DF" - fibdecode $mask 1 1 - M4F='AT+QNWPREFCFG="lte_band",'$lst - log "Fake RM500 $M4F" - fi - - else # EM160 - mask="20000A7E0BB0F38DF" - fibdecode $mask 1 1 - M4='AT+QNWPREFCFG="lte_band",'$lst - fi - ;; - "0800"|"0900"|"0801" ) - - ;; - * ) - M3="AT" - M4='AT+QCFG="band",0,'$M3',0' - ;; - esac - - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") - log "$OX" - if [ ! -z $M5 ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M5") - log "$OX" - fi - sleep 5 - ;; - "1199" ) - M2='AT!LTEINFO?' - case $uPid in - - "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 - M3="101101A" - M3X="0" - M4='AT!BAND=11,"Test",0,'$M3,$M3X - ;; - "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 - M3="100030818DF" - M3X="0" - M4='AT!BAND=11,"Test",0,'$M3,$M3X - if [ -e /etc/fake ]; then - M4='AT!BAND=11,"Test",0,A300BA0E38DF,2,0,0,0' - fi - ;; - "9090"|"9091"|"90b1" ) # EM7565 - EM7565=$(echo "$model" | grep "7565") - if [ ! -z $EM7565 ]; then - M3="A300BA0E38DF" - M3X="2" - M4='AT!BAND=11,"Test",0,'$M3","$M3X",0,0,0" - else - EM7511=$(echo "$model" | grep "7511") - if [ ! -z $EM7511 ]; then # EM7511 - M3="A300BA0E38DF" - M3X="2" - M4='AT!BAND=11,"Test",0,'$M3","$M3X",0,0,0" - else - M3="87000300385A" - M3X="42" - M4='AT!BAND=11,"Test",0,'$M3","$M3X",0,0,0" - fi - fi - - ;; - * ) - M3="AT" - ;; - esac - log "Set full : $M4" - if [ -e /etc/fake ]; then - M4='AT!BAND=11,"Test",0,'$M3,$M3X - fi - M1='AT!ENTERCND="A710"' - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M1") - log "$OX" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") - log "$OX" - M4='AT!BAND=00;!BAND=11' - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") - log "$OX" - ATCMDD='AT!ENTERCND="AWRONG"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ;; - "8087"|"2cb7" ) - rm -f /tmp/scan - echo "Cell Scanner Start ..." > /tmp/scan - echo " " >> /tmp/scan - if [ -e /tmp/scan$CURRMODEM ]; then - SCX=$(cat /tmp/scan$CURRMODEM) - echo "$SCX" >> /tmp/scan - else - echo "No Neighbouring cells were found" >> /tmp/scan - fi - echo " " >> /tmp/scan - echo "Done" >> /tmp/scan - exit 0 - ;; - * ) - rm -f /tmp/scanx - echo "Scan for Neighbouring cells not supported" >> /tmp/scan - uci set modem.pinginfo$CURRMODEM.alive=$ALIVE - uci commit modem - exit 0 - ;; -esac - -export TIMEOUT="10" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") -log "$OX" -ERR=$(echo "$OX" | grep "ERROR") -if [ ! -z $ERR ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - log "$OX" -fi -if [ ! -z $ERR ]; then - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M2") - log "$OX" -fi -log "$OX" -echo "$OX" > /tmp/scanx -rm -f /tmp/scan -echo "Cell Scanner Start ..." > /tmp/scan -echo " " >> /tmp/scan -flg=0 -while IFS= read -r line -do - case $uVid in - "2c7c" ) - qm=$(echo $line" " | grep "+QENG:" | tr -d '"' | tr " " ",") - if [ "$qm" ]; then - INT=$(echo $qm | cut -d, -f3) - BND=$(echo $qm | cut -d, -f5) - PCI=$(echo $qm | cut -d, -f6) - RSSI=$(echo $qm | cut -d, -f9) - BAND=$(/usr/bin/chan2band.sh $BND) - if [ "$INT" = "intra" ]; then - echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI (current)" >> /tmp/scan - else - echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI" >> /tmp/scan - fi - flg=1 - fi - ;; - "1199" ) - qm=$(echo $line" " | grep "Serving:" | tr -d '"' | tr " " ",") - if [ "$qm" ]; then - read -r line - qm=$(echo $line" " | tr -d '"' | tr " " ",") - BND=$(echo $qm | cut -d, -f1) - PCI=$(echo $qm | cut -d, -f10) - BAND=$(/usr/bin/chan2band.sh $BND) - RSSI=$(echo $qm | cut -d, -f13) - echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI (current)" >> /tmp/scan - flg=1 - else - qm=$(echo $line" " | grep "InterFreq:" | tr -d '"' | tr " " ",") - log "$line" - if [ "$qm" ]; then - while [ 1 = 1 ] - do - read -r line - log "$line" - qm="" - qm=$(echo $line" " | grep ":" | tr -d '"' | tr " " ",") - if [ "$qm" ]; then - break - fi - qm=$(echo $line" " | grep "OK" | tr -d '"' | tr " " ",") - if [ "$qm" ]; then - break - fi - qm=$(echo $line" " | tr -d '"' | tr " " ",") - if [ "$qm" = "," ]; then - break - fi - BND=$(echo $qm | cut -d, -f1) - PCI=$(echo $qm | cut -d, -f10) - BAND=$(/usr/bin/chan2band.sh $BND) - RSSI=$(echo $qm | cut -d, -f8) - echo "Band : $BAND Signal : $RSSI (dBm) EARFCN : $BND PCI : $PCI" >> /tmp/scan - flg=1 - done - break - fi - fi - ;; - * ) - - ;; - esac -done < /tmp/scanx - -rm -f /tmp/scanx -if [ $flg -eq 0 ]; then - echo "No Neighbouring cells were found" >> /tmp/scan -fi -echo " " >> /tmp/scan -echo "Done" >> /tmp/scan - -case $uVid in - "2c7c" ) - if [ $uPid != "0800" ]; then - if [ $uPid = 0620 -o $uPid = "0800" -o $uPid = "030b" ]; then - EM20=$(echo $model | grep "EM20") - if [ ! -z $EM20 ]; then # EM20 - M2='AT+QCFG="band",0,'$L1',0' - if [ -e /etc/fake ]; then - fibdecode $L1 1 1 - M2F='AT+QNWPREFCFG="lte_band",'$lst - log "Fake EM160 Band Set "$M2F - fi - else - fibdecode $L1 1 1 - M2='AT+QNWPREFCFG="lte_band",'$lst - fi - else - M4='AT+QCFG="band",0,'$L1',0' - fi - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") - log "$OX" - fi - ;; - "1199" ) - M1='AT!ENTERCND="A710"' - case $uPid in - - "68c0"|"9041"|"901f" ) # MC7354 EM/MC7355 - M4='AT!BAND=11,"Test",0,'$L1X,0 - ;; - "9070"|"9071"|"9078"|"9079"|"907a"|"907b" ) # EM/MC7455 - M4='AT!BAND=11,"Test",0,'$L1X,0 - if [ -e /etc/fake ]; then - M4='AT!BAND=11,"Test",0,'$L1X','$L2',0,0,0' - fi - ;; - "9090"|"9091"|"90b1" ) - M4='AT!BAND=11,"Test",0,'$L1X','$L2',0,0,0' - ;; - esac - log "Set back : $M4" - if [ -e /etc/fake ]; then - M4='AT!BAND=11,"Test",0,00000100030818DF,0' - fi - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M1") - log "$OX" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") - log "$OX" - M4='AT!BAND=00;!BAND=11' - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$M4") - log "$OX" - ATCMDD='AT!ENTERCND="AWRONG"' - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - ;; -esac -uci set modem.pinginfo$CURRMODEM.alive=$ACTIVE -uci commit modem - -log "Finished Scan" diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh deleted file mode 100644 index 4b8a488..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/setcell.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "Lock Cell $CURRMODEM" "$@" -} - -dat="$1" - -CURRMODEM=$(uci -q get modem.general.miscnum) - -dat1=$(echo $dat | tr "|" ",") -dat2=$(echo $dat1 | cut -d, -f1) -if [ $dat2 = "0" ]; then - uci set custom.bandlock.cenable$CURRMODEM='0' -else - ear=$(echo $dat1 | cut -d, -f2) - pc=$(echo $dat1 | cut -d, -f3) - ear1=$(echo $dat1 | cut -d, -f4) - pc1=$(echo $dat1 | cut -d, -f5) - ear2=$(echo $dat1 | cut -d, -f6) - pc2=$(echo $dat1 | cut -d, -f7) - ear3=$(echo $dat1 | cut -d, -f8) - pc3=$(echo $dat1 | cut -d, -f9) - uci set custom.bandlock.cenable$CURRMODEM='1' - uci set custom.bandlock.earfcn$CURRMODEM=$ear - uci set custom.bandlock.pci$CURRMODEM=$pc - uci set custom.bandlock.earfcn1$CURRMODEM=$ear1 - uci set custom.bandlock.pci1$CURRMODEM=$pc1 - uci set custom.bandlock.earfcn2$CURRMODEM=$ear2 - uci set custom.bandlock.pci2$CURRMODEM=$pc2 - uci set custom.bandlock.earfcn3$CURRMODEM=$ear3 - uci set custom.bandlock.pci3$CURRMODEM=$pc3 -fi -uci commit custom - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - - -CURRMODEM=$(uci get modem.general.miscnum) -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -CPORT=$(uci -q get modem.modem$CURRMODEM.commport) - -ATCMDD="at+qnwlock=\"common/4g\"" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -if `echo $OX | grep "ERROR" 1>/dev/null 2>&1` -then - ATCMDD="at+qnwlock=\"common/lte\",0" -else - ATCMDD=$ATCMDD",0" -fi -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -log "$OX" -sleep 5 -/usr/lib/rooter/luci/restart.sh $CURRMODEM "9" diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh deleted file mode 100644 index 1f791a0..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/luci/wifiradio.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -config_cb() { - local type="$1" - local name="$2" - if [ ! -z $type ]; then - if [ $type = "wifi-device" ]; then - echo $name >> /tmp/wifi-device - fi - fi -} - -rm -f /tmp/wifi-device -config_load wireless diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua deleted file mode 100644 index 7e7e67b..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/mbimfind.lua +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/lua - -drv = {} -idV = arg[1] -idP = arg[2] - -retval = 0 -echo = 0 - -printf = function(s,...) - if pflag ~= 0 then - io.write(s:format(...)) - local ss = s:format(...) - if echo == 1 then - os.execute("/usr/lib/rooter/logprint.sh " .. ss) - end - end -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - --- MAIN --- C: #Ifs= 3 Cfg#= 3 Atr=a0 MxPwr=500mA - -Cfgs = 1 -local i=0 -local file = io.open("/tmp/prembim", "r") -repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("D:") - if s ~= nil then - cs, ce = line:find("#Cfgs= ") - Cfgs = trim(line:sub(ce+1)) - --printf("Cfgs = %s\n", Cfgs) - end - - s, e = line:find("Vendor=") - if s ~= nil then - cs, ce = line:find(" ", e) - m_idV = trim(line:sub(e+1, cs-1)) - s, e = line:find("ProdID=") - cs, ce = line:find(" ", e) - m_idP = trim(line:sub(e+1, cs-1)) - --printf("%s %s\n", m_idV, m_idP) - if m_idV == idV and m_idP == idP then - if Cfgs == "1" then - break - end - Inter = 0 - repeat - line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("C:") - if s ~= nil then - s, e = line:find("Cfg#= ") - cs, ce = line:find(" ", e+1) - Inter = trim(line:sub(e+1, cs)) - --printf("Inter = %s\n", Inter) - end - s, e = line:find("T:") - if s ~= nil then - break - end - s, e = line:find("Cls=02") - if s ~= nil then - s, e = line:find("Sub=0e Prot=00 Driver=") - if s ~= nil then - retval=tonumber(Inter) - --printf("retval = %d\n", retval) - break - end - end - end - until 1==0 - break - end - end - end -until 1==0 -file:close() - - -os.exit(retval) \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh deleted file mode 100644 index 58f40e8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/modeswitch.sh +++ /dev/null @@ -1,620 +0,0 @@ -#!/bin/sh -. /lib/functions/procd.sh - -MODCNT=6 - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -modeswitch="/usr/bin/usb_modeswitch" - -log() { - modlog "usb-modeswitch $CURRMODEM" "$@" -} - -sanitize() { - sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@" -} - -find_usb_attrs() { - local usb_dir="/sys$DEVPATH" - [ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}" - - uVid=$(cat "$usb_dir/idVendor") - uPid=$(cat "$usb_dir/idProduct") - uMa=$(sanitize "$usb_dir/manufacturer") - uPr=$(sanitize "$usb_dir/product") - uSe=$(sanitize "$usb_dir/serial") -} - -display_top() { - log "*****************************************************************" - log "*" -} - -display_bottom() { - log "*****************************************************************" -} - - -display() { - local line1=$1 - log "* $line1" - log "*" -} - -# -# Save Interface variables -# -save_variables() { - echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file - echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file - echo 'USBN="'"$USBN"'"' >> /tmp/variable.file - echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file - echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file - echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file -} -# -# delay until ROOter Initialization done -# -bootdelay() { - if [ ! -f /tmp/bootend.file ]; then - log "Delay for boot up" - sleep 10 - while [ ! -f /tmp/bootend.file ]; do - sleep 1 - done - sleep 10 - fi -} - -# -# return modem number based on port number -# 0 is not found -# -find_device() { - DEVN=$1 - COUNTER=1 - while [ $COUNTER -le $MODCNT ]; do - EMPTY=$(uci get modem.modem$COUNTER.empty) - if [ $EMPTY -eq 0 ]; then - DEVS=$(uci get modem.modem$COUNTER.device) - if [ $DEVN = $DEVS ]; then - retresult=$COUNTER - return - fi - fi - let COUNTER=COUNTER+1 - done - retresult=0 -} - -# -# check if all modems are inactive or empty -# delete all if nothing active -# -check_all_empty() { - COUNTER=1 - while [ $COUNTER -le $MODCNT ]; do - EMPTY=$(uci get modem.modem$COUNTER.empty) - if [ $EMPTY -eq 0 ]; then - ACTIVE=$(uci get modem.modem$COUNTER.active) - if [ $ACTIVE -eq 1 ]; then - return - fi - fi - let COUNTER=COUNTER+1 - done - COUNTER=1 - while [ $COUNTER -le $MODCNT ]; do - uci delete modem.modem$COUNTER - uci set modem.modem$COUNTER=modem - uci set modem.modem$COUNTER.empty=1 - let COUNTER=COUNTER+1 - done - uci set modem.general.modemnum=1 - uci commit modem - MODSTART=1 - WWAN=0 - USBN=0 - ETHN=1 - WDMN=0 - BASEPORT=0 - if - ifconfig eth1 - then - if [ -e "/sys/class/net/eth1/device/bInterfaceProtocol" ]; then - ETHN=1 - else - ETHN=2 - fi - fi - save_variables - display_top; display "No Modems present"; display_bottom -} - -change_bconf() { - local devname=$1 - local conf=$2 - local mode=$3 - local unconf=0 - log "Switching Modem at $DEVICENAME to $mode by selecting Cfg# $bestcfg" - echo $unconf >/sys/bus/usb/devices/$devname/bConfigurationValue - sleep 1 - echo $conf >/sys/bus/usb/devices/$devname/bConfigurationValue -} - - -# -# Add Modem and connect -# -if [ "$ACTION" = add ]; then - bootdelay - CNTR=0 - while [ -e /tmp/modgone ]; do - sleep 1 - CNTR=`expr $CNTR + 1` - if [ $CNTR -gt 10 ]; then - rm -f /tmp/modgone - break - fi - done - find_usb_attrs - - if echo $DEVICENAME | grep -q ":" ; then - exit 0 - fi - - if [ -z $uMa ]; then - log "Ignoring Unnamed Hub" - exit 0 - fi - - UPR=${uPr} - CT=`echo $UPR | tr '[A-Z]' '[a-z]'` - if echo $CT | grep -q "hub" ; then - log "Ignoring Named Hub" - exit 0 - fi - - if [ $uVid = 1d6b ]; then - log "Ignoring Linux Hub" - exit 0 - fi - -# -# Ignore Ethernet adapters -# - if [ $uVid = 13b1 -a $uPid = 0041 ]; then - exit 0 - elif [ $uVid = 2357 -a $uPid = 0601 ]; then - exit 0 - elif [ $uVid = 0b95 -a $uPid = 772b ]; then - exit 0 - elif [ $uVid = 0b95 -a $uPid = 1790 ]; then - exit 0 - elif [ $uVid = 0bda -a $uPid = 8152 ]; then - exit 0 - fi - - bNumConfs=$(cat /sys/bus/usb/devices/$DEVICENAME/bNumConfigurations) - bNumIfs=$(cat /sys/bus/usb/devices/$DEVICENAME/bNumInterfaces) - - # Uncomment the next line to ignore USB-Serial adapters and similar single-port devices - # if [ $bNumConfs = 1 -a $bNumIfs = 1 ] && exit 0 - - $ROOTER/proto.sh $uVid $uPid $DEVICENAME 0 - source /tmp/proto - rm -f /tmp/proto - #cat /sys/kernel/debug/usb/devices > /tmp/wdrv - #lua $ROOTER/protofind.lua $uVid $uPid 0 - #retval=$? - - if [ -e /etc/config/mjpg-streamer ]; then - if [ $retval -eq 99 ]; then - log "Start MJPEG Streamer $DEVICENAME" - /etc/init.d/mjpg-streamer start - uci delete mjpg-streamer.camera - uci set mjpg-streamer.camera=mjpg-stream - uci set mjpg-streamer.camera.idv=$DEVICENAME - uci commit mjpg-streamer - exit 0 - fi - fi - if [ -e /etc/config/p910nd ]; then - if [ $retval -eq 98 ]; then - # Check if lp device is plugged in and p910nd is not already started - log "USB Printer device plugged in, starting p910nd" - /etc/init.d/p910nd start - uci delete p910nd.printer - uci set p910nd.printer=printer - uci set p910nd.printer.idv=$DEVICENAME - uci commit p910nd - exit 0 - fi - fi - if [ $retval -eq 97 ]; then - if grep "$uVid:$uPid" /etc/usb-mode.json > /dev/null ; then - log "Modem found" - else - log "Found USB Storage" - exit 0 - fi - fi - - DELAY=1 - if [ -f /tmp/usbwait ]; then - log "Delay for previous modem" - while [ -f /tmp/usbwait ]; do - sleep 1 - let DELAY=$DELAY+1 - if [ $DELAY -gt 15 ]; then - break - fi - done - fi - echo "1" > /tmp/usbwait - - source /tmp/variable.file - source /tmp/modcnt - MODCNT=$MODCNTX - - reinsert=0 - find_device $DEVICENAME - if [ $retresult -gt 0 ]; then - ACTIVE=$(uci get modem.modem$retresult.active) - if [ $ACTIVE = 1 ]; then - rm -f /tmp/usbwait - exit 0 - else - IDP=$(uci get modem.modem$retresult.uPid) - IDV=$(uci get modem.modem$retresult.uVid) - if [ $uVid = $IDV -a $uPid = $IDP ]; then - reinsert=1 - CURRMODEM=$retresult - MODSTART=$retresult - WWANX=$(uci get modem.modem$CURRMODEM.wwan) - if [ -n "$WWANX" ]; then - WWAN=$WWANX - save_variables - fi - WDMNX=$(uci get modem.modem$CURRMODEM.wdm) - if [ -n "$WDMNX" ]; then - WDMN=$WDMNX - save_variables - fi - else - display_top; display "Reinsert of different Modem not allowed"; display_bottom - rm -f /tmp/usbwait - exit 0 - fi - fi - fi - - log "Add : $DEVICENAME: Manufacturer=${uMa:-?} Product=${uPr:-?} Serial=${uSe:-?} $uVid $uPid" - - if [ $MODSTART -gt $MODCNT ]; then - display_top; display "Exceeded Maximun Number of Modems"; display_bottom - exit 0 - fi - - if [ $reinsert = 0 ]; then - CURRMODEM=$MODSTART - fi - - FILEN=$uVid:$uPid - display_top; display "Start of Modem Detection and Connection Information" - display "Product=${uPr:-?} $uVid $uPid"; display_bottom - cat /sys/kernel/debug/usb/devices > /tmp/prembim - lua $ROOTER/mbimfind.lua $uVid $uPid - retval=$? - rm -f /tmp/prembim - if [ ! -e /sbin/umbim ]; then - retval=0 - fi - - while : ; do - bConfig=$(cat /sys/bus/usb/devices/$DEVICENAME/bConfigurationValue) - if [ -n "$bConfig" -a -n "$bNumConfs" ]; then - log "Found Modem at $DEVICENAME in Cfg#= $bConfig from $bNumConfs available" - break - else - sleep 1 - fi - done - - FORCEQMI='03f0:0857 1bc7:1900' - if echo $FORCEQMI | grep -q -i "$FILEN"; then - bestcfg=1 - if [ $bConfig -ne $bestcfg ]; then - change_bconf $DEVICENAME $bestcfg QMI - fi - else - if [ $retval -ne 0 ]; then - display_top; display "Found MBIM Modem at $DEVICENAME with Config of $retval"; display_bottom - if [ $FILEN = "12d1:15c1" ]; then - bestcfg=2 - if [ $bConfig -ne $bestcfg ]; then - change_bconf $DEVICENAME $bestcfg ECM - fi - elif [ $FILEN = "413c:81d7" -o $FILEN = "05c6:9025" ]; then - bestcfg=1 - case $bNumConfs in - "3" ) - change_bconf $DEVICENAME $bestcfg QMI - ;; - "2" ) - if [ $bNumIfs -lt 4 ]; then - change_bconf $DEVICENAME $bestcfg QMI - fi - ;; - esac - elif [ $FILEN = "03f0:9d1d" -a $bNumConfs -eq 3 ]; then - bestcfg=1 - change_bconf $DEVICENAME $bestcfg QMI - else - if [ $bConfig -ne $retval ]; then - change_bconf $DEVICENAME $retval MBIM - fi - fi - else - if grep "$FILEN" /etc/usb-mode.json > /dev/null ; then - procd_open_service "usbmode" - procd_open_instance - procd_set_param command "/sbin/usbmode" -s - procd_close_instance - procd_close_service - else - display_top; display "Device at $DEVICENAME does not have a switch data file"; display_bottom - fi - fi - fi - sleep 10 - usb_dir="/sys$DEVPATH" - idV="$(sanitize "$usb_dir/idVendor")" - idP="$(sanitize "$usb_dir/idProduct")" - display_top; display "Modem at $DEVICENAME switched to : $idV:$idP"; display_bottom - - if [ $idV = 2357 -a $idP = 9000 ]; then - sleep 10 - fi - - #cat /sys/kernel/debug/usb/devices > /tmp/wdrv - #lua $ROOTER/protofind.lua $idV $idP 1 - $ROOTER/proto.sh $uVid $uPid $DEVICENAME 1 - source /tmp/proto - rm -f /tmp/proto - #retval=$? - if [ $idV = 8087 -a $idP = 095a ]; then - retval=28 - fi - if [ $idV = 2cb7 -a $idP = 000b ]; then - retval=28 - fi - display_top; display "ProtoFind returns : $retval"; display_bottom - rm -f /tmp/wdrv - - if [ $reinsert = 0 ]; then - BASEP=$BASEPORT - if [ -f /tmp/drv ]; then - source /tmp/drv - BASEPORT=`expr $PORTN + $BASEPORT` - fi - fi - rm -f /tmp/drv - - if [ $retval -ne 0 ]; then - log "Found Modem $CURRMODEM" - if [ $reinsert = 0 ]; then - uci set modem.modem$CURRMODEM.empty=0 - uci set modem.modem$CURRMODEM.uVid=$uVid - uci set modem.modem$CURRMODEM.uPid=$uPid - uci set modem.modem$CURRMODEM.idV=$idV - uci set modem.modem$CURRMODEM.idP=$idP - uci set modem.modem$CURRMODEM.device=$DEVICENAME - uci set modem.modem$CURRMODEM.baseport=$BASEP - uci set modem.modem$CURRMODEM.maxport=$BASEPORT - uci set modem.modem$CURRMODEM.proto=$retval - uci set modem.modem$CURRMODEM.maxcontrol=/sys$DEVPATH/descriptors - find_usb_attrs - uci set modem.modem$CURRMODEM.manuf=$uMa - uci set modem.modem$CURRMODEM.model=$uPr - uci set modem.modem$CURRMODEM.serial=$uSe - uci set modem.modem$CURRMODEM.celltype="-" - fi - uci set modem.modem$CURRMODEM.active=1 - uci set modem.modem$CURRMODEM.connected=0 - uci commit modem - if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 1 - fi - fi - - if [ $reinsert = 0 -a $retval != 0 ]; then - MODSTART=`expr $MODSTART + 1` - save_variables - fi - -# -# Handle specific modem models -# - case $retval in - "0" ) - # - # ubox GPS module - # - if [ $idV = 1546 ]; then - if echo $uPr | grep -q "GPS"; then - SYMLINK="gps0" - BASEX=`expr 1 + $BASEP` - ln -s /dev/ttyUSB$BASEX /dev/${SYMLINK} - display_top ; display "Hotplug Symlink from /dev/ttyUSB$BASEX to /dev/${SYMLINK} created" - display_bottom - fi - fi - rm -f /tmp/usbwait - exit 0 - ;; - "1" ) - log "Connecting a Sierra Modem" - ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "2" ) - log "Connecting a QMI Modem" - ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "88" ) - log "Connecting a RMNET Modem" - ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "3" ) - log "Connecting a MBIM Modem" - ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "6"|"4"|"7"|"24"|"26"|"27" ) - log "Connecting a Huawei NCM Modem" - ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "28" ) - log "Connecting a Fibocom NCM Modem" - ln -s $ROOTER/connect/create_connect.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "5" ) - log "Connecting a Hostless Modem or Phone" - ln -s $ROOTER/connect/create_hostless.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM & - ;; - "10"|"11"|"12"|"13"|"14"|"15"|"16" ) - log "Connecting a PPP Modem" - ln -s $ROOTER/ppp/create_ppp.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM - ;; - "9" ) - log "Connecting an iPhone" - ln -s $ROOTER/connect/create_iphone.sh $ROOTER_LINK/create_proto$CURRMODEM - $ROOTER_LINK/create_proto$CURRMODEM $CURRMODEM - ;; - esac - -fi - -# -# Remove Modem -# -if [ "$ACTION" = remove ]; then - find_usb_attrs - - if echo $DEVICENAME | grep -q ":" ; then - exit 0 - fi - find_device $DEVICENAME - if [ $retresult -gt 0 ]; then - IDP=$(uci get modem.modem$retresult.idP) - IDV=$(uci get modem.modem$retresult.idV) - if [ $uVid = $IDV ]; then - exit 0 - else - INTER=$(uci get modem.modem$retresult.inter) - if [ -z $INTER ]; then - INTER=$retresult - fi - if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $retresult 0 - fi - uci set modem.modem$retresult.active=0 - uci set modem.modem$retresult.connected=0 - uci commit modem - if [ -e /etc/config/mwan3 ]; then - ENB=$(uci get mwan3.wan$retresult.enabled) - if [ ! -z $ENB ]; then - uci set mwan3.wan$INTER.enabled=0 - uci commit mwan3 - fi - fi - SMS=$(uci get modem.modem$CURRMODEM.sms) - if [ $SMS = 1 ]; then - if [ -e /usr/lib/sms/stopsms ]; then - /usr/lib/sms/stopsms $CURRMODEM - fi - fi - ifdown wan$INTER - uci delete network.wan$INTER - uci set network.wan$INTER=interface - uci set network.wan$INTER.proto=dhcp - ifname1="ifname" - if [ -e /etc/newstyle ]; then - ifname1="device" - fi - uci set network.wan$INTER.${ifname1}=" " - uci set network.wan$INTER.metric=$INTER"0" - uci commit network - /etc/init.d/network reload - ifdown wan$INTER - PID=$(ps |grep "getsignal$retresult" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID - rm -f $ROOTER_LINK/getsignal$retresult - PID=$(ps |grep "reconnect$retresult" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID - rm -f $ROOTER_LINK/reconnect$retresult - PID=$(ps |grep "create_proto$retresult" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID - rm -f $ROOTER_LINK/create_proto$retresult - PID=$(ps |grep "processsms$retresult" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID - rm -f $ROOTER_LINK/processsms$retresult - PID=$(ps |grep "con_monitor$retresult" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID - rm -f $ROOTER_LINK/con_monitor$retresult - PID=$(ps |grep "mbim_monitor$retresult" | grep -v grep |head -n 1 | awk '{print $1}') - kill -9 $PID - rm -f $ROOTER_LINK/mbim_monitor$retresult - if [ -e /usr/lib/gps/gpskill.sh ]; then - /usr/lib/gps/gpskill.sh $retresult - fi - $ROOTER/signal/status.sh $retresult "No Modem Present" - $ROOTER/log/logger "Disconnect (Removed) Modem #$retresult" - display_top; display "Remove : $DEVICENAME : Modem $retresult"; display_bottom - check_all_empty - rm -f /tmp/usbwait - rm -f /tmp/mdown$retresult - rm -f /tmp/msimdata$retresult - rm -f /tmp/msimnum$retresult - rm -f /tmp/modgone - rm -f /tmp/bmask - rm -f /tmp/simpin$retresult - fi - else - IDV=$(uci get mjpg-streamer.camera.idv) - if [ ! -z $IDV ]; then - if [ $DEVICENAME = $IDV ]; then - uci delete mjpg-streamer.camera - uci commit mjpg-streamer - /etc/init.d/mjpg-streamer stop - log "Stop MJPEG-Streamer" - fi - fi - IDV=$(uci get p910nd.printer.idv) - if [ ! -z $IDV ]; then - if [ $DEVICENAME = $IDV ]; then - uci delete p910nd.printer - uci commit p910nd - if [ ! -d /sys$DEVPATH/*/lp0 -a -f /var/run/p9100d.pid ]; then - log "USB Printer device unplugged, stopping p910nd" - /etc/init.d/p910nd stop - # p910nd does not seem to remove .pid file when stopped, removing it manually - rm /var/run/p9100d.pid - fi - fi - fi - fi -fi - -if [ "$ACTION" = "motion" ]; then - logger webcam motion event -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua deleted file mode 100644 index 3e39cb3..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/ncmfind.lua +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/lua - -drv = {} -idV = arg[1] -idP = arg[2] - -printf = function(s,...) - io.write(s:format(...)) -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -local Inter=0 -local file = io.open("/tmp/wdrv", "r") -repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("Vendor=") - if s ~= nil then - cs, ce = line:find(" ", e) - m_idV = trim(line:sub(e+1, cs-1)) - s, e = line:find("ProdID=") - cs, ce = line:find(" ", e) - m_idP = trim(line:sub(e+1, cs-1)) - if m_idV == idV and m_idP == idP then - repeat - line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("Prot=") - if s ~= nil then - cs, ce = line:find(" ", e+1) - proto = trim(line:sub(e+1, cs)) - if proto == "2" or proto == "02" or proto == "12" or proto == "32" or proto == "42" or proto == "62" or proto == "72" then - break - else - s, e = line:find("=option") - if s ~= nil then - Inter = Inter + 1 - end - end - end - s, e = line:find("T:") - if s ~= nil then - break - end - end - until 1==0 - break - end - end - end -until 1==0 -file:close() - -os.exit(Inter) \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh deleted file mode 100644 index 1a00770..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/nitz2sys.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -log() { - logger -t "NITZ set time" "$@" -} - -CURRMODEM=$(uci -q get modem.general.modemnum) -COMMPORT="/dev/ttyUSB"$(uci -q get modem.modem$CURRMODEM.commport) -ROOTER=/usr/lib/rooter - -ATCMDD="AT+CTZU?;+CCLK?" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -OX=$OX -SUCCESS=1 -NITZstat=$(echo "$OX" | grep "+CTZU: 1") -if [ -n "$NITZstat" ]; then - DTG=$(echo "$OX" | grep -o "+CCLK:.*" | cut -d\" -f2) - DTGyymmdd=$(echo "$DTG" | cut -d, -f1 | tr '/' '-') - DTGhhmmss=$(echo "$DTG" | cut -d, -f2) - DTGhhmmss=${DTGhhmmss:0:8} - DTGtz=$(echo "$DTG" | grep -o "[-+][0-9]\{1,2\}") - if [ -n "$DTGtz" ]; then - DTGif=$(date +%s -u -s "$DTGyymmdd $DTGhhmmss") - OX=$(date -s @$DTGif) - log "$OX" - SUCCESS=0 - fi -fi -exit $SUCCESS diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh deleted file mode 100644 index 968f039..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/portchge.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -DIR=$1 - -log() { - logger -t "port change" "$@" -} - - -CURRMODEM=$(uci get modem.general.modemnum) -BASEP=$(uci get modem.modem$CURRMODEM.baseport) -MAXP=$(uci get modem.modem$CURRMODEM.maxport) -PORT=$(uci get modem.modem$CURRMODEM.commport) - -log "$DIR" - -if [ $DIR = "up" ]; then - if [ $PORT -lt $MAXP ]; then - PORT=`expr $PORT + 1` - echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file - fi -else - if [ $PORT -gt $BASEP ]; then - PORT=`expr $PORT - 1` - echo 'PORT="'"$PORT"'"' > /tmp/port$CURRMODEM.file - fi -fi - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh deleted file mode 100644 index e018901..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/ppp/create_ppp.sh +++ /dev/null @@ -1,247 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Create Connection $CURRMODEM" "$@" -} - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -set_dns() { - local pDNS1=$(uci -q get modem.modeminfo$CURRMODEM.dns1) - local pDNS2=$(uci -q get modem.modeminfo$CURRMODEM.dns2) - local pDNS3=$(uci -q get modem.modeminfo$CURRMODEM.dns3) - local pDNS4=$(uci -q get modem.modeminfo$CURRMODEM.dns4) - - local aDNS="$pDNS1 $pDNS2 $pDNS3 $pDNS4" - local bDNS="" - - echo "$aDNS" | grep -o "[[:graph:]]" &>/dev/null - if [ $? = 0 ]; then - log "Using DNS settings from the Connection Profile" - pdns=1 - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0.0.0.0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -n "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - - bDNS=$(echo $bDNS) - if [ $DHCP = 1 ]; then - uci set network.wan$INTER.peerdns=0 - uci set network.wan$INTER.dns="$bDNS" - fi - echo "$bDNS" > /tmp/v4dns$INTER - - bDNS="" - for DNSV in $(echo "$aDNS"); do - if [ "$DNSV" != "0:0:0:0:0:0:0:0" ] && [ -z "$(echo "$bDNS" | grep -o "$DNSV")" ]; then - [ -z "$(echo "$DNSV" | grep -o ":")" ] && continue - bDNS="$bDNS $DNSV" - fi - done - echo "$bDNS" > /tmp/v6dns$INTER - else - log "Using Provider assigned DNS" - pdns=0 - rm -f /tmp/v[46]dns$INTER - fi -} - -save_variables() { - echo 'MODSTART="'"$MODSTART"'"' > /tmp/variable.file - echo 'WWAN="'"$WWAN"'"' >> /tmp/variable.file - echo 'USBN="'"$USBN"'"' >> /tmp/variable.file - echo 'ETHN="'"$ETHN"'"' >> /tmp/variable.file - echo 'WDMN="'"$WDMN"'"' >> /tmp/variable.file - echo 'BASEPORT="'"$BASEPORT"'"' >> /tmp/variable.file -} - -get_connect() { - NAPN=$(uci get modem.modeminfo$CURRMODEM.apn) - NUSER=$(uci get modem.modeminfo$CURRMODEM.user) - NPASS=$(uci get modem.modeminfo$CURRMODEM.passw) - NAUTH=$(uci get modem.modeminfo$CURRMODEM.auth) - PINC=$(uci get modem.modeminfo$CURRMODEM.pincode) - - uci set modem.modem$CURRMODEM.apn=$NAPN - uci set modem.modem$CURRMODEM.user=$NUSER - uci set modem.modem$CURRMODEM.pass=$NPASS - uci set modem.modem$CURRMODEM.auth=$NAUTH - uci set modem.modem$CURRMODEM.pin=$PINC - uci commit modem -} - -CURRMODEM=$1 -source /tmp/variable.file - -MAN=$(uci get modem.modem$CURRMODEM.manuf) -MOD=$(uci get modem.modem$CURRMODEM.model) -BASEP=$(uci get modem.modem$CURRMODEM.baseport) -$ROOTER/signal/status.sh $CURRMODEM "$MAN $MOD" "Connecting" -PROT=$(uci get modem.modem$CURRMODEM.proto) - -DELAY=$(uci get modem.modem$CURRMODEM.delay) -if [ -z $DELAY ]; then - DELAY=5 -fi - -idV=$(uci get modem.modem$CURRMODEM.idV) -idP=$(uci get modem.modem$CURRMODEM.idP) - -cat /sys/kernel/debug/usb/devices > /tmp/cdma -lua $ROOTER/cdmafind.lua $idV $idP -retval=$? -rm -f /tmp/cdma -if [ $retval -eq 1 ]; then - log "Found CDMA modem" -fi - -case $PROT in -"10" ) - if [ $retval -eq 0 ]; then - DP=0 - CP=2 - else - DP=0 - CP=0 - fi - ;; -"11"|"12" ) - if [ $retval -eq 0 ]; then - DP=2 - CP=1 - else - DP=0 - CP=0 - fi - ;; -"13" ) - if [ $retval -eq 0 ]; then - DP=4 - CP=3 - else - DP=0 - CP=0 - fi - ;; -"14" ) - if [ $retval -eq 0 ]; then - DP=3 - CP=2 - else - DP=0 - CP=0 - fi - ;; -"15" ) - if [ $retval -eq 0 ]; then - DP=1 - CP=2 - else - DP=0 - CP=0 - fi - ;; -"16" ) - if [ $retval -eq 0 ]; then - DP=2 - CP=0 - ln -s /dev/ttyACM$CP /dev/ttyUSB$CP - ln -s /dev/ttyACM$DP /dev/ttyUSB$DP - else - DP=0 - CP=0 - fi - ;; -esac -$ROOTER/common/modemchk.lua "$idV" "$idP" "$DP" "$CP" -source /tmp/parmpass - -CPORT=`expr $CPORT + $BASEP` -DPORT=`expr $DPORT + $BASEP` -uci set modem.modem$CURRMODEM.commport=$CPORT -uci set modem.modem$CURRMODEM.dataport=$DPORT -uci set modem.modem$CURRMODEM.service=$retval -uci commit modem - -$ROOTER/common/gettype.sh $CURRMODEM -$ROOTER/connect/get_profile.sh $CURRMODEM -get_connect - -INTER=$(uci get modem.modeminfo$CURRMODEM.inter) -if [ -z $INTER ]; then - INTER=$CURRMODEM -else - if [ $INTER = 0 ]; then - INTER=$CURRMODEM - fi -fi -log "Profile for Modem $CURRMODEM sets interface to WAN$INTER" -OTHER=1 -if [ $CURRMODEM = 1 ]; then - OTHER=2 -fi -EMPTY=$(uci get modem.modem$OTHER.empty) -if [ $EMPTY = 0 ]; then - OINTER=$(uci get modem.modem$OTHER.inter) - if [ ! -z $OINTER ]; then - if [ $INTER = $OINTER ]; then - INTER=1 - if [ $OINTER = 1 ]; then - INTER=2 - fi - log "Switched Modem $CURRMODEM to WAN$INTER as Modem $OTHER is using WAN$OINTER" - fi - fi -fi -uci set modem.modem$CURRMODEM.inter=$INTER -uci commit modem -log "Modem $CURRMODEM is using WAN$INTER" -uci delete network.wan$INTER -uci set network.wan$INTER=interface -uci set network.wan$INTER.${ifname1}=3x-wan$INTER -uci set network.wan$INTER.proto=3x -if [ $retval -eq 0 ]; then - uci set network.wan$INTER.service=umts -else - uci set network.wan$INTER.service=cdma -fi -uci set network.wan$INTER.keepalive=10 -uci set network.wan$INTER.device=/dev/ttyUSB$DPORT -uci set network.wan$INTER.apn=$NAPN -uci set network.wan$INTER.username=$NUSER -uci set network.wan$INTER.auth=$NAUTH -uci set network.wan$INTER.password=$NPASS -uci set network.wan$INTER.pincode=$PINC -uci set network.wan$INTER.metric=$CURRMODEM"0" -uci set network.wan$INTER.currmodem=$CURRMODEM -uci set network.wan$INTER.pppd_options="debug noipdefault" -set_dns -uci commit network - -log "PPP Comm Port : /dev/ttyUSB$CPORT" -log "PPP Data Port : /dev/ttyUSB$DPORT" - -if [ $retval -eq 0 ]; then - case $idV in - "1199"|"0f3d"|"413c"|"2c7c"|"05c6" ) - $ROOTER/luci/celltype.sh $CURRMODEM - ;; - esac - $ROOTER/common/lockchk.sh $CURRMODEM - $ROOTER/sms/check_sms.sh $CURRMODEM & -fi - -if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 2 -fi - -rm -f /tmp/usbwait -ifup wan$INTER diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/proto.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/proto.sh deleted file mode 100644 index f4afc7f..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/proto.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/sh - -log() { - modlog "Protofind $idV/$idP" "$@" -} - -idV=$1 -idP=$2 -DEVICENAME=$3 -path="/sys/bus/usb/devices/$DEVICENAME/" -cnfg=$(cat $path"bConfigurationValue") -ipath="$DEVICENAME:$cnfg." - -cntr=$(cat $path"bNumInterfaces") -cntr=$(echo "$cntr" | sed 's/[[:space:]]//g') -if [ $4 -eq 1 ]; then - log "Number Interfaces w/drivers : $cntr" -fi -serialcnt=0 -retval=0 -fcntr=0 - -while [ true ]; do - if [ -e $path$ipath$fcntr ]; then - DRIVER="" - cat $path$ipath$fcntr"/uevent" > /tmp/uevent$DEVICENAME - source /tmp/uevent$DEVICENAME - rm -f /tmp/uevent$DEVICENAME - if [ $4 -eq 1 ]; then - log "Driver Name : $fcntr $DRIVER" - fi - if [ "$DRIVER" = "option" -o "$DRIVER" = "qcserial" -o "$DRIVER" = "usb_serial" -o drv[j] == "usb_serial" -o "$DRIVER" = "sierra" ]; then - let serialcnt=$serialcnt+1 - fi - let cntr=$cntr-1 - if [ "$cntr" -lt 1 ]; then - break - fi - fi - let fcntr=$fcntr+1 -done -cntr=$(cat $path"bNumInterfaces") -cntr=$(echo "$cntr" | sed 's/[[:space:]]//g') -fcntr=0 -while [ true ]; do - if [ -e $path$ipath$fcntr ]; then - cat $path$ipath$fcntr"/uevent" > /tmp/uevent$DEVICENAME - source /tmp/uevent$DEVICENAME - rm -f /tmp/uevent$DEVICENAME - case $DRIVER in - "sierra_net" ) - retval=1 - break - ;; - "qmi_wwan" ) - retval=2 - break - ;; - "qmi_wwan_q" ) - retval=88 - break - ;; - "cdc_mbim" ) - retval=3 - break - ;; - "huawei_cdc_ncm" ) - retval=4 - break - ;; - "cdc_ncm" ) - retval=24 - break - ;; - "cdc_ether"|"rndis_host" ) - retval=5 - break - ;; - "ipheth" ) - retval=9 - break - ;; - "uvcvideo" ) - retval=99 - break - ;; - "usblp" ) - retval=98 - break - ;; - "usb-storage" ) - retval=97 - break - ;; - esac - let cntr=$cntr-1 - if [ "$cntr" -lt 1 ]; then - break - fi - fi - let fcntr=$fcntr+1 -done -if [ $serialcnt -gt 0 -a $retval -eq 0 ]; then - retval=88 -fi -echo 'retval="'"$retval"'"' > /tmp/proto - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua deleted file mode 100644 index 1df86c6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/protofind.lua +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/lua - -drv = {} -idV = arg[1] -idP = arg[2] -pflag = arg[3] -if pflag == nil then - pflag = 1 -end - -special = {} --- PPP special cases --- VID PID port # -special[1] = "1bbb" ; special[2] = "0017" ; special[3] = 13 -special[4] = "12d1" ; special[5] = nil ; special[6] = 10 -special[7] = "1546" ; special[8] = "01a6" ; special[9] = 0 -special[10] = "1546" ; special[11] = "01a5" ; special[12] = 0 -special[13] = "1199" ; special[14] = "68a3" ; special[15] = 14 -special[16] = "2001" ; special[17] = "7e35" ; special[18] = 15 - - -retval = 0 -echo = 1 - -printf = function(s,...) - if pflag ~= 0 then - io.write(s:format(...)) - local ss = s:format(...) - if echo == 1 then - os.execute("/usr/lib/rooter/logprint.sh " .. ss) - end - end -end - -function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) -end - -function checkserial() - local got = 0 - j = 1 - repeat - if drv[j] ~= nil then - if drv[j] == "option" or drv[j] == "qcserial" or drv[j] == "usb_serial" or drv[j] == "sierra" then - got = 1 - break - end - j = j + 1 - end - until drv[j] == nil - return got -end - -function countserial() - local got = 0 - j = 1 - repeat - if drv[j] ~= nil then - if drv[j] == "option" or drv[j] == "sierra" or drv[j] == "usb_serial" or drv[j] == "qcserial" then - got = got + 1 - end - j = j + 1 - end - until drv[j] == nil - return got -end - --- MAIN - -local t = {} - -local i=0 -local file = io.open("/tmp/wdrv", "r") -repeat - local line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("Vendor=") - if s ~= nil then - cs, ce = line:find(" ", e) - m_idV = trim(line:sub(e+1, cs-1)) - s, e = line:find("ProdID=") - cs, ce = line:find(" ", e) - m_idP = trim(line:sub(e+1, cs-1)) - if m_idV == idV and m_idP == idP then - repeat - line = file:read("*line") - if line == nil then - break - end - if string.len(line) > 5 then - s, e = line:find("T:") - if s ~= nil then - break - end - s, e = line:find("Cls=02") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - s, e = line:find("Cls=ff") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - s, e = line:find("1 Cls=e0") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - s, e = line:find("Cls=0a") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - s, e = line:find("Cls=0e") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - s, e = line:find("Cls=07") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - s, e = line:find("Cls=08") - if s ~= nil then - t[i] = trim(line:sub(63)) - i = i + 1 - end - end - until 1==0 - break - end - end - end -until 1==0 -file:close() -if i > 0 then - file = io.open("/tmp/drv", "w") - for j=0,i-1 do - drv[j+1] = t[j] - drver = string.format("%s%d%s%q", "DRIVER", j+1, "=", t[j]) - file:write(drver .. "\n") - end - ports = countserial() - drver = string.format("%s%s%d%s", "PORTN", "=\"", ports, "\"") - file:write(drver .. "\n") - file:close() -end - -i = 1 -repeat - if drv[i] ~= nil then - printf("Driver Name : %d %s\n", i, drv[i]) - i = i + 1 - end -until drv[i] == nil - -i = 1 -repeat - if drv[i] ~= nil then - if drv[i] == "sierra_net" then - retval = 1 - break - end - if drv[i] == "qmi_wwan" then - retval = 2 - break - end - if drv[i] == "cdc_mbim" then - retval = 3 - break - end - if drv[i] == "huawei_cdc_ncm" then - if i == 2 then - retval = 4 - else - if i == 3 then - retval = 6 - else - retval = 7 - end - end - break - end - if drv[i] == "cdc_ncm" then - if i == 2 then - retval = 24 - else - if i == 3 then - retval = 26 - else - retval = 27 - end - end - break - end - if drv[i] == "cdc_ether" or drv[i] == "rndis_host" then - retval = 5 - break - end - if drv[i] == "ipheth" then - retval = 9 - break - end - if drv[i] == "uvcvideo" then - retval = 99 - break - end - if drv[i] == "usblp" then - retval = 98 - break - end - if drv[i] == "usb-storage" then - retval = 97 - end - i = i + 1 - end -until drv[i] == nil - -if retval == 0 then - if checkserial() == 1 then - retval = 11 - k = 1 - vendor = special[k] - while vendor ~= nil do - if idV == vendor then - if special[k+1] == nil then - retval = special[k+2] - break - else - if special[k+1] == idP then - retval = special[k+2] - break - end - end - end - k = k + 3 - vendor = special[k] - end - end -end - -os.exit(retval) diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh deleted file mode 100644 index aaa15c7..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/pwrtoggle.sh +++ /dev/null @@ -1,181 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - modlog "Power Toggle $CURRMODEM" "$@" -} - -ifname1="ifname" -if [ -e /etc/newstyle ]; then - ifname1="device" -fi - -waitfor() { - CNTR=0 - while [ -e /tmp/modgone ]; do - sleep 1 - CNTR=`expr $CNTR + 1` - if [ $CNTR -gt 35 ]; then - rm -f /tmp/modgone - break - fi - done -} - -rebind() { - CFUNDONE=false - ARG=$1 - CURRMODEM=$(echo "${ARG: -1}") - PROT=$(uci -q get modem.modem$CURRMODEM.proto) - CPORT=$(uci -q get modem.modem$CURRMODEM.commport) - if [ -n "$CPORT" ]; then - VENDOR=$(uci -q get modem.modem$CURRMODEM.idV) - PRODUCT=$(uci -q get modem.modem$CURRMODEM.idP) - # list vendors that do not fully support 3GPP +CFUN - NOCFUN="2c7c" # Quectel will stuck after CFUN, so not using that method at all - case $VENDOR in - "12d1" ) - ATCMDD="AT^RESET" - ;; - "2c7c" ) - ATCMDD="AT" - ;; - * ) - ATCMDD="AT+CFUN=1,1" - ;; - esac - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - if `echo ${OX} | grep "OK" 1>/dev/null 2>&1` && \ - [[ ! `echo $NOCFUN | grep -o "$VENDOR"` ]]; then - CFUNDONE=true - log "Hard modem reset done on /dev/ttyUSB$CPORT to reload drivers" - ifdown wan$CURRMODEM - uci delete network.wan$CURRMODEM - uci set network.wan$CURRMODEM=interface - uci set network.wan$CURRMODEM.proto=dhcp - uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM - uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" - uci commit network - /etc/init.d/network reload - ifdown wan$CURRMODEM - echo "1" > /tmp/modgone - log "Setting Modem Removal flag (1)" - fi - fi - if ! $CFUNDONE; then - PORT=$1 - log "Re-binding USB driver on $PORT to reset modem" - echo $PORT > /sys/bus/usb/drivers/usb/unbind - sleep 35 - echo $PORT > /sys/bus/usb/drivers/usb/bind - ifdown wan$CURRMODEM - uci delete network.wan$CURRMODEM - uci set network.wan$CURRMODEM=interface - uci set network.wan$CURRMODEM.proto=dhcp - uci set network.wan$CURRMODEM.${ifname1}="wan"$CURRMODEM - uci set network.wan$CURRMODEM.metric=$CURRMODEM"0" - uci commit network - /etc/init.d/network reload - ifdown wan$CURRMODEM - echo "1" > /tmp/modgone - log "Setting Modem Removal flag (2)" - if [[ -n "$CPORT" ]] && [[ ! `echo $NOCFUN | grep -o "$VENDOR"` ]]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - sleep 30 - else - if [ -f $ROOTER_LINK/reconnect$CURRMODEM ]; then - $ROOTER_LINK/reconnect$CURRMODEM $CURRMODEM & - fi - fi - fi -} - -power_toggle() { - MODE=$1 - REBIND=false - if [ -f "/tmp/gpiopin" ]; then - rm -f /tmp/modgone - source /tmp/gpiopin - if [ -f "/tmp/gpioname" ]; then - source /tmp/gpioname - else - echo "$GPIOPIN" > /sys/class/gpio/unexport - echo "$GPIOPIN" > /sys/class/gpio/export - if [ $? -eq 0 ]; then - echo "out" > /sys/class/gpio/gpio$GPIOPIN/direction - if [ $? -ne 0 ]; then - REBIND=true - fi - else - REBIND=true - fi - fi - if ! $REBIND; then - if [ -z $GPIOPIN2 ]; then - if [ -z $GPIONAME ]; then - GPIOT="gpio$GPIOPIN" - else - GPIOT=$GPIONAME - fi - echo 0 > /sys/class/gpio/$GPIOT/value - waitfor - echo 1 > /sys/class/gpio/$GPIOT/value - else - if [ -z $GPIONAME2 ]; then - echo "$GPIOPIN2" > /sys/class/gpio/unexport - echo "$GPIOPIN2" > /sys/class/gpio/export - echo "out" > /sys/class/gpio/gpio$GPIOPIN2/direction - - GPIOT2="gpio$GPIOPIN2" - else - GPIOT2=$GPIONAME2 - fi - if [ -z $GPIONAME ]; then - GPIOT="gpio$GPIOPIN" - else - GPIOT=$GPIONAME - fi - if [ $MODE = 1 ]; then - echo 0 > /sys/class/gpio/$GPIOT/value - waitfor - echo 1 > /sys/class/gpio/$GPIOT/value - fi - if [ $MODE = 2 ]; then - echo 0 > /sys/class/gpio/$GPIOT2/value - waitfor - echo 1 > /sys/class/gpio/$GPIOT2/value - fi - if [ $MODE = 3 ]; then - echo 0 > /sys/class/gpio/$GPIOT/value - echo 0 > /sys/class/gpio/$GPIOT2/value - waitfor - echo 1 > /sys/class/gpio/$GPIOT/value - echo 1 > /sys/class/gpio/$GPIOT2/value - fi - sleep 2 - fi - echo "1" > /tmp/modgone - log "Power Toggle Modem" - log "Setting Modem Removal flag (3)" - fi - else - REBIND=true - fi - if $REBIND; then - # unbind/bind driver from USB to reset modem when power toggle is selected, but not available - if [ $MODE = 1 ]; then - PORT="usb1" - rebind $PORT - fi - if [ $MODE = 2 ]; then - PORT="usb2" - rebind $PORT - fi - echo "1" > /tmp/modgone - log "Setting Modem Removal flag (4)" - fi -} - -power_toggle $1 diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh deleted file mode 100644 index 32aabd9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/shutall.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -CURRMODEM=1 -COMMPORT=$(uci get modem.modem$CURRMODEM.commport) -if [ -n "$COMMPORT" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=0") -fi -CURRMODEM=2 -COMMPORT=$(uci get modem.modem$CURRMODEM.commport) -if [ -n "$COMMPORT" ]; then - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "AT+CFUN=0") -fi -poweroff diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh deleted file mode 100644 index 4b0a31e..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/basedata.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "basedata" "$@" -} - -CURRMODEM=$1 -COMMPORT=$2 - -get_base() { - echo "0" > /tmp/block - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "baseinfo.gcom" "$CURRMODEM") - O=$($ROOTER/common/processat.sh "$OX") - rm -f /tmp/block -} - -get_base - -DOWN=$(echo "$O" | awk -F[,] '/\+CGEQNEG:/ {printf "%s", $4}') -if [ "x$DOWN" != "x" ]; then - UP=$(echo "$O" | awk -F[,] '/\+CGEQNEG:/ {printf "%s", $3}') - DOWN=$DOWN" kbps Down | " - UP=$UP" kbps Up" -else - DOWN="-" - UP="-" -fi - -MANUF=$(echo "$O" | awk -F[:] '/Manufacturer:/ { print $2}') -if [ "x$MANUF" = "x" ]; then - MANUF=$(uci get modem.modem$CURRMODEM.manuf) -fi - -MODEL=$(echo "$O" | awk -F[,\ ] '/^\+MODEL:/ {print $2}') -if [ "x$MODEL" != "x" ]; then - MODEL=$(echo "$MODEL" | sed -e 's/"//g') - if [ $MODEL = 0 ]; then - MODEL = "mf820" - fi -else - MODEL=$(uci get modem.modem$CURRMODEM.model) -fi -MODEM=$MANUF" "$MODEL - -pval=$(uci get modem.modem$CURRMODEM.proto) -case $pval in -"1" ) - PROTO="Direct-IP" - ;; -"88" ) - PROTO="(QMI-RMNET)" - ;; -"2" ) - PROTO="QMI" - ;; -"3"|"30" ) - PROTO="MBIM" - ;; -"6"|"4"|"7"|"24"|"26"|"27"|"28" ) - PROTO="NCM" - ;; -"10"|"11"|"12"|"13"|"14"|"15" ) - PROTO="PPP" - ;; -"5" ) - PROTO="Ethernet" - ;; -"9" ) - PROTO="ipheth" - ;; -esac - -echo 'MODEM="'"$MODEM"'"' >> /tmp/base$CURRMODEM.file -echo 'DOWN="'"$DOWN"'"' >> /tmp/base$CURRMODEM.file -echo 'UP="'"$UP"'"' >> /tmp/base$CURRMODEM.file -echo 'PROTO="'"$PROTO"'"' >> /tmp/base$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh deleted file mode 100644 index 4e163f7..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celldata.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -CURRMODEM=$1 -COMMPORT=$2 - -if [ -e /etc/nocops ]; then - echo "0" > /tmp/block - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "cellinfo0.gcom" "$CURRMODEM") - rm -f /tmp/block -else - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "cellinfo0.gcom" "$CURRMODEM") -fi -OY=$($ROOTER/gcom/gcom-locked "$COMMPORT" "cellinfo.gcom" "$CURRMODEM") -OXx=$OX - -OX=$(echo $OX | tr 'a-z' 'A-Z') -OY=$(echo $OY | tr 'a-z' 'A-Z') -OX=$OX" "$OY - -COPS="-" -COPS_MCC="-" -COPS_MNC="-" -COPSX=$(echo $OXx | grep -o "+COPS: [01],0,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - -if [ "x$COPSX" != "x" ]; then - COPS=$COPSX -fi - -COPSX=$(echo $OX | grep -o "+COPS: [01],2,.\+," | cut -d, -f3 | grep -o "[^\"]\+") - -if [ "x$COPSX" != "x" ]; then - COPS_MCC=${COPSX:0:3} - COPS_MNC=${COPSX:3:3} - if [ "$COPS" = "-" ]; then - COPS=$(awk -F[\;] '/'$COPS'/ {print $2}' $ROOTER/signal/mccmnc.data) - [ "x$COPS" = "x" ] && COPS="-" - fi -fi - -if [ "$COPS" = "-" ]; then - COPS=$(echo "$O" | awk -F[\"] '/^\+COPS: 0,0/ {print $2}') - if [ "x$COPS" = "x" ]; then - COPS="-" - COPS_MCC="-" - COPS_MNC="-" - fi -fi -COPS_MNC=" "$COPS_MNC - -OX=$(echo "${OX//[ \"]/}") - -CID="" -CID5="" -RAT="" -REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}") -if [ -n "$REGV" ]; then - LAC5=$(echo "$REGV" | cut -d, -f3) - LAC5=$LAC5" ($(printf "%d" 0x$LAC5))" - CID5=$(echo "$REGV" | cut -d, -f4) - CID5L=$(printf "%010X" 0x$CID5) - RNC5=${CID5L:1:6} - RNC5=$RNC5" ($(printf "%d" 0x$RNC5))" - CID5=${CID5L:7:3} - CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))" - RAT=$(echo "$REGV" | cut -d, -f5) -fi -REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}") -REGFMT="3GPP" -if [ -z "$REGV" ]; then - REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}") - REGFMT="SW" -fi -if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - if [ $REGFMT = "3GPP" ]; then - CID=$(echo "$REGV" | cut -d, -f4) - else - CID=$(echo "$REGV" | cut -d, -f5) - fi - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:5} - RNC=$RNC" ($(printf "%d" 0x$RNC))" - CID=${CIDL:6:2} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - -else - REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}") - if [ -n "$REGV" ]; then - LAC=$(echo "$REGV" | cut -d, -f3) - CID=$(echo "$REGV" | cut -d, -f4) - if [ ${#CID} -gt 4 ]; then - LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))" - CIDL=$(printf "%08X" 0x$CID) - RNC=${CIDL:1:3} - CID=${CIDL:4:4} - CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))" - else - LAC="" - fi - else - LAC="" - fi -fi -REGSTAT=$(echo "$REGV" | cut -d, -f2) -if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then - COPS_MNC=$COPS_MNC" (Roaming)" -fi -if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then - LAC="4G $LAC, 5G $LAC5" - CID="4G $CID
                                                                      5G $CID5" - RNC="4G $RNC, 5G $RNC5" -elif [ -n "$CID5" ]; then - LAC=$LAC5 - CID=$CID5 - RNC=$RNC5 -fi -if [ -z "$LAC" ]; then - LAC="-" - CID="-" - RNC="-" -fi - -{ - echo 'COPS="'"$COPS"'"' - echo 'COPS_MCC="'"$COPS_MCC"'"' - echo 'COPS_MNC="'"$COPS_MNC"'"' - echo 'LAC="'"$LAC"'"' - echo 'LAC_NUM="'""'"' - echo 'CID="'"$CID"'"' - echo 'CID_NUM="'""'"' - echo 'RNC="'"$RNC"'"' - echo 'RNC_NUM="'""'"' -} > /tmp/cell$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua deleted file mode 100644 index 62b8ab5..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/celltype.lua +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/lua - -modem = arg[1] -numb = arg[2] -echo = 0 - -datalist = {} -celllist = {} - -datalist[1] = "320u" -celllist[1] = 2 -datalist[2] = "330u" -celllist[2] = 2 -datalist[3] = "e3276" -celllist[3] = 3 -datalist[4] = "e398" -celllist[4] = 3 -datalist[5] = "e389" -celllist[5] = 3 -datalist[6] = "e392" -celllist[6] = 3 -datalist[7] = "e397" -celllist[7] = 3 -datalist[8] = "e8278" -celllist[8] = 3 -datalist[9] = "mf820" -celllist[9] = 3 -datalist[10] = "mf821" -celllist[10] = 3 -datalist[11] = "k5005" -celllist[11] = 3 -datalist[12] = "k5007" -celllist[12] = 3 -datalist[13] = "l800" -celllist[13] = 3 -datalist[14] = "e398" -celllist[14] = 3 -datalist[15] = "mf880" -celllist[15] = 3 -datalist[16] = "e3272" -celllist[16] = 3 -datalist[17] = "e3372" -celllist[17] = 3 -datalist[18] = "lte" -celllist[18] = 3 -datalist[19] = "340u" -celllist[19] = 2 -datalist[20] = "mf91d" -celllist[20] = 3 -datalist[21] = "mf825a" -celllist[21] = 3 -datalist[22] = "mf826" -celllist[22] = 3 -datalist[23] = "313u" -celllist[23] = 2 -datalist[24] = "341u" -celllist[24] = 2 -datalist[25] = "em74" -celllist[25] = 2 -datalist[26] = "mc74" -celllist[26] = 2 -datalist[27] = "em75" -celllist[27] = 2 -datalist[28] = "ec2" -celllist[28] = 3 -datalist[29] = "em06" -celllist[29] = 2 -datalist[30] = "ep06" -celllist[30] = 2 -datalist[31] = "slm750" -celllist[31] = 3 -datalist[32] = "bg96" -celllist[32] = 3 -datalist[33] = "em12" -celllist[33] = 2 -datalist[34] = "em20" -celllist[34] = 2 -datalist[35] = "rm5" -celllist[35] = 4 -datalist[36] = "l850" -celllist[36] = 2 -datalist[37] = "l860" -celllist[37] = 2 -datalist[38] = "fm15" -celllist[38] = 4 -datalist[39] = "em18" -celllist[39] = 2 -datalist[40] = "4105" -celllist[40] = 2 -datalist[41] = "em919" -celllist[41] = 4 -datalist[42] = "em16" -celllist[42] = 2 -datalist[43] = "sim820" -celllist[43] = 4 -datalist[44] = "mc73" -celllist[44] = 2 -datalist[45] = "eg25" -celllist[45] = 2 -datalist[46] = "srm8" -celllist[46] = 4 -datalist[47] = "4087" -celllist[47] = 3 -datalist[48] = "rg5" -celllist[48] = 4 -datalist[49] = "eg12" -celllist[49] = 2 -datalist[50] = "eg18" -celllist[50] = 2 -datalist[51] = "megafon" -celllist[51] = 2 -datalist[52] = "ln9" -celllist[52] = 2 - -printf = function(s,...) - if echo == 0 then - io.write(s:format(...)) - else - ss = s:format(...) - os.execute("/usr/lib/rooter/logprint.sh " .. ss) - end -end - -found = 3 -index = 1 -line = datalist[index] -data = string.lower(modem) - -while line ~= nil do - s, e = string.find(data, line) - if s ~= nil then - found = celllist[index] - break - end - index = index + 1 - line = datalist[index] -end - -file = io.open("/tmp/celltype" .. numb, "w") -cell = string.format("%s%s%s%s", "CELL", "=\"", found, "\"") -file:write(cell.. "\n") -file:close() diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh deleted file mode 100644 index aa3fd3f..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/huaweihostless.sh +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "hostless " "$@" -} - -TMPFILE="/tmp/XXXXXX" - -handle_timeout(){ - local wget_pid="$1" - local count=0 - ps | grep -v grep | grep $wget_pid - res="$?" - while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do - sleep 1 - count=$((count+1)) - ps | grep -v grep | grep $wget_pid - res="$?" - done - - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill "$wget_pid" 2> /dev/null - ps | grep -v grep | grep $wget_pid - res="$?" - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill -9 $wget_pid 2> /dev/null - fi - fi -} - -make_status() { - echo "$IP" > /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$CSQ" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$MODEM" >> /tmp/status$CURRMODEM.file - echo "$COPS" >> /tmp/status$CURRMODEM.file - echo "$NETWORK" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$COPS_MCC" >> /tmp/status$CURRMODEM.file - echo "$COPS_MNC" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo "$MONSTAT" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$CONN" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "Hostless/Phone" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file -} - -get_signal() { - TIMEOUT=3 - wget http://$IP/api/monitoring/status --load-cookies cookie -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - local in_CurrentNetworkType="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" - if [ -z $in_CurrentNetworkType ]; then - NETWORK="-" - else - [ "$in_CurrentNetworkType" = "19" ] && NETWORK="LTE" # LTE - [ "$in_CurrentNetworkType" = "9" ] && NETWORK="HSPA+" # HSPA+ - [ "$in_CurrentNetworkType" = "7" ] && NETWORK="HSPA" # HSPA - [ "$in_CurrentNetworkType" = "6" ] && NETWORK="HSUPA" # HSUPA - [ "$in_CurrentNetworkType" = "5" ] && NETWORK="HSDPA" # HSDPA - [ "$in_CurrentNetworkType" = "4" ] && NETWORK="WCDMA" # WCDMA - [ "$in_CurrentNetworkType" = "3" ] && NETWORK="EDGE" # EDGE - [ "$in_CurrentNetworkType" = "2" ] && NETWORK="GPRS" # GPRS - [ "$in_CurrentNetworkType" = "1" ] && NETWORK="GSM" # GSM - fi - SIGNAL="" - local in_SignalStrength="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" - [ "$in_SignalStrength" != "" ] && SIGNAL="$in_SignalStrength" - - if [ "$SIGNAL" = "" ]; then - in_SignalStrength="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" - [ "$in_SignalStrength" != "" ] && SIGNAL="$((in_SignalStrength*20))" - fi - [ -z $SIGNAL ] && SIGNAL=0 - rm -f $TMPFILE -} - -CURRMODEM=$1 -PROTO=$2 -CONN="Modem #"$CURRMODEM - -MANUF=$(uci get modem.modem$CURRMODEM.manuf) -MODEL=$(uci get modem.modem$CURRMODEM.model) -MODEM=$MANUF" "$MODEL -IP=$(uci get modem.modem$CURRMODEM.ip) - -STARTIMEX=$(date +%s) -MONSTAT="Unknown" -rm -f /tmp/monstat$CURRMODEM - -sleep 5 -TIMEOUT=5 -wget -q http://$IP/html/home.html -O nul --save-cookies cookie --keep-session-cookies -sleep 5 -wget http://$IP/api/net/current-plmn -O $TMPFILE --load-cookies cookie > /dev/null 2>&1 & -handle_timeout "$!" - -wget http://$IP/api/device/information -O $TMPFILE --load-cookies cookie > /dev/null 2>&1 & -handle_timeout "$!" -in_mod="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -if [ "$in_mod" != "" ]; then - MODEM=$MANUF" "$in_mod -fi -IMEI="Unknown" -IMSI="Unknown" -ICCID="Unknown" -CNUM="*" -CNUMx="*" -in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -if [ "$in_im" != "" ]; then - IMEI=$in_im -fi -in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -if [ "$in_im" != "" ]; then - IMSI=$in_im -fi -in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -if [ "$in_im" != "" ]; then - ICCID=$in_im -fi -in_im="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -if [ "$in_im" != "" ]; then - CNUM=$in_im -fi - - -IDP=$(uci get modem.modem$CURRMODEM.idP) -IDV=$(uci get modem.modem$CURRMODEM.idV) - -echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM -echo "$IMEI" >> /tmp/msimdatax$CURRMODEM -echo "$IMSI" >> /tmp/msimdatax$CURRMODEM -echo "$ICCID" >> /tmp/msimdatax$CURRMODEM -echo "1" >> /tmp/msimdatax$CURRMODEM -mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM -echo "$CNUM" > /tmp/msimnumx$CURRMODEM -echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM -mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM - -sleep 20 -TIMEOUT=20 -wget http://$IP/api/net/current-plmn -O $TMPFILE --load-cookies cookie > /dev/null 2>&1 & -handle_timeout "$!" -COPS="" -in_provider="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -[ "$in_provider" != "" ] && COPS="$in_provider" - -if [ "$COPS" = "" ]; then - COPS="-" - in_provider="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" - [ "$in_provider" != "" ] && COPS="$in_provider)" -fi -COPS_MCC="-" -COPS_MNC="-" -in_mcc="`cat $TMPFILE | grep \"\" | cut -d \">\" -f 2 | cut -d \"<\" -f 1`" -if [ "$in_mcc" != "" ]; then - COPS_MCC=${in_mcc:0:3} - COPS_MNC=${in_mcc:3:3} -fi -COPS_MNC=" "$COPS_MNC -TIMEOUT=5 - -while [ 1 = 1 ]; do - get_signal - CSQ="$SIGNAL" - if [ -e /tmp/monstat$CURRMODEM ]; then - source /tmp/monstat$CURRMODEM - fi - if [ -z $MONSTAT ]; then - MONSTAT="Unknown" - fi - make_status - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - while [ $ELAPSE -lt 10 ]; do - sleep 2 - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - done - STARTIMEX=$CURRTIME -done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data deleted file mode 100644 index b4cdb19..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/mccmnc.data +++ /dev/null @@ -1,11 +0,0 @@ -50501;Telstra -50502;Optus -50503;Vodafone -50506;3 -302220;Telus -302610;Bell -302720;Rogers Communication -24004;SWEDEN -24005;Sweden 3G -24008;Telenor SE -51503;Smart \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh deleted file mode 100644 index 09ea6a6..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/modemsignal.sh +++ /dev/null @@ -1,287 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "modem signal" "$@" -} - -CURRMODEM=$1 -PROTO=$2 -CONN="Modem #"$CURRMODEM -STARTIME=$(date +%s) -STARTIMEX=$(date +%s) -SMSTIME=0 -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -NUMB=0 -MONSTAT="Unknown" -rm -f /tmp/monstat$CURRMODEM - -make_connect() { - { - echo "Changing Port" - echo "-" - echo "-" - echo "-" - echo "$MODEM" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo " " - echo " " - echo "-" - echo "-" - echo "-" - echo "$CONN" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - echo "-" - } > /tmp/statusx$CURRMODEM.file - mv -f /tmp/statusx$CURRMODEM.file /tmp/status$CURRMODEM.file -} - -make_signal() { - { - if [ -e $ROOTER/provchk.sh ]; then - $ROOTER/provchk.sh $COPS $CURRMODEM - source /tmp/cops$CURRMODEM.file - rm -f /tmp/cops$CURRMODEM.file - fi - echo "$COMMPORT" - echo "$CSQ" - echo "$CSQ_PER" - echo "$CSQ_RSSI" - echo "$MODEM" - echo "$COPS" - echo "$MODE" - echo "$LAC" - echo "$LAC_NUM" - echo "$CID" - echo "$CID_NUM" - echo "$COPS_MCC" - echo "$COPS_MNC" - echo "$RNC" - echo "$RNC_NUM" - echo "$DOWN" - echo "$UP" - echo "$ECIO" - echo "$RSCP" - echo "$ECIO1" - echo "$RSCP1" - echo "$MONSTAT" - echo "$CELL" - echo "$MODTYPE" - echo "$CONN" - echo "$CHANNEL" - echo "$CNUM" - echo "$CNAM" - echo "$LBAND" - echo "$TEMP" - echo "$PROTO" - echo "$PCI" - echo "$SINR" - echo "$LATITUDE" - echo "$LONGITUDE" - } > /tmp/statusx$CURRMODEM.file - mv -f /tmp/statusx$CURRMODEM.file /tmp/status$CURRMODEM.file - if [ -e $ROOTER/modem-led.sh ]; then - $ROOTER/modem-led.sh $CURRMODEM 4 $CSQ - fi -} - -get_basic() { - $ROOTER/signal/basedata.sh $CURRMODEM $COMMPORT - if [ -e /tmp/base$CURRMODEM.file ]; then - source /tmp/base$CURRMODEM.file - rm -f /tmp/base$CURRMODEM.file - fi - $ROOTER/signal/celldata.sh $CURRMODEM $COMMPORT - if [ -e /tmp/cell$CURRMODEM.file ]; then - source /tmp/cell$CURRMODEM.file - rm -f /tmp/cell$CURRMODEM.file - fi - lua $ROOTER/signal/celltype.lua "$MODEM" $CURRMODEM - if [ -e /tmp/celltype$CURRMODEM ]; then - source /tmp/celltype$CURRMODEM - rm -f /tmp/celltype$CURRMODEM - fi -} - -get_basic -while [ 1 = 1 ]; do - get_basic - if [ -e /tmp/port$CURRMODEM.file ]; then - source /tmp/port$CURRMODEM.file - rm -f /tmp/port$CURRMODEM.file - COMMPORT="/dev/ttyUSB"$PORT - uci set modem.modem$CURRMODEM.commport=$PORT - make_connect - get_basic - STARTIME=$(date +%s) - else - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIME - if [ $ELAPSE -ge 60 ]; then - STARTIME=$CURRTIME - $ROOTER/signal/celldata.sh $CURRMODEM $COMMPORT - if [ -e /tmp/cell$CURRMODEM.file ]; then - source /tmp/cell$CURRMODEM.file - rm -f /tmp/cell$CURRMODEM.file - fi - fi - if [ -e /tmp/port$CURRMODEM.file ]; then - source /tmp/port$CURRMODEM.file - rm -f /tmp/port$CURRMODEM.file - COMMPORT="/dev/ttyUSB"$PORT - uci set modem.modem$CURRMODEM.commport=$PORT - make_connect - get_basic - STARTIME=$(date +%s) - else - VENDOR=$(uci get modem.modem$CURRMODEM.idV) - PROD=$(uci get modem.modem$CURRMODEM.idP) -# This case statement should be kept in sync with: $ROOTER/luci/celltype.sh - case $VENDOR in - "1199"|"0f3d" ) - $ROOTER/common/sierradata.sh $CURRMODEM $COMMPORT - ;; - "19d2" ) - if [ $PROD = 1432 ]; then - $ROOTER/common/mdm9215data.sh $CURRMODEM $COMMPORT - else - $ROOTER/common/ztedata.sh $CURRMODEM $COMMPORT - fi - ;; - "12d1" ) - $ROOTER/common/huaweidata.sh $CURRMODEM $COMMPORT - ;; - "2c7c" ) - $ROOTER/common/quecteldata.sh $CURRMODEM $COMMPORT - ;; - "2cb7"|"1508" ) - $ROOTER/common/fibocomdata.sh $CURRMODEM $COMMPORT - ;; - "2dee" ) - $ROOTER/common/meigdata.sh $CURRMODEM $COMMPORT - ;; - "05c6" ) - case $PROD in - "f601" ) - $ROOTER/common/meigdata.sh $CURRMODEM $COMMPORT - ;; - "5042" ) - $ROOTER/common/mdm9215data.sh $CURRMODEM $COMMPORT - ;; - "9090"|"9003"|"9215" ) - $ROOTER/common/quecteldata.sh $CURRMODEM $COMMPORT - ;; - "90db" ) - $ROOTER/common/simcomdata.sh $CURRMODEM $COMMPORT - ;; - * ) - $ROOTER/common/otherdata.sh $CURRMODEM $COMMPORT - ;; - esac - ;; - "1bc7" ) - case $PROD in - "1900"|"1901"|"1910"|"1911" ) - $ROOTER/common/t77data.sh $CURRMODEM $COMMPORT - ;; - * ) - $ROOTER/common/telitdata.sh $CURRMODEM $COMMPORT - ;; - esac - ;; - "1410" ) - $ROOTER/common/novateldata.sh $CURRMODEM $COMMPORT - ;; - "413c" ) - case $PROD in - "81d7"|"81d8"|"81e0" ) - $ROOTER/common/t77data.sh $CURRMODEM $COMMPORT - ;; - * ) - $ROOTER/common/sierradata.sh $CURRMODEM $COMMPORT - ;; - esac - ;; - "0489" |"03f0" ) - $ROOTER/common/t77data.sh $CURRMODEM $COMMPORT - ;; - "1e0e" ) - $ROOTER/common/simcomdata.sh $CURRMODEM $COMMPORT - ;; - "8087" ) - if [ $PROD = "095a" ]; then - $ROOTER/common/fibocomdata.sh $CURRMODEM $COMMPORT - fi - ;; - "0408" ) - $ROOTER/common/quantadata.sh $CURRMODEM $COMMPORT - ;; - * ) - $ROOTER/common/otherdata.sh $CURRMODEM $COMMPORT - ;; - esac - CHANNEL="-" - PCI="-" - LBAND="-" - TEMP="-" - SINR="-" - LATITUDE="-" - LONGITUDE="-" - if [ -e /tmp/signal$CURRMODEM.file ]; then - source /tmp/signal$CURRMODEM.file - rm -f /tmp/signal$CURRMODEM.file - fi - if [ -e /tmp/phonenumber$CURRMODEM ]; then - source /tmp/phonenumber$CURRMODEM - rm -f /tmp/phonenumber$CURRMODEM - fi - if [ -e /tmp/gpsdata ]; then - source /tmp/gpsdata - fi - make_signal - uci set modem.modem$CURRMODEM.cmode="1" - uci commit modem - if [ -e /tmp/monstat$CURRMODEM ]; then - source /tmp/monstat$CURRMODEM - fi - if [ -z "$MONSTAT" ]; then - MONSTAT="Unknown" - fi - fi - fi - if [ -e /etc/netspeed ]; then - NETSPEED=60 - else - NETSPEED=10 - fi - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - while [ $ELAPSE -lt $NETSPEED ]; do - sleep 2 - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - done - STARTIMEX=$CURRTIME -done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh deleted file mode 100644 index 621d626..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/otherhostless.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "hostless " "$@" -} - -get_basic() { - # get basic data here - # - # how it is done with other modems - # - COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - $ROOTER/signal/basedata.sh $CURRMODEM $COMMPORT - source /tmp/base$CURRMODEM.file - rm -f /tmp/base$CURRMODEM.file - $ROOTER/signal/celldata.sh $CURRMODEM $COMMPORT - source /tmp/cell$CURRMODEM.file - rm -f /tmp/cell$CURRMODEM.file - lua $ROOTER/signal/celltype.lua "$MODEM" $CURRMODEM - source /tmp/celltype$CURRMODEM - rm -f /tmp/celltype$CURRMODEM -} - -make_signal() { - # get signal data here - # - # how it is done with other modems (Sierra) - # - COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) - MANUF=$(uci get modem.modem$CURRMODEM.manuf) - MODEL=$(uci get modem.modem$CURRMODEM.model) - MODEM=$MANUF" "$MODEL - $ROOTER/common/ubloxdata.sh $CURRMODEM $COMMPORT - source /tmp/signal$CURRMODEM.file - rm -f /tmp/signal$CURRMODEM.file - echo "$COMMPORT" > /tmp/statusx$CURRMODEM.file - echo "$CSQ" >> /tmp/statusx$CURRMODEM.file - echo "$CSQ_PER" >> /tmp/statusx$CURRMODEM.file - echo "$CSQ_RSSI" >> /tmp/statusx$CURRMODEM.file - echo "$MODEM" >> /tmp/statusx$CURRMODEM.file - echo "$COPS" >> /tmp/statusx$CURRMODEM.file - echo "$MODE" >> /tmp/statusx$CURRMODEM.file - echo "$LAC" >> /tmp/statusx$CURRMODEM.file - echo "$LAC_NUM" >> /tmp/statusx$CURRMODEM.file - echo "$CID" >> /tmp/statusx$CURRMODEM.file - echo "$CID_NUM" >> /tmp/statusx$CURRMODEM.file - echo "$COPS_MCC" >> /tmp/statusx$CURRMODEM.file - echo "$COPS_MNC" >> /tmp/statusx$CURRMODEM.file - echo "$RNC" >> /tmp/statusx$CURRMODEM.file - echo "$RNC_NUM" >> /tmp/statusx$CURRMODEM.file - echo "$DOWN" >> /tmp/statusx$CURRMODEM.file - echo "$UP" >> /tmp/statusx$CURRMODEM.file - echo "$ECIO" >> /tmp/statusx$CURRMODEM.file - echo "$RSCP" >> /tmp/statusx$CURRMODEM.file - echo "$ECIO1" >> /tmp/statusx$CURRMODEM.file - echo "$RSCP1" >> /tmp/statusx$CURRMODEM.file - echo "$MONSTAT" >> /tmp/statusx$CURRMODEM.file - echo "$CELL" >> /tmp/statusx$CURRMODEM.file - echo "$MODTYPE" >> /tmp/statusx$CURRMODEM.file - echo "$CONN" >> /tmp/statusx$CURRMODEM.file - echo "$CHANNEL" >> /tmp/statusx$CURRMODEM.file - echo "$CNUM" >> /tmp/statusx$CURRMODEM.file - echo "$CNAM" >> /tmp/statusx$CURRMODEM.file - echo "$LBAND" >> /tmp/statusx$CURRMODEM.file - echo "$TEMP" >> /tmp/statusx$CURRMODEM.file - echo "$PROTO" >> /tmp/statusx$CURRMODEM.file - echo "$PCI" >> /tmp/statusx$CURRMODEM.file - echo "-" >> /tmp/statusx$CURRMODEM.file - echo "-" >> /tmp/statusx$CURRMODEM.file - mv -f /tmp/statusx$CURRMODEM.file /tmp/status$CURRMODEM.file -} - -CURRMODEM=$1 -PROTO=$2 -CONN="Modem #"$CURRMODEM - -MANUF=$(uci get modem.modem$CURRMODEM.manuf) -MODEL=$(uci get modem.modem$CURRMODEM.model) -MODEM=$MANUF" "$MODEL -IP=$(uci get modem.modem$CURRMODEM.ip) -MONSTAT="Unknown" -rm -f /tmp/monstat$CURRMODEM - -idV=$(uci get modem.modem$CURRMODEM.idV) -idP=$(uci get modem.modem$CURRMODEM.idP) -if [ $idV = 1546 -a $idP = 1146 ]; then - get_basic -fi - - -STARTIMEX=$(date +%s) -MONSTAT="Unknown" -rm -f /tmp/monstat$CURRMODEM - -while [ 1 = 1 ]; do - if [ $idV = 1546 -a $idP = 1146 ]; then -# ublox - make_signal - else - echo "$IP" > /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$MODEM" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo "$MONSTAT" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$CONN" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "Hostless/Phone" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - fi - if [ -e /tmp/monstat$CURRMODEM ]; then - source /tmp/monstat$CURRMODEM - fi - if [ -z $MONSTAT ]; then - MONSTAT="Unknown" - fi - CURRTIME=$(date +%s) - - if [ -e /etc/netspeed ]; then - NETSPEED=60 - else - NETSPEED=10 - fi - - - - let ELAPSE=CURRTIME-STARTIMEX - while [ $ELAPSE -lt $NETSPEED ]; do - sleep 2 - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - done - STARTIMEX=$CURRTIME -done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh deleted file mode 100644 index 2b61da8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/status.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -CURRMODEM=$1 -MSG=$2 -MSG1=$3 -COMMPORT="/dev/ttyUSB"$(uci -q get modem.modem$CURRMODEM.commport) -if [ -z $MSG1 ]; then - MSG1="-" - COMMPORT="-" -fi - -echo "$COMMPORT" > /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "$MSG" >> /tmp/status$CURRMODEM.file -echo "$MSG1" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo " " >> /tmp/status$CURRMODEM.file -echo " " >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "Modem $CURRMODEM" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file -echo "-" >> /tmp/status$CURRMODEM.file diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh deleted file mode 100644 index cedd8e9..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/signal/ztehostless.sh +++ /dev/null @@ -1,215 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - logger -t "hostless " "$@" -} - -TMPFILE="/tmp/XXXXXX" -TMPFILE1="/tmp/XXXXXX1" - -make_status() { - echo "$IP" > /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$CSQ" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$MODEM" >> /tmp/status$CURRMODEM.file - echo "$PROV" >> /tmp/status$CURRMODEM.file - echo "$NETWORK" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo " " >> /tmp/status$CURRMODEM.file - echo "$MONSTAT" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "$CONN" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "Hostless/Phone" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file - echo "-" >> /tmp/status$CURRMODEM.file -} - -handle_timeout(){ - local wget_pid="$1" - local count=0 - ps | grep -v grep | grep $wget_pid - res="$?" - while [ "$res" = 0 -a $count -lt "$((TIMEOUT))" ]; do - sleep 1 - count=$((count+1)) - ps | grep -v grep | grep $wget_pid - res="$?" - done - - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill "$wget_pid" 2> /dev/null - ps | grep -v grep | grep $wget_pid - res="$?" - if [ "$res" = 0 ]; then - log "Killing process on timeout" - kill -9 $wget_pid 2> /dev/null - fi - fi -} - -get_zte_model() { - uci set modem.modem$CURRMODEM.ztemodel=UNKNOWN - uci commit modem - SERIAL=$(uci get modem.modem$CURRMODEM.serial) - if [ $PROD = 1405 ]; then - if [ "`echo $SERIAL | grep P680A1ZTED`" != "" ]; then - uci set modem.modem$CURRMODEM.ztemodel=MF669 - uci set modem.modem$CURRMODEM.model=MF669/MF70 - uci commit modem - else - uci set modem.modem$CURRMODEM.ztemodel=V5 - uci set modem.modem$CURRMODEM.model=MF823/MF825/MF93D - uci commit modem - fi - fi - if [ $PROD = 0349 ]; then - uci set modem.modem$CURRMODEM.ztemodel=MF821D - uci set modem.modem$CURRMODEM.model=MF821D - uci commit modem - fi - if [ $PROD = 0166 ]; then - if [ "`echo $MODEL | grep MF91`" != "" ]; then - uci set modem.modem$CURRMODEM.ztemodel=MF91D - uci set modem.modem$CURRMODEM.model=MF91D - uci commit modem - else - if [ "`echo $MODEL | grep MF91`" != "" ]; then - uci set modem.modem$CURRMODEM.ztemodel=MF91 - uci set modem.modem$CURRMODEM.model=MF91 - uci commit modem - fi - fi - fi - if [ $PROD = 1408 ]; then - if [ "`echo $SERIAL | grep P680A1ZTED`" != "" ]; then - uci set modem.modem$CURRMODEM.ztemodel=V5 - uci set modem.modem$CURRMODEM.model=MF93D - uci commit modem - fi - fi -} - -get_basic(){ - ZTEMOD=$(uci get modem.modem$CURRMODEM.ztemodel) - TIMEOUT=3 - case $ZTEMOD in - "MF669" ) - wget http://$IP/logo_data.asp -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - LUCKNUM="`cat $TMPFILE | grep lucknum | cut -d \' -f 2`" - ;; - "V5" ) - wget "http://$IP/goform/goform_get_cmd_process?isTest=false&cmd=network_type%2Cwan_ipaddr%2Cppp_status%2Cprefer_dns_auto%2Cstandby_dns_auto%2Csignalbar&multi_data=1&_=1376406501348" -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - ;; - "MF821D"|"MF91D"|"MF91" ) - wget http://$IP/goform/status_update -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - ;; - esac - PROV="`cat $TMPFILE | grep network_provider | cut -d \' -f 2`" - [ -z $PROV ] && PROV="-" - rm -f $TMPFILE -} - -get_signal(){ - TIMEOUT=3 - case $ZTEMOD in - "MF669" ) - wget http://$IP/logo_data.asp -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - SIGNAL="`cat $TMPFILE | grep signalbar | cut -d \' -f 2`" - NETWORK="`cat $TMPFILE | grep network_type | cut -d \' -f 2`" - ;; - "V5" ) - wget "http://$IP/goform/goform_get_cmd_process?isTest=false&cmd=signalbar,wan_csq,network_type,network_provider,ppp_status,modem_main_state,rmcc,rmnc,,domain_stat,cell_id,rssi,rscp,lte_rssi,lte_rsrq,lte_rsrp,lte_snr,ecio,sms_received_flag,sts_received_flag,simcard_roam&multi_data=1&sms_received_flag_flag=0&sts_received_flag_flag=0" -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - SIGNAL="`cat $TMPFILE | grep signalbar'\"\:\"[^\"]*' -o | cut -d'"' -f 3`" - NETWORK="`cat $TMPFILE | grep network_type'\"\:\"[^\"]*' -o | cut -d'"' -f 3`" - ;; - "MF821D"|"MF91D"|"MF91" ) - wget http://$IP/goform/status_update -O $TMPFILE > /dev/null 2>&1 & - handle_timeout "$!" - SIGNAL="`cat $TMPFILE | cut -d \; -f 1-1`" - net="`cat $TMPFILE | cut -d \; -f 4-4`" - if [ -z $net ]; then - NETWORK="-" - else - [ "$net" = "0" ] && NETWORK="No Service" - [ "$net" = "1" ] && NETWORK="LTE" - [ "$net" = "2" ] && NETWORK="EVDO" - [ "$net" = "3" ] && NETWORK="CDMA" - [ "$net" = "4" ] && NETWORK="WCDMA" - [ "$net" = "5" ] && NETWORK="GSM" - [ "$net" = "6" ] && NETWORK="HSDPA" - [ "$net" = "7" ] && NETWORK="HUSPA" - [ "$net" = "8" ] && NETWORK="HSPA+" - [ "$net" = "10" ] && NETWORK="EDGE" - [ "$net" = "11" ] && NETWORK="GPRS" - fi - ;; - esac - [ -z $SIGNAL ] && SIGNAL=0 - [ -z $NETWORK ] && NETWORK="-" - rm -f $TMPFILE -} - -CURRMODEM=$1 -PROTO=$2 -CONN="Modem #"$CURRMODEM - -PROD=$(uci get modem.modem$CURRMODEM.idP) -get_zte_model -MANUF=$(uci get modem.modem$CURRMODEM.manuf) -MODEL=$(uci get modem.modem$CURRMODEM.model) -MODEM=$MANUF" "$MODEL -IP=$(uci get modem.modem$CURRMODEM.ip) - -get_basic - -STARTIMEX=$(date +%s) -MONSTAT="Unknown" -rm -f /tmp/monstat$CURRMODEM - -while [ 1 = 1 ]; do - get_signal - CSQ="$SIGNAL Bars" - if [ -e /tmp/monstat$CURRMODEM ]; then - source /tmp/monstat$CURRMODEM - fi - if [ -z $MONSTAT ]; then - MONSTAT="Unknown" - fi - make_status - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - while [ $ELAPSE -lt 10 ]; do - sleep 2 - CURRTIME=$(date +%s) - let ELAPSE=CURRTIME-STARTIMEX - done - STARTIMEX=$CURRTIME -done diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh deleted file mode 100644 index 4148ad8..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/simlock.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter - -log() { - modlog "SimLock $CURRMODEM" "$@" -} - -CURRMODEM=$1 -CPORT=$(uci get modem.modem$CURRMODEM.commport) - -ATCMDD="at+cpin?" -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -ERR=$(echo "$OX" | grep "ERROR") -if [ ! -z "$ERR" ]; then # No SIM - log "No SIM" - echo "2" > /tmp/simpin$CURRMODEM - exit 0 -fi -RDY=$(echo "$OX" | grep "READY") -if [ -z "$RDY" ]; then # SIM Locked - spin=$(uci -q get custom.simpin.pin) # SIM Pin - if [ -z "$spin" ]; then - spin=$(uci -q get modem.modeminfo$CURRMODEM.pincode) # Profile Pin - if [ -z "$spin" ]; then - spin=$(uci -q get profile.simpin.pin) # Default profile Pin - if [ -z "$spin" ]; then - echo "0" > /tmp/simpin$CURRMODEM # Locked/No Pin - log "Locked/No Pin" - exit 0 - fi - fi - fi - export PINCODE="$spin" # Use Pin to unlock - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "setpin.gcom" "$CURRMODEM") - sleep 5 - ATCMDD="at+cpin?" - OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") - RDY=$(echo "$OX" | grep "READY") - if [ -z "$RDY" ]; then # sim locked - echo "1" > /tmp/simpin$CURRMODEM # Incorrect Pin - log "Incorrect Pin" - exit 0 - fi - log "Correct Pin" - $ROOTER/common/gettype.sh $CURRMODEM -else - log "Not Locked" - sblk=$(uci -q get custom.simpin.block) - if [ "$sblk" = "1" ]; then - echo "4" > /tmp/simpin$CURRMODEM - log "Unlocked not allowed" - exit 0 - fi -fi -rm -f /tmp/simpin$CURRMODEM # not locked - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh deleted file mode 100644 index af4651d..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/simlockc.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -log() { - logger -t "SIM Lock" "$@" -} diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh deleted file mode 100644 index 0475e85..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/sms/check_sms.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -ROOTER=/usr/lib/rooter -ROOTER_LINK="/tmp/links" - -CURRMODEM=$1 - -if [ -e /etc/nosms ]; then - uci set modem.modem$CURRMODEM.sms=0 - uci commit modem - exit 0 -fi - -CPORT=$(uci get modem.modem$CURRMODEM.commport) -sleep 10 -OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "smschk.gcom" "$CURRMODEM") - -ERROR="ERROR" -if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` -then - uci set modem.modem$CURRMODEM.sms=0 - uci commit modem -else - uci set modem.modem$CURRMODEM.sms=1 - uci commit modem - if [ -e /usr/lib/sms/processsms ]; then - if [ ! -e $ROOTER_LINK/processsms$CURRMODEM ]; then - ln -s /usr/lib/sms/processsms $ROOTER_LINK/processsms$CURRMODEM - $ROOTER_LINK/processsms$CURRMODEM $CURRMODEM & - fi - fi -fi diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh deleted file mode 100644 index a0f1800..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/timezone.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -sleep 10 -rm -f /tmp/timez -wget --no-check-certificate -O /tmp/timez http://ip-api.com/json > /dev/null 2>&1 -OX=$(cat /tmp/timez) - -TZ=$(echo $OX" " | tr -d '"' | grep -o 'timezone:[^;]*' | tr ":" ",") -ZONEN=$(echo "$TZ" | cut -d, -f2) - -/usr/lib/rooter/tzone.lua "$ZONEN" -source /tmp/tzone - -uci set system.@system[-1].timezone="$ZNAME" -uci set system.@system[-1].zonename="$ZONEN" -uci commit system -/etc/init.d/system restart - - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua b/rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua deleted file mode 100644 index 279ad3c..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/tzone.lua +++ /dev/null @@ -1,478 +0,0 @@ -#!/usr/bin/lua - -TZ = { - { 'Africa/Abidjan', 'GMT0' }, - { 'Africa/Accra', 'GMT0' }, - { 'Africa/Addis Ababa', 'EAT-3' }, - { 'Africa/Algiers', 'CET-1' }, - { 'Africa/Asmara', 'EAT-3' }, - { 'Africa/Bamako', 'GMT0' }, - { 'Africa/Bangui', 'WAT-1' }, - { 'Africa/Banjul', 'GMT0' }, - { 'Africa/Bissau', 'GMT0' }, - { 'Africa/Blantyre', 'CAT-2' }, - { 'Africa/Brazzaville', 'WAT-1' }, - { 'Africa/Bujumbura', 'CAT-2' }, - { 'Africa/Cairo', 'EET-2' }, - { 'Africa/Casablanca', '<+01>-1' }, - { 'Africa/Ceuta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Africa/Conakry', 'GMT0' }, - { 'Africa/Dakar', 'GMT0' }, - { 'Africa/Dar es Salaam', 'EAT-3' }, - { 'Africa/Djibouti', 'EAT-3' }, - { 'Africa/Douala', 'WAT-1' }, - { 'Africa/El Aaiun', '<+01>-1' }, - { 'Africa/Freetown', 'GMT0' }, - { 'Africa/Gaborone', 'CAT-2' }, - { 'Africa/Harare', 'CAT-2' }, - { 'Africa/Johannesburg', 'SAST-2' }, - { 'Africa/Juba', 'EAT-3' }, - { 'Africa/Kampala', 'EAT-3' }, - { 'Africa/Khartoum', 'CAT-2' }, - { 'Africa/Kigali', 'CAT-2' }, - { 'Africa/Kinshasa', 'WAT-1' }, - { 'Africa/Lagos', 'WAT-1' }, - { 'Africa/Libreville', 'WAT-1' }, - { 'Africa/Lome', 'GMT0' }, - { 'Africa/Luanda', 'WAT-1' }, - { 'Africa/Lubumbashi', 'CAT-2' }, - { 'Africa/Lusaka', 'CAT-2' }, - { 'Africa/Malabo', 'WAT-1' }, - { 'Africa/Maputo', 'CAT-2' }, - { 'Africa/Maseru', 'SAST-2' }, - { 'Africa/Mbabane', 'SAST-2' }, - { 'Africa/Mogadishu', 'EAT-3' }, - { 'Africa/Monrovia', 'GMT0' }, - { 'Africa/Nairobi', 'EAT-3' }, - { 'Africa/Ndjamena', 'WAT-1' }, - { 'Africa/Niamey', 'WAT-1' }, - { 'Africa/Nouakchott', 'GMT0' }, - { 'Africa/Ouagadougou', 'GMT0' }, - { 'Africa/Porto-Novo', 'WAT-1' }, - { 'Africa/Sao Tome', 'GMT0' }, - { 'Africa/Tripoli', 'EET-2' }, - { 'Africa/Tunis', 'CET-1' }, - { 'Africa/Windhoek', 'CAT-2' }, - { 'America/Adak', 'HST10HDT,M3.2.0,M11.1.0' }, - { 'America/Anchorage', 'AKST9AKDT,M3.2.0,M11.1.0' }, - { 'America/Anguilla', 'AST4' }, - { 'America/Antigua', 'AST4' }, - { 'America/Araguaina', '<-03>3' }, - { 'America/Argentina/Buenos Aires', '<-03>3' }, - { 'America/Argentina/Catamarca', '<-03>3' }, - { 'America/Argentina/Cordoba', '<-03>3' }, - { 'America/Argentina/Jujuy', '<-03>3' }, - { 'America/Argentina/La Rioja', '<-03>3' }, - { 'America/Argentina/Mendoza', '<-03>3' }, - { 'America/Argentina/Rio Gallegos', '<-03>3' }, - { 'America/Argentina/Salta', '<-03>3' }, - { 'America/Argentina/San Juan', '<-03>3' }, - { 'America/Argentina/San Luis', '<-03>3' }, - { 'America/Argentina/Tucuman', '<-03>3' }, - { 'America/Argentina/Ushuaia', '<-03>3' }, - { 'America/Aruba', 'AST4' }, - { 'America/Asuncion', '<-04>4<-03>,M10.1.0/0,M3.4.0/0' }, - { 'America/Atikokan', 'EST5' }, - { 'America/Bahia', '<-03>3' }, - { 'America/Bahia Banderas', 'CST6CDT,M4.1.0,M10.5.0' }, - { 'America/Barbados', 'AST4' }, - { 'America/Belem', '<-03>3' }, - { 'America/Belize', 'CST6' }, - { 'America/Blanc-Sablon', 'AST4' }, - { 'America/Boa Vista', '<-04>4' }, - { 'America/Bogota', '<-05>5' }, - { 'America/Boise', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'America/Cambridge Bay', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'America/Campo Grande', '<-04>4' }, - { 'America/Cancun', 'EST5' }, - { 'America/Caracas', '<-04>4' }, - { 'America/Cayenne', '<-03>3' }, - { 'America/Cayman', 'EST5' }, - { 'America/Chicago', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Chihuahua', 'MST7MDT,M4.1.0,M10.5.0' }, - { 'America/Costa Rica', 'CST6' }, - { 'America/Creston', 'MST7' }, - { 'America/Cuiaba', '<-04>4' }, - { 'America/Curacao', 'AST4' }, - { 'America/Danmarkshavn', 'GMT0' }, - { 'America/Dawson', 'MST7' }, - { 'America/Dawson Creek', 'MST7' }, - { 'America/Denver', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'America/Detroit', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Dominica', 'AST4' }, - { 'America/Edmonton', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'America/Eirunepe', '<-05>5' }, - { 'America/El Salvador', 'CST6' }, - { 'America/Fort Nelson', 'MST7' }, - { 'America/Fortaleza', '<-03>3' }, - { 'America/Glace Bay', 'AST4ADT,M3.2.0,M11.1.0' }, - { 'America/Goose Bay', 'AST4ADT,M3.2.0,M11.1.0' }, - { 'America/Grand Turk', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Grenada', 'AST4' }, - { 'America/Guadeloupe', 'AST4' }, - { 'America/Guatemala', 'CST6' }, - { 'America/Guayaquil', '<-05>5' }, - { 'America/Guyana', '<-04>4' }, - { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' }, - { 'America/Havana', 'CST5CDT,M3.2.0/0,M11.1.0/1' }, - { 'America/Hermosillo', 'MST7' }, - { 'America/Indiana/Indianapolis', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Knox', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Marengo', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Petersburg', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Tell City', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Vevay', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Vincennes', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Indiana/Winamac', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Inuvik', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'America/Iqaluit', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Jamaica', 'EST5' }, - { 'America/Juneau', 'AKST9AKDT,M3.2.0,M11.1.0' }, - { 'America/Kentucky/Louisville', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Kentucky/Monticello', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Kralendijk', 'AST4' }, - { 'America/La Paz', '<-04>4' }, - { 'America/Lima', '<-05>5' }, - { 'America/Los Angeles', 'PST8PDT,M3.2.0,M11.1.0' }, - { 'America/Lower Princes', 'AST4' }, - { 'America/Maceio', '<-03>3' }, - { 'America/Managua', 'CST6' }, - { 'America/Manaus', '<-04>4' }, - { 'America/Marigot', 'AST4' }, - { 'America/Martinique', 'AST4' }, - { 'America/Matamoros', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Mazatlan', 'MST7MDT,M4.1.0,M10.5.0' }, - { 'America/Menominee', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Merida', 'CST6CDT,M4.1.0,M10.5.0' }, - { 'America/Metlakatla', 'AKST9AKDT,M3.2.0,M11.1.0' }, - { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' }, - { 'America/Miquelon', '<-03>3<-02>,M3.2.0,M11.1.0' }, - { 'America/Moncton', 'AST4ADT,M3.2.0,M11.1.0' }, - { 'America/Monterrey', 'CST6CDT,M4.1.0,M10.5.0' }, - { 'America/Montevideo', '<-03>3' }, - { 'America/Montserrat', 'AST4' }, - { 'America/Nassau', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/New York', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Nipigon', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Nome', 'AKST9AKDT,M3.2.0,M11.1.0' }, - { 'America/Noronha', '<-02>2' }, - { 'America/North Dakota/Beulah', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/North Dakota/Center', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/North Dakota/New Salem', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Nuuk', '<-03>3<-02>,M3.5.0/-2,M10.5.0/-1' }, - { 'America/Ojinaga', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'America/Panama', 'EST5' }, - { 'America/Pangnirtung', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Paramaribo', '<-03>3' }, - { 'America/Phoenix', 'MST7' }, - { 'America/Port of Spain', 'AST4' }, - { 'America/Port-au-Prince', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Porto Velho', '<-04>4' }, - { 'America/Puerto Rico', 'AST4' }, - { 'America/Punta Arenas', '<-03>3' }, - { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Rankin Inlet', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Recife', '<-03>3' }, - { 'America/Regina', 'CST6' }, - { 'America/Resolute', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Rio Branco', '<-05>5' }, - { 'America/Santarem', '<-03>3' }, - { 'America/Santiago', '<-04>4<-03>,M9.1.6/24,M4.1.6/24' }, - { 'America/Santo Domingo', 'AST4' }, - { 'America/Sao Paulo', '<-03>3' }, - { 'America/Scoresbysund', '<-01>1<+00>,M3.5.0/0,M10.5.0/1' }, - { 'America/Sitka', 'AKST9AKDT,M3.2.0,M11.1.0' }, - { 'America/St Barthelemy', 'AST4' }, - { 'America/St Johns', 'NST3:30NDT,M3.2.0,M11.1.0' }, - { 'America/St Kitts', 'AST4' }, - { 'America/St Lucia', 'AST4' }, - { 'America/St Thomas', 'AST4' }, - { 'America/St Vincent', 'AST4' }, - { 'America/Swift Current', 'CST6' }, - { 'America/Tegucigalpa', 'CST6' }, - { 'America/Thule', 'AST4ADT,M3.2.0,M11.1.0' }, - { 'America/Thunder Bay', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Tijuana', 'PST8PDT,M3.2.0,M11.1.0' }, - { 'America/Toronto', 'EST5EDT,M3.2.0,M11.1.0' }, - { 'America/Tortola', 'AST4' }, - { 'America/Vancouver', 'PST8PDT,M3.2.0,M11.1.0' }, - { 'America/Whitehorse', 'MST7' }, - { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, - { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, - { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'Antarctica/Casey', '<+08>-8' }, - { 'Antarctica/Davis', '<+07>-7' }, - { 'Antarctica/DumontDUrville', '<+10>-10' }, - { 'Antarctica/Macquarie', '<+11>-11' }, - { 'Antarctica/Mawson', '<+05>-5' }, - { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, - { 'Antarctica/Palmer', '<-03>3' }, - { 'Antarctica/Rothera', '<-03>3' }, - { 'Antarctica/Syowa', '<+03>-3' }, - { 'Antarctica/Troll', '<+00>0<+02>-2,M3.5.0/1,M10.5.0/3' }, - { 'Antarctica/Vostok', '<+06>-6' }, - { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Asia/Aden', '<+03>-3' }, - { 'Asia/Almaty', '<+06>-6' }, - { 'Asia/Amman', 'EET-2EEST,M3.5.4/24,M10.5.5/1' }, - { 'Asia/Anadyr', '<+12>-12' }, - { 'Asia/Aqtau', '<+05>-5' }, - { 'Asia/Aqtobe', '<+05>-5' }, - { 'Asia/Ashgabat', '<+05>-5' }, - { 'Asia/Atyrau', '<+05>-5' }, - { 'Asia/Baghdad', '<+03>-3' }, - { 'Asia/Bahrain', '<+03>-3' }, - { 'Asia/Baku', '<+04>-4' }, - { 'Asia/Bangkok', '<+07>-7' }, - { 'Asia/Barnaul', '<+07>-7' }, - { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' }, - { 'Asia/Bishkek', '<+06>-6' }, - { 'Asia/Brunei', '<+08>-8' }, - { 'Asia/Chita', '<+09>-9' }, - { 'Asia/Choibalsan', '<+08>-8' }, - { 'Asia/Colombo', '<+0530>-5:30' }, - { 'Asia/Damascus', 'EET-2EEST,M3.5.5/0,M10.5.5/0' }, - { 'Asia/Dhaka', '<+06>-6' }, - { 'Asia/Dili', '<+09>-9' }, - { 'Asia/Dubai', '<+04>-4' }, - { 'Asia/Dushanbe', '<+05>-5' }, - { 'Asia/Famagusta', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Asia/Gaza', 'EET-2EEST,M3.5.5/0,M10.5.6/1' }, - { 'Asia/Hebron', 'EET-2EEST,M3.5.5/0,M10.5.6/1' }, - { 'Asia/Ho Chi Minh', '<+07>-7' }, - { 'Asia/Hong Kong', 'HKT-8' }, - { 'Asia/Hovd', '<+07>-7' }, - { 'Asia/Irkutsk', '<+08>-8' }, - { 'Asia/Jakarta', 'WIB-7' }, - { 'Asia/Jayapura', 'WIT-9' }, - { 'Asia/Jerusalem', 'IST-2IDT,M3.4.4/26,M10.5.0' }, - { 'Asia/Kabul', '<+0430>-4:30' }, - { 'Asia/Kamchatka', '<+12>-12' }, - { 'Asia/Karachi', 'PKT-5' }, - { 'Asia/Kathmandu', '<+0545>-5:45' }, - { 'Asia/Khandyga', '<+09>-9' }, - { 'Asia/Kolkata', 'IST-5:30' }, - { 'Asia/Krasnoyarsk', '<+07>-7' }, - { 'Asia/Kuala Lumpur', '<+08>-8' }, - { 'Asia/Kuching', '<+08>-8' }, - { 'Asia/Kuwait', '<+03>-3' }, - { 'Asia/Macau', 'CST-8' }, - { 'Asia/Magadan', '<+11>-11' }, - { 'Asia/Makassar', 'WITA-8' }, - { 'Asia/Manila', 'PST-8' }, - { 'Asia/Muscat', '<+04>-4' }, - { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Asia/Novokuznetsk', '<+07>-7' }, - { 'Asia/Novosibirsk', '<+07>-7' }, - { 'Asia/Omsk', '<+06>-6' }, - { 'Asia/Oral', '<+05>-5' }, - { 'Asia/Phnom Penh', '<+07>-7' }, - { 'Asia/Pontianak', 'WIB-7' }, - { 'Asia/Pyongyang', 'KST-9' }, - { 'Asia/Qatar', '<+03>-3' }, - { 'Asia/Qostanay', '<+06>-6' }, - { 'Asia/Qyzylorda', '<+05>-5' }, - { 'Asia/Riyadh', '<+03>-3' }, - { 'Asia/Sakhalin', '<+11>-11' }, - { 'Asia/Samarkand', '<+05>-5' }, - { 'Asia/Seoul', 'KST-9' }, - { 'Asia/Shanghai', 'CST-8' }, - { 'Asia/Singapore', '<+08>-8' }, - { 'Asia/Srednekolymsk', '<+11>-11' }, - { 'Asia/Taipei', 'CST-8' }, - { 'Asia/Tashkent', '<+05>-5' }, - { 'Asia/Tbilisi', '<+04>-4' }, - { 'Asia/Tehran', '<+0330>-3:30<+0430>,J79/24,J263/24' }, - { 'Asia/Thimphu', '<+06>-6' }, - { 'Asia/Tokyo', 'JST-9' }, - { 'Asia/Tomsk', '<+07>-7' }, - { 'Asia/Ulaanbaatar', '<+08>-8' }, - { 'Asia/Urumqi', '<+06>-6' }, - { 'Asia/Ust-Nera', '<+10>-10' }, - { 'Asia/Vientiane', '<+07>-7' }, - { 'Asia/Vladivostok', '<+10>-10' }, - { 'Asia/Yakutsk', '<+09>-9' }, - { 'Asia/Yangon', '<+0630>-6:30' }, - { 'Asia/Yekaterinburg', '<+05>-5' }, - { 'Asia/Yerevan', '<+04>-4' }, - { 'Atlantic/Azores', '<-01>1<+00>,M3.5.0/0,M10.5.0/1' }, - { 'Atlantic/Bermuda', 'AST4ADT,M3.2.0,M11.1.0' }, - { 'Atlantic/Canary', 'WET0WEST,M3.5.0/1,M10.5.0' }, - { 'Atlantic/Cape Verde', '<-01>1' }, - { 'Atlantic/Faroe', 'WET0WEST,M3.5.0/1,M10.5.0' }, - { 'Atlantic/Madeira', 'WET0WEST,M3.5.0/1,M10.5.0' }, - { 'Atlantic/Reykjavik', 'GMT0' }, - { 'Atlantic/South Georgia', '<-02>2' }, - { 'Atlantic/St Helena', 'GMT0' }, - { 'Atlantic/Stanley', '<-03>3' }, - { 'Australia/Adelaide', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' }, - { 'Australia/Brisbane', 'AEST-10' }, - { 'Australia/Broken Hill', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' }, - { 'Australia/Currie', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, - { 'Australia/Darwin', 'ACST-9:30' }, - { 'Australia/Eucla', '<+0845>-8:45' }, - { 'Australia/Hobart', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, - { 'Australia/Lindeman', 'AEST-10' }, - { 'Australia/Lord Howe', '<+1030>-10:30<+11>-11,M10.1.0,M4.1.0' }, - { 'Australia/Melbourne', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, - { 'Australia/Perth', 'AWST-8' }, - { 'Australia/Sydney', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, - { 'Etc/GMT', 'GMT0' }, - { 'Etc/GMT+1', '<-01>1' }, - { 'Etc/GMT+10', '<-10>10' }, - { 'Etc/GMT+11', '<-11>11' }, - { 'Etc/GMT+12', '<-12>12' }, - { 'Etc/GMT+2', '<-02>2' }, - { 'Etc/GMT+3', '<-03>3' }, - { 'Etc/GMT+4', '<-04>4' }, - { 'Etc/GMT+5', '<-05>5' }, - { 'Etc/GMT+6', '<-06>6' }, - { 'Etc/GMT+7', '<-07>7' }, - { 'Etc/GMT+8', '<-08>8' }, - { 'Etc/GMT+9', '<-09>9' }, - { 'Etc/GMT-1', '<+01>-1' }, - { 'Etc/GMT-10', '<+10>-10' }, - { 'Etc/GMT-11', '<+11>-11' }, - { 'Etc/GMT-12', '<+12>-12' }, - { 'Etc/GMT-13', '<+13>-13' }, - { 'Etc/GMT-14', '<+14>-14' }, - { 'Etc/GMT-2', '<+02>-2' }, - { 'Etc/GMT-3', '<+03>-3' }, - { 'Etc/GMT-4', '<+04>-4' }, - { 'Etc/GMT-5', '<+05>-5' }, - { 'Etc/GMT-6', '<+06>-6' }, - { 'Etc/GMT-7', '<+07>-7' }, - { 'Etc/GMT-8', '<+08>-8' }, - { 'Etc/GMT-9', '<+09>-9' }, - { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Astrakhan', '<+04>-4' }, - { 'Europe/Athens', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Belgrade', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Berlin', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Bratislava', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Brussels', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Bucharest', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Budapest', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Busingen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Chisinau', 'EET-2EEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Dublin', 'IST-1GMT0,M10.5.0,M3.5.0/1' }, - { 'Europe/Gibraltar', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Guernsey', 'GMT0BST,M3.5.0/1,M10.5.0' }, - { 'Europe/Helsinki', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Isle of Man', 'GMT0BST,M3.5.0/1,M10.5.0' }, - { 'Europe/Istanbul', '<+03>-3' }, - { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' }, - { 'Europe/Kaliningrad', 'EET-2' }, - { 'Europe/Kiev', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Kirov', '<+03>-3' }, - { 'Europe/Lisbon', 'WET0WEST,M3.5.0/1,M10.5.0' }, - { 'Europe/Ljubljana', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/London', 'GMT0BST,M3.5.0/1,M10.5.0' }, - { 'Europe/Luxembourg', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Madrid', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Malta', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Mariehamn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Minsk', '<+03>-3' }, - { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Moscow', 'MSK-3' }, - { 'Europe/Oslo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Paris', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Podgorica', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Prague', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Riga', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Rome', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Samara', '<+04>-4' }, - { 'Europe/San Marino', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Sarajevo', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Saratov', '<+04>-4' }, - { 'Europe/Simferopol', 'MSK-3' }, - { 'Europe/Skopje', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Sofia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Stockholm', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Tallinn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Tirane', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Ulyanovsk', '<+04>-4' }, - { 'Europe/Uzhgorod', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Vaduz', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Vatican', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Vienna', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Vilnius', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Volgograd', '<+04>-4' }, - { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Europe/Zaporozhye', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Europe/Zurich', 'CET-1CEST,M3.5.0,M10.5.0/3' }, - { 'Indian/Antananarivo', 'EAT-3' }, - { 'Indian/Chagos', '<+06>-6' }, - { 'Indian/Christmas', '<+07>-7' }, - { 'Indian/Cocos', '<+0630>-6:30' }, - { 'Indian/Comoro', 'EAT-3' }, - { 'Indian/Kerguelen', '<+05>-5' }, - { 'Indian/Mahe', '<+04>-4' }, - { 'Indian/Maldives', '<+05>-5' }, - { 'Indian/Mauritius', '<+04>-4' }, - { 'Indian/Mayotte', 'EAT-3' }, - { 'Indian/Reunion', '<+04>-4' }, - { 'Pacific/Apia', '<+13>-13<+14>,M9.5.0/3,M4.1.0/4' }, - { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, - { 'Pacific/Bougainville', '<+11>-11' }, - { 'Pacific/Chatham', '<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45' }, - { 'Pacific/Chuuk', '<+10>-10' }, - { 'Pacific/Easter', '<-06>6<-05>,M9.1.6/22,M4.1.6/22' }, - { 'Pacific/Efate', '<+11>-11' }, - { 'Pacific/Enderbury', '<+13>-13' }, - { 'Pacific/Fakaofo', '<+13>-13' }, - { 'Pacific/Fiji', '<+12>-12<+13>,M11.2.0,M1.2.3/99' }, - { 'Pacific/Funafuti', '<+12>-12' }, - { 'Pacific/Galapagos', '<-06>6' }, - { 'Pacific/Gambier', '<-09>9' }, - { 'Pacific/Guadalcanal', '<+11>-11' }, - { 'Pacific/Guam', 'ChST-10' }, - { 'Pacific/Honolulu', 'HST10' }, - { 'Pacific/Kiritimati', '<+14>-14' }, - { 'Pacific/Kosrae', '<+11>-11' }, - { 'Pacific/Kwajalein', '<+12>-12' }, - { 'Pacific/Majuro', '<+12>-12' }, - { 'Pacific/Marquesas', '<-0930>9:30' }, - { 'Pacific/Midway', 'SST11' }, - { 'Pacific/Nauru', '<+12>-12' }, - { 'Pacific/Niue', '<-11>11' }, - { 'Pacific/Norfolk', '<+11>-11<+12>,M10.1.0,M4.1.0/3' }, - { 'Pacific/Noumea', '<+11>-11' }, - { 'Pacific/Pago Pago', 'SST11' }, - { 'Pacific/Palau', '<+09>-9' }, - { 'Pacific/Pitcairn', '<-08>8' }, - { 'Pacific/Pohnpei', '<+11>-11' }, - { 'Pacific/Port Moresby', '<+10>-10' }, - { 'Pacific/Rarotonga', '<-10>10' }, - { 'Pacific/Saipan', 'ChST-10' }, - { 'Pacific/Tahiti', '<-10>10' }, - { 'Pacific/Tarawa', '<+12>-12' }, - { 'Pacific/Tongatapu', '<+13>-13' }, - { 'Pacific/Wake', '<+12>-12' }, - { 'Pacific/Wallis', '<+12>-12' }, -} - -name = arg[1] -TM = nil - -array = {} -i = 1 -repeat - array = TZ[i] - if array[1] == name then - TM = array[2] - break - end - i = i+1 -until(array == nil) - -local tfile = io.open("/tmp/tzone", "w") -if TM ~= nil then - tfile:write("ZNAME=\"", TM, "\"\n") - tfile:write("ZONEN=\"", name, "\"\n") -end -tfile:close() - diff --git a/rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh b/rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh deleted file mode 100644 index fb685b0..0000000 --- a/rooter/ext-rooter-basic/files/usr/lib/rooter/ussd.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -CURRMODEM=$(uci get modem.general.modemnum) -COMMPORT="/dev/ttyUSB"$(uci get modem.modem$CURRMODEM.commport) -ROOTER=/usr/lib/rooter - -if [ -n "$1" ]; then - echo "$1" > /tmp/ussd_arg$CURRMODEM -fi - -while true; do - if [ -e /tmp/ussd_arg$CURRMODEM ]; then - read USSDSTR < /tmp/ussd_arg$CURRMODEM - rm /tmp/ussd_arg$CURRMODEM - fi - if [ -n "$USSDSTR" ]; then - ATCMDD="AT+CUSD=1,\"$USSDSTR\",15" - OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "ussd.gcom" "$CURRMODEM" "$ATCMDD" | tr "\n" "\v") - USSD=$(echo "$OX" | grep -o "+CUSD: .\+\",[0-9]\+" | tr "\v" "\n") - USSDL=${#USSD} - USSDLx=$((USSDL - 2)) - DCS=$(printf "${USSD:$USSDLx:2}") - if [ $USSDL -ge 14 ]; then - USSDL=$((USSDL - 14)) - USSD=$(printf "${USSD:10:$USSDL}") - if [ $DCS -eq "72" ]; then - USSDx="" - USSDL=${#USSD} - nV=0 - until [ $nV -ge $USSDL ]; do - UU=$(printf "%d" "0x"${USSD:$nV:4}) - if [[ $UU -lt 128 ]]; then - USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UU")") - elif [[ $UU -lt 2048 ]]; then - UUU=$(((($UU & 1984) >> 6) | 192)) - USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") - UUU=$((($UU & 63) | 128)) - USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") - else - UUU=$(((($UU & 61440) >> 12) | 224)) - USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") - UUU=$(((($UU & 4032) >> 6) | 128)) - USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") - UUU=$((($UU & 63) | 128)) - USSDx="$USSDx"$(printf "%b" "\\$(printf "0%o" "$UUU")") - fi - nV=$(( $nV + 4 )) - done - USSD="$USSDx" - fi - else - USSD=$(echo "$OX" | tr "\v" "\n") - fi - echo - echo "-----------------------------------------------------------" - echo "$USSD" - echo "-----------------------------------------------------------" - echo - fi - printf "Enter blank to quit, or a USSD string to send: "; read USSDSTR - if [ -z "$USSDSTR" ]; then - break - fi -done -ATCMDD="AT+CUSD=2" -OX=$($ROOTER/gcom/gcom-locked "$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") -exit 0 diff --git a/rooter/ext-rooter-basic/files/usr/sbin/modlog b/rooter/ext-rooter-basic/files/usr/sbin/modlog deleted file mode 100644 index 46a614f..0000000 --- a/rooter/ext-rooter-basic/files/usr/sbin/modlog +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -name=$1 -text=$2 - -logger -t "$name" "$text" -/usr/lib/rooter/log/modlogger.sh "$name $text" \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/background/main_bg.jpg b/rooter/ext-rooter-basic/files/www/luci-static/background/main_bg.jpg deleted file mode 100644 index 66222dcbef009ee206460169e829eeed027f2848..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 134812 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

                                                                      5p0_H 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 Oxtd{R3XbI-wg1_EhJN<| diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css b/rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css deleted file mode 100644 index a04fe19..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/css/cascade.css +++ /dev/null @@ -1,3305 +0,0 @@ -@import url(fonts.css?v=3); - -@import url(pure-min.css?v=1); - -:root { - --primary: #5e72e4; - --dark-primary: #483d8b; - --main-color: #09c; - --header-bg: #09c; - --header-color: #fff; - --bar-bg: #5e72e4; - --menu-bg-color: #fff; - --menu-color: #5f6368; - --menu-color-hover: #202124; - --main-menu-color: #202124; - --submenu-bg-hover: #d4d4d4; - --submenu-bg-hover-active: #09c; - --blue: #5e72e4; - --indigo: #5603ad; - --purple: #8965e0; - --pink: #f3a4b5; - --red: #f5365c; - --orange: #fb6340; - --yellow: #ffd600; - --green: #2dce89; - --teal: #11cdef; - --cyan: #2bffc6; - --gray: #8898aa; - --gray-dark: #32325d; - --lighter: #e9ecef; - --secondary: #f7fafc; - --success: #2dce89; - --info: #11cdef; - --warning: #fb6340; - --danger: #f5365c; - --light: #adb5bd; - --dark: #212529; - --default: #172b4d; - --white: #fff; - --neutral: #fff; - --darker: #000; - --background-color: #f4f5f7; - --login-form-bg-color: rgba(244,245,247,0.8); - --breakpoint-xs: 0; - --breakpoint-sm: 576px; - --breakpoint-md: 768px; - --breakpoint-lg: 992px; - --breakpoint-xl: 1200px; - --blur-radius: 10px; - --blur-opacity: .5; - --blur-radius-dark: 10px; - --blur-opacity-dark: .5; - --font-family-sans-serif: "Google Sans","Microsoft Yahei","WenQuanYi Micro Hei",sans-serif,"Helvetica Neue",Helvetica,"Hiragino Sans GB"; - --font-family-monospace: SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace; - --font-family-normal: Open Sans,PingFangSC-Regular,Microsoft Yahei,WenQuanYi Micro Hei,"Helvetica Neue",Helvetica,Hiragino Sans GB,sans-serif; -} - -html,body { - height: 100%; - font-size: 16px; - font-family: var(--font-family-sans-serif); - margin: 0px; - padding: 0px; -} - -html { - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -body { - font-size: .875rem; - background-color: var(--background-color); - color: var(--gray-dark); -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -::selection { - background-color: var(--primary); - color: var(--white); -} - -a:link,a:visited,a:active { - color: var(--primary); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -li { - list-style-type: none; -} - -.table { - position: relative; - display: table; -} - -.tr { - display: table-row; -} - -.thead { - display: table-header-group; -} - -.tbody { - display: table-row-group; -} - -.tfoot { - display: table-footer-group; -} - -.td,.th { - line-height: normal; - display: table-cell; - text-align: center; - vertical-align: middle; - padding: .5em; -} - -.th { - font-weight: 700; - white-space: nowrap; -} - -.tr.placeholder { - height: 4em; -} - -.tr.placeholder>.td { - line-height: 3; - position: absolute; - right: 0; - bottom: 0; - left: 0; - text-align: center!important; - background: inherit; - padding: .4rem 0!important; -} - -.td[width="33%"] { - padding: 1.1em 1.5rem; -} - -.table[width="33%"],.th[width="33%"],.td[width="33%"] { - width: 33%; -} - -.col-1 { - flex: 1 1 30px!important; -} - -.col-2 { - flex: 2 2 60px!important; -} - -.col-3 { - flex: 3 3 90px!important; -} - -.col-4 { - flex: 4 4 120px!important; -} - -.col-5 { - flex: 5 5 150px!important; -} - -.col-6 { - flex: 6 6 180px!important; -} - -.col-7 { - flex: 7 7 210px!important; -} - -.col-8 { - flex: 8 8 240px!important; -} - -.col-9 { - flex: 9 9 270px!important; -} - -.col-10 { - flex: 10 10 300px!important; -} - -.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6 { - font-family: inherit; - font-weight: 400; - line-height: 1.1!important; - color: inherit; -} - -select { - color: #555; - border: thin solid #ccc; - background-color: #fff; - background-image: none; - padding: .36rem .8rem; -} - -.btn,button,select,input,.cbi-dropdown { - line-height: 1.5rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: .25rem; - outline: 0; - background-image: none; - box-shadow: none; - transition: box-shadow .15s ease; - margin: .25rem .1rem; - padding: .5rem .75rem; -} - -select,.cbi-dropdown { - width: inherit; - cursor: default; -} - -select:not([multiple="multiple"]):focus,input:not(.cbi-button):focus,.cbi-dropdown:focus { - box-shadow: 0 3px 9px rgba(50,50,9,0),3px 4px 8px rgba(94,114,228,0.1); - border-color: var(--primary); -} - -pre { - overflow: auto; -} - -code { - font-size: 1rem; - font-size-adjust: .35; - color: #101010; - border-radius: 2px; - background: #ddd; - padding: 1px 3px; -} - -abbr { - cursor: help; - text-decoration: underline; - color: var(--primary); -} - -hr { - opacity: .1; - border-color: #eee; - margin: 1rem 0; -} - -.login-page { - height: 95vh; - width: 95vw; -} - -.login-page .video { - position: absolute; - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - background-color: var(--darker); - overflow: hidden; -} - -.login-page .video video { - width: 100%; - height: auto; -} - -.login-page .volume-control { - position: fixed; - right: 1rem; - top: 1rem; - width: 1.5rem; - height: 1.5rem; - z-index: 5000; - cursor: pointer; - background-size: contain; - background-image: url(../img/volume_high.svg); -} - -.login-page .volume-control.mute { - background-image: url(../img/volume_off.svg); -} - -.login-page .main-bg { - position: absolute; - width: 101vw; - height: 101vh; - left: 0; - top: 0; - background-image: url(../img/blank.png); - background-repeat: no-repeat; - background-position: center; - background-size: cover; - transition: all .5s; - background-color: rgba(255,255,255,1); -} - - -.login-page .status-container { - height: 100%; - position: absolute; - top: 0px; - - right: 0px; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 100%; - z-index: 2; - width: 800px; - box-shadow: rgba(0,0,0,0.75) 0 0 35px -5px; - margin-left: 5%; - background: transparent; -} - -.login-page .status-container .status-form { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: right; - position: absolute; - top: 0px; - width: 100%; - min-height: 100%; - max-width: 800px; - background-color: rgba(224,224,224,0); -} - -.login-page .login-container { - height: 100%; - position: absolute; - top: 0px; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 100%; - z-index: 2; - width: 20vw; - box-shadow: rgba(0,0,0,0.75) 0 0 35px -5px; - margin-left: 4%; - background: transparent; -} - -/* color of login panel */ -.login-page .login-container .login-form { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 100%; - max-width: 100%; - background-color: rgba(224,224,224,0.7); -} - -/* change for login box */ -.login-page .login-container .login-form .brand { - display: flex; - -webkit-box-align: center; - align-items: center; - color: var(--default); - margin: 20px auto 5px 10px; -} - -.login-page .login-container .login-form .brandim { - display: flex; - -webkit-box-align: center; - align-items: center; - color: var(--default); - margin: 12vh 0px 30px 0px; -} - -.login-page .login-container .login-form .brandim .icon-im { - width: 19vw; - height: auto; - margin-right: 0px; -} - -.login-page .login-iframem { - height: 76vh; - position: absolute; - - left: 40vw; - top: 0; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 76vh; - z-index: 2; - width: 50vw; - margin-left: 1vw; - background: transparent; -} -.login-page .login-iframem .login-iform { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 76vh; - max-width: 100%; -} - -.login-page .login-iframem .login-iform .ifframe { - width: 100vw; - max-width: 100%; - height: 76vh; - max-height: 100%; - left: 0px; - position: absolute; - top: 0px; -} - -.login-page .login-iframe { - height: 12vh; - position: absolute; - top: 85vh; - left: 0; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 12vh; - z-index: 2; - width: 18vw; - margin-left: 1vw; - background: transparent; -} -.login-page .login-iframe .login-iform { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 12vh; - max-width: 100%; -} - -.login-page .login-iframe .login-iform .ifframe { - width: 100vw; - max-width: 100%; - height: 50vh; - max-height: 100%; - left: 0px; - position: absolute; - top: 0px; -} - -.login-page .login-bframe { - height: 45vh; - position: absolute; - top: 52vh; - left: 0; - display: flex; - flex-direction: column; - -webkit-box-pack: center; - justify-content: center; - align-items: flex-start; - min-height: 45vh; - z-index: 2; - width: 24vw; - margin-left: -2vw; - background: transparent; -} -.login-page .login-bframe .login-bform { - display: flex; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: absolute; - top: 0px; - width: 100%; - min-height: 45vh; - max-width: 100%; -} - -.login-page .login-bframe .login-bform .ibframe { - width: 100vw; - max-width: 100%; - height: 50vh; - max-height: 100%; - left: 0px; - position: absolute; - top: 0px; -} - -/* size of logo displayed */ -.login-page .login-container .login-form .brand .icon-lg { - width: 19vw; - height: auto; - margin-right: 10px; -} - -.login-page .login-container .login-form .brand .icon { - width: 7vw; - height: auto; - margin-right: 10px; -} - -.login-page .login-container .login-form .brand .brand-text { - font-size: 1.2vw; - font-weight: 700; - font-family: TypoGraphica; -} - -.login-page .login-container .login-form .brand .brand-textlg { - font-size: 1.2vw; - font-weight: 700; - font-family: TypoGraphica; - margin-left: 2vw; -} - -.login-page .login-container .login-form .form-login { - width: 100%; - box-sizing: border-box; - padding: 20px 50px; -} - -.login-page .login-container .login-form .form-login .errorbox { - text-align: center; - color: var(--warning); - padding-bottom: 2rem; -} - -.login-page .login-container .login-form .form-login .input-group { - margin-bottom: 1.25rem; - position: relative; -} - -.login-page .login-container .login-form .form-login .input-group::before { - font-family: argon!important; - font-style: normal; - font-weight: 400; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - color: var(--default); - font-size: 1.5rem; - position: absolute; - z-index: 100; - left: 10px; - top: 10px; -} - -.login-page .login-container .login-form .form-login .input-group .border { - position: absolute; - width: 100%; - height: 1px; - bottom: 0; - border-bottom: 1px var(--primary) solid; - transform: scaleX(0); - transition: transform .3s; -} - -.login-page .login-container .login-form .form-login .input-group input { - font-size: 1rem; - line-height: 1.5em; - display: block; - width: 100%; - box-sizing: border-box; - transition: all .3s cubic-bezier(.68,-0.55,.265,1.55); - color: var(--default); - border: 0; - border-radius: 0; - border-bottom: 1px solid var(--white); - background-color: transparent; - background-clip: padding-box; - box-shadow: 0 3px 2px rgba(233,236,239,0.05); - outline: none; - margin: .825rem 0; - padding: .5rem .75rem .5rem 3rem; -} - -.login-page .login-container .login-form .form-login .input-group input:focus+.border { - transform: scaleX(1); -} - -.login-page .login-container .login-form .form-login .input-group .cbi-input-password { - margin-bottom: 2rem; - position: relative; -} - -.login-page .login-container .login-form .form-login .user-icon::before { - content: "\e971"; -} - -.login-page .login-container .login-form .form-login .pass-icon::before { - content: "\e910"; -} - -.login-page .login-container .login-form .cbi-button-apply { - width: 100%!important; - box-shadow: rgba(0,0,0,0.1) 0 0 50px 0; - font-weight: 600; - font-size: 15px; - color: var(--white); - text-align: center; - cursor: pointer; - min-height: 50px; - background-color: var(--primary)!important; - border-radius: 6px; - outline: none; - border-image: initial; - transition: all .3s!important; - letter-spacing: .8rem; - border-color: initial; - border-style: none; - border-width: initial; - margin: 30px 0px 20px; - padding: 10px 0px; -} - -.login-page .login-container .login-form .cbi-button-apply:hover,.login-page .login-container .login-form .cbi-button-apply :focus { - opacity: .9; -} - -.login-page .login-container footer { - box-sizing: border-box; - width: 100%; - text-align: center; - line-height: 1.6rem; - display: flex; - justify-content: space-evenly; - margin-top: auto; - z-index: 10; - color: var(--default); - position: absolute; - bottom: 0; - padding: 0px 0px 30px; -} - -.login-page .login-container footer .ftc { - position: absolute; - bottom: 30px; - width: 100%; -} - -footer { - font-size: .8rem; - overflow: hidden; - text-align: right; - white-space: nowrap; - color: #aaa; - padding: 1rem; -} - -footer>a { - text-decoration: none; - color: #aaa; -} - -small { - font-size: 90%; - line-height: 1.42857143; - white-space: normal; -} - -.main { - position: relative; - top: 0; - bottom: 0; - overflow-y: auto; - height: 100%; -} - -.main-left { - top: 0; - float: left; - width: calc(0% + 15rem); - height: 100%; - background-color: var(--menu-bg-color); - box-shadow: rgba(0,0,0,0.75) 0 0 15px -5px; - overflow-x: auto; - position: fixed; - z-index: 100; -} - -.main-left .sidenav-header { - text-align: center; - padding: 1.5rem; -} - -.main-left .sidenav-header .brand { - font-size: 1.8rem; - color: var(--primary); - font-family: TypoGraphica; - text-decoration: none; - text-align: center; - cursor: default; - vertical-align: text-bottom; - white-space: nowrap; -} - -.main-left::-webkit-scrollbar { - width: 5px; - height: 1px; -} - -.main-right { - float: right; - width: calc(100% - 15rem); - height: 100%; - transition: all .2s; -} - -.main-right>#maincontent { - position: relative; - z-index: 50; -} - -.pull-right { - float: right; -} - -.nowrap:not(.td) { - white-space: nowrap; -} - -[disabled="disabled"] { - pointer-events: none; -} - -header { - color: var(--header-color); - position: relative; - padding: 0; -} - -header.bg-primary { - background-color: var(--primary)!important; -} - -header::after { - content: ""; - position: absolute; - height: 2rem; - width: 100%; - background-color: var(--primary)!important; -} - -header .fill { - border-bottom: 0 solid rgba(255,255,255,0.08)!important; - padding: .8rem 0; -} - -header .fill .container { - height: 2rem; - padding: 0 1.25rem; -} - -header .fill .container .showSide { - display: none; - color: #fff; - font-size: 1.4rem; -} - -header .fill .container .brand { - font-size: 1.5rem; - color: #fff; - font-family: TypoGraphica; - text-decoration: none; - padding-left: 1rem; - cursor: default; - vertical-align: text-bottom; - display: none; -} - -header .fill .container .pull-right { - float: right; - margin-top: 0rem; - display: flex; -} - -header .fill .status { - position: absolute; - top: 25%; - right: 1.25rem; - float: right; -} - -header .fill .status span[data-indicator="poll-status"] { - display: block; - font-size: .8rem; - font-weight: 700; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - text-shadow: none; - border-radius: 3px; - cursor: pointer; - transition: all .3s; - padding: .3rem .8rem; -} - -header .fill .status span[data-style="active"] { - color: #32325d!important; - background-color: #fff; -} - -header .fill .status span[data-style="inactive"] { - color: #FFF!important; - background-color: #32325d; -} - -#xhr_poll_status { - display: flex; - margin-left: .5rem; -} - -div[style="width:100%;height:300px;border:1px solid #000;background:#fff"] { - border: 0!important; -} - -.danger { - background-color: #ff7d60!important; -} - -.warning { - background-color: #f0e68c!important; -} - -.success { - background-color: #5cb85c!important; -} - -.notice { - background-color: #11cdef!important; - color: #fff; -} - -.error { - color: red; -} - -.alert,.alert-message { - font-weight: 700; - margin-bottom: 1em; - border: 0; - border-radius: .375rem!important; - background-color: #fff; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - text-shadow: 1px 1px rgba(0,0,0,0.1); - padding: 1rem; -} - -.alert.error,.alert-message.error { - background-color: #ffd600; -} - -.alert h4,.alert-message h4 { - padding: 0 1.5rem .75rem 0; -} - -.alert-message>h4 { - font-size: 110%; - font-weight: 700; -} - -.alert-message>* { - margin: .5rem 0; -} - -.alert-message .btn { - padding: .3rem .6rem; -} - -.main .main-left { - transition: all .2s; -} - -.main .main-left .nav li { - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - padding: 0; -} - -.main .main-left .nav li a { - display: block; - color: var(--menu-color); -} - -.main .main-left .nav li.slide .slide-menu { - margin: 0 .5rem 0 2.5rem; - padding: 0 .5rem; -} - -.main .main-left .nav li.slide .slide-menu li { - position: relative; - border-radius: .375rem; - background: none; - list-style: none; - margin: 0; - padding: .5rem 0; -} - -.main .main-left .nav li.slide .slide-menu li a { - white-space: nowrap; - text-decoration: none; -} - -.main .main-left .nav li.slide .slide-menu li::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 0; - height: 2px; - background-color: var(--primary); - transition: all .2s; -} - -.main .main-left .nav li.slide .slide-menu .active { - background: none; - color: var(--menu-color); -} - -.main .main-left .nav li.slide .slide-menu .active a { - color: var(--menu-color); -} - -.main .main-left .nav li.slide .slide-menu .active::after { - content: ""; - position: absolute; - left: 0; - bottom: 0; - width: 100%; - height: 2px; - background-color: var(--primary); - transition: all .2s; -} - -.main .main-left .nav li .menu::after { - position: absolute; - right: .5rem; - top: .8rem; - font-family: argon!important; - font-style: normal; - font-weight: 400; - font-variant: normal; - text-transform: none; - line-height: 1; - -moz-osx-font-smoothing: grayscale; - content: '\e90f'; - color: #ced4da; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - transition: all .3s; -} - -.main .main-left .nav li .menu[data-title=Status]:before { - content: "\e906"; - color: var(--primary); -} - -.main .main-left .nav li .menu[data-title=System]:before { - content: "\e90a"; - color: #fb6340; -} - -.main .main-left .nav li .menu[data-title=Services]:before { - content: "\e909"; - color: #11cdef; -} - -.main .main-left .nav li .menu[data-title=NAS]:before { - content: "\e90c"; - color: #f3a4b5; -} - -.main .main-left .nav li .menu[data-title=VPN]:before { - content: "\e90b"; - color: #8965e0; -} - -.main .main-left .nav li .menu[data-title=Network]:before { - content: "\e908"; - color: #8965e0; -} - -.main .main-left .nav li .menu[data-title=Bandwidth_Monitor]:before { - content: "\e90d"; - color: #2dce89; -} - -.main .main-left .nav li .menu[data-title=Docker]:before { - content: "\e911"; - color: #69F; -} - -.main .main-left .nav li .menu[data-title=Statistics]:before { - content: "\e913"; - color: #8965e0; -} - -.main .main-left .nav li .menu[data-title=Control]:before { - content: "\e912"; - color: var(--primary); -} - -.main .main-left .nav li .menu[data-title=Asterisk]:before { - content: "\e914"; - color: #fb6340; -} - -.main .main-left .nav li a[data-title=Logout]:before { - content: "\e907"; - color: #adb5bd; -} - -.lg { - margin: 0; - padding: 0!important; -} - -.logout { - display: block; - border-radius: .375rem; - text-decoration: none; - font-size: 1rem; - transition: all .2s; - position: relative; - margin: .8rem .5rem .1rem; - padding: .675rem 0 .675rem 2.5rem; -} - -.logout:before { - font-family: argon!important; - font-style: normal; - font-weight: 400; - font-variant: normal; - text-transform: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - position: absolute; - left: .8rem; - padding-top: 3px; - transition: all .3s; - content: "\e907"; - color: #32325d!important; -} - -body[class*="node-"]>.main>.main-left>.nav>.slide>.menu::before { - transition: transform .1s ease-in-out; -} - -body[class*="node-"]>.main>.main-left>.nav>.slide>.menu.active::before { - transition: transform .2s ease-in-out; -} - -#maincontent>.container { - margin: 0 1.25rem 1rem; -} - -ul { - line-height: normal; -} - -h1 { - font-size: 2rem; - padding-bottom: 10px; - border-bottom: thin solid #eee; -} - -h2 { - font-size: 1.25rem; - letter-spacing: .1rem; - color: #32325d; - border-radius: .375rem; - background: #fff; - box-shadow: 0 4px 8px rgba(0,0,0,0.03); - margin: 0 0 1rem; - padding: 1rem 1.5rem; -} - -h3 { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - color: var(--gray-dark); - border-radius: .375rem; - background: #fff; - margin: 0; - padding: .8755rem 1.5rem; -} - -h4 { - font-size: .7rem; - font-weight: 600; - color: #525f7f; - background-color: var(--lighter); - margin: 0; - padding: .75rem 1.5rem; -} - -h4 em { - padding: 0 .5rem; -} - -h5 { - font-size: 1rem; - padding-bottom: 10px; - margin: 2rem 0 0; -} - -.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container { - font-family: inherit; - font-weight: 400; - font-style: normal; - line-height: normal; - min-width: inherit; - border: 0; - border-radius: .375rem; - background-color: #fff; - box-shadow: 0 0 1rem 0 rgba(136,152,170,0.15); - margin: 1.5rem 0; - padding: 0rem; -} - -.cbi-modal .cbi-section,.cbi-section .cbi-section { - box-shadow: none; - padding: 0; -} - -.cbi-modal .cbi-tabmenu { - margin-left: 0; -} - -.cbi-map-descr,.cbi-section-descr { - font-size: small; - line-height: 1.42857143; - padding: .5rem 1.5rem; -} - -.cbi-map-descr>abbr { - cursor: help; - text-decoration: underline; -} - -.cbi-section>legend { - display: none!important; -} - -fieldset>fieldset,.cbi-section>.cbi-section { - border: 0; - box-shadow: none; - margin: 0; - padding: 0; -} - -.cbi-section>h3:first-child,.panel-title { - font-size: 1.1rem; - line-height: 1; - display: block; - width: 100%; - color: var(--gray-dark); - margin: 0; - padding: .8755rem 1.5rem; -} - -table { - border-spacing: 0; - border-collapse: collapse; -} - -table,.table { - overflow-y: hidden; - width: 100%; - font-size: 90%; -} - -.table .table-titles th { - background-color: var(--lighter); -} - -.container>.cbi-section:first-of-type>.table[width="100%"]>.tr>.td { - padding: .6rem; -} - -.cbi-section-table-cell { - line-height: 1.1; - align-self: flex-end; - flex: 1 1 auto; -} - -tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2) { - border-top: thin solid #ddd; - padding: 1.1em 1.5rem; -} - -#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th { - border-top: 0!important; - background-color: #f6f9fc; - line-height: 1.3rem; - padding: 1.1em 1.5rem; -} - -.table[width="100%"]>.tr:first-child>.td { - margin: auto 0; -} - -.cbi-section-table-row { - margin-bottom: 1rem; - text-align: center!important; - background: #f4f4f4; -} - -.cbi-section-table-row:last-child { - margin-bottom: 0; -} - -.cbi-section-table-row>.cbi-value-field [data-dynlist]>input,.cbi-section-table-row>.cbi-value-field input.cbi-input-password { - width: calc(100% - 1.5rem); -} - -table table,.table .table,.cbi-value-field table,.cbi-value-field .table,td>table>tbody>tr>td,.td>.table>.tbody>.tr>.td,.cbi-value-field>table>tbody>tr>td,.cbi-value-field>.table>.tbody>.tr>.td { - border: 0; -} - -.btn,.cbi-button,.item::after { - font-size: .8rem; - display: inline-block; - width: auto!important; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - transition: all .2s ease-in-out; - text-align: center; - vertical-align: middle; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: rgba(0,0,0,0.87); - border: 0; - border-radius: .2rem; - background-color: #f0f0f0; - background-image: none; - -webkit-appearance: none; - -ms-touch-action: manipulation; - touch-action: manipulation; - padding: .45rem .8rem; -} - -.cbi-button-up,.cbi-button-down { - font-size: 1.2rem; - display: inline-block; - min-width: 0; - color: transparent!important; - background: url(../icon/arrow.svg) no-repeat center; - background-size: 12px 20px; - padding: .2rem .3rem; -} - -.cbi-button-up { - transform: scaleY(-1); -} - -.cbi-button:not(select) { - -webkit-appearance: none!important; -} - -.btn:hover,.btn:focus,.btn:active,.cbi-button:hover,.cbi-button:focus,.cbi-button:active,.item:hover::after,.item:focus::after,.item:active::after,.cbi-page-actions .cbi-button-apply+.cbi-button-save:hover,.cbi-page-actions .cbi-button-apply+.cbi-button-save:focus,.cbi-page-actions .cbi-button-apply+.cbi-button-save:active { - text-decoration: none; - outline: 0; -} - -.btn:hover,.btn:focus,.cbi-button:hover,.cbi-button:focus,.item:hover::after,.item:focus::after { - box-shadow: 0 0 2px rgba(0,0,0,0.12),0 2px 2px rgba(0,0,0,0.2); -} - -.btn:active,.cbi-button:active,.item:active::after { - box-shadow: 0 10px 20px rgba(0,0,0,0.19),0 6px 6px rgba(0,0,0,0.23); -} - -.cbi-button-up:hover,.cbi-button-up:focus { - box-shadow: 0 0 2px rgba(0,0,0,0.12),0 -2px 2px rgba(0,0,0,0.2); -} - -.cbi-button-up:active { - box-shadow: 0 -10px 20px rgba(0,0,0,0.19),0 -6px 6px rgba(0,0,0,0.23); -} - -.btn:disabled,.cbi-button:disabled { - cursor: not-allowed; - pointer-events: none; - opacity: .5; - box-shadow: none; -} - -.alert-message [class="btn"],.modal div[class="btn"],.cbi-button-find,.cbi-button-link,.cbi-button-up,.cbi-button-down,.cbi-button-neutral,.cbi-button[name="zero"],.cbi-button[name="restart"],.cbi-button[onclick="hide_empty(this)"] { - font-weight: 700; - color: #fff; - border: thin solid #8898aa; - background-color: #8898aa; -} - -.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"] { - font-weight: 400; - color: #fff; - border: thin solid var(--red); - background-color: var(--red); -} - -.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"] { - font-weight: 400; - color: #fff; - border: thin solid #eea236; - background-color: #f0ad4e; -} - -.cbi-button-success,.cbi-button-download,.cbi-button[name="backup"],.cbi-button[value="Download"],.cbi-button[value="Save mtdblock"] { - font-weight: 400; - color: #fff; - border: thin solid #4cae4c; - background-color: #5cb85c; -} - -.cbi-value-field .cbi-button-add { - font-weight: 700; - display: flex; - align-items: center; - margin: 4px 0 4px 3px; - padding: 1px 6px; -} - -.tabs { - background-color: #FFF; - border-radius: .375rem; - box-shadow: 0 4px 8px rgba(0,0,0,0.03); - white-space: nowrap; - overflow-x: auto; - margin: 0 0 1rem; - padding: 0 1rem; -} - -.tabs li[class~="active"],.tabs li:hover { - cursor: pointer; - border-bottom: .18751rem solid var(--primary); - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; - border-radius: 0; -} - -.tabs li { - font-size: .875rem; - display: inline-block; - border-bottom: .18751rem solid rgba(0,0,0,0); - margin: 0 .2rem; - padding: .875rem 0; -} - -.tabs li:hover { - border-bottom: .18751rem solid var(--primary); -} - -.cbi-tabmenu { - color: #fff; - white-space: nowrap; - overflow-x: auto; - padding: .5rem 1rem 0; -} - -.cbi-tabmenu li { - background: #dce3e9; - display: inline-block; - font-size: .875rem; - border-top-left-radius: .25rem; - border-top-right-radius: .25rem; - border-bottom: .18751rem solid rgba(0,0,0,0); - margin: 0 .2rem; - padding: .5rem 0; -} - -.cbi-tabmenu li:hover { - cursor: pointer; - border-bottom: .18751rem solid var(--primary); - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; -} - -.cbi-tabmenu li:hover a { - color: #525f7f; -} - -.cbi-tabmenu li[class~="cbi-tab"] { - border-bottom: .18751rem solid var(--primary); - color: var(--primary); - background-color: #dce1fe; - margin-bottom: 0; -} - -.cbi-tab-descr { - padding: .5rem 1.5rem; -} - -[data-tab-title] { - overflow: hidden; - height: 0; - opacity: 0; - margin: 0; - padding: 0rem!important; -} - -[data-tab-title] p { - margin-left: 1rem; - margin-bottom: 1rem; -} - -[data-tab-active="true"] { - overflow: visible; - height: auto; - opacity: 1; - transition: opacity .25s ease-in; - margin: inherit!important; -} - -.cbi-section-node-tabbed { - margin-top: 0; - border: 0 solid #d4d4d4; - border-radius: .375rem; - padding: 0; -} - -.cbi-value-field,.cbi-value-description { - line-height: 1.25; - display: table-cell; -} - -.cbi-value-field abbr,.cbi-value-description abbr { - color: var(--gray-dark); -} - -.cbi-value-description { - font-size: small; - opacity: .5; - padding: .5rem; -} - -.cbi-value-title { - display: table-cell; - float: left; - width: 23rem; - padding-top: .25rem; - padding-right: 2rem; - text-align: right; - word-wrap: break-word; -} - -.cbi-value { - display: inline-block; - width: 100%; - line-height: 2.4rem; - padding: .35rem 1rem .2rem; -} - -.cbi-value ul { - line-height: 1.25; -} - -.cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"] { - min-width: 18rem; -} - -.cbi-value input[type="password"] { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: 0; -} - -.cbi-value input[type="password"]+.cbi-button-neutral { - height: 42px; - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin-left: 0; - border: 0; -} - -#cbi-firewall-zone .cbi-input-select,#cbi-network-switch_vlan .cbi-input-select { - min-width: 11rem; -} - -#cbi-network-switch_vlan .cbi-input-text { - max-width: 3rem; -} - -.cbi-input-invalid { - color: #f5365c; - border-bottom-color: #f5365c; -} - -.cbi-section-error { - font-weight: 700; - line-height: 1.42857143; - border: thin solid #f5365c; - border-radius: 3px; - background-color: #fce6e6; - margin: 18px; - padding: 6px; -} - -.cbi-section-error ul { - margin: 0 0 0 20px; -} - -.cbi-section-error ul li { - font-weight: 700; - color: #f5365c; -} - -.td[data-title]::before { - font-weight: 700; - display: none; - content: attr(data-title) ":\20"; - text-align: left; - white-space: nowrap; - padding: .25rem 0; -} - -.tr[data-title]::before,.tr.cbi-section-table-titles.named::before { - font-weight: 700; - display: table-cell; - align-self: center; - flex: 1 1 5%; - content: attr(data-title) "\20"; - text-align: center; - vertical-align: middle; - white-space: normal; - word-wrap: break-word; - padding: .25rem; -} - -.cbi-rowstyle-2 { - background-color: #eee; -} - -.cbi-rowstyle-2 .cbi-button-up,.cbi-rowstyle-2 .cbi-button-down,body:not(.Interfaces) .cbi-rowstyle-2:first-child { - background-color: #fff!important; -} - -.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell { - width: auto!important; -} - -.td.cbi-section-actions { - text-align: right!important; - vertical-align: middle; -} - -.td.cbi-section-actions>* { - display: inline-flex; -} - -.td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>* { - display: flex; - align-items: center; - margin: 0 5px; -} - -.td.cbi-section-actions>*>form { - display: inline-flex; - margin: 0; -} - -.cbi-checkbox { - margin: 0 .25rem; -} - -.cbi-dynlist { - line-height: 1.3; - flex-direction: column; - min-height: 30px; - cursor: text; -} - -.cbi-dynlist>.item { - position: relative; - max-width: 25rem; - pointer-events: none; - color: #8898aa; - outline: 0; -} - -.cbi-dynlist[name="sshkeys"]>.item { - max-width: none; -} - -.cbi-dynlist>.item::after { - position: absolute; - width: 2.2rem!important; - height: calc(100% - .5rem - 2px); - right: 0; - bottom: 0; - content: "\00D7"; - pointer-events: auto; - background-color: var(--red); - font-weight: 400; - font-size: 1.2rem; - display: flex; - align-items: center; - justify-content: center; - line-height: 1.5rem; - color: #fff; - border: 1px solid #f5365c; - border-radius: .25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - margin: .25rem .1rem .25rem 0; - padding: 0; -} - -.cbi-dynlist>.item>span { - white-space: normal; - word-break: break-word; - line-height: 1.5rem; - color: #8898aa; - border: 1px solid #dee2e6; - border-radius: .25rem; - outline: 0; - background-image: none; - box-shadow: none; - display: block; - transition: box-shadow .15s ease; - box-sizing: border-box; - min-width: 15rem; - margin: .25rem .1rem; - padding: .5rem; -} - -.cbi-dynlist>.add-item { - display: inline-flex; - align-items: center; - width: 100%; - min-width: 16rem; -} - -.cbi-dynlist>.add-item input { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - margin-right: 0; - border-right: none; -} - -.cbi-dynlist>.add-item .cbi-button-add { - font-weight: 400; - font-size: 1.2rem; - display: flex; - align-items: center; - line-height: 1.5rem; - color: #fff; - border: 1px solid var(--primary); - border-radius: .25rem; - outline: 0; - background-image: none; - box-shadow: none; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - margin: .25rem .1rem .25rem 0; - padding: .5rem .75rem; -} - -.cbi-dynlist>.add-item:not([ondrop])>input { - overflow: hidden; - width: 100%; - min-width: 15rem; - white-space: nowrap; - text-overflow: ellipsis; -} - -.cbi-dynlist>.add-item[ondrop]>input { - min-width: 13rem; -} - -.cbi-dynlist,.cbi-dropdown { - position: relative; - display: inline-flex; - padding: .2rem; -} - -.cbi-dropdown[placeholder*="select"] { - max-width: 25rem; - height: auto; - margin-top: -3px; -} - -.cbi-dropdown>ul { - display: flex; - overflow-x: hidden; - overflow-y: auto; - width: 100%; - list-style: none; - outline: 0; - margin: 0!important; - padding: 0; -} - -.cbi-dropdown>.open { - flex-basis: 15px; -} - -.cbi-dropdown>.open,.cbi-dropdown>.more { - font-size: 1rem; - font-weight: 900; - line-height: 2; - display: flex; - flex-direction: column; - flex-grow: 0; - flex-shrink: 0; - justify-content: center; - cursor: default; - text-align: center; - outline: 0; - padding: 0 .25em; -} - -.cbi-dropdown>.more,.cbi-dropdown>ul>li[placeholder] { - font-weight: 700; - display: none; - color: #777; - text-shadow: 1px 1px 0 #fff; -} - -.cbi-dropdown>ul>li { - display: none; - overflow: hidden; - align-items: center; - align-self: center; - flex-grow: 1; - flex-shrink: 1; - min-height: 20px; - white-space: nowrap; - text-overflow: ellipsis; - padding: .25em; -} - -.cbi-dropdown>ul>li[display]:not([display="0"]) { - border-left: thin solid #ccc; -} - -.cbi-dropdown[empty]>ul { - max-width: 1px; -} - -.cbi-dropdown>ul>li>form { - display: none; - pointer-events: none; - margin: 0; - padding: 0; -} - -.cbi-dropdown>ul>li img { - margin-right: .25em; - vertical-align: middle; -} - -.cbi-dropdown>ul>li>form>input[type="checkbox"] { - height: auto; - margin: 0; -} - -.cbi-dropdown>ul>li input[type="text"] { - height: 20px; -} - -.cbi-dropdown[open]>ul.dropdown { - position: absolute; - z-index: 1100; - display: block; - width: auto; - min-width: 100%; - max-width: none; - max-height: 200px!important; - border: 0 solid #918e8c; - background: #FFF; - box-shadow: 0 0 4px #918e8c; - border-bottom-left-radius: .35rem; - border-bottom-right-radius: .35rem; - color: var(--main-menu-color); - margin-left: -0.2rem!important; -} - -.cbi-dropdown[open]>ul.dropdown li { - color: #000; -} - -.cbi-dropdown>ul>li[display],.cbi-dropdown[open]>ul.preview,.cbi-dropdown[open]>ul.dropdown>li,.cbi-dropdown[multiple]>ul>li>label,.cbi-dropdown[multiple][open]>ul.dropdown>li,.cbi-dropdown[multiple][more]>.more,.cbi-dropdown[multiple][empty]>.more { - display: flex; - align-items: center; - flex-grow: 1; -} - -.cbi-dropdown[open]>ul.dropdown>li { - border-bottom: thin solid #ccc; - padding: .5rem .8rem; -} - -.cbi-dropdown[open]>ul.dropdown>li[selected] { - background: #dce1fe; -} - -.cbi-dropdown[open]>ul.dropdown>li.focus { - background: #dce1fe; - outline: none; -} - -.cbi-dropdown[open]>ul.dropdown>li:last-child { - margin-bottom: 0; - border-bottom: 0; -} - -.cbi-dropdown[open]>ul.dropdown>li[unselectable] { - opacity: .7; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -.cbi-dropdown[open] .zonebadge { - width: auto; -} - -.cbi-progressbar { - position: relative; - min-width: 170px; - height: 20px; - border: thin solid #999; - background: #eee; - border-radius: .2rem; - overflow: hidden; - margin: 6px 0; -} - -.cbi-progressbar>div { - width: 0; - height: 100%; - transition: width .25s ease-in; - background: var(--bar-bg); -} - -.cbi-progressbar::after { - font-family: monospace; - font-size: 1em; - font-weight: 700; - font-size-adjust: .38; - line-height: normal; - position: absolute; - top: 2px; - right: 0; - bottom: 2px; - left: 0; - overflow: hidden; - content: attr(title); - text-align: center; - white-space: pre; - text-overflow: ellipsis; -} - -#modal_overlay { - position: fixed; - z-index: 900; - top: 0; - right: 10000px; - bottom: 0; - left: -10000px; - overflow-y: scroll; - transition: opacity .125s ease-in; - opacity: 0; - background: rgba(0,0,0,0.7); - -webkit-overflow-scrolling: touch; -} - -.modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 90%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - border-radius: 3px!important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - margin: 5em auto; - padding: 1em; -} - -.modal>* { - line-height: normal; - flex-basis: 100%; - margin-bottom: .5em; - max-width: 100%; -} - -.modal>pre,.modal>textarea { - font-size: 1rem; - font-size-adjust: .35; - overflow: auto; - margin-bottom: .5em; - cursor: auto; - white-space: pre-wrap; - color: #eee; - outline: 0; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - padding: 8.5px; -} - -.modal>h4 { - margin: .5em 0; -} - -.modal ul { - margin-left: 2.2em; -} - -.modal li { - list-style-type: square; - color: gray; -} - -.modal p { - word-break: break-word; -} - -.modal .label { - font-size: .6rem; - font-weight: 400; - cursor: default; - border-radius: 0; - padding: .1rem .3rem 0; -} - -.modal .label.warning { - background-color: #f0ad4e!important; -} - -.modal .btn { - padding: .45rem .8rem; -} - -.modal.cbi-modal { - max-width: 90%; - max-height: none; -} - -body.modal-overlay-active { - overflow: hidden; - height: 100vh; -} - -body.modal-overlay-active #modal_overlay { - right: 0; - left: 0; - opacity: 1; -} - -.spinning { - position: relative; - padding-left: 32px!important; -} - -.spinning::before { - position: absolute; - top: 0; - bottom: 0; - left: .2em; - width: 32px; - content: ""; - background: url(/luci-static/resources/icons/loading.gif) no-repeat center; - background-size: 16px; -} - -.left,.left::before { - text-align: left!important; -} - -.right,.right::before { - text-align: right!important; -} - -.top { - align-self: flex-start!important; - vertical-align: top!important; -} - -.bottom { - align-self: flex-end!important; - vertical-align: bottom!important; -} - -.inline { - display: inline; -} - -.cbi-page-actions { - padding-top: 1rem; - text-align: right; -} - -.cbi-page-actions>form[method="post"] { - display: inline-block; -} - -.th[data-type="button"],.td[data-type="button"],.th[data-type="fvalue"],.td[data-type="fvalue"] { - flex: 1 1 2em; - text-align: center; -} - -.ifacebadge { - display: inline-flex; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05); - padding: .5rem .8rem; -} - -td>.ifacebadge,.td>.ifacebadge { - font-size: .8rem; - background-color: #f0f0f0; -} - -.ifacebadge>em,.ifacebadge>img { - display: inline-block; - align-self: flex-start; - margin: 0 .2rem; -} - -.ifacebadge>img+img { - margin: 0 .2rem 0 0; -} - -.network-status-table .ifacebox { - flex-grow: 1; - margin: .5em; -} - -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; -} - -.network-status-table .ifacebox-body>span { - flex: 10 10 auto; - height: 100%; -} - -.network-status-table .ifacebox-body .ifacebadge { - align-items: center; - flex: 1 1 auto; - min-width: 220px; - background-color: #fff; - margin: .5em 0 0; - padding: .5em; -} - -.cbi-input-textarea { - font-family: monospace; - width: 100%; - font-size: .875rem; - min-height: 14rem; - color: #000; - padding: .8rem; -} - -#syslog { - font-size: small; - line-height: 1.25; - overflow-y: hidden; - width: 100%; - min-height: 15rem; - resize: none; - color: #242424; - border: 0; - border-radius: .375rem; - background-color: #FFF; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - padding: 1rem; -} - -#syslog:focus { - outline: 0; -} - -.uci-change-list { - font-family: monospace; -} - -.uci-change-list ins,.uci-change-legend-label ins { - display: block; - text-decoration: none; - border: thin solid #0f0; - background-color: #cfc; - padding: 2px; -} - -.uci-change-list del,.uci-change-legend-label del { - font-style: normal; - display: block; - text-decoration: none; - border: thin solid red; - background-color: #fcc; - padding: 2px; -} - -.uci-change-list var,.uci-change-legend-label var { - font-style: normal; - display: block; - text-decoration: none; - border: thin solid #ccc; - background-color: #eee; - padding: 2px; -} - -.uci-change-list var ins,.uci-change-list var del { - font-style: normal; - white-space: pre; - border: 0; - padding: 0; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - float: left; - width: 150px; -} - -.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var { - display: block; - float: left; - width: 10px; - height: 10px; - margin-right: 4px; -} - -.uci-change-legend-label var ins,.uci-change-legend-label var del { - line-height: .4; - border: 0; -} - -#iwsvg,#iwsvg2,#bwsvg { - border: thin solid #d4d4d4!important; -} - -#iwsvg,[data-page="admin-status-realtime-bandwidth"] #bwsvg { - border-top: 0!important; -} - -.ifacebox { - line-height: 1.25; - display: inline-flex; - flex-direction: column; - min-width: 100px; - border-bottom: thin solid #ccc; - background-color: #f9f9f9; - box-shadow: inset 0 1px 0 rgba(255,255,255,0.4),0 1px 2px rgba(0,0,0,0.2); -} - -.ifacebox-head { - background: #eee; - padding: .25em; -} - -.ifacebox-head.active { - background: var(--primary); -} - -.ifacebox-head.active * { - color: var(--white); -} - -.ifacebox-body { - line-height: 1.6em; - padding: .5em 1rem; -} - -.zonebadge { - display: inline-block; - padding: .2rem .5rem; -} - -.zonebadge .ifacebadge { - border: thin solid #6c6c6c; - margin: .1rem .2rem; - padding: .2rem .3rem; -} - -.zonebadge>input[type="text"] { - min-width: 10rem; - margin-top: .3rem; - padding: .16rem 1rem; -} - -.zonebadge>em,.zonebadge>strong { - display: inline-block; - margin: 0 .2rem; -} - -.cbi-value-field .cbi-input-checkbox,.cbi-value-field .cbi-input-radio { - margin-top: .1rem; -} - -.cbi-value-field>ul>li { - display: flex; -} - -.cbi-value-field>ul>li .ifacebadge { - margin-top: -0.5rem; - margin-left: .4rem; - background-color: #eee; -} - -.cbi-section-table-row>.cbi-value-field .cbi-dropdown { - min-width: 7rem; -} - -.cbi-section-create { - display: inline-flex; - align-items: center; - margin: .25rem 0 .25rem 1rem; -} - -.cbi-section-create>* { - margin: .5rem; -} - -div.cbi-value var,td.cbi-value-field var,.td.cbi-value-field var { - font-style: italic; - color: #0069d6; -} - -.cbi-optionals { - border-top: thin solid #ccc; - padding: 1rem 1rem 0; -} - -.cbi-dropdown-container { - position: relative; -} - -.cbi-tooltip-container,span[data-tooltip],span[data-tooltip] .label { - cursor: help!important; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - transition: opacity .25s ease-out; - white-space: pre; - pointer-events: none; - opacity: 0; - border-radius: 3px; - background: #fff; - box-shadow: 0 0 2px #444; - padding: 2px 5px; -} - -.cbi-tooltip-container:hover .cbi-tooltip { - left: auto; - transition: opacity .25s ease-in; - opacity: 1; -} - -.zonebadge .cbi-tooltip { - background: inherit; - margin: -1.5rem 0 0 -0.5rem; - padding: .25rem; -} - -.zonebadge-empty { - color: #404040; - background: repeating-linear-gradient(45deg,rgba(204,204,204,0.5),rgba(204,204,204,0.5) 5px,rgba(255,255,255,0.5) 5px,rgba(255,255,255,0.5) 10px); -} - -.zone-forwards { - display: flex; - min-width: 10rem; -} - -.zone-forwards>* { - flex: 1 1 45%; -} - -.zone-forwards>span { - flex-basis: 10%; - text-align: center; - padding: 0 .25rem; -} - -.zone-forwards .zone-src,.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} - -.label { - font-size: .8rem; - font-weight: 700; - white-space: nowrap; - text-decoration: none; - text-transform: uppercase; - color: #fff!important; - border-radius: 3px; - background-color: #bfbfbf; - text-shadow: none; - padding: .3rem .8rem; -} - -label>input[type="checkbox"],label>input[type="radio"] { - position: relative; - top: .4rem; - right: .2rem; - vertical-align: bottom; - margin: 0; -} - -label[data-index][data-depends] { - padding-right: 2em; -} - -.darkMask { - position: fixed; - z-index: 99; - display: none; - width: 100%; - height: 100%; - content: ""; - top: 0; - background-color: rgba(0,0,0,0.56); -} - -#diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code { - font-size: 1.2rem; - font-size-adjust: .35; - line-height: normal; - display: block; - overflow-y: hidden; - width: 100%; - white-space: pre; - color: #eee; - background-color: #101010; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - padding: 8.5px; -} - -[data-page="admin-network-diagnostics"] .table { - box-shadow: none; -} - -input[name="ping"],input[name="traceroute"],input[name="nslookup"] { - width: 80%; -} - -.node-status-overview>.main fieldset:nth-child(4) .td:nth-child(2),.node-status-processes>.main .table .tr .td:nth-child(3) { - white-space: normal; -} - -[data-page="admin-system-reboot"] .cbi-button { - background: #fb6340!important; -} - -[data-page="admin-system-reboot"] p>span { - position: relative; - top: .1rem; - left: 1rem; -} - -[data-page="admin-vpn-passwall"] h4 { - background: transparent; -} - -#cbi-samba [data-tab="template"] .cbi-value-title { - width: auto; - padding-bottom: .6rem; -} - -.controls { - margin: .5em 1rem 1em!important; -} - -.controls>*>.btn:not([aria-label$="page"]) { - flex-grow: initial!important; - margin-top: .25rem; -} - -.controls>#pager>.btn[aria-label$="page"] { - font-size: 1.4rem; - font-weight: 700; -} - -.controls>*>label { - margin-bottom: .2rem; -} - -[data-page="admin-system-opkg"] div.btn { - line-height: 3; - display: inline; - padding: .3rem .6rem; -} - -[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container { - margin-top: 2rem; - padding-top: .1rem; -} - -[data-page="admin-system-opkg"] #maincontent>.container { - margin: 0 1.25rem 1rem; -} - -.td.version,.td.size { - white-space: normal!important; - word-break: break-word; -} - -[data-page="admin-system-crontab"] #view p { - margin-bottom: 1rem; -} - -[data-page="admin-system-flash"] .cbi-map-tabbed { - border-radius: .375rem; -} - -[data-page="admin-system-flash"] legend { - display: block!important; - font-size: 1.2rem; - width: 100%; - border-bottom: 1px solid rgba(0,0,0,0.05); - line-height: 1.5; - margin-bottom: 0rem; - letter-spacing: .1rem; - color: #32325d; - font-weight: 700; - padding: 1rem 0 1rem 1.5rem; -} - -[data-page="admin-system-flash"] .cbi-section-descr { - font-weight: 600; - color: #525f7f; - padding: 1rem 0 1rem 1.5rem; -} - -[data-page="admin-system-flash"] .modal label>input[type="checkbox"] { - top: -0.35rem; -} - -[data-page="admin-system-flash"] .modal .btn { - white-space: normal!important; -} - -#cbi-wireless>#wifi_assoclist_table>.tr { - box-shadow: inset 1px -1px 0 #ddd,inset -1px -1px 0 #ddd; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.placeholder>.td { - right: 33px; - bottom: 33px; - left: 33px; - border-top: thin solid #ddd!important; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.table-titles { - box-shadow: inset 1px 0 0 #ddd,inset -1px 0 0 #ddd; -} - -#cbi-wireless>#wifi_assoclist_table>.tr.table-titles>.th { - border-bottom: thin solid #ddd; - box-shadow: 0 -1px 0 0 #ddd; -} - -#wifi_assoclist_table>.tr>.td[data-title="RX Rate / TX Rate"] { - width: 23rem; -} - -[data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem 0!important; -} - -#iptables { - margin: 0; -} - -.Firewall form { - box-shadow: none; - margin: 2rem 2rem 0 0; - padding: 0; -} - -#cbi-firewall-redirect table *,#cbi-network-switch_vlan table *,#cbi-firewall-zone table * { - font-size: small; -} - -#cbi-firewall-redirect table input[type="text"],#cbi-network-switch_vlan table input[type="text"],#cbi-firewall-zone table input[type="text"] { - width: 5rem; -} - -#cbi-firewall-redirect table select,#cbi-network-switch_vlan table select,#cbi-firewall-zone table select { - min-width: 3.5rem; -} - -#cbi-network-switch_vlan .th,#cbi-network-switch_vlan .td { - flex-basis: 12%; -} - -[data-page="admin-network-firewall-custom"] #view p,[data-page="admin-status-routes"] #view p { - margin-bottom: 1rem; - padding: 0 1.5rem; -} - -[data-page="admin-network-firewall-custom"] #view p textarea,[data-page="admin-status-routes"] #view p textarea { - border-radius: .375rem; - padding: 1rem; -} - -#applyreboot-container { - margin: 2rem; -} - -#applyreboot-section { - line-height: 300%; - margin: 2rem; -} - -.OpenVPN a { - line-height: initial!important; -} - -.commandbox { - width: 24%!important; - border-bottom: thin solid #ccc; - background: #eee; - box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05); - margin: 10px 0 0 10px!important; - padding: .5rem 1rem; -} - -.commandbox h3 { - line-height: normal!important; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin: 6px 0!important; -} - -.commandbox div { - left: auto!important; -} - -.commandbox code { - position: absolute; - overflow: hidden; - max-width: 60%; - margin-left: 4px; - white-space: nowrap; - text-overflow: ellipsis; - padding: 2px 3px; -} - -.commandbox code:hover { - overflow-y: auto; - max-height: 50px; - white-space: normal; -} - -.commandbox p:first-of-type { - margin-top: -6px; -} - -.commandbox p:nth-of-type(2) { - margin-top: 2px; -} - -#command-rc-output .alert-message { - line-height: 1.42857143; - position: absolute; - top: 40px; - right: 32px; - max-width: 40%; - animation: anim-fade-in 1.5s forwards; - word-break: break-word; - opacity: 0; - margin: 0; -} - -input[type="checkbox"] { - appearance: none!important; - -webkit-appearance: none!important; - border: 1px solid #dee2e6; - width: 16px!important; - height: 16px!important; - cursor: pointer; - transition: all .2s; - margin: 1rem 0 0; - padding: 0; -} - -input[type="checkbox"]:checked { - border: 1px solid var(--primary); - background-image: url('data:image/svg+xml,%3csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3e%3cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3e%3c/svg%3e')!important; - background-color: var(--primary); - background-size: 70%; - background-repeat: no-repeat; - background-position: center; -} - -.fb-container .cbi-button { - height: auto!important; -} - -#cbi-usb_printer-printer em { - display: block; - text-align: center; - padding: 1rem; -} - -pre.command-output { - padding: 1.5rem; -} - -[data-page="admin-nlbw-display"] .cbi-section[data-tab="export"] { - padding: 1.5rem!important; -} - -[data-page="admin-status-iptables"] .right { - margin-bottom: 0!important; -} - -.table[width="100%"],.th[width="100%"],.td[width="100%"],header,.main,.main .main-left .nav li.slide .slide-menu li:hover::after,.main .main-left .nav li.slide .slide-menu .active:hover::after,.cbi-section-table-row>.cbi-value-field .cbi-dropdown,.cbi-section-table-row>.cbi-value-field .cbi-input-select,.cbi-section-table-row>.cbi-value-field .cbi-input-text,.cbi-section-table-row>.cbi-value-field .cbi-input-password,.cbi-dropdown[open]>ul.dropdown>li>input.create-item-input:first-child:last-child,.cbi-dropdown .zonebadge,#cbi-firewall-zone .td,#cbi-network-switch_vlan .td { - width: 100%; -} - -.cbi-dropdown,select[multiple="multiple"],.alert .btn,.alert-message .btn { - height: auto; -} - -.login-page .login-container .login-form .brand:hover,header .fill .container .showSide:hover,.a-to-btn { - text-decoration: none; -} - -.login-page .login-container footer .luci-link,.cbi-dropdown[empty]>ul>li,.cbi-dropdown[optional][open]>ul.dropdown>li[placeholder],.cbi-dropdown[multiple][open]>ul.dropdown>li>form,#cbi-samba [data-tab="template"] .cbi-value-field,#cbi-firewall-zone .table,#cbi-network-switch_vlan .table { - display: block; -} - -.main-left::-webkit-scrollbar-thumb,.tabs::-webkit-scrollbar-thumb,.cbi-tabmenu::-webkit-scrollbar-thumb { - background-color: #f6f9fc; -} - -.main-left::-webkit-scrollbar-track,.tabs::-webkit-scrollbar-track,.cbi-tabmenu::-webkit-scrollbar-track { - background-color: #fff; -} - -.pull-left,.cbi-page-actions .cbi-button-link:first-child { - float: left; -} - -#xhr_poll_status *,.cbi-button-apply>ul.preview li,.cbi-button-apply>ul:first-child li { - color: #fff; -} - -.container .alert,.container .alert-message,.cbi-map-descr+fieldset { - margin-top: 1rem; -} - -.main .main-left .nav,.cbi-value-field>ul>li>label { - margin-top: .5rem; -} - -.main .main-left .nav>li>a:first-child,.main .main-left .nav li .menu { - border-radius: .375rem; - cursor: default; - display: block; - font-size: 1rem; - position: relative; - text-decoration: none; - transition: all .2s; - margin: .1rem .5rem; - padding: .675rem 0 .675rem 2.5rem; -} - -.main .main-left .nav>li>a:first-child.active,.main .main-left .nav li .menu.active { - background: var(--primary); - color: #fff; -} - -.main .main-left .nav>li>a:first-child.active::before,.main .main-left .nav>li>a:first-child:hover::before,.main .main-left .nav li .menu.active::before,.main .main-left .nav li .menu:hover::before { - color: #fff!important; -} - -.main .main-left .nav>li>a:first-child.active::after,.main .main-left .nav li .menu.active::after { - color: #fff!important; - transform: rotate(90deg); -} - -.main .main-left .nav>li>a:first-child:hover,.main .main-left .nav li .menu:hover { - background: var(--primary); - color: #fff; - cursor: pointer; -} - -.main .main-left .nav>li>a:first-child::before,.main .main-left .nav li .menu::before { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - color: var(--primary); - content: "\e915"; - font-family: argon!important; - font-style: normal; - font-variant: normal; - font-weight: 400; - left: .8rem; - line-height: 1; - padding-top: 3px; - position: absolute; - text-transform: none; - transition: all .3s; -} - -.main .main-left .nav li.slide,[data-page="admin-system-flash"] .cbi-value,[data-page="admin-network-dhcp"] .cbi-value { - padding: 0; -} - -.main .main-left .nav li.slide ul,.main>.main-left[style*="overflow: hidden"]>.nav>.slide>.menu::before,.tr.placeholder .td[data-title]::before,.cbi-dropdown>ul.preview,.cbi-button-apply>ul.preview,.cbi-dropdown>ul>li .hide-close,.cbi-dropdown[open]>ul.dropdown>li .hide-open,.hidden,.showSide,[data-page^="admin-system-commands"] .panel-title,[data-page^="command-cfg"] .mobile-hide,[data-page^="command-cfg"] .showSide { - display: none; -} - -.main .main-left .nav li.slide:hover,.main .main-left .nav li.slide .slide-menu li:hover,.main .main-left .nav li.slide .slide-menu .active:hover { - background: none; -} - -.cbi-section>h3:first-child,.cbi-section>h4:first-child,.cbi-section>p:first-child,[data-tab-title]>h3:first-child,[data-tab-title]>h4:first-child,[data-tab-title]>p:first-child,.cbi-section p { - padding: 1rem; -} - -table>tbody>tr>td,table>tbody>tr>th,table>tfoot>tr>td,table>tfoot>tr>th,table>thead>tr>td,table>thead>tr>th,.table>.tbody>.tr>.td,.table>.tbody>.tr>.th,.table>.tfoot>.tr>.td,.table>.tfoot>.tr>.th,.table>.thead>.tr>.td,.table>.thead>.tr>.th,.table>.tr>.td.cbi-value-field,.table>.tr>.th.cbi-section-table-cell,.uci-change-list var,.uci-change-list del,.uci-change-list ins,.cbi-section-remove { - padding: .5rem; -} - -.cbi-section-table-row .td,.center,.center::before { - text-align: center!important; -} - -div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n),.cbi-section .cbi-section-remove:nth-of-type(2n),.container>.cbi-section .cbi-section-node:nth-of-type(2n),.cbi-section[id] .cbi-section-remove:nth-of-type(4n+3),.cbi-section[id] .cbi-section-node:nth-of-type(4n+4),.cbi-tabcontainer>.cbi-value:nth-of-type(2n),.cbi-rowstyle-1 { - background-color: #f9f9f9; -} - -.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"],.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"] { - background-color: var(--primary); - border: thin solid var(--primary); - color: #fff!important; - font-weight: 400; -} - -.tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar { - height: 5px; - width: 1px; -} - -.tabs li[class~="active"] a,.tabs li:hover a,.cbi-tabmenu li[class~="cbi-tab"] a { - color: var(--primary); -} - -.tabs li a,.cbi-tabmenu li a { - color: #404040; - text-decoration: none; - padding: .5rem .8rem; -} - -.cbi-dropdown>ul>li .hide-open,.cbi-dropdown[open]>ul.dropdown>li .hide-close { - display: initial; -} - -.cbi-dropdown[open]>ul.dropdown>li label,.cbi-image-button { - margin-left: .5rem; -} - -.network-status-table,.network-status-table .ifacebox-body>div { - display: flex; - flex-wrap: wrap; -} - -[data-page="admin-system-reboot"] p,[data-page="admin-nlbw-backup"] form { - padding-left: 1.5rem; -} - -[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr,[data-page="admin-system-opkg"] h2 { - color: var(--gray-dark); - margin-left: 0; -} - -.cbi-tabmenu+.cbi-section,[data-page="admin-system-flash"] .cbi-section .cbi-section { - margin-top: 0; -} - -@keyframes anim-fade-in { - 100% { - opacity: 1; - } -} - -@media all and (-ms-high-contrast:none) { - .main>.main-left>.nav>.slide>.menu::before { - top: 30.25%; - } - - .main>.main-left>.nav>li:last-child::before { - top: 20%; - } - - .showSide::before { - top: -12px; - } -} - -@media screen and (max-width:1600px) { - header>.fill>.container>#logo { - margin: 0 2.5rem 0 .5rem; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - .btn:not(button),.cbi-button { - font-size: .8rem; - } - - .label { - padding: .2rem .6rem; - } - - .cbi-value-title { - width: 15rem; - padding-right: .6rem; - } - - .cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"] { - min-width: 18rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 9rem; - } - - .cbi-input-textarea { - font-size: small; - } - - .node-admin-status>.main fieldset li>a { - padding: .3rem .6rem; - } -} - -@media screen and (max-width:1366px) { - header>.fill>.container { - cursor: default; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - .tabs>li>a,.cbi-tabmenu>li>a { - padding: .2rem .8rem; - } - - .panel-title { - font-size: 1.1rem; - padding-bottom: 1rem; - } - - table { - font-size: .7rem!important; - width: 100%!important; - } - - .table .cbi-input-text { - width: 100%; - } - - .cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"],.cbi-value input[type="password"] { - min-width: 16rem; - } - - #cbi-firewall-zone .cbi-input-select { - min-width: 4rem; - } - - .main>.main-left>.nav>li,.main>.main-left>.nav>li>a,.main .main-left .nav>li>a:first-child,.main>.main-left>.nav>.slide>.menu,.main>.main-left>.nav>li>[data-title="Logout"] { - font-size: .9rem; - } - - .main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: .7rem; - } - - #modal_overlay { - top: 0rem; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table) { - display: block; - } - - [data-page="admin-network-firewall-forwards"] .table:not(.cbi-section-table),[data-page="admin-network-firewall-rules"] .table:not(.cbi-section-table),[data-page="admin-network-hosts"] .table,[data-page="admin-network-routes"] .table { - overflow-y: visible; - } - - .commandbox { - width: 32%!important; - } - - .btn:not(button),.cbi-button { - font-size: .8rem; - } -} - -@media screen and (max-width:1152px) { - header>.fill>.container>.brand { - position: relative; - } - - html,.main { - overflow-y: visible; - } - - .main>.loading>span { - top: 25%; - } - - .main-left { - width: calc(0% + 13rem); - } - - .main-right { - width: calc(100% - 13rem); - } - - body:not(.logged-in) .showSide { - visibility: hidden; - width: 0; - margin: 0; - } - - .cbi-value-title { - width: 12rem; - padding-right: 1rem; - } - - .cbi-value-field .cbi-dropdown,.cbi-value-field .cbi-input-select,.cbi-value input[type="text"] { - width: 16rem; - min-width: 16rem; - } - - .cbi-value input[name^="pw"],.cbi-value input[data-update="change"]:nth-child(2) { - width: 13rem!important; - min-width: 13rem; - } - - #diag-rc-output>pre,#command-rc-output>pre,[data-page="admin-services-wol"] .notice code { - font-size: 1rem; - } - - .Interfaces .table { - overflow-x: hidden; - } - - #packages.table { - display: grid; - } - - .tr { - display: flex; - flex-direction: row; - flex-wrap: wrap; - } - - .Overview .table[width="100%"]>.tr { - flex-wrap: nowrap; - } - - .tr.placeholder { - border-bottom: thin solid #ddd; - } - - .tr.placeholder>.td,#cbi-firewall .tr>.td,#cbi-network .tr:nth-child(2)>.td,.cbi-section #wifi_assoclist_table .tr>.td { - border-top: 0; - } - - .th,.td { - display: inline-block; - align-self: flex-start; - flex: 2 2 10%; - text-overflow: ellipsis; - word-wrap: break-word; - } - - .td select,.td input[type="text"] { - width: 100%; - word-wrap: normal; - } - - .td [data-dynlist]>input,.td input.cbi-input-password { - width: calc(100% - 1.5rem); - } - - .td[data-type="button"],.td[data-type="fvalue"] { - flex: 1 1 12.5%; - text-align: left; - } - - .th.cbi-value-field,.td.cbi-value-field,.th.cbi-section-table-cell,.td.cbi-section-table-cell { - flex-basis: auto; - padding-top: 1rem; - } - - .cbi-section-table-row { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: space-between; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - } - - .td.cbi-value-field,.cbi-section-table-cell { - display: inline-block; - flex: 10 10 auto; - flex-basis: 50%; - text-align: center; - } - - .td.cbi-section-actions { - vertical-align: bottom; - } - - .tr[data-title]::before,.tr.cbi-section-table-titles.named::before { - font-size: .9rem; - display: block; - flex: 1 1 100%; - border-bottom: thin solid rgba(0,0,0,0.26); - background: #e9ecef; - } - - .cbi-button+.cbi-button { - margin-left: 0; - } - - .td.cbi-section-actions>*>*,.td.cbi-section-actions>*>form>* { - margin: 2.1px 3px; - } - - .Firewall form { - position: static!important; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - margin: 0 0 2rem; - padding: 2rem; - } - - .Firewall form input { - width: 100%!important; - margin: 1rem 0 0; - } - - .Firewall .center,.Firewall .center::before { - text-align: left!important; - } - - .commandbox { - width: 100%!important; - margin-left: 0!important; - } - - .btn:not(button),.cbi-button { - font-size: .8rem; - } - - header>.fill>.container>#logo,.tr.table-titles,.tr.cbi-section-table-titles,.tr.cbi-section-table-descr { - display: none; - } - - .node-main-login>.main .cbi-value-title,.td[data-title],[data-page^="admin-status-realtime"] .td[id] { - text-align: left; - } - - .table,.td[data-title]::before { - display: block; - } -} - -@media screen and (max-width:768px) { - .cbi-progressbar::after { - font-size: .5rem; - line-height: 1.5; - } - - .main-left { - position: fixed; - z-index: 100; - width: 0; - } - - .main-right { - width: 100%; - } - - .showSide { - position: relative; - z-index: 99; - display: inline-block!important; - padding: .1rem; - } - - .showSide::before { - font-family: argon!important; - font-style: normal!important; - font-weight: 400!important; - font-variant: normal!important; - text-transform: none!important; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - content: "\e20e"; - font-size: 1.7rem; - } - - header>.fill>.container>.brand { - display: inline-block; - } - - body,.main>.main-left>.nav>.slide>.slide-menu>li>a { - font-size: .8rem; - } -} - -@media screen and (max-width:600px) { - #maincontent>.container { - margin: 0 1rem 1rem; - } - - .cbi-value-title { - text-align: left; - } - - [data-page="admin-system-flash"] .cbi-value { - padding: 0 1rem; - } - - [data-page="admin-network-dhcp"] [data-tab-active="true"] { - padding: 1rem!important; - } - - .cbi-dynlist p { - padding: .5rem 1rem; - } - - body { - overflow-x: hidden; - } - - .node-main-login .main .main-right #maincontent .container .cbi-map .cbi-section .cbi-section-node .cbi-value .cbi-value-field { - width: 16rem; - } - - .tabs::-webkit-scrollbar,.cbi-tabmenu::-webkit-scrollbar { - width: 0px; - height: 0px; - } - - .cbi-value-field,.cbi-value-description { - display: block!important; - padding-left: 0!important; - padding-right: 0!important; - } - - [data-page="admin-system-admin-password"] .cbi-value-field { - display: table-cell!important; - } - - .modal.cbi-modal { - max-width: 100%; - max-height: none; - } - - .modal { - display: flex; - align-items: center; - flex-wrap: wrap; - width: 100%; - min-width: 270px; - max-width: 600px; - min-height: 32px; - border-radius: 3px!important; - background: #fff; - box-shadow: 0 2px 2px 0 rgba(0,0,0,0.16),0 0 2px 0 rgba(0,0,0,0.12); - margin: 5em auto; - padding: 1em; - } - - .cbi-dropdown[open]>ul.dropdown { - left: .2rem!important; - right: 0!important; - margin-bottom: 1rem; - } - - .mobile-hide,.node-main-login footer { - display: none; - } - - [data-page="admin-system-flash"] legend,[data-page="admin-system-flash"] .cbi-section-descr { - padding: 1rem 0 1rem 1rem; - } -} - -@media screen and (min-width:600px) { - ::-webkit-scrollbar { - width: 10px; - height: 10px; - } - - ::-webkit-scrollbar,::-webkit-scrollbar-corner { - background: transparent; - } - - ::-webkit-scrollbar-thumb { - background: #9e9e9e; - } - - ::-webkit-scrollbar-thumb:hover { - background: #757575; - } - - ::-webkit-scrollbar-thumb:active { - background: #424242; - } -} - -@media screen and (max-width:480px) { - .mobile-hide { - display: none; - } - - .login-page .login-container { - margin-left: 0rem!important; - width: 100%; - } - - .login-page .login-container .login-form .form-login .input-group::before { - color: #525461; - } - - .login-page .login-container .login-form .form-login .input-group input { - color: #525461; - border-bottom: var(--white) 1px solid; - border-radius: 0; - } -} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/dark.css b/rooter/ext-rooter-basic/files/www/luci-static/css/dark.css deleted file mode 100644 index 885b575..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/css/dark.css +++ /dev/null @@ -1 +0,0 @@ -body{background:#1e1e1e;color:#CCC}.login-page .login-container .login-form .form-login .input-group input{background-color:transparent!important;color:#adb5bd;border-bottom:#adb5bd 1px solid!important;border-radius:0!important;border-top:none!important;border-left:none!important;border-right:none!important;box-shadow:none}.login-page .login-container .login-form .form-login .cbi-button-apply:hover,.login-page .login-container .login-form .form-login .cbi-button-apply:focus{opacity:.9}.main .main-left{background-color:#333!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.15)}.main .main-left .nav .slide .slide-menu li a:hover{background:none!important}.main .main-left .nav li a{color:#CCC!important}.main .main-left::-webkit-scrollbar-thumb{background-color:#252526!important}h2{color:#ccc;background:#333}h3{color:#ccc;border-bottom:0;background:#333}a:-webkit-any-link{cursor:pointer;color:var(--dark-primary)}input:-webkit-autofill{background-color:#3c3c3c!important}.cbi-value-field .cbi-input-apply,.cbi-button-apply,.cbi-button-edit{color:#fff!important;background-color:var(--dark-primary)!important;border-color:var(--dark-primary)!important}.cbi-section{background:none;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.panel-title{color:#ccc;background-color:#333;border-bottom:0px}table>tbody>tr>td,table>tfoot>tr>td,table>thead>tr>td{color:#ccc;border-top:1px solid #252526}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last{line-height:1.8em}.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"]{border:1px solid #999!important;background-color:transparent!important}tr>td,tr>th,.tr>.td,.tr>.th,.cbi-section-table-row::before,#cbi-wireless>#wifi_assoclist_table>.tr:nth-child(2){border-top:0}.cbi-section>h3:first-child,.panel-title,h3{color:#ccc;border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.cbi-progressbar{position:relative;min-width:170px;height:20px;border:thin solid #999;background:transparent;border-radius:.2rem;overflow:hidden;margin:6px 0}.cbi-button{color:#ccc!important;background-color:var(--dark-primary)}.cbi-section-node{background:none;border-radius:0 0 .375rem .375rem;padding:0rem}#content_syslog{box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}#iwsvg,#iwsvg2,#bwsvg{overflow:hidden;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e!important}.tabs>li[class~="active"],.tabs>li:hover{border-bottom:.18751rem solid var(--dark-primary);color:#ccc;background-color:#181819}.cbi-tabmenu>li{background:#2d2d2d}.cbi-tabmenu>li:hover{color:#ccc;background:#2d2d2d}.cbi-tabmenu>li[class~="cbi-tab"]{background-color:#181819}select,input{color:#ccc;background-color:transparent!important;border:1px solid #252526;box-shadow:none}select:not([multiple="multiple"]):focus,input:focus{outline:0;border-color:var(--dark-primary)!important}.cbi-section-node .cbi-value{padding:1rem 1rem .3rem}.ifacebox{background-color:none;border:1px solid #1e1e1e}.ifacebox-head{color:#666}.zonebadge strong{color:#333}.node-services-vssr .block{background-color:#3c3c3c!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}.node-services-vssr .status-bar{color:#ccc;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35);background-color:#1e1e1e}.node-services-vssr .cbi-section-table-row{color:#ccc;background-color:#3c3c3c!important;box-shadow:0 0 5px 0 rgba(0,0,0,0.35)}.node-services-vssr .cbi-section-table-row.fast{background:var(--dark-primary)!important;color:#fff}.node-services-vssr .incon:nth-child(2){border-right:#1e1e1e 1px solid}.cbi-input-find,.cbi-input-save,.cbi-button-add,.cbi-button-save,.cbi-button-find,.cbi-input-reload,.cbi-button-reload{color:#fff!important;background:#556B2F!important;border-color:#556B2F!important}.cbi-button-reset,.cbi-input-remove{color:#fff!important;background-color:#FF8C00!important;border-color:#FF8C00!important}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit.important,.cbi-button-apply.important,.cbi-button-reload.important,.cbi-button-action.important{border:1px var(--dark-primary) solid!important}.btn[value="Dismiss"],.cbi-button[value="Terminate"],.cbi-button[value="Reset"],.cbi-button[value="Disabled"],.cbi-button[onclick^="iface_reconnect"],.cbi-button[onclick="handleReset(event)"],.cbi-button-neutral[value="Disable"]{font-weight:400;color:#fff;border:thin solid #FF8C00!important;background-color:#FF8C00!important}#detail-bubble>div{border:1px solid #ccc;border-radius:2px;background:#252525;padding:5px}.network-status-table .ifacebox-body .ifacebadge{background-color:#252526;border-bottom:0;box-shadow:none}td>.ifacebadge,.td>.ifacebadge{background-color:var(--dark-primary);border:0}.cbi-section,.cbi-section-error,#iptables,.Firewall form,#cbi-network>.cbi-section-node,#cbi-wireless>.cbi-section-node,#cbi-wireless>#wifi_assoclist_table,[data-tab-title],[data-page^="admin-system-admin"]:not(.node-main-login) .cbi-map:not(#cbi-dropbear),[data-page="admin-system-opkg"] #maincontent>.container{background:#1e1e1e!important;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}div[style="width:100%;height:300px;border:1px solid #000;background:#fff"]{background:transparent!important}[data-page="admin-system-flash"] .modal label>input[type="checkbox"]{top:-0.35rem}[data-page="admin-system-flash"] .modal .btn{white-space:normal!important;background-color:#8FBC8F}[data-page="admin-system-flash"] .modal .alert-message{background-color:transparent!important}.cbi-button-positive{color:#fff!important;background-color:#556B2F!important}.logout:before{color:#adb5bd!important}.cbi-dropdown[open]{border-color:var(--dark-primary)!important}.cbi-dropdown[open]>ul.dropdown{background:#252526!important;color:#ccc!important;box-shadow:none;border:1px solid #3c3c3c!important}.cbi-dropdown[open]>ul.dropdown li{color:#ccc;border-bottom:1px solid #3c3c3c!important}.cbi-dropdown[open]>ul.dropdown>li[selected]{background-color:var(--dark-primary)!important;border-bottom:1px solid #3c3c3c!important}.cbi-dropdown[open]>ul.dropdown>li.focus{background:var(--dark-primary);outline:none}.cbi-page-actions .cbi-button-apply,.cbi-section-actions .cbi-button-edit,.cbi-button-edit,.cbi-button-apply,.cbi-button-reload,.cbi-button-action,.cbi-button[value="Submit"],.cbi-button[value="Upload"],.cbi-button[value$="Apply"],.cbi-button[onclick="addKey(event)"]{background:var(--dark-primary)!important}.btn.primary,.cbi-page-actions .cbi-button-save,.cbi-page-actions .cbi-button-apply+.cbi-button-save,.cbi-button-add,.cbi-button-save,.cbi-button-positive,.cbi-button-link,.cbi-button[value="Enable"],.cbi-button[value="Scan"],.cbi-button[value^="Back"],.cbi-button-neutral[onclick="handleConfig(event)"]{background:var(--dark-primary)}.login-page .login-container .login-form,.main .main-right,.cbi-rowstyle-2,.cbi-section-remove:nth-of-type(2n),.cbi-section-node:nth-of-type(2n),.modal{background-color:#1e1e1e}.login-page .login-container .login-form .brand,.login-page .login-container .login-form .form-login .input-group::before{color:#adb5bd}.login-page .login-container .login-form .form-login .cbi-button-apply,.notice,.cbi-value input[type="password"]+.cbi-button-neutral{background-color:var(--dark-primary)!important}header::after,header.bg-primary,select,.cbi-section-table-row{background-color:#1e1e1e!important}.main .main-left .sidenav-header .brand,.cbi-section em,.cbi-map-descr,.tabs>li[class~="active"]>a,.cbi-tabmenu>li>a,.tabs>li>a,.cbi-tabmenu>li>a:hover,.tabs>li>a:hover,.cbi-tabmenu li[class~="cbi-tab"] a,.cbi-value-title,.cbi-section-descr,.node-system-packages>.main table tr td:nth-last-child(1),.node-services-vssr .ssr-button,[data-page="admin-system-admin"] .cbi-map h2,[data-page="admin-system-admin-password"] .cbi-map h2,[data-page="admin-system-admin"] .cbi-map .cbi-map-descr,[data-page="admin-system-admin-password"] .cbi-map .cbi-map-descr,.cbi-dropdown .preview,[data-page="admin-system-flash"] legend{color:#ccc}.main .main-left .nav .slide .slide-menu .active a,.main .main-left .nav .slide .slide-menu li a{color:#CCC}.main .main-left .nav .slide .slide-menu .active a::after,.main .main-left .nav .slide .menu.active a::after{background-color:#CCC!important}.main .main-left .nav .slide .menu.active,.main .main-left .nav li a:hover{background-color:var(--dark-primary)!important;color:#CCC!important}.main .main-left::-webkit-scrollbar-track,.ifacebox-body,fieldset[id^="cbi-apply-"],.ifacebadge{background-color:#333}div>table>tbody>tr:nth-of-type(2n),div>.table>.tr:nth-of-type(2n),fieldset>table>tbody>tr:nth-of-type(2n),.cbi-rowstyle-1,div>table>tbody>tr:nth-of-type(2n),div>.table>.tbody>.tr:nth-of-type(2n),.tabs,.cbi-tabcontainer>.cbi-value:nth-of-type(2n){background-color:#252526}#swaptotal>div>div,#swapfree>div>div,#memfree>div>div,#membuff>div>div,#conns>div>div,#memtotal>div>div,.node-system-packages>.main .cbi-section-node:first-child .cbi-value-last div[style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080"] div,.cbi-progressbar div,.ifacebox-head.active{background-color:#32325d!important}#swaptotal>div>div>div>small,#swapfree>div>div>div>small,#memfree>div>div>div>small,#membuff>div>div>div>small,#conns>div>div>div>small,#memtotal>div>div>div>small,#cbi-dropbear h2,#cbi-dropbear .cbi-map-descr,#cbi-dropbear .cbi-map-descr abbr,#cbi-rc h2,#cbi-rc .cbi-map-descr,#cbi-distfeedconf h2,#cbi-distfeedconf .cbi-map-descr,#cbi-customfeedconf h2,#cbi-customfeedconf .cbi-map-descr,#cbi-download h2,#cbi-filelist h2,.node-services-vssr .block h4,[data-page="admin-system-opkg"] h2{color:#ccc!important}table>tbody>tr>th,table>tfoot>tr>th,table>thead>tr>th,#cbi-wireless .td,#cbi-network .tr:first-child>.td,.table[width="100%"]>.tr:first-child>.td,[data-page="admin-network-diagnostics"] .tr>.td,.tr.table-titles>.th,.tr.cbi-section-table-titles>.th{background-color:#252526;border-bottom:#000 1px solid!important}h4,.cbi-section-table .cbi-section-table-titles .cbi-section-table-cell{background-color:#1e1e1f}abbr,div.cbi-value var,td.cbi-value-field var{color:#5e72e4}.cbi-value-field>ul>li .ifacebadge,.zonebadge>.ifacebadge{background-color:#3c3c3c}.cbi-input-textarea,#syslog,#diag-rc-output>pre{background-color:#1e1e1e;color:#ccc}#xhr_poll_status>.label.success,header .fill .status span[data-style="active"]{background-color:#556B2F!important;color:#ccc!important}.btn.danger,.cbi-section-remove>.cbi-button,.cbi-button-remove,.cbi-button-reset,.cbi-button-negative,.cbi-button[value="Stop"],.cbi-button[value="Kill"],.cbi-button[onclick="reboot(this)"],.cbi-button-neutral[value="Restart"],[data-page="admin-system-flash"] .modal .danger{background-color:#FF8C00!important;border:thin solid #FF8C00!important}.btn,button,select,input,.cbi-dropdown,.cbi-dynlist>.item>span{border:1px solid #3c3c3c!important}@media screen and (max-width:480px){.node-status-iptables>.main div>.cbi-map>form{background-color:#1e1e1e;box-shadow:0 0 .5rem 0 rgba(0,0,0,0.35)}} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css b/rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css deleted file mode 100644 index 20dd22e..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/css/fonts.css +++ /dev/null @@ -1 +0,0 @@ -@font-face{font-family:argon;src:url(../fonts/argon.eot?u6kthm#iefix) format('embedded-opentype'),url(../fonts/argon.ttf?u6kthm) format('truetype'),url(../fonts/argon.woff?u6kthm) format('woff'),url(../fonts/argon.svg?u6kthm#argon) format('svg');font-weight:400;font-style:normal;font-display:block}[class^="icon-"],[class*=" icon-"]{font-family:argon!important;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-expand_more:before{content:"\e20b"}.icon-menu:before{content:"\e20e"}.icon-favorite:before{content:"\e291"}.icon-spinner:before{content:"\e603"}.icon-delete:before{content:"\e900"}.icon-edit:before{content:"\e901"}.icon-use:before{content:"\e902"}.icon-loading:before{content:"\e903"}.icon-switch:before{content:"\e904"}.icon-error:before{content:"\e905"}.icon-dashboard:before{content:"\e906"}.icon-logout:before{content:"\e907"}.icon-Network:before{content:"\e908"}.icon-services:before{content:"\e909"}.icon-system:before{content:"\e90a"}.icon-vpn:before{content:"\e90b"}.icon-storage:before{content:"\e90c"}.icon-statistics:before{content:"\e90d"}.icon-hello-world:before{content:"\e90e"}.icon-angle-right:before{content:"\e90f"}.icon-password:before{content:"\e910"}.icon-user:before{content:"\e971"}.icon-question:before{content:"\f059"}.icon-docker:before{content:"\e911"}.icon-control:before{content:"\e912"}.icon-statistics1:before{content:"\e913"}.icon-asterisk:before{content:"\e914"}.icon-app:before{content:"\e915"} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css b/rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css deleted file mode 100644 index 43786a7..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/css/pure-min.css +++ /dev/null @@ -1 +0,0 @@ -html{line-height:1.15;-webkit-text-size-adjust:100%;font-family:sans-serif}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}abbr[title]{border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;white-space:normal;padding:0}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}.hidden,[hidden]{display:none!important}.pure-img{max-width:100%;height:auto}.pure-g{letter-spacing:-.31em;text-rendering:optimizespeed;font-family:FreeSans,Arimo,"Droid Sans",Helvetica,Arial,sans-serif;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-line-pack:start;align-content:flex-start}.pure-g [class*=pure-u]{font-family:sans-serif}.pure-u-1-24{width:4.1667%}.pure-u-1-12,.pure-u-2-24{width:8.3333%}.pure-u-1-8,.pure-u-3-24{width:12.5%}.pure-u-1-6,.pure-u-4-24{width:16.6667%}.pure-u-1-5{width:20%}.pure-u-5-24{width:20.8333%}.pure-u-7-24{width:29.1667%}.pure-u-1-3,.pure-u-8-24{width:33.3333%}.pure-u-3-8,.pure-u-9-24{width:37.5%}.pure-u-2-5{width:40%}.pure-u-10-24,.pure-u-5-12{width:41.6667%}.pure-u-11-24{width:45.8333%}.pure-u-13-24{width:54.1667%}.pure-u-14-24,.pure-u-7-12{width:58.3333%}.pure-u-3-5{width:60%}.pure-u-15-24,.pure-u-5-8{width:62.5%}.pure-u-16-24,.pure-u-2-3{width:66.6667%}.pure-u-17-24{width:70.8333%}.pure-u-19-24{width:79.1667%}.pure-u-4-5{width:80%}.pure-u-20-24,.pure-u-5-6{width:83.3333%}.pure-u-21-24,.pure-u-7-8{width:87.5%}.pure-u-11-12,.pure-u-22-24{width:91.6667%}.pure-u-23-24{width:95.8333%}.pure-button{display:inline-block;line-height:normal;white-space:nowrap;vertical-align:middle;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:inherit;font-size:100%;color:rgba(0,0,0,.8);border:none transparent;background-color:#e6e6e6;text-decoration:none;border-radius:2px;padding:.5em 1em}.pure-button::-moz-focus-inner{border:0;padding:0}.pure-button-group{letter-spacing:-.31em;text-rendering:optimizespeed}.pure-button-group .pure-button{letter-spacing:normal;word-spacing:normal;vertical-align:top;text-rendering:auto;border-radius:0;border-right:1px solid rgba(0,0,0,.2);margin:0}.pure-button-hover,.pure-button:focus,.pure-button:hover{background-image:linear-gradient(transparent,rgba(0,0,0,.05) 40%,rgba(0,0,0,.1))}.pure-button:focus{outline:0}.pure-button-active,.pure-button:active{-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;box-shadow:0 0 0 1px rgba(0,0,0,.15) inset,0 0 6px rgba(0,0,0,.2) inset;border-color:#000}.pure-button-disabled,.pure-button-disabled:active,.pure-button-disabled:focus,.pure-button-disabled:hover,.pure-button[disabled]{border:none;background-image:none;opacity:.4;cursor:not-allowed;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.pure-button-primary,.pure-button-selected,a.pure-button-primary,a.pure-button-selected{background-color:#0078e7;color:#fff}.pure-button-group .pure-button:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.pure-button-group .pure-button:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px;border-right:none}.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form select,.pure-form textarea{display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;vertical-align:middle;-webkit-box-sizing:border-box;box-sizing:border-box;padding:.5em .6em}.pure-form input:not([type]){display:inline-block;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 3px #ddd;box-shadow:inset 0 1px 3px #ddd;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;padding:.5em .6em}.pure-form input[type=color]{padding:.2em .5em}.pure-form input[type=checkbox]:focus,.pure-form input[type=file]:focus,.pure-form input[type=radio]:focus{outline:1px auto #129fea}.pure-form .pure-checkbox,.pure-form .pure-radio{display:block;margin:.5em 0}.pure-form input[readonly],.pure-form select[readonly],.pure-form textarea[readonly]{background-color:#eee;color:#777;border-color:#ccc}.pure-form input:focus:invalid,.pure-form select:focus:invalid,.pure-form textarea:focus:invalid{color:#b94a48;border-color:#e9322d}.pure-form input[type=checkbox]:focus:invalid:focus,.pure-form input[type=file]:focus:invalid:focus,.pure-form input[type=radio]:focus:invalid:focus{outline-color:#e9322d}.pure-form select{height:2.25em;border:1px solid #ccc;background-color:#fff}.pure-form label{margin:.5em 0 .2em}.pure-form fieldset{border:0;margin:0;padding:.35em 0 .75em}.pure-form legend{display:block;width:100%;margin-bottom:.3em;color:#333;border-bottom:1px solid #e5e5e5;padding:.3em 0}.pure-form-aligned textarea{vertical-align:top}.pure-form-aligned .pure-control-group{margin-bottom:.5em}.pure-form-aligned .pure-control-group label{text-align:right;display:inline-block;vertical-align:middle;width:10em;margin:0 1em 0 0}.pure-form-aligned .pure-controls{margin:1.5em 0 0 11em}.pure-form .pure-input-rounded,.pure-form input.pure-input-rounded{border-radius:2em;padding:.5em 1em}.pure-form .pure-group fieldset{margin-bottom:10px}.pure-form .pure-group input,.pure-form .pure-group textarea{display:block;border-radius:0;position:relative;top:-1px;margin:0 0 -1px;padding:10px}.pure-form .pure-group input:focus,.pure-form .pure-group textarea:focus{z-index:3}.pure-form .pure-group input:first-child,.pure-form .pure-group textarea:first-child{top:1px;border-radius:4px 4px 0 0;margin:0}.pure-form .pure-group input:first-child:last-child,.pure-form .pure-group textarea:first-child:last-child{top:1px;border-radius:4px;margin:0}.pure-form .pure-group input:last-child,.pure-form .pure-group textarea:last-child{top:-2px;border-radius:0 0 4px 4px;margin:0}.pure-form .pure-group button{margin:.35em 0}.pure-form .pure-input-2-3{width:66%}.pure-form .pure-input-1-3{width:33%}.pure-form-message-inline{display:inline-block;padding-left:.3em;color:#666;vertical-align:middle;font-size:.875em}.pure-form-message{display:block;color:#666;font-size:.875em}.pure-menu{-webkit-box-sizing:border-box;box-sizing:border-box}.pure-menu-fixed{position:fixed;left:0;top:0;z-index:3}.pure-menu-item,.pure-menu-list{position:relative}.pure-menu-list{list-style:none;margin:0;padding:0}.pure-menu-item{height:100%;margin:0;padding:0}.pure-menu-heading,.pure-menu-link{display:block;text-decoration:none;white-space:nowrap}.pure-menu-horizontal{width:100%;white-space:nowrap}.pure-menu-children{display:none;position:absolute;left:100%;top:0;z-index:3;background-color:#fff;margin:0;padding:0}.pure-menu-horizontal .pure-menu-children{left:0;top:auto;width:inherit}.pure-menu-active>.pure-menu-children,.pure-menu-allow-hover:hover>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;padding:.5em 0}.pure-menu-horizontal .pure-menu-children .pure-menu-separator,.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-horizontal .pure-menu-children .pure-menu-separator{display:block;width:auto}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-disabled,.pure-menu-heading,.pure-menu-link{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-active>.pure-menu-link,.pure-menu-link:focus,.pure-menu-link:hover{background-color:#eee}.pure-menu-selected>.pure-menu-link,.pure-menu-selected>.pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;text-align:center;padding:1em 0}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;font-size:inherit;overflow:visible;border-width:0 0 0 1px;margin:0;padding:.5em 1em}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-horizontal td,.pure-table-horizontal th{border-bottom:1px solid #cbcbcb;border-width:0 0 1px}main,details,.pure-menu-item .pure-menu-item,.pure-menu-scrollable .pure-menu-list{display:block}pre,code,kbd,samp{font-family:monospace,monospace;font-size:1em}a,.pure-menu-disabled .pure-menu-link:hover,.pure-table td{background-color:transparent}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button,.pure-form select[multiple]{height:auto}template,[hidden],.pure-button-hidden{display:none}.opera-only :-o-prefocus,.pure-g,.opera-only :-o-prefocus,.pure-button-group{word-spacing:-.43em}.pure-u,.pure-u-1,.pure-u-1-1,.pure-u-1-12,.pure-u-1-2,.pure-u-1-24,.pure-u-1-3,.pure-u-1-4,.pure-u-1-5,.pure-u-1-6,.pure-u-1-8,.pure-u-10-24,.pure-u-11-12,.pure-u-11-24,.pure-u-12-24,.pure-u-13-24,.pure-u-14-24,.pure-u-15-24,.pure-u-16-24,.pure-u-17-24,.pure-u-18-24,.pure-u-19-24,.pure-u-2-24,.pure-u-2-3,.pure-u-2-5,.pure-u-20-24,.pure-u-21-24,.pure-u-22-24,.pure-u-23-24,.pure-u-24-24,.pure-u-3-24,.pure-u-3-4,.pure-u-3-5,.pure-u-3-8,.pure-u-4-24,.pure-u-4-5,.pure-u-5-12,.pure-u-5-24,.pure-u-5-5,.pure-u-5-6,.pure-u-5-8,.pure-u-6-24,.pure-u-7-12,.pure-u-7-24,.pure-u-7-8,.pure-u-8-24,.pure-u-9-24{display:inline-block;letter-spacing:normal;text-rendering:auto;vertical-align:top;word-spacing:normal}.pure-u-1-4,.pure-u-6-24,.pure-form .pure-input-1-4{width:25%}.pure-u-1-2,.pure-u-12-24,.pure-form .pure-input-1-2{width:50%}.pure-u-18-24,.pure-u-3-4,.pure-form .pure-input-3-4{width:75%}.pure-u-1,.pure-u-1-1,.pure-u-24-24,.pure-u-5-5,.pure-form .pure-input-1{width:100%}.pure-form input[type=color]:focus,.pure-form input[type=date]:focus,.pure-form input[type=datetime-local]:focus,.pure-form input[type=datetime]:focus,.pure-form input[type=email]:focus,.pure-form input[type=month]:focus,.pure-form input[type=number]:focus,.pure-form input[type=password]:focus,.pure-form input[type=search]:focus,.pure-form input[type=tel]:focus,.pure-form input[type=text]:focus,.pure-form input[type=time]:focus,.pure-form input[type=url]:focus,.pure-form input[type=week]:focus,.pure-form select:focus,.pure-form textarea:focus,.pure-form input:not([type]):focus{outline:0;border-color:#129fea}.pure-form input[type=color][disabled],.pure-form input[type=date][disabled],.pure-form input[type=datetime-local][disabled],.pure-form input[type=datetime][disabled],.pure-form input[type=email][disabled],.pure-form input[type=month][disabled],.pure-form input[type=number][disabled],.pure-form input[type=password][disabled],.pure-form input[type=search][disabled],.pure-form input[type=tel][disabled],.pure-form input[type=text][disabled],.pure-form input[type=time][disabled],.pure-form input[type=url][disabled],.pure-form input[type=week][disabled],.pure-form select[disabled],.pure-form textarea[disabled],.pure-form input:not([type])[disabled]{background-color:#eaeded;color:#cad2d3;cursor:not-allowed}.pure-form-stacked input[type=color],.pure-form-stacked input[type=date],.pure-form-stacked input[type=datetime-local],.pure-form-stacked input[type=datetime],.pure-form-stacked input[type=email],.pure-form-stacked input[type=file],.pure-form-stacked input[type=month],.pure-form-stacked input[type=number],.pure-form-stacked input[type=password],.pure-form-stacked input[type=search],.pure-form-stacked input[type=tel],.pure-form-stacked input[type=text],.pure-form-stacked input[type=time],.pure-form-stacked input[type=url],.pure-form-stacked input[type=week],.pure-form-stacked label,.pure-form-stacked select,.pure-form-stacked textarea,.pure-form-stacked input:not([type]){display:block;margin:.25em 0}.pure-form-aligned input,.pure-form-aligned select,.pure-form-aligned textarea,.pure-form-message-inline,.pure-menu-horizontal .pure-menu-heading,.pure-menu-horizontal .pure-menu-item,.pure-menu-horizontal .pure-menu-separator{display:inline-block;vertical-align:middle}.pure-menu-horizontal .pure-menu-list,.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-table-odd td,.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered tbody>tr:last-child>td,.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0}@media all and (-ms-high-contrast:none),(-ms-high-contrast:active){table .pure-g{display:block}}@media only screen and (max-width :480px){.pure-form button[type=submit]{margin:.7em 0 0}.pure-form input:not([type]),.pure-form input[type=color],.pure-form input[type=date],.pure-form input[type=datetime-local],.pure-form input[type=datetime],.pure-form input[type=email],.pure-form input[type=month],.pure-form input[type=number],.pure-form input[type=password],.pure-form input[type=search],.pure-form input[type=tel],.pure-form input[type=text],.pure-form input[type=time],.pure-form input[type=url],.pure-form input[type=week],.pure-form label{margin-bottom:.3em;display:block}.pure-group input:not([type]),.pure-group input[type=color],.pure-group input[type=date],.pure-group input[type=datetime-local],.pure-group input[type=datetime],.pure-group input[type=email],.pure-group input[type=month],.pure-group input[type=number],.pure-group input[type=password],.pure-group input[type=search],.pure-group input[type=tel],.pure-group input[type=text],.pure-group input[type=time],.pure-group input[type=url],.pure-group input[type=week]{margin-bottom:0}.pure-form-aligned .pure-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.pure-form-aligned .pure-controls{margin:1.5em 0 0}.pure-form-message,.pure-form-message-inline{display:block;font-size:.75em;padding:.2em 0 .8em}} \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Medium-webfont.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Medium-webfont.woff deleted file mode 100644 index 9024faeb8f52376392077cb7f343b072e318daa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70200 zcmbSy1ym$Wmu2D5xI<%&yE`CeQ3PaXHK>1wpU zi3y8{erna9G1Xs#0{yZp_ET2jQ(FT7sPzBv`dmoT$iNt@ ztO7j~06@3&+3qtRpxc5(xnW?XXA1z((*OWqqyPZ8w<3@O-@w`N8vwwh_?h$1GT@58 zMjP9jSbb`~pLrnw01RnD@vWkXp2KHbHt5g1|1=~MOE=?B4G92frU!s%xavYw;F}uh z83F+3{GWM@pT-8I!_{T_DSm2>pE2R5k-$BCSvIwDbp6y)KD!G50Fb^1e-)>(v@!V1 zd-&XbsN+xln=AGtxRsvk=W;*(F7w-8gHQn@vDULP`qU^sxA)KII_`#lyNkB9ac~5H zfWUqBwG03dm;7K+`eJKuWD5X6KKyL=xo-i|2rt9gpC!nr0j6#FfPc&WOJusg<>-sW z<3BZ@JphP44HN(d00lDwfPfi;8Gm{v;0T}f;Q!Qol556UCXA=j!rjHg1{5?*@)`pb z6-5YI5tpvqFRoj2^ zd7Fc9D%1W?!SAZW0gT)R29I6%#SKs5Rblf;udv$WVV=8&xt%&0wCjZI^yh0z3#OZ8 zU>lIjqOGAxMH@&s9$z;(>Apszwps@?8hDu;P0R2SxnDaa<@B=0*exH0IXFEd2OZiC z1jB?ZgffOIbodqJmf670`f?zV2~j_hv7XJjSQ_DGV~&73$18jAn!#zJ#0@Mkalk)z z7FoSxaulC1qXZqQ2Wd%tnPhTE|86{)l|C1I@|8CA&Eo6HsWe{p+>k02!=mMgTFfjp zY~;koJLXr7y{HRr>LOWN$NRYNiB94&+3lo$M{Yh79uCu0zcf)&cpZP&EDI##-sb5g z!=*=)hnqfxXRSjk8F( zW8Bt|jd&YaDvItTGFg~m9cuSEO)#ME39F07F|Txb#oY|6lU?%IHY1*rz>W73(QO5BI>6^91v zrt)-pwcHQS_#Ig>nD97!e#o<1jP!6^o3$$&w8C3tIj>W&m*sp+Fpz24O;D>ZO#PjWMJIZqGQg6F#O&1Y z+UdM!<5-bV)HFgq07$K3A9d1?Su24pC}JP$XjRlIzmQuzwpgI?s(Mb%DyUpcJl0;% zS3X2PhVM}8DAJL?IEe(}uA8sJqPPd_9pxv^izvre)~nyT=g#;1CSbLiOM3EXv_}5O zMa?LaGYp4{-9=cZxtPuJlwTZkD!-U-E9qKoRbp44XjQt!z%<27J>jexa>L=QA_s>aggk5Aj#p{IzwdGvVN5;PNh2PD}> zVRq|uhwDN!B zy>SX^xDX#o))!(+?U)Yq34o9Gy?7DOsA9qCj5lPRyC$I~tR|%z_+nh17bdA_i$l5|Ttlc1Uq_MSRhNPxR9d;;uuU-)?wUHV5{T|`O1 zsoou^7r#yn80a_5-9O7|OQ!0EW(g7Q@YaE0&{1rwOFz|Dk(R)6QtIA`r5|7RzsdOC%n zlgRof&q+CP? RJLNkvR~;KUg2O;o9GHF6^hW%;QpboCCIy=YYxIDnx$!I#kF=#Z zVUkB*@vT|?&4K~tY5mRI23gdW?H(`mYvjteeC=KWP_9#od}XG^M5& z^ikwxfl(YED>U19jqEr3cy+OL}SV7oT)b-Olw- zW%tEKu3P&SiTyEaaaY;Q-9Qz1d?xl})tge$GbSA`4@^yDsGGIFd#R2OOeC3E=-<-( zzGKME5e&mX2EKk>lnthY~xxw16l<&rt?zurFx{Qg@mUYk2AFQ8nepxZd4q zWn3>i9b{rGmk(Fc{O~-m`)uDT^`$bn&C_Kg#>SVJQpI<_;X7!QS2-UN0`#}oY6Ju! zTdd$dC2{rOe2uMYfSC)?8RQ9^R#etl%x`GQ#%}`{`Ahz9X*D{`_mVL+lfq4#w!0{J z1HsP4B@pEV8|7%o(hCX7Yx1ckY$ALz0^2>_6LL)e$`K z2$yH6CNb5B5MK@op1z9fU=~${&n*rdoowGa*lmK2QRqO9^-ymqRYRcpp;W^s1bnFm zI|WV5`6}Fv{}Wb!*db=qr+-f|R*Vn1C^}@0zW)ewyZ?iuX0!i|!;Vj8EgJPfIwBf% zXQ%&>gOOL})1BJszu~z0EoqD*I0V zcr&Z^u3C{lj4n|M_$0`Ies-ss1<;_$-SS-Th6HHYyUwEB-*Ba z)I@~OGgo^*93W+xPfHeb`w`VQwBLIxXgAlH-)x}+YiEi5?u7pC1ai7Lezo_gjFdgv zQ#85#{nx_DWy!Z%&1je1Z3U3+UfEFC4l@V>Buwvb7WZewbZ~;elMvVz1|K{-JtRBA z@Mc>gJ3>r6$l|<*f$1Hi?OvqqUc+rcIxa0)%}0<53Vu!K>A1PN#?|O(0rJ&2^S%_- zBkR}Q{0vxd5Sw6_0Vh3Hx(Kc)usc_AH^V6HyqLHkg8)OhA;7NOCSNy}U#s(#A#ne2nB(jk0|Ig{HMzFe>28wFnSXtFK z%=~{k7)5bVVgoKt*l)(1oYo1r>=IEpq(hN$JE9|YdACJ-yLocwh$9dkLCm|Y*}HCPjqq;F&~E$nN>8;|r!6zckm7xhJBrA!xr zrB6XT2YU#B>UO_GUMdcsE`_cLn=Xcq{G^b^O`tXJ2`2VR=cU@RCOC-HXRx@Kl9|rmTjhv|)KDGTlQn z-WMkzPx_6|7Do7S6hpyx=gJTlz@p6mu#Y4g#Q=Ul@@i(%CTV$}(M;&7_>)N5$Gb` zL7znX4{;u#mec2WCOwDq^Q!iCcKH?nCXX=tZo~DS2ddSl8Yv3kw{!40x*_oS`37+a z|4%$mFuWP3cr%Z?5({r)8@J1ixaP%OiIVO_N(|y8MzB+1+bA+^gfRRkLUclDIuyXW z-6C3i0FzLd{sewUyL`--S!LZ!z<-@0yHh|ArMGfnzO(oR|GJuHz(4+zi~oNo?ZZDo zFzpO}m}Hl|;MytOu&AzjSoF7-y@44L@6LQt1&$Knu~CXX#FN@xL4aL`WX2TivOE4)9Y_U3w4? zm?g<>ZP0s^YRq3945vYQ^p=r}+!YEv;0(x8pa;GVe;kO$;|_dbhs%oMcgClK7}TIG zeyB?Js-pnos+FNFf>e1!_u~JJI+4oAYutG;WcAMk%g>%WwiIai!uM|O%*!)KsLuOG zf0SqRw+5-!Az5JPPYBYegcN+KQ6x;F5}qSTBb#9fE&RbE{o4#hI^I-0q%i0|C@s41 z$@JfdzEdm;^BX+^LnGYQ5aTPyFM^@V9V~C$J{N;WYq-tGKW&Vj?7yN1FK4iLzxIh4 zJetB0ME=QR^kn&O#8-x29|M;iDHjgm6qsPge^eMfseZ{0T$W(*qW4AXKgz-Jh5Zp@ ze5Lq>IB=PZ#f#P#tp6wt*A@DQo$;0I*Jl4^I+izTpUr#74t#?Hw1 z?I;bXm`hUxCd&9-h{KyoZV+5C%fZXWwdjw%q2HH3&-p6{-x$DC zkcUaGujeU9rg^`(rC3EzPw|R8!QDxnZ?G{jKE22{rXq(4nTb;VxOc%T0T<>Y^6KD< zyQY|4A2uReWfr54R@jWt#rSD2-2kmSV#D>D(0mcK;UskBPWa6Iw=<7iTUN2wrdd6z z?s|l)XoxouSr<(gZ5*1S`~O6W6MWv!WVzx#iu#!dLF|Vnb(q1kAEL#yzxi$wBi^e9 z{fh#adzQU{D6w**#)H`h{saN(-2q!w^IecWN5L+)CyqsTpg;u|jg!~5iuFy}iay!n z%XqHWd<4Fd7oFx8wP2t5KLk$i>#`2P4pgsc+^PF?##B3|z4XT`7y7(5zY(pjAhtiZ zx#(OQ_~b(0w$XxHa?;wNu>4eMsP$ZFxbE#j)b);_m&x?7&I|S8h_|-baXvKj;*TFnLHW18j-uH zqm{Y4qcW}!x}fZ;t%jVj5ihEokF)HIx@uha3K&DIeTDNL8J4Ea*A#9^VamSdJZ=}x?2AjV=%y@DWS_K9E&i?f4#3zhb%O?@|Hej716Z-z=vFcYQ8Xe!g zWW6UN)s4REvEiJt;iOMh@F~iA;2E~Yn+N!?O9qrw+Z^O_Lxr2~?N(>nVXEE!U%<4@ z^ob=(B2+r!e-Mz%#Po-WX^W|L^Iuq60Vv=MJC5m&5UL)--}TYK=fOxmIc?iFO`zQ(h>g! z8?h)NFifvpyJNs@V=i2`LbXCKHJ1F8HlW3*x)E+LsYe;a621H1$gdf>QMnuVWl0@e zBdB@-TtiZ?47^c7x2)fWe5&S*RtwaCltKAl6s~KD96=jYQ^3#&I+)bEB#&j`{~7#K z-3Z-?(USzGAIAC%B7 z{}+AHD@Xbpj@YOi)OaE*x2a-wtHYEhcCQerYJ9Pf)T^Le@5E?mszP&+_Qq+8eC~oQ ztXLO#0<21Vcm(c=^)Rpa@j%_Bn-ShglprmMgagfxr zrW~gYYC&gc0^L{cUi*@w0pdWdYaP^#G^pGs51vF+jYjx8)ilYs0D6W-fJL%f8N89G z8r`n~+OpzT#e#4nc)4(hK1@m|(g;d*-B)MjzESg(C2&+^)sSvMa15eqB)=eN8ev^R zP}l`wmcIW@`X?*UH2K>KE6Ndya0|FxC5R{y1F~P}0)repDsoClcfUDNX3e{Kxpr^^ zvFfTSmwynkDuQgecRrYgOr+|6nE1_}G(;VSQM_`lYB*Cr zXRX3z>}!W6kcsS_TisKj?08B}Y%YxKM8c`HQtqJ6n=&N`eDR3Nsbixg=>&1UP5c?3 z^G3F&OFBHXKtl?SPS95GTr<#=@rU|90g`_J5^mtuH*hF6+@<;yELt*Ai_jT${Uabs zKr&KB;8x!+#B|_xp+>m0h22~QDS{XqZjdSM57#d}3eZ`CmuUXv%qxh0eF?LFQ{#+< zX+W<3NvTi5svw1A&vmr;(JKcXWywMHD-Q`bXluBzq2H9Y=C7PAZ4o-BzI~Jw7ubfh z7Gz3k_Xt~{A%TJ~bcyx5pt&9`Ica-Ve%lt?e+)_U*DNjR56RFO`L7cS_RX|Gt4Oq@ zqJLxk`h=9n04(C`epRO3oo-6q?Pjo*hsQ)P#B!Bv`7Tfqts!iGGw z&$J8Gv?_iWPGLD0>IVOmRF59U1OL>GVXr4Fc@n^r@}ux3n#8JpdFoyMNi5EJ<+>-Tfj22b>YA)7`*QjSjMV;pgms}b%N$wS8;uo&vO8G*^E27p zR98Gf3p>2|2a)rT$@(eid15hksrCvV6U)Ya2BUV{FEfJaZHGs{=55FMzi6J1eZ zrl-otXvnLnZ(mm*jgdCtwvz?woAzu(=vG#}9o>VC_yieSRVTb}evP{~T7i1k>w9pH zmC%eQwN;D5Uo}OwM)Y6JaKuvl%7(m}`If}wR$VcP+;S9xDk=6g{$b_Vys_xF6zx0K z19Pbw*-G`Bu`TQY!}9#uekM%P1t?&QfZOOs%2g<67Z6$lR22Ig#NjRVJ z0fK->10)}~?P!5l#t=TptD$f2SpEN-s5h`XPNu`wQcF7+uT??VrVhp&u4jx|PBZj8 zR`aM&(}@*MKeRnIk_Oa0+f#Mr1ZqV&VHzwCco!;4nAPS-*KEmjY)mOV97opx$;umG zBx&z&rpywUZ|!LsaH(krCD<@(-^PvDj1J2CMPIB;FLIt7Os#99_r$w!kCKVs>}#W0 z4GAoUd4Vxr<%BP)LiaVlP7NZ51>z86`**cg-?ILwTbfkP+W|c%TctC6&pk|48V;?q zDurjf5L+(<9w=JV$*J}!B@&#K!q4R#H-*|tMLu{Ab;PQ)gjP!ntQPdcd6s@hH7Ze` z4Exk|b27Li=M|di{)+nT^S257{dA?dnM%Vk#xW27ND3y-yj}p;iZZQLDX<+(Fuha> zq7@%UxJCf&FDXU{K7Y+;mtXwm1TX&;#v+CxERfXB0ZG1MiFaA;frvm-UOCH1n!U#OW=)8>WJG$g_`pqpt7b7;g?2SwDPhpLZI zXnZ0zKe45w3;Z7pJD=bGAZ1iF8UM6L2ueIv}1 zR#l)#wkXYszFM;CqIiZye=S{-Q>aa(>f*pZp2=UYl@91M(}q0Os=wkrMJjLe>bA}s zeRv+(;d8Ghe87JB{bM=6ZT~XnL$NIP?aANGV)DDJcn9Ud*~9mqc07|TV%)P$o8wm+ z!W&M(V_J?WAJ}soUZKY{_F1kh`uq*?oATuZ2ggh&dLwi;b(&gXA7p@O=ztc@xxU?E zJEz~m`fa9u)0@l{%5ewa9aI}!vPY7any$RLdb>9amik;}Lx65K1zs0*NpPL$Cny$a zcLJ;eom30MUhjW7)Dd0Io$05A7i4YMpsFcU&wXjI7L`6?Eoau(M8J`yx3*!W`LY=t zy%|!VQvL-++Y$FDon>qFQE#CnZu#MUWi4zQ!fETVE3&U1<}WQQ=eM@8CfjjM)z(#$ zwIDmp!OxX6Zc68#pgV1=z9?N(^Fb}wZ}Gh;-@(-oV5ERB(&dKslkJv4f;`N34*0t1 zq1iq(@W0Yq8utR-#?Cg6^|MUF>O|)8JFr9-GzFT>&!M|zi~n2^>g~{g$@>Oh$>Lax z>Iou=W%*;k)D}JkLaNc5d+)~k^iB#G8EpJqcBQmawEpym??h*?D1xuyNiO{&<@@vl z_H|z%0rA7*`>aF@rsFk^J<|^PpqR|1fq`^ew5AX}AMBc7<|-w#*Deen+xgKhYT4^! zGt`+wSJbM^YfmPJKYnT0zhk2$Y@_50{6>*WsUR5YI{U1U(u~mA@8HtExPT*ma=4XO z5_bTJ3%? z?y*KZnmkP@s8>sbl-27-BAM76#zSWMb}?&)tg#g;2_sAt8L zJ9ulLV|hHJcaUX2eDoV)7N~%lK=n5l|1sgJH+`=tr!uT=<>(4J4OGiJjzy0nhmO7( z0*6X=5u3^Bar~R4D!1f$JqsQaDceR86K0!~#u)T;T4`^*$}tQ~HN^aN92nGhCANI0 zo8l8}x9J^aJhlce_?3+&DKp(k?P(`!r+^I3Df8>8ER#uUP%|FxNsG#-nwVR#{gy+l zD_TZnT-qq)p|G8Srjc7&5*seH2-KpGiqG=4%m!lf( zcSc4*-$tzwIz?*}R#gn6lB3=3MXtOQjyFZl4(-^6%`Hes8joA9%^r^j+vVpJM@SOd zWpFFTr5hTqxyEwKcy0VHmqjBRyR&Cz|2u<(eC%SBc~|Y))6Fk~sw(kAOPkz>tSXs( z7-vuV8uL2&+So0;U1@{Nht!AGWNdZMXOw#vms4ef^djkDcyoAj)Xl!LU6z-GASrrS zY%hB^{+jZs-cyt=A>63bQ~O_`O5M}C7o0`*Yf~Y)kwv>`B?LME(vMnO{JnT=6TLz z%{#9gTc3xrR6Wg(lrnbvJ^4z_(Zui; zdqx%7z0v~BhJ>;t`vv(*^>L-}7IQ`wtKHH_&4!dR42Qqs=%*-8sY10UQJ`6pz?(j< zDg_P;qSp9r4C85w`FdujyQwF1%h2`<7UBlk7_>i#G5GWi`~Zlz(3KX=jxILT7>DX$ z4-{hhw4BN)&ENh=TPnMAws~gs}2be!KK;OMTYth$r$|XfBOGT z_5Vd`H}K6O|D1EU`+ma0@OJ`v_QvzW;gS#P|4m}z&x7x~aXSMg+fqyelKoOw282Ve z6Bq1Vq?IuyWvCUJCk?#p4;>61o|8d-lzyBoEiESdm6P0d{0lh{0qlq!+goD6T6Q5G zhl73lh*LP;Zy^q1Xaw(%f6Bz7c(0#`T?i6A=7|k{MR7WeqZ%~cd+yELB#KR`;D6wB zULQV{<{gwpWmR#xcOL&M@M-!R9UMMo6ZS7%+wx_9y&J-z22yu|-!pr3yb9-Bok>fVWU^z={g@$uJ1*wwkg8~#aR*8OW@ zsT$ktYfK>s4x2%rvE@<(eER1c>MZLwHLy4q+X2YRC10(y8cAjqEB+y4M@!MabpF)4 z`_YX__QBdoJ<^j^u{5_ddAJ(ZS@G|*asweTg-OAqlXL6oH+usy>XS%EvXk^8#${x4*zM>7kR{Xg(IwpZO-Hip zu1mBsKIpyebzk~j;zRoVs~YvrtYlZ)M~nPB_X{~R>!bV)z7~-5ZS3;*AHiuIxaoyf z5zG_iw_h@c@?Nc-nq9*yWF10qXizMS_-sDxek=D@6FPR?zESSp>l91zR09Bp>5tX* zM4~gvyZ6m#=Bg3hh>mMjpP5&5 zw}^m1=;IbkxAFPaCPa^}+|4zyUBe8MsEjIt1rQ#|4`CnvD!N;veR}Uc#@|f{wMH2} zyRKfTo!Xn#Hh~+3Rg=xNH>B#G*9%U!*-jPj`F(@$jjeCyPf63v53Al)QAhES^rvM) zMRta*88e%##U5@;KJgcnJ=PB$&~!i%uJ(%qybWPqH-3dtzD`FQZ2XN8A+JqI+K#;s z9(9|CvFx;!BQ3CMhX6Jk-d$td<(QS^8d9TNixsm4;^)-nzX3voW~quw!?iLGFEjHjo*&Op45=Tx#-SVUwfYDlmbKt@hK#Ke(q6BzT3H`_qFfJ=0mIgi z3J7~kO(0{&vM#ZDSyJE}?G3&rU>oG(#t#9gn zo)Upz<*?5JH}NY}aVk!bK58nkB}>3&auHpNJh3tT7?QGNg5AS-^vJ(4Z#9N1I;h@C zTsqh==VqQ9%#YsBtU}@Q{Q@j^>T?PWdpRg|IVl#k)_a0Ipx4ahmSbzwib z6K?YBbh06cqqF^pQc- z_oCp8H+;9MTUhQ)eSdcUSd|6&bT%6Ty8SE0 zEF<>*%C@ty<%ID$#5kKl>bv(CZ%EfQ^{rJpLb(y#cnWv@;rBbU>OqevZIC&L1-*$g<#4{p_ZJFe;unN`DM z1alqyG+Fzd0vFxZYGKd2mZK*&P_OjM!&KgNtj3|1^Q~|cCy}a=WUbT^QdJi z@ym$s=?AGzX$P>yuGf4m)!@!h1;t2jO{B%i#KcD>ZTZ$2gK zypv}+9{qi3*)=0`c0>~WCmQ7CMdw8>3K&y_6(e z@IgY_&C=ZUp0N3TIij?JgE*~;7Pvo>c?pvE(okO)zjua5%Yi*dxPvZ0v&U&I5avs# z115eoRltpdsw1}Qw!Xo6&&gFlvFl?i)1Z^!hxKKvt6N)X1St{*vp+4b9w=&RzhNOm z;#A6@BkuvMF+)6kg-T1G7XD?7*y{w}_k9>ydZoG^r%Jm-zQ@cl&24r%d%v5E9hFJ@ zaORACOc}elY|b7#-rw;C5euZWB}*(NLea*kDdPkwV?0MtaU4j+ zYK?-Z(@GFQZ6)jAL`hy_Lvh!9;gwdR)mezZojH)Al;OUC_Sq7B-AU>5qS+?T(now5 z9-z<20r=ScvVUb(R>X1HfoZ#9Tijys-e=>I4uKi?#Wp1NC%2kOeZ5cf1^t=8O|;|l zt!dW`16||g{>LD{M86;>j50qA08 zPJZ|-W4$vnelG51C)or0h@G)eV=_!%&S={iQo=hU1WS%L8w<) z70@cm9N-^1l@Qg7OSaV0&?-~;Tdp61)+5QIC#N+B#fgI;kLsh5Pz=>9UyX z{|=RiKtJcaTkqE;a-Fm@h3O&J$uw+C9y!QSh4|p;Euf^*@C}aT$Rmz^Co=0k_ohsKMOBfuh%C`?-{UqQ zs_hx1t6N;+84R49UsgZyG@zP~uS|1~JR0tjf>)6`T1-)gk{V5UXCs5555nx-?49aU z`15XSqKY{QFWI}MD>i*bfS?RT9WbbC_Y-v-cJ$5Ry~;cLBmAT8Bi?6?5BQuPQ`H<%C>Pf2n`QSb2tk!$8yUR~VFx&orW$GwA;tUa z<;R%U+Jc#_iMNhekg+pn(A19TffJ9ghT;cFXN^dr1?il6QaIG*q&7{q&niqFauwgdAwe8PVXM_ha}`V)Wm3LQnEw$lU$#Cw z-nWnLVwW=aT?{8$Jg+nc2Fu|<8HtDYYcdcS0nnY~Es9`F_fG0&ohMZkV9H%@b zvr$WV3{zGtO6Zs)a7G$aW2v9*#-M#z*|~a7@sX*jCRn8<2cy^>UnN{IvUE>vA?J9$ z*9XvH^;Z6QPW=2_1A0I0=9Bv%ssR8 z5xpXcmetc;8yF<*OlZ|^g_tQgXLNchNsRv!eHlbJd#N<>^xmjF`8A67Wf7O$JYndy z-qT<(T|^{Zx-W!!F8-a(9njs5xw5(Gz~m5L4TJz3^aPdTEm*nR_hk1wK||Ok_hvM z9ia7ad%!*idUA{4>z!P}0l1}g1_Jt6`EM_i=%QVPEn2@?me&W7L>P4WTLblO<55ctS7*|yksOs>M>6<*+;oG6P>l7K?aajWoCixB&n=26Fa|@C;n}w%8*1 zyKRW)J!=!$8W((XMQDJs}BWOATgQRGPv zf~rk#AP0#^cp{kwBQ+HRZyCy5WiBEK9o#%#8tnY&@``4w&u2t+Fgb>AUPKyB6wRKR zt)3zn9L8U5?@2LuuU3=~3QxP&zgRjHPkSlR_daV@0`h+%q3M5a<1SE|tpWdc5=mZ88Qy37!z_ zu#5UJq`d8x?IrfBJy_f(@NLRK+(-~W<>yz})!@U6Rmvu#knKl$zzHU9V0*M9)U$GA zXG6=5d~q~hyZuqwvb0xcn-Ek!yr&}0WYw-SYQt-@h0MhHho;ppw2xBl znKFWri_8;$_LI-ScCQ0_KmRub^6>#cbj_IWaM4v1c>uVZSTD!5{%~gJS*H0RPRP#& zfdY-=4o{mad4U(Z!3{bqfP_pF;xA$8c}a;87UHijf+lAf@=aGiz>xf6e0;slC4TGR zqN6J-#nSm)gFY1N9ZehU zXo%_Uku(5BZhf0nn9oHGH_0$~U3~n>u-&XGxih93b%rS%4pLWDm|pp=mj1 zI4&gi8#YsGg3am76dwFfaU^~4KsYu5G{!d^1L8)>y-4Pmx$RmG2d%?giAO{&Oxg9b zE7-m^LC-H25bbfgD797WS zUw5(n_Jr=;V?YZoumaL-5D5N<&_!O*Q`1t)Q89nrI1(DMF7OvP6a-{7#*?bx0$W?c z>PriA09Z9vNUjy~Gq#Cvn0|FoN)5@#G;BP`SnV_QWINyhUmaq1Lpfug-gF1E(*ee)#2tZOJ= zb(P!eR@kP&J75K%i@vGZlj$EeD)FoOr^=#|U`yIlY2gchM57wYCB!1p4%dn&E9KM2 zLUKiAB+Sz!q{k;`pVSWKA?=R;up^@cLZ|cKs}Z9GETpCfsS~OMP9$cMJEzrN&&h65 zZ{GB3sJ8Pu%|FiUuzNnwkc-{7+e`N@E=o81(530H71*sh(4T+MY>!FaXKN=DsIr>< z%&uuUo9ujih5ADt73}p?((b%3EPx>j)J!HwkcAPL&SoLhp+JLd>9f~TOD!1*y^_1H zo(9ARMs8d+($I9PT1KG>F_TdLPMk%HNQ{z3@!f{IrI!nA3HQ^3S_T)1J=(0rrCB}V z?{m1;TyEq*%jJldw|}x#C*oDTMcf=I8RoU${1y3fU$OakTbH@gcs^a?lpe+LdUSUz zrlsCwvsxmZ9wn^lD@z~aOym9DLb{GY@V$9yy-UZgX&VGAtZa(b{k>&?R1$%=X^AJt zCLQI$7v#K)TjIebFe^+@Zo;VqWxt2e@XJJy);WWTd|i9Kl!>vvr&K*_uO-W2No)0w zVhSQo&RHS}3Jf4lpbXgowdNWV&;ZX;U2`j$An=wv>my|Xqi6FAtPCE=VL&&R9@{h85)%#~~}yQw3+ zhe#1Mc%00$**#h*>-*EYm8I~&oQtsi{rJV-ZLJuP?AA;rZsr$_XKi^I1Akjk`MR<-DF?J@jtyr9n+Oz$(8v}Z zlEGS%dNx^TgjmoQNE37I6jFAyqWv~Ye+bODrjIdjs~=gQsT8E7M!L zV@yAZnbaCd37&%yPyTs)X_QQP2SQcT!z4o(vsX=n)`UGs7`^E%>_R`blr$Szr_d+o zoDfAJs?q0VCk1Z|9jEoRcH^DahQ}ir*}G05bN7pj+w()&4T7G7mWpaMiDU#=5W!e( z)u{!+Tr_mAplPy6o8Kg7dU1a5 zFdao{w?{PA++PnXu?RH7aHO~9lHz&whx@x=9DU4OHu0zD*tnvObl(a<$}HW9zi7bh zYAL=V5cC-=1=?&mRHx6aTdK2U+&{-M)&^v4<76eaG;44Cz5Vrjutienl~g17ygOaY?}_~Ss3iqwa(k^O$fj3gzgcnJYY&=Bf}+u2 z0s2dO?M!W7%Ity{(&2rBnjX+aSR!zfxEPBOWX)xN*2Ehr*qxk~xOi7OZ4#GQ$19>Z z>I2zSE|>TD5{K%NG)>V-s`|DstlyGL%852)IE|AA8fBWB$<4q;MZ-cdZ7J-3I*@=3XBkJu zhXoE3=Zjp}bE)VIm6t%WsYyL8{&iGDTie*Fun;-}tT%%zzi`3m@HTuKiBXmx}$!sL9YXAB`>josh|ZI6}2+rxDOvnsBG>1@+9bS@T& z02Lj@kPX|A5YLb4_kF!I;FcMbLkU;jkm_Fd7HhY_@+Vwv9Ap5>77W?jE!a=A(0AG& zJ#p*e$uLPmCthF;4~pHA-3=YHc;A?Q(phsmoX%hMC2RM6`Qmy}*F^@O&J?fcd5_UT zv!kONnceO<*-qYH$vlLZ%9@v5`|%RJf!ESyw;v8W`D%ORWHjw>WUxQw6+ffISPrt+ zXG|z;dW2B;J#TVS=8Hco1E`Z;S^4H_95_|6>;rg3nDwdRt{{SBsetG1aO{^Udk~SgL_Q;r!EVIo*_R?!9qy9dKRFFV6k)-!VtG1MKE1Ugcr)y;QEp;#sSxRjEAhPbFW%9 zNNeJ(b7lA^zE7u(f4B&9n01%xf_tdO`#O*_d{-eVWs%r`m;OS1DJ>?tldMS&|BE24 z+&8ML{D#qsmtO8E8jbeMN@?tAQT%f0oate!`~;Br3p_~@N6hB1!m#f4I?VnAsolbt6;8th`JwZ)3@u*#<6S~EosSM?gNgpm0AZhC)Uo}FCr zZ-qZM8uz&BS6g!o^=V(}zzS-o(Msji;BK2ZOy!@qnElfQ)cn7#p6?$fCAcx#lE{xb7 ziC?Vi&;}!oVH3K^#NDFC<6JAWH7ERpHXSK$)V8RO;nfOlN_a`UQR*#-E9E1+>XCJ4 zQmjqsh}MPfGj~UwaZkbCf-a#&gHW*%egP}=hp1Bo*dYyEe@382IZ+|2Z%wXnYoA_+ zSI1=i^+$^(+4`%j1&UM?x01fE^#BV*DASThDdRBaR}3wb6jug`h}fRNsl_pNrM{vx zPYxw!iC7Q&ksP}|cfQMTig&x$ofC~hw&?ixcO0Hpy$vs|#UzAuhU%{C*`ujVRYyDi zd*4pOT~?W*%pbYeq3v?EFjhYeTnsH->e^4qQjbO^1Dh#4gk4Rmmnr@Lq`Tlx4$d_d zb3)=c(J2Lm40C>Eg-ocjC?r`XRj0<6$42#=vMfpI7EG`IXmMmf_ketk>_IZFPS9s;Lv`nD1)}j7DsB7Vy+d!9U z`nv8#`83m=;wRlE9AuyH%Fq)F4G)9xxQc)jD#-ByeO2X08N?h_nZfXOYmodSHgXY8 zy@rtHdSxzN?g5@%<1@3@iFYRwOJGXx=kiH(b(8X{P!VIr?+Q7nm<0_*@$v&5S;m; zYT5>t(r^1)IJS6b*}E`SX$@>4uo}}Z979J$$d4a*TOW|q&#>pYcjVo#KU51h;Fel1 z19nnakd)}*R*i^?>xO^m48Ug{mnaoKQ$5#>I^ff~OA8e2a<;r$BWC!9>(T>sVkZUD zdjv_AR@T=WV~_-FNqm9m*!r-rK~n+3`F0ah#Gt6yX#WFNK&ih10}?ScgyVdMGSf{E zlc=mKlvBDaj%>-NR3Ugvg=VTV*`X>{JJHv_q0mXg);&yqzd??mjtf_>oD)ReK+?2j zYnJ~am!E!T=pzm7Czqf53~wiy(k_{4G4rUicgF6{j{p*P+6@ER8r6%iI1 z5@?o1ZRh8JRtvKOQr}7inTTcB{W5iEr2>cY2{cZ4T%fVtZ?}0RzAI7CTtHqe{%tIg zFYgj^5;d!W0jEm%`eQq{K3~3L+b(oTxkP?LeL?TAA~Whw?*5=`-gW(Da_!aYk8a^> zP3Ij(2mCHvD0GLJ&0sEuo5O+v;1i>WwDpdaktS)i8J2vD4Kti5fJrSlM2puyvlCr` zh6j>;5jYLNuDjVkv6Q2$v_w9fi4n-Qg>)#LVR3w zWVj_HnA&d|RpbW&Rm6gh%gF*vDkV)&1Q}Fa-t@f*BUzDvwJ^HKu1y#DRJ=*&TaY{F z2_Y||)*galCGqOc4G$lEd)JKBPVymcaH?zt>IUO!0zchqgb$Q?+rN8(d{F*Sn?XWzcW_W(J@XMC zKy4+EG=l1$2F)KRN7gY$Cz}&6m+U6wz~ZdR$|2|?iW5DTad)syXL{Da^gN8m$(~XV z^3f~R$z`FT+sIqgbnGhTiQV*-+Ir zDFats(ArjMDbsBZV7i-by{snKX0Tu)n=Yg$BG!xx<#QsMrvMeLP%5P;Ty;$@ueypQ zJL6^JYOc$c|M$L0BgS0Y=;i{y7w1%jai0>c~is677k<46CycmLbCjQl|! zM?>I41(@tmvX}gc5C8JZVe%ScJ^4K%X)}}l*6jVwJ@K>{70wLhzu<@V=0y`7^ zEgV1licU6_W0F^HIUQ(SCC>T{S;(#5$SG8~YW3<>

                                                                      h``9dzg^ZvQNPHdbqWhZnrrhF4ATR0sYR~dYTBk1*~dlpBnpN_na!Pjb%5aGS%i@6V|Hm!V_P# z+uQ#hlQ#98?w@b^EG_-s6UXO`?(b-@4?9xH>U6|WojNK!OxF7e(#)U@SP<>HASu*_ zQZ)i?4po*U>nD*a192$AX16-C5R+HQF5jf0KPr)V#?*O}5|i&Xv@MxJuKclia8 z;6a|JLgHswLIpSl( zLW6^JHmxfVBv&Fxe_ZEOh@NVB9sadF8s6ie2Ci(W_F0hLRV40M^3?Sj6nW_eijnaz zI~UDcvH95_Z<8OcUM7d(gIAX>*??vad?2g%lLO^Hc>b$QU;V(K(n(F-UqAQi7dI{_ z%T`RH<4A(}-^}#DjCw4s2s){HQLM5Zq`G;f&7`Q3w3DWSs1KKZJ;C|dN|>A90H;N0 z;tqySEP^GN@*q)@yjI!_VmgM8>KI~+>dkbiL}rnGBX3v#P2R11VZ+u}fL9k+l3!7H zrTAub@vdi|-6g)s+XPKgmYJ;2bgL3fcLJ(0I(GD_I<{DQc2_=fQ2iB8idLe~AS8PJ zzUsMyM6`DNSSj^x56adAN@{}g1>>nj?y%aYo<^U>42ucG30faJ_)9g&Y@8C(G1hR} z9{uMCcOjQlt$dCI^7Pl_YlU38O!f;kUnt1>Iod8o1A7gu`kk^rDGK_K4Qq9i@zyNL zTa5<4G1^UvNJTW|u2c?Uq%9XnAnkv=23UI{aifpOC2|t}eT&|Mck$wO9PP>SBw?rL zYkV1hEYQPBLHZNgGYaW$BX3QUM^q!HepxX}`S`GU?gcvGF2nxYB@X6|K zM8tvOQ*1u_0q*{6y$aoCI+1>K*T4iClf=A|0yFSc0@Tipj9j!+@s~?2eJh%Yzptvn zr#-F2E60!TkjhSMX3)#Y>o`_fe@{<>Cc%L~uzE_sH9@3#5;%<0ZrvrHUzFTF-UnN%g=dJQbL(|Q9By#ZYN6ZUK%c^y6d4}BA;fhp3yVb&=o z+t~Q&3+r1r^>Mf?&Omycy??*5{_m_~N?*X8i!X|~Y<@G`j8gpfwUJZWfmULNbWSW_(SVBWp|!&!?=eK9+#Cy3kLd=oxx zC;foK<(r^ay6G9A4+lGA4fd_HiJkA=3o#D_K=}?F{vN5uC_?%HNeal7-oS&fR04W= zhVZ;QItgYoHQAAolmVY4Mn_t~bPEbF$Yy=3Eo~ql8-TQi?r^^cwdT^GDT9KTgCAqn zsUK=HAw{9Q%ScbZsJ0&CF7`by|Ig=*NS2Kn7R~{UbU2PI#9a=#IeCR%kB~w22mx2L zCsV&4mkMHFkVS0z)Tn1){rk$X5rcaV{{EW&eT;Fid@$ItGWR+8Fv%nLhq z9~x3Nw0kS0EPm&$S4cved4(?wD%?A+Ls2JgBQA#d%2OhNS0@N7+`(}%wg`F_Vl+rt z(a%xi03?Y~kr<2@u%zg52sTl(MHOP9Hq}UHP8HB3V%#p>6R6%NU_0AjHX85AKOFOaS7#Kcm9I%zCWb&pMPen^WoEcZ73~^|7L9zFrQ(jB{_fx z7QpV&O>8KgbzL+9U7P>;1Pw$G>c%02(s9{oKvF7qPPAt`BM=lL^nFi6&x9a`hwcYc1bTThg9WBW_3TcR&owE5^6?^wm_Qg^`y zV=Z;tBJD_sjj<<0CRjoO1B{AbLpDv?HVqHLB97onAwM|)W@$j0Vjb#LYZavFwQ`aG z%Ocpb!{U&`z(|QY@I)XiyMrFGborJ1fdW4H@>|acEG=I#VpCD~qO*I3+#ih5{$W;> zakJq~l#58^m1XjZr<*j|lh;|?``~0beC!fRTj?-}FO^1uUFhVdVGMSGg-UVy!ana- z!vJo%ilRzAAz(dnrbj(4W}5*xgHcgETh3e;KjF~MiRgjchx_)OD0g;j6cy1lwtM$8 zXT+7SEPVNRfcbSv8Bn_LmFl@Lp94r2$;@ayL)hmIO-oHmq<*WQ07^Z+xR$7X?ji*# zLUIEvD|R6KP*Ar+fPKkUfpaLjq1o>C9&6fseGg-yEv*3ost*Ajj-c_me?Vf?(N;ca zfRcLB;qo1V_|w^d%V&mdaYepI$gkc1(>b+hXOHD`U26xNzFhIZf|3c2qzPRXs3h0B zUEtXyFc|(QSN|G_BQ14}NLD z7v%_&NvFMrdVQiYcjYry?X;-;irTeP^L7n>?(NDE!%OaOP+2Ly(6#j9cb-Xj+oI|D zO{=d!qp(&Rp%csCPkQdrxE_rl(x(fVY9}kt8z9X=fvT>wgvJCwUjq4QbUl8RBy%mlidR^ey}lLM z&$mLA&2s}PDte=26h|IHkCGqJMUtvSRxd}7kzmge)~;_}>+?OCYWtpG2I+dxb0R^R z0edG|nB%5E$*?_~G$t$}jC%NF(WKu$$p)ZyA;|`7M9pi?c#H-*4iFQP>RO3$r%^bA z3TFfhmyV4?^F8K;m6;T@GitKeqNxaf`a*+)a`%oKzau64smV_ss~j?4{$01U7Jd@FGf8PTPyZ=dMK=0B1_!MTr*diGf5@DU~V zCqd^Q?S0?*uRTNXo`vHJbEGK)K}o3hVFW9LlNO^UmqVth>&f*~N4xGL-e@ zALVlt*PXClck+p2vt9wByDkuUbtmkvZJF!SwscSFbtk$_?DgtSIhWrVwBA*DE;47! zuy?UtTyZ_s~TKZ*;|inz*_z(?vRuNlF^q z!K;gubXs;d1uHF!s6aSe*bM!h*YdMx1a<%8BQVwwVT{{MWq|?;hNK^5k_ngzw^KpZ zg{vpLqL+2@xaJfp2EBmZHPp`eL%o1(-BML~q3(LTYix%h(Uq4&)0ULlQbNTcQj2^~ zs8q1K_h5s}`q&Hfr4ONx|KI#jq4)Mf<>?eyEhd?J(-|${Z-*>@^Sz&5KmMzXuZ`{7 zZ&06=r{DYS)F;0y_&aIwp!>$4hRr&~rS4d~`t8%}l-9#~6y&##Zn$gd=A&P%QwI0x z3_VD!xsF%L#s6Dp3S>GHXhwpPLA4}m2~w?zu^5rcDPK&Dg=$Eg5bWHXqTeppRD%MP;lP@Zt zP`-N+72`Wq@8GkZ9I3!#!MAApV7H6ELi_*5=VjLWyihpR4g$E(OL`aC$#ZBhx$)6Q zG>TK}`ot3ZOPUol|I0Oyjyb zQ)02I#L9eX!yQax^=eA35U46wBb8r~nYc3^-4Nd{F(#-{CBMiD3*?~7H zErocYz^%{~)^wy)JJStALof=D2MG|yTrr5dVi0%5fDz3$o$6%IWzv*wyg1}@!sB5l z_6-?6e8|2NO@{aE)342)@pcT6;8#WyAci_i%P#sVD^3KRHX zSOyN$6zB^Z6L4ZS7Ctn(nsh8KD>LU6L(H(={qMW4fA3*Ujz2wkH4GJ&hH4o z8jH`ZeD~zXAD?`8-7`OUT{iN9(@D2}ib3h0IX^||v6p{J`gE)2xq)$jPCY?B1><;x z<#r_rNsdH18f!RBoZ@`c7kd@h&z);WiUGKbVvr1q!-yoa3Dcu4Y6%$(YC27j&6~)@ zH#nHydHUz1w14{`SHgjc9R^3Ps|e+$!h)pwi+nrqjH_~^bo@E0PBAxbEI+Z!^z(@i ze~|F?No9S8o6ri}cUrF<1;>vEy*PNz$(tYkdhsP?+^A(UZ=R%+eP7Lwa(C%B7X1k{ zM58}#5jtvb9vvAL3VNL*CIr-XG0CV1l7K~Plm*z0)42U-kQ*|b#cq(8z1cY^6*hdyKmXJDZfR_W?MHsT=Jih!(Qz2 z&?Y?ZC?NhsM;dnI4~0xB+1nLjx!@Q z)Y&LA=1q-U;NMm)xq|)!p*9h_Vg9CxJ{up<)xf*ps(q!)EdU z%HF(T3w{sQVm0v6NoxL~i}Fv}F?gq!Z(#UJj1}tltbr>G;TBgE-L|WL{P9OpA;why zD87sT-zU<)0W)2`W^WI z)ZGJf=dN4%TE&ljd$nne!hgDn0%iQmx&=#@&prA3kDhbsCCT}@^N;7YPt0$z8lApx zO?vj4VTay%?@I;Eojjsjw*k%E|9xS=y3Fjg!=C-%n={I&m7}`#>66p?Xr?(T*jiT5 ze_(#7HNaNZyvHy$$4^N=h;!8SORdL06k036lgq?hmkdARoQet(``d5Q4`BKIaxA%;G@9q~Rymi2U!J|eE z9?;(tg8KgPJL*fG{ryjJU@m$LHAJcCF*1yNNxmS%ajEj~?oSWRdj9i0+myj&Yo^Vf z{$TH+E6CsEVKfeQpaG2`JINhXh{{P1a*CWJCFmtK-w)tdL<@`U$`CHNBWs@_@e?GU z56A}m+ZF+`y8%7^VfMNaHkO11nUN$lQGD4UUKh0jwr`hmC)jDVo`q)=8PN=gdtkxT zxGc~;1^j~smdhabgfzd$g?b)Vc#La(r%jDfy{AohsL?Dsrj*QD`s@=A7B+9)aUW6+ ztXsJ|Fqo`zO$b}vxpx6RZfzXhxaHjOQ)au0igOwVDZ`hpUrF9^^-Et`;2h`9%Ak5J z=o-U>2gF(8me3Tj-5+0D3}QRfw&rUgjK+`Gd|e)tL4(cNAJFebXr_2vOolP^sT~*9 zrQA&8_$Wh7yvHeNj60TRVAcP%s*BLm$>Z;OR)}rTOe7s-eN=PGKp&zJpOUs`0>DDe z77B%N?&!$K!sfZI$n40b8R>B`(NVSt|A=aL>m+0_rh&zRtqT1O3z-H3F&SkO-6Tdc zGDyZcsk3^2m67K&YP%p@w>x;Ci>$QQz7dVy=F>pw}NpQ4hb+val%MVBTet z+H`$vL)*b6!IbP2Fbiyw>O6({gU9XT|H^Q{(4p2fJqp5mi)$u5vb z(C7;&x%!ycMqG26%s^{Tqs4c>IZ5YpBHo2RlTQP>2kOhYWBPg;&AX#f8xo4(iFXdl zvn8ga`|{VA_c6T=EDr^*2blNRKSfVVQnowrXP(DVQ+GpGUQ73@Sb1*K+FiqDFTrRq z-n9t{dF|6Oo3&`7jM=nwM$eh!CexFm;dleSF25tB3zh$zpVy^4rk}gGz8pP=H$_hX zosx!)>icYiDQ6CP>X0ZpQWZP(J>wL`mk()8RWskxa+%JA8ijuVl?+!-qh|TbU=rp_Kj0oL7NcoBu^3t$3y;JwQ%a*6EYGw?4m)xJrwGU7 z)(QEhLaMn9x0wu;5||%l7K@j+3e2NN_mMANp5bR_Phqsu1F%T$Hq!Y~+39nj#Og!T z1IPe;Ia4YyCr6zhjf*(y4@b*K4(mH5uJRj0qgh>Aj!3DH3Orl)&u-a546AylPi|gJ zEGd$|{N%R5-?WB zTm;UsL&l*|-AfxSiZ(3amj53Ngi7RyDW-aDFuhGbD6!lIt^s=JMOF9X>* zexrLlLYoG_SlzQ;+bUQsIYIXukA0!~Bu!|e^;qz8xYgty1ICW%`2hY!M1Q>X$@R_C znk7ho|BZKVoI9xdgT04M7{s#IUSD)^K+}PJ(e7(>eiCVplA&{0ijczc5Zehqp+SP_ zMU0N1L24c%hv}rj%tpJ>Kow@7A4~@?3@Q~KNBvcp{(dkcG?)RxlW3v}GtmzwNNa1N zumIghVek=jpC8O@4NpImhhA1;US=zZf$jyvWEM*r4jOGl-6}d-?s;w)wQgx}i(-@& zsxTM@MD40tIWh)%ViBW8KpR-Pyyy^_+aR3%AcvT0m|VRmgqV(y%b+`4@yxN{WY6~z z_~E<1qPa0L&(%6b#-1X1XbfJ6IE_vsEoj~ojHe+R^L+GHO%=}tt*KJS%yN6!I;E@Y zbd0SN(ybGR>7>ETMh~!cLb`S0Fde)wuuiktIw9RUahM;{B;kr2>u_nsDKLVzn zRhEB6`CVrkNdSfd@Vt;<_#}{rW}5V#X^Cw(y2gs4>a|+xI|vccC^EkgbDwG{S>Xg z3&RkA$>DR0BGEK;pG@elW8&m;u6PXo(85 z#1AG(Yipu#2;HylxBJyRuLp zfDLR?uxikQ9>rpJ_`$z76Id7c7*o$rnz7f}j~u3x1~VIdP=`Nom=0bTpqY>B@CObPq~Vz;yil7z@VIu?R*|2~(AokX zy%k^WhH>pu5oq&Gh%#+`N#IQU){j~9%&aCbN@UTfMKAz1yw zzj8p$^;#-uZpEMP9r$V{YWwA>UeBg9O`BJA-(d3E!Xd2&PLbMud-p%jPy4W_E%{;1 zE3YKQo{DPNyF*uG-Bk8*mmb5mu3&V+Vzw0{tV?@Ujx2?>GQxf@k7moF!5B1{*{C_} zMFtb)4S{Js?bv16@qxiMPMvuXC#XTB~t{xC0W6?G$F;n%Ay3Du_)3oN*ZGoY6~)AZqTAYtc!I` zxu%7hWYKN>KyIr=o~CgSTO-i zXSPP|X2$R}^sNzmZ&bghbke9kS^^lwivyK5jpPuKIvny@t&NF6v3!+d+4nUEK)5WG zE8+V;R6S!9Xlh1k9LU}_HUKl3AXlg`iZDAy;t&$Y@fv(TNWSgG0Xjw^a32PNRU9>Y z0cM7LSZik@7}*Mi!Q~34H!QROnkr1XYKSqvn`=u4W=L( zc<4w>h>c-o9EAX8wW$t#8nNLMEbMsM7Um6IZ|LRH~GEfD@V7~E~PtKe^^4o7VLCx8nbZA!*bv_a^uMl z|0eICsPo?;d#fCI@a`7dC(TnV@qs79+hjd3sjB7qy~~@pUwLrO3!FAsoFd!1z4_kl zpU!7Xw|8^cx|gavUaaXk9)RYm|J@gM6X_-5sQOAvA2M#BHU2QTTz2nBwBgR(7#VaT! zGBkj^bpxU?&tK))k-|-(evxAjCHCuVQ@F;4p>hA4*JRIcgE1I00-b~_qNYde8 zHUhV$`v{++=Tsce>2WC0nk?@#bv(y0Ud2Ir$xgYP;|MjN{$ew}zez7ClgXI&{BvB) z?Oj^ugV`<()%7~UY!{@nU0D7Q;~yPWn8u8MARYhUcm{d#0A;<->>H%BZ#W)V#RIhE zvU4mdkKs7-G#q`=gJ`jeW3e8G{EfFS03!%#97~#iUq)zn%D~pTU&V93Uta>XzLa&2 z;aF68%4&!h=zOKAI977s2lDCFuoiNG5(zM!D2zBt^vGcxMh^S`lP#>qmmh*X83h{m zKDRB|86WGddQ5A-Q7-M5J6LEzCee|IjV4g2jr1Ir=D3Km+I17HY2@3hMp|(%MvYbk zqp#Kf>1mcPXEgfQuTee3RFknMj)m)zyp9Z; zi%gYYyjq7}uv{+2FS>Gm(a~Qg;W(ygIQj@bqqkKYZ~Nhh)^PNh=g%)Wjyw%VU$nFi z&tW(i&*`edSQ*d3I-WC`1kk!TUOeI`bd;>+c*t76zO3=$5oZD)UC8k))XlAIW;TB# zbzZL2vH4lv7K7=g!r1*`U_VC!p6$SQ!Ua3%$IUz<1b~WT=0~<>T2+jO z)0vRLP%ELI*T%Fs84qH0aHt|Chb>=DtKmHOAgzZ}y%ewY%#faXqKeScI1+vW1(M%U zpl2~njzTrp)ZDWep@%!dS7Dv%0o2adcw%F!rdtrt9ij!cks|Q(W|OY+O{lkn3NO}B zH_wK%1_z!^{?=!vZQWXljM8ax)jvN?I(=aOerAij36r^z$rA1p9Z=J%wvVvp34oc- zWXT^YOp;*b(!}buX(*oUjDK*y>GYarwfP6bGe_R5**(*1Vrp)ycHnIl<|lv|$My~H zPoJ8pwRuR*8Gz}^_RSwEOmCr#_ovKDXX&IDdY|ooz!R#V{@-$YBM3f!fyuNI{`m?1 z`5sub=NaG0QhAEWpYH(KY@qfbi=VA8@622~?`$c}oMXP}n(IoUTpr5%Vh|eRZmi9X zpmRO0M27Od7=-RL;{-m>gFU;)&8Z}atE3AaDSsc9f_kZTX2Y64 z)Vch_>su#LwC)k$X`=4gb!4ZyXLqVFOGpgO;RBc+Doj4vrNZn|$Gx7$y~0rbkM)zx z_pYCWZcVAEC__C^vPg!aH^}?wIZ`SWkRBjQJT;!Pg2spQ42jUUrm9chiL%vs$X5Hm zk=o;i`v9h=3KN5-s4!Esd5EEPn7nvkj5Gbm2rv^#49zL@;t@v)F?C>gJ*Ss+c!;FZ zru3YyKcDLHpof{xguFVFhDYlU@Y@rfPdSX|QyrdNK0H8=e|Zk6Fo)E20pmbw%yh3@ zw=pP?t%`R=5-AsC(JcZis8zez6kC&ItIW!w8FKSsWmeG8S6X;#)~rf#SjmwR5_KF8 zZE&Ok-oek$p*`FXcp9w*r39E|Nu&QLZ}D;?ulB7aVX{->d@JQpype}DZK51hoR@PX z$I}u|YI>w8uGHj0C+}GW=-}Vg@fUMnfkE{ZP?+9z^mJHjTCd8B2j>5~I_tO)=plgF z3cXdB-u10D^ru8SJ1G-9b#wsUpFqubQ8w96$F8};zK`^^Q?t>Z7GO@dkS?+WYZxhX zV0oI6LL`+Fe%ZX~b_>R$ft4>14GI&3EiJ8u#omfs za`{~g&Fy_tHV!FmRjWJ~%_9Ywu1FVJs#oAD)u^pHdLLN5n7Rv(A$SzkE~w6lPuSX;9vt;m;mZhuy+f zSUh}Wm&s0G%iDYQKmWBSk&gTw+0eHXUtTyquW9wSQh{~`6`-9#O&30>a|X@*L9b~3 zpy{Rlwl2ppO*`xAgA}H_VV&;AeNNF{zZK|r>ja(lCiu?7hH7{QqGtZ*VJe4lF^xi3|FO90XZU|s?o0EkqcXV`QVtizBbh1xxqU(u-0KE<5f_1?$NHDN+3^d+} z=}W#W*C3l&b5rxv2panu*U#MXcP` zbH-%njCJjK`4w{j>VnLu2{NIsfu<8=)CuB>Fc_qKgYn!6^1;au1a@`+>!bVydngIy zaC2dlJ3hN967q7JHqUNO?`DaMiL^(A1%tIr^In&x_2o2hs+L`iMtUo2c;(%j27jL`a0COlrp-^BY8sP(0+ zrT@Gn!5VF5Yt&p_qltCqKap5y-Y~%QSJ&tZvPp&6q{6WJc5IEBt9@BjM=mEqU((ol zo{9(EkejG-w}~ouy>;?JgjWBM2b*YMQFdIXrT6#Hi>?G&_A4suR4qlCjtRD+xc7YJ z*|W5W9w|C6hE?Ab!w#UPCr*$Lsa@!)xsKP##UMxTqjBt9p7JZWcoi4k1&s^jgtCaC z0I*xl83u$EBuX@mC(fwmOPhGUG<1z>0ovtEEMMAMZ_aeCH*fm0&vcp7@4l<%PVYNF z?r7Q5$Z%jE&!5)L;zwxb^#g=Y>%@~V|2d-r?q44;KxZj>aWFfvK$WfM>iC(s4}P!a zgP-2p&q~zwWsugFK1iL6FHvQ8lHY=42$nV-uNyJk3+-LPxw_B z#J%H#{PA?r@C-!xb>b8#o-+A&4bMQ~nE$yS#Y1}0T8kVH^IPrV=N9m}ODf>cGXHi* z_BpF#$b2O&R9kUl9e)bT`DSMxgH#wx?K4R=hJxZL67(^3dOZA$;I{XS0F}o2pPg_V zL0%kMJe__HSe-x?JJL$!eN*bhj<6hQcE&P9g^90oj>GXJdGUY^<*q}E9M5}RJYYlJ z5+XRB2!A}?H9Td&X9ufz2K(XpOT`1ct+~RnuvJ4qRRZ3oGy-1YVsXW4H6CAXgF(GN zz#FO?;*BomRk-z)psbd)Ck{2}m>Ffui0NJ`9ijD~j>^j5(yETkuk7|# zR#5C;uu5E6U8va-;wgRcDyD;u1U)EF8NqbW*6u*3BR1N?B89aR?X(~yq6n}C*eyah z4U`ZBahtX$7S4`$)K|r( zQ|p-3qc)#Pb8qQcx0;Pwzg3y26v6%+!)(lGA=+-G)qoV)7vUDu&+VYq2Qa(N&192l z)uP(fw_|iLSjeashFNA-@388r|El!vb^fi_{Hnmdf}{2?|GXyA^Gw}pu&i!}JWcv9 z@VX`5TK!a7(wa?*?3a6x0VFR+*(8{1FqcJ<+LBn#;NB=^QDU#90%K|XkI-uL6hc@X z84r!7x#ivj1buN2Hez`q7N7s`M>c(x4`om{>A&(zCoR<<*Q)n18=L3ORDF39GVJ2eRE*(tyX7laYi4iw8rc=;WR zRc1Q(8qQns`8ql`i*;f#7Y9_B^(^K>)Wuw|xJkn*fO%Bq(VrmdTNDA$POU#P!M>FM z=5-Y&OR#Y~HcihZ2EC37y4p&zO4a#RX*#MwucHD?l0OXaMVLdhh1E5=Cl98sDY0%9 zG^w5{XlRR%$+h;DKVxi7n#1*vz2Zi+0OYhH@){7kq#wi<@=c(ucC~BkGRkE2b*U?k z7WbgZi`azeJ%i!i&uK7z2Bl5)ra`MS)!@ucc8M)cY*_y`GH#HnBiF8tz71{7fwmgS zzt!JXl&+R9i!!Bgf+j(0ORe#%=KS!s@?BQhnVjoFA1}W^e&0?0_)H$R+ERTtob!*F z(l&gD>B>3Yyp*5-zxvNn23l>G4T9x*#PWL3YULK5K;SFaUm;2_Y}xvPEWT3Qu1#yX zT$%UCBlDDk&YcT*d)uW8=qdT|zs@s6Pmu}~EM52p+TJVOkBw@cVOBkPhW|4crEZep z-tk>Kj~&yc+qj7t32|u+;}g^6s7@nBbn1NH;7$o?X$gs$nY`bfNiTFA^ssQDkz1km zyw>k%Gt&UVO)#c#UzSlAw;&u^u7%wj-ItHn6&0uE#H7VK8}w^AYT2awU1hGMtiXWv z;Zf5@bzh&)>RCyji#_GP0OKLI*%Crq^o^8JLME*?VrGuRaD>B6v`D;`TN$Lwv@+0G zWtO&_R?j0MuTB!HdzP0os}C0OvL-a@Of7VxFL0vf!?8*B)iQ%HZpPs&|<%V5$KX?ky7e6Tuh=a5E;gVqJa5^44+=auykoneL)v#7J}NanCM6{% zKJ{wbfdkvN?c1+SY-(z3e8Yy6CwVSQ(`y{^CzcLEJI^5x$$YeQF~7l!%=6k!WP~)e z<|+9jfSFA~Jbz}qSo)RIr-ZIEE`av7Lac!=xW-a{Sj_Up0!ayS`Qe&uomQ%gi$GbTpwWGi`7J<3mm{-$gJ! zL%zZUC!M&BE2V2Pk`(eM^{TP4Cy{-mNzL;A`(31@31v)V-#45;T$cVs)k@Gm-$iQT zw~8W{=tSmLT@kK4Ya>r`B;rF%)Li^VYEP_)~S~wuD;8`)!Gr^fLmOD<%;L_ zl`9MHY~RdkNPtYerNw!vIZ>es8u1@h-tqj#Fh!Wh&U?GCc##k-Mq&h+R42}L4n0F* zxEe8=bp+YPK3_@mdDydA>a)+(u}8zG-6j${XN z;^|j$(cPt}Bd#D@=pjyz-^Xkm7m8C}tC{2I&nOZELmCMJEDr9vP7O!HdTAEt5kL)y&I!?n1~{ll?^anJONuZZj1BwJJD(i%s-EeU(sY$#ReCzZ#+b|ScYya@ zSsqO>t>0%d(grmA>C|5usL&cjGB1v)zlW>#2u(DfG1r8s-xP^9G6|olszM)-Z1Ee< zV6+*3==uG`4qS{|?Kt82)9d?XeQECVS+Vy;Z2mjK*cY*TO6ct~rEXi2BR(!F(#kS2 z`BM0z{M=0wZI~9>O0a|V7eT!z$e^%HeiKrt*{7(td3uw6n9so`SR({hT#Sa#=jYO3 zJbS(c>_IsvCDmX7D^MJK6S>H_o0Y$j50LA2rRU<_^@_57uh@U@Iz?HxSGr^--+uco z`QCK)eG`iP_6l;CKlLQ8e?r7~JeHn$Xv5PI_H4)EQ!qyLju04QOE!OWj6GqDQ7qFs zGRzVf0E?{2BYTipt)Gao|2-b8;t{o11$s1^0vnXtuF!Rt*jib-wUS)9U2&8ARIz!X zQh}p!=!vIsg6E2doR1=}qRw{IRH&gJJb5Avi`%$7n@D*s@D3-vXWW_Opfz-0s*Q^8 zp7CH-^2zE`G=o?q6JmuvedP@E!c=!h9Eu3D15vnW?KWN*#TtPPKp^;=nalTW-u&dM zIVAAT?DeRix*E0EFjJ@@0q@45u*z{CU%K@1xZlamn0HSOM5#}XK{hmmJWhTY^CbCl z&`IIn~lN*vr{u^L6sW3q`*HxSTx)z5p zOi~!0Eh>zi;Xyh)&w~6~$l`pqG2i0|@pBd8bIlh{?|NvWtOuCK8O+EQud5R7bq)g@ zhxJ)10UbU=_>fjQNK17jz`Ix)txGLsqh6cJih(VV?8Jf+Ov6$|>P4grXrO@yp}ev^ z7|=A}mAQqwl&AM|XTw91{vp-P$R8Ezc@Rv9BEN^^`W_N=&)C!(qErON{`$%g+obhNkQG@}_zhyzQUVslFOu>))x6b_V`@K3 z1zG05K;Vs+@UJ^Uvj}n;glnZq)D!}KW%; zCDT{U89zrpb>Wr4yPIUbvG}8FY3Zc7{LIUho*h$0mCau~qWVh1j5U)cZavC)L?Ri& zYT44e2WTSYchko8qxhbiGwLDg-N zi$0KoJURXQd+Ud@dVLLq?(T?4yC5XQ*&9SQfKP0JX5GzWS+GPnoL11VvU|q_QA$&l zIGJ5z=gXlC<~NZdtHU5`{#ja6vK3CwMOuL~%Dcp4q!gpviOac%_Ollah+IM|7A;_| zTDkmf<-4AL?qvSi%wMe^qQrQlT;JjO>dY>y>aFEGmGKR!8&K0QcNonmr1z;t+IZzX z&A;C|kQD-v#AJRm4fDy0X@VlrODNM|IweJv{7Njcj1u)m++YK*Lgl+^TVE-!5LvaG zwrMR*T48VK*b#k){r&OlLXC`np4)%)_>rSdpPo2%&iK&_f5tMo{rbn`50pJ%v7^D9 zj@$RWv|ee^y?66g9iQ*itySNFZsp164na4DkuvdpSR)7M4%CKpfQFb5X*C-(8#0C0 zH=(s@!_;zx67t>@g}k~0UlYWYGi+dWz z;-12VY5!P1zX7kGFV?A_53I|mQnDQ5Zpdrsi}lvf*MTbcuA@(5nGU{IIbwts!Svqu zRc}c}3nw?ruKtGC(HB{~cN(k3V)N?rUSGK``=|jc$|+$%f8}1SO9Oc+TJF7P<@K$g ziE^Sq4wYp{X~c8!BDssCix-hxNiyb7ojQkPpwH${nK~Dns>x;KtU|l1Py=$QihR0t z>%OP9pi5xDrR);R$IFGhv$-Y=TDtW;xJL7%E-`>jFEZQ$QGffmoXgJ}+>ErR;deEK?D zV0#+~Us>KZ&c&mZtmq*j$Pdu!fN?KqfKg3REMQe8+E4XKfvH?JSn4)x#}3=V0-Bf3pNE>%7%xy1#Z zgWA@>CDqHs1;@CaNbkOA%I-*rqi3AHyM=sboOX~qpl#4IPVGoDRDV3{M)ZM@h28f*UTMAb1A@zPC`i<-$m&T1)Fl)=BM-Pho7xr)6rvPt2kiS>IyLXT%m0Uck44QLxlXJ~MTind0 zvyL`;Dxqu3%*H{<$o!@AXVi?%WiOzK1wa#_z=?C*fpO7Rb_as)#%gx0fVb44|2ZnZ zuUfBl2>A}5zCmj=S)~Q!&pso`U*BGXt!%uCTU5WhVClSh^A@1R^TnBMPfoR7AQx#= z-p?o=1g_KDAnbE;Q~bKd4SnJvQV z#PPdAt%4QUiMh^Qq53ja!Pt9OD3dNJIMrnfvxZ{M((j)=YVHGKq3bu7`^ukJ{+0?n zk3Ra)PfspD!m9Cv>>zi^Yn6BLaG3A5BuQQYZPVN63*5olJk?#V^V3snXB(kH+F0&&6$L!M^W- zt;c9hI?_#QD|HrONC84eN=%3mNF@~ZA&3O9 z2o$ROiB#oFRqy4(2Bw5iT_a4Q(xe!k#eUDq`e#9lWcP ziernV&U>f+2mQz6B6+Pk0GoSTQINcM)t86_h$ghGZC?q4*rB`?)^#DQYaI1^^YeeZ z%@PW_nCAD64GTe%H^_!+jUrVZ%__yxHKXMXT-5YoE35N=h`p4@wu?nMH}l$%Kgc(g z9`bAD_9co`P`wgIU)VP1?y}Lm^$`uSCgYM5_^n)s9mA#>6ijy(-DWU)R`&zs8skn1HmKneu6i~F zw{R_>=b~TQ^^k^57&5JD>W~S;H5XK`#sw9I%_)P~$6>JB9|rdO z48U^*blqqHT62dcH%N$!w9{Jr`rHI}ezbrUoPs2Us_3#JV_rd2R3z@-^Oc>|^IxW4 z@aQKiFU}i<@>L0&(jYh4Cp+?S#CwlF^#(azQ$mR;nZrPIFJIQ8K2qgqU2qcsZ9Rfi*1ccCg3B3lScPRo=6bm3# z5UijgT?8x$KU4&zC|xCMgJfslDfiypO#=AydEWQ^{Qtk_iDWl(&pmTy=FB-W=X{TL zK*a1CvT8l%J+&5u_hE(0R;o*uH$9TFe{2=)AE2-%Z_>w0y|CRgPxTeR_BBf`;Ko z@iJL_&X_W|S;P-^-jlwSPmmq8FRPhHeD>HF9<9vRnLe(KIG(&>V0iLG0n@q_2D0AB zAk%9}1G|>=i0JdEmCGYV_(Jm+(&Ge|fkta3a5X5MLlXY(5yr=$ZV8zq$r8Hz^12sx z!ynjd?~AK9z-8ro`~bRw7leQry5mPTl$9Iq?oT?J`p(^rtF$wg{|jopm%j)5N9Wsh zoOi{q*)uhmjY?V?o3L}USfQOQGAv9G!eYZJMTXOJv!DQm@M{o3zcr~$Z>SBDpq4+T zbCXs+HiRl_nO670nE@7NN?9$$7x70HYX)%vB7lC)&KzYk)cy@Z@ZH}W-(p)aewbEy z^%QXn)Ska&$$WXQ<1TidJ?j+6^o_#<@UkOhKy%RRj>?WZ8w*En;Qq>5mH$984()8= zK|w)LL6M=sYAU!{k=&6TY*hqg0;7bC++~&wRP)3ryokKPAhK;(2ce*=jPOc9-dGoC z8lA>FEJ90*A>#oAGxi;0?RIenWXxZ@c)r*a4R@US{rJg;=sCv>(hmg(FC8{`37dP( z$$I{c<*nDZ`KuZ0%)fH^iMCi5e3Rw?3)KI0Pg3U!fSnNOi~n8R@b5=pw$EJgx3=!D z+<1V^@aMY8rGN7^&+bZ<2U<=rS@Xk*Il|YxsLm1MWXT4q^WX&6c|^aI)p<3@8oEK_ z@8K&ow*H)F{5|Qz3j89m`}aOMUO|+q=_ThyL6<*6eP_A%{AO~69WAlr)^?mJ?=1Lb>~U73=S?iuKpj7U<){k^a2BXvB`2oD+%tOS3CvJ{w#)WI8URwv$@; zG+;AXp91uDA8HrV8SudIt@tASL}xA$`x_-^$iyW>Z*e@>SU6&}P(H3e)4%jH)xU&q zD_$pGB7FN2zMI$r=^jB7Q;cP^QWEIx3V9-ebVa{ECU%V|dfu-Bztts+E{e_W8Hpy>lC*JX}D5=QoYl)?dT>heIHhF(D3rF>3SttsbTBl zXYf+|6A0a=LJ_>cz^Im)30FRJ8pLQlQRtGXHAK88>?g zK7b!xXR80L#jkv@_4SX$783^dE}Gm^+5f{gpZ4Ecqw4Nyr*8b`tkQSx>_Jn;tG+f{ zr)+(xbpk!(9L#hU^GbRKk4k#9vSu=?*A*rO+wF>DN^voZA(4Vn$sMx3?jyma2YPCH z0J=a#xg49au@|Xo{DGfPkDZ&dGhJSDPha&kj!+Uf(xIUYoFzZiwXzL^h>L9)ve}L+ z|5Tb*dC>^QrM@2+p$U3jcuH(Wbyps(7AHYIuhsqz(}i+z4o($giM3~OM4qt+gkPrr z*cxb5VO_x_Z=%h-7_NtVZ9#)uZ9!kXwjh+REr`0ME6@VG9lvI8f2q;n>d}=uSUdEJ zs)YT(ELM6!Oe*OxcV$T6J6?Wmn>3YbFdo(T2hyim>~q=Jfn`L$9A@(+^D+83ns}m; zfFig?rdzozu&gqp?5>gN1hOo%qowvwic1cW2@@pUF9~s+he3jhlOf$^dt4*!?u2{7 zZgU_$kXXCq1ynx#@{jIzYCeI-OrVlUaEr8;Zrk(r^mgE4`#&>wFTt(D`VJ6AR=r3^g*oB0tCD1t)I$Tl_s}1hhvJJ- zto`qseDmQO5TQ=<_g^*^viaVa*~bjC-#wYo?cQOg< z?>%mR7~*f%51smMf8eA%@jjZTuuu9PAmiKc+kszVZ@ z@nbPAKdQ_b2D{`&;kdVLWMzM0?Eaj%hCx}aTUfj2INme0+Gus`939bbjm2aA`lT=)Pjsr%vF z(?1fm*Brf3G-~uxJ@<#*M>W^)9%?H=#5PV9UZ=Irs2yZUjZck=2n`7eFe*YE#JS>9 z61v&yhmqZ?QVenFe7P~?iEM5NHL5TJ>d~-X@{CTjC|g$9#}QSi5?42-Cq1mjrUdFY z9rYnI!#|K#n_!hZeIXVaLYPOm1?ujd_$rkF!KQxl#c=VjC=vpi>UA?Sa0PkJ= zwV>OmiB~_ze}cJJubu_?&#(LS9XjN=l(lwsn~AaE^SizH5}d{MW;wPNZ$iWDCOPbk zhA`ip@coqd$JgQKkr7aW*>;zBW(F8x_r)#G~ znTPaKKScFB%%KW0iu!?`k)LNbA_j6M1#why)o6VYvb!uw$ZO^sj{aO(>}X(zN2a6% zn1-((flCiyXXygRH^d=Xk1E62m#*cZH=HWwp45)a@z%`FAi7flcGvW;{Sfm%@I%DU znin_6n9QUp_!X!oI5Ugu3QnkwH<2$+!+zYB{-8!sg1f?Y_9HtE6aJnhdR}C)JpXU_ zA^uPCL)^3hX7OE5^Fhpy^FhRL;(p*> zOFj&!8sL$e%y_*p$?Sn8R>ui}&SCp>sld@^sZitx$I{~Vu;4*oAA zDLh#Y8RNn50Y2tJCv%iKKGWtN>-RtPbIeclb252qthpE;fA?~2NEp$|Kcx`uZ^>wsJUZ^dbTD67e!CXHMFxi#wV;-0B*X9tI2xg2;Ap_>#?x^ysd0Q2`wkQb83eXr(=FXxL3}y0Z6%W(_psYx ziyhv7pU|*3%oA%U5ZOj7F9=D zmpVK&IEedkWEsZjmUHbukYt%9xs|O*t)Kr=3?BU=U&YVXDp9jw)Y^e%>Y~yj)ZZiN z;hsAf-~Q;Hgud5`P%AHf4;go@cc9MoJ&Im^n(|wp==t0K{=WV;e#MTry5HApm<}vn zrx)7;+v5V|pb{>`62CcH=w%D7msu;VYDz*pk0aw}mAYQdHYtdB%(at~B!dzWibR9R z(ces<-b1tPp4hGi&D7Isx-p1x71vh7vJTOsMc7S`dda3?TU$I}Z`)rv)p>q;aqXq~ zpZ@T}i5|;p7pE`ia`K8iaoV&t!{XwGL&tj! zb13|E$bI}n!)!+>l-8|BBYfZZPm}sMqF$r-Ri zyiwY~*1|vWqs>q8ql@gY)xN@B`X4E)bb&aDY<%BAfA*enES4&pcq&;oZx?o`e#Sr? zM3I^q9zL`ydz~v83m2wGuDbY#J#9d(Z+3W@`+a-$?t=~=+4#~4apFs2^*?+p;KNlw=Gb^anW%2%J|G=X3(T6 zh6@b9b7z?S=Mgf4QXZG7&3qTh(j%gn7}~RH-q4c5sXHYo5o=?*S*A3AmY>48t`Ob zOch5SWu9bM(Fe99)Q|J?uOFI~qoYQjln&uv8EAB>iha?mGdi!LM<06W!wkAk=6k#5>;e=jT=kmdKbJC8OM}2!(N+A*6yTrf{t~^?8t6{iq*@ogB6P7 z{7>rp(7a@v3(MFu?bw`8Bm2uv7C-Ypx`#Jcd=Ky1lbE|f{qc+deJ_x_w9V=M(JRFJ z=$DTk5^db8FEP&Nvt5chB1iF;$KlK+IO{l$4;M7c>CX5jb3oZn_@?*olb?3~p1aq# zn=PIe#55v$_YVB--CXAGU5a|bMSa=EYH@A4=es)TvC|b2S3~O{aXiqA_xtqj)fa7o z4ZL@78C!`G(s~6HTmJtS?DjYCDR=Dl0R!xiDILJSm%(m7u;cBw^<0Mj@&mH|ZmDd;o@%$8p`dv~%~csg1T?_3^WwU<*dEl0t43 zpNVPa9eLFpokj5C2p?x3QD$f;-J zDqboJK5~O&Q*CBzh9$%r;GsyR+{~h8-$Nw+{#xOloSZ$Quj9)Qak=S?%=*c_GA688 zH>LOR=ugnN!%@QvCT&v7i#Uf8Wg~D=~VweoYvr0CuIPw5KV>dQN=!yUi8qDXLi^{ z)9T2)m68oS@|vm$BP+pORd2^42^lsH4Nj<_wVIifo*5*vbi6u&$?0Y=kZo0@S@VB~ zDlx+ff8QCb7}_^7mY82$@Wmu$;Tc?10wYI_f_xa`sNFwm6>PqO&pU4a1q<;+(i24S z{@Hy@#qm4pEtV^OhcH7Cj3l$2v} zH|@Xtq6TlY*v~JtTI@J<$nm3kX@i_MsST_|{?GX|RlujkrMuLU6T0?7uj4DK@_OS9 zJH(Su)J~R~;_1v%Zn^`i5sCV{d0WMSTLE*952vhHju3*Ma6MR@nV-Sh}$1#v%>21uxuQD63KjeVm5Q@v-v+H#0Z$p zMyeu>MxQdoOi{Mh|CSK5i1b5JLX6`+gTul#Bjad1p%!cy=U6H4bi9&(t@#$u`SuDqDoKgnRRMJ6Zl6JRYrsKT*m9YcDa z2nG{HsW5XK^?x=d=8DH8?|(wDoH)tYboeg`GD7+o`9EQdI5@RtyCthbRHuvuC#B(& zNEtg`HQ~N137BrT7X_94M>XUM#~KmTg){QBm$@D1a~{_wwoLsm!N`oc4dZ3HKT&<^ z%VGrl1lto(fGvVSqJAT>KM~*LQ4EW@lFQv4FkNT`3(<;;7G0jcxC9w)BB8`_4hHQ} zU_Bm4e^|&uXL`;;#7Fc>Gq$$|P#*mK{xJ{iI??=i9@52Rs{!43_Gpj6f5G;fu=6k6 z^Y8wlN+^Wk+w_O|I>$ii){XG-i69ta)p|N@{y{yRM8S)&;U%P)iH|KKkzty|m{^F5 zky?GONJYwxsB#v>Z8IVt*bg0{78TCIMVE^fm8`_S5!h`fS?2+C)8*uUn}T!v4Y*5cxmyR}S)@cPBSsrZI6QI1$eoY@mxkjKyjB0^Q1 zT%?XgOrXsEnL~ITLS!0EZ2Gpg;MhvhQIQmlgp9G-D7#yd)ndp{`+6a&?r3TqJG}?y z@EHV_vhA8|yoRS9`$-MRWM-+*Z2oK@@(!{{hi8r1reeYOV zjHAV>;>G)TBlKT6I>50L^%F<0q@RAfh~_%x!8@GySv0PM$T^ZQ(T<+X#YA)5(BPl| zKZZHtic+W+Wk7-RxVE!WF*D}a|D=~g7s*V7{n6tF54Ig}yi7ID6GssVDcC0NFiaAv2^qpbTQ~?AwQJR^ky&pAnGavOdCCGF}8o7(X?SVTl+b$ z!~0v(CoEXE@_9(s05!$D!oK;VPMrQ=)aGhc-kko~^~^M~F|SK`XU3w%Mg1pDJt@AX zB5oof9k&n{C~-^%L!K&wrsZTH7!;%!P>P!X=x%OuOByzFF`$aY;0jZCoEU<1F{~Xk zyl?~+!#Uii+mOP)PStGDxKo1;lU{|lUQQb_Wp>fpA2b=DQEi%Jwff+d740TlEt5OF zxSPpfW$IfKXU~4d)~fY(F@?)Ojb&`lVj1T!A63l(B%e16?zm+>LM0)U-c$McR;xl5 zJIk8#t>jmUdWyP+%8m#?NU9u5oJ4wyCn&7!Dv=5jWCK!T;#_$t9+5?!NYimb04)`g zp<0VPlZsuiP}_u?FLFRxd^0?zdglllV`S-?-uCA8_^vhkeBGi}*I+oXsXPERjW(K; z9G6Z5j+(|LOqmiBJ0(5w-J5ql;I%~P9VY2_j8I(|V2g~cM0=iStyDd>I>n>*jq!`2 zeRrKFhKB`+r1QxZ(Ll4tB;p5C{9xXFGF1%jAf4rcb2Ol8?Z7vKRu$*IF^8!zX#LLQ zpvV-knjih%!hfMzmTa$pX(J|1ll*Oob+$aP)bk3QGHlE=Sqf;B&~z;Wu+~n4Yun>f zER$c@J4X(S?PN=d9lz++A~`IoGqt0M2P`MZM}-iwBD}S#ovwIWhF=|TW*7ow3DF%W zMGe8BVYfbN?i6u(lSm`Utq}`B*3mk(hAwZ{Gl`Cvc4$bX5_vvt^C(NLurMjgr$&RH2@)(GHUv2~y=?ON1c|nslIK~BCiB~+a583(m7d+FpjVPFMBLz_s>P8_&s;V7v${~WU z*<|)Lx$vI61+%X=@o-}Nz{d+rf{%%*clXmzgXig|>AyMs%t#OMIQgV-D+z4>vvTyP zbV$xjP7jgt(P^ zO3k|SrWCe->Z5UH`z$!X4oSD--<$%zhd0+vOREb#A(&XI{*ccON$C;P+soz&Di zQ29=sdr+NC*h8!9uKc)ma*Z0vwLe~2cl9AMU01rMYljA-7EYvgKi3x&JGP}TkKXV# zZ`!DV7JtRdM1_U;`+DBL1ZofK8Svv!M`IV?$+#(?8>Ynm9ByU~|3i#+rH!J*1 zgWaFVZxQ(=kbRKYGuC)|CKDE_ogjHi)=$?3WQpd)fl=X@F;#u3I0dpV8Wk_a=#}CF z#NYNZBr~BJ1QbPUN*gKaAU*kH9}HopD0VYrD@%tA%YR44*8K4#1TP=O%O{z*{ff_1 z2&qS|?&E8vXJA3;bpnH|p~#Pd;#-46gEbk7$=KE1zxEycY6;9bvrw7z#ex^jCB{bW z4NCCN-wTJuD4}wWHbxIiPSD$(zfc%dyMlYJit3Nf;AMF0s8Q4w9*P%9?-IW)LYQFl zrr4u2@7@*D#w>|y-VD!>Axx=A0%Z#U@$@Bc29%akL34?PptB+m+H=}fu{9tGWdty6 zSv^NTfQE#KX~h?ukWo?!aT2<_X7vj@cD%3#FM`3bkoy2ah>g`vJKM*%-?_{0T6*Gz z;savaKej&+Pw9{UzwD2{dwWpN8k;n2;)J4=cp(gpgDRg> zjH(-ND&41@Sz%p$iu7XydBG~Vp%5h0wkdwTZnb?a49QGAU8Q{aa}XO^-pEzsS2iS) z*^-zkv!8U4d`3OM(h^^OXU|pqLkmd!3}0yl)(>{wfW$WVM>xD|<_>%qmhGIm69(^` zwG*1-VLNB+pfY_)dQBWHJIK`C#PEI$g1RDQ_Z1n*>I=ltN-CigBvPvjLgNQ=_gcEy zBIr3mwa5HDfr9t5zXL5yKvU0S^r9^By!aIVGkY>p%}yt6>A&G}ch~Ys4hw;H`vAqm zTXI|x{4yNA=X2vdIZS*@2_ZgIJ)1v~o0{n_1VDgWq^LfkCKf2bAS7wLKR=cZs+B+n zmLIxV8ydMhqJ=ctF2rdOy?q*&f}yb?#_uXKU9sw^hq#P0|{rHENJu zuWm+qT#dLI)vMCmO#fK_*qEq@@Q@%^C7R0aI9V$V6ko4v`>+5>RtEJ+wn!%P#KO#) zl8d@U_VF?Lgn38VR{yUsrPA~zbIJdI z%pnT%W|Nrbis;I)?B}4T{QbZET$Y|#9m%8n6ckEmaLrn^YQWD(E-WY*BcUN_>9tbZ zvrqJo|@%K^^lAE85YYY$kH(hzU;=Tl3*1o3ma^Kw6ut9 zl8H(seJB$24`3>h*L!-xxQkdqU|WHB=c!h#H< zl;<_2pm~-z`46h(18wovl5swGKje!W5#%&Y#LiMX!k;vQq^bcg2Bwf*Rhv+jjcZfbCjwR0oXc12OBf|ed z@hD%bG1>oPKFt;K=^l^5`PAZ3`d(GTQ4SuoU%kqLQN)CPEJ`q8$ME4eO^ZYkg_VTI zBkVqo#KJegU_X#hOf)gaWXa4DfatCmBDl(-vv7&BAgEEctj9d4 z-@<6=eB~ZynX$4#%uLi1W72scZxu*YON|l7Ek3vyrd~PGb6L9mY1(9 zL*po*>eP7|$XI*QJ$$9H&0&|nThQhingFx)>zphcR>#bQq!Vu!nSp6CVi;2NCw)S5j$6lcjZHo%3mq_|ag_Nc{DL2+kV+8Is#-M(!b zMf&+2ZF2NMn|7cuykT*I6MWyvhSet~JBJC~_Lb zn=B7EyFy;#%_dYa8)ofpgGXppzy?iGZso>CE0(YP3FYEmja|vl6E1Kty{uqytm_S# zw01Haqjw47b@>+iJ`}H4GHC5&xWT`derDef#$6~*5c&Q%t1Ec}HkPY>{w(fFb9hOc zpVT%<&cD?*e`^>xc)i??)oe~v>GQjjWq7^x3VZJ@{=L{{;eQ} zMUQf=PBv-c?i;nDG&HW&gw(P$YIKNMgB+*hX+jpD{=638M$|XR5}pdX@#pw#lh^a@ z_Wakg!6NT@LlDM6K-2$FcVmiIMIIbqW$>s-taBNh>k0$ z9X^XDI2K7$b}U)4gZw^3c64$8({;{$L~b>ea3Zhvw$R|9C-9aU=*F9|3~yvzm_h}k z(X8>ORLCFAQ$Cwt{KXf=pMTyF5+MdJg^lzr%4AUdFzT_t}`{34-#e zic>@Qs!%^A`q0oLdOxmN3Ovz`BXlTbgk{OFXkro%Otd>N`lFnb?jLom)kMVdSLGiW zz5?NaIKvh4;Qe?W%#Y)NvM_XHF|LI^DU-D=PB`Y4wymz!-E6H^SJ!GU9w$%M>Mpic z@2YE+=X$->+Qqzpc( zzn_m=eqUuHyP+m-EIkOI71Vg#fDTXUp5{=2Cg=6Vjz5I-PY!Zjew-H@6X!W^EW~$f zyqWa;(0MBm>sjmj{F36B=csstz|RM7e^m>Y%T#B zItF4fC#mvL!9w)>Vw-PrVss=$ouCyoFZ-M;e#xDJM|qm=E|}sN*PXH)7UH_SON9(MLq8X!P}r!-x$S$t!`tw$_;%63PwT@v=Z_iJ%{FXJP{yp5T8;EZQX3+pn!?LA|LWD;rR1uF5ZKLDpZ2z9yoDxb zRw5kGB2%&?DYR6otd!}tDlFs@R)Y#3mlamb=c&(oh)oCBkEK-rw40+cVxw?0@Walz zb9Uihzq*C5faSVUv~tyS-zeWMy z2qDz6O+OQ@IEA|tNFvk0Q|s&TA2oX@c4k|@?3voY2=OH>=9M71&6<9wP& zN7}Sh+f*voCZ6c9l}xwQ<2no_F#7fJdWsuBblY$Id$?S_ejdfqAEwhg>7iD3S#21Of3d3rt2bxs1jmTvz^Gsx&V5EA09INq@nnW@puUM zp?m0=#BR(+29k@BzmJ zAhM33GNqUROxB+>nbpECD<@bSbt_wFMUlz64Ui-lWut&1B(+eh!tn46?84JT)7niY zqe&0KqzPgn7FTXNte|lpb{K|NqowvE_L7gKyT<^Im3%|gXSCxS^yU6n65c4+m9kmg z-p5C{C$K;kj#mHzk2~Uf3B5iN*o6__bXgjdi;Ji~(6R4T`~q>}v15*04Z(oO=y@W$ zCCnbbpzgH|nC!+8*}W)blkfjfW!j48M60-gBGLHAY{8Nwg-L4dB1QI$R3Uz2S}4ds zMw=>1hR{J_8i=i6QSr6_#TYo$s9L@;ie2j0^n6SLIpt~3*=jxR8I761iwN5L7N7(dshve8Oz>vGAmBA2{1EfGpH*bc)9-tIwQ18+U<&h}_^{(pV)9@ul z5J3$|*U^;Ou{;BrRD=H0Rp=4PEgy3P9hXw@v(H`C`8|ps_;E3ph^3Eiozb!nr5|B-%Qc`RZ&GYy3 zF;b|f7#Gf;mqI)z!m<(>j3hCN*uWCm&sa?l=B?<3c3G;FS*x~V06j)kjuXUGU^oR~ zfkIfE5D;Q9ga)bwfkc)#L$))iD&B{e7+%^Ui91`jsRZ4Ag;=Ornj=a--5j|!uV(GD zzis>^5TR3B!eA!YLeFiM^T!86FmwmJ79XFZT*QB-#C;fBPxih2o*etu1pzrfCwqQA zt1X#GW40^BfDmtqNvxC@7DDsQ42lp9(RyEVs3AeS8WBXg8p*o~vO?xlN`+nauc){2 z0!3O+XZ8$>1W|K`JUWXG+`)f{lcw#cQq|&k=er*r{g5JO;AIiUn7D7e!i5XrpJG(xn;^-bKhoj4|%-C7=4Yf_@ayVBnID1JyGOYH7Hg7#a z$6G&VNu)E~!0M$DXCP2TyK(_*x_l=Z+pU?yR*Qywg&uy3zdhG^@hsS}2H&;Y$HEav z5Nn3vE6?K}Ywk)}U$}0y;{|$DKo1Hip6nf|3Cmf}u8^O2hDj4btHhUK#{4*Dl64p^ zbauz#!v{K#9R{oBys4sbp+1#=*f$sdk-9r^{(z~^88uWcBEM98NWQ}Mno}&#IY6Rk z{MgatRZdN{o?FIK6LdSNp2!e}qS z;D*S6R73_vPk#19V_-md#1XU~r0@&Af%QYObBI4k#5)tsd=#LfF7)n%c5%m$=3(bD z46c92oB6-xjpofC+?tThp&=R*zmbD=mCV<9gWs70$^2?n{?xC2jQr_+%w^5TX7V3X zt_`sns14w<8PEgGW}thZ%Vq$F>dzlC)L`$e#c9gN%F$eg4=Ih=d+(^cT`bq8?3$%9 z+YjlQrI_*zckVn}v&e1DGR#dSlC){g^X5kn<(MEt`TY~8;iJ*eYY8K_dJK$)d|IO+ z43CK7xFIU8h!5GaMl!w@F}^xE?<$)a_QVbyx4IhRvx>^+&T_hiW0yo}*d)-U|1i$y zFxmhKU7dI2EcrOYp6Fx?4G*K0v%+G-V`-+BQ4vBR)K#Z1n5^O;AH+6RL`-j_R`n1V z@CuJKEmuI5?neGXA_Zr)WF{fC2u%>f(+LR2_8#>4y4VTow<6W7ZquwX5S3NqA8xF{F!}eEr5r{G%-1SukSyinVK&!2sk~EAQQan}yvvs-xJi zT(A?C$VaJO>xIWl^zI~DSZ?!;iU0vH`H2QHaX)dk5Zso@<6m34M9Cxp?FV^>ofWlIbIW&0ABFvcV#;LyjUn7+kl%y z+&p~pr;DeRg1K`Bten47aN+7Jf9mx$#tK)Vxw>YXYr2x*cD$nEb|}Kw&cCS|>oAb7c8D7V;UKh)wqVtaCWiT3h*t|n-^N!c_I<409A~Z5Qb(D^+ zkK#OW9FfI^y>Bp*br+|;;{ zo`U4%b^prcNk*n8F=>bwjG^7amca;WdBRp45Z!n*k@p9p@bAb7eY!3Xv zd5QPr+KS?`2R?GFVszvO%Zf@r{KZ&2I=Qp|12)FZ_pU@Bd{D#*| z5CZ6V2|sh<2PU59B|gmQrIxlqkF1~$FIAez9aWa!)37ryb_OPX_dL9gzsJYO|NRIX zXOG9zh;~VXbcn;#oc+0#dk>c!9#76HAoW9T%4sJHCB@??DjDty!>W(E{-W z6#eKK5YC<{aik)@7e*Ft)OC%>aJ2Xt(m*mdw-DZF4bZl>@Q4TyA}kSc(UJ57+C+0_ z!y!!fMJo#w0EZ$20zI;jHMoBxEzL+aMCNj;7ndrN)L71J2$^+~XgNuPB3TnPw$U(+ z=i)Z~hDi`x>7FG4Nx1YQVz;nfF#b_=Ng%-F;cd3&^;^^8?Dt2s?oj@FId3aPO1Ka& zqzhebfvMG!6Db0Dkczyjk9J*JyFSf|kP;040^n_hi zLepJcL4s9Lb15>wBZ-1|+P$uv>M*C49pyC{{~YUCyp{Cq=P!zORja*z@X0G^k99!f zX%ogyZ#g)gco+dpy z>u(!j(y-abM^79y=Jx+*#DLelG9qy#4vKv*IgnvRX0MBqv$F)oGQ=gm_DA zR0Pd8GMn7`m6-yfRGk*|pa)j6B(supWK=a|d5X!xkyPC4<}#pRk3Nv`BYj{7O0w4B zWId%jhKviuSMAnEf;iHZ1SH$vdgWzf$2PaodjonG^v91B@ILob_pSr-?^a2L=V!Lr z+-~5?78h@dV`k-M=X}&Wr&;@>JJvl@m=HOsYeT|rEBq5#LVL+-OBU8puaqJ#kWX=u z5#9{3&g0BBGk_?i#Q1Pgq z9xWU@V*1hVPZz#kD|zp%Nwz7Lu=pj-#}&?Y9LAqQ&IwwR6n`Z?AY=W%D-ZL(l}FhJ zyYtZR3g$(5dF=mb(7?e1@Kp({=YH+hrFZA>=#pr^{?DRjR2r~xf9s~rx*p!Y@tFz9 zadUfjPU;a95ZpJdW7{rx1eXS@G3~r%C}Q(tkIkRfXJsfH2G6?aq4WkqrtTz45!?!~ z(W4@|TWHt*Jkd1mNlod-!aleu0E%;3!6UBBX=53Up`sDF)hx7Bq$(vJ-02#An31w@ zins#unv8SPj5oh{`-Dlli$m}jyzCfwK~1!`9oc&`iG0kQ#uNw((%BWl+4hfd5`}3o>=nU`=?CU`Qas-l+w4el;x;SM6+d8 z&%*_i_H_9ZKO~YtKKK#YH^2NE4qbvX>}-zArMYA-#RxMPR&`-Lu5QC`Ot&ayPj+djEbNYbj#n_u|6gX#85#B^<)KBVx|lbv_V@q zwyKY9$)-Q)E3k_`UxV619k0Klu@xinGj==dwWAKrdk&zZdY5jCCGWp?$^-{6aT;(F z_(&bp9*6rB?dZ%0mFa}O#Ac&8U>2b@&5MbS3Js=+2ow!gzrU$Y@esU-X+se!5G}Bh zB6y-SXo)huJnBtWv*|sPm)#9DbP)f6_dyzJL&&E7 zLkK(zK0tOr=vBSiUW@g?KK%DP4`9Kh_HPxuF{;g_JN*8sGx0NjVwkp^e~P+6Z#g{p z46OSHs{6<)tGrrZ! zt@|u#N{k(@m*UsA|&b)n%=NKy)h2Mi2P)ucY25O^By zxQqBY>JlprW$`E|oDCu9$mY%Oy}I}0OZeQi>e{P(bzN>1Dt^Gg!=7;@C&&fr-2TxFIKomIdNhYan zpaLt{=Tzb|JG8qL>KjX=)HvE)$)Vk!FkgC<8aGnJ>aVhMZhr&xBt7QX9&=euDt@+2 zz86*q27Yp6(0qPYw~^MMR?qJzp(UO*sA=5}(q_D3AZoKCS$XA<)9#J$$(_~>+o!|-zF zGMvu4I-TLd{c`6!ad?Y|Z2L-=RoU+HkZoV78J8`%WXta#PU?3U1=4kBsor6<^ti*A ztJ5ivW-uNI9mS1~oMZS+qa%(L)yAHb8<(C&5E5mvuU$Gq0<3uDj^au`#qz$0iv%kv??~P{&A>b9ap%9WREl zOz8P1L8k^``l$I+X@}9P1(A=Q-q*`Ik4J=0p{>eeTMr&L=sX_j@5SZi_>sAsMy@-J$vTaz!fDb^PNS0tjZB@!)j@%rMxZ;5S~`tu!WRrf z2)QtX)V}X~;Ss(iyf+tElU=kgZcFvrgwK@98uOtK3u9 z*FAlGF`2M+T18!_W7s+c&vi<8xuVkuzGlg|YEZ&vy_cQ)VabPD7Ues>L?ch|Mq-qA^&*Bi?19hA;kqpZ;(bMh1nQrG?< zH#!g5-qDHA$#x!lhoCTC9_lp42w$^3nbJ`AWakpb%WFD~G2K1)4$4Qe(OaicD4c;D zl}3&mAG_J!!D$qBD8F|wxfs)RI-`ZNP*0^(&qFSkbvmOvmft(rI5B-zTb+|%!$^I+ z0-2mgay7*VMH@G^hjij|vU`|5dI4^Gh&qbwJ!Gva-Ub>s(M+uoaDne5;JJ_7rS=sx zSKD-9_7!rouQ;9hI-O=v3G!4rc^-6(IvrYTAd=IG^rZ8FMu*I+D9BRjWO>k;tI;9z zYGb*1#p!g`>EsKSpqEOgm&Z6*v~hs^9#uG%DqNoZ@fO8f>BnhMoi2L`+WNRFoz~yq zSK3f+eas_m9X%$d`^D)zpn!@J9r*Y7CQ=@dx4%E^?|>8I1l7hW$XQ%=WQ zuLF`_$wQ{jT2%Kb>vi3S@d@Dq*RmJ1KCMS1q;JKV{>{anXN8XGHYR5@LVlZk*Fx;+ zEE0r)18rP4J??u6Hx}2io8_hgIB5hFVpWcp*p)ue8Cxp_CP$tpQy{Lvr_K# ztZoZE6bD+JRpn1q@gQiDvImDUV{_=h(f@&F zOF7mGRPtQDvKizVtUioX2`{kIn`S#q633J-6UTfC6YwH|V=Wa(^;q0@?o)CrDzmx} zG|5wDXV~-#+yuPry?bJa!m4kpZ&x{>Sr$?~%EdAmLw^V-cmeq-fLD&7w~tYFjyc*8 zeinceH5LCBe1s}Cg`x-Q;~plkNk~_nz|Sn{Kj9(+(^Zp>XuxI0f=L4gPM$Pyz+}i3ka5RkyqZko7PJZ*wosii}ArrkLD25I}2q{ts(O9xz zrnlmRds>K$mz(nP(vPqxuCxY!pk7A;$AV*EacVa?FmMKVbltONoa|Xa&f`;1GFicC z+m^H%my|dzcggl`i`$G(Od8W_*)~Vi=7meQZCku(i?}SeakHka8aHVPC$-;7+O}-g zxMged+Yi&x$>}g)#_sy*wX=86$eXzz30tCqF-@zdm1x22Cu#%;vO)%=L;b(rz&}FV8z>1E!n`1u$8}97LObg5w3+7PL?dkWJGpQnU3H>K|&*xCUzn7j@GT5Vhi;0^78fabyeavxJUA_9A6`kQh#u*aXM0KFxDfQ8aE^wS9zv7LEy<8B1|*B<{H$5WaJmF%P90Nz z7bm^AckgI4-mxEAA^Z;O+Yqz_IpqUnHI379NqCJM_nb~^H(LsQsXwnrqk?qNw;EV+ zSJy{&*OEj_qIk3ww3b>qXxfm&G?y<21`wAps^zr#$D1@tZx(o5-Zk0QV$DlfhEoH& z*Qnw+C&oEh+^N)n*%wvWUOd}58IR=qIUcF*k?lyEVPs4y3kN9LA^Ep5uRItVL*qg< z1Rmn=K~-j3zRZj3&iow3tEh0t(nkWbO@;uMeVU@pJ%8CIc`40-sQ~lX;@n zjZwD7?lhE?e?x>xh}McXSTg95zBMB~nf}!Fz>lIO{m2j8MRBp{Fq9^lQ&Z6!ugWjK zDBU{x#SIDF9nrZ&NhFmrdU#yCgHN!9{a z69XuO01xd6Q**H><_N5M1e1!vAOBWdR5W|;+}TCqhewWNr3EJiM8#Um zB6dv(k%(EFV_xovM@FMQ#ayuw+J2>0hT@_S8qmPF4Ep1F|Hc4W#ErQ2`nmN+*AA{b zwc&kyX(jm|Snt;#*Ce=3Vcj|F;0&$}XW%!qc1J+KaX)_uyN8x-T;}}%;{5$i`UmY_ z=evvsdPzbdv85N1zQ&N=))N{CJ~nf9gVc=VII}2u5w$=IASE>bkD0E9W0l!C(>-=o zx>us@NP2P3{0$rC&Rr*=R~y#LYS1t{vmu0UUA}C~mgUQ~Zg1J7Nvo#K8|NOH?x;6i zN>qlf-Z``F%-w5;DrwE~bK2UvH%l!op1Eu1b7ZI7J%jCuO}ggW#7|q6ENjVZ%Vy5| z;&Q@&6wxXsn-ZJohmcoQ*`N@ni5xR%TA#)kGO(b&3>9mWWuRYDuHH=RU%O7f8v8dc z*!A_h1>@4HSgKW5+H~*{#b3@F%;tk$Ua;@z<+s;XS&a`4Xf|h#xTsqFCcS&(!%+X- zKB_HbY$qS~r?GN^zf~xbtVF=&-#TTT$ET=h)@*Nsz zqRDKF}2}Z@n}NMb}x}D>EBf-MR+t@Mkw`;P*4?)o&aEQ5r>N%l#`kBx`(*8I36VjfjVDtiOe@JbAO>h5# z-hPnt4?~>1hqMQ$11)3i|KjbXK)wAky?rl2e==<^Itf3#eI1qlu(Ium%$hjwN_p~q zAy}|bnMH*V%Y%%GBm{(TTy_rZoS6#AL3G~p>;2$RxCKGb5ud;MBfeI8CI6*bV)&gM z+a|r7ux|MD8LQ;`_3=>r&G&!cQxNgxPY|3@L*9A5M#+lLH_oWtV(-#Pd#KLY>Wq?p zC-cETY#Smz@S=(0930~Ji;mv^k@9|$&p)cBP>d`awli!vU)t70RC84m(9I{q1oYn7 z0OAZRiDGui4AjB#rqrU;DMBeqbgYq&u0@}s6E7Z>9cu`km(d9Es#ufRQ^aZ@bm+yk zc(wE+u?ZS+jK@L}C9#Vo3EfBOe-pqYSZN5 z<8%+}PkexH873|D0laL+npL8$en=!Vf?ZJWT7Urqfe%sf#6nocXoiJqn83^oE@{KJ z_|MCmZne$3_3{<`HyFR)bUUx@?N=^=**gRS4$Yo8{ZZl6NwW@xh8~(TVJbLp z;;)acT6Gkv-^}_MY8+m^{4oCN=d}kP^-d_j&iB`^e;=SAp;yU)7a492&PCgl>OwT_ zt3RS+P^NHk9d}H6Sbkt@LROq#Kvrm0FYRw*6k*9Rwmk&$k^y3h;$vNn^;A>WUE1> z&}HjeMd(VP&%;UD!)rAR=!7(H)q@k45BA z(~|-xf;rS+LW*Kk*a<;81732UgfZ052(Xa-;-f8Fe*U86vYv?zCp8~2@WKT&$Zi+s zz1{QZ`Pi6KAyIw$^nAN?ii%HGh45KdsZRW>T;^Z3NAGCgD`#Baiv!)hzpsCvEacMf z>2vZ>((h2AJ04@WC%-B9kd;$~Xp9`8h0s>$C_F3lA@hBRFhVF4#tTKlEMcCoNLVJU z6xIkeZKWs+P(LdpDK^3v znL@p)f`{!PGaHg7>rzWHAUW90P6^@5Hp6OASX;7>22i*v3x%x;fB*~e%@Q*xrX-}R z)ul3+=2U;&e-GjalvP1i%`rL#iEh7(na>RzICJLU0W%@4=a4#Sm8*>!@ZqM`jT*OZ zZL{Ty2Qn+ys?!N6Lwd9y+VkPD!eesflcW9~0U5{Sdr)Uo>34FC^o&|XkO!fT9uVT_ zNz4?p>-P_zZBVa%*0ZG#3fcb*@uS%PP}72`Qwv7-ojkekH|^R~Z|>vQFgZ8Zap{|8 zd3nu7H*MFh>4s``s;4S#+xKh-Q%c%F_Gg8KpW)+5EX0i4zI`0NzPUOd9 zIQGAXb@?l#9&yQ)E3YXndQ=+nu!#RdW`0k{1;a&SU!v733Go8G!Su6vC#P5wV=dmq zCzi<`B+9kxWU>Jv;}i?&+@lOu489N&W(`Rf$y}vBQn+}iG^ezw_FFT5Y2<^Skxf z;bBC#GkzSw&Spcl;ROH zAT;P1AGJR%23KLyt~jC#hBJQ?X9b&~>vrY#ZE0!ASlCHZPZ`dYv|3b@4~P~IrZj^5 zIUn37(NiFkt;w0`$cf~4)~$a>LA%l*+P}w`DOb-r$r}rL^z7{v4h|kRX!t>C>8r1FoMnkz(dYFy;1NF2 zHaD-+wpK0L*cfkvoxe(H(n}PB&nB5gW^08?E)%J&|0PvMvQzl(BEAEm7q2*EbZ7kd z(Tf+49ycE5E5|+uudnUr!0YoP%80?QPWgS>YePnHxzfHhCVexJot=)27YK;=i&r3G zAiK=1TL$la3kmr9Z;u}z^WwTfX(_gUb?zMgLp)RZ`)gCbp8UF?;xvk%6MD=>R3v6c z^7Cu@BTm9blvnzRXmjj?zo8T#`$SrL7#9orv)?gZ=-!I>vsU%V*$zjs*v7FHiEstS z)2GgBa_UXw6vyme`b?s`C0RyHnM6}tq~3MyAKt~6AmPT1QW@QzGGW^K4YLa-R{9mL zZfZUhOc(55gZa~KN`4O_s_C!BhMj*)<4>BR_l?@f7ONg$oi0uJ-SMcn7%9KQH@Gqp zj}O@Oe!)!goXfVRyEM!!E+${HT%2FTCFECs`geiJOa(vCCpKDNeE);f_Y`zzSbp9> zX=&+CZ+(4mpVB>lSa`YShO__FP5%@r~=(@O6l~ zejQ@$E2d3f_Wbl|%i-(={3n<%*w53FTjycM#*H(6f9~a%pX2YLF@h~v-N*9pA&!FE zd$ek5QVaa&)vNdqFkQV0-uCAvPnt=85PFEOL8XVV>o0m1{ukP`fBz=j;nlbIzsB}9 z=P$;E(o6nqZzDF@FVbjcleH#ecbDFgiY%8FIyZ^pyP29}%>FL_p#I$eU4@523U863 z-H~z{2Ca=S2`ZP1XAL4_QJ?1ei@)=n-Eg;Df9>yzr2QQ_)eq$qLiyioleu$|{k@p) zyAUe4wNUeWJ4jQdrF?H@_%#CrZO@*inDsrohj54NE9~vj`m=0b&(zy=gGgZvZ!^ZT zO_biIi}1cMjPo$eqmBHI)~uxsT?{eARr(Jcm^YfAi9cY;*~^KTs1~FMvTX*OH5Fc=*HE!u4gtHgSSl2 z_VL~@17?$N|B%n`>zeAWs_tJMUDLz(4A$~V;8t=@jK)c#@x?lQAQ)nr$ILEX{TPL) zFJENEKcKQcrj>}ce_c zA4ZCTq}iN4mySUMO78=ZY`QcQo<~Ll>{Z^MUc7$$3xokMcY4O`^yzU4X5b}kJd4`R zZ6N>mBY(NHW1G-BBu14uJ=@i>b1mlDwZsGtWosGA< zo!n&d`08}yka1)s^QAhuDeAICZOgz*q08a$6Jjo+XYztMWqBUzSUg=vvc8)=?dKBZM9@WVQ)6_~dc&B8^iW7Kv+gdaDjcQvEOD;Ogx&;z#-CoQ_}Xq4j-5pt2jDF`9R@G$GstPAB5f!Ob7ExTy-$L0>KQx=G_8 zVV*bBkGJl4U+s8|%8`vb>W*7T*p1hjNzW|QIkSw$QcDxU9pH4jExAtIwb9~t0$11d z>}xh-e8{7555o`@dd2C!azto8!!+>}9~g$jXa;n{2Rs+dq&8p7Fx67W;+V&7k|)p@ zjLj3GN$nPcv9onSd$v@4^kXn~Hf7qg88ccx24mxbbiT3PM!nU~T%_w@bA&9?Sp~(p zu_QOuo}E&Vs!@yHK`r7OJ0lwDjL77mHi<3vvG6XaY0%G)<1HhFxJv@VU>_l*`uQyvCH>O_>kqEvNa0 zps-Nr-lKHOZqhxKf7-s)qbPu-I5^cHDNb!2O>q)7`~7Lj77I%$&v|~iYo0^nE*xw2 zv#6GxBEEP1sB^M&q~QoGVJx*NJvfm<$6YXM*4Md90kj&k9{z6 z`LKbtbJB(-nHigYo!6AVMpkiM`{ayj0vL2y+a(VbT#kNmk{D8dK#mmb@NGd8y z5=IyD<`#mrRZ`?QcTd5G&G`*{CS1pJQn~G{-iouPZz&1FpP{g?zG0sN9`p|h4&0Iy zI%dhRLBlf>!9szn!nj5MdVm)zw=%^u_*ju;}L~`eJ^J9|t zMz*)3jc^2`u|!GWG8e?|WjHy>+gUBD^Qy|-!4dRMOL>1zP@;ofe>WR1S0B$H_v-N3 zxmKn%20cd%9yxg=;iYLtlRypk70c~8QggEJ@&+TQq1Rl!OuQ_70>45}$?euzxnkN> zV1z%vMe{xU8DlN`yaIoox7B^*-p)1^4Ayzv9^K%V>;7~Lkq2kAkn{)9I)q%Rv3S_S zxxbTV9-8`2Y&Q=z7}n+j4lP zE~j+q%F^sPmavRhUP3EuodMMR`=98=*DZosX8FeVDmMoBF{~)X^JP%`IMVxbTh5fM zUFWt+yb_R#B&Ou1S6Tqv8@D6CHK;gh)j_YVN#FhlJ^j~pbQ1*sC1u%w^$UuZERvtG zwLW1z;M}H4|IimV{)t|LK~KQ;b}(AqC)7W7!{IGUS1hG+J78RXh~=hrF+*CfG5{uh z?L3S*a%IUs{Qh`5Fsf5K@~34#qo-&#+J5gIh=l_hPSMZPoEBrPBl&!f{(#;+k!ODO z`@PJ_wXAk;(9^;@&ab=m)$_LRp5PQadyXnAW83#%qmCc0qQ?Sw09LCCihz$_q>Zv^ zQ^V1dyM-w;Bm4p;+Kt+}zUk1h1H#Oh$sGHA65?0HUVzS;C|>#lw5=WO;`i~b9qxSV zNrneBHpBEL+A|DH=(4m=TYH$u7NL80?x4HB)|Hjj%Bs}{=Wg9P2cN4A=9d)bz~__? z@ppWd*gr>HnOMu6pCfzJD zPhkW8`0abG!i9V2-+YKBOv2IvZ`_Q1A{g zM5*m46BxqzaG=@%Wq}XiPvmp7E+*+gA=O1a=(qa8Vwl~L1mo4`_?(uO5 zpVZ~CN+BUOaau$ghQx=>f4iR?lbrGT-2OLmcwZGeJv$}kDEuU9!r1r-KcW8M-fdHs zI}Bcxw*APyU4nl?;<#y12e7Wauw5;&eMpZl)^*QLj1*gL@o`b`xx07&sy<@~gP*C- zgAh4rI(7BxR^D9Q3$%#67}#d~FH}#zgI9uRM18!PF`+uh(K9DBr`D}1=IHrX=T0IG zu-+Fjuiv5>393}tW^0RM7G^bhu_Has{(1kkjzg>^*gcGVG|OdhNCkN^lY1|@Njb9Pz?=#4zp){|lx#~vw_CCfnCcS`(!vL$Wq;Pj{@=hI(^>rQL=?PXkx{eq+e3TOF zMJ1aLTWL%{?+@P*0JX8HvM+BZS9*BbDL_N|<-1eSwIflgO|sR%t1mhUt6E#|{*19;xVm@m_;BSQyQ+o7>-McW zw|Xy{WMgeSVP?>1uK@bH z)YmVt7f1kqtN+;80>GNGvih8Pf}x9>zmMOfL6%h32)qI8@mvO+F_E>mQMYqsp~S%k zJeZev0;L&%T`g!9{|~_k3|_NlO+M_81Ucvn%{ca!&NKKE*4zJu31EAmU*K2||HDw& zyQFb%sNeWWhZz3Ze?L z=26V!xplHIxIrM;YeK$x640ZcS&v>EPtFOcwKyu=M{Bo*r;dHVq1*7$T7GeMWW?OL z5mQuYN(Vc)kwYAm!e*gGelI*dJv=-mCEVW4&ECP?o#AU7{<99t(hcX=wUh&YSia7p zbFU7;bX|RpZYzv_HpmY-(X{D{FPfTKPQ-+TMMqBvn+hDOckZliTfJw`YB(`AcH-rT zn3xF0-yh@S;ZA(~4Q%R5V~w|9)2-x6=lp=vH{YE3{55)YHgt1{gI{5CScY}sv^Z79 z{>r3;VNPw$yKbq^qEC-J>}UCzxfxjNK0IJ8^EV~2iItT}vBh??!=hC4ri9MsXT&aZ7+O2?gCj>im{~j2 zVOi{kJ$uy2p@}oYCeD}vgZ(2X2Lwb%b5e|!F5SH{j1eG>F)7CI>4!G9->pYdxsP*>k)}li$PP^uxY-{WIXl~Ves_dmpp(e2)H#N1m znAkiDug$A7hJTCAX_3K%HE?#dIUG{)p|auKJI{f|)f+fUyYe8WIechH)trpF{%aTJ zyjQsIqsFztAx|Iv1DK;9U!s6V=sz}tzOb=|iul0vjfXy3R@2Z~cL<<9p7to17U z=+_x;UwQN9%9AH^^77_90V`06toqs~d%yp3{*=`t^Lt;^d&mO+;;th4C(r6O9Mr?`n7M>> z(}{BDA_|=(WW>FU4eAuOsh1J2*J7?IM^@Y$NYnK=tkTh>=RuiWSWBEHN{AxjE~1(! zCvu5=;$F_tq{d;LiAScXM}tYmHvK0|@y27mGaBQZ1T>L1IC*F?B|UHoP~se8zid2j zijgMYmWkQ+mtqWg zsD1#`^&x1r4|B{i z)DJN*S;%%O`7FNZ4e`ZU>@)9hk7DCE>?XfN95p{?yk7G| zUo>F0sk6_OeIUNrkH>{&uQFdhyg}w4kR?VrhwR_ZCH6_VK1)1HOby7#?6_N;79^Nj z{|asV3isL4i!YPU&YRVUsY9VT!nJ>wV;n=JwO)VAB%b_gedPks+vEd)M(jL#Y5k>m*~ zAHOr{XqLGoS51k(z&YkWLLcv>T}L{j{dng-xT@7}5A~7$-RE?3PZCeuhs`~%O>)xe z;0)XvY9r&n)aGIf_S?PL3QL@p8GyyWGU9#Zw1n?1ylRfm%x5D_r-oPW?(;eFzTJ{ z*d0m5-pEnxb-JM4KXQDJNJpKwgn4-i5vyxu+lRU8+9LvEPtzQ_6k}o!9Ph*bGVeSTYin7PGavt|x6uB3$ z+|9vE=kpw^5??c!DEEGX*={p3y{kCj9_BtYR#Ja*o#&XVNyy?pYDBZ5HVf=vZNzh2 zSTkaI;In~$-YoM=|IgXsQ}OlB4E{;RU*SOSt@g=TNX`JG@aRCbne4KL?;7xZSpWLt z-tS{;Zcs0;%e`xHe_Y|Gn$bXHG7z$Qkr>RoNgms_@;QaiExfG!s^`waTsi1&XT2wM zGmJ{2jJJ2C~K|hO3ok!c0Q2RPrpSo;r%`(~4m_Oq|o}=ePUgtQ2ct;wIM)wR>c`H!l zHDC?(b2)3^Y^M>e<}J=!jl2A`H`)Rl z^agDd1@|NCrp-1+_t0y7z1PWkn~5&59r^hG%oRI!EW|Et{$DIE@LSqK&WSR&Anpf@ z$!sL35q`V=oPSu~fl}(!J@mzL;%=gh*v$L#q`ondGk8u8E-pyz8 zyEglOfKs`WN?b`i{ugB-rL6#XoOQx~NZN@40B~1cb&(j3%q+E;GuK-4 zJTq&pIj_9E=4#h-(wg(EnW?wymOs9lxw2;Z_3O9hoC^_&I3gk<;usMT5)ly*5iuen zA|l3nf4+YnpAQ0op#BdjqUT(~IrX`d1TbMP5s_Gts7;I{t|fj&;*ljt0}?_WexvvX zPC_QNCygazk`2kuWH@;y`5*)L@}d?m z;4d^>m_TFD8Z?MryO?@Wbn*4Y=*68hY+7+zQ<@_!nzr>_=XVDf0cQGA#--*S39rHU){#j@jCo#{LJ^n@5ip; zuPLt${~-FIJp-8$%~-gOypFmKU!ToHWHw~Z{;2&CA|MG2LLC7hL9T8uVNTczz4a0-9|upnA6R}e4QEjXno z(J^!)olh6hrSw+1jt7n0z;?1>c8opGUS;pG&q~lGnI-g+=90M^#2bbi zn;Z$JiKFK9aNL{_XNt4P+2kCSl1mw-PfNkl)zV{bF;~gmzDc;LzS(oreG|I5$;;$b z@S1o7Jct+KP4O0ZYrGxaA@6HhS{be^v#hdAQ>HKLDFe!O%MQv;_(VRHU(8qWHGD6B zjK9tQ!auqtztwyzT#hWqmXpdk<)U(Vd0V;ZHtqKG?Zb-tin%-ZJDNM6E0ZeGmE)BY zmD6|0cNupF?(Pb>0;^y`aP*V-r%fSU=n{?zCxi>aHQ|?^>wb=kGDLJyxyUN=R;5%a ztJGCJRY29gxKi9Bc8f#eDe-~$q`IP7R9#mMRtKw3Bua@#GA@~r97;}W5^7RwFg5rZ zLJhe_U8AdcT{Bs8T1%@{)lS|^x+l07sUz35*LB`czu$I$;QsdgFZJB|@%oMWg9qdX ziU-hxl?Urmq!cApNCD}*6EABkjLGsnXj2EphA}@~A2sKKbp{A?3YJu9V-g#O4()4mplcd3DGBi?+Q?vd% z@%IU>MBAiQYYkef)}{4m*E=#g$Q`T>eaBSCLdQzyqt4w|g)b+tN$ zF04E3LUv)h6kXA-xvqHER@c5Bp~vX)da9nQ7whHvX1z*p&^z=;-N+kZ%A)UZM@&cdB=> zceD4GRw`aW}O)@gXXAt*1TfgHXmD3EO-mmQf`r1lop)@uy`#I%Zz2& zvSm53rdbJAnw4*@wJNM?Ymarn8njMY|FN!H_iYFp-bS`n5LyaI27*W`71quw1K-k0NJ`2;?huhrM-v-;e=kZ;Pj=-c!if(c+c zNCahIE2smlpcjmQv)~H24IcYb{CGdr&+|+CO@6h%$3NhQ{4xK$f7QR|KZDRvCPat$ zkO-1PDo76jkQa(TGte@$0UZPo0Zf1p5C!Ccwtykv2!MfTU@j03>;_KZRQMW9g}Ja8 zmcwnZ33kCS9E0cJIJ^s=j-p00MrEU}QO{_63^PU?6OOfxS;xS!rT3WkCGXqb$KJ05 z(}UEYB&Z6yf|J3O;Qoiq55*r8AK(uQq12EtG!Tk~mOo-X3O=enj(^+;r-w;lY1kd! z`Govb`)T0Q)TgQc02T^@&Hw-a0RR954*-_{764xW1pop7Pyk;5FaQ7msR7IY0{{Vd zoPCioPuoBkhTk(GQA$!lN|&foZ)h1RVI_=?R3RZj2T-L9=~SslY#fWkhwRJ1g8BFS2w~Nc&6@!TX^B^2yde9eGuLve-`eb?R}-X zsx`TKUsh7EV&sdkhv&EwUc(!F7p|d;YvFag!*Ag_x@sWYz`lxvn`o(D!W-CDx56## zs6WD+XnBF~7Wt!a2VF13AuLk*rxC*NYe-}6UEmTK62zF4(If6zuBM2%+CvY04jkIl z>CiZ%$M)hfOX7*sN7lyENbmLf{9(vbr<{&cj) zSS_gJ2>xj=bb>{?V3phnkB4kxj@g6kNfah?E=P=I$QdmR&`jtv@p23vH#v&3Jh7?n z`@P~BtY~d_mDcW3t6Eh;Rb3kGSb^cGh-V4|&beoC_QY=gq4p%#M!U>}(adD$+MbEm ze$_E?22ZjS*E(AU{jnt<@OHDZAjh{UjaU?0nB%x#n1h2!mgFumsb(Qj=5m`>o00-i zbzyb;|GAXE)Xt@@0001ZoNd_!c-zL`2k;*_PD4%GF*9#nOmQ+c$Zgs*>5^uJp_{mg zTgT1}r7<%zGcz+YZ~rkfGxPS!x^H4Nd;2``_eA%(J6SqQB_ZeEzw@b&{-1xIM*D+F zSXfEPLsjIZY8pc|R7-VKPYpDd8fhGjrwOziEl(@ZinJ1~OsmkUv>L5WYtWjs7OhR| z(7Lo9txp@!hO`lFOq9zqThK(>lA6dzehN^KLexxQYN1xzingY0Xj|Hjwx=B^ zLQ#rQoGePvB$`ZZG=-*8J58ew>ZIwkBXv!-AMd#2JbTNDANP2?~qLb(c`jL*I)97$|h~A;^>0G*!ex{%3 z7rKzHp(p4ux|ZfrFCA}>)>D+C$LUFWj-IAx=vn%l=FyAvJiS2IQ9pf0C(tYO61_|V z^d)^wN6>sq(*hc#3}xwj%F&)QM0qMuiHfw47SR{9n3mEK+Kcv~z3FzkfcB$(X@5F^ zzM^mFPOf4vSMwOI;ad8e{^2^V=LQ~2|1xnSkK^&oJb{6K=QVjPUYpn9b$LBrpEuwQc_ZGKH{nfrGv1uHpg-tUp2%Br6Z_cD0Soxa z+{#<=*1QdUKp*n9yd7`PJ8*=f9OF1!oZv}3ncH{@Po?YW25#qR+`*kZop(a8Ge?Z9V7ANw>_99@$A|$}E{J zb7W`PMRt|lWOvy^k}_9%rB6~aPx@t@+<7qD*#iLZ9!smPb`{k++9D{Ts3R)X>b2Fl zL#n859bIQC5=W6Pwro{cLLCv>Izp&B)Dc!~U0-n|Lfx!}#+4R{CRBfRX6HA*-~N6- zJM){*n>X{`n|Xh{H}9T#7wLL#GT&VjR@H>ar9f46gfuK}$aJ4}(z@wUyrdcqT&OBv zQriUfqMpmE8~{$CisV6Yz!6lwyy|s87gZ{+)&Yp1US_MP0U9WBHi!hsp$fBA?*kB2 zS+?3dAcT71q9O~ZqKaKW>3}qo*X1A@WC zh`ZVk(s$V=UQhUykM|=uei^51cOrTQL;08r~wyH zGREdL#9TW^*2R?+h!FGf6id=o}t{jRp}fP0>|% z&TE$G1A%BgqIt-NJrm{L#B$Mdc`;ecYzcNw)^M~8C0`Vi3?5Q#fN#*L7^Mls2IC8N z57b7I9>YBhg-bHpxCfzjN%TDKF{on_W0w03)Yh7g=N^SRSTh)0F{phXy_zczMf5S& zxcjI!I`pU9Z>ew{2EaW;wJWEWaF0_R%NdJYVX7^XPT*~)p~xy1r`#v6 zU4yD_`A1nqRf(mcUJfk)(s(Mh*ss#iz^=5m|HsrD<(@t;h^p{jv}oVf;whzrgoJh&XrI9s{`)tn)Y0ikIQEV-+`Z^xy^tkaMXuI&H1>kvB3OQxa2pED)EUvAvg%cRFB5n+NbF z%1-2KnrOkr+wQ!nb@PU18Z-LZ(%B{#f;>AkvU_4;@IeTpZNjy=X6Z$te($H8dRFgx z`gwb1diPO0vk0iJ8829Ef5|97c{+$@gFUmsnblIb8?`D=8N9d4>o?c-Ly#}VHQdsq zZr5xIyTvVGxucJG_Z-Sh`?)K+0rJcqLH4Fr+W379Bh)jP{_hv^l}464DvCwemj%gt zJr2v6ODM@+t3BzQe8l6Z+~xLU8NKi62c~wVgm>zfoZ5xio`0pZ@$~K(hT@=K6m%8*=6B zA+tXS{|yPHHM_%Wc4sBbc03Agj&Do)i@Is&kJ_JQB1D^orlOIpe@R;Zx~pSmKZX6D z!DB8m*K_nfsV_gXZV488-^46|`V`i4u7x8DvDFXyOtPiDoJoOzqXnmn`dm1{Z}f*7 ziKjgD^%DFp)t*-FRM(45P#(AwMBOY^-`d@=t=$=K?dpFt&7Uo`_085#edos_0@ID7 zDE(4@qA^!)X1LjJgM!lD{d1fcDz|mYcxdWHCuFTZK5jA644=f_p^*f0UdMS_Ba*+c z<~JfvG4Jy}#WlsSOV=*6V)bY|X1>hEsN_Z7q*u7{ExdMWtQ{W>=5*z+-Qd`e@0y*> ze3e|(afTJt8!bs&&m{avq!|>O>q0ZM3I#q(q_6OXN6(FI+~hk+HsC?pO&xjguCZDZ?ouAD~%;E83S0>?ZCiojxT4Fp2++uN){R2lW zgp*>JdajKV0&A*Mj#@TcHRaqkTJ_-Ij46qjJBbNPkV)o~2>$m5ES$+^*v>ODNJ~mY z3J-%B4tU**e^Lw@wS)!TOZXz@q@LF$SwT|zBlNrOkItB7^o){fru~Wu zvrYWKZd@AT%)7buu5~ZoN6U8!GfTGa#sPCh(%jIoSuNPDIm$29&>q&}rf`N|M9SRwG| zCoESUFh@V--adbZGL-6OmPJ`Eb07U01Pf{%bpl}27SWyFI%%2p7RMN zG>-VEB`X?*!P92daE^YI=tgYsLPJGwhNh_R5%_Y*5+JKnh+nU{eSzU~~? z^d*jTX$obcP6!Lbfo3nx%P2+K!|iE z90^BqW`E{ob!&dgE)Gxd&Y^bwz;cYzlzjmoGTF~sS`h0-Gw7>u(}C@%wMTDMMmRfn z8}$eG9Ngo6vf_}k`N@hs$`2|IUp;xULjA7S$#{ob6^AanE8nXSQ8up@65hX0v-*J8 hAF=qiJMoE1kwcfwovK9D_g%F!-zoWKpXN?|{{Z0qZkPZ7 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Regular-webfont.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/Roboto-Regular-webfont.woff deleted file mode 100644 index 5413a37ee0c57147ef81660849eebd5c3531cdaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68776 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 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.eot deleted file mode 100644 index efce636a84d6da92d5e40498fc945e93a90e4307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33846 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 M>%j(UEQQ4X1Pp)(oB#j- diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg deleted file mode 100644 index c555b75..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.svg +++ /dev/null @@ -1,1191 +0,0 @@ - - - - -Created by FontForge 20090622 at Tue Jul 23 03:29:07 2019 - By deploy user -TypoGraphica ©Sharkshock Productions 2015. All Rights Reserved - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.ttf deleted file mode 100644 index e11f89a0f749b95a9001e33de3100be7a0bb858e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33632 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 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/TypoGraphica.woff deleted file mode 100644 index fef38ca003e3d02372d80287057424843e6bd4f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17816 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 P{|_V(EFb^?vO@>^k62-U diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.eot deleted file mode 100644 index f85324aacd32146dc3f40b9fae97c20273f43bd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8480 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 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg deleted file mode 100644 index a4ae739..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.svg +++ /dev/null @@ -1,53 +0,0 @@ - - - -Generated by Fontastic.me - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.ttf deleted file mode 100644 index 0f59478d517233be2269d3e7f719649444b101d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8288 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

                                                                      ?Nv5>2jM{^Uow~~U2 z`fzo)GCGE)?>72xE#XEGcMrRl-4&3W!(@U?cH_c5_ujRCF*jC5;eRzC?D*wZYkx1V zX`Q3NzyjAOI4$R-kxm8<3oNoJf>U^hViYHr5|ktl|6!#lO>LB+cIu!`%2F5QC{Nu~ zpdRX_B9*8Qr%?kmNJH9vi+8OV9UTqRu`sQKX*Ep8!?YHr^)S66Os@>nRbje1Os@&k zHLY|koM$YYXDpm&ESzU79Dghvf2A}-by%cC7ic%Xk(1{{V>3wP64N diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/advancedtomato.woff deleted file mode 100644 index 42512481990775135c4da591e761b1b51c408234..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6272 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 H0qFk=!5PYt diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.eot deleted file mode 100644 index e28f6db55e898dd8a1d9ead5318f7528ec9286c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8888 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 JAO6eX{{!P-6bb+U diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg deleted file mode 100644 index 1e12b5f..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.ttf deleted file mode 100644 index 3d062dcf264462eae98dbe9565560187362e7f5c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8732 zcmbVR3vgW3c|PZ!``*2G_wMe!`;d0E5ACjGJ$6_7k}X+QE!iO3*g$L{116Sj;YY9x z#s*^&Fr5r-fsz18n=~FuGbFe;kA|jY20KJ#Xu^azO*2i}nbMTf3=L({$@DQy6KU1& z+`BS@B#`#*o^$^5pa1;-dH&}={~?qR;v;7WBjp_*C=CTd#x1~HMA*Ck=r7AwS#A z7M2&tI72`oAB&YQ?E+jH51lCUQsz>15|JDN-oa=vA_JFx&G(x5+9R*CH|#fV``Pa0 zrR8Op!`par8Bdr0CHX(ew~{9lVpMg$82Bc5td{LoY)6z(a0;v{7YJ#tb;;kZ^FBB* zp^OOY`B>4YMw?OL#nEN5Oh#W6)&rmbAditV9Yel4+7;PqRMKK}fz>@P74Lvr!$2^5EDJMaEAcV@Jy6krBt4m^g4^ z+qM%2CMIgN_3Ix<4(}ZtoSbYn*X^5}y#D&h$$i^*?i?HYFs7A|P@`Te4$@+Q4Y@^4*(Jy};9+qT`7&J6eT;Q!!Fdyc$kDO)HOfA@wP4&AWh>N~R8T<-L>*X-#T9_~4^=cWgH zdKSrhmGbG7$jtHrJBR-0=uwHRCtC^Wpy)vcT?l9LqZEzpqdcI+yw#o5&PX+kqhnhU zIhQTe*?Z(ZlHSpz7n(b|7JttAnrqGuc6_6=bat@Hu5SIv2?QJ-&i@i1yts64!4f=eaY$+RM zxlazsNOsadAY4iO;zW?9Hs%wHk9Oqq9dym%V0loucs9(X)oXW_%9@riOr1UzZiHKj zAm>Muf+m)j$eD`}!coE%iY3x7_Q_x!f(Ut|V#%I<>cf86#rJVoqeWUI^o(%ke5>yV z^n44@(|`yuF(es)GG%GtpI4t6}@sX4pZ-1W^C??;LWU9I;ch1obev$o8H|TR@pvd4FC^_qDiyJl$1~ArhKHx}alT06 z`HMZB$)28MXU`Y)hi@@abmf0cQWQy6lpS0&f}jTi zI>I%c;LyWC+lE{x@I03rN+izP$)wH0r?}WyIvtzw#O5QNJw2VBy}gIK`un@O`ue&a z&6GXC7d@d>u0yy^d>wQ9N7#8d)`vbc?Y zb+sOK>x7%wgW)2LQZmJ!om!ll@)C9@huO1k1kl~vp8oaDg8<}ZtW2Co_)!F5n7-6P zSR`J`7Fy?*b_v5vFVS7C^YkSSq0RF0H$|B}hf^hubyv^er%^WKBx$Y=R`se4<(7eV zv!LBF!cyyTx{qqDx4zvwI>*`1jrO*Ndq+om=}XT(`RylLZ?)cHY_#{~mluEd^2;30 z*7S~o`^tH-(%vwMLNAfL*We6qxErc=&PK>Ux{W~3P#lJCaG@m+esvrlT^L^)A7|qW z%NUPk(rOb53s0mMo_OL_J|`l{FJEA1eZrW?HBUyS{5TzrMUmSF4)DrVcM`R|XS7>&)Gz=B}toi}B zao{QV)qtXyS}*##Ut(fPGnFePS(dJpOkWCmWxuS6y(uN2u0ap>V^mgA1awe{`z4*N znf4l3fqjB?F5rA`;e78TN3jN0><{;dgDK?MD}0jVT)qy21%J$P5eP4n1LS2C(0Umg zke7*q*2`1@d6}li0vUnSOM{yt_%;oe>Z@VeiZxTJV}>*4UG_j68T9BJ8lP&$;sf?c zv&%ALGBRzlwC|KN5Q{fcf-XNLgRBvc_dBPIOxTD^osHPnS45OHg(H#hrqYVI^B&W9 zY`{5Xrh}X*sy0%ZZJJ%i36JS2+5OI4W+uFvj5pEgZ#Qw3{)xg~njwdwe>`h03HvD7 z-YM&`v2uMV;8s$SvIuNK83W2ug&cItP-8uHqd}VUOvtt|SoO?BkQH;38!Sb>%bHPc zQ`+orCMuN)JCU$|!lV4-<*sz;LsES}FLjj?k=9T4*oi%bX4jV7-krPd?at@B@7=X? z@7`Uz?#bt=xTm#ma&%-S5trGk%>t{%_)3n&?dLeJ=j?c_t6c7iwI0$FzNz~vo%x6C z_)T$pPqT1RH}d&=cJ11`nyW9NxAv)-^!^PSHrZ?Je<~H4Gp^p5!g_la>n%$*;Xd*R z#%IX2j`;|<%f~as(6#l@Em%j@wbXillKT6TSVIn9mMMy9_+?obMR$opoIob;85!A= zO(m08SF7_QBlFej)yZTkyJuwNp2`1j*$S6;b6v>`n&0qu$7Unlmerx@__Pko>W<9D zx>3-YGW@(WoVTn5FVyvfW#z-X)Nj0kz^mqiR)<&EVFmNNDryOjt`JW}@>Xz#AZXNa$!Cf8Y6s@ zcku`Zf&)u8$3DOKOukmj)6-wJI+)lQp%;*{4*MB;H^<-qSe4nz6A{5LKOJ-lK2l|l zeAWSC!Agiy!eO7RcQ1XsyFOtDos<)Fk`wiA;nwbYYvUj4O#4w)k$J&=fPb)2(QGS@ z<1=*mT%94GAzvf^P8}R*Tj*YTl0HoTjDCmyGkr@43td7@*n%~xp?w*jt>uq`*1g?{eVdx+)9UTcA9? zT*bR$wQp7t8Ru{m?ZQdva4|Sn>mEhXyL-6>99w8K8xALRsrii)NZw>wiQ+!uH5PXm zs2Hn6WXX@2r9LPS5xsClXBI2qtqu87yQSE(Mzgfvgs|8L z!cR%6gwtO!7#L}mDw=*p6C_=hG?BrG=Xin1qO42I)Km?2K2rh;!}S71xTK+amrv6S zCTB`C7RIhul%*>oN zeX^_^pkU~eV8BE)gHnyNwmbfdQnXywDD`WiE(+4u(Fnip3-Iw%j1;AiCHQ2F9sZCYsH&9WaXEnqtb)0Y}rQt}+q*3U0O6 zIGW$Dsg^2WUuG9Gez8{87KhO$@3EuBEt`>gFKkAP`eSof$I~01)oTXyND8 zpc;+QLJH%dhgDOS#8^ZN>qRh!41M5+K~)z7E;lu2=wS3UBVmX-S_Pxc?zO`*mY|B+!E8m)x&*`u5(T*c8$4lPXiz2#YEbzL z*(dohhFV0IO;Oe?$^Q)rD4k+@6Mj*pia#j%hs49XT$LT=uGm_GA^04rN@E^n`M58NS9B2UU%87DU zj_^Y3XJ(H%V44dHCX%8_g8`F14lHs#<_j+XHE5bHm3!`zJC^^IJ-|Lq23((EhHEBQ z4e?u5`-oXNf9#b*dF2RpWPbK;!0Eayx9q7=`Z$dKP5`n{FbZ-wBb^DG8Dpj-7!5p zJT^O+X+4lGmC_WoTOZbf0sW4^P^z<6*4FjMdi{66OIRdZ#cB52xY-8Wn{17Yl1Z|S z>?Aj0_?lg~S;AsyryF1_@cafEwRtKz(MHsU=T%ZV^9O(vFl7fP;^iKx}8IlH+-wLu;tBd3N?hEWMyhBt-H=NQ2dGM0BRfb zQCL%*_~mK)qC0Haa(Hp__lALX?|#m&~s1x{4}I#(;#%e5Q| zaY~{_krNflMV^KKu2RgFD;&?SIkGZLa|jg$NZ22_NEVA-sc;ld+Hxd^4gpt=*x5+M zR*-`sP<9c+yqy0%0Da*_kxCR%l$SUa%KEZhd$$!pe6a6|8FJ{lNc>2k*9Gm#7%CPFu0>P$_1)dC9|f z2p&UI;oUHx3u1H9J$Ih4Sj8`Iz*S9j(T`XRC zWwF@J*w*?rS8P6*O0qM_)WOYHEY(x@ZyBxCw>#0Ov%Ov$-Ex1bE=Qe-zW#E#zi+~c zVtnwic{WcXID_W6+**+@D}_5_qI?FMc*g>+h=&73#$yazEI58wJp-<$#3SL`zk1Yt zC&Z&2YV-F)uNq$X1OgBLJY4+k|$Q&mC2{u2GMwGK^-Go*C-vi$?D<^|hi>G>w26 zb_~M^LjBvGU|-1c>9TB^reWKO`FF8%MPN=aFE`&@zx&u{J{TDNZ{ow_7`}hl|CQTU zQg{U};6z_QUgf@g_d`AR9hy6smzSRwr(I6%LN`f!oIDh-CV~XGGYHeX3}L37a`@dr zZsYPug*H6JrFk$NM|uZBv0YX`3dK#j5ymm!-lt>UQ+Q9>MoyF0=r%lvIk2u%@YUYL z9%bJZzYlk@F8{qUrXSHiq5s_XDZ??Qjb}{N+-QCuEcp1Og{|D5fN!PuZl)cXp`4(QwA zuS5Y!Lz4`W+PmoAmA!WE;K^HNkCSUr^&mM(ZsDBYMYH+X{E76zx%s){vnS>br1#yG zp4xxxs$<9I2gznv(h0~q2nO@6{8@4W=>g#Ok-HF2VXTgks}Ojr1~IzseqKHN?}Yys DNS*~X diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/argon.woff deleted file mode 100644 index ef1e9c2c434f786a409d2e3ac47a5035872e98e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8808 zcmbVR3vgW3c|PZ!``*2G_wMe!`;d0E5ACjGN&C>gWJ{J+OE$g^NaIjf&oBr#}qOD(r)P10*sF@$GZ`7u5OGrA3ui# zL6JdAzvg?*eC@&4*&Fs7xBX<-;=ol zE(<83kQ8uh^|Ay)TC3frzTMvUpg{;_L|DtmibgfsiV81|Es{kt_M)&B2n7P+40Cm! zofXalQ~1gXXY7pK$k-C#EF%k`a}dtY{N48L-aAvN zILg7XBZ`clK*o<$Dx;&0GdX$S#Fi~54optg>ucBEmmJwsDostbT5I-AO;gtlR{FnHBMdeDaxfgwc%!?UM$gKfepJ^E!kzvWnE&U zUdUx-I}+vW0y%u+jraBUGa;L~ZS$rbGh4RYmd=dy_2Ga2O}mf0Yc88F7Jv7K8xGyD z?dnt6Y%X`^+G}?Ajg0gi*?rUfeSMe6yXEq^lgQ4+dG;jwqoYSG{l8FV3> z$&XPqc7Sp~i+QWNshyGP7)QspB62QUXs~xleK5VPMK83r^<4TH8)&UMSL*s|cllhY z#;$JvzzGB#4(ERX5nf!lr+L*?P2t`lTceGU?qacfyi7IwySzkuClBe9zZ}OtAd4@s zAG6Ps9?~Mm_-@b3Su_-5&nJTxGw6oZ>7&Ib1{0N4s5eK|iZ^4lSubL4v$;yPn#Fuo zirGS$mgqVP8I@)O;Rvmc(^`F)hZUz*8LkdHwWuR2yj+g#B8xQ99sg$6}kiWCE( zpj0YbG`YULCy~!5gu4>?!@(1mgnv92ZiL%AHPcLJTBUNT-q7fi;qb!63Kb}I0YNtt zXwV}Flz}YpOb|9Ira_+{kS%4sEDy*b8PRqc2!yMNpPvZQ)cSnl(nDSOd>37HI9MqO z&z%eN+8Xsc$`wsZ7^Y622sgv+M3Bp)NkJ3KOyt5vRKiKZ6^bR&&ke{B9YPiIdc~4G z{WO66u!Ha8uttltNa$JN?D_VD&YefP3S0xK`r! zuS~Fmj0vJBFm|6JNvbMI%CkO2_4!oA_mZjmOw*^EPlpU6#NjR{5Okbiz$wMUp?EwL zju(=4B$bNT$>W)5G{fPEe4HcM*?qpwIvb*oIgFUIi!Bo%SnMx*GE@v~9YOS}o z#^LKs6y5qiA}NX_E6O%rH9*h<0UdCSS8?cpplzdGC-6M4HryDt^wZw8nJ^*NLxVZvO~74`&>;Y8I8OoJDE) zO#61>$7ks8)7RUCeW|@=i$E@Ipr{V3f>wf0-z=pUQq;%CSD+avvBWBv4{ zXCD8?qFo{Ahk-XR73~#s#H9KbmGN|1K z(6bbWp$jgy;Nh=M;G^>s3lkG;Vtx_hu}In-Mq&Q3^!#Iwy~^iAB>BY)>@{|QY$ex| zCkTc-->f&rXc5YdYq0>JyrkB-3M>}n0F|8{Do3E=qagLr6qH>Gal{#=I1ad8j5h6(b-MF^^Lf!|gvRSRe(=9iC1jOO%!vQ5%7=^Dw>(}E}+k^ExG z9>wbxeDa}-_lw?`DQZjuh=#~Al zCibV4fVv7j*pE?J!4c5GA?}xSwra*}U={WW*13T5y^Zs|n;gX&Sh7FdBMzpJXRq){ zl5_b63>N$`%S8~pL=KpjP{8XYY+zm@3SKW!1Lh@Ko(Loa(kPcUMDT4Wl^ZK@+K#nS zs$+&T=AHIX90~O3Ni;syip7WQlV*=)#$+TqY-!(VXDAkLr377mLIzti9v^g08=0^X zm%5v=uPjwj-VlyN!W+s<)t&c*#$!XyX)_(UbqO(Tm)M&N4ddLpihV*hzIT309 zXt$l%U1;@e%I(>{{%(*m(bh$)J%H+x^)}u zRrWuX3$2~5-kHXFdj{(*OE%y>@*u`%*tL%N2)N6~GsMufwa_hCN43?|dT*A-d$U-> z4quijifQ=8x-g3F5=C_anYw#)baytDOkQ29&5e%E)oNEKld0_P(b2o7{=a!kQZARe zlom9<;qQ&@jr3Ypm!{*>x-6?VvNzU?jP|tQ=egm$WhHo~t|u%jALhA!;}rlenh#oC zUS^jS%=4lsB|NmmJRQkf!6k;Em5)p>iQ{L2u(-JR_iT}U+?^Yon@d(OH|rJIHThdy zZ8x~>Z(*gf9HtDa-o(m<`CMp@@=e~u0~`nrEZrRY%%!LE^?IJ3`GVEO#O?^afS7gJ zPt&_N{X-Aen5{e(5&ZH~L6_l!HRj0Y91!NMgeWB(_VGsV!bf`>lXlQaIYB2m+2|E+ z?QOKz|Dn#bAJi0?XWR??yXzIrw&FNGL(AvtPV!0eW%3`?!GX4k?x82?1N6`6H|amq zw}i0JBh-aWSc7Y5&C^o|-BscSxXO4M4WVcJ^Ch~9<~-fUcb~fjd4P+Mr{WNL*FC+#hofj0PD+PYgLAdvaTL9~mz%+< zg=VYia8{R_-#9_!O_r4??jv4fafgA5F*{72NKkmIVZ*{%NhocE$Tp4nX z7N_#T=V>_t?v^`XoV!?XJLQgTr^)rE;u00UkU2Mc%JnAh6N;+~a&nk>0HRfC<+lz_r;y+9T&X(-;~(=>z0nKF%qvFjCO;Yv=CWnUO`9Sl=l)BM!2d@zhA4TGqW4?0n{yk8SSTg2TRHT5nsTk z`voqd+ho$)1j^=-STR5Du>U&q^DYy)aIcjzp~zKH6T6yS{*WN3s+9{{Jps+9>k=Pi zBa{y6iok-JV#?7WN7JaTG7ZnjrBn%}RfmMV!(sUm+ z)bfobtOn8WIYW-B3bNl4m=MZ^be~^~4n;#rcm?Qg-akrpMUQBXO$%NAsNa(&22};u zQd~@RvxGSa#MDrC#!Ll(gu60Y_<1#`Mq{*)!g%Om)s!VM7SY0b5yDZ2K6FD#)dhjq zA3YDyeAK6vcb64aV18e;Y`J{Y&`LL!LJU^!oVmAkS9Te`o(~s`eX_p1_Ps|$s(3ZSjT|s5Ofh01pNwCMTp}x9Rz+x zQaV8%5MB`elh}l4bjgbY4ZvMFQSQnSUTFWs>@$ZN!C%+mQ|FCEHDN3bLFvv(a%H?D)4t|b{| zqiu3{>-4d(psQDFhTu=8W}3~hbqKQ~RkE_t31{ig zcW*r{O4s~`tOvA_a%CzM!g<{_Gcq#1x0Gq$moAsn6s6n0sRaZ2slafmyIPR7U-*+RCH8!>#X9^5QpF?8Z}Fcx@v9gW&NmYiraYQys? zDKab5R(`luY)UY1J*Fk*Umgqb>r83_7TnmN5AQUn0eJX2(+?8eJ-BB3@YD@oZ_jUf zbBjU^;YV4S8VhT#GYw>aY$kxx27QQ^Li{jbB^_R7bC)3)*WUv$fP;OfNsa3}@vbY( zn}n8ph_=7X^?h(dBcR!vcdZrzJ5g#^(BtOuE(l(VcLpH|&4zJ|1=jH$2e1-$lA9^s z4Q(oi5y4Uc zgUeZLVIkqtP{lgpmK=PQHP2t!st(s-9W<&fl*5ujI9#tHY}Rq;SJ%=?lN$vPGzQ;h z1tI?Xk;No6L~`g5XqAYajZ|#~DHsA3moUQf`QJm(7oHWVMiE4Lj#EVnAq*={ zc4Mc?Z9ebUWbr1r^|&UATalaO7*w-M@bC`G zI%H(R=K!Ck$Hl{C5i5%=cq61k*j(HRrbyvV8^U?d{S`H+=lE*nacg(IUQF^_UPbm?`-ikU5goTbSv#QLrCks5bbXNu#-vcPA0XNGJDUR(~H)WrRz`9sYo&zX+QU*u7gn2-_B`2 z$8+e^QVxIr>Ro(^y~6$+uX-6$g}#7ci_t2gz5EFyD#2eDm0+F2y$51ek>G=9!M5dG ziiC|tKV_#jBK=H?Cpp&zCplsSfcXCE3|z>fpvJ78y;J~C4#rWW3b8L=8a0botdh12LtQ78yiSik2;T;RK zA|4JD8ILh=vEcY!@eH_<6OV*%{~A&Eoe+<9D9zswy<&Lb69_!~b8zu@qKA6YmGbcY z)2gvqgp0B#98PsPw$I zx<);!$}pN$dUkkVAR4{X)K`m2(KG^P*f9(v2=#A!75hS#PnTuWG!5HM%v~nVtpam` zdAa%K#$Crg`ToGze-j@b$MF5b{x9CX6vHcU0Vn!A(kl1myC2HA@6g=Aytw$3IO9s{ zWV%t>ljMZ_(Qc(j%M~;UJcqQA>!5Qd{4lV*e)WIdZ?Ua^K1^IUPE0ICc&?F^Nzl{H~HWv9I(BTXL^irLoj_d&Az;p}e=j+K_yB18 b$ejqMF;>UORRG?q5=PhE&nt)jo%sI(Ce#aG diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.eot b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.eot deleted file mode 100644 index 9e6ffc9b826cb39a58e56359d6b8b922a4b07364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1912 zcmah~Ur1Y582`?_x%Vc~T>r!*OpT4P8o`m;m_K$==`c84Z6{8{+A(HKZlhvuY>cgr zKFA)%(1*FfM*FnUZZIZ{J&ZBvpfZF#Y)@lIVSRG2hwi1Y4#u`F`<;8QXe6-ja?bgE zzwN>ij! zo>pmzGE@TNr8Jlltw75)0Xj=z>Nm6}M}y=6>u7^S>VN6wGm(a7S2vh%P-e4*%<|74 z-T45bcKGFdW@Q;|Bm8Z&_WaWN)fd`ZeusaHNO&->WpYaP$#+CHu8YruP`(wvhyN-3 z)ANP$nqL?8;r{@?cd3}o2=nYs_)p+_3z@ZLe9%0RR1ZI(XA0Ww7af1Ye-<&`S}v}X zF;AHMCGRIuyn~rYh<#h&Z+ypW*>5z!99(zI7^Yoq=ZPL)7I!PVbY4V3=V9`>F2E}z z8jskHKC=}KRXf?}74Xf-hKS{56ga3mP!HbyReXH8^0ZRngTXngI9B<^|Cj$y|Mga> z;R}pA9?uwniV?%;hGTu$Jc)CL^hp0d9A5GarZvNJ<6ufi3Gpco?d=T-GZmvH1`UH| zm}{8N!4f`UZ>U1NTNno5ddx?}-q;a0gdKdb1FJ*sPETj7DTdm^s|}H!LSzj^@e}6Xo3K zXf!%Jyy+jD4Tn>yMB=%*RO-r=RBGa)o-oe4%#d}+m|4=Q~$QQ44QKuG~z>i4Xv1q8Lj|COk&su!m zB#R{CF*mpnCZx!x7-pM@8!0(V$8jZ+b@ar1M!vd&d^FFaIShFeNRsTjU4j|Sd#3{Z zXChnUcGm@);*d_c-5qUSPhEZ6>5dLdQtxVZJDg384u_&VOeQt$##&BG!nEAl4Grj% zf?bkj$zHI_k|f*NMx?LL=UZ2u=WI$ybv3ANugm3X>D=4hK9vL(>`jZV6X?ab{kvf)^jN}pSC8R2xdumC)3 zVG%fPVH@zOg(aM_9t+FhFId=#{kw^X%;o^2qQ}GnaNfcq@UVq#z&9-{;jj-_SO!03 zVJAiDPgt_+pY=D^L-I_h!b%DZS?d0}MTT%Y6XQicBm D*A6pu diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg deleted file mode 100644 index d38d057..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.ttf b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.ttf deleted file mode 100644 index 84669323e9ddfdca80c91416b6d4fe31ea1829ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1748 zcmah}U1%d!6h3n&Gn1cY`jbCwn>0i)RYHn=Nd(_}VjX(rt? z-ECzbiVq^~gR7wIJ}Ik$SP&mXgcU4O@Ijw^C=2dW1t0Wf!4*VZ<9BDKw5tWraPR%j zch0@%%sF?41R`?L28k4Z?)j66)(&?+m@hHriq*pM5AWT1he+s#-Y6GVma(=$zlqge zURuBMOt<$}=(mX2y^2;SDaD815ZSn2x&lJ^TKpFJN6=4Hs*Sav&i0^x2YqmLYKX+Z zh4)?i>i(NQi4QI{A2plC?(n|zF-~ay82lsnd+=JP)cPs*9gSyfz$B1>-K|G#j3{&3 za6R<@9}b5+fwX3MZ5)CURiZq_(cRrqHrq5-65u1iXN>y@0f&$Yu-(xnaWfkO;Qq)* z#NF5yH`q4b*n#elr`Ok;YENPI@o7V(M{qI++s^0z-kX`(%jfy~2$ZLw_^~)dT}1uS z0rN>EGwI<(fDgaVtH^j5jW5RI*{t6`F;QxqJJ%>pOeB+IW1GQ|xmYZh%VeIK&*d&( z&gJGW%*>3B-$2WWnmaZ^=Q=5cP!W|W1*=Ev4Ne;?! z)Dy)zd{P0UUVRb1o7d6YhB`8mB)e{xAja}mPdI)uu{C9PpS39tsmJ39b@_d+maY?_ zkmb_i?(jIA?QIT+qTJ7BHSPLZNy|dC(%N+m=)h}3M^?w~_ggCg@Q$N?gdbxG{B zx-Tq&<|jJo3a&GkgUE(rO)7n2#T7^aXXe0w=PWD&r!8y)UbV1p!rv)lfjj9+m((_t< zWuc~rPsQT+HZ`i#3LId-Ij1N_@nd%#OHOO$)ulomK{X`0N=sCr`mvsqHN6ooYr0l1 zG_+E9emy)@ter=0F`6`DHxRvyV{{{<0yVIfz|GS-<|*R^&YLfQ9MQz1E%`702g#=) A_5c6? diff --git a/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.woff b/rooter/ext-rooter-basic/files/www/luci-static/fonts/font.woff deleted file mode 100644 index 00cf84ea037c9748eba8fced0acff7dd29c12b2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1824 zcmah~U1%d!6h3z*Gn1dq^e2DXHffq}n?fO*P4m+=ZK*U=>UMvqZE#n_rpav5(j>cS zx@~12iVq^~gR7vpPs*;oSP-8?SivF%AM{D2EZCG7&Rrx~vs#LD8 z6G>0NAK>b*2>Z*`Jo2P*_+G9;iM>+Jt)s5=Jp7=pDwQg^vIY+G*{fXdJZt;odUXZ8 zDo8Q&L?BVT%Wji|-tGur!++fv+0Qh@Y&`XZu+|ff4#$ZeUJ-X2yEHCB!7-gTOi&;6 zDnMO`aoh#Vv%1Jayytdm1tWk99y$)y!#92uA6{uZZZr@haQ1(2tnt17cmHqxn;lZi z$L30U;t9iuVRnmN#h?YE)H%Ji~}l4#fh3$L$@8 zB@^+8(AyRp6H=J9PPd>@Tz*hhgR$y%{W5Pf*FI~Y9^ z+n%yI&s!9m)a`NwI=vppsm{}ZfSGd2+3vF0+gfclML9^PHEnIZprs*NVSP;l`k-u; zWLdJ7t+FJ^R<;=%9Q64%RQoxL5>}lps>|ziI$L`}{T`#RqrJ^xmt|E|ogPm| zCrxYtUNy0VFSW^2&zRUw zae99-UoBUw6 - */ - -@font-face { - font-family: 'Roboto'; - src: local('Roboto Medium'), local('Roboto-Medium'), url('Roboto-Medium-webfont.woff') format('woff'); - font-weight: 500; - font-style: normal; -} - -@font-face { - font-family: 'Roboto'; - src: local('Roboto'), local('Roboto Regular'), local('Roboto-Regular'), url('Roboto-Regular-webfont.woff') format('woff'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'icomoon'; - src: url('font.eot'); - src: url('font.eot') format('embedded-opentype'), - url('font.ttf') format('truetype'), - url('font.woff') format('woff'), - url('font.svg') format('svg'); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "advancedtomato"; - src:url("advancedtomato.eot"); - src:url("advancedtomato.eot?#iefix") format("embedded-opentype"), - url("advancedtomato.woff") format("woff"), - url("advancedtomato.ttf") format("truetype"), - url("advancedtomato.svg#advancedtomato") format("svg"); - font-weight: normal; - font-style: normal; -} diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/android-icon-192x192.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/android-icon-192x192.png deleted file mode 100644 index 7c17009d3d83e8d0aedf334165c8fcdf95df501b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6411 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 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-144x144.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-144x144.png deleted file mode 100644 index 5308d66b779b26d1828690516a4ab5dc01b7cec9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5222 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 aWS&p(fIu!(CjkFLSj>$d8r2y%$NwKzaNBSI diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-60x60.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-60x60.png deleted file mode 100644 index f18dfa49cd35fa6d5cb882ea8ae703c852e313df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2561 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 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-72x72.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/apple-icon-72x72.png deleted file mode 100644 index bb3e2423331068c72c5ad0e1bc49a51e1fdd71af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2877 zcmYjSc{tSD8=r0}vX+WuN!ij(L|36)A(HGRB#dS3W{feIF_y*{)QDuu_ERKVCP@?$ zB}*himadx^%Ph>8efxcTe*gT=bIyCt`8?12p3nO^?|Dv^i<6z~UX{Hd5J>ily^R|% z+y5StI{^zewnhMx1jOo^6$nJkl@bi=&4v0EVJB1CblC z89e_uQdAlfl0*$oB*$e6pm#V3ya*h><_BMnNoU1pi^DPWkR(b(3Ox|H9-h4Q+hXWI zhh=bqemnM8Sn?)-0}Euf_;&0v;P}6Fe3l46klDX&L<%D^l>r2aOkn_92#O{aivh=| z)a`K0Rw$YV;6P;P9X2?A6@sG1W^jR+(P_*G3?1--VmSc_QXp~-pyVI70>g3uN&sOP zmIucP5O^WLJUX2fo52r5Zw4i-$J}8DC2T;FC}C(Ca5O+EJb4q~6Ou>{PS^-V(Lzzw z$W$gkDKLHwNES#WDvcF{Tn8goMIvzkVik_#0h$2%1jLcTF${rF3emkLMBVhV2YMVLV-Z+2VVilugBp9TMRLqBOadySaBw2g(1J?rIKmCr3g>n z{{BN4il+1UVxdrcx0DWumQl!wPG@%y@E4bbs~f_I6eev;H1bt|y2piKw`0;73qJ)> zY3#;!AYV@Zh+uGB2x$1clMP00)V^Scq5-Y8!jkFj?>H}egs6LhgsknAHPP5NVPp#P zO+T-whSl(jgSpQyuNS1{^QxPfkty_bvWUYK|J?v-&rjq%|b4B{I> zX`QgJhTqg7#6AQ9ZX&Zb8{3)T=#Bg;I<9cDs*w?#u--c;>K)=`77KDK1sDQ=P@bU) zQ@|VeGtSM)9rXVHTi;Ie_qtP|9Q9D$soJzOb55=LbZr_(eY!8Lc8WiDdRYnt+Vl8| zjg`mEzNVSPn~D$>(59=8&nbtkS8P_x0ON#&2j1JK&3m8z2JvU}Ou_6EZ>(11n-Im8 zyrWVlur2s`Nj>&)S-hm=AF)ZUP2{9hyWXAsHz-|E$nP;{j7yMmll8R9!C!30?zf(} zqo1Ja#?(aJGwQH@#WQQ=^Vs4t$}IvBprNC!?Q36uZTZ&?n+#PmEs63r%a?r(ODKd{?T@Z5)Y8AG z(sQdLYPJ?T___REWoXoPui=cTfqFLX#Af0isGj6DQE|~F$`S|TJI|iD|Llc8j#qXC zLY0(B>+akyVs%{QCO6JW7{ANus_eL^{D;%fb*Rj%%J&?hVUv^lO0vpX8CFZp-NqouQt3Kng0xwwO%WQ7@@ z-AVs~*1{Z@&ebeK^?b#;&=9aB)v_~g=4dcQe08T&&Tf`Za@)Rh%1L)y?bfmb>>hp~ zc^%fJdY^>EnL<_f|0D-?(!4ub4W}Kvltxmr4EAp`6*aarXg6V=

                                                                      l43o znrK}nG+gtc>gLx>3i3^0x2Jw8raK+QC7@P3yP)0$WkXdfo&(SJ7avZx7?9gye*=Fh z7^#U3mveCVTs5L%k>I3&;}DR@Gbl&OjgX3u6tH~ViyWGN=xhHJmXqb75p?YjBWI!7 zXQOk-o;;ew1%hU;dPQNyb1>nPku#Dsp8165-LI*cm;3`hb@pts4Q9lGd3wP*%H&|w z#Y>P2Qdtzn;Zr^Nrr-KTgP$9mN;J=My)3^EvJclURe zzxaz!|C)L*;B4u@+V+tfo@4yjLty;pzP;DbiSEZ!{C2@hNG7H+L8>yc0aV=!#xqsf_rp|b*a?=O zdkVxzBZ`Xxvy1NF!Of&k>bbv|?No7}*&6tlNnM-BoI~GLkBVxAjG^a7Bjs-?yuPT{ zaCZ9d049+>}fFM zCuM`!K6?G2=tfO`8%FKLCo0w-FIs3?#=UL&dYAFn92b2cl7NrqHomX5^lw6=lPxZ;uW0c%Ty}83g+jQYV9D~#HHw~lDUs=oH8a=Hj`uh= z!BzHhEOD6gYOc$2dw7sCJ#_5-L+xxIh_vkW9Hl+35F2w2p`x1c-S~PyU#40vro1qf z*QDd|-L1B<&Pe-a=&Hu+2vT?+eYlk`b3I7pU$^P^vQ=OUo=@of5wksfpx*xpfoHPg z!}gpIjQ$ldh4xh7F>6ZzF;idtxrrv>4EFQ(l?hCGu#Ysm{Jp zXJe*zQIKhfkM@M2hi6x1BfELj=@yOO&>qu%Go-mBjM(Vo_eJ%p|Htkl^Wku3@3Zi>ZKo#XAY5CTVcnVy;=;QYF>U;ju%hgvOoXWk7$Wk8E$eH zKVY6^yFDE_AM>65v32|SDW&Lg9*xEG9bJW#WJW69eso4uvF_WS$dy0c_5LCYUSYC@ zDDu<@1|K+ld`9`>$0d)uPr%!slyse{)ip#KSRIf?hg$kD@Xdp+*gDxXU-D1?FEo)L Ao&W#< diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml b/rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml deleted file mode 100644 index c554148..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/icon/browserconfig.xml +++ /dev/null @@ -1,2 +0,0 @@ - -#ffffff \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-16x16.png b/rooter/ext-rooter-basic/files/www/luci-static/icon/favicon-16x16.png deleted file mode 100644 index 308843a09261dc8c5d95f01a3b4e6592e1a83ff0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1019 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 aWS&p(fIu!(CjkFLSj>$d8r2y%$NwKzaNBSI diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg deleted file mode 100644 index be864c5..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/icons/arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg deleted file mode 100644 index d529b94..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/icons/logout.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg deleted file mode 100644 index 46bd0ae..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/icons/menu.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg b/rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg deleted file mode 100644 index 6ddd3b3..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/icons/spinner.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg b/rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg deleted file mode 100644 index 654e2fe..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/img/argon.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/blank.png b/rooter/ext-rooter-basic/files/www/luci-static/img/blank.png deleted file mode 100644 index 9f4100e6e2ea2fa08912439eb7425af3f048eedd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 938 zcmaJ=L66cv6t0pOLtGQRxu;1t8cn3rmX@UxDuEV+#1g`iEC&ykc7V#ZQ`^B74o1E0 z!9@RtCjJ4Vo;`W;;-Byjn5vqfmTeG-$ z^$PpHk-vXt%Pra((IYaUi5+3C;gT^1UEiMK0k+-cvv0V@afLhHa70JeBjgZYurrL1 z`XOU;T&;m#;qnwG=S{ zA5$Bo{z(v{ROi>ah{f44|Y zg;KdBRgfYgSq7VrXW1fmf(B-LlZ)+ienx4CAWV`(NXi0_9I4~G;sIW3tW=K z_tqTCLfs&ycHrQysq;)l@H`ilE0WPRn-#+l6-jC}G^uPDimIwwvsqP|M$R>fv+!|1 zbFO>AJ>1F7#=#F+W)nx=bL_Sw;)8YB$lL8j*{QeTy1TuoJGqdVf!XE$b=mn5o1iS* zjxO75haU%Q;v+WNFFxG9&Ys17*K7>apX1+WXZ3>g^7K_leE${|FI~RI{kU1U@$}2P Q$Jy)YwtD8r=9AZd04Jv&d;kCd diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/open.png b/rooter/ext-rooter-basic/files/www/luci-static/img/open.png deleted file mode 100644 index 7c92fbee992c314b7d1974b6a5dec664e2985feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7603 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 V)c(S)E{XsE002ovPDHLkV1h0R-5US^ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg b/rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg deleted file mode 100644 index f01ad5c..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/img/volume_high.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg b/rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg deleted file mode 100644 index 0598d58..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/img/volume_off.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css b/rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css deleted file mode 100644 index 9f4b624..0000000 --- a/rooter/ext-rooter-basic/files/www/luci-static/resources/buttons/buttons.css +++ /dev/null @@ -1,702 +0,0 @@ -/* Buttons CSS */ - -:root { - --green-color: rgb(44,187,99); - --red-color: rgb(218,42,42); -} - -/* -

                                                                      <%:Exit%>
                                                                      -*/ - -.button-73 { - appearance: none; - background-color: #FFFFFF; - border-radius: 40em; - border-style: none; - box-shadow: #ADCFFF 0 -12px 6px inset; - box-sizing: border-box; - color: #000000; - cursor: pointer; - display: inline-block; - font-family: -apple-system,sans-serif; - font-size: 1.2rem; - font-weight: 700; - letter-spacing: -.24px; - margin: 0; - outline: none; - padding: 1rem 1.3rem; - quotes: auto; - text-align: center; - text-decoration: none; - transition: all .15s; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; -} - -.button-73:hover { - background-color: #FFC229; - box-shadow: #FF6314 0 -6px 8px inset; - transform: scale(1.125); -} - -.button-73:active { - transform: scale(1.025); -} - -@media (min-width: 768px) { - .button-73 { - font-size: 1.5rem; - padding: .75rem 2rem; - } -} - -/* -
                                                                      <%:Exit%>
                                                                      -*/ -.button-71 { - background-color: #0078d0; - border: 0; - border-radius: 56px; - color: #fff; - cursor: pointer; - display: inline-block; - font-family: system-ui,-apple-system,system-ui,"Segoe UI",Roboto,Ubuntu,"Helvetica Neue",sans-serif; - font-size: 1.25rem; - font-weight: 600; - outline: 0; - padding: 16px 21px; - position: relative; - text-align: center; - text-decoration: none; - transition: all .3s; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; -} - -.button-71:before { - background-color: initial; - background-image: linear-gradient(#fff 0, rgba(255, 255, 255, 0) 100%); - border-radius: 125px; - content: ""; - height: 50%; - left: 4%; - opacity: .5; - position: absolute; - top: 0; - transition: all .3s; - width: 92%; -} - -.button-71:hover { - box-shadow: rgba(255, 255, 255, .2) 0 3px 15px inset, rgba(0, 0, 0, .1) 0 3px 5px, rgba(0, 0, 0, .1) 0 10px 13px; - transform: scale(1.05); -} - -@media (min-width: 768px) { - .button-71 { - padding: 16px 48px; - } -} - -/* -
                                                                      <%:Exit%>
                                                                      -*/ -.button-62 { - background: linear-gradient(to bottom right, #EF4765, #FF9A5A); - border: 0; - border-radius: 12px; - color: #FFFFFF; - cursor: pointer; - display: inline-block; - font-family: -apple-system,system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; - font-size: 16px; - font-weight: 500; - line-height: 2.5; - outline: transparent; - padding: 0 1rem; - text-align: center; - text-decoration: none; - transition: box-shadow .2s ease-in-out; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; - white-space: nowrap; -} - -.button-62:not([disabled]):focus { - box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5); -} - -.button-62:not([disabled]):hover { - box-shadow: 0 0 .25rem rgba(0, 0, 0, 0.5), -.125rem -.125rem 1rem rgba(239, 71, 101, 0.5), .125rem .125rem 1rem rgba(255, 154, 90, 0.5); -} - -/* -
                                                                      - - - - Button 82 - -
                                                                      - - Red button -*/ - -.button-82-pushable { - position: relative; - border: none; - background: transparent; - padding: 0; - cursor: pointer; - outline-offset: 4px; - transition: filter 250ms; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; -} - -.button-82-shadow { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border-radius: 12px; - background: hsl(0deg 0% 0% / 0.25); - will-change: transform; - transform: translateY(2px); - transition: - transform - 600ms - cubic-bezier(.3, .7, .4, 1); -} - -.button-82-edge { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border-radius: 12px; - background: linear-gradient( - to left, - hsl(340deg 100% 16%) 0%, - hsl(340deg 100% 32%) 8%, - hsl(340deg 100% 32%) 92%, - hsl(340deg 100% 16%) 100% - ); -} - -.button-82-front { - display: block; - position: relative; - padding: 12px 27px; - border-radius: 12px; - font-size: 1.1rem; - color: white; - background: hsl(345deg 100% 47%); - will-change: transform; - transform: translateY(-4px); - transition: - transform - 600ms - cubic-bezier(.3, .7, .4, 1); -} - -@media (min-width: 768px) { - .button-82-front { - font-size: 1.25rem; - padding: 12px 42px; - } -} - -.button-82-pushable:hover { - filter: brightness(110%); - -webkit-filter: brightness(110%); -} - -.button-82-pushable:hover .button-82-front { - transform: translateY(-6px); - transition: - transform - 250ms - cubic-bezier(.3, .7, .4, 1.5); -} - -.button-82-pushable:active .button-82-front { - transform: translateY(-2px); - transition: transform 34ms; -} - -.button-82-pushable:hover .button-82-shadow { - transform: translateY(4px); - transition: - transform - 250ms - cubic-bezier(.3, .7, .4, 1.5); -} - -.button-82-pushable:active .button-82-shadow { - transform: translateY(1px); - transition: transform 34ms; -} - -.button-82-pushable:focus:not(:focus-visible) { - outline: none; -} - -/* -
                                                                      <%:Exit%>
                                                                      - Green button -*/ - -.button-33 { - background-color: #c2fbd7; - border-radius: 100px; - box-shadow: rgba(44,187,99, .2) 0 -25px 18px -14px inset,rgba(44,187,99, .15) 0 1px 2px,rgba(44,187,99, .15) 0 2px 4px,rgba(44,187,99, .15) 0 4px 8px,rgba(44,187,99, .15) 0 8px 16px,rgba(44,187,99, .15) 0 16px 32px; - color: green; - cursor: pointer; - display: inline-block; - font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; - padding: 7px 20px; - text-align: center; - text-decoration: none; - transition: all 250ms; - border: 0; - font-size: 20px; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; -} - -.button-33:hover { - box-shadow: rgba(44,187,99,.35) 0 -25px 18px -14px inset,rgba(44,187,99,.25) 0 1px 2px,rgba(44,187,99,.25) 0 2px 4px,rgba(44,187,99,.25) 0 4px 8px,rgba(44,187,99,.25) 0 8px 16px,rgba(44,187,99,.25) 0 16px 32px; - transform: scale(1.05) rotate(-1deg); -} - -/* Red button */ - -.button-34 { - background-color: var(--red-color); - border-radius: 100px; - box-shadow: rgba(218,42,42, .2) 0 -25px 18px -14px inset,rgba(218,42,42, .15) 0 1px 2px,rgba(218,42,42, .15) 0 2px 4px,rgba(218,42,42, .15) 0 4px 8px,rgba(218,42,42, .15) 0 8px 16px,rgba(218,42,42, .15) 0 16px 32px; - color: green; - cursor: pointer; - display: inline-block; - font-family: CerebriSans-Regular,-apple-system,system-ui,Roboto,sans-serif; - padding: 7px 20px; - text-align: center; - text-decoration: none; - transition: all 250ms; - border: 0; - font-size: 20px; - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; -} - -.button-34:hover { - box-shadow: rgba(218,42,42,.35) 0 -25px 18px -14px inset,rgba(218,42,42,.25) 0 1px 2px,rgba(218,42,42,.25) 0 2px 4px,rgba(218,42,42,.25) 0 4px 8px,rgba(218,42,42,.25) 0 8px 16px,rgba(218,42,42,.25) 0 16px 32px; - transform: scale(1.05) rotate(-1deg); -} - - -.button-40 { - background-color: #0078d0; - border: 1px solid transparent; - border-radius: .75rem; - box-sizing: border-box; - color: #ffffff; - cursor: pointer; - flex: 0 0 auto; - font-family: "Inter var",ui-sans-serif,system-ui,-apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; - font-size: 1.80rem; - font-weight: 600; - line-height: 1.5rem; - padding: .75rem 1.2rem; - text-align: center; - text-decoration: none #6B7280 solid; - text-decoration-thickness: auto; - transition-duration: .2s; - transition-property: background-color,border-color,color,fill,stroke; - transition-timing-function: cubic-bezier(.4, 0, 0.2, 1); - user-select: none; - -webkit-user-select: none; - touch-action: manipulation; - width: auto; -} - -.button-40:hover { - -} - -.button-40:focus { - box-shadow: none; - outline: 2px solid transparent; - outline-offset: 2px; -} - -@media (min-width: 768px) { - .button-40 { - padding: .75rem 1.5rem; - } -} - -/* -
                                                                      - -
                                                                      -*/ - -*, -*:before, -*:after { - box-sizing: border-box; -} - -.toggle { - cursor: pointer; - display: inline-block; -} - -.toggle-switch { - display: inline-block; - background: #ccc; - border-radius: 16px; - width: 58px; - height: 32px; - position: relative; - vertical-align: middle; - transition: background 0.25s; -} -.toggle-switch:before, .toggle-switch:after { - content: ""; -} -.toggle-switch:before { - display: block; - background: linear-gradient(to bottom, #fff 0%, #eee 100%); - border-radius: 50%; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25); - width: 24px; - height: 24px; - position: absolute; - top: 4px; - left: 4px; - transition: left 0.25s; -} -.toggle:hover .toggle-switch:before { - background: linear-gradient(to bottom, #fff 0%, #fff 100%); - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5); -} -.toggle-checkbox:checked + .toggle-switch { - background: #56c080; -} -.toggle-checkbox:checked + .toggle-switch:before { - left: 30px; -} - -.toggle-checkbox { - position: absolute; - visibility: hidden; -} - -.toggle-label { - margin-left: 5px; - position: relative; - top: 2px; -} - -/* - -*/ -/* The switch - the box around the slider */ -.switch { - position: relative; - display: inline-block; - width: 60px; - height: 34px; -} - -/* Hide default HTML checkbox */ -.switch input { - opacity: 0; - width: 0; - height: 0; -} - -/* The slider */ -.slider { - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: #ccc; - -webkit-transition: .4s; - transition: .4s; -} - -.slider:before { - position: absolute; - content: ""; - height: 26px; - width: 26px; - left: 4px; - bottom: 4px; - background-color: white; - -webkit-transition: .4s; - transition: .4s; -} - -input:checked + .slider { - background-color: #2196F3; -} - -input:focus + .slider { - box-shadow: 0 0 1px #2196F3; -} - -input:checked + .slider:before { - -webkit-transform: translateX(26px); - -ms-transform: translateX(26px); - transform: translateX(26px); -} - -/* Rounded sliders */ -.slider.round { - border-radius: 34px; -} - -.slider.round:before { - border-radius: 50%; -} - -/* -
                                                                      -

                                                                      - - -

                                                                      -

                                                                      - -

                                                                      -

                                                                      - -

                                                                      -

                                                                      - -

                                                                      -
                                                                      -*/ - - -/* Toggle Switch */ - -.toggleSwitch span span { - display: none; -} - -@media only screen { - .toggleSwitch { - display: inline-block; - height: 18px; - position: relative; - overflow: visible; - padding: 0; - margin-left: 50px; - cursor: pointer; - width: 40px; - user-select: none; - } - .toggleSwitch * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - } - .toggleSwitch label, - .toggleSwitch > span { - line-height: 20px; - height: 20px; - vertical-align: middle; - } - .toggleSwitch input:focus ~ a, - .toggleSwitch input:focus + label { - outline: none; - } - .toggleSwitch label { - position: relative; - z-index: 3; - display: block; - width: 100%; - } - .toggleSwitch input { - position: absolute; - opacity: 0; - z-index: 5; - } - .toggleSwitch > span { - position: absolute; - left: -50px; - width: 100%; - margin: 0; - padding-right: 50px; - text-align: left; - white-space: nowrap; - } - .toggleSwitch > span span { - position: absolute; - top: 0; - left: 0; - z-index: 5; - display: block; - width: 50%; - margin-left: 50px; - text-align: left; - font-size: 0.9em; - width: 100%; - left: 15%; - top: -1px; - opacity: 0; - } - .toggleSwitch a { - position: absolute; - right: 50%; - z-index: 4; - display: block; - height: 100%; - padding: 0; - left: 2px; - width: 18px; - background-color: #fff; - border: 1px solid #CCC; - border-radius: 100%; - -webkit-transition: all 0.2s ease-out; - -moz-transition: all 0.2s ease-out; - transition: all 0.2s ease-out; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); - } - .toggleSwitch > span span:first-of-type { - color: #ccc; - opacity: 1; - left: 45%; - } - .toggleSwitch > span:before { - content: ''; - display: block; - width: 100%; - height: 100%; - position: absolute; - left: 50px; - top: -2px; - background-color: #fafafa; - border: 1px solid #ccc; - border-radius: 30px; - -webkit-transition: all 0.2s ease-out; - -moz-transition: all 0.2s ease-out; - transition: all 0.2s ease-out; - } - .toggleSwitch input:checked ~ a { - border-color: #fff; - left: 100%; - margin-left: -8px; - } - .toggleSwitch input:checked ~ span:before { - border-color: #0097D1; - box-shadow: inset 0 0 0 30px #0097D1; - } - .toggleSwitch input:checked ~ span span:first-of-type { - opacity: 0; - } - .toggleSwitch input:checked ~ span span:last-of-type { - opacity: 1; - color: #fff; - } - /* Switch Sizes */ - .toggleSwitch.large { - width: 60px; - height: 27px; - } - .toggleSwitch.large a { - width: 27px; - } - .toggleSwitch.large > span { - height: 29px; - line-height: 28px; - } - .toggleSwitch.large input:checked ~ a { - left: 41px; - } - .toggleSwitch.large > span span { - font-size: 1.1em; - } - .toggleSwitch.large > span span:first-of-type { - left: 50%; - } - .toggleSwitch.xlarge { - width: 80px; - height: 36px; - } - .toggleSwitch.xlarge a { - width: 36px; - } - .toggleSwitch.xlarge > span { - height: 38px; - line-height: 37px; - } - .toggleSwitch.xlarge input:checked ~ a { - left: 52px; - } - .toggleSwitch.xlarge > span span { - font-size: 1.4em; - } - .toggleSwitch.xlarge > span span:first-of-type { - left: 50%; - } -} - - -/* End Toggle Switch */ diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/lock1.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/lock1.png deleted file mode 100644 index 0e650f33a4091374ff1970c47c8ef148269ed47f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13833 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 LNkvXXu0mjf;`?Qb diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/unlock1.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/icons/unlock1.png deleted file mode 100644 index 0839da5f9f3bd22d7294abf95c4b96c5a3d00bed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12460 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 diff --git a/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rooter.png b/rooter/ext-rooter-basic/files/www/luci-static/resources/img/rooter.png deleted file mode 100644 index 630f30d523e51bc1da06e9f06fe24e1327e1968d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4644 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 a68;B0zfK%Q zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3;ek{r2mMgOr1Edev&%fV=-9ccMF7nvlxDXJws z6WPs5W@SYLe7J)Hbmu?*{knhSS4+veTw1SItLIm?Y;o|S`_He>*WmN}^Zgn>z8C)f zzDxJ}jmTSxuj%vGdcL0@ykCC(K+E6v=ilFVZGErPzZd#`*wp>RKcqW%`6@B5+rId(5Xe|@6x<7NE&H~JzkfBp5B z*xkGPz2~#Kkt>m^?z<@ey~KOP2f0X2@5d^?8~+zxxA)ul-C5!y=$mX#elHg+L?U}b z4m*r+!+Bpc7J;FU-|v>Lieh4Lr^g5CssUHQ~~lB%AEe>QzRtZZ%oUJ@B8h3 zruEk^B{q@4^1|F%;PCTviCMz0+Db3aiO&_Eo&S`3X#0BsLd3lb4?`{I;A==F)Zkl; zEd=7&$fZcJ3-7bB#LwG63yCPHrbcQk4U&~}p?+HK z)X*rYWLHY5rIlW+jGAh$rPkW2Flw~aax1O2)_Suxdg{5CUVH1kTOSrJ0b#|eHD}$- z#^9!dOAmf}@QE>IoN4A+W}R*JX>%;fXXRB^U2XMcYwWnwru}!_&F#Kzj}s21bn+>u zo_6}NGcL7u)6KWsdfV;S?)aItZ&v@FweVZ!{yA&mn>A%Dzt6Q_S>x^2eq165PKt6y z#$pa+yeR_|bX3lK4>?C=PC4@yX^IlbS}01+4$2rA%qPTh!_VCP%G^KZ&6WIr%3J*J zGUt@K|BuW$rS6-#|C+ZyWNnYfDCs3gU8tD)bOAO#aQcXSh?9POog-g(qL*@4DJS|q z_9$h-8zO-+&N(&o3s@CDmILNyxK{E!3zoHW8n9NOxoE^Ct;9NSAB~2YETaf1!fL1G zb>r%R40V9cm3Z1TQP!bF(*eWUC>2Z=V}O8!hyFV;>|77)zkc;RY)5EbKzDpi=~PFV zowImMTQ!BUZTWp`+HvfeZD#7?*sZ|tYV@s(gKKlAYGsYwPiyyt zLRS@8!x>Stq&4MWCZg(Xch1<}BiE!*lsU5x#0{B>1%;MU}n%HaH{bcKlw1q&kv~f4Y zI+Zi3^y;DRqEWyER?53Qy+8NnNm)hN*|m{Y8KvzxE(Nzwin$xF>rJ(p54ufjCpGGh zQrh%X9>8a&Rq}%H{hD)9*(K03efAx53yRf>QDxgHMV3_tj2+g|6U+=U+z8sWyltj6 z`n;QR<}utpGbjXcp4b}&L3z$}1S<)A2}BYQf#>KvI!i&+4ET2w{FLP^7a2ednBY>J8cTPHBLA;{bw6I*K{osaM2L21 zgQTEjXYU8(eDz6Ao1UQ~nUtbJ$57;GDB!0%`i3T?F=M-)L?mlz)R~*ww$o=+8wn<+ z2a7@Rm)m@pSQRdh?e z(HEoib~)MgJyQpJPeY!7)YW(%3smu{5K5$(QJ0O{gUHCrOfV4L2u9iHd=z$^lowE& z(`8!ka9gP*8OqpfZ*-nhA3pYo+c$TVwi4p`!e5?lw)#aMTx zs$=MMV6f6blLjIoyNwR;4J?J-j^uA7jGkbn0uRZH9NwO2;JrglH`V}<@*a>iK$sOO zK(sR}=DKtS{8}%y*vBn>f_CbWGg;csD2O(P(Y$+FtJLp|1izp&AbYNt4ALSp^%kD6 zTv~LAPdL2;p9oGfPSv`FUJeJo@M)wRHR*q6HM^mdwr)`dWhKrvu0 zSxE?i(dnrhZ3+`wi^^#rWuj4?3$)E*XUKcHBgOgnjaQ*K?p@ z?uG26Ugi|5pSr1ALKhdZmzCO?Cpml2@B|w|MjdCOWd-P>ZE*G=YigHKl#DGT zYNJ!E>~k=oM}~9aGqIot=`_nneA%QtFK|j7JPHj!5#6sVFLdLHWAa&~I|Vrx+Np2I z0zC@Pq0In4`j&2yny!}P*AVV?spf`0qE~!USdlq1Cvw`JKAiCVk-Y5|@Z%kfkd`5& zOPUN+gSO;8C2yDWaLYmF)VaZ5NR5jj^P{{IC0<59#9~Ua;881iiwz*pGtn~{z69U8 zT7>6hCFqlRBp=iRh5YgKc#c3v38a(| z3lvs`=KBsNZ(>5y3Kl}P6Pg9|Zt4JU=aE?c*mRcPZnCa?E@}t~06>d{VW3n8E%Jol zLiq7!7jbtU8tCM*nTEvSTwqN#dYmwg^6Q3mFd8~u2#HImAkd|}ZYGL?M?5+Q?i$G6 zF;UTCHh}pK^lqVPL~w$N@1583}bzJqPkc zt5CTp*NaB6QLq? z-J@`@fF(789EkdLaM}C}C67}Aw&ekkt>`igN5KzGRH_Uk=^=)=Rhc%V3}j3{JP(K# zLXDXNtp{dJ;oByA(-aBd7OW(FMGRde0Sq@>M6o#_PK}Bp4r;nf zH%2-YT?@iCX=}h5=ty&w88nN%lCz>(R0E`nEyM;&H5?|#)E@dd=kHu%;f{2SsV zYb3c5T6o%X5SG|4q}0J-5k91+46{Q*joxI6Za%rA(eFALFocFPkiV4ypd9xx{8QUy zAU`2wGo%E19I_%^%Nc!51*jz zB6sOvD56g=6TH&E7qo>(BNuTDHEw7)0s#!c>pUv17uZHhpt%55L!QmXZQa&dPz;8n z!Vl16$R5fSNe{4hFgNi4t!hy*j zWmEHlG0-@-3Ni0G@iuQjf|Pp8TRQNNFr8OgwTj%ArVxD!8x%{d-T^8*wN3 zi_xM=P7eM!2o}wUq?-kZElKc)e9jBS4OsxtSK4dqxoFc&QBbWI)C#>7pcY4is~uD} z-XQ`XVLwo!ykh*w4A!xMy67iT2Weha`Ute#`h)}qp3}f|7UD^N$6V}&g(#;d76FW6 zBJgh8+Z!}WrAY!Jxu59KBna?bhZL|>A8EIXJ33yP$4jzd1gYithsn*KzMeG~(kp~n z5({=h|f)_Fqaxh=(- z9E1S0G-y%yA6Q_+AhCEf7GBHbSYiUpcFjJ6*7z@pNd!c|FwN{S8mJ5>8IvBd3sI5L zK+;}9LHj`2C*{D z8CbV$-lc<4vzOqZYCkg>Po{z7@iL(?X8jQMr&-=V_jn*U3fxOxL#Z+X0Rh>sw`L&7vR@uZ!F=ei9FMsh)%!_ z(Me0ybwy>JbmM3EMS`g?Kx3wcb+GlB}H*#LKt$nP4S5g2rQmyQ(Yc?kNGz1BVxHuBfz zC+9d|dW~9`1qcWqXJPReXoJ9ye9;gc-A>qWvMG5@0f)8=u0jM`)Hg%v%T1P51N(a9#9HrQSLlBLZFd#{945YD>ta>7M&_Wwm8XA!b^I)UsNxvhh{04 zGC)u=-5_XcTg(Si=NmOY!BE)M@Xrw{lo+a9Ljk~HQ-o8dH`9_Av&}QHV!Q_|R3NKN z60zoFeyYm=K)%_E!?XfDNTQV&4}fY73D>OAVneze!lRuo(9X9vazdYx5%tMREEiS7 z1!8pEkozMs@Tdk-V*C-J7uAmIUrKm51sDXAZe|@xCa`z#pG!Qc34|qI+$dNk#1v!_ zspcdYJ@CGy8z$WlCJ-S+fIw+M)d~-yK0y3U5J4y}d^#ZH)Fg(s9C#rZbkv$=kaNXO zqaSmMl=<99f5_PjRhHK7i!iDkjR@*<*^mwXYGDwujZn>zO$!>5YwRO`rI=97P&HDt zeIe|JcOo{0#%M1#P{o96Yr<=y zq$o(t>}{Lhy0_$!f58PefLPP~WoUMCDr-P2U82VV3n9h&615oBLbYQBfPazWL9`JHbUQKyTehjw;xvT|K{29E376md%3H%gmDqG5 z2LgFh8nhc_8&@@h{2V+0I}@0N5OnBqOiY>)nf;wa0rN<3q?y-@N3wlsgqcvRBy{p{ zl&|5eS(K4lL{81FcR9b|6V1$$rh&v~HS&tfN0e(QgOBZ+VjlSJjcsXWgV&E{rrJ=^ z(3i_mo{9d?R};e!%0~ZcutUWc?Vz+a-;j-d1Ux_(%_I>lXAEro8Zw$%8vKp;OA%UV zSZmyC0rP1@$zXIWfLuCsrs*k~5JI?QL~$+v-qB_r>hMh9yP0!st$ z3!Yi7r6W+4YDtIWaN$&+uN~KcW);mWe7@3zjy)AMPG~)r=j4@}h8|$LHW^uX#UW}J zod1fvZhsHsh)d*nC3@dKJHCw_sAizEd< zfZ9Srp^zy#9J?ewD?|Ki50{)2fEiBi+R!LIb$(L2Vj#Vw5Yl+zxFuFpFLzRacGoc$7SC%GS-iqtgTZ9Z2`u3 zNpu1RX*|z@$fWwYTSSeJB&d`8A_3AxZa27|N2LfgkHL^~4Z!fie4}8bOgb1~w>Q?< z;$YO4E|fBW?6u1qwgyX(3$azXl3ViA0DJ=l>0GL{07y4$G7i46Y%vVv+Fh4uMNDbi zj4udPC{07>Q?;M0A4jzsj73zcdXiuh%smKSyhpkWFNdsIa*ya5a=LM1+3*s3VGckR z4ahtif+Z|S{7`}v5dDwF*Q673PD6B9usX@Au1!2`A9kcGE47K6#=YT!yw+>n3><|W zjtz1KMJZ;;IdmkLOmh}z0ku8K_W5AiDFWOvyALBxQ@<7gI`aaBoYY16baBrAtA)k@uW*52N;F&Lwz67B0W6cjzW{stXLOUaPG*ybZ!CpJVN|v&adMx zO@rB^<5{$$$5sT*WoYRwJE~0$=-L}@1GnvP0jFj(R3~Jn(RHMWSjDOYoG=SwO=NIj zM0K_r2k0ey6Sg_aYl4MhlU!Qbl?4Jk42AUz+GeRqd&??7B-4SjsBDCTy{hwdBv`Ek z?eGLhYdd9`pDS_YyYMP<%R^#bbUsflXWXy$ITF~(&t4dYOwQd4S?rHu`E zN+hEB^3wi`E~7(TbR-J^e6HrmLOm9Qf+s^fDZ)ceGrk=*=OMnui!5z)z%v4e2eX6{ zLTJ^gV*)&hZAA%P9Fm_P|3dI>2+0Ja+BrrV_~&|87WCpZ6?%MBlcyob1VnqHqw0yO z6cM%yO>%R8ha@fn8#&?dQxXuc4{Z(xHEye2uTghn`LB#lA}-4?C{ zfC?bdkeUf1)h|2)RuZ}gbWH#)3fBNArgK2#1UBQAb*KP(hH+p7jGwMe6T4?_#2Ti} zxu^k9QXAs~X|}`S(Au|zb2Xobp0wACA^=e7^(F&KH_`p%cSUqX$1S51-hQ(;ZJ{GZ zC>#wMHRh#LBBi6FiR5`mR&^c>#lfTE5fBj=QM8ChrzQB%yiHn|{M zlkWv5cGA|NPVB@DCnATC&BJGH&S~RG8W~l6Xud|nT~^t_G(q5Jrv@UJ!&fWS-6vfJ znm1{-Hz&^^qK%{(h~pXPVx(%7Sl{HIqUwhCIWj@-z`>*#3Qt71rWmuX%#-1g_ADI& zEagp7-n3zAqrOEyHR%yRXi$6VejQ%Hn&wc>nlPr4imDe)4fH}CJCQW4mrrs>1-fKv zqQi#e1o(A9YJI_~0*vG^1r!36KQJhOSKlgLKlPj#7mAdY9LPHDkKm70bI47h#UX%35o8vssXvmRhcTF&6dpAD)kdS3CukBIkxAPnoyh`g zJrFanM4~%clAh>h>>0un&;QQQ=r{~89yT_oon-=e9VY^vGByi}KIoc0g0@q2o(4eK zi%QO#<39S+nIWXpF{oV_pou>;tao*sBJ4ig(V3P4g|C+*O>Du1pk20!Dr#LyuxrDA zhelc(wu?sGSe*mHio06qwK<#{ZetKXs(8jJaLqh~f7St7RhTkBF7_qx~!t~iQMTANTr99w`jozKEHd}ip)jyK zQQa89C?CQ^=2NgOMSO-F0;|=Ij?Q=JlnMVyNfUnh zVHqS7Zm(sdnK%?CXk zA=` z6q+>GXbAS7xE9v1paUnEeQ7HS9}Nqvp`XJzRM*BF!z(@W$y4zi;1ZE23Cz4O*-@h%=OWWIBz zM5i`5v)cBQi%-WwB4PABNmw8`C|_++#~q0##tpB3F44DBM@`)mWi3I?(Agt)aW<~9tX+P)8STS8q zyT9}$<%uAP4qHn5spY4pp3M}CDNhME%DGz761KJ_gu5Di1D-5k%T(hfi^t zv&D)&9XfwRW6xv)N1dsWh7NYoc}4bl<7Sc$i*tA3$rhx*Mq}T4Shk}C87g&1a%j&#~&7}`wm1_j_4#|rPz3|5hZXEe9Y?*ZaE4d45Sfdb)D z`gbo-cGq^1Ps7QN0kbG8B%wx<;s;Peo5$m}jRRfCtwBWL1R{K@j#ji%F*jg6K=P@4GKsr-lF4U`RFu-N&`A?PFwEuP0-FmMIFS& z4;0F&;#ui5>+)_#(+!WVl3{9@f=k+zpEMwfgKTKRj%(oi^kLo;(nOr&+ys5^=nPSV zvHhZfz?Oxw1AJ={(8AC9*B0n#jiFKH3%72PwR7v#&+u&#&^@JqKr-#8qE(TL3FOy4 z8NM3dKyAWk+ApM?whM4~K+VbGzUo7Sk(K5(dyoKRSzUur!0DvltAX2otHFKB!RxfA z%0bl-{-)}Q_f(tdWH1Pc4k#KcVwFna~_d32+qPDaq&RGNyC=y13!i=|8{SDjQx zYLhSFKfa&Rg$Z$pI4;1S$mt(U!6HH1UTHkr#*e{b+aTwLC@V7J)Wg-$&aw(?Kwsg? zvi1QL4qTMYjlD&UAkw&(Ft*8)6`i7lqMxf%&q(e|l2#hgYX|a=o{nH|Zgl3>-ctwC zi1pJ!AH|Q7g2O$Pb_seAkpB|=88G_l{piTH4mFS?U=b6`vI;*@h1G*<0@=Nx$|J21 zW2Z8tG$1Xnf7LcUR9>;T!$}jMKDPcoA@J$(0f@1s&m{OLzL_+RHAVD6HN`M(8V z7@#iXch^Hz0-6{DO56N3b#ytokO~nrq~K76V%V;!7Ii+u0wq4e808s!f^Gm?KvYl_ z;23GpBpeovMw5cVB(U0m3i}6-1#tjfK=5E{Kn(;RG1fv-5CW*`>iecV2GfuB`40!< z_Wf~PY`(dG#;XH;d^r`b3UE3Q*aU>Q7ha`ze_LM$mMgPg1}V?+!T0s_6$PZgdVRs_ zq``YnN{OOal9Hw$L0kCnZ_cj0>~n9mN)`DM2?_;$2dh%<6$2Dj?lBA_Rb4`YFaJ33 z^baf0u<6fP)(Zf}ZBN-O=`VZg<>LARRWpnB`{Uaa&_u{%tpK~1*J%RO0C=E;R2)r? zXpwOkD61vg&e7Bbmupxoz&S8V1c!Jepnx*q4WtyPOM?btikO|Y)}#d6Eqwf|v&X*Z zi?6q845GYU50!-!Kq=9dy@z@!=Z?Ws8;cKM4Jaa-i1UupR*>|5?V7wuRhL(!0V;_4 zV2r*O#D7}>oy?hzz%(%hr0T%bc@lv@0!kt>sljD!=Hb`BJp0OryZxY50Vp)M5$X!G z1~-5YuxOy)LQ}}!`we{h+p|CErJsAys)V=)D(;PQw}q;KqJZeZ7#KUK>*-x1u-+}y zL=DM8k_GU+fPQNN3Ms2hHJSM<8q|a8^DmWX(6raA0f$Gi4K)OV_VC%?oqeMRy7PLg zl!0-8#S(O${ELggvN0Gfnk|Y~!29ogv-<(ueYI7TvLK3Dgw7ngGK#!Vo%q&NdBMu_ zeJ`Kis(>E4Q&G&DijZQq$3FX>#oh;1fO2>W2EYY5?YHlKb77f|m+y<9c0H_4L=Zv> z7@csTC#8Tkw+JI#o=c4O$w%Mp{&#=Ys*psJ_MN9JEk*W`BMunznWYG5*1+Ej=(j1L z`Ri)uQ@Vq|$!4vo_d$``2S{Ut%?3XI`+q&bye6oxwn|y?BQdb)JC=<`;RvkQUV={W z={J0aSKn+^&|vM5wWVlDjXek`!$H7Ud>J9xvQ)l`Z$aqs?kC zBv5)pXP99aM(U~oEHQdQbQIR&Tu)Jy2gdz-9Q1LA{YKKAgCue0nMhJVm@W39CameYl@QN{)fN+ z^U;-fHKjJB2-`~uphho&Vp7nLUXYCV zy#RizQT&xq9z;dPjCraK2zUa$yM;}EUVi6G_ghs~NahKMA)$?g?wf8)-7I!~_~mxX zYH`YT3w6%nKl%gw)9>VcUwXY&MJ?mgk6*AX8(=AUjPL!=uTp{jNTKQ*{7gMBoQD`E zG3Vcf-60gY5`{3({%nNvUaQJdo>?o=pfM_vmaLa87Yw5eiM5v1VnyFWUBU-{dwmfa zV7-B6l_<*^Po(S4IcaX8rtI5+Yn1Ys%c$!)&*?aY_gxmy{$LpG)xnyy;z5Ev9dkYv z3}d9KG%91PlQ%_Sb zNbUwdD#EIP?U*Rb6^h8BNhmy$T`C}IoC8~dSBb!YLZdPwk}@T=P?=wl_Fw%j3#r{N z!-K5wEc_9(OzJD=gaB13pQV)OgQv757neP&lM0pK;otnn7tXt{wMv)Jjj&pQ8zMz1 z+<_3q7yW34D==KbYPmo;@w5N;AGhj%{P(NptuJ9^q12WTz&p{4l}VIEwl-0VuNxsL z#o!u>3Suw5YF!KUP%Chwr?3|O6U0~+Y7!cS7MaW@MyX@&@${S9@t3r+SPgN2A@tOX z0%Mnq9!^dQyn{6S#~y&&4_bv5_8STorM#o5)@%n)ZT|u{+)VxZ?FakMU%A(+)2FYW zQ#B%JA03=~=RvEqQ8<@rdSrg<2p`T^o0lK7$|*<&iYhRy*Hp_@W^8|VGf_Gvfr-+Q z7^W+Jsm(5cx?=1V9^d!q0-A+Esf0>kwPafeUriMLcNNZw;8AQC{Qp9+LE`|AA+o3n zdF?0ARIlC@QcCaVp^^_ixH=9Wy?d5|18obOx1t!!S0BTt>4GWsortr-GnUD0jevzf*A{JmB+ISuNf{CxbkPyXI_ zf7YrLA#C8`0p0Jpw_4$VZ{X7d;ePe)R{79TmzLl?##Y~H4QjtiIQ5ZQRS1@+c7qZL z-5S$0_^9ZIoK5lnelPXH-BuMAiUz!joNupBU|C2;DABVlPh=<(JazIz01CT@k&=RN z)A%%i-T;ovbxFNgTs!Bv=USyspm*^5BTd>3QU&nvh>Pli1WcbDo$nnKb;CIJl;w9@ zI03Al;2|<=m~bGm7DaJw5O(BbETkV`s;40-j4db)oIir!e+5(NnKxSX`L{&1GnxLk zegyT?n##`Ow}t^QJbHA=Q@1LJ!o)9YP}<;Ak2M7W=C48KW$Tg{mfULKd^7VrE9eU_ z&CCQe^TPk%Zx|b0L1d&XYyLAFR-lfAu)QZCJqYk8-r{jJrsx^@iiRO)N@9Ava6b1& zCJ-BVv29h%xBlc`$sKquGmk)+^p~48#bR~koFBj3s?tCTJ<2S2>Zuz30-;`u1^NaP>qCD`oK)S!cu~*GyNQ_d6<}F)Ea@c@#>ZV$nPW z!Q%Q+l0&6od%4*;rDHb`U7)HJLBYiqoQKaI1IGXKUaPDX4Ws zJo{3s?!M8gJ8!h=*;l`wz<%`JSsMGS+H?&p2~M=zPNRifap}azL=9KD!)ouM8w^_A ztf^`P!Br?N3vd0!^>ez5!z!d>35U&vls#WD@$a7{w}sfr&&ThbrC;ZFi^IXOHzm@=Lv)vv z7EJm9al4|@B_=^_5``9S<>^T#QW){ko_YQ23F(KwIuq;cDj2|c*q&eYQ6~pSq_hLQ z2GfBZr0Yj2fCVX8tcqw0fBDk&=lJLsXX%4?&JsbA7XSG9^>Mhh0P982u4&fHX~uK>UkuO4+Y5V2F(Uz@l!5KA?@+r&1Hd7|>P` zgF~y5z6;cq#d)#Pqfcn7=sNiA*AURVcLhuQAW!)1w_2qX3|n~WAa0VP(=IQNYEOd6 z8Y%>7264HOTKjkq!J7nqFV*ggg_atFTu7Ka7za%)*YXOsql}5~p{a7`5(7y^Mwe?q zGbt?O>uW0kQdP-)y6%$2j!RnejSD0GBMWFuYoKJaNiw(k_Ip8q6ID*kh#2K7? z{O|@SnM1hSfXaK!;_G%+e+numZfDo0@kq9%AD>=mUYAQKkG zo9{a-r1x6Y2dRlNWp1hfSnsl3)fv~#F?O(55ep4N-&0kxI0v6ldL)?x^Y`VwU-Ok8kr2`9I}1xH~D#&Mu3rM*s! z2BR&Ia?7B_cUyyYE@F&AMYyt^dT$V+*al{zkD(weffcy&p5G@ z+=kj3Ds2efqiwM>?&?}^shE39MewDVl_UXSk?}~E2CS+vQApcCtr>`DP9bIibsj2* z4+GeS_29Twt{}>S>9&q$WpKWyumuUlW;@UVx5LKF~v#2STCij)#QBur)iD@Q}7dolvSIQjwg-8g{OZ_YPAA5H@j>uzjlUMJrjz5ZrCO$}S zwv;is5q|ZACiKpmt(s^g6GWp9$;*?2cl01hO+u(qsW=jf3Hr&{YdXke?YOBzt{_N2 zM}iM-(5TPdYn9IMmSKaBTMAv^hCorBN(a0swp=NR7Ps3=nx;bOM2rJUgThEKIaREx zK=K}COL^#Iug|#xb*1HvG_#PQ$ilYkUg<~-c>ppfm8N%|7HrD*ulAh+kK0?$PJEmf zkaTtEr>jJDc-C>liR|~J!#TN0K-0{iQO7h+bdCIP-)D0?s+=LImN}&wCj@z>Pn8~a3FI*-c;knp=Q=s2G<42W@+X#S$E!Ql`dfP z=QQ?~$iJ3%tgKXAni4`xq!hAm98kHbs)=tpSV(T`h{f#nLc>d_1|g$11S2%XgQG12*&aJnl4n)2FA9CK0i_41Nk zuGQ~Nf&y&=wip94jtj|VS!{IY6p){j5d`=+?ptWkUdU-0k&;*mlaQ1lsQbJ_KX zN9#&oUvyWhc=goh-*SmCEQ`NwTQUy>FgQ6(1 zSsx>1scA}^HT8JK%ZNMAMS>u$s%s&mnzZKxp&YEJcp%28ye#urA_~+`tbfTCHHkh$MI~^`X6;!nb7La5B3!Oy@Q%6(BnrVRZd<&%}FW+mGDW>2%ptZwd_nDk4!QP}@ z(m`aNCqd=>KL*k=`xjHR9*@i;SEA>1BR5yi2y&c>rp;ALE3g&(cZyfk>f#@aE@&}qI$7MPGT zBs&3}+AtP5`qcZ}CI*7$AXdu0s{<~xh7gmlufQo?7SJl=qY%AEmlp4GQeh!^d>sWJ z*O{88BAj2qRMa+P=Krob)xjt4f3;A*`ev&}57M{6=P|W2PX82@PbRQ9&=!-aEDi*e z1A#u&bdwo&$ksa56?jUi$KjyI0;;b^;$cRsAC{V{uM*IM(&@QfUal>cBh49SeDZ^5 zQ7P9XrL=#?h)k@H;)5*~G7vs^tUYqr4=h^OL9@*H>pU?gPo5hj`vTB!I_joj=n~aZ z?KEUJd_hws(xgGt3fGrZRTehuuzDl}k1;32Aqf~^tvG605r}LZRA#?me2`5R^tAa# z5?`~b4@ffUXfD(K^+pH3`PEr^?Psm>PToUnaK4lB-$^qbG_gooIH%?dDMefusjS6C z(5aLTcL&1cgQw7vAxi$BU{g)CUt<=~lbr=p`bh;ehnNAhmL9DkZ}^~c8kt{S^?;2vjXtRUZR2I&ZgVo?ASl?;T=*1C?SwOo^@J%=F zHO%NF&)HOR!Odo5xhNU>L{%%2lljpGoKLtg(ljECK9eJ~$`6sVCl_C?IemJSCnKV? z0~>L1E#EJ05i{o3=VuBoV2t=^M(1t{W6C#(jIN`oN+OCc&mB+QYVrUMd2&5N7^uvO z$Vwo!V-t1k!so4UViHJ7WdYY$pdoW*TbZOH(}oF9?7~5CY{zp7yP(i3x-HZT82pCX z%6J8*&=Ut$9mt4!v`cOzR=X7NlWNdm98gMA77NBf;t0}#p4qvDqF8)CV5{b;A9{dc z$E@wmP9slJWoMsZ+ij@p8m;y&MoI_0uY$;1O8Y&llm-=34;TV=2f0iNWjpjNs*>LK zGYY0RGOX7u44^q*n>&Mv5}~pt&3)?R?1~3oKgt9bP*5@D-!0uvzhTZo{G|(Rd<`f&xXuI3!AY z5G5Y$IhC^OqaKSx9-CFW69@%td#DyNe8ae=E{!nCw8p3k?_zGad)4eFMHbM2x#BY) zcZ`no!(jM0>(!l$0? za3MavPnT>rD?WKbcF>EjXLgVVt0Hk6u-ag(qIZTuYogB^X3Z4Oz4&sg>;hB?hBbaL zSlwW(_=U!Zy6?B}*~9r~`qA^P(zURys<@x5FlD=j3l+kQsJ%4`b=$ z6l->%4hah`1PW71Ezm?TiIaJqX!1?|p5NiSDTrWx@Pr)JXJ2Yny_5{9PXj4l(iFFL z*`;aw9M=SU2&CDiAorL+ zJksF$8tAy~wk(>}-cQd9E<^|inQoW1lqwREqf&L|>!h9-Dn9s{{gZzBpjAz^Uq4f` z1{LOW;>X7eZ%NCUr4h~LomkG~;ln3gEN`_c^f`#j9Owz$pWG3XWUHH1CMb^^Vd@u$ zRl6x3Kv`2~zWp({fvQ+AI!~Fu=*NW80c*p753BOG?T(%phwBXdujH_1ilA0qR$c`} zdl0h>yNXjO3pbA?EvF^mXP%(4GpeM1^vGz(b_YL`^8JG}A`>QY~s!IFm_ z$4FUNh8{MT@Pnr%E0?r1XS>+It*5e~NNY-E=!Z2rQsF(k^fimqrb@+tW9yta>@$Ro zpWINT`I~pnk`8i>t&!ss)UxC$QnN4@3{CgJ1vrEWQ6XXKC07 z$2B;ix0fdoOb=>9;DY@|W4S?7D%khguW->)6sPnqVvCwFcs6~9EtTwUeAttJhZp4_ zNlP8#oj0yO|8sA&>e-*Q>c=znR-1DPE{9>dwmnKvRS1*5cp~bXa}K2h>>%yqf;o2D z7aJ%SB6)6{;G-&+!4yX@nZKUmOjlhD??t-?FX_Ol6ybEE^iuuJFVE6P@0_K7{O~NL zL8@@VxFjS+T{Xf74G}^Qzy6xr5Wd*9N;6=n*gS&IKRgo7S6XFi(IhuDX}J9}srKAl z!sqYLe19oU`8dEo&S;`%?}=G-SqXmp*E5Z`UT#&j1fLSN^mKltuuJLEA&&UY&cq4M z%VOhv=48e_Ib@;0GtrP$m(j8P=SdcAQQJ z=v>VA&GgM3@}1X_4-%7nG^2=a-))tTP_M-AcfnyzzR=fgLU;RTtrDt7u`drfI%+HI zp9I`}y;XC**x)nXHM6R9geHGuRl=QntvY_O&whE9UU*d|`{NrH!H0R_y!2YDC<~G; z=%VD@KRWu(o!47MmGx?dmwbP=onE+W3c3|;j^7X?6keO zg&#d=)$flQSNH>>%Wn?G?b-X%?Ber04!3{SDyu~ReTKxk9zOYC#(cjb%^x0@ZgzWxYMfTNrA=pC|!T;`u|~o+KxmlRRJH(Xs!uMo$%Bb?zHMRM?Hu>|HWDQ z$?L6}E4!^r5u&mTi~|&QKG9xi;io>y5wdgs$qhdDrS%Z{T7Ji!BVZ3dDrQvBHIAP4G&itDc`u}W=Dzk zqv|N@4VO2ld8K5cpZTkKU-jkJTlM3Y#N9~lx^VvGy;ePQ?1MY80CUGb&!7vdMq1LK z0%L!1P%E?%D{(x*zc@=p1pjCz0DYxZU#EgYC3*2qhPhPotP2UMCjPAN{K6B)IfAY~;N(!ERbAFzleZ5sLJZROOw_BA;xEw&E z3n`oU8aqzdykS+MkkZ>5!mIOh$&dYyhl2nB3+hQkK~x6?gm`0n`gC^r}?D$q%G8PYUypUNYAMuCktHHm-22`7Tp6O zw)|)&_;pd-fZGqQ|IL=-)|{VTk0~P8!Gcd8o~7jB{1T0UOwM;*`*DAXdVK*c zIH{Rg9G|=^Zh@PjlEx$f%4){i{ofzVkJFs&kTL$$z@4{S_0iv)rI%lm67Udjg2Uwh zTdSG~tS`3$*eNxyeHN#ZxOncZR((3-uT&}rK@RS`(yF-%%iv(lOQyQXMCqIN3G)0%I)DGtd0Y>#Yh7PHcwk3@j=sckoFQmH7GB7Do+Z=vWx>L$p4f zr7Zu$yJzXyw_0^$S3WflH*GptE^^lRcyYWYO@E70S_#!fZYD8vZs;MFA|IPUP>Ib3 zn$^uazUZ7#FnP>RPZns5ryJ(sG@Z#3H)+UiCbpa6W)$GlpPwb|B|*1c&!7RXwyIcw zUBWZ3TsJwN{`@SB=g<@d$q7a{C!uvUUtsw0J7-BUk!s&saRx2$Av3XZS{*AZdTwXD z%|-6Ml5_q~pC}XsDKuDJ6J6R-@k*@;GZJ*Uh3Z6nY+Hg(f#?SefuUbxnQ!H&5-dzZ zw;d^22s`NplD3L6e{&e@*w2r}qRG7nX5QQ7I3gN2y(NK+uIA_d_rEwxWe2Kqz<#DnN^axSn%2iHl&6z5-X@tDncfA`5*(g`lUgnB9P%iMXNy?2&2U&8N> z{jGb_3@ho8qz0PR{C)oM;aTdxgiqf&OaJ`I)oZ+Zzg1IixxS&NtKZ1`Oaheu=;`}W7IJ}X_=P4?NLq1bRQ~6~v!tU~ zt`IzhHI%j@#-7t=g&(Et zQy(Ay^no;GE0e?xAO8GIYAy}DcyC6z{PHY4{DlDVAHH*z>O5}FXE^Uzo<2NFjPQ9z zQZyEof+u;y-`%ha+})qGDq5l3eR@M89>a%8aB(hsQa<>wFQ!l<8?ZieuT{@K zxcM5lUu)Ivw^|jI_+;yCqAD~dYsi;pzWdVsR$Z)fA~K2gzUlfe-EEckkKY~d{Lxe= za3Gi}7ro)cRZcv%!R$|8Y?VsF2?ZFp(zR~2C}sn`EBF6WT#SgPs3a5j`fIJa_wo%; z+nrY3zuzirB)ICvKU_mDKo+k>k@){WkKBIHs-NDye$6{Cw(6DFS{0)pFqc~??|$)y zwDha_^FlX7@2D$Dyv&h_?mlQ$3=@PlY|*A+(@VxfHJM|%l|aDc>I|Q=8!<^R(Ug+q zSX#JP!|Exi;tW{E?3aG|B|P=CY_D=FN2L?_H%g`Q&V}gxmlS19qG2azn<6^@eS~p{oBY z>#g{q!zj_cnFJ`x{axDPOi!gwFg^zYN=&z3fK!sj-JHW;oC;nV1L!6aRL9ya`RqvR z-M!x`-9S|5Xe@yxG55uq{6}k~->Fj2<;@<*f7dy%H50{mY7y^*fHDz+%0hfiQ%X;; zsVD5z2h67q&4AUVEY+gPH&CEdN409CFZ$rHO~HCQQY}i>!zCwmgCSumVcMMDlFl7P zS)fyt3lsS-Ps`Iib(&GMB4M~CP+F0-+2rIWjT=U)s$o?@WJ_Z_4$q>oXevyp(77a{ z;(`d&%`MyrWl`nP@OT_9oKu<#rB_7P3AYsJhmK{nkX&P?t(j7z$|`Ha$mRN+X03{gi>1OV zxb;Jkg%mwnODRc_SzH!+5(*aIDjkvI`5|D{NtLevLMfrTL-M)&r+av7?2ZRFN1x-3C^xhNK+bu%W3c#&Jzd z9jB{?L_tVeYL^<&lz_uh5GUMrB9N!4F_i^XUFEQ=k@NK*d3yD~0hZ17lEvag$^s3n zhd;8YR%jZc18oWl`!ocp2SW+FNGoZQVU)uAErlsS8BAIVEHgC&G#yE43Mw|^NK=Z1 zD73~dYCi%K=esKcNJ;M933LRTRcYfbncR( zSdvI6EY4|48k~bglY6B^kJ16>I;x_;`H_I8v?px0y)1b}+Tnd;+%QO!cWku~Z#pKx zQR;vX9R^K-&HkK6YuH>SfkjeIct?&QACV3tQK`9!WURo zqtH}kO;fGdZhI7(m_dF8^!=964f0%*a2~X-x!!hQ-#g{$)hU115JA zY>H+__e(xN7|>eEMk*`SO-7ZJb_q$ds28Xdg1FjRWty%;a5mU|XKVs2dVF*!y+Sq@ zfX(KT#j<4ArOrbfd-R0&=sz7Nj5T!7qabOs$iR)kb}MjA%H2x zN$j_>_gJ-vc8e)9 z)Z@M<>O}vW`l^v4%1n(O3R0?A=hp3R=vY++F?x))Y`UJJS#YsgbFw_8OyJjY?iWL@ zOBw}uweA$A o&piNQc9V3j?aG()gSZ0!KLh6sReP576951J07*qoM6N<$f`H8iw*UYD diff --git a/sendat/Makefile b/sendat/Makefile deleted file mode 100644 index 6b25f0d..0000000 --- a/sendat/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -include $(TOPDIR)/rules.mk#将openwrt顶层目录下的rules.mk文件中的内容导入进来 - -PKG_NAME:=sendat#软件包名 -PKG_VERSION:=6.8.2#软件包版本 -PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)#真正编译当前软件包的目录 - - -include $(INCLUDE_DIR)/package.mk#将$(TOPDIR)/include目录下的package.mk文件中的内容导入进来 - -define Package/sendat - SECTION:=wrtnode#软件包类型 - CATEGORY:=Daocaoren#menuconfig中软件包所属的一级目录 - SUBMENU :=CPE#menuconfig中软件包所属的二级目录 - TITLE:=Sendat AT#软件包标题 - DEPENDS:=+libpthread#运行本软件依赖的其他包 -endef - -define Package/sendat/description #软件包描述 - A sample for sendat test -endef - -define Build/Prepare #编译之前的准备动作 - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - - -define Package/sendat/install #软件包的安装方法,主要就是将一系列编译好的文件、启动脚本、UCI配置文件等拷贝到指定位置 - $(INSTALL_DIR) $(1)/bin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/sendat $(1)/bin/ -endef - -$(eval $(call BuildPackage,sendat)) \ No newline at end of file diff --git a/sendat/README.md b/sendat/README.md deleted file mode 100644 index 00fe05c..0000000 --- a/sendat/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# sendat -AT 命令工具 -1简化使用AT命令请求方式 -使用命令说明 -sendat 2 'ATI' 2表示 /dev/ttyUSB2 'ATI' 为at命令 diff --git a/sendat/src/Makefile b/sendat/src/Makefile deleted file mode 100644 index 301b189..0000000 --- a/sendat/src/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -all:sendat - -OBJS = sendat.o - -sendat:$(OBJS) - $(CC) $(CFLAGS) -o $@ $(OBJS) -lpthread - -clean: - rm -f sendat *.o \ No newline at end of file diff --git a/sendat/src/pdu.c b/sendat/src/pdu.c deleted file mode 100644 index df7d9d4..0000000 --- a/sendat/src/pdu.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * 2017 - 2021 Cezary Jackiewicz - * 2014 lovewilliam - */ -// Copyright 2011 The Avalon Project Authors. All rights reserved. -// Use of this source code is governed by the Apache License 2.0 -// that can be found in the LICENSE file. -// -// SMS encoding/decoding functions, which are based on examples from: -// http://www.dreamfabric.com/sms/ - -#include "pdu.h" - -#include -#include - -enum { - BITMASK_7BITS = 0x7F, - BITMASK_8BITS = 0xFF, - BITMASK_HIGH_4BITS = 0xF0, - BITMASK_LOW_4BITS = 0x0F, - - TYPE_OF_ADDRESS_UNKNOWN = 0x81, - TYPE_OF_ADDRESS_INTERNATIONAL_PHONE = 0x91, - TYPE_OF_ADDRESS_NATIONAL_SUBSCRIBER = 0xC8, - TYPE_OF_ADDRESS_ALPHANUMERIC = 0xD0, - - SMS_DELIVER_ONE_MESSAGE = 0x04, - SMS_SUBMIT = 0x11, - - SMS_MAX_7BIT_TEXT_LENGTH = 160, -}; - -// Swap decimal digits of a number (e.g. 12 -> 21). -static unsigned char -SwapDecimalNibble(const unsigned char x) -{ - return (x / 16) + ((x % 16) * 10); -} - -// Encode/Decode PDU: Translate ASCII 7bit characters to 8bit buffer. -// SMS encoding example from: http://www.dreamfabric.com/sms/. -// -// 7-bit ASCII: "hellohello" -// [0]:h [1]:e [2]:l [3]:l [4]:o [5]:h [6]:e [7]:l [8]:l [9]:o -// 1101000 1100101 1101100 1101100 1101111 1101000 1100101 1101100 1101100 1101111 -// | ||| ||||| | ||||||| |||||| -// /-------------/ ///-------/// /////-///// \------------\ ||||||| \\\\\\ . -// | ||| ||||| | ||||||| |||||| -// input buffer position -// 10000000 22111111 33322222 44443333 55555333 66666655 77777776 98888888 --999999 -// | ||| ||||| | ||||||| |||||| -// 8bit encoded buffer -// 11101000 00110010 10011011 11111101 01000110 10010111 11011001 11101100 00110111 -// E8 32 9B FD 46 97 D9 EC 37 - - -// Encode PDU message by merging 7 bit ASCII characters into 8 bit octets. -int -EncodePDUMessage(const char* sms_text, int sms_text_length, unsigned char* output_buffer, int buffer_size) -{ - // Check if output buffer is big enough. - if ((sms_text_length * 7 + 7) / 8 > buffer_size) - return -1; - - int output_buffer_length = 0; - int carry_on_bits = 1; - int i = 0; - - for (; i < sms_text_length - 1; ++i) { - output_buffer[output_buffer_length++] = - ((sms_text[i] & BITMASK_7BITS) >> (carry_on_bits - 1)) | - ((sms_text[i + 1] & BITMASK_7BITS) << (8 - carry_on_bits)); - carry_on_bits++; - if (carry_on_bits == 8) { - carry_on_bits = 1; - ++i; - } - } - - if (i <= sms_text_length) - output_buffer[output_buffer_length++] = (sms_text[i] & BITMASK_7BITS) >> (carry_on_bits - 1); - - return output_buffer_length; -} - -// Decode PDU message by splitting 8 bit encoded buffer into 7 bit ASCII -// characters. -int -DecodePDUMessage_GSM_7bit(const unsigned char* buffer, int buffer_length, char* output_sms_text, int sms_text_length) -{ - int output_text_length = 0; - if (buffer_length > 0) - output_sms_text[output_text_length++] = BITMASK_7BITS & buffer[0]; - - if (sms_text_length > 1) { - int carry_on_bits = 1; - int i = 1; - for (; i < buffer_length; ++i) { - - output_sms_text[output_text_length++] = BITMASK_7BITS & ((buffer[i] << carry_on_bits) | (buffer[i - 1] >> (8 - carry_on_bits))); - - if (output_text_length == sms_text_length) break; - - carry_on_bits++; - - if (carry_on_bits == 8) { - carry_on_bits = 1; - output_sms_text[output_text_length++] = buffer[i] & BITMASK_7BITS; - if (output_text_length == sms_text_length) break; - } - - } - if (output_text_length < sms_text_length) // Add last remainder. - output_sms_text[output_text_length++] = buffer[i - 1] >> (8 - carry_on_bits); - } - - return output_text_length; -} - -#define GSM_7BITS_ESCAPE 0x1b - -static const unsigned char gsm7bits_to_latin1[128] = { - '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec, 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5, - 0, '_', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xc6, 0xe6, 0xdf, 0xc9, - ' ', '!', '"', '#', 0xa4, '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', - 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7, - 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0, -}; - -static const unsigned char gsm7bits_extend_to_latin1[128] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\f', 0, 0, 0, 0, 0, - 0, 0, 0, 0, '^', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, '{', '}', 0, 0, 0, 0, 0,'\\', - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '~', ']', 0, - '|', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -static int -G7bitToAscii(char* buffer, int buffer_length) -{ - int i; - - for (i = 0; i buffer_size) - return -1; - - int i = 0; - for (; i < phone_number_length; ++i) { - - if (phone_number[i] < '0' && phone_number[i] > '9') - return -1; - - if (i % 2 == 0) { - output_buffer[output_buffer_length++] = BITMASK_HIGH_4BITS | (phone_number[i] - '0'); - } else { - output_buffer[output_buffer_length - 1] = - (output_buffer[output_buffer_length - 1] & BITMASK_LOW_4BITS) | - ((phone_number[i] - '0') << 4); - } - } - - return output_buffer_length; -} - -// Decode a digit based phone number for SMS based format. -static int -DecodePhoneNumber(const unsigned char* buffer, int phone_number_length, char* output_phone_number) -{ - int i = 0; - for (; i < phone_number_length; ++i) { - if (i % 2 == 0) - output_phone_number[i] = (buffer[i / 2] & BITMASK_LOW_4BITS) + '0'; - else - output_phone_number[i] = ((buffer[i / 2] & BITMASK_HIGH_4BITS) >> 4) + '0'; - } - output_phone_number[phone_number_length] = '\0'; // Terminate C string. - return phone_number_length; -} - -// Encode a SMS message to PDU -int -pdu_encode(const char* service_center_number, const char* phone_number, const char* sms_text, - unsigned char* output_buffer, int buffer_size) -{ - if (buffer_size < 2) - return -1; - - int output_buffer_length = 0; - - // 1. Set SMS center number. - int length = 0; - if (service_center_number && strlen(service_center_number) > 0) { - output_buffer[1] = TYPE_OF_ADDRESS_INTERNATIONAL_PHONE; - length = EncodePhoneNumber(service_center_number, - output_buffer + 2, buffer_size - 2); - if (length < 0 && length >= 254) - return -1; - length++; // Add type of address. - } - output_buffer[0] = length; - output_buffer_length = length + 1; - if (output_buffer_length + 4 > buffer_size) - return -1; // Check if it has space for four more bytes. - - // 2. Set type of message. - output_buffer[output_buffer_length++] = SMS_SUBMIT; - output_buffer[output_buffer_length++] = 0x00; // Message reference. - - // 3. Set phone number. - output_buffer[output_buffer_length] = strlen(phone_number); - - if (strlen(phone_number) < 6) { - output_buffer[output_buffer_length + 1] = TYPE_OF_ADDRESS_UNKNOWN; - } else { - output_buffer[output_buffer_length + 1] = TYPE_OF_ADDRESS_INTERNATIONAL_PHONE; - } - - length = EncodePhoneNumber(phone_number, - output_buffer + output_buffer_length + 2, - buffer_size - output_buffer_length - 2); - output_buffer_length += length + 2; - if (output_buffer_length + 4 > buffer_size) - return -1; // Check if it has space for four more bytes. - - - // 4. Protocol identifiers. - output_buffer[output_buffer_length++] = 0x00; // TP-PID: Protocol identifier. - output_buffer[output_buffer_length++] = 0x00; // TP-DCS: Data coding scheme. - output_buffer[output_buffer_length++] = 0xB0; // TP-VP: Validity: 10 days - - // 5. SMS message. - int sms_text_length = strlen(sms_text); - char sms_text_7bit[2*SMS_MAX_7BIT_TEXT_LENGTH]; - sms_text_length = AsciiToG7bit(sms_text, sms_text_length, sms_text_7bit); - if (sms_text_length > SMS_MAX_7BIT_TEXT_LENGTH) - return -1; - output_buffer[output_buffer_length++] = sms_text_length; - length = EncodePDUMessage(sms_text_7bit, sms_text_length, - output_buffer + output_buffer_length, - buffer_size - output_buffer_length); - if (length < 0) - return -1; - output_buffer_length += length; - - return output_buffer_length; -} - -int pdu_decode(const unsigned char* buffer, int buffer_length, - time_t* output_sms_time, - char* output_sender_phone_number, int sender_phone_number_size, - char* output_sms_text, int sms_text_size, - int* tp_dcs, - int* ref_number, - int* total_parts, - int* part_number, - int* skip_bytes) -{ - - if (buffer_length <= 0) - return -1; - - const int sms_deliver_start = 1 + buffer[0]; - if (sms_deliver_start + 1 > buffer_length) - return -2; - - const int user_data_header_length = (buffer[sms_deliver_start]>>4); - - const int sender_number_length = buffer[sms_deliver_start + 1]; - if (sender_number_length + 1 > sender_phone_number_size) - return -3; // Buffer too small to hold decoded phone number. - - const int sender_type_of_address = buffer[sms_deliver_start + 2]; - if (sender_type_of_address == TYPE_OF_ADDRESS_ALPHANUMERIC) { - DecodePDUMessage_GSM_7bit(buffer + sms_deliver_start + 3, (sender_number_length + 1) / 2, output_sender_phone_number, sender_number_length); - } else { - DecodePhoneNumber(buffer + sms_deliver_start + 3, sender_number_length, output_sender_phone_number); - } - - const int sms_pid_start = sms_deliver_start + 3 + (buffer[sms_deliver_start + 1] + 1) / 2; - - // Decode timestamp. - struct tm sms_broken_time; - sms_broken_time.tm_year = 100 + SwapDecimalNibble(buffer[sms_pid_start + 2]); - sms_broken_time.tm_mon = SwapDecimalNibble(buffer[sms_pid_start + 3]) - 1; - sms_broken_time.tm_mday = SwapDecimalNibble(buffer[sms_pid_start + 4]); - sms_broken_time.tm_hour = SwapDecimalNibble(buffer[sms_pid_start + 5]); - sms_broken_time.tm_min = SwapDecimalNibble(buffer[sms_pid_start + 6]); - sms_broken_time.tm_sec = SwapDecimalNibble(buffer[sms_pid_start + 7]); - (*output_sms_time) = timegm(&sms_broken_time); - - const int sms_start = sms_pid_start + 2 + 7; - if (sms_start + 1 > buffer_length) return -1; // Invalid input buffer. - - int tmp; - if((user_data_header_length&0x04)==0x04) { - tmp = buffer[sms_start + 1] + 1; - *skip_bytes = tmp; - *ref_number = 0x000000FF&buffer[sms_start + tmp - 2]; - *total_parts = 0x000000FF&buffer[sms_start + tmp - 1]; - *part_number = 0x000000FF&buffer[sms_start + tmp]; - } else { - tmp = 0; - *skip_bytes = tmp; - *ref_number = tmp; - *total_parts = tmp; - *part_number = tmp; - } - - int output_sms_text_length = buffer[sms_start]; - if (sms_text_size < output_sms_text_length) return -1; // Cannot hold decoded buffer. - - const int sms_tp_dcs_start = sms_pid_start + 1; - *tp_dcs = buffer[sms_tp_dcs_start]; - - switch((*tp_dcs / 4) % 4) - { - case 0: - { - // GSM 7 bit - int decoded_sms_text_size = DecodePDUMessage_GSM_7bit(buffer + sms_start + 1, buffer_length - (sms_start + 1), - output_sms_text, output_sms_text_length); - if (decoded_sms_text_size != output_sms_text_length) return -1; // Decoder length is not as expected. - output_sms_text_length = G7bitToAscii(output_sms_text, output_sms_text_length); - break; - } - case 2: - { - // UCS2 - memcpy(output_sms_text, buffer + sms_start + 1, output_sms_text_length); - break; - } - default: - break; - } - - // Add a C string end. - if (output_sms_text_length < sms_text_size) - output_sms_text[output_sms_text_length] = 0; - else - output_sms_text[sms_text_size-1] = 0; - - return output_sms_text_length; -} - diff --git a/sendat/src/pdu.h b/sendat/src/pdu.h deleted file mode 100644 index 734a393..0000000 --- a/sendat/src/pdu.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 2017 - 2021 Cezary Jackiewicz - * 2014 lovewilliam - */ -// Copyright 2011 The Avalon Project Authors. All rights reserved. -// Use of this source code is governed by the Apache License 2.0 -// that can be found in the LICENSE file. -#ifndef SMS_PDU_H_ -#define SMS_PDU_H_ - -#include - -enum { SMS_MAX_PDU_LENGTH = 256 }; - -/* - * Encode an SMS message. Output the encoded message into output pdu buffer. - * Returns the length of the SMS encoded message in the output buffer or - * a negative number in case encoding failed (for example provided output buffer - * does not have enough space). - */ -int pdu_encode(const char* service_center_number, const char* phone_number, const char* text, - unsigned char* pdu, int pdu_size); - -/* - * Decode an SMS message. Output the decoded message into the sms text buffer. - * Returns the length of the SMS dencoded message or a negative number in - * case encoding failed (for example provided output buffer has not enough - * space). - */ -int pdu_decode(const unsigned char* pdu, int pdu_len, - time_t* sms_time, - char* phone_number, int phone_number_size, - char* text, int text_size, - int* tp_dcs, - int* ref_number, - int* total_parts, - int* part_number, - int* skip_bytes); - -int ucs2_to_utf8 (int ucs2, unsigned char * utf8); - -int DecodePDUMessage_GSM_7bit(const unsigned char* buffer, - int buffer_length, - char* output_sms_text, - int sms_text_length); - -int EncodePDUMessage(const char* sms_text, - int sms_text_length, - unsigned char* output_buffer, - int buffer_size); - -#endif // SMS_SMS_H_ diff --git a/sendat/src/pdu_decoder.c b/sendat/src/pdu_decoder.c deleted file mode 100644 index 9e9e055..0000000 --- a/sendat/src/pdu_decoder.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 2014 lovewilliam - * SMS PDU Decoder - */ -#include "pdu.h" - -#include -#include -#include -#include -#include - -int ucs2_to_utf8 (int ucs2, unsigned char * utf8); - -int sms_decode() -{ - char buffer[2*SMS_MAX_PDU_LENGTH+4]; - char *p = buffer; - char t[2]; - int d; - do - { - t[0] = getchar(); - if(t[0]=='\n') - { - break; - } - t[1] = getchar(); - if(t[1]=='\n') - { - break; - } - *p = strtol(t,NULL,16); - p++; - }while(1); - - time_t sms_time; - char sms_phone[40]; - char sms_text[161]; - int tp_dcs_type; - int ref_number; - int total_parts; - int part_number; - int skip_bytes; - - int sms_text_length = pdu_decode((const unsigned char*)buffer, - sizeof(buffer), - &sms_time, - sms_phone, sizeof(sms_phone), - sms_text, sizeof(sms_text), - &tp_dcs_type, - &ref_number, - &total_parts, - &part_number, - &skip_bytes); - - printf("From:%s\n",sms_phone); - printf("Textlen=%d\n",sms_text_length); - char time_data_str[64]; - strftime(time_data_str,64,"%D %T", localtime(&sms_time)); - printf("Date/Time:%s\n",time_data_str); - - if (total_parts > 0) { - printf("Reference number: %d\n", ref_number); - printf("SMS segment %d of %d\n", part_number, total_parts); - } - - switch((tp_dcs_type / 4) % 4) - { - case 0: - { - // GSM7 bit - int i = skip_bytes; - if(skip_bytes > 0) i = (skip_bytes*8+6)/7; - for(;i -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include "pdu.h" - - -#define MAX_PORTS 4 -/*this array hold information about each port we have opened */ -struct PortInfo { - char name[16]; - int port_fd; -}; -int serial_init(int port, int spd, int databits, int parity, \ - int stopbits, int RTSCTS, int need_line_input); -int serial_write(int fd, void *src, int len); -int serial_read(int fd, char *buf, int len); -int serial_recv(int fd,char *rbuf,int rbuf_len, int timeout); -//串口常用初始化接口 -#define serial_com_init(port, spd, databits, parity, stopbits)\ - serial_init(port, spd, databits, parity, stopbits, 0, 0) -//串口默认初始化接口 -#define serial_def_init(port, spd) serial_init(port, spd, 8, 'n', 1, 0, 1) -#endif - - - -/* -** File: uart.c -** -** Description: -** Provides an RS-232 interface that is very similar to the CVI provided -** interface library -*/ -/*this array hold information about each port we have opened */ -struct PortInfo ports[13] = -{ - {"/dev/ttyUSB0", 0}, - {"/dev/ttyUSB1", 0}, - {"/dev/ttyUSB2", 0}, - {"/dev/ttyUSB3", 0}, - {"/dev/ttyUSB4", 0}, - {"/dev/ttyUSB5", 0}, - {"/dev/ttyUSB6", 0}, - {"/dev/ttyUSB7", 0}, - {"/dev/ttyUSB8", 0}, - {"/dev/ttyUSB9", 0}, - {"/dev/ttyUSB10", 0}, - {"/dev/ttyUSB11", 0}, - {"/dev/ttyUSB12", 0}, -}; -FILE* pf; -FILE* pfi; -int spd_arr[] = {B2000000, B1500000, B576000, B500000, B460800, B230400, B115200, B57600, B38400, B19200, B9600, B4800, B2400}; -int name_arr[] = { 2000000, 1500000, 576000, 500000, 460800, 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400 }; -/** -*@brief 设置串口通信速率 -*@param fd 类型 int 打开串口的文件句柄 -*@param speed 类型 int 串口速度 -*@return void -*/ -int set_speed(int fd, int speed) -{ - int i; - int status; - struct termios Opt; - tcgetattr(fd, &Opt); - for ( i= 0; i < sizeof(spd_arr) / sizeof(int); i++) { - if(speed == name_arr[i]) { - tcflush(fd, TCIOFLUSH); - cfsetispeed(&Opt, spd_arr[i]); - cfsetospeed(&Opt, spd_arr[i]); - status = tcsetattr(fd, TCSANOW, &Opt); - if (status != 0) { - printf("tcsetattr failed"); - return 1; - } - tcflush(fd,TCIOFLUSH); - } - } - // printf("set_speed\n"); - return 0; -} - -/** -*@brief 设置串口数据位,停止位和效验位 -*@param fd 类型 int 打开的串口文件句柄 -*@param databits 类型 int 数据位 取值为 7 或者8 -*@param stopbits 类型 int 停止位 取值为 1 或者2 -*@param parity 类型 int 效验类型 取值为N,E,O,,S -*/ -int set_Parity(int fd, int databits, int parity, int stopbits, int RTSCTS) -{ - struct termios options; - if ( tcgetattr( fd,&options) != 0) { - perror("SetupSerial 1"); - return -1; - } - options.c_cflag &= ~CSIZE; - switch (databits) /*设置数据位数*/ - { - case 7: - options.c_cflag |= CS7; - break; - case 8: - options.c_cflag |= CS8; - break; - default: - fprintf(stderr,"Unsupported data size\n"); - return -1; - } - - options.c_iflag |= INPCK; - cfmakeraw(&options); - //options.c_lflag |= (ICANON | ECHO | ECHOE); - //options.c_lflag &= ~(ICANON | ECHO | ECHOE); - //options.c_iflag &= ~(IXON | IXOFF); - switch (parity) - { - case 'n': - case 'N': - options.c_cflag &= ~PARENB; /* Clear parity enable */ - options.c_iflag &= ~INPCK; /* Enable parity checking */ - break; - case 'o': - case 'O': - options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ - break; - case 'e': - case 'E': - options.c_cflag |= PARENB; /* Enable parity */ - options.c_cflag &= ~PARODD; /* 转换为偶效验*/ - break; - case 'S': - case 's': /*as no parity*/ - options.c_cflag &= ~PARENB; - options.c_cflag &= ~CSTOPB; - break; - default: - fprintf(stderr,"Unsupported parity\n"); - return -1; - } - - /* 设置停止位*/ - switch (stopbits) - { - case 1: - options.c_cflag &= ~CSTOPB; - break; - case 2: - options.c_cflag |= CSTOPB; - break; - default: - fprintf(stderr,"Unsupported stop bits\n"); - return -1; - } - - /* Set rts/cts */ - if (RTSCTS) - { - printf("Set rts/cts"); - options.c_cflag |= CRTSCTS; - } - - tcflush(fd,TCIFLUSH); - options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/ - options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ - if (tcsetattr(fd,TCSANOW,&options) != 0) - { - printf("SetupSerial failed"); - return -1; - } - // printf("set_Parity\n"); - return 0; -} - -//接收消息结尾加换行符 -int serial_set_line_input(int fd) -{ - struct termios options; - if ( tcgetattr( fd,&options) != 0) { - perror("SetupSerial 1"); - return -1; - } - - options.c_lflag |= ICANON; - - tcflush(fd,TCIFLUSH); - options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/ - options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ - if (tcsetattr(fd,TCSANOW,&options) != 0) - { - perror("SetupSerial 3"); - return -1; - } - return 0; -} - -/** -*@brief -*@param port 串口端口号 -*@param spd 串口速度 -*@param databits,parity,stopbits,RTSCTS,分别为数据位,校验位,停止位,rtscts位 -*@param need_line_input接收数据结尾是否加换行符? -*/ -int serial_init(int port, int spd, int databits, int parity, int stopbits, int RTSCTS, int need_line_input) -{ - int fd; - if(port < 13) - { - // printf("open port:%d\n", port); - } - else { - printf("error: port:%d > MAX_PORTS\n", port); - return -1; - } - // - fd = open(ports[port].name, O_RDWR|O_NOCTTY);//O_NONBLOCK 非阻塞, O_WRONLY 只读写, O_RDONLY 只读, O_RDWR 读写,O_NOCTTY 阻塞 - - if (-1 == fd) { - printf("init %s failed\n", ports[port].name); - return -1; - } - pf = fdopen(port, "w"); - pfi = fdopen(port, "r"); - if (!pf || ! pfi) - fprintf(stderr,"open port failed\n"); - - - - set_speed(fd, spd); - - set_Parity(fd, databits, parity, stopbits, RTSCTS); - - if (need_line_input) { - serial_set_line_input(fd); - } - - ports[port].port_fd = fd; - - return fd; -} - -/** -*@brief -*@param fd 串口端口号文件描述符 -*@param src 需要通过串口发送的数据 -*@param len 需要发送的数据长度 -*@param 成功返回0, 否则返回-1 -*/ -int serial_write(int fd, void *src, int len) -{ - int ret = write(fd, src, len); - if (len != ret) { - perror("oh, write serial failed!"); - return -1; - } - return 0; -} - -/** -*@brief -*@param fd 串口端口号文件描述符 -*@param src 串口接收数据的指针 -*@param len 需要接收的数据长度 -*@param 成功返回0, 否则返回-1 -*/ -int serial_read(int fd, char *buf, int len) -{ - int ret = read(fd, buf, len-1); - if (-1 == ret) { - perror("oh, read serial failed!"); - return -1; - } - buf[ret] = '\0'; - return ret; -} - -int serial_recv(int fd,char *rbuf,int rbuf_len, int timeout) -{ - int retval; - fd_set rset; - struct timeval time_out; - if(!rbuf || rbuf_len <= 0) - { - // printf("serial_recv Invalid parameter.\n"); - return -1; - } - if(timeout) //指定延时等待 - { - time_out.tv_sec = (time_t)(timeout / 1000); - time_out.tv_usec = 0; - FD_ZERO(&rset); - FD_SET(fd,&rset); - - retval = select(fd,&rset,NULL,NULL,&time_out); - if(retval < 0) - { - // printf("%s,Select failed:%s\n",strerror(errno)); - return -2; - } - else if(0 == retval) - { - // printf("Time Out.\n"); - return 0; - } - - } - // usleep(1000); - retval = read(fd, rbuf, rbuf_len); - if( retval <= 0) - { - // printf("Read failed:%s\n",strerror(errno)); - return -3; - } - return retval; - -} - - -static void timeout() -{ - fprintf(stderr,"No response from modem.\n"); - exit(2); -} -/*字符包含判断*/ -static int starts_with(const char* prefix, const char* str) -{ - while(*prefix) - { - if (*prefix++ != *str++) - { - return 0; - } - } - return 1; -} -/*判断是否存在*/ -int FileExist(const char* filename) -{ - if (filename && access(filename, F_OK) == 0) { - return 1; - } - return 0; -} -/*字符转小写*/ -char* str_tolower(const char* str) -{ - size_t len = strlen(str); - char *lower = calloc(len+1, sizeof(char)); - for (size_t i = 0; i < len; ++i) { - lower[i] = tolower((unsigned char)str[i]); - } - /*free(upper);*/ - return lower; -} -/*字符转大写*/ -char* str_toupper(const char* str) -{ - size_t len = strlen(str); - char *upper = calloc(len+1, sizeof(char)); - for (size_t i = 0; i < len; ++i) { - upper[i] = toupper((unsigned char)str[i]); - } - /*free(upper);*/ - return upper; -} -/*char*转char[]*/ -char strx_tostrarr(const char* str) -{ - return 0; -} - - -int main(int argc, char **argv) -{ - if(argc<3) - { - printf("ERROR demo: sendat 2 'ATI'\n"); - exit(1); - return 0; - } - int debug = 1; - int port= 0; - sscanf(argv[1], "%d", &port); - if(FileExist(ports[port].name)==0) - { - printf("AT ERROR absent.\n"); - return 0; - } - char *message= argv[2]; - char *nty= "\r\n"; - char buff[1024]; - signal(SIGALRM,timeout); - alarm(2); - /*信号超时3秒自动退出*/ - int fd = serial_def_init(port, 1500000); - if(fd < 0) return 0; - char *send= strcat(message,nty); - serial_write(fd,send, strlen(send)); - while(1) { - int read = serial_read(fd, buff, sizeof(buff)); - if(starts_with("OK", buff)) { - if (debug == 1) - printf("%s", buff); - close(fd);//关闭串口 - exit(0); - } - if(starts_with("ERROR", buff)) { - if (debug == 1) - printf("%s", buff); - close(fd);//关闭串口 - exit(1); - } - if(starts_with("COMMAND NOT SUPPORT", buff)) { - if (debug == 1) - printf("%s", buff); - close(fd);//关闭串口 - exit(1); - } - if(starts_with("+CME ERROR", buff)) { - if (debug == 1) - printf("%s", buff); - close(fd);//关闭串口 - exit(1); - } - printf("%s", buff); - } - - exit(1); - return 0; -} diff --git a/sendat/src/ucs2_to_utf8.c b/sendat/src/ucs2_to_utf8.c deleted file mode 100644 index 5baa433..0000000 --- a/sendat/src/ucs2_to_utf8.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 2014 lovewilliam - * from http://www.lemoda.net/c/ucs2-to-utf8/ucs2-to-utf8.c - */ -/* Input: a Unicode code point, "ucs2". - - Output: UTF-8 characters in buffer "utf8". - - Return value: the number of bytes written into "utf8", or -1 if - there was an error. - - This adds a zero byte to the end of the string. It assumes that the - buffer "utf8" has at least four bytes of space to write to. */ - -#define UNICODE_SURROGATE_PAIR -2 -#define UNICODE_BAD_INPUT -1 - -int ucs2_to_utf8 (int ucs2, unsigned char * utf8) -{ - if (ucs2 < 0x80) { - utf8[0] = ucs2; - utf8[1] = '\0'; - return 1; - } - if (ucs2 >= 0x80 && ucs2 < 0x800) { - utf8[0] = (ucs2 >> 6) | 0xC0; - utf8[1] = (ucs2 & 0x3F) | 0x80; - utf8[2] = '\0'; - return 2; - } - if (ucs2 >= 0x800 && ucs2 < 0xFFFF) { - if (ucs2 >= 0xD800 && ucs2 <= 0xDFFF) { - /* Ill-formed. */ - return UNICODE_SURROGATE_PAIR; - } - utf8[0] = ((ucs2 >> 12) ) | 0xE0; - utf8[1] = ((ucs2 >> 6 ) & 0x3F) | 0x80; - utf8[2] = ((ucs2 ) & 0x3F) | 0x80; - utf8[3] = '\0'; - return 3; - } - if (ucs2 >= 0x10000 && ucs2 < 0x10FFFF) { - /* http://tidy.sourceforge.net/cgi-bin/lxr/source/src/utf8.c#L380 */ - utf8[0] = 0xF0 | (ucs2 >> 18); - utf8[1] = 0x80 | ((ucs2 >> 12) & 0x3F); - utf8[2] = 0x80 | ((ucs2 >> 6) & 0x3F); - utf8[3] = 0x80 | ((ucs2 & 0x3F)); - utf8[4] = '\0'; - return 4; - } - return UNICODE_BAD_INPUT; -} -