Compare commits

...
111 Commits
Author SHA1 Message Date
Sergio R. Caprile ccfe7e0724 update version 2025-05-21 09:46:14 -03:00
Sergio R. Caprile 8061a41b38 workaround 2025-05-19 09:22:59 -03:00
Sergio R. Caprile 39392b3690 Merge pull request #3139 from cesanta/freewill
free ifp on mgr_free
2025-05-15 18:04:42 -03:00
Sergio R. Caprile 54d4611eb6 call mg_tcpip_free from mg_mgr_free() 2025-05-15 17:37:40 -03:00
Sergio R. Caprile 34cdce750d Merge pull request #3138 from cesanta/pedantic
make clang happy
2025-05-15 17:11:22 -03:00
Sergio R. Caprile f3fafb6759 make clang happy 2025-05-15 17:09:29 -03:00
Sergio R. Caprile 0372c97ff5 add fuzz 2025-05-15 16:48:16 -03:00
Sergio R. Caprile b46136a0af Merge pull request #3137 from cesanta/testtls
add fuzz tests
2025-05-15 16:33:17 -03:00
Sergio R. Caprile ac3d41fb79 add fuzz tests 2025-05-15 16:32:42 -03:00
Sergio R. Caprile 14be42c868 INFO -> VERBOSE 2025-05-15 15:50:36 -03:00
robertc2000 f0ec14543a Merge pull request #3136 from cesanta/ra6-driver-init
RA6 driver init macro
2025-05-15 10:20:31 +03:00
robert f46c5b7214 RA6 driver init macro 2025-05-15 03:13:49 -04:00
Sergey Lyubka ccd6bcd95f Merge pull request #3132 from cesanta/tls
stronger bounds checking
2025-05-13 22:26:35 +01:00
Sergey Lyubka a3b63f3b0d Merge pull request #3130 from cesanta/longpost
fix broken TCP closure
2025-05-13 22:26:15 +01:00
Sergey Lyubka f2905a5e10 Merge pull request #3135 from cesanta/mss
Handle (specific) TCP options
2025-05-13 22:25:52 +01:00
Sergio R. Caprile 1ef6c6aeb5 Handle TCP options 2025-05-13 16:27:50 -03:00
robertc2000 bd53529b45 Merge pull request #3134 from cesanta/ota-rw612
OTA for FRDM-RW612
2025-05-13 10:33:41 +03:00
Sergio R. Caprile cc8ecc5a42 stronger bounds checking 2025-05-12 18:13:41 -03:00
robert 5a816a1d41 OTA for FRDM-RW612 2025-05-12 07:59:15 -04:00
robertc2000 9922286c67 Merge pull request #3131 from cesanta/ws-offset
Websocket offset validation enhancement
2025-05-09 13:05:20 +03:00
robert cdc439bc38 Websocket offset validation enhancement 2025-05-09 06:04:34 -04:00
Sergio R. Caprile ae8422e304 fix broken TCP closure 2025-05-08 13:40:02 -03:00
robert 539d080346 check null pointer 2025-05-07 08:40:07 -04:00
Sergey Lyubka 041ec6e1f8 Close if drained 2025-05-03 10:28:40 +01:00
Sergio R. Caprile f618fe125c Fix lwIP builds
fixes #3119

lwIP does not export ip_mreq by default, it requires enabling support for IGMP by setting LWIP_IGMP, with the associated extra stuff. Mongoose will print an error if mg_multicast_add() is called with no multicast support in lwIP.
2025-04-29 19:24:17 -03:00
Sergio R. Caprile 8ab514fabc make hexdump send CRLF 2025-04-28 12:33:31 -03:00
novlean 08ad2c3145 Merge pull request #3113 from cesanta/novlean-patch-2
Update README.md
2025-04-24 17:40:00 +01:00
novlean c64fd404d4 Update README.md
article
2025-04-24 17:39:51 +01:00
Sergio R. Caprile 143b0ac126 fix 2025-04-24 11:04:43 -03:00
Sergio R. Caprile c2e2432010 Merge pull request #3093 from cesanta/mdns-multicast
Added MDNS and driver support for multicast
2025-04-22 14:01:34 -03:00
Sergio R. Caprile 1d2a768184 refactor the rest of the drivers 2025-04-22 13:59:03 -03:00
novlean fb099641bc Merge pull request #3111 from cesanta/novlean-patch-2
Update README.md
2025-04-22 17:48:28 +01:00
novlean 6da9afbf29 Update README.md 2025-04-22 17:48:12 +01:00
Sergio R. Caprile dceb4beb09 Refactor MIP strategy and first driver (CMSIS) 2025-04-22 12:55:21 -03:00
robert 6f697db49d Added MDNS and driver support for multicast 2025-04-22 12:55:15 -03:00
Sergio R. Caprile b44193780e Merge pull request #3110 from cesanta/tlsfindata
Fix not reading last TLS small record with fast closure
2025-04-22 10:03:40 -03:00
Sergio R. Caprile 8e0212c3db Fix not reading last TLS small record with fast closure
Fixes #3104
MbedTLS API fairplay
2025-04-22 09:56:49 -03:00
Sergio R. Caprile 3861e2e1e7 Merge pull request #3097 from cesanta/builtdoze
fix missing weird types
2025-04-14 13:13:06 -03:00
Sergio R. Caprile 21eefa4b55 Merge pull request #3102 from cesanta/mipfin
Fix handling of FIN segments carrying data
2025-04-14 11:27:09 -03:00
Sergey Lyubka fb6c6aafeb Merge pull request #3100 from cesanta/timers
Fix #2768 - remove completed timers
2025-04-14 15:15:36 +01:00
Sergio R. Caprile df07426e78 Fix handling of FIN segments carrying data 2025-04-14 11:11:48 -03:00
Sergio R. Caprile 5cf1523a13 Merge pull request #3101 from cesanta/tlszero
workaround causing TLS libs to return zero
2025-04-14 10:40:36 -03:00
Sergio R. Caprile f2fe47e9f7 workaround causing TLS libs to return zero 2025-04-11 14:42:15 -03:00
Sergio R. Caprile 2557ab2e60 Merge pull request #3086 from cesanta/cywst
Add support for RM2 with STM32F (429, 746)
2025-04-11 09:28:25 -03:00
Sergio R. Caprile fbc1708000 Add support for RM2 with STM32F (429, 746) 2025-04-11 09:20:40 -03:00
Sergey Lyubka 0539cf1023 Fix #2768 - remove completed timers 2025-04-11 11:24:10 +01:00
Sergio R. Caprile 07b410447b fix missing weird types 2025-04-10 10:02:20 -03:00
Sergey Lyubka fb69016196 Merge pull request #3096 from cesanta/polldoze
allow other stack than WinSock in Windows
2025-04-10 07:21:29 +01:00
Sergio R. Caprile 169cbc044f Merge pull request #3095 from cesanta/noVLA
no VLA
2025-04-09 13:28:21 -03:00
Sergio R. Caprile 08091d02e5 allow other stack than WinSock in Windows 2025-04-09 12:05:01 -03:00
Sergio R. Caprile 6f2dcf92a7 no VLA 2025-04-09 10:55:54 -03:00
Sergio R. Caprile 578e52618d Merge pull request #3092 from cesanta/picofix
unbreak pico[2]W auto init
2025-04-07 16:00:33 -03:00
Sergio R. Caprile ec0fe66a17 unbreak pico[2]W auto init 2025-04-07 15:56:11 -03:00
novlean 8fee24291a Merge pull request #3091 from cesanta/novlean-patch-2
Update README.md
2025-04-07 17:53:34 +01:00
novlean 05bba2958d Update README.md
Articles
2025-04-07 17:53:22 +01:00
robert e656b1c792 Removed alloca call for ARM-CGT compatibility 2025-04-07 09:08:22 -04:00
Sergey Lyubka e0ccbadd25 Merge pull request #3083 from cesanta/cyw
Introducing CYW driver and Wi-Fi AP support
2025-03-30 11:27:56 +01:00
Sergey Lyubka 40a2a8822f Squash warning 2025-03-29 18:59:01 +00:00
Sergio R. Caprile e2ee356a87 Merge pull request #3084 from cesanta/2ap
Add support for AP in Pico 2 W (valid for Pico W)
2025-03-28 09:51:15 -03:00
Sergio R. Caprile 189bef61d3 Add support for AP in Pico 2 W (valid for Pico W) 2025-03-24 17:49:40 -03:00
Sergio R. Caprile 7d94f9f61b Add Pico + RM2 Wi-Fi example 2025-03-24 17:41:12 -03:00
Sergio R. Caprile e37a0b9056 Add CYW driver 2025-03-24 17:03:05 -03:00
Sergio R. Caprile 0b57b23951 Add support for Wi-Fi chip drivers 2025-03-24 17:02:50 -03:00
Sergey Lyubka c84826e84e Merge pull request #3081 from cesanta/dhcp
Allow user to set custom DHCP name
2025-03-24 08:01:43 +00:00
Sergey Lyubka 064fc6ff7b Allow user to set custom DHCP name 2025-03-22 16:30:02 +00:00
Sergio R. Caprile 042ea53478 Merge pull request #3076 from cesanta/mondirw
keep up with Wizard dir structure
2025-03-12 17:14:30 -03:00
Sergio R. Caprile 900b0acf7a keep up with Wizard dir structure 2025-03-12 17:08:36 -03:00
Sergio R. Caprile dc5f2e295a Merge pull request #3074 from cesanta/wait
fix IO_WAIT on send for builtin TLS and MbedTLS
2025-03-11 16:21:32 -03:00
Sergio R. Caprile c1849c2b19 fix IO_WAIT on send for builtin TLS and MbedTLS 2025-03-11 16:14:12 -03:00
Sergio R. Caprile 4eadf3699f unbreak C89 2025-03-11 16:00:42 -03:00
Sergio R. Caprile b30cf6587c Merge pull request #3072 from cesanta/rw612-wifi-xpresso
RW612 MCUXpresso WiFi example with FreeRTOS and LWIP
2025-03-08 14:56:29 -03:00
Sergio R. Caprile fbc231f33e Merge pull request #3070 from cesanta/hton
remove memcpy from htons/l and test load/save bigendian macros
2025-03-08 14:46:46 -03:00
Sergio R. Caprile bc8c839342 Merge pull request #3033 from cesanta/wifi
Change driver API: up(ifp) -> poll(ifp, 1second)
2025-03-08 11:40:39 -03:00
Sergio R. Caprile 90a23fe230 Add support for Wi-Fi chip drivers 2025-03-07 16:41:33 -03:00
Sergio R. Caprile 065027843e Change driver API: up(ifp) -> poll(ifp, 1second)
Add misc extras required by Wi-Fi drivers (in progress)
2025-03-07 14:14:16 -03:00
Sergio R. Caprile 8906b1ac0f Merge pull request #3025 from cesanta/ub
fix UB and possible exception trigger
2025-03-07 13:49:37 -03:00
robert 05f9e61a41 RW612 MCUXpresso WiFi example with FreeRTOS and LWIP 2025-03-07 11:12:30 -05:00
Sergio R. Caprile 782896b5d3 remove memcpy from htons/l 2025-03-05 17:20:35 -03:00
Sergio R. Caprile 4258f62560 Merge pull request #3069 from cesanta/beduino
add test for ESP32
2025-03-05 14:23:05 -03:00
Sergio R. Caprile 537ba64a54 add test for ESP32 2025-03-05 12:34:22 -03:00
Sergey Lyubka 25d20b7354 Add mg_tcpip_driver_w5100 to the header 2025-03-05 06:54:20 +00:00
Sergio R. Caprile 04d8362905 Merge pull request #3068 from cesanta/arduino
fix Arduino tests
2025-03-04 16:31:57 -03:00
Sergio R. Caprile 21266e9a45 fix Arduino tests 2025-03-04 16:20:18 -03:00
Sergio R. Caprile 7304e2171d Merge pull request #3065 from cesanta/reduino
Rename conflictive macros, add and refactor crypto tests
2025-03-04 12:11:45 -03:00
Sergio R. Caprile 61fc480850 Rename conflictive macros, refactor crypto tests 2025-03-04 11:55:57 -03:00
robertc2000 562e82f5ac Merge pull request #3059 from cesanta/ota-rt1050
OTA on RT1050
2025-03-03 10:09:27 +02:00
robert d7ff85bb48 OTA on RT1050 2025-03-03 03:03:28 -05:00
Sergio R. Caprile 55bc6105e1 Merge pull request #3058 from cesanta/move
move examples -> tutorials
2025-02-28 14:00:06 -03:00
Sergio R. Caprile 306c0b6096 move examples -> tutorials 2025-02-28 13:55:57 -03:00
Sergio R. Caprile 024078ae33 Merge pull request #3057 from cesanta/move
move vendors -> tutorials
2025-02-28 10:10:07 -03:00
Sergio R. Caprile b5a9ba8390 move vendors -> tutorials 2025-02-28 10:01:51 -03:00
Sergey Lyubka 93f36927ca Add .mjs mime type 2025-02-27 16:50:04 +00:00
Sergio R. Caprile 1db90cafd1 Merge pull request #3056 from cesanta/move
move Zephyr -> tutorials
2025-02-27 12:02:48 -03:00
Sergio R. Caprile bf23a0def7 move Zephyr -> tutorials 2025-02-27 10:57:08 -03:00
Sergio R. Caprile ea1cbeea9d Merge pull request #3054 from cesanta/move
move UART bridge -> tutorials
2025-02-26 15:11:27 -03:00
Sergio R. Caprile aeda7e5520 move UART bridge -> tutorials 2025-02-26 15:08:06 -03:00
Sergio R. Caprile a7899af8b8 Merge pull request #3053 from cesanta/move
move ESP32 device dashboard -> tutorials
2025-02-26 14:17:06 -03:00
Sergio R. Caprile b0385f47af move ESP32 device dashboard -> tutorials 2025-02-26 14:14:08 -03:00
Sergio R. Caprile 86c384657c Merge pull request #3052 from cesanta/move
integrate reference-projects into existing tutorials
2025-02-26 12:05:14 -03:00
Sergio R. Caprile 6e569110d2 integrate reference-projects intto existing tutorials 2025-02-26 12:00:46 -03:00
Sergio R. Caprile 3b1024b13c Merge pull request #3051 from cesanta/move
move MicroPython and dashboards -> tutorials
2025-02-26 11:43:14 -03:00
Sergio R. Caprile b3f5d11275 move MicroPython and dashboards -> tutorials 2025-02-26 11:31:01 -03:00
Sergio R. Caprile 1078ba0a92 Merge pull request #3050 from cesanta/move
move file-transfer -> tutorials
2025-02-25 16:54:25 -03:00
Sergio R. Caprile 005c8170d4 move file-transfer -> tutorials 2025-02-25 16:52:16 -03:00
Sergio R. Caprile b8d1d7a10b Merge pull request #3049 from cesanta/move
move ESP8266 -> tutorials
2025-02-25 16:11:30 -03:00
Sergio R. Caprile 76769fb4d5 move ESP8266 -> tutorials 2025-02-25 16:10:28 -03:00
Sergio R. Caprile 6ff6f0a4c6 Merge pull request #3048 from cesanta/move
move Arduino examples -> tutorials
2025-02-25 15:52:12 -03:00
Sergio R. Caprile 72a45d2f6a move Arduino examples -> tutorials 2025-02-25 15:48:09 -03:00
Sergio R. Caprile 2fe7c8a410 Merge pull request #3044 from cesanta/eth-drivers-rx
ETH driver: use the same scheme for RX
2025-02-19 14:12:49 -03:00
robert 5269eb9c39 ETH driver: use the same scheme for RX 2025-02-19 10:01:54 -05:00
Sergio R. Caprile a0d9b6a7e0 fix UB and possible HF trigger 2025-01-28 10:24:59 -03:00
2789 changed files with 487341 additions and 5756 deletions

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
name: Fuzz
on:
schedule:
- cron: '0 21 * * *' # run at 9 PM UTC
# Allow manual runs
workflow_dispatch:
env:
CC: clang
jobs:
fuzz:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target: [fuzz, fuzz_tls]
name: ${{ matrix.target }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: make -C test ${{ matrix.target }}
+65 -151
View File
@@ -165,97 +165,12 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: make -C test riscv SSL=${{ matrix.ssl }} - run: make -C test riscv SSL=${{ matrix.ssl }}
examples:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
name: examples ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
- run: sudo apt -y install libpcap-dev
- run: make -C test examples CFLAGS_EXTRA="${{ matrix.ssl }}"
- run: make -C test clean_examples
examples_win:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
name: examples_win ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
# - uses: egor-tensin/setup-mingw@v2
# with:
# platform: x64
- name: test they build
run: make -C test examples_win CFLAGS_EXTRA="${{ matrix.ssl }}"
shell: cmd
- name: test they clean
run: make -C test clean_examples_win
shell: cmd
examples_mac:
runs-on: macos-latest
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
strategy:
fail-fast: false
matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
name: examples_mac ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
- run: make -C test examples_mac CFLAGS_EXTRA="${{ matrix.ssl }}"
- run: make -C test clean_examples_mac
refprojs:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
name: reference-projects ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
- run: make -C test refprojs CFLAGS_EXTRA="${{ matrix.ssl }}"
- run: make -C test clean_refprojs
refprojs_win:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
name: reference-projects_win ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
# - uses: egor-tensin/setup-mingw@v2
# with:
# platform: x64
- name: test they build
run: make -C test refprojs_win CFLAGS_EXTRA="${{ matrix.ssl }}"
shell: cmd
- name: test they clean
run: make -C test clean_refprojs_win
shell: cmd
refprojs_mac:
runs-on: macos-latest
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
strategy:
fail-fast: false
matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
name: reference-projects_mac ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
- run: make -C test refprojs CFLAGS_EXTRA="${{ matrix.ssl }}"
- run: make -C test clean_refprojs
tutorials: tutorials:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN] ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
name: tutorials ${{ matrix.ssl }} name: tutorials ${{ matrix.ssl }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -267,7 +182,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN] ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
name: tutorials_win ${{ matrix.ssl }} name: tutorials_win ${{ matrix.ssl }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -286,7 +201,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN] ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
name: tutorials_mac ${{ matrix.ssl }} name: tutorials_mac ${{ matrix.ssl }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -300,11 +215,8 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: echo # nothing specific to install or do - run: echo # nothing specific to install or do
- run: make -C examples/arduino arduino-xiao - run: make -C test/arduino
# TODO(): - run: make -C examples/arduino arduino-esp32 - run: make -C test/arduino cleanall
# TODO(): - run: make -C examples/arduino arduino-teensy41
# - run: make -C examples/arduino arduino-nano
- run: make -C examples/arduino clean
# wizard_examples: # wizard_examples:
@@ -322,7 +234,7 @@ jobs:
# with: { fetch-depth: 2 } # with: { fetch-depth: 2 }
# - run: echo # nothing specific to install or do # - run: echo # nothing specific to install or do
# fi # fi
# - run: make -C examples/${{ matrix.example.path }} build # - run: make -C tutorials/${{ matrix.example.path }} build
wizard_examples_arm: wizard_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -330,7 +242,9 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: infineon/infineon-xmc7200 - path: infineon/xmc47_relax-make-baremetal-builtin
- path: infineon/xmc_plt2go_4400-make-baremetal-builtin
- path: infineon/xmc72_evk-make-baremetal-builtin
- path: nxp/frdm-mcxn947-make-baremetal-builtin - path: nxp/frdm-mcxn947-make-baremetal-builtin
- path: nxp/frdm-mcxn947-make-freertos-builtin - path: nxp/frdm-mcxn947-make-freertos-builtin
- path: nxp/rt1020-evk-make-baremetal-builtin - path: nxp/rt1020-evk-make-baremetal-builtin
@@ -361,7 +275,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi - run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/${{ matrix.example.path }} build - run: make -C tutorials/${{ matrix.example.path }} build
generic_examples: generic_examples:
@@ -370,9 +284,9 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: esp32/uart-bridge - path: micropython/esp32
- path: esp32/micropython - path: http/uart-bridge/esp32
- path: esp8266/http-client-server - path: http/http-client/esp8266/http-client-server
name: ${{ matrix.example.path }} name: ${{ matrix.example.path }}
env: env:
GO: 0 GO: 0
@@ -380,7 +294,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: echo # nothing specific to install or do - run: echo # nothing specific to install or do
- run: make -C examples/${{ matrix.example.path }} build - run: make -C tutorials/${{ matrix.example.path }} build
generic_examples_arm: generic_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -388,8 +302,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: microchip/same54-xpro/mqtt-client - path: mqtt/mqtt-client/microchip/same54-xpro
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
- path: nxp/nxp-mimxrt1020-azurertos - path: nxp/nxp-mimxrt1020-azurertos
- path: nxp/nxp-frdmk66f-freertos - path: nxp/nxp-frdmk66f-freertos
- path: nxp/nxp-lpcxpresso54s018m-freertos - path: nxp/nxp-lpcxpresso54s018m-freertos
@@ -420,7 +333,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi - run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/${{ matrix.example.path }} build - run: make -C tutorials/${{ matrix.example.path }} build
device_dashboard_examples: device_dashboard_examples:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -428,13 +341,14 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: esp32/device-dashboard - path: esp32
name: ${{ matrix.example.path }} name: ${{ matrix.example.path }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: echo # nothing specific to install or do - run: echo # nothing specific to install or do
- run: make -C examples/${{ matrix.example.path }} build - run: make -C tutorials/http/device-dashboard/${{ matrix.example.path }} build
device_dashboard_examples_arm: device_dashboard_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -443,7 +357,7 @@ jobs:
matrix: matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN] ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
example: example:
- path: microchip/same54-xpro/device-dashboard - path: tutorials/http/device-dashboard/microchip/same54-xpro
- path: nxp/rt1020-evk-make-freertos-builtin - path: nxp/rt1020-evk-make-freertos-builtin
- path: nxp/rt1060-evk-make-freertos-builtin - path: nxp/rt1060-evk-make-freertos-builtin
- path: nxp/rt1170-evk-make-freertos-builtin - path: nxp/rt1170-evk-make-freertos-builtin
@@ -458,7 +372,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi - run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/${{ matrix.example.path }} build CFLAGS_EXTRA="${{ matrix.ssl }}" - run: make -C tutorials/${{ matrix.example.path }} build CFLAGS_EXTRA="${{ matrix.ssl }}"
# mqtt_dashboard_examples: # mqtt_dashboard_examples:
# runs-on: ubuntu-latest # runs-on: ubuntu-latest
@@ -472,7 +386,7 @@ jobs:
# - uses: actions/checkout@v4 # - uses: actions/checkout@v4
# with: { fetch-depth: 2 } # with: { fetch-depth: 2 }
# - run: echo # nothing specific to install or do # - run: echo # nothing specific to install or do
# - run: make -C examples/${{ matrix.example.path }} build # - run: make -C tutorials/${{ matrix.example.path }} build
mqtt_dashboard_examples_arm: mqtt_dashboard_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -486,7 +400,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi - run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/${{ matrix.example.path }} build - run: make -C tutorials/${{ matrix.example.path }} build
# dual_examples: # dual_examples:
# runs-on: ubuntu-latest # runs-on: ubuntu-latest
@@ -500,8 +414,8 @@ jobs:
# - uses: actions/checkout@v4 # - uses: actions/checkout@v4
# with: { fetch-depth: 2 } # with: { fetch-depth: 2 }
# - run: echo # nothing specific to install or do # - run: echo # nothing specific to install or do
# - run: make -C examples/${{ matrix.example.path }} device_dashboard # - run: make -C tutorials/${{ matrix.example.path }} device_dashboard
# - run: make -C examples/${{ matrix.example.path }} mqtt_dashboard # - run: make -C tutorials/${{ matrix.example.path }} mqtt_dashboard
cube_examples: cube_examples:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -517,17 +431,17 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi - run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/zephyr init REPO=zephyrprojectrtos/ci:v0.26.14 # "no space left on device" with newers - run: make -C tutorials/zephyr init REPO=zephyrprojectrtos/ci:v0.26.14 # "no space left on device" with newers
- name: minify manifest - name: minify manifest
uses: mikefarah/yq@master uses: mikefarah/yq@master
with: with:
cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' examples/zephyr/zephyrproject/zephyr/west.yml cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' tutorials/zephyr/zephyrproject/zephyr/west.yml
- run: make -C examples/zephyr update - run: make -C tutorials/zephyr update
- run: make -C examples/zephyr/device-dashboard build - run: make -C tutorials/zephyr/device-dashboard build
- run: make -C examples/zephyr/http-client build - run: make -C tutorials/zephyr/http-client build
- run: make -C examples/zephyr/http-server build - run: make -C tutorials/zephyr/http-server build
- run: make -C examples/zephyr/mqtt-aws-client build - run: make -C tutorials/zephyr/mqtt-aws-client build
- run: make -C examples/zephyr/websocket-server build - run: make -C tutorials/zephyr/websocket-server build
test_f7: test_f7:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -536,14 +450,14 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- name: Cube - name: Cube
run: echo # nothing specific to install or do run: echo # nothing specific to install or do
# - run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5 # - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# - run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5 # - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5 - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
test_f4: test_f4:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -552,13 +466,13 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- name: Cube - name: Cube
run: echo # nothing specific to install or do run: echo # nothing specific to install or do
# - run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2 # - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# - run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2 # - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2 - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
test_h743: test_h743:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -567,12 +481,12 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# - name: Cube # - name: Cube
# run: echo # nothing specific to install or do # run: echo # nothing specific to install or do
# - run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6 # - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# - run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6 # - run: make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
test_h723: test_h723:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -581,8 +495,8 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_h5: test_h5:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -591,8 +505,8 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_rt1020: test_rt1020:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -601,8 +515,8 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_rt1060: test_rt1060:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -611,8 +525,8 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_rt1170: test_rt1170:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -621,8 +535,8 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_ra6m4: test_ra6m4:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -631,8 +545,8 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# - run: make -C examples/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} # - run: make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_tm4c: test_tm4c:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -641,8 +555,8 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_same54: test_same54:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -651,8 +565,8 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- run: make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
test_pico_w5500: test_pico_w5500:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -661,5 +575,5 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: SDK - name: SDK
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C examples/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} - run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
+99 -152
View File
@@ -91,60 +91,6 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: make -C test riscv - run: make -C test riscv
examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make -C test examples_essential
- run: make -C test clean_examples_essential
examples_win:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
# - uses: egor-tensin/setup-mingw@v2
# with:
# platform: x64
- name: test they build
run: make -C test examples_win
shell: cmd
- name: test they clean
run: make -C test clean_examples_win
shell: cmd
examples_mac:
runs-on: macos-latest
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
steps:
- uses: actions/checkout@v4
- run: make -C test examples_mac
- run: make -C test clean_examples_mac
refprojs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make -C test refprojs
- run: make -C test clean_refprojs
refprojs_win:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
# - uses: egor-tensin/setup-mingw@v2
# with:
# platform: x64
- name: test they build
run: make -C test refprojs_win
shell: cmd
- name: test they clean
run: make -C test clean_refprojs_win
shell: cmd
refprojs_mac:
runs-on: macos-latest
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
steps:
- uses: actions/checkout@v4
- run: make -C test refprojs
- run: make -C test clean_refprojs
tutorials: tutorials:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -192,7 +138,7 @@ jobs:
# # nothing specific to install or do # # nothing specific to install or do
# fi # fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: make -C examples/${{ matrix.example.path }} build # run: make -C tutorials/${{ matrix.example.path }} build
wizard_examples_arm: wizard_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -200,7 +146,9 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: infineon/infineon-xmc7200 - path: infineon/xmc47_relax-make-baremetal-builtin
- path: infineon/xmc_plt2go_4400-make-baremetal-builtin
- path: infineon/xmc72_evk-make-baremetal-builtin
- path: nxp/frdm-mcxn947-make-baremetal-builtin - path: nxp/frdm-mcxn947-make-baremetal-builtin
- path: nxp/frdm-mcxn947-make-freertos-builtin - path: nxp/frdm-mcxn947-make-freertos-builtin
- path: nxp/rt1020-evk-make-baremetal-builtin - path: nxp/rt1020-evk-make-baremetal-builtin
@@ -236,7 +184,7 @@ jobs:
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build run: make -C tutorials/${{ matrix.example.path }} build
generic_examples: generic_examples:
@@ -245,20 +193,20 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: esp32/uart-bridge - path: http/uart-bridge/esp32
- path: esp8266/http-client-server - path: http/http-client/esp8266/http-client-server
name: ${{ matrix.example.path }} name: ${{ matrix.example.path }}
env: env:
GO: 0 GO: 0
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi - run: if ./test/match_changed_files.sh '^src|^tutorials/http/uart-bridge|^tutorials/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
# nothing specific to install or do # nothing specific to install or do
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build run: make -C tutorials/${{ matrix.example.path }} build
generic_examples_arm: generic_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -266,7 +214,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
- path: stm32/nucleo-g031-make-baremetal-builtin - path: stm32/nucleo-g031-make-baremetal-builtin
name: ${{ matrix.example.path }} name: ${{ matrix.example.path }}
env: env:
@@ -274,11 +221,11 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi - run: if ./test/match_changed_files.sh '^src|^tutorials/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build run: make -C tutorials/${{ matrix.example.path }} build
device_dashboard_examples: device_dashboard_examples:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -286,7 +233,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: esp32/device-dashboard - path: esp32
name: ${{ matrix.example.path }} name: ${{ matrix.example.path }}
env: env:
GO: 0 GO: 0
@@ -294,12 +241,12 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: | - run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
# nothing specific to install or do # nothing specific to install or do
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build run: make -C tutorials/http/device-dashboard/${{ matrix.example.path }} build
device_dashboard_examples_arm: device_dashboard_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -307,7 +254,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
example: example:
- path: microchip/same54-xpro/device-dashboard - path: http/device-dashboard/microchip/same54-xpro
- path: nxp/rt1020-evk-make-freertos-builtin - path: nxp/rt1020-evk-make-freertos-builtin
- path: nxp/rt1060-evk-make-freertos-builtin - path: nxp/rt1060-evk-make-freertos-builtin
- path: nxp/rt1170-evk-make-freertos-builtin - path: nxp/rt1170-evk-make-freertos-builtin
@@ -324,12 +271,12 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: | - run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|^tutorials/${{ matrix.example.path }}'; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build run: make -C tutorials/${{ matrix.example.path }} build
# mqtt_dashboard_examples: # mqtt_dashboard_examples:
# runs-on: ubuntu-latest # runs-on: ubuntu-latest
@@ -345,12 +292,12 @@ jobs:
# - uses: actions/checkout@v4 # - uses: actions/checkout@v4
# with: { fetch-depth: 2 } # with: { fetch-depth: 2 }
# - run: | # - run: |
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then # if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-dashboard/device|^tutorials/${{ matrix.example.path }}'; then
# echo GO=1 >> $GITHUB_ENV # echo GO=1 >> $GITHUB_ENV
# # nothing specific to install or do # # nothing specific to install or do
# fi # fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: make -C examples/${{ matrix.example.path }} build # run: make -C tutorials/${{ matrix.example.path }} build
mqtt_dashboard_examples_arm: mqtt_dashboard_examples_arm:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -366,12 +313,12 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: | - run: |
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-dashboard/device|^tutorials/${{ matrix.example.path }}'; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/${{ matrix.example.path }} build run: make -C tutorials/${{ matrix.example.path }} build
cube_examples: cube_examples:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -381,7 +328,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- run: | - run: |
if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-*-cube-*'; then if ./test/match_changed_files.sh '^src|tutorials/stm32/nucleo-*-cube-*'; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo pip install yq sudo pip install yq
fi fi
@@ -397,7 +344,7 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32|examples/nxp|examples/ti|examples/microchip/same" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f7.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
@@ -405,40 +352,40 @@ jobs:
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true # continue so next test has a chance to re-flash and exit from collisions and flash failures continue-on-error: true # continue so next test has a chance to re-flash and exit from collisions and flash failures
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f746zg-make-baremetal-builtin'; then
make -C examples/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-builtin'; then
make -C examples/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-make-freertos-tcp'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-tcp'; then
make -C examples/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- name: Cube - name: Cube
run: | run: |
echo GO=0 >> $GITHUB_ENV echo GO=0 >> $GITHUB_ENV
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f7.*-cube-'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f7.*-cube-'; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
# nothing specific to install or do # nothing specific to install or do
fi fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-baremetal-builtin'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5 # make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# fi # fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-freertos-builtin'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-builtin'; then
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5 # make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# fi # fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-freertos-lwip'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-lwip'; then
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5 make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
fi fi
@@ -451,42 +398,42 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f4.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f4.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f429zi-make-baremetal-builtin'; then
make -C examples/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-make-freertos-builtin'; then
make -C examples/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- name: Cube - name: Cube
run: | run: |
echo GO=0 >> $GITHUB_ENV echo GO=0 >> $GITHUB_ENV
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f4.*-cube-'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f4.*-cube-'; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
# nothing specific to install or do # nothing specific to install or do
fi fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-baremetal-builtin'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2 # make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# fi # fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-freertos-builtin'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-builtin'; then
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2 # make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# fi # fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-freertos-lwip'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-lwip'; then
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2 make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
fi fi
test_h743: test_h743:
@@ -498,37 +445,37 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h74.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h74.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h743zi-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h743zi-make-baremetal-builtin'; then
make -C examples/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-make-freertos-builtin'; then
make -C examples/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
# - name: Cube # - name: Cube
# run: | # run: |
# echo GO=0 >> $GITHUB_ENV # echo GO=0 >> $GITHUB_ENV
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-h74.*-cube-'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h74.*-cube-'; then
# echo GO=1 >> $GITHUB_ENV # echo GO=1 >> $GITHUB_ENV
# # nothing specific to install or do # # nothing specific to install or do
# fi # fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-cube-baremetal-builtin'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6 # make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# fi # fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-cube-freertos-builtin'; then # if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-freertos-builtin'; then
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6 # make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# fi # fi
test_h723: test_h723:
@@ -540,20 +487,20 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h72.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h72.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h723zg-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h723zg-make-baremetal-builtin'; then
make -C examples/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h723zg-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h723zg-make-freertos-builtin'; then
make -C examples/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_h5: test_h5:
@@ -565,20 +512,20 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h5.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h5.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h563zi-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h563zi-make-baremetal-builtin'; then
make -C examples/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h563zi-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h563zi-make-freertos-builtin'; then
make -C examples/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_rt1020: test_rt1020:
@@ -590,20 +537,20 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1020.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1020-evk-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020-evk-make-baremetal-builtin'; then
make -C examples/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/nxp/rt1020-evk-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/nxp/rt1020-evk-make-freertos-builtin'; then
make -C examples/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_rt1060: test_rt1060:
@@ -615,20 +562,20 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1060.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1060-evk-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060-evk-make-baremetal-builtin'; then
make -C examples/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/nxp/rt1060-evk-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/nxp/rt1060-evk-make-freertos-builtin'; then
make -C examples/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_rt1170: test_rt1170:
@@ -640,20 +587,20 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1170.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1170-evk-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170-evk-make-baremetal-builtin'; then
make -C examples/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/nxp/rt1170-evk-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/nxp/rt1170-evk-make-freertos-builtin'; then
make -C examples/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_ra6m4: test_ra6m4:
@@ -665,20 +612,20 @@ jobs:
with: { fetch-depth: 3 } with: { fetch-depth: 3 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/renesas/ek-ra6m4.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
continue-on-error: true continue-on-error: true
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/renesas/ek-ra6m4-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4-make-baremetal-builtin'; then
make -C examples/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
# - if: ${{ env.GO == 1 }} # - if: ${{ env.GO == 1 }}
# run: | # run: |
# if ./test/match_changed_files.sh 'examples/renesas/ek-ra6m4-make-freertos-builtin'; then # if ./test/match_changed_files.sh 'tutorials/renesas/ek-ra6m4-make-freertos-builtin'; then
# make -C examples/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} # make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi # fi
test_tm4c: test_tm4c:
@@ -690,19 +637,19 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/ti/ek-tm4c.*-make-" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c.*-make-" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/ti/ek-tm4c1294xl-make-baremetal-builtin'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
make -C examples/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/ti/ek-tm4c1294xl-make-freertos-builtin'; then if ./test/match_changed_files.sh 'tutorials/ti/ek-tm4c1294xl-make-freertos-builtin'; then
make -C examples/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_same54: test_same54:
@@ -714,19 +661,19 @@ jobs:
with: { fetch-depth: 2 } with: { fetch-depth: 2 }
- name: baremetal - name: baremetal
run: | run: |
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/microchip/same54-xpro" ; then if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/mqtt/mqtt-client" ; then
echo GO=1 >> $GITHUB_ENV echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/microchip/same54-xpro/device-dashboard'; then if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: | run: |
if ./test/match_changed_files.sh 'examples/microchip/same54-xpro/mqtt-client'; then if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}} make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi fi
test_pico_w5500: test_pico_w5500:
@@ -743,5 +690,5 @@ jobs:
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi fi
- if: ${{ env.GO == 1 }} - if: ${{ env.GO == 1 }}
run: make -C examples/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}} run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
+8
View File
@@ -171,6 +171,14 @@ We take security seriously:
of which we get notified and in case of any issue, act similar to (3). of which we get notified and in case of any issue, act similar to (3).
## Articles
Technical guides and deep dives into embedded web servers, WebUI integration and embedded networking technologies:
- [Embedded Web Server: A Comprehensive Guide for Modern Connected Devices](https://mongoose.ws/articles/embedded-web-server-a-comprehensive-guide-for-modern-connected-devices/)
- [Building Embedded Web Device Dashboards](https://mongoose.ws/articles/building-embedded-web-device-dashboard/)
- [ESP32 Device Dashboard: A Step-by-Step Guide for Developers](https://mongoose.ws/articles/esp32-device-dashboard/)
## Contributions ## Contributions
Contributions are welcome! Please follow the guidelines below: Contributions are welcome! Please follow the guidelines below:
-24
View File
@@ -1,24 +0,0 @@
# Mongoose Network Library Examples
In order to build and run any of the existing examples, please follow:
https://mongoose.ws/documentation/#how-to-build-and-run-examples
## Contributing
Rules for creating a new example:
- Makefile golden reference for desktop/server example: [http-server](http-server)
- Makefile golden reference for the embedded example:
[stm32/nucleo-f746zg-baremetal](stm32/nucleo-f746zg-baremetal)
- An example must build on Windows, Mac and Ubuntu Linux systems
- Assume that user installed tools according to https://mongoose.ws/tutorials/tools/
- Makefile must not include any other make files
- Use `CFLAGS` for system-specific compilation options
- Use `CFLAGS_MONGOOSE` for mongoose-specific compilation options
- Use `$(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA)` to compile
- If external repository is required, download it on demand using git
shallow clone. See embedded example golden reference
- Keep Makefile as short as possible, but verbose to understand it easily
- Symlink files when required, like `mongoose.c`, `ca.pem`, etc. Make no copies
- Example's README.md should contain only the title and the link to mongoose.ws
tutorial page
-41
View File
@@ -1,41 +0,0 @@
all:
example:
true
arduino: ENV = -v $(CWD):/root
arduino:
curl -sL http://downloads.arduino.cc/arduino-1.8.19-linux64.tar.xz | unxz | tar -xf -
mv arduino-* $@
arduino-xiao-board:
./arduino/arduino --pref "boardsmanager.additional.urls=https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json" --save-prefs
./arduino/arduino --pref "compiler.warning_level=all" --save-prefs
./arduino/arduino --install-boards Seeeduino:samd
arduino-xiao: arduino arduino-xiao-board
cd sim800-mqtt && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 sim800-mqtt.ino
cd w5500-http && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 w5500-http.ino
cd w5500-mqtt && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 w5500-mqtt.ino
arduino-nano: arduino
cd w5500-http && ../arduino/arduino --pref compiler.cpp.extra_flags=-DMG_ENABLE_LOG=0 --verbose --verify --board arduino:avr:nano w5500-http.ino
cd w5500-mqtt && ../arduino/arduino --pref compiler.cpp.extra_flags=-DMG_ENABLE_LOG=0 --verbose --verify --board arduino:avr:nano w5500-mqtt.ino
arduino-esp32: arduino
# cd esp32-http && ../arduino/arduino --verbose --verify --board esp32-http.ino
# esp32-mqtt
arduino-teensy41: arduino
# cd teensy41-http && ../arduino/arduino --verbose --verify --board teensy41-http.ino
clean:
rm -rf arduino
cleanall: clean #otherwise some parts of xiao-board installation will fail as already installed
rm -rf ~/.arduino15 ~/.oracle_jre_usage
-1
View File
@@ -1 +0,0 @@
../../mongoose.c
-1
View File
@@ -1 +0,0 @@
../../mongoose.h
File diff suppressed because it is too large. Load diff
@@ -1 +0,0 @@
/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter var,Helvetica,sans-serif;font-feature-settings:"cv11","ss01";font-variation-settings:"opsz" 32}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.left-0{left:0}.right-auto{right:auto}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.col-span-2{grid-column:span 2/span 2}.m-4{margin:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.mb-1{margin-bottom:.25rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-7{margin-top:1.75rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-0{width:0}.w-11{width:2.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-96{width:24rem}.w-full{width:100%}.min-w-full{min-width:100%}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.grow-0{flex-grow:0}.basis-\[30px\]{flex-basis:30px}.border-separate{border-collapse:initial}.border-spacing-0Line truncated
@@ -1 +0,0 @@
../../../micropython/mongoose/micropython.cmake
@@ -1 +0,0 @@
../../../micropython/mongoose/micropython.mk
@@ -1 +0,0 @@
../../../micropython/mongoose/module.c
-1
View File
@@ -1 +0,0 @@
../../../uart-bridge/net.c
@@ -1 +0,0 @@
../../../uart-bridge/packed_fs.c
-1
View File
@@ -1 +0,0 @@
../../mongoose.c
-1
View File
@@ -1 +0,0 @@
../../mongoose.h
@@ -1,9 +0,0 @@
NAME ?= $(notdir $(CURDIR))
build:
git clone --depth 1 https://github.com/mongoose-examples/$(NAME)
cp ./../../../mongoose.[ch] $(NAME)
make -C $(NAME) build
clean:
rm -rf $(NAME)
@@ -1 +0,0 @@
../../../../mongoose.c
@@ -1 +0,0 @@
../../../../mongoose.h
-1
View File
@@ -1 +0,0 @@
../device-dashboard/certs
-1
View File
@@ -1 +0,0 @@
../../mongoose.c
-1
View File
@@ -1 +0,0 @@
../../mongoose.h
@@ -1 +0,0 @@
../../../../mongoose.c
@@ -1 +0,0 @@
../../../../mongoose.h
@@ -1 +0,0 @@
../../../device-dashboard/net.c
@@ -1 +0,0 @@
../../../device-dashboard/net.h
@@ -1 +0,0 @@
../../../device-dashboard/packed_fs.c
@@ -1 +0,0 @@
../../mqtt-dashboard/device/net.c
@@ -1 +0,0 @@
../../mqtt-dashboard/device/net.h
-1
View File
@@ -1 +0,0 @@
pico-sdk
-1
View File
@@ -1 +0,0 @@
../../mongoose.c
-1
View File
@@ -1 +0,0 @@
../../mongoose.h
@@ -1 +0,0 @@
../../mongoose.c
@@ -1 +0,0 @@
../../mongoose.h
@@ -1,17 +0,0 @@
module.exports = {
content: ['./web_root/*.{html,js}'],
xplugins: [ 'tailwindcss', 'xautoprefixer' ],
corePlugins: {outline: false},
theme: {
extend: {},
fontFamily: {
sans:
[
"Inter var, Helvetica, sans-serif", {
fontFeatureSettings: '"cv11", "ss01"',
fontVariationSettings: '"opsz" 32',
}
]
}
}
}
@@ -1 +0,0 @@
../../device-dashboard/web_root/bundle.js
+2636 -387
View File
File diff suppressed because it is too large. Load diff
+305 -116
View File
@@ -20,7 +20,7 @@
#ifndef MONGOOSE_H #ifndef MONGOOSE_H
#define MONGOOSE_H #define MONGOOSE_H
#define MG_VERSION "7.17" #define MG_VERSION "7.18"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -424,6 +424,18 @@ static inline int mg_mkdir(const char *path, mode_t mode) {
#if MG_ARCH == MG_ARCH_WIN32 #if MG_ARCH == MG_ARCH_WIN32
// Avoid name clashing; (macro expansion producing 'defined' has undefined
// behaviour). See config.h for user options
#ifndef MG_ENABLE_WINSOCK
#if (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP) && \
(!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && \
(!defined(MG_ENABLE_FREERTOS_TCP) || !MG_ENABLE_FREERTOS_TCP)
#define MG_ENABLE_WINSOCK 1
#else
#define MG_ENABLE_WINSOCK 0
#endif
#endif
#ifndef _CRT_RAND_S #ifndef _CRT_RAND_S
#define _CRT_RAND_S #define _CRT_RAND_S
#endif #endif
@@ -469,12 +481,14 @@ typedef enum { false = 0, true = 1 } bool;
#else #else
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#if MG_ENABLE_WINSOCK
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#endif
#include <process.h> #include <process.h>
#include <winerror.h> #include <winerror.h>
#include <winsock2.h> #include <winsock2.h> // fix missing macros and types
// For mg_random() // For mg_random()
#if defined(_MSC_VER) && _MSC_VER < 1700 #if defined(_MSC_VER) && _MSC_VER < 1700
@@ -485,6 +499,20 @@ typedef enum { false = 0, true = 1 } bool;
#pragma comment(lib, "advapi32.lib") #pragma comment(lib, "advapi32.lib")
#endif #endif
#if defined(_MSC_VER) && _MSC_VER <= 1200
#ifndef IPPROTO_IP
#define IPPROTO_IP 0
#endif
#ifndef IP_ADD_MEMBERSHIP
struct ip_mreq {
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
#define IP_ADD_MEMBERSHIP 12
#endif
#endif
// Protect from calls like std::snprintf in app code // Protect from calls like std::snprintf in app code
// See https://github.com/cesanta/mongoose/issues/1047 // See https://github.com/cesanta/mongoose/issues/1047
#ifndef __cplusplus #ifndef __cplusplus
@@ -495,25 +523,30 @@ typedef enum { false = 0, true = 1 } bool;
#endif #endif
#endif #endif
#define MG_INVALID_SOCKET INVALID_SOCKET
#define MG_SOCKET_TYPE SOCKET
typedef unsigned long nfds_t; typedef unsigned long nfds_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#if MG_ENABLE_WINSOCK
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#endif
#ifndef alloca #ifndef alloca
#define alloca(a) _alloca(a) #define alloca(a) _alloca(a)
#endif #endif
#endif #endif
#define poll(a, b, c) WSAPoll((a), (b), (c))
#define closesocket(x) closesocket(x)
typedef int socklen_t;
#define MG_DIRSEP '\\' #define MG_DIRSEP '\\'
#ifndef MG_PATH_MAX #ifndef MG_PATH_MAX
#define MG_PATH_MAX FILENAME_MAX #define MG_PATH_MAX FILENAME_MAX
#endif #endif
#if MG_ENABLE_WINSOCK
#define MG_INVALID_SOCKET INVALID_SOCKET
#define MG_SOCKET_TYPE SOCKET
#define poll(a, b, c) WSAPoll((a), (b), (c))
#define closesocket(x) closesocket(x)
typedef int socklen_t;
#ifndef SO_EXCLUSIVEADDRUSE #ifndef SO_EXCLUSIVEADDRUSE
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR)) #define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
#endif #endif
@@ -528,13 +561,15 @@ typedef int socklen_t;
#define MG_SOCK_RESET(errcode) \ #define MG_SOCK_RESET(errcode) \
(((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET)) (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
#endif // MG_ENABLE_WINSOCK
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX) #define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
#define sleep(x) Sleep((x) * 1000) #define sleep(x) Sleep((x) *1000)
#define mkdir(a, b) _mkdir(a) #define mkdir(a, b) _mkdir(a)
#define timegm(x) _mkgmtime(x) #define timegm(x) _mkgmtime(x)
#ifndef S_ISDIR #ifndef S_ISDIR
#define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
#endif #endif
#ifndef MG_ENABLE_DIRLIST #ifndef MG_ENABLE_DIRLIST
@@ -774,7 +809,8 @@ struct timeval {
#define MG_ENABLE_MD5 1 #define MG_ENABLE_MD5 1
#endif #endif
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP) // Set MG_ENABLE_WINSOCK=0 for Win32 builds with other external IP stack not
// mentioned in arch_win32.h
#ifndef MG_ENABLE_WINSOCK #ifndef MG_ENABLE_WINSOCK
#define MG_ENABLE_WINSOCK 1 #define MG_ENABLE_WINSOCK 1
#endif #endif
@@ -892,8 +928,8 @@ struct timeval {
#define MG_SET_MAC_ADDRESS(mac) #define MG_SET_MAC_ADDRESS(mac)
#endif #endif
#ifndef MG_SET_WIFI_CREDS #ifndef MG_SET_WIFI_CONFIG
#define MG_SET_WIFI_CREDS(ssid, pass) #define MG_SET_WIFI_CONFIG(data)
#endif #endif
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS #ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
@@ -1020,16 +1056,17 @@ void mg_log_set_fn(mg_pfn_t fn, void *param);
struct mg_timer { struct mg_timer {
unsigned long id; // Timer ID uint64_t period_ms; // Timer period in milliseconds
uint64_t period_ms; // Timer period in milliseconds uint64_t expire; // Expiration timestamp in milliseconds
uint64_t expire; // Expiration timestamp in milliseconds unsigned flags; // Possible flags values below
unsigned flags; // Possible flags values below #define MG_TIMER_ONCE 0 // Call function once
#define MG_TIMER_ONCE 0 // Call function once #define MG_TIMER_REPEAT 1 // Call function periodically
#define MG_TIMER_REPEAT 1 // Call function periodically #define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set #define MG_TIMER_CALLED 4 // Timer function was called at least once
void (*fn)(void *); // Function to call #define MG_TIMER_AUTODELETE 8 // free() timer when done
void *arg; // Function argument void (*fn)(void *); // Function to call
struct mg_timer *next; // Linkage void *arg; // Function argument
struct mg_timer *next; // Linkage
}; };
void mg_timer_init(struct mg_timer **head, struct mg_timer *timer, void mg_timer_init(struct mg_timer **head, struct mg_timer *timer,
@@ -1068,7 +1105,7 @@ struct mg_fs {
}; };
extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard extern struct mg_fs mg_fs_packed; // see tutorials/core/embedded-filesystem
extern struct mg_fs mg_fs_fat; // FAT FS extern struct mg_fs mg_fs_fat; // FAT FS
// File descriptor // File descriptor
@@ -1104,18 +1141,14 @@ struct mg_str mg_unpacked(const char *path); // Packed file as mg_str
void mg_bzero(volatile unsigned char *buf, size_t len); void mg_bzero(volatile unsigned char *buf, size_t len);
bool mg_random(void *buf, size_t len); bool mg_random(void *buf, size_t len);
char *mg_random_str(char *buf, size_t len); char *mg_random_str(char *buf, size_t len);
uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net);
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len); uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
uint64_t mg_millis(void); // Return milliseconds since boot uint64_t mg_millis(void); // Return milliseconds since boot
bool mg_path_is_sane(const struct mg_str path); bool mg_path_is_sane(const struct mg_str path);
void mg_delayms(unsigned int ms);
#define mg_htons(x) mg_ntohs(x) #define MG_U32(a, b, c, d) \
#define mg_htonl(x) mg_ntohl(x) (((uint32_t) ((a) &255) << 24) | ((uint32_t) ((b) &255) << 16) | \
((uint32_t) ((c) &255) << 8) | (uint32_t) ((d) &255))
#define MG_U32(a, b, c, d) \
(((uint32_t) ((a) & 255) << 24) | ((uint32_t) ((b) & 255) << 16) | \
((uint32_t) ((c) & 255) << 8) | (uint32_t) ((d) & 255))
#define MG_IPV4(a, b, c, d) mg_htonl(MG_U32(a, b, c, d)) #define MG_IPV4(a, b, c, d) mg_htonl(MG_U32(a, b, c, d))
@@ -1124,9 +1157,15 @@ bool mg_path_is_sane(const struct mg_str path);
#define MG_IPADDR_PARTS(ADDR) \ #define MG_IPADDR_PARTS(ADDR) \
MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3] MG_U8P(ADDR)[0], MG_U8P(ADDR)[1], MG_U8P(ADDR)[2], MG_U8P(ADDR)[3]
#define MG_LOAD_BE16(p) ((uint16_t) ((MG_U8P(p)[0] << 8U) | MG_U8P(p)[1])) #define MG_LOAD_BE16(p) \
#define MG_LOAD_BE24(p) \ ((uint16_t) (((uint16_t) MG_U8P(p)[0] << 8U) | MG_U8P(p)[1]))
((uint32_t) ((MG_U8P(p)[0] << 16U) | (MG_U8P(p)[1] << 8U) | MG_U8P(p)[2])) #define MG_LOAD_BE24(p) \
((uint32_t) (((uint32_t) MG_U8P(p)[0] << 16U) | \
((uint32_t) MG_U8P(p)[1] << 8U) | MG_U8P(p)[2]))
#define MG_LOAD_BE32(p) \
((uint32_t) (((uint32_t) MG_U8P(p)[0] << 24U) | \
((uint32_t) MG_U8P(p)[1] << 16U) | \
((uint32_t) MG_U8P(p)[2] << 8U) | MG_U8P(p)[3]))
#define MG_STORE_BE16(p, n) \ #define MG_STORE_BE16(p, n) \
do { \ do { \
MG_U8P(p)[0] = ((n) >> 8U) & 255; \ MG_U8P(p)[0] = ((n) >> 8U) & 255; \
@@ -1138,6 +1177,18 @@ bool mg_path_is_sane(const struct mg_str path);
MG_U8P(p)[1] = ((n) >> 8U) & 255; \ MG_U8P(p)[1] = ((n) >> 8U) & 255; \
MG_U8P(p)[2] = (n) &255; \ MG_U8P(p)[2] = (n) &255; \
} while (0) } while (0)
#define MG_STORE_BE32(p, n) \
do { \
MG_U8P(p)[0] = ((n) >> 24U) & 255; \
MG_U8P(p)[1] = ((n) >> 16U) & 255; \
MG_U8P(p)[2] = ((n) >> 8U) & 255; \
MG_U8P(p)[3] = (n) &255; \
} while (0)
uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net);
#define mg_htons(x) mg_ntohs(x)
#define mg_htonl(x) mg_ntohl(x)
#define MG_REG(x) ((volatile uint32_t *) (x))[0] #define MG_REG(x) ((volatile uint32_t *) (x))[0]
#define MG_BIT(x) (((uint32_t) 1U) << (x)) #define MG_BIT(x) (((uint32_t) 1U) << (x))
@@ -2195,7 +2246,6 @@ struct mg_mgr {
int dnstimeout; // DNS resolve timeout in milliseconds int dnstimeout; // DNS resolve timeout in milliseconds
bool use_dns6; // Use DNS6 server by default, see #1532 bool use_dns6; // Use DNS6 server by default, see #1532
unsigned long nextid; // Next connection ID unsigned long nextid; // Next connection ID
unsigned long timerid; // Next timer ID
void *userdata; // Arbitrary user data pointer void *userdata; // Arbitrary user data pointer
void *tls_ctx; // TLS context shared by all TLS sessions void *tls_ctx; // TLS context shared by all TLS sessions
uint16_t mqtt_id; // MQTT IDs for pub/sub uint16_t mqtt_id; // MQTT IDs for pub/sub
@@ -2211,40 +2261,41 @@ struct mg_mgr {
}; };
struct mg_connection { struct mg_connection {
struct mg_connection *next; // Linkage in struct mg_mgr :: connections struct mg_connection *next; // Linkage in struct mg_mgr :: connections
struct mg_mgr *mgr; // Our container struct mg_mgr *mgr; // Our container
struct mg_addr loc; // Local address struct mg_addr loc; // Local address
struct mg_addr rem; // Remote address struct mg_addr rem; // Remote address
void *fd; // Connected socket, or LWIP data void *fd; // Connected socket, or LWIP data
unsigned long id; // Auto-incrementing unique connection ID unsigned long id; // Auto-incrementing unique connection ID
struct mg_iobuf recv; // Incoming data struct mg_iobuf recv; // Incoming data
struct mg_iobuf send; // Outgoing data struct mg_iobuf send; // Outgoing data
struct mg_iobuf prof; // Profile data enabled by MG_ENABLE_PROFILE struct mg_iobuf prof; // Profile data enabled by MG_ENABLE_PROFILE
struct mg_iobuf rtls; // TLS only. Incoming encrypted data struct mg_iobuf rtls; // TLS only. Incoming encrypted data
mg_event_handler_t fn; // User-specified event handler function mg_event_handler_t fn; // User-specified event handler function
void *fn_data; // User-specified function parameter void *fn_data; // User-specified function parameter
mg_event_handler_t pfn; // Protocol-specific handler function mg_event_handler_t pfn; // Protocol-specific handler function
void *pfn_data; // Protocol-specific function parameter void *pfn_data; // Protocol-specific function parameter
char data[MG_DATA_SIZE]; // Arbitrary connection data char data[MG_DATA_SIZE]; // Arbitrary connection data
void *tls; // TLS specific data void *tls; // TLS specific data
unsigned is_listening : 1; // Listening connection unsigned is_listening : 1; // Listening connection
unsigned is_client : 1; // Outbound (client) connection unsigned is_client : 1; // Outbound (client) connection
unsigned is_accepted : 1; // Accepted (server) connection unsigned is_accepted : 1; // Accepted (server) connection
unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress
unsigned is_connecting : 1; // Non-blocking connect is in progress unsigned is_connecting : 1; // Non-blocking connect is in progress
unsigned is_tls : 1; // TLS-enabled connection unsigned is_tls : 1; // TLS-enabled connection
unsigned is_tls_hs : 1; // TLS handshake is in progress unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection unsigned is_udp : 1; // UDP connection
unsigned is_websocket : 1; // WebSocket connection unsigned is_websocket : 1; // WebSocket connection
unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator
unsigned is_hexdumping : 1; // Hexdump in/out traffic unsigned is_hexdumping : 1; // Hexdump in/out traffic
unsigned is_draining : 1; // Send remaining data, then close and free unsigned is_draining : 1; // Send remaining data, then close and free
unsigned is_closing : 1; // Close and free the connection immediately unsigned is_closing : 1; // Close and free the connection immediately
unsigned is_full : 1; // Stop reads, until cleared unsigned is_full : 1; // Stop reads, until cleared
unsigned is_resp : 1; // Response is still being generated unsigned is_tls_throttled : 1; // Last TLS write: MG_SOCK_PENDING() was true
unsigned is_readable : 1; // Connection is ready to read unsigned is_resp : 1; // Response is still being generated
unsigned is_writable : 1; // Connection is ready to write unsigned is_readable : 1; // Connection is ready to read
unsigned is_writable : 1; // Connection is ready to write
}; };
void mg_mgr_poll(struct mg_mgr *, int ms); void mg_mgr_poll(struct mg_mgr *, int ms);
@@ -2412,6 +2463,9 @@ struct mg_tls {
#ifdef MBEDTLS_SSL_SESSION_TICKETS #ifdef MBEDTLS_SSL_SESSION_TICKETS
mbedtls_ssl_ticket_context ticket; // Session tickets context mbedtls_ssl_ticket_context ticket; // Session tickets context
#endif #endif
// https://github.com/Mbed-TLS/mbedtls/blob/3b3c652d/include/mbedtls/ssl.h#L5071C18-L5076C29
unsigned char *throttled_buf; // see #3074
size_t throttled_len;
}; };
#endif #endif
@@ -2615,6 +2669,8 @@ void mg_resolve_cancel(struct mg_connection *);
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *); bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs, size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
bool is_question, struct mg_dns_rr *); bool is_question, struct mg_dns_rr *);
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name);
@@ -2687,10 +2743,12 @@ void mg_rpc_list(struct mg_rpc_req *r);
#define MG_OTA_CH32V307 100 // WCH CH32V307 #define MG_OTA_CH32V307 100 // WCH CH32V307
#define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6 #define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6
#define MG_OTA_RT1020 300 // IMXRT1020 #define MG_OTA_RT1020 300 // IMXRT1020
#define MG_OTA_RT1060 301 // IMXRT1060 #define MG_OTA_RT1050 301 // IMXRT1050
#define MG_OTA_RT1064 302 // IMXRT1064 #define MG_OTA_RT1060 302 // IMXRT1060
#define MG_OTA_RT1170 303 // IMXRT1170 #define MG_OTA_RT1064 303 // IMXRT1064
#define MG_OTA_RT1170 304 // IMXRT1170
#define MG_OTA_MCXN 310 // MCXN947 #define MG_OTA_MCXN 310 // MCXN947
#define MG_OTA_FRDM 320 // FRDM-RW612
#define MG_OTA_FLASH 900 // OTA via an internal flash #define MG_OTA_FLASH 900 // OTA via an internal flash
#define MG_OTA_ESP32 910 // ESP32 OTA implementation #define MG_OTA_ESP32 910 // ESP32 OTA implementation
#define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash #define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash
@@ -2737,6 +2795,37 @@ bool mg_ota_flash_end(struct mg_flash *flash);
struct mg_wifi_scan_bss_data {
struct mg_str SSID;
char *BSSID;
int16_t RSSI;
uint8_t security;
#define MG_WIFI_SECURITY_OPEN 0
#define MG_WIFI_SECURITY_WEP MG_BIT(0)
#define MG_WIFI_SECURITY_WPA MG_BIT(1)
#define MG_WIFI_SECURITY_WPA2 MG_BIT(2)
#define MG_WIFI_SECURITY_WPA3 MG_BIT(3)
uint8_t channel;
unsigned band :2;
#define MG_WIFI_BAND_2G 0
#define MG_WIFI_BAND_5G 1
unsigned has_n :1;
};
bool mg_wifi_scan(void);
bool mg_wifi_connect(char *ssid, char *pass);
bool mg_wifi_disconnect(void);
bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel);
bool mg_wifi_ap_stop(void);
#if MG_ENABLE_TCPIP
struct mg_tcpip_if; // Mongoose TCP/IP network interface struct mg_tcpip_if; // Mongoose TCP/IP network interface
@@ -2744,21 +2833,26 @@ struct mg_tcpip_driver {
bool (*init)(struct mg_tcpip_if *); // Init driver bool (*init)(struct mg_tcpip_if *); // Init driver
size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame
size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame
bool (*up)(struct mg_tcpip_if *); // Up/down status bool (*poll)(struct mg_tcpip_if *, bool); // Poll, return Up/down status
}; };
typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev, typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev,
void *ev_data); void *ev_data);
enum { enum {
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state) MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str * MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
MG_TCPIP_EV_USER // Starting ID for user events MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct mg_wifi_scan_bss_data *
MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL
MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and chip specific
MG_TCPIP_EV_DRIVER, // Driver event driver specific
MG_TCPIP_EV_USER // Starting ID for user events
}; };
// Network interface // Network interface
struct mg_tcpip_if { struct mg_tcpip_if {
uint8_t mac[6]; // MAC address. Must be set to a valid MAC uint8_t mac[6]; // MAC address. Must be set to a valid MAC
@@ -2771,11 +2865,13 @@ struct mg_tcpip_if {
bool enable_req_sntp; // DCHP client requests SNTP server bool enable_req_sntp; // DCHP client requests SNTP server
bool enable_crc32_check; // Do a CRC check on RX frames and strip it bool enable_crc32_check; // Do a CRC check on RX frames and strip it
bool enable_mac_check; // Do a MAC check on RX frames bool enable_mac_check; // Do a MAC check on RX frames
bool update_mac_hash_table; // Signal drivers to update MAC controller
struct mg_tcpip_driver *driver; // Low level driver struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data void *driver_data; // Driver-specific data
mg_tcpip_event_handler_t fn; // User-specified event handler function mg_tcpip_event_handler_t fn; // User-specified event handler function
struct mg_mgr *mgr; // Mongoose event manager struct mg_mgr *mgr; // Mongoose event manager
struct mg_queue recv_queue; // Receive queue struct mg_queue recv_queue; // Receive queue
char dhcp_name[12]; // Name reported to DHCP, "mip" if unset
uint16_t mtu; // Interface MTU uint16_t mtu; // Interface MTU
#define MG_TCPIP_MTU_DEFAULT 1500 #define MG_TCPIP_MTU_DEFAULT 1500
@@ -2804,6 +2900,7 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac);
extern struct mg_tcpip_driver mg_tcpip_driver_stm32f; extern struct mg_tcpip_driver mg_tcpip_driver_stm32f;
extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
extern struct mg_tcpip_driver mg_tcpip_driver_w5100;
extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
extern struct mg_tcpip_driver mg_tcpip_driver_tms570; extern struct mg_tcpip_driver mg_tcpip_driver_tms570;
extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
@@ -2816,6 +2913,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_xmc7;
extern struct mg_tcpip_driver mg_tcpip_driver_ppp; extern struct mg_tcpip_driver mg_tcpip_driver_ppp;
extern struct mg_tcpip_driver mg_tcpip_driver_pico_w; extern struct mg_tcpip_driver mg_tcpip_driver_pico_w;
extern struct mg_tcpip_driver mg_tcpip_driver_rw612; extern struct mg_tcpip_driver mg_tcpip_driver_rw612;
extern struct mg_tcpip_driver mg_tcpip_driver_cyw;
// Drivers that require SPI, can use this SPI abstraction // Drivers that require SPI, can use this SPI abstraction
struct mg_tcpip_spi { struct mg_tcpip_spi {
@@ -2825,6 +2923,8 @@ struct mg_tcpip_spi {
uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
}; };
#endif
// Macros to record timestamped events that happens with a connection. // Macros to record timestamped events that happens with a connection.
@@ -2832,7 +2932,7 @@ struct mg_tcpip_spi {
// timestamp in milliseconds since connection init time. // timestamp in milliseconds since connection init time.
// //
// Test (run in two separate terminals): // Test (run in two separate terminals):
// make -C examples/http-server/ CFLAGS_EXTRA=-DMG_ENABLE_PROFILE=1 // make -C tutorials/http/http-server/ CFLAGS_EXTRA=-DMG_ENABLE_PROFILE=1
// curl localhost:8000 // curl localhost:8000
// Output: // Output:
// 1ea1f1e7 2 net.c:150:mg_close_conn 3 profile: // 1ea1f1e7 2 net.c:150:mg_close_conn 3 profile:
@@ -2908,6 +3008,60 @@ struct mg_profitem {
#endif #endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
struct mg_tcpip_spi_ {
void *spi; // Opaque SPI bus descriptor
void (*begin)(void *); // SPI begin: slave select low
void (*end)(void *); // SPI end: slave select high
void (*txn)(void *, uint8_t *, uint8_t *,
size_t len); // SPI transaction: write-read len bytes
};
struct mg_tcpip_driver_cyw_firmware {
const uint8_t *code_addr;
size_t code_len;
const uint8_t *nvram_addr;
size_t nvram_len;
const uint8_t *clm_addr;
size_t clm_len;
};
struct mg_tcpip_driver_cyw_data {
struct mg_tcpip_spi_ *spi;
struct mg_tcpip_driver_cyw_firmware *fw;
char *ssid;
char *pass;
char *apssid;
char *appass;
uint8_t security; // TBD
uint8_t apsecurity; // TBD
uint8_t apchannel;
bool apmode; // start in AP mode; 'false' starts connection to 'ssid' if not NULL
bool hs; // use chip "high-speed" mode; otherwise SPI CPOL0 CPHA0 (DS 4.2.3 Table 6)
};
#if 0
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_cyw_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_pico_w; \
mif_.driver_data = &driver_data_; \
mif_.recv_queue.size = 8192; \
mif_.mac[0] = 2; /* MAC read from OTP at driver init */ \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: cyw, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
#endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
struct mg_tcpip_driver_imxrt_data { struct mg_tcpip_driver_imxrt_data {
@@ -2986,13 +3140,19 @@ bool mg_phy_up(struct mg_phy *, uint8_t addr, bool *full_duplex,
struct mg_tcpip_driver_pico_w_data { struct mg_tcpip_driver_pico_w_data {
char *ssid; char *ssid;
char *pass; char *pass;
char *apssid;
char *appass;
uint8_t security; // TBD
uint8_t apsecurity; // TBD
uint8_t apchannel;
bool apmode; // start in AP mode; 'false' starts connection to 'ssid' if not NULL
}; };
#define MG_TCPIP_DRIVER_INIT(mgr) \ #define MG_TCPIP_DRIVER_INIT(mgr) \
do { \ do { \
static struct mg_tcpip_driver_pico_w_data driver_data_; \ static struct mg_tcpip_driver_pico_w_data driver_data_; \
static struct mg_tcpip_if mif_; \ static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CREDS(&driver_data_.ssid, &driver_data_.pass); \ MG_SET_WIFI_CONFIG(&driver_data_); \
mif_.ip = MG_TCPIP_IP; \ mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \ mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \ mif_.gw = MG_TCPIP_GW; \
@@ -3027,6 +3187,35 @@ struct mg_tcpip_driver_ra_data {
uint8_t phy_addr; // PHY address uint8_t phy_addr; // PHY address
}; };
#ifndef MG_DRIVER_CLK_FREQ
#define MG_DRIVER_CLK_FREQ 100000000UL
#endif
#ifndef MG_DRIVER_IRQ_NO
#define MG_DRIVER_IRQ_NO 0
#endif
#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_ra_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.clock = MG_DRIVER_CLK_FREQ; \
driver_data_.irqno = MG_DRIVER_IRQ_NO; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_ra; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: ra, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif #endif
@@ -3267,41 +3456,6 @@ struct mg_tcpip_driver_tms570_data {
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7
struct mg_tcpip_driver_xmc7_data {
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
uint8_t phy_addr;
};
#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif
#ifndef MG_DRIVER_MDC_CR
#define MG_DRIVER_MDC_CR 3
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_xmc7_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_xmc7; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC
struct mg_tcpip_driver_xmc_data { struct mg_tcpip_driver_xmc_data {
@@ -3348,6 +3502,41 @@ struct mg_tcpip_driver_xmc_data {
#endif #endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7
struct mg_tcpip_driver_xmc7_data {
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
uint8_t phy_addr;
};
#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif
#ifndef MG_DRIVER_MDC_CR
#define MG_DRIVER_MDC_CR 3
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_xmc7_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_xmc7; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
-1
View File
@@ -1 +0,0 @@
See detailed tutorials at https://mongoose.ws/documentation/#reference-projects
@@ -1,31 +0,0 @@
CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include -Icmsis_f7/Include
CFLAGS += -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 $(CFLAGS_EXTRA)
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs nosys.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
SOURCES += cmsis_f7/Source/Templates/gcc/startup_stm32f746xx.s
SOURCES += main.c hal.c mongoose.c packed_fs.c net.c
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
all build example: firmware.bin
firmware.bin: firmware.elf
arm-none-eabi-objcopy -O binary $< $@
arm-none-eabi-size --format=berkeley $<
firmware.elf: cmsis_core cmsis_f7 $(SOURCES) hal.h link.ld Makefile
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
flash: firmware.bin
st-flash --reset write $< 0x8000000
cmsis_core:
git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
cmsis_f7:
git clone --depth 1 -b v1.2.8 https://github.com/STMicroelectronics/cmsis_device_f7 $@
clean:
rm -rf firmware.* cmsis_core cmsis_f7
@@ -1,146 +0,0 @@
// Copyright (c) 2024 Cesanta Software Limited
// All rights reserved
#include "hal.h"
static volatile uint64_t s_ticks; // Milliseconds since boot
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
s_ticks++;
}
void mg_random(void *buf, size_t len) { // Use on-board RNG
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
uint32_t r = rng_read();
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
}
}
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
return s_ticks; // Return number of milliseconds since boot
}
void hal_init(void) {
clock_init(); // Set system clock to SYS_FREQUENCY
SystemCoreClock = SYS_FREQUENCY; // Update SystemCoreClock global var
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
rng_init(); // Initialise random number generator
uart_init(UART_DEBUG, 115200); // Initialise UART
gpio_output(LED1); // Initialise LED1
gpio_output(LED2); // Initialise LED2
gpio_output(LED3); // Initialise LED3
ethernet_init(); // Initialise Ethernet pins
}
#if defined(__ARMCC_VERSION)
// Keil specific - implement IO printf redirection
int fputc(int c, FILE *stream) {
if (stream == stdout || stream == stderr) uart_write_byte(UART_DEBUG, c);
return c;
}
#elif defined(__GNUC__)
// ARM GCC specific. ARM GCC is shipped with Newlib C library.
// Implement newlib syscalls:
// _sbrk() for malloc
// _write() for printf redirection
// the rest are just stubs
#include <sys/stat.h> // For _fstat()
uint32_t SystemCoreClock;
void SystemInit(void) { // Called automatically by startup code
}
int _fstat(int fd, struct stat *st) {
(void) fd, (void) st;
return -1;
}
extern unsigned char _end[]; // End of data section, start of heap. See link.ld
static unsigned char *s_current_heap_end = _end;
size_t hal_ram_used(void) {
return (size_t) (s_current_heap_end - _end);
}
size_t hal_ram_free(void) {
unsigned char endofstack;
return (size_t) (&endofstack - s_current_heap_end);
}
void *_sbrk(int incr) {
unsigned char *prev_heap;
unsigned char *heap_end = (unsigned char *) ((size_t) &heap_end - 256);
prev_heap = s_current_heap_end;
// Check how much space we got from the heap end to the stack end
if (s_current_heap_end + incr > heap_end) return (void *) -1;
s_current_heap_end += incr;
return prev_heap;
}
int _open(const char *path) {
(void) path;
return -1;
}
int _close(int fd) {
(void) fd;
return -1;
}
int _isatty(int fd) {
(void) fd;
return 1;
}
int _lseek(int fd, int ptr, int dir) {
(void) fd, (void) ptr, (void) dir;
return 0;
}
void _exit(int status) {
(void) status;
for (;;) asm volatile("BKPT #0");
}
void _kill(int pid, int sig) {
(void) pid, (void) sig;
}
int _getpid(void) {
return -1;
}
int _write(int fd, char *ptr, int len) {
(void) fd, (void) ptr, (void) len;
if (fd == 1) uart_write_buf(UART_DEBUG, ptr, (size_t) len);
return -1;
}
int _read(int fd, char *ptr, int len) {
(void) fd, (void) ptr, (void) len;
return -1;
}
int _link(const char *a, const char *b) {
(void) a, (void) b;
return -1;
}
int _unlink(const char *a) {
(void) a;
return -1;
}
int _stat(const char *path, struct stat *st) {
(void) path, (void) st;
return -1;
}
int mkdir(const char *path, mode_t mode) {
(void) path, (void) mode;
return -1;
}
void _init(void) {
}
#endif // __GNUC__
Whitespace-only changes.
@@ -1 +0,0 @@
../../../windows-macos-linux/web-ui-dashboard/main.c
@@ -1 +0,0 @@
../../../../mongoose.c
@@ -1 +0,0 @@
../../../../mongoose.h
@@ -1 +0,0 @@
../../../windows-macos-linux/web-ui-dashboard/net.c
@@ -1 +0,0 @@
../../../windows-macos-linux/web-ui-dashboard/net.h
@@ -1 +0,0 @@
../../../windows-macos-linux/web-ui-dashboard/packed_fs.c
@@ -1,49 +0,0 @@
# Environment setup: https://mongoose.ws/documentation/tutorials/tools/
PROG ?= ./example # Program we are building
DELETE = rm -rf # Command to remove files
NPX ?= npx # For generating optimised tailwind CSS
OUT ?= -o $(PROG) # Compiler argument for output file
SOURCES = main.c mongoose.c net.c packed_fs.c
CFLAGS += -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion -Wconversion -Wno-sign-conversion
CFLAGS += -fno-common -ffunction-sections -fdata-sections
CFLAGS += -g3 -Os -I.
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
CFLAGS_MONGOOSE += -DMG_ENABLE_PACKED_FS=1
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
PROG = example.exe # Use .exe suffix for the binary
CC = gcc # Use MinGW gcc compiler
CFLAGS += -lws2_32 # Link against Winsock library
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
endif
# Default target. Build and run program
all: $(PROG)
$(RUN) $(PROG) $(ARGS)
# Build program from sources
$(PROG): $(SOURCES)
$(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(OUT)
# Build using Microsoft Visual C compiler
vc: $(SOURCES) Makefile
cl $(SOURCES) /DMG_ENABLE_PACKED_FS=1 /MD /W3 /nologo /Fedemo.exe
# Bundle JS libraries (preact, preact-router, ...) into a single file
web_root/bundle.js:
curl -s https://npm.reversehttp.com/preact,preact/hooks,htm/preact,preact-router -o $@
# Create optimised CSS. Prerequisite: npm -g i tailwindcss tailwindcss-font-inter
css: web_root/index.html $(wildcard web_root/*.js)
$(NPX) tailwindcss -o web_root/main.css --minify
# Generate packed filesystem for serving Web UI
packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile
node pack.js $(addsuffix ::gzip, $(wildcard web_root/*)) certs/* > $@
# Cleanup. Delete built program and all build artifacts
clean:
$(DELETE) $(PROG) *.o *.obj *.exe *.dSYM mbedtls
@@ -1,13 +0,0 @@
# A complete device dashboard
This example is a demonstration of how Mongoose Library could be integrated
into an embedded device and provide a complete device dashboard with the
following features:
- Authentication: login-protected dashboard
- Multiple logins (with possibly different permissions)
- The Web UI can be fully embedded into the firmware binary, then not
needing a filesystem to serve it; so being resilient to FS problems
- All changes are propagated to all connected clients
See a detailed tutorial at https://mongoose.ws/tutorials/device-dashboard/
@@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X
DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT
BgcqhkjOPQIBBggqhkjOPQMBBwNCAARzSQS5OHd17lUeNI+6kp9WYu0cxuEIi/JT
jphbCmdJD1cUvhmzM9/phvJT9ka10Z9toZhgnBq0o0xfTQ4jC1vwMAoGCCqGSM49
BAMCA0gAMEUCIQCe0T2E0GOiVe9KwvIEPeX1J1J0T7TNacgR0Ya33HV9VgIgNvdn
aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=
-----END CERTIFICATE-----
@@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49
AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf
6YbyU/ZGtdGfbaGYYJwatKNMX00OIwtb8A==
-----END EC PRIVATE KEY-----
@@ -1,21 +0,0 @@
// Copyright (c) 2024 Cesanta Software Limited
// All rights reserved
#pragma once
#define LED1 0
#define LED2 1
#define UART_DEBUG NULL
// No-op HAL API implementation for a device with GPIO and UART
#define hal_init()
#define hal_ram_free() 0
#define hal_ram_used() 0
#define gpio_output(pin)
#define gpio_toggle(pin)
#define gpio_read(pin) 0
#define gpio_write(pin, val)
#define uart_init(uart, baud)
#define uart_read_ready(uart) 0
#define uart_write_byte(uart, ch)
#define uart_write_buf(uart, buf, len)
@@ -1,32 +0,0 @@
// Copyright (c) 2024 Cesanta Software Limited
// All rights reserved
#include "hal.h"
#include "mongoose.h"
#include "net.h"
#define BLINK_PERIOD_MS 1000 // LED blinking period in millis
static void timer_fn(void *arg) {
gpio_toggle(LED1); // Blink LED
(void) arg; // Unused
}
// In RTOS environment, you can run this function in a separate task
static void run_mongoose(void) {
struct mg_mgr mgr; // Mongoose event manager
mg_mgr_init(&mgr); // Initialise event manager
mg_log_set(MG_LL_DEBUG); // Set log level to debug
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, NULL);
net_init(&mgr); // Initialise application defined in net.c
for (;;) { // Infinite event loop
mg_mgr_poll(&mgr, 0); // Process network events
}
}
int main(void) {
hal_init(); // Cross-platform hardware init
run_mongoose(); // Initialise and run network application
return 0;
}
@@ -1,256 +0,0 @@
// Copyright (c) 2023 Cesanta Software Limited
// All rights reserved
#include "hal.h"
#include "net.h"
// Authenticated user.
// A user can be authenticated by:
// - a name:pass pair, passed in a header Authorization: Basic .....
// - an access_token, passed in a header Cookie: access_token=....
// When a user is shown a login screen, she enters a user:pass. If successful,
// a server responds with a http-only access_token cookie set.
struct user {
const char *name, *pass, *access_token;
};
// Settings
struct settings {
bool log_enabled;
int log_level;
long brightness;
char *device_name;
};
static struct settings s_settings = {true, 1, 57, NULL};
static const char *s_json_header =
"Content-Type: application/json\r\n"
"Cache-Control: no-cache\r\n";
int ui_event_next(int no, struct ui_event *e) {
if (no < 0 || no >= MAX_EVENTS_NO) return 0;
srand((unsigned) no);
e->type = (uint8_t) rand() % 4;
e->prio = (uint8_t) rand() % 3;
e->timestamp =
(unsigned long) ((int64_t) mg_now() - 86400 * 1000 /* one day back */ +
no * 300 * 1000 /* 5 mins between alerts */ +
1000 * (rand() % 300) /* randomize event time */) /
1000UL;
mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, "event#%d", no);
return no + 1;
}
static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time
mg_sntp_connect(param, "udp://time.google.com:123", NULL, NULL);
}
// Parse HTTP requests, return authenticated user or NULL
static struct user *authenticate(struct mg_http_message *hm) {
// In production, make passwords strong and tokens randomly generated
// In this example, user list is kept in RAM. In production, it can
// be backed by file, database, or some other method.
static struct user users[] = {
{"admin", "admin", "admin_token"},
{"user1", "user1", "user1_token"},
{"user2", "user2", "user2_token"},
{NULL, NULL, NULL},
};
char user[64], pass[64];
struct user *u, *result = NULL;
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
MG_VERBOSE(("user [%s] pass [%s]", user, pass));
if (user[0] != '\0' && pass[0] != '\0') {
// Both user and password is set, search by user/password
for (u = users; result == NULL && u->name != NULL; u++)
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) result = u;
} else if (user[0] == '\0') {
// Only password is set, search by token
for (u = users; result == NULL && u->name != NULL; u++)
if (strcmp(pass, u->access_token) == 0) result = u;
}
return result;
}
static void handle_login(struct mg_connection *c, struct user *u) {
char cookie[256];
const char *cookie_name = c->is_tls ? "secure_access_token" : "access_token";
mg_snprintf(cookie, sizeof(cookie),
"Set-Cookie: %s=%s; Path=/; "
"%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
cookie_name, u->access_token,
c->is_tls ? "Secure; " : "", 3600 * 24);
mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
}
static void handle_logout(struct mg_connection *c) {
char cookie[256];
const char *cookie_name = c->is_tls ? "secure_access_token" : "access_token";
mg_snprintf(cookie, sizeof(cookie),
"Set-Cookie: %s=; Path=/; "
"Expires=Thu, 01 Jan 1970 00:00:00 UTC; "
"%sHttpOnly; Max-Age=0; \r\n", cookie_name,
c->is_tls ? "Secure; " : "");
mg_http_reply(c, 200, cookie, "true\n");
}
static void handle_debug(struct mg_connection *c, struct mg_http_message *hm) {
int level = (int) mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
mg_log_set(level);
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
}
static size_t print_int_arr(void (*out)(char, void *), void *ptr, va_list *ap) {
size_t i, len = 0, num = va_arg(*ap, size_t); // Number of items in the array
int *arr = va_arg(*ap, int *); // Array ptr
for (i = 0; i < num; i++) {
len += mg_xprintf(out, ptr, "%s%d", i == 0 ? "" : ",", arr[i]);
}
return len;
}
static void handle_stats_get(struct mg_connection *c) {
int points[] = {21, 22, 22, 19, 18, 20, 23, 23, 22, 22, 22, 23, 22};
mg_http_reply(c, 200, s_json_header, "{%m:%d,%m:%d,%m:[%M]}\n",
MG_ESC("temperature"), 21, //
MG_ESC("humidity"), 67, //
MG_ESC("points"), print_int_arr,
sizeof(points) / sizeof(points[0]), points);
}
static size_t print_events(void (*out)(char, void *), void *ptr, va_list *ap) {
size_t len = 0;
struct ui_event ev;
int pageno = va_arg(*ap, int);
int no = (pageno - 1) * EVENTS_PER_PAGE;
int end = no + EVENTS_PER_PAGE;
while ((no = ui_event_next(no, &ev)) != 0 && no <= end) {
len += mg_xprintf(out, ptr, "%s{%m:%lu,%m:%d,%m:%d,%m:%m}\n", //
len == 0 ? "" : ",", //
MG_ESC("time"), ev.timestamp, //
MG_ESC("type"), ev.type, //
MG_ESC("prio"), ev.prio, //
MG_ESC("text"), MG_ESC(ev.text));
}
return len;
}
static void handle_events_get(struct mg_connection *c,
struct mg_http_message *hm) {
int pageno = (int) mg_json_get_long(hm->body, "$.page", 1);
mg_http_reply(c, 200, s_json_header, "{%m:[%M], %m:%d}\n", MG_ESC("arr"),
print_events, pageno, MG_ESC("totalCount"), MAX_EVENTS_NO);
}
static void handle_settings_set(struct mg_connection *c, struct mg_str body) {
struct settings settings;
char *s = mg_json_get_str(body, "$.device_name");
bool ok = true;
memset(&settings, 0, sizeof(settings));
mg_json_get_bool(body, "$.log_enabled", &settings.log_enabled);
settings.log_level = (int) mg_json_get_long(body, "$.log_level", 0);
settings.brightness = mg_json_get_long(body, "$.brightness", 0);
if (s && strlen(s) < MAX_DEVICE_NAME) {
free(settings.device_name);
settings.device_name = s;
} else {
free(s);
}
s_settings = settings; // Save to the device flash
mg_http_reply(c, 200, s_json_header,
"{%m:%s,%m:%m}", //
MG_ESC("status"), ok ? "true" : "false", //
MG_ESC("message"), MG_ESC(ok ? "Success" : "Failed"));
}
static void handle_settings_get(struct mg_connection *c) {
mg_http_reply(c, 200, s_json_header, "{%m:%s,%m:%hhu,%m:%hhu,%m:%m}\n", //
MG_ESC("log_enabled"),
s_settings.log_enabled ? "true" : "false", //
MG_ESC("log_level"), s_settings.log_level, //
MG_ESC("brightness"), s_settings.brightness, //
MG_ESC("device_name"), MG_ESC(s_settings.device_name));
}
static void handle_firmware_upload(struct mg_connection *c,
struct mg_http_message *hm) {
char name[64], offset[20], total[20];
struct mg_str data = hm->body;
long ofs = -1, tot = -1;
name[0] = offset[0] = '\0';
mg_http_get_var(&hm->query, "name", name, sizeof(name));
mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
mg_http_get_var(&hm->query, "total", total, sizeof(total));
MG_INFO(("File %s, offset %s, len %lu", name, offset, data.len));
if ((ofs = mg_json_get_long(mg_str(offset), "$", -1)) < 0 ||
(tot = mg_json_get_long(mg_str(total), "$", -1)) < 0) {
mg_http_reply(c, 500, "", "offset and total not set\n");
} else if (ofs == 0 && mg_ota_begin((size_t) tot) == false) {
mg_http_reply(c, 500, "", "mg_ota_begin(%ld) failed\n", tot);
} else if (data.len > 0 && mg_ota_write(data.buf, data.len) == false) {
mg_http_reply(c, 500, "", "mg_ota_write(%lu) @%ld failed\n", data.len, ofs);
mg_ota_end();
} else if (data.len == 0 && mg_ota_end() == false) {
mg_http_reply(c, 500, "", "mg_ota_end() failed\n", tot);
} else {
mg_http_reply(c, 200, s_json_header, "true\n");
}
}
// HTTP request handler function
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_ACCEPT) {
if (c->fn_data != NULL) { // TLS listener!
struct mg_tls_opts opts = {0};
opts.cert = mg_unpacked("/certs/server_cert.pem");
opts.key = mg_unpacked("/certs/server_key.pem");
mg_tls_init(c, &opts);
}
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct user *u = authenticate(hm);
if (mg_match(hm->uri, mg_str("/api/#"), NULL) && u == NULL) {
mg_http_reply(c, 403, "", "Not Authorised\n");
} else if (mg_match(hm->uri, mg_str("/api/login"), NULL)) {
handle_login(c, u);
} else if (mg_match(hm->uri, mg_str("/api/logout"), NULL)) {
handle_logout(c);
} else if (mg_match(hm->uri, mg_str("/api/debug"), NULL)) {
handle_debug(c, hm);
} else if (mg_match(hm->uri, mg_str("/api/stats/get"), NULL)) {
handle_stats_get(c);
} else if (mg_match(hm->uri, mg_str("/api/events/get"), NULL)) {
handle_events_get(c, hm);
} else if (mg_match(hm->uri, mg_str("/api/settings/get"), NULL)) {
handle_settings_get(c);
} else if (mg_match(hm->uri, mg_str("/api/settings/set"), NULL)) {
handle_settings_set(c, hm->body);
} else if (mg_match(hm->uri, mg_str("/api/firmware/upload"), NULL)) {
handle_firmware_upload(c, hm);
} else {
struct mg_http_serve_opts opts;
memset(&opts, 0, sizeof(opts));
opts.fs = HAL_FS;
opts.root_dir = HAL_WEB_ROOT_DIR;
mg_http_serve_dir(c, ev_data, &opts);
}
MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len,
hm->method.buf, (int) hm->uri.len, hm->uri.buf, (int) 3,
&c->send.buf[9]));
}
}
void net_init(struct mg_mgr *mgr) {
s_settings.device_name = strdup("My Device");
mg_http_listen(mgr, HTTP_URL, ev_handler, NULL);
mg_http_listen(mgr, HTTPS_URL, ev_handler, (void *) 1);
mg_timer_add(mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT,
timer_sntp_fn, mgr);
}
@@ -1,50 +0,0 @@
// Copyright (c) 2023-2024 Cesanta Software Limited
// All rights reserved
#pragma once
#include "mongoose.h"
#ifdef __cplusplus
extern "C" {
#endif
#if MG_ENABLE_FATFS
#define HAL_FS (&mg_fs_fat)
#define HAL_ROOT_DIR "/"
#elif MG_ENABLE_PACKED_FS
#define HAL_FS (&mg_fs_packed)
#define HAL_ROOT_DIR "/"
#else
#define HAL_FS (&mg_fs_posix)
#define HAL_ROOT_DIR "./"
#endif
#define HAL_WEB_ROOT_DIR HAL_ROOT_DIR "web_root"
#if defined(HTTP_URL) && defined(HTTPS_URL)
// Allow to override via the build flags
#elif MG_ENABLE_TCPIP
#define HTTP_URL "http://0.0.0.0:80" // Embedded build:
#define HTTPS_URL "https://0.0.0.0:443" // Use standard privileged ports
#else
#define HTTP_URL "http://0.0.0.0:8000" // Workstation build:
#define HTTPS_URL "https://0.0.0.0:8443" // Use non-privileged ports
#endif
#define MAX_DEVICE_NAME 40
#define MAX_EVENTS_NO 400
#define MAX_EVENT_TEXT_SIZE 10
#define EVENTS_PER_PAGE 20
// Event log entry
struct ui_event {
uint8_t type, prio;
unsigned long timestamp;
char text[10];
};
void net_init(struct mg_mgr *mgr);
#ifdef __cplusplus
}
#endif
@@ -1,70 +0,0 @@
// DO NOT EDIT. This file is generated using this command:
// /usr/local/bin/node /Users/cpq/src/mongoose/reference-projects/windows-macos-linux/web-ui-dashboard/pack.js web_root/bundle.js::gzip web_root/components.js::gzip web_root/history.min.js::gzip web_root/index.html::gzip web_root/main.css::gzip web_root/main.js::gzip certs/server_cert.pem certs/server_key.pem
#include <stddef.h>
#include <string.h>
#include <time.h>
#if defined(__cplusplus)
extern "C" {
#endif
const char *mg_unlist(size_t no);
const char *mg_unpack(const char *, size_t *, time_t *);
#if defined(__cplusplus)
}
#endif
static const unsigned char v0[] = {31,139,8,0,0,0,0,0,0,19,173,60,253,119,219,54,146,255,138,197,203,227,2,213,132,150,210,118,239,142,10,170,151,186,105,157,54,73,179,249,234,238,170,42,31,69,65,22,107,10,148,65,80,137,107,234,254,246,123,51,0,72,74,150,123,119,251,238,23,11,223,24,12,6,243,77,239,82,125,166,192,128,132,4,52,148,144,67,13,5,100,226,110,15,169,152,205,161,18,231,105,150,155,70,126,102,211,184,106,174,26,213,108,155,71,188,209,219,117,115,165,243,101,83,126,170,154,141,202,26,101,62,53,185,146,179,108,61,111,254,40,203,230,183,82,47,155,220,72,157,158,231,147,85,173,50,147,151,234,108,197,20,24,126,183,42,53,219,165,250,76,158,229,234,204,112,53,147,115,97,102,114,62,209,210,212,90,157,169,125,59,99,203,20,191,195,177,70,168,104,155,106,169,204,235,114,41,39,38,12,77,164,229,166,220,201,139,117,94,44,153,226,221,164,53,163,19,217,137,238,88,226,110,63,193,125,115,220,83,242,224,90,222,6,66,228,83,45,228,44,159,199,129,150,43,170,151,182,94,207,242,57,149,38,249,138,165,250,170,222,72,101,170,168,144,234,202,172,191,121,18,134,172,142,50,220,88,75,37,238,245,127,57,85,81,150,22,69,55,19,158,240,56,225,16,120,24,3,33,204,237,86,150,171,51,19,134,170,46,138,129,48,209,82,174,210,186,48,111,116,185,173,120,11,236,81,251,174,204,151,103,35,33,4,130,136,112,32,164,135,99,102,249,156,123,92,46,153,129,154,238,22,119,233,33,105,201,148,191,116,139,168,90,220,33,72,177,130,45,46,18,39,112,45,111,99,13,90,174,226,18,146,228,58,198,21,32,73,252,239,34,30,65,146,72,95,93,198,22,52,72,146,204,183,173,109,33,43,85,101,116,157,153,82,119,131,118,212,135,56,31,14,101,156,239,219,219,183,173,29,90,118,170,92,74,188,111,42,176,154,67,221,29,99,199,248,157,157,120,151,213,26,233,131,150,221,119,35,54,72,66,126,237,246,210,186,254,91,75,148,102,157,87,17,157,92,40,160,74,86,42,35,63,27,97,186,177,87,118,108,190,98,22,74,195,219,133,147,100,122,197,240,7,240,79,148,36,215,81,174,150,242,243,207,43,166,248,112,204,9,172,73,75,250,19,243,84,209,32,75,50,19,51,28,114,183,236,64,48,41,168,115,102,230,220,227,65,70,73,34,253,118,84,113,8,59,65,83,42,194,2,194,99,183,237,14,176,104,223,19,200,73,183,159,162,253,218,189,176,146,217,119,138,69,11,77,22,45,210,74,10,186,80,35,70,255,226,1,238,238,45,104,207,178,208,50,189,222,187,227,33,148,189,27,188,70,160,217,0,231,44,195,144,64,90,138,193,136,135,161,142,182,117,181,102,138,135,225,224,34,74,18,61,28,54,77,57,16,244,32,22,101,173,50,249,86,170,165,212,185,186,226,97,200,88,121,178,167,105,114,206,46,122,143,227,130,89,44,121,222,136,44,164,128,140,174,79,71,85,169,13,171,249,68,9,29,85,235,124,101,24,159,112,15,157,17,218,161,4,18,225,136,189,244,133,66,176,156,144,195,163,36,217,225,31,9,44,35,20,188,65,248,18,100,186,172,20,43,118,183,135,156,211,40,145,227,223,225,24,222,179,12,114,40,1,71,43,176,43,14,132,200,162,242,147,146,250,221,199,31,158,23,18,153,13,88,124,227,180,245,116,86,204,221,99,4,75,178,197,244,138,229,60,46,128,250,57,188,101,9,228,156,106,114,32,138,48,92,176,156,115,240,135,248,198,32,150,221,137,249,132,144,44,70,29,166,62,179,251,242,163,178,200,91,193,22,214,176,131,91,88,192,53,92,136,36,12,233,93,52,77,10,159,197,133,39,28,196,41,30,233,26,207,190,18,163,201,234,169,105,251,14,136,106,71,136,186,158,173,230,194,158,133,237,132,153,173,230,188,105,130,69,89,22,50,237,189,129,93,211,156,120,25,187,41,206,140,131,202,224,197,31,142,86,245,102,33,245,97,219,34,191,202,149,233,207,95,18,52,176,35,116,218,63,59,30,63,211,58,189,141,242,138,126,217,142,79,151,108,3,119,158,217,196,187,125,111,56,49,226,120,23,37,201,226,155,209,116,201,118,244,90,97,103,185,15,236,162,107,121,11,187,72,203,213,148,254,218,251,219,17,197,196,59,78,236,7,107,66,82,227,130,176,178,24,142,221,5,11,182,22,23,22,43,235,48,164,213,132,88,227,15,214,112,43,129,117,44,112,28,231,104,115,34,139,74,158,225,101,108,197,104,178,125,250,121,178,29,14,105,47,90,111,139,15,249,207,23,187,195,81,126,53,251,158,215,116,81,251,247,76,193,14,214,98,221,52,217,1,157,192,173,216,217,71,176,21,116,86,30,134,107,252,29,136,109,24,178,235,166,97,72,22,28,168,49,12,175,237,123,167,154,199,61,184,198,45,97,35,107,154,91,216,113,238,30,193,237,212,113,234,69,24,178,133,184,61,41,130,237,65,240,64,72,133,120,158,36,185,158,238,136,205,20,226,57,219,65,1,138,199,133,248,96,207,1,23,112,11,197,201,165,164,91,138,40,122,41,10,206,227,2,143,132,60,15,31,87,209,83,98,6,66,133,33,43,196,21,91,115,190,247,207,64,138,5,172,196,231,201,234,241,227,9,183,135,192,91,10,67,246,39,219,117,227,112,133,48,244,37,65,180,177,108,225,121,198,18,30,41,249,217,188,203,23,5,114,62,248,133,225,88,32,130,225,40,17,174,73,243,176,239,240,186,255,14,95,49,124,121,112,61,27,14,219,159,30,203,124,110,25,65,167,221,37,160,173,16,128,82,140,38,58,12,203,167,158,169,76,202,225,144,179,68,232,89,57,39,182,135,212,172,192,136,19,71,76,172,44,123,206,18,90,62,254,192,144,217,32,187,73,136,114,12,111,117,157,158,160,190,180,130,218,119,8,211,52,179,185,123,32,234,20,187,80,77,195,14,31,177,226,83,21,85,229,70,50,230,151,69,5Line truncated
static const unsigned char v1[] = {31,139,8,0,0,0,0,0,0,19,237,125,107,115,219,70,182,224,119,255,138,19,150,54,36,199,236,22,186,241,150,68,165,28,207,77,57,85,214,220,84,156,232,75,110,118,13,129,32,137,17,30,92,0,164,36,107,248,223,183,206,233,198,147,148,236,100,124,167,118,181,83,149,64,64,163,159,231,253,2,61,222,150,17,148,85,17,135,213,248,252,85,156,110,242,162,130,71,88,207,160,136,178,69,84,204,96,91,70,31,170,160,138,232,238,63,150,203,40,172,232,246,231,104,57,131,117,149,38,51,248,57,223,86,81,1,123,88,22,121,10,48,230,167,55,219,108,145,68,252,239,229,248,252,213,171,211,83,120,23,37,155,168,128,229,54,11,171,56,207,160,90,7,21,20,81,181,45,178,18,2,216,20,121,26,151,81,221,92,230,201,46,42,33,88,226,172,139,40,9,30,94,133,121,86,86,240,87,188,135,57,76,210,114,6,187,32,153,194,252,18,178,232,14,126,82,19,76,244,88,108,46,163,234,151,56,141,242,109,85,183,206,160,30,54,61,127,245,42,186,167,179,170,137,127,196,63,48,135,199,87,0,235,40,40,170,51,220,211,166,196,137,240,140,31,47,202,221,10,194,36,40,203,249,201,35,189,226,244,180,135,251,52,201,202,249,104,93,85,155,179,211,211,187,187,59,126,103,242,188,88,157,74,195,48,78,203,221,106,4,203,56,73,230,163,44,207,162,17,236,226,232,238,251,252,126,62,50,192,0,105,129,180,70,151,23,155,160,90,35,22,242,219,136,37,113,22,133,193,102,62,42,242,109,182,24,117,155,255,158,199,217,176,253,46,94,84,235,249,72,142,96,49,31,93,89,220,20,30,56,120,13,44,110,3,254,111,128,97,24,216,230,88,239,133,4,105,224,93,226,114,199,147,140,174,189,158,140,58,178,166,187,203,29,211,73,152,192,41,213,245,72,119,48,62,141,46,47,78,241,24,151,23,120,230,203,143,179,87,0,139,252,46,123,83,20,57,30,248,95,9,208,1,108,4,183,235,166,249,40,220,22,69,148,85,111,243,36,47,70,151,240,167,64,143,144,246,193,227,210,126,231,114,59,144,92,218,64,23,130,72,243,184,243,7,175,154,167,245,177,55,52,112,199,134,175,88,243,238,157,176,175,124,16,50,49,193,76,13,48,18,147,153,41,51,193,188,198,183,35,56,189,132,14,240,183,155,127,131,254,107,130,62,53,152,153,48,4,57,130,30,193,158,154,204,188,22,7,128,15,243,213,139,131,56,183,125,11,76,238,91,33,55,124,198,109,75,114,219,97,220,183,64,112,33,240,102,45,185,237,155,33,183,17,116,130,27,146,155,190,71,111,185,111,37,92,10,19,4,151,158,8,185,225,152,220,116,81,82,153,220,241,28,238,88,54,247,92,110,184,22,55,44,46,44,151,27,158,201,165,228,66,186,220,148,22,23,190,195,93,196,130,139,19,187,54,23,210,74,4,151,194,101,220,178,157,64,112,33,109,80,87,3,12,33,184,233,114,203,199,46,190,131,216,180,220,131,62,140,75,7,4,183,76,129,178,205,48,76,238,73,55,100,92,250,38,151,22,227,150,233,113,71,152,120,35,184,239,203,192,225,174,237,131,186,226,4,6,112,105,219,33,227,134,225,114,211,245,184,48,61,238,218,220,50,185,143,75,27,134,205,61,233,133,220,146,22,55,109,110,155,22,247,109,171,94,22,87,149,190,247,212,238,4,55,29,159,91,62,237,174,62,104,200,184,105,219,140,11,211,100,220,181,25,55,92,137,155,119,29,132,72,224,112,219,5,186,232,3,34,4,61,28,100,10,46,60,147,113,219,19,220,242,109,198,29,203,226,158,227,39,172,193,11,30,196,231,182,133,189,28,238,91,184,5,66,157,88,51,196,172,21,50,66,45,174,39,25,226,150,213,152,87,179,48,133,93,198,13,7,223,187,22,227,166,144,12,49,76,235,49,238,185,184,69,9,116,169,183,200,16,203,184,71,137,7,243,29,198,93,201,16,213,234,96,140,112,173,96,112,20,215,10,82,12,209,77,16,117,217,113,136,114,233,48,133,110,68,13,238,70,186,33,151,62,46,102,113,203,116,25,162,155,227,249,21,182,125,19,119,138,87,194,54,35,108,35,178,241,112,30,34,193,83,72,80,67,20,21,209,188,222,81,98,163,213,147,231,182,136,100,203,8,231,120,92,135,48,206,77,219,65,124,115,215,70,120,72,104,161,66,216,231,134,133,44,227,48,110,120,174,6,167,199,77,19,111,60,147,219,158,196,25,109,141,0,199,71,70,180,20,170,62,41,185,245,103,69,130,176,65,200,192,4,19,217,93,48,7,12,80,15,134,112,208,28,24,8,197,50,170,170,56,91,149,239,94,154,104,20,6,183,193,89,251,220,181,245,125,32,56,162,213,86,128,49,193,72,77,48,186,141,6,54,94,33,78,193,65,45,150,154,32,36,205,144,50,188,246,122,27,199,166,48,104,138,148,209,28,6,205,225,51,103,109,210,20,230,31,154,66,45,72,171,63,133,179,235,151,134,51,7,132,201,237,107,2,151,1,120,244,30,180,12,52,175,152,217,3,22,181,1,142,184,22,14,183,83,33,153,249,79,77,192,28,230,215,19,152,95,62,129,79,19,24,252,16,89,97,144,189,52,60,185,220,38,216,188,115,222,244,13,51,197,59,59,193,237,43,4,166,234,36,188,126,47,33,13,188,163,110,8,185,235,131,14,194,3,234,179,102,216,133,249,96,12,87,18,180,146,240,118,140,214,250,98,153,7,202,255,137,202,219,42,223,188,52,180,248,32,92,180,151,81,227,185,65,13,1,84,240,62,160,205,33,223,35,226,164,88,163,129,225,72,65,151,55,117,63,4,34,218,239,238,53,205,146,58,76,200,107,49,48,229,69,107,202,191,179,185,180,135,88,1,97,95,99,123,42,60,48,6,196,33,208,14,3,243,200,56,195,132,102,208,181,144,127,116,73,73,75,14,25,47,72,162,127,109,184,224,95,162,213,44,238,161,185,141,182,184,12,164,201,61,203,3,253,7,1,105,115,203,182,40,28,240,198,227,190,227,130,186,106,166,66,33,181,99,220,189Line truncated
static const unsigned char v2[] = {31,139,8,0,0,0,0,0,0,19,237,91,109,111,219,184,150,254,43,182,6,43,144,48,163,218,157,185,179,187,114,57,70,218,166,47,64,130,4,77,218,249,96,24,3,69,166,108,78,100,210,165,40,39,134,173,255,190,56,164,168,23,91,73,211,189,157,189,131,221,253,18,75,124,61,60,58,60,231,121,14,153,126,146,139,88,115,41,144,38,2,239,60,121,251,39,139,181,71,169,222,174,153,76,122,236,97,45,149,206,124,255,168,102,37,231,121,202,38,246,39,40,219,81,129,112,232,185,49,235,198,115,150,112,193,124,223,254,6,209,106,62,177,143,104,58,35,2,135,143,205,59,41,127,131,15,60,211,82,109,205,248,186,249,86,32,189,228,25,169,150,129,119,138,233,92,137,94,189,48,188,115,207,61,129,36,222,241,4,177,169,156,225,178,33,60,59,249,199,155,72,245,20,133,34,186,43,203,194,93,65,248,60,148,36,149,209,156,205,195,254,168,24,151,93,53,116,141,163,52,69,202,141,64,20,169,159,5,38,42,176,221,104,127,88,87,20,48,13,163,187,106,32,17,172,168,38,34,136,41,35,34,88,83,207,35,2,13,113,129,166,205,239,67,24,222,121,121,198,122,153,86,60,214,222,184,90,151,132,85,58,161,124,95,7,127,252,193,178,11,251,133,116,184,155,179,36,202,83,29,234,162,16,141,42,144,73,4,177,98,145,102,87,145,94,82,17,172,35,149,185,231,84,198,17,140,158,157,42,118,246,53,143,82,234,26,159,151,53,85,193,5,91,73,181,173,62,75,89,250,33,202,150,135,101,175,149,188,207,152,114,197,27,201,231,189,161,83,59,122,137,199,151,198,18,2,107,30,87,74,174,153,210,91,36,136,215,158,218,35,59,38,242,21,83,209,109,202,194,254,144,44,152,14,143,173,64,29,72,92,20,152,60,58,195,209,130,159,61,201,81,207,162,192,102,81,156,50,52,122,98,81,149,190,159,57,21,175,191,208,147,75,169,63,234,179,7,174,187,56,225,35,202,208,191,99,18,83,137,34,76,114,202,208,127,96,146,81,137,114,76,18,202,208,127,98,146,82,137,18,60,126,228,235,198,65,105,121,164,203,36,178,163,218,182,25,165,174,190,32,7,94,170,185,7,14,12,122,44,130,104,62,63,103,209,156,139,197,117,26,101,75,218,244,4,118,181,222,11,143,82,170,131,120,25,169,83,141,134,120,162,67,239,133,55,208,5,17,1,12,188,254,254,1,130,44,191,205,180,66,35,28,214,195,92,41,150,240,7,218,22,191,212,248,208,140,192,197,156,61,92,38,72,52,134,16,65,202,196,66,47,155,35,221,168,136,167,207,151,72,151,67,156,140,204,184,41,143,25,26,146,19,39,92,189,205,155,35,193,55,23,84,239,247,222,11,143,48,112,66,18,254,40,42,42,49,189,159,60,60,86,125,74,79,70,190,143,36,21,78,102,133,137,168,223,134,68,97,183,1,26,157,39,208,185,180,55,55,6,171,123,241,131,49,56,134,130,57,139,229,156,125,254,244,17,9,76,118,235,72,47,69,180,98,161,32,25,139,84,188,12,189,9,172,156,77,60,47,100,100,25,101,203,208,251,9,74,36,148,200,162,104,187,184,142,245,6,110,76,194,168,14,236,168,68,82,29,192,96,68,81,38,42,1,140,106,170,53,48,223,247,38,94,159,82,230,251,72,13,104,41,73,195,42,24,72,55,96,152,72,223,247,126,130,166,178,108,106,69,108,52,149,32,246,64,98,162,138,182,189,255,53,94,255,25,206,189,229,155,75,79,19,101,25,95,136,253,190,21,93,165,66,86,149,163,177,120,21,169,69,190,98,66,103,165,5,142,197,96,96,85,205,104,85,55,21,179,177,235,38,123,92,244,24,46,39,88,43,169,37,128,0,208,254,229,189,112,78,205,134,89,70,36,246,125,4,113,215,4,105,92,184,229,23,196,184,218,33,38,17,149,96,73,49,188,142,192,109,73,20,131,219,50,142,248,104,145,109,77,19,105,69,229,110,241,229,230,2,213,139,69,13,79,244,4,113,138,134,36,171,119,18,70,26,19,30,100,58,210,140,10,28,34,78,21,218,21,68,99,98,199,162,148,242,202,212,124,31,213,47,212,243,76,87,99,121,19,107,82,238,181,182,16,211,197,22,130,165,13,220,11,14,235,98,143,112,99,181,19,107,108,246,229,96,8,40,2,251,27,216,71,232,110,139,188,82,208,62,165,194,247,27,66,155,53,217,233,203,213,129,184,119,108,75,25,24,118,99,37,19,239,133,157,215,21,28,204,93,173,24,13,73,228,220,59,110,84,16,89,61,98,144,172,234,208,40,39,188,232,52,224,78,47,91,239,110,74,13,190,113,250,119,59,221,20,219,71,40,52,170,128,34,120,128,2,88,38,188,223,177,173,239,163,33,201,107,177,181,213,135,113,209,145,102,248,91,27,215,88,59,109,196,222,98,172,43,228,44,255,242,93,95,161,172,159,49,225,20,73,240,217,13,97,160,86,83,145,167,41,105,108,139,134,38,169,104,54,215,212,152,9,178,93,96,237,172,209,11,182,18,81,6,107,67,117,159,106,183,177,58,216,129,158,104,232,129,67,61,62,218,105,124,210,209,65,78,36,226,68,225,80,161,254,16,254,66,52,233,143,112,193,210,140,245,76,97,65,36,157,206,136,234,112,248,253,97,83,84,188,19,160,196,104,189,78,183,200,26,61,169,252,20,174,16,186,12,214,121,182,68,172,165,50,65,251,35,34,169,12,18,158,106,166,208,113,88,238,105,8,15,5,168,135,55,231,116,206,79,211,67,127,73,4,61,85,42,218,130,59,97,116,56,102,175,244,152,13,6,88,76,217,172,225,64,217,108,44,131,68,170,179,40,94,118,206,219,94,145,192,69,181,150,93,198,244,149,146,171,181,14,5,137,165,72,184,90,221,168,72,100,28,198,184,145,33,35,209,122,205,196,252,156,103,154,9,166,66,69,132,212,60,217,186,130,44,228,128,17,133,219,10,148,127,39,68,139,35,241,57,99,111,47,47,104,31,121,185,176,248,117,94,127,224,123,46,230,242,126,191,239,219,135,96,46,99,179,238,227,146,210,1Line truncated
static const unsigned char v3[] = {31,139,8,0,0,0,0,0,0,19,93,147,77,115,219,32,16,134,239,249,21,91,46,58,52,66,232,91,206,8,205,164,105,14,61,116,218,67,219,105,143,68,90,75,36,8,84,192,114,252,239,59,178,108,215,201,133,133,125,159,133,133,93,234,15,159,191,61,252,248,243,253,17,6,63,170,230,166,94,12,40,161,123,78,80,19,104,149,112,142,147,33,220,238,148,130,167,62,220,15,210,35,105,110,0,234,1,69,183,76,0,106,47,189,194,166,142,86,187,250,70,244,2,218,65,88,135,158,147,157,223,134,21,129,232,90,28,188,159,66,252,187,147,51,39,191,195,159,247,225,131,25,39,225,229,147,66,2,173,209,30,181,231,228,203,35,199,174,199,119,177,90,140,200,201,44,113,63,25,235,175,240,189,236,252,192,59,156,101,139,225,113,113,11,82,75,47,133,10,93,43,20,242,152,178,255,155,41,169,95,192,162,226,68,182,70,19,240,135,9,57,145,163,232,49,114,115,255,241,117,84,4,6,139,91,78,58,225,197,221,27,229,182,118,115,15,175,163,210,142,7,203,109,238,162,104,191,223,211,125,74,141,237,163,132,49,182,160,1,108,165,82,60,208,70,99,0,75,206,159,204,43,15,24,48,72,50,72,178,0,156,183,230,229,148,46,15,98,154,159,93,60,104,119,214,162,246,15,70,25,27,52,80,79,194,15,103,94,73,141,173,152,120,96,205,78,119,193,181,251,217,72,125,241,119,60,248,26,103,180,202,75,136,75,202,170,68,36,41,173,178,10,78,134,1,99,57,205,242,44,140,105,26,223,87,116,83,148,176,142,12,88,28,87,176,161,101,62,135,180,252,181,185,47,160,56,6,20,176,153,105,153,139,247,116,152,208,52,78,160,160,44,73,218,152,150,105,74,139,12,82,154,23,16,83,86,229,176,156,148,195,114,210,152,211,50,206,128,137,36,163,73,158,195,201,28,119,57,73,23,36,133,20,24,196,23,33,128,168,129,122,121,222,230,93,53,215,106,141,66,106,218,58,71,214,234,58,127,80,232,6,68,127,162,235,232,220,191,245,147,233,14,231,78,31,165,14,135,208,181,22,81,147,166,142,22,237,8,185,214,202,201,131,179,45,39,131,116,222,216,3,29,165,166,207,110,193,86,245,26,92,27,105,52,221,110,233,230,99,216,49,165,183,124,29,173,255,238,31,169,238,250,235,136,3,0,0,0};
static const unsigned char v4[] = {31,139,8,0,0,0,0,0,0,19,237,60,217,142,228,56,114,191,34,247,96,128,202,177,168,214,153,89,169,130,141,53,22,48,188,192,142,31,108,63,120,209,213,15,76,137,153,201,45,93,38,169,170,204,214,202,223,110,4,41,74,212,145,215,28,246,236,194,24,84,87,49,46,6,131,100,40,24,12,206,231,31,254,206,18,152,102,31,180,72,19,206,173,247,192,9,28,223,250,139,245,227,31,254,195,250,35,77,72,193,137,245,23,235,40,68,197,227,207,159,13,82,39,41,243,31,62,255,96,199,120,47,8,179,227,29,217,151,140,52,187,242,132,56,253,70,139,67,188,43,89,74,24,218,149,167,23,245,103,236,90,188,204,104,106,125,71,34,178,33,187,118,194,139,144,248,64,73,89,8,82,136,248,211,167,246,40,242,172,201,104,65,208,145,208,195,81,196,158,19,189,160,15,178,123,163,2,9,114,18,208,19,65,56,253,115,205,69,236,185,238,247,47,40,47,191,33,129,119,18,19,135,47,168,52,91,198,159,251,178,16,104,143,115,154,157,227,63,20,130,48,235,29,51,251,159,24,197,153,253,47,36,123,39,130,38,216,230,184,224,136,19,70,247,29,3,193,162,102,4,113,34,4,45,14,60,254,148,188,123,222,39,251,19,231,174,247,73,209,188,99,70,177,160,101,97,80,149,21,255,246,201,10,252,118,87,166,231,38,199,236,64,139,216,125,49,199,70,139,35,97,84,180,71,214,116,16,247,37,41,179,146,105,76,103,68,36,202,10,125,208,84,28,99,175,58,181,120,183,99,241,199,145,48,242,244,69,80,145,145,175,171,102,100,162,148,36,37,147,250,196,117,145,18,6,125,90,105,41,4,73,95,110,17,180,71,207,62,250,246,49,176,143,161,125,140,236,227,186,145,67,148,54,212,106,73,200,199,120,16,184,25,171,62,237,72,211,237,108,46,88,89,28,26,83,200,174,204,82,194,218,164,76,137,253,182,75,237,138,17,155,227,188,106,204,57,171,41,202,203,162,228,21,78,136,253,239,255,252,99,89,148,232,223,200,161,206,48,179,127,36,69,86,218,63,150,5,78,74,251,247,101,193,203,12,115,251,143,116,71,84,247,22,80,219,191,47,107,70,9,179,254,149,124,216,189,168,151,97,124,30,201,91,158,227,44,51,198,252,236,126,223,242,122,103,243,186,50,160,155,232,251,209,84,186,47,85,201,169,28,40,35,25,22,244,157,188,188,19,6,43,42,67,56,163,7,48,0,21,20,103,32,172,217,149,66,148,121,140,28,63,130,46,235,170,17,101,21,35,7,90,2,239,50,210,72,243,209,34,133,125,225,234,117,176,184,56,146,50,203,112,197,73,172,255,104,119,181,16,101,97,211,162,170,133,93,86,226,192,202,186,178,57,201,72,34,108,16,140,25,193,35,211,142,38,86,153,2,182,214,194,60,47,45,224,201,162,237,215,122,133,211,20,188,130,171,53,82,42,168,177,9,134,11,190,47,89,30,23,101,65,218,47,226,92,145,127,80,116,95,109,213,98,132,19,161,27,188,222,229,84,124,181,21,73,191,224,113,85,17,204,112,145,144,88,97,94,118,56,121,131,17,23,105,111,47,105,120,19,65,115,124,32,170,227,88,250,143,125,153,212,156,209,226,208,148,181,128,33,198,184,22,101,135,172,41,162,197,59,206,104,170,124,221,17,167,229,135,226,174,88,121,96,132,243,230,194,100,199,177,86,148,22,5,97,136,87,180,64,157,53,6,92,89,139,49,78,251,3,169,68,55,126,130,89,114,252,186,52,112,176,231,158,146,44,125,233,148,71,229,126,207,137,136,145,95,157,12,21,148,8,99,83,46,9,83,70,233,121,246,52,35,168,174,178,18,167,232,166,233,97,189,244,27,157,215,121,142,217,185,73,41,175,50,124,142,51,202,5,162,130,228,237,46,43,147,183,255,170,75,65,236,52,181,211,204,222,211,67,205,136,61,115,61,246,145,217,21,56,131,222,127,182,114,156,156,136,57,196,206,200,129,20,105,51,172,186,156,20,181,93,102,118,13,159,20,46,16,23,231,76,13,112,105,141,246,27,131,17,185,3,244,140,182,114,31,197,106,41,84,25,78,200,81,122,171,126,39,205,81,77,89,225,132,138,115,236,117,91,227,187,109,130,3,188,215,162,150,165,220,35,224,11,43,179,97,155,116,19,146,212,140,151,44,174,74,10,95,181,54,78,41,7,31,146,106,68,74,246,184,206,68,139,235,148,150,118,130,139,119,204,109,146,239,72,106,211,61,195,57,177,105,126,176,203,221,159,193,63,240,247,131,253,78,83,82,246,19,39,167,107,234,205,114,154,166,25,105,129,81,81,231,248,164,191,81,224,58,70,11,248,72,211,148,20,95,123,137,114,141,253,96,199,49,108,201,148,149,213,52,164,144,97,65,231,223,192,73,211,226,128,78,177,251,178,4,63,107,184,244,40,25,22,100,32,29,64,61,21,43,5,22,68,183,248,27,249,24,200,101,171,167,228,9,206,64,150,103,54,207,186,89,225,2,157,98,107,104,156,251,6,45,146,35,250,86,150,185,134,240,132,149,89,134,120,129,43,196,5,163,137,40,8,231,113,197,202,19,205,169,56,43,170,3,195,41,37,224,148,89,153,163,254,123,98,77,176,239,20,95,70,138,114,134,43,89,74,11,156,245,186,100,152,31,73,138,190,17,86,106,88,81,231,132,209,4,169,125,56,133,118,134,158,17,51,156,152,253,128,247,68,180,0,191,99,66,148,43,234,150,134,91,157,230,168,110,133,239,247,123,3,215,1,131,221,179,191,95,63,187,115,174,206,11,187,150,107,125,231,186,174,73,177,140,186,6,85,221,145,116,138,221,101,53,211,163,217,49,88,209,114,226,58,8,196,173,12,115,97,204,194,89,174,18,13,56,214,68,175,183,14,66,11,216,71,253,92,64,104,105,96,57,169,40,214,13,216,23,90,105,173,66,183,93,198,122,245,192,153,130,61,106,170,105,143,152,169,220,99,230,186,247,168,241,32,122,176,246,89,83,248,116,148,3,66,13,183,117,56,67,101,145,157,155,126,233,226Line truncated
static const unsigned char v5[] = {31,139,8,0,0,0,0,0,0,19,189,59,107,115,219,56,146,223,253,43,122,180,222,145,228,33,41,82,150,223,150,167,146,76,102,146,173,76,146,138,157,212,237,186,92,9,68,66,36,198,36,193,2,160,215,104,248,159,238,55,220,47,187,106,128,79,73,86,50,179,123,151,170,200,36,1,116,55,26,141,126,161,49,24,0,188,125,119,247,242,18,158,189,127,13,62,137,99,9,201,76,42,144,138,8,5,11,166,34,232,146,140,13,186,192,82,224,34,160,2,20,7,73,197,156,130,138,40,144,44,3,162,128,164,43,248,248,225,245,193,65,119,38,41,72,37,152,175,186,87,7,44,201,184,80,176,134,200,2,65,211,128,10,11,102,146,222,42,162,168,126,122,57,157,82,95,233,199,15,116,106,65,164,146,216,130,15,124,166,168,128,28,166,130,39,0,93,103,48,153,165,65,76,157,223,100,19,232,107,159,167,210,130,55,60,100,169,5,183,84,41,150,134,22,60,159,41,197,241,131,34,202,2,197,178,23,60,230,66,90,160,255,210,192,130,183,92,177,41,243,137,98,216,239,61,9,89,90,60,127,204,98,78,130,159,89,76,13,148,146,134,174,51,240,121,146,241,148,166,74,26,50,14,16,187,66,236,28,198,144,9,158,73,24,223,232,25,124,185,150,243,16,252,152,72,57,62,92,235,38,71,191,229,176,76,226,84,142,59,145,82,217,229,96,176,88,44,156,197,177,195,69,56,24,186,174,59,144,243,176,3,115,70,23,207,249,114,220,113,193,5,111,232,156,159,233,223,147,206,205,117,64,167,242,230,90,170,85,76,111,156,56,182,253,88,218,222,122,202,226,248,50,229,41,189,146,74,240,71,122,249,55,215,117,139,103,59,97,138,138,152,37,76,93,122,213,199,5,11,84,116,233,58,39,217,242,42,191,30,24,128,215,3,3,62,4,22,140,59,111,200,138,138,207,195,14,4,68,17,59,37,9,45,190,193,176,211,238,227,217,187,122,121,157,155,235,140,168,168,96,67,167,164,182,3,193,184,243,171,55,116,78,135,150,231,156,15,63,157,59,23,222,51,207,57,57,183,244,143,107,185,150,103,121,158,229,185,206,232,252,213,136,120,206,104,100,233,31,221,100,123,182,115,124,246,204,57,189,112,78,47,138,222,67,231,124,100,121,110,108,59,158,237,120,67,226,156,123,206,185,87,244,119,188,19,219,25,157,127,58,113,78,206,136,115,126,230,156,159,21,195,156,243,83,219,57,63,125,53,114,206,142,63,157,57,195,115,226,156,159,58,231,167,186,217,181,244,203,201,171,11,103,132,16,79,156,243,147,170,225,196,118,206,79,62,29,59,163,147,103,173,33,158,235,120,199,214,177,229,156,157,58,103,245,71,77,32,113,134,23,206,208,144,236,34,153,182,227,225,188,46,204,143,249,172,39,247,106,232,28,95,124,66,230,32,95,206,44,253,99,72,30,89,206,240,228,149,231,109,53,212,12,253,87,103,176,151,243,200,86,195,220,79,222,54,227,207,157,11,13,235,213,78,244,206,240,196,242,188,79,199,206,197,104,155,2,231,124,104,13,145,252,115,231,130,180,39,230,225,216,227,179,216,241,134,142,71,26,220,241,44,199,243,28,111,212,224,34,126,26,57,163,179,114,69,42,198,123,182,121,121,117,238,120,199,229,114,214,204,183,205,178,156,190,194,101,105,46,52,182,96,183,79,23,206,168,41,26,174,229,120,39,206,232,60,118,60,45,52,181,68,97,203,177,227,121,86,91,246,92,51,11,205,224,65,88,252,151,243,240,230,203,213,193,193,116,150,250,168,67,224,21,37,1,21,189,117,204,67,62,51,170,77,88,32,169,186,141,248,226,150,5,116,66,240,189,126,201,251,176,62,0,16,84,205,68,106,244,199,193,117,192,230,229,250,77,66,123,17,49,133,106,149,249,143,43,80,60,179,93,248,221,190,31,157,63,192,114,97,79,103,113,12,19,173,155,237,9,100,43,123,8,135,235,6,124,248,254,123,232,102,177,125,54,236,230,160,4,73,37,67,66,109,18,199,16,204,132,214,124,246,177,235,154,182,41,23,73,231,230,0,160,73,66,182,180,135,80,96,202,86,182,11,9,254,76,99,186,4,166,104,34,109,159,166,138,10,61,14,224,122,98,116,167,90,101,116,220,49,47,29,224,169,31,51,255,113,124,184,166,115,84,148,109,142,244,244,183,239,230,253,188,196,169,232,82,217,50,38,138,218,35,215,45,64,3,92,31,174,181,222,119,38,68,200,227,170,119,100,159,118,96,80,224,31,148,15,141,41,104,98,241,199,246,32,36,153,189,180,71,32,105,60,181,165,18,84,249,17,196,225,165,249,126,90,227,106,140,23,52,38,138,205,41,52,0,117,110,42,84,59,144,53,57,83,161,220,129,5,224,90,102,36,109,207,59,129,205,249,199,60,12,105,128,102,152,200,75,56,92,163,92,229,13,252,109,10,34,22,4,52,69,116,147,152,251,143,248,16,25,244,11,59,91,234,239,161,29,10,178,178,135,174,219,1,34,24,177,205,152,113,71,137,25,109,77,77,115,221,24,196,28,20,83,49,106,121,45,222,29,96,62,79,199,229,154,24,153,207,27,107,93,126,169,217,52,104,175,146,254,131,63,95,174,14,242,230,62,42,5,99,61,19,177,217,47,197,70,49,118,247,45,153,191,97,233,35,140,161,183,214,36,89,154,20,11,34,129,142,196,76,196,121,191,178,199,133,56,23,136,137,238,51,238,252,237,112,141,15,121,167,100,154,121,135,241,24,135,195,143,208,157,132,197,10,156,184,102,61,38,241,140,218,167,174,11,161,224,179,172,11,151,208,213,223,53,39,207,92,23,34,62,167,226,178,221,215,124,43,249,125,82,14,206,141,40,25,113,56,6,193,103,105,64,3,59,9,32,179,135,80,138,65,76,73,192,210,208,62,133,41,79,149,45,105,194,38,60,14,154,251,1,231,93,109,132,133,125,10,184,25,42,134,31,26,246,228,37,211,43,174,127,185,250,138,214,153,51,30,83,101,123,56,5,105,227,36,98,178,106,60,218,60,163,2Line truncated
static const unsigned char v6[] = {45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,66,67,84,67,66,115,65,73,74,65,75,57,119,98,73,68,107,72,110,65,111,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,77,65,48,120,67,122,65,74,66,103,78,86,66,65,89,84,65,107,108,70,77,66,52,88,10,68,84,73,122,77,68,69,121,79,84,73,120,77,106,69,122,79,70,111,88,68,84,77,122,77,68,69,121,78,106,73,120,77,106,69,122,79,70,111,119,68,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,83,85,85,119,87,84,65,84,10,66,103,99,113,104,107,106,79,80,81,73,66,66,103,103,113,104,107,106,79,80,81,77,66,66,119,78,67,65,65,82,122,83,81,83,53,79,72,100,49,55,108,85,101,78,73,43,54,107,112,57,87,89,117,48,99,120,117,69,73,105,47,74,84,10,106,112,104,98,67,109,100,74,68,49,99,85,118,104,109,122,77,57,47,112,104,118,74,84,57,107,97,49,48,90,57,116,111,90,104,103,110,66,113,48,111,48,120,102,84,81,52,106,67,49,118,119,77,65,111,71,67,67,113,71,83,77,52,57,10,66,65,77,67,65,48,103,65,77,69,85,67,73,81,67,101,48,84,50,69,48,71,79,105,86,101,57,75,119,118,73,69,80,101,88,49,74,49,74,48,84,55,84,78,97,99,103,82,48,89,97,51,51,72,86,57,86,103,73,103,78,118,100,110,10,97,69,87,105,66,112,49,120,115,104,115,52,105,122,54,87,98,112,120,114,83,49,73,72,117,99,114,113,107,90,117,74,76,102,78,90,71,90,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0};
static const unsigned char v7[] = {45,45,45,45,45,66,69,71,73,78,32,69,67,32,80,82,73,86,65,84,69,32,75,69,89,45,45,45,45,45,10,77,72,99,67,65,81,69,69,73,67,66,122,51,72,79,107,81,76,80,66,68,116,100,107,110,113,67,55,107,49,80,78,115,87,106,54,72,102,104,121,78,66,53,77,101,110,102,106,109,113,105,111,111,65,111,71,67,67,113,71,83,77,52,57,10,65,119,69,72,111,85,81,68,81,103,65,69,99,48,107,69,117,84,104,51,100,101,53,86,72,106,83,80,117,112,75,102,86,109,76,116,72,77,98,104,67,73,118,121,85,52,54,89,87,119,112,110,83,81,57,88,70,76,52,90,115,122,80,102,10,54,89,98,121,85,47,90,71,116,100,71,102,98,97,71,89,89,74,119,97,116,75,78,77,88,48,48,79,73,119,116,98,56,65,61,61,10,45,45,45,45,45,69,78,68,32,69,67,32,80,82,73,86,65,84,69,32,75,69,89,45,45,45,45,45,10,0};
static const struct packed_file {
const char *name;
const unsigned char *data;
size_t size;
time_t mtime;
} packed_files[] = {
{"/web_root/bundle.js.gz", v0, sizeof(v0) - 1, 1710000285},
{"/web_root/components.js.gz", v1, sizeof(v1) - 1, 1713984696},
{"/web_root/history.min.js.gz", v2, sizeof(v2) - 1, 1710000285},
{"/web_root/index.html.gz", v3, sizeof(v3) - 1, 1710000285},
{"/web_root/main.css.gz", v4, sizeof(v4) - 1, 1713984502},
{"/web_root/main.js.gz", v5, sizeof(v5) - 1, 1713984681},
{"/certs/server_cert.pem", v6, sizeof(v6) - 1, 1710000285},
{"/certs/server_key.pem", v7, sizeof(v7) - 1, 1710000285},
{NULL, NULL, 0, 0}
};
static int scmp(const char *a, const char *b) {
while (*a && (*a == *b)) a++, b++;
return *(const unsigned char *) a - *(const unsigned char *) b;
}
const char *mg_unlist(size_t no) {
return packed_files[no].name;
}
const char *mg_unpack(const char *name, size_t *size, time_t *mtime) {
const struct packed_file *p;
for (p = packed_files; p->name != NULL; p++) {
if (scmp(p->name, name) != 0) continue;
if (size != NULL) *size = p->size;
if (mtime != NULL) *mtime = p->mtime;
return (const char *) p->data;
}
return NULL;
};
@@ -1 +0,0 @@
var n,t,e,_,r,o,i,u,l,c={},a=[],s=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function f(n,t){for(var e in t)n[e]=t[e];return n}function p(n){var t=n.parentNode;t&&t.removeChild(n)}function h(t,e,_){var r,o,i,u={};for(i in e)"key"==i?r=e[i]:"ref"==i?o=e[i]:u[i]=e[i];if(arguments.length>2&&(u.children=arguments.length>3?n.call(arguments,2):_),"function"==typeof t&&null!=t.defaultProps)for(i in t.defaultProps)void 0===u[i]&&(u[i]=t.defaultProps[i]);return d(t,u,r,o,null)}function d(n,_,r,o,i){var u={type:n,props:_,key:r,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==i?++e:i};return null==i&&null!=t.vnode&&t.vnode(u),u}function v(){return{current:null}}function m(n){return n.children}function y(n,t){this.props=n,this.context=t}function g(n,t){if(null==t)return n.__?g(n.__,n.__.__k.indexOf(n)+1):null;for(var e;t<n.__k.length;t++)if(null!=(e=n.__k[t])&&null!=e.__e)return e.__e;return"function"==typeof n.type?g(n):null}function b(n){var t,e;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,t=0;t<n.__k.length;t++)if(null!=(e=n.__k[t])&&null!=e.__e){n.__e=n.__c.base=e.__e;break}return b(n)}}function k(n){(!n.__d&&(n.__d=!0)&&r.push(n)&&!C.__r++||o!==t.debounceRendering)&&((o=t.debounceRendering)||i)(C)}function C(){var n,t,e,_,o,i,l,c;for(r.sort(u);n=r.shift();)n.__d&&(t=r.length,_=void 0,o=void 0,l=(i=(e=n).__v).__e,(c=e.__P)&&(_=[],(o=f({},i)).__v=i.__v+1,T(c,i,o,e.__n,void 0!==c.ownerSVGElement,null!=i.__h?[l]:null,_,null==l?g(i):l,i.__h),R(_,i),i.__e!=l&&b(i)),r.length>t&&r.sort(u));C.__r=0}function x(n,t,e,_,r,o,i,u,l,s){var f,p,h,v,y,b,k,C=_&&_.__k||a,x=C.length;for(e.__k=[],f=0;f<t.length;f++)if(null!=(v=e.__k[f]=null==(v=t[f])||"boolean"==typeof v||"function"==typeof v?null:"string"==typeof v||"number"==typeof v||"bigint"==typeof v?d(null,v,null,null,v):Array.isArray(v)?d(m,{children:v},null,null,null):v.__b>0?d(v.type,v.props,v.key,v.ref?v.ref:null,v.__v):v)){if(v.__=e,v.__b=e.__b+1,null===(h=C[f])||h&&v.key==h.key&&v.type===h.type)C[f]=void 0;else for(p=0;p<x;p++){if((h=C[p])&&v.key==h.key&&v.type===h.type){C[p]=void 0;break}h=null}T(n,v,h=h||c,r,o,i,u,l,s),y=v.__e,(p=v.ref)&&h.ref!=p&&(k||(k=[]),h.ref&&k.push(h.ref,null,v),k.push(p,v.__c||y,v)),null!=y?(null==b&&(b=y),"function"==typeof v.type&&v.__k===h.__k?v.__d=l=E(v,l,n):l=U(n,v,h,C,y,l),"function"==typeof e.type&&(e.__d=l)):l&&h.__e==l&&l.parentNode!=n&&(l=g(h))}for(e.__e=b,f=x;f--;)null!=C[f]&&("function"==typeof e.type&&null!=C[f].__e&&C[f].__e==e.__d&&(e.__d=A(_).nextSibling),W(C[f],C[f]));if(k)for(f=0;f<k.length;f++)M(k[f],k[++f],k[++f])}function E(n,t,e){for(var _,r=n.__k,o=0;r&&o<r.length;o++)(_=r[o])&&(_.__=n,t="function"==typeof _.type?E(_,t,e):U(e,_,_,r,_.__e,t));return t}function H(n,t){return t=t||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some((function(n){H(n,t)})):t.push(n)),t}function U(n,t,e,_,r,o){var i,u,l;if(void 0!==t.__d)i=t.__d,t.__d=void 0;else if(null==e||r!=o||null==r.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(r),i=null;else{for(u=o,l=0;(u=u.nextSibling)&&l<_.length;l+=1)if(u==r)break n;n.insertBefore(r,o),i=o}return void 0!==i?i:r.nextSibling}function A(n){var t,e,_;if(null==n.type||"string"==typeof n.type)return n.__e;if(n.__k)for(t=n.__k.length-1;t>=0;t--)if((e=n.__k[t])&&(_=A(e)))return _;return null}function P(n,t,e,_,r){var o;for(o in e)"children"===o||"key"===o||o in t||N(n,o,null,e[o],_);for(o in t)r&&"function"!=typeof t[o]||"children"===o||"key"===o||"value"===o||"checked"===o||e[o]===t[o]||N(n,o,t[o],e[o],_)}function S(n,t,e){"-"===t[0]?n.setProperty(t,null==e?"":e):n[t]=null==e?"":"number"!=typeof e||s.test(t)?e:e+"px"}function N(n,t,e,_,r){var o;n:if("style"===t)if("string"==typeof e)n.style.cssText=e;else{if("string"==typeof _&&(n.style.cssText=_=""),_)for(t in _)e&&t in e||S(n.style,t,"");if(e)for(t in e)_&&e[t]===_[t]||S(n.style,t,e[t])}else if("o"===t[0]&&"n"===t[1])o=t!==(t=t.replace(/Capture$/,"")),t=t.toLowerCase()in n?t.toLowerCase().slice(2):t.slice(2),n.l||(n.l={}),n.l[t+o]=e,e?_||n.addEventListener(t,o?D:w,o):n.removeEventListener(t,o?D:w,o);else if("dangerouslySetInnerHTML"!==t){if(r)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==t&&"height"!==t&&"href"!==t&&"list"!==t&&"form"!==t&&"tabIndex"!==t&&"download"!==t&&t in n)try{n[t]=null==e?"":e;break n}catch(n){}"function"==typeof e||(null==e||!1===e&&"-"!==t[4]?n.removeAttribute(t):n.setAttribute(t,e))}}function w(n){return this.l[n.type+!1](t.event?t.event(n):n)}function D(n){return this.l[n.type+!0](t.event?t.event(n):n)}function T(n,e,_,r,o,i,u,l,c){var a,s,p,h,d,v,g,b,k,C,E,H,U,A,P,S=e.type;if(void 0!==e.constructor)return null;null!=_.__h&&(c=_.__h,l=e.__e=_.__e,e.__h=null,i=[l]),(a=t.__b)&&a(e);try{n:if("function"==typeof S){if(b=e.props,k=(a=S.contextType)&&r[a.__c],C=a?k?k.props.value:a.__:r,_.__c?g=(s=e.__c=_.__c).__=s.__E:("prototype"in S&&S.prototype.render?e.__c=s=new S(b,C):(e.__c=s=new y(b,C),s.constructor=S,s.rLine truncated
@@ -1,356 +0,0 @@
'use strict';
import { h, render, useState, useEffect, useRef, html, Router } from './bundle.js';
// Helper function that returns a promise that resolves after delay
const Delay = (ms, val) => new Promise(resolve => setTimeout(resolve, ms, val));
export const Icons = {
heart: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>`,
downArrowBox: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15M9 12l3 3m0 0l3-3m-3 3V2.25" /> </svg>`,
upArrowBox: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15" /> </svg>`,
cog: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>`,
settingsH: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" /> </svg>`,
settingsV: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6 13.5V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m12-3V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m-6-9V3.75m0 3.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 9.75V10.5" /> </svg>`,
scan: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 3.75H6A2.25 2.25 0 003.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0120.25 6v1.5m0 9V18A2.25 2.25 0 0118 20.25h-1.5m-9 0H6A2.25 2.25 0 013.75 18v-1.5M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg> `,
desktop: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25" /> </svg>`,
alert: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5" /> </svg>`,
bell: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5" /> </svg>`,
refresh: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" /> </svg> `,
bars4: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 5.25h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5" /> </svg>`,
bars3: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> </svg>`,
logout: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12.75 15l3-3m0 0l-3-3m3 3h-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>`,
save: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>`,
email: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /> </svg>`,
expand: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" /> </svg>`,
shrink: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" /> </svg>`,
ok: props => html`<svg class=${props.class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>`,
fail: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>`,
upload: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" /> </svg> `,
download: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" /> </svg> `,
bolt: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>`,
home: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> </svg> `,
link: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244" /> </svg> `,
shield: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /> </svg> `,
barsdown: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0l-3.75-3.75M17.25 21L21 17.25" /> </svg> `,
arrowdown: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75" /> </svg> `,
arrowup: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 19.5v-15m0 0l-6.75 6.75M12 4.5l6.75 6.75" /> </svg>`,
warn: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`,
info: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" /> </svg>`,
exclamationTriangle: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`,
thumbUp: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z" /> </svg>`,
backward: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M21 16.811c0 .864-.933 1.405-1.683.977l-7.108-4.062a1.125 1.125 0 010-1.953l7.108-4.062A1.125 1.125 0 0121 8.688v8.123zM11.25 16.811c0 .864-.933 1.405-1.683.977l-7.108-4.062a1.125 1.125 0 010-1.953L9.567 7.71a1.125 1.125 0 011.683.977v8.123z" /> </svg>`,
chip: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21m-9-1.5h10.5a2.25 2.25 0 002.25-2.25V6.75a2.25 2.25 0 00-2.25-2.25H6.75A2.25 2.25 0 004.5 6.75v10.5a2.25 2.25 0 002.25 2.25zm.75-12h9v9h-9v-9z" /> </svg>`,
camera: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6.827 6.175A2.31 2.31 0 015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM18.75 10.5h.008v.008h-.008V10.5z" /> </svg>`,
arrows: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" /> </svg>`,
doc: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /></svg>`,
};
export const tipColors = {
green: 'bg-green-100 text-green-900 ring-green-300',
yellow: 'bg-yellow-100 text-yellow-900 ring-yellow-300',
red: 'bg-red-100 text-red-900 ring-red-300',
};
export function Button({title, onclick, disabled, cls, icon, ref, colors, hovercolor, disabledcolor}) {
const [spin, setSpin] = useState(false);
const cb = function(ev) {
const res = onclick ? onclick() : null;
if (res && typeof (res.catch) === 'function') {
setSpin(true);
res.catch(() => false).then(() => setSpin(false));
}
};
if (!colors) colors = 'bg-blue-600 hover:bg-blue-500 disabled:bg-blue-400';
return html`
<button type="button" class="inline-flex justify-center items-center gap-2 rounded px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm ${colors} ${cls}"
ref=${ref} onclick=${cb} disabled=${disabled || spin} >
${title}
<${spin ? Icons.refresh : icon} class="w-4 ${spin ? 'animate-spin' : ''}" />
<//>`
};
export function Notification({ok, text, close}) {
const closebtn = useRef(null);
const from = 'translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2';
const to = 'translate-y-0 opacity-100 sm:translate-x-0';
const [tr, setTr] = useState(from);
useEffect(function() {
setTr(to);
setTimeout(ev => closebtn && closebtn.current.click && closebtn.current.click(), 1500);
}, []);
const onclose = ev => { setTr(from); setTimeout(close, 300); };
return html`
<div aria-live="assertive" class="z-10 pointer-events-none absolute inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6">
<div class="flex w-full flex-col items-center space-y-4 sm:items-end">
<div class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 transform ease-out duration-300 transition ${tr}">
<div class="p-4">
<div class="flex items-start">
<div class="flex-shrink-0">
<${ok ? Icons.ok : Icons.fail} class="h-6 w-6 ${ok ? 'text-green-400' : 'text-red-400'}" />
<//>
<div class="ml-3 w-0 flex-1 pt-0.5">
<p class="text-sm font-medium text-gray-900">${text}</p>
<p class="hidden mt-1 text-sm text-gray-500">Anyone with a link can now view this file.</p>
<//>
<div class="ml-4 flex flex-shrink-0">
<button type="button" ref=${closebtn} onclick=${onclose} class="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none">
<span class="sr-only">Close</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
<//>
<//>
<//>
<//>
<//>
<//>
<//>
<//>`;
};
export function Login({loginFn, logoIcon, title, tipText}) {
const [user, setUser] = useState('');
const [pass, setPass] = useState('');
const onsubmit = function(ev) {
const authhdr = 'Basic ' + btoa(user + ':' + pass);
const headers = {Authorization: authhdr};
return fetch('api/login', {headers}).then(loginFn).finally(r => setPass(''));
};
return html`
<div class="h-screen flex items-center justify-center bg-slate-200">
<div class="border rounded bg-white w-96 p-5">
<div class="my-5 py-2 flex items-center justify-center gap-x-4">
<${logoIcon} class="h-12 stroke-cyan-600 stroke-1" />
<h1 class="font-bold text-xl">${title || 'Login'}<//>
<//>
<div class="my-3">
<label class="block text-sm mb-1 dark:text-white">Username</label>
<input type="text" autocomplete="current-user" required
class="font-normal bg-white rounded border border-gray-300 w-full
flex-1 py-0.5 px-2 text-gray-900 placeholder:text-gray-400
focus:outline-none sm:text-sm sm:leading-6 disabled:cursor-not-allowed
disabled:bg-gray-100 disabled:text-gray-500"
oninput=${ev => setUser(ev.target.value)} value=${user} />
<//>
<div class="my-3">
<label class="block text-sm mb-1 dark:text-white">Password</label>
<input type="password" autocomplete="current-password" required
class="font-normal bg-white rounded border border-gray-300 w-full flex-1 py-0.5 px-2 text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-500"
oninput=${ev => setPass(ev.target.value)}
value=${pass} onchange=${onsubmit} />
<//>
<div class="mt-7">
<${Button} title="Sign In" icon=${Icons.logout} onclick=${onsubmit} cls="flex w-full justify-center" />
<//>
<div class="mt-5 text-slate-400 text-xs">${tipText}<//>
<//>
<//>`;
};
export function Colored({icon, text, colors}) {
colors ||= 'bg-slate-100 text-slate-900';
return html`
<span class="inline-flex items-center gap-1.5 py-0.5">
${icon && html`<${icon} class="w-5 h-5" />`}
<span class="inline-block font-medium rounded-md px-2 py-1 text-xs ring-1 ring-inset ${colors}">${text}<//>
<//>`;
};
export function Stat({title, text, tipText, tipIcon, tipColors, colors}) {
return html`
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-slate-900 dark:border-gray-800">
<div class="overflow-auto rounded-lg bg-white px-4 py-2 ">
<div class="flex items-center gap-x-2">
<p class="text-sm truncate text-gray-500 font-medium"> ${title} </p>
<//>
<div class="mt-1 flex items-center gap-x-2">
<h3 class="text-xl truncate font-semibold tracking-tight ${colors || 'text-gray-800 dark:text-gray-200'}">
${text}
<//>
<span class="flex items-center ${tipText || 'hidden'}">
<${Colored} text=${tipText} icon=${tipIcon} colors=${tipColors} />
<//>
<//>
<//>
<//>`;
};
export function TextValue({value, setfn, disabled, placeholder, type, addonRight, addonLeft, attr, min, max, step, mult}) {
const [bg, setBg] = useState('bg-white');
useEffect(() => { if (type == 'number') checkval(+min, +max, +value); }, []);
step ||= '1', mult ||= 1;
const checkval = function(min, max, v) {
setBg('bg-white');
if (min && v < min) setBg('bg-red-100 border-red-200');
if (max && v > max) setBg('bg-red-100 border-red-200');
};
const m = step.match(/^.+\.(.+)/);
const digits = m ? m[1].length : 0;
const onchange = ev => {
let v = ev.target.value;
if (type == 'number') {
checkval(+min, +max, +v);
v = +(parseFloat(v) / mult).toFixed(digits);
}
setfn(v);
};
if (type == 'number') value = +(value * mult).toFixed(digits);
return html`
<div class="flex w-full items-center rounded border shadow-sm ${bg}">
${addonLeft && html`<span class="inline-flex font-normal truncate py-1 border-r bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs">${addonLeft}<//>` }
<input type=${type || 'text'} disabled=${disabled} value=${value}
step=${step} min=${min} max=${max}
onchange=${onchange} ...${attr}
class="${bg} font-normal text-sm rounded w-full flex-1 py-0.5 px-2 text-gray-700 placeholder:text-gray-400 focus:outline-none disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-500" placeholder=${placeholder} />
${addonRight && html`<span class="inline-flex font-normal truncate py-1 border-l bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs overflow-scroll" style="min-width: 50%;">${addonRight}<//>` }
<//>`;
};
export function SelectValue({value, setfn, options, disabled}) {
const toInt = x => x == parseInt(x) ? parseInt(x) : x;
const onchange = ev => setfn(toInt(ev.target.value));
return html`
<select onchange=${onchange} class="w-full rounded font-normal border py-0.5 px-1 text-gray-600 focus:outline-none text-sm disabled:cursor-not-allowed" disabled=${disabled}>
${options.map(v => html`<option value=${v[0]} selected=${v[0] == value}>${v[1]}<//>`) }
<//>`;
};
export function SwitchValue({value, setfn}) {
const onclick = ev => setfn(!value);
const bg = !!value ? 'bg-blue-600' : 'bg-gray-200';
const tr = !!value ? 'translate-x-5' : 'translate-x-0';
return html`
<button type="button" onclick=${onclick} class="${bg} inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-0 ring-0" role="switch" aria-checked=${!!value}>
<span aria-hidden="true" class="${tr} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 focus:ring-0 transition duration-200 ease-in-out"></span>
</button>`;
};
export function Setting(props) {
let input = TextValue;
if (props.type == 'switch') input = SwitchValue;
if (props.type == 'select') input = SelectValue;
return html`
<div class=${props.cls || 'grid grid-cols-2 gap-2 my-1'}>
<label class="flex items-center text-sm text-gray-700 mr-2 font-medium ${props.title || 'hidden'}">${props.title}<//>
<div class="flex items-center">${h(input, props)}<//>
<//>`;
};
export function Pagination({ totalItems, itemsPerPage, currentPage, setPageFn, colors }) {
const totalPages = Math.ceil(totalItems / itemsPerPage);
const maxPageRange = 2;
const lessThanSymbol = "<";
const greaterThanSymbol = ">";
const whiteSpace = " ";
const itemcls = 'relative inline-flex items-center px-3 py-1 text-sm focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-0 focus-visible:outline-blue-600';
colors ||= 'bg-blue-600';
const PageItem = ({ page, isActive }) => (
html`<a
onClick=${() => setPageFn(page)}
class="${itemcls} ${isActive ? `${colors} text-white` : 'cursor-pointer text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50'}"
>
${page}
</a>`
);
return html`
<div class="flex items-center justify-between bg-white px-3 py-2">
<div class="sm:flex sm:flex-1 sm:items-center sm:justify-between space-x-4 whitespace-nowrap select-none">
<p class="text-sm text-slate-500 font-medium">
showing <span class="font-bold text-slate-700">${(currentPage - 1) * itemsPerPage + 1}</span> - <span class="font-medium">${Math.min(currentPage * itemsPerPage, totalItems)}</span> of ${whiteSpace}
<span class="font-bold text-slate-700">${totalItems}</span> results
</p>
<div>
<nav class="isolate inline-flex -space-x-px rounded-md" aria-label="Pagination">
<a
onClick=${() => setPageFn(Math.max(currentPage - 1, 1))}
class="relative inline-flex px-3 items-center text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 ${currentPage != 1 ? 'cursor-pointer' : ''} focus:z-20 focus:outline-offset-0">
${lessThanSymbol}
</a>
<${PageItem} page=${1} isActive=${currentPage === 1} />
${currentPage > maxPageRange + 2 ? html`<span class="${itemcls} ring-1 ring-inset ring-gray-300 text-slate-300">...</span>` : ''}
${Array.from({length: Math.min(totalPages, maxPageRange * 2 + 1)}, (_, i) => Math.max(2, currentPage - maxPageRange) + i).map(page => page > 1 && page < totalPages && html`<${PageItem} page=${page} isActive=${currentPage === page} />`)}
${currentPage < totalPages - (maxPageRange + 1) ? html`<span class="${itemcls} ring-1 ring-inset ring-gray-300 text-slate-300">...</span>` : ''}
${totalPages > 1 ? html`<${PageItem} page=${totalPages} isActive=${currentPage === totalPages} />` : ''}
<a
onClick=${() => setPageFn(Math.min(currentPage + 1, totalPages))}
class="relative inline-flex px-3 items-center text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 ${currentPage != totalPages ? 'cursor-pointer' : ''} focus:z-20 focus:outline-offset-0">
${greaterThanSymbol}
</a>
</nav>
</div>
</div>
</div>`;
};
export function UploadFileButton(props) {
const [upload, setUpload] = useState(null); // Upload promise
const [status, setStatus] = useState(''); // Current upload status
const btn = useRef(null);
const input = useRef(null);
// Send a large file chunk by chunk
const sendFileData = function(url, fileName, fileData, chunkSize) {
return new Promise(function(resolve, reject) {
const finish = ok => {
setUpload(null);
const res = props.onupload ? props.onupload(ok, fileName, fileData.length) : null;
if (res && typeof (res.catch) === 'function') {
res.catch(() => false).then(() => ok ? resolve() : reject());
} else {
ok ? resolve() : reject();
}
};
const sendChunk = function(offset) {
var chunk = fileData.subarray(offset, offset + chunkSize) || '';
var opts = {method: 'POST', body: chunk};
var fullUrl = url + '?offset=' + offset +
'&total=' + fileData.length +
'&name=' + encodeURIComponent(fileName);
var ok;
setStatus('Uploading ' + fileName + ', bytes ' + offset + '..' +
(offset + chunk.length) + ' of ' + fileData.length);
fetch(fullUrl, opts)
.then(function(res) {
if (res.ok && chunk.length > 0) sendChunk(offset + chunk.length);
ok = res.ok;
return res.text();
})
.then(function(text) {
if (!ok) setStatus('Error: ' + text), finish(ok); // Fail
if (chunk.length > 0) return; // More chunks to send
setStatus(x => x + '. Done, resetting device...');
finish(ok); // All chunks sent
});
};
sendChunk(0);
});
};
const onchange = function(ev) {
if (!ev.target.files[0]) return;
let r = new FileReader(), f = ev.target.files[0];
r.readAsArrayBuffer(f);
r.onload = function() {
setUpload(sendFileData(props.url, f.name, new Uint8Array(r.result), 2048));
ev.target.value = '';
ev.preventDefault();
btn && btn.current.base.click();
};
};
const onclick = function(ev) {
let fn; setUpload(x => fn = x);
if (!fn) input.current.click(); // No upload in progress, show file dialog
return fn;
};
return html`
<div class="inline-flex flex-col ${props.class}">
<input class="hidden" type="file" ref=${input} onchange=${onchange} accept=${props.accept} />
<${Button} title=${props.title} icon=${Icons.download} onclick=${onclick} ref=${btn} colors=${props.colors} />
<div class="pt-2 text-sm text-slate-400 ${status || 'hidden'}">${status}<//>
<//>`;
};
@@ -1 +0,0 @@
!function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.History=n():t.History=n()}(this,function(){return function(t){function n(o){if(e[o])return e[o].exports;var r=e[o]={exports:{},id:o,loaded:!1};return t[o].call(r.exports,r,r.exports,n),r.loaded=!0,r.exports}var e={};return n.m=t,n.c=e,n.p="",n(0)}([function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0,n.createPath=n.parsePath=n.locationsAreEqual=n.createLocation=n.createMemoryHistory=n.createHashHistory=n.createBrowserHistory=void 0;var r=e(2);Object.defineProperty(n,"createLocation",{enumerable:!0,get:function(){return r.createLocation}}),Object.defineProperty(n,"locationsAreEqual",{enumerable:!0,get:function(){return r.locationsAreEqual}});var i=e(1);Object.defineProperty(n,"parsePath",{enumerable:!0,get:function(){return i.parsePath}}),Object.defineProperty(n,"createPath",{enumerable:!0,get:function(){return i.createPath}});var a=e(7),c=o(a),u=e(8),s=o(u),f=e(9),l=o(f);n.createBrowserHistory=c.default,n.createHashHistory=s.default,n.createMemoryHistory=l.default},function(t,n){"use strict";n.__esModule=!0;n.addLeadingSlash=function(t){return"/"===t.charAt(0)?t:"/"+t},n.stripLeadingSlash=function(t){return"/"===t.charAt(0)?t.substr(1):t},n.stripPrefix=function(t,n){return 0===t.indexOf(n)?t.substr(n.length):t},n.stripTrailingSlash=function(t){return"/"===t.charAt(t.length-1)?t.slice(0,-1):t},n.parsePath=function(t){var n=t||"/",e="",o="",r=n.indexOf("#");r!==-1&&(o=n.substr(r),n=n.substr(0,r));var i=n.indexOf("?");return i!==-1&&(e=n.substr(i),n=n.substr(0,i)),n=decodeURI(n),{pathname:n,search:"?"===e?"":e,hash:"#"===o?"":o}},n.createPath=function(t){var n=t.pathname,e=t.search,o=t.hash,r=encodeURI(n||"/");return e&&"?"!==e&&(r+="?"===e.charAt(0)?e:"?"+e),o&&"#"!==o&&(r+="#"===o.charAt(0)?o:"#"+o),r}},function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0,n.locationsAreEqual=n.createLocation=void 0;var r=Object.assign||function(t){for(var n=1;n<arguments.length;n++){var e=arguments[n];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t},i=e(10),a=o(i),c=e(11),u=o(c),s=e(1);n.createLocation=function(t,n,e,o){var i=void 0;return"string"==typeof t?(i=(0,s.parsePath)(t),i.state=n):(i=r({},t),void 0===i.pathname&&(i.pathname=""),i.search?"?"!==i.search.charAt(0)&&(i.search="?"+i.search):i.search="",i.hash?"#"!==i.hash.charAt(0)&&(i.hash="#"+i.hash):i.hash="",void 0!==n&&void 0===i.state&&(i.state=n)),i.key=e,o&&(i.pathname?"/"!==i.pathname.charAt(0)&&(i.pathname=(0,a.default)(i.pathname,o.pathname)):i.pathname=o.pathname),i},n.locationsAreEqual=function(t,n){return t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash&&t.key===n.key&&(0,u.default)(t.state,n.state)}},function(t,n,e){"use strict";var o=function(){};t.exports=o},function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0;var r=e(3),i=(o(r),function(){var t=null,n=function(n){return t=n,function(){t===n&&(t=null)}},e=function(n,e,o,r){if(null!=t){var i="function"==typeof t?t(n,e):t;"string"==typeof i?"function"==typeof o?o(i,r):r(!0):r(i!==!1)}else r(!0)},o=[],r=function(t){var n=!0,e=function(){n&&t.apply(void 0,arguments)};return o.push(e),function(){n=!1,o=o.filter(function(t){return t!==e})}},i=function(){for(var t=arguments.length,n=Array(t),e=0;e<t;e++)n[e]=arguments[e];o.forEach(function(t){return t.apply(void 0,n)})};return{setPrompt:n,confirmTransitionTo:e,appendListener:r,notifyListeners:i}});n.default=i},function(t,n){"use strict";n.__esModule=!0;n.canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement),n.addEventListener=function(t,n,e){return t.addEventListener?t.addEventListener(n,e,!1):t.attachEvent("on"+n,e)},n.removeEventListener=function(t,n,e){return t.removeEventListener?t.removeEventListener(n,e,!1):t.detachEvent("on"+n,e)},n.getConfirmation=function(t,n){return n(window.confirm(t))},n.supportsHistory=function(){var t=window.navigator.userAgent;return(t.indexOf("Android 2.")===-1&&t.indexOf("Android 4.0")===-1||t.indexOf("Mobile Safari")===-1||t.indexOf("Chrome")!==-1||t.indexOf("Windows Phone")!==-1)&&(window.history&&"pushState"in window.history)},n.supportsPopStateOnHashChange=function(){return window.navigator.userAgent.indexOf("Trident")===-1},n.supportsGoWithoutReloadUsingHash=function(){return window.navigator.userAgent.indexOf("Firefox")===-1},n.isExtraneousPopstateEvent=function(t){return void 0===t.state&&navigator.userAgent.indexOf("CriOS")===-1}},function(t,n,e){"use strict";var o=function(t,n,e,o,r,i,a,c){if(!t){var u;if(void 0===n)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var s=[e,o,r,i,a,c],f=0;u=new Error(n.replace(/%s/g,function(){return s[f++]})),u.name="InLine truncated
@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en" class="h-full bg-white">
<head>
<title></title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='currentColor'> <path stroke-linecap='round' stroke-linejoin='round' d='M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0' /> </svg>" />
<link href="main.css" rel="stylesheet" />
</head>
<body class="min-h-screen"></body>
<script src="history.min.js"></script>
<script type="module" src="main.js"></script>
</html>
@@ -1 +0,0 @@
/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter var,Arial,Helvetica,sans-serif;font-feature-settings:"cv11","ss01";font-variation-settings:"opsz" 32}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.left-0{left:0}.right-auto{right:auto}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.col-span-2{grid-column:span 2/span 2}.m-4{margin:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.mb-1{margin-bottom:.25rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-7{margin-top:1.75rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.h-screen{height:100vh}.min-h-screen{min-height:100vh}.w-0{width:0}.w-11{width:2.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-96{width:24rem}.w-full{width:100%}.min-w-full{min-width:100%}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.grow-0{flex-grow:0}.basis-\[30px\]{flex-basis:30px}.border-separate{border-collaLine truncated
@@ -1,376 +0,0 @@
// NOTE: API calls must start with 'api/' in order to serve the app at any URI
'use strict';
import { h, render, useState, useEffect, useRef, html, Router } from './bundle.js';
import { Icons, Login, Setting, Button, Stat, tipColors, Colored, Notification, Pagination, UploadFileButton } from './components.js';
const Logo = props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12.87 12.85"><defs><style>.ll-cls-1{fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:0.5px;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="ll-cls-1" d="M12.62,1.82V8.91A1.58,1.58,0,0,1,11,10.48H4a1.44,1.44,0,0,1-1-.37A.69.69,0,0,1,2.84,10l-.1-.12a.81.81,0,0,1-.15-.48V5.57a.87.87,0,0,1,.86-.86H4.73V7.28a.86.86,0,0,0,.86.85H9.42a.85.85,0,0,0,.85-.85V3.45A.86.86,0,0,0,10.13,3,.76.76,0,0,0,10,2.84a.29.29,0,0,0-.12-.1,1.49,1.49,0,0,0-1-.37H2.39V1.82A1.57,1.57,0,0,1,4,.25H11A1.57,1.57,0,0,1,12.62,1.82Z"/><path class="ll-cls-1" d="M10.48,10.48V11A1.58,1.58,0,0,1,8.9,12.6H1.82A1.57,1.57,0,0,1,.25,11V3.94A1.57,1.57,0,0,1,1.82,2.37H8.9a1.49,1.49,0,0,1,1,.37l.12.1a.76.76,0,0,1,.11.14.86.86,0,0,1,.14.47V7.28a.85.85,0,0,1-.85.85H8.13V5.57a.86.86,0,0,0-.85-.86H3.45a.87.87,0,0,0-.86.86V9.4a.81.81,0,0,0,.15.48l.1.12a.69.69,0,0,0,.13.11,1.44,1.44,0,0,0,1,.37Z"/></g></g></svg>`;
function Header({logout, user, setShowSidebar, showSidebar}) {
return html`
<div class="bg-white sticky top-0 z-[48] xw-full border-b py-2 ${showSidebar && 'pl-72'} transition-all duration-300 transform">
<div class="px-2 w-full py-0 my-0 flex items-center">
<button type="button" onclick=${ev => setShowSidebar(v => !v)} class="text-slate-400">
<${Icons.bars3} class="h-6" />
<//>
<div class="flex flex-1 gap-x-4 self-stretch lg:gap-x-6">
<div class="relative flex flex-1"><//>
<div class="flex items-center gap-x-4 lg:gap-x-6">
<span class="text-sm text-slate-400">logged in as: ${user}<//>
<div class="hidden lg:block lg:h-4 lg:w-px lg:bg-gray-200" aria-hidden="true"><//>
<${Button} title="Logout" icon=${Icons.logout} onclick=${logout} />
<//>
<//>
<//>
<//>`;
};
function Sidebar({url, show}) {
const NavLink = ({title, icon, href, url}) => html`
<div>
<a href="#${href}" class="${href == url ? 'bg-slate-50 text-blue-600 group' : 'text-gray-700 hover:text-blue-600 hover:bg-gray-50 group'} flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
<${icon} class="w-6 h-6"/>
${title}
<///>
<//>`;
return html`
<div class="bg-violet-100 hs-overlay hs-overlay-open:translate-x-0
-translate-x-full transition-all duration-300 transform
fixed top-0 left-0 bottom-0 z-[60] w-72 bg-white border-r
border-gray-200 overflow-y-auto scrollbar-y
${show && 'translate-x-0'} right-auto bottom-0">
<div class="flex flex-col m-4 gap-y-6">
<div class="flex h-10 shrink-0 items-center gap-x-4 font-bold text-xl text-slate-500">
<${Logo} class="h-full"/> Your Brand
<//>
<div class="flex flex-1 flex-col">
<${NavLink} title="Dashboard" icon=${Icons.home} href="/" url=${url} />
<${NavLink} title="Settings" icon=${Icons.cog} href="/settings" url=${url} />
<${NavLink} title="Firmware Update" icon=${Icons.download} href="/update" url=${url} />
<${NavLink} title="Events" icon=${Icons.alert} href="/events" url=${url} />
<//>
<//>
<//>`;
};
function Events({}) {
const [events, setEvents] = useState([]);
const [page, setPage] = useState(1);
const refresh = () =>
fetch('api/events/get', {
method: 'POST', body: JSON.stringify({page: page}),
}).then(r => r.json())
.then(r => setEvents(r));
useEffect(refresh, [page]);
useEffect(() => {
setPage(JSON.parse(localStorage.getItem('page')));
}, []);
useEffect(() => {
localStorage.setItem('page', page.toString());
}, [page]);
const Th = props => html`<th scope="col" class="sticky top-0 z-10 border-b border-slate-300 bg-white bg-opacity-75 py-1.5 px-4 text-left text-sm font-semibold text-slate-900 backdrop-blur backdrop-filter">${props.title}</th>`;
const Td = props => html`<td class="whitespace-nowrap border-b border-slate-200 py-2 px-4 pr-3 text-sm text-slate-900">${props.text}</td>`;
const Prio = ({prio}) => {
const text = ['high', 'medium', 'low'][prio];
const colors = [tipColors.red, tipColors.yellow, tipColors.green][prio];
return html`<${Colored} colors=${colors} text=${text} />`;
};
const Event = ({e}) => html`
<tr>
<${Td} text=${['power', 'hardware', 'tier3', 'tier4'][e.type]} />
<${Td} text=${html`<${Prio} prio=${e.prio}/>`} />
<${Td} text=${e.time ? (new Date(e.time * 1000)).toLocaleString() : '1970-01-01'} />
<${Td} text=${e.text} />
<//>`;
return html`
<div class="m-4 divide-y divide-gray-200 overflow-auto rounded bg-white">
<div class="font-semibold flex items-center text-gray-600 px-3 justify-between whitespace-nowrap">
<div class="font-semibold flex items-center text-gray-600">
<div class="mr-4">EVENT LOG</div>
</div>
<${Pagination} currentPage=${page} setPageFn=${setPage} totalItems=400 itemsPerPage=20 />
<//>
<div class="inline-block min-w-full align-middle" style="max-height: 82vh; overflow: auto;">
<table class="min-w-full border-separate border-spacing-0">
<thead>
<tr>
<${Th} title="Type" />
<${Th} title="Prio" />
<${Th} title="Time" />
<${Th} title="Description" />
</tr>
</thead>
<tbody>
${(events.arr ? events.arr : []).map(e => h(Event, {e}))}
</tbody>
</table>
<//>
<//>`;
};
function Chart({data}) {
const n = data.length /* entries */, w = 20 /* entry width */, ls = 15/* left space */;
const h = 100 /* graph height */, yticks = 5 /* Y axis ticks */, bs = 10 /* bottom space */;
const ymax = 25;
const yt = i => (h - bs) / yticks * (i + 1);
const bh = p => (h - bs) * p / 100; // Bar height
const by = p => (h - bs) - bh(p);
const range = (start, size, step) => Array.from({length: size}, (_, i) => i * (step || 1) + start);
// console.log(ds);
return html`
<div class="my-4 divide-y divide-gray-200 overflow-auto rounded bg-white">
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
Temperature, last 24h
<//>
<div class="relative">
<svg class="bg-yellow-x50 w-full p-4" viewBox="0 0 ${n*w+ls} ${h}">
${range(0, yticks).map(i => html`
<line x1=0 y1=${yt(i)} x2=${ls+n*w} y2=${yt(i)} stroke-width=0.3 class="stroke-slate-300" stroke-dasharray="1,1" />
<text x=0 y=${yt(i)-2} class="text-[6px] fill-slate-400">${ymax-ymax/yticks*(i+1)}<//>
`)}
${range(0, n).map(x => html`
<rect x=${ls+x*w} y=${by(data[x]*100/ymax)} width=12 height=${bh(data[x]*100/ymax)} rx=2 class="fill-cyan-500" />
<text x=${ls+x*w} y=100 class="text-[6px] fill-slate-400">${x*2}:00<//>
`)}
<//>
<//>
<//>`;
};
function DeveloperNote({text, children}) {
return html`
<div class="flex p-4 gap-2">
<div class="text-sm text-slate-500">
<div class="flex items-center">
<${Icons.info} class="self-start basis-[30px] grow-0 shrink-0 text-green-600 mr-2" />
<div class="font-semibold">Developer Note<//>
<//>
${(text || '').split('.').map(v => html` <p class="my-2 ">${v}<//>`)}
${children}
<//>
<//>`;
};
function Main({}) {
const [stats, setStats] = useState(null);
const refresh = () => fetch('api/stats/get').then(r => r.json()).then(r => setStats(r));
useEffect(refresh, []);
if (!stats) return '';
return html`
<div class="p-2">
<div class="p-4 sm:p-2 mx-auto grid grid-cols-2 lg:grid-cols-4 gap-4">
<${Stat} title="Temperature" text="${stats.temperature} °C" tipText="good" tipIcon=${Icons.ok} tipColors=${tipColors.green} />
<${Stat} title="Humidity" text="${stats.humidity} %" tipText="warn" tipIcon=${Icons.warn} tipColors=${tipColors.yellow} />
<div class="bg-white col-span-2 border rounded-md shadow-lg" role="alert">
<${DeveloperNote} text="Stats data is received from the Mongoose backend" />
<//>
<//>
<div class="p-4 sm:p-2 mx-auto grid grid-cols-1 lg:grid-cols-2 gap-4">
<${Chart} data=${stats.points} />
<div class="my-4 hx-24 bg-white border rounded-md shadow-lg" role="alert">
<${DeveloperNote}
text="This chart is an SVG image, generated on the fly from the
data returned by the api/stats/get API call" />
<//>
<//>
<//>`;
};
function FirmwareStatus({title, info, children}) {
const state = ['UNAVAILABLE', 'FIRST_BOOT', 'NOT_COMMITTED', 'COMMITTED'][(info.status || 0) % 4];
const valid = info.status > 0;
return html`
<div class="bg-white py-1 divide-y border rounded">
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
${title}
<//>
<div class="px-4 py-2 relative">
<div class="my-1">Status: ${state}<//>
<div class="my-1">CRC32: ${valid ? info.crc32.toString(16) : 'n/a'}<//>
<div class="my-1">Size: ${valid ? info.size : 'n/a'}<//>
<div class="my-1">Flashed at: ${valid ? new Date(info.timestamp * 1000).toLocaleString() : 'n/a'}<//>
${children}
<//>
<//>`;
};
function FirmwareUpdate({}) {
const [info, setInfo] = useState([{}, {}]);
const refresh = () => fetch('api/firmware/status').then(r => r.json()).then(r => setInfo(r));
useEffect(refresh, []);
const oncommit = ev => fetch('api/firmware/commit')
.then(r => r.json())
.then(refresh);
const onreboot = ev => fetch('api/device/reset')
.then(r => r.json())
.then(r => new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000)));
const onrollback = ev => fetch('api/firmware/rollback')
.then(onreboot);
const onerase = ev => fetch('api/device/eraselast').then(refresh);
const onupload = function(ok, name, size) {
if (!ok) return false;
return new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000));
};
return html`
<div class="m-4 gap-4 grid grid-cols-1 lg:grid-cols-3">
<${FirmwareStatus} title="Current firmware image" info=${info[0]}>
<div class="flex flex-wrap gap-2">
<${Button} title="Commit this firmware" onclick=${oncommit}
icon=${Icons.thumbUp} disabled=${info[0].status == 3} cls="w-full" />
<//>
<//>
<${FirmwareStatus} title="Previous firmware image" info=${info[1]}>
<${Button} title="Rollback to this firmware" onclick=${onrollback}
icon=${Icons.backward} disabled=${info[1].status == 0} cls="w-full" />
<//>
<div class="bg-white xm-4 divide-y border rounded flex flex-col">
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
Device control
<//>
<div class="px-4 py-3 flex flex-col gap-2 grow">
<${UploadFileButton}
title="Upload new firmware .bin file" onupload=${onupload}
url="api/firmware/upload" accept=".bin,.uf2" />
<div class="grow"><//>
<${Button} title="Reboot device" onclick=${onreboot} icon=${Icons.refresh} cls="w-full" />
<${Button} title="Erase last sector" onclick=${onerase} icon=${Icons.doc} cls="w-full hidden" />
<//>
<//>
<//>
<div class="m-4 gap-4 grid grid-cols-1 lg:grid-cols-2">
<div class="bg-white border shadow-lg">
<${DeveloperNote}>
<div class="my-2">
Firmware status and other information is stored in the last sector
of flash
<//>
<div class="my-2">
Firmware status can be FIRST_BOOT, UNCOMMITTED or COMMITTED. If no
information is available, it is UNAVAILABLE.
<//>
<div class="my-2">
This GUI loads a firmware file and sends it chunk by chunk to the
device, passing current chunk offset, total firmware size and a file name:
api/firmware/upload?offset=X&total=Y&name=Z
<//>
<//>
<//>
<div class="bg-white border shadow-lg">
<${DeveloperNote}>
<div>
Firmware update mechanism defines 3 API functions that the target
device must implement: mg_ota_begin(), mg_ota_write() and mg_ota_end()
<//>
<div class="my-2">
RESTful API handlers use ota_xxx() API to save firmware to flash.
The last 0-length chunk triggers ota_end() which performs firmware
update using saved firmware image
<//>
<div class="my-2">
<a class="link text-blue-600 underline"
href="https://mongoose.ws/webinars/">Join our free webinar</a> to
get detailed explanations about possible firmware updates strategies
and implementation demo
<//>
<//>
<//>
<//>`;
};
function Settings({}) {
const [settings, setSettings] = useState(null);
const [saveResult, setSaveResult] = useState(null);
const refresh = () => fetch('api/settings/get')
.then(r => r.json())
.then(r => setSettings(r));
useEffect(refresh, []);
const mksetfn = k => (v => setSettings(x => Object.assign({}, x, {[k]: v})));
const onsave = ev => fetch('api/settings/set', {
method: 'post', body: JSON.stringify(settings)
}).then(r => r.json())
.then(r => setSaveResult(r))
.then(refresh);
if (!settings) return '';
const logOptions = [[0, 'Disable'], [1, 'Error'], [2, 'Info'], [3, 'Debug']];
return html`
<div class="m-4 grid grid-cols-1 gap-4 md:grid-cols-2">
<div class="py-1 divide-y border rounded bg-white flex flex-col">
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
Device Settings
<//>
<div class="py-2 px-5 flex-1 flex flex-col relative">
${saveResult && html`<${Notification} ok=${saveResult.status}
text=${saveResult.message} close=${() => setSaveResult(null)} />`}
<${Setting} title="Enable Logs" value=${settings.log_enabled} setfn=${mksetfn('log_enabled')} type="switch" />
<${Setting} title="Log Level" value=${settings.log_level} setfn=${mksetfn('log_level')} type="select" addonLeft="0-3" disabled=${!settings.log_enabled} options=${logOptions}/>
<${Setting} title="Brightness" value=${settings.brightness} setfn=${mksetfn('brightness')} type="number" addonRight="%" />
<${Setting} title="Device Name" value=${settings.device_name} setfn=${mksetfn('device_name')} type="" />
<div class="mb-1 mt-3 flex place-content-end"><${Button} icon=${Icons.save} onclick=${onsave} title="Save Settings" /><//>
<//>
<//>
<div class="bg-white border rounded-md text-ellipsis overflow-auto" role="alert">
<${DeveloperNote}
text="A variety of controls are pre-defined to ease the development:
toggle button, dropdown select, input field with left and right
addons. Device settings are received by calling
api/settings/get API call, which returns settings JSON object.
Clicking on the save button calls api/settings/set
API call" />
<//>
<//>`;
};
const App = function({}) {
const [loading, setLoading] = useState(true);
const [url, setUrl] = useState('/');
const [user, setUser] = useState('');
const [showSidebar, setShowSidebar] = useState(true);
const logout = () => fetch('api/logout').then(r => setUser(''));
const login = r => !r.ok ? setLoading(false) && setUser(null) : r.json()
.then(r => setUser(r.user))
.finally(r => setLoading(false));
useEffect(() => fetch('api/login').then(login), []);
if (loading) return ''; // Show blank page on initial load
if (!user) return html`<${Login} loginFn=${login} logoIcon=${Logo}
title="Device Dashboard Login"
tipText="To login, use: admin/admin, user1/user1, user2/user2" />`; // If not logged in, show login screen
return html`
<div class="h-screen bg-slate-100">
<${Sidebar} url=${url} show=${showSidebar} />
<${Header} logout=${logout} user=${user} showSidebar=${showSidebar} setShowSidebar=${setShowSidebar} />
<div class="${showSidebar && 'pl-72'} transition-all duration-300 transform">
<${Router} onChange=${ev => setUrl(ev.url)} history=${History.createHashHistory()} >
<${Main} default=${true} />
<${Settings} path="settings" />
<${FirmwareUpdate} path="update" />
<${Events} path="events" />
<//>
<//>
<//>`;
};
window.onload = () => render(h(App), document.body);
+43 -8
View File
@@ -2,6 +2,18 @@
#if MG_ARCH == MG_ARCH_WIN32 #if MG_ARCH == MG_ARCH_WIN32
// Avoid name clashing; (macro expansion producing 'defined' has undefined
// behaviour). See config.h for user options
#ifndef MG_ENABLE_WINSOCK
#if (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP) && \
(!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && \
(!defined(MG_ENABLE_FREERTOS_TCP) || !MG_ENABLE_FREERTOS_TCP)
#define MG_ENABLE_WINSOCK 1
#else
#define MG_ENABLE_WINSOCK 0
#endif
#endif
#ifndef _CRT_RAND_S #ifndef _CRT_RAND_S
#define _CRT_RAND_S #define _CRT_RAND_S
#endif #endif
@@ -47,12 +59,14 @@ typedef enum { false = 0, true = 1 } bool;
#else #else
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#if MG_ENABLE_WINSOCK
#include <ws2tcpip.h> #include <ws2tcpip.h>
#endif #endif
#endif
#include <process.h> #include <process.h>
#include <winerror.h> #include <winerror.h>
#include <winsock2.h> #include <winsock2.h> // fix missing macros and types
// For mg_random() // For mg_random()
#if defined(_MSC_VER) && _MSC_VER < 1700 #if defined(_MSC_VER) && _MSC_VER < 1700
@@ -63,6 +77,20 @@ typedef enum { false = 0, true = 1 } bool;
#pragma comment(lib, "advapi32.lib") #pragma comment(lib, "advapi32.lib")
#endif #endif
#if defined(_MSC_VER) && _MSC_VER <= 1200
#ifndef IPPROTO_IP
#define IPPROTO_IP 0
#endif
#ifndef IP_ADD_MEMBERSHIP
struct ip_mreq {
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
#define IP_ADD_MEMBERSHIP 12
#endif
#endif
// Protect from calls like std::snprintf in app code // Protect from calls like std::snprintf in app code
// See https://github.com/cesanta/mongoose/issues/1047 // See https://github.com/cesanta/mongoose/issues/1047
#ifndef __cplusplus #ifndef __cplusplus
@@ -73,25 +101,30 @@ typedef enum { false = 0, true = 1 } bool;
#endif #endif
#endif #endif
#define MG_INVALID_SOCKET INVALID_SOCKET
#define MG_SOCKET_TYPE SOCKET
typedef unsigned long nfds_t; typedef unsigned long nfds_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)
#if MG_ENABLE_WINSOCK
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#endif
#ifndef alloca #ifndef alloca
#define alloca(a) _alloca(a) #define alloca(a) _alloca(a)
#endif #endif
#endif #endif
#define poll(a, b, c) WSAPoll((a), (b), (c))
#define closesocket(x) closesocket(x)
typedef int socklen_t;
#define MG_DIRSEP '\\' #define MG_DIRSEP '\\'
#ifndef MG_PATH_MAX #ifndef MG_PATH_MAX
#define MG_PATH_MAX FILENAME_MAX #define MG_PATH_MAX FILENAME_MAX
#endif #endif
#if MG_ENABLE_WINSOCK
#define MG_INVALID_SOCKET INVALID_SOCKET
#define MG_SOCKET_TYPE SOCKET
#define poll(a, b, c) WSAPoll((a), (b), (c))
#define closesocket(x) closesocket(x)
typedef int socklen_t;
#ifndef SO_EXCLUSIVEADDRUSE #ifndef SO_EXCLUSIVEADDRUSE
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR)) #define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
#endif #endif
@@ -106,13 +139,15 @@ typedef int socklen_t;
#define MG_SOCK_RESET(errcode) \ #define MG_SOCK_RESET(errcode) \
(((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET)) (((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
#endif // MG_ENABLE_WINSOCK
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX) #define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
#define sleep(x) Sleep((x) * 1000) #define sleep(x) Sleep((x) *1000)
#define mkdir(a, b) _mkdir(a) #define mkdir(a, b) _mkdir(a)
#define timegm(x) _mkgmtime(x) #define timegm(x) _mkgmtime(x)
#ifndef S_ISDIR #ifndef S_ISDIR
#define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
#endif #endif
#ifndef MG_ENABLE_DIRLIST #ifndef MG_ENABLE_DIRLIST
+4 -3
View File
@@ -56,7 +56,8 @@
#define MG_ENABLE_MD5 1 #define MG_ENABLE_MD5 1
#endif #endif
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP) // Set MG_ENABLE_WINSOCK=0 for Win32 builds with other external IP stack not
// mentioned in arch_win32.h
#ifndef MG_ENABLE_WINSOCK #ifndef MG_ENABLE_WINSOCK
#define MG_ENABLE_WINSOCK 1 #define MG_ENABLE_WINSOCK 1
#endif #endif
@@ -174,8 +175,8 @@
#define MG_SET_MAC_ADDRESS(mac) #define MG_SET_MAC_ADDRESS(mac)
#endif #endif
#ifndef MG_SET_WIFI_CREDS #ifndef MG_SET_WIFI_CONFIG
#define MG_SET_WIFI_CREDS(ssid, pass) #define MG_SET_WIFI_CONFIG(data)
#endif #endif
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS #ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
+80
View File
@@ -100,6 +100,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
const struct mg_dns_header *h = (struct mg_dns_header *) buf; const struct mg_dns_header *h = (struct mg_dns_header *) buf;
struct mg_dns_rr rr; struct mg_dns_rr rr;
size_t i, n, num_answers, ofs = sizeof(*h); size_t i, n, num_answers, ofs = sizeof(*h);
bool is_response;
memset(dm, 0, sizeof(*dm)); memset(dm, 0, sizeof(*dm));
if (len < sizeof(*h)) return 0; // Too small, headers dont fit if (len < sizeof(*h)) return 0; // Too small, headers dont fit
@@ -110,12 +111,22 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
num_answers = 10; // Sanity cap num_answers = 10; // Sanity cap
} }
dm->txnid = mg_ntohs(h->txnid); dm->txnid = mg_ntohs(h->txnid);
is_response = mg_ntohs(h->flags) & 0x8000;
for (i = 0; i < mg_ntohs(h->num_questions); i++) { for (i = 0; i < mg_ntohs(h->num_questions); i++) {
if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false; if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
// MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass)); // MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
ofs += n; ofs += n;
} }
if (!is_response) {
// For queries, there is no need to parse the answers. In this way,
// we also ensure the domain name (dm->name) is parsed from
// the question field.
return true;
}
for (i = 0; i < num_answers; i++) { for (i = 0; i < num_answers; i++) {
if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false; if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
// MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass, // MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
@@ -265,3 +276,72 @@ void mg_resolve(struct mg_connection *c, const char *url) {
mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6); mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
} }
} }
static const uint8_t mdns_answer[] = {
0, 1, // 2 bytes - record type, A
0, 1, // 2 bytes - address class, INET
0, 0, 0, 120, // 4 bytes - TTL
0, 4 // 2 bytes - address length
};
static void mdns_cb(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_READ) {
struct mg_dns_header *qh = (struct mg_dns_header *) c->recv.buf;
if (c->recv.len > 12 && (qh->flags & mg_htons(0xF800)) == 0) {
// flags -> !resp, opcode=0 => query; ignore other opcodes and responses
struct mg_dns_rr rr; // Parse first question, offset 12 is header size
size_t n = mg_dns_parse_rr(c->recv.buf, c->recv.len, 12, true, &rr);
MG_VERBOSE(("mDNS request parsed, result=%d", (int) n));
if (n > 0) {
// RFC-6762 Appendix C, RFC2181 11: m(n + 1-63), max 255 + 0x0
// buf and h declared here to ease future expansion to DNS-SD
uint8_t buf[sizeof(struct mg_dns_header) + 256 + sizeof(mdns_answer) + 4];
struct mg_dns_header *h = (struct mg_dns_header *) buf;
char local_name[63 + 7]; // name label + '.' + local label + '\0'
uint8_t name_len = (uint8_t) strlen((char *)c->fn_data);
struct mg_dns_message dm;
bool unicast = (rr.aclass & MG_BIT(15)) != 0; // QU
// uint16_t q = mg_ntohs(qh->num_questions);
rr.aclass &= (uint16_t) ~MG_BIT(15); // remove "QU" (unicast response)
qh->num_questions = mg_htons(1); // parser sanity
mg_dns_parse(c->recv.buf, c->recv.len, &dm);
if (name_len > (sizeof(local_name) - 7)) // leave room for .local\0
name_len = sizeof(local_name) - 7;
memcpy(local_name, c->fn_data, name_len);
strcpy(local_name + name_len, ".local"); // ensure proper name.local\0
if (strcmp(local_name, dm.name) == 0) {
uint8_t *p = &buf[sizeof(*h)];
memset(h, 0, sizeof(*h)); // clear header
h->txnid = unicast ? qh->txnid : 0; // RFC-6762 18.1
// RFC-6762 6: 0 questions, 1 Answer, 0 Auth, 0 Additional RRs
h->num_answers = mg_htons(1); // only one answer
h->flags = mg_htons(0x8400); // Authoritative response
*p++ = name_len; // label 1
memcpy(p, c->fn_data, name_len), p += name_len;
*p++ = 5; // label 2
memcpy(p, "local", 5), p += 5;
*p++ = 0; // no more labels
memcpy(p, mdns_answer, sizeof(mdns_answer)), p += sizeof(mdns_answer);
#if MG_ENABLE_TCPIP
memcpy(p, &c->mgr->ifp->ip, 4), p += 4;
#else
memcpy(p, c->data, 4), p += 4;
#endif
if (!unicast) memcpy(&c->rem, &c->loc, sizeof(c->rem));
mg_send(c, buf, (size_t)(p - buf)); // And send it!
MG_DEBUG(("mDNS %c response sent", unicast ? 'U' : 'M'));
}
}
}
mg_iobuf_del(&c->recv, 0, c->recv.len);
}
(void) ev_data;
}
void mg_multicast_add(struct mg_connection *c, char *ip);
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
struct mg_connection *c =
mg_listen(mgr, "udp://224.0.0.251:5353", mdns_cb, name);
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
return c;
}
+2
View File
@@ -36,3 +36,5 @@ void mg_resolve_cancel(struct mg_connection *);
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *); bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs, size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
bool is_question, struct mg_dns_rr *); bool is_question, struct mg_dns_rr *);
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name);
+17 -3
View File
@@ -13,12 +13,12 @@ static struct mg_tcpip_if *s_ifp;
static void mac_cb(uint32_t); static void mac_cb(uint32_t);
static bool cmsis_init(struct mg_tcpip_if *); static bool cmsis_init(struct mg_tcpip_if *);
static bool cmsis_up(struct mg_tcpip_if *); static bool cmsis_poll(struct mg_tcpip_if *, bool);
static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *); static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *); static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL, struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
cmsis_up}; cmsis_poll};
static bool cmsis_init(struct mg_tcpip_if *ifp) { static bool cmsis_init(struct mg_tcpip_if *ifp) {
ARM_ETH_MAC_ADDR addr; ARM_ETH_MAC_ADDR addr;
@@ -56,7 +56,21 @@ static size_t cmsis_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
return len; return len;
} }
static bool cmsis_up(struct mg_tcpip_if *ifp) { static void cmsis_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
ARM_ETH_MAC_ADDR addr;
memcpy(&addr, mcast_addr, sizeof(addr));
mac->SetAddressFilter(&addr, 1);
(void) ifp;
}
static bool cmsis_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
cmsis_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0; ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0; ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
+1200
View File
File diff suppressed because it is too large. Load diff
+54
View File
@@ -0,0 +1,54 @@
#pragma once
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
struct mg_tcpip_spi_ {
void *spi; // Opaque SPI bus descriptor
void (*begin)(void *); // SPI begin: slave select low
void (*end)(void *); // SPI end: slave select high
void (*txn)(void *, uint8_t *, uint8_t *,
size_t len); // SPI transaction: write-read len bytes
};
struct mg_tcpip_driver_cyw_firmware {
const uint8_t *code_addr;
size_t code_len;
const uint8_t *nvram_addr;
size_t nvram_len;
const uint8_t *clm_addr;
size_t clm_len;
};
struct mg_tcpip_driver_cyw_data {
struct mg_tcpip_spi_ *spi;
struct mg_tcpip_driver_cyw_firmware *fw;
char *ssid;
char *pass;
char *apssid;
char *appass;
uint8_t security; // TBD
uint8_t apsecurity; // TBD
uint8_t apchannel;
bool apmode; // start in AP mode; 'false' starts connection to 'ssid' if not NULL
bool hs; // use chip "high-speed" mode; otherwise SPI CPOL0 CPHA0 (DS 4.2.3 Table 6)
};
#if 0
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_cyw_data driver_data_; \
static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CONFIG(&driver_data_); \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_pico_w; \
mif_.driver_data = &driver_data_; \
mif_.recv_queue.size = 8192; \
mif_.mac[0] = 2; /* MAC read from OTP at driver init */ \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: cyw, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
#endif
+24 -2
View File
@@ -115,9 +115,14 @@ static bool mg_tcpip_driver_imxrt_init(struct mg_tcpip_if *ifp) {
ENET->RDAR = MG_BIT(24); // Receive Descriptors have changed ENET->RDAR = MG_BIT(24); // Receive Descriptors have changed
ENET->TDAR = MG_BIT(24); // Transmit Descriptors have changed ENET->TDAR = MG_BIT(24); // Transmit Descriptors have changed
// ENET->OPD = 0x10014; // ENET->OPD = 0x10014;
ENET->IAUR = 0;
ENET->IALR = 0;
ENET->GAUR = 0;
ENET->GALR = 0;
return true; return true;
} }
// Transmit frame // Transmit frame
static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len, static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len,
struct mg_tcpip_if *ifp) { struct mg_tcpip_if *ifp) {
@@ -142,7 +147,24 @@ static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len,
return len; return len;
} }
static bool mg_tcpip_driver_imxrt_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_imxrt_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
// RM 37.3.4.3.2
uint32_t hash_table[2] = {0, 0};
// uint8_t hash64 = ((~mg_crc32(0, mcast_addr, 6)) >> 26) & 0x3f;
// hash_table[((uint8_t)hash64) >> 5] |= (1 << (hash64 & 0x1f));
hash_table[1] = MG_BIT(1); // above reduces to this for mDNS addr
ENET->GAUR = hash_table[1];
ENET->GALR = hash_table[0];
(void) ifp;
}
static bool mg_tcpip_driver_imxrt_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_imxrt_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_imxrt_data *d = struct mg_tcpip_driver_imxrt_data *d =
(struct mg_tcpip_driver_imxrt_data *) ifp->driver_data; (struct mg_tcpip_driver_imxrt_data *) ifp->driver_data;
uint8_t speed = MG_PHY_SPEED_10M; uint8_t speed = MG_PHY_SPEED_10M;
@@ -188,6 +210,6 @@ void ENET_IRQHandler(void) {
struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init, struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init,
mg_tcpip_driver_imxrt_tx, NULL, mg_tcpip_driver_imxrt_tx, NULL,
mg_tcpip_driver_imxrt_up}; mg_tcpip_driver_imxrt_poll};
#endif #endif
+121 -20
View File
@@ -1,8 +1,8 @@
#if MG_ENABLE_TCPIP && MG_ARCH == MG_ARCH_PICOSDK && \ #if MG_ENABLE_TCPIP && MG_ARCH == MG_ARCH_PICOSDK && \
defined(MG_ENABLE_DRIVER_PICO_W) && MG_ENABLE_DRIVER_PICO_W defined(MG_ENABLE_DRIVER_PICO_W) && MG_ENABLE_DRIVER_PICO_W
#include "net_builtin.h"
#include "drivers/pico-w.h" #include "drivers/pico-w.h"
#include "net_builtin.h"
#include "pico/stdlib.h" #include "pico/stdlib.h"
static struct mg_tcpip_if *s_ifp; static struct mg_tcpip_if *s_ifp;
@@ -13,49 +13,150 @@ static bool mg_tcpip_driver_pico_w_init(struct mg_tcpip_if *ifp) {
s_ifp = ifp; s_ifp = ifp;
if (cyw43_arch_init() != 0) if (cyw43_arch_init() != 0)
return false; // initialize async_context and WiFi chip return false; // initialize async_context and WiFi chip
cyw43_arch_enable_sta_mode(); if (d->apmode && d->apssid != NULL) {
// start connecting to network MG_DEBUG(("Starting AP '%s' (%u)", d->apssid, d->apchannel));
if (cyw43_arch_wifi_connect_bssid_async(d->ssid, NULL, d->pass, if (!mg_wifi_ap_start(d->apssid, d->appass, d->apchannel)) return false;
CYW43_AUTH_WPA2_AES_PSK) != 0) cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac); // same MAC
return false; } else {
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac); cyw43_arch_enable_sta_mode();
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac);
if (d->ssid != NULL) {
MG_DEBUG(("Connecting to '%s'", d->ssid));
return mg_wifi_connect(d->ssid, d->pass);
} else {
cyw43_arch_disable_sta_mode();
}
}
return true; return true;
} }
static size_t mg_tcpip_driver_pico_w_tx(const void *buf, size_t len, static size_t mg_tcpip_driver_pico_w_tx(const void *buf, size_t len,
struct mg_tcpip_if *ifp) { struct mg_tcpip_if *ifp) {
(void) ifp; struct mg_tcpip_driver_pico_w_data *d =
return cyw43_send_ethernet(&cyw43_state, CYW43_ITF_STA, len, buf, false) (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
? 0 return cyw43_send_ethernet(&cyw43_state,
: len; d->apmode ? CYW43_ITF_AP : CYW43_ITF_STA, len, buf,
false) == 0
? len
: 0;
} }
static bool mg_tcpip_driver_pico_w_up(struct mg_tcpip_if *ifp) { static bool s_aplink = false, s_scanning = false;
(void) ifp; static bool s_stalink = false, s_connecting = false;
return (cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA) ==
CYW43_LINK_JOIN); static bool mg_tcpip_driver_pico_w_poll(struct mg_tcpip_if *ifp, bool s1) {
cyw43_arch_poll(); // not necessary, except when IRQs are disabled (OTA)
if (s_scanning && !cyw43_wifi_scan_active(&cyw43_state)) {
MG_VERBOSE(("scan complete"));
s_scanning = 0;
mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_END, NULL);
}
if (ifp->update_mac_hash_table) {
// first call to _poll() is after _init(), so this is safe
cyw43_wifi_update_multicast_filter(&cyw43_state, (uint8_t *)mcast_addr, true);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_pico_w_data *d =
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
if (d->apmode) return s_aplink;
int sdkstate = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA);
MG_VERBOSE(("conn: %c state: %d", s_connecting ? '1' : '0', sdkstate));
if (sdkstate < 0 && s_connecting) {
mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_CONNECT_ERR, &sdkstate);
s_connecting = false;
}
return s_stalink;
} }
struct mg_tcpip_driver mg_tcpip_driver_pico_w = { struct mg_tcpip_driver mg_tcpip_driver_pico_w = {
mg_tcpip_driver_pico_w_init, mg_tcpip_driver_pico_w_init,
mg_tcpip_driver_pico_w_tx, mg_tcpip_driver_pico_w_tx,
NULL, NULL,
mg_tcpip_driver_pico_w_up, mg_tcpip_driver_pico_w_poll,
}; };
// Called once per outstanding frame by async_context // Called once per outstanding frame by async_context
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len,
const uint8_t *buf) { const uint8_t *buf) {
if (itf != CYW43_ITF_STA) return;
mg_tcpip_qwrite((void *) buf, len, s_ifp); mg_tcpip_qwrite((void *) buf, len, s_ifp);
(void) cb_data; (void) cb_data;
} }
// Called by async_context // Called by async_context
void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {} void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {} if (itf == CYW43_ITF_AP) {
s_aplink = true;
} else {
s_stalink = true;
s_connecting = false;
}
}
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
if (itf == CYW43_ITF_AP) {
s_aplink = false;
} else {
s_stalink = false;
// SDK calls this before we check status, don't clear s_connecting here
}
}
// there's life beyond lwIP // there's life beyond lwIP
void pbuf_copy_partial(void) {(void) 0;} void pbuf_copy_partial(void) {
(void) 0;
}
static int result_cb(void *arg, const cyw43_ev_scan_result_t *data) {
struct mg_wifi_scan_bss_data bss;
bss.SSID = mg_str_n(data->ssid, data->ssid_len);
bss.BSSID = (char *) data->bssid;
bss.RSSI = (int8_t) data->rssi;
bss.has_n = 0; // SDK ignores this
bss.channel = (uint8_t) data->channel;
bss.band = MG_WIFI_BAND_2G;
// SDK-internal dependency, 2.1.0
bss.security = data->auth_mode & MG_BIT(0) ? MG_WIFI_SECURITY_WEP
: MG_WIFI_SECURITY_OPEN;
if (data->auth_mode & MG_BIT(1)) bss.security |= MG_WIFI_SECURITY_WPA;
if (data->auth_mode & MG_BIT(2)) bss.security |= MG_WIFI_SECURITY_WPA2;
MG_VERBOSE(("BSS: %.*s (%u) (%M) %d dBm %u", bss.SSID.len, bss.SSID.buf,
bss.channel, mg_print_mac, bss.BSSID, (int) bss.RSSI,
bss.security));
mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_RESULT, &bss);
return 0;
}
bool mg_wifi_scan(void) {
cyw43_wifi_scan_options_t opts;
memset(&opts, 0, sizeof(opts));
bool res = (cyw43_wifi_scan(&cyw43_state, &opts, NULL, result_cb) == 0);
if (res) s_scanning = true;
return res;
}
bool mg_wifi_connect(char *ssid, char *pass) {
cyw43_arch_enable_sta_mode();
int res = cyw43_arch_wifi_connect_async(ssid, pass, CYW43_AUTH_WPA2_AES_PSK);
MG_VERBOSE(("res: %d", res));
if (res == 0) s_connecting = true;
return (res == 0);
}
bool mg_wifi_disconnect(void) {
cyw43_arch_disable_sta_mode();
s_connecting = false;
return true;
}
bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
cyw43_wifi_ap_set_channel(&cyw43_state, channel);
cyw43_arch_enable_ap_mode(ssid, pass, CYW43_AUTH_WPA2_AES_PSK);
return true;
}
bool mg_wifi_ap_stop(void) {
cyw43_arch_disable_ap_mode();
return true;
}
#endif #endif
+7 -1
View File
@@ -10,13 +10,19 @@
struct mg_tcpip_driver_pico_w_data { struct mg_tcpip_driver_pico_w_data {
char *ssid; char *ssid;
char *pass; char *pass;
char *apssid;
char *appass;
uint8_t security; // TBD
uint8_t apsecurity; // TBD
uint8_t apchannel;
bool apmode; // start in AP mode; 'false' starts connection to 'ssid' if not NULL
}; };
#define MG_TCPIP_DRIVER_INIT(mgr) \ #define MG_TCPIP_DRIVER_INIT(mgr) \
do { \ do { \
static struct mg_tcpip_driver_pico_w_data driver_data_; \ static struct mg_tcpip_driver_pico_w_data driver_data_; \
static struct mg_tcpip_if mif_; \ static struct mg_tcpip_if mif_; \
MG_SET_WIFI_CREDS(&driver_data_.ssid, &driver_data_.pass); \ MG_SET_WIFI_CONFIG(&driver_data_); \
mif_.ip = MG_TCPIP_IP; \ mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \ mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \ mif_.gw = MG_TCPIP_GW; \
+2 -1
View File
@@ -96,7 +96,8 @@ static uint32_t fcs_do(uint32_t fcs, uint8_t x) {
return fcs; return fcs;
} }
static bool mg_ppp_up(struct mg_tcpip_if *ifp) { static bool mg_ppp_poll(struct mg_tcpip_if *ifp, bool s1) {
(void) s1;
return ifp->driver_data != NULL; return ifp->driver_data != NULL;
} }
+20 -12
View File
@@ -101,9 +101,9 @@ static uint16_t smi_rd(uint16_t header) {
pir = 0; // read, mdc = 0 pir = 0; // read, mdc = 0
ETHERC->PIR = pir; ETHERC->PIR = pir;
raspin(s_smispin / 2); // 1/4 clock period, 300ns max access time raspin(s_smispin / 2); // 1/4 clock period, 300ns max access time
data |= (uint16_t)(ETHERC->PIR & MG_BIT(3) ? 1 : 0); // read mdio data |= (uint16_t) (ETHERC->PIR & MG_BIT(3) ? 1 : 0); // read mdio
raspin(s_smispin / 2); // 1/4 clock period raspin(s_smispin / 2); // 1/4 clock period
pir |= MG_BIT(0); // mdc = 1 pir |= MG_BIT(0); // mdc = 1
ETHERC->PIR = pir; ETHERC->PIR = pir;
raspin(s_smispin); raspin(s_smispin);
} }
@@ -111,11 +111,14 @@ static uint16_t smi_rd(uint16_t header) {
} }
static uint16_t raeth_read_phy(uint8_t addr, uint8_t reg) { static uint16_t raeth_read_phy(uint8_t addr, uint8_t reg) {
return smi_rd((uint16_t)((1 << 14) | (2 << 12) | (addr << 7) | (reg << 2) | (2 << 0))); return smi_rd(
(uint16_t) ((1 << 14) | (2 << 12) | (addr << 7) | (reg << 2) | (2 << 0)));
} }
static void raeth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { static void raeth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
smi_wr((uint16_t)((1 << 14) | (1 << 12) | (addr << 7) | (reg << 2) | (2 << 0)), val); smi_wr(
(uint16_t) ((1 << 14) | (1 << 12) | (addr << 7) | (reg << 2) | (2 << 0)),
val);
} }
// MDC clock is generated manually; as per 802.3, it must not exceed 2.5MHz // MDC clock is generated manually; as per 802.3, it must not exceed 2.5MHz
@@ -152,7 +155,7 @@ static bool mg_tcpip_driver_ra_init(struct mg_tcpip_if *ifp) {
MG_DEBUG(("PHY addr: %d, smispin: %d", d->phy_addr, s_smispin)); MG_DEBUG(("PHY addr: %d, smispin: %d", d->phy_addr, s_smispin));
struct mg_phy phy = {raeth_read_phy, raeth_write_phy}; struct mg_phy phy = {raeth_read_phy, raeth_write_phy};
mg_phy_init(&phy, d->phy_addr, 0); // MAC clocks PHY mg_phy_init(&phy, d->phy_addr, 0); // MAC clocks PHY
// Select RMII mode, // Select RMII mode,
ETHERC->ECMR = MG_BIT(2) | MG_BIT(1); // 100M, Full-duplex, CRC ETHERC->ECMR = MG_BIT(2) | MG_BIT(1); // 100M, Full-duplex, CRC
@@ -171,9 +174,9 @@ static bool mg_tcpip_driver_ra_init(struct mg_tcpip_if *ifp) {
EDMAC->FDR = 0x070f; // (27.2.11) EDMAC->FDR = 0x070f; // (27.2.11)
EDMAC->RMCR = MG_BIT(0); // (27.2.12) EDMAC->RMCR = MG_BIT(0); // (27.2.12)
ETHERC->ECMR |= MG_BIT(6) | MG_BIT(5); // TE RE ETHERC->ECMR |= MG_BIT(6) | MG_BIT(5); // TE RE
EDMAC->EESIPR = MG_BIT(18); // Enable Rx IRQ EDMAC->EESIPR = MG_BIT(18); // FR: Enable Rx (frame) IRQ
EDMAC->EDRRR = MG_BIT(0); // Receive Descriptors have changed EDMAC->EDRRR = MG_BIT(0); // Receive Descriptors have changed
EDMAC->EDTRR = MG_BIT(0); // Transmit Descriptors have changed EDMAC->EDTRR = MG_BIT(0); // Transmit Descriptors have changed
return true; return true;
} }
@@ -198,7 +201,12 @@ static size_t mg_tcpip_driver_ra_tx(const void *buf, size_t len,
return len; return len;
} }
static bool mg_tcpip_driver_ra_up(struct mg_tcpip_if *ifp) { static bool mg_tcpip_driver_ra_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
EDMAC->EESIPR = MG_BIT(18) | MG_BIT(7); // FR, RMAF: Frame and mcast IRQ
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_ra_data *d = struct mg_tcpip_driver_ra_data *d =
(struct mg_tcpip_driver_ra_data *) ifp->driver_data; (struct mg_tcpip_driver_ra_data *) ifp->driver_data;
uint8_t speed = MG_PHY_SPEED_10M; uint8_t speed = MG_PHY_SPEED_10M;
@@ -224,7 +232,7 @@ static uint32_t s_rxno;
void EDMAC_IRQHandler(void) { void EDMAC_IRQHandler(void) {
struct mg_tcpip_driver_ra_data *d = struct mg_tcpip_driver_ra_data *d =
(struct mg_tcpip_driver_ra_data *) s_ifp->driver_data; (struct mg_tcpip_driver_ra_data *) s_ifp->driver_data;
EDMAC->EESR = MG_BIT(18); // Ack IRQ in EDMAC 1st EDMAC->EESR = MG_BIT(18) | MG_BIT(7); // Ack IRQ in EDMAC 1st
ICU_IELSR[d->irqno] &= ~MG_BIT(16); // Ack IRQ in ICU last ICU_IELSR[d->irqno] &= ~MG_BIT(16); // Ack IRQ in ICU last
// Frame received, loop // Frame received, loop
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
@@ -245,6 +253,6 @@ void EDMAC_IRQHandler(void) {
struct mg_tcpip_driver mg_tcpip_driver_ra = {mg_tcpip_driver_ra_init, struct mg_tcpip_driver mg_tcpip_driver_ra = {mg_tcpip_driver_ra_init,
mg_tcpip_driver_ra_tx, NULL, mg_tcpip_driver_ra_tx, NULL,
mg_tcpip_driver_ra_up}; mg_tcpip_driver_ra_poll};
#endif #endif
+29
View File
@@ -9,4 +9,33 @@ struct mg_tcpip_driver_ra_data {
uint8_t phy_addr; // PHY address uint8_t phy_addr; // PHY address
}; };
#ifndef MG_DRIVER_CLK_FREQ
#define MG_DRIVER_CLK_FREQ 100000000UL
#endif
#ifndef MG_DRIVER_IRQ_NO
#define MG_DRIVER_IRQ_NO 0
#endif
#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_ra_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.clock = MG_DRIVER_CLK_FREQ; \
driver_data_.irqno = MG_DRIVER_IRQ_NO; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_ra; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: ra, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif #endif
+19 -3
View File
@@ -89,6 +89,10 @@ static bool mg_tcpip_driver_rw612_init(struct mg_tcpip_if *ifp) {
ENET->PALR = ENET->PALR =
ifp->mac[0] << 24 | ifp->mac[1] << 16 | ifp->mac[2] << 8 | ifp->mac[3]; ifp->mac[0] << 24 | ifp->mac[1] << 16 | ifp->mac[2] << 8 | ifp->mac[3];
ENET->PAUR |= (ifp->mac[4] << 24 | ifp->mac[5] << 16); ENET->PAUR |= (ifp->mac[4] << 24 | ifp->mac[5] << 16);
ENET->IALR = 0;
ENET->IAUR = 0;
ENET->GALR = 0;
ENET->GAUR = 0;
ENET->MSCR = ((d->mdc_cr & 0x3f) << 1) | ((d->mdc_holdtime & 7) << 8); ENET->MSCR = ((d->mdc_cr & 0x3f) << 1) | ((d->mdc_holdtime & 7) << 8);
ENET->EIMR = MG_BIT(25); // Enable RX interrupt ENET->EIMR = MG_BIT(25); // Enable RX interrupt
ENET->ECR |= MG_BIT(8) | MG_BIT(1); // DBSWP, Enable ENET->ECR |= MG_BIT(8) | MG_BIT(1); // DBSWP, Enable
@@ -121,7 +125,19 @@ static size_t mg_tcpip_driver_rw612_tx(const void *buf, size_t len,
return len; return len;
} }
static bool mg_tcpip_driver_rw612_up(struct mg_tcpip_if *ifp) {
static void mg_tcpip_driver_rw612_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
ENET->GAUR = MG_BIT(1); // see imxrt, it reduces to this for mDNS
(void) ifp;
}
static bool mg_tcpip_driver_rw612_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_rw612_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_rw612_data *d = struct mg_tcpip_driver_rw612_data *d =
(struct mg_tcpip_driver_rw612_data *) ifp->driver_data; (struct mg_tcpip_driver_rw612_data *) ifp->driver_data;
uint8_t speed = MG_PHY_SPEED_10M; uint8_t speed = MG_PHY_SPEED_10M;
@@ -157,7 +173,7 @@ static bool mg_tcpip_driver_rw612_up(struct mg_tcpip_if *ifp) {
void ENET_IRQHandler(void) { void ENET_IRQHandler(void) {
if (ENET->EIR & MG_BIT(25)) { if (ENET->EIR & MG_BIT(25)) {
ENET->EIR = MG_BIT(25); // Ack RX ENET->EIR = MG_BIT(25); // Ack RX
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) != 0) break; // exit when done if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) != 0) break; // exit when done
// skip partial/errored frames // skip partial/errored frames
@@ -177,5 +193,5 @@ void ENET_IRQHandler(void) {
struct mg_tcpip_driver mg_tcpip_driver_rw612 = {mg_tcpip_driver_rw612_init, struct mg_tcpip_driver mg_tcpip_driver_rw612 = {mg_tcpip_driver_rw612_init,
mg_tcpip_driver_rw612_tx, NULL, mg_tcpip_driver_rw612_tx, NULL,
mg_tcpip_driver_rw612_up}; mg_tcpip_driver_rw612_poll};
#endif #endif
+31 -14
View File
@@ -1,6 +1,7 @@
#include "net_builtin.h" #include "net_builtin.h"
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54 #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
MG_ENABLE_DRIVER_SAME54
#include <sam.h> #include <sam.h>
@@ -164,21 +165,37 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
return len; return len;
} }
static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_same54_update_hash_table(struct mg_tcpip_if *ifp) {
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR); // TODO(): read database, rebuild hash table
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0; // Setting Hash Index for 01:00:5e:00:00:fb (multicast)
// 24.6.9 Hash addressing
// computed hash is 55, which means bit 23 (55 - 32) in
// HRT register must be set
GMAC_REGS->GMAC_HRT = MG_BIT(23);
GMAC_REGS->GMAC_NCFGR |= MG_BIT(6); // enable multicast hash filtering
(void) ifp;
}
// If PHY is ready, update NCFGR accordingly static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->state == MG_TCPIP_STATE_DOWN && up) { if (ifp->update_mac_hash_table) {
uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR); mg_tcpip_driver_same54_update_hash_table(ifp);
bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0; ifp->update_mac_hash_table = false;
bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
} }
if (s1) {
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
return up; // If PHY is ready, update NCFGR accordingly
if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0;
bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
}
}
return false;
} }
void GMAC_Handler(void); void GMAC_Handler(void);
@@ -211,5 +228,5 @@ void GMAC_Handler(void) {
struct mg_tcpip_driver mg_tcpip_driver_same54 = { struct mg_tcpip_driver mg_tcpip_driver_same54 = {
mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL, mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL,
mg_tcpip_driver_same54_up}; mg_tcpip_driver_same54_poll};
#endif #endif
+18 -3
View File
@@ -136,7 +136,7 @@ static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
// MG_BIT(25); // MG_BIT(25);
ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause
// ETH->MACFFR = MG_BIT(31); // Receive all ETH->MACFFR = MG_BIT(10); // Perfect filtering
struct mg_phy phy = {eth_read_phy, eth_write_phy}; struct mg_phy phy = {eth_read_phy, eth_write_phy};
mg_phy_init(&phy, phy_addr, MG_PHY_CLOCKS_MAC); mg_phy_init(&phy, phy_addr, MG_PHY_CLOCKS_MAC);
ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
@@ -178,7 +178,22 @@ static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len,
return len; return len;
} }
static bool mg_tcpip_driver_stm32f_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_stm32f_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
ETH->MACA1LR = (uint32_t) mcast_addr[3] << 24 |
(uint32_t) mcast_addr[2] << 16 |
(uint32_t) mcast_addr[1] << 8 | (uint32_t) mcast_addr[0];
ETH->MACA1HR = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
ETH->MACA1HR |= MG_BIT(31); // AE
(void) ifp;
}
static bool mg_tcpip_driver_stm32f_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_stm32f_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_stm32f_data *d = struct mg_tcpip_driver_stm32f_data *d =
(struct mg_tcpip_driver_stm32f_data *) ifp->driver_data; (struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
uint8_t phy_addr = d == NULL ? 0 : d->phy_addr; uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
@@ -229,5 +244,5 @@ void ETH_IRQHandler(void) {
struct mg_tcpip_driver mg_tcpip_driver_stm32f = { struct mg_tcpip_driver mg_tcpip_driver_stm32f = {
mg_tcpip_driver_stm32f_init, mg_tcpip_driver_stm32f_tx, NULL, mg_tcpip_driver_stm32f_init, mg_tcpip_driver_stm32f_tx, NULL,
mg_tcpip_driver_stm32f_up}; mg_tcpip_driver_stm32f_poll};
#endif #endif
+26 -4
View File
@@ -2,7 +2,7 @@
#if MG_ENABLE_TCPIP && (MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN) #if MG_ENABLE_TCPIP && (MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN)
// STM32H: vendor modded single-queue Synopsys v4.2 // STM32H: vendor modded single-queue Synopsys v4.2
// MCXNx4x: dual-queue Synopsys v5.2 // MCXNx4x: dual-queue Synopsys v5.2 with no hash table option
// RT1170 ENET_QOS: quad-queue Synopsys v5.1 // RT1170 ENET_QOS: quad-queue Synopsys v5.1
struct synopsys_enet_qos { struct synopsys_enet_qos {
volatile uint32_t MACCR, MACECR, MACPFR, MACWTR, MACHT0R, MACHT1R, volatile uint32_t MACCR, MACECR, MACPFR, MACWTR, MACHT0R, MACHT1R,
@@ -102,7 +102,9 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
ETH->DMASBMR |= MG_BIT(12); // AAL NOTE(scaprile): is this actually needed ETH->DMASBMR |= MG_BIT(12); // AAL NOTE(scaprile): is this actually needed
ETH->MACIER = 0; // Do not enable additional irq sources (reset value) ETH->MACIER = 0; // Do not enable additional irq sources (reset value)
ETH->MACTFCR = MG_BIT(7); // Disable zero-quanta pause ETH->MACTFCR = MG_BIT(7); // Disable zero-quanta pause
// ETH->MACPFR = MG_BIT(31); // Receive all #if !MG_ENABLE_DRIVER_MCXN
ETH->MACPFR = MG_BIT(10); // Perfect filtering
#endif
struct mg_phy phy = {eth_read_phy, eth_write_phy}; struct mg_phy phy = {eth_read_phy, eth_write_phy};
mg_phy_init(&phy, phy_addr, phy_conf); mg_phy_init(&phy, phy_addr, phy_conf);
ETH->DMACRDLAR = ETH->DMACRDLAR =
@@ -168,7 +170,27 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
(void) ifp; (void) ifp;
} }
static bool mg_tcpip_driver_stm32h_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_stm32h_update_hash_table(struct mg_tcpip_if *ifp) {
#if MG_ENABLE_DRIVER_MCXN
ETH->MACPFR = MG_BIT(4); // Pass Multicast (pass all multicast frames)
#else
// TODO(): read database, rebuild hash table
// add mDNS / DNS-SD multicast address
ETH->MACA1LR = (uint32_t) mcast_addr[3] << 24 |
(uint32_t) mcast_addr[2] << 16 |
(uint32_t) mcast_addr[1] << 8 | (uint32_t) mcast_addr[0];
ETH->MACA1HR = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
ETH->MACA1HR |= MG_BIT(31); // AE
#endif
(void) ifp;
}
static bool mg_tcpip_driver_stm32h_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_stm32h_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_stm32h_data *d = struct mg_tcpip_driver_stm32h_data *d =
(struct mg_tcpip_driver_stm32h_data *) ifp->driver_data; (struct mg_tcpip_driver_stm32h_data *) ifp->driver_data;
uint8_t phy_addr = d == NULL ? 0 : d->phy_addr; uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
@@ -223,5 +245,5 @@ void ETH_IRQHandler(void) {
struct mg_tcpip_driver mg_tcpip_driver_stm32h = { struct mg_tcpip_driver mg_tcpip_driver_stm32h = {
mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, NULL, mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, NULL,
mg_tcpip_driver_stm32h_up}; mg_tcpip_driver_stm32h_poll};
#endif #endif
+42 -22
View File
@@ -55,7 +55,8 @@ static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) { static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
EMAC->EMACMIIDATA = val; EMAC->EMACMIIDATA = val;
EMAC->EMACMIIADDR &= (0xf << 2); EMAC->EMACMIIADDR &= (0xf << 2);
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1); EMAC->EMACMIIADDR |=
((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
EMAC->EMACMIIADDR |= MG_BIT(0); EMAC->EMACMIIADDR |= MG_BIT(0);
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1); while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
} }
@@ -133,8 +134,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
// Init RX descriptors // Init RX descriptors
for (int i = 0; i < ETH_DESC_CNT; i++) { for (int i = 0; i < ETH_DESC_CNT; i++) {
s_rxdesc[i][0] = MG_BIT(31); // Own s_rxdesc[i][0] = MG_BIT(31); // Own
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
s_rxdesc[i][3] = s_rxdesc[i][3] =
(uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain (uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
@@ -148,8 +149,9 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
} }
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) tm4cspin(1); // Wait until done while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0)
tm4cspin(1); // Wait until done
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr; int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
@@ -157,25 +159,25 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use // NOTE(cpq): we do not use extended descriptor bit 7, and do not use
// hardware checksum. Therefore, descriptor size is 4, not 8 // hardware checksum. Therefore, descriptor size is 4, not 8
// EMAC->EMACDMABUSMOD = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) | MG_BIT(25); // EMAC->EMACDMABUSMOD = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) |
// MG_BIT(25);
EMAC->EMACIM = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT EMAC->EMACIM = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
EMAC->EMACFLOWCTL = MG_BIT(7); // Disable zero-quanta pause EMAC->EMACFLOWCTL = MG_BIT(7); // Disable zero-quanta pause
// EMAC->EMACFRAMEFLTR = MG_BIT(31); // Receive all EMAC->EMACFRAMEFLTR = MG_BIT(10); // Perfect filtering
// EMAC->EMACPC defaults to internal PHY (EPHY) in MMI mode // EMAC->EMACPC defaults to internal PHY (EPHY) in MMI mode
emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(15)); // Reset internal PHY (EPHY) emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(15)); // Reset internal PHY (EPHY)
emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(12)); // Set autonegotiation emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(12)); // Set autonegotiation
EMAC->EMACRXDLADDR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors EMAC->EMACRXDLADDR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
EMAC->EMACTXDLADDR = (uint32_t) (uintptr_t) s_txdesc; // TX descriptors EMAC->EMACTXDLADDR = (uint32_t) (uintptr_t) s_txdesc; // TX descriptors
EMAC->EMACDMAIM = MG_BIT(6) | MG_BIT(16); // RIE, NIE EMAC->EMACDMAIM = MG_BIT(6) | MG_BIT(16); // RIE, NIE
EMAC->EMACCFG = MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast EMAC->EMACCFG =
MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
EMAC->EMACDMAOPMODE = EMAC->EMACDMAOPMODE =
MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
EMAC->EMACADDR0H = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4]; EMAC->EMACADDR0H = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
EMAC->EMACADDR0L = (uint32_t) (ifp->mac[3] << 24) | EMAC->EMACADDR0L = (uint32_t) (ifp->mac[3] << 24) |
((uint32_t) ifp->mac[2] << 16) | ((uint32_t) ifp->mac[2] << 16) |
((uint32_t) ifp->mac[1] << 8) | ifp->mac[0]; ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
// NOTE(scaprile) There are 3 additional slots for filtering, disabled by
// default. This also applies to the STM32 driver (at least for F7)
return true; return true;
} }
@@ -200,12 +202,28 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
if (++s_txno >= ETH_DESC_CNT) s_txno = 0; if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
} }
EMAC->EMACDMARIS = MG_BIT(2) | MG_BIT(5); // Clear any prior TU/UNF EMAC->EMACDMARIS = MG_BIT(2) | MG_BIT(5); // Clear any prior TU/UNF
EMAC->EMACTXPOLLD = 0; // and resume EMAC->EMACTXPOLLD = 0; // and resume
return len; return len;
(void) ifp; (void) ifp;
} }
static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_tm4c_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
// add mDNS / DNS-SD multicast address
EMAC->EMACADDR1L = (uint32_t) mcast_addr[3] << 24 |
(uint32_t) mcast_addr[2] << 16 |
(uint32_t) mcast_addr[1] << 8 | (uint32_t) mcast_addr[0];
EMAC->EMACADDR1H = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
EMAC->EMACADDR1H |= MG_BIT(31); // AE
(void) ifp;
}
static bool mg_tcpip_driver_tm4c_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_tm4c_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
uint32_t bmsr = emac_read_phy(EPHY_ADDR, EPHYBMSR); uint32_t bmsr = emac_read_phy(EPHY_ADDR, EPHYBMSR);
bool up = (bmsr & MG_BIT(2)) ? 1 : 0; bool up = (bmsr & MG_BIT(2)) ? 1 : 0;
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
@@ -213,9 +231,10 @@ static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
// tmp = reg with flags set to the most likely situation: 100M full-duplex // tmp = reg with flags set to the most likely situation: 100M full-duplex
// if(link is slow or half) set flags otherwise // if(link is slow or half) set flags otherwise
// reg = tmp // reg = tmp
uint32_t emaccfg = EMAC->EMACCFG | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex uint32_t emaccfg =
if (sts & MG_BIT(1)) emaccfg &= ~MG_BIT(14); // 10M EMAC->EMACCFG | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
if ((sts & MG_BIT(2)) == 0) emaccfg &= ~MG_BIT(11); // Half-duplex if (sts & MG_BIT(1)) emaccfg &= ~MG_BIT(14); // 10M
if ((sts & MG_BIT(2)) == 0) emaccfg &= ~MG_BIT(11); // Half-duplex
EMAC->EMACCFG = emaccfg; // IRQ handler does not fiddle with this register EMAC->EMACCFG = emaccfg; // IRQ handler does not fiddle with this register
MG_DEBUG(("Link is %uM %s-duplex", emaccfg & MG_BIT(14) ? 100 : 10, MG_DEBUG(("Link is %uM %s-duplex", emaccfg & MG_BIT(14) ? 100 : 10,
emaccfg & MG_BIT(11) ? "full" : "half")); emaccfg & MG_BIT(11) ? "full" : "half"));
@@ -226,11 +245,12 @@ static bool mg_tcpip_driver_tm4c_up(struct mg_tcpip_if *ifp) {
void EMAC0_IRQHandler(void); void EMAC0_IRQHandler(void);
static uint32_t s_rxno; static uint32_t s_rxno;
void EMAC0_IRQHandler(void) { void EMAC0_IRQHandler(void) {
if (EMAC->EMACDMARIS & MG_BIT(6)) { // Frame received, loop if (EMAC->EMACDMARIS & MG_BIT(6)) { // Frame received, loop
EMAC->EMACDMARIS = MG_BIT(16) | MG_BIT(6); // Clear flag EMAC->EMACDMARIS = MG_BIT(16) | MG_BIT(6); // Clear flag
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) == (MG_BIT(8) | MG_BIT(9))) && if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) ==
(MG_BIT(8) | MG_BIT(9))) &&
!(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames !(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1)); uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
// printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0], // printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
@@ -242,10 +262,10 @@ void EMAC0_IRQHandler(void) {
} }
} }
EMAC->EMACDMARIS = MG_BIT(7); // Clear possible RU while processing EMAC->EMACDMARIS = MG_BIT(7); // Clear possible RU while processing
EMAC->EMACRXPOLLD = 0; // and resume RX EMAC->EMACRXPOLLD = 0; // and resume RX
} }
struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init, struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init,
mg_tcpip_driver_tm4c_tx, NULL, mg_tcpip_driver_tm4c_tx, NULL,
mg_tcpip_driver_tm4c_up}; mg_tcpip_driver_tm4c_poll};
#endif #endif
+36 -21
View File
@@ -105,10 +105,6 @@ static bool mg_tcpip_driver_tms570_init(struct mg_tcpip_if *ifp) {
while (delay-- != 0) (void) 0; while (delay-- != 0) (void) 0;
struct mg_phy phy = {emac_read_phy, emac_write_phy}; struct mg_phy phy = {emac_read_phy, emac_write_phy};
mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC); mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC);
// set the mac address
EMAC->MACSRCADDRHI = ifp->mac[0] | (ifp->mac[1] << 8) | (ifp->mac[2] << 16) |
(ifp->mac[3] << 24);
EMAC->MACSRCADDRLO = ifp->mac[4] | (ifp->mac[5] << 8);
uint32_t channel; uint32_t channel;
for (channel = 0; channel < 8; channel++) { for (channel = 0; channel < 8; channel++) {
EMAC->MACINDEX = channel; EMAC->MACINDEX = channel;
@@ -118,8 +114,9 @@ static bool mg_tcpip_driver_tms570_init(struct mg_tcpip_if *ifp) {
MG_BIT(19) | (channel << 16); MG_BIT(19) | (channel << 16);
} }
EMAC->RXUNICASTSET = 1; // accept unicast frames; EMAC->RXUNICASTSET = 1; // accept unicast frames;
EMAC->RXMBPENABLE = MG_BIT(30) | MG_BIT(13); // CRC, broadcast;
EMAC->RXMBPENABLE |= MG_BIT(30) | MG_BIT(13); // CRC, broadcast
// Initialize the descriptors // Initialize the descriptors
for (i = 0; i < ETH_DESC_CNT; i++) { for (i = 0; i < ETH_DESC_CNT; i++) {
if (i < ETH_DESC_CNT - 1) { if (i < ETH_DESC_CNT - 1) {
@@ -172,12 +169,30 @@ static size_t mg_tcpip_driver_tms570_tx(const void *buf, size_t len,
return len; return len;
(void) ifp; (void) ifp;
} }
static bool mg_tcpip_driver_tms570_up(struct mg_tcpip_if *ifp) {
static void mg_tcpip_driver_tms570_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
// Setting Hash Index for 01:00:5e:00:00:fb (multicast)
// using TMS570 XOR method (32.5.37).
// computed hash is 55, which means bit 23 (55 - 32) in
// HASH2 register must be set
EMAC->MACHASH2 = MG_BIT(23);
EMAC->RXMBPENABLE = MG_BIT(5); // enable hash filtering
(void) ifp;
}
static bool mg_tcpip_driver_tms570_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_tms570_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_tms570_data *d = struct mg_tcpip_driver_tms570_data *d =
(struct mg_tcpip_driver_tms570_data *) ifp->driver_data; (struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
uint8_t speed = MG_PHY_SPEED_10M; uint8_t speed = MG_PHY_SPEED_10M;
bool up = false, full_duplex = false; bool up = false, full_duplex = false;
struct mg_phy phy = {emac_read_phy, emac_write_phy}; struct mg_phy phy = {emac_read_phy, emac_write_phy};
if (!s1) return false;
up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed); up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {
// link state just went up // link state just went up
@@ -186,6 +201,7 @@ static bool mg_tcpip_driver_tms570_up(struct mg_tcpip_if *ifp) {
} }
return up; return up;
} }
#pragma CODE_STATE(EMAC_TX_IRQHandler, 32) #pragma CODE_STATE(EMAC_TX_IRQHandler, 32)
#pragma INTERRUPT(EMAC_TX_IRQHandler, IRQ) #pragma INTERRUPT(EMAC_TX_IRQHandler, IRQ)
void EMAC_TX_IRQHandler(void) { void EMAC_TX_IRQHandler(void) {
@@ -206,19 +222,18 @@ void EMAC_RX_IRQHandler(void) {
uint32_t i; uint32_t i;
//MG_INFO(("RX interrupt")); //MG_INFO(("RX interrupt"));
for (i = 0; i < 10; i++) { // read as they arrive but not forever for (i = 0; i < 10; i++) { // read as they arrive but not forever
if ((s_rxdesc[s_rxno][3] & SWAP32(MG_BIT(29))) == 0) { if (s_rxdesc[s_rxno][3] & SWAP32(MG_BIT(29))) break;
uint32_t len = SWAP32(s_rxdesc[s_rxno][3]) & 0xffff; uint32_t len = SWAP32(s_rxdesc[s_rxno][3]) & 0xffff;
//MG_INFO(("recv len: %d", len)); //MG_INFO(("recv len: %d", len));
//mg_hexdump(s_rxbuf[s_rxno], len); //mg_hexdump(s_rxbuf[s_rxno], len);
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp); mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
uint32_t flags = s_rxdesc[s_rxno][3]; uint32_t flags = s_rxdesc[s_rxno][3];
s_rxdesc[s_rxno][3] = SWAP32(MG_BIT(29)); s_rxdesc[s_rxno][3] = SWAP32(MG_BIT(29));
s_rxdesc[s_rxno][2] = SWAP32(ETH_PKT_SIZE); s_rxdesc[s_rxno][2] = SWAP32(ETH_PKT_SIZE);
EMAC->RXCP[0] = (uint32_t) &s_rxdesc[s_rxno][0]; EMAC->RXCP[0] = (uint32_t) &s_rxdesc[s_rxno][0];
if (flags & SWAP32(MG_BIT(28))) { if (flags & SWAP32(MG_BIT(28))) {
//MG_INFO(("EOQ detected")); //MG_INFO(("EOQ detected"));
EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0]; EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
}
} }
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
} }
@@ -228,6 +243,6 @@ void EMAC_RX_IRQHandler(void) {
} }
struct mg_tcpip_driver mg_tcpip_driver_tms570 = {mg_tcpip_driver_tms570_init, struct mg_tcpip_driver mg_tcpip_driver_tms570 = {mg_tcpip_driver_tms570_init,
mg_tcpip_driver_tms570_tx, NULL, mg_tcpip_driver_tms570_tx, NULL,
mg_tcpip_driver_tms570_up}; mg_tcpip_driver_tms570_poll};
#endif #endif
+27 -26
View File
@@ -2,8 +2,8 @@
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5100) && MG_ENABLE_DRIVER_W5100 #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5100) && MG_ENABLE_DRIVER_W5100
static void w5100_txn(struct mg_tcpip_spi *s, uint16_t addr, static void w5100_txn(struct mg_tcpip_spi *s, uint16_t addr, bool wr, void *buf,
bool wr, void *buf, size_t len) { size_t len) {
size_t i; size_t i;
uint8_t *p = (uint8_t *) buf; uint8_t *p = (uint8_t *) buf;
uint8_t control = wr ? 0xF0 : 0x0F; uint8_t control = wr ? 0xF0 : 0x0F;
@@ -28,8 +28,8 @@ static uint16_t w5100_r2(struct mg_tcpip_spi *s, uint16_t addr) { uint8_t buf[2
static size_t w5100_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) { static size_t w5100_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data; struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
uint16_t r = 0, n = 0, len = (uint16_t) buflen, n2; // Read recv len uint16_t r = 0, n = 0, len = (uint16_t) buflen, n2; // Read recv len
while ((n2 = w5100_r2(s, 0x426)) > n) n = n2; // Until it is stable while ((n2 = w5100_r2(s, 0x426)) > n) n = n2; // Until it is stable
if (n > 0) { if (n > 0) {
uint16_t ptr = w5100_r2(s, 0x428); // Get read pointer uint16_t ptr = w5100_r2(s, 0x428); // Get read pointer
if (n <= len + 2 && n > 1) { if (n <= len + 2 && n > 1) {
@@ -46,7 +46,7 @@ static size_t w5100_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
w5100_rn(s, rxbuf_addr, buf + remaining_len, n - remaining_len); w5100_rn(s, rxbuf_addr, buf + remaining_len, n - remaining_len);
} }
w5100_w2(s, 0x428, (uint16_t) (ptr + n)); w5100_w2(s, 0x428, (uint16_t) (ptr + n));
w5100_w1(s, 0x401, 0x40); // Sock0 CR -> RECV w5100_w1(s, 0x401, 0x40); // Sock0 CR -> RECV
} }
return r; return r;
} }
@@ -55,27 +55,27 @@ static size_t w5100_tx(const void *buf, size_t buflen,
struct mg_tcpip_if *ifp) { struct mg_tcpip_if *ifp) {
struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data; struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
uint16_t i, n = 0, ptr = 0, len = (uint16_t) buflen; uint16_t i, n = 0, ptr = 0, len = (uint16_t) buflen;
while (n < len) n = w5100_r2(s, 0x420); // Wait for space while (n < len) n = w5100_r2(s, 0x420); // Wait for space
ptr = w5100_r2(s, 0x424); // Get write pointer ptr = w5100_r2(s, 0x424); // Get write pointer
uint16_t txbuf_size = (1 << (w5100_r1(s, 0x1b) & 3)) * 1024; uint16_t txbuf_size = (1 << (w5100_r1(s, 0x1b) & 3)) * 1024;
uint16_t ptr_ofs = ptr & (txbuf_size - 1); uint16_t ptr_ofs = ptr & (txbuf_size - 1);
uint16_t txbuf_addr = 0x4000; uint16_t txbuf_addr = 0x4000;
if (ptr_ofs + len > txbuf_size) { if (ptr_ofs + len > txbuf_size) {
uint16_t size = txbuf_size - ptr_ofs; uint16_t size = txbuf_size - ptr_ofs;
w5100_wn(s, txbuf_addr + ptr_ofs, (char*) buf, size); w5100_wn(s, txbuf_addr + ptr_ofs, (char *) buf, size);
w5100_wn(s, txbuf_addr, (char*) buf + size, len - size); w5100_wn(s, txbuf_addr, (char *) buf + size, len - size);
} else { } else {
w5100_wn(s, txbuf_addr + ptr_ofs, (char*) buf, len); w5100_wn(s, txbuf_addr + ptr_ofs, (char *) buf, len);
} }
w5100_w2(s, 0x424, (uint16_t) (ptr + len)); // Advance write pointer w5100_w2(s, 0x424, (uint16_t) (ptr + len)); // Advance write pointer
w5100_w1(s, 0x401, 0x20); // Sock0 CR -> SEND w5100_w1(s, 0x401, 0x20); // Sock0 CR -> SEND
for (i = 0; i < 40; i++) { for (i = 0; i < 40; i++) {
uint8_t ir = w5100_r1(s, 0x402); // Read S0 IR uint8_t ir = w5100_r1(s, 0x402); // Read S0 IR
if (ir == 0) continue; if (ir == 0) continue;
// printf("IR %d, len=%d, free=%d, ptr %d\n", ir, (int) len, (int) n, ptr); // printf("IR %d, len=%d, free=%d, ptr %d\n", ir, (int) len, (int) n, ptr);
w5100_w1(s, 0x402, ir); // Write S0 IR: clear it! w5100_w1(s, 0x402, ir); // Write S0 IR: clear it!
if (ir & 8) len = 0; // Timeout. Report error if (ir & 8) len = 0; // Timeout. Report error
if (ir & (16 | 8)) break; // Stop on SEND_OK or timeout if (ir & (16 | 8)) break; // Stop on SEND_OK or timeout
} }
return len; return len;
} }
@@ -83,24 +83,25 @@ static size_t w5100_tx(const void *buf, size_t buflen,
static bool w5100_init(struct mg_tcpip_if *ifp) { static bool w5100_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data; struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
s->end(s->spi); s->end(s->spi);
w5100_w1(s, 0, 0x80); // Reset chip: CR -> 0x80 w5100_w1(s, 0, 0x80); // Reset chip: CR -> 0x80
w5100_w1(s, 0x72, 0x53); // CR PHYLCKR -> unlock PHY w5100_w1(s, 0x72, 0x53); // CR PHYLCKR -> unlock PHY
w5100_w1(s, 0x46, 0); // CR PHYCR0 -> autonegotiation w5100_w1(s, 0x46, 0); // CR PHYCR0 -> autonegotiation
w5100_w1(s, 0x47, 0); // CR PHYCR1 -> reset w5100_w1(s, 0x47, 0); // CR PHYCR1 -> reset
w5100_w1(s, 0x72, 0x00); // CR PHYLCKR -> lock PHY w5100_w1(s, 0x72, 0x00); // CR PHYLCKR -> lock PHY
w5100_w1(s, 0x1a, 6); // Sock0 RX buf size - 4KB w5100_wn(s, 0x09, ifp->mac, 6); // SHAR
w5100_w1(s, 0x1b, 6); // Sock0 TX buf size - 4KB w5100_w1(s, 0x1a, 6); // Sock0 RX buf size - 4KB
w5100_w1(s, 0x400, 4); // Sock0 MR -> MACRAW w5100_w1(s, 0x1b, 6); // Sock0 TX buf size - 4KB
w5100_w1(s, 0x400, 0x44); // Sock0 MR -> MACRAW, MAC filter
w5100_w1(s, 0x401, 1); // Sock0 CR -> OPEN w5100_w1(s, 0x401, 1); // Sock0 CR -> OPEN
return w5100_r1(s, 0x403) == 0x42; // Sock0 SR == MACRAW return w5100_r1(s, 0x403) == 0x42; // Sock0 SR == MACRAW
} }
static bool w5100_up(struct mg_tcpip_if *ifp) { static bool w5100_poll(struct mg_tcpip_if *ifp, bool s1) {
struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data; struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data;
uint8_t physr0 = w5100_r1(spi, 0x3c); return s1 ? w5100_r1(spi, 0x3c /* PHYSR */) & 1
return physr0 & 1; // Bit 0 of PHYSR is LNK (0 - down, 1 - up) : false; // Bit 0 of PHYSR is LNK (0 - down, 1 - up)
} }
struct mg_tcpip_driver mg_tcpip_driver_w5100 = {w5100_init, w5100_tx, w5100_rx, struct mg_tcpip_driver mg_tcpip_driver_w5100 = {w5100_init, w5100_tx, w5100_rx,
w5100_up}; w5100_poll};
#endif #endif
+4 -4
View File
@@ -81,12 +81,12 @@ static bool w5500_init(struct mg_tcpip_if *ifp) {
return w5500_r1(s, W5500_S0, 3) == 0x42; // Sock0 SR == MACRAW return w5500_r1(s, W5500_S0, 3) == 0x42; // Sock0 SR == MACRAW
} }
static bool w5500_up(struct mg_tcpip_if *ifp) { static bool w5500_poll(struct mg_tcpip_if *ifp, bool s1) {
struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data; struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data;
uint8_t phycfgr = w5500_r1(spi, W5500_CR, 0x2e); return s1 ? w5500_r1(spi, W5500_CR, 0x2e /* PHYCFGR */) & 1
return phycfgr & 1; // Bit 0 of PHYCFGR is LNK (0 - down, 1 - up) : false; // Bit 0 of PHYCFGR is LNK (0 - down, 1 - up)
} }
struct mg_tcpip_driver mg_tcpip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx, struct mg_tcpip_driver mg_tcpip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx,
w5500_up}; w5500_poll};
#endif #endif
+74 -60
View File
@@ -4,34 +4,34 @@
struct ETH_GLOBAL_TypeDef { struct ETH_GLOBAL_TypeDef {
volatile uint32_t MAC_CONFIGURATION, MAC_FRAME_FILTER, HASH_TABLE_HIGH, volatile uint32_t MAC_CONFIGURATION, MAC_FRAME_FILTER, HASH_TABLE_HIGH,
HASH_TABLE_LOW, GMII_ADDRESS, GMII_DATA, FLOW_CONTROL, VLAN_TAG, VERSION, HASH_TABLE_LOW, GMII_ADDRESS, GMII_DATA, FLOW_CONTROL, VLAN_TAG, VERSION,
DEBUG, REMOTE_WAKE_UP_FRAME_FILTER, PMT_CONTROL_STATUS, RESERVED[2], DEBUG, REMOTE_WAKE_UP_FRAME_FILTER, PMT_CONTROL_STATUS, RESERVED[2],
INTERRUPT_STATUS, INTERRUPT_MASK, MAC_ADDRESS0_HIGH, MAC_ADDRESS0_LOW, INTERRUPT_STATUS, INTERRUPT_MASK, MAC_ADDRESS0_HIGH, MAC_ADDRESS0_LOW,
MAC_ADDRESS1_HIGH, MAC_ADDRESS1_LOW, MAC_ADDRESS2_HIGH, MAC_ADDRESS2_LOW, MAC_ADDRESS1_HIGH, MAC_ADDRESS1_LOW, MAC_ADDRESS2_HIGH, MAC_ADDRESS2_LOW,
MAC_ADDRESS3_HIGH, MAC_ADDRESS3_LOW, RESERVED1[40], MMC_CONTROL, MAC_ADDRESS3_HIGH, MAC_ADDRESS3_LOW, RESERVED1[40], MMC_CONTROL,
MMC_RECEIVE_INTERRUPT, MMC_TRANSMIT_INTERRUPT, MMC_RECEIVE_INTERRUPT_MASK, MMC_RECEIVE_INTERRUPT, MMC_TRANSMIT_INTERRUPT, MMC_RECEIVE_INTERRUPT_MASK,
MMC_TRANSMIT_INTERRUPT_MASK, TX_STATISTICS[26], RESERVED2, MMC_TRANSMIT_INTERRUPT_MASK, TX_STATISTICS[26], RESERVED2,
RX_STATISTICS_1[26], RESERVED3[6], MMC_IPC_RECEIVE_INTERRUPT_MASK, RX_STATISTICS_1[26], RESERVED3[6], MMC_IPC_RECEIVE_INTERRUPT_MASK,
RESERVED4, MMC_IPC_RECEIVE_INTERRUPT, RESERVED5, RX_STATISTICS_2[30], RESERVED4, MMC_IPC_RECEIVE_INTERRUPT, RESERVED5, RX_STATISTICS_2[30],
RESERVED7[286], TIMESTAMP_CONTROL, SUB_SECOND_INCREMENT, RESERVED7[286], TIMESTAMP_CONTROL, SUB_SECOND_INCREMENT,
SYSTEM_TIME_SECONDS, SYSTEM_TIME_NANOSECONDS, SYSTEM_TIME_SECONDS, SYSTEM_TIME_NANOSECONDS, SYSTEM_TIME_SECONDS_UPDATE,
SYSTEM_TIME_SECONDS_UPDATE, SYSTEM_TIME_NANOSECONDS_UPDATE, SYSTEM_TIME_NANOSECONDS_UPDATE, TIMESTAMP_ADDEND, TARGET_TIME_SECONDS,
TIMESTAMP_ADDEND, TARGET_TIME_SECONDS, TARGET_TIME_NANOSECONDS, TARGET_TIME_NANOSECONDS, SYSTEM_TIME_HIGHER_WORD_SECONDS,
SYSTEM_TIME_HIGHER_WORD_SECONDS, TIMESTAMP_STATUS, TIMESTAMP_STATUS, PPS_CONTROL, RESERVED8[564], BUS_MODE,
PPS_CONTROL, RESERVED8[564], BUS_MODE, TRANSMIT_POLL_DEMAND, TRANSMIT_POLL_DEMAND, RECEIVE_POLL_DEMAND,
RECEIVE_POLL_DEMAND, RECEIVE_DESCRIPTOR_LIST_ADDRESS, RECEIVE_DESCRIPTOR_LIST_ADDRESS, TRANSMIT_DESCRIPTOR_LIST_ADDRESS, STATUS,
TRANSMIT_DESCRIPTOR_LIST_ADDRESS, STATUS, OPERATION_MODE, OPERATION_MODE, INTERRUPT_ENABLE,
INTERRUPT_ENABLE, MISSED_FRAME_AND_BUFFER_OVERFLOW_COUNTER, MISSED_FRAME_AND_BUFFER_OVERFLOW_COUNTER,
RECEIVE_INTERRUPT_WATCHDOG_TIMER, RESERVED9, AHB_STATUS, RECEIVE_INTERRUPT_WATCHDOG_TIMER, RESERVED9, AHB_STATUS, RESERVED10[6],
RESERVED10[6], CURRENT_HOST_TRANSMIT_DESCRIPTOR, CURRENT_HOST_TRANSMIT_DESCRIPTOR, CURRENT_HOST_RECEIVE_DESCRIPTOR,
CURRENT_HOST_RECEIVE_DESCRIPTOR, CURRENT_HOST_TRANSMIT_BUFFER_ADDRESS, CURRENT_HOST_TRANSMIT_BUFFER_ADDRESS, CURRENT_HOST_RECEIVE_BUFFER_ADDRESS,
CURRENT_HOST_RECEIVE_BUFFER_ADDRESS, HW_FEATURE; HW_FEATURE;
}; };
#undef ETH0 #undef ETH0
#define ETH0 ((struct ETH_GLOBAL_TypeDef*) 0x5000C000UL) #define ETH0 ((struct ETH_GLOBAL_TypeDef *) 0x5000C000UL)
#define ETH_PKT_SIZE 1536 // Max frame size #define ETH_PKT_SIZE 1536 // Max frame size
#define ETH_DESC_CNT 4 // Descriptors count #define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 4 // Descriptor size (words) #define ETH_DS 4 // Descriptor size (words)
@@ -43,27 +43,27 @@ struct ETH_GLOBAL_TypeDef {
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] ETH_RAM_SECTION; static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] ETH_RAM_SECTION;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] ETH_RAM_SECTION; static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] ETH_RAM_SECTION;
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] ETH_RAM_SECTION; // RX descriptors static uint32_t s_rxdesc[ETH_DESC_CNT]
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] ETH_RAM_SECTION; // TX descriptors [ETH_DS] ETH_RAM_SECTION; // RX descriptors
static uint8_t s_txno; // Current TX descriptor static uint32_t s_txdesc[ETH_DESC_CNT]
static uint8_t s_rxno; // Current RX descriptor [ETH_DS] ETH_RAM_SECTION; // TX descriptors
static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor
static struct mg_tcpip_if *s_ifp; // MIP interface static struct mg_tcpip_if *s_ifp; // MIP interface
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 }; enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) { static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & 0x3c) | ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & 0x3c) | ((uint32_t) addr << 11) |
((uint32_t)addr << 11) | ((uint32_t) reg << 6) | 1;
((uint32_t)reg << 6) | 1;
while ((ETH0->GMII_ADDRESS & 1) != 0) (void) 0; while ((ETH0->GMII_ADDRESS & 1) != 0) (void) 0;
return (uint16_t)(ETH0->GMII_DATA & 0xffff); return (uint16_t) (ETH0->GMII_DATA & 0xffff);
} }
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) { static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
ETH0->GMII_DATA = val; ETH0->GMII_DATA = val;
ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & 0x3c) | ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & 0x3c) | ((uint32_t) addr << 11) |
((uint32_t)addr << 11) | ((uint32_t) reg << 6) | 3;
((uint32_t)reg << 6) | 3;
while ((ETH0->GMII_ADDRESS & 1) != 0) (void) 0; while ((ETH0->GMII_ADDRESS & 1) != 0) (void) 0;
} }
@@ -98,22 +98,22 @@ static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) {
// set the MAC address // set the MAC address
ETH0->MAC_ADDRESS0_HIGH = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]); ETH0->MAC_ADDRESS0_HIGH = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
ETH0->MAC_ADDRESS0_LOW = ETH0->MAC_ADDRESS0_LOW =
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]); MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
// Configure the receive filter // Configure the receive filter
ETH0->MAC_FRAME_FILTER = MG_BIT(10) | MG_BIT(2); // HFP, HMC ETH0->MAC_FRAME_FILTER = MG_BIT(10); // Perfect filter
// Disable flow control // Disable flow control
ETH0->FLOW_CONTROL = 0; ETH0->FLOW_CONTROL = 0;
// Enable store and forward mode // Enable store and forward mode
ETH0->OPERATION_MODE = MG_BIT(25) | MG_BIT(21); // RSF, TSF ETH0->OPERATION_MODE = MG_BIT(25) | MG_BIT(21); // RSF, TSF
// Configure DMA bus mode (AAL, USP, RPBL, PBL) // Configure DMA bus mode (AAL, USP, RPBL, PBL)
ETH0->BUS_MODE = MG_BIT(25) | MG_BIT(23) | (32 << 17) | (32 << 8); ETH0->BUS_MODE = MG_BIT(25) | MG_BIT(23) | (32 << 17) | (32 << 8);
// init RX descriptors // init RX descriptors
for (int i = 0; i < ETH_DESC_CNT; i++) { for (int i = 0; i < ETH_DESC_CNT; i++) {
s_rxdesc[i][0] = MG_BIT(31); // OWN descriptor s_rxdesc[i][0] = MG_BIT(31); // OWN descriptor
s_rxdesc[i][1] = MG_BIT(14) | ETH_PKT_SIZE; s_rxdesc[i][1] = MG_BIT(14) | ETH_PKT_SIZE;
s_rxdesc[i][2] = (uint32_t) s_rxbuf[i]; s_rxdesc[i][2] = (uint32_t) s_rxbuf[i];
if (i == ETH_DESC_CNT - 1) { if (i == ETH_DESC_CNT - 1) {
@@ -143,9 +143,9 @@ static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) {
ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF; ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF;
ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF; ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
ETH0->INTERRUPT_MASK = MG_BIT(9) | MG_BIT(3); // TSIM, PMTIM ETH0->INTERRUPT_MASK = MG_BIT(9) | MG_BIT(3); // TSIM, PMTIM
//Enable interrupts (NIE, RIE, TIE) // Enable interrupts (NIE, RIE, TIE)
ETH0->INTERRUPT_ENABLE = MG_BIT(16) | MG_BIT(6) | MG_BIT(0); ETH0->INTERRUPT_ENABLE = MG_BIT(16) | MG_BIT(6) | MG_BIT(0);
// Enable MAC transmission and reception (TE, RE) // Enable MAC transmission and reception (TE, RE)
@@ -156,7 +156,7 @@ static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) {
} }
static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len, static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len,
struct mg_tcpip_if *ifp) { struct mg_tcpip_if *ifp) {
if (len > sizeof(s_txbuf[s_txno])) { if (len > sizeof(s_txbuf[s_txno])) {
MG_ERROR(("Frame too big, %ld", (long) len)); MG_ERROR(("Frame too big, %ld", (long) len));
len = 0; // Frame is too big len = 0; // Frame is too big
@@ -174,12 +174,27 @@ static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len,
} }
// Resume processing // Resume processing
ETH0->STATUS = MG_BIT(2); // clear Transmit unavailable ETH0->STATUS = MG_BIT(2); // clear Transmit unavailable
ETH0->TRANSMIT_POLL_DEMAND = 0; ETH0->TRANSMIT_POLL_DEMAND = 0;
return len; return len;
} }
static bool mg_tcpip_driver_xmc_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_xmc_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
// set the multicast address filter
ETH0->MAC_ADDRESS1_HIGH =
MG_U32(0, 0, mcast_addr[5], mcast_addr[4]) | MG_BIT(31);
ETH0->MAC_ADDRESS1_LOW =
MG_U32(mcast_addr[3], mcast_addr[2], mcast_addr[1], mcast_addr[0]);
(void) ifp;
}
static bool mg_tcpip_driver_xmc_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_xmc_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_xmc_data *d = struct mg_tcpip_driver_xmc_data *d =
(struct mg_tcpip_driver_xmc_data *) ifp->driver_data; (struct mg_tcpip_driver_xmc_data *) ifp->driver_data;
uint8_t speed = MG_PHY_SPEED_10M; uint8_t speed = MG_PHY_SPEED_10M;
@@ -199,16 +214,15 @@ void ETH0_0_IRQHandler(void) {
// check if a frame was received // check if a frame was received
if (irq_status & MG_BIT(6)) { if (irq_status & MG_BIT(6)) {
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { for (uint8_t i = 0; i < 10; i++) { // read as they arrive, but not forever
if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) == 0) { if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break;
size_t len = (s_rxdesc[s_rxno][0] & 0x3fff0000) >> 16; size_t len = (s_rxdesc[s_rxno][0] & 0x3fff0000) >> 16;
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
s_rxdesc[s_rxno][0] = MG_BIT(31); // OWN bit: handle control to DMA s_rxdesc[s_rxno][0] = MG_BIT(31); // OWN bit: handle control to DMA
// Resume processing // Resume processing
ETH0->STATUS = MG_BIT(7) | MG_BIT(6); // clear RU and RI ETH0->STATUS = MG_BIT(7) | MG_BIT(6); // clear RU and RI
ETH0->RECEIVE_POLL_DEMAND = 0; ETH0->RECEIVE_POLL_DEMAND = 0;
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
}
} }
ETH0->STATUS = MG_BIT(6); ETH0->STATUS = MG_BIT(6);
} }
@@ -224,7 +238,7 @@ void ETH0_0_IRQHandler(void) {
} }
} }
struct mg_tcpip_driver mg_tcpip_driver_xmc = { struct mg_tcpip_driver mg_tcpip_driver_xmc = {mg_tcpip_driver_xmc_init,
mg_tcpip_driver_xmc_init, mg_tcpip_driver_xmc_tx, NULL, mg_tcpip_driver_xmc_tx, NULL,
mg_tcpip_driver_xmc_up}; mg_tcpip_driver_xmc_poll};
#endif #endif
+25 -13
View File
@@ -66,8 +66,8 @@ static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED; static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED; static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
static uint8_t s_txno MG_8BYTE_ALIGNED; // Current TX descriptor static uint8_t s_txno MG_8BYTE_ALIGNED; // Current TX descriptor
static uint8_t s_rxno MG_8BYTE_ALIGNED; // Current RX descriptor static uint8_t s_rxno MG_8BYTE_ALIGNED; // Current RX descriptor
static struct mg_tcpip_if *s_ifp; // MIP interface static struct mg_tcpip_if *s_ifp; // MIP interface
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 }; enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
@@ -104,8 +104,7 @@ static bool mg_tcpip_driver_xmc7_init(struct mg_tcpip_if *ifp) {
// set NSP change, ignore RX FCS, data bus width, clock rate // set NSP change, ignore RX FCS, data bus width, clock rate
// frame length 1536, full duplex, speed // frame length 1536, full duplex, speed
ETH0->NETWORK_CONFIG = MG_BIT(29) | MG_BIT(26) | MG_BIT(21) | ETH0->NETWORK_CONFIG = MG_BIT(29) | MG_BIT(26) | MG_BIT(21) |
((cr & 7) << 18) | MG_BIT(8) | MG_BIT(4) | MG_BIT(1) | ((cr & 7) << 18) | MG_BIT(8) | MG_BIT(1) | MG_BIT(0);
MG_BIT(0);
// config DMA settings: Force TX burst, Discard on Error, set RX buffer size // config DMA settings: Force TX burst, Discard on Error, set RX buffer size
// to 1536, TX_PBUF_SIZE, RX_PBUF_SIZE, AMBA_BURST_LENGTH // to 1536, TX_PBUF_SIZE, RX_PBUF_SIZE, AMBA_BURST_LENGTH
@@ -181,7 +180,21 @@ static size_t mg_tcpip_driver_xmc7_tx(const void *buf, size_t len,
return len; return len;
} }
static bool mg_tcpip_driver_xmc7_up(struct mg_tcpip_if *ifp) { static void mg_tcpip_driver_xmc7_update_hash_table(struct mg_tcpip_if *ifp) {
// TODO(): read database, rebuild hash table
// set multicast MAC address
ETH0->SPEC_ADD2_BOTTOM = mcast_addr[3] << 24 | mcast_addr[2] << 16 |
mcast_addr[1] << 8 | mcast_addr[0];
ETH0->SPEC_ADD2_TOP = mcast_addr[5] << 8 | mcast_addr[4];
(void) ifp;
}
static bool mg_tcpip_driver_xmc7_poll(struct mg_tcpip_if *ifp, bool s1) {
if (ifp->update_mac_hash_table) {
mg_tcpip_driver_xmc7_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
if (!s1) return false;
struct mg_tcpip_driver_xmc7_data *d = struct mg_tcpip_driver_xmc7_data *d =
(struct mg_tcpip_driver_xmc7_data *) ifp->driver_data; (struct mg_tcpip_driver_xmc7_data *) ifp->driver_data;
uint8_t speed = MG_PHY_SPEED_10M; uint8_t speed = MG_PHY_SPEED_10M;
@@ -219,13 +232,12 @@ static bool mg_tcpip_driver_xmc7_up(struct mg_tcpip_if *ifp) {
void ETH_IRQHandler(void) { void ETH_IRQHandler(void) {
uint32_t irq_status = ETH0->INT_STATUS; uint32_t irq_status = ETH0->INT_STATUS;
if (irq_status & MG_BIT(1)) { if (irq_status & MG_BIT(1)) {
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) { for (uint8_t i = 0; i < 10; i++) { // read as they arrive, but not forever
if (s_rxdesc[s_rxno][0] & MG_BIT(0)) { if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1); size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
s_rxdesc[s_rxno][0] &= ~MG_BIT(0); // OWN bit: handle control to DMA s_rxdesc[s_rxno][0] &= ~MG_BIT(0); // OWN bit: handle control to DMA
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0; if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
}
} }
} }
@@ -234,5 +246,5 @@ void ETH_IRQHandler(void) {
struct mg_tcpip_driver mg_tcpip_driver_xmc7 = {mg_tcpip_driver_xmc7_init, struct mg_tcpip_driver mg_tcpip_driver_xmc7 = {mg_tcpip_driver_xmc7_init,
mg_tcpip_driver_xmc7_tx, NULL, mg_tcpip_driver_xmc7_tx, NULL,
mg_tcpip_driver_xmc7_up}; mg_tcpip_driver_xmc7_poll};
#endif #endif
+1 -1
View File
@@ -28,7 +28,7 @@ struct mg_fs {
}; };
extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek extern struct mg_fs mg_fs_posix; // POSIX open/close/read/write/seek
extern struct mg_fs mg_fs_packed; // Packed FS, see examples/device-dashboard extern struct mg_fs mg_fs_packed; // see tutorials/core/embedded-filesystem
extern struct mg_fs mg_fs_fat; // FAT FS extern struct mg_fs mg_fs_fat; // FAT FS
// File descriptor // File descriptor
+1
View File
@@ -502,6 +502,7 @@ static struct mg_str s_known_types[] = {
MG_C_STR("htm"), MG_C_STR("text/html; charset=utf-8"), MG_C_STR("htm"), MG_C_STR("text/html; charset=utf-8"),
MG_C_STR("css"), MG_C_STR("text/css; charset=utf-8"), MG_C_STR("css"), MG_C_STR("text/css; charset=utf-8"),
MG_C_STR("js"), MG_C_STR("text/javascript; charset=utf-8"), MG_C_STR("js"), MG_C_STR("text/javascript; charset=utf-8"),
MG_C_STR("mjs"), MG_C_STR("text/javascript; charset=utf-8"),
MG_C_STR("gif"), MG_C_STR("image/gif"), MG_C_STR("gif"), MG_C_STR("image/gif"),
MG_C_STR("png"), MG_C_STR("image/png"), MG_C_STR("png"), MG_C_STR("image/png"),
MG_C_STR("jpg"), MG_C_STR("image/jpeg"), MG_C_STR("jpg"), MG_C_STR("image/jpeg"),
+3 -2
View File
@@ -57,7 +57,8 @@ void mg_hexdump(const void *buf, size_t len) {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if ((i % 16) == 0) { if ((i % 16) == 0) {
// Print buffered ascii chars // Print buffered ascii chars
if (i > 0) logs(" ", 2), logs((char *) ascii, 16), logc('\n'), alen = 0; if (i > 0)
logs(" ", 2), logs((char *) ascii, 16), logs("\r\n", 2), alen = 0;
// Print hex address, then \t // Print hex address, then \t
logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)), logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)),
logc(nibble((i >> 4) & 15)), logc('0'), logs(" ", 3); logc(nibble((i >> 4) & 15)), logc('0'), logs(" ", 3);
@@ -67,5 +68,5 @@ void mg_hexdump(const void *buf, size_t len) {
ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.'; // Add to the ascii buf ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.'; // Add to the ascii buf
} }
while (alen < 16) logs(" ", 3), ascii[alen++] = ' '; while (alen < 16) logs(" ", 3), ascii[alen++] = ' ';
logs(" ", 2), logs((char *) ascii, 16), logc('\n'); logs(" ", 2), logs((char *) ascii, 16), logs("\r\n", 2);
} }
+5 -2
View File
@@ -1,7 +1,7 @@
#include "net.h"
#include "dns.h" #include "dns.h"
#include "fmt.h" #include "fmt.h"
#include "log.h" #include "log.h"
#include "net.h"
#include "printf.h" #include "printf.h"
#include "profile.h" #include "profile.h"
#include "timer.h" #include "timer.h"
@@ -218,8 +218,8 @@ struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
unsigned flags, void (*fn)(void *), void *arg) { unsigned flags, void (*fn)(void *), void *arg) {
struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t)); struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
if (t != NULL) { if (t != NULL) {
flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg); mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
t->id = mgr->timerid++;
} }
return t; return t;
} }
@@ -247,6 +247,9 @@ void mg_mgr_free(struct mg_mgr *mgr) {
if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1; if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
#endif #endif
mg_tls_ctx_free(mgr); mg_tls_ctx_free(mgr);
#if MG_ENABLE_TCPIP
if (mgr->ifp) mg_tcpip_free(mgr->ifp);
#endif
} }
void mg_mgr_init(struct mg_mgr *mgr) { void mg_mgr_init(struct mg_mgr *mgr) {
+35 -35
View File
@@ -27,7 +27,6 @@ struct mg_mgr {
int dnstimeout; // DNS resolve timeout in milliseconds int dnstimeout; // DNS resolve timeout in milliseconds
bool use_dns6; // Use DNS6 server by default, see #1532 bool use_dns6; // Use DNS6 server by default, see #1532
unsigned long nextid; // Next connection ID unsigned long nextid; // Next connection ID
unsigned long timerid; // Next timer ID
void *userdata; // Arbitrary user data pointer void *userdata; // Arbitrary user data pointer
void *tls_ctx; // TLS context shared by all TLS sessions void *tls_ctx; // TLS context shared by all TLS sessions
uint16_t mqtt_id; // MQTT IDs for pub/sub uint16_t mqtt_id; // MQTT IDs for pub/sub
@@ -43,40 +42,41 @@ struct mg_mgr {
}; };
struct mg_connection { struct mg_connection {
struct mg_connection *next; // Linkage in struct mg_mgr :: connections struct mg_connection *next; // Linkage in struct mg_mgr :: connections
struct mg_mgr *mgr; // Our container struct mg_mgr *mgr; // Our container
struct mg_addr loc; // Local address struct mg_addr loc; // Local address
struct mg_addr rem; // Remote address struct mg_addr rem; // Remote address
void *fd; // Connected socket, or LWIP data void *fd; // Connected socket, or LWIP data
unsigned long id; // Auto-incrementing unique connection ID unsigned long id; // Auto-incrementing unique connection ID
struct mg_iobuf recv; // Incoming data struct mg_iobuf recv; // Incoming data
struct mg_iobuf send; // Outgoing data struct mg_iobuf send; // Outgoing data
struct mg_iobuf prof; // Profile data enabled by MG_ENABLE_PROFILE struct mg_iobuf prof; // Profile data enabled by MG_ENABLE_PROFILE
struct mg_iobuf rtls; // TLS only. Incoming encrypted data struct mg_iobuf rtls; // TLS only. Incoming encrypted data
mg_event_handler_t fn; // User-specified event handler function mg_event_handler_t fn; // User-specified event handler function
void *fn_data; // User-specified function parameter void *fn_data; // User-specified function parameter
mg_event_handler_t pfn; // Protocol-specific handler function mg_event_handler_t pfn; // Protocol-specific handler function
void *pfn_data; // Protocol-specific function parameter void *pfn_data; // Protocol-specific function parameter
char data[MG_DATA_SIZE]; // Arbitrary connection data char data[MG_DATA_SIZE]; // Arbitrary connection data
void *tls; // TLS specific data void *tls; // TLS specific data
unsigned is_listening : 1; // Listening connection unsigned is_listening : 1; // Listening connection
unsigned is_client : 1; // Outbound (client) connection unsigned is_client : 1; // Outbound (client) connection
unsigned is_accepted : 1; // Accepted (server) connection unsigned is_accepted : 1; // Accepted (server) connection
unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress unsigned is_resolving : 1; // Non-blocking DNS resolution is in progress
unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress unsigned is_arplooking : 1; // Non-blocking ARP resolution is in progress
unsigned is_connecting : 1; // Non-blocking connect is in progress unsigned is_connecting : 1; // Non-blocking connect is in progress
unsigned is_tls : 1; // TLS-enabled connection unsigned is_tls : 1; // TLS-enabled connection
unsigned is_tls_hs : 1; // TLS handshake is in progress unsigned is_tls_hs : 1; // TLS handshake is in progress
unsigned is_udp : 1; // UDP connection unsigned is_udp : 1; // UDP connection
unsigned is_websocket : 1; // WebSocket connection unsigned is_websocket : 1; // WebSocket connection
unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator unsigned is_mqtt5 : 1; // For MQTT connection, v5 indicator
unsigned is_hexdumping : 1; // Hexdump in/out traffic unsigned is_hexdumping : 1; // Hexdump in/out traffic
unsigned is_draining : 1; // Send remaining data, then close and free unsigned is_draining : 1; // Send remaining data, then close and free
unsigned is_closing : 1; // Close and free the connection immediately unsigned is_closing : 1; // Close and free the connection immediately
unsigned is_full : 1; // Stop reads, until cleared unsigned is_full : 1; // Stop reads, until cleared
unsigned is_resp : 1; // Response is still being generated unsigned is_tls_throttled : 1; // Last TLS write: MG_SOCK_PENDING() was true
unsigned is_readable : 1; // Connection is ready to read unsigned is_resp : 1; // Response is still being generated
unsigned is_writable : 1; // Connection is ready to write unsigned is_readable : 1; // Connection is ready to read
unsigned is_writable : 1; // Connection is ready to write
}; };
void mg_mgr_poll(struct mg_mgr *, int ms); void mg_mgr_poll(struct mg_mgr *, int ms);
+147 -90
View File
@@ -1,6 +1,6 @@
#include "net_builtin.h" #include "net_builtin.h"
#if defined(MG_ENABLE_TCPIP) && MG_ENABLE_TCPIP #if MG_ENABLE_TCPIP
#define MG_EPHEMERAL_PORT_BASE 32768 #define MG_EPHEMERAL_PORT_BASE 32768
#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a)))) #define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
@@ -16,11 +16,12 @@
struct connstate { struct connstate {
uint32_t seq, ack; // TCP seq/ack counters uint32_t seq, ack; // TCP seq/ack counters
uint64_t timer; // TCP keep-alive / ACK timer uint64_t timer; // TCP timer (see 'ttype' below)
uint32_t acked; // Last ACK-ed number uint32_t acked; // Last ACK-ed number
size_t unacked; // Not acked bytes size_t unacked; // Not acked bytes
uint16_t dmss; // destination MSS (from TCP opts)
uint8_t mac[6]; // Peer MAC address uint8_t mac[6]; // Peer MAC address
uint8_t ttype; // Timer type. 0: ack, 1: keep-alive uint8_t ttype; // Timer type:
#define MIP_TTYPE_KEEPALIVE 0 // Connection is idle for long, send keepalive #define MIP_TTYPE_KEEPALIVE 0 // Connection is idle for long, send keepalive
#define MIP_TTYPE_ACK 1 // Peer sent us data, we have to ack it soon #define MIP_TTYPE_ACK 1 // Peer sent us data, we have to ack it soon
#define MIP_TTYPE_ARP 2 // ARP resolve sent, waiting for response #define MIP_TTYPE_ARP 2 // ARP resolve sent, waiting for response
@@ -121,7 +122,7 @@ struct dhcp {
uint32_t ciaddr, yiaddr, siaddr, giaddr; uint32_t ciaddr, yiaddr, siaddr, giaddr;
uint8_t hwaddr[208]; uint8_t hwaddr[208];
uint32_t magic; uint32_t magic;
uint8_t options[32]; uint8_t options[30 + sizeof(((struct mg_tcpip_if *) 0)->dhcp_name)];
}; };
#pragma pack(pop) #pragma pack(pop)
@@ -176,6 +177,7 @@ static void settmout(struct mg_connection *c, uint8_t type) {
: type == MIP_TTYPE_SYN ? MIP_TCP_SYN_MS : type == MIP_TTYPE_SYN ? MIP_TCP_SYN_MS
: type == MIP_TTYPE_FIN ? MIP_TCP_FIN_MS : type == MIP_TTYPE_FIN ? MIP_TCP_FIN_MS
: MIP_TCP_KEEPALIVE_MS; : MIP_TCP_KEEPALIVE_MS;
if (s->ttype == MIP_TTYPE_FIN) return; // skip if 3-way closing
s->timer = ifp->now + n; s->timer = ifp->now + n;
s->ttype = type; s->ttype = type;
MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer)); MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
@@ -280,22 +282,26 @@ static const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255};
// RFC-2131 #4.3.6, #4.4.1; RFC-2132 #9.8 // RFC-2131 #4.3.6, #4.4.1; RFC-2132 #9.8
static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req, static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req,
uint32_t ip_srv) { uint32_t ip_srv) {
uint8_t opts[] = { uint8_t extra = (uint8_t) ((ifp->enable_req_dns ? 1 : 0) +
53, 1, 3, // Type: DHCP request (ifp->enable_req_sntp ? 1 : 0));
12, 3, 'm', 'i', 'p', // Host name: "mip" size_t len = strlen(ifp->dhcp_name);
54, 4, 0, 0, 0, 0, // DHCP server ID size_t olen = 21 + len + extra + 2 + 1; // Total length of options
50, 4, 0, 0, 0, 0, // Requested IP #define OPTS_MAXLEN (21 + sizeof(ifp->dhcp_name) + 2 + 2 + 1)
55, 2, 1, 3, 255, 255, // GW, mask [DNS] [SNTP] uint8_t opts[OPTS_MAXLEN]; // Allocate options (max size possible)
255 // End of options uint8_t *p = opts;
}; assert(olen <= sizeof(opts));
uint8_t addopts = 0; memset(opts, 0, sizeof(opts));
memcpy(opts + 10, &ip_srv, sizeof(ip_srv)); *p++ = 53, *p++ = 1, *p++ = 3; // Type: DHCP request
memcpy(opts + 16, &ip_req, sizeof(ip_req)); *p++ = 54, *p++ = 4, memcpy(p, &ip_srv, 4), p += 4; // DHCP server ID
if (ifp->enable_req_dns) opts[24 + addopts++] = 6; // DNS *p++ = 50, *p++ = 4, memcpy(p, &ip_req, 4), p += 4; // Requested IP
if (ifp->enable_req_sntp) opts[24 + addopts++] = 42; // SNTP *p++ = 12, *p++ = (uint8_t) (len & 255); // DHCP host
opts[21] += addopts; memcpy(p, ifp->dhcp_name, len), p += len; // name
tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, *p++ = 55, *p++ = 2 + extra, *p++ = 1, *p++ = 3; // GW, MASK
sizeof(opts) + addopts - 2, false); if (ifp->enable_req_dns) *p++ = 6; // DNS
if (ifp->enable_req_sntp) *p++ = 42; // SNTP
*p++ = 255; // End of options
// assert((size_t) (p - opts) < olen);
tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, olen, 0);
MG_DEBUG(("DHCP req sent")); MG_DEBUG(("DHCP req sent"));
} }
@@ -520,17 +526,17 @@ static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip, static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
uint8_t flags, uint16_t sport, uint16_t dport, uint8_t flags, uint16_t sport, uint16_t dport,
uint32_t seq, uint32_t ack, const void *buf, size_t len) { uint32_t seq, uint32_t ack, const void *buf, size_t len) {
#if 0 struct ip *ip;
uint8_t opts[] = {2, 4, 5, 0xb4, 4, 2, 0, 0}; // MSS = 1460, SACK permitted struct tcp *tcp;
if (flags & TH_SYN) { uint16_t opts[4 / 2];
// Handshake? Set MSS if (flags & TH_SYN) { // Send MSS, RFC-9293 3.7.1
opts[0] = mg_htons(0x0204); // RFC-9293 3.2
opts[1] = mg_htons(ifp->mtu - 40); // RFC-6691
buf = opts; buf = opts;
len = sizeof(opts); len = sizeof(opts);
} }
#endif ip = tx_ip(ifp, dst_mac, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
struct ip *ip = tcp = (struct tcp *) (ip + 1);
tx_ip(ifp, dst_mac, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
struct tcp *tcp = (struct tcp *) (ip + 1);
memset(tcp, 0, sizeof(*tcp)); memset(tcp, 0, sizeof(*tcp));
if (buf != NULL && len) memmove(tcp + 1, buf, len); if (buf != NULL && len) memmove(tcp + 1, buf, len);
tcp->sport = sport; tcp->sport = sport;
@@ -540,7 +546,7 @@ static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
tcp->flags = flags; tcp->flags = flags;
tcp->win = mg_htons(MIP_TCP_WIN); tcp->win = mg_htons(MIP_TCP_WIN);
tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4); tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
// if (flags & TH_SYN) tcp->off = 0x70; // Handshake? header size 28 bytes if (flags & TH_SYN) tcp->off += (uint8_t) (sizeof(opts) / 4 << 4);
uint32_t cs = 0; uint32_t cs = 0;
uint16_t n = (uint16_t) (sizeof(*tcp) + len); uint16_t n = (uint16_t) (sizeof(*tcp) + len);
@@ -574,6 +580,7 @@ static struct mg_connection *accept_conn(struct mg_connection *lsn,
return NULL; return NULL;
} }
struct connstate *s = (struct connstate *) (c + 1); struct connstate *s = (struct connstate *) (c + 1);
s->dmss = 1460; // TODO(scaprile): 536; // assume default, RFC-9293 3.7.1
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq); s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
memcpy(s->mac, pkt->eth->src, sizeof(s->mac)); memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
settmout(c, MIP_TTYPE_KEEPALIVE); settmout(c, MIP_TTYPE_KEEPALIVE);
@@ -627,10 +634,11 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
len = trim_len(c, len); len = trim_len(c, len);
if (c->is_udp) { if (c->is_udp) {
tx_udp(ifp, s->mac, ifp->ip, c->loc.port, dst_ip, c->rem.port, buf, len); tx_udp(ifp, s->mac, ifp->ip, c->loc.port, dst_ip, c->rem.port, buf, len);
} else { } else { // TCP, cap to peer's MSS
size_t sent = size_t sent;
tx_tcp(ifp, s->mac, dst_ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port, if (len > s->dmss) len = s->dmss; // RFC-6691: reduce if sending opts
mg_htonl(s->seq), mg_htonl(s->ack), buf, len); sent = tx_tcp(ifp, s->mac, dst_ip, TH_PUSH | TH_ACK, c->loc.port,
c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), buf, len);
if (sent == 0) { if (sent == 0) {
return MG_IO_WAIT; return MG_IO_WAIT;
} else if (sent == (size_t) -1) { } else if (sent == (size_t) -1) {
@@ -651,7 +659,8 @@ static void handle_tls_recv(struct mg_connection *c) {
mg_error(c, "oom"); mg_error(c, "oom");
} else { } else {
// Decrypt data directly into c->recv // Decrypt data directly into c->recv
long n = mg_tls_recv(c, &io->buf[io->len], io->size - io->len); long n = mg_tls_recv(c, io->buf != NULL ? &io->buf[io->len] : io->buf,
io->size - io->len);
if (n == MG_IO_ERR) { if (n == MG_IO_ERR) {
mg_error(c, "TLS recv error"); mg_error(c, "TLS recv error");
} else if (n > 0) { } else if (n > 0) {
@@ -689,8 +698,10 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
} }
tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port, tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
mg_htonl(s->seq), mg_htonl(s->ack), "", 0); mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
} else if (pkt->pay.len == 0) { // this is an ACK if (pkt->pay.len == 0) return; // if no data, we're done
} else if (pkt->pay.len == 0) { // this is an ACK
if (s->fin_rcvd && s->ttype == MIP_TTYPE_FIN) s->twclosure = true; if (s->fin_rcvd && s->ttype == MIP_TTYPE_FIN) s->twclosure = true;
return; // no data to process
} else if (seq != s->ack) { } else if (seq != s->ack) {
uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len); uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
if (s->ack == ack) { if (s->ack == ack) {
@@ -700,44 +711,62 @@ static void read_conn(struct mg_connection *c, struct pkt *pkt) {
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port, tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
mg_htonl(s->seq), mg_htonl(s->ack), "", 0); mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
} }
return; // drop it
} else if (io->size - io->len < pkt->pay.len && } else if (io->size - io->len < pkt->pay.len &&
!mg_iobuf_resize(io, io->len + pkt->pay.len)) { !mg_iobuf_resize(io, io->len + pkt->pay.len)) {
mg_error(c, "oom"); mg_error(c, "oom");
return; // drop it
}
// Copy TCP payload into the IO buffer. If the connection is plain text,
// we copy to c->recv. If the connection is TLS, this data is encrypted,
// therefore we copy that encrypted data to the c->rtls iobuffer instead,
// and then call mg_tls_recv() to decrypt it. NOTE: mg_tls_recv() will
// call back mg_io_recv() which grabs raw data from c->rtls
memcpy(&io->buf[io->len], pkt->pay.buf, pkt->pay.len);
io->len += pkt->pay.len;
MG_VERBOSE(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
// Advance ACK counter
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
s->unacked += pkt->pay.len;
// size_t diff = s->acked <= s->ack ? s->ack - s->acked : s->ack;
if (s->unacked > MIP_TCP_WIN / 2 && s->acked != s->ack) {
// Send ACK immediately
MG_VERBOSE(("%lu imm ACK %lu", c->id, s->acked));
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
s->unacked = 0;
s->acked = s->ack;
if (s->ttype != MIP_TTYPE_KEEPALIVE) settmout(c, MIP_TTYPE_KEEPALIVE);
} else { } else {
// Copy TCP payload into the IO buffer. If the connection is plain text, // if not already running, setup a timer to send an ACK later
// we copy to c->recv. If the connection is TLS, this data is encrypted, if (s->ttype != MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_ACK);
// therefore we copy that encrypted data to the c->rtls iobuffer instead, }
// and then call mg_tls_recv() to decrypt it. NOTE: mg_tls_recv() will if (c->is_tls && c->is_tls_hs) {
// call back mg_io_recv() which grabs raw data from c->rtls mg_tls_handshake(c);
memcpy(&io->buf[io->len], pkt->pay.buf, pkt->pay.len); } else if (c->is_tls) {
io->len += pkt->pay.len; handle_tls_recv(c);
} else {
// Plain text connection, data is already in c->recv, trigger MG_EV_READ
mg_call(c, MG_EV_READ, &pkt->pay.len);
}
}
MG_VERBOSE(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack)); // process options (MSS)
// Advance ACK counter static void handle_opt(struct connstate *s, struct tcp *tcp) {
s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len); uint8_t *opts = (uint8_t *) (tcp + 1);
s->unacked += pkt->pay.len; int len = 4 * ((int) (tcp->off >> 4) - ((int) sizeof(*tcp) / 4));
// size_t diff = s->acked <= s->ack ? s->ack - s->acked : s->ack; s->dmss = 536; // assume default, RFC-9293 3.7.1
if (s->unacked > MIP_TCP_WIN / 2 && s->acked != s->ack) { while (len > 0) { // RFC-9293 3.1 3.2
// Send ACK immediately uint8_t kind = opts[0], optlen = 1;
MG_VERBOSE(("%lu imm ACK %lu", c->id, s->acked)); if (kind != 1) { // No-Operation
tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port, if (kind == 0) break; // End of Option List
mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0); optlen = opts[1];
s->unacked = 0; if (kind == 2 && optlen == 4) // set received MSS
s->acked = s->ack; s->dmss = (uint16_t) (((uint16_t) opts[2] << 8) + opts[3]);
if (s->ttype != MIP_TTYPE_KEEPALIVE) settmout(c, MIP_TTYPE_KEEPALIVE);
} else {
// if not already running, setup a timer to send an ACK later
if (s->ttype != MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_ACK);
}
if (c->is_tls && c->is_tls_hs) {
mg_tls_handshake(c);
} else if (c->is_tls) {
handle_tls_recv(c);
} else {
// Plain text connection, data is already in c->recv, trigger MG_EV_READ
mg_call(c, MG_EV_READ, &pkt->pay.len);
} }
MG_VERBOSE(("kind: %u, optlen: %u, len: %d\n", kind, optlen, len));
opts += optlen;
len -= optlen;
} }
} }
@@ -748,6 +777,7 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len)); MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len));
#endif #endif
if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) { if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) {
handle_opt(s, pkt->tcp); // process options (MSS)
s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1; s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1;
tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0); tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0);
c->is_connecting = 0; // Client connected c->is_connecting = 0; // Client connected
@@ -777,6 +807,8 @@ static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
if (c->is_accepted) mg_error(c, "peer RST"); // RFC-1122 4.2.2.13 if (c->is_accepted) mg_error(c, "peer RST"); // RFC-1122 4.2.2.13
// ignore RST if not connected // ignore RST if not connected
} else if (pkt->tcp->flags & TH_SYN) { } else if (pkt->tcp->flags & TH_SYN) {
// TODO(): handle_opt(s, pkt->tcp); // process options (MSS)
// At this point, s = NULL, there is no connection.
// Use peer's source port as ISN, in order to recognise the handshake // Use peer's source port as ISN, in order to recognise the handshake
uint32_t isn = mg_htonl((uint32_t) mg_ntohs(pkt->tcp->sport)); uint32_t isn = mg_htonl((uint32_t) mg_ntohs(pkt->tcp->sport));
tx_tcp_pkt(ifp, pkt, TH_SYN | TH_ACK, isn, NULL, 0); tx_tcp_pkt(ifp, pkt, TH_SYN | TH_ACK, isn, NULL, 0);
@@ -914,24 +946,27 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
ifp->state = MG_TCPIP_STATE_READY; // keep best-effort MAC ifp->state = MG_TCPIP_STATE_READY; // keep best-effort MAC
onstatechange(ifp); onstatechange(ifp);
} }
// Handle physical interface up/down status // poll driver
if (expired_1000ms && ifp->driver->up) { if (ifp->driver->poll) {
bool up = ifp->driver->up(ifp); bool up = ifp->driver->poll(ifp, expired_1000ms);
bool current = ifp->state != MG_TCPIP_STATE_DOWN; // Handle physical interface up/down status
if (!up && ifp->enable_dhcp_client) ifp->ip = 0; if (expired_1000ms) {
if (up != current) { // link state has changed bool current = ifp->state != MG_TCPIP_STATE_DOWN;
ifp->state = up == false ? MG_TCPIP_STATE_DOWN if (!up && ifp->enable_dhcp_client) ifp->ip = 0;
: ifp->enable_dhcp_client || ifp->ip == 0 if (up != current) { // link state has changed
? MG_TCPIP_STATE_UP ifp->state = up == false ? MG_TCPIP_STATE_DOWN
: MG_TCPIP_STATE_IP; : ifp->enable_dhcp_client || ifp->ip == 0
onstatechange(ifp); ? MG_TCPIP_STATE_UP
} else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP && : MG_TCPIP_STATE_IP;
ifp->ip) { onstatechange(ifp);
ifp->state = MG_TCPIP_STATE_IP; // ifp->fn has set an IP } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
onstatechange(ifp); ifp->ip) {
ifp->state = MG_TCPIP_STATE_IP; // ifp->fn has set an IP
onstatechange(ifp);
}
if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
} }
if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
} }
if (ifp->state == MG_TCPIP_STATE_DOWN) return; if (ifp->state == MG_TCPIP_STATE_DOWN) return;
@@ -953,14 +988,14 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
} }
// Read data from the network // Read data from the network
if (ifp->driver->rx != NULL) { // Polling driver. We must call it if (ifp->driver->rx != NULL) { // Simple polling driver, returns one frame
size_t len = size_t len =
ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp); ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp);
if (len > 0) { if (len > 0) {
ifp->nrecv++; ifp->nrecv++;
mg_tcpip_rx(ifp, ifp->recv_queue.buf, len); mg_tcpip_rx(ifp, ifp->recv_queue.buf, len);
} }
} else { // Interrupt-based driver. Fills recv queue itself } else { // Complex poll / Interrupt-based driver. Queues recvd frames
char *buf; char *buf;
size_t len = mg_queue_next(&ifp->recv_queue, &buf); size_t len = mg_queue_next(&ifp->recv_queue, &buf);
if (len > 0) { if (len > 0) {
@@ -1029,6 +1064,12 @@ void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
MG_INFO(("MAC not set. Generated random: %M", mg_print_mac, ifp->mac)); MG_INFO(("MAC not set. Generated random: %M", mg_print_mac, ifp->mac));
} }
// If DHCP name is not set, use "mip"
if (ifp->dhcp_name[0] == '\0') {
memcpy(ifp->dhcp_name, "mip", 4);
}
ifp->dhcp_name[sizeof(ifp->dhcp_name) - 1] = '\0'; // Just in case
if (ifp->driver->init && !ifp->driver->init(ifp)) { if (ifp->driver->init && !ifp->driver->init(ifp)) {
MG_ERROR(("driver init failed")); MG_ERROR(("driver init failed"));
} else { } else {
@@ -1075,6 +1116,13 @@ static void mac_resolved(struct mg_connection *c) {
} }
} }
static void ip4_mcastmac(uint8_t *mac, uint32_t *ip) {
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group MAC
memcpy(mac, mcastp, 3);
memcpy(mac + 3, ((uint8_t *) ip) + 1, 3); // 23 LSb
mac[3] &= 0x7F;
}
void mg_connect_resolved(struct mg_connection *c) { void mg_connect_resolved(struct mg_connection *c) {
struct mg_tcpip_if *ifp = c->mgr->ifp; struct mg_tcpip_if *ifp = c->mgr->ifp;
uint32_t rem_ip; uint32_t rem_ip;
@@ -1100,10 +1148,7 @@ void mg_connect_resolved(struct mg_connection *c) {
c->is_arplooking = 1; c->is_arplooking = 1;
} else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) { } else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF
uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group ip4_mcastmac(s->mac, &rem_ip); // multicast group
memcpy(s->mac, mcastp, 3);
memcpy(s->mac + 3, ((uint8_t *) &rem_ip) + 1, 3); // 23 LSb
s->mac[3] &= 0x7F;
mac_resolved(c); mac_resolved(c);
} else { } else {
struct connstate *s = (struct connstate *) (c + 1); struct connstate *s = (struct connstate *) (c + 1);
@@ -1114,6 +1159,10 @@ void mg_connect_resolved(struct mg_connection *c) {
bool mg_open_listener(struct mg_connection *c, const char *url) { bool mg_open_listener(struct mg_connection *c, const char *url) {
c->loc.port = mg_htons(mg_url_port(url)); c->loc.port = mg_htons(mg_url_port(url));
if (!mg_aton(mg_url_host(url), &c->loc)) {
MG_ERROR(("invalid listening URL: %s", url));
return false;
}
return true; return true;
} }
@@ -1201,4 +1250,12 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
} }
return res; return res;
} }
uint8_t mcast_addr[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb};
void mg_multicast_add(struct mg_connection *c, char *ip) {
(void) ip; // ip4_mcastmac(mcast_mac, &ip);
// TODO(): actual IP -> MAC; check database, update
c->mgr->ifp->update_mac_hash_table = true; // mark dirty
}
#endif // MG_ENABLE_TCPIP #endif // MG_ENABLE_TCPIP
+20 -7
View File
@@ -5,27 +5,34 @@
#include "queue.h" #include "queue.h"
#include "str.h" #include "str.h"
#if MG_ENABLE_TCPIP
struct mg_tcpip_if; // Mongoose TCP/IP network interface struct mg_tcpip_if; // Mongoose TCP/IP network interface
struct mg_tcpip_driver { struct mg_tcpip_driver {
bool (*init)(struct mg_tcpip_if *); // Init driver bool (*init)(struct mg_tcpip_if *); // Init driver
size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame size_t (*tx)(const void *, size_t, struct mg_tcpip_if *); // Transmit frame
size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame size_t (*rx)(void *buf, size_t len, struct mg_tcpip_if *); // Receive frame
bool (*up)(struct mg_tcpip_if *); // Up/down status bool (*poll)(struct mg_tcpip_if *, bool); // Poll, return Up/down status
}; };
typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev, typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev,
void *ev_data); void *ev_data);
enum { enum {
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state) MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str * MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
MG_TCPIP_EV_USER // Starting ID for user events MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct mg_wifi_scan_bss_data *
MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL
MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and chip specific
MG_TCPIP_EV_DRIVER, // Driver event driver specific
MG_TCPIP_EV_USER // Starting ID for user events
}; };
// Network interface // Network interface
struct mg_tcpip_if { struct mg_tcpip_if {
uint8_t mac[6]; // MAC address. Must be set to a valid MAC uint8_t mac[6]; // MAC address. Must be set to a valid MAC
@@ -38,11 +45,13 @@ struct mg_tcpip_if {
bool enable_req_sntp; // DCHP client requests SNTP server bool enable_req_sntp; // DCHP client requests SNTP server
bool enable_crc32_check; // Do a CRC check on RX frames and strip it bool enable_crc32_check; // Do a CRC check on RX frames and strip it
bool enable_mac_check; // Do a MAC check on RX frames bool enable_mac_check; // Do a MAC check on RX frames
bool update_mac_hash_table; // Signal drivers to update MAC controller
struct mg_tcpip_driver *driver; // Low level driver struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data void *driver_data; // Driver-specific data
mg_tcpip_event_handler_t fn; // User-specified event handler function mg_tcpip_event_handler_t fn; // User-specified event handler function
struct mg_mgr *mgr; // Mongoose event manager struct mg_mgr *mgr; // Mongoose event manager
struct mg_queue recv_queue; // Receive queue struct mg_queue recv_queue; // Receive queue
char dhcp_name[12]; // Name reported to DHCP, "mip" if unset
uint16_t mtu; // Interface MTU uint16_t mtu; // Interface MTU
#define MG_TCPIP_MTU_DEFAULT 1500 #define MG_TCPIP_MTU_DEFAULT 1500
@@ -71,6 +80,7 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac);
extern struct mg_tcpip_driver mg_tcpip_driver_stm32f; extern struct mg_tcpip_driver mg_tcpip_driver_stm32f;
extern struct mg_tcpip_driver mg_tcpip_driver_w5500; extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
extern struct mg_tcpip_driver mg_tcpip_driver_w5100;
extern struct mg_tcpip_driver mg_tcpip_driver_tm4c; extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
extern struct mg_tcpip_driver mg_tcpip_driver_tms570; extern struct mg_tcpip_driver mg_tcpip_driver_tms570;
extern struct mg_tcpip_driver mg_tcpip_driver_stm32h; extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
@@ -83,6 +93,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_xmc7;
extern struct mg_tcpip_driver mg_tcpip_driver_ppp; extern struct mg_tcpip_driver mg_tcpip_driver_ppp;
extern struct mg_tcpip_driver mg_tcpip_driver_pico_w; extern struct mg_tcpip_driver mg_tcpip_driver_pico_w;
extern struct mg_tcpip_driver mg_tcpip_driver_rw612; extern struct mg_tcpip_driver mg_tcpip_driver_rw612;
extern struct mg_tcpip_driver mg_tcpip_driver_cyw;
// Drivers that require SPI, can use this SPI abstraction // Drivers that require SPI, can use this SPI abstraction
struct mg_tcpip_spi { struct mg_tcpip_spi {
@@ -91,3 +102,5 @@ struct mg_tcpip_spi {
void (*end)(void *); // SPI end: slave select high void (*end)(void *); // SPI end: slave select high
uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
}; };
#endif
+5 -3
View File
@@ -13,10 +13,12 @@
#define MG_OTA_CH32V307 100 // WCH CH32V307 #define MG_OTA_CH32V307 100 // WCH CH32V307
#define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6 #define MG_OTA_U2A 200 // Renesas U2A16, U2A8, U2A6
#define MG_OTA_RT1020 300 // IMXRT1020 #define MG_OTA_RT1020 300 // IMXRT1020
#define MG_OTA_RT1060 301 // IMXRT1060 #define MG_OTA_RT1050 301 // IMXRT1050
#define MG_OTA_RT1064 302 // IMXRT1064 #define MG_OTA_RT1060 302 // IMXRT1060
#define MG_OTA_RT1170 303 // IMXRT1170 #define MG_OTA_RT1064 303 // IMXRT1064
#define MG_OTA_RT1170 304 // IMXRT1170
#define MG_OTA_MCXN 310 // MCXN947 #define MG_OTA_MCXN 310 // MCXN947
#define MG_OTA_FRDM 320 // FRDM-RW612
#define MG_OTA_FLASH 900 // OTA via an internal flash #define MG_OTA_FLASH 900 // OTA via an internal flash
#define MG_OTA_ESP32 910 // ESP32 OTA implementation #define MG_OTA_ESP32 910 // ESP32 OTA implementation
#define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash #define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash
+364
View File
@@ -0,0 +1,364 @@
#include "flash.h"
#include "log.h"
#include "ota.h"
#if MG_OTA == MG_OTA_FRDM
MG_IRAM static bool mg_frdm_write(void *, const void *, size_t);
static bool mg_frdm_swap(void);
static struct mg_flash s_mg_flash_frdm = {(void *) 0x08000000, // Start,
0x200000, // Size
0x1000, // Sector size
0x100, // Align
mg_frdm_write,
mg_frdm_swap};
struct mg_flexspi_lut_seq {
uint8_t seqNum;
uint8_t seqId;
uint16_t reserved;
};
struct mg_flexspi_mem_config {
uint32_t tag;
uint32_t version;
uint32_t reserved0;
uint8_t readSampleClkSrc;
uint8_t csHoldTime;
uint8_t csSetupTime;
uint8_t columnAddressWidth;
uint8_t deviceModeCfgEnable;
uint8_t deviceModeType;
uint16_t waitTimeCfgCommands;
struct mg_flexspi_lut_seq deviceModeSeq;
uint32_t deviceModeArg;
uint8_t configCmdEnable;
uint8_t configModeType[3];
struct mg_flexspi_lut_seq configCmdSeqs[3];
uint32_t reserved1;
uint32_t configCmdArgs[3];
uint32_t reserved2;
uint32_t controllerMiscOption;
uint8_t deviceType;
uint8_t sflashPadType;
uint8_t serialClkFreq;
uint8_t lutCustomSeqEnable;
uint32_t reserved3[2];
uint32_t sflashA1Size;
uint32_t sflashA2Size;
uint32_t sflashB1Size;
uint32_t sflashB2Size;
uint32_t csPadSettingOverride;
uint32_t sclkPadSettingOverride;
uint32_t dataPadSettingOverride;
uint32_t dqsPadSettingOverride;
uint32_t timeoutInMs;
uint32_t commandInterval;
uint16_t dataValidTime[2];
uint16_t busyOffset;
uint16_t busyBitPolarity;
uint32_t lookupTable[64];
struct mg_flexspi_lut_seq lutCustomSeq[12];
uint32_t reserved4[4];
};
struct mg_flexspi_nor_config {
struct mg_flexspi_mem_config memConfig;
uint32_t pageSize;
uint32_t sectorSize;
uint8_t ipcmdSerialClkFreq;
uint8_t isUniformBlockSize;
uint8_t isDataOrderSwapped;
uint8_t reserved0[1];
uint8_t serialNorType;
uint8_t needExitNoCmdMode;
uint8_t halfClkForNonReadCmd;
uint8_t needRestoreNoCmdMode;
uint32_t blockSize;
uint32_t flashStateCtx;
uint32_t reserve2[10];
};
struct mg_flexspi_nor_driver_interface {
uint32_t version;
uint32_t (*init)(uint32_t instance, struct mg_flexspi_nor_config *config);
uint32_t (*wait_busy)(uint32_t instance, struct mg_flexspi_nor_config *config,
uint32_t address, bool keepState);
uint32_t (*page_program)(uint32_t instance,
struct mg_flexspi_nor_config *config,
uint32_t dstAddr, const uint32_t *src,
bool keepState);
uint32_t (*erase_all)(uint32_t instance,
struct mg_flexspi_nor_config *config);
uint32_t (*erase)(uint32_t instance, struct mg_flexspi_nor_config *config,
uint32_t start, uint32_t length);
uint32_t (*erase_sector)(uint32_t instance,
struct mg_flexspi_nor_config *config,
uint32_t address);
uint32_t (*erase_block)(uint32_t instance,
struct mg_flexspi_nor_config *config,
uint32_t address);
uint32_t (*read)(uint32_t instance, struct mg_flexspi_nor_config *config,
uint32_t *dst, uint32_t start, uint32_t bytes);
void (*config_clock)(uint32_t instance, uint32_t freqOption,
uint32_t sampleClkMode);
uint32_t (*set_clock_source)(uint32_t clockSrc);
uint32_t (*get_config)(uint32_t instance,
struct mg_flexspi_nor_config *config,
uint32_t *option);
void (*hw_reset)(uint32_t instance, uint32_t reset_logic);
uint32_t (*xfer)(uint32_t instance, char *xfer);
uint32_t (*update_lut)(uint32_t instance, uint32_t seqIndex,
const uint32_t *lutBase, uint32_t numberOfSeq);
uint32_t (*partial_program)(uint32_t instance,
struct mg_flexspi_nor_config *config,
uint32_t dstAddr, const uint32_t *src,
uint32_t length, bool keepState);
};
#define MG_FLEXSPI_CFG_BLK_TAG (0x42464346UL)
#define MG_FLEXSPI_BASE 0x40134000UL
#define MG_CMD_SDR 0x01
#define MG_RADDR_SDR 0x02
#define MG_WRITE_SDR 0x08
#define MG_READ_SDR 0x09
#define MG_DUMMY_SDR 0x0C
#define MG_STOP_EXE 0
#define MG_FLEXSPI_1PAD 0
#define MG_FLEXSPI_4PAD 2
#define MG_FLEXSPI_LUT_OPERAND0(x) (((x) &0xFF) << 0)
#define MG_FLEXSPI_LUT_NUM_PADS0(x) (((x) &0x3) << 8)
#define MG_FLEXSPI_LUT_OPCODE0(x) (((x) &0x3F) << 10)
#define MG_FLEXSPI_LUT_OPERAND1(x) (((x) &0xFF) << 16)
#define MG_FLEXSPI_LUT_NUM_PADS1(x) (((x) &0x3) << 24)
#define MG_FLEXSPI_LUT_OPCODE1(x) (((x) &0x3F) << 26)
#define MG_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \
(MG_FLEXSPI_LUT_OPERAND0(op0) | MG_FLEXSPI_LUT_NUM_PADS0(pad0) | \
MG_FLEXSPI_LUT_OPCODE0(cmd0) | MG_FLEXSPI_LUT_OPERAND1(op1) | \
MG_FLEXSPI_LUT_NUM_PADS1(pad1) | MG_FLEXSPI_LUT_OPCODE1(cmd1))
struct mg_flexspi_nor_config default_config = {
.memConfig =
{
.tag = MG_FLEXSPI_CFG_BLK_TAG,
.version = 0,
.readSampleClkSrc = 1,
.csHoldTime = 3,
.csSetupTime = 3,
.deviceModeCfgEnable = 1,
.deviceModeSeq = {.seqNum = 1, .seqId = 2},
.deviceModeArg = 0x0740,
.configCmdEnable = 0,
.deviceType = 0x1,
.sflashPadType = 4,
.serialClkFreq = 4,
.sflashA1Size = 0x4000000U,
.sflashA2Size = 0,
.sflashB1Size = 0,
.sflashB2Size = 0,
.lookupTable =
{
[0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0xEB,
MG_RADDR_SDR, MG_FLEXSPI_4PAD, 0x18),
[1] =
MG_FLEXSPI_LUT_SEQ(MG_DUMMY_SDR, MG_FLEXSPI_4PAD, 0x06,
MG_READ_SDR, MG_FLEXSPI_4PAD, 0x04),
[4 * 1 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x05,
MG_READ_SDR, MG_FLEXSPI_1PAD, 0x04),
[4 * 2 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x01,
MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x02),
[4 * 3 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x06,
MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00),
[4 * 5 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x20,
MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18),
[4 * 8 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x52,
MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18),
[4 * 9 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x02,
MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18),
[4 * 9 + 1] =
MG_FLEXSPI_LUT_SEQ(MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x00,
MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00),
[4 * 11 + 0] =
MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x60,
MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00),
},
},
.pageSize = 0x100,
.sectorSize = 0x1000,
.ipcmdSerialClkFreq = 0,
.blockSize = 0x8000,
};
#define MG_FLEXSPI_NOR_INSTANCE 0
#define MG_ROMAPI_ADDRESS 0x13030000U
#define flexspi_nor \
((struct mg_flexspi_nor_driver_interface *) (( \
(uint32_t *) MG_ROMAPI_ADDRESS)[5]))
MG_IRAM static bool flash_page_start(volatile uint32_t *dst) {
char *base = (char *) s_mg_flash_frdm.start,
*end = base + s_mg_flash_frdm.size;
volatile char *p = (char *) dst;
return p >= base && p < end && ((p - base) % s_mg_flash_frdm.secsz) == 0;
}
MG_IRAM static int flexspi_nor_get_config(
struct mg_flexspi_nor_config *config) {
uint32_t option = 0xc0000004;
return flexspi_nor->get_config(MG_FLEXSPI_NOR_INSTANCE, config, &option);
}
MG_IRAM static int flash_init(void) {
static bool initialized = false;
if (!initialized) {
struct mg_flexspi_nor_config config;
memset(&config, 0, sizeof(config));
flexspi_nor->set_clock_source(0);
flexspi_nor->config_clock(MG_FLEXSPI_NOR_INSTANCE, 1, 0);
if (flexspi_nor->init(MG_FLEXSPI_NOR_INSTANCE, &default_config)) {
return 1;
}
flexspi_nor_get_config(&config);
if (flexspi_nor->init(MG_FLEXSPI_NOR_INSTANCE, &config)) {
return 1;
}
initialized = true;
}
return 0;
}
MG_IRAM static bool flash_erase(struct mg_flexspi_nor_config *config,
void *addr) {
if (flash_page_start(addr) == false) {
MG_ERROR(("%p is not on a sector boundary", addr));
return false;
}
void *dst = (void *) ((char *) addr - (char *) s_mg_flash_frdm.start);
bool ok = (flexspi_nor->erase_sector(MG_FLEXSPI_NOR_INSTANCE, config,
(uint32_t) dst) == 0);
MG_INFO(("Sector starting at %p erasure: %s", addr, ok ? "ok" : "fail"));
return ok;
}
MG_IRAM bool mg_frdm_swap(void) {
return true;
}
MG_IRAM static void flash_wait(void) {
while ((*((volatile uint32_t *) (MG_FLEXSPI_BASE + 0xE0)) & MG_BIT(1)) == 0)
(void) 0;
}
static bool s_flash_irq_disabled;
MG_IRAM static bool mg_frdm_write(void *addr, const void *buf, size_t len) {
struct mg_flexspi_nor_config config;
bool ok = false;
MG_ARM_DISABLE_IRQ();
if (flash_init() != 0) goto fwxit;
if (flexspi_nor_get_config(&config) != 0) goto fwxit;
if ((len % s_mg_flash_frdm.align) != 0) {
MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_frdm.align));
goto fwxit;
}
if ((char *) addr < (char *) s_mg_flash_frdm.start) {
MG_ERROR(("Invalid flash write address: %p", addr));
goto fwxit;
}
uint32_t *dst = (uint32_t *) addr;
uint32_t *src = (uint32_t *) buf;
uint32_t *end = (uint32_t *) ((char *) buf + len);
ok = true;
while (ok && src < end) {
if (flash_page_start(dst) && flash_erase(&config, dst) == false) {
ok = false;
break;
}
uint32_t status;
uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_frdm.start;
if ((char *) buf >= (char *) s_mg_flash_frdm.start &&
(char *) buf <
(char *) (s_mg_flash_frdm.start + s_mg_flash_frdm.size)) {
// If we copy from FLASH to FLASH, then we first need to copy the source
// to RAM
size_t tmp_buf_size = s_mg_flash_frdm.align / sizeof(uint32_t);
uint32_t tmp[tmp_buf_size];
for (size_t i = 0; i < tmp_buf_size; i++) {
flash_wait();
tmp[i] = src[i];
}
status = flexspi_nor->page_program(MG_FLEXSPI_NOR_INSTANCE, &config,
(uint32_t) dst_ofs, tmp, false);
} else {
status = flexspi_nor->page_program(MG_FLEXSPI_NOR_INSTANCE, &config,
(uint32_t) dst_ofs, src, false);
}
src = (uint32_t *) ((char *) src + s_mg_flash_frdm.align);
dst = (uint32_t *) ((char *) dst + s_mg_flash_frdm.align);
if (status != 0) {
ok = false;
}
}
MG_INFO(("Flash write %lu bytes @ %p: %s.", len, dst, ok ? "ok" : "fail"));
fwxit:
if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ();
return ok;
}
// just overwrite instead of swap
MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
// no stdlib calls here
for (size_t ofs = 0; ofs < s; ofs += ss) {
mg_frdm_write(p1 + ofs, p2 + ofs, ss);
}
*(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
}
bool mg_ota_begin(size_t new_firmware_size) {
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_frdm);
}
bool mg_ota_write(const void *buf, size_t len) {
return mg_ota_flash_write(buf, len, &s_mg_flash_frdm);
}
bool mg_ota_end(void) {
if (mg_ota_flash_end(&s_mg_flash_frdm)) {
if (0) { // is_dualbank()
// TODO(): no devices so far
*(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
} else {
// Swap partitions. Pray power does not go away
MG_INFO(("Swapping partitions, size %u (%u sectors)",
s_mg_flash_frdm.size,
s_mg_flash_frdm.size / s_mg_flash_frdm.secsz));
MG_INFO(("Do NOT power off..."));
mg_log_level = MG_LL_NONE;
s_flash_irq_disabled = true;
// Runs in RAM, will reset when finished
single_bank_swap(
(char *) s_mg_flash_frdm.start,
(char *) s_mg_flash_frdm.start + s_mg_flash_frdm.size / 2,
s_mg_flash_frdm.size / 2, s_mg_flash_frdm.secsz);
}
}
return false;
}
#endif
+197 -28
View File
@@ -13,18 +13,26 @@ static bool mg_imxrt_swap(void);
#elif MG_OTA == MG_OTA_RT1064 #elif MG_OTA == MG_OTA_RT1064
#define MG_IMXRT_FLASH_START 0x70000000 #define MG_IMXRT_FLASH_START 0x70000000
#define FLEXSPI_NOR_INSTANCE 1 #define FLEXSPI_NOR_INSTANCE 1
#else // RT1170 #else // RT1170
#define MG_IMXRT_FLASH_START 0x30000000 #define MG_IMXRT_FLASH_START 0x30000000
#define FLEXSPI_NOR_INSTANCE 1 #define FLEXSPI_NOR_INSTANCE 1
#endif #endif
#if MG_OTA == MG_OTA_RT1050
#define MG_IMXRT_SECTOR_SIZE (256 * 1024)
#define MG_IMXRT_PAGE_SIZE 512
#else
#define MG_IMXRT_SECTOR_SIZE (4 * 1024)
#define MG_IMXRT_PAGE_SIZE 256
#endif
// TODO(): fill at init, support more devices in a dynamic way // TODO(): fill at init, support more devices in a dynamic way
// TODO(): then, check alignment is <= 256, see Wizard's #251 // TODO(): then, check alignment is <= 256, see Wizard's #251
static struct mg_flash s_mg_flash_imxrt = { static struct mg_flash s_mg_flash_imxrt = {
(void *) MG_IMXRT_FLASH_START, // Start, (void *) MG_IMXRT_FLASH_START, // Start,
4 * 1024 * 1024, // Size, 4mb 4 * 1024 * 1024, // Size, 4mb
4 * 1024, // Sector size, 4k MG_IMXRT_SECTOR_SIZE, // Sector size
256, // Align, MG_IMXRT_PAGE_SIZE, // Align
mg_imxrt_write, mg_imxrt_write,
mg_imxrt_swap, mg_imxrt_swap,
}; };
@@ -106,8 +114,10 @@ struct mg_flexspi_nor_config {
#define MG_CMD_DDR 0x21 #define MG_CMD_DDR 0x21
#define MG_DUMMY_SDR 0x0C #define MG_DUMMY_SDR 0x0C
#define MG_DUMMY_DDR 0x2C #define MG_DUMMY_DDR 0x2C
#define MG_DUMMY_RWDS_DDR 0x2D
#define MG_RADDR_SDR 0x02 #define MG_RADDR_SDR 0x02
#define MG_RADDR_DDR 0x22 #define MG_RADDR_DDR 0x22
#define MG_CADDR_DDR 0x23
#define MG_READ_SDR 0x09 #define MG_READ_SDR 0x09
#define MG_READ_DDR 0x29 #define MG_READ_DDR 0x29
#define MG_WRITE_SDR 0x08 #define MG_WRITE_SDR 0x08
@@ -141,6 +151,131 @@ struct mg_flexspi_nor_config {
MG_STOP, MG_FLEXSPI_1PAD, 0x0), \ MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
} }
#define MG_FLEXSPI_HYPER_LUT \
{ \
[0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xA0, MG_RADDR_DDR, \
MG_FLEXSPI_8PAD, 0x18), \
[1] = MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
MG_DUMMY_DDR, MG_FLEXSPI_8PAD, 0x0C), \
[2] = MG_FLEXSPI_LUT_SEQ(MG_READ_DDR, MG_FLEXSPI_8PAD, 0x04, MG_STOP, \
MG_FLEXSPI_1PAD, 0x0), \
[4 * 1 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 1 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 1 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 1 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x70), \
[4 * 2 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xA0, \
MG_RADDR_DDR, MG_FLEXSPI_8PAD, 0x18), \
[4 * 2 + 1] = \
MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
MG_DUMMY_RWDS_DDR, MG_FLEXSPI_8PAD, 0x0B), \
[4 * 2 + 2] = MG_FLEXSPI_LUT_SEQ(MG_READ_DDR, MG_FLEXSPI_8PAD, 0x4, \
MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
[4 * 3 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 3 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 3 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 3 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 4 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 4 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
[4 * 4 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x02), \
[4 * 4 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
[4 * 5 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 5 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 5 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 5 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x80), \
[4 * 6 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 6 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 6 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 6 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 7 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 7 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
[4 * 7 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x02), \
[4 * 7 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
[4 * 8 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_RADDR_DDR, MG_FLEXSPI_8PAD, 0x18), \
[4 * 8 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 8 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x30, \
MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
[4 * 9 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 9 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 9 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 9 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xA0), \
[4 * 10 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_RADDR_DDR, MG_FLEXSPI_8PAD, 0x18), \
[4 * 10 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
MG_WRITE_DDR, MG_FLEXSPI_8PAD, 0x80), \
[4 * 11 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 11 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 11 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 11 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x80), \
[4 * 12 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 12 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 12 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 12 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 13 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 13 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
[4 * 13 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x02), \
[4 * 13 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
[4 * 14 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
[4 * 14 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
[4 * 14 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
[4 * 14 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x10), \
}
#define MG_LUT_CUSTOM_SEQ \
{ \
{.seqNum = 0, .seqId = 0, .reserved = 0}, \
{.seqNum = 2, .seqId = 1, .reserved = 0}, \
{.seqNum = 2, .seqId = 3, .reserved = 0}, \
{.seqNum = 4, .seqId = 5, .reserved = 0}, \
{.seqNum = 2, .seqId = 9, .reserved = 0}, \
{.seqNum = 4, .seqId = 11, .reserved = 0}, \
}
#define MG_FLEXSPI_LUT_OPERAND0(x) (((uint32_t) (((uint32_t) (x)))) & 0xFFU) #define MG_FLEXSPI_LUT_OPERAND0(x) (((uint32_t) (((uint32_t) (x)))) & 0xFFU)
#define MG_FLEXSPI_LUT_NUM_PADS0(x) \ #define MG_FLEXSPI_LUT_NUM_PADS0(x) \
(((uint32_t) (((uint32_t) (x)) << 8U)) & 0x300U) (((uint32_t) (((uint32_t) (x)) << 8U)) & 0x300U)
@@ -153,8 +288,8 @@ struct mg_flexspi_nor_config {
#define MG_FLEXSPI_LUT_OPCODE1(x) \ #define MG_FLEXSPI_LUT_OPCODE1(x) \
(((uint32_t) (((uint32_t) (x)) << 26U)) & 0xFC000000U) (((uint32_t) (((uint32_t) (x)) << 26U)) & 0xFC000000U)
#if MG_OTA == MG_OTA_RT1020 #if MG_OTA == MG_OTA_RT1020 || MG_OTA == MG_OTA_RT1050
// RT102X boards support ROM API version 1.4 // RT102X and RT105x boards support ROM API version 1.4
struct mg_flexspi_nor_driver_interface { struct mg_flexspi_nor_driver_interface {
uint32_t version; uint32_t version;
int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config); int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config);
@@ -212,10 +347,10 @@ struct mg_flexspi_nor_driver_interface {
uint32_t address); uint32_t address);
void (*hw_reset)(uint32_t instance, uint32_t resetLogic); void (*hw_reset)(uint32_t instance, uint32_t resetLogic);
int (*wait_busy)(uint32_t instance, struct mg_flexspi_nor_config *config, int (*wait_busy)(uint32_t instance, struct mg_flexspi_nor_config *config,
bool isParallelMode, uint32_t address); bool isParallelMode, uint32_t address);
int (*set_clock_source)(uint32_t instance, uint32_t clockSrc); int (*set_clock_source)(uint32_t instance, uint32_t clockSrc);
void (*config_clock)(uint32_t instance, uint32_t freqOption, void (*config_clock)(uint32_t instance, uint32_t freqOption,
uint32_t sampleClkMode); uint32_t sampleClkMode);
}; };
#endif #endif
@@ -234,33 +369,67 @@ struct mg_flexspi_nor_driver_interface {
static bool s_flash_irq_disabled; static bool s_flash_irq_disabled;
MG_IRAM static bool flash_page_start(volatile uint32_t *dst) { MG_IRAM static bool flash_page_start(volatile uint32_t *dst) {
char *base = (char *) s_mg_flash_imxrt.start, *end = base + s_mg_flash_imxrt.size; char *base = (char *) s_mg_flash_imxrt.start,
*end = base + s_mg_flash_imxrt.size;
volatile char *p = (char *) dst; volatile char *p = (char *) dst;
return p >= base && p < end && ((p - base) % s_mg_flash_imxrt.secsz) == 0; return p >= base && p < end && ((p - base) % s_mg_flash_imxrt.secsz) == 0;
} }
// Note: the get_config function below works both for RT1020 and 1060 #if MG_OTA == MG_OTA_RT1050
// must reside in RAM, as flash will be erased // Configuration for Hyper flash memory
static struct mg_flexspi_nor_config default_config = { static struct mg_flexspi_nor_config default_config = {
.memConfig = {.tag = MG_FLEXSPI_CFG_BLK_TAG, .memConfig =
.version = MG_FLEXSPI_CFG_BLK_VERSION, {
.readSampleClkSrc = 1, // ReadSampleClk_LoopbackFromDqsPad .tag = MG_FLEXSPI_CFG_BLK_TAG,
.csHoldTime = 3, .version = MG_FLEXSPI_CFG_BLK_VERSION,
.csSetupTime = 3, .readSampleClkSrc = 3, // ReadSampleClk_LoopbackFromDqsPad
.controllerMiscOption = MG_BIT(4), .csHoldTime = 3,
.deviceType = 1, // serial NOR .csSetupTime = 3,
.sflashPadType = 4, .columnAddressWidth = 3u,
.serialClkFreq = 7, // 133MHz .controllerMiscOption =
.sflashA1Size = 8 * 1024 * 1024, MG_BIT(6) | MG_BIT(4) | MG_BIT(3) | MG_BIT(0),
.lookupTable = MG_FLEXSPI_QSPI_LUT}, .deviceType = 1, // serial NOR
.pageSize = 256, .sflashPadType = 8,
.sectorSize = 4 * 1024, .serialClkFreq = 7, // 133MHz
.ipcmdSerialClkFreq = 1, .sflashA1Size = 64 * 1024 * 1024,
.blockSize = 64 * 1024, .dataValidTime = {15, 0},
.isUniformBlockSize = false .busyOffset = 15,
}; .busyBitPolarity = 1,
.lutCustomSeqEnable = 0x1,
.lookupTable = MG_FLEXSPI_HYPER_LUT,
.lutCustomSeq = MG_LUT_CUSTOM_SEQ,
},
.pageSize = 512,
.sectorSize = 256 * 1024,
.ipcmdSerialClkFreq = 1,
.serialNorType = 1u,
.blockSize = 256 * 1024,
.isUniformBlockSize = true};
#else
// Note: this QSPI configuration works for RTs supporting QSPI
// Configuration for QSPI memory
static struct mg_flexspi_nor_config default_config = {
.memConfig = {.tag = MG_FLEXSPI_CFG_BLK_TAG,
.version = MG_FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = 1, // ReadSampleClk_LoopbackFromDqsPad
.csHoldTime = 3,
.csSetupTime = 3,
.controllerMiscOption = MG_BIT(4),
.deviceType = 1, // serial NOR
.sflashPadType = 4,
.serialClkFreq = 7, // 133MHz
.sflashA1Size = 8 * 1024 * 1024,
.lookupTable = MG_FLEXSPI_QSPI_LUT},
.pageSize = 256,
.sectorSize = 4 * 1024,
.ipcmdSerialClkFreq = 1,
.blockSize = 64 * 1024,
.isUniformBlockSize = false};
#endif
// must reside in RAM, as flash will be erased
MG_IRAM static int flexspi_nor_get_config( MG_IRAM static int flexspi_nor_get_config(
struct mg_flexspi_nor_config **config) { struct mg_flexspi_nor_config **config) {
*config = &default_config; *config = &default_config;
return 0; return 0;
} }
+1 -1
View File
@@ -6,7 +6,7 @@
// timestamp in milliseconds since connection init time. // timestamp in milliseconds since connection init time.
// //
// Test (run in two separate terminals): // Test (run in two separate terminals):
// make -C examples/http-server/ CFLAGS_EXTRA=-DMG_ENABLE_PROFILE=1 // make -C tutorials/http/http-server/ CFLAGS_EXTRA=-DMG_ENABLE_PROFILE=1
// curl localhost:8000 // curl localhost:8000
// Output: // Output:
// 1ea1f1e7 2 net.c:150:mg_close_conn 3 profile: // 1ea1f1e7 2 net.c:150:mg_close_conn 3 profile:
+8 -12
View File
@@ -173,15 +173,11 @@ void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
mg_sha256_final(dst, &ctx); mg_sha256_final(dst, &ctx);
} }
//===================================== #define rotr64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
// TODO: rename macros #define ep064(x) (rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39))
#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n)))) #define ep164(x) (rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) #define sig064(x) (rotr64(x, 1) ^ rotr64(x, 8) ^ ((x) >> 7))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define sig164(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ ((x) >> 6))
#define EP0(x) (ROTR64(x, 28) ^ ROTR64(x, 34) ^ ROTR64(x, 39))
#define EP1(x) (ROTR64(x, 14) ^ ROTR64(x, 18) ^ ROTR64(x, 41))
#define SIG0(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ ((x) >> 7))
#define SIG1(x) (ROTR64(x, 19) ^ ROTR64(x, 61) ^ ((x) >> 6))
static const uint64_t mg_sha256_k2[80] = { static const uint64_t mg_sha256_k2[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
@@ -223,7 +219,7 @@ static void mg_sha384_transform(mg_sha384_ctx *ctx, const uint8_t data[]) {
((uint64_t) data[j + 4] << 24) | ((uint64_t) data[j + 5] << 16) | ((uint64_t) data[j + 4] << 24) | ((uint64_t) data[j + 5] << 16) |
((uint64_t) data[j + 6] << 8) | ((uint64_t) data[j + 7]); ((uint64_t) data[j + 6] << 8) | ((uint64_t) data[j + 7]);
for (; i < 80; ++i) for (; i < 80; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; m[i] = sig164(m[i - 2]) + m[i - 7] + sig064(m[i - 15]) + m[i - 16];
a = ctx->state[0]; a = ctx->state[0];
b = ctx->state[1]; b = ctx->state[1];
@@ -235,8 +231,8 @@ static void mg_sha384_transform(mg_sha384_ctx *ctx, const uint8_t data[]) {
h = ctx->state[7]; h = ctx->state[7];
for (i = 0; i < 80; ++i) { for (i = 0; i < 80; ++i) {
uint64_t t1 = h + EP1(e) + CH(e, f, g) + mg_sha256_k2[i] + m[i]; uint64_t t1 = h + ep164(e) + ch(e, f, g) + mg_sha256_k2[i] + m[i];
uint64_t t2 = EP0(a) + MAJ(a, b, c); uint64_t t2 = ep064(a) + maj(a, b, c);
h = g; h = g;
g = f; g = f;
f = e; f = e;
+23 -4
View File
@@ -128,7 +128,7 @@ long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
} }
MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n))); MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n)));
if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; if (MG_SOCK_PENDING(n)) return MG_IO_WAIT;
if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507 if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507
if (n <= 0) return MG_IO_ERR; if (n <= 0) return MG_IO_ERR;
return n; return n;
} }
@@ -176,6 +176,25 @@ static void mg_set_non_blocking_mode(MG_SOCKET_TYPE fd) {
#endif #endif
} }
void mg_multicast_add(struct mg_connection *c, char *ip);
void mg_multicast_add(struct mg_connection *c, char *ip) {
#if MG_ENABLE_RL
#error UNSUPPORTED
#elif MG_ENABLE_FREERTOS_TCP
// TODO(): prvAllowIPPacketIPv4()
#else
// lwIP, Unix, Windows, Zephyr(, AzureRTOS ?)
#if MG_ENABLE_LWIP && !LWIP_IGMP
MG_ERROR(("LWIP_IGMP not defined, no multicast support"));
#else
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(ip);
mreq.imr_interface.s_addr = mg_htonl(INADDR_ANY);
setsockopt(FD(c), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
#endif
#endif
}
bool mg_open_listener(struct mg_connection *c, const char *url) { bool mg_open_listener(struct mg_connection *c, const char *url) {
MG_SOCKET_TYPE fd = MG_INVALID_SOCKET; MG_SOCKET_TYPE fd = MG_INVALID_SOCKET;
bool success = false; bool success = false;
@@ -250,7 +269,7 @@ static long recv_raw(struct mg_connection *c, void *buf, size_t len) {
} }
MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n))); MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n)));
if (MG_SOCK_PENDING(n)) return MG_IO_WAIT; if (MG_SOCK_PENDING(n)) return MG_IO_WAIT;
if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507 if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507
if (n <= 0) return MG_IO_ERR; if (n <= 0) return MG_IO_ERR;
return n; return n;
} }
@@ -287,11 +306,11 @@ static void read_conn(struct mg_connection *c) {
} }
// there can still be > 16K from last iteration, always mg_tls_recv() // there can still be > 16K from last iteration, always mg_tls_recv()
m = c->is_tls_hs ? (long) MG_IO_WAIT : mg_tls_recv(c, buf, len); m = c->is_tls_hs ? (long) MG_IO_WAIT : mg_tls_recv(c, buf, len);
if (n == MG_IO_ERR || n == MG_IO_RESET) { // Windows, see #3031 if (n == MG_IO_ERR || n == MG_IO_RESET) { // Windows, see #3031
if (c->rtls.len == 0 || m < 0) { if (c->rtls.len == 0 || m < 0) {
// Close only when we have fully drained both rtls and TLS buffers // Close only when we have fully drained both rtls and TLS buffers
c->is_closing = 1; // or there's nothing we can do about it. c->is_closing = 1; // or there's nothing we can do about it.
m = MG_IO_ERR; if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104
} else { // see #2885 } else { // see #2885
// TLS buffer is capped to max record size, even though, there can // TLS buffer is capped to max record size, even though, there can
// be more than one record, give TLS a chance to process them. // be more than one record, give TLS a chance to process them.
Loaded 100 of 2789 files, more files were not shown because too many files have changed in this diff. Show more