Compare commits

...
280 Commits
Author SHA1 Message Date
Sergio R. Caprile 236724ea29 fix mg_send() failing on 0 length 2025-11-19 17:02:28 -03:00
Sergio R. Caprile b503915ca5 update version 2025-11-19 10:04:04 -03:00
Sergio R. Caprile 156db0bc5e enable CYW driver autoinit 2025-11-19 09:57:37 -03:00
Sergey Lyubka 11b6bd7d9c Merge pull request #3338 from cesanta/tls
Fix 2-way auth max msg size, + some neats
2025-11-18 00:46:38 +00:00
Sergio R. Caprile 7ca952faa6 Merge pull request #3342 from cesanta/lsnb4ip
Allow listeners to start before stack is ready
2025-11-17 15:38:38 -03:00
Sergio R. Caprile 4fc40f0ffb Allow listeners to start before stack is ready 2025-11-17 15:23:37 -03:00
cpq cac4b3e254 Fix TM4C warnings on TI compiler (C89) 2025-11-14 06:49:53 +00:00
robert 0d5cb5cbcc undef ENET 2025-11-13 08:02:55 -05:00
Sergio R. Caprile a35901121b Fix 2-way auth max msg size, + some neats 2025-11-12 20:13:06 -03:00
novlean e0740fc2ca Merge pull request #3337 from cesanta/novlean-patch-1
Update README.md
2025-11-10 16:30:57 +00:00
novlean 7d22b5fe18 Update README.md
article 9 added
2025-11-10 16:30:44 +00:00
Sergey Lyubka d2e66ac58d Merge pull request #3325 from cesanta/oom
Handle OOM situations
2025-11-06 14:53:46 +00:00
Sergio R. Caprile 34cc8da87e Merge pull request #3335 from cesanta/mip6
enable IPv6 fuzzing
2025-11-05 19:01:06 -03:00
Sergio R. Caprile 1957ba8ffe Merge pull request #3334 from cesanta/tls
increase TLS fuzz depth
2025-11-05 17:42:29 -03:00
Sergio R. Caprile 72758812f5 increase TLS fuzz depth 2025-11-05 17:41:39 -03:00
Sergio R. Caprile ab5a0c43de enable IPv6 fuzzing 2025-11-05 16:43:51 -03:00
Sergio R. Caprile c8291e4ae9 add OOM handling to apps 2025-11-05 14:01:49 -03:00
Sergio R. Caprile 84e9ea76db wip 2025-11-05 13:55:14 -03:00
Sergio R. Caprile b8994f8bc3 Handle OOM situations in iobuf expansion 2025-11-05 13:53:18 -03:00
Sergio R. Caprile b53d8439e5 Merge pull request #3282 from cesanta/mip6
Introduce IPv6, unit tests pass
2025-11-05 11:58:26 -03:00
Sergio R. Caprile 337e8abf2f Introduce IPv6, unit tests pass 2025-11-05 11:04:23 -03:00
Sergio R. Caprile f0bc1c031f Merge pull request #3331 from cesanta/tls2
TLS: fix resuming handshake, fix improper cert req length
2025-11-04 17:08:34 -03:00
Sergio R. Caprile 19d2b93ec7 add IPaddress type SAN elements 2025-11-04 16:55:03 -03:00
Sergio R. Caprile e0304f2b8f TLS: fix resuming handshake, cert req length, 2-way auth app key generation and handling 2025-11-04 15:35:28 -03:00
Sergey Lyubka f7a86f8cf1 Merge pull request #3328 from cesanta/memory
Add memory management example, o1heap flavor
2025-11-01 17:08:42 +00:00
Sergio R. Caprile 340f0dbf89 Merge pull request #3329 from cesanta/updtst
update cesanta.com CA cert
2025-10-30 14:50:17 -03:00
Sergio R. Caprile d90b62d911 update cesanta.com CA cert 2025-10-30 14:45:20 -03:00
Sergio R. Caprile d84aff6420 Add memory management example, o1heap flavor 2025-10-29 15:51:42 -03:00
Sergio R. Caprile b3b73f4751 Merge pull request #3327 from cesanta/printoom
close connection on OOM when printing
2025-10-29 15:48:57 -03:00
Sergio R. Caprile 3c7b2dcd6d close connection on OOM when printing 2025-10-29 15:41:00 -03:00
Sergio R. Caprile 49470f9bd2 Merge pull request #3326 from cesanta/ethram
Be less intrusive with non-ld-savvy users
2025-10-28 11:06:55 -03:00
Sergio R. Caprile f7cf4f60ef Be less intrusive with non-ld-savvy users 2025-10-28 11:03:58 -03:00
novlean 7e0d06689e Merge pull request #3323 from cesanta/novlean-patch-1
Added new article
2025-10-27 17:53:28 +00:00
novlean b843957bd2 Add link for limiting TCP/IP RAM usage on STM32 2025-10-27 17:53:07 +00:00
Sergio R. Caprile 1a0167eb6d Merge pull request #3322 from cesanta/tests
fix error logs not uploading on test failure
2025-10-27 13:53:17 -03:00
Sergio R. Caprile 6ea3b98941 fix error logs not uploading on test failure 2025-10-27 13:49:35 -03:00
Sergio R. Caprile 4b0b93d4f3 Merge pull request #3307 from cesanta/openssl
improve resiliency
2025-10-13 10:55:42 -03:00
Sergio R. Caprile 64abf061bf improve resiliency 2025-10-13 10:43:45 -03:00
Sergio R. Caprile 05d5c68982 Merge pull request #3304 from cesanta/uniram
uniformize memory attributes
2025-10-13 09:41:52 -03:00
Sergio R. Caprile 235dafe646 Merge pull request #3305 from cesanta/chacha
improve error handling with ChaCha
2025-10-10 14:00:02 -03:00
Sergio R. Caprile 0cc40b0c70 improve error handling with ChaCha 2025-10-10 13:58:53 -03:00
Sergio R. Caprile 07a0d1265b uniformize memory attributes 2025-10-10 11:07:31 -03:00
Sergio R. Caprile 967d746574 fix Espressif deprecating ESP_IF_WIFI_STA and replacing it with WIFI_IF_STA 2025-10-09 11:43:01 -03:00
Sergey Lyubka bd12cb1b87 Merge pull request #3302 from cesanta/stm32h
Allow STM32H driver DMA bufs be placed elsewhere
2025-10-09 14:15:45 +01:00
cpq a21ca5d40b Allow STM32H driver DMA bufs be placed elsewhere 2025-10-09 13:16:50 +01:00
Sergio R. Caprile 2d399107fb Merge pull request #3299 from cesanta/tests
fix Espressif deprecating ESP_IF_WIFI_STA and replacing it with WIFI_…
2025-10-08 10:44:06 -03:00
Sergio R. Caprile 03bfa3806b fix Espressif deprecating ESP_IF_WIFI_STA and replacing it with WIFI_IF_STA (ugly) 2025-10-08 10:32:32 -03:00
Sergio R. Caprile 6536ae9bcc remove corpus 2025-10-08 09:38:27 -03:00
robertc2000 e8fc817a0c Merge pull request #3295 from cesanta/mcxe247
Add NXP MCXE driver support
2025-10-06 11:16:02 +03:00
robert e621ade392 Add NXP MCXE driver support 2025-10-06 04:07:51 -04:00
Sergio R. Caprile 3273c20ca9 Merge pull request #3293 from cesanta/tests
fix for non-64-bit test platforms
2025-10-01 17:25:01 -03:00
Sergio R. Caprile a6b2124fd5 fix for non-64-bit test platforms 2025-10-01 17:06:39 -03:00
Sergio R. Caprile 5a1ff125d7 Merge pull request #3292 from cesanta/tests
fixes for C89 (remove mg_queue_vprintf())
2025-10-01 14:04:54 -03:00
Sergio R. Caprile ad58a48144 fixes for C89 2025-10-01 13:51:37 -03:00
Sergio R. Caprile a205fd7877 Merge pull request #3291 from cesanta/tests
fix fuzzers for IPv6
2025-10-01 11:55:44 -03:00
Sergio R. Caprile 776360ca93 fix fuzzers for IPv6 2025-10-01 11:39:21 -03:00
cpq af7602497d Squash warning 2025-09-30 16:43:41 +01:00
Sergio R. Caprile 0f83c2a6e5 Merge pull request #3290 from cesanta/stm32n6
Add STM32N driver support
2025-09-30 08:20:15 -03:00
robert 0d58748e63 Add STM32N driver support 2025-09-30 03:48:42 -04:00
Sergio R. Caprile 01902bb8b9 Merge pull request #3289 from hgarrereyn/master
fix wrong call and undefined use of va_args in mg_queue_vprintf
2025-09-29 14:08:57 -03:00
Sergey Lyubka e28e9aa1d7 Merge pull request #3287 from cesanta/2way
Fix 2-way auth, fix skip hostname validation
2025-09-29 11:49:18 +01:00
hgarrereyn 587e79dc05 fix use of va_args in mg_queue_vprintf, fixes #3285 2025-09-26 14:28:10 -04:00
Sergio R. Caprile acd65f2340 Merge pull request #3288 from cesanta/iobuf
fix iobuf shrink to less than current len
2025-09-26 14:37:34 -03:00
Sergio R. Caprile d55fb80746 fix iobuf shrink to less than current len 2025-09-26 14:34:17 -03:00
Sergio R. Caprile 4536694f20 Fix 2-way auth, fix skip hostname validation 2025-09-26 13:40:15 -03:00
Sergio R. Caprile 2c5a6d4df6 update tests 2025-09-23 13:32:06 -03:00
Sergio R. Caprile 4c8e219643 Merge pull request #3281 from cesanta/tls36retro
add call to mbedtls_psa_free()for MbedTLS >= 3, defaulting to TLS 1.3…
2025-09-23 13:25:34 -03:00
Sergio R. Caprile daeca8128b add call to mbedtls_psa_free()for MbedTLS >= 3, defaulting to TLS 1.3, retroactively documented in 3.6.1 2025-09-23 11:31:10 -03:00
Sergey Lyubka fe6d357858 Merge pull request #3273 from cesanta/dhcpname
Make DHCP name size configurable
2025-09-20 16:43:36 +01:00
Sergio R. Caprile a99cc3dbaf fix statechange test 2025-09-17 10:45:28 -03:00
Sergio R. Caprile 3c4c04199a fix statechange test 2025-09-17 10:29:06 -03:00
Sergio R. Caprile 8ca692100f tests 2025-09-17 10:18:01 -03:00
Sergio R. Caprile 0b9f28b8e3 Make DHCP name size configurable 2025-09-15 09:40:43 -03:00
Sergio R. Caprile 1dff394b63 unbreak ARP 2025-09-12 11:11:00 -03:00
Sergio R. Caprile f4c35d1036 Merge pull request #3269 from cesanta/wifi612
add support for NXP Wifi in RW612, in an example
2025-09-11 17:51:54 -03:00
Sergio R. Caprile 81c166ad74 add support for NXP Wifi in RW612, in an example 2025-09-11 09:36:04 -03:00
Sergio R. Caprile 1f56776050 compiler nits 2025-09-10 19:27:17 -03:00
Sergio R. Caprile b3a0e7b884 fix extension header traversal 2025-09-10 18:57:15 -03:00
Sergio R. Caprile 8594507b5b Merge pull request #3267 from cesanta/wifi
move debugging logs
2025-09-09 16:24:16 -03:00
Sergio R. Caprile fa811ce12b move debugging logs 2025-09-09 16:20:54 -03:00
Sergio R. Caprile c1ef477ff3 Merge pull request #3266 from cesanta/wifi
Move interface stuff out of user handlers
2025-09-09 14:29:29 -03:00
Sergio R. Caprile 4be3a96987 Merge pull request #3265 from cesanta/alip
align mg_addr to 32- and 64-bits
2025-09-09 10:19:58 -03:00
Sergio R. Caprile 387f875aa1 Move interface stuff out of user handlers 2025-09-08 16:00:44 -03:00
Sergio R. Caprile cc069e7e5d align mg_addr to 32- and 64-bits 2025-09-08 11:43:28 -03:00
Sergey Lyubka df994df611 Merge pull request #3264 from cesanta/opts
Fix IP opts
2025-09-07 15:53:34 +01:00
Sergio R. Caprile 8f77fd3940 fixes for Keil 2025-09-04 19:45:18 -03:00
Sergio R. Caprile 7530062e4b fixes for Keil 2025-09-04 19:43:17 -03:00
Sergio R. Caprile 0e63510708 Fix IP opts
Refactor payload handling
Refactor UDP port unreachable
Add UDP unit tests
Introduce basic IPv6 handling
2025-09-02 15:58:02 -03:00
Sergio R. Caprile 26260a1d88 Merge pull request #3263 from cesanta/tests
building health dashboard
2025-09-02 10:36:31 -03:00
Sergio R. Caprile 9e82844f10 building health dashboard 2025-09-02 10:35:44 -03:00
Sergio R. Caprile 0568b5a75b Merge pull request #3262 from cesanta/tests
Push test results for health dashboard
2025-09-01 15:17:15 -03:00
Sergio R. Caprile 3baabebb34 Push test results for health dashboard 2025-09-01 14:52:37 -03:00
Sergio R. Caprile bf4dd15317 Merge pull request #3261 from cesanta/tests
Start pushing test results for health dashboard
2025-08-29 14:29:50 -03:00
Sergio R. Caprile b0f2f9621a Start pushing test results for health dashboard 2025-08-29 14:28:44 -03:00
Sergey Lyubka 04d6d05e9e Merge pull request #3258 from cesanta/tcput
Fix TCP error handling
2025-08-29 15:18:52 +01:00
Sergio R. Caprile 7339c7dfe7 Fix TCP error handling
Add unit tests for TCP error handling
Account for options in TCP header for payload start address calculation
Take UDP payload length from UDP header
2025-08-29 10:34:17 -03:00
Sergio R. Caprile c1152f5eeb Merge pull request #3255 from cesanta/tests
add support for health dashboard
2025-08-28 14:54:28 -03:00
Sergio R. Caprile 024922d566 add support for health dashboard 2025-08-27 13:35:38 -03:00
Sergio R. Caprile 6f64c8c0de Merge pull request #3254 from cesanta/upwiz
update to new wizard backend API
2025-08-27 08:59:55 -03:00
Sergio R. Caprile 2a5ac3c2e5 update to new wizard backend API 2025-08-26 19:04:10 -03:00
Sergey Lyubka 7b0120f0c2 Merge pull request #3251 from cesanta/backlog
add TCP backlog to handle client MSS
2025-08-23 21:06:12 +01:00
Sergio R. Caprile 7ee1f14a6d add TCP backlog to handle client MSS 2025-08-22 11:42:41 -03:00
Sergio R. Caprile 3aaf7d0da7 Merge pull request #3252 from cesanta/idfbrokeit
handle IDF breaking UART API
2025-08-21 18:21:30 -03:00
Sergio R. Caprile 434f3f8415 handle IDF breaking UART API 2025-08-21 18:15:21 -03:00
Sergio R. Caprile 739d78a45a update version 2025-08-21 13:13:25 -03:00
Sergio R. Caprile 8a62633b2f keep, linked by other examples 2025-08-14 11:38:48 -03:00
Sergio R. Caprile aae1a687a9 Merge pull request #3235 from cesanta/client
Refactor HTTP client
2025-08-14 11:00:23 -03:00
Sergio R. Caprile 61285ec418 cleanup 2025-08-14 10:59:07 -03:00
Sergio R. Caprile a00b3f1c6c Merge pull request #3241 from cesanta/mingw
Fixed mingw build error
2025-08-13 10:48:53 -03:00
robert 2c813f3e72 Fixed mingw build error 2025-08-13 05:17:34 -04:00
Sergio R. Caprile ea68d7a705 Merge pull request #3240 from cesanta/ppp
fix ppp driver
2025-08-12 17:51:40 -03:00
Sergio R. Caprile 654f401038 fix ppp driver 2025-08-12 17:21:36 -03:00
Sergio R. Caprile ad89122a06 Merge pull request #3237 from cesanta/tests
Fix built-in TLS CA bundle, cleanup
2025-08-12 16:34:51 -03:00
Sergio R. Caprile 73ed158e76 Fix built-in TLS CA bundle, cleanup 2025-08-12 16:10:12 -03:00
Sergio R. Caprile 548c3dc77f fix #9f76ea8 breaking bigendian 2025-08-12 15:57:26 -03:00
Sergio R. Caprile c1fa067a1f Merge pull request #3236 from cesanta/tls
Verify host against CN, too
2025-08-12 12:09:23 -03:00
Sergey Lyubka 9fd87060f9 Verify host against CN, too 2025-08-12 15:49:08 +01:00
Sergey Lyubka de0a3b035a Refactor HTTP client 2025-08-12 09:21:38 +01:00
Sergey Lyubka 9f76ea8030 CHACHA20 -> MG_ENABLE_CHACHA20 2025-08-12 08:42:20 +01:00
Sergio R. Caprile 76b7356873 Zephyr wants _DEBUG to provide mbedtls_strerror() 2025-08-11 13:23:51 -03:00
novlean c24d5aabd8 Merge pull request #3231 from cesanta/novlean-patch-2
Update README.md
2025-08-06 14:38:25 +01:00
novlean 0df6645b90 Update README.md 2025-08-06 14:38:11 +01:00
Sergey Lyubka b19cf8654f Merge pull request #3203 from cesanta/dns
Built-in TCP/IP (re-)starts DNS connection on DHCP link up
2025-08-01 12:13:39 +01:00
Sergey Lyubka 19933a4673 Merge pull request #3222 from cesanta/mbedrbose
Add verbose MbedTLS errors
2025-08-01 12:10:20 +01:00
Sergio R. Caprile 76963f7d01 Merge pull request #3229 from cesanta/tests
fix possible overflow, improve tests
2025-07-31 13:50:42 -03:00
Sergio R. Caprile e670ea3d61 fix possible overflow, improve tests 2025-07-31 13:43:18 -03:00
Sergio R. Caprile fa33b57e4f Merge pull request #3228 from cesanta/tests
mask built-in TCP/IP with WolfSSL test
2025-07-30 17:10:16 -03:00
Sergio R. Caprile 77e369bc79 mask built-in TCP/IP with WolfSSL test 2025-07-30 17:09:42 -03:00
Sergio R. Caprile 94ad9767d3 Merge pull request #3225 from cesanta/tests
ChaCha20 not working in S390 (bigendian)
2025-07-30 16:15:40 -03:00
Sergio R. Caprile aa76f5673b ChaCha20 not working in S390 (bigendian) 2025-07-30 16:13:34 -03:00
Sergio R. Caprile 81a699c801 Merge pull request #3224 from cesanta/tests
Fix tests
2025-07-29 17:26:07 -03:00
Sergio R. Caprile bd15c456b2 Fix tests
Fix Ubuntu starting Mosquitto right after install
Skip TLS on localhost on MacOS with MbedTLS
fix MQTT_LOCALHOST for built-in TCP/IP tests
2025-07-29 17:17:03 -03:00
Sergio R. Caprile 10d9e1e9ae Merge pull request #3223 from cesanta/zephyr
Improve 4.2 test time
2025-07-29 11:22:56 -03:00
Sergio R. Caprile 6a3813f633 Improve 4.2 test time
fix for intermediate releases
2025-07-29 11:19:16 -03:00
Sergio R. Caprile 51fe22a95f Add verbose MbedTLS errors 2025-07-28 16:18:53 -03:00
Sergio R. Caprile 105762416f Merge pull request #3221 from cesanta/tests
add tests for Zephyr 4.2.0
2025-07-28 15:07:50 -03:00
Sergio R. Caprile db7087f455 add tests for Zephyr 4.2.0 2025-07-28 14:43:09 -03:00
Sergio R. Caprile c5693503cb Merge pull request #3220 from cesanta/zephyr
update to Zephyr 4.2.0
2025-07-28 11:26:03 -03:00
Sergio R. Caprile b74590a4a5 update to Zephyr 4.2.0 2025-07-28 11:25:02 -03:00
Sergio R. Caprile d5eeed48eb Merge pull request #3219 from cesanta/tests
workaround GH storage
2025-07-28 10:44:53 -03:00
Sergio R. Caprile fc5c0d0964 workaround GH storage 2025-07-28 10:28:18 -03:00
robert aa2647c0bc clang format 2025-07-28 04:11:22 -04:00
robertc2000 cef0acdb40 Merge pull request #3218 from cesanta/same54-driver-update
Update same54 driver
2025-07-28 11:07:47 +03:00
robert 2140656acc Update same54 driver 2025-07-28 03:55:00 -04:00
Sergio R. Caprile fd0c969f16 Merge pull request #3217 from cesanta/tests
move Zephyr tests to their own script
2025-07-25 17:08:19 -03:00
Sergio R. Caprile dfeb929e0e move Zephyr tests to their own script 2025-07-25 17:07:06 -03:00
Sergio R. Caprile d3e67733a6 Merge pull request #3216 from cesanta/tests
Tests
2025-07-25 11:44:36 -03:00
Sergio R. Caprile eff74fdc9d Zephyr: only clean if there's a build 2025-07-25 11:38:30 -03:00
Sergio R. Caprile 5e4c40ad09 remove tailwindcss dependency 2025-07-25 11:33:49 -03:00
Sergio R. Caprile 087e6d3142 Merge pull request #3215 from cesanta/tests
fix mingw[++] tests, add local MQTTS
2025-07-24 18:43:57 -03:00
Sergio R. Caprile 587b074822 fix mingw[++] tests, add local MQTTS 2025-07-24 18:42:14 -03:00
Sergio R. Caprile 6aa8c01ac7 fix TLS text 2025-07-24 17:11:19 -03:00
Sergio R. Caprile 3bbcd5df3e Merge pull request #3214 from cesanta/tests
introduce local MQTT server, fix container calling, fill prerequisites
2025-07-24 16:10:08 -03:00
Sergio R. Caprile af512c57ef introduce local MQTT server, fix container calling, fill prerequisites 2025-07-24 15:54:58 -03:00
Sergio R. Caprile 58297a7871 remove obsolete example 2025-07-24 11:25:11 -03:00
Sergio R. Caprile 18a530048c Increase MQTT connect expected time 2025-07-24 10:15:09 -03:00
Sergio R. Caprile f9ed75d6b3 attempt to get reasons 2025-07-23 10:53:00 -03:00
Sergio R. Caprile 3c1f41e575 disable scheduled run 2025-07-23 10:33:51 -03:00
Sergio R. Caprile c772936dd1 enable manual run 2025-07-23 10:31:07 -03:00
Sergio R. Caprile 253696be45 Merge pull request #3213 from cesanta/tests
disable hw tests on quick test
2025-07-23 10:27:12 -03:00
Sergio R. Caprile 79b7accc55 disable hw tests on quick test 2025-07-23 10:26:34 -03:00
Sergio R. Caprile 7a1e846c73 Merge pull request #3211 from cesanta/ooofin
Fix ignoring SEQ on FIN
2025-07-23 08:34:05 -03:00
Sergio R. Caprile ce59ff89c3 Merge pull request #3212 from cesanta/tests
fix sh not being bash
2025-07-22 18:03:00 -03:00
Sergio R. Caprile d31d064d5e fix sh not being bash 2025-07-22 17:01:01 -03:00
Sergio R. Caprile 467fbf4bb4 Fix ignoring SEQ on FIN 2025-07-22 14:16:35 -03:00
Sergey Lyubka 6769223ce1 Nitpick: rename fn -> mqtt_ev_handler 2025-07-22 10:11:20 +01:00
Sergey Lyubka 294e483885 Nitpick: rename s_conn -> s_mqtt_conn 2025-07-22 10:10:14 +01:00
Sergey Lyubka 43513e2d56 Update MQTT client: enable keep alive, use rx/tx topics 2025-07-22 09:44:43 +01:00
Sergey Lyubka d1b7687e98 Fix comments 2025-07-21 23:01:43 +01:00
Sergey Lyubka 9ac09da1d2 Remove mg_http_run_simple_server - move to docs 2025-07-21 14:03:12 +01:00
Sergey Lyubka 24a330c750 Nits 2025-07-20 12:49:58 +01:00
Sergey Lyubka 13a9c773f2 mg_hello -> mg_http_run_simple_server() 2025-07-20 09:36:34 +01:00
Sergey Lyubka 3cd166d065 MG_ARCH_CUBE nitpicks 2025-07-19 08:33:48 +01:00
Sergio R. Caprile 490066fd17 Merge pull request #3209 from cesanta/tests
Fix misc warnings and nits
2025-07-18 17:40:53 -03:00
Sergio R. Caprile 94fce72ade Fix misc warnings and nits 2025-07-18 17:08:32 -03:00
Sergio R. Caprile eacc64bdd1 fix missing def 2025-07-18 16:44:38 -03:00
Sergio R. Caprile 7b037f4957 Merge pull request #3208 from cesanta/cube
Introduce MG_ARCH_CUBE, autodetect everything
2025-07-18 11:22:17 -03:00
Sergio R. Caprile fa841916c1 assorted nit picks 2025-07-18 11:19:58 -03:00
Sergey Lyubka 75c11436ff Introduce MG_ARCH_CUBE, autodetect everything 2025-07-17 17:29:48 +01:00
Sergio R. Caprile e07a8283ec Merge pull request #3207 from cesanta/hal
Autodetect STM32 in mg_millis()
2025-07-16 10:27:37 -03:00
Sergey Lyubka 2a174b0d3b Autodetect STM32 in mg_millis() 2025-07-16 07:38:29 +01:00
Sergey Lyubka 013993abae example configs 2025-07-16 07:37:25 +01:00
Sergey Lyubka dccc153c68 example configs 2025-07-16 07:37:07 +01:00
Sergio R. Caprile db0867f435 Merge pull request #3206 from cesanta/restrict
Avoid trashing VC++'s own proprietary restrict-like keyword
2025-07-15 16:55:52 -03:00
Sergio R. Caprile 7234121835 Avoid trashing VC++'s own propropietary restrict-like keyword 2025-07-15 16:47:06 -03:00
Sergio R. Caprile 3aafc073d8 unbreak after #8a9b1d9 2025-07-15 13:42:48 -03:00
Sergio R. Caprile b527ed313c Merge pull request #3204 from cesanta/tests
Moving tests from GH yaml to bash scripts and Makefiles
2025-07-15 11:27:24 -03:00
Sergio R. Caprile cd86559685 Move tests to bash scripts and Makefiles 2025-07-15 11:24:09 -03:00
Sergio R. Caprile f67e843be6 fix tests 2025-07-15 11:24:09 -03:00
Sergio R. Caprile 4f9ebd8092 Merge pull request #3202 from cesanta/gcc
Rename MG_ARCH_NEWLIB -> MG_ARCH_ARMGCC
2025-07-15 09:08:13 -03:00
Sergey Lyubka 6c044d6aeb Rename MG_ARCH_NEWLIB -> MG_ARCH_ARM_GCC 2025-07-15 11:22:17 +01:00
Sergio R. Caprile c6ee909aa4 uint16_t always >= 0 2025-07-14 15:12:50 -03:00
Sergio R. Caprile 393063428e Built-in TCP/IP (re-)starts DNS connection on link up 2025-07-14 15:06:31 -03:00
Sergio R. Caprile 1494f5e831 Merge pull request #3201 from cesanta/sntp
fix SNTP through proper protocol handler setup
2025-07-14 10:09:47 -03:00
Sergey Lyubka 8bfd0c2ca3 add config template 2025-07-13 07:34:48 +01:00
Sergey Lyubka e9de2f3eb1 Remove gurubase link - useless 2025-07-12 06:50:27 +01:00
Sergio R. Caprile 8bf9d09d96 fix SNTP through proper protocol handler setup 2025-07-11 16:56:12 -03:00
Sergio R. Caprile 67255ce8f5 fix broken links 2025-07-10 09:48:53 -03:00
Sergey Lyubka 5db89aa264 Update help message 2025-07-09 12:58:15 +01:00
Sergey Lyubka 8a9b1d9873 Simplify dashboard 2025-07-09 00:21:31 +01:00
Sergio R. Caprile c08c1afb1e Merge pull request #3198 from cesanta/c89
make it C89-friendly
2025-07-08 14:10:58 -03:00
Sergio R. Caprile 2c7f58aed2 test checksum primitives, enforce rx frag test 2025-07-08 13:57:03 -03:00
Sergio R. Caprile b3ee71acbe make TCP/IP C89-friendly 2025-07-08 11:15:32 -03:00
Sergio R. Caprile 52ab6bc499 make it C89-friendly 2025-07-07 15:15:31 -03:00
Sergio R. Caprile bf059ad42f Merge pull request #3197 from cesanta/select
select() minimum wait is now 1ms
2025-07-07 14:43:52 -03:00
Sergio R. Caprile 85df6a6131 select() minimum wait is now 1ms 2025-07-07 14:40:18 -03:00
Sergio R. Caprile d840b4a4ee Merge pull request #3196 from cesanta/tests
fix tests
2025-07-07 11:33:25 -03:00
Sergio R. Caprile a8c2ce544e fix tests 2025-07-07 11:32:31 -03:00
Sergio R. Caprile b95022a3b3 Merge pull request #3195 from cesanta/sanasan
remove false positive
2025-07-03 11:49:01 -03:00
Sergio R. Caprile 8c45a9d2c9 remove false positive 2025-07-03 10:53:59 -03:00
Sergio R. Caprile 0fe64fbff9 Merge pull request #3194 from cesanta/udpret
mg_send and mg_io_send now honor UDP failures
2025-07-02 17:00:50 -03:00
Sergio R. Caprile 64e806628b Merge pull request #3188 from cesanta/wintls
Fix incorrect reference to a Windows compiler
Fix memory leaks in RSA signature verificator
2025-07-02 16:49:32 -03:00
Sergio R. Caprile ccd2b2699f fix memory leaks in RSA verification function 2025-07-02 16:40:36 -03:00
Sergio R. Caprile 0b5c0c9889 mg_send now honors UDP failures 2025-07-02 10:04:24 -03:00
robertc2000 6293e7dbec Merge pull request #3193 from cesanta/driver-macro
Removed MG_DRIVER_* macros
2025-07-02 13:08:39 +03:00
robert 87325ece82 Removed MG_DRIVER_* macros 2025-07-02 05:03:32 -04:00
Sergio R. Caprile 6cbd9b3067 Merge pull request #3192 from cesanta/freeunix
fix unix detection in wrong place
2025-07-01 16:32:20 -03:00
Sergio R. Caprile aa27fde9d0 fix unix detection in wrong place 2025-07-01 16:28:13 -03:00
Sergio R. Caprile e854585802 Improve Zephyr support 2025-06-30 10:35:53 -03:00
Sergio R. Caprile 2c5aba24cc Merge pull request #3189 from cesanta/zephyrotahack
Improve Zephyr support
2025-06-27 14:13:17 -03:00
Sergio R. Caprile 806ee0f2cb Improve Zephyr support 2025-06-27 14:11:04 -03:00
Sergey Lyubka e72b95fb1c Fix tutorials/http/http-server build with windows gcc 2025-06-27 14:33:44 +01:00
Sergey Lyubka 471e7ff61a Left-align tables 2025-06-26 10:42:47 +01:00
Sergey Lyubka 3d2de154d1 Add support matrix 2025-06-26 10:40:15 +01:00
Sergio R. Caprile fc551ec2e9 Merge pull request #3182 from cesanta/calloc
Introduce mg_calloc and MG_ENABLE_CUSTOM_CALLOC
2025-06-24 16:32:28 -03:00
Sergio R. Caprile f5e2c68c8b update examples 2025-06-24 16:26:31 -03:00
Sergey Lyubka 074ef5197b Introduce mg_calloc 2025-06-24 10:52:44 +01:00
Sergey Lyubka 5f1f4a0df8 malloc -> calloc 2025-06-24 09:12:38 +01:00
Sergey Lyubka 86334e9040 Keep only one listener 2025-06-24 08:57:49 +01:00
Sergey Lyubka f71cc3ebc3 Merge pull request #3173 from cesanta/chachaleak
Avoid chacha20 header leaking its redefinitions
2025-06-18 10:47:19 +01:00
Sergio R. Caprile 00910462e7 Merge pull request #3174 from cesanta/wka
Allow KA from erroneous implementations
2025-06-17 15:17:29 -03:00
Sergio R. Caprile 2fc56dd1d0 Allow KA from erroneous implementations 2025-06-17 15:14:30 -03:00
Sergio R. Caprile a5ebe71394 Avoid chacha20 header leaking its redefinitions 2025-06-17 12:12:48 -03:00
Sergio R. Caprile 0eb8bf6b51 Merge pull request #3167 from cesanta/threadx
Add MG_ARCH_TREADX
2025-06-16 10:51:16 -03:00
Sergey Lyubka 3a0fe5288c Add MG_ARCH_TREADX 2025-06-16 11:09:41 +01:00
Sergey Lyubka bfca233160 Merge pull request #3170 from cesanta/keepack
Add Keep-Alive ACK
2025-06-12 08:37:00 +01:00
Sergio R. Caprile acf217601b Add Keep-Alive ACK 2025-06-11 14:25:05 -03:00
Sergio R. Caprile b0d0fbfd9f clarify bridging for Wi-Fi 2025-06-11 09:31:24 -03:00
Sergio R. Caprile 9411f1c7b6 Merge pull request #3165 from cesanta/wifi612
Add Wi-Fi example for RW-612
2025-06-06 18:39:35 -03:00
Sergio R. Caprile d7d7ebf99a Add Wi-Fi example for RW-612 2025-06-06 18:26:27 -03:00
novlean 8072ae2057 Update README.md 2025-06-06 16:34:19 +01:00
Sergio R. Caprile e529e644ab Merge pull request #3164 from cesanta/asan
avoid ASAN reporting read overflows
2025-06-06 09:03:02 -03:00
Sergio R. Caprile d6fdfe5b1b avoid ASAN reporting read overflows 2025-06-05 17:26:56 -03:00
Sergio R. Caprile 50e15e574f Merge pull request #3163 from cesanta/test
expand test coverage
2025-06-05 14:24:47 -03:00
Sergio R. Caprile 58f1533779 expand test coverage 2025-06-05 14:24:03 -03:00
Sergio R. Caprile f4a49829ea unbreak FreeRTOS (#3158) 2025-06-05 14:03:26 -03:00
Sergio R. Caprile 3efe6641eb Merge pull request #3161 from cesanta/fix
Unbreak MbedTLS (#3148), rollback debugging leftovers
2025-06-04 09:08:32 -03:00
Sergio R. Caprile 0459d9e106 Unbreak MbedTLS (#3148), rollback debugging leftovers 2025-06-04 09:05:27 -03:00
Sergio R. Caprile 305d69ee36 Merge pull request #3159 from cesanta/isacheese
fix error introduced in #3149
2025-06-03 15:41:13 -03:00
Sergio R. Caprile 98e744a9ad fix error introduced in #3149 2025-06-03 15:29:28 -03:00
Sergey Lyubka 1d97f2e2b5 Enable POSIX_FS on ESP32 2025-06-03 08:23:05 +01:00
Sergio R. Caprile c92bc4b4ac Merge pull request #3158 from cesanta/posiz
Redefine mkdir only if MG_ENABLE_POSIX_FS==0
2025-06-02 11:06:09 -03:00
Sergey Lyubka 6a3e1e41c4 Redefine mkdir only if MG_ENABLE_POSIX_FS==0 2025-06-02 11:04:16 -03:00
Sergio R. Caprile 650caface3 fix duplicates 2025-05-30 10:03:01 -03:00
novlean 8b6e02e985 Merge pull request #3154 from cesanta/novlean-patch-2
Update README.md - stm32 websocket article
2025-05-29 17:01:52 +01:00
novlean 3ee6fe45f9 Update README.md 2025-05-29 17:01:05 +01:00
Sergio R. Caprile e811afd397 Merge pull request #3152 from cesanta/fuzzer
fix memory leak in fuzz test itself
2025-05-28 14:36:07 -03:00
Sergio R. Caprile b197a674e1 fix memory leak in fuzz test itself 2025-05-28 13:56:04 -03:00
Sergio R. Caprile 08f6b99b13 remove conditionals from CIfuzz 2025-05-28 11:57:27 -03:00
Sergio R. Caprile b18d0301f3 Update README.md 2025-05-28 11:46:49 -03:00
Sergio R. Caprile 5596621420 Update README.md 2025-05-28 11:05:37 -03:00
Sergio R. Caprile bd8a66eee7 Update README.md
GH changes in icon stuff
2025-05-28 11:02:07 -03:00
Sergio R. Caprile b62ebb3c10 Update README.md
GH changes in build icon
2025-05-28 10:59:57 -03:00
Sergio R. Caprile 45d796fe5b Merge pull request #3151 from cesanta/wonder
Add Portenta H7 STM32CubeIDE example
2025-05-27 17:27:43 -03:00
Sergio R. Caprile d8a3b90cad Add Portenta H7 STM32CubeIDE example 2025-05-27 17:26:26 -03:00
Sergio R. Caprile 5be9e55425 Merge pull request #3142 from cesanta/wonder
Add support for SDIO
2025-05-26 10:07:41 -03:00
Sergio R. Caprile 6b6acd3967 Merge pull request #3149 from cesanta/is_tls
set is_tls at mg_listen and mg_connect level
2025-05-26 10:06:38 -03:00
Sergio R. Caprile 1b06403a19 Add support for SDIO
Add support for SDIO in CYW driver
Add Portenta H7 example
2025-05-26 10:04:44 -03:00
Sergio R. Caprile b740c80855 set is_tls at mg_listen and mg_connect level 2025-05-26 09:42:48 -03:00
Sergey Lyubka 29594283c1 Merge pull request #3148 from cesanta/iowaitormsscapped
flush TLS buffer
2025-05-26 11:38:41 +01:00
Sergio R. Caprile 51f54f9b7e Merge pull request #3147 from cesanta/ra8-eth
RA8 eth and phy support
2025-05-23 14:23:52 -03:00
Sergio R. Caprile 1f48b1ca65 flush TLS buffer 2025-05-23 14:04:59 -03:00
robert fd2d7cccf3 RA8 eth and phy support 2025-05-23 10:15:49 -04:00
Sergio R. Caprile 5726e680ec Merge pull request #3143 from cesanta/fairplay
Make built-in TLS play fair to TCP
2025-05-23 10:22:56 -03:00
Sergio R. Caprile fadf28adb4 Make built-in TLS play fair to TCP
Handshake functions in Mongoose TLS assumed data was being fully sent
after calling mg_io_send(). This was in fact the case with the usual 1460-bytes MSS, but not with the default 536-bytes MSS.
This PR removes all those calls from individual handshake functions, actual send is done at the main handshake function, keeping track of the amount of data sent, and so handling small MTUs/MSSs and possible MG_IO_WAITs when running over a socket layer.
2025-05-22 14:45:46 -03:00
novlean a321c2d096 Merge pull request #3146 from cesanta/novlean-patch-2
Update README.md
2025-05-22 17:59:06 +01:00
novlean bbb07bf6f7 Update README.md 2025-05-22 17:58:42 +01:00
Sergio R. Caprile a801160bc0 collaterals #3140
We prepend current path to the URI, so a tilde could not be the first
char in a path. However, the same would happen for double dots, and
since we're already checking for that, it doesn't hurt to be on the safe
side for future's sake.
2025-05-21 10:43:14 -03:00
Sergio R. Caprile 662cc27f4f Merge pull request #3140 from dag10/master
Fix URIs or header values containing tildes being unparsable.
2025-05-21 09:58:30 -03:00
Drew Gottlieb d01aa01a51 Fix URIs or header values containing tildes being unparsable. 2025-05-15 17:13:15 -07:00
1390 changed files with 974381 additions and 10765 deletions

No files matched your search

+1 -4
View File
@@ -11,17 +11,14 @@ jobs:
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^src/' ; then echo GO=1 >> $GITHUB_ENV ; fi
- name: Build Fuzzers
id: build
if: ${{ env.GO == 1 }}
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'mongoose'
dry-run: false
language: c++
- name: Run Fuzzers
if: ${{ env.GO == 1 }}
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'mongoose'
@@ -30,7 +27,7 @@ jobs:
language: c++
- name: Upload Crash
uses: actions/upload-artifact@v4
if: env.GO == 1 && failure() && steps.build.outcome == 'success'
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts
+2 -2
View File
@@ -2,8 +2,8 @@ name: "CodeQL Scanning"
# https://github.com/github/codeql-action
on:
schedule:
- cron: '30 23 * * *' # run at 11:30 PM UTC
#schedule:
# - cron: '30 23 * * *' # run at 11:30 PM UTC
# Allow manual runs
workflow_dispatch:
+5 -1
View File
@@ -17,4 +17,8 @@ jobs:
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: make -C test ${{ matrix.target }}
- run: make -C test ${{ matrix.target }} ARGS="-max_total_time=7200"
# as we're not getting access to test units causing a problem, convert from the log:
# base64 -d > dataofdeath
# then paste the base64 data, enter, Ctrl-D; maybe check with hexdump -C dataofdeath
+100 -45
View File
@@ -33,11 +33,19 @@ jobs:
env:
CC: ${{ matrix.cc }}
SSL: ${{ matrix.ssl }}
TFLAGS: ${{ matrix.select }}
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST -DNO_ABORT
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }}
- uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && test/setup_mqtt_server.sh && make -C test ${{ matrix.target }} > log
- if: success() || failure()
run: |
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/linux_${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
mip:
runs-on: ubuntu-latest
strategy:
@@ -46,14 +54,40 @@ jobs:
cc: [gcc, clang, g++, clang++]
target: [mip_test, mip_tap_test]
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
# #3226: built-in TCP is currently not working with WolfSSL (builds fine)
exclude:
- ssl: WOLFSSL
target: mip_tap_test
name: ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
env:
CC: ${{ matrix.cc }}
SSL: ${{ matrix.ssl }}
TFLAGS: -DMQTT_LOCALHOST -DNO_ABORT
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} IPV6=0
- uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} IPV6=0 > log
- if: success() || failure()
run: |
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_$(date +"%Y%m%d").json"
mip89:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1 # no parallel runs, to minimize MQTT errors
matrix:
target: [mip_vc98]
name: mip89 ${{ matrix.target }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: make -C test ${{ matrix.target }}
s390:
runs-on: ubuntu-latest
strategy:
@@ -61,10 +95,12 @@ jobs:
matrix:
ssl: ["", BUILTIN]
name: S390 SSL=${{ matrix.ssl }}
env:
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }}
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }} MULTIREC=NO
armhf:
runs-on: ubuntu-latest
strategy:
@@ -72,10 +108,12 @@ jobs:
matrix:
ssl: ["", BUILTIN]
name: ArmHF SSL=${{ matrix.ssl }}
env:
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }}
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }} MULTIREC=NO
unamalgamated-mg_prefix:
runs-on: ubuntu-latest
strategy:
@@ -87,7 +125,7 @@ jobs:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev
- run: make -C test unamalgamated && make -C test mg_prefix
- run: make -C test unamalgamated SSL=${{ matrix.ssl }} && make -C test mg_prefix
valgrind:
runs-on: ubuntu-latest
strategy:
@@ -95,35 +133,53 @@ jobs:
matrix:
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
name: Valgrind SSL=${{ matrix.ssl }}
env:
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev valgrind
- run: make -C test valgrind SSL=${{ matrix.ssl }}
- run: ./test/setup_mqtt_server.sh && make -C test valgrind SSL=${{ matrix.ssl }}
macos:
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
# Mongoose does not work with WolfSSL version in MacOS
ssl: ["", BUILTIN, MBEDTLS, OPENSSL] # , WOLFSSL]
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
include:
- ssl: MBEDTLS
env:
# MbedTLS version in MacOS refuses to validate a certificate without a hostname, causing MQTT tests to fail when using MQTT_LOCALHOST
tflags: -DNO_MQTT_TESTS
exclude:
- ssl: MBEDTLS
select: -DMG_ENABLE_POLL=0
- ssl: OPENSSL
select: -DMG_ENABLE_POLL=0
- ssl: WOLFSSL
select: -DMG_ENABLE_POLL=0
#- ssl: WOLFSSL
# select: -DMG_ENABLE_POLL=0
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
env:
SSL: ${{ matrix.ssl }}
TFLAGS: ${{ matrix.select }} -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST ${{ matrix.env.tflags }} -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
HOMEBREW_NO_AUTO_UPDATE: 1
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: brew install mbedtls wolfssl # jq openssl already pre-installed
- run: make -C test test ASAN_OPTIONS= MBEDTLS=$(echo $(brew --cellar)/mbedtls*/*) OPENSSL=$(echo $(brew --cellar)/openssl*/*) WOLFSSL=$(echo $(brew --cellar)/wolfssl*/*)
- uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
- run: brew install mbedtls wolfssl mosquitto gawk # jq openssl already pre-installed
- run: /opt/homebrew/opt/mosquitto/sbin/mosquitto -c /Users/runner/work/mongoose/mongoose/test/mosquitto.conf.macos &
- run: make -C test test ASAN_OPTIONS= MBEDTLS=$(echo $(brew --cellar)/mbedtls*/*) OPENSSL=$(echo $(brew --cellar)/openssl*/*) WOLFSSL=$(echo $(brew --cellar)/wolfssl*/*) > log
- if: success() || failure()
run: |
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/macos_test_cc_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
windows:
runs-on: ubuntu-latest
strategy:
@@ -138,12 +194,21 @@ jobs:
select: -DMG_ENABLE_POLL=1
name: windows ${{ matrix.target }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
env:
SSL: SSL=${{ matrix.ssl }}
TFLAGS: ${{ matrix.select }}
SSL: ${{ matrix.ssl }}
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: make -C test ${{ matrix.target }}
- uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
- run: ./test/setup_mqtt_server.sh && make -C test ${{ matrix.target }} > log
- if: success() || failure()
run: |
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/windows_${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
arm:
runs-on: ubuntu-latest
strategy:
@@ -174,9 +239,18 @@ jobs:
name: tutorials ${{ matrix.ssl }}
steps:
- uses: actions/checkout@v4
- uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
- run: sudo apt -y install libpcap-dev
- run: make -C test tutorials CFLAGS_EXTRA="${{ matrix.ssl }}"
- run: make -C test tutorials CFLAGS_EXTRA="${{ matrix.ssl }}" > log
- if: success() || failure()
run: |
cat log
test/health.awk < log > json
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/tutorials_${{ matrix.ssl }}_$(date +"%Y%m%d").json"
- run: make -C test clean_tutorials
tutorials_win:
runs-on: windows-latest
strategy:
@@ -303,7 +377,6 @@ jobs:
matrix:
example:
- path: mqtt/mqtt-client/microchip/same54-xpro
- path: nxp/nxp-mimxrt1020-azurertos
- path: nxp/nxp-frdmk66f-freertos
- path: nxp/nxp-lpcxpresso54s018m-freertos
- path: nxp/nxp-mimxrt1020-freertos
@@ -357,7 +430,7 @@ jobs:
matrix:
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
example:
- path: tutorials/http/device-dashboard/microchip/same54-xpro
- path: http/device-dashboard/microchip/same54-xpro
- path: nxp/rt1020-evk-make-freertos-builtin
- path: nxp/rt1060-evk-make-freertos-builtin
- path: nxp/rt1170-evk-make-freertos-builtin
@@ -425,24 +498,6 @@ jobs:
- run: sudo pip install yq
- run: cd test/cube && make
zephyr_examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
- run: make -C tutorials/zephyr init REPO=zephyrprojectrtos/ci:v0.26.14 # "no space left on device" with newers
- name: minify manifest
uses: mikefarah/yq@master
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))' tutorials/zephyr/zephyrproject/zephyr/west.yml
- run: make -C tutorials/zephyr update
- run: make -C tutorials/zephyr/device-dashboard build
- run: make -C tutorials/zephyr/http-client build
- run: make -C tutorials/zephyr/http-server build
- run: make -C tutorials/zephyr/mqtt-aws-client build
- run: make -C tutorials/zephyr/websocket-server build
test_f7:
runs-on: ubuntu-latest
steps:
@@ -455,9 +510,9 @@ jobs:
- run: make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- name: Cube
run: echo # nothing specific to install or do
# - 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=../../tutorials/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-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
- run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
test_f4:
runs-on: ubuntu-latest
@@ -470,9 +525,9 @@ jobs:
- run: make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
- name: Cube
run: echo # nothing specific to install or do
# - 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=../../tutorials/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-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
- run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
test_h743:
runs-on: ubuntu-latest
@@ -485,8 +540,8 @@ jobs:
- run: make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# - name: Cube
# run: echo # nothing specific to install or do
# - 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=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
test_h723:
runs-on: ubuntu-latest
+351 -339
View File
@@ -5,6 +5,8 @@ on:
- "**Makefile"
- "**.c"
- "**.h"
# Allow manual runs
workflow_dispatch:
env:
IPV6: 0
jobs:
@@ -20,28 +22,33 @@ jobs:
env:
CC: ${{ matrix.cc }}
SSL: ${{ matrix.ssl }}
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test ${{ matrix.target }}
run: if [ "${{ matrix.target }}" == "test" ]; then ./test/setup_mqtt_server.sh ; fi && make -C test ${{ matrix.target }}
s390:
runs-on: ubuntu-latest
env:
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
armhf:
runs-on: ubuntu-latest
env:
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
unamalgamated-mg_prefix:
runs-on: ubuntu-latest
steps:
@@ -59,14 +66,17 @@ jobs:
name: macos SSL=${{ matrix.ssl }}
env:
SSL: ${{ matrix.ssl }}
#TFLAGS: -DNO_SNTP_CHECK
TFLAGS: -DMQTT_LOCALHOST # -DNO_SNTP_CHECK
HOMEBREW_NO_AUTO_UPDATE: 1
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test test ASAN_OPTIONS=
run: |
brew install mosquitto
/opt/homebrew/opt/mosquitto/sbin/mosquitto -c /Users/runner/work/mongoose/mongoose/test/mosquitto.conf.macos &
make -C test test ASAN_OPTIONS=
windows:
runs-on: ubuntu-latest
strategy:
@@ -74,12 +84,14 @@ jobs:
matrix:
target: [vc98, vc22, mingw++]
name: windows ${{ matrix.target }}
env:
TFLAGS: -DMQTT_LOCALHOST
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
- if: ${{ env.GO == 1 }}
run: make -C test ${{ matrix.target }}
run: ./test/setup_mqtt_server.sh && make -C test ${{ matrix.target }}
arm:
runs-on: ubuntu-latest
steps:
@@ -335,360 +347,360 @@ jobs:
- if: ${{ env.GO == 1 }}
run: cd test/cube && make
test_f7:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f7.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
# always run baremetal on core or dashboard or specific example changes; other examples only on specific example changes
- 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
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f746zg-make-baremetal-builtin'; then
make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-builtin'; then
make -C tutorials/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-tcp'; then
make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- name: Cube
run: |
echo GO=0 >> $GITHUB_ENV
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f7.*-cube-'; then
echo GO=1 >> $GITHUB_ENV
# nothing specific to install or do
fi
# - if: ${{ env.GO == 1 }}
# test_f7:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f7.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# # always run baremetal on core or dashboard or specific example changes; other examples only on specific example changes
# - 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
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f746zg-make-baremetal-builtin'; then
# make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-builtin'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-lwip'; then
make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
fi
test_f4:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f4.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f429zi-make-baremetal-builtin'; then
make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-make-freertos-builtin'; then
make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- name: Cube
run: |
echo GO=0 >> $GITHUB_ENV
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f4.*-cube-'; then
echo GO=1 >> $GITHUB_ENV
# nothing specific to install or do
fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-builtin'; then
# make -C tutorials/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-builtin'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-tcp'; then
# make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-lwip'; then
make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
fi
test_h743:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h74.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h743zi-make-baremetal-builtin'; then
make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-make-freertos-builtin'; then
make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
# - name: Cube
# run: |
# echo GO=0 >> $GITHUB_ENV
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h74.*-cube-'; then
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f7.*-cube-'; then
# echo GO=1 >> $GITHUB_ENV
# # nothing specific to install or do
# fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
## fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-builtin'; then
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
## fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-lwip'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
# fi
#
#
# test_f4:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f4.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f429zi-make-baremetal-builtin'; then
# make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-freertos-builtin'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-make-freertos-builtin'; then
# make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
test_h723:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h72.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h723zg-make-baremetal-builtin'; then
make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h723zg-make-freertos-builtin'; then
make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_h5:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h5.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h563zi-make-baremetal-builtin'; then
make -C tutorials/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h563zi-make-freertos-builtin'; then
make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_rt1020:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020-evk-make-baremetal-builtin'; then
make -C tutorials/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/nxp/rt1020-evk-make-freertos-builtin'; then
make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_rt1060:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060-evk-make-baremetal-builtin'; then
make -C tutorials/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/nxp/rt1060-evk-make-freertos-builtin'; then
make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_rt1170:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170-evk-make-baremetal-builtin'; then
make -C tutorials/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/nxp/rt1170-evk-make-freertos-builtin'; then
make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_ra6m4:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 3 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
continue-on-error: true
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4-make-baremetal-builtin'; then
make -C tutorials/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
# - name: Cube
# run: |
# echo GO=0 >> $GITHUB_ENV
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f4.*-cube-'; then
# echo GO=1 >> $GITHUB_ENV
# # nothing specific to install or do
# fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
## fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-builtin'; then
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
## fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/renesas/ek-ra6m4-make-freertos-builtin'; then
# make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-lwip'; then
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
# fi
test_tm4c:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c.*-make-" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
make -C tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh 'tutorials/ti/ek-tm4c1294xl-make-freertos-builtin'; then
make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_same54:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- name: baremetal
run: |
if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/mqtt/mqtt-client" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
- if: ${{ env.GO == 1 }}
run: |
if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
fi
test_pico_w5500:
runs-on: ubuntu-latest
env:
GO: 0
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- name: SDK
run: |
if ./test/match_changed_files.sh "^src" ; then
echo GO=1 >> $GITHUB_ENV
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
fi
- if: ${{ env.GO == 1 }}
run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
#
# test_h743:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h74.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h743zi-make-baremetal-builtin'; then
# make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-make-freertos-builtin'; then
# make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
## - name: Cube
## run: |
## echo GO=0 >> $GITHUB_ENV
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h74.*-cube-'; then
## echo GO=1 >> $GITHUB_ENV
## # nothing specific to install or do
## fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
## fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-freertos-builtin'; then
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
## fi
#
# test_h723:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h72.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h723zg-make-baremetal-builtin'; then
# make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h723zg-make-freertos-builtin'; then
# make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_h5:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h5.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h563zi-make-baremetal-builtin'; then
# make -C tutorials/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h563zi-make-freertos-builtin'; then
# make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_rt1020:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1020-evk-make-baremetal-builtin'; then
# make -C tutorials/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/nxp/rt1020-evk-make-freertos-builtin'; then
# make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_rt1060:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1060-evk-make-baremetal-builtin'; then
# make -C tutorials/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/nxp/rt1060-evk-make-freertos-builtin'; then
# make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_rt1170:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/nxp/rt1170-evk-make-baremetal-builtin'; then
# make -C tutorials/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/nxp/rt1170-evk-make-freertos-builtin'; then
# make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_ra6m4:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 3 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# continue-on-error: true
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4-make-baremetal-builtin'; then
# make -C tutorials/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
## - if: ${{ env.GO == 1 }}
## run: |
## if ./test/match_changed_files.sh 'tutorials/renesas/ek-ra6m4-make-freertos-builtin'; then
## make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
## fi
#
# test_tm4c:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c.*-make-" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
# make -C tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh 'tutorials/ti/ek-tm4c1294xl-make-freertos-builtin'; then
# make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_same54:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - name: baremetal
# run: |
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/mqtt/mqtt-client" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
# make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
# - if: ${{ env.GO == 1 }}
# run: |
# if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
# make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
# fi
#
# test_pico_w5500:
# runs-on: ubuntu-latest
# env:
# GO: 0
# steps:
# - uses: actions/checkout@v4
# with: { fetch-depth: 2 }
# - name: SDK
# run: |
# if ./test/match_changed_files.sh "^src" ; then
# echo GO=1 >> $GITHUB_ENV
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
# fi
# - if: ${{ env.GO == 1 }}
# run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
+26
View File
@@ -0,0 +1,26 @@
name: Zephyr
on:
schedule:
- cron: '0 0 * * *' # run at 12 AM UTC
# Allow manual runs
workflow_dispatch:
jobs:
zephyr_examples:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
revno: ["--mr v3.7-branch", "--mr v4.2.0"] # LTS, latest stable
name: Zephyr ${{ matrix.revno }}
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 2 }
- run: test/setup_ga_docker_filesystem.sh
- run: make -C tutorials/zephyr init REPO=zephyrprojectrtos/ci REVNO="${{ matrix.revno }}"
- run: make -C tutorials/zephyr minify REVNO="${{ matrix.revno }}"
- run: make -C tutorials/zephyr update
- run: make -C tutorials/zephyr/device-dashboard build
- run: make -C tutorials/zephyr/http-client build
- run: make -C tutorials/zephyr/http-server build
- run: make -C tutorials/zephyr/mqtt-aws-client build
- run: make -C tutorials/zephyr/websocket-server build
+37 -3
View File
@@ -1,10 +1,9 @@
# Mongoose - Embedded Web Server / Embedded Network Library
[![License: GPLv2/Commercial](https://img.shields.io/badge/License-GPLv2%20or%20Commercial-green.svg)](https://opensource.org/licenses/gpl-2.0.php)
[![Build Status]( https://github.com/cesanta/mongoose/workflows/build/badge.svg)](https://github.com/cesanta/mongoose/actions)
[![Build Status]( https://github.com/cesanta/mongoose/actions/workflows/quicktest.yml/badge.svg)](https://github.com/cesanta/mongoose/actions)
[![Code Coverage](https://codecov.io/gh/cesanta/mongoose/branch/master/graph/badge.svg)](https://codecov.io/gh/cesanta/mongoose)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/mongoose.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20Mongoose%20Guru-006BFF)](https://gurubase.io/g/mongoose)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/mongoose.svg)](https://issues.oss-fuzz.com/issues?sort=-opened&can=1&q=proj:mongoose)
Mongoose is a network library for C/C++. It provides event-driven non-blocking
APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocols. It is designed
@@ -35,6 +34,35 @@ robust, and easy. Features include:
See https://mongoose.ws/ for complete documentation, videos, case studies, etc.
## Supported platforms
Mongoose can work on top of any TCP/IP stack that supports BSD sockets API.
Platforms supported by the 3rd party TCP/IP stacks:
| TCP/IP stack | Notes |
| :-------------- | :------- |
| **lwIP** | All devices running lwIP, for example ESP32, ESP32S3, ESP32C3, ESP32C6, etc |
| **Zephyr** | All devices supported by Zephyr |
| **Other** | Any other TCP/IP stack that supports BSD socket API, for example Amazon FreeRTOS-TCP |
| **Linux, Mac, Windows** | Workstations, server, single board computers, embedded Linux devices running on MPUs or FPGAs |
Optionally, Mongoose provides its own built-in TCP/IP stack, eliminating the
need for additional software to implement networking functionality. The
built-in stack supports operation in both bare-metal and RTOS environments.
Platforms supported by the Mongoose built-in TCP/IP stack:
| Hardware | Notes |
| :------------- | :------- |
| **STM32** | All STM32 MCUs with built-in Ethernet: STM32Fxx, STM32H5xx, STM32H7xx |
| **NXP** | All NXP MCUs with built-in Ethernet: IMXRT102x, IMXRT104x, IMXRT105x, IMXRT106x, IMXRT117x, RW612, MCXN94x |
| **Microchip** | ATSAME54 MCUs with built-int Ethernet |
| **Renesas** | RA5M, RA6M, RA8M MCUs with built-in Ethernet |
| **Infineon** | XMC4, XMC7 MCUs with built-in Ethernet |
| **Texas Instruments** | TM4C, TMS570 MCUs with built-in Ethernet |
| **Cypress WiFi** | Any MCU with CY43xx WiFi chips, like RP2040 Pico-W, RP2350 Pico2-W, Arduino Portenta |
| **Wiznet Ethernet** | Any MCU that use Wiznet W5500 or Wiznet 5100 MAC+PHY chips |
| **Cellular** | NRF9160, SIM800 |
## Usage Examples
Below are quick snippets that should give an idea how simple the API is and
@@ -177,6 +205,12 @@ Technical guides and deep dives into embedded web servers, WebUI integration and
- [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/)
- [How to build an STM32 Web Dashboard](https://mongoose.ws/articles/stm32-device-dashboard/)
- [STM32 WebSocket Guide](https://mongoose.ws/articles/stm32-websocket-guide/)
- [Web File Manager on STM32, ESP32 and Embedded Linux](https://mongoose.ws/articles/building-a-web-file-manager-on-stm32-esp32-embedded-linux/)
- [Web dashboard on Zephyr RTOS](https://mongoose.ws/articles/web-dashboard-on-zephyr-rtos/)
- [Limiting TCP/IP RAM usage on STM32](https://mongoose.ws/articles/limiting-tcpip-ram-usage-on-stm32/)
- [STM32 Ethernet explained](https://mongoose.ws/articles/stm32-ethernet-explained/)
## Contributions
+2821 -1241
View File
File diff suppressed because it is too large. Load diff
+854 -472
View File
File diff suppressed because it is too large. Load diff
+9 -4
View File
@@ -6,9 +6,9 @@
#define MG_ARCH_ESP32 3 // ESP32
#define MG_ARCH_ESP8266 4 // ESP8266
#define MG_ARCH_FREERTOS 5 // FreeRTOS
#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
#define MG_ARCH_THREADX 6 // Eclipse ThreadX (former MS Azure RTOS)
#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
#define MG_ARCH_NEWLIB 8 // Bare metal ARM
#define MG_ARCH_ARMGCC 8 // Plain ARM GCC
#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
#define MG_ARCH_PICOSDK 11 // Raspberry Pi Pico-SDK (RP2040, RP2350)
@@ -16,6 +16,9 @@
#define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS)
#define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS
#define MG_ARCH_ARMCGT 15 // Texas Semi ARM-CGT
#define MG_ARCH_CUBE 16 // STM32Cube environment
#define MG_ARCH_NEWLIB MG_ARCH_ARMGCC // Alias, deprecate in 2025
#if !defined(MG_ARCH)
#if defined(__unix__) || defined(__APPLE__)
@@ -30,17 +33,19 @@
#endif
#if !defined(MG_ARCH)
#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in your compiler"
#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in mongoose_config.h"
#endif
// http://esr.ibiblio.org/?p=5095
#define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
#include "arch_armgcc.h"
#include "arch_cube.h"
#include "arch_esp32.h"
#include "arch_esp8266.h"
#include "arch_freertos.h"
#include "arch_newlib.h"
#include "arch_rtx.h"
#include "arch_threadx.h"
#include "arch_unix.h"
#include "arch_win32.h"
#include "arch_zephyr.h"
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#if MG_ARCH == MG_ARCH_NEWLIB
#if MG_ARCH == MG_ARCH_ARMGCC
#define _POSIX_TIMERS
#include <ctype.h>
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#if MG_ARCH == MG_ARCH_AZURERTOS
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <fx_api.h>
#include <tx_api.h>
#include <nx_api.h>
#include <nx_bsd.h>
#include <nx_port.h>
#include <tx_port.h>
#define PATH_MAX FX_MAXIMUM_PATH
#define MG_DIRSEP '\\'
#define socklen_t int
#define closesocket(x) soc_close(x)
#undef FOPEN_MAX
#endif
+85
View File
@@ -0,0 +1,85 @@
#pragma once
#if MG_ARCH == MG_ARCH_CUBE
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
// Cube-generated header, includes ST Cube HAL
// NOTE: use angle brackets to prevent amalgamator ditching it
#include <main.h>
#ifndef MG_PATH_MAX
#define MG_PATH_MAX 100
#endif
#ifndef MG_ENABLE_DIRLIST
#define MG_ENABLE_DIRLIST 0
#endif
#ifndef MG_ENABLE_SOCKET
#define MG_ENABLE_SOCKET 0
#endif
#ifndef MG_ENABLE_TCPIP
#define MG_ENABLE_TCPIP 1 // Enable built-in TCP/IP stack
#endif
#if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_STM32F) && !defined(MG_ENABLE_DRIVER_STM32H)
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
#define MG_ENABLE_DRIVER_STM32F 1
#elif defined(STM32H5) || defined(STM32H7)
#define MG_ENABLE_DRIVER_STM32H 1
#else
#error Select a driver in mongoose_config.h
#endif
#endif
#ifndef MG_TLS
#define MG_TLS MG_TLS_BUILTIN
#endif
#if !defined(MG_OTA) && defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
#define MG_OTA MG_OTA_STM32F
#elif !defined(MG_OTA) && defined(STM32H5)
#define MG_OTA MG_OTA_STM32H5
#elif !defined(MG_OTA) && defined(STM32H7)
#define MG_OTA MG_OTA_STM32H7
#endif
// use HAL-defined execute-in-ram section
#define MG_IRAM __attribute__((section(".RamFunc")))
#ifndef HAL_ICACHE_MODULE_ENABLED
#define HAL_ICACHE_IsEnabled() 0
#define HAL_ICACHE_Enable() (void) 0
#define HAL_ICACHE_Disable() (void) 0
#endif
#ifndef MG_SET_MAC_ADDRESS
// Construct MAC address from UUID
#define MGUID ((uint32_t *) UID_BASE) // Unique 96-bit chip ID
#define MG_SET_MAC_ADDRESS(mac) \
do { \
int icache_enabled_ = HAL_ICACHE_IsEnabled(); \
if (icache_enabled_) HAL_ICACHE_Disable(); \
mac[0] = 42; \
mac[1] = ((MGUID[0] >> 0) & 255) ^ ((MGUID[2] >> 19) & 255); \
mac[2] = ((MGUID[0] >> 10) & 255) ^ ((MGUID[1] >> 10) & 255); \
mac[3] = (MGUID[0] >> 19) & 255; \
mac[4] = ((MGUID[1] >> 0) & 255) ^ ((MGUID[2] >> 10) & 255); \
mac[5] = ((MGUID[2] >> 0) & 255) ^ ((MGUID[1] >> 19) & 255); \
if (icache_enabled_) HAL_ICACHE_Enable(); \
} while (0)
#endif
#endif
+8
View File
@@ -22,4 +22,12 @@
#define MG_PATH_MAX 128
#ifndef MG_ENABLE_POSIX_FS
#define MG_ENABLE_POSIX_FS 1
#endif
#ifndef MG_ENABLE_DIRLIST
#define MG_ENABLE_DIRLIST 1
#endif
#endif
+9 -4
View File
@@ -17,6 +17,7 @@
#define mode_t size_t
#include <alloca.h>
#include <time.h>
#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
#elif defined(__CCRH__)
#else
#include <sys/stat.h>
@@ -25,10 +26,11 @@
#include <FreeRTOS.h>
#include <task.h>
#define calloc(a, b) mg_calloc(a, b)
#define free(a) vPortFree(a)
#define malloc(a) pvPortMalloc(a)
#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
#define MG_ENABLE_CUSTOM_CALLOC 1
static inline void mg_free(void *ptr) {
vPortFree(ptr);
}
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
static inline void *mg_calloc(size_t cnt, size_t size) {
@@ -37,10 +39,13 @@ static inline void *mg_calloc(size_t cnt, size_t size) {
return p;
}
#if !defined(MG_ENABLE_POSIX_FS) || !MG_ENABLE_POSIX_FS
#else
#define mkdir(a, b) mg_mkdir(a, b)
static inline int mg_mkdir(const char *path, mode_t mode) {
(void) path, (void) mode;
return -1;
}
#endif
#endif // MG_ARCH == MG_ARCH_FREERTOS
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#if MG_ARCH == MG_ARCH_THREADX
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
// Do not include time.h and stdlib.h, since they conflict with nxd_bsd.h
// extern time_t time(time_t *);
#include <nxd_bsd.h>
#define MG_DIRSEP '\\'
#undef FOPEN_MAX
#ifndef MG_PATH_MAX
#define MG_PATH_MAX 32
#endif
#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
#define MG_SOCK_LISTEN_BACKLOG_SIZE 3
#endif
#ifndef MG_ENABLE_IPV6
#define MG_ENABLE_IPV6 0
#endif
#define socklen_t int
#define closesocket(x) soc_close(x)
// In order to enable BSD support in NetxDuo, do the following (assuming Cube):
// 1. Add nxd_bsd.h and nxd_bsd.c to the repo:
// https://github.com/eclipse-threadx/netxduo/blob/v6.1.12_rel/addons/BSD/nxd_bsd.c
// https://github.com/eclipse-threadx/netxduo/blob/v6.1.12_rel/addons/BSD/nxd_bsd.h
// 2. Add to tx_user.h
// #define TX_THREAD_USER_EXTENSION int bsd_errno;
// 3. Add to nx_user.h
// #define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
// 4. Add __CCRX__ build preprocessor constant
// Project -> Properties -> C/C++ -> Settings -> MCU Compiler -> Preprocessor
#endif
+13 -4
View File
@@ -18,6 +18,17 @@
#define _CRT_RAND_S
#endif
#ifndef _WIN32_WINNT
#if defined(_MSC_VER) && _MSC_VER < 1700
#define _WIN32_WINNT 0x0400 // Let vc98 pick up wincrypt.h
#else
#define _WIN32_WINNT 0x0600
#endif
#endif
#ifndef WINVER
#define WINVER _WIN32_WINNT
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@@ -45,6 +56,8 @@
#include <sys/types.h>
#include <time.h>
#include <winsock2.h> // fix missing macros and types
#if defined(_MSC_VER) && _MSC_VER < 1700
#define __func__ ""
typedef __int64 int64_t;
@@ -66,13 +79,9 @@ typedef enum { false = 0, true = 1 } bool;
#include <process.h>
#include <winerror.h>
#include <winsock2.h> // fix missing macros and types
// For mg_random()
#if defined(_MSC_VER) && _MSC_VER < 1700
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400 // Let vc98 pick up wincrypt.h
#endif
#include <wincrypt.h>
#pragma comment(lib, "advapi32.lib")
#endif
+1
View File
@@ -3,6 +3,7 @@
#if MG_ARCH == MG_ARCH_ZEPHYR
#include <zephyr/kernel.h>
#include <zephyr/version.h>
#include <ctype.h>
#include <errno.h>
+32
View File
@@ -4,6 +4,10 @@
#define MG_ENABLE_LOG 1
#endif
#ifndef MG_ENABLE_CUSTOM_CALLOC
#define MG_ENABLE_CUSTOM_CALLOC 0
#endif
#ifndef MG_ENABLE_CUSTOM_LOG
#define MG_ENABLE_CUSTOM_LOG 0 // Let user define their own MG_LOG
#endif
@@ -171,10 +175,34 @@
#define MG_TCPIP_GW MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP)
#endif
#if MG_ENABLE_IPV6
#ifndef MG_TCPIP_GLOBAL
#define MG_TCPIP_GLOBAL MG_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
#endif
#ifndef MG_TCPIP_IPV6_LINKLOCAL
#define MG_TCPIP_IPV6_LINKLOCAL MG_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
#endif
#ifndef MG_TCPIP_PREFIX_LEN
#define MG_TCPIP_PREFIX_LEN 0
#endif
#ifndef MG_TCPIP_GW6
#define MG_TCPIP_GW6 MG_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
#endif
#endif
#ifndef MG_SET_MAC_ADDRESS
#define MG_SET_MAC_ADDRESS(mac)
#endif
#ifndef MG_TCPIP_DHCPNAME_SIZE
#define MG_TCPIP_DHCPNAME_SIZE 18 // struct mg_tcpip_if :: dhcp_name size
#endif
#ifndef MG_SET_WIFI_CONFIG
#define MG_SET_WIFI_CONFIG(data)
#endif
@@ -182,3 +210,7 @@
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
#define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
#endif
#ifndef MG_ENABLE_CHACHA20
#define MG_ENABLE_CHACHA20 1 // When set to 0, GCM is used. For MG_TLS_BUILTIN
#endif
+18 -12
View File
@@ -18,7 +18,7 @@ static void mg_sendnsreq(struct mg_connection *, struct mg_str *, int,
static void mg_dns_free(struct dns_data **head, struct dns_data *d) {
LIST_DELETE(struct dns_data, head, d);
free(d);
mg_free(d);
}
void mg_resolve_cancel(struct mg_connection *c) {
@@ -232,21 +232,26 @@ static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name,
return mg_send(c, &pkt, sizeof(pkt.header) + n);
}
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc);
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc) {
if (dnsc->url == NULL) {
mg_error(0, "DNS server URL is NULL. Call mg_mgr_init()");
return false;
}
if (dnsc->c == NULL) {
dnsc->c = mg_connect(mgr, dnsc->url, NULL, NULL);
if (dnsc->c == NULL) return false;
dnsc->c->pfn = dns_cb;
}
return true;
}
static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
struct mg_dns *dnsc, bool ipv6) {
struct dns_data *d = NULL;
if (dnsc->url == NULL) {
mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()");
} else if (dnsc->c == NULL) {
dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL);
if (dnsc->c != NULL) {
dnsc->c->pfn = dns_cb;
// dnsc->c->is_hexdumping = 1;
}
}
if (dnsc->c == NULL) {
if (!mg_dnsc_init(c->mgr, dnsc)) {
mg_error(c, "resolver");
} else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
} else if ((d = (struct dns_data *) mg_calloc(1, sizeof(*d))) == NULL) {
mg_error(c, "resolve OOM");
} else {
struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
@@ -345,3 +350,4 @@ struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
return c;
}
+362 -147
View File
@@ -1,32 +1,54 @@
#include "cyw.h"
#include "net.h"
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
#if MG_ENABLE_TCPIP && \
((defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW) || \
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO))
#ifndef MG_ENABLE_DRIVER_CYW
#define MG_ENABLE_DRIVER_CYW 0
#endif
#ifndef MG_ENABLE_DRIVER_CYW_SDIO
#define MG_ENABLE_DRIVER_CYW_SDIO 0
#endif
static struct mg_tcpip_if *s_ifp;
static uint32_t s_ip, s_mask;
static bool s_link, s_auth, s_join;
static void wifi_cb(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
struct mg_wifi_data *wifi = &((struct mg_tcpip_driver_cyw_data *) ifp->driver_data)->wifi;
if (wifi->apmode && ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_UP) {
MG_DEBUG(("Access Point started"));
s_ip = ifp->ip, ifp->ip = wifi->apip;
s_mask = ifp->mask, ifp->mask = wifi->apmask;
ifp->enable_dhcp_client = false;
ifp->enable_dhcp_server = true;
}
}
static bool cyw_init(uint8_t *mac);
static void cyw_poll(void);
static bool mg_tcpip_driver_cyw_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_cyw_data *d =
(struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
struct mg_wifi_data *wifi = &d->wifi;
if (MG_BIG_ENDIAN) {
MG_ERROR(("Big-endian host"));
return false;
}
s_ifp = ifp;
s_ip = ifp->ip;
s_mask = ifp->mask;
s_link = s_auth = s_join = false;
ifp->pfn = wifi_cb;
if (!cyw_init(ifp->mac)) return false;
if (d->apmode) {
MG_DEBUG(("Starting AP '%s' (%u)", d->apssid, d->apchannel));
return mg_wifi_ap_start(d->apssid, d->appass, d->apchannel);
} else if (d->ssid != NULL && d->pass != NULL) {
MG_DEBUG(("Connecting to '%s'", d->ssid));
return mg_wifi_connect(d->ssid, d->pass);
if (wifi->apmode) {
return mg_wifi_ap_start(wifi);
} else if (wifi->ssid != NULL && wifi->pass != NULL) {
return mg_wifi_connect(wifi);
}
return true;
}
@@ -36,7 +58,7 @@ size_t mg_tcpip_driver_cyw_output(const void *buf, size_t len,
struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_cyw_data *d =
(struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
return mg_cyw_tx(d->apmode ? 1 : 0, (void *) buf, len) >= len ? len : 0;
return mg_cyw_tx(d->wifi.apmode ? 1 : 0, (void *) buf, len) >= len ? len : 0;
}
static bool mg_tcpip_driver_cyw_poll(struct mg_tcpip_if *ifp, bool s1) {
@@ -44,7 +66,7 @@ static bool mg_tcpip_driver_cyw_poll(struct mg_tcpip_if *ifp, bool s1) {
if (!s1) return false;
struct mg_tcpip_driver_cyw_data *d =
(struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
return d->apmode ? s_link : s_link && s_auth && s_join;
return d->wifi.apmode ? s_link : s_link && s_auth && s_join;
}
struct mg_tcpip_driver mg_tcpip_driver_cyw = {mg_tcpip_driver_cyw_init,
@@ -68,10 +90,12 @@ struct mg_tcpip_driver mg_tcpip_driver_cyw = {mg_tcpip_driver_cyw_init,
// SPI | SDIO <-- padded to 32-bit | 64-bytes
//
// - SDPCM has 3 channels (control, data, and asynchronous data)
// - SPI (and SDIO) has 4 "functions", F0 to F3, to access different
// blocks in the chip, like the SPI/SDIO controller, chip backplane, and 2 DMA
// I/Os; these are usually handled by SDPCM but we need to explicitly access
// the I/O controller and chip backplane during initialization
// - SPI has 4 "functions", F0 to F3, to access different blocks in the chip,
// like the SPI/SDIO controller, chip backplane, and 2 DMA I/Os; these are
// usually handled by SDPCM but we need to explicitly access the I/O controller
// and chip backplane during initialization
// - SDIO has 3 functions (proper SDIO terminology), F0 to F2, coincident with
// those for SPI, accessed through standard SDIO practices. There is no F3.
// Processor core firmware is loaded to TCM RAM, along with module-dependent
// (hardware design) NVRAM data, via the chip backplane access through the bus
@@ -121,10 +145,15 @@ struct data_hdr {
struct bdc_hdr bdc;
};
// gSPI, DS 4.2.1 Fig.12, 2-bit field
#define CYW_SD_FUNC_BUS 0 // F0
#define CYW_SD_FUNC_CHIP 1 // F1
#define CYW_SD_FUNC_WLAN 2 // F2
// gSPI, CYW43439 DS 4.2.1 Fig.12, 2-bit field
#define CYW_SPID_FUNC_BUS 0 // F0
#define CYW_SPID_FUNC_CHIP 1 // F1
#define CYW_SPID_FUNC_WLAN 2 // F2
// SDIO functions, 3-bit field; CYW4343W and CYW43439 DS 4.1
#define CYW_SDIO_FUNC_BUS 0 // F0
#define CYW_SDIO_FUNC_CHIP 1 // F1
#define CYW_SDIO_FUNC_WLAN 2 // F2
#define CYW_SDPCM_CTRL_HDR 0
#define CYW_SDPCM_ASYNC_HDR 1
@@ -139,7 +168,7 @@ static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len);
static void cyw_handle_bdc(struct bdc_hdr *bdc, size_t len);
static void cyw_handle_bdc_evnt(struct bdc_hdr *bdc, size_t len);
static size_t cyw_spi_poll(uint8_t *dest);
static size_t cyw_bus_specific_poll(uint32_t *dest);
static void cyw_update_hash_table(void);
// High-level comm stuff
@@ -152,7 +181,7 @@ static void cyw_poll(void) {
cyw_update_hash_table();
s_ifp->update_mac_hash_table = false;
}
if (cyw_spi_poll((uint8_t *) resp) == 0) return; // BUS DEPENDENCY
if (cyw_bus_specific_poll(resp) == 0) return;
if ((sdpcm->len ^ sdpcm->_len) != 0xffff || sdpcm->len < sizeof(*sdpcm) ||
sdpcm->len > 2048 - sizeof(*sdpcm))
return;
@@ -185,7 +214,7 @@ static void cyw_handle_bdc(struct bdc_hdr *bdc, size_t len) {
mg_tcpip_qwrite(payload, len - (payload - (uint8_t *) bdc), s_ifp);
}
static size_t cyw_bus_tx(uint32_t *data, uint16_t len);
static size_t cyw_bus_specific_tx(uint32_t *data, uint16_t len);
// WLAN frame transmission
static size_t mg_cyw_tx(unsigned int ifc, void *data, size_t len) {
@@ -194,15 +223,15 @@ static size_t mg_cyw_tx(unsigned int ifc, void *data, size_t len) {
memset(txdata, 0, sizeof(*hdr));
memcpy((uint8_t *) txdata + sizeof(*hdr), data, len);
// TODO(): hdr->bdc.priority = map IP to TOS if supporting QoS/ToS
hdr->bdc.flags = 2 << 4; // BDC version 2
hdr->bdc.flags2 = ifc; // 0 -> STA, 1 -> AP
hdr->bdc.flags = 2 << 4; // BDC version 2
hdr->bdc.flags2 = (uint8_t) ifc; // 0 -> STA, 1 -> AP
// hdr->bdc.data_offset = 0; // actually zeroed above
hdr->sdpcm.len = txlen;
hdr->sdpcm._len = (uint16_t) ~txlen;
hdr->sdpcm.sw_hdr.sequence = ++s_tx_seqno;
hdr->sdpcm.sw_hdr.channel_and_flags = CYW_SDPCM_DATA_HDR,
hdr->sdpcm.sw_hdr.header_length = offsetof(struct data_hdr, bdc);
return cyw_bus_tx(txdata, txlen);
return cyw_bus_specific_tx(txdata, txlen);
}
// WLAN event handling
@@ -250,6 +279,7 @@ struct scan_result;
static void cyw_handle_scan_result(uint32_t status, struct scan_result *data,
size_t len);
// Do not call any IOCTL functions here, otherwise revise cyw_ioctl_wait()
static void cyw_handle_bdc_evnt(struct bdc_hdr *bdc, size_t len) {
struct evnt_msg *msg = (struct evnt_msg *) &bdc[bdc->data_offset + 1];
MG_VERBOSE(("%u bytes event", len));
@@ -313,7 +343,7 @@ static bool cyw_ioctl_iovar_set_(unsigned int ifc, char *var, void *data,
size_t len);
// clang-format off
// convenience: ioctl funcs on default ifc (0), as only AP needs ifc 1
static bool cyw_ioctl_get(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_get_(0, cmd, data, len); }
__attribute__((unused)) static bool cyw_ioctl_get(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_get_(0, cmd, data, len); }
static bool cyw_ioctl_set(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_set_(0, cmd, data, len); }
static bool cyw_ioctl_iovar_get(char *var, void *data, size_t len) { return cyw_ioctl_iovar_get_(0, var, data, len); }
static bool cyw_ioctl_iovar_set(char *var, void *data, size_t len) { return cyw_ioctl_iovar_set_(0, var, data, len); }
@@ -324,9 +354,10 @@ static bool cyw_ioctl_iovar_set(char *var, void *data, size_t len) { return cyw_
// clang-format off
static bool cyw_wifi_connect(char *ssid, char *pass) {
uint32_t sup_wpa[2] = {0, 1}; // bss index 0 = STA, not open
static const uint32_t const eapver[2] = {0, (uint32_t) -1}, // accept AP version
static const uint32_t eapver[2] = {0, (uint32_t) -1}, // accept AP version
tmo[2] = {0, 2500};
uint32_t data[64/4 + 1]; // max pass length: 64 for WPA, 128 for WPA3 SAE
uint16_t *da = (uint16_t *) data;
unsigned int len;
uint32_t val;
val = 4; // security type: 0 for none, 2 for WPA, 4 for WPA2/WPA3, 6 for mixed WPA/WPA2
@@ -340,8 +371,8 @@ static bool cyw_wifi_connect(char *ssid, char *pass) {
// skip if not using auth
memset(data, 0, sizeof(data));
len = strlen(pass);
((uint16_t *)data)[0] = (uint16_t) len;
((uint16_t *)data)[1] = 1; // indicates wireless security key, skip for WPA3 SAE
da[0] = (uint16_t) len;
da[1] = 1; // indicates wireless security key, skip for WPA3 SAE
memcpy((uint8_t *)data + 2 * sizeof(uint16_t), pass, len); // skip for WPA3 SAE
if (!cyw_ioctl_set(268 /* SET_WSEC_PMK */, data, sizeof(data))) return false; // skip for WPA3 SAE, sizeof/2 if supporting SAE but using WPA
// for WPA3 SAE: memcpy((uint8_t *)data + sizeof(uint16_t), pass, len); cyw_ioctl_iovar_set("sae_password", data, sizeof(data));
@@ -368,6 +399,7 @@ static bool cyw_wifi_disconnect(void) {
static bool cyw_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
uint32_t data[64/4 + 2]; // max pass length: 64 for WPA, 128 for WPA3 SAE
uint16_t *da = (uint16_t *) data;
unsigned int len;
uint32_t val;
// CHIP DEPENDENCY
@@ -394,8 +426,8 @@ static bool cyw_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
// NOTE(): WHD does not set SAE password for shared WPA2/WPA3, same do we
memset(data, 0, sizeof(data));
len = strlen(pass);
((uint16_t *)data)[0] = (uint16_t) len; // skip for WPA3 SAE
((uint16_t *)data)[1] = 1; // indicates wireless security key, skip for WPA3 SAE
da[0] = (uint16_t) len; // skip for WPA3 SAE (43430 does NOT support WPA3 in AP)
da[1] = 1; // indicates wireless security key, skip for WPA3 SAE
memcpy((uint8_t *)data + 2 * sizeof(uint16_t), pass, len); // skip for WPA3 SAE
if (!cyw_ioctl_set_(1, 268 /* SET_WSEC_PMK */, data, sizeof(data))) return false; // skip for WPA3 SAE, sizeof/2 if supporting SAE but using WPA
/* for WPA3 SAE:
@@ -539,8 +571,8 @@ static void cyw_handle_scan_result(uint32_t status, struct scan_result *data, si
if (sbss->length > len - offsetof(struct scan_result, bss) || sbss->SSID_len > sizeof(sbss->SSID) || sbss->ie_offset < sizeof(*sbss) || sbss->ie_offset > (sizeof(*sbss) + sbss->ie_length) || sbss->ie_offset + sbss->ie_length > sbss->length)
return; // silently discard malformed data
if (!(sbss->flags & MG_BIT(2))) return; // RSSI_ONCHANNEL, ignore off-channel results
bss.SSID = mg_str_n(sbss->SSID, sbss->SSID_len);
bss.BSSID = sbss->BSSID;
bss.SSID = mg_str_n((char *)sbss->SSID, sbss->SSID_len);
bss.BSSID = (char *)sbss->BSSID;
bss.RSSI = (int8_t)sbss->RSSI;
bss.has_n = sbss->n_cap != 0;
bss.channel = bss.has_n ? sbss->ctl_ch : (uint8_t)(sbss->chanspec & 0xff); // n 40MHz vs a/b/g and 20MHz
@@ -575,7 +607,7 @@ static uint8_t *s_ioctl_resp;
static bool s_ioctl_err;
static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len) {
uint8_t *resp = (uint8_t *) cdc + sizeof(*cdc);
uint8_t *r = (uint8_t *) cdc + sizeof(*cdc);
MG_VERBOSE(("%u bytes CDC frame", len));
if ((cdc->flags >> 16) != s_ioctl_reqid) return;
if (cdc->flags & 1) {
@@ -584,9 +616,8 @@ static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len) {
return;
}
if (mg_log_level >= MG_LL_VERBOSE) mg_hexdump((void *) cdc, len);
MG_DEBUG(("IOCTL result: %02x %02x %02x %02x ...", resp[0], resp[1], resp[2],
resp[3]));
s_ioctl_resp = resp;
MG_DEBUG(("IOCTL result: %02x %02x %02x %02x ...", r[0], r[1], r[2], r[3]));
s_ioctl_resp = r;
}
// NOTE(): alt no loop handler dispatching IOCTL response to current handler:
// static void *s_ioctl_hnd; *s_ioctl_hnd(ioctl, len);
@@ -618,7 +649,7 @@ static void cyw_ioctl_send_cmd(unsigned int ifc, unsigned int cmd, bool set,
hdr->sdpcm.sw_hdr.sequence = ++s_tx_seqno;
hdr->sdpcm.sw_hdr.channel_and_flags = CYW_SDPCM_CTRL_HDR;
hdr->sdpcm.sw_hdr.header_length = offsetof(struct ctrl_hdr, cdc);
cyw_bus_tx(txdata, txlen);
cyw_bus_specific_tx(txdata, txlen);
}
// just send respective commands, response handled via CDC handler
@@ -652,20 +683,29 @@ static void cyw_ioctl_send_iovar_set2(unsigned int ifc, char *var, void *data1,
cyw_ioctl_send_cmd(ifc, 263, true, txlen); // cmd = SET IOVAR
}
static void cyw_ioctl_send_iovar_set(unsigned int ifc, char *var, void *data,
size_t len) {
__attribute__((unused)) static void cyw_ioctl_send_iovar_set(unsigned int ifc,
char *var,
void *data,
size_t len) {
cyw_ioctl_send_iovar_set2(ifc, var, data, len, NULL, 0);
}
static inline bool delayms(unsigned int ms) {
mg_delayms(ms);
return true;
}
// wait for a response, meanwhile delivering received frames and events
static bool cyw_ioctl_wait(void) {
unsigned int times = 6000;
unsigned int times = 100;
s_ioctl_resp = NULL;
s_ioctl_err = false;
while (s_ioctl_resp == NULL && !s_ioctl_err && times-- > 0)
cyw_poll(); // TODO(scaprile): review wait/sleep strategy (this loop is executed only when initializing/acting on the chip)
MG_DEBUG(("resp: %lp, err: %c, times: %d", s_ioctl_resp,
s_ioctl_err ? '1' : '0', (int) times));
do { // IOCTL response processing does not call any other IOCTL function
cyw_poll(); // otherwise we can't allow them to pile up here
// network frames will be pushed to the queue so that is safe
} while (s_ioctl_resp == NULL && !s_ioctl_err && times-- > 0 && delayms(1));
MG_VERBOSE(("resp: %lp, err: %c, times: %d", s_ioctl_resp,
s_ioctl_err ? '1' : '0', (int) times));
return s_ioctl_resp != NULL;
}
@@ -723,15 +763,22 @@ struct clm_hdr {
#pragma pack(pop)
// worlwide rev0, try rev 17 for 4343W
// worlwide rev0, TODO(): try rev 17 for 4343W
static const uint32_t country_code = 'X' + ('X' << 8) + (0 << 16);
static bool cyw_spi_init();
static bool cyw_bus_specific_init();
static bool cyw_load_clmll(void *data, size_t len);
static bool cyw_load_clm(struct mg_tcpip_driver_cyw_firmware *fw) {
return cyw_load_clmll((void *) fw->clm_addr, fw->clm_len);
}
// clang-format off
static bool cyw_init(uint8_t *mac) {
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
uint32_t val = 0;
if (!cyw_spi_init()) return false; // BUS DEPENDENCY
if (!cyw_bus_specific_init()) return false;
if (!cyw_load_clm(d->fw)) return false; // Load CLM blob
// BT-ENABLED DEPENDENCY
// set Wi-Fi up
val = 0 /* disable */; cyw_ioctl_iovar_set("bus:txglom", (uint8_t *)&val, sizeof(val));
@@ -759,7 +806,7 @@ static bool cyw_init(uint8_t *mac) {
unsigned int times = 100;
while (times --)
if (cyw_ioctl_iovar_set("bsscfg:event_msgs", (uint8_t *)data, sizeof(data))) break;
if (times == ~0) return false;
if (times == (unsigned int) ~0) return false;
}
val = 0; if (!cyw_ioctl_set(64 /* SET_ANTDIV */, (uint8_t *)&val, sizeof(val))) return false;
if (!cyw_ioctl_set(2 /* UP, interface up */, NULL, 0)) return false;
@@ -818,20 +865,18 @@ static bool cyw_load_clmll(void *data, size_t len) {
break;
sent += bytes;
offset += bytes;
hdr.flag &= ~MG_BIT(1); // DL_BEGIN
hdr.flag &= (uint16_t)~MG_BIT(1); // DL_BEGIN
}
return sent >= len;
}
// clang-format on
static bool cyw_load_clm(struct mg_tcpip_driver_cyw_firmware *fw) {
return cyw_load_clmll((void *) fw->clm_addr, fw->clm_len);
}
static void cyw_update_hash_table(void) {
// TODO(): read database, rebuild hash table
uint32_t val = 0;
val = 1; cyw_ioctl_iovar_set2_(0, "mcast_list", (uint8_t *)&val, sizeof(val), (uint8_t *)mcast_addr, sizeof(mcast_addr));
val = 1;
cyw_ioctl_iovar_set2_(0, "mcast_list", (uint8_t *) &val, sizeof(val),
(uint8_t *) mcast_addr, sizeof(mcast_addr));
mg_delayms(50);
}
@@ -848,8 +893,16 @@ static void cyw_update_hash_table(void) {
#define CYW_CHIP_BCKPLN_ADDRMSK 0x7fff
#define CYW_CHIP_BCKPLN_ACCSS4B MG_BIT(15)
#define CYW_CHIP_BCKPLN_WRAPPOFF 0x100000
// BUS DEPENDENCY: max bus to backplane transfer size, bus function id
#define CYW_CHIP_BCKPLN_SPIMAX 64
#define CYW_CHIP_BCKPLN_SDIOMAX 1536
#if MG_ENABLE_DRIVER_CYW_SDIO
#define CYW_CHIP_BCKPLN_BUSMAX CYW_CHIP_BCKPLN_SDIOMAX
#define CYW_BUS_FUNC_CHIP CYW_SDIO_FUNC_CHIP
#else
#define CYW_CHIP_BCKPLN_BUSMAX CYW_CHIP_BCKPLN_SPIMAX
#define CYW_BUS_FUNC_CHIP CYW_SPID_FUNC_CHIP
#endif
// CHIP DEPENDENCY
#define CYW_CHIP_ARMCORE_BASE (CYW_CHIP_CHIPCOMMON + 0x3000)
@@ -874,9 +927,9 @@ static void cyw_update_hash_table(void) {
#define CYW_CHIP_AI_IOCTRL 0x408
#define CYW_CHIP_AI_RESETCTRL 0x800
static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
static bool cyw_bus_write(unsigned int f, uint32_t addr, void *data,
uint16_t len);
static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
static bool cyw_bus_read(unsigned int f, uint32_t addr, void *data,
uint16_t len);
// clang-format off
@@ -884,9 +937,9 @@ static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
static void cyw_set_backplane_window(uint32_t addr) {
uint32_t val;
addr &= ~CYW_CHIP_BCKPLN_ADDRMSK;
val = (addr >> 24) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRHIGH, &val, 1);
val = (addr >> 16) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRMID, &val, 1);
val = (addr >> 8) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRLOW, &val, 1);
val = (addr >> 24) & 0xff; cyw_bus_write(CYW_BUS_FUNC_CHIP, CYW_CHIP_ADDRHIGH, &val, 1);
val = (addr >> 16) & 0xff; cyw_bus_write(CYW_BUS_FUNC_CHIP, CYW_CHIP_ADDRMID, &val, 1);
val = (addr >> 8) & 0xff; cyw_bus_write(CYW_BUS_FUNC_CHIP, CYW_CHIP_ADDRLOW, &val, 1);
}
static bool cyw_core_reset(uint32_t core_base, bool check) {
@@ -894,21 +947,21 @@ static bool cyw_core_reset(uint32_t core_base, bool check) {
// core disabled after chip reset
cyw_set_backplane_window(core_base); // set backplane window for requested area; we do know offsets fall within that window
// possible CHIP DEPENDENCY: AI_RESETSTATUS check and wait (instead of these cool reads) to ensure backplane operations end
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
val = MG_BIT(1) | MG_BIT(0) /* SICF_FGC | SICF_CLOCK_EN */; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // reset
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // release reset
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
val = MG_BIT(1) | MG_BIT(0) /* SICF_FGC | SICF_CLOCK_EN */; cyw_bus_write(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // reset
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
val = 0x00; cyw_bus_write(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // release reset
mg_delayms(1);
val = MG_BIT(0) /* SICF_CLOCK_EN */; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
val = MG_BIT(0) /* SICF_CLOCK_EN */; cyw_bus_write(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
mg_delayms(1);
if (check) {
// Verify only clock is enabled
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
if ((val & (MG_BIT(1) | MG_BIT(0)) /* SICF_FGC | SICF_CLOCK_EN) */) != MG_BIT(0)) return false;
// Verify it is not in reset state
cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
cyw_bus_read(CYW_BUS_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
if (val & MG_BIT(0)) return false; // AIRC_RESET
}
return true;
@@ -916,29 +969,28 @@ static bool cyw_core_reset(uint32_t core_base, bool check) {
static void cyw_socram_init(void) {
uint32_t val;
// CHIP DEPENDENCY: disable remap for SRAM_3
// CHIP DEPENDENCY: disable remap for SRAM_3: 43430 and 43439 only
cyw_set_backplane_window(CYW_CHIP_SOCSRAM_BASE); // set backplane window for requested area; we do know offsets fall within that window
val = 0x03; cyw_spi_write(CYW_SD_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXIDX) & CYW_CHIP_BCKPLN_ADDRMSK) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXPDA) & CYW_CHIP_BCKPLN_ADDRMSK) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
val = 0x03; cyw_bus_write(CYW_BUS_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXIDX) & CYW_CHIP_BCKPLN_ADDRMSK), &val, sizeof(val));
val = 0x00; cyw_bus_write(CYW_BUS_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXPDA) & CYW_CHIP_BCKPLN_ADDRMSK), &val, sizeof(val));
}
// transfer is fractioned in bus-to-backplane-size units within backplane windows
static void cyw_load_data(uint32_t dest, void *data, size_t len) {
size_t sent = 0, offset = 0;
uint32_t last_addr = ~0;
uint32_t last_addr = (uint32_t) ~0;
while (sent < len) {
size_t bytes = len - sent, avail;
uint32_t addr = dest + offset;
if (addr - last_addr >= CYW_CHIP_BCKPLN_WINSZ || last_addr == ~0) {
if (addr - last_addr >= CYW_CHIP_BCKPLN_WINSZ || last_addr == (uint32_t) ~0) {
cyw_set_backplane_window(addr); // set backplane window for requested area
last_addr = addr & ~CYW_CHIP_BCKPLN_ADDRMSK;
}
addr &= CYW_CHIP_BCKPLN_ADDRMSK;
avail = CYW_CHIP_BCKPLN_WINSZ - (unsigned int) addr;
avail = CYW_CHIP_BCKPLN_WINSZ - (unsigned int) addr; // internal backplane limit
if (bytes > avail) bytes = avail;
// BUS DEPENDENCY: max bus to backplane transfer size
if (bytes > CYW_CHIP_BCKPLN_SPIMAX) bytes = CYW_CHIP_BCKPLN_SPIMAX;
cyw_spi_write(CYW_SD_FUNC_CHIP, addr | CYW_CHIP_BCKPLN_ACCSS4B, (uint8_t *)data + offset, bytes);
if (bytes > CYW_CHIP_BCKPLN_BUSMAX) bytes = CYW_CHIP_BCKPLN_BUSMAX; // bus to backplane transfer limit
cyw_bus_write(CYW_BUS_FUNC_CHIP, addr, (uint8_t *)data + offset, (uint16_t) bytes);
sent += bytes;
offset += bytes;
}
@@ -950,13 +1002,13 @@ static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nv
cyw_core_reset(CYW_CHIP_SOCSRAM, false); // cores were disabled at chip reset
cyw_socram_init();
cyw_load_data(CYW_CHIP_ATCMRAM_BASE, fwdata, fwlen);
mg_delayms(5); // ************ CHECK IF THIS IS ACTUALLY NEEDED
mg_delayms(5); // TODO(scaprile): CHECK IF THIS IS ACTUALLY NEEDED
// Load NVRAM and place 'length ~length' at the end; end of chip RAM
{
const uint32_t start = CYW_CHIP_RAM_SIZE - 4 - nvramlen;
cyw_load_data(start, nvramdata, nvramlen); // nvramlen must be a multiple of 4
// RAM_SIZE is a multiple of WINSZ, so the place for len ~len will be at the end of the window
cyw_spi_write(CYW_SD_FUNC_CHIP, (CYW_CHIP_BCKPLN_WINSZ - 4) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
cyw_bus_write(CYW_BUS_FUNC_CHIP, (CYW_CHIP_BCKPLN_WINSZ - 4), &val, sizeof(val));
}
// Reset ARM core and check it starts
if (!cyw_core_reset(CYW_CHIP_ARMCORE, true)) return false;
@@ -964,6 +1016,8 @@ static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nv
}
// clang-format on
#if !MG_ENABLE_DRIVER_CYW_SDIO
// CYW43 SPI bus specifics
#define CYW_BUS_SPI_BUSCTRL 0x00 // 4 regs, 0 to 3
@@ -975,29 +1029,33 @@ static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nv
#define CYW_BUS_STS_LEN(x) ((x >> 9) & 0x7ff)
static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
uint16_t len);
static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
uint16_t len);
// clang-format off
static size_t cyw_spi_poll(uint8_t *response) {
size_t len;
uint32_t res;
// SPI poll
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &res, sizeof(res));
if (res == ~0 || !(res & MG_BIT(8) /* packet available */ )) return 0;
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_STATUS, &res, sizeof(res));
if (res == (uint32_t) ~0 || !(res & MG_BIT(8) /* packet available */ )) return 0;
len = CYW_BUS_STS_LEN(res);
if (len == 0) { // just ack IRQ
uint16_t val = 1;
cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_SPIFRCTRL, &val, 1);
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_SPIFRCTRL, &val, 1);
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
return 0;
}
cyw_spi_read(CYW_SD_FUNC_WLAN, 0, response, len);
cyw_spi_read(CYW_SPID_FUNC_WLAN, 0, response, (uint16_t)len);
return len;
}
// BUS DEPENDENCY: name is generic but function is bus dependent
static size_t cyw_bus_tx(uint32_t *data, uint16_t len) {
while (len & 3) data[len++] = 0; // SPI 32-bit padding (SDIO->64-byte)
return cyw_spi_write(CYW_SD_FUNC_WLAN, 0, data, len) ? len: 0;
static size_t cyw_spi_tx(uint32_t *data, uint16_t len) {
while (len & 3) data[len++] = 0; // SPI 32-bit padding
return cyw_spi_write(CYW_SPID_FUNC_WLAN, 0, data, len) ? len: 0;
}
// this can be integrated in lowest level SPI read/write _driver_ functions
@@ -1007,20 +1065,19 @@ uint32_t sw16_2(uint32_t data) {
}
// DS 4.2.2 Table 6: signal we're working in 16-bit mode
#define CYW_SD_16bMODE MG_BIT(2) // arbitrary bit out of the FUNC space
#define CYW_SPI_16bMODE MG_BIT(2) // arbitrary bit out of the FUNC space
static bool cyw_spi_init() {
struct mg_tcpip_driver_cyw_data *d =
(struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
uint32_t val = 0;
// DS 4.2.3 Boot-Up Sequence; WHD: other chips might require more effort
unsigned int times = 51;
while (times--) {
cyw_spi_read(CYW_SD_FUNC_BUS | CYW_SD_16bMODE, CYW_BUS_SPI_TEST, &val, sizeof(val));
cyw_spi_read(CYW_SPID_FUNC_BUS | CYW_SPI_16bMODE, CYW_BUS_SPI_TEST, &val, sizeof(val));
if (sw16_2(val) == 0xFEEDBEAD) break;
mg_delayms(1);
}
if (times == ~0) return false;
if (times == (unsigned int) ~0) return false;
// DS 4.2.3 Table 6. Chip starts in 16-bit little-endian mode.
// Configure SPI and switch to 32-bit big-endian mode:
// - High-speed mode: d->hs true
@@ -1028,33 +1085,34 @@ static bool cyw_spi_init() {
// - SPI RESPONSE DELAY 4 bytes time [not in DS] TODO(scaprile): logic ana
// - Status not sent after command, IRQ with status
val = sw16_2(0x000204a3 | (d->hs ? MG_BIT(4) : 0)); // 4 reg content
cyw_spi_write(CYW_SD_FUNC_BUS | CYW_SD_16bMODE, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
cyw_spi_write(CYW_SPID_FUNC_BUS | CYW_SPI_16bMODE, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
mg_tcpip_call(s_ifp, MG_TCPIP_EV_DRIVER, NULL);
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_TEST, &val, sizeof(val));
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_TEST, &val, sizeof(val));
if (val != 0xFEEDBEAD) return false;
val = 4; cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_RESPDLY_F1, &val, 1);
val = 4; cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_RESPDLY_F1, &val, 1);
val = 0x99; // clear error bits DATA_UNAVAILABLE, COMMAND_ERROR, DATA_ERROR, F1_OVERFLOW
cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, 1);
cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INT, &val, 1);
val = 0x00be; // Enable IRQs F2_F3_FIFO_RD_UNDERFLOW, F2_F3_FIFO_WR_OVERFLOW, COMMAND_ERROR, DATA_ERROR, F2_PACKET_AVAILABLE, F1_OVERFLOW
// BT-ENABLED DEPENDENCY: add F1_INTR (bit 13)
cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
// chip backplane is ready, initialize it
// request ALP (Active Low Power) clock
val = MG_BIT(3) /* ALP_REQ */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
val = MG_BIT(3) /* ALP_REQ */; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
// BT-ENABLED DEPENDENCY
times = 10;
while (times--) {
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
if (val & MG_BIT(6)) break; // ALP_AVAIL
mg_delayms(1);
}
if (times == ~0) return false;
if (times == (unsigned int) ~0) return false;
// clear request
val = 0; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
val = 0; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
cyw_set_backplane_window(CYW_CHIP_CHIPCOMMON); // set backplane window to start of CHIPCOMMON area
cyw_spi_read(CYW_SD_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
MG_INFO(("WLAN chip is CYW%u", *((uint16_t *)&val)));
cyw_spi_read(CYW_SPID_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
if (val == 43430) val = 4343;
MG_INFO(("WLAN chip is CYW%u%c", val, val == 4343 ? 'W' : ' '));
// Load firmware (code and NVRAM)
if (!cyw_load_firmware(d->fw)) return false;
@@ -1062,77 +1120,74 @@ static bool cyw_spi_init() {
// Wait for High Throughput (HT) clock ready
times = 50;
while (times--) {
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
if (val & MG_BIT(7)) break; // HT_AVAIL
mg_delayms(1);
}
if (times == ~0) return false;
if (times == (unsigned int) ~0) return false;
// Wait for backplane ready
times = 1000;
while (times--) {
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
if (val & MG_BIT(5)) break; // F2_RX_READY
mg_delayms(1);
}
if (times == ~0) return false;
if (times == (unsigned int) ~0) return false;
// CHIP DEPENDENCY
// Enable save / restore
// Configure WakeupCtrl, set HT_AVAIL in CLOCK_CSR
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
#if 0
// Set BRCM_CARDCAP to CMD_NODEC. NOTE(): This is probably only necessary for SDIO, not SPI
val = MG_BIT(3); cyw_spi_write(CYW_SD_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
val = MG_BIT(3); cyw_spi_write(CYW_SPID_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
#endif
// Force HT request to chip backplane
val = MG_BIT(1) /* FORCE_HT */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
val = MG_BIT(1) /* FORCE_HT */; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
// Enable Keep SDIO On (KSO)
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
if (!(val & MG_BIT(0))) {
val |= MG_BIT(0); cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
val |= MG_BIT(0); cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
}
// The SPI bus can be configured for sleep (KSO controls wlan block sleep)
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
val &= ~MG_BIT(7) /* WAKE_UP */; cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
val &= ~MG_BIT(7) /* WAKE_UP */; cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
// Set SPI bus sleep
val = 0x0f; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
val = 0x0f; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
// Clear pullups. NOTE(): ?
val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
val = 0x00; cyw_spi_write(CYW_SPID_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
cyw_spi_read(CYW_SPID_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
// Clear possible data unavailable error
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
if (val & MG_BIT(0)) cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
// Load CLM blob
if (!cyw_load_clm(d->fw)) return false;
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
if (val & MG_BIT(0)) cyw_spi_write(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
return true;
}
// clang-format on
// gSPI, DS 4.2.1 Fig.12
#define CYW_SD_LEN(x) ((x) &0x7FF) // bits 0-10
#define CYW_SD_ADDR(x) (((x) &0x1FFFF) << 11) // bits 11-27,
#define CYW_SD_FUNC(x) (((x) &3) << 28) // bits 28-29
#define CYW_SD_INC MG_BIT(30)
#define CYW_SD_WR MG_BIT(31)
// gSPI, CYW43439 DS 4.2.1 Fig.12
#define CYW_SPID_LEN(x) ((x) &0x7FF) // bits 0-10
#define CYW_SPID_ADDR(x) (((x) &0x1FFFF) << 11) // bits 11-27,
#define CYW_SPID_FUNC(x) (((x) &3) << 28) // bits 28-29
#define CYW_SPID_INC MG_BIT(30)
#define CYW_SPID_WR MG_BIT(31)
static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
uint16_t len) {
struct mg_tcpip_driver_cyw_data *d =
(struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->spi;
uint32_t hdr = CYW_SD_WR | CYW_SD_INC | CYW_SD_FUNC(f) | CYW_SD_ADDR(addr) |
CYW_SD_LEN(len); // gSPI header
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->bus;
uint32_t hdr = CYW_SPID_WR | CYW_SPID_INC | CYW_SPID_FUNC(f) |
CYW_SPID_ADDR(addr) | CYW_SPID_LEN(len); // gSPI header
// TODO(scaprile): check spin in between and timeout values, return false
if (f == CYW_SD_FUNC_WLAN) {
if (f == CYW_SPID_FUNC_WLAN) {
uint32_t val = 0;
while ((val & MG_BIT(5)) != MG_BIT(5)) // F2 rx ready (FIFO ready)
cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
cyw_spi_read(CYW_SPID_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
}
if (f & CYW_SD_16bMODE)
if (f & CYW_SPI_16bMODE)
hdr = sw16_2(hdr); // swap half-words in 16-bit little-endian mode
s->begin(NULL);
@@ -1148,26 +1203,26 @@ static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
return true;
}
// will write 32-bit aligned quantities to data if f == CYW_SD_FUNC_WLAN
// will write 32-bit aligned quantities to data if f == CYW_SPID_FUNC_WLAN
static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
uint16_t len) {
struct mg_tcpip_driver_cyw_data *d =
(struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->spi;
struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->bus;
uint32_t padding =
f == CYW_SD_FUNC_CHIP
f == CYW_SPID_FUNC_CHIP
? 4
: 0; // add padding to chip backplane reads as a response delay
uint32_t hdr = CYW_SD_INC | CYW_SD_FUNC(f) | CYW_SD_ADDR(addr) |
CYW_SD_LEN(len + padding); // gSPI header
if (f == CYW_SD_FUNC_WLAN && (len & 3))
uint32_t hdr = CYW_SPID_INC | CYW_SPID_FUNC(f) | CYW_SPID_ADDR(addr) |
CYW_SPID_LEN(len + padding); // gSPI header
if (f == CYW_SPID_FUNC_WLAN && (len & 3))
len = (len + 4) & ~3; // align WLAN transfers to 32-bit
if (f & CYW_SD_16bMODE)
if (f & CYW_SPI_16bMODE)
hdr = sw16_2(hdr); // swap half-words in 16-bit little-endian mode
s->begin(NULL);
s->txn(NULL, (uint8_t *) &hdr, NULL, sizeof(hdr));
if (f == CYW_SD_FUNC_CHIP) {
if (f == CYW_SPID_FUNC_CHIP) {
uint32_t pad;
s->txn(NULL, NULL, (uint8_t *) &pad, 4); // read padding back and discard
}
@@ -1175,22 +1230,182 @@ static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
s->end(NULL);
}
static bool cyw_bus_specific_init(void) {
return cyw_spi_init();
}
static size_t cyw_bus_specific_poll(uint32_t *response) {
return cyw_spi_poll((uint8_t *) response);
}
static size_t cyw_bus_specific_tx(uint32_t *data, uint16_t len) {
return cyw_spi_tx(data, len);
}
static bool cyw_bus_write(unsigned int f, uint32_t addr, void *data,
uint16_t len) {
if (f == CYW_SPID_FUNC_CHIP && len >= 4) addr |= CYW_CHIP_BCKPLN_ACCSS4B;
return cyw_spi_write(f, addr, data, len);
}
static bool cyw_bus_read(unsigned int f, uint32_t addr, void *data,
uint16_t len) {
cyw_spi_read(f, addr, data, len);
return true;
}
#else // MG_ENABLE_DRIVER_CYW_SDIO
#include "sdio.h"
// CYW43 SDIO bus specifics
// CYW4343W and CYW43439 DS 4.1 SDIO v2.0:
//- F0: max block size is 32 bytes
//- F1: max block size is 64 bytes
//- F2: max block size is 512 bytes
// clang-format off
static bool cyw_sdio_transfer(bool write, unsigned int f, uint32_t addr, void *data, uint32_t len) {
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
struct mg_tcpip_sdio *s = (struct mg_tcpip_sdio *) d->bus;
uint32_t *ptr = (uint32_t *) data; // assume 32-bit aligned data (all except firmware)
if (write && (size_t) data & 3) { // missed, source data is not 32-bit aligned
memcpy(txdata, data, len); // copy to an aligned buffer, we know it fits
ptr = txdata;
} // all possible read destinations are 32-bit aligned
// mg_sdio_transfer requires 32-bit alignment for > 1 byte transfers
return mg_sdio_transfer(s, write, f, addr, ptr, len);
}
static size_t cyw_sdio_poll(uint32_t *response) {
uint32_t res;
uint16_t *len = (uint16_t *)&res;
// WHD: internal docs, "tag" hinting a possible packet.
// This is actually the len / ~len field of a possible struct sdpcm_hdr, if there is a packet available, or 0 if there is none.
cyw_sdio_transfer(false, CYW_SDIO_FUNC_WLAN, 0, &res, sizeof(res)); // read "the tag"
if ((len[0] | len[1]) == 0 || (len[0] ^ len[1]) != 0xffff || *len <= 4) return 0;
response[0] = res; // copy what we already read, then read the rest
cyw_sdio_transfer(false, CYW_SDIO_FUNC_WLAN, 0, response + 1, *len - sizeof(res));
return (size_t)*len;
}
static size_t cyw_sdio_tx(uint32_t *data, uint16_t len) {
return cyw_sdio_transfer(true, CYW_SDIO_FUNC_WLAN, 0, data, len) ? len: 0;
}
static bool cyw_sdio_init() {
struct mg_tcpip_driver_cyw_data *d = (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
struct mg_tcpip_sdio *s = (struct mg_tcpip_sdio *) d->bus;
uint32_t val = 0;
if (!mg_sdio_init(s)) return false;
// no block transfers on F0. if (!mg_sdio_set_blksz(s, CYW_SDIO_FUNC_BUS, 32)) return false;
if (!mg_sdio_set_blksz(s, CYW_SDIO_FUNC_CHIP, 64)) return false;
if (!mg_sdio_set_blksz(s, CYW_SDIO_FUNC_WLAN, 64)) return false;
// TODO(scaprile): we don't handle SDIO interrupts, study CCCR INTEN and SDIO support (SDIO 6.3, 8)
// Enable chip backplane (F1)
if (!mg_sdio_enable_f(s, CYW_SDIO_FUNC_CHIP)) return false;
// Wait for F1 to be ready
if (!mg_sdio_waitready_f(s, CYW_SDIO_FUNC_CHIP)) return false;
// chip backplane is ready, initialize it
// request ALP (Active Low Power) clock
val = MG_BIT(5) | MG_BIT(3) | MG_BIT(0); // HW_CLKREQ_OFF ALP_REQ FORCE_ALP
cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
// BT-ENABLED DEPENDENCY
unsigned int times = 10;
while (times--) {
if(!cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1)) return false;
if (val & MG_BIT(6)) break; // ALP_AVAIL
mg_delayms(1);
}
if (times == (unsigned int) ~0) return false;
// clear request
val = 0; cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
// Enable WLAN (F2)
if (!mg_sdio_enable_f(s, CYW_SDIO_FUNC_WLAN)) return false;
// Clear pullups. NOTE(): ?
val = 0x00; cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
// we don't handle wake nor OOB interrupts; SEP_INT_CTL is a vendor specific SDIO register
// SDIO interrupts: enable F2 interrupt only
cyw_set_backplane_window(CYW_CHIP_CHIPCOMMON); // set backplane window to start of CHIPCOMMON area
cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
if (val == 43430) val = 4343;
MG_INFO(("WLAN chip is CYW%u%c", val, val == 4343 ? 'W' : ' '));
// Load firmware (code and NVRAM)
if (!cyw_load_firmware(d->fw)) return false;
// Wait for High Throughput (HT) clock ready
times = 50;
while (times--) {
if(!cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1)) return false;
if (val & MG_BIT(7)) break; // HT_AVAIL
mg_delayms(1);
}
if (times == (unsigned int) ~0) return false;
// Wait for WLAN ready
if (!mg_sdio_waitready_f(s, CYW_SDIO_FUNC_WLAN)) return false;
// CHIP DEPENDENCY
// Enable save / restore
// Configure WakeupCtrl, set HT_AVAIL in CLOCK_CSR
if(!cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1)) return false;
val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
#if 0 // TODO(scaprile): Check if this is actually necessary
// Set BRCM_CARDCAP to CMD_NODEC. This is a vendor specific SDIO register
val = MG_BIT(3); cyw_sdio_transfer(true, CYW_SDIO_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
#endif
// Force HT request to chip backplane
val = MG_BIT(1) /* FORCE_HT */; if(!cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1)) return false;
// Enable Keep SDIO On (KSO)
cyw_sdio_transfer(false, CYW_SDIO_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
if (!(val & MG_BIT(0))) {
val |= MG_BIT(0); cyw_sdio_transfer(true, CYW_SDIO_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
}
return true;
}
// clang-format on
static bool cyw_bus_specific_init(void) {
return cyw_sdio_init();
}
static size_t cyw_bus_specific_poll(uint32_t *response) {
return cyw_sdio_poll(response);
}
static size_t cyw_bus_specific_tx(uint32_t *data, uint16_t len) {
return cyw_sdio_tx(data, len);
}
static bool cyw_bus_write(unsigned int f, uint32_t addr, void *data,
uint16_t len) {
if (f == CYW_SDIO_FUNC_CHIP && len == 4) addr |= CYW_CHIP_BCKPLN_ACCSS4B;
return cyw_sdio_transfer(true, f, addr, data, (uint32_t) len);
}
static bool cyw_bus_read(unsigned int f, uint32_t addr, void *data,
uint16_t len) {
return cyw_sdio_transfer(false, f, addr, data, (uint32_t) len);
}
#endif
// Mongoose Wi-Fi API functions
bool mg_wifi_scan(void) {
return cyw_wifi_scan();
}
bool mg_wifi_connect(char *ssid, char *pass) {
return cyw_wifi_connect(ssid, pass);
bool mg_wifi_connect(struct mg_wifi_data *wifi) {
s_ifp->ip = s_ip;
s_ifp->mask = s_mask;
if (s_ifp->ip == 0) s_ifp->enable_dhcp_client = true;
s_ifp->enable_dhcp_server = false;
MG_DEBUG(("Connecting to '%s'", wifi->ssid));
return cyw_wifi_connect(wifi->ssid, wifi->pass);
}
bool mg_wifi_disconnect(void) {
return cyw_wifi_disconnect();
}
bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
return cyw_wifi_ap_start(ssid, pass, channel);
bool mg_wifi_ap_start(struct mg_wifi_data *wifi) {
MG_DEBUG(("Starting AP '%s' (%u)", wifi->apssid, wifi->apchannel));
return cyw_wifi_ap_start(wifi->apssid, wifi->appass, wifi->apchannel);
}
bool mg_wifi_ap_stop(void) {
+19 -26
View File
@@ -1,6 +1,8 @@
#pragma once
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
#if MG_ENABLE_TCPIP && \
((defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW) || \
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO))
struct mg_tcpip_spi_ {
void *spi; // Opaque SPI bus descriptor
@@ -20,35 +22,26 @@ struct mg_tcpip_driver_cyw_firmware {
};
struct mg_tcpip_driver_cyw_data {
struct mg_tcpip_spi_ *spi;
struct mg_wifi_data wifi;
void *bus;
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)
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_); \
#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_cyw; \
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
+19 -11
View File
@@ -1,6 +1,9 @@
#include "net_builtin.h"
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
#if MG_ENABLE_TCPIP && \
(defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10) || \
(defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11) || \
(defined(MG_ENABLE_DRIVER_MCXE) && MG_ENABLE_DRIVER_MCXE)
struct imxrt_enet {
volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3],
ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR,
@@ -26,12 +29,15 @@ struct imxrt_enet {
};
#undef ENET
#if defined(MG_DRIVER_IMXRT_RT11) && MG_DRIVER_IMXRT_RT11
#if defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40424000U)
#define ETH_DESC_CNT 5 // Descriptors count
#else
#elif defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x402D8000U)
#define ETH_DESC_CNT 4 // Descriptors count
#else // MG_ENABLE_DRIVER_MCXE
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40079000U)
#define ETH_DESC_CNT 4 // Descriptor count
#endif
#define ETH_PKT_SIZE 1536 // Max frame size, 64-bit aligned
@@ -42,15 +48,12 @@ struct enet_desc {
uint32_t *buffer; // Data ptr
};
// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
#define MG_64BYTE_ALIGNED __attribute__((aligned((64U))))
// Descriptors: in non-cached area (TODO(scaprile)), (37.5.1.22.2 37.5.1.23.2)
// Buffers: 64-byte aligned (37.3.14)
static volatile struct enet_desc s_rxdesc[ETH_DESC_CNT] MG_64BYTE_ALIGNED;
static volatile struct enet_desc s_txdesc[ETH_DESC_CNT] MG_64BYTE_ALIGNED;
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_64BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_64BYTE_ALIGNED;
static volatile struct enet_desc s_rxdesc[ETH_DESC_CNT] MG_ETH_RAM MG_64BYTE_ALIGNED;
static volatile struct enet_desc s_txdesc[ETH_DESC_CNT] MG_ETH_RAM MG_64BYTE_ALIGNED;
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_64BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_64BYTE_ALIGNED;
static struct mg_tcpip_if *s_ifp; // MIP interface
static uint16_t enet_read_phy(uint8_t addr, uint8_t reg) {
@@ -187,9 +190,14 @@ static bool mg_tcpip_driver_imxrt_poll(struct mg_tcpip_if *ifp, bool s1) {
return up;
}
void ENET_IRQHandler(void);
static uint32_t s_rxno;
#if !defined(MG_ENABLE_DRIVER_MCXE)
void ENET_IRQHandler(void);
void ENET_IRQHandler(void) {
#else
void ENET_Receive_IRQHandler(void);
void ENET_Receive_IRQHandler(void) {
#endif
ENET->EIR = MG_BIT(25); // Ack IRQ
// Frame received, loop
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
+4 -1
View File
@@ -1,6 +1,9 @@
#pragma once
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
#if MG_ENABLE_TCPIP && \
(defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10) || \
(defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11) || \
(defined(MG_ENABLE_DRIVER_MCXE) && MG_ENABLE_DRIVER_MCXE)
struct mg_tcpip_driver_imxrt_data {
// MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
+91
View File
@@ -0,0 +1,91 @@
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_NXP_WIFI) && \
MG_ENABLE_DRIVER_NXP_WIFI
#include "drivers/nxp_wifi.h"
bool __attribute__((weak)) netif_init(struct mg_tcpip_if *ifp) {
(void) ifp;
MG_ERROR(("Please link wifi/port/net contents"));
return false;
}
size_t __attribute__((weak))
netif_tx(const void *bfr, size_t len, struct mg_tcpip_if *ifp) {
(void) bfr;
(void) len;
netif_init(ifp);
return 0;
}
bool __attribute__((weak)) netif_connect(struct mg_wifi_data *wifi) {
(void) wifi;
return netif_init(NULL);
}
bool __attribute__((weak))
netif_poll(struct mg_tcpip_if *ifp, bool s1, mg_tcpip_event_handler_t evcb) {
(void) ifp;
(void) s1;
(void) evcb;
return false;
}
static struct mg_tcpip_if *s_ifp;
static uint32_t s_ip, s_mask;
static void wifi_cb(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
struct mg_wifi_data *wifi =
&((struct mg_tcpip_driver_nxp_wifi_data *) ifp->driver_data)->wifi;
if (wifi->apmode && ev == MG_TCPIP_EV_ST_CHG &&
*(uint8_t *) ev_data == MG_TCPIP_STATE_UP) {
MG_DEBUG(("Access Point started"));
s_ip = ifp->ip, ifp->ip = wifi->apip;
s_mask = ifp->mask, ifp->mask = wifi->apmask;
ifp->enable_dhcp_client = false;
ifp->enable_dhcp_server = true;
}
}
static bool nxp_wifi_init(struct mg_tcpip_if *ifp) {
struct mg_wifi_data *wifi =
&((struct mg_tcpip_driver_nxp_wifi_data *) ifp->driver_data)->wifi;
s_ifp = ifp;
s_ip = ifp->ip;
s_mask = ifp->mask;
ifp->pfn = wifi_cb;
if (!netif_init(ifp)) return false;
if (wifi->apmode) {
return mg_wifi_ap_start(wifi);
} else if (wifi->ssid != NULL && wifi->pass != NULL) {
return mg_wifi_connect(wifi);
}
return true;
}
bool nxp_wifi_poll(struct mg_tcpip_if *ifp, bool s1) {
return netif_poll(ifp, s1, mg_tcpip_call);
}
struct mg_tcpip_driver mg_tcpip_driver_nxp_wifi = {nxp_wifi_init, netif_tx,
NULL, nxp_wifi_poll};
bool mg_wifi_connect(struct mg_wifi_data *wifi) {
s_ifp->ip = s_ip;
s_ifp->mask = s_mask;
if (s_ifp->ip == 0) s_ifp->enable_dhcp_client = true;
s_ifp->enable_dhcp_server = false;
return netif_connect(wifi);
}
bool __attribute__((weak)) mg_wifi_scan(void) {
return netif_init(NULL);
}
bool __attribute__((weak)) mg_wifi_disconnect(void) {
return netif_init(NULL);
}
bool __attribute__((weak)) mg_wifi_ap_start(struct mg_wifi_data *wifi) {
(void) wifi;
return netif_init(NULL);
}
bool __attribute__((weak)) mg_wifi_ap_stop(void) {
return netif_init(NULL);
}
#endif
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#if MG_ENABLE_TCPIP && \
defined(MG_ENABLE_DRIVER_NXP_WIFI) && MG_ENABLE_DRIVER_NXP_WIFI
struct mg_tcpip_driver_nxp_wifi_data {
struct mg_wifi_data wifi;
};
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_nxp_wifi_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_nxp_wifi; \
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: nxp wifi, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
+20 -10
View File
@@ -1,13 +1,15 @@
#include "phy.h"
enum { // ID1 ID2
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
enum { // ID1 ID2
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
MG_PHY_DP83x = 0x2000,
MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
MG_PHY_DP83848 = 0x5ca2, // 2000 5ca2 - TI DP83848I
MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
MG_PHY_RTL8201 = 0x1C // 001c c816 - RTL8201
MG_PHY_RTL8201 = 0x1C, // 001c c816 - RTL8201,
MG_PHY_ICS1894x = 0x15,
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
};
enum {
@@ -23,7 +25,8 @@ enum {
MG_PHY_KSZ8x_REG_PC2R = 31,
MG_PHY_LAN87x_REG_SCSR = 31,
MG_PHY_RTL8201_REG_RMSR = 16, // in page 7
MG_PHY_RTL8201_REG_PAGESEL = 31
MG_PHY_RTL8201_REG_PAGESEL = 31,
MG_PHY_ICS189432_REG_POLL = 17
};
static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
@@ -45,10 +48,11 @@ static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
return "LAN87x";
case MG_PHY_RTL8201:
return "RTL8201";
case MG_PHY_ICS1894x:
return "ICS1894x";
default:
return "unknown";
}
(void) id2;
}
void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
@@ -77,11 +81,13 @@ void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
} else if (id1 == MG_PHY_KSZ8x) {
// Disable isolation (override hw, it doesn't make sense at this point)
phy->write_reg( // #2848, some NXP boards set ISO, even though
phy_addr, MG_PHY_REG_BCR, // docs say they don't
phy->read_reg(phy_addr, MG_PHY_REG_BCR) & (uint16_t) ~MG_BIT(10));
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R, // now do clock stuff
MG_BIT(15) | MG_BIT(8) | MG_BIT(7));
// - #2848, some NXP boards set ISO, even though docs say they don't
phy->write_reg(phy_addr, MG_PHY_REG_BCR,
(uint16_t) (phy->read_reg(phy_addr, MG_PHY_REG_BCR) &
(uint16_t) ~MG_BIT(10)));
// now do clock stuff
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R,
(uint16_t) (MG_BIT(15) | MG_BIT(8) | MG_BIT(7)));
} else if (id1 == MG_PHY_LAN87x) {
// nothing to do
} else if (id1 == MG_PHY_RTL8201) {
@@ -134,6 +140,10 @@ bool mg_phy_up(struct mg_phy *phy, uint8_t phy_addr, bool *full_duplex,
uint16_t bcr = phy->read_reg(phy_addr, MG_PHY_REG_BCR);
*full_duplex = bcr & MG_BIT(8);
*speed = (bcr & MG_BIT(13)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
} else if (id1 == MG_PHY_ICS1894x) {
uint16_t poll_reg = phy->read_reg(phy_addr, MG_PHY_ICS189432_REG_POLL);
*full_duplex = poll_reg & MG_BIT(14);
*speed = (poll_reg & MG_BIT(15)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
}
}
return up;
+45 -21
View File
@@ -6,23 +6,41 @@
#include "pico/stdlib.h"
static struct mg_tcpip_if *s_ifp;
static uint32_t s_ip, s_mask;
static bool s_aplink = false, s_scanning = false;
static bool s_stalink = false, s_connecting = false;
static void wifi_cb(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
struct mg_wifi_data *wifi =
&((struct mg_tcpip_driver_pico_w_data *) ifp->driver_data)->wifi;
if (wifi->apmode && ev == MG_TCPIP_EV_ST_CHG &&
*(uint8_t *) ev_data == MG_TCPIP_STATE_UP) {
MG_DEBUG(("Access Point started"));
s_ip = ifp->ip, ifp->ip = wifi->apip;
s_mask = ifp->mask, ifp->mask = wifi->apmask;
ifp->enable_dhcp_client = false;
ifp->enable_dhcp_server = true;
}
}
static bool mg_tcpip_driver_pico_w_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_pico_w_data *d =
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
struct mg_wifi_data *wifi = &d->wifi;
s_ifp = ifp;
s_ip = ifp->ip;
s_mask = ifp->mask;
ifp->pfn = wifi_cb;
if (cyw43_arch_init() != 0)
return false; // initialize async_context and WiFi chip
if (d->apmode && d->apssid != NULL) {
MG_DEBUG(("Starting AP '%s' (%u)", d->apssid, d->apchannel));
if (!mg_wifi_ap_start(d->apssid, d->appass, d->apchannel)) return false;
if (wifi->apmode && wifi->apssid != NULL) {
if (!mg_wifi_ap_start(wifi)) return false;
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac); // same MAC
} else {
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);
if (wifi->ssid != NULL) {
return mg_wifi_connect(wifi);
} else {
cyw43_arch_disable_sta_mode();
}
@@ -35,35 +53,33 @@ static size_t mg_tcpip_driver_pico_w_tx(const void *buf, size_t len,
struct mg_tcpip_driver_pico_w_data *d =
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
return cyw43_send_ethernet(&cyw43_state,
d->apmode ? CYW43_ITF_AP : CYW43_ITF_STA, len, buf,
false) == 0
d->wifi.apmode ? CYW43_ITF_AP : CYW43_ITF_STA, len,
buf, false) == 0
? len
: 0;
}
static bool s_aplink = false, s_scanning = false;
static bool s_stalink = false, s_connecting = false;
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);
mg_tcpip_call(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);
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;
if (d->wifi.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);
mg_tcpip_call(ifp, MG_TCPIP_EV_WIFI_CONNECT_ERR, &sdkstate);
s_connecting = false;
}
return s_stalink;
@@ -94,7 +110,7 @@ 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 = false;
s_aplink = false;
} else {
s_stalink = false;
// SDK calls this before we check status, don't clear s_connecting here
@@ -134,9 +150,15 @@ bool mg_wifi_scan(void) {
return res;
}
bool mg_wifi_connect(char *ssid, char *pass) {
bool mg_wifi_connect(struct mg_wifi_data *wifi) {
s_ifp->ip = s_ip;
s_ifp->mask = s_mask;
if (s_ifp->ip == 0) s_ifp->enable_dhcp_client = true;
s_ifp->enable_dhcp_server = false;
cyw43_arch_enable_sta_mode();
int res = cyw43_arch_wifi_connect_async(ssid, pass, CYW43_AUTH_WPA2_AES_PSK);
MG_DEBUG(("Connecting to '%s'", wifi->ssid));
int res = cyw43_arch_wifi_connect_async(wifi->ssid, wifi->pass,
CYW43_AUTH_WPA2_AES_PSK);
MG_VERBOSE(("res: %d", res));
if (res == 0) s_connecting = true;
return (res == 0);
@@ -148,9 +170,11 @@ bool mg_wifi_disconnect(void) {
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);
bool mg_wifi_ap_start(struct mg_wifi_data *wifi) {
MG_DEBUG(("Starting AP '%s' (%u)", wifi->apssid, wifi->apchannel));
cyw43_wifi_ap_set_channel(&cyw43_state, wifi->apchannel);
cyw43_arch_enable_ap_mode(wifi->apssid, wifi->appass,
CYW43_AUTH_WPA2_AES_PSK);
return true;
}
+1 -8
View File
@@ -8,14 +8,7 @@
#include "pico/unique_id.h" // keep this include
struct mg_tcpip_driver_pico_w_data {
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
struct mg_wifi_data wifi;
};
#define MG_TCPIP_DRIVER_INIT(mgr) \
+1 -1
View File
@@ -323,6 +323,6 @@ static size_t mg_ppp_rx(void *ethbuf, size_t ethlen, struct mg_tcpip_if *ifp) {
}
struct mg_tcpip_driver mg_tcpip_driver_ppp = {mg_ppp_init, mg_ppp_tx, mg_ppp_rx,
mg_ppp_up};
mg_ppp_poll};
#endif
+17 -12
View File
@@ -1,6 +1,8 @@
#include "net_builtin.h"
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
#if MG_ENABLE_TCPIP && \
(defined(MG_ENABLE_DRIVER_RA6) && MG_ENABLE_DRIVER_RA6) || \
(defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8)
struct ra_etherc {
volatile uint32_t ECMR, RESERVED, RFLR, RESERVED1, ECSR, RESERVED2, ECSIPR,
RESERVED3, PIR, RESERVED4, PSR, RESERVED5[5], RDMLR, RESERVED6[3], IPGR,
@@ -18,27 +20,30 @@ struct ra_edmac {
};
#undef ETHERC
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
#undef EDMAC
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
#undef RASYSC
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
#undef ICU_IELSR
#if defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40354100U)
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40354000U)
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x4000C300U)
#else
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x40006300U)
#endif
#define ETH_PKT_SIZE 1536 // Max frame size, multiple of 32
#define ETH_DESC_CNT 4 // Descriptors count
// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
#define MG_16BYTE_ALIGNED __attribute__((aligned((16U))))
#define MG_32BYTE_ALIGNED __attribute__((aligned((32U))))
// Descriptors: 16-byte aligned
// Buffers: 32-byte aligned (27.3.1)
static volatile uint32_t s_rxdesc[ETH_DESC_CNT][4] MG_16BYTE_ALIGNED;
static volatile uint32_t s_txdesc[ETH_DESC_CNT][4] MG_16BYTE_ALIGNED;
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_32BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_32BYTE_ALIGNED;
static volatile uint32_t s_rxdesc[ETH_DESC_CNT][4] MG_ETH_RAM MG_16BYTE_ALIGNED;
static volatile uint32_t s_txdesc[ETH_DESC_CNT][4] MG_ETH_RAM MG_16BYTE_ALIGNED;
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_32BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_32BYTE_ALIGNED;
static struct mg_tcpip_if *s_ifp; // MIP interface
// fastest is 3 cycles (SUB + BNE) on a 3-stage pipeline or equivalent
+3 -1
View File
@@ -1,6 +1,8 @@
#pragma once
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
#if MG_ENABLE_TCPIP && \
(defined(MG_ENABLE_DRIVER_RA6) && MG_ENABLE_DRIVER_RA6) || \
(defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8)
struct mg_tcpip_driver_ra_data {
// MDC clock "divider". MDC clock is software generated,
+5 -5
View File
@@ -26,17 +26,17 @@ struct ENET_Type {
CHANNEL_TCSR[4], CHANNEL_TCCR[4];
};
#undef ENET
#define ENET ((struct ENET_Type *) 0x40138000)
#define ETH_PKT_SIZE 1536 // Max frame size
#define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 2 // Descriptor size (words)
#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_8BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] 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 uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor
+100 -82
View File
@@ -3,7 +3,35 @@
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
MG_ENABLE_DRIVER_SAME54
#include <sam.h>
struct GMAC_REGS_ {
uint32_t GMAC_NCR, GMAC_NCFGR, GMAC_NSR, GMAC_UR, GMAC_DCFGR, GMAC_TSR,
GMAC_RBQB, GMAC_TBQB, GMAC_RSR, GMAC_ISR, GMAC_IER, GMAC_IDR, GMAC_IMR,
GMAC_MAN, GMAC_RPQ, GMAC_TPQ, GMAC_TPSF, GMAC_RPSF, GMAC_RJFML,
Reserved1[13], GMAC_HRB, GMAC_HRT, GMAC_SAB0, GMAC_SAT0, GMAC_SAB1,
GMAC_SAT1, GMAC_SAB2, GMAC_SAT2, GMAC_SAB3, GMAC_SAT3, GMAC_TIDM[4],
GMAC_WOL, GMAC_IPGS, GMAC_SVLAN, GMAC_TPFCP, GMAC_SAMB1, GMAC_SAMT1,
Reserved2[3], GMAC_NSC, GMAC_SCL, GMAC_SCH, GMAC_EFTSH, GMAC_EFRSH,
GMAC_PEFTSH, GMAC_PEFRSH, Reserved3[2], GMAC_OTLO, GMAC_OTHI, GMAC_FT,
GMAC_BCFT, GMAC_MFT, GMAC_PFT, GMAC_BFT64, GMAC_TBFT127, GMAC_TBFT255,
GMAC_TBFT511, GMAC_TBFT1023, GMAC_TBFT1518, GMAC_GTBFT1518, GMAC_TUR,
GMAC_SCF, GMAC_MCF, GMAC_EC, GMAC_LC, GMAC_DTF, GMAC_CSE, GMAC_ORLO,
GMAC_ORHI, GMAC_FR, GMAC_BCFR, GMAC_MFR, GMAC_PFR, GMAC_BFR64,
GMAC_TBFR127, GMAC_TBFR255, GMAC_TBFR511, GMAC_TBFR1023, GMAC_TBFR1518,
GMAC_TMXBFR, GMAC_UFR, GMAC_OFR, GMAC_JR, GMAC_FCSE, GMAC_LFFE, GMAC_RSE,
GMAC_AE, GMAC_RRE, GMAC_ROE, GMAC_IHCE, GMAC_TCE, GMAC_UCE, Reserved4[2],
GMAC_TISUBN, GMAC_TSH, Reserved5, GMAC_TSSSL, GMAC_TSSN, GMAC_TSL,
GMAC_TN, GMAC_TA, GMAC_TI, GMAC_EFTSL, GMAC_EFTN, GMAC_EFRSL, GMAC_EFRN,
GMAC_PEFTSL, GMAC_PEFTN, GMAC_PEFRSL, GMAC_PEFRN, Reserved6[28],
GMAC_RLPITR, GMAC_RLPITI, GMAC_TLPITR, GMAC_TLPITI;
};
struct GCLK_REGS_ {
uint32_t GCLK_CTRLA_RESERVED, GCLK_SYNCBUSY, Reserved2[6], GCLK_GENCTRL[12],
Reserved3[12], GCLK_PCHCTRL[48];
};
#define GMAC_REGS ((struct GMAC_REGS_ *) 0x42000800)
#define GCLK_REGS ((struct GCLK_REGS_ *) 0x40001c00)
#define ETH_PKT_SIZE 1536 // Max frame size
#define ETH_DESC_CNT 4 // Descriptors count
@@ -17,72 +45,67 @@ 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
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
#define MG_PHYREGBIT_BCR_DUPLEX_MODE MG_BIT(8)
#define MG_PHYREGBIT_BCR_SPEED MG_BIT(13)
#define MG_PHYREGBIT_BSR_LINK_STATUS MG_BIT(2)
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
GMAC_MAN_OP(2) | // Setting the read operation
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
GMAC_MAN_REGA(reg); // Setting the register
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0;
return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value
GMAC_REGS->GMAC_MAN = MG_BIT(30) | // Clause 22
MG_BIT(29) | // Setting the read operation
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
((reg & 0x1f) << 18); // Setting the register
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))) (void) 0;
return GMAC_REGS->GMAC_MAN & 0xffff; // Getting the read value
}
#if 0
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete
GMAC_REGS->GMAC_MAN = MG_BIT(30) |
MG_BIT(28) | // Setting the write operation
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
((reg & 0x1f) << 18) | val; // Setting the register
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2)))
; // Waiting until the write op is complete
}
#endif
int get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
uint32_t get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
return d->mdc_cr;
} else {
// get MCLK from GCLK_GENERATOR 0
uint32_t div = 512;
uint32_t mclk;
if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) {
if (!(GCLK_REGS->GCLK_GENCTRL[0] & MG_BIT(12))) {
div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
if (div == 0) div = 1;
}
switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) {
case GCLK_GENCTRL_SRC_XOSC0_Val:
mclk = 32000000UL; /* 32MHz */
switch (GCLK_REGS->GCLK_GENCTRL[0] & 0xF) {
case 0: // GCLK_GENCTRL_SRC_XOSC0_Val
mclk = 32000000UL; // 32MHz
break;
case GCLK_GENCTRL_SRC_XOSC1_Val:
mclk = 32000000UL; /* 32MHz */
case 1: // GCLK_GENCTRL_SRC_XOSC1_Val
mclk = 32000000UL; // 32MHz
break;
case GCLK_GENCTRL_SRC_OSCULP32K_Val:
mclk = 32000UL;
case 4: // GCLK_GENCTRL_SRC_OSCULP32K_Val
mclk = 32000UL; // 32Khz
break;
case GCLK_GENCTRL_SRC_XOSC32K_Val:
mclk = 32000UL;
case 5: // GCLK_GENCTRL_SRC_XOSC32K_Val
mclk = 32000UL; // 32Khz
break;
case GCLK_GENCTRL_SRC_DFLL_Val:
mclk = 48000000UL; /* 48MHz */
case 6: // GCLK_GENCTRL_SRC_DFLL_Val
mclk = 48000000UL; // 48MHz
break;
case GCLK_GENCTRL_SRC_DPLL0_Val:
mclk = 200000000UL; /* 200MHz */
case 7: // GCLK_GENCTRL_SRC_DPLL0_Val:
mclk = 200000000UL; // 200MHz
break;
case GCLK_GENCTRL_SRC_DPLL1_Val:
mclk = 200000000UL; /* 200MHz */
case 8: // GCLK_GENCTRL_SRC_DPLL1_Val
mclk = 200000000UL; // 200MHz
break;
default:
mclk = 200000000UL; /* 200MHz */
mclk = 200000000UL; // 200MHz
}
mclk /= div;
uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
for (int i = 0; i < 6; i++) {
if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) {
if (mclk / dividers[i] <= 2375000UL) { // 2.5MHz - 5%
return crs[i];
}
}
@@ -96,11 +119,12 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
(struct mg_tcpip_driver_same54_data *) ifp->driver_data;
s_ifp = ifp;
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk;
MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk;
GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO
GMAC_REGS->GMAC_NCFGR = get_clock_rate(d) << 18; // Set MDC divider
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
GMAC_REGS->GMAC_NCR |= MG_BIT(4); // Enable MDC & MDIO
struct mg_phy phy = {eth_read_phy, eth_write_phy};
mg_phy_init(&phy, d->phy_addr, 0);
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
@@ -108,38 +132,33 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
}
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18) // DMA recv buf 1536
| GMAC_DCFGR_RXBMS(GMAC_DCFGR_RXBMS_FULL_Val) |
GMAC_DCFGR_TXPBMS(1); // See #2487
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
s_rxdesc[i][1] = 0; // Clear status
GMAC_REGS->GMAC_DCFGR = (0x18 << 16) | // DMA recv buf 1536
(3 << 8) | // RXBMS
MG_BIT(10); // See #2487
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
s_rxdesc[i][1] = 0; // Clear status
}
s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
GMAC_REGS->SA[0].GMAC_SAB =
GMAC_REGS->GMAC_SAB0 =
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
GMAC_REGS->GMAC_SAT0 = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII
GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk |
GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk;
GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk |
GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk;
GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk |
GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk;
GMAC_REGS->GMAC_UR &= ~MG_BIT(0); // Disable MII, use RMII
GMAC_REGS->GMAC_NCFGR |= MG_BIT(8) | MG_BIT(6) | // MAXFX, MTIHEN
MG_BIT(25) | MG_BIT(4); // EFRHD, CAF
GMAC_REGS->GMAC_TSR = 0x17f; // all transmit statuses
GMAC_REGS->GMAC_RSR = 0xf; // all recv statuses
GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk |
GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk |
GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk |
GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk;
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk;
NVIC_EnableIRQ(GMAC_IRQn);
GMAC_REGS->GMAC_IER = MG_BIT(11) | MG_BIT(10) | // HRESP, ROVR
MG_BIT(7) | MG_BIT(6) | // TCOMP, TFC
MG_BIT(5) | MG_BIT(4) | // RLEX, TUR
MG_BIT(2) | MG_BIT(1); // RXUBR, RCOMP
GMAC_REGS->GMAC_NCR |= MG_BIT(3) | MG_BIT(2); // TXEN, RXEN
return true;
}
@@ -160,8 +179,8 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
s_txdesc[s_txno][1] = status;
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
}
__DSB(); // Ensure descriptors have been written
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission
MG_DSB(); // Ensure descriptors have been written
GMAC_REGS->GMAC_NCR |= MG_BIT(9); // Enable transmission
return len;
}
@@ -172,7 +191,7 @@ static void mg_tcpip_driver_same54_update_hash_table(struct mg_tcpip_if *ifp) {
// 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
GMAC_REGS->GMAC_NCFGR |= MG_BIT(6); // enable multicast hash filtering
(void) ifp;
}
@@ -181,21 +200,22 @@ static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
mg_tcpip_driver_same54_update_hash_table(ifp);
ifp->update_mac_hash_table = false;
}
bool up = false;
if (s1) {
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
uint8_t speed = MG_PHY_SPEED_10M;
bool full_duplex = false;
struct mg_phy phy = {eth_read_phy, eth_write_phy};
up = mg_phy_up(&phy, 0, &full_duplex, &speed);
// 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);
GMAC_REGS->GMAC_NCFGR =
(GMAC_REGS->GMAC_NCFGR & ~(MG_BIT(0) | MG_BIT(1))) | (speed & 1) |
(full_duplex << 1);
}
}
return false;
return up;
}
void GMAC_Handler(void);
@@ -203,8 +223,8 @@ void GMAC_Handler(void) {
uint32_t isr = GMAC_REGS->GMAC_ISR;
uint32_t rsr = GMAC_REGS->GMAC_RSR;
uint32_t tsr = GMAC_REGS->GMAC_TSR;
if (isr & GMAC_ISR_RCOMP_Msk) {
if (rsr & GMAC_ISR_RCOMP_Msk) {
if (isr & MG_BIT(1)) {
if (rsr & MG_BIT(1)) {
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
@@ -215,9 +235,7 @@ void GMAC_Handler(void) {
}
}
if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk |
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
if (tsr != 0) {
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
}
+27 -5
View File
@@ -1,13 +1,35 @@
#pragma once
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
struct mg_tcpip_driver_same54_data {
int mdc_cr;
};
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
MG_ENABLE_DRIVER_SAME54
#ifndef MG_DRIVER_MDC_CR
#define MG_DRIVER_MDC_CR 5
#endif
#ifndef MG_DRIVER_PHY_ADDR
#define MG_DRIVER_PHY_ADDR 0
#endif
struct mg_tcpip_driver_same54_data {
int mdc_cr;
uint8_t phy_addr;
};
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_same54_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
driver_data_.phy_addr = MG_DRIVER_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_same54; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: same54, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
+169
View File
@@ -0,0 +1,169 @@
#include "sdio.h"
#if MG_ENABLE_TCPIP && \
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO)
// SDIO 6.9 Table 6-1 CCCR (Common Card Control Registers)
#define MG_SDIO_CCCR_SDIOREV 0x000
#define MG_SDIO_CCCR_SDREV 0x001
#define MG_SDIO_CCCR_IOEN 0x002
#define MG_SDIO_CCCR_IORDY 0x003
#define MG_SDIO_CCCR_INTEN 0x004
#define MG_SDIO_CCCR_BIC 0x007
#define MG_SDIO_CCCR_CCAP 0x008
#define MG_SDIO_CCCR_CCIS 0x009 // 3 registers
#define MG_SDIO_CCCR_F0BLKSZ 0x010 // 2 registers
#define MG_SDIO_CCCR_HISPD 0x013
// SDIO 6.10 Table 6-3 FBR (Function Basic Registers)
#define MG_SDIO_FBR_FnBLKSZ(n) (((n) &7) * 0x100 + 0x10) // 2 registers
// SDIO 5.1 IO_RW_DIRECT Command (CMD52)
#define MG_SDIO_DATA(x) ((x) &0xFF) // bits 0-7
#define MG_SDIO_ADDR(x) (((x) &0x1FFFF) << 9) // bits 9-25
#define MG_SDIO_FUNC(x) (((x) &3) << 28) // bits 28-30 (30 unused here)
#define MG_SDIO_WR MG_BIT(31)
// SDIO 5.3 IO_RW_EXTENDED Command (CMD53)
#define MG_SDIO_LEN(x) ((x) &0x1FF) // bits 0-8
#define MG_SDIO_OPINC MG_BIT(26)
#define MG_SDIO_BLKMODE MG_BIT(27)
// - Drivers set blocksize, drivers request transfers. Requesting a read
// transfer > blocksize means block transfer will be used.
// - To simplify the use of DMA transfers and avoid intermediate buffers,
// drivers must have room to accomodate a whole block transfer, e.g.: blocksize
// = 64, read 65 => 2 blocks = 128 bytes
// - Transfers of more than 1 byte assume (uint32_t *) data. 1-byte transfers
// use (uint8_t *) data
// - 'len' is the number of _bytes_ to transfer
bool mg_sdio_transfer(struct mg_tcpip_sdio *sdio, bool write, unsigned int f,
uint32_t addr, void *data, uint32_t len) {
uint32_t arg, val = 0;
unsigned int blksz = 64; // TODO(): mg_sdio_set_blksz() stores in an array,
// index on f, skip if 0
if (len == 1) {
arg = (write ? MG_SDIO_WR : 0) | MG_SDIO_FUNC(f) | MG_SDIO_ADDR(addr) |
(write ? MG_SDIO_DATA(*(uint8_t *) data) : 0);
bool res = sdio->txn(sdio, 52, arg, &val); // IO_RW_DIRECT
if (!write) *(uint8_t *) data = (uint8_t) val;
return res;
}
// IO_RW_EXTENDED
arg = (write ? MG_SDIO_WR : 0) | MG_SDIO_OPINC | MG_SDIO_FUNC(f) |
MG_SDIO_ADDR(addr);
if (len > 512 || (blksz != 0 && len > blksz)) { // SDIO 5.3 512 -> len=0
unsigned int blkcnt;
if (blksz == 0) return false; // > 512 requires block size set
blkcnt = (len + blksz - 1) / blksz;
if (blkcnt > 511) return false; // we don't support "infinite" blocks
arg |= MG_SDIO_BLKMODE | MG_SDIO_LEN(blkcnt); // block transfer
len = blksz * blkcnt;
} else {
arg |= MG_SDIO_LEN(len); // multi-byte transfer
}
return sdio->xfr(sdio, write, arg,
(arg & MG_SDIO_BLKMODE) ? (uint16_t) blksz : 0,
(uint32_t *) data, len, &val);
}
bool mg_sdio_set_blksz(struct mg_tcpip_sdio *sdio, unsigned int f,
uint16_t blksz) {
uint32_t val = blksz & 0xff;
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_FBR_FnBLKSZ(f), &val, 1))
return false;
val = (blksz >> 8) & 0x0f; // SDIO 6.10 Table 6-4, max 2048
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_FBR_FnBLKSZ(f) + 1, &val, 1))
return false;
// TODO(): store in an array, index on f. Static 8-element array
MG_VERBOSE(("F%c block size set", (f & 7) + '0'));
return true;
}
// Enable Fx
bool mg_sdio_enable_f(struct mg_tcpip_sdio *sdio, unsigned int f) {
uint8_t bit = 1U << (f & 7), bits;
uint32_t val = 0;
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IOEN, &val, 1))
return false;
bits = (uint8_t) val | bit;
unsigned int times = 501;
while (times--) {
val = bits; /* IOEf */
;
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_IOEN, &val, 1))
return false;
mg_delayms(1);
val = 0;
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IOEN, &val, 1))
return false;
if (val & bit) break;
}
if (times == (unsigned int) ~0) return false;
MG_VERBOSE(("F%c enabled", (f & 7) + '0'));
return true;
}
// Wait for Fx to be ready
bool mg_sdio_waitready_f(struct mg_tcpip_sdio *sdio, unsigned int f) {
uint8_t bit = 1U << (f & 7);
unsigned int times = 501;
while (times--) {
uint32_t val;
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IORDY, &val, 1))
return false;
if (val & bit) break; // IORf
mg_delayms(1);
}
if (times == (unsigned int) ~0) return false;
MG_VERBOSE(("F%c ready", (f & 7) + '0'));
return true;
}
// SDIO 6.14 Bus State Diagram
bool mg_sdio_init(struct mg_tcpip_sdio *sdio) {
uint32_t val = 0;
if (!sdio->txn(sdio, 0, 0, NULL)) return false; // GO_IDLE_STATE
sdio->txn(sdio, 5, 0, &val); // IO_SEND_OP_COND, no CRC
MG_VERBOSE(("IO Functions: %u, Memory: %c", 1 + ((val >> 28) & 7),
(val & MG_BIT(27)) ? 'Y' : 'N'));
if (!sdio->txn(sdio, 3, 0, &val)) return false; // SEND_RELATIVE_ADDR
val = ((uint32_t) val) >> 16; // RCA
if (!sdio->txn(sdio, 7, val << 16, &val))
return false; // SELECT/DESELECT_CARD
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_SDIOREV, &val, 1);
MG_DEBUG(("CCCR: %u.%u, SDIO: %u.%u", 1 + ((val >> 2) & 3), (val >> 0) & 3,
1 + ((val >> 6) & 3), (val >> 4) & 3));
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_SDREV, &val, 1);
MG_VERBOSE(("SD: %u.%u", 1 + ((val >> 2) & 3), (val >> 0) & 3));
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_BIC, &val, 1);
MG_SET_BITS(val, 3,
MG_BIT(7) | MG_BIT(1)); // SDIO 6.9 Tables 6-1 6-2, 4-bit bus
mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_BIC, &val, 1);
// All Full-Speed SDIO cards support a 4-bit bus. Skip for Low-Speed SDIO
// cards, we don't provide separate low-level functions for width and speed
sdio->cfg(sdio, 0); // set DS;
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_HISPD, &val, 1))
return false;
if (val & MG_BIT(0) /* SHS */) {
val = MG_BIT(1); /* EHS */
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_HISPD, &val, 1))
return false;
sdio->cfg(sdio, 1); // set HS;
MG_VERBOSE(("Bus set to 4-bit @50MHz"));
} else {
MG_VERBOSE(("Bus set to 4-bit @25MHz"));
}
return true;
}
// - 6.11 Card Information Structure (CIS): 0x0001000-0x017FF; for card common
// and all functions
// - 16.5 SDIO Card Metaformat
// - 16.7.2 CISTPL_FUNCE (0x22): Function Extension Tuple, provides standard
// information about the card (common) and each individual function. One
// CISTPL_FUNCE in each function’s CIS, immediately following the CISTPL_FUNCID
// tuple
// - 16.7.3 CISTPL_FUNCE Tuple for Function 0 (common)
// - 16.7.4 CISTPL_FUNCE Tuple for Function 1-7
#endif
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#if MG_ENABLE_TCPIP && \
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO)
// Specific chip/card driver --> SDIO driver --> HAL --> SDIO hw controller
// API with HAL for hardware controller
// - Provide a function to init the controller (external)
// - Provide these functions:
struct mg_tcpip_sdio {
void *sdio; // Opaque SDIO bus descriptor
void (*cfg)(void *, uint8_t); // select operating parameters
// SDIO transaction: send cmd with a possible 1-byte read or write
bool (*txn)(void *, uint8_t cmd, uint32_t arg, uint32_t *r);
// SDIO extended transaction: write or read len bytes, using blksz blocks
bool (*xfr)(void *, bool write, uint32_t arg, uint16_t blksz, uint32_t *,
uint32_t len, uint32_t *r);
};
// API with driver (e.g.: cyw.c)
// Once the hardware controller has been initialized:
// - Init card: selects the card, sets F0 block size, sets bus width and speed
bool mg_sdio_init(struct mg_tcpip_sdio *sdio);
// - Enable other possible functions (F1 to F7)
bool mg_sdio_enable_f(struct mg_tcpip_sdio *sdio, unsigned int f);
// - Wait for them to be ready
bool mg_sdio_waitready_f(struct mg_tcpip_sdio *sdio, unsigned int f);
// - Set their transfer block length
bool mg_sdio_set_blksz(struct mg_tcpip_sdio *sdio, unsigned int f,
uint16_t blksz);
// - Transfer data to/from a function (abstracts from transaction type)
// - Requesting a read transfer > blocksize means block transfer will be used.
// - Drivers must have room to accomodate a whole block transfer, see sdio.c
// - Transfers of > 1 byte --> (uint32_t *) data. 1-byte --> (uint8_t *) data
bool mg_sdio_transfer(struct mg_tcpip_sdio *sdio, bool write, unsigned int f,
uint32_t addr, void *data, uint32_t len);
#endif
+4 -4
View File
@@ -22,10 +22,10 @@ struct stm32f_eth {
#define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 4 // Descriptor size (words)
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM; // RX descriptors
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM; // TX descriptors
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM; // RX ethernet buffers
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM; // TX ethernet buffers
static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor
+7
View File
@@ -28,6 +28,12 @@ struct mg_tcpip_driver_stm32f_data {
#define MG_DRIVER_MDC_CR 4
#endif
#if MG_ARCH == MG_ARCH_CUBE
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH_IRQn)
#else
#define MG_ENABLE_ETH_IRQ()
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_stm32f_data driver_data_; \
@@ -40,6 +46,7 @@ struct mg_tcpip_driver_stm32f_data {
mif_.driver = &mg_tcpip_driver_stm32f; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
MG_ENABLE_ETH_IRQ(); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: stm32f, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
+19 -11
View File
@@ -1,8 +1,9 @@
#include "net_builtin.h"
#if MG_ENABLE_TCPIP && (MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN)
#if MG_ENABLE_TCPIP && (MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN || \
MG_ENABLE_DRIVER_STM32N)
// STM32H: vendor modded single-queue Synopsys v4.2
// MCXNx4x: dual-queue Synopsys v5.2 with no hash table option
// STM32N, MCXNx4x: dual-queue Synopsys v5.2 with no hash table option
// RT1170 ENET_QOS: quad-queue Synopsys v5.1
struct synopsys_enet_qos {
volatile uint32_t MACCR, MACECR, MACPFR, MACWTR, MACHT0R, MACHT1R,
@@ -41,17 +42,19 @@ struct synopsys_enet_qos {
0x8000UL))
#elif MG_ENABLE_DRIVER_MCXN
#define ETH ((struct synopsys_enet_qos *) (uintptr_t) 0x40100000UL)
#elif MG_ENABLE_DRIVER_STM32N
#define ETH ((struct synopsys_enet_qos *) (uintptr_t) 0x48036000UL)
#endif
#define ETH_PKT_SIZE 1540 // Max frame size
#define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 4 // Descriptor size (words)
static volatile uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
static volatile uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers
static struct mg_tcpip_if *s_ifp; // MIP interface
static volatile uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
static volatile uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_8BYTE_ALIGNED;
static struct mg_tcpip_if *s_ifp; // MIP interface
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
ETH->MACMDIOAR &= (0xF << 8);
@@ -77,12 +80,14 @@ static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
uint8_t phy_conf = d == NULL ? MG_PHY_CLOCKS_MAC : d->phy_conf;
// Init RX descriptors
memset((char *) s_rxdesc, 0, sizeof(s_rxdesc)); // manual init
for (int i = 0; i < ETH_DESC_CNT; i++) {
s_rxdesc[i][0] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
s_rxdesc[i][3] = MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
}
// Init TX descriptors
memset((char *) s_txdesc, 0, sizeof(s_txdesc)); // manual init
for (int i = 0; i < ETH_DESC_CNT; i++) {
s_txdesc[i][0] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
}
@@ -102,7 +107,7 @@ 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->MACIER = 0; // Do not enable additional irq sources (reset value)
ETH->MACTFCR = MG_BIT(7); // Disable zero-quanta pause
#if !MG_ENABLE_DRIVER_MCXN
#if MG_ENABLE_DRIVER_STM32H
ETH->MACPFR = MG_BIT(10); // Perfect filtering
#endif
struct mg_phy phy = {eth_read_phy, eth_write_phy};
@@ -171,7 +176,7 @@ static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
}
static void mg_tcpip_driver_stm32h_update_hash_table(struct mg_tcpip_if *ifp) {
#if MG_ENABLE_DRIVER_MCXN
#if MG_ENABLE_DRIVER_MCXN || MG_ENABLE_DRIVER_STM32N
ETH->MACPFR = MG_BIT(4); // Pass Multicast (pass all multicast frames)
#else
// TODO(): read database, rebuild hash table
@@ -182,7 +187,7 @@ static void mg_tcpip_driver_stm32h_update_hash_table(struct mg_tcpip_if *ifp) {
ETH->MACA1HR = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
ETH->MACA1HR |= MG_BIT(31); // AE
#endif
(void) ifp;
(void) ifp;
}
static bool mg_tcpip_driver_stm32h_poll(struct mg_tcpip_if *ifp, bool s1) {
@@ -216,9 +221,12 @@ static uint32_t s_rxno;
#if MG_ENABLE_DRIVER_MCXN
void ETHERNET_IRQHandler(void);
void ETHERNET_IRQHandler(void) {
#else
#elif MG_ENABLE_DRIVER_STM32H
void ETH_IRQHandler(void);
void ETH_IRQHandler(void) {
#else
void ETH1_IRQHandler(void);
void ETH1_IRQHandler(void) {
#endif
if (ETH->DMACSR & MG_BIT(6)) { // Frame received, loop
ETH->DMACSR = MG_BIT(15) | MG_BIT(6); // Clear flag
+24 -1
View File
@@ -7,7 +7,10 @@
#if !defined(MG_ENABLE_DRIVER_MCXN)
#define MG_ENABLE_DRIVER_MCXN 0
#endif
#if MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN
#if !defined(MG_ENABLE_DRIVER_STM32N)
#define MG_ENABLE_DRIVER_STM32N 0
#endif
#if MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN || MG_ENABLE_DRIVER_STM32N
struct mg_tcpip_driver_stm32h_data {
// MDC clock divider. MDC clock is derived from HCLK, must not exceed 2.5MHz
@@ -40,6 +43,24 @@ struct mg_tcpip_driver_stm32h_data {
#define MG_DRIVER_MDC_CR 4
#endif
#if MG_ENABLE_DRIVER_STM32H && MG_ARCH == MG_ARCH_CUBE
#define MG_ENABLE_ETH_IRQ() NVIC_EnableIRQ(ETH_IRQn)
#else
#define MG_ENABLE_ETH_IRQ()
#endif
#if MG_ENABLE_IPV6
#define MG_IPV6_INIT(mif) \
do { \
memcpy(mif.ip6ll, (uint8_t[16]) MG_TCPIP_IPV6_LINKLOCAL, 16); \
memcpy(mif.ip6, (uint8_t[16]) MG_TCPIP_GLOBAL, 16); \
memcpy(mif.gw6, (uint8_t[16]) MG_TCPIP_GW6, 16); \
mif.prefix_len = MG_TCPIP_PREFIX_LEN; \
} while(0)
#else
#define MG_IPV6_INIT(mif)
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_stm32h_data driver_data_; \
@@ -53,7 +74,9 @@ struct mg_tcpip_driver_stm32h_data {
mif_.driver = &mg_tcpip_driver_stm32h; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
MG_IPV6_INIT(mif_); \
mg_tcpip_init(mgr, &mif_); \
MG_ENABLE_ETH_IRQ(); \
MG_INFO(("Driver: stm32h, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
+7 -6
View File
@@ -111,11 +111,11 @@ static int guess_mdc_cr(void) {
uint8_t crs[] = {2, 3, 0, 1}; // EMAC->MACMIIAR::CR values
uint8_t div[] = {16, 26, 42, 62}; // Respective HCLK dividers
uint32_t sysclk = get_sysclk(); // Guess system SYSCLK
int result = -1; // Invalid CR value
int i, result = -1; // Invalid CR value
if (sysclk < 25000000) {
MG_ERROR(("SYSCLK too low"));
} else {
for (int i = 0; i < 4; i++) {
for (i = 0; i < 4; i++) {
if (sysclk / div[i] <= 2375000UL /* 2.5MHz - 5% */) {
result = crs[i];
break;
@@ -130,10 +130,11 @@ static int guess_mdc_cr(void) {
static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
struct mg_tcpip_driver_tm4c_data *d =
(struct mg_tcpip_driver_tm4c_data *) ifp->driver_data;
int i;
s_ifp = ifp;
// Init RX descriptors
for (int i = 0; i < ETH_DESC_CNT; i++) {
for (i = 0; i < ETH_DESC_CNT; i++) {
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][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
@@ -143,7 +144,7 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
}
// Init TX descriptors
for (int i = 0; i < ETH_DESC_CNT; i++) {
for (i = 0; i < ETH_DESC_CNT; i++) {
s_txdesc[i][2] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
s_txdesc[i][3] =
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
@@ -204,7 +205,6 @@ static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
EMAC->EMACDMARIS = MG_BIT(2) | MG_BIT(5); // Clear any prior TU/UNF
EMAC->EMACTXPOLLD = 0; // and resume
return len;
(void) ifp;
}
static void mg_tcpip_driver_tm4c_update_hash_table(struct mg_tcpip_if *ifp) {
@@ -245,9 +245,10 @@ static bool mg_tcpip_driver_tm4c_poll(struct mg_tcpip_if *ifp, bool s1) {
void EMAC0_IRQHandler(void);
static uint32_t s_rxno;
void EMAC0_IRQHandler(void) {
int i;
if (EMAC->EMACDMARIS & MG_BIT(6)) { // Frame received, loop
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 (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(8) | MG_BIT(9))) ==
(MG_BIT(8) | MG_BIT(9))) &&
+4 -10
View File
@@ -35,18 +35,12 @@ struct ETH_GLOBAL_TypeDef {
#define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 4 // Descriptor size (words)
#ifndef ETH_RAM_SECTION
// if no section is specified, then the data will be placed in the default
// bss section
#define ETH_RAM_SECTION
#endif
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_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM;
static uint32_t s_rxdesc[ETH_DESC_CNT]
[ETH_DS] ETH_RAM_SECTION; // RX descriptors
[ETH_DS] MG_ETH_RAM; // RX descriptors
static uint32_t s_txdesc[ETH_DESC_CNT]
[ETH_DS] ETH_RAM_SECTION; // TX descriptors
[ETH_DS] MG_ETH_RAM; // TX descriptors
static uint8_t s_txno; // Current TX descriptor
static uint8_t s_rxno; // Current RX descriptor
+6 -9
View File
@@ -59,15 +59,12 @@ struct ETH_Type {
#define ETH_DESC_CNT 4 // Descriptors count
#define ETH_DS 2 // Descriptor size (words)
// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
static uint8_t s_rxbuf[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_txdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
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_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM;
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM;
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
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
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
+7 -6
View File
@@ -1,14 +1,15 @@
#include "fs.h"
#include "printf.h"
#include "str.h"
#include "util.h"
struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
struct mg_fd *fd = (struct mg_fd *) calloc(1, sizeof(*fd));
struct mg_fd *fd = (struct mg_fd *) mg_calloc(1, sizeof(*fd));
if (fd != NULL) {
fd->fd = fs->op(path, flags);
fd->fs = fs;
if (fd->fd == NULL) {
free(fd);
mg_free(fd);
fd = NULL;
}
}
@@ -18,7 +19,7 @@ struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
void mg_fs_close(struct mg_fd *fd) {
if (fd != NULL) {
fd->fs->cl(fd->fd);
free(fd);
mg_free(fd);
}
}
@@ -27,10 +28,10 @@ struct mg_str mg_file_read(struct mg_fs *fs, const char *path) {
void *fp;
fs->st(path, &result.len, NULL);
if ((fp = fs->op(path, MG_FS_READ)) != NULL) {
result.buf = (char *) calloc(1, result.len + 1);
result.buf = (char *) mg_calloc(1, result.len + 1);
if (result.buf != NULL &&
fs->rd(fp, (void *) result.buf, result.len) != result.len) {
free((void *) result.buf);
mg_free((void *) result.buf);
result.buf = NULL;
}
fs->cl(fp);
@@ -66,7 +67,7 @@ bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...) {
data = mg_vmprintf(fmt, &ap);
va_end(ap);
result = mg_file_write(fs, path, data, strlen(data));
free(data);
mg_free(data);
return result;
}
+2 -2
View File
@@ -74,7 +74,7 @@ static void *ff_open(const char *path, int flags) {
if (flags & MG_FS_WRITE) mode |= FA_WRITE | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
if (f_open(&f, path, mode) == 0) {
FIL *fp;
if ((fp = calloc(1, sizeof(*fp))) != NULL) {
if ((fp = mg_calloc(1, sizeof(*fp))) != NULL) {
memcpy(fp, &f, sizeof(*fp));
return fp;
}
@@ -85,7 +85,7 @@ static void *ff_open(const char *path, int flags) {
static void ff_close(void *fp) {
if (fp != NULL) {
f_close((FIL *) fp);
free(fp);
mg_free(fp);
}
}
+3 -2
View File
@@ -1,6 +1,7 @@
#include "fs.h"
#include "printf.h"
#include "str.h"
#include "util.h"
struct packed_file {
const char *data;
@@ -72,7 +73,7 @@ static void *packed_open(const char *path, int flags) {
struct packed_file *fp = NULL;
if (data == NULL) return NULL;
if (flags & MG_FS_WRITE) return NULL;
if ((fp = (struct packed_file *) calloc(1, sizeof(*fp))) != NULL) {
if ((fp = (struct packed_file *) mg_calloc(1, sizeof(*fp))) != NULL) {
fp->size = size;
fp->data = data;
}
@@ -80,7 +81,7 @@ static void *packed_open(const char *path, int flags) {
}
static void packed_close(void *fp) {
if (fp != NULL) free(fp);
if (fp != NULL) mg_free(fp);
}
static size_t packed_read(void *fd, void *buf, size_t len) {
+3 -3
View File
@@ -99,7 +99,7 @@ DIR *opendir(const char *name) {
if (name == NULL) {
SetLastError(ERROR_BAD_ARGUMENTS);
} else if ((d = (DIR *) calloc(1, sizeof(*d))) == NULL) {
} else if ((d = (DIR *) mg_calloc(1, sizeof(*d))) == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
} else {
to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
@@ -109,7 +109,7 @@ DIR *opendir(const char *name) {
d->handle = FindFirstFileW(wpath, &d->info);
d->result.d_name[0] = '\0';
} else {
free(d);
mg_free(d);
d = NULL;
}
}
@@ -121,7 +121,7 @@ int closedir(DIR *d) {
if (d != NULL) {
if (d->handle != INVALID_HANDLE_VALUE)
result = FindClose(d->handle) ? 0 : -1;
free(d);
mg_free(d);
} else {
result = -1;
SetLastError(ERROR_BAD_ARGUMENTS);
+19 -51
View File
@@ -216,7 +216,7 @@ static bool vcb(uint8_t c) {
static size_t clen(const char *s, const char *end) {
const unsigned char *u = (unsigned char *) s, c = *u;
long n = (long) (end - s);
if (c > ' ' && c < '~') return 1; // Usual ascii printed char
if (c > ' ' && c <= '~') return 1; // Usual ascii printed char
if ((c & 0xe0) == 0xc0 && n > 1 && vcb(u[1])) return 2; // 2-byte UTF8
if ((c & 0xf0) == 0xe0 && n > 2 && vcb(u[1]) && vcb(u[2])) return 3;
if ((c & 0xf8) == 0xf0 && n > 3 && vcb(u[1]) && vcb(u[2]) && vcb(u[3]))
@@ -280,17 +280,17 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
hm->uri.buf = (char *) s;
while (s < end && (n = clen(s, end)) > 0) s += n, hm->uri.len += n;
while (s < end && s[0] == ' ') s++; // Skip spaces
is_response = hm->method.len > 5 &&
(mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
is_response =
hm->method.len > 5 && (mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
if ((s = skiptorn(s, end, &hm->proto)) == NULL) return false;
// If we're given a version, check that it is HTTP/x.x
version_prefix_valid = hm->proto.len > 5 &&
(mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
version_prefix_valid =
hm->proto.len > 5 && (mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
if (!is_response && hm->proto.len > 0 &&
(!version_prefix_valid || hm->proto.len != 8 ||
(hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
(hm->proto.buf[6] != '.') ||
(hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
(!version_prefix_valid || hm->proto.len != 8 ||
(hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
(hm->proto.buf[6] != '.') ||
(hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
return -1;
}
@@ -346,14 +346,14 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
va_list *ap) {
size_t len = c->send.len;
mg_send(c, " \r\n", 10);
if (!mg_send(c, " \r\n", 10)) mg_error(c, "OOM");
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
if (c->send.len >= len + 10) {
mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10);
c->send.buf[len + 8] = '\r';
if (c->send.len == len + 10) c->is_resp = 0; // Last chunk, reset marker
}
mg_send(c, "\r\n", 2);
if (!mg_send(c, "\r\n", 2)) mg_error(c, "OOM");
}
void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
@@ -365,8 +365,7 @@ void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
mg_printf(c, "%lx\r\n", (unsigned long) len);
mg_send(c, buf, len);
mg_send(c, "\r\n", 2);
if (!mg_send(c, buf, len) || !mg_send(c, "\r\n", 2)) mg_error(c, "OOM");
if (len == 0) c->is_resp = 0;
}
@@ -589,13 +588,11 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
// If a browser sends us "Accept-Encoding: gzip", try to open .gz first
struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
if (ae != NULL) {
char *ae_ = mg_mprintf("%.*s", ae->len, ae->buf);
if (ae_ != NULL && strstr(ae_, "gzip") != NULL) {
if (mg_match(*ae, mg_str("*gzip*"), NULL)) {
mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
fd = mg_fs_open(fs, tmp, MG_FS_READ);
if (fd != NULL) gzip = true, path = tmp;
}
free(ae_);
}
// No luck opening .gz? Open what we've told to open
if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
@@ -686,7 +683,7 @@ static void printdirentry(const char *name, void *userdata) {
sizeof(path)) {
MG_ERROR(("%s truncated", name));
} else if ((flags = fs->st(path, &size, &t)) == 0) {
MG_ERROR(("%lu stat(%s): %d", d->c->id, path, errno));
MG_ERROR(("%lu stat(%s)", d->c->id, path));
} else {
const char *slash = flags & MG_FS_DIR ? "/" : "";
if (flags & MG_FS_DIR) {
@@ -977,7 +974,7 @@ long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
mg_http_reply(c, 400, "", "%s: offset mismatch", path);
res = -5;
} else if ((fd = mg_fs_open(fs, path, MG_FS_WRITE)) == NULL) {
mg_http_reply(c, 400, "", "open(%s): %d", path, errno);
mg_http_reply(c, 400, "", "open(%s)", path);
res = -6;
} else {
res = offset + (long) fs->wr(fd->fd, hm->body.buf, hm->body.len);
@@ -1042,7 +1039,7 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
c->pfn = NULL;
return;
}
if (ev == MG_EV_CLOSE) { // If client did not set Content-Length
if (ev == MG_EV_CLOSE) { // If client did not set Content-Length
hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG
hm.body.len = hm.message.len - (size_t) (hm.body.buf - hm.message.buf);
}
@@ -1073,7 +1070,8 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
}
if (require_content_len) {
if (!c->is_client) mg_http_reply(c, 411, "", "");
MG_ERROR(("Content length missing from %s", is_response ? "response" : "request"));
MG_ERROR(("Content length missing from %s",
is_response ? "response" : "request"));
}
}
@@ -1120,39 +1118,9 @@ static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
(void) ev_data;
}
static void mg_hfn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/quit"), NULL)) {
mg_http_reply(c, 200, "", "ok\n");
c->is_draining = 1;
c->data[0] = 'X';
} else if (mg_match(hm->uri, mg_str("/debug"), NULL)) {
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);
} else {
mg_http_reply(c, 200, "", "hi\n");
}
} else if (ev == MG_EV_CLOSE) {
if (c->data[0] == 'X') *(bool *) c->fn_data = true;
}
}
void mg_hello(const char *url) {
struct mg_mgr mgr;
bool done = false;
mg_mgr_init(&mgr);
if (mg_http_listen(&mgr, url, mg_hfn, &done) == NULL) done = true;
while (done == false) mg_mgr_poll(&mgr, 100);
mg_mgr_free(&mgr);
}
struct mg_connection *mg_http_connect(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data) {
struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
if (c != NULL) c->pfn = http_cb;
return c;
return mg_connect_svc(mgr, url, fn, fn_data, http_cb, NULL);
}
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
-2
View File
@@ -40,7 +40,6 @@ int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...);
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
void mg_http_delete_chunk(struct mg_connection *c, struct mg_http_message *hm);
struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data);
struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
@@ -63,4 +62,3 @@ void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
int mg_http_status(const struct mg_http_message *hm);
void mg_hello(const char *url);
+10 -10
View File
@@ -1,5 +1,5 @@
#include "arch.h"
#include "iobuf.h"
#include "arch.h"
#include "log.h"
#include "util.h"
@@ -7,34 +7,34 @@ static size_t roundup(size_t size, size_t align) {
return align == 0 ? size : (size + align - 1) / align * align;
}
int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
int ok = 1;
bool mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
bool ok = true;
new_size = roundup(new_size, io->align);
if (new_size == 0) {
mg_bzero(io->buf, io->size);
free(io->buf);
mg_free(io->buf);
io->buf = NULL;
io->len = io->size = 0;
} else if (new_size != io->size) {
// NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
// porting to some obscure platforms like FreeRTOS
void *p = calloc(1, new_size);
// NOTE(lsm): do not use realloc here. Use mg_calloc/mg_free only
void *p = mg_calloc(1, new_size);
if (p != NULL) {
size_t len = new_size < io->len ? new_size : io->len;
if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
mg_bzero(io->buf, io->size);
free(io->buf);
mg_free(io->buf);
io->buf = (unsigned char *) p;
io->size = new_size;
io->len = len;
} else {
ok = 0;
ok = false;
MG_ERROR(("%lld->%lld", (uint64_t) io->size, (uint64_t) new_size));
}
}
return ok;
}
int mg_iobuf_init(struct mg_iobuf *io, size_t size, size_t align) {
bool mg_iobuf_init(struct mg_iobuf *io, size_t size, size_t align) {
io->buf = NULL;
io->align = align;
io->size = io->len = 0;
+2 -2
View File
@@ -9,8 +9,8 @@ struct mg_iobuf {
size_t align; // Alignment during allocation
};
int mg_iobuf_init(struct mg_iobuf *, size_t, size_t);
int mg_iobuf_resize(struct mg_iobuf *, size_t);
bool mg_iobuf_init(struct mg_iobuf *, size_t, size_t);
bool mg_iobuf_resize(struct mg_iobuf *, size_t);
void mg_iobuf_free(struct mg_iobuf *);
size_t mg_iobuf_add(struct mg_iobuf *, size_t, const void *, size_t);
size_t mg_iobuf_del(struct mg_iobuf *, size_t ofs, size_t len);
+5 -4
View File
@@ -1,6 +1,7 @@
#include "json.h"
#include "base64.h"
#include "fmt.h"
#include "util.h"
static const char *escapeseq(int esc) {
return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
@@ -320,10 +321,10 @@ char *mg_json_get_str(struct mg_str json, const char *path) {
char *result = NULL;
int len = 0, off = mg_json_get(json, path, &len);
if (off >= 0 && len > 1 && json.buf[off] == '"') {
if ((result = (char *) calloc(1, (size_t) len)) != NULL &&
if ((result = (char *) mg_calloc(1, (size_t) len)) != NULL &&
!mg_json_unescape(mg_str_n(json.buf + off + 1, (size_t) (len - 2)),
result, (size_t) len)) {
free(result);
mg_free(result);
result = NULL;
}
}
@@ -334,7 +335,7 @@ char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) {
char *result = NULL;
int len = 0, off = mg_json_get(json, path, &len);
if (off >= 0 && json.buf[off] == '"' && len > 1 &&
(result = (char *) calloc(1, (size_t) len)) != NULL) {
(result = (char *) mg_calloc(1, (size_t) len)) != NULL) {
size_t k = mg_base64_decode(json.buf + off + 1, (size_t) (len - 2), result,
(size_t) len);
if (slen != NULL) *slen = (int) k;
@@ -346,7 +347,7 @@ char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) {
char *result = NULL;
int len = 0, off = mg_json_get(json, path, &len);
if (off >= 0 && json.buf[off] == '"' && len > 1 &&
(result = (char *) calloc(1, (size_t) len / 2)) != NULL) {
(result = (char *) mg_calloc(1, (size_t) len / 2)) != NULL) {
int i;
for (i = 0; i < len - 2; i += 2) {
mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, &result[i >> 1],
+1 -1
View File
@@ -3,7 +3,7 @@
#include "str.h"
#include "util.h"
int mg_log_level = MG_LL_INFO;
int mg_log_level = MG_LL_DEBUG;
static mg_pfn_t s_log_func = mg_pfn_stdout;
static void *s_log_func_param = NULL;
+111 -69
View File
@@ -46,8 +46,8 @@ static const struct mg_mqtt_pmap s_prop_map[] = {
{MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE, MQTT_PROP_TYPE_BYTE},
{MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE, MQTT_PROP_TYPE_BYTE}};
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
uint32_t len) {
static bool mqtt_send_header(struct mg_connection *c, uint8_t cmd,
uint8_t flags, uint32_t len) {
uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
buf[0] = (uint8_t) ((cmd << 4) | flags);
do {
@@ -56,15 +56,20 @@ void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
if (len > 0) *vlen |= 0x80;
vlen++;
} while (len > 0 && vlen < &buf[sizeof(buf)]);
mg_send(c, buf, (size_t) (vlen - buf));
return mg_send(c, buf, (size_t) (vlen - buf));
}
static void mg_send_u16(struct mg_connection *c, uint16_t value) {
mg_send(c, &value, sizeof(value));
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
uint32_t len) {
if (!mqtt_send_header(c, cmd, flags, len)) mg_error(c, "OOM");
}
static void mg_send_u32(struct mg_connection *c, uint32_t value) {
mg_send(c, &value, sizeof(value));
static bool mg_send_u16(struct mg_connection *c, uint16_t value) {
return mg_send(c, &value, sizeof(value));
}
static bool mg_send_u32(struct mg_connection *c, uint32_t value) {
return mg_send(c, &value, sizeof(value));
}
static uint8_t varint_size(size_t length) {
@@ -157,46 +162,50 @@ static size_t get_props_size(struct mg_mqtt_prop *props, size_t count) {
return size;
}
static void mg_send_mqtt_properties(struct mg_connection *c,
static bool mg_send_mqtt_properties(struct mg_connection *c,
struct mg_mqtt_prop *props, size_t nprops) {
size_t total_size = get_properties_length(props, nprops);
uint8_t buf_v[4] = {0, 0, 0, 0};
uint8_t buf[4] = {0, 0, 0, 0};
size_t i, len = encode_varint(buf, total_size);
mg_send(c, buf, (size_t) len);
if (!mg_send(c, buf, (size_t) len)) return false;
for (i = 0; i < nprops; i++) {
mg_send(c, &props[i].id, sizeof(props[i].id));
if (!mg_send(c, &props[i].id, sizeof(props[i].id))) return false;
switch (mqtt_prop_type_by_id(props[i].id)) {
case MQTT_PROP_TYPE_STRING_PAIR:
mg_send_u16(c, mg_htons((uint16_t) props[i].key.len));
mg_send(c, props[i].key.buf, props[i].key.len);
mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
mg_send(c, props[i].val.buf, props[i].val.len);
if (!mg_send_u16(c, mg_htons((uint16_t) props[i].key.len)) ||
!mg_send(c, props[i].key.buf, props[i].key.len) ||
!mg_send_u16(c, mg_htons((uint16_t) props[i].val.len)) ||
!mg_send(c, props[i].val.buf, props[i].val.len))
return false;
break;
case MQTT_PROP_TYPE_BYTE:
mg_send(c, &props[i].iv, sizeof(uint8_t));
if (!mg_send(c, &props[i].iv, sizeof(uint8_t))) return false;
break;
case MQTT_PROP_TYPE_SHORT:
mg_send_u16(c, mg_htons((uint16_t) props[i].iv));
if (!mg_send_u16(c, mg_htons((uint16_t) props[i].iv))) return false;
break;
case MQTT_PROP_TYPE_INT:
mg_send_u32(c, mg_htonl((uint32_t) props[i].iv));
if (!mg_send_u32(c, mg_htonl((uint32_t) props[i].iv))) return false;
break;
case MQTT_PROP_TYPE_STRING:
mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
mg_send(c, props[i].val.buf, props[i].val.len);
if (!mg_send_u16(c, mg_htons((uint16_t) props[i].val.len)) ||
!mg_send(c, props[i].val.buf, props[i].val.len))
return false;
break;
case MQTT_PROP_TYPE_BINARY_DATA:
mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
mg_send(c, props[i].val.buf, props[i].val.len);
if (!mg_send_u16(c, mg_htons((uint16_t) props[i].val.len)) ||
!mg_send(c, props[i].val.buf, props[i].val.len))
return false;
break;
case MQTT_PROP_TYPE_VARIABLE_INT:
len = encode_varint(buf_v, props[i].iv);
mg_send(c, buf_v, (size_t) len);
if (!mg_send(c, buf_v, (size_t) len)) return false;
break;
}
}
return true;
}
size_t mg_mqtt_next_prop(struct mg_mqtt_message *msg, struct mg_mqtt_prop *prop,
@@ -289,33 +298,41 @@ void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
total_len += get_props_size(opts->will_props, opts->num_will_props);
}
mg_mqtt_send_header(c, MQTT_CMD_CONNECT, 0, (uint32_t) total_len);
mg_send(c, hdr, sizeof(hdr));
// keepalive == 0 means "do not disconnect us!"
mg_send_u16(c, mg_htons((uint16_t) opts->keepalive));
if (!mqtt_send_header(c, MQTT_CMD_CONNECT, 0, (uint32_t) total_len) ||
!mg_send(c, hdr, sizeof(hdr)) ||
!mg_send_u16(c, mg_htons((uint16_t) opts->keepalive)))
goto fail;
if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
if (c->is_mqtt5 && !mg_send_mqtt_properties(c, opts->props, opts->num_props))
goto fail;
mg_send_u16(c, mg_htons((uint16_t) cid.len));
mg_send(c, cid.buf, cid.len);
if (!mg_send_u16(c, mg_htons((uint16_t) cid.len)) ||
!mg_send(c, cid.buf, cid.len))
goto fail;
if (hdr[7] & MQTT_HAS_WILL) {
if (c->is_mqtt5)
mg_send_mqtt_properties(c, opts->will_props, opts->num_will_props);
if (c->is_mqtt5 &&
!mg_send_mqtt_properties(c, opts->will_props, opts->num_will_props))
goto fail;
mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
mg_send(c, opts->topic.buf, opts->topic.len);
mg_send_u16(c, mg_htons((uint16_t) opts->message.len));
mg_send(c, opts->message.buf, opts->message.len);
}
if (opts->user.len > 0) {
mg_send_u16(c, mg_htons((uint16_t) opts->user.len));
mg_send(c, opts->user.buf, opts->user.len);
}
if (opts->pass.len > 0) {
mg_send_u16(c, mg_htons((uint16_t) opts->pass.len));
mg_send(c, opts->pass.buf, opts->pass.len);
if (!mg_send_u16(c, mg_htons((uint16_t) opts->topic.len)) ||
!mg_send(c, opts->topic.buf, opts->topic.len) ||
!mg_send_u16(c, mg_htons((uint16_t) opts->message.len)) ||
!mg_send(c, opts->message.buf, opts->message.len))
goto fail;
}
if (opts->user.len > 0 &&
(!mg_send_u16(c, mg_htons((uint16_t) opts->user.len)) ||
!mg_send(c, opts->user.buf, opts->user.len)))
goto fail;
if (opts->pass.len > 0 &&
(!mg_send_u16(c, mg_htons((uint16_t) opts->pass.len)) ||
!mg_send(c, opts->pass.buf, opts->pass.len)))
goto fail;
return;
fail:
mg_error(c, "OOM");
}
uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
@@ -330,20 +347,28 @@ uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
if (c->is_mqtt5) len += get_props_size(opts->props, opts->num_props);
if (opts->qos > 0 && id != 0) flags |= 1 << 3;
mg_mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, (uint32_t) len);
mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
mg_send(c, opts->topic.buf, opts->topic.len);
if (!mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, (uint32_t) len) ||
!mg_send_u16(c, mg_htons((uint16_t) opts->topic.len)) ||
!mg_send(c, opts->topic.buf, opts->topic.len))
goto fail;
if (opts->qos > 0) { // need to send 'id' field
if (id == 0) { // generate new one if not resending
if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
id = c->mgr->mqtt_id;
}
mg_send_u16(c, mg_htons(id));
if (!mg_send_u16(c, mg_htons(id))) goto fail;
}
if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
if (c->is_mqtt5 && !mg_send_mqtt_properties(c, opts->props, opts->num_props))
goto fail;
if (opts->message.len > 0) mg_send(c, opts->message.buf, opts->message.len);
if (opts->message.len > 0 &&
!mg_send(c, opts->message.buf, opts->message.len))
goto fail;
return id;
fail:
mg_error(c, "OOM");
return id;
}
@@ -352,14 +377,20 @@ void mg_mqtt_sub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
size_t plen = c->is_mqtt5 ? get_props_size(opts->props, opts->num_props) : 0;
size_t len = 2 + opts->topic.len + 2 + 1 + plen;
mg_mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, 2, (uint32_t) len);
if (!mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, 2, (uint32_t) len)) goto fail;
if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
mg_send_u16(c, mg_htons(c->mgr->mqtt_id));
if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
if (!mg_send_u16(c, mg_htons(c->mgr->mqtt_id))) goto fail;
mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
mg_send(c, opts->topic.buf, opts->topic.len);
mg_send(c, &qos_, sizeof(qos_));
if (c->is_mqtt5 && !mg_send_mqtt_properties(c, opts->props, opts->num_props))
goto fail;
if (!mg_send_u16(c, mg_htons((uint16_t) opts->topic.len)) ||
!mg_send(c, opts->topic.buf, opts->topic.len) ||
!mg_send(c, &qos_, sizeof(qos_)))
goto fail;
return;
fail:
mg_error(c, "OOM");
}
int mg_mqtt_parse(const uint8_t *buf, size_t len, uint8_t version,
@@ -466,15 +497,16 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
uint32_t remaining_len = sizeof(id);
if (c->is_mqtt5) remaining_len += 2; // 3.4.2
mg_mqtt_send_header(
c,
(uint8_t) (mm.qos == 2 ? MQTT_CMD_PUBREC : MQTT_CMD_PUBACK),
0, remaining_len);
mg_send(c, &id, sizeof(id));
if (!mqtt_send_header(c,
(uint8_t) (mm.qos == 2 ? MQTT_CMD_PUBREC
: MQTT_CMD_PUBACK),
0, remaining_len) ||
!mg_send(c, &id, sizeof(id)))
goto fail;
if (c->is_mqtt5) {
uint16_t zero = 0;
mg_send(c, &zero, sizeof(zero));
if (!mg_send(c, &zero, sizeof(zero))) goto fail;
}
}
mg_call(c, MG_EV_MQTT_MSG, &mm); // let the app handle qos stuff
@@ -483,15 +515,18 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
case MQTT_CMD_PUBREC: { // MQTT5: 3.5.2-1 TODO(): variable header rc
uint16_t id = mg_ntohs(mm.id);
uint32_t remaining_len = sizeof(id); // MQTT5 3.6.2-1
mg_mqtt_send_header(c, MQTT_CMD_PUBREL, 2, remaining_len);
mg_send(c, &id, sizeof(id)); // MQTT5 3.6.1-1, flags = 2
if (!mqtt_send_header(c, MQTT_CMD_PUBREL, 2,
remaining_len) // MQTT5 3.6.1-1, flags = 2
|| !mg_send(c, &id, sizeof(id)))
goto fail;
break;
}
case MQTT_CMD_PUBREL: { // MQTT5: 3.6.2-1 TODO(): variable header rc
uint16_t id = mg_ntohs(mm.id);
uint32_t remaining_len = sizeof(id); // MQTT5 3.7.2-1
mg_mqtt_send_header(c, MQTT_CMD_PUBCOMP, 0, remaining_len);
mg_send(c, &id, sizeof(id));
if (!mqtt_send_header(c, MQTT_CMD_PUBCOMP, 0, remaining_len) ||
!mg_send(c, &id, sizeof(id)))
goto fail;
break;
}
}
@@ -503,6 +538,9 @@ static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
}
}
(void) ev_data;
return;
fail:
mg_error(c, "OOM");
}
void mg_mqtt_ping(struct mg_connection *nc) {
@@ -517,24 +555,28 @@ void mg_mqtt_disconnect(struct mg_connection *c,
const struct mg_mqtt_opts *opts) {
size_t len = 0;
if (c->is_mqtt5) len = 1 + get_props_size(opts->props, opts->num_props);
mg_mqtt_send_header(c, MQTT_CMD_DISCONNECT, 0, (uint32_t) len);
if (!mqtt_send_header(c, MQTT_CMD_DISCONNECT, 0, (uint32_t) len)) goto fail;
if (c->is_mqtt5) {
uint8_t zero = 0;
mg_send(c, &zero, sizeof(zero)); // reason code
mg_send_mqtt_properties(c, opts->props, opts->num_props);
if (!mg_send(c, &zero, sizeof(zero)) // reason code
|| !mg_send_mqtt_properties(c, opts->props, opts->num_props))
goto fail;
}
return;
fail:
mg_error(c, "OOM");
}
struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
const struct mg_mqtt_opts *opts,
mg_event_handler_t fn, void *fn_data) {
struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
struct mg_connection *c =
mg_connect_svc(mgr, url, fn, fn_data, mqtt_cb, NULL);
if (c != NULL) {
struct mg_mqtt_opts empty;
memset(&empty, 0, sizeof(empty));
mg_mqtt_login(c, opts == NULL ? &empty : opts);
c->pfn = mqtt_cb;
}
return c;
}
+37 -15
View File
@@ -1,7 +1,7 @@
#include "net.h"
#include "dns.h"
#include "fmt.h"
#include "log.h"
#include "net.h"
#include "printf.h"
#include "profile.h"
#include "timer.h"
@@ -9,8 +9,14 @@
size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
size_t old = c->send.len;
mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
return c->send.len - old;
size_t expected = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
size_t actual = c->send.len - old;
if (actual != expected) {
mg_error(c, "OOM");
c->send.len = old;
actual = 0;
}
return actual;
}
size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
@@ -126,7 +132,7 @@ bool mg_aton(struct mg_str str, struct mg_addr *addr) {
struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
struct mg_connection *c =
(struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
(struct mg_connection *) mg_calloc(1, sizeof(*c) + mgr->extraconnsize);
if (c != NULL) {
c->mgr = mgr;
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
@@ -153,11 +159,12 @@ void mg_close_conn(struct mg_connection *c) {
mg_iobuf_free(&c->send);
mg_iobuf_free(&c->rtls);
mg_bzero((unsigned char *) c, sizeof(*c));
free(c);
mg_free(c);
}
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data) {
struct mg_connection *mg_connect_svc(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data,
mg_event_handler_t pfn, void *pfn_data) {
struct mg_connection *c = NULL;
if (url == NULL || url[0] == '\0') {
MG_ERROR(("null url"));
@@ -170,22 +177,30 @@ struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
c->fn = fn;
c->is_client = true;
c->fn_data = fn_data;
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
c->is_tls = (mg_url_is_ssl(url) != 0);
c->pfn = pfn;
c->pfn_data = pfn_data;
mg_call(c, MG_EV_OPEN, (void *) url);
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
mg_resolve(c, url);
}
return c;
}
struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data) {
return mg_connect_svc(mgr, url, fn, fn_data, NULL, NULL);
}
struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data) {
struct mg_connection *c = NULL;
if ((c = mg_alloc_conn(mgr)) == NULL) {
MG_ERROR(("OOM %s", url));
} else if (!mg_open_listener(c, url)) {
MG_ERROR(("Failed: %s, errno %d", url, errno));
MG_ERROR(("Failed: %s", url));
MG_PROF_FREE(c);
free(c);
mg_free(c);
c = NULL;
} else {
c->is_listening = 1;
@@ -193,8 +208,8 @@ struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
c->fn = fn;
c->fn_data = fn_data;
c->is_tls = (mg_url_is_ssl(url) != 0);
mg_call(c, MG_EV_OPEN, NULL);
if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must
MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
}
return c;
@@ -216,9 +231,9 @@ struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
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 *) mg_calloc(1, sizeof(*t));
if (t != NULL) {
flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete
flags |= MG_TIMER_AUTODELETE; // We have alloc'ed it, so autodelete
mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
}
return t;
@@ -235,7 +250,7 @@ long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
void mg_mgr_free(struct mg_mgr *mgr) {
struct mg_connection *c;
struct mg_timer *tmp, *t = mgr->timers;
while (t != NULL) tmp = t->next, free(t), t = tmp;
while (t != NULL) tmp = t->next, mg_free(t), t = tmp;
mgr->timers = NULL; // Important. Next call to poll won't touch timers
for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
mg_mgr_poll(mgr, 0);
@@ -266,7 +281,7 @@ void mg_mgr_init(struct mg_mgr *mgr) {
// clang-format on
#elif MG_ENABLE_FREERTOS_TCP
mgr->ss = FreeRTOS_CreateSocketSet();
#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
#elif MG_ARCH == MG_ARCH_UNIX
// Ignore SIGPIPE signal, so if client cancels the request, it
// won't kill the whole process.
signal(SIGPIPE, SIG_IGN);
@@ -278,4 +293,11 @@ void mg_mgr_init(struct mg_mgr *mgr) {
mgr->dns4.url = "udp://8.8.8.8:53";
mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
mg_tls_ctx_init(mgr);
MG_DEBUG(("MG_IO_SIZE: %lu, TLS: %s", MG_IO_SIZE,
MG_TLS == MG_TLS_NONE ? "none"
: MG_TLS == MG_TLS_MBED ? "MbedTLS"
: MG_TLS == MG_TLS_OPENSSL ? "OpenSSL"
: MG_TLS == MG_TLS_BUILTIN ? "builtin"
: MG_TLS == MG_TLS_WOLFSSL ? "WolfSSL"
: "custom"));
}
+8 -1
View File
@@ -14,7 +14,11 @@ struct mg_dns {
};
struct mg_addr {
uint8_t ip[16]; // Holds IPv4 or IPv6 address, in network byte order
union { // Holds IPv4 or IPv6 address, in network byte order
uint8_t ip[16];
uint32_t ip4;
uint64_t ip6[2];
};
uint16_t port; // TCP or UDP port in network byte order
uint8_t scope_id; // IPv6 scope ID
bool is_ip6; // True when address is IPv6 address
@@ -105,3 +109,6 @@ bool mg_wakeup(struct mg_mgr *, unsigned long id, const void *buf, size_t len);
bool mg_wakeup_init(struct mg_mgr *);
struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
unsigned flags, void (*fn)(void *), void *arg);
struct mg_connection *mg_connect_svc(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data,
mg_event_handler_t pfn, void *pfn_data);
+1086 -296
View File
File diff suppressed because it is too large. Load diff
+56 -5
View File
@@ -29,10 +29,10 @@ enum {
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_ST6_CHG, // state6 change uint8_t * (&ifp->state6)
MG_TCPIP_EV_USER // Starting ID for user events
};
// Network interface
struct mg_tcpip_if {
uint8_t mac[6]; // MAC address. Must be set to a valid MAC
@@ -48,15 +48,24 @@ struct mg_tcpip_if {
bool update_mac_hash_table; // Signal drivers to update MAC controller
struct mg_tcpip_driver *driver; // Low level driver
void *driver_data; // Driver-specific data
mg_tcpip_event_handler_t pfn; // Driver-specific event handler function
mg_tcpip_event_handler_t fn; // User-specified event handler function
struct mg_mgr *mgr; // Mongoose event manager
struct mg_queue recv_queue; // Receive queue
char dhcp_name[12]; // Name reported to DHCP, "mip" if unset
uint16_t mtu; // Interface MTU
char dhcp_name[MG_TCPIP_DHCPNAME_SIZE]; // Name for DHCP, "mip" if unset
uint16_t mtu; // Interface MTU
#define MG_TCPIP_MTU_DEFAULT 1500
#if MG_ENABLE_IPV6
uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses
uint8_t prefix_len; // Prefix length
uint64_t gw6[2]; // Default gateway
bool enable_slaac; // Enable IPv6 address autoconfiguration
bool enable_dhcp6_client; // Enable DCHPv6 client
#endif
// Internal state, user can use it but should not change it
uint8_t gwmac[6]; // Router's MAC
char *dns4_url; // DNS server URL
uint64_t now; // Current time
uint64_t timer_1000ms; // 1000 ms timer: for DHCP and link state
uint64_t lease_expire; // Lease expiration time, in ms
@@ -65,14 +74,17 @@ struct mg_tcpip_if {
volatile uint32_t nrecv; // Number of received frames
volatile uint32_t nsent; // Number of transmitted frames
volatile uint32_t nerr; // Number of driver errors
uint8_t state; // Current state
uint8_t state; // Current link and IPv4 state
#define MG_TCPIP_STATE_DOWN 0 // Interface is down
#define MG_TCPIP_STATE_UP 1 // Interface is up
#define MG_TCPIP_STATE_REQ 2 // Interface is up, DHCP REQUESTING state
#define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned
#define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work
#if MG_ENABLE_IPV6
uint8_t gw6mac[6]; // IPv6 Router's MAC
uint8_t state6; // Current IPv6 state
#endif
};
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
void mg_tcpip_free(struct mg_tcpip_if *);
void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
@@ -94,6 +106,7 @@ 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_rw612;
extern struct mg_tcpip_driver mg_tcpip_driver_cyw;
extern struct mg_tcpip_driver mg_tcpip_driver_nxp_wifi;
// Drivers that require SPI, can use this SPI abstraction
struct mg_tcpip_spi {
@@ -103,4 +116,42 @@ struct mg_tcpip_spi {
uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
};
// Alignment and memory section requirements
#ifndef MG_8BYTE_ALIGNED
#if defined(__GNUC__)
#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
#else
#define MG_8BYTE_ALIGNED
#endif // compiler
#endif // 8BYTE_ALIGNED
#ifndef MG_16BYTE_ALIGNED
#if defined(__GNUC__)
#define MG_16BYTE_ALIGNED __attribute__((aligned((16U))))
#else
#define MG_16BYTE_ALIGNED
#endif // compiler
#endif // 16BYTE_ALIGNED
#ifndef MG_32BYTE_ALIGNED
#if defined(__GNUC__)
#define MG_32BYTE_ALIGNED __attribute__((aligned((32U))))
#else
#define MG_32BYTE_ALIGNED
#endif // compiler
#endif // 32BYTE_ALIGNED
#ifndef MG_64BYTE_ALIGNED
#if defined(__GNUC__)
#define MG_64BYTE_ALIGNED __attribute__((aligned((64U))))
#else
#define MG_64BYTE_ALIGNED
#endif // compiler
#endif // 64BYTE_ALIGNED
#ifndef MG_ETH_RAM
#define MG_ETH_RAM
#endif
#endif
+1 -1
View File
@@ -150,7 +150,7 @@ fwxit:
// try to swap (honor dual image), otherwise just overwrite
MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
char *tmp = malloc(ss);
char *tmp = mg_calloc(1, ss);
// no stdlib calls here
for (size_t ofs = 0; ofs < s; ofs += ss) {
if (tmp != NULL)
+1 -1
View File
@@ -100,7 +100,7 @@ static bool __no_inline_not_in_flash_func(mg_picosdk_write)(void *addr,
static void __no_inline_not_in_flash_func(single_bank_swap)(char *p1, char *p2,
size_t s,
size_t ss) {
char *tmp = malloc(ss);
char *tmp = mg_calloc(1, ss);
if (tmp == NULL) return;
#if PICO_RP2040
uint32_t xip[256 / sizeof(uint32_t)];
+4
View File
@@ -200,6 +200,10 @@ MG_IRAM void single_bank_swap(char *p1, char *p2, size_t size) {
bool mg_ota_begin(size_t new_firmware_size) {
s_mg_flash_stm32f.size = flash_size();
#ifdef __ZEPHYR__
*((uint32_t *)0xE000ED94) = 0;
MG_DEBUG(("Jailbreak %s", *((uint32_t *)0xE000ED94) == 0 ? "successful" : "failed"));
#endif
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32f);
}
+4
View File
@@ -135,6 +135,10 @@ static bool mg_stm32h5_write(void *addr, const void *buf, size_t len) {
}
bool mg_ota_begin(size_t new_firmware_size) {
#ifdef __ZEPHYR__
*((uint32_t *)0xE000ED94) = 0;
MG_DEBUG(("Jailbreak %s", *((uint32_t *)0xE000ED94) == 0 ? "successful" : "failed"));
#endif
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32h5);
}
+4
View File
@@ -184,6 +184,10 @@ bool mg_ota_begin(size_t new_firmware_size) {
// Using only the 1st bank (mapped to CM7)
s_mg_flash_stm32h7.size /= 2;
}
#ifdef __ZEPHYR__
*((uint32_t *)0xE000ED94) = 0;
MG_DEBUG(("Jailbreak %s", *((uint32_t *)0xE000ED94) == 0 ? "successful" : "failed"));
#endif
return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32h7);
}
+11 -16
View File
@@ -2,24 +2,19 @@
#include "fmt.h"
#include "util.h"
size_t mg_queue_vprintf(struct mg_queue *q, const char *fmt, va_list *ap) {
size_t len = mg_snprintf(NULL, 0, fmt, ap);
char *buf;
if (len == 0 || mg_queue_book(q, &buf, len + 1) < len + 1) {
len = 0; // Nah. Not enough space
} else {
len = mg_vsnprintf((char *) buf, len + 1, fmt, ap);
mg_queue_add(q, len);
}
return len;
}
size_t mg_queue_printf(struct mg_queue *q, const char *fmt, ...) {
va_list ap;
char *buf;
size_t len;
va_start(ap, fmt);
len = mg_queue_vprintf(q, fmt, &ap);
va_end(ap);
va_list ap1, ap2;
va_start(ap1, fmt);
len = mg_vsnprintf(NULL, 0, fmt, &ap1);
va_end(ap1);
if (len == 0 || mg_queue_book(q, &buf, len + 1) < len + 1)
return 0; // Nah. Not enough space
va_start(ap2, fmt);
len = mg_vsnprintf(buf, len + 1, fmt, &ap2);
mg_queue_add(q, len);
va_end(ap2);
return len;
}
-1
View File
@@ -9,7 +9,6 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap);
size_t mg_snprintf(char *, size_t, const char *fmt, ...);
char *mg_vmprintf(const char *fmt, va_list *ap);
char *mg_mprintf(const char *fmt, ...);
size_t mg_queue_vprintf(struct mg_queue *, const char *fmt, va_list *);
size_t mg_queue_printf(struct mg_queue *, const char *fmt, ...);
// %M print helper functions
+4 -3
View File
@@ -1,9 +1,10 @@
#include "rpc.h"
#include "printf.h"
#include "util.h"
void mg_rpc_add(struct mg_rpc **head, struct mg_str method,
void (*fn)(struct mg_rpc_req *), void *fn_data) {
struct mg_rpc *rpc = (struct mg_rpc *) calloc(1, sizeof(*rpc));
struct mg_rpc *rpc = (struct mg_rpc *) mg_calloc(1, sizeof(*rpc));
if (rpc != NULL) {
rpc->method = mg_strdup(method);
rpc->fn = fn;
@@ -17,8 +18,8 @@ void mg_rpc_del(struct mg_rpc **head, void (*fn)(struct mg_rpc_req *)) {
while ((r = *head) != NULL) {
if (r->fn == fn || fn == NULL) {
*head = r->next;
free((void *) r->method.buf);
free(r);
mg_free((void *) r->method.buf);
mg_free(r);
} else {
head = &(*head)->next;
}
+2 -7
View File
@@ -82,12 +82,7 @@ void mg_sntp_request(struct mg_connection *c) {
}
struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fnd) {
struct mg_connection *c = NULL;
mg_event_handler_t fn, void *fn_data) {
if (url == NULL) url = "udp://time.google.com:123";
if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) {
c->pfn = sntp_cb;
sntp_cb(c, MG_EV_OPEN, (void *) url);
}
return c;
return mg_connect_svc(mgr, url, fn, fn_data, sntp_cb, NULL);
}
+40 -22
View File
@@ -141,7 +141,9 @@ bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
iolog(c, (char *) buf, n, false);
return n > 0;
} else {
return mg_iobuf_add(&c->send, c->send.len, buf, len);
return len == 0 || mg_iobuf_add(&c->send, c->send.len, buf, len) > 0;
// returning 0 means an OOM condition (iobuf couldn't resize), yet this is
// so far recoverable, let the caller decide
}
}
@@ -160,8 +162,10 @@ static void mg_set_non_blocking_mode(MG_SOCKET_TYPE fd) {
if (setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off)) != 0) (void) 0;
#elif MG_ENABLE_LWIP
lwip_fcntl(fd, F_SETFL, O_NONBLOCK);
#elif MG_ARCH == MG_ARCH_AZURERTOS
fcntl(fd, F_SETFL, O_NONBLOCK);
#elif MG_ARCH == MG_ARCH_THREADX
// NetxDuo fails to send large blocks of data to the non-blocking sockets
(void) fd;
// fcntl(fd, F_SETFL, O_NONBLOCK);
#elif MG_ARCH == MG_ARCH_TIRTOS
int val = 0;
setsockopt(fd, SOL_SOCKET, SO_BLOCKING, &val, sizeof(val));
@@ -179,19 +183,24 @@ static void mg_set_non_blocking_mode(MG_SOCKET_TYPE fd) {
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
MG_ERROR(("unsupported"));
#elif MG_ENABLE_FREERTOS_TCP
// TODO(): prvAllowIPPacketIPv4()
#else
// lwIP, Unix, Windows, Zephyr(, AzureRTOS ?)
// lwIP, Unix, Windows, Zephyr 4+(, AzureRTOS ?)
#if MG_ENABLE_LWIP && !LWIP_IGMP
MG_ERROR(("LWIP_IGMP not defined, no multicast support"));
#else
#if defined(__ZEPHYR__) && ZEPHYR_VERSION_CODE < 0x40000
MG_ERROR(("struct ip_mreq not defined"));
#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
setsockopt(FD(c), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq,
sizeof(mreq));
#endif // !Zephyr
#endif // !lwIP
#endif
}
@@ -309,9 +318,9 @@ static void read_conn(struct mg_connection *c) {
if (n == MG_IO_ERR || n == MG_IO_RESET) { // Windows, see #3031
if (c->rtls.len == 0 || m < 0) {
// 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.
if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104
} else { // see #2885
c->is_closing = 1; // or there's nothing we can do about it.
if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104
} else { // see #2885
// TLS buffer is capped to max record size, even though, there can
// be more than one record, give TLS a chance to process them.
}
@@ -332,6 +341,7 @@ static void write_conn(struct mg_connection *c) {
char *buf = (char *) c->send.buf;
size_t len = c->send.len;
long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_io_send(c, buf, len);
// TODO(): mg_tls_send() may return 0 forever on steady OOM
MG_DEBUG(("%lu %ld snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd,
(long) c->send.len, (long) c->send.size, (long) c->recv.len,
(long) c->recv.size, n, MG_SOCK_ERR(n)));
@@ -361,13 +371,14 @@ static void connect_conn(struct mg_connection *c) {
mg_call(c, MG_EV_CONNECT, NULL);
MG_EPOLL_MOD(c, 0);
if (c->is_tls_hs) mg_tls_handshake(c);
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
} else {
mg_error(c, "socket error");
}
}
static void setsockopts(struct mg_connection *c) {
#if MG_ENABLE_FREERTOS_TCP || MG_ARCH == MG_ARCH_AZURERTOS || \
#if MG_ENABLE_FREERTOS_TCP || MG_ARCH == MG_ARCH_THREADX || \
MG_ARCH == MG_ARCH_TIRTOS
(void) c;
#else
@@ -412,8 +423,9 @@ void mg_connect_resolved(struct mg_connection *c) {
rc = connect(FD(c), &usa.sa, slen); // Attempt to connect
if (rc == 0) { // Success
setlocaddr(FD(c), &c->loc);
mg_call(c, MG_EV_CONNECT, NULL); // Send MG_EV_CONNECT to the user
} else if (MG_SOCK_PENDING(rc)) { // Need to wait for TCP handshake
mg_call(c, MG_EV_CONNECT, NULL); // Send MG_EV_CONNECT to the user
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
} else if (MG_SOCK_PENDING(rc)) { // Need to wait for TCP handshake
MG_DEBUG(("%lu %ld -> %M pend", c->id, c->fd, mg_print_ip_port, &c->rem));
c->is_connecting = 1;
} else {
@@ -438,8 +450,8 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
socklen_t sa_len = sizeof(usa);
MG_SOCKET_TYPE fd = raccept(FD(lsn), &usa, &sa_len);
if (fd == MG_INVALID_SOCKET) {
#if MG_ARCH == MG_ARCH_AZURERTOS || defined(__ECOS)
// AzureRTOS, in non-block socket mode can mark listening socket readable
#if MG_ARCH == MG_ARCH_THREADX || defined(__ECOS)
// NetxDuo, in non-block socket mode can mark listening socket readable
// even it is not. See comment for 'select' func implementation in
// nx_bsd.c That's not an error, just should try later
if (errno != EAGAIN)
@@ -468,10 +480,12 @@ static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
c->pfn_data = lsn->pfn_data;
c->fn = lsn->fn;
c->fn_data = lsn->fn_data;
c->is_tls = lsn->is_tls;
MG_DEBUG(("%lu %ld accepted %M -> %M", c->id, c->fd, mg_print_ip_port,
&c->rem, mg_print_ip_port, &c->loc));
mg_call(c, MG_EV_OPEN, NULL);
mg_call(c, MG_EV_ACCEPT, NULL);
if (!c->is_tls_hs) c->is_tls = 0; // user did not call mg_tls_init()
}
}
@@ -577,7 +591,7 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
}
}
#else
struct timeval tv = {ms / 1000, (ms % 1000) * 1000}, tv_zero = {0, 0}, *tvp;
struct timeval tv = {ms / 1000, (ms % 1000) * 1000}, tv_1ms = {0, 1000}, *tvp;
struct mg_connection *c;
fd_set rset, wset, eset;
MG_SOCKET_TYPE maxfd = 0;
@@ -593,16 +607,16 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
FD_SET(FD(c), &eset);
if (can_read(c)) FD_SET(FD(c), &rset);
if (can_write(c)) FD_SET(FD(c), &wset);
if (c->rtls.len > 0 || mg_tls_pending(c) > 0) tvp = &tv_zero;
if (c->rtls.len > 0 || mg_tls_pending(c) > 0) tvp = &tv_1ms;
if (FD(c) > maxfd) maxfd = FD(c);
if (c->is_closing) tvp = &tv_zero;
if (c->is_closing) tvp = &tv_1ms;
}
if ((rc = select((int) maxfd + 1, &rset, &wset, &eset, tvp)) < 0) {
if ((rc = select((int) maxfd + 1, &rset, &wset, &eset, tvp)) <= 0) {
#if MG_ARCH == MG_ARCH_WIN32
if (maxfd == 0) Sleep(ms); // On Windows, select fails if no sockets
#else
MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc)));
if (rc < 0) MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc)));
#endif
FD_ZERO(&rset);
FD_ZERO(&wset);
@@ -611,7 +625,12 @@ static void mg_iotest(struct mg_mgr *mgr, int ms) {
for (c = mgr->conns; c != NULL; c = c->next) {
if (FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &eset)) {
#if MG_ARCH == MG_ARCH_THREADX
// NetxDuo stack returns exceptions for listening connection after accept
if (c->is_listening == 0) mg_error(c, "socket error");
#else
mg_error(c, "socket error");
#endif
} else {
c->is_readable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &rset);
c->is_writable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &wset);
@@ -734,11 +753,10 @@ void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
if (c->is_readable) accept_conn(mgr, c);
} else if (c->is_connecting) {
if (c->is_readable || c->is_writable) connect_conn(c);
//} else if (c->is_tls_hs) {
// if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
} else {
if (c->is_readable) read_conn(c);
if (c->is_writable) write_conn(c);
if (c->is_tls && !c->is_tls_hs && c->send.len == 0) mg_tls_flush(c);
}
if (c->is_draining && c->send.len == 0) c->is_closing = 1;
+27 -13
View File
@@ -1,6 +1,7 @@
#include "ssi.h"
#include "log.h"
#include "printf.h"
#include "ssi.h"
#include "util.h"
#ifndef MG_MAX_SSI_DEPTH
#define MG_MAX_SSI_DEPTH 5
@@ -30,31 +31,35 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
mg_snprintf(tmp, sizeof(tmp), "%.*s%s", (int) (p - path), path, arg);
if (depth < MG_MAX_SSI_DEPTH &&
(data = mg_ssi(tmp, root, depth + 1)) != NULL) {
mg_iobuf_add(&b, b.len, data, strlen(data));
free(data);
size_t datalen = strlen(data);
size_t ret = mg_iobuf_add(&b, b.len, data, datalen);
mg_free(data);
if (datalen > 0 && ret == 0) goto fail;
} else {
MG_ERROR(("%s: file=%s error or too deep", path, arg));
}
} // TODO(): or OOM at recursive call
} else if (sscanf(buf, "<!--#include virtual=\"%[^\"]", arg) > 0) {
char tmp[MG_PATH_MAX + MG_SSI_BUFSIZ + 10], *data;
mg_snprintf(tmp, sizeof(tmp), "%s%s", root, arg);
if (depth < MG_MAX_SSI_DEPTH &&
(data = mg_ssi(tmp, root, depth + 1)) != NULL) {
mg_iobuf_add(&b, b.len, data, strlen(data));
free(data);
size_t datalen = strlen(data);
size_t ret = mg_iobuf_add(&b, b.len, data, datalen);
mg_free(data);
if (datalen > 0 && ret == 0) goto fail;
} else {
MG_ERROR(("%s: virtual=%s error or too deep", path, arg));
}
} // TODO(): or OOM at recursive call
} else {
// Unknown SSI tag
MG_ERROR(("Unknown SSI tag: %.*s", (int) len, buf));
mg_iobuf_add(&b, b.len, buf, len);
if (len > 0 && mg_iobuf_add(&b, b.len, buf, len) == 0) goto fail;
}
intag = 0;
len = 0;
} else if (ch == '<') {
intag = 1;
if (len > 0) mg_iobuf_add(&b, b.len, buf, len);
if (len > 0 && mg_iobuf_add(&b, b.len, buf, len) == 0) goto fail;
len = 0;
buf[len++] = (char) (ch & 0xff);
} else if (intag) {
@@ -68,26 +73,35 @@ static char *mg_ssi(const char *path, const char *root, int depth) {
} else {
buf[len++] = (char) (ch & 0xff);
if (len >= sizeof(buf)) {
mg_iobuf_add(&b, b.len, buf, len);
if (mg_iobuf_add(&b, b.len, buf, len) == 0) goto fail;
len = 0;
}
}
}
if (len > 0) mg_iobuf_add(&b, b.len, buf, len);
if (b.len > 0) mg_iobuf_add(&b, b.len, "", 1); // nul-terminate
if (len > 0 && mg_iobuf_add(&b, b.len, buf, len) == 0) goto fail;
if (b.len > 0 && mg_iobuf_add(&b, b.len, "", 1) == 0) // nul-terminate
goto fail;
fclose(fp);
}
(void) depth;
(void) root;
return (char *) b.buf;
fail:
fclose(fp);
return NULL;
}
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
const char *fullpath) {
const char *headers = "Content-Type: text/html; charset=utf-8\r\n";
char *data = mg_ssi(fullpath, root, 0);
if (data == NULL) {
mg_error(c, "OOM");
return;
}
mg_http_reply(c, 200, headers, "%s", data == NULL ? "" : data);
free(data);
mg_free(data);
}
#else
void mg_http_serve_ssi(struct mg_connection *c, const char *root,
+2 -1
View File
@@ -1,4 +1,5 @@
#include "str.h"
#include "util.h"
struct mg_str mg_str_s(const char *s) {
struct mg_str str = {(char *) s, s == NULL ? 0 : strlen(s)};
@@ -26,7 +27,7 @@ int mg_casecmp(const char *s1, const char *s2) {
struct mg_str mg_strdup(const struct mg_str s) {
struct mg_str r = {NULL, 0};
if (s.len > 0 && s.buf != NULL) {
char *sc = (char *) calloc(1, s.len + 1);
char *sc = (char *) mg_calloc(1, s.len + 1);
if (sc != NULL) {
memcpy(sc, s.buf, s.len);
sc[s.len] = '\0';
+2 -1
View File
@@ -1,5 +1,6 @@
#include "arch.h"
#include "timer.h"
#include "util.h"
void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
unsigned flags, void (*fn)(void *), void *arg) {
@@ -38,7 +39,7 @@ void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
// If this timer is not repeating and marked AUTODELETE, remove it
if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
mg_timer_free(head, t);
free(t);
mg_free(t);
}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ struct mg_timer {
#define MG_TIMER_REPEAT 1 // Call function periodically
#define MG_TIMER_RUN_NOW 2 // Call immediately when timer is set
#define MG_TIMER_CALLED 4 // Timer function was called at least once
#define MG_TIMER_AUTODELETE 8 // free() timer when done
#define MG_TIMER_AUTODELETE 8 // mg_free() timer when done
void (*fn)(void *); // Function to call
void *arg; // Function argument
struct mg_timer *next; // Linkage
+1
View File
@@ -28,6 +28,7 @@ void mg_tls_free(struct mg_connection *);
long mg_tls_send(struct mg_connection *, const void *buf, size_t len);
long mg_tls_recv(struct mg_connection *, void *buf, size_t len);
size_t mg_tls_pending(struct mg_connection *);
void mg_tls_flush(struct mg_connection *);
void mg_tls_handshake(struct mg_connection *);
// Private
+3 -3
View File
@@ -20,6 +20,9 @@
*
*******************************************************************************/
#include "arch.h"
#include "tls.h"
#if MG_TLS == MG_TLS_BUILTIN
/******************************************************************************/
#define AES_DECRYPTION 1 // whether AES decryption is supported
/******************************************************************************/
@@ -27,11 +30,8 @@
#define MG_ENCRYPT 1 // specify whether we're encrypting
#define MG_DECRYPT 0 // or decrypting
#include "arch.h"
#include "tls.h"
#include "tls_aes128.h"
#if MG_TLS == MG_TLS_BUILTIN
/******************************************************************************
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
******************************************************************************/
+419 -324
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -20,8 +20,8 @@
#if defined(_MSC_VER) || defined(__cplusplus)
// add restrict support
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || defined(__clang__) || \
defined(__GNUC__)
#if ((defined(_MSC_VER) && _MSC_VER >= 1900) && !defined(__cplusplus)) || \
defined(__clang__) || defined(__GNUC__)
#define restrict __restrict
#else
#define restrict
+3
View File
@@ -6,7 +6,9 @@
#include "arch.h"
#include "config.h"
#include "tls.h"
#if MG_TLS == MG_TLS_BUILTIN
#ifndef __PORTABLE_8439_H
#define __PORTABLE_8439_H
#if defined(__cplusplus)
@@ -108,3 +110,4 @@ PORTABLE_8439_DECL size_t mg_chacha20_poly1305_decrypt(
}
#endif
#endif
#endif
+3
View File
@@ -21,6 +21,9 @@ size_t mg_tls_pending(struct mg_connection *c) {
(void) c;
return 0;
}
void mg_tls_flush(struct mg_connection *c) {
(void) c;
}
void mg_tls_ctx_init(struct mg_mgr *mgr) {
(void) mgr;
}
+32 -10
View File
@@ -1,5 +1,8 @@
#include "log.h"
#include "printf.h"
#include "profile.h"
#include "tls.h"
#include "util.h"
#if MG_TLS == MG_TLS_MBED
@@ -9,6 +12,13 @@
#define MG_MBEDTLS_RNG_GET
#endif
static int mg_tls_err(struct mg_connection *c, int rc) {
char s[80];
mbedtls_strerror(rc, s, sizeof(s));
MG_ERROR(("%lu %s", ((struct mg_connection *) c)->id, s));
return rc;
}
static int mg_mbed_rng(void *ctx, unsigned char *buf, size_t len) {
mg_random(buf, len);
(void) ctx;
@@ -49,7 +59,11 @@ void mg_tls_free(struct mg_connection *c) {
#ifdef MBEDTLS_SSL_SESSION_TICKETS
mbedtls_ssl_ticket_free(&tls->ticket);
#endif
free(tls);
#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 && \
defined(MBEDTLS_PSA_CRYPTO_C)
mbedtls_psa_crypto_free(); // https://github.com/Mbed-TLS/mbedtls/issues/9223#issuecomment-2144898336
#endif
mg_free(tls);
c->tls = NULL;
}
}
@@ -84,7 +98,7 @@ void mg_tls_handshake(struct mg_connection *c) {
MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
c->is_tls_hs, rc, -rc));
} else {
mg_error(c, "TLS handshake: -%#x", -rc); // Error
mg_error(c, "TLS handshake: -%#x", -mg_tls_err(c, rc)); // Error
}
}
@@ -95,7 +109,7 @@ static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
}
void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
struct mg_tls *tls = (struct mg_tls *) mg_calloc(1, sizeof(*tls));
int rc = 0;
c->tls = tls;
if (c->tls == NULL) {
@@ -122,7 +136,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
&tls->conf,
c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
mg_error(c, "tls defaults %#x", -rc);
mg_error(c, "tls defaults %#x", -mg_tls_err(c, rc));
goto fail;
}
mbedtls_ssl_conf_rng(&tls->conf, mg_mbed_rng, c);
@@ -138,7 +152,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
char *host = mg_mprintf("%.*s", opts->name.len, opts->name.buf);
mbedtls_ssl_set_hostname(&tls->ssl, host);
MG_DEBUG(("%lu hostname verification: %s", c->id, host));
free(host);
mg_free(host);
}
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
}
@@ -146,7 +160,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
if (!mg_load_key(opts->key, &tls->pk)) goto fail;
if (tls->cert.version &&
(rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk)) != 0) {
mg_error(c, "own cert %#x", -rc);
mg_error(c, "own cert %#x", -mg_tls_err(c, rc));
goto fail;
}
@@ -157,7 +171,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
#endif
if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) {
mg_error(c, "setup err %#x", -rc);
mg_error(c, "setup err %#x", -mg_tls_err(c, rc));
goto fail;
}
c->is_tls = 1;
@@ -204,13 +218,21 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
tls->throttled_buf = (unsigned char *)buf; // MbedTLS code actually ignores
tls->throttled_len = len; // these, but let's play API rules
return (long) len; // already encripted that when throttled
}
} // if last chunk fails to be sent, it needs to be flushed
if (n <= 0) return MG_IO_ERR;
return n;
}
void mg_tls_flush(struct mg_connection *c) {
struct mg_tls *tls = (struct mg_tls *) c->tls;
if (c->is_tls_throttled) {
long n = mbedtls_ssl_write(&tls->ssl, tls->throttled_buf, tls->throttled_len);
c->is_tls_throttled = (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE);
}
}
void mg_tls_ctx_init(struct mg_mgr *mgr) {
struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx));
struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mg_calloc(1, sizeof(*ctx));
if (ctx == NULL) {
MG_ERROR(("TLS context init OOM"));
} else {
@@ -233,7 +255,7 @@ void mg_tls_ctx_free(struct mg_mgr *mgr) {
#ifdef MBEDTLS_SSL_SESSION_TICKETS
mbedtls_ssl_ticket_free(&ctx->tickets);
#endif
free(ctx);
mg_free(ctx);
mgr->tls_ctx = NULL;
}
}
+1
View File
@@ -7,6 +7,7 @@
#if MG_TLS == MG_TLS_MBED
#include <mbedtls/debug.h>
#include <mbedtls/error.h>
#include <mbedtls/net_sockets.h>
#include <mbedtls/ssl.h>
#include <mbedtls/ssl_ticket.h>
+10 -3
View File
@@ -1,5 +1,6 @@
#include "printf.h"
#include "tls.h"
#include "util.h"
#if MG_TLS == MG_TLS_OPENSSL || MG_TLS == MG_TLS_WOLFSSL
@@ -38,6 +39,7 @@ static STACK_OF(X509_INFO) * load_ca_certs(struct mg_str ca) {
static bool add_ca_certs(SSL_CTX *ctx, STACK_OF(X509_INFO) * certs) {
int i;
X509_STORE *cert_store = SSL_CTX_get_cert_store(ctx);
if (cert_store == NULL) return false;
for (i = 0; i < sk_X509_INFO_num(certs); i++) {
X509_INFO *cert_info = sk_X509_INFO_value(certs, i);
if (cert_info->x509 && !X509_STORE_add_cert(cert_store, cert_info->x509))
@@ -104,6 +106,7 @@ static void ssl_keylog_cb(const SSL *ssl, const char *line) {
fprintf(f, "%s\n", line);
fflush(f);
fclose(f);
(void) ssl;
}
#endif
@@ -113,12 +116,12 @@ void mg_tls_free(struct mg_connection *c) {
SSL_free(tls->ssl);
SSL_CTX_free(tls->ctx);
BIO_meth_free(tls->bm);
free(tls);
mg_free(tls);
c->tls = NULL;
}
void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
struct mg_tls *tls = (struct mg_tls *) mg_calloc(1, sizeof(*tls));
const char *id = "mongoose";
static unsigned char s_initialised = 0;
BIO *bio = NULL;
@@ -211,7 +214,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
X509_VERIFY_PARAM_set1_host(SSL_get0_param(tls->ssl), s, 0);
#endif
SSL_set_tlsext_host_name(tls->ssl, s);
free(s);
mg_free(s);
}
#endif
#if MG_TLS == MG_TLS_WOLFSSL
@@ -270,6 +273,10 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
return n;
}
void mg_tls_flush(struct mg_connection *c) {
(void) c;
}
void mg_tls_ctx_init(struct mg_mgr *mgr) {
(void) mgr;
}
+36 -25
View File
@@ -1,5 +1,6 @@
#include "tls.h"
#include "tls_rsa.h"
#include "util.h"
#if MG_TLS == MG_TLS_BUILTIN
@@ -62,7 +63,7 @@ typedef uint16_t comp; /**< A single precision component. */
typedef uint32_t long_comp; /**< A double precision component. */
typedef int32_t slong_comp; /**< A signed double precision component. */
#else /* regular 32 bit */
#ifdef WIN32
#ifdef _MSC_VER
#define COMP_RADIX 4294967296i64
#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64
#else
@@ -158,10 +159,10 @@ typedef struct _BI_CTX BI_CTX;
*/
NS_INTERNAL BI_CTX *bi_initialize(void);
//NS_INTERNAL void bi_terminate(BI_CTX *ctx);
NS_INTERNAL void bi_terminate(BI_CTX *ctx);
NS_INTERNAL void bi_permanent(bigint *bi);
NS_INTERNAL void bi_depermanent(bigint *bi);
//NS_INTERNAL void bi_clear_cache(BI_CTX *ctx);
NS_INTERNAL void bi_clear_cache(BI_CTX *ctx);
NS_INTERNAL void bi_free(BI_CTX *ctx, bigint *bi);
NS_INTERNAL bigint *bi_copy(bigint *bi);
NS_INTERNAL bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
@@ -183,7 +184,7 @@ NS_INTERNAL bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi,
#endif
NS_INTERNAL int bi_compare(bigint *bia, bigint *bib);
NS_INTERNAL void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
//NS_INTERNAL void bi_free_mod(BI_CTX *ctx, int mod_offset);
NS_INTERNAL void bi_free_mod(BI_CTX *ctx, int mod_offset);
#ifdef CONFIG_SSL_FULL_MODE
NS_INTERNAL void bi_print(const char *label, bigint *bi);
@@ -309,8 +310,8 @@ static void check(const bigint *bi);
* @return A bigint context.
*/
NS_INTERNAL BI_CTX *bi_initialize(void) {
/* calloc() sets everything to zero */
BI_CTX *ctx = (BI_CTX *) calloc(1, sizeof(BI_CTX));
/* mg_calloc() sets everything to zero */
BI_CTX *ctx = (BI_CTX *) mg_calloc(1, sizeof(BI_CTX));
/* the radix */
ctx->bi_radix = alloc(ctx, 2);
@@ -320,7 +321,6 @@ NS_INTERNAL BI_CTX *bi_initialize(void) {
return ctx;
}
#if 0
/**
* @brief Close the bigint context and free any resources.
*
@@ -340,7 +340,7 @@ NS_INTERNAL void bi_terminate(BI_CTX *ctx) {
}
bi_clear_cache(ctx);
free(ctx);
mg_free(ctx);
}
/**
@@ -353,14 +353,13 @@ NS_INTERNAL void bi_clear_cache(BI_CTX *ctx) {
for (p = ctx->free_list; p != NULL; p = pn) {
pn = p->next;
free(p->comps);
free(p);
mg_free(p->comps);
mg_free(p);
}
ctx->free_count = 0;
ctx->free_list = NULL;
}
#endif
/**
* @brief Increment the number of references to this object.
@@ -930,7 +929,6 @@ NS_INTERNAL void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) {
#endif
}
#if 0
/**
* @brief Used when cleaning various bigints at the end of a session.
* @param ctx [in] The bigint session context.
@@ -952,7 +950,6 @@ void bi_free_mod(BI_CTX *ctx, int mod_offset) {
bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
}
#endif
/**
* Perform a standard multiplication between two bigints.
@@ -1192,9 +1189,9 @@ NS_INTERNAL int bi_compare(bigint *bia, bigint *bib) {
static void more_comps(bigint *bi, int n) {
if (n > bi->max_comps) {
int max = MAX(bi->max_comps * 2, n);
void *p = calloc(1, (size_t) max * COMP_BYTE_SIZE);
void *p = mg_calloc(1, (size_t) max * COMP_BYTE_SIZE);
if (p != NULL && bi->size > 0) memcpy(p, bi->comps, (size_t) bi->max_comps * COMP_BYTE_SIZE);
free(bi->comps);
mg_free(bi->comps);
bi->max_comps = (short) max;
bi->comps = (comp *) p;
}
@@ -1229,8 +1226,8 @@ static bigint *alloc(BI_CTX *ctx, int size) {
more_comps(biR, size);
} else {
/* No free bigints available - create a new one. */
biR = (bigint *) calloc(1, sizeof(bigint));
biR->comps = (comp *) calloc(1, (size_t) size * COMP_BYTE_SIZE);
biR = (bigint *) mg_calloc(1, sizeof(bigint));
biR->comps = (comp *) mg_calloc(1, (size_t) size * COMP_BYTE_SIZE);
biR->max_comps = (short) size; /* give some space to spare */
}
@@ -1419,7 +1416,7 @@ static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) {
k <<= 1;
}
ctx->g = (bigint **) calloc(1, k * sizeof(bigint *));
ctx->g = (bigint **) mg_calloc(1, k * sizeof(bigint *));
ctx->g[0] = bi_clone(ctx, g1);
bi_permanent(ctx->g[0]);
g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */
@@ -1470,7 +1467,7 @@ NS_INTERNAL bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) {
/* work out the slide constants */
precompute_slide_window(ctx, window_size, bi);
#else /* just one constant */
ctx->g = (bigint **) calloc(1, sizeof(bigint *));
ctx->g = (bigint **) mg_calloc(1, sizeof(bigint *));
ctx->g[0] = bi_clone(ctx, bi);
ctx->window = 1;
bi_permanent(ctx->g[0]);
@@ -1513,7 +1510,7 @@ NS_INTERNAL bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) {
bi_free(ctx, ctx->g[i]);
}
free(ctx->g);
mg_free(ctx->g);
bi_free(ctx, bi);
bi_free(ctx, biexp);
#if defined CONFIG_BIGINT_MONTGOMERY
@@ -1562,18 +1559,32 @@ NS_INTERNAL bigint *bi_crt(BI_CTX *ctx, bigint *bi, bigint *dP, bigint *dQ,
}
#endif
// Proper lib usage:
// - BI_CTX *c = bi_initialize()
// - allocate bigints (e.g.: calling bi_import(), int_to_bi(), ...)
// - function calls, allocate bigints, etc.
// - bigint *n = bi_import(c, indata, insize)
// - bi_set_mod(c, n, x)
// - mod function calls
// - bigint *nn = bi_mod_pwr(c, m, e) <-- frees m, e
// - bi_free_mod(c, x) <-- frees n
// - bi_export(c, nn, outdata, outsize) <-- frees nn
// - function calls
// - free bigints calling bi_free()
// - bi_terminate(c) <-- frees c
int mg_rsa_mod_pow(const uint8_t *mod, size_t modsz, const uint8_t *exp, size_t expsz, const uint8_t *msg, size_t msgsz, uint8_t *out, size_t outsz) {
BI_CTX *bi_ctx = bi_initialize();
bigint *m1;
bigint *n = bi_import(bi_ctx, mod, (int) modsz);
bigint *e = bi_import(bi_ctx, exp, (int) expsz);
bigint *h = bi_import(bi_ctx, msg, (int) msgsz);
bi_set_mod(bi_ctx, n, 0);
bigint *m1 = bi_mod_power(bi_ctx, h, e);
m1 = bi_mod_power(bi_ctx, h, e);
bi_free_mod(bi_ctx, 0);
bi_export(bi_ctx, m1, out, (int) outsz);
bi_free(bi_ctx, n);
bi_free(bi_ctx, e);
bi_free(bi_ctx, h);
bi_free(bi_ctx, m1);
bi_terminate(bi_ctx);
return 0;
}
+27 -1
View File
@@ -17,6 +17,13 @@ bool mg_random(void *buf, size_t len) {
#if MG_ARCH == MG_ARCH_ESP32
while (len--) *p++ = (unsigned char) (esp_random() & 255);
success = true;
#elif MG_ARCH == MG_ARCH_CUBE && defined(HAL_RNG_MODULE_ENABLED)
extern RNG_HandleTypeDef hrng;
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
uint32_t r = HAL_RNG_ReadLastRandomNumber(&hrng);
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
}
success = true;
#elif MG_ARCH == MG_ARCH_PICOSDK
while (len--) *p++ = (unsigned char) (get_rand_32() & 255);
success = true;
@@ -127,6 +134,7 @@ int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip) {
bool mg_path_is_sane(const struct mg_str path) {
const char *s = path.buf;
size_t n = path.len;
if (path.buf[0] == '~') return false; // Starts with ~
if (path.buf[0] == '.' && path.buf[1] == '.') return false; // Starts with ..
for (; s[0] != '\0' && n > 0; s++, n--) {
if ((s[0] == '/' || s[0] == '\\') && n >= 2) { // Subdir?
@@ -146,7 +154,9 @@ uint64_t mg_millis(void) {
#elif MG_ARCH == MG_ARCH_ESP8266 || MG_ARCH == MG_ARCH_ESP32 || \
MG_ARCH == MG_ARCH_FREERTOS
return xTaskGetTickCount() * portTICK_PERIOD_MS;
#elif MG_ARCH == MG_ARCH_AZURERTOS
#elif MG_ARCH == MG_ARCH_CUBE
return (uint64_t) HAL_GetTick();
#elif MG_ARCH == MG_ARCH_THREADX
return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
#elif MG_ARCH == MG_ARCH_TIRTOS
return (uint64_t) Clock_getTicks();
@@ -194,7 +204,23 @@ uint32_t mg_ntohl(uint32_t net) {
return MG_LOAD_BE32(&net);
}
uint64_t mg_ntohll(uint64_t net) {
return MG_LOAD_BE64(&net);
}
void mg_delayms(unsigned int ms) {
uint64_t to = mg_millis() + ms + 1;
while (mg_millis() < to) (void) 0;
}
#if MG_ENABLE_CUSTOM_CALLOC
#else
void *mg_calloc(size_t count, size_t size) {
return calloc(count, size);
}
void mg_free(void *ptr) {
free(ptr);
}
#endif
+43 -1
View File
@@ -11,6 +11,8 @@
#define assert(x)
#endif
void *mg_calloc(size_t count, size_t size);
void mg_free(void *ptr);
void mg_bzero(volatile unsigned char *buf, size_t len);
bool mg_random(void *buf, size_t len);
char *mg_random_str(char *buf, size_t len);
@@ -25,6 +27,16 @@ void mg_delayms(unsigned int ms);
#define MG_IPV4(a, b, c, d) mg_htonl(MG_U32(a, b, c, d))
#define MG_IPV6(a, b, c, d, e, f, g ,h) \
{ (uint8_t)((a)>>8),(uint8_t)(a), \
(uint8_t)((b)>>8),(uint8_t)(b), \
(uint8_t)((c)>>8),(uint8_t)(c), \
(uint8_t)((d)>>8),(uint8_t)(d), \
(uint8_t)((e)>>8),(uint8_t)(e), \
(uint8_t)((f)>>8),(uint8_t)(f), \
(uint8_t)((g)>>8),(uint8_t)(g), \
(uint8_t)((h)>>8),(uint8_t)(h) }
// For printing IPv4 addresses: printf("%d.%d.%d.%d\n", MG_IPADDR_PARTS(&ip))
#define MG_U8P(ADDR) ((uint8_t *) (ADDR))
#define MG_IPADDR_PARTS(ADDR) \
@@ -39,6 +51,14 @@ void mg_delayms(unsigned int ms);
((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_LOAD_BE64(p) \
((uint64_t) (((uint64_t) MG_U8P(p)[0] << 56U) | \
((uint64_t) MG_U8P(p)[1] << 48U) | \
((uint64_t) MG_U8P(p)[2] << 40U) | \
((uint64_t) MG_U8P(p)[3] << 32U) | \
((uint64_t) MG_U8P(p)[4] << 24U) | \
((uint64_t) MG_U8P(p)[5] << 16U) | \
((uint64_t) MG_U8P(p)[6] << 8U) | MG_U8P(p)[7]))
#define MG_STORE_BE16(p, n) \
do { \
MG_U8P(p)[0] = ((n) >> 8U) & 255; \
@@ -57,11 +77,24 @@ void mg_delayms(unsigned int ms);
MG_U8P(p)[2] = ((n) >> 8U) & 255; \
MG_U8P(p)[3] = (n) &255; \
} while (0)
#define MG_STORE_BE64(p, n) \
do { \
MG_U8P(p)[0] = ((n) >> 56U) & 255; \
MG_U8P(p)[1] = ((n) >> 48U) & 255; \
MG_U8P(p)[2] = ((n) >> 40U) & 255; \
MG_U8P(p)[3] = ((n) >> 32U) & 255; \
MG_U8P(p)[4] = ((n) >> 24U) & 255; \
MG_U8P(p)[5] = ((n) >> 16U) & 255; \
MG_U8P(p)[6] = ((n) >> 8U) & 255; \
MG_U8P(p)[7] = (n) &255; \
} while (0)
uint16_t mg_ntohs(uint16_t net);
uint32_t mg_ntohl(uint32_t net);
uint64_t mg_ntohll(uint64_t net);
#define mg_htons(x) mg_ntohs(x)
#define mg_htonl(x) mg_ntohl(x)
#define mg_htonll(x) mg_ntohll(x)
#define MG_REG(x) ((volatile uint32_t *) (x))[0]
#define MG_BIT(x) (((uint32_t) 1U) << (x))
@@ -70,9 +103,14 @@ uint32_t mg_ntohl(uint32_t net);
#define MG_ROUND_UP(x, a) ((a) == 0 ? (x) : ((((x) + (a) -1) / (a)) * (a)))
#define MG_ROUND_DOWN(x, a) ((a) == 0 ? (x) : (((x) / (a)) * (a)))
#if defined(__GNUC__)
#if defined(__GNUC__) && defined(__arm__)
#ifdef __ZEPHYR__
#define MG_ARM_DISABLE_IRQ() __asm__ __volatile__("cpsid i" : : : "memory")
#define MG_ARM_ENABLE_IRQ() __asm__ __volatile__("cpsie i" : : : "memory")
#else
#define MG_ARM_DISABLE_IRQ() asm volatile("cpsid i" : : : "memory")
#define MG_ARM_ENABLE_IRQ() asm volatile("cpsie i" : : : "memory")
#endif // !ZEPHYR
#elif defined(__CCRH__)
#define MG_RH850_DISABLE_IRQ() __DI()
#define MG_RH850_ENABLE_IRQ() __EI()
@@ -86,7 +124,11 @@ uint32_t mg_ntohl(uint32_t net);
#elif defined(__ARMCC_VERSION)
#define MG_DSB() __builtin_arm_dsb(0xf)
#elif defined(__GNUC__) && defined(__arm__) && defined(__thumb__)
#ifdef __ZEPHYR__
#define MG_DSB() __asm__("DSB 0xf")
#else
#define MG_DSB() asm("DSB 0xf")
#endif // !ZEPHYR
#elif defined(__ICCARM__)
#define MG_DSB() __iar_builtin_DSB()
#else
+1 -1
View File
@@ -1 +1 @@
#define MG_VERSION "7.18"
#define MG_VERSION "7.20"
+26 -17
View File
@@ -4,26 +4,35 @@
#include "log.h"
#include "str.h"
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;
struct mg_wifi_data {
char *ssid, *pass; // STA mode, SSID to connect to
char *apssid, *appass; // AP mode, our SSID
uint32_t apip, apmask; // AP mode, our IP address and mask
uint8_t security; // STA mode, TBD
uint8_t apsecurity; // AP mode, TBD
uint8_t apchannel; // AP mode, channel to use
bool apmode; // start in AP mode; 'false' -> connect to 'ssid' != NULL
};
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_connect(struct mg_wifi_data *);
bool mg_wifi_disconnect(void);
bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel);
bool mg_wifi_ap_start(struct mg_wifi_data *);
bool mg_wifi_ap_stop(void);
+8 -8
View File
@@ -1,16 +1,18 @@
#include "wifi.h"
#if (!defined(MG_ENABLE_DRIVER_PICO_W) || !MG_ENABLE_DRIVER_PICO_W) && \
(!defined(MG_ENABLE_DRIVER_CYW) || !MG_ENABLE_DRIVER_CYW)
(!defined(MG_ENABLE_DRIVER_CYW) || !MG_ENABLE_DRIVER_CYW) && \
(!defined(MG_ENABLE_DRIVER_CYW_SDIO) || !MG_ENABLE_DRIVER_CYW_SDIO) && \
(!defined(MG_ENABLE_DRIVER_NXP_WIFI) || !MG_ENABLE_DRIVER_NXP_WIFI)
bool mg_wifi_scan(void) {
MG_ERROR(("No Wi-Fi driver enabled"));
return false;
}
bool mg_wifi_connect(char *ssid, char *pass) {
(void) ssid;
(void) pass;
bool mg_wifi_connect(struct mg_wifi_data *wifi) {
(void) wifi;
return mg_wifi_scan();
}
@@ -18,10 +20,8 @@ bool mg_wifi_disconnect(void) {
return mg_wifi_scan();
}
bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
(void) ssid;
(void) pass;
(void) channel;
bool mg_wifi_ap_start(struct mg_wifi_data *wifi) {
(void) wifi;
return mg_wifi_scan();
}
+3 -3
View File
@@ -55,7 +55,7 @@ static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey,
mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len,
wsproto->buf);
}
mg_send(c, "\r\n", 2);
if (!mg_send(c, "\r\n", 2)) mg_error(c, "OOM");
}
static uint32_t be32(const uint8_t *p) {
@@ -292,6 +292,6 @@ size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op) {
memmove(p, p - header_len, len); // Shift data
memcpy(p - header_len, header, header_len); // Prepend header
mg_ws_mask(c, len); // Mask data
}
return c->send.len;
} // returning 0 means an OOM condition (iobuf couldn't resize), yet this is
return c->send.len; // so far recoverable, let the caller decide
}
+34 -17
View File
@@ -9,12 +9,12 @@ CWD ?= $(realpath $(CURDIR))
ROOT_DIR = $(realpath $(CWD)/..)
ENV ?= -e Tmp=. -e WINEDEBUG=-all
DOCKER_BIN ?= docker
DOCKER ?= $(DOCKER_BIN) run --platform linux/amd64 --rm $(ENV) -v $(ROOT_DIR):$(ROOT_DIR) -w $(CWD)
VCFLAGS = /nologo /W3 /O2 /MD /I. $(DEFS) $(TFLAGS)
# use net=host so all tests have the same network and can access localhost and ad hoc services
DOCKER ?= $(DOCKER_BIN) run --platform linux/amd64 --net=host --rm $(ENV) -v $(ROOT_DIR):$(ROOT_DIR) -w $(CWD)
VCFLAGS ?= /nologo /W3 /O2 /MD /I.
IPV6 ?= 1
ASAN ?= -fsanitize=address,undefined,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
ASAN_OPTIONS ?= detect_leaks=1
REFPROJS := $(dir $(wildcard ../reference-projects/windows-macos-linux/*/Makefile))
# This does not include ESP32, ESP8266, Microchip; all examples that are directly placed under an OS tutorial. Also, it is needed that way...
TUTORIALS_EMBEDDED := $(dir $(wildcard ../tutorials/infineon/*/Makefile)) $(dir $(wildcard ../tutorials/nxp/*/Makefile)) $(dir $(wildcard ../tutorials/pico-sdk/*/Makefile)) $(dir $(wildcard ../tutorials/renesas/*/Makefile)) $(dir $(wildcard ../tutorials/stm32/*/Makefile)) $(dir $(wildcard ../tutorials/ti/*/Makefile)) $(dir $(wildcard ../tutorials/wch/*/Makefile))
TUTORIALS := ../tutorials/micropython/ $(filter-out $(TUTORIALS_EMBEDDED), $(dir $(wildcard ../tutorials/*/*/Makefile)))
@@ -75,13 +75,13 @@ LDFLAGS += -L$(WOLFSSL)/lib -lwolfssl
endif
ifeq "$(SSL)" "BUILTIN"
CFLAGS += -DMG_TLS=MG_TLS_BUILTIN
DEFS += -DMG_TLS=MG_TLS_BUILTIN
endif
all:
$(MAKE) -C ../tutorials/http/http-server
tall: mg_prefix unamalgamated test mip_test arm tutorials vc98 vc17 vc22 mingw mingw++ fuzz
tall: mg_prefix unamalgamated test valgrind fuzz fuzz_tls vc98 vc17 vc22 mingw mingw++ arm armhf riscv s390 tutorials tutorials_win tutorials_embedded mip_test mip_vc98
mip_test: mip_test.c mongoose.c mongoose.h packed_fs.c Makefile
$(CC) mip_test.c packed_fs.c $(CFLAGS) $(LDFLAGS) -o $@
@@ -91,6 +91,10 @@ mip_tap_test: mip_tap_test.c mongoose.c mongoose.h packed_fs.c Makefile tls_mult
$(CC) mip_tap_test.c packed_fs.c $(CFLAGS) $(LDFLAGS) -o $@
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
mip_vc98: mip_test.c mongoose.c mongoose.h packed_fs.c Makefile
$(DOCKER) mdashnet/vc98 wine cl mip_test.c packed_fs.c $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc98 wine $@.exe
packed_fs.c: Makefile data/ssi.h fuzz.c data/a.txt data/ca.pem certs/ca.crt certs/server.crt certs/server.key
$(CC) $(CFLAGS) pack.c -o pack
$(RUN) ./pack Makefile data/ssi.h fuzz.c data/a.txt data/range.txt data/ca.pem certs/ca.crt certs/server.crt certs/server.key certs/client.key certs/client.crt > $@
@@ -113,7 +117,7 @@ unamalgamated: $(HDRS) Makefile packed_fs.c
fuzz: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined
fuzz: mongoose.c mongoose.h Makefile fuzz.c
$(CC) fuzz.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer
$(RUN) ./fuzzer
$(RUN) ./fuzzer $(ARGS)
FUZZDATA ?= /tmp/fuzzdata
fuzz2: mongoose.c mongoose.h Makefile fuzz.c
@@ -123,7 +127,11 @@ fuzz2: mongoose.c mongoose.h Makefile fuzz.c
fuzz_tls: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined
fuzz_tls: mongoose.c mongoose.h Makefile fuzz_tls.c
$(CC) fuzz_tls.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer_tls
$(RUN) ./fuzzer_tls -max_len=17000
$(RUN) ./fuzzer_tls -max_len=17000 $(ARGS)
fuzz_tls2: mongoose.c mongoose.h Makefile fuzz_tls.c
$(CC) fuzz_tls.c -DMAIN $(OPTS) $(WARN) $(ASAN) $(INCS) -o fuzzer_tls
$(RUN) ./fuzzer_tls $(FUZZDATA)
@@ -132,7 +140,12 @@ test: Makefile mongoose.h $(SRCS) tls_multirec/server
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./unit_test
tls_multirec/server: FORCE
ifneq "$(SSL)" ""
ifeq "$(MULTIREC)" ""
$(MAKE) -C tls_multirec CC=gcc
endif
endif
true
FORCE:
true
@@ -156,44 +169,48 @@ misra:
cppcheck --addon=misra --clang -DMG_ENABLE_LINES=1 -DMG_ENABLE_SSI=1 mongoose.c >>/tmp/x 2>&1
less /tmp/x
# https://ddanilov.me/how-signals-are-handled-in-a-docker-container
armhf: ASAN=
armhf: IPV6=0
armhf: CC = $(DOCKER) mdashnet/armhf cc
armhf: RUN = $(DOCKER) mdashnet/armhf
armhf: RUN = $(DOCKER) --init mdashnet/armhf
armhf: test
s390: ASAN=
s390: IPV6=0
s390: CFLAGS += -Wno-stringop-overflow
s390: DEFS += -DMG_ENABLE_CHACHA20=0
s390: CC = $(DOCKER) mdashnet/s390 cc
s390: RUN = $(DOCKER) mdashnet/s390
s390: RUN = $(DOCKER) --init mdashnet/s390
s390: test
arm: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_NEWLIB -DNO_SLEEP_ABORT
arm: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_ARMGCC -DNO_SLEEP_ABORT
arm: mongoose.h $(SRCS)
$(DOCKER) mdashnet/armgcc arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test -nostartfiles --specs nosys.specs -e 0
riscv: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_NEWLIB -DNO_SLEEP_ABORT
riscv: DEFS += -DMG_ENABLE_POSIX_FS=0 -DMG_ENABLE_TCPIP=1 -DMG_ENABLE_TCPIP_DRIVER_INIT=0 -DMG_ARCH=MG_ARCH_ARMGCC -DNO_SLEEP_ABORT
riscv: mongoose.h $(SRCS)
$(DOCKER) mdashnet/riscv riscv-none-elf-gcc -march=rv32imc -mabi=ilp32 $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test
vc98: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc98 wine $@.exe
vc17: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc17 wine64 $@.exe
vc22: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) $(DEFS) $(TFLAGS) /Fe$@.exe
$(DOCKER) mdashnet/vc22 wine64 $@.exe
mingw: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -lbcrypt -o $@.exe
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) $(TFLAGS) -lws2_32 -lbcrypt -o $@.exe
$(DOCKER) mdashnet/mingw wine64 $@.exe
mingw++: Makefile mongoose.h $(SRCS)
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -lbcrypt -o $@.exe
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) $(TFLAGS) -lws2_32 -lbcrypt -o $@.exe
@echo "NOT RUNNING"
linux-libs: CFLAGS += -fPIC
linux-libs: LDFLAGS += -Wl,-soname,libmongoose.so.$(VERSION)
@@ -213,7 +230,7 @@ mongoose.c: Makefile $(wildcard ../src/*.c) $(wildcard ../src/drivers/*.c)
cd .. && (export LC_ALL=C ; cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/drivers/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
mongoose.h: $(HDRS) Makefile
cd .. && (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/tls_chacha20.h src/tls_rsa.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/flash.h src/wifi.h src/net_builtin.h src/profile.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
cd .. && (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/profile.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/tls_chacha20.h src/tls_rsa.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/flash.h src/wifi.h src/net_builtin.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
clean: clean_tutorials clean_tutorials_embedded
+59
View File
@@ -0,0 +1,59 @@
#pragma once
// Build environment. Possible options are at https://github.com/cesanta/mongoose/blob/master/src/arch.h
// #define MG_ARCH MG_ARCH_CUSTOM
// Choice of the network stack. By default, use an external BSD-compatible stack
// #define MG_ENABLE_FREERTOS_TCP 0 // Amazon FreeRTOS-TCP
// #define MG_ENABLE_LWIP 0 // lWIP
// #define MG_ENABLE_TCPIP 0 // Mongoose built-in
// #define MG_ENABLE_RL 0 // ARM MDK
// #define MG_ENABLE_POLL 0 // Only for BSD stack. Use poll()
// #define MG_ENABLE_EPOLL 0 // Only for Linux/BSD stack. Use epoll()
// #define MG_ENABLE_WINSOCK 1 // Only for Windows stack. Use Winsock
// #define MG_ENABLE_SOCKET !MG_ENABLE_TCPIP
// #define MG_SOCK_LISTEN_BACKLOG_SIZE 3 // Only for socket-based stacks
// Only for built-in network stack, MG_ENABLE_TCPIP == 1
// #define MG_ENABLE_TCPIP_DRIVER_INIT 1 // enabled built-in driver for
// #define MG_SET_MAC_ADDRESS(mac) // set MAC address for built-in driver
// #define MG_SET_WIFI_CONFIG(data)
// #define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
// Choose a driver for built-in network stack, MG_ENABLE_TCPIP == 1
// #define MG_ENABLE_DRIVER_STM32H 0
// #define MG_ENABLE_DRIVER_STM32F 0
// #define MG_ENABLE_DRIVER_IMXRT 0
// #define MG_ENABLE_DRIVER_CMSIS 0
// #define MG_ENABLE_DRIVER_RA 0
// #define MG_ENABLE_DRIVER_RW612 0
// #define MG_ENABLE_DRIVER_SAME54 0
// #define MG_ENABLE_DRIVER_MCXN 0
// #define MG_ENABLE_DRIVER_TM4C 0
// #define MG_ENABLE_DRIVER_TMS570 0
// #define MG_ENABLE_DRIVER_XMC7 0
// #define MG_ENABLE_DRIVER_XMC 0
// Filesystem support
// #define MG_ENABLE_PACKED_FS 0 // Enable packed filesystem support
// #define MG_ENABLE_FATFS 0 // Enable FATFS support, mg_fs_packed
// #define MG_ENABLE_POSIX_FS 0 // Enable POSIX filesystem support, mg_fs_posix
// #define MG_PATH_MAX 128 // Maximum path length
// #define MG_DIRSEP '/' // Directory separator
// Misc options
// #define MG_ENABLE_LOG 1 // Enable logging
// #define MG_TLS MG_TLS_NONE // MG_TLS_NONE, MG_TLS_MBED, MG_TLS_OPENSSL, MG_TLS_CUSTOM
// #define MG_ENABLE_IPV6 0 // Enable IPv6 support
// #define MG_IPV6_V6ONLY 0 // IPv6 socket binds only to V6, not V4 address
// #define MG_ENABLE_CUSTOM_CALLOC 0 // Set to 1 to let user define mg_calloc() and mg_free()
// #define MG_ENABLE_CUSTOM_RANDOM 0 // Set to 1 to let user define mg_random()
// #define MG_ENABLE_CUSTOM_MILLIS 0 // Set to 1 to let user define mg_millis()
// #define MG_ENABLE_SSI 0 // Enable SSI support
// #define MG_ENABLE_DIRLIST 0 // Enable directory listing
// #define MG_IO_SIZE 512 // Granularity of the send/recv IO buffer growth
// #define MG_MAX_RECV_SIZE (3UL * 1024UL * 1024UL) // Maximum recv IO buffer size
// #define MG_DATA_SIZE 32 // struct mg_connection :: data size
// #define MG_MAX_HTTP_HEADERS 30 // Maximum number of HTTP headers
// #define MG_HTTP_INDEX "index.html" // Default HTTP index file
// #define MG_ENABLE_LINES 0 // Show unamalgamated line numbers
+7 -2
View File
@@ -7,18 +7,23 @@ IMAGE ?= scaprile/cubeozone
all: $(PROJECTS)
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -removeAll workspace
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf workspace/.metadata"
$(PROJECTS): FORCE
(make -C $@ && sudo make -C $@ clean) || ( \
COREDIRS=`find $@ -maxdepth 1 -name 'CM*' -print` && ( \
(test "$$COREDIRS" = "" && \
PROJNAME=`xq -r .projectDescription.name $@/.project` && \
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@ -cleanBuild $$PROJNAME/$(TARGET) ) || ( \
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@ -cleanBuild $$PROJNAME/$(TARGET) && \
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -remove $@ && \
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf $@/.settings $@/$(TARGET)") || ( \
(test "$$COREDIRS" != "" && \
for core in $$COREDIRS; do \
DIR=`basename $$core` \
PROJNAME=`xq -r .projectDescription.name $@/$$DIR/.project` && \
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@/$$DIR -cleanBuild $$PROJNAME/$(TARGET) || exit 1; \
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -import $@/$$DIR -cleanBuild $$PROJNAME/$(TARGET) && \
$(DOCKER) $(IMAGE) $(PATHTO)headless-build.sh -data workspace -remove $@/$$DIR && \
$(DOCKER) $(IMAGE) /bin/bash -c "rm -rf $@/$$DIR/.settings $@/$$DIR/Drivers $@/$$DIR/Middlewares $@/$$DIR/$(TARGET)" || exit 1; \
done ))))
FORCE:
+34
View File
@@ -0,0 +1,34 @@
- Make sure your PEM file starts with a dash -
1 s:C=US, O=Let's Encrypt, CN=E8
i:C=US, O=Internet Security Research Group, CN=ISRG Root X1
a:PKEY: id-ecPublicKey, 384 (bit); sigalg: RSA-SHA256
v:NotBefore: Mar 13 00:00:00 2024 GMT; NotAfter: Mar 12 23:59:59 2027 GMT
-----BEGIN CERTIFICATE-----
MIIEVjCCAj6gAwIBAgIQY5WTY8JOcIJxWRi/w9ftVjANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQswCQYDVQQDEwJFODB2MBAGByqGSM49AgEGBSuBBAAiA2IABNFl8l7c
S7QMApzSsvru6WyrOq44ofTUOTIzxULUzDMMNMchIJBwXOhiLxxxs0LXeb5GDcHb
R6EToMffgSZjO9SNHfY9gjMy9vQr5/WWOrQTZxh7az6NSNnq3u2ubT6HTKOB+DCB
9TAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMB
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFI8NE6L2Ln7RUGwzGDhdWY4j
cpHKMB8GA1UdIwQYMBaAFHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEB
BCYwJDAiBggrBgEFBQcwAoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzATBgNVHSAE
DDAKMAgGBmeBDAECATAnBgNVHR8EIDAeMBygGqAYhhZodHRwOi8veDEuYy5sZW5j
ci5vcmcvMA0GCSqGSIb3DQEBCwUAA4ICAQBnE0hGINKsCYWi0Xx1ygxD5qihEjZ0
RI3tTZz1wuATH3ZwYPIp97kWEayanD1j0cDhIYzy4CkDo2jB8D5t0a6zZWzlr98d
AQFNh8uKJkIHdLShy+nUyeZxc5bNeMp1Lu0gSzE4McqfmNMvIpeiwWSYO9w82Ob8
otvXcO2JUYi3svHIWRm3+707DUbL51XMcY2iZdlCq4Wa9nbuk3WTU4gr6LY8MzVA
aDQG2+4U3eJ6qUF10bBnR1uuVyDYs9RhrwucRVnfuDj29CMLTsplM5f5wSV5hUpm
Uwp/vV7M4w4aGunt74koX71n4EdagCsL/Yk5+mAQU0+tue0JOfAV/R6t1k+Xk9s2
HMQFeoxppfzAVC04FdG9M+AC2JWxmFSt6BCuh3CEey3fE52Qrj9YM75rtvIjsm/1
Hl+u//Wqxnu1ZQ4jpa+VpuZiGOlWrqSP9eogdOhCGisnyewWJwRQOqK16wiGyZeR
xs/Bekw65vwSIaVkBruPiTfMOo0Zh4gVa8/qJgMbJbyrwwG97z/PRgmLKCDl8z3d
tA0Z7qq7fta0Gl24uyuB05dqI5J1LvAzKuWdIjT1tP8qCoxSE/xpix8hX2dt3h+/
jujUgFPFZ0EVZ0xSyBNRF3MboGZnYXFUxpNjTWPKpagDHJQmqrAcDmWJnMsFY3jS
u1igv3OefnWjSQ==
-----END CERTIFICATE-----
+1 -1
View File
@@ -11,6 +11,6 @@ all: $(PROJECTS)
$(PROJECTS): FORCE
(make -C $@ build && make -C $@ clean) || ( \
$(DOCKER) $(IMAGE) /bin/bash -c 'cd $@ && idf.py build' && \
rm -rf build sdkconfig )
$(DOCKER) $(IMAGE) /bin/bash -c 'rm -rf .cache && cd $@ && rm -rf build sdkconfig')
FORCE:
+29 -14
View File
@@ -1,3 +1,5 @@
// https://llvm.org/docs/LibFuzzer.html
#define MG_ENABLE_SOCKET 0
#define MG_ENABLE_LOG 0
#define MG_ENABLE_LINES 1
@@ -109,31 +111,43 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
uint8_t ip_protos[] = {1, 6, 17}; // ICMP, TCP, UDP
struct ip *ip4 = (struct ip *) (eth + 1);
ip4->ver = (ip4->ver & ~0xf0) | (4 << 4);
// send all handled ip protos, then 2 random ones
// send all handled IP protos, then 2 random ones
if (j >= (sizeof(ip_protos) / sizeof(ip_protos[0]) + 2)) j = 0;
if (j < (sizeof(ip_protos) / sizeof(ip_protos[0]))) ip4->proto = (ip_protos[j++]);
if (ip4->proto == 1) { // ICMP
} else if (ip4->proto == 6) { // TCP
} else if (ip4->proto == 17 && size > (sizeof(*eth) + sizeof(struct ip) + sizeof(struct udp))) { // UDP
static size_t k;
uint16_t udp_ports[] = {67, 68}; // DHCP server and client
struct udp *udp = (struct udp *) (ip4 + 1);
// send all handled udp ports, then 2 random ones
if (k >= (sizeof(udp_ports) / sizeof(udp_ports[0]) + 2)) k = 0;
if (k < (sizeof(udp_ports) / sizeof(udp_ports[0]))) udp->dport = mg_htons(udp_ports[k++]);
} else if (ip4->proto == 17) { // UDP
if (size > (sizeof(*eth) + sizeof(struct ip) + sizeof(struct udp))) {
static size_t k;
uint16_t udp_ports[] = {67, 68}; // DHCP server and client
struct udp *udp = (struct udp *) (ip4 + 1);
// send all handled UDP ports, then 2 random ones
if (k >= (sizeof(udp_ports) / sizeof(udp_ports[0]) + 2)) k = 0;
if (k < (sizeof(udp_ports) / sizeof(udp_ports[0]))) udp->dport = mg_htons(udp_ports[k++]);
}
}
} else if (eth->type == mg_htons(0x806)) { // ARP
} else if (eth->type == mg_htons(0x86dd) && size > (sizeof(*eth) + sizeof(struct ip6))) { // IPv6
static size_t j;
uint8_t ip6_protos[] = {6, 17}; // TCP, UDP
uint8_t ip6_protos[] = {6, 17, 58}; // TCP, UDP, ICMPv6
struct ip6 *ip6 = (struct ip6 *) (eth + 1);
ip6->ver = (ip6->ver & ~0xf0) | (6 << 4);
// send all handled ip6 "next headers", then 2 random ones
// send all handled IPv6 "next headers", then 2 random ones
if (j >= (sizeof(ip6_protos) / sizeof(ip6_protos[0]) + 2)) j = 0;
if (j < (sizeof(ip6_protos) / sizeof(ip6_protos[0]))) ip6->proto = (ip6_protos[j++]);
if (ip6->proto == 6) { // TCP
} else if (ip6->proto == 17) { // UDP
}
if (j < (sizeof(ip6_protos) / sizeof(ip6_protos[0]))) ip6->next = (ip6_protos[j++]);
if (ip6->next == 6) { // TCP
} else if (ip6->next == 17) { // UDP
} else if (ip6->next == 58) { // ICMPv6
if (size >= (sizeof(*eth) + sizeof(struct ip6) + sizeof(struct icmp6))) {
static size_t k;
uint8_t icmp6_types[] = {128, 134, 135, 136}; // Echo Request, RA, NS, NA
struct icmp6 *icmp6 = (struct icmp6 *) (ip6 + 1);
// send all handled ICMPv6 types, then 2 random ones
if (k >= (sizeof(icmp6_types) / sizeof(icmp6_types[0]) + 2)) k = 0;
if (k < (sizeof(icmp6_types) / sizeof(icmp6_types[0]))) icmp6->type = icmp6_types[k++];
}
}
}
}
@@ -146,6 +160,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
c->pfn(c, MG_EV_READ, NULL); // manually invoke protocol event handler
free(pkt);
mg_mgr_free(&mgr);
}
return 0;
+54 -15
View File
@@ -1,3 +1,5 @@
// https://llvm.org/docs/LibFuzzer.html
#define MG_ENABLE_SOCKET 1
#define MG_ENABLE_LOG 0
#define MG_ENABLE_LINES 1
@@ -12,33 +14,46 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
#else
int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
#endif
typedef int (*f)(struct mg_connection *);
f f_[] = {
mg_tls_server_recv_hello,
#if 0
mg_tls_client_recv_hello,
mg_tls_client_recv_ext,
mg_tls_client_recv_cert,
mg_tls_client_recv_cert_verify
#endif
// Preprocessor magic, just add/remove functions here and leave the rest alone
#define TABLE(_) \
_(mg_tls_server_recv_hello) \
_(mg_tls_server_recv_finish) \
_(mg_tls_client_recv_hello) \
_(mg_tls_client_recv_finish) \
_(mg_tls_client_recv_ext) \
_(mg_tls_recv_cert_verify) \
// ...
struct f {
int (*f)(struct mg_connection *);
const char *name;
};
struct f f_[] = {
#define ENTRY(func) { func, #func },
TABLE(ENTRY)
#undef ENTRY
};
// end of preprocessor magic
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
struct mg_connection c_[sizeof(f_)/sizeof(f)], *c = &c_[0];
struct tls_data tls_[sizeof(f_)/sizeof(f)];
struct mg_connection c_[sizeof(f_)/sizeof(struct f)], *c = &c_[0];
struct tls_data tls_[sizeof(f_)/sizeof(struct f)];
int i;
if (size == 0) return 0;
mg_log_set(MG_LL_INFO);
memset(c, 0, sizeof(*c));
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
c->is_tls = c->is_tls_hs = 1;
for (i = 0; i < (int)(sizeof(f_)/sizeof(f)); i++) {
for (i = 0; i < (int)(sizeof(f_)/sizeof(struct f)); i++) {
struct mg_iobuf *io;
c = &c_[i];
io = &c->rtls;
if (i > 0) memcpy(c, &c_[0], sizeof(*c)); // copy from 1st one
if (i > 0) c->is_client = 1; // from 1 on, client functions
if (i > 1) c->is_client = 1; // from 2 on, client functions
memset(&tls_[i], 0, sizeof(struct tls_data));
if (io->size - io->len < size && !mg_iobuf_resize(io, io->len + size)) {
mg_error(c, "oom");
@@ -47,10 +62,34 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
memcpy(&io->buf[io->len], data, size);
io->len += size;
c->tls = &tls_[i];
f_[i](&c[i]);
#ifdef PRINT_FUNCNAME
printf("CALLING %s\n", f_[i].name);
#endif
f_[i].f(c);
mg_iobuf_free(io);
}
// mg_tls_recv_cert() has an extra bool parameter
c = &c_[0]; // reuse first one
c->tls = &tls_[0];
for (i = 0; i < 2; i++) {
struct mg_iobuf *io;
io = &c->rtls;
c->is_client = (i > 0);
memset(c->tls, 0, sizeof(struct tls_data));
if (io->size - io->len < size && !mg_iobuf_resize(io, io->len + size)) {
mg_error(c, "oom");
return 0; // drop it
}
memcpy(&io->buf[io->len], data, size);
io->len += size;
#ifdef PRINT_FUNCNAME
printf("CALLING mg_tls_recv_cert\n");
#endif
mg_tls_recv_cert(c, !c->is_client); // call server for client and client for server
mg_iobuf_free(io);
}
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
{
"data-root": "/mnt/docker"
}
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env -S gawk -f
# gawk used to avoid "towc" errors seen on MacOS. env used to circumvent brew installing it wherever they like
BEGIN {
FS="\t"
print "{"
}
/HEALTH_DASHBOARD/ { print $2 }
END {
print "}"
}
Executable
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
cd /data/downloads/health
find . -mtime +28 -not -name 'index*.json' -delete
find . -name "*.json" -not -name 'index*.json' | jq -R . | jq -s . > index.json
+134 -31
View File
@@ -20,9 +20,13 @@
#include "driver_mock.c"
#define MQTT_URL "mqtt://broker.hivemq.com:1883" // MQTT broker URL
#ifdef MQTT_LOCALHOST
#define MQTT_URL "mqtt://127.0.0.1:1883"
#else
#define MQTT_URL "mqtt://broker.hivemq.com:1883"
#endif
#if MG_TLS == MG_TLS_BUILTIN
#define MQTTS_URL "mqtts://mongoose.ws:8883" // HiveMQ does not do TLS1.3
#define MQTTS_URL "mqtts://mongoose.ws:8883" // test requires TLS 1.3
#define MQTTS_CA mg_str(s_ca_cert)
static const char *s_ca_cert =
"-----BEGIN CERTIFICATE-----\n"
@@ -57,27 +61,53 @@ static const char *s_ca_cert =
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
"-----END CERTIFICATE-----\n";
#elif MG_TLS
#define MQTTS_URL "mqtts://broker.hivemq.com:8883" // MQTT broker URL
#ifdef MQTT_LOCALHOST
// we'll generate MQTTS_URL
#define MQTTS_CA mg_str(s_ca_cert)
static const char *s_ca_cert =
"-----BEGIN CERTIFICATE-----\n"
"MIIBFTCBvAIJAMNTFtpfcq8NMAoGCCqGSM49BAMCMBMxETAPBgNVBAMMCE1vbmdv\n"
"b3NlMB4XDTI0MDUwNzE0MzczNloXDTM0MDUwNTE0MzczNlowEzERMA8GA1UEAwwI\n"
"TW9uZ29vc2UwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASuP+86T/rOWnGpEVhl\n"
"fxYZ+pjMbCmDZ+vdnP0rjoxudwRMRQCv5slRlDK7Lxue761sdvqxWr0Ma6TFGTNg\n"
"epsRMAoGCCqGSM49BAMCA0gAMEUCIQCwb2CxuAKm51s81S6BIoy1IcandXSohnqs\n"
"us64BAA7QgIgGGtUrpkgFSS0oPBlCUG6YPHFVw42vTfpTC0ySwAS0M4=\n"
"-----END CERTIFICATE-----\n";
#else
#define MQTTS_URL "mqtts://broker.hivemq.com:8883"
#define MQTTS_CA mg_unpacked("/data/ca.pem")
#endif // MQTT_LOCALHOST
#endif
static char *host_ip;
static int s_num_tests = 0;
static bool s_error = false;
#define ABORT() \
usleep(500000); /* 500 ms, GH print reason */ \
#ifdef NO_ABORT
static int s_abort = 0;
#define ABORT() ++s_abort, s_error = true
#else
#ifdef NO_SLEEP_ABORT
#define ABORT() abort()
#else
#define ABORT() \
sleep(2); /* 2s, GH print reason */ \
abort();
#endif
#endif
#define ASSERT(expr) \
do { \
s_num_tests++; \
if (!(expr)) { \
printf("FAILURE %s:%d: %s\n", __FILE__, __LINE__, #expr); \
fflush(stdout); \
ABORT(); \
} \
} while (0)
static struct mg_http_message gethm(const char *buf) {
struct mg_http_message hm;
memset(&hm, 0, sizeof(hm));
@@ -156,14 +186,22 @@ static void fcb(struct mg_connection *c, int ev, void *ev_data) {
if (mg_url_is_ssl(fd->url)) {
struct mg_tls_opts opts;
memset(&opts, 0, sizeof(opts)); // read CA from packed_fs
opts.name = mg_url_host(fd->url);
opts.ca = mg_unpacked("/data/ca.pem");
if (host_ip != NULL && strstr(fd->url, host_ip) != NULL) {
MG_DEBUG(("Local connection, using self-signed certificates"));
opts.name = mg_str_s("localhost");
opts.ca = mg_unpacked("/certs/ca.crt");
} else {
opts.name = mg_url_host(fd->url);
opts.ca = mg_unpacked("/data/ca.pem");
#if MG_TLS == MG_TLS_BUILTIN
// our TLS does not search for the proper CA in a bundle
opts.ca = mg_file_read(&mg_fs_posix, "data/e5.crt");
#endif
}
mg_tls_init(c, &opts);
#if MG_TLS == MG_TLS_BUILTIN
mg_free((void *) opts.ca.buf);
#endif
}
} else if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
@@ -215,7 +253,7 @@ static int fetch(struct mg_mgr *mgr, char *buf, const char *url,
static void test_http_client(struct mg_mgr *mgr) {
char buf[FETCH_BUF_SIZE];
int rc = 0;
const bool ipv6 = 0;
const bool ipv6 = MG_ENABLE_IPV6;
#if MG_TLS
if (ipv6) {
rc = fetch(mgr, buf, "https://ipv6.google.com",
@@ -229,11 +267,12 @@ static void test_http_client(struct mg_mgr *mgr) {
if (ipv6) {
rc = fetch(mgr, buf, "http://ipv6.google.com",
"GET / HTTP/1.0\r\nHost: ipv6.google.com\r\n\r\n");
ASSERT(rc == 200); // OK
} else {
rc = fetch(mgr, buf, "http://cesanta.com",
"GET /robots.txt HTTP/1.0\r\nHost: cesanta.com\r\n\r\n");
ASSERT(rc == 301); // OK: Permanently moved (HTTP->HTTPS redirect)
}
ASSERT(rc == 301); // OK: Permanently moved (HTTP->HTTPS redirect)
#endif
}
@@ -241,14 +280,20 @@ static void test_http_client(struct mg_mgr *mgr) {
static struct mg_connection *s_conn;
static char s_topic[16];
struct mqtt_data {
char *url;
bool passed;
};
static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data) {
struct mqtt_data *data = (struct mqtt_data *) c->fn_data;
if (ev == MG_EV_CONNECT) {
MG_DEBUG(("CONNECT"));
#if MG_TLS
struct mg_tls_opts opts;
memset(&opts, 0, sizeof(opts));
opts.ca = MQTTS_CA;
opts.name = mg_url_host(MQTTS_URL);
opts.name = mg_url_host(data->url);
mg_tls_init(c, &opts);
#endif
} else if (ev == MG_EV_MQTT_OPEN) {
@@ -267,12 +312,32 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data) {
} else if (ev == MG_EV_MQTT_MSG) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
MG_DEBUG(("TOPIC: %.*s, MSG: %.*s", (int) mm->topic.len, mm->topic.buf,
(int) mm->data.len, mm->data.buf));
mm->data.len > 10 ? 10 : (int) mm->data.len, mm->data.buf));
ASSERT(mm->topic.len == strlen(s_topic) &&
strcmp(mm->topic.buf, s_topic) == 0);
ASSERT(mm->data.len == 2 && strcmp(mm->data.buf, "hi") == 0);
mg_mqtt_disconnect(c, NULL);
*(bool *) c->fn_data = true;
strncmp(mm->topic.buf, s_topic, mm->topic.len) == 0);
if (mm->data.len == 2 && strncmp(mm->data.buf, "hi", 2) == 0) {
struct mg_mqtt_opts pub_opts;
memset(&pub_opts, 0, sizeof(pub_opts));
pub_opts.topic = mm->topic;
// send more than 1 record, content is not relevant
pub_opts.message = mg_str_n((char *)(size_t) mqtt_fn, 21098);
pub_opts.qos = 1, pub_opts.retain = false;
mg_mqtt_pub(c, &pub_opts);
} else if (mm->data.len == 8 && strncmp(mm->data.buf, "farewell", 8) == 0) {
// close on farewell
MG_INFO(("%lu CLOSING", c->id));
mg_mqtt_disconnect(c, NULL);
data->passed = true;
} else if (mm->data.len == 21098) {
struct mg_mqtt_opts pub_opts;
ASSERT(memcmp((const char *) (size_t) mqtt_fn, mm->data.buf, 21098) == 0);
// send farewell after receiving big data
memset(&pub_opts, 0, sizeof(pub_opts));
pub_opts.topic = mm->topic;
pub_opts.message = mg_str("farewell");
pub_opts.qos = 1, pub_opts.retain = false;
mg_mqtt_pub(c, &pub_opts);
}
} else if (ev == MG_EV_CLOSE) {
MG_DEBUG(("CLOSE"));
s_conn = NULL;
@@ -282,22 +347,40 @@ static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data) {
}
static void test_mqtt_connsubpub(struct mg_mgr *mgr) {
bool passed = false;
struct mqtt_data data;
struct mg_mqtt_opts opts;
memset(&opts, 0, sizeof(opts));
opts.clean = true, opts.version = 4;
#if MG_TLS
s_conn = mg_mqtt_connect(mgr, MQTTS_URL, &opts, mqtt_fn, &passed);
#else
s_conn = mg_mqtt_connect(mgr, MQTT_URL, &opts, mqtt_fn, &passed);
data.passed = false;
#if defined(MQTT_LOCALHOST) && MG_TLS != MG_TLS_BUILTIN
if (host_ip == NULL) {
printf("\nMQTT_LOCALHOST defined but no HOST_IP provided, skipping MQTTS tests\n");
return;
}
printf("HOST_IP: %s\n", host_ip);
#endif
#if MG_TLS
#if defined(MQTT_LOCALHOST) && MG_TLS != MG_TLS_BUILTIN
data.url = mg_mprintf("mqtts://%s:8883", host_ip);
#else
data.url = strdup(MQTTS_URL);
#endif
#else
#ifdef MQTT_LOCALHOST
data.url = mg_mprintf("mqtt://%s:1883", host_ip);
#else
data.url = strdup(MQTT_URL);
#endif
#endif
s_conn = mg_mqtt_connect(mgr, data.url, &opts, mqtt_fn, &data);
ASSERT(s_conn != NULL);
for (int i = 0; i < 500 && s_conn != NULL && !s_conn->is_closing; i++) {
for (int i = 0; i < 1000 && s_conn != NULL && !s_conn->is_closing; i++) {
mg_mgr_poll(mgr, 0);
usleep(10000); // 10 ms. Slow down poll loop to ensure packets transit
}
ASSERT(passed);
ASSERT(data.passed);
mg_mgr_poll(mgr, 0);
free(data.url);
}
#include <pthread.h>
@@ -330,6 +413,7 @@ static void test_http_server(struct mg_mgr *mgr) {
mg_mprintf("./mip_curl.sh http://%M:12347", mg_print_ip4, &mgr->ifp->ip);
#endif
ASSERT(c != NULL);
ASSERT (mg_send(c, "NADA", 0)); // check mg_send allows len=0
pthread_create(&thread_id, NULL, poll_thread,
mgr); // simpler this way, no concurrency anyway
MG_DEBUG(("CURL"));
@@ -456,22 +540,41 @@ int main(void) {
usleep(10000); // 10 ms
}
#define DASHBOARD(x) printf("HEALTH_DASHBOARD\t\"%s\": %s,\n", x, s_error ? "false":"true");
// RUN TESTS
usleep(500000); // 500 ms
s_error = false;
test_http_client(&mgr);
usleep(500000); // 500 ms
test_http_server(&mgr);
usleep(500000); // 500 ms
test_tls(&mgr);
usleep(500000); // 500 ms
test_mqtt_connsubpub(&mgr);
usleep(500000); // 500 ms
DASHBOARD("http_client");
printf("SUCCESS. Total tests: %d\n", s_num_tests);
usleep(500000); // 500 ms
s_error = false;
test_http_server(&mgr);
DASHBOARD("http_server");
usleep(500000); // 500 ms
s_error = false;
test_tls(&mgr);
DASHBOARD("tls");
usleep(500000); // 500 ms
s_error = false;
test_mqtt_connsubpub(&mgr);
DASHBOARD("mqtt");
// Clear
s_error = false;
mg_mgr_free(&mgr);
ASSERT(mgr.conns == NULL); // Deconstruction OK
close(fd);
return 0;
printf("HEALTH_DASHBOARD\t\"cleanup\": %s\n", s_error ? "false":"true");
// last entry with no comma
#ifdef NO_ABORT
if (s_abort != 0) return EXIT_FAILURE;
#endif
printf("SUCCESS. Total tests: %d\n", s_num_tests);
return EXIT_SUCCESS;
}
Loaded 100 of 1390 files, more files were not shown because too many files have changed in this diff. Show more